Commit 2a7fcbb4 by Jim Stichnoth

Subzero: Use std::vector<> instead of std::list for live range segments.

This generally uses less memory and fewer allocations. Also removes the commented-out alternative implementation using std::set<>, which would almost certainly never be a good idea here. BUG= none R=jvoung@chromium.org Review URL: https://codereview.chromium.org/734053006
parent 4828be2e
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include <limits> #include <limits>
#include <list> #include <list>
#include <map> #include <map>
#include <set>
#include <string> #include <string>
#include <vector> #include <vector>
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
......
...@@ -33,37 +33,6 @@ bool operator==(const RegWeight &A, const RegWeight &B) { ...@@ -33,37 +33,6 @@ bool operator==(const RegWeight &A, const RegWeight &B) {
} }
void LiveRange::addSegment(InstNumberT Start, InstNumberT End) { void LiveRange::addSegment(InstNumberT Start, InstNumberT 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()) { if (Range.empty()) {
Range.push_back(RangeElementType(Start, End)); Range.push_back(RangeElementType(Start, End));
return; return;
...@@ -71,7 +40,10 @@ void LiveRange::addSegment(InstNumberT Start, InstNumberT End) { ...@@ -71,7 +40,10 @@ void LiveRange::addSegment(InstNumberT Start, InstNumberT End) {
// Special case for faking in-arg liveness. // Special case for faking in-arg liveness.
if (End < Range.front().first) { if (End < Range.front().first) {
assert(Start < 0); assert(Start < 0);
Range.push_front(RangeElementType(Start, End)); // This is inefficient with Range as a std::vector, but there are
// generally very few arguments compared to the total number of
// variables with non-empty live ranges.
Range.insert(Range.begin(), RangeElementType(Start, End));
return; return;
} }
InstNumberT CurrentEnd = Range.back().second; InstNumberT CurrentEnd = Range.back().second;
...@@ -82,7 +54,6 @@ void LiveRange::addSegment(InstNumberT Start, InstNumberT End) { ...@@ -82,7 +54,6 @@ void LiveRange::addSegment(InstNumberT Start, InstNumberT End) {
return; return;
} }
Range.push_back(RangeElementType(Start, End)); Range.push_back(RangeElementType(Start, End));
#endif
} }
// Returns true if this live range ends before Other's live range // Returns true if this live range ends before Other's live range
......
...@@ -326,6 +326,13 @@ bool operator==(const RegWeight &A, const RegWeight &B); ...@@ -326,6 +326,13 @@ bool operator==(const RegWeight &A, const RegWeight &B);
class LiveRange { class LiveRange {
public: public:
LiveRange() : Weight(0) {} LiveRange() : Weight(0) {}
// Special constructor for building a kill set. The advantage is
// that we can reserve the right amount of space in advance.
LiveRange(const std::vector<InstNumberT> &Kills) : Weight(0) {
Range.reserve(Kills.size());
for (InstNumberT I : Kills)
addSegment(I, I);
}
LiveRange(const LiveRange &) = default; LiveRange(const LiveRange &) = default;
LiveRange &operator=(const LiveRange &) = default; LiveRange &operator=(const LiveRange &) = default;
...@@ -353,19 +360,9 @@ public: ...@@ -353,19 +360,9 @@ public:
void addWeight(uint32_t Delta) { Weight.addWeight(Delta); } void addWeight(uint32_t Delta) { Weight.addWeight(Delta); }
void dump(Ostream &Str) const; void dump(Ostream &Str) const;
// Defining USE_SET uses std::set to hold the segments instead of
// std::list. Using std::list will be slightly faster, but is more
// restrictive because new segments cannot be added in the middle.
//#define USE_SET
private: private:
typedef std::pair<InstNumberT, InstNumberT> RangeElementType; typedef std::pair<InstNumberT, InstNumberT> RangeElementType;
#ifdef USE_SET typedef std::vector<RangeElementType> RangeType;
typedef std::set<RangeElementType> RangeType;
#else
typedef std::list<RangeElementType> RangeType;
#endif
RangeType Range; RangeType Range;
RegWeight Weight; RegWeight Weight;
// TrimmedBegin is an optimization for the overlaps() computation. // TrimmedBegin is an optimization for the overlaps() computation.
......
...@@ -268,9 +268,7 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull) { ...@@ -268,9 +268,7 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull) {
VariablesMetadata *VMetadata = Func->getVMetadata(); VariablesMetadata *VMetadata = Func->getVMetadata();
// Build a LiveRange representing the Kills list. // Build a LiveRange representing the Kills list.
LiveRange KillsRange; LiveRange KillsRange(Kills);
for (InstNumberT I : Kills)
KillsRange.addSegment(I, I);
KillsRange.untrim(); KillsRange.untrim();
// RegUses[I] is the number of live ranges (variables) that register // RegUses[I] is the number of live ranges (variables) that register
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment