Skip to content

Commit 84576d5

Browse files
alanzhao1aokblast
authored andcommitted
[InstCombine][profcheck] Preserve profile with negated select conditionals (llvm#164342)
If a select instruction is replaced with one whose conditional is the negation of the original, then the replacement's branch weights are the reverse of the original's. Tracking issue: llvm#147390
1 parent c375e2b commit 84576d5

File tree

3 files changed

+51
-19
lines changed

3 files changed

+51
-19
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3455,27 +3455,45 @@ Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) {
34553455
// select a, false, b -> select !a, b, false
34563456
if (match(TrueVal, m_Specific(Zero))) {
34573457
Value *NotCond = Builder.CreateNot(CondVal, "not." + CondVal->getName());
3458-
return SelectInst::Create(NotCond, FalseVal, Zero);
3458+
Instruction *MDFrom = ProfcheckDisableMetadataFixes ? nullptr : &SI;
3459+
SelectInst *NewSI =
3460+
SelectInst::Create(NotCond, FalseVal, Zero, "", nullptr, MDFrom);
3461+
NewSI->swapProfMetadata();
3462+
return NewSI;
34593463
}
34603464
// select a, b, true -> select !a, true, b
34613465
if (match(FalseVal, m_Specific(One))) {
34623466
Value *NotCond = Builder.CreateNot(CondVal, "not." + CondVal->getName());
3463-
return SelectInst::Create(NotCond, One, TrueVal);
3467+
Instruction *MDFrom = ProfcheckDisableMetadataFixes ? nullptr : &SI;
3468+
SelectInst *NewSI =
3469+
SelectInst::Create(NotCond, One, TrueVal, "", nullptr, MDFrom);
3470+
NewSI->swapProfMetadata();
3471+
return NewSI;
34643472
}
34653473

34663474
// DeMorgan in select form: !a && !b --> !(a || b)
34673475
// select !a, !b, false --> not (select a, true, b)
34683476
if (match(&SI, m_LogicalAnd(m_Not(m_Value(A)), m_Not(m_Value(B)))) &&
34693477
(CondVal->hasOneUse() || TrueVal->hasOneUse()) &&
3470-
!match(A, m_ConstantExpr()) && !match(B, m_ConstantExpr()))
3471-
return BinaryOperator::CreateNot(Builder.CreateSelect(A, One, B));
3478+
!match(A, m_ConstantExpr()) && !match(B, m_ConstantExpr())) {
3479+
Instruction *MDFrom = ProfcheckDisableMetadataFixes ? nullptr : &SI;
3480+
SelectInst *NewSI =
3481+
cast<SelectInst>(Builder.CreateSelect(A, One, B, "", MDFrom));
3482+
NewSI->swapProfMetadata();
3483+
return BinaryOperator::CreateNot(NewSI);
3484+
}
34723485

34733486
// DeMorgan in select form: !a || !b --> !(a && b)
34743487
// select !a, true, !b --> not (select a, b, false)
34753488
if (match(&SI, m_LogicalOr(m_Not(m_Value(A)), m_Not(m_Value(B)))) &&
34763489
(CondVal->hasOneUse() || FalseVal->hasOneUse()) &&
3477-
!match(A, m_ConstantExpr()) && !match(B, m_ConstantExpr()))
3478-
return BinaryOperator::CreateNot(Builder.CreateSelect(A, B, Zero));
3490+
!match(A, m_ConstantExpr()) && !match(B, m_ConstantExpr())) {
3491+
Instruction *MDFrom = ProfcheckDisableMetadataFixes ? nullptr : &SI;
3492+
SelectInst *NewSI =
3493+
cast<SelectInst>(Builder.CreateSelect(A, B, Zero, "", MDFrom));
3494+
NewSI->swapProfMetadata();
3495+
return BinaryOperator::CreateNot(NewSI);
3496+
}
34793497

