PIPS
ri_to_transformer_lists.c File Reference
#include <stdio.h>
#include <string.h>
#include "genC.h"
#include "database.h"
#include "linear.h"
#include "ri.h"
#include "effects.h"
#include "text.h"
#include "text-util.h"
#include "ri-util.h"
#include "prettyprint.h"
#include "effects-util.h"
#include "constants.h"
#include "effects-generic.h"
#include "effects-simple.h"
#include "misc.h"
#include "properties.h"
#include "transformer.h"
#include "semantics.h"
+ Include dependency graph for ri_to_transformer_lists.c:

Go to the source code of this file.

Functions

list declaration_to_transformer_list (entity v, transformer pre)
 Postpone convex hulls by keeping transformer lists instead. More...
 
list declarations_to_transformer_list (list dl, transformer pre)
 For C declarations. More...
 
static list block_to_transformer_list (list b, transformer pre)
 Generate all possible linear control paths. More...
 
static list test_to_transformer_list (test t, transformer pre, list ef)
 effects of t More...
 
list intrinsic_to_transformer_list (entity e, list pc, transformer pre, list ef)
 because of the conditional and the comma C intrinsics at least More...
 
list assigned_expression_to_transformer_list (entity v, expression expr, transformer pre)
 transformer assigned_expression_to_transformer(entity e, expression expr, list ef): returns a transformer abstracting the effect of assignment "e = expr" when possible, transformer_undefined otherwise. More...
 
list safe_assigned_expression_to_transformer_list (entity v, expression expr, transformer pre)
 Always returns a fully defined transformer. More...
 
list integer_assign_to_transformer_list (expression lhs, expression rhs, transformer pre, list ef)
 This function never returns an undefined transformer. More...
 
list any_scalar_assign_to_transformer_list (entity v, expression rhs, list ef, transformer pre)
 precondition More...
 
list any_assign_to_transformer_list (list args, list ef, transformer pre)
 precondition More...
 
list any_update_to_transformer_list (entity op, list args, list ef, transformer pre)
 precondition More...
 
list any_basic_update_to_transformer_list (entity op, list args, list ef, transformer pre)
 precondition More...
 
static list instruction_to_transformer_list (instruction i, transformer tf, transformer pre, list e)
 effects associated to instruction i More...
 
list statement_to_transformer_list (statement s, transformer spre)
 A transformer is already available for statement s, but it is going to be refined into a list of transformers to isolate at least the identity transformer from effective transformers. More...
 

Function Documentation

◆ any_assign_to_transformer_list()

list any_assign_to_transformer_list ( list  args,
list  ef,
transformer  pre 
)

precondition

The lhs must be a scalar reference to perform an interesting analysis

if some condition was not met and transformer derivation failed

Parameters
argsrgs
efarguments for assign
preeffects of assign

Definition at line 777 of file ri_to_transformer_lists.c.

780 {
781  list tl = NIL;
783  expression lhs = EXPRESSION(CAR(args));
784  expression rhs = EXPRESSION(CAR(CDR(args)));
785  syntax slhs = expression_syntax(lhs);
786 
787  pips_internal_error("Not implemented yet.");
788 
789  pips_assert("2 args to assign", CDR(CDR(args))==NIL);
790 
791  /* The lhs must be a scalar reference to perform an interesting analysis */
792  if(syntax_reference_p(slhs)) {
793  reference rlhs = syntax_reference(slhs);
794  if(ENDP(reference_indices(rlhs))) {
795  entity v = reference_variable(rlhs);
796  tf = any_scalar_assign_to_transformer(v, rhs, ef, pre);
797  }
798  }
799 
800  /* if some condition was not met and transformer derivation failed */
801  if(tf==transformer_undefined)
802  tf = effects_to_transformer(ef);
803 
804  pips_debug(6,"return tl=%p\n", tl);
805  ifdebug(6) (void) print_transformers(tl);
806  pips_debug(8,"end\n");
807  return tl;
808 }
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
#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 pips_internal_error
Definition: misc-local.h:149
list print_transformers(list tl)
Definition: io.c:62
#define syntax_reference_p(x)
Definition: ri.h:2728
#define transformer_undefined
Definition: ri.h:2847
#define syntax_reference(x)
Definition: ri.h:2730
#define reference_variable(x)
Definition: ri.h:2326
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define reference_indices(x)
Definition: ri.h:2328
#define expression_syntax(x)
Definition: ri.h:1247
transformer effects_to_transformer(list e)
list of effects
transformer any_scalar_assign_to_transformer(entity v, expression rhs, list ef, transformer pre)
precondition
#define ifdebug(n)
Definition: sg.c:47
The structure used to build lists in NewGen.
Definition: newgen_list.h:41

References any_scalar_assign_to_transformer(), CAR, CDR, effects_to_transformer(), ENDP, EXPRESSION, expression_syntax, ifdebug, NIL, pips_assert, pips_debug, pips_internal_error, print_transformers(), reference_indices, reference_variable, syntax_reference, syntax_reference_p, and transformer_undefined.

+ Here is the call graph for this function:

◆ any_basic_update_to_transformer_list()

list any_basic_update_to_transformer_list ( entity  op,
list  args,
list  ef,
transformer  pre 
)

precondition

The lhs must be a scalar reference to perform an interesting analysis

if some condition was not met and transformer derivation failed

Parameters
opp
argsrgs
efarguments for update
preeffects of assign

Definition at line 849 of file ri_to_transformer_lists.c.

853 {
854  list tl = NIL;
856  expression lhs = EXPRESSION(CAR(args));
857  syntax slhs = expression_syntax(lhs);
858 
859  pips_internal_error("Not implemented yet.");
860 
861  pips_assert("1 arg for basic_update", CDR(args)==NIL);
862 
863  /* The lhs must be a scalar reference to perform an interesting analysis */
864  if(syntax_reference_p(slhs)) {
865  reference rlhs = syntax_reference(slhs);
866  if(ENDP(reference_indices(rlhs))) {
867  entity v = reference_variable(rlhs);
871 
873  ve = int_to_expression(1);
874  else
875  ve = int_to_expression(-1);
876 
877  n_rhs = MakeBinaryCall(plus, ve, copy_expression(lhs));
878 
879  tf = any_scalar_assign_to_transformer(v, n_rhs, ef, pre);
880  free_expression(n_rhs);
881  }
882  }
883 
884  /* if some condition was not met and transformer derivation failed */
885  if(tf==transformer_undefined)
886  tf = effects_to_transformer(ef);
887 
888  pips_debug(6,"return tl=%p\n", tl);
889  ifdebug(6) (void) print_transformers(tl);
890  pips_debug(8,"end\n");
891  return tl;
892 }
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
void free_expression(expression p)
Definition: ri.c:853
#define ENTITY_POST_INCREMENT_P(e)
#define ENTITY_PRE_INCREMENT_P(e)
#define PLUS_C_OPERATOR_NAME
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
expression MakeBinaryCall(entity f, expression eg, expression ed)
Creates a call expression to a function with 2 arguments.
Definition: expression.c:354
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
#define expression_undefined
Definition: ri.h:1223

References any_scalar_assign_to_transformer(), CAR, CDR, copy_expression(), effects_to_transformer(), ENDP, entity_intrinsic(), ENTITY_POST_INCREMENT_P, ENTITY_PRE_INCREMENT_P, EXPRESSION, expression_syntax, expression_undefined, free_expression(), ifdebug, int_to_expression(), MakeBinaryCall(), NIL, pips_assert, pips_debug, pips_internal_error, PLUS_C_OPERATOR_NAME, print_transformers(), reference_indices, reference_variable, syntax_reference, syntax_reference_p, and transformer_undefined.

+ Here is the call graph for this function:

◆ any_scalar_assign_to_transformer_list()

list any_scalar_assign_to_transformer_list ( entity  v,
expression  rhs,
list  ef,
transformer  pre 
)

precondition

Is it standard compliant? The assigned variable is modified by the rhs.

Take care of aliasing

tf = transformer_value_substitute(tf, v_new, v_old);

Parameters
rhshs
eff
preeffects of assign

Definition at line 709 of file ri_to_transformer_lists.c.

