[LiveIntervalAnalysis] Speed up creation of live ranges for physical registers

by using a segment set.

The patch addresses a compile-time performance regression in the LiveIntervals
analysis pass (see http://llvm.org/bugs/show_bug.cgi?id=18580). This regression
is especially critical when compiling long functions. Our analysis had shown
that the most of time is taken for generation of live intervals for physical
registers. Insertions in the middle of the array of live ranges cause quadratic
algorithmic complexity, which is apparently the main reason for the slow-down. 

Overview of changes:
- The patch introduces an additional std::set<Segment>* member in LiveRange for
  storing segments in the phase of initial creation. The set is used if this
  member is not NULL, otherwise everything works the old way. 
- The set of operations on LiveRange used during initial creation (i.e. used by
  createDeadDefs and extendToUses) have been reimplemented to use the segment
  set if it is available.
- After a live range is created the contents of the set are flushed to the
  segment vector, because the set is not as efficient as the vector for the
  later uses of the live range. After the flushing, the set is deleted and
  cannot be used again.
- The set is only for live ranges computed in
  LiveIntervalAnalysis::computeLiveInRegUnits() and getRegUnit() but not in
  computeVirtRegs(), because I did not bring any performance benefits to
  computeVirtRegs() and for some examples even brought a slow down.

Patch by Vaidas Gasiunas <vaidas.gasiunas@sap.com>

Differential Revision: http://reviews.llvm.org/D6013


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228421 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Quentin Colombet
2015-02-06 18:42:41 +00:00
parent b3189eac3f
commit 4c2a2ac196
4 changed files with 347 additions and 153 deletions

View File

@@ -27,6 +27,7 @@
#include "llvm/Support/Allocator.h"
#include <cassert>
#include <climits>
#include <set>
namespace llvm {
class CoalescerPair;
@@ -194,6 +195,12 @@ namespace llvm {
Segments segments; // the liveness segments
VNInfoList valnos; // value#'s
// The segment set is used temporarily to accelerate initial computation
// of live ranges of physical registers in computeRegUnitRange.
// After that the set is flushed to the segment vector and deleted.
typedef std::set<Segment> SegmentSet;
SegmentSet *segmentSet;
typedef Segments::iterator iterator;
iterator begin() { return segments.begin(); }
iterator end() { return segments.end(); }
@@ -211,12 +218,18 @@ namespace llvm {
const_vni_iterator vni_end() const { return valnos.end(); }
/// Constructs a new LiveRange object.
LiveRange() {
LiveRange(bool UseSegmentSet = false) : segmentSet(nullptr) {
if (UseSegmentSet)
segmentSet = new SegmentSet();
}
/// Constructs a new LiveRange object by copying segments and valnos from
/// another LiveRange.
LiveRange(const LiveRange &Other, BumpPtrAllocator &Allocator) {
LiveRange(const LiveRange &Other, BumpPtrAllocator &Allocator)
: segmentSet(nullptr) {
assert(Other.segmentSet == nullptr &&
"Copying of LiveRanges with active SegmentSets is not supported");
// Duplicate valnos.
for (const VNInfo *VNI : Other.valnos) {
createValueCopy(VNI, Allocator);
@@ -227,6 +240,8 @@ namespace llvm {
}
}
~LiveRange() { delete segmentSet; }
/// advanceTo - Advance the specified iterator to point to the Segment
/// containing the specified position, or end() if the position is past the
/// end of the range. If no Segment contains this position, but the
@@ -437,9 +452,7 @@ namespace llvm {
/// Add the specified Segment to this range, merging segments as
/// appropriate. This returns an iterator to the inserted segment (which
/// may have grown since it was inserted).
iterator addSegment(Segment S) {
return addSegmentFrom(S, segments.begin());
}
iterator addSegment(Segment S);
/// extendInBlock - If this range is live before Kill in the basic block
/// that starts at StartIdx, extend it to be live up to Kill, and return
@@ -540,6 +553,12 @@ namespace llvm {
return thisIndex < otherIndex;
}
/// Flush segment set into the regular segment vector.
/// The method is to be called after the live range
/// has been created, if use of the segment set was
/// activated in the constructor of the live range.
void flushSegmentSet();
void print(raw_ostream &OS) const;
void dump() const;
@@ -557,10 +576,8 @@ namespace llvm {
void append(const LiveRange::Segment S);
private:
iterator addSegmentFrom(Segment S, iterator From);
void extendSegmentEndTo(iterator I, SlotIndex NewEnd);
iterator extendSegmentStartTo(iterator I, SlotIndex NewStr);
friend class LiveRangeUpdater;
void addSegmentToSet(Segment S);
void markValNoForDeletion(VNInfo *V);
};