[llvm] r322327 - [InstSimplify] fold implied cmp with zero (PR35790)

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 11 15:27:37 PST 2018


Author: spatel
Date: Thu Jan 11 15:27:37 2018
New Revision: 322327

URL: http://llvm.org/viewvc/llvm-project?rev=322327&view=rev
Log:
[InstSimplify] fold implied cmp with zero (PR35790)

This doesn't handle the more complicated case in the bug report yet:
https://bugs.llvm.org/show_bug.cgi?id=35790

For that, we have to match / look through a cast.

Modified:
    llvm/trunk/lib/Analysis/InstructionSimplify.cpp
    llvm/trunk/test/Transforms/InstSimplify/and-or-icmp-zero.ll

Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=322327&r1=322326&r2=322327&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
+++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Thu Jan 11 15:27:37 2018
@@ -1413,6 +1413,42 @@ static Value *simplifyAndOrOfICmpsWithCo
   return nullptr;
 }
 
+static Value *simplifyAndOrOfICmpsWithZero(ICmpInst *Cmp0, ICmpInst *Cmp1,
+                                           bool IsAnd) {
+  ICmpInst::Predicate P0 = Cmp0->getPredicate(), P1 = Cmp1->getPredicate();
+  if (!match(Cmp0->getOperand(1), m_Zero()) ||
+      !match(Cmp1->getOperand(1), m_Zero()) || P0 != P1)
+    return nullptr;
+
+  if ((IsAnd && P0 != ICmpInst::ICMP_NE) || (!IsAnd && P1 != ICmpInst::ICMP_EQ))
+    return nullptr;
+
+  // We have one of:
+  //   or (icmp eq X, 0), (icmp eq Y, 0)
+  //   and (icmp ne X, 0), (icmp ne Y, 0)
+  Value *X = Cmp0->getOperand(0);
+  Value *Y = Cmp1->getOperand(0);
+
+  // If one of the compares is a masked version of a (not) null check, then
+  // that compare implies the other, so we eliminate the other.
+
+  // or (icmp eq X, 0), (icmp eq (and X, ?), 0) --> icmp eq (and X, ?), 0
+  // or (icmp eq X, 0), (icmp eq (and ?, X), 0) --> icmp eq (and ?, X), 0
+  // and (icmp ne X, 0), (icmp ne (and X, ?), 0) --> icmp ne (and X, ?), 0
+  // and (icmp ne X, 0), (icmp ne (and ?, X), 0) --> icmp ne (and ?, X), 0
+  if (match(Y, m_c_And(m_Specific(X), m_Value())))
+    return Cmp1;
+
+  // or (icmp eq (and Y, ?), 0), (icmp eq Y, 0) --> icmp eq (and Y, ?), 0
+  // or (icmp eq (and ?, Y), 0), (icmp eq Y, 0) --> icmp eq (and ?, Y), 0
+  // and (icmp ne (and Y, ?), 0), (icmp ne Y, 0) --> icmp ne (and Y, ?), 0
+  // and (icmp ne (and ?, Y), 0), (icmp ne Y, 0) --> icmp ne (and ?, Y), 0
+  if (match(X, m_c_And(m_Specific(Y), m_Value())))
+    return Cmp0;
+
+  return nullptr;
+}
+
 static Value *simplifyAndOfICmpsWithAdd(ICmpInst *Op0, ICmpInst *Op1) {
   // (icmp (add V, C0), C1) & (icmp V, C0)
   ICmpInst::Predicate Pred0, Pred1;
@@ -1473,6 +1509,9 @@ static Value *simplifyAndOfICmps(ICmpIns
   if (Value *X = simplifyAndOrOfICmpsWithConstants(Op0, Op1, true))
     return X;
 
+  if (Value *X = simplifyAndOrOfICmpsWithZero(Op0, Op1, true))
+    return X;
+
   if (Value *X = simplifyAndOfICmpsWithAdd(Op0, Op1))
     return X;
   if (Value *X = simplifyAndOfICmpsWithAdd(Op1, Op0))
@@ -1541,6 +1580,9 @@ static Value *simplifyOrOfICmps(ICmpInst
   if (Value *X = simplifyAndOrOfICmpsWithConstants(Op0, Op1, false))
     return X;
 
+  if (Value *X = simplifyAndOrOfICmpsWithZero(Op0, Op1, false))
+    return X;
+
   if (Value *X = simplifyOrOfICmpsWithAdd(Op0, Op1))
     return X;
   if (Value *X = simplifyOrOfICmpsWithAdd(Op1, Op0))

Modified: llvm/trunk/test/Transforms/InstSimplify/and-or-icmp-zero.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/and-or-icmp-zero.ll?rev=322327&r1=322326&r2=322327&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/and-or-icmp-zero.ll (original)
+++ llvm/trunk/test/Transforms/InstSimplify/and-or-icmp-zero.ll Thu Jan 11 15:27:37 2018
@@ -8,11 +8,9 @@
 
 define i1 @or_cmps_eq_zero_with_mask_commute1(i64 %x, i64 %y) {
 ; CHECK-LABEL: @or_cmps_eq_zero_with_mask_commute1(
-; CHECK-NEXT:    [[ISNULL:%.*]] = icmp eq i64 %x, 0
 ; CHECK-NEXT:    [[SOMEBITS:%.*]] = and i64 %x, %y
 ; CHECK-NEXT:    [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq i64 [[SOMEBITS]], 0
-; CHECK-NEXT:    [[R:%.*]] = or i1 [[SOMEBITS_ARE_ZERO]], [[ISNULL]]
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 [[SOMEBITS_ARE_ZERO]]
 ;
   %isnull = icmp eq i64 %x, 0
   %somebits = and i64 %x, %y
@@ -25,11 +23,9 @@ define i1 @or_cmps_eq_zero_with_mask_com
 
 define <2 x i1> @or_cmps_eq_zero_with_mask_commute2(<2 x i64> %x, <2 x i64> %y) {
 ; CHECK-LABEL: @or_cmps_eq_zero_with_mask_commute2(
-; CHECK-NEXT:    [[ISNULL:%.*]] = icmp eq <2 x i64> %x, zeroinitializer
 ; CHECK-NEXT:    [[SOMEBITS:%.*]] = and <2 x i64> %x, %y
 ; CHECK-NEXT:    [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq <2 x i64> [[SOMEBITS]], zeroinitializer
-; CHECK-NEXT:    [[R:%.*]] = or <2 x i1> [[ISNULL]], [[SOMEBITS_ARE_ZERO]]
-; CHECK-NEXT:    ret <2 x i1> [[R]]
+; CHECK-NEXT:    ret <2 x i1> [[SOMEBITS_ARE_ZERO]]
 ;
   %isnull = icmp eq <2 x i64> %x, zeroinitializer
   %somebits = and <2 x i64> %x, %y
@@ -42,11 +38,9 @@ define <2 x i1> @or_cmps_eq_zero_with_ma
 
 define i1 @or_cmps_eq_zero_with_mask_commute3(i4 %x, i4 %y) {
 ; CHECK-LABEL: @or_cmps_eq_zero_with_mask_commute3(
-; CHECK-NEXT:    [[ISNULL:%.*]] = icmp eq i4 %x, 0
 ; CHECK-NEXT:    [[SOMEBITS:%.*]] = and i4 %y, %x
 ; CHECK-NEXT:    [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq i4 [[SOMEBITS]], 0
-; CHECK-NEXT:    [[R:%.*]] = or i1 [[SOMEBITS_ARE_ZERO]], [[ISNULL]]
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 [[SOMEBITS_ARE_ZERO]]
 ;
   %isnull = icmp eq i4 %x, 0
   %somebits = and i4 %y, %x
@@ -59,11 +53,9 @@ define i1 @or_cmps_eq_zero_with_mask_com
 
 define <2 x i1> @or_cmps_eq_zero_with_mask_commute4(<2 x i4> %x, <2 x i4> %y) {
 ; CHECK-LABEL: @or_cmps_eq_zero_with_mask_commute4(
-; CHECK-NEXT:    [[ISNULL:%.*]] = icmp eq <2 x i4> %x, zeroinitializer
 ; CHECK-NEXT:    [[SOMEBITS:%.*]] = and <2 x i4> %y, %x
 ; CHECK-NEXT:    [[SOMEBITS_ARE_ZERO:%.*]] = icmp eq <2 x i4> [[SOMEBITS]], zeroinitializer
-; CHECK-NEXT:    [[R:%.*]] = or <2 x i1> [[ISNULL]], [[SOMEBITS_ARE_ZERO]]
-; CHECK-NEXT:    ret <2 x i1> [[R]]
+; CHECK-NEXT:    ret <2 x i1> [[SOMEBITS_ARE_ZERO]]
 ;
   %isnull = icmp eq <2 x i4> %x, zeroinitializer
   %somebits = and <2 x i4> %y, %x
@@ -76,11 +68,9 @@ define <2 x i1> @or_cmps_eq_zero_with_ma
 
 define <3 x i1> @and_cmps_eq_zero_with_mask_commute1(<3 x i4> %x, <3 x i4> %y) {
 ; CHECK-LABEL: @and_cmps_eq_zero_with_mask_commute1(
-; CHECK-NEXT:    [[ISNOTNULL:%.*]] = icmp ne <3 x i4> %x, zeroinitializer
 ; CHECK-NEXT:    [[SOMEBITS:%.*]] = and <3 x i4> %x, %y
 ; CHECK-NEXT:    [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne <3 x i4> [[SOMEBITS]], zeroinitializer
-; CHECK-NEXT:    [[R:%.*]] = and <3 x i1> [[SOMEBITS_ARE_NOT_ZERO]], [[ISNOTNULL]]
-; CHECK-NEXT:    ret <3 x i1> [[R]]
+; CHECK-NEXT:    ret <3 x i1> [[SOMEBITS_ARE_NOT_ZERO]]
 ;
   %isnotnull = icmp ne <3 x i4> %x, zeroinitializer
   %somebits = and <3 x i4> %x, %y
@@ -93,11 +83,9 @@ define <3 x i1> @and_cmps_eq_zero_with_m
 
 define i1 @and_cmps_eq_zero_with_mask_commute2(i4 %x, i4 %y) {
 ; CHECK-LABEL: @and_cmps_eq_zero_with_mask_commute2(
-; CHECK-NEXT:    [[ISNOTNULL:%.*]] = icmp ne i4 %x, 0
 ; CHECK-NEXT:    [[SOMEBITS:%.*]] = and i4 %x, %y
 ; CHECK-NEXT:    [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne i4 [[SOMEBITS]], 0
-; CHECK-NEXT:    [[R:%.*]] = and i1 [[ISNOTNULL]], [[SOMEBITS_ARE_NOT_ZERO]]
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 [[SOMEBITS_ARE_NOT_ZERO]]
 ;
   %isnotnull = icmp ne i4 %x, 0
   %somebits = and i4 %x, %y
@@ -110,11 +98,9 @@ define i1 @and_cmps_eq_zero_with_mask_co
 
 define <3 x i1> @and_cmps_eq_zero_with_mask_commute3(<3 x i64> %x, <3 x i64> %y) {
 ; CHECK-LABEL: @and_cmps_eq_zero_with_mask_commute3(
-; CHECK-NEXT:    [[ISNOTNULL:%.*]] = icmp ne <3 x i64> %x, zeroinitializer
 ; CHECK-NEXT:    [[SOMEBITS:%.*]] = and <3 x i64> %y, %x
 ; CHECK-NEXT:    [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne <3 x i64> [[SOMEBITS]], zeroinitializer
-; CHECK-NEXT:    [[R:%.*]] = and <3 x i1> [[SOMEBITS_ARE_NOT_ZERO]], [[ISNOTNULL]]
-; CHECK-NEXT:    ret <3 x i1> [[R]]
+; CHECK-NEXT:    ret <3 x i1> [[SOMEBITS_ARE_NOT_ZERO]]
 ;
   %isnotnull = icmp ne <3 x i64> %x, zeroinitializer
   %somebits = and <3 x i64> %y, %x
@@ -127,11 +113,9 @@ define <3 x i1> @and_cmps_eq_zero_with_m
 
 define i1 @and_cmps_eq_zero_with_mask_commute4(i64 %x, i64 %y) {
 ; CHECK-LABEL: @and_cmps_eq_zero_with_mask_commute4(
-; CHECK-NEXT:    [[ISNOTNULL:%.*]] = icmp ne i64 %x, 0
 ; CHECK-NEXT:    [[SOMEBITS:%.*]] = and i64 %y, %x
 ; CHECK-NEXT:    [[SOMEBITS_ARE_NOT_ZERO:%.*]] = icmp ne i64 [[SOMEBITS]], 0
-; CHECK-NEXT:    [[R:%.*]] = and i1 [[ISNOTNULL]], [[SOMEBITS_ARE_NOT_ZERO]]
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 [[SOMEBITS_ARE_NOT_ZERO]]
 ;
   %isnotnull = icmp ne i64 %x, 0
   %somebits = and i64 %y, %x




More information about the llvm-commits mailing list