PandA-2024.02
multiple_entry_if_reduction.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  */
33 
56 
58 #include "loop.hpp"
59 #include "loops.hpp"
60 
62 #include "application_manager.hpp"
63 #include "basic_block.hpp"
64 #include "behavioral_helper.hpp"
65 #include "function_behavior.hpp"
66 
68 #include "design_flow_graph.hpp"
69 #include "design_flow_manager.hpp"
70 
72 #include "simple_code_motion.hpp"
73 
75 #include "hls.hpp"
76 #include "hls_manager.hpp"
77 
80 
82 #include "Parameter.hpp"
83 
85 #include "token_interface.hpp"
86 
88 #include <boost/range/adaptor/reversed.hpp>
89 #include <cmath>
90 #include <fstream>
91 #include <limits>
92 #include <string>
93 
95 #include "custom_map.hpp"
96 #include "custom_set.hpp"
97 #include <list>
98 #include <set>
99 #include <utility>
100 
102 #include "ext_tree_node.hpp"
103 #include "tree_basic_block.hpp"
104 #include "tree_helper.hpp"
105 #include "tree_manager.hpp"
106 #include "tree_manipulation.hpp"
107 #include "tree_node.hpp"
108 #pragma GCC diagnostic ignored "-Woverloaded-virtual"
109 #include "dbgPrintHelper.hpp" // for DEBUG_LEVEL_
110 #include "string_manipulation.hpp" // for GET_CLASS
111 #include "tree_node_dup.hpp"
112 #include "tree_reindex.hpp"
113 
115 
116 #define MAX_DOUBLE std::numeric_limits<double>::max();
117 
119  const application_managerRef _AppM, unsigned int _function_id,
120  const DesignFlowManagerConstRef _design_flow_manager)
121  : FunctionFrontendFlowStep(_AppM, _function_id, MULTIPLE_ENTRY_IF_REDUCTION, _design_flow_manager, _parameters)
122 {
123  debug_level = parameters->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
124 }
125 
127 
130 {
132  switch(relationship_type)
133  {
135  {
136  relationships.insert(std::make_pair(BB_FEEDBACK_EDGES_IDENTIFICATION, SAME_FUNCTION));
137  break;
138  }
140  {
141  relationships.insert(std::make_pair(PHI_OPT, SAME_FUNCTION));
142  relationships.insert(std::make_pair(BUILD_VIRTUAL_PHI, SAME_FUNCTION));
143  relationships.insert(std::make_pair(SIMPLE_CODE_MOTION, SAME_FUNCTION));
144  break;
145  }
147  {
148  switch(GetStatus())
149  {
151  {
152  relationships.insert(std::make_pair(PHI_OPT, SAME_FUNCTION));
153  relationships.insert(std::make_pair(SIMPLE_CODE_MOTION, SAME_FUNCTION));
154  break;
155  }
160  {
161  break;
162  }
166  break;
167  default:
168  THROW_UNREACHABLE("");
169  }
170  break;
171  }
172  default:
173  THROW_UNREACHABLE("");
174  }
175  return relationships;
176 }
177 
179 {
180  if(!parameters->IsParameter("meif_threshold"))
181  {
182  return false;
183  }
184  const auto frontend_step = design_flow_manager.lock()->GetDesignFlowStep(
185  FunctionFrontendFlowStep::ComputeSignature(FrontendFlowStepType::SIMPLE_CODE_MOTION, function_id));
186  if(!frontend_step)
187  {
188  return false;
189  }
190  const auto design_flow_graph = design_flow_manager.lock()->CGetDesignFlowGraph();
191  const auto design_flow_step = design_flow_graph->CGetDesignFlowStepInfo(frontend_step)->design_flow_step;
192  return GetPointerS<const simple_code_motion>(design_flow_step)->IsScheduleBased();
193 }
194 
196 {
197  bb_modified = false;
198  TM = AppM->get_tree_manager();
200  const auto fd = GetPointerS<const function_decl>(TM->CGetTreeNode(function_id));
201  sl = GetPointerS<statement_list>(GET_NODE(fd->body));
202  if(GetPointer<const HLS_manager>(AppM) && GetPointerS<const HLS_manager>(AppM)->get_HLS(function_id) &&
203  GetPointerS<const HLS_manager>(AppM)->get_HLS(function_id)->allocation_information)
204  {
205  allocation_information = GetPointerS<const HLS_manager>(AppM)->get_HLS(function_id)->allocation_information;
206  }
207 }
208 
210 {
211  THROW_ASSERT(parameters->IsParameter("meif_threshold"), "");
212  const auto threshold = parameters->GetParameter<double>("meif_threshold");
213  const auto max_iteration_number = parameters->IsParameter("meif_max_iterations_number") ?
214  parameters->GetParameter<size_t>("meif_max_iterations_number") :
216 
217  static size_t executed_iteration = 0;
218  if(executed_iteration >= max_iteration_number)
219  {
221  }
222 
224  bool modified = false;
226  std::list<unsigned int> block_to_erase;
227 
228  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Multiple Entry If Reduction");
229 
231  const auto bb_cfg = function_behavior->GetBBGraph(FunctionBehavior::BB);
232  const auto bb_fcfg = function_behavior->CGetBBGraph(FunctionBehavior::FBB);
233  const auto loops = function_behavior->CGetLoops();
234  const auto bb_index_map = bb_cfg->CGetBBGraphInfo()->bb_index_map;
235 
236  VertexIterator basic_block, basic_block_end;
237  for(boost::tie(basic_block, basic_block_end) = boost::vertices(*bb_fcfg); basic_block != basic_block_end;
238  basic_block++)
239  {
240  const auto block = bb_cfg->CGetBBNodeInfo(*basic_block)->block;
241  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Examining BB" + STR(block->number));
242  if(!AppM->ApplyNewTransformation())
243  {
244  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Skipped because reached max cfg transformations");
245  continue;
246  }
248  if(block->CGetStmtList().empty())
249  {
250  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Skipped because empty");
251  continue;
252  }
253  const auto last_stmt = GET_NODE(block->CGetStmtList().back());
254  if((!parameters->IsParameter("MEIR_y") || !parameters->GetParameter<bool>("MEIR_y")) &&
255  last_stmt->get_kind() != gimple_cond_K && last_stmt->get_kind() != gimple_multi_way_if_K)
256  {
257  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Skipped because does not end with a condition");
258  continue;
259  }
260  if(block->list_of_pred.size() < 2)
261  {
262  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Skipped because it has a single predecessor");
263  continue;
264  }
265  const bool vdef_op = [&]() -> bool {
266  for(const auto& stmt : block->CGetStmtList())
267  {
268  const auto ga = GetPointer<const gimple_assign>(GET_CONST_NODE(stmt));
269  if(ga && ga->temporary_address)
270  {
271  return true;
272  }
274  if(GET_CONST_NODE(stmt)->get_kind() == gimple_call_K)
275  {
276  return true;
277  }
278  }
279  return false;
280  }();
281 
282  if(vdef_op)
283  {
285  "<--Skipped because there is at least a vdef or a computation of an address");
286  continue;
287  }
288 
289  const auto area_weight = GetAreaCost(block->CGetStmtList());
290  const auto multiplier =
291  (parameters->IsParameter("MEIR_single") && parameters->GetParameter<bool>("MEIR_single")) ?
292  1 :
293  static_cast<double>(boost::in_degree(*basic_block, *bb_fcfg) - 1);
294  if(area_weight * multiplier > threshold)
295  {
297  "<--Skipped because too large " + STR(area_weight) + " * " +
298  STR((static_cast<double>(boost::in_degree(*basic_block, *bb_fcfg)) - 1)) +
299  " to be duplicated");
300  continue;
301  }
302 
304  if(boost::in_degree(*basic_block, *bb_cfg) != boost::in_degree(*basic_block, *bb_fcfg))
305  {
306  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Skipped because header loop");
307  continue;
308  }
309  const bool source_feedback =
310  boost::out_degree(*basic_block, *bb_cfg) != boost::out_degree(*basic_block, *bb_fcfg);
312  modified = true;
313 
315  auto loop_id = bb_cfg->CGetBBNodeInfo(*basic_block)->loop_id;
316 
318  auto depth = loops->CGetLoop(loop_id)->depth;
319 
320  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Modifying basic block graph");
323  InEdgeIterator to_be_copied_ie, to_be_copied_ie_end;
324  for(boost::tie(to_be_copied_ie, to_be_copied_ie_end) = boost::in_edges(*basic_block, *bb_cfg);
325  to_be_copied_ie != to_be_copied_ie_end; to_be_copied_ie++)
326  {
327  const auto source = boost::source(*to_be_copied_ie, *bb_cfg);
328  const auto source_block = bb_cfg->CGetBBNodeInfo(source)->block;
329  const auto source_id = source_block->number;
330 
331  const auto new_bb_index = sl->list_of_bloc.rbegin()->first + 1;
332  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Creating BB" + STR(new_bb_index));
333  copy_ids[source_id] = new_bb_index;
334 
335  const auto new_block = blocRef(new bloc(new_bb_index));
336  new_block->loop_id = block->loop_id;
337  if(GetPointer<HLS_manager>(AppM) && GetPointerS<HLS_manager>(AppM)->get_HLS(function_id))
338  {
339  new_block->schedule = GetPointerS<HLS_manager>(AppM)->get_HLS(function_id)->Rsch;
340  }
341  new_block->SetSSAUsesComputed();
342  sl->list_of_bloc[new_bb_index] = new_block;
343 
344  std::replace(source_block->list_of_succ.begin(), source_block->list_of_succ.end(), block->number,
345  new_bb_index);
346  if(source_block->true_edge == block->number)
347  {
348  source_block->true_edge = new_bb_index;
349  }
350  else if(source_block->false_edge == block->number)
351  {
352  source_block->false_edge = new_bb_index;
353  }
354  new_block->list_of_pred.push_back(source_id);
355  for(const auto& succ : block->list_of_succ)
356  {
357  const auto target_block = sl->list_of_bloc.at(succ);
358  const auto target_id = target_block->number;
359  if(target_block->number != BB_EXIT)
360  {
361  target_block->list_of_pred.push_back(new_bb_index);
362  }
363  new_block->list_of_succ.push_back(target_id);
364  if(block->true_edge == target_id)
365  {
366  new_block->true_edge = target_id;
367  }
368  else if(block->false_edge == target_id)
369  {
370  new_block->false_edge = target_id;
371  }
372  }
373  if(source_block->CGetStmtList().size() &&
374  GetPointer<gimple_multi_way_if>(GET_NODE(source_block->CGetStmtList().back())))
375  {
376  const auto gmwi = GetPointerS<gimple_multi_way_if>(GET_NODE(source_block->CGetStmtList().back()));
377  for(auto& cond : gmwi->list_of_cond)
378  {
379  if(cond.second == block->number)
380  {
381  cond.second = new_bb_index;
382  }
383  }
384  }
385  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Created BB" + STR(new_bb_index));
386  }
387  OutEdgeIterator oe, oe_end;
388  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Fixing other phis");
389  for(boost::tie(oe, oe_end) = boost::out_edges(*basic_block, *bb_fcfg); oe != oe_end; oe++)
390  {
391  const auto target = boost::target(*oe, *bb_cfg);
392  auto target_block = bb_cfg->CGetBBNodeInfo(target)->block;
393  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Fixing phis of BB" + STR(target_block->number));
395  for(const auto& phi : target_block->CGetPhiList())
396  {
398  auto gp = GetPointerS<gimple_phi>(GET_NODE(phi));
399  gimple_phi::DefEdgeList def_edge_list;
400  for(const auto& def_edge : gp->CGetDefEdgesList())
401  {
402  if(def_edge.second == block->number)
403  {
404  const auto sn = GetPointer<const ssa_name>(GET_NODE(def_edge.first));
405  if(!sn ||
406  GetPointerS<const gimple_node>(GET_CONST_NODE(sn->CGetDefStmt()))->bb_index != block->number)
407  {
408  for(const auto& copy_id : copy_ids)
409  {
410  def_edge_list.push_back(gimple_phi::DefEdge(def_edge.first, copy_id.second));
411  }
412  }
413  else
414  {
415  def_edge_list.push_back(def_edge);
416  }
417  }
418  else
419  {
420  def_edge_list.push_back(def_edge);
421  }
422  }
423  gp->SetDefEdgeList(TM, def_edge_list);
424  gp->SetSSAUsesComputed();
426  }
427  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Fixed phis of BB" + STR(target_block->number));
428  if(std::find(target_block->list_of_pred.begin(), target_block->list_of_pred.end(), block->number) !=
429  target_block->list_of_pred.end())
430  {
431  target_block->list_of_pred.erase(
432  std::find(target_block->list_of_pred.begin(), target_block->list_of_pred.end(), block->number));
433  }
434  }
438  for(const auto& copy : copy_ids)
439  {
440  tree_node_dups[copy.second] = tree_node_dupRef(new tree_node_dup(remaps[copy.second], AppM));
441  }
442  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Modified basic block graph");
443 
445  std::list<tree_nodeRef> gimples;
446  for(const auto& phi : block->CGetPhiList())
447  {
448  gimples.push_back(phi);
449  }
450  for(const auto& stmt : block->CGetStmtList())
451  {
452  gimples.push_back(stmt);
453  }
454  for(const auto& gimple : gimples)
455  {
456  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Considering gimple " + STR(gimple));
458  TreeNodeSet defined_sns;
459 
461  CustomSet<vertex> use_bbs;
462 
464  TreeNodeSet use_stmts;
465 
468 
471 
472  const auto vdef = GetPointer<const gimple_node>(GET_CONST_NODE(gimple))->vdef;
473  if(vdef)
474  {
475  defined_sns.insert(vdef);
476  }
477 
478  if(GET_CONST_NODE(gimple)->get_kind() == gimple_phi_K)
479  {
480  const auto old_gp = GetPointerS<const gimple_phi>(GET_CONST_NODE(gimple));
481  defined_sns.insert(old_gp->res);
482  for(const auto& def_edge : old_gp->CGetDefEdgesList())
483  {
484  THROW_ASSERT(copy_ids.count(def_edge.second),
485  "Copy BB connected to BB" + STR(def_edge.second) + " not found");
486  reaching_defs[copy_ids[def_edge.second]] = def_edge.first;
487  remaps[copy_ids[def_edge.second]][old_gp->res->index] = def_edge.first->index;
488  }
489  }
490  else if(GET_CONST_NODE(gimple)->get_kind() == gimple_assign_K)
491  {
492  const auto old_ga = GetPointerS<const gimple_assign>(GET_CONST_NODE(gimple));
493  if(GET_NODE(old_ga->op0)->get_kind() == ssa_name_K)
494  {
495  defined_sns.insert(old_ga->op0);
496  }
497  }
498  else if(GET_CONST_NODE(gimple)->get_kind() == gimple_multi_way_if_K ||
499  GET_CONST_NODE(gimple)->get_kind() == gimple_cond_K ||
500  GET_CONST_NODE(gimple)->get_kind() == gimple_return_K)
501  {
502  }
503  else
504  {
505  THROW_UNREACHABLE(STR(gimple));
506  }
508  if(GET_CONST_NODE(gimple)->get_kind() == gimple_phi_K)
509  {
510  }
511  else if(GET_CONST_NODE(gimple)->get_kind() == gimple_assign_K)
512  {
513  const auto ga = GetPointerS<const gimple_assign>(GET_CONST_NODE(gimple));
514  const auto ssa_uses = tree_helper::ComputeSsaUses(ga->op1);
515  for(const auto& ssa_use : ssa_uses)
516  {
517  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Considering use " + STR(ssa_use.first));
518  if(GetPointerS<const gimple_node>(
519  GET_CONST_NODE(GetPointerS<const ssa_name>(GET_CONST_NODE(ssa_use.first))->CGetDefStmt()))
520  ->bb_index == block->number)
521  {
522 #if HAVE_ASSERTS
523  for(const auto& copy : copy_ids)
524  {
525  THROW_ASSERT(remaps.at(copy.second).count(ssa_use.first->index), STR(ssa_use.first));
526  }
527 #endif
528  }
529  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Considered use " + STR(ssa_use.first));
530  }
531  for(const auto& copy : copy_ids)
532  {
533  if(GET_CONST_NODE(ga->op0)->get_kind() == ssa_name_K)
534  {
535  const auto ssa0 = GetPointerS<const ssa_name>(GET_CONST_NODE(ga->op0));
536  const auto new_ssa = tree_man->create_ssa_name(nullptr, ssa0->type, ssa0->min, ssa0->max);
537  remaps[copy.second][ga->op0->index] = new_ssa->index;
538  reaching_defs[copy.second] = new_ssa;
539  }
540  if(ga->vdef)
541  {
542  const auto new_ssa = tree_man->create_ssa_name(
543  nullptr, GetPointerS<const ssa_name>(GET_CONST_NODE(ga->vdef))->type, nullptr, nullptr);
544  GetPointerS<ssa_name>(GET_NODE(new_ssa))->virtual_flag = true;
545  remaps[copy.second][ga->vdef->index] = new_ssa->index;
546  reaching_defs[copy.second] = new_ssa;
547  }
548  const auto new_stmt = tree_node_dups[copy.second]->create_tree_node(GET_NODE(gimple));
550  "---New statement (" + STR(new_stmt) + ") is " + STR(TM->CGetTreeNode(new_stmt)));
551  sl->list_of_bloc.at(copy.second)->PushBack(TM->GetTreeReindex(new_stmt), AppM);
552  }
553  }
554  else if(GET_CONST_NODE(gimple)->get_kind() == gimple_multi_way_if_K ||
555  GET_CONST_NODE(gimple)->get_kind() == gimple_cond_K ||
556  GET_CONST_NODE(gimple)->get_kind() == gimple_return_K)
557  {
558  const auto ssa_uses = tree_helper::ComputeSsaUses(gimple);
559  for(const auto& ssa_use : ssa_uses)
560  {
561  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Considering use " + STR(ssa_use.first));
562  for(const auto& copy : copy_ids)
563  {
564  if((GetPointerS<const gimple_node>(
565  GET_CONST_NODE(GetPointerS<const ssa_name>(GET_CONST_NODE(ssa_use.first))->CGetDefStmt()))
566  ->bb_index != block->number))
567  {
569  remaps[copy.second][ssa_use.first->index] = ssa_use.first->index;
570  }
571  else
572  {
573  THROW_ASSERT(remaps.at(copy.second).count(ssa_use.first->index), STR(ssa_use.first));
574  }
575  }
576  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Considered use " + STR(ssa_use.first));
577  }
578  for(const auto& copy : copy_ids)
579  {
580  const auto new_stmt = tree_node_dups[copy.second]->create_tree_node(GET_NODE(gimple));
582  "---New statement is " + STR(TM->CGetTreeNode(new_stmt)));
583  sl->list_of_bloc.at(copy.second)->PushBack(TM->GetTreeReindex(new_stmt), AppM);
584  }
585  }
586  else
587  {
588  THROW_UNREACHABLE(STR(gimple));
589  }
590  for(const auto& defined_sn : defined_sns)
591  {
592  const auto sn = GetPointerS<ssa_name>(GET_NODE(defined_sn));
593  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Updating uses of " + sn->ToString());
595  TreeNodeSet uses_to_be_removed;
596  for(const auto& use_stmt : sn->CGetUseStmts())
597  {
599  "-->Considering use in " + STR(use_stmt.first->index) + " " + STR(use_stmt.first));
600  const auto use_bb_index = GetPointerS<const gimple_node>(GET_CONST_NODE(use_stmt.first))->bb_index;
601  if(bb_index_map.find(use_bb_index) == bb_index_map.end())
602  {
603  THROW_ASSERT(sn->virtual_flag, "");
604  const auto gn = GetPointerS<gimple_node>(GET_NODE(use_stmt.first));
605  THROW_ASSERT(gn->vovers.find(defined_sn) == gn->vovers.end(), "vovers not handled");
606  THROW_ASSERT(gn->vuses.find(defined_sn) != gn->vuses.end(), "vuse not found");
607  gn->vuses.erase(defined_sn);
608  uses_to_be_removed.insert(use_stmt.first);
609  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Removing use from just created statement");
610  continue;
611  }
612  const auto& use_bb = bb_index_map.at(use_bb_index);
613 
614  use_stmts.insert(use_stmt.first);
615  use_bbs.insert(use_bb);
616 
617  auto use_loop_id = bb_cfg->CGetBBNodeInfo(use_bb)->loop_id;
618  auto use_depth = loops->CGetLoop(use_loop_id)->depth;
619 
621  if(sn->virtual_flag && GET_NODE(use_stmt.first)->get_kind() != gimple_phi_K &&
622  !function_behavior->CheckBBReachability(*basic_block, use_bb))
623  {
624  const auto gn = GetPointerS<gimple_node>(GET_NODE(use_stmt.first));
625  THROW_ASSERT(gn->vovers.find(defined_sn) == gn->vovers.end(), "vovers not handled");
626  THROW_ASSERT(gn->vuses.find(defined_sn) != gn->vuses.end(), "vuse not found");
627  gn->vuses.erase(defined_sn);
628  uses_to_be_removed.insert(use_stmt.first);
630  "---Removing " + STR(defined_sn) + " from vuses of " + gn->ToString());
631  for(const auto& copy : copy_ids)
632  {
633  if(gn->AddVuse(TM->GetTreeReindex(remaps[copy.second][sn->index])))
634  {
635  const auto vssa = GetPointerS<ssa_name>(TM->GetTreeNode(remaps[copy.second][sn->index]));
636  vssa->AddUseStmt(use_stmt.first);
637  }
638  }
639  }
641  if(use_loop_id == loop_id)
642  {
643  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Use is in the same loop");
644  continue;
645  }
646  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Definition and use are in different loops");
648  "---Current loop is " + STR(loop_id) + " (depth is " + STR(depth) + ") - Use loop is " +
649  STR(use_loop_id) + " (depth " + STR(use_depth) + ")");
651  while(use_depth > depth)
652  {
653  use_loop_id = loops->CGetLoop(use_loop_id)->Parent()->GetId();
654  use_depth = loops->CGetLoop(use_loop_id)->depth;
655  }
657  while(use_depth < depth)
658  {
659  loop_id = loops->CGetLoop(loop_id)->Parent()->GetId();
660  depth = loops->CGetLoop(loop_id)->depth;
661  }
662  while(use_loop_id != loop_id)
663  {
664  use_loop_id = loops->CGetLoop(use_loop_id)->Parent()->GetId();
665  loop_id = loops->CGetLoop(loop_id)->Parent()->GetId();
666  depth = loops->CGetLoop(loop_id)->depth;
667  }
669  "<--Loop to be considered updated to " + STR(loop_id));
670  }
671  for(const auto& use_to_be_removed : uses_to_be_removed)
672  {
673  sn->RemoveUse(use_to_be_removed);
674  }
675  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Loop to be considered is " + STR(loop_id));
676 
677  // The set of header basic blocks where a phi has to be inserted
678  CustomSet<vertex> phi_headers;
679  auto current_loop = loops->CGetLoop(bb_cfg->CGetBBNodeInfo(*basic_block)->loop_id);
680  while(current_loop->GetId() != loop_id)
681  {
682  phi_headers.insert(current_loop->GetHeader());
684  "---Phi has to be added in header of loop " + STR(current_loop->GetId()));
685  current_loop = current_loop->Parent();
686  }
687  phi_headers.insert(current_loop->GetHeader());
689  "---Phi has to be added in header of loop " + STR(current_loop->GetId()));
690 
692  CustomUnorderedSet<vertex> loop_basic_blocks;
693  loops->CGetLoop(loop_id)->get_recursively_bb(loop_basic_blocks);
695  if(use_bbs.find(loops->CGetLoop(loop_id)->GetHeader()) == use_bbs.end())
696  {
697  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---SSA not used in the header of the loop");
699  CustomSet<vertex> to_be_removed;
700  for(const auto current : loop_basic_blocks)
701  {
703  "---Considering BB" + STR(bb_cfg->CGetBBNodeInfo(current)->block->number));
704  bool reachable = false;
705  for(const auto use_bb : use_bbs)
706  {
707  if(function_behavior->CheckBBReachability(current, use_bb))
708  {
710  "---BB" + STR(bb_cfg->CGetBBNodeInfo(use_bb)->block->number) +
711  " can be reached from BB" +
712  STR(bb_cfg->CGetBBNodeInfo(current)->block->number));
713  reachable = true;
714  break;
715  }
716  else if(current == use_bb)
717  {
719  "---BB" + STR(bb_cfg->CGetBBNodeInfo(use_bb)->block->number) +
720  " contains a use");
721  reachable = true;
722  break;
723  }
724  }
725  if(!reachable)
726  {
727  to_be_removed.insert(current);
728  }
729  }
730  for(const auto removable : to_be_removed)
731  {
733  "---Removing BB" + STR(bb_cfg->CGetBBNodeInfo(removable)->block->number));
734  loop_basic_blocks.erase(removable);
735  }
736  }
737 
739  std::set<vertex, bb_vertex_order_by_map> to_be_processed(
740  bb_vertex_order_by_map(function_behavior->get_bb_map_levels()));
741  OutEdgeIterator oe_basic_block, oe_basic_block_end;
742  for(boost::tie(oe_basic_block, oe_basic_block_end) = boost::out_edges(*basic_block, *bb_cfg);
743  oe_basic_block != oe_basic_block_end; oe_basic_block++)
744  {
745  const auto target = boost::target(*oe_basic_block, *bb_cfg);
746  if(loop_basic_blocks.find(target) != loop_basic_blocks.end())
747  {
748  to_be_processed.insert(target);
749  }
750  }
751 
752  while(to_be_processed.size())
753  {
754  const auto current = *(to_be_processed.begin());
755  const auto current_id = bb_cfg->CGetBBNodeInfo(current)->block->number;
756  const auto current_block = sl->list_of_bloc[current_id];
757  to_be_processed.erase(current);
758  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Checking BB" + STR(current_id));
759 
761 
762  if(current_block->list_of_pred.size() == 1)
763  {
764  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Single entry BB");
765  const auto source_id = current_block->list_of_pred.front();
766  if(reaching_defs.find(current_id) == reaching_defs.end() &&
767  reaching_defs.find(source_id) != reaching_defs.end())
768  {
769  reaching_defs[current_id] = reaching_defs[source_id];
770  }
771  }
772  else
773  {
774  bool build_phi = true;
775  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Multiple entries BB");
776  TreeNodeSet local_reaching_defs;
777  InEdgeIterator ie, ie_end;
778  for(boost::tie(ie, ie_end) = boost::in_edges(current, *bb_fcfg); ie != ie_end; ie++)
779  {
780  const auto source = boost::source(*ie, *bb_fcfg);
781  const auto source_id = bb_fcfg->CGetBBNodeInfo(source)->block->number;
782  if(bb_fcfg->GetSelector(*ie) & FB_CFG_SELECTOR)
783  {
785  "---Skipping feedback edge coming from BB" + STR(source_id));
786  }
787  else if(source_id == block->number)
788  {
789  for(const auto& copy_id : copy_ids)
790  {
791  THROW_ASSERT(reaching_defs.find(copy_id.second) != reaching_defs.end(),
792  "Definition coming from BB" + STR(copy_id.second) + " not found");
794  "---" + STR(reaching_defs.find(copy_id.second)->second) + " from BB" +
795  STR(copy_id.second));
796  local_reaching_defs.insert(reaching_defs.find(copy_id.second)->second);
797  }
798  }
799  else if(reaching_defs.find(source_id) != reaching_defs.end())
800  {
802  "---" + STR(reaching_defs.find(source_id)->second) + " from BB" +
803  STR(source_id));
804  local_reaching_defs.insert(reaching_defs[source_id]);
805  }
806  else
807  {
809  "---Nothing comes from BB" + STR(source_id));
810  build_phi = false;
811  }
812  }
813  if(build_phi)
814  {
815  if(local_reaching_defs.size() == 1)
816  {
817  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---PHI has not to be built");
818  reaching_defs[current_id] = *(local_reaching_defs.begin());
819  }
820  else
821  {
822  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---PHI has to be built");
823 
824  std::vector<gimple_phi::DefEdge> def_edges;
825  for(boost::tie(ie, ie_end) = boost::in_edges(current, *bb_fcfg); ie != ie_end; ie++)
826  {
827  const auto source = boost::source(*ie, *bb_fcfg);
828  const auto source_id = bb_fcfg->CGetBBNodeInfo(source)->block->number;
829  if(source_id == block->number)
830  {
831  for(const auto& copy_id : copy_ids)
832  {
833  THROW_ASSERT(reaching_defs.find(copy_id.second) != reaching_defs.end(), "");
834  THROW_ASSERT(reaching_defs.find(copy_id.second)->second, "");
835  def_edges.push_back(
836  gimple_phi::DefEdge(reaching_defs[copy_id.second], copy_id.second));
837  }
838  }
839  else
840  {
841  if((bb_fcfg->GetSelector(*ie) & FB_CFG_SELECTOR) == 0)
842  {
843  THROW_ASSERT(reaching_defs.find(source_id) != reaching_defs.end(), "");
844  THROW_ASSERT(reaching_defs.find(source_id)->second, "");
845  def_edges.push_back(gimple_phi::DefEdge(reaching_defs[source_id], source_id));
846  }
847  else
848  {
849  THROW_ASSERT(bb_fcfg->CGetBBNodeInfo(current)->loop_id ==
850  bb_fcfg->CGetBBNodeInfo(current)->block->number,
851  "");
852  def_edges.push_back(gimple_phi::DefEdge(reaching_defs[current_id], source_id));
853  }
854  }
855  }
856  tree_nodeRef phi_def_ssa_node;
857  const auto phi_gimple_stmt =
858  tree_man->create_phi_node(phi_def_ssa_node, def_edges, function_id, sn->virtual_flag);
859  THROW_ASSERT(tree_helper::CGetType(phi_def_ssa_node)->index ==
861  "");
862  auto new_gp = GetPointerS<gimple_phi>(GET_NODE(phi_gimple_stmt));
863  new_gp->SetSSAUsesComputed();
865  "---Created ssa_" +
866  STR(GetPointer<const ssa_name>(GET_CONST_NODE(phi_def_ssa_node))->vers));
867  bb_cfg->GetBBNodeInfo(current)->block->AddPhi(phi_gimple_stmt);
868  reaching_defs[current_id] = phi_def_ssa_node;
869  added_phis[current] = phi_gimple_stmt;
870  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created phi " + new_gp->ToString());
871  }
872  }
873  for(const auto& local_phi : bb_cfg->CGetBBNodeInfo(current)->block->CGetPhiList())
874  {
875  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Analyzing " + STR(local_phi));
876  auto uses = tree_helper::ComputeSsaUses(local_phi);
877  if(uses.find(TM->GetTreeReindex(sn->index)) != uses.end())
878  {
880  gimple_phi::DefEdgeList new_def_edge_list;
881  auto local_gp = GetPointerS<gimple_phi>(GET_NODE(local_phi));
882  for(const auto& def_edge : local_gp->CGetDefEdgesList())
883  {
885  "---" + STR(def_edge.first) + " comes from BB" + STR(def_edge.second));
886  if(def_edge.first->index == sn->index)
887  {
888  if(def_edge.second == block->number)
889  {
890  for(const auto& copy_id : copy_ids)
891  {
892  const auto new_source_id = copy_id.second;
893  THROW_ASSERT(reaching_defs.find(new_source_id) != reaching_defs.end(),
894  "Defintion coming from " + STR(new_source_id) + " not found");
895  new_def_edge_list.push_back(
896  gimple_phi::DefEdge(reaching_defs.find(new_source_id)->second, new_source_id));
897  }
898  }
899  else
900  {
901  THROW_ASSERT(reaching_defs.find(def_edge.second) != reaching_defs.end(),
902  "Defintion coming from " + STR(def_edge.second) + " not found");
903  new_def_edge_list.push_back(
904  gimple_phi::DefEdge(reaching_defs.find(def_edge.second)->second, def_edge.second));
905  }
906  }
907  else
908  {
909  new_def_edge_list.push_back(def_edge);
910  }
911  }
912  local_gp->SetDefEdgeList(TM, new_def_edge_list);
914  "<--Transformed in " + local_gp->ToString());
915  }
916  }
917  }
919  if(use_bbs.find(current) != use_bbs.end())
920  {
921  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->There is a use in BB" + STR(current_id));
922  for(const auto& stmt : bb_cfg->CGetBBNodeInfo(current)->block->CGetStmtList())
923  {
924  if(use_stmts.find(stmt) != use_stmts.end())
925  {
927  "---Replacing " + STR(sn) + " with " + STR(reaching_defs[current_id]) + " in " +
928  STR(stmt));
929  TM->ReplaceTreeNode(stmt, TM->GetTreeReindex(sn->index), reaching_defs[current_id]);
930  }
931  }
933  }
934 
935  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Checking successors");
936  for(boost::tie(oe, oe_end) = boost::out_edges(current, *bb_fcfg); oe != oe_end; oe++)
937  {
938  const auto target = boost::target(*oe, *bb_fcfg);
939  if(loop_basic_blocks.find(target) != loop_basic_blocks.end())
940  {
942  "---Considering BB" + STR(bb_fcfg->CGetBBNodeInfo(target)->block->number));
943  if((bb_fcfg->GetSelector(*oe) & FB_CFG_SELECTOR) != 0)
944  {
945  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Connected by feedback edge");
946  for(const auto& target_phi : bb_fcfg->CGetBBNodeInfo(target)->block->CGetPhiList())
947  {
948  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Analyzing " + STR(target_phi));
949  auto gp = GetPointerS<gimple_phi>(GET_NODE(target_phi));
950  for(const auto& def_edge : gp->CGetDefEdgesList())
951  {
952  if(def_edge.first->index == sn->index && def_edge.second == current_id)
953  {
954  THROW_ASSERT(reaching_defs.find(current_id) != reaching_defs.end(), "");
955  gp->ReplaceDefEdge(
956  TM, def_edge,
957  gimple_phi::DefEdge(reaching_defs.find(current_id)->second, def_edge.second));
958  }
959  }
960  }
962  }
963  else
964  {
965  to_be_processed.insert(target);
966  }
967  }
968  }
969  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Checked successors");
971  "<--Checked BB" + STR(bb_cfg->CGetBBNodeInfo(current)->block->number));
972  }
973  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Updated uses of " + sn->ToString());
974  }
975  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Considered " + STR(gimple));
976  }
978  if(source_feedback)
979  {
981  "-->Duplicating BB is source of feeback edges - Fixing header phis");
982  for(boost::tie(oe, oe_end) = boost::out_edges(*basic_block, *bb_fcfg); oe != oe_end; oe++)
983  {
984  if(bb_fcfg->GetSelector(*oe) & FB_CFG_SELECTOR)
985  {
986  const auto header = boost::target(*oe, *bb_fcfg);
987  const auto& header_bb_node_info = bb_fcfg->CGetBBNodeInfo(header)->block;
989  "BB" + STR(header_bb_node_info->number) + " is the header");
990  for(const auto& phi : header_bb_node_info->CGetPhiList())
991  {
993  auto gp = GetPointerS<gimple_phi>(GET_NODE(phi));
994  const auto old_def_edge_list = gp->CGetDefEdgesList();
995  gimple_phi::DefEdgeList new_def_edge_list;
996  for(const auto& old_def_edge : old_def_edge_list)
997  {
998  if(old_def_edge.second != block->number)
999  {
1000  new_def_edge_list.push_back(old_def_edge);
1001  }
1002  else
1003  {
1004  for(const auto& copy : copy_ids)
1005  {
1006  THROW_ASSERT(remaps.find(copy.second) != remaps.end(), STR(copy.second));
1007  THROW_ASSERT(remaps.find(copy.second)->second.find(old_def_edge.first->index) !=
1008  remaps.find(copy.second)->second.end(),
1009  STR(old_def_edge.first->index) + " " +
1010  STR(TM->CGetTreeNode(old_def_edge.first->index)));
1011  new_def_edge_list.push_back(gimple_phi::DefEdge(
1012  TM->GetTreeReindex(remaps[copy.second][old_def_edge.first->index]), copy.second));
1013  }
1014  }
1015  }
1016  gp->SetDefEdgeList(TM, new_def_edge_list);
1018  }
1019  }
1020  }
1022  "<--Duplicated BB is source of feeback edges - Fixing header phis");
1023  }
1024  while(block->CGetStmtList().size())
1025  {
1026  block->RemoveStmt(block->CGetStmtList().front(), AppM);
1027  }
1028  while(block->CGetPhiList().size())
1029  {
1030  block->RemovePhi(block->CGetPhiList().front());
1031  }
1032  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Ended duplicated " + STR(block->number));
1033  sl->list_of_bloc.erase(block->number);
1034  executed_iteration++;
1035  AppM->RegisterTransformation(GetName(), nullptr);
1036  break;
1037  }
1039  if(modified)
1040  {
1041  function_behavior->UpdateBBVersion();
1043  "-->starting erasing blocks " + STR(block_to_erase.size()));
1045 
1046  while(!block_to_erase.empty())
1047  {
1048  sl->list_of_bloc.erase(block_to_erase.back());
1049  block_to_erase.pop_back();
1050  }
1051  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--ending erasing blocks");
1052 
1054  }
1056 }
1057 
1058 double MultipleEntryIfReduction::GetAreaCost(const std::list<tree_nodeRef>& list_of_stmt) const
1059 {
1060  double ret_value = 0.0;
1061  for(const auto& temp_stmt : list_of_stmt)
1062  {
1063  const auto area = allocation_information->GetStatementArea(temp_stmt->index);
1064  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Area of " + STR(temp_stmt) + " is " + STR(area));
1065  ret_value += area;
1066  }
1067  return ret_value;
1068 }
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:343
MultipleEntryIfReduction(const ParameterConstRef _Param, const application_managerRef _AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
Data structure representing the entire HLS information.
Step does not exits.
This struct specifies the field bloc (basic block).
#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
Basic block control flow graph.
File containing functions and utilities to support the printing of debug messagges.
Step successfully executed.
string target
Definition: lenet_tvm.py:16
const tree_nodeRef CGetTreeReindex(const unsigned int i) const
Return a tree_reindex wrapping the i-th tree_node.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
void ReplaceTreeNode(const tree_nodeRef &stmt, const tree_nodeRef &old_node, const tree_nodeRef &new_node)
Replace the occurrences of tree node old_node with new_node in statement identified by tn...
#define BB_EXIT
constant identifying the basic block node of type exit
Definition of the class representing a generic C application.
refcount< tree_manipulation > tree_manipulationRef
std::string GetName() const override
Return the name of this design step.
Step successfully executed but without any IR change.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
std::list< DefEdge > DefEdgeList
The type of the def edge list.
Definition: tree_node.hpp:3753
CustomOrderedMap< T, U > CustomMap
Definition: custom_map.hpp:167
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.
Class performing the reduction of n input - m output BB by duplicating the BB over all its predecesso...
std::map< unsigned int, blocRef > list_of_bloc
list_of_bloc field is the list of basic block. If this field is null then the list_of_stmt field is n...
Definition: tree_node.hpp:4673
tree_manipulationRef tree_man
The tree manipulation.
Data structure describing a basic block at tree level.
redefinition of map to manage ordered/unordered structures
const tree_nodeConstRef CGetTreeNode(const unsigned int i) const
double GetStatementArea(const unsigned int statement_index) const
Returns the area for a given statement.
#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.
#define max
Definition: backprop.h:17
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec.
REF_FORWARD_DECL(tree_node_dup)
Header include.
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
redefinition of set to manage ordered/unordered structures
tree_nodeRef GetTreeReindex(const unsigned int i)
Return a tree_reindex wrapping the i-th tree_node.
const Wrefcount< const DesignFlowManager > design_flow_manager
The design flow manager.
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
#define GET_CONST_NODE(t)
Definition: tree_node.hpp:347
boost::graph_traits< graph >::vertex_iterator VertexIterator
vertex_iterator definition.
Definition: graph.hpp:1307
DesignFlowStep_Status GetStatus() const
Return the status of this design step.
Classes specification of the tree_node data structures.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
This package is used by all HLS packages to manage resource constraints and characteristics.
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.
tree_nodeRef GetTreeNode(const unsigned int index) const
Return the index-th tree_node (modifiable version)
refcount< T > lock() const
Definition: refcount.hpp:212
tree_managerRef TM
The tree manager.
const unsigned int function_id
The index of the function to be analyzed.
Analysis step that performs some simple code motions over the IR.
~MultipleEntryIfReduction() override
Destructor.
const application_managerRef AppM
The application manager.
Class specification of the tree_reindex support class.
Class specification of the basic_block structure.
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.
AllocationInformationConstRef allocation_information
The allocation information.
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
Classes specification of the tree_node data structures not present in the gcc.
this class is used to manage the command-line or XML options.
tree_nodeRef create_ssa_name(const tree_nodeConstRef &var, const tree_nodeConstRef &type, const tree_nodeConstRef &min, const tree_nodeConstRef &max, bool volatile_flag=false, bool virtual_flag=false) const
MISCELLANEOUS_OBJ_TREE_NODES.
tree node duplication class.
statement_list * sl
The statement list.
int debug_level
The debug level.
block(unsigned int i)
constructor
Definition: tree_node.hpp:1823
double GetAreaCost(const std::list< tree_nodeRef > &list_of_stmt) const
Estimate the area cost of the statements of a basic block.
tree_nodeRef create_phi_node(tree_nodeRef &ssa_res, const std::vector< std::pair< tree_nodeRef, unsigned int >> &list_of_def_edge, unsigned int function_decl_nid, bool virtual_flag=false) const
GIMPLE_PHI.
Data structure definition for high-level synthesis flow.
static void ComputeSsaUses(const tree_nodeRef &, TreeNodeMap< size_t > &uses)
recursively compute the references to the ssa_name variables used in a statement
Step is symbolic and it has already been marked.
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 brief description of the C++ Header File.
DesignFlowStep_Status InternalExec() override
Extract patterns from the IR.
const FunctionBehaviorRef function_behavior
The function behavior of the function to be analyzed.
Step not yet executed.
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