713 {
714  list tl = NIL;
716 
717  pips_internal_error("Not implemented yet.");
718 
719  if(entity_has_values_p(v)) {
720  entity v_new = entity_to_new_value(v);
721  entity v_old = entity_to_old_value(v);
723 
724  tf = any_expression_to_transformer(tmp, rhs, pre, true);
725 
726  if(!transformer_undefined_p(tf)) {
727 
728  pips_debug(9, "A transformer has been obtained:\n");
729  ifdebug(9) dump_transformer(tf);
730 
732  /* Is it standard compliant? The assigned variable is modified by the rhs. */
733  transformer teq = simple_equality_to_transformer(v, tmp, true);
734  string s = expression_to_string(rhs);
735 
736  semantics_user_warning("Variable \"%s\" in lhs is uselessly or illegally updated by rhs '%s;'\n",
737  entity_user_name(v), s);
738  // entity_local_name(v), s);
739 
740  free(s);
741 
742  tf = transformer_combine(tf, teq);
743  free_transformer(teq);
744  }
745  else {
746  /* Take care of aliasing */
747  entity v_repr = value_to_variable(v_new);
748 
749  /* tf = transformer_value_substitute(tf, v_new, v_old); */
750  tf = transformer_value_substitute(tf, v_new, v_old);
751 
752  pips_debug(9,"After substitution v_new=%s -> v_old=%s\n",
753  entity_local_name(v_new), entity_local_name(v_old));
754 
755  tf = transformer_value_substitute(tf, tmp, v_new);
756 
757  pips_debug(9,"After substitution tmp=%s -> v_new=%s\n",
758  entity_local_name(tmp), entity_local_name(v_new));
759 
761  }
762  }
763  if(!transformer_undefined_p(tf)) {
765  pips_debug(9, "After temporary value projection, tf=%p:\n", tf);
766  ifdebug(9) dump_transformer(tf);
767  }
769  }
770 
772  tf = effects_to_transformer(ef);
773 
774  return tl;
775 }
void free_transformer(transformer p)
Definition: ri.c:2616
bool entity_is_argument_p(entity e, cons *args)
Definition: arguments.c:150
transformer transformer_add_modified_variable(transformer tf, entity var)
FI: this function does not end up with a consistent transformer because the old value is not added to...
Definition: basic.c:889
if(!(yy_init))
Definition: genread_lex.c:1029
void free(void *)
string expression_to_string(expression e)
Definition: expression.c:77
#define dump_transformer(t)
Definition: print.c:355
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
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
type ultimate_type(type)
Definition: type.c:3466
#define transformer_undefined_p(x)
Definition: ri.h:2848
#define transformer_arguments(x)
Definition: ri.h:2871
#define entity_type(x)
Definition: ri.h:2792
#define semantics_user_warning
transformer any_expression_to_transformer(entity v, expression expr, transformer pre, bool is_internal)
A set of functions to compute the transformer associated to an expression evaluated in a given contex...
Definition: expression.c:4993
return(s1)
transformer transformer_combine(volatile transformer t1, transformer t2)
transformer transformer_combine(transformer t1, transformer t2): compute the composition of transform...
Definition: transformer.c:238
transformer transformer_value_substitute(transformer t, entity e1, entity e2)
transformer transformer_value_substitute(transformer t, entity e1, entity e2): if e2 does not appear ...
Definition: transformer.c:1993
transformer transformer_temporary_value_projection(transformer tf)
Definition: transformer.c:1149
transformer simple_equality_to_transformer(entity e, entity f, bool assignment)
e and f are assumed to be values, Type independent.
Definition: transformer.c:58
entity make_local_temporary_value_entity(type)
Definition: value.c:605
entity entity_to_new_value(entity)
Definition: value.c:859
void reset_temporary_value_counter(void)
Definition: value.c:250
bool entity_has_values_p(entity)
This function could be made more robust by checking the storage of e.
Definition: value.c:911
entity entity_to_old_value(entity)
Definition: value.c:869
entity value_to_variable(entity)
Get the primitive variable associated to any value involved in a transformer.
Definition: value.c:1624

References any_expression_to_transformer(), dump_transformer, effects_to_transformer(), entity_has_values_p(), entity_is_argument_p(), entity_local_name(), entity_to_new_value(), entity_to_old_value(), entity_type, entity_user_name(), expression_to_string(), free(), free_transformer(), ifdebug, make_local_temporary_value_entity(), NIL, pips_debug, pips_internal_error, reset_temporary_value_counter(), semantics_user_warning, simple_equality_to_transformer(), transformer_add_modified_variable(), transformer_arguments, transformer_combine(), transformer_temporary_value_projection(), transformer_undefined, transformer_undefined_p, transformer_value_substitute(), ultimate_type(), and value_to_variable().

+ Here is the call graph for this function:

◆ any_update_to_transformer_list()

list any_update_to_transformer_list ( entity  op,
list  args,
list  ef,
transformer  pre 
)

precondition

The lhs must be a scalar reference to perform an interesting analysis

if some condition was not met and transformer derivation failed

Parameters
opp
argsrgs
efarguments for update
preeffects of assign

Definition at line 810 of file ri_to_transformer_lists.c.

814 {
815  list tl = NIL;
817  expression lhs = EXPRESSION(CAR(args));
818  expression rhs = EXPRESSION(CAR(CDR(args)));
819  syntax slhs = expression_syntax(lhs);
820 
821  pips_internal_error("Not implemented yet.");
822 
823  pips_assert("2 args for regular update", CDR(CDR(args))==NIL);
824 
825  /* The lhs must be a scalar reference to perform an interesting analysis */
826  if(syntax_reference_p(slhs)) {
827  reference rlhs = syntax_reference(slhs);
828  if(ENDP(reference_indices(rlhs))) {
829  entity v = reference_variable(rlhs);
832  expression n_rhs = MakeBinaryCall(sop, ve, copy_expression(rhs));
833 
834  tf = any_scalar_assign_to_transformer(v, n_rhs, ef, pre);
835  free_expression(n_rhs);
836  }
837  }
838 
839  /* if some condition was not met and transformer derivation failed */
840  if(tf==transformer_undefined)
841  tf = effects_to_transformer(ef);
842 
843  pips_debug(6,"return tl=%p\n", tl);
844  ifdebug(6) (void) print_transformers(tl);
845  pips_debug(8,"end\n");
846  return tl;
847 }
entity update_operator_to_regular_operator(entity op)
Returns the binary operator associated to a C update operator such as +=.
Definition: entity.c:2154
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165

References any_scalar_assign_to_transformer(), CAR, CDR, copy_expression(), effects_to_transformer(), ENDP, entity_to_expression(), EXPRESSION, expression_syntax, free_expression(), ifdebug, MakeBinaryCall(), NIL, pips_assert, pips_debug, pips_internal_error, print_transformers(), reference_indices, reference_variable, syntax_reference, syntax_reference_p, transformer_undefined, and update_operator_to_regular_operator().

+ Here is the call graph for this function:

◆ assigned_expression_to_transformer_list()

list assigned_expression_to_transformer_list ( entity  v,
expression  expr,
transformer  pre 
)

transformer assigned_expression_to_transformer(entity e, expression expr, list ef): returns a transformer abstracting the effect of assignment "e = expr" when possible, transformer_undefined otherwise.

Note: it might be better to distinguish further between e and expr and to return a transformer stating that e is modified when e is accepted for semantics analysis.

if the assigned variable is also assigned by the expression as in i = (i = 2) + 1, transformer_value_substitute() cannot be used right away. The previous store must be projected out.

v must be assigned

subcase of previous aternative

vect_rm(ve);

Parameters
exprxpr
prere

Definition at line 551 of file ri_to_transformer_lists.c.

554 {
555  list tl = NIL;
557 
558  pips_internal_error("Not implemented yet.");
559 
560  pips_debug(8, "begin\n");
561 
562  if(entity_has_values_p(v)) {
563  entity v_new = entity_to_new_value(v);
564  entity v_old = entity_to_old_value(v);
566  //list tf_args = CONS(ENTITY, v, NIL);
567 
568  tf = any_expression_to_transformer(tmp, expr, pre, true);
569  // The assignment may be part of a more complex expression
570  // This should be guarded by "is_internal==FALSE" if is_internal were an argument
571  //reset_temporary_value_counter();
572  if(!transformer_undefined_p(tf)) {
573  /* if the assigned variable is also assigned by the expression
574  as in i = (i = 2) + 1, transformer_value_substitute() cannot be
575  used right away. The previous store must be projected out. */
577  /* v must be assigned */
578  transformer teq = simple_equality_to_transformer(v, tmp, true);
579  tf = transformer_combine(tf, teq);
580  free_transformer(teq);
581 
582  }
583  else { /* subcase of previous aternative */
584  tf = transformer_value_substitute(tf, v_new, v_old);
585  tf = transformer_value_substitute(tf, tmp, v_new);
586  // v cannot be a temporary variable
587  //transformer_arguments(tf) =
588  //arguments_add_entity(transformer_arguments(tf), v);
589  tf = transformer_add_value_update(tf, v);
590  }
592  }
593  }
594  else {
595  /* vect_rm(ve); */
597  }
598 
599  pips_debug(8, "end with tf=%p\n", tl);
600 
601  return tl;
602 }
transformer transformer_add_value_update(transformer t, entity v)
Add an update of variable v to t (a value cannot be updated)
Definition: basic.c:321

