Commit 877b04e4 by Jim Stichnoth

Subzero: Speed up VariablesMetadata initialization.

Currently, O2 calls VariablesMetadata::init() 4 times: - Twice for liveness analysis, where only multi-block use information is needed for dealing with sparse bit vectors. - Once for address mode inference, where single-definition information is needed. - Once for register allocation, where all information is needed, including the set of all definitions which is needed for determining AllowOverlap. So we limit the amount of data we gather based on the actual need. BUG= none R=jvoung@chromium.org Review URL: https://codereview.chromium.org/650613003
parent 7b451a92
...@@ -164,7 +164,7 @@ void Cfg::genFrame() { ...@@ -164,7 +164,7 @@ void Cfg::genFrame() {
// doesn't need to iterate until convergence. // doesn't need to iterate until convergence.
void Cfg::livenessLightweight() { void Cfg::livenessLightweight() {
TimerMarker T(TimerStack::TT_livenessLightweight, this); TimerMarker T(TimerStack::TT_livenessLightweight, this);
getVMetadata()->init(); getVMetadata()->init(VMK_Uses);
for (CfgNode *Node : Nodes) for (CfgNode *Node : Nodes)
Node->livenessLightweight(); Node->livenessLightweight();
} }
...@@ -172,7 +172,7 @@ void Cfg::livenessLightweight() { ...@@ -172,7 +172,7 @@ void Cfg::livenessLightweight() {
void Cfg::liveness(LivenessMode Mode) { void Cfg::liveness(LivenessMode Mode) {
TimerMarker T(TimerStack::TT_liveness, this); TimerMarker T(TimerStack::TT_liveness, this);
Live.reset(new Liveness(this, Mode)); Live.reset(new Liveness(this, Mode));
getVMetadata()->init(); getVMetadata()->init(VMK_Uses);
Live->init(); Live->init();
// Initialize with all nodes needing to be processed. // Initialize with all nodes needing to be processed.
llvm::BitVector NeedToProcess(Nodes.size(), true); llvm::BitVector NeedToProcess(Nodes.size(), true);
......
...@@ -185,8 +185,10 @@ Variable Variable::asType(Type Ty) { ...@@ -185,8 +185,10 @@ Variable Variable::asType(Type Ty) {
return V; return V;
} }
void VariableTracking::markUse(const Inst *Instr, const CfgNode *Node, void VariableTracking::markUse(MetadataKind TrackingKind, const Inst *Instr,
bool IsFromDef, bool IsImplicit) { const CfgNode *Node, bool IsFromDef,
bool IsImplicit) {
(void)TrackingKind;
if (MultiBlock == MBS_MultiBlock) if (MultiBlock == MBS_MultiBlock)
return; return;
// TODO(stichnot): If the use occurs as a source operand in the // TODO(stichnot): If the use occurs as a source operand in the
...@@ -227,19 +229,31 @@ void VariableTracking::markUse(const Inst *Instr, const CfgNode *Node, ...@@ -227,19 +229,31 @@ void VariableTracking::markUse(const Inst *Instr, const CfgNode *Node,
} }
} }
void VariableTracking::markDef(const Inst *Instr, const CfgNode *Node) { void VariableTracking::markDef(MetadataKind TrackingKind, const Inst *Instr,
const CfgNode *Node) {
// TODO(stichnot): If the definition occurs in the last instruction // TODO(stichnot): If the definition occurs in the last instruction
// of the block, consider not marking this as a separate use. But // of the block, consider not marking this as a separate use. But
// be careful not to omit all uses of the variable if markDef() and // be careful not to omit all uses of the variable if markDef() and
// markUse() both use this optimization. // markUse() both use this optimization.
assert(Node); assert(Node);
// Verify that instructions are added in increasing order. // Verify that instructions are added in increasing order.
assert(Definitions.empty() || #ifndef NDEBUG
Instr->getNumber() >= Definitions.back()->getNumber()); if (TrackingKind == VMK_All) {
Definitions.push_back(Instr); const Inst *LastInstruction =
Definitions.empty() ? FirstOrSingleDefinition : Definitions.back();
assert(LastInstruction == NULL ||
Instr->getNumber() >= LastInstruction->getNumber());
}
#endif
const bool IsFromDef = true; const bool IsFromDef = true;
const bool IsImplicit = false; const bool IsImplicit = false;
markUse(Instr, Node, IsFromDef, IsImplicit); markUse(TrackingKind, Instr, Node, IsFromDef, IsImplicit);
if (TrackingKind == VMK_Uses)
return;
if (FirstOrSingleDefinition == NULL)
FirstOrSingleDefinition = Instr;
else if (TrackingKind == VMK_All)
Definitions.push_back(Instr);
switch (MultiDef) { switch (MultiDef) {
case MDS_Unknown: case MDS_Unknown:
assert(SingleDefNode == NULL); assert(SingleDefNode == NULL);
...@@ -275,8 +289,8 @@ const Inst *VariableTracking::getFirstDefinition() const { ...@@ -275,8 +289,8 @@ const Inst *VariableTracking::getFirstDefinition() const {
return NULL; return NULL;
case MDS_SingleDef: case MDS_SingleDef:
case MDS_MultiDefSingleBlock: case MDS_MultiDefSingleBlock:
assert(!Definitions.empty()); assert(FirstOrSingleDefinition);
return Definitions[0]; return FirstOrSingleDefinition;
} }
} }
...@@ -287,13 +301,14 @@ const Inst *VariableTracking::getSingleDefinition() const { ...@@ -287,13 +301,14 @@ const Inst *VariableTracking::getSingleDefinition() const {
case MDS_MultiDefSingleBlock: case MDS_MultiDefSingleBlock:
return NULL; return NULL;
case MDS_SingleDef: case MDS_SingleDef:
assert(!Definitions.empty()); assert(FirstOrSingleDefinition);
return Definitions[0]; return FirstOrSingleDefinition;
} }
} }
void VariablesMetadata::init() { void VariablesMetadata::init(MetadataKind TrackingKind) {
TimerMarker T(TimerStack::TT_vmetadata, Func); TimerMarker T(TimerStack::TT_vmetadata, Func);
Kind = TrackingKind;
Metadata.clear(); Metadata.clear();
Metadata.resize(Func->getNumVariables()); Metadata.resize(Func->getNumVariables());
...@@ -303,7 +318,8 @@ void VariablesMetadata::init() { ...@@ -303,7 +318,8 @@ void VariablesMetadata::init() {
const CfgNode *EntryNode = Func->getEntryNode(); const CfgNode *EntryNode = Func->getEntryNode();
const bool IsFromDef = false; const bool IsFromDef = false;
const bool IsImplicit = true; const bool IsImplicit = true;
Metadata[Var->getIndex()].markUse(NoInst, EntryNode, IsFromDef, IsImplicit); Metadata[Var->getIndex()]
.markUse(Kind, NoInst, EntryNode, IsFromDef, IsImplicit);
} }
for (CfgNode *Node : Func->getNodes()) { for (CfgNode *Node : Func->getNodes()) {
...@@ -318,14 +334,14 @@ void VariablesMetadata::init() { ...@@ -318,14 +334,14 @@ void VariablesMetadata::init() {
Variable *Var = llvm::cast<Variable>(I->getSrc(SrcNum)); Variable *Var = llvm::cast<Variable>(I->getSrc(SrcNum));
SizeT VarNum = Var->getIndex(); SizeT VarNum = Var->getIndex();
assert(VarNum < Metadata.size()); assert(VarNum < Metadata.size());
Metadata[VarNum].markDef(Kill, Node); Metadata[VarNum].markDef(Kind, Kill, Node);
} }
continue; // no point in executing the rest continue; // no point in executing the rest
} }
if (Variable *Dest = I->getDest()) { if (Variable *Dest = I->getDest()) {
SizeT DestNum = Dest->getIndex(); SizeT DestNum = Dest->getIndex();
assert(DestNum < Metadata.size()); assert(DestNum < Metadata.size());
Metadata[DestNum].markDef(I, Node); Metadata[DestNum].markDef(Kind, I, Node);
} }
for (SizeT SrcNum = 0; SrcNum < I->getSrcSize(); ++SrcNum) { for (SizeT SrcNum = 0; SrcNum < I->getSrcSize(); ++SrcNum) {
Operand *Src = I->getSrc(SrcNum); Operand *Src = I->getSrc(SrcNum);
...@@ -336,7 +352,7 @@ void VariablesMetadata::init() { ...@@ -336,7 +352,7 @@ void VariablesMetadata::init() {
assert(VarNum < Metadata.size()); assert(VarNum < Metadata.size());
const bool IsFromDef = false; const bool IsFromDef = false;
const bool IsImplicit = false; const bool IsImplicit = false;
Metadata[VarNum].markUse(I, Node, IsFromDef, IsImplicit); Metadata[VarNum].markUse(Kind, I, Node, IsFromDef, IsImplicit);
} }
} }
} }
...@@ -344,6 +360,7 @@ void VariablesMetadata::init() { ...@@ -344,6 +360,7 @@ void VariablesMetadata::init() {
} }
bool VariablesMetadata::isMultiDef(const Variable *Var) const { bool VariablesMetadata::isMultiDef(const Variable *Var) const {
assert(Kind != VMK_Uses);
if (Var->getIsArg()) if (Var->getIsArg())
return false; return false;
if (!isTracked(Var)) if (!isTracked(Var))
...@@ -364,6 +381,7 @@ bool VariablesMetadata::isMultiBlock(const Variable *Var) const { ...@@ -364,6 +381,7 @@ bool VariablesMetadata::isMultiBlock(const Variable *Var) const {
} }
const Inst *VariablesMetadata::getFirstDefinition(const Variable *Var) const { const Inst *VariablesMetadata::getFirstDefinition(const Variable *Var) const {
assert(Kind != VMK_Uses);
if (!isTracked(Var)) if (!isTracked(Var))
return NULL; // conservative answer return NULL; // conservative answer
SizeT VarNum = Var->getIndex(); SizeT VarNum = Var->getIndex();
...@@ -371,6 +389,7 @@ const Inst *VariablesMetadata::getFirstDefinition(const Variable *Var) const { ...@@ -371,6 +389,7 @@ const Inst *VariablesMetadata::getFirstDefinition(const Variable *Var) const {
} }
const Inst *VariablesMetadata::getSingleDefinition(const Variable *Var) const { const Inst *VariablesMetadata::getSingleDefinition(const Variable *Var) const {
assert(Kind != VMK_Uses);
if (!isTracked(Var)) if (!isTracked(Var))
return NULL; // conservative answer return NULL; // conservative answer
SizeT VarNum = Var->getIndex(); SizeT VarNum = Var->getIndex();
...@@ -378,11 +397,12 @@ const Inst *VariablesMetadata::getSingleDefinition(const Variable *Var) const { ...@@ -378,11 +397,12 @@ const Inst *VariablesMetadata::getSingleDefinition(const Variable *Var) const {
} }
const InstDefList & const InstDefList &
VariablesMetadata::getDefinitions(const Variable *Var) const { VariablesMetadata::getLatterDefinitions(const Variable *Var) const {
assert(Kind == VMK_All);
if (!isTracked(Var)) if (!isTracked(Var))
return NoDefinitions; return NoDefinitions;
SizeT VarNum = Var->getIndex(); SizeT VarNum = Var->getIndex();
return Metadata[VarNum].getDefinitions(); return Metadata[VarNum].getLatterDefinitions();
} }
const CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const { const CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const {
......
...@@ -516,6 +516,11 @@ protected: ...@@ -516,6 +516,11 @@ protected:
Variable *VarsReal[1]; Variable *VarsReal[1];
}; };
enum MetadataKind {
VMK_Uses, // Track only uses, not defs
VMK_SingleDefs, // Track uses+defs, but only record single def
VMK_All // Track uses+defs, including full def list
};
typedef std::vector<const Inst *> InstDefList; typedef std::vector<const Inst *> InstDefList;
// VariableTracking tracks the metadata for a single variable. It is // VariableTracking tracks the metadata for a single variable. It is
...@@ -539,16 +544,17 @@ public: ...@@ -539,16 +544,17 @@ public:
}; };
VariableTracking() VariableTracking()
: MultiDef(MDS_Unknown), MultiBlock(MBS_Unknown), SingleUseNode(NULL), : MultiDef(MDS_Unknown), MultiBlock(MBS_Unknown), SingleUseNode(NULL),
SingleDefNode(NULL) {} SingleDefNode(NULL), FirstOrSingleDefinition(NULL) {}
MultiDefState getMultiDef() const { return MultiDef; } MultiDefState getMultiDef() const { return MultiDef; }
MultiBlockState getMultiBlock() const { return MultiBlock; } MultiBlockState getMultiBlock() const { return MultiBlock; }
const Inst *getFirstDefinition() const; const Inst *getFirstDefinition() const;
const Inst *getSingleDefinition() const; const Inst *getSingleDefinition() const;
const InstDefList &getDefinitions() const { return Definitions; } const InstDefList &getLatterDefinitions() const { return Definitions; }
const CfgNode *getNode() const { return SingleUseNode; } const CfgNode *getNode() const { return SingleUseNode; }
void markUse(const Inst *Instr, const CfgNode *Node, bool IsFromDef, void markUse(MetadataKind TrackingKind, const Inst *Instr,
bool IsImplicit); const CfgNode *Node, bool IsFromDef, bool IsImplicit);
void markDef(const Inst *Instr, const CfgNode *Node); void markDef(MetadataKind TrackingKind, const Inst *Instr,
const CfgNode *Node);
private: private:
MultiDefState MultiDef; MultiDefState MultiDef;
...@@ -557,7 +563,8 @@ private: ...@@ -557,7 +563,8 @@ private:
const CfgNode *SingleDefNode; const CfgNode *SingleDefNode;
// All definitions of the variable are collected here, in increasing // All definitions of the variable are collected here, in increasing
// order of instruction number. // order of instruction number.
InstDefList Definitions; InstDefList Definitions; // Only used if Kind==VMK_All
const Inst *FirstOrSingleDefinition; // == Definitions[0] if Kind==VMK_All
}; };
// VariablesMetadata analyzes and summarizes the metadata for the // VariablesMetadata analyzes and summarizes the metadata for the
...@@ -570,7 +577,7 @@ public: ...@@ -570,7 +577,7 @@ public:
VariablesMetadata(const Cfg *Func) : Func(Func) {} VariablesMetadata(const Cfg *Func) : Func(Func) {}
// Initialize the state by traversing all instructions/variables in // Initialize the state by traversing all instructions/variables in
// the CFG. // the CFG.
void init(); void init(MetadataKind TrackingKind);
// Returns whether the given Variable is tracked in this object. It // Returns whether the given Variable is tracked in this object. It
// should only return false if changes were made to the CFG after // should only return false if changes were made to the CFG after
// running init(), in which case the state is stale and the results // running init(), in which case the state is stale and the results
...@@ -594,7 +601,7 @@ public: ...@@ -594,7 +601,7 @@ public:
const Inst *getSingleDefinition(const Variable *Var) const; const Inst *getSingleDefinition(const Variable *Var) const;
// Returns the list of all definition instructions of the given // Returns the list of all definition instructions of the given
// Variable. // Variable.
const InstDefList &getDefinitions(const Variable *Var) const; const InstDefList &getLatterDefinitions(const Variable *Var) const;
// Returns whether the given Variable is live across multiple // Returns whether the given Variable is live across multiple
// blocks. Mainly, this is used to partition Variables into // blocks. Mainly, this is used to partition Variables into
...@@ -610,6 +617,7 @@ public: ...@@ -610,6 +617,7 @@ public:
private: private:
const Cfg *Func; const Cfg *Func;
MetadataKind Kind;
std::vector<VariableTracking> Metadata; std::vector<VariableTracking> Metadata;
const static InstDefList NoDefinitions; const static InstDefList NoDefinitions;
}; };
......
...@@ -32,7 +32,10 @@ namespace { ...@@ -32,7 +32,10 @@ namespace {
bool overlapsDefs(const Cfg *Func, const Variable *Item, const Variable *Var) { bool overlapsDefs(const Cfg *Func, const Variable *Item, const Variable *Var) {
const bool UseTrimmed = true; const bool UseTrimmed = true;
VariablesMetadata *VMetadata = Func->getVMetadata(); VariablesMetadata *VMetadata = Func->getVMetadata();
const InstDefList &Defs = VMetadata->getDefinitions(Var); if (const Inst *FirstDef = VMetadata->getFirstDefinition(Var))
if (Item->getLiveRange().overlapsInst(FirstDef->getNumber(), UseTrimmed))
return true;
const InstDefList &Defs = VMetadata->getLatterDefinitions(Var);
for (size_t i = 0; i < Defs.size(); ++i) { for (size_t i = 0; i < Defs.size(); ++i) {
if (Item->getLiveRange().overlapsInst(Defs[i]->getNumber(), UseTrimmed)) if (Item->getLiveRange().overlapsInst(Defs[i]->getNumber(), UseTrimmed))
return true; return true;
...@@ -47,11 +50,11 @@ void dumpDisableOverlap(const Cfg *Func, const Variable *Var, ...@@ -47,11 +50,11 @@ void dumpDisableOverlap(const Cfg *Func, const Variable *Var,
Ostream &Str = Func->getContext()->getStrDump(); Ostream &Str = Func->getContext()->getStrDump();
Str << "Disabling Overlap due to " << Reason << " " << *Var Str << "Disabling Overlap due to " << Reason << " " << *Var
<< " LIVE=" << Var->getLiveRange() << " Defs="; << " LIVE=" << Var->getLiveRange() << " Defs=";
const InstDefList &Defs = VMetadata->getDefinitions(Var); if (const Inst *FirstDef = VMetadata->getFirstDefinition(Var))
Str << FirstDef->getNumber();
const InstDefList &Defs = VMetadata->getLatterDefinitions(Var);
for (size_t i = 0; i < Defs.size(); ++i) { for (size_t i = 0; i < Defs.size(); ++i) {
if (i > 0) Str << "," << Defs[i]->getNumber();
Str << ",";
Str << Defs[i]->getNumber();
} }
Str << "\n"; Str << "\n";
} }
......
...@@ -329,7 +329,7 @@ void TargetX8632::translateO2() { ...@@ -329,7 +329,7 @@ void TargetX8632::translateO2() {
Func->dump("After Phi lowering"); Func->dump("After Phi lowering");
// Address mode optimization. // Address mode optimization.
Func->getVMetadata()->init(); Func->getVMetadata()->init(VMK_SingleDefs);
Func->doAddressOpt(); Func->doAddressOpt();
// Argument lowering // Argument lowering
...@@ -372,7 +372,7 @@ void TargetX8632::translateO2() { ...@@ -372,7 +372,7 @@ void TargetX8632::translateO2() {
// The post-codegen dump is done here, after liveness analysis and // The post-codegen dump is done here, after liveness analysis and
// associated cleanup, to make the dump cleaner and more useful. // associated cleanup, to make the dump cleaner and more useful.
Func->dump("After initial x8632 codegen"); Func->dump("After initial x8632 codegen");
Func->getVMetadata()->init(); Func->getVMetadata()->init(VMK_All);
regAlloc(); regAlloc();
if (Func->hasError()) if (Func->hasError())
return; return;
......
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