[llvm] 00808e3 - [InstSimplify] allow vector folds for (Pow2C << X) == NonPow2C

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Sun Nov 8 07:07:39 PST 2020


Author: Sanjay Patel
Date: 2020-11-08T09:52:05-05:00
New Revision: 00808e321c724bd9f2a822bce87fe7fe87376371

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

LOG: [InstSimplify] allow vector folds for (Pow2C << X) == NonPow2C

Existing pre-conditions seem to be correct:
https://rise4fun.com/Alive/lCLB

  Name: non-zero C1
  Pre: !isPowerOf2(C1) && isPowerOf2(C2) && C1 != 0
  %sub = shl i8 C2, %X
  %cmp = icmp eq i8 %sub, C1
  =>
  %cmp = false

  Name: one == C2
  Pre: !isPowerOf2(C1) && isPowerOf2(C2) && C2 == 1
  %sub = shl i8 C2, %X
  %cmp = icmp eq i8 %sub, C1
  =>
  %cmp = false

  Name: nuw
  Pre: !isPowerOf2(C1) && isPowerOf2(C2)
  %sub = shl nuw i8 C2, %X
  %cmp = icmp eq i8 %sub, C1
  =>
  %cmp = false

  Name: nsw
  Pre: !isPowerOf2(C1) && isPowerOf2(C2)
  %sub = shl nsw i8 C2, %X
  %cmp = icmp eq i8 %sub, C1
  =>
  %cmp = false

Added: 
    

Modified: 
    llvm/lib/Analysis/InstructionSimplify.cpp
    llvm/test/Transforms/InstSimplify/compare.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 44de7e9e40c1..813fb6c89863 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -2992,33 +2992,27 @@ static Value *simplifyICmpWithBinOp(CmpInst::Predicate Pred, Value *LHS,
     }
   }
 
