PandA-2024.02
CSE.cpp
Go to the documentation of this file.
1 /*
2  *
3  * _/_/_/ _/_/ _/ _/ _/_/_/ _/_/
4  * _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
5  * _/_/_/ _/_/_/_/ _/ _/_/ _/ _/ _/_/_/_/
6  * _/ _/ _/ _/ _/ _/ _/ _/ _/
7  * _/ _/ _/ _/ _/ _/_/_/ _/ _/
8  *
9  * ***********************************************
10  * PandA Project
11  * URL: http://panda.dei.polimi.it
12  * Politecnico di Milano - DEIB
13  * System Architectures Group
14  * ***********************************************
15  * Copyright (C) 2004-2024 Politecnico di Milano
16  *
17  * This file is part of the PandA framework.
18  *
19  * The PandA framework is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
33 
45 #include "CSE.hpp"
47 
49 #include "Parameter.hpp"
50 
52 #include <boost/graph/topological_sort.hpp>
53 
55 #include "application_manager.hpp"
56 #include "call_graph_manager.hpp"
57 #include "function_behavior.hpp"
58 
60 #include "Dominance.hpp"
61 
63 #include "design_flow_manager.hpp"
64 
67 
69 #include "hls_manager.hpp"
70 #if HAVE_ILP_BUILT
71 #include "hls.hpp"
73 
75 #include "schedule.hpp"
76 #endif
77 
79 #include <cmath>
80 #include <fstream>
81 #include <string>
82 
84 #include "behavioral_helper.hpp"
85 #include "tree_basic_block.hpp"
86 #include "tree_helper.hpp"
87 #include "tree_manager.hpp"
88 #include "tree_manipulation.hpp"
89 #include "tree_reindex.hpp"
90 
91 #include "basic_block.hpp"
92 #include "string_manipulation.hpp" // for GET_CLASS
93 
94 CSE::CSE(const ParameterConstRef _parameters, const application_managerRef _AppM, unsigned int _function_id,
95  const DesignFlowManagerConstRef _design_flow_manager)
96  : FunctionFrontendFlowStep(_AppM, _function_id, CSE_STEP, _design_flow_manager, _parameters),
97  TM(_AppM->get_tree_manager()),
98  restart_phi_opt(false)
99 {
100  debug_level = parameters->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
101 }
102 
103 CSE::~CSE() = default;
104 
107 {
109  switch(relationship_type)
110  {
112  {
113  if(!parameters->getOption<int>(OPT_gcc_openmp_simd))
114  {
115  relationships.insert(std::make_pair(BITVALUE_RANGE, SAME_FUNCTION));
116  }
117  relationships.insert(std::make_pair(DEAD_CODE_ELIMINATION, SAME_FUNCTION));
118  relationships.insert(std::make_pair(DEAD_CODE_ELIMINATION_IPA, WHOLE_APPLICATION));
119  relationships.insert(std::make_pair(DETERMINE_MEMORY_ACCESSES, SAME_FUNCTION));
120  relationships.insert(std::make_pair(SIMPLE_CODE_MOTION, SAME_FUNCTION));
121  relationships.insert(std::make_pair(USE_COUNTING, SAME_FUNCTION));
122  break;
123  }
125  {
126  relationships.insert(std::make_pair(IR_LOWERING, SAME_FUNCTION));
127  relationships.insert(std::make_pair(PHI_OPT, SAME_FUNCTION));
128  relationships.insert(std::make_pair(SDC_CODE_MOTION, SAME_FUNCTION));
129  relationships.insert(std::make_pair(UN_COMPARISON_LOWERING, SAME_FUNCTION));
130  break;
131  }
133  {
134  switch(GetStatus())
135  {
137  {
138  relationships.insert(std::make_pair(DEAD_CODE_ELIMINATION, SAME_FUNCTION));
139  if(restart_phi_opt)
140  {
141  relationships.insert(std::make_pair(PHI_OPT, SAME_FUNCTION));
142  }
143  break;
144  }
149  {
150  break;
151  }
155  default:
156  THROW_UNREACHABLE("");
157  }
158  break;
159  }
160  default:
161  THROW_UNREACHABLE("");
162  }
163  return relationships;
164 }
165 
167 {
168 #if HAVE_ILP_BUILT
169  if(GetPointer<const HLS_manager>(AppM) && GetPointerS<const HLS_manager>(AppM)->get_HLS(function_id) &&
170  GetPointerS<const HLS_manager>(AppM)->get_HLS(function_id)->Rsch)
171  {
172  schedule = GetPointerS<const HLS_manager>(AppM)->get_HLS(function_id)->Rsch;
173  }
174 #endif
175 }
176 
178 {
179  if(parameters->IsParameter("disable-cse") && parameters->GetParameter<unsigned int>("disable-cse") == 1)
180  {
182  }
183  bool IR_changed = false;
184  restart_phi_opt = false;
185 #ifndef NDEBUG
186  size_t n_equiv_stmt = 0;
187 #endif
188  const auto IRman = tree_manipulationRef(new tree_manipulation(TM, parameters, AppM));
190  std::map<vertex, CustomUnorderedMapStable<CSE_tuple_key_type, tree_nodeRef>> unique_table;
191 
192  const auto temp = TM->CGetTreeNode(function_id);
193  const auto fd = GetPointerS<const function_decl>(temp);
194  const auto sl = GetPointerS<const statement_list>(GET_CONST_NODE(fd->body));
195 
197  BBGraphsCollectionRef GCC_bb_graphs_collection(
199  BBGraphRef GCC_bb_graph(new BBGraph(GCC_bb_graphs_collection, CFG_SELECTOR));
200  CustomUnorderedMap<unsigned int, vertex> inverse_vertex_map;
202  for(const auto& block : sl->list_of_bloc)
203  {
204  inverse_vertex_map[block.first] =
205  GCC_bb_graphs_collection->AddVertex(BBNodeInfoRef(new BBNodeInfo(block.second)));
206  }
208  for(const auto& idx_bb : sl->list_of_bloc)
209  {
210  for(const auto& pred : idx_bb.second->list_of_pred)
211  {
212  THROW_ASSERT(inverse_vertex_map.find(pred) != inverse_vertex_map.end(),
213  "BB" + STR(pred) + " (successor of BB" + STR(idx_bb.first) + ") does not exist");
214  GCC_bb_graphs_collection->AddEdge(inverse_vertex_map[pred], inverse_vertex_map[idx_bb.first], CFG_SELECTOR);
215  }
216  for(const auto& succ : idx_bb.second->list_of_succ)
217  {
218  if(succ == bloc::EXIT_BLOCK_ID)
219  {
220  GCC_bb_graphs_collection->AddEdge(inverse_vertex_map[idx_bb.first], inverse_vertex_map[succ], CFG_SELECTOR);
221  }
222  }
223  if(idx_bb.second->list_of_succ.empty())
224  {
225  GCC_bb_graphs_collection->AddEdge(inverse_vertex_map[idx_bb.first], inverse_vertex_map[bloc::EXIT_BLOCK_ID],
226  CFG_SELECTOR);
227  }
228  }
230  GCC_bb_graphs_collection->AddEdge(inverse_vertex_map[bloc::ENTRY_BLOCK_ID], inverse_vertex_map[bloc::EXIT_BLOCK_ID],
231  CFG_SELECTOR);
232 
233  refcount<dominance<BBGraph>> bb_dominators;
234  bb_dominators = refcount<dominance<BBGraph>>(new dominance<BBGraph>(
235  *GCC_bb_graph, inverse_vertex_map[bloc::ENTRY_BLOCK_ID], inverse_vertex_map[bloc::EXIT_BLOCK_ID], parameters));
236  bb_dominators->calculate_dominance_info(dominance<BBGraph>::CDI_DOMINATORS);
237  const auto& bb_dominator_map = bb_dominators->get_dominator_map();
238 
239  BBGraphRef bb_domGraph(new BBGraph(GCC_bb_graphs_collection, D_SELECTOR));
240  for(auto it : bb_dominator_map)
241  {
242  if(it.first != inverse_vertex_map[bloc::ENTRY_BLOCK_ID])
243  {
244  GCC_bb_graphs_collection->AddEdge(it.second, it.first, D_SELECTOR);
245  }
246  }
247 
248  std::deque<vertex> sort_list;
249  boost::topological_sort(*bb_domGraph, std::front_inserter(sort_list));
250 
251  for(const auto& bb : sort_list)
252  {
253  const auto B = bb_domGraph->CGetBBNodeInfo(bb)->block;
254  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Considering BB " + STR(B->number));
256  unique_table[bb].clear();
257  if(bb_dominator_map.find(bb) != bb_dominator_map.end())
258  {
259  THROW_ASSERT(unique_table.find(bb_dominator_map.at(bb)) != unique_table.end(), "unexpected condition");
261  "---Adding dominator equiv: " +
262  STR(bb_domGraph->CGetBBNodeInfo(bb_dominator_map.at(bb))->block->number));
263 
264  for(const auto& key_value_pair : unique_table.at(bb_dominator_map.at(bb)))
265  {
266  unique_table.at(bb)[key_value_pair.first] = key_value_pair.second;
267  }
268  }
269  TreeNodeSet to_be_removed;
270  for(const auto& stmt : B->CGetStmtList())
271  {
273  if(!AppM->ApplyNewTransformation())
274  {
275  break;
276  }
277  const auto eq_tn = hash_check(GET_NODE(stmt), bb, sl, unique_table);
278  if(eq_tn)
279  {
280  const auto ref_ga = GetPointerS<gimple_assign>(eq_tn);
281  const auto dead_ga = GetPointerS<const gimple_assign>(GET_CONST_NODE(stmt));
282  const auto ref_ssa = GetPointerS<ssa_name>(GET_NODE(ref_ga->op0));
283  const auto dead_ssa = GetPointerS<const ssa_name>(GET_CONST_NODE(dead_ga->op0));
284 
285  if(ref_ssa->min)
286  {
287  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---ref_min=" + STR(ref_ssa->min));
288  }
289  if(ref_ssa->max)
290  {
291  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---ref_max=" + STR(ref_ssa->max));
292  }
293  if(dead_ssa->min)
294  {
295  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---dead_min=" + STR(dead_ssa->min));
296  }
297  if(dead_ssa->max)
298  {
299  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---dead_max=" + STR(dead_ssa->max));
300  }
301 
302  if(!ref_ssa->bit_values.empty())
303  {
304  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---ref_bit_values=" + ref_ssa->bit_values);
305  }
306  if(!dead_ssa->bit_values.empty())
307  {
308  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---dead_bit_values=" + dead_ssa->bit_values);
309  }
310 
311  bool same_range = false;
312  if(!parameters->getOption<int>(OPT_gcc_openmp_simd))
313  {
314  same_range = dead_ssa->bit_values.empty() || ref_ssa->bit_values == dead_ssa->bit_values;
315  }
316  else
317  {
318  const auto ga_op_type = tree_helper::CGetType(ref_ga->op0);
319  if(GET_CONST_NODE(ga_op_type)->get_kind() == integer_type_K && ref_ssa->min && ref_ssa->max &&
320  dead_ssa->min && dead_ssa->max)
321  {
322  const auto ref_min = tree_helper::GetConstValue(ref_ssa->min);
323  const auto dead_min = tree_helper::GetConstValue(dead_ssa->min);
324  const auto ref_max = tree_helper::GetConstValue(ref_ssa->max);
325  const auto dead_max = tree_helper::GetConstValue(dead_ssa->max);
326  if(dead_min == ref_min && dead_max == ref_max)
327  {
328  same_range = true;
329  }
330  else
331  {
333  "---replace equivalent statement before: ref_min=" + STR(ref_min) + " dead_min=" +
334  STR(dead_min) + " ref_max=" + STR(ref_max) + " dead_max=" + STR(dead_max));
335  }
336  }
337  }
338  if(same_range)
339  {
340  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Updating/Removing " + STR(dead_ga->op0));
341  ref_ga->temporary_address = ref_ga->temporary_address && dead_ga->temporary_address;
343  "---ref_ga->temporary_address" +
344  (ref_ga->temporary_address ? std::string("T") : std::string("F")));
345  if(dead_ssa->use_set && !ref_ssa->use_set)
346  {
347  ref_ssa->use_set = dead_ssa->use_set;
348  }
349 
350  const auto StmtUses = dead_ssa->CGetUseStmts();
351  for(const auto& use : StmtUses)
352  {
354  "---replace equivalent statement before: " + use.first->ToString());
355  TM->ReplaceTreeNode(use.first, dead_ga->op0, ref_ga->op0);
357  "---replace equivalent statement after: " + use.first->ToString());
358  }
359  to_be_removed.insert(stmt);
360 
361  AppM->RegisterTransformation(GetName(), stmt);
362  IR_changed = true;
363 #ifndef NDEBUG
364  ++n_equiv_stmt;
365 #endif
367  "<--Updated/Removed duplicated statement " + STR(dead_ga->op0));
368  }
369  else
370  {
371  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---not the same range");
372  }
373  }
374  }
375  for(const auto& stmt : to_be_removed)
376  {
378  B->RemoveStmt(stmt, AppM);
379  }
380  if(B->CGetStmtList().empty() && B->CGetPhiList().empty() && !to_be_removed.empty())
381  {
382  restart_phi_opt = true;
383  }
384  if(!to_be_removed.empty() && schedule)
385  {
386  for(const auto& stmt : B->CGetStmtList())
387  {
389  }
390  }
391  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Considered BB" + STR(B->number));
392  }
393  if(!IR_changed)
394  {
395  restart_phi_opt = false;
396  }
397  INDENT_DBG_MEX(DEBUG_LEVEL_VERBOSE, debug_level, "---CSE: number of equivalent statement = " + STR(n_equiv_stmt));
398  IR_changed ? function_behavior->UpdateBBVersion() : 0;
400 }
401 
403 {
404  const auto& fun_mem_data = function_behavior->get_function_mem();
405  const auto rhs_kind = GET_CONST_NODE(ga->op1)->get_kind();
406  const auto op0_type = tree_helper::CGetType(ga->op0);
407  const auto op1_type = tree_helper::CGetType(ga->op1);
409  const auto is_a_vector_bitfield =
410  rhs_kind == bit_field_ref_K &&
411  tree_helper::IsVectorType(GetPointerS<const bit_field_ref>(GET_CONST_NODE(ga->op1))->op0);
412 
413  bool skip_check = rhs_kind == var_decl_K || rhs_kind == string_cst_K || rhs_kind == constructor_K ||
414  (rhs_kind == bit_field_ref_K && !is_a_vector_bitfield) || rhs_kind == component_ref_K ||
415  rhs_kind == indirect_ref_K || rhs_kind == misaligned_indirect_ref_K || rhs_kind == array_ref_K ||
416  rhs_kind == target_mem_ref_K || rhs_kind == target_mem_ref461_K or rhs_kind == mem_ref_K;
417  if(rhs_kind == realpart_expr_K || rhs_kind == imagpart_expr_K)
418  {
419  const auto code1 = GET_CONST_NODE(GetPointerS<const unary_expr>(GET_CONST_NODE(ga->op1))->op)->get_kind();
420  if((code1 == bit_field_ref_K && !is_a_vector_bitfield) || code1 == component_ref_K || code1 == indirect_ref_K ||
421  code1 == bit_field_ref_K || code1 == misaligned_indirect_ref_K || code1 == mem_ref_K || code1 == array_ref_K ||
422  code1 == target_mem_ref_K || code1 == target_mem_ref461_K)
423  {
424  skip_check = true;
425  }
426  if(code1 == var_decl_K && fun_mem_data.find(GET_INDEX_CONST_NODE(
427  GetPointerS<const unary_expr>(GET_CONST_NODE(ga->op1))->op)) != fun_mem_data.end())
428  {
429  skip_check = true;
430  }
431  }
432  else if(rhs_kind == view_convert_expr_K)
433  {
434  const auto vc = GetPointerS<const view_convert_expr>(GET_CONST_NODE(ga->op1));
435  const auto vc_op_type = tree_helper::CGetType(vc->op);
436  if(GET_CONST_NODE(op0_type)->get_kind() == record_type_K || GET_CONST_NODE(op0_type)->get_kind() == union_type_K)
437  {
438  skip_check = true;
439  }
440  if(GET_CONST_NODE(vc_op_type)->get_kind() == record_type_K ||
441  GET_CONST_NODE(vc_op_type)->get_kind() == union_type_K)
442  {
443  skip_check = true;
444  }
445 
446  if(GET_CONST_NODE(vc_op_type)->get_kind() == array_type_K &&
447  GET_CONST_NODE(op0_type)->get_kind() == vector_type_K)
448  {
449  skip_check = true;
450  }
451  if(GET_CONST_NODE(vc_op_type)->get_kind() == vector_type_K &&
452  GET_CONST_NODE(op0_type)->get_kind() == array_type_K)
453  {
454  skip_check = true;
455  }
456  }
457  if(!tree_helper::IsVectorType(ga->op0) && tree_helper::IsArrayEquivType(ga->op0) &&
459  {
460  skip_check = true;
461  }
462  if(fun_mem_data.find(GET_INDEX_CONST_NODE(ga->op0)) != fun_mem_data.end() ||
463  fun_mem_data.find(GET_INDEX_CONST_NODE(ga->op1)) != fun_mem_data.end())
464  {
465  skip_check = true;
466  }
467  if(op0_type && op1_type &&
468  ((GET_CONST_NODE(op0_type)->get_kind() == record_type_K &&
469  GET_CONST_NODE(op1_type)->get_kind() == record_type_K && rhs_kind != view_convert_expr_K) ||
470  (GET_CONST_NODE(op0_type)->get_kind() == union_type_K && GET_CONST_NODE(op1_type)->get_kind() == union_type_K &&
471  rhs_kind != view_convert_expr_K) ||
472  (GET_CONST_NODE(op0_type)->get_kind() == array_type_K)))
473  {
474  skip_check = true;
475  }
476 
477  return skip_check;
478 }
479 
481 CSE::hash_check(const tree_nodeRef& tn, vertex bb_vertex, const statement_list* sl,
483 {
485  if(GetPointer<const gimple_node>(tn)->keep)
486  {
487  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Checked: null keep");
488  return nullptr;
489  }
490  const auto ga = GetPointer<const gimple_assign>(tn);
491  if(ga && (ga->clobber || ga->init_assignment))
492  {
493  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Checked: null clobber/init_assignment");
494  return nullptr;
495  }
496  if(ga && GET_CONST_NODE(ga->op0)->get_kind() == ssa_name_K)
497  {
498  auto bitwidth_values = tree_helper::Size(ga->op0);
499  const auto rhs = GET_CONST_NODE(ga->op1);
500  const auto rhs_kind = rhs->get_kind();
501  if(GetPointer<const binary_expr>(rhs))
502  {
503  bitwidth_values = std::max(bitwidth_values, tree_helper::Size(GetPointerS<const binary_expr>(rhs)->op0));
504  }
505  if(rhs_kind != extract_bit_expr_K && rhs_kind != lut_expr_K && parameters->IsParameter("CSE_size") &&
506  bitwidth_values < parameters->GetParameter<unsigned int>("CSE_size"))
507  {
508  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Checked: too small");
509  return nullptr;
510  }
511  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Right part type: " + rhs->get_kind_text());
512 
514  if(has_memory_access(ga))
515  {
516  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Checked: null memory");
517  return nullptr;
518  }
519  std::vector<unsigned int> ins;
521  ins.push_back(tree_helper::CGetType(ga->op1)->index);
522 
523  if(ga->vuses.size())
524  {
526  ins.push_back(ga->bb_index);
527  for(const auto& vuse : ga->vuses)
528  {
529  ins.push_back(vuse->index);
530 
532  const auto virtual_sn = GetPointerS<const ssa_name>(GET_CONST_NODE(vuse));
533  const auto virtual_sn_def = virtual_sn->CGetDefStmt();
534  const auto virtual_sn_gn = GetPointerS<const gimple_node>(GET_CONST_NODE(virtual_sn_def));
535 
536  if(virtual_sn_gn->bb_index == ga->bb_index)
537  {
538  THROW_ASSERT(sl->list_of_bloc.count(ga->bb_index), "");
539  const auto& bb = sl->list_of_bloc.at(ga->bb_index);
540  const auto vdef_it =
541  virtual_sn_def->get_kind() == gimple_phi_K ?
542  bb->CGetStmtList().end() :
543  std::find_if(bb->CGetStmtList().begin(), bb->CGetStmtList().end(),
544  [&](const tree_nodeRef& stmt) { return stmt->index == virtual_sn_gn->index; });
545  const auto ga_it = std::find_if(vdef_it, bb->CGetStmtList().end(),
546  [&](const tree_nodeRef& stmt) { return stmt->index == ga->index; });
547  if(ga_it != bb->CGetStmtList().end())
548  {
549  ins.push_back(virtual_sn_def->index);
550  }
551  }
552  }
553  }
554  if(rhs_kind == ssa_name_K)
555  {
556  ins.push_back(rhs->index);
557  }
558  else if(GetPointer<const cst_node>(rhs))
559  {
560  ins.push_back(rhs->index);
561  }
562  else if(rhs_kind == nop_expr_K || rhs_kind == view_convert_expr_K || rhs_kind == convert_expr_K ||
563  rhs_kind == float_expr_K || rhs_kind == fix_trunc_expr_K)
564  {
565  const auto ue = GetPointerS<const unary_expr>(rhs);
566  ins.push_back(GET_INDEX_CONST_NODE(ue->op));
567  const auto type_index = tree_helper::CGetType(ga->op0)->index;
568  ins.push_back(type_index);
569  }
570  else if(GetPointer<const unary_expr>(rhs))
571  {
572  const auto ue = GetPointerS<const unary_expr>(rhs);
573  ins.push_back(GET_INDEX_CONST_NODE(ue->op));
574  }
575  else if(GetPointer<const binary_expr>(rhs))
576  {
577  const auto be = GetPointerS<const binary_expr>(rhs);
578  ins.push_back(GET_INDEX_CONST_NODE(be->op0));
579  ins.push_back(GET_INDEX_CONST_NODE(be->op1));
580  }
581  else if(GetPointer<const ternary_expr>(rhs))
582  {
583  const auto te = GetPointerS<const ternary_expr>(rhs);
584  ins.push_back(GET_INDEX_CONST_NODE(te->op0));
585  ins.push_back(GET_INDEX_CONST_NODE(te->op1));
586  if(te->op2)
587  {
588  ins.push_back(GET_INDEX_CONST_NODE(te->op2));
589  }
590  }
591  else if(GetPointer<const call_expr>(rhs))
592  {
593  const auto ce = GetPointerS<const call_expr>(rhs);
594  if(GET_CONST_NODE(ce->fn)->get_kind() == addr_expr_K)
595  {
596  const auto addr_node = GET_CONST_NODE(ce->fn);
597  const auto ae = GetPointerS<const addr_expr>(addr_node);
598  ins.push_back(GET_INDEX_CONST_NODE(ae->op));
599  const auto fd = GetPointerS<const function_decl>(GET_CONST_NODE(ae->op));
600  // TODO: may be optimized
601  if(fd->undefined_flag || fd->writing_memory || fd->reading_memory || ga->vuses.size())
602  {
604  return nullptr;
605  }
606  for(const auto& arg : ce->args)
607  {
608  ins.push_back(GET_INDEX_CONST_NODE(arg));
609  }
610  }
611  else
612  {
614  return nullptr;
615  }
616  }
617  else if(GetPointer<const lut_expr>(rhs))
618  {
619  const auto le = GetPointerS<const lut_expr>(rhs);
620  ins.push_back(GET_INDEX_CONST_NODE(le->op0));
621  ins.push_back(GET_INDEX_CONST_NODE(le->op1));
622  if(le->op2)
623  {
624  ins.push_back(GET_INDEX_CONST_NODE(le->op2));
625  }
626  if(le->op3)
627  {
628  ins.push_back(GET_INDEX_CONST_NODE(le->op3));
629  }
630  if(le->op4)
631  {
632  ins.push_back(GET_INDEX_CONST_NODE(le->op4));
633  }
634  if(le->op5)
635  {
636  ins.push_back(GET_INDEX_CONST_NODE(le->op5));
637  }
638  if(le->op6)
639  {
640  ins.push_back(GET_INDEX_CONST_NODE(le->op6));
641  }
642  if(le->op7)
643  {
644  ins.push_back(GET_INDEX_CONST_NODE(le->op7));
645  }
646  if(le->op8)
647  {
648  ins.push_back(GET_INDEX_CONST_NODE(le->op8));
649  }
650  }
651  else
652  {
654  return nullptr;
655  }
656 
657 #ifndef NDEBUG
658  auto signature_message = "Signature of " + STR(tn->index) + " is ";
659  for(const auto& temp_sign : ins)
660  {
661  signature_message += STR(temp_sign) + "-";
662  }
663  signature_message.pop_back();
665 #endif
666  CSE_tuple_key_type t(rhs_kind, ins);
667  if(unique_table.at(bb_vertex).find(t) != unique_table.at(bb_vertex).end())
668  {
669  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "--- statement = " + tn->ToString());
671  "--- equivalent with = " + unique_table.at(bb_vertex).at(t)->ToString());
673  THROW_ASSERT(!ga->memdef, "Unexpected memdef " + ga->memdef->ToString() + " in " + tn->ToString());
674  THROW_ASSERT(!ga->vdef, "Unexpected vdef " + ga->vdef->ToString() + " in " + tn->ToString());
675  THROW_ASSERT(ga->vovers.empty(), "Unexpected vovers in " + tn->ToString());
676  return unique_table.at(bb_vertex).at(t);
677  }
678  else
679  {
680  unique_table.at(bb_vertex)[t] = tn;
681  }
682  }
684  return nullptr;
685 }
#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.
Step does not exits.
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
std::string ToString() const
Print this node as string in gimple format.
Step successfully executed.
Definition of the node_info object for the basic_block graph.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
tree_nodeRef op1
The second operand of the binary expression.
Definition: tree_node.hpp:3024
This struct specifies the statement_list node.
Definition: tree_node.hpp:4662
Definition of the class representing a generic C application.
refcount< tree_manipulation > tree_manipulationRef
static bool IsArrayEquivType(const tree_nodeConstRef &type)
Return true if treenode is an array or it is equivalent to an array (record recursively having a sing...
std::string GetName() const override
Return the name of this design step.
Step successfully executed but without any IR change.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
ScheduleRef schedule
The scheduling solution.
Definition: CSE.hpp:93
#define D_SELECTOR
Selectors used only in basic block graphs; numbers continue from cdfg_edge_info.hpp.
Definition: basic_block.hpp:85
bool has_memory_access(const gimple_assign *ga) const
check if the gimple assignment is a load, store or a memcpy/memset
Definition: CSE.cpp:402
tree_nodeRef op0
The first operand of the binary expression.
Definition: tree_node.hpp:3021
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 Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec)
Definition: CSE.cpp:166
CSE(const ParameterConstRef _parameters, const application_managerRef _AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
Definition: CSE.cpp:94
Data structure describing a basic block at tree level.
tree_nodeRef hash_check(const tree_nodeRef &tn, vertex bb, const statement_list *sl, std::map< vertex, CustomUnorderedMapStable< CSE_tuple_key_type, tree_nodeRef >> &unique_table) const
check if the statement has an equivalent in the unique table
Definition: CSE.cpp:481
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
#define max
Definition: backprop.h:17
std::string ToString(ActorGraphBackend_Type actor_graph_backend_type)
Header include.
const tree_managerRef TM
tree manager
Definition: CSE.hpp:96
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
void UpdateTime(const unsigned int operation_index, bool update_cs=true)
Compute the starting and the ending time of a statement.
Definition: schedule.cpp:337
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.
unsigned map[NUM_VERTICES]
Definition: bfs.c:12
absl::flat_hash_map< T, U, Hash, Eq, Alloc > CustomUnorderedMap
Definition: custom_map.hpp:148
This struct specifies the gimple_assign node (GCC 4.3 tree node).
Definition: tree_node.hpp:3015
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.
Definition: CSE.cpp:106
Data structure used to store the schedule of the operations.
refcount< BBNodeInfo > BBNodeInfoRef
refcount definition of the class
Information associated with the whole basic-block graph.
const unsigned int index
Represent the index read from the raw file and the index-1 of the vector of tree_node associated to t...
Definition: tree_node.hpp:146
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
Definition: graph.hpp:1303
static bool IsVectorType(const tree_nodeConstRef &type)
Return true if the treenode is a vector.
#define GET_CONST_NODE(t)
Definition: tree_node.hpp:347
std::pair< enum kind, std::vector< unsigned int > > CSE_tuple_key_type
define the type of the unique table key
Definition: CSE.hpp:105
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.
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.
DesignFlowStep_Status InternalExec() override
perform CSE analysis
Definition: CSE.cpp:177
const unsigned int function_id
The index of the function to be analyzed.
const application_managerRef AppM
The application manager.
~CSE() override
Destructor.
Class specification of the tree_reindex support class.
static const unsigned int ENTRY_BLOCK_ID
constant identifying the entry basic block
CSE analysis.
Class specification of the basic_block structure.
bool restart_phi_opt
when true PHI_OPT step has to restart
Definition: CSE.hpp:99
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
static tree_nodeConstRef CGetType(const tree_nodeConstRef &node)
Return the treenode of the type of node.
this class is used to manage the command-line or XML options.
Wrapper to call graph.
absl::node_hash_map< T, U, Hash, Eq, Alloc > CustomUnorderedMapStable
Definition: custom_map.hpp:152
static integer_cst_t GetConstValue(const tree_nodeConstRef &tn, bool is_signed=true)
Get value from integer constant.
int debug_level
The debug level.
#define GET_INDEX_CONST_NODE(t)
Definition: tree_node.hpp:363
#define DEBUG_LEVEL_VERBOSE
verbose debugging print is performed.
static bool IsPointerType(const tree_nodeConstRef &type)
Return true if treenode index is a pointer.
#define CFG_SELECTOR
Control flow graph edge selector.
#define B
Definition: generate.c:14
Data structure definition for high-level synthesis flow.
Step is symbolic and it has already been marked.
refcount< BBGraphInfo > BBGraphInfoRef
refcount definition of the class
This class contains the base representation for a generic frontend flow step which works on the whole...
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.
const FunctionBehaviorRef function_behavior
The function behavior of the function to be analyzed.
int sl
Definition: adpcm.c:105
Step not yet executed.
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:51 for PandA-2024.02 by doxygen 1.8.13