diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/Target/ARM/ARMInstructionSelector.cpp | 27 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMLegalizerInfo.cpp | 6 | ||||
| -rw-r--r-- | llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-exts.mir | 79 | ||||
| -rw-r--r-- | llvm/test/CodeGen/ARM/GlobalISel/thumb-select-exts.mir | 288 |
4 files changed, 385 insertions, 15 deletions
diff --git a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp index 2d5c990ab0e..4007e9e02bc 100644 --- a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp +++ b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp @@ -229,17 +229,19 @@ static bool selectUnmergeValues(MachineInstrBuilder &MIB, /// instruction). Extension operations more complicated than that should not /// invoke this. Returns the original opcode if it doesn't know how to select a /// better one. -static unsigned selectSimpleExtOpc(unsigned Opc, unsigned Size) { +static unsigned selectSimpleExtOpc(unsigned Opc, unsigned Size, bool isThumb) { using namespace TargetOpcode; if (Size != 8 && Size != 16) return Opc; if (Opc == G_SEXT) - return Size == 8 ? ARM::SXTB : ARM::SXTH; + return isThumb ? Size == 8 ? ARM::t2SXTB : ARM::t2SXTH + : Size == 8 ? ARM::SXTB : ARM::SXTH; if (Opc == G_ZEXT) - return Size == 8 ? ARM::UXTB : ARM::UXTH; + return isThumb ? Size == 8 ? ARM::t2UXTB : ARM::t2UXTH + : Size == 8 ? ARM::UXTB : ARM::UXTH; return Opc; } @@ -715,7 +717,7 @@ bool ARMInstructionSelector::select(MachineInstr &I, switch (SrcSize) { case 1: { // ZExt boils down to & 0x1; for SExt we also subtract that from 0 - I.setDesc(TII.get(ARM::ANDri)); + I.setDesc(TII.get(STI.isThumb() ? ARM::t2ANDri : ARM::ANDri)); MIB.addImm(1).add(predOps(ARMCC::AL)).add(condCodeOp()); if (isSExt) { @@ -726,13 +728,13 @@ bool ARMInstructionSelector::select(MachineInstr &I, I.getOperand(0).setReg(AndResult); auto InsertBefore = std::next(I.getIterator()); - auto SubI = - BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(ARM::RSBri)) - .addDef(SExtResult) - .addUse(AndResult) - .addImm(0) - .add(predOps(ARMCC::AL)) - .add(condCodeOp()); + auto SubI = BuildMI(MBB, InsertBefore, I.getDebugLoc(), + TII.get(STI.isThumb() ? ARM::t2RSBri : ARM::RSBri)) + .addDef(SExtResult) + .addUse(AndResult) + .addImm(0) + .add(predOps(ARMCC::AL)) + .add(condCodeOp()); if (!constrainSelectedInstRegOperands(*SubI, TII, TRI, RBI)) return false; } @@ -740,7 +742,8 @@ bool ARMInstructionSelector::select(MachineInstr &I, } case 8: case 16: { - unsigned NewOpc = selectSimpleExtOpc(I.getOpcode(), SrcSize); + unsigned NewOpc = + selectSimpleExtOpc(I.getOpcode(), SrcSize, STI.isThumb()); if (NewOpc == I.getOpcode()) return false; I.setDesc(TII.get(NewOpc)); diff --git a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp index 2edeeacb6c6..a8bfd03a1f4 100644 --- a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp +++ b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp @@ -82,6 +82,9 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) { return; } + getActionDefinitionsBuilder({G_SEXT, G_ZEXT, G_ANYEXT}) + .legalForCartesianProduct({s32}, {s1, s8, s16}); + // We're keeping these builders around because we'll want to add support for // floating point to them. auto &LoadStoreBuilder = @@ -126,9 +129,6 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) { setAction({Op, s32}, Libcall); } - getActionDefinitionsBuilder({G_SEXT, G_ZEXT, G_ANYEXT}) - .legalForCartesianProduct({s32}, {s1, s8, s16}); - getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, s32}}); getActionDefinitionsBuilder(G_PTRTOINT).legalFor({{s32, p0}}); diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-exts.mir b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-exts.mir new file mode 100644 index 00000000000..672b42671a1 --- /dev/null +++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-exts.mir @@ -0,0 +1,79 @@ +# RUN: llc -mtriple arm-- -run-pass=legalizer %s -o - | FileCheck %s +# RUN: llc -mtriple thumb-- -mattr=+v6t2 -run-pass=legalizer %s -o - | FileCheck %s +--- | + define void @test_zext_s16() { ret void } + define void @test_sext_s8() { ret void } + define void @test_anyext_s1() { ret void } +... +--- +name: test_zext_s16 +# CHECK-LABEL: name: test_zext_s16 +legalized: false +# CHECK: legalized: true +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +body: | + bb.0: + liveins: $r0 + + %0(p0) = COPY $r0 + %1(s16) = G_LOAD %0 :: (load 2) + %2(s32) = G_ZEXT %1 + ; G_ZEXT with s16 is legal, so we should find it unchanged in the output + ; CHECK: {{%[0-9]+}}:_(s32) = G_ZEXT {{%[0-9]+}} + $r0 = COPY %2(s32) + BX_RET 14, $noreg, implicit $r0 +... +--- +name: test_sext_s8 +# CHECK-LABEL: name: test_sext_s8 +legalized: false +# CHECK: legalized: true +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +body: | + bb.0: + liveins: $r0 + + %0(p0) = COPY $r0 + %1(s8) = G_LOAD %0(p0) :: (load 1) + %2(s32) = G_SEXT %1 + ; G_SEXT with s8 is legal, so we should find it unchanged in the output + ; CHECK: {{%[0-9]+}}:_(s32) = G_SEXT {{%[0-9]+}} + $r0 = COPY %2(s32) + BX_RET 14, $noreg, implicit $r0 +... +--- +name: test_anyext_s1 +# CHECK-LABEL: name: test_anyext_s1 +legalized: false +# CHECK: legalized: true +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +body: | + bb.0: + liveins: $r0 + + %0(p0) = COPY $r0 + %1(s1) = G_LOAD %0(p0) :: (load 1) + %2(s32) = G_ANYEXT %1 + ; G_ANYEXT with s1 is legal, so we should find it unchanged in the output + ; CHECK: {{%[0-9]+}}:_(s32) = G_ANYEXT {{%[0-9]+}} + $r0 = COPY %2(s32) + BX_RET 14, $noreg, implicit $r0 +... diff --git a/llvm/test/CodeGen/ARM/GlobalISel/thumb-select-exts.mir b/llvm/test/CodeGen/ARM/GlobalISel/thumb-select-exts.mir new file mode 100644 index 00000000000..365a614d6ec --- /dev/null +++ b/llvm/test/CodeGen/ARM/GlobalISel/thumb-select-exts.mir @@ -0,0 +1,288 @@ +# RUN: llc -O0 -mtriple thumb-- -mattr=+v6t2 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s +--- | + define void @test_trunc_and_zext_s1() { ret void } + define void @test_trunc_and_sext_s1() { ret void } + define void @test_trunc_and_anyext_s1() { ret void } + + define void @test_trunc_and_zext_s8() { ret void } + define void @test_trunc_and_sext_s8() { ret void } + define void @test_trunc_and_anyext_s8() { ret void } + + define void @test_trunc_and_zext_s16() { ret void } + define void @test_trunc_and_sext_s16() { ret void } + define void @test_trunc_and_anyext_s16() { ret void } +... +--- +name: test_trunc_and_zext_s1 +# CHECK-LABEL: name: test_trunc_and_zext_s1 +legalized: true +regBankSelected: true +selected: false +# CHECK: selected: true +tracksRegLiveness: true +registers: + - { id: 0, class: gprb } + - { id: 1, class: gprb } + - { id: 2, class: gprb } +body: | + bb.0: + liveins: $r0 + + %0(s32) = COPY $r0 + ; CHECK: [[VREG:%[0-9]+]]:gpr = COPY $r0 + + %1(s1) = G_TRUNC %0(s32) + + %2(s32) = G_ZEXT %1(s1) + ; CHECK: [[RVREG:%[0-9]+]]:rgpr = COPY [[VREG]] + ; CHECK: [[VREGEXT:%[0-9]+]]:rgpr = t2ANDri [[RVREG]], 1, 14, $noreg, $noreg + + $r0 = COPY %2(s32) + ; CHECK: $r0 = COPY [[VREGEXT]] + + BX_RET 14, $noreg, implicit $r0 + ; CHECK: BX_RET 14, $noreg, implicit $r0 +... +--- +name: test_trunc_and_sext_s1 +# CHECK-LABEL: name: test_trunc_and_sext_s1 +legalized: true +regBankSelected: true +selected: false +# CHECK: selected: true +tracksRegLiveness: true +registers: + - { id: 0, class: gprb } + - { id: 1, class: gprb } + - { id: 2, class: gprb } +body: | + bb.0: + liveins: $r0 + + %0(s32) = COPY $r0 + ; CHECK: [[VREG:%[0-9]+]]:gpr = COPY $r0 + + %1(s1) = G_TRUNC %0(s32) + + %2(s32) = G_SEXT %1(s1) + ; CHECK: [[RVREG:%[0-9]+]]:rgpr = COPY [[VREG]] + ; CHECK: [[VREGAND:%[0-9]+]]:rgpr = t2ANDri [[RVREG]], 1, 14, $noreg, $noreg + ; CHECK: [[VREGEXT:%[0-9]+]]:rgpr = t2RSBri [[VREGAND]], 0, 14, $noreg, $noreg + + $r0 = COPY %2(s32) + ; CHECK: $r0 = COPY [[VREGEXT]] + + BX_RET 14, $noreg, implicit $r0 + ; CHECK: BX_RET 14, $noreg, implicit $r0 +... +--- +name: test_trunc_and_anyext_s1 +# CHECK-LABEL: name: test_trunc_and_anyext_s1 +legalized: true +regBankSelected: true +selected: false +# CHECK: selected: true +tracksRegLiveness: true +registers: + - { id: 0, class: gprb } + - { id: 1, class: gprb } + - { id: 2, class: gprb } +body: | + bb.0: + liveins: $r0 + + %0(s32) = COPY $r0 + ; CHECK: [[VREG:%[0-9]+]]:gpr = COPY $r0 + + %1(s1) = G_TRUNC %0(s32) + + %2(s32) = G_ANYEXT %1(s1) + + $r0 = COPY %2(s32) + ; CHECK: $r0 = COPY [[VREG]] + + BX_RET 14, $noreg, implicit $r0 + ; CHECK: BX_RET 14, $noreg, implicit $r0 +... +--- +name: test_trunc_and_zext_s8 +# CHECK-LABEL: name: test_trunc_and_zext_s8 +legalized: true +regBankSelected: true +selected: false +# CHECK: selected: true +tracksRegLiveness: true +registers: + - { id: 0, class: gprb } + - { id: 1, class: gprb } + - { id: 2, class: gprb } +body: | + bb.0: + liveins: $r0 + + %0(s32) = COPY $r0 + ; CHECK: [[VREG:%[0-9]+]]:gpr = COPY $r0 + + %1(s8) = G_TRUNC %0(s32) + ; CHECK: [[VREGTRUNC:%[0-9]+]]:rgpr = COPY [[VREG]] + + %2(s32) = G_ZEXT %1(s8) + ; CHECK: [[VREGEXT:%[0-9]+]]:rgpr = t2UXTB [[VREGTRUNC]], 0, 14, $noreg + + $r0 = COPY %2(s32) + ; CHECK: $r0 = COPY [[VREGEXT]] + + BX_RET 14, $noreg, implicit $r0 + ; CHECK: BX_RET 14, $noreg, implicit $r0 +... +--- +name: test_trunc_and_sext_s8 +# CHECK-LABEL: name: test_trunc_and_sext_s8 +legalized: true +regBankSelected: true +selected: false +# CHECK: selected: true +tracksRegLiveness: true +registers: + - { id: 0, class: gprb } + - { id: 1, class: gprb } + - { id: 2, class: gprb } +body: | + bb.0: + liveins: $r0 + + %0(s32) = COPY $r0 + ; CHECK: [[VREG:%[0-9]+]]:gpr = COPY $r0 + + %1(s8) = G_TRUNC %0(s32) + ; CHECK: [[VREGTRUNC:%[0-9]+]]:rgpr = COPY [[VREG]] + + %2(s32) = G_SEXT %1(s8) + ; CHECK: [[VREGEXT:%[0-9]+]]:rgpr = t2SXTB [[VREGTRUNC]], 0, 14, $noreg + + $r0 = COPY %2(s32) + ; CHECK: $r0 = COPY [[VREGEXT]] + + BX_RET 14, $noreg, implicit $r0 + ; CHECK: BX_RET 14, $noreg, implicit $r0 +... +--- +name: test_trunc_and_anyext_s8 +# CHECK-LABEL: name: test_trunc_and_anyext_s8 +legalized: true +regBankSelected: true +selected: false +# CHECK: selected: true +tracksRegLiveness: true +registers: + - { id: 0, class: gprb } + - { id: 1, class: gprb } + - { id: 2, class: gprb } +body: | + bb.0: + liveins: $r0 + + %0(s32) = COPY $r0 + ; CHECK: [[VREG:%[0-9]+]]:gpr = COPY $r0 + + %1(s8) = G_TRUNC %0(s32) + + %2(s32) = G_ANYEXT %1(s8) + + $r0 = COPY %2(s32) + ; CHECK: $r0 = COPY [[VREG]] + + BX_RET 14, $noreg, implicit $r0 + ; CHECK: BX_RET 14, $noreg, implicit $r0 +... +--- +name: test_trunc_and_zext_s16 +# CHECK-LABEL: name: test_trunc_and_zext_s16 +legalized: true +regBankSelected: true +selected: false +# CHECK: selected: true +tracksRegLiveness: true +registers: + - { id: 0, class: gprb } + - { id: 1, class: gprb } + - { id: 2, class: gprb } +body: | + bb.0: + liveins: $r0 + + %0(s32) = COPY $r0 + ; CHECK: [[VREG:%[0-9]+]]:gpr = COPY $r0 + + %1(s16) = G_TRUNC %0(s32) + ; CHECK: [[VREGTRUNC:%[0-9]+]]:rgpr = COPY [[VREG]] + + %2(s32) = G_ZEXT %1(s16) + ; CHECK: [[VREGEXT:%[0-9]+]]:rgpr = t2UXTH [[VREGTRUNC]], 0, 14, $noreg + + $r0 = COPY %2(s32) + ; CHECK: $r0 = COPY [[VREGEXT]] + + BX_RET 14, $noreg, implicit $r0 + ; CHECK: BX_RET 14, $noreg, implicit $r0 +... +--- +name: test_trunc_and_sext_s16 +# CHECK-LABEL: name: test_trunc_and_sext_s16 +legalized: true +regBankSelected: true +selected: false +# CHECK: selected: true +tracksRegLiveness: true +registers: + - { id: 0, class: gprb } + - { id: 1, class: gprb } + - { id: 2, class: gprb } +body: | + bb.0: + liveins: $r0 + + %0(s32) = COPY $r0 + ; CHECK: [[VREG:%[0-9]+]]:gpr = COPY $r0 + + %1(s16) = G_TRUNC %0(s32) + ; CHECK: [[VREGTRUNC:%[0-9]+]]:rgpr = COPY [[VREG]] + + %2(s32) = G_SEXT %1(s16) + ; CHECK: [[VREGEXT:%[0-9]+]]:rgpr = t2SXTH [[VREGTRUNC]], 0, 14, $noreg + + $r0 = COPY %2(s32) + ; CHECK: $r0 = COPY [[VREGEXT]] + + BX_RET 14, $noreg, implicit $r0 + ; CHECK: BX_RET 14, $noreg, implicit $r0 +... +--- +name: test_trunc_and_anyext_s16 +# CHECK-LABEL: name: test_trunc_and_anyext_s16 +legalized: true +regBankSelected: true +selected: false +# CHECK: selected: true +tracksRegLiveness: true +registers: + - { id: 0, class: gprb } + - { id: 1, class: gprb } + - { id: 2, class: gprb } +body: | + bb.0: + liveins: $r0 + + %0(s32) = COPY $r0 + ; CHECK: [[VREG:%[0-9]+]]:gpr = COPY $r0 + + %1(s16) = G_TRUNC %0(s32) + + %2(s32) = G_ANYEXT %1(s16) + + $r0 = COPY %2(s32) + ; CHECK: $r0 = COPY [[VREG]] + + BX_RET 14, $noreg, implicit $r0 + ; CHECK: BX_RET 14, $noreg, implicit $r0 +... |

