PIPS
pragma.c
Go to the documentation of this file.
1 /*
2 
3  $Id: pragma.c 22764 2015-08-07 13:25:47Z coelho $
4 
5  Copyright 1989-2010 HPC Project
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  This file define methods to deal with objects extensions and pragma
29  used as extensions to statements in the PIPS internal representation.
30 
31  A middle term, extensions method could go in another file.
32 
33  It is a trivial implementation based on strings for a proof of concept.
34 
35  Pierre.Villalon@hpc-project.com
36  Ronan.Keryell@hpc-project.com
37 */
38 
39 #include "linear.h"
40 #include "genC.h"
41 #include "misc.h"
42 #include "ri.h"
43 #include "naming.h"
44 #include "ri-util.h"
45 #include "properties.h"
46 
47 //*************************************************** Not so Local constant
48 
49 // unused: static const string C_PRAGMA_HEADER = C_PRAGMA_HEADER_STRING;
50 // FI: progress over #define and #include?
53 
54 
55 
56 /*****************************************************Local static function
57  */
60  return (ENTITY_OMP_PRIVATE_P (ent));
61 }
62 
65  return (ENTITY_OMP_IF_P (ent));
66 }
67 
70  return (ENTITY_OMP_REDUCTION_P (ent));
71 }
72 
75  return ENTITY_OMP_OMP_P(ent);
76 }
77 
80  return ENTITY_OMP_FOR_P(ent);
81 }
82 
85  return ENTITY_OMP_PARALLEL_P(ent);
86 }
87 
90  const char* prop = get_string_property ("OMP_IF_MERGE_POLICY");
91  if (strcmp (prop, "ignore") == 0) {
92  result = IGNORE_IF_POLICY;
93  }
94  else if (strcmp (prop, "or") == 0) {
95  result = OR_IF_POLICY;
96  }
97  else if (strcmp (prop, "and") == 0) {
98  result = AND_IF_POLICY;
99  }
100  return result;
101 }
102 
103 // merge all if conditions
107  switch(policy) {
108  case IGNORE_IF_POLICY:
109  break;
110  case AND_IF_POLICY:
111  // switch(get_prettyprint_language_tag()) {
112  switch(language_tag(l)) {
113  case is_language_fortran:
116  break;
117  case is_language_c:
119  break;
120  default:
121  pips_internal_error ("This case should have been handled before");
122  break;
123  }
124  break;
125  case OR_IF_POLICY:
126  //switch(get_prettyprint_language_tag()) {
127  switch(language_tag(l)) {
128  case is_language_fortran:
131  break;
132  case is_language_c:
134  break;
135  default:
136  pips_internal_error ("This case should have been handled before");
137  break;
138  }
139  break;
140  default:
141  pips_internal_error ("update switch case");
142  break;
143  }
144  // now we have a list of condition and an operator -> merge them
145  result = expressions_to_operation(l_cond, op);
146  return result;
147 }
148 
149 
150 /***************************************************PRAGMA AS EXPRESSION PART
151  */
152 
153 /**
154  @brief build the expression to be put in the if clause. This functions
155  takes care of the output language.
156  @return the condition compared to the threshold as an expression
157  @param cond, the condition to be compared to the threshold
158 **/
161  //switch(get_prettyprint_language_tag()) {
162  switch(language_tag(l)) {
163  case is_language_fortran:
166  break;
167  case is_language_c:
169  break;
170  default:
171  pips_internal_error ("This case should have been handled before" );
172  break;
173  }
174  int threshold = get_int_property("OMP_LOOP_PARALLEL_THRESHOLD_VALUE");
175  list args_if = gen_expression_cons(int_to_expression(threshold), NIL);
176  args_if = gen_expression_cons(cond, args_if);
177  call c = make_call(op, args_if);
178  return call_to_expression(c);
179 }
180 
181 /** @return "if (cond)" as an expression
182  * @param arg, the condition to be evaluted by the if clause
183  */
186  list args_expr = gen_expression_cons (arg, NIL);
187  call c = make_call (omp, args_expr);
188  // syntax s = make_syntax_call (c);
189  expression expr_if = call_to_expression (c);// make_expression (s, normalized_undefined);
190  return expr_if;
191 }
192 
193 /** @return "private (x,y)" as an expression
194  * @param args_expr, the private variables as a list of expression
195  */
198  call c = make_call (omp, args_expr);
199  syntax s = make_syntax_call (c);
201  return expr_omp;
202 }
203 
204 /** @return "private (x,y)" as an expression
205  * @param arg, the private variables as a list of entities
206  */
208  // build the privates variable as a list of expression
209  list args_expr = entities_to_expressions (args_ent);
210  return pragma_private_as_expr_with_args (args_expr);
211 }
212 
213 /** @return "omp parallel" as a list of expression
214  */
216  // first prepare "omp" as an expression
218  call c = make_call (omp, NULL);
219  syntax s = make_syntax_call (c);
221 
222  //secondly prepare "parallel" as an expression
224  c = make_call (parallel, NULL);
225  s = make_syntax_call (c);
226  expression expr_parallel = make_expression (s, normalized_undefined);
227 
228  // build the list of expression
229  list result = CONS(EXPRESSION, expr_omp, NIL);
230  result = gen_expression_cons (expr_parallel, result);
231  return result;
232 }
233 
234 /** @return "omp parallel for" as an expression
235  */
237  // first prepare "for" as an expression
239  call c = make_call (e, NULL);
240  syntax s = make_syntax_call (c);
242 
243  //secondly get "omp parallel as an expr and concat
245  result = gen_expression_cons (expr_for, result);
246 
247  return result;
248 }
249 
250 
251 /**
252  * @brief filter out a pragma (expression list) removing all requested variables
253  * @params l_expr is the list of expressions to filter
254  * @params to_filter is the list of entities to remove from l_pragma
255  */
257  list /* of entities */to_filter) {
258 
259  // If all variable in exp are removed, we remove the expr from the list
260  list expr_to_remove = NIL;
261 
262  FOREACH (EXPRESSION, expr, l_expr) {
263  // Get the list of arguments, to filter out
264  call c = expression_call(expr);
265  list args = call_arguments (c);
266 
267  // The list where we will record arg to remove from args
268  list entity_to_remove = NIL;
269 
270  // FI: to avoid cycles between librairies ri-util and prettyprint
271  /* ifdebug(5) { */
272  /* pips_debug(5,"Handling expression : "); */
273  /* print_expression(expr); */
274  /* } */
275  if(is_expression_omp_private_p(expr)) {
276  // Handle private omp clause
277  // Lookup each requested entities
278  FOREACH(ENTITY, e, to_filter)
279  {
280  FOREACH (EXPRESSION, exp, args)
281  {
282  pips_debug(6,"Matching %s against %s\n",entity_name(e),
284  if(expression_to_entity(exp) == e) {
285  entity_to_remove = gen_expression_cons(exp, entity_to_remove);
286  break;
287  }
288  }
289  }
290  FOREACH(EXPRESSION,exp,entity_to_remove)
291  {
293  }
294  if(ENDP(call_arguments(c))) {
295  expr_to_remove = gen_expression_cons(expr, expr_to_remove);
296  }
297  } else if(is_expression_omp_if_p(expr)) {
298  // FIXME : todo, merge with previous case ?
299  } else if(is_expression_omp_reduction_p(expr)) {
300  // FIXME : shouldn't be a problem ! (handled before)
301  } else if(is_expression_omp_omp_p(expr) || is_expression_omp_for_p(expr)
302  || is_expression_omp_parallel_p(expr)) {
303  // FIXME : is there anything to do here ?
304  } else {
305  pips_debug(0,"Unsupported case : ");
306  // FI: to avoid cycles between librairies ri-util and prettyprint
307  // print_expression(expr);
308  pips_internal_error("We don't know how to handle this omp clause !");
309  }
310  }
311  //Remove expression that are now empty
312  FOREACH(EXPRESSION,expr,expr_to_remove) {
313  gen_remove(&l_expr, expr);
314  }
315 
316  return l_expr;
317 }
318 
319 /**
320  @brief merge omp pragma.
321  @return the merged pragma as a list of expression
322  @param l_pragma, the list of pragma to merge. The pragma as to be
323  a list of expression ordered. The pragma list has to be ordered
324  from the outer pragma to the inner pragma as in the original loop nest.
325 **/
326 list pragma_omp_merge_expr (list outer_extensions, list l_pragma, language l) {
327  // The "omp parallel for" as a list of expression
329  // The list of the variables of the private clauses
330  list priv_var = NIL;
331  // The list of condition of the if clauses
332  list if_cond = NIL;
333  // The list of reductions
334  list red = NIL;
335  // Get the if clause policy
337  // the outer pragmas
338  set outer_pragmas = set_make(set_pointer);
339  FOREACH(EXTENSION,ex, outer_extensions) {
340  pragma p = extension_pragma(ex);
341  if(pragma_expression_p(p)) {
343  set_add_element(outer_pragmas,outer_pragmas,e);
344  }
345  }
346 
347  // look into each pragma for private, reduction and if clauses
348  FOREACH (PRAGMA, p, l_pragma) {
349  pips_assert ("Can only merge a list of pragma as expression",
350  pragma_expression_p (p));
352  // check each expression and save what need to be saved to generate
353  // the new omp pragma
354  call c = expression_call(e);
355  list args = call_arguments (c);
356  // bind the args to the right list
358  // each private var has to be uniquely declared
359  list add = NIL;
360  FOREACH (EXPRESSION, exp, args) {
361  if(!expression_equal_in_list_p(exp, priv_var) )
362  add = gen_expression_cons(exp, add);
363  }
364  priv_var = gen_nconc(priv_var, add);
365  } else if(is_expression_omp_if_p(e)) {
366  // if clause : check the policy
367  switch(policy) {
368  case IGNORE_IF_POLICY:
369  // do nothing
370  break;
371  case AND_IF_POLICY:
372  case OR_IF_POLICY:
373  if_cond = gen_nconc(if_cond, args);
374  break;
375  default:
376  pips_internal_error ("Should not happen");
377  break;
378  }
379  } else if(is_expression_omp_reduction_p(e)) {
380  // only reductions on outer statement are kept
381  if(set_belong_p(outer_pragmas,e) ) {
382  red = gen_expression_cons(e, red);
383  }
386  // nothing to do the omp parallel for will be automaticly generated
387  } else {
388  // FI: to avoid cycles between librairies ri-util and prettyprint
389  // print_expression(e);
390  pips_internal_error("pips cannot merge this pragma clause");
391  }
392  }
393  }
394  set_free(outer_pragmas);
395  // build the private clause if needed
396  if(priv_var != NIL) {
398  // append the private clause to the omp parallel for
399  result = gen_expression_cons(priv, result);
400  }
401  // append the reduction clauses if any
402  if(red != NIL) {
403  result = gen_nconc(red, result);
404  }
405  // merge the if condition if needed
406  if(policy != IGNORE_IF_POLICY) {
407  expression expr_if = merge_conditions(if_cond, policy, l);
408  // encapsulate the condition into the if clause
409  expr_if = pragma_if_as_expr(expr_if);
410  // append the if clause to the omp parallel for
411  result = gen_expression_cons(expr_if, result);
412  }
413  return result;
414 }
415 
416 /********************************************************** PRAGMA MANAGEMENT
417  */
418 
419 /** @brief Add a string as a pragma to a statement.
420  * @return void
421  * @param st, the statement on which we want to add a pragma
422  * @param s, the pragma string.
423  * @param copy_flag, to be set to true to duplicate the string
424  */
425 void add_pragma_str_to_statement(statement st, const char* s, bool copy_flag) {
426  /* Duplicate string if requested */
427  string ps = copy_flag ? strdup(s) : (char*)s /* dangerous !*/;
428 
429  /* Make a new pragma */
430  pragma p = make_pragma_string(ps);
431 
432  /* Will be save as an extension attached to
433  * the statement's extension list
434  */
437  list el = extensions_extension(es);
438  el = gen_extension_cons(e, el);
439  extensions_extension(es) = el;
440 }
441 
442 
443 /** Add a list of strings as as many pragmas to a statement
444  @param st, the statement on which we want to add a pragma
445  @param l, a list of pragma string(s)
446  @param copy_flag, to be set to true to duplicate the string
447  */
448 void add_pragma_strings_to_statement(statement st, list l, bool copy_flag) {
449  FOREACH(STRING, p, l)
450  add_pragma_str_to_statement(st, p, copy_flag);
451 }
452 
453 
454 /** @brief Add a pragma as a list of expression to a statement.
455  * @return void
456  * @param st, the statement on which we want to add a pragma
457  * @param l, the list of expression.
458  */
459 void
462  /* Make a new pragma: */
464  p = make_pragma_expression(l);
466  /* Add the new pragma to the extension list: */
467  list el = extensions_extension(es);
468  el = gen_extension_cons(e, el);
469  extensions_extension(es) = el;
470  ifdebug (5) {
471  // This is debugging code. It creates a cycle between ri-util and prettyprint
472  /* extern string pragma_to_string(pragma); */
473  /* string str = pragma_to_string (p); */
474  /* if (str != string_undefined) */
475  /* pips_debug (5, "pragma : %s added\n", str); */
476  ;
477  }
478 }
479 
int get_int_property(const string)
list gen_expression_cons(expression p, list l)
Definition: ri.c:866
call make_call(entity a1, list a2)
Definition: ri.c:269
syntax make_syntax_call(call _field_)
Definition: ri.c:2500
expression make_expression(syntax a1, normalized a2)
Definition: ri.c:886
list gen_extension_cons(extension p, list l)
Definition: ri.c:908
pragma make_pragma_expression(list _field_)
Definition: ri.c:1778
extension make_extension_pragma(pragma _field_)
Definition: ri.c:938
pragma make_pragma_string(string _field_)
Definition: ri.c:1775
char * get_string_property(const char *)
#define STRING(x)
Definition: genC.h:87
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
void gen_remove(list *cpp, const void *o)
remove all occurences of item o from list *cpp, which is thus modified.
Definition: list.c:685
#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
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#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
#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 pips_internal_error
Definition: misc-local.h:149
#define FORTRAN_PRAGMA_HEADER_STRING
Definition: naming-local.h:116
#define FORTRAN_OMP_CONTINUATION_STRING
Definition: naming-local.h:117
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
#define C_AND_OPERATOR_NAME
#define C_GREATER_OR_EQUAL_OPERATOR_NAME
#define ENTITY_OMP_PARALLEL_P(e)
if_clause_policy
that is all for ri-util-local.h
@ AND_IF_POLICY
@ OR_IF_POLICY
@ IGNORE_IF_POLICY
#define ENTITY_OMP_OMP_P(e)
#define ENTITY_OMP_IF_P(e)
OMP entity test.
#define AND_OPERATOR_NAME
FI: intrinsics are defined at a third place after bootstrap and effects! I guess the name should be d...
#define OMP_FOR_FUNCTION_NAME
#define OMP_OMP_FUNCTION_NAME
#define OMP_PARALLEL_FUNCTION_NAME
#define ENTITY_OMP_PRIVATE_P(e)
#define GREATER_OR_EQUAL_OPERATOR_NAME
#define OMP_IF_FUNCTION_NAME
OMP related function and opertor names.
#define C_OR_OPERATOR_NAME
#define ENTITY_OMP_FOR_P(e)
#define ENTITY_OMP_REDUCTION_P(e)
#define OR_OPERATOR_NAME
#define OMP_PRIVATE_FUNCTION_NAME
list entities_to_expressions(list l_ent)
build a list of expressions from a list of entities
Definition: entity.c:2703
entity CreateIntrinsic(string name)
this function does not create an intrinsic function because they must all be created beforehand by th...
Definition: entity.c:1311
expression expressions_to_operation(const list l_exprs, entity op)
take a list of expression and apply a binary operator between all of them and return it as an express...
Definition: expression.c:3544
call expression_call(expression e)
Definition: expression.c:445
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
bool expression_equal_in_list_p(expression e, list le)
This function returns true, if there exists an expression equal in the list false,...
Definition: expression.c:566
entity expression_to_entity(expression e)
just returns the entity of an expression, or entity_undefined
Definition: expression.c:3140
expression call_to_expression(call c)
Build an expression that call a function or procedure.
Definition: expression.c:309
static bool is_expression_omp_omp_p(expression exp)
Definition: pragma.c:73
static expression merge_conditions(list l_cond, if_clause_policy policy, language l)
Definition: pragma.c:104
const string FORTRAN_PRAGMA_HEADER
pragma.c
Definition: pragma.c:51
list pragma_omp_parallel_as_exprs(void)
Definition: pragma.c:215
list pragma_omp_merge_expr(list outer_extensions, list l_pragma, language l)
merge omp pragma.
Definition: pragma.c:326
expression pragma_if_as_expr(expression arg)
Definition: pragma.c:184
static bool is_expression_omp_parallel_p(expression exp)
Definition: pragma.c:83
list filter_variables_in_pragma_expr(list l_expr, list to_filter)
filter out a pragma (expression list) removing all requested variables @params l_expr is the list of ...
Definition: pragma.c:256
void add_pragma_expr_to_statement(statement st, list l)
Add a pragma as a list of expression to a statement.
Definition: pragma.c:460
list pragma_omp_parallel_for_as_exprs(void)
Definition: pragma.c:236
static if_clause_policy get_if_clause_policy(void)
Definition: pragma.c:88
const string FORTRAN_OMP_CONTINUATION
Definition: pragma.c:52
static bool is_expression_omp_reduction_p(expression exp)
Definition: pragma.c:68
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
static bool is_expression_omp_for_p(expression exp)
Definition: pragma.c:78
expression pragma_private_as_expr(list args_ent)
Definition: pragma.c:207
static bool is_expression_omp_private_p(expression exp)
Definition: pragma.c:58
expression pragma_private_as_expr_with_args(list args_expr)
Definition: pragma.c:196
static bool is_expression_omp_if_p(expression exp)
Definition: pragma.c:63
void add_pragma_strings_to_statement(statement st, list l, bool copy_flag)
Add a list of strings as as many pragmas to a statement.
Definition: pragma.c:448
expression pragma_build_if_condition(expression cond, language l)
build the expression to be put in the if clause.
Definition: pragma.c:159
#define PRAGMA(x)
PRAGMA.
Definition: ri.h:1991
#define normalized_undefined
Definition: ri.h:1745
#define pragma_undefined
Definition: ri.h:1997
#define pragma_expression_p(x)
Definition: ri.h:2034
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define extension_pragma(x)
Definition: ri.h:1295
#define EXTENSION(x)
EXTENSION.
Definition: ri.h:1253
#define entity_undefined
Definition: ri.h:2761
#define pragma_expression(x)
Definition: ri.h:2036
#define expression_undefined
Definition: ri.h:1223
#define entity_name(x)
Definition: ri.h:2790
#define statement_extensions(x)
Definition: ri.h:2464
#define extensions_extension(x)
Definition: ri.h:1330
#define call_arguments(x)
Definition: ri.h:711
#define language_tag(x)
Definition: ri.h:1590
@ is_language_fortran
Definition: ri.h:1566
@ is_language_fortran95
Definition: ri.h:1568
@ is_language_c
Definition: ri.h:1567
char * strdup()
#define ifdebug(n)
Definition: sg.c:47
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 exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207