diff options
author | Tim Northover <tnorthover@apple.com> | 2016-10-12 22:49:15 +0000 |
---|---|---|
committer | Tim Northover <tnorthover@apple.com> | 2016-10-12 22:49:15 +0000 |
commit | fb8d9898188c1b95ffb56600b608e11bbbb94946 (patch) | |
tree | babee83b5f80e3c2cbc6c1db98717a4feae94dc2 | |
parent | 69271c64d5582adf3b6d3680de9f27cb55e7b6f8 (diff) | |
download | bcm5719-llvm-fb8d9898188c1b95ffb56600b608e11bbbb94946.tar.gz bcm5719-llvm-fb8d9898188c1b95ffb56600b608e11bbbb94946.zip |
GlobalISel: support G_TRUNC selection on AArch64.
Ahmed's patch again.
llvm-svn: 284075
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp | 80 | ||||
-rw-r--r-- | llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir | 37 |
2 files changed, 117 insertions, 0 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp index df4bf699f02..3a3090ee21e 100644 --- a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp @@ -41,6 +41,32 @@ AArch64InstructionSelector::AArch64InstructionSelector( : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()), RBI(RBI) {} +// FIXME: This should be target-independent, inferred from the types declared +// for each class in the bank. +static const TargetRegisterClass * +getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB, + const RegisterBankInfo &RBI) { + if (RB.getID() == AArch64::GPRRegBankID) { + if (Ty.getSizeInBits() <= 32) + return &AArch64::GPR32RegClass; + if (Ty.getSizeInBits() == 64) + return &AArch64::GPR64RegClass; + return nullptr; + } + + if (RB.getID() == AArch64::FPRRegBankID) { + if (Ty.getSizeInBits() == 32) + return &AArch64::FPR32RegClass; + if (Ty.getSizeInBits() == 64) + return &AArch64::FPR64RegClass; + if (Ty.getSizeInBits() == 128) + return &AArch64::FPR128RegClass; + return nullptr; + } + + return nullptr; +} + /// Check whether \p I is a currently unsupported binary operation: /// - it has an unsized type /// - an operand is not a vreg @@ -633,6 +659,60 @@ bool AArch64InstructionSelector::select(MachineInstr &I) const { return constrainSelectedInstRegOperands(I, TII, TRI, RBI); } + case TargetOpcode::G_TRUNC: { + const LLT DstTy = MRI.getType(I.getOperand(0).getReg()); + const LLT SrcTy = MRI.getType(I.getOperand(1).getReg()); + + const unsigned DstReg = I.getOperand(0).getReg(); + const unsigned SrcReg = I.getOperand(1).getReg(); + + const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI); + const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI); + + if (DstRB.getID() != SrcRB.getID()) { + DEBUG(dbgs() << "G_TRUNC input/output on different banks\n"); + return false; + } + + if (DstRB.getID() == AArch64::GPRRegBankID) { + const TargetRegisterClass *DstRC = + getRegClassForTypeOnBank(DstTy, DstRB, RBI); + if (!DstRC) + return false; + + const TargetRegisterClass *SrcRC = + getRegClassForTypeOnBank(SrcTy, SrcRB, RBI); + if (!SrcRC) + return false; + + if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) || + !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) { + DEBUG(dbgs() << "Failed to constrain G_TRUNC\n"); + return false; + } + + if (DstRC == SrcRC) { + // Nothing to be done + } else if (DstRC == &AArch64::GPR32RegClass && + SrcRC == &AArch64::GPR64RegClass) { + I.getOperand(1).setSubReg(AArch64::sub_32); + } else { + return false; + } + + I.setDesc(TII.get(TargetOpcode::COPY)); + return true; + } else if (DstRB.getID() == AArch64::FPRRegBankID) { + if (DstTy == LLT::vector(4, 16) && SrcTy == LLT::vector(4, 32)) { + I.setDesc(TII.get(AArch64::XTNv4i16)); + constrainSelectedInstRegOperands(I, TII, TRI, RBI); + return true; + } + } + + return false; + } + case TargetOpcode::G_ANYEXT: { const unsigned DstReg = I.getOperand(0).getReg(); const unsigned SrcReg = I.getOperand(1).getReg(); diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir index c42db8b0280..d60fb940fb6 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir @@ -104,6 +104,8 @@ @var_got = external global i8 define i8* @global_got() { ret i8* undef } + define void @trunc() { ret void } + define void @anyext_gpr() { ret void } define void @zext_gpr() { ret void } define void @sext_gpr() { ret void } @@ -1768,6 +1770,41 @@ body: | ... --- +# CHECK-LABEL: name: trunc +name: trunc +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr64 } +# CHECK-NEXT: - { id: 3, class: gpr32 } +# CHECK-NEXT: - { id: 4, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + - { id: 3, class: gpr } + - { id: 4, class: gpr } + +# CHECK: body: +# CHECK: %1 = COPY %0 +# CHECK: %3 = COPY %2.sub_32 +# CHECK: %4 = COPY %2.sub_32 +body: | + bb.0: + liveins: %w0, %x0 + + %0(s32) = COPY %w0 + %1(s1) = G_TRUNC %0 + + %2(s64) = COPY %x0 + %3(s32) = G_TRUNC %2 + %4(s8) = G_TRUNC %2 +... + +--- # CHECK-LABEL: name: anyext_gpr name: anyext_gpr legalized: true |