mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-05-25 10:38:44 +00:00
Make the coallescer a bit smarter, allowing it to join more live ranges.
For example, we can now join things like [0-30:0)[31-40:1)[52-59:2) with [40:60:0) if the 52-59 range is defined by a copy from the 40-60 range. The resultant range ends up being [0-30:0)[31-60:1). This fires a lot through-out the test suite (e.g. shrinking bc from 19492 -> 18509 machineinstrs) though most gains are smaller (e.g. about 50 copies eliminated from crafty). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23866 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9e20d352c2
commit
aa51a484e1
@ -633,6 +633,49 @@ void LiveIntervals::computeIntervals()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// IntA is defined as a copy from IntB and we know it only has one value
|
||||||
|
/// number. If all of the places that IntA and IntB overlap are defined by
|
||||||
|
/// copies from IntA to IntB, we know that these two ranges can really be
|
||||||
|
/// merged if we adjust the value numbers. If it is safe, adjust the value
|
||||||
|
/// numbers and return true, allowing coallescing to occur.
|
||||||
|
bool LiveIntervals::
|
||||||
|
AdjustIfAllOverlappingRangesAreCopiesFrom(LiveInterval &IntA,
|
||||||
|
LiveInterval &IntB,
|
||||||
|
unsigned CopyIdx) {
|
||||||
|
std::vector<LiveRange*> Ranges;
|
||||||
|
IntA.getOverlapingRanges(IntB, CopyIdx, Ranges);
|
||||||
|
|
||||||
|
assert(!Ranges.empty() && "Why didn't we do a simple join of this?");
|
||||||
|
|
||||||
|
unsigned IntBRep = rep(IntB.reg);
|
||||||
|
|
||||||
|
// Check to see if all of the overlaps (entries in Ranges) are defined by a
|
||||||
|
// copy from IntA. If not, exit.
|
||||||
|
for (unsigned i = 0, e = Ranges.size(); i != e; ++i) {
|
||||||
|
unsigned Idx = Ranges[i]->start;
|
||||||
|
MachineInstr *MI = getInstructionFromIndex(Idx);
|
||||||
|
unsigned SrcReg, DestReg;
|
||||||
|
if (!tii_->isMoveInstr(*MI, SrcReg, DestReg)) return false;
|
||||||
|
|
||||||
|
// If this copy isn't actually defining this range, it must be a live
|
||||||
|
// range spanning basic blocks or something.
|
||||||
|
if (rep(DestReg) != rep(IntA.reg)) return false;
|
||||||
|
|
||||||
|
// Check to see if this is coming from IntB. If not, bail out.
|
||||||
|
if (rep(SrcReg) != IntBRep) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Okay, we can change this one. Get the IntB value number that IntA is
|
||||||
|
// copied from.
|
||||||
|
unsigned ActualValNo = IntA.getLiveRangeContaining(CopyIdx-1)->ValId;
|
||||||
|
|
||||||
|
// Change all of the value numbers to the same as what we IntA is copied from.
|
||||||
|
for (unsigned i = 0, e = Ranges.size(); i != e; ++i)
|
||||||
|
Ranges[i]->ValId = ActualValNo;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void LiveIntervals::joinIntervalsInMachineBB(MachineBasicBlock *MBB) {
|
void LiveIntervals::joinIntervalsInMachineBB(MachineBasicBlock *MBB) {
|
||||||
DEBUG(std::cerr << ((Value*)MBB->getBasicBlock())->getName() << ":\n");
|
DEBUG(std::cerr << ((Value*)MBB->getBasicBlock())->getName() << ":\n");
|
||||||
|
|
||||||
@ -643,60 +686,72 @@ void LiveIntervals::joinIntervalsInMachineBB(MachineBasicBlock *MBB) {
|
|||||||
// we only join virtual registers with allocatable
|
// we only join virtual registers with allocatable
|
||||||
// physical registers since we do not have liveness information
|
// physical registers since we do not have liveness information
|
||||||
// on not allocatable physical registers
|
// on not allocatable physical registers
|
||||||
unsigned regA, regB;
|
unsigned SrcReg, DestReg;
|
||||||
if (tii_->isMoveInstr(*mi, regA, regB) &&
|
if (tii_->isMoveInstr(*mi, SrcReg, DestReg) &&
|
||||||
(MRegisterInfo::isVirtualRegister(regA) || allocatableRegs_[regA]) &&
|
(MRegisterInfo::isVirtualRegister(SrcReg) || allocatableRegs_[SrcReg])&&
|
||||||
(MRegisterInfo::isVirtualRegister(regB) || allocatableRegs_[regB])) {
|
(MRegisterInfo::isVirtualRegister(DestReg)||allocatableRegs_[DestReg])){
|
||||||
|
|
||||||
// Get representative registers.
|
// Get representative registers.
|
||||||
regA = rep(regA);
|
SrcReg = rep(SrcReg);
|
||||||
regB = rep(regB);
|
DestReg = rep(DestReg);
|
||||||
|
|
||||||
// If they are already joined we continue.
|
// If they are already joined we continue.
|
||||||
if (regA == regB)
|
if (SrcReg == DestReg)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// If they are both physical registers, we cannot join them.
|
// If they are both physical registers, we cannot join them.
|
||||||
if (MRegisterInfo::isPhysicalRegister(regA) &&
|
if (MRegisterInfo::isPhysicalRegister(SrcReg) &&
|
||||||
MRegisterInfo::isPhysicalRegister(regB))
|
MRegisterInfo::isPhysicalRegister(DestReg))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// If they are not of the same register class, we cannot join them.
|
// If they are not of the same register class, we cannot join them.
|
||||||
if (differingRegisterClasses(regA, regB))
|
if (differingRegisterClasses(SrcReg, DestReg))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
LiveInterval &IntA = getInterval(regA);
|
LiveInterval &SrcInt = getInterval(SrcReg);
|
||||||
LiveInterval &IntB = getInterval(regB);
|
LiveInterval &DestInt = getInterval(DestReg);
|
||||||
assert(IntA.reg == regA && IntB.reg == regB &&
|
assert(SrcInt.reg == SrcReg && DestInt.reg == DestReg &&
|
||||||
"Register mapping is horribly broken!");
|
"Register mapping is horribly broken!");
|
||||||
|
|
||||||
DEBUG(std::cerr << "\t\tInspecting " << IntA << " and " << IntB << ": ");
|
DEBUG(std::cerr << "\t\tInspecting " << SrcInt << " and " << DestInt
|
||||||
|
<< ": ");
|
||||||
|
|
||||||
// If two intervals contain a single value and are joined by a copy, it
|
// If two intervals contain a single value and are joined by a copy, it
|
||||||
// does not matter if the intervals overlap, they can always be joined.
|
// does not matter if the intervals overlap, they can always be joined.
|
||||||
bool TriviallyJoinable =
|
bool Joinable = SrcInt.containsOneValue() && DestInt.containsOneValue();
|
||||||
IntA.containsOneValue() && IntB.containsOneValue();
|
|
||||||
|
|
||||||
unsigned MIDefIdx = getDefIndex(getInstructionIndex(mi));
|
unsigned MIDefIdx = getDefIndex(getInstructionIndex(mi));
|
||||||
if ((TriviallyJoinable || IntB.joinable(IntA, MIDefIdx)) &&
|
|
||||||
!overlapsAliases(&IntA, &IntB)) {
|
// If the intervals think that this is joinable, do so now.
|
||||||
IntB.join(IntA, MIDefIdx);
|
if (!Joinable && DestInt.joinable(SrcInt, MIDefIdx))
|
||||||
DEBUG(std::cerr << "Joined. Result = " << IntB << "\n");
|
Joinable = true;
|
||||||
|
|
||||||
if (!MRegisterInfo::isPhysicalRegister(regA)) {
|
// If DestInt is actually a copy from SrcInt (which we know) that is used
|
||||||
r2iMap_.erase(regA);
|
// to define another value of SrcInt, we can change the other range of
|
||||||
r2rMap_[regA] = regB;
|
// SrcInt to be the value of the range that defines DestInt, allowing a
|
||||||
|
// coallesce.
|
||||||
|
if (!Joinable && DestInt.containsOneValue() &&
|
||||||
|
AdjustIfAllOverlappingRangesAreCopiesFrom(SrcInt, DestInt, MIDefIdx))
|
||||||
|
Joinable = true;
|
||||||
|
|
||||||
|
if (!Joinable || overlapsAliases(&SrcInt, &DestInt)) {
|
||||||
|
DEBUG(std::cerr << "Interference!\n");
|
||||||
|
} else {
|
||||||
|
DestInt.join(SrcInt, MIDefIdx);
|
||||||
|
DEBUG(std::cerr << "Joined. Result = " << DestInt << "\n");
|
||||||
|
|
||||||
|
if (!MRegisterInfo::isPhysicalRegister(SrcReg)) {
|
||||||
|
r2iMap_.erase(SrcReg);
|
||||||
|
r2rMap_[SrcReg] = DestReg;
|
||||||
} else {
|
} else {
|
||||||
// Otherwise merge the data structures the other way so we don't lose
|
// Otherwise merge the data structures the other way so we don't lose
|
||||||
// the physreg information.
|
// the physreg information.
|
||||||
r2rMap_[regB] = regA;
|
r2rMap_[DestReg] = SrcReg;
|
||||||
IntB.reg = regA;
|
DestInt.reg = SrcReg;
|
||||||
IntA.swap(IntB);
|
SrcInt.swap(DestInt);
|
||||||
r2iMap_.erase(regB);
|
r2iMap_.erase(DestReg);
|
||||||
}
|
}
|
||||||
++numJoins;
|
++numJoins;
|
||||||
} else {
|
|
||||||
DEBUG(std::cerr << "Interference!\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user