PIPS
regions_to_loops.c
Go to the documentation of this file.
1 #ifdef HAVE_CONFIG_H
2  #include "pips_config.h"
3 #endif
4 
5 #include <stdio.h>
6 #include <ctype.h>
7 #include <string.h>
8 #include "boolean.h"
9 
10 
11 #include "genC.h"
12 #include "linear.h"
13 #include "ri.h"
14 #include "effects.h"
15 #include "database.h"
16 #include "misc.h"
17 #include "text.h"
18 #include "text-util.h"
19 #include "ri-util.h"
20 #include "workspace-util.h"
21 #include "effects-util.h"
22 
23 #include "effects-generic.h"
24 #include "effects-simple.h"
25 
26 #include "pipsdbm.h"
27 #include "resources.h"
28 #include "control.h"
29 #include "conversion.h"
30 #include "properties.h"
31 #include "transformations.h"
32 
33 /*static_control*/
34 #include "arithmetique.h"
35 #include "vecteur.h"
36 #include "contrainte.h"
37 #include "ray_dte.h"
38 #include "sommet.h"
39 #include "sg.h"
40 #include "sc.h"
41 #include "polyedre.h"
42 #include "matrix.h"
43 
44 /* Pips includes */
45 #include "ri.h"
46 /* Types arc_label and vertex_label must be defined although they are
47  not used */
48 //typedef void * arc_label;
49 //typedef void * vertex_label;
50 #include "phrase.h"
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 #include "preprocessor.h"
65 #include "effects-convex.h"
66 #include "callgraph.h" // For compute_callees()
67 #include "effects-generic.h" // For compute_callees()
68 #include "accel-util.h" // For outliner()
69 #include "c_syntax.h"
70 #include "syntax.h"
71 #include "contrainte.h"
72 #include "vecteur.h"
73 #include "semantics.h"
74 #include "regions_to_loops.h"
75 
76 /* Filter the region list by removing irrelevant regions */
77 static void filter_regions(list* l) {
78  list l_temp = gen_copy_seq(*l);
79  descriptor d;
80  reference r;
81  list indices;
82  FOREACH(effect, e, l_temp) {
83  d = effect_descriptor(e);
84  r = effect_any_reference(e);
86  if (!effect_region_p(e) || indices == NIL || descriptor_none_p(d)) {
87  gen_remove(l, e);
88  }
89  }
90 }
91 
92 /* Makes the body of a "write" loop.
93  An assign statement is made using the array and the expression built using
94  read variables. This allows to avoid dead code elimination.
95 */
99  pips_assert("write body is not properly generated", statement_consistent_p(s));
100  return s;
101 }
102 
103 /* Makes the body of a "read" loop.
104  An assign statement is made using the variables generated and the array.
105 */
108  expression e2 = entity_to_expression(readVar);
109  statement s = make_assign_statement(e2, e);
110  pips_assert("read body is not properly generated", statement_consistent_p(s));
111  return s;
112 }
113 
114 /* Builds a loop from a Psysteme.
115  The same function is called whether it is a read or a write region, therefore the body changes.
116  Please refer to the documentation of algorithm_row_echelon_generic and systeme_to_loop_nest for more
117  details.
118  Depending on whether it is a read or a write region, readVar is entity_undefined or exp is expression_undefined.
119 */
120 static statement Psysteme_to_loop_nest(entity v,list vl, Pbase b, Psysteme p, bool isRead, entity readVar, expression exp, list l_var) {
121  Psysteme condition, enumeration;
122  statement body;
123  if (isRead)
124  body = make_read_loopbody(v, readVar, l_var);
125  else
126  body = make_write_loopbody(v, exp, l_var);
127  algorithm_row_echelon_generic(p, b, &condition, &enumeration, true);
129  pips_assert("s is not properly generated (systeme_to_loop_nest)", statement_consistent_p(s));
130  return s;
131 }
132 
133 /* Returns the entity corresponding to the global name */
134 /* static entity global_name_to_entity( const char* package, const char* name ) { */
135 /* return gen_find_tabulated(concatenate(package, MODULE_SEP_STRING, name, NULL), entity_domain); */
136 /* } */
137 
138 /* Takes a region, its type (R/W), a read variable OR an expression (one of them is undefined).
139  Returns a loop statement
140  The scalar case has been made just in case, due to the filter, there should be no scalar variables left in the region list
141 */
145  type t = entity_type(v);
147  if (type_variable_p(t)) {
148  variable tv = type_variable(t);
149  list dl = variable_dimensions(tv);
150  if (ENDP(dl)) {
151  s = make_nop_statement();
152  append_comments_to_statement(s, "scalar case");
153  }
154  else {
155  Psysteme p = region_system(r);
157  // Build the base
161  }
162  s = Psysteme_to_loop_nest(v, base_to_list(base), base, p, isRead, readVar, exp, reference_indices(ref));
163  }
164 
165  }
166  else {
167  pips_internal_error("unexpected type \n");
168  }
169  pips_assert("s is properly generated", statement_consistent_p(s));
170  return s;
171 
172 }
173 
174 /* Makes an addition expression from two expressions */
176  entity add_ent = gen_find_entity("TOP-LEVEL:+");
177  return make_call_expression(add_ent, CONS(EXPRESSION, e1, CONS(EXPRESSION, e2, NIL)));
178 }
179 
180 /* This function is in charge of replacing the PHI entity of the region by generated indices.
181  PHI values has no correspondance in the code. Therefore we have to create actual indices and
182  replace them in the region in order for the rest to be build using the right entities.
183 */
184 void replace_indices_region(region r, list* dadd, int indNum, entity module) {
185  Psysteme ps = region_system(r);
187  list ref_indices = reference_indices(ref);
188  list l_var = base_to_list(sc_base(ps));
189  list l_var_new = NIL;
190  list li = NIL;
191  // Default name given to indices
192  char* s = "REGIONS-PACKAGE:autogen";
193  char s2[128];
194  int indIntern = 0;
195  list l_var_temp = gen_nreverse(gen_copy_seq(l_var));
196  bool modified = false;
197  // The objective here is to explore the indices and the variable list we got from the base in order to compare and
198  // treat only the relevant cases
199  FOREACH(entity, e, l_var_temp) {
200  if (!ENDP(ref_indices)) {
201  FOREACH(expression, exp, ref_indices) {
203  if (!strcmp(entity_name(phi), entity_name(e))) {
204  // If the names match, we generate a new name for the variable
205  sprintf(s2, "%s_%d_%d", s, indNum, indIntern);
206  indIntern++;
207  // We make a copy of the entity with a new name
208  entity ec = make_entity_copy_with_new_name(e, s2, false);
209  // However the new variable still has a rom type of storage, therefore we create a new ram object
210  // entity dynamic_area = global_name_to_entity(module_local_name(module), DYNAMIC_AREA_LOCAL_NAME);
214  s2[0] = '\0';
215  // We build the list we are going to use to rename the variables of our system
216  l_var_new = CONS(ENTITY, ec, l_var_new);
217  // We build the list which will replace the list of indices of the region's reference
218  li = CONS(EXPRESSION, entity_to_expression(ec), li);
219  // We build the list which will be used to build the declaration statement
220  *dadd = CONS(ENTITY, ec, *dadd);
221  modified = true;
222  }
223  }
224  if (!modified) {
225  gen_remove_once(&l_var, e);
226  }
227  }
228  modified = false;
229  }
230  pips_assert("different length \n", gen_length(l_var) == gen_length(l_var_new));
231  // Renaming the variables of the system and replacing the indice list of the region's reference
232  ps = sc_list_variables_rename(ps, l_var, l_var_new);
234  pips_assert("region is not consistent", region_consistent_p(r));
235 }
236 
237 /* Make a sequence from a statement list
238  The equivalent of this function was already made somewhere else.
239  However when the list only has one element it returns that element
240  instead of making a sequence of one element containing that element.
241  This function always makes a sequence
242 */
244  if (l == NIL) {
245  return statement_undefined;
246  }
247  else {
248  if (gen_length(l) == 1) {
250  }
251  else {
252  return make_block_statement(l);
253  }
254  }
255 }
256 
257 /* This phase replaces the body of a function by automatically generated loops where the read
258  and write statements are representative of the original function.
259  If the regions are not computable then the function is not modified.
260 */
262  // List of the read/write regions
263  list l_write = NIL;
264  list l_read = NIL;
265 
266  // List of variables to add in the declaration statement
267  list declarations_to_add = NIL;
268 
269  // Standard initialization
271  statement module_stat = (statement)db_get_memory_resource(DBR_CODE, module_name, true);
272  set_ordering_to_statement(module_stat);
274  set_current_module_statement(module_stat);
276 
277  // We fetch the summary region list
278  list func_regions = effects_to_list((effects)db_get_memory_resource(DBR_SUMMARY_REGIONS, module_name, true));
279 
280  // And separate the R/W regions into two lists
281  l_write = regions_write_regions(func_regions);
282  l_read = regions_read_regions(func_regions);
283  // We remove irrelevant regions from the lists
284  filter_regions(&l_read);
285  filter_regions(&l_write);
286 
287  // If no regions were fetched or if no region is left after filtering then we do nothing
288  if (l_read == NIL && l_write == NIL) {
289  // Standard reset
296  return true;
297  }
298 
299  // List of statement we are going to use to build the new body of the function
300  list sl = NIL;
301  // Indices for variable and indices generation
302  int varNum = 0;
303  int indNum = 0;
304  // List of the generated variables for read purposes
305  list readVar = NIL;
306  // a simple "3" in order to complete the "write" assign statements in case there is no read
307  // Given that X1, X2 .. XN are the variables used to make the read statements
308  // X1+X2+..+XN+3 is the expression used to make the write statements
309  // In theory this avoids dead code elimination
311  // loop indice
312  int i = 0;
313 
314  // We build as many variable as there are read regions
315  for (i = 0; i < (int) gen_length(l_read); i++) {
317  // We add the new variable to the current expression used for write assignments
318  addVarRead = make_addition(addVarRead, entity_to_expression(e));
319  varNum++;
320  // We add this variable to a specific list
321  readVar = CONS(ENTITY, e, readVar);
322  }
323  // The variables for read purposes having been made, we can add them to the list of declarations to add
324  declarations_to_add = gen_nconc(declarations_to_add, readVar);
325 
326  // Read regions processing
327  // We replace the PHI variables of the region, we create a loop statement for this region and add
328  // it to the list of statement of the new body
329  FOREACH(effect, e, l_read) {
330  replace_indices_region(e, &declarations_to_add, indNum, module);
331  indNum++;
333  POP(readVar);
334  sl = CONS(STATEMENT, s, sl);
335  }
336 
337  // Write regions processing
338  // Same processing as above.
339  FOREACH(effect, e, l_write) {
340  replace_indices_region(e, &declarations_to_add, indNum, module);
341  indNum++;
342  statement s = region_to_loop_nest(e, false, entity_undefined, addVarRead);
343  sl = CONS(STATEMENT, s, sl);
344  }
345 
346  // Inverting and duplicating the elements of the list in order to avoid corrupting data structures.
348  // Make a new sequence statement in order to replace the old one
350 
351  // Using the list of variables needed to be declared we call a function
352  // appending declaration statements to our main sequence
353  declarations_to_add = gen_full_copy_list(gen_nreverse(declarations_to_add));
354  FOREACH(entity, e, declarations_to_add) {
355  ns = add_declaration_statement(ns, e);
356  }
357 
358  // Consistency check
359  pips_assert("list of statement is not consistent", statement_consistent_p(ns));
360  pips_assert("list of statement is not sequence", statement_sequence_p(ns));
361 
362  // Free of the old body
363  free_statement(module_stat);
364 
365  // Reorder and putting resource for the new function body
366  module_stat = ns;
367  module_reorder(module_stat);
368  DB_PUT_MEMORY_RESOURCE(DBR_CODE, module_name, module_stat);
369 
370  // Standard reset
377  return true;
378 }
entity gen_find_entity(char *s)
Definition: ri.c:2551
ram make_ram(entity a1, entity a2, intptr_t a3, list a4)
Definition: ri.c:1999
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
bool statement_consistent_p(statement p)
Definition: ri.c:2195
storage make_storage_ram(ram _field_)
Definition: ri.c:2279
void free_statement(statement p)
Definition: ri.c:2189
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
void const char const char const int
Pbase base_add_variable(Pbase b, Variable var)
Pbase base_add_variable(Pbase b, Variable v): add variable v as a new dimension to basis b at the end...
Definition: base.c:88
bdt base
Current expression.
Definition: bdt_read_paf.c:100
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
statement systeme_to_loop_nest(Psysteme, list, statement, entity)
sc is used to generate the loop nest bounds for variables vars.
#define region_system(reg)
#define effect_region_p(e)
#define region
simulation of the type region
bool region_consistent_p(region reg)
Definition: debug.c:50
list regions_write_regions(list)
Psysteme sc_list_variables_rename(Psysteme, list, list)
list regions_read_regions(list)
void set_methods_for_convex_effects(void)
methods.c
Definition: methods.c:235
void reset_out_summary_regions_list(void)
void reset_out_summary_effects_list(void)
out_effects_engine.c
void generic_effects_reset_all_methods(void)
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
list effects_to_list(effects)
Definition: effects.c:209
#define effect_descriptor(x)
Definition: effects.h:646
#define descriptor_none_p(x)
Definition: effects.h:602
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
statement make_block_statement(list)
Make a block statement from a list of statement.
Definition: statement.c:616
statement make_block_with_stmt_if_not_already(statement)
Build a statement block from a statement if not already a statement block.
Definition: statement.c:768
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
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
#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
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 POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
void gen_remove_once(list *pl, const void *o)
Remove the first occurence of o in list pl:
Definition: list.c:691
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
list gen_copy_seq(list l)
Copy a list structure.
Definition: list.c:501
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
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
#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
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
void * gen_car(list l)
Definition: list.c:364
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_sequence_p(statement)
Statement classes induced from instruction type.
Definition: statement.c:335
statement make_assign_statement(expression, expression)
Definition: statement.c:583
void append_comments_to_statement(statement, string)
Append a comment string (if non empty) to the comments of a statement, if the c.
Definition: statement.c:1889
statement add_declaration_statement(statement, entity)
Definition: statement.c:2790
list base_to_list(Pbase base)
Most includes are centralized here.
static list indices
Definition: icm.c:204
#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 DYNAMIC_AREA_LOCAL_NAME
Definition: naming-local.h:69
hash_table set_ordering_to_statement(statement s)
To be used instead of initialize_ordering_to_statement() to make sure that the hash table ots is in s...
Definition: ordering.c:172
void reset_ordering_to_statement(void)
Reset the mapping from ordering to statement.
Definition: ordering.c:185
static entity dynamic_area
static char * module
Definition: pips.c:74
static void filter_regions(list *l)
tatic_control
statement make_read_loopbody(entity v, entity readVar, list vl)
Makes the body of a "read" loop.
void replace_indices_region(region r, list *dadd, int indNum, entity module)
This function is in charge of replacing the PHI entity of the region by generated indices.
expression make_addition(expression e1, expression e2)
Makes an addition expression from two expressions.
bool regions_to_loops(char *module_name)
This phase replaces the body of a function by automatically generated loops where the read and write ...
statement make_write_loopbody(entity v, expression exp, list vl)
Makes the body of a "write" loop.
statement make_sequence_from_statement_list(list l)
Make a sequence from a statement list The equivalent of this function was already made somewhere else...
static statement Psysteme_to_loop_nest(entity v, list vl, Pbase b, Psysteme p, bool isRead, entity readVar, expression exp, list l_var)
Builds a loop from a Psysteme.
statement region_to_loop_nest(region r, bool isRead, entity readVar, expression exp)
Returns the entity corresponding to the global name.
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
#define make_nop_statement
An alias for make_empty_block_statement.
#define DIVIDE_OPERATOR_NAME
int current_offset_of_area(entity a, entity v)
Definition: area.c:174
entity FindEntity(const char *package, const char *name)
Retrieve an entity from its package/module name and its local name.
Definition: entity.c:1503
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
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
entity make_entity_copy_with_new_name(entity e, string global_new_name, bool move_initialization_p)
Create a copy of an entity, with (almost) identical type, storage and initial value if move_initializ...
Definition: entity.c:2463
expression reference_to_expression(reference r)
Definition: expression.c:196
expression make_call_expression(entity e, list l)
Build an expression that call an function entity with an argument list.
Definition: expression.c:321
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
entity make_new_module_variable(entity, int)
Make a new module integer variable of name X<d>.
Definition: variable.c:830
entity make_integer_constant_entity(_int)
entity make_integer_constant_entity(int c) make entity for integer constant c
Definition: variable.c:1345
#define syntax_reference(x)
Definition: ri.h:2730
#define reference_variable(x)
Definition: ri.h:2326
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define type_variable(x)
Definition: ri.h:2949
#define entity_storage(x)
Definition: ri.h:2794
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define entity_undefined
Definition: ri.h:2761
#define expression_undefined
Definition: ri.h:1223
#define entity_name(x)
Definition: ri.h:2790
#define reference_indices(x)
Definition: ri.h:2328
#define variable_dimensions(x)
Definition: ri.h:3122
#define entity_type(x)
Definition: ri.h:2792
#define expression_syntax(x)
Definition: ri.h:1247
#define type_variable_p(x)
Definition: ri.h:2947
#define statement_undefined
Definition: ri.h:2419
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
void algorithm_row_echelon_generic(Psysteme scn, Pbase base_index, Psysteme *pcondition, Psysteme *penumeration, bool redundancy)
each variable should be at least within one <= and one >=; scn IS NOT modified.
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
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
void * Variable
arithmetique is a requirement for vecteur, but I do not want to inforce it in all pips files....
Definition: vecteur-local.h:60
#define BASE_NULLE
MACROS SUR LES BASES.