aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/llvm/CodeGen/LiveIntervalAnalysis.h7
-rw-r--r--lib/CodeGen/LiveIntervalAnalysis.cpp52
-rw-r--r--lib/CodeGen/SimpleRegisterCoalescing.cpp52
-rw-r--r--test/CodeGen/X86/phys_subreg_coalesce.ll24
4 files changed, 115 insertions, 20 deletions
diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h
index 9dd5526..52ee885 100644
--- a/include/llvm/CodeGen/LiveIntervalAnalysis.h
+++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h
@@ -24,6 +24,7 @@
#include "llvm/CodeGen/LiveInterval.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Allocator.h"
#include <cmath>
@@ -256,6 +257,12 @@ namespace llvm {
bool conflictsWithPhysRegDef(const LiveInterval &li, VirtRegMap &vrm,
unsigned reg);
+ /// conflictsWithPhysRegRef - Similar to conflictsWithPhysRegRef except
+ /// it can check use as well.
+ bool conflictsWithPhysRegRef(LiveInterval &li, unsigned Reg,
+ bool CheckUse,
+ SmallPtrSet<MachineInstr*,32> &JoinedCopies);
+
/// findLiveInMBBs - Given a live range, if the value of the range
/// is live in any MBB returns true as well as the list of basic blocks
/// in which the value is live.
diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp
index 1900c1a..2259589 100644
--- a/lib/CodeGen/LiveIntervalAnalysis.cpp
+++ b/lib/CodeGen/LiveIntervalAnalysis.cpp
@@ -323,6 +323,47 @@ bool LiveIntervals::conflictsWithPhysRegDef(const LiveInterval &li,
return false;
}
+/// conflictsWithPhysRegRef - Similar to conflictsWithPhysRegRef except
+/// it can check use as well.
+bool LiveIntervals::conflictsWithPhysRegRef(LiveInterval &li,
+ unsigned Reg, bool CheckUse,
+ SmallPtrSet<MachineInstr*,32> &JoinedCopies) {
+ for (LiveInterval::Ranges::const_iterator
+ I = li.ranges.begin(), E = li.ranges.end(); I != E; ++I) {
+ for (unsigned index = getBaseIndex(I->start),
+ end = getBaseIndex(I->end-1) + InstrSlots::NUM; index != end;
+ index += InstrSlots::NUM) {
+ // Skip deleted instructions.
+ MachineInstr *MI = 0;
+ while (index != end) {
+ MI = getInstructionFromIndex(index);
+ if (MI)
+ break;
+ index += InstrSlots::NUM;
+ }
+ if (index == end) break;
+
+ if (JoinedCopies.count(MI))
+ continue;
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ MachineOperand& MO = MI->getOperand(i);
+ if (!MO.isReg())
+ continue;
+ if (MO.isUse() && !CheckUse)
+ continue;
+ unsigned PhysReg = MO.getReg();
+ if (PhysReg == 0 || TargetRegisterInfo::isVirtualRegister(PhysReg))
+ continue;
+ if (tri_->isSubRegister(Reg, PhysReg))
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+
void LiveIntervals::printRegName(unsigned reg) const {
if (TargetRegisterInfo::isPhysicalRegister(reg))
cerr << tri_->getName(reg);
@@ -794,10 +835,15 @@ unsigned LiveIntervals::getVNInfoSourceReg(const VNInfo *VNI) const {
if (!VNI->copy)
return 0;
- if (VNI->copy->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG)
- return VNI->copy->getOperand(1).getReg();
- if (VNI->copy->getOpcode() == TargetInstrInfo::INSERT_SUBREG)
+ if (VNI->copy->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) {
+ // If it's extracting out of a physical register, return the sub-register.
+ unsigned Reg = VNI->copy->getOperand(1).getReg();
+ if (TargetRegisterInfo::isPhysicalRegister(Reg))
+ Reg = tri_->getSubReg(Reg, VNI->copy->getOperand(2).getImm());
+ return Reg;
+ } else if (VNI->copy->getOpcode() == TargetInstrInfo::INSERT_SUBREG)
return VNI->copy->getOperand(2).getReg();
+
unsigned SrcReg, DstReg;
if (tii_->isMoveInstr(*VNI->copy, SrcReg, DstReg))
return SrcReg;
diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp
index cfc77ee..7f36ef5 100644
--- a/lib/CodeGen/SimpleRegisterCoalescing.cpp
+++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp
@@ -1276,8 +1276,8 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
// preference.
unsigned Length = li_->getApproximateInstructionCount(JoinVInt);
if (Length > Threshold &&
- (((float)std::distance(mri_->use_begin(JoinVReg),
- mri_->use_end()) / Length) < (1.0 / Threshold))) {
+ (((float)std::distance(mri_->use_begin(JoinVReg), mri_->use_end())
+ / Length) < (1.0 / Threshold))) {
JoinVInt.preference = JoinPReg;
++numAborts;
DOUT << "\tMay tie down a physical register, abort!\n";
@@ -1334,7 +1334,7 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
assert(TargetRegisterInfo::isVirtualRegister(SrcReg) &&
"LiveInterval::join didn't work right!");
- // If we're about to merge live ranges into a physical register live range,
+ // If we're about to merge live ranges into a physical register live interval,
// we have to update any aliased register's live ranges to indicate that they
// have clobbered values for this range.
if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
@@ -1712,8 +1712,9 @@ bool SimpleRegisterCoalescing::SimpleJoin(LiveInterval &LHS, LiveInterval &RHS){
/// physreg, this method always canonicalizes LHS to be it. The output
/// "RHS" will not have been modified, so we can use this information
/// below to update aliases.
-bool SimpleRegisterCoalescing::JoinIntervals(LiveInterval &LHS,
- LiveInterval &RHS, bool &Swapped) {
+bool
+SimpleRegisterCoalescing::JoinIntervals(LiveInterval &LHS, LiveInterval &RHS,
+ bool &Swapped) {
// Compute the final value assignment, assuming that the live ranges can be
// coalesced.
SmallVector<int, 16> LHSValNoAssignments;
@@ -1721,26 +1722,43 @@ bool SimpleRegisterCoalescing::JoinIntervals(LiveInterval &LHS,
DenseMap<VNInfo*, VNInfo*> LHSValsDefinedFromRHS;
DenseMap<VNInfo*, VNInfo*> RHSValsDefinedFromLHS;
SmallVector<VNInfo*, 16> NewVNInfo;
-
+
// If a live interval is a physical register, conservatively check if any
// of its sub-registers is overlapping the live interval of the virtual
// register. If so, do not coalesce.
if (TargetRegisterInfo::isPhysicalRegister(LHS.reg) &&
*tri_->getSubRegisters(LHS.reg)) {
- for (const unsigned* SR = tri_->getSubRegisters(LHS.reg); *SR; ++SR)
- if (li_->hasInterval(*SR) && RHS.overlaps(li_->getInterval(*SR))) {
- DOUT << "Interfere with sub-register ";
- DEBUG(li_->getInterval(*SR).print(DOUT, tri_));
+ // If it's coalescing a virtual register to a physical register, estimate
+ // its live interval length. This is the *cost* of scanning an entire live
+ // interval. If the cost is low, we'll do an exhaustive check instead.
+ if (RHS.containsOneValue() &&
+ li_->getApproximateInstructionCount(RHS) <= 10) {
+ // Perform a more exhaustive check for some common cases.
+ if (li_->conflictsWithPhysRegRef(RHS, LHS.reg, true, JoinedCopies))
return false;
- }
+ } else {
+ for (const unsigned* SR = tri_->getSubRegisters(LHS.reg); *SR; ++SR)
+ if (li_->hasInterval(*SR) && RHS.overlaps(li_->getInterval(*SR))) {
+ DOUT << "Interfere with sub-register ";
+ DEBUG(li_->getInterval(*SR).print(DOUT, tri_));
+ return false;
+ }
+ }
} else if (TargetRegisterInfo::isPhysicalRegister(RHS.reg) &&
*tri_->getSubRegisters(RHS.reg)) {
- for (const unsigned* SR = tri_->getSubRegisters(RHS.reg); *SR; ++SR)
- if (li_->hasInterval(*SR) && LHS.overlaps(li_->getInterval(*SR))) {
- DOUT << "Interfere with sub-register ";
- DEBUG(li_->getInterval(*SR).print(DOUT, tri_));
+ if (LHS.containsOneValue() &&
+ li_->getApproximateInstructionCount(LHS) <= 10) {
+ // Perform a more exhaustive check for some common cases.
+ if (li_->conflictsWithPhysRegRef(LHS, RHS.reg, false, JoinedCopies))
return false;
- }
+ } else {
+ for (const unsigned* SR = tri_->getSubRegisters(RHS.reg); *SR; ++SR)
+ if (li_->hasInterval(*SR) && LHS.overlaps(li_->getInterval(*SR))) {
+ DOUT << "Interfere with sub-register ";
+ DEBUG(li_->getInterval(*SR).print(DOUT, tri_));
+ return false;
+ }
+ }
}
// Compute ultimate value numbers for the LHS and RHS values.
@@ -1755,7 +1773,7 @@ bool SimpleRegisterCoalescing::JoinIntervals(LiveInterval &LHS,
VNInfo *RHSValNoInfo = NULL;
VNInfo *RHSValNoInfo0 = RHS.getValNumInfo(0);
unsigned RHSSrcReg = li_->getVNInfoSourceReg(RHSValNoInfo0);
- if ((RHSSrcReg == 0 || RHSSrcReg != LHS.reg)) {
+ if (RHSSrcReg == 0 || RHSSrcReg != LHS.reg) {
// If RHS is not defined as a copy from the LHS, we can use simpler and
// faster checks to see if the live ranges are coalescable. This joiner
// can't swap the LHS/RHS intervals though.
diff --git a/test/CodeGen/X86/phys_subreg_coalesce.ll b/test/CodeGen/X86/phys_subreg_coalesce.ll
new file mode 100644
index 0000000..789a4ba
--- /dev/null
+++ b/test/CodeGen/X86/phys_subreg_coalesce.ll
@@ -0,0 +1,24 @@
+; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin9 -mattr=+sse2 | not grep movl
+
+ %struct.dpoint = type { double, double }
+
+define %struct.dpoint @midpoint(i64 %p1.0, i64 %p2.0) nounwind readnone {
+entry:
+ %0 = trunc i64 %p1.0 to i32 ; <i32> [#uses=1]
+ %1 = sitofp i32 %0 to double ; <double> [#uses=1]
+ %2 = trunc i64 %p2.0 to i32 ; <i32> [#uses=1]
+ %3 = sitofp i32 %2 to double ; <double> [#uses=1]
+ %4 = add double %1, %3 ; <double> [#uses=1]
+ %5 = mul double %4, 5.000000e-01 ; <double> [#uses=1]
+ %6 = lshr i64 %p1.0, 32 ; <i64> [#uses=1]
+ %7 = trunc i64 %6 to i32 ; <i32> [#uses=1]
+ %8 = sitofp i32 %7 to double ; <double> [#uses=1]
+ %9 = lshr i64 %p2.0, 32 ; <i64> [#uses=1]
+ %10 = trunc i64 %9 to i32 ; <i32> [#uses=1]
+ %11 = sitofp i32 %10 to double ; <double> [#uses=1]
+ %12 = add double %8, %11 ; <double> [#uses=1]
+ %13 = mul double %12, 5.000000e-01 ; <double> [#uses=1]
+ %mrv3 = insertvalue %struct.dpoint undef, double %5, 0 ; <%struct.dpoint> [#uses=1]
+ %mrv4 = insertvalue %struct.dpoint %mrv3, double %13, 1 ; <%struct.dpoint> [#uses=1]
+ ret %struct.dpoint %mrv4
+}