PandA-2024.02
add_op_phi_flow_edges.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  */
44 
46 #include "Parameter.hpp"
47 
49 #include "basic_block.hpp"
50 #include "function_behavior.hpp"
51 #include "op_graph.hpp"
53 
55 #include "dbgPrintHelper.hpp" // for DEBUG_LEVEL_
56 #include "ext_tree_node.hpp"
57 #include "hash_helper.hpp"
58 #include "string_manipulation.hpp" // for GET_CLASS
59 #include "tree_basic_block.hpp"
60 #include "tree_node.hpp"
61 #include "tree_reindex.hpp"
62 
63 AddOpPhiFlowEdges::AddOpPhiFlowEdges(const application_managerRef _AppM, const unsigned int _function_id,
64  const DesignFlowManagerConstRef _design_flow_manager,
65  const ParameterConstRef _parameters)
66  : FunctionFrontendFlowStep(_AppM, _function_id, ADD_OP_PHI_FLOW_EDGES, _design_flow_manager, _parameters)
67 {
68  debug_level = parameters->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
69 }
70 
72 
75 {
77  switch(relationship_type)
78  {
80  {
81  relationships.insert(std::make_pair(OPERATIONS_CFG_COMPUTATION, SAME_FUNCTION));
82  relationships.insert(std::make_pair(DOM_POST_DOM_COMPUTATION, SAME_FUNCTION));
83  relationships.insert(std::make_pair(EXTRACT_GIMPLE_COND_OP, SAME_FUNCTION));
84  break;
85  }
88  {
89  break;
90  }
91  default:
92  {
94  }
95  }
96  return relationships;
97 }
98 
100 {
101  if(bb_version != 0 and bb_version != function_behavior->GetBBVersion())
102  {
103  const OpGraphConstRef flg = function_behavior->CGetOpGraph(FunctionBehavior::FLG);
104  if(boost::num_vertices(*flg) != 0)
105  {
106  EdgeIterator edge, edge_end;
107  for(boost::tie(edge, edge_end) = boost::edges(*flg); edge != edge_end; edge++)
108  {
109  if((GET_TYPE(flg, boost::target(*edge, *flg)) & TYPE_PHI) != 0)
110  {
111  function_behavior->ogc->RemoveSelector(*edge, FLG_SELECTOR);
112  }
113  }
114  }
115  }
116 }
117 
119 {
121  const OpGraphConstRef fcfg = function_behavior->CGetOpGraph(FunctionBehavior::FCFG);
122 
124  const auto bb_fcfg = function_behavior->CGetBBGraph(FunctionBehavior::FBB);
125  const auto dom_tree = function_behavior->CGetBBGraph(FunctionBehavior::DOM_TREE);
126 
127  const auto bb_index_map = dom_tree->CGetBBGraphInfo()->bb_index_map;
128 
129  VertexIterator operation, operation_end;
130  for(boost::tie(operation, operation_end) = boost::vertices(*fcfg); operation != operation_end; operation++)
131  {
132  if((GET_TYPE(fcfg, *operation) & TYPE_PHI) != 0)
133  {
134  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Analyzing " + GET_NAME(fcfg, *operation));
135  const auto bb_index = fcfg->CGetOpNodeInfo(*operation)->bb_index;
136  const auto bb_vertex = bb_index_map.find(bb_index)->second;
138  bool found_feedback_edge = false;
139  InEdgeIterator ie, ie_end;
140  for(boost::tie(ie, ie_end) = boost::in_edges(bb_vertex, *bb_fcfg); ie != ie_end; ie++)
141  {
142  if(bb_fcfg->GetSelector(*ie) & FB_CFG_SELECTOR)
143  {
144  found_feedback_edge = true;
145  break;
146  }
147  }
148  if(found_feedback_edge)
149  {
150  continue;
151  }
152  boost::tie(ie, ie_end) = boost::in_edges(bb_vertex, *dom_tree);
153  const auto dominator = boost::source(*ie, *dom_tree);
154  const auto dominator_statements = dom_tree->CGetBBNodeInfo(dominator)->block->CGetStmtList();
155  THROW_ASSERT(dominator_statements.size(),
156  "BB" + STR(dom_tree->CGetBBNodeInfo(dominator)->block->number) + " is empty");
157  const auto last_statement = GET_NODE(dominator_statements.back());
158  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Last statement is " + last_statement->ToString());
159  if(last_statement->get_kind() == gimple_cond_K)
160  {
161  const auto gc = GetPointer<const gimple_cond>(last_statement);
162  if(GET_NODE(gc->op0)->get_kind() == integer_cst_K)
163  {
164  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Considered " + GET_NAME(fcfg, *operation));
165  continue;
166  }
167  THROW_ASSERT(GET_NODE(gc->op0)->get_kind() == ssa_name_K,
168  "Operand of gimple_cond is " + gc->op0->ToString());
169  const auto ssa = GetPointer<const ssa_name>(GET_NODE(gc->op0));
170  const auto def_stmt_node = ssa->CGetDefStmt();
171  if(GetPointer<gimple_nop>(GET_NODE(def_stmt_node)))
172  {
173  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Considered " + GET_NAME(fcfg, *operation));
174  continue;
175  }
176  const auto def_stmt_index = def_stmt_node->index;
177  THROW_ASSERT(fcfg->CGetOpGraphInfo()->tree_node_to_operation.find(def_stmt_index) !=
178  fcfg->CGetOpGraphInfo()->tree_node_to_operation.end(),
179  "Vertex corresponding to " + ssa->CGetDefStmt()->ToString() + " not found");
180  const auto def_stmt_vertex = fcfg->CGetOpGraphInfo()->tree_node_to_operation.find(def_stmt_index)->second;
181  function_behavior->ogc->AddEdge(def_stmt_vertex, *operation, FLG_SELECTOR);
182  }
183  else if(last_statement->get_kind() == gimple_multi_way_if_K)
184  {
186  const auto gmwi = GetPointer<const gimple_multi_way_if>(last_statement);
187  for(const auto& cond : gmwi->list_of_cond)
188  {
189  const auto cond_bb = bb_index_map.find(cond.second)->second;
190  if(cond.first and
191  ((cond.second == bb_index) or function_behavior->CheckBBReachability(cond_bb, bb_vertex)))
192  {
193  if(GET_NODE(cond.first)->get_kind() == integer_cst_K)
194  {
196  "<--Considered " + GET_NAME(fcfg, *operation));
197  continue;
198  }
199  THROW_ASSERT(GET_NODE(cond.first)->get_kind() == ssa_name_K,
200  "Operand of gimple_multi_way_if is " + cond.first->ToString());
201  const auto ssa = GetPointer<const ssa_name>(GET_NODE(cond.first));
202  THROW_ASSERT(ssa, GET_NODE(cond.first)->get_kind_text() + " " + STR(cond.first));
203  const auto def_stmt_index = ssa->CGetDefStmt()->index;
204  const auto def_stmt_vertex =
205  fcfg->CGetOpGraphInfo()->tree_node_to_operation.find(def_stmt_index)->second;
206  function_behavior->ogc->AddEdge(def_stmt_vertex, *operation, FLG_SELECTOR);
207  }
208  }
209  }
210  else if(last_statement->get_kind() == gimple_switch_K)
211  {
212  const auto gs = GetPointer<const gimple_switch>(last_statement);
213  THROW_ASSERT(GET_NODE(gs->op0)->get_kind() == ssa_name_K,
214  "Operand of gimple_switch is " + gs->op0->ToString());
215  const auto ssa = GetPointer<const ssa_name>(GET_NODE(gs->op0));
216  if(not ssa->var or GET_NODE(ssa->var)->get_kind() != parm_decl_K)
217  {
218  const auto def_stmt_index = ssa->CGetDefStmt()->index;
219  THROW_ASSERT(fcfg->CGetOpGraphInfo()->tree_node_to_operation.find(def_stmt_index) !=
220  fcfg->CGetOpGraphInfo()->tree_node_to_operation.end(),
221  "Vertex corresponding to " + ssa->CGetDefStmt()->ToString() + " not found");
222  const auto def_stmt_vertex =
223  fcfg->CGetOpGraphInfo()->tree_node_to_operation.find(def_stmt_index)->second;
224  function_behavior->ogc->AddEdge(def_stmt_vertex, *operation, FLG_SELECTOR);
225  }
226  }
227  else
228  {
229  THROW_UNREACHABLE("gimple phi is dominated by " + last_statement->ToString());
230  }
231  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Considered " + GET_NAME(fcfg, *operation));
232  }
233  }
234 
236 }
#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 FLG_SELECTOR
Flow edge selector.
Definition: op_graph.hpp:515
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
Analysis step which adds flow edges from the computation of the condition(s) of gimple_cond and gimpl...
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
#define GET_TYPE(data, vertex_index)
Helper macro returning the type associated with a node.
File containing functions and utilities to support the printing of debug messagges.
string target
Definition: lenet_tvm.py:16
#define GET_CLASS(obj)
Macro returning the actual type of an object.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
#define GET_NAME(data, vertex_index)
Helper macro returning the name associated with a node.
boost::graph_traits< graph >::in_edge_iterator InEdgeIterator
in_edge_iterator definition.
Definition: graph.hpp:1310
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 TYPE_PHI
constant string identifying an operation node of type PHI
Definition: op_graph.hpp:135
#define STR(s)
Macro which performs a lexical_cast to a string.
Auxiliary methods for manipulating string.
#define FB_CFG_SELECTOR
Feedback control flow edge selector.
AddOpPhiFlowEdges(const application_managerRef AppM, const unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager, const ParameterConstRef parameters)
Constructor.
boost::graph_traits< graph >::edge_iterator EdgeIterator
edge_iterator definition.
Definition: graph.hpp:1314
const OpNodeInfoConstRef CGetOpNodeInfo(const vertex node) const
Returns the info associated with a node.
Definition: op_graph.hpp:843
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 THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
unsigned edges[4545]
Definition: graph.h:25
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec.
This class specifies the characteristic of a particular operation working on a given functional unit...
Basic block dominator tree.
Basic block control flow graph with feedback.
const OpGraphInfoConstRef CGetOpGraphInfo() const
Returns the property associated with the graph.
Definition: op_graph.hpp:871
~AddOpPhiFlowEdges() override
Destructor.
boost::graph_traits< graph >::vertex_iterator VertexIterator
vertex_iterator definition.
Definition: graph.hpp:1307
Classes specification of the tree_node data structures.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
#define DEBUG_LEVEL_NONE
no debugging print is performed.
DesignFlowStep_Status InternalExec() override
Performs the adding of flow edges to operation graphs.
Class specification of the tree_reindex support class.
Class specification of the basic_block structure.
This file collects some hash functors.
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
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.
Control flow graph with feedback.
int debug_level
The debug level.
This class provides methods to build an operations graph.
A brief description of the C++ Header File.
const FunctionBehaviorRef function_behavior
The function behavior of the function to be analyzed.
#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