Revert "Expand existing loopsink testing to also test loopsinking using new pass manager and fix LICM bug."

This reverts commit d4ba28bddc.
This commit is contained in:
Jamie Schmeiser 2020-11-18 15:17:53 -05:00
parent 87369c6261
commit 562addba65
6 changed files with 32 additions and 141 deletions

View File

@ -163,10 +163,8 @@ static bool pointerInvalidatedByLoop(MemoryLocation MemLoc,
AliasSetTracker *CurAST, Loop *CurLoop, AliasSetTracker *CurAST, Loop *CurLoop,
AAResults *AA); AAResults *AA);
static bool pointerInvalidatedByLoopWithMSSA(MemorySSA *MSSA, MemoryUse *MU, static bool pointerInvalidatedByLoopWithMSSA(MemorySSA *MSSA, MemoryUse *MU,
Loop *CurLoop, Instruction &I, Loop *CurLoop,
SinkAndHoistLICMFlags &Flags); SinkAndHoistLICMFlags &Flags);
static bool pointerInvalidatedByBlockWithMSSA(BasicBlock &BB, MemorySSA &MSSA,
MemoryUse &MU);
static Instruction *cloneInstructionInExitBlock( static Instruction *cloneInstructionInExitBlock(
Instruction &I, BasicBlock &ExitBlock, PHINode &PN, const LoopInfo *LI, Instruction &I, BasicBlock &ExitBlock, PHINode &PN, const LoopInfo *LI,
const LoopSafetyInfo *SafetyInfo, MemorySSAUpdater *MSSAU); const LoopSafetyInfo *SafetyInfo, MemorySSAUpdater *MSSAU);
@ -1157,7 +1155,7 @@ bool llvm::canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT,
CurLoop, AA); CurLoop, AA);
else else
Invalidated = pointerInvalidatedByLoopWithMSSA( Invalidated = pointerInvalidatedByLoopWithMSSA(
MSSA, cast<MemoryUse>(MSSA->getMemoryAccess(LI)), CurLoop, I, *Flags); MSSA, cast<MemoryUse>(MSSA->getMemoryAccess(LI)), CurLoop, *Flags);
// Check loop-invariant address because this may also be a sinkable load // Check loop-invariant address because this may also be a sinkable load
// whose address is not necessarily loop-invariant. // whose address is not necessarily loop-invariant.
if (ORE && Invalidated && CurLoop->isLoopInvariant(LI->getPointerOperand())) if (ORE && Invalidated && CurLoop->isLoopInvariant(LI->getPointerOperand()))
@ -1213,7 +1211,7 @@ bool llvm::canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT,
CurAST, CurLoop, AA); CurAST, CurLoop, AA);
else else
Invalidated = pointerInvalidatedByLoopWithMSSA( Invalidated = pointerInvalidatedByLoopWithMSSA(
MSSA, cast<MemoryUse>(MSSA->getMemoryAccess(CI)), CurLoop, I, MSSA, cast<MemoryUse>(MSSA->getMemoryAccess(CI)), CurLoop,
*Flags); *Flags);
if (Invalidated) if (Invalidated)
return false; return false;
@ -1314,6 +1312,7 @@ bool llvm::canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT,
} }
} }
} }
auto *Source = MSSA->getSkipSelfWalker()->getClobberingMemoryAccess(SI); auto *Source = MSSA->getSkipSelfWalker()->getClobberingMemoryAccess(SI);
Flags->incrementClobberingCalls(); Flags->incrementClobberingCalls();
// If there are no clobbering Defs in the loop, store is safe to hoist. // If there are no clobbering Defs in the loop, store is safe to hoist.
@ -2286,7 +2285,7 @@ static bool pointerInvalidatedByLoop(MemoryLocation MemLoc,
} }
bool pointerInvalidatedByLoopWithMSSA(MemorySSA *MSSA, MemoryUse *MU, bool pointerInvalidatedByLoopWithMSSA(MemorySSA *MSSA, MemoryUse *MU,
Loop *CurLoop, Instruction &I, Loop *CurLoop,
SinkAndHoistLICMFlags &Flags) { SinkAndHoistLICMFlags &Flags) {
// For hoisting, use the walker to determine safety // For hoisting, use the walker to determine safety
if (!Flags.getIsSink()) { if (!Flags.getIsSink()) {
@ -2322,22 +2321,12 @@ bool pointerInvalidatedByLoopWithMSSA(MemorySSA *MSSA, MemoryUse *MU,
if (Flags.tooManyMemoryAccesses()) if (Flags.tooManyMemoryAccesses())
return true; return true;
for (auto *BB : CurLoop->getBlocks()) for (auto *BB : CurLoop->getBlocks())
if (pointerInvalidatedByBlockWithMSSA(*BB, *MSSA, *MU)) if (auto *Accesses = MSSA->getBlockDefs(BB))
return true; for (const auto &MA : *Accesses)
// When sinking, the source block may not be part of the loop so check it. if (const auto *MD = dyn_cast<MemoryDef>(&MA))
if (!CurLoop->contains(&I)) if (MU->getBlock() != MD->getBlock() ||
return pointerInvalidatedByBlockWithMSSA(*I.getParent(), *MSSA, *MU); !MSSA->locallyDominates(MD, MU))
return true;
return false;
}
bool pointerInvalidatedByBlockWithMSSA(BasicBlock &BB, MemorySSA &MSSA,
MemoryUse &MU) {
if (const auto *Accesses = MSSA.getBlockDefs(&BB))
for (const auto &MA : *Accesses)
if (const auto *MD = dyn_cast<MemoryDef>(&MA))
if (MU.getBlock() != MD->getBlock() || !MSSA.locallyDominates(MD, &MU))
return true;
return false; return false;
} }

View File

@ -39,8 +39,6 @@
#include "llvm/Analysis/Loads.h" #include "llvm/Analysis/Loads.h"
#include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/MemorySSA.h"
#include "llvm/Analysis/MemorySSAUpdater.h"
#include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
#include "llvm/IR/Dominators.h" #include "llvm/IR/Dominators.h"
@ -69,14 +67,6 @@ static cl::opt<unsigned> MaxNumberOfUseBBsForSinking(
"max-uses-for-sinking", cl::Hidden, cl::init(30), "max-uses-for-sinking", cl::Hidden, cl::init(30),
cl::desc("Do not sink instructions that have too many uses.")); cl::desc("Do not sink instructions that have too many uses."));
static cl::opt<bool> EnableMSSAInLoopSink(
"enable-mssa-in-loop-sink", cl::Hidden, cl::init(false),
cl::desc("Enable MemorySSA for LoopSink in new pass manager"));
static cl::opt<bool> EnableMSSAInLegacyLoopSink(
"enable-mssa-in-legacy-loop-sink", cl::Hidden, cl::init(false),
cl::desc("Enable MemorySSA for LoopSink in legacy pass manager"));
/// Return adjusted total frequency of \p BBs. /// Return adjusted total frequency of \p BBs.
/// ///
/// * If there is only one BB, sinking instruction will not introduce code /// * If there is only one BB, sinking instruction will not introduce code
@ -182,10 +172,11 @@ findBBsToSinkInto(const Loop &L, const SmallPtrSetImpl<BasicBlock *> &UseBBs,
// sinking is successful. // sinking is successful.
// \p LoopBlockNumber is used to sort the insertion blocks to ensure // \p LoopBlockNumber is used to sort the insertion blocks to ensure
// determinism. // determinism.
static bool sinkInstruction( static bool sinkInstruction(Loop &L, Instruction &I,
Loop &L, Instruction &I, const SmallVectorImpl<BasicBlock *> &ColdLoopBBs, const SmallVectorImpl<BasicBlock *> &ColdLoopBBs,
const SmallDenseMap<BasicBlock *, int, 16> &LoopBlockNumber, LoopInfo &LI, const SmallDenseMap<BasicBlock *, int, 16> &LoopBlockNumber,
DominatorTree &DT, BlockFrequencyInfo &BFI, MemorySSAUpdater *MSSAU) { LoopInfo &LI, DominatorTree &DT,
BlockFrequencyInfo &BFI) {
// Compute the set of blocks in loop L which contain a use of I. // Compute the set of blocks in loop L which contain a use of I.
SmallPtrSet<BasicBlock *, 2> BBs; SmallPtrSet<BasicBlock *, 2> BBs;
for (auto &U : I.uses()) { for (auto &U : I.uses()) {
@ -239,21 +230,6 @@ static bool sinkInstruction(
Instruction *IC = I.clone(); Instruction *IC = I.clone();
IC->setName(I.getName()); IC->setName(I.getName());
IC->insertBefore(&*N->getFirstInsertionPt()); IC->insertBefore(&*N->getFirstInsertionPt());
if (MSSAU && MSSAU->getMemorySSA()->getMemoryAccess(&I)) {
// Create a new MemoryAccess and let MemorySSA set its defining access.
MemoryAccess *NewMemAcc =
MSSAU->createMemoryAccessInBB(IC, nullptr, N, MemorySSA::Beginning);
if (NewMemAcc) {
if (auto *MemDef = dyn_cast<MemoryDef>(NewMemAcc))
MSSAU->insertDef(MemDef, /*RenameUses=*/true);
else {
auto *MemUse = cast<MemoryUse>(NewMemAcc);
MSSAU->insertUse(MemUse, /*RenameUses=*/true);
}
}
}
// Replaces uses of I with IC in N // Replaces uses of I with IC in N
I.replaceUsesWithIf(IC, [N](Use &U) { I.replaceUsesWithIf(IC, [N](Use &U) {
return cast<Instruction>(U.getUser())->getParent() == N; return cast<Instruction>(U.getUser())->getParent() == N;
@ -268,11 +244,6 @@ static bool sinkInstruction(
NumLoopSunk++; NumLoopSunk++;
I.moveBefore(&*MoveBB->getFirstInsertionPt()); I.moveBefore(&*MoveBB->getFirstInsertionPt());
if (MSSAU)
if (MemoryUseOrDef *OldMemAcc = cast_or_null<MemoryUseOrDef>(
MSSAU->getMemorySSA()->getMemoryAccess(&I)))
MSSAU->moveToPlace(OldMemAcc, MoveBB, MemorySSA::Beginning);
return true; return true;
} }
@ -281,11 +252,10 @@ static bool sinkInstruction(
static bool sinkLoopInvariantInstructions(Loop &L, AAResults &AA, LoopInfo &LI, static bool sinkLoopInvariantInstructions(Loop &L, AAResults &AA, LoopInfo &LI,
DominatorTree &DT, DominatorTree &DT,
BlockFrequencyInfo &BFI, BlockFrequencyInfo &BFI,
ScalarEvolution *SE, ScalarEvolution *SE) {
AliasSetTracker *CurAST,
MemorySSA *MSSA) {
BasicBlock *Preheader = L.getLoopPreheader(); BasicBlock *Preheader = L.getLoopPreheader();
assert(Preheader && "Expected loop to have preheader"); if (!Preheader)
return false;
// Enable LoopSink only when runtime profile is available. // Enable LoopSink only when runtime profile is available.
// With static profile, the sinking decision may be sub-optimal. // With static profile, the sinking decision may be sub-optimal.
@ -301,15 +271,13 @@ static bool sinkLoopInvariantInstructions(Loop &L, AAResults &AA, LoopInfo &LI,
})) }))
return false; return false;
std::unique_ptr<MemorySSAUpdater> MSSAU;
std::unique_ptr<SinkAndHoistLICMFlags> LICMFlags;
if (MSSA) {
MSSAU = std::make_unique<MemorySSAUpdater>(MSSA);
LICMFlags =
std::make_unique<SinkAndHoistLICMFlags>(/*IsSink=*/true, &L, MSSA);
}
bool Changed = false; bool Changed = false;
AliasSetTracker CurAST(AA);
// Compute alias set.
for (BasicBlock *BB : L.blocks())
CurAST.add(*BB);
CurAST.add(*Preheader);
// Sort loop's basic blocks by frequency // Sort loop's basic blocks by frequency
SmallVector<BasicBlock *, 10> ColdLoopBBs; SmallVector<BasicBlock *, 10> ColdLoopBBs;
@ -332,11 +300,9 @@ static bool sinkLoopInvariantInstructions(Loop &L, AAResults &AA, LoopInfo &LI,
// No need to check for instruction's operands are loop invariant. // No need to check for instruction's operands are loop invariant.
assert(L.hasLoopInvariantOperands(I) && assert(L.hasLoopInvariantOperands(I) &&
"Insts in a loop's preheader should have loop invariant operands!"); "Insts in a loop's preheader should have loop invariant operands!");
if (!canSinkOrHoistInst(*I, &AA, &DT, &L, CurAST, MSSAU.get(), false, if (!canSinkOrHoistInst(*I, &AA, &DT, &L, &CurAST, nullptr, false))
LICMFlags.get()))
continue; continue;
if (sinkInstruction(L, *I, ColdLoopBBs, LoopBlockNumber, LI, DT, BFI, if (sinkInstruction(L, *I, ColdLoopBBs, LoopBlockNumber, LI, DT, BFI))
MSSAU.get()))
Changed = true; Changed = true;
} }
@ -345,13 +311,6 @@ static bool sinkLoopInvariantInstructions(Loop &L, AAResults &AA, LoopInfo &LI,
return Changed; return Changed;
} }
static void computeAliasSet(Loop &L, BasicBlock &Preheader,
AliasSetTracker &CurAST) {
for (BasicBlock *BB : L.blocks())
CurAST.add(*BB);
CurAST.add(Preheader);
}
PreservedAnalyses LoopSinkPass::run(Function &F, FunctionAnalysisManager &FAM) { PreservedAnalyses LoopSinkPass::run(Function &F, FunctionAnalysisManager &FAM) {
LoopInfo &LI = FAM.getResult<LoopAnalysis>(F); LoopInfo &LI = FAM.getResult<LoopAnalysis>(F);
// Nothing to do if there are no loops. // Nothing to do if there are no loops.
@ -362,10 +321,6 @@ PreservedAnalyses LoopSinkPass::run(Function &F, FunctionAnalysisManager &FAM) {
DominatorTree &DT = FAM.getResult<DominatorTreeAnalysis>(F); DominatorTree &DT = FAM.getResult<DominatorTreeAnalysis>(F);
BlockFrequencyInfo &BFI = FAM.getResult<BlockFrequencyAnalysis>(F); BlockFrequencyInfo &BFI = FAM.getResult<BlockFrequencyAnalysis>(F);
MemorySSA *MSSA = EnableMSSAInLoopSink
? &FAM.getResult<MemorySSAAnalysis>(F).getMSSA()
: nullptr;
// We want to do a postorder walk over the loops. Since loops are a tree this // We want to do a postorder walk over the loops. Since loops are a tree this
// is equivalent to a reversed preorder walk and preorder is easy to compute // is equivalent to a reversed preorder walk and preorder is easy to compute
// without recursion. Since we reverse the preorder, we will visit siblings // without recursion. Since we reverse the preorder, we will visit siblings
@ -377,22 +332,11 @@ PreservedAnalyses LoopSinkPass::run(Function &F, FunctionAnalysisManager &FAM) {
do { do {
Loop &L = *PreorderLoops.pop_back_val(); Loop &L = *PreorderLoops.pop_back_val();
BasicBlock *Preheader = L.getLoopPreheader();
if (!Preheader)
continue;
std::unique_ptr<AliasSetTracker> CurAST;
if (!EnableMSSAInLoopSink) {
CurAST = std::make_unique<AliasSetTracker>(AA);
computeAliasSet(L, *Preheader, *CurAST.get());
}
// Note that we don't pass SCEV here because it is only used to invalidate // Note that we don't pass SCEV here because it is only used to invalidate
// loops in SCEV and we don't preserve (or request) SCEV at all making that // loops in SCEV and we don't preserve (or request) SCEV at all making that
// unnecessary. // unnecessary.
Changed |= sinkLoopInvariantInstructions(L, AA, LI, DT, BFI, Changed |= sinkLoopInvariantInstructions(L, AA, LI, DT, BFI,
/*ScalarEvolution*/ nullptr, /*ScalarEvolution*/ nullptr);
CurAST.get(), MSSA);
} while (!PreorderLoops.empty()); } while (!PreorderLoops.empty());
if (!Changed) if (!Changed)
@ -400,14 +344,6 @@ PreservedAnalyses LoopSinkPass::run(Function &F, FunctionAnalysisManager &FAM) {
PreservedAnalyses PA; PreservedAnalyses PA;
PA.preserveSet<CFGAnalyses>(); PA.preserveSet<CFGAnalyses>();
if (MSSA) {
PA.preserve<MemorySSAAnalysis>();
if (VerifyMemorySSA)
MSSA->verifyMemorySSA();
}
return PA; return PA;
} }
@ -422,41 +358,19 @@ struct LegacyLoopSinkPass : public LoopPass {
if (skipLoop(L)) if (skipLoop(L))
return false; return false;
BasicBlock *Preheader = L->getLoopPreheader();
if (!Preheader)
return false;
AAResults &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
auto *SE = getAnalysisIfAvailable<ScalarEvolutionWrapperPass>(); auto *SE = getAnalysisIfAvailable<ScalarEvolutionWrapperPass>();
std::unique_ptr<AliasSetTracker> CurAST; return sinkLoopInvariantInstructions(
MemorySSA *MSSA = nullptr; *L, getAnalysis<AAResultsWrapperPass>().getAAResults(),
if (EnableMSSAInLegacyLoopSink) getAnalysis<LoopInfoWrapperPass>().getLoopInfo(),
MSSA = &getAnalysis<MemorySSAWrapperPass>().getMSSA();
else {
CurAST = std::make_unique<AliasSetTracker>(AA);
computeAliasSet(*L, *Preheader, *CurAST.get());
}
bool Changed = sinkLoopInvariantInstructions(
*L, AA, getAnalysis<LoopInfoWrapperPass>().getLoopInfo(),
getAnalysis<DominatorTreeWrapperPass>().getDomTree(), getAnalysis<DominatorTreeWrapperPass>().getDomTree(),
getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI(), getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI(),
SE ? &SE->getSE() : nullptr, CurAST.get(), MSSA); SE ? &SE->getSE() : nullptr);
if (MSSA && VerifyMemorySSA)
MSSA->verifyMemorySSA();
return Changed;
} }
void getAnalysisUsage(AnalysisUsage &AU) const override { void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesCFG(); AU.setPreservesCFG();
AU.addRequired<BlockFrequencyInfoWrapperPass>(); AU.addRequired<BlockFrequencyInfoWrapperPass>();
getLoopAnalysisUsage(AU); getLoopAnalysisUsage(AU);
if (EnableMSSAInLegacyLoopSink) {
AU.addRequired<MemorySSAWrapperPass>();
AU.addPreserved<MemorySSAWrapperPass>();
}
} }
}; };
} }
@ -466,7 +380,6 @@ INITIALIZE_PASS_BEGIN(LegacyLoopSinkPass, "loop-sink", "Loop Sink", false,
false) false)
INITIALIZE_PASS_DEPENDENCY(LoopPass) INITIALIZE_PASS_DEPENDENCY(LoopPass)
INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass) INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MemorySSAWrapperPass)
INITIALIZE_PASS_END(LegacyLoopSinkPass, "loop-sink", "Loop Sink", false, false) INITIALIZE_PASS_END(LegacyLoopSinkPass, "loop-sink", "Loop Sink", false, false)
Pass *llvm::createLoopSinkPass() { return new LegacyLoopSinkPass(); } Pass *llvm::createLoopSinkPass() { return new LegacyLoopSinkPass(); }

View File

@ -1,7 +1,4 @@
; RUN: opt -S -loop-sink < %s | FileCheck %s ; RUN: opt -S -loop-sink < %s | FileCheck %s
; RUN: opt -S -verify-memoryssa -enable-mssa-in-legacy-loop-sink -loop-sink < %s | FileCheck %s
; RUN: opt -S -aa-pipeline=basic-aa -passes=loop-sink < %s | FileCheck %s
; RUN: opt -S -verify-memoryssa -enable-mssa-in-loop-sink -aa-pipeline=basic-aa -passes=loop-sink < %s | FileCheck %s
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc19.13.26128" target triple = "x86_64-pc-windows-msvc19.13.26128"

View File

@ -1,7 +1,4 @@
; RUN: opt -S -loop-sink < %s | FileCheck %s ; RUN: opt -S -loop-sink < %s | FileCheck %s
; RUN: opt -S -verify-memoryssa -enable-mssa-in-legacy-loop-sink -loop-sink < %s | FileCheck %s
; RUN: opt -S -aa-pipeline=basic-aa -passes=loop-sink < %s | FileCheck %s
; RUN: opt -S -verify-memoryssa -enable-mssa-in-loop-sink -aa-pipeline=basic-aa -passes=loop-sink < %s | FileCheck %s
; CHECK: pr39570 ; CHECK: pr39570
; Make sure not to assert. ; Make sure not to assert.

View File

@ -1,7 +1,4 @@
; RUN: opt -S -loop-sink < %s | FileCheck %s ; RUN: opt -S -loop-sink < %s | FileCheck %s
; RUN: opt -S -verify-memoryssa -enable-mssa-in-legacy-loop-sink -loop-sink < %s | FileCheck %s
; RUN: opt -S -aa-pipeline=basic-aa -passes=loop-sink < %s | FileCheck %s
; RUN: opt -S -verify-memoryssa -enable-mssa-in-loop-sink -aa-pipeline=basic-aa -passes=loop-sink < %s | FileCheck %s
; The load instruction should not be sunk into following loop. ; The load instruction should not be sunk into following loop.
; CHECK: @foo ; CHECK: @foo

View File

@ -1,7 +1,5 @@
; RUN: opt -S -loop-sink < %s | FileCheck %s ; RUN: opt -S -loop-sink < %s | FileCheck %s
; RUN: opt -S -verify-memoryssa -enable-mssa-in-legacy-loop-sink -loop-sink < %s | FileCheck %s
; RUN: opt -S -aa-pipeline=basic-aa -passes=loop-sink < %s | FileCheck %s ; RUN: opt -S -aa-pipeline=basic-aa -passes=loop-sink < %s | FileCheck %s
; RUN: opt -S -verify-memoryssa -enable-mssa-in-loop-sink -aa-pipeline=basic-aa -passes=loop-sink < %s | FileCheck %s
@g = global i32 0, align 4 @g = global i32 0, align 4