[llvm] [InstCombine] Fix Failure to fold (and %x, (sext i1 %m)) -> (select %m, %x, 0) with multiple uses of %m (PR #81409)

via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 16 08:05:48 PST 2024


https://github.com/SahilPatidar updated https://github.com/llvm/llvm-project/pull/81409

>From c745528fa35ab4d585bf931225ed9415229d2624 Mon Sep 17 00:00:00 2001
From: SahilPatidar <patidarsahil at 2001gmail.com>
Date: Sun, 11 Feb 2024 15:10:33 +0530
Subject: [PATCH 1/3] Fix Failure to fold (and %x, (sext i1 %m)) -> (select %m,
 %x, 0) with multiple uses of %m Resolve #81288

---
 .../InstCombine/InstCombineAndOrXor.cpp       |  2 +-
 llvm/test/Transforms/InstCombine/and.ll       | 55 ++++++++++++++++++-
 2 files changed, 54 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 5fd944a859ef09..516af05b4cc531 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2637,7 +2637,7 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
   //       arm may not be reversible due to poison semantics. Is that a good
   //       canonicalization?
   Value *A, *B;
-  if (match(&I, m_c_And(m_OneUse(m_SExt(m_Value(A))), m_Value(B))) &&
+  if (match(&I, m_c_And(m_SExt(m_Value(A)), m_Value(B))) &&
       A->getType()->isIntOrIntVectorTy(1))
     return SelectInst::Create(A, B, Constant::getNullValue(Ty));
 
diff --git a/llvm/test/Transforms/InstCombine/and.ll b/llvm/test/Transforms/InstCombine/and.ll
index 2e37fee07cc47b..ef18452d667e6f 100644
--- a/llvm/test/Transforms/InstCombine/and.ll
+++ b/llvm/test/Transforms/InstCombine/and.ll
@@ -1818,7 +1818,7 @@ define i8 @not_ashr_bitwidth_mask_use2(i8 %x, i8 %y) {
 ; CHECK-NEXT:    [[ISNOTNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1
 ; CHECK-NEXT:    [[NOT:%.*]] = sext i1 [[ISNOTNEG]] to i8
 ; CHECK-NEXT:    call void @use8(i8 [[NOT]])
-; CHECK-NEXT:    [[R:%.*]] = and i8 [[NOT]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[ISNOTNEG]], i8 [[Y:%.*]], i8 0
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %sign = ashr i8 %x, 7
@@ -1925,7 +1925,7 @@ define i16 @invert_signbit_splat_mask_use3(i8 %x, i16 %y) {
 ; CHECK-NEXT:    [[ISNOTNEG:%.*]] = icmp sgt i8 [[X:%.*]], -1
 ; CHECK-NEXT:    [[S:%.*]] = sext i1 [[ISNOTNEG]] to i16
 ; CHECK-NEXT:    call void @use16(i16 [[S]])
-; CHECK-NEXT:    [[R:%.*]] = and i16 [[S]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[ISNOTNEG]], i16 [[Y:%.*]], i16 0
 ; CHECK-NEXT:    ret i16 [[R]]
 ;
   %a = ashr i8 %x, 7
@@ -2768,3 +2768,54 @@ define i32 @add_constant_equal_with_the_top_bit_of_demandedbits_insertpt(i32 %x,
   %and = and i32 %or, 24
   ret i32 %and
 }
+
+define i32 @and_sext_multiuse(i32 %x, i32 %y, i32 %a, i32 %b) {
+; CHECK-LABEL: @and_sext_multiuse(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[ADD:%.*]] = select i1 [[CMP]], i32 [[TMP1]], i32 0
+; CHECK-NEXT:    ret i32 [[ADD]]
+;
+  %cmp = icmp sgt i32 %x, %y
+  %sext = sext i1 %cmp to i32
+  %and1 = and i32 %sext, %a
+  %and2 = and i32 %sext, %b
+  %add = add i32 %and1, %and2
+  ret i32 %add
+}
+
+define <2 x i32> @and_sext_multiuse_with_vector(<2 x i32> %x, <2 x i32> %y, <2 x i32> %a, <2 x i32> %b) {
+; CHECK-LABEL: @and_sext_multiuse_with_vector(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <2 x i32> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add <2 x i32> [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[ADD:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[TMP1]], <2 x i32> zeroinitializer
+; CHECK-NEXT:    ret <2 x i32> [[ADD]]
+;
+  %cmp = icmp sgt <2 x i32> %x, %y
+  %sext = sext <2 x i1> %cmp to <2 x i32>
+  %and1 = and <2 x i32> %a, %sext
+  %and2 = and <2 x i32> %b, %sext
+  %add = add <2 x i32> %and1, %and2
+  ret <2 x i32> %add
+}
+
+define <2 x i32> @and_sext_multiuse_commuted(<2 x i32> %x, <2 x i32> %y, <2 x i32> %a, <2 x i32> %b, <2 x i32> %c, <2 x i32> %d) {
+; CHECK-LABEL: @and_sext_multiuse_commuted(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <2 x i32> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add <2 x i32> [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = add <2 x i32> [[C:%.*]], [[D:%.*]]
+; CHECK-NEXT:    [[TMP3:%.*]] = add <2 x i32> [[TMP1]], [[TMP2]]
+; CHECK-NEXT:    [[ADD3:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[TMP3]], <2 x i32> zeroinitializer
+; CHECK-NEXT:    ret <2 x i32> [[ADD3]]
+;
+  %cmp = icmp sgt <2 x i32> %x, %y
+  %sext = sext <2 x i1> %cmp to <2 x i32>
+  %and1 = and <2 x i32> %sext, %a
+  %and2 = and <2 x i32> %b, %sext
+  %and3 = and <2 x i32> %c, %sext
+  %and4 = and <2 x i32> %sext, %d
+  %add1 = add <2 x i32> %and1, %and2
+  %add2 = add <2 x i32> %and3, %and4
+  %add3 = add <2 x i32> %add1, %add2
+  ret <2 x i32> %add3
+}

>From e52f1c01f7da99b56a47c3257b6b0a8c6c8be2d7 Mon Sep 17 00:00:00 2001
From: SahilPatidar <patidarsahil at 2001gmail.com>
Date: Fri, 16 Feb 2024 11:29:08 +0530
Subject: [PATCH 2/3] Some fixes in test coverage

---
 llvm/test/Transforms/InstCombine/and.ll | 40 ++-----------------------
 1 file changed, 2 insertions(+), 38 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/and.ll b/llvm/test/Transforms/InstCombine/and.ll
index ef18452d667e6f..6bb6b54dada7c0 100644
--- a/llvm/test/Transforms/InstCombine/and.ll
+++ b/llvm/test/Transforms/InstCombine/and.ll
@@ -1811,7 +1811,7 @@ define i8 @not_ashr_bitwidth_mask_use1(i8 %x, i8 %y) {
   ret i8 %r
 }
 
-; negative test - extra use
+; extra use of xor is ok
 
 define i8 @not_ashr_bitwidth_mask_use2(i8 %x, i8 %y) {
 ; CHECK-LABEL: @not_ashr_bitwidth_mask_use2(
@@ -1918,7 +1918,7 @@ define i16 @invert_signbit_splat_mask_use2(i8 %x, i16 %y) {
   ret i16 %r
 }
 
-; negative test - extra use
+; extra use of sext is ok 
 
 define i16 @invert_signbit_splat_mask_use3(i8 %x, i16 %y) {
 ; CHECK-LABEL: @invert_signbit_splat_mask_use3(
@@ -2783,39 +2783,3 @@ define i32 @and_sext_multiuse(i32 %x, i32 %y, i32 %a, i32 %b) {
   %add = add i32 %and1, %and2
   ret i32 %add
 }
-
-define <2 x i32> @and_sext_multiuse_with_vector(<2 x i32> %x, <2 x i32> %y, <2 x i32> %a, <2 x i32> %b) {
-; CHECK-LABEL: @and_sext_multiuse_with_vector(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <2 x i32> [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[TMP1:%.*]] = add <2 x i32> [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT:    [[ADD:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[TMP1]], <2 x i32> zeroinitializer
-; CHECK-NEXT:    ret <2 x i32> [[ADD]]
-;
-  %cmp = icmp sgt <2 x i32> %x, %y
-  %sext = sext <2 x i1> %cmp to <2 x i32>
-  %and1 = and <2 x i32> %a, %sext
-  %and2 = and <2 x i32> %b, %sext
-  %add = add <2 x i32> %and1, %and2
-  ret <2 x i32> %add
-}
-
-define <2 x i32> @and_sext_multiuse_commuted(<2 x i32> %x, <2 x i32> %y, <2 x i32> %a, <2 x i32> %b, <2 x i32> %c, <2 x i32> %d) {
-; CHECK-LABEL: @and_sext_multiuse_commuted(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt <2 x i32> [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[TMP1:%.*]] = add <2 x i32> [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT:    [[TMP2:%.*]] = add <2 x i32> [[C:%.*]], [[D:%.*]]
-; CHECK-NEXT:    [[TMP3:%.*]] = add <2 x i32> [[TMP1]], [[TMP2]]
-; CHECK-NEXT:    [[ADD3:%.*]] = select <2 x i1> [[CMP]], <2 x i32> [[TMP3]], <2 x i32> zeroinitializer
-; CHECK-NEXT:    ret <2 x i32> [[ADD3]]
-;
-  %cmp = icmp sgt <2 x i32> %x, %y
-  %sext = sext <2 x i1> %cmp to <2 x i32>
-  %and1 = and <2 x i32> %sext, %a
-  %and2 = and <2 x i32> %b, %sext
-  %and3 = and <2 x i32> %c, %sext
-  %and4 = and <2 x i32> %sext, %d
-  %add1 = add <2 x i32> %and1, %and2
-  %add2 = add <2 x i32> %and3, %and4
-  %add3 = add <2 x i32> %add1, %add2
-  ret <2 x i32> %add3
-}

>From 70e3b08dfab75b56f9d0a843142352905879819b Mon Sep 17 00:00:00 2001
From: SahilPatidar <patidarsahil at 2001gmail.com>
Date: Fri, 16 Feb 2024 21:35:16 +0530
Subject: [PATCH 3/3] update tests

---
 llvm/test/Transforms/InstCombine/binop-cast.ll            | 8 +++-----
 .../Transforms/InstCombine/sub-ashr-and-to-icmp-select.ll | 2 +-
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/binop-cast.ll b/llvm/test/Transforms/InstCombine/binop-cast.ll
index e3345194d0b328..d521a7d5a2b3a1 100644
--- a/llvm/test/Transforms/InstCombine/binop-cast.ll
+++ b/llvm/test/Transforms/InstCombine/binop-cast.ll
@@ -50,7 +50,7 @@ define i32 @and_sext_to_sel_multi_use(i32 %x, i1 %y) {
 ; CHECK-LABEL: @and_sext_to_sel_multi_use(
 ; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[Y:%.*]] to i32
 ; CHECK-NEXT:    call void @use(i32 [[SEXT]])
-; CHECK-NEXT:    [[R:%.*]] = and i32 [[SEXT]], [[X:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[Y]], i32 [[X:%.*]], i32 0
 ; CHECK-NEXT:    ret i32 [[R]]
 ;
   %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) {
 ; Negative test of and_add_bool_to_select
 define i32 @and_add_bool_to_select_multi_use(i1 %x, i32 %y) {
 ; CHECK-LABEL: @and_add_bool_to_select_multi_use(
-; CHECK-NEXT:    [[NOT_X:%.*]] = xor i1 [[X:%.*]], true
-; CHECK-NEXT:    [[MASK:%.*]] = sext i1 [[NOT_X]] to i32
-; CHECK-NEXT:    [[RES:%.*]] = and i32 [[MASK]], [[Y:%.*]]
-; CHECK-NEXT:    [[RET:%.*]] = add i32 [[RES]], [[MASK]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[Y:%.*]], -1
+; CHECK-NEXT:    [[RET:%.*]] = select i1 [[X:%.*]], i32 0, i32 [[TMP1]]
 ; CHECK-NEXT:    ret i32 [[RET]]
 ;
   %val = zext i1 %x to i32
diff --git a/llvm/test/Transforms/InstCombine/sub-ashr-and-to-icmp-select.ll b/llvm/test/Transforms/InstCombine/sub-ashr-and-to-icmp-select.ll
index 94ab50422c4a11..84f6294c3500f8 100644
--- a/llvm/test/Transforms/InstCombine/sub-ashr-and-to-icmp-select.ll
+++ b/llvm/test/Transforms/InstCombine/sub-ashr-and-to-icmp-select.ll
@@ -163,7 +163,7 @@ define i32 @sub_ashr_and_i32_extra_use_ashr(i32 %x, i32 %y, ptr %p) {
 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    [[SHR:%.*]] = sext i1 [[TMP1]] to i32
 ; CHECK-NEXT:    store i32 [[SHR]], ptr [[P:%.*]], align 4
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[SHR]], [[X]]
+; CHECK-NEXT:    [[AND:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 0
 ; CHECK-NEXT:    ret i32 [[AND]]
 ;
   %sub = sub nsw i32 %y, %x



More information about the llvm-commits mailing list