Commit cc89c959 by Jim Stichnoth

Subzero: Ignore variables with no actual uses.

Liveness analysis uses a pair of bit vectors in each CFG node. The early bits correspond to "global" variables that are referenced in more than one block, and the latter bits correspond to "local" variables that are referenced in only that particular single block. Due to an oversight, variables that have no uses are conservatively classified as global, and consume space in every liveness bit vector. This CL improves memory usage by reducing liveness bit vector size: 1. Identify variables with no actual uses and exclude them from the bit vectors. 2. Don't do liveness analysis on rematerializable variables, because they have no need to be involved in register allocation or dead code elimination. BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4366 R=jpp@chromium.org Review URL: https://codereview.chromium.org/1844713004 .
parent b5eee3d7
......@@ -206,7 +206,7 @@ bool Inst::liveness(InstNumberT InstNumber, LivenessBV &Live,
assert(!isDeleted());
Dead = false;
if (Dest) {
if (Dest && !Dest->isRematerializable()) {
SizeT VarNum = Liveness->getLiveIndex(Dest->getIndex());
if (Live[VarNum]) {
if (!isDestRedefined()) {
......@@ -227,6 +227,8 @@ bool Inst::liveness(InstNumberT InstNumber, LivenessBV &Live,
bool IsPhi = llvm::isa<InstPhi>(this);
resetLastUses();
FOREACH_VAR_IN_INST(Var, *this) {
if (Var->isRematerializable())
continue;
SizeT VarNum = Liveness->getLiveIndex(Var->getIndex());
if (!Live[VarNum]) {
setLastUse(IndexOfVarInInst(Var));
......@@ -411,10 +413,12 @@ void InstPhi::livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
for (SizeT I = 0; I < getSrcSize(); ++I) {
if (Labels[I] == Target) {
if (auto *Var = llvm::dyn_cast<Variable>(getSrc(I))) {
SizeT SrcIndex = Liveness->getLiveIndex(Var->getIndex());
if (!Live[SrcIndex]) {
setLastUse(I);
Live[SrcIndex] = true;
if (!Var->isRematerializable()) {
SizeT SrcIndex = Liveness->getLiveIndex(Var->getIndex());
if (!Live[SrcIndex]) {
setLastUse(I);
Live[SrcIndex] = true;
}
}
}
return;
......
......@@ -50,7 +50,7 @@ void Liveness::initInternal(NodeList::const_iterator FirstNode,
Variable *Var = *I;
if (VMetadata->isMultiBlock(Var)) {
++TmpNumGlobals;
} else {
} else if (VMetadata->isSingleBlock(Var)) {
SizeT Index = VMetadata->getLocalUseNode(Var)->getIndex();
++Nodes[Index].NumLocals;
}
......@@ -81,18 +81,18 @@ void Liveness::initInternal(NodeList::const_iterator FirstNode,
for (auto I = FirstVar, E = Func->getVariables().end(); I != E; ++I) {
Variable *Var = *I;
SizeT VarIndex = Var->getIndex();
SizeT LiveIndex;
SizeT LiveIndex = InvalidLiveIndex;
if (VMetadata->isMultiBlock(Var)) {
LiveIndex = TmpNumGlobals++;
LiveToVarMap[LiveIndex] = Var;
} else {
} else if (VMetadata->isSingleBlock(Var)) {
SizeT NodeIndex = VMetadata->getLocalUseNode(Var)->getIndex();
LiveIndex = Nodes[NodeIndex].NumLocals++;
Nodes[NodeIndex].LiveToVarMap[LiveIndex] = Var;
LiveIndex += NumGlobals;
}
VarToLiveMap[VarIndex] = LiveIndex;
if (Var->getIgnoreLiveness())
if (LiveIndex == InvalidLiveIndex || Var->getIgnoreLiveness())
RangeMask[VarIndex] = false;
}
assert(TmpNumGlobals == (IsFullInit ? NumGlobals : 0));
......
......@@ -67,7 +67,11 @@ public:
Cfg *getFunc() const { return Func; }
LivenessMode getMode() const { return Mode; }
Variable *getVariable(SizeT LiveIndex, const CfgNode *Node) const;
SizeT getLiveIndex(SizeT VarIndex) const { return VarToLiveMap[VarIndex]; }
SizeT getLiveIndex(SizeT VarIndex) const {
const SizeT LiveIndex = VarToLiveMap[VarIndex];
assert(LiveIndex != InvalidLiveIndex);
return LiveIndex;
}
SizeT getNumGlobalVars() const { return NumGlobals; }
SizeT getNumVarsInNode(const CfgNode *Node) const {
return NumGlobals + Nodes[Node->getIndex()].NumLocals;
......@@ -106,6 +110,7 @@ private:
if (Index >= Nodes.size())
Nodes.resize(Index + 1);
}
static constexpr SizeT InvalidLiveIndex = -1;
Cfg *Func;
LivenessMode Mode;
SizeT NumGlobals = 0;
......
......@@ -256,6 +256,7 @@ void VariableTracking::markUse(MetadataKind TrackingKind, const Inst *Instr,
if (!MakeMulti) {
switch (MultiBlock) {
case MBS_Unknown:
case MBS_NoUses:
MultiBlock = MBS_SingleBlock;
SingleUseNode = Node;
break;
......@@ -370,7 +371,7 @@ void VariablesMetadata::init(MetadataKind TrackingKind) {
TimerMarker T(TimerStack::TT_vmetadata, Func);
Kind = TrackingKind;
Metadata.clear();
Metadata.resize(Func->getNumVariables());
Metadata.resize(Func->getNumVariables(), VariableTracking::MBS_NoUses);
// Mark implicit args as being used in the entry node.
for (Variable *Var : Func->getImplicitArgs()) {
......@@ -439,11 +440,42 @@ bool VariablesMetadata::isMultiDef(const Variable *Var) const {
bool VariablesMetadata::isMultiBlock(const Variable *Var) const {
if (Var->getIsArg())
return true;
if (Var->isRematerializable())
return false;
if (!isTracked(Var))
return true; // conservative answer
SizeT VarNum = Var->getIndex();
switch (Metadata[VarNum].getMultiBlock()) {
case VariableTracking::MBS_NoUses:
case VariableTracking::MBS_SingleBlock:
return false;
// Conservatively return true if the state is unknown.
return Metadata[VarNum].getMultiBlock() != VariableTracking::MBS_SingleBlock;
case VariableTracking::MBS_Unknown:
case VariableTracking::MBS_MultiBlock:
return true;
}
assert(0);
return true;
}
bool VariablesMetadata::isSingleBlock(const Variable *Var) const {
if (Var->getIsArg())
return false;
if (Var->isRematerializable())
return false;
if (!isTracked(Var))
return false; // conservative answer
SizeT VarNum = Var->getIndex();
switch (Metadata[VarNum].getMultiBlock()) {
case VariableTracking::MBS_SingleBlock:
return true;
case VariableTracking::MBS_Unknown:
case VariableTracking::MBS_NoUses:
case VariableTracking::MBS_MultiBlock:
return false;
}
assert(0);
return false;
}
const Inst *
......
......@@ -661,7 +661,9 @@ public:
void setIsImplicitArg(bool Val = true) { IsImplicitArgument = Val; }
void setIgnoreLiveness() { IgnoreLiveness = true; }
bool getIgnoreLiveness() const { return IgnoreLiveness; }
bool getIgnoreLiveness() const {
return IgnoreLiveness || IsRematerializable;
}
int32_t getStackOffset() const { return StackOffset; }
void setStackOffset(int32_t Offset) { StackOffset = Offset; }
......@@ -863,8 +865,6 @@ using InstDefList = CfgVector<const Inst *>;
/// VariableTracking tracks the metadata for a single variable. It is
/// only meant to be used internally by VariablesMetadata.
class VariableTracking {
VariableTracking &operator=(const VariableTracking &) = delete;
public:
enum MultiDefState {
// TODO(stichnot): Consider using just a simple counter.
......@@ -873,9 +873,16 @@ public:
MDS_MultiDefSingleBlock,
MDS_MultiDefMultiBlock
};
enum MultiBlockState { MBS_Unknown, MBS_SingleBlock, MBS_MultiBlock };
enum MultiBlockState {
MBS_Unknown, // Not yet initialized, so be conservative
MBS_NoUses, // Known to have no uses
MBS_SingleBlock, // All uses in are in a single block
MBS_MultiBlock // Several uses across several blocks
};
VariableTracking() = default;
VariableTracking(const VariableTracking &) = default;
VariableTracking &operator=(const VariableTracking &) = default;
VariableTracking(MultiBlockState MultiBlock) : MultiBlock(MultiBlock) {}
MultiDefState getMultiDef() const { return MultiDef; }
MultiBlockState getMultiBlock() const { return MultiBlock; }
const Inst *getFirstDefinitionSingleBlock() const;
......@@ -948,6 +955,7 @@ public:
/// always considered multi-block because they are live coming into the entry
/// block.
bool isMultiBlock(const Variable *Var) const;
bool isSingleBlock(const Variable *Var) const;
/// Returns the node that the given Variable is used in, assuming
/// isMultiBlock() returns false. Otherwise, nullptr is returned.
CfgNode *getLocalUseNode(const Variable *Var) const;
......
......@@ -219,8 +219,6 @@ void LinearScan::initForInfOnly() {
if (Instr.isDeleted())
continue;
FOREACH_VAR_IN_INST(Var, Instr) {
if (Var->isRematerializable())
continue;
if (Var->getIgnoreLiveness())
continue;
if (Var->hasReg() || Var->mustHaveReg()) {
......@@ -231,7 +229,7 @@ void LinearScan::initForInfOnly() {
}
}
if (const Variable *Var = Instr.getDest()) {
if (!Var->isRematerializable() && !Var->getIgnoreLiveness() &&
if (!Var->getIgnoreLiveness() &&
(Var->hasReg() || Var->mustHaveReg())) {
if (LRBegin[Var->getIndex()] == Inst::NumberSentinel) {
LRBegin[Var->getIndex()] = Instr.getNumber();
......
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