PandA-2024.02
NI_SSA_liveness.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  */
81 #include "NI_SSA_liveness.hpp"
83 
85 #include "application_manager.hpp"
86 #include "behavioral_helper.hpp"
87 #include "function_behavior.hpp"
88 
90 #include "Parameter.hpp"
91 
93 #include <fstream>
94 
96 #include "dbgPrintHelper.hpp" // for DEBUG_LEVEL_
97 #include "string_manipulation.hpp" // for GET_CLASS
98 #include "tree_basic_block.hpp"
99 #include "tree_helper.hpp"
100 #include "tree_manager.hpp"
101 #include "tree_reindex.hpp"
102 
104  unsigned int _function_id, const DesignFlowManagerConstRef _design_flow_manager)
105  : FunctionFrontendFlowStep(_AppM, _function_id, NI_SSA_LIVENESS, _design_flow_manager, _parameters)
106 {
107  debug_level = parameters->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
108 }
109 
111 
114 {
116  switch(relationship_type)
117  {
119  {
120  relationships.insert(std::make_pair(COMPLETE_BB_GRAPH, SAME_FUNCTION));
121  relationships.insert(std::make_pair(EXTRACT_PATTERNS, SAME_FUNCTION));
122  relationships.insert(std::make_pair(HDL_VAR_DECL_FIX, SAME_FUNCTION));
123  relationships.insert(std::make_pair(USE_COUNTING, SAME_FUNCTION));
124  break;
125  }
127  {
128  break;
129  }
131  {
132  relationships.insert(std::make_pair(COND_EXPR_RESTRUCTURING, SAME_FUNCTION));
133  relationships.insert(std::make_pair(CSE_STEP, SAME_FUNCTION));
134  relationships.insert(std::make_pair(FANOUT_OPT, SAME_FUNCTION));
135  relationships.insert(std::make_pair(FUNCTION_CALL_OPT, SAME_FUNCTION));
136  relationships.insert(std::make_pair(VECTORIZE, SAME_FUNCTION));
137  break;
138  }
139  default:
140  {
141  THROW_UNREACHABLE("");
142  }
143  }
144  return relationships;
145 }
146 
148 {
150  auto* v_ssa_name = GetPointer<ssa_name>(GET_NODE(v));
151  if(!v_ssa_name)
152  {
153  return;
154  }
155  if(v_ssa_name->volatile_flag)
156  {
157  return;
158  }
159  THROW_ASSERT(v_ssa_name->CGetDefStmts().size() == 1,
160  "SSA " + v_ssa_name->ToString() + " (" + STR(v_ssa_name->index) + ") is not in SSA form");
161  unsigned int def_stmt = GET_INDEX_NODE(v_ssa_name->CGetDefStmt());
162  if(((GET_NODE(v_ssa_name->CGetDefStmt()))->get_kind() == gimple_nop_K &&
163  GET_NODE(v_ssa_name->var)->get_kind() == parm_decl_K))
164  {
165  return;
166  }
167 
168  for(const auto& stmt : B->CGetStmtList())
169  {
170  if(def_stmt == GET_INDEX_NODE(stmt))
171  {
172  return;
173  }
174  }
176  unsigned int v_index = GET_INDEX_NODE(v);
177  if(B->live_in.find(v_index) != B->live_in.end())
178  {
179  return;
180  }
182  B->live_in.insert(v_index);
184  for(const auto& phi : B->CGetPhiList())
185  {
186  auto* pn = GetPointer<gimple_phi>(GET_NODE(phi));
187  if(GET_INDEX_NODE(pn->res) == v_index)
188  {
189  return;
190  }
191  }
193  auto lp_it_end = B->list_of_pred.end();
194  for(auto lp_it = B->list_of_pred.begin(); lp_it != lp_it_end; ++lp_it)
195  {
196  const blocRef P = sl->list_of_bloc[*lp_it];
197  P->live_out.insert(v_index);
198  Up_and_Mark(P, v, sl);
199  }
200 }
201 
203 {
204  const tree_managerRef TM = AppM->get_tree_manager();
206  auto* fd = GetPointer<function_decl>(tn);
207  THROW_ASSERT(fd && fd->body, "Node is not a function or it hasn't a body");
208  auto* sl = GetPointer<statement_list>(GET_NODE(fd->body));
209  THROW_ASSERT(sl, "Body is not a statement_list");
210  auto B_it_end = sl->list_of_bloc.end();
212  for(auto B_it = sl->list_of_bloc.begin(); B_it != B_it_end; ++B_it)
213  {
214  blocRef B = B_it->second;
215  unsigned int B_id = B->number;
217  auto ls_it_end = B->list_of_succ.end();
218  for(auto ls_it = B->list_of_succ.begin(); ls_it != ls_it_end; ++ls_it)
219  {
220  const blocRef B_succ = sl->list_of_bloc[*ls_it];
221  for(auto const& phi : B_succ->CGetPhiList())
222  {
223  auto* pn = GetPointer<gimple_phi>(GET_NODE(phi));
224  bool is_virtual = pn->virtual_flag;
225  if(!is_virtual)
226  {
227  for(const auto& def_edge : pn->CGetDefEdgesList())
228  {
229  if(def_edge.second == B_id)
230  {
233  B->live_out.insert(GET_INDEX_NODE(def_edge.first));
234  Up_and_Mark(B, def_edge.first, sl);
235  }
236  }
237  }
238  }
239  }
240 
241  CustomSet<tree_nodeRef> bb_ssa_uses;
242  for(const auto& stmt : B->CGetStmtList())
243  {
244  const auto stmt_uses = tree_helper::ComputeSsaUses(stmt);
245  for(const auto& stmt_use : stmt_uses)
246  {
247  if(not tree_helper::is_virtual(TM, stmt_use.first->index))
248  {
249  bb_ssa_uses.insert(stmt_use.first);
250  }
251  }
252  }
254  for(const auto& ssa_use : bb_ssa_uses)
255  {
256  Up_and_Mark(B, ssa_use, sl);
257  }
258  }
259 
260 #ifndef NDEBUG
262  {
264  const BehavioralHelperConstRef BH = AppM->CGetFunctionBehavior(function_id)->CGetBehavioralHelper();
265  PRINT_DBG_MEX(DEBUG_LEVEL_PEDANTIC, debug_level, "Liveness for function " + BH->get_function_name());
266 
267  for(auto B_it = sl->list_of_bloc.begin(); B_it != B_it_end; ++B_it)
268  {
269  blocRef B = B_it->second;
270  auto li_it_end = B->live_in.end();
271  PRINT_DBG_STRING(DEBUG_LEVEL_PEDANTIC, debug_level, "Live In for BB" + STR(B->number) + ": ");
272  for(auto li_it = B->live_in.begin(); li_it != li_it_end; ++li_it)
273  {
275  }
277  auto lo_it_end = B->live_out.end();
278  PRINT_DBG_STRING(DEBUG_LEVEL_PEDANTIC, debug_level, "Live Out for BB" + STR(B->number) + ": ");
279  for(auto lo_it = B->live_out.begin(); lo_it != lo_it_end; ++lo_it)
280  {
282  }
284  }
285  }
286 #endif
288 }
289 
291 {
292  if(bb_version != 0 and bb_version != function_behavior->GetBBVersion())
293  {
294  const auto TM = AppM->get_tree_manager();
295  auto tn = TM->get_tree_node_const(function_id);
296  auto fd = GetPointer<function_decl>(tn);
297  THROW_ASSERT(fd && fd->body, "Node is not a function or it hasn't a body");
298  auto sl = GetPointer<statement_list>(GET_NODE(fd->body));
299  for(const auto& block : sl->list_of_bloc)
300  {
301  block.second->live_in.clear();
302  block.second->live_out.clear();
303  }
304  }
305 }
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:343
File containing functions and utilities to support the printing of debug messagges.
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.
#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.
std::string get_function_name() const
Return the name of the function.
This struct specifies the statement_list node.
Definition: tree_node.hpp:4662
Definition of the class representing a generic C application.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
void Up_and_Mark(blocRef B, tree_nodeRef v, statement_list *sl)
Algorithm 5: Explore all paths from a variable’s use to its definition.
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
#define GET_INDEX_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:361
#define PRINT_DBG_STRING(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed; no newline is added;...
Non-Iterative liveness analysis for SSA based gimple descriptions.
Data structure describing a basic block at tree level.
unsigned int bb_version
The version of the basic block intermediate representation on which this step has been applied...
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
DesignFlowStep_Status InternalExec() override
Performes the liveness analysis.
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.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
const size_t P
Definition: helm.c:5
static bool is_virtual(const tree_managerConstRef &TM, const unsigned int index)
return true in case the ssa_name is virtual
~NI_SSA_liveness() override
Destructor.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
#define DEBUG_LEVEL_NONE
no debugging print is performed.
std::string PrintVariable(unsigned int var) const
Print the name of the variable associated to the index.
NI_SSA_liveness(const ParameterConstRef _Param, const application_managerRef _AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
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.
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec.
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
this class is used to manage the command-line or XML options.
int debug_level
The debug level.
#define B
Definition: generate.c:14
static void ComputeSsaUses(const tree_nodeRef &, TreeNodeMap< size_t > &uses)
recursively compute the references to the ssa_name variables used in a statement
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