PIPS
pocc_prettyprinter.c
Go to the documentation of this file.
1 #ifdef HAVE_CONFIG_H
2  #include "pips_config.h"
3 #endif
4 
5 
6 #include <stdio.h>
7 #include <ctype.h>
8 #include <string.h>
9 #include "boolean.h"
10 
11 
12 #include "genC.h"
13 #include "linear.h"
14 #include "ri.h"
15 #include "effects.h"
16 #include "database.h"
17 #include "misc.h"
18 #include "text.h"
19 #include "text-util.h"
20 #include "ri-util.h"
21 #include "accel-util.h"
22 #include "effects-util.h"
23 
24 #include "effects-generic.h"
25 #include "effects-simple.h"
26 
27 #include "pipsdbm.h"
28 #include "resources.h"
29 #include "control.h"
30 #include "conversion.h"
31 #include "properties.h"
32 #include "transformations.h"
33 
34 /*static_control*/
35 #include "arithmetique.h"
36 #include "vecteur.h"
37 #include "contrainte.h"
38 #include "ray_dte.h"
39 #include "sommet.h"
40 #include "sg.h"
41 #include "sc.h"
42 #include "polyedre.h"
43 #include "matrix.h"
44 
45 /* Pips includes */
46 #include "ri.h"
47 /* Types arc_label and vertex_label must be defined although they are
48  not used */
49 typedef void * arc_label;
50 typedef void * vertex_label;
51 #include "graph.h"
52 #include "paf_ri.h"
53 #include "database.h"
54 #include "ri-util.h"
55 #include "constants.h"
56 #include "misc.h"
57 #include "control.h"
58 #include "text-util.h"
59 #include "pipsdbm.h"
60 #include "resources.h"
61 #include "paf-util.h"
62 #include "static_controlize.h"
63 #include "pocc-interface.h"
64 
65 // Global variable
67 
68 static bool are_stmts_eq (statement stmt1, statement stmt2) {
69  return statement_number(stmt1) == statement_number(stmt2);
70 }
71 
72 /* Look for a loop in a statement */
74  if(statement_sequence_p(s)) {
76  sequence seq = instruction_sequence(inst);
77  list stmts = sequence_statements(seq);
78  FOREACH(statement, stmt, stmts) {
80  return true;
81  }
82  }
83  else {
85  return true;
86  }
87  return false;
88 }
89 
90 /* Checks if a test contains a loop */
92  if (!statement_test_p(s))
93  return false;
95  test t = instruction_test(inst);
96  statement true_body = test_true(t);
97  statement false_body = test_false(t);
99  return true;
100  else
101  return false;
102 }
103 
104 /* Checks if there is at least one loop in the sequence.
105  If not it removes the previously added pragma on the last_added_pragma statement.
106 */
107 bool is_SCOP_rich (sequence seq, statement last_added_pragma, statement curStmt, bool* pragma_added_p) {
108  // Should not occur but just in case
109  if(!statement_with_pragma_p(last_added_pragma)) {
110  return false;
111  }
112  bool startSearch = false;
113  list stmts = sequence_statements(seq);
114  FOREACH(statement, stmt, stmts) {
115  // We start searching in sequence from the current statement
116  if (are_stmts_eq(stmt, last_added_pragma)) {
117  startSearch = true;
118  }
119  // We stop searching when we are at the current statement in the sequence
120  else if (are_stmts_eq(stmt, curStmt)) {
121  startSearch = false;
122  }
123  if (startSearch) {
124  // If the statement is a loop or if it is a test containing a loop
126  return true;
127  }
128  }
129  }
130  // Clearing pragma
131  clear_pragma_on_statement(last_added_pragma);
132  *pragma_added_p = false;
133  return false;
134 }
135 
136 /* Check if the SCoP is rich, add pragma "endscop" before stmt and change the value of pragma_added_p */
137 static void insert_endscop_before_stmt(statement stmt, bool* pragma_added_p, sequence seqInst, list stmts, statement last_added_pragma) {
138  if (!is_SCOP_rich(seqInst, last_added_pragma, stmt, pragma_added_p))
139  return;
141  add_pragma_str_to_statement(endscop, "endscop", true);
142  *pragma_added_p = false;
143  sequence_statements(seqInst) = gen_insert_before(endscop, stmt, stmts);
144 }
145 
146 /* Check if the SCoP is rich, add pragma "endscop" after stmt and change the value of pragma_added_p */
147 static void insert_endscop_after_stmt(statement stmt, bool* pragma_added_p, sequence seqInst, statement last_added_pragma) {
148  if (!is_SCOP_rich(seqInst, last_added_pragma, stmt, pragma_added_p))
149  return;
151  add_pragma_str_to_statement(endscop, "endscop", true);
152  *pragma_added_p = false;
153  gen_insert_after(endscop, stmt, sequence_statements(seqInst));
154 }
155 
156 /*Insert a pragma "endscop" before/after the statement stmt
157  Insert a ";" statement in sequence with stmt thereby converting stmt to a sequence */
158 static void insert_endscop_in_sequence(statement stmt, bool* pragma_added_p, bool insertBefore) {
160  add_pragma_str_to_statement(endscop, "endscop", true);
161  *pragma_added_p = false;
162  // Insert the continue statement after the statement parameter, thereby creating a sequence
163  insert_statement(stmt, endscop, insertBefore);
164 }
165 
166 /* Add a "scop" pragma to the statement stmt. Set pragma_added_p to true */
167 static void add_to_stmt(statement stmt, bool* pragma_added_p) {
168  add_pragma_str_to_statement(stmt, "scop", true);
169  *pragma_added_p = true;
170 }
171 
172 /* Returns true if the instruction is a subroutine */
174  // Is the call's entity a functional type ?
175  bool testFunction = false;
176  // If it is a functional type, is the functional's result type void ?
177  bool isVoid = false;
178  if (instruction_call_p(inst)) {
180  if(testFunction) {
182  }
183  }
184  return isVoid;
185 }
186 
187 /* Called recursively, place pragmas on statements according to SCoP conditions */
188 static void pragma_scop(statement s, bool pragma_added_p, bool in_loop_p) {
189  // The purpose of this variable is to keep track of the last stmt checked in the FOREACH loop.
190  // In case we go through the entire part of the code without finding any non-SCoP part, we go
191  // out of the FOREACH loop and add the end pragma to the last iterated statement
192  // The second variable is used to keep the place where we add the last pragma in order to be able
193  // to remove it if necessary
194  statement save_stmt = statement_undefined,
195  last_added_pragma = statement_undefined;
196 
197  instruction instTop = statement_instruction(s);
198 
199  switch (instruction_tag(instTop)) {
200  // If that instruction is a sequence, we go through the statements of the sequence and look for SCoP part
202  {
203  sequence seqInst = instruction_sequence(instTop);
204  list stmts = sequence_statements(seqInst);
205  FOREACH(statement, stmt, stmts) {
206  // The current statement is saved
207  save_stmt = stmt;
209  static_control sc;
210  switch (instruction_tag(inst)) {
211  case is_instruction_loop :
212  {
213  loop l = instruction_loop(inst);
214  // We test if the body of the loop is a SCoP
216  // If it is and we don't already have a pragma in the current "layer"
217  if (static_control_yes(sc) && !pragma_added_p) {
218  add_to_stmt(stmt, &pragma_added_p);
219  last_added_pragma = stmt;
220  }
221  // If it is not a SCoP and we already have a start pragma, that means we have reached
222  // the limit of our SCoP and therefore we put an end pragma
223  else if (!static_control_yes(sc) && pragma_added_p) {
224  // As adding a pragma to a statement is putting it on top of that statement, to place a
225  // pragma at the end of a statement means we have to put it on the next statement
226  // Here we will create an continue_statement (a ";"), add an end pragma to it and add it to
227  // the list representing the current sequence of the statement. Please note that the continue
228  // statement is added before the current statement (which is not SCoP)
229  insert_endscop_before_stmt(stmt, &pragma_added_p, seqInst, stmts, last_added_pragma);
230  // As the non-SCoP part is actually a loop, the body of that loop may contains SCoP, therefore we
231  // call the function on that subset of the code
232  pragma_scop(stmt, pragma_added_p, true);
233  }
234  // If the loop is not a SCoP and we do not already have a start pragma, we can call the function again on
235  // that subset of the code without having to take care of the current SCoP zone (as there is none)
236  else if (!static_control_yes(sc) && !pragma_added_p) {
237  pragma_scop(stmt, pragma_added_p, true);
238  }
239  }
240  break;
241  case is_instruction_test :
242  {
244  bool testStatic = static_control_yes(scCond);
245  // If the test is static control : the condition and both true and false body have to fit the conditions
246  if (testStatic && !pragma_added_p) {
247  add_to_stmt(stmt, &pragma_added_p);
248  last_added_pragma = stmt;
249  }
250  // If the test is not static, we close the current SCoP and go explore the true and false body
251  else if (!testStatic && pragma_added_p) {
252  insert_endscop_before_stmt(stmt, &pragma_added_p, seqInst, stmts, last_added_pragma);
253  pragma_scop(test_true(instruction_test(inst)), pragma_added_p, in_loop_p);
254  pragma_scop(test_false(instruction_test(inst)), pragma_added_p, in_loop_p);
255  }
256  else if (!testStatic && !pragma_added_p) {
257  pragma_scop(test_true(instruction_test(inst)), pragma_added_p, in_loop_p);
258  pragma_scop(test_false(instruction_test(inst)), pragma_added_p, in_loop_p);
259  }
260  }
261  break;
262  case is_instruction_call :
263  {
264  // Depending on this option we will consider function calls part of SCoP or not
265  bool across_call = get_bool_property("STATIC_CONTROLIZE_ACROSS_USER_CALLS");
266  if (return_statement_p(stmt) && pragma_added_p) {
267  insert_endscop_before_stmt(stmt, &pragma_added_p, seqInst, stmts, last_added_pragma);
268  }
269  else if ((!across_call && is_subroutine(inst)) || (across_call && !user_call_p(instruction_call(inst)))) {
270  if (pragma_added_p)
271  insert_endscop_before_stmt(stmt, &pragma_added_p, seqInst, stmts, last_added_pragma);
272  }
273  else if (!declaration_statement_p(stmt)) {
275  if (static_control_yes(sc) && !pragma_added_p) {
276  add_to_stmt(stmt, &pragma_added_p);
277  last_added_pragma = stmt;
278  }
279  else if (!static_control_yes(sc) && pragma_added_p) {
280  insert_endscop_before_stmt(stmt, &pragma_added_p, seqInst, stmts, last_added_pragma);
281  }
282  }
283  }
284  break;
285  default :
286  {
288  // If we already have a start pragma and the current statement is not SCoP or if it is a function call,
289  // that puts an end to our current SCoP and as we did above, we add the end pragma
290  bool isRoutine = is_subroutine(inst);
291  bool across_call = get_bool_property("STATIC_CONTROLIZE_ACROSS_USER_CALLS");
292  if (pragma_added_p && (!static_control_yes(sc) || (isRoutine && !across_call))) {
293  insert_endscop_before_stmt(stmt, &pragma_added_p, seqInst, stmts, last_added_pragma);
294  }
295  // We go explore this statement
296  pragma_scop(stmt, pragma_added_p, in_loop_p);
297  }
298  break;
299  }
300  }
301  // If we go into that block, it means that we had a start pragma, went through every statement in the list and everything is static control.
302  // Therefore we just use the same technique, we add a continue statement AFTER the last statement encountered (save_stmt)
303  if (pragma_added_p) {
304  insert_endscop_after_stmt(save_stmt, &pragma_added_p, seqInst, last_added_pragma);
305  }
306  }
307  break;
308  // If it the loop is static control, we add a set of pragma to it else we call the function on the body
309  // of the loop
310  case is_instruction_loop :
311  {
312  loop loopAlone = instruction_loop(instTop);
314  if (static_control_yes(scAlone) && !pragma_added_p) {
315  add_to_stmt(s, &pragma_added_p);
316  last_added_pragma = s;
317  insert_endscop_in_sequence(s, &pragma_added_p, false);
318  }
319  else {
320  pragma_scop(loop_body(instruction_loop(instTop)), pragma_added_p, true);
321  }
322  }
323  break;
324  // A while loop is never considered SCoP, so we just explore the body
326  pragma_scop(whileloop_body(instruction_whileloop(instTop)), false, true);
327  break;
328  // Same principle as the loop
329  case is_instruction_forloop :
330  {
331  forloop forLoopAlone = instruction_forloop(instTop);
333  if (static_control_yes(scAlone) && !pragma_added_p) {
334  add_to_stmt(s, &pragma_added_p);
335  last_added_pragma = s;
336  insert_endscop_in_sequence(s, &pragma_added_p, false);
337  }
338  else {
339  pragma_scop(forloop_body(instruction_forloop(instTop)), false, true);
340  }
341  }
342  break;
343  // If test is a SCoP (both conditions and true/false body fit the conditions) we place
344  // pragma around the condition thereby creating a sequence with a ";"
345  // else we call the function on both statement : true and false
346  case is_instruction_test :
347  {
349  bool testStatic = static_control_yes(scCond);
350  if (testStatic && !pragma_added_p) {
351  add_to_stmt(s, &pragma_added_p);
352  last_added_pragma = s;
353  insert_endscop_in_sequence(s, &pragma_added_p, false);
354  }
355  else if (!testStatic && !pragma_added_p) {
356  pragma_scop(test_true(instruction_test(instTop)), pragma_added_p, in_loop_p);
357  pragma_scop(test_false(instruction_test(instTop)), pragma_added_p, in_loop_p);
358  }
359  }
360  break;
361  default :
362  break;
363  }
364 }
365 
366 /**
367  * use the result of control static to add pragmas for pocc
368  * compiler , that pragmas delimit control static parts (static
369  * control region which can contains many loop nests
370  */
371 
373  // Standard setup
374  statement module_stat;
377  module_stat = get_current_module_statement();
378 
379  Gsc_map = (statement_mapping)db_get_memory_resource(DBR_STATIC_CONTROL, module_name, true);
380 
381  // First call of the function on the global statement
382  pragma_scop(module_stat, false, false);
383 
384  // Standard procedure
385  DB_PUT_MEMORY_RESOURCE(DBR_CODE, module_name,module_stat);
388 
389  return true;
390 }
void clear_pragma_on_statement(statement)
Remove all pragma attached to a given statement.
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
void reset_current_module_statement(void)
Reset the current module statement.
Definition: static.c:221
statement set_current_module_statement(statement)
Set the current module statement.
Definition: static.c:165
statement get_current_module_statement(void)
Get the current module statement.
Definition: static.c:208
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
void gen_insert_after(const void *no, const void *o, list l)
Definition: list.c:223
list gen_insert_before(const void *no, const void *o, list l)
Definition: list.c:238
string db_get_memory_resource(const char *rname, const char *oname, bool pure)
Return the pointer to the resource, whatever it is.
Definition: database.c:755
#define DB_PUT_MEMORY_RESOURCE(res_name, own_name, res_val)
conform to old interface.
Definition: pipsdbm-local.h:66
bool statement_test_p(statement)
Definition: statement.c:343
bool statement_forloop_p(statement)
Definition: statement.c:374
bool statement_loop_p(statement)
Definition: statement.c:349
bool statement_sequence_p(statement)
Statement classes induced from instruction type.
Definition: statement.c:335
bool return_statement_p(statement)
Test if a statement is a C or Fortran "return".
Definition: statement.c:172
bool statement_with_pragma_p(statement)
Test if a statement has some pragma.
Definition: statement.c:3836
void insert_statement(statement, statement, bool)
This is the normal entry point.
Definition: statement.c:2570
statement make_continue_statement(entity)
Definition: statement.c:953
bool declaration_statement_p(statement)
Had to be optimized according to Beatrice Creusillet.
Definition: statement.c:224
#define GET_STATEMENT_MAPPING(map, stat)
Definition: newgen-local.h:49
hash_table statement_mapping
these macros are obsolete! newgen functions (->) should be used instead
Definition: newgen-local.h:42
struct _newgen_struct_static_control_ * static_control
Definition: paf_ri.h:184
#define static_control_yes(x)
Definition: paf_ri.h:753
static void add_to_stmt(statement stmt, bool *pragma_added_p)
Add a "scop" pragma to the statement stmt.
static void pragma_scop(statement s, bool pragma_added_p, bool in_loop_p)
Called recursively, place pragmas on statements according to SCoP conditions.
static bool are_stmts_eq(statement stmt1, statement stmt2)
bool pocc_prettyprinter(char *module_name)
use the result of control static to add pragmas for pocc compiler , that pragmas delimit control stat...
static statement_mapping Gsc_map
static void insert_endscop_after_stmt(statement stmt, bool *pragma_added_p, sequence seqInst, statement last_added_pragma)
Check if the SCoP is rich, add pragma "endscop" after stmt and change the value of pragma_added_p.
static void insert_endscop_in_sequence(statement stmt, bool *pragma_added_p, bool insertBefore)
nsert a pragma "endscop" before/after the statement stmt Insert a ";" statement in sequence with stmt...
bool condition_body_contains_loop_p(statement s)
Look for a loop in a statement.
static void insert_endscop_before_stmt(statement stmt, bool *pragma_added_p, sequence seqInst, list stmts, statement last_added_pragma)
Check if the SCoP is rich, add pragma "endscop" before stmt and change the value of pragma_added_p.
void * arc_label
tatic_control
void * vertex_label
bool condition_contains_loop_p(statement s)
Checks if a test contains a loop.
bool is_SCOP_rich(sequence seq, statement last_added_pragma, statement curStmt, bool *pragma_added_p)
Checks if there is at least one loop in the sequence.
bool is_subroutine(instruction inst)
Returns true if the instruction is a subroutine.
entity local_name_to_top_level_entity(const char *n)
This function try to find a top-level entity from a local name.
Definition: entity.c:1450
entity entity_empty_label(void)
Definition: entity.c:1105
bool user_call_p(call c)
Test if a call is a user call.
Definition: expression.c:4361
void add_pragma_str_to_statement(statement st, const char *s, bool copy_flag)
Add a string as a pragma to a statement.
Definition: pragma.c:425
#define type_functional_p(x)
Definition: ri.h:2950
#define loop_body(x)
Definition: ri.h:1644
#define functional_result(x)
Definition: ri.h:1444
#define call_function(x)
Definition: ri.h:709
#define instruction_loop(x)
Definition: ri.h:1520
#define type_functional(x)
Definition: ri.h:2952
#define test_false(x)
Definition: ri.h:2837
@ is_instruction_whileloop
Definition: ri.h:1472
@ is_instruction_test
Definition: ri.h:1470
@ is_instruction_call
Definition: ri.h:1474
@ is_instruction_sequence
Definition: ri.h:1469
@ is_instruction_forloop
Definition: ri.h:1477
@ is_instruction_loop
Definition: ri.h:1471
#define instruction_tag(x)
Definition: ri.h:1511
#define type_void_p(x)
Definition: ri.h:2959
#define test_true(x)
Definition: ri.h:2835
#define sequence_statements(x)
Definition: ri.h:2360
#define instruction_sequence(x)
Definition: ri.h:1514
#define instruction_forloop(x)
Definition: ri.h:1538
#define instruction_call_p(x)
Definition: ri.h:1527
#define instruction_whileloop(x)
Definition: ri.h:1523
#define whileloop_body(x)
Definition: ri.h:3162
#define statement_instruction(x)
Definition: ri.h:2458
#define instruction_call(x)
Definition: ri.h:1529
#define instruction_test(x)
Definition: ri.h:1517
#define entity_type(x)
Definition: ri.h:2792
#define statement_number(x)
Definition: ri.h:2452
#define forloop_body(x)
Definition: ri.h:1372
#define statement_undefined
Definition: ri.h:2419
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: statement.c:54