forked from OSchip/llvm-project
[ARM] GlobalISel: Add support for G_TRUNC
Select them as copies. We only select if both the source and the destination are on the same register bank, so this shouldn't cause any trouble. llvm-svn: 300971
This commit is contained in:
parent
4df04ec227
commit
64a33431eb
|
@ -47,12 +47,9 @@ static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
|
|||
unsigned SrcReg = I.getOperand(1).getReg();
|
||||
const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
|
||||
(void)SrcSize;
|
||||
assert((DstSize == SrcSize ||
|
||||
// Copies are a means to setup initial types, the number of
|
||||
// bits may not exactly match.
|
||||
(TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
|
||||
DstSize <= SrcSize)) &&
|
||||
"Copy with different width?!");
|
||||
// We use copies for trunc, so it's ok for the size of the destination to be
|
||||
// smaller (the higher bits will just be undefined).
|
||||
assert(DstSize <= SrcSize && "Copy with different width?!");
|
||||
|
||||
assert((RegBank->getID() == ARM::GPRRegBankID ||
|
||||
RegBank->getID() == ARM::FPRRegBankID) &&
|
||||
|
@ -294,6 +291,28 @@ bool ARMInstructionSelector::select(MachineInstr &I) const {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case G_TRUNC: {
|
||||
// The high bits are undefined, so there's nothing special to do, just
|
||||
// treat it as a copy.
|
||||
auto SrcReg = I.getOperand(1).getReg();
|
||||
auto DstReg = I.getOperand(0).getReg();
|
||||
|
||||
const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
|
||||
const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
|
||||
|
||||
if (SrcRegBank.getID() != DstRegBank.getID()) {
|
||||
DEBUG(dbgs() << "G_TRUNC operands on different register banks\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (SrcRegBank.getID() != ARM::GPRRegBankID) {
|
||||
DEBUG(dbgs() << "G_TRUNC on non-GPR not supported yet\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
I.setDesc(TII.get(COPY));
|
||||
return selectCopy(I, TII, MRI, TRI, RBI);
|
||||
}
|
||||
case G_ADD:
|
||||
case G_GEP:
|
||||
I.setDesc(TII.get(ARM::ADDrr));
|
||||
|
|
|
@ -223,6 +223,7 @@ ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
|
|||
case G_MUL:
|
||||
case G_SEXT:
|
||||
case G_ZEXT:
|
||||
case G_TRUNC:
|
||||
case G_GEP:
|
||||
// FIXME: We're abusing the fact that everything lives in a GPR for now; in
|
||||
// the real world we would use different mappings.
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
define void @test_sext_s8() { ret void }
|
||||
define void @test_zext_s16() { ret void }
|
||||
|
||||
define void @test_trunc_s32_16() { ret void }
|
||||
|
||||
define void @test_add_s8() { ret void }
|
||||
define void @test_add_s16() { ret void }
|
||||
define void @test_add_s32() { ret void }
|
||||
|
@ -142,6 +144,34 @@ body: |
|
|||
; CHECK: BX_RET 14, _, implicit %r0
|
||||
...
|
||||
---
|
||||
name: test_trunc_s32_16
|
||||
# CHECK-LABEL: name: test_trunc_s32_16
|
||||
legalized: true
|
||||
regBankSelected: true
|
||||
selected: false
|
||||
# CHECK: selected: true
|
||||
registers:
|
||||
- { id: 0, class: gprb }
|
||||
- { id: 1, class: gprb }
|
||||
# CHECK-DAG: id: 0, class: gpr
|
||||
# CHECK-DAG: id: 1, class: gpr
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: %r0
|
||||
|
||||
%0(s32) = COPY %r0
|
||||
; CHECK: [[VREGX:%[0-9]+]] = COPY %r0
|
||||
|
||||
%1(s16) = G_TRUNC %0(s32)
|
||||
; CHECK: [[VREGTRUNC:%[0-9]+]] = COPY [[VREGX]]
|
||||
|
||||
%r0 = COPY %1(s16)
|
||||
; CHECK: %r0 = COPY [[VREGTRUNC]]
|
||||
|
||||
BX_RET 14, _, implicit %r0
|
||||
; CHECK: BX_RET 14, _, implicit %r0
|
||||
...
|
||||
---
|
||||
name: test_add_s8
|
||||
# CHECK-LABEL: name: test_add_s8
|
||||
legalized: true
|
||||
|
|
|
@ -40,6 +40,30 @@ entry:
|
|||
ret i16 %x
|
||||
}
|
||||
|
||||
define void @test_trunc_i32_i16(i32 %v, i16 *%p) {
|
||||
; CHECK-LABEL: test_trunc_i32_i16:
|
||||
; The trunc doesn't result in any instructions, but we
|
||||
; expect the store to be explicitly 16-bit.
|
||||
; CHECK: strh r0, [r1]
|
||||
; CHECK: bx lr
|
||||
entry:
|
||||
%v16 = trunc i32 %v to i16
|
||||
store i16 %v16, i16 *%p
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_trunc_i32_i8(i32 %v, i8 *%p) {
|
||||
; CHECK-LABEL: test_trunc_i32_i8:
|
||||
; The trunc doesn't result in any instructions, but we
|
||||
; expect the store to be explicitly 8-bit.
|
||||
; CHECK: strb r0, [r1]
|
||||
; CHECK: bx lr
|
||||
entry:
|
||||
%v8 = trunc i32 %v to i8
|
||||
store i8 %v8, i8 *%p
|
||||
ret void
|
||||
}
|
||||
|
||||
define i8 @test_add_i8(i8 %x, i8 %y) {
|
||||
; CHECK-LABEL: test_add_i8:
|
||||
; CHECK: add r0, r0, r1
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
define void @test_constants() { ret void }
|
||||
|
||||
define void @test_trunc_s32_16() { ret void }
|
||||
|
||||
define void @test_fadd_s32() #0 { ret void }
|
||||
define void @test_fadd_s64() #0 { ret void }
|
||||
|
||||
|
@ -442,6 +444,27 @@ body: |
|
|||
BX_RET 14, _, implicit %r0
|
||||
...
|
||||
---
|
||||
name: test_trunc_s32_16
|
||||
# CHECK-LABEL: name: test_trunc_s32_16
|
||||
legalized: true
|
||||
regBankSelected: false
|
||||
selected: false
|
||||
# CHECK: registers:
|
||||
# CHECK: - { id: 0, class: gprb }
|
||||
# CHECK: - { id: 1, class: gprb }
|
||||
registers:
|
||||
- { id: 0, class: _ }
|
||||
- { id: 1, class: _ }
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: %r0
|
||||
|
||||
%0(s32) = COPY %r0
|
||||
%1(s16) = G_TRUNC %0(s32)
|
||||
%r0 = COPY %1(s16)
|
||||
BX_RET 14, _, implicit %r0
|
||||
...
|
||||
---
|
||||
name: test_fadd_s32
|
||||
# CHECK-LABEL: name: test_fadd_s32
|
||||
legalized: true
|
||||
|
|
Loading…
Reference in New Issue