PandA-2024.02
loops.cpp
Go to the documentation of this file.
1 /*
2  *
3  * _/_/_/ _/_/ _/ _/ _/_/_/ _/_/
4  * _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
5  * _/_/_/ _/_/_/_/ _/ _/_/ _/ _/ _/_/_/_/
6  * _/ _/ _/ _/ _/ _/ _/ _/ _/
7  * _/ _/ _/ _/ _/ _/_/_/ _/ _/
8  *
9  * ***********************************************
10  * PandA Project
11  * URL: http://panda.dei.polimi.it
12  * Politecnico di Milano - DEIB
13  * System Architectures Group
14  * ***********************************************
15  * Copyright (C) 2004-2024 Politecnico di Milano
16  *
17  * This file is part of the PandA framework.
18  *
19  * The PandA framework is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
49 #include "loops.hpp"
51 
53 #include "config_HAVE_HOST_PROFILING_BUILT.hpp"
54 
55 #include "custom_map.hpp"
56 #include "custom_set.hpp"
57 #include <boost/graph/depth_first_search.hpp>
58 #include <boost/graph/graph_traits.hpp>
59 #include <iosfwd>
60 #include <list>
61 #include <ostream> // for operator<<, basic_o...
62 #include <utility>
63 #include <vector>
64 
65 #include "Dominance.hpp"
66 #include "Parameter.hpp"
67 #include "Vertex.hpp"
68 #include "basic_block.hpp"
70 #include "behavioral_helper.hpp"
72 #include "dbgPrintHelper.hpp"
73 #include "exceptions.hpp"
74 #include "function_behavior.hpp"
75 #include "graph.hpp"
76 #include "hash_helper.hpp"
77 #include "loop.hpp"
78 #if HAVE_HOST_PROFILING_BUILT
80 #endif
81 #include "string_manipulation.hpp" // for STR GET_CLASS
82 #include "tree_basic_block.hpp"
83 
87 struct djgraph_dfs_tree_visitor : public boost::default_dfs_visitor
88 {
89  private:
92 
95 
97  unsigned int dfs_number;
98 
100  unsigned int& max_level;
101 
104 
106  const int debug_level;
107 
108  public:
118  CustomUnorderedMap<vertex, unsigned int>& _dfs_order, unsigned int& _max_level,
119  vertex2obj<vertex>& _parent_depth_search_spanning_tree, const ParameterConstRef parameters)
120  : vertex_level(_vertex_level),
121  dfs_order(_dfs_order),
122  dfs_number(0),
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)))
126  {
127  }
128 
129  template <class Vertex, class Graph>
130  void discover_vertex(Vertex v, Graph& g)
131  {
133  "---Discovered vertex BB" + STR(g.CGetBBNodeInfo(v)->block->number));
135  dfs_order[v] = dfs_number++;
137  if(v == g.CGetBBGraphInfo()->entry_vertex)
138  {
139  vertex_level[v] = 0;
140  }
141  else
142  {
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)
147  {
148  vertex source = boost::source(*ei, g);
149  if(vertex_level.find(source) != vertex_level.end())
150  {
151  unsigned int source_level = vertex_level[source];
152  if(new_level == 0)
153  {
154  new_level = source_level + 1;
155  }
156  else
157  {
158  if(source_level + 1 < new_level)
159  {
160  new_level = source_level + 1;
161  }
162  }
163  }
164  }
165  THROW_ASSERT(new_level > 0, "Cannot determine a proper vertex level");
166  vertex_level[v] = new_level;
167  if(new_level > max_level)
168  {
169  max_level = new_level;
170  }
171  }
172  }
173 
174  template <class Edge, class Graph>
175  void tree_edge(Edge e, const Graph& g) const
176  {
177  vertex src, tgt;
178  src = boost::source(e, g);
179  tgt = boost::target(e, g);
180  parent_depth_search_spanning_tree[tgt] = src;
181  }
182 };
183 
185  : FB(FunctionBehaviorRef(_FB.get(), null_deleter())),
186  Param(parameters),
187  debug_level(parameters->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE))
188 {
190  DetectLoops();
192  BuildZeroLoop();
194  computeDepth(GetLoop(0));
196  std::list<LoopRef>::const_iterator loop, loop_end = modifiable_loops_list.end();
197  for(loop = modifiable_loops_list.begin(); loop != loop_end; ++loop)
198  {
199  (*loop)->ComputeLandingPadExits();
200  }
201 }
202 
204 {
205  vertex_pair vp(source, target);
206  return l.find(vp) != l.end();
207 }
208 
209 static bool check_ancestor(vertex x, vertex y, const vertex2obj<vertex>& parent_depth_search_spanning_tree)
210 {
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)));
214 }
215 
217 {
218  const BasicBlocksGraphConstructorRef bbcg = FB->bbgc;
219  const BBGraphRef cfg = FB->GetBBGraph(FunctionBehavior::FBB);
220  const BehavioralHelperConstRef helper = FB->CGetBehavioralHelper();
221  const std::string function_name = helper->get_function_name();
222  const vertex entry = cfg->CGetBBGraphInfo()->entry_vertex;
223  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Starting Loops Detection of " + function_name);
224 
226  const dominance<BBGraph>* dom = FB->dominators;
227  const auto full_dom = dom->getAllDominated();
228 
232 
237  EdgeIterator ei, ei_end;
238  for(boost::tie(ei, ei_end) = boost::edges(*cfg); ei != ei_end; ++ei)
239  {
240  vertex source = boost::source(*ei, *cfg);
241  vertex target = boost::target(*ei, *cfg);
242 
243  if(source != dom->get_immediate_dominator(target))
244  {
245  bbcg->AddEdge(source, target, J_SELECTOR);
246 
248  bool cj;
249  if(full_dom.find(target) == full_dom.end())
250  {
251  cj = true;
252  }
253  else
254  {
255  const CustomOrderedSet<vertex>& dom_set = full_dom.find(target)->second;
256  if(dom_set.find(source) != dom_set.end())
257  {
259  cj = false;
260  }
261  else
262  {
264  cj = true;
265  }
266  }
267  if(cj)
268  {
269  vertex_pair cj_edge(source, target);
270  cj_edges.insert(cj_edge);
271  }
272  else
273  {
274  vertex_pair bj_edge(source, target);
275  bj_edges.insert(bj_edge);
276  }
277  }
278  }
279 
280  const BBGraphRef djg = FB->GetBBGraph(FunctionBehavior::DJ);
281 
283  {
284  djg->WriteDot("BB_DJ.dot");
285  }
286 
290  unsigned int max_level = 0;
291 
293  vertex2obj<vertex> parent_depth_search_spanning_tree;
294 
296  parent_depth_search_spanning_tree[entry] = entry;
297 
299  std::vector<boost::default_color_type> color_vec(boost::num_vertices(*djg));
300  djgraph_dfs_tree_visitor vis(vertex_level_rel, dfs_order, max_level, parent_depth_search_spanning_tree, Param);
301  boost::depth_first_visit(
302  *djg, entry, vis,
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)
307  {
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)
312  {
313  ++pos;
314  }
315  if(pos == pos_end)
316  {
317  curr_list.push_back(vl_pair.first);
318  }
319  else
320  {
321  curr_list.insert(pos, vl_pair.first);
322  }
323  }
324 
326  CustomUnorderedSet<vertex_pair> sp_back_edges;
327  for(boost::tie(ei, ei_end) = boost::edges(*djg); ei != ei_end; ++ei)
328  {
329  vertex source = boost::source(*ei, *djg);
330  vertex target = boost::target(*ei, *djg);
331 
332  if(source == target || check_ancestor(source, target, parent_depth_search_spanning_tree))
333  {
335  vertex_pair sp_edge(source, target);
336  sp_back_edges.insert(sp_edge);
337  }
338  }
339 
340  for(unsigned int index = max_level + 1; index > 0; --index)
341  {
342  unsigned int lev = index - 1;
343  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Level " + std::to_string(lev));
344  bool irreducible = false;
345  for(auto v : level_vertices_rel[lev])
346  {
348  "Considering BB" + std::to_string(cfg->CGetBBNodeInfo(v)->block->number));
349  const LoopRef loop = LoopRef(new Loop(cfg, v));
350  bool reducible = false;
351  CustomOrderedSet<vertex> visited;
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)
354  {
355  vertex m = boost::source(*e_iter, *djg);
356  vertex n = boost::target(*e_iter, *djg);
357  if(is_edge_in_list(cj_edges, m, n) && is_edge_in_list(sp_back_edges, m, n))
358  {
361  "Irreducible loop found: SP-BACK-EDGE=" + std::to_string(cfg->CGetBBNodeInfo(m)->block->number) +
362  "->" + std::to_string(cfg->CGetBBNodeInfo(n)->block->number));
363  irreducible = true;
364  }
365  if(is_edge_in_list(bj_edges, m, n))
366  {
367  reducible = true;
369  block_to_loop[n] = loop;
370  DetectReducibleLoop(djg, visited, loop, m, n);
371 
374  "Found a reducible Loop: SP-BACK-EDGE=" + std::to_string(cfg->CGetBBNodeInfo(m)->block->number) +
375  "->" + std::to_string(cfg->CGetBBNodeInfo(n)->block->number));
376  }
377  }
378  if(reducible)
379  {
380  modifiable_loops_list.push_back(loop);
381  const_loops_list.push_back(loop);
382  }
383  }
384  if(irreducible)
385  {
387  DetectIrreducibleLoop(djg, lev, max_level, level_vertices_rel);
388  }
389  }
390  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Ended Loops Detection of " + function_name);
391  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Adding spanning tree back edges at " + function_name);
392  for(const auto& curr_loop : modifiable_loops_list)
393  {
395  curr_loop->get_recursively_bb(blocks);
396  for(auto curr_sp_back_edge : sp_back_edges)
397  {
398  if(blocks.find(curr_sp_back_edge.first) != blocks.end() &&
399  blocks.find(curr_sp_back_edge.second) != blocks.end())
400  {
401  curr_loop->add_sp_back_edge(curr_sp_back_edge.first, curr_sp_back_edge.second);
402  if(!curr_loop->IsReducible())
403  {
404  curr_loop->add_entry(curr_sp_back_edge.second);
405  vertex entry_imm_dom = dom->get_immediate_dominator(curr_sp_back_edge.second);
406  for(auto cur_bb : blocks)
407  {
408  if(entry_imm_dom == dom->get_immediate_dominator(cur_bb))
409  {
410  curr_loop->add_entry(cur_bb);
411  }
412  }
413  }
414  }
415  }
416  THROW_ASSERT(curr_loop->get_sp_back_edges().size() > 0, "wrongly computed loop back edges");
417  }
418  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Added spanning tree back edges at " + function_name);
419 }
420 
422  vertex header)
423 {
424  graph::in_edge_iterator e_iter, e_iter_end;
425 
426  if(real_node == header)
427  {
428  return;
429  }
430  visited.insert(real_node);
431 
432  if(block_to_loop.find(real_node) == block_to_loop.end())
433  {
434  // Update the loop
435  l->add_block(real_node);
436  // Update the block to loop map
437  block_to_loop[real_node] = l;
438  }
439  else if(block_to_loop[real_node] != l)
440  {
441  // This block belongs to another loop therefore we have a nesting here and we should not
442  // add this block to the outermost
443  LoopRef innermost_loop = LoopRef(block_to_loop[real_node]);
444  if(innermost_loop->Parent() == nullptr)
445  {
446  l->AddChild(innermost_loop);
447  innermost_loop->SetParent(l);
448  }
449  }
450  // else the block already belongs to this loop. Nothing to be done
451 
452  // Note that since this is a reducible loop, we cannot have any edge entering the loop
453  // body other then the predecessors of the loop header
454  for(boost::tie(e_iter, e_iter_end) = boost::in_edges(real_node, *djg); e_iter != e_iter_end; ++e_iter)
455  {
456  vertex source = boost::source(*e_iter, *djg);
457  if(visited.find(source) == visited.end())
458  {
459  DetectReducibleLoop(djg, visited, l, source, header);
460  }
461  }
462 }
463 
464 void Loops::DetectIrreducibleLoop(const BBGraphRef djg, unsigned int min_level, unsigned int max_level,
465  std::vector<std::list<vertex>>& level_vertices_rel)
466 {
468  "-->Detecting irreducible loop - Min level " + STR(min_level) + " - Max level " + STR(max_level));
470 
472  for(auto level = min_level; level <= max_level; ++level)
473  {
474  for(auto v : level_vertices_rel[level])
475  {
477  "---Inserting BB" + STR(djg->CGetBBNodeInfo(v)->block->number) + " into set to be analyzed");
478  u.insert(v);
479  }
480  }
481 
482  THROW_ASSERT(u.size() > 0, "There must be at least one item in u");
483  do
484  {
485  unsigned int max_dfs = 0;
486  vertex min_ord_ver = *(u.begin());
489  "DetectIrreducibleLoop: starting vertex=" +
490  std::to_string(FB->GetBBGraph(FunctionBehavior::BB)->CGetBBNodeInfo(min_ord_ver)->block->number));
492  std::list<vertex> s;
494  tarjan_scc(djg, min_ord_ver, dfs_order, lowlink, s, u, max_dfs);
495  s.clear();
496  lowlink.clear();
497  dfs_order.clear();
498  } while(!u.empty());
499  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Detected irreducible loop");
500 }
501 
502 bool Loops::stack_contains(std::list<vertex> stack, vertex v)
503 {
504  auto stack_iter = stack.begin();
505  auto stack_end = stack.end();
506 
507  for(; stack_iter != stack_end; ++stack_iter)
508  {
509  vertex current_node = *stack_iter;
510  if(current_node == v)
511  {
512  return true;
513  }
514  }
515  return false;
516 }
517 
519  CustomUnorderedMap<vertex, unsigned int>& lowlink, std::list<vertex>& s,
520  CustomOrderedSet<vertex>& u, unsigned int& max_dfs)
521 {
522  dfs_order[v] = max_dfs++;
523  lowlink[v] = dfs_order[v];
524  s.push_back(v);
525  u.erase(v);
526 
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)
529  {
530  vertex target = boost::target(*e_out_iter, *djg);
531 
532  if(u.find(target) != u.end())
533  {
534  tarjan_scc(djg, target, dfs_order, lowlink, s, u, max_dfs);
535  lowlink[v] = lowlink[v] < lowlink[target] ? lowlink[v] : lowlink[target];
536  }
537  else if(stack_contains(s, target))
538  {
539  lowlink[v] = lowlink[v] < dfs_order[target] ? lowlink[v] : dfs_order[target];
540  }
541  }
542 
543  if(s.back() == v && lowlink[v] == dfs_order[v])
544  {
545  s.pop_back();
546  }
547  else if(lowlink[v] == dfs_order[v])
548  {
549  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Checking if we have to build a new irreducible loop");
550  // v is the root of a strongly connectec component
551  CustomUnorderedSet<vertex> candidate_body_loop;
552  vertex v1;
553  do
554  {
555  v1 = s.back();
556  s.pop_back();
557  // Add v1 to the loop
558  vertex real_node;
559 
560  real_node = v1;
561  candidate_body_loop.insert(real_node);
562  } while(v1 != v);
563  CustomUnorderedSet<vertex> real_body_loop;
564  CustomUnorderedSet<LoopRef> nested_loops;
565  for(const auto candidate : candidate_body_loop)
566  {
568  "-->Analyzing candidate BB" + STR(djg->CGetBBNodeInfo(candidate)->block->number));
569  if(block_to_loop.find(candidate) != block_to_loop.end())
570  {
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())
573  {
574  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--It is the header of a nested loop");
575  nested_loops.insert(candidate_nesting_loop);
576  }
577  else
578  {
579  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Already belongs to a loop");
580  }
581  }
582  else
583  {
584  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--It will be added to the body loop");
585  real_body_loop.insert(candidate);
586  }
587  }
588  if(real_body_loop.size())
589  {
590  LoopRef l = LoopRef(new Loop(djg));
592  "-->Creating data structure for irreducible loop " + STR(l->GetId()));
593  for(const auto body_loop_vertex : real_body_loop)
594  {
596  "---Adding BB" + STR(djg->CGetBBNodeInfo(body_loop_vertex)->block->number));
597  l->add_block(body_loop_vertex);
598  block_to_loop[body_loop_vertex] = l;
599  }
600  for(const auto& nested_loop : nested_loops)
601  {
603  "---Setting " + STR(l->GetId()) + " as parent of " + STR(nested_loop->GetId()));
604  nested_loop->SetParent(l);
605  l->AddChild(nested_loop);
606  }
607  modifiable_loops_list.push_back(l);
608  const_loops_list.push_back(l);
610  "<--Created data structure for irreducible loop " + STR(l->GetId()));
612  "<--Checking if we have to build a new irreducible loop: Yes");
613  }
614  else
615  {
617  "<--Checking if we have to build a new irreducible loop: No");
618  }
619  }
620 }
621 
622 const std::list<LoopConstRef>& Loops::GetList() const
623 {
624  return const_loops_list;
625 }
626 
627 const std::list<LoopRef>& Loops::GetModifiableList() const
628 {
629  return modifiable_loops_list;
630 }
631 
632 const LoopConstRef Loops::CGetLoop(unsigned int id) const
633 {
634  std::list<LoopConstRef>::const_iterator it, it_end;
635  it_end = const_loops_list.end();
636  for(it = const_loops_list.begin(); it != it_end; ++it)
637  {
638  if((*it)->GetId() == id)
639  {
640  return *it;
641  }
642  }
643  THROW_UNREACHABLE("Loop with id " + std::to_string(id) + " doesn't exist");
644  return LoopConstRef();
645 }
646 
647 const LoopRef Loops::GetLoop(unsigned int id)
648 {
649  std::list<LoopRef>::const_iterator it, it_end;
650  it_end = modifiable_loops_list.end();
651  for(it = modifiable_loops_list.begin(); it != it_end; ++it)
652  {
653  if((*it)->GetId() == id)
654  {
655  return *it;
656  }
657  }
658  THROW_UNREACHABLE("Loop with id " + std::to_string(id) + " doesn't exist");
659  return LoopRef();
660 }
661 
662 size_t Loops::NumLoops() const
663 {
664  return const_loops_list.size();
665 }
666 
667 void Loops::WriteDot(const std::string& file_name
668 #if HAVE_HOST_PROFILING_BUILT
669  ,
670  const ProfilingInformationConstRef profiling_information
671 #endif
672 ) const
673 {
674  auto output_directory = Param->getOption<std::string>(OPT_dot_directory);
675  output_directory += FB->CGetBehavioralHelper()->get_function_name() + "/";
676  const BBGraphRef cfg = FB->GetBBGraph(FunctionBehavior::BB);
677  std::ofstream dot((output_directory + file_name).c_str());
678  dot << "digraph LoopForest {" << std::endl;
679  for(const auto& loop : const_loops_list)
680  {
681  dot << loop->GetId() << " [label=\"LoopId=" << loop->GetId() << " - Depth: " << loop->depth;
682 #if HAVE_HOST_PROFILING_BUILT
683  if(profiling_information)
684  {
685  dot << "\\nAvg. Iterations=" << profiling_information->GetLoopAvgIterations(loop)
686  << "- Max Iterations=" << profiling_information->GetLoopMaxIterations(loop->GetId());
687  }
688 #endif
689  dot << "\\nType:";
690  if(loop->loop_type & SINGLE_EXIT_LOOP)
691  {
692  dot << " Single-Exit";
693  }
694  if(loop->loop_type == UNKNOWN_LOOP)
695  {
696  dot << " Generic";
697  }
698  if(loop->loop_type & WHILE_LOOP)
699  {
700  dot << " While";
701  }
702  if(loop->loop_type & FOR_LOOP)
703  {
704  dot << " For";
705  }
706  if(loop->loop_type & DOALL_LOOP)
707  {
708  dot << " DoAll";
709  }
710  if(loop->loop_type & DO_WHILE_LOOP)
711  {
712  dot << " DoWhile";
713  }
714  if(loop->loop_type & COUNTABLE_LOOP)
715  {
716  dot << " Countable[" << STR(loop->lower_bound) << ":" << STR(loop->increment) << ":" << STR(loop->upper_bound)
717  << (loop->close_interval ? "]" : ")");
718  }
719  if(loop->loop_type & PIPELINABLE_LOOP)
720  {
721  dot << " Pipelinable";
722  }
723  dot << "\\nBlocks:";
724  const CustomUnorderedSet<vertex>& blocks = loop->get_blocks();
725  CustomUnorderedSet<vertex>::const_iterator bb, bb_end = blocks.end();
726  for(bb = blocks.begin(); bb != bb_end; ++bb)
727  {
728  dot << " BB" + std::to_string(cfg->CGetBBNodeInfo(*bb)->block->number);
729  }
730  dot << "\\n\"];" << std::endl;
731  }
732  for(const auto& loop : const_loops_list)
733  {
734  for(const auto& child : loop->GetChildren())
735  {
736  dot << loop->GetId() << "->" << child->GetId() << ";" << std::endl;
737  }
738  }
739  dot << "}" << std::endl;
740 }
741 
742 void Loops::computeDepth(const LoopConstRef loop)
743 {
744  const CustomOrderedSet<LoopConstRef> children = loop->GetChildren();
745  CustomOrderedSet<LoopConstRef>::const_iterator child, child_end = children.end();
746  for(child = children.begin(); child != child_end; ++child)
747  {
748  auto* child_loop = const_cast<Loop*>(child->get());
749  child_loop->depth = loop->depth + 1;
750  computeDepth(*child);
751  }
752 }
753 
755 {
756  const BBGraphRef cfg = FB->GetBBGraph(FunctionBehavior::BB);
757  const LoopRef zero_loop(new Loop(cfg, cfg->CGetBBGraphInfo()->entry_vertex));
759  VertexIterator v, v_end;
760  for(boost::tie(v, v_end) = boost::vertices(*cfg); v != v_end; v++)
761  {
762  zero_loop->blocks.insert(*v);
763  }
764 
765  if(not const_loops_list.empty())
766  {
767  zero_loop->is_innermost_loop = false;
768  }
769  else
770  {
771  zero_loop->is_innermost_loop = true;
772  }
773 
774  std::list<LoopRef>::iterator loop, loop_end = modifiable_loops_list.end();
775  for(loop = modifiable_loops_list.begin(); loop != loop_end; ++loop)
776  {
777  if(not(*loop)->Parent())
778  {
779  (*loop)->parent_loop = zero_loop;
780  zero_loop->children.insert(*loop);
781  CustomUnorderedSet<vertex> children_blocks;
782  (*loop)->get_recursively_bb(children_blocks);
783  CustomUnorderedSet<vertex>::const_iterator child_block, child_block_end = children_blocks.end();
784  for(child_block = children_blocks.begin(); child_block != child_block_end; ++child_block)
785  {
786  if(zero_loop->blocks.find(*child_block) != zero_loop->blocks.end())
787  {
788  zero_loop->blocks.erase(zero_loop->blocks.find(*child_block));
789  }
790  }
791  }
792  }
793 
794  modifiable_loops_list.push_front(zero_loop);
795  const_loops_list.push_front(zero_loop);
796 }
void SetParent(LoopRef parent)
Sets parent for this loop.
Definition: loop.cpp:244
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
bool is_innermost_loop
tells if there aren&#39;t loop nested in this
Definition: loop.hpp:166
Vertex get_immediate_dominator(Vertex v) const
Return the immediate dominator of a Vertex.
Definition: Dominance.hpp:757
#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)
Definition: loops.cpp:209
void AddChild(LoopRef child)
Adds a child loop.
Definition: loop.cpp:287
void BuildZeroLoop()
Creates Loop zero data structure.
Definition: loops.cpp:754
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.
Definition: loops.cpp:117
const LoopRef Parent() const
returns the parent loop
Definition: loop.cpp:239
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
string target
Definition: lenet_tvm.py:16
#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
Definition: loop.hpp:141
const int debug_level
The debug level.
Definition: loops.cpp:106
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 ...
Definition: Dominance.hpp:767
Header include.
Definition: loops.cpp:87
const BBGraphInfoConstRef CGetBBGraphInfo() const
Returns the property associated with the graph.
#define COUNTABLE_LOOP
countable loop
Definition: loop.hpp:138
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
Definition: loop.cpp:282
CustomUnorderedMap< vertex, unsigned int > & dfs_order
dfs order of vertices
Definition: loops.cpp:94
size_t NumLoops() const
Returns the number of loops.
Definition: loops.cpp:662
CustomOrderedSet< LoopConstRef > children
Child loops.
Definition: loop.hpp:172
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
Definition: loops.cpp:175
redefinition of map to manage ordered/unordered structures
#define UNKNOWN_LOOP
unknown loop
Definition: loop.hpp:123
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
#define WHILE_LOOP
while or for loop
Definition: loop.hpp:126
#define FOR_LOOP
for loop
Definition: loop.hpp:129
boost::graph_traits< graph >::edge_iterator EdgeIterator
edge_iterator definition.
Definition: graph.hpp:1314
CustomUnorderedSet< vertex > blocks
Blocks which belong to this loop.
Definition: loop.hpp:175
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
void computeDepth(const LoopConstRef loop)
Sets depth for each loop in the forest starting from loop.
Definition: loops.cpp:742
Class specification for storing profiling information.
unsigned edges[4545]
Definition: graph.h:25
#define J_SELECTOR
j graph edge selector for dj graph (used during loop computation)
Definition: basic_block.hpp:91
vertex2obj< vertex > & parent_depth_search_spanning_tree
spanning tree
Definition: loops.cpp:103
absl::flat_hash_map< T, U, Hash, Eq, Alloc > CustomUnorderedMap
Definition: custom_map.hpp:148
bool is_edge_in_list(CustomUnorderedSet< vertex_pair > &l, vertex source, vertex target)
Definition: loops.cpp:203
CustomUnorderedMap< vertex, unsigned int > & vertex_level
topological level of the vertices
Definition: loops.cpp:91
std::list< LoopRef > modifiable_loops_list
List of found loops.
Definition: loops.hpp:106
bool stack_contains(std::list< vertex > stack, vertex v)
Definition: loops.cpp:502
Basic block control flow graph with feedback.
#define index(x, y)
Definition: Keccak.c:74
redefinition of set to manage ordered/unordered structures
int debug_level
Debug level.
Definition: loops.hpp:100
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
Definition: graph.hpp:1303
void discover_vertex(Vertex v, Graph &g)
Definition: loops.cpp:130
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)
Definition: loops.cpp:518
boost::graph_traits< graph >::vertex_iterator VertexIterator
vertex_iterator definition.
Definition: graph.hpp:1307
unsigned int dfs_number
last label used during the dfs graph visiting
Definition: loops.cpp:97
#define DEBUG_LEVEL_NONE
no debugging print is performed.
Definition: loop.hpp:153
null deleter
Definition: refcount.hpp:51
Loops()=delete
unsigned int & max_level
maximum level of vertices
Definition: loops.cpp:100
unsigned int GetId() const
returns the loop id
Definition: loop.cpp:131
Definition: tree.c:10
const std::list< LoopConstRef > & GetList() const
Returns the list of loops (const)
Definition: loops.cpp:622
#define DO_WHILE_LOOP
do while loop
Definition: loop.hpp:135
const std::list< LoopRef > & GetModifiableList() const
Return the list of loops.
Definition: loops.cpp:627
const LoopConstRef CGetLoop(unsigned int id) const
Returns a loop given the id.
Definition: loops.cpp:632
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.
interface of a loop
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...
Definition: refcount.hpp:94
int level
Definition: main.c:98
refcount< Loop > LoopRef
refcount definition of the class
Definition: loop.hpp:406
interface of loops finding algorithm
const ParameterConstRef Param
class containing all the parameters
Definition: loops.hpp:97
void DetectLoops()
Computes the loops of the control flow graph.
Definition: loops.cpp:216
void DetectReducibleLoop(const BBGraphRef djg, CustomOrderedSet< vertex > &visited, LoopRef loop, vertex node, vertex header)
Reducible loop construction.
Definition: loops.cpp:421
this class is used to manage the command-line or XML options.
const LoopRef GetLoop(unsigned int id)
Returns a loop given the id.
Definition: loops.cpp:647
std::pair< vertex, vertex > vertex_pair
Definition: loops.hpp:109
#define DOALL_LOOP
parallelizable for loop
Definition: loop.hpp:132
x
Return the smallest n such that 2^n >= _x.
list children
Definition: test_panda.py:872
std::list< LoopConstRef > const_loops_list
Definition: loops.hpp:107
unsigned int depth
Nesting depth of this loop.
Definition: loop.hpp:206
void WriteDot(const std::string &file_name) const
Write dot files representing the loop forest.
Definition: loops.cpp:667
CustomUnorderedMap< vertex, LoopRef > block_to_loop
Maps between basic block and loop to which it belongs.
Definition: loops.hpp:103
#define SINGLE_EXIT_LOOP
loop with single exit
Definition: loop.hpp:120
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)
Definition: loops.cpp:464
const FunctionBehaviorRef FB
The function behavior.
Definition: loops.hpp:94
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...
Definition: exceptions.hpp:289

Generated on Mon Feb 12 2024 13:02:50 for PandA-2024.02 by doxygen 1.8.13