Skip to content

Commit d76c8f5

Browse files
committed
[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
1 parent 3aff787 commit d76c8f5

File tree

3 files changed

+38
-20
lines changed

3 files changed

+38
-20
lines changed

llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,13 @@ static bool canEvaluateShifted(Value *V, unsigned NumBits, bool IsLeftShift,
566566
return false;
567567
return true;
568568
}
569+
case Instruction::Mul: {
570+
const APInt *MulConst;
571+
// We can fold (shr (mul X, -(1 << C)), C) -> (and (neg X), C`)
572+
return !IsLeftShift && match(I->getOperand(1), m_APInt(MulConst)) &&
573+
MulConst->isNegatedPowerOf2() &&
574+
MulConst->countTrailingZeros() == NumBits;
575+
}
569576
}
570577
}
571578

@@ -680,6 +687,17 @@ static Value *getShiftedValue(Value *V, unsigned NumBits, bool isLeftShift,
680687
isLeftShift, IC, DL));
681688
return PN;
682689
}
690+
case Instruction::Mul: {
691+
assert(!isLeftShift && "Unexpected shift direction!");
692+
auto *Neg = BinaryOperator::CreateNeg(I->getOperand(0));
693+
IC.InsertNewInstWith(Neg, *I);
694+
unsigned TypeWidth = I->getType()->getScalarSizeInBits();
695+
APInt Mask = APInt::getLowBitsSet(TypeWidth, TypeWidth - NumBits);
696+
auto *And = BinaryOperator::CreateAnd(Neg,
697+
ConstantInt::get(I->getType(), Mask));
698+
And->takeName(I);
699+
return IC.InsertNewInstWith(And, *I);
700+
}
683701
}
684702
}
685703

