Index: lib/CodeGen/RegAllocFast.cpp =================================================================== --- lib/CodeGen/RegAllocFast.cpp +++ lib/CodeGen/RegAllocFast.cpp @@ -156,6 +156,7 @@ enum : unsigned { spillClean = 50, spillDirty = 100, + spillPrefBonus = 20, spillImpossible = ~0u }; @@ -216,6 +217,9 @@ void spillAll(MachineBasicBlock::iterator MI, bool OnlyLiveOut); bool setPhysReg(MachineInstr &MI, MachineOperand &MO, MCPhysReg PhysReg); + unsigned traceCopies(unsigned VirtReg) const; + unsigned traceCopyChain(unsigned Reg) const; + int getStackSpaceFor(unsigned VirtReg); void spill(MachineBasicBlock::iterator Before, unsigned VirtReg, MCPhysReg AssignedReg, bool Kill); @@ -594,8 +598,48 @@ setPhysRegState(PhysReg, VirtReg); } +static bool isCoalescable(const MachineInstr &MI) { + return MI.isCopy() && MI.getOperand(0).getSubReg() == 0 && + MI.getOperand(1).getSubReg() == 0; +} + +unsigned RegAllocFast::traceCopyChain(unsigned Reg) const { + static const unsigned ChainLengthLimit = 3; + unsigned C = 0; + do { + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + return Reg; + assert(TargetRegisterInfo::isVirtualRegister(Reg)); + + MachineInstr *VRegDef = MRI->getUniqueVRegDef(Reg); + if (VRegDef == nullptr || !isCoalescable(*VRegDef)) + return 0; + Reg = VRegDef->getOperand(1).getReg(); + } while(++C <= ChainLengthLimit); + return 0; +} + +/// Check if any of \p VirtReg's definitions is a copy. If it is follow the +/// chain of copies to check whether we reach a physical register we can +/// coalesce with. +unsigned RegAllocFast::traceCopies(unsigned VirtReg) const { + static const unsigned DefLimit = 3; + unsigned C = 0; + for (const MachineInstr &MI : MRI->def_instructions(VirtReg)) { + if (isCoalescable(MI)) { + unsigned Reg = MI.getOperand(1).getReg(); + Reg = traceCopyChain(Reg); + if (Reg != 0) + return Reg; + } + if (++C >= DefLimit) + break; + } + return 0; +} + /// Allocates a physical register for VirtReg. -void RegAllocFast::allocVirtReg(MachineInstr &MI, LiveReg &LR, unsigned Hint) { +void RegAllocFast::allocVirtReg(MachineInstr &MI, LiveReg &LR, unsigned Hint1) { const unsigned VirtReg = LR.VirtReg; assert(TargetRegisterInfo::isVirtualRegister(VirtReg) && @@ -606,16 +650,45 @@ << " in class " << TRI->getRegClassName(&RC) << '\n'); // Take hint when possible. - if (TargetRegisterInfo::isPhysicalRegister(Hint) && - MRI->isAllocatable(Hint) && RC.contains(Hint)) { + unsigned Hint0 = traceCopies(VirtReg); + if (TargetRegisterInfo::isPhysicalRegister(Hint0) && + MRI->isAllocatable(Hint0) && RC.contains(Hint0) && + !isRegUsedInInstr(Hint0)) { + // Ignore the hint if we would have to spill a dirty register. + unsigned Cost = calcSpillCost(Hint0); + if (Cost < spillDirty) { + LLVM_DEBUG(dbgs() << "\tPreferred Register 0: " << printReg(Hint0, TRI) + << '\n'); + if (Cost) + definePhysReg(MI, Hint0, regFree); + assignVirtToPhysReg(LR, Hint0); + return; + } else { + LLVM_DEBUG(dbgs() << "\tPreferred Register 0: " << printReg(Hint0, TRI) + << "occupied\n"); + } + } else { + Hint0 = 0; + } + + // Try other hint. + if (TargetRegisterInfo::isPhysicalRegister(Hint1) && + MRI->isAllocatable(Hint1) && RC.contains(Hint1)) { // Ignore the hint if we would have to spill a dirty register. - unsigned Cost = calcSpillCost(Hint); + unsigned Cost = calcSpillCost(Hint1); if (Cost < spillDirty) { + LLVM_DEBUG(dbgs() << "\tPreferred Register 1: " << printReg(Hint1, TRI) + << '\n'); if (Cost) - definePhysReg(MI, Hint, regFree); - assignVirtToPhysReg(LR, Hint); + definePhysReg(MI, Hint1, regFree); + assignVirtToPhysReg(LR, Hint1); return; + } else { + LLVM_DEBUG(dbgs() << "\tPreferred Register 1: " << printReg(Hint1, TRI) + << "occupied\n"); } + } else { + Hint1 = 0; } MCPhysReg BestReg = 0; @@ -630,6 +703,8 @@ assignVirtToPhysReg(LR, PhysReg); return; } + if (PhysReg == Hint0 || PhysReg == Hint1) + Cost -= spillPrefBonus; if (Cost < BestCost) { BestReg = PhysReg; BestCost = Cost;