[llvm] b5a9361 - [InstCombine] canonicalize zext-and-of-bool compare to narrow and

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 29 09:03:00 PDT 2022


Author: Sanjay Patel
Date: 2022-07-29T12:02:54-04:00
New Revision: b5a9361c90ca43c715780ab4f7422fbc9d3a067b

URL: https://github.com/llvm/llvm-project/commit/b5a9361c90ca43c715780ab4f7422fbc9d3a067b
DIFF: https://github.com/llvm/llvm-project/commit/b5a9361c90ca43c715780ab4f7422fbc9d3a067b.diff

LOG: [InstCombine] canonicalize zext-and-of-bool compare to narrow and

https://alive2.llvm.org/ce/z/3jYbEH

We should choose one of these forms, and the option that uses
the narrow type allows the motivating example from issue #56294
to reduce. In the best case (no 'not' needed and 'trunc' remains),
this does remove an instruction.

Note that there is what looks like a regression because there
is an existing canonicalization that turns trunc into and+icmp.
That is a long-standing transform, and I'm not sure what effect
reversing it would have.

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
    llvm/test/Transforms/InstCombine/and-xor-or.ll
    llvm/test/Transforms/InstCombine/icmp.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index c7921109f910..b61567a77323 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -1904,6 +1904,19 @@ Instruction *InstCombinerImpl::foldICmpAndConstant(ICmpInst &Cmp,
     return new ICmpInst(NewPred, X, SubOne(cast<Constant>(Cmp.getOperand(1))));
   }
 
+  // ((zext i1 X) & Y) == 0 --> !((trunc Y) & X)
+  // ((zext i1 X) & Y) != 0 -->  ((trunc Y) & X)
+  if (match(And, m_OneUse(m_c_And(m_OneUse(m_ZExt(m_Value(X))), m_Value(Y)))) &&
+      C.isZero() && X->getType()->isIntOrIntVectorTy(1)) {
+    Value *TruncY = Builder.CreateTrunc(Y, X->getType());
+    if (Pred == CmpInst::ICMP_EQ) {
+      Value *And = Builder.CreateAnd(TruncY, X);
+      return BinaryOperator::CreateNot(And);
+    }
+    assert(Pred == CmpInst::ICMP_NE && "Unexpected predicate");
+    return BinaryOperator::CreateAnd(TruncY, X);
+  }
+
   return nullptr;
 }
 

