aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Scalar/LICM.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Scalar/LICM.cpp')
-rw-r--r--llvm/lib/Transforms/Scalar/LICM.cpp319
1 files changed, 224 insertions, 95 deletions
diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp
index d2b4ba296f41..30058df3ded5 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -162,6 +162,7 @@ static bool sink(Instruction &I, LoopInfo *LI, DominatorTree *DT,
OptimizationRemarkEmitter *ORE);
static bool isSafeToExecuteUnconditionally(Instruction &Inst,
const DominatorTree *DT,
+ const TargetLibraryInfo *TLI,
const Loop *CurLoop,
const LoopSafetyInfo *SafetyInfo,
OptimizationRemarkEmitter *ORE,
@@ -185,12 +186,17 @@ static void moveInstructionBefore(Instruction &I, Instruction &Dest,
ICFLoopSafetyInfo &SafetyInfo,
MemorySSAUpdater *MSSAU, ScalarEvolution *SE);
+static void foreachMemoryAccess(MemorySSA *MSSA, Loop *L,
+ function_ref<void(Instruction *)> Fn);
+static SmallVector<SmallSetVector<Value *, 8>, 0>
+collectPromotionCandidates(MemorySSA *MSSA, AliasAnalysis *AA, Loop *L);
+
namespace {
struct LoopInvariantCodeMotion {
bool runOnLoop(Loop *L, AAResults *AA, LoopInfo *LI, DominatorTree *DT,
BlockFrequencyInfo *BFI, TargetLibraryInfo *TLI,
TargetTransformInfo *TTI, ScalarEvolution *SE, MemorySSA *MSSA,
- OptimizationRemarkEmitter *ORE);
+ OptimizationRemarkEmitter *ORE, bool LoopNestMode = false);
LoopInvariantCodeMotion(unsigned LicmMssaOptCap,
unsigned LicmMssaNoAccForPromotionCap)
@@ -203,9 +209,6 @@ private:
std::unique_ptr<AliasSetTracker>
collectAliasInfoForLoop(Loop *L, LoopInfo *LI, AAResults *AA);
- std::unique_ptr<AliasSetTracker>
- collectAliasInfoForLoopWithMSSA(Loop *L, AAResults *AA,
- MemorySSAUpdater *MSSAU);
};
struct LegacyLICMPass : public LoopPass {
@@ -292,6 +295,33 @@ PreservedAnalyses LICMPass::run(Loop &L, LoopAnalysisManager &AM,
return PA;
}
+PreservedAnalyses LNICMPass::run(LoopNest &LN, LoopAnalysisManager &AM,
+ LoopStandardAnalysisResults &AR,
+ LPMUpdater &) {
+ // For the new PM, we also can't use OptimizationRemarkEmitter as an analysis
+ // pass. Function analyses need to be preserved across loop transformations
+ // but ORE cannot be preserved (see comment before the pass definition).
+ OptimizationRemarkEmitter ORE(LN.getParent());
+
+ LoopInvariantCodeMotion LICM(LicmMssaOptCap, LicmMssaNoAccForPromotionCap);
+
+ Loop &OutermostLoop = LN.getOutermostLoop();
+ bool Changed = LICM.runOnLoop(&OutermostLoop, &AR.AA, &AR.LI, &AR.DT, AR.BFI,
+ &AR.TLI, &AR.TTI, &AR.SE, AR.MSSA, &ORE, true);
+
+ if (!Changed)
+ return PreservedAnalyses::all();
+
+ auto PA = getLoopPassPreservedAnalyses();
+
+ PA.preserve<DominatorTreeAnalysis>();
+ PA.preserve<LoopAnalysis>();
+ if (AR.MSSA)
+ PA.preserve<MemorySSAAnalysis>();
+
+ return PA;
+}
+
char LegacyLICMPass::ID = 0;
INITIALIZE_PASS_BEGIN(LegacyLICMPass, "licm", "Loop Invariant Code Motion",
false, false)
@@ -344,7 +374,8 @@ llvm::SinkAndHoistLICMFlags::SinkAndHoistLICMFlags(
bool LoopInvariantCodeMotion::runOnLoop(
Loop *L, AAResults *AA, LoopInfo *LI, DominatorTree *DT,
BlockFrequencyInfo *BFI, TargetLibraryInfo *TLI, TargetTransformInfo *TTI,
- ScalarEvolution *SE, MemorySSA *MSSA, OptimizationRemarkEmitter *ORE) {
+ ScalarEvolution *SE, MemorySSA *MSSA, OptimizationRemarkEmitter *ORE,
+ bool LoopNestMode) {
bool Changed = false;
assert(L->isLCSSAForm(*DT) && "Loop is not in LCSSA form.");
@@ -359,6 +390,22 @@ bool LoopInvariantCodeMotion::runOnLoop(
std::unique_ptr<MemorySSAUpdater> MSSAU;
std::unique_ptr<SinkAndHoistLICMFlags> Flags;
+ // Don't sink stores from loops with coroutine suspend instructions.
+ // LICM would sink instructions into the default destination of
+ // the coroutine switch. The default destination of the switch is to
+ // handle the case where the coroutine is suspended, by which point the
+ // coroutine frame may have been destroyed. No instruction can be sunk there.
+ // FIXME: This would unfortunately hurt the performance of coroutines, however
+ // there is currently no general solution for this. Similar issues could also
+ // potentially happen in other passes where instructions are being moved
+ // across that edge.
+ bool HasCoroSuspendInst = llvm::any_of(L->getBlocks(), [](BasicBlock *BB) {
+ return llvm::any_of(*BB, [](Instruction &I) {
+ IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I);
+ return II && II->getIntrinsicID() == Intrinsic::coro_suspend;
+ });
+ });
+
if (!MSSA) {
LLVM_DEBUG(dbgs() << "LICM: Using Alias Set Tracker.\n");
CurAST = collectAliasInfoForLoop(L, LI, AA);
@@ -395,7 +442,7 @@ bool LoopInvariantCodeMotion::runOnLoop(
if (Preheader)
Changed |= hoistRegion(DT->getNode(L->getHeader()), AA, LI, DT, BFI, TLI, L,
CurAST.get(), MSSAU.get(), SE, &SafetyInfo,
- *Flags.get(), ORE);
+ *Flags.get(), ORE, LoopNestMode);
// Now that all loop invariants have been removed from the loop, promote any
// memory references to scalars that we can.
@@ -405,7 +452,7 @@ bool LoopInvariantCodeMotion::runOnLoop(
// preheader for SSA updater, so also avoid sinking when no preheader
// is available.
if (!DisablePromotion && Preheader && L->hasDedicatedExits() &&
- !Flags->tooManyMemoryAccesses()) {
+ !Flags->tooManyMemoryAccesses() && !HasCoroSuspendInst) {
// Figure out the loop exits and their insertion points
SmallVector<BasicBlock *, 8> ExitBlocks;
L->getUniqueExitBlocks(ExitBlocks);
@@ -430,31 +477,43 @@ bool LoopInvariantCodeMotion::runOnLoop(
PredIteratorCache PIC;
bool Promoted = false;
-
- // Build an AST using MSSA.
- if (!CurAST.get())
- CurAST = collectAliasInfoForLoopWithMSSA(L, AA, MSSAU.get());
-
- // Loop over all of the alias sets in the tracker object.
- for (AliasSet &AS : *CurAST) {
- // We can promote this alias set if it has a store, if it is a "Must"
- // alias set, if the pointer is loop invariant, and if we are not
- // eliminating any volatile loads or stores.
- if (AS.isForwardingAliasSet() || !AS.isMod() || !AS.isMustAlias() ||
- !L->isLoopInvariant(AS.begin()->getValue()))
- continue;
-
- assert(
- !AS.empty() &&
- "Must alias set should have at least one pointer element in it!");
-
- SmallSetVector<Value *, 8> PointerMustAliases;
- for (const auto &ASI : AS)
- PointerMustAliases.insert(ASI.getValue());
-
- Promoted |= promoteLoopAccessesToScalars(
- PointerMustAliases, ExitBlocks, InsertPts, MSSAInsertPts, PIC, LI,
- DT, TLI, L, CurAST.get(), MSSAU.get(), &SafetyInfo, ORE);
+ if (CurAST.get()) {
+ // Loop over all of the alias sets in the tracker object.
+ for (AliasSet &AS : *CurAST) {
+ // We can promote this alias set if it has a store, if it is a "Must"
+ // alias set, if the pointer is loop invariant, and if we are not
+ // eliminating any volatile loads or stores.
+ if (AS.isForwardingAliasSet() || !AS.isMod() || !AS.isMustAlias() ||
+ !L->isLoopInvariant(AS.begin()->getValue()))
+ continue;
+
+ assert(
+ !AS.empty() &&
+ "Must alias set should have at least one pointer element in it!");
+
+ SmallSetVector<Value *, 8> PointerMustAliases;
+ for (const auto &ASI : AS)
+ PointerMustAliases.insert(ASI.getValue());
+
+ Promoted |= promoteLoopAccessesToScalars(
+ PointerMustAliases, ExitBlocks, InsertPts, MSSAInsertPts, PIC, LI,
+ DT, TLI, L, CurAST.get(), MSSAU.get(), &SafetyInfo, ORE);
+ }
+ } else {
+ // Promoting one set of accesses may make the pointers for another set
+ // loop invariant, so run this in a loop (with the MaybePromotable set
+ // decreasing in size over time).
+ bool LocalPromoted;
+ do {
+ LocalPromoted = false;
+ for (const SmallSetVector<Value *, 8> &PointerMustAliases :
+ collectPromotionCandidates(MSSA, AA, L)) {
+ LocalPromoted |= promoteLoopAccessesToScalars(
+ PointerMustAliases, ExitBlocks, InsertPts, MSSAInsertPts, PIC,
+ LI, DT, TLI, L, /*AST*/nullptr, MSSAU.get(), &SafetyInfo, ORE);
+ }
+ Promoted |= LocalPromoted;
+ } while (LocalPromoted);
}
// Once we have promoted values across the loop body we have to
@@ -521,8 +580,8 @@ bool llvm::sinkRegion(DomTreeNode *N, AAResults *AA, LoopInfo *LI,
for (BasicBlock::iterator II = BB->end(); II != BB->begin();) {
Instruction &I = *--II;
- // If the instruction is dead, we would try to sink it because it isn't
- // used in the loop, instead, just delete it.
+ // The instruction is not used in the loop if it is dead. In this case,
+ // we just delete it instead of sinking it.
if (isInstructionTriviallyDead(&I, TLI)) {
LLVM_DEBUG(dbgs() << "LICM deleting dead inst: " << I << '\n');
salvageKnowledge(&I);
@@ -828,7 +887,7 @@ bool llvm::hoistRegion(DomTreeNode *N, AAResults *AA, LoopInfo *LI,
AliasSetTracker *CurAST, MemorySSAUpdater *MSSAU,
ScalarEvolution *SE, ICFLoopSafetyInfo *SafetyInfo,
SinkAndHoistLICMFlags &Flags,
- OptimizationRemarkEmitter *ORE) {
+ OptimizationRemarkEmitter *ORE, bool LoopNestMode) {
// Verify inputs.
assert(N != nullptr && AA != nullptr && LI != nullptr && DT != nullptr &&
CurLoop != nullptr && SafetyInfo != nullptr &&
@@ -851,7 +910,7 @@ bool llvm::hoistRegion(DomTreeNode *N, AAResults *AA, LoopInfo *LI,
for (BasicBlock *BB : Worklist) {
// Only need to process the contents of this block if it is not part of a
// subloop (which would already have been processed).
- if (inSubLoop(BB, CurLoop, LI))
+ if (!LoopNestMode && inSubLoop(BB, CurLoop, LI))
continue;
for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;) {
@@ -885,7 +944,7 @@ bool llvm::hoistRegion(DomTreeNode *N, AAResults *AA, LoopInfo *LI,
ORE) &&
worthSinkOrHoistInst(I, CurLoop->getLoopPreheader(), ORE, BFI) &&
isSafeToExecuteUnconditionally(
- I, DT, CurLoop, SafetyInfo, ORE,
+ I, DT, TLI, CurLoop, SafetyInfo, ORE,
CurLoop->getLoopPreheader()->getTerminator())) {
hoist(I, DT, CurLoop, CFH.getOrCreateHoistedBlock(BB), SafetyInfo,
MSSAU, SE, ORE);
@@ -1089,7 +1148,7 @@ bool isHoistableAndSinkableInst(Instruction &I) {
isa<InsertValueInst>(I) || isa<FreezeInst>(I));
}
/// Return true if all of the alias sets within this AST are known not to
-/// contain a Mod, or if MSSA knows thare are no MemoryDefs in the loop.
+/// contain a Mod, or if MSSA knows there are no MemoryDefs in the loop.
bool isReadOnly(AliasSetTracker *CurAST, const MemorySSAUpdater *MSSAU,
const Loop *L) {
if (CurAST) {
@@ -1314,7 +1373,7 @@ bool llvm::canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT,
}
// Any call, while it may not be clobbering SI, it may be a use.
if (auto *CI = dyn_cast<CallInst>(MD->getMemoryInst())) {
- // Check if the call may read from the memory locattion written
+ // Check if the call may read from the memory location written
// to by SI. Check CI's attributes and arguments; the number of
// such checks performed is limited above by NoOfMemAccTooLarge.
ModRefInfo MRI = AA->getModRefInfo(CI, MemoryLocation::get(SI));
@@ -1466,25 +1525,23 @@ static Instruction *cloneInstructionInExitBlock(
}
}
- // Build LCSSA PHI nodes for any in-loop operands. Note that this is
- // particularly cheap because we can rip off the PHI node that we're
+ // Build LCSSA PHI nodes for any in-loop operands (if legal). Note that
+ // this is particularly cheap because we can rip off the PHI node that we're
// replacing for the number and blocks of the predecessors.
// OPT: If this shows up in a profile, we can instead finish sinking all
// invariant instructions, and then walk their operands to re-establish
// LCSSA. That will eliminate creating PHI nodes just to nuke them when
// sinking bottom-up.
- for (User::op_iterator OI = New->op_begin(), OE = New->op_end(); OI != OE;
- ++OI)
- if (Instruction *OInst = dyn_cast<Instruction>(*OI))
- if (Loop *OLoop = LI->getLoopFor(OInst->getParent()))
- if (!OLoop->contains(&PN)) {
- PHINode *OpPN =
- PHINode::Create(OInst->getType(), PN.getNumIncomingValues(),
- OInst->getName() + ".lcssa", &ExitBlock.front());
- for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i)
- OpPN->addIncoming(OInst, PN.getIncomingBlock(i));
- *OI = OpPN;
- }
+ for (Use &Op : New->operands())
+ if (LI->wouldBeOutOfLoopUseRequiringLCSSA(Op.get(), PN.getParent())) {
+ auto *OInst = cast<Instruction>(Op.get());
+ PHINode *OpPN =
+ PHINode::Create(OInst->getType(), PN.getNumIncomingValues(),
+ OInst->getName() + ".lcssa", &ExitBlock.front());
+ for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i)
+ OpPN->addIncoming(OInst, PN.getIncomingBlock(i));
+ Op = OpPN;
+ }
return New;
}
@@ -1627,17 +1684,8 @@ static bool sink(Instruction &I, LoopInfo *LI, DominatorTree *DT,
BlockFrequencyInfo *BFI, const Loop *CurLoop,
ICFLoopSafetyInfo *SafetyInfo, MemorySSAUpdater *MSSAU,
OptimizationRemarkEmitter *ORE) {
- LLVM_DEBUG(dbgs() << "LICM sinking instruction: " << I << "\n");
- ORE->emit([&]() {
- return OptimizationRemark(DEBUG_TYPE, "InstSunk", &I)
- << "sinking " << ore::NV("Inst", &I);
- });
bool Changed = false;
- if (isa<LoadInst>(I))
- ++NumMovedLoads;
- else if (isa<CallInst>(I))
- ++NumMovedCalls;
- ++NumSunk;
+ LLVM_DEBUG(dbgs() << "LICM sinking instruction: " << I << "\n");
// Iterate over users to be ready for actual sinking. Replace users via
// unreachable blocks with undef and make all user PHIs trivially replaceable.
@@ -1689,6 +1737,16 @@ static bool sink(Instruction &I, LoopInfo *LI, DominatorTree *DT,
if (VisitedUsers.empty())
return Changed;
+ ORE->emit([&]() {
+ return OptimizationRemark(DEBUG_TYPE, "InstSunk", &I)
+ << "sinking " << ore::NV("Inst", &I);
+ });
+ if (isa<LoadInst>(I))
+ ++NumMovedLoads;
+ else if (isa<CallInst>(I))
+ ++NumMovedCalls;
+ ++NumSunk;
+
#ifndef NDEBUG
SmallVector<BasicBlock *, 32> ExitBlocks;
CurLoop->getUniqueExitBlocks(ExitBlocks);
@@ -1752,12 +1810,16 @@ static void hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop,
// Conservatively strip all metadata on the instruction unless we were
// guaranteed to execute I if we entered the loop, in which case the metadata
// is valid in the loop preheader.
- if (I.hasMetadataOtherThanDebugLoc() &&
+ // Similarly, If I is a call and it is not guaranteed to execute in the loop,
+ // then moving to the preheader means we should strip attributes on the call
+ // that can cause UB since we may be hoisting above conditions that allowed
+ // inferring those attributes. They may not be valid at the preheader.
+ if ((I.hasMetadataOtherThanDebugLoc() || isa<CallInst>(I)) &&
// The check on hasMetadataOtherThanDebugLoc is to prevent us from burning
// time in isGuaranteedToExecute if we don't actually have anything to
// drop. It is a compile time optimization, not required for correctness.
!SafetyInfo->isGuaranteedToExecute(I, DT, CurLoop))
- I.dropUnknownNonDebugMetadata();
+ I.dropUndefImplyingAttrsAndUnknownMetadata();
if (isa<PHINode>(I))
// Move the new node to the end of the phi list in the destination block.
@@ -1780,11 +1842,12 @@ static void hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop,
/// or if it is a trapping instruction and is guaranteed to execute.
static bool isSafeToExecuteUnconditionally(Instruction &Inst,
const DominatorTree *DT,
+ const TargetLibraryInfo *TLI,
const Loop *CurLoop,
const LoopSafetyInfo *SafetyInfo,
OptimizationRemarkEmitter *ORE,
const Instruction *CtxI) {
- if (isSafeToSpeculativelyExecute(&Inst, CtxI, DT))
+ if (isSafeToSpeculativelyExecute(&Inst, CtxI, DT, TLI))
return true;
bool GuaranteedToExecute =
@@ -1821,19 +1884,21 @@ class LoopPromoter : public LoadAndStorePromoter {
AAMDNodes AATags;
ICFLoopSafetyInfo &SafetyInfo;
+ // We're about to add a use of V in a loop exit block. Insert an LCSSA phi
+ // (if legal) if doing so would add an out-of-loop use to an instruction
+ // defined in-loop.
Value *maybeInsertLCSSAPHI(Value *V, BasicBlock *BB) const {
- if (Instruction *I = dyn_cast<Instruction>(V))
- if (Loop *L = LI.getLoopFor(I->getParent()))
- if (!L->contains(BB)) {
- // We need to create an LCSSA PHI node for the incoming value and
- // store that.
- PHINode *PN = PHINode::Create(I->getType(), PredCache.size(BB),
- I->getName() + ".lcssa", &BB->front());
- for (BasicBlock *Pred : PredCache.get(BB))
- PN->addIncoming(I, Pred);
- return PN;
- }
- return V;
+ if (!LI.wouldBeOutOfLoopUseRequiringLCSSA(V, BB))
+ return V;
+
+ Instruction *I = cast<Instruction>(V);
+ // We need to create an LCSSA PHI node for the incoming value and
+ // store that.
+ PHINode *PN = PHINode::Create(I->getType(), PredCache.size(BB),
+ I->getName() + ".lcssa", &BB->front());
+ for (BasicBlock *Pred : PredCache.get(BB))
+ PN->addIncoming(I, Pred);
+ return PN;
}
public:
@@ -1911,10 +1976,21 @@ public:
}
};
+bool isNotCapturedBeforeOrInLoop(const Value *V, const Loop *L,
+ DominatorTree *DT) {
+ // We can perform the captured-before check against any instruction in the
+ // loop header, as the loop header is reachable from any instruction inside
+ // the loop.
+ // TODO: ReturnCaptures=true shouldn't be necessary here.
+ return !PointerMayBeCapturedBefore(V, /* ReturnCaptures */ true,
+ /* StoreCaptures */ true,
+ L->getHeader()->getTerminator(), DT);
+}
/// Return true iff we can prove that a caller of this function can not inspect
/// the contents of the provided object in a well defined program.
-bool isKnownNonEscaping(Value *Object, const TargetLibraryInfo *TLI) {
+bool isKnownNonEscaping(Value *Object, const Loop *L,
+ const TargetLibraryInfo *TLI, DominatorTree *DT) {
if (isa<AllocaInst>(Object))
// Since the alloca goes out of scope, we know the caller can't retain a
// reference to it and be well defined. Thus, we don't need to check for
@@ -1931,7 +2007,7 @@ bool isKnownNonEscaping(Value *Object, const TargetLibraryInfo *TLI) {
// weaker condition and handle only AllocLikeFunctions (which are
// known to be noalias). TODO
return isAllocLikeFn(Object, TLI) &&
- !PointerMayBeCaptured(Object, true, true);
+ isNotCapturedBeforeOrInLoop(Object, L, DT);
}
} // namespace
@@ -2017,7 +2093,7 @@ bool llvm::promoteLoopAccessesToScalars(
// this by proving that the caller can't have a reference to the object
// after return and thus can't possibly load from the object.
Value *Object = getUnderlyingObject(SomePtr);
- if (!isKnownNonEscaping(Object, TLI))
+ if (!isKnownNonEscaping(Object, CurLoop, TLI, DT))
return false;
// Subtlety: Alloca's aren't visible to callers, but *are* potentially
// visible to other threads if captured and used during their lifetimes.
@@ -2054,10 +2130,11 @@ bool llvm::promoteLoopAccessesToScalars(
// Note that proving a load safe to speculate requires proving
// sufficient alignment at the target location. Proving it guaranteed
// to execute does as well. Thus we can increase our guaranteed
- // alignment as well.
+ // alignment as well.
if (!DereferenceableInPH || (InstAlignment > Alignment))
- if (isSafeToExecuteUnconditionally(*Load, DT, CurLoop, SafetyInfo,
- ORE, Preheader->getTerminator())) {
+ if (isSafeToExecuteUnconditionally(*Load, DT, TLI, CurLoop,
+ SafetyInfo, ORE,
+ Preheader->getTerminator())) {
DereferenceableInPH = true;
Alignment = std::max(Alignment, InstAlignment);
}
@@ -2104,7 +2181,7 @@ bool llvm::promoteLoopAccessesToScalars(
if (!DereferenceableInPH) {
DereferenceableInPH = isDereferenceableAndAlignedPointer(
Store->getPointerOperand(), Store->getValueOperand()->getType(),
- Store->getAlign(), MDL, Preheader->getTerminator(), DT);
+ Store->getAlign(), MDL, Preheader->getTerminator(), DT, TLI);
}
} else
return false; // Not a load or store.
@@ -2151,7 +2228,7 @@ bool llvm::promoteLoopAccessesToScalars(
Value *Object = getUnderlyingObject(SomePtr);
SafeToInsertStore =
(isAllocLikeFn(Object, TLI) || isa<AllocaInst>(Object)) &&
- !PointerMayBeCaptured(Object, true, true);
+ isNotCapturedBeforeOrInLoop(Object, CurLoop, DT);
}
}
@@ -2218,6 +2295,67 @@ bool llvm::promoteLoopAccessesToScalars(
return true;
}
+static void foreachMemoryAccess(MemorySSA *MSSA, Loop *L,
+ function_ref<void(Instruction *)> Fn) {
+ for (const BasicBlock *BB : L->blocks())
+ if (const auto *Accesses = MSSA->getBlockAccesses(BB))
+ for (const auto &Access : *Accesses)
+ if (const auto *MUD = dyn_cast<MemoryUseOrDef>(&Access))
+ Fn(MUD->getMemoryInst());
+}
+
+static SmallVector<SmallSetVector<Value *, 8>, 0>
+collectPromotionCandidates(MemorySSA *MSSA, AliasAnalysis *AA, Loop *L) {
+ AliasSetTracker AST(*AA);
+
+ auto IsPotentiallyPromotable = [L](const Instruction *I) {
+ if (const auto *SI = dyn_cast<StoreInst>(I))
+ return L->isLoopInvariant(SI->getPointerOperand());
+ if (const auto *LI = dyn_cast<LoadInst>(I))
+ return L->isLoopInvariant(LI->getPointerOperand());
+ return false;
+ };
+
+ // Populate AST with potentially promotable accesses and remove them from
+ // MaybePromotable, so they will not be checked again on the next iteration.
+ SmallPtrSet<Value *, 16> AttemptingPromotion;
+ foreachMemoryAccess(MSSA, L, [&](Instruction *I) {
+ if (IsPotentiallyPromotable(I)) {
+ AttemptingPromotion.insert(I);
+ AST.add(I);
+ }
+ });
+
+ // We're only interested in must-alias sets that contain a mod.
+ SmallVector<const AliasSet *, 8> Sets;
+ for (AliasSet &AS : AST)
+ if (!AS.isForwardingAliasSet() && AS.isMod() && AS.isMustAlias())
+ Sets.push_back(&AS);
+
+ if (Sets.empty())
+ return {}; // Nothing to promote...
+
+ // Discard any sets for which there is an aliasing non-promotable access.
+ foreachMemoryAccess(MSSA, L, [&](Instruction *I) {
+ if (AttemptingPromotion.contains(I))
+ return;
+
+ llvm::erase_if(Sets, [&](const AliasSet *AS) {
+ return AS->aliasesUnknownInst(I, *AA);
+ });
+ });
+
+ SmallVector<SmallSetVector<Value *, 8>, 0> Result;
+ for (const AliasSet *Set : Sets) {
+ SmallSetVector<Value *, 8> PointerMustAliases;
+ for (const auto &ASI : *Set)
+ PointerMustAliases.insert(ASI.getValue());
+ Result.push_back(std::move(PointerMustAliases));
+ }
+
+ return Result;
+}
+
/// Returns an owning pointer to an alias set which incorporates aliasing info
/// from L and all subloops of L.
std::unique_ptr<AliasSetTracker>
@@ -2238,15 +2376,6 @@ LoopInvariantCodeMotion::collectAliasInfoForLoop(Loop *L, LoopInfo *LI,
return CurAST;
}
-std::unique_ptr<AliasSetTracker>
-LoopInvariantCodeMotion::collectAliasInfoForLoopWithMSSA(
- Loop *L, AAResults *AA, MemorySSAUpdater *MSSAU) {
- auto *MSSA = MSSAU->getMemorySSA();
- auto CurAST = std::make_unique<AliasSetTracker>(*AA, MSSA, L);
- CurAST->addAllInstructionsInLoopUsingMSSA();
- return CurAST;
-}
-
static bool pointerInvalidatedByLoop(MemoryLocation MemLoc,
AliasSetTracker *CurAST, Loop *CurLoop,
AAResults *AA) {