summaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/MemoryLocation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Analysis/MemoryLocation.cpp')
-rw-r--r--llvm/lib/Analysis/MemoryLocation.cpp54
1 files changed, 44 insertions, 10 deletions
diff --git a/llvm/lib/Analysis/MemoryLocation.cpp b/llvm/lib/Analysis/MemoryLocation.cpp
index 72b643c56a99..dcc51178b975 100644
--- a/llvm/lib/Analysis/MemoryLocation.cpp
+++ b/llvm/lib/Analysis/MemoryLocation.cpp
@@ -12,6 +12,7 @@
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/IntrinsicsARM.h"
+#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/Type.h"
#include <optional>
using namespace llvm;
@@ -150,6 +151,33 @@ MemoryLocation::getForDest(const CallBase *CB, const TargetLibraryInfo &TLI) {
return MemoryLocation::getBeforeOrAfter(UsedV, CB->getAAMetadata());
}
+// If the mask for a memory op is a get active lane mask intrinsic
+// we can possibly infer the size of memory written or read
+static std::optional<FixedVectorType *>
+getKnownTypeFromMaskedOp(Value *Mask, VectorType *Ty) {
+ using namespace llvm::PatternMatch;
+ ConstantInt *Op0, *Op1;
+ if (!match(Mask, m_Intrinsic<Intrinsic::get_active_lane_mask>(
+ m_ConstantInt(Op0), m_ConstantInt(Op1))))
+ return std::nullopt;
+
+ APInt LaneMaskLo = Op0->getValue();
+ APInt LaneMaskHi = Op1->getValue();
+ if (LaneMaskHi.ule(LaneMaskLo))
+ return std::nullopt;
+
+ APInt NumElts = LaneMaskHi - LaneMaskLo;
+ if (NumElts.ugt(Ty->getElementCount().getKnownMinValue())) {
+ if (isa<ScalableVectorType>(Ty))
+ return std::nullopt;
+ // Unlike scalable vectors, fixed vector types are guaranteed to handle the
+ // KnownMinValue and can be clamped
+ NumElts = Ty->getElementCount().getKnownMinValue();
+ }
+
+ return FixedVectorType::get(Ty->getElementType(), NumElts.getZExtValue());
+}
+
MemoryLocation MemoryLocation::getForArgument(const CallBase *Call,
unsigned ArgIdx,
const TargetLibraryInfo *TLI) {
@@ -213,20 +241,26 @@ MemoryLocation MemoryLocation::getForArgument(const CallBase *Call,
cast<ConstantInt>(II->getArgOperand(0))->getZExtValue()),
AATags);
- case Intrinsic::masked_load:
+ case Intrinsic::masked_load: {
assert(ArgIdx == 0 && "Invalid argument index");
- return MemoryLocation(
- Arg,
- LocationSize::upperBound(DL.getTypeStoreSize(II->getType())),
- AATags);
- case Intrinsic::masked_store:
+ auto *Ty = cast<VectorType>(II->getType());
+ if (auto KnownType = getKnownTypeFromMaskedOp(II->getOperand(2), Ty))
+ return MemoryLocation(Arg, DL.getTypeStoreSize(*KnownType), AATags);
+
+ return MemoryLocation(
+ Arg, LocationSize::upperBound(DL.getTypeStoreSize(Ty)), AATags);
+ }
+ case Intrinsic::masked_store: {
assert(ArgIdx == 1 && "Invalid argument index");
+
+ auto *Ty = cast<VectorType>(II->getArgOperand(0)->getType());
+ if (auto KnownType = getKnownTypeFromMaskedOp(II->getOperand(3), Ty))
+ return MemoryLocation(Arg, DL.getTypeStoreSize(*KnownType), AATags);
+
return MemoryLocation(
- Arg,
- LocationSize::upperBound(
- DL.getTypeStoreSize(II->getArgOperand(0)->getType())),
- AATags);
+ Arg, LocationSize::upperBound(DL.getTypeStoreSize(Ty)), AATags);
+ }
case Intrinsic::invariant_end:
// The first argument to an invariant.end is a "descriptor" type (e.g. a