aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/Loads.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Analysis/Loads.cpp')
-rw-r--r--llvm/lib/Analysis/Loads.cpp45
1 files changed, 45 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/Loads.cpp b/llvm/lib/Analysis/Loads.cpp
index 42fe548..d82ed02 100644
--- a/llvm/lib/Analysis/Loads.cpp
+++ b/llvm/lib/Analysis/Loads.cpp
@@ -593,6 +593,51 @@ Value *llvm::FindAvailablePtrLoadStore(Value *Ptr, Type *AccessTy,
return nullptr;
}
+Value *llvm::FindAvailableLoadedValue(LoadInst *Load, AAResults &AA,
+ bool *IsLoadCSE,
+ unsigned MaxInstsToScan) {
+ const DataLayout &DL = Load->getModule()->getDataLayout();
+ Value *StrippedPtr = Load->getPointerOperand()->stripPointerCasts();
+ BasicBlock *ScanBB = Load->getParent();
+ Type *AccessTy = Load->getType();
+ bool AtLeastAtomic = Load->isAtomic();
+
+ if (!Load->isUnordered())
+ return nullptr;
+
+ // Try to find an available value first, and delay expensive alias analysis
+ // queries until later.
+ Value *Available = nullptr;;
+ SmallVector<Instruction *> MustNotAliasInsts;
+ for (Instruction &Inst : make_range(++Load->getReverseIterator(),
+ ScanBB->rend())) {
+ if (isa<DbgInfoIntrinsic>(&Inst))
+ continue;
+
+ if (MaxInstsToScan-- == 0)
+ return nullptr;
+
+ Available = getAvailableLoadStore(&Inst, StrippedPtr, AccessTy,
+ AtLeastAtomic, DL, IsLoadCSE);
+ if (Available)
+ break;
+
+ if (Inst.mayWriteToMemory())
+ MustNotAliasInsts.push_back(&Inst);
+ }
+
+ // If we found an available value, ensure that the instructions in between
+ // did not modify the memory location.
+ if (Available) {
+ auto AccessSize = LocationSize::precise(DL.getTypeStoreSize(AccessTy));
+ for (Instruction *Inst : MustNotAliasInsts)
+ if (isModSet(AA.getModRefInfo(Inst, StrippedPtr, AccessSize)))
+ return nullptr;
+ }
+
+ return Available;
+}
+
bool llvm::canReplacePointersIfEqual(Value *A, Value *B, const DataLayout &DL,
Instruction *CtxI) {
Type *Ty = A->getType();