diff options
| author | Haicheng Wu <haicheng@codeaurora.org> | 2016-11-15 20:16:48 +0000 |
|---|---|---|
| committer | Haicheng Wu <haicheng@codeaurora.org> | 2016-11-15 20:16:48 +0000 |
| commit | faee2b71a79f2eedb75279c2455e84b54b7e839b (patch) | |
| tree | d98279dcfac76b023afa1fd82ff9c0bdf2ddf660 /llvm/lib | |
| parent | 3666629837d87332f17ead6d70eb98676614900c (diff) | |
| download | bcm5719-llvm-faee2b71a79f2eedb75279c2455e84b54b7e839b.tar.gz bcm5719-llvm-faee2b71a79f2eedb75279c2455e84b54b7e839b.zip | |
[AArch64] Lower multiplication by a constant int to shl+add+shl
Lower a = b * C where C = (2^n + 1) * 2^m to
add w0, w0, w0, lsl n
lsl w0, w0, m
Differential Revision: https://reviews.llvm.org/D229245
llvm-svn: 287019
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 48 |
1 files changed, 39 insertions, 9 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 403021e87d3..b8d6795fb35 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -7670,6 +7670,31 @@ static SDValue performMulCombine(SDNode *N, SelectionDAG &DAG, // future CPUs have a cheaper MADD instruction, this may need to be // gated on a subtarget feature. For Cyclone, 32-bit MADD is 4 cycles and // 64-bit is 5 cycles, so this is always a win. + // More aggressively, some multiplications N0 * C can be lowered to + // shift+add+shift if the constant C = A * B where A = 2^N + 1 and B = 2^M, + // e.g. 6=3*2=(2+1)*2. + // TODO: consider lowering more cases, e.g. C = 14, -6, -14 or even 45 + // which equals to (1+2)*16-(1+2). + SDValue N0 = N->getOperand(0); + // TrailingZeroes is used to test if the mul can be lowered to + // shift+add+shift. + unsigned TrailingZeroes = ConstValue.countTrailingZeros(); + if (TrailingZeroes) { + // Conservatively do not lower to shift+add+shift if the mul might be + // folded into smul or umul. + if (N0->hasOneUse() && (isSignExtended(N0.getNode(), DAG) || + isZeroExtended(N0.getNode(), DAG))) + return SDValue(); + // Conservatively do not lower to shift+add+shift if the mul might be + // folded into madd or msub. + if (N->hasOneUse() && (N->use_begin()->getOpcode() == ISD::ADD || + N->use_begin()->getOpcode() == ISD::SUB)) + return SDValue(); + } + // Use ShiftedConstValue instead of ConstValue to support both shift+add/sub + // and shift+add+shift. + APInt ShiftedConstValue = ConstValue.ashr(TrailingZeroes); + unsigned ShiftAmt, AddSubOpc; // Is the shifted value the LHS operand of the add/sub? bool ShiftValUseIsN0 = true; @@ -7679,10 +7704,11 @@ static SDValue performMulCombine(SDNode *N, SelectionDAG &DAG, if (ConstValue.isNonNegative()) { // (mul x, 2^N + 1) => (add (shl x, N), x) // (mul x, 2^N - 1) => (sub (shl x, N), x) - APInt CVMinus1 = ConstValue - 1; + // (mul x, (2^N + 1) * 2^M) => (shl (add (shl x, N), x), M) + APInt SCVMinus1 = ShiftedConstValue - 1; APInt CVPlus1 = ConstValue + 1; - if (CVMinus1.isPowerOf2()) { - ShiftAmt = CVMinus1.logBase2(); + if (SCVMinus1.isPowerOf2()) { + ShiftAmt = SCVMinus1.logBase2(); AddSubOpc = ISD::ADD; } else if (CVPlus1.isPowerOf2()) { ShiftAmt = CVPlus1.logBase2(); @@ -7708,18 +7734,22 @@ static SDValue performMulCombine(SDNode *N, SelectionDAG &DAG, SDLoc DL(N); EVT VT = N->getValueType(0); - SDValue N0 = N->getOperand(0); - SDValue ShiftedVal = DAG.getNode(ISD::SHL, DL, VT, N->getOperand(0), + SDValue ShiftedVal = DAG.getNode(ISD::SHL, DL, VT, N0, DAG.getConstant(ShiftAmt, DL, MVT::i64)); SDValue AddSubN0 = ShiftValUseIsN0 ? ShiftedVal : N0; SDValue AddSubN1 = ShiftValUseIsN0 ? N0 : ShiftedVal; SDValue Res = DAG.getNode(AddSubOpc, DL, VT, AddSubN0, AddSubN1); - if (!NegateResult) - return Res; - + assert(!(NegateResult && TrailingZeroes) && + "NegateResult and TrailingZeroes cannot both be true for now."); // Negate the result. - return DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT), Res); + if (NegateResult) + return DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT), Res); + // Shift the result. + if (TrailingZeroes) + return DAG.getNode(ISD::SHL, DL, VT, Res, + DAG.getConstant(TrailingZeroes, DL, MVT::i64)); + return Res; } static SDValue performVectorCompareAndMaskUnaryOpCombine(SDNode *N, |

