Skip to content

Commit 910e536

Browse files
authored
[SimplifyCFG][profcheck] Synthesize profile for br (X == 0 | X == 1), T, F1 -> switch (#161549)
We cannot calculate the weights of the switch precisely, but we do know the probability of the default branch. We then split equally the remaining probability over the rest of the cases. If we did nothing, the static estimation could be considerably poorer. Issue #147390
1 parent 1b30e49 commit 910e536

File tree

2 files changed

+43
-14
lines changed

2 files changed

+43
-14
lines changed

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5152,14 +5152,18 @@ bool SimplifyCFGOpt::simplifyBranchOnICmpChain(BranchInst *BI,
51525152
if (ExtraCase && Values.size() < 2)
51535153
return false;
51545154

5155-
// TODO: Preserve branch weight metadata, similarly to how
5156-
// foldValueComparisonIntoPredecessors preserves it.
5155+
SmallVector<uint32_t> BranchWeights;
5156+
const bool HasProfile = !ProfcheckDisableMetadataFixes &&
5157+
extractBranchWeights(*BI, BranchWeights);
51575158

51585159
// Figure out which block is which destination.
51595160
BasicBlock *DefaultBB = BI->getSuccessor(1);
51605161
BasicBlock *EdgeBB = BI->getSuccessor(0);
5161-
if (!TrueWhenEqual)
5162+
if (!TrueWhenEqual) {
51625163
std::swap(DefaultBB, EdgeBB);
5164+
if (HasProfile)
5165+
std::swap(BranchWeights[0], BranchWeights[1]);
5166+
}
51635167

51645168
BasicBlock *BB = BI->getParent();
51655169

@@ -5190,10 +5194,11 @@ bool SimplifyCFGOpt::simplifyBranchOnICmpChain(BranchInst *BI,
51905194
if (!isGuaranteedNotToBeUndefOrPoison(ExtraCase, AC, BI, nullptr))
51915195
ExtraCase = Builder.CreateFreeze(ExtraCase);
51925196

5193-
if (TrueWhenEqual)
5194-
Builder.CreateCondBr(ExtraCase, EdgeBB, NewBB);
5195-
else
5196-
Builder.CreateCondBr(ExtraCase, NewBB, EdgeBB);
5197+
// We don't have any info about this condition.
5198+
auto *Br = TrueWhenEqual ? Builder.CreateCondBr(ExtraCase, EdgeBB, NewBB)
5199+
: Builder.CreateCondBr(ExtraCase, NewBB, EdgeBB);
5200+
setExplicitlyUnknownBranchWeightsIfProfiled(*Br, *NewBB->getParent(),
5201+
DEBUG_TYPE);
51975202

51985203
OldTI->eraseFromParent();
51995204

@@ -5220,6 +5225,17 @@ bool SimplifyCFGOpt::simplifyBranchOnICmpChain(BranchInst *BI,
52205225

52215226
// Create the new switch instruction now.
52225227
SwitchInst *New = Builder.CreateSwitch(CompVal, DefaultBB, Values.size());
5228+
if (HasProfile) {
5229+
// We know the weight of the default case. We don't know the weight of the
5230+
// other cases, but rather than completely lose profiling info, we split
5231+
// the remaining probability equally over them.
5232+
SmallVector<uint32_t> NewWeights(Values.size() + 1);
5233+
NewWeights[0] = BranchWeights[1]; // this is the default, and we swapped if
5234+
// TrueWhenEqual.
5235+
for (auto &V : drop_begin(NewWeights))
5236+
V = BranchWeights[0] / Values.size();
5237+
setBranchWeights(*New, NewWeights, /*IsExpected=*/false);
5238+
}
52235239

52245240
// Add all of the 'cases' to the switch instruction.
52255241
for (ConstantInt *Val : Values)

llvm/test/Transforms/SimplifyCFG/switch_create.ll

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals
22
; RUN: opt -S -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -switch-range-to-icmp < %s | FileCheck %s
33
; RUN: opt -S -data-layout="p:32:32-p1:16:16" -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -switch-range-to-icmp < %s | FileCheck -check-prefix=CHECK -check-prefix=DL %s
44

55
declare void @foo1()
66

77
declare void @foo2()
88

9-
define void @test1(i32 %V) {
9+
define void @test1(i32 %V) !prof !0 {
1010
; CHECK-LABEL: @test1(
1111
; CHECK-NEXT: switch i32 [[V:%.*]], label [[F:%.*]] [
1212
; CHECK-NEXT: i32 17, label [[T:%.*]]
1313
; CHECK-NEXT: i32 4, label [[T]]
14-
; CHECK-NEXT: ]
14+
; CHECK-NEXT: ], !prof [[PROF1:![0-9]+]]
1515
; CHECK: common.ret:
1616
; CHECK-NEXT: ret void
1717
; CHECK: T:
@@ -24,7 +24,7 @@ define void @test1(i32 %V) {
2424
%C1 = icmp eq i32 %V, 4 ; <i1> [#uses=1]
2525
%C2 = icmp eq i32 %V, 17 ; <i1> [#uses=1]
2626
%CN = or i1 %C1, %C2 ; <i1> [#uses=1]
27-
br i1 %CN, label %T, label %F
27+
br i1 %CN, label %T, label %F, !prof !1
2828
T: ; preds = %0
2929
call void @foo1( )
3030
ret void
@@ -116,12 +116,12 @@ F: ; preds = %0
116116
ret void
117117
}
118118

119-
define void @test2(i32 %V) {
119+
define void @test2(i32 %V) !prof !0 {
120120
; CHECK-LABEL: @test2(
121121
; CHECK-NEXT: switch i32 [[V:%.*]], label [[T:%.*]] [
122122
; CHECK-NEXT: i32 17, label [[F:%.*]]
123123
; CHECK-NEXT: i32 4, label [[F]]
124-
; CHECK-NEXT: ]
124+
; CHECK-NEXT: ], !prof [[PROF2:![0-9]+]]
125125
; CHECK: common.ret:
126126
; CHECK-NEXT: ret void
127127
; CHECK: T:
@@ -134,7 +134,7 @@ define void @test2(i32 %V) {
134134
%C1 = icmp ne i32 %V, 4 ; <i1> [#uses=1]
135135
%C2 = icmp ne i32 %V, 17 ; <i1> [#uses=1]
136136
%CN = and i1 %C1, %C2 ; <i1> [#uses=1]
137-
br i1 %CN, label %T, label %F
137+
br i1 %CN, label %T, label %F, !prof !1
138138
T: ; preds = %0
139139
call void @foo1( )
140140
ret void
@@ -1313,3 +1313,16 @@ if.then:
13131313
if.end:
13141314
ret void
13151315
}
1316+
1317+
!0 = !{!"function_entry_count", i32 100}
1318+
!1 = !{!"branch_weights", i32 6, i32 10}
1319+
;.
1320+
; DL: attributes #[[ATTR0:[0-9]+]] = { noredzone nounwind ssp }
1321+
; DL: attributes #[[ATTR1:[0-9]+]] = { nounwind }
1322+
; DL: attributes #[[ATTR2]] = { noredzone nounwind }
1323+
; DL: attributes #[[ATTR3]] = { noredzone }
1324+
;.
1325+
; DL: [[META0:![0-9]+]] = !{!"function_entry_count", i32 100}
1326+
; DL: [[PROF1]] = !{!"branch_weights", i32 10, i32 3, i32 3}
1327+
; DL: [[PROF2]] = !{!"branch_weights", i32 6, i32 5, i32 5}
1328+
;.

0 commit comments

Comments
 (0)