PandA-2024.02
split_return.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  */
46 #include "split_return.hpp"
47 #include "Parameter.hpp"
48 #include "application_manager.hpp"
49 #include "call_graph.hpp"
50 #include "call_graph_manager.hpp"
51 #include "hls.hpp"
52 #include "hls_manager.hpp"
53 #include "phi_opt.hpp"
54 #if HAVE_ILP_BUILT
55 #include "hls_step.hpp"
56 #endif
57 #include "custom_set.hpp"
58 #include "dbgPrintHelper.hpp" // for DEBUG_LEVEL_
59 #include "ext_tree_node.hpp"
60 #include "string_manipulation.hpp" // for GET_CLASS
61 #include "token_interface.hpp"
62 #include "tree_basic_block.hpp"
63 #include "tree_helper.hpp"
64 #include "tree_manager.hpp"
65 #include "tree_manipulation.hpp"
66 #include "tree_node.hpp"
67 #include "tree_reindex.hpp"
68 #include <fstream>
69 
71  unsigned int _function_id, const DesignFlowManagerConstRef _design_flow_manager)
72  : FunctionFrontendFlowStep(_AppM, _function_id, SPLIT_RETURN, _design_flow_manager, _parameters)
73 {
74  debug_level = parameters->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
75 }
76 
77 SplitReturn::~SplitReturn() = default;
78 
81 {
83  switch(relationship_type)
84  {
86  {
87  relationships.insert(std::make_pair(BLOCK_FIX, SAME_FUNCTION));
88  relationships.insert(std::make_pair(SWITCH_FIX, SAME_FUNCTION));
89  relationships.insert(std::make_pair(USE_COUNTING, SAME_FUNCTION));
90  break;
91  }
93  {
94  break;
95  }
97  {
98  relationships.insert(std::make_pair(CSE_STEP, SAME_FUNCTION));
99  relationships.insert(std::make_pair(REMOVE_CLOBBER_GA, SAME_FUNCTION));
100  break;
101  }
102  default:
103  {
104  THROW_UNREACHABLE("");
105  }
106  }
107  return relationships;
108 }
109 
111 {
112  if(parameters->IsParameter("disable-SplitReturn") && parameters->GetParameter<int>("disable-SplitReturn") == 1)
113  {
114  return false;
115  }
116 #if HAVE_ILP_BUILT
117  if(parameters->isOption(OPT_scheduling_algorithm) &&
118  parameters->getOption<HLSFlowStep_Type>(OPT_scheduling_algorithm) == HLSFlowStep_Type::SDC_SCHEDULING)
119  {
120  return GetPointer<const HLS_manager>(AppM) && GetPointer<const HLS_manager>(AppM)->get_HLS(function_id) &&
121  GetPointer<const HLS_manager>(AppM)->get_HLS(function_id)->Rsch &&
123  }
124  else
125 #endif
126  {
128  }
129 }
130 
132 {
133  const auto TM = AppM->get_tree_manager();
134  const auto tree_man = tree_manipulationRef(new tree_manipulation(TM, parameters, AppM));
135  const auto f_node = TM->CGetTreeNode(function_id);
136  const auto ret_type = tree_helper::GetFunctionReturnType(f_node);
137  const auto fd = GetPointerS<const function_decl>(f_node);
138  const auto sl = GetPointerS<statement_list>(GET_NODE(fd->body));
139 
140  const auto create_return_and_fix_cfg = [&](const tree_nodeRef& new_gr, const blocRef& pred_block,
141  const blocRef& curr_bb) -> void {
142  const auto bb_index = curr_bb->number;
143  if(pred_block->list_of_succ.size() == 1)
144  {
145  pred_block->PushBack(new_gr, AppM);
146  pred_block->list_of_succ.erase(
147  std::find(pred_block->list_of_succ.begin(), pred_block->list_of_succ.end(), bb_index));
148  pred_block->list_of_succ.push_back(curr_bb->list_of_succ.front());
149  }
150  else
151  {
152  const auto new_basic_block_index = (sl->list_of_bloc.rbegin())->first + 1;
154  "---Created BB" + STR(new_basic_block_index) + " as new successor of BB" +
155  STR(pred_block->number));
156  const auto new_block = blocRef(new bloc(new_basic_block_index));
157  sl->list_of_bloc[new_basic_block_index] = new_block;
158  new_block->loop_id = curr_bb->loop_id;
159  new_block->SetSSAUsesComputed();
160  new_block->schedule = curr_bb->schedule;
161  new_block->PushBack(new_gr, AppM);
163  new_block->list_of_pred.push_back(pred_block->number);
165  new_block->list_of_succ.push_back(curr_bb->list_of_succ.front());
167  pred_block->list_of_succ.erase(
168  std::find(pred_block->list_of_succ.begin(), pred_block->list_of_succ.end(), bb_index));
169  pred_block->list_of_succ.push_back(new_basic_block_index);
170  if(pred_block->true_edge == bb_index)
171  {
172  pred_block->true_edge = new_basic_block_index;
173  }
174  if(pred_block->false_edge == bb_index)
175  {
176  pred_block->false_edge = new_basic_block_index;
177  }
179  if(pred_block->CGetStmtList().size())
180  {
181  const auto pred_last_stmt = GET_NODE(pred_block->CGetStmtList().back());
182  if(pred_last_stmt->get_kind() == gimple_multi_way_if_K)
183  {
184  const auto gmwi = GetPointerS<gimple_multi_way_if>(pred_last_stmt);
185  for(auto& cond : gmwi->list_of_cond)
186  {
187  if(cond.second == bb_index)
188  {
189  cond.second = new_basic_block_index;
190  }
191  }
192  }
193  }
194  }
195  };
196 
197  const auto list_of_bloc = sl->list_of_bloc;
198  bool modified = false;
199  for(const auto& bbi_bb : list_of_bloc)
200  {
201  auto& bb = bbi_bb.second;
203  "--- Considering BB" + STR(bb->number) + " " + STR(bb->CGetPhiList().size()) + " " +
204  STR(bb->CGetStmtList().size()));
205  if(bb->list_of_pred.size() > 1 && bb->CGetPhiList().size() == 1 && bb->CGetStmtList().size() == 1)
206  {
207  const auto stmt = GET_CONST_NODE(bb->CGetStmtList().front());
208  if(stmt->get_kind() == gimple_return_K)
209  {
210  const auto bb_index = bb->number;
211  const auto gp = GetPointerS<const gimple_phi>(GET_CONST_NODE(bb->CGetPhiList().front()));
212  const auto gr = GetPointerS<const gimple_return>(stmt);
213  if(gr->op && GET_INDEX_NODE(gp->res) == GET_INDEX_NODE(gr->op))
214  {
216  "--- There is a split return possible at BB" + STR(bb_index));
217  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "--- Create return statement based of def edges");
218  for(const auto& def_edge : gp->CGetDefEdgesList())
219  {
220  const auto new_gr =
221  tree_man->create_gimple_return(ret_type, def_edge.first, function_id, BUILTIN_SRCP);
222  auto& pred_block = sl->list_of_bloc.at(def_edge.second);
223  create_return_and_fix_cfg(new_gr, pred_block, bb);
224  }
225  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Removing BB" + STR(bb_index));
226  bb->RemovePhi(bb->CGetPhiList().front());
227  bb->RemoveStmt(bb->CGetStmtList().front(), AppM);
228  sl->list_of_bloc.erase(bb_index);
229  modified = true;
230  }
231  else if(gp->virtual_flag)
232  {
234  "--- There is a split return possible at BB" + STR(bb_index));
235  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "--- Create return statement based of def edges");
236  for(const auto& def_edge : gp->CGetDefEdgesList())
237  {
238  const auto new_gr = tree_man->create_gimple_return(ret_type, gr->op, function_id, BUILTIN_SRCP);
239  GetPointerS<gimple_return>(GET_NODE(new_gr))->AddVuse(def_edge.first);
240  const auto& pred_block = sl->list_of_bloc.at(def_edge.second);
241  create_return_and_fix_cfg(new_gr, pred_block, bb);
242  }
243  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Removing BB" + STR(bb_index));
244  bb->RemovePhi(bb->CGetPhiList().front());
245  bb->RemoveStmt(bb->CGetStmtList().front(), AppM);
246  sl->list_of_bloc.erase(bb_index);
247  modified = true;
248  }
249  }
250  }
251  else if(bb->list_of_pred.size() > 1 && bb->CGetPhiList().size() == 0 && bb->CGetStmtList().size() == 1)
252  {
253  const auto bb_index = bb->number;
254  const auto stmt = GET_CONST_NODE(bb->CGetStmtList().front());
255  if(stmt->get_kind() == gimple_return_K)
256  {
257  const auto gr = GetPointerS<const gimple_return>(stmt);
258  for(const auto& pred_block_index : bb->list_of_pred)
259  {
260  const auto& pred_block = sl->list_of_bloc.at(pred_block_index);
261  const auto new_gr = tree_man->create_gimple_return(ret_type, gr->op, function_id, BUILTIN_SRCP);
262  create_return_and_fix_cfg(new_gr, pred_block, bb);
263  }
264  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Removing BB" + STR(bb_index));
265  bb->RemoveStmt(bb->CGetStmtList().front(), AppM);
266  sl->list_of_bloc.erase(bb_index);
267  modified = true;
268  }
269  }
270  }
271 
272  if(modified)
273  {
274  function_behavior->UpdateBBVersion();
276  }
278 }
#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.
Data structure representing the entire HLS information.
This struct specifies the field bloc (basic block).
#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.
Step successfully executed.
#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
RelationshipType
The relationship type.
Source must be executed to satisfy target.
A simple interface to token object of the raw files.
Analysis step that optimize the phis starting from the IR.
#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.
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
HLSFlowStep_Type
Definition: hls_step.hpp:95
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
redefinition of set to manage ordered/unordered structures
#define GET_CONST_NODE(t)
Definition: tree_node.hpp:347
Classes specification of the tree_node data structures.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
Call graph hierarchy.
Class defining some useful functions to create tree nodes and to manipulate the tree manager...
#define DEBUG_LEVEL_NONE
no debugging print is performed.
SplitReturn(const ParameterConstRef _Param, const application_managerRef _AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
DesignFlowStep_Status InternalExec() override
Restructures the unstructured code.
This file collects some utility functions.
#define BUILTIN_SRCP
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
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.
Wrapper to call graph.
int debug_level
The debug level.
Data structure definition for high-level synthesis flow.
static tree_nodeConstRef GetFunctionReturnType(const tree_nodeConstRef &function, bool void_as_null=true)
Return the return type of a function.
~SplitReturn() override
Destructor.
This class creates a layer to add nodes and to manipulate the tree_nodes manager. ...
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.
Class specification of the manager of the tree structures extracted from the raw file.
const FunctionBehaviorRef function_behavior
The function behavior of the function to be analyzed.
int sl
Definition: adpcm.c:105

Generated on Mon Feb 12 2024 13:02:52 for PandA-2024.02 by doxygen 1.8.13