PandA-2024.02
build_virtual_phi.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  */
41 #include "build_virtual_phi.hpp"
43 
45 #include "Parameter.hpp"
46 
48 #include "loop.hpp"
49 #include "loops.hpp"
50 
52 #include "application_manager.hpp"
53 #include "basic_block.hpp"
54 #include "cdfg_edge_info.hpp"
55 #include "function_behavior.hpp"
56 
58 #include "token_interface.hpp"
59 
61 #include "dbgPrintHelper.hpp" // for DEBUG_LEVEL_
62 #include "design_flow_graph.hpp"
63 #include "design_flow_manager.hpp"
64 #include "string_manipulation.hpp" // for GET_CLASS
65 #include "tree_basic_block.hpp"
66 #include "tree_helper.hpp"
67 #include "tree_manager.hpp"
68 #include "tree_manipulation.hpp"
69 #include "tree_node.hpp"
70 #include "tree_reindex.hpp"
71 
72 #include <set>
73 
74 BuildVirtualPhi::BuildVirtualPhi(const application_managerRef _AppM, unsigned int _function_id,
75  const DesignFlowManagerConstRef _design_flow_manager,
76  const ParameterConstRef _parameters)
77  : FunctionFrontendFlowStep(_AppM, _function_id, BUILD_VIRTUAL_PHI, _design_flow_manager, _parameters),
78  TM(_AppM->get_tree_manager())
79 {
80  debug_level = parameters->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
81 }
82 
84 
86  const DesignFlowStep::RelationshipType relationship_type)
87 {
88  switch(relationship_type)
89  {
91  {
92  break;
93  }
95  {
96  break;
97  }
99  {
101  AppM->CGetFunctionBehavior(function_id)->is_simple_pipeline())
102  {
103  const auto step_signature =
104  FunctionFrontendFlowStep::ComputeSignature(FrontendFlowStepType::SIMPLE_CODE_MOTION, function_id);
105  const auto frontend_step = design_flow_manager.lock()->GetDesignFlowStep(step_signature);
106  THROW_ASSERT(frontend_step != NULL_VERTEX, "step " + step_signature + " is not present");
107  const auto design_flow_graph = design_flow_manager.lock()->CGetDesignFlowGraph();
108  const auto design_flow_step = design_flow_graph->CGetDesignFlowStepInfo(frontend_step)->design_flow_step;
109  relationship.insert(design_flow_step);
110  }
111  break;
112  }
113  default:
114  THROW_UNREACHABLE("");
115  }
116  FunctionFrontendFlowStep::ComputeRelationships(relationship, relationship_type);
117 }
118 
121 {
123  switch(relationship_type)
124  {
126  {
127  relationships.insert(std::make_pair(BB_FEEDBACK_EDGES_IDENTIFICATION, SAME_FUNCTION));
128  relationships.insert(std::make_pair(BB_REACHABILITY_COMPUTATION, SAME_FUNCTION));
129  relationships.insert(std::make_pair(DOM_POST_DOM_COMPUTATION, SAME_FUNCTION));
130  relationships.insert(std::make_pair(USE_COUNTING, SAME_FUNCTION));
131  break;
132  }
134  {
135  relationships.insert(std::make_pair(BASIC_BLOCKS_CFG_COMPUTATION, SAME_FUNCTION));
136 #if HAVE_FROM_PRAGMA_BUILT
137  relationships.insert(std::make_pair(EXTRACT_OMP_ATOMIC, SAME_FUNCTION));
138 #endif
139  relationships.insert(std::make_pair(VECTORIZE, SAME_FUNCTION));
140  break;
141  }
143  {
144  break;
145  }
146  default:
147  {
148  THROW_UNREACHABLE("");
149  }
150  }
151  return relationships;
152 }
153 
155 {
156  const auto tree_man = tree_manipulationRef(new tree_manipulation(TM, parameters, AppM));
157  const auto basic_block_graph = function_behavior->GetBBGraph(FunctionBehavior::FBB);
158  const auto loops = function_behavior->CGetLoops();
159  const auto bb_index_map = basic_block_graph->CGetBBGraphInfo()->bb_index_map;
165  TreeNodeMap<tree_nodeConstRef> virtual_ssa_definitions;
168 
170  VertexIterator basic_block, basic_block_end;
171  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Computing definitions");
172  for(boost::tie(basic_block, basic_block_end) = boost::vertices(*basic_block_graph); basic_block != basic_block_end;
173  basic_block++)
174  {
176  "-->Analyzing BB" + STR(basic_block_graph->CGetBBNodeInfo(*basic_block)->block->number));
177  const auto block_info = basic_block_graph->CGetBBNodeInfo(*basic_block)->block;
178  for(const auto& stmt : block_info->CGetStmtList())
179  {
180  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Analyzing stmt " + STR(stmt));
181  const auto gn = GetPointerS<gimple_node>(GET_NODE(stmt));
182  if(gn->vdef)
183  {
184  THROW_ASSERT(virtual_ssa_definitions.count(gn->vdef) == 0,
185  gn->vdef->ToString() + " is defined also in " + STR(virtual_ssa_definitions.at(gn->vdef)));
186  virtual_ssa_definitions[gn->vdef] = stmt;
187  }
188  const auto& cur_bb = bb_index_map.at(gn->bb_index);
189  const auto vo_it = gn->vdef ? gn->vovers.find(gn->vdef) : gn->vovers.end();
190  if(vo_it != gn->vovers.end() && !function_behavior->CheckBBReachability(cur_bb, cur_bb))
191  {
192  gn->vovers.erase(vo_it);
193  GetPointerS<ssa_name>(GET_NODE(gn->vdef))->RemoveUse(stmt);
194  }
195  for(const auto& vover : gn->vovers)
196  {
197  vovers[vover].insert(stmt);
198  }
200  auto vu_it = gn->vuses.begin();
201  while(vu_it != gn->vuses.end())
202  {
203  const auto sn = GetPointerS<ssa_name>(GET_NODE(*vu_it));
204  const auto def_stmt = sn->CGetDefStmt();
205  const auto use_bb_index = GetPointerS<const gimple_node>(GET_NODE(def_stmt))->bb_index;
206  const auto& use_bb = bb_index_map.at(use_bb_index);
207  if(use_bb_index == gn->bb_index)
208  {
210  ++vu_it;
211  }
212  else if(!function_behavior->CheckBBReachability(use_bb, cur_bb) &&
213  !function_behavior->CheckBBReachability(cur_bb, use_bb))
214  {
215  sn->RemoveUse(stmt);
217  "---Removing " + STR(*vu_it) + " from vuses of unreachable stmt: " + STR(sn));
218  vu_it = gn->vuses.erase(vu_it);
219  }
220  else
221  {
222  ++vu_it;
223  }
224  }
225  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Analyzed stmt " + STR(stmt));
226  }
228  "<--Analyzed BB" + STR(basic_block_graph->CGetBBNodeInfo(*basic_block)->block->number));
229  }
230  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Computed definitions");
231 
234  for(const auto& virtual_ssa_definition : virtual_ssa_definitions)
235  {
237  "-->Considering ssa " + virtual_ssa_definition.first->ToString());
238  const auto sn = GetPointerS<ssa_name>(GET_NODE(virtual_ssa_definition.first));
240  "---Defined in " + virtual_ssa_definition.second->ToString());
241  const auto definition = GetPointerS<const gimple_node>(GET_CONST_NODE(virtual_ssa_definition.second));
242  THROW_ASSERT(definition, STR(sn->CGetDefStmt()));
243  const auto definition_bb_index = definition->bb_index;
244  const auto& definition_bb = bb_index_map.at(definition_bb_index);
245  THROW_ASSERT(sn, STR(virtual_ssa_definition.first));
246 
248  auto loop_id = basic_block_graph->CGetBBNodeInfo(definition_bb)->loop_id;
249 
251  auto depth = loops->CGetLoop(loop_id)->depth;
252 
254  CustomSet<vertex> use_bbs;
255 
257  TreeNodeSet use_stmts;
258 
260  TreeNodeMap<size_t> transitive_uses;
261 
262  for(const auto& use_stmt : sn->CGetUseStmts())
263  {
264  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Considering use in " + STR(use_stmt.first));
265  const auto use_bb_index = GetPointerS<const gimple_node>(GET_NODE(use_stmt.first))->bb_index;
266  const auto& use_bb = bb_index_map.at(use_bb_index);
267 
268  const auto gn = GetPointerS<const gimple_node>(GET_NODE(use_stmt.first));
269 
271  bool skip = [&]() -> bool {
272  if(definition_bb_index == use_bb_index)
273  {
274  return false;
275  }
276  if(vovers.find(virtual_ssa_definition.first) != vovers.end())
277  {
278  for(const auto& vover_stmt : vovers.find(virtual_ssa_definition.first)->second)
279  {
280  const auto vover_bb_index = GetPointerS<const gimple_node>(GET_NODE(vover_stmt))->bb_index;
281  const auto vover_bb = bb_index_map.at(vover_bb_index);
282  if(function_behavior->CheckBBReachability(use_bb, vover_bb) || use_bb == vover_bb)
283  {
284  return false;
285  }
286  }
287  }
288  for(const auto& other_use_stmt : sn->CGetUseStmts())
289  {
290  const auto other_use_bb_index = GetPointerS<const gimple_node>(GET_NODE(other_use_stmt.first))->bb_index;
291  const auto other_use_bb = bb_index_map.at(other_use_bb_index);
292  if(other_use_stmt.first->index != use_stmt.first->index &&
293  function_behavior->CheckBBReachability(other_use_bb, use_bb) &&
294  other_use_stmt.first->index != virtual_ssa_definition.second->index)
295  {
297  "---Considered other use: " + STR(other_use_stmt.first->index) + " " +
298  STR(other_use_stmt.first));
299  const auto other_gn = GetPointerS<const gimple_node>(GET_NODE(other_use_stmt.first));
300  if(other_gn->vdef && gn->vuses.find(other_gn->vdef) != gn->vuses.end())
301  {
302  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Defines " + STR(other_gn->vdef));
303  return true;
304  }
305  }
306  }
307  return false;
308  }();
309  if(skip)
310  {
311  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Skipped because of transitivity");
312  transitive_uses.insert(use_stmt);
313  continue;
314  }
315  use_stmts.insert(use_stmt.first);
316  use_bbs.insert(use_bb);
317 
318  auto use_loop_id = basic_block_graph->CGetBBNodeInfo(use_bb)->loop_id;
319  auto use_depth = loops->CGetLoop(use_loop_id)->depth;
320 
322  if(use_loop_id == loop_id)
323  {
324  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Use is in the same loop");
325  continue;
326  }
327  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Definition and use are in different loops");
329  "---Current loop is " + STR(loop_id) + " (depth is " + STR(depth) + ") - Use loop is " +
330  STR(use_loop_id) + " (depth " + STR(use_depth) + ")");
332  while(use_depth > depth)
333  {
334  use_loop_id = loops->CGetLoop(use_loop_id)->Parent()->GetId();
335  use_depth = loops->CGetLoop(use_loop_id)->depth;
336  }
338  while(use_depth < depth)
339  {
340  loop_id = loops->CGetLoop(loop_id)->Parent()->GetId();
341  depth = loops->CGetLoop(loop_id)->depth;
342  }
343  while(use_loop_id != loop_id)
344  {
345  use_loop_id = loops->CGetLoop(use_loop_id)->Parent()->GetId();
346  loop_id = loops->CGetLoop(loop_id)->Parent()->GetId();
347  depth = loops->CGetLoop(loop_id)->depth;
348  }
349  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Loop to be considered updated to " + STR(loop_id));
350  }
351  for(const auto& transitive_use : transitive_uses)
352  {
354  "---Removing " + STR(virtual_ssa_definition.first) + " from vuses of " +
355  STR(transitive_use.first));
356  const auto gn = GetPointerS<gimple_node>(GET_NODE(transitive_use.first));
357  gn->vuses.erase(virtual_ssa_definition.first);
358  sn->RemoveUse(transitive_use.first);
359  }
360 
362  if(use_bbs.empty())
363  {
364  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--There is not any reachable use");
365  continue;
366  }
367 
368  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Loop to be considered is " + STR(loop_id));
369 
370  // The set of header basic blocks where a phi has to be inserted
371  CustomSet<vertex> phi_headers;
372  auto current_loop = loops->CGetLoop(basic_block_graph->CGetBBNodeInfo(definition_bb)->loop_id);
373  while(current_loop->GetId() != loop_id)
374  {
375  for(const auto& cur_pair : current_loop->get_sp_back_edges())
376  {
377  phi_headers.insert(cur_pair.second);
378  }
380  "---Phi has to be added in header of loop " + STR(current_loop->GetId()));
381  current_loop = current_loop->Parent();
382  }
383  for(const auto& cur_pair : current_loop->get_sp_back_edges())
384  {
385  phi_headers.insert(cur_pair.second);
386  }
388  "---Phi has to be added in header of loop " + STR(current_loop->GetId()));
389 
391  std::map<TreeVocabularyTokenTypes_TokenEnum, std::string> nop_IR_schema;
392  const auto nop_id = TM->new_tree_node_id();
393  nop_IR_schema[TOK(TOK_SRCP)] = BUILTIN_SRCP;
394  nop_IR_schema[TOK(TOK_SCPE)] = STR(function_id);
395  TM->create_tree_node(nop_id, gimple_nop_K, nop_IR_schema);
396 
397  const auto volatile_sn = tree_man->create_ssa_name(sn->var, tree_helper::CGetType(virtual_ssa_definition.first),
398  nullptr, nullptr, true, true);
399  GetPointerS<ssa_name>(GET_NODE(volatile_sn))->SetDefStmt(TM->GetTreeReindex(nop_id));
400  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created volatile ssa " + STR(volatile_sn));
401 
403  CustomUnorderedSet<vertex> loop_basic_blocks;
404  loops->CGetLoop(loop_id)->get_recursively_bb(loop_basic_blocks);
405 
407  const bb_vertex_order_by_map comp_i(function_behavior->get_bb_map_levels());
408  std::set<vertex, bb_vertex_order_by_map> to_be_processed(comp_i);
409 
411  if(loop_id == 0)
412  {
413  reaching_defs[virtual_ssa_definition.first][basic_block_graph->CGetBBGraphInfo()->entry_vertex] = volatile_sn;
414  OutEdgeIterator oe, oe_end;
415  for(boost::tie(oe, oe_end) =
416  boost::out_edges(basic_block_graph->CGetBBGraphInfo()->entry_vertex, *basic_block_graph);
417  oe != oe_end; oe++)
418  {
419  const auto target = boost::target(*oe, *basic_block_graph);
420  if(basic_block_graph->CGetBBGraphInfo()->exit_vertex != target)
421  {
422  to_be_processed.insert(target);
423  }
424  }
425 
427  CustomSet<vertex> to_be_removed;
428  for(const auto current : loop_basic_blocks)
429  {
430  bool reachable = false;
431  for(const auto use_bb : use_bbs)
432  {
433  if(function_behavior->CheckBBFeedbackReachability(current, use_bb))
434  {
436  "---BB" + STR(basic_block_graph->CGetBBNodeInfo(use_bb)->block->number) +
437  " can be reached from BB" +
438  STR(basic_block_graph->CGetBBNodeInfo(current)->block->number));
439  reachable = true;
440  break;
441  }
442  else if(current == use_bb)
443  {
444  reachable = true;
445  break;
446  }
447  }
448  if(!reachable)
449  {
450  to_be_removed.insert(current);
451  }
452  }
453  for(const auto removable : to_be_removed)
454  {
456  "---Removing BB" + STR(basic_block_graph->CGetBBNodeInfo(removable)->block->number));
457  loop_basic_blocks.erase(removable);
458  }
459  }
460  else
461  {
463  loops->CGetLoop(loop_id)->get_recursively_bb(loop_bbs);
464  for(const auto& loop_bb : loop_bbs)
465  {
466  InEdgeIterator ei, ei_end;
467  for(boost::tie(ei, ei_end) = boost::in_edges(loop_bb, *basic_block_graph); ei != ei_end; ei++)
468  {
469  const auto source = boost::source(*ei, *basic_block_graph);
470  if(loop_bbs.find(source) == loop_bbs.end())
471  {
472  reaching_defs[virtual_ssa_definition.first][source] = volatile_sn;
473  }
474  }
475  }
476  for(const auto& feedback_edge : loops->CGetLoop(loop_id)->get_sp_back_edges())
477  {
478  to_be_processed.insert(feedback_edge.second);
479  }
480  }
481 
482  while(to_be_processed.size())
483  {
484  const auto current = *(to_be_processed.begin());
485  to_be_processed.erase(current);
487  "-->Checking BB" + STR(basic_block_graph->CGetBBNodeInfo(current)->block->number));
488 
489  InEdgeIterator ie, ie_end;
490  if(boost::in_degree(current, *basic_block_graph) == 1)
491  {
492  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Single entry BB");
493  boost::tie(ie, ie_end) = boost::in_edges(current, *basic_block_graph);
494  const auto source = boost::source(*ie, *basic_block_graph);
495  THROW_ASSERT(reaching_defs.at(virtual_ssa_definition.first).count(source), "unexpected condition");
496  reaching_defs[virtual_ssa_definition.first][current] =
497  reaching_defs.at(virtual_ssa_definition.first).at(source);
498  }
499  else
500  {
501  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Multiple entries BB");
503  bool build_phi = false;
504  TreeNodeSet local_reaching_defs;
505  for(boost::tie(ie, ie_end) = boost::in_edges(current, *basic_block_graph); ie != ie_end; ie++)
506  {
507  const auto source = boost::source(*ie, *basic_block_graph);
508  if((basic_block_graph->GetSelector(*ie) & FB_CFG_SELECTOR))
509  {
510  if(phi_headers.find(current) != phi_headers.end())
511  {
513  build_phi = true;
514  break;
515  }
516  else
517  {
519  const auto current_loop_id = basic_block_graph->CGetBBNodeInfo(current)->loop_id;
520  if(!loops->CGetLoop(current_loop_id)->IsReducible())
521  {
525  build_phi = true;
526  }
527  }
528  }
529  else
530  {
531  THROW_ASSERT(reaching_defs.find(virtual_ssa_definition.first) != reaching_defs.end() &&
532  reaching_defs.find(virtual_ssa_definition.first)->second.count(source),
533  "Definition coming from BB" +
534  STR(basic_block_graph->CGetBBNodeInfo(source)->block->number));
535  local_reaching_defs.insert(reaching_defs.at(virtual_ssa_definition.first).at(source));
536  }
537  }
538  if(local_reaching_defs.size() > 1)
539  {
540  build_phi = true;
541  }
542 
543  if(build_phi)
544  {
545  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---PHI has to be built");
546 
547  std::vector<gimple_phi::DefEdge> def_edges;
548  for(boost::tie(ie, ie_end) = boost::in_edges(current, *basic_block_graph); ie != ie_end; ie++)
549  {
550  if((basic_block_graph->GetSelector(*ie) & CFG_SELECTOR) != 0)
551  {
552  const auto source = boost::source(*ie, *basic_block_graph);
553  const auto& vssa = reaching_defs.at(virtual_ssa_definition.first).at(source);
554  def_edges.push_back(
555  gimple_phi::DefEdge(vssa, basic_block_graph->CGetBBNodeInfo(source)->block->number));
556  }
557  }
558  tree_nodeRef phi_res;
559  const auto phi_stmt = tree_man->create_phi_node(phi_res, def_edges, function_id, true);
561  tree_helper::CGetType(virtual_ssa_definition.first)->index,
562  "");
563  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created ssa " + phi_res->ToString());
564  GetPointerS<gimple_phi>(GET_NODE(phi_stmt))->SetSSAUsesComputed();
565  basic_block_graph->GetBBNodeInfo(current)->block->AddPhi(phi_stmt);
566  reaching_defs[virtual_ssa_definition.first][current] = phi_res;
567  added_phis[virtual_ssa_definition.first][current] = phi_stmt;
568  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created phi " + phi_stmt->ToString());
569  }
570  else
571  {
572  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---PHI has not to be built");
573  THROW_ASSERT(local_reaching_defs.size() == 1, "");
574  reaching_defs[virtual_ssa_definition.first][current] = *(local_reaching_defs.begin());
575  }
576  }
577 
579  if(definition_bb == current || use_bbs.count(current))
580  {
581  bool before_definition =
582  definition_bb == current || function_behavior->CheckBBReachability(current, definition_bb);
583  for(const auto& stmt : basic_block_graph->CGetBBNodeInfo(current)->block->CGetStmtList())
584  {
585  const auto& reaching_def = reaching_defs.at(virtual_ssa_definition.first).at(current);
586  if(use_stmts.count(stmt) && stmt->index != virtual_ssa_definition.second->index)
587  {
588  if(before_definition)
589  {
591  "---Adding for anti dependence " + STR(reaching_def) + " in " + STR(stmt));
592  THROW_ASSERT(!GetPointerS<ssa_name>(GET_NODE(reaching_def))->volatile_flag ||
593  !function_behavior->CheckBBFeedbackReachability(definition_bb, current),
594  "");
595  if(GetPointerS<gimple_node>(GET_NODE(stmt))->AddVuse(reaching_def))
596  {
597  GetPointerS<ssa_name>(GET_NODE(reaching_def))->AddUseStmt(stmt);
598  }
599  }
600  else
601  {
603  "---Replacing " + STR(virtual_ssa_definition.first) + " with " + STR(reaching_def) +
604  " in " + STR(stmt));
605  THROW_ASSERT(!GetPointerS<ssa_name>(GET_NODE(reaching_def))->volatile_flag ||
606  !function_behavior->CheckBBFeedbackReachability(definition_bb, current),
607  "");
608  TM->ReplaceTreeNode(stmt, virtual_ssa_definition.first, reaching_def);
609  }
610  }
611  if(stmt->index == virtual_ssa_definition.second->index)
612  {
613  before_definition = false;
614  const auto gn = GetPointerS<gimple_node>(GET_NODE(stmt));
615  if(gn->vovers.erase(virtual_ssa_definition.first))
616  {
617  const auto old_vssa = GetPointerS<ssa_name>(GET_NODE(virtual_ssa_definition.first));
618  old_vssa->RemoveUse(stmt);
619  }
620  if(gn->AddVover(reaching_def))
621  {
622  const auto reaching_vssa = GetPointerS<ssa_name>(GET_NODE(reaching_def));
623  reaching_vssa->AddUseStmt(stmt);
624  }
625  reaching_defs[virtual_ssa_definition.first][current] = virtual_ssa_definition.first;
626  }
627  }
628  }
630  "---Reaching definition at the exit is " +
631  STR(reaching_defs.at(virtual_ssa_definition.first).at(current)));
632 
633  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Checking successors");
634  OutEdgeIterator oe, oe_end;
635  for(boost::tie(oe, oe_end) = boost::out_edges(current, *basic_block_graph); oe != oe_end; oe++)
636  {
637  const auto target = boost::target(*oe, *basic_block_graph);
638  if(loop_basic_blocks.count(target))
639  {
641  "---Considering BB" + STR(basic_block_graph->CGetBBNodeInfo(target)->block->number));
642  if((basic_block_graph->GetSelector(*oe) & FB_CFG_SELECTOR) != 0)
643  {
644  if(phi_headers.count(target))
645  {
646  THROW_ASSERT(added_phis.find(virtual_ssa_definition.first) != added_phis.end() &&
647  added_phis.find(virtual_ssa_definition.first)->second.count(target),
648  "Phi for " + STR(virtual_ssa_definition.first) + " was not created in BB" +
649  STR(basic_block_graph->CGetBBNodeInfo(target)->block->number));
650  GetPointerS<gimple_phi>(GET_NODE(added_phis.at(virtual_ssa_definition.first).at(target)))
651  ->AddDefEdge(TM,
652  gimple_phi::DefEdge(reaching_defs.at(virtual_ssa_definition.first).at(current),
653  basic_block_graph->CGetBBNodeInfo(current)->block->number));
655  "---Updated phi " + STR(added_phis.at(virtual_ssa_definition.first).at(target)));
656  }
657  else if(!loops->CGetLoop(basic_block_graph->CGetBBNodeInfo(target)->loop_id)->IsReducible())
658  {
659  THROW_ASSERT(added_phis.find(virtual_ssa_definition.first) != added_phis.end() &&
660  added_phis.find(virtual_ssa_definition.first)->second.count(target),
661  "Phi for " + STR(virtual_ssa_definition.first) + " was not created in BB" +
662  STR(basic_block_graph->CGetBBNodeInfo(target)->block->number));
663  GetPointerS<gimple_phi>(GET_NODE(added_phis.at(virtual_ssa_definition.first).at(target)))
664  ->AddDefEdge(TM,
665  gimple_phi::DefEdge(reaching_defs.at(virtual_ssa_definition.first).at(current),
666  basic_block_graph->CGetBBNodeInfo(current)->block->number));
668  "---Updated phi " + STR(added_phis.at(virtual_ssa_definition.first).at(target)));
669  }
670  else
671  {
672  TreeNodeSet local_reaching_defs;
674  for(boost::tie(ie, ie_end) = boost::in_edges(target, *basic_block_graph); ie != ie_end; ie++)
675  {
676  if((basic_block_graph->GetSelector(*ie) & FB_CFG_SELECTOR) == 0)
677  {
678  const auto source = boost::source(*ie, *basic_block_graph);
679  THROW_ASSERT(reaching_defs.find(virtual_ssa_definition.first) != reaching_defs.end() &&
680  reaching_defs.find(virtual_ssa_definition.first)->second.count(source),
681  "Definition coming from BB" +
682  STR(basic_block_graph->CGetBBNodeInfo(source)->block->number));
683  local_reaching_defs.insert(reaching_defs.at(virtual_ssa_definition.first).at(source));
684  }
685  }
686  if(local_reaching_defs.size() > 1)
687  {
688  THROW_ASSERT(added_phis.find(virtual_ssa_definition.first) != added_phis.end() &&
689  added_phis.find(virtual_ssa_definition.first)->second.count(target),
690  "Phi for " + STR(virtual_ssa_definition.first) + " was not created in BB" +
691  STR(basic_block_graph->CGetBBNodeInfo(target)->block->number));
692  GetPointerS<gimple_phi>(GET_NODE(added_phis.at(virtual_ssa_definition.first).at(target)))
693  ->AddDefEdge(
694  TM, gimple_phi::DefEdge(reaching_defs.at(virtual_ssa_definition.first).at(current),
695  basic_block_graph->CGetBBNodeInfo(current)->block->number));
697  "---Updated phi " + STR(added_phis.at(virtual_ssa_definition.first).at(target)));
698  }
699  }
700  }
701  else
702  {
703  to_be_processed.insert(target);
704  }
705  }
706  }
707  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Checked successors");
709  "<--Checked BB" + STR(basic_block_graph->CGetBBNodeInfo(current)->block->number));
710  }
711  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Considered ssa " + STR(virtual_ssa_definition.first));
712  }
714  // function_behavior->UpdateBBVersion();
715  if(parameters->getOption<bool>(OPT_print_dot))
716  {
717  function_behavior->GetBBGraph(FunctionBehavior::FBB)->WriteDot("BB_FCFG.dot");
718  }
719  bool restart;
720  std::set<tree_nodeRef> removedPhis;
721  do
722  {
723  restart = false;
724  for(const auto& ssa_bbv : added_phis)
725  {
726  for(const auto& bbv_phi : ssa_bbv.second)
727  {
728  if(removedPhis.find(bbv_phi.second) == removedPhis.end())
729  {
730  const auto& bb = basic_block_graph->GetBBNodeInfo(bbv_phi.first)->block;
731  const auto phi_stmt = GetPointerS<gimple_phi>(GET_NODE(bbv_phi.second));
732  const auto vssa = GetPointerS<ssa_name>(GET_NODE(phi_stmt->res));
733  if(vssa->CGetNumberUses() == 0 ||
734  (vssa->CGetNumberUses() == 1 &&
735  GET_INDEX_NODE(vssa->CGetUseStmts().begin()->first) == phi_stmt->index))
736  {
738  "---Removing just created dead phi from BB" + STR(bb->number) + " - (" +
739  GetPointerS<ssa_name>(GET_NODE(ssa_bbv.first))->ToString() + ") " +
740  phi_stmt->ToString());
741  bb->RemovePhi(bbv_phi.second);
742  restart = true;
743  removedPhis.insert(bbv_phi.second);
744  }
745  }
746  }
747  }
748  if(restart)
749  {
750  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Phi dead removal restarted");
751  }
752  } while(restart);
753 #ifndef NDEBUG
755  {
756  for(boost::tie(basic_block, basic_block_end) = boost::vertices(*basic_block_graph);
757  basic_block != basic_block_end; basic_block++)
758  {
759  const auto& block = basic_block_graph->CGetBBNodeInfo(*basic_block)->block;
760  for(const auto& phi : block->CGetPhiList())
761  {
762  const auto gp = GetPointerS<const gimple_phi>(GET_CONST_NODE(phi));
763  if(gp->virtual_flag)
764  {
765  THROW_ASSERT(gp->CGetDefEdgesList().size() == boost::in_degree(*basic_block, *basic_block_graph),
766  STR(phi) + " of BB" + STR(block->number) +
767  " has wrong number of inputs: " + STR(gp->CGetDefEdgesList().size()) + " vs " +
768  STR(boost::in_degree(*basic_block, *basic_block_graph)));
769  }
770  }
771  }
772  }
773 #endif
775 }
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:343
BuildVirtualPhi(const application_managerRef AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager, const ParameterConstRef parameters)
Constructor.
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
boost::graph_traits< graph >::out_edge_iterator OutEdgeIterator
out_edge_iterator definition.
Definition: graph.hpp:1312
File containing functions and utilities to support the printing of debug messagges.
std::string ToString() const
Print this node as string in gimple format.
string target
Definition: lenet_tvm.py:16
#define GET_CLASS(obj)
Macro returning the actual type of an object.
Definition of the class representing a generic C application.
refcount< tree_manipulation > tree_manipulationRef
~BuildVirtualPhi() override
Destructor.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
boost::graph_traits< graph >::in_edge_iterator InEdgeIterator
in_edge_iterator definition.
Definition: graph.hpp:1310
A simple interface to token object of the raw files.
Analysis step building phi of vops.
#define GET_INDEX_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:361
Data structure describing a basic block at tree level.
#define TOK(token)
Macro used to convert a token symbol into a treeVocabularyTokenTypes.
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
#define FB_CFG_SELECTOR
Feedback control flow edge selector.
void ComputeRelationships(DesignFlowStepSet &relationship, const DesignFlowStep::RelationshipType relationship_type) override
Compute the relationships of a step with other steps.
std::string GetSignature() const override
Return the signature of this step.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
const unsigned int index
Represent the index read from the raw file and the index-1 of the vector of tree_node associated to t...
Definition: tree_node.hpp:146
Classes to describe design flow graph.
Basic block control flow graph with feedback.
#define index(x, y)
Definition: Keccak.c:74
std::pair< tree_nodeRef, unsigned int > DefEdge
The type of the def edge.
Definition: tree_node.hpp:3750
const Wrefcount< const DesignFlowManager > design_flow_manager
The design flow manager.
#define GET_CONST_NODE(t)
Definition: tree_node.hpp:347
boost::graph_traits< graph >::vertex_iterator VertexIterator
vertex_iterator definition.
Definition: graph.hpp:1307
Classes specification of the tree_node data structures.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
Class defining some useful functions to create tree nodes and to manipulate the tree manager...
#define DEBUG_LEVEL_NONE
no debugging print is performed.
The key comparison function for vertices set based on levels.
Wrapper of design_flow.
This struct specifies the block node.
Definition: tree_node.hpp:1820
This file collects some utility functions.
void ComputeRelationships(DesignFlowStepSet &relationship, const DesignFlowStep::RelationshipType relationship_type) override
Compute the relationships of a step with other steps.
Data structures used to represent an edge in operation and basic block graphs.
refcount< T > lock() const
Definition: refcount.hpp:212
#define BUILTIN_SRCP
const unsigned int function_id
The index of the function to be analyzed.
const tree_managerRef TM
The tree manager.
const application_managerRef AppM
The application manager.
Class specification of the tree_reindex support class.
DesignFlowStep_Status InternalExec() override
Performs the loops analysis.
Class specification of the basic_block structure.
interface of a loop
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
static tree_nodeConstRef CGetType(const tree_nodeConstRef &node)
Return the treenode of the type of node.
interface of loops finding algorithm
this class is used to manage the command-line or XML options.
int debug_level
The debug level.
block(unsigned int i)
constructor
Definition: tree_node.hpp:1823
const CustomUnorderedSet< std::pair< FrontendFlowStepType, FunctionRelationship > > ComputeFrontendRelationships(const DesignFlowStep::RelationshipType relationship_type) const override
Return the set of analyses in relationship with this design step.
#define CFG_SELECTOR
Control flow graph edge selector.
#define NULL_VERTEX
null vertex definition
Definition: graph.hpp:1305
This class creates a layer to add nodes and to manipulate the tree_nodes manager. ...
Class specification of the manager of the tree structures extracted from the raw file.
A map with key tree_nodeRef.
Definition: tree_helper.hpp:65
A brief description of the C++ Header File.
const FunctionBehaviorRef function_behavior
The function behavior of the function to be analyzed.
static const std::string ComputeSignature(const FrontendFlowStepType frontend_flow_step_type, const unsigned int function_id)
Compute the signature of a function frontend flow step.
#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:52 for PandA-2024.02 by doxygen 1.8.13