diff options
-rw-r--r-- | llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h | 65 | ||||
-rw-r--r-- | llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp | 108 |
2 files changed, 154 insertions, 19 deletions
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h b/llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h index 9634f0a610e..57137ec5fb8 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h @@ -64,11 +64,13 @@ #ifndef LLVM_CODEGEN_GLOBALISEL_REGBANKSELECT_H #define LLVM_CODEGEN_GLOBALISEL_REGBANKSELECT_H +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" +#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" namespace llvm { // Forward declarations. -class RegisterBankInfo; +class MachineRegisterInfo; /// This pass implements the reg bank selector pass used in the GlobalISel /// pipeline. At the end of this pass, all register operands have been assigned @@ -81,6 +83,29 @@ private: /// to register banks. const RegisterBankInfo *RBI; + /// MRI contains all the register class/bank information that this + /// pass uses and updates. + MachineRegisterInfo *MRI; + + /// Helper class used for every code morphing. + MachineIRBuilder MIRBuilder; + + /// Assign the register bank of each operand of \p MI. + void assignInstr(MachineInstr &MI); + + /// Initialize the field members using \p MF. + void init(MachineFunction &MF); + + /// Check if \p Reg is already assigned what is described by \p ValMapping. + bool assignmentMatch(unsigned Reg, + const RegisterBankInfo::ValueMapping &ValMapping) const; + + /// Insert repairing code to map \p Reg as specified by \p ValMapping. + /// The repairing code is inserted where the MIRBuilder points. + /// \return The register of the properly mapped value. + unsigned repairReg(unsigned Reg, + const RegisterBankInfo::ValueMapping &ValMapping); + public: // Ctor, nothing fancy. RegBankSelect(); @@ -89,21 +114,29 @@ public: return "RegBankSelect"; } - // Simplified algo: - // RBI = MF.subtarget.getRegBankInfo() - // MIRBuilder.reset(MF) - // for each bb in MF - // for each inst in bb - // MappingCosts = RBI.getMapping(inst); - // Idx = findIdxOfMinCost(MappingCosts) - // CurRegBank = MappingCosts[Idx].RegBank - // MRI.setRegBank(inst.getOperand(0).getReg(), CurRegBank) - // for each argument in inst - // if (CurRegBank != argument.RegBank) - // ArgReg = argument.getReg() - // Tmp = MRI.createNewVirtual(MRI.getSize(ArgReg), CurRegBank) - // MIRBuilder.buildInstr(COPY, Tmp, ArgReg) - // inst.getOperand(argument.getOperandNo()).setReg(Tmp) + /// Walk through \p MF and assign a register bank to every virtual register + /// that are still mapped to nothing. + /// The target needs to provide a RegisterBankInfo and in particular + /// override RegisterBankInfo::getInstrMapping. + /// + /// Simplified algo: + /// \code + /// RBI = MF.subtarget.getRegBankInfo() + /// MIRBuilder.setMF(MF) + /// for each bb in MF + /// for each inst in bb + /// MIRBuilder.setInstr(inst) + /// MappingCosts = RBI.getMapping(inst); + /// Idx = findIdxOfMinCost(MappingCosts) + /// CurRegBank = MappingCosts[Idx].RegBank + /// MRI.setRegBank(inst.getOperand(0).getReg(), CurRegBank) + /// for each argument in inst + /// if (CurRegBank != argument.RegBank) + /// ArgReg = argument.getReg() + /// Tmp = MRI.createNewVirtual(MRI.getSize(ArgReg), CurRegBank) + /// MIRBuilder.buildInstr(COPY, Tmp, ArgReg) + /// inst.getOperand(argument.getOperandNo()).setReg(Tmp) + /// \endcode bool runOnMachineFunction(MachineFunction &MF) override; }; } // End namespace llvm. diff --git a/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp b/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp index 7f1e9d9a653..b4179233036 100644 --- a/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp +++ b/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp @@ -11,6 +11,9 @@ //===----------------------------------------------------------------------===// #include "llvm/CodeGen/GlobalISel/RegBankSelect.h" +#include "llvm/CodeGen/GlobalISel/RegisterBank.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetSubtargetInfo.h" #define DEBUG_TYPE "regbankselect" @@ -21,12 +24,111 @@ INITIALIZE_PASS(RegBankSelect, "regbankselect", "Assign register bank of generic virtual registers", false, false); -RegBankSelect::RegBankSelect() : MachineFunctionPass(ID), RBI(nullptr) { +RegBankSelect::RegBankSelect() + : MachineFunctionPass(ID), RBI(nullptr), MRI(nullptr) { initializeRegBankSelectPass(*PassRegistry::getPassRegistry()); } +void RegBankSelect::init(MachineFunction &MF) { + RBI = MF.getSubtarget().getRegBankInfo(); + assert(RBI && "Cannot work without RegisterBankInfo"); + MRI = &MF.getRegInfo(); + MIRBuilder.setMF(MF); +} + +bool RegBankSelect::assignmentMatch( + unsigned Reg, const RegisterBankInfo::ValueMapping &ValMapping) const { + // Each part of a break down needs to end up in a different register. + // In other word, Reg assignement does not match. + if (ValMapping.BreakDown.size() > 1) + return false; + + const RegClassOrRegBank &CurAssignment = MRI->getRegClassOrRegBank(Reg); + // Nothing assigned, the assignment does not match. + if (!CurAssignment) + return false; + // Get the register bank form the current assignment. + const RegisterBank *CurRegBank = nullptr; + if (CurAssignment.is<const TargetRegisterClass *>()) + CurRegBank = &RBI->getRegBankFromRegClass( + *CurAssignment.get<const TargetRegisterClass *>()); + else + CurRegBank = CurAssignment.get<const RegisterBank *>(); + return CurRegBank == ValMapping.BreakDown[0].RegBank; +} + +unsigned +RegBankSelect::repairReg(unsigned Reg, + const RegisterBankInfo::ValueMapping &ValMapping) { + assert(ValMapping.BreakDown.size() == 1 && + "Support for complex break down not supported yet"); + const RegisterBankInfo::PartialMapping &PartialMap = ValMapping.BreakDown[0]; + assert(PartialMap.Mask.getBitWidth() == MRI->getSize(Reg) && + "Repairing other than copy not implemented yet"); + unsigned NewReg = + MRI->createGenericVirtualRegister(PartialMap.Mask.getBitWidth()); + (void)MIRBuilder.buildInstr(TargetOpcode::COPY, NewReg, Reg); + return NewReg; +} + +void RegBankSelect::assignInstr(MachineInstr &MI) { + const RegisterBankInfo::InstructionMapping DefaultMapping = + RBI->getInstrMapping(MI); + // Make sure the mapping is valid for MI. + DefaultMapping.verify(MI); + // Set the insertion point before MI. + // This is where we are going to insert the repairing code if any. + MIRBuilder.setInstr(MI, /*Before*/ true); + + // For now, do not look for alternative mappings. + // Alternative mapping may require to rewrite MI and we do not support + // that yet. + // Walk the operands and assign then to the chosen mapping, possibly with + // the insertion of repair code for uses. + for (unsigned OpIdx = 0, EndIdx = MI.getNumOperands(); OpIdx != EndIdx; + ++OpIdx) { + MachineOperand &MO = MI.getOperand(OpIdx); + // Nothing to be done for non-register operands. + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg) + continue; + + const RegisterBankInfo::ValueMapping &ValMapping = + DefaultMapping.getOperandMapping(OpIdx); + // If Reg is already properly mapped, move on. + if (assignmentMatch(Reg, ValMapping)) + continue; + + // For uses, we may need to create a new temporary. + // Indeed, if Reg is already assigned a register bank, at this + // point, we know it is different from the one defined by the + // chosen mapping, we need to adjust for that. + assert(ValMapping.BreakDown.size() == 1 && + "Support for complex break down not supported yet"); + if (!MO.isDef() && MRI->getRegClassOrRegBank(Reg)) { + // For phis, we need to change the insertion point to the end of + // the related predecessor block. + assert(!MI.isPHI() && "PHI support not implemented yet"); + Reg = repairReg(Reg, ValMapping); + } + // If we end up here, MO should be free of encoding constraints, + // i.e., we do not have to constrained the RegBank of Reg to + // the requirement of the operands. + // If that is not the case, this means the code was broken before + // hands because we should have found that the assignment match. + // This will not hold when we will consider alternative mappings. + MRI->setRegBank(Reg, *ValMapping.BreakDown[0].RegBank); + MO.setReg(Reg); + } +} + bool RegBankSelect::runOnMachineFunction(MachineFunction &MF) { - // Avoid unused field member warning. - (void)RBI; + init(MF); + // Walk the function and assign register banks to all operands. + for (MachineBasicBlock &MBB : MF) + for (MachineInstr &MI : MBB) + assignInstr(MI); return false; } |