From 2d7ea04e2822bbe5faad0eefceb7a300ea01224e Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Mon, 19 Mar 2012 19:19:50 +0000 Subject: [PATCH] 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 --- lib/Target/ARM/ARMISelLowering.cpp | 66 ++++++++++++++++++++++-------- test/CodeGen/ARM/mul_const.ll | 42 +++++++++++++++++++ 2 files changed, 90 insertions(+), 18 deletions(-) diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 459d82cdbe9..e26dd22c929 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -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); diff --git a/test/CodeGen/ARM/mul_const.ll b/test/CodeGen/ARM/mul_const.ll index 3cb8a8e816f..c50a2335467 100644 --- a/test/CodeGen/ARM/mul_const.ll +++ b/test/CodeGen/ARM/mul_const.ll @@ -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 +}