forked from OSchip/llvm-project
[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
This commit is contained in:
parent
0b7fce6d72
commit
54b0115547
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue