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
float weight; // weight of this interval:
// (number of uses *10^loopDepth)
Ranges ranges; // the ranges in which this register is live
float weight; // weight of this interval:
// (number of uses *10^loopDepth)
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);
// done once for the vreg. We use an empty interval to detect the first
// time we see a vreg.
if (interval.empty()) {
// done once for the vreg. We use an empty interval to detect the first
// time we see a vreg.
if (interval.empty()) {
+ // Assume this interval is singly defined until we find otherwise.
+ interval.isDefinedOnce = true;
+
// Get the Idx of the defining instructions.
unsigned defIndex = getDefIndex(getInstructionIndex(mi));
// Get the Idx of the defining instructions.
unsigned defIndex = getDefIndex(getInstructionIndex(mi));
interval.addRange(defIndex,
getInstructionIndex(&mbb->back()) + InstrSlots::NUM);
}
interval.addRange(defIndex,
getInstructionIndex(&mbb->back()) + InstrSlots::NUM);
}
+ interval.isDefinedOnce = false;
}
DEBUG(std::cerr << '\n');
}
DEBUG(std::cerr << '\n');
Intervals::iterator intA = r2iA->second;
Intervals::iterator intB = r2iB->second;
Intervals::iterator intA = r2iA->second;
Intervals::iterator intB = r2iB->second;
+ DEBUG(std::cerr << "\t\tInspecting " << *intA << " and " << *intB
+ << ": ");
+
// both A and B are virtual registers
if (MRegisterInfo::isVirtualRegister(intA->reg) &&
MRegisterInfo::isVirtualRegister(intB->reg)) {
// both A and B are virtual registers
if (MRegisterInfo::isVirtualRegister(intA->reg) &&
MRegisterInfo::isVirtualRegister(intB->reg)) {
const TargetRegisterClass *rcA, *rcB;
rcA = mf_->getSSARegMap()->getRegClass(intA->reg);
rcB = mf_->getSSARegMap()->getRegClass(intB->reg);
const TargetRegisterClass *rcA, *rcB;
rcA = mf_->getSSARegMap()->getRegClass(intA->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) {
+ DEBUG(std::cerr << "Differing reg classes.\n");
// 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)) {
+ DEBUG(std::cerr << "Joined. Result = " << *intA << "\n");
r2iB->second = r2iA->second;
r2rMap_.insert(std::make_pair(intB->reg, intA->reg));
intervals_.erase(intB);
r2iB->second = r2iA->second;
r2rMap_.insert(std::make_pair(intB->reg, intA->reg));
intervals_.erase(intB);
+ } else {
+ DEBUG(std::cerr << "Interference!\n");
- } else if (MRegisterInfo::isPhysicalRegister(intA->reg) ^
- MRegisterInfo::isPhysicalRegister(intB->reg)) {
+ } else if (!MRegisterInfo::isPhysicalRegister(intA->reg) ||
+ !MRegisterInfo::isPhysicalRegister(intB->reg)) {
if (MRegisterInfo::isPhysicalRegister(intB->reg)) {
std::swap(regA, regB);
std::swap(intA, intB);
if (MRegisterInfo::isPhysicalRegister(intB->reg)) {
std::swap(regA, regB);
std::swap(intA, intB);
rcA = mri_->getRegClass(intA->reg);
rcB = mf_->getSSARegMap()->getRegClass(intB->reg);
// if they are not of the same register class we continue
rcA = mri_->getRegClass(intA->reg);
rcB = mf_->getSSARegMap()->getRegClass(intB->reg);
// if they are not of the same register class we continue
+ if (rcA != rcB) {
+ DEBUG(std::cerr << "Differing reg classes.\n");
if (!intA->overlaps(*intB) &&
!overlapsAliases(*intA, *intB)) {
intA->join(*intB);
if (!intA->overlaps(*intB) &&
!overlapsAliases(*intA, *intB)) {
intA->join(*intB);
+ DEBUG(std::cerr << "Joined. Result = " << *intA << "\n");
r2iB->second = r2iA->second;
r2rMap_.insert(std::make_pair(intB->reg, intA->reg));
intervals_.erase(intB);
r2iB->second = r2iA->second;
r2rMap_.insert(std::make_pair(intB->reg, intA->reg));
intervals_.erase(intB);
+ } else {
+ DEBUG(std::cerr << "Interference!\n");
+ } else {
+ DEBUG(std::cerr << "Cannot join physregs.\n");
LiveInterval::LiveInterval(unsigned r)
: reg(r),
LiveInterval::LiveInterval(unsigned 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
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(),
e = other.ranges.end(); i != e; ++i) {
for (Ranges::const_iterator i = other.ranges.begin(),
e = other.ranges.end(); i != e; ++i) {
}
weight += other.weight;
++numJoins;
}
weight += other.weight;
++numJoins;
- DEBUG(std::cerr << ". Result = " << *this << "\n");
}
LiveInterval::Ranges::iterator LiveInterval::
}
LiveInterval::Ranges::iterator LiveInterval::
float weight; // weight of this interval:
// (number of uses *10^loopDepth)
Ranges ranges; // the ranges in which this register is live
float weight; // weight of this interval:
// (number of uses *10^loopDepth)
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);