References any_expression_to_transformer(), entity_has_values_p(), entity_is_argument_p(), entity_to_new_value(), entity_to_old_value(), entity_type, free_transformer(), make_local_temporary_value_entity(), NIL, pips_debug, pips_internal_error, simple_equality_to_transformer(), transformer_add_value_update(), transformer_arguments, transformer_combine(), transformer_temporary_value_projection(), transformer_undefined, transformer_undefined_p, and transformer_value_substitute().

+ Here is the call graph for this function:

◆ block_to_transformer_list()

static list block_to_transformer_list ( list  b,
transformer  pre 
)
static

Generate all possible linear control paths.

We start with a unique precondition.

For each statement, we start with a transformer list btfl_i-1 and with a postcondition list postl_i-1

To each statement s_i, we associate a transformer list stfl_i.

For each transformer stf_j in stfl_i, for each transformer btf_k and postcondition post_k in btfl_i-1 and postl_i-1, we compute a new transformer nbtf_j,k=stf_j o btf_k and a new postcondition npost_j,k=stf_j(post_k).

btfl_i = {nbtf_j,k} and postl_i = {npost_j,k}

The first statement must be handled in a specific way or btfl_0 be initialized to a singleton list with the identity transformer and postl_0 be initialized as a singleton list with a single element {pre}.

The number of transformers returned increase exponentially with the block size n. Assume that each statement returns two transformers: 2**n transformers are returned by this function.

More thinking about memory management probably useful. Also postconditions are automatically available in the transformers. The simultaneous computation of postconditions seem redundant.

Handle the first statement

For the next statements

Now, switch from btfl and postl to nbtfl and npostl

Postconditions are discarded

Clean up the transformer list: reduce identity transformers to one if any and move it ahead of the list

Definition at line 292 of file ri_to_transformer_lists.c.

293 {
294  list btfl = NIL; //block transformer list
296  //transformer stf = transformer_undefined;
298  //transformer next_pre = transformer_undefined;
299  list l = b;
300 
301  pips_debug(8,"begin\n");
302 
303  if(ENDP(l)) {
304  //btf = transformer_identity();
305  // pre must be a range, hence a subset of identity
306  btf = copy_transformer(pre);
307  btfl = CONS(TRANSFORMER, btf, NIL);
308  }
309  else {
310  /* Handle the first statement */
311  statement s = STATEMENT(CAR(l));
312  list postl = NIL;
313  btfl = statement_to_transformer_list(s, pre);
314  postl = transformers_safe_apply(btfl, pre);
315  postl = transformers_range(postl);
316  postl = transformers_safe_normalize(postl, 2);
317  // Useless if no storage occurs; stfl should replace btfl above
318  //btfl = gen_full_sequence_copy(stfl);
319  pips_assert("One postcondition for each transformer",
320  gen_length(btfl) == gen_length(postl));
321 
322  /* For the next statements */
323  for (POP(l) ; !ENDP(l); POP(l)) {
324  list precl = postl;
325  list npostl = NIL;
326  list nbtfl = NIL;
327  s = STATEMENT(CAR(l));
328  FOREACH(TRANSFORMER, btf, btfl) {
329  // Get the corresponding postcondition, now a precondition
330  transformer next_pre = TRANSFORMER(CAR(precl));
331  list stfl = statement_to_transformer_list(s, next_pre);
332  FOREACH(TRANSFORMER, stf, stfl) {
333  post = transformer_safe_apply(stf, next_pre);
334  post = transformer_safe_normalize(post, 2);
335  transformer post_r = transformer_range(post);
336  free_transformer(post);
337  transformer nbtf = copy_transformer(btf); // preserve outer
338  // loop variable
339  nbtf = transformer_combine(nbtf, stf);
340  nbtf = transformer_normalize(nbtf, 2);
341  ifdebug(1) {
342  pips_assert("btf is a consistent transformer",
344  pips_assert("post_r is a consistent transformer if pre is defined",
346  || transformer_consistency_p(post_r));
347  }
348  if(!transformer_empty_p(nbtf)) {
349  nbtfl = gen_nconc(nbtfl, CONS(TRANSFORMER, nbtf, NIL));
350  npostl = gen_nconc(npostl, CONS(TRANSFORMER, post_r, NIL));
351  }
352  }
353  gen_full_free_list(stfl);
354  POP(precl);
355  }
356  /* Now, switch from btfl and postl to nbtfl and npostl */
357  // The transformers are updated and moved into the new list nbtfl
358  //gen_full_free_list(btfl);
359  //gen_full_free_list(postl);
360  btfl = nbtfl;
361  postl = npostl;
362  }
363  /* Postconditions are discarded */
364  gen_full_free_list(postl);
365 
366  /* Clean up the transformer list: reduce identity transformers to
367  one if any and move it ahead of the list */
368 
369  btfl = clean_up_transformer_list(btfl);
370  btfl = transformers_safe_normalize(btfl, 2);
371  }
372 
373  pips_debug(8, "ends with %zd transformers\n", gen_length(btfl));
374  ifdebug(8)
375  print_transformers(btfl);
376  return btfl;
377 }
transformer copy_transformer(transformer p)
TRANSFORMER.
Definition: ri.c:2613
bool transformer_consistency_p(transformer t)
FI: I do not know if this procedure should always return or fail when an inconsistency is found.
Definition: basic.c:612
void gen_full_free_list(list l)
Definition: genClib.c:1023
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
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 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 TRANSFORMER(x)
TRANSFORMER.
Definition: ri.h:2841
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
list statement_to_transformer_list(statement s, transformer spre)
A transformer is already available for statement s, but it is going to be refined into a list of tran...
bool stf(const string)
standardize_structure.c
transformer transformer_safe_apply(transformer tf, transformer pre)
Definition: transformer.c:1627
list transformers_range(list tfl)
Substitute each transformer in list tfl by its range.
Definition: transformer.c:754
transformer transformer_normalize(transformer t, int level)
Eliminate (some) rational or integer redundancy.
Definition: transformer.c:932
transformer transformer_safe_normalize(transformer t, int level)
Definition: transformer.c:1111
bool transformer_empty_p(transformer t)
If true is returned, the transformer certainly is empty.
Definition: transformer.c:2455
list transformers_safe_apply(list tl, transformer pre)
returns a list of postconditions, one for each transformer in tl
Definition: transformer.c:1638
list transformers_safe_normalize(list tl, int level)
Definition: transformer.c:1119
transformer transformer_range(transformer tf)
Return the range of relation tf in a newly allocated transformer.
Definition: transformer.c:714
list clean_up_transformer_list(list)
Eliminate empty transformers and keep at most one identity transformer, placed as first list element.

References CAR, clean_up_transformer_list(), CONS, copy_transformer(), ENDP, FOREACH, free_transformer(), gen_full_free_list(), gen_length(), gen_nconc(), ifdebug, NIL, pips_assert, pips_debug, POP, print_transformers(), STATEMENT, statement_to_transformer_list(), stf(), TRANSFORMER, transformer_combine(), transformer_consistency_p(), transformer_empty_p(), transformer_normalize(), transformer_range(), transformer_safe_apply(), transformer_safe_normalize(), transformer_undefined, transformer_undefined_p, transformers_range(), transformers_safe_apply(), and transformers_safe_normalize().

Referenced by instruction_to_transformer_list().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ declaration_to_transformer_list()

list declaration_to_transformer_list ( entity  v,
transformer  pre 
)

Postpone convex hulls by keeping transformer lists instead.

ri_to_transformer_lists.c

This development was prompted by the last example found in the paper by Schrammel and Jeannet at NSAD 2010. See test cases schrammel04, 05 and 06. The minimal goal is to avoid the indentity transformer when performing the convex hull of several transformers.

This could also be useful to automatize the handling of tests within a loop using the technique presented at NSAD 2010 by Ancourt & al. The control structure

"while(c) if(t) T; else F;"

is replaced by

"while(c) {while(c&&t) T; while(c&& !t) F;}".

This replacement could be performed on the equations instead of requiring a program transformation. semantical analysis

phasis 3: compute transformer lists from statements and statement transformers

For refined precondition analysis. Keep track of all control paths within sequences

Francois Irigoin, September 2010 include <stdlib.h> Note: initializations of static variables are not used as transformers but to initialize the program precondition. It is not assumed that entity_has_values_p(v)==true A write effect on the declared variable is assumed as required by Beatrice Creusillet for region computation.

FI: the initialization expression might have relevant side-effects? This could ba handled by generalizing variable_to_initial_expression() and by returning expression_undefined incase of failure instead of aborting.

Use the dimension expressions and the initial value

FI: I preserve the code below in case I have problems with integer typing in the future

Parameters
prere

Definition at line 100 of file ri_to_transformer_lists.c.

101 {
102  list tfl = NIL;
104 
105  pips_internal_error("Not implemented yet.");
106 
107  pips_debug(8, "Transformer for declaration of \"%s\"\n", entity_name(v));
108 
109  if(false && !entity_has_values_p(v)) {
110  /* FI: the initialization expression might have relevant
111  side-effects? This could ba handled by generalizing
112  variable_to_initial_expression() and by returning
113  expression_undefined incase of failure instead of aborting. */
114  tf = transformer_identity();
115  }
116  else if(variable_static_p(v)) {
117  if(get_bool_property("SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT"))
118  tf = transformer_range(pre);
119  else
120  tf = transformer_identity();
121  }
122  else {
123  /* Use the dimension expressions and the initial value */
125  transformer npre = transformer_apply(dt, pre);
128  tf = dt;
129  tf = transformer_combine(tf, itf);
130  free_expression(ie);
131  }
132 
133  pips_assert("tf is defined", !transformer_undefined_p(tf));
134 
135  /* FI: I preserve the code below in case I have problems with
136  integer typing in the future*/
137  /*
138  if(entity_has_values_p(v) && !variable_static_p(v)) {
139  value vv = entity_initial(v);
140  if(value_unknown_p(vv)) {
141  tf = transformer_identity();
142  }
143  else if (value_symbolic_p(vv)) {
144  pips_internal_error("Unexpected value tag: symbolic");
145  }
146  else if (value_constant_p(vv)) {
147  tf = transformer_identity();
148  // SG: quickly fix this, unsure about the meaning
149  //pips_internal_error("Unexpected value tag: constant");
150  }
151  else if (value_expression_p(vv)) {
152  expression e = value_expression(vv);
153  basic eb = basic_of_expression(e);
154  type vt = ultimate_type(entity_type(v));
155  basic vb = variable_basic(type_variable(vt));
156 
157  if(same_basic_p(eb, vb)) {
158  tf = safe_any_expression_to_transformer(v, e, pre, false);
159  tf = transformer_temporary_value_projection(tf);
160  }
161  else {
162  if(basic_int_p(eb) && basic_int_p(vb)) {
163  int i1 = basic_int(eb);
164  int i2 = basic_int(vb);
165  if(ABS(i1-i2)==10) {
166  tf = safe_any_expression_to_transformer(v, e, pre, false);
167  tf = transformer_temporary_value_projection(tf);
168  semantics_user_warning("Possible conversion issue between signed and"
169  " unsigned int\n");
170  }
171  else {
172  tf = safe_any_expression_to_transformer(v, e, pre, false);
173  tf = transformer_temporary_value_projection(tf);
174  semantics_user_warning("Possible conversion issue between diffent kinds"
175  " of ints and/or char (%dd and %d)\n", i1, i2);
176  }
177  }
178  else {
179  //list el = expression_to_proper_effects(e);
180  list el = expression_to_proper_constant_path_effects(e);
181 
182  semantics_user_warning("Type mismatch detected in initialization expression."
183  " May be due to overloading and/or implicit confusion"
184  " between logical and integer in C\n");
185  tf = effects_to_transformer(el);
186  }
187  }
188  }
189  else {
190  pips_internal_error("Unexpected value tag");
191  }
192  }
193  else {
194  tf = transformer_identity();
195  }
196  */
197 
198  ifdebug(8) {
199  pips_debug(8, "Ends with:\n");
200  (void) print_transformers(tfl);
201  }
202 
203  return tfl;
204 }
transformer transformer_identity()
Allocate an identity transformer.
Definition: basic.c:110
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
expression variable_initial_expression(entity)
Returns a copy of the initial (i.e.
Definition: variable.c:1899
bool variable_static_p(entity)
true if v appears in a SAVE statement, or in a DATA statement, or is declared static i C.
Definition: variable.c:1579
#define entity_name(x)
Definition: ri.h:2790
transformer safe_assigned_expression_to_transformer(entity v, expression expr, transformer pre)
Always returns a fully defined transformer.
transformer dimensions_to_transformer(entity v, transformer pre)
Assumes that entity_has_values_p(v) holds.
transformer transformer_apply(transformer tf, transformer pre)
transformer transformer_apply(transformer tf, transformer pre): apply transformer tf on precondition ...
Definition: transformer.c:1559

References dimensions_to_transformer(), entity_has_values_p(), entity_name, free_expression(), get_bool_property(), ifdebug, NIL, pips_assert, pips_debug, pips_internal_error, print_transformers(), safe_assigned_expression_to_transformer(), transformer_apply(), transformer_combine(), transformer_identity(), transformer_range(), transformer_undefined, transformer_undefined_p, variable_initial_expression(), and variable_static_p().

+ Here is the call graph for this function:

◆ declarations_to_transformer_list()

list declarations_to_transformer_list ( list  dl,
transformer  pre 
)

For C declarations.

Very close to a block_to_transformer() as declarations can be seen as a sequence of assignments.

Note: initialization of static variables are not taken into account. They must be used for summary preconditions.

post = transformer_safe_normalize(post, 4);

post = transformer_safe_normalize(post, 4);

btf = transformer_normalize(btf, 4);

Parameters
dll
prere

Definition at line 212 of file ri_to_transformer_lists.c.

213 {
214  list tfl = list_undefined;
220  list l = dl;
221 
222  // May never be useful
223  pips_internal_error("Not implemented yet.");
224 
225  pips_debug(8,"begin\n");
226 
227  if(ENDP(l))
228  btf = transformer_identity();
229  else {
230  v = ENTITY(CAR(l));
232  post = transformer_safe_apply(stf, pre);
233 /* post = transformer_safe_normalize(post, 4); */
234  post = transformer_safe_normalize(post, 2);
235  btf = transformer_dup(stf);
236  for (POP(l) ; !ENDP(l); POP(l)) {
237  v = ENTITY(CAR(l));
238  if(!transformer_undefined_p(next_pre))
239  free_transformer(next_pre);
240  next_pre = transformer_range(post);
241  stf = declaration_to_transformer(v, next_pre);
242  post = transformer_safe_apply(stf, next_pre);
243  free_transformer(next_pre);
244  next_pre = transformer_undefined; // FI: works even without this...
245 /* post = transformer_safe_normalize(post, 4); */
246  post = transformer_safe_normalize(post, 2);
247  btf = transformer_combine(btf, stf);
248 /* btf = transformer_normalize(btf, 4); */
249  btf = transformer_normalize(btf, 2);
250 
251  ifdebug(1)
252  pips_assert("btf is a consistent transformer", transformer_consistency_p(btf));
253  pips_assert("post is a consistent transformer if pre is defined",
255  }
256  free_transformer(post);
257  }
258 
259  pips_debug(8, "end\n");
260  return tfl;
261 }
transformer transformer_dup(transformer t_in)
transformer package - basic routines
Definition: basic.c:49
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
char end
Definition: gtk_status.c:82
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define entity_undefined
Definition: ri.h:2761
transformer declaration_to_transformer(entity v, transformer pre)
Note: initializations of static variables are not used as transformers but to initialize the program ...

References CAR, declaration_to_transformer(), ENDP, ENTITY, entity_undefined, free_transformer(), ifdebug, list_undefined, pips_assert, pips_debug, pips_internal_error, POP, stf(), transformer_combine(), transformer_consistency_p(), transformer_dup(), transformer_identity(), transformer_normalize(), transformer_range(), transformer_safe_apply(), transformer_safe_normalize(), transformer_undefined, and transformer_undefined_p.

+ Here is the call graph for this function:

◆ instruction_to_transformer_list()

static list instruction_to_transformer_list ( instruction  i,
transformer  tf,
transformer  pre,
list  e 
)
static

effects associated to instruction i

Nothing fancy yet in spite of the C ? and , operators

Bourdoncle's to be replaced

Nothing fancy yet in spite of the C ? and , operators

Definition at line 894 of file ri_to_transformer_lists.c.

898 {
899  list tl = NIL;
900  //transformer tf = transformer_undefined;
901  test t;
902  loop l;
903  //call c;
904  whileloop wl;
905  forloop fl;
906 
907  pips_debug(8,"begin\n");
908 
909  switch(instruction_tag(i)) {
912  break;
913  case is_instruction_test:
914  t = instruction_test(i);
915  tl = test_to_transformer_list(t, pre, e);
916  break;
917  case is_instruction_loop:
918  l = instruction_loop(i);
919  tl = complete_loop_transformer_list(tf, pre, l);
920  break;
922  wl = instruction_whileloop(i);
923  // FI: the complete_xxx functions require a transformer as argument
924  tl = complete_whileloop_transformer_list(tf, pre, wl);
925  break;
926  }
928  fl = instruction_forloop(i);
929  tl = complete_forloop_transformer_list(tf, pre, fl);
930  break;
931  case is_instruction_goto:
932  pips_internal_error("unexpected goto in semantics analysis");
933  tl = NIL; // never executed
934  break;
935  case is_instruction_call: {
936  /* Nothing fancy yet in spite of the C ? and , operators*/
937  call c = instruction_call(i);
938  tf = call_to_transformer(c, pre, e);
939  if(!transformer_empty_p(tf))
940  tl = CONS(TRANSFORMER, tf, NIL);
941  // Reuse the existing transformer: tl==NIL has a semantic, not feasible
942  // tl = NIL;
943  }
944  break;
946  /* Bourdoncle's to be replaced */
947  //tf = unstructured_to_transformer(instruction_unstructured(i), pre, e);
948  //tl = CONS(TRANSFORMER, tf, NIL);
949  // Reuse the existing transformer
950  tl = list_undefined;
951  break ;
953  /* Nothing fancy yet in spite of the C ? and , operators*/
954  //tl = expression_to_transformer_list(instruction_expression(i), pre, e);
955  //tf = expression_to_transformer(instruction_expression(i), pre, e);
956  //tl = CONS(TRANSFORMER, tf, NIL);
957  // Reuse the existing transformer
958  tl = list_undefined;
959  break;
960  default:
961  pips_internal_error("unexpected tag %d", instruction_tag(i));
962  }
963  pips_debug(9, "resultat:\n");
964  ifdebug(9)
965  {
966  if(!list_undefined_p(tl))
967  (void) print_transformers(tl);
968  else
969  (void) fprintf(stderr, "undefined list\n");
970  }
971  pips_debug(8, "end\n");
972  return tl;
973 }
#define list_undefined_p(c)
Return if a list is undefined.
Definition: newgen_list.h:75
#define is_instruction_block
soft block->sequence transition
#define instruction_block(i)
#define instruction_loop(x)
Definition: ri.h:1520
@ is_instruction_goto
Definition: ri.h:1473
@ is_instruction_unstructured
Definition: ri.h:1475
@ is_instruction_whileloop
Definition: ri.h:1472
@ is_instruction_expression
Definition: ri.h:1478
@ is_instruction_test
Definition: ri.h:1470
@ is_instruction_call
Definition: ri.h:1474
@ is_instruction_forloop
Definition: ri.h:1477
@ is_instruction_loop
Definition: ri.h:1471
#define instruction_tag(x)
Definition: ri.h:1511
#define instruction_forloop(x)
Definition: ri.h:1538
#define instruction_whileloop(x)
Definition: ri.h:1523
#define instruction_call(x)
Definition: ri.h:1529
#define instruction_test(x)
Definition: ri.h:1517
static list block_to_transformer_list(list b, transformer pre)
Generate all possible linear control paths.
static list test_to_transformer_list(test t, transformer pre, list ef)
effects of t
transformer call_to_transformer(call c, transformer pre, list ef)
Use to be static, but may be called from expressions in C.
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
list complete_loop_transformer_list(transformer ltf, transformer pre, loop l)
Definition: loop.c:2061
list complete_forloop_transformer_list(transformer t_body_star, transformer pre, forloop fl)
Definition: loop.c:1732
list complete_whileloop_transformer_list(transformer ltf, transformer pre, whileloop wl)
Definition: loop.c:2198

References block_to_transformer_list(), call_to_transformer(), complete_forloop_transformer_list(), complete_loop_transformer_list(), complete_whileloop_transformer_list(), CONS, fprintf(), ifdebug, instruction_block, instruction_call, instruction_forloop, instruction_loop, instruction_tag, instruction_test, instruction_whileloop, is_instruction_block, is_instruction_call, is_instruction_expression, is_instruction_forloop, is_instruction_goto, is_instruction_loop, is_instruction_test, is_instruction_unstructured, is_instruction_whileloop, list_undefined, list_undefined_p, NIL, pips_debug, pips_internal_error, print_transformers(), test_to_transformer_list(), TRANSFORMER, and transformer_empty_p().

Referenced by statement_to_transformer_list().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ integer_assign_to_transformer_list()

list integer_assign_to_transformer_list ( expression  lhs,
expression  rhs,
transformer  pre,
list  ef 
)

This function never returns an undefined transformer.

It is used for an assignment statement, not for an assignment operation. effects of assign

algorithm: if lhs and rhs are linear expressions on scalar integer variables, build the corresponding equation; else, use effects ef

should be extended to cope with constant integer division as in N2 = N/2 because it is used in real program; inequalities should be generated in that case 2*N2 <= N <= 2*N2+1

same remark for MOD operator

implementation: part of this function should be moved into transformer.c

&& integer_scalar_entity_p(e)

FI: the initial version was conservative because only affine scalar integer assignments were processed precisely. But non-affine operators and calls to user defined functions can also bring some information as soon as some integer read or write effect exists

check that all read effects are on integer scalar entities

Check that some read or write effects are on integer scalar entities. This is almost always true... Let's hope assigned_expression_to_transformer() returns quickly for array expressions used to initialize a scalar integer entity.

if some condition was not met and transformer derivation failed

Parameters
lhshs
rhshs
prere
eff

Definition at line 645 of file ri_to_transformer_lists.c.

649 {
650  /* algorithm: if lhs and rhs are linear expressions on scalar integer
651  variables, build the corresponding equation; else, use effects ef
652 
653  should be extended to cope with constant integer division as in
654  N2 = N/2
655  because it is used in real program; inequalities should be
656  generated in that case 2*N2 <= N <= 2*N2+1
657 
658  same remark for MOD operator
659 
660  implementation: part of this function should be moved into
661  transformer.c
662  */
663 
664  list tl = NIL;
667 
668  pips_internal_error("Not implemented yet.");
669 
670  pips_debug(8,"begin\n");
671 
672  if(normalized_linear_p(n)) {
673  Pvecteur vlhs = (Pvecteur) normalized_linear(n);
674  entity e = (entity) vecteur_var(vlhs);
675 
676  if(entity_has_values_p(e) /* && integer_scalar_entity_p(e) */) {
677  /* FI: the initial version was conservative because
678  * only affine scalar integer assignments were processed
679  * precisely. But non-affine operators and calls to user defined
680  * functions can also bring some information as soon as
681  * *some* integer read or write effect exists
682  */
683  /* check that *all* read effects are on integer scalar entities */
684  /*
685  if(integer_scalar_read_effects_p(ef)) {
686  tf = assigned_expres`sion_to_transformer(e, rhs, ef);
687  }
688  */
689  /* Check that *some* read or write effects are on integer
690  * scalar entities. This is almost always true... Let's hope
691  * assigned_expression_to_transformer() returns quickly for array
692  * expressions used to initialize a scalar integer entity.
693  */
695  tf = assigned_expression_to_transformer(e, rhs, pre);
696  }
697  }
698  }
699  /* if some condition was not met and transformer derivation failed */
700  if(tf==transformer_undefined)
701  tf = effects_to_transformer(ef);
702 
703  pips_debug(6,"return tl=%lx\n", (unsigned long)tl);
704  ifdebug(6) (void) print_transformers(tl);
705  pips_debug(8,"end\n");
706  return tl;
707 }
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
bool some_integer_scalar_read_or_write_effects_p(cons *)
#define NORMALIZE_EXPRESSION(e)
#define normalized_linear_p(x)
Definition: ri.h:1779
#define normalized_linear(x)
Definition: ri.h:1781
transformer assigned_expression_to_transformer(entity v, expression expr, transformer pre)
transformer assigned_expression_to_transformer(entity e, expression expr, list ef): returns a transfo...
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
#define vecteur_var(v)
struct Svecteur * Pvecteur

References assigned_expression_to_transformer(), effects_to_transformer(), entity_has_values_p(), ifdebug, NIL, NORMALIZE_EXPRESSION, normalized_linear, normalized_linear_p, pips_debug, pips_internal_error, print_transformers(), some_integer_scalar_read_or_write_effects_p(), transformer_undefined, and vecteur_var.

+ Here is the call graph for this function:

◆ intrinsic_to_transformer_list()

list intrinsic_to_transformer_list ( entity  e,
list  pc,
transformer  pre,
list  ef 
)

because of the conditional and the comma C intrinsics at least

effects of intrinsic call

FI: this may happen, for instance with the macro definition of assert() or because the programmer writes "i>1? (i = 2): (i = 3);" instead of "i = i>1? 2 : 3;"

FI: the condition should be evaluated and considered true on exit, but this is sometimes captured by a macro definition and the code below is then useless

Parameters
pcc
prere
eff

Definition at line 480 of file ri_to_transformer_lists.c.

484 {
485  list tl = NIL;
487 
488  pips_internal_error("Not implemented yet.");
489 
490  pips_debug(8, "begin\n");
491 
492  if(ENTITY_ASSIGN_P(e)) {
493  tf = any_assign_to_transformer(pc, ef, pre);
494  }
500  //tf = update_addition_operation_to_transformer(pc, ef, pre);
501  tf = any_update_to_transformer(e, pc, ef, pre);
502  }
505  tf = any_basic_update_to_transformer(e, pc, ef, pre);
506  }
507  else if(ENTITY_C_RETURN_P(e)) {
508  tf = c_return_to_transformer(e, pc, ef, pre);
509  }
512  tf = transformer_empty();
513  else if(ENTITY_COMMA_P(e)) {
514  tf = expressions_to_transformer(pc, pre);
515  }
516  else if(ENTITY_CONDITIONAL_P(e)) {
517  /* FI: this may happen, for instance with the macro definition of
518  assert() or because the programmer writes "i>1? (i = 2): (i =
519  3);" instead of "i = i>1? 2 : 3;" */
520  expression cond = EXPRESSION(CAR(pc));
521  expression e1 = EXPRESSION(CAR(CDR(pc)));
522  expression e2 = EXPRESSION(CAR(CDR(CDR(pc))));
523  tf = conditional_to_transformer(cond, e1, e2, pre, ef);
524  }
525  else if(ENTITY_ASSERT_SYSTEM_P(e)) {
526  /* FI: the condition should be evaluated and considered true on
527  exit, but this is sometimes captured by a macro definition and the code
528  below is then useless */
529  expression cond = EXPRESSION(CAR(pc));
530  tf = condition_to_transformer(cond, pre, true);
531  }
532  else
533  tf = effects_to_transformer(ef);
534 
535  pips_debug(8, "end\n");
536 
537  tl=CONS(TRANSFORMER,tf,NIL);
538  return tl;
539 }
transformer transformer_empty()
Allocate an empty transformer.
Definition: basic.c:120
#define ENTITY_PLUS_UPDATE_P(e)
#define ENTITY_MODULO_UPDATE_P(e)
#define ENTITY_STOP_P(e)
#define ENTITY_BITWISE_AND_UPDATE_P(e)
#define ENTITY_ASSIGN_P(e)
#define ENTITY_COMMA_P(e)
#define ENTITY_ASSERT_SYSTEM_P(e)
include <assert.h>
#define ENTITY_PRE_DECREMENT_P(e)
#define ENTITY_POST_DECREMENT_P(e)
#define ENTITY_EXIT_SYSTEM_P(e)
#define ENTITY_CONDITIONAL_P(e)
#define ENTITY_RIGHT_SHIFT_UPDATE_P(e)
#define ENTITY_BITWISE_OR_UPDATE_P(e)
#define ENTITY_ABORT_SYSTEM_P(e)
#define ENTITY_MULTIPLY_UPDATE_P(e)
#define ENTITY_DIVIDE_UPDATE_P(e)
#define ENTITY_C_RETURN_P(e)
#define ENTITY_BITWISE_XOR_UPDATE_P(e)
#define ENTITY_MINUS_UPDATE_P(e)
#define ENTITY_LEFT_SHIFT_UPDATE_P(e)
#define ENTITY_ASSERT_FAIL_SYSTEM_P(e)
transformer any_basic_update_to_transformer(entity op, list args, list ef, transformer pre)
precondition
transformer any_assign_to_transformer(list args, list ef, transformer pre)
precondition
transformer any_update_to_transformer(entity op, list args, list ef, transformer pre)
precondition
transformer c_return_to_transformer(entity e __attribute__((__unused__)), list pc, list ef, transformer pre)
FI: This transformer carry the information about the value returned, but not the fact that the next s...
transformer expressions_to_transformer(list expl, transformer pre)
Compute the transformer associated to a list of expressions such as "i=0, j = 1;".
Definition: expression.c:5722
transformer conditional_to_transformer(expression cond, expression te, expression fe, transformer pre, list ef)
FI: not too smart to start with the special case with no value returned, just side-effects....
Definition: expression.c:5488
transformer condition_to_transformer(expression cond, transformer pre, bool veracity)
To capture side effects and to add C twist for numerical conditions.
Definition: expression.c:5348

