Commit 552490c2 by Jim Stichnoth

Subzero: Slight improvement to phi lowering.

When doing post phi lowering register allocation, the original code limited register allocation to pre-colored or infinite-weight variables with a non-empty live range within the new edge-split nodes. This limitation ends up missing some opportunities. Specifically, when a temporary is introduced to break a dependency cycle, e.g.: // a = phi(b) // b = phi(a) t = a a = b b = t then t was always stack-allocated, even if a physical register was available. In the new design, the RangeMask bitvector specifies which variables should have their live ranges tracked and computed. For normal liveness analysis, all variables are tracked. For post phi lowering liveness analysis, all variables created from phi lowering, plus all pre-colored variables, plus all infinite-weight variables, are tracked. The result is slightly better code quality, and sometimes the frame size is 1 or 2 words smaller. The hope was to narrow the 10% translation-time degradation in pnacl-llc.pexe compared to the old, hackish way of phi lowering, but that goal still proves to be elusive. BUG= none R=jvoung@chromium.org Review URL: https://codereview.chromium.org/1271923002.
parent e0d9afa8
...@@ -273,9 +273,6 @@ void Cfg::advancedPhiLowering() { ...@@ -273,9 +273,6 @@ void Cfg::advancedPhiLowering() {
InstNumberT FirstInstNum = getNextInstNumber(); InstNumberT FirstInstNum = getNextInstNumber();
(*I)->renumberInstructions(); (*I)->renumberInstructions();
InstNumberT LastInstNum = getNextInstNumber() - 1; InstNumberT LastInstNum = getNextInstNumber() - 1;
// TODO(stichnot): May be able to speed up liveness and live range
// calculation by having it consider only pre-colored or infinite-weight
// variables. Could also simplify LinearScan::initForInfOnly() that way.
(*I)->liveness(getLiveness()); (*I)->liveness(getLiveness());
(*I)->livenessAddIntervals(getLiveness(), FirstInstNum, LastInstNum); (*I)->livenessAddIntervals(getLiveness(), FirstInstNum, LastInstNum);
} }
......
...@@ -580,6 +580,8 @@ bool CfgNode::liveness(Liveness *Liveness) { ...@@ -580,6 +580,8 @@ bool CfgNode::liveness(Liveness *Liveness) {
Live |= Liveness->getLiveIn(Succ); Live |= Liveness->getLiveIn(Succ);
// Mark corresponding argument of phis in successor as live. // Mark corresponding argument of phis in successor as live.
for (Inst &I : Succ->Phis) { for (Inst &I : Succ->Phis) {
if (I.isDeleted())
continue;
auto Phi = llvm::dyn_cast<InstPhi>(&I); auto Phi = llvm::dyn_cast<InstPhi>(&I);
Phi->livenessPhiOperand(Live, this, Liveness); Phi->livenessPhiOperand(Live, this, Liveness);
} }
...@@ -698,6 +700,9 @@ void CfgNode::livenessAddIntervals(Liveness *Liveness, InstNumberT FirstInstNum, ...@@ -698,6 +700,9 @@ void CfgNode::livenessAddIntervals(Liveness *Liveness, InstNumberT FirstInstNum,
InstNumberT LE = i == i2 ? IEB->second : LastInstNum + 1; InstNumberT LE = i == i2 ? IEB->second : LastInstNum + 1;
Variable *Var = Liveness->getVariable(i, this); Variable *Var = Liveness->getVariable(i, this);
// TODO(stichnot): Push getIgnoreLiveness() into the initialization of
// Liveness::RangeMask so that LiveBegin and LiveEnd never even reference
// such variables.
if (!Var->getIgnoreLiveness()) { if (!Var->getIgnoreLiveness()) {
if (LB > LE) { if (LB > LE) {
Var->addLiveRange(FirstInstNum, LE, 1); Var->addLiveRange(FirstInstNum, LE, 1);
...@@ -720,7 +725,8 @@ void CfgNode::livenessAddIntervals(Liveness *Liveness, InstNumberT FirstInstNum, ...@@ -720,7 +725,8 @@ void CfgNode::livenessAddIntervals(Liveness *Liveness, InstNumberT FirstInstNum,
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);
Var->addLiveRange(FirstInstNum, LastInstNum + 1, 1); if (Liveness->getRangeMask(Var->getIndex()))
Var->addLiveRange(FirstInstNum, LastInstNum + 1, 1);
} }
} }
......
...@@ -183,7 +183,7 @@ bool Inst::liveness(InstNumberT InstNumber, LivenessBV &Live, ...@@ -183,7 +183,7 @@ bool Inst::liveness(InstNumberT InstNumber, LivenessBV &Live,
if (Live[VarNum]) { if (Live[VarNum]) {
if (!isDestNonKillable()) { if (!isDestNonKillable()) {
Live[VarNum] = false; Live[VarNum] = false;
if (LiveBegin) { if (LiveBegin && Liveness->getRangeMask(Dest->getIndex())) {
LiveBegin->push_back(std::make_pair(VarNum, InstNumber)); LiveBegin->push_back(std::make_pair(VarNum, InstNumber));
} }
} }
...@@ -223,7 +223,7 @@ bool Inst::liveness(InstNumberT InstNumber, LivenessBV &Live, ...@@ -223,7 +223,7 @@ bool Inst::liveness(InstNumberT InstNumber, LivenessBV &Live,
// when LiveEnd[VarNum]==0 (sentinel value). Note that it's // when LiveEnd[VarNum]==0 (sentinel value). Note that it's
// OK to set LiveBegin multiple times because of the // OK to set LiveBegin multiple times because of the
// backwards traversal. // backwards traversal.
if (LiveEnd) { if (LiveEnd && Liveness->getRangeMask(Var->getIndex())) {
// Ideally, we would verify that VarNum wasn't already // Ideally, we would verify that VarNum wasn't already
// added in this block, but this can't be done very // added in this block, but this can't be done very
// efficiently with LiveEnd as a vector. Instead, // efficiently with LiveEnd as a vector. Instead,
......
...@@ -100,6 +100,17 @@ void Liveness::initInternal(NodeList::const_iterator FirstNode, ...@@ -100,6 +100,17 @@ void Liveness::initInternal(NodeList::const_iterator FirstNode,
// LiveBegin and LiveEnd are reinitialized before each pass over // LiveBegin and LiveEnd are reinitialized before each pass over
// the block. // the block.
} }
// Initialize the bitmask of which variables to track.
RangeMask.resize(NumVars);
RangeMask.set(0, NumVars);
if (!IsFullInit) {
// Reset initial variables that are not pre-colored or infinite-weight.
for (auto I = Func->getVariables().begin(); I != FirstVar; ++I) {
Variable *Var = *I;
RangeMask[Var->getIndex()] = (Var->hasReg() || Var->getWeight().isInf());
}
}
} }
void Liveness::init() { void Liveness::init() {
......
...@@ -96,6 +96,7 @@ public: ...@@ -96,6 +96,7 @@ public:
resize(Index); resize(Index);
return &Nodes[Index].LiveEnd; return &Nodes[Index].LiveEnd;
} }
bool getRangeMask(SizeT Index) const { return RangeMask[Index]; }
private: private:
void initInternal(NodeList::const_iterator FirstNode, void initInternal(NodeList::const_iterator FirstNode,
...@@ -116,6 +117,9 @@ private: ...@@ -116,6 +117,9 @@ 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;
/// RangeMask[Variable::Number] indicates whether we want to track that
/// Variable's live range.
llvm::BitVector RangeMask;
}; };
} // end of namespace Ice } // end of namespace Ice
......
...@@ -107,10 +107,6 @@ void LinearScan::initForGlobal() { ...@@ -107,10 +107,6 @@ void LinearScan::initForGlobal() {
// it was never referenced. // it was never referenced.
if (Var->getLiveRange().isEmpty()) if (Var->getLiveRange().isEmpty())
continue; continue;
// Post phi lowering register allocation is only concerned with variables
// that are infinite-weight or pre-colored.
if (Kind == RAK_Phi && !Var->getWeight().isInf() && !Var->hasReg())
continue;
Var->untrimLiveRange(); Var->untrimLiveRange();
Unhandled.push_back(Var); Unhandled.push_back(Var);
if (Var->hasReg()) { if (Var->hasReg()) {
......
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