PandA-2024.02
short_circuit_taf.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 "short_circuit_taf.hpp"
46 
47 #include "phi_opt.hpp"
48 
50 #include "application_manager.hpp"
51 #include "call_graph.hpp"
52 #include "call_graph_manager.hpp"
53 #include "function_behavior.hpp"
54 
56 #if HAVE_ILP_BUILT
57 #include "hls.hpp"
58 #include "hls_manager.hpp"
59 #include "hls_step.hpp"
60 #endif
61 
63 #include "Parameter.hpp"
64 
66 #include "design_flow_graph.hpp"
67 #include "design_flow_manager.hpp"
68 
70 #include "hls_manager.hpp"
71 
73 #include "token_interface.hpp"
74 
76 #include <fstream>
77 
79 #include "custom_set.hpp"
80 #include <utility>
81 #include <vector>
82 
84 #include "technology_flow_step.hpp"
86 
88 #include "behavioral_helper.hpp"
89 #include "ext_tree_node.hpp"
90 #include "tree_basic_block.hpp"
91 #include "tree_helper.hpp"
92 #include "tree_manager.hpp"
93 #include "tree_manipulation.hpp"
94 #include "tree_node.hpp"
95 #include "tree_reindex.hpp"
96 
98 #include "dbgPrintHelper.hpp" // for DEBUG_LEVEL_
99 #include "string_manipulation.hpp" // for GET_CLASS
100 
102  unsigned int _function_id, const DesignFlowManagerConstRef _design_flow_manager)
103  : FunctionFrontendFlowStep(_AppM, _function_id, SHORT_CIRCUIT_TAF, _design_flow_manager, _parameters)
104 {
105  debug_level = parameters->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
106 }
107 
109 
112 {
114  switch(relationship_type)
115  {
117  {
118  relationships.insert(std::make_pair(BLOCK_FIX, SAME_FUNCTION));
119  relationships.insert(std::make_pair(SWITCH_FIX, SAME_FUNCTION));
120  relationships.insert(std::make_pair(USE_COUNTING, SAME_FUNCTION));
121  relationships.insert(std::make_pair(UN_COMPARISON_LOWERING, SAME_FUNCTION));
122 #if HAVE_ILP_BUILT
123  if(parameters->getOption<HLSFlowStep_Type>(OPT_scheduling_algorithm) == HLSFlowStep_Type::SDC_SCHEDULING)
124  {
125  relationships.insert(std::make_pair(UPDATE_SCHEDULE, SAME_FUNCTION));
126  }
127 #endif
128  if(!parameters->getOption<int>(OPT_gcc_openmp_simd))
129  {
130  relationships.insert(std::make_pair(BITVALUE_RANGE, SAME_FUNCTION));
131  }
132  break;
133  }
135  {
138  {
139  if(parameters->getOption<HLSFlowStep_Type>(OPT_scheduling_algorithm) == HLSFlowStep_Type::SDC_SCHEDULING and
140  GetPointer<const HLS_manager>(AppM) and GetPointer<const HLS_manager>(AppM)->get_HLS(function_id) and
141  GetPointer<const HLS_manager>(AppM)->get_HLS(function_id)->Rsch)
142  {
144  const auto update_schedule = design_flow_manager.lock()->GetDesignFlowStep(
145  FunctionFrontendFlowStep::ComputeSignature(FrontendFlowStepType::UPDATE_SCHEDULE, function_id));
146  if(update_schedule)
147  {
148  const DesignFlowGraphConstRef design_flow_graph = design_flow_manager.lock()->CGetDesignFlowGraph();
149  const DesignFlowStepRef design_flow_step =
150  design_flow_graph->CGetDesignFlowStepInfo(update_schedule)->design_flow_step;
151  if(GetPointer<const FunctionFrontendFlowStep>(design_flow_step)->CGetBBVersion() !=
152  function_behavior->GetBBVersion())
153  {
154  relationships.insert(std::make_pair(UPDATE_SCHEDULE, SAME_FUNCTION));
155  break;
156  }
157  }
158  }
159  }
160  else
161  {
162  relationships.insert(std::make_pair(EXTRACT_GIMPLE_COND_OP, SAME_FUNCTION));
163  }
164  break;
165  }
167  {
168  relationships.insert(std::make_pair(DETERMINE_MEMORY_ACCESSES, SAME_FUNCTION));
169  relationships.insert(std::make_pair(INTERFACE_INFER, WHOLE_APPLICATION));
170  relationships.insert(std::make_pair(REMOVE_CLOBBER_GA, SAME_FUNCTION));
171  relationships.insert(std::make_pair(EXTRACT_GIMPLE_COND_OP, SAME_FUNCTION));
172  break;
173  }
174  default:
175  {
176  THROW_UNREACHABLE("");
177  }
178  }
179  return relationships;
180 }
181 
183 {
184 }
185 
187 {
188  const auto TM = AppM->get_tree_manager();
189  const auto temp = TM->CGetTreeNode(function_id);
190  const auto fd = GetPointer<const function_decl>(temp);
191  const auto sl = GetPointer<statement_list>(GET_NODE(fd->body));
192 
194  CustomUnorderedSet<unsigned int> merging_candidates;
195  for(const auto& idx_bb : sl->list_of_bloc)
196  {
197  if(idx_bb.first == bloc::ENTRY_BLOCK_ID || idx_bb.first == bloc::EXIT_BLOCK_ID)
198  {
199  continue;
200  }
201  unsigned int n_pred_bb = 0;
202  if(idx_bb.second->list_of_pred.size() <= 1)
203  {
204  continue;
205  }
206  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Analyzing BB" + STR(idx_bb.first));
207  for(auto const pred : idx_bb.second->list_of_pred)
208  {
209  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Analyzing predecessor BB" + STR(pred));
210  if(pred != bloc::ENTRY_BLOCK_ID && idx_bb.first != pred && sl->list_of_bloc.at(pred)->CGetStmtList().size() &&
211  GET_CONST_NODE(sl->list_of_bloc.at(pred)->CGetStmtList().back())->get_kind() == gimple_cond_K)
212  {
213  ++n_pred_bb;
215  }
216  else
217  {
219  }
220  }
221  if(n_pred_bb > 1 && check_phis(idx_bb.first, sl->list_of_bloc))
222  {
223  merging_candidates.insert(idx_bb.first);
224  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Added candidate BB" + STR(idx_bb.first));
225  }
226  else
227  {
228  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Skipped BB" + STR(idx_bb.first));
229  }
230  }
231  if(!merging_candidates.empty())
232  {
233  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Merging candidate number " + STR(merging_candidates.size()));
234  }
235  else
236  {
238  }
239 
241  auto bb1 = static_cast<unsigned int>(-1), bb2 = static_cast<unsigned int>(-1), merging_candidate = 0U;
242  bool bb1_true = false;
243  bool bb2_true = false;
244  bool mergeable_pair_found;
245  bool something_change = false;
246 
247  int merge_n = 0;
248  do
249  {
250  mergeable_pair_found = false;
251  const auto it_mc_end = merging_candidates.cend();
252  for(auto it_mc = merging_candidates.cbegin(); !mergeable_pair_found && it_mc != it_mc_end; ++it_mc)
253  {
254  merging_candidate = *it_mc;
255  mergeable_pair_found =
256  check_merging_candidate(bb1, bb2, merging_candidate, bb1_true, bb2_true, sl->list_of_bloc);
257  }
258  if(!AppM->ApplyNewTransformation())
259  {
260  break;
261  }
262  if(mergeable_pair_found)
263  {
264  AppM->RegisterTransformation(GetName(), tree_nodeConstRef());
265  if(create_gimple_cond(bb1, bb2, bb1_true, sl->list_of_bloc, bb2_true, merging_candidate))
266  {
267  something_change = true;
268  restructure_CFG(bb1, bb2, merging_candidate, sl->list_of_bloc);
269  merging_candidates.erase(bb1);
270  if(!check_merging_candidate(bb1, bb2, merging_candidate, bb1_true, bb2_true, sl->list_of_bloc))
271  {
272  merging_candidates.erase(merging_candidate);
273  }
275  (!parameters->IsParameter("print-dot-FF") || parameters->GetParameter<unsigned int>("print-dot-FF")))
276  {
277  WriteBBGraphDot("BB_After_" + GetName() + "_merge_" + STR(merge_n) + ".dot");
278  }
279  merge_n++;
280  }
281  else
282  {
283  merging_candidates.erase(merging_candidate);
284  }
285  }
286  } while(mergeable_pair_found);
287 
288  if(something_change)
289  {
290  function_behavior->UpdateBBVersion();
292  }
293  else
294  {
296  }
297 }
298 
299 bool short_circuit_taf::check_merging_candidate(unsigned int& bb1, unsigned int& bb2, unsigned int merging_candidate,
300  bool& bb1_true, bool& bb2_true,
301  const std::map<unsigned int, blocRef>& list_of_bloc)
302 {
303  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Checking merging candidate BB" + STR(merging_candidate));
304  bool mergeable_pair_found = false;
306  THROW_ASSERT(list_of_bloc.find(merging_candidate) != list_of_bloc.end(),
307  "merging_candidate is not included in list_of_bloc");
308  const auto it_pred_end = list_of_bloc.at(merging_candidate)->list_of_pred.end();
309  for(auto it_bb1_pred = list_of_bloc.at(merging_candidate)->list_of_pred.begin();
310  !mergeable_pair_found && it_pred_end != it_bb1_pred; ++it_bb1_pred)
311  {
312  bb1 = *it_bb1_pred;
313  if(bb1 == bloc::ENTRY_BLOCK_ID || bb1 == merging_candidate)
314  {
315  continue;
316  }
317  if(list_of_bloc.at(bb1)->CGetStmtList().empty())
318  {
319  continue;
320  }
321  if(GET_CONST_NODE(list_of_bloc.at(bb1)->CGetStmtList().back())->get_kind() != gimple_cond_K)
322  {
323  continue;
324  }
326  "-->Examining merging candidate predecessor BB" + STR(bb1));
327  THROW_ASSERT(list_of_bloc.at(bb1)->true_edge > 0,
328  "bb1 has to be an if statement " + STR(bb1) + " " + STR(merging_candidate));
329  if(list_of_bloc.at(bb1)->true_edge == merging_candidate)
330  {
331  bb1_true = true;
332  }
333  else
334  {
335  bb1_true = false;
336  }
338  for(auto it_bb2_pred = list_of_bloc.at(merging_candidate)->list_of_pred.begin();
339  !mergeable_pair_found && it_pred_end != it_bb2_pred; ++it_bb2_pred)
340  {
341  bb2 = *it_bb2_pred;
343  "Examining merging candidate nested predecessor " + STR(bb2));
344  if(bb2 == bloc::ENTRY_BLOCK_ID || bb2 == merging_candidate)
345  {
346  continue;
347  }
348  if(list_of_bloc.at(bb2)->list_of_pred.size() > 1)
349  {
350  continue;
351  }
352  if(list_of_bloc.at(bb2)->CGetStmtList().size() != 1)
353  {
354  continue;
355  }
356  if(list_of_bloc.at(bb2)->CGetPhiList().size() != 0)
357  {
358  continue;
359  }
360  if(GET_CONST_NODE(list_of_bloc.at(bb2)->CGetStmtList().back())->get_kind() != gimple_cond_K)
361  {
362  continue;
363  }
364  THROW_ASSERT(list_of_bloc.at(bb2)->true_edge > 0,
365  "bb2 has to be an if statement " + STR(bb2) + " " + STR(merging_candidate));
366  // This check is needed for empty while loop with short circuit (e. g. 20000314-1.c)
367  if(list_of_bloc.at(bb2)->true_edge == bb1 || list_of_bloc.at(bb2)->false_edge == bb1)
368  {
369  continue;
370  }
371  if(bb1_true && list_of_bloc.at(bb1)->false_edge == bb2)
372  {
373  if(list_of_bloc.at(bb2)->true_edge == merging_candidate)
374  {
375  bb2_true = true;
376  }
377  else
378  {
379  bb2_true = false;
380  }
381  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Pair found: " << STR(bb1) << " and " << STR(bb2));
382  mergeable_pair_found = true;
383  if(bb2_true)
384  {
386  "bb1 T " + STR(bb1) + " bb2 T " + STR(bb2) + " MC " + STR(merging_candidate));
387  }
388  else
389  {
391  "bb1 T " + STR(bb1) + " bb2 F " + STR(bb2) + " MC " + STR(merging_candidate));
392  }
393  }
394  else if(!bb1_true && list_of_bloc.at(bb1)->true_edge == bb2)
395  {
396  if(list_of_bloc.at(bb2)->true_edge == merging_candidate)
397  {
398  bb2_true = true;
399  }
400  else
401  {
402  bb2_true = false;
403  }
404  mergeable_pair_found = true;
405  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Pair found: " << STR(bb1) << " and " << STR(bb2));
406  if(bb2_true)
407  {
409  "bb1 F " + STR(bb1) + " bb2 T " + STR(bb2) + " MC " + STR(merging_candidate));
410  }
411  else
412  {
414  "bb1 F " + STR(bb1) + " bb2 F " + STR(bb2) + " MC " + STR(merging_candidate));
415  }
416  }
417  }
418  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Examined mergin candidate predecessor BB" + STR(bb1));
419  }
420  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Checked merging candidate");
421  return mergeable_pair_found;
422 }
423 
424 bool short_circuit_taf::create_gimple_cond(unsigned int bb1, unsigned int bb2, bool bb1_true,
425  const std::map<unsigned int, blocRef>& list_of_bloc, bool or_type,
426  unsigned int merging_candidate)
427 {
428  const tree_managerRef TM = AppM->get_tree_manager();
429 
431  "Creating new cond expr: " + STR(bb1) + " is the first basic block, " + STR(bb2) +
432  " is the second basic block");
435  if(list_of_bloc.at(bb2)->CGetStmtList().size() != 1)
436  {
437  return false;
438  }
439  const auto list_of_stmt_cond2 = list_of_bloc.at(bb2)->CGetStmtList();
440 
442  const auto& list_of_stmt_cond1 = list_of_bloc.at(bb1)->CGetStmtList();
443  THROW_ASSERT(GET_CONST_NODE(list_of_stmt_cond1.back())->get_kind() == gimple_cond_K, "a gimple_cond is expected");
444  const auto cond_statement = list_of_stmt_cond1.back();
445  list_of_bloc.at(bb1)->RemoveStmt(cond_statement, AppM);
446 
447  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---First gimple cond is " + STR(cond_statement));
448  const auto ce1 = GetPointer<const gimple_cond>(GET_CONST_NODE(cond_statement));
449  auto cond1 = ce1->op0;
450  auto type_node = tree_helper::CGetType(cond1);
451  const auto tree_man = tree_manipulationConstRef(new tree_manipulation(TM, parameters, AppM));
453  {
454  type_node = tree_man->GetBooleanType();
455  }
456 
458  const auto cond1_created_stmt =
459  tree_man->CreateGimpleAssign(type_node, nullptr, nullptr, cond1, function_id, BUILTIN_SRCP);
460  const auto ssa1_cond_node = GetPointer<const gimple_assign>(GET_CONST_NODE(cond1_created_stmt))->op0;
462  list_of_bloc.at(bb1)->PushBack(cond1_created_stmt, AppM);
464  "---Created statement in BB" + STR(bb1) + " - " + STR(cond1_created_stmt));
465  cond1 = ssa1_cond_node;
466 
468  if(list_of_bloc.at(merging_candidate)->CGetPhiList().size())
469  {
470  for(const auto& phi : list_of_bloc.at(merging_candidate)->CGetPhiList())
471  {
472  const auto mc_phi = GetPointer<gimple_phi>(GET_NODE(phi));
473  std::pair<tree_nodeRef, unsigned int> def_edge_to_be_removed(tree_nodeRef(), 0);
474  std::pair<tree_nodeRef, unsigned int> def_edge_to_be_updated(tree_nodeRef(), 0);
475  for(const auto& def_edge : mc_phi->CGetDefEdgesList())
476  {
477  if(def_edge.second == bb1)
478  {
479  def_edge_to_be_removed = def_edge;
480  }
481  else if(def_edge.second == bb2)
482  {
483  def_edge_to_be_updated = def_edge;
484  }
485  }
486  THROW_ASSERT(def_edge_to_be_removed.first, "unexpected condition");
487  THROW_ASSERT(def_edge_to_be_updated.first, "unexpected condition");
488  auto op1 = def_edge_to_be_removed.first;
489  auto op2 = def_edge_to_be_updated.first;
490  if(!bb1_true)
491  {
492  std::swap(op1, op2);
493  }
494 
496  const auto res_type = tree_helper::CGetType(mc_phi->res);
497  auto condition_type = tree_helper::CGetType(cond1);
498  auto isAVectorType = tree_helper::is_a_vector(TM, GET_INDEX_CONST_NODE(condition_type));
499  const auto cond_expr_node = tree_man->create_ternary_operation(
500  res_type, cond1, op1, op2, BUILTIN_SRCP, (isAVectorType ? vec_cond_expr_K : cond_expr_K));
501  const auto created_stmt =
502  tree_man->CreateGimpleAssign(res_type, nullptr, nullptr, cond_expr_node, function_id, BUILTIN_SRCP);
503  const auto ssa_cond_node = GetPointer<const gimple_assign>(GET_CONST_NODE(created_stmt))->op0;
504 
507  "---Created new assignment: " + GET_CONST_NODE(created_stmt)->ToString());
508  list_of_bloc.at(bb1)->PushBack(created_stmt, AppM);
509  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Phi is " + mc_phi->ToString());
510  mc_phi->ReplaceDefEdge(TM, def_edge_to_be_updated,
511  gimple_phi::DefEdge(ssa_cond_node, def_edge_to_be_updated.second));
512  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Phi is " + mc_phi->ToString());
513  mc_phi->RemoveDefEdge(TM, def_edge_to_be_removed);
514  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Phi is " + mc_phi->ToString());
515  }
516  }
517 
518  if((bb1_true && !or_type) || (!bb1_true && or_type))
519  {
521  const auto not_cond1 = tree_man->create_unary_operation(type_node, cond1, BUILTIN_SRCP, truth_not_expr_K);
522  const auto created_stmt =
523  tree_man->CreateGimpleAssign(type_node, nullptr, nullptr, not_cond1, function_id, BUILTIN_SRCP);
524  cond1 = GetPointer<const gimple_assign>(GET_CONST_NODE(created_stmt))->op0;
526  list_of_bloc.at(bb1)->PushBack(created_stmt, AppM);
527  }
529  THROW_ASSERT(list_of_bloc.at(bb2)->CGetPhiList().size() == 0, "not expected phi nodes");
530 
531  THROW_ASSERT(GET_CONST_NODE(list_of_stmt_cond2.front())->get_kind() == gimple_cond_K, "a gimple_cond is expected");
532 
533  const auto second_stmt = list_of_stmt_cond2.front();
534  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Second gimple cond is " + STR(second_stmt));
535  auto ce2 = GetPointer<gimple_cond>(GET_NODE(second_stmt));
536  auto cond2 = ce2->op0;
537 
539  const auto cond2_created_stmt =
540  tree_man->CreateGimpleAssign(type_node, nullptr, nullptr, cond2, function_id, BUILTIN_SRCP);
541  cond2 = GetPointer<const gimple_assign>(GET_CONST_NODE(cond2_created_stmt))->op0;
543  list_of_bloc.at(bb1)->PushBack(cond2_created_stmt, AppM);
544 
548  list_of_bloc.at(bb2)->RemoveStmt(second_stmt, AppM);
550  ce2->op0 = tree_man->create_binary_operation(type_node, cond1, cond2, BUILTIN_SRCP,
551  (or_type ? truth_or_expr_K : truth_and_expr_K));
552 
554  list_of_bloc.at(bb2)->PushBack(second_stmt, AppM);
555 
557  while(list_of_stmt_cond1.size())
558  {
559  const auto stmt = list_of_stmt_cond1.back();
560  list_of_bloc.at(bb1)->RemoveStmt(stmt, AppM);
561  list_of_bloc.at(bb2)->PushFront(stmt, AppM);
562  }
565  const auto& bb1_phi_list = list_of_bloc.at(bb1)->CGetPhiList();
566  while(bb1_phi_list.size())
567  {
568  const auto phi = bb1_phi_list.back();
569  list_of_bloc.at(bb1)->RemovePhi(phi);
570  list_of_bloc.at(bb2)->AddPhi(phi);
571  }
572 
574  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "GIMPLE_COND built");
575  return true;
576 }
577 
578 void short_circuit_taf::restructure_CFG(unsigned int bb1, unsigned int bb2, unsigned int merging_candidate,
579  std::map<unsigned int, blocRef>& list_of_bloc)
580 {
582  std::vector<unsigned int>::iterator pos;
583  for(const auto& bb1_pred : list_of_bloc.at(bb1)->list_of_pred)
584  {
585  list_of_bloc.at(bb2)->list_of_pred.push_back(bb1_pred);
586  pos = std::find(list_of_bloc.at(bb1_pred)->list_of_succ.begin(), list_of_bloc.at(bb1_pred)->list_of_succ.end(),
587  bb1);
588  *pos = bb2;
589  if(list_of_bloc.at(bb1_pred)->true_edge == bb1)
590  {
591  list_of_bloc.at(bb1_pred)->true_edge = bb2;
592  }
593  else if(list_of_bloc.at(bb1_pred)->false_edge == bb1)
594  {
595  list_of_bloc.at(bb1_pred)->false_edge = bb2;
596  }
597  }
598  pos = std::find(list_of_bloc.at(bb2)->list_of_pred.begin(), list_of_bloc.at(bb2)->list_of_pred.end(), bb1);
599  list_of_bloc.at(bb2)->list_of_pred.erase(pos);
601  pos = std::find(list_of_bloc.at(merging_candidate)->list_of_pred.begin(),
602  list_of_bloc.at(merging_candidate)->list_of_pred.end(), bb1);
603  list_of_bloc.at(merging_candidate)->list_of_pred.erase(pos);
604  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Removed BB " + STR(bb1));
606  for(const auto& pred : list_of_bloc.at(bb1)->list_of_pred)
607  {
608  const auto list_of_pred_stmt = list_of_bloc.at(pred)->CGetStmtList();
609  const auto cond_statement =
610  list_of_pred_stmt.begin() != list_of_pred_stmt.end() ? list_of_pred_stmt.back() : tree_nodeRef();
611  const auto cond_statement_node = cond_statement ? GET_NODE(cond_statement) : cond_statement;
612  if(cond_statement_node && GetPointer<gimple_multi_way_if>(cond_statement_node))
613  {
614  const auto gmwi = GetPointerS<gimple_multi_way_if>(cond_statement_node);
615  for(auto& cond : gmwi->list_of_cond)
616  {
617  if(cond.second == bb1)
618  {
619  cond.second = bb2;
620  }
621  }
622  }
623  }
624  list_of_bloc.erase(bb1);
625 }
626 
627 bool short_circuit_taf::check_phis(unsigned int curr_bb, const std::map<unsigned int, blocRef>& list_of_bloc)
628 {
629  for(const auto& phi : list_of_bloc.at(curr_bb)->CGetPhiList())
630  {
631  const auto cb_phi = GetPointerS<const gimple_phi>(GET_CONST_NODE(phi));
632  if(cb_phi->virtual_flag)
633  {
634  return false;
635  }
636  }
637  return true;
638 }
639 
641 {
643  {
644  return false;
645  }
646 
647 #if HAVE_ILP_BUILT
648  if(parameters->getOption<HLSFlowStep_Type>(OPT_scheduling_algorithm) == HLSFlowStep_Type::SDC_SCHEDULING)
649  {
650  if(GetPointer<const HLS_manager>(AppM) and GetPointer<const HLS_manager>(AppM)->get_HLS(function_id) and
651  GetPointer<const HLS_manager>(AppM)->get_HLS(function_id)->Rsch)
652  {
654  const auto update_schedule = design_flow_manager.lock()->GetDesignFlowStep(
655  FunctionFrontendFlowStep::ComputeSignature(FrontendFlowStepType::UPDATE_SCHEDULE, function_id));
656  if(update_schedule)
657  {
658  const DesignFlowGraphConstRef design_flow_graph = design_flow_manager.lock()->CGetDesignFlowGraph();
659  const DesignFlowStepRef design_flow_step =
660  design_flow_graph->CGetDesignFlowStepInfo(update_schedule)->design_flow_step;
661  if(GetPointer<const FunctionFrontendFlowStep>(design_flow_step)->CGetBBVersion() !=
662  function_behavior->GetBBVersion())
663  {
664  return false;
665  }
666  else
667  {
668  return true;
669  }
670  }
671  else
672  {
673  return false;
674  }
675  }
676  else
677  {
678  return true;
679  }
680  }
681 #endif
682 
683  return true;
684 }
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:343
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
Data structure representing the entire HLS information.
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
File containing functions and utilities to support the printing of debug messagges.
#define PRINT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
Step successfully executed.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
Analysis step rebuilding a short circuit in a single gimple_cond with the condition in three address ...
Definition of the class representing a generic C application.
std::string GetName() const override
Return the name of this design step.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
A simple interface to token object of the raw files.
Analysis step that optimize the phis starting from the IR.
static const unsigned int EXIT_BLOCK_ID
constant identifying the exit basic block
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
Data structure describing a basic block at tree level.
#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.
std::string ToString(ActorGraphBackend_Type actor_graph_backend_type)
Header include.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
static bool IsBooleanType(const tree_nodeConstRef &type)
Return true if the treenode is of bool type.
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.
HLSFlowStep_Type
Definition: hls_step.hpp:95
void WriteBBGraphDot(const std::string &filename) const
Write the current version of statement list in dot format.
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
bool check_phis(unsigned int curr_bb, const std::map< unsigned int, blocRef > &list_of_bloc)
check if phi could create problem to the short circuit collapsing
Factory for technology flow step.
const Wrefcount< const DesignFlowManager > design_flow_manager
The design flow manager.
#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.
Classes specification of the tree_node data structures.
~short_circuit_taf() override
Destructor.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
void restructure_CFG(unsigned int bb1, unsigned int bb2, unsigned int merging_candidate, std::map< unsigned int, blocRef > &list_of_bloc)
restructure the CFG eliminating all BBs not needed after short circuit collapsing ...
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 file collects some utility functions.
DesignFlowStep_Status InternalExec() override
Restructures the unstructured code.
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 application_managerRef AppM
The application manager.
struct definition of the type node structures.
Definition: tree_node.hpp:1318
Class specification of the tree_reindex support class.
static const unsigned int ENTRY_BLOCK_ID
constant identifying the entry basic block
bool check_merging_candidate(unsigned int &bb1, unsigned int &bb2, unsigned int merging_candidate, bool &bb1_true, bool &bb2_true, const std::map< unsigned int, blocRef > &list_of_bloc)
Check if a basic block is a merging BB for a short circuit.
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec.
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.
short_circuit_taf(const ParameterConstRef _Param, const application_managerRef _AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
refcount< const tree_manipulation > tree_manipulationConstRef
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
static bool is_a_vector(const tree_managerConstRef &TM, const unsigned int index)
Return true if the treenode index is a vector.
Wrapper to call graph.
int debug_level
The debug level.
#define GET_INDEX_CONST_NODE(t)
Definition: tree_node.hpp:363
bool create_gimple_cond(unsigned int bb1, unsigned int bb2, bool bb1_true, const std::map< unsigned int, blocRef > &list_of_bloc, bool or_type, unsigned int merging_candidate)
create the or/and expression required by short circuit collapsing
Data structure definition for high-level synthesis flow.
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.
Base class for technology flow steps.
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.
#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