diff --git a/lib/Target/AMDGPU/AMDGPUGenRegisterBankInfo.def b/lib/Target/AMDGPU/AMDGPUGenRegisterBankInfo.def index bf7deb500d1..336c5e726ab 100644 --- a/lib/Target/AMDGPU/AMDGPUGenRegisterBankInfo.def +++ b/lib/Target/AMDGPU/AMDGPUGenRegisterBankInfo.def @@ -19,7 +19,9 @@ enum PartialMappingIdx { PM_SGPR32 = 0, PM_SGPR64 = 1, PM_VGPR32 = 2, - PM_VGPR64 = 3 + PM_VGPR64 = 3, + PM_SGPR1 = 4, + PM_VGPR1 = 5, }; const RegisterBankInfo::PartialMapping PartMappings[] { @@ -27,7 +29,9 @@ const RegisterBankInfo::PartialMapping PartMappings[] { {0, 32, SGPRRegBank}, {0, 64, SGPRRegBank}, {0, 32, VGPRRegBank}, - {0, 64, VGPRRegBank} + {0, 64, VGPRRegBank}, + {0, 1, SCCRegBank}, + {0, 1, SGPRRegBank} }; const RegisterBankInfo::ValueMapping ValMappings[] { @@ -38,7 +42,9 @@ const RegisterBankInfo::ValueMapping ValMappings[] { // VGPR 32-bit {&PartMappings[2], 1}, // VGPR 64-bit - {&PartMappings[3], 1} + {&PartMappings[3], 1}, + {&PartMappings[4], 1}, + {&PartMappings[5], 1} }; enum ValueMappingIdx { @@ -48,9 +54,14 @@ enum ValueMappingIdx { const RegisterBankInfo::ValueMapping *getValueMapping(unsigned BankID, unsigned Size) { - assert(Size % 32 == 0); - unsigned Idx = BankID == AMDGPU::SGPRRegBankID ? SGPRStartIdx : VGPRStartIdx; - Idx += (Size / 32) - 1; + unsigned Idx; + if (Size == 1) { + Idx = BankID == AMDGPU::SCCRegBankID ? PM_SGPR1 : PM_VGPR1; + } else { + assert(Size % 32 == 0); + Idx = BankID == AMDGPU::SGPRRegBankID ? SGPRStartIdx : VGPRStartIdx; + Idx += (Size / 32) - 1; + } return &ValMappings[Idx]; } diff --git a/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp b/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp index 8d94898415b..a2647addc4e 100644 --- a/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp +++ b/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp @@ -56,6 +56,13 @@ unsigned AMDGPURegisterBankInfo::copyCost(const RegisterBank &Dst, if (Dst.getID() == AMDGPU::SGPRRegBankID && Src.getID() == AMDGPU::VGPRRegBankID) return std::numeric_limits::max(); + + // SGPRRegBank with size 1 is actually vcc or another 64-bit sgpr written by + // the valu. + if (Size == 1 && Dst.getID() == AMDGPU::SCCRegBankID && + Src.getID() == AMDGPU::SGPRRegBankID) + return std::numeric_limits::max(); + return RegisterBankInfo::copyCost(Dst, Src, Size); } @@ -75,11 +82,11 @@ AMDGPURegisterBankInfo::getInstrAlternativeMappings( const MachineFunction &MF = *MI.getParent()->getParent(); const MachineRegisterInfo &MRI = MF.getRegInfo(); - unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI); InstructionMappings AltMappings; switch (MI.getOpcode()) { case TargetOpcode::G_LOAD: { + unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, *TRI); // FIXME: Should we be hard coding the size for these mappings? const InstructionMapping &SSMapping = getInstructionMapping( 1, 1, getOperandsMapping( @@ -107,6 +114,42 @@ AMDGPURegisterBankInfo::getInstrAlternativeMappings( return AltMappings; } + case TargetOpcode::G_ICMP: { + unsigned Size = getSizeInBits(MI.getOperand(2).getReg(), MRI, *TRI); + const InstructionMapping &SSMapping = getInstructionMapping(1, 1, + getOperandsMapping({AMDGPU::getValueMapping(AMDGPU::SCCRegBankID, 1), + nullptr, // Predicate operand. + AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size), + AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size)}), + 4); // Num Operands + AltMappings.push_back(&SSMapping); + + const InstructionMapping &SVMapping = getInstructionMapping(2, 1, + getOperandsMapping({AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 1), + nullptr, // Predicate operand. + AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size), + AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size)}), + 4); // Num Operands + AltMappings.push_back(&SVMapping); + + const InstructionMapping &VSMapping = getInstructionMapping(3, 1, + getOperandsMapping({AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 1), + nullptr, // Predicate operand. + AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size), + AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size)}), + 4); // Num Operands + AltMappings.push_back(&VSMapping); + + const InstructionMapping &VVMapping = getInstructionMapping(4, 1, + getOperandsMapping({AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, 1), + nullptr, // Predicate operand. + AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size), + AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, Size)}), + 4); // Num Operands + AltMappings.push_back(&VVMapping); + + return AltMappings; + } default: break; } @@ -158,6 +201,22 @@ AMDGPURegisterBankInfo::getInstrMappingForLoad(const MachineInstr &MI) const { // handle that during instruction selection? } +unsigned +AMDGPURegisterBankInfo::getRegBankID(unsigned Reg, + const MachineRegisterInfo &MRI, + const TargetRegisterInfo &TRI, + unsigned Default) const { + + const RegisterBank *Bank = getRegBank(Reg, MRI, TRI); + return Bank ? Bank->getID() : Default; +} + +/// +/// This function must return a legal mapping, because +/// AMDGPURegisterBankInfo::getInstrAlternativeMappings() is not called +/// in RegBankSelect::Mode::Fast. Any mapping that would cause a +/// VGPR to SGPR generated is illegal. +/// const RegisterBankInfo::InstructionMapping & AMDGPURegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { const RegisterBankInfo::InstructionMapping &Mapping = getInstrMappingImpl(MI); @@ -213,6 +272,20 @@ AMDGPURegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { break; } + case AMDGPU::G_ICMP: { + unsigned Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits(); + unsigned Op2Bank = getRegBankID(MI.getOperand(2).getReg(), MRI, *TRI); + unsigned Op3Bank = getRegBankID(MI.getOperand(3).getReg(), MRI, *TRI); + unsigned Op0Bank = Op2Bank == AMDGPU::SGPRRegBankID && + Op3Bank == AMDGPU::SGPRRegBankID ? + AMDGPU::SCCRegBankID : AMDGPU::VGPRRegBankID; + OpdsMapping[0] = AMDGPU::getValueMapping(Op0Bank, 1); + OpdsMapping[1] = nullptr; // Predicate Operand. + OpdsMapping[2] = AMDGPU::getValueMapping(Op2Bank, Size); + OpdsMapping[3] = AMDGPU::getValueMapping(Op3Bank, Size); + break; + } + case AMDGPU::G_LOAD: return getInstrMappingForLoad(MI); } diff --git a/lib/Target/AMDGPU/AMDGPURegisterBankInfo.h b/lib/Target/AMDGPU/AMDGPURegisterBankInfo.h index 201fdc1974c..31589236b94 100644 --- a/lib/Target/AMDGPU/AMDGPURegisterBankInfo.h +++ b/lib/Target/AMDGPU/AMDGPURegisterBankInfo.h @@ -16,19 +16,15 @@ #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" +#define GET_REGBANK_DECLARATIONS +#include "AMDGPUGenRegisterBank.inc" +#undef GET_REGBANK_DECLARATIONS + namespace llvm { class SIRegisterInfo; class TargetRegisterInfo; -namespace AMDGPU { -enum { - SGPRRegBankID = 0, - VGPRRegBankID = 1, - NumRegisterBanks -}; -} // End AMDGPU namespace. - /// This class provides the information for the target register banks. class AMDGPUGenRegisterBankInfo : public RegisterBankInfo { @@ -46,6 +42,10 @@ class AMDGPURegisterBankInfo : public AMDGPUGenRegisterBankInfo { const RegisterBankInfo::InstructionMapping & getInstrMappingForLoad(const MachineInstr &MI) const; + unsigned getRegBankID(unsigned Reg, const MachineRegisterInfo &MRI, + const TargetRegisterInfo &TRI, + unsigned Default = AMDGPU::VGPRRegBankID) const; + public: AMDGPURegisterBankInfo(const TargetRegisterInfo &TRI); diff --git a/lib/Target/AMDGPU/AMDGPURegisterBanks.td b/lib/Target/AMDGPU/AMDGPURegisterBanks.td index f4428e56035..7f7f75f6564 100644 --- a/lib/Target/AMDGPU/AMDGPURegisterBanks.td +++ b/lib/Target/AMDGPU/AMDGPURegisterBanks.td @@ -14,3 +14,5 @@ def SGPRRegBank : RegisterBank<"SGPR", def VGPRRegBank : RegisterBank<"VGPR", [VGPR_32, VReg_64, VReg_96, VReg_128, VReg_256, VReg_512] >; + +def SCCRegBank : RegisterBank <"SCC", [SCC_CLASS ]>; diff --git a/test/CodeGen/AMDGPU/GlobalISel/regbankselect-icmp.mir b/test/CodeGen/AMDGPU/GlobalISel/regbankselect-icmp.mir new file mode 100644 index 00000000000..114a6d0b251 --- /dev/null +++ b/test/CodeGen/AMDGPU/GlobalISel/regbankselect-icmp.mir @@ -0,0 +1,67 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -march=amdgcn -mcpu=fiji -run-pass=regbankselect -global-isel %s -verify-machineinstrs -o - -regbankselect-fast | FileCheck %s +# RUN: llc -march=amdgcn -mcpu=fiji -run-pass=regbankselect -global-isel %s -verify-machineinstrs -o - -regbankselect-greedy | FileCheck %s + +--- +name: icmp_ss +legalized: true + +body: | + bb.0: + liveins: $sgpr0, $sgpr1 + ; CHECK-LABEL: name: icmp_ss + ; CHECK: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr1 + ; CHECK: [[ICMP:%[0-9]+]]:scc(s1) = G_ICMP intpred(ne), [[COPY]](s32), [[COPY1]] + %0:_(s32) = COPY $sgpr0 + %1:_(s32) = COPY $sgpr1 + %2:_(s1) = G_ICMP intpred(ne), %0, %1 +... + +--- +name: icmp_sv +legalized: true + +body: | + bb.0: + liveins: $sgpr0, $vgpr0 + ; CHECK-LABEL: name: icmp_sv + ; CHECK: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[ICMP:%[0-9]+]]:sgpr(s1) = G_ICMP intpred(ne), [[COPY]](s32), [[COPY1]] + %0:_(s32) = COPY $sgpr0 + %1:_(s32) = COPY $vgpr0 + %2:_(s1) = G_ICMP intpred(ne), %0, %1 +... + +--- +name: icmp_vs +legalized: true + +body: | + bb.0: + liveins: $sgpr0, $vgpr0 + ; CHECK-LABEL: name: icmp_vs + ; CHECK: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[ICMP:%[0-9]+]]:sgpr(s1) = G_ICMP intpred(ne), [[COPY1]](s32), [[COPY]] + %0:_(s32) = COPY $sgpr0 + %1:_(s32) = COPY $vgpr0 + %2:_(s1) = G_ICMP intpred(ne), %1, %0 +... + +--- +name: icmp_vv +legalized: true + +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + ; CHECK-LABEL: name: icmp_vv + ; CHECK: [[COPY:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr1 + ; CHECK: [[ICMP:%[0-9]+]]:sgpr(s1) = G_ICMP intpred(ne), [[COPY]](s32), [[COPY1]] + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s1) = G_ICMP intpred(ne), %0, %1 +...