PandA-2024.02
remove_ending_if.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  */
89 #include "remove_ending_if.hpp"
90 #include "Parameter.hpp"
92 #include "application_manager.hpp"
93 #include "basic_block.hpp"
94 #include "behavioral_helper.hpp"
95 #include "call_graph.hpp"
96 #include "call_graph_manager.hpp"
97 #include "custom_set.hpp"
99 #include "dbgPrintHelper.hpp" // for DEBUG_LEVEL_
100 #include "design_flow_manager.hpp"
101 #include "ext_tree_node.hpp"
102 #include "function_behavior.hpp"
103 #include "hls.hpp"
104 #include "hls_constraints.hpp"
105 #include "hls_manager.hpp"
106 #include "hls_step.hpp"
107 #include "schedule.hpp"
108 #include "string_manipulation.hpp" // for GET_CLASS
109 #include "token_interface.hpp"
110 #include "tree_basic_block.hpp"
111 #include "tree_helper.hpp"
112 #include "tree_manager.hpp"
113 #include "tree_manipulation.hpp"
114 #include "tree_reindex.hpp"
115 #include <cstdlib>
116 #include <fstream>
117 
120  unsigned int _function_id, const DesignFlowManagerConstRef _design_flow_manager)
121  : FunctionFrontendFlowStep(_AppM, _function_id, REMOVE_ENDING_IF, _design_flow_manager, _parameters),
122  sl(nullptr),
123  schedule(ScheduleRef())
124 {
125  debug_level = parameters->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
126 }
127 
129 
132 {
134  switch(relationship_type)
135  {
137  {
138  relationships.insert(std::make_pair(SWITCH_FIX, SAME_FUNCTION));
139  relationships.insert(std::make_pair(BLOCK_FIX, SAME_FUNCTION));
140  relationships.insert(std::make_pair(USE_COUNTING, SAME_FUNCTION));
141  break;
142  }
144  {
146  {
147  relationships.insert(std::make_pair(PHI_OPT, SAME_FUNCTION));
148  }
149  break;
150  }
152  {
153  relationships.insert(std::make_pair(PHI_OPT, SAME_FUNCTION));
154  break;
155  }
156  default:
157  {
158  THROW_UNREACHABLE("");
159  }
160  }
161  return relationships;
162 }
163 
165 {
166  TM = AppM->get_tree_manager();
168  const auto temp = TM->get_tree_node_const(function_id);
169  auto fd = GetPointer<function_decl>(temp);
170  sl = GetPointer<statement_list>(GET_NODE(fd->body));
171 #if HAVE_ILP_BUILT
172  if(parameters->getOption<HLSFlowStep_Type>(OPT_scheduling_algorithm) == HLSFlowStep_Type::SDC_SCHEDULING and
173  GetPointer<const HLS_manager>(AppM) and GetPointer<const HLS_manager>(AppM)->get_HLS(function_id) and
174  GetPointer<const HLS_manager>(AppM)->get_HLS(function_id)->Rsch)
175  {
176  schedule = GetPointer<const HLS_manager>(AppM)->get_HLS(function_id)->Rsch;
177  }
178 #endif
179 }
180 
182 {
184 #if HAVE_ILP_BUILT
185  if(parameters->getOption<HLSFlowStep_Type>(OPT_scheduling_algorithm) == HLSFlowStep_Type::SDC_SCHEDULING and
186  GetPointer<const HLS_manager>(AppM) and GetPointer<const HLS_manager>(AppM)->get_HLS(function_id) and
187  GetPointer<const HLS_manager>(AppM)->get_HLS(function_id)->Rsch)
188  {
190  }
191 #endif
192  return false;
193 }
194 
196 {
197  bool bb_modified = false;
198  const auto HLS = GetPointer<const HLS_manager>(AppM)->get_HLS(function_id);
199  const auto clock_period = HLS->HLS_C->get_clock_period();
200  const auto clock_period_margin = HLS->allocation_information->GetClockPeriodMargin();
201  const auto net_clock_period = clock_period - clock_period_margin;
202  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Remove ending if is starting");
203  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Looking for feasible blocs");
204  for(const auto& block : sl->list_of_bloc)
205  {
206  if(not AppM->ApplyNewTransformation())
207  {
209  "---Skipping remaining transformations because of reached limit of cfg transformations");
210  break;
211  }
213  "---Checking if a bloc has just 2 incoming and 1 outcoming");
214  // The block should have 2 inc arcs from if and then BB and one outgoing to EXIT
215  if(block.second->list_of_succ.size() == 1 and block.second->list_of_pred.size() == 2)
216  {
217  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Checking if the successor is the EXIT bloc");
218  const auto successor_id = block.second->list_of_succ.front();
219  // Control on the successor
220  if(successor_id == bloc::EXIT_BLOCK_ID)
221  {
223  // Control if the BB has just the return stmt
224  if(block.second->CGetStmtList().size() == 1)
225  {
226  auto last_stmt = GET_NODE(block.second->CGetStmtList().back());
227  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---The block has just 1 statement");
228  if(last_stmt->get_kind() == gimple_return_K)
229  {
230  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Feasible block found");
231  auto block_pred1 = *(sl->list_of_bloc.find(block.second->list_of_pred.front()));
232  auto block_pred2 = *(sl->list_of_bloc.find(block.second->list_of_pred.back()));
233  // Check if the two pred of block are the BB of the searched pattern
234  // The BB containing IF should has: 2 outgoing arcs, one into "block"
235  // and one into bloc_pred2
236  const std::pair<blocRef, blocRef> if_succ = [&]() -> std::pair<blocRef, blocRef> {
237  const blocRef if_block = [&]() -> blocRef {
239  if(block_pred1.second->list_of_succ.size() == 2 and block_pred1.second->loop_id == 0)
240  {
241  return block_pred1.second;
242  }
243  if(block_pred2.second->list_of_succ.size() == 2 and block_pred2.second->loop_id == 0)
244  {
245  return block_pred2.second;
246  }
247  return blocRef();
248  }();
249  if(not if_block)
250  {
251  return std::pair<blocRef, blocRef>(blocRef(), blocRef());
252  }
253  const auto dep_block =
254  block_pred1.first == if_block->number ? block_pred2.second : block_pred1.second;
255  if(dep_block->list_of_pred.size() != 1 or dep_block->list_of_succ.size() != 1 or
256  dep_block->list_of_pred.front() != if_block->number)
257  {
258  return std::pair<blocRef, blocRef>(blocRef(), blocRef());
259  }
260  return std::pair<blocRef, blocRef>(if_block, dep_block);
261  }();
262  if(if_succ.first and if_succ.second)
263  {
264  const auto if_block = if_succ.first;
265  const auto dep_block = if_succ.second;
266  const bool to_be_removed = [&]() -> bool {
267  if(dep_block->CGetStmtList().empty())
268  {
269  return false;
270  }
272  double max = 0.0;
273  for(const auto& stmt : dep_block->CGetStmtList())
274  {
275  if(schedule->GetStartingTime(stmt->index) < min)
276  {
277  min = schedule->GetStartingTime(stmt->index);
278  }
279  if(schedule->GetEndingTime(stmt->index) > max)
280  {
281  max = schedule->GetEndingTime(stmt->index);
282  }
283  if((GET_NODE(stmt)->get_kind() == gimple_call_K) ||
284  ((GetPointer<const gimple_assign>(GET_NODE(stmt))) &&
285  ((GET_NODE(GetPointer<const gimple_assign>(GET_NODE(stmt))->op1)->get_kind() ==
286  call_expr_K) ||
287  (GET_NODE(GetPointer<const gimple_assign>(GET_NODE(stmt))->op1)->get_kind() ==
288  aggr_init_expr_K))))
289  {
290  return false;
291  }
292  if(GetPointer<const gimple_node>(GET_NODE(stmt))->vdef)
293  {
294  return false;
295  }
296  }
297  if((max - min) > net_clock_period)
298  {
299  return false;
300  }
301  return true;
302  }();
303  // Remove from the "then" BB and add to the "if" BB
304  if(to_be_removed)
305  {
306  while(not dep_block->CGetStmtList().empty())
307  {
308  auto current_stmt = dep_block->CGetStmtList().front();
309  dep_block->RemoveStmt(current_stmt, AppM);
310  if_block->PushBack(current_stmt, AppM);
311  }
312 
313  bb_modified = true;
314  AppM->RegisterTransformation(GetName(), last_stmt);
315  }
316  }
317  else
318  {
319  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---pattern NOT found");
320  }
321  }
322  }
323  else
324  {
325  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---The block has more than 1 statement");
326  }
327  }
328  else
329  {
330  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---It is not the EXIT");
331  }
332  }
333  else
334  {
336  "---Skipped this bloc, because has more or less incoming/outcoming arcs than expected");
337  continue;
338  }
339  }
340 
341  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Remove ending if has finished");
342 
343  bb_modified ? function_behavior->UpdateBBVersion() : 0;
345 }
#define GET_NODE(t)
Macro used to hide implementation details when accessing a tree_node from another tree_node...
Definition: tree_node.hpp:343
tree_managerRef TM
The tree manager.
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
Data structure representing the entire HLS information.
#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.
tree_manipulationRef tree_man
The tree manipulation.
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
std::string GetName() const override
Return the name of this design step.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
A simple interface to token object of the raw files.
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
static const unsigned int EXIT_BLOCK_ID
constant identifying the exit basic block
#define min(x, y)
RemoveEndingIf(const ParameterConstRef _Param, const application_managerRef _AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager)
Constructor.
Data structure describing a basic block at tree level.
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
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.
Auxiliary methods for manipulating string.
#define max
Definition: backprop.h:17
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
std::string GetSignature() const override
Return the signature of this step.
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
Data structure used to store the schedule of the operations.
DesignFlowStep_Status InternalExec() override
Restructures the unstructured code.
HLSFlowStep_Type
Definition: hls_step.hpp:95
redefinition of set to manage ordered/unordered structures
const Wrefcount< const DesignFlowManager > design_flow_manager
The design flow manager.
const ParameterConstRef parameters
Set of input parameters.
DesignFlowStep_Status
The status of a step.
This package is used by all HLS packages to manage resource constraints and characteristics.
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec.
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.
Wrapper of design_flow.
statement_list * sl
The statement list of the analyzed function.
Data structure definition for HLS constraints.
This struct specifies the block node.
Definition: tree_node.hpp:1820
This file collects some utility functions.
double GetStartingTime(const unsigned int operation) const
Return the starting time of the operation.
Definition: schedule.cpp:1151
refcount< T > lock() const
Definition: refcount.hpp:212
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.
File used to compute the topological sort in a cyclic graph.
Class specification of the basic_block structure.
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.
double GetEndingTime(const unsigned int operation) const
Return the starting time of the operation.
Definition: schedule.cpp:1140
Data structure definition for high-level synthesis flow.
~RemoveEndingIf() override
Destructor.
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.
ScheduleRef schedule
The scheduling solution.
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