PIPS
statement_insertion.c
Go to the documentation of this file.
1 /*
2  Copyright 1989-2016 MINES ParisTech
3 
4  This file is part of PIPS.
5 
6  PIPS is free software: you can redistribute it and/or modify it
7  under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  any later version.
10 
11  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
12  WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  FITNESS FOR A PARTICULAR PURPOSE.
14 
15  See the GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
19 
20 */
21 
22 /**
23  * @file insert_statement.c
24  * check if a statement can be inserted without too much side effect
25  * @author Serge Guelton <serge.guelton@enst-bretagne.fr>
26  * @date 2010-06-01
27  */
28 #ifdef HAVE_CONFIG_H
29  #include "pips_config.h"
30 #endif
31 #include <ctype.h>
32 
33 
34 #include "genC.h"
35 #include "linear.h"
36 #include "ri.h"
37 #include "ri-util.h"
38 #include "workspace-util.h"
39 #include "text.h"
40 #include "pipsdbm.h"
41 #include "resources.h"
42 #include "properties.h"
43 #include "misc.h"
44 #include "conversion.h"
45 #include "effects.h" // For "semantics.h"
46 #include "semantics.h"
47 #include "transformer.h"
48 #include "control.h"
49 #include "effects-generic.h"
50 #include "effects-simple.h"
51 #include "effects-convex.h"
52 #include "text-util.h"
53 #include "parser_private.h"
54 #include "accel-util.h"
55 
56 typedef struct {
60 
62 {
63  if(same_entity_p(p->to,call_function(c)))
64  p->found=CONS(CALL,c,p->found);
65 }
66 
68 {
72 }
73 
74 /* returns a list of call to @p to found in @p in*/
76  entity_list_pair p = { to , NIL };
80  NULL);
81  return p.found;
82 }
83 
84 
85 /* tries hard to propagate entity dimension change */
86 static void statement_insertion_fix_access_in_callers(const char * module_name, entity new_formal)
87 {
88  callees callers = (callees)db_get_memory_resource(DBR_CALLERS, module_name,true);
89  intptr_t new_formal_offset=formal_offset(storage_formal(entity_storage(new_formal)));
90  size_t new_formal_dimensions=gen_length(variable_dimensions(type_variable(ultimate_type(entity_type(new_formal)))));
92 
93  statement caller_statement = (statement)db_get_memory_resource(DBR_CODE,caller_name,true);
95  FOREACH(CALL,c,calls) {
96  expression nth = EXPRESSION(gen_nth(new_formal_offset-1,call_arguments(c)));
97  if(expression_reference_p(nth))
98  {
100  size_t nb_indices = gen_length(reference_indices(r));
102  if(nb_dimensions - nb_indices == new_formal_dimensions)
103  {
105  for(size_t i=1;i<nb_indices;i++) POP(*iter);
106  gen_full_free_list(*iter);
109  }
110  else pips_internal_error("unhandled case");
111  }
112  else pips_internal_error("unhandled case");
113  }
114  DB_PUT_MEMORY_RESOURCE(DBR_CODE,caller_name,caller_statement);
115  gen_free_list(calls);
116  }
117 }
118 
119 /* fixes statement declaration depending on region access */
121 {
122  VOLATILE_FOREACH(REGION, reg, regions)
123  {
125  entity e = reference_variable(r);
126  if(formal_parameter_p(e)) {
127  pips_user_warning("cannot change formal parameter with this version\n"
128  "try using inlining if possible\n");
129  break;
130  }
132  Psysteme dims_syst = entity_declaration_sc(e);
133  Psysteme access_syst = region_system(reg);
134 
135  volatile Psysteme sr;
137  {
138  pips_debug(1, "overflow error\n");
139  return ;
140  }
141  TRY
142  {
143  sr = sc_cute_convex_hull(access_syst, dims_syst);
144  sc_rm(dims_syst);
145  sc_nredund(&sr);
147  }
148  // if we reach this point, we are ready for backward translation
149  // from vecteur to dimensions :)
150  list new_dimensions = NIL;
151  FOREACH(ENTITY,phi,phis)
152  {
153  Pcontrainte lower,upper;
154  constraints_for_bounds(phi, &sc_inegalites(sr), &lower, &upper);
155  if( !CONTRAINTE_UNDEFINED_P(lower) && !CONTRAINTE_UNDEFINED_P(upper))
156  {
159  new_dimensions= CONS(DIMENSION,
160  make_dimension(elower,eupper,NIL),
161  new_dimensions);
162  }
163  else {
164  pips_user_warning("failed to translate region\n");
165  }
166  }
167  new_dimensions=gen_nreverse(new_dimensions);
169  variable_dimensions(type_variable(entity_type(e)))=new_dimensions;
170  gen_free_list(phis);
171  // formal entites are a special case: the actual parameter
172  // declaration must be changed too
173 
174  // currently disabled, see you later, aligator
175  if(formal_parameter_p(e))
177  }
178 }
179 
181 {
182  /* first find a statement with the relevant pragma */
183  const char* inserted_pragma = get_string_property("STATEMENT_INSERTION_PRAGMA");
184  if(empty_string_p(inserted_pragma)) {
185  pips_user_warning("STATEMENT_INSERTION_PRAGMA property should not be empty\n");
186  }
187  else {
188  list flagged_statements = find_statements_with_pragma(s,inserted_pragma);
189  if(ENDP(flagged_statements)) {
190  pips_user_warning("no statement with pragma '%s' found\n",inserted_pragma);
191  }
192  else {
193  FOREACH(STATEMENT,flagged_statement,flagged_statements) {
195  if(ENDP(out_regions))
196  {
197  /* make sure all data access are ok by building the convex union of data access and data declarations */
198  list regions = load_cumulated_rw_effects_list(flagged_statement);
200  /* update pragma */
202  {
204  {
205  string str_pragma = pragma_string(extension_pragma(ext));
206  if(strstr( str_pragma , inserted_pragma ))
207  {
208  free(str_pragma);
209  pragma_string(extension_pragma(ext))=strdup(get_string_property("STATEMENT_INSERTION_SUCCESS_PRAGMA"));
210  }
211  }
212  }
213  return true;
214  }
215  else
216  {
217  pips_user_warning("inserted statment has out effects\n");
218  /* update pragma */
220  {
222  {
223  string str_pragma = pragma_string(extension_pragma(ext));
224  if(strstr( str_pragma , inserted_pragma ))
225  {
226  free(str_pragma);
227  pragma_string(extension_pragma(ext))=strdup(get_string_property("STATEMENT_INSERTION_FAILURE_PRAGMA"));
228  }
229  }
230  }
231  }
232 
233  }
234  }
235 
236  }
237  return false;
238 }
239 
241 {
242  /* init */
247  debug_on("STATEMENT_INSERTION_DEBUG_LEVEL");
248 
249  /* do */
251  {
252  /* validate */
255  }
256 
257  debug_off();
262  return true;
263 }
264 typedef struct {
268 
270  if(statement_block_p(s)) {
272  param->s=s;
273  gen_recurse_stop(0);
274  }
275  }
276 }
277 
278 
279 /* returns the statement block declaring entity @p e among all thoses in @p top
280  * assumes the entity *is* declared locally
281  * c only
282  */
285  if(formal_parameter_p(e))
286  return top;
287  else {
289  pips_assert("entity not a local entity ?",!statement_undefined_p(param.s));
290  return param.s;
291  }
292 }
293 
295  list remove = NIL;
297  if(s==sp)
298  remove=CONS(ENTITY,e,remove);
299  }
300  FOREACH(ENTITY,e,remove)
301  hash_del(expanded,e);
302  gen_free_list(remove);
303 }
304 
307  set declarations =set_make(set_pointer);
309  VOLATILE_FOREACH(REGION,reg,regions)
310  {
312  entity e = reference_variable(r);
313  if(set_belong_p(declarations,e) &&
315  array_entity_p(e) ) {
316 
320 
322  Psysteme access_syst = region_system(reg);
324 
325  volatile Psysteme sr;
327  {
328  pips_debug(1, "overflow error\n");
329  return true;
330  }
331  TRY
332  {
333  Psysteme tmp = sc_cute_convex_hull(access_syst,decl);
334  tmp=
335  sc_safe_append(tmp,
337  sc_nredund(&tmp);
338  Pbase pb = list_to_base(phis);
339  sr = sc_rectangular_hull(tmp,pb);
340  sc_rm(tmp);
342  }
343  /* if we reach this point, we are ready for backward translation from vecteur to dimensions :) */
344  list new_dimensions = NIL;
345  bool ok=true;
346  FOREACH(ENTITY,phi,phis)
347  {
348  Pcontrainte lower,upper;
349  constraints_for_bounds(phi, &sc_inegalites(sr), &lower, &upper);
350  if( !CONTRAINTE_UNDEFINED_P(lower) && !CONTRAINTE_UNDEFINED_P(upper))
351  {
353  simplify_minmax_expression(elower,tr);
355  simplify_minmax_expression(eupper,tr);
356  new_dimensions=CONS(DIMENSION,
357  make_dimension(elower,eupper,NIL),
358  new_dimensions);
359  }
360  else {
361  pips_user_warning("failed to translate region\n");
362  ok=false;
363  }
364  }
365  transformer_free(tr);
366  if(ok) {
367  hash_put(expanded,e,s);
368  new_dimensions=gen_nreverse(new_dimensions);
370  variable_dimensions(type_variable(entity_type(e)))=new_dimensions;
371  gen_free_list(phis);
372  if(formal_parameter_p(e)) {
376  if(i++ == offset) {
377  dummy d = parameter_dummy(p);
378  if(dummy_identifier_p(d))
379  {
380  entity di = dummy_identifier(d);
383  variable_dimensions(v)=gen_full_copy_list(new_dimensions);
384  }
385  }
386  }
387  }
388  }
389  }
390  }
391  set_free(declarations);
392  return true;
393 }
394 
395 bool array_expansion(const char *module_name)
396 {
397  /* init */
404  debug_on("ARRAY_EXPANSION_DEBUG_LEVEL");
405 
406  /* do */
411 
412  /* validate */
415 
416  debug_off();
422  return true;
423 }
dimension make_dimension(expression a1, expression a2, list a3)
Definition: ri.c:565
static const char * caller_name
Definition: alias_check.c:122
#define CATCH(what)
@ overflow_error
#define UNCATCH(what)
#define TRY
void transformer_free(transformer t)
Definition: basic.c:68
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
#define CONTRAINTE_UNDEFINED_P(c)
void constraints_for_bounds(Variable, Pcontrainte *, Pcontrainte *, Pcontrainte *)
void constraints_for_bounds(var, pinit, plower, pupper) Variable var; Pcontrainte *pinit,...
Definition: unaires.c:176
expression constraints_to_loop_bound(Pcontrainte, Variable, bool, entity)
expression constraints_to_loop_bound(c, var, is_lower)
int dummy
A dummy file, to prevent empty libraries from breaking builds.
Definition: dummy.c:41
#define region_any_reference(reg)
To be avoided.
#define region_system(reg)
#define REGION
static Value offset
Definition: translation.c:283
Psysteme entity_declaration_sc(entity)
bool out_regions(const string)
effects load_proper_rw_effects(statement)
void reset_proper_rw_effects(void)
void set_proper_rw_effects(statement_effects)
void set_cumulated_rw_effects(statement_effects)
list load_cumulated_rw_effects_list(statement)
void reset_cumulated_rw_effects(void)
#define effects_effects(x)
Definition: effects.h:710
bool empty_string_p(const char *s)
Definition: entity_names.c:239
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
char * get_string_property(const char *)
#define gen_context_recurse(start, ctxt, domain_number, flt, rwt)
Definition: genC.h:285
#define STRING(x)
Definition: genC.h:87
void gen_full_free_list(list l)
Definition: genClib.c:1023
void free(void *)
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
const char * get_current_module_name(void)
Get the name of the current module.
Definition: static.c:121
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
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
void gen_recurse_stop(void *obj)
Tells the recursion not to go in this object.
Definition: genClib.c:3251
void gen_context_multi_recurse(void *o, void *context,...)
Multi-recursion with context function visitor.
Definition: genClib.c:3373
bool gen_true2(__attribute__((unused)) gen_chunk *u1, __attribute__((unused)) void *u2)
Definition: genClib.c:2785
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#define VOLATILE_FOREACH(_fe_CASTER, _fe_item, _fe_list)
Definition: newgen_list.h:186
size_t gen_length(const list l)
Definition: list.c:150
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
#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
gen_chunk gen_nth(int n, const list l)
to be used as ENTITY(gen_nth(3, l))...
Definition: list.c:710
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
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
list find_statements_with_pragma(statement, const char *)
Get a list of statements with pragma begining with a prefix.
Definition: statement.c:3912
hash_table hash_table_make(hash_key_type key_type, size_t size)
Definition: hash.c:294
void * hash_get(const hash_table htp, const void *key)
this function retrieves in the hash table pointed to by htp the couple whose key is equal to key.
Definition: hash.c:449
void hash_put(hash_table htp, const void *key, const void *val)
This functions stores a couple (key,val) in the hash table pointed to by htp.
Definition: hash.c:364
void hash_table_free(hash_table htp)
this function deletes a hash table that is no longer useful.
Definition: hash.c:327
void * hash_del(hash_table htp, const void *key)
this function removes from the hash table pointed to by htp the couple whose key is equal to key.
Definition: hash.c:439
static statement expanded
Definition: inlining.c:157
#define debug_on(env)
Definition: misc-local.h:157
#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_user_warning
Definition: misc-local.h:146
#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 debug_off()
Definition: misc-local.h:160
Pbase list_to_base(list l)
Pbase list_to_base(list l): returns the Pbase that contains the variables of list "l",...
@ hash_pointer
Definition: newgen_hash.h:32
#define HASH_UNDEFINED_VALUE
value returned by hash_get() when the key is not found; could also be called HASH_KEY_NOT_FOUND,...
Definition: newgen_hash.h:56
#define HASH_FOREACH(key_type, k, value_type, v, ht)
Definition: newgen_hash.h:71
#define HASH_DEFAULT_SIZE
Definition: newgen_hash.h:26
set set_assign_list(set, const list)
assigns a list contents to a set all duplicated elements are lost
Definition: set.c:474
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
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
Psysteme sc_rectangular_hull(Psysteme, Pbase)
take the rectangular bounding box of the systeme sc, by projecting each constraint of the systeme aga...
Definition: sc_enveloppe.c:456
Psysteme sc_cute_convex_hull(Psysteme, Psysteme)
returns s1 v s2.
Definition: sc_enveloppe.c:369
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
#define statement_block_p(stat)
#define entity_declarations(e)
MISC: newgen shorthands.
#define DIVIDE_OPERATOR_NAME
#define module_functional_parameters(func)
bool entity_in_list_p(entity ent, list ent_l)
look for ent in ent_l
Definition: entity.c:2221
bool array_entity_p(entity e)
Definition: entity.c:793
bool same_entity_p(entity e1, entity e2)
predicates on entities
Definition: entity.c:1321
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
list expressions_to_entities(list expressions)
map expression_to_entity on expressions
Definition: expression.c:3161
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
type ultimate_type(type)
Definition: type.c:3466
bool formal_parameter_p(entity)
Definition: variable.c:1489
#define formal_offset(x)
Definition: ri.h:1408
#define dummy_identifier(x)
Definition: ri.h:1033
struct _newgen_struct_callees_ * callees
Definition: ri.h:55
#define parameter_dummy(x)
Definition: ri.h:1823
#define pragma_string(x)
Definition: ri.h:2033
#define call_function(x)
Definition: ri.h:709
#define callees_callees(x)
Definition: ri.h:675
#define reference_variable(x)
Definition: ri.h:2326
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define pragma_string_p(x)
Definition: ri.h:2031
#define type_variable(x)
Definition: ri.h:2949
#define entity_storage(x)
Definition: ri.h:2794
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58
#define storage_formal(x)
Definition: ri.h:2524
#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 transformer_relation(x)
Definition: ri.h:2873
#define PARAMETER(x)
PARAMETER.
Definition: ri.h:1788
#define reference_indices(x)
Definition: ri.h:2328
#define statement_extensions(x)
Definition: ri.h:2464
#define variable_dimensions(x)
Definition: ri.h:3122
#define statement_declarations(x)
Definition: ri.h:2460
#define CALL(x)
CALL.
Definition: ri.h:679
#define extensions_extension(x)
Definition: ri.h:1330
#define call_arguments(x)
Definition: ri.h:711
#define statement_undefined_p(x)
Definition: ri.h:2420
#define entity_type(x)
Definition: ri.h:2792
#define value_expression_p(x)
Definition: ri.h:3080
#define dummy_identifier_p(x)
Definition: ri.h:1031
#define predicate_system(x)
Definition: ri.h:2069
#define statement_undefined
Definition: ri.h:2419
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define entity_initial(x)
Definition: ri.h:2796
void sc_rm(Psysteme ps)
void sc_rm(Psysteme ps): liberation de l'espace memoire occupe par le systeme de contraintes ps;
Definition: sc_alloc.c:277
Psysteme sc_safe_append(Psysteme s1, Psysteme s2)
Psysteme sc_safe_append(Psysteme s1, Psysteme s2) input : output : calcul de l'intersection des polye...
char * strdup()
void simplify_minmax_expression(expression e, transformer tr)
tries hard to simplify expression e if it is a min or a max operator, by evaluating it under precondi...
Definition: expression.c:5849
void module_to_value_mappings(entity m)
void module_to_value_mappings(entity m): build hash tables between variables and values (old,...
Definition: mappings.c:624
transformer load_statement_precondition(statement)
void reset_precondition_map(void)
void set_precondition_map(statement_mapping)
return(s1)
static bool ok
static void entity_to_declaring_statement_aux(statement s, entity_to_declaring_statement_t *param)
static bool do_statement_insertion(statement s)
bool statement_insertion(const char *module_name)
statement_insertion.c
static void statement_insertion_fix_access(list regions)
fixes statement declaration depending on region access
static void find_calls_to_function_walker_in_declaration(statement s, entity_list_pair *p)
static void do_array_expansion_aux(statement s, hash_table expanded)
static list find_calls_to_function(statement in, entity to)
returns a list of call to to found in in
static statement entity_to_declaring_statement(entity e, statement top)
returns the statement block declaring entity e among all thoses in top assumes the entity is declared...
bool array_expansion(const char *module_name)
static void statement_insertion_fix_access_in_callers(const char *module_name, entity new_formal)
tries hard to propagate entity dimension change
static bool do_array_expansion(statement s, hash_table expanded)
static void find_calls_to_function_walker(call c, entity_list_pair *p)
#define intptr_t
Definition: stdint.in.h:294
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
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
Definition: replace.c:135
transformer transformer_range(transformer tf)
Return the range of relation tf in a newly allocated transformer.
Definition: transformer.c:714
void free_value_mappings(void)
Normal call to free the mappings.
Definition: value.c:1212