llvm/test/Transforms/InstCombine/apint-shift.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,9 @@ define <2 x i19> @eq_lshr_shl_splat_vec(<2 x i19> %X) {
199199

200200
define <2 x i7> @lshr_shl_splat_vec(<2 x i7> %X) {
201201
; CHECK-LABEL: @lshr_shl_splat_vec(
202-
; CHECK-NEXT: [[MUL:%.*]] = mul <2 x i7> [[X:%.*]], <i7 -8, i7 -8>
203-
; CHECK-NEXT: [[SH1:%.*]] = lshr exact <2 x i7> [[MUL]], <i7 1, i7 1>
204-
; CHECK-NEXT: ret <2 x i7> [[SH1]]
202+
; CHECK-NEXT: [[DOTNEG:%.*]] = mul <2 x i7> [[X:%.*]], <i7 60, i7 60>
203+
; CHECK-NEXT: [[SH2:%.*]] = and <2 x i7> [[DOTNEG]], <i7 60, i7 60>
204+
; CHECK-NEXT: ret <2 x i7> [[SH2]]
205205
;
206206
%mul = mul <2 x i7> %X, <i7 -8, i7 -8>
207207
%sh1 = lshr exact <2 x i7> %mul, <i7 3, i7 3>

llvm/test/Transforms/InstCombine/shift.ll

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1832,9 +1832,9 @@ define i8 @shl_mask_demand(i8 %x) {
18321832

18331833
define i64 @lshr_mul_negpow2(i64 %x) {
18341834
; CHECK-LABEL: @lshr_mul_negpow2(
1835-
; CHECK-NEXT: [[A:%.*]] = mul i64 [[X:%.*]], -4294967296
1836-
; CHECK-NEXT: [[B:%.*]] = lshr exact i64 [[A]], 32
1837-
; CHECK-NEXT: ret i64 [[B]]
1835+
; CHECK-NEXT: [[TMP1:%.*]] = sub i64 0, [[X:%.*]]
1836+
; CHECK-NEXT: [[A:%.*]] = and i64 [[TMP1]], 4294967295
1837+
; CHECK-NEXT: ret i64 [[A]]
18381838
;
18391839
%a = mul i64 %x, -4294967296
18401840
%b = lshr i64 %a, 32
@@ -1843,9 +1843,9 @@ define i64 @lshr_mul_negpow2(i64 %x) {
18431843

18441844
define i64 @lshr_mul_negpow2_2(i64 %x) {
18451845
; CHECK-LABEL: @lshr_mul_negpow2_2(
1846-
; CHECK-NEXT: [[A:%.*]] = mul i64 [[X:%.*]], -65536
1847-
; CHECK-NEXT: [[B:%.*]] = lshr exact i64 [[A]], 16
1848-
; CHECK-NEXT: ret i64 [[B]]
1846+
; CHECK-NEXT: [[TMP1:%.*]] = sub i64 0, [[X:%.*]]
1847+
; CHECK-NEXT: [[A:%.*]] = and i64 [[TMP1]], 281474976710655
1848+
; CHECK-NEXT: ret i64 [[A]]
18491849
;
18501850
%a = mul i64 %x, -65536
18511851
%b = lshr i64 %a, 16
@@ -1854,9 +1854,9 @@ define i64 @lshr_mul_negpow2_2(i64 %x) {
18541854

18551855
define <2 x i32> @lshr_mul_negpow2_3(<2 x i32> %x) {
18561856
; CHECK-LABEL: @lshr_mul_negpow2_3(
1857-
; CHECK-NEXT: [[A:%.*]] = mul <2 x i32> [[X:%.*]], <i32 -16777216, i32 -16777216>
1858-
; CHECK-NEXT: [[B:%.*]] = lshr exact <2 x i32> [[A]], <i32 24, i32 24>
1859-
; CHECK-NEXT: ret <2 x i32> [[B]]
1857+
; CHECK-NEXT: [[TMP1:%.*]] = sub <2 x i32> zeroinitializer, [[X:%.*]]
1858+
; CHECK-NEXT: [[A:%.*]] = and <2 x i32> [[TMP1]], <i32 255, i32 255>
1859+
; CHECK-NEXT: ret <2 x i32> [[A]]
18601860
;
18611861
%a = mul <2 x i32> %x, <i32 -16777216, i32 -16777216>
18621862
%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) {
18651865

18661866
define i32 @lshr_mul_negpow2_4(i32 %x) {
18671867
; CHECK-LABEL: @lshr_mul_negpow2_4(
1868-
; CHECK-NEXT: [[A:%.*]] = mul i32 [[X:%.*]], -65536
1869-
; CHECK-NEXT: [[B:%.*]] = lshr exact i32 [[A]], 16
1870-
; CHECK-NEXT: [[C:%.*]] = xor i32 [[B]], 1
1871-
; CHECK-NEXT: ret i32 [[C]]
1868+
; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[X:%.*]]
1869+
; CHECK-NEXT: [[A:%.*]] = and i32 [[TMP1]], 65535
1870+
; CHECK-NEXT: [[B:%.*]] = xor i32 [[A]], 1
1871+
; CHECK-NEXT: ret i32 [[B]]
18721872
;
18731873
%a = mul i32 %x, -65536
18741874
%b = xor i32 %a, 65536
@@ -1878,10 +1878,10 @@ define i32 @lshr_mul_negpow2_4(i32 %x) {
18781878

18791879
define <2 x i32> @lshr_mul_negpow2_5(<2 x i32> %x) {
18801880
; CHECK-LABEL: @lshr_mul_negpow2_5(
1881-
; CHECK-NEXT: [[A:%.*]] = mul <2 x i32> [[X:%.*]], <i32 -65536, i32 -65536>
1882-
; CHECK-NEXT: [[B:%.*]] = lshr exact <2 x i32> [[A]], <i32 16, i32 16>
1883-
; CHECK-NEXT: [[C:%.*]] = or <2 x i32> [[B]], <i32 8, i32 8>
1884-
; CHECK-NEXT: ret <2 x i32> [[C]]
1881+
; CHECK-NEXT: [[TMP1:%.*]] = sub <2 x i32> zeroinitializer, [[X:%.*]]
1882+
; CHECK-NEXT: [[A:%.*]] = and <2 x i32> [[TMP1]], <i32 65527, i32 65527>
1883+
; CHECK-NEXT: [[B:%.*]] = or <2 x i32> [[A]], <i32 8, i32 8>
1884+
; CHECK-NEXT: ret <2 x i32> [[B]]
18851885
;
18861886
%a = mul <2 x i32> %x, <i32 -65536, i32 -65536>
18871887
%b = or <2 x i32> %a, <i32 524288, i32 524288>

0 commit comments

Comments
 (0)