Skip to content

Commit 5207cde

Browse files
committed
[InstCombine] Conditionally fold select i1 into and/or
This patch fixes llvm.org/pr49688 by conditionally folding select i1 into and/or: ``` select cond, cond2, false -> and cond, cond2 ``` This is not safe if cond2 is poison whereas cond isn’t. Unconditionally disabling this transformation affects later pipelines that depend on and/or i1s. To minimize its impact, this patch conservatively checks whether cond2 is an instruction that creates a poison or its operand creates a poison. This approach is similar to what InstSimplify's SimplifyWithOpReplaced is doing. Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D99674
1 parent 6147501 commit 5207cde

File tree

6 files changed

+66
-34
lines changed

6 files changed

+66
-34
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2618,13 +2618,32 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
26182618

26192619
if (SelType->isIntOrIntVectorTy(1) &&
26202620
TrueVal->getType() == CondVal->getType()) {
2621-
if (match(TrueVal, m_One()) &&
2622-
(EnableUnsafeSelectTransform || impliesPoison(FalseVal, CondVal))) {
2621+
auto IsSafeToConvert = [&](Value *OtherVal) {
2622+
if (impliesPoison(OtherVal, CondVal))
2623+
return true;
2624+
2625+
if (!EnableUnsafeSelectTransform)
2626+
return false;
2627+
2628+
// We block this transformation if OtherVal or its operand can create
2629+
// poison. See PR49688
2630+
if (auto *Op = dyn_cast<Operator>(OtherVal)) {
2631+
if (canCreatePoison(Op))
2632+
return false;
2633+
if (propagatesPoison(Op) &&
2634+
llvm::any_of(Op->operand_values(), [](Value *V) {
2635+
return isa<Operator>(V) ? canCreatePoison(cast<Operator>(V))
2636+
: false;
2637+
}))
2638+
return false;
2639+
}
2640+
return true;
2641+
};
2642+
if (match(TrueVal, m_One()) && IsSafeToConvert(FalseVal)) {
26232643
// Change: A = select B, true, C --> A = or B, C
26242644
return BinaryOperator::CreateOr(CondVal, FalseVal);
26252645
}
2626-
if (match(FalseVal, m_Zero()) &&
2627-
(EnableUnsafeSelectTransform || impliesPoison(TrueVal, CondVal))) {
2646+
if (match(FalseVal, m_Zero()) && IsSafeToConvert(TrueVal)) {
26282647
// Change: A = select B, C, false --> A = and B, C
26292648
return BinaryOperator::CreateAnd(CondVal, TrueVal);
26302649
}

llvm/test/Transforms/InstCombine/and-fcmp.ll

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,13 @@ define i1 @PR41069_commute(i1 %z, float %c, float %d) {
7373
ret i1 %r
7474
}
7575

76+
; TODO: this should be fixed using freeze
7677
define i1 @PR41069_commute_logical(i1 %z, float %c, float %d) {
7778
; CHECK-LABEL: @PR41069_commute_logical(
78-
; CHECK-NEXT: [[TMP1:%.*]] = fcmp ninf ord float [[D:%.*]], [[C:%.*]]
79-
; CHECK-NEXT: [[R:%.*]] = and i1 [[TMP1]], [[Z:%.*]]
79+
; CHECK-NEXT: [[ORD1:%.*]] = fcmp ninf ord float [[C:%.*]], 0.000000e+00
80+
; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD1]], [[Z:%.*]]
81+
; CHECK-NEXT: [[ORD2:%.*]] = fcmp reassoc ninf ord float [[D:%.*]], 0.000000e+00
82+
; CHECK-NEXT: [[R:%.*]] = select i1 [[ORD2]], i1 [[AND]], i1 false
8083
; CHECK-NEXT: ret i1 [[R]]
8184
;
8285
%ord1 = fcmp ninf ord float %c, 0.0

llvm/test/Transforms/InstCombine/onehot_merge.ll

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ define i1 @foo1_and_signbit_lshr_without_shifting_signbit_logical(i32 %k, i32 %c
468468
; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0
469469
; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]]
470470
; CHECK-NEXT: [[T4:%.*]] = icmp sgt i32 [[T3]], -1
471-
; CHECK-NEXT: [[OR:%.*]] = or i1 [[T2]], [[T4]]
471+
; CHECK-NEXT: [[OR:%.*]] = select i1 [[T2]], i1 true, i1 [[T4]]
472472
; CHECK-NEXT: ret i1 [[OR]]
473473
;
474474
%t0 = shl i32 1, %c1
@@ -506,7 +506,7 @@ define i1 @foo1_or_signbit_lshr_without_shifting_signbit_logical(i32 %k, i32 %c1
506506
; CHECK-NEXT: [[T2:%.*]] = icmp ne i32 [[T1]], 0
507507
; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]]
508508
; CHECK-NEXT: [[T4:%.*]] = icmp slt i32 [[T3]], 0
509-
; CHECK-NEXT: [[OR:%.*]] = and i1 [[T2]], [[T4]]
509+
; CHECK-NEXT: [[OR:%.*]] = select i1 [[T2]], i1 [[T4]], i1 false
510510
; CHECK-NEXT: ret i1 [[OR]]
511511
;
512512
%t0 = shl i32 1, %c1
@@ -535,13 +535,15 @@ define i1 @foo1_and_signbit_lshr_without_shifting_signbit_both_sides(i32 %k, i32
535535
ret i1 %or
536536
}
537537

538+
; %t2 can be poison where as %t0 isn't; merging these two is unsafe.
538539
define i1 @foo1_and_signbit_lshr_without_shifting_signbit_both_sides_logical(i32 %k, i32 %c1, i32 %c2) {
539540
; CHECK-LABEL: @foo1_and_signbit_lshr_without_shifting_signbit_both_sides_logical(
540541
; CHECK-NEXT: [[T0:%.*]] = shl i32 [[K:%.*]], [[C1:%.*]]
542+
; CHECK-NEXT: [[T1:%.*]] = icmp sgt i32 [[T0]], -1
541543
; CHECK-NEXT: [[T2:%.*]] = shl i32 [[K]], [[C2:%.*]]
542-
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[T0]], [[T2]]
543-
; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[TMP1]], -1
544-
; CHECK-NEXT: ret i1 [[TMP2]]
544+
; CHECK-NEXT: [[T3:%.*]] = icmp sgt i32 [[T2]], -1
545+
; CHECK-NEXT: [[OR:%.*]] = select i1 [[T1]], i1 true, i1 [[T3]]
546+
; CHECK-NEXT: ret i1 [[OR]]
545547
;
546548
%t0 = shl i32 %k, %c1
547549
%t1 = icmp sgt i32 %t0, -1
@@ -567,13 +569,15 @@ define i1 @foo1_or_signbit_lshr_without_shifting_signbit_both_sides(i32 %k, i32
567569
ret i1 %or
568570
}
569571

572+
; %t2 can be poison where as %t0 isn't; merging these two is unsafe.
570573
define i1 @foo1_or_signbit_lshr_without_shifting_signbit_both_sides_logical(i32 %k, i32 %c1, i32 %c2) {
571574
; CHECK-LABEL: @foo1_or_signbit_lshr_without_shifting_signbit_both_sides_logical(
572575
; CHECK-NEXT: [[T0:%.*]] = shl i32 [[K:%.*]], [[C1:%.*]]
576+
; CHECK-NEXT: [[T1:%.*]] = icmp slt i32 [[T0]], 0
573577
; CHECK-NEXT: [[T2:%.*]] = shl i32 [[K]], [[C2:%.*]]
574-
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[T0]], [[T2]]
575-
; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 0
576-
; CHECK-NEXT: ret i1 [[TMP2]]
578+
; CHECK-NEXT: [[T3:%.*]] = icmp slt i32 [[T2]], 0
579+
; CHECK-NEXT: [[OR:%.*]] = select i1 [[T1]], i1 [[T3]], i1 false
580+
; CHECK-NEXT: ret i1 [[OR]]
577581
;
578582
%t0 = shl i32 %k, %c1
579583
%t1 = icmp slt i32 %t0, 0
@@ -886,7 +890,7 @@ define i1 @foo1_and_signbit_lshr_without_shifting_signbit_extra_use_shl1_logical
886890
; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0
887891
; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]]
888892
; CHECK-NEXT: [[T4:%.*]] = icmp sgt i32 [[T3]], -1
889-
; CHECK-NEXT: [[OR:%.*]] = or i1 [[T2]], [[T4]]
893+
; CHECK-NEXT: [[OR:%.*]] = select i1 [[T2]], i1 true, i1 [[T4]]
890894
; CHECK-NEXT: ret i1 [[OR]]
891895
;
892896
%t0 = shl i32 1, %c1
@@ -929,7 +933,7 @@ define i1 @foo1_and_signbit_lshr_without_shifting_signbit_extra_use_and_logical(
929933
; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0
930934
; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]]
931935
; CHECK-NEXT: [[T4:%.*]] = icmp sgt i32 [[T3]], -1
932-
; CHECK-NEXT: [[OR:%.*]] = or i1 [[T2]], [[T4]]
936+
; CHECK-NEXT: [[OR:%.*]] = select i1 [[T2]], i1 true, i1 [[T4]]
933937
; CHECK-NEXT: ret i1 [[OR]]
934938
;
935939
%t0 = shl i32 1, %c1
@@ -972,7 +976,7 @@ define i1 @foo1_and_signbit_lshr_without_shifting_signbit_extra_use_cmp1_logical
972976
; CHECK-NEXT: store i1 [[T2]], i1* [[P:%.*]], align 1
973977
; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]]
974978
; CHECK-NEXT: [[T4:%.*]] = icmp sgt i32 [[T3]], -1
975-
; CHECK-NEXT: [[OR:%.*]] = or i1 [[T2]], [[T4]]
979+
; CHECK-NEXT: [[OR:%.*]] = select i1 [[T2]], i1 true, i1 [[T4]]
976980
; CHECK-NEXT: ret i1 [[OR]]
977981
;
978982
%t0 = shl i32 1, %c1
@@ -1015,7 +1019,7 @@ define i1 @foo1_and_signbit_lshr_without_shifting_signbit_extra_use_shl2_logical
10151019
; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]]
10161020
; CHECK-NEXT: store i32 [[T3]], i32* [[P:%.*]], align 4
10171021
; CHECK-NEXT: [[T4:%.*]] = icmp sgt i32 [[T3]], -1
1018-
; CHECK-NEXT: [[OR:%.*]] = or i1 [[T2]], [[T4]]
1022+
; CHECK-NEXT: [[OR:%.*]] = select i1 [[T2]], i1 true, i1 [[T4]]
10191023
; CHECK-NEXT: ret i1 [[OR]]
10201024
;
10211025
%t0 = shl i32 1, %c1
@@ -1058,7 +1062,7 @@ define i1 @foo1_and_signbit_lshr_without_shifting_signbit_extra_use_cmp2_logical
10581062
; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]]
10591063
; CHECK-NEXT: [[T4:%.*]] = icmp sgt i32 [[T3]], -1
10601064
; CHECK-NEXT: store i1 [[T4]], i1* [[P:%.*]], align 1
1061-
; CHECK-NEXT: [[OR:%.*]] = or i1 [[T2]], [[T4]]
1065+
; CHECK-NEXT: [[OR:%.*]] = select i1 [[T2]], i1 true, i1 [[T4]]
10621066
; CHECK-NEXT: ret i1 [[OR]]
10631067
;
10641068
%t0 = shl i32 1, %c1
@@ -1100,7 +1104,7 @@ define i1 @foo1_and_signbit_lshr_without_shifting_signbit_not_pwr2_logical(i32 %
11001104
; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0
11011105
; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]]
11021106
; CHECK-NEXT: [[T4:%.*]] = icmp sgt i32 [[T3]], -1
1103-
; CHECK-NEXT: [[OR:%.*]] = or i1 [[T2]], [[T4]]
1107+
; CHECK-NEXT: [[OR:%.*]] = select i1 [[T2]], i1 true, i1 [[T4]]
11041108
; CHECK-NEXT: ret i1 [[OR]]
11051109
;
11061110
%t0 = shl i32 3, %c1

