[llvm] d76c8f5 - [InstCombine] Add mul with negated power of 2 constant to canEvaluateShifted.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 20 11:01:13 PDT 2022


Author: Craig Topper
Date: 2022-07-20T11:00:22-07:00
New Revision: d76c8f51276fdd7829d5743b5b7874a76cd4b518

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

LOG: [InstCombine] Add mul with negated power of 2 constant to canEvaluateShifted.

If we are right shifting a multiply by a negated power of 2 where
the power of 2 is the same as the shift amount, we can replace with
a negate followed by an And.

New tests have not been committed yet but the patch shows the diffs.
Let me know if you want any changes or additional tests.

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

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index f4e2d1239f0f2..13c98b935adfb 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -566,6 +566,13 @@ static bool canEvaluateShifted(Value *V, unsigned NumBits, bool IsLeftShift,
         return false;
     return true;
   }
+  case Instruction::Mul: {
+    const APInt *MulConst;
+    // We can fold (shr (mul X, -(1 << C)), C) -> (and (neg X), C`)
+    return !IsLeftShift && match(I->getOperand(1), m_APInt(MulConst)) &&
+           MulConst->isNegatedPowerOf2() &&
+           MulConst->countTrailingZeros() == NumBits;
+  }
   }
 }
 
@@ -680,6 +687,17 @@ static Value *getShiftedValue(Value *V, unsigned NumBits, bool isLeftShift,
                                               isLeftShift, IC, DL));
     return PN;
   }
+  case Instruction::Mul: {
+    assert(!isLeftShift && "Unexpected shift direction!");
+    auto *Neg = BinaryOperator::CreateNeg(I->getOperand(0));
+    IC.InsertNewInstWith(Neg, *I);
+    unsigned TypeWidth = I->getType()->getScalarSizeInBits();
+    APInt Mask = APInt::getLowBitsSet(TypeWidth, TypeWidth - NumBits);
+    auto *And = BinaryOperator::CreateAnd(Neg,
+                                          ConstantInt::get(I->getType(), Mask));
+    And->takeName(I);
+    return IC.InsertNewInstWith(And, *I);
+  }
   }
 }
 

