diff options
| author | Sjoerd Meijer <sjoerd.meijer@arm.com> | 2018-11-30 08:14:28 +0000 | 
|---|---|---|
| committer | Sjoerd Meijer <sjoerd.meijer@arm.com> | 2018-11-30 08:14:28 +0000 | 
| commit | ecc7dcb879c3917f8e2092969511aa5776dcb398 (patch) | |
| tree | 3ff343f7f45473821994d2e7251d079fd665e4e4 /llvm/lib/Target/ARM/ARMISelLowering.cpp | |
| parent | 957578ddf71db9efedf9c7ca8a802e6bba3c90eb (diff) | |
| download | bcm5719-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.cpp | 44 | 
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 &&  | 

