[llvm] a0c3c60 - [InstCombine] fold shift-right-by-constant with shift-right-of-constant operand

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Mon May 30 12:34:15 PDT 2022


Author: Sanjay Patel
Date: 2022-05-30T15:30:01-04:00
New Revision: a0c3c60728ee5bc7d6ca40a5b6e446cde72c6700

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

LOG: [InstCombine] fold shift-right-by-constant with shift-right-of-constant operand

  (C2 >> X) >> C1 --> (C2 >> C1) >> X

The shift-left form of this transform has existed since:
16f18ed7b555bce5163

...but it applies to matching shift right opcodes too:
https://alive2.llvm.org/ce/z/c5eQms

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
    llvm/test/Transforms/InstCombine/and.ll
    llvm/test/Transforms/InstCombine/icmp-and-shift.ll
    llvm/test/Transforms/InstCombine/shift-shift.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index 8d5dbf83b7ea..b25c83a2a962 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -702,10 +702,18 @@ static bool canShiftBinOpWithConstantRHS(BinaryOperator &Shift,
   }
 }
 
-Instruction *InstCombinerImpl::FoldShiftByConstant(Value *Op0, Constant *Op1,
+Instruction *InstCombinerImpl::FoldShiftByConstant(Value *Op0, Constant *C1,
                                                    BinaryOperator &I) {
+  // (C2 << X) << C1 --> (C2 << C1) << X
+  // (C2 >> X) >> C1 --> (C2 >> C1) >> X
+  Constant *C2;
+  Value *X;
+  if (match(Op0, m_BinOp(I.getOpcode(), m_Constant(C2), m_Value(X))))
+    return BinaryOperator::Create(I.getOpcode(),
+                                  ConstantExpr::get(I.getOpcode(), C2, C1), X);
+
   const APInt *Op1C;
-  if (!match(Op1, m_APInt(Op1C)))
+  if (!match(C1, m_APInt(Op1C)))
     return nullptr;
 
   // See if we can propagate this shift into the input, this covers the trivial
@@ -743,10 +751,10 @@ Instruction *InstCombinerImpl::FoldShiftByConstant(Value *Op0, Constant *Op1,
     if (match(Op0BO->getOperand(1), m_APInt(Op0C))) {
       if (canShiftBinOpWithConstantRHS(I, Op0BO)) {
         Constant *NewRHS = ConstantExpr::get(
-            I.getOpcode(), cast<Constant>(Op0BO->getOperand(1)), Op1);
+            I.getOpcode(), cast<Constant>(Op0BO->getOperand(1)), C1);
 
         Value *NewShift =
-            Builder.CreateBinOp(I.getOpcode(), Op0BO->getOperand(0), Op1);
+            Builder.CreateBinOp(I.getOpcode(), Op0BO->getOperand(0), C1);
         NewShift->takeName(Op0BO);
 
         return BinaryOperator::Create(Op0BO->getOpcode(), NewShift, NewRHS);
@@ -772,9 +780,9 @@ Instruction *InstCombinerImpl::FoldShiftByConstant(Value *Op0, Constant *Op1,
         match(TBO->getOperand(1), m_APInt(C)) &&
         canShiftBinOpWithConstantRHS(I, TBO)) {
       Constant *NewRHS = ConstantExpr::get(
-          I.getOpcode(), cast<Constant>(TBO->getOperand(1)), Op1);
+          I.getOpcode(), cast<Constant>(TBO->getOperand(1)), C1);
 
-      Value *NewShift = Builder.CreateBinOp(I.getOpcode(), FalseVal, Op1);
+      Value *NewShift = Builder.CreateBinOp(I.getOpcode(), FalseVal, C1);
       Value *NewOp = Builder.CreateBinOp(TBO->getOpcode(), NewShift, NewRHS);
       return SelectInst::Create(Cond, NewOp, NewShift);
     }
@@ -789,9 +797,9 @@ Instruction *InstCombinerImpl::FoldShiftByConstant(Value *Op0, Constant *Op1,
         match(FBO->getOperand(1), m_APInt(C)) &&
         canShiftBinOpWithConstantRHS(I, FBO)) {
       Constant *NewRHS = ConstantExpr::get(
-          I.getOpcode(), cast<Constant>(FBO->getOperand(1)), Op1);
+          I.getOpcode(), cast<Constant>(FBO->getOperand(1)), C1);
 
-      Value *NewShift = Builder.CreateBinOp(I.getOpcode(), TrueVal, Op1);
+      Value *NewShift = Builder.CreateBinOp(I.getOpcode(), TrueVal, C1);
       Value *NewOp = Builder.CreateBinOp(FBO->getOpcode(), NewShift, NewRHS);
       return SelectInst::Create(Cond, NewShift, NewOp);
     }
@@ -1009,10 +1017,6 @@ Instruction *InstCombinerImpl::visitShl(BinaryOperator &I) {
   if (match(Op1, m_Constant(C1))) {
     Constant *C2;
     Value *X;
-    // (C2 << X) << C1 --> (C2 << C1) << X
-    if (match(Op0, m_Shl(m_Constant(C2), m_Value(X))))
-      return BinaryOperator::CreateShl(ConstantExpr::getShl(C2, C1), X);
-
     // (X * C2) << C1 --> X * (C2 << C1)
     if (match(Op0, m_Mul(m_Value(X), m_Constant(C2))))
       return BinaryOperator::CreateMul(X, ConstantExpr::getShl(C2, C1));

diff  --git a/llvm/test/Transforms/InstCombine/and.ll b/llvm/test/Transforms/InstCombine/and.ll
index c7a63d7fc528..2617ac1eb6de 100644
--- a/llvm/test/Transforms/InstCombine/and.ll
+++ b/llvm/test/Transforms/InstCombine/and.ll
@@ -1699,8 +1699,7 @@ define i16 @shl_lshr_pow2_const_negative_overflow2(i16 %x) {
 
 define i16 @lshr_lshr_pow2_const(i16 %x) {
 ; CHECK-LABEL: @lshr_lshr_pow2_const(
-; CHECK-NEXT:    [[LSHR1:%.*]] = lshr i16 2048, [[X:%.*]]
-; CHECK-NEXT:    [[LSHR2:%.*]] = lshr i16 [[LSHR1]], 6
+; CHECK-NEXT:    [[LSHR2:%.*]] = lshr i16 32, [[X:%.*]]
 ; CHECK-NEXT:    [[R:%.*]] = and i16 [[LSHR2]], 4
 ; CHECK-NEXT:    ret i16 [[R]]
 ;
@@ -1712,8 +1711,7 @@ define i16 @lshr_lshr_pow2_const(i16 %x) {
 
 define i16 @lshr_lshr_pow2_const_negative_oneuse(i16 %x) {
 ; CHECK-LABEL: @lshr_lshr_pow2_const_negative_oneuse(
-; CHECK-NEXT:    [[LSHR1:%.*]] = lshr i16 2048, [[X:%.*]]
-; CHECK-NEXT:    [[LSHR2:%.*]] = lshr i16 [[LSHR1]], 6
+; CHECK-NEXT:    [[LSHR2:%.*]] = lshr i16 32, [[X:%.*]]
 ; CHECK-NEXT:    call void @use16(i16 [[LSHR2]])
 ; CHECK-NEXT:    [[R:%.*]] = and i16 [[LSHR2]], 4
 ; CHECK-NEXT:    ret i16 [[R]]
@@ -1727,8 +1725,7 @@ define i16 @lshr_lshr_pow2_const_negative_oneuse(i16 %x) {
 
 define i16 @lshr_lshr_pow2_const_negative_nopow2_1(i16 %x) {
 ; CHECK-LABEL: @lshr_lshr_pow2_const_negative_nopow2_1(
-; CHECK-NEXT:    [[LSHR1:%.*]] = lshr i16 2047, [[X:%.*]]
-; CHECK-NEXT:    [[LSHR2:%.*]] = lshr i16 [[LSHR1]], 6
+; CHECK-NEXT:    [[LSHR2:%.*]] = lshr i16 31, [[X:%.*]]
 ; CHECK-NEXT:    [[R:%.*]] = and i16 [[LSHR2]], 4
 ; CHECK-NEXT:    ret i16 [[R]]
 ;
@@ -1740,8 +1737,7 @@ define i16 @lshr_lshr_pow2_const_negative_nopow2_1(i16 %x) {
 
 define i16 @lshr_lshr_pow2_const_negative_nopow2_2(i16 %x) {
 ; CHECK-LABEL: @lshr_lshr_pow2_const_negative_nopow2_2(
-; CHECK-NEXT:    [[LSHR1:%.*]] = lshr i16 8192, [[X:%.*]]
-; CHECK-NEXT:    [[LSHR2:%.*]] = lshr i16 [[LSHR1]], 6
+; CHECK-NEXT:    [[LSHR2:%.*]] = lshr i16 128, [[X:%.*]]
 ; CHECK-NEXT:    [[R:%.*]] = and i16 [[LSHR2]], 3
 ; CHECK-NEXT:    ret i16 [[R]]
 ;

diff  --git a/llvm/test/Transforms/InstCombine/icmp-and-shift.ll b/llvm/test/Transforms/InstCombine/icmp-and-shift.ll
index 6193692976a1..9c9f1a99e82d 100644
--- a/llvm/test/Transforms/InstCombine/icmp-and-shift.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-and-shift.ll
@@ -335,8 +335,7 @@ define i32 @icmp_ne_and1_lshr_pow2(i32 %0) {
 
 define <2 x i32> @icmp_ne_and1_lshr_pow2_vec(<2 x i32> %0) {
 ; CHECK-LABEL: @icmp_ne_and1_lshr_pow2_vec(
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr <2 x i32> <i32 8, i32 8>, [[TMP0:%.*]]
-; CHECK-NEXT:    [[AND:%.*]] = lshr <2 x i32> [[LSHR]], <i32 2, i32 2>
+; CHECK-NEXT:    [[AND:%.*]] = lshr <2 x i32> <i32 2, i32 2>, [[TMP0:%.*]]
 ; CHECK-NEXT:    [[AND_LOBIT:%.*]] = and <2 x i32> [[AND]], <i32 1, i32 1>
 ; CHECK-NEXT:    ret <2 x i32> [[AND_LOBIT]]
 ;
@@ -349,8 +348,7 @@ define <2 x i32> @icmp_ne_and1_lshr_pow2_vec(<2 x i32> %0) {
 
 define i32 @icmp_eq_and_pow2_lshr_pow2(i32 %0) {
 ; CHECK-LABEL: @icmp_eq_and_pow2_lshr_pow2(
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 8, [[TMP0:%.*]]
-; CHECK-NEXT:    [[AND:%.*]] = lshr i32 [[LSHR]], 2
+; CHECK-NEXT:    [[AND:%.*]] = lshr i32 2, [[TMP0:%.*]]
 ; CHECK-NEXT:    [[AND_LOBIT:%.*]] = and i32 [[AND]], 1
 ; CHECK-NEXT:    [[TMP2:%.*]] = xor i32 [[AND_LOBIT]], 1
 ; CHECK-NEXT:    ret i32 [[TMP2]]
@@ -375,8 +373,7 @@ define i32 @icmp_eq_and_pow2_lshr_pow2_case2(i32 %0) {
 
 define <2 x i32> @icmp_eq_and_pow2_lshr_pow2_vec(<2 x i32> %0) {
 ; CHECK-LABEL: @icmp_eq_and_pow2_lshr_pow2_vec(
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr <2 x i32> <i32 8, i32 8>, [[TMP0:%.*]]
-; CHECK-NEXT:    [[AND:%.*]] = lshr <2 x i32> [[LSHR]], <i32 2, i32 2>
+; CHECK-NEXT:    [[AND:%.*]] = lshr <2 x i32> <i32 2, i32 2>, [[TMP0:%.*]]
 ; CHECK-NEXT:    [[AND_LOBIT:%.*]] = and <2 x i32> [[AND]], <i32 1, i32 1>
 ; CHECK-NEXT:    [[TMP2:%.*]] = xor <2 x i32> [[AND_LOBIT]], <i32 1, i32 1>
 ; CHECK-NEXT:    ret <2 x i32> [[TMP2]]
@@ -390,8 +387,7 @@ define <2 x i32> @icmp_eq_and_pow2_lshr_pow2_vec(<2 x i32> %0) {
 
 define i32 @icmp_ne_and_pow2_lshr_pow2(i32 %0) {
 ; CHECK-LABEL: @icmp_ne_and_pow2_lshr_pow2(
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 8, [[TMP0:%.*]]
-; CHECK-NEXT:    [[AND:%.*]] = lshr i32 [[LSHR]], 2
+; CHECK-NEXT:    [[AND:%.*]] = lshr i32 2, [[TMP0:%.*]]
 ; CHECK-NEXT:    [[AND_LOBIT:%.*]] = and i32 [[AND]], 1
 ; CHECK-NEXT:    [[TMP2:%.*]] = xor i32 [[AND_LOBIT]], 1
 ; CHECK-NEXT:    ret i32 [[TMP2]]
@@ -416,8 +412,7 @@ define i32 @icmp_ne_and_pow2_lshr_pow2_case2(i32 %0) {
 
 define <2 x i32> @icmp_ne_and_pow2_lshr_pow2_vec(<2 x i32> %0) {
 ; CHECK-LABEL: @icmp_ne_and_pow2_lshr_pow2_vec(
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr <2 x i32> <i32 8, i32 8>, [[TMP0:%.*]]
-; CHECK-NEXT:    [[AND:%.*]] = lshr <2 x i32> [[LSHR]], <i32 2, i32 2>
+; CHECK-NEXT:    [[AND:%.*]] = lshr <2 x i32> <i32 2, i32 2>, [[TMP0:%.*]]
 ; CHECK-NEXT:    [[AND_LOBIT:%.*]] = and <2 x i32> [[AND]], <i32 1, i32 1>
 ; CHECK-NEXT:    ret <2 x i32> [[AND_LOBIT]]
 ;

diff  --git a/llvm/test/Transforms/InstCombine/shift-shift.ll b/llvm/test/Transforms/InstCombine/shift-shift.ll
index d76f3c00261a..aaf10f28b423 100644
--- a/llvm/test/Transforms/InstCombine/shift-shift.ll
+++ b/llvm/test/Transforms/InstCombine/shift-shift.ll
@@ -277,7 +277,7 @@ define i32 @ashr_ashr_constants_use(i32 %x) {
 ; CHECK-LABEL: @ashr_ashr_constants_use(
 ; CHECK-NEXT:    [[S:%.*]] = ashr i32 -33, [[X:%.*]]
 ; CHECK-NEXT:    call void @use32(i32 [[S]])
-; CHECK-NEXT:    [[R:%.*]] = ashr i32 [[S]], 3
+; CHECK-NEXT:    [[R:%.*]] = ashr i32 -5, [[X]]
 ; CHECK-NEXT:    ret i32 [[R]]
 ;
   %s = ashr i32 -33, %x
@@ -288,8 +288,7 @@ define i32 @ashr_ashr_constants_use(i32 %x) {
 
 define <3 x i8> @ashr_ashr_constants_vec(<3 x i8> %x) {
 ; CHECK-LABEL: @ashr_ashr_constants_vec(
-; CHECK-NEXT:    [[S:%.*]] = ashr <3 x i8> <i8 33, i8 -2, i8 -128>, [[X:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = ashr <3 x i8> [[S]], <i8 3, i8 -1, i8 7>
+; CHECK-NEXT:    [[R:%.*]] = ashr <3 x i8> <i8 4, i8 poison, i8 -1>, [[X:%.*]]
 ; CHECK-NEXT:    ret <3 x i8> [[R]]
 ;
   %s = ashr <3 x i8> <i8 33, i8 -2, i8 -128>, %x
@@ -301,7 +300,7 @@ define i32 @lshr_lshr_constants_use(i32 %x) {
 ; CHECK-LABEL: @lshr_lshr_constants_use(
 ; CHECK-NEXT:    [[S:%.*]] = lshr i32 -33, [[X:%.*]]
 ; CHECK-NEXT:    call void @use32(i32 [[S]])
-; CHECK-NEXT:    [[R:%.*]] = lshr i32 [[S]], 3
+; CHECK-NEXT:    [[R:%.*]] = lshr i32 536870907, [[X]]
 ; CHECK-NEXT:    ret i32 [[R]]
 ;
   %s = lshr i32 -33, %x
@@ -312,8 +311,7 @@ define i32 @lshr_lshr_constants_use(i32 %x) {
 
 define <3 x i8> @lshr_lshr_constants_vec(<3 x i8> %x) {
 ; CHECK-LABEL: @lshr_lshr_constants_vec(
-; CHECK-NEXT:    [[S:%.*]] = lshr <3 x i8> <i8 33, i8 -2, i8 1>, [[X:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = lshr <3 x i8> [[S]], <i8 3, i8 -1, i8 7>
+; CHECK-NEXT:    [[R:%.*]] = lshr <3 x i8> <i8 4, i8 poison, i8 0>, [[X:%.*]]
 ; CHECK-NEXT:    ret <3 x i8> [[R]]
 ;
   %s = lshr <3 x i8> <i8 33, i8 -2, i8 1>, %x


        


More information about the llvm-commits mailing list