-  // handle:
-  //   CI2 << X == CI
-  //   CI2 << X != CI
-  //
-  //   where CI2 is a power of 2 and CI isn't
-  if (auto *CI = dyn_cast<ConstantInt>(RHS)) {
-    const APInt *CI2Val, *CIVal = &CI->getValue();
-    if (LBO && match(LBO, m_Shl(m_APInt(CI2Val), m_Value())) &&
-        CI2Val->isPowerOf2()) {
-      if (!CIVal->isPowerOf2()) {
-        // CI2 << X can equal zero in some circumstances,
-        // this simplification is unsafe if CI is zero.
-        //
-        // We know it is safe if:
-        // - The shift is nsw, we can't shift out the one bit.
-        // - The shift is nuw, we can't shift out the one bit.
-        // - CI2 is one
-        // - CI isn't zero
-        if (Q.IIQ.hasNoSignedWrap(cast<OverflowingBinaryOperator>(LBO)) ||
-            Q.IIQ.hasNoUnsignedWrap(cast<OverflowingBinaryOperator>(LBO)) ||
-            CI2Val->isOneValue() || !CI->isZero()) {
-          if (Pred == ICmpInst::ICMP_EQ)
-            return ConstantInt::getFalse(RHS->getContext());
-          if (Pred == ICmpInst::ICMP_NE)
-            return ConstantInt::getTrue(RHS->getContext());
-        }
-      }
+  //   If C2 is a power-of-2 and C is not:
+  //   (C2 << X) == C --> false
+  //   (C2 << X) != C --> true
+  const APInt *C;
+  if (match(LHS, m_Shl(m_Power2(), m_Value())) &&
+      match(RHS, m_APIntAllowUndef(C)) && !C->isPowerOf2()) {
+    // C2 << X can equal zero in some circumstances.
+    // This simplification might be unsafe if C is zero.
+    //
+    // We know it is safe if:
+    // - The shift is nsw. We can't shift out the one bit.
+    // - The shift is nuw. We can't shift out the one bit.
+    // - C2 is one.
+    // - C isn't zero.
+    if (Q.IIQ.hasNoSignedWrap(cast<OverflowingBinaryOperator>(LBO)) ||
+        Q.IIQ.hasNoUnsignedWrap(cast<OverflowingBinaryOperator>(LBO)) ||
+        match(LHS, m_Shl(m_One(), m_Value())) || !C->isNullValue()) {
+      if (Pred == ICmpInst::ICMP_EQ)
+        return ConstantInt::getFalse(GetCompareTy(RHS));
+      if (Pred == ICmpInst::ICMP_NE)
+        return ConstantInt::getTrue(GetCompareTy(RHS));
     }
   }
 

diff  --git a/llvm/test/Transforms/InstSimplify/compare.ll b/llvm/test/Transforms/InstSimplify/compare.ll
index b31f3383bf79..834b0befac05 100644
--- a/llvm/test/Transforms/InstSimplify/compare.ll
+++ b/llvm/test/Transforms/InstSimplify/compare.ll
@@ -1542,9 +1542,7 @@ define i1 @shl_1_cmp_eq_nonpow2(i32 %x) {
 
 define <2 x i1> @shl_1_cmp_eq_nonpow2_splat(<2 x i32> %x) {
 ; CHECK-LABEL: @shl_1_cmp_eq_nonpow2_splat(
-; CHECK-NEXT:    [[S:%.*]] = shl <2 x i32> <i32 1, i32 1>, [[X:%.*]]
-; CHECK-NEXT:    [[C:%.*]] = icmp eq <2 x i32> [[S]], <i32 31, i32 31>
-; CHECK-NEXT:    ret <2 x i1> [[C]]
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
 ;
   %s = shl <2 x i32> <i32 1, i32 1>, %x
   %c = icmp eq <2 x i32> %s, <i32 31, i32 31>
@@ -1553,9 +1551,7 @@ define <2 x i1> @shl_1_cmp_eq_nonpow2_splat(<2 x i32> %x) {
 
 define <2 x i1> @shl_1_cmp_eq_nonpow2_splat_undef(<2 x i32> %x) {
 ; CHECK-LABEL: @shl_1_cmp_eq_nonpow2_splat_undef(
-; CHECK-NEXT:    [[S:%.*]] = shl <2 x i32> <i32 1, i32 1>, [[X:%.*]]
-; CHECK-NEXT:    [[C:%.*]] = icmp eq <2 x i32> [[S]], <i32 31, i32 undef>
-; CHECK-NEXT:    ret <2 x i1> [[C]]
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
 ;
   %s = shl <2 x i32> <i32 1, i32 1>, %x
   %c = icmp eq <2 x i32> %s, <i32 31, i32 undef>
@@ -1573,9 +1569,7 @@ define i1 @shl_1_cmp_ne_nonpow2(i32 %x) {
 
 define <2 x i1> @shl_1_cmp_ne_nonpow2_splat(<2 x i32> %x) {
 ; CHECK-LABEL: @shl_1_cmp_ne_nonpow2_splat(
-; CHECK-NEXT:    [[S:%.*]] = shl <2 x i32> <i32 1, i32 1>, [[X:%.*]]
-; CHECK-NEXT:    [[C:%.*]] = icmp ne <2 x i32> [[S]], <i32 42, i32 42>
-; CHECK-NEXT:    ret <2 x i1> [[C]]
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
 ;
   %s = shl <2 x i32> <i32 1, i32 1>, %x
   %c = icmp ne <2 x i32> %s, <i32 42, i32 42>
@@ -1584,9 +1578,7 @@ define <2 x i1> @shl_1_cmp_ne_nonpow2_splat(<2 x i32> %x) {
 
 define <2 x i1> @shl_1_cmp_ne_nonpow2_splat_undef(<2 x i32> %x) {
 ; CHECK-LABEL: @shl_1_cmp_ne_nonpow2_splat_undef(
-; CHECK-NEXT:    [[S:%.*]] = shl <2 x i32> <i32 undef, i32 1>, [[X:%.*]]
-; CHECK-NEXT:    [[C:%.*]] = icmp ne <2 x i32> [[S]], <i32 42, i32 undef>
-; CHECK-NEXT:    ret <2 x i1> [[C]]
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
 ;
   %s = shl <2 x i32> <i32 undef, i32 1>, %x
   %c = icmp ne <2 x i32> %s, <i32 42, i32 undef>
@@ -1604,15 +1596,15 @@ define i1 @shl_pow2_cmp_eq_nonpow2(i32 %x) {
 
 define <2 x i1> @shl_pow21_cmp_ne_nonpow2_splat_undef(<2 x i32> %x) {
 ; CHECK-LABEL: @shl_pow21_cmp_ne_nonpow2_splat_undef(
-; CHECK-NEXT:    [[S:%.*]] = shl <2 x i32> <i32 undef, i32 4>, [[X:%.*]]
-; CHECK-NEXT:    [[C:%.*]] = icmp ne <2 x i32> [[S]], <i32 31, i32 undef>
-; CHECK-NEXT:    ret <2 x i1> [[C]]
+; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
 ;
   %s = shl <2 x i32> <i32 undef, i32 4>, %x
   %c = icmp ne <2 x i32> %s, <i32 31, i32 undef>
   ret <2 x i1> %c
 }
 
+; Negative test - overflowing shift could be zero.
+
 define i1 @shl_pow2_cmp_ne_zero(i32 %x) {
 ; CHECK-LABEL: @shl_pow2_cmp_ne_zero(
 ; CHECK-NEXT:    [[S:%.*]] = shl i32 16, [[X:%.*]]
@@ -1624,6 +1616,8 @@ define i1 @shl_pow2_cmp_ne_zero(i32 %x) {
   ret i1 %c
 }
 
+; Negative test - overflowing shift could be zero.
+
 define <2 x i1> @shl_pow2_cmp_ne_zero_splat(<2 x i32> %x) {
 ; CHECK-LABEL: @shl_pow2_cmp_ne_zero_splat(
 ; CHECK-NEXT:    [[S:%.*]] = shl <2 x i32> <i32 16, i32 16>, [[X:%.*]]
@@ -1664,9 +1658,7 @@ define i1 @shl_pow2_cmp_ne_zero_nsw(i32 %x) {
 
 define <2 x i1> @shl_pow2_cmp_eq_zero_nsw_splat_undef(<2 x i32> %x) {
 ; CHECK-LABEL: @shl_pow2_cmp_eq_zero_nsw_splat_undef(
-; CHECK-NEXT:    [[S:%.*]] = shl nsw <2 x i32> <i32 undef, i32 16>, [[X:%.*]]
-; CHECK-NEXT:    [[C:%.*]] = icmp eq <2 x i32> [[S]], <i32 0, i32 undef>
-; CHECK-NEXT:    ret <2 x i1> [[C]]
+; CHECK-NEXT:    ret <2 x i1> zeroinitializer
 ;
   %s = shl nsw <2 x i32> <i32 undef, i32 16>, %x
   %c = icmp eq <2 x i32> %s, <i32 0, i32 undef>


        


More information about the llvm-commits mailing list