References any_assign_to_transformer(), any_basic_update_to_transformer(), any_update_to_transformer(), c_return_to_transformer(), CAR, CDR, condition_to_transformer(), conditional_to_transformer(), CONS, effects_to_transformer(), ENTITY_ABORT_SYSTEM_P, ENTITY_ASSERT_FAIL_SYSTEM_P, ENTITY_ASSERT_SYSTEM_P, ENTITY_ASSIGN_P, ENTITY_BITWISE_AND_UPDATE_P, ENTITY_BITWISE_OR_UPDATE_P, ENTITY_BITWISE_XOR_UPDATE_P, ENTITY_C_RETURN_P, ENTITY_COMMA_P, ENTITY_CONDITIONAL_P, ENTITY_DIVIDE_UPDATE_P, ENTITY_EXIT_SYSTEM_P, ENTITY_LEFT_SHIFT_UPDATE_P, ENTITY_MINUS_UPDATE_P, ENTITY_MODULO_UPDATE_P, ENTITY_MULTIPLY_UPDATE_P, ENTITY_PLUS_UPDATE_P, ENTITY_POST_DECREMENT_P, ENTITY_POST_INCREMENT_P, ENTITY_PRE_DECREMENT_P, ENTITY_PRE_INCREMENT_P, ENTITY_RIGHT_SHIFT_UPDATE_P, ENTITY_STOP_P, EXPRESSION, expressions_to_transformer(), NIL, pips_debug, pips_internal_error, TRANSFORMER, transformer_empty(), and transformer_undefined.

