PandA-2024.02
dead_code_elimination.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  */
45 
46 #include "application_manager.hpp"
47 #include "behavioral_helper.hpp"
48 #include "call_graph_manager.hpp"
49 #include "custom_map.hpp"
50 #include "custom_set.hpp"
51 #include "dbgPrintHelper.hpp" // for DEBUG_LEVEL_
52 #include "design_flow_graph.hpp"
53 #include "design_flow_manager.hpp"
54 #include "ext_tree_node.hpp"
55 #include "function_behavior.hpp"
56 #include "hls.hpp"
57 #include "hls_function_step.hpp"
58 #include "hls_manager.hpp"
59 #include "math_function.hpp"
60 #include "sdc_scheduling.hpp"
61 #include "string_manipulation.hpp" // for GET_CLASS
62 #include "token_interface.hpp"
63 #include "tree_basic_block.hpp"
64 #include "tree_helper.hpp"
65 #include "tree_manager.hpp"
66 #include "tree_manipulation.hpp"
67 #include "tree_node.hpp"
68 #include "tree_reindex.hpp"
69 #include "var_pp_functor.hpp"
70 
72 #include <fstream>
73 #include <list>
74 #include <queue>
75 #include <string>
76 #include <utility>
77 #include <vector>
78 
80  unsigned int _function_id,
81  const DesignFlowManagerConstRef _design_flow_manager)
82  : FunctionFrontendFlowStep(_AppM, _function_id, DEAD_CODE_ELIMINATION, _design_flow_manager, _parameters),
83  restart_if_opt(false),
84  restart_mwi_opt(false),
85  restart_mem(false)
86 {
87  debug_level = parameters->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
88 }
89 
91 
94 {
96  switch(relationship_type)
97  {
99  {
100  if(!parameters->getOption<int>(OPT_gcc_openmp_simd))
101  {
102  relationships.insert(std::make_pair(BITVALUE_RANGE, SAME_FUNCTION));
103  }
104  relationships.insert(std::make_pair(COMPUTE_IMPLICIT_CALLS, SAME_FUNCTION));
105  relationships.insert(std::make_pair(DEAD_CODE_ELIMINATION, CALLED_FUNCTIONS));
106  relationships.insert(std::make_pair(FIX_STRUCTS_PASSED_BY_VALUE, SAME_FUNCTION));
107  relationships.insert(std::make_pair(FUNCTION_ANALYSIS, WHOLE_APPLICATION));
108  relationships.insert(std::make_pair(PARM_DECL_TAKEN_ADDRESS, SAME_FUNCTION));
109  if(parameters->isOption(OPT_soft_float) && parameters->getOption<bool>(OPT_soft_float))
110  {
111  relationships.insert(std::make_pair(SOFT_FLOAT_CG_EXT, SAME_FUNCTION));
112  }
113  relationships.insert(std::make_pair(USE_COUNTING, SAME_FUNCTION));
114  relationships.insert(std::make_pair(USE_COUNTING, CALLING_FUNCTIONS));
115  relationships.insert(std::make_pair(UN_COMPARISON_LOWERING, SAME_FUNCTION));
116  relationships.insert(std::make_pair(PHI_OPT, SAME_FUNCTION));
117  relationships.insert(std::make_pair(MULTI_WAY_IF, SAME_FUNCTION));
118  relationships.insert(std::make_pair(SHORT_CIRCUIT_TAF, SAME_FUNCTION));
119  relationships.insert(std::make_pair(DETERMINE_MEMORY_ACCESSES, SAME_FUNCTION));
120  break;
121  }
123  {
124  break;
125  }
127  {
129  {
130  if(restart_mem)
131  {
132  relationships.insert(std::make_pair(DETERMINE_MEMORY_ACCESSES, SAME_FUNCTION));
133  }
134  if(restart_if_opt)
135  {
136  relationships.insert(std::make_pair(SHORT_CIRCUIT_TAF, SAME_FUNCTION));
137  relationships.insert(std::make_pair(PHI_OPT, SAME_FUNCTION));
138  }
139  if(restart_mwi_opt)
140  {
141  relationships.insert(std::make_pair(MULTI_WAY_IF, SAME_FUNCTION));
142  relationships.insert(std::make_pair(PHI_OPT, SAME_FUNCTION));
143  }
144  if(!parameters->getOption<int>(OPT_gcc_openmp_simd))
145  {
146  relationships.insert(std::make_pair(BIT_VALUE, SAME_FUNCTION));
147  }
148  }
149  break;
150  }
151  default:
152  {
153  THROW_UNREACHABLE("");
154  }
155  }
156  return relationships;
157 }
158 
160 {
162  {
163  return true;
164  }
165  std::map<unsigned int, bool> cur_writing_memory;
166  std::map<unsigned int, bool> cur_reading_memory;
167  const auto TM = AppM->get_tree_manager();
168  for(const auto i : AppM->CGetCallGraphManager()->get_called_by(function_id))
169  {
170  const auto curr_tn = TM->GetTreeNode(i);
171  const auto fdCalled = GetPointerS<const function_decl>(curr_tn);
172  cur_writing_memory[i] = fdCalled->writing_memory;
173  cur_reading_memory[i] = fdCalled->reading_memory;
174  }
175  return cur_writing_memory != last_writing_memory || cur_reading_memory != last_reading_memory;
176 }
177 
178 void dead_code_elimination::fix_sdc_motion(DesignFlowManagerConstRef design_flow_manager, unsigned int function_id,
179  tree_nodeRef removedStmt)
180 {
181  const auto design_flow_graph = design_flow_manager->CGetDesignFlowGraph();
182  const auto sdc_scheduling_step = design_flow_manager->GetDesignFlowStep(HLSFunctionStep::ComputeSignature(
183  HLSFlowStep_Type::SDC_SCHEDULING, HLSFlowStepSpecializationConstRef(), function_id));
184  if(sdc_scheduling_step)
185  {
186  const auto sdc_scheduling =
187  GetPointer<SDCScheduling>(design_flow_graph->CGetDesignFlowStepInfo(sdc_scheduling_step)->design_flow_step);
188  const auto removed_index = GET_INDEX_CONST_NODE(removedStmt);
189  sdc_scheduling->movements_list.remove_if(
190  [&](const std::vector<unsigned int>& mv) { return mv[0] == removed_index; });
191  }
192 }
193 
195 {
196  return fix_sdc_motion(design_flow_manager.lock(), function_id, removedStmt);
197 }
198 
200 {
201  THROW_ASSERT(op0->get_kind() == tree_reindex_K, "expected a tree_reindex object");
202  THROW_ASSERT(GET_NODE(op0)->get_kind() == ssa_name_K, "expected a ssa_name object");
203  const auto ssa = GetPointerS<ssa_name>(GET_NODE(op0));
204  THROW_ASSERT(ssa->CGetDefStmts().size() == 1, "unexpected condition");
205 
206  if(ssa->CGetNumberUses() != 0)
207  {
208  const auto ssa_type = tree_helper::CGetType(op0);
209  tree_nodeRef val;
210  if(tree_helper::IsRealType(ssa_type))
211  {
212  val = TM->CreateUniqueRealCst(0.l, ssa_type);
213  }
214  else if(tree_helper::IsComplexType(ssa_type) || tree_helper::IsVectorType(ssa_type))
215  {
216  const auto tree_man = tree_manipulationRef(new tree_manipulation(TM, parameters, AppM));
217  const auto utype = tree_man->GetUnsignedIntegerType();
218  const auto zeroVal = TM->CreateUniqueIntegerCst(0LL, utype);
219  std::map<TreeVocabularyTokenTypes_TokenEnum, std::string> ne_schema;
220  ne_schema[TOK(TOK_TYPE)] = STR(ssa_type->index);
221  ne_schema[TOK(TOK_SRCP)] = BUILTIN_SRCP;
222  ne_schema[TOK(TOK_OP)] = STR(zeroVal->index);
223  const auto ne_id = TM->new_tree_node_id();
224  TM->create_tree_node(ne_id, nop_expr_K, ne_schema);
225  val = TM->GetTreeReindex(ne_id);
226  }
227  else
228  {
229  val = TM->CreateUniqueIntegerCst(0LL, ssa_type);
230  }
231  const TreeNodeMap<size_t> StmtUses = ssa->CGetUseStmts();
232  for(const auto& use : StmtUses)
233  {
235  "---replace constant usage before: " + use.first->ToString());
236  TM->ReplaceTreeNode(use.first, op0, val);
238  "---replace constant usage after: " + use.first->ToString());
239  }
240  THROW_ASSERT(ssa->CGetNumberUses() == 0, "unexpected condition");
241  }
242 }
243 
245 {
246  const auto v_ssa = GetPointerS<ssa_name>(GET_NODE(vdef));
247  const auto function_id = GET_INDEX_CONST_NODE(GetPointerS<gimple_node>(GET_NODE(v_ssa->CGetDefStmt()))->scpe);
248  const auto gimple_nop_id = TM->new_tree_node_id();
249  {
250  std::map<TreeVocabularyTokenTypes_TokenEnum, std::string> gimple_nop_schema;
251  gimple_nop_schema[TOK(TOK_SRCP)] = BUILTIN_SRCP;
252  gimple_nop_schema[TOK(TOK_SCPE)] = STR(function_id);
253  TM->create_tree_node(gimple_nop_id, gimple_nop_K, gimple_nop_schema);
254  }
255  const auto nop_stmt = TM->GetTreeReindex(gimple_nop_id);
256  GetPointerS<gimple_node>(GET_NODE(nop_stmt))->vdef = vdef;
257  v_ssa->SetDefStmt(nop_stmt);
258  return nop_stmt;
259 }
260 
262  const blocRef& bb)
263 {
264  const auto gn = GetPointer<gimple_node>(GET_NODE(cur_stmt));
265  THROW_ASSERT(gn, "");
266  const auto nop_stmt_id = TM->new_tree_node_id();
267  {
268  std::map<TreeVocabularyTokenTypes_TokenEnum, std::string> gimple_nop_IR_schema;
269  gimple_nop_IR_schema[TOK(TOK_SRCP)] =
270  gn->include_name + ":" + STR(gn->line_number) + ":" + STR(gn->column_number);
271  gimple_nop_IR_schema[TOK(TOK_SCPE)] = STR(function_id);
272  TM->create_tree_node(nop_stmt_id, gimple_nop_K, gimple_nop_IR_schema);
273  }
274  const auto nop_stmt = TM->GetTreeReindex(nop_stmt_id);
275  const auto new_gn = GetPointerS<gimple_node>(GET_NODE(nop_stmt));
276  if(gn->vdef)
277  {
278  new_gn->vdef = gn->vdef;
279  gn->vdef = nullptr;
280  }
281  if(gn->vuses.size())
282  {
283  new_gn->vuses = gn->vuses;
284  }
285  if(gn->vovers.size())
286  {
287  new_gn->vovers = gn->vovers;
288  }
289  bb->PushBefore(nop_stmt, cur_stmt, AppM);
290  return nop_stmt;
291 }
292 
293 blocRef dead_code_elimination::move2emptyBB(const tree_managerRef& TM, const unsigned int new_bbi,
294  const statement_list* sl, const blocRef& bb_pred,
295  const unsigned int cand_bb_dest, const unsigned int bb_dest_number) const
296 {
297  const auto& bb_succ = sl->list_of_bloc.at(cand_bb_dest);
298  const auto& bb_dest = sl->list_of_bloc.at(bb_dest_number);
299 
301  const auto bb_new = blocRef(new bloc(new_bbi));
303  "---Created BB" + STR(bb_new->number) + " as new successor of BB" + STR(bb_pred->number));
304  // sl->list_of_bloc[bb_new->number] = bb_new;
305 
306  bb_new->loop_id = bb_pred->loop_id;
307  bb_new->SetSSAUsesComputed();
308  bb_new->schedule = bb_pred->schedule;
309 
310  bb_new->list_of_pred.push_back(bb_pred->number);
311  bb_new->list_of_succ.push_back(bb_dest->number);
312  bb_dest->list_of_pred.push_back(bb_new->number);
313  bb_pred->list_of_succ.erase(std::find(bb_pred->list_of_succ.begin(), bb_pred->list_of_succ.end(), bb_succ->number));
314  bb_pred->list_of_succ.push_back(bb_new->number);
315 
316  bb_succ->list_of_pred.erase(std::find(bb_succ->list_of_pred.begin(), bb_succ->list_of_pred.end(), bb_pred->number));
318  for(const auto& phi : bb_succ->CGetPhiList())
319  {
320  const auto gp = GetPointerS<gimple_phi>(GET_NODE(phi));
321  for(const auto& def_edge : gp->CGetDefEdgesList())
322  {
323  if(def_edge.second == bb_pred->number)
324  {
326  "---Removing <" + def_edge.first->ToString() + ", BB" + STR(def_edge.second) + ">");
327  gp->RemoveDefEdge(TM, def_edge);
328  break;
329  }
330  }
331  }
332  for(const auto& phi : bb_dest->CGetPhiList())
333  {
334  const auto gp = GetPointerS<gimple_phi>(GET_NODE(phi));
335  gimple_phi::DefEdgeList new_defedges;
336  for(const auto& def_edge : gp->CGetDefEdgesList())
337  {
338  if(def_edge.second == bb_pred->number)
339  {
340  new_defedges.push_back(gimple_phi::DefEdge(def_edge.first, bb_new->number));
341  }
342  }
343  for(const auto& def_edge : new_defedges)
344  {
346  "---Adding from predecessor <" + def_edge.first->ToString() + ", BB" + STR(def_edge.second) +
347  ">");
348  gp->AddDefEdge(TM, def_edge);
349  }
350  }
351  return bb_new;
352 }
353 
359 {
360  if(parameters->IsParameter("disable-dce") && parameters->GetParameter<unsigned int>("disable-dce") == 1)
361  {
363  }
364  const auto TM = AppM->get_tree_manager();
365  auto fd = GetPointerS<function_decl>(TM->GetTreeNode(function_id));
366  auto sl = GetPointerS<statement_list>(GET_NODE(fd->body));
368  const auto& blocks = sl->list_of_bloc;
369 
370  bool modified = false;
371  bool restart_analysis = false;
372  restart_mem = false;
373  restart_if_opt = false;
374  restart_mwi_opt = false;
375 
376  do
377  {
378  restart_analysis = false;
379  bool do_reachability = false;
380  std::list<blocRef> new_bbs;
381  const auto get_new_bbi = [&]() -> unsigned int {
382  return sl->list_of_bloc.rbegin()->first + 1U + static_cast<unsigned int>(new_bbs.size());
383  };
385  // CustomUnorderedSet<unsigned> vdefvover_map;
386  for(const auto& block : blocks)
387  {
388  const auto& stmt_list = block.second->CGetStmtList();
389  for(const auto& stmt : stmt_list)
390  {
391  const auto gn = GetPointerS<gimple_node>(GET_NODE(stmt));
392  THROW_ASSERT(gn->vovers.empty() || gn->vdef, "unexpected condition");
393  for(const auto& vo : gn->vovers)
394  {
395  vdefvover_map[GET_INDEX_NODE(vo)].insert(GET_INDEX_NODE(gn->vdef));
396  // vdefvover_map.insert(GET_INDEX_NODE(vo));
397  }
398  }
399  }
400  for(const auto& block : blocks)
401  {
402  const auto& bb = block.second;
403  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "-->Analyzing BB" + STR(bb->number));
404  const auto& stmt_list = bb->CGetStmtList();
405  std::list<tree_nodeRef> new_vssa_nop;
406  std::list<tree_nodeRef> stmts_to_be_removed;
407  for(auto stmt = stmt_list.rbegin(); stmt != stmt_list.rend(); stmt++)
408  {
409  if(!AppM->ApplyNewTransformation())
410  {
411  break;
412  }
413  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Analyzing " + (*stmt)->ToString());
415  if(GET_NODE(*stmt)->get_kind() == gimple_assign_K)
416  {
417  const auto ga = GetPointerS<gimple_assign>(GET_NODE(*stmt));
419  if(ga->predicate && GET_NODE(ga->predicate)->get_kind() == integer_cst_K &&
420  tree_helper::GetConstValue(ga->predicate) == 0)
421  {
422  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Dead predicate found");
423  if(ga->vdef)
424  {
425  new_vssa_nop.push_back(kill_vdef(TM, ga->vdef));
426  ga->vdef = nullptr;
427  restart_mem = true;
428  }
429  else if(GET_NODE(ga->op0)->get_kind() == ssa_name_K)
430  {
431  if(ga->vdef || ga->vuses.size() || ga->vovers.size())
432  {
433  restart_mem = true;
434  }
435  kill_uses(TM, ga->op0);
436  }
437  else
438  {
439  THROW_ERROR("unexpected condition");
440  }
441  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Dead code found");
442  stmts_to_be_removed.push_back(*stmt);
443  AppM->RegisterTransformation(GetName(), *stmt);
444  }
445  else
446  {
448  const auto op0 = GET_NODE(ga->op0);
449  const auto op1_type = tree_helper::CGetType(ga->op1);
450  if(op0->get_kind() == ssa_name_K)
451  {
452  const auto ssa = GetPointerS<ssa_name>(op0);
454  if(ssa->CGetNumberUses() == 0 and ssa->CGetDefStmts().size() == 1)
455  {
456  bool is_a_writing_memory_call = false;
457  bool is_a_reading_memory_call = false;
458  if(GET_NODE(ga->op1)->get_kind() == call_expr_K ||
459  GET_NODE(ga->op1)->get_kind() == aggr_init_expr_K)
460  {
461  const auto ce = GetPointerS<call_expr>(GET_NODE(ga->op1));
462  if(GET_NODE(ce->fn)->get_kind() == addr_expr_K)
463  {
464  const auto addr_node = GET_NODE(ce->fn);
465  const auto ae = GetPointerS<const addr_expr>(addr_node);
466  const auto fu_decl_node = GET_CONST_NODE(ae->op);
467  THROW_ASSERT(fu_decl_node->get_kind() == function_decl_K,
468  "node " + STR(fu_decl_node) + " is not function_decl but " +
469  fu_decl_node->get_kind_text());
470  const auto fdCalled = GetPointerS<const function_decl>(fu_decl_node);
471  if(fdCalled->writing_memory || !fdCalled->body)
472  {
473  is_a_writing_memory_call = true;
474  }
475  if(fdCalled->reading_memory)
476  {
477  is_a_reading_memory_call = true;
478  }
479  }
480  else
481  {
482  is_a_writing_memory_call = true;
483  }
484  }
485  if(!is_a_writing_memory_call)
486  {
487  if(ga->vdef)
488  {
489  add_gimple_nop(TM, *stmt, bb);
490  restart_mem = true;
491  }
492  if(is_a_reading_memory_call || ga->vdef || ga->vuses.size() || ga->vovers.size() ||
493  GET_NODE(ga->op1)->get_kind() == addr_expr_K ||
494  GET_NODE(ga->op1)->get_kind() == mem_ref_K)
495  {
496  restart_mem = true;
497  }
498  stmts_to_be_removed.push_back(*stmt);
499  AppM->RegisterTransformation(GetName(), *stmt);
500  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Dead code found");
501  }
502  }
503  else
504  {
506  "---LHS ssa used: " + STR(ssa->CGetNumberUses()) + "-" +
507  STR(ssa->CGetDefStmts().size()));
508  }
509  }
510  else if(op0->get_kind() == mem_ref_K && !ga->artificial && !tree_helper::IsVectorType(op1_type))
511  {
512  const auto mr = GetPointerS<mem_ref>(op0);
513  THROW_ASSERT(GET_NODE(mr->op1)->get_kind() == integer_cst_K, "unexpected condition");
514  const auto type_w = tree_helper::CGetType(ga->op1);
515  const auto written_bw = std::max(8ULL, ceil_pow2(tree_helper::Size(type_w)));
516  if(tree_helper::GetConstValue(mr->op1) == 0)
517  {
518  if(GET_NODE(mr->op0)->get_kind() == integer_cst_K)
519  {
520  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---do nothing with constant values");
521  }
522  else
523  {
524  THROW_ASSERT(GET_NODE(mr->op0)->get_kind() == ssa_name_K,
525  "unexpected condition" + ga->ToString());
526  auto derefVar = GetPointerS<ssa_name>(GET_NODE(mr->op0));
527  auto& defStmts = derefVar->CGetDefStmts();
528  if(defStmts.size() == 1)
529  {
530  auto defStmt = *defStmts.begin();
531  if(GET_NODE(defStmt)->get_kind() == gimple_assign_K)
532  {
533  const auto derefGA = GetPointerS<gimple_assign>(GET_NODE(defStmt));
534  if(GET_NODE(derefGA->op1)->get_kind() == addr_expr_K)
535  {
536  const auto addressedVar = GetPointerS<addr_expr>(GET_NODE(derefGA->op1))->op;
537  if(GET_NODE(addressedVar)->get_kind() == var_decl_K)
538  {
539  const auto varDecl = GetPointerS<var_decl>(GET_NODE(addressedVar));
540  if(varDecl->scpe && function_id == GET_INDEX_NODE(varDecl->scpe) &&
541  !varDecl->static_flag)
542  {
543  ssa_name* ssaDef = nullptr;
544  if(ga->vdef)
545  {
546  ssaDef = GetPointerS<ssa_name>(GET_NODE(ga->vdef));
548  "---VDEF: " + STR(ga->vdef));
549  }
550  else
551  {
552  THROW_ERROR("unexpected condition");
553  }
554  THROW_ASSERT(ssaDef, "unexpected condition");
556  if(ssaDef->CGetDefStmts().size() == 1)
557  {
558  if(ssaDef->CGetNumberUses() == 0 &&
559  vdefvover_map.find(ssaDef->index) == vdefvover_map.end())
560  {
562  "---Dead Store found");
563  if(ga->vdef)
564  {
565  add_gimple_nop(TM, *stmt, bb);
566  }
567  stmts_to_be_removed.push_back(*stmt);
568  AppM->RegisterTransformation(GetName(), *stmt);
569  restart_mem = true;
570  }
571  else
572  {
574  "---check if the associated load are dead");
575  const TreeNodeMap<size_t> StmtUses = ssaDef->CGetUseStmts();
576  for(const auto& use : StmtUses)
577  {
578  const auto gn_used = GetPointerS<gimple_node>(GET_NODE(use.first));
579  if(!gn_used->vdef && gn_used->bb_index == ga->bb_index &&
580  gn_used->get_kind() == gimple_assign_K)
581  {
582  const auto ga_used =
583  GetPointerS<gimple_assign>(GET_NODE(use.first));
584  if(GET_NODE(ga_used->op0)->get_kind() == ssa_name_K &&
585  GET_NODE(ga_used->op1)->get_kind() == mem_ref_K &&
586  !(ga_used->predicate &&
587  GET_NODE(ga_used->predicate)->get_kind() == integer_cst_K &&
588  tree_helper::GetConstValue(ga_used->predicate) == 0))
589  {
590  const auto mr_used =
591  GetPointerS<mem_ref>(GET_NODE(ga_used->op1));
592  if(tree_helper::GetConstValue(mr->op1) ==
593  tree_helper::GetConstValue(mr_used->op1))
594  {
595  const auto type_r = tree_helper::CGetType(ga_used->op0);
596  const auto read_bw =
597  std::max(8ULL, ceil_pow2(tree_helper::Size(type_r)));
599  "---read_bw: " + STR(read_bw) +
600  " written_bw: " + STR(written_bw));
601  if(GET_INDEX_NODE(mr->op0) ==
602  GET_INDEX_NODE(mr_used->op0) &&
603  written_bw == read_bw &&
605  type_r,
606  type_w))
607  {
612  "---found a candidate " +
613  GET_NODE(use.first)->ToString());
615  auto curr_stmt = stmt;
616  bool found_load = false;
617  if(curr_stmt != stmt_list.rbegin())
618  {
619  --curr_stmt;
620  while(true)
621  {
622  if(GET_INDEX_NODE(*curr_stmt) ==
623  GET_INDEX_NODE(use.first))
624  {
625  found_load = true;
626  break;
627  }
628  const auto gn_curr =
629  GetPointerS<gimple_node>(GET_NODE(*curr_stmt));
630  if(!found_load && gn_curr->vdef &&
631  (ga_used->vuses.find(gn_curr->vdef) !=
632  ga_used->vuses.end() ||
633  (vdefvover_map.find(ssaDef->index) !=
634  vdefvover_map.end() &&
635  vdefvover_map.find(ssaDef->index)
636  ->second.find(
637  GET_INDEX_NODE(gn_curr->vdef)) !=
638  vdefvover_map.find(ssaDef->index)
639  ->second.end())))
640  {
641  break;
642  }
643  if(curr_stmt == stmt_list.rbegin())
644  {
645  break;
646  }
647  else
648  {
649  --curr_stmt;
650  }
651  }
652  }
653  if(found_load)
654  {
656  "---found a Dead Load " +
657  GET_NODE(*curr_stmt)->ToString());
658  const auto ssa_used_op0 =
659  GetPointerS<ssa_name>(GET_NODE(ga_used->op0));
660  const TreeNodeMap<size_t> StmtUsesOp0 =
661  ssa_used_op0->CGetUseStmts();
662  for(const auto& useop0 : StmtUsesOp0)
663  {
665  debug_level,
666  "---replace var usage before: " +
667  useop0.first->ToString());
668  TM->ReplaceTreeNode(useop0.first, ga_used->op0,
669  ga->op1);
671  debug_level,
672  "---replace var usage after: " +
673  useop0.first->ToString());
674  }
675  THROW_ASSERT(ssa_used_op0->CGetNumberUses() == 0,
676  "unexpected condition");
677  stmts_to_be_removed.push_back(*curr_stmt);
678  AppM->RegisterTransformation(GetName(), *curr_stmt);
679  restart_mem = true;
680  }
681  }
682  }
683  }
684  }
685  }
686  }
687  }
688  else
689  {
691  "---local variable later used");
692  }
693  }
694  else
695  {
697  "---non local variable");
698  }
699  }
700  else
701  {
703  }
704  }
705  else
706  {
707  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---not supported pattern1");
708  }
709  }
710  else
711  {
712  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---not supported pattern2");
713  }
714  }
715  else
716  {
717  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---not supported pattern3");
718  }
719  }
720  }
721  else
722  {
723  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---non-null offset in the mem_ref");
724  }
725  }
726  else
727  {
729  }
730  }
731  }
732  else if(GET_NODE(*stmt)->get_kind() == gimple_cond_K)
733  {
734  const auto gc = GetPointerS<gimple_cond>(GET_NODE(*stmt));
735  if(GET_NODE(gc->op0)->get_kind() == integer_cst_K)
736  {
737  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---gimple_cond with a constant condition");
738  do_reachability = true;
739  restart_if_opt = true;
740  if(tree_helper::GetConstValue(gc->op0))
741  {
742  const auto new_bb = move2emptyBB(TM, get_new_bbi(), sl, bb, bb->false_edge, bb->true_edge);
743  new_bbs.push_back(new_bb);
744  bb->false_edge = new_bb->number;
745  }
746  else
747  {
748  const auto new_bb = move2emptyBB(TM, get_new_bbi(), sl, bb, bb->true_edge, bb->false_edge);
749  new_bbs.push_back(new_bb);
750  bb->true_edge = new_bb->number;
751  }
752  }
753  }
754  else if(GET_NODE(*stmt)->get_kind() == gimple_multi_way_if_K)
755  {
756  const auto gm = GetPointerS<gimple_multi_way_if>(GET_NODE(*stmt));
757 
758  bool one_is_const = false;
759  bool all_false = true;
760  unsigned int bb_dest = 0;
761  for(const auto& cond : gm->list_of_cond)
762  {
763  if(!cond.first)
764  {
765  if(all_false)
766  {
767  THROW_ASSERT(!one_is_const, "only one can be true");
768  bb_dest = cond.second;
769  }
770  }
771  else if(GET_NODE(cond.first)->get_kind() == integer_cst_K)
772  {
773  if(tree_helper::GetConstValue(cond.first))
774  {
775  all_false = false;
776  THROW_ASSERT(!one_is_const, "only one can be true");
777  one_is_const = true;
778  bb_dest = cond.second;
779  }
780  }
781  else
782  {
783  all_false = false;
784  }
785  }
786  if(all_false || one_is_const)
787  {
789  "---gimple_multi_way_if with constant conditions");
790  restart_mwi_opt = true;
791  for(auto& cond : gm->list_of_cond)
792  {
793  if(cond.second != bb_dest)
794  {
795  do_reachability = true;
796  const auto new_bb = move2emptyBB(TM, get_new_bbi(), sl, bb, cond.second, bb_dest);
797  new_bbs.push_back(new_bb);
798  cond.second = new_bb->number;
799  }
800  }
801  }
802  else
803  {
805  std::map<unsigned int, unsigned int> condIndex2BBdest;
806  auto do0ConstantCondRemoval = false;
807  for(auto& cond : gm->list_of_cond)
808  {
809  if(cond.first)
810  {
811  if(GET_NODE(cond.first)->get_kind() == integer_cst_K)
812  {
813  if(!blocks.at(cond.second)->CGetStmtList().empty())
814  {
815  do0ConstantCondRemoval = true;
816  }
817  }
818  else if(condIndex2BBdest.find(GET_INDEX_NODE(cond.first)) == condIndex2BBdest.end())
819  {
820  condIndex2BBdest[GET_INDEX_NODE(cond.first)] = cond.second;
821  }
822  else if(!blocks.at(cond.second)->CGetStmtList().empty())
823  {
824  do_reachability = true;
826  "---gimple_multi_way_if duplicated condition from BB" + STR(bb->number) +
827  " to BB" + STR(cond.second));
828  const auto new_bb = move2emptyBB(TM, get_new_bbi(), sl, bb, cond.second,
829  condIndex2BBdest.at(GET_INDEX_NODE(cond.first)));
830  new_bbs.push_back(new_bb);
831  cond.second = new_bb->number;
832  }
833  }
834  }
835  if(do0ConstantCondRemoval)
836  {
838  "---gimple_multi_way_if do zero condition removal");
839  const auto bb0_dest = condIndex2BBdest.begin()->second;
840  for(auto& cond : gm->list_of_cond)
841  {
842  if(cond.first)
843  {
844  if(GET_NODE(cond.first)->get_kind() == integer_cst_K)
845  {
846  THROW_ASSERT(tree_helper::GetConstValue(cond.first) == 0, "unexpected condition");
847  do_reachability = true;
849  "---gimple_multi_way_if duplicated condition from BB" + STR(bb->number) +
850  " to BB" + STR(cond.second));
851  const auto new_bb = move2emptyBB(TM, get_new_bbi(), sl, bb, cond.second, bb0_dest);
852  new_bbs.push_back(new_bb);
853  cond.second = new_bb->number;
854  }
855  }
856  }
857  }
858  }
859  }
860  else if(GET_NODE(*stmt)->get_kind() == gimple_call_K)
861  {
862  const auto gc = GetPointerS<gimple_call>(GET_NODE(*stmt));
863  auto temp_node = GET_NODE(gc->fn);
864  function_decl* fdCalled = nullptr;
865 
866  if(temp_node->get_kind() == addr_expr_K)
867  {
868  const auto ue = GetPointerS<unary_expr>(temp_node);
869  temp_node = ue->op;
870  fdCalled = GetPointer<function_decl>(GET_NODE(temp_node));
871  }
872  else if(temp_node->get_kind() == obj_type_ref_K)
873  {
874  temp_node = tree_helper::find_obj_type_ref_function(gc->fn);
875  fdCalled = GetPointer<function_decl>(GET_NODE(temp_node));
876  }
877  if(fdCalled)
878  {
879  bool is_a_writing_memory_call = false;
880  if(fdCalled->writing_memory or !fdCalled->body)
881  {
882  is_a_writing_memory_call = true;
883  }
884  if(tree_helper::is_a_nop_function_decl(fdCalled) || !is_a_writing_memory_call)
885  {
886  if(gc->vdef || gc->vuses.size() || gc->vovers.size())
887  {
888  restart_mem = true;
889  }
890  add_gimple_nop(TM, *stmt, bb);
891  stmts_to_be_removed.push_back(*stmt);
892  AppM->RegisterTransformation(GetName(), *stmt);
893  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Dead code found");
894  }
895  }
896  }
897  else
898  {
899  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Not gimple_assign statement");
900  }
901  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Analyzed statement");
902  }
903  if(!stmts_to_be_removed.empty())
904  {
905  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Restart dead code");
906  modified = true;
907  restart_analysis = true;
909  "-->Removing " + STR(stmts_to_be_removed.size()) + " dead statements");
910  for(const auto& curr_el : stmts_to_be_removed)
911  {
912  bb->RemoveStmt(curr_el, AppM);
913  fix_sdc_motion(curr_el);
914  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Removed " + curr_el->ToString());
915  }
916  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Removed dead statements");
917  for(const auto& vssa_nop : new_vssa_nop)
918  {
919  bb->PushFront(vssa_nop, AppM);
920  }
921  if(bb->CGetStmtList().empty() && bb->CGetPhiList().empty())
922  {
923  restart_if_opt = true;
924  restart_mwi_opt = true;
925  }
926  }
927  /*
928  * check also phi operations. if a phi assigns an ssa which is not used
929  * anymore, the phi can be removed
930  */
931  const auto& phi_list = bb->CGetPhiList();
932  std::list<tree_nodeRef> phis_to_be_removed;
934  for(auto phi = phi_list.rbegin(); phi != phi_list.rend(); phi++)
935  {
936  if(!AppM->ApplyNewTransformation())
937  {
938  break;
939  }
940 
941  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Analyzing " + (*phi)->ToString());
942  THROW_ASSERT(GET_NODE(*phi)->get_kind() == gimple_phi_K,
943  GET_NODE(*phi)->ToString() + " is of kind " +
944  tree_node::GetString(GET_NODE(*phi)->get_kind()));
945  const auto gphi = GetPointerS<gimple_phi>(GET_NODE(*phi));
946  const auto res = GET_NODE(gphi->res);
947  THROW_ASSERT(res->get_kind() == ssa_name_K,
948  res->ToString() + " is of kind " + tree_node::GetString(res->get_kind()));
949  const auto ssa = GetPointerS<ssa_name>(res);
950  // very strict condition for the elimination
951  if(ssa->CGetNumberUses() == 0 && ssa->CGetDefStmts().size() == 1)
952  {
953  THROW_ASSERT(ssa->CGetUseStmts().empty(), "");
954  phis_to_be_removed.push_back(*phi);
955  AppM->RegisterTransformation(GetName(), *phi);
956  }
958  }
960  if(!phis_to_be_removed.empty())
961  {
962  modified = true;
963  restart_analysis = true;
965  "-->Removing " + STR(phis_to_be_removed.size()) + " dead phis");
966  for(const auto& curr_phi : phis_to_be_removed)
967  {
968  bb->RemovePhi(curr_phi);
969  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Removed " + curr_phi->ToString());
970  }
971  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Removed dead phis");
972  }
973  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "<--Analyzed BB" + STR(bb->number));
974  }
975  for(const auto& bb : new_bbs)
976  {
977  sl->list_of_bloc[bb->number] = bb;
978  }
979  new_bbs.clear();
980  while(do_reachability)
981  {
983  do_reachability = false;
984  CustomOrderedSet<unsigned> bb_to_remove;
985  CustomOrderedSet<unsigned> BB_reached;
986  BB_reached.insert(bloc::ENTRY_BLOCK_ID);
987  std::queue<unsigned> to_be_processed;
988  to_be_processed.push(bloc::ENTRY_BLOCK_ID);
989  while(!to_be_processed.empty())
990  {
991  auto curr = to_be_processed.front();
992  to_be_processed.pop();
993  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "---Analyzing BB" + STR(curr));
994  for(auto bb : blocks.at(curr)->list_of_succ)
995  {
996  if(BB_reached.insert(bb).second)
997  {
998  to_be_processed.push(bb);
999  }
1000  }
1001  }
1002  BB_reached.insert(bloc::EXIT_BLOCK_ID);
1003  for(const auto& bb_pair : blocks)
1004  {
1005  if(BB_reached.find(bb_pair.first) == BB_reached.end())
1006  {
1007  bb_to_remove.insert(bb_pair.first);
1008  }
1009  }
1010  if(!bb_to_remove.empty())
1011  {
1013  "-->Removing " + STR(bb_to_remove.size()) + " unreachable BBs");
1014  for(auto bbi : bb_to_remove)
1015  {
1016  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Removing BB" + STR(bbi));
1017  do_reachability = true;
1018  const auto& bb = blocks.at(bbi);
1019  const auto phi_list = bb->CGetPhiList();
1020  std::list<tree_nodeRef> phis_to_be_removed;
1022  for(auto phi = phi_list.rbegin(); phi != phi_list.rend(); phi++)
1023  {
1024  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Removing " + (*phi)->ToString());
1025  THROW_ASSERT(GET_NODE(*phi)->get_kind() == gimple_phi_K,
1026  GET_NODE(*phi)->ToString() + " is of kind " + GET_NODE(*phi)->get_kind_text());
1027  const auto gphi = GetPointerS<gimple_phi>(GET_NODE(*phi));
1028  const auto res = GET_NODE(gphi->res);
1029  THROW_ASSERT(res->get_kind() == ssa_name_K, res->ToString() + " is of kind " + res->get_kind_text());
1030  const auto ssa = GetPointerS<const ssa_name>(res);
1031  if(ssa->virtual_flag)
1032  {
1033  kill_vdef(TM, gphi->res);
1034  }
1035  else
1036  {
1037  kill_uses(TM, gphi->res);
1038  }
1039  bb->RemovePhi(*phi);
1040  }
1042  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Removing statements");
1043  const auto stmt_list = bb->CGetStmtList();
1044  for(auto stmt = stmt_list.rbegin(); stmt != stmt_list.rend(); stmt++)
1045  {
1046  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Removing " + (*stmt)->ToString());
1047  const auto node_stmt = GET_NODE(*stmt);
1048  const auto gn = GetPointerS<gimple_node>(node_stmt);
1049  if(gn->vdef)
1050  {
1051  kill_vdef(TM, gn->vdef);
1052  gn->vdef = nullptr;
1053  }
1054  else if(node_stmt->get_kind() == gimple_assign_K)
1055  {
1056  const auto ga = GetPointerS<gimple_assign>(node_stmt);
1057  if(GET_NODE(ga->op0)->get_kind() == ssa_name_K)
1058  {
1059  kill_uses(TM, ga->op0);
1060  }
1061  }
1062  bb->RemoveStmt(*stmt, AppM);
1063  fix_sdc_motion(*stmt);
1064  }
1065  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Removed statements");
1066  if(bb->CGetStmtList().empty() && bb->CGetPhiList().empty())
1067  {
1068  restart_if_opt = true;
1069  restart_mwi_opt = true;
1070  }
1071  for(const auto sblock : bb->list_of_succ)
1072  {
1073  if(sblock == bloc::EXIT_BLOCK_ID)
1074  {
1075  continue;
1076  }
1077  THROW_ASSERT(blocks.find(sblock) != blocks.end(), "Already removed BB" + STR(sblock));
1078  const auto& succ_block = blocks.at(sblock);
1079  succ_block->list_of_pred.erase(
1080  std::find(succ_block->list_of_pred.begin(), succ_block->list_of_pred.end(), bb->number));
1082  for(const auto& phi : succ_block->CGetPhiList())
1083  {
1084  const auto gp = GetPointerS<gimple_phi>(GET_NODE(phi));
1085  for(const auto& def_edge : gp->CGetDefEdgesList())
1086  {
1087  if(def_edge.second == bb->number)
1088  {
1090  "---Removing <" + def_edge.first->ToString() + ", BB" + STR(def_edge.second) +
1091  ">");
1092  gp->RemoveDefEdge(TM, def_edge);
1093  break;
1094  }
1095  }
1096  }
1097  }
1098  bb->list_of_succ.clear();
1100  }
1101  for(const auto bbi : bb_to_remove)
1102  {
1103  sl->list_of_bloc.erase(bbi);
1104  }
1105  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Removed unreachable BBs");
1106  }
1107  }
1108  } while(restart_analysis);
1109 
1111  for(const auto& block : blocks)
1112  {
1113  const auto& bb = block.second;
1114  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "-->Analyzing BB" + STR(bb->number));
1115  const auto& stmt_list = bb->CGetStmtList();
1116  std::list<tree_nodeRef> new_vssa_nop;
1117  for(auto stmt = stmt_list.rbegin(); stmt != stmt_list.rend(); stmt++)
1118  {
1119  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Analyzing " + (*stmt)->ToString());
1120  const auto stmt_kind = GET_NODE(*stmt)->get_kind();
1121  const function_decl* fdCalled = nullptr;
1122  if(stmt_kind == gimple_assign_K)
1123  {
1124  const auto ga = GetPointerS<const gimple_assign>(GET_CONST_NODE(*stmt));
1125  const auto rhs_kind = GET_CONST_NODE(ga->op1)->get_kind();
1126  if(rhs_kind == call_expr_K || rhs_kind == aggr_init_expr_K)
1127  {
1128  const auto ce = GetPointerS<const call_expr>(GET_CONST_NODE(ga->op1));
1129  if(GET_CONST_NODE(ce->fn)->get_kind() == addr_expr_K)
1130  {
1131  const auto addr_node = GET_CONST_NODE(ce->fn);
1132  const auto ae = GetPointerS<const addr_expr>(addr_node);
1133  const auto fu_decl_node = GET_CONST_NODE(ae->op);
1134  THROW_ASSERT(fu_decl_node->get_kind() == function_decl_K, "node " + STR(fu_decl_node) +
1135  " is not function_decl but " +
1136  fu_decl_node->get_kind_text());
1137  fdCalled = GetPointer<const function_decl>(fu_decl_node);
1138  }
1139  }
1140  }
1141  else if(stmt_kind == gimple_call_K)
1142  {
1143  const auto gc = GetPointerS<const gimple_call>(GET_CONST_NODE(*stmt));
1144  const auto op_kind = GET_CONST_NODE(gc->fn)->get_kind();
1145  if(op_kind == addr_expr_K)
1146  {
1147  const auto ue = GetPointerS<const unary_expr>(GET_CONST_NODE(gc->fn));
1148  fdCalled = GetPointer<const function_decl>(GET_CONST_NODE(ue->op));
1149  }
1150  else if(op_kind == obj_type_ref_K)
1151  {
1152  const auto obj_ref = tree_helper::find_obj_type_ref_function(gc->fn);
1153  fdCalled = GetPointer<const function_decl>(GET_CONST_NODE(obj_ref));
1154  }
1155  }
1156  if(fdCalled)
1157  {
1158  const auto gn = GetPointerS<gimple_node>(GET_NODE(*stmt));
1159  if(!fdCalled->writing_memory && fdCalled->body)
1160  {
1161  if(gn->vdef)
1162  {
1163  if(fdCalled->reading_memory)
1164  {
1166  for(const auto& vo : gn->vovers)
1167  {
1168  if(!gn->vdef || (GET_INDEX_NODE(vo) != GET_INDEX_NODE(gn->vdef)))
1169  {
1170  if(gn->AddVuse(vo))
1171  {
1172  THROW_ASSERT(GET_NODE(vo)->get_kind() == ssa_name_K, "");
1173  GetPointerS<ssa_name>(GET_NODE(vo))->AddUseStmt(*stmt);
1174  }
1175  }
1176  }
1177  }
1179  new_vssa_nop.push_back(kill_vdef(TM, gn->vdef));
1180  gn->vdef = nullptr;
1181  for(const auto& vo : gn->vovers)
1182  {
1183  THROW_ASSERT(GET_NODE(vo)->get_kind() == ssa_name_K, "");
1184  GetPointerS<ssa_name>(GET_NODE(vo))->RemoveUse(*stmt);
1185  }
1186  gn->vovers.clear();
1187  restart_mem = true;
1189  "---Nothing is written by this function: Fixed VDEF/VOVER ");
1190  }
1191  }
1192  }
1193  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Analyzed statement");
1194  }
1195  for(const auto& vssa_nop : new_vssa_nop)
1196  {
1197  bb->PushFront(vssa_nop, AppM);
1198  }
1199  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "<--Analyzed BB" + STR(bb->number));
1200  }
1201 
1203  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "---Update memory read/write flag");
1204  fd->writing_memory = false;
1205  fd->reading_memory = false;
1206  for(const auto& block : blocks)
1207  {
1208  const auto& bb = block.second;
1209  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "-->Analyzing BB" + STR(bb->number));
1210  const auto& stmt_list = bb->CGetStmtList();
1211  for(auto stmt = stmt_list.rbegin(); stmt != stmt_list.rend(); stmt++)
1212  {
1213  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Analyzing " + (*stmt)->ToString());
1214  const auto gn = GetPointerS<const gimple_node>(GET_CONST_NODE(*stmt));
1215 
1216  if(!gn->vuses.empty() && GET_CONST_NODE(*stmt)->get_kind() != gimple_return_K)
1217  {
1218  fd->reading_memory = true;
1219  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "--- reading_memory (1)");
1220  }
1221  if(gn->vdef)
1222  {
1223  fd->writing_memory = true;
1224  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "--- writing_memory (3)");
1225  }
1226  else if(const auto ga = GetPointer<const gimple_assign>(GET_CONST_NODE(*stmt)))
1227  {
1228  if(GET_CONST_NODE(ga->op1)->get_kind() == call_expr_K ||
1229  GET_CONST_NODE(ga->op1)->get_kind() == aggr_init_expr_K)
1230  {
1231  const auto ce = GetPointerS<const call_expr>(GET_CONST_NODE(ga->op1));
1232  if(GET_CONST_NODE(ce->fn)->get_kind() == addr_expr_K)
1233  {
1234  const auto addr_node = GET_CONST_NODE(ce->fn);
1235  const auto ae = GetPointerS<const addr_expr>(addr_node);
1236  const auto fu_decl_node = GET_CONST_NODE(ae->op);
1237  THROW_ASSERT(fu_decl_node->get_kind() == function_decl_K, "node " + STR(fu_decl_node) +
1238  " is not function_decl but " +
1239  fu_decl_node->get_kind_text());
1240  const auto fdCalled = GetPointerS<const function_decl>(fu_decl_node);
1241  if(fdCalled->writing_memory || !fdCalled->body || fdCalled->undefined_flag)
1242  {
1243  fd->writing_memory = true;
1244  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "--- writing_memory (5)");
1245  }
1246  if(fdCalled->reading_memory || !fdCalled->body || fdCalled->undefined_flag)
1247  {
1248  fd->reading_memory = true;
1249  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "--- reading_memory (6)");
1250  }
1251  }
1252  else
1253  {
1254  fd->writing_memory = true;
1255  fd->reading_memory = true;
1256  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "--- reading_memory+writing_memory (7)");
1257  }
1258  }
1259  }
1260  else if(const auto gc = GetPointer<const gimple_call>(GET_CONST_NODE(*stmt)))
1261  {
1262  const function_decl* fdCalled = nullptr;
1263  if(GET_CONST_NODE(gc->fn)->get_kind() == addr_expr_K)
1264  {
1265  const auto ue = GetPointerS<const unary_expr>(GET_CONST_NODE(gc->fn));
1266  fdCalled = GetPointer<const function_decl>(GET_CONST_NODE(ue->op));
1267  }
1268  else if(GET_CONST_NODE(gc->fn)->get_kind() == obj_type_ref_K)
1269  {
1270  const auto obj_ref = tree_helper::find_obj_type_ref_function(gc->fn);
1271  fdCalled = GetPointerS<const function_decl>(GET_CONST_NODE(gc->fn));
1272  }
1273  if(fdCalled)
1274  {
1275  if(fdCalled->writing_memory || !fdCalled->body || fdCalled->undefined_flag)
1276  {
1277  fd->writing_memory = true;
1278  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "--- writing_memory (8)");
1279  }
1280  if(fdCalled->reading_memory || !fdCalled->body || fdCalled->undefined_flag)
1281  {
1282  fd->reading_memory = true;
1283  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "--- reading_memory (9)");
1284  }
1285  }
1286  else
1287  {
1288  fd->writing_memory = true;
1289  fd->reading_memory = true;
1290  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "--- reading_memory+writing_memory (10)");
1291  }
1292  }
1293  else if(GetPointer<const gimple_asm>(GET_CONST_NODE(*stmt)))
1294  {
1295  fd->writing_memory = true;
1296  fd->reading_memory = true;
1297  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "--- reading_memory+writing_memory (11)");
1298  }
1299  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Analyzed statement");
1300  }
1301  INDENT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "<--Analyzed BB" + STR(bb->number));
1302  }
1304  "---write flag " + (fd->writing_memory ? std::string("T") : std::string("F")));
1306  "---read flag " + (fd->reading_memory ? std::string("T") : std::string("F")));
1307 
1308  const auto calledSet = AppM->CGetCallGraphManager()->get_called_by(function_id);
1309  for(const auto i : calledSet)
1310  {
1311  const auto fdCalled = GetPointerS<const function_decl>(AppM->get_tree_manager()->CGetTreeNode(i));
1312  last_writing_memory[i] = fdCalled->writing_memory;
1313  last_reading_memory[i] = fdCalled->reading_memory;
1314  }
1315 
1316  if(restart_mem || modified || restart_if_opt || restart_mwi_opt)
1317  {
1318  function_behavior->UpdateBBVersion();
1320  }
1321  else
1322  {
1324  }
1325 }
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:343
static bool IsSameType(const tree_nodeConstRef &tn0, const tree_nodeConstRef &tn1)
Given two nodes tells if they have same base type (const is not considered: const double == double) ...
const TreeNodeSet CGetDefStmts() const
Return the set of definition statements.
Definition: tree_node.cpp:1274
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
static bool IsComplexType(const tree_nodeConstRef &type)
Return if treenode is a complex.
const TreeNodeMap< size_t > & CGetUseStmts() const
Return the use stmts.
Definition: tree_node.cpp:1343
static bool is_a_nop_function_decl(const function_decl *fd)
Data structure representing the entire HLS information.
This struct specifies the field bloc (basic block).
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
File containing functions and utilities to support the printing of debug messagges.
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
Step successfully executed.
bool writing_memory
True if function write in memory somehow.
Definition: tree_node.hpp:2780
#define GET_CLASS(obj)
Macro returning the actual type of an object.
void ReplaceTreeNode(const tree_nodeRef &stmt, const tree_nodeRef &old_node, const tree_nodeRef &new_node)
Replace the occurrences of tree node old_node with new_node in statement identified by tn...
This struct specifies the statement_list node.
Definition: tree_node.hpp:4662
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 of the class representing a generic C application.
refcount< tree_manipulation > tree_manipulationRef
std::string GetName() const override
Return the name of this design step.
RelationshipType
The relationship type.
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
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
static std::string GetString(const enum kind k)
Given a kind, return the corresponding string.
Definition: tree_node.cpp:120
tree_nodeRef add_gimple_nop(const tree_managerRef &TM, const tree_nodeRef &cur_stmt, const blocRef &bb)
std::list< DefEdge > DefEdgeList
The type of the def edge list.
Definition: tree_node.hpp:3753
bool undefined_flag
undefined_flag means external reference: do not allocate storage, and refer to a definition elsewhere...
Definition: tree_node.hpp:2848
void fix_sdc_motion(tree_nodeRef removedStmt) const
A simple interface to token object of the raw files.
std::map< unsigned int, blocRef > list_of_bloc
list_of_bloc field is the list of basic block. If this field is null then the list_of_stmt field is n...
Definition: tree_node.hpp:4673
static const unsigned int EXIT_BLOCK_ID
constant identifying the exit basic block
blocRef move2emptyBB(const tree_managerRef &TM, const unsigned int new_bbi, const statement_list *sl, const blocRef &bb_pred, const unsigned int cand_bb_dest, const unsigned int bb_dest) const
#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
~dead_code_elimination() override
Destructor.
Data structure describing a basic block at tree level.
static std::string ComputeSignature(const HLSFlowStep_Type hls_flow_step_type, const HLSFlowStepSpecializationConstRef hls_flow_step_specialization, const unsigned int function_id)
Compute the signature of a hls flow step.
dead_code_elimination(const ParameterConstRef _parameters, const application_managerRef AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
redefinition of map to manage ordered/unordered structures
#define TOK(token)
Macro used to convert a token symbol into a treeVocabularyTokenTypes.
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 HasToBeExecuted() const override
Check if this step has actually to be executed.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
static unsigned long long Size(const tree_nodeConstRef &tn)
Return the size of a tree object.
absl::flat_hash_map< T, U, Hash, Eq, Alloc > CustomUnorderedMap
Definition: custom_map.hpp:148
size_t CGetNumberUses() const
Return the number of uses.
Definition: tree_node.cpp:1348
void kill_uses(const tree_managerRef &TM, const tree_nodeRef &op0) const
unsigned int new_tree_node_id(const unsigned int ask=0)
Return a new node id in the intermediate representation.
tree_nodeRef CreateUniqueRealCst(long double value, const tree_nodeConstRef &type)
memoization of integer constants
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
void create_tree_node(const unsigned int node_id, enum kind tree_node_type, std::map< TreeVocabularyTokenTypes_TokenEnum, std::string > &tree_node_schema)
Factory method.
Classes to describe design flow graph.
tree_nodeRef body
body field is the saved representation of the body of the entire function.
Definition: tree_node.hpp:2870
tree_nodeRef CreateUniqueIntegerCst(integer_cst_t value, const tree_nodeConstRef &type)
memoization of integer constants
std::pair< tree_nodeRef, unsigned int > DefEdge
The type of the def edge.
Definition: tree_node.hpp:3750
redefinition of set to manage ordered/unordered structures
tree_nodeRef GetTreeReindex(const unsigned int i)
Return a tree_reindex wrapping the i-th tree_node.
const Wrefcount< const DesignFlowManager > design_flow_manager
The design flow manager.
static bool IsVectorType(const tree_nodeConstRef &type)
Return true if the treenode is a vector.
Class definition of the sdc scheduling.
bool reading_memory
True if function read from memory somehow.
Definition: tree_node.hpp:2783
#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.
Eliminate dead code.
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.
static tree_nodeRef kill_vdef(const tree_managerRef &TM, const tree_nodeRef &vdef)
Replace virtual ssa definition with gimple nop.
This struct specifies the block node.
Definition: tree_node.hpp:1820
This file collects some utility functions.
static tree_nodeRef find_obj_type_ref_function(const tree_nodeConstRef &tn)
Given the tree_node of an obj_type_ref return the tree_node of the called function.
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.
Class specification of the tree_reindex support class.
static const unsigned int ENTRY_BLOCK_ID
constant identifying the entry basic block
std::map< unsigned int, bool > last_writing_memory
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.
std::map< unsigned int, bool > last_reading_memory
Classes specification of the tree_node data structures not present in the gcc.
This struct specifies the ssa_name node.
Definition: tree_node.hpp:4523
Wrapper to call graph.
static integer_cst_t GetConstValue(const tree_nodeConstRef &tn, bool is_signed=true)
Get value from integer constant.
int debug_level
The debug level.
refcount< const HLSFlowStepSpecialization > HLSFlowStepSpecializationConstRef
const refcount definition of the class
Definition: hls_step.hpp:93
#define GET_INDEX_CONST_NODE(t)
Definition: tree_node.hpp:363
Data structure definition for high-level synthesis flow.
DesignFlowStep_Status InternalExec() override
Performs dead code elimination.
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 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