PandA-2024.02
virtual_phi_nodes_split.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  */
43 
45 #include "Parameter.hpp"
46 
48 #include "application_manager.hpp"
49 #include "function_behavior.hpp"
50 
52 #include "token_interface.hpp"
53 
55 #include <fstream>
56 
58 #include "dbgPrintHelper.hpp" // for DEBUG_LEVEL_
59 #include "ext_tree_node.hpp"
60 #include "string_manipulation.hpp" // for GET_CLASS
61 #include "tree_basic_block.hpp"
62 #include "tree_helper.hpp"
63 #include "tree_manager.hpp"
64 #include "tree_manipulation.hpp"
65 #include "tree_reindex.hpp"
66 
68 
70  const application_managerRef _AppM, unsigned int _function_id,
71  const DesignFlowManagerConstRef _design_flow_manager)
72  : FunctionFrontendFlowStep(_AppM, _function_id, VIRTUAL_PHI_NODES_SPLIT, _design_flow_manager, _parameters),
73  tree_man(new tree_manipulation(AppM->get_tree_manager(), parameters, AppM))
74 {
75  debug_level = parameters->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
76 }
77 
79 
82 {
84  switch(relationship_type)
85  {
87  {
88  relationships.insert(std::make_pair(BLOCK_FIX, SAME_FUNCTION));
89  break;
90  }
92  {
93  break;
94  }
96  {
97  relationships.insert(std::make_pair(SHORT_CIRCUIT_TAF, SAME_FUNCTION));
98  relationships.insert(std::make_pair(MULTI_WAY_IF, SAME_FUNCTION));
99  relationships.insert(std::make_pair(PHI_OPT, SAME_FUNCTION));
100  break;
101  }
102  default:
103  {
104  THROW_UNREACHABLE("");
105  }
106  }
107  return relationships;
108 }
109 
111 {
112  const tree_managerRef TM = AppM->get_tree_manager();
114  {
115  tree_dumped = true;
116  std::string raw_file_name =
117  parameters->getOption<std::string>(OPT_output_temporary_directory) + "before_virtual_phi_nodes_split.raw";
118  std::ofstream raw_file(raw_file_name.c_str());
119  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Tree-Manager dumped for debug purpose");
120  raw_file << TM;
121  raw_file.close();
122  }
125  std::map<std::pair<unsigned int, unsigned int>, unsigned int> replace;
126 
128  auto* fd = GetPointer<function_decl>(temp);
129  auto* sl = GetPointer<statement_list>(GET_NODE(fd->body));
130  std::map<unsigned int, blocRef>& list_of_bloc = sl->list_of_bloc;
131 
132  std::map<unsigned int, blocRef>::iterator iit, iit_end = list_of_bloc.end();
133  for(iit = list_of_bloc.begin(); iit != iit_end; ++iit)
134  {
135  blocRef& bb_block = iit->second;
136  for(const auto& phi : bb_block->CGetPhiList())
137  {
138  virtual_split_phi(phi, bb_block, list_of_bloc, TM, replace);
139  }
140  }
141 
143  {
144  std::string raw_file_name =
145  parameters->getOption<std::string>(OPT_output_temporary_directory) + "after_virtual_phi_nodes_split.raw";
146  std::ofstream raw_file(raw_file_name.c_str());
147  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Tree-Manager dumped for debug purpose");
148  raw_file << TM;
149  raw_file.close();
150  }
151  function_behavior->UpdateBBVersion();
153 }
154 
156  std::map<unsigned int, blocRef>& list_of_bloc, const tree_managerRef TM,
157  std::map<std::pair<unsigned int, unsigned int>, unsigned int>& replace)
158 {
159  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Splitting phi node " + STR(GET_INDEX_NODE(tree_phi)));
160  auto* phi = GetPointer<gimple_phi>(GET_NODE(tree_phi));
161  THROW_ASSERT(phi, "A non-phi node is stored in the phi_list");
162  // std::cout << "Analyzing phi-node: @" << GET_INDEX_NODE(tree_phi) << std::endl;
163  if(phi->virtual_flag)
164  {
165  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Phi node is virtual so no splitting is performed");
166  return;
167  }
168  for(const auto& def_edge : phi->CGetDefEdgesList())
169  {
170  tree_nodeRef def = def_edge.first;
171 
173  auto* ssa_var = GetPointer<ssa_name>(GET_NODE(phi->res));
174  THROW_ASSERT(ssa_var, "unexpected condition " + STR(GET_INDEX_NODE(phi->res)));
175  const auto type_node = tree_helper::CGetType(phi->res);
176  const auto res = tree_man->create_ssa_name(type_node, ssa_var->var, nullptr, nullptr);
177 
179  phi->ReplaceDefEdge(TM, def_edge, gimple_phi::DefEdge(res, def_edge.second));
180  unsigned int bb_source = def_edge.second;
181  blocRef source_bb;
182  std::map<unsigned int, blocRef>::iterator it, it_end = list_of_bloc.end();
183  for(it = list_of_bloc.begin(); it != it_end; ++it)
184  {
185  source_bb = it->second;
186  if(source_bb->number != bb_source)
187  {
188  continue;
189  }
190  if(replace.find(std::make_pair(bb_source, bb_block->number)) != replace.end())
191  {
192  bb_source = replace[std::make_pair(bb_source, bb_block->number)];
193  source_bb = list_of_bloc.find(bb_source)->second;
194  phi->ReplaceDefEdge(TM, def_edge, gimple_phi::DefEdge(def_edge.first, bb_source));
195  }
196  if(bb_source == bloc::ENTRY_BLOCK_ID)
197  {
198  // New block has not been created
199  if(!next_entry)
200  {
201  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Predecessor is entry: creating new basic block");
202  THROW_ASSERT(source_bb->list_of_succ.size() == 1, "ENTRY BB has more than one successor");
203  unsigned int this_bb_index = source_bb->list_of_succ.front();
204  // Creating new basic block
205  blocRef new_bb = blocRef(new bloc(list_of_bloc.rbegin()->first + 1));
206  new_bb->list_of_pred.push_back(bloc::ENTRY_BLOCK_ID);
207  new_bb->list_of_succ.push_back(this_bb_index);
209  "Adding edge from " + STR(bloc::ENTRY_BLOCK_ID) + " to " + STR(this_bb_index));
210 
211  // Updating entry
212  source_bb->list_of_succ.clear();
213  source_bb->list_of_succ.push_back(new_bb->number);
214 
215  // Updating this
216  blocRef this_bb;
217  unsigned int index;
218  for(index = 0; index < list_of_bloc.size(); index++)
219  {
220  if(list_of_bloc[index]->number == this_bb_index)
221  {
222  this_bb = list_of_bloc[index];
223  break;
224  }
225  }
226  THROW_ASSERT(index < list_of_bloc.size(), "Current basic block not found");
227  for(index = 0; index < this_bb->list_of_pred.size(); index++)
228  {
229  if(this_bb->list_of_pred[index] == bloc::ENTRY_BLOCK_ID)
230  {
232  "Adding edge from " + STR(new_bb->number) + " to " +
233  STR(this_bb->list_of_pred[index]));
234  this_bb->list_of_pred[index] = new_bb->number;
235  break;
236  }
237  }
238  THROW_ASSERT(index < this_bb->list_of_pred.size(),
239  "Entry not found in predecessors of current basic block");
240 
241  list_of_bloc[new_bb->number] = new_bb;
242  source_bb = new_bb;
243  next_entry = new_bb;
244  }
245  else
246  {
247  source_bb = next_entry;
248  }
249  }
250  const auto list_of_stmt = source_bb->CGetStmtList();
251 
252  const auto created_stmt = tree_man->create_gimple_modify_stmt(res, def, function_id, BUILTIN_SRCP);
253  phi->ReplaceDefEdge(TM, def_edge, gimple_phi::DefEdge(def_edge.first, source_bb->number));
254  if(list_of_stmt.size() and (GetPointer<gimple_goto>(GET_NODE(list_of_stmt.back())) ||
255  GetPointer<gimple_while>(GET_NODE(list_of_stmt.back())) ||
256  GetPointer<gimple_for>(GET_NODE(list_of_stmt.back())) ||
257  GetPointer<gimple_switch>(GET_NODE(list_of_stmt.back()))))
258  {
259  source_bb->PushBack(created_stmt, AppM);
261  }
262  else if(list_of_stmt.size() && GetPointer<gimple_cond>(GET_NODE(list_of_stmt.back())))
263  {
264  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "One of the predecessors ends with an if");
265  bool true_case = source_bb->true_edge == bb_block->number;
266  blocRef new_bb = blocRef(new bloc(list_of_bloc.rbegin()->first + 1));
267  if(true_case)
268  {
269  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "This is true edge");
270  // Creating new basic block
271  new_bb->list_of_pred.push_back(source_bb->true_edge);
272  new_bb->list_of_succ.push_back(bb_block->number);
273  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Created new basic block " + STR(new_bb->number));
274 
275  // Updating predecessor
276  source_bb->list_of_succ.erase(
277  std::find(source_bb->list_of_succ.begin(), source_bb->list_of_succ.end(), bb_block->number));
278  source_bb->list_of_succ.push_back(new_bb->number);
279  source_bb->true_edge = new_bb->number;
280 
281  // Updating this
282  bb_block->list_of_pred.erase(
283  std::find(bb_block->list_of_pred.begin(), bb_block->list_of_pred.end(), source_bb->number));
284  bb_block->list_of_pred.push_back(new_bb->number);
286  "Adding edge from " + STR(source_bb->number) + " to " + STR(new_bb->number));
287  }
288  else
289  {
290  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "This is false edge");
291  // Creating new basic block
292  new_bb->list_of_pred.push_back(source_bb->false_edge);
293  new_bb->list_of_succ.push_back(bb_block->number);
294  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Created new basic block " + STR(new_bb->number));
295 
296  // Updating predecessor
297  source_bb->list_of_succ.erase(
298  std::find(source_bb->list_of_succ.begin(), source_bb->list_of_succ.end(), bb_block->number));
299  source_bb->list_of_succ.push_back(new_bb->number);
300  source_bb->false_edge = new_bb->number;
301  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Updated predecessor");
302 
303  // Updating this
304  bb_block->list_of_pred.erase(
305  std::find(bb_block->list_of_pred.begin(), bb_block->list_of_pred.end(), source_bb->number));
306  bb_block->list_of_pred.push_back(new_bb->number);
308  "Adding edge from " + STR(source_bb->number) + " to " + STR(new_bb->number));
309  }
310  list_of_bloc[new_bb->number] = new_bb;
311  replace[std::make_pair(source_bb->number, bb_block->number)] = new_bb->number;
312  phi->ReplaceDefEdge(TM, def_edge, gimple_phi::DefEdge(def_edge.first, new_bb->number));
313 
314  // Inserting phi
315  new_bb->PushBack(created_stmt, AppM);
317  "Inserted new gimple " + STR(GET_INDEX_CONST_NODE(created_stmt)));
318  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Finished creation of new basic block");
319  }
320  else
321  {
323  "Inserted new gimple " + STR(GET_INDEX_CONST_NODE(created_stmt)));
324  source_bb->PushBack(created_stmt, AppM);
325  }
326  break;
327  }
328  }
329  return;
330 }
#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.
This struct specifies the field bloc (basic block).
File containing functions and utilities to support the printing of debug messagges.
#define PRINT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
Definition of the class representing a generic C application.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
A simple interface to token object of the raw files.
#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
Data structure describing a basic block at tree level.
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
const tree_nodeRef get_tree_node_const(unsigned int i) const
Return the reference to the i-th tree_node Constant version of get_tree_node.
static bool tree_dumped
flag to check if initial tree has been dumped
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
unsigned map[NUM_VERTICES]
Definition: bfs.c:12
#define index(x, y)
Definition: Keccak.c:74
std::pair< tree_nodeRef, unsigned int > DefEdge
The type of the def edge.
Definition: tree_node.hpp:3750
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.
This file collects some utility functions.
void virtual_split_phi(tree_nodeRef phi, blocRef &bb_block, std::map< unsigned int, blocRef > &list_of_bloc, const tree_managerRef TM, std::map< std::pair< unsigned int, unsigned int >, unsigned int > &replace)
virtually split a particular phi in two or more assignments
#define BUILTIN_SRCP
DesignFlowStep_Status InternalExec() override
Performs the virtual splitting of the phi-nodes.
const unsigned int function_id
The index of the function to be analyzed.
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.
~virtual_phi_nodes_split() override
Destructor.
const application_managerRef AppM
The application manager.
struct definition of the type node structures.
Definition: tree_node.hpp:1318
Class specification of the tree_reindex support class.
static const unsigned int ENTRY_BLOCK_ID
constant identifying the entry basic block
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.
Classes specification of the tree_node data structures not present in the gcc.
this class is used to manage the command-line or XML options.
tree_nodeRef create_ssa_name(const tree_nodeConstRef &var, const tree_nodeConstRef &type, const tree_nodeConstRef &min, const tree_nodeConstRef &max, bool volatile_flag=false, bool virtual_flag=false) const
MISCELLANEOUS_OBJ_TREE_NODES.
virtual_phi_nodes_split(const ParameterConstRef _parameters, const application_managerRef AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
int debug_level
The debug level.
blocRef next_entry
Basic block introduced after entry.
#define GET_INDEX_CONST_NODE(t)
Definition: tree_node.hpp:363
tree_nodeRef create_gimple_modify_stmt(const tree_nodeRef &op0, const tree_nodeRef &op1, unsigned int function_decl_nid, const std::string &srcp) const
GIMPLE_ASSIGN.
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
#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