Skip to content

Commit 4b483ec

Browse files
authored
[InstCombine] Fix failure to fold (and %x, (sext i1 %m)) -> (select %m, %x, 0) with multiple uses of %m (#81409)
Resolves #81288.
1 parent c310782 commit 4b483ec

File tree

4 files changed

+24
-11
lines changed

4 files changed

+24
-11
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2710,7 +2710,7 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
27102710
// arm may not be reversible due to poison semantics. Is that a good
27112711
// canonicalization?
27122712
Value *A, *B;
2713-
if (match(&I, m_c_And(m_OneUse(m_SExt(m_Value(A))), m_Value(B))) &&
2713+
if (match(&I, m_c_And(m_SExt(m_Value(A)), m_Value(B))) &&
27142714
A->getType()->isIntOrIntVectorTy(1))
27152715
return SelectInst::Create(A, B, Constant::getNullValue(Ty));
27162716

llvm/test/Transforms/InstCombine/and.ll

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1897,14 +1897,14 @@ define i8 @not_ashr_bitwidth_mask_use1(i8 %x, i8 %y) {
18971897
ret i8 %r
18981898
}
18991899

1900-
; negative test - extra use
1900+
; extra use of xor is ok
19011901

19021902
define i8 @not_ashr_bitwidth_mask_use2(i8 %x, i8 %y) {
19031903
; CHECK-LABEL: @not_ashr_bitwidth_mask_use2(
19041904
; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1
19051905
; CHECK-NEXT: [[NOT:%.*]] = sext i1 [[ISNOTNEG]] to i8
19061906
; CHECK-NEXT: call void @use8(i8 [[NOT]])
1907-
; CHECK-NEXT: [[R:%.*]] = and i8 [[NOT]], [[Y:%.*]]
1907+
; CHECK-NEXT: [[R:%.*]] = select i1 [[ISNOTNEG]], i8 [[Y:%.*]], i8 0
19081908
; CHECK-NEXT: ret i8 [[R]]
19091909
;
19101910
%sign = ashr i8 %x, 7
@@ -2004,14 +2004,14 @@ define i16 @invert_signbit_splat_mask_use2(i8 %x, i16 %y) {
20042004
ret i16 %r
20052005
}
20062006

2007-
; negative test - extra use
2007+
; extra use of sext is ok
20082008

20092009
define i16 @invert_signbit_splat_mask_use3(i8 %x, i16 %y) {
20102010
; CHECK-LABEL: @invert_signbit_splat_mask_use3(
20112011
; CHECK-NEXT: [[ISNOTNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1
20122012
; CHECK-NEXT: [[S:%.*]] = sext i1 [[ISNOTNEG]] to i16
20132013
; CHECK-NEXT: call void @use16(i16 [[S]])
2014-
; CHECK-NEXT: [[R:%.*]] = and i16 [[S]], [[Y:%.*]]
2014+
; CHECK-NEXT: [[R:%.*]] = select i1 [[ISNOTNEG]], i16 [[Y:%.*]], i16 0
20152015
; CHECK-NEXT: ret i16 [[R]]
20162016
;
20172017
%a = ashr i8 %x, 7
@@ -2854,3 +2854,18 @@ define i32 @add_constant_equal_with_the_top_bit_of_demandedbits_insertpt(i32 %x,
28542854
%and = and i32 %or, 24
28552855
ret i32 %and
28562856
}
2857+
2858+
define i32 @and_sext_multiuse(i32 %x, i32 %y, i32 %a, i32 %b) {
2859+
; CHECK-LABEL: @and_sext_multiuse(
2860+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]]
2861+
; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
2862+
; CHECK-NEXT: [[ADD:%.*]] = select i1 [[CMP]], i32 [[TMP1]], i32 0
2863+
; CHECK-NEXT: ret i32 [[ADD]]
2864+
;
2865+
%cmp = icmp sgt i32 %x, %y
2866+
%sext = sext i1 %cmp to i32
2867+
%and1 = and i32 %sext, %a
2868+
%and2 = and i32 %sext, %b
2869+
%add = add i32 %and1, %and2
2870+
ret i32 %add
2871+
}

llvm/test/Transforms/InstCombine/binop-cast.ll

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ define i32 @and_sext_to_sel_multi_use(i32 %x, i1 %y) {
5050
; CHECK-LABEL: @and_sext_to_sel_multi_use(
5151
; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[Y:%.*]] to i32
5252
; CHECK-NEXT: call void @use(i32 [[SEXT]])
53-
; CHECK-NEXT: [[R:%.*]] = and i32 [[SEXT]], [[X:%.*]]
53+
; CHECK-NEXT: [[R:%.*]] = select i1 [[Y]], i32 [[X:%.*]], i32 0
5454
; CHECK-NEXT: ret i32 [[R]]
5555
;
5656
%sext = sext i1 %y to i32
@@ -326,10 +326,8 @@ define <2 x i32> @and_add_bool_vec_to_select(<2 x i1> %x, <2 x i32> %y) {
326326
; Negative test of and_add_bool_to_select
327327
define i32 @and_add_bool_to_select_multi_use(i1 %x, i32 %y) {
328328
; CHECK-LABEL: @and_add_bool_to_select_multi_use(
329-
; CHECK-NEXT: [[NOT_X:%.*]] = xor i1 [[X:%.*]], true
330-
; CHECK-NEXT: [[MASK:%.*]] = sext i1 [[NOT_X]] to i32
331-
; CHECK-NEXT: [[RES:%.*]] = and i32 [[MASK]], [[Y:%.*]]
332-
; CHECK-NEXT: [[RET:%.*]] = add i32 [[RES]], [[MASK]]
329+
; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[Y:%.*]], -1
330+
; CHECK-NEXT: [[RET:%.*]] = select i1 [[X:%.*]], i32 0, i32 [[TMP1]]
333331
; CHECK-NEXT: ret i32 [[RET]]
334332
;
335333
%val = zext i1 %x to i32

llvm/test/Transforms/InstCombine/sub-ashr-and-to-icmp-select.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ define i32 @sub_ashr_and_i32_extra_use_ashr(i32 %x, i32 %y, ptr %p) {
163163
; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[Y:%.*]], [[X:%.*]]
164164
; CHECK-NEXT: [[SHR:%.*]] = sext i1 [[TMP1]] to i32
165165
; CHECK-NEXT: store i32 [[SHR]], ptr [[P:%.*]], align 4
166-
; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHR]], [[X]]
166+
; CHECK-NEXT: [[AND:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 0
167167
; CHECK-NEXT: ret i32 [[AND]]
168168
;
169169
%sub = sub nsw i32 %y, %x

0 commit comments

Comments
 (0)