summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/Target/ARM/ARMInstructionSelector.cpp27
-rw-r--r--llvm/lib/Target/ARM/ARMLegalizerInfo.cpp6
-rw-r--r--llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-exts.mir79
-rw-r--r--llvm/test/CodeGen/ARM/GlobalISel/thumb-select-exts.mir288
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
+...
OpenPOWER on IntegriCloud