Skip to content

Commit c914877

Browse files
[JumpThreading] Set edge probabilities when creating basic blocks
This patch teaches the jump threading pass to set edge probabilities whenever the pass creates new basic blocks. Without this patch, the compiler sometimes produces non-deterministic results. The non-determinism comes from the jump threading pass using stale edge probabilities in BranchProbabilityInfo. Specifically, when the jump threading pass creates a new basic block, we don't initialize its outgoing edge probability. Edge probabilities are maintained in: DenseMap<Edge, BranchProbability> Probs; in class BranchProbabilityInfo, where Edge is an ordered pair of BasicBlock * and a successor index declared as: using Edge = std::pair<const BasicBlock *, unsigned>; Probs maps edges to their corresponding probabilities. Now, we rarely remove entries from this map, so if we happen to allocate a new basic block at the same address as a previously deleted basic block with an edge probability assigned, the newly created basic block appears to have an edge probability, albeit a stale one. This patch fixes the problem by explicitly setting edge probabilities whenever the jump threading pass creates new basic blocks. Differential Revision: https://reviews.llvm.org/D90106
1 parent 8412915 commit c914877

File tree

4 files changed

+152
-1
lines changed

4 files changed

+152
-1
lines changed

llvm/lib/Transforms/Scalar/JumpThreading.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2236,6 +2236,14 @@ void JumpThreadingPass::ThreadThroughTwoBasicBlocks(BasicBlock *PredPredBB,
22362236
DenseMap<Instruction *, Value *> ValueMapping =
22372237
CloneInstructions(PredBB->begin(), PredBB->end(), NewBB, PredPredBB);
22382238

2239+
// Copy the edge probabilities from PredBB to NewBB.
2240+
if (HasProfileData) {
2241+
SmallVector<BranchProbability, 4> Probs;
2242+
for (BasicBlock *Succ : successors(PredBB))
2243+
Probs.push_back(BPI->getEdgeProbability(PredBB, Succ));
2244+
BPI->setEdgeProbability(NewBB, Probs);
2245+
}
2246+
22392247
// Update the terminator of PredPredBB to jump to NewBB instead of PredBB.
22402248
// This eliminates predecessors from PredPredBB, which requires us to simplify
22412249
// any PHI nodes in PredBB.
@@ -2424,8 +2432,15 @@ BasicBlock *JumpThreadingPass::SplitBlockPreds(BasicBlock *BB,
24242432
if (HasProfileData) // Update frequencies between Pred -> NewBB.
24252433
NewBBFreq += FreqMap.lookup(Pred);
24262434
}
2427-
if (HasProfileData) // Apply the summed frequency to NewBB.
2435+
if (HasProfileData) {
2436+
// Apply the summed frequency to NewBB.
24282437
BFI->setBlockFreq(NewBB, NewBBFreq.getFrequency());
2438+
2439+
// NewBB has exactly one successor.
2440+
SmallVector<BranchProbability, 1> BBSuccProbs;
2441+
BBSuccProbs.push_back(BranchProbability::getOne());
2442+
BPI->setEdgeProbability(NewBB, BBSuccProbs);
2443+
}
24292444
}
24302445

24312446
DTU->applyUpdatesPermissive(Updates);
@@ -2498,6 +2513,11 @@ void JumpThreadingPass::UpdateBlockFreqAndEdgeWeight(BasicBlock *PredBB,
24982513
// Update edge probabilities in BPI.
24992514
BPI->setEdgeProbability(BB, BBSuccProbs);
25002515

2516+
// NewBB has exactly one successor.
2517+
SmallVector<BranchProbability, 1> NewBBSuccProbs;
2518+
NewBBSuccProbs.push_back(BranchProbability::getOne());
2519+
BPI->setEdgeProbability(NewBB, NewBBSuccProbs);
2520+
25012521
// Update the profile metadata as well.
25022522
//
25032523
// Don't do this if the profile of the transformed blocks was statically
@@ -2708,6 +2728,13 @@ void JumpThreadingPass::UnfoldSelectInstr(BasicBlock *Pred, BasicBlock *BB,
27082728
PHINode *Phi = dyn_cast<PHINode>(BI); ++BI)
27092729
if (Phi != SIUse)
27102730
Phi->addIncoming(Phi->getIncomingValueForBlock(Pred), NewBB);
2731+
2732+
if (HasProfileData) {
2733+
// NewBB has exactly one successor.
2734+
SmallVector<BranchProbability, 1> BBSuccProbs;
2735+
BBSuccProbs.push_back(BranchProbability::getOne());
2736+
BPI->setEdgeProbability(NewBB, BBSuccProbs);
2737+
}
27112738
}
27122739

