PIPS
fortran90.c
Go to the documentation of this file.
1 /*
2 
3  $Id: fortran90.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 /* Prettyprint one FORTRAN 90 loop as an array expression.
28 
29  Pierre Jouvelot
30 
31  For one level only loop, with one assignment as body. Replaces
32  occurences of the index variable by ranges in expressions. Ranges are
33  prettyprinted as triplet when they occur as subscript expressions and
34  as vectors with implicit DO otherwise. If the replacement cannot occur,
35  for instance because subscript expressions are coupled, the loop is
36  printed as a loop.
37 
38  There are/were memory leaks here since a new expression is constructed.
39 
40 */
41 
42 #include <stdio.h>
43 
44 #include "linear.h"
45 
46 #include "genC.h"
47 #include "text.h"
48 #include "text-util.h"
49 #include "ri.h"
50 #include "misc.h"
51 
52 #include "ri-util.h"
53 #include "prettyprint.h"
54 
55 /* FI: To keep track of vectorized subexpressions (a guess...) */
56 static set vectors;
57 
58 /* The tests necessary to check the underlying assumptions have been
59  performed in text_loop(): b is either an assignment or a sequence
60  with only one statement which is an assignment. */
62 {
65 
66  if(instruction_sequence_p(bi)) {
68  s = STATEMENT(CAR(sl));
69  }
70  else /* because of the input assumptions */
71  s = b;
72 
73  return s;
74 }
75 
76 /* Generate range subscript for simple loop with only one assignment. */
77 text text_loop_90(entity module, const char* label, int margin, loop obj, int n)
78 {
79  /* text_loop_90() only is called if the loop is parallel and if its
80  * body is a unique assignment statement or a list containing a
81  * unique assignment.
82  */
85  entity idx = loop_index( obj ) ;
86  range r = loop_range( obj ) ;
87 
88  expression lhs =
90  expression rhs =
94  text t = text_undefined;
95 
96  pips_assert("Loop obj is consistent", loop_consistent_p(obj));
97 
99 
100  new_lhs = expand_expression( lhs, idx, r ) ;
101  new_rhs = expand_expression( rhs, idx, r ) ;
102 
103  pips_assert("new_lhs is consistent", expression_consistent_p(new_lhs));
104  pips_assert("new_rhs is consistent", expression_consistent_p(new_rhs));
105 
106  set_free(vectors);
107 
108  if(!expression_undefined_p(new_lhs) && !expression_undefined_p(new_rhs)) {
109  statement new_s = make_assign_statement( new_lhs, new_rhs );
110 
111  statement_number(new_s) = statement_number(as);
112  /* statement_ordering must be initialized too to avoid a
113  prettyprinter warning */
116  list pdl = NIL;
117  t = text_statement(module, margin, new_s, &pdl);
118  gen_free_list(pdl);
119  /* FI: Although new_s has been converted to text, it cannot
120  always be freed. I do not know which part of new_s is
121  reused in the result of text_statement() or somewhere
122  else... Found with valgrind and validation case
123  Prettyprint/aa01.tpips */
124  //free_statement(new_s);
125  }
126  else {
127  /* No legal vector form has been found */
128  free_expression(new_lhs);
129  free_expression(new_rhs);
130  list pdl = NIL;
131  t = text_loop_default(module, label, margin, obj, n, &pdl, true);
132  gen_free_list(pdl);
133  }
134 
135  pips_assert("Loop obj still is consistent", loop_consistent_p(obj));
136 
137  return t;
138 }
139 ␌
140 /* Only one call site for expand_call(). All args have been newly
141  allocated there and are re-used here to build new_e, Or they are freed
142  without forgetting the references thru set "vectors". There is no
143  sharing between e and new_e. */
144 
146 {
148  bool vector_op =
149  (strcmp( entity_local_name( f ), PLUS_OPERATOR_NAME ) == 0 ||
150  strcmp( entity_local_name( f ), MINUS_OPERATOR_NAME ) == 0 ||
151  /* strcmp( entity_local_name( f ), DIVIDE_OPERATOR_NAME ) == 0 || */
152  strcmp( entity_local_name( f ), MULTIPLY_OPERATOR_NAME ) == 0 ) ;
153 
154  if( !vector_op ) {
155  /* FI: Sharing thru args? Yes, but see above. */
156  bool vectorp = false;
158  make_call( f, args )),
160  MAP(EXPRESSION, arg, {
161  vectorp |= set_belong_p( vectors, (char *)arg );
162  }, args);
163 
164  if(vectorp)
165  set_add_element( vectors, vectors, (char *)new_e ) ;
166  }
167  else {
168  expression lhs = EXPRESSION(CAR(args)) ;
169  expression rhs = EXPRESSION(CAR(CDR(args))) ;
170  syntax ls = expression_syntax( lhs ) ;
171  syntax rs = expression_syntax( rhs ) ;
172 
173  if(set_belong_p( vectors, (char *)lhs ) &&
174  set_belong_p( vectors, (char *)rhs )) {
175  if( syntax_range_p( ls ) && syntax_range_p( rs )) {
176  range rl = syntax_range( ls ) ;
177  range rr = syntax_range( rs ) ;
178 
179  new_e = update_range(f, rl,
180  range_lower(rr), range_upper(rr),
181  range_increment(rr), true) ;
182  }
183  else {
184  new_e = MakeBinaryCall( f, lhs, rhs ) ;
185  }
186  set_add_element( vectors, vectors, (char *)new_e ) ;
187  }
188  else if( set_belong_p( vectors, (char *)lhs )) {
189  if( syntax_range_p( ls )) {
190  range rl = syntax_range( ls ) ;
191 
192  new_e = update_range(f, rl, rhs, rhs, int_to_expression(1), true) ;
193  }
194  else {
195  new_e = MakeBinaryCall( f, lhs, rhs ) ;
196  }
197  set_add_element( vectors, vectors, (char *)new_e ) ;
198  }
199  else if( set_belong_p( vectors, (char *)rhs )) {
200  if( syntax_range_p( rs )) {
201  range rr = syntax_range( rs ) ;
202 
203  new_e = update_range(f, rr, lhs, lhs, int_to_expression(1), false) ;
204  }
205  else {
206  new_e = MakeBinaryCall( f, lhs, rhs ) ;
207  }
208  set_add_element(vectors, vectors, (char *) new_e);
209  }
210  else {
211  /* No sharing between e and new_e */
212  new_e = copy_expression(e);
213  }
214  }
215  return new_e;
216 }
217 ␌
218 /* A reference cannot always be expanded. Subscript expression coupling as
219  in A(I,I) prevent expansion and an undefined expression is returned. Non-affine expressions such as A(I**2)
220  cannot be transformed into triplets but can be tranformed into implicit
221  DO vectors.
222 
223  Arguments s, e, i and r should not be shared with the returned expression. */
224 
226 {
227  reference rf = syntax_reference(s) ;
229 
230  if( same_entity_p( reference_variable( rf ), i )) {
231  /* expand occurence of loop index */
233  new_e = make_expression(new_s, normalized_undefined) ;
234  set_add_element( vectors, vectors, (char *) new_e ) ;
235  }
236  else {
237  /* expand 1 subscript expression or fail or leave unexpanded */
238  int dim = 0 ;
239  cons *new_args = NIL ;
240  reference new_r ;
241 
242  MAPL( args, {
243  expression arg = EXPRESSION( CAR( args )) ;
244 
245  new_e = expand_expression( arg, i, r ) ;
246 
247  if(expression_undefined_p(new_e))
248  return new_e;
249 
250  if(set_belong_p( vectors, (char *)new_e ))
251  dim++;
252 
253  new_args = CONS(EXPRESSION, new_e, new_args ) ;
254  }, reference_indices( rf )) ;
255 
256  if( dim==1 ) {
258  gen_nreverse(new_args)) ;
261  set_add_element( vectors, vectors, (char *)new_e ) ;
262  }
263  else if(dim > 1) {
264  /* If dim is greater than 1, subscript expressions are coupled
265  * as in A(I,I+1).
266  */
267  /* new_args should be freed */
268  new_e = expression_undefined;
269  }
270  else {
271  /* Just the spine or more? */
272  gen_free_list(new_args);
273  new_e = copy_expression(e);
274  }
275  }
276  return new_e;
277 }
278 
279 
280 /* Expression with a non-expandable sub-expression, e.g. a non-expandable
281  reference, cannot be expanded.
282 
283  Arguments are not (should not be) shared with the returned expression.
284  */
285 
287 expression e ;
288 entity i ;
289 range r ;
290 {
291  syntax s = expression_syntax( e ) ;
293 
294  switch(syntax_tag( s ))
295  {
296  case is_syntax_reference:
297  new_e = expand_reference( s, e, i, r);
298  break;
299  case is_syntax_call: {
300  call c = syntax_call( s ) ;
301  cons *new_args = NIL ;
302  entity f = call_function( c ) ;
303  int dim = 0 ;
304 
305  MAPL( args, {
306  expression arg = EXPRESSION( CAR( args )) ;
307 
308  new_e = expand_expression( arg, i, r ) ;
309 
310  if(expression_undefined_p(new_e)) {
311  return new_e;
312  }
313 
314  /* FI: I do not know why dim is computed. Old cut-and-paste
315  from expand_reference()? */
316  if(set_belong_p( vectors, (char *)new_e )) {
317  dim++;
318  }
319 
320  new_args = CONS(EXPRESSION, new_e, new_args ) ;
321  }, call_arguments( c )) ;
322 
323  new_e = expand_call(e, f, gen_nreverse(new_args));
324  break;
325  }
326  case is_syntax_range:
327  pips_internal_error("Range expansion not implemented" ) ;
328  default:
329  pips_internal_error("unexpected syntax tag (%d)",
330  syntax_tag(s));
331  }
332 
333  return new_e;
334 }
call make_call(entity a1, list a2)
Definition: ri.c:269
range copy_range(range p)
RANGE.
Definition: ri.c:2005
expression make_expression(syntax a1, normalized a2)
Definition: ri.c:886
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
bool expression_consistent_p(expression p)
Definition: ri.c:859
void free_expression(expression p)
Definition: ri.c:853
bool loop_consistent_p(loop p)
Definition: ri.c:1274
syntax make_syntax(enum syntax_utype tag, void *val)
Definition: ri.c:2491
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
#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
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
#define MAPL(_map_list_cp, _code, _l)
Apply some code on the addresses of all the elements of a list.
Definition: newgen_list.h:203
#define MAP(_map_CASTER, _map_item, _map_code, _map_list)
Apply/map an instruction block on all the elements of a list (old fashioned)
Definition: newgen_list.h:226
statement make_assign_statement(expression, expression)
Definition: statement.c:583
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
void set_free(set)
Definition: set.c:332
bool set_belong_p(const set, const void *)
Definition: set.c:194
@ set_pointer
Definition: newgen_set.h:44
set set_make(set_type)
Create an empty set of any type but hash_private.
Definition: set.c:102
set set_add_element(set, const set, const void *)
Definition: set.c:152
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
static char * module
Definition: pips.c:74
expression expand_expression(e, i, r)
Expression with a non-expandable sub-expression, e.g.
Definition: fortran90.c:286
expression expand_reference(syntax s, expression e, entity i, range r)
A reference cannot always be expanded.
Definition: fortran90.c:225
static expression expand_call(expression e, entity f, list args)
Only one call site for expand_call().
Definition: fortran90.c:145
text text_loop_90(entity module, const char *label, int margin, loop obj, int n)
Generate range subscript for simple loop with only one assignment.
Definition: fortran90.c:77
static statement body_to_assignment_statement(statement b)
The tests necessary to check the underlying assumptions have been performed in text_loop(): b is eith...
Definition: fortran90.c:61
static set vectors
Prettyprint one FORTRAN 90 loop as an array expression.
Definition: fortran90.c:56
text text_loop_default(entity module, const char *label, int margin, loop obj, int n, list *ppdl, bool is_recursive_p)
exported for fortran90.c
Definition: misc.c:3118
text text_statement(entity, int, statement, list *)
#define MINUS_OPERATOR_NAME
#define PLUS_OPERATOR_NAME
#define MULTIPLY_OPERATOR_NAME
const char * entity_local_name(entity e)
entity_local_name modified so that it does not core when used in vect_fprint, since someone thought t...
Definition: entity.c:453
bool same_entity_p(entity e1, entity e2)
predicates on entities
Definition: entity.c:1321
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
expression update_range(f, r, expression lw, expression up, expression in, bool left)
Prettyprint one FORTRAN 90 loop as an array expression.
Definition: fortran90.c:61
#define loop_body(x)
Definition: ri.h:1644
#define normalized_undefined
Definition: ri.h:1745
#define instruction_sequence_p(x)
Definition: ri.h:1512
#define syntax_reference(x)
Definition: ri.h:2730
#define syntax_tag(x)
Definition: ri.h:2727
#define call_function(x)
Definition: ri.h:709
#define reference_variable(x)
Definition: ri.h:2326
#define range_upper(x)
Definition: ri.h:2290
#define statement_ordering(x)
Definition: ri.h:2454
#define syntax_range(x)
Definition: ri.h:2733
@ is_syntax_range
Definition: ri.h:2692
@ is_syntax_call
Definition: ri.h:2693
@ is_syntax_reference
Definition: ri.h:2691
#define range_increment(x)
Definition: ri.h:2292
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define expression_undefined
Definition: ri.h:1223
#define sequence_statements(x)
Definition: ri.h:2360
#define reference_indices(x)
Definition: ri.h:2328
#define instruction_sequence(x)
Definition: ri.h:1514
#define syntax_call(x)
Definition: ri.h:2736
#define expression_undefined_p(x)
Definition: ri.h:1224
#define range_lower(x)
Definition: ri.h:2288
#define statement_instruction(x)
Definition: ri.h:2458
#define statement_comments(x)
Definition: ri.h:2456
#define instruction_call(x)
Definition: ri.h:1529
#define loop_range(x)
Definition: ri.h:1642
#define call_arguments(x)
Definition: ri.h:711
#define syntax_range_p(x)
Definition: ri.h:2731
#define statement_number(x)
Definition: ri.h:2452
#define expression_syntax(x)
Definition: ri.h:1247
#define loop_index(x)
Definition: ri.h:1640
#define statement_undefined
Definition: ri.h:2419
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
#define text_undefined
Definition: text.h:91