aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/LiveInterval.cpp189
-rw-r--r--lib/CodeGen/LiveIntervalAnalysis.cpp215
2 files changed, 249 insertions, 155 deletions
diff --git a/lib/CodeGen/LiveInterval.cpp b/lib/CodeGen/LiveInterval.cpp
index 7f16b31823..8be9677929 100644
--- a/lib/CodeGen/LiveInterval.cpp
+++ b/lib/CodeGen/LiveInterval.cpp
@@ -101,101 +101,6 @@ bool LiveInterval::overlapsFrom(const LiveInterval& other,
return false;
}
-/// NontrivialOverlap - Check to see if the two live ranges specified by i and j
-/// overlap. If so, check to see if they have value numbers that are not
-/// iIdx/jIdx respectively. If both conditions are true, return true.
-static inline bool NontrivialOverlap(const LiveRange &I, const LiveRange &J,
- unsigned iIdx, unsigned jIdx) {
- if (I.start == J.start) {
- // If this is not the allowed value merge, we cannot join.
- if (I.ValId != iIdx || J.ValId != jIdx)
- return true;
- } else if (I.start < J.start) {
- if (I.end > J.start && (I.ValId != iIdx || J.ValId != jIdx)) {
- return true;
- }
- } else {
- if (J.end > I.start && (I.ValId != iIdx || J.ValId != jIdx))
- return true;
- }
-
- return false;
-}
-
-/// joinable - Two intervals are joinable if the either don't overlap at all
-/// or if the destination of the copy is a single assignment value, and it
-/// only overlaps with one value in the source interval.
-bool LiveInterval::joinable(const LiveInterval &other, unsigned CopyIdx) const {
- const LiveRange *SourceLR = other.getLiveRangeContaining(CopyIdx-1);
- const LiveRange *DestLR = getLiveRangeContaining(CopyIdx);
- assert(SourceLR && DestLR && "Not joining due to a copy?");
- unsigned OtherValIdx = SourceLR->ValId;
- unsigned ThisValIdx = DestLR->ValId;
-
- Ranges::const_iterator i = ranges.begin();
- Ranges::const_iterator ie = ranges.end();
- Ranges::const_iterator j = other.ranges.begin();
- Ranges::const_iterator je = other.ranges.end();
-
- if (i->start < j->start) {
- i = std::upper_bound(i, ie, j->start);
- if (i != ranges.begin()) --i;
- } else if (j->start < i->start) {
- j = std::upper_bound(j, je, i->start);
- if (j != other.ranges.begin()) --j;
- }
-
- while (i != ie && j != je) {
- if (NontrivialOverlap(*i, *j, ThisValIdx, OtherValIdx))
- return false;
-
- if (i->end < j->end)
- ++i;
- else
- ++j;
- }
-
- return true;
-}
-
-/// getOverlapingRanges - Given another live interval which is defined as a
-/// copy from this one, return a list of all of the live ranges where the
-/// two overlap and have different value numbers.
-void LiveInterval::getOverlapingRanges(const LiveInterval &other,
- unsigned CopyIdx,
- std::vector<LiveRange*> &Ranges) {
- const LiveRange *SourceLR = getLiveRangeContaining(CopyIdx-1);
- const LiveRange *DestLR = other.getLiveRangeContaining(CopyIdx);
- assert(SourceLR && DestLR && "Not joining due to a copy?");
- unsigned OtherValIdx = SourceLR->ValId;
- unsigned ThisValIdx = DestLR->ValId;
-
- Ranges::iterator i = ranges.begin();
- Ranges::iterator ie = ranges.end();
- Ranges::const_iterator j = other.ranges.begin();
- Ranges::const_iterator je = other.ranges.end();
-
- if (i->start < j->start) {
- i = std::upper_bound(i, ie, j->start);
- if (i != ranges.begin()) --i;
- } else if (j->start < i->start) {
- j = std::upper_bound(j, je, i->start);
- if (j != other.ranges.begin()) --j;
- }
-
- while (i != ie && j != je) {
- if (NontrivialOverlap(*i, *j, ThisValIdx, OtherValIdx))
- Ranges.push_back(&*i);
-
- if (i->end < j->end)
- ++i;
- else
- ++j;
- }
-}
-
-
-
/// extendIntervalEndTo - This method is used when we want to extend the range
/// specified by I to end at the specified endpoint. To do this, we should
/// merge and eliminate all ranges that this will overlap with. The iterator is
@@ -361,7 +266,7 @@ LiveInterval::FindLiveRangeContaining(unsigned Idx) const {
LiveInterval::iterator
LiveInterval::FindLiveRangeContaining(unsigned Idx) {
iterator It = std::upper_bound(begin(), end(), Idx);
- if (It != ranges.begin()) {
+ if (It != begin()) {
--It;
if (It->contains(Idx))
return It;
@@ -370,10 +275,13 @@ LiveInterval::FindLiveRangeContaining(unsigned Idx) {
return end();
}
-/// join - Join two live intervals (this, and other) together. This operation
-/// is the result of a copy instruction in the source program, that occurs at
-/// index 'CopyIdx' that copies from 'Other' to 'this'.
-void LiveInterval::join(LiveInterval &Other, unsigned CopyIdx) {
+/// join - Join two live intervals (this, and other) together. This applies
+/// mappings to the value numbers in the LHS/RHS intervals as specified. If
+/// the intervals are not joinable, this aborts.
+void LiveInterval::join(LiveInterval &Other, int *LHSValNoAssignments,
+ int *RHSValNoAssignments,
+ SmallVector<unsigned, 16> &NewInstDefiningValue) {
+
// Try to do the least amount of work possible. In particular, if there are
// more liverange chunks in the other set than there are in the 'this' set,
// swap sets to merge the fewest chunks in possible.
@@ -385,39 +293,61 @@ void LiveInterval::join(LiveInterval &Other, unsigned CopyIdx) {
MRegisterInfo::isVirtualRegister(reg)) ||
MRegisterInfo::isPhysicalRegister(Other.reg)) {
swap(Other);
- std::swap(ThisOffs, OtherOffs);
+ std::swap(LHSValNoAssignments, RHSValNoAssignments);
+ }
+
+ // Determine if any of our live range values are mapped. This is uncommon, so
+ // we want to avoid the interval scan if not.
+ bool MustMapCurValNos = false;
+ for (unsigned i = 0, e = getNumValNums(); i != e; ++i) {
+ if (InstDefiningValue[i] == ~2U) continue; // tombstone value #
+ if (i != (unsigned)LHSValNoAssignments[i]) {
+ MustMapCurValNos = true;
+ break;
+ }
+ }
+
+ // If we have to apply a mapping to our base interval assignment, rewrite it
+ // now.
+ if (MustMapCurValNos) {
+ // Map the first live range.
+ iterator OutIt = begin();
+ OutIt->ValId = LHSValNoAssignments[OutIt->ValId];
+ ++OutIt;
+ for (iterator I = OutIt, E = end(); I != E; ++I) {
+ OutIt->ValId = LHSValNoAssignments[I->ValId];
+
+ // If this live range has the same value # as its immediate predecessor,
+ // and if they are neighbors, remove one LiveRange. This happens when we
+ // have [0,3:0)[4,7:1) and map 0/1 onto the same value #.
+ if (OutIt->ValId == (OutIt-1)->ValId && (OutIt-1)->end == OutIt->start) {
+ (OutIt-1)->end = OutIt->end;
+ } else {
+ if (I != OutIt) {
+ OutIt->start = I->start;
+ OutIt->end = I->end;
+ }
+
+ // Didn't merge, on to the next one.
+ ++OutIt;
+ }
+ }
+
+ // If we merge some live ranges, chop off the end.
+ ranges.erase(OutIt, end());
}
- const LiveRange *SourceLR = Other.getLiveRangeContaining(CopyIdx-OtherOffs);
- const LiveRange *DestLR = getLiveRangeContaining(CopyIdx-ThisOffs);
- assert(SourceLR && DestLR && "Not joining due to a copy?");
- unsigned MergedSrcValIdx = SourceLR->ValId;
- unsigned MergedDstValIdx = DestLR->ValId;
-
- // Join the ranges of other into the ranges of this interval.
- std::map<unsigned, unsigned> Dst2SrcIdxMap;
+ // Okay, now insert the RHS live ranges into the LHS.
iterator InsertPos = begin();
for (iterator I = Other.begin(), E = Other.end(); I != E; ++I) {
// Map the ValId in the other live range to the current live range.
- if (I->ValId == MergedSrcValIdx)
- I->ValId = MergedDstValIdx;
- else {
- unsigned &NV = Dst2SrcIdxMap[I->ValId];
- if (NV == 0) NV = getNextValue(Other.getInstForValNum(I->ValId));
- I->ValId = NV;
- }
-
+ I->ValId = RHSValNoAssignments[I->ValId];
InsertPos = addRangeFrom(*I, InsertPos);
}
-
- // Update the value number information for the value number defined by the
- // copy. The copy is about to be removed, so ensure that the value is defined
- // by whatever the other value is defined by.
- if (InstDefiningValue[MergedDstValIdx] == CopyIdx) {
- InstDefiningValue[MergedDstValIdx] =
- Other.InstDefiningValue[MergedSrcValIdx];
- }
-
+
+ InstDefiningValue.clear();
+ InstDefiningValue.append(NewInstDefiningValue.begin(),
+ NewInstDefiningValue.end());
weight += Other.weight;
}
@@ -511,10 +441,9 @@ void LiveInterval::MergeValueNumberInto(unsigned V1, unsigned V2) {
// Now that V1 is dead, remove it. If it is the largest value number, just
// nuke it (and any other deleted values neighboring it), otherwise mark it as
// ~1U so it can be nuked later.
- if (V1 == NumValues-1) {
+ if (V1 == getNumValNums()-1) {
do {
InstDefiningValue.pop_back();
- --NumValues;
} while (InstDefiningValue.back() == ~1U);
} else {
InstDefiningValue[V1] = ~1U;
@@ -548,9 +477,9 @@ void LiveInterval::print(std::ostream &OS, const MRegisterInfo *MRI) const {
}
// Print value number info.
- if (NumValues) {
+ if (getNumValNums()) {
OS << " ";
- for (unsigned i = 0; i != NumValues; ++i) {
+ for (unsigned i = 0; i != getNumValNums(); ++i) {
if (i) OS << " ";
OS << i << "@";
if (InstDefiningValue[i] == ~0U) {
diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp
index 4f34881cf0..a26feb3023 100644
--- a/lib/CodeGen/LiveIntervalAnalysis.cpp
+++ b/lib/CodeGen/LiveIntervalAnalysis.cpp
@@ -629,8 +629,9 @@ void LiveIntervals::computeIntervals() {
/// This returns true if an interval was modified.
///
bool LiveIntervals::AdjustCopiesBackFrom(LiveInterval &IntA, LiveInterval &IntB,
- MachineInstr *CopyMI,
- unsigned CopyIdx) {
+ MachineInstr *CopyMI) {
+ unsigned CopyIdx = getDefIndex(getInstructionIndex(CopyMI));
+
// BValNo is a value number in B that is defined by a copy from A. 'B3' in
// the example above.
LiveInterval::iterator BLR = IntB.FindLiveRangeContaining(CopyIdx);
@@ -768,34 +769,22 @@ bool LiveIntervals::JoinCopy(MachineInstr *CopyMI,
std::cerr << " and "; DestInt.print(std::cerr, mri_);
std::cerr << ": ");
- // 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.
+ // Okay, attempt to join these two intervals. On failure, this returns false.
+ // Otherwise, if one of the intervals being joined is a physreg, this method
+ // always canonicalizes DestInt to be it. The output "SrcInt" will not have
+ // been modified, so we can use this information below to update aliases.
+ if (!JoinIntervals(DestInt, SrcInt)) {
+ // Coallescing failed.
+
+ // If we can eliminate the copy without merging the live ranges, do so now.
+ if (AdjustCopiesBackFrom(SrcInt, DestInt, CopyMI))
+ return true;
- bool Joinable = SrcInt.containsOneValue() && DestInt.containsOneValue();
-
- unsigned MIDefIdx = getDefIndex(getInstructionIndex(CopyMI));
-
- // If the intervals think that this is joinable, do so now.
- if (!Joinable && DestInt.joinable(SrcInt, MIDefIdx))
- Joinable = true;
-
- // If DestInt is actually a copy from SrcInt (which we know) that is used
- // to define another value of SrcInt, we can change the other range of
- // SrcInt to be the value of the range that defines DestInt, simplying the
- // interval an promoting coallescing.
- if (!Joinable && AdjustCopiesBackFrom(SrcInt, DestInt, CopyMI, MIDefIdx))
- return true;
-
- if (!Joinable) {
+ // Otherwise, we are unable to join the intervals.
DEBUG(std::cerr << "Interference!\n");
return false;
}
- // Okay, we can join these two intervals. If one of the intervals being
- // joined is a physreg, this method always canonicalizes DestInt to be it.
- // The output "SrcInt" will not have been modified.
- DestInt.join(SrcInt, MIDefIdx);
-
bool Swapped = SrcReg == DestInt.reg;
if (Swapped)
std::swap(SrcReg, DstReg);
@@ -823,6 +812,182 @@ bool LiveIntervals::JoinCopy(MachineInstr *CopyMI,
return true;
}
+/// ComputeUltimateVN - Assuming we are going to join two live intervals,
+/// compute what the resultant value numbers for each value in the input two
+/// ranges will be. This is complicated by copies between the two which can
+/// and will commonly cause multiple value numbers to be merged into one.
+///
+/// VN is the value number that we're trying to resolve. InstDefiningValue
+/// keeps track of the new InstDefiningValue assignment for the result
+/// LiveInterval. ThisFromOther/OtherFromThis are sets that keep track of
+/// whether a value in this or other is a copy from the opposite set.
+/// ThisValNoAssignments/OtherValNoAssignments keep track of value #'s that have
+/// already been assigned.
+///
+/// ThisFromOther[x] - If x is defined as a copy from the other interval, this
+/// contains the value number the copy is from.
+///
+static unsigned ComputeUltimateVN(unsigned VN,
+ SmallVector<unsigned, 16> &InstDefiningValue,
+ SmallVector<int, 16> &ThisFromOther,
+ SmallVector<int, 16> &OtherFromThis,
+ SmallVector<int, 16> &ThisValNoAssignments,
+ SmallVector<int, 16> &OtherValNoAssignments,
+ LiveInterval &ThisLI, LiveInterval &OtherLI) {
+ // If the VN has already been computed, just return it.
+ if (ThisValNoAssignments[VN] >= 0)
+ return ThisValNoAssignments[VN];
+ assert(ThisValNoAssignments[VN] != -2 && "FIXME: Cyclic case, handle it!");
+
+ // If this val is not a copy from the other val, then it must be a new value
+ // number in the destination.
+ int OtherValNo = ThisFromOther[VN];
+ if (OtherValNo == -1) {
+ InstDefiningValue.push_back(ThisLI.getInstForValNum(VN));
+ return ThisValNoAssignments[VN] = InstDefiningValue.size()-1;
+ }
+
+ // Otherwise, this *is* a copy from the RHS. Mark this value number as
+ // currently being computed, then ask what the ultimate value # of the other
+ // value is.
+ ThisValNoAssignments[VN] = -2;
+ unsigned UltimateVN =
+ ComputeUltimateVN(OtherValNo, InstDefiningValue,
+ OtherFromThis, ThisFromOther,
+ OtherValNoAssignments, ThisValNoAssignments,
+ OtherLI, ThisLI);
+ return ThisValNoAssignments[VN] = UltimateVN;
+}
+
+
+/// JoinIntervals - Attempt to join these two intervals. On failure, this
+/// returns false. Otherwise, if one of the intervals being joined is a
+/// 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 LiveIntervals::JoinIntervals(LiveInterval &LHS, LiveInterval &RHS) {
+ // Loop over the value numbers of the LHS, seeing if any are defined from the
+ // RHS.
+ SmallVector<int, 16> LHSValsDefinedFromRHS;
+ LHSValsDefinedFromRHS.resize(LHS.getNumValNums(), -1);
+ for (unsigned VN = 0, e = LHS.getNumValNums(); VN != e; ++VN) {
+ unsigned ValInst = LHS.getInstForValNum(VN);
+ if (ValInst == ~0U || ValInst == ~1U)
+ continue;
+
+ // If the instruction defining the LHS's value is a copy.
+ MachineInstr *ValInstMI = getInstructionFromIndex(ValInst);
+
+ // If the value number is not defined by a copy instruction, ignore it.
+ unsigned SrcReg, DstReg;
+ if (!tii_->isMoveInstr(*ValInstMI, SrcReg, DstReg))
+ continue;
+
+ // DstReg is known to be a register in the LHS interval. If the src is from
+ // the RHS interval, we can use its value #.
+ if (rep(SrcReg) != RHS.reg)
+ continue;
+
+ // Figure out the value # from the RHS.
+ LHSValsDefinedFromRHS[VN] = RHS.getLiveRangeContaining(ValInst-1)->ValId;
+ }
+
+ // Loop over the value numbers of the RHS, seeing if any are defined from the
+ // LHS.
+ SmallVector<int, 16> RHSValsDefinedFromLHS;
+ RHSValsDefinedFromLHS.resize(RHS.getNumValNums(), -1);
+ for (unsigned VN = 0, e = RHS.getNumValNums(); VN != e; ++VN) {
+ unsigned ValInst = RHS.getInstForValNum(VN);
+ if (ValInst == ~0U || ValInst == ~1U)
+ continue;
+
+ // If the instruction defining the RHS's value is a copy.
+ MachineInstr *ValInstMI = getInstructionFromIndex(ValInst);
+
+ // If the value number is not defined by a copy instruction, ignore it.
+ unsigned SrcReg, DstReg;
+ if (!tii_->isMoveInstr(*ValInstMI, SrcReg, DstReg))
+ continue;
+
+ // DstReg is known to be a register in the RHS interval. If the src is from
+ // the LHS interval, we can use its value #.
+ if (rep(SrcReg) != LHS.reg)
+ continue;
+
+ // Figure out the value # from the LHS.
+ RHSValsDefinedFromLHS[VN] = LHS.getLiveRangeContaining(ValInst-1)->ValId;
+ }
+
+ // Now that we know the value mapping, compute the final value assignment,
+ // assuming that the live ranges can be coallesced.
+ SmallVector<int, 16> LHSValNoAssignments;
+ SmallVector<int, 16> RHSValNoAssignments;
+ SmallVector<unsigned, 16> InstDefiningValue;
+ LHSValNoAssignments.resize(LHS.getNumValNums(), -1);
+ RHSValNoAssignments.resize(RHS.getNumValNums(), -1);
+
+ // Compute ultimate value numbers for the LHS and RHS values.
+ for (unsigned VN = 0, e = LHS.getNumValNums(); VN != e; ++VN) {
+ if (LHS.getInstForValNum(VN) == ~2U) continue;
+ ComputeUltimateVN(VN, InstDefiningValue,
+ LHSValsDefinedFromRHS, RHSValsDefinedFromLHS,
+ LHSValNoAssignments, RHSValNoAssignments, LHS, RHS);
+ }
+ for (unsigned VN = 0, e = RHS.getNumValNums(); VN != e; ++VN) {
+ if (RHS.getInstForValNum(VN) == ~2U) continue;
+ ComputeUltimateVN(VN, InstDefiningValue,
+ RHSValsDefinedFromLHS, LHSValsDefinedFromRHS,
+ RHSValNoAssignments, LHSValNoAssignments, RHS, LHS);
+ }
+
+ // Armed with the mappings of LHS/RHS values to ultimate values, walk the
+ // interval lists to see if these intervals are coallescable.
+ LiveInterval::const_iterator I = LHS.begin();
+ LiveInterval::const_iterator IE = LHS.end();
+ LiveInterval::const_iterator J = RHS.begin();
+ LiveInterval::const_iterator JE = RHS.end();
+
+ // Skip ahead until the first place of potential sharing.
+ if (I->start < J->start) {
+ I = std::upper_bound(I, IE, J->start);
+ if (I != LHS.begin()) --I;
+ } else if (J->start < I->start) {
+ J = std::upper_bound(J, JE, I->start);
+ if (J != RHS.begin()) --J;
+ }
+
+ while (1) {
+ // Determine if these two live ranges overlap.
+ bool Overlaps;
+ if (I->start < J->start) {
+ Overlaps = I->end > J->start;
+ } else {
+ Overlaps = J->end > I->start;
+ }
+
+ // If so, check value # info to determine if they are really different.
+ if (Overlaps) {
+ // If the live range overlap will map to the same value number in the
+ // result liverange, we can still coallesce them. If not, we can't.
+ if (LHSValNoAssignments[I->ValId] != RHSValNoAssignments[J->ValId])
+ return false;
+ }
+
+ if (I->end < J->end) {
+ ++I;
+ if (I == IE) break;
+ } else {
+ ++J;
+ if (J == JE) break;
+ }
+ }
+
+ // If we get here, we know that we can coallesce the live ranges. Ask the
+ // intervals to coallesce themselves now.
+ LHS.join(RHS, &LHSValNoAssignments[0], &RHSValNoAssignments[0],
+ InstDefiningValue);
+ return true;
+}
namespace {