aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib
diff options
context:
space:
mode:
authorJoshua Cao <cao.joshua@yahoo.com>2022-12-16 04:00:56 -0500
committerJoshua Cao <cao.joshua@yahoo.com>2023-01-05 00:05:49 -0800
commit629d880dc527cd7a8d692cd24af196db4ea8646b (patch)
treef49022fb86dfa739ae46614d6963b3a5094690e4 /llvm/lib
parent6a930e889145cbfb3ff1d99f67a5382c19bc1745 (diff)
downloadllvm-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.cpp39
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);
- }
}
/*