diff options
author | Matt Arsenault <Matthew.Arsenault@amd.com> | 2019-05-16 12:50:39 +0000 |
---|---|---|
committer | Matt Arsenault <Matthew.Arsenault@amd.com> | 2019-05-16 12:50:39 +0000 |
commit | 828b685ebe3fed20ec0674f9a38594bfed84621f (patch) | |
tree | e67f959e857f773a0b5b3ddf9d3280d5014426fd /llvm/lib/CodeGen/RegAllocFast.cpp | |
parent | 3a0e6e1c6c9622d692e94d627e17925b45602547 (diff) | |
download | bcm5719-llvm-828b685ebe3fed20ec0674f9a38594bfed84621f.tar.gz bcm5719-llvm-828b685ebe3fed20ec0674f9a38594bfed84621f.zip |
RegAllocFast: Improve hinting heuristic
Trace through multiple COPYs when looking for a physreg source. Add
hinting for vregs that will be copied into physregs (we only hinted
for vregs getting copied to a physreg previously). Give hinted a
register a bonus when deciding which value to spill. This is part of
my rewrite regallocfast series. In fact this one doesn't even have an
effect unless you also flip the allocation to happen from back to
front of a basic block. Nonetheless it helps to split this up to ease
review of D52010
Patch by Matthias Braun
llvm-svn: 360887
Diffstat (limited to 'llvm/lib/CodeGen/RegAllocFast.cpp')
-rw-r--r-- | llvm/lib/CodeGen/RegAllocFast.cpp | 91 |
1 files changed, 84 insertions, 7 deletions
diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp index 52502a4b821..4da0912508d 100644 --- a/llvm/lib/CodeGen/RegAllocFast.cpp +++ b/llvm/lib/CodeGen/RegAllocFast.cpp @@ -155,6 +155,7 @@ namespace { enum : unsigned { spillClean = 50, spillDirty = 100, + spillPrefBonus = 20, spillImpossible = ~0u }; @@ -215,6 +216,9 @@ namespace { 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); @@ -593,8 +597,48 @@ void RegAllocFast::assignVirtToPhysReg(LiveReg &LR, MCPhysReg PhysReg) { setPhysRegState(PhysReg, VirtReg); } +static bool isCoalescable(const MachineInstr &MI) { + return MI.isFullCopy(); +} + +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 || !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 Hint0) { const unsigned VirtReg = LR.VirtReg; assert(TargetRegisterInfo::isVirtualRegister(VirtReg) && @@ -603,19 +647,48 @@ void RegAllocFast::allocVirtReg(MachineInstr &MI, LiveReg &LR, unsigned Hint) { const TargetRegisterClass &RC = *MRI->getRegClass(VirtReg); LLVM_DEBUG(dbgs() << "Search register for " << printReg(VirtReg) << " in class " << TRI->getRegClassName(&RC) - << " with hint " << printReg(Hint, TRI) << '\n'); + << " with hint " << printReg(Hint0, TRI) << '\n'); // Take hint when possible. - if (TargetRegisterInfo::isPhysicalRegister(Hint) && - MRI->isAllocatable(Hint) && RC.contains(Hint)) { + if (TargetRegisterInfo::isPhysicalRegister(Hint0) && + MRI->isAllocatable(Hint0) && RC.contains(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 1: " << printReg(Hint0, TRI) + << '\n'); + if (Cost) + definePhysReg(MI, Hint0, regFree); + assignVirtToPhysReg(LR, Hint0); + return; + } else { + LLVM_DEBUG(dbgs() << "\tPreferred Register 1: " << printReg(Hint0, TRI) + << "occupied\n"); + } + } else { + Hint0 = 0; + } + + // Try other hint. + unsigned Hint1 = traceCopies(VirtReg); + if (TargetRegisterInfo::isPhysicalRegister(Hint1) && + MRI->isAllocatable(Hint1) && RC.contains(Hint1) && + !isRegUsedInInstr(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 0: " << 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 0: " << printReg(Hint1, TRI) + << "occupied\n"); } + } else { + Hint1 = 0; } MCPhysReg BestReg = 0; @@ -630,6 +703,10 @@ void RegAllocFast::allocVirtReg(MachineInstr &MI, LiveReg &LR, unsigned Hint) { assignVirtToPhysReg(LR, PhysReg); return; } + + if (PhysReg == Hint1 || PhysReg == Hint0) + Cost -= spillPrefBonus; + if (Cost < BestCost) { BestReg = PhysReg; BestCost = Cost; |