PandA-2024.02
extract_omp_for.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) 2015-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  */
42 #include "extract_omp_for.hpp"
44 
46 #include "Parameter.hpp"
47 
49 #include "loop.hpp"
50 #include "loops.hpp"
51 
53 #include "application_manager.hpp"
54 #include "basic_block.hpp"
55 #include "function_behavior.hpp"
56 
58 #include "design_flow_graph.hpp"
59 #include "design_flow_manager.hpp"
60 
62 #include "custom_set.hpp"
63 #include <utility>
64 
66 #include "behavioral_helper.hpp"
67 #include "tree_basic_block.hpp"
68 #include "tree_manager.hpp"
69 #include "tree_node.hpp"
70 #include "tree_reindex.hpp"
71 
73 #include "dbgPrintHelper.hpp"
74 #include "utility.hpp"
75 
76 ExtractOmpFor::ExtractOmpFor(const application_managerRef _AppM, unsigned int _function_id,
77  const DesignFlowManagerConstRef _design_flow_manager, const ParameterConstRef _parameters)
78  : FunctionFrontendFlowStep(_AppM, _function_id, EXTRACT_OMP_FOR, _design_flow_manager, _parameters)
79 {
80  debug_level = parameters->get_class_debug_level(GET_CLASS(*this), DEBUG_LEVEL_NONE);
81 }
82 
84 
87 {
88  const auto TM = AppM->get_tree_manager();
90  switch(relationship_type)
91  {
93  {
94  relationships.insert(std::make_pair(LOOPS_ANALYSIS_BAMBU, SAME_FUNCTION));
95  break;
96  }
98  {
99  break;
100  }
102  {
103  break;
104  }
105  default:
106  {
107  THROW_UNREACHABLE("");
108  }
109  }
110  return relationships;
111 }
112 
114 {
115 }
116 
118 {
119  return bb_version == 0;
120 }
121 
123 {
124  const auto behavioral_helper = function_behavior->CGetBehavioralHelper();
125  const auto basic_block_graph = function_behavior->CGetBBGraph(FunctionBehavior::BB);
126  const auto basic_block_graph_info = basic_block_graph->CGetBBGraphInfo();
127  const auto TM = AppM->get_tree_manager();
128  if(behavioral_helper->GetOmpForDegree() or behavioral_helper->IsOmpBodyLoop())
129  {
131  }
133  (!parameters->IsParameter("print-dot-FF") || parameters->GetParameter<unsigned int>("print-dot-FF")))
134  {
135  WriteBBGraphDot("BB_Before_" + GetName() + ".dot");
136  PrintTreeManager(true);
137  }
138  bool changed = false;
139  const auto loops = function_behavior->CGetLoops();
140  for(const auto& loop : loops->GetList())
141  {
142  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Analyzing loop " + STR(loop->GetId()));
143  if(not(loop->loop_type & DOALL_LOOP))
144  {
145  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Skipped loop " + STR(loop->GetId()));
146  continue;
147  }
148  CustomUnorderedSet<vertex> basic_blocks;
149  loop->get_recursively_bb(basic_blocks);
150  THROW_ASSERT(basic_blocks.size() >= 1, "Unexpected pattern");
151  if(basic_blocks.size() == 1)
152  {
153  for(const auto basic_block : basic_blocks)
154  {
155  const auto bb_node_info = basic_block_graph->CGetBBNodeInfo(basic_block);
157  "-->Analyzing BB" + STR(bb_node_info->block->number));
158  if(bb_node_info->block->CGetStmtList().size() == 1)
159  {
160  THROW_ERROR("BB" + STR(bb_node_info->block->number) + " has only one statement");
161  }
162  else
163  {
164  const auto list_of_stmt = bb_node_info->block->CGetStmtList();
165  THROW_ASSERT(list_of_stmt.size() >= 2, "Unexpected pattern");
166  const auto first_node = list_of_stmt.front();
167  const auto call = GetPointer<const gimple_call>(GET_NODE(first_node));
168  if(not call)
169  {
170  THROW_ERROR("First operation of loop body is " + first_node->ToString());
171  }
172  auto stmt_it = list_of_stmt.begin();
173  ++stmt_it;
174  const auto second_node = *stmt_it;
175  const auto ga = GetPointer<const gimple_assign>(GET_NODE(second_node));
176  if(not ga)
177  {
178  THROW_ERROR("Second operation of loop body is " + second_node->ToString());
179  }
180  const auto pe = GetPointer<const plus_expr>(GET_NODE(ga->op1));
181  if(not pe)
182  {
183  THROW_ERROR("Second operation of loop body is " + second_node->ToString());
184  }
185  const auto induction_variable = GetPointer<const ssa_name>(GET_NODE(ga->op0));
186  THROW_ASSERT(loop->main_iv, "");
187  if(not induction_variable or induction_variable->index != loop->main_iv)
188  {
189  THROW_ERROR("Induction variable is " + TM->get_tree_node_const(loop->main_iv)->ToString() +
190  " - Second operation of loop body is " + second_node->ToString());
191  }
192  const auto call_op = GetPointer<const addr_expr>(GET_NODE(call->fn));
193  if(not call_op)
194  {
195  THROW_ERROR("First operation of loop body is " + first_node->ToString());
196  }
197  auto called_function = GetPointer<function_decl>(GET_NODE(call_op->op));
198  if(not called_function)
199  {
200  THROW_ERROR("First operation of loop body is " + first_node->ToString());
201  }
202  called_function->omp_body_loop = true;
203  }
204  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Analyzed BB" + STR(bb_node_info->block->number));
205  }
206  if(loops->GetList().size() == 2)
207  {
208  VertexIterator basic_block, basic_block_end;
209  for(boost::tie(basic_block, basic_block_end) = boost::vertices(*basic_block_graph);
210  basic_block != basic_block_end; basic_block++)
211  {
212  const auto basic_block_info = basic_block_graph->CGetBBNodeInfo(*basic_block);
213  if(*basic_block == basic_block_graph_info->entry_vertex or
214  *basic_block == basic_block_graph_info->exit_vertex)
215  {
216  continue;
217  }
218  if(basic_block_info->loop_id)
219  {
220  continue;
221  }
222  if(not basic_block_info->block->CGetStmtList().size())
223  {
224  continue;
225  }
226  if(boost::in_degree(*basic_block, *basic_block_graph) == 1 &&
227  boost::source(*(boost::in_edges(*basic_block, *basic_block_graph).first), *basic_block_graph) ==
228  basic_block_graph_info->entry_vertex)
229  {
230  const auto& stm_list = basic_block_info->block->CGetStmtList();
231  if(stm_list.size() != 3)
232  {
233  THROW_ERROR("unexpected pattern");
234  }
235  auto stmt_iter = stm_list.begin();
236  const auto ga1 = GetPointer<const gimple_assign>(GET_NODE(*stmt_iter));
237  if(not ga1)
238  {
239  THROW_ERROR("First statement of pre-loop BB is " + (*stmt_iter)->ToString());
240  }
241  const auto nop1 = GetPointer<const nop_expr>(GET_NODE(ga1->op1));
242  if(not nop1)
243  {
244  THROW_ERROR("First statement of pre-loop BB is " + (*stmt_iter)->ToString());
245  }
246  ++stmt_iter;
247  const auto ga2 = GetPointer<const gimple_assign>(GET_NODE(*stmt_iter));
248  if(not ga2)
249  {
250  THROW_ERROR("Second statement of pre-loop BB is " + (*stmt_iter)->ToString());
251  }
252  if(GET_NODE(ga2->op1)->get_kind() == gt_expr_K)
253  {
254  continue;
255  }
256  else
257  {
258  THROW_ERROR("Second statement of pre-loop BB is " + (*stmt_iter)->ToString());
259  }
260  }
261  for(const auto& statement : basic_block_info->block->CGetStmtList())
262  {
263  const auto gr = GetPointer<const gimple_return>(GET_NODE(statement));
264  if(gr and not gr->op)
265  {
266  continue;
267  }
268  THROW_ERROR(statement->ToString());
269  }
270  }
271  auto fd = GetPointer<function_decl>(TM->get_tree_node_const(function_id));
272  function_behavior->UpdateBBVersion();
273  fd->omp_for_wrapper = parameters->getOption<size_t>(OPT_num_accelerators);
274  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Skipped loop " + STR(loop->GetId()));
275  break;
276  }
277  }
278  if(basic_blocks.size() == 2)
279  {
280  for(const auto basic_block : basic_blocks)
281  {
282  if(basic_block == loop->GetHeader())
283  {
284  continue;
285  }
286  const auto bb_node_info = basic_block_graph->CGetBBNodeInfo(basic_block);
288  "-->Analyzing BB" + STR(bb_node_info->block->number));
289  const auto list_of_stmt = bb_node_info->block->CGetStmtList();
290  const auto first_node = list_of_stmt.front();
291  const auto second_node = [&]() -> tree_nodeRef {
292  if(list_of_stmt.size() == 1)
293  {
294  const auto header_node_info = basic_block_graph->CGetBBNodeInfo(loop->GetHeader());
295  const auto header_list_of_stmt = header_node_info->block->CGetStmtList();
296  if(header_list_of_stmt.size() != 3)
297  {
298  THROW_ERROR("Unexpected pattern in header. Number of operations is " +
299  STR(header_list_of_stmt.size()));
300  }
301  auto stmt_it = header_list_of_stmt.begin();
302  stmt_it++;
303  return *stmt_it;
304  }
305  else if(list_of_stmt.size() == 2)
306  {
307  return list_of_stmt.back();
308  }
309  else
310  {
311  THROW_ERROR("Pattern not supported");
312  return tree_nodeRef();
313  }
314  }();
315  const auto call = GetPointer<const gimple_call>(GET_NODE(first_node));
316  if(not call)
317  {
318  THROW_ERROR("First operation of loop body is " + first_node->ToString());
319  }
320  const auto ga = GetPointer<const gimple_assign>(GET_NODE(second_node));
321  if(not ga)
322  {
323  THROW_ERROR("Second operation of loop body is " + second_node->ToString());
324  }
325  const auto pe = GetPointer<const plus_expr>(GET_NODE(ga->op1));
326  if(not pe)
327  {
328  THROW_ERROR("Second operation of loop body is " + second_node->ToString());
329  }
330  const auto induction_variable = GetPointer<const ssa_name>(GET_NODE(pe->op0));
331  THROW_ASSERT(loop->main_iv, "");
332  if(not induction_variable or induction_variable->index != loop->main_iv)
333  {
334  THROW_ERROR("Induction variable is " + TM->get_tree_node_const(loop->main_iv)->ToString() +
335  " - Second operation of loop body is " + second_node->ToString());
336  }
337  const auto call_op = GetPointer<const addr_expr>(GET_NODE(call->fn));
338  if(not call_op)
339  {
340  THROW_ERROR("First operation of loop body is " + first_node->ToString());
341  }
342  auto called_function = GetPointer<function_decl>(GET_NODE(call_op->op));
343  if(not called_function)
344  {
345  THROW_ERROR("First operation of loop body is " + first_node->ToString());
346  }
347  called_function->omp_body_loop = true;
348  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Analyzed BB" + STR(bb_node_info->block->number));
349  }
350  if(loops->GetList().size() == 2)
351  {
352  VertexIterator basic_block, basic_block_end;
353  for(boost::tie(basic_block, basic_block_end) = boost::vertices(*basic_block_graph);
354  basic_block != basic_block_end; basic_block++)
355  {
356  const auto basic_block_info = basic_block_graph->CGetBBNodeInfo(*basic_block);
357  if(*basic_block == basic_block_graph_info->entry_vertex or
358  *basic_block == basic_block_graph_info->exit_vertex)
359  {
360  continue;
361  }
362  if(basic_block_info->loop_id)
363  {
364  continue;
365  }
366  if(not basic_block_info->block->CGetStmtList().size())
367  {
368  continue;
369  }
370  for(const auto& statement : basic_block_info->block->CGetStmtList())
371  {
372  const auto gr = GetPointer<const gimple_return>(GET_NODE(statement));
373  if(gr and not gr->op)
374  {
375  continue;
376  }
377  THROW_ERROR(statement->ToString());
378  }
379  }
380  auto fd = GetPointer<function_decl>(TM->get_tree_node_const(function_id));
381  function_behavior->UpdateBBVersion();
382  fd->omp_for_wrapper = parameters->getOption<size_t>(OPT_num_accelerators);
383  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Skipped loop " + STR(loop->GetId()));
384  break;
385  }
386  }
387  THROW_ERROR("To be implemented");
388  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Analyzed loop " + STR(loop->GetId()));
389  }
391 }
#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.
#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.
#define DEBUG_LEVEL_PEDANTIC
very verbose debugging print is performed.
Step successfully executed.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
Definition of the class representing a generic C application.
std::string GetName() const override
Return the name of this design step.
RelationshipType
The relationship type.
Source must be executed to satisfy target.
void PrintTreeManager(const bool before) const
Dump the tree manager.
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...
~ExtractOmpFor() override
Destructor.
#define STR(s)
Macro which performs a lexical_cast to a string.
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
void WriteBBGraphDot(const std::string &filename) const
Write the current version of statement list in dot format.
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 to describe design flow graph.
redefinition of set to manage ordered/unordered structures
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.
This file collects some utility functions and macros.
#define DEBUG_LEVEL_NONE
no debugging print is performed.
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
Definition: exceptions.hpp:263
Wrapper of design_flow.
const unsigned int function_id
The index of the function to be analyzed.
Analysis step extracting openmp for.
const application_managerRef AppM
The application manager.
Class specification of the tree_reindex support class.
Class specification of the basic_block structure.
bool HasToBeExecuted() const override
Check if this step has actually to be executed.
void Initialize() override
Initialize the step (i.e., like a constructor, but executed just before exec.
interface of a loop
ExtractOmpFor(const application_managerRef _AppM, unsigned int function_id, const DesignFlowManagerConstRef design_flow_manager, const ParameterConstRef parameters)
Constructor.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
interface of loops finding algorithm
this class is used to manage the command-line or XML options.
refcount< tree_node > tree_nodeRef
RefCount type definition of the tree_node class structure.
Definition: tree_node.hpp:212
#define DOALL_LOOP
parallelizable for loop
Definition: loop.hpp:132
int debug_level
The debug level.
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.
DesignFlowStep_Status InternalExec() override
Restructures the unstructured code.
#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