diff options
| -rw-r--r-- | llvm/lib/Target/ARM/ARMISelDAGToDAG.cpp | 32 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMInstrThumb.td | 21 | ||||
| -rw-r--r-- | llvm/test/CodeGen/ARM/load.ll | 60 | 
3 files changed, 71 insertions, 42 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, diff --git a/llvm/test/CodeGen/ARM/load.ll b/llvm/test/CodeGen/ARM/load.ll index d44bdac97a0..f33294267f5 100644 --- a/llvm/test/CodeGen/ARM/load.ll +++ b/llvm/test/CodeGen/ARM/load.ll @@ -608,9 +608,8 @@ entry:  define i32 @ldrb_ri_negative(i8* %p) {  ; CHECK-T1-LABEL: ldrb_ri_negative:  ; CHECK-T1:       @ %bb.0: @ %entry -; CHECK-T1-NEXT:    movs r1, #0 -; CHECK-T1-NEXT:    mvns r1, r1 -; CHECK-T1-NEXT:    ldrb r0, [r0, r1] +; CHECK-T1-NEXT:    subs r0, r0, #1 +; CHECK-T1-NEXT:    ldrb r0, [r0]  ; CHECK-T1-NEXT:    bx lr  ;  ; CHECK-T2-LABEL: ldrb_ri_negative: @@ -627,9 +626,8 @@ entry:  define i32 @ldrh_ri_negative(i8* %p) {  ; CHECK-T1-LABEL: ldrh_ri_negative:  ; CHECK-T1:       @ %bb.0: @ %entry -; CHECK-T1-NEXT:    movs r1, #0 -; CHECK-T1-NEXT:    mvns r1, r1 -; CHECK-T1-NEXT:    ldrh r0, [r0, r1] +; CHECK-T1-NEXT:    subs r0, r0, #1 +; CHECK-T1-NEXT:    ldrh r0, [r0]  ; CHECK-T1-NEXT:    bx lr  ;  ; CHECK-T2-LABEL: ldrh_ri_negative: @@ -647,9 +645,8 @@ entry:  define i32 @ldr_ri_negative(i8* %p) {  ; CHECK-T1-LABEL: ldr_ri_negative:  ; CHECK-T1:       @ %bb.0: @ %entry -; CHECK-T1-NEXT:    movs r1, #0 -; CHECK-T1-NEXT:    mvns r1, r1 -; CHECK-T1-NEXT:    ldr r0, [r0, r1] +; CHECK-T1-NEXT:    subs r0, r0, #1 +; CHECK-T1-NEXT:    ldr r0, [r0]  ; CHECK-T1-NEXT:    bx lr  ;  ; CHECK-T2-LABEL: ldr_ri_negative: @@ -666,9 +663,8 @@ entry:  define void @strb_ri_negative(i8* %p, i32 %x) {  ; CHECK-T1-LABEL: strb_ri_negative:  ; CHECK-T1:       @ %bb.0: @ %entry -; CHECK-T1-NEXT:    movs r2, #0 -; CHECK-T1-NEXT:    mvns r2, r2 -; CHECK-T1-NEXT:    strb r1, [r0, r2] +; CHECK-T1-NEXT:    subs r0, r0, #1 +; CHECK-T1-NEXT:    strb r1, [r0]  ; CHECK-T1-NEXT:    bx lr  ;  ; CHECK-T2-LABEL: strb_ri_negative: @@ -685,9 +681,8 @@ entry:  define void @strh_ri_negative(i8* %p, i32 %x) {  ; CHECK-T1-LABEL: strh_ri_negative:  ; CHECK-T1:       @ %bb.0: @ %entry -; CHECK-T1-NEXT:    movs r2, #0 -; CHECK-T1-NEXT:    mvns r2, r2 -; CHECK-T1-NEXT:    strh r1, [r0, r2] +; CHECK-T1-NEXT:    subs r0, r0, #1 +; CHECK-T1-NEXT:    strh r1, [r0]  ; CHECK-T1-NEXT:    bx lr  ;  ; CHECK-T2-LABEL: strh_ri_negative: @@ -705,9 +700,8 @@ entry:  define void @str_ri_negative(i8* %p, i32 %x) {  ; CHECK-T1-LABEL: str_ri_negative:  ; CHECK-T1:       @ %bb.0: @ %entry -; CHECK-T1-NEXT:    movs r2, #0 -; CHECK-T1-NEXT:    mvns r2, r2 -; CHECK-T1-NEXT:    str r1, [r0, r2] +; CHECK-T1-NEXT:    subs r0, r0, #1 +; CHECK-T1-NEXT:    str r1, [r0]  ; CHECK-T1-NEXT:    bx lr  ;  ; CHECK-T2-LABEL: str_ri_negative: @@ -766,9 +760,8 @@ entry:  define i32 @ldrb_ri_negative255(i8* %p) {  ; CHECK-T1-LABEL: ldrb_ri_negative255:  ; CHECK-T1:       @ %bb.0: @ %entry -; CHECK-T1-NEXT:    movs r1, #254 -; CHECK-T1-NEXT:    mvns r1, r1 -; CHECK-T1-NEXT:    ldrb r0, [r0, r1] +; CHECK-T1-NEXT:    subs r0, #255 +; CHECK-T1-NEXT:    ldrb r0, [r0]  ; CHECK-T1-NEXT:    bx lr  ;  ; CHECK-T2-LABEL: ldrb_ri_negative255: @@ -785,9 +778,8 @@ entry:  define i32 @ldrh_ri_negative255(i8* %p) {  ; CHECK-T1-LABEL: ldrh_ri_negative255:  ; CHECK-T1:       @ %bb.0: @ %entry -; CHECK-T1-NEXT:    movs r1, #254 -; CHECK-T1-NEXT:    mvns r1, r1 -; CHECK-T1-NEXT:    ldrh r0, [r0, r1] +; CHECK-T1-NEXT:    subs r0, #255 +; CHECK-T1-NEXT:    ldrh r0, [r0]  ; CHECK-T1-NEXT:    bx lr  ;  ; CHECK-T2-LABEL: ldrh_ri_negative255: @@ -805,9 +797,8 @@ entry:  define i32 @ldr_ri_negative255(i8* %p) {  ; CHECK-T1-LABEL: ldr_ri_negative255:  ; CHECK-T1:       @ %bb.0: @ %entry -; CHECK-T1-NEXT:    movs r1, #254 -; CHECK-T1-NEXT:    mvns r1, r1 -; CHECK-T1-NEXT:    ldr r0, [r0, r1] +; CHECK-T1-NEXT:    subs r0, #255 +; CHECK-T1-NEXT:    ldr r0, [r0]  ; CHECK-T1-NEXT:    bx lr  ;  ; CHECK-T2-LABEL: ldr_ri_negative255: @@ -824,9 +815,8 @@ entry:  define void @strb_ri_negative255(i8* %p, i32 %x) {  ; CHECK-T1-LABEL: strb_ri_negative255:  ; CHECK-T1:       @ %bb.0: @ %entry -; CHECK-T1-NEXT:    movs r2, #254 -; CHECK-T1-NEXT:    mvns r2, r2 -; CHECK-T1-NEXT:    strb r1, [r0, r2] +; CHECK-T1-NEXT:    subs r0, #255 +; CHECK-T1-NEXT:    strb r1, [r0]  ; CHECK-T1-NEXT:    bx lr  ;  ; CHECK-T2-LABEL: strb_ri_negative255: @@ -843,9 +833,8 @@ entry:  define void @strh_ri_negative255(i8* %p, i32 %x) {  ; CHECK-T1-LABEL: strh_ri_negative255:  ; CHECK-T1:       @ %bb.0: @ %entry -; CHECK-T1-NEXT:    movs r2, #254 -; CHECK-T1-NEXT:    mvns r2, r2 -; CHECK-T1-NEXT:    strh r1, [r0, r2] +; CHECK-T1-NEXT:    subs r0, #255 +; CHECK-T1-NEXT:    strh r1, [r0]  ; CHECK-T1-NEXT:    bx lr  ;  ; CHECK-T2-LABEL: strh_ri_negative255: @@ -863,9 +852,8 @@ entry:  define void @str_ri_negative255(i8* %p, i32 %x) {  ; CHECK-T1-LABEL: str_ri_negative255:  ; CHECK-T1:       @ %bb.0: @ %entry -; CHECK-T1-NEXT:    movs r2, #254 -; CHECK-T1-NEXT:    mvns r2, r2 -; CHECK-T1-NEXT:    str r1, [r0, r2] +; CHECK-T1-NEXT:    subs r0, #255 +; CHECK-T1-NEXT:    str r1, [r0]  ; CHECK-T1-NEXT:    bx lr  ;  ; CHECK-T2-LABEL: str_ri_negative255:  | 

