| Index: src/IceOperand.cpp
|
| diff --git a/src/IceOperand.cpp b/src/IceOperand.cpp
|
| index 56520d3ef273489968a898d47662f2a3927df3d3..cc542634044fd4652125f75a6d82f74038388748 100644
|
| --- a/src/IceOperand.cpp
|
| +++ b/src/IceOperand.cpp
|
| @@ -7,9 +7,8 @@
|
| //
|
| //===----------------------------------------------------------------------===//
|
| //
|
| -// This file implements the Operand class and its
|
| -// target-independent subclasses, primarily for the methods of the
|
| -// Variable class.
|
| +// This file implements the Operand class and its target-independent
|
| +// subclasses, primarily for the methods of the Variable class.
|
| //
|
| //===----------------------------------------------------------------------===//
|
|
|
| @@ -36,6 +35,103 @@ bool operator==(const RegWeight &A, const RegWeight &B) {
|
| return !(B < A) && !(A < B);
|
| }
|
|
|
| +void LiveRange::addSegment(int32_t Start, int32_t End) {
|
| +#ifdef USE_SET
|
| + RangeElementType Element(Start, End);
|
| + RangeType::iterator Next = Range.lower_bound(Element);
|
| + assert(Next == Range.upper_bound(Element)); // Element not already present
|
| +
|
| + // Beginning of code that merges contiguous segments. TODO: change
|
| + // "if(true)" to "if(false)" to see if this extra optimization code
|
| + // gives any performance gain, or is just destabilizing.
|
| + if (true) {
|
| + RangeType::iterator FirstDelete = Next;
|
| + RangeType::iterator Prev = Next;
|
| + bool hasPrev = (Next != Range.begin());
|
| + bool hasNext = (Next != Range.end());
|
| + if (hasPrev)
|
| + --Prev;
|
| + // See if Element and Next should be joined.
|
| + if (hasNext && End == Next->first) {
|
| + Element.second = Next->second;
|
| + ++Next;
|
| + }
|
| + // See if Prev and Element should be joined.
|
| + if (hasPrev && Prev->second == Start) {
|
| + Element.first = Prev->first;
|
| + FirstDelete = Prev;
|
| + }
|
| + Range.erase(FirstDelete, Next);
|
| + }
|
| + // End of code that merges contiguous segments.
|
| +
|
| + Range.insert(Next, Element);
|
| +#else
|
| + if (Range.empty()) {
|
| + Range.push_back(RangeElementType(Start, End));
|
| + return;
|
| + }
|
| + // Special case for faking in-arg liveness.
|
| + if (End < Range.front().first) {
|
| + assert(Start < 0);
|
| + Range.push_front(RangeElementType(Start, End));
|
| + return;
|
| + }
|
| + int32_t CurrentEnd = Range.back().second;
|
| + assert(Start >= CurrentEnd);
|
| + // Check for merge opportunity.
|
| + if (Start == CurrentEnd) {
|
| + Range.back().second = End;
|
| + return;
|
| + }
|
| + Range.push_back(RangeElementType(Start, End));
|
| +#endif
|
| +}
|
| +
|
| +// Returns true if this live range ends before Other's live range
|
| +// starts. This means that the highest instruction number in this
|
| +// live range is less than or equal to the lowest instruction number
|
| +// of the Other live range.
|
| +bool LiveRange::endsBefore(const LiveRange &Other) const {
|
| + // Neither range should be empty, but let's be graceful.
|
| + if (Range.empty() || Other.Range.empty())
|
| + return true;
|
| + int32_t MyEnd = (*Range.rbegin()).second;
|
| + int32_t OtherStart = (*Other.Range.begin()).first;
|
| + return MyEnd <= OtherStart;
|
| +}
|
| +
|
| +// Returns true if there is any overlap between the two live ranges.
|
| +bool LiveRange::overlaps(const LiveRange &Other) const {
|
| + // Do a two-finger walk through the two sorted lists of segments.
|
| + RangeType::const_iterator I1 = Range.begin(), I2 = Other.Range.begin();
|
| + RangeType::const_iterator E1 = Range.end(), E2 = Other.Range.end();
|
| + while (I1 != E1 && I2 != E2) {
|
| + if (I1->second <= I2->first) {
|
| + ++I1;
|
| + continue;
|
| + }
|
| + if (I2->second <= I1->first) {
|
| + ++I2;
|
| + continue;
|
| + }
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +// Returns true if the live range contains the given instruction
|
| +// number. This is only used for validating the live range
|
| +// calculation.
|
| +bool LiveRange::containsValue(int32_t Value) const {
|
| + for (RangeType::const_iterator I = Range.begin(), E = Range.end(); I != E;
|
| + ++I) {
|
| + if (I->first <= Value && Value <= I->second)
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| void Variable::setUse(const Inst *Inst, const CfgNode *Node) {
|
| if (DefNode == NULL)
|
| return;
|
| @@ -115,12 +211,12 @@ void Variable::dump(const Cfg *Func) const {
|
| }
|
| }
|
|
|
| -void ConstantRelocatable::emit(const Cfg *Func) const {
|
| - Ostream &Str = Func->getContext()->getStrEmit();
|
| +void ConstantRelocatable::emit(GlobalContext *Ctx) const {
|
| + Ostream &Str = Ctx->getStrEmit();
|
| if (SuppressMangling)
|
| Str << Name;
|
| else
|
| - Str << Func->getContext()->mangleName(Name);
|
| + Str << Ctx->mangleName(Name);
|
| if (Offset) {
|
| if (Offset > 0)
|
| Str << "+";
|
| @@ -128,13 +224,28 @@ void ConstantRelocatable::emit(const Cfg *Func) const {
|
| }
|
| }
|
|
|
| -void ConstantRelocatable::dump(const Cfg *Func) const {
|
| - Ostream &Str = Func->getContext()->getStrDump();
|
| +void ConstantRelocatable::dump(GlobalContext *Ctx) const {
|
| + Ostream &Str = Ctx->getStrDump();
|
| Str << "@" << Name;
|
| if (Offset)
|
| Str << "+" << Offset;
|
| }
|
|
|
| +void LiveRange::dump(Ostream &Str) const {
|
| + Str << "(weight=" << Weight << ") ";
|
| + for (RangeType::const_iterator I = Range.begin(), E = Range.end(); I != E;
|
| + ++I) {
|
| + if (I != Range.begin())
|
| + Str << ", ";
|
| + Str << "[" << (*I).first << ":" << (*I).second << ")";
|
| + }
|
| +}
|
| +
|
| +Ostream &operator<<(Ostream &Str, const LiveRange &L) {
|
| + L.dump(Str);
|
| + return Str;
|
| +}
|
| +
|
| Ostream &operator<<(Ostream &Str, const RegWeight &W) {
|
| if (W.getWeight() == RegWeight::Inf)
|
| Str << "Inf";
|
|
|