mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-15 06:29:05 +00:00
Force coallescing of live ranges that have a single definition, even if they
interfere. Because these intervals have a single definition, and one of them is a copy instruction, they are always safe to merge even if their lifetimes interfere. This slightly reduces the amount of spill code, for example on 252.eon, from: 12837 spiller - Number of loads added 7604 spiller - Number of stores added 5842 spiller - Number of register spills 18155 liveintervals - Number of identity moves eliminated after coalescing to: 12754 spiller - Number of loads added 7585 spiller - Number of stores added 5803 spiller - Number of register spills 18262 liveintervals - Number of identity moves eliminated after coalescing The much much bigger win would be to merge intervals with multiple definitions (aka phi nodes) but this is not that day. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15124 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -36,6 +36,7 @@ namespace llvm {
|
|||||||
float weight; // weight of this interval:
|
float weight; // weight of this interval:
|
||||||
// (number of uses *10^loopDepth)
|
// (number of uses *10^loopDepth)
|
||||||
Ranges ranges; // the ranges in which this register is live
|
Ranges ranges; // the ranges in which this register is live
|
||||||
|
bool isDefinedOnce; // True if there is one def of this register
|
||||||
|
|
||||||
explicit LiveInterval(unsigned r);
|
explicit LiveInterval(unsigned r);
|
||||||
|
|
||||||
|
@@ -285,6 +285,9 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock* mbb,
|
|||||||
// done once for the vreg. We use an empty interval to detect the first
|
// done once for the vreg. We use an empty interval to detect the first
|
||||||
// time we see a vreg.
|
// time we see a vreg.
|
||||||
if (interval.empty()) {
|
if (interval.empty()) {
|
||||||
|
// Assume this interval is singly defined until we find otherwise.
|
||||||
|
interval.isDefinedOnce = true;
|
||||||
|
|
||||||
// Get the Idx of the defining instructions.
|
// Get the Idx of the defining instructions.
|
||||||
unsigned defIndex = getDefIndex(getInstructionIndex(mi));
|
unsigned defIndex = getDefIndex(getInstructionIndex(mi));
|
||||||
|
|
||||||
@@ -357,6 +360,7 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock* mbb,
|
|||||||
interval.addRange(defIndex,
|
interval.addRange(defIndex,
|
||||||
getInstructionIndex(&mbb->back()) + InstrSlots::NUM);
|
getInstructionIndex(&mbb->back()) + InstrSlots::NUM);
|
||||||
}
|
}
|
||||||
|
interval.isDefinedOnce = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG(std::cerr << '\n');
|
DEBUG(std::cerr << '\n');
|
||||||
@@ -524,6 +528,9 @@ void LiveIntervals::joinIntervalsInMachineBB(MachineBasicBlock *MBB) {
|
|||||||
Intervals::iterator intA = r2iA->second;
|
Intervals::iterator intA = r2iA->second;
|
||||||
Intervals::iterator intB = r2iB->second;
|
Intervals::iterator intB = r2iB->second;
|
||||||
|
|
||||||
|
DEBUG(std::cerr << "\t\tInspecting " << *intA << " and " << *intB
|
||||||
|
<< ": ");
|
||||||
|
|
||||||
// both A and B are virtual registers
|
// both A and B are virtual registers
|
||||||
if (MRegisterInfo::isVirtualRegister(intA->reg) &&
|
if (MRegisterInfo::isVirtualRegister(intA->reg) &&
|
||||||
MRegisterInfo::isVirtualRegister(intB->reg)) {
|
MRegisterInfo::isVirtualRegister(intB->reg)) {
|
||||||
@@ -531,19 +538,26 @@ void LiveIntervals::joinIntervalsInMachineBB(MachineBasicBlock *MBB) {
|
|||||||
const TargetRegisterClass *rcA, *rcB;
|
const TargetRegisterClass *rcA, *rcB;
|
||||||
rcA = mf_->getSSARegMap()->getRegClass(intA->reg);
|
rcA = mf_->getSSARegMap()->getRegClass(intA->reg);
|
||||||
rcB = mf_->getSSARegMap()->getRegClass(intB->reg);
|
rcB = mf_->getSSARegMap()->getRegClass(intB->reg);
|
||||||
|
|
||||||
// if they are not of the same register class we continue
|
// if they are not of the same register class we continue
|
||||||
if (rcA != rcB)
|
if (rcA != rcB) {
|
||||||
|
DEBUG(std::cerr << "Differing reg classes.\n");
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// if their intervals do not overlap we join them
|
// if their intervals do not overlap we join them
|
||||||
if (!intB->overlaps(*intA)) {
|
if ((intA->isDefinedOnce && intB->isDefinedOnce) ||
|
||||||
|
!intB->overlaps(*intA)) {
|
||||||
intA->join(*intB);
|
intA->join(*intB);
|
||||||
|
DEBUG(std::cerr << "Joined. Result = " << *intA << "\n");
|
||||||
r2iB->second = r2iA->second;
|
r2iB->second = r2iA->second;
|
||||||
r2rMap_.insert(std::make_pair(intB->reg, intA->reg));
|
r2rMap_.insert(std::make_pair(intB->reg, intA->reg));
|
||||||
intervals_.erase(intB);
|
intervals_.erase(intB);
|
||||||
|
} else {
|
||||||
|
DEBUG(std::cerr << "Interference!\n");
|
||||||
}
|
}
|
||||||
} else if (MRegisterInfo::isPhysicalRegister(intA->reg) ^
|
} else if (!MRegisterInfo::isPhysicalRegister(intA->reg) ||
|
||||||
MRegisterInfo::isPhysicalRegister(intB->reg)) {
|
!MRegisterInfo::isPhysicalRegister(intB->reg)) {
|
||||||
if (MRegisterInfo::isPhysicalRegister(intB->reg)) {
|
if (MRegisterInfo::isPhysicalRegister(intB->reg)) {
|
||||||
std::swap(regA, regB);
|
std::swap(regA, regB);
|
||||||
std::swap(intA, intB);
|
std::swap(intA, intB);
|
||||||
@@ -558,16 +572,23 @@ void LiveIntervals::joinIntervalsInMachineBB(MachineBasicBlock *MBB) {
|
|||||||
rcA = mri_->getRegClass(intA->reg);
|
rcA = mri_->getRegClass(intA->reg);
|
||||||
rcB = mf_->getSSARegMap()->getRegClass(intB->reg);
|
rcB = mf_->getSSARegMap()->getRegClass(intB->reg);
|
||||||
// if they are not of the same register class we continue
|
// if they are not of the same register class we continue
|
||||||
if (rcA != rcB)
|
if (rcA != rcB) {
|
||||||
|
DEBUG(std::cerr << "Differing reg classes.\n");
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!intA->overlaps(*intB) &&
|
if (!intA->overlaps(*intB) &&
|
||||||
!overlapsAliases(*intA, *intB)) {
|
!overlapsAliases(*intA, *intB)) {
|
||||||
intA->join(*intB);
|
intA->join(*intB);
|
||||||
|
DEBUG(std::cerr << "Joined. Result = " << *intA << "\n");
|
||||||
r2iB->second = r2iA->second;
|
r2iB->second = r2iA->second;
|
||||||
r2rMap_.insert(std::make_pair(intB->reg, intA->reg));
|
r2rMap_.insert(std::make_pair(intB->reg, intA->reg));
|
||||||
intervals_.erase(intB);
|
intervals_.erase(intB);
|
||||||
|
} else {
|
||||||
|
DEBUG(std::cerr << "Interference!\n");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
DEBUG(std::cerr << "Cannot join physregs.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -642,8 +663,8 @@ LiveInterval& LiveIntervals::getOrCreateInterval(unsigned reg)
|
|||||||
|
|
||||||
LiveInterval::LiveInterval(unsigned r)
|
LiveInterval::LiveInterval(unsigned r)
|
||||||
: reg(r),
|
: reg(r),
|
||||||
weight((MRegisterInfo::isPhysicalRegister(r) ? HUGE_VAL : 0.0F))
|
weight((MRegisterInfo::isPhysicalRegister(r) ? HUGE_VAL : 0.0F)),
|
||||||
{
|
isDefinedOnce(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LiveInterval::spilled() const
|
bool LiveInterval::spilled() const
|
||||||
@@ -740,8 +761,8 @@ void LiveInterval::addRange(unsigned start, unsigned end)
|
|||||||
|
|
||||||
void LiveInterval::join(const LiveInterval& other)
|
void LiveInterval::join(const LiveInterval& other)
|
||||||
{
|
{
|
||||||
DEBUG(std::cerr << "\t\tjoining " << *this << " with " << other);
|
|
||||||
Ranges::iterator cur = ranges.begin();
|
Ranges::iterator cur = ranges.begin();
|
||||||
|
isDefinedOnce &= other.isDefinedOnce;
|
||||||
|
|
||||||
for (Ranges::const_iterator i = other.ranges.begin(),
|
for (Ranges::const_iterator i = other.ranges.begin(),
|
||||||
e = other.ranges.end(); i != e; ++i) {
|
e = other.ranges.end(); i != e; ++i) {
|
||||||
@@ -751,7 +772,6 @@ void LiveInterval::join(const LiveInterval& other)
|
|||||||
}
|
}
|
||||||
weight += other.weight;
|
weight += other.weight;
|
||||||
++numJoins;
|
++numJoins;
|
||||||
DEBUG(std::cerr << ". Result = " << *this << "\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LiveInterval::Ranges::iterator LiveInterval::
|
LiveInterval::Ranges::iterator LiveInterval::
|
||||||
|
@@ -36,6 +36,7 @@ namespace llvm {
|
|||||||
float weight; // weight of this interval:
|
float weight; // weight of this interval:
|
||||||
// (number of uses *10^loopDepth)
|
// (number of uses *10^loopDepth)
|
||||||
Ranges ranges; // the ranges in which this register is live
|
Ranges ranges; // the ranges in which this register is live
|
||||||
|
bool isDefinedOnce; // True if there is one def of this register
|
||||||
|
|
||||||
explicit LiveInterval(unsigned r);
|
explicit LiveInterval(unsigned r);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user