34803498
// select (select a, true, b), true, b -> select a, true, b
34813499
if (match(CondVal, m_Select(m_Value(A), m_One(), m_Value(B))) &&

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

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
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
declare void @use(i1)
55
declare i1 @gen_i1()
66
declare <2 x i1> @gen_v2i1()
77

88
; Should not be converted to "and", which has different poison semantics.
9+
;.
10+
; CHECK: @g1 = external global i16
11+
; CHECK: @g2 = external global i16
12+
;.
913
define i1 @logical_and(i1 %a, i1 %b) {
1014
; CHECK-LABEL: @logical_and(
1115
; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 false
@@ -225,29 +229,29 @@ define i1 @not_not_true(i1 %x, i1 %y) {
225229

226230
; (!x && !y) --> !(x || y)
227231

228-
define i1 @not_not_false(i1 %x, i1 %y) {
232+
define i1 @not_not_false(i1 %x, i1 %y) !prof !0 {
229233
; CHECK-LABEL: @not_not_false(
230-
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[Y:%.*]]
234+
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[Y:%.*]], !prof [[PROF1:![0-9]+]]
231235
; CHECK-NEXT: [[R:%.*]] = xor i1 [[TMP1]], true
232236
; CHECK-NEXT: ret i1 [[R]]
233237
;
234238
%notx = xor i1 %x, true
235239
%noty = xor i1 %y, true
236-
%r = select i1 %notx, i1 %noty, i1 false
240+
%r = select i1 %notx, i1 %noty, i1 false, !prof !1
237241
ret i1 %r
238242
}
239243

240244
; (!x || !y) --> !(x && y)
241245

242-
define i1 @not_true_not(i1 %x, i1 %y) {
246+
define i1 @not_true_not(i1 %x, i1 %y) !prof !0 {
243247
; CHECK-LABEL: @not_true_not(
244-
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i1 [[Y:%.*]], i1 false
248+
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i1 [[Y:%.*]], i1 false, !prof [[PROF1]]
245249
; CHECK-NEXT: [[R:%.*]] = xor i1 [[TMP1]], true
246250
; CHECK-NEXT: ret i1 [[R]]
247251
;
248252
%notx = xor i1 %x, true
249253
%noty = xor i1 %y, true
250-
%r = select i1 %notx, i1 true, i1 %noty
254+
%r = select i1 %notx, i1 true, i1 %noty, !prof !1
251255
ret i1 %r
252256
}
253257

@@ -1348,3 +1352,12 @@ define i8 @test_logical_commuted_and_ne_a_b(i1 %other_cond, i8 %a, i8 %b) {
13481352
%select = select i1 %or.cond, i8 %a, i8 %b
13491353
ret i8 %select
13501354
}
1355+
1356+
!0 = !{!"function_entry_count", i64 1000}
1357+
!1 = !{!"branch_weights", i32 2, i32 3}
1358+
;.
1359+
; CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
1360+
;.
1361+
; CHECK: [[META0:![0-9]+]] = !{!"function_entry_count", i64 1000}
1362+
; CHECK: [[PROF1]] = !{!"branch_weights", i32 3, i32 2}
1363+
;.

llvm/test/Transforms/InstCombine/select-safe-transforms.ll

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,15 @@ define i1 @cond_eq_or_const(i8 %X, i8 %Y) !prof !0 {
5858
ret i1 %res
5959
}
6060

61-
define i1 @xor_and(i1 %c, i32 %X, i32 %Y) {
61+
define i1 @xor_and(i1 %c, i32 %X, i32 %Y) !prof !0 {
6262
; CHECK-LABEL: @xor_and(
6363
; CHECK-NEXT: [[COMP:%.*]] = icmp uge i32 [[X:%.*]], [[Y:%.*]]
6464
; CHECK-NEXT: [[NOT_C:%.*]] = xor i1 [[C:%.*]], true
65-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[NOT_C]], i1 true, i1 [[COMP]]
65+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[NOT_C]], i1 true, i1 [[COMP]], !prof [[PROF2:![0-9]+]]
6666
; CHECK-NEXT: ret i1 [[SEL]]
6767
;
6868
%comp = icmp ult i32 %X, %Y
69-
%sel = select i1 %c, i1 %comp, i1 false
69+
%sel = select i1 %c, i1 %comp, i1 false, !prof !1
7070
%res = xor i1 %sel, true
7171
ret i1 %res
7272
}
@@ -97,15 +97,15 @@ define <2 x i1> @xor_and3(<2 x i1> %c, <2 x i32> %X, <2 x i32> %Y) {
9797
ret <2 x i1> %res
9898
}
9999

100-
define i1 @xor_or(i1 %c, i32 %X, i32 %Y) {
100+
define i1 @xor_or(i1 %c, i32 %X, i32 %Y) !prof !0 {
101101
; CHECK-LABEL: @xor_or(
102102
; CHECK-NEXT: [[COMP:%.*]] = icmp uge i32 [[X:%.*]], [[Y:%.*]]
103103
; CHECK-NEXT: [[NOT_C:%.*]] = xor i1 [[C:%.*]], true
104-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[NOT_C]], i1 [[COMP]], i1 false
104+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[NOT_C]], i1 [[COMP]], i1 false, !prof [[PROF2]]
105105
; CHECK-NEXT: ret i1 [[SEL]]
106106
;
107107
%comp = icmp ult i32 %X, %Y
108-
%sel = select i1 %c, i1 true, i1 %comp
108+
%sel = select i1 %c, i1 true, i1 %comp, !prof !1
109109
%res = xor i1 %sel, true
110110
ret i1 %res
111111
}
@@ -802,4 +802,5 @@ define <2 x i1> @not_logical_and2(i1 %b, <2 x i32> %a) {
802802
;.
803803
; CHECK: [[META0:![0-9]+]] = !{!"function_entry_count", i64 1000}
804804
; CHECK: [[PROF1]] = !{!"branch_weights", i32 2, i32 3}
805+
; CHECK: [[PROF2]] = !{!"branch_weights", i32 3, i32 2}
805806
;.

0 commit comments

Comments
 (0)