+ Here is the call graph for this function:

◆ safe_assigned_expression_to_transformer_list()

list safe_assigned_expression_to_transformer_list ( entity  v,
expression  expr,
transformer  pre 
)

Always returns a fully defined transformer.

FI: The property to compute transformers in context is not taken into account to add information from pre within tf. pre is used to evaluate expr, but is not made part of tf.

Parameters
exprxpr
prere

Definition at line 610 of file ri_to_transformer_lists.c.

613 {
614  list tl = NIL;
616 
617  pips_internal_error("Not implemented yet.");
618 
619  if(expression_undefined_p(expr)) {
620  ; // That is fixed below
621  }
622  else
623  tf = assigned_expression_to_transformer(v, expr, pre);
624 
625  if(transformer_undefined_p(tf)) {
626  if(get_bool_property("SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT"))
627  tf = transformer_range(pre);
628  else
629  tf = transformer_identity();
630 
631  if(entity_has_values_p(v)) {
633  }
634  }
635 
636  //pips_assert("tf is defined", !transformer_undefined_p(tf));
637  pips_assert("tl is consistent", transformers_consistency_p(tl));
638 
639  return tl;
640 }
transformer transformer_add_modified_variable_entity(transformer tf, entity var)
FI: like the previous function, but supposed to end up with a consistent transformer.
Definition: basic.c:909
bool transformers_consistency_p(list tl)
Definition: basic.c:616
#define expression_undefined_p(x)
Definition: ri.h:1224

