Internals: V3Inline support for future hard-no-inline. No functional change.

This commit is contained in:
Wilson Snyder 2013-05-26 11:17:42 -04:00
parent 24fcae4f49
commit 8e2617ab8d
2 changed files with 45 additions and 25 deletions

View File

@ -844,7 +844,7 @@ void AstVarXRef::dump(ostream& str) {
if (lvalue()) str<<" [LV] => "; if (lvalue()) str<<" [LV] => ";
else str<<" [RV] <- "; else str<<" [RV] <- ";
str<<dotted()<<". - "; str<<dotted()<<". - ";
if (inlinedDots()!="") str<<" flat.="<<inlinedDots()<<" - "; if (inlinedDots()!="") str<<" inline.="<<inlinedDots()<<" - ";
if (varScopep()) { varScopep()->dump(str); } if (varScopep()) { varScopep()->dump(str); }
else if (varp()) { varp()->dump(str); } else if (varp()) { varp()->dump(str); }
else { str<<"UNLINKED"; } else { str<<"UNLINKED"; }

View File

@ -51,23 +51,42 @@ static const int INLINE_MODS_SMALLER = 100; // If a mod is < this # nodes, can a
class InlineMarkVisitor : public AstNVisitor { class InlineMarkVisitor : public AstNVisitor {
private: private:
// NODE STATE // NODE STATE
// Entire netlist // Output
// AstNodeModule::user1() // OUTPUT: bool. User request to inline this module // AstNodeModule::user1() // OUTPUT: bool. User request to inline this module
// AstNodeModule::user2() // bool. Allowed to automatically inline module // Entire netlist (can be cleared after this visit completes)
// AstNodeModule::user2() // CIL_*. Allowed to automatically inline module
// AstNodeModule::user3() // int. Number of cells referencing this module // AstNodeModule::user3() // int. Number of cells referencing this module
AstUser1InUse m_inuser1; AstUser1InUse m_inuser1;
AstUser2InUse m_inuser2; AstUser2InUse m_inuser2;
AstUser3InUse m_inuser3; AstUser3InUse m_inuser3;
enum {CIL_NOTHARD=0, // For user2, inline not supported
CIL_NOTSOFT, // For user2, don't inline unless user overrides
CIL_MAYBE}; // For user2, might inline
// STATE // STATE
AstNodeModule* m_modp; // Flattened cell's containing module AstNodeModule* m_modp; // Flattened cell's containing module
int m_stmtCnt; // Statements in module int m_stmtCnt; // Statements in module
V3Double0 m_statUnsup; // Statistic tracking
// METHODS // METHODS
void cantInline(const char* reason) { static int debug() {
if (m_modp->user2()) { static int level = -1;
UINFO(4," No inline: "<<reason<<" "<<m_modp<<endl); if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
m_modp->user2(false); return level;
}
void cantInline(const char* reason, bool hard) {
if (hard) {
if (m_modp->user2() != CIL_NOTHARD) {
UINFO(4," No inline hard: "<<reason<<" "<<m_modp<<endl);
m_modp->user2(CIL_NOTHARD);
m_statUnsup++;
}
} else {
if (m_modp->user2() == CIL_MAYBE) {
UINFO(4," No inline soft: "<<reason<<" "<<m_modp<<endl);
m_modp->user2(CIL_NOTSOFT);
}
} }
} }
@ -75,28 +94,28 @@ private:
virtual void visit(AstNodeModule* nodep, AstNUser*) { virtual void visit(AstNodeModule* nodep, AstNUser*) {
m_stmtCnt = 0; m_stmtCnt = 0;
m_modp = nodep; m_modp = nodep;
m_modp->user2(true); // Allowed = true m_modp->user2(CIL_MAYBE);
if (m_modp->modPublic()) cantInline("modPublic"); if (m_modp->modPublic()) cantInline("modPublic",false);
// //
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
// //
bool userinline = nodep->user1(); bool userinline = nodep->user1();
bool allowed = nodep->user2(); int allowed = nodep->user2();
int refs = nodep->user3(); int refs = nodep->user3();
// Should we automatically inline this module? // Should we automatically inline this module?
// inlineMult = 2000 by default. If a mod*#instances is < this # nodes, can inline it // inlineMult = 2000 by default. If a mod*#instances is < this # nodes, can inline it
bool doit = (userinline || (allowed && (refs==1 bool doit = ((allowed == CIL_NOTSOFT || allowed == CIL_MAYBE)
|| m_stmtCnt < INLINE_MODS_SMALLER && (userinline
|| v3Global.opt.inlineMult() < 1 || ((allowed == CIL_MAYBE)
|| refs*m_stmtCnt < v3Global.opt.inlineMult()))); && (refs==1
|| m_stmtCnt < INLINE_MODS_SMALLER
|| v3Global.opt.inlineMult() < 1
|| refs*m_stmtCnt < v3Global.opt.inlineMult()))));
// Packages aren't really "under" anything so they confuse this algorithm // Packages aren't really "under" anything so they confuse this algorithm
if (nodep->castPackage()) doit = false; if (nodep->castPackage()) doit = false;
UINFO(4, " Inline="<<doit<<" Possible="<<allowed<<" Usr="<<userinline<<" Refs="<<refs<<" Stmts="<<m_stmtCnt UINFO(4, " Inline="<<doit<<" Possible="<<allowed<<" Usr="<<userinline<<" Refs="<<refs<<" Stmts="<<m_stmtCnt
<<" "<<nodep<<endl); <<" "<<nodep<<endl);
if (doit) { nodep->user1(doit);
UINFO(4," AutoInline "<<nodep<<endl);
nodep->user1(true);
}
m_modp = NULL; m_modp = NULL;
} }
virtual void visit(AstCell* nodep, AstNUser*) { virtual void visit(AstCell* nodep, AstNUser*) {
@ -116,7 +135,7 @@ private:
if (!m_modp) { if (!m_modp) {
nodep->v3error("Inline pragma not under a module"); nodep->v3error("Inline pragma not under a module");
} else { } else {
cantInline("Pragma NO_INLINE_MODULE"); cantInline("Pragma NO_INLINE_MODULE",false);
} }
nodep->unlinkFrBack()->deleteTree(); nodep=NULL; // Remove so don't propagate to upper cell... nodep->unlinkFrBack()->deleteTree(); nodep=NULL; // Remove so don't propagate to upper cell...
} else { } else {
@ -156,13 +175,14 @@ public:
InlineMarkVisitor(AstNode* nodep) { InlineMarkVisitor(AstNode* nodep) {
m_modp = NULL; m_modp = NULL;
m_stmtCnt = 0; m_stmtCnt = 0;
//VV***** We reset all userp() on the whole netlist!!!
AstNode::user1ClearTree();
AstNode::user2ClearTree();
AstNode::user3ClearTree();
nodep->accept(*this); nodep->accept(*this);
} }
virtual ~InlineMarkVisitor() {} virtual ~InlineMarkVisitor() {
V3Stats::addStat("Optimizations, Inline unsupported", m_statUnsup);
// Done with these, are not outputs
AstNode::user2ClearTree();
AstNode::user3ClearTree();
}
}; };
//###################################################################### //######################################################################
@ -226,7 +246,7 @@ private:
new AstVarRef(nodep->fileline(), exprvarrefp->varp(), true), new AstVarRef(nodep->fileline(), exprvarrefp->varp(), true),
new AstVarRef(nodep->fileline(), nodep, false))); new AstVarRef(nodep->fileline(), nodep, false)));
} else { } else {
// Due to inlining child's variable now within the same module, so a AstVarRef not AstVarXRef below // Do to inlining child's variable now within the same module, so a AstVarRef not AstVarXRef below
m_modp->addStmtp(new AstAssignAlias(nodep->fileline(), m_modp->addStmtp(new AstAssignAlias(nodep->fileline(),
new AstVarRef(nodep->fileline(), nodep, true), new AstVarRef(nodep->fileline(), nodep, true),
new AstVarRef(nodep->fileline(), exprvarrefp->varp(), false))); new AstVarRef(nodep->fileline(), exprvarrefp->varp(), false)));