diff --git a/llvm/lib/Target/RISCV/RISCVRegisterBankInfo.h b/llvm/lib/Target/RISCV/RISCVRegisterBankInfo.h --- a/llvm/lib/Target/RISCV/RISCVRegisterBankInfo.h +++ b/llvm/lib/Target/RISCV/RISCVRegisterBankInfo.h @@ -32,6 +32,12 @@ class RISCVRegisterBankInfo final : public RISCVGenRegisterBankInfo { public: RISCVRegisterBankInfo(unsigned HwMode); + + const RegisterBank &getRegBankFromRegClass(const TargetRegisterClass &RC, + LLT Ty) const override; + + const InstructionMapping & + getInstrMapping(const MachineInstr &MI) const override; }; } // end namespace llvm #endif diff --git a/llvm/lib/Target/RISCV/RISCVRegisterBankInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterBankInfo.cpp --- a/llvm/lib/Target/RISCV/RISCVRegisterBankInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterBankInfo.cpp @@ -12,6 +12,7 @@ #include "RISCVRegisterBankInfo.h" #include "MCTargetDesc/RISCVMCTargetDesc.h" +#include "RISCVSubtarget.h" #include "llvm/CodeGen/GlobalISel/RegisterBank.h" #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" @@ -20,7 +21,114 @@ #define GET_TARGET_REGBANK_IMPL #include "RISCVGenRegisterBank.inc" +namespace llvm { +namespace RISCV { + +RegisterBankInfo::PartialMapping PartMappings[] = { + {0, 32, GPRRegBank}, + {0, 64, GPRRegBank} +}; + +enum PartialMappingIdx { + PMI_GPR32 = 0, + PMI_GPR64 = 1 +}; + +RegisterBankInfo::ValueMapping ValueMappings[] = { + // Invalid value mapping. + {nullptr, 0}, + // Maximum 3 GPR operands; 32 bit. + {&PartMappings[PMI_GPR32], 1}, + {&PartMappings[PMI_GPR32], 1}, + {&PartMappings[PMI_GPR32], 1}, + // Maximum 3 GPR operands; 64 bit. + {&PartMappings[PMI_GPR64], 1}, + {&PartMappings[PMI_GPR64], 1}, + {&PartMappings[PMI_GPR64], 1} +}; + +enum ValueMappingsIdx { + InvalidIdx = 0, + GPR32Idx = 1, + GPR64Idx = 4 +}; +} // namespace RISCV +} // namespace llvm + using namespace llvm; RISCVRegisterBankInfo::RISCVRegisterBankInfo(unsigned HwMode) : RISCVGenRegisterBankInfo(HwMode) {} + +const RegisterBank & +RISCVRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC, + LLT Ty) const { + switch (RC.getID()) { + default: + llvm_unreachable("Register class not supported"); + case RISCV::GPRRegClassID: + case RISCV::GPRNoX0RegClassID: + case RISCV::GPRNoX0X2RegClassID: + case RISCV::GPRTCRegClassID: + case RISCV::GPRCRegClassID: + case RISCV::GPRC_and_GPRTCRegClassID: + case RISCV::GPRX0RegClassID: + case RISCV::SPRegClassID: + return getRegBank(RISCV::GPRRegBankID); + case RISCV::FPR32RegClassID: + case RISCV::FPR32CRegClassID: + case RISCV::FPR64RegClassID: + case RISCV::FPR64CRegClassID: + llvm_unreachable("Register class not supported"); + } +} + +const RegisterBankInfo::InstructionMapping & +RISCVRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { + const auto &Mapping = getInstrMappingImpl(MI); + if (Mapping.isValid()) + return Mapping; + + const MachineFunction &MF = *MI.getParent()->getParent(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); + + bool IsRV64 = MF.getSubtarget().is64Bit(); + + // Indicate if LLT sizes don't match available register banks. + // TODO: Fixed size FPR reigsters on both Rv32/RV64. + for (const auto &Op : MI.operands()) { + if (Op.isReg()) { + LLT RegTy = MRI.getType(Op.getReg()); + unsigned Size = RegTy.getSizeInBits(); + + if (IsRV64) { + if (Size != 64) + return getInvalidInstructionMapping(); + } else { + if (Size != 32) + return getInvalidInstructionMapping(); + } + } + } + + size_t NumOperands = MI.getNumOperands(); + const ValueMapping *OperandsMapping = + &RISCV::ValueMappings[IsRV64 ? RISCV::GPR64Idx : RISCV::GPR32Idx]; + unsigned MappingID = DefaultMappingID; + + switch (MI.getOpcode()) { + case TargetOpcode::G_ADD: + case TargetOpcode::G_SUB: + case TargetOpcode::G_MUL: + case TargetOpcode::G_SDIV: + case TargetOpcode::G_SREM: + case TargetOpcode::G_UDIV: + case TargetOpcode::G_UREM: + break; + default: + return getInvalidInstructionMapping(); + } + + return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping, + NumOperands); +} diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/alu32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/alu32.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/alu32.mir @@ -0,0 +1,175 @@ +# RUN: llc -march=riscv32 -x mir -run-pass=regbankselect -disable-gisel-legality-check -simplify-mir -verify-machineinstrs < %s \ +# RUN: | FileCheck -check-prefix=RV32I %s + +--- | + + define i32 @add_i32(i32 %a, i32 %b) { entry: ret i32 0 } + define i32 @sub_i32(i32 %a, i32 %b) { entry: ret i32 0 } + define i32 @mul_i32(i32 %a, i32 %b) { entry: ret i32 0 } + define i32 @sdiv_i32(i32 %a, i32 %b) { entry: ret i32 0 } + define i32 @srem_i32(i32 %a, i32 %b) { entry: ret i32 0 } + define i32 @udiv_i32(i32 %a, i32 %b) { entry: ret i32 0 } + define i32 @urem_i32(i32 %a, i32 %b) { entry: ret i32 0 } + +... +--- +name: add_i32 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $x10, $x11 + + ; RV32I-LABEL: name: add_i32 + ; RV32I: bb.0.entry: + ; RV32I-NEXT: liveins: $x10, $x11 + ; RV32I: [[COPY:%[0-9]+]]:gprb(s32) = COPY $x10 + ; RV32I-NEXT: [[COPY1:%[0-9]+]]:gprb(s32) = COPY $x11 + ; RV32I-NEXT: [[ADD:%[0-9]+]]:gprb(s32) = G_ADD [[COPY]], [[COPY1]] + ; RV32I-NEXT: $x10 = COPY [[ADD]](s32) + ; RV32I-NEXT: PseudoRET implicit $x10 + %0:_(s32) = COPY $x10 + %1:_(s32) = COPY $x11 + %2:_(s32) = G_ADD %0, %1 + $x10 = COPY %2(s32) + PseudoRET implicit $x10 + +... +--- +name: sub_i32 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $x10, $x11 + + ; RV32I-LABEL: name: sub_i32 + ; RV32I: bb.0.entry: + ; RV32I-NEXT: liveins: $x10, $x11 + ; RV32I: [[COPY:%[0-9]+]]:gprb(s32) = COPY $x10 + ; RV32I-NEXT: [[COPY1:%[0-9]+]]:gprb(s32) = COPY $x11 + ; RV32I-NEXT: [[SUB:%[0-9]+]]:gprb(s32) = G_SUB [[COPY]], [[COPY1]] + ; RV32I-NEXT: $x10 = COPY [[SUB]](s32) + ; RV32I-NEXT: PseudoRET implicit $x10 + %0:_(s32) = COPY $x10 + %1:_(s32) = COPY $x11 + %2:_(s32) = G_SUB %0, %1 + $x10 = COPY %2(s32) + PseudoRET implicit $x10 + +... +--- +name: mul_i32 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $x10, $x11 + + ; RV32I-LABEL: name: mul_i32 + ; RV32I: bb.0.entry: + ; RV32I-NEXT: liveins: $x10, $x11 + ; RV32I: [[COPY:%[0-9]+]]:gprb(s32) = COPY $x10 + ; RV32I-NEXT: [[COPY1:%[0-9]+]]:gprb(s32) = COPY $x11 + ; RV32I-NEXT: [[MUL:%[0-9]+]]:gprb(s32) = G_MUL [[COPY]], [[COPY1]] + ; RV32I-NEXT: $x10 = COPY [[MUL]](s32) + ; RV32I-NEXT: PseudoRET implicit $x10 + %0:_(s32) = COPY $x10 + %1:_(s32) = COPY $x11 + %2:_(s32) = G_MUL %0, %1 + $x10 = COPY %2(s32) + PseudoRET implicit $x10 + +... +--- +name: sdiv_i32 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $x10, $x11 + + ; RV32I-LABEL: name: sdiv_i32 + ; RV32I: bb.0.entry: + ; RV32I-NEXT: liveins: $x10, $x11 + ; RV32I: [[COPY:%[0-9]+]]:gprb(s32) = COPY $x10 + ; RV32I-NEXT: [[COPY1:%[0-9]+]]:gprb(s32) = COPY $x11 + ; RV32I-NEXT: [[SDIV:%[0-9]+]]:gprb(s32) = G_SDIV [[COPY]], [[COPY1]] + ; RV32I-NEXT: $x10 = COPY [[SDIV]](s32) + ; RV32I-NEXT: PseudoRET implicit $x10 + %0:_(s32) = COPY $x10 + %1:_(s32) = COPY $x11 + %2:_(s32) = G_SDIV %0, %1 + $x10 = COPY %2(s32) + PseudoRET implicit $x10 + +... +--- +name: srem_i32 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $x10, $x11 + + ; RV32I-LABEL: name: srem_i32 + ; RV32I: bb.0.entry: + ; RV32I-NEXT: liveins: $x10, $x11 + ; RV32I: [[COPY:%[0-9]+]]:gprb(s32) = COPY $x10 + ; RV32I-NEXT: [[COPY1:%[0-9]+]]:gprb(s32) = COPY $x11 + ; RV32I-NEXT: [[SREM:%[0-9]+]]:gprb(s32) = G_SREM [[COPY]], [[COPY1]] + ; RV32I-NEXT: $x10 = COPY [[SREM]](s32) + ; RV32I-NEXT: PseudoRET implicit $x10 + %0:_(s32) = COPY $x10 + %1:_(s32) = COPY $x11 + %2:_(s32) = G_SREM %0, %1 + $x10 = COPY %2(s32) + PseudoRET implicit $x10 + +... +--- +name: udiv_i32 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $x10, $x11 + + ; RV32I-LABEL: name: udiv_i32 + ; RV32I: bb.0.entry: + ; RV32I-NEXT: liveins: $x10, $x11 + ; RV32I: [[COPY:%[0-9]+]]:gprb(s32) = COPY $x10 + ; RV32I-NEXT: [[COPY1:%[0-9]+]]:gprb(s32) = COPY $x11 + ; RV32I-NEXT: [[UDIV:%[0-9]+]]:gprb(s32) = G_UDIV [[COPY]], [[COPY1]] + ; RV32I-NEXT: $x10 = COPY [[UDIV]](s32) + ; RV32I-NEXT: PseudoRET implicit $x10 + %0:_(s32) = COPY $x10 + %1:_(s32) = COPY $x11 + %2:_(s32) = G_UDIV %0, %1 + $x10 = COPY %2(s32) + PseudoRET implicit $x10 + +... +--- +name: urem_i32 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $x10, $x11 + + ; RV32I-LABEL: name: urem_i32 + ; RV32I: bb.0.entry: + ; RV32I-NEXT: liveins: $x10, $x11 + ; RV32I: [[COPY:%[0-9]+]]:gprb(s32) = COPY $x10 + ; RV32I-NEXT: [[COPY1:%[0-9]+]]:gprb(s32) = COPY $x11 + ; RV32I-NEXT: [[UREM:%[0-9]+]]:gprb(s32) = G_UREM [[COPY]], [[COPY1]] + ; RV32I-NEXT: $x10 = COPY [[UREM]](s32) + ; RV32I-NEXT: PseudoRET implicit $x10 + %0:_(s32) = COPY $x10 + %1:_(s32) = COPY $x11 + %2:_(s32) = G_UREM %0, %1 + $x10 = COPY %2(s32) + PseudoRET implicit $x10 + +... diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/alu64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/alu64.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/alu64.mir @@ -0,0 +1,175 @@ +# RUN: llc -march=riscv64 -x mir -run-pass=regbankselect -disable-gisel-legality-check -simplify-mir -verify-machineinstrs < %s \ +# RUN: | FileCheck -check-prefix=RV64I %s + +--- | + + define i64 @add_i64(i64 %a, i64 %b) { entry: ret i64 0 } + define i64 @sub_i64(i64 %a, i64 %b) { entry: ret i64 0 } + define i64 @mul_i64(i64 %a, i64 %b) { entry: ret i64 0 } + define i64 @sdiv_i64(i64 %a, i64 %b) { entry: ret i64 0 } + define i64 @srem_i64(i64 %a, i64 %b) { entry: ret i64 0 } + define i64 @udiv_i64(i64 %a, i64 %b) { entry: ret i64 0 } + define i64 @urem_i64(i64 %a, i64 %b) { entry: ret i64 0 } + +... +--- +name: add_i64 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $x10, $x11 + + ; RV64I-LABEL: name: add_i64 + ; RV64I: bb.0.entry: + ; RV64I-NEXT: liveins: $x10, $x11 + ; RV64I: [[COPY:%[0-9]+]]:gprb(s64) = COPY $x10 + ; RV64I-NEXT: [[COPY1:%[0-9]+]]:gprb(s64) = COPY $x11 + ; RV64I-NEXT: [[ADD:%[0-9]+]]:gprb(s64) = G_ADD [[COPY]], [[COPY1]] + ; RV64I-NEXT: $x10 = COPY [[ADD]](s64) + ; RV64I-NEXT: PseudoRET implicit $x10 + %0:_(s64) = COPY $x10 + %1:_(s64) = COPY $x11 + %2:_(s64) = G_ADD %0, %1 + $x10 = COPY %2(s64) + PseudoRET implicit $x10 + +... +--- +name: sub_i64 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $x10, $x11 + + ; RV64I-LABEL: name: sub_i64 + ; RV64I: bb.0.entry: + ; RV64I-NEXT: liveins: $x10, $x11 + ; RV64I: [[COPY:%[0-9]+]]:gprb(s64) = COPY $x10 + ; RV64I-NEXT: [[COPY1:%[0-9]+]]:gprb(s64) = COPY $x11 + ; RV64I-NEXT: [[SUB:%[0-9]+]]:gprb(s64) = G_SUB [[COPY]], [[COPY1]] + ; RV64I-NEXT: $x10 = COPY [[SUB]](s64) + ; RV64I-NEXT: PseudoRET implicit $x10 + %0:_(s64) = COPY $x10 + %1:_(s64) = COPY $x11 + %2:_(s64) = G_SUB %0, %1 + $x10 = COPY %2(s64) + PseudoRET implicit $x10 + +... +--- +name: mul_i64 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $x10, $x11 + + ; RV64I-LABEL: name: mul_i64 + ; RV64I: bb.0.entry: + ; RV64I-NEXT: liveins: $x10, $x11 + ; RV64I: [[COPY:%[0-9]+]]:gprb(s64) = COPY $x10 + ; RV64I-NEXT: [[COPY1:%[0-9]+]]:gprb(s64) = COPY $x11 + ; RV64I-NEXT: [[MUL:%[0-9]+]]:gprb(s64) = G_MUL [[COPY]], [[COPY1]] + ; RV64I-NEXT: $x10 = COPY [[MUL]](s64) + ; RV64I-NEXT: PseudoRET implicit $x10 + %0:_(s64) = COPY $x10 + %1:_(s64) = COPY $x11 + %2:_(s64) = G_MUL %0, %1 + $x10 = COPY %2(s64) + PseudoRET implicit $x10 + +... +--- +name: sdiv_i64 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $x10, $x11 + + ; RV64I-LABEL: name: sdiv_i64 + ; RV64I: bb.0.entry: + ; RV64I-NEXT: liveins: $x10, $x11 + ; RV64I: [[COPY:%[0-9]+]]:gprb(s64) = COPY $x10 + ; RV64I-NEXT: [[COPY1:%[0-9]+]]:gprb(s64) = COPY $x11 + ; RV64I-NEXT: [[SDIV:%[0-9]+]]:gprb(s64) = G_SDIV [[COPY]], [[COPY1]] + ; RV64I-NEXT: $x10 = COPY [[SDIV]](s64) + ; RV64I-NEXT: PseudoRET implicit $x10 + %0:_(s64) = COPY $x10 + %1:_(s64) = COPY $x11 + %2:_(s64) = G_SDIV %0, %1 + $x10 = COPY %2(s64) + PseudoRET implicit $x10 + +... +--- +name: srem_i64 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $x10, $x11 + + ; RV64I-LABEL: name: srem_i64 + ; RV64I: bb.0.entry: + ; RV64I-NEXT: liveins: $x10, $x11 + ; RV64I: [[COPY:%[0-9]+]]:gprb(s64) = COPY $x10 + ; RV64I-NEXT: [[COPY1:%[0-9]+]]:gprb(s64) = COPY $x11 + ; RV64I-NEXT: [[SREM:%[0-9]+]]:gprb(s64) = G_SREM [[COPY]], [[COPY1]] + ; RV64I-NEXT: $x10 = COPY [[SREM]](s64) + ; RV64I-NEXT: PseudoRET implicit $x10 + %0:_(s64) = COPY $x10 + %1:_(s64) = COPY $x11 + %2:_(s64) = G_SREM %0, %1 + $x10 = COPY %2(s64) + PseudoRET implicit $x10 + +... +--- +name: udiv_i64 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $x10, $x11 + + ; RV64I-LABEL: name: udiv_i64 + ; RV64I: bb.0.entry: + ; RV64I-NEXT: liveins: $x10, $x11 + ; RV64I: [[COPY:%[0-9]+]]:gprb(s64) = COPY $x10 + ; RV64I-NEXT: [[COPY1:%[0-9]+]]:gprb(s64) = COPY $x11 + ; RV64I-NEXT: [[UDIV:%[0-9]+]]:gprb(s64) = G_UDIV [[COPY]], [[COPY1]] + ; RV64I-NEXT: $x10 = COPY [[UDIV]](s64) + ; RV64I-NEXT: PseudoRET implicit $x10 + %0:_(s64) = COPY $x10 + %1:_(s64) = COPY $x11 + %2:_(s64) = G_UDIV %0, %1 + $x10 = COPY %2(s64) + PseudoRET implicit $x10 + +... +--- +name: urem_i64 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $x10, $x11 + + ; RV64I-LABEL: name: urem_i64 + ; RV64I: bb.0.entry: + ; RV64I-NEXT: liveins: $x10, $x11 + ; RV64I: [[COPY:%[0-9]+]]:gprb(s64) = COPY $x10 + ; RV64I-NEXT: [[COPY1:%[0-9]+]]:gprb(s64) = COPY $x11 + ; RV64I-NEXT: [[UREM:%[0-9]+]]:gprb(s64) = G_UREM [[COPY]], [[COPY1]] + ; RV64I-NEXT: $x10 = COPY [[UREM]](s64) + ; RV64I-NEXT: PseudoRET implicit $x10 + %0:_(s64) = COPY $x10 + %1:_(s64) = COPY $x11 + %2:_(s64) = G_UREM %0, %1 + $x10 = COPY %2(s64) + PseudoRET implicit $x10 + +...