Skip to content

Commit c54d0d7

Browse files
authored
[InstCombine] Preserve profile after folding select instructions with conditionals (#159666)
If `select` simplification produces the transform: ``` (select A && B, T, F) -> (select A, T, F) ``` or ``` (select A || B, T, F) -> (select A, T, F) ``` it stands to reason that if the branches are the same, then the branch weights remain the same since the net effect is a simplification of the conditional. There are also cases where InstCombine negates the conditional (and therefore reverses the branches); this PR asserts that the branch weights are reversed in this case. Tracking issue: #147390
1 parent 1af8ed1 commit c54d0d7

File tree

3 files changed

+71
-41
lines changed

3 files changed

+71
-41
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
using namespace llvm;
5151
using namespace PatternMatch;
5252

53+
extern cl::opt<bool> ProfcheckDisableMetadataFixes;
5354

5455
/// Replace a select operand based on an equality comparison with the identity
5556
/// constant of a binop.
@@ -4492,8 +4493,21 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
44924493
auto FoldSelectWithAndOrCond = [&](bool IsAnd, Value *A,
44934494
Value *B) -> Instruction * {
44944495
if (Value *V = simplifySelectInst(B, TrueVal, FalseVal,
4495-
SQ.getWithInstruction(&SI)))
4496-
return SelectInst::Create(A, IsAnd ? V : TrueVal, IsAnd ? FalseVal : V);
4496+
SQ.getWithInstruction(&SI))) {
4497+
Value *NewTrueVal = IsAnd ? V : TrueVal;
4498+
Value *NewFalseVal = IsAnd ? FalseVal : V;
4499+
4500+
// If the True and False values don't change, then preserve the branch
4501+
// metadata of the original select as the net effect of this change is to
4502+
// simplify the conditional.
4503+
Instruction *MDFrom = nullptr;
4504+
if (NewTrueVal == TrueVal && NewFalseVal == FalseVal &&
4505+
!ProfcheckDisableMetadataFixes) {
4506+
MDFrom = &SI;
4507+
}
4508+
return SelectInst::Create(A, NewTrueVal, NewFalseVal, "", nullptr,
4509+
MDFrom);
4510+
}
44974511

