aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/llvm/CodeGen/LiveIntervalAnalysis.h6
-rw-r--r--lib/CodeGen/LiveIntervalAnalysis.cpp54
-rw-r--r--lib/CodeGen/RegAllocLinearScan.cpp92
-rw-r--r--test/CodeGen/X86/2009-01-12-CoalescerBug.ll2
-rw-r--r--test/CodeGen/X86/twoaddr-coalesce.ll2
5 files changed, 103 insertions, 53 deletions
diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h
index 7a02d0f..65f36e7 100644
--- a/include/llvm/CodeGen/LiveIntervalAnalysis.h
+++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h
@@ -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,
diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp
index 35337ef..0945634 100644
--- a/lib/CodeGen/LiveIntervalAnalysis.cpp
+++ b/lib/CodeGen/LiveIntervalAnalysis.cpp
@@ -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,
diff --git a/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp
index 4ff5129..79bde16 100644
--- a/lib/CodeGen/RegAllocLinearScan.cpp
+++ b/lib/CodeGen/RegAllocLinearScan.cpp
@@ -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;
+ }
+
+ if (TargetRegisterInfo::isVirtualRegister(CandReg)) {
+ if (!vrm_->isAssignedReg(CandReg))
return Reg;
- PhysReg = vrm_->getPhys(SrcReg);
+ CandReg = vrm_->getPhys(CandReg);
}
- if (Reg == PhysReg)
+ 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) {
diff --git a/test/CodeGen/X86/2009-01-12-CoalescerBug.ll b/test/CodeGen/X86/2009-01-12-CoalescerBug.ll
index 27a7113..8e41e5a 100644
--- a/test/CodeGen/X86/2009-01-12-CoalescerBug.ll
+++ b/test/CodeGen/X86/2009-01-12-CoalescerBug.ll
@@ -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 }
diff --git a/test/CodeGen/X86/twoaddr-coalesce.ll b/test/CodeGen/X86/twoaddr-coalesce.ll
index d0e13f6..4c37225 100644
--- a/test/CodeGen/X86/twoaddr-coalesce.ll
+++ b/test/CodeGen/X86/twoaddr-coalesce.ll
@@ -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]