diff  --git a/llvm/test/Transforms/InstCombine/apint-shift.ll b/llvm/test/Transforms/InstCombine/apint-shift.ll
index 039f263101f53..98948a64dd6f2 100644
--- a/llvm/test/Transforms/InstCombine/apint-shift.ll
+++ b/llvm/test/Transforms/InstCombine/apint-shift.ll
@@ -199,9 +199,9 @@ define <2 x i19> @eq_lshr_shl_splat_vec(<2 x i19> %X) {
 
 define <2 x i7> @lshr_shl_splat_vec(<2 x i7> %X) {
 ; CHECK-LABEL: @lshr_shl_splat_vec(
-; CHECK-NEXT:    [[MUL:%.*]] = mul <2 x i7> [[X:%.*]], <i7 -8, i7 -8>
-; CHECK-NEXT:    [[SH1:%.*]] = lshr exact <2 x i7> [[MUL]], <i7 1, i7 1>
-; CHECK-NEXT:    ret <2 x i7> [[SH1]]
+; CHECK-NEXT:    [[DOTNEG:%.*]] = mul <2 x i7> [[X:%.*]], <i7 60, i7 60>
+; CHECK-NEXT:    [[SH2:%.*]] = and <2 x i7> [[DOTNEG]], <i7 60, i7 60>
+; CHECK-NEXT:    ret <2 x i7> [[SH2]]
 ;
   %mul = mul <2 x i7> %X, <i7 -8, i7 -8>
   %sh1 = lshr exact <2 x i7> %mul, <i7 3, i7 3>

diff  --git a/llvm/test/Transforms/InstCombine/shift.ll b/llvm/test/Transforms/InstCombine/shift.ll
index 454227cce6496..d73a5fe9d81a6 100644
--- a/llvm/test/Transforms/InstCombine/shift.ll
+++ b/llvm/test/Transforms/InstCombine/shift.ll
@@ -1832,9 +1832,9 @@ define i8 @shl_mask_demand(i8 %x) {
 
 define i64 @lshr_mul_negpow2(i64 %x) {
 ; CHECK-LABEL: @lshr_mul_negpow2(
-; CHECK-NEXT:    [[A:%.*]] = mul i64 [[X:%.*]], -4294967296
-; CHECK-NEXT:    [[B:%.*]] = lshr exact i64 [[A]], 32
-; CHECK-NEXT:    ret i64 [[B]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i64 0, [[X:%.*]]
+; CHECK-NEXT:    [[A:%.*]] = and i64 [[TMP1]], 4294967295
+; CHECK-NEXT:    ret i64 [[A]]
 ;
   %a = mul i64 %x, -4294967296
   %b = lshr i64 %a, 32
@@ -1843,9 +1843,9 @@ define i64 @lshr_mul_negpow2(i64 %x) {
 
 define i64 @lshr_mul_negpow2_2(i64 %x) {
 ; CHECK-LABEL: @lshr_mul_negpow2_2(
-; CHECK-NEXT:    [[A:%.*]] = mul i64 [[X:%.*]], -65536
-; CHECK-NEXT:    [[B:%.*]] = lshr exact i64 [[A]], 16
-; CHECK-NEXT:    ret i64 [[B]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i64 0, [[X:%.*]]
+; CHECK-NEXT:    [[A:%.*]] = and i64 [[TMP1]], 281474976710655
+; CHECK-NEXT:    ret i64 [[A]]
 ;
   %a = mul i64 %x, -65536
   %b = lshr i64 %a, 16
@@ -1854,9 +1854,9 @@ define i64 @lshr_mul_negpow2_2(i64 %x) {
 
 define <2 x i32> @lshr_mul_negpow2_3(<2 x i32> %x) {
 ; CHECK-LABEL: @lshr_mul_negpow2_3(
-; CHECK-NEXT:    [[A:%.*]] = mul <2 x i32> [[X:%.*]], <i32 -16777216, i32 -16777216>
-; CHECK-NEXT:    [[B:%.*]] = lshr exact <2 x i32> [[A]], <i32 24, i32 24>
-; CHECK-NEXT:    ret <2 x i32> [[B]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sub <2 x i32> zeroinitializer, [[X:%.*]]
+; CHECK-NEXT:    [[A:%.*]] = and <2 x i32> [[TMP1]], <i32 255, i32 255>
+; CHECK-NEXT:    ret <2 x i32> [[A]]
 ;
   %a = mul <2 x i32> %x, <i32 -16777216, i32 -16777216>
   %b = lshr <2 x i32> %a, <i32 24, i32 24>
@@ -1865,10 +1865,10 @@ define <2 x i32> @lshr_mul_negpow2_3(<2 x i32> %x) {
 
 define i32 @lshr_mul_negpow2_4(i32 %x) {
 ; CHECK-LABEL: @lshr_mul_negpow2_4(
-; CHECK-NEXT:    [[A:%.*]] = mul i32 [[X:%.*]], -65536
-; CHECK-NEXT:    [[B:%.*]] = lshr exact i32 [[A]], 16
-; CHECK-NEXT:    [[C:%.*]] = xor i32 [[B]], 1
-; CHECK-NEXT:    ret i32 [[C]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 0, [[X:%.*]]
+; CHECK-NEXT:    [[A:%.*]] = and i32 [[TMP1]], 65535
+; CHECK-NEXT:    [[B:%.*]] = xor i32 [[A]], 1
+; CHECK-NEXT:    ret i32 [[B]]
 ;
   %a = mul i32 %x, -65536
   %b = xor i32 %a, 65536
@@ -1878,10 +1878,10 @@ define i32 @lshr_mul_negpow2_4(i32 %x) {
 
 define <2 x i32> @lshr_mul_negpow2_5(<2 x i32> %x) {
 ; CHECK-LABEL: @lshr_mul_negpow2_5(
-; CHECK-NEXT:    [[A:%.*]] = mul <2 x i32> [[X:%.*]], <i32 -65536, i32 -65536>
-; CHECK-NEXT:    [[B:%.*]] = lshr exact <2 x i32> [[A]], <i32 16, i32 16>
-; CHECK-NEXT:    [[C:%.*]] = or <2 x i32> [[B]], <i32 8, i32 8>
-; CHECK-NEXT:    ret <2 x i32> [[C]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sub <2 x i32> zeroinitializer, [[X:%.*]]
+; CHECK-NEXT:    [[A:%.*]] = and <2 x i32> [[TMP1]], <i32 65527, i32 65527>
+; CHECK-NEXT:    [[B:%.*]] = or <2 x i32> [[A]], <i32 8, i32 8>
+; CHECK-NEXT:    ret <2 x i32> [[B]]
 ;
   %a = mul <2 x i32> %x, <i32 -65536, i32 -65536>
   %b = or <2 x i32> %a, <i32 524288, i32 524288>


        


More information about the llvm-commits mailing list