diff options
author | Philip Reames <listmail@philipreames.com> | 2021-08-17 17:50:58 -0700 |
---|---|---|
committer | Philip Reames <listmail@philipreames.com> | 2021-08-17 17:52:04 -0700 |
commit | 94d091429253e46e4cdd31a30e4d1b25b2879d6a (patch) | |
tree | 9069ec1933b78a8b088de67696bf541fe1f06770 /llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp | |
parent | b26e1efc424ad840143f02a96246cc666ee99e72 (diff) | |
download | llvm-94d091429253e46e4cdd31a30e4d1b25b2879d6a.zip llvm-94d091429253e46e4cdd31a30e4d1b25b2879d6a.tar.gz llvm-94d091429253e46e4cdd31a30e4d1b25b2879d6a.tar.bz2 |
[runtimeunroll] Support multiple exits to latch exit w/epilogue loop
This patch extends the runtime unrolling infrastructure to support unrolling a loop with multiple exiting blocks branching to the same exit block used by the latch. It intentionally does not include a cost model change to enable this functionality unless appropriate force flags are used.
I decided to restrict this to the epilogue case. Given the changes ended up being pretty generic, we may be able to unblock the prolog case too, but I want to do that in a separate change to reduce the amount of code we all have to understand at one time.
Differential Revision: https://reviews.llvm.org/D107381
Diffstat (limited to 'llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp b/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp index 51b4a4e..0bad348 100644 --- a/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp +++ b/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp @@ -215,7 +215,10 @@ static void ConnectEpilog(Loop *L, Value *ModVal, BasicBlock *NewExit, // PN = PHI [I, Latch] // ... // Exit: - // EpilogPN = PHI [PN, EpilogPreHeader] + // EpilogPN = PHI [PN, EpilogPreHeader], [X, Exit2], [Y, Exit2.epil] + // + // Exits from non-latch blocks point to the original exit block and the + // epilogue edges have already been added. // // There is EpilogPreHeader incoming block instead of NewExit as // NewExit was spilt 1 more time to get EpilogPreHeader. @@ -441,9 +444,8 @@ static bool canSafelyUnrollMultiExitLoop(Loop *L, BasicBlock *LatchExit, return false; // TODO: Support multiple exiting blocks jumping to the `LatchExit` when - // UnrollRuntimeMultiExit is true. This will need updating the logic in - // connectEpilog/connectProlog. - if (!LatchExit->getSinglePredecessor()) { + // using a prolog loop. + if (!UseEpilogRemainder && !LatchExit->getSinglePredecessor()) { LLVM_DEBUG( dbgs() << "Bailout for multi-exit handling when latch exit has >1 " "predecessor.\n"); @@ -477,6 +479,11 @@ static bool canProfitablyUnrollMultiExitLoop( if (UnrollRuntimeMultiExit.getNumOccurrences()) return UnrollRuntimeMultiExit; + // TODO: We used to bail out for correctness (now fixed). Under what + // circumstances is this case profitable to allow? + if (!LatchExit->getSinglePredecessor()) + return false; + // The main pain point with multi-exit loop unrolling is that once unrolled, // we will not be able to merge all blocks into a straight line code. // There are branches within the unrolled loop that go to the OtherExits. @@ -740,8 +747,7 @@ bool llvm::UnrollRuntimeLoopRemainder( NewPreHeader = SplitBlock(PreHeader, PreHeader->getTerminator(), DT, LI); NewPreHeader->setName(PreHeader->getName() + ".new"); // Split LatchExit to create phi nodes from branch above. - SmallVector<BasicBlock*, 4> Preds(predecessors(LatchExit)); - NewExit = SplitBlockPredecessors(LatchExit, Preds, ".unr-lcssa", DT, LI, + NewExit = SplitBlockPredecessors(LatchExit, {Latch}, ".unr-lcssa", DT, LI, nullptr, PreserveLCSSA); // NewExit gets its DebugLoc from LatchExit, which is not part of the // original Loop. @@ -856,6 +862,14 @@ bool llvm::UnrollRuntimeLoopRemainder( // node. for (unsigned i = 0; i < oldNumOperands; i++){ auto *PredBB =PN.getIncomingBlock(i); + if (PredBB == Latch) + // The latch exit is handled seperately, see connectX + continue; + if (!L->contains(PredBB)) + // Even if we had dedicated exits, the code above inserted an + // extra branch which can reach the latch exit. + continue; + auto *V = PN.getIncomingValue(i); if (Instruction *I = dyn_cast<Instruction>(V)) if (L->contains(I)) |