aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-06-13 19:31:46 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-06-13 19:37:19 +0000
commite8d8bef961a50d4dc22501cde4fb9fb0be1b2532 (patch)
tree94f04805f47bb7c59ae29690d8952b6074fff602 /contrib/llvm-project/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
parentbb130ff39747b94592cb26d71b7cb097b9a4ea6b (diff)
parentb60736ec1405bb0a8dd40989f67ef4c93da068ab (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Transforms/Scalar/LoopInterchange.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Transforms/Scalar/LoopInterchange.cpp135
1 files changed, 102 insertions, 33 deletions
diff --git a/contrib/llvm-project/llvm/lib/Transforms/Scalar/LoopInterchange.cpp b/contrib/llvm-project/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
index 7787c0bccd4c..d9dbc0deb42a 100644
--- a/contrib/llvm-project/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
+++ b/contrib/llvm-project/llvm/lib/Transforms/Scalar/LoopInterchange.cpp
@@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/Transforms/Scalar/LoopInterchange.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
@@ -27,6 +28,7 @@
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
@@ -427,9 +429,7 @@ private:
const LoopInterchangeLegality &LIL;
};
-// Main LoopInterchange Pass.
-struct LoopInterchange : public LoopPass {
- static char ID;
+struct LoopInterchange {
ScalarEvolution *SE = nullptr;
LoopInfo *LI = nullptr;
DependenceInfo *DI = nullptr;
@@ -438,34 +438,21 @@ struct LoopInterchange : public LoopPass {
/// Interface to emit optimization remarks.
OptimizationRemarkEmitter *ORE;
- LoopInterchange() : LoopPass(ID) {
- initializeLoopInterchangePass(*PassRegistry::getPassRegistry());
- }
-
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.addRequired<DependenceAnalysisWrapperPass>();
- AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
+ LoopInterchange(ScalarEvolution *SE, LoopInfo *LI, DependenceInfo *DI,
+ DominatorTree *DT, OptimizationRemarkEmitter *ORE)
+ : SE(SE), LI(LI), DI(DI), DT(DT), ORE(ORE) {}
- getLoopAnalysisUsage(AU);
- }
-
- bool runOnLoop(Loop *L, LPPassManager &LPM) override {
- if (skipLoop(L) || L->getParentLoop())
+ bool run(Loop *L) {
+ if (L->getParentLoop())
return false;
- SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
- LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
- DI = &getAnalysis<DependenceAnalysisWrapperPass>().getDI();
- DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
- ORE = &getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
-
return processLoopList(populateWorklist(*L));
}
bool isComputableLoopNest(LoopVector LoopList) {
for (Loop *L : LoopList) {
const SCEV *ExitCountOuter = SE->getBackedgeTakenCount(L);
- if (ExitCountOuter == SE->getCouldNotCompute()) {
+ if (isa<SCEVCouldNotCompute>(ExitCountOuter)) {
LLVM_DEBUG(dbgs() << "Couldn't compute backedge count\n");
return false;
}
@@ -624,6 +611,13 @@ bool LoopInterchangeLegality::tightlyNested(Loop *OuterLoop, Loop *InnerLoop) {
containsUnsafeInstructions(OuterLoopLatch))
return false;
+ // Also make sure the inner loop preheader does not contain any unsafe
+ // instructions. Note that all instructions in the preheader will be moved to
+ // the outer loop header when interchanging.
+ if (InnerLoopPreHeader != OuterLoopHeader &&
+ containsUnsafeInstructions(InnerLoopPreHeader))
+ return false;
+
LLVM_DEBUG(dbgs() << "Loops are perfectly nested\n");
// We have a perfect loop nest.
return true;
@@ -667,6 +661,10 @@ static Value *followLCSSA(Value *SV) {
// Check V's users to see if it is involved in a reduction in L.
static PHINode *findInnerReductionPhi(Loop *L, Value *V) {
+ // Reduction variables cannot be constants.
+ if (isa<Constant>(V))
+ return nullptr;
+
for (Value *User : V->users()) {
if (PHINode *PHI = dyn_cast<PHINode>(User)) {
if (PHI->getNumIncomingValues() == 1)
@@ -707,8 +705,7 @@ bool LoopInterchangeLegality::findInductionAndReductions(
Value *V = followLCSSA(PHI.getIncomingValueForBlock(L->getLoopLatch()));
PHINode *InnerRedPhi = findInnerReductionPhi(InnerLoop, V);
if (!InnerRedPhi ||
- !llvm::any_of(InnerRedPhi->incoming_values(),
- [&PHI](Value *V) { return V == &PHI; })) {
+ !llvm::is_contained(InnerRedPhi->incoming_values(), &PHI)) {
LLVM_DEBUG(
dbgs()
<< "Failed to recognize PHI as an induction or reduction.\n");
@@ -1045,6 +1042,10 @@ int LoopInterchangeProfitability::getInstrOrderCost() {
bool FoundInnerInduction = false;
bool FoundOuterInduction = false;
for (unsigned i = 0; i < NumOp; ++i) {
+ // Skip operands that are not SCEV-able.
+ if (!SE->isSCEVable(GEP->getOperand(i)->getType()))
+ continue;
+
const SCEV *OperandVal = SE->getSCEV(GEP->getOperand(i));
const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(OperandVal);
if (!AR)
@@ -1189,7 +1190,7 @@ void LoopInterchangeTransform::restructureLoops(
removeChildLoop(NewInner, NewOuter);
LI->changeTopLevelLoop(NewInner, NewOuter);
}
- while (!NewOuter->empty())
+ while (!NewOuter->isInnermost())
NewInner->addChildLoop(NewOuter->removeChildLoop(NewOuter->begin()));
NewOuter->addChildLoop(NewInner);
@@ -1305,6 +1306,21 @@ bool LoopInterchangeTransform::transform() {
LLVM_DEBUG(dbgs() << "splitting InnerLoopHeader done\n");
}
+ // Instructions in the original inner loop preheader may depend on values
+ // defined in the outer loop header. Move them there, because the original
+ // inner loop preheader will become the entry into the interchanged loop nest.
+ // Currently we move all instructions and rely on LICM to move invariant
+ // instructions outside the loop nest.
+ BasicBlock *InnerLoopPreHeader = InnerLoop->getLoopPreheader();
+ BasicBlock *OuterLoopHeader = OuterLoop->getHeader();
+ if (InnerLoopPreHeader != OuterLoopHeader) {
+ SmallPtrSet<Instruction *, 4> NeedsMoving;
+ for (Instruction &I :
+ make_early_inc_range(make_range(InnerLoopPreHeader->begin(),
+ std::prev(InnerLoopPreHeader->end()))))
+ I.moveBefore(OuterLoopHeader->getTerminator());
+ }
+
Transformed |= adjustLoopLinks();
if (!Transformed) {
LLVM_DEBUG(dbgs() << "adjustLoopLinks failed\n");
@@ -1521,8 +1537,7 @@ bool LoopInterchangeTransform::adjustLoopBranches() {
InnerLoopPreHeader, DTUpdates, /*MustUpdateOnce=*/false);
// The outer loop header might or might not branch to the outer latch.
// We are guaranteed to branch to the inner loop preheader.
- if (std::find(succ_begin(OuterLoopHeaderBI), succ_end(OuterLoopHeaderBI),
- OuterLoopLatch) != succ_end(OuterLoopHeaderBI))
+ if (llvm::is_contained(OuterLoopHeaderBI->successors(), OuterLoopLatch))
updateSuccessor(OuterLoopHeaderBI, OuterLoopLatch, LoopExit, DTUpdates,
/*MustUpdateOnce=*/false);
updateSuccessor(OuterLoopHeaderBI, InnerLoopPreHeader,
@@ -1569,9 +1584,9 @@ bool LoopInterchangeTransform::adjustLoopBranches() {
// Now update the reduction PHIs in the inner and outer loop headers.
SmallVector<PHINode *, 4> InnerLoopPHIs, OuterLoopPHIs;
- for (PHINode &PHI : drop_begin(InnerLoopHeader->phis(), 1))
+ for (PHINode &PHI : drop_begin(InnerLoopHeader->phis()))
InnerLoopPHIs.push_back(cast<PHINode>(&PHI));
- for (PHINode &PHI : drop_begin(OuterLoopHeader->phis(), 1))
+ for (PHINode &PHI : drop_begin(OuterLoopHeader->phis()))
OuterLoopPHIs.push_back(cast<PHINode>(&PHI));
auto &OuterInnerReductions = LIL.getOuterInnerReductions();
@@ -1595,6 +1610,17 @@ bool LoopInterchangeTransform::adjustLoopBranches() {
InnerLoopHeader->replacePhiUsesWith(OuterLoopPreHeader, InnerLoopPreHeader);
InnerLoopHeader->replacePhiUsesWith(OuterLoopLatch, InnerLoopLatch);
+ // Values defined in the outer loop header could be used in the inner loop
+ // latch. In that case, we need to create LCSSA phis for them, because after
+ // interchanging they will be defined in the new inner loop and used in the
+ // new outer loop.
+ IRBuilder<> Builder(OuterLoopHeader->getContext());
+ SmallVector<Instruction *, 4> MayNeedLCSSAPhis;
+ for (Instruction &I :
+ make_range(OuterLoopHeader->begin(), std::prev(OuterLoopHeader->end())))
+ MayNeedLCSSAPhis.push_back(&I);
+ formLCSSAForInstructions(MayNeedLCSSAPhis, *DT, *LI, SE, Builder);
+
return true;
}
@@ -1612,15 +1638,58 @@ bool LoopInterchangeTransform::adjustLoopLinks() {
return Changed;
}
-char LoopInterchange::ID = 0;
+/// Main LoopInterchange Pass.
+struct LoopInterchangeLegacyPass : public LoopPass {
+ static char ID;
+
+ LoopInterchangeLegacyPass() : LoopPass(ID) {
+ initializeLoopInterchangeLegacyPassPass(*PassRegistry::getPassRegistry());
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequired<DependenceAnalysisWrapperPass>();
+ AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
+
+ getLoopAnalysisUsage(AU);
+ }
+
+ bool runOnLoop(Loop *L, LPPassManager &LPM) override {
+ if (skipLoop(L))
+ return false;
+
+ auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
+ auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
+ auto *DI = &getAnalysis<DependenceAnalysisWrapperPass>().getDI();
+ auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
+ auto *ORE = &getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
+
+ return LoopInterchange(SE, LI, DI, DT, ORE).run(L);
+ }
+};
-INITIALIZE_PASS_BEGIN(LoopInterchange, "loop-interchange",
+char LoopInterchangeLegacyPass::ID = 0;
+
+INITIALIZE_PASS_BEGIN(LoopInterchangeLegacyPass, "loop-interchange",
"Interchanges loops for cache reuse", false, false)
INITIALIZE_PASS_DEPENDENCY(LoopPass)
INITIALIZE_PASS_DEPENDENCY(DependenceAnalysisWrapperPass)
INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass)
-INITIALIZE_PASS_END(LoopInterchange, "loop-interchange",
+INITIALIZE_PASS_END(LoopInterchangeLegacyPass, "loop-interchange",
"Interchanges loops for cache reuse", false, false)
-Pass *llvm::createLoopInterchangePass() { return new LoopInterchange(); }
+Pass *llvm::createLoopInterchangePass() {
+ return new LoopInterchangeLegacyPass();
+}
+
+PreservedAnalyses LoopInterchangePass::run(Loop &L, LoopAnalysisManager &AM,
+ LoopStandardAnalysisResults &AR,
+ LPMUpdater &U) {
+ Function &F = *L.getHeader()->getParent();
+
+ DependenceInfo DI(&F, &AR.AA, &AR.SE, &AR.LI);
+ OptimizationRemarkEmitter ORE(&F);
+ if (!LoopInterchange(&AR.SE, &AR.LI, &DI, &AR.DT, &ORE).run(&L))
+ return PreservedAnalyses::all();
+ return getLoopPassPreservedAnalyses();
+}