PIPS
if_conversion_compact.c
Go to the documentation of this file.
1 /*
2 
3  $Id: if_conversion_compact.c 23495 2018-10-24 09:19:47Z 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 <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 
32 #include "genC.h"
33 #include "linear.h"
34 #include "ri.h"
35 #include "effects.h"
36 
37 #include "ri-util.h"
38 #include "prettyprint.h"
39 #include "effects-util.h"
40 #include "text-util.h"
41 #include "database.h"
42 #include "misc.h"
43 #include "pipsdbm.h"
44 #include "resources.h"
45 #include "control.h"
46 
47 #include "effects-generic.h"
48 #include "effects-simple.h"
49 #include "properties.h"
50 
51 #include "sac.h"
52 #include "ricedg.h"
53 
54 
55 /**
56  * checks wether a statement is a phi function call of the form
57  * a=phi(cond, vt,vf)
58  * where phi is given by a property
59  *
60  * @param s statement to check
61  *
62  * @return result of the check
63  */
64 static bool
66 {
68  {
70  if(expression_call_p(rhs))
71  {
72  const char* phi_name = get_string_property("IF_CONVERSION_PHI");
73  entity phi = entity_intrinsic(phi_name);
75  }
76  }
77  return false;
78 }
79 
80 
81 /**
82  * try to compact two phi-statements into a single one
83  *
84  * @param s0 first statement to compact
85  * @param s1 second statement to compact
86  *
87  * @return true if compaction succeeded, false otherwise
88  */
90 {
91  /* all datas are handeled as pairs in an array of 2 elements
92  * we use i and !i to denote current index and its opposite
93  */
94  statement s [2] = { s0,s1 };
95 
96  expression lhs[2];
97  for(size_t i=0;i<2;i++)
98  lhs[i]=binary_call_lhs(statement_call(s[i]));
99 
100  /* let's compare assignment part */
101  if(same_expression_p(lhs[0],lhs[1]) && expression_reference_p(lhs[0]))
102  {
103 
104  /* ok it may be good, now
105  let's compare both phi functions */
106  call phis[2];
107  reference ref[2];
108  expression cond[2], true_val[2], false_val[2];
109  for(size_t i=0;i<2;i++)
110  {
111  ref[i]=expression_reference(lhs[i]);
113  cond[i]=EXPRESSION(CAR(call_arguments(phis[i])));
114  true_val[i]=EXPRESSION(CAR(CDR(call_arguments(phis[i]))));
115  false_val[i]=EXPRESSION(CAR(CDR(CDR(call_arguments(phis[i])))));
116  }
117 
118  /* first constraint : ref[i] == false_val[i] */
119  if( expression_reference_p(false_val[0]) && expression_reference_p(false_val[1]))
120  {
121  if(reference_equal_p(ref[0],expression_reference(false_val[0])) &&
122  reference_equal_p(ref[1],expression_reference(false_val[1])))
123  {
124  /* second constraint : cond[0] == !cond[1] */
125  bool ok = false;
126  size_t i;
127  for(i =0;i<2;i++)
128  {
129  if(expression_call(cond[!i]) && ENTITY_NOT_P(call_function(expression_call(cond[!i]))))
130  {
132  cond[i])))
133  break;
134  }
135  }
136  if(ok)
137  {
138  /* yes, we have in s1 a = cond ? b:a; and in s2 a = !cond ? c: a;
139  * it will become a = cond ? b :c ;*/
140 
141  /* 1:replace false_val[i] by true_val[!i]*/
142  free_expression(false_val[i]);
143  *REFCAR(CDR(CDR(call_arguments(phis[i]))))=(gen_chunkp)true_val[!i];
144  /* 2:unlink true_val[!i]*/
146  /* 3: replace s[!i] by a continue */
148  return true;
149  }
150  }
151  }
152  }
153  return false;
154 }
155 
156 /**
157  * checks if there is a write-read conflict between @a source and @a sink
158  * according to dg successors @a source_successors
159  */
160 static bool
161 statement_conflicts_p(statement sink,list source_successors)
162 {
163  FOREACH(SUCCESSOR,s,source_successors)
164  {
166  if(ss==sink)
167  {
169  {
170  /* if there is a write-read conflict, we cannot do much */
173  return true;
174 
175  }
176  }
177  }
178  return false;
179 }
180 
181 /*
182  This function does the job for each sequence.
183  */
185 {
186  // Only look at the sequence statements
187  if(statement_block_p(stat))
188  {
190 
191  for(list iter = statement_block(stat);!ENDP(iter);POP(iter))
192  {
193  statement st = STATEMENT(CAR(iter));
195  {
196  ifdebug(1) {
197  pips_debug(1,"checking statement:\n");
198  print_statement(st);
199  }
200  /* iterate over the trailing statements to find a legal statement to compact
201  * we stop when a conflict is found or when we achived our goal
202  */
203  list succ = hash_get(successors,st);
204  FOREACH(STATEMENT,next,CDR(iter))
205  {
206 
207  if(statement_phi_function_p(next))
208  {
209  if(compact_phi_functions(st,next))
210  {
211  ifdebug(1) {
212  pips_debug(1,"compacted into statement:\n");
213  print_statement(st);
214  }
215  break;
216  }
217  }
218  /* look for a write - read conflict between st and next */
219  else if(statement_conflicts_p(next, succ)) break;
220  }
221  }
222  }
224  }
225 }
226 
227 /*
228  This phase is applied after if_conversion phase and will changes:
229 
230  .
231  .
232  .
233  I = PHI(L, I1, I)
234  .
235  .
236  .
237  I = PHI(.NOT.L, I2, I)
238  .
239  .
240  .
241 
242 into:
243 
244 .
245 .
246 .
247 I = PHI(L, I1, I2)
248 .
249 .
250 .
251 */
252 bool if_conversion_compact(char * mod_name)
253 {
254  // get the resources
255  statement mod_stmt = (statement)
256  db_get_memory_resource(DBR_CODE, mod_name, true);
257 
260  set_ordering_to_statement(mod_stmt);
261 
262  graph dg = (graph) db_get_memory_resource(DBR_DG, mod_name, true);
263 
265  db_get_memory_resource(DBR_PROPER_EFFECTS, mod_name, true));
266 
267  debug_on("IF_CONVERSION_COMPACT_DEBUG_LEVEL");
268  // Now do the job
269 
271 
272  // Reorder the module, because new statements have been added
273  module_reorder(mod_stmt);
274  DB_PUT_MEMORY_RESOURCE(DBR_CODE, mod_name, mod_stmt);
275 
276  // update/release resources
281 
282  debug_off();
283 
284  return true;
285 }
void free_expression(expression p)
Definition: ri.c:853
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
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
static list successors(list l)
#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
void reset_proper_rw_effects(void)
void set_proper_rw_effects(statement_effects)
#define effect_write_p(eff)
#define effect_read_p(eff)
#define effect_scalar_p(eff) entity_scalar_p(effect_entity(eff))
char * get_string_property(const char *)
#define gen_context_recurse(start, ctxt, domain_number, flt, rwt)
Definition: genC.h:285
#define gen_chunk_undefined
Definition: genC.h:74
union gen_chunk * gen_chunkp
#define successor_vertex(x)
Definition: graph.h:118
#define successor_arc_label(x)
Definition: graph.h:116
struct _newgen_struct_graph_ * graph
Definition: graph.h:31
#define SUCCESSOR(x)
SUCCESSOR.
Definition: graph.h:86
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
bool gen_true2(__attribute__((unused)) gen_chunk *u1, __attribute__((unused)) void *u2)
Definition: genClib.c:2785
instruction make_continue_instruction()
Creates a CONTINUE instruction, that is the FORTRAN nop, the ";" in C or the "pass" in Python for exa...
Definition: instruction.c:79
#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
#define REFCAR(pc)
Get the adress of the first element of a list.
Definition: newgen_list.h:119
#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
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
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 statement_block(statement)
Get the list of block statements of a statement sequence.
Definition: statement.c:1338
call statement_call(statement)
Get the call of a statement.
Definition: statement.c:1406
statement update_statement_instruction(statement, instruction)
Replace the instruction in statement s by instruction i.
Definition: statement.c:3039
bool assignment_statement_p(statement)
Test if a statement is an assignment.
Definition: statement.c:135
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_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
static bool statement_phi_function_p(statement s)
checks wether a statement is a phi function call of the form a=phi(cond, vt,vf) where phi is given by...
bool if_conversion_compact(char *mod_name)
cproto-generated files
static bool compact_phi_functions(statement s0, statement s1)
try to compact two phi-statements into a single one
static bool statement_conflicts_p(statement sink, list source_successors)
checks if there is a write-read conflict between source and sink according to dg successors source_su...
static void if_conversion_compact_stats(statement stat, graph dg)
#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 debug_off()
Definition: misc-local.h:160
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 print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
#define binary_call_rhs(c)
#define statement_block_p(stat)
#define ENTITY_NOT_P(e)
#define binary_call_lhs(c)
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
bool expression_call_p(expression e)
Definition: expression.c:415
bool expression_equal_p(expression e1, expression e2)
Syntactic equality e1==e2.
Definition: expression.c:1347
call expression_call(expression e)
Definition: expression.c:445
bool reference_equal_p(reference r1, reference r2)
Definition: expression.c:1500
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
bool same_expression_p(expression e1, expression e2)
this is slightly different from expression_equal_p, as it will return true for a+b vs b+a
Definition: expression.c:1426
#define call_function(x)
Definition: ri.h:709
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define call_arguments(x)
Definition: ri.h:711
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
hash_table statements_to_successors(list, graph)
creates a hash_table containing statements from statements as keys and their respective succesors acc...
Definition: util.c:1018
s1
Definition: set.c:247
#define ifdebug(n)
Definition: sg.c:47
static bool ok
The structure used to build lists in NewGen.
Definition: newgen_list.h:41