Index: llvm/lib/Target/ARM/ARMBaseInstrInfo.h =================================================================== --- llvm/lib/Target/ARM/ARMBaseInstrInfo.h +++ llvm/lib/Target/ARM/ARMBaseInstrInfo.h @@ -884,6 +884,10 @@ return std::abs(Imm) < ((1 << 7) * 4) && Imm % 4 == 0; case ARMII::AddrModeT2_i8: return std::abs(Imm) < ((1 << 8) * 1); + case ARMII::AddrModeT2_i8pos: + return Imm >= 0 && Imm < ((1 << 8) * 1); + case ARMII::AddrModeT2_i8neg: + return Imm < 0 && -Imm < ((1 << 8) * 1); case ARMII::AddrModeT2_i8s4: return std::abs(Imm) < ((1 << 8) * 4) && Imm % 4 == 0; case ARMII::AddrModeT2_i12: Index: llvm/lib/Target/ARM/ARMFrameLowering.cpp =================================================================== --- llvm/lib/Target/ARM/ARMFrameLowering.cpp +++ llvm/lib/Target/ARM/ARMFrameLowering.cpp @@ -1693,7 +1693,7 @@ // Default 12 bit limit. break; case ARMII::AddrMode3: - case ARMII::AddrModeT2_i8: + case ARMII::AddrModeT2_i8neg: Limit = std::min(Limit, (1U << 8) - 1); break; case ARMII::AddrMode5FP16: Index: llvm/lib/Target/ARM/ARMInstrFormats.td =================================================================== --- llvm/lib/Target/ARM/ARMInstrFormats.td +++ llvm/lib/Target/ARM/ARMInstrFormats.td @@ -103,15 +103,17 @@ def AddrModeT1_s : AddrMode<10>; def AddrModeT2_i12 : AddrMode<11>; def AddrModeT2_i8 : AddrMode<12>; -def AddrModeT2_so : AddrMode<13>; -def AddrModeT2_pc : AddrMode<14>; -def AddrModeT2_i8s4 : AddrMode<15>; -def AddrMode_i12 : AddrMode<16>; -def AddrMode5FP16 : AddrMode<17>; -def AddrModeT2_ldrex : AddrMode<18>; -def AddrModeT2_i7s4 : AddrMode<19>; -def AddrModeT2_i7s2 : AddrMode<20>; -def AddrModeT2_i7 : AddrMode<21>; +def AddrModeT2_i8pos : AddrMode<13>; +def AddrModeT2_i8neg : AddrMode<14>; +def AddrModeT2_so : AddrMode<15>; +def AddrModeT2_pc : AddrMode<16>; +def AddrModeT2_i8s4 : AddrMode<17>; +def AddrMode_i12 : AddrMode<18>; +def AddrMode5FP16 : AddrMode<19>; +def AddrModeT2_ldrex : AddrMode<20>; +def AddrModeT2_i7s4 : AddrMode<21>; +def AddrModeT2_i7s2 : AddrMode<22>; +def AddrModeT2_i7 : AddrMode<23>; // Load / store index mode. class IndexMode val> { @@ -1392,9 +1394,12 @@ class T2Ii12 pattern> : Thumb2I; -class T2Ii8 pattern> - : Thumb2I; +class T2Ii8p pattern> + : Thumb2I; +class T2Ii8n pattern> + : Thumb2I; class T2Iso pattern> : Thumb2I; Index: llvm/lib/Target/ARM/ARMInstrThumb2.td =================================================================== --- llvm/lib/Target/ARM/ARMInstrThumb2.td +++ llvm/lib/Target/ARM/ARMInstrThumb2.td @@ -1191,9 +1191,9 @@ let DecoderMethod = "DecodeT2LoadImm12"; } - def i8 : T2Ii8 <(outs target:$Rt), (ins t2addrmode_negimm8:$addr), iii, - opc, "\t$Rt, $addr", - [(set target:$Rt, (opnode t2addrmode_negimm8:$addr))]>, + def i8 : T2Ii8n <(outs target:$Rt), (ins t2addrmode_negimm8:$addr), iii, + opc, "\t$Rt, $addr", + [(set target:$Rt, (opnode t2addrmode_negimm8:$addr))]>, Sched<[WriteLd]> { bits<4> Rt; bits<13> addr; @@ -1284,9 +1284,9 @@ let Inst{23} = addr{12}; // U let Inst{11-0} = addr{11-0}; // imm } - def i8 : T2Ii8 <(outs), (ins target:$Rt, t2addrmode_negimm8:$addr), iii, - opc, "\t$Rt, $addr", - [(opnode target:$Rt, t2addrmode_negimm8:$addr)]>, + def i8 : T2Ii8n <(outs), (ins target:$Rt, t2addrmode_negimm8:$addr), iii, + opc, "\t$Rt, $addr", + [(opnode target:$Rt, t2addrmode_negimm8:$addr)]>, Sched<[WriteST]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0000; @@ -1580,8 +1580,8 @@ // LDRT, LDRBT, LDRHT, LDRSBT, LDRSHT all have offset mode (PUW=0b110). // Ref: A8.6.57 LDR (immediate, Thumb) Encoding T4 class T2IldT type, string opc, InstrItinClass ii> - : T2Ii8<(outs rGPR:$Rt), (ins t2addrmode_posimm8:$addr), ii, opc, - "\t$Rt, $addr", []>, Sched<[WriteLd]> { + : T2Ii8p<(outs rGPR:$Rt), (ins t2addrmode_posimm8:$addr), ii, opc, + "\t$Rt, $addr", []>, Sched<[WriteLd]> { bits<4> Rt; bits<13> addr; let Inst{31-27} = 0b11111; @@ -1747,8 +1747,8 @@ // only. // Ref: A8.6.193 STR (immediate, Thumb) Encoding T4 class T2IstT type, string opc, InstrItinClass ii> - : T2Ii8<(outs), (ins rGPR:$Rt, t2addrmode_imm8:$addr), ii, opc, - "\t$Rt, $addr", []>, Sched<[WriteST]> { + : T2Ii8p<(outs), (ins rGPR:$Rt, t2addrmode_posimm8:$addr), ii, opc, + "\t$Rt, $addr", []>, Sched<[WriteST]> { let Inst{31-27} = 0b11111; let Inst{26-25} = 0b00; let Inst{24} = 0; // not signed @@ -1851,8 +1851,8 @@ let DecoderMethod = "DecodeT2LoadImm12"; } - def i8 : T2Ii8<(outs), (ins t2addrmode_negimm8:$addr), IIC_Preload, opc, - "\t$addr", + def i8 : T2Ii8n<(outs), (ins t2addrmode_negimm8:$addr), IIC_Preload, opc, + "\t$addr", [(ARMPreload t2addrmode_negimm8:$addr, (i32 write), (i32 instr))]>, Sched<[WritePreLd]> { let Inst{31-25} = 0b1111100; Index: llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp =================================================================== --- llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp +++ llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp @@ -2708,13 +2708,13 @@ if (isLegalAddressImm(Opcode, Imm, TII)) return true; - // We can convert AddrModeT2_i12 to AddrModeT2_i8. + // We can convert AddrModeT2_i12 to AddrModeT2_i8neg. const MCInstrDesc &Desc = TII->get(Opcode); unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); switch (AddrMode) { case ARMII::AddrModeT2_i12: CodesizeEstimate += 1; - return std::abs(Imm) < (((1 << 8) * 1) - 1); + return Imm < 0 && -Imm < ((1 << 8) * 1); } return false; } Index: llvm/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h =================================================================== --- llvm/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h +++ llvm/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h @@ -195,16 +195,18 @@ AddrModeT1_4 = 9, AddrModeT1_s = 10, // i8 * 4 for pc and sp relative data AddrModeT2_i12 = 11, - AddrModeT2_i8 = 12, - AddrModeT2_so = 13, - AddrModeT2_pc = 14, // +/- i12 for pc relative data - AddrModeT2_i8s4 = 15, // i8 * 4 - AddrMode_i12 = 16, - AddrMode5FP16 = 17, // i8 * 2 - AddrModeT2_ldrex = 18, // i8 * 4, with unscaled offset in MCInst - AddrModeT2_i7s4 = 19, // i7 * 4 - AddrModeT2_i7s2 = 20, // i7 * 2 - AddrModeT2_i7 = 21, // i7 * 1 + AddrModeT2_i8 = 12, // +/- i8 + AddrModeT2_i8pos = 13, // + i8 + AddrModeT2_i8neg = 14, // - i8 + AddrModeT2_so = 15, + AddrModeT2_pc = 16, // +/- i12 for pc relative data + AddrModeT2_i8s4 = 17, // i8 * 4 + AddrMode_i12 = 18, + AddrMode5FP16 = 19, // i8 * 2 + AddrModeT2_ldrex = 20, // i8 * 4, with unscaled offset in MCInst + AddrModeT2_i7s4 = 21, // i7 * 4 + AddrModeT2_i7s2 = 22, // i7 * 2 + AddrModeT2_i7 = 23, // i7 * 1 }; inline static const char *AddrModeToString(AddrMode addrmode) { @@ -223,6 +225,8 @@ case AddrModeT1_s: return "AddrModeT1_s"; case AddrModeT2_i12: return "AddrModeT2_i12"; case AddrModeT2_i8: return "AddrModeT2_i8"; + case AddrModeT2_i8pos: return "AddrModeT2_i8pos"; + case AddrModeT2_i8neg: return "AddrModeT2_i8neg"; case AddrModeT2_so: return "AddrModeT2_so"; case AddrModeT2_pc: return "AddrModeT2_pc"; case AddrModeT2_i8s4: return "AddrModeT2_i8s4"; Index: llvm/lib/Target/ARM/Thumb2InstrInfo.cpp =================================================================== --- llvm/lib/Target/ARM/Thumb2InstrInfo.cpp +++ llvm/lib/Target/ARM/Thumb2InstrInfo.cpp @@ -634,7 +634,8 @@ unsigned NumBits = 0; unsigned Scale = 1; - if (AddrMode == ARMII::AddrModeT2_i8 || AddrMode == ARMII::AddrModeT2_i12) { + if (AddrMode == ARMII::AddrModeT2_i8neg || + AddrMode == ARMII::AddrModeT2_i12) { // i8 supports only negative, and i12 supports only positive, so // based on Offset sign convert Opcode to the appropriate // instruction Index: llvm/test/CodeGen/Thumb2/postinc-distribute.mir =================================================================== --- llvm/test/CodeGen/Thumb2/postinc-distribute.mir +++ llvm/test/CodeGen/Thumb2/postinc-distribute.mir @@ -610,11 +610,12 @@ ; CHECK: liveins: $r0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:gprnopc = COPY $r0 - ; CHECK-NEXT: [[t2LDRH_POST:%[0-9]+]]:rgpr, [[t2LDRH_POST1:%[0-9]+]]:rgpr = t2LDRH_POST [[COPY]], -32, 14 /* CC::al */, $noreg :: (load (s32)) - ; CHECK-NEXT: [[t2LDRHi12_:%[0-9]+]]:rgpr = t2LDRHi12 [[t2LDRH_POST1]], 36, 14 /* CC::al */, $noreg :: (load (s32)) - ; CHECK-NEXT: [[t2LDRHi8_:%[0-9]+]]:rgpr = t2LDRHi8 [[t2LDRH_POST1]], 24, 14 /* CC::al */, $noreg :: (load (s32)) - ; CHECK-NEXT: [[t2LDRSHi12_:%[0-9]+]]:rgpr = t2LDRSHi12 [[t2LDRH_POST1]], 44, 14 /* CC::al */, $noreg :: (load (s32)) - ; CHECK-NEXT: $r0 = COPY [[t2LDRH_POST1]] + ; CHECK-NEXT: [[t2LDRHi12_:%[0-9]+]]:rgpr = t2LDRHi12 [[COPY]], 0, 14 /* CC::al */, $noreg :: (load (s32)) + ; CHECK-NEXT: [[t2SUBri:%[0-9]+]]:rgpr = nuw t2SUBri [[COPY]], 32, 14 /* CC::al */, $noreg, $noreg + ; CHECK-NEXT: [[t2LDRHi12_1:%[0-9]+]]:rgpr = t2LDRHi12 [[COPY]], 4, 14 /* CC::al */, $noreg :: (load (s32)) + ; CHECK-NEXT: [[t2LDRHi8_:%[0-9]+]]:rgpr = t2LDRHi8 [[COPY]], -8, 14 /* CC::al */, $noreg :: (load (s32)) + ; CHECK-NEXT: [[t2LDRSHi12_:%[0-9]+]]:rgpr = t2LDRSHi12 [[COPY]], 12, 14 /* CC::al */, $noreg :: (load (s32)) + ; CHECK-NEXT: $r0 = COPY [[t2SUBri]] ; CHECK-NEXT: tBX_RET 14 /* CC::al */, $noreg, implicit $r0 %0:gprnopc = COPY $r0 %1:rgpr = t2LDRHi12 %0, 0, 14, $noreg :: (load (s32), align 4) @@ -646,11 +647,12 @@ ; CHECK: liveins: $r0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:gprnopc = COPY $r0 - ; CHECK-NEXT: [[t2LDRB_POST:%[0-9]+]]:rgpr, [[t2LDRB_POST1:%[0-9]+]]:rgpr = t2LDRB_POST [[COPY]], -32, 14 /* CC::al */, $noreg :: (load (s32)) - ; CHECK-NEXT: [[t2LDRBi12_:%[0-9]+]]:rgpr = t2LDRBi12 [[t2LDRB_POST1]], 36, 14 /* CC::al */, $noreg :: (load (s32)) - ; CHECK-NEXT: [[t2LDRBi8_:%[0-9]+]]:rgpr = t2LDRBi8 [[t2LDRB_POST1]], 24, 14 /* CC::al */, $noreg :: (load (s32)) - ; CHECK-NEXT: [[t2LDRSBi12_:%[0-9]+]]:rgpr = t2LDRSBi12 [[t2LDRB_POST1]], 44, 14 /* CC::al */, $noreg :: (load (s32)) - ; CHECK-NEXT: $r0 = COPY [[t2LDRB_POST1]] + ; CHECK-NEXT: [[t2LDRBi12_:%[0-9]+]]:rgpr = t2LDRBi12 [[COPY]], 0, 14 /* CC::al */, $noreg :: (load (s32)) + ; CHECK-NEXT: [[t2SUBri:%[0-9]+]]:rgpr = nuw t2SUBri [[COPY]], 32, 14 /* CC::al */, $noreg, $noreg + ; CHECK-NEXT: [[t2LDRBi12_1:%[0-9]+]]:rgpr = t2LDRBi12 [[COPY]], 4, 14 /* CC::al */, $noreg :: (load (s32)) + ; CHECK-NEXT: [[t2LDRBi8_:%[0-9]+]]:rgpr = t2LDRBi8 [[COPY]], -8, 14 /* CC::al */, $noreg :: (load (s32)) + ; CHECK-NEXT: [[t2LDRSBi12_:%[0-9]+]]:rgpr = t2LDRSBi12 [[COPY]], 12, 14 /* CC::al */, $noreg :: (load (s32)) + ; CHECK-NEXT: $r0 = COPY [[t2SUBri]] ; CHECK-NEXT: tBX_RET 14 /* CC::al */, $noreg, implicit $r0 %0:gprnopc = COPY $r0 %1:rgpr = t2LDRBi12 %0, 0, 14, $noreg :: (load (s32), align 4) @@ -716,10 +718,11 @@ ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:gprnopc = COPY $r0 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:rgpr = COPY $r1 - ; CHECK-NEXT: early-clobber %2:rgpr = t2STRH_POST [[COPY1]], [[COPY]], -32, 14 /* CC::al */, $noreg :: (store (s32)) - ; CHECK-NEXT: t2STRHi12 [[COPY1]], %2, 36, 14 /* CC::al */, $noreg :: (store (s32)) - ; CHECK-NEXT: t2STRHi8 [[COPY1]], %2, 24, 14 /* CC::al */, $noreg :: (store (s32)) - ; CHECK-NEXT: $r0 = COPY %2 + ; CHECK-NEXT: t2STRHi12 [[COPY1]], [[COPY]], 0, 14 /* CC::al */, $noreg :: (store (s32)) + ; CHECK-NEXT: [[t2SUBri:%[0-9]+]]:rgpr = nuw t2SUBri [[COPY]], 32, 14 /* CC::al */, $noreg, $noreg + ; CHECK-NEXT: t2STRHi12 [[COPY1]], [[COPY]], 4, 14 /* CC::al */, $noreg :: (store (s32)) + ; CHECK-NEXT: t2STRHi8 [[COPY1]], [[COPY]], -8, 14 /* CC::al */, $noreg :: (store (s32)) + ; CHECK-NEXT: $r0 = COPY [[t2SUBri]] ; CHECK-NEXT: tBX_RET 14 /* CC::al */, $noreg, implicit $r0 %0:gprnopc = COPY $r0 %1:rgpr = COPY $r1 @@ -750,10 +753,11 @@ ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:gprnopc = COPY $r0 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:rgpr = COPY $r1 - ; CHECK-NEXT: early-clobber %2:rgpr = t2STRB_POST [[COPY1]], [[COPY]], -32, 14 /* CC::al */, $noreg :: (store (s32)) - ; CHECK-NEXT: t2STRBi12 [[COPY1]], %2, 36, 14 /* CC::al */, $noreg :: (store (s32)) - ; CHECK-NEXT: t2STRBi8 [[COPY1]], %2, 24, 14 /* CC::al */, $noreg :: (store (s32)) - ; CHECK-NEXT: $r0 = COPY %2 + ; CHECK-NEXT: t2STRBi12 [[COPY1]], [[COPY]], 0, 14 /* CC::al */, $noreg :: (store (s32)) + ; CHECK-NEXT: [[t2SUBri:%[0-9]+]]:rgpr = nuw t2SUBri [[COPY]], 32, 14 /* CC::al */, $noreg, $noreg + ; CHECK-NEXT: t2STRBi12 [[COPY1]], [[COPY]], 4, 14 /* CC::al */, $noreg :: (store (s32)) + ; CHECK-NEXT: t2STRBi8 [[COPY1]], [[COPY]], -8, 14 /* CC::al */, $noreg :: (store (s32)) + ; CHECK-NEXT: $r0 = COPY [[t2SUBri]] ; CHECK-NEXT: tBX_RET 14 /* CC::al */, $noreg, implicit $r0 %0:gprnopc = COPY $r0 %1:rgpr = COPY $r1