Fix stats critical fast path calculation.

This commit is contained in:
Wilson Snyder 2017-10-30 22:38:47 -04:00
parent 52c3031a82
commit eb87232472
1 changed files with 48 additions and 37 deletions

View File

@ -45,18 +45,20 @@ private:
// STATE // STATE
string m_stage; // Name of the stage we are scanning string m_stage; // Name of the stage we are scanning
bool m_fast; // Counting only fastpath /// m_fast = true: Counting only critical branch of fastpath
/// m_fast = false: Counting every node, ignoring structure of program
bool m_fast;
AstCFunc* m_cfuncp; // Current CFUNC AstCFunc* m_cfuncp; // Current CFUNC
V3Double0 m_statInstrLong; // Instruction count V3Double0 m_statInstrLong; // Instruction count
bool m_counting; // Currently counting bool m_counting; // Currently counting
double m_instrs; // Current instr count double m_instrs; // Current instr count (for determining branch direction)
vector<V3Double0> m_statTypeCount; // Nodes of given type vector<V3Double0> m_statTypeCount; // Nodes of given type
V3Double0 m_statAbove[AstType::_ENUM_END][AstType::_ENUM_END]; // Nodes of given type V3Double0 m_statAbove[AstType::_ENUM_END][AstType::_ENUM_END]; // Nodes of given type
V3Double0 m_statPred[AstBranchPred::_ENUM_END]; // Nodes of given type V3Double0 m_statPred[AstBranchPred::_ENUM_END]; // Nodes of given type
V3Double0 m_statInstr; // Instruction count V3Double0 m_statInstr; // Instruction count
V3Double0 m_statInstrFast; // Instruction count V3Double0 m_statInstrFast; // Instruction count, non-slow() eval functions only
vector<V3Double0> m_statVarWidths; // Variables of given width vector<V3Double0> m_statVarWidths; // Variables of given width
vector<NameMap> m_statVarWidthNames; // Var names of given width vector<NameMap> m_statVarWidthNames; // Var names of given width
V3Double0 m_statVarArray; // Statistic tracking V3Double0 m_statVarArray; // Statistic tracking
@ -65,6 +67,12 @@ private:
V3Double0 m_statVarScpBytes; // Statistic tracking V3Double0 m_statVarScpBytes; // Statistic tracking
// METHODS // METHODS
static int debug() {
static int level = -1;
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
return level;
}
void allNodes(AstNode* nodep) { void allNodes(AstNode* nodep) {
m_instrs += nodep->instrCount(); m_instrs += nodep->instrCount();
if (m_counting) { if (m_counting) {
@ -128,48 +136,52 @@ private:
} }
} }
virtual void visit(AstNodeIf* nodep) { virtual void visit(AstNodeIf* nodep) {
UINFO(4," IF "<<nodep<<endl); UINFO(4," IF i="<<m_instrs<<" "<<nodep<<endl);
allNodes(nodep); allNodes(nodep);
// Condition is part of PREVIOUS block // Condition is part of cost allocated to PREVIOUS block
nodep->condp()->iterateAndNextConst(*this); nodep->condp()->iterateAndNextConst(*this);
// Track prediction // Track prediction
if (m_counting) { if (m_counting) {
++m_statPred[nodep->branchPred()]; ++m_statPred[nodep->branchPred()];
} }
if (!m_fast) { if (!m_fast) {
// Count everything
nodep->iterateChildrenConst(*this); nodep->iterateChildrenConst(*this);
} else { } else {
// See which path we want to take // See which path we want to take
bool takeElse = false; // Need to do even if !m_counting because maybe determining upstream if/else
if (!nodep->elsesp() || (nodep->branchPred()==AstBranchPred::BP_LIKELY)) { double ifInstrs = 0.0;
// Always take the if double elseInstrs = 0.0;
} else if (!nodep->ifsp() || (nodep->branchPred()==AstBranchPred::BP_UNLIKELY)) { if (nodep->branchPred() != AstBranchPred::BP_UNLIKELY) { // Check if
// Always take the else
} else {
// Take the longer path
bool prevCounting = m_counting;
double prevInstr = m_instrs; double prevInstr = m_instrs;
m_counting = false; bool prevCounting = m_counting;
// Check if {
m_instrs = 0; m_counting = false;
nodep->ifsp()->iterateAndNextConst(*this); m_instrs = 0.0;
double instrIf = m_instrs;
// Check else
m_instrs = 0;
nodep->elsesp()->iterateAndNextConst(*this);
double instrElse = m_instrs;
// Max of if or else condition
takeElse = (instrElse > instrIf);
// Restore
m_counting = prevCounting;
m_instrs = prevInstr + (takeElse?instrElse:instrIf);
}
// Count the block
if (m_counting) {
if (takeElse) {
nodep->elsesp()->iterateAndNextConst(*this);
} else {
nodep->ifsp()->iterateAndNextConst(*this); nodep->ifsp()->iterateAndNextConst(*this);
ifInstrs = m_instrs;
}
m_instrs = prevInstr;
m_counting = prevCounting;
}
if (nodep->branchPred() != AstBranchPred::BP_LIKELY) { // Check else
double prevInstr = m_instrs;
bool prevCounting = m_counting;
{
m_counting = false;
m_instrs = 0.0;
nodep->elsesp()->iterateAndNextConst(*this);
elseInstrs = m_instrs;
}
m_instrs = prevInstr;
m_counting = prevCounting;
}
// Now collect the stats
if (m_counting) {
if (ifInstrs >= elseInstrs) {
nodep->ifsp()->iterateAndNextConst(*this);
} else {
nodep->elsesp()->iterateAndNextConst(*this);
} }
} }
} }
@ -178,7 +190,6 @@ private:
//virtual void visit(AstWhile* nodep) { //virtual void visit(AstWhile* nodep) {
virtual void visit(AstCCall* nodep) { virtual void visit(AstCCall* nodep) {
//UINFO(4," CCALL "<<nodep<<endl);
allNodes(nodep); allNodes(nodep);
nodep->iterateChildrenConst(*this); nodep->iterateChildrenConst(*this);
if (m_fast) { if (m_fast) {
@ -199,8 +210,8 @@ private:
public: public:
// CONSTRUCTORS // CONSTRUCTORS
StatsVisitor(AstNetlist* nodep, const string& stage, bool fast) StatsVisitor(AstNetlist* nodep, const string& stage, bool fast)
: m_stage(stage), m_fast(fast) : m_stage(stage), m_fast(fast) {
{ UINFO(9,"Starting stats, fast="<<fast<<endl);
m_cfuncp = NULL; m_cfuncp = NULL;
m_counting = !m_fast; m_counting = !m_fast;
m_instrs = 0; m_instrs = 0;
@ -212,7 +223,7 @@ public:
virtual ~StatsVisitor() { virtual ~StatsVisitor() {
// Done. Publish statistics // Done. Publish statistics
V3Stats::addStat(m_stage, "Instruction count, TOTAL", m_statInstr); V3Stats::addStat(m_stage, "Instruction count, TOTAL", m_statInstr);
V3Stats::addStat(m_stage, "Instruction count, fast", m_statInstrFast); V3Stats::addStat(m_stage, "Instruction count, fast critical", m_statInstrFast);
// Vars // Vars
V3Stats::addStat(m_stage, "Vars, unpacked arrayed", m_statVarArray); V3Stats::addStat(m_stage, "Vars, unpacked arrayed", m_statVarArray);
V3Stats::addStat(m_stage, "Vars, clock attribute", m_statVarClock); V3Stats::addStat(m_stage, "Vars, clock attribute", m_statVarClock);