Skip to content

Commit 6a38336

Browse files
committed
PGOInstrumentation, GCOVProfiling: Split indirectbr critical edges regardless of PHIs
The `SplitIndirectBrCriticalEdges` function was originally designed for `CodeGenPrepare` and skipped splitting of edges when the destination block didn't contain any `PHI` instructions. This only makes sense when reducing COPYs like `CodeGenPrepare`. In the case of `PGOInstrumentation` or `GCOVProfiling` it would result in missed counters and wrong result in functions with computed goto. Differential Revision: https://reviews.llvm.org/D120096
1 parent d7a3073 commit 6a38336

File tree

11 files changed

+96
-25
lines changed

11 files changed

+96
-25
lines changed

llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,9 @@ BranchInst *GetIfCondition(BasicBlock *BB, BasicBlock *&IfTrue,
500500
// create the following structure:
501501
// A -> D0A, B -> D0A, I -> D0B, D0A -> D1, D0B -> D1
502502
// If BPI and BFI aren't non-null, BPI/BFI will be updated accordingly.
503-
bool SplitIndirectBrCriticalEdges(Function &F,
503+
// When `IgnoreBlocksWithoutPHI` is set to `true` critical edges leading to a
504+
// block without phi-instructions will not be split.
505+
bool SplitIndirectBrCriticalEdges(Function &F, bool IgnoreBlocksWithoutPHI,
504506
BranchProbabilityInfo *BPI = nullptr,
505507
BlockFrequencyInfo *BFI = nullptr);
506508

llvm/lib/CodeGen/CodeGenPrepare.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,8 @@ bool CodeGenPrepare::runOnFunction(Function &F) {
524524

525525
// Split some critical edges where one of the sources is an indirect branch,
526526
// to help generate sane code for PHIs involving such edges.
527-
EverMadeChange |= SplitIndirectBrCriticalEdges(F);
527+
EverMadeChange |=
528+
SplitIndirectBrCriticalEdges(F, /*IgnoreBlocksWithoutPHI=*/true);
528529

529530
bool MadeChange = true;
530531
while (MadeChange) {

llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -862,7 +862,8 @@ bool GCOVProfiler::emitProfileNotes(
862862

863863
// Split indirectbr critical edges here before computing the MST rather
864864
// than later in getInstrBB() to avoid invalidating it.
865-
SplitIndirectBrCriticalEdges(F, BPI, BFI);
865+
SplitIndirectBrCriticalEdges(F, /*IgnoreBlocksWithoutPHI=*/false, BPI,
866+
BFI);
866867

867868
CFGMST<Edge, BBInfo> MST(F, /*InstrumentFuncEntry_=*/false, BPI, BFI);
868869

llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -940,7 +940,7 @@ static void instrumentOneFunc(
940940
bool IsCS) {
941941
// Split indirectbr critical edges here before computing the MST rather than
942942
// later in getInstrBB() to avoid invalidating it.
943-
SplitIndirectBrCriticalEdges(F, BPI, BFI);
943+
SplitIndirectBrCriticalEdges(F, /*IgnoreBlocksWithoutPHI=*/false, BPI, BFI);
944944

945945
FuncPGOInstrumentation<PGOEdge, BBInfo> FuncInfo(
946946
F, TLI, ComdatMembers, true, BPI, BFI, IsCS, PGOInstrumentEntry);
@@ -1929,7 +1929,7 @@ static bool annotateAllFunctions(
19291929
auto *BFI = LookupBFI(F);
19301930
// Split indirectbr critical edges here before computing the MST rather than
19311931
// later in getInstrBB() to avoid invalidating it.
1932-
SplitIndirectBrCriticalEdges(F, BPI, BFI);
1932+
SplitIndirectBrCriticalEdges(F, /*IgnoreBlocksWithoutPHI=*/false, BPI, BFI);
19331933
PGOUseFunc Func(F, &M, TLI, ComdatMembers, BPI, BFI, PSI, IsCS,
19341934
InstrumentFuncEntry);
19351935
// When AllMinusOnes is true, it means the profile for the function

llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -317,18 +317,11 @@ llvm::SplitKnownCriticalEdge(Instruction *TI, unsigned SuccNum,
317317
// predecessors of BB.
318318
static BasicBlock *
319319
findIBRPredecessor(BasicBlock *BB, SmallVectorImpl<BasicBlock *> &OtherPreds) {
320-
// If the block doesn't have any PHIs, we don't care about it, since there's
321-
// no point in splitting it.
322-
PHINode *PN = dyn_cast<PHINode>(BB->begin());
323-
if (!PN)
324-
return nullptr;
325-
326320
// Verify we have exactly one IBR predecessor.
327321
// Conservatively bail out if one of the other predecessors is not a "regular"
328322
// terminator (that is, not a switch or a br).
329323
BasicBlock *IBB = nullptr;
330-
for (unsigned Pred = 0, E = PN->getNumIncomingValues(); Pred != E; ++Pred) {
331-
BasicBlock *PredBB = PN->getIncomingBlock(Pred);
324+
for (BasicBlock *PredBB : predecessors(BB)) {
332325
Instruction *PredTerm = PredBB->getTerminator();
333326
switch (PredTerm->getOpcode()) {
334327
case Instruction::IndirectBr:
@@ -349,6 +342,7 @@ findIBRPredecessor(BasicBlock *BB, SmallVectorImpl<BasicBlock *> &OtherPreds) {
349342
}
350343

351344
bool llvm::SplitIndirectBrCriticalEdges(Function &F,
345+
bool IgnoreBlocksWithoutPHI,
352346
BranchProbabilityInfo *BPI,
353347
BlockFrequencyInfo *BFI) {
354348
// Check whether the function has any indirectbrs, and collect which blocks
@@ -370,6 +364,9 @@ bool llvm::SplitIndirectBrCriticalEdges(Function &F,
370364
bool ShouldUpdateAnalysis = BPI && BFI;
371365
bool Changed = false;
372366
for (BasicBlock *Target : Targets) {
367+
if (IgnoreBlocksWithoutPHI && Target->phis().empty())
368+
continue;
369+
373370
SmallVector<BasicBlock *, 16> OtherPreds;
374371
BasicBlock *IBRPred = findIBRPredecessor(Target, OtherPreds);
375372
// If we did not found an indirectbr, or the indirectbr is the only

llvm/test/Transforms/GCOVProfiling/split-indirectbr-critical-edges.ll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ indirect.preheader: ; preds = %for.cond
3333
indirect: ; preds = %indirect.preheader, %indirect
3434
indirectbr i8* %2, [label %indirect, label %end]
3535

36+
indirect2:
37+
; For this test we do not want critical edges split. Adding a 2nd `indirectbr`
38+
; does the trick.
39+
indirectbr i8* %2, [label %indirect, label %end]
40+
3641
end: ; preds = %indirect
3742
ret i32 0, !dbg !22
3843
}

llvm/test/Transforms/PGOProfile/Inputs/irreducible.proftext

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,10 @@ _Z11irreducibleii
1414

1515
_Z11irreduciblePh
1616
# Func Hash:
17-
331779889035882993
17+
52047014671956012
1818
# Num Counters:
1919
9
2020
# Counter Values:
21-
100
2221
300
2322
99
2423
300
@@ -27,3 +26,4 @@ _Z11irreduciblePh
2726
1
2827
0
2928
0
29+
0

llvm/test/Transforms/PGOProfile/Inputs/irreducible_entry.proftext

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@ _Z11irreducibleii
1515

1616
_Z11irreduciblePh
1717
# Func Hash:
18-
331779889035882993
18+
52047014671956012
1919
# Num Counters:
2020
9
2121
# Counter Values:
2222
1
23-
100
2423
300
2524
99
2625
300
2726
201
2827
1
2928
0
3029
0
30+
0

llvm/test/Transforms/PGOProfile/irreducible.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,4 @@ indirectgoto: ; preds = %if.then18, %if.then
139139
; USE: ![[IF_END9_IRR_LOOP]] = !{!"loop_header_weight", i64 1000}
140140
; USE: ![[SW_BB6_IRR_LOOP]] = !{!"loop_header_weight", i64 501}
141141
; USE: ![[SW_BB15_IRR_LOOP]] = !{!"loop_header_weight", i64 100}
142-
; USE: ![[INDIRECTGOTO_IRR_LOOP]] = !{!"loop_header_weight", i64 400}
142+
; USE: ![[INDIRECTGOTO_IRR_LOOP]] = !{!"loop_header_weight", i64 399}

llvm/test/Transforms/PGOProfile/split-indirectbr-critical-edges.ll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ if.end: ; preds = %if.end.preheader, %
4343
; CHECK-LABEL: @cannot_split(
4444
; CHECK-NEXT: entry:
4545
; CHECK-NEXT: call void @llvm.instrprof.increment
46+
; CHECK: indirect:
4647
; CHECK-NOT: call void @llvm.instrprof.increment
48+
; CHECK: indirect2:
49+
; CHECK-NEXT: call void @llvm.instrprof.increment
4750
define i32 @cannot_split(i8* nocapture readonly %p) {
4851
entry:
4952
%targets = alloca <2 x i8*>, align 16
@@ -56,6 +59,11 @@ entry:
5659
br label %indirect
5760

5861
indirect: ; preds = %entry, %indirect
62+
indirectbr i8* %1, [label %indirect, label %end, label %indirect2]
63+
64+
indirect2:
65+
; For this test we do not want critical edges split. Adding a 2nd `indirectbr`
66+
; does the trick.
5967
indirectbr i8* %1, [label %indirect, label %end]
6068

6169
end: ; preds = %indirect

llvm/unittests/Transforms/Utils/BasicBlockUtilsTest.cpp

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -437,21 +437,23 @@ define void @crit_edge(i1 %cond0, i1 %cond1) {
437437
EXPECT_TRUE(PDT.verify());
438438
}
439439

440-
TEST(BasicBlockUtils, SplitIndirectBrCriticalEdge) {
440+
TEST(BasicBlockUtils, SplitIndirectBrCriticalEdgesIgnorePHIs) {
441441
LLVMContext C;
442442
std::unique_ptr<Module> M = parseIR(C, R"IR(
443-
define void @crit_edge(i8* %cond0, i1 %cond1) {
443+
define void @crit_edge(i8* %tgt, i1 %cond0, i1 %cond1) {
444444
entry:
445-
indirectbr i8* %cond0, [label %bb0, label %bb1]
445+
indirectbr i8* %tgt, [label %bb0, label %bb1, label %bb2]
446446
bb0:
447-
br label %bb1
447+
br i1 %cond0, label %bb1, label %bb2
448448
bb1:
449449
%p = phi i32 [0, %bb0], [0, %entry]
450-
br i1 %cond1, label %bb2, label %bb3
450+
br i1 %cond1, label %bb3, label %bb4
451451
bb2:
452452
ret void
453453
bb3:
454454
ret void
455+
bb4:
456+
ret void
455457
}
456458
)IR");
457459
Function *F = M->getFunction("crit_edge");
@@ -460,14 +462,69 @@ define void @crit_edge(i8* %cond0, i1 %cond1) {
460462
BranchProbabilityInfo BPI(*F, LI);
461463
BlockFrequencyInfo BFI(*F, BPI, LI);
462464

463-
ASSERT_TRUE(SplitIndirectBrCriticalEdges(*F, &BPI, &BFI));
465+
ASSERT_TRUE(SplitIndirectBrCriticalEdges(*F, /*IgnoreBlocksWithoutPHI=*/true,
466+
&BPI, &BFI));
464467

465468
// Check that successors of the split block get their probability correct.
466469
BasicBlock *BB1 = getBasicBlockByName(*F, "bb1");
467470
BasicBlock *SplitBB = BB1->getTerminator()->getSuccessor(0);
468-
EXPECT_EQ(2u, SplitBB->getTerminator()->getNumSuccessors());
471+
ASSERT_EQ(2u, SplitBB->getTerminator()->getNumSuccessors());
469472
EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 0u));
470473
EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 1u));
474+
475+
// bb2 has no PHI, so we shouldn't split bb0 -> bb2
476+
BasicBlock *BB0 = getBasicBlockByName(*F, "bb0");
477+
ASSERT_EQ(2u, BB0->getTerminator()->getNumSuccessors());
478+
EXPECT_EQ(BB0->getTerminator()->getSuccessor(1),
479+
getBasicBlockByName(*F, "bb2"));
480+
}
481+
482+
TEST(BasicBlockUtils, SplitIndirectBrCriticalEdges) {
483+
LLVMContext C;
484+
std::unique_ptr<Module> M = parseIR(C, R"IR(
485+
define void @crit_edge(i8* %tgt, i1 %cond0, i1 %cond1) {
486+
entry:
487+
indirectbr i8* %tgt, [label %bb0, label %bb1, label %bb2]
488+
bb0:
489+
br i1 %cond0, label %bb1, label %bb2
490+
bb1:
491+
%p = phi i32 [0, %bb0], [0, %entry]
492+
br i1 %cond1, label %bb3, label %bb4
493+
bb2:
494+
ret void
495+
bb3:
496+
ret void
497+
bb4:
498+
ret void
499+
}
500+
)IR");
501+
Function *F = M->getFunction("crit_edge");
502+
DominatorTree DT(*F);
503+
LoopInfo LI(DT);
504+
BranchProbabilityInfo BPI(*F, LI);
505+
BlockFrequencyInfo BFI(*F, BPI, LI);
506+
507+
ASSERT_TRUE(SplitIndirectBrCriticalEdges(*F, /*IgnoreBlocksWithoutPHI=*/false,
508+
&BPI, &BFI));
509+
510+
// Check that successors of the split block get their probability correct.
511+
BasicBlock *BB1 = getBasicBlockByName(*F, "bb1");
512+
BasicBlock *SplitBB = BB1->getTerminator()->getSuccessor(0);
513+
ASSERT_EQ(2u, SplitBB->getTerminator()->getNumSuccessors());
514+
EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 0u));
515+
EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 1u));
516+
517+
// Should split, resulting in:
518+
// bb0 -> bb2.clone; bb2 -> split1; bb2.clone -> split,
519+
BasicBlock *BB0 = getBasicBlockByName(*F, "bb0");
520+
ASSERT_EQ(2u, BB0->getTerminator()->getNumSuccessors());
521+
BasicBlock *BB2Clone = BB0->getTerminator()->getSuccessor(1);
522+
BasicBlock *BB2 = getBasicBlockByName(*F, "bb2");
523+
EXPECT_NE(BB2Clone, BB2);
524+
ASSERT_EQ(1u, BB2->getTerminator()->getNumSuccessors());
525+
ASSERT_EQ(1u, BB2Clone->getTerminator()->getNumSuccessors());
526+
EXPECT_EQ(BB2->getTerminator()->getSuccessor(0),
527+
BB2Clone->getTerminator()->getSuccessor(0));
471528
}
472529

473530
TEST(BasicBlockUtils, SetEdgeProbability) {

0 commit comments

Comments
 (0)