Index: lib/Target/ARM/ARMISelDAGToDAG.cpp =================================================================== --- lib/Target/ARM/ARMISelDAGToDAG.cpp +++ lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -1032,8 +1032,23 @@ // Thumb Addressing Modes //===----------------------------------------------------------------------===// +static bool shouldUseZeroOffsetLdSt(SDValue N) { + // Negative numbers are difficult to materialise in thumb1. If we are + // selecting the add of a negative, we want 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; + + if (auto C = dyn_cast(N.getOperand(1))) + return C->getSExtValue() < 0; + + return false; +} + bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N, SDValue &Base, SDValue &Offset){ + if (shouldUseZeroOffsetLdSt(N)) + return false; // Select ri instead if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) { ConstantSDNode *NC = dyn_cast(N); if (!NC || !NC->isNullValue()) @@ -1051,6 +1066,12 @@ 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 Index: test/CodeGen/ARM/load.ll =================================================================== --- test/CodeGen/ARM/load.ll +++ test/CodeGen/ARM/load.ll @@ -568,9 +568,9 @@ define i32 @ldrsb_ri_negative(i8* %p) { ; CHECK-LABEL: ldrsb_ri_negative: -; CHECK-T1: movs r1, #3 -; CHECK-T1: mvns r1, r1 -; CHECK-T1: ldrsb r0, [r0, r1] +; CHECK-T1: subs r0, r0, #4 +; CHECK-T1: ldrb r0, [r0] +; CHECK-T1: sxtb r0, r0 ; CHECK-T2: ldrsb r0, [r0, #-4] entry: %add.ptr = getelementptr inbounds i8, i8* %p, i32 -4 @@ -581,9 +581,9 @@ define i32 @ldrsh_ri_negative(i8* %p) { ; CHECK-LABEL: ldrsh_ri_negative: -; CHECK-T1: movs r1, #3 -; CHECK-T1: mvns r1, r1 -; CHECK-T1: ldrsh r0, [r0, r1] +; CHECK-T1: subs r0, r0, #4 +; CHECK-T1: ldrh r0, [r0] +; CHECK-T1: sxth r0, r0 ; CHECK-T2: ldrsh r0, [r0, #-4] entry: %add.ptr = getelementptr inbounds i8, i8* %p, i32 -4 @@ -595,9 +595,8 @@ define i32 @ldrb_ri_negative(i8* %p) { ; CHECK-LABEL: ldrb_ri_negative: -; CHECK-T1: movs r1, #3 -; CHECK-T1: mvns r1, r1 -; CHECK-T1: ldrb r0, [r0, r1] +; CHECK-T1: subs r0, r0, #4 +; CHECK-T1: ldrb r0, [r0] ; CHECK-T2: ldrb r0, [r0, #-4] entry: %add.ptr = getelementptr inbounds i8, i8* %p, i32 -4 @@ -608,9 +607,8 @@ define i32 @ldrh_ri_negative(i8* %p) { ; CHECK-LABEL: ldrh_ri_negative: -; CHECK-T1: movs r1, #3 -; CHECK-T1: mvns r1, r1 -; CHECK-T1: ldrh r0, [r0, r1] +; CHECK-T1: subs r0, r0, #4 +; CHECK-T1: ldrh r0, [r0] ; CHECK-T2: ldrh r0, [r0, #-4] entry: %add.ptr = getelementptr inbounds i8, i8* %p, i32 -4 @@ -622,9 +620,8 @@ define i32 @ldr_ri_negative(i8* %p) { ; CHECK-LABEL: ldr_ri_negative: -; CHECK-T1: movs r1, #3 -; CHECK-T1: mvns r1, r1 -; CHECK-T1: ldr r0, [r0, r1] +; CHECK-T1: subs r0, r0, #4 +; CHECK-T1: ldr r0, [r0] ; CHECK-T2: ldr r0, [r0, #-4] entry: %add.ptr = getelementptr inbounds i8, i8* %p, i32 -4 @@ -635,9 +632,8 @@ define void @strb_ri_negative(i8* %p, i32 %x) { ; CHECK-LABEL: strb_ri_negative: -; CHECK-T1: movs r2, #3 -; CHECK-T1: mvns r2, r2 -; CHECK-T1: strb r1, [r0, r2] +; CHECK-T1: subs r0, r0, #4 +; CHECK-T1: strb r1, [r0] ; CHECK-T2: strb r1, [r0, #-4] entry: %conv = trunc i32 %x to i8 @@ -648,9 +644,8 @@ define void @strh_ri_negative(i8* %p, i32 %x) { ; CHECK-LABEL: strh_ri_negative: -; CHECK-T1: movs r2, #3 -; CHECK-T1: mvns r2, r2 -; CHECK-T1: strh r1, [r0, r2] +; CHECK-T1: subs r0, r0, #4 +; CHECK-T1: strh r1, [r0] ; CHECK-T2: strh r1, [r0, #-4] entry: %conv = trunc i32 %x to i16 @@ -662,9 +657,8 @@ define void @str_ri_negative(i8* %p, i32 %x) { ; CHECK-LABEL: str_ri_negative: -; CHECK-T1: movs r2, #3 -; CHECK-T1: mvns r2, r2 -; CHECK-T1: str r1, [r0, r2] +; CHECK-T1: subs r0, r0, #4 +; CHECK-T1: str r1, [r0] ; CHECK-T2: str r1, [r0, #-4] entry: %add.ptr = getelementptr inbounds i8, i8* %p, i32 -4