diff  --git a/llvm/test/Transforms/InstCombine/and-xor-or.ll b/llvm/test/Transforms/InstCombine/and-xor-or.ll
index 592e61fd58c4..6a70fd9cd4b9 100644
--- a/llvm/test/Transforms/InstCombine/and-xor-or.ll
+++ b/llvm/test/Transforms/InstCombine/and-xor-or.ll
@@ -4345,11 +4345,7 @@ define i32 @or_sext_sext_use1(i8 %x, i4 %y) {
 define i1 @PR56294(i8 %x) {
 ; CHECK-LABEL: define {{[^@]+}}@PR56294
 ; CHECK-SAME: (i8 [[X:%.*]]) {
-; CHECK-NEXT:    [[T2:%.*]] = icmp eq i8 [[X]], 2
-; CHECK-NEXT:    [[TMP1:%.*]] = zext i1 [[T2]] to i8
-; CHECK-NEXT:    [[TMP2:%.*]] = and i8 [[TMP1]], [[X]]
-; CHECK-NEXT:    [[T7:%.*]] = icmp ne i8 [[TMP2]], 0
-; CHECK-NEXT:    ret i1 [[T7]]
+; CHECK-NEXT:    ret i1 false
 ;
   %t2 = icmp eq i8 %x, 2
   %t3 = and i8 %x, 1

diff  --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll
index 9c73435025ed..35c85b7072be 100644
--- a/llvm/test/Transforms/InstCombine/icmp.ll
+++ b/llvm/test/Transforms/InstCombine/icmp.ll
@@ -4113,9 +4113,10 @@ define i1 @signbit_true_logic_uses_commute(i64 %x) {
 
 define i1 @zext_bool_and_eq0(i1 %x, i8 %y) {
 ; CHECK-LABEL: @zext_bool_and_eq0(
-; CHECK-NEXT:    [[ZX:%.*]] = zext i1 [[X:%.*]] to i8
-; CHECK-NEXT:    [[A:%.*]] = and i8 [[ZX]], [[Y:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[A]], 0
+; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[Y:%.*]], 1
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i8 [[TMP1]], 0
+; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP2]], [[X:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = xor i1 [[TMP3]], true
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %zx = zext i1 %x to i8
@@ -4126,9 +4127,9 @@ define i1 @zext_bool_and_eq0(i1 %x, i8 %y) {
 
 define <2 x i1> @zext_bool_and_eq0_commute(<2 x i1> %x, <2 x i8> %p) {
 ; CHECK-LABEL: @zext_bool_and_eq0_commute(
-; CHECK-NEXT:    [[ZX:%.*]] = zext <2 x i1> [[X:%.*]] to <2 x i8>
-; CHECK-NEXT:    [[A:%.*]] = and <2 x i8> [[ZX]], [[P:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = icmp eq <2 x i8> [[A]], zeroinitializer
+; CHECK-NEXT:    [[TMP1:%.*]] = trunc <2 x i8> [[P:%.*]] to <2 x i1>
+; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i1> [[TMP1]], [[X:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = xor <2 x i1> [[TMP2]], <i1 true, i1 true>
 ; CHECK-NEXT:    ret <2 x i1> [[R]]
 ;
   %y = mul <2 x i8> %p, %p ; thwart complexity-based canonicalization
@@ -4140,9 +4141,9 @@ define <2 x i1> @zext_bool_and_eq0_commute(<2 x i1> %x, <2 x i8> %p) {
 
 define i1 @zext_bool_and_ne0(i1 %x, i8 %y) {
 ; CHECK-LABEL: @zext_bool_and_ne0(
-; CHECK-NEXT:    [[ZX:%.*]] = zext i1 [[X:%.*]] to i8
-; CHECK-NEXT:    [[A:%.*]] = and i8 [[ZX]], [[Y:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[A]], 0
+; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[Y:%.*]], 1
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i8 [[TMP1]], 0
+; CHECK-NEXT:    [[R:%.*]] = and i1 [[TMP2]], [[X:%.*]]
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %zx = zext i1 %x to i8
@@ -4151,6 +4152,8 @@ define i1 @zext_bool_and_ne0(i1 %x, i8 %y) {
   ret i1 %r
 }
 
+; TODO: This should transform similarly to eq/ne 0.
+
 define i1 @zext_bool_and_ne1(i1 %x, i8 %y) {
 ; CHECK-LABEL: @zext_bool_and_ne1(
 ; CHECK-NEXT:    [[ZX:%.*]] = zext i1 [[X:%.*]] to i8
@@ -4164,6 +4167,8 @@ define i1 @zext_bool_and_ne1(i1 %x, i8 %y) {
   ret i1 %r
 }
 
+; negative test - wrong logic op
+
 define i1 @zext_bool_or_eq0(i1 %x, i8 %y) {
 ; CHECK-LABEL: @zext_bool_or_eq0(
 ; CHECK-NEXT:    [[ZX:%.*]] = zext i1 [[X:%.*]] to i8
@@ -4177,6 +4182,8 @@ define i1 @zext_bool_or_eq0(i1 %x, i8 %y) {
   ret i1 %r
 }
 
+; negative test - extra use
+
 define i1 @zext_bool_and_eq0_use(i1 %x, i64 %y) {
 ; CHECK-LABEL: @zext_bool_and_eq0_use(
 ; CHECK-NEXT:    [[ZX:%.*]] = zext i1 [[X:%.*]] to i64
@@ -4192,6 +4199,8 @@ define i1 @zext_bool_and_eq0_use(i1 %x, i64 %y) {
   ret i1 %r
 }
 
+; negative test - extra use
+
 define i1 @zext_bool_and_ne0_use(i1 %x, i64 %y) {
 ; CHECK-LABEL: @zext_bool_and_ne0_use(
 ; CHECK-NEXT:    [[ZX:%.*]] = zext i1 [[X:%.*]] to i64
@@ -4207,6 +4216,8 @@ define i1 @zext_bool_and_ne0_use(i1 %x, i64 %y) {
   ret i1 %r
 }
 
+; negative test - must zext from i1
+
 define i1 @zext_notbool_and_ne0(i2 %x, i8 %y) {
 ; CHECK-LABEL: @zext_notbool_and_ne0(
 ; CHECK-NEXT:    [[ZX:%.*]] = zext i2 [[X:%.*]] to i8


        


More information about the llvm-commits mailing list