diff options
author | Joshua Cao <cao.joshua@yahoo.com> | 2022-12-16 04:00:56 -0500 |
---|---|---|
committer | Joshua Cao <cao.joshua@yahoo.com> | 2023-01-05 00:05:49 -0800 |
commit | 629d880dc527cd7a8d692cd24af196db4ea8646b (patch) | |
tree | f49022fb86dfa739ae46614d6963b3a5094690e4 /llvm/lib | |
parent | 6a930e889145cbfb3ff1d99f67a5382c19bc1745 (diff) | |
download | llvm-629d880dc527cd7a8d692cd24af196db4ea8646b.zip llvm-629d880dc527cd7a8d692cd24af196db4ea8646b.tar.gz llvm-629d880dc527cd7a8d692cd24af196db4ea8646b.tar.bz2 |
[LoopUnrollAndJam] Visit phi operand dependencies in post-order
Fixes https://github.com/llvm/llvm-project/issues/58565
The previous implementation visits operands in pre-order, but this does
not guarantee an instruction is visited before its uses. This can cause
instructions to be copied in the incorrect order. For example:
```
a = ...
b = add a, 1
c = add a, b
d = add b, a
```
Pre-order visits does not guarantee the order in which `a` and `b` are
visited. LoopUnrollAndJam may incorrectly insert `b` before `a`.
This patch implements post-order visits. By visiting dependencies first,
we guarantee that an instruction's dependencies are visited first.
Differential Revision: https://reviews.llvm.org/D140255
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp | 39 |
1 files changed, 17 insertions, 22 deletions
diff --git a/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp b/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp index 416aa21..b125e95 100644 --- a/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp +++ b/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp @@ -137,25 +137,28 @@ static bool partitionOuterLoopBlocks(Loop *L, Loop *SubLoop, template <typename T> static bool processHeaderPhiOperands(BasicBlock *Header, BasicBlock *Latch, BasicBlockSet &AftBlocks, T Visit) { - SmallVector<Instruction *, 8> Worklist; SmallPtrSet<Instruction *, 8> VisitedInstr; - for (auto &Phi : Header->phis()) { - Value *V = Phi.getIncomingValueForBlock(Latch); - if (Instruction *I = dyn_cast<Instruction>(V)) - Worklist.push_back(I); - } - while (!Worklist.empty()) { - Instruction *I = Worklist.pop_back_val(); - if (!Visit(I)) - return false; + std::function<bool(Instruction * I)> ProcessInstr = [&](Instruction *I) { + if (VisitedInstr.count(I)) + return true; + VisitedInstr.insert(I); if (AftBlocks.count(I->getParent())) for (auto &U : I->operands()) if (Instruction *II = dyn_cast<Instruction>(U)) - if (!VisitedInstr.count(II)) - Worklist.push_back(II); + if (!ProcessInstr(II)) + return false; + + return Visit(I); + }; + + for (auto &Phi : Header->phis()) { + Value *V = Phi.getIncomingValueForBlock(Latch); + if (Instruction *I = dyn_cast<Instruction>(V)) + if (!ProcessInstr(I)) + return false; } return true; @@ -168,20 +171,12 @@ static void moveHeaderPhiOperandsToForeBlocks(BasicBlock *Header, BasicBlockSet &AftBlocks) { // We need to ensure we move the instructions in the correct order, // starting with the earliest required instruction and moving forward. - std::vector<Instruction *> Visited; processHeaderPhiOperands(Header, Latch, AftBlocks, - [&Visited, &AftBlocks](Instruction *I) { + [&AftBlocks, &InsertLoc](Instruction *I) { if (AftBlocks.count(I->getParent())) - Visited.push_back(I); + I->moveBefore(InsertLoc); return true; }); - - // Move all instructions in program order to before the InsertLoc - BasicBlock *InsertLocBB = InsertLoc->getParent(); - for (Instruction *I : reverse(Visited)) { - if (I->getParent() != InsertLocBB) - I->moveBefore(InsertLoc); - } } /* |