Perform mul combine when multiplying wiht negative constants.

Patch by Weiming Zhao!
This fixes PR12212


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153049 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Anton Korobeynikov 2012-03-19 19:19:50 +00:00
parent 23f1cbbd68
commit 2d7ea04e28
2 changed files with 90 additions and 18 deletions

View File

@ -6865,33 +6865,63 @@ static SDValue PerformMULCombine(SDNode *N,
if (!C)
return SDValue();
uint64_t MulAmt = C->getZExtValue();
int64_t MulAmt = C->getSExtValue();
unsigned ShiftAmt = CountTrailingZeros_64(MulAmt);
ShiftAmt = ShiftAmt & (32 - 1);
SDValue V = N->getOperand(0);
DebugLoc DL = N->getDebugLoc();
SDValue Res;
MulAmt >>= ShiftAmt;
if (isPowerOf2_32(MulAmt - 1)) {
// (mul x, 2^N + 1) => (add (shl x, N), x)
Res = DAG.getNode(ISD::ADD, DL, VT,
V, DAG.getNode(ISD::SHL, DL, VT,
V, DAG.getConstant(Log2_32(MulAmt-1),
MVT::i32)));
} else if (isPowerOf2_32(MulAmt + 1)) {
// (mul x, 2^N - 1) => (sub (shl x, N), x)
Res = DAG.getNode(ISD::SUB, DL, VT,
DAG.getNode(ISD::SHL, DL, VT,
V, DAG.getConstant(Log2_32(MulAmt+1),
MVT::i32)),
V);
} else
return SDValue();
if (MulAmt >= 0) {
if (isPowerOf2_32(MulAmt - 1)) {
// (mul x, 2^N + 1) => (add (shl x, N), x)
Res = DAG.getNode(ISD::ADD, DL, VT,
V,
DAG.getNode(ISD::SHL, DL, VT,
V,
DAG.getConstant(Log2_32(MulAmt - 1),
MVT::i32)));
} else if (isPowerOf2_32(MulAmt + 1)) {
// (mul x, 2^N - 1) => (sub (shl x, N), x)
Res = DAG.getNode(ISD::SUB, DL, VT,
DAG.getNode(ISD::SHL, DL, VT,
V,
DAG.getConstant(Log2_32(MulAmt + 1),
MVT::i32)),
V);
} else
return SDValue();
} else {
uint64_t MulAmtAbs = -MulAmt;
if (isPowerOf2_32(MulAmtAbs + 1)) {
// (mul x, -(2^N - 1)) => (sub x, (shl x, N))
Res = DAG.getNode(ISD::SUB, DL, VT,
V,
DAG.getNode(ISD::SHL, DL, VT,
V,
DAG.getConstant(Log2_32(MulAmtAbs + 1),
MVT::i32)));
} else if (isPowerOf2_32(MulAmtAbs - 1)) {
// (mul x, -(2^N + 1)) => - (add (shl x, N), x)
Res = DAG.getNode(ISD::ADD, DL, VT,
V,
DAG.getNode(ISD::SHL, DL, VT,
V,
DAG.getConstant(Log2_32(MulAmtAbs-1),
MVT::i32)));
Res = DAG.getNode(ISD::SUB, DL, VT,
DAG.getConstant(0, MVT::i32),Res);
} else
return SDValue();
}
if (ShiftAmt != 0)
Res = DAG.getNode(ISD::SHL, DL, VT, Res,
DAG.getConstant(ShiftAmt, MVT::i32));
Res = DAG.getNode(ISD::SHL, DL, VT,
Res, DAG.getConstant(ShiftAmt, MVT::i32));
// Do not add new nodes to DAG combiner worklist.
DCI.CombineTo(N, Res, false);

View File

@ -41,3 +41,45 @@ entry:
ret i32 %0
}
define i32 @tn9(i32 %v) nounwind readnone {
entry:
; CHECK: tn9:
; CHECK: add r0, r0, r0, lsl #3
; CHECK: rsb r0, r0, #0
%0 = mul i32 %v, -9
ret i32 %0
}
define i32 @tn7(i32 %v) nounwind readnone {
entry:
; CHECK: tn7:
; CHECK: sub r0, r0, r0, lsl #3
%0 = mul i32 %v, -7
ret i32 %0
}
define i32 @tn5(i32 %v) nounwind readnone {
entry:
; CHECK: tn5:
; CHECK: add r0, r0, r0, lsl #2
; CHECK: rsb r0, r0, #0
%0 = mul i32 %v, -5
ret i32 %0
}
define i32 @tn3(i32 %v) nounwind readnone {
entry:
; CHECK: tn3:
; CHECK: sub r0, r0, r0, lsl #2
%0 = mul i32 %v, -3
ret i32 %0
}
define i32 @tn12288(i32 %v) nounwind readnone {
entry:
; CHECK: tn12288:
; CHECK: sub r0, r0, r0, lsl #2
; CHECK: lsl{{.*}}#12
%0 = mul i32 %v, -12288
ret i32 %0
}