diff options
| author | Sanjay Patel <spatel@rotateright.com> | 2018-09-19 15:57:40 +0000 |
|---|---|---|
| committer | Sanjay Patel <spatel@rotateright.com> | 2018-09-19 15:57:40 +0000 |
| commit | 4fd2e2a4980d3a0512524b8352669ef4aa9258a9 (patch) | |
| tree | e8a4697b5a408a2abaaf3d996544de30bf18f4a0 /llvm/lib/CodeGen | |
| parent | bd810dbd276a8d8150862b0ede16ea200c89546d (diff) | |
| download | bcm5719-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.cpp | 26 |
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) && |