References assigned_expression_to_transformer(), entity_has_values_p(), expression_undefined_p, get_bool_property(), NIL, pips_assert, pips_internal_error, transformer_add_modified_variable_entity(), transformer_identity(), transformer_range(), transformer_undefined, transformer_undefined_p, and transformers_consistency_p().

+ Here is the call graph for this function:

◆ statement_to_transformer_list()

list statement_to_transformer_list ( statement  s,
transformer  spre 
)

A transformer is already available for statement s, but it is going to be refined into a list of transformers to isolate at least the identity transformer from effective transformers.

stmt precondition

Transformation REFINE_TRANSFORMERS is being executed: add information available from the statement precondition

it would be nicer to control warning_on_redefinition

FI: an empty tl means that s does not return. An undefined tl means that instruction_to_transformer() is not implemented in a satisfactory way. So the existing transformer is used by default.

add array references information using proper effects

nt = transformer_normalize(nt, 0);

When we leave a block the local stack allocated variables disappear

Get rid of the dynamic and stack variables declared in this block statement. No stack variable should be analyzed as the stack area is used only for dependent types.

nt = transformer_normalize(nt, 7);

nt = transformer_normalize(nt, 4);

(void) print_transformer(load_statement_transformer(s));

The transformer returned for the statement is not always the transformer stored for the statement. This happens for loops and for context sensitive transformers for replicated statements in CFG/unstructured. See comments in loop.c

Parameters
sprepre

Definition at line 978 of file ri_to_transformer_lists.c.

