bool *IsLoadCSE = nullptr,
unsigned *NumScanedInst = nullptr);
+/// This overload provides a more efficient implementation of
+/// FindAvailableLoadedValue() for the case where we are not interested in
+/// finding the closest clobbering instruction if no available load is found.
+/// This overload cannot be used to scan across multiple blocks.
+Value *FindAvailableLoadedValue(LoadInst *Load, AAResults &AA, bool *IsLoadCSE,
+ unsigned MaxInstsToScan = DefMaxInstsToScan);
+
/// Scan backwards to see if we have the value of the given pointer available
/// locally within a small number of instructions.
///
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();
// Do really simple store-to-load forwarding and load CSE, to catch cases
// where there are several consecutive memory accesses to the same location,
// separated by a few arithmetic operations.
- BasicBlock::iterator BBI(LI);
bool IsLoadCSE = false;
- if (Value *AvailableVal = FindAvailableLoadedValue(
- &LI, LI.getParent(), BBI, DefMaxInstsToScan, AA, &IsLoadCSE)) {
+ if (Value *AvailableVal = FindAvailableLoadedValue(&LI, *AA, &IsLoadCSE)) {
if (IsLoadCSE)
combineMetadataForCSE(cast<LoadInst>(AvailableVal), &LI, false);