PandA-2024.02
fanout_opt.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) 2017-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 "fanout_opt.hpp"
46 
47 #include "Parameter.hpp"
48 #include "application_manager.hpp"
49 #include "function_behavior.hpp"
50 #include "hls_manager.hpp"
51 #include <boost/graph/topological_sort.hpp>
52 #if HAVE_ILP_BUILT
53 #include "hls.hpp"
54 #include "schedule.hpp"
55 #endif
56 #include "dbgPrintHelper.hpp" // for DEBUG_LEVEL_
57 #include "string_manipulation.hpp" // for GET_CLASS
58 #include "tree_basic_block.hpp"
59 #include "tree_helper.hpp"
60 #include "tree_manager.hpp"
61 #include "tree_manipulation.hpp"
62 #include "tree_node.hpp"
63 #include "tree_reindex.hpp"
64 #include <cmath>
65 #include <fstream>
66 #include <string>
67 
69  unsigned int _function_id, const DesignFlowManagerConstRef _design_flow_manager)
70  : FunctionFrontendFlowStep(_AppM, _function_id, FANOUT_OPT, _design_flow_manager, _parameters),
71  TM(_AppM->get_tree_manager())
72 {
73  debug_level = parameters->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
74 }
75 
76 fanout_opt::~fanout_opt() = default;
77 
80 {
82  switch(relationship_type)
83  {
85  {
86  switch(GetStatus())
87  {
89  {
90  if(!parameters->getOption<int>(OPT_gcc_openmp_simd))
91  {
92  relationships.insert(std::make_pair(BIT_VALUE, SAME_FUNCTION));
93  }
94  break;
95  }
100  {
101  break;
102  }
106  default:
107  THROW_UNREACHABLE("");
108  }
109  break;
110  }
112  {
113  break;
114  }
116  {
117  relationships.insert(std::make_pair(CSE_STEP, SAME_FUNCTION));
118  relationships.insert(std::make_pair(EXTRACT_PATTERNS, SAME_FUNCTION));
119  break;
120  }
121  default:
122  THROW_UNREACHABLE("");
123  }
124  return relationships;
125 }
126 
128 {
129  THROW_ASSERT(t->get_kind() == tree_reindex_K, "t is not a tree_reindex node");
130  if(GET_NODE(t)->get_kind() == gimple_assign_K)
131  {
132  auto* temp_assign = GetPointer<gimple_assign>(GET_NODE(t));
133  if(GET_NODE(temp_assign->op1)->get_kind() == mult_expr_K ||
134  GET_NODE(temp_assign->op1)->get_kind() == widen_mult_expr_K ||
135  GET_NODE(temp_assign->op1)->get_kind() == ternary_plus_expr_K ||
136  GET_NODE(temp_assign->op1)->get_kind() == ternary_mm_expr_K ||
137  GET_NODE(temp_assign->op1)->get_kind() == ternary_pm_expr_K ||
138  GET_NODE(temp_assign->op1)->get_kind() == ternary_mp_expr_K)
139  {
140  return true;
141  }
142  }
143  return false;
144 }
145 
147 {
148  if(parameters->IsParameter("disable-fanout_opt"))
149  {
151  }
152  bool IR_changed = false;
153 
154  tree_nodeRef temp = TM->get_tree_node_const(function_id);
155  auto* fd = GetPointer<function_decl>(temp);
156  auto* sl = GetPointer<statement_list>(GET_NODE(fd->body));
158 
159  for(const auto& block : sl->list_of_bloc)
160  {
161  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Examining BB" + STR(block.first));
162  for(const auto& stmt : block.second->CGetStmtList())
163  {
164  if(not AppM->ApplyNewTransformation())
165  {
166  break;
167  }
168  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Examining statement " + GET_NODE(stmt)->ToString());
169  if(GET_NODE(stmt)->get_kind() == gimple_assign_K)
170  {
171  auto* ga = GetPointer<gimple_assign>(GET_NODE(stmt));
172  const std::string srcp_default =
173  ga->include_name + ":" + STR(ga->line_number) + ":" + STR(ga->column_number);
174  if(GET_NODE(ga->op0)->get_kind() == ssa_name_K)
175  {
176  auto* ssa_defined = GetPointer<ssa_name>(GET_NODE(ga->op0));
177  if(ssa_defined->CGetNumberUses() > 1)
178  {
179  const auto assigned_ssa_type_node = tree_helper::CGetType(ga->op0);
181  "---the assigned ssa_name " + STR(GET_NODE(ga->op0)) + " has type " +
182  STR(assigned_ssa_type_node));
183  bool is_first_stmt = true;
184  std::list<tree_nodeRef> list_of_dest_statements;
185  for(const auto& dest_statement : ssa_defined->CGetUseStmts())
186  {
187  if(is_first_stmt)
188  {
189  is_first_stmt = false;
190  }
191  else if(is_dest_relevant(dest_statement.first, false))
192  {
193  list_of_dest_statements.push_back(dest_statement.first);
194  }
195  }
196  for(const auto& dest_statement : list_of_dest_statements)
197  {
198  tree_nodeRef temp_assign =
199  tree_man->CreateGimpleAssign(assigned_ssa_type_node, ssa_defined->min, ssa_defined->max,
200  ga->op0, function_id, srcp_default);
202  "---create a temporary assignment " + temp_assign->ToString());
203  block.second->PushAfter(temp_assign, stmt, AppM);
204  tree_nodeRef temp_ssa_var = GetPointer<gimple_assign>(GET_NODE(temp_assign))->op0;
205  GetPointer<gimple_assign>(GET_NODE(temp_assign))->keep = true;
206  GetPointer<gimple_assign>(GET_NODE(temp_assign))->temporary_address = ga->temporary_address;
207  GetPointer<ssa_name>(GET_NODE(temp_ssa_var))->SetDefStmt(temp_assign);
209  "---dest statement before replacement " + dest_statement->ToString());
210  TM->ReplaceTreeNode(dest_statement, ga->op0, temp_ssa_var);
212  "---dest statement after replacement " + dest_statement->ToString());
213  IR_changed = true;
214  }
215  }
216  }
217  }
218  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Statement examined " + GET_NODE(stmt)->ToString());
219  }
220 #if 1
221  if(!parameters->getOption<int>(OPT_gcc_openmp_simd))
223  {
224  for(const auto& phi : block.second->CGetPhiList())
225  {
226  auto gp = GetPointer<gimple_phi>(GET_NODE(phi));
227  auto* ssa_defined = GetPointer<ssa_name>(GET_NODE(gp->res));
228 
229  if(ssa_defined->CGetNumberUses() > 1)
230  {
231  bool is_first_stmt = true;
232  std::list<tree_nodeRef> list_of_dest_statements;
233  for(const auto& dest_statement : ssa_defined->CGetUseStmts())
234  {
235  if(is_first_stmt)
236  {
237  is_first_stmt = false;
238  }
239  else if(is_dest_relevant(dest_statement.first, true))
240  {
241  list_of_dest_statements.push_back(dest_statement.first);
242  }
243  }
244  for(const auto& dest_statement : list_of_dest_statements)
245  {
247  std::vector<std::pair<tree_nodeRef, unsigned int>> list_of_def_edge;
248  for(const auto& def_edge : gp->CGetDefEdgesList())
249  {
250  list_of_def_edge.push_back(std::pair<tree_nodeRef, unsigned int>(def_edge.first, def_edge.second));
251  }
252  tree_nodeRef new_res_var;
253  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---starting from phi " + phi->ToString());
254  auto new_phi =
255  tree_man->create_phi_node(new_res_var, list_of_def_edge, GET_INDEX_CONST_NODE(gp->scpe));
256  auto new_res_var_ssa = GetPointer<ssa_name>(GET_NODE(new_res_var));
257  new_res_var_ssa->min = ssa_defined->min;
258  new_res_var_ssa->max = ssa_defined->max;
259  GetPointer<gimple_phi>(GET_NODE(new_phi))->SetSSAUsesComputed();
260  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---created a new phi " + new_phi->ToString());
261  block.second->AddPhi(new_phi);
262  GetPointer<gimple_phi>(GET_NODE(new_phi))->keep = true;
264  "---dest statement before replacement " + dest_statement->ToString());
265  TM->ReplaceTreeNode(dest_statement, gp->res, new_res_var);
267  "---dest statement after replacement " + dest_statement->ToString());
268  IR_changed = true;
269  }
270  }
271  }
272  }
273 #endif
274  if(IR_changed && schedule)
275  {
276  for(const auto& stmt : block.second->CGetStmtList())
277  {
279  }
280  }
281  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Considered BB" + STR(block.first));
282  }
283  IR_changed ? function_behavior->UpdateBBVersion() : 0;
285 }
286 
288 {
289 #if HAVE_ILP_BUILT
290  if(GetPointer<const HLS_manager>(AppM) and GetPointer<const HLS_manager>(AppM)->get_HLS(function_id) and
291  GetPointer<const HLS_manager>(AppM)->get_HLS(function_id)->Rsch)
292  {
293  schedule = GetPointer<const HLS_manager>(AppM)->get_HLS(function_id)->Rsch;
294  }
295 #endif
296 }
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:343
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec)
Definition: fanout_opt.cpp:287
#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;.
File containing functions and utilities to support the printing of debug messagges.
std::string ToString() const
Print this node as string in gimple format.
Step successfully executed.
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: fanout_opt.cpp:79
#define GET_CLASS(obj)
Macro returning the actual type of an object.
Definition of the class representing a generic C application.
refcount< tree_manipulation > tree_manipulationRef
Step successfully executed but without any IR change.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
#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
const tree_managerRef TM
tree manager
Definition: fanout_opt.hpp:69
Data structure describing a basic block at tree level.
DesignFlowStep_Status InternalExec() override
perform fanout_opt analysis
Definition: fanout_opt.cpp:146
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.
std::string ToString(ActorGraphBackend_Type actor_graph_backend_type)
Header include.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
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
Data structure used to store the schedule of the operations.
fanout_opt(const ParameterConstRef _parameters, const application_managerRef _AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
Definition: fanout_opt.cpp:68
bool is_dest_relevant(tree_nodeRef t, bool is_phi)
return true in case the use is relevant for the fanout optimization
Definition: fanout_opt.cpp:127
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.
ScheduleRef schedule
The scheduling solution.
Definition: fanout_opt.hpp:66
This struct specifies the block node.
Definition: tree_node.hpp:1820
This file collects some utility functions.
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.
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.
Fanout optimization step.
this class is used to manage the command-line or XML options.
int debug_level
The debug level.
#define GET_INDEX_CONST_NODE(t)
Definition: tree_node.hpp:363
Data structure definition for high-level synthesis flow.
Step is symbolic and it has already been marked.
This class creates a layer to add nodes and to manipulate the tree_nodes manager. ...
~fanout_opt() override
Destructor.
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.
#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