aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target
diff options
context:
space:
mode:
authorAkira Hatanaka <ahatanaka@mips.com>2013-06-26 18:48:17 +0000
committerAkira Hatanaka <ahatanaka@mips.com>2013-06-26 18:48:17 +0000
commit9a308df027b60057d0fe3ba7a3ee9648f6677879 (patch)
treeab9099f616eb3dfee3cd5db7f6f79c203e549f45 /lib/Target
parenta8f936446134c9cdcf06f74b861112a62fe66d71 (diff)
downloadexternal_llvm-9a308df027b60057d0fe3ba7a3ee9648f6677879.zip
external_llvm-9a308df027b60057d0fe3ba7a3ee9648f6677879.tar.gz
external_llvm-9a308df027b60057d0fe3ba7a3ee9648f6677879.tar.bz2
[mips] Improve code generation for constant multiplication using shifts, adds and
subs. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185011 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target')
-rw-r--r--lib/Target/Mips/MipsSEISelLowering.cpp54
1 files changed, 54 insertions, 0 deletions
diff --git a/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp
index f640ecc..8b5a874 100644
--- a/lib/Target/Mips/MipsSEISelLowering.cpp
+++ b/lib/Target/Mips/MipsSEISelLowering.cpp
@@ -99,6 +99,7 @@ MipsSETargetLowering::MipsSETargetLowering(MipsTargetMachine &TM)
setTargetDAGCombine(ISD::ADDE);
setTargetDAGCombine(ISD::SUBE);
+ setTargetDAGCombine(ISD::MUL);
computeRegisterProperties();
}
@@ -320,6 +321,57 @@ static SDValue performSUBECombine(SDNode *N, SelectionDAG &DAG,
return SDValue();
}
+static SDValue genConstMult(SDValue X, uint64_t C, SDLoc DL, EVT VT,
+ EVT ShiftTy, SelectionDAG &DAG) {
+ // Clear the upper (64 - VT.sizeInBits) bits.
+ C &= ((uint64_t)-1) >> (64 - VT.getSizeInBits());
+
+ // Return 0.
+ if (C == 0)
+ return DAG.getConstant(0, VT);
+
+ // Return x.
+ if (C == 1)
+ return X;
+
+ // If c is power of 2, return (shl x, log2(c)).
+ if (isPowerOf2_64(C))
+ return DAG.getNode(ISD::SHL, DL, VT, X,
+ DAG.getConstant(Log2_64(C), ShiftTy));
+
+ unsigned Log2Ceil = Log2_64_Ceil(C);
+ uint64_t Floor = 1LL << Log2_64(C);
+ uint64_t Ceil = Log2Ceil == 64 ? 0LL : 1LL << Log2Ceil;
+
+ // If |c - floor_c| <= |c - ceil_c|,
+ // where floor_c = pow(2, floor(log2(c))) and ceil_c = pow(2, ceil(log2(c))),
+ // return (add constMult(x, floor_c), constMult(x, c - floor_c)).
+ if (C - Floor <= Ceil - C) {
+ SDValue Op0 = genConstMult(X, Floor, DL, VT, ShiftTy, DAG);
+ SDValue Op1 = genConstMult(X, C - Floor, DL, VT, ShiftTy, DAG);
+ return DAG.getNode(ISD::ADD, DL, VT, Op0, Op1);
+ }
+
+ // If |c - floor_c| > |c - ceil_c|,
+ // return (sub constMult(x, ceil_c), constMult(x, ceil_c - c)).
+ SDValue Op0 = genConstMult(X, Ceil, DL, VT, ShiftTy, DAG);
+ SDValue Op1 = genConstMult(X, Ceil - C, DL, VT, ShiftTy, DAG);
+ return DAG.getNode(ISD::SUB, DL, VT, Op0, Op1);
+}
+
+static SDValue performMULCombine(SDNode *N, SelectionDAG &DAG,
+ const TargetLowering::DAGCombinerInfo &DCI,
+ const MipsSETargetLowering *TL) {
+ EVT VT = N->getValueType(0);
+
+ if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1)))
+ if (!VT.isVector())
+ return genConstMult(N->getOperand(0), C->getZExtValue(), SDLoc(N),
+ VT, TL->getScalarShiftAmountTy(VT), DAG);
+
+ return SDValue(N, 0);
+}
+
static SDValue performDSPShiftCombine(unsigned Opc, SDNode *N, EVT Ty,
SelectionDAG &DAG,
const MipsSubtarget *Subtarget) {
@@ -432,6 +484,8 @@ MipsSETargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const {
return performADDECombine(N, DAG, DCI, Subtarget);
case ISD::SUBE:
return performSUBECombine(N, DAG, DCI, Subtarget);
+ case ISD::MUL:
+ return performMULCombine(N, DAG, DCI, this);
case ISD::SHL:
return performSHLCombine(N, DAG, DCI, Subtarget);
case ISD::SRA: