Internals: Use runtime type info instead of dynamic_cast for faster graph type checks (#4397)

This commit is contained in:
Krzysztof Bieganski
2023-08-31 18:00:53 -04:00
committed by GitHub
parent 96ee81fa3f
commit ffbbd438ae
22 changed files with 390 additions and 143 deletions
+25 -17
View File
@@ -99,6 +99,7 @@ VL_DEFINE_DEBUG_FUNCTIONS;
// Support classes
class SplitNodeVertex VL_NOT_FINAL : public V3GraphVertex {
VL_RTTI_IMPL(SplitNodeVertex, V3GraphVertex)
AstNode* const m_nodep;
protected:
@@ -117,6 +118,7 @@ public:
};
class SplitPliVertex final : public SplitNodeVertex {
VL_RTTI_IMPL(SplitPliVertex, SplitNodeVertex)
public:
explicit SplitPliVertex(V3Graph* graphp, AstNode* nodep)
: SplitNodeVertex{graphp, nodep} {}
@@ -126,6 +128,7 @@ public:
};
class SplitLogicVertex final : public SplitNodeVertex {
VL_RTTI_IMPL(SplitLogicVertex, SplitNodeVertex)
public:
SplitLogicVertex(V3Graph* graphp, AstNode* nodep)
: SplitNodeVertex{graphp, nodep} {}
@@ -134,6 +137,7 @@ public:
};
class SplitVarStdVertex final : public SplitNodeVertex {
VL_RTTI_IMPL(SplitVarStdVertex, SplitNodeVertex)
public:
SplitVarStdVertex(V3Graph* graphp, AstNode* nodep)
: SplitNodeVertex{graphp, nodep} {}
@@ -142,6 +146,7 @@ public:
};
class SplitVarPostVertex final : public SplitNodeVertex {
VL_RTTI_IMPL(SplitVarPostVertex, SplitNodeVertex)
public:
SplitVarPostVertex(V3Graph* graphp, AstNode* nodep)
: SplitNodeVertex{graphp, nodep} {}
@@ -154,6 +159,7 @@ public:
// Edge types
class SplitEdge VL_NOT_FINAL : public V3GraphEdge {
VL_RTTI_IMPL(SplitEdge, V3GraphEdge)
uint32_t m_ignoreInStep = 0; // Step number that if set to, causes this edge to be ignored
static uint32_t s_stepNum; // Global step number
protected:
@@ -170,14 +176,12 @@ public:
void setIgnoreThisStep() { m_ignoreInStep = s_stepNum; }
virtual bool followScoreboard() const = 0;
static bool followScoreboard(const V3GraphEdge* edgep) {
const SplitEdge* const oedgep = dynamic_cast<const SplitEdge*>(edgep);
if (!oedgep) v3fatalSrc("Following edge of non-SplitEdge type");
const SplitEdge* const oedgep = edgep->as<SplitEdge>();
if (oedgep->ignoreThisStep()) return false;
return oedgep->followScoreboard();
}
static bool followCyclic(const V3GraphEdge* edgep) {
const SplitEdge* const oedgep = dynamic_cast<const SplitEdge*>(edgep);
if (!oedgep) v3fatalSrc("Following edge of non-SplitEdge type");
const SplitEdge* const oedgep = edgep->as<SplitEdge>();
return (!oedgep->ignoreThisStep());
}
string dotStyle() const override {
@@ -187,6 +191,7 @@ public:
uint32_t SplitEdge::s_stepNum = 0;
class SplitPostEdge final : public SplitEdge {
VL_RTTI_IMPL(SplitPostEdge, SplitEdge)
public:
SplitPostEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top)
: SplitEdge{graphp, fromp, top, WEIGHT_NORMAL} {}
@@ -196,6 +201,7 @@ public:
};
class SplitLVEdge final : public SplitEdge {
VL_RTTI_IMPL(SplitLVEdge, SplitEdge)
public:
SplitLVEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top)
: SplitEdge{graphp, fromp, top, WEIGHT_NORMAL} {}
@@ -205,6 +211,7 @@ public:
};
class SplitRVEdge final : public SplitEdge {
VL_RTTI_IMPL(SplitRVEdge, SplitEdge)
public:
SplitRVEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top)
: SplitEdge{graphp, fromp, top, WEIGHT_NORMAL} {}
@@ -213,7 +220,8 @@ public:
string dotColor() const override { return "green"; }
};
struct SplitScorebdEdge : public SplitEdge {
class SplitScorebdEdge final : public SplitEdge {
VL_RTTI_IMPL(SplitScorebdEdge, SplitEdge)
public:
SplitScorebdEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top)
: SplitEdge{graphp, fromp, top, WEIGHT_NORMAL} {}
@@ -222,7 +230,8 @@ public:
string dotColor() const override { return "blue"; }
};
struct SplitStrictEdge : public SplitEdge {
class SplitStrictEdge final : public SplitEdge {
VL_RTTI_IMPL(SplitStrictEdge, SplitEdge)
// A strict order, based on the original statement order in the graph
// The only non-cutable edge type
public:
@@ -316,14 +325,14 @@ protected:
void pruneDepsOnInputs() {
for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); vertexp;
vertexp = vertexp->verticesNextp()) {
if (!vertexp->outBeginp() && dynamic_cast<SplitVarStdVertex*>(vertexp)) {
if (!vertexp->outBeginp() && vertexp->is<SplitVarStdVertex>()) {
if (debug() >= 9) {
const SplitVarStdVertex* const stdp = static_cast<SplitVarStdVertex*>(vertexp);
UINFO(0, "Will prune deps on var " << stdp->nodep() << endl);
stdp->nodep()->dumpTree("- ");
}
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
SplitEdge* const oedgep = dynamic_cast<SplitEdge*>(edgep);
SplitEdge* const oedgep = edgep->as<SplitEdge>();
oedgep->setIgnoreThisStep();
}
}
@@ -474,17 +483,16 @@ protected:
// vertexes not involved with this step as unimportant
for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); vertexp;
vertexp = vertexp->verticesNextp()) {
if (const SplitLogicVertex* const vvertexp
= dynamic_cast<SplitLogicVertex*>(vertexp)) {
if (!vvertexp->user()) {
if (!vertexp->user()) {
if (const SplitLogicVertex* const vvertexp = vertexp->cast<SplitLogicVertex>()) {
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep;
edgep = edgep->inNextp()) {
SplitEdge* const oedgep = dynamic_cast<SplitEdge*>(edgep);
SplitEdge* const oedgep = edgep->as<SplitEdge>();
oedgep->setIgnoreThisStep();
}
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep;
edgep = edgep->outNextp()) {
SplitEdge* const oedgep = dynamic_cast<SplitEdge*>(edgep);
SplitEdge* const oedgep = edgep->as<SplitEdge>();
oedgep->setIgnoreThisStep();
}
}
@@ -903,7 +911,7 @@ protected:
// inputs) prune all edges that depend on the 'if'.
for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); vertexp;
vertexp = vertexp->verticesNextp()) {
const SplitLogicVertex* const logicp = dynamic_cast<SplitLogicVertex*>(vertexp);
const SplitLogicVertex* const logicp = vertexp->cast<const SplitLogicVertex>();
if (!logicp) continue;
const AstNodeIf* const ifNodep = VN_CAST(logicp->nodep(), NodeIf);
@@ -911,7 +919,7 @@ protected:
bool pruneMe = true;
for (V3GraphEdge* edgep = logicp->outBeginp(); edgep; edgep = edgep->outNextp()) {
const SplitEdge* const oedgep = dynamic_cast<SplitEdge*>(edgep);
const SplitEdge* const oedgep = edgep->as<const SplitEdge>();
if (!oedgep->ignoreThisStep()) {
// This if conditional depends on something we can't
// prune -- a variable generated in the current block.
@@ -921,7 +929,7 @@ protected:
// give a hint about why...
if (debug() >= 9) {
V3GraphVertex* vxp = oedgep->top();
const SplitNodeVertex* const nvxp = dynamic_cast<SplitNodeVertex*>(vxp);
const SplitNodeVertex* const nvxp = vxp->as<const SplitNodeVertex>();
UINFO(0, "Cannot prune if-node due to edge "
<< oedgep << " pointing to node " << nvxp->nodep() << endl);
nvxp->nodep()->dumpTree("- ");
@@ -935,7 +943,7 @@ protected:
// This if can be split; prune dependencies on it.
for (V3GraphEdge* edgep = logicp->inBeginp(); edgep; edgep = edgep->inNextp()) {
SplitEdge* const oedgep = dynamic_cast<SplitEdge*>(edgep);
SplitEdge* const oedgep = edgep->as<SplitEdge>();
oedgep->setIgnoreThisStep();
}
}