Index: lib/Target/SystemZ/SystemZISelLowering.cpp =================================================================== --- lib/Target/SystemZ/SystemZISelLowering.cpp +++ lib/Target/SystemZ/SystemZISelLowering.cpp @@ -5507,6 +5507,9 @@ return Reg; } +// EXPERIMENTAL +static cl::opt LOCRCONSTRAIN("locr-constrain", cl::Hidden, cl::init(false)); + // Implement EmitInstrWithCustomInserter for pseudo Select* instruction MI. MachineBasicBlock * SystemZTargetLowering::emitSelect(MachineInstr &MI, @@ -5528,6 +5531,23 @@ .addReg(FalseReg).addReg(TrueReg) .addImm(CCValid).addImm(CCMask); MI.eraseFromParent(); + + if (LOCROpcode == SystemZ::LOCRMux && LOCRCONSTRAIN) { + // Try to help regalloc by constraining GRX32 as called for. + const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); + MachineRegisterInfo *MRI = &MBB->getParent()->getRegInfo(); + // Find smallest common reg class of dest/true/false regs. + const TargetRegisterClass *RC = + TRI->getCommonSubClass(MRI->getRegClass(FalseReg), + MRI->getRegClass(TrueReg)); + RC = TRI->getCommonSubClass(RC, MRI->getRegClass(DestReg)); + if (RC && RC != &SystemZ::GRX32BitRegClass) { + MRI->setRegClass(DestReg, RC); + MRI->setRegClass(FalseReg, RC); + MRI->setRegClass(TrueReg, RC); + } + } + return MBB; } Index: lib/Target/SystemZ/SystemZRegisterInfo.h =================================================================== --- lib/Target/SystemZ/SystemZRegisterInfo.h +++ lib/Target/SystemZ/SystemZRegisterInfo.h @@ -42,6 +42,13 @@ return &SystemZ::ADDR64BitRegClass; } + void getRegAllocationHints(unsigned VirtReg, + ArrayRef Order, + SmallVectorImpl &Hints, + const MachineFunction &MF, + const VirtRegMap *VRM, + const LiveRegMatrix *Matrix) const override; + // Override TargetRegisterInfo.h. bool requiresRegisterScavenging(const MachineFunction &MF) const override { return true; Index: lib/Target/SystemZ/SystemZRegisterInfo.cpp =================================================================== --- lib/Target/SystemZ/SystemZRegisterInfo.cpp +++ lib/Target/SystemZ/SystemZRegisterInfo.cpp @@ -12,6 +12,7 @@ #include "SystemZSubtarget.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/VirtRegMap.h" #include "llvm/Target/TargetFrameLowering.h" using namespace llvm; @@ -22,6 +23,73 @@ SystemZRegisterInfo::SystemZRegisterInfo() : SystemZGenRegisterInfo(SystemZ::R14D) {} +// EXPERIMENTAL +static cl::opt LOCRHINTS("locr-hints", cl::Hidden, cl::init(true)); + +static const TargetRegisterClass *getRC32(MachineOperand &MO, + const VirtRegMap *VRM, + const MachineRegisterInfo *MRI) { + const TargetRegisterClass *RC = MRI->getRegClass(MO.getReg()); + + if (SystemZ::GR32BitRegClass.hasSubClassEq(RC) || + MO.getSubReg() == SystemZ::subreg_l32) + return &SystemZ::GR32BitRegClass; + if (RC == &SystemZ::GRH32BitRegClass || + MO.getSubReg() == SystemZ::subreg_h32) + return &SystemZ::GRH32BitRegClass; + + if (VRM && VRM->hasPhys(MO.getReg())) { + unsigned PhysReg = VRM->getPhys(MO.getReg()); + if (SystemZ::GR32BitRegClass.contains(PhysReg)) + return &SystemZ::GR32BitRegClass; + assert (SystemZ::GRH32BitRegClass.contains(PhysReg) && + "Phys reg not in GR32 or GRH32?"); + return &SystemZ::GRH32BitRegClass; + } + + return RC; +} + +void +SystemZRegisterInfo::getRegAllocationHints(unsigned VirtReg, + ArrayRef Order, + SmallVectorImpl &Hints, + const MachineFunction &MF, + const VirtRegMap *VRM, + const LiveRegMatrix *Matrix) const { + if (!LOCRHINTS) { + TargetRegisterInfo::getRegAllocationHints(VirtReg, Order, Hints, MF, VRM); + return; + } + + const MachineRegisterInfo &MRI = MF.getRegInfo(); + const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); + if (MRI.getRegClass(VirtReg) == &SystemZ::GRX32BitRegClass) { + for (auto &Use : MRI.use_instructions(VirtReg)) { + if (Use.getOpcode() == SystemZ::LOCRMux) { + // MachineOperand &DestMO = Use.getOperand(0); + MachineOperand &TrueMO = Use.getOperand(1); + MachineOperand &FalseMO = Use.getOperand(2); + const TargetRegisterClass *RC = + TRI->getCommonSubClass(getRC32(FalseMO, VRM, &MRI), + getRC32(TrueMO, VRM, &MRI)); + // RC = TRI->getCommonSubClass(RC, getRC32(DestMO, VRM, &MRI)); + + if (RC && RC != &SystemZ::GRX32BitRegClass) { + // Add all regs in the allocation order of VirtReg that are part of + // RC32 as hints. + for (MCPhysReg Reg : Order) + if (RC->contains(Reg) && !MRI.isReserved(Reg)) + Hints.push_back(Reg); + return; + } + } // LOCRMux + } // use_instructions + } // GRX32 + + TargetRegisterInfo::getRegAllocationHints(VirtReg, Order, Hints, MF, VRM); +} + const MCPhysReg * SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { if (MF->getSubtarget().getTargetLowering()->supportSwiftError() &&