Speed up Dfg common sub-expression elimination

Added a DfgVertex::user() mechanism for storing data in vertices.
Similar in spirit to AstNode user data, but the generation counter is
stored in the DfgGraph the vertex is held under. Use this to cache
DfgVertex::hash results, and also speed up DfgVertex hashing in general.

Use these and additional improvements to speed up CSE.
This commit is contained in:
Geza Lore
2022-10-06 19:59:01 +01:00
parent 97add4d57a
commit 4f0158b5e0
5 changed files with 132 additions and 66 deletions
+22 -14
View File
@@ -77,28 +77,36 @@ V3DfgOptimizationContext::~V3DfgOptimizationContext() {
// Common subexpression elimination
void V3DfgPasses::cse(DfgGraph& dfg, V3DfgCseContext& ctx) {
DfgVertex::HashCache hashCache;
DfgVertex::EqualsCache equalsCache;
std::unordered_multimap<V3Hash, DfgVertex*> verticesWithEqualHashes;
std::unordered_map<V3Hash, std::vector<DfgVertex*>> verticesWithEqualHashes;
verticesWithEqualHashes.reserve(dfg.size());
// Used by DfgVertex::hash
const auto userDataInUse = dfg.userDataInUse();
// In reverse, as the graph is sometimes in reverse topological order already
dfg.forEachVertexInReverse([&](DfgVertex& vtx) {
for (DfgVertex *vtxp = dfg.verticesRbegin(), *nextp; vtxp; vtxp = nextp) {
nextp = vtxp->verticesPrev();
if (VL_LIKELY(nextp)) VL_PREFETCH_RW(nextp);
// Don't merge constants
if (vtx.is<DfgConst>()) return;
if (vtxp->is<DfgConst>()) continue;
// For everything else...
const V3Hash hash = vtx.hash(hashCache);
auto pair = verticesWithEqualHashes.equal_range(hash);
for (auto it = pair.first, end = pair.second; it != end; ++it) {
DfgVertex* const candidatep = it->second;
if (candidatep->equals(vtx, equalsCache)) {
std::vector<DfgVertex*>& vec = verticesWithEqualHashes[vtxp->hash()];
bool replaced = false;
for (DfgVertex* const candidatep : vec) {
if (candidatep->equals(*vtxp, equalsCache)) {
++ctx.m_eliminated;
vtx.replaceWith(candidatep);
vtx.unlinkDelete(dfg);
return;
vtxp->replaceWith(candidatep);
vtxp->unlinkDelete(dfg);
replaced = true;
break;
}
}
verticesWithEqualHashes.emplace(hash, &vtx);
});
if (replaced) continue;
vec.push_back(vtxp);
}
}
void V3DfgPasses::removeVars(DfgGraph& dfg, DfgRemoveVarsContext& ctx) {