Skip to content

Commit b2659ca

Browse files
authored
[InstCombine] Propagate flags in foldSelectICmpAndBinOp (#127437)
It is always safe to add poison-generating flags for `BinOp Y, Identity`. Proof: https://alive2.llvm.org/ce/z/8BLEpq and https://alive2.llvm.org/ce/z/584Bb4 Then we can propagate flags from one of the arms: ``` select Cond, Y, (BinOp flags Y, Z) -> select Cond, (BinOp flags Y, Identity), (BinOp flags Y, Z) -> BinOp flags Y, (select Cond, Identity, Z) ``` This patch is proposed to avoid information loss caused by #127390.
1 parent 2207e3e commit b2659ca

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -829,7 +829,10 @@ static Value *foldSelectICmpAndBinOp(const ICmpInst *IC, Value *TrueVal,
829829
if (NeedXor)
830830
V = Builder.CreateXor(V, *C2);
831831

832-
return Builder.CreateBinOp(BinOp->getOpcode(), Y, V);
832+
auto *Res = Builder.CreateBinOp(BinOp->getOpcode(), Y, V);
833+
if (auto *BO = dyn_cast<BinaryOperator>(Res))
834+
BO->copyIRFlags(BinOp);
835+
return Res;
833836
}
834837

835838
/// Canonicalize a set or clear of a masked set of constant bits to

llvm/test/Transforms/InstCombine/select-with-bitwise-ops.ll

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,34 @@ define i32 @select_icmp_eq_and_1_0_or_2(i32 %x, i32 %y) {
2020
ret i32 %select
2121
}
2222

23+
define i32 @select_icmp_eq_and_1_0_or_2_disjoint(i32 %x, i32 %y) {
24+
; CHECK-LABEL: @select_icmp_eq_and_1_0_or_2_disjoint(
25+
; CHECK-NEXT: [[AND:%.*]] = shl i32 [[X:%.*]], 1
26+
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[AND]], 2
27+
; CHECK-NEXT: [[SELECT:%.*]] = or disjoint i32 [[Y:%.*]], [[TMP1]]
28+
; CHECK-NEXT: ret i32 [[SELECT]]
29+
;
30+
%and = and i32 %x, 1
31+
%cmp = icmp eq i32 %and, 0
32+
%or = or disjoint i32 %y, 2
33+
%select = select i1 %cmp, i32 %y, i32 %or
34+
ret i32 %select
35+
}
36+
37+
define i32 @select_icmp_eq_and_1_0_add_2_nsw_nuw(i32 %x, i32 %y) {
38+
; CHECK-LABEL: @select_icmp_eq_and_1_0_add_2_nsw_nuw(
39+
; CHECK-NEXT: [[AND:%.*]] = shl i32 [[X:%.*]], 1
40+
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[AND]], 2
41+
; CHECK-NEXT: [[SELECT:%.*]] = add nuw nsw i32 [[Y:%.*]], [[TMP1]]
42+
; CHECK-NEXT: ret i32 [[SELECT]]
43+
;
44+
%and = and i32 %x, 1
45+
%cmp = icmp eq i32 %and, 0
46+
%or = add nsw nuw i32 %y, 2
47+
%select = select i1 %cmp, i32 %y, i32 %or
48+
ret i32 %select
49+
}
50+
2351
define <2 x i32> @select_icmp_eq_and_1_0_or_2_vec(<2 x i32> %x, <2 x i32> %y) {
2452
; CHECK-LABEL: @select_icmp_eq_and_1_0_or_2_vec(
2553
; CHECK-NEXT: [[AND:%.*]] = shl <2 x i32> [[X:%.*]], splat (i32 1)
@@ -1696,6 +1724,20 @@ define i8 @select_icmp_eq_and_1_0_lshr_fv(i8 %x, i8 %y) {
16961724
ret i8 %select
16971725
}
16981726

1727+
define i8 @select_icmp_eq_and_1_0_lshr_exact_fv(i8 %x, i8 %y) {
1728+
; CHECK-LABEL: @select_icmp_eq_and_1_0_lshr_exact_fv(
1729+
; CHECK-NEXT: [[AND:%.*]] = shl i8 [[X:%.*]], 1
1730+
; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[AND]], 2
1731+
; CHECK-NEXT: [[SELECT:%.*]] = lshr exact i8 [[Y:%.*]], [[TMP1]]
1732+
; CHECK-NEXT: ret i8 [[SELECT]]
1733+
;
1734+
%and = and i8 %x, 1
1735+
%cmp = icmp eq i8 %and, 0
1736+
%blshr = lshr exact i8 %y, 2
1737+
%select = select i1 %cmp, i8 %y, i8 %blshr
1738+
ret i8 %select
1739+
}
1740+
16991741
define i8 @select_icmp_eq_and_1_0_lshr_tv(i8 %x, i8 %y) {
17001742
; CHECK-LABEL: @select_icmp_eq_and_1_0_lshr_tv(
17011743
; CHECK-NEXT: [[AND:%.*]] = shl i8 [[X:%.*]], 1

0 commit comments

Comments
 (0)