44984512
// Is (select B, T, F) a SPF?
44994513
if (CondVal->hasOneUse() && SelType->isIntOrIntVectorTy()) {

llvm/test/Transforms/InstCombine/select-and-cmp.ll

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
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=instcombine -S | FileCheck %s
33

44
define i32 @select_and_icmp(i32 %x, i32 %y, i32 %z) {
@@ -114,34 +114,34 @@ define i32 @select_and_icmp_inv(i32 %x, i32 %y, i32 %z) {
114114

115115
; Below used to be negative tests in InstSimplify, but are no more negative cases here
116116

117-
define i32 @select_and_icmp_pred_bad_1(i32 %x, i32 %y, i32 %z) {
117+
define i32 @select_and_icmp_pred_bad_1(i32 %x, i32 %y, i32 %z) !prof !0 {
118118
; CHECK-LABEL: @select_and_icmp_pred_bad_1(
119-
; CHECK-NEXT: ret i32 [[X]]
119+
; CHECK-NEXT: ret i32 [[X:%.*]]
120120
;
121121
%A = icmp eq i32 %x, %z
122122
%B = icmp ne i32 %y, %z
123123
%C = and i1 %A, %B
124-
%D = select i1 %C, i32 %z, i32 %x
124+
%D = select i1 %C, i32 %z, i32 %x, !prof !1
125125
ret i32 %D
126126
}
127127

128-
define i32 @select_and_icmp_pred_bad_2(i32 %x, i32 %y, i32 %z) {
128+
define i32 @select_and_icmp_pred_bad_2(i32 %x, i32 %y, i32 %z) !prof !0 {
129129
; CHECK-LABEL: @select_and_icmp_pred_bad_2(
130130
; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z:%.*]]
131-
; CHECK-NEXT: [[D:%.*]] = select i1 [[B]], i32 [[Z]], i32 [[X]]
131+
; CHECK-NEXT: [[D:%.*]] = select i1 [[B]], i32 [[Z]], i32 [[X:%.*]], !prof [[PROF1:![0-9]+]]
132132
; CHECK-NEXT: ret i32 [[D]]
133133
;
134134
%A = icmp ne i32 %x, %z
135135
%B = icmp eq i32 %y, %z
136136
%C = and i1 %A, %B
137-
%D = select i1 %C, i32 %z, i32 %x
137+
%D = select i1 %C, i32 %z, i32 %x, !prof !1
138138
ret i32 %D
139139
}
140140

141141
define i32 @select_and_icmp_pred_bad_3(i32 %x, i32 %y, i32 %z) {
142142
; CHECK-LABEL: @select_and_icmp_pred_bad_3(
143-
; CHECK-NEXT: [[B_NOT:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
144-
; CHECK-NEXT: [[D:%.*]] = select i1 [[B_NOT]], i32 [[X]], i32 [[Z]]
143+
; CHECK-NEXT: [[B_NOT:%.*]] = icmp eq i32 [[Y:%.*]], [[Z:%.*]]
144+
; CHECK-NEXT: [[D:%.*]] = select i1 [[B_NOT]], i32 [[X:%.*]], i32 [[Z]]
145145
; CHECK-NEXT: ret i32 [[D]]
146146
;
147147
%A = icmp ne i32 %x, %z
@@ -153,8 +153,8 @@ define i32 @select_and_icmp_pred_bad_3(i32 %x, i32 %y, i32 %z) {
153153

154154
define i32 @select_and_icmp_pred_bad_4(i32 %x, i32 %y, i32 %z) {
155155
; CHECK-LABEL: @select_and_icmp_pred_bad_4(
156-
; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
157-
; CHECK-NEXT: [[D:%.*]] = select i1 [[B]], i32 [[Z]], i32 [[X]]
156+
; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z:%.*]]
157+
; CHECK-NEXT: [[D:%.*]] = select i1 [[B]], i32 [[Z]], i32 [[X:%.*]]
158158
; CHECK-NEXT: ret i32 [[D]]
159159
;
160160
%A = icmp eq i32 %x, %z
@@ -166,7 +166,7 @@ define i32 @select_and_icmp_pred_bad_4(i32 %x, i32 %y, i32 %z) {
166166

167167
define i32 @select_and_icmp_alt_bad_1(i32 %x, i32 %y, i32 %z) {
168168
; CHECK-LABEL: @select_and_icmp_alt_bad_1(
169-
; CHECK-NEXT: ret i32 [[Z]]
169+
; CHECK-NEXT: ret i32 [[Z:%.*]]
170170
;
171171
%A = icmp eq i32 %x, %z
172172
%B = icmp ne i32 %y, %z
@@ -177,8 +177,8 @@ define i32 @select_and_icmp_alt_bad_1(i32 %x, i32 %y, i32 %z) {
177177

178178
define i32 @select_and_icmp_alt_bad_2(i32 %x, i32 %y, i32 %z) {
179179
; CHECK-LABEL: @select_and_icmp_alt_bad_2(
180-
; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
181-
; CHECK-NEXT: [[D:%.*]] = select i1 [[B]], i32 [[X]], i32 [[Z]]
180+
; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z:%.*]]
181+
; CHECK-NEXT: [[D:%.*]] = select i1 [[B]], i32 [[X:%.*]], i32 [[Z]]
182182
; CHECK-NEXT: ret i32 [[D]]
183183
;
184184
%A = icmp ne i32 %x, %z
@@ -191,8 +191,8 @@ define i32 @select_and_icmp_alt_bad_2(i32 %x, i32 %y, i32 %z) {
191191

192192
define i32 @select_and_icmp_alt_bad_3(i32 %x, i32 %y, i32 %z) {
193193
; CHECK-LABEL: @select_and_icmp_alt_bad_3(
194-
; CHECK-NEXT: [[B_NOT:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
195-
; CHECK-NEXT: [[D:%.*]] = select i1 [[B_NOT]], i32 [[Z]], i32 [[X]]
194+
; CHECK-NEXT: [[B_NOT:%.*]] = icmp eq i32 [[Y:%.*]], [[Z:%.*]]
195+
; CHECK-NEXT: [[D:%.*]] = select i1 [[B_NOT]], i32 [[Z]], i32 [[X:%.*]]
196196
; CHECK-NEXT: ret i32 [[D]]
197197
;
198198
%A = icmp ne i32 %x, %z
@@ -204,8 +204,8 @@ define i32 @select_and_icmp_alt_bad_3(i32 %x, i32 %y, i32 %z) {
204204

205205
define i32 @select_and_icmp_alt_bad_4(i32 %x, i32 %y, i32 %z) {
206206
; CHECK-LABEL: @select_and_icmp_alt_bad_4(
207-
; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
208-
; CHECK-NEXT: [[D:%.*]] = select i1 [[B]], i32 [[X]], i32 [[Z]]
207+
; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z:%.*]]
208+
; CHECK-NEXT: [[D:%.*]] = select i1 [[B]], i32 [[X:%.*]], i32 [[Z]]
209209
; CHECK-NEXT: ret i32 [[D]]
210210
;
211211
%A = icmp eq i32 %x, %z
@@ -322,3 +322,11 @@ define i32 @select_and_icmp_alt_bad_false_val(i32 %x, i32 %y, i32 %z, i32 %k) {
322322
%D = select i1 %C, i32 %x, i32 %k
323323
ret i32 %D
324324
}
325+
326+
!0 = !{!"function_entry_count", i64 1000}
327+
!1 = !{!"branch_weights", i32 2, i32 3}
328+
329+
;.
330+
; CHECK: [[META0:![0-9]+]] = !{!"function_entry_count", i64 1000}
331+
; CHECK: [[PROF1]] = !{!"branch_weights", i32 2, i32 3}
332+
;.

llvm/test/Transforms/InstCombine/select-or-cmp.ll

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
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=instcombine -S | FileCheck %s
33

44
define i32 @select_or_icmp(i32 %x, i32 %y, i32 %z) {
@@ -114,47 +114,47 @@ define i32 @select_or_icmp_inv(i32 %x, i32 %y, i32 %z) {
114114

115115
; Below used to be negative tests in InstSimplify, but are no more negative cases here
116116

117-
define i32 @select_and_icmp_pred_bad_1(i32 %x, i32 %y, i32 %z) {
117+
define i32 @select_and_icmp_pred_bad_1(i32 %x, i32 %y, i32 %z) !prof !0 {
118118
; CHECK-LABEL: @select_and_icmp_pred_bad_1(
119-
; CHECK-NEXT: [[B_NOT:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
120-
; CHECK-NEXT: [[D:%.*]] = select i1 [[B_NOT]], i32 [[X]], i32 [[Z]]
119+
; CHECK-NEXT: [[B_NOT:%.*]] = icmp eq i32 [[Y:%.*]], [[Z:%.*]]
120+
; CHECK-NEXT: [[D:%.*]] = select i1 [[B_NOT]], i32 [[X:%.*]], i32 [[Z]], !prof [[PROF1:![0-9]+]]
121121
; CHECK-NEXT: ret i32 [[D]]
122122
;
123123
%A = icmp eq i32 %x, %z
124124
%B = icmp ne i32 %y, %z
125125
%C = or i1 %A, %B
126-
%D = select i1 %C, i32 %z, i32 %x
126+
%D = select i1 %C, i32 %z, i32 %x, !prof !1
127127
ret i32 %D
128128
}
129129

130-
define i32 @select_and_icmp_pred_bad_2(i32 %x, i32 %y, i32 %z) {
130+
define i32 @select_and_icmp_pred_bad_2(i32 %x, i32 %y, i32 %z) !prof !0 {
131131
; CHECK-LABEL: @select_and_icmp_pred_bad_2(
132-
; CHECK-NEXT: ret i32 [[Z]]
132+
; CHECK-NEXT: ret i32 [[Z:%.*]]
133133
;
134134
%A = icmp ne i32 %x, %z
135135
%B = icmp eq i32 %y, %z
136136
%C = or i1 %A, %B
137-
%D = select i1 %C, i32 %z, i32 %x
137+
%D = select i1 %C, i32 %z, i32 %x, !prof !1
138138
ret i32 %D
139139
}
140140

141-
define i32 @select_and_icmp_pred_bad_3(i32 %x, i32 %y, i32 %z) {
141+
define i32 @select_and_icmp_pred_bad_3(i32 %x, i32 %y, i32 %z) !prof !0 {
142142
; CHECK-LABEL: @select_and_icmp_pred_bad_3(
143-
; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
144-
; CHECK-NEXT: [[D:%.*]] = select i1 [[B]], i32 [[Z]], i32 [[X]]
143+
; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z:%.*]]
144+
; CHECK-NEXT: [[D:%.*]] = select i1 [[B]], i32 [[Z]], i32 [[X:%.*]], !prof [[PROF2:![0-9]+]]
145145
; CHECK-NEXT: ret i32 [[D]]
146146
;
147147
%A = icmp eq i32 %x, %z
148148
%B = icmp eq i32 %y, %z
149149
%C = or i1 %A, %B
150-
%D = select i1 %C, i32 %z, i32 %x
150+
%D = select i1 %C, i32 %z, i32 %x, !prof !1
151151
ret i32 %D
152152
}
153153

154154
define i32 @select_and_icmp_pred_bad_4(i32 %x, i32 %y, i32 %z) {
155155
; CHECK-LABEL: @select_and_icmp_pred_bad_4(
156-
; CHECK-NEXT: [[B_NOT:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
157-
; CHECK-NEXT: [[D:%.*]] = select i1 [[B_NOT]], i32 [[X]], i32 [[Z]]
156+
; CHECK-NEXT: [[B_NOT:%.*]] = icmp eq i32 [[Y:%.*]], [[Z:%.*]]
157+
; CHECK-NEXT: [[D:%.*]] = select i1 [[B_NOT]], i32 [[X:%.*]], i32 [[Z]]
158158
; CHECK-NEXT: ret i32 [[D]]
159159
;
160160
%A = icmp ne i32 %x, %z
@@ -166,8 +166,8 @@ define i32 @select_and_icmp_pred_bad_4(i32 %x, i32 %y, i32 %z) {
166166

167167
define i32 @select_or_icmp_alt_bad_1(i32 %x, i32 %y, i32 %z) {
168168
; CHECK-LABEL: @select_or_icmp_alt_bad_1(
169-
; CHECK-NEXT: [[B_NOT:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
170-
; CHECK-NEXT: [[D:%.*]] = select i1 [[B_NOT]], i32 [[Z]], i32 [[X]]
169+
; CHECK-NEXT: [[B_NOT:%.*]] = icmp eq i32 [[Y:%.*]], [[Z:%.*]]
170+
; CHECK-NEXT: [[D:%.*]] = select i1 [[B_NOT]], i32 [[Z]], i32 [[X:%.*]]
171171
; CHECK-NEXT: ret i32 [[D]]
172172
;
173173
%A = icmp eq i32 %x, %z
@@ -179,7 +179,7 @@ define i32 @select_or_icmp_alt_bad_1(i32 %x, i32 %y, i32 %z) {
179179

180180
define i32 @select_or_icmp_alt_bad_2(i32 %x, i32 %y, i32 %z) {
181181
; CHECK-LABEL: @select_or_icmp_alt_bad_2(
182-
; CHECK-NEXT: ret i32 [[X]]
182+
; CHECK-NEXT: ret i32 [[X:%.*]]
183183
;
184184
%A = icmp ne i32 %x, %z
185185
%B = icmp eq i32 %y, %z
@@ -190,8 +190,8 @@ define i32 @select_or_icmp_alt_bad_2(i32 %x, i32 %y, i32 %z) {
190190

191191
define i32 @select_or_icmp_alt_bad_3(i32 %x, i32 %y, i32 %z) {
192192
; CHECK-LABEL: @select_or_icmp_alt_bad_3(
193-
; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
194-
; CHECK-NEXT: [[D:%.*]] = select i1 [[B]], i32 [[X]], i32 [[Z]]
193+
; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z:%.*]]
194+
; CHECK-NEXT: [[D:%.*]] = select i1 [[B]], i32 [[X:%.*]], i32 [[Z]]
195195
; CHECK-NEXT: ret i32 [[D]]
196196
;
197197
%A = icmp eq i32 %x, %z
@@ -203,8 +203,8 @@ define i32 @select_or_icmp_alt_bad_3(i32 %x, i32 %y, i32 %z) {
203203

204204
define i32 @select_or_icmp_alt_bad_4(i32 %x, i32 %y, i32 %z) {
205205
; CHECK-LABEL: @select_or_icmp_alt_bad_4(
206-
; CHECK-NEXT: [[B_NOT:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]]
207-
; CHECK-NEXT: [[D:%.*]] = select i1 [[B_NOT]], i32 [[Z]], i32 [[X]]
206+
; CHECK-NEXT: [[B_NOT:%.*]] = icmp eq i32 [[Y:%.*]], [[Z:%.*]]
207+
; CHECK-NEXT: [[D:%.*]] = select i1 [[B_NOT]], i32 [[Z]], i32 [[X:%.*]]
208208
; CHECK-NEXT: ret i32 [[D]]
209209
;
210210
%A = icmp ne i32 %x, %z
@@ -321,3 +321,11 @@ define i32 @select_or_icmp_alt_bad_false_val(i32 %x, i32 %y, i32 %z, i32 %k) {
321321
%D = select i1 %C, i32 %x, i32 %k
322322
ret i32 %D
323323
}
324+
325+
!0 = !{!"function_entry_count", i64 1000}
326+
!1 = !{!"branch_weights", i32 2, i32 3}
327+
;.
328+
; CHECK: [[META0:![0-9]+]] = !{!"function_entry_count", i64 1000}
329+
; CHECK: [[PROF1]] = !{!"branch_weights", i32 3, i32 2}
330+
; CHECK: [[PROF2]] = !{!"branch_weights", i32 2, i32 3}
331+
;.

0 commit comments

Comments
 (0)