Commit 5ce0abb8 by Jim Stichnoth

Subzero: Register allocator performance improvements and simplifications.

This removes the redundancy between live ranges stored in the Variable and those stored in Liveness, by removing the Liveness copy. After liveness analysis, live ranges are constructed directly into the Variable. Also, the LiveRangeWrapper is removed and Variable * is directly used instead. The original thought behind LiveRangeWrapper was that it could be extended to include live range splitting. However, when/if live range splitting is implemented, it will probably involve creating a new variable with its own live range, and carrying around some extra bookkeeping until the split is committed, so such a wrapper probably won't be needed. BUG= none R=jvoung@chromium.org Review URL: https://codereview.chromium.org/656023002
parent 962befa4
...@@ -219,32 +219,21 @@ void Cfg::liveness(LivenessMode Mode) { ...@@ -219,32 +219,21 @@ void Cfg::liveness(LivenessMode Mode) {
// "r=arg1+arg2", both args may be assigned the same register. // "r=arg1+arg2", both args may be assigned the same register.
for (SizeT I = 0; I < Args.size(); ++I) { for (SizeT I = 0; I < Args.size(); ++I) {
Variable *Arg = Args[I]; Variable *Arg = Args[I];
if (!Live->getLiveRange(Arg).isEmpty()) { if (!Arg->getLiveRange().isEmpty()) {
// Add live range [-1,0) with weight 0. TODO: Here and below, // Add live range [-1,0) with weight 0. TODO: Here and below,
// use better symbolic constants along the lines of // use better symbolic constants along the lines of
// Inst::NumberDeleted and Inst::NumberSentinel instead of -1 // Inst::NumberDeleted and Inst::NumberSentinel instead of -1
// and 0. // and 0.
Live->addLiveRange(Arg, -1, 0, 0); Arg->addLiveRange(-1, 0, 0);
} }
// Do the same for i64 args that may have been lowered into i32 // Do the same for i64 args that may have been lowered into i32
// Lo and Hi components. // Lo and Hi components.
Variable *Lo = Arg->getLo(); Variable *Lo = Arg->getLo();
if (Lo && !Live->getLiveRange(Lo).isEmpty()) if (Lo && !Lo->getLiveRange().isEmpty())
Live->addLiveRange(Lo, -1, 0, 0); Lo->addLiveRange(-1, 0, 0);
Variable *Hi = Arg->getHi(); Variable *Hi = Arg->getHi();
if (Hi && !Live->getLiveRange(Hi).isEmpty()) if (Hi && !Hi->getLiveRange().isEmpty())
Live->addLiveRange(Hi, -1, 0, 0); Hi->addLiveRange(-1, 0, 0);
}
// Copy Liveness::LiveRanges into individual variables. TODO:
// Remove Variable::LiveRange and redirect to
// Liveness::LiveRanges. TODO: make sure Variable weights
// are applied properly.
SizeT NumVars = Variables.size();
for (SizeT i = 0; i < NumVars; ++i) {
Variable *Var = Variables[i];
Var->setLiveRange(Live->getLiveRange(Var));
if (Var->getWeight().isInf())
Var->setLiveRangeInfiniteWeight();
} }
} }
} }
......
...@@ -357,16 +357,6 @@ bool CfgNode::liveness(Liveness *Liveness) { ...@@ -357,16 +357,6 @@ bool CfgNode::liveness(Liveness *Liveness) {
return Changed; return Changed;
} }
#ifndef NDEBUG
namespace {
bool comparePair(const LiveBeginEndMapEntry &A, const LiveBeginEndMapEntry &B) {
return A.first == B.first;
}
} // end of anonymous namespace
#endif // NDEBUG
// Now that basic liveness is complete, remove dead instructions that // Now that basic liveness is complete, remove dead instructions that
// were tentatively marked as dead, and compute actual live ranges. // were tentatively marked as dead, and compute actual live ranges.
// It is assumed that within a single basic block, a live range begins // It is assumed that within a single basic block, a live range begins
...@@ -406,7 +396,7 @@ void CfgNode::livenessPostprocess(LivenessMode Mode, Liveness *Liveness) { ...@@ -406,7 +396,7 @@ void CfgNode::livenessPostprocess(LivenessMode Mode, Liveness *Liveness) {
for (SizeT Src = 0; Src < NumSrcs; ++Src) { for (SizeT Src = 0; Src < NumSrcs; ++Src) {
Variable *Var = llvm::cast<Variable>(I->getSrc(Src)); Variable *Var = llvm::cast<Variable>(I->getSrc(Src));
InstNumberT InstNumber = I->getNumber(); InstNumberT InstNumber = I->getNumber();
Liveness->addLiveRange(Var, InstNumber, InstNumber, 1); Var->addLiveRange(InstNumber, InstNumber, 1);
} }
} }
} }
...@@ -424,9 +414,15 @@ void CfgNode::livenessPostprocess(LivenessMode Mode, Liveness *Liveness) { ...@@ -424,9 +414,15 @@ void CfgNode::livenessPostprocess(LivenessMode Mode, Liveness *Liveness) {
std::sort(MapBegin.begin(), MapBegin.end()); std::sort(MapBegin.begin(), MapBegin.end());
std::sort(MapEnd.begin(), MapEnd.end()); std::sort(MapEnd.begin(), MapEnd.end());
// Verify there are no duplicates. // Verify there are no duplicates.
assert(std::adjacent_find(MapBegin.begin(), MapBegin.end(), comparePair) == struct ComparePair {
bool operator()(const LiveBeginEndMapEntry &A,
const LiveBeginEndMapEntry &B) {
return A.first == B.first;
}
};
assert(std::adjacent_find(MapBegin.begin(), MapBegin.end(), ComparePair()) ==
MapBegin.end()); MapBegin.end());
assert(std::adjacent_find(MapEnd.begin(), MapEnd.end(), comparePair) == assert(std::adjacent_find(MapEnd.begin(), MapEnd.end(), ComparePair()) ==
MapEnd.end()); MapEnd.end());
LivenessBV LiveInAndOut = LiveIn; LivenessBV LiveInAndOut = LiveIn;
...@@ -453,15 +449,15 @@ void CfgNode::livenessPostprocess(LivenessMode Mode, Liveness *Liveness) { ...@@ -453,15 +449,15 @@ void CfgNode::livenessPostprocess(LivenessMode Mode, Liveness *Liveness) {
Variable *Var = Liveness->getVariable(i, this); Variable *Var = Liveness->getVariable(i, this);
if (!Var->getIgnoreLiveness()) { if (!Var->getIgnoreLiveness()) {
if (LB > LE) { if (LB > LE) {
Liveness->addLiveRange(Var, FirstInstNum, LE, 1); Var->addLiveRange(FirstInstNum, LE, 1);
Liveness->addLiveRange(Var, LB, LastInstNum + 1, 1); Var->addLiveRange(LB, LastInstNum + 1, 1);
// Assert that Var is a global variable by checking that its // Assert that Var is a global variable by checking that its
// liveness index is less than the number of globals. This // liveness index is less than the number of globals. This
// ensures that the LiveInAndOut[] access is valid. // ensures that the LiveInAndOut[] access is valid.
assert(i < Liveness->getNumGlobalVars()); assert(i < Liveness->getNumGlobalVars());
LiveInAndOut[i] = false; LiveInAndOut[i] = false;
} else { } else {
Liveness->addLiveRange(Var, LB, LE, 1); Var->addLiveRange(LB, LE, 1);
} }
} }
if (i == i1) if (i == i1)
...@@ -473,7 +469,7 @@ void CfgNode::livenessPostprocess(LivenessMode Mode, Liveness *Liveness) { ...@@ -473,7 +469,7 @@ void CfgNode::livenessPostprocess(LivenessMode Mode, Liveness *Liveness) {
for (int i = LiveInAndOut.find_first(); i != -1; for (int i = LiveInAndOut.find_first(); i != -1;
i = LiveInAndOut.find_next(i)) { i = LiveInAndOut.find_next(i)) {
Variable *Var = Liveness->getVariable(i, this); Variable *Var = Liveness->getVariable(i, this);
Liveness->addLiveRange(Var, FirstInstNum, LastInstNum + 1, 1); Var->addLiveRange(FirstInstNum, LastInstNum + 1, 1);
} }
} }
......
...@@ -35,8 +35,6 @@ void Liveness::init() { ...@@ -35,8 +35,6 @@ void Liveness::init() {
VariablesMetadata *VMetadata = Func->getVMetadata(); VariablesMetadata *VMetadata = Func->getVMetadata();
Nodes.resize(NumNodes); Nodes.resize(NumNodes);
VarToLiveMap.resize(NumVars); VarToLiveMap.resize(NumVars);
if (Mode == Liveness_Intervals)
LiveRanges.resize(NumVars);
// Count the number of globals, and the number of locals for each // Count the number of globals, and the number of locals for each
// block. // block.
...@@ -98,16 +96,4 @@ Variable *Liveness::getVariable(SizeT LiveIndex, const CfgNode *Node) const { ...@@ -98,16 +96,4 @@ Variable *Liveness::getVariable(SizeT LiveIndex, const CfgNode *Node) const {
return Nodes[NodeIndex].LiveToVarMap[LiveIndex - NumGlobals]; return Nodes[NodeIndex].LiveToVarMap[LiveIndex - NumGlobals];
} }
void Liveness::addLiveRange(Variable *Var, InstNumberT Start, InstNumberT End,
uint32_t WeightDelta) {
LiveRange &LiveRange = LiveRanges[Var->getIndex()];
assert(WeightDelta != RegWeight::Inf);
LiveRange.addSegment(Start, End);
LiveRange.addWeight(WeightDelta);
}
LiveRange &Liveness::getLiveRange(Variable *Var) {
return LiveRanges[Var->getIndex()];
}
} // end of namespace Ice } // end of namespace Ice
...@@ -52,6 +52,9 @@ private: ...@@ -52,6 +52,9 @@ private:
}; };
class Liveness { class Liveness {
Liveness(const Liveness &) = delete;
Liveness &operator=(const Liveness &) = delete;
public: public:
Liveness(Cfg *Func, LivenessMode Mode) Liveness(Cfg *Func, LivenessMode Mode)
: Func(Func), Mode(Mode), NumGlobals(0) {} : Func(Func), Mode(Mode), NumGlobals(0) {}
...@@ -76,9 +79,6 @@ public: ...@@ -76,9 +79,6 @@ public:
LiveBeginEndMap *getLiveEnd(const CfgNode *Node) { LiveBeginEndMap *getLiveEnd(const CfgNode *Node) {
return &Nodes[Node->getIndex()].LiveEnd; return &Nodes[Node->getIndex()].LiveEnd;
} }
LiveRange &getLiveRange(Variable *Var);
void addLiveRange(Variable *Var, InstNumberT Start, InstNumberT End,
uint32_t WeightDelta);
private: private:
Cfg *Func; Cfg *Func;
...@@ -92,10 +92,6 @@ private: ...@@ -92,10 +92,6 @@ private:
// LiveToVarMap is analogous to LivenessNode::LiveToVarMap, but for // LiveToVarMap is analogous to LivenessNode::LiveToVarMap, but for
// non-local variables. // non-local variables.
std::vector<Variable *> LiveToVarMap; std::vector<Variable *> LiveToVarMap;
// LiveRanges maps a Variable::Number to its live range.
std::vector<LiveRange> LiveRanges;
Liveness(const Liveness &) = delete;
Liveness &operator=(const Liveness &) = delete;
}; };
} // end of namespace Ice } // end of namespace Ice
......
...@@ -412,6 +412,7 @@ public: ...@@ -412,6 +412,7 @@ public:
void setWeight(uint32_t NewWeight) { Weight = NewWeight; } void setWeight(uint32_t NewWeight) { Weight = NewWeight; }
void setWeightInfinite() { Weight = RegWeight::Inf; } void setWeightInfinite() { Weight = RegWeight::Inf; }
LiveRange &getLiveRange() { return Live; }
const LiveRange &getLiveRange() const { return Live; } const LiveRange &getLiveRange() const { return Live; }
void setLiveRange(const LiveRange &Range) { Live = Range; } void setLiveRange(const LiveRange &Range) { Live = Range; }
void resetLiveRange() { Live.reset(); } void resetLiveRange() { Live.reset(); }
...@@ -426,6 +427,17 @@ public: ...@@ -426,6 +427,17 @@ public:
void setLiveRangeInfiniteWeight() { Live.setWeight(RegWeight::Inf); } void setLiveRangeInfiniteWeight() { Live.setWeight(RegWeight::Inf); }
void trimLiveRange(InstNumberT Start) { Live.trim(Start); } void trimLiveRange(InstNumberT Start) { Live.trim(Start); }
void untrimLiveRange() { Live.untrim(); } void untrimLiveRange() { Live.untrim(); }
bool rangeEndsBefore(const Variable *Other) const {
return Live.endsBefore(Other->Live);
}
bool rangeOverlaps(const Variable *Other) const {
const bool UseTrimmed = true;
return Live.overlaps(Other->Live, UseTrimmed);
}
bool rangeOverlapsStart(const Variable *Other) const {
const bool UseTrimmed = true;
return Live.overlapsInst(Other->Live.getStart(), UseTrimmed);
}
Variable *getLo() const { return LoVar; } Variable *getLo() const { return LoVar; }
Variable *getHi() const { return HiVar; } Variable *getHi() const { return HiVar; }
......
...@@ -7,10 +7,9 @@ ...@@ -7,10 +7,9 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //
// This file declares the data structures used during linear-scan // This file declares the LinearScan data structure used during
// register allocation. This includes LiveRangeWrapper which // linear-scan register allocation, which holds the various work
// encapsulates a variable and its live range, and LinearScan which // queues for the linear-scan algorithm.
// holds the various work queues for the linear-scan algorithm.
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
...@@ -22,34 +21,10 @@ ...@@ -22,34 +21,10 @@
namespace Ice { namespace Ice {
// Currently this just wraps a Variable pointer, so in principle we
// could use containers of Variable* instead of LiveRangeWrapper. But
// in the future, we may want to do more complex things such as live
// range splitting, and keeping a wrapper should make that simpler.
class LiveRangeWrapper {
public:
LiveRangeWrapper(Variable *Var) : Var(Var) {}
const LiveRange &range() const { return Var->getLiveRange(); }
bool endsBefore(const LiveRangeWrapper &Other) const {
return range().endsBefore(Other.range());
}
bool overlaps(const LiveRangeWrapper &Other) const {
const bool UseTrimmed = true;
return range().overlaps(Other.range(), UseTrimmed);
}
bool overlapsStart(const LiveRangeWrapper &Other) const {
const bool UseTrimmed = true;
return range().overlapsInst(Other.range().getStart(), UseTrimmed);
}
Variable *Var;
void dump(const Cfg *Func) const;
private:
// LiveRangeWrapper(const LiveRangeWrapper &) = delete;
// LiveRangeWrapper &operator=(const LiveRangeWrapper &) = delete;
};
class LinearScan { class LinearScan {
LinearScan(const LinearScan &) = delete;
LinearScan &operator=(const LinearScan &) = delete;
public: public:
LinearScan(Cfg *Func) : Func(Func) {} LinearScan(Cfg *Func) : Func(Func) {}
void scan(const llvm::SmallBitVector &RegMask); void scan(const llvm::SmallBitVector &RegMask);
...@@ -57,15 +32,13 @@ public: ...@@ -57,15 +32,13 @@ public:
private: private:
Cfg *const Func; Cfg *const Func;
typedef std::vector<LiveRangeWrapper> OrderedRanges; typedef std::vector<Variable *> OrderedRanges;
typedef std::list<LiveRangeWrapper> UnorderedRanges; typedef std::list<Variable *> UnorderedRanges;
OrderedRanges Unhandled; OrderedRanges Unhandled;
// UnhandledPrecolored is a subset of Unhandled, specially collected // UnhandledPrecolored is a subset of Unhandled, specially collected
// for faster processing. // for faster processing.
OrderedRanges UnhandledPrecolored; OrderedRanges UnhandledPrecolored;
UnorderedRanges Active, Inactive, Handled; UnorderedRanges Active, Inactive, Handled;
LinearScan(const LinearScan &) = delete;
LinearScan &operator=(const LinearScan &) = delete;
}; };
} // end of namespace Ice } // end of namespace Ice
......
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