PandA-2024.02
multi_way_if.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  */
44 #include "multi_way_if.hpp"
45 #include "Parameter.hpp"
46 #include "application_manager.hpp"
47 #include "basic_block.hpp"
48 #include "call_graph.hpp"
49 #include "call_graph_manager.hpp"
51 #include "design_flow_graph.hpp"
52 #include "design_flow_manager.hpp"
53 #include "function_behavior.hpp"
54 #include "hls.hpp"
55 #include "hls_manager.hpp"
56 #if HAVE_ILP_BUILT
57 #include "hls_step.hpp"
58 #endif
59 #include "behavioral_helper.hpp"
60 #include "custom_map.hpp"
61 #include "custom_set.hpp"
62 #include "dbgPrintHelper.hpp" // for DEBUG_LEVEL_
63 #include "ext_tree_node.hpp"
64 #include "schedule.hpp"
65 #include "string_manipulation.hpp" // for GET_CLASS
66 #include "token_interface.hpp"
67 #include "tree_basic_block.hpp"
68 #include "tree_helper.hpp"
69 #include "tree_manager.hpp"
70 #include "tree_manipulation.hpp"
71 #include "tree_reindex.hpp"
72 #include <cstdlib>
73 #include <fstream>
74 
76  unsigned int _function_id, const DesignFlowManagerConstRef _design_flow_manager)
77  : FunctionFrontendFlowStep(_AppM, _function_id, MULTI_WAY_IF, _design_flow_manager, _parameters),
78  sl(nullptr),
79  bb_modified(false)
80 {
81  debug_level = parameters->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
82 }
83 
84 multi_way_if::~multi_way_if() = default;
85 
88 {
90  switch(relationship_type)
91  {
93  {
94  relationships.insert(std::make_pair(SWITCH_FIX, SAME_FUNCTION));
95  relationships.insert(std::make_pair(BLOCK_FIX, SAME_FUNCTION));
96  relationships.insert(std::make_pair(USE_COUNTING, SAME_FUNCTION));
97 #if HAVE_ILP_BUILT
98  if(parameters->getOption<HLSFlowStep_Type>(OPT_scheduling_algorithm) == HLSFlowStep_Type::SDC_SCHEDULING)
99  {
100  relationships.insert(std::make_pair(UPDATE_SCHEDULE, SAME_FUNCTION));
101  }
102 #endif
103  if(!parameters->getOption<int>(OPT_gcc_openmp_simd))
104  {
105  relationships.insert(std::make_pair(BITVALUE_RANGE, SAME_FUNCTION));
106  }
107  relationships.insert(std::make_pair(SHORT_CIRCUIT_TAF, SAME_FUNCTION));
108  break;
109  }
111  {
114  {
115  if(parameters->getOption<HLSFlowStep_Type>(OPT_scheduling_algorithm) == HLSFlowStep_Type::SDC_SCHEDULING and
116  GetPointer<const HLS_manager>(AppM) and GetPointer<const HLS_manager>(AppM)->get_HLS(function_id) and
117  GetPointer<const HLS_manager>(AppM)->get_HLS(function_id)->Rsch)
118  {
120  const auto update_schedule = design_flow_manager.lock()->GetDesignFlowStep(
121  FunctionFrontendFlowStep::ComputeSignature(FrontendFlowStepType::UPDATE_SCHEDULE, function_id));
122  if(update_schedule)
123  {
124  const DesignFlowGraphConstRef design_flow_graph = design_flow_manager.lock()->CGetDesignFlowGraph();
125  const DesignFlowStepRef design_flow_step =
126  design_flow_graph->CGetDesignFlowStepInfo(update_schedule)->design_flow_step;
127  if(GetPointer<const FunctionFrontendFlowStep>(design_flow_step)->CGetBBVersion() !=
128  function_behavior->GetBBVersion())
129  {
130  relationships.insert(std::make_pair(UPDATE_SCHEDULE, SAME_FUNCTION));
131  break;
132  }
133  }
134  }
135  }
136  break;
137  }
139  {
140  relationships.insert(std::make_pair(DETERMINE_MEMORY_ACCESSES, SAME_FUNCTION));
141  relationships.insert(std::make_pair(INTERFACE_INFER, WHOLE_APPLICATION));
142  relationships.insert(std::make_pair(REMOVE_CLOBBER_GA, SAME_FUNCTION));
143  break;
144  }
145  default:
146  {
147  THROW_UNREACHABLE("");
148  }
149  }
150  return relationships;
151 }
152 
154 {
155  bb_modified = false;
156  TM = AppM->get_tree_manager();
158  const auto temp = TM->CGetTreeNode(function_id);
159  const auto fd = GetPointerS<const function_decl>(temp);
160  sl = GetPointerS<statement_list>(GET_NODE(fd->body));
161 #if HAVE_ILP_BUILT
162  if(parameters->getOption<HLSFlowStep_Type>(OPT_scheduling_algorithm) == HLSFlowStep_Type::SDC_SCHEDULING and
163  GetPointer<const HLS_manager>(AppM) and GetPointer<const HLS_manager>(AppM)->get_HLS(function_id) and
164  GetPointer<const HLS_manager>(AppM)->get_HLS(function_id)->Rsch)
165  {
166  for(const auto& block : sl->list_of_bloc)
167  {
168  block.second->schedule = GetPointer<const HLS_manager>(AppM)->get_HLS(function_id)->Rsch;
169  }
170  }
171 #endif
172 }
173 
174 void multi_way_if::UpdateCfg(const blocRef& pred_bb, const blocRef& curr_bb)
175 {
176  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Updating control flow graph");
178  pred_bb->list_of_succ.erase(std::remove(pred_bb->list_of_succ.begin(), pred_bb->list_of_succ.end(), curr_bb->number),
179  pred_bb->list_of_succ.end());
180 
182  for(const auto succ : curr_bb->list_of_succ)
183  {
184  THROW_ASSERT(sl->list_of_bloc.count(succ), "");
185  const auto& succ_bb = sl->list_of_bloc.at(succ);
187  succ_bb->list_of_pred.erase(
188  std::remove(succ_bb->list_of_pred.begin(), succ_bb->list_of_pred.end(), curr_bb->number),
189  succ_bb->list_of_pred.end());
190 
192  if(std::find(succ_bb->list_of_pred.begin(), succ_bb->list_of_pred.end(), pred_bb->number) ==
193  succ_bb->list_of_pred.end())
194  {
195  succ_bb->list_of_pred.push_back(pred_bb->number);
196  }
197 
199  if(std::find(pred_bb->list_of_succ.begin(), pred_bb->list_of_succ.end(), succ) == pred_bb->list_of_succ.end())
200  {
201  pred_bb->list_of_succ.push_back(succ);
202  }
203 
205  for(const auto& phi : succ_bb->CGetPhiList())
206  {
207  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Original phi " + phi->ToString());
208  auto* current_phi = GetPointerS<gimple_phi>(GET_NODE(phi));
209  for(const auto& def_edge : current_phi->CGetDefEdgesList())
210  {
211  if(def_edge.second == curr_bb->number)
212  {
213  current_phi->ReplaceDefEdge(TM, def_edge, gimple_phi::DefEdge(def_edge.first, pred_bb->number));
214  }
215  }
216  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Modified phi " + phi->ToString());
217  }
218  }
219  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Updated control flow graph");
220 }
221 
223 {
224  CustomUnorderedMap<unsigned int, vertex> inverse_vertex_map;
225  BBGraphsCollectionRef GCC_bb_graphs_collection(
227  BBGraphRef GCC_bb_graph(new BBGraph(GCC_bb_graphs_collection, CFG_SELECTOR));
228 
229  CustomOrderedSet<unsigned int> bb_to_be_removed;
230  for(const auto& block : sl->list_of_bloc)
231  {
232  inverse_vertex_map[block.first] =
233  GCC_bb_graphs_collection->AddVertex(BBNodeInfoRef(new BBNodeInfo(block.second)));
234  }
236  for(const auto& bb : sl->list_of_bloc)
237  {
238  const auto& curr_bbi = bb.first;
239  const auto& curr_bb = bb.second;
240  for(const auto pred : curr_bb->list_of_pred)
241  {
242  GCC_bb_graphs_collection->AddEdge(inverse_vertex_map[pred], inverse_vertex_map[curr_bbi], CFG_SELECTOR);
243  }
244  for(const auto succ : curr_bb->list_of_succ)
245  {
246  if(succ == bloc::EXIT_BLOCK_ID)
247  {
248  GCC_bb_graphs_collection->AddEdge(inverse_vertex_map[curr_bbi], inverse_vertex_map[succ], CFG_SELECTOR);
249  }
250  }
251  if(curr_bb->list_of_succ.empty())
252  {
253  GCC_bb_graphs_collection->AddEdge(inverse_vertex_map[curr_bbi], inverse_vertex_map[bloc::EXIT_BLOCK_ID],
254  CFG_SELECTOR);
255  }
256  }
258  GCC_bb_graphs_collection->AddEdge(inverse_vertex_map[bloc::ENTRY_BLOCK_ID], inverse_vertex_map[bloc::EXIT_BLOCK_ID],
259  CFG_SELECTOR);
261  std::list<vertex> bb_sorted_vertices;
262  cyclic_topological_sort(*GCC_bb_graph, std::front_inserter(bb_sorted_vertices));
263  for(auto bb : bb_sorted_vertices)
264  {
265  const auto bb_node_info = GCC_bb_graph->CGetBBNodeInfo(bb);
266  const auto& curr_bbi = bb_node_info->block->number;
267  const auto& curr_bb = bb_node_info->block;
268  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Examining BB" + STR(curr_bbi));
270  (!parameters->IsParameter("print-dot-FF") || parameters->GetParameter<unsigned int>("print-dot-FF")))
271  {
272  WriteBBGraphDot("BB_Before_" + GetName() + "_" + STR(curr_bbi) + ".dot");
273  }
274  if(curr_bbi == bloc::ENTRY_BLOCK_ID || curr_bbi == bloc::EXIT_BLOCK_ID)
275  {
276  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Skipped because entry or exit");
277  continue;
278  }
279  if(bb_node_info->block->list_of_pred.size() > 1)
280  {
281  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Skipped because it has multiple predecessors");
282  continue;
283  }
284  const auto pred = bb_node_info->block->list_of_pred.front();
285  if(pred == bloc::ENTRY_BLOCK_ID)
286  {
287  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Skipped because predecessor is entry");
288  continue;
289  }
290  THROW_ASSERT(sl->list_of_bloc.count(pred), "");
291  const auto pred_bb = sl->list_of_bloc.at(pred);
292  if(pred_bb->CGetStmtList().empty())
293  {
294  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Skipped because predecessor is empty");
295  continue;
296  }
297  const auto last_pred_stmt = GET_NODE(pred_bb->CGetStmtList().back());
298  if(last_pred_stmt->get_kind() != gimple_cond_K && last_pred_stmt->get_kind() != gimple_multi_way_if_K)
299  {
301  "<--Skipped because predecessor ends with " + last_pred_stmt->get_kind_text());
302  continue;
303  }
304  if(curr_bb->CGetStmtList().size() != 1)
305  {
306  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Skipped because it is not a singleton");
307  continue;
308  }
309  const auto last_curr_stmt = GET_NODE(curr_bb->CGetStmtList().back());
310 #if 0
311  if(last_curr_stmt->get_kind() == gimple_multi_way_if_K)
312  {
313  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Skipped because it contains a multi way if");
314  continue;
315  }
316 #endif
317  if(last_curr_stmt->get_kind() != gimple_cond_K && last_curr_stmt->get_kind() != gimple_multi_way_if_K)
318  {
320  "<--Skipped because it ends with a " + last_curr_stmt->get_kind_text());
321  continue;
322  }
323  if(curr_bb->CGetPhiList().size() != 0)
324  {
325  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Skipped because it contains a phi");
326  continue;
327  }
328  if(!AppM->ApplyNewTransformation())
329  {
330  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Reached limit of cfg transformations");
331  continue;
332  }
333  AppM->RegisterTransformation(GetName(), tree_nodeConstRef());
338  bool restart = false;
339  const auto& curr_list_of_succ = curr_bb->list_of_succ;
340  do
341  {
342  restart = false;
343  for(const auto succ_bbi : pred_bb->list_of_succ)
344  {
345  if(std::find(curr_list_of_succ.begin(), curr_list_of_succ.end(), succ_bbi) != curr_list_of_succ.end())
346  {
348  "---BB" + STR(succ_bbi) + " is a common sucessor");
349  THROW_ASSERT(sl->list_of_bloc.count(succ_bbi), "");
350  FixCfg(curr_bb, sl->list_of_bloc.at(succ_bbi));
351  restart = true;
353  (!parameters->IsParameter("print-dot-FF") || parameters->GetParameter<unsigned int>("print-dot-FF")))
354  {
355  WriteBBGraphDot("BB_After_" + GetName() + "_" + STR(curr_bbi) + "_Fix.dot");
356  }
357  break;
358  }
359  }
360  }
362  while(restart);
363 
365  if(last_pred_stmt->get_kind() == gimple_cond_K && last_curr_stmt->get_kind() == gimple_cond_K)
366  {
368  "---Merging gimple_cond with gimple_cond (BB" + STR(curr_bbi) + " with BB" + STR(pred) + ")");
369  MergeCondCond(pred_bb, curr_bb);
370  }
371  else if(last_pred_stmt->get_kind() == gimple_cond_K && last_curr_stmt->get_kind() == gimple_multi_way_if_K)
372  {
374  "---Merging gimple_cond with gimple_multi_way_if (BB" + STR(curr_bbi) + " with BB" + STR(pred) +
375  ")");
376  MergeCondMulti(pred_bb, curr_bb);
377  }
378  else if(last_pred_stmt->get_kind() == gimple_multi_way_if_K &&
379  last_curr_stmt->get_kind() == gimple_multi_way_if_K)
380  {
382  "---Merging gimple_multi_way_if with gimple_multi_way_if (BB" + STR(curr_bbi) + " with BB" +
383  STR(pred) + ")");
384  MergeMultiMulti(pred_bb, curr_bb);
385  }
386  else
387  {
389  "---Merging gimple_multi_way_if with gimple_cond (BB" + STR(curr_bbi) + " with BB" + STR(pred) +
390  ")");
391  MergeMultiCond(pred_bb, curr_bb);
392  }
393  UpdateCfg(pred_bb, curr_bb);
394  bb_modified = true;
395  bb_to_be_removed.insert(curr_bbi);
397  (!parameters->IsParameter("print-dot-FF") || parameters->GetParameter<unsigned int>("print-dot-FF")))
398  {
399  WriteBBGraphDot("BB_After_" + GetName() + "_" + STR(curr_bbi) + ".dot");
400  }
402  }
403  CustomOrderedSet<unsigned int>::iterator it_tbr, it_tbr_end = bb_to_be_removed.end();
404  for(it_tbr = bb_to_be_removed.begin(); it_tbr != it_tbr_end; ++it_tbr)
405  {
406  sl->list_of_bloc.erase(*it_tbr);
407  }
408  bb_to_be_removed.clear();
409 
410  bb_modified ? function_behavior->UpdateBBVersion() : 0;
412 }
413 
414 void multi_way_if::MergeCondMulti(const blocRef& pred_bb, const blocRef& curr_bb)
415 {
417  std::map<TreeVocabularyTokenTypes_TokenEnum, std::string> IR_schema;
418  unsigned int gimple_multi_way_if_id = TM->new_tree_node_id();
419  IR_schema[TOK(TOK_SRCP)] = BUILTIN_SRCP;
420  IR_schema[TOK(TOK_SCPE)] = STR(function_id);
421  TM->create_tree_node(gimple_multi_way_if_id, gimple_multi_way_if_K, IR_schema);
422  auto new_gwi = GetPointerS<gimple_multi_way_if>(TM->get_tree_node_const(gimple_multi_way_if_id));
423  new_gwi->bb_index = pred_bb->number;
424 
425  const auto old_gwi = GetPointerS<const gimple_multi_way_if>(GET_CONST_NODE(curr_bb->CGetStmtList().back()));
426 
428  const auto ce_cond = tree_man->ExtractCondition(pred_bb->CGetStmtList().back(), pred_bb, function_id);
429 
431  pred_bb->RemoveStmt(pred_bb->CGetStmtList().back(), AppM);
432 
434  while(curr_bb->CGetStmtList().size())
435  {
436  curr_bb->RemoveStmt(curr_bb->CGetStmtList().front(), AppM);
437  }
438 
440  if(pred_bb->true_edge == curr_bb->number)
441  {
442  auto default_bb = 0u;
443  for(const auto& old_cond : old_gwi->list_of_cond)
444  {
445  if(old_cond.first)
446  {
447  const auto new_cond = tree_man->CreateAndExpr(ce_cond, old_cond.first, pred_bb, function_id);
448  new_gwi->add_cond(new_cond, old_cond.second);
449  }
450  else
451  {
452  default_bb = old_cond.second;
454  }
455  }
456  new_gwi->add_cond(tree_man->CreateNotExpr(ce_cond, pred_bb, function_id), pred_bb->false_edge);
457  new_gwi->add_cond(tree_nodeRef(), default_bb);
458  }
460  else
461  {
462  new_gwi->add_cond(ce_cond, pred_bb->true_edge);
463  for(const auto& old_cond : old_gwi->list_of_cond)
464  {
465  const auto not_second = tree_man->CreateNotExpr(ce_cond, pred_bb, function_id);
466  const tree_nodeRef new_cond =
467  old_cond.first ?
468  tree_man->CreateAndExpr(old_cond.first, tree_man->CreateNotExpr(ce_cond, pred_bb, function_id),
469  pred_bb, function_id) :
470  tree_nodeRef();
471  new_gwi->add_cond(new_cond, old_cond.second);
472  }
473  }
474  pred_bb->PushBack(TM->GetTreeReindex(gimple_multi_way_if_id), AppM);
475  pred_bb->false_edge = 0;
476  pred_bb->true_edge = 0;
477  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created " + new_gwi->ToString());
478 }
479 
480 void multi_way_if::MergeMultiMulti(const blocRef& pred_bb, const blocRef& curr_bb)
481 {
483  std::map<TreeVocabularyTokenTypes_TokenEnum, std::string> IR_schema;
484  unsigned int gimple_multi_way_if_id = TM->new_tree_node_id();
485  IR_schema[TOK(TOK_SRCP)] = BUILTIN_SRCP;
486  IR_schema[TOK(TOK_SCPE)] = STR(function_id);
487  TM->create_tree_node(gimple_multi_way_if_id, gimple_multi_way_if_K, IR_schema);
488  auto new_gwi = GetPointerS<gimple_multi_way_if>(TM->get_tree_node_const(gimple_multi_way_if_id));
489  new_gwi->bb_index = pred_bb->number;
490 
491  const auto old_gwi1 = GetPointerS<const gimple_multi_way_if>(GET_CONST_NODE(pred_bb->CGetStmtList().back()));
492  const auto old_gwi2 = GetPointerS<const gimple_multi_way_if>(GET_CONST_NODE(curr_bb->CGetStmtList().back()));
493  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---First gimple multi way if is " + old_gwi1->ToString());
494  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Second gimple multi way if is " + old_gwi2->ToString());
495 
497  pred_bb->RemoveStmt(pred_bb->CGetStmtList().back(), AppM);
498 
500  while(curr_bb->CGetStmtList().size())
501  {
502  curr_bb->RemoveStmt(curr_bb->CGetStmtList().front(), AppM);
503  }
504 
505  for(const auto& old_cond1 : old_gwi1->list_of_cond)
506  {
508  "-->Considering condition " + (old_cond1.first ? old_cond1.first->ToString() : " default"));
510  if(old_cond1.first && old_cond1.second == curr_bb->number)
511  {
513  "---It is not default and nested gimple_multi_way_if is on this edge");
514  for(const auto& old_cond2 : old_gwi2->list_of_cond)
515  {
516  if(old_cond2.first)
517  {
518  const auto new_cond = tree_man->CreateAndExpr(old_cond1.first, old_cond2.first, pred_bb, function_id);
519  new_gwi->add_cond(new_cond, old_cond2.second);
520  }
521  else
522  {
523  tree_nodeRef new_cond = tree_nodeRef();
524  for(const auto& other_old_cond2 : old_gwi2->list_of_cond)
525  {
526  if(other_old_cond2.first)
527  {
528  if(new_cond)
529  {
530  new_cond = tree_man->CreateAndExpr(
531  new_cond, tree_man->CreateNotExpr(other_old_cond2.first, pred_bb, function_id), pred_bb,
532  function_id);
533  }
534  else
535  {
536  new_cond = tree_man->CreateNotExpr(other_old_cond2.first, pred_bb, function_id);
537  }
538  }
539  }
540  new_cond = tree_man->CreateAndExpr(new_cond, old_cond1.first, pred_bb, function_id);
541  new_gwi->add_cond(new_cond, old_cond2.second);
542  }
543  }
544  }
546  else if(old_cond1.first)
547  {
549  "---It is not default and nested gimple_multi_way_if is not on this edge");
550  new_gwi->add_cond(old_cond1.first, old_cond1.second);
551  }
553  else if(old_cond1.second == curr_bb->number)
554  {
556  "---It is default and nested gimple_multi_way_if is on this edge");
558  tree_nodeRef not_cond = tree_nodeRef();
559  for(const auto& other_old_cond1 : old_gwi1->list_of_cond)
560  {
561  if(other_old_cond1.first)
562  {
563  if(not_cond)
564  {
565  not_cond = tree_man->CreateAndExpr(
566  not_cond, tree_man->CreateNotExpr(other_old_cond1.first, pred_bb, function_id), pred_bb,
567  function_id);
568  }
569  else
570  {
571  not_cond = tree_man->CreateNotExpr(other_old_cond1.first, pred_bb, function_id);
572  }
573  }
574  }
575  for(const auto& old_cond2 : old_gwi2->list_of_cond)
576  {
577  if(old_cond2.first)
578  {
579  const auto new_cond = tree_man->CreateAndExpr(not_cond, old_cond2.first, pred_bb, function_id);
580  new_gwi->add_cond(new_cond, old_cond2.second);
581  }
582  else
583  {
584  new_gwi->add_cond(tree_nodeRef(), old_cond2.second);
585  }
586  }
587  }
589  else
590  {
592  "---It is default and nested gimple_multi_way_if is not on this edge");
593  new_gwi->add_cond(tree_nodeRef(), old_cond1.second);
594  }
596  "<--Considered condition " + (old_cond1.first ? old_cond1.first->ToString() : " default"));
597  }
598  pred_bb->PushBack(TM->GetTreeReindex(gimple_multi_way_if_id), AppM);
599  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created " + new_gwi->ToString());
600 }
601 
602 void multi_way_if::MergeMultiCond(const blocRef& pred_bb, const blocRef& curr_bb)
603 {
605  std::map<TreeVocabularyTokenTypes_TokenEnum, std::string> IR_schema;
606  unsigned int gimple_multi_way_if_id = TM->new_tree_node_id();
607  IR_schema[TOK(TOK_SRCP)] = BUILTIN_SRCP;
608  IR_schema[TOK(TOK_SCPE)] = STR(function_id);
609  TM->create_tree_node(gimple_multi_way_if_id, gimple_multi_way_if_K, IR_schema);
610  auto new_gwi = GetPointerS<gimple_multi_way_if>(TM->get_tree_node_const(gimple_multi_way_if_id));
611  new_gwi->bb_index = pred_bb->number;
612 
613  const auto old_gwi = GetPointerS<const gimple_multi_way_if>(GET_CONST_NODE(pred_bb->CGetStmtList().back()));
614  const auto old_ce = curr_bb->CGetStmtList().back();
615  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Gimple multi way if is " + old_gwi->ToString());
616  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Gimple cond " + old_ce->ToString());
617 
619  pred_bb->RemoveStmt(pred_bb->CGetStmtList().back(), AppM);
620 
622  while(curr_bb->CGetStmtList().size())
623  {
624  curr_bb->RemoveStmt(curr_bb->CGetStmtList().front(), AppM);
625  }
626 
628  const auto ce_cond = tree_man->ExtractCondition(old_ce, pred_bb, function_id);
629  for(const auto& old_cond : old_gwi->list_of_cond)
630  {
632  if(old_cond.first && old_cond.second == curr_bb->number)
633  {
634  const auto true_cond = tree_man->CreateAndExpr(old_cond.first, ce_cond, pred_bb, function_id);
635  new_gwi->add_cond(true_cond, curr_bb->true_edge);
636  const auto false_cond = tree_man->CreateAndExpr(
637  old_cond.first, tree_man->CreateNotExpr(ce_cond, pred_bb, function_id), pred_bb, function_id);
638  new_gwi->add_cond(false_cond, curr_bb->false_edge);
639  }
641  else if(old_cond.first)
642  {
643  new_gwi->add_cond(old_cond.first, old_cond.second);
644  }
646  else if(old_cond.second == curr_bb->number)
647  {
649  tree_nodeRef not_cond = tree_nodeRef();
650  for(const auto& other_old_cond : old_gwi->list_of_cond)
651  {
652  if(other_old_cond.first)
653  {
654  if(not_cond)
655  {
656  not_cond = tree_man->CreateAndExpr(
657  not_cond, tree_man->CreateNotExpr(other_old_cond.first, pred_bb, function_id), pred_bb,
658  function_id);
659  }
660  else
661  {
662  not_cond = tree_man->CreateNotExpr(other_old_cond.first, pred_bb, function_id);
663  }
664  }
665  }
666  const auto true_cond = tree_man->CreateAndExpr(not_cond, ce_cond, pred_bb, function_id);
667  new_gwi->add_cond(true_cond, curr_bb->true_edge);
668  new_gwi->add_cond(tree_nodeRef(), curr_bb->false_edge);
669  }
671  else
672  {
673  new_gwi->add_cond(tree_nodeRef(), old_cond.second);
674  }
675  }
676  pred_bb->PushBack(TM->GetTreeReindex(gimple_multi_way_if_id), AppM);
677  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created " + new_gwi->ToString());
678 }
679 
680 void multi_way_if::MergeCondCond(const blocRef& pred_bb, const blocRef& curr_bb)
681 {
683  const auto list_of_stmt_cond1 = pred_bb->CGetStmtList();
684  THROW_ASSERT(GET_CONST_NODE(list_of_stmt_cond1.back())->get_kind() == gimple_cond_K, "a gimple_cond is expected");
685  const auto cond1_statement = list_of_stmt_cond1.back();
686  pred_bb->RemoveStmt(cond1_statement, AppM);
687  const auto ssa1_node = tree_man->ExtractCondition(cond1_statement, pred_bb, function_id);
688 
690  const auto list_of_stmt_cond2 = curr_bb->CGetStmtList();
691  THROW_ASSERT(GET_CONST_NODE(list_of_stmt_cond2.back())->get_kind() == gimple_cond_K, "a gimple_cond is expected");
692  const auto cond2_statement = list_of_stmt_cond2.back();
693  curr_bb->RemoveStmt(cond2_statement, AppM);
694  const auto ssa2_node = tree_man->ExtractCondition(cond2_statement, pred_bb, function_id);
695 
697  std::map<TreeVocabularyTokenTypes_TokenEnum, std::string> IR_schema;
698  const auto gimple_multi_way_if_id = TM->new_tree_node_id();
699  IR_schema[TOK(TOK_SRCP)] = BUILTIN_SRCP;
700  IR_schema[TOK(TOK_SCPE)] = STR(function_id);
701  TM->create_tree_node(gimple_multi_way_if_id, gimple_multi_way_if_K, IR_schema);
702  IR_schema.clear();
703  const auto gimple_multi_way_if_stmt = TM->GetTreeReindex(gimple_multi_way_if_id);
704  auto* gmwi = GetPointerS<gimple_multi_way_if>(GET_NODE(gimple_multi_way_if_stmt));
705  gmwi->bb_index = pred_bb->number;
706  if(pred_bb->false_edge == curr_bb->number)
707  {
708  gmwi->add_cond(ssa1_node, pred_bb->true_edge);
709  const auto res_and = tree_man->CreateAndExpr(ssa2_node, tree_man->CreateNotExpr(ssa1_node, pred_bb, function_id),
710  pred_bb, function_id);
711  gmwi->add_cond(res_and, curr_bb->true_edge);
712  gmwi->add_cond(tree_nodeRef(), curr_bb->false_edge);
713  }
714  else
715  {
716  const auto res_not = tree_man->CreateNotExpr(ssa1_node, pred_bb, function_id);
717  gmwi->add_cond(res_not, pred_bb->false_edge);
718  const auto res_and2 = tree_man->CreateAndExpr(ssa1_node, ssa2_node, pred_bb, function_id);
719  gmwi->add_cond(res_and2, curr_bb->true_edge);
720  gmwi->add_cond(tree_nodeRef(), curr_bb->false_edge);
721  }
722  pred_bb->PushBack(gimple_multi_way_if_stmt, AppM);
723  pred_bb->false_edge = 0;
724  pred_bb->true_edge = 0;
725  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Created " + gmwi->ToString());
726 }
727 
728 void multi_way_if::FixCfg(const blocRef& pred_bb, const blocRef& succ_bb)
729 {
731  const unsigned int new_basic_block_index = (sl->list_of_bloc.rbegin())->first + 1;
732  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Adding BB" + STR(new_basic_block_index));
733 
735  const auto new_block = blocRef(new bloc(new_basic_block_index));
736  sl->list_of_bloc[new_basic_block_index] = new_block;
737 
738  new_block->list_of_pred.push_back(pred_bb->number);
739  new_block->list_of_succ.push_back(succ_bb->number);
740  new_block->loop_id = succ_bb->loop_id;
741  new_block->SetSSAUsesComputed();
742  new_block->schedule = pred_bb->schedule;
743 
745  THROW_ASSERT(std::find(pred_bb->list_of_succ.begin(), pred_bb->list_of_succ.end(), succ_bb->number) !=
746  pred_bb->list_of_succ.end(),
747  "");
748  pred_bb->list_of_succ.erase(std::remove(pred_bb->list_of_succ.begin(), pred_bb->list_of_succ.end(), succ_bb->number),
749  pred_bb->list_of_succ.end());
750  pred_bb->list_of_succ.push_back(new_basic_block_index);
751  if(pred_bb->true_edge == succ_bb->number)
752  {
753  pred_bb->true_edge = new_basic_block_index;
754  }
755  if(pred_bb->false_edge == succ_bb->number)
756  {
757  pred_bb->false_edge = new_basic_block_index;
758  }
759 
761  const auto& pred_list_of_stmt = pred_bb->CGetStmtList();
762  THROW_ASSERT(pred_list_of_stmt.size(), "Unexpexted condition");
763  const auto pred_last_stmt = GET_NODE(pred_list_of_stmt.back());
764  if(pred_last_stmt->get_kind() == gimple_multi_way_if_K)
765  {
766  auto gmwi = GetPointerS<gimple_multi_way_if>(pred_last_stmt);
767  for(auto& cond : gmwi->list_of_cond)
768  {
769  if(cond.second == succ_bb->number)
770  {
771  cond.second = new_basic_block_index;
772  }
773  }
774  }
775 
777  succ_bb->list_of_pred.erase(std::remove(succ_bb->list_of_pred.begin(), succ_bb->list_of_pred.end(), pred_bb->number),
778  succ_bb->list_of_pred.end());
779  succ_bb->list_of_pred.push_back(new_basic_block_index);
780 
782  for(const auto& phi : succ_bb->CGetPhiList())
783  {
784  auto gp = GetPointer<gimple_phi>(GET_NODE(phi));
785  for(auto& def_edge : gp->CGetDefEdgesList())
786  {
787  if(def_edge.second == pred_bb->number)
788  {
789  gp->ReplaceDefEdge(TM, def_edge, gimple_phi::DefEdge(def_edge.first, new_basic_block_index));
790  }
791  }
792  }
793  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Added BB" + STR(new_basic_block_index));
794 }
795 
797 {
799  {
800  return false;
801  }
802 
803 #if HAVE_ILP_BUILT
804  if(parameters->getOption<HLSFlowStep_Type>(OPT_scheduling_algorithm) == HLSFlowStep_Type::SDC_SCHEDULING)
805  {
806  if(GetPointer<const HLS_manager>(AppM) and GetPointer<const HLS_manager>(AppM)->get_HLS(function_id) and
807  GetPointer<const HLS_manager>(AppM)->get_HLS(function_id)->Rsch)
808  {
810  const auto update_schedule = design_flow_manager.lock()->GetDesignFlowStep(
811  FunctionFrontendFlowStep::ComputeSignature(FrontendFlowStepType::UPDATE_SCHEDULE, function_id));
812  if(update_schedule)
813  {
814  const DesignFlowGraphConstRef design_flow_graph = design_flow_manager.lock()->CGetDesignFlowGraph();
815  const DesignFlowStepRef design_flow_step =
816  design_flow_graph->CGetDesignFlowStepInfo(update_schedule)->design_flow_step;
817  if(GetPointer<const FunctionFrontendFlowStep>(design_flow_step)->CGetBBVersion() !=
818  function_behavior->GetBBVersion())
819  {
820  return false;
821  }
822  else
823  {
824  return true;
825  }
826  }
827  else
828  {
829  return false;
830  }
831  }
832  else
833  {
834  return true;
835  }
836  }
837 #endif
838 
840  if(parameters->getOption<int>(OPT_gcc_openmp_simd))
841  {
842  const auto vectorize_vertex =
843  design_flow_manager.lock()->GetDesignFlowStep(ComputeSignature(FrontendFlowStepType::VECTORIZE, function_id));
844  if(vectorize_vertex == NULL_VERTEX)
845  {
846  return false;
847  }
848  const auto vectorize_step =
849  design_flow_manager.lock()->CGetDesignFlowGraph()->CGetDesignFlowStepInfo(vectorize_vertex)->design_flow_step;
850  if(GetPointer<const FunctionFrontendFlowStep>(vectorize_step)->CGetBBVersion() == 0)
851  {
852  return false;
853  }
854  }
855 
856  return true;
857 }
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:343
statement_list * sl
The statement list of the analyzed function.
tree_nodeRef CreateNotExpr(const tree_nodeConstRef &condition, const blocRef &block, unsigned int function_decl_nid) const
UTILITY.
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
tree_nodeRef ExtractCondition(const tree_nodeRef &condition, const blocRef &block, unsigned int function_decl_nid) const
Extract computation of condition from a gimple_cond.
Data structure representing the entire HLS information.
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;.
multi_way_if(const ParameterConstRef _Param, const application_managerRef _AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
File containing functions and utilities to support the printing of debug messagges.
Step successfully executed.
Definition of the node_info object for the basic_block graph.
void MergeMultiMulti(const blocRef &pred_bb, const blocRef &curr_bb)
Merge two gimple_multi_way_if in a single one.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
void MergeCondCond(const blocRef &pred_bb, const blocRef &curr_bb)
Merge two basic blocks both ending with gimple_cond_K.
~multi_way_if() override
Destructor.
void UpdateCfg(const blocRef &pred_bb, const blocRef &curr_bb)
Update the basic block control flow graph data structure.
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.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
bool bb_modified
Modified file.
A simple interface to token object of the raw files.
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
static const unsigned int EXIT_BLOCK_ID
constant identifying the exit basic block
void MergeCondMulti(const blocRef &pred_bb, const blocRef &curr_bb)
Build the gimple_multi_way_if by mergin a gimple_cond with a gimple_multi_way_if. ...
Data structure describing a basic block at tree level.
redefinition of map to manage ordered/unordered structures
#define TOK(token)
Macro used to convert a token symbol into a treeVocabularyTokenTypes.
const tree_nodeConstRef CGetTreeNode(const unsigned int i) const
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec.
const tree_nodeRef get_tree_node_const(unsigned int i) const
Return the reference to the i-th tree_node Constant version of get_tree_node.
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 THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
void FixCfg(const blocRef &pred_bb, const blocRef &succ_bb)
Insert a basic block on an edge.
void MergeMultiCond(const blocRef &pred_bb, const blocRef &curr_bb)
Merge a gimple_cond in a gimple_multi_way_if.
Class used to describe a particular graph with basic blocks as nodes.
absl::flat_hash_map< T, U, Hash, Eq, Alloc > CustomUnorderedMap
Definition: custom_map.hpp:148
Data structure used to store the schedule of the operations.
unsigned int new_tree_node_id(const unsigned int ask=0)
Return a new node id in the intermediate representation.
HLSFlowStep_Type
Definition: hls_step.hpp:95
void cyclic_topological_sort(VertexListGraph &g, OutputIterator result, const boost::bgl_named_params< P, T, R > &params)
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
refcount< BBNodeInfo > BBNodeInfoRef
refcount definition of the class
void WriteBBGraphDot(const std::string &filename) const
Write the current version of statement list in dot format.
Information associated with the whole basic-block graph.
void create_tree_node(const unsigned int node_id, enum kind tree_node_type, std::map< TreeVocabularyTokenTypes_TokenEnum, std::string > &tree_node_schema)
Factory method.
Classes to describe design flow graph.
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.
Analysis step rebuilding multi-way if.
#define GET_CONST_NODE(t)
Definition: tree_node.hpp:347
refcount< const tree_node > tree_nodeConstRef
Definition: tree_node.hpp:213
DesignFlowStep_Status GetStatus() const
Return the status of this design step.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
Call graph hierarchy.
Class defining some useful functions to create tree nodes and to manipulate the tree manager...
#define DEBUG_LEVEL_NONE
no debugging print is performed.
Wrapper of design_flow.
This struct specifies the block node.
Definition: tree_node.hpp:1820
This file collects some utility functions.
tree_manipulationRef tree_man
The tree manipulation.
refcount< T > lock() const
Definition: refcount.hpp:212
#define BUILTIN_SRCP
const unsigned int function_id
The index of the function to be analyzed.
tree_managerRef TM
The tree manager.
const application_managerRef AppM
The application manager.
Class specification of the tree_reindex support class.
static const unsigned int ENTRY_BLOCK_ID
constant identifying the entry basic block
File used to compute the topological sort in a cyclic graph.
Class specification of the basic_block structure.
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
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.
refcount< tree_node > tree_nodeRef
RefCount type definition of the tree_node class structure.
Definition: tree_node.hpp:212
Wrapper to call graph.
int debug_level
The debug level.
#define CFG_SELECTOR
Control flow graph edge selector.
Data structure definition for high-level synthesis flow.
DesignFlowStep_Status InternalExec() override
Restructures the unstructured code.
refcount< BBGraphInfo > BBGraphInfoRef
refcount definition of the class
#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. ...
tree_nodeRef CreateAndExpr(const tree_nodeConstRef &first_condition, const tree_nodeConstRef &second_condition, const blocRef &block, unsigned int function_decl_nid) const
Create an or expression.
Class specification of the manager of the tree structures extracted from the raw file.
A brief description of the C++ Header File.
const FunctionBehaviorRef function_behavior
The function behavior of the function to be analyzed.
int sl
Definition: adpcm.c:105
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.
This structure defines graphs where nodes are basic_blocks.
#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