PIPS
singleass.c
Go to the documentation of this file.
1 /*
2 
3  $Id: singleass.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 #include "genC.h"
29 #include "linear.h"
30 #include "ri.h"
31 #include "effects.h"
32 
33 #include "resources.h"
34 
35 #include "misc.h"
36 #include "ri-util.h"
37 #include "effects-util.h"
38 #include "text-util.h"
39 #include "pipsdbm.h"
40 
41 #include "effects-generic.h"
42 
43 #include "control.h"
44 #include "transformations.h"
45 #include "effects-simple.h"
46 #include "sac.h"
47 #include "ricedg.h"
48 
49 /* helper thats checks if entity @p e is involved in a conflict of successor @p s
50  * */
55  )
56  return true;
57  }
58  return false;
59 }
60 /* helper that checks if there is a cycle from @p curr back to @p v following chains of @p e */
61 static bool vertex_in_cycle_aux_p(vertex v, entity e, vertex curr,set visited) {
62  if(v==curr) return true;
63  if(set_belong_p(visited,curr)) return false;
64  set_add_element(visited,visited,curr);
68  return true;
69  }
70  return false;
71 }
72 
73 /* check if there is a cycle from @pv to @p v following chains from @p e */
74 static bool vertex_in_cycle_p(vertex v, entity e ) {
75  set visited = set_make(set_pointer);
78  vertex_in_cycle_aux_p(v,e,successor_vertex(s),visited)) {
79  set_free(visited);
80  return true;
81  }
82  }
83  set_free(visited);
84  return false;
85 }
86 
87 /* @return the list of vertices for which a write on @p e leads to a new declaration
88  * that is writes without reductions or cycles
89  */
91  set live_writes = set_make(set_pointer);
94  bool read_p = effects_read_variable_p(effects,e),
95  write_p = effects_write_variable_p(effects,e);
96  if( write_p && !read_p && !vertex_in_cycle_p(v,e) )
97  set_add_element(live_writes,live_writes,v);
98  }
99  return live_writes;
100 }
101 
102 static void do_scalar_renaming_in_successors(vertex v, entity e, entity new, set live_writes, hash_table visited, hash_table renamings)
103 {
106  vertex v2 = successor_vertex(s);
107  bool read_p = false;
108  /* check if sink is read */
110  if(effect_read_p(conflict_sink(c))) {
111  read_p= true;
112  break;
113  }
114  }
115  /* this successor belongs to the def-use chain */
116  if(read_p && !set_belong_p(live_writes,v2)) {
117  /* was it already renamed ? */
118  entity renamed = (entity)hash_get(visited,v2);
119  /* no -> proceeed */
120  if(renamed == HASH_UNDEFINED_VALUE) {
121  hash_put(visited,v2,new);
123  do_scalar_renaming_in_successors(v2,e,new,live_writes,visited,renamings);
124  }
125  /* yes, but no conflict */
126  else if (same_entity_p(renamed,new) ) {
127  continue;
128  }
129  /* yes and a conbflict -> fix it by adding an assign */
130  else {
131  set renaming = (set) hash_get(renamings,v);
135  false);
139  hash_put_or_update(renamings,v,renaming);
140  }
141  continue;
142  }
143  }
144  }
145  }
146 }
147 
148 static void do_scalar_renaming_in_vertex(vertex v, entity e, set live_writes, hash_table visited, hash_table renamings) {
149 
150  /* create new assigned value */
155  /* propagate it to each reading successor */
156  do_scalar_renaming_in_successors(v,e,new,live_writes,visited,renamings);
157 }
158 
159 
161  set live_writes = graph_to_live_writes(g, e);
164  list l = set_to_sorted_list(live_writes,compare_vertex);
165  FOREACH(VERTEX,v,l) {
167  if(!declaration_statement_p(s) ||
169  do_scalar_renaming_in_vertex(v,e,live_writes,visited,renamings);
170  }
171  hash_table_free(visited);
172  HASH_FOREACH(entity,k,set,v,renamings) set_free(v);
173  hash_table_free(renamings);
174  gen_free_list(l);
175  set_free(live_writes);
176 }
177 
178 /* do scalar renaming for graph @p dg of module @p module and statements @p module_statement
179  */
181 
183  /* only local non static scalar entities
184  * non static as a quick fix ...*/
187  }
189  unnormalize_expression(module_statement); // overkill ? It's not a game of kick-the-orphe
190 }
191 
192 /* recursievly computes the set of all chains involving e starting from v */
193 static set vertex_to_chains(vertex v, entity e, set visited) {
194  set all = set_make(set_pointer);
195  if(!set_belong_p(visited,v)) {
196  set_add_element(visited,visited,v);
198  bool read_p = effects_read_variable_p(effects,e),
199  write_p = effects_write_variable_p(effects,e);
200  if(read_p||write_p) {
201  list this = CONS(VERTEX,v,NIL);
202  set_add_element(all,all,this);
205  vertex v2 = successor_vertex(s);
208  {
209  set tmp2=vertex_to_chains(v2,e,visited);
210  SET_FOREACH(list,ltmp,tmp2)
211  set_add_element(all,all,CONS(VERTEX,v,ltmp));
212  set_free(tmp2);
213  }
214  }
215  }
216  }
217  }
218  return all;
219 }
220 
221 /* we know l is included in l2, let's remove redundant arcs */
222 static void do_prune_arcs(list l, list l2) {
223  bool same_chain_p = false;
224  vertex prev = vertex_undefined;
225  for(;!ENDP(l)&&!ENDP(l2);POP(l2)) {
226  vertex v = VERTEX(CAR(l)),
227  v2=VERTEX(CAR(l2));
228  if(v==v2) {
229  same_chain_p=true;
230  prev=v;
231  POP(l);
232  }
233  else if(same_chain_p) {
234  /* arc between prev and v are not needed */
235  set remove = set_make(set_pointer);
237  if(v==successor_vertex(s))
238  set_add_element(remove,remove,s);
239  SET_FOREACH(successor,s,remove)
241  set_free(remove);
242  }
243  }
244 }
245 
246 /* remove all conflicts that involve entity e
247  * and that can be regenerated from another conflict chain
248  */
249 static void do_simplify_dg(graph g, entity e) {
251  /* SG: I am not sure it is ok to prune the exploration space like this */
252  set visited = set_make(set_pointer);
254  set tmp = vertex_to_chains(v,e,visited);
255  set_union(chains,chains,tmp);
256  set_free(tmp);
257  }
258  set_free(visited);
259  /* arcs now holds all possible arcs of g that impact e
260  * let's remove the chains that are not needed, that is those that have an englobing chain */
261  SET_FOREACH(list,l,chains) {
262  SET_FOREACH(list,l2,chains) {
263  /* if s is included in s2, arcs in s not is s2 are not needed */
264  if(l!=l2) {
265  set s = set_make(set_pointer);
266  set_assign_list(s,l);
267  set s2 = set_make(set_pointer);
268  set_assign_list(s2,l2);
269  /* prune some arcs */
270  if(set_inclusion_p(s,s2))
271  do_prune_arcs(l,l2);
272  set_free(s);
273  set_free(s2);
274  }
275  }
276  }
277 #if 0 //that's some ugly debug !
278  FILE * fd = fopen("/tmp/a.dot","w");
280  fclose(fd);
281 #endif
282 
283 }
284 /* removes redundant arcs from dg.
285  * An arc from v to v' is redundant if there exist a chain in dg that
286  * goes from v to v'
287  */
290  /* only local entity */
292  do_simplify_dg(dg,e);
293  }
294  }
295 }
296 
297 
298 /* rename scalars to remove some false dependencies
299  */
300 bool scalar_renaming(char * mod_name)
301 {
302  /* Get the resources */
303  statement mod_stmt = (statement)
304  db_get_memory_resource(DBR_CODE, mod_name, true);
305  graph dg = (graph) db_get_memory_resource(DBR_DG, mod_name, true);
306 
309  set_ordering_to_statement(mod_stmt); /* needed for vertex_to_statement */
310 
312  db_get_memory_resource(DBR_PROPER_EFFECTS, mod_name, true));
313 
314  debug_on("SCALAR_RENAMING_DEBUG_LEVEL");
315 
316  /* prune graph */
318 
319  /* Now do the job */
321 
322  pips_assert("Statement is consistent after SCALAR_RENAMING",
323  statement_consistent_p(mod_stmt));
324 
325  /* Reorder the module, because new statements have been added */
326  module_reorder(mod_stmt);
327 
328  DB_PUT_MEMORY_RESOURCE(DBR_CODE, mod_name, mod_stmt);
329 
330  /* update/release resources */
335 
336  debug_off();
337 
338  return true;
339 }
basic copy_basic(basic p)
BASIC.
Definition: ri.c:104
bool statement_consistent_p(statement p)
Definition: ri.c:2195
value copy_value(value p)
VALUE.
Definition: ri.c:2784
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
static statement module_statement
Definition: alias_check.c:125
static bool chains(char *module_name, enum chain_type use)
Compute chain dependence for a module according different kinds of store-like effects.
Definition: chains.c:1397
static graph dg
dg is the dependency graph ; FIXME : should not be static global ?
Definition: chains.c:124
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
#define conflict_sink(x)
Definition: dg.h:167
#define CONFLICT(x)
CONFLICT.
Definition: dg.h:134
#define dg_arc_label_conflicts(x)
Definition: dg.h:201
#define conflict_source(x)
Definition: dg.h:165
list load_proper_rw_effects_list(statement)
void reset_proper_rw_effects(void)
void set_proper_rw_effects(statement_effects)
#define effect_read_p(eff)
#define effect_scalar_p(eff) entity_scalar_p(effect_entity(eff))
#define effect_any_entity(e)
some useful SHORTHANDS for EFFECT:
bool effects_read_variable_p(list, entity)
Definition: effects.c:1123
bool effects_write_variable_p(list, entity)
Definition: effects.c:1091
#define gen_chunk_undefined_p(c)
Definition: genC.h:75
#define successor_vertex(x)
Definition: graph.h:118
#define vertex_undefined
Definition: graph.h:128
#define successor_arc_label(x)
Definition: graph.h:116
struct _newgen_struct_graph_ * graph
Definition: graph.h:31
#define vertex_successors(x)
Definition: graph.h:154
#define SUCCESSOR(x)
SUCCESSOR.
Definition: graph.h:86
#define graph_vertices(x)
Definition: graph.h:82
#define VERTEX(x)
VERTEX.
Definition: graph.h:122
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
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 replace_entity(void *s, entity old, entity new)
per variable version of replace_entities.
Definition: replace.c:113
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#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
#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 FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
void * gen_find_eq(const void *item, const list seq)
Definition: list.c:422
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
statement make_assign_statement(expression, expression)
Definition: statement.c:583
void insert_statement(statement, statement, bool)
This is the normal entry point.
Definition: statement.c:2570
bool declaration_statement_p(statement)
Had to be optimized according to Beatrice Creusillet.
Definition: statement.c:224
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
statement vertex_to_statement(vertex v)
Vertex_to_statement looks for the statement that is pointed to by vertex v.
Definition: util.c:45
#define debug_on(env)
Definition: misc-local.h:157
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define debug_off()
Definition: misc-local.h:160
@ 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_put_or_update(h, k, v)
Definition: newgen_hash.h:80
#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
struct _set_chunk * set
Definition: newgen_set.h:38
list set_to_sorted_list(const set, gen_cmp_func_t)
Definition: set.c:447
#define SET_FOREACH(type_name, the_item, the_set)
enumerate set elements in their internal order.
Definition: newgen_set.h:78
void set_free(set)
Definition: set.c:332
bool set_inclusion_p(const set, const set)
return whether s1 \included s2
Definition: set.c:305
bool set_belong_p(const set, const void *)
Definition: set.c:194
set set_union(set, const set, const set)
Definition: set.c:211
@ 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
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
void unnormalize_expression(void *st)
void unnormalize_expression(expression exp): puts all the normalized field of expressions in "st" to ...
Definition: normalize.c:452
static char * module
Definition: pips.c:74
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
#define entity_declarations(e)
MISC: newgen shorthands.
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
bool same_entity_p(entity e1, entity e2)
predicates on entities
Definition: entity.c:1321
bool local_entity_of_module_p(entity e, entity module)
This test shows that "e" has been declared in "module".
Definition: entity.c:1069
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
basic entity_basic(entity e)
return the basic associated to entity e if it's a function/variable/constant basic_undefined otherwis...
Definition: entity.c:1380
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
bool entity_static_variable_p(entity)
return true if the entity is declared with the keyword static
Definition: variable.c:1146
bool entity_scalar_p(entity)
The concrete type of e is a scalar type.
Definition: variable.c:1113
void AddEntityToCurrentModule(entity)
Add a variable entity to the current module declarations.
Definition: variable.c:260
entity make_new_scalar_variable_with_prefix(const char *, entity, basic)
Create a new scalar variable of type b in the given module.
Definition: variable.c:592
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define statement_ordering(x)
Definition: ri.h:2454
#define statement_declarations(x)
Definition: ri.h:2460
#define entity_initial(x)
Definition: ri.h:2796
int compare_vertex(const void *, const void *)
compare two vertices based on their ordering
Definition: util.c:58
void prettyprint_dot_dependence_graph(FILE *, statement, graph)
Output dependence graph in a file in graphviz dot format.
Definition: util.c:583
static void do_prune_arcs(list l, list l2)
we know l is included in l2, let's remove redundant arcs
Definition: singleass.c:222
static set vertex_to_chains(vertex v, entity e, set visited)
recursievly computes the set of all chains involving e starting from v
Definition: singleass.c:193
static void do_scalar_renaming_in_graph(graph g, entity e)
Definition: singleass.c:160
static void do_simplify_dg(graph g, entity e)
remove all conflicts that involve entity e and that can be regenerated from another conflict chain
Definition: singleass.c:249
static void simplify_dg(entity module, graph dg)
removes redundant arcs from dg.
Definition: singleass.c:288
bool scalar_renaming(char *mod_name)
rename scalars to remove some false dependencies
Definition: singleass.c:300
static bool vertex_in_cycle_p(vertex v, entity e)
check if there is a cycle from @pv to v following chains from e
Definition: singleass.c:74
static bool vertex_in_cycle_aux_p(vertex v, entity e, vertex curr, set visited)
helper that checks if there is a cycle from curr back to v following chains of e
Definition: singleass.c:61
static bool successor_conflicts_on_entity_p(successor s, entity e)
helper thats checks if entity e is involved in a conflict of successor s
Definition: singleass.c:51
static void do_scalar_renaming(entity module, statement module_statement, graph dg)
do scalar renaming for graph dg of module module and statements module_statement
Definition: singleass.c:180
static set graph_to_live_writes(graph g, entity e)
Definition: singleass.c:90
static void do_scalar_renaming_in_successors(vertex v, entity e, entity new, set live_writes, hash_table visited, hash_table renamings)
Definition: singleass.c:102
static void do_scalar_renaming_in_vertex(vertex v, entity e, set live_writes, hash_table visited, hash_table renamings)
Definition: singleass.c:148
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
void module_clean_declarations(entity module, statement module_statement)
declarations.c
Definition: declarations.c:140