[llvm] 5354a21 - [InstCombine] fold shift+trunc signbit check

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 12 13:26:00 PDT 2021


Author: Sanjay Patel
Date: 2021-04-12T16:19:43-04:00
New Revision: 5354a213a0e309f1bfd8d80c5041a559608d7968

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

LOG: [InstCombine] fold shift+trunc signbit check

https://alive2.llvm.org/ce/z/6vQvrP

This solves:
https://llvm.org/PR49866

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
    llvm/test/Transforms/InstCombine/compare-signs.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 30048d1232cbf..1474830843957 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -1523,11 +1523,11 @@ Instruction *InstCombinerImpl::foldICmpTruncConstant(ICmpInst &Cmp,
                           ConstantInt::get(V->getType(), 1));
   }
 
+  unsigned DstBits = Trunc->getType()->getScalarSizeInBits(),
+           SrcBits = X->getType()->getScalarSizeInBits();
   if (Cmp.isEquality() && Trunc->hasOneUse()) {
     // Simplify icmp eq (trunc x to i8), 42 -> icmp eq x, 42|highbits if all
     // of the high bits truncated out of x are known.
-    unsigned DstBits = Trunc->getType()->getScalarSizeInBits(),
-             SrcBits = X->getType()->getScalarSizeInBits();
     KnownBits Known = computeKnownBits(X, 0, &Cmp);
 
     // If all the high bits are known, we can do this xform.
@@ -1539,6 +1539,22 @@ Instruction *InstCombinerImpl::foldICmpTruncConstant(ICmpInst &Cmp,
     }
   }
 
+  // Look through truncated right-shift of the sign-bit for a sign-bit check:
+  // trunc iN (ShOp >> ShAmtC) to i[N - ShAmtC] < 0  --> ShOp <  0
+  // trunc iN (ShOp >> ShAmtC) to i[N - ShAmtC] > -1 --> ShOp > -1
+  Value *ShOp;
+  const APInt *ShAmtC;
+  bool TrueIfSigned;
+  if (isSignBitCheck(Pred, C, TrueIfSigned) &&
+      match(X, m_Shr(m_Value(ShOp), m_APInt(ShAmtC))) &&
+      DstBits == SrcBits - ShAmtC->getZExtValue()) {
+    return TrueIfSigned
+               ? new ICmpInst(ICmpInst::ICMP_SLT, ShOp,
+                              ConstantInt::getNullValue(X->getType()))
+               : new ICmpInst(ICmpInst::ICMP_SGT, ShOp,
+                              ConstantInt::getAllOnesValue(X->getType()));
+  }
+
   return nullptr;
 }
 

diff  --git a/llvm/test/Transforms/InstCombine/compare-signs.ll b/llvm/test/Transforms/InstCombine/compare-signs.ll
index 8be5ee08bf406..cac253c587be8 100644
--- a/llvm/test/Transforms/InstCombine/compare-signs.ll
+++ b/llvm/test/Transforms/InstCombine/compare-signs.ll
@@ -152,9 +152,7 @@ define <2 x i1> @test4c_vec(<2 x i64> %a) {
 
 define i1 @shift_trunc_signbit_test(i32 %x) {
 ; CHECK-LABEL: @shift_trunc_signbit_test(
-; CHECK-NEXT:    [[SH:%.*]] = lshr i32 [[X:%.*]], 24
-; CHECK-NEXT:    [[TR:%.*]] = trunc i32 [[SH]] to i8
-; CHECK-NEXT:    [[R:%.*]] = icmp slt i8 [[TR]], 0
+; CHECK-NEXT:    [[R:%.*]] = icmp slt i32 [[X:%.*]], 0
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %sh = lshr i32 %x, 24
@@ -169,7 +167,7 @@ define <2 x i1> @shift_trunc_signbit_test_vec_uses(<2 x i17> %x, <2 x i17>* %p1,
 ; CHECK-NEXT:    store <2 x i17> [[SH]], <2 x i17>* [[P1:%.*]], align 8
 ; CHECK-NEXT:    [[TR:%.*]] = trunc <2 x i17> [[SH]] to <2 x i13>
 ; CHECK-NEXT:    store <2 x i13> [[TR]], <2 x i13>* [[P2:%.*]], align 4
-; CHECK-NEXT:    [[R:%.*]] = icmp sgt <2 x i13> [[TR]], <i13 -1, i13 -1>
+; CHECK-NEXT:    [[R:%.*]] = icmp sgt <2 x i17> [[X]], <i17 -1, i17 -1>
 ; CHECK-NEXT:    ret <2 x i1> [[R]]
 ;
   %sh = lshr <2 x i17> %x, <i17 4, i17 4>
@@ -180,6 +178,8 @@ define <2 x i1> @shift_trunc_signbit_test_vec_uses(<2 x i17> %x, <2 x i17>* %p1,
   ret <2 x i1> %r
 }
 
+; negative test
+
 define i1 @shift_trunc_wrong_shift(i32 %x) {
 ; CHECK-LABEL: @shift_trunc_wrong_shift(
 ; CHECK-NEXT:    [[SH:%.*]] = lshr i32 [[X:%.*]], 23
@@ -193,6 +193,8 @@ define i1 @shift_trunc_wrong_shift(i32 %x) {
   ret i1 %r
 }
 
+; negative test
+
 define i1 @shift_trunc_wrong_cmp(i32 %x) {
 ; CHECK-LABEL: @shift_trunc_wrong_cmp(
 ; CHECK-NEXT:    [[SH:%.*]] = lshr i32 [[X:%.*]], 24


        


More information about the llvm-commits mailing list