53 #include "config_HAVE_HOST_PROFILING_BUILT.hpp" 57 #include <boost/graph/depth_first_search.hpp> 58 #include <boost/graph/graph_traits.hpp> 78 #if HAVE_HOST_PROFILING_BUILT 120 : vertex_level(_vertex_level),
121 dfs_order(_dfs_order),
123 max_level(_max_level),
124 parent_depth_search_spanning_tree(_parent_depth_search_spanning_tree),
125 debug_level(parameters->get_class_debug_level(
GET_CLASS(*this)))
129 template <
class Vertex,
class Graph>
133 "---Discovered vertex BB" +
STR(g.CGetBBNodeInfo(v)->block->number));
135 dfs_order[v] = dfs_number++;
137 if(v == g.CGetBBGraphInfo()->entry_vertex)
144 typename boost::graph_traits<Graph>::in_edge_iterator ei, ei_end;
145 unsigned int new_level = 0;
146 for(boost::tie(ei, ei_end) = boost::in_edges(v, g); ei != ei_end; ++ei)
148 vertex source = boost::source(*ei, g);
149 if(vertex_level.find(source) != vertex_level.end())
151 unsigned int source_level = vertex_level[source];
154 new_level = source_level + 1;
158 if(source_level + 1 < new_level)
160 new_level = source_level + 1;
165 THROW_ASSERT(new_level > 0,
"Cannot determine a proper vertex level");
166 vertex_level[v] = new_level;
167 if(new_level > max_level)
169 max_level = new_level;
174 template <
class Edge,
class Graph>
178 src = boost::source(e, g);
180 parent_depth_search_spanning_tree[tgt] = src;
199 (*loop)->ComputeLandingPadExits();
206 return l.find(vp) != l.end();
211 return ((x != y && y == parent_depth_search_spanning_tree(x)) ||
212 (x != parent_depth_search_spanning_tree(x) &&
213 check_ancestor(parent_depth_search_spanning_tree(x), y, parent_depth_search_spanning_tree)));
218 const BasicBlocksGraphConstructorRef bbcg =
FB->bbgc;
238 for(boost::tie(ei, ei_end) =
boost::edges(*cfg); ei != ei_end; ++ei)
240 vertex source = boost::source(*ei, *cfg);
249 if(full_dom.find(target) == full_dom.end())
256 if(dom_set.find(source) != dom_set.end())
270 cj_edges.insert(cj_edge);
275 bj_edges.insert(bj_edge);
290 unsigned int max_level = 0;
296 parent_depth_search_spanning_tree[entry] = entry;
299 std::vector<boost::default_color_type> color_vec(boost::num_vertices(*djg));
301 boost::depth_first_visit(
303 boost::make_iterator_property_map(color_vec.begin(), boost::get(boost::vertex_index, *djg), boost::white_color));
304 std::vector<std::list<vertex>> level_vertices_rel(max_level + 1);
306 for(
auto vl_pair : vertex_level_rel)
308 auto& curr_list = level_vertices_rel[vl_pair.second];
309 auto pos = curr_list.begin();
310 const auto pos_end = curr_list.end();
311 while(pos_end != pos && dfs_order.find(vl_pair.first)->second > dfs_order.find(*pos)->second)
317 curr_list.push_back(vl_pair.first);
321 curr_list.insert(pos, vl_pair.first);
327 for(boost::tie(ei, ei_end) =
boost::edges(*djg); ei != ei_end; ++ei)
329 vertex source = boost::source(*ei, *djg);
332 if(source == target ||
check_ancestor(source, target, parent_depth_search_spanning_tree))
336 sp_back_edges.insert(sp_edge);
342 unsigned int lev =
index - 1;
344 bool irreducible =
false;
345 for(
auto v : level_vertices_rel[lev])
348 "Considering BB" + std::to_string(cfg->
CGetBBNodeInfo(v)->block->number));
350 bool reducible =
false;
352 graph::in_edge_iterator e_iter, e_iter_end;
353 for(boost::tie(e_iter, e_iter_end) = boost::in_edges(v, *djg); e_iter != e_iter_end; ++e_iter)
355 vertex m = boost::source(*e_iter, *djg);
361 "Irreducible loop found: SP-BACK-EDGE=" + std::to_string(cfg->
CGetBBNodeInfo(m)->block->number) +
374 "Found a reducible Loop: SP-BACK-EDGE=" + std::to_string(cfg->
CGetBBNodeInfo(m)->block->number) +
395 curr_loop->get_recursively_bb(blocks);
396 for(
auto curr_sp_back_edge : sp_back_edges)
398 if(blocks.find(curr_sp_back_edge.first) != blocks.end() &&
399 blocks.find(curr_sp_back_edge.second) != blocks.end())
401 curr_loop->add_sp_back_edge(curr_sp_back_edge.first, curr_sp_back_edge.second);
402 if(!curr_loop->IsReducible())
404 curr_loop->add_entry(curr_sp_back_edge.second);
406 for(
auto cur_bb : blocks)
410 curr_loop->add_entry(cur_bb);
416 THROW_ASSERT(curr_loop->get_sp_back_edges().size() > 0,
"wrongly computed loop back edges");
424 graph::in_edge_iterator e_iter, e_iter_end;
426 if(real_node == header)
430 visited.insert(real_node);
444 if(innermost_loop->
Parent() ==
nullptr)
454 for(boost::tie(e_iter, e_iter_end) = boost::in_edges(real_node, *djg); e_iter != e_iter_end; ++e_iter)
456 vertex source = boost::source(*e_iter, *djg);
457 if(visited.find(source) == visited.end())
465 std::vector<std::list<vertex>>& level_vertices_rel)
468 "-->Detecting irreducible loop - Min level " +
STR(min_level) +
" - Max level " +
STR(max_level));
474 for(
auto v : level_vertices_rel[
level])
477 "---Inserting BB" +
STR(djg->
CGetBBNodeInfo(v)->block->number) +
" into set to be analyzed");
482 THROW_ASSERT(u.size() > 0,
"There must be at least one item in u");
485 unsigned int max_dfs = 0;
486 vertex min_ord_ver = *(u.begin());
489 "DetectIrreducibleLoop: starting vertex=" +
494 tarjan_scc(djg, min_ord_ver, dfs_order, lowlink, s, u, max_dfs);
504 auto stack_iter = stack.begin();
505 auto stack_end = stack.end();
507 for(; stack_iter != stack_end; ++stack_iter)
509 vertex current_node = *stack_iter;
510 if(current_node == v)
522 dfs_order[v] = max_dfs++;
523 lowlink[v] = dfs_order[v];
527 graph::out_edge_iterator e_out_iter, e_out_iter_end;
528 for(boost::tie(e_out_iter, e_out_iter_end) = boost::out_edges(v, *djg); e_out_iter != e_out_iter_end; ++e_out_iter)
532 if(u.find(target) != u.end())
534 tarjan_scc(djg, target, dfs_order, lowlink, s, u, max_dfs);
535 lowlink[v] = lowlink[v] < lowlink[
target] ? lowlink[v] : lowlink[
target];
539 lowlink[v] = lowlink[v] < dfs_order[
target] ? lowlink[v] : dfs_order[
target];
543 if(s.back() == v && lowlink[v] == dfs_order[v])
547 else if(lowlink[v] == dfs_order[v])
561 candidate_body_loop.insert(real_node);
565 for(
const auto candidate : candidate_body_loop)
568 "-->Analyzing candidate BB" +
STR(djg->
CGetBBNodeInfo(candidate)->block->number));
571 const auto candidate_nesting_loop =
block_to_loop.find(candidate)->second;
572 if(candidate_nesting_loop->GetHeader() == candidate and not candidate_nesting_loop->Parent())
575 nested_loops.insert(candidate_nesting_loop);
585 real_body_loop.insert(candidate);
588 if(real_body_loop.size())
592 "-->Creating data structure for irreducible loop " +
STR(l->
GetId()));
593 for(
const auto body_loop_vertex : real_body_loop)
600 for(
const auto& nested_loop : nested_loops)
603 "---Setting " +
STR(l->
GetId()) +
" as parent of " +
STR(nested_loop->GetId()));
604 nested_loop->SetParent(l);
610 "<--Created data structure for irreducible loop " +
STR(l->
GetId()));
612 "<--Checking if we have to build a new irreducible loop: Yes");
617 "<--Checking if we have to build a new irreducible loop: No");
634 std::list<LoopConstRef>::const_iterator it, it_end;
638 if((*it)->GetId() == id)
644 return LoopConstRef();
649 std::list<LoopRef>::const_iterator it, it_end;
653 if((*it)->GetId() == id)
668 #
if HAVE_HOST_PROFILING_BUILT
670 const ProfilingInformationConstRef profiling_information
674 auto output_directory =
Param->getOption<std::string>(OPT_dot_directory);
675 output_directory +=
FB->CGetBehavioralHelper()->get_function_name() +
"/";
677 std::ofstream dot((output_directory + file_name).c_str());
678 dot <<
"digraph LoopForest {" << std::endl;
681 dot << loop->GetId() <<
" [label=\"LoopId=" << loop->GetId() <<
" - Depth: " << loop->depth;
682 #if HAVE_HOST_PROFILING_BUILT 683 if(profiling_information)
685 dot <<
"\\nAvg. Iterations=" << profiling_information->GetLoopAvgIterations(loop)
686 <<
"- Max Iterations=" << profiling_information->GetLoopMaxIterations(loop->GetId());
692 dot <<
" Single-Exit";
716 dot <<
" Countable[" <<
STR(loop->lower_bound) <<
":" <<
STR(loop->increment) <<
":" <<
STR(loop->upper_bound)
717 << (loop->close_interval ?
"]" :
")");
721 dot <<
" Pipelinable";
726 for(bb = blocks.begin(); bb != bb_end; ++bb)
728 dot <<
" BB" + std::to_string(cfg->
CGetBBNodeInfo(*bb)->block->number);
730 dot <<
"\\n\"];" << std::endl;
732 for(
const auto& loop : const_loops_list)
734 for(
const auto& child : loop->GetChildren())
736 dot << loop->GetId() <<
"->" << child->GetId() <<
";" << std::endl;
739 dot <<
"}" << std::endl;
746 for(child = children.begin(); child != child_end; ++child)
748 auto* child_loop =
const_cast<Loop*
>(child->get());
749 child_loop->
depth = loop->depth + 1;
760 for(boost::tie(v, v_end) = boost::vertices(*cfg); v != v_end; v++)
762 zero_loop->
blocks.insert(*v);
777 if(not(*loop)->Parent())
779 (*loop)->parent_loop = zero_loop;
782 (*loop)->get_recursively_bb(children_blocks);
784 for(child_block = children_blocks.begin(); child_block != child_block_end; ++child_block)
786 if(zero_loop->
blocks.find(*child_block) != zero_loop->
blocks.end())
788 zero_loop->
blocks.erase(zero_loop->
blocks.find(*child_block));
void SetParent(LoopRef parent)
Sets parent for this loop.
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
bool is_innermost_loop
tells if there aren't loop nested in this
Vertex get_immediate_dominator(Vertex v) const
Return the immediate dominator of a Vertex.
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
static bool check_ancestor(vertex x, vertex y, const vertex2obj< vertex > &parent_depth_search_spanning_tree)
void AddChild(LoopRef child)
Adds a child loop.
void BuildZeroLoop()
Creates Loop zero data structure.
Basic block control flow graph.
File containing functions and utilities to support the printing of debug messagges.
#define PRINT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
djgraph_dfs_tree_visitor(CustomUnorderedMap< vertex, unsigned int > &_vertex_level, CustomUnorderedMap< vertex, unsigned int > &_dfs_order, unsigned int &_max_level, vertex2obj< vertex > &_parent_depth_search_spanning_tree, const ParameterConstRef parameters)
Constructor of the postorder tree visitor.
const LoopRef Parent() const
returns the parent loop
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
std::string get_function_name() const
Return the name of the function.
#define PIPELINABLE_LOOP
pipelinable loop
const int debug_level
The debug level.
void WriteDot(const std::string &file_name, const int detail_level=0) const
Writes this graph in dot format.
const CustomUnorderedMapStable< Vertex, CustomOrderedSet< Vertex > > getAllDominated() const
Returns a map containing, for each Vertex, a set formed by all the vertices dominated by it (all the ...
const BBGraphInfoConstRef CGetBBGraphInfo() const
Returns the property associated with the graph.
#define COUNTABLE_LOOP
countable loop
Class specification of the graph structures.
Data structures used to manage set of vertexes.
exceptions managed by PandA
void add_block(vertex block)
adds a block to this loop
CustomUnorderedMap< vertex, unsigned int > & dfs_order
dfs order of vertices
size_t NumLoops() const
Returns the number of loops.
CustomOrderedSet< LoopConstRef > children
Child loops.
This class provides methods to build a basic blocks graph.
Data structure describing a basic block at tree level.
void tree_edge(Edge e, const Graph &g) const
redefinition of map to manage ordered/unordered structures
#define UNKNOWN_LOOP
unknown loop
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
#define WHILE_LOOP
while or for loop
boost::graph_traits< graph >::edge_iterator EdgeIterator
edge_iterator definition.
CustomUnorderedSet< vertex > blocks
Blocks which belong to this loop.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
void computeDepth(const LoopConstRef loop)
Sets depth for each loop in the forest starting from loop.
#define J_SELECTOR
j graph edge selector for dj graph (used during loop computation)
vertex2obj< vertex > & parent_depth_search_spanning_tree
spanning tree
absl::flat_hash_map< T, U, Hash, Eq, Alloc > CustomUnorderedMap
bool is_edge_in_list(CustomUnorderedSet< vertex_pair > &l, vertex source, vertex target)
CustomUnorderedMap< vertex, unsigned int > & vertex_level
topological level of the vertices
std::list< LoopRef > modifiable_loops_list
List of found loops.
bool stack_contains(std::list< vertex > stack, vertex v)
Basic block control flow graph with feedback.
redefinition of set to manage ordered/unordered structures
int debug_level
Debug level.
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
void discover_vertex(Vertex v, Graph &g)
void tarjan_scc(const BBGraphRef djg, vertex v, CustomUnorderedMap< vertex, unsigned int > &dfs_order, CustomUnorderedMap< vertex, unsigned int > &lowlink, std::list< vertex > &s, CustomOrderedSet< vertex > &u, unsigned int &max_dfs)
boost::graph_traits< graph >::vertex_iterator VertexIterator
vertex_iterator definition.
unsigned int dfs_number
last label used during the dfs graph visiting
#define DEBUG_LEVEL_NONE
no debugging print is performed.
unsigned int & max_level
maximum level of vertices
unsigned int GetId() const
returns the loop id
const std::list< LoopConstRef > & GetList() const
Returns the list of loops (const)
#define DO_WHILE_LOOP
do while loop
const std::list< LoopRef > & GetModifiableList() const
Return the list of loops.
const LoopConstRef CGetLoop(unsigned int id) const
Returns a loop given the id.
DJ basic block graph (used for loop computation)
Collect all structs used to write a graph in the dot format.
Class specification of the basic_block structure.
This file collects some hash functors.
const BBNodeInfoConstRef CGetBBNodeInfo(const vertex node) const
Return the info associated with a basic block.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
refcount< Loop > LoopRef
refcount definition of the class
interface of loops finding algorithm
const ParameterConstRef Param
class containing all the parameters
void DetectLoops()
Computes the loops of the control flow graph.
void DetectReducibleLoop(const BBGraphRef djg, CustomOrderedSet< vertex > &visited, LoopRef loop, vertex node, vertex header)
Reducible loop construction.
this class is used to manage the command-line or XML options.
const LoopRef GetLoop(unsigned int id)
Returns a loop given the id.
std::pair< vertex, vertex > vertex_pair
#define DOALL_LOOP
parallelizable for loop
x
Return the smallest n such that 2^n >= _x.
std::list< LoopConstRef > const_loops_list
unsigned int depth
Nesting depth of this loop.
void WriteDot(const std::string &file_name) const
Write dot files representing the loop forest.
CustomUnorderedMap< vertex, LoopRef > block_to_loop
Maps between basic block and loop to which it belongs.
#define SINGLE_EXIT_LOOP
loop with single exit
A brief description of the C++ Header File.
void DetectIrreducibleLoop(const BBGraphRef djg, unsigned int min_level, unsigned int max_level, std::vector< std::list< vertex >> &level_vertices_rel)
const FunctionBehaviorRef FB
The function behavior.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...