980 {
983  list tl = NIL;
984  list e = NIL;
985  //transformer t = transformer_undefined;
986  //transformer ot = transformer_undefined; /* old transformer for s */
987  //transformer nt = transformer_undefined; /* new transformer for s under spre */
988  //transformer te = transformer_undefined; /* nt updated with loop exit information */
990 
991  pips_debug(8,"begin for statement %03td (%td,%td) with precondition %p:\n",
994  ifdebug(8) {
995  pips_assert("The statement and its substatements are fully defined",
997  (void) print_transformer(spre);
998  }
999 
1000  pips_assert("spre is a consistent precondition",
1001  transformer_consistent_p(spre));
1002 
1003  if(get_bool_property("SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT")) {
1005  transformer_range(spre);
1006  if(refine_transformers_p) {
1007  /* Transformation REFINE_TRANSFORMERS is being executed: add
1008  information available from the statement precondition */
1010  transformer srpre_r = transformer_range(srpre);
1011 
1012  pre = transformer_domain_intersection(pre, srpre_r);
1013  free_transformer(srpre_r);
1014  }
1015  }
1016  else {
1017  // Avoid lots of test in the callees
1018  // pre = transformer_undefined;
1019  pre = transformer_identity();
1020  }
1021 
1022  pips_assert("pre is a consistent precondition",
1024 
1025  pips_debug(8,"Range precondition pre:\n");
1026  ifdebug(8) {
1027  (void) print_transformer(pre);
1028  }
1029 
1030  // Probably not useful
1032 
1033  /* it would be nicer to control warning_on_redefinition */
1034  if (true) {
1036 
1037  if(!ENDP(dl)) {
1039  tl = CONS(TRANSFORMER, dt, NIL);
1040  }
1041  else {
1042  tl = instruction_to_transformer_list(i, tf, pre, e);
1043  /* FI: an empty tl means that s does not return. An undefined
1044  tl means that instruction_to_transformer() is not
1045  implemented in a satisfactory way. So the existing
1046  transformer is used by default. */
1047  if(list_undefined_p(tl)) {
1049  tl = CONS(TRANSFORMER, copy_transformer(tf), NIL);
1050  }
1051  }
1052 
1053  FOREACH(TRANSFORMER, nt, tl) {
1054  /* add array references information using proper effects */
1055  if(get_bool_property("SEMANTICS_TRUST_ARRAY_REFERENCES")) {
1057  /* nt = transformer_normalize(nt, 0); */
1058  }
1059 
1060  /* When we leave a block the local stack allocated variables
1061  disappear */
1062  if(statement_block_p(s) && !ENDP(dl=statement_declarations(s))) {
1063  /* Get rid of the dynamic and stack variables declared in this block
1064  statement. No stack variable should be analyzed as the stack
1065  area is used only for dependent types. */
1067  if(!ENDP(vl))
1068  nt = safe_transformer_projection(nt, vl);
1069  }
1070  /* nt = transformer_normalize(nt, 7); */
1071  /* nt = transformer_normalize(nt, 4); */
1072  nt = transformer_normalize(nt, 2);
1073 
1074  if(!transformer_consistency_p(nt)) {
1075  _int so = statement_ordering(s);
1076  (void) fprintf(stderr, "statement %03td (%td,%td):\n",
1077  statement_number(s),
1079  /* (void) print_transformer(load_statement_transformer(s)); */
1080  (void) print_transformer(nt);
1081  dump_transformer(nt);
1082  pips_internal_error("Inconsistent transformer detected");
1083  }
1084  ifdebug(1) {
1085  pips_assert("Transformer is internally consistent",
1087  }
1088  }
1089 
1090 #if 0
1091  /* When the statement is virtually replicated via control nodes, the
1092  statement transformer is the convex hull of all its replicate
1093  transformers. */
1094  if(transformer_undefined_p(ot)) {
1095  if (get_int_property("SEMANTICS_NORMALIZATION_LEVEL_BEFORE_STORAGE") == 4)
1096  nt = transformer_normalize(nt, 4);
1097  t = copy_transformer(nt);
1098  }
1099  else {
1100  /* This implies that transformers are computed in context and that
1101  we are dealing with a non-deterministic unstructured with several
1102  nodes for a unique statement. */
1103  t = transformer_convex_hull(nt, ot);
1104 
1105  ifdebug(1) {
1106  pips_assert("transformers are computed in context",
1107  get_bool_property("SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT"));
1108  pips_debug(1, "Convex hull for transformer of statement %03td (%td,%td)\n",
1111  pips_debug(1, "Previous transformer:\n");
1112  (void) print_transformer(ot);
1113  pips_debug(1, "New transformer:\n");
1114  (void) print_transformer(nt);
1115  pips_debug(1, "Resulting transformer:\n");
1116  (void) print_transformer(t);
1117  }
1118  }
1119 
1120  /* store or update the statement transformer */
1121  if(transformer_undefined_p(ot)) {
1123  }
1124  else {
1125  transformer_free(ot);
1127  /* delete_statement_transformer(s); */
1128  /* store_statement_transformer(s, t); */
1129  }
1130 #endif
1131  }
1132  else {
1133  semantics_user_warning("redefinition for statement %03d (%d,%d)\n",
1134  statement_number(s),
1137  pips_internal_error("transformer redefinition");
1138  }
1139 
1140  /* The transformer returned for the statement is not always the
1141  transformer stored for the statement. This happens for loops and for
1142  context sensitive transformers for replicated statements in
1143  CFG/unstructured. See comments in loop.c */
1144 
1145  // FI: Should not be useful for transformer lists? Why?
1146  // te = complete_statement_transformer(nt, pre, s);
1147 
1148  free_transformer(pre);
1149 
1150  ifdebug(8) {
1151  pips_assert("The statement and its substatements are still fully defined",
1153  }
1154 
1155  //pips_debug(8,"end for statement %03td (%td,%td) with t=%p, nt=%p and te=%p\n",
1156  // statement_number(s), ORDERING_NUMBER(statement_ordering(s)),
1157  // ORDERING_STATEMENT(statement_ordering(s)), t, nt, te);
1158 
1159  ifdebug(1) {
1160  pips_debug(1, "Transformer list has %zd elements:\n", gen_length(tl));
1161  print_transformers(tl);
1162  }
1163 
1164  return tl;
1165 }
int get_int_property(const string)
bool transformer_consistent_p(transformer p)
Definition: ri.c:2622
void transformer_free(transformer t)
Definition: basic.c:68
bool transformer_internal_consistency_p(transformer t)
Same as above but equivalenced variables should not appear in the argument list or in the predicate b...
Definition: basic.c:790
bool refine_transformers_p
Transformer recomputation cannot be of real use unless an interprocedural analysis is performed.
list load_cumulated_rw_effects_list(statement)
bool all_statements_defined_p(statement)
Definition: statement.c:3213
bool declaration_statement_p(statement)
Had to be optimized according to Beatrice Creusillet.
Definition: statement.c:224
intptr_t _int
_INT
Definition: newgen_types.h:53
#define print_transformer(t)
Definition: print.c:357
#define ORDERING_NUMBER(o)
#define ORDERING_STATEMENT(o)
#define statement_block_p(stat)
#define statement_ordering(x)
Definition: ri.h:2454
#define statement_declarations(x)
Definition: ri.h:2460
#define statement_instruction(x)
Definition: ri.h:2458
#define statement_number(x)
Definition: ri.h:2452
void transformer_add_reference_information(transformer tf, statement s)
static list instruction_to_transformer_list(instruction i, transformer tf, transformer pre, list e)
effects associated to instruction i
transformer declarations_to_transformer(list dl, transformer pre)
For C declarations.
list dynamic_variables_to_values(list list_mod)
Build the list of values to be projected when the declaration list list_mod is no longer valid becaus...
Definition: mappings.c:1007
transformer load_statement_precondition(statement)
void store_statement_transformer(statement, transformer)
transformer load_statement_transformer(statement)
void update_statement_transformer(statement, transformer)
transformer transformer_convex_hull(transformer t1, transformer t2)
transformer transformer_convex_hull(t1, t2): compute convex hull for t1 and t2; t1 and t2 are slightl...
Definition: convex_hull.c:216
transformer safe_transformer_projection(transformer t, list args)
t may be undefined, args may contain values unrelated to t
Definition: transformer.c:1187
transformer transformer_domain_intersection(transformer tf, transformer pre)
Restrict the domain of the relation tf with pre.
Definition: transformer.c:661

References all_statements_defined_p(), CONS, copy_transformer(), declaration_statement_p(), declarations_to_transformer(), dump_transformer, dynamic_variables_to_values(), ENDP, FOREACH, fprintf(), free_transformer(), gen_length(), get_bool_property(), get_int_property(), ifdebug, instruction_to_transformer_list(), list_undefined_p, load_cumulated_rw_effects_list(), load_statement_precondition(), load_statement_transformer(), NIL, ORDERING_NUMBER, ORDERING_STATEMENT, pips_assert, pips_debug, pips_internal_error, print_transformer, print_transformers(), refine_transformers_p, safe_transformer_projection(), semantics_user_warning, statement_block_p, statement_declarations, statement_instruction, statement_number, statement_ordering, store_statement_transformer(), TRANSFORMER, transformer_add_reference_information(), transformer_consistency_p(), transformer_consistent_p(), transformer_convex_hull(), transformer_domain_intersection(), transformer_free(), transformer_identity(), transformer_internal_consistency_p(), transformer_normalize(), transformer_range(), transformer_undefined, transformer_undefined_p, and update_statement_transformer().

Referenced by block_to_transformer_list(), test_to_transformer_list(), and whileloop_to_postcondition().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ test_to_transformer_list()

static list test_to_transformer_list ( test  t,
transformer  pre,
list  ef 
)
static

effects of t

EXPRESSION_TO_TRANSFORMER() SHOULD BE USED MORE EFFECTIVELY

Clearly, this must be true for transformer list to be computed. However, if test_to_transformer_list() is more general than test_to_transformer(), the later should disappear and be merged here, with a convex hull to reduce the list

Ideally, they should be initialized with the current best precondition, intraprocedural if nothing else better is available. This function's profile as well as most function profiles in ri_to_transformers should be modifed.

True condition transformer, TCT

False condition transformer, FCT

tffwc = precondition_add_condition_information(tffwc, e, context, false);

Definition at line 380 of file ri_to_transformer_lists.c.

383 {
384  list tl = NIL;
385  statement st = test_true(t);
386  statement sf = test_false(t);
387  transformer tf;
388 
389  /* EXPRESSION_TO_TRANSFORMER() SHOULD BE USED MORE EFFECTIVELY */
390 
391  pips_debug(8,"begin\n");
392 
393  /* Clearly, this must be true for transformer list to be
394  computed. However, if test_to_transformer_list() is more general
395  than test_to_transformer(), the later should disappear and be
396  merged here, with a convex hull to reduce the list */
398  expression e = test_condition(t);
399  /* Ideally, they should be initialized with the current best
400  precondition, intraprocedural if nothing else better is
401  available. This function's profile as well as most function
402  profiles in ri_to_transformers should be modifed. */
407  transformer tffwc = transformer_dup(tftwc);
408  list post_tftwc = NIL;
409  list post_tffwc = NIL;
410  list ta = NIL;
411  list fa = NIL;
412  /* True condition transformer, TCT */
414  /* False condition transformer, FCT */
416 
417  tftwc = transformer_apply(tct, context);
418 
419  ifdebug(8) {
420  pips_debug(8, "tftwc before transformer_temporary_value_projection %p:\n", tftwc);
421  (void) print_transformer(tftwc);
422  }
425  ifdebug(8) {
426  pips_debug(8, "tftwc before transformer_apply %p:\n", tftwc);
427  (void) print_transformer(tftwc);
428  }
429  list ttl = statement_to_transformer_list(st, tftwc);
430  // FI: why should we compute postconditions for ttl?!?
431  post_tftwc = transformer_apply_map(ttl, tftwc);
432  ifdebug(8) {
433  pips_debug(8, "tftwc after transformer_apply %p:\n", tftwc);
434  (void) print_transformer(tftwc);
435  pips_debug(8, "post_tftwc after transformer_apply %p:\n", post_tftwc);
436  (void) print_transformers(post_tftwc);
437  }
438 
439  /* tffwc = precondition_add_condition_information(tffwc, e, context, false); */
440  tffwc = transformer_apply(fct, context);
443  list ftl = statement_to_transformer_list(sf, tffwc);
444  // FI: why should we compute postconditions for ftl?!?
445  post_tffwc = transformer_apply_map(ftl, tffwc);
446 
447  ifdebug(8) {
448  pips_debug(8, "post_tftwc before transformer_convex_hull %p:\n", post_tftwc);
449  (void) print_transformers(post_tftwc);
450  pips_debug(8, "post_tffwc after transformer_apply %p:\n", post_tffwc);
451  (void) print_transformers(post_tffwc);
452  }
453 
454  //tf = transformer_convex_hull(post_tftwc, post_tffwc);
455  //tl = merge_transformer_lists(ttl, ftl); condition and its side
456  //effects are lost
457  tl = merge_transformer_lists(post_tftwc, post_tffwc);
459  transformer_free(tftwc);
460  transformer_free(tffwc);
461  //transformer_free(post_tftwc);
462  //transformer_free(post_tffwc);
463  free_arguments(ta);
464  free_arguments(fa);
465  }
466  else {
468  (void) statement_to_transformer(st, id);
469  (void) statement_to_transformer(sf, id);
470  tf = effects_to_transformer(ef);
471  tl = CONS(TRANSFORMER, tf, NIL);
472  free_transformer(id);
473  }
474 
475  pips_debug(8,"end\n");
476  return tl;
477 }
void free_arguments(cons *args)
Definition: arguments.c:218
transformer precondition_to_abstract_store(transformer pre)
Get rid of all old values and arguments.
Definition: basic.c:871
#define pips_flag_p(p)
for upwards compatibility with Francois's modified version
#define SEMANTICS_FLOW_SENSITIVE
#define test_false(x)
Definition: ri.h:2837
#define test_true(x)
Definition: ri.h:2835
#define test_condition(x)
Definition: ri.h:2833
transformer statement_to_transformer(statement s, transformer spre)
stmt precondition
Definition: delay.c:253
list transformer_apply_map(list tl, transformer pre)
Generates a new list of postconditions, one for each transformer in tl, unless the postcondition is e...
Definition: transformer.c:1610
list merge_transformer_lists(list, list)
transformer_list.c

References condition_to_transformer(), CONS, effects_to_transformer(), free_arguments(), free_transformer(), ifdebug, merge_transformer_lists(), NIL, pips_debug, pips_flag_p, precondition_to_abstract_store(), print_transformer, print_transformers(), reset_temporary_value_counter(), SEMANTICS_FLOW_SENSITIVE, statement_to_transformer(), statement_to_transformer_list(), test_condition, test_false, test_true, TRANSFORMER, transformer_apply(), transformer_apply_map(), transformer_dup(), transformer_free(), transformer_identity(), transformer_temporary_value_projection(), and transformer_undefined_p.

Referenced by instruction_to_transformer_list().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: