diff options
-rw-r--r-- | llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h | 36 | ||||
-rw-r--r-- | llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp | 149 |
2 files changed, 144 insertions, 41 deletions
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h b/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h index 380d55323a3..69e6cb41c19 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h @@ -26,6 +26,7 @@ namespace llvm { class MachineInstr; +class MachineRegisterInfo; class TargetRegisterInfo; class raw_ostream; @@ -66,6 +67,7 @@ public: struct ValueMapping { /// How the value is broken down between the different register banks. SmallVector<PartialMapping, 2> BreakDown; + /// Verify that this mapping makes sense for a value of \p ExpectedBitWidth. void verify(unsigned ExpectedBitWidth) const; }; @@ -132,6 +134,13 @@ public: /// This is a lightweight check for obvious wrong instance. bool isValid() const { return getID() != InvalidMappingID; } + /// Set the operand mapping for the \p OpIdx-th operand. + /// The mapping will consist of only one element in the break down list. + /// This element will map to \p RegBank and fully define a mask, whose + /// bitwidth matches the size of \p MaskSize. + void setOperandMapping(unsigned OpIdx, unsigned MaskSize, + const RegisterBank &RegBank); + /// Verifiy that this mapping makes sense for \p MI. /// \pre \p MI must be connected to a MachineFunction. void verify(const MachineInstr &MI) const; @@ -197,6 +206,25 @@ protected: return RegBanks[ID]; } + /// Try to get the mapping of \p MI. + /// See getInstrMapping for more details on what a mapping represents. + /// + /// Unlike getInstrMapping the returned InstructionMapping may be invalid + /// (isValid() == false). + /// This means that the target independent code is not smart enough + /// to get the mapping of \p MI and thus, the target has to provide the + /// information for \p MI. + /// + /// This implementation is able to get the mapping of: + /// - Target specific instructions by looking at the encoding constraints. + /// - Any instruction if all the register operands are already been assigned + /// a register, a register class, or a register bank. + /// - Copies and phis if at least one of the operand has been assigned a + /// register, a register class, or a register bank. + /// In other words, this method will likely fail to find a mapping for + /// any generic opcode that has not been lowered by target specific code. + InstructionMapping getInstrMappingImpl(const MachineInstr &MI) const; + public: virtual ~RegisterBankInfo() {} @@ -205,6 +233,14 @@ public: return const_cast<RegisterBankInfo *>(this)->getRegBank(ID); } + /// Get the register bank of \p Reg. + /// If Reg has not been assigned a register, a register class, + /// or a register bank, then this returns nullptr. + /// + /// \pre Reg != 0 (NoRegister) + const RegisterBank *getRegBank(unsigned Reg, const MachineRegisterInfo &MRI, + const TargetRegisterInfo &TRI) const; + /// Get the total number of register banks. unsigned getNumRegBanks() const { return NumRegBanks; } diff --git a/llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp b/llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp index 20fa1723b70..73d4a62652f 100644 --- a/llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp +++ b/llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp @@ -209,52 +209,107 @@ void RegisterBankInfo::addRegBankCoverage(unsigned ID, unsigned RCId, } while (!WorkList.empty()); } +const RegisterBank * +RegisterBankInfo::getRegBank(unsigned Reg, const MachineRegisterInfo &MRI, + const TargetRegisterInfo &TRI) const { + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + return &getRegBankFromRegClass(*TRI.getMinimalPhysRegClass(Reg)); + + assert(Reg && "NoRegister does not have a register bank"); + const RegClassOrRegBank &RegClassOrBank = MRI.getRegClassOrRegBank(Reg); + if (RegClassOrBank.is<const RegisterBank *>()) + return RegClassOrBank.get<const RegisterBank *>(); + const TargetRegisterClass *RC = + RegClassOrBank.get<const TargetRegisterClass *>(); + if (RC) + return &getRegBankFromRegClass(*RC); + return nullptr; +} + RegisterBankInfo::InstructionMapping -RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { - if (MI.getOpcode() > TargetOpcode::GENERIC_OP_END) { - // This is a target specific opcode: - // The mapping of the registers is already available via the - // register class. - // Just map the register class to a register bank. - RegisterBankInfo::InstructionMapping Mapping(DefaultMappingID, /*Cost*/ 1, - MI.getNumOperands()); - const MachineFunction &MF = *MI.getParent()->getParent(); - const TargetSubtargetInfo &STI = MF.getSubtarget(); - const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); - const TargetInstrInfo &TII = *STI.getInstrInfo(); - const MachineRegisterInfo &MRI = MF.getRegInfo(); - - for (unsigned OpIdx = 0, End = MI.getNumOperands(); OpIdx != End; ++OpIdx) { - const MachineOperand &MO = MI.getOperand(OpIdx); - if (!MO.isReg()) - continue; - unsigned Reg = MO.getReg(); - if (!Reg) - continue; - // Since this is a target instruction, the operand must have a register - // class constraint. +RegisterBankInfo::getInstrMappingImpl(const MachineInstr &MI) const { + RegisterBankInfo::InstructionMapping Mapping(DefaultMappingID, /*Cost*/ 1, + MI.getNumOperands()); + const MachineFunction &MF = *MI.getParent()->getParent(); + const TargetSubtargetInfo &STI = MF.getSubtarget(); + const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); + // We may need to query the instruction encoding to guess the mapping. + const TargetInstrInfo &TII = *STI.getInstrInfo(); + + // Before doing anything complicated check if the mapping is not + // directly available. + bool CompleteMapping = true; + // For copies we want to walk over the operands and try to find one + // that has a register bank. + bool isCopyLike = MI.isCopy() || MI.isPHI(); + // Remember the register bank for reuse for copy-like instructions. + const RegisterBank *RegBank = nullptr; + // Remember the size of the register for reuse for copy-like instructions. + unsigned RegSize = 0; + for (unsigned OpIdx = 0, End = MI.getNumOperands(); OpIdx != End; ++OpIdx) { + const MachineOperand &MO = MI.getOperand(OpIdx); + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg) + continue; + const RegisterBank *CurRegBank = getRegBank(Reg, MRI, TRI); + if (!CurRegBank) { + // The mapping of the registers may be available via the + // register class constraints. const TargetRegisterClass *RC = MI.getRegClassConstraint(OpIdx, &TII, &TRI); - // Note: This cannot be a "dynamic" constraint like inline asm, - // since inlineasm opcode is a generic opcode. - assert(RC && "Invalid encoding constraints for target instruction?"); - - // Build the value mapping. - const RegisterBank &RegBank = getRegBankFromRegClass(*RC); - unsigned RegSize = getSizeInBits(Reg, MRI, TRI); - assert(RegSize <= RegBank.getSize() && "Register bank too small"); - // Assume the value is mapped in one register that lives in the - // register bank that covers RC. - APInt Mask(RegSize, 0); - // The value is represented by all the bits. - Mask.flipAllBits(); - - // Create the mapping object. - ValueMapping ValMapping; - ValMapping.BreakDown.push_back(PartialMapping(Mask, RegBank)); - Mapping.setOperandMapping(OpIdx, ValMapping); + + if (RC) + CurRegBank = &getRegBankFromRegClass(*RC); + } + if (!CurRegBank) { + CompleteMapping = false; + + if (!isCopyLike) + // MI does not carry enough information to guess the mapping. + return InstructionMapping(); + + // For copies, we want to keep interating to find a register + // bank for the other operands if we did not find one yet. + if(RegBank) + break; + continue; } + RegBank = CurRegBank; + RegSize = getSizeInBits(Reg, MRI, TRI); + Mapping.setOperandMapping(OpIdx, RegSize, *CurRegBank); + } + + if (CompleteMapping) return Mapping; + + assert(isCopyLike && "We should have bailed on non-copies at this point"); + // For copy like instruction, if none of the operand has a register + // bank avialable, there is nothing we can propagate. + if (!RegBank) + return InstructionMapping(); + + // This is a copy-like instruction. + // Propagate RegBank to all operands that do not have a + // mapping yet. + for (unsigned OpIdx = 0, End = MI.getNumOperands(); OpIdx != End; ++OpIdx) { + if (!static_cast<const InstructionMapping *>(&Mapping) + ->getOperandMapping(OpIdx) + .BreakDown.empty()) + continue; + Mapping.setOperandMapping(OpIdx, RegSize, *RegBank); + } + return Mapping; +} + +RegisterBankInfo::InstructionMapping +RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { + if (!isPreISelGenericOpcode(MI.getOpcode())) { + RegisterBankInfo::InstructionMapping Mapping = getInstrMappingImpl(MI); + if (Mapping.isValid()) + return Mapping; } llvm_unreachable("The target must implement this"); } @@ -336,6 +391,18 @@ void RegisterBankInfo::ValueMapping::verify(unsigned ExpectedBitWidth) const { assert(ValueMask.isAllOnesValue() && "Value is not fully mapped"); } +void RegisterBankInfo::InstructionMapping::setOperandMapping( + unsigned OpIdx, unsigned MaskSize, const RegisterBank &RegBank) { + // Build the value mapping. + assert(MaskSize <= RegBank.getSize() && "Register bank is too small"); + APInt Mask(MaskSize, 0); + // The value is represented by all the bits. + Mask.flipAllBits(); + + // Create the mapping object. + getOperandMapping(OpIdx).BreakDown.push_back(PartialMapping(Mask, RegBank)); +} + void RegisterBankInfo::InstructionMapping::verify( const MachineInstr &MI) const { // Check that all the register operands are properly mapped. |