summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp19
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp4
2 files changed, 16 insertions, 7 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;
}
}
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 398bf11065c..b49ef7b6a44 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -4736,7 +4736,9 @@ bool X86TargetLowering::decomposeMulByConstant(EVT VT, SDValue C) const {
if (isOperationLegal(ISD::MUL, VT))
return false;
- return (MulC + 1).isPowerOf2() || (MulC - 1).isPowerOf2();
+ // shl+add, shl+sub, shl+add+neg
+ return (MulC + 1).isPowerOf2() || (MulC - 1).isPowerOf2() ||
+ (1 - MulC).isPowerOf2() || (-(MulC + 1)).isPowerOf2();
}
bool X86TargetLowering::isExtractSubvectorCheap(EVT ResVT, EVT SrcVT,
OpenPOWER on IntegriCloud