27132740
bool JumpThreadingPass::TryToUnfoldSelect(SwitchInst *SI, BasicBlock *BB) {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
; RUN: opt -debug-only=branch-prob -jump-threading -S %s 2>&1 | FileCheck %s
2+
3+
; Make sure that we set the branch probability for the newly created
4+
; basic block.
5+
6+
define void @foo(i1 %arg1, i1 %arg2, i32 %arg3) !prof !0 !PGOFuncName !1 {
7+
entry:
8+
call void @bar(i32 0)
9+
br i1 %arg1, label %bb3, label %bb1, !prof !2
10+
11+
bb1:
12+
call void @bar(i32 1)
13+
br i1 %arg2, label %bb2, label %bb3, !prof !3
14+
15+
bb2:
16+
call void @bar(i32 2)
17+
br label %bb3
18+
19+
bb3:
20+
; CHECK: set edge bb3.thr_comm -> 0 successor probability to 0x80000000 / 0x80000000
21+
%ptr = phi i32 [ 0, %bb1 ], [ 0, %entry ], [ %arg3, %bb2 ]
22+
call void @bar(i32 3)
23+
%bool = icmp eq i32 %ptr, 0
24+
br i1 %bool, label %exit, label %bb4, !prof !4
25+
; CHECK: set edge bb3.thread -> 0 successor probability to 0x80000000 / 0x80000000
26+
27+
bb4:
28+
call void @bar(i32 %ptr)
29+
br label %exit
30+
31+
exit:
32+
ret void
33+
}
34+
35+
declare void @bar(i32)
36+
37+
!0 = !{!"function_entry_count", i64 15985}
38+
!1 = !{!"foo:foo"}
39+
!2 = !{!"branch_weights", i32 15973, i32 36865}
40+
!3 = !{!"branch_weights", i32 2957, i32 5798}
41+
!4 = !{!"branch_weights", i32 1807, i32 35058}
42+
!5 = !{!"branch_weights", i32 38, i32 287958}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
; RUN: opt -debug-only=branch-prob -jump-threading -S %s 2>&1 | FileCheck %s
2+
3+
; Make sure that we set the branch probability for the newly created
4+
; basic block.
5+
6+
define void @foo(i32 %v0, i1 %arg2) !prof !0 !PGOFuncName !1 {
7+
entry:
8+
%bool1 = icmp eq i32 %v0, 0
9+
br i1 %bool1, label %bb2, label %bb1, !prof !2
10+
11+
bb1:
12+
%sel = select i1 %arg2, i32 %v0, i32 0, !prof !3
13+
br label %bb2
14+
; CHECK: set edge select.unfold -> 0 successor probability to 0x80000000 / 0x80000000
15+
16+
bb2:
17+
%phi = phi i32 [ %sel, %bb1 ], [ 0, %entry ]
18+
%bool2 = icmp eq i32 %phi, 0
19+
br i1 %bool2, label %exit, label %bb3, !prof !4
20+
21+
bb3:
22+
br label %exit
23+
24+
exit:
25+
ret void
26+
}
27+
28+
!0 = !{!"function_entry_count", i64 15985}
29+
!1 = !{!"foo.cpp:foo"}
30+
!2 = !{!"branch_weights", i32 0, i32 36865}
31+
!3 = !{!"branch_weights", i32 35058, i32 1807}
32+
!4 = !{!"branch_weights", i32 1807, i32 35058}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
; RUN: opt -debug-only=branch-prob -jump-threading -S %s 2>&1 | FileCheck %s
2+
3+
; Make sure that we set the branch probability for the newly created
4+
; basic block.
5+
6+
define void @foo(i1 %cond1, i1 %cond2) !prof !0 !PGOFuncName !1 {
7+
entry:
8+
br i1 %cond1, label %bb.f1, label %bb.f2, !prof !2
9+
10+
bb.f1:
11+
call void @f1()
12+
br label %bb.cond2
13+
14+
bb.f2:
15+
call void @f2()
16+
br label %bb.cond2
17+
18+
bb.cond2:
19+
br i1 %cond2, label %exit, label %bb.cond1again, !prof !3
20+
; CHECK: set edge bb.cond2.thread -> 0 successor probability to 0x79b9d244 / 0x80000000
21+
; CHECK: set edge bb.cond2.thread -> 1 successor probability to 0x06462dbc / 0x80000000 = 4.90
22+
23+
bb.cond1again:
24+
br i1 %cond1, label %bb.f3, label %bb.f4, !prof !4
25+
26+
bb.f3:
27+
call void @f3()
28+
br label %exit
29+
30+
bb.f4:
31+
call void @f4()
32+
br label %exit
33+
34+
exit:
35+
ret void
36+
}
37+
38+
declare void @f1()
39+
40+
declare void @f2()
41+
42+
declare void @f3()
43+
44+
declare void @f4()
45+
46+
!0 = !{!"function_entry_count", i64 15985}
47+
!1 = !{!"foo.cpp:foo"}
48+
!2 = !{!"branch_weights", i32 0, i32 36865}
49+
!3 = !{!"branch_weights", i32 35058, i32 1807}
50+
!4 = !{!"branch_weights", i32 1807, i32 35058}

0 commit comments

Comments
 (0)