[llvm] 7b07c01 - [InstCombine] Support arbitrary const shift amount for `lshr (sext i1 ...)`

Anton Afanasyev via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 15 03:51:47 PDT 2021


Author: Anton Afanasyev
Date: 2021-10-15T13:39:13+03:00
New Revision: 7b07c01351407095d9822592e04b0d8233185584

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

LOG: [InstCombine] Support arbitrary const shift amount for `lshr (sext i1 ...)`

Add lshr (sext i1 X to iN), C --> select (X, -1 >> C, 0) case. This expands
C == N-1 case to arbitrary C.

Fixes PR52078.

Reviewed By: spatel, RKSimon, lebedev.ri

Differential Revision: https://reviews.llvm.org/D111330

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
    llvm/test/Transforms/InstCombine/lshr.ll
    llvm/test/Transforms/PhaseOrdering/X86/pr52078.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index 0f83be53b8750..6f303b645544e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -1067,28 +1067,31 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
       return new ZExtInst(NewLShr, Ty);
     }
 
-    if (match(Op0, m_SExt(m_Value(X))) &&
-        (!Ty->isIntegerTy() || shouldChangeType(Ty, X->getType()))) {
-      // Are we moving the sign bit to the low bit and widening with high zeros?
+    if (match(Op0, m_SExt(m_Value(X)))) {
       unsigned SrcTyBitWidth = X->getType()->getScalarSizeInBits();
-      if (ShAmtC == BitWidth - 1) {
-        // lshr (sext i1 X to iN), N-1 --> zext X to iN
-        if (SrcTyBitWidth == 1)
-          return new ZExtInst(X, Ty);
+      // lshr (sext i1 X to iN), C --> select (X, -1 >> C, 0)
+      if (SrcTyBitWidth == 1) {
+        auto *NewC = ConstantInt::get(
+            Ty, APInt::getLowBitsSet(BitWidth, BitWidth - ShAmtC));
+        return SelectInst::Create(X, NewC, ConstantInt::getNullValue(Ty));
+      }
 
-        // lshr (sext iM X to iN), N-1 --> zext (lshr X, M-1) to iN
-        if (Op0->hasOneUse()) {
+      if ((!Ty->isIntegerTy() || shouldChangeType(Ty, X->getType())) &&
+          Op0->hasOneUse()) {
+        // Are we moving the sign bit to the low bit and widening with high
+        // zeros? lshr (sext iM X to iN), N-1 --> zext (lshr X, M-1) to iN
+        if (ShAmtC == BitWidth - 1) {
           Value *NewLShr = Builder.CreateLShr(X, SrcTyBitWidth - 1);
           return new ZExtInst(NewLShr, Ty);
         }
-      }
 
-      // lshr (sext iM X to iN), N-M --> zext (ashr X, min(N-M, M-1)) to iN
-      if (ShAmtC == BitWidth - SrcTyBitWidth && Op0->hasOneUse()) {
-        // The new shift amount can't be more than the narrow source type.
-        unsigned NewShAmt = std::min(ShAmtC, SrcTyBitWidth - 1);
-        Value *AShr = Builder.CreateAShr(X, NewShAmt);
-        return new ZExtInst(AShr, Ty);
+        // lshr (sext iM X to iN), N-M --> zext (ashr X, min(N-M, M-1)) to iN
+        if (ShAmtC == BitWidth - SrcTyBitWidth) {
+          // The new shift amount can't be more than the narrow source type.
+          unsigned NewShAmt = std::min(ShAmtC, SrcTyBitWidth - 1);
+          Value *AShr = Builder.CreateAShr(X, NewShAmt);
+          return new ZExtInst(AShr, Ty);
+        }
       }
     }
 

diff  --git a/llvm/test/Transforms/InstCombine/lshr.ll b/llvm/test/Transforms/InstCombine/lshr.ll
index 89f36e5409260..d524bdb93ea2d 100644
--- a/llvm/test/Transforms/InstCombine/lshr.ll
+++ b/llvm/test/Transforms/InstCombine/lshr.ll
@@ -620,8 +620,7 @@ define i12 @trunc_sandwich_big_sum_shift2_use1(i32 %x) {
 
 define i16 @lshr_sext_i1_to_i16(i1 %a) {
 ; CHECK-LABEL: @lshr_sext_i1_to_i16(
-; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[A:%.*]] to i16
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr i16 [[SEXT]], 4
+; CHECK-NEXT:    [[LSHR:%.*]] = select i1 [[A:%.*]], i16 4095, i16 0
 ; CHECK-NEXT:    ret i16 [[LSHR]]
 ;
   %sext = sext i1 %a to i16
@@ -631,8 +630,7 @@ define i16 @lshr_sext_i1_to_i16(i1 %a) {
 
 define i128 @lshr_sext_i1_to_i128(i1 %a) {
 ; CHECK-LABEL: @lshr_sext_i1_to_i128(
-; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[A:%.*]] to i128
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr i128 [[SEXT]], 42
+; CHECK-NEXT:    [[LSHR:%.*]] = select i1 [[A:%.*]], i128 77371252455336267181195263, i128 0
 ; CHECK-NEXT:    ret i128 [[LSHR]]
 ;
   %sext = sext i1 %a to i128
@@ -644,7 +642,7 @@ define i32 @lshr_sext_i1_to_i32_use(i1 %a) {
 ; CHECK-LABEL: @lshr_sext_i1_to_i32_use(
 ; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[A:%.*]] to i32
 ; CHECK-NEXT:    call void @use(i32 [[SEXT]])
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 [[SEXT]], 14
+; CHECK-NEXT:    [[LSHR:%.*]] = select i1 [[A]], i32 262143, i32 0
 ; CHECK-NEXT:    ret i32 [[LSHR]]
 ;
   %sext = sext i1 %a to i32
@@ -657,7 +655,7 @@ define <3 x i14> @lshr_sext_i1_to_i14_splat_vec_use1(<3 x i1> %a) {
 ; CHECK-LABEL: @lshr_sext_i1_to_i14_splat_vec_use1(
 ; CHECK-NEXT:    [[SEXT:%.*]] = sext <3 x i1> [[A:%.*]] to <3 x i14>
 ; CHECK-NEXT:    call void @usevec(<3 x i14> [[SEXT]])
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr <3 x i14> [[SEXT]], <i14 4, i14 4, i14 4>
+; CHECK-NEXT:    [[LSHR:%.*]] = select <3 x i1> [[A]], <3 x i14> <i14 1023, i14 1023, i14 1023>, <3 x i14> zeroinitializer
 ; CHECK-NEXT:    ret <3 x i14> [[LSHR]]
 ;
   %sext = sext <3 x i1> %a to <3 x i14>

diff  --git a/llvm/test/Transforms/PhaseOrdering/X86/pr52078.ll b/llvm/test/Transforms/PhaseOrdering/X86/pr52078.ll
index 2fbfbca7ebe39..388d5718115d7 100644
--- a/llvm/test/Transforms/PhaseOrdering/X86/pr52078.ll
+++ b/llvm/test/Transforms/PhaseOrdering/X86/pr52078.ll
@@ -16,8 +16,7 @@ define i16 @foo(i1 %a) {
 ; IC-NEXT:    ret i16 [[TRUNC]]
 ;
 ; AIC_AND_IC-LABEL: @foo(
-; AIC_AND_IC-NEXT:    [[SEXT:%.*]] = sext i1 [[A:%.*]] to i16
-; AIC_AND_IC-NEXT:    [[LSHR:%.*]] = lshr i16 [[SEXT]], 1
+; AIC_AND_IC-NEXT:    [[LSHR:%.*]] = select i1 [[A:%.*]], i16 32767, i16 0
 ; AIC_AND_IC-NEXT:    ret i16 [[LSHR]]
 ;
   %sext = sext i1 %a to i16
@@ -29,18 +28,15 @@ define i16 @foo(i1 %a) {
 
 define i16 @foo2(i1 %a) {
 ; CHECK-LABEL: @foo2(
-; CHECK-NEXT:    [[S:%.*]] = sext i1 [[A:%.*]] to i16
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr i16 [[S]], 1
+; CHECK-NEXT:    [[LSHR:%.*]] = select i1 [[A:%.*]], i16 32767, i16 0
 ; CHECK-NEXT:    ret i16 [[LSHR]]
 ;
 ; IC-LABEL: @foo2(
-; IC-NEXT:    [[S:%.*]] = sext i1 [[A:%.*]] to i16
-; IC-NEXT:    [[LSHR:%.*]] = lshr i16 [[S]], 1
+; IC-NEXT:    [[LSHR:%.*]] = select i1 [[A:%.*]], i16 32767, i16 0
 ; IC-NEXT:    ret i16 [[LSHR]]
 ;
 ; AIC_AND_IC-LABEL: @foo2(
-; AIC_AND_IC-NEXT:    [[S:%.*]] = sext i1 [[A:%.*]] to i16
-; AIC_AND_IC-NEXT:    [[LSHR:%.*]] = lshr i16 [[S]], 1
+; AIC_AND_IC-NEXT:    [[LSHR:%.*]] = select i1 [[A:%.*]], i16 32767, i16 0
 ; AIC_AND_IC-NEXT:    ret i16 [[LSHR]]
 ;
   %s = sext i1 %a to i16


        


More information about the llvm-commits mailing list