summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/ARM/ARMISelLowering.cpp
diff options
context:
space:
mode:
authorSjoerd Meijer <sjoerd.meijer@arm.com>2018-11-30 08:14:28 +0000
committerSjoerd Meijer <sjoerd.meijer@arm.com>2018-11-30 08:14:28 +0000
commitecc7dcb879c3917f8e2092969511aa5776dcb398 (patch)
tree3ff343f7f45473821994d2e7251d079fd665e4e4 /llvm/lib/Target/ARM/ARMISelLowering.cpp
parent957578ddf71db9efedf9c7ca8a802e6bba3c90eb (diff)
downloadbcm5719-llvm-ecc7dcb879c3917f8e2092969511aa5776dcb398.tar.gz
bcm5719-llvm-ecc7dcb879c3917f8e2092969511aa5776dcb398.zip
[ARM] Don't expand sdiv when optimising for minsize
Don't expand SDIV with an immediate that is a power of 2 if we optimise for minimum code size. For example: sdiv %1, i32 4 gets expanded to a sequence of 3 instructions, but this is suboptimal for minimum code size so instead we just generate a MOV and a SDIV if integer division is supported. Differential Revision: https://reviews.llvm.org/D54546 llvm-svn: 347965
Diffstat (limited to 'llvm/lib/Target/ARM/ARMISelLowering.cpp')
-rw-r--r--llvm/lib/Target/ARM/ARMISelLowering.cpp44
1 files changed, 44 insertions, 0 deletions
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 56d2e510cb7..3eaa6103ead 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -7794,6 +7794,50 @@ SDValue ARMTargetLowering::LowerWindowsDIVLibCall(SDValue Op, SelectionDAG &DAG,
return LowerCallTo(CLI).first;
}
+// This is a code size optimisation: return the original SDIV node to
+// DAGCombiner when we don't want to expand SDIV into a sequence of
+// instructions, and an empty node otherwise which will cause the
+// SDIV to be expanded in DAGCombine.
+SDValue
+ARMTargetLowering::BuildSDIVPow2(SDNode *N, const APInt &Divisor,
+ SelectionDAG &DAG,
+ SmallVectorImpl<SDNode *> &Created) const {
+ // TODO: Support SREM
+ if (N->getOpcode() != ISD::SDIV)
+ return SDValue();
+
+ const auto &ST = static_cast<const ARMSubtarget&>(DAG.getSubtarget());
+ const auto &MF = DAG.getMachineFunction();
+ const bool MinSize = MF.getFunction().optForMinSize();
+ const bool HasDivide = ST.isThumb() ? ST.hasDivideInThumbMode()
+ : ST.hasDivideInARMMode();
+
+ // Don't touch vector types; rewriting this may lead to scalarizing
+ // the int divs.
+ if (N->getOperand(0).getValueType().isVector())
+ return SDValue();
+
+ // Bail if MinSize is not set, and also for both ARM and Thumb mode we need
+ // hwdiv support for this to be really profitable.
+ if (!(MinSize && HasDivide))
+ return SDValue();
+
+ // ARM mode is a bit simpler than Thumb: we can handle large power
+ // of 2 immediates with 1 mov instruction; no further checks required,
+ // just return the sdiv node.
+ if (!ST.isThumb())
+ return SDValue(N, 0);
+
+ // In Thumb mode, immediates larger than 128 need a wide 4-byte MOV,
+ // and thus lose the code size benefits of a MOVS that requires only 2.
+ // TargetTransformInfo and 'getIntImmCodeSizeCost' could be helpful here,
+ // but as it's doing exactly this, it's not worth the trouble to get TTI.
+ if (Divisor.sgt(128))
+ return SDValue();
+
+ return SDValue(N, 0);
+}
+
SDValue ARMTargetLowering::LowerDIV_Windows(SDValue Op, SelectionDAG &DAG,
bool Signed) const {
assert(Op.getValueType() == MVT::i32 &&
OpenPOWER on IntegriCloud