Index: llvm/include/llvm/CodeGen/GlobalISel/Utils.h =================================================================== --- llvm/include/llvm/CodeGen/GlobalISel/Utils.h +++ llvm/include/llvm/CodeGen/GlobalISel/Utils.h @@ -92,6 +92,16 @@ const RegisterBankInfo &RBI, Register Reg, const TargetRegisterClass &RegClass); +/// Check if constraining Reg to the specified register class is required. This +/// check is to be used in cases when we need to figure out upfront whether +/// constraining the register will cause any change at all. +/// +/// \return True if constraining is needed. +bool needToConstrainRegToClass(MachineRegisterInfo &MRI, + const TargetInstrInfo &TII, + const RegisterBankInfo &RBI, Register 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 Index: llvm/include/llvm/CodeGen/MachineRegisterInfo.h =================================================================== --- llvm/include/llvm/CodeGen/MachineRegisterInfo.h +++ llvm/include/llvm/CodeGen/MachineRegisterInfo.h @@ -703,6 +703,13 @@ const TargetRegisterClass *RC, unsigned MinNumRegs = 0); + /// Check if constraining the register to the specified register class is + /// required. This function is used to make sure if calling \p + /// constrainRegClass() for the \p Reg and \p RC will actually cause any + /// change. + bool needToConstrainRegClass(Register Reg, + const TargetRegisterClass *RC) const; + /// Constrain the register class or the register bank of the virtual register /// \p Reg (and low-level type) to be a common subclass or a common bank of /// both registers provided respectively (and a common low-level type). Do Index: llvm/include/llvm/CodeGen/RegisterBankInfo.h =================================================================== --- llvm/include/llvm/CodeGen/RegisterBankInfo.h +++ llvm/include/llvm/CodeGen/RegisterBankInfo.h @@ -635,6 +635,16 @@ return std::numeric_limits::max(); } + /// Check if there's a need to constrain the (possibly generic) virtual + /// register \p Reg to \p RC. + /// + /// \pre \p Reg is a virtual register that either has a bank or a class. + /// \returns True if a change is required to constrain the \p Reg to \p RC, + /// false otherwise. + static bool needToConstrainGenericRegister(Register Reg, + const TargetRegisterClass &RC, + MachineRegisterInfo &MRI); + /// Constrain the (possibly generic) virtual register \p Reg to \p RC. /// /// \pre \p Reg is a virtual register that either has a bank or a class. Index: llvm/lib/CodeGen/GlobalISel/Utils.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/Utils.cpp +++ llvm/lib/CodeGen/GlobalISel/Utils.cpp @@ -39,6 +39,13 @@ using namespace llvm; using namespace MIPatternMatch; +bool llvm::needToConstrainRegToClass(MachineRegisterInfo &MRI, + const TargetInstrInfo &TII, + const RegisterBankInfo &RBI, Register Reg, + const TargetRegisterClass &RegClass) { + return RBI.needToConstrainGenericRegister(Reg, RegClass, MRI); +} + Register llvm::constrainRegToClass(MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, Register Reg, @@ -58,6 +65,9 @@ // Assume physical registers are properly constrained. assert(Register::isVirtualRegister(Reg) && "PhysReg not implemented"); + if (!needToConstrainRegToClass(MRI, TII, RBI, Reg, RegClass)) + return Reg; + Register 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. Index: llvm/lib/CodeGen/MachineRegisterInfo.cpp =================================================================== --- llvm/lib/CodeGen/MachineRegisterInfo.cpp +++ llvm/lib/CodeGen/MachineRegisterInfo.cpp @@ -63,11 +63,16 @@ VRegInfo[Reg].first = &RegBank; } +static bool needToConstrainRegClass(const TargetRegisterClass *OldRC, + const TargetRegisterClass *RC) { + return OldRC != RC; +} + static const TargetRegisterClass * constrainRegClass(MachineRegisterInfo &MRI, Register Reg, const TargetRegisterClass *OldRC, const TargetRegisterClass *RC, unsigned MinNumRegs) { - if (OldRC == RC) + if (!needToConstrainRegClass(OldRC, RC)) return RC; const TargetRegisterClass *NewRC = MRI.getTargetRegisterInfo()->getCommonSubClass(OldRC, RC); @@ -79,6 +84,11 @@ return NewRC; } +bool MachineRegisterInfo::needToConstrainRegClass( + Register Reg, const TargetRegisterClass *RC) const { + return ::needToConstrainRegClass(getRegClass(Reg), RC); +} + const TargetRegisterClass * MachineRegisterInfo::constrainRegClass(Register Reg, const TargetRegisterClass *RC, Index: llvm/lib/CodeGen/RegisterBankInfo.cpp =================================================================== --- llvm/lib/CodeGen/RegisterBankInfo.cpp +++ llvm/lib/CodeGen/RegisterBankInfo.cpp @@ -126,6 +126,16 @@ return &RegBank; } +bool RegisterBankInfo::needToConstrainGenericRegister( + Register Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI) { + // If the register already has a class, there's a chance + // it's already constrained appropriately. + if (MRI.getRegClassOrNull(Reg) != nullptr) + return MRI.needToConstrainRegClass(Reg, &RC); + + return true; +} + const TargetRegisterClass *RegisterBankInfo::constrainGenericRegister( Register Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI) {