summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
authorDavid Green <david.green@arm.com>2019-01-29 10:40:31 +0000
committerDavid Green <david.green@arm.com>2019-01-29 10:40:31 +0000
commit54b011554715919de3f277e8dc1bf500f5b2b32c (patch)
tree2a6532946f6ca531a2ea80f449646a96dc408bab /llvm/lib/Target
parent0b7fce6d72f54c5c45aa98e1cee938b6c2b64303 (diff)
downloadbcm5719-llvm-54b011554715919de3f277e8dc1bf500f5b2b32c.tar.gz
bcm5719-llvm-54b011554715919de3f277e8dc1bf500f5b2b32c.zip
[ARM] Use sub for negative offset load/store in thumb1
This attempts to optimise negative values used in load/store operands a little. We currently try to selct them as rr, materialising the negative constant using a MOV/MVN pair. This instead selects ri with an immediate of 0, forcing the add node to become a simpler sub. Differential Revision: https://reviews.llvm.org/D57121 llvm-svn: 352475
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp32
-rw-r--r--llvm/lib/Target/ARM/ARMInstrThumb.td21
2 files changed, 47 insertions, 6 deletions
diff --git a/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp b/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
index 2c07ef7ec87..a51cbda4f1d 100644
--- a/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
+++ b/llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp
@@ -130,6 +130,7 @@ public:
// Thumb Addressing Modes:
bool SelectThumbAddrModeRR(SDValue N, SDValue &Base, SDValue &Offset);
+ bool SelectThumbAddrModeRRSext(SDValue N, SDValue &Base, SDValue &Offset);
bool SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, SDValue &Base,
SDValue &OffImm);
bool SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base,
@@ -1032,8 +1033,22 @@ bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N,
// Thumb Addressing Modes
//===----------------------------------------------------------------------===//
-bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N,
- SDValue &Base, SDValue &Offset){
+static bool shouldUseZeroOffsetLdSt(SDValue N) {
+ // Negative numbers are difficult to materialise in thumb1. If we are
+ // selecting the add of a negative, instead try to select ri with a zero
+ // offset, so create the add node directly which will become a sub.
+ if (N.getOpcode() != ISD::ADD)
+ return false;
+
+ // Look for an imm which is not legal for ld/st, but is legal for sub.
+ if (auto C = dyn_cast<ConstantSDNode>(N.getOperand(1)))
+ return C->getSExtValue() < 0 && C->getSExtValue() >= -255;
+
+ return false;
+}
+
+bool ARMDAGToDAGISel::SelectThumbAddrModeRRSext(SDValue N, SDValue &Base,
+ SDValue &Offset) {
if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) {
ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N);
if (!NC || !NC->isNullValue())
@@ -1048,9 +1063,22 @@ bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N,
return true;
}
+bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N, SDValue &Base,
+ SDValue &Offset) {
+ if (shouldUseZeroOffsetLdSt(N))
+ return false; // Select ri instead
+ return SelectThumbAddrModeRRSext(N, Base, Offset);
+}
+
bool
ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale,
SDValue &Base, SDValue &OffImm) {
+ if (shouldUseZeroOffsetLdSt(N)) {
+ Base = N;
+ OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i32);
+ return true;
+ }
+
if (!CurDAG->isBaseWithConstantOffset(N)) {
if (N.getOpcode() == ISD::ADD) {
return false; // We want to select register offset instead
diff --git a/llvm/lib/Target/ARM/ARMInstrThumb.td b/llvm/lib/Target/ARM/ARMInstrThumb.td
index 5076b717ae2..1035c4b8c48 100644
--- a/llvm/lib/Target/ARM/ARMInstrThumb.td
+++ b/llvm/lib/Target/ARM/ARMInstrThumb.td
@@ -187,6 +187,19 @@ def t_addrmode_rr : MemOperand,
let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
}
+// t_addrmode_rr_sext := reg + reg
+//
+// This is similar to t_addrmode_rr, but uses different heuristics for
+// ldrsb/ldrsh.
+def t_addrmode_rr_sext : MemOperand,
+ ComplexPattern<i32, 2, "SelectThumbAddrModeRRSext", []> {
+ let EncoderMethod = "getThumbAddrModeRegRegOpValue";
+ let PrintMethod = "printThumbAddrModeRROperand";
+ let DecoderMethod = "DecodeThumbAddrModeRR";
+ let ParserMatchClass = t_addrmode_rr_asm_operand;
+ let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
+}
+
// t_addrmode_rrs := reg + reg
//
// We use separate scaled versions because the Select* functions need
@@ -731,17 +744,17 @@ defm tLDRH : thumb_ld_rr_ri_enc<0b101, 0b1000, t_addrmode_rr,
let AddedComplexity = 10 in
def tLDRSB : // A8.6.80
- T1pILdStEncode<0b011, (outs tGPR:$Rt), (ins t_addrmode_rr:$addr),
+ T1pILdStEncode<0b011, (outs tGPR:$Rt), (ins t_addrmode_rr_sext:$addr),
AddrModeT1_1, IIC_iLoad_bh_r,
"ldrsb", "\t$Rt, $addr",
- [(set tGPR:$Rt, (sextloadi8 t_addrmode_rr:$addr))]>;
+ [(set tGPR:$Rt, (sextloadi8 t_addrmode_rr_sext:$addr))]>;
let AddedComplexity = 10 in
def tLDRSH : // A8.6.84
- T1pILdStEncode<0b111, (outs tGPR:$Rt), (ins t_addrmode_rr:$addr),
+ T1pILdStEncode<0b111, (outs tGPR:$Rt), (ins t_addrmode_rr_sext:$addr),
AddrModeT1_2, IIC_iLoad_bh_r,
"ldrsh", "\t$Rt, $addr",
- [(set tGPR:$Rt, (sextloadi16 t_addrmode_rr:$addr))]>;
+ [(set tGPR:$Rt, (sextloadi16 t_addrmode_rr_sext:$addr))]>;
def tSTRspi : T1pIs<(outs), (ins tGPR:$Rt, t_addrmode_sp:$addr), IIC_iStore_i,
OpenPOWER on IntegriCloud