PIPS
loop_spaghettify.c
Go to the documentation of this file.
1 /*
2 
3  $Id: loop_spaghettify.c 23065 2016-03-02 09:05:50Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 /**
28  * The spaghettifier is used in context of PHRASE project while
29  * creating "Finite State Machine"-like code portions in order to synthetise
30  * them in reconfigurables units.
31  *
32  * This file contains the code used for spaghettify loops.
33  *
34  * General syntax of loop in Fortran are:
35  *
36  * DO INDEX=BEGIN, END, INCREMENT
37  * STATEMENT
38  * END DO
39  *
40  * where INDEX is an entity (variable)
41  * and BEGIN, END, INCREMENT are expressions.
42  *
43  * Be careful: Fortran interprets all the values of the loop
44  * INDEX, BEGIN, END, INCREMENT before to enter the loop, and
45  * those values could therefore be modified inside the loop
46  * (during the execution of STATEMENT).
47  * That's the reason, to generate equivalent code, why we
48  * introduce the variables:
49  * INDEX', BEGIN', END', INCREMENT'
50  *
51  * If INCREMENT is evaluable and POSITIVE, following code is generated:
52  *
53  * BEGIN' = BEGIN
54  * END' = END
55  * INC' = INC
56  * INDEX' = BEGIN'
57  * 10 IF (INDEX'.LE.END') THEN
58  * INDEX = INDEX'
59  * STATEMENT
60  * INDEX' = INDEX' + INC'
61  * GOTO 10
62  * ENDIF
63  * 20 CONTINUE
64  *
65  *
66  * If INCREMENT is evaluable and NEGATIVE, following code is generated:
67  *
68  * BEGIN' = BEGIN
69  * END' = END
70  * INC' = INC
71  * INDEX' = BEGIN'
72  * 10 IF (INDEX'.GE.END') THEN
73  * INDEX = INDEX'
74  * STATEMENT
75  * INDEX' = INDEX' + INC'
76  * GOTO 10
77  * ENDIF
78  * 20 CONTINUE
79  *
80  * If INCREMENT is not evaluable, following code is generated:
81  *
82  * BEGIN' = BEGIN
83  * END' = END
84  * INC' = INC
85  * INDEX' = BEGIN'
86  * 10 IF (((INDEX'.LE.END').AND.(INC'.GE.0)).OR.((INDEX'.GE.END').AND.(INC'.LE.0))) THEN
87  * INDEX = INDEX'
88  * STATEMENT
89  * INDEX' = INDEX' + INC'
90  * GOTO 10
91  * ENDIF
92  * 20 CONTINUE
93  *
94  */
95 
96 #include <stdio.h>
97 #include <ctype.h>
98 
99 #include "genC.h"
100 #include "linear.h"
101 #include "ri.h"
102 #include "effects.h"
103 
104 #include "resources.h"
105 
106 #include "misc.h"
107 #include "ri-util.h"
108 #include "effects-util.h"
109 
110 #include "text-util.h"
111 
112 #include "dg.h"
113 
114 
115 #include "phrase_tools.h"
116 #include "spaghettify.h"
117 
118 
119 /**
120  * Creates index variable for a loop the_loop of a statement stat
121  */
122 static entity make_index_variable (loop the_loop,
123  statement stat,
124  const char* module_name)
125 {
128  stat,
129  module_name);
130 }
131 
132 /**
133  * Creates begin variable for a loop the_loop of a statement stat
134  */
135 static entity make_begin_variable (loop the_loop,
136  statement stat,
137  const char* module_name)
138 {
141  stat,
142  module_name);
143 }
144 
145 /**
146  * Creates end variable for a loop the_loop of a statement stat
147  */
148 static entity make_end_variable (loop the_loop,
149  statement stat,
150  const char* module_name)
151 {
154  stat,
155  module_name);
156 }
157 
158 /**
159  * Creates increment variable for a loop the_loop of a statement stat
160  */
162  statement stat,
163  const char* module_name)
164 {
167  stat,
168  module_name);
169 }
170 
171 /**
172  * Build and return a new control containing initialization statement
173  * of the unstructured loop
174  */
176  statement stat,
177  entity index_variable,
178  entity begin_variable,
179  entity end_variable,
180  entity increment_variable)
181 {
182  statement init_begin_statement;
183  statement init_end_statement;
184  statement init_increment_statement;
185  statement init_index_statement;
186  expression lower = range_lower(loop_range(the_loop));
187  expression upper = range_upper(loop_range(the_loop));
188  expression increment = range_increment(loop_range(the_loop));
189  sequence init_sequence;
190 
191  init_begin_statement
192  = make_assignement_statement (begin_variable, lower, stat);
193  init_end_statement
194  = make_assignement_statement (end_variable, upper, stat);
195  init_increment_statement
196  = make_assignement_statement (increment_variable, increment, stat);
197  init_index_statement
198  = make_assignement_statement (index_variable,
199  entity_to_expression(begin_variable),
200  stat);
201 
202  init_sequence
204  init_begin_statement,
205  CONS(STATEMENT,
206  init_end_statement,
207  CONS(STATEMENT,
208  init_increment_statement,
209  CONS(STATEMENT,
210  init_index_statement,
211  NIL)))));
212 
214  statement_number(stat),
215  statement_ordering(stat),
218  init_sequence),
219  NIL, NULL,
221  NIL, NIL);
222 }
223 
224 /**
225  * Build and return a new control containing condition statement
226  * of the unstructured loop
227  */
229  statement stat,
230  entity index_variable,
231  entity end_variable,
232  entity increment_variable)
233 {
234  statement condition_statement;
235  test condition_test;
236  intptr_t increment_value;
237  string intrinsic_name;
239 
241  (range_increment(loop_range(the_loop)),
242  &increment_value)) {
243  if (increment_value >= 0) {
244  intrinsic_name = LESS_OR_EQUAL_OPERATOR_NAME;
245  }
246  else {
247  intrinsic_name = GREATER_OR_EQUAL_OPERATOR_NAME;
248  }
250  = MakeBinaryCall (entity_intrinsic(intrinsic_name),
251  entity_to_expression (index_variable),
252  entity_to_expression (end_variable));
253  }
254  else {
255  // Generate (((INDEX'.LE.END').AND.(INC'.GE.0)).OR.((INDEX'.GE.END').AND.(INC'.LE.0)))
260  entity_to_expression (index_variable),
261  entity_to_expression (end_variable)),
263  entity_to_expression (increment_variable),
264  int_to_expression (0))),
267  entity_to_expression (index_variable),
268  entity_to_expression (end_variable)),
270  entity_to_expression (increment_variable),
271  int_to_expression (0))));
272 
273 
274  }
275 
276  condition_test
280 
281 
282  condition_statement = make_statement(entity_empty_label(),
283  statement_number(stat),
284  statement_ordering(stat),
287  condition_test),
288  NIL,NULL,
290 
291  return make_control (condition_statement, NIL, NIL);
292 }
293 
294 /**
295  * Build and return a new control containing exit statement
296  * of the unstructured loop (this is a continue statement)
297  */
299 {
301 }
302 
303 /**
304  * Build and return a new control containing body statement
305  * of the unstructured loop
306  */
307 static control make_body_from_loop (loop the_loop,
308  const char* module_name,
309  statement stat,
310  entity index_variable,
311  entity increment_variable)
312 {
313  statement assignement_statement
315  entity_to_expression (index_variable),
316  stat);
317  statement spaghettified_body
318  = spaghettify_statement(loop_body(the_loop),
319  module_name);
320  statement increment_statement
322  (index_variable,
324  entity_to_expression (index_variable),
325  entity_to_expression (increment_variable)),
326  stat);
327 
328  sequence body_sequence
329  = make_sequence (CONS(STATEMENT, assignement_statement,
330  CONS(STATEMENT, spaghettified_body,
331  CONS(STATEMENT, increment_statement, NIL))));
332 
333  statement body_statement
335  statement_number(stat),
336  statement_ordering(stat),
339  body_sequence),
340  NIL,NULL,
342  return make_control (body_statement, NIL, NIL);
343 }
344 
345 /**
346  * Build and return a new unstructured coding the
347  * "destructured" loop
348  */
350  statement stat,
351  const char* module_name)
352 {
353  entity index_variable = make_index_variable (the_loop, stat, module_name);
354  entity begin_variable = make_begin_variable (the_loop, stat, module_name);
355  entity end_variable = make_end_variable (the_loop, stat, module_name);
356  entity increment_variable = make_increment_variable (the_loop, stat, module_name);
358  = make_initialization_from_loop (the_loop,
359  stat,
360  index_variable,
361  begin_variable,
362  end_variable,
363  increment_variable);
364  control condition = make_condition_from_loop (the_loop,
365  stat,
366  index_variable,
367  end_variable,
368  increment_variable);
370  control body = make_body_from_loop (the_loop,
371  module_name,
372  stat,
373  index_variable,
374  increment_variable);
375 
376  link_2_control_nodes (initialization, condition); /* after init, we test */
377 
378  /* The first connexion is the false one */
379  link_2_control_nodes (condition, exit); /* false condition, we exit from loop */
380  link_2_control_nodes (condition, body); /* true condition, we go to body */
381 
382  link_2_control_nodes (body, condition); /* after body, we go back to condition */
383 
385 }
386 
387 /*
388  * This function takes the statement stat as parameter and return a new
389  * spaghettized statement, asserting stat is a LOOP statement
390  */
392 {
393  statement returned_statement = stat;
394  instruction unstructured_instruction;
395  unstructured new_unstructured;
396 
397  pips_assert("Statement is LOOP in FSM_GENERATION",
400 
401  pips_debug(2, "spaghettify_loop, module %s\n", module_name);
402  new_unstructured = make_unstructured_from_loop (statement_loop(stat),
403  stat,
404  module_name);
405 
406  unstructured_instruction = make_instruction(is_instruction_unstructured,
407  new_unstructured);
408 
409  statement_instruction(returned_statement) = unstructured_instruction;
410 
411  return returned_statement;
412 }
unstructured make_unstructured(control a1, control a2)
Definition: ri.c:2778
test make_test(expression a1, statement a2, statement a3)
Definition: ri.c:2607
statement make_statement(entity a1, intptr_t a2, intptr_t a3, string a4, instruction a5, list a6, string a7, extensions a8, synchronization a9)
Definition: ri.c:2222
instruction make_instruction(enum instruction_utype tag, void *val)
Definition: ri.c:1166
synchronization make_synchronization_none(void)
Definition: ri.c:2424
sequence make_sequence(list a)
Definition: ri.c:2125
control make_control(statement a1, list a2, list a3)
Definition: ri.c:523
void initialization(graph dg, gen_array_t annotations)
Definition: cost_model.c:267
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
void link_2_control_nodes(control source, control target)
Add an edge between 2 control nodes.
Definition: control.c:1193
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
loop statement_loop(statement)
Get the loop of a statement.
Definition: statement.c:1374
statement make_continue_statement(entity)
Definition: statement.c:953
static control make_condition_from_loop(loop the_loop, statement stat, entity index_variable, entity end_variable, entity increment_variable)
Build and return a new control containing condition statement of the unstructured loop.
static control make_body_from_loop(loop the_loop, const char *module_name, statement stat, entity index_variable, entity increment_variable)
Build and return a new control containing body statement of the unstructured loop.
static entity make_index_variable(loop the_loop, statement stat, const char *module_name)
The spaghettifier is used in context of PHRASE project while creating "Finite State Machine"-like cod...
statement spaghettify_loop(statement stat, const char *module_name)
This function takes the statement stat as parameter and return a new spaghettized statement,...
static control make_initialization_from_loop(loop the_loop, statement stat, entity index_variable, entity begin_variable, entity end_variable, entity increment_variable)
Build and return a new control containing initialization statement of the unstructured loop.
static entity make_increment_variable(loop the_loop, statement stat, const char *module_name)
Creates increment variable for a loop the_loop of a statement stat.
static control make_exit_from_loop()
Build and return a new control containing exit statement of the unstructured loop (this is a continue...
static entity make_end_variable(loop the_loop, statement stat, const char *module_name)
Creates end variable for a loop the_loop of a statement stat.
static unstructured make_unstructured_from_loop(loop the_loop, statement stat, const char *module_name)
Build and return a new unstructured coding the "destructured" loop.
static entity make_begin_variable(loop the_loop, statement stat, const char *module_name)
Creates begin variable for a loop the_loop of a statement stat.
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define exit(code)
Definition: misc-local.h:54
statement spaghettify_statement(statement, const char *)
spaghettify.c
Definition: spaghettify.c:85
statement make_assignement_statement(entity, expression, statement)
Build and return new statement which is a assignement of variable a_variable with expression an_expre...
Definition: phrase_tools.c:392
entity make_variable_from_name_and_entity(entity, const char *, statement, const char *)
Build and return new entity obtained by cloning variable cloned_variable, with a name obtained by the...
Definition: phrase_tools.c:325
#define PLUS_OPERATOR_NAME
#define AND_OPERATOR_NAME
FI: intrinsics are defined at a third place after bootstrap and effects! I guess the name should be d...
#define GREATER_OR_EQUAL_OPERATOR_NAME
#define empty_comments
Empty comments (i.e.
#define LESS_OR_EQUAL_OPERATOR_NAME
#define OR_OPERATOR_NAME
entity entity_empty_label(void)
Definition: entity.c:1105
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
bool expression_integer_value(expression e, intptr_t *pval)
Definition: eval.c:792
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
expression MakeBinaryCall(entity f, expression eg, expression ed)
Creates a call expression to a function with 2 arguments.
Definition: expression.c:354
expression int_to_expression(_int i)
transform an int into an expression and generate the corresponding entity if necessary; it is not cle...
Definition: expression.c:1188
#define loop_body(x)
Definition: ri.h:1644
#define range_upper(x)
Definition: ri.h:2290
#define statement_ordering(x)
Definition: ri.h:2454
#define range_increment(x)
Definition: ri.h:2292
@ is_instruction_unstructured
Definition: ri.h:1475
@ is_instruction_test
Definition: ri.h:1470
@ is_instruction_sequence
Definition: ri.h:1469
@ is_instruction_loop
Definition: ri.h:1471
#define instruction_tag(x)
Definition: ri.h:1511
#define statement_extensions(x)
Definition: ri.h:2464
#define test_condition(x)
Definition: ri.h:2833
#define range_lower(x)
Definition: ri.h:2288
#define statement_instruction(x)
Definition: ri.h:2458
#define loop_range(x)
Definition: ri.h:1642
#define statement_number(x)
Definition: ri.h:2452
#define loop_index(x)
Definition: ri.h:1640
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define END_VARIABLE_NAME
Definition: spaghettify.h:29
#define BEGIN_VARIABLE_NAME
Definition: spaghettify.h:28
#define INCREMENT_VARIABLE_NAME
Definition: spaghettify.h:30
#define INDEX_VARIABLE_NAME
Definition: spaghettify.h:27
#define intptr_t
Definition: stdint.in.h:294