diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2021-06-13 19:31:46 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2021-06-13 19:37:19 +0000 |
commit | e8d8bef961a50d4dc22501cde4fb9fb0be1b2532 (patch) | |
tree | 94f04805f47bb7c59ae29690d8952b6074fff602 /contrib/llvm-project/llvm/lib/Transforms/Scalar/LoopInterchange.cpp | |
parent | bb130ff39747b94592cb26d71b7cb097b9a4ea6b (diff) | |
parent | b60736ec1405bb0a8dd40989f67ef4c93da068ab (diff) |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Transforms/Scalar/LoopInterchange.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Transforms/Scalar/LoopInterchange.cpp | 135 |
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(); +} |