Skip to content

Commit ecc3545

Browse files
authored
[Utils] Fix incorrect LCSSA PHI nodes when splitting critical edges with MergeIdenticalEdges (#131744)
This PR fixes incorrect LCSSA PHI node generation when splitting critical edges with both `PreserveLCSSA` and `MergeIdenticalEdges` enabled. The bug caused PHI nodes in the split block to miss predecessors when multiple identical edges were merged.
1 parent bf51609 commit ecc3545

File tree

2 files changed

+67
-1
lines changed

2 files changed

+67
-1
lines changed

llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp

+10-1
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ llvm::SplitKnownCriticalEdge(Instruction *TI, unsigned SuccNum,
207207
}
208208
}
209209

210+
unsigned NumSplitIdenticalEdges = 1;
211+
210212
// If there are any other edges from TIBB to DestBB, update those to go
211213
// through the split block, making those edges non-critical as well (and
212214
// reducing the number of phi entries in the DestBB if relevant).
@@ -219,6 +221,9 @@ llvm::SplitKnownCriticalEdge(Instruction *TI, unsigned SuccNum,
219221

220222
// We found another edge to DestBB, go to NewBB instead.
221223
TI->setSuccessor(i, NewBB);
224+
225+
// Record the number of split identical edges to DestBB.
226+
NumSplitIdenticalEdges++;
222227
}
223228
}
224229

@@ -290,7 +295,11 @@ llvm::SplitKnownCriticalEdge(Instruction *TI, unsigned SuccNum,
290295

291296
// Update LCSSA form in the newly created exit block.
292297
if (Options.PreserveLCSSA) {
293-
createPHIsForSplitLoopExit(TIBB, NewBB, DestBB);
298+
// If > 1 identical edges to be split, we need to introduce the same
299+
// number of the incoming blocks for the new PHINode.
300+
createPHIsForSplitLoopExit(
301+
SmallVector<BasicBlock *, 4>(NumSplitIdenticalEdges, TIBB), NewBB,
302+
DestBB);
294303
}
295304

296305
if (!LoopPreds.empty()) {

llvm/unittests/Transforms/Utils/BasicBlockUtilsTest.cpp

+57
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,63 @@ define void @crit_edge(i1 %cond0, i1 %cond1) {
438438
EXPECT_TRUE(PDT.verify());
439439
}
440440

441+
TEST(BasicBlockUtils, SplitLoopCriticalEdge) {
442+
LLVMContext C;
443+
std::unique_ptr<Module> M = parseIR(C, R"IR(
444+
declare i1 @predicate(ptr %p)
445+
446+
define ptr @Parse(ptr %gp) {
447+
entry:
448+
br label %for.inc
449+
450+
for.inc:
451+
%phi = phi ptr [ %gp, %entry ], [ %cp, %while.cond ], [ %cp, %while.cond ]
452+
%cond = call i1 @predicate(ptr %phi)
453+
%inc= getelementptr inbounds i8, ptr %phi, i64 1
454+
br i1 %cond, label %while.cond, label %exit
455+
456+
while.cond:
457+
%cp = phi ptr [ %inc, %for.inc ], [ %incdec, %while.body ]
458+
%val = load i8, ptr %cp, align 1
459+
switch i8 %val, label %while.body [
460+
i8 10, label %for.inc
461+
i8 0, label %for.inc
462+
]
463+
464+
while.body:
465+
%incdec = getelementptr inbounds i8, ptr %cp, i64 1
466+
br label %while.cond
467+
468+
exit:
469+
ret ptr %phi
470+
}
471+
)IR");
472+
Function *F = M->getFunction("Parse");
473+
DominatorTree DT(*F);
474+
LoopInfo LI(DT);
475+
476+
CriticalEdgeSplittingOptions CESO =
477+
CriticalEdgeSplittingOptions(nullptr, &LI, nullptr)
478+
.setMergeIdenticalEdges()
479+
.setPreserveLCSSA();
480+
EXPECT_EQ(2u, SplitAllCriticalEdges(*F, CESO));
481+
482+
BasicBlock *WhileBB = getBasicBlockByName(*F, "while.cond");
483+
BasicBlock *SplitBB = WhileBB->getTerminator()->getSuccessor(1);
484+
// The only 1 successor of SplitBB is %for.inc
485+
EXPECT_EQ(1u, SplitBB->getTerminator()->getNumSuccessors());
486+
// MergeIdenticalEdges: SplitBB has two identical predecessors, %while.cond.
487+
EXPECT_EQ(WhileBB, SplitBB->getUniquePredecessor());
488+
EXPECT_TRUE(SplitBB->hasNPredecessors(2));
489+
490+
auto *PN = dyn_cast<PHINode>(&SplitBB->front());
491+
// PreserveLCSSA: should insert a PHI node in front of SplitBB
492+
EXPECT_NE(nullptr, PN);
493+
// The PHI node should have 2 identical incoming blocks.
494+
EXPECT_EQ(2u, PN->getNumIncomingValues());
495+
EXPECT_EQ(PN->getIncomingBlock(0), PN->getIncomingBlock(1));
496+
}
497+
441498
TEST(BasicBlockUtils, SplitIndirectBrCriticalEdgesIgnorePHIs) {
442499
LLVMContext C;
443500
std::unique_ptr<Module> M = parseIR(C, R"IR(

0 commit comments

Comments
 (0)