[LICM] Remove AST-based implementation

MSSA-based LICM has been enabled by default for a few years now.
This drops the old AST-based implementation. Using loop(licm) will
result in a fatal error, the use of loop-mssa(licm) is required
(or just licm, which defaults to loop-mssa).

Note that the core canSinkOrHoistInst() logic has to retain AST
support for now, because it is shared with LoopSink.

Differential Revision: https://reviews.llvm.org/D108244
This commit is contained in:
Nikita Popov 2021-08-17 21:31:35 +02:00
parent 4d559837e8
commit 3dd8c9176b
53 changed files with 179 additions and 283 deletions

View File

@ -151,18 +151,17 @@ protected:
/// this function is called by \p sinkRegionForLoopNest.
bool sinkRegion(DomTreeNode *, AAResults *, LoopInfo *, DominatorTree *,
BlockFrequencyInfo *, TargetLibraryInfo *,
TargetTransformInfo *, Loop *CurLoop, AliasSetTracker *,
MemorySSAUpdater *, ICFLoopSafetyInfo *,
SinkAndHoistLICMFlags &, OptimizationRemarkEmitter *,
Loop *OutermostLoop = nullptr);
TargetTransformInfo *, Loop *CurLoop, MemorySSAUpdater *,
ICFLoopSafetyInfo *, SinkAndHoistLICMFlags &,
OptimizationRemarkEmitter *, Loop *OutermostLoop = nullptr);
/// Call sinkRegion on loops contained within the specified loop
/// in order from innermost to outermost.
bool sinkRegionForLoopNest(DomTreeNode *, AAResults *, LoopInfo *,
DominatorTree *, BlockFrequencyInfo *,
TargetLibraryInfo *, TargetTransformInfo *, Loop *,
AliasSetTracker *, MemorySSAUpdater *,
ICFLoopSafetyInfo *, SinkAndHoistLICMFlags &,
MemorySSAUpdater *, ICFLoopSafetyInfo *,
SinkAndHoistLICMFlags &,
OptimizationRemarkEmitter *);
/// Walk the specified region of the CFG (defined by all blocks
@ -175,9 +174,8 @@ bool sinkRegionForLoopNest(DomTreeNode *, AAResults *, LoopInfo *,
/// Diagnostics is emitted via \p ORE. It returns changed status.
bool hoistRegion(DomTreeNode *, AAResults *, LoopInfo *, DominatorTree *,
BlockFrequencyInfo *, TargetLibraryInfo *, Loop *,
AliasSetTracker *, MemorySSAUpdater *, ScalarEvolution *,
ICFLoopSafetyInfo *, SinkAndHoistLICMFlags &,
OptimizationRemarkEmitter *, bool);
MemorySSAUpdater *, ScalarEvolution *, ICFLoopSafetyInfo *,
SinkAndHoistLICMFlags &, OptimizationRemarkEmitter *, bool);
/// This function deletes dead loops. The caller of this function needs to
/// guarantee that the loop is infact dead.
@ -211,7 +209,7 @@ bool promoteLoopAccessesToScalars(
const SmallSetVector<Value *, 8> &, SmallVectorImpl<BasicBlock *> &,
SmallVectorImpl<Instruction *> &, SmallVectorImpl<MemoryAccess *> &,
PredIteratorCache &, LoopInfo *, DominatorTree *, const TargetLibraryInfo *,
Loop *, AliasSetTracker *, MemorySSAUpdater *, ICFLoopSafetyInfo *,
Loop *, MemorySSAUpdater *, ICFLoopSafetyInfo *,
OptimizationRemarkEmitter *);
/// Does a BFS from a given node to all of its children inside a given loop.

View File

