mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-01 15:11:24 +00:00
Also attempt trivial coalescing for live intervals that end in a copy.
The coalescer is supposed to clean these up, but when setting up parameters for a function call, there may be copies to physregs. If the defining instruction has been LICM'ed far away, the coalescer won't touch it. The register allocation hint does not always work - when the register allocator is backtracking, it clears the hints. This patch is more conservative than r90502, and does not break 483.xalancbmk/i686. It still breaks the PowerPC bootstrap, so it is disabled by default, and can be enabled with the -trivial-coalesce-ends option. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@91049 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f05e45eb37
commit
cf97036675
@ -112,10 +112,13 @@ namespace llvm {
|
||||
return (unsigned)(IntervalPercentage * indexes_->getFunctionSize());
|
||||
}
|
||||
|
||||
/// conflictsWithPhysRegDef - Returns true if the specified register
|
||||
/// is defined during the duration of the specified interval.
|
||||
bool conflictsWithPhysRegDef(const LiveInterval &li, VirtRegMap &vrm,
|
||||
unsigned reg);
|
||||
/// conflictsWithPhysReg - Returns true if the specified register is used or
|
||||
/// defined during the duration of the specified interval. Copies to and
|
||||
/// from li.reg are allowed. This method is only able to analyze simple
|
||||
/// ranges that stay within a single basic block. Anything else is
|
||||
/// considered a conflict.
|
||||
bool conflictsWithPhysReg(const LiveInterval &li, VirtRegMap &vrm,
|
||||
unsigned reg);
|
||||
|
||||
/// conflictsWithPhysRegRef - Similar to conflictsWithPhysRegRef except
|
||||
/// it can check use as well.
|
||||
|
@ -149,42 +149,69 @@ void LiveIntervals::dumpInstrs() const {
|
||||
printInstrs(errs());
|
||||
}
|
||||
|
||||
/// conflictsWithPhysRegDef - Returns true if the specified register
|
||||
/// is defined during the duration of the specified interval.
|
||||
bool LiveIntervals::conflictsWithPhysRegDef(const LiveInterval &li,
|
||||
VirtRegMap &vrm, unsigned reg) {
|
||||
for (LiveInterval::Ranges::const_iterator
|
||||
I = li.ranges.begin(), E = li.ranges.end(); I != E; ++I) {
|
||||
for (SlotIndex index = I->start.getBaseIndex(),
|
||||
end = I->end.getPrevSlot().getBaseIndex().getNextIndex();
|
||||
index != end;
|
||||
index = index.getNextIndex()) {
|
||||
MachineInstr *MI = getInstructionFromIndex(index);
|
||||
if (!MI)
|
||||
continue; // skip deleted instructions
|
||||
bool LiveIntervals::conflictsWithPhysReg(const LiveInterval &li,
|
||||
VirtRegMap &vrm, unsigned reg) {
|
||||
// We don't handle fancy stuff crossing basic block boundaries
|
||||
if (li.ranges.size() != 1)
|
||||
return true;
|
||||
const LiveRange &range = li.ranges.front();
|
||||
SlotIndex idx = range.start.getBaseIndex();
|
||||
SlotIndex end = range.end.getPrevSlot().getBaseIndex().getNextIndex();
|
||||
|
||||
unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
|
||||
if (tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubReg, DstSubReg))
|
||||
if (SrcReg == li.reg || DstReg == li.reg)
|
||||
// Skip deleted instructions
|
||||
MachineInstr *firstMI = getInstructionFromIndex(idx);
|
||||
while (!firstMI && idx != end) {
|
||||
idx = idx.getNextIndex();
|
||||
firstMI = getInstructionFromIndex(idx);
|
||||
}
|
||||
if (!firstMI)
|
||||
return false;
|
||||
|
||||
// Find last instruction in range
|
||||
SlotIndex lastIdx = end.getPrevIndex();
|
||||
MachineInstr *lastMI = getInstructionFromIndex(lastIdx);
|
||||
while (!lastMI && lastIdx != idx) {
|
||||
lastIdx = lastIdx.getPrevIndex();
|
||||
lastMI = getInstructionFromIndex(lastIdx);
|
||||
}
|
||||
if (!lastMI)
|
||||
return false;
|
||||
|
||||
// Range cannot cross basic block boundaries or terminators
|
||||
MachineBasicBlock *MBB = firstMI->getParent();
|
||||
if (MBB != lastMI->getParent() || lastMI->getDesc().isTerminator())
|
||||
return true;
|
||||
|
||||
MachineBasicBlock::const_iterator E = lastMI;
|
||||
++E;
|
||||
for (MachineBasicBlock::const_iterator I = firstMI; I != E; ++I) {
|
||||
const MachineInstr &MI = *I;
|
||||
|
||||
// Allow copies to and from li.reg
|
||||
unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
|
||||
if (tii_->isMoveInstr(MI, SrcReg, DstReg, SrcSubReg, DstSubReg))
|
||||
if (SrcReg == li.reg || DstReg == li.reg)
|
||||
continue;
|
||||
|
||||
// Check for operands using reg
|
||||
for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
|
||||
const MachineOperand& mop = MI.getOperand(i);
|
||||
if (!mop.isReg())
|
||||
continue;
|
||||
unsigned PhysReg = mop.getReg();
|
||||
if (PhysReg == 0 || PhysReg == li.reg)
|
||||
continue;
|
||||
if (TargetRegisterInfo::isVirtualRegister(PhysReg)) {
|
||||
if (!vrm.hasPhys(PhysReg))
|
||||
continue;
|
||||
for (unsigned i = 0; i != MI->getNumOperands(); ++i) {
|
||||
MachineOperand& mop = MI->getOperand(i);
|
||||
if (!mop.isReg())
|
||||
continue;
|
||||
unsigned PhysReg = mop.getReg();
|
||||
if (PhysReg == 0 || PhysReg == li.reg)
|
||||
continue;
|
||||
if (TargetRegisterInfo::isVirtualRegister(PhysReg)) {
|
||||
if (!vrm.hasPhys(PhysReg))
|
||||
continue;
|
||||
PhysReg = vrm.getPhys(PhysReg);
|
||||
}
|
||||
if (PhysReg && tri_->regsOverlap(PhysReg, reg))
|
||||
return true;
|
||||
PhysReg = vrm.getPhys(PhysReg);
|
||||
}
|
||||
if (PhysReg && tri_->regsOverlap(PhysReg, reg))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// No conflicts found.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,11 @@ PreSplitIntervals("pre-alloc-split",
|
||||
cl::desc("Pre-register allocation live interval splitting"),
|
||||
cl::init(false), cl::Hidden);
|
||||
|
||||
static cl::opt<bool>
|
||||
TrivCoalesceEnds("trivial-coalesce-ends",
|
||||
cl::desc("Attempt trivial coalescing of interval ends"),
|
||||
cl::init(false), cl::Hidden);
|
||||
|
||||
static RegisterRegAlloc
|
||||
linearscanRegAlloc("linearscan", "linear scan register allocator",
|
||||
createLinearScanRegisterAllocator);
|
||||
@ -390,66 +395,71 @@ void RALinScan::ComputeRelatedRegClasses() {
|
||||
RelatedRegClasses.unionSets(I->second, OneClassForEachPhysReg[*AS]);
|
||||
}
|
||||
|
||||
/// attemptTrivialCoalescing - If a simple interval is defined by a copy,
|
||||
/// try allocate the definition the same register as the source register
|
||||
/// if the register is not defined during live time of the interval. This
|
||||
/// eliminate a copy. This is used to coalesce copies which were not
|
||||
/// coalesced away before allocation either due to dest and src being in
|
||||
/// different register classes or because the coalescer was overly
|
||||
/// conservative.
|
||||
/// attemptTrivialCoalescing - If a simple interval is defined by a copy, try
|
||||
/// allocate the definition the same register as the source register if the
|
||||
/// register is not defined during live time of the interval. If the interval is
|
||||
/// killed by a copy, try to use the destination register. This eliminates a
|
||||
/// copy. This is used to coalesce copies which were not coalesced away before
|
||||
/// allocation either due to dest and src being in different register classes or
|
||||
/// because the coalescer was overly conservative.
|
||||
unsigned RALinScan::attemptTrivialCoalescing(LiveInterval &cur, unsigned Reg) {
|
||||
unsigned Preference = vrm_->getRegAllocPref(cur.reg);
|
||||
if ((Preference && Preference == Reg) || !cur.containsOneValue())
|
||||
return Reg;
|
||||
|
||||
VNInfo *vni = cur.begin()->valno;
|
||||
if ((vni->def == SlotIndex()) ||
|
||||
vni->isUnused() || !vni->isDefAccurate())
|
||||
// We cannot handle complicated live ranges. Simple linear stuff only.
|
||||
if (cur.ranges.size() != 1)
|
||||
return Reg;
|
||||
MachineInstr *CopyMI = li_->getInstructionFromIndex(vni->def);
|
||||
unsigned SrcReg, DstReg, SrcSubReg, DstSubReg, PhysReg;
|
||||
if (!CopyMI ||
|
||||
!tii_->isMoveInstr(*CopyMI, SrcReg, DstReg, SrcSubReg, DstSubReg))
|
||||
|
||||
const LiveRange &range = cur.ranges.front();
|
||||
|
||||
VNInfo *vni = range.valno;
|
||||
if (vni->isUnused())
|
||||
return Reg;
|
||||
PhysReg = SrcReg;
|
||||
if (TargetRegisterInfo::isVirtualRegister(SrcReg)) {
|
||||
if (!vrm_->isAssignedReg(SrcReg))
|
||||
|
||||
unsigned CandReg;
|
||||
{
|
||||
MachineInstr *CopyMI;
|
||||
unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
|
||||
if (vni->def != SlotIndex() && vni->isDefAccurate() &&
|
||||
(CopyMI = li_->getInstructionFromIndex(vni->def)) &&
|
||||
tii_->isMoveInstr(*CopyMI, SrcReg, DstReg, SrcSubReg, DstSubReg))
|
||||
// Defined by a copy, try to extend SrcReg forward
|
||||
CandReg = SrcReg;
|
||||
else if (TrivCoalesceEnds &&
|
||||
(CopyMI =
|
||||
li_->getInstructionFromIndex(range.end.getBaseIndex())) &&
|
||||
tii_->isMoveInstr(*CopyMI, SrcReg, DstReg, SrcSubReg, DstSubReg) &&
|
||||
cur.reg == SrcReg)
|
||||
// Only used by a copy, try to extend DstReg backwards
|
||||
CandReg = DstReg;
|
||||
else
|
||||
return Reg;
|
||||
PhysReg = vrm_->getPhys(SrcReg);
|
||||
}
|
||||
if (Reg == PhysReg)
|
||||
|
||||
if (TargetRegisterInfo::isVirtualRegister(CandReg)) {
|
||||
if (!vrm_->isAssignedReg(CandReg))
|
||||
return Reg;
|
||||
CandReg = vrm_->getPhys(CandReg);
|
||||
}
|
||||
if (Reg == CandReg)
|
||||
return Reg;
|
||||
|
||||
const TargetRegisterClass *RC = mri_->getRegClass(cur.reg);
|
||||
if (!RC->contains(PhysReg))
|
||||
if (!RC->contains(CandReg))
|
||||
return Reg;
|
||||
|
||||
if (li_->conflictsWithPhysReg(cur, *vrm_, CandReg))
|
||||
return Reg;
|
||||
|
||||
// Try to coalesce.
|
||||
if (!li_->conflictsWithPhysRegDef(cur, *vrm_, PhysReg)) {
|
||||
DEBUG(errs() << "Coalescing: " << cur << " -> " << tri_->getName(PhysReg)
|
||||
<< '\n');
|
||||
vrm_->clearVirt(cur.reg);
|
||||
vrm_->assignVirt2Phys(cur.reg, PhysReg);
|
||||
DEBUG(errs() << "Coalescing: " << cur << " -> " << tri_->getName(CandReg)
|
||||
<< '\n');
|
||||
vrm_->clearVirt(cur.reg);
|
||||
vrm_->assignVirt2Phys(cur.reg, CandReg);
|
||||
|
||||
// Remove unnecessary kills since a copy does not clobber the register.
|
||||
if (li_->hasInterval(SrcReg)) {
|
||||
LiveInterval &SrcLI = li_->getInterval(SrcReg);
|
||||
for (MachineRegisterInfo::use_iterator I = mri_->use_begin(cur.reg),
|
||||
E = mri_->use_end(); I != E; ++I) {
|
||||
MachineOperand &O = I.getOperand();
|
||||
if (!O.isKill())
|
||||
continue;
|
||||
MachineInstr *MI = &*I;
|
||||
if (SrcLI.liveAt(li_->getInstructionIndex(MI).getDefIndex()))
|
||||
O.setIsKill(false);
|
||||
}
|
||||
}
|
||||
|
||||
++NumCoalesce;
|
||||
return PhysReg;
|
||||
}
|
||||
|
||||
return Reg;
|
||||
++NumCoalesce;
|
||||
return CandReg;
|
||||
}
|
||||
|
||||
bool RALinScan::runOnMachineFunction(MachineFunction &fn) {
|
||||
|
Loading…
Reference in New Issue
Block a user