From f8322a85c41875eb69f9fac139029ad9b013d1ea Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Tue, 11 Oct 2016 22:29:23 +0000 Subject: [PATCH] GlobalISel: support same-size casts on AArch64. Mostly Ahmed's work again, I'm just sprucing things up slightly before committing. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@283952 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../AArch64/AArch64InstructionSelector.cpp | 62 +++++++++++++++++++ .../AArch64/AArch64MachineLegalizer.cpp | 13 ++++ .../GlobalISel/arm64-instructionselect.mir | 31 ++++++++++ 3 files changed, 106 insertions(+) diff --git a/lib/Target/AArch64/AArch64InstructionSelector.cpp b/lib/Target/AArch64/AArch64InstructionSelector.cpp index 164beacea0d4..04e74b01d803 100644 --- a/lib/Target/AArch64/AArch64InstructionSelector.cpp +++ b/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 @@ -493,6 +519,42 @@ bool AArch64InstructionSelector::select(MachineInstr &I) const { I.eraseFromParent(); return true; } + + case TargetOpcode::G_INTTOPTR: + case TargetOpcode::G_PTRTOINT: + case TargetOpcode::G_BITCAST: { + 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); + + 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_BITCAST\n"); + return false; + } + + BuildMI(MBB, I, I.getDebugLoc(), TII.get(AArch64::COPY)) + .addDef(DstReg) + .addUse(SrcReg); + + I.eraseFromParent(); + return true; + } } return false; diff --git a/lib/Target/AArch64/AArch64MachineLegalizer.cpp b/lib/Target/AArch64/AArch64MachineLegalizer.cpp index f59804d38539..4bb0f8d530fb 100644 --- a/lib/Target/AArch64/AArch64MachineLegalizer.cpp +++ b/lib/Target/AArch64/AArch64MachineLegalizer.cpp @@ -176,5 +176,18 @@ AArch64MachineLegalizer::AArch64MachineLegalizer() { setAction({G_INTTOPTR, 0, p0}, Legal); setAction({G_INTTOPTR, 1, s64}, Legal); + for (auto Ty : {s1, s8, s16, s32, s64}) { + setAction({G_BITCAST, 0, Ty}, Legal); + setAction({G_BITCAST, 1, Ty}, Legal); + } + + for (int EltSize = 8; EltSize <= 64; EltSize *= 2) { + setAction({G_BITCAST, 0, LLT::vector(128/EltSize, EltSize)}, Legal); + if (EltSize == 64) + continue; + + setAction({G_BITCAST, 0, LLT::vector(64/EltSize, EltSize)}, Legal); + } + computeTables(); } diff --git a/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir b/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir index 2d3c9f2512ef..af4bde9237ca 100644 --- a/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir +++ b/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir @@ -86,6 +86,8 @@ define void @anyext_gpr() { ret void } define void @zext_gpr() { ret void } define void @sext_gpr() { ret void } + + define void @casts() { ret void } ... --- @@ -1423,3 +1425,32 @@ body: | %2(s8) = COPY %w0 %3(s32) = G_SEXT %2 ... + +--- +# CHECK-LABEL: name: casts +name: casts +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: fpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: fpr } + - { id: 2, class: gpr } + - { id: 3, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %0 +# CHECK: %2 = COPY %0 +# CHECK: %3 = COPY %2 +body: | + bb.0: + liveins: %w0 + %0(s64) = COPY %x0 + %1(<8 x s8>) = G_BITCAST %0(s64) + %2(p0) = G_INTTOPTR %0 + %3(s64) = G_PTRTOINT %2 +...