llvm/test/Transforms/InstCombine/pr49688.ll

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
22
; RUN: opt < %s -instcombine -S | FileCheck %s
33

4+
; %cmp should not vanish
45
define i1 @f(i32 %i1) {
56
; CHECK-LABEL: @f(
67
; CHECK-NEXT: entry:
7-
; CHECK-NEXT: [[SHR:%.*]] = lshr i32 7, [[I1:%.*]]
8-
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SHR]], [[I1]]
9-
; CHECK-NEXT: ret i1 [[TMP0]]
8+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I1:%.*]], 0
9+
; CHECK-NEXT: [[SHR:%.*]] = lshr i32 7, [[I1]]
10+
; CHECK-NEXT: [[CMP4:%.*]] = icmp slt i32 [[SHR]], [[I1]]
11+
; CHECK-NEXT: [[I2:%.*]] = select i1 [[CMP]], i1 true, i1 [[CMP4]]
12+
; CHECK-NEXT: ret i1 [[I2]]
1013
;
1114
entry:
1215
%cmp = icmp slt i32 %i1, 0
@@ -16,11 +19,14 @@ entry:
1619
ret i1 %i2
1720
}
1821

22+
; %cmp should not vanish
1923
define i32 @f2(i32 signext %g, i32 zeroext %h) {
2024
; CHECK-LABEL: @f2(
25+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[G:%.*]], 0
2126
; CHECK-NEXT: [[SHR:%.*]] = lshr i32 7, [[H:%.*]]
22-
; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[SHR]], [[G:%.*]]
23-
; CHECK-NEXT: [[LOR_EXT:%.*]] = zext i1 [[TMP1]] to i32
27+
; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[SHR]], [[G]]
28+
; CHECK-NEXT: [[DOT0:%.*]] = select i1 [[CMP]], i1 true, i1 [[CMP1]]
29+
; CHECK-NEXT: [[LOR_EXT:%.*]] = zext i1 [[DOT0]] to i32
2430
; CHECK-NEXT: ret i32 [[LOR_EXT]]
2531
;
2632
%cmp = icmp slt i32 %g, 0

