Index: include/llvm/CodeGen/GlobalISel/Utils.h =================================================================== --- include/llvm/CodeGen/GlobalISel/Utils.h +++ include/llvm/CodeGen/GlobalISel/Utils.h @@ -15,7 +15,6 @@ #define LLVM_CODEGEN_GLOBALISEL_UTILS_H #include "llvm/ADT/StringRef.h" - namespace llvm { class AnalysisUsage; @@ -36,21 +35,37 @@ class APFloat; /// Try to constrain Reg to the specified register class. If this fails, -/// create a new virtual register in the correct class and insert a COPY before -/// \p InsertPt. The debug location of \p InsertPt is used for the new copy. +/// create a new virtual register in the correct class. /// /// \return The virtual register constrained to the right register class. unsigned constrainRegToClass(MachineRegisterInfo &MRI, const TargetInstrInfo &TII, - const RegisterBankInfo &RBI, - MachineInstr &InsertPt, unsigned Reg, + const RegisterBankInfo &RBI, unsigned Reg, const TargetRegisterClass &RegClass); +/// Constrain the Register operand OpIdx, so that it is now constrained to the +/// TargetRegisterClass passed as an argument (RegClass). +/// If this fails, create a new virtual register in the correct class and +/// insert a COPY before \p InsertPt if it is a use or after if it is a +/// definition. The debug location of \p InsertPt is used for the new copy. +/// +/// \return The virtual register constrained to the right register class. +unsigned constrainOperandRegClass(const MachineFunction &MF, + const TargetRegisterInfo &TRI, + MachineRegisterInfo &MRI, + const TargetInstrInfo &TII, + const RegisterBankInfo &RBI, + MachineInstr &InsertPt, + const TargetRegisterClass &RegClass, + const MachineOperand &RegMO, unsigned OpIdx); + /// Try to constrain Reg so that it is usable by argument OpIdx of the /// provided MCInstrDesc \p II. If this fails, create a new virtual -/// register in the correct class and insert a COPY before \p InsertPt. -/// This is equivalent to constrainRegToClass() with RegClass obtained from the -/// MCInstrDesc. The debug location of \p InsertPt is used for the new copy. +/// register in the correct class and insert a COPY before \p InsertPt +/// if it is a use or after if it is a definition. +/// This is equivalent to constrainOperandRegClass(..., RegClass, ...) +/// with RegClass obtained from the MCInstrDesc. The debug location of \p +/// InsertPt is used for the new copy. /// /// \return The virtual register constrained to the right register class. unsigned constrainOperandRegClass(const MachineFunction &MF, @@ -59,7 +74,8 @@ const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const MCInstrDesc &II, - const MachineOperand &RegMO, unsigned OpIdx); + const MachineOperand &RegMO, unsigned OpIdx, + const TargetRegisterClass *RC = nullptr); /// Mutate the newly-selected instruction \p I to constrain its (possibly /// generic) virtual register operands to the instruction's register class. Index: lib/CodeGen/GlobalISel/InstructionSelector.cpp =================================================================== --- lib/CodeGen/GlobalISel/InstructionSelector.cpp +++ lib/CodeGen/GlobalISel/InstructionSelector.cpp @@ -41,8 +41,8 @@ MachineFunction &MF = *MBB.getParent(); MachineRegisterInfo &MRI = MF.getRegInfo(); - return - constrainRegToClass(MRI, TII, RBI, I, I.getOperand(OpIdx).getReg(), RC); + return constrainOperandRegClass(MF, TRI, MRI, TII, RBI, I, RC, + I.getOperand(OpIdx), OpIdx); } bool InstructionSelector::isOperandImmEqual( Index: lib/CodeGen/GlobalISel/Utils.cpp =================================================================== --- lib/CodeGen/GlobalISel/Utils.cpp +++ lib/CodeGen/GlobalISel/Utils.cpp @@ -29,31 +29,58 @@ unsigned llvm::constrainRegToClass(MachineRegisterInfo &MRI, const TargetInstrInfo &TII, - const RegisterBankInfo &RBI, - MachineInstr &InsertPt, unsigned Reg, + const RegisterBankInfo &RBI, unsigned Reg, const TargetRegisterClass &RegClass) { - if (!RBI.constrainGenericRegister(Reg, RegClass, MRI)) { - unsigned NewReg = MRI.createVirtualRegister(&RegClass); - BuildMI(*InsertPt.getParent(), InsertPt, InsertPt.getDebugLoc(), - TII.get(TargetOpcode::COPY), NewReg) - .addReg(Reg); - return NewReg; - } + if (!RBI.constrainGenericRegister(Reg, RegClass, MRI)) + return MRI.createVirtualRegister(&RegClass); return Reg; } +unsigned llvm::constrainOperandRegClass( + const MachineFunction &MF, const TargetRegisterInfo &TRI, + MachineRegisterInfo &MRI, const TargetInstrInfo &TII, + const RegisterBankInfo &RBI, MachineInstr &InsertPt, + const TargetRegisterClass &RegClass, const MachineOperand &RegMO, + unsigned OpIdx) { + unsigned Reg = RegMO.getReg(); + // Assume physical registers are properly constrained. + assert(TargetRegisterInfo::isVirtualRegister(Reg) && + "PhysReg not implemented"); + + unsigned ConstrainedReg = constrainRegToClass(MRI, TII, RBI, Reg, RegClass); + // If we created a new virtual register because the class is not compatible + // then create a copy between the new and the old register. + if (ConstrainedReg != Reg) { + MachineBasicBlock::iterator InsertIt(&InsertPt); + MachineBasicBlock &MBB = *InsertPt.getParent(); + if (RegMO.isUse()) { + BuildMI(MBB, InsertIt, InsertPt.getDebugLoc(), + TII.get(TargetOpcode::COPY), ConstrainedReg) + .addReg(Reg); + } else { + assert(RegMO.isDef() && "Must be a definition"); + BuildMI(MBB, std::next(InsertIt), InsertPt.getDebugLoc(), + TII.get(TargetOpcode::COPY), Reg) + .addReg(ConstrainedReg); + } + } + return ConstrainedReg; +} + unsigned llvm::constrainOperandRegClass( const MachineFunction &MF, const TargetRegisterInfo &TRI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const MCInstrDesc &II, - const MachineOperand &RegMO, unsigned OpIdx) { + const MachineOperand &RegMO, unsigned OpIdx, + const TargetRegisterClass *RC) { unsigned Reg = RegMO.getReg(); // Assume physical registers are properly constrained. assert(TargetRegisterInfo::isVirtualRegister(Reg) && "PhysReg not implemented"); - const TargetRegisterClass *RegClass = TII.getRegClass(II, OpIdx, &TRI, MF); + const TargetRegisterClass *RegClass = + RC ? RC : TII.getRegClass(II, OpIdx, &TRI, MF); // Some of the target independent instructions, like COPY, may not impose any // register class constraints on some of their operands: If it's a use, we can // skip constraining as the instruction defining the register would constrain @@ -81,7 +108,8 @@ // and they never reach this function. return Reg; } - return constrainRegToClass(MRI, TII, RBI, InsertPt, Reg, *RegClass); + return constrainOperandRegClass(MF, TRI, MRI, TII, RBI, InsertPt, *RegClass, + RegMO, OpIdx); } bool llvm::constrainSelectedInstRegOperands(MachineInstr &I,