PIPS
induction_substitution.c
Go to the documentation of this file.
1 /*
2 
3  $Id: induction_substitution.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 
25 // do not compiled unless required
26 #include "phases.h"
27 #ifdef BUILDER_INDUCTION_SUBSTITUTION
28 
29 #ifdef HAVE_CONFIG_H
30  #include "pips_config.h"
31 #endif
32 /* package induction_substitution
33  */
34 
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <math.h>
38 
39 #include "genC.h"
40 #include "linear.h"
41 
42 #include "misc.h"
43 #include "pipsdbm.h"
44 #include "properties.h"
45 
46 #include "ri.h"
47 #include "ri-util.h"
48 #include "prettyprint.h" // for debugging
49 #include "text-util.h" // dump_text
50 
51 #include "control.h" // clean_up_sequences, module_reorder
52 
53 #include "transformer.h" // used
54 #include "semantics.h" // used
55 #include "effects-generic.h" // used
56 
57 /* Context used for substitution with gen_context_recurse */
58 typedef struct {
59  entity to_substitute; /* The induction variable */
60  expression substitute_by; /* The substitution expression */
61  bool substitution_occured_p; /* flag to detect a substitution */
62  instruction root_instruction; /* instruction holding all the stuff we're working on */
63 } substitute_ctx;
64 
65 /** \fn static bool is_modified_entity_in_transformer( transformer T, entity ent )
66  * \brief Check in transformer if the entity ent is not (potentially) modified
67  * \param T the transformer that will be checked
68  * \param ent the entity we are looking for
69  * \return true if entity ent has been found in the transformer T
70  */
71 static bool is_modified_entity_in_transformer( transformer T, entity ent ) {
72  bool is_modified = false;
73 
75 
76  for ( list el = entities; !ENDP( el ); POP( el ) ) {
77  if ( ENTITY( CAR( el ) ) == ent ) {
78  is_modified = true;
79  break;
80  }
81  }
82  return is_modified;
83 }
84 
85 
86 /**
87  * Use transformer associated to the loop to check that variable v is invariant
88  */
89 static bool loop_invariant_p( Variable v, list /* of statements */ loops ) {
90  bool result = true;
91  FOREACH(statement, s, loops) {
93  if( is_modified_entity_in_transformer(t,(entity)v ) ) {
94  result = false;
95  }
96  }
97 
98  if(result) pips_debug(4,"%s is a loop invariant !\n",entity_name((entity)v));
99  else pips_debug(4,"%s is not a loop invariant !\n",entity_name((entity)v));
100 
101  return result;
102 }
103 
104 /**
105  * \brief check if the instruction is a --
106  */
107 static bool decrement_call_p( call c ) {
110  ;
111 }
112 
113 /**
114  * \brief check if the call is a ++
115  */
116 static bool increment_call_p( call c ) {
119  ;
120 }
121 
122 
123 /**
124  * \brief check if the call is a post operator ; like in i++ or i--
125  */
126 static bool post_inc_or_de_crement_call_p(call c) {
129  ;
130 }
131 
132 
133 /** \fn static bool reference_substitute( expression e, substitute_ctx *ctx )
134  * \brief callback for gen_recurse
135  * called during bottom-up phase on expression,
136  * in fact we aim to filter reference expressions only
137  * It will used context ctx to substitute references
138  * to ctx->to_substitute by the expression ctx->substitute_by
139  * \param e the expression that may contain a reference to the induction variable
140  * \param ctx the context contains the induction variable, and the substitute expression.
141  */
142 static void reference_substitute( expression e, substitute_ctx *ctx ) {
143  /* We filter expression that are references */
144  if ( syntax_reference_p( expression_syntax( e ) ) ) {
145  /* Check if the reference is the variable we aim to substitute */
146  if ( reference_variable( syntax_reference ( expression_syntax( e ) ) ) == ctx->to_substitute ) {
147 
148  ifdebug(6) {
149  pips_debug( 6, "Find substitution :" );
150  print_expression( e );
151  pips_debug( 6, "Will replace by :" );
152  print_expression( ctx->substitute_by );
153  }
154 
155  /* Delete the old syntax (no leak ;-))*/
157  /* Substitute by new one */
158  expression_syntax( e ) = copy_syntax( expression_syntax( ctx->substitute_by ) );
160  }
161  }
162 }
163 
164 
165 /**
166  * \brief Return an expression corresponding to the right part of an assignment
167  * \param c the call from which we want the right part
168  * \return the expression corresponding to right part of an assignment,
169  * or expression_undefined if instruction i is not an assignment.
170  */
171 static expression get_right_part_of_assignment( call c ) {
173  /* call must be an assignment or a self modifying operator : += /= *= -= */
174  if ( native_call_p( c, ASSIGN_OPERATOR_NAME ) //
179 
180  /* Right part of assignment is the arguments of the call but the first
181  * one (CDR jump it) */
182  e = EXPRESSION( CAR( CDR( call_arguments( c ) ) ) );
183  }
184  return e;
185 }
186 
187 
188 /**
189  * Substitute in an expression, this is a callback for gen_context_recurse
190  * It'll find all call and when the induction variable is on the left side,
191  * it'll replace the call with an equivalent expression using the substitute
192  * expression
193  */
194 static bool substitute_in_call( call c, substitute_ctx *ctx) {
195  entity induction_variable_candidate = ctx->to_substitute;
196  expression substitute = ctx->substitute_by;
197 
198  /* Sanity check */
199  if ( call_undefined_p(c) ) {
200  pips_user_error("call is undefined (and shouldn't be) !\n");
201  }
202 
203  /* Sanity check : we need at least an argument :) */
204  if( !call_arguments(c)) {
205  return true;
206  }
207 
208  //
209  expression unsugarized = expression_undefined;
210 
211  /* We want induction_variable_candidate to be the left part of the call */
212  expression e = EXPRESSION( CAR( call_arguments( c ) ) );
213  if (expression_reference_p( e )
214  && is_expression_reference_to_entity_p(e, induction_variable_candidate)){
215 
216  /* This call is candidate to a replacement, check if we can handled it ! */
217 
218 
219  /* In the case of unary operator, prepare the assignment
220  */
221  bool increment_p = increment_call_p( c );
222  bool decrement_p = decrement_call_p( c );
223 
224  if(increment_p || decrement_p ) {
225  if( increment_call_p( c ) ) {
226  unsugarized = make_op_exp( PLUS_OPERATOR_NAME , //
227  substitute, //
228  int_to_expression(1) );
229  } else if( decrement_call_p( c ) ) {
230  unsugarized = make_op_exp( MINUS_OPERATOR_NAME , //
231  substitute, //
232  int_to_expression(1) );
233  }
234 
235  } else {
236  /* We'll assume i isn't modified on the right hand side !
237  * There might be some weird "valid" statement like i = i++ && ... as &&
238  * is a synchronization point. More work required on the standard here :-(
239  */
240  expression substitute_on = get_right_part_of_assignment( c );
241  if(!expression_undefined_p(substitute_on)) {
242 
243  // We have a right part of an assignment, we can replace :)
244  gen_context_recurse ( substitute_on, ctx,
246  gen_true2,
247  reference_substitute );
248 
249  /* Force to generate again the normalized field of the expression */
250  expression_normalized(substitute_on) = NormalizeExpression( substitute_on );
251 
252  /* Handle "update" affection (+=, -= , ...)
253  * Transform z += 1 in z = induction + 1
254  */
256  unsugarized = make_op_exp( ( MULTIPLY_OPERATOR_NAME ), //
257  substitute, //
258  copy_expression( substitute_on ) );
259  } else if ( native_call_p( c, DIVIDE_UPDATE_OPERATOR_NAME ) ) {
260  unsugarized = make_op_exp( ( DIVIDE_OPERATOR_NAME ), //
261  substitute, //
262  copy_expression( substitute_on ) );
263  } else if ( native_call_p( c, PLUS_UPDATE_OPERATOR_NAME ) ) {
264  unsugarized = make_op_exp( ( PLUS_OPERATOR_NAME ), //
265  substitute, //
266  copy_expression( substitute_on ) );
267  } else if ( native_call_p( c, MINUS_UPDATE_OPERATOR_NAME ) ) {
268  unsugarized = make_op_exp( ( MINUS_OPERATOR_NAME ), //
269  substitute, //
270  copy_expression( substitute_on ) );
271  }
272  }
273  }
274  }
275 
276  if ( !expression_undefined_p( unsugarized ) ) {
277 
278  ifdebug( 1 ) {
279  pips_debug( 1, "Before update assignment : " );
281  fprintf(stderr,"\n");
282  }
283 
284  /* Force to generate again the normalized field of the expression */
285  expression_normalized(unsugarized) = NormalizeExpression( unsugarized );
286 
287  /* FIXME : free argument list for the call */
288  // ...
289 
290  /* Construct the unsugarized call */
292  CONS( EXPRESSION, //
293  entity_to_expression( induction_variable_candidate ), //
294  CONS(EXPRESSION, unsugarized, NIL ) ) );
295 
296 
297  if(post_inc_or_de_crement_call_p(c)) {
298  /* It's a separate case since there's no right hand side and we have to
299  * be sioux enough if it's a post increment :
300  * i++ has to be replaced by (i=i+1,i-1) so that the old value is returned
301  */
302 
303  /* if we have only k++; then no return value is needed. This occurs
304  * when ancestor is an instruction
305  */
306  instruction owner = ctx->root_instruction;
308  expression minus;
309  minus = make_op_exp( ( MINUS_OPERATOR_NAME ), //
310  entity_to_expression( induction_variable_candidate), //
311  int_to_expression(1) );
314  call_to_expression(new_call),
315  CONS(EXPRESSION, minus, NIL)));
316  }
317  }
318 
319 
320 //call_assign_contents(c,new_call); // Fails badly :-(
321  *c = *new_call;
322 
323  ctx->substitution_occured_p = true;
324 
325  ifdebug( 1 ) {
326  pips_debug( 1, "Unsugar update assignment : " );
328  }
329  }
330 
331 
332  return true;
333 }
334 
335 /**
336  * This function replace the variable induction_variable_candidate by expression
337  * substitute in call c.
338  * @param substitute is the replacement expression
339  * @param induction_variable_candidate is the variable to replace
340  * @param c is the call on which the substitution will occur. It'll be
341  * modified by side effect
342  */
343 static bool expression_subtitution_on_call( expression substitute,
344  entity induction_variable_candidate,
345  call c,
346  instruction root_instruction) {
347  ifdebug( 1 ) {
348  pips_debug(1, "Induction substitution : %s => ", //
349  entity_local_name( induction_variable_candidate ) );
350  print_syntax( expression_syntax( substitute ) );
351  fprintf(stderr, " on call : " );
352  print_expression(call_to_expression(c)); // Leak...
353  fprintf( stderr, "\n" );
354  }
355 
356  substitute_ctx ctx;
357  ctx.to_substitute = induction_variable_candidate;
358  ctx.substitute_by = substitute;
359  ctx.substitution_occured_p = false;
360  ctx.root_instruction = root_instruction;
361 
362  gen_context_recurse(c, &ctx, call_domain, substitute_in_call, gen_null2);
363 
364  return ctx.substitution_occured_p;
365 }
366 
367 
368 /** \fn static bool subtitute_induction_statement_in( statement s )
369  * \brief Call during top-down phase while recursing on statements
370  * Will use precondition on each assignment statement to construct
371  * substitution expression when possible
372  * \param s the statement that will be checked
373  * \return always true
374  */
375 static bool subtitute_induction_statement_in( statement s ) {
376  bool result = true;
377 
378  ifdebug( 1 ) {
379  pips_debug( 1, "Statement:\n" );
380  print_statement( s );
381  }
382 
383  // Get enclosing loops
385  if ( !ENDP( loops ) && !statement_loop_p(s) ) {
386  /* s is not a loop, but we must be somewhere inside a loop since we have some (useful) loop_indices */
387 
388  /* We'll evaluate now the instruction */
389  instruction stmt_instr = statement_instruction( s );
390 
391  call the_call = call_undefined;
392 
393  if( instruction_call_p( stmt_instr ) ) {
394  the_call = instruction_call( stmt_instr );
395  } else if(instruction_test_p(stmt_instr)) {
396  expression cond = test_condition(instruction_test(stmt_instr));
397  if(expression_call_p(cond)) {
398  the_call = expression_call(cond);
399  }
400  }
401 
402  if(!call_undefined_p(the_call)) {
403  /* The precondition will be used for building a substitution expression */
405 
406  ifdebug( 5 ) {
407  pips_debug( 5, "Preconditions:\n" );
408  text tmp = text_transformer( prec );
409  dump_text( tmp );
410  free_text( tmp );
411  pips_debug( 5, "Transformers:\n" );
413  dump_text( tmp );
414  free_text( tmp );
415  print_statement( s );
416  pips_debug( 5, "Nb of enclosing loops : %d\n", (int)gen_length(loops) );
417  }
418 
419  /* Get the set of preconditions equations from which we'll build substitution expressions */
420  transformer trans_range = transformer_range( prec );
422  Pcontrainte eqs = sc_egalites( D );
423  Pcontrainte c;
424 
425  /* Loop over equations
426  for each one we will evaluate if it can be used to produce a substitution expression,
427  and if applicable, we'll use this expression to make the substitution. */
428  for ( c = eqs; !CONTRAINTE_UNDEFINED_P( c ); c = contrainte_succ( c ) ) {
429  Pvecteur vec = contrainte_vecteur( c );
430  Pvecteur p;
431 
432  /* Loop over variable in this equation
433  simple induction variables are detected
434  The condition is that the equation has to involve only loop
435  indices, a constant, and the variable itself */
436 
437  bool found_loop_index = false; /* flag to keep track if we have find at least one loop index */
438  expression substitute = expression_undefined; /* the substitution expression */
439  Variable induction_variable_candidate = entity_undefined; /* the variable to substitute */
440  int induction_variable_candidate_coeff = 0; /* the coefficient associated to the variable */
441 
442  for ( p = vec; !VECTEUR_NUL_P( p ); p = vecteur_succ( p ) ) {
443  Variable v = vecteur_var( p ); /* Current variable */
444  Value coeff = vecteur_val( p ); /* Associate coefficient */
445  expression local_expr = expression_undefined; /* will be used to compute "coeff*v" */
446 
447  if ( v == TCST ) {
448  /* This is the constant term in the equation */
449  local_expr = int_to_expression( coeff );
450  } else {
451  /* We have a variable */
452 
453  if(index_of_a_loop_p(v, loops) || loop_invariant_p(v, loops)) {
454  /* We have found a loop index */
455  found_loop_index = true;
456  /* We build an expression "coeff*v" */
457  if ( coeff == -1 ) {
458  /* Coeff is -1, we want "-v" instead of "-1 * v" */
460  entity_to_expression( v ) );
461  } else if ( coeff == 1 ) {
462  /* Coeff is 1, we want "v" instead of "1 * v" */
463  local_expr = entity_to_expression( v );
464  } else {
465  /* General case : produce "coeff*v" */
466  local_expr = make_op_exp( ( MULTIPLY_OPERATOR_NAME ), //
467  int_to_expression( coeff ), //
468  entity_to_expression( v ) );
469  }
470  } else if ( !entity_undefined_p( induction_variable_candidate ) ) {
471  /* We have a variable that is not a loop index,
472  * but we already have one, so we abort substitution */
473  pips_debug(5,"We already have an induction candidate for this"
474  "equation (%s) and encounter a new one (%s), so skip "
475  "this equation...",
476  entity_local_name(induction_variable_candidate ),
477  entity_local_name(v));
478  induction_variable_candidate = entity_undefined;
479  break;
480  } else {
481  /* We have a variable that is not a loop index,
482  * and it's the first one, so record it */
483  induction_variable_candidate = v;
484  /* we have to take the opposite (-coeff) because we want
485  * to go from coeff*x+b=0 to x=b/(-coeff) */
486  induction_variable_candidate_coeff = -coeff;
487  }
488  }
489 
490  if ( !expression_undefined_p( local_expr ) ) {
491  /* we have a local_expr (loop index or constant) */
492  if ( expression_undefined_p( substitute ) ) {
493  /* it's the first one */
494  substitute = local_expr;
495  } else {
496  /* it's not the first one, we chain it with a "+" operation */
497  substitute = make_op_exp( PLUS_OPERATOR_NAME , //
498  local_expr, //
499  substitute );
500  }
501  }
502 
503  ifdebug( 5 ) {
504  if ( !expression_undefined_p( substitute ) ) {
505  pips_debug( 5, "Expression : " );
506  print_syntax( expression_syntax( substitute ) );
507  fprintf( stderr, "\n" );
508  }
509  }
510  }
511 
512 
513  ifdebug(4) {
514  if ( found_loop_index ) {
515  pips_debug(4,"Loop index found !\n");
516  } else {
517  pips_debug(4,"No loop index found !\n");
518  }
519  if ( !entity_undefined_p( induction_variable_candidate )) {
520  pips_debug(4,"Induction variable candidate found : %s\n",
521  entity_local_name(induction_variable_candidate));
522  } else {
523  pips_debug(4,"No Induction variable candidate found !\n");
524  }
525  if ( induction_variable_candidate_coeff != 0) {
526  pips_debug(4,"Variable is active !\n");
527  } else {
528  pips_debug(4,"Variable is not active !\n");
529  }
530  if ( !expression_undefined_p( substitute )) {
531  pips_debug(4,"The substitute expression is ");
532  print_syntax( expression_syntax( substitute ) );
533  fprintf( stderr, "\n" );
534  } else {
535  pips_debug(4,"The substitute expression is undefined.\n");
536  }
537  if( is_modified_entity_in_transformer(
539  induction_variable_candidate ) ) {
540  pips_debug(4,"Variable is modified by this statement\n");
541  } else {
542  pips_debug(4,"Variable is not modified by this statement\n");
543  }
544  }
545 
546  if ( found_loop_index // The expression depends on loop index
547  // We have found an induction variable
548  && !entity_undefined_p( induction_variable_candidate ) //
549  // The variable is really active (this check shouldn't be useful ?)
550  && induction_variable_candidate_coeff != 0 //
551  // We have a substitution expression to use :-)
552  && !expression_undefined_p( substitute ) //
553  ) {
554 
555  /* Add final division using the coeff */
556  if ( induction_variable_candidate_coeff == -1 ) {
557  /* Instead of dividing by -1, we rather use
558  * unary minus in front of expression */
559  substitute = make_op_exp( MINUS_OPERATOR_NAME ,
561  substitute );
562  } else if ( induction_variable_candidate_coeff != 1 ) {
563  /* General case */
564  substitute = make_op_exp( DIVIDE_OPERATOR_NAME , //
565  substitute, //
566  int_to_expression( induction_variable_candidate_coeff ) );
567  }
568 
569  if(is_modified_entity_in_transformer(load_statement_transformer( s ),
570  induction_variable_candidate )) {
571  // Variable is modified by this statement
572  expression_subtitution_on_call(substitute,
573  induction_variable_candidate,
574  the_call,
575  stmt_instr);
576  } else {
577  // Variable is not modified by this statement
578  substitute_ctx ctx;
579  ctx.to_substitute = induction_variable_candidate;
580  ctx.substitute_by = substitute;
581  ctx.substitution_occured_p = false;
582 
583  gen_context_recurse ( the_call, &ctx,
584  expression_domain, gen_true2, reference_substitute );
585 
586  }
587  }
588 
589  /* Free substitute expression */
590  if ( !expression_undefined_p( substitute ) ) {
591  // FIXME free_expression( substitute );
592  }
593  }
594  /* Try to avoid memory leak */
595  empty_transformer( trans_range );
596  transformer_free( trans_range );
597  }
598  }
599  return result;
600 }
601 
602 /** \fn bool induction_substitution( char * module_name )
603  * \brief This pass implement the detection and the substitution
604  * of induction variable in loop
605  * \param module_name the name of the module to work on
606  * \return currently always true
607  */
608 bool induction_substitution(const string module_name)
609 {
610  entity module;
611  statement module_stat;
612 
615 
617  module_stat = get_current_module_statement( );
618 
622 
624 
626 
627  debug_on( "INDUCTION_SUBSTITUTION_DEBUG_LEVEL" );
628  pips_debug( 1, "begin\n" );
629 
630 
631  pips_debug(6, "finding enclosing loops ...\n");
633 
634  /* We now traverse our module's statements. */
635  gen_recurse( module_stat,
636  statement_domain, subtitute_induction_statement_in, gen_null );
637 
638  /* Sanity checks */
639  pips_assert( "Consistent final check\n", gen_consistent_p( (gen_chunk *)module_stat ) );
640 
641  pips_debug( 1, "end\n" );
642  debug_off();
643 
644  /* Save modified code to database */
645  module_reorder( module_stat );
646  DB_PUT_MEMORY_RESOURCE( DBR_CODE, strdup( module_name ), module_stat );
647 
649 
652 
657 
659 
660  /* Return value */
661  bool good_result_p = true;
662 
663  return ( good_result_p );
664 
665 }
666 
667 #endif // BUILDER_INDUCTION_SUBSTITUTION
call make_call(entity a1, list a2)
Definition: ri.c:269
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
syntax copy_syntax(syntax p)
SYNTAX.
Definition: ri.c:2442
void free_syntax(syntax p)
Definition: ri.c:2445
void free_text(text p)
Definition: text.c:74
int Value
void transformer_free(transformer t)
Definition: basic.c:68
transformer empty_transformer(transformer t)
Do not allocate an empty transformer, but transform an allocated transformer into an empty_transforme...
Definition: basic.c:144
static list loops
#define CONTRAINTE_UNDEFINED_P(c)
#define contrainte_succ(c)
#define contrainte_vecteur(c)
passage au champ vecteur d'une contrainte "a la Newgen"
void reset_proper_rw_effects(void)
void set_proper_rw_effects(statement_effects)
void set_cumulated_rw_effects(statement_effects)
void reset_cumulated_rw_effects(void)
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
#define gen_context_recurse(start, ctxt, domain_number, flt, rwt)
Definition: genC.h:285
#define gen_recurse(start, domain_number, flt, rwt)
Definition: genC.h:283
int gen_consistent_p(gen_chunk *obj)
GEN_CONSISTENT_P dynamically checks the type correctness of OBJ.
Definition: genClib.c:2398
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 gen_null2(__attribute__((unused)) void *u1, __attribute__((unused)) void *u2)
idem with 2 args, to please overpeaky compiler checks
Definition: genClib.c:2758
bool gen_true2(__attribute__((unused)) gen_chunk *u1, __attribute__((unused)) void *u2)
Definition: genClib.c:2785
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
bool native_call_p(call c, string op_name)
Test if a call is a native instruction of the language.
Definition: instruction.c:124
void clean_enclosing_loops(void)
Definition: loop.c:58
bool index_of_a_loop_p(Variable v, list loops)
Check if variable v is an index for an enclosing loop.
Definition: loop.c:980
statement_mapping loops_mapping_of_statement(statement stat)
Definition: loop.c:155
#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 NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
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
#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
bool statement_loop_p(statement)
Definition: statement.c:349
#define D(A)
Definition: iabrev.h:56
#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_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define debug_off()
Definition: misc-local.h:160
#define pips_user_error
Definition: misc-local.h:147
normalized NormalizeExpression(expression e)
normalize.c
Definition: normalize.c:81
static char * module
Definition: pips.c:74
void print_syntax(syntax s)
Definition: expression.c:121
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
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
#define POST_DECREMENT_OPERATOR_NAME
Definition: ri-util-local.h:98
#define MINUS_OPERATOR_NAME
#define DIVIDE_UPDATE_OPERATOR_NAME
#define COMMA_OPERATOR_NAME
#define PLUS_OPERATOR_NAME
#define MULTIPLY_UPDATE_OPERATOR_NAME
#define MINUS_UPDATE_OPERATOR_NAME
#define PRE_DECREMENT_OPERATOR_NAME
#define DIVIDE_OPERATOR_NAME
#define UNARY_MINUS_OPERATOR_NAME
#define PRE_INCREMENT_OPERATOR_NAME
Definition: ri-util-local.h:99
#define POST_INCREMENT_OPERATOR_NAME
Definition: ri-util-local.h:97
#define PLUS_UPDATE_OPERATOR_NAME
#define MULTIPLY_OPERATOR_NAME
#define ASSIGN_OPERATOR_NAME
Definition: ri-util-local.h:95
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 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
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
call expression_call(expression e)
Definition: expression.c:445
expression int_to_expression(_int i)
transform an int into an expression and generate the corresponding entity if necessary; it is not cle...
Definition: expression.c:1188
expression make_op_exp(char *op_name, expression exp1, expression exp2)
================================================================
Definition: expression.c:2012
expression MakeUnaryCall(entity f, expression a)
Creates a call expression to a function with one argument.
Definition: expression.c:342
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
bool is_expression_reference_to_entity_p(expression e, entity v)
Test if an expression is a reference to a given variable entity.
Definition: expression.c:541
expression call_to_expression(call c)
Build an expression that call a function or procedure.
Definition: expression.c:309
list load_statement_enclosing_loops(statement)
void set_enclosing_loops_map(statement_mapping)
#define normalized_undefined
Definition: ri.h:1745
#define syntax_reference_p(x)
Definition: ri.h:2728
#define expression_domain
newgen_execution_domain_defined
Definition: ri.h:154
#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 call_undefined_p(x)
Definition: ri.h:686
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define entity_undefined_p(x)
Definition: ri.h:2762
#define entity_undefined
Definition: ri.h:2761
#define expression_undefined
Definition: ri.h:1223
#define entity_name(x)
Definition: ri.h:2790
#define transformer_relation(x)
Definition: ri.h:2873
#define expression_normalized(x)
Definition: ri.h:1249
#define transformer_arguments(x)
Definition: ri.h:2871
#define instruction_call_p(x)
Definition: ri.h:1527
#define expression_undefined_p(x)
Definition: ri.h:1224
#define test_condition(x)
Definition: ri.h:2833
#define statement_instruction(x)
Definition: ri.h:2458
#define instruction_call(x)
Definition: ri.h:1529
#define instruction_test_p(x)
Definition: ri.h:1515
#define call_arguments(x)
Definition: ri.h:711
#define instruction_test(x)
Definition: ri.h:1517
#define call_undefined
Definition: ri.h:685
#define expression_syntax(x)
Definition: ri.h:1247
#define predicate_system(x)
Definition: ri.h:2069
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
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
text text_transformer(transformer tran)
text text_transformer(transformer tran) input : a transformer representing a transformer or a precond...
Definition: prettyprint.c:464
transformer load_statement_precondition(statement)
void set_transformer_map(statement_mapping)
transformer load_statement_transformer(statement)
void reset_precondition_map(void)
void set_precondition_map(statement_mapping)
void reset_transformer_map(void)
#define ifdebug(n)
Definition: sg.c:47
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
Definition: pip__tab.h:48
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
void dump_text(text t)
FI: print_text() should be fprint_text() and dump_text(), print_text()
Definition: print.c:205
bool induction_substitution(const string)
induction_substitution.c
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
A gen_chunk is used to store every object.
Definition: genC.h:58
#define TCST
VARIABLE REPRESENTANT LE TERME CONSTANT.
#define vecteur_val(v)
#define vecteur_var(v)
#define vecteur_succ(v)
#define VECTEUR_NUL_P(v)
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