diff --git a/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h b/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h index 2965f409653..4285b11b91f 100644 --- a/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h +++ b/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h @@ -395,6 +395,22 @@ protected: const TargetInstrInfo &TII, const TargetRegisterInfo &TRI) const; + /// Helper method to apply something that is like the default mapping. + /// Basically, that means that \p OpdMapper.getMI() is left untouched + /// aside from the reassignment of the register operand that have been + /// remapped. + /// If the mapping of one of the operand spans several registers, this + /// method will abort as this is not like a default mapping anymore. + /// + /// \pre For OpIdx in {0..\p OpdMapper.getMI().getNumOperands()) + /// the range OpdMapper.getVRegs(OpIdx) is empty or of size 1. + static void applyDefaultMapping(const OperandsMapper &OpdMapper); + + /// See ::applyMapping. + virtual void applyMappingImpl(const OperandsMapper &OpdMapper) const { + llvm_unreachable("The target has to implement that part"); + } + public: virtual ~RegisterBankInfo() {} @@ -503,6 +519,24 @@ public: /// \post !returnedVal.empty(). InstructionMappings getInstrPossibleMappings(const MachineInstr &MI) const; + /// Apply \p OpdMapper.getInstrMapping() to \p OpdMapper.getMI(). + /// After this call \p OpdMapper.getMI() may not be valid anymore. + /// \p OpdMapper.getInstrMapping().getID() carries the information of + /// what has been chosen to map \p OpdMapper.getMI(). This ID is set + /// by the various getInstrXXXMapping method. + /// + /// Therefore, getting the mapping and applying it should be kept in + /// sync. + void applyMapping(const OperandsMapper &OpdMapper) const { + // The only mapping we know how to handle is the default mapping. + if (OpdMapper.getInstrMapping().getID() == DefaultMappingID) + return applyDefaultMapping(OpdMapper); + // For other mapping, the target needs to do the right thing. + // If that means calling applyDefaultMapping, fine, but this + // must be explicitly stated. + applyMappingImpl(OpdMapper); + } + /// Get the size in bits of \p Reg. /// Utility method to get the size of any registers. Unlike /// MachineRegisterInfo::getSize, the register does not need to be a diff --git a/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp b/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp index 02abb60e625..6bee4808406 100644 --- a/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp +++ b/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp @@ -332,6 +332,33 @@ RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const { return InstructionMappings(); } +void RegisterBankInfo::applyDefaultMapping(const OperandsMapper &OpdMapper) { + MachineInstr &MI = OpdMapper.getMI(); + DEBUG(dbgs() << "Applying default-like mapping\n"); + for (unsigned OpIdx = 0, EndIdx = MI.getNumOperands(); OpIdx != EndIdx; + ++OpIdx) { + DEBUG(dbgs() << "OpIdx " << OpIdx); + MachineOperand &MO = MI.getOperand(OpIdx); + if (!MO.isReg()) { + DEBUG(dbgs() << " is not a register, nothing to be done\n"); + continue; + } + assert( + OpdMapper.getInstrMapping().getOperandMapping(OpIdx).BreakDown.size() == + 1 && + "This mapping is too complex for this function"); + iterator_range::const_iterator> NewRegs = + OpdMapper.getVRegs(OpIdx); + if (NewRegs.begin() == NewRegs.end()) { + DEBUG(dbgs() << " has not been repaired, nothing to be done\n"); + continue; + } + DEBUG(dbgs() << " changed, replace " << MO.getReg()); + MO.setReg(*NewRegs.begin()); + DEBUG(dbgs() << " with " << MO.getReg()); + } +} + unsigned RegisterBankInfo::getSizeInBits(unsigned Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) {