-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[LoopUnroll] Rotate loop before unrolling inside of UnrollRuntimeLoopRemainder #148243
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
c8bd1d2
cfb1619
b2e1fe6
c9c1bc5
b180cb9
5e41351
ea61d39
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -58,6 +58,7 @@ | |
| #include "llvm/Transforms/Utils/BasicBlockUtils.h" | ||
| #include "llvm/Transforms/Utils/Cloning.h" | ||
| #include "llvm/Transforms/Utils/Local.h" | ||
| #include "llvm/Transforms/Utils/LoopRotationUtils.h" | ||
| #include "llvm/Transforms/Utils/LoopSimplify.h" | ||
| #include "llvm/Transforms/Utils/LoopUtils.h" | ||
| #include "llvm/Transforms/Utils/SimplifyIndVar.h" | ||
|
|
@@ -486,12 +487,7 @@ llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI, | |
|
|
||
| // All these values should be taken only after peeling because they might have | ||
| // changed. | ||
| BasicBlock *Preheader = L->getLoopPreheader(); | ||
| BasicBlock *Header = L->getHeader(); | ||
| BasicBlock *LatchBlock = L->getLoopLatch(); | ||
| SmallVector<BasicBlock *, 4> ExitBlocks; | ||
| L->getExitBlocks(ExitBlocks); | ||
| std::vector<BasicBlock *> OriginalLoopBlocks = L->getBlocks(); | ||
|
|
||
| const unsigned MaxTripCount = SE->getSmallConstantMaxTripCount(L); | ||
| const bool MaxOrZero = SE->isBackedgeTakenCountMaxOrZero(L); | ||
|
|
@@ -504,42 +500,6 @@ llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI, | |
| if (MaxTripCount && ULO.Count > MaxTripCount) | ||
| ULO.Count = MaxTripCount; | ||
|
|
||
| struct ExitInfo { | ||
| unsigned TripCount; | ||
| unsigned TripMultiple; | ||
| unsigned BreakoutTrip; | ||
| bool ExitOnTrue; | ||
| BasicBlock *FirstExitingBlock = nullptr; | ||
| SmallVector<BasicBlock *> ExitingBlocks; | ||
| }; | ||
| DenseMap<BasicBlock *, ExitInfo> ExitInfos; | ||
| SmallVector<BasicBlock *, 4> ExitingBlocks; | ||
| L->getExitingBlocks(ExitingBlocks); | ||
| for (auto *ExitingBlock : ExitingBlocks) { | ||
| // The folding code is not prepared to deal with non-branch instructions | ||
| // right now. | ||
| auto *BI = dyn_cast<BranchInst>(ExitingBlock->getTerminator()); | ||
| if (!BI) | ||
| continue; | ||
|
|
||
| ExitInfo &Info = ExitInfos[ExitingBlock]; | ||
| Info.TripCount = SE->getSmallConstantTripCount(L, ExitingBlock); | ||
| Info.TripMultiple = SE->getSmallConstantTripMultiple(L, ExitingBlock); | ||
| if (Info.TripCount != 0) { | ||
| Info.BreakoutTrip = Info.TripCount % ULO.Count; | ||
| Info.TripMultiple = 0; | ||
| } else { | ||
| Info.BreakoutTrip = Info.TripMultiple = | ||
| (unsigned)std::gcd(ULO.Count, Info.TripMultiple); | ||
| } | ||
| Info.ExitOnTrue = !L->contains(BI->getSuccessor(0)); | ||
| Info.ExitingBlocks.push_back(ExitingBlock); | ||
| LLVM_DEBUG(dbgs() << " Exiting block %" << ExitingBlock->getName() | ||
| << ": TripCount=" << Info.TripCount | ||
| << ", TripMultiple=" << Info.TripMultiple | ||
| << ", BreakoutTrip=" << Info.BreakoutTrip << "\n"); | ||
| } | ||
|
|
||
| // Are we eliminating the loop control altogether? Note that we can know | ||
| // we're eliminating the backedge without knowing exactly which iteration | ||
| // of the unrolled body exits. | ||
|
|
@@ -552,17 +512,6 @@ llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI, | |
| if (CompletelyUnroll) | ||
| ULO.Runtime = false; | ||
|
|
||
| // Go through all exits of L and see if there are any phi-nodes there. We just | ||
| // conservatively assume that they're inserted to preserve LCSSA form, which | ||
| // means that complete unrolling might break this form. We need to either fix | ||
| // it in-place after the transformation, or entirely rebuild LCSSA. TODO: For | ||
| // now we just recompute LCSSA for the outer loop, but it should be possible | ||
| // to fix it in-place. | ||
| bool NeedToFixLCSSA = | ||
| PreserveLCSSA && CompletelyUnroll && | ||
| any_of(ExitBlocks, | ||
| [](const BasicBlock *BB) { return isa<PHINode>(BB->begin()); }); | ||
|
|
||
| // The current loop unroll pass can unroll loops that have | ||
| // (1) single latch; and | ||
| // (2a) latch is unconditional; or | ||
|
|
@@ -587,21 +536,116 @@ llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI, | |
| UnrollRuntimeEpilog.getNumOccurrences() ? UnrollRuntimeEpilog | ||
| : isEpilogProfitable(L); | ||
|
|
||
| if (ULO.Runtime && | ||
| !UnrollRuntimeLoopRemainder(L, ULO.Count, ULO.AllowExpensiveTripCount, | ||
| EpilogProfitability, ULO.UnrollRemainder, | ||
| ULO.ForgetAllSCEV, LI, SE, DT, AC, TTI, | ||
| PreserveLCSSA, ULO.SCEVExpansionBudget, | ||
| ULO.RuntimeUnrollMultiExit, RemainderLoop)) { | ||
| bool LoopRotated = false; | ||
mark-sed marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| bool ReminderUnrolled = false; | ||
| if (ULO.Runtime) { | ||
| // Call unroll with disabled rotation, to see if it is possible without it. | ||
| ReminderUnrolled = UnrollRuntimeLoopRemainder( | ||
| L, ULO.Count, ULO.AllowExpensiveTripCount, EpilogProfitability, | ||
| ULO.UnrollRemainder, ULO.ForgetAllSCEV, LI, SE, DT, AC, TTI, | ||
| PreserveLCSSA, ULO.SCEVExpansionBudget, ULO.RuntimeUnrollMultiExit, | ||
| RemainderLoop); | ||
|
|
||
| // If unroll is not possible, then try with loop rotation. | ||
| if (!ReminderUnrolled) { | ||
| BasicBlock *OrigHeader = L->getHeader(); | ||
| BranchInst *BI = dyn_cast<BranchInst>(OrigHeader->getTerminator()); | ||
| if (BI && !BI->isUnconditional() && | ||
| isa<SCEVCouldNotCompute>(SE->getExitCount(L, L->getLoopLatch())) && | ||
| !isa<SCEVCouldNotCompute>(SE->getExitCount(L, OrigHeader))) { | ||
| LLVM_DEBUG( | ||
| dbgs() << " Rotating loop to make the exit count computable.\n"); | ||
| SimplifyQuery SQ{OrigHeader->getDataLayout()}; | ||
| SQ.TLI = nullptr; | ||
| SQ.DT = DT; | ||
| SQ.AC = AC; | ||
| LoopRotated = | ||
| llvm::LoopRotation(L, LI, TTI, AC, DT, SE, | ||
| /*MemorySSAUpdater*/ nullptr, SQ, | ||
| /*RotationOnly*/ false, /*Threshold*/ 16, | ||
| /*IsUtilMode*/ false, /*PrepareForLTO*/ false, | ||
| [](Loop *, ScalarEvolution *) { return true; }); | ||
|
||
| } | ||
| if (LoopRotated) { | ||
| // Loop was rotated, try unrolling. | ||
| ReminderUnrolled = UnrollRuntimeLoopRemainder( | ||
| L, ULO.Count, ULO.AllowExpensiveTripCount, EpilogProfitability, | ||
| ULO.UnrollRemainder, ULO.ForgetAllSCEV, LI, SE, DT, AC, TTI, | ||
| PreserveLCSSA, ULO.SCEVExpansionBudget, ULO.RuntimeUnrollMultiExit, | ||
| RemainderLoop); | ||
| } | ||
| } | ||
| // Latch block needs to be updated. | ||
| LatchBlock = L->getLoopLatch(); | ||
| LatchIsExiting = L->isLoopExiting(LatchBlock); | ||
| } | ||
|
|
||
| if (ULO.Runtime && !ReminderUnrolled) { | ||
| if (ULO.Force) | ||
| ULO.Runtime = false; | ||
| else { | ||
| LLVM_DEBUG(dbgs() << "Won't unroll; remainder loop could not be " | ||
| "generated when assuming runtime trip count\n"); | ||
| return LoopUnrollResult::Unmodified; | ||
| // Loop might have been rotated inside of UnrollRuntimeLoopRemainder and | ||
| // this needs to be propagated. | ||
| return LoopRotated ? LoopUnrollResult::Modified | ||
| : LoopUnrollResult::Unmodified; | ||
| } | ||
| } | ||
|
|
||
| BasicBlock *Preheader = L->getLoopPreheader(); | ||
| BasicBlock *Header = L->getHeader(); | ||
| SmallVector<BasicBlock *, 4> ExitBlocks; | ||
| L->getExitBlocks(ExitBlocks); | ||
| std::vector<BasicBlock *> OriginalLoopBlocks = L->getBlocks(); | ||
|
|
||
| // Go through all exits of L and see if there are any phi-nodes there. We just | ||
| // conservatively assume that they're inserted to preserve LCSSA form, which | ||
| // means that complete unrolling might break this form. We need to either fix | ||
| // it in-place after the transformation, or entirely rebuild LCSSA. TODO: For | ||
| // now we just recompute LCSSA for the outer loop, but it should be possible | ||
| // to fix it in-place. | ||
| bool NeedToFixLCSSA = | ||
| PreserveLCSSA && CompletelyUnroll && | ||
| any_of(ExitBlocks, | ||
| [](const BasicBlock *BB) { return isa<PHINode>(BB->begin()); }); | ||
|
|
||
| struct ExitInfo { | ||
| unsigned TripCount; | ||
| unsigned TripMultiple; | ||
| unsigned BreakoutTrip; | ||
| bool ExitOnTrue; | ||
| BasicBlock *FirstExitingBlock = nullptr; | ||
| SmallVector<BasicBlock *> ExitingBlocks; | ||
| }; | ||
| DenseMap<BasicBlock *, ExitInfo> ExitInfos; | ||
| SmallVector<BasicBlock *, 4> ExitingBlocks; | ||
| L->getExitingBlocks(ExitingBlocks); | ||
| for (auto *ExitingBlock : ExitingBlocks) { | ||
| // The folding code is not prepared to deal with non-branch instructions | ||
| // right now. | ||
| auto *BI = dyn_cast<BranchInst>(ExitingBlock->getTerminator()); | ||
| if (!BI) | ||
| continue; | ||
|
|
||
| ExitInfo &Info = ExitInfos[ExitingBlock]; | ||
| Info.TripCount = SE->getSmallConstantTripCount(L, ExitingBlock); | ||
| Info.TripMultiple = SE->getSmallConstantTripMultiple(L, ExitingBlock); | ||
| if (Info.TripCount != 0) { | ||
| Info.BreakoutTrip = Info.TripCount % ULO.Count; | ||
| Info.TripMultiple = 0; | ||
| } else { | ||
| Info.BreakoutTrip = Info.TripMultiple = | ||
| (unsigned)std::gcd(ULO.Count, Info.TripMultiple); | ||
| } | ||
| Info.ExitOnTrue = !L->contains(BI->getSuccessor(0)); | ||
| Info.ExitingBlocks.push_back(ExitingBlock); | ||
| LLVM_DEBUG(dbgs() << " Exiting block %" << ExitingBlock->getName() | ||
| << ": TripCount=" << Info.TripCount | ||
| << ", TripMultiple=" << Info.TripMultiple | ||
| << ", BreakoutTrip=" << Info.BreakoutTrip << "\n"); | ||
| } | ||
|
|
||
| using namespace ore; | ||
| // Report the unrolling decision. | ||
| if (CompletelyUnroll) { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.