summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp19
1 files changed, 13 insertions, 6 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 6d19f226a28..d09efca5e43 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -2924,28 +2924,35 @@ SDValue DAGCombiner::visitMUL(SDNode *N) {
}
// Try to transform multiply-by-(power-of-2 +/- 1) into shift and add/sub.
+ // mul x, (2^N + 1) --> add (shl x, N), x
+ // mul x, (2^N - 1) --> sub (shl x, N), x
// Examples: x * 33 --> (x << 5) + x
// x * 15 --> (x << 4) - x
+ // x * -33 --> -((x << 5) + x)
+ // x * -15 --> -((x << 4) - x) ; this reduces --> x - (x << 4)
if (N1IsConst && TLI.decomposeMulByConstant(VT, N1)) {
- // TODO: Negative constants can be handled by negating the result.
// TODO: We could handle more general decomposition of any constant by
// having the target set a limit on number of ops and making a
// callback to determine that sequence (similar to sqrt expansion).
unsigned MathOp = ISD::DELETED_NODE;
- if ((ConstValue1 - 1).isPowerOf2())
+ APInt MulC = ConstValue1.abs();
+ if ((MulC - 1).isPowerOf2())
MathOp = ISD::ADD;
- else if ((ConstValue1 + 1).isPowerOf2())
+ else if ((MulC + 1).isPowerOf2())
MathOp = ISD::SUB;
if (MathOp != ISD::DELETED_NODE) {
- unsigned ShAmt = MathOp == ISD::ADD ? (ConstValue1 - 1).logBase2()
- : (ConstValue1 + 1).logBase2();
+ unsigned ShAmt = MathOp == ISD::ADD ? (MulC - 1).logBase2()
+ : (MulC + 1).logBase2();
assert(ShAmt > 0 && ShAmt < VT.getScalarSizeInBits() &&
"Not expecting multiply-by-constant that could have simplified");
SDLoc DL(N);
SDValue Shl = DAG.getNode(ISD::SHL, DL, VT, N0,
DAG.getConstant(ShAmt, DL, VT));
- return DAG.getNode(MathOp, DL, VT, Shl, N0);
+ SDValue R = DAG.getNode(MathOp, DL, VT, Shl, N0);
+ if (ConstValue1.isNegative())
+ R = DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT), R);
+ return R;
}
}
OpenPOWER on IntegriCloud