summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/RegAllocFast.cpp
diff options
context:
space:
mode:
authorMatt Arsenault <Matthew.Arsenault@amd.com>2019-05-16 12:50:39 +0000
committerMatt Arsenault <Matthew.Arsenault@amd.com>2019-05-16 12:50:39 +0000
commit828b685ebe3fed20ec0674f9a38594bfed84621f (patch)
treee67f959e857f773a0b5b3ddf9d3280d5014426fd /llvm/lib/CodeGen/RegAllocFast.cpp
parent3a0e6e1c6c9622d692e94d627e17925b45602547 (diff)
downloadbcm5719-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.cpp91
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;
OpenPOWER on IntegriCloud