PandA-2024.02
basic_blocks_cfg_computation.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  */
41 
42 #include "Parameter.hpp"
43 #include "application_manager.hpp"
44 #include "basic_block.hpp"
46 #include "function_behavior.hpp"
47 #include "op_graph.hpp"
48 #if HAVE_HOST_PROFILING_BUILT
50 #endif
52 
54 #include "design_flow_graph.hpp"
55 #include "design_flow_manager.hpp"
56 
59 
61 #include "graph.hpp"
62 
64 #include <fstream>
65 
67 #include <list>
68 
70 #include "token_interface.hpp"
71 
73 #include "behavioral_helper.hpp"
75 #include "ext_tree_node.hpp"
76 #include "tree_basic_block.hpp"
77 #include "tree_manager.hpp"
78 #include "tree_reindex.hpp"
79 
81 #include "dbgPrintHelper.hpp"
82 #include "string_manipulation.hpp" // for GET_CLASS
83 
85  const application_managerRef _AppM, unsigned int _function_id,
86  const DesignFlowManagerConstRef _design_flow_manager)
87  : FunctionFrontendFlowStep(_AppM, _function_id, BASIC_BLOCKS_CFG_COMPUTATION, _design_flow_manager, _parameters)
88 {
89  debug_level = parameters->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
90 }
91 
93 
96 {
98  switch(relationship_type)
99  {
101  {
102  relationships.insert(std::make_pair(COMPLETE_BB_GRAPH, SAME_FUNCTION));
103  if(parameters->isOption(OPT_writer_language))
104  {
105  relationships.insert(std::make_pair(HDL_VAR_DECL_FIX, SAME_FUNCTION));
106  }
107  else
108  {
109  relationships.insert(std::make_pair(VAR_DECL_FIX, SAME_FUNCTION));
110  }
111  relationships.insert(std::make_pair(EXTRACT_PATTERNS, SAME_FUNCTION));
112  break;
113  }
115  {
116  break;
117  }
119  {
120  relationships.insert(std::make_pair(COND_EXPR_RESTRUCTURING, SAME_FUNCTION));
121  relationships.insert(std::make_pair(CSE_STEP, SAME_FUNCTION));
122  relationships.insert(std::make_pair(FANOUT_OPT, SAME_FUNCTION));
123  relationships.insert(std::make_pair(FUNCTION_CALL_OPT, SAME_FUNCTION));
124  relationships.insert(std::make_pair(IR_LOWERING, SAME_FUNCTION));
125 #if HAVE_ILP_BUILT
126  relationships.insert(std::make_pair(SDC_CODE_MOTION, SAME_FUNCTION));
127 #endif
128  relationships.insert(std::make_pair(UN_COMPARISON_LOWERING, SAME_FUNCTION));
129  break;
130  }
131  default:
132  {
133  THROW_UNREACHABLE("");
134  }
135  }
136  return relationships;
137 }
138 
140 {
141  if(bb_version != 0 and bb_version != function_behavior->GetBBVersion())
142  {
143  function_behavior->bbgc->Clear();
144 #if HAVE_HOST_PROFILING_BUILT
145  function_behavior->profiling_information->Clear();
146 #endif
147  }
148 }
149 
151 {
152  const auto TM = AppM->get_tree_manager();
153  const auto bbgc = function_behavior->bbgc;
154  const auto fd = GetPointer<const function_decl>(TM->CGetTreeNode(function_id));
155  THROW_ASSERT(fd && fd->body, "Node is not a function or it hasn't a body");
156  const auto sl = GetPointer<const statement_list>(GET_CONST_NODE(fd->body));
157  THROW_ASSERT(sl, "Body is not a statement_list");
158  for(const auto& id_bb : sl->list_of_bloc)
159  {
160  const auto& bb = id_bb.second;
161  if(bb->number != BB_ENTRY && bb->number != BB_EXIT)
162  {
163  continue;
164  }
165  bbgc->add_vertex(bb);
166  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Added basic block with index " + STR(bb->number));
167  if(bb->number == BB_EXIT)
168  {
169  const auto exit = bbgc->Cget_vertex(BB_EXIT);
170  bbgc->connect_to_entry(exit);
171  }
172  }
173  for(const auto& id_bb : sl->list_of_bloc)
174  {
175  const auto& bb = id_bb.second;
176  if(bb->number == BB_ENTRY || bb->number == BB_EXIT)
177  {
178  continue;
179  }
180  bbgc->add_vertex(bb);
181  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Added basic block with index " + STR(bb->number));
182  }
183  for(const auto& id_bb : sl->list_of_bloc)
184  {
185  const auto& bb = id_bb.second;
186  if(bb->number == BB_ENTRY || bb->number == BB_EXIT)
187  {
188  continue;
189  }
190  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Considering connections for BB" + STR(bb->number));
191  const auto current = bbgc->Cget_vertex(bb->number);
192  if(bb->list_of_pred.empty() || std::count(bb->list_of_pred.begin(), bb->list_of_pred.end(), bloc::ENTRY_BLOCK_ID))
193  {
195  "---Connecting Basic block " + STR(bb->number) + " to ENTRY");
196  bbgc->connect_to_entry(current);
197  }
198  for(const auto su : bb->list_of_succ)
199  {
200  if(su == bloc::EXIT_BLOCK_ID)
201  {
203  "---Connecting Basic block " + STR(bb->number) + " to EXIT");
204  bbgc->connect_to_exit(current);
205  }
206  else
207  {
209  "---Connecting Basic block " + STR(bb->number) + " to " + STR(su));
210  bbgc->AddEdge(current, bbgc->Cget_vertex(su), CFG_SELECTOR);
211  // Considering label
212  if(su == bb->true_edge)
213  {
214  bbgc->add_bb_edge_info(current, bbgc->Cget_vertex(su), CFG_SELECTOR, T_COND);
215  }
216  if(su == bb->false_edge)
217  {
218  bbgc->add_bb_edge_info(current, bbgc->Cget_vertex(su), CFG_SELECTOR, F_COND);
219  }
220  }
221  }
222  const auto& statements = bb->CGetStmtList();
223  if(!statements.empty())
224  {
225  const auto& last = statements.back();
227  if(GET_CONST_NODE(last)->get_kind() == gimple_switch_K)
228  {
229  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->BB" + STR(bb->number) + " ends with a switch");
230  // Map between gimple_label and index of basic block
231  std::map<tree_nodeRef, unsigned int> label_to_bb;
232  for(const auto su : bb->list_of_succ)
233  {
234  THROW_ASSERT(sl->list_of_bloc.at(su)->CGetStmtList().size(), "Empty Basic Block");
235  const auto first = sl->list_of_bloc.at(su)->CGetStmtList().front();
236  THROW_ASSERT(GET_CONST_NODE(first)->get_kind() == gimple_label_K,
237  "First operation of BB" + STR(su) + " is a " + GET_CONST_NODE(first)->get_kind_text() +
238  ": " + GET_CONST_NODE(first)->ToString());
239  const auto le = GetPointerS<const gimple_label>(GET_CONST_NODE(first));
240  label_to_bb[GET_CONST_NODE(le->op)] = su;
242  "---Gimple label of BB" + STR(su) + " is " + STR(GET_INDEX_CONST_NODE(le->op)));
243  }
244  const auto se = GetPointer<const gimple_switch>(GET_CONST_NODE(last));
245  THROW_ASSERT(se->op1, "case_label_exprs not found");
246  const auto tv = GetPointer<const tree_vec>(GET_CONST_NODE(se->op1));
247 
248  for(const auto& op : tv->list_of_op)
249  {
250  const auto cl = GetPointer<const case_label_expr>(GET_CONST_NODE(op));
251  THROW_ASSERT(label_to_bb.count(GET_CONST_NODE(cl->got)),
252  "There is not corresponding case_label_exprs with index " +
253  STR(GET_INDEX_CONST_NODE(cl->got)));
254  if(cl->default_flag)
255  {
256  bbgc->add_bb_edge_info(current, bbgc->Cget_vertex(label_to_bb[GET_CONST_NODE(cl->got)]), CFG_SELECTOR,
257  default_COND);
258  }
259  else
260  {
261  bbgc->add_bb_edge_info(current, bbgc->Cget_vertex(label_to_bb[GET_CONST_NODE(cl->got)]), CFG_SELECTOR,
263  }
264  }
266  }
268  else if(GET_CONST_NODE(last)->get_kind() == gimple_goto_K && bb->list_of_succ.size() > 1)
269  {
270  // Map between gimple_label and index of basic block
271  for(const auto su : bb->list_of_succ)
272  {
273  bbgc->add_bb_edge_info(current, bbgc->Cget_vertex(su), CFG_SELECTOR, su);
274  }
275  }
277  else if(GET_CONST_NODE(last)->get_kind() == gimple_multi_way_if_K)
278  {
279  const auto gmwi = GetPointerS<const gimple_multi_way_if>(GET_CONST_NODE(last));
280  for(const auto& cond : gmwi->list_of_cond)
281  {
282  bbgc->add_bb_edge_info(current, bbgc->Cget_vertex(cond.second), CFG_SELECTOR,
283  cond.first ? cond.first->index : default_COND);
284  }
285  }
286  }
287  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Considered connections for BB" + STR(bb->number));
288  }
289  const auto exit = bbgc->Cget_vertex(BB_EXIT);
290  const auto fcfg = function_behavior->GetBBGraph(FunctionBehavior::FBB);
291  BOOST_FOREACH(vertex v, boost::vertices(*fcfg))
292  {
293  if(boost::out_degree(v, *fcfg) == 0 && v != exit)
294  {
295  bbgc->AddEdge(v, exit, CFG_SELECTOR);
296  }
297  }
298  if(parameters->getOption<bool>(OPT_print_dot))
299  {
300  function_behavior->GetBBGraph(FunctionBehavior::BB)->WriteDot("BB_CFG.dot");
301  }
303 }
BasicBlocksCfgComputation(const ParameterConstRef _parameters, const application_managerRef AppM, unsigned int _function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
Basic block control flow graph.
File containing functions and utilities to support the printing of debug messagges.
~BasicBlocksCfgComputation() override
Destructor.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
#define BB_EXIT
constant identifying the basic block node of type exit
Definition of the class representing a generic C application.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
Class specification of the graph structures.
Analysis step creating the control flow graph for the operations.
A simple interface to token object of the raw files.
static const unsigned int EXIT_BLOCK_ID
constant identifying the exit basic block
This class provides methods to build a basic blocks graph.
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.
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
Class specification for storing profiling information.
DesignFlowStep_Status InternalExec() override
Computes the basic block graph structure.
Build basic block control flow graph data structure starting from the tree_manager.
#define default_COND
constant used to represent label "default" of a switch construct
Classes to describe design flow graph.
Basic block control flow graph with feedback.
#define BB_ENTRY
constant identifying the basic block node of type entry
boost::graph_traits< graph >::vertex_descriptor vertex
vertex definition.
Definition: graph.hpp:1303
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec.
#define T_COND
constant used to represent control edges representing a true edge of a conditional statement...
#define GET_CONST_NODE(t)
Definition: tree_node.hpp:347
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
#define DEBUG_LEVEL_NONE
no debugging print is performed.
Wrapper of design_flow.
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
Collect all structs used to write a graph in the dot format.
Class specification of the basic_block structure.
Data structures used in operations graph.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
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.
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.
#define F_COND
constant used to represent control edges representing a false edge of a conditional statement...
int debug_level
The debug level.
This class provides methods to build an operations graph.
#define GET_INDEX_CONST_NODE(t)
Definition: tree_node.hpp:363
#define CFG_SELECTOR
Control flow graph edge selector.
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:51 for PandA-2024.02 by doxygen 1.8.13