summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2005-10-30 06:41:49 +0000
committerChris Lattner <sabre@nondot.org>2005-10-30 06:41:49 +0000
commita70878d4fb3a7595f9d5c55e6c1d0d77a77015c5 (patch)
tree7380b8bf3d5c36cd5a499372aab17a28dec2a602
parent9cc9f0fca1942daf8b119c10314e1728b77217d6 (diff)
downloadllvm-a70878d4fb3a7595f9d5c55e6c1d0d77a77015c5.tar.gz
Codegen mul by negative power of two with a shift and negate.
This implements test/Regression/CodeGen/PowerPC/mul-neg-power-2.ll, producing: _foo: slwi r2, r3, 1 subfic r3, r2, 63 blr instead of: _foo: mulli r2, r3, -2 addi r3, r2, 63 blr llvm-svn: 24106
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp16
1 files changed, 13 insertions, 3 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 412b47e2a476..048737f13e2b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -735,8 +735,7 @@ SDOperand DAGCombiner::visitMUL(SDNode *N) {
// fold (mul c1, c2) -> c1*c2
if (N0C && N1C)
- return DAG.getConstant(N0C->getValue() * N1C->getValue(),
- N->getValueType(0));
+ return DAG.getConstant(N0C->getValue() * N1C->getValue(), VT);
// canonicalize constant to RHS
if (N0C && !N1C)
return DAG.getNode(ISD::MUL, VT, N1, N0);
@@ -748,9 +747,20 @@ SDOperand DAGCombiner::visitMUL(SDNode *N) {
return DAG.getNode(ISD::SUB, VT, DAG.getConstant(0, VT), N0);
// fold (mul x, (1 << c)) -> x << c
if (N1C && isPowerOf2_64(N1C->getValue()))
- return DAG.getNode(ISD::SHL, N->getValueType(0), N0,
+ return DAG.getNode(ISD::SHL, VT, N0,
DAG.getConstant(Log2_64(N1C->getValue()),
TLI.getShiftAmountTy()));
+ // fold (mul x, -(1 << c)) -> -(x << c) or (-x) << c
+ if (N1C && isPowerOf2_64(-N1C->getSignExtended())) {
+ // FIXME: If the input is something that is easily negated (e.g. a
+ // single-use add), we should put the negate there.
+ return DAG.getNode(ISD::SUB, VT, DAG.getConstant(0, VT),
+ DAG.getNode(ISD::SHL, VT, N0,
+ DAG.getConstant(Log2_64(-N1C->getSignExtended()),
+ TLI.getShiftAmountTy())));
+ }
+
+
// fold (mul (mul x, c1), c2) -> (mul x, c1*c2)
if (N1C && N0.getOpcode() == ISD::MUL) {
ConstantSDNode *N00C = dyn_cast<ConstantSDNode>(N0.getOperand(0));