19#ifndef BF_P4C_MAU_TABLE_FLOW_GRAPH_H_
20#define BF_P4C_MAU_TABLE_FLOW_GRAPH_H_
26#include <boost/graph/adjacency_list.hpp>
27#include <boost/graph/transitive_closure.hpp>
29#include "backends/tofino/bf-p4c/ir/control_flow_visitor.h"
30#include "backends/tofino/bf-p4c/lib/boost_graph.h"
31#include "backends/tofino/bf-p4c/mau/mau_visitor.h"
34enum vertex_table_t { vertex_table };
35BOOST_INSTALL_PROPERTY(vertex, table);
37enum edge_annotation_t { edge_annotation };
38BOOST_INSTALL_PROPERTY(edge, annotation);
46 typedef boost::adjacency_list<boost::vecS, boost::vecS,
47 boost::bidirectionalS,
49 boost::property<boost::vertex_table_t, const IR::MAU::Table *>,
51 boost::property<boost::edge_annotation_t, cstring>>
58 std::map<typename Graph::vertex_descriptor, typename Graph::vertex_descriptor> *parent =
68 typename Graph::vertex_descriptor dst;
71 void examine_edge(
typename Graph::edge_descriptor e,
const Graph &
g) {
72 auto src = boost::source(e,
g);
73 auto dst = boost::target(e,
g);
75 if (!parent->count(dst)) (*parent)[dst] = src;
76 if (dst == this->dst)
throw done{};
81 std::vector<typename Graph::vertex_descriptor> find_path(
82 typename Graph::vertex_descriptor src,
typename Graph::vertex_descriptor dst) {
83 std::map<typename Graph::vertex_descriptor, typename Graph::vertex_descriptor> parent;
84 this->parent = &parent;
88 boost::breadth_first_search(graph, src, boost::visitor(*
this));
89 }
catch (done
const &) {
92 std::vector<typename Graph::vertex_descriptor> result;
93 if (parent.count(dst)) {
96 result.emplace_back(cur);
99 result.emplace_back(cur);
100 }
while (cur != src);
103 for (
unsigned i = 0; i < result.size() / 2; ++i) {
104 std::swap(result[i], result[result.size() - i - 1]);
109 this->parent =
nullptr;
122 typename Graph::vertex_descriptor
v_sink;
124 std::optional<gress_t> gress;
135 mutable std::optional<std::map<const IR::MAU::Table *, std::set<const IR::MAU::Table *>>>
141 bool emptyFlowGraph =
true;
145 return boost::get(boost::edge_annotation,
g)[edge];
149 gress = std::nullopt;
154 :
g(
std::move(other.
g)),
155 gress(
std::move(other.gress)),
160 emptyFlowGraph(
std::move(other.emptyFlowGraph)),
171 emptyFlowGraph(other.emptyFlowGraph),
176 std::map<const IR::MAU::Table *, typename Graph::vertex_descriptor>
tableToVertex;
179 std::map<typename Graph::vertex_descriptor, const IR::MAU::Table *>
vertexToTable;
183 auto all_vertices = boost::vertices(
g);
184 if (++all_vertices.first == all_vertices.second) {
193 gress = std::nullopt;
194 reachability.
clear();
199 emptyFlowGraph =
true;
202 void add_sink_vertex() {
211 bool can_reach(
const IR::MAU::Table *t1,
const IR::MAU::Table *t2)
const {
212 if (t2 ==
nullptr)
return true;
213 if (t1 ==
nullptr)
return false;
216 return reachability.
canReach(v1, v2);
222 const std::set<const IR::MAU::Table *>
get_dominators(
const IR::MAU::Table *table)
const;
233 std::vector<const IR::MAU::Table *>
find_path(
const IR::MAU::Table *src,
234 const IR::MAU::Table *dst) {
236 std::vector<const IR::MAU::Table *> result;
237 for (
auto node : path) {
245 const IR::MAU::Table *
get_vertex(
typename Graph::vertex_descriptor v)
const {
246 return boost::get(boost::vertex_table,
g)[v];
250 typename Graph::vertex_descriptor
get_vertex(
const IR::MAU::Table *tbl)
const {
252 tbl->externalName());
261 typename Graph::vertex_descriptor
add_vertex(
const IR::MAU::Table *table) {
263 if (table !=
nullptr && gress == std::nullopt) gress = table->gress;
270 auto v = boost::add_vertex(table,
g);
273 if (table)
tables.insert(table);
277 if (table !=
nullptr) emptyFlowGraph =
false;
284 std::pair<typename Graph::edge_descriptor, bool>
add_edge(
const IR::MAU::Table *src,
285 const IR::MAU::Table *dst,
287 typename Graph::vertex_descriptor src_v, dst_v;
292 typename Graph::out_edge_iterator out, end;
293 for (boost::tie(out, end) = boost::out_edges(src_v,
g); out != end; ++out) {
294 if (boost::target(*out,
g) == dst_v)
return {*out,
false};
298 auto maybe_new_e = boost::add_edge(src_v, dst_v,
g);
299 if (!maybe_new_e.second)
302 BUG(
"Boost Graph Library failed to add edge.");
303 boost::get(boost::edge_annotation,
g)[maybe_new_e.first] = edge_label;
304 return {maybe_new_e.first,
true};
307 std::vector<const IR::MAU::Table *> topological_sort()
const {
308 std::vector<Graph::vertex_descriptor> internal_result;
309 boost::topological_sort(
g, std::back_inserter(internal_result));
313 std::vector<const IR::MAU::Table *> result;
314 for (
auto it = internal_result.rbegin(); it != internal_result.rend(); ++it) {
324 virtual void dump(std::ostream &,
const IR::MAU::Table *)
const {}
327 static std::string viz_node_name(
const IR::MAU::Table *tbl);
328 void dump_viz(std::ostream &out,
const DumpTableDetails *details =
nullptr);
363 const IR::MAU::Table *next_table;
367 std::pair<bool, cstring> next_incomplete(
const IR::MAU::Table *t);
370 bool preorder(
const IR::MAU::TableSeq *)
override;
371 bool preorder(
const IR::MAU::Table *)
override;
372 bool preorder(
const IR::MAU::Action *)
override;
373 void end_apply()
override;
379 visitDagOnce =
false;
390 bool preorder(
const IR::MAU::TableSeq *)
override;
391 bool preorder(
const IR::BFN::Deparser *)
override;
Computes a table control-flow graph for the IR.
Definition table_flow_graph.h:346
Computes a table control-flow graph for each gress in the IR.
Definition table_flow_graph.h:384
Custom BFS visitor for finding a shortest path between two nodes.
Definition table_flow_graph.h:55
Definition mau_visitor.h:29
Definition ordered_map.h:32
Definition boost_graph.h:39
void setSink(std::optional< Vertex > sink)
Sets the sink node; no nodes will be considered reachable from this node.
Definition boost_graph.h:68
void clear()
Definition boost_graph.h:62
bool canReach(Vertex v1, Vertex v2)
Determines whether vertex v2 is reachable from the vertex v1.
Definition boost_graph.h:47
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
Definition table_flow_graph.h:33
Definition table_flow_graph.h:323
Definition table_flow_graph.h:45
const std::set< const IR::MAU::Table * > get_dominators(const IR::MAU::Table *table) const
Definition mau/table_flow_graph.cpp:84
Graph::vertex_descriptor v_source
The source node, representing the entry point (i.e., entry from the parser).
Definition table_flow_graph.h:119
bool is_empty() const
Determines whether this graph is empty.
Definition table_flow_graph.h:182
Graph g
The underlying Boost graph backing this FlowGraph.
Definition table_flow_graph.h:116
bool can_reach(const IR::MAU::Table *t1, const IR::MAU::Table *t2) const
Definition table_flow_graph.h:211
const std::set< const IR::MAU::Table * > get_tables() const
Definition table_flow_graph.h:257
Graph::vertex_descriptor get_vertex(const IR::MAU::Table *tbl) const
Definition table_flow_graph.h:250
BFSPathFinder path_finder
Helper for find_path.
Definition table_flow_graph.h:228
void clear()
Clears the state in this FlowGraph.
Definition table_flow_graph.h:191
friend std::ostream & operator<<(std::ostream &, const FlowGraph &)
Definition mau/table_flow_graph.cpp:23
std::map< typename Graph::vertex_descriptor, const IR::MAU::Table * > vertexToTable
Reverse map of above.
Definition table_flow_graph.h:179
ordered_map< const IR::MAU::Table *, int > tableToVertexIndex
Maps each table to its corresponding vertex ID in the Boost graph.
Definition table_flow_graph.h:129
std::optional< std::map< const IR::MAU::Table *, std::set< const IR::MAU::Table * > > > dominators
The dominator set for each table in the graph. Lazily computed.
Definition table_flow_graph.h:136
Graph::vertex_descriptor v_sink
The sink node, representing the exit point (i.e., entry to the deparser).
Definition table_flow_graph.h:122
std::pair< typename Graph::edge_descriptor, bool > add_edge(const IR::MAU::Table *src, const IR::MAU::Table *dst, const cstring edge_label)
Definition table_flow_graph.h:284
std::vector< const IR::MAU::Table * > find_path(const IR::MAU::Table *src, const IR::MAU::Table *dst)
Definition table_flow_graph.h:233
const cstring get_ctrl_dependency_info(typename Graph::edge_descriptor edge) const
Definition table_flow_graph.h:144
const IR::MAU::Table * get_vertex(typename Graph::vertex_descriptor v) const
Definition table_flow_graph.h:245
std::map< const IR::MAU::Table *, typename Graph::vertex_descriptor > tableToVertex
Maps each table to its associated graph vertex.
Definition table_flow_graph.h:176
bool is_always_reached(const IR::MAU::Table *) const
Determines whether the given table is executed on all paths.
Definition mau/table_flow_graph.cpp:163
Graph::vertex_descriptor add_vertex(const IR::MAU::Table *table)
Definition table_flow_graph.h:261
std::set< const IR::MAU::Table * > tables
All tables in this graph, excluding the nullptr table, used to represent the sink node.
Definition table_flow_graph.h:132