mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01: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 takes care of a few more cases that r90163 missed. llvm-svn: 90502
This commit is contained in:
parent
0f151e89ab
commit
7c5af26d12
@ -117,6 +117,12 @@ namespace llvm {
|
||||
bool conflictsWithPhysRegDef(const LiveInterval &li, VirtRegMap &vrm,
|
||||
unsigned reg);
|
||||
|
||||
/// conflictsWithPhysRegUse - 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.
|
||||
bool conflictsWithPhysRegUse(const LiveInterval &li, VirtRegMap &vrm,
|
||||
unsigned reg);
|
||||
|
||||
/// conflictsWithPhysRegRef - Similar to conflictsWithPhysRegRef except
|
||||
/// it can check use as well.
|
||||
bool conflictsWithPhysRegRef(LiveInterval &li, unsigned Reg,
|
||||
|
@ -157,19 +157,15 @@ bool LiveIntervals::conflictsWithPhysRegDef(const LiveInterval &li,
|
||||
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()) {
|
||||
index != end;
|
||||
index = index.getNextIndex()) {
|
||||
MachineInstr *MI = getInstructionFromIndex(index);
|
||||
if (!MI)
|
||||
continue; // skip deleted instructions
|
||||
|
||||
unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
|
||||
if (tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubReg, DstSubReg))
|
||||
if (SrcReg == li.reg || DstReg == li.reg)
|
||||
continue;
|
||||
for (unsigned i = 0; i != MI->getNumOperands(); ++i) {
|
||||
MachineOperand& mop = MI->getOperand(i);
|
||||
if (!mop.isReg())
|
||||
if (!mop.isReg() || mop.isUse())
|
||||
continue;
|
||||
unsigned PhysReg = mop.getReg();
|
||||
if (PhysReg == 0 || PhysReg == li.reg)
|
||||
@ -188,6 +184,50 @@ bool LiveIntervals::conflictsWithPhysRegDef(const LiveInterval &li,
|
||||
return false;
|
||||
}
|
||||
|
||||
/// conflictsWithPhysRegUse - 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.
|
||||
bool LiveIntervals::conflictsWithPhysRegUse(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
|
||||
|
||||
// Terminators are considered conflicts since reg may be used at the
|
||||
// destination.
|
||||
if (MI->getDesc().isTerminator())
|
||||
return true;
|
||||
|
||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||
MachineOperand& mop = MI->getOperand(i);
|
||||
if (!mop.isReg() || mop.isUndef())
|
||||
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)) {
|
||||
unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
|
||||
if (!tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubReg, DstSubReg) ||
|
||||
(SrcReg != li.reg && DstReg != li.reg))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// conflictsWithPhysRegRef - Similar to conflictsWithPhysRegRef except
|
||||
/// it can check use as well.
|
||||
bool LiveIntervals::conflictsWithPhysRegRef(LiveInterval &li,
|
||||
|
@ -390,66 +390,70 @@ 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())
|
||||
if (vni->isUnused())
|
||||
return Reg;
|
||||
MachineInstr *CopyMI = li_->getInstructionFromIndex(vni->def);
|
||||
unsigned SrcReg, DstReg, SrcSubReg, DstSubReg, PhysReg;
|
||||
if (!CopyMI ||
|
||||
!tii_->isMoveInstr(*CopyMI, SrcReg, DstReg, SrcSubReg, DstSubReg))
|
||||
return Reg;
|
||||
PhysReg = SrcReg;
|
||||
if (TargetRegisterInfo::isVirtualRegister(SrcReg)) {
|
||||
if (!vrm_->isAssignedReg(SrcReg))
|
||||
unsigned CandReg;
|
||||
bool forward; // extending physreg forward
|
||||
{
|
||||
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, forward = true;
|
||||
else if (cur.ranges.size()==1 &&
|
||||
(CopyMI =
|
||||
li_->getInstructionFromIndex(cur.begin()->end.getBaseIndex())) &&
|
||||
tii_->isMoveInstr(*CopyMI, SrcReg, DstReg, SrcSubReg, DstSubReg) &&
|
||||
cur.reg == SrcReg)
|
||||
// Only used by a copy, try to extend DstReg backwards
|
||||
CandReg = DstReg, forward = false;
|
||||
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;
|
||||
|
||||
// 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);
|
||||
|
||||
// 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;
|
||||
if (forward) {
|
||||
if (li_->conflictsWithPhysRegDef(cur, *vrm_, CandReg))
|
||||
return Reg;
|
||||
} else {
|
||||
if (li_->conflictsWithPhysRegUse(cur, *vrm_, CandReg))
|
||||
return Reg;
|
||||
}
|
||||
|
||||
return Reg;
|
||||
// Try to coalesce.
|
||||
DEBUG(errs() << "Coalescing: " << cur << " -> " << tri_->getName(CandReg)
|
||||
<< '\n');
|
||||
vrm_->clearVirt(cur.reg);
|
||||
vrm_->assignVirt2Phys(cur.reg, CandReg);
|
||||
|
||||
++NumCoalesce;
|
||||
return CandReg;
|
||||
}
|
||||
|
||||
bool RALinScan::runOnMachineFunction(MachineFunction &fn) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | grep movq | count 2
|
||||
; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | grep movq | count 1
|
||||
; PR3311
|
||||
|
||||
%struct.CUMULATIVE_ARGS = type { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 }
|
||||
|
@ -1,4 +1,4 @@
|
||||
; RUN: llc < %s -march=x86 | grep mov | count 5
|
||||
; RUN: llc < %s -march=x86 | grep mov | count 4
|
||||
; rdar://6523745
|
||||
|
||||
@"\01LC" = internal constant [4 x i8] c"%d\0A\00" ; <[4 x i8]*> [#uses=1]
|
||||
|
Loading…
Reference in New Issue
Block a user