PIPS
simple_atomize.c
Go to the documentation of this file.
1 /*
2 
3  $Id: simple_atomize.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 <stdio.h>
29 #include <string.h>
30 
31 #include "genC.h"
32 
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 "misc.h"
41 #include "properties.h"
42 
43 /* void atomize_as_required(stat, ref_decide, call_decide, test_decide, range_decide, while_decide, new)
44  * statement stat;
45  * bool (*ref_decide)(ref r, expression e);
46  * bool (*call_decide)(call r, expression e);
47  * bool (*test_decide)(test t, expression e);
48  * bool (*range_decide)(range r, expression e),
49  * bool (*while_decide)(whileloop w, expression e),
50  * entity (*new)(entity m, basic b);
51  *
52  * atomizes the given statement as driven by the given functions.
53  * ??? does not care of any side effect and so.
54  *
55  * - ref_decide tells whether or not to atomize for reference r
56  * and expression indice e of this reference. If yes, expression e
57  * is computed outside.
58  * - call_decide tells whether or not to atomize for call c
59  * and argument expression e...
60  * - test_decide tells whether expression condition e of a test
61  * should be atomized or not.
62  * - new creates a new entity in the current module, the basic type
63  * of which should be t.
64  */
65 
66 static void atomize_object(gen_chunk*);
67 
68 /* static functions used
69  */
70 static bool (*ref_atomize_decision)(/* ref r, expression e */) = NULL;
71 static bool (*call_atomize_decision)(/* call c, expression e */)= NULL;
72 static bool (*test_atomize_decision)(/* expression e */) = NULL;
73 static bool (*range_atomize_decision)(/* range r, expression e */)= NULL;
74 static bool (*while_atomize_decision)(/* whileloop w, expression e */)= NULL;
75 
76 static entity (*create_new_variable)(/* entity m, tag t */) = NULL;
77 
78 
79 /* the stack of the encoutered statements is maintained
80  * to be able to insert the needed computations just before the
81  * very last statement encountered.
82  *
83  * The use of a stack is not necessary, since there are no effective rewrite.
84  * but it could have been... It enables some recursive calls that would have
85  * required to save the current statement explicitely otherwise.
86  */
88 DEFINE_LOCAL_STACK(current_control, control)
89 
91 {
92  error_reset_current_statement_stack();
93  error_reset_current_control_stack();
94 }
95 
96 /* s is inserted before the current statement.
97  * if it is a block, it is added just before the last statement of the block,
98  * else a block statement is created in place of the current statement.
99  */
101 {
102  statement cs = current_statement_head();
104  control cc = current_control_empty_p() ?
105  control_undefined : current_control_head() ;
106 
107  if (!control_undefined_p(cc) && control_statement(cc)==cs)
108  {
109  /* it is in an unstructured, and s is to be inserted properly
110  */
111  bool seen;
112  control newc;
113 
114  pips_debug(8, "unstructured\n");
115 
116  newc = make_control(s, control_predecessors(cc),
117  CONS(CONTROL, cc, NIL));
118  control_predecessors(cc) = CONS(CONTROL, newc, NIL);
119 
120  /* update the other lists
121  */
122  MAPL(c1,
123  {
124  seen=false;
125 
126  MAPL(c2,
127  {
128  if (CONTROL(CAR(c2))==cc)
129  {
130  CONTROL_(CAR(c2))=newc;
131  seen=true;
132  }
133  },
135 
136  assert(seen);
137  },
138  control_predecessors(newc));
139 
140  /* new current statement, to avoid other control insertions
141  */
142  current_statement_replace(s);
143  gen_recurse_stop(newc);
144  }
145  else
146  {
147  pips_debug(7, "statement\n");
148 
149  if (instruction_block_p(i)) {
150  list /* of statement */ block = instruction_block(i);
151  /* insert statement before the last one */
154  block);
155  }
156  else {
159  CONS(STATEMENT, s,
160  CONS(STATEMENT,
162  statement_number(cs),
163  statement_ordering(cs),
164  statement_comments(cs),
166  NIL, NULL,
169  NIL)));
175  }
176  }
177 }
178 
179 /* returns the assignment statement is moved, or NULL if not.
180  */
182  entity (*create)(entity, basic),
183  expression e)
184 {
185  /* it does not make sense to atomize a range...
186  */
187  if (syntax_range_p(expression_syntax(e))) return NULL;
188 
189  basic bofe = basic_of_expression(e);
190  statement out = NULL;
191  if(!basic_undefined_p(bofe)) {
192  if (!basic_overloaded_p(bofe))
193  {
194  bool skip_this_expression = false;
195  if( get_bool_property("COMMON_SUBEXPRESSION_ELIMINATION_SKIP_ADDED_CONSTANT") && expression_call_p(e) )
196  {
197  call c = expression_call(e);
198  entity op = call_function(c);
200  {
202  skip_this_expression|=expression_constant_p(arg);
203  }
204 
205  }
206 
207  if(!skip_this_expression) {
208  ifdebug(1) {
209  pips_debug(1,"atomizing expression:\n");
210  print_expression(e);
211  }
212  entity newvar = (*create)(get_current_module_entity(), copy_basic(bofe));
213  AddEntityToCurrentModule(newvar);
216 
218 
220  expression_syntax(e) = ref;
221  }
222  }
223  }
224  free_basic(bofe);
225  return out;
226 }
227 
229 {
231  if (stat) insert_before_current_statement(stat);
232 }
233 
234 static void ref_rwt(reference r)
235 {
236  MAPL(ce,
237  {
238  expression *pe = (expression*) REFCAR(ce);
239 
240  if ((*ref_atomize_decision)(r, *pe))
241  {
242  /* syntax saved = expression_syntax(*pe);*/
244  /* atomize_object(saved); */
245  }
246  },
247  reference_indices(r));
248 
249  /* return(false);*/
250 }
251 
252 static void call_rwt(call c)
253 {
255  return; /* (panic mode:-) */
256 
257  MAPL(ce,
258  {
259  expression *pe = (expression*) REFCAR(ce);
260 
261  if ((*call_atomize_decision)(c, *pe))
262  {
263  /* syntax saved = expression_syntax(*pe);*/
264 
266  /* atomize_object(saved); */
267  }
268  },
269  call_arguments(c));
270 }
271 
272 
273 static void exp_range_rwt (range r, expression * pe)
274 {
275  if ((*range_atomize_decision)(r, *pe))
276  {
277  /* syntax saved = expression_syntax(*pe); */
279  /* atomize_object(saved);*/
280  }
281 }
282 
283 static void range_rwt(range r)
284 {
285  /* lower */
286  exp_range_rwt(r, &range_lower(r));
287 
288  /* upper */
289  exp_range_rwt(r, &range_upper(r));
290 
291  /* increment */
293 }
294 
295 
296 static void test_rwt(test t)
297 {
298  expression *pe = &test_condition(t);
299 
300  if ((*test_atomize_decision)(t, *pe))
301  {
302  /* syntax saved = expression_syntax(*pe);*/
303  /* else I have to break the condition
304  * and to complete the recursion.
305  */
307  /* atomize_object(saved); */
308  }
309 }
310 
311 static void whileloop_rwt(whileloop w)
312 {
314 
315  if ((*while_atomize_decision)(w, *pe))
316  {
317  /* syntax saved = expression_syntax(*pe); */
318  /* else I have to break the condition
319  * and to complete the recursion.
320  */
322  /* atomize_object(saved);*/
323  }
324 }
325 
327 {
329  {
332  /* the subscript could be a reference ! */
333  {
335 
336  /* update reference with additionnal indices */
337  reference r = syntax_reference(sa);
339  /* prepare to free subscript */
342  free_subscript(s);
343  /* transform subscript into reference */
346  }
347  }
348 }
349 
351 {
352  if(expression_call_p(exp)) {
353  call c = expression_call(exp);
355  expression lhs = binary_call_lhs(c);
356  if(expression_call_p(lhs)) {
357  call c = expression_call(lhs);
359  expression lhs = binary_call_lhs(c);
360  syntax syn = expression_syntax(lhs);
363  }
364  }
365  }
366  }
367 }
368 
369 void cleanup_subscripts(void* obj)
370 {
373 }
374 
375 static void atomize_object(gen_chunk *obj)
376 {
378  (obj,
379  control_domain, current_control_filter,
380  current_control_rewrite, /* CONTROL */
381  statement_domain, current_statement_filter,
382  current_statement_rewrite, /* STATEMENT */
383  reference_domain, gen_true, ref_rwt, /* REFERENCE */
384  test_domain, gen_true, test_rwt, /* TEST */
385  call_domain, gen_true, call_rwt, /* CALL */
386  range_domain, gen_true, range_rwt, /* RANGE */
387  whileloop_domain, gen_true, whileloop_rwt,/* WHILELOOP */
388  NULL);
389  cleanup_subscripts(obj);
390 }
391 
393  statement stat,
394  bool (*ref_decide)(reference, expression), /* reference */
395  bool (*call_decide)(call, expression), /* call */
396  bool (*test_decide)(test, expression), /* test */
397  bool (*range_decide)(range, expression), /* range */
398  bool (*while_decide)(whileloop, expression), /* whileloop */
399  entity (*new)(entity, basic))
400 {
401  ifdebug(5) {
402  pips_debug(5,
403  "Statement at entry:\n");
404  print_statement(stat);
405  }
407  make_current_statement_stack();
408  make_current_control_stack();
409  ref_atomize_decision = ref_decide;
410  call_atomize_decision = call_decide;
411  test_atomize_decision = test_decide;
412  range_atomize_decision = range_decide;
413  while_atomize_decision = while_decide;
414  create_new_variable = new;
415 
416  atomize_object((gen_chunkp) stat);
417 
418  ref_atomize_decision = NULL;
419  call_atomize_decision = NULL;
420  test_atomize_decision = NULL;
421  range_atomize_decision = NULL;
422  while_atomize_decision = NULL;
423  create_new_variable = NULL;
424  free_current_statement_stack();
425  free_current_control_stack();
427 
428  ifdebug(5) {
429  pips_debug(5,
430  "Statement at exit:\n");
431  print_statement(stat);
432  }
433 }
434 
435 /* that is all
436  */
437 
438 
439 
440 
static hash_table seen
static function to store whether a module has been seen during the recursive generation of the daVinc...
Definition: graph.c:85
expression make_expression(syntax a1, normalized a2)
Definition: ri.c:886
basic copy_basic(basic p)
BASIC.
Definition: ri.c:104
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
statement make_statement(entity a1, intptr_t a2, intptr_t a3, string a4, instruction a5, list a6, string a7, extensions a8, synchronization a9)
Definition: ri.c:2222
void free_subscript(subscript p)
Definition: ri.c:2294
syntax copy_syntax(syntax p)
SYNTAX.
Definition: ri.c:2442
synchronization make_synchronization_none(void)
Definition: ri.c:2424
void free_basic(basic p)
Definition: ri.c:107
control make_control(statement a1, list a2, list a3)
Definition: ri.c:523
syntax make_syntax_reference(reference _field_)
Definition: ri.c:2494
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
static FILE * out
Definition: alias_check.c:128
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
#define gen_recurse(start, domain_number, flt, rwt)
Definition: genC.h:283
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_multi_recurse(void *o,...)
Multi recursion visitor function.
Definition: genClib.c:3428
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
instruction make_instruction_block(list statements)
Build an instruction block from a list of statements.
Definition: instruction.c:106
#define REFCAR(pc)
Get the adress of the first element of a list.
Definition: newgen_list.h:119
#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 CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
list gen_last(list l)
Return the last element of a list.
Definition: list.c:578
#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 MAPL(_map_list_cp, _code, _l)
Apply some code on the addresses of all the elements of a list.
Definition: newgen_list.h:203
list gen_insert_before(const void *no, const void *o, list l)
Definition: list.c:238
statement make_assign_statement(expression, expression)
Definition: statement.c:583
bool expression_constant_p(expression)
HPFC module by Fabien COELHO.
Definition: expression.c:2453
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
void reset_hooks_unregister(reset_func_t)
remove registered cleanup hook.
Definition: reset_hooks.c:73
void reset_hooks_register(reset_func_t)
reset_hooks.c
Definition: reset_hooks.c:44
#define STATEMENT_ORDERING_UNDEFINED
mapping.h inclusion
Definition: newgen-local.h:35
#define assert(ex)
Definition: newgen_assert.h:41
#define DEFINE_LOCAL_STACK(name, type)
#define same_string_p(s1, s2)
int bool
we cannot use an enum or stdbool because we need to be compatible with newgen, thus boolean need to h...
Definition: newgen_types.h:78
void normalize_all_expressions_of(void *obj)
Definition: normalize.c:668
void print_expression(expression e)
no file descriptor is passed to make is easier to use in a debugging stage.
Definition: expression.c:58
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
void create(char *workspace_name, char **filenames)
create a new workspace...
Definition: pypips.c:239
#define ENTITY_PLUS_UPDATE_P(e)
#define instruction_block_p(i)
#define ENTITY_DEREFERENCING_P(e)
#define ENTITY_PLUS_P(e)
#define STATEMENT_NUMBER_UNDEFINED
default values
#define IMPLIED_DO_NAME
Definition: ri-util-local.h:75
#define ENTITY_PLUS_C_P(e)
#define binary_call_lhs(c)
#define instruction_block(i)
#define ENTITY_ADDRESS_OF_P(e)
#define empty_comments
Empty comments (i.e.
const char * entity_local_name(entity e)
entity_local_name modified so that it does not core when used in vect_fprint, since someone thought t...
Definition: entity.c:453
entity entity_empty_label(void)
Definition: entity.c:1105
bool expression_call_p(expression e)
Definition: expression.c:415
call expression_call(expression e)
Definition: expression.c:445
void update_expression_syntax(expression e, syntax s)
frees expression syntax of e and replace it by the new syntax s
Definition: expression.c:3564
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
extensions empty_extensions(void)
extension.c
Definition: extension.c:43
basic basic_of_expression(expression)
basic basic_of_expression(expression exp): Makes a basic of the same basic as the expression "exp".
Definition: type.c:1383
void AddEntityToCurrentModule(entity)
Add a variable entity to the current module declarations.
Definition: variable.c:260
#define test_domain
newgen_entity_domain_defined
Definition: ri.h:418
#define normalized_undefined
Definition: ri.h:1745
#define expression_domain
newgen_execution_domain_defined
Definition: ri.h:154
#define control_undefined
Definition: ri.h:916
#define CONTROL_(x)
Definition: ri.h:913
#define syntax_reference(x)
Definition: ri.h:2730
#define syntax_tag(x)
Definition: ri.h:2727
#define call_function(x)
Definition: ri.h:709
#define control_predecessors(x)
Definition: ri.h:943
#define range_upper(x)
Definition: ri.h:2290
#define statement_ordering(x)
Definition: ri.h:2454
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define control_domain
newgen_controlmap_domain_defined
Definition: ri.h:98
#define CONTROL(x)
CONTROL.
Definition: ri.h:910
@ is_syntax_reference
Definition: ri.h:2691
#define range_increment(x)
Definition: ri.h:2292
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58
#define basic_overloaded_p(x)
Definition: ri.h:623
#define basic_undefined_p(x)
Definition: ri.h:557
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define subscript_indices(x)
Definition: ri.h:2563
#define statement_label(x)
Definition: ri.h:2450
#define reference_domain
newgen_range_domain_defined
Definition: ri.h:338
#define reference_indices(x)
Definition: ri.h:2328
#define statement_extensions(x)
Definition: ri.h:2464
#define control_successors(x)
Definition: ri.h:945
#define control_undefined_p(x)
Definition: ri.h:917
#define test_condition(x)
Definition: ri.h:2833
#define subscript_array(x)
Definition: ri.h:2561
#define range_lower(x)
Definition: ri.h:2288
#define whileloop_domain
newgen_variable_domain_defined
Definition: ri.h:466
#define statement_instruction(x)
Definition: ri.h:2458
#define syntax_undefined
Definition: ri.h:2676
#define statement_comments(x)
Definition: ri.h:2456
#define syntax_subscript(x)
Definition: ri.h:2745
#define call_arguments(x)
Definition: ri.h:711
#define control_statement(x)
Definition: ri.h:941
#define whileloop_condition(x)
Definition: ri.h:3160
#define syntax_range_p(x)
Definition: ri.h:2731
#define statement_number(x)
Definition: ri.h:2452
#define expression_syntax(x)
Definition: ri.h:1247
#define range_domain
newgen_ram_domain_defined
Definition: ri.h:330
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define syntax_subscript_p(x)
Definition: ri.h:2743
static statement current_statement
#define ifdebug(n)
Definition: sg.c:47
static void compute_before_current_statement(expression *pe)
static void ref_rwt(reference r)
static void atomize_object(gen_chunk *)
void atomize_as_required(stat, ref_decide, call_decide, test_decide, range_decide,...
static void cleanup_subscript_pre(expression exp)
static bool(* range_atomize_decision)()
static bool(* ref_atomize_decision)()
static functions used
static void cleanup_subscript(expression e)
static entity(* create_new_variable)()
void atomize_as_required(statement stat, bool(*ref_decide)(reference, expression), bool(*call_decide)(call, expression), bool(*test_decide)(test, expression), bool(*range_decide)(range, expression), bool(*while_decide)(whileloop, expression), entity(*new)(entity, basic))
static void whileloop_rwt(whileloop w)
static bool(* call_atomize_decision)()
void cleanup_subscripts(void *obj)
static void test_rwt(test t)
static void insert_before_current_statement(statement s)
s is inserted before the current statement.
static bool(* test_atomize_decision)()
static bool(* while_atomize_decision)()
static void simple_atomize_error_handler()
the stack of the encoutered statements is maintained to be able to insert the needed computations jus...
statement atomize_this_expression(entity(*create)(entity, basic), expression e)
returns the assignment statement is moved, or NULL if not.
static void call_rwt(call c)
static void range_rwt(range r)
static void exp_range_rwt(range r, expression *pe)
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
A gen_chunk is used to store every object.
Definition: genC.h:58
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207