@ -174,7 +174,7 @@ static Instruction *cloneInstructionInExitBlock(
const LoopSafetyInfo *SafetyInfo, MemorySSAUpdater *MSSAU);
static void eraseInstruction(Instruction &I, ICFLoopSafetyInfo &SafetyInfo,
AliasSetTracker *AST, MemorySSAUpdater *MSSAU);
MemorySSAUpdater *MSSAU);
static void moveInstructionBefore(Instruction &I, Instruction &Dest,
ICFLoopSafetyInfo &SafetyInfo,
@ -200,9 +200,6 @@ struct LoopInvariantCodeMotion {
private:
unsigned LicmMssaOptCap;
unsigned LicmMssaNoAccForPromotionCap;
std::unique_ptr<AliasSetTracker>
collectAliasInfoForLoop(Loop *L, LoopInfo *LI, AAResults *AA);
};
struct LegacyLICMPass : public LoopPass {
@ -265,6 +262,9 @@ private:
PreservedAnalyses LICMPass::run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR, LPMUpdater &) {
if (!AR.MSSA)
report_fatal_error("LICM requires MemorySSA (loop-mssa)");
// 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).
@ -279,8 +279,7 @@ PreservedAnalyses LICMPass::run(Loop &L, LoopAnalysisManager &AM,
PA.preserve<DominatorTreeAnalysis>();
PA.preserve<LoopAnalysis>();
if (AR.MSSA)
PA.preserve<MemorySSAAnalysis>();
PA.preserve<MemorySSAAnalysis>();
return PA;
}
@ -288,6 +287,9 @@ PreservedAnalyses LICMPass::run(Loop &L, LoopAnalysisManager &AM,
PreservedAnalyses LNICMPass::run(LoopNest &LN, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR,
LPMUpdater &) {
if (!AR.MSSA)
report_fatal_error("LNICM requires MemorySSA (loop-mssa)");
// 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).
@ -306,8 +308,7 @@ PreservedAnalyses LNICMPass::run(LoopNest &LN, LoopAnalysisManager &AM,
PA.preserve<DominatorTreeAnalysis>();
PA.preserve<LoopAnalysis>();
if (AR.MSSA)
PA.preserve<MemorySSAAnalysis>();
PA.preserve<MemorySSAAnalysis>();
return PA;
}
@ -376,10 +377,6 @@ bool LoopInvariantCodeMotion::runOnLoop(
return false;
}
std::unique_ptr<AliasSetTracker> CurAST;
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
@ -396,17 +393,9 @@ bool LoopInvariantCodeMotion::runOnLoop(
});
});
if (!MSSA) {
LLVM_DEBUG(dbgs() << "LICM: Using Alias Set Tracker.\n");
CurAST = collectAliasInfoForLoop(L, LI, AA);
Flags = std::make_unique<SinkAndHoistLICMFlags>(
LicmMssaOptCap, LicmMssaNoAccForPromotionCap, /*IsSink=*/true);
} else {
LLVM_DEBUG(dbgs() << "LICM: Using MemorySSA.\n");
MSSAU = std::make_unique<MemorySSAUpdater>(MSSA);
Flags = std::make_unique<SinkAndHoistLICMFlags>(
LicmMssaOptCap, LicmMssaNoAccForPromotionCap, /*IsSink=*/true, L, MSSA);
}
MemorySSAUpdater MSSAU(MSSA);
SinkAndHoistLICMFlags Flags(LicmMssaOptCap, LicmMssaNoAccForPromotionCap,
/*IsSink=*/true, L, MSSA);
// Get the preheader block to move instructions into...
BasicBlock *Preheader = L->getLoopPreheader();
@ -425,19 +414,16 @@ bool LoopInvariantCodeMotion::runOnLoop(
// us to sink instructions in one pass, without iteration. After sinking
// instructions, we perform another pass to hoist them out of the loop.
if (L->hasDedicatedExits())
Changed |=
LoopNestMode
? sinkRegionForLoopNest(DT->getNode(L->getHeader()), AA, LI, DT,
BFI, TLI, TTI, L, CurAST.get(), MSSAU.get(),
&SafetyInfo, *Flags.get(), ORE)
: sinkRegion(DT->getNode(L->getHeader()), AA, LI, DT, BFI, TLI, TTI,
L, CurAST.get(), MSSAU.get(), &SafetyInfo,
*Flags.get(), ORE);
Flags->setIsSink(false);
Changed |= LoopNestMode
? sinkRegionForLoopNest(DT->getNode(L->getHeader()), AA, LI,
DT, BFI, TLI, TTI, L, &MSSAU,
&SafetyInfo, Flags, ORE)
: sinkRegion(DT->getNode(L->getHeader()), AA, LI, DT, BFI,
TLI, TTI, L, &MSSAU, &SafetyInfo, Flags, ORE);
Flags.setIsSink(false);
if (Preheader)
Changed |= hoistRegion(DT->getNode(L->getHeader()), AA, LI, DT, BFI, TLI, L,
CurAST.get(), MSSAU.get(), SE, &SafetyInfo,
*Flags.get(), ORE, LoopNestMode);
&MSSAU, SE, &SafetyInfo, Flags, ORE, LoopNestMode);
// Now that all loop invariants have been removed from the loop, promote any
// memory references to scalars that we can.
@ -447,7 +433,7 @@ bool LoopInvariantCodeMotion::runOnLoop(
// preheader for SSA updater, so also avoid sinking when no preheader
// is available.
if (!DisablePromotion && Preheader && L->hasDedicatedExits() &&
!Flags->tooManyMemoryAccesses() && !HasCoroSuspendInst) {
!Flags.tooManyMemoryAccesses() && !HasCoroSuspendInst) {
// Figure out the loop exits and their insertion points
SmallVector<BasicBlock *, 8> ExitBlocks;
L->getUniqueExitBlocks(ExitBlocks);
@ -461,55 +447,29 @@ bool LoopInvariantCodeMotion::runOnLoop(
SmallVector<Instruction *, 8> InsertPts;
SmallVector<MemoryAccess *, 8> MSSAInsertPts;
InsertPts.reserve(ExitBlocks.size());
if (MSSAU)
MSSAInsertPts.reserve(ExitBlocks.size());
MSSAInsertPts.reserve(ExitBlocks.size());
for (BasicBlock *ExitBlock : ExitBlocks) {
InsertPts.push_back(&*ExitBlock->getFirstInsertionPt());
if (MSSAU)
MSSAInsertPts.push_back(nullptr);
MSSAInsertPts.push_back(nullptr);
}
PredIteratorCache PIC;
// 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 Promoted = false;
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);
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, &MSSAU, &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);
}
Promoted |= LocalPromoted;
} while (LocalPromoted);
// Once we have promoted values across the loop body we have to
// recursively reform LCSSA as any nested loop may now have values defined
@ -531,8 +491,8 @@ bool LoopInvariantCodeMotion::runOnLoop(
assert((L->isOutermost() || L->getParentLoop()->isLCSSAForm(*DT)) &&
"Parent loop not left in LCSSA form after LICM!");
if (MSSAU.get() && VerifyMemorySSA)
MSSAU->getMemorySSA()->verifyMemorySSA();
if (VerifyMemorySSA)
MSSA->verifyMemorySSA();
if (Changed && SE)
SE->forgetLoopDispositions(L);
@ -547,17 +507,15 @@ bool LoopInvariantCodeMotion::runOnLoop(
bool llvm::sinkRegion(DomTreeNode *N, AAResults *AA, LoopInfo *LI,
DominatorTree *DT, BlockFrequencyInfo *BFI,
TargetLibraryInfo *TLI, TargetTransformInfo *TTI,
Loop *CurLoop, AliasSetTracker *CurAST,
MemorySSAUpdater *MSSAU, ICFLoopSafetyInfo *SafetyInfo,
Loop *CurLoop, MemorySSAUpdater *MSSAU,
ICFLoopSafetyInfo *SafetyInfo,
SinkAndHoistLICMFlags &Flags,
OptimizationRemarkEmitter *ORE, Loop *OutermostLoop) {
// Verify inputs.
assert(N != nullptr && AA != nullptr && LI != nullptr && DT != nullptr &&
CurLoop != nullptr && SafetyInfo != nullptr &&
CurLoop != nullptr && MSSAU != nullptr && SafetyInfo != nullptr &&
"Unexpected input to sinkRegion.");
assert(((CurAST != nullptr) ^ (MSSAU != nullptr)) &&
"Either AliasSetTracker or MemorySSA should be initialized.");
// We want to visit children before parents. We will enque all the parents
// before their children in the worklist and process the worklist in reverse
@ -582,7 +540,7 @@ bool llvm::sinkRegion(DomTreeNode *N, AAResults *AA, LoopInfo *LI,
salvageKnowledge(&I);
salvageDebugInfo(I);
++II;
eraseInstruction(I, *SafetyInfo, CurAST, MSSAU);
eraseInstruction(I, *SafetyInfo, MSSAU);
Changed = true;
continue;
}
@ -597,20 +555,20 @@ bool llvm::sinkRegion(DomTreeNode *N, AAResults *AA, LoopInfo *LI,
if (!I.mayHaveSideEffects() &&
isNotUsedOrFreeInLoop(I, LoopNestMode ? OutermostLoop : CurLoop,
SafetyInfo, TTI, FreeInLoop, LoopNestMode) &&
canSinkOrHoistInst(I, AA, DT, CurLoop, CurAST, MSSAU, true, &Flags,
ORE)) {
canSinkOrHoistInst(I, AA, DT, CurLoop, /*CurAST*/nullptr, MSSAU, true,
&Flags, ORE)) {
if (sink(I, LI, DT, BFI, CurLoop, SafetyInfo, MSSAU, ORE)) {
if (!FreeInLoop) {
++II;
salvageDebugInfo(I);
eraseInstruction(I, *SafetyInfo, CurAST, MSSAU);
eraseInstruction(I, *SafetyInfo, MSSAU);
}
Changed = true;
}
}
}
}
if (MSSAU && VerifyMemorySSA)
if (VerifyMemorySSA)
MSSAU->getMemorySSA()->verifyMemorySSA();
return Changed;
}
@ -618,9 +576,8 @@ bool llvm::sinkRegion(DomTreeNode *N, AAResults *AA, LoopInfo *LI,
bool llvm::sinkRegionForLoopNest(
DomTreeNode *N, AAResults *AA, LoopInfo *LI, DominatorTree *DT,
BlockFrequencyInfo *BFI, TargetLibraryInfo *TLI, TargetTransformInfo *TTI,
Loop *CurLoop, AliasSetTracker *CurAST, MemorySSAUpdater *MSSAU,
ICFLoopSafetyInfo *SafetyInfo, SinkAndHoistLICMFlags &Flags,
OptimizationRemarkEmitter *ORE) {
Loop *CurLoop, MemorySSAUpdater *MSSAU, ICFLoopSafetyInfo *SafetyInfo,
SinkAndHoistLICMFlags &Flags, OptimizationRemarkEmitter *ORE) {
bool Changed = false;
SmallPriorityWorklist<Loop *, 4> Worklist;
@ -628,9 +585,8 @@ bool llvm::sinkRegionForLoopNest(
appendLoopsToWorklist(*CurLoop, Worklist);
while (!Worklist.empty()) {
Loop *L = Worklist.pop_back_val();
Changed |=
sinkRegion(DT->getNode(L->getHeader()), AA, LI, DT, BFI, TLI, TTI, L,
CurAST, MSSAU, SafetyInfo, Flags, ORE, CurLoop);
Changed |= sinkRegion(DT->getNode(L->getHeader()), AA, LI, DT, BFI, TLI,
TTI, L, MSSAU, SafetyInfo, Flags, ORE, CurLoop);
}
return Changed;
}
@ -837,9 +793,8 @@ public:
if (HoistTarget == InitialPreheader) {
// Phis in the loop header now need to use the new preheader.
InitialPreheader->replaceSuccessorsPhiUsesWith(HoistCommonSucc);
if (MSSAU)
MSSAU->wireOldPredecessorsToNewImmediatePredecessor(
HoistTarget->getSingleSuccessor(), HoistCommonSucc, {HoistTarget});
MSSAU->wireOldPredecessorsToNewImmediatePredecessor(
HoistTarget->getSingleSuccessor(), HoistCommonSucc, {HoistTarget});
// The new preheader dominates the loop header.
DomTreeNode *PreheaderNode = DT->getNode(HoistCommonSucc);
DomTreeNode *HeaderNode = DT->getNode(CurLoop->getHeader());
@ -901,16 +856,14 @@ static bool worthSinkOrHoistInst(Instruction &I, BasicBlock *DstBlock,
bool llvm::hoistRegion(DomTreeNode *N, AAResults *AA, LoopInfo *LI,
DominatorTree *DT, BlockFrequencyInfo *BFI,
TargetLibraryInfo *TLI, Loop *CurLoop,
AliasSetTracker *CurAST, MemorySSAUpdater *MSSAU,
ScalarEvolution *SE, ICFLoopSafetyInfo *SafetyInfo,
MemorySSAUpdater *MSSAU, ScalarEvolution *SE,
ICFLoopSafetyInfo *SafetyInfo,
SinkAndHoistLICMFlags &Flags,
OptimizationRemarkEmitter *ORE, bool LoopNestMode) {
// Verify inputs.
assert(N != nullptr && AA != nullptr && LI != nullptr && DT != nullptr &&
CurLoop != nullptr && SafetyInfo != nullptr &&
CurLoop != nullptr && MSSAU != nullptr && SafetyInfo != nullptr &&
"Unexpected input to hoistRegion.");
assert(((CurAST != nullptr) ^ (MSSAU != nullptr)) &&
"Either AliasSetTracker or MemorySSA should be initialized.");
ControlFlowHoister CFH(LI, DT, CurLoop, MSSAU);
@ -939,12 +892,10 @@ bool llvm::hoistRegion(DomTreeNode *N, AAResults *AA, LoopInfo *LI,
&I, I.getModule()->getDataLayout(), TLI)) {
LLVM_DEBUG(dbgs() << "LICM folding inst: " << I << " --> " << *C
<< '\n');
if (CurAST)
CurAST->copyValue(&I, C);
// FIXME MSSA: Such replacements may make accesses unoptimized (D51960).
I.replaceAllUsesWith(C);
if (isInstructionTriviallyDead(&I, TLI))
eraseInstruction(I, *SafetyInfo, CurAST, MSSAU);
eraseInstruction(I, *SafetyInfo, MSSAU);
Changed = true;
continue;
}
@ -957,8 +908,8 @@ bool llvm::hoistRegion(DomTreeNode *N, AAResults *AA, LoopInfo *LI,
// and we have accurately duplicated the control flow from the loop header
// to that block.
if (CurLoop->hasLoopInvariantOperands(&I) &&
canSinkOrHoistInst(I, AA, DT, CurLoop, CurAST, MSSAU, true, &Flags,
ORE) &&
canSinkOrHoistInst(I, AA, DT, CurLoop, /*CurAST*/ nullptr, MSSAU,
true, &Flags, ORE) &&
worthSinkOrHoistInst(I, CurLoop->getLoopPreheader(), ORE, BFI) &&
isSafeToExecuteUnconditionally(
I, DT, TLI, CurLoop, SafetyInfo, ORE,
@ -987,7 +938,7 @@ bool llvm::hoistRegion(DomTreeNode *N, AAResults *AA, LoopInfo *LI,
SafetyInfo->insertInstructionTo(Product, I.getParent());
Product->insertAfter(&I);
I.replaceAllUsesWith(Product);
eraseInstruction(I, *SafetyInfo, CurAST, MSSAU);
eraseInstruction(I, *SafetyInfo, MSSAU);
hoist(*ReciprocalDivisor, DT, CurLoop, CFH.getOrCreateHoistedBlock(BB),
SafetyInfo, MSSAU, SE, ORE);
@ -1066,7 +1017,7 @@ bool llvm::hoistRegion(DomTreeNode *N, AAResults *AA, LoopInfo *LI,
}
}
}
if (MSSAU && VerifyMemorySSA)
if (VerifyMemorySSA)
MSSAU->getMemorySSA()->verifyMemorySSA();
// Now that we've finished hoisting make sure that LI and DT are still
@ -1573,9 +1524,7 @@ static Instruction *cloneInstructionInExitBlock(
}
static void eraseInstruction(Instruction &I, ICFLoopSafetyInfo &SafetyInfo,
AliasSetTracker *AST, MemorySSAUpdater *MSSAU) {
if (AST)
AST->deleteValue(&I);
MemorySSAUpdater *MSSAU) {
if (MSSAU)
MSSAU->removeMemoryAccess(&I);
SafetyInfo.removeInstruction(&I);
@ -1813,7 +1762,7 @@ static bool sink(Instruction &I, LoopInfo *LI, DominatorTree *DT,
Instruction *New = sinkThroughTriviallyReplaceablePHI(
PN, &I, LI, SunkCopies, SafetyInfo, CurLoop, MSSAU);
PN->replaceAllUsesWith(New);
eraseInstruction(*PN, *SafetyInfo, nullptr, nullptr);
eraseInstruction(*PN, *SafetyInfo, nullptr);
Changed = true;
}
return Changed;
@ -1902,7 +1851,6 @@ class LoopPromoter : public LoadAndStorePromoter {
SmallVectorImpl<Instruction *> &LoopInsertPts;
SmallVectorImpl<MemoryAccess *> &MSSAInsertPts;
PredIteratorCache &PredCache;
AliasSetTracker *AST;
MemorySSAUpdater *MSSAU;
LoopInfo &LI;
DebugLoc DL;
@ -1934,12 +1882,12 @@ public:
SmallVectorImpl<BasicBlock *> &LEB,
SmallVectorImpl<Instruction *> &LIP,
SmallVectorImpl<MemoryAccess *> &MSSAIP, PredIteratorCache &PIC,
AliasSetTracker *ast, MemorySSAUpdater *MSSAU, LoopInfo &li,
DebugLoc dl, int alignment, bool UnorderedAtomic,
const AAMDNodes &AATags, ICFLoopSafetyInfo &SafetyInfo)
MemorySSAUpdater *MSSAU, LoopInfo &li, DebugLoc dl,
int alignment, bool UnorderedAtomic, const AAMDNodes &AATags,
ICFLoopSafetyInfo &SafetyInfo)
: LoadAndStorePromoter(Insts, S), SomePtr(SP), PointerMustAliases(PMA),
LoopExitBlocks(LEB), LoopInsertPts(LIP), MSSAInsertPts(MSSAIP),
PredCache(PIC), AST(ast), MSSAU(MSSAU), LI(li), DL(std::move(dl)),
PredCache(PIC), MSSAU(MSSAU), LI(li), DL(std::move(dl)),
Alignment(alignment), UnorderedAtomic(UnorderedAtomic), AATags(AATags),
SafetyInfo(SafetyInfo) {}
@ -1972,34 +1920,24 @@ public:
if (AATags)
NewSI->setAAMetadata(AATags);
if (MSSAU) {
MemoryAccess *MSSAInsertPoint = MSSAInsertPts[i];
MemoryAccess *NewMemAcc;
if (!MSSAInsertPoint) {
NewMemAcc = MSSAU->createMemoryAccessInBB(
NewSI, nullptr, NewSI->getParent(), MemorySSA::Beginning);
} else {
NewMemAcc =
MSSAU->createMemoryAccessAfter(NewSI, nullptr, MSSAInsertPoint);
}
MSSAInsertPts[i] = NewMemAcc;
MSSAU->insertDef(cast<MemoryDef>(NewMemAcc), true);
// FIXME: true for safety, false may still be correct.
MemoryAccess *MSSAInsertPoint = MSSAInsertPts[i];
MemoryAccess *NewMemAcc;
if (!MSSAInsertPoint) {
NewMemAcc = MSSAU->createMemoryAccessInBB(
NewSI, nullptr, NewSI->getParent(), MemorySSA::Beginning);
} else {
NewMemAcc =
MSSAU->createMemoryAccessAfter(NewSI, nullptr, MSSAInsertPoint);
}
MSSAInsertPts[i] = NewMemAcc;
MSSAU->insertDef(cast<MemoryDef>(NewMemAcc), true);
// FIXME: true for safety, false may still be correct.
}
}
void replaceLoadWithValue(LoadInst *LI, Value *V) const override {
// Update alias analysis.
if (AST)
AST->copyValue(LI, V);
}
void instructionDeleted(Instruction *I) const override {
SafetyInfo.removeInstruction(I);
if (AST)
AST->deleteValue(I);
if (MSSAU)
MSSAU->removeMemoryAccess(I);
MSSAU->removeMemoryAccess(I);
}
};
@ -2050,8 +1988,8 @@ bool llvm::promoteLoopAccessesToScalars(
SmallVectorImpl<Instruction *> &InsertPts,
SmallVectorImpl<MemoryAccess *> &MSSAInsertPts, PredIteratorCache &PIC,
LoopInfo *LI, DominatorTree *DT, const TargetLibraryInfo *TLI,
Loop *CurLoop, AliasSetTracker *CurAST, MemorySSAUpdater *MSSAU,
ICFLoopSafetyInfo *SafetyInfo, OptimizationRemarkEmitter *ORE) {
Loop *CurLoop, MemorySSAUpdater *MSSAU, ICFLoopSafetyInfo *SafetyInfo,
OptimizationRemarkEmitter *ORE) {
// Verify inputs.
assert(LI != nullptr && DT != nullptr && CurLoop != nullptr &&
SafetyInfo != nullptr &&
@ -2283,7 +2221,7 @@ bool llvm::promoteLoopAccessesToScalars(
SmallVector<PHINode *, 16> NewPHIs;
SSAUpdater SSA(&NewPHIs);
LoopPromoter Promoter(SomePtr, LoopUses, SSA, PointerMustAliases, ExitBlocks,
InsertPts, MSSAInsertPts, PIC, CurAST, MSSAU, *LI, DL,
InsertPts, MSSAInsertPts, PIC, MSSAU, *LI, DL,
Alignment.value(), SawUnorderedAtomic, AATags,
*SafetyInfo);
@ -2300,24 +2238,22 @@ bool llvm::promoteLoopAccessesToScalars(
PreheaderLoad->setAAMetadata(AATags);
SSA.AddAvailableValue(Preheader, PreheaderLoad);
if (MSSAU) {
MemoryAccess *PreheaderLoadMemoryAccess = MSSAU->createMemoryAccessInBB(
PreheaderLoad, nullptr, PreheaderLoad->getParent(), MemorySSA::End);
MemoryUse *NewMemUse = cast<MemoryUse>(PreheaderLoadMemoryAccess);
MSSAU->insertUse(NewMemUse, /*RenameUses=*/true);
}
MemoryAccess *PreheaderLoadMemoryAccess = MSSAU->createMemoryAccessInBB(
PreheaderLoad, nullptr, PreheaderLoad->getParent(), MemorySSA::End);
MemoryUse *NewMemUse = cast<MemoryUse>(PreheaderLoadMemoryAccess);
MSSAU->insertUse(NewMemUse, /*RenameUses=*/true);
if (MSSAU && VerifyMemorySSA)
if (VerifyMemorySSA)
MSSAU->getMemorySSA()->verifyMemorySSA();
// Rewrite all the loads in the loop and remember all the definitions from
// stores in the loop.
Promoter.run(LoopUses);
if (MSSAU && VerifyMemorySSA)
if (VerifyMemorySSA)
MSSAU->getMemorySSA()->verifyMemorySSA();
// If the SSAUpdater didn't use the load in the preheader, just zap it now.
if (PreheaderLoad->use_empty())
eraseInstruction(*PreheaderLoad, *SafetyInfo, CurAST, MSSAU);
eraseInstruction(*PreheaderLoad, *SafetyInfo, MSSAU);
return true;
}
@ -2383,26 +2319,6 @@ collectPromotionCandidates(MemorySSA *MSSA, AliasAnalysis *AA, Loop *L) {
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>
LoopInvariantCodeMotion::collectAliasInfoForLoop(Loop *L, LoopInfo *LI,
AAResults *AA) {
auto CurAST = std::make_unique<AliasSetTracker>(*AA);
// Add everything from all the sub loops.
for (Loop *InnerL : L->getSubLoops())
for (BasicBlock *BB : InnerL->blocks())
CurAST->add(*BB);
// And merge in this loop (without anything from inner loops).
for (BasicBlock *BB : L->blocks())
if (LI->getLoopFor(BB) == L)
CurAST->add(*BB);
return CurAST;
}
static bool pointerInvalidatedByLoop(MemoryLocation MemLoc,
AliasSetTracker *CurAST, Loop *CurLoop,
AAResults *AA) {

View File

@ -2,9 +2,8 @@
; disambiguating some obvious cases. If LICM is able to disambiguate the
; two pointers, then the load should be hoisted, and the store sunk.
; RUN: opt < %s -basic-aa -licm -enable-new-pm=0 -S | FileCheck %s -check-prefixes=CHECK,MSSA
; RUN: opt < %s -aa-pipeline=basic-aa -passes='loop(licm)' -S | FileCheck %s -check-prefixes=CHECK,AST
; RUN: opt < %s -aa-pipeline=basic-aa -passes='loop-mssa(licm)' -S | FileCheck %s -check-prefixes=CHECK,MSSA
; RUN: opt < %s -basic-aa -licm -enable-new-pm=0 -S | FileCheck %s
; RUN: opt < %s -aa-pipeline=basic-aa -passes='loop-mssa(licm)' -S | FileCheck %s
target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
@A = global i32 7 ; <i32*> [#uses=3]
@ -27,13 +26,11 @@ Out: ; preds = %Loop
; The Loop block should be empty after the load/store are promoted.
; CHECK: @test1
; CHECK: load i32, i32* @A
; MSSA: load i32, i32* @A
; MSSA: store i32 %Atmp, i32* @B
; CHECK: load i32, i32* @A
; CHECK: store i32 %Atmp, i32* @B
; CHECK: Loop:
; CHECK-NEXT: br i1 %c, label %Out, label %Loop
; CHECK: Out:
; AST: store i32 %Atmp, i32* @B
; AST: load i32, i32* @A
}
define i32 @test2(i1 %c) {

View File

@ -1,5 +1,5 @@
; RUN: opt < %s -instcombine -globals-aa -licm -enable-new-pm=0 -S | FileCheck %s
; RUN: opt < %s -aa-pipeline=basic-aa,globals-aa -passes='function(instcombine),require<globals-aa>,function(invalidate<aa>,loop(licm))' -S | FileCheck %s
; RUN: opt < %s -aa-pipeline=basic-aa,globals-aa -passes='function(instcombine),require<globals-aa>,function(invalidate<aa>,loop-mssa(licm))' -S | FileCheck %s
; Make sure -globals-aa ignores dead uses of globals.

View File

@ -2,7 +2,6 @@
; RUN: opt -loop-rotate -licm %s -disable-output -debug-only=licm 2>&1 | FileCheck %s -check-prefix=LICM
; RUN: opt -loop-rotate -licm %s -S | FileCheck %s
; LICM: Using
; LICM-NOT: LICM sinking instruction: %.pre = load i8, i8* %arrayidx.phi.trans.insert
; CHECK-LABEL: @fn1

View File

@ -4,26 +4,26 @@
;
; First make sure we emit remarks on this test case.
; RUN: opt %s -disable-output -aa-pipeline=basic-aa 2>&1 \
; RUN: -passes='require<opt-remark-emit>,loop(licm)' \
; RUN: -passes='require<opt-remark-emit>,loop-mssa(licm)' \
; RUN: -pass-remarks=licm -pass-remarks-with-hotness \
; RUN: | FileCheck %s
;
; Check that passes which preserve BFI don't invalidate the emitter.
; RUN: opt %s -disable-output -aa-pipeline=basic-aa 2>&1 \
; RUN: -passes='require<opt-remark-emit>,instcombine,require<opt-remark-emit>,loop(licm)' -debug-pass-manager \
; RUN: -passes='require<opt-remark-emit>,instcombine,require<opt-remark-emit>,loop-mssa(licm)' -debug-pass-manager \
; RUN: -pass-remarks=licm -pass-remarks-with-hotness \
; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-PM-PRESERVE
;
; Check that invalidating BFI computes a fresh emitter.
; RUN: opt %s -disable-output -aa-pipeline=basic-aa 2>&1 \
; RUN: -passes='require<opt-remark-emit>,invalidate<block-freq>,require<opt-remark-emit>,loop(licm)' -debug-pass-manager \
; RUN: -passes='require<opt-remark-emit>,invalidate<block-freq>,require<opt-remark-emit>,loop-mssa(licm)' -debug-pass-manager \
; RUN: -pass-remarks=licm -pass-remarks-with-hotness \
; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-PM-INVALIDATE
;
; Check that invalidating BFI desn't compute a fresh emitter when we don't
; request hotness remarks.
; RUN: opt %s -disable-output -aa-pipeline=basic-aa 2>&1 \
; RUN: -passes='require<opt-remark-emit>,invalidate<block-freq>,require<opt-remark-emit>,loop(licm)' -debug-pass-manager \
; RUN: -passes='require<opt-remark-emit>,invalidate<block-freq>,require<opt-remark-emit>,loop-mssa(licm)' -debug-pass-manager \
; RUN: -pass-remarks=licm \
; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-PM-NO-INVALIDATE

View File

@ -3,12 +3,12 @@
; RUN: opt < %s -disable-output -passes='default<O2>' -time-passes 2>&1 | FileCheck %s --check-prefix=TIME
;
; For new pass manager, check that -time-passes-per-run emit one report for each pass run.
; RUN: opt < %s -disable-output -passes='instcombine,instcombine,loop(licm)' -time-passes-per-run 2>&1 | FileCheck %s --check-prefix=TIME --check-prefix=TIME-NEW
; RUN: opt < %s -disable-output -passes='instcombine,loop(licm),instcombine,loop(licm)' -time-passes-per-run 2>&1 | FileCheck %s --check-prefix=TIME --check-prefix=TIME-NEW -check-prefix=TIME-DOUBLE-LICM-NEW
; RUN: opt < %s -disable-output -passes='instcombine,instcombine,loop-mssa(licm)' -time-passes-per-run 2>&1 | FileCheck %s --check-prefix=TIME --check-prefix=TIME-NEW
; RUN: opt < %s -disable-output -passes='instcombine,loop-mssa(licm),instcombine,loop-mssa(licm)' -time-passes-per-run 2>&1 | FileCheck %s --check-prefix=TIME --check-prefix=TIME-NEW -check-prefix=TIME-DOUBLE-LICM-NEW
;
; For new pass manager, check that -time-passes emit one report for each pass.
; RUN: opt < %s -disable-output -passes='instcombine,instcombine,loop(licm)' -time-passes 2>&1 | FileCheck %s --check-prefixes=TIME,TIME-NEW-PER-PASS
; RUN: opt < %s -disable-output -passes='instcombine,loop(licm),instcombine,loop(licm)' -time-passes 2>&1 | FileCheck %s --check-prefixes=TIME,TIME-NEW-PER-PASS
; RUN: opt < %s -disable-output -passes='instcombine,instcombine,loop-mssa(licm)' -time-passes 2>&1 | FileCheck %s --check-prefixes=TIME,TIME-NEW-PER-PASS
; RUN: opt < %s -disable-output -passes='instcombine,loop-mssa(licm),instcombine,loop-mssa(licm)' -time-passes 2>&1 | FileCheck %s --check-prefixes=TIME,TIME-NEW-PER-PASS
;
; The following 4 test runs verify -info-output-file interaction (default goes to stderr, '-' goes to stdout).
; RUN: opt -enable-new-pm=0 < %s -disable-output -O2 -time-passes -info-output-file='-' 2>/dev/null | FileCheck %s --check-prefix=TIME

View File

@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -licm -adce -licm -S < %s | FileCheck %s
; RUN: opt -passes='loop(licm),adce,loop(licm)' -S < %s | FileCheck %s
; RUN: opt -passes='loop-mssa(licm),adce,loop-mssa(licm)' -S < %s | FileCheck %s
;
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128-ni:1-p2:32:8:8:32-ni:2"

View File

@ -1,5 +1,5 @@
; RUN: opt -licm -basic-aa < %s -S | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck %s
define void @f_0(i1 %p) nounwind ssp {
; CHECK-LABEL: @f_0(

View File

@ -1,6 +1,5 @@
; RUN: opt < %s -S -basic-aa -licm -enable-new-pm=0 | FileCheck -check-prefixes=CHECK,MSSA %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck -check-prefixes=CHECK,AST %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck -check-prefixes=CHECK,MSSA %s
; RUN: opt < %s -S -basic-aa -licm -enable-new-pm=0 | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck %s
; Check that we can hoist unordered loads
define i32 @test1(i32* nocapture %y) nounwind uwtable ssp {
@ -174,12 +173,10 @@ loop:
end:
ret i32 %vala
; CHECK-LABEL: define i32 @test7b(
; AST-LABEL: entry:
; AST: store i32 5, i32* %x
; CHECK-LABEL: loop:
; CHECK: load atomic i32, i32* %y monotonic
; CHECK-LABEL: end:
; MSSA: store i32 5, i32* %x
; CHECK: store i32 5, i32* %x
; CHECK: store atomic i32 %{{.+}}, i32* %z unordered, align 4
}

View File

@ -1,5 +1,5 @@
; RUN: opt < %s -licm | llvm-dis
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s | llvm-dis
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s | llvm-dis
define void @testfunc(i32 %i) {
; <label>:0

View File

@ -1,5 +1,5 @@
; RUN: opt -S -basic-aa -licm %s | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck %s
declare i32 @load(i32* %p) argmemonly readonly nounwind

View File

@ -1,5 +1,5 @@
; RUN: opt < %s -S -basic-aa -licm | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck %s
; This fixes PR22460
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"

View File

@ -1,5 +1,5 @@
; RUN: opt -licm -disable-output < %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' -disable-output < %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' -disable-output < %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-apple-darwin10.0.0"

View File

@ -1,5 +1,5 @@
; RUN: opt -licm -basic-aa < %s -S | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck %s
define void @dgefa() nounwind ssp {
entry:

View File

@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -make-guards-explicit -basic-aa -licm < %s | FileCheck %s
; RUN: opt -S -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,make-guards-explicit,loop(licm)' < %s | FileCheck %s
; RUN: opt -S -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,make-guards-explicit,loop-mssa(licm)' < %s | FileCheck %s
declare void @llvm.experimental.guard(i1,...)
declare void @maythrow()

View File

@ -1,5 +1,5 @@
; RUN: opt < %s -licm -S | FileCheck %s
; RUN: opt -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s
; RUN: opt -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck %s
; PR19835
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,5 +1,5 @@
; RUN: opt -licm -basic-aa < %s -S | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck %s
define void @test1(i64 %n) {
; CHECK-LABEL: @test1

View File

@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -licm -S | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck %s
target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
target triple = "i386-pc-windows-msvc18.0.0"

View File

@ -1,8 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; REQUIRES: asserts
; RUN: opt -licm -basic-aa -ipt-expensive-asserts=true < %s -S | FileCheck %s --check-prefixes=CHECK,MSSA
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' -ipt-expensive-asserts=true < %s -S | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' -ipt-expensive-asserts=true < %s -S | FileCheck %s --check-prefixes=CHECK,MSSA
; RUN: opt -licm -basic-aa -ipt-expensive-asserts=true < %s -S | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' -ipt-expensive-asserts=true < %s -S | FileCheck %s
; Hoist guard and load.
define void @test1(i1 %cond, i32* %ptr) {
@ -84,17 +83,17 @@ loop:
; But can hoist if the side effect is hoisted with MSSA
define void @test2b_prime(i1 %cond, i32* noalias %ptr) {
; MSSA-LABEL: @test2b_prime(
; MSSA-NEXT: entry:
; MSSA-NEXT: [[P2:%.*]] = getelementptr i32, i32* [[PTR:%.*]], i32 1
; MSSA-NEXT: store i32 0, i32* [[P2]]
; MSSA-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND:%.*]]) [ "deopt"(i32 0) ]
; MSSA-NEXT: [[VAL:%.*]] = load i32, i32* [[PTR]]
; MSSA-NEXT: br label [[LOOP:%.*]]
; MSSA: loop:
; MSSA-NEXT: [[X:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[X_INC:%.*]], [[LOOP]] ]
; MSSA-NEXT: [[X_INC]] = add i32 [[X]], [[VAL]]
; MSSA-NEXT: br label [[LOOP]]
; CHECK-LABEL: @test2b_prime(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, i32* [[PTR:%.*]], i32 1
; CHECK-NEXT: store i32 0, i32* [[P2]]
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND:%.*]]) [ "deopt"(i32 0) ]
; CHECK-NEXT: [[VAL:%.*]] = load i32, i32* [[PTR]]
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[X:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[X_INC:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[X_INC]] = add i32 [[X]], [[VAL]]
; CHECK-NEXT: br label [[LOOP]]
entry:
br label %loop

View File

@ -1,4 +1,4 @@
; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop(loop-simplifycfg,licm)' -S < %s | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop-mssa(loop-simplifycfg,licm)' -S < %s | FileCheck %s
; RUN: opt -S -basic-aa -licm -verify-memoryssa < %s | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"

View File

@ -1,5 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop(loop-simplifycfg,licm)' -S < %s | FileCheck %s
; RUN: opt -S -basic-aa -licm -verify-memoryssa < %s | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop-mssa(loop-simplifycfg,licm)' -verify-memoryssa -S < %s | FileCheck %s

View File

@ -1,6 +1,6 @@
; REQUIRES: asserts
; RUN: opt -S -basic-aa -licm -ipt-expensive-asserts=true < %s | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop(licm)' -ipt-expensive-asserts=true -S %s | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop-mssa(licm)' -ipt-expensive-asserts=true -S %s | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,4 +1,4 @@
; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop(licm)' -S %s | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop-mssa(licm)' -S %s | FileCheck %s
; RUN: opt -S -basic-aa -licm -verify-memoryssa < %s | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,9 +1,7 @@
; RUN: opt -S -licm < %s | FileCheck %s -check-prefixes=CHECK,CHECK-DISABLED
; RUN: opt -S -licm -licm-control-flow-hoisting=1 < %s | FileCheck %s -check-prefixes=CHECK,CHECK-ENABLED
; RUN: opt -S -licm -licm-control-flow-hoisting=0 < %s | FileCheck %s -check-prefixes=CHECK,CHECK-DISABLED
; RUN: opt -passes='require<opt-remark-emit>,loop(licm)' -S < %s | FileCheck %s -check-prefixes=CHECK,CHECK-DISABLED
; RUN: opt -passes='require<opt-remark-emit>,loop(licm)' -licm-control-flow-hoisting=1 -S < %s | FileCheck %s -check-prefixes=CHECK,CHECK-ENABLED
; RUN: opt -passes='require<opt-remark-emit>,loop(licm)' -licm-control-flow-hoisting=0 -S < %s | FileCheck %s -check-prefixes=CHECK,CHECK-DISABLED
; RUN: opt -passes='require<opt-remark-emit>,loop-mssa(licm)' -S < %s | FileCheck %s -check-prefixes=CHECK,CHECK-DISABLED
; RUN: opt -passes='require<opt-remark-emit>,loop-mssa(licm)' -licm-control-flow-hoisting=1 -verify-memoryssa -S < %s | FileCheck %s -check-prefixes=CHECK,CHECK-ENABLED
; Enable run below when adding promotion. e.g. "store i32 %phi, i32* %p" is promoted to phi.lcssa.

View File

@ -1,4 +1,4 @@
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' -S %s | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' -S %s | FileCheck %s
; RUN: opt -S -licm -verify-memoryssa < %s | FileCheck %s
target datalayout = "E-m:e-p:32:32-i8:8:8-i16:16:16-i64:32:32-f64:32:32-v64:32:32-v128:32:32-a0:0:32-n32"

View File

@ -1,4 +1,4 @@
; RUN: opt < %s -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop(licm)' -S | FileCheck %s
; RUN: opt < %s -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop-mssa(licm)' -S | FileCheck %s
; RUN: opt < %s -licm -verify-memoryssa -S | FileCheck %s
@X = global i32 0 ; <i32*> [#uses=1]

View File

@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -basic-aa -licm < %s | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop(licm)' -S %s | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop-mssa(licm)' -S %s | FileCheck %s
; Make sure we don't hoist the unsafe division to some executable block.
define void @test_impossible_exit_in_untaken_block(i32 %a, i32 %b, i32* %p) {

View File

@ -1,5 +1,5 @@
; RUN: opt -S -basic-aa -licm < %s | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' -S %s| FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' -S %s| FileCheck %s
;
; Manually validate LCSSA form is preserved even after SSAUpdater is used to
; promote things in the loop bodies.

View File

@ -1,5 +1,5 @@
; RUN: opt -passes='loop(licm)' -S %s | FileCheck %s --check-prefixes CHECK,LICM
; RUN: opt -passes='loop(lnicm)' -S %s | FileCheck %s --check-prefixes CHECK,LNICM
; RUN: opt -passes='loop-mssa(licm)' -S %s | FileCheck %s --check-prefixes CHECK,LICM
; RUN: opt -passes='loop-mssa(lnicm)' -S %s | FileCheck %s --check-prefixes CHECK,LNICM
; This test represents the following function:
;

View File

@ -1,6 +1,6 @@
; RUN: opt -aa-pipeline=basic-aa -passes='loop(loop-interchange)' -S %s | FileCheck %s --check-prefixes INTC
; RUN: opt -aa-pipeline=basic-aa -passes='loop(lnicm,loop-interchange)' -S %s | FileCheck %s --check-prefixes LNICM,CHECK
; RUN: opt -aa-pipeline=basic-aa -passes='loop(licm,loop-interchange)' -S %s | FileCheck %s --check-prefixes LICM,CHECK
; RUN: opt -aa-pipeline=basic-aa -passes='loop-mssa(lnicm),loop(loop-interchange)' -S %s | FileCheck %s --check-prefixes LNICM,CHECK
; RUN: opt -aa-pipeline=basic-aa -passes='loop-mssa(licm),loop(loop-interchange)' -S %s | FileCheck %s --check-prefixes LICM,CHECK
; This test represents the following function:
; void test(int x[10][10], int y[10], int *z) {

View File

@ -1,6 +1,6 @@
; Test that LICM works when there is not a loop-preheader
; RUN: opt < %s -licm | llvm-dis
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s | llvm-dis
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s | llvm-dis
define void @testfunc(i32 %i.s, i1 %ifcond) {
br i1 %ifcond, label %Then, label %Else

View File

@ -1,5 +1,5 @@
; RUN: opt < %s -licm -pass-remarks-missed=licm -o /dev/null 2>&1 | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' %s -o /dev/null -pass-remarks-missed=licm 2>&1 | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' %s -o /dev/null -pass-remarks-missed=licm 2>&1 | FileCheck %s
target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
; With the load from %p conditional, we can't optmize this and the remark

View File

@ -1,5 +1,5 @@
; RUN: opt < %s -licm -pass-remarks-missed=licm -o /dev/null 2>&1 | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' %s -o /dev/null -pass-remarks-missed=licm 2>&1 | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' %s -o /dev/null -pass-remarks-missed=licm 2>&1 | FileCheck %s
target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
; Without the noalias on %p, we can't optmize this and the remark should tell

View File

@ -1,5 +1,5 @@
; RUN: opt < %s -licm -pass-remarks=licm -o /dev/null 2>&1 | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' %s -o /dev/null -pass-remarks=licm 2>&1 | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' %s -o /dev/null -pass-remarks=licm 2>&1 | FileCheck %s
target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
define void @hoist(i32* %array, i32* noalias %p) {

View File

@ -1,5 +1,5 @@
;RUN: opt -verify-dom-info -loop-simplify -postdomtree -licm -adce -verify-loop-info -S -o - %s | FileCheck %s
;RUN: opt -verify-dom-info -passes='loop-simplify,require<postdomtree>,require<opt-remark-emit>,loop(licm),function(adce)' -S -o - %s | FileCheck %s
;RUN: opt -verify-dom-info -passes='loop-simplify,require<postdomtree>,require<opt-remark-emit>,loop-mssa(licm),function(adce)' -S -o - %s | FileCheck %s
target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,4 +1,4 @@
; RUN: opt -disable-basic-aa -alias-set-saturation-threshold=2 -passes='loop(licm)' -S < %s | FileCheck %s
; RUN: opt -disable-basic-aa -alias-set-saturation-threshold=2 -passes='loop-mssa(licm)' -S < %s | FileCheck %s
; REQUIRES: asserts
; CHECK-LABEL: @f1()

View File

@ -1,5 +1,5 @@
; RUN: opt -S -licm < %s | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' -S %s | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' -S %s | FileCheck %s
declare void @use_nothrow(i64 %a) nounwind
declare void @use(i64 %a)

View File

@ -1,6 +1,5 @@
; RUN: opt -tbaa -basic-aa -licm -enable-new-pm=0 -S < %s | FileCheck %s --check-prefixes=CHECK,MSSA
; RUN: opt -aa-pipeline=tbaa,basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' -S %s | FileCheck %s --check-prefixes=CHECK,AST
; RUN: opt -aa-pipeline=tbaa,basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' -S %s | FileCheck %s --check-prefixes=CHECK,MSSA
; RUN: opt -tbaa -basic-aa -licm -enable-new-pm=0 -S < %s | FileCheck %s
; RUN: opt -aa-pipeline=tbaa,basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' -S %s | FileCheck %s
; LICM should keep the stores in their original order when it sinks/promotes them.
; rdar://12045203
@ -13,9 +12,8 @@ target triple = "x86_64-apple-macosx10.8.0"
define i32* @_Z4doiti(i32 %n, float* %tmp1, i32* %tmp3) nounwind {
; CHECK-LABEL: for.body.lr.ph:
; CHECK: store float 1.000000e+00, float* %tmp1
; AST-LABEL: for.cond.for.end_crit_edge:
; CHECK: store i32 1, i32* %tmp3
; MSSA-LABEL: for.cond.for.end_crit_edge:
; CHECK-LABEL: for.cond.for.end_crit_edge:
entry:
%cmp1 = icmp slt i32 0, %n

View File

@ -1,5 +1,5 @@
; RUN: opt -tbaa -basic-aa -licm -S < %s | FileCheck %s
; RUN: opt -aa-pipeline=tbaa,basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' -S %s | FileCheck %s
; RUN: opt -aa-pipeline=tbaa,basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' -S %s | FileCheck %s
; If we can prove a local is thread local, we can insert stores during
; promotion which wouldn't be legal otherwise.

View File

@ -1,5 +1,5 @@
; RUN: opt < %s -basic-aa -licm -S | FileCheck %s
; RUN: opt -aa-pipeline=tbaa,basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' -S %s | FileCheck %s
; RUN: opt -aa-pipeline=tbaa,basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' -S %s | FileCheck %s
; Make sure we don't hoist a conditionally-executed store out of the loop;
; it would violate the concurrency memory model

View File

@ -1,5 +1,5 @@
; RUN: opt < %s -basic-aa -licm -S | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' -S %s | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' -S %s | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

View File

@ -1,5 +1,5 @@
; RUN: opt < %s -basic-aa -tbaa -licm -S | FileCheck %s
; RUN: opt -aa-pipeline=tbaa,basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' -S %s | FileCheck %s
; RUN: opt -aa-pipeline=tbaa,basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' -S %s | FileCheck %s
target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
@X = global i32 7 ; <i32*> [#uses=4]

View File

@ -1,6 +1,6 @@
; RUN: opt -S -licm -licm-coldness-threshold=0 < %s | FileCheck %s --check-prefix=CHECK-LICM
; RUN: opt -S -licm < %s | opt -S -loop-sink | FileCheck %s --check-prefix=CHECK-SINK
; RUN: opt -S < %s -passes='require<opt-remark-emit>,loop(licm),loop-sink' \
; RUN: opt -S < %s -passes='require<opt-remark-emit>,loop-mssa(licm),loop-sink' \
; RUN: | FileCheck %s --check-prefix=CHECK-SINK
; RUN: opt -S -licm -licm-coldness-threshold=0 -verify-memoryssa < %s | FileCheck %s --check-prefix=CHECK-LICM
; RUN: opt -S -licm -verify-memoryssa < %s | FileCheck %s --check-prefix=CHECK-BFI-LICM

View File

@ -1,5 +1,5 @@
; RUN: opt -S -licm < %s | FileCheck %s
; RUN: opt -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' -S %s | FileCheck %s
; RUN: opt -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' -S %s | FileCheck %s
; UDiv is safe to speculate if the denominator is known non-zero.

View File

@ -1,6 +1,5 @@
; RUN: opt -S -basic-aa -licm %s -enable-new-pm=0 | FileCheck -check-prefixes=CHECK,MSSA %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck -check-prefixes=CHECK,AST %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck -check-prefixes=CHECK,MSSA %s
; RUN: opt -S -basic-aa -licm %s -enable-new-pm=0 | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' < %s -S | FileCheck %s
define void @test(i32* %loc) {
; CHECK-LABEL: @test
@ -47,11 +46,9 @@ exit2:
define i32* @false_negative_2use(i32* %loc) {
; CHECK-LABEL: @false_negative_2use
; AST-LABEL: exit:
; AST: store i32 0, i32* %loc
; MSSA-LABEL: entry:
; MSSA: store i32 0, i32* %loc
; MSSA-LABEL: loop:
; CHECK-LABEL: entry:
; CHECK: store i32 0, i32* %loc
; CHECK-LABEL: loop:
entry:
br label %loop
@ -348,11 +345,9 @@ exit:
; the load must observe.
define i32 @test_dominated_read(i32* %loc) {
; CHECK-LABEL: @test_dominated_read
; MSSA-LABEL: entry:
; MSSA: store i32 0, i32* %loc
; MSSA-LABEL: loop:
; AST-LABEL: exit:
; AST: store i32 0, i32* %loc
; CHECK-LABEL: entry:
; CHECK: store i32 0, i32* %loc
; CHECK-LABEL: loop:
entry:
br label %loop

View File

@ -3,7 +3,7 @@
; alias information for inner loops, and in the new PM it is recomputed for each
; loop.
;
; RUN: opt -S -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop(licm)' < %s | FileCheck %s
; RUN: opt -S -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop-mssa(licm)' < %s | FileCheck %s
; RUN: opt -S -basic-aa -licm < %s | FileCheck %s
define i32 @test(i32* %a, i64 %n.0, i64 %n.0.0, i64 %n.0.0.0, i64 %n.0.0.0.0) nounwind uwtable readonly {

View File

@ -1,6 +1,6 @@
; RUN: opt -S -licm < %s | FileCheck %s --check-prefix=IR-AFTER-TRANSFORM
; RUN: opt -analyze -scalar-evolution -licm -scalar-evolution -enable-new-pm=0 < %s | FileCheck %s --check-prefix=SCEV-EXPRS
; RUN: opt -passes='print<scalar-evolution>,loop(licm),print<scalar-evolution>' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=SCEV-EXPRS
; RUN: opt -passes='print<scalar-evolution>,loop-mssa(licm),print<scalar-evolution>' -disable-output < %s 2>&1 | FileCheck %s --check-prefix=SCEV-EXPRS
declare void @clobber()

View File

@ -1,4 +1,4 @@
; RUN: opt -basic-aa -sroa -loop-rotate %s | opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' -S | FileCheck %s
; RUN: opt -basic-aa -sroa -loop-rotate %s | opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' -S | FileCheck %s
; RUN: opt -basic-aa -sroa -loop-rotate -licm -verify-memoryssa -S < %s | FileCheck %s
; The objects *p and *q are aliased to each other, but even though *q is
; volatile, *p can be considered invariant in the loop. Check if it is moved

View File

@ -1,5 +1,5 @@
; RUN: opt < %s -O1 -S -loop-versioning-licm -licm -debug-only=loop-versioning-licm -enable-new-pm=0 2>&1 | FileCheck %s
; RUN: opt < %s -S -passes='default<O1>,loop-versioning-licm,licm' -debug-only=loop-versioning-licm 2>&1 | FileCheck %s
; RUN: opt < %s -S -passes='default<O1>,function(loop-versioning-licm,loop-mssa(licm))' -debug-only=loop-versioning-licm 2>&1 | FileCheck %s
; REQUIRES: asserts
;
; Test to confirm loop is a candidate for LoopVersioningLICM.

View File

@ -1,5 +1,5 @@
; RUN: opt < %s -O1 -S -loop-versioning-licm -licm -debug-only=loop-versioning-licm -disable-loop-unrolling -enable-new-pm=0 2>&1 | FileCheck %s
; RUN: opt < %s -S -passes='default<O1>,loop-versioning-licm,licm' -debug-only=loop-versioning-licm -disable-loop-unrolling 2>&1 | FileCheck %s
; RUN: opt < %s -S -passes='default<O1>,function(loop-versioning-licm,loop-mssa(licm))' -debug-only=loop-versioning-licm -disable-loop-unrolling 2>&1 | FileCheck %s
; REQUIRES: asserts
;
; Test to confirm loop is a good candidate for LoopVersioningLICM

View File

@ -1,5 +1,5 @@
; RUN: opt < %s -O1 -S -loop-versioning-licm -licm 2>&1 | FileCheck %s
; RUN: opt < %s -S -passes='loop-versioning-licm,licm' 2>&1 | FileCheck %s
; RUN: opt < %s -S -passes='function(loop-versioning-licm,loop-mssa(licm))' 2>&1 | FileCheck %s
; CHECK-LABEL: @without_metadata(
define i32 @without_metadata(i32* nocapture %var1, i32* nocapture readnone %var2, i32* nocapture %var3, i32 %itr) #0 {

View File

@ -32,7 +32,7 @@ TEST(LICMTest, TestSCEVInvalidationOnHoisting) {
PB.registerLoopAnalyses(LAM);
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
StringRef PipelineStr = "require<opt-remark-emit>,loop(licm)";
StringRef PipelineStr = "require<opt-remark-emit>,loop-mssa(licm)";
ASSERT_THAT_ERROR(PB.parsePassPipeline(MPM, PipelineStr), Succeeded());
SMDiagnostic Error;