llvm/test/Transforms/InstCombine/signed-truncation-check.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@ define i1 @oneuse_shl_ashr_logical(i32 %arg) {
606606
; CHECK-NEXT: call void @use32(i32 [[T4]])
607607
; CHECK-NEXT: [[T5:%.*]] = icmp eq i32 [[T4]], [[ARG]]
608608
; CHECK-NEXT: call void @use1(i1 [[T5]])
609-
; CHECK-NEXT: [[T6:%.*]] = and i1 [[T2]], [[T5]]
609+
; CHECK-NEXT: [[T6:%.*]] = select i1 [[T2]], i1 [[T5]], i1 false
610610
; CHECK-NEXT: ret i1 [[T6]]
611611
;
612612
%t1 = trunc i32 %arg to i8

llvm/test/Transforms/InstCombine/widenable-conditions.ll

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ define i1 @test1(i1 %a, i1 %b) {
2020
define i1 @test1_logical(i1 %a, i1 %b) {
2121
; CHECK-LABEL: @test1_logical(
2222
; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition()
23-
; CHECK-NEXT: [[LHS:%.*]] = and i1 [[WC]], [[B:%.*]]
23+
; CHECK-NEXT: [[LHS:%.*]] = select i1 [[B:%.*]], i1 [[WC]], i1 false
2424
; CHECK-NEXT: [[AND:%.*]] = and i1 [[LHS]], [[A:%.*]]
2525
; CHECK-NEXT: ret i1 [[AND]]
2626
;
@@ -49,7 +49,7 @@ define i1 @test1b(i1 %a, i1 %b) {
4949
define i1 @test1b_logical(i1 %a, i1 %b) {
5050
; CHECK-LABEL: @test1b_logical(
5151
; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition()
52-
; CHECK-NEXT: [[LHS:%.*]] = and i1 [[WC]], [[B:%.*]]
52+
; CHECK-NEXT: [[LHS:%.*]] = select i1 [[B:%.*]], i1 [[WC]], i1 false
5353
; CHECK-NEXT: call void @use(i1 [[LHS]])
5454
; CHECK-NEXT: [[AND:%.*]] = and i1 [[LHS]], [[A:%.*]]
5555
; CHECK-NEXT: ret i1 [[AND]]
@@ -87,7 +87,7 @@ define i1 @test1c_logical(i1 %a, i1 %b) {
8787
; CHECK-NEXT: call void @use(i1 [[B:%.*]])
8888
; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition()
8989
; CHECK-NEXT: call void @use(i1 [[WC]])
90-
; CHECK-NEXT: [[LHS:%.*]] = and i1 [[WC]], [[B]]
90+
; CHECK-NEXT: [[LHS:%.*]] = select i1 [[B]], i1 [[WC]], i1 false
9191
; CHECK-NEXT: [[AND:%.*]] = and i1 [[LHS]], [[A]]
9292
; CHECK-NEXT: ret i1 [[AND]]
9393
;
@@ -147,7 +147,7 @@ define i1 @test3_logical(i1 %a, i1 %b, i1 %c) {
147147
; CHECK-LABEL: @test3_logical(
148148
; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition()
149149
; CHECK-NEXT: [[LHS:%.*]] = and i1 [[A:%.*]], [[B:%.*]]
150-
; CHECK-NEXT: [[RHS:%.*]] = and i1 [[WC]], [[C:%.*]]
150+
; CHECK-NEXT: [[RHS:%.*]] = select i1 [[C:%.*]], i1 [[WC]], i1 false
151151
; CHECK-NEXT: [[AND:%.*]] = and i1 [[LHS]], [[RHS]]
152152
; CHECK-NEXT: ret i1 [[AND]]
153153
;
@@ -178,7 +178,7 @@ define i1 @test4_logical(i1 %a, i1 %b, i1 %c) {
178178
; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition()
179179
; CHECK-NEXT: [[LHS:%.*]] = and i1 [[A:%.*]], [[B:%.*]]
180180
; CHECK-NEXT: [[RHS:%.*]] = and i1 [[WC]], [[C:%.*]]
181-
; CHECK-NEXT: [[AND:%.*]] = and i1 [[LHS]], [[RHS]]
181+
; CHECK-NEXT: [[AND:%.*]] = select i1 [[LHS]], i1 [[RHS]], i1 false
182182
; CHECK-NEXT: ret i1 [[AND]]
183183
;
184184
%wc = call i1 @llvm.experimental.widenable.condition()
@@ -225,7 +225,7 @@ define i1 @test6_logical(i1 %a, i1 %b) {
225225
; CHECK-LABEL: @test6_logical(
226226
; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition()
227227
; CHECK-NEXT: [[WC2:%.*]] = call i1 @llvm.experimental.widenable.condition()
228-
; CHECK-NEXT: [[AND:%.*]] = and i1 [[WC]], [[WC2]]
228+
; CHECK-NEXT: [[AND:%.*]] = select i1 [[WC]], i1 [[WC2]], i1 false
229229
; CHECK-NEXT: ret i1 [[AND]]
230230
;
231231
%wc = call i1 @llvm.experimental.widenable.condition()
@@ -254,7 +254,7 @@ define i1 @test7_logical(i1 %a, i1 %b) {
254254
; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition()
255255
; CHECK-NEXT: call void @use(i1 [[WC]])
256256
; CHECK-NEXT: [[WC2:%.*]] = call i1 @llvm.experimental.widenable.condition()
257-
; CHECK-NEXT: [[AND:%.*]] = and i1 [[WC]], [[WC2]]
257+
; CHECK-NEXT: [[AND:%.*]] = select i1 [[WC]], i1 [[WC2]], i1 false
258258
; CHECK-NEXT: ret i1 [[AND]]
259259
;
260260
%wc = call i1 @llvm.experimental.widenable.condition()
@@ -284,7 +284,7 @@ define i1 @test8_logical(i1 %a, i1 %b) {
284284
; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition()
285285
; CHECK-NEXT: [[WC2:%.*]] = call i1 @llvm.experimental.widenable.condition()
286286
; CHECK-NEXT: call void @use(i1 [[WC2]])
287-
; CHECK-NEXT: [[AND:%.*]] = and i1 [[WC]], [[WC2]]
287+
; CHECK-NEXT: [[AND:%.*]] = select i1 [[WC]], i1 [[WC2]], i1 false
288288
; CHECK-NEXT: ret i1 [[AND]]
289289
;
290290
%wc = call i1 @llvm.experimental.widenable.condition()

0 commit comments

Comments
 (0)