diff options
author | Michael Zolotukhin <mzolotukhin@apple.com> | 2016-09-08 01:52:26 +0000 |
---|---|---|
committer | Michael Zolotukhin <mzolotukhin@apple.com> | 2016-09-08 01:52:26 +0000 |
commit | 5e0a20697e5e57d7306d4b335cb5aa9cd359e99b (patch) | |
tree | 3747e5c33115403d958ad8162bf89adc9fe1f433 /llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp | |
parent | 81291a0fce2fb46f466676c1fd023af09c5ebbd7 (diff) | |
download | llvm-5e0a20697e5e57d7306d4b335cb5aa9cd359e99b.zip llvm-5e0a20697e5e57d7306d4b335cb5aa9cd359e99b.tar.gz llvm-5e0a20697e5e57d7306d4b335cb5aa9cd359e99b.tar.bz2 |
[LoopUnroll] Properly update loop-info when cloning prologues and epilogues.
Summary:
When cloning blocks for prologue/epilogue we need to replicate the loop
structure from the original loop. It wasn't a problem for the innermost
loops, but it led to an incorrect loop info when we unrolled a loop with
a child loop - in this case created prologue-loop had a child loop, but
loop info didn't reflect that.
This fixes PR28888.
Reviewers: chandlerc, sanjoy, hfinkel
Subscribers: llvm-commits, silvas
Differential Revision: https://reviews.llvm.org/D24203
llvm-svn: 280901
Diffstat (limited to 'llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp | 65 |
1 files changed, 54 insertions, 11 deletions
diff --git a/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp b/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp index 5758a41..ee8bd35 100644 --- a/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp +++ b/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp @@ -291,15 +291,10 @@ static void CloneLoopBlocks(Loop *L, Value *NewIter, Function *F = Header->getParent(); LoopBlocksDFS::RPOIterator BlockBegin = LoopBlocks.beginRPO(); LoopBlocksDFS::RPOIterator BlockEnd = LoopBlocks.endRPO(); - Loop *NewLoop = nullptr; Loop *ParentLoop = L->getParentLoop(); - if (CreateRemainderLoop) { - NewLoop = new Loop(); - if (ParentLoop) - ParentLoop->addChildLoop(NewLoop); - else - LI->addTopLevelLoop(NewLoop); - } + + // The map from original loops to their cloned copies. + SmallDenseMap<const Loop *, Loop *, 4> NewLoops; // For each block in the original loop, create a new copy, // and update the value map with the newly created values. @@ -307,10 +302,57 @@ static void CloneLoopBlocks(Loop *L, Value *NewIter, BasicBlock *NewBB = CloneBasicBlock(*BB, VMap, "." + suffix, F); NewBlocks.push_back(NewBB); + // Figure out which loop NewBB is in. + auto findClonedLoop = [&](const Loop *OldLoop) { + Loop *&NewLoop = NewLoops[OldLoop]; + // If we've encountered this loop before, return it right away. + if (NewLoop) + return NewLoop; + + // If BB is from L, and we're not creating a remainder, the loop for + // NewBB will be ParentLoop, which might be null. Update NewLoops map and + // return ParentLoop. + if (OldLoop == L && !CreateRemainderLoop) + return (NewLoop = ParentLoop); + + // Now we know that there should be a cloned counterpart for OldLoop, but + // we haven't seen it yet. Note that OldLoop might be L if we're + // generating a remainder loop, or it can be an inner loop of L - in this + // case we'll recreate the loop structure of L in its clone. + + // This is a first block belonging to OldLoop encountered in our RPO + // traversal. + assert(*BB == OldLoop->getHeader() && "Header should be first in RPO"); + + NewLoop = new Loop; + Loop *OldLoopParent = OldLoop->getParentLoop(); + // If OldLoop has a parent loop, we have two options: + // 1. ParentLoop is the parent of L. It won't be cloned, and it will + // be a parent for NewLoop too. + // 2. ParentLoop is not a parent of L. In this case, it should be one + // of the cloned loops and we should be able to find it in our map. + // + // If OldLoop doesn't have a parent, then NewLoop should be yet another + // top-level loop. + if (OldLoopParent) { + Loop *NewLoopParent = ParentLoop == OldLoopParent + ? ParentLoop + : NewLoops.lookup(OldLoopParent); + assert(NewLoopParent && "Expected parent loop before sub-loop in RPO"); + NewLoopParent->addChildLoop(NewLoop); + } else + LI->addTopLevelLoop(NewLoop); + return NewLoop; + }; + + Loop *NewLoop = findClonedLoop(LI->getLoopFor(*BB)); + + assert(NewLoop || + (!CreateRemainderLoop && !ParentLoop) && + "NewLoop can only be null if we are cloning top-level loop " + "without creating a remainder loop."); if (NewLoop) NewLoop->addBasicBlockToLoop(NewBB, *LI); - else if (ParentLoop) - ParentLoop->addBasicBlockToLoop(NewBB, *LI); VMap[*BB] = NewBB; if (Header == *BB) { @@ -369,7 +411,8 @@ static void CloneLoopBlocks(Loop *L, Value *NewIter, NewPHI->setIncomingValue(idx, V); } } - if (NewLoop) { + if (CreateRemainderLoop) { + Loop *NewLoop = NewLoops[L]; // Add unroll disable metadata to disable future unrolling for this loop. SmallVector<Metadata *, 4> MDs; // Reserve first location for self reference to the LoopID metadata node. |