PandA-2024.02
simple_code_motion.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 #pragma GCC diagnostic ignored "-Woverloaded-virtual"
46 
48 #include "simple_code_motion.hpp"
49 
51 #include "Parameter.hpp"
52 
54 #include "Dominance.hpp"
55 
57 #include "application_manager.hpp"
58 #include "basic_block.hpp"
59 #include "function_behavior.hpp"
60 
62 #include "design_flow_graph.hpp"
63 #include "design_flow_manager.hpp"
64 
65 #if HAVE_ILP_BUILT
66 #include "hls.hpp"
68 #include "hls_manager.hpp"
69 #include "hls_step.hpp"
70 
72 #include "schedule.hpp"
73 #endif
74 
76 #include "token_interface.hpp"
77 
79 #include <fstream>
80 
82 #include "ext_tree_node.hpp"
83 #include "tree_basic_block.hpp"
84 #include "tree_helper.hpp"
85 #include "tree_manager.hpp"
86 #include "tree_manipulation.hpp"
87 #include "tree_node.hpp"
88 #include "tree_reindex.hpp"
89 
91 #include "dbgPrintHelper.hpp"
92 #include "math_function.hpp"
93 
94 #include "behavioral_helper.hpp"
96 #include "string_manipulation.hpp" // for GET_CLASS
97 
99  unsigned int _function_id, const DesignFlowManagerConstRef _design_flow_manager)
100  : FunctionFrontendFlowStep(_AppM, _function_id, SIMPLE_CODE_MOTION, _design_flow_manager, _parameters),
101  restart_ifmwi_opt(false),
102  schedule(ScheduleRef()),
103  conservative(
104 #if HAVE_ILP_BUILT
105  (parameters->IsParameter("enable-conservative-sdc") &&
106  parameters->GetParameter<bool>("enable-conservative-sdc") &&
107  parameters->isOption(OPT_scheduling_algorithm) and
108  parameters->getOption<HLSFlowStep_Type>(OPT_scheduling_algorithm) == HLSFlowStep_Type::SDC_SCHEDULING) ?
109  true :
110  false
111 #else
112  false
113 #endif
114  )
115 {
116  debug_level = _parameters->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
117 }
118 
120 
123 {
125  switch(relationship_type)
126  {
128  {
129  relationships.insert(std::make_pair(PREDICATE_STATEMENTS, SAME_FUNCTION));
130  relationships.insert(std::make_pair(USE_COUNTING, SAME_FUNCTION));
131  relationships.insert(std::make_pair(BLOCK_FIX, SAME_FUNCTION));
132  relationships.insert(std::make_pair(SWITCH_FIX, SAME_FUNCTION));
133  break;
134  }
136  {
137 #if HAVE_ILP_BUILT
138  relationships.insert(std::make_pair(SDC_CODE_MOTION, SAME_FUNCTION));
139 #endif
140  relationships.insert(std::make_pair(DEAD_CODE_ELIMINATION_IPA, WHOLE_APPLICATION));
141  break;
142  }
144  {
146  {
148  {
149  relationships.insert(std::make_pair(SHORT_CIRCUIT_TAF, SAME_FUNCTION));
150  relationships.insert(std::make_pair(PHI_OPT, SAME_FUNCTION));
151  relationships.insert(std::make_pair(MULTI_WAY_IF, SAME_FUNCTION));
152  }
153  }
154  break;
155  }
156  default:
157  {
158  THROW_UNREACHABLE("");
159  }
160  }
161  return relationships;
162 }
163 
165 {
166 #if HAVE_ILP_BUILT
167  if(GetPointer<const HLS_manager>(AppM) && GetPointer<const HLS_manager>(AppM)->get_HLS(function_id) &&
168  GetPointer<const HLS_manager>(AppM)->get_HLS(function_id)->Rsch)
169  {
170  if(parameters->isOption(OPT_scheduling_algorithm) &&
171  parameters->getOption<HLSFlowStep_Type>(OPT_scheduling_algorithm) == HLSFlowStep_Type::SDC_SCHEDULING)
172  {
173  const auto TM = AppM->get_tree_manager();
174  schedule = GetPointerS<const HLS_manager>(AppM)->get_HLS(function_id)->Rsch;
175 #if 0
176  tree_nodeRef temp = TM->get_tree_node_const(function_id);
177  function_decl * fd = GetPointer<function_decl>(temp);
178  statement_list * sl = GetPointer<statement_list>(GET_NODE(fd->body));
179  for(const auto block : sl->list_of_bloc)
180  {
181  block.second->schedule = schedule;
182  }
183 #endif
184  }
185  }
186 #endif
187 }
188 
190  bool& zero_delay, const tree_managerRef TM)
191 {
192  if(AppM->CGetFunctionBehavior(function_id)->is_simple_pipeline())
193  {
194  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Yes because we aim to full pipelining");
196  }
197  if(tn->get_kind() == gimple_nop_K)
198  {
200  }
201 
202  auto* ga = GetPointer<gimple_assign>(tn);
203 
205  "-->Checking if " + STR(ga->index) + " - " + ga->ToString() + " can be moved in BB" + STR(bb_index));
206  tree_nodeRef left = GET_NODE(ga->op0);
207  if(!GetPointer<ssa_name>(left))
208  {
210  "<--No because of " + left->get_kind_text() + " in left part");
212  }
214  if(GET_NODE(ga->op1)->get_kind() == call_expr_K || GET_NODE(ga->op1)->get_kind() == aggr_init_expr_K)
215  {
216  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--No because of call_expr in right part");
218  }
219  if(tree_helper::is_constant(TM, GET_INDEX_NODE(ga->op1)))
220  {
221  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Yes because right part is constant");
223  }
224  if(GET_NODE(ga->op0)->get_kind() == ssa_name_K && GET_NODE(ga->op1)->get_kind() == constructor_K)
225  {
226  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Yes because it is an assignment with a constructor");
228  }
229  if(GET_NODE(ga->op0)->get_kind() == ssa_name_K && GET_NODE(ga->op1)->get_kind() == ssa_name_K)
230  {
231  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Yes because it is an assignment");
233  }
235  tree_helper::compute_ssa_uses_rec_ptr(ga->op1, rhs_ssa_uses);
236  tree_nodeRef right = GET_NODE(ga->op1);
237 
238  if(rhs_ssa_uses.empty() && right->get_kind() != call_expr_K && right->get_kind() != aggr_init_expr_K &&
239  right->get_kind() != var_decl_K && right->get_kind() != mem_ref_K)
240  {
242  "<--Yes because there is not any use of ssa in right part");
244  }
245 
247 #if HAVE_ILP_BUILT
248  if(schedule)
249  {
250  auto movable = schedule->CanBeMoved(ga->index, bb_index);
252  {
253  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--No because of timing");
254  }
255  else
256  {
257  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Yes because of timing");
258  }
259  return movable;
260  }
261 #endif
262  switch(right->get_kind())
263  {
264  case assert_expr_K:
265  case convert_expr_K:
266  case view_convert_expr_K:
267  case ssa_name_K:
268  case constructor_K:
269  {
272  }
274  case eq_expr_K:
275  case lrotate_expr_K:
276  case lshift_expr_K:
277  case max_expr_K:
278  case min_expr_K:
279  case ne_expr_K:
280  case rrotate_expr_K:
281  case rshift_expr_K:
282  {
283  if(conservative)
284  {
287  }
288  else
289  {
290  auto* be = GetPointer<binary_expr>(right);
291  auto n_bit = std::max(tree_helper::Size(be->op0), tree_helper::Size(be->op1));
292  bool is_constant = tree_helper::is_constant(TM, GET_INDEX_NODE(be->op0)) ||
294  if(n_bit > 9 && !is_constant)
295  {
296  zero_delay = false;
297  }
300  }
301  }
302  case fshl_expr_K:
303  case fshr_expr_K:
304  {
305  if(conservative)
306  {
309  }
310  else
311  {
312  auto* te = GetPointer<ternary_expr>(right);
313  auto n_bit = tree_helper::Size(te->op0);
314  bool is_constant = tree_helper::is_constant(TM, GET_INDEX_NODE(te->op1));
315  if(n_bit > 9 && !is_constant)
316  {
317  zero_delay = false;
318  }
321  }
322  }
323  case mult_expr_K:
324  case mult_highpart_expr_K:
325  case widen_mult_expr_K:
326  {
327  if(tree_helper::is_real(TM, ga->op1->index))
328  {
329  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--No because floating point operations");
331  }
332  auto* be = GetPointer<binary_expr>(right);
333  if(tree_helper::IsConstant(be->op1))
334  {
335  const auto ic = GetPointer<integer_cst>(GET_NODE(be->op1));
336  if(ic)
337  {
338  const auto v = tree_helper::GetConstValue(be->op1);
339  if(!(v && !(v & (v - 1))))
340  {
341  zero_delay = false;
342  }
345  }
346  else
347  {
348  zero_delay = false;
349  }
350  }
351  else
352  {
353  zero_delay = false;
354  }
356  "<--No because is a multiplication with non constant args");
358  }
359  case nop_expr_K:
360  {
361  auto* ne = GetPointer<nop_expr>(right);
362  const auto left_type = tree_helper::CGetType(ga->op0);
363  const auto right_type = tree_helper::CGetType(ne->op);
364  const auto is_realR = tree_helper::IsRealType(right_type);
365  const auto is_realL = tree_helper::IsRealType(left_type);
366  if(is_realR || is_realL)
367  {
368  zero_delay = false;
369  }
370 
373  }
374  case addr_expr_K:
375  {
376  zero_delay = false;
379  }
380  case bit_and_expr_K:
381  case bit_ior_expr_K:
382  case bit_xor_expr_K:
383  case truth_and_expr_K:
384  case truth_andif_expr_K:
385  case truth_or_expr_K:
386  case truth_orif_expr_K:
387  case truth_xor_expr_K:
388  case bit_not_expr_K:
389  case truth_not_expr_K:
390  case cond_expr_K:
391  case lut_expr_K:
392  {
393  if(conservative)
394  {
397  }
398  else
399  {
402  }
403  }
404  case bit_ior_concat_expr_K:
405  {
408  }
409  case extractvalue_expr_K:
410  case insertvalue_expr_K:
411  case extract_bit_expr_K:
412  case extractelement_expr_K:
413  case insertelement_expr_K:
414  {
417  }
418  case ge_expr_K:
419  case gt_expr_K:
420  case le_expr_K:
421  case lt_expr_K:
422  case minus_expr_K:
423  case plus_expr_K:
424  case pointer_plus_expr_K:
425  case postdecrement_expr_K:
426  case postincrement_expr_K:
427  case predecrement_expr_K:
428  case preincrement_expr_K:
429  case sat_plus_expr_K:
430  case sat_minus_expr_K:
431  {
432  if(tree_helper::is_real(TM, ga->op1->index))
433  {
434  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--No because floating point operations");
436  }
437  if(conservative)
438  {
441  }
442  else
443  {
444  auto* be = GetPointer<binary_expr>(right);
445  auto n_bit = std::max(tree_helper::Size(be->op0), tree_helper::Size(be->op1));
446  auto n_bit_min = std::min(tree_helper::Size(be->op0), tree_helper::Size(be->op1));
447  bool is_constant = tree_helper::is_constant(TM, GET_INDEX_NODE(be->op0)) ||
449 #if 0
450  const bool is_gimple_cond_input = [&]()
451  {
452  const auto sn = GetPointer<const ssa_name>(left);
453  if(!sn)
454  return false;
455  const auto use_stmts = sn->CGetUseStmts();
456  if(use_stmts.size() != 1)
457  return false;
458  const auto use_stmt = *(use_stmts.begin());
459  if(GET_NODE(use_stmt.first)->get_kind() != gimple_cond_K)
460  return false;
461  return true;
462  }();
463 #endif
464  if((n_bit > 9 && !is_constant && n_bit_min != 1) || n_bit > 16)
465  {
466  zero_delay = false;
467  }
470  }
471  }
472  case ternary_plus_expr_K:
473  case ternary_pm_expr_K:
474  case ternary_mp_expr_K:
475  case ternary_mm_expr_K:
476  {
477  if(conservative)
478  {
481  }
482  else
483  {
484  auto* be = GetPointer<ternary_expr>(right);
485  auto n_bit =
487  auto n_bit_min =
489  bool is_constant = tree_helper::is_constant(TM, GET_INDEX_NODE(be->op0)) ||
491  if((n_bit > 9 && !is_constant && n_bit_min != 1) || n_bit > 16)
492  {
493  zero_delay = false;
494  }
497  }
498  }
499  case negate_expr_K:
500  {
501  auto* ne = GetPointer<negate_expr>(right);
502  auto n_bit = tree_helper::Size(ne->op);
503  bool is_constant = tree_helper::is_constant(TM, GET_INDEX_NODE(ne->op));
504  if((n_bit > 9 && !is_constant) || n_bit > 16)
505  {
506  zero_delay = false;
507  }
510  }
511  case float_expr_K:
512  {
513  zero_delay = false;
516  }
517  case exact_div_expr_K:
518  case trunc_div_expr_K:
519  case trunc_mod_expr_K:
520  {
521  auto* be = GetPointer<binary_expr>(right);
522  if(tree_helper::IsConstant(be->op1))
523  {
524  auto ic = GetPointer<integer_cst>(GET_NODE(be->op1));
525  if(ic)
526  {
527  const auto v = tree_helper::GetConstValue(be->op1);
528  if(v)
529  {
530  if(!(v && !(v & (v - 1))))
531  {
532  zero_delay = false;
533  }
536  }
537  }
538  }
539  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--No because is a division by a non constant");
541  }
542  case abs_expr_K:
543  {
544  if(conservative)
545  {
548  }
549  else
550  {
552  }
553  }
554  case catch_expr_K:
555  case ceil_div_expr_K:
556  case ceil_mod_expr_K:
557  case complex_expr_K:
558  case compound_expr_K:
559  case eh_filter_expr_K:
560  case fdesc_expr_K:
561  case floor_div_expr_K:
562  case floor_mod_expr_K:
563  case goto_subroutine_K:
564  case in_expr_K:
565  case init_expr_K:
566  case mem_ref_K:
567  case modify_expr_K:
568  case ordered_expr_K:
569  case range_expr_K:
570  case round_div_expr_K:
571  case round_mod_expr_K:
572  case set_le_expr_K:
573  case try_catch_expr_K:
574  case try_finally_K:
575  case uneq_expr_K:
576  case ltgt_expr_K:
577  case unge_expr_K:
578  case ungt_expr_K:
579  case unle_expr_K:
580  case unlt_expr_K:
581  case unordered_expr_K:
582  case widen_sum_expr_K:
583  case with_size_expr_K:
584  case vec_lshift_expr_K:
585  case vec_rshift_expr_K:
586  case widen_mult_hi_expr_K:
587  case widen_mult_lo_expr_K:
588  case vec_pack_trunc_expr_K:
589  case vec_pack_sat_expr_K:
590  case vec_pack_fix_trunc_expr_K:
591  case vec_extracteven_expr_K:
592  case vec_extractodd_expr_K:
593  case vec_interleavehigh_expr_K:
594  case vec_interleavelow_expr_K:
595  case CASE_CPP_NODES:
596  case CASE_CST_NODES:
597  case CASE_DECL_NODES:
598  case CASE_GIMPLE_NODES:
599  case component_ref_K:
600  case bit_field_ref_K:
601  case vtable_ref_K:
602  case with_cleanup_expr_K:
603  case obj_type_ref_K:
604  case save_expr_K:
605  case vec_cond_expr_K:
606  case vec_perm_expr_K:
607  case dot_prod_expr_K:
608  case call_expr_K:
609  case aggr_init_expr_K:
610  case CASE_FAKE_NODES:
611  case rdiv_expr_K:
612  case frem_expr_K:
613  case case_label_expr_K:
614  case target_mem_ref_K:
615  case binfo_K:
616  case block_K:
617  case identifier_node_K:
618  case CASE_PRAGMA_NODES:
619  case statement_list_K:
620  case tree_list_K:
621  case tree_vec_K:
623  case CASE_TYPE_NODES:
624  case alignof_expr_K:
625  case arrow_expr_K:
626  case buffer_ref_K:
627  case card_expr_K:
628  case cleanup_point_expr_K:
629  case conj_expr_K:
630  case exit_expr_K:
631  case fix_ceil_expr_K:
632  case fix_floor_expr_K:
633  case fix_round_expr_K:
634  case fix_trunc_expr_K:
635  case imagpart_expr_K:
636  case indirect_ref_K:
637  case misaligned_indirect_ref_K:
638  case loop_expr_K:
639  case non_lvalue_expr_K:
640  case realpart_expr_K:
641  case reference_expr_K:
642  case reinterpret_cast_expr_K:
643  case sizeof_expr_K:
644  case static_cast_expr_K:
645  case throw_expr_K:
646  case unsave_expr_K:
647  case va_arg_expr_K:
648  case reduc_max_expr_K:
649  case reduc_min_expr_K:
650  case reduc_plus_expr_K:
651  case vec_unpack_hi_expr_K:
652  case vec_unpack_lo_expr_K:
653  case vec_unpack_float_hi_expr_K:
654  case vec_unpack_float_lo_expr_K:
655  case target_expr_K:
656  case target_mem_ref461_K:
657  case error_mark_K:
658  {
660  "<--No because right part is " + right->get_kind_text());
662  }
663  case paren_expr_K:
664  default:
665  {
666  THROW_UNREACHABLE("");
668  }
669  }
670 }
671 
673 {
674  const auto TM = AppM->get_tree_manager();
675  bool modified = false;
676  restart_ifmwi_opt = false;
677 
678  const auto fd = GetPointerS<const function_decl>(TM->CGetTreeNode(function_id));
679  const auto sl = GetPointerS<const statement_list>(GET_CONST_NODE(fd->body));
680 
681  const auto isFunctionPipelined = AppM->CGetFunctionBehavior(function_id)->is_simple_pipeline();
682 
684  const auto bb_graph_info = BBGraphInfoRef(new BBGraphInfo(AppM, function_id));
685  BBGraphsCollectionRef GCC_bb_graphs_collection(new BBGraphsCollection(bb_graph_info, parameters));
686  BBGraphRef GCC_bb_graph(new BBGraph(GCC_bb_graphs_collection, CFG_SELECTOR));
688  CustomUnorderedMap<unsigned int, vertex> inverse_vertex_map;
690  const auto& list_of_bloc = sl->list_of_bloc;
691  for(const auto& block : list_of_bloc)
692  {
693  inverse_vertex_map[block.first] =
694  GCC_bb_graphs_collection->AddVertex(BBNodeInfoRef(new BBNodeInfo(block.second)));
695  direct_vertex_map[inverse_vertex_map[block.first]] = block.first;
696  }
698  for(const auto& bbi_bb : list_of_bloc)
699  {
700  const auto& bbi = bbi_bb.first;
701  const auto& bb = bbi_bb.second;
702  for(const auto& pred : bb->list_of_pred)
703  {
704  THROW_ASSERT(inverse_vertex_map.count(pred),
705  "BB" + STR(pred) + " (predecessor of " + STR(bbi) + ") does not exist");
706  THROW_ASSERT(inverse_vertex_map.count(bbi), STR(bbi));
707  GCC_bb_graphs_collection->AddEdge(inverse_vertex_map.at(pred), inverse_vertex_map.at(bbi), CFG_SELECTOR);
708  }
709  for(const auto& succ : bb->list_of_succ)
710  {
711  if(succ == bloc::EXIT_BLOCK_ID)
712  {
713  GCC_bb_graphs_collection->AddEdge(inverse_vertex_map.at(bbi), inverse_vertex_map.at(succ), CFG_SELECTOR);
714  }
715  }
716  if(bb->list_of_succ.empty())
717  {
718  GCC_bb_graphs_collection->AddEdge(inverse_vertex_map.at(bbi), inverse_vertex_map.at(bloc::EXIT_BLOCK_ID),
719  CFG_SELECTOR);
720  }
721  }
722  bb_graph_info->entry_vertex = inverse_vertex_map.at(bloc::ENTRY_BLOCK_ID);
723  bb_graph_info->exit_vertex = inverse_vertex_map.at(bloc::EXIT_BLOCK_ID);
725  GCC_bb_graphs_collection->AddEdge(inverse_vertex_map.at(bloc::ENTRY_BLOCK_ID),
726  inverse_vertex_map.at(bloc::EXIT_BLOCK_ID), CFG_SELECTOR);
728  std::list<vertex> bb_sorted_vertices;
729  cyclic_topological_sort(*GCC_bb_graph, std::front_inserter(bb_sorted_vertices));
730  static size_t counter = 0;
732  (!parameters->IsParameter("print-dot-FF") || parameters->GetParameter<unsigned int>("print-dot-FF")))
733  {
734  GCC_bb_graph->WriteDot("BB_simple_code_motion_" + STR(counter) + ".dot");
736  "---Written BB_simple_code_motion_" + STR(counter) + ".dot");
737  counter++;
738  }
739 
740  std::unique_ptr<dominance<BBGraph>> bb_dominators(
741  new dominance<BBGraph>(*GCC_bb_graph, inverse_vertex_map.at(bloc::ENTRY_BLOCK_ID),
742  inverse_vertex_map.at(bloc::EXIT_BLOCK_ID), parameters));
743  bb_dominators->calculate_dominance_info(dominance<BBGraph>::CDI_DOMINATORS);
744  const auto& bb_dominator_map = bb_dominators->get_dominator_map();
745 
747  // cppcheck-suppress uninitvar
748  const CustomSet<vertex> simd_loop_headers =
749  parameters->getOption<int>(OPT_gcc_openmp_simd) == 0 ? CustomSet<vertex>() : [&]() -> CustomSet<vertex> const {
750  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Looking for openmp simd pragma");
751  CustomSet<vertex> return_value;
752  for(const auto& block : list_of_bloc)
753  {
754  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Analyzing BB" + STR(block.first));
755  for(const auto& statement : block.second->CGetStmtList())
756  {
757  const auto* gp = GetPointer<const gimple_pragma>(GET_NODE(statement));
758  if(gp && GetPointer<const omp_pragma>(GET_NODE(gp->scope)) &&
759  GetPointer<const omp_simd_pragma>(GET_NODE(gp->directive)))
760  {
761  THROW_ASSERT(boost::out_degree(inverse_vertex_map[block.first], *GCC_bb_graph) == 1,
762  "OpenMP simd pragma block has more than one successor");
763  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Found openmp pragma");
764  OutEdgeIterator oe, oe_end;
765  boost::tie(oe, oe_end) = boost::out_edges(inverse_vertex_map[block.first], *GCC_bb_graph);
766  return_value.insert(boost::target(*oe, *GCC_bb_graph));
767  break;
768  }
769  }
771  }
772  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Found " + STR(return_value.size()) + " simd pragmas");
773  return return_value;
774  }();
775 
776 #if 0
777  const CustomSet<vertex> to_be_parallelized = simd_loop_headers.empty() ? CustomSet<vertex>() : [&] () -> CustomSet<vertex> const
778  {
779  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Computing loop basic blocks");
780  CustomSet<vertex> return_value;
781  for(const auto simd_loop_header : simd_loop_headers)
782  {
783  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Computing loop basic blocks of Loop " + STR(direct_vertex_map[simd_loop_header]));
784  const auto loop_id = list_of_bloc.at(direct_vertex_map[simd_loop_header)]->loop_id;
785  CustomSet<vertex> already_processed;
786  std::list<vertex> to_be_processed;
787  InEdgeIterator ie, ie_end;
788  for(boost::tie(ie, ie_end) = boost::in_edges(simd_loop_header, *GCC_bb_graph); ie != ie_end; ie++)
789  {
790  const vertex source = boost::source(*ie, *GCC_bb_graph);
792  if(list_of_bloc.at(direct_vertex_map[source)]->loop_id >= loop_id)
793  {
794  to_be_processed.push_front(source);
795  }
796  }
797  while(to_be_processed.size())
798  {
799  vertex current = to_be_processed.front();
800  to_be_processed.pop_front();
801  already_processed.insert(current);
802  return_value.insert(current);
803  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Processing BB" + STR(direct_vertex_map[current]));
804  for(boost::tie(ie, ie_end) = boost::in_edges(current, *GCC_bb_graph); ie != ie_end; ie++)
805  {
806  const vertex source = boost::source(*ie, *GCC_bb_graph);
807  if(already_processed.find(source) != already_processed.end() or current == simd_loop_header)
808  {
809  continue;
810  }
811  const auto source_loop_id = list_of_bloc.at(direct_vertex_map[source)]->loop_id;
813  if(source_loop_id > loop_id)
814  to_be_processed.push_front(source);
815  else
816  to_be_processed.push_back(source);
817  }
818  }
819  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Computed loop basic blocks of Loop " + STR(simd_loop_header));
820  }
821  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Computed loop basic blocks");
822  return return_value;
823  }();
824 #else
825  const CustomSet<vertex> to_be_parallelized = CustomSet<vertex>();
826 #endif
828 
829  for(const auto bb_vertex : bb_sorted_vertices)
830  {
831  const auto curr_bb = direct_vertex_map.at(bb_vertex);
832  bool parallel_bb = to_be_parallelized.find(bb_vertex) != to_be_parallelized.end();
833  if(curr_bb == bloc::ENTRY_BLOCK_ID)
834  {
835  continue;
836  }
837  if(curr_bb == bloc::EXIT_BLOCK_ID)
838  {
839  continue;
840  }
841 #if 0
842  bool have_multi_way_if_pred = false;
844  for(const auto pred : list_of_bloc.at(curr_bb)->list_of_pred)
845  {
846  if(!list_of_bloc.at(pred)->list_of_stmt.empty())
847  {
848  tree_nodeRef last = GET_NODE(list_of_bloc.at(pred)->list_of_stmt.back());
849  if(GetPointer<gimple_multi_way_if>(last))
850  have_multi_way_if_pred = true;
851  }
852  }
853  if(have_multi_way_if_pred)
854  continue;
855 #endif
857  "-->Analyzing BB" + STR(curr_bb) + (parallel_bb ? "(Parallel)" : ""));
858  bool restart_bb_code_motion = false;
859  do
860  {
862  (!parameters->IsParameter("print-dot-FF") || parameters->GetParameter<unsigned int>("print-dot-FF")))
863  {
864  GCC_bb_graph->WriteDot("BB_simple_code_motion_" + STR(counter) + ".dot");
866  "---Written BB_simple_code_motion_" + STR(counter) + ".dot");
867  counter++;
868  }
869  const auto& list_of_stmt = list_of_bloc.at(curr_bb)->CGetStmtList();
870  std::list<tree_nodeRef> to_be_removed;
871  CustomOrderedSet<unsigned int> zero_delay_stmts;
872  std::list<tree_nodeRef> to_be_added_back;
873  std::list<tree_nodeRef> to_be_added_front;
875  for(auto statement = list_of_stmt.begin(); statement != list_of_stmt.end(); statement++)
876  {
877  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Analyzing " + (*statement)->ToString());
879  tree_nodeRef tn = GET_NODE(*statement);
880  auto* gn = GetPointer<gimple_node>(tn);
881 
882  THROW_ASSERT(gn, "unexpected condition");
883  if(!isFunctionPipelined && !parallel_bb && gn->vdef)
884  {
885  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Skipped because of memory store");
886  continue;
887  }
888 
890  if(!GetPointer<gimple_assign>(tn) && !GetPointer<gimple_nop>(tn))
891  {
892  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Skipped because " + tn->get_kind_text());
893  continue;
894  }
895 
897  CustomOrderedSet<const ssa_name*> stmt_ssa_uses;
898  tree_helper::compute_ssa_uses_rec_ptr(*statement, stmt_ssa_uses);
899  for(const auto& vo : gn->vovers)
900  {
901  tree_helper::compute_ssa_uses_rec_ptr(vo, stmt_ssa_uses);
902  }
903 
907  for(auto stmt0 = list_of_stmt.begin(); stmt0 != list_of_stmt.end() && *stmt0 != *statement && gn->vdef;
908  stmt0++)
909  {
910  tree_nodeRef tn0 = GET_NODE(*stmt0);
911  const auto gn0 = GetPointerS<gimple_node>(tn0);
912  if(gn0->vuses.find(gn->vdef) != gn0->vuses.end())
913  {
914  BB_def.insert(curr_bb);
915  }
916  }
917 
918  const auto ssu_it_end = stmt_ssa_uses.cend();
919  for(auto ssu_it = stmt_ssa_uses.cbegin(); ssu_it != ssu_it_end; ++ssu_it)
920  {
921  const auto sn = *ssu_it;
922  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---for variable " + sn->ToString());
923  for(auto const& def_stmt : sn->CGetDefStmts())
924  {
925  auto* def_gn = GetPointer<gimple_node>(GET_NODE(def_stmt));
926  THROW_ASSERT(def_gn->get_kind() == gimple_nop_K or def_gn->index,
927  sn->ToString() + " is defined in entry");
928  THROW_ASSERT(def_gn->get_kind() == gimple_nop_K or
929  (def_gn->get_kind() == gimple_assign_K &&
930  GetPointer<const gimple_assign>(GET_NODE(def_stmt))->clobber) or
931  def_gn->bb_index or sn->virtual_flag,
932  "Definition " + def_gn->ToString() + " of " + sn->ToString() + " is in BB" +
933  STR(def_gn->bb_index));
934  if(statement == list_of_stmt.begin() && list_of_bloc.at(curr_bb)->list_of_pred.size() == 1 &&
935  def_gn->bb_index == curr_bb && def_gn->get_kind() != gimple_phi_K)
936  {
939  "--- no constraint because is the first one");
940  }
941  else
942  {
944  "--- Adding BB" + STR(def_gn->bb_index) + " because of " + def_gn->ToString());
945  BB_def.insert(def_gn->bb_index);
946  }
947  }
948  }
950  if(BB_def.find(curr_bb) != BB_def.end())
951  {
953  bool can_be_pipelined = list_of_bloc.at(curr_bb)->loop_id != 0;
954  const auto Lop_it_end = list_of_bloc.at(curr_bb)->list_of_pred.end();
955  for(auto Lop_it = list_of_bloc.at(curr_bb)->list_of_pred.begin();
956  Lop_it != Lop_it_end && can_be_pipelined; ++Lop_it)
957  {
958  can_be_pipelined = list_of_bloc.at(curr_bb)->loop_id >= list_of_bloc.at(*Lop_it)->loop_id;
959  }
961  bool zero_delay = true;
962  if(can_be_pipelined && (gn->vuses.size() || CheckMovable(curr_bb, tn, zero_delay, TM) ==
964  {
965  THROW_ASSERT(bb_dominator_map.find(bb_vertex) != bb_dominator_map.end(), "unexpected condition");
966  }
968  "<--Skipped because uses ssa defined in the same block");
969  continue;
970  }
971  if((gn->vuses.size() || (GetPointer<gimple_assign>(tn) &&
972  (GET_NODE(GetPointer<gimple_assign>(tn)->op1)->get_kind() == call_expr_K ||
973  GET_NODE(GetPointer<gimple_assign>(tn)->op1)->get_kind() == mem_ref_K))) &&
974  !isFunctionPipelined && !parallel_bb)
975  {
976  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Skipped because of vuses");
977  continue;
978  }
980  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Checking where it can be moved");
981  auto dest_bb_index = curr_bb;
982  auto prev_dest_bb_index = curr_bb;
983  if(gn->vdef || gn->vuses.size() ||
984  (tn->get_kind() == gimple_assign_K &&
985  GET_NODE(GetPointer<gimple_assign>(tn)->op1)->get_kind() == mem_ref_K))
986  {
987  if(list_of_bloc.at(curr_bb)->list_of_pred.size() == 1 &&
988  list_of_bloc.at(curr_bb)->list_of_pred.front() != bloc::ENTRY_BLOCK_ID &&
989  ((tn->get_kind() == gimple_assign_K &&
990  (GET_NODE(GetPointer<gimple_assign>(tn)->op0)->get_kind() == mem_ref_K ||
991  GET_NODE(GetPointer<gimple_assign>(tn)->op1)->get_kind() == mem_ref_K)) ||
992  tn->get_kind() == gimple_nop_K) &&
993  list_of_bloc.at(list_of_bloc.at(curr_bb)->list_of_pred.front())->loop_id ==
994  list_of_bloc.at(curr_bb)->loop_id)
995  {
996  dest_bb_index = list_of_bloc.at(curr_bb)->list_of_pred.front();
997  }
998  else
999  {
1001  "<--Skipped because is not a store/load or because we do not know the condition under "
1002  "which the store/load is done");
1004  continue;
1005  }
1006  }
1007  else
1008  {
1009  vertex dom_bb = bb_vertex;
1010  if(bb_dominator_map.find(dom_bb) != bb_dominator_map.end())
1011  {
1012  dom_bb = bb_dominator_map.find(dom_bb)->second;
1014  "---Considering its dominator BB" + STR(direct_vertex_map[dom_bb]));
1015  auto dom_bb_index = direct_vertex_map[dom_bb];
1016  while(dom_bb_index != bloc::ENTRY_BLOCK_ID)
1017  {
1018  unsigned loop_idU = list_of_bloc.at(dom_bb_index)->loop_id;
1019  unsigned loop_idC = list_of_bloc.at(curr_bb)->loop_id;
1020  if(loop_idC >= loop_idU)
1021  {
1022  prev_dest_bb_index = dest_bb_index;
1023  dest_bb_index = dom_bb_index;
1024  bool internLoopDep = false;
1025  for(auto BBdef : BB_def)
1026  {
1027  if(list_of_bloc.at(BBdef)->loop_id > loop_idU && list_of_bloc.at(BBdef)->loop_id <= loop_idC)
1028  {
1029  internLoopDep = true;
1030  }
1031  }
1032  if(internLoopDep)
1033  {
1035  "---the statement depends on values defined at inner level than dest BB" +
1036  STR(dest_bb_index));
1037  dest_bb_index = curr_bb;
1038  break;
1039  }
1041  "---Going up one level. Considering now BB" + STR(dest_bb_index));
1042  }
1043  if(BB_def.find(dom_bb_index) != BB_def.end())
1044  {
1046  "---It contains the definition of one SSA used by the statement to be moved");
1047  break;
1048  }
1049  if(bb_dominator_map.find(dom_bb) == bb_dominator_map.end())
1050  {
1051  break;
1052  }
1053  dom_bb = bb_dominator_map.find(dom_bb)->second;
1054  dom_bb_index = direct_vertex_map[dom_bb];
1055  }
1056  }
1057  }
1059 
1061  if(dest_bb_index == curr_bb)
1062  {
1064  "<--Skipped (1) because destination would be the same bb");
1065  continue;
1066  }
1068  bool is_controlling_condition_constant = true;
1069  const auto Lop_it_end = list_of_bloc.at(curr_bb)->list_of_pred.end();
1070  for(auto Lop_it = list_of_bloc.at(curr_bb)->list_of_pred.begin();
1071  Lop_it != Lop_it_end && is_controlling_condition_constant; ++Lop_it)
1072  {
1073  if(sl->list_of_bloc.at(*Lop_it)->CGetStmtList().empty())
1074  {
1075  is_controlling_condition_constant = false;
1076  }
1077  else
1078  {
1079  auto last_statement = sl->list_of_bloc.at(*Lop_it)->CGetStmtList().back();
1080  if(GET_NODE(last_statement)->get_kind() == gimple_cond_K)
1081  {
1082  auto* gc = GetPointer<gimple_cond>(GET_NODE(last_statement));
1083  if(GET_NODE(gc->op0)->get_kind() != integer_cst_K)
1084  {
1085  is_controlling_condition_constant = false;
1086  }
1087  }
1088  else if(GET_NODE(last_statement)->get_kind() == gimple_multi_way_if_K)
1089  {
1090  is_controlling_condition_constant = false;
1091  }
1092  else
1093  {
1094  is_controlling_condition_constant = false;
1095  }
1096  }
1097  }
1098  bool zero_delay = true;
1099  auto check_movable = CheckMovable(dest_bb_index, tn, zero_delay, TM);
1100  if((check_movable == FunctionFrontendFlowStep_Movable::TIMING) && is_controlling_condition_constant)
1101  {
1103  }
1104  if(!isFunctionPipelined && !parallel_bb && check_movable == FunctionFrontendFlowStep_Movable::UNMOVABLE)
1105  {
1106  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Skipped because cannot be moved");
1107  continue;
1108  }
1109  if(!AppM->ApplyNewTransformation())
1110  {
1112  "<--Skipped because reached limit of CFG transformations");
1113  continue;
1114  }
1115 
1117 
1119  bool only_phis = true;
1120  for(const auto sn : stmt_ssa_uses)
1121  {
1122  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Checking definition of " + sn->ToString());
1123  for(auto const& def_stmt : sn->CGetDefStmts())
1124  {
1125  auto* def_gn = GetPointer<gimple_node>(GET_NODE(def_stmt));
1126  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Checked definition " + def_gn->ToString());
1127  if(def_gn->bb_index == dest_bb_index && def_gn->get_kind() != gimple_phi_K &&
1128  zero_delay_stmts.find(def_stmt->index) == zero_delay_stmts.end())
1129  {
1130  only_phis = false;
1132  }
1133  }
1135  }
1136  if(only_phis && zero_delay)
1137  {
1138  zero_delay_stmts.insert(GET_INDEX_NODE(*statement));
1139  }
1140  if(check_movable == FunctionFrontendFlowStep_Movable::TIMING or (!only_phis && !zero_delay && !parallel_bb))
1141  {
1143  "---Going down of one level because of non-zero delay");
1144  dest_bb_index = prev_dest_bb_index;
1145  }
1146 
1148  if(dest_bb_index == curr_bb)
1149  {
1151  "<--Skipped (2) because destination would be the same bb");
1152  continue;
1153  }
1154  modified = true;
1155  AppM->RegisterTransformation(GetName(), *statement);
1156 
1158  if(tn->get_kind() == gimple_assign_K &&
1159  (GET_NODE(GetPointer<gimple_assign>(tn)->op0)->get_kind() == mem_ref_K ||
1160  GET_NODE(GetPointer<gimple_assign>(tn)->op1)->get_kind() == mem_ref_K))
1161  {
1162  if(list_of_bloc.at(dest_bb_index)->CGetStmtList().empty())
1163  {
1165  }
1166  else
1167  {
1168  const auto& lastStmt = *(list_of_bloc.at(dest_bb_index)->CGetStmtList().rbegin());
1169  auto lastStmtNode = GET_NODE(lastStmt);
1170  auto ga = GetPointer<gimple_assign>(tn);
1171  if(lastStmtNode->get_kind() == gimple_cond_K)
1172  {
1173  if(ga->predicate && GET_NODE(ga->predicate)->get_kind() == integer_cst_K)
1174  {
1175  auto cond = tree_helper::GetConstValue(ga->predicate);
1176  if(cond != 0)
1177  {
1178  if(list_of_bloc.at(dest_bb_index)->true_edge == curr_bb)
1179  {
1180  TM->ReplaceTreeNode(*statement, ga->predicate,
1181  GetPointer<gimple_cond>(lastStmtNode)->op0);
1182  }
1183  else
1184  {
1186  auto not_cond = tree_man->CreateNotExpr(GetPointer<gimple_cond>(lastStmtNode)->op0,
1187  list_of_bloc.at(dest_bb_index), function_id);
1188  TM->ReplaceTreeNode(*statement, ga->predicate, not_cond);
1189  }
1190  }
1191  }
1192  else
1193  {
1194  if(list_of_bloc.at(dest_bb_index)->true_edge == curr_bb)
1195  {
1196  auto and_cond =
1197  tree_man->CreateAndExpr(GetPointer<gimple_cond>(lastStmtNode)->op0, ga->predicate,
1198  list_of_bloc.at(dest_bb_index), function_id);
1199  TM->ReplaceTreeNode(*statement, ga->predicate, and_cond);
1200  }
1201  else
1202  {
1203  auto not_cond = tree_man->CreateNotExpr(GetPointer<gimple_cond>(lastStmtNode)->op0,
1204  list_of_bloc.at(dest_bb_index), function_id);
1205  auto and_cond = tree_man->CreateAndExpr(not_cond, ga->predicate,
1206  list_of_bloc.at(dest_bb_index), function_id);
1207  TM->ReplaceTreeNode(*statement, ga->predicate, and_cond);
1208  }
1209  }
1210  }
1211  else if(lastStmtNode->get_kind() == gimple_multi_way_if_K)
1212  {
1213  auto gmwi = GetPointer<gimple_multi_way_if>(lastStmtNode);
1214  bool found_condition = false;
1215  for(const auto& gmwicond : gmwi->list_of_cond)
1216  {
1217  if(gmwicond.second == curr_bb)
1218  {
1219  found_condition = true;
1220  if(!gmwicond.first)
1221  {
1223  auto firstCond = true;
1224  tree_nodeRef Cur;
1225  for(const auto& gmwicond0 : gmwi->list_of_cond)
1226  {
1227  if(gmwicond0.first)
1228  {
1229  if(firstCond)
1230  {
1231  Cur = gmwicond0.first;
1232  firstCond = false;
1233  }
1234  else
1235  {
1236  Cur = tree_man->CreateOrExpr(Cur, gmwicond0.first,
1237  list_of_bloc.at(dest_bb_index), function_id);
1238  }
1239  }
1240  }
1241  Cur = tree_man->CreateNotExpr(Cur, list_of_bloc.at(dest_bb_index), function_id);
1242  if(ga->predicate && GET_NODE(ga->predicate)->get_kind() == integer_cst_K)
1243  {
1244  const auto cond = tree_helper::GetConstValue(ga->predicate);
1245  if(cond != 0)
1246  {
1247  TM->ReplaceTreeNode(*statement, ga->predicate, Cur);
1248  }
1249  }
1250  else
1251  {
1252  auto and_cond = tree_man->CreateAndExpr(Cur, ga->predicate,
1253  list_of_bloc.at(dest_bb_index), function_id);
1254  TM->ReplaceTreeNode(*statement, ga->predicate, and_cond);
1255  }
1256  }
1257  else
1258  {
1259  if(ga->predicate && GET_NODE(ga->predicate)->get_kind() == integer_cst_K)
1260  {
1261  const auto cond = tree_helper::GetConstValue(ga->predicate);
1262  if(cond != 0)
1263  {
1264  TM->ReplaceTreeNode(*statement, ga->predicate, gmwicond.first);
1265  }
1266  }
1267  else
1268  {
1269  auto and_cond = tree_man->CreateAndExpr(gmwicond.first, ga->predicate,
1270  list_of_bloc.at(dest_bb_index), function_id);
1271  TM->ReplaceTreeNode(*statement, ga->predicate, and_cond);
1272  }
1273  }
1274  break;
1275  }
1276  }
1277  if(!found_condition)
1278  {
1279  THROW_ERROR("node not supported: " + lastStmtNode->get_kind_text() + " " +
1280  lastStmtNode->ToString());
1281  }
1282  }
1283  else if(list_of_bloc.at(dest_bb_index)->list_of_succ.size() == 1 &&
1284  list_of_bloc.at(dest_bb_index)->loop_id == list_of_bloc.at(curr_bb)->loop_id)
1285  {
1287  }
1288  else
1289  {
1290  THROW_ERROR("node not supported: " + lastStmtNode->get_kind_text() + " " +
1291  lastStmtNode->ToString());
1292  }
1293  }
1294  }
1295  const auto temp_statement = *statement;
1297  auto tmp_it = statement;
1298  ++tmp_it;
1300  list_of_bloc.at(curr_bb)->RemoveStmt(temp_statement, AppM);
1301  if(list_of_bloc.at(curr_bb)->CGetStmtList().empty() && list_of_bloc.at(curr_bb)->CGetPhiList().empty())
1302  {
1303  restart_ifmwi_opt = true;
1304  }
1305  list_of_bloc.at(dest_bb_index)->PushBack(temp_statement, AppM);
1307  --tmp_it;
1308  statement = tmp_it;
1309  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Moved in BB" + STR(dest_bb_index));
1310  }
1311 
1312  for(const auto& removing : to_be_removed)
1313  {
1315  "---Removing " + removing->ToString() + " from BB" + STR(curr_bb));
1316  list_of_bloc.at(curr_bb)->RemoveStmt(removing, AppM);
1317  }
1318  if(!to_be_removed.empty() && list_of_bloc.at(curr_bb)->CGetStmtList().empty() &&
1319  list_of_bloc.at(curr_bb)->CGetPhiList().empty())
1320  {
1321  restart_ifmwi_opt = true;
1322  }
1323  for(const auto& adding_back : to_be_added_back)
1324  {
1326  "---Adding back " + adding_back->ToString() + " from BB" + STR(curr_bb));
1327  list_of_bloc.at(curr_bb)->PushBack(adding_back, AppM);
1328  }
1329  for(const auto& adding_front : to_be_added_front)
1330  {
1332  "---Adding front " + adding_front->ToString() + " from BB" + STR(curr_bb));
1333  list_of_bloc.at(curr_bb)->PushFront(adding_front, AppM);
1334  }
1335  restart_bb_code_motion = (!to_be_added_back.empty()) or (!to_be_added_front.empty());
1337  (!parameters->IsParameter("print-dot-FF") || parameters->GetParameter<unsigned int>("print-dot-FF")))
1338  {
1339  GCC_bb_graph->WriteDot("BB_simple_code_motion_" + STR(counter) + ".dot");
1341  "---Written BB_simple_code_motion_" + STR(counter) + ".dot");
1342  counter++;
1343  }
1344  if(restart_bb_code_motion)
1345  {
1347  "---Restart Analyzing BB" + STR(curr_bb) + (parallel_bb ? "(Parallel)" : ""));
1348  }
1349  } while(restart_bb_code_motion);
1350  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Analyzed BB" + STR(curr_bb));
1351  }
1352 
1353  modified ? function_behavior->UpdateBBVersion() : 0;
1355 }
1356 
1358 {
1359  if(schedule)
1360  {
1361  return true;
1362  }
1363  else
1364  {
1365  return false;
1366  }
1367 }
#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;.
boost::graph_traits< graph >::out_edge_iterator OutEdgeIterator
out_edge_iterator definition.
Definition: graph.hpp:1312
File containing functions and utilities to support the printing of debug messagges.
Step successfully executed.
static bool IsConstant(const tree_nodeConstRef &node)
Return if a tree node is a constant object.
Definition of the node_info object for the basic_block graph.
string target
Definition: lenet_tvm.py:16
#define GET_CLASS(obj)
Macro returning the actual type of an object.
This struct specifies the statement_list node.
Definition: tree_node.hpp:4662
Definition of the class representing a generic C application.
#define CASE_DECL_NODES
NOTE that cast_expr is a unary expression but it could not be included in the CASE_UNARY_EXPRESSION b...
Definition: tree_node.hpp:672
std::string GetName() const override
Return the name of this design step.
static bool is_real(const tree_managerConstRef &TM, const unsigned int index)
Return true if the treenode is of real type.
void WriteDot(const std::string &file_name, const int detail_level=0) const
Writes this graph in dot format.
ScheduleRef schedule
The scheduling solution.
RelationshipType
The relationship type.
struct definition of the function_decl tree node.
Definition: tree_node.hpp:2759
Source must be executed to satisfy target.
mathematical utility function not provided by standard libraries
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.
static const unsigned int EXIT_BLOCK_ID
constant identifying the exit basic block
DesignFlowStep_Status InternalExec() override
Updates the tree to have a more compliant CFG.
#define GET_INDEX_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:361
#define min(x, y)
Data structure describing a basic block at tree level.
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.
~simple_code_motion() override
Destructor.
FunctionFrontendFlowStep_Movable CheckMovable(const unsigned int dest_bb_index, tree_nodeRef tn, bool &zero_delay, const tree_managerRef TM)
Check if a statement can be moved in a basic block.
bool
Definition: bellmanford.c:29
virtual enum kind get_kind() const =0
Virtual function returning the type of the actual class.
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
#define max
Definition: backprop.h:17
bool conservative
True if only zero delay statement can be moved.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
virtual std::string get_kind_text() const =0
Virtual function returning the name of the actual class.
static unsigned long long Size(const tree_nodeConstRef &tn)
Return the size of a tree object.
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.
static void compute_ssa_uses_rec_ptr(const tree_nodeConstRef &tn, CustomOrderedSet< const ssa_name *> &ssa_uses)
recursively compute the pointers to the ssa_name variables used in a statement
#define CASE_QUATERNARY_EXPRESSION
This macro collects all case labels for quaternary_expr objects.
Definition: tree_node.hpp:574
FunctionFrontendFlowStep_Movable CanBeMoved(const unsigned int statement_index, const unsigned int basic_block) const
Check if a statement can be moved at the end of a basic block.
Definition: schedule.cpp:601
HLSFlowStep_Type
Definition: hls_step.hpp:95
void cyclic_topological_sort(VertexListGraph &g, OutputIterator result, const boost::bgl_named_params< P, T, R > &params)
refcount< BBNodeInfo > BBNodeInfoRef
refcount definition of the class
Information associated with the whole basic-block graph.
Classes to describe design flow graph.
tree_nodeRef body
body field is the saved representation of the body of the entire function.
Definition: tree_node.hpp:2870
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
Definition: graph.hpp:1303
#define GET_CONST_NODE(t)
Definition: tree_node.hpp:347
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.
Class defining some useful functions to create tree nodes and to manipulate the tree manager...
#define DEBUG_LEVEL_NONE
no debugging print is performed.
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
Definition: exceptions.hpp:263
Wrapper of design_flow.
This struct specifies the block node.
Definition: tree_node.hpp:1820
#define CASE_TYPE_NODES
This macro collects all case labels for type objects.
Definition: tree_node.hpp:581
This file collects some utility functions.
FunctionFrontendFlowStep_Movable
Enum class used to specify if a statement can be moved.
const unsigned int function_id
The index of the function to be analyzed.
Analysis step that performs some simple code motions over the IR.
#define CASE_CST_NODES
This macro collects all case labels for cast nodes.
Definition: tree_node.hpp:689
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
#define CASE_FAKE_NODES
This macro collects all case labels for fake or empty nodes.
Definition: tree_node.hpp:635
File used to compute the topological sort in a cyclic graph.
Class specification of the basic_block structure.
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.
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.
#define CASE_CPP_NODES
This macro collects all case labels for cpp nodes.
Definition: tree_node.hpp:644
bool IsScheduleBased() const
Return true if the last run of this step was based on scheduling.
unsigned counter[N_THREADS]
Definition: data.c:3
simple_code_motion(const ParameterConstRef parameters, const application_managerRef AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
#define CASE_GIMPLE_NODES
This macro collects all cases labels for gimple nodes.
Definition: tree_node.hpp:700
static integer_cst_t GetConstValue(const tree_nodeConstRef &tn, bool is_signed=true)
Get value from integer constant.
int debug_level
The debug level.
static bool is_constant(const tree_managerConstRef &TM, const unsigned int index)
Return if a tree node is a constant object.
#define CFG_SELECTOR
Control flow graph edge selector.
Data structure definition for high-level synthesis flow.
Operation cannot be moved because of timing.
refcount< BBGraphInfo > BBGraphInfoRef
refcount definition of the class
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.
static bool IsRealType(const tree_nodeConstRef &type)
Return true if the treenode is of real type.
const FunctionBehaviorRef function_behavior
The function behavior of the function to be analyzed.
int sl
Definition: adpcm.c:105
#define CASE_PRAGMA_NODES
This macro collects all case labels for pragma objects.
Definition: tree_node.hpp:610
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