Skip to content

Commit

Permalink
SLP Vectorize
Browse files Browse the repository at this point in the history
  • Loading branch information
gezalore committed Apr 27, 2024
1 parent ab86782 commit d5114e7
Show file tree
Hide file tree
Showing 10 changed files with 587 additions and 15 deletions.
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ set(COMMON_SOURCES
V3DfgPasses.cpp
V3DfgPeephole.cpp
V3DfgRegularize.cpp
V3DfgVectorize.cpp
V3DupFinder.cpp
V3Timing.cpp
V3EmitCBase.cpp
Expand Down
1 change: 1 addition & 0 deletions src/Makefile_obj.in
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ RAW_OBJS_PCH_ASTNOMT = \
V3DfgPasses.o \
V3DfgPeephole.o \
V3DfgRegularize.o \
V3DfgVectorize.o \
V3DupFinder.o \
V3EmitCMain.o \
V3EmitCMake.o \
Expand Down
28 changes: 14 additions & 14 deletions src/V3Dfg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,14 @@ void DfgGraph::addGraph(DfgGraph& other) {
m_opVertices.splice(m_opVertices.end(), other.m_opVertices);
}

static const string toDotId(const DfgVertex& vtx) { return '"' + cvtToHex(&vtx) + '"'; }
const std::string DfgVertex::toDotId() const { return '"' + cvtToHex(this) + '"'; }

// Dump one DfgVertex in Graphviz format
static void dumpDotVertex(std::ostream& os, const DfgVertex& vtx) {

if (const DfgVarPacked* const varVtxp = vtx.cast<DfgVarPacked>()) {
AstVar* const varp = varVtxp->varp();
os << toDotId(vtx);
os << vtx.toDotId();
os << " [label=\"" << varp->name() << "\nW" << varVtxp->width() << " / F"
<< varVtxp->fanout() << '"';

Expand Down Expand Up @@ -90,7 +90,7 @@ static void dumpDotVertex(std::ostream& os, const DfgVertex& vtx) {
if (const DfgVarArray* const arrVtxp = vtx.cast<DfgVarArray>()) {
AstVar* const varp = arrVtxp->varp();
const int elements = VN_AS(arrVtxp->dtypep(), UnpackArrayDType)->elementsConst();
os << toDotId(vtx);
os << vtx.toDotId();
os << " [label=\"" << varp->name() << "[" << elements << "]\"";
if (varp->direction() == VDirection::INPUT) {
os << ", shape=box3d, style=filled, fillcolor=chartreuse2"; // Green
Expand All @@ -116,7 +116,7 @@ static void dumpDotVertex(std::ostream& os, const DfgVertex& vtx) {
if (const DfgConst* const constVtxp = vtx.cast<DfgConst>()) {
const V3Number& num = constVtxp->num();

os << toDotId(vtx);
os << vtx.toDotId();
os << " [label=\"";
if (num.width() <= 32 && !num.isSigned()) {
os << constVtxp->width() << "'d" << num.toUInt() << "\n";
Expand All @@ -133,7 +133,7 @@ static void dumpDotVertex(std::ostream& os, const DfgVertex& vtx) {
if (const DfgSel* const selVtxp = vtx.cast<DfgSel>()) {
const uint32_t lsb = selVtxp->lsb();
const uint32_t msb = lsb + selVtxp->width() - 1;
os << toDotId(vtx);
os << vtx.toDotId();
os << " [label=\"SEL\n_[" << msb << ":" << lsb << "]\nW" << vtx.width() << " / F"
<< vtx.fanout() << '"';
if (vtx.hasMultipleSinks()) {
Expand All @@ -145,7 +145,7 @@ static void dumpDotVertex(std::ostream& os, const DfgVertex& vtx) {
return;
}

os << toDotId(vtx);
os << vtx.toDotId();
os << " [label=\"" << vtx.typeName() << "\nW" << vtx.width() << " / F" << vtx.fanout() << '"';
if (vtx.hasMultipleSinks()) {
os << ", shape=doublecircle";
Expand All @@ -157,18 +157,18 @@ static void dumpDotVertex(std::ostream& os, const DfgVertex& vtx) {

// Dump one DfgEdge in Graphviz format
static void dumpDotEdge(std::ostream& os, const DfgEdge& edge, const string& headlabel) {
os << toDotId(*edge.sourcep()) << " -> " << toDotId(*edge.sinkp());
os << edge.sourcep()->toDotId() << " -> " << edge.sinkp()->toDotId();
if (!headlabel.empty()) os << " [headlabel=\"" << headlabel << "\"]";
os << "\n";
}

// Dump one DfgVertex and all of its source DfgEdges in Graphviz format
static void dumpDotVertexAndSourceEdges(std::ostream& os, const DfgVertex& vtx) {
dumpDotVertex(os, vtx);
vtx.forEachSourceEdge([&](const DfgEdge& edge, size_t idx) { //
void DfgVertex::dumpDotVertexAndSourceEdges(std::ostream& os) const {
dumpDotVertex(os, *this);
forEachSourceEdge([&](const DfgEdge& edge, size_t idx) {
if (edge.sourcep()) {
string headLabel;
if (vtx.arity() > 1 || vtx.is<DfgVertexVar>()) headLabel = vtx.srcName(idx);
if (arity() > 1 || is<DfgVertexVar>()) headLabel = srcName(idx);
dumpDotEdge(os, edge, headLabel);
}
});
Expand All @@ -183,7 +183,7 @@ void DfgGraph::dumpDot(std::ostream& os, const string& label) const {
os << "graph [rankdir=LR]\n";

// Emit all vertices
forEachVertex([&](const DfgVertex& vtx) { dumpDotVertexAndSourceEdges(os, vtx); });
forEachVertex([&](const DfgVertex& vtx) { vtx.dumpDotVertexAndSourceEdges(os); });

// Footer
os << "}\n";
Expand Down Expand Up @@ -228,13 +228,13 @@ static void dumpDotUpstreamConeFromVertex(std::ostream& os, const DfgVertex& vtx
itemp->forEachSource([&](const DfgVertex& src) { queue.push_back(&src); });

// Emit this vertex and all of its source edges
dumpDotVertexAndSourceEdges(os, *itemp);
itemp->dumpDotVertexAndSourceEdges(os);
}

// Emit all DfgVarPacked vertices that have external references driven by this vertex
vtx.forEachSink([&](const DfgVertex& dst) {
if (const DfgVarPacked* const varVtxp = dst.cast<DfgVarPacked>()) {
if (varVtxp->hasNonLocalRefs()) dumpDotVertexAndSourceEdges(os, dst);
if (varVtxp->hasNonLocalRefs()) dst.dumpDotVertexAndSourceEdges(os);
}
});
}
Expand Down
10 changes: 10 additions & 0 deletions src/V3Dfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,11 @@ class DfgVertex VL_NOT_FINAL {
// Fanout (number of sinks) of this vertex (expensive to compute)
uint32_t fanout() const VL_MT_DISABLED;

// If this vertex has a single sink, return it, otherwise return nullptr
DfgVertex* singleSink() {
return m_sinksp && !m_sinksp->m_nextp ? m_sinksp->sinkp() : nullptr;
}

// Unlink from container (graph or builder), then delete this vertex
void unlinkDelete(DfgGraph& dfg) VL_MT_DISABLED;

Expand Down Expand Up @@ -399,6 +404,11 @@ class DfgVertex VL_NOT_FINAL {

// Human-readable name for source operand with given index for debugging
virtual const string srcName(size_t idx) const = 0;

// Returns Graphviz id of this vertex.
const std::string toDotId() const;
// Dump this vertex and all it's source edges in Graphviz format to given stream 'os'.
void dumpDotVertexAndSourceEdges(std::ostream& os) const;
};

//------------------------------------------------------------------------------
Expand Down
4 changes: 4 additions & 0 deletions src/V3DfgPasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,10 @@ void V3DfgPasses::optimize(DfgGraph& dfg, V3DfgOptimizationContext& ctx) {
}
// Accumulate patterns for reporting
if (v3Global.opt.stats()) ctx.m_patternStats.accumulate(dfg);
apply(4, "vectorize", [&]() {
vectorize(dfg);
removeUnused(dfg);
});
apply(4, "regularize", [&]() { regularize(dfg, ctx.m_regularizeContext); });
if (dumpDfgLevel() >= 8) dfg.dumpDotAllVarConesPrefixed(ctx.prefix() + "optimized");
}
3 changes: 2 additions & 1 deletion src/V3DfgPasses.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,12 @@ void inlineVars(DfgGraph&) VL_MT_DISABLED;
void peephole(DfgGraph&, V3DfgPeepholeContext&) VL_MT_DISABLED;
// Regularize graph. This must be run before converting back to Ast.
void regularize(DfgGraph&, V3DfgRegularizeContext&) VL_MT_DISABLED;
// Vectorize compatible vertices
void vectorize(DfgGraph&);
// Remove unused nodes
void removeUnused(DfgGraph&) VL_MT_DISABLED;
// Eliminate (remove or replace) redundant variables. Also removes resulting unused logic.
void eliminateVars(DfgGraph&, V3DfgEliminateVarsContext&) VL_MT_DISABLED;

} // namespace V3DfgPasses

#endif
Loading

0 comments on commit d5114e7

Please sign in to comment.