summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2018-09-19 15:57:40 +0000
committerSanjay Patel <spatel@rotateright.com>2018-09-19 15:57:40 +0000
commit4fd2e2a4980d3a0512524b8352669ef4aa9258a9 (patch)
treee8a4697b5a408a2abaaf3d996544de30bf18f4a0 /llvm/lib/CodeGen
parentbd810dbd276a8d8150862b0ede16ea200c89546d (diff)
downloadbcm5719-llvm-4fd2e2a4980d3a0512524b8352669ef4aa9258a9.tar.gz
bcm5719-llvm-4fd2e2a4980d3a0512524b8352669ef4aa9258a9.zip
[DAGCombiner][x86] add transform/hook to decompose integer multiply into shift/add
This is an alternative to D37896. I don't see a way to decompose multiplies generically without a target hook to tell us when it's profitable. ARM and AArch64 may be able to remove some duplicate code that overlaps with this transform. As a first step, we're only getting the most clear wins on the vector examples requested in PR34474: https://bugs.llvm.org/show_bug.cgi?id=34474 As noted in the code comment, it's likely that the x86 constraints are tighter than necessary, but it may not always be a win to replace a pmullw/pmulld. Differential Revision: https://reviews.llvm.org/D52195 llvm-svn: 342554
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp26
1 files changed, 26 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 81ee8ad5224..df015433287 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -2931,6 +2931,32 @@ SDValue DAGCombiner::visitMUL(SDNode *N) {
getShiftAmountTy(N0.getValueType()))));
}
+ // Try to transform multiply-by-(power-of-2 +/- 1) into shift and add/sub.
+ // Examples: x * 33 --> (x << 5) + x
+ // x * 15 --> (x << 4) - x
+ 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())
+ MathOp = ISD::ADD;
+ else if ((ConstValue1 + 1).isPowerOf2())
+ MathOp = ISD::SUB;
+
+ if (MathOp != ISD::DELETED_NODE) {
+ unsigned ShAmt = MathOp == ISD::ADD ? (ConstValue1 - 1).logBase2()
+ : (ConstValue1 + 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);
+ }
+ }
+
// (mul (shl X, c1), c2) -> (mul X, c2 << c1)
if (N0.getOpcode() == ISD::SHL &&
isConstantOrConstantVector(N1, /* NoOpaques */ true) &&
OpenPOWER on IntegriCloud