diff options
Diffstat (limited to 'llvm/lib/Transforms/Scalar/LICM.cpp')
-rw-r--r-- | llvm/lib/Transforms/Scalar/LICM.cpp | 319 |
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) { |