PIPS
loop.c File Reference
#include <stdio.h>
#include <string.h>
#include "genC.h"
#include "linear.h"
#include "ri.h"
#include "effects.h"
#include "ri-util.h"
#include "workspace-util.h"
#include "effects-util.h"
#include "effects-generic.h"
#include "effects-simple.h"
#include "misc.h"
#include "properties.h"
#include "vecteur.h"
#include "contrainte.h"
#include "transformer.h"
#include "semantics.h"
+ Include dependency graph for loop.c:

Go to the source code of this file.

Macros

#define IS_LOWER_BOUND   0
 
#define IS_UPPER_BOUND   1
 

Functions

transformer any_loop_to_k_transformer (transformer t_init, transformer t_enter, transformer t_next, statement body, list __attribute__((unused)) lel, transformer post_init, int k)
 Processing of loops for transformers, preconditions and transformer lists. More...
 
transformer any_loop_to_transformer (transformer t_init, transformer t_enter, transformer t_next, statement body, list __attribute__((unused)) lel, transformer post_init)
 
transformer forloop_to_transformer (forloop fl, transformer pre, list flel)
 effects of forloop fl More...
 
list forloop_to_transformer_list (forloop l __attribute__((unused)), transformer pre __attribute__((unused)), list e __attribute__((unused)))
 
transformer new_whileloop_to_transformer (whileloop wl, transformer pre, list wlel)
 effects of whileloop wl More...
 
transformer new_whileloop_to_k_transformer (whileloop wl, transformer pre, list wlel, int k)
 
transformer repeatloop_to_transformer (whileloop wl, transformer pre, list wlel)
 effects of whileloop wl More...
 
transformer add_loop_skip_condition (transformer tf, loop l, transformer pre)
 tf and pre are a unique data structure when preconditions are computed More...
 
static transformer add_affine_bound_conditions (transformer pre, entity index, Pvecteur v_bound, bool lower_or_upper, transformer tfb)
 FI: could be moved somewhere else, e.g. More...
 
static transformer add_index_bound_conditions (transformer pre, entity index, expression bound, int lower_or_upper, transformer tfb)
 Side effect on pre. More...
 
transformer add_index_range_conditions (transformer pre, entity i, range r, transformer tfb)
 
static transformer add_good_loop_conditions (transformer pre, loop l)
 
static transformer add_loop_index_initialization (transformer tf, loop l, transformer pre)
 Always returns newly allocated memory. More...
 
transformer add_loop_index_exit_value (transformer post, loop l, transformer pre)
 The exit value is known if. More...
 
bool simple_dead_loop_p (expression lower, expression upper)
 
transformer precondition_filter_old_values (transformer pre)
 
transformer transformer_add_loop_index_initialization (transformer tf, loop l, transformer pre)
 The loop initialization is performed before tf. More...
 
transformer transformer_add_loop_index_incrementation (transformer tf, loop l, transformer pre)
 
transformer loop_bound_evaluation_to_transformer (loop l, transformer pre)
 Side effects in loop bounds and increment are taken into account. More...
 
transformer loop_initialization_to_transformer (loop l, transformer pre)
 Note: It used to be implemented by computing the effect list of the lower bound expression and and new allocated effect for the loop index definition. More...
 
transformer loop_to_transformer (loop l, transformer pre, list e)
 The transformer associated to a DO loop does not include the exit condition because it is used to compute the precondition for any loop iteration. More...
 
list loop_to_transformer_list (loop l __attribute__((unused)), transformer pre __attribute__((unused)), list e __attribute__((unused)))
 
transformer loop_to_initialization_transformer (loop l, transformer pre)
 Transformer expression the loop initialization. More...
 
transformer loop_to_enter_transformer (loop l, transformer pre)
 Transformer expressiong the conditions between the index and the loop bounds according to the sign of the increment. More...
 
transformer loop_to_continue_transformer (loop l, transformer pre)
 
transformer new_loop_to_transformer (loop l, transformer pre, list lel)
 loop_to_transformer() was developed first but is not as powerful as the new algorithm used for all kinds of loops. More...
 
list complete_any_loop_transformer_list (transformer t_init, transformer t_skip, transformer t_body_star, transformer t_body, transformer t_inc, transformer t_exit)
 FI: used to be complete_any_loop_transformer() with a direct reduction by convex hull. More...
 
transformer complete_any_loop_transformer (transformer t_init, transformer __attribute__((unused)) t_enter, transformer t_skip, transformer t_body_star, transformer t_body, transformer __attribute__((unused)) t_continue, transformer t_inc, transformer t_exit)
 Reduce the transformer list associated to a loop to a unique transformer using a convex hull. More...
 
transformer complete_forloop_transformer (transformer t_body_star, transformer pre, forloop fl)
 
list complete_forloop_transformer_list (transformer t_body_star, transformer pre, forloop fl)
 
list new_complete_whileloop_transformer_list (transformer t_body_star, transformer pre, whileloop wl, bool entered_p __attribute__((__unused__)))
 entered_p is used to for the execution of at least one iteration More...
 
transformer new_complete_whileloop_transformer (transformer t_body_star, transformer pre, whileloop wl, bool entered_p)
 entered_p is used to for the execution of at least one iteration More...
 
list complete_repeatloop_transformer_list (transformer t_body_star, transformer __attribute__((unused)) pre, whileloop wl)
 
transformer complete_repeatloop_transformer (transformer t_body_star, transformer pre, whileloop wl)
 
transformer complete_loop_transformer (transformer ltf, transformer pre, loop l)
 The transformer computed and stored for a loop is useful to compute the loop body precondition, but it is not useful to analyze a higher level construct, which need the loop transformer with the exit condition. More...
 
list complete_loop_transformer_list (transformer ltf, transformer pre, loop l)
 
transformer complete_whileloop_transformer (transformer ltf, transformer pre, whileloop wl)
 FI: I'm not sure this function is useful. More...
 
list complete_whileloop_transformer_list (transformer ltf, transformer pre, whileloop wl)
 
transformer old_complete_whileloop_transformer (transformer ltf, transformer pre, whileloop l)
 
static transformer recompute_loop_transformer (loop l, transformer pre)
 Recompute a fixpoint conditionnally to a valid precondition for all iterations. More...
 
static transformer __attribute__ ((unused))
 NOT USED. More...
 
static transformer loop_body_transformer_add_entry_and_iteration_information (transformer tfb, transformer pre)
 FI: I do not have one test case to show that this function is of some use. More...
 
transformer standard_whileloop_to_transformer (whileloop l, transformer pre, list e)
 This function computes the effect of K loop iteration, with K positive. More...
 
transformer whileloop_to_transformer (whileloop l, transformer pre, list e)
 effects of whileloop l More...
 
transformer whileloop_to_k_transformer (whileloop l, transformer pre, list e, int k)
 
transformer any_loop_to_postcondition (statement body, transformer t_init, transformer t_enter, transformer t_skip, transformer t_body_star, transformer t_body, transformer t_next, transformer t_inc, transformer t_exit, transformer pre)
 
transformer forloop_to_postcondition (transformer pre, forloop fl, transformer t_body_star)
 
transformer repeatloop_to_postcondition (transformer pre, whileloop wl, transformer t_body_star)
 
transformer loop_to_postcondition (transformer pre, loop l, transformer tf)
 
transformer loop_to_total_precondition (transformer t_post, loop l, transformer tf, transformer context)
 
transformer whileloop_to_postcondition (transformer pre, whileloop l, transformer tf)
 
transformer whileloop_to_total_precondition (transformer t_post, whileloop l, transformer tf, transformer context)
 

Macro Definition Documentation

◆ IS_LOWER_BOUND

#define IS_LOWER_BOUND   0

Definition at line 491 of file loop.c.

◆ IS_UPPER_BOUND

#define IS_UPPER_BOUND   1

Definition at line 492 of file loop.c.

Function Documentation

◆ __attribute__()

static transformer __attribute__ ( (unused)  )
static

NOT USED.

NOT FULLY IMPLEMENTED YET. SHOULD BE REDUNDANT WITH whileloop_to_tramsformer() Recompute a fixpoint conditionnally to a valid precondition for all iterations Could/Should be later called from whileloop_to_postcondition()

Definition at line 2403 of file loop.c.

2404 {
2406  pips_assert("To shut up gcc", wl==wl && pre==pre);
2407  return new_tf;
2408 }
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define transformer_undefined
Definition: ri.h:2847

References pips_assert, and transformer_undefined.

◆ add_affine_bound_conditions()

static transformer add_affine_bound_conditions ( transformer  pre,
entity  index,
Pvecteur  v_bound,
bool  lower_or_upper,
transformer  tfb 
)
static

FI: could be moved somewhere else, e.g.

in transformer library. lower_or_upper: 0 for lower, 1 for upper, i.e. upper_p

check that v is not affected by tfb: N = 10 DO I = 1, N N = 1 {1<=I<=N} !wrong! T(I) = 0. ENDDO and make sure that aliasings (I,J) and (I,X) are correctly handled

Achtung: value_mappings_compatible_vector_p() has a side effect on its argument; it has to be evaluated before the second half of the test else effects would be wrongly interpreted in case of equivalences

Definition at line 580 of file loop.c.

585 {
586  Pvecteur v = vect_dup(v_bound);
587 
588  /* check that v is not affected by tfb:
589  * N = 10
590  * DO I = 1, N
591  * N = 1
592  * {1<=I<=N} !wrong!
593  * T(I) = 0.
594  * ENDDO
595  * and make sure that aliasings (I,J) and (I,X) are correctly handled
596  */
597 
598  /* Achtung: value_mappings_compatible_vector_p() has a side effect
599  * on its argument; it has to be evaluated before the second half of
600  * the test else effects would be wrongly interpreted in case of
601  * equivalences
602  */
603 
605  !transformer_affect_linear_p(tfb,v)) {
606  if (lower_or_upper == IS_LOWER_BOUND)
607  vect_add_elem(&v,
609  else{
610  vect_chg_sgn(v);
612  }
613  pre = transformer_inequality_add(pre, v);
614  }
615  else{
616  vect_rm(v);
617  v = VECTEUR_UNDEFINED;
618  }
619  return pre;
620 }
#define VALUE_MONE
#define VALUE_ONE
transformer transformer_inequality_add(transformer tf, Pvecteur i)
Definition: basic.c:375
void vect_chg_sgn(Pvecteur v)
void vect_chg_sgn(Pvecteur v): multiplie v par -1
Definition: scalaires.c:151
#define IS_LOWER_BOUND
Definition: loop.c:491
bool value_mappings_compatible_vector_p(Pvecteur iv)
transform a vector based on variable entities into a vector based on new value entities when possible...
Definition: mappings.c:924
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
bool transformer_affect_linear_p(transformer tf, Pvecteur l)
bool transformer_affect_linear_p(transformer tf, Pvecteur l): returns TRUE if there is a state s such...
Definition: transformer.c:1850
entity entity_to_new_value(entity)
Definition: value.c:859
#define VECTEUR_UNDEFINED
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
Pvecteur vect_dup(Pvecteur v_in)
Pvecteur vect_dup(Pvecteur v_in): duplication du vecteur v_in; allocation de et copie dans v_out;.
Definition: alloc.c:51
void vect_rm(Pvecteur v)
void vect_rm(Pvecteur v): desallocation des couples de v;
Definition: alloc.c:78
void vect_add_elem(Pvecteur *pvect, Variable var, Value val)
void vect_add_elem(Pvecteur * pvect, Variable var, Value val): addition d'un vecteur colineaire au ve...
Definition: unaires.c:72

References entity_to_new_value(), IS_LOWER_BOUND, transformer_affect_linear_p(), transformer_inequality_add(), value_mappings_compatible_vector_p(), VALUE_MONE, VALUE_ONE, vect_add_elem(), vect_chg_sgn(), vect_dup(), vect_rm(), and VECTEUR_UNDEFINED.

Referenced by add_index_bound_conditions().

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

◆ add_good_loop_conditions()

static transformer add_good_loop_conditions ( transformer  pre,
loop  l 
)
static

loop bounds can be kept as preconditions for the loop body if the loop increment is numerically known and if they are linear and if they are loop body invariant, i.e. indices are accepted

arg. tf is unused, it was replaced by tfb to correct a bug

Only OK if transformers already have been computed

transformer tfb = load_statement_transformer(b);

New version to deal with complex do loop bounds?

Old version

Definition at line 790 of file loop.c.

792 {
793  /* loop bounds can be kept as preconditions for the loop body
794  if the loop increment is numerically known and if they
795  are linear and if they are loop body invariant, i.e.
796  indices are accepted */
797  /* arg. tf is unused, it was replaced by tfb to correct a bug */
798  statement b = loop_body(l);
799  entity i = loop_index(l);
800  range r = loop_range(l);
801  /* Only OK if transformers already have been computed */
802  /* transformer tfb = load_statement_transformer(b); */
805 
806  pips_debug(8, "begin\n");
807 
808  if(false) { /* New version to deal with complex do loop bounds? */
810  transformer opre = pre;
811  pre = transformer_apply(pre, lbt);
812  free_transformer(opre);
813  }
814  else {
815  /* Old version */
816  pre = add_index_range_conditions(pre, i, r, tfb);
817  }
818 
819  pips_debug(8, "end\n");
820 
821  return(pre);
822 }
void free_transformer(transformer p)
Definition: ri.c:2616
list load_cumulated_rw_effects_list(statement)
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define loop_body(x)
Definition: ri.h:1644
#define loop_range(x)
Definition: ri.h:1642
#define loop_index(x)
Definition: ri.h:1640
transformer effects_to_transformer(list e)
list of effects
transformer loop_bound_evaluation_to_transformer(loop l, transformer pre)
Side effects in loop bounds and increment are taken into account.
Definition: loop.c:1203
transformer add_index_range_conditions(transformer pre, entity i, range r, transformer tfb)
Definition: loop.c:711
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
transformer transformer_apply(transformer tf, transformer pre)
transformer transformer_apply(transformer tf, transformer pre): apply transformer tf on precondition ...
Definition: transformer.c:1559

References add_index_range_conditions(), effects_to_transformer(), free_transformer(), load_cumulated_rw_effects_list(), loop_body, loop_bound_evaluation_to_transformer(), loop_index, loop_range, pips_debug, and transformer_apply().

Referenced by loop_to_postcondition(), loop_to_total_precondition(), and loop_to_transformer().

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

◆ add_index_bound_conditions()

static transformer add_index_bound_conditions ( transformer  pre,
entity  index,
expression  bound,
int  lower_or_upper,
transformer  tfb 
)
static

Side effect on pre.

lower_or_upper: 0 for lower, 1 for upper, i.e. upper_p

It is assumed on entry that index has values recognized by the semantics analysis

pips_assert("add_index_bound_conditions", entity_has_values_p(index));

Old implementation, careful about the impact of the loop body but not about side effets in bound

tfb does not take into account the index incrementation

Why not use loop_bound_evaluation_to_transformer()?

An inequation between index and bv should be added

FI: Fixt the result of the intersection in case of side effects in loop range

Make sure the loop body does not modify the loop bounds

FI: we need a side effect on pre...

Likely memory leak here: arguments_union may allocate a new list

This might or not make sense, depending on the caller transformer_arguments(pre) = arguments_difference(arguments_union(transformer_arguments(pre), transformer_arguments(npre)), transformer_arguments(tfb));

When dealing with the loop body precondition, there is no reasons to remove the arguments of tfb, as tfb is part of the definition of pre

Definition at line 624 of file loop.c.

629 {
630  normalized n = NORMALIZE_EXPRESSION(bound);
631 
632  /* It is assumed on entry that index has values recognized
633  * by the semantics analysis
634  */
635  /* pips_assert("add_index_bound_conditions", entity_has_values_p(index)); */
636 
637  if(normalized_linear_p(n)) {
638  /* Old implementation, careful about the impact of the loop body
639  but not about side effets in bound */
640  Pvecteur v_bound = (Pvecteur) normalized_linear(n);
641  /* tfb does not take into account the index incrementation */
642  transformer t_iter = transformer_dup(tfb);
643 
644  transformer_arguments(t_iter) =
646 
647  add_affine_bound_conditions(pre, index, v_bound, lower_or_upper, t_iter);
648  free_transformer(t_iter);
649  }
650  else { /* Why not use loop_bound_evaluation_to_transformer()? */
651  type it = ultimate_type(entity_type(index));
653  transformer pre_r = transformer_range(pre);
654  transformer bt = safe_any_expression_to_transformer(bv, bound, pre_r, true);
657 
658  /* An inequation between index and bv should be added */
659  if(lower_or_upper)
660  br = transformer_add_inequality(br, index, bv, false);
661  else
662  br = transformer_add_inequality(br, bv, index, false);
663 
667 
668  /* FI: Fixt the result of the intersection in case of side
669  effects in loop range*/
670  npre = transformer_range_intersection(pre, br);
671  //transformer_arguments(npre) = arguments_union(transformer_arguments(pre),
672  // transformer_arguments(npre));
673  /* Make sure the loop body does not modify the loop bounds */
674  // FI: ipre is not a range, invariant_wrt_transformer() cannot be used
675  //npre = invariant_wrt_transformer(ipre, tfb);
676  // FI: removes to many variables of ipre or npre; induction
677  // variables are lost when computing the preconditions
678  //npre = safe_transformer_projection(npre, transformer_arguments(tfb));
679  /* FI: we need a side effect on pre... */
680  //gen_free_list(transformer_arguments(pre));
682  /* Likely memory leak here: arguments_union may allocate a new list*/
683  /* This might or not make sense, depending on the caller
684  transformer_arguments(pre) =
685  arguments_difference(arguments_union(transformer_arguments(pre),
686  transformer_arguments(npre)),
687  transformer_arguments(tfb));
688  */
689  /* When dealing with the loop body precondition, there is no
690  reasons to remove the arguments of tfb, as tfb is part of the
691  definition of pre */
694  transformer_arguments(npre));
695 
697  free_transformer(bt);
698  free_transformer(br);
699  transformer_arguments(npre) = NIL;
701  free_transformer(npre);
702  free_transformer(pre_r);
703  }
704 
705  pips_assert("The resulting transformer is consistent",
707 
708  return(pre);
709 }
bool transformer_consistent_p(transformer p)
Definition: ri.c:2622
void free_predicate(predicate p)
Definition: ri.c:1787
cons * arguments_union(cons *a1, cons *a2)
cons * arguments_union(cons * a1, cons * a2): returns a = union(a1, a2) where a1 and a2 are lists of ...
Definition: arguments.c:116
cons * arguments_add_entity(cons *a, entity e)
Definition: arguments.c:85
transformer transformer_dup(transformer t_in)
transformer package - basic routines
Definition: basic.c:49
transformer transformer_add_inequality(transformer tf, entity v1, entity v2, bool strict_p)
Add the equality v1 <= v2 or v1 < v2.
Definition: basic.c:464
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#define NORMALIZE_EXPRESSION(e)
type ultimate_type(type)
Definition: type.c:3466
#define normalized_linear_p(x)
Definition: ri.h:1779
#define transformer_relation(x)
Definition: ri.h:2873
#define predicate_undefined
Definition: ri.h:2046
#define transformer_arguments(x)
Definition: ri.h:2871
#define entity_type(x)
Definition: ri.h:2792
#define normalized_linear(x)
Definition: ri.h:1781
transformer safe_any_expression_to_transformer(entity v, expression expr, transformer pre, bool is_internal)
Always return a usable transformer.
Definition: expression.c:5156
static transformer add_affine_bound_conditions(transformer pre, entity index, Pvecteur v_bound, bool lower_or_upper, transformer tfb)
FI: could be moved somewhere else, e.g.
Definition: loop.c:580
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_range_intersection(transformer tf, transformer r)
Allocate a new transformer rtf that is tf with its range restricted by the range r.
Definition: transformer.c:830
transformer transformer_range(transformer tf)
Return the range of relation tf in a newly allocated transformer.
Definition: transformer.c:714
transformer transformer_temporary_value_projection(transformer tf)
Definition: transformer.c:1149
entity make_local_temporary_value_entity(type)
Definition: value.c:605
void reset_temporary_value_counter(void)
Definition: value.c:250
struct Svecteur * Pvecteur

References add_affine_bound_conditions(), arguments_add_entity(), arguments_union(), entity_type, free_predicate(), free_transformer(), make_local_temporary_value_entity(), NIL, NORMALIZE_EXPRESSION, normalized_linear, normalized_linear_p, pips_assert, predicate_undefined, reset_temporary_value_counter(), safe_any_expression_to_transformer(), safe_transformer_projection(), transformer_add_inequality(), transformer_arguments, transformer_consistent_p(), transformer_dup(), transformer_range(), transformer_range_intersection(), transformer_relation, transformer_temporary_value_projection(), transformer_undefined, and ultimate_type().

Referenced by add_index_range_conditions().

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

◆ add_index_range_conditions()

transformer add_index_range_conditions ( transformer  pre,
entity  i,
range  r,
transformer  tfb 
)

if tfb is not undefined, then it is a loop; loop bounds can be kept as preconditions for the loop body if the loop increment is numerically known and if they are linear and if they are loop body invariant, i.e. indices are accepted

is the loop increment numerically known? Is its sign known?

incr == 0 is used below as a give-up condition

When lost, try to exploit type information thanks to unsigned variables

find the real upper and lower bounds

try to add the lower bound

try to add the upper bound

Parameters
prere
tfbfb

Definition at line 711 of file loop.c.

715 {
716  /* if tfb is not undefined, then it is a loop;
717  loop bounds can be kept as preconditions for the loop body
718  if the loop increment is numerically known and if they
719  are linear and if they are loop body invariant, i.e.
720  indices are accepted */
721 
722  expression lb = range_lower(r);
723  expression ub = range_upper(r);
724  expression e_incr = range_increment(r);
725  int incr = 0;
726  int incr_lb = 0;
727  int incr_ub = 0;
728 
729  pips_debug(8, "begin\n");
730 
731  if(entity_has_values_p(i)) {
732 
733  /* is the loop increment numerically known? Is its sign known? */
734  expression_and_precondition_to_integer_interval(e_incr, pre, &incr_lb, &incr_ub);
735 
736  if(incr_lb==incr_ub) {
737  if(incr_lb==0) {
738  pips_user_error("Illegal null increment\n");
739  }
740  else
741  incr = incr_lb;
742  }
743  else if(incr_lb>=1) {
744  incr = 1;
745  }
746  else if(incr_ub<=-1) {
747  incr = -1;
748  }
749  else {
750  /* incr == 0 is used below as a give-up condition */
751  incr = 0;
752  }
753 
754  /* When lost, try to exploit type information thanks to unsigned variables */
755  if(incr==0) {
756  if(positive_expression_p(e_incr))
757  incr = 1;
758  else if(negative_expression_p(e_incr))
759  incr = -1;
760  }
761 
762  /* find the real upper and lower bounds */
763  if(incr<0) {
764  ub = range_lower(r);
765  lb = range_upper(r);
766  }
767 
768  if(incr!=0) {
769  if(simple_dead_loop_p(lb, ub)) {
770  transformer new_pre = transformer_empty();
771 
772  free_transformer(pre);
773  pre = new_pre;
774  }
775  else {
776  /* try to add the lower bound */
777  add_index_bound_conditions(pre, i, lb, IS_LOWER_BOUND, tfb);
778 
779  /* try to add the upper bound */
780  add_index_bound_conditions(pre, i, ub, IS_UPPER_BOUND, tfb);
781  }
782  }
783 
784  }
785 
786  pips_debug(8, "end\n");
787  return pre;
788 }
transformer transformer_empty()
Allocate an empty transformer.
Definition: basic.c:120
#define pips_user_error
Definition: misc-local.h:147
bool positive_expression_p(expression e)
Use constants and type information to decide if the value of sigma(e) is always positive,...
Definition: eval.c:826
bool negative_expression_p(expression e)
Use constants and type information to decide if the value of sigma(e) is always negative,...
Definition: eval.c:896
#define range_upper(x)
Definition: ri.h:2290
#define range_increment(x)
Definition: ri.h:2292
#define range_lower(x)
Definition: ri.h:2288
#define IS_UPPER_BOUND
Definition: loop.c:492
bool simple_dead_loop_p(expression lower, expression upper)
Definition: loop.c:1028
static transformer add_index_bound_conditions(transformer pre, entity index, expression bound, int lower_or_upper, transformer tfb)
Side effect on pre.
Definition: loop.c:624
void expression_and_precondition_to_integer_interval(expression, transformer, int *, int *)
Evaluate expression e in context p, assuming that e is an integer expression.
Definition: utils.c:325
bool entity_has_values_p(entity)
This function could be made more robust by checking the storage of e.
Definition: value.c:911

References add_index_bound_conditions(), entity_has_values_p(), expression_and_precondition_to_integer_interval(), free_transformer(), IS_LOWER_BOUND, IS_UPPER_BOUND, negative_expression_p(), pips_debug, pips_user_error, positive_expression_p(), range_increment, range_lower, range_upper, simple_dead_loop_p(), and transformer_empty().

Referenced by add_good_loop_conditions(), comp_regions_of_implied_do(), and loop_to_transformer().

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

◆ add_loop_index_exit_value()

transformer add_loop_index_exit_value ( transformer  post,
loop  l,
transformer  pre 
)

The exit value is known if.

  • the loop index is an analyzed integer scalar variable real index are standard-compliant, integer index can be equivalenced to a real variable,...
  • the increment is affine (non-necessary assumption made: it is affine if the increment sign is known)
  • the increment sign is known
  • the body and loop initialization execution does not modify the value of the upper bound
  • the upper bound is affine (?)

Affine increments can be handled when their signs only are known.

For instance, for increment==k: i >= ub i-k <= ub-1

Note the simplification when k==1.

But, first of all, the value of the loop index in post must be incremented. This changes its relationship with induction variables.

Most tests here are redundant because this function is only called if it has been proved that the loop was executed which implies that the upper and lower bounds are affine, that the increment is affine and that the increment sign is known.

Always returns a newly allocated value precondition on loop entrance

This part should be useless because post really is a loop postcondition. There should be no need for an index incrementation or anything. It is used to recover some of the fix-point failures:-(

In fact, it may be useful. The loop transformer and its invariant are computed without knowledge about the number of iteration, which may be zero. By adding one execution of the loop body and the index incrementation, we change b* into b+ which should add effective information.

Do not apply an extra iteration!

post = transformer_apply(t_body, post);

v_i - v_incr == v_ub, regardless of the sign

v_i - v_incr <= v_ub < v_i or: v_i - v_incr - v_ub <= 0, v_ub - v_i + 1 <= 0

v_i - v_incr >= v_ub > v_i

or:

  • v_i + v_incr + v_ub <= 0, - v_ub + v_i + 1 <= 0

should never happen!

Parameters
postost
lpostcondition of the last iteration
preloop to process

Definition at line 878 of file loop.c.

882 {
883  entity i = loop_index(l);
885  normalized n_incr = NORMALIZE_EXPRESSION(e_incr);
886  expression e_ub = range_upper(loop_range(l));
887  normalized n_ub = NORMALIZE_EXPRESSION(e_ub);
890  list li = CONS(ENTITY, i, NIL);
891  int ub_inc = 0;
892  int lb_inc = 0;
893 
894  ifdebug(8) {
895  pips_debug(8, "begin with post:\n");
896  (void) print_transformer(post);
897  }
898 
899  if(!entity_has_values_p(i)) {
900  ifdebug(8) {
901  pips_debug(8, "give up because %s has no values:\n",
902  entity_local_name(i));
903  pips_debug(8, "end with post:\n");
904  (void) print_transformer(post);
905  }
906  return transformer_dup(post);
907  }
908 
909  expression_and_precondition_to_integer_interval(e_incr, pre, &lb_inc, &ub_inc);
910 
911  /* This part should be useless because post really is a loop postcondition.
912  * There should be no need for an index incrementation or anything.
913  * It is used to recover some of the fix-point failures:-(
914  *
915  * In fact, it may be useful. The loop transformer and its invariant are
916  * computed without knowledge about the number of iteration, which may be
917  * zero. By adding one execution of the loop body and the index incrementation,
918  * we change b* into b+ which should add effective information.
919  */
920  if(normalized_linear_p(n_incr)) {
921  Pvecteur v_incr = (Pvecteur) normalized_linear(n_incr);
923  entity i_new = entity_to_new_value(i);
924  entity i_rep = value_to_variable(i_new);
925  t_incr = affine_increment_to_transformer(i_rep, v_incr);
926  }
927  else {
928  t_incr = transformer_undefined;
929  }
930  }
931  else {
932  t_incr = transformer_undefined;
933  }
934  if(t_incr==transformer_undefined)
935  t_incr = args_to_transformer(li);
936  /* Do not apply an extra iteration! */
937  /* post = transformer_apply(t_body, post); */
938  post = transformer_apply(t_incr, post);
939  transformer_free(t_incr);
940 
941  ifdebug(8) {
942  pips_debug(8, "post after index incrementation:\n");
943  (void) print_transformer(post);
944  }
945 
946  if(normalized_linear_p(n_ub)
948  if(lb_inc >= 1 || ub_inc <= -1) {
949  Pvecteur v_ub = (Pvecteur) normalized_linear(n_ub);
950  Pvecteur v_incr = (Pvecteur) normalized_linear(n_incr);
951 
954  entity i_new = entity_to_new_value(i);
955  entity i_rep = value_to_variable(i_new);
956  Pvecteur v_i = vect_new((Variable) i_rep, (Value) 1);
959 
960  pips_assert("The increment is an affine function", normalized_linear_p(n_incr));
961  if(lb_inc==ub_inc && ABS(lb_inc)==1) {
962  /* v_i - v_incr == v_ub, regardless of the sign */
963  c1 = vect_substract(v_i, v_incr);
964  c1 = vect_cl(c1, (Value) -1, v_ub);
965  transformer_equality_add(post, c1);
966  }
967  else {
968  if(lb_inc>=1) {
969  /* v_i - v_incr <= v_ub < v_i
970  * or:
971  * v_i - v_incr - v_ub <= 0, v_ub - v_i + 1 <= 0
972  */
973  c1 = vect_substract(v_i, v_incr);
974  c2 = vect_substract(v_ub, v_i);
975 
976  c1 = vect_cl(c1, (Value) -1, v_ub);
977  vect_add_elem(&c2, (Variable) TCST, (Value) 1);
978  }
979  else if(ub_inc<=-1) {
980  /* v_i - v_incr >= v_ub > v_i
981  *
982  * or:
983  * - v_i + v_incr + v_ub <= 0, - v_ub + v_i + 1 <= 0
984  */
985  c1 = vect_substract(v_incr, v_i);
986  c2 = vect_substract(v_i, v_ub);
987 
988  c1 = vect_cl(c1, (Value) 1, v_ub);
989  vect_add_elem(&c2, (Variable) TCST, (Value) 1);
990  }
991  else {
992  /* should never happen! */
993  pips_assert("add_loop_index_exit_value", false);
994  }
995  transformer_inequality_add(post, c1);
996  transformer_inequality_add(post, c2);
997  }
998 
999  ifdebug(8) {
1000  pips_debug(8, "post with exit conditions:\n");
1001  (void) print_transformer(post);
1002  }
1003  }
1004  else {
1005  pips_debug(8,
1006  "post is unchanged because the increment or the upper bound"
1007  " reference unanalyzed variables\n");
1008  }
1009  }
1010  else {
1011  pips_debug(8,
1012  "post is unchanged because the increment sign is unknown\n");
1013  }
1014  }
1015  else {
1016  pips_debug(8,
1017  "post is unchanged because the upper bound is not affine\n");
1018  }
1019 
1020  ifdebug(8) {
1021  pips_debug(8, "end: post:\n");
1022  (void) print_transformer(post);
1023  }
1024 
1025  return post;
1026 }
int Value
#define ABS(x)
was: #define value_mult(v,w) value_direct_multiply(v,w) #define value_product(v,w) value_direct_produ...
void transformer_free(transformer t)
Definition: basic.c:68
transformer transformer_equality_add(transformer tf, Pvecteur i)
Definition: basic.c:383
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
#define print_transformer(t)
Definition: print.c:357
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
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
transformer affine_increment_to_transformer(entity e, Pvecteur a)
Definition: expression.c:1269
transformer load_statement_transformer(statement)
#define ifdebug(n)
Definition: sg.c:47
transformer args_to_transformer(list le)
Generates a transformer abstracting a totally unknown modification of the values associated to variab...
Definition: transformer.c:1907
entity value_to_variable(entity)
Get the primitive variable associated to any value involved in a transformer.
Definition: value.c:1624
#define TCST
VARIABLE REPRESENTANT LE TERME CONSTANT.
Pvecteur vect_new(Variable var, Value coeff)
Pvecteur vect_new(Variable var,Value coeff): allocation d'un vecteur colineaire au vecteur de base va...
Definition: alloc.c:110
Pvecteur vect_substract(Pvecteur v1, Pvecteur v2)
Pvecteur vect_substract(Pvecteur v1, Pvecteur v2): allocation d'un vecteur v dont la valeur est la di...
Definition: binaires.c:75
Pvecteur vect_cl(Pvecteur v, Value lambda, Pvecteur u)
Definition: binaires.c:181

References ABS, affine_increment_to_transformer(), args_to_transformer(), CONS, ENTITY, entity_has_values_p(), entity_local_name(), entity_to_new_value(), expression_and_precondition_to_integer_interval(), ifdebug, load_statement_transformer(), loop_body, loop_index, loop_range, NIL, NORMALIZE_EXPRESSION, normalized_linear, normalized_linear_p, pips_assert, pips_debug, print_transformer, range_increment, range_upper, TCST, transformer_affect_linear_p(), transformer_apply(), transformer_dup(), transformer_equality_add(), transformer_free(), transformer_inequality_add(), transformer_undefined, value_mappings_compatible_vector_p(), value_to_variable(), vect_add_elem(), vect_cl(), vect_new(), vect_substract(), and VECTEUR_UNDEFINED.

Referenced by complete_loop_transformer(), complete_loop_transformer_list(), loop_to_postcondition(), and loop_to_total_precondition().

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

◆ add_loop_index_initialization()

static transformer add_loop_index_initialization ( transformer  tf,
loop  l,
transformer  pre 
)
static

Always returns newly allocated memory.

Definition at line 825 of file loop.c.

828 {
829  entity i = loop_index(l);
833  //list lef = expression_to_proper_effects(init);
835  transformer pre_r = transformer_range(pre);
836 
837  t_init = any_scalar_assign_to_transformer(i, init, lef, pre_r);
838  free_transformer(pre_r);
839 
840  if(t_init==transformer_undefined)
841  t_init = effects_to_transformer(lef);
842  post = transformer_apply(t_init, tf);
843 
844  transformer_free(t_init);
845 
846  return post;
847 }
list expression_to_proper_constant_path_effects(expression)
static int init
Maximal value set for Fortran 77.
Definition: entity.c:320
transformer any_scalar_assign_to_transformer(entity v, expression rhs, list ef, transformer pre)
precondition

References any_scalar_assign_to_transformer(), effects_to_transformer(), expression_to_proper_constant_path_effects(), free_transformer(), init, loop_index, loop_range, range_lower, transformer_apply(), transformer_free(), transformer_range(), and transformer_undefined.

Referenced by complete_loop_transformer(), complete_loop_transformer_list(), and loop_to_postcondition().

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

◆ add_loop_skip_condition()

transformer add_loop_skip_condition ( transformer  tf,
loop  l,
transformer  pre 
)

tf and pre are a unique data structure when preconditions are computed

It is assumed that loop l is not entered

EXPRESSION_TO_TRANSFORMER() should be used

is the loop increment numerically known? Is its sign known?

incr == 0 is used below as a give-up condition

find the real upper and lower bounds

exchange bounds

ub < lb, i.e. ub + lb + 1 <= 0

Parameters
tff
prere

Definition at line 495 of file loop.c.

496 {
497  /* It is assumed that loop l is not entered */
498  range r = loop_range(l);
499  expression e_lb = range_lower(r);
500  expression e_ub = range_upper(r);
501  expression e_incr = range_increment(r);
502  normalized n_lb = NORMALIZE_EXPRESSION(e_lb);
503  normalized n_ub = NORMALIZE_EXPRESSION(e_ub);
504  int incr = 0;
505  int incr_lb = 0;
506  int incr_ub = 0;
507 
508  /* EXPRESSION_TO_TRANSFORMER() should be used */
509 
510  pips_debug(8,"begin with transformer tf=%p\n", tf);
511  ifdebug(8) {
512  (void) print_transformer(tf);
513  pips_debug(8,"and precondition pre=%p\n", pre);
514  (void) print_transformer(pre);
515  }
516 
517  /* is the loop increment numerically known? Is its sign known? */
518  expression_and_precondition_to_integer_interval(e_incr, pre, &incr_lb, &incr_ub);
519 
520  if(incr_lb==incr_ub) {
521  if(incr_lb==0) {
522  user_error("add_loop_skip_condition", "Illegal null loop increment\n");
523  }
524  else
525  incr = incr_lb;
526  }
527  else if(incr_lb>=1) {
528  incr = 1;
529  }
530  else if(incr_ub<=-1) {
531  incr = -1;
532  }
533  else
534  incr = 0;
535 
536  /* incr == 0 is used below as a give-up condition */
537 
538  /* find the real upper and lower bounds */
539  if(incr<0) {
540  /* exchange bounds */
541  n_lb = NORMALIZE_EXPRESSION(e_ub);
542  n_ub = NORMALIZE_EXPRESSION(e_lb);
543  }
544 
545  if(incr!=0 && normalized_linear_p(n_lb) && normalized_linear_p(n_ub)) {
546  /* ub < lb, i.e. ub + lb + 1 <= 0 */
547  Pvecteur v_ub = (Pvecteur) normalized_linear(n_ub);
548  Pvecteur v_lb = (Pvecteur) normalized_linear(n_lb);
549 
552  Pvecteur v = vect_substract(v_ub, v_lb);
553 
554  vect_add_elem(&v, TCST, (Value) 1);
555  tf = transformer_inequality_add(tf, v);
556 
557  ifdebug(8) {
558  debug(8,"add_loop_skip_condition","Skip condition:\n");
559  vect_fprint(stderr, v, (char * (*)(Variable)) external_value_name);
560  }
561  }
562  else {
563  pips_debug(8,"Non-analyzed variable in loop bound(s)\n");
564  }
565  }
566  else {
567  pips_debug(8,"increment sign unknown or non-affine bound\n");
568  }
569 
570  ifdebug(8) {
571  pips_debug(8,"end with new tf=%p\n", tf);
572  (void) print_transformer(tf);
573  }
574 
575  return tf;
576 }
void vect_fprint(FILE *f, Pvecteur v, get_variable_name_t variable_name)
void vect_fprint(FILE * f, Pvecteur v, char * (*variable_name)()): impression d'un vecteur creux v su...
Definition: io.c:124
#define user_error(fn,...)
Definition: misc-local.h:265
void debug(const int the_expected_debug_level, const char *calling_function_name, const char *a_message_format,...)
ARARGS0.
Definition: debug.c:189
const char * external_value_name(entity)
Definition: value.c:753

References debug(), expression_and_precondition_to_integer_interval(), external_value_name(), ifdebug, loop_range, NORMALIZE_EXPRESSION, normalized_linear, normalized_linear_p, pips_debug, print_transformer, range_increment, range_lower, range_upper, TCST, transformer_inequality_add(), user_error, value_mappings_compatible_vector_p(), vect_add_elem(), vect_fprint(), and vect_substract().

Referenced by complete_loop_transformer(), complete_loop_transformer_list(), loop_to_postcondition(), and loop_to_total_precondition().

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

◆ any_loop_to_k_transformer()

transformer any_loop_to_k_transformer ( transformer  t_init,
transformer  t_enter,
transformer  t_next,
statement  body,
list __attribute__((unused))  lel,
transformer  post_init,
int  k 
)

Processing of loops for transformers, preconditions and transformer lists.

semantic analysis: processing of loops include "constants.h" include "control.h" General handling of structured loops: while, repeat, for, do.

Because the functions for "do" loops pre-existed this framework, they have not (yet) been reimplemented with it. Their implementations are likely to be more CPU efficient because only useful objects are computed whereas the general case requires the computation and use of neutral and absorbent elements such as tranformer_identity() and transformer_empty(). The functions for "while" loops have been rewritten to check the genericity.

Slightly different equations are used for the repeat loop, which executes once or at least twice instead of zero or at least once. These equations are given in the corresponding module, complete_repeatloop_transformer() and repeatloop_to_postcondition().

The transformer associated to any kind of loop, but the repeat_loop, is defined by equation:

t_loop = t_init ; t_skip + t_init ; t_enter ; (t_body ; t_next)* ; t_body ; t_inc; t_exit

where ";" is the combine operator and "+" the union. Note already that t_init is not factored out because the union usually loses information and its use must be postponed as much as possible.

Transformers t_init, t_skip, t_inc, t_next and t_exit are dependent on the kind of loops. For instance, t_skip is transformer_empty for a repeat loop and t_next may include the incrementation (t_inc) and the looping condition (for loop) or just the looping condition (while loop). When no incrementation occurs, t_inc is t_identity and

t_next = t_continue. Elsewhere:

t_next = t_inc ; t_continue

Because transformers are used to compute preconditions, we need to preserve:

t_body_star = t_init ; t_enter ;(t_body ; t_next)*

to compute the body preconditions as t_body_star(pre). But it might be better to use equation

.t_init ; t_enter(pre) + (t_init ; t_enter ;(t_body ; t_next)* ; t_body ; t_next)(pre)

to reduce the approximation in the * operator (see below).

Since we store only one transformer per statement (no such thing as proper and cumulated effects), we store t_body_star instead of t_loop. Note that the range of t_body_star can be restricted by the union of the ranges of t_enter and t_continue (or t_next) which are the last transitions to occur in t_body_star.

But to obtain a correct transformer for the bottom-up composition of transformers, we fix the resulting transformer in statement_to_transformer with the equation:

t_loop = t_init ; t_skip + t_body_star ; t_body ; t_inc; t_exit

When computing the loop postcondition, we do not use t_loop either because we want to postpone the use of "+":

post = (t_init ; t_skip)(pre) + (t_body_star ; t_body ; t_inc ; t_exit) (pre)

When computing the body precondition, we use the following equation

p_body = (t_init ; t_enter)(pre) + (t_body_star ; t_body ; t_next) (pre)

in order to avoid t_body_star imprecision due to a union with t_identity and to delay it in the precondition domain whose dimension is half of the transformer domain dimension.

Note also that the different transformers are computed relatively to a current precondition. So t_init, t_skip etc... may have different values at differente stages. This happens more when transformers are computed in context (setproprety SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT true) and even more when they are recomputed (apply REFINE_TRANSFORMERS). For this reason, a first crude precondition is computed with effects information to be used to compute the body transformer. And since t_enter cannot be computed without its precondition, the later is passed as post_init instead of the loop precondition pre:

post_init = t_init(pre)

A new transformer is allocated. None of the arguments are modified.

The source code has been restructured with a lot of the processing moved into any_transformer_to_k_closure Would be nicer with a proper graph. The transformer associated to a loop in a PIPS print out is the transformer leading from the loop precondition to the loop invariant, t_????. But the transformer recursively returned is t_loop, leading from the loop precondition to the loop postcondition. Designed in West Palm Beach, Dec. 2009. Notations may have sliglhty changed during the coding.

x loop precondition----------------------------------— | t_init | t_????? | t_loop v | |

x post_init
-----------------------—

| | t_enter | | | t_skip v | | | x post_enter | | | | identity | | | v | | | -> x <---------—loop invariant | | tf_body_star/__/| t_body | | | v | | | x | | | | t_inc | | | v | | | x | ! | | | | | ---------------— | | | | t_exit | t_continue | | v v v | | ------— x-----------— | | | v | x loop postcondition <-------------------------------—

The same scheme is used for all kinds of loops. Of course, t_inc, t_exit, t_skip and t_continue have to be adapted to the loop kind. k is the periodicity sought. The normal standard default value is

  1. If k == 1, the body transformer is computed first and the loop transformer is derived from it. If k>1, the body transformer is retrieved and the loop transformer is based on the assumption that the number of iterations executed is always a multiple of k.

This is obsolete and k should always be equal to 1. When a different value of k is required, call directly any_transformer_to_k_closure().

Compute a first rough body precondition, pre_body, using different heuristics:

  • a very approximate fix-point and the conditions met for the body to execute, pre_iteration.
  • the convex hull of the precondition holding for the first iteration and the range of the extended body transformer, t_next.

Add the loop body execution condition

Compute the body transformer

Any transformer or other data structure to free?

Definition at line 203 of file loop.c.

210 {
211  transformer t_body = transformer_undefined; // Body transformer
212  transformer t_body_star = transformer_undefined; // result: t_init ; t_enter ; tfbodystar
215  // This does not include the loop effects, e.g. the index incrementation
216  //list bel = load_cumulated_rw_effects_list(body);
217  //transformer t_effects = effects_to_transformer(bel);
218  transformer t_effects = effects_to_transformer(lel);
219  transformer post_enter = transformer_apply(t_enter, post_init);
220  //post_enter = transformer_normalize(post_enter, 0);
222  transformer t_next_star = transformer_undefined;
223 
224  // They are displayed by any_transformer_to_k_closure()
225  ifdebug(9) {
226  fprintf(stderr, "t_init:\n");
227  print_transformer(t_init);
228  fprintf(stderr, "t_enter:\n");
229  print_transformer(t_enter);
230  fprintf(stderr, "t_next:\n");
231  print_transformer(t_next);
232  fprintf(stderr, "post_init:\n");
233  print_transformer(post_init);
234  }
235 
236  /* Compute a first rough body precondition, pre_body, using
237  * different heuristics:
238  *
239  * - a very approximate fix-point and the conditions met for the
240  * body to execute, pre_iteration.
241  *
242  * -
243  *
244  * - the convex hull of the precondition holding for the first
245  * iteration and the range of the extended body transformer,
246  * t_next.
247  */
248  //
249  // First heuristics:
250  //pre_body = invariant_wrt_transformer(post_enter, t_effects);
251  // memory leak for pre_body? for transformer_range(pre_iteration)?
252  //pre_body = invariant_wrt_transformer(pre_body, t_next);
253  /* Add the loop body execution condition */
254  //pre_body = transformer_combine(pre_body, pre_iteration);
255  //
256  // Second heuristics: either we enter directly or we loop
257  post_body = transformer_apply(t_effects, post_enter);
258  // temporary memory leaks
259  t_next_star = (* transformer_fix_point_operator)(t_next);
260  post_next = transformer_range(transformer_apply(transformer_combine(t_next_star, t_next), post_body));
261  //post_next = transformer_normalize(post_next, 0);
262  transformer pre_body_2 = transformer_range(transformer_convex_hull(post_next, post_enter));
263  //
264  // Third heuristics: either it is the first iteration, or we are in
265  // the range of t_next (added for Semantics-New/flip-flop01.c, but
266  // turns out to be useless for flip-flop02)
267  // transformer pre_body_3 = transformer_convex_hull(post_enter, transformer_range(t_next));
268 
269  // pre_body = transformer_intersection(pre_body_2, pre_body_3);
270  //free_transformers(pre_body_2, pre_body_3, NULL);
271  pre_body = pre_body_2;
272 
273  /* Compute the body transformer */
274  // THIS PART SHOULD BE CLEANED-UP and k not used to avoid
275  // recomputing the transformers inside the loop body
276  // There is no longer any reason to call this function with k !=1
277  // For k == 2, call directly any_transformer_to_k_closure()
278  // statement_to_transformer() allocated a new transformer which is not the stored transformer
279  //t_body = transformer_dup(statement_to_transformer(body, pre_body));
280  if(k==1) {
281  t_body = statement_to_transformer(body, pre_body);
282  // Experimental: produces wrong results
283  // t_body = transformer_intersect_range_with_domain(t_body);
284  }
285  else // assume k==2
287 
288 
289  // Insert a call to any_transformer_to_k_closure()
290  t_body_star = any_transformer_to_k_closure(t_init,
291  t_enter,
292  t_next,
293  t_body,
294  post_init,
295  k, // unrollling degree
296  false); // assume a first
297  // execution of t_body
298 
299  /* Any transformer or other data structure to free? */
300  //free_transformer(t_body); FI: no idea if it should be freed or not...
301  free_transformer(pre_body);
302  free_transformer(post_body);
303  free_transformer(post_next);
304  free_transformer(t_effects);
305  free_transformer(post_enter);
306  free_transformer(t_next_star);
307 
308  ifdebug(8) {
309  fprintf(stderr, "t_body_star:\n");
310  print_transformer(t_body_star);
311  }
312 
313  return t_body_star;
314 }
transformer copy_transformer(transformer p)
TRANSFORMER.
Definition: ri.c:2613
transformer any_transformer_to_k_closure(transformer t_init, transformer t_enter, transformer t_next, transformer t_body, transformer post_init, int k, bool assume_previous_iteration_p)
Derived from any_loop_to_k_transformer()
Definition: fix_point.c:1304
transformer statement_to_transformer(statement s, transformer spre)
stmt precondition
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
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 transformer_combine(volatile transformer t1, transformer t2)
transformer transformer_combine(transformer t1, transformer t2): compute the composition of transform...
Definition: transformer.c:238

References any_transformer_to_k_closure(), copy_transformer(), effects_to_transformer(), fprintf(), free_transformer(), ifdebug, load_statement_transformer(), print_transformer, statement_to_transformer(), transformer_apply(), transformer_combine(), transformer_convex_hull(), transformer_range(), and transformer_undefined.

Referenced by any_loop_to_transformer(), and new_whileloop_to_k_transformer().

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

◆ any_loop_to_postcondition()

transformer any_loop_to_postcondition ( statement  body,
transformer  t_init,
transformer  t_enter,
transformer  t_skip,
transformer  t_body_star,
transformer  t_body,
transformer  t_next,
transformer  t_inc,
transformer  t_exit,
transformer  pre 
)

The precondition to propagate in the body is:

p_body = (t_init ; t_enter)(pre) + (t_body_star ; t_body ; t_next) (pre)

The loop postcondition to return is:

post = (t_init ; t_skip)(pre) + (t_body_star ; t_body ; t_inc ; t_exit) (pre)

To restrict the state at the beginning of the last iteration: should be part of t_body_star

Decompose the computation of p_body

Decompose the computation of post

a_post should be used because it is more accurate than direct recomputation, but we chose for the time being to recompute post entirely

Get rid of now useless transformers

Parameters
bodyody
t_init_init
t_enter_enter
t_skip_skip
t_body_star_body_star
t_body_body
t_next_next
t_inc_inc
t_exit_exit
prere

Definition at line 2634 of file loop.c.

2644 {
2645  /* The precondition to propagate in the body is:
2646  *
2647  * p_body = (t_init ; t_enter)(pre) + (t_body_star ; t_body ; t_next) (pre)
2648  *
2649  * The loop postcondition to return is:
2650  *
2651  * post = (t_init ; t_skip)(pre) + (t_body_star ; t_body ; t_inc ; t_exit) (pre)
2652  */
2655  /* To restrict the state at the beginning of the last iteration:
2656  should be part of t_body_star */
2657  //transformer post_enter = transformer_range(t_enter);
2658  //transformer post_continue = transformer_range(t_next);
2659  //transformer pre_iteration = transformer_convex_hull(post_enter, post_continue);
2660  /* Decompose the computation of p_body */
2661  transformer p_body_1 = transformer_apply(t_enter, transformer_apply(t_init, pre));
2662  transformer p_body_2 = transformer_apply(t_body_star, pre);
2663  //transformer p_body_3 = transformer_apply(pre_iteration, p_body_2);
2664  transformer p_body_4 = transformer_apply(t_body, p_body_2);
2665  transformer p_body_5 = transformer_apply(t_next, p_body_4);
2667  /* Decompose the computation of post */
2668  transformer post_1 = transformer_apply(t_skip, transformer_apply(t_init, pre));
2669  transformer post_2 = transformer_apply(t_body_star, pre);
2670  //transformer post_3 = transformer_apply(pre_iteration, post_2);
2671  transformer post_4 = transformer_apply(t_body, post_2);
2672  transformer post_5 = transformer_apply(t_inc, post_4);
2673  transformer post_6 = transformer_apply(t_exit, post_5);
2674 
2675  p_body = transformer_convex_hull(p_body_1, p_body_5);
2676  a_post = statement_to_postcondition(p_body, body);
2677 
2678  /* a_post should be used because it is more accurate than direct
2679  recomputation, but we chose for the time being to recompute post
2680  entirely */
2681  post = transformer_convex_hull(post_1, post_6);
2682 
2683  /* Get rid of now useless transformers */
2684 
2685  free_transformer(a_post);
2686 
2687  //free_transformer(post_enter);
2688  //free_transformer(post_continue);
2689  //free_transformer(pre_iteration);
2690 
2691  free_transformer(p_body_1);
2692  free_transformer(p_body_2);
2693  //free_transformer(p_body_3);
2694  free_transformer(p_body_4);
2695  free_transformer(p_body_5);
2696 
2697  free_transformer(post_1);
2698  free_transformer(post_2);
2699  //free_transformer(post_3);
2700  free_transformer(post_4);
2701  free_transformer(post_5);
2702  free_transformer(post_6);
2703 
2704  return post;
2705 }
transformer statement_to_postcondition(transformer, statement)
end of the non recursive section

References free_transformer(), statement_to_postcondition(), transformer_apply(), transformer_convex_hull(), and transformer_undefined.

Referenced by forloop_to_postcondition(), and repeatloop_to_postcondition().

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

◆ any_loop_to_transformer()

transformer any_loop_to_transformer ( transformer  t_init,
transformer  t_enter,
transformer  t_next,
statement  body,
list __attribute__((unused))  lel,
transformer  post_init 
)

Definition at line 316 of file loop.c.

322 {
323  return any_loop_to_k_transformer(t_init, t_enter, t_next, body, lel, post_init, 1);
324 }
transformer any_loop_to_k_transformer(transformer t_init, transformer t_enter, transformer t_next, statement body, list __attribute__((unused)) lel, transformer post_init, int k)
Processing of loops for transformers, preconditions and transformer lists.
Definition: loop.c:203

References any_loop_to_k_transformer().

Referenced by forloop_to_transformer(), new_loop_to_transformer(), new_whileloop_to_transformer(), and repeatloop_to_transformer().

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

◆ complete_any_loop_transformer()

transformer complete_any_loop_transformer ( transformer  t_init,
transformer __attribute__((unused))  t_enter,
transformer  t_skip,
transformer  t_body_star,
transformer  t_body,
transformer __attribute__((unused))  t_continue,
transformer  t_inc,
transformer  t_exit 
)

Reduce the transformer list associated to a loop to a unique transformer using a convex hull.

An empty list is converted into an empty transformer. The input list is freed.

Definition at line 1662 of file loop.c.

1670 {
1673  t_skip,
1674  t_body_star,
1675  t_body,
1676  t_inc,
1677  t_exit);
1678 
1680 
1681  gen_free_list(ltl);
1682 
1683  return ltf;
1684 }
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
list complete_any_loop_transformer_list(transformer t_init, transformer t_skip, transformer t_body_star, transformer t_body, transformer t_inc, transformer t_exit)
FI: used to be complete_any_loop_transformer() with a direct reduction by convex hull.
Definition: loop.c:1578
transformer transformer_list_to_transformer(list)
Reduce the transformer list ltl to one transformer using the convex hull operator.

References complete_any_loop_transformer_list(), gen_free_list(), transformer_list_to_transformer(), and transformer_undefined.

Referenced by complete_forloop_transformer(), and complete_forloop_transformer_list().

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

◆ complete_any_loop_transformer_list()

list complete_any_loop_transformer_list ( transformer  t_init,
transformer  t_skip,
transformer  t_body_star,
transformer  t_body,
transformer  t_inc,
transformer  t_exit 
)

FI: used to be complete_any_loop_transformer() with a direct reduction by convex hull.

t_loop = t_init ; t_skip + t_bodystar ; t_body ; t_inc; t_exit

Before entering t_body, t_enter or t_next have been applied which let us restrict the set of state modified by t_body. But this information should already been included in t_body_star.

Several cases must be tested:

  1. The loop is always entered and exited (usual case for scientific code: t_skip = transformer_empty).
  2. The loop is always entered and never exited (real-time code situation, t_exit = transformer_empty)
  3. The loop is never entered (in its current context, t_bodystar = transformer_empty because t_enter = transformer_empty).
  4. The loop may be entered and exited (usual case for general purpose computing, think of list handling).
  5. The loop may be entered but is then never exited (real-time code again).

These cases are checked with complete01.c, complete02.c,... complete05.c

loop skipped transformer

add loop entered transformer/condition: should already be in t_body_star

combine both cases in a transformer list

Parameters
t_init_init
t_skip_skip
t_body_star_body_star
t_body_body
t_inc_inc
t_exit_exit

Definition at line 1578 of file loop.c.

1584 {
1585  /* t_loop = t_init ; t_skip + t_bodystar ; t_body ; t_inc; t_exit
1586  *
1587  * Before entering t_body, t_enter or t_next have been applied which
1588  * let us restrict the set of state modified by t_body. But this
1589  * information should already been included in t_body_star.
1590  */
1591 
1592  /* Several cases must be tested:
1593  *
1594  * 1. The loop is always entered and exited (usual case for
1595  * scientific code: t_skip = transformer_empty).
1596  *
1597  * 2. The loop is always entered and never exited (real-time code
1598  * situation, t_exit = transformer_empty)
1599  *
1600  * 3. The loop is never entered (in its current context, t_bodystar
1601  * = transformer_empty because t_enter = transformer_empty).
1602  *
1603  * 4. The loop may be entered and exited (usual case for general
1604  * purpose computing, think of list handling).
1605  *
1606  * 5. The loop may be entered but is then never exited (real-time
1607  * code again).
1608  *
1609  * These cases are checked with complete01.c,
1610  * complete02.c,... complete05.c
1611  */
1612  list ltl = NIL;
1613  // transformer ct = transformer_undefined;
1614  /* loop skipped transformer */
1615  transformer lst = transformer_combine(copy_transformer(t_init), t_skip);
1616  /* add loop entered transformer/condition: should already be in t_body_star */
1617  //transformer post_enter = transformer_range(t_enter);
1618  //transformer post_continue = transformer_range(t_continue);
1619  //transformer pre_body = transformer_convex_hull(post_enter, post_continue);
1620  //transformer let = transformer_combine(copy_transformer(t_body_star), pre_body);
1621  transformer let = copy_transformer(t_body_star);
1622 
1623  ifdebug(8) {
1624  fprintf(stderr, "t_init:\n");
1625  print_transformer(t_init);
1626  fprintf(stderr, "t_skip:\n");
1627  print_transformer(t_skip);
1628  fprintf(stderr, "t_body_star:\n");
1629  print_transformer(t_body_star);
1630  fprintf(stderr, "t_body:inc\n");
1631  print_transformer(t_body);
1632  fprintf(stderr, "t_inc:\n");
1633  print_transformer(t_inc);
1634  fprintf(stderr, "t_exit:\n");
1635  print_transformer(t_exit);
1636  }
1637 
1638  let = transformer_combine(let, t_body);
1639  let = transformer_combine(let, t_inc);
1640  let = transformer_combine(let, t_exit);
1641  let = transformer_normalize(let, 2);
1642 
1643  /* combine both cases in a transformer list */
1644  //ct = transformer_convex_hull(lst, let);
1645  ltl = two_transformers_to_list(lst, let);
1646 
1647  //free_transformer(post_enter);
1648  //free_transformer(post_continue);
1649  //free_transformer(pre_body);
1650 
1651  ifdebug(8) {
1652  fprintf(stderr, "ltl:\n");
1653  print_transformers(ltl);
1654  }
1655 
1656  return ltl;
1657 }
list print_transformers(list tl)
Definition: io.c:62
transformer transformer_normalize(transformer t, int level)
Eliminate (some) rational or integer redundancy.
Definition: transformer.c:932
list two_transformers_to_list(transformer, transformer)
Transformer two transformers into a correct transformer list.

References copy_transformer(), fprintf(), ifdebug, NIL, print_transformer, print_transformers(), transformer_combine(), transformer_normalize(), and two_transformers_to_list().

Referenced by complete_any_loop_transformer(), and new_complete_whileloop_transformer_list().

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

◆ complete_forloop_transformer()

transformer complete_forloop_transformer ( transformer  t_body_star,
transformer  pre,
forloop  fl 
)

This function does not seem to exist because we only used statement effects in the past and because those are stored in the database.

An effort could be made to compute the precondition for t_exit, especially if the precondition to t_inc is available.

An effort could be made to compute the precondition for t_inc

Make sure you have the effective statement transformer: it is not stored for loops and this is key for nested loops.

Parameters
t_body_star_body_star
prere
fll

Definition at line 1686 of file loop.c.

1689 {
1691  statement body_s = forloop_body(fl);
1692  transformer t_body = load_statement_transformer(body_s);
1695  expression init_e = forloop_initialization(fl);
1696  /* This function does not seem to exist because we only used
1697  statement effects in the past and because those are stored in the
1698  database. */
1699  transformer t_init = safe_expression_to_transformer(init_e, pre);
1700  transformer post_init = transformer_apply(t_init, pre);
1701  expression cond_e = forloop_condition(fl);
1702  expression inc_e = forloop_increment(fl);
1703  transformer t_skip = condition_to_transformer(cond_e, post_init, false);
1704  transformer t_enter = condition_to_transformer(cond_e, post_init, true);
1705 /* An effort could be made to compute the precondition for t_exit,
1706  especially if the precondition to t_inc is available. */
1707  transformer t_continue = condition_to_transformer(cond_e, transformer_undefined, true);
1709  /* An effort could be made to compute the precondition for t_inc */
1711 
1712  /* Make sure you have the effective statement transformer: it is not
1713  stored for loops and this is key for nested loops. */
1714  pre_body = transformer_apply(t_body_star, pre);
1715  ct_body = complete_statement_transformer(t_body, pre_body, body_s);
1716 
1717  ct = complete_any_loop_transformer(t_init, t_enter, t_skip, t_body_star, ct_body, t_continue, t_inc, t_exit);
1718 
1719  free_transformer(ct_body);
1720  free_transformer(pre_body);
1721  free_transformer(t_init);
1722  free_transformer(post_init);
1723  free_transformer(t_skip);
1724  free_transformer(t_enter);
1725  free_transformer(t_continue);
1726  free_transformer(t_exit);
1727  free_transformer(t_inc);
1728 
1729  return ct;
1730 }
#define forloop_initialization(x)
Definition: ri.h:1366
#define forloop_increment(x)
Definition: ri.h:1370
#define forloop_condition(x)
Definition: ri.h:1368
#define forloop_body(x)
Definition: ri.h:1372
transformer complete_statement_transformer(transformer t, transformer pre, statement s)
Returns the effective transformer ct for a given statement s.
transformer safe_expression_to_transformer(expression exp, transformer pre)
Definition: expression.c:5307
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
transformer complete_any_loop_transformer(transformer t_init, transformer __attribute__((unused)) t_enter, transformer t_skip, transformer t_body_star, transformer t_body, transformer __attribute__((unused)) t_continue, transformer t_inc, transformer t_exit)
Reduce the transformer list associated to a loop to a unique transformer using a convex hull.
Definition: loop.c:1662

References complete_any_loop_transformer(), complete_statement_transformer(), condition_to_transformer(), forloop_body, forloop_condition, forloop_increment, forloop_initialization, free_transformer(), load_statement_transformer(), safe_expression_to_transformer(), transformer_apply(), and transformer_undefined.

Referenced by generic_complete_statement_transformer().

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

◆ complete_forloop_transformer_list()

list complete_forloop_transformer_list ( transformer  t_body_star,
transformer  pre,
forloop  fl 
)

This function does not seem to exist because we only used statement effects in the past and because those are stored in the database.

An effort could be made to compute the precondition for t_exit, especially if the precondition to t_inc is available.

An effort could be made to compute the precondition for t_inc

Make sure you have the effective statement transformer: it is not stored for loops and this is key for nested loops.

Parameters
t_body_star_body_star
prere
fll

Definition at line 1732 of file loop.c.

1735 {
1736  list tfl = list_undefined;
1737  statement body_s = forloop_body(fl);
1738  transformer t_body = load_statement_transformer(body_s);
1741  expression init_e = forloop_initialization(fl);
1742  /* This function does not seem to exist because we only used
1743  statement effects in the past and because those are stored in the
1744  database. */
1745  transformer t_init = safe_expression_to_transformer(init_e, pre);
1746  transformer post_init = transformer_apply(t_init, pre);
1747  expression cond_e = forloop_condition(fl);
1748  expression inc_e = forloop_increment(fl);
1749  transformer t_skip = condition_to_transformer(cond_e, post_init, false);
1750  transformer t_enter = condition_to_transformer(cond_e, post_init, true);
1751 /* An effort could be made to compute the precondition for t_exit,
1752  especially if the precondition to t_inc is available. */
1753  transformer t_continue = condition_to_transformer(cond_e, transformer_undefined, true);
1755  /* An effort could be made to compute the precondition for t_inc */
1757 
1758  pips_internal_error("function is not implemented");
1759 
1760  /* Make sure you have the effective statement transformer: it is not
1761  stored for loops and this is key for nested loops. */
1762  pre_body = transformer_apply(t_body_star, pre);
1763  ct_body = complete_statement_transformer(t_body, pre_body, body_s);
1764 
1765  (void)complete_any_loop_transformer(t_init, t_enter, t_skip, t_body_star, ct_body, t_continue, t_inc, t_exit);
1766 
1767  free_transformer(ct_body);
1768  free_transformer(pre_body);
1769  free_transformer(t_init);
1770  free_transformer(post_init);
1771  free_transformer(t_skip);
1772  free_transformer(t_enter);
1773  free_transformer(t_continue);
1774  free_transformer(t_exit);
1775  free_transformer(t_inc);
1776 
1777  return tfl;
1778 }
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
#define pips_internal_error
Definition: misc-local.h:149

References complete_any_loop_transformer(), complete_statement_transformer(), condition_to_transformer(), forloop_body, forloop_condition, forloop_increment, forloop_initialization, free_transformer(), list_undefined, load_statement_transformer(), pips_internal_error, safe_expression_to_transformer(), transformer_apply(), and transformer_undefined.

Referenced by instruction_to_transformer_list().

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

◆ complete_loop_transformer()

transformer complete_loop_transformer ( transformer  ltf,
transformer  pre,
loop  l 
)

The transformer computed and stored for a loop is useful to compute the loop body precondition, but it is not useful to analyze a higher level construct, which need the loop transformer with the exit condition.

Only Fortran DO loops are handled here. The need for nested WHILE loops has not been identified yet. The index variable is always initialized and then the loop is either entered and exited or not entered

loop body transformer

compute the loop body transformer

Since it is not stored, we need to go down recursively. A way to avoid this would be to always have sequences as loop bodies... Let's hope that perfectly nested loops are neither frequent nor deep!

compute the loop body precondition

You do not need a range to recurse. A full precondition with arguments is expected by complete_loop_transformer(). Maybe, but it's much easier to debug with ranges as they only carry the useful information. And the result is correct for Semantics-New/for03.c and 04.c

The final index incrementation is performed later by add_loop_index_exit_value()

btf = transformer_add_loop_index_incrementation(btf, l, pre);

compute the transformer when the loop is entered: T o T*

Semantics-New/for04.c: this leads to t_enter == empty_transformer because the same conditions on the initial values of cpi and cpj are preserved in both ltf, which is OK, and btf, which is not OK.

add the entry condition

but it seems to be in t already

t_enter = transformer_add_loop_index_initialization(t_enter, l);

It would make sense to apply the incrementation, but this is performed as a side effect by add_loop_index_exit_value(), which avoids unfeasability wrt the final loop bound.

add the exit condition, without any information pre to estimate the increment

FI: oops, pre is used in spite of previous comment

add initialization for the unconditional initialization of the loop index variable

It might be better not to compute useless transformer, but it's more readable that way. Since pre is information free, only loops with constant lower and upper bound and constant increment can benefit from this.

pre cannot be used as such. the loop initialization must be applied first: the previous comment seems to be correct.

Parameters
ltftf
prere

Definition at line 1927 of file loop.c.

1928 {
1932  /* loop body transformer */
1934  range r = loop_range(l);
1935  statement s = loop_body(l);
1936 
1937  pips_debug(8,"begin with loop precondition\n");
1938  ifdebug(8) {
1939  (void) print_transformer(pre);
1940  pips_debug(8,"and loop transformer:\n");
1941  (void) print_transformer(ltf);
1942  }
1943 
1944  /* compute the loop body transformer */
1945  if(statement_loop_p(s)) {
1946  /* Since it is not stored, we need to go down recursively. A way to
1947  avoid this would be to always have sequences as loop
1948  bodies... Let's hope that perfectly nested loops are neither
1949  frequent nor deep! */
1951  /* compute the loop body precondition */
1952  transformer raw_ipre = transformer_apply(ltf, pre);
1953  transformer ipre = transformer_range(raw_ipre);
1954  ipre = transformer_normalize(ipre, 2);
1955  /* You do not need a range to recurse. A full precondition with
1956  arguments is expected by complete_loop_transformer(). Maybe,
1957  but it's much easier to debug with ranges as they only carry
1958  the useful information. And the result is correct for
1959  Semantics-New/for03.c and 04.c */
1961  btf = complete_loop_transformer(st, ipre, il);
1962  btf = transformer_normalize(btf, 2);
1963  free_transformer(ipre);
1964  free_transformer(raw_ipre);
1965  }
1966  else {
1968  }
1969  /* The final index incrementation is performed later by add_loop_index_exit_value() */
1970  /* btf = transformer_add_loop_index_incrementation(btf, l, pre); */
1971 
1972  /* compute the transformer when the loop is entered: T o T* */
1973  /* Semantics-New/for04.c: this leads to t_enter ==
1974  empty_transformer because the same conditions on the initial
1975  values of cpi and cpj are preserved in both ltf, which is OK, and
1976  btf, which is not OK. */
1977  t_enter = transformer_combine(transformer_dup(ltf), btf);
1978 
1979  ifdebug(8) {
1980  pips_debug(8, "entered loop transformer t_enter=\n");
1982  }
1983 
1984  /* add the entry condition */
1985  /* but it seems to be in t already */
1986  /* t_enter = transformer_add_loop_index_initialization(t_enter, l); */
1987 
1988  /* It would make sense to apply the incrementation, but this is
1989  performed as a side effect by add_loop_index_exit_value(), which
1990  avoids unfeasability wrt the final loop bound. */
1991  /*
1992  transformer t_inc = transformer_identity();
1993  t_inc = transformer_add_loop_index_incrementation(t_inc, l, pre);
1994  t_enter = transformer_combine(t_enter, t_inc);
1995  */
1996 
1997  /* add the exit condition, without any information pre to estimate the
1998  increment */
1999  transformer tmp = t_enter;
2000  /* FI: oops, pre is used in spite of previous comment */
2001  t_enter = add_loop_index_exit_value(t_enter, l, pre);
2002  transformer_free(tmp);
2003 
2004  ifdebug(8) {
2005  pips_debug(8, "entered and exited loop transformer t_enter=\n");
2007  }
2008 
2009  /* add initialization for the unconditional initialization of the loop
2010  index variable */
2011  tmp = transformer_undefined_p(pre)?
2013  transformer_dup(pre);
2014  t_skip = add_loop_index_initialization(tmp, l, pre);
2015  //transformer ipre = transformer_apply(t_skip, pre);
2016  //transformer ripre = transformer_range(ipre);
2017  transformer_free(tmp);
2018  t_skip = add_loop_skip_condition(t_skip, l, pre);
2019  t_skip = transformer_normalize(t_skip, 2);
2020 
2021  ifdebug(8) {
2022  pips_debug(8, "skipped loop transformer t_skip=\n");
2024  }
2025 
2026  /* It might be better not to compute useless transformer, but it's more
2027  readable that way. Since pre is information free, only loops with
2028  constant lower and upper bound and constant increment can benefit
2029  from this. */
2030  /* pre cannot be used as such. the loop initialization must be
2031  applied first: the previous comment seems to be correct. */
2032  // if(empty_range_wrt_precondition_p(r, ripre)) {
2033  if(empty_range_wrt_precondition_p(r, pre)) {
2034  tf = t_skip;
2035  free_transformer(t_enter);
2036  }
2037  // else if(non_empty_range_wrt_precondition_p(r, ripre)) {
2038  else if(non_empty_range_wrt_precondition_p(r, pre)) {
2039  tf = t_enter;
2040  free_transformer(t_skip);
2041  }
2042  else {
2043  tf = transformer_convex_hull(t_enter, t_skip);
2044  free_transformer(t_enter);
2045  free_transformer(t_skip);
2046  }
2047  //free_transformer(ipre);
2048  //free_transformer(ripre);
2049 
2050  tf = transformer_normalize(tf, 2);
2051 
2052  ifdebug(8) {
2053  pips_debug(8, "full refined loop transformer tf=\n");
2055  pips_debug(8, "end\n");
2056  }
2057 
2058  return tf;
2059 }
transformer transformer_identity()
Allocate an identity transformer.
Definition: basic.c:110
bool statement_loop_p(statement)
Definition: statement.c:349
transformer fprint_transformer(FILE *fd, transformer tf, get_variable_name_t value_name)
Definition: io.c:69
#define transformer_undefined_p(x)
Definition: ri.h:2848
#define instruction_loop(x)
Definition: ri.h:1520
#define statement_instruction(x)
Definition: ri.h:2458
transformer complete_loop_transformer(transformer ltf, transformer pre, loop l)
The transformer computed and stored for a loop is useful to compute the loop body precondition,...
Definition: loop.c:1927
static transformer add_loop_index_initialization(transformer tf, loop l, transformer pre)
Always returns newly allocated memory.
Definition: loop.c:825
transformer add_loop_index_exit_value(transformer post, loop l, transformer pre)
The exit value is known if.
Definition: loop.c:878
transformer add_loop_skip_condition(transformer tf, loop l, transformer pre)
tf and pre are a unique data structure when preconditions are computed
Definition: loop.c:495
bool non_empty_range_wrt_precondition_p(range, transformer)
Definition: utils.c:121
bool empty_range_wrt_precondition_p(range, transformer)
A range cannot be tested exactly wrt a precondition You can try to prove that it is empty or you can ...
Definition: utils.c:112
char *(* get_variable_name_t)(Variable)
Definition: vecteur-local.h:62

References add_loop_index_exit_value(), add_loop_index_initialization(), add_loop_skip_condition(), empty_range_wrt_precondition_p(), external_value_name(), fprint_transformer(), free_transformer(), ifdebug, instruction_loop, load_statement_transformer(), loop_body, loop_range, non_empty_range_wrt_precondition_p(), pips_debug, print_transformer, statement_instruction, statement_loop_p(), transformer_apply(), transformer_combine(), transformer_convex_hull(), transformer_dup(), transformer_free(), transformer_identity(), transformer_normalize(), transformer_range(), transformer_undefined, and transformer_undefined_p.

Referenced by complete_loop_transformer_list(), generic_complete_statement_transformer(), and old_complete_whileloop_transformer().

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

◆ complete_loop_transformer_list()

list complete_loop_transformer_list ( transformer  ltf,
transformer  pre,
loop  l 
)

loop body transformer

compute the loop body transformer

Since it is not stored, we need to go down recursively. A way to avoid this would be to always have sequences as loop bodies... Let's hope that perfectly nested loops are neither frequent nor deep!

compute the loop body precondition

You do not need a range to recurse. A full precondition with arguments is expected by complete_loop_transformer().

The final index incrementation is performed later by add_loop_index_exit_value()

btf = transformer_add_loop_index_incrementation(btf, l, pre);

compute the transformer when the loop is entered: T o T*

add the entry condition

but it seems to be in t already

t_enter = transformer_add_loop_index_initialization(t_enter, l);

It would make sense to apply the incrementation, but this is performed as a side effect by add_loop_index_exit_value(), which avoids unfeasability wrt the final loop bound.

add the exit condition, without any information pre to estimate the increment

FI: oops, pre is used in spite of previous comment

add initialization for the unconditional initialization of the loop index variable

It might be better not to compute useless transformer, but it's more readable that way. Since pre is information free, only loops with constant lower and upper bound and constant increment can benefit from this.

Parameters
ltftf
prere

Definition at line 2061 of file loop.c.

2062 {
2063  list tfl = list_undefined;
2067  /* loop body transformer */
2069  range r = loop_range(l);
2070  statement s = loop_body(l);
2071 
2072  pips_internal_error("Function not implemented.");
2073 
2074  pips_debug(8,"begin with loop precondition\n");
2075  ifdebug(8) {
2076  (void) print_transformer(pre);
2077  pips_debug(8,"and loop transformer:\n");
2078  (void) print_transformer(ltf);
2079  }
2080 
2081  /* compute the loop body transformer */
2082  if(statement_loop_p(s)) {
2083  /* Since it is not stored, we need to go down recursively. A way to
2084  avoid this would be to always have sequences as loop
2085  bodies... Let's hope that perfectly nested loops are neither
2086  frequent nor deep! */
2088  /* compute the loop body precondition */
2089  transformer raw_ipre = transformer_apply(ltf, pre);
2090  //transformer ipre = transformer_range(raw_ipre);
2091  //ipre = transformer_normalize(ipre, 2);
2092  /* You do not need a range to recurse. A full precondition with
2093  arguments is expected by complete_loop_transformer(). */
2094  btf = complete_loop_transformer(load_statement_transformer(s), raw_ipre, il);
2095  btf = transformer_normalize(btf, 2);
2096  //free_transformer(ipre);
2097  free_transformer(raw_ipre);
2098  }
2099  else {
2101  }
2102  /* The final index incrementation is performed later by add_loop_index_exit_value() */
2103  /* btf = transformer_add_loop_index_incrementation(btf, l, pre); */
2104 
2105  /* compute the transformer when the loop is entered: T o T* */
2106  t_enter = transformer_combine(transformer_dup(ltf), btf);
2107 
2108  ifdebug(8) {
2109  pips_debug(8, "entered loop transformer t_enter=\n");
2111  }
2112 
2113  /* add the entry condition */
2114  /* but it seems to be in t already */
2115  /* t_enter = transformer_add_loop_index_initialization(t_enter, l); */
2116 
2117  /* It would make sense to apply the incrementation, but this is
2118  performed as a side effect by add_loop_index_exit_value(), which
2119  avoids unfeasability wrt the final loop bound. */
2120  /*
2121  transformer t_inc = transformer_identity();
2122  t_inc = transformer_add_loop_index_incrementation(t_inc, l, pre);
2123  t_enter = transformer_combine(t_enter, t_inc);
2124  */
2125 
2126  /* add the exit condition, without any information pre to estimate the
2127  increment */
2128  transformer tmp = t_enter;
2129  /* FI: oops, pre is used in spite of previous comment */
2130  t_enter = add_loop_index_exit_value(t_enter, l, pre);
2131  transformer_free(tmp);
2132 
2133  ifdebug(8) {
2134  pips_debug(8, "entered and exited loop transformer t_enter=\n");
2136  }
2137 
2138  /* add initialization for the unconditional initialization of the loop
2139  index variable */
2140  tmp = transformer_undefined_p(pre)?
2142  transformer_dup(pre);
2143  t_skip = add_loop_index_initialization(tmp, l, pre);
2144  transformer_free(tmp);
2145  t_skip = add_loop_skip_condition(t_skip, l, pre);
2146  t_skip = transformer_normalize(t_skip, 2);
2147 
2148  ifdebug(8) {
2149  pips_debug(8, "skipped loop transformer t_skip=\n");
2151  }
2152 
2153  /* It might be better not to compute useless transformer, but it's more
2154  readable that way. Since pre is information free, only loops with
2155  constant lower and upper bound and constant increment can benefit
2156  from this. */
2157  if(empty_range_wrt_precondition_p(r, pre)) {
2158  tf = t_skip;
2159  free_transformer(t_enter);
2160  }
2161  else if(non_empty_range_wrt_precondition_p(r, pre)) {
2162  tf = t_enter;
2163  free_transformer(t_skip);
2164  }
2165  else {
2166  tf = transformer_convex_hull(t_enter, t_skip);
2167  free_transformer(t_enter);
2168  free_transformer(t_skip);
2169  }
2170 
2171  tf = transformer_normalize(tf, 2);
2172 
2173  ifdebug(8) {
2174  pips_debug(8, "full refined loop transformer tf=\n");
2176  pips_debug(8, "end\n");
2177  }
2178 
2179  return tfl;
2180 }

References add_loop_index_exit_value(), add_loop_index_initialization(), add_loop_skip_condition(), complete_loop_transformer(), empty_range_wrt_precondition_p(), external_value_name(), fprint_transformer(), free_transformer(), ifdebug, instruction_loop, list_undefined, load_statement_transformer(), loop_body, loop_range, non_empty_range_wrt_precondition_p(), pips_debug, pips_internal_error, print_transformer, statement_instruction, statement_loop_p(), transformer_apply(), transformer_combine(), transformer_convex_hull(), transformer_dup(), transformer_free(), transformer_identity(), transformer_normalize(), transformer_undefined, 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:

◆ complete_repeatloop_transformer()

transformer complete_repeatloop_transformer ( transformer  t_body_star,
transformer  pre,
whileloop  wl 
)
Parameters
t_body_star_body_star
prere
wll

Definition at line 1910 of file loop.c.

1913 {
1914  list tl = complete_repeatloop_transformer_list(t_body_star, pre, wl);
1916  return ct;
1917 }
list complete_repeatloop_transformer_list(transformer t_body_star, transformer __attribute__((unused)) pre, whileloop wl)
Definition: loop.c:1845

References complete_repeatloop_transformer_list(), and transformer_list_to_transformer().

Referenced by complete_whileloop_transformer(), and generic_complete_statement_transformer().

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

◆ complete_repeatloop_transformer_list()

list complete_repeatloop_transformer_list ( transformer  t_body_star,
transformer __attribute__((unused))  pre,
whileloop  wl 
)

An effort could be made to compute the precondition for t_exit

Make sure you have the effective statement transformer: it is not stored for loops and this is key for nested loops.

The generic equation is not adpated to repeat loops, which may execute once or at least twice instead of zero or twice

The equation is: t_loop = (t_body ; t_exit) + (t_body ; t_continue ; t_body_star ; t_body ; t_exit)

where we assume that t_body_star includes the continuation condition.

Definition at line 1845 of file loop.c.

1848 {
1849  list tfl = NIL;
1850  statement body_s = whileloop_body(wl);
1851  transformer pt_body = load_statement_transformer(body_s);
1854  transformer t_init = transformer_identity();
1855  expression cond_e = whileloop_condition(wl);
1856  transformer t_continue = condition_to_transformer(cond_e, transformer_undefined, true);
1857  transformer t_enter = transformer_identity();
1858  transformer t_skip = transformer_empty();
1860  /* An effort could be made to compute the precondition for t_exit */
1863  transformer t_loop_2 = transformer_undefined;;
1864 
1865  /* Make sure you have the effective statement transformer: it is not
1866  stored for loops and this is key for nested loops. */
1867  pre_body = transformer_apply(t_body_star, pre);
1868  t_body = complete_statement_transformer(pt_body, pre_body, body_s);
1869 
1870  t_loop_1 = copy_transformer(t_body);
1871  t_loop_2 = copy_transformer(t_body);
1872 
1873  /* The generic equation is not adpated to repeat loops, which may
1874  * execute once or at least twice instead of zero or twice
1875  *
1876  * The equation is:
1877  *.
1878  * t_loop = (t_body ; t_exit) +
1879  * (t_body ; t_continue ; t_body_star ; t_body ; t_exit)
1880  *
1881  * where we assume that t_body_star includes the continuation condition.
1882  */
1883 
1884  // ct = complete_any_loop_transformer(t_init, t_enter, t_skip, t_body_star, t_body, t_continue, t_inc, t_exit);
1885 
1886  t_loop_1 = transformer_combine(t_loop_1, t_exit);
1887 
1888  t_loop_2 = transformer_combine(t_loop_2, t_continue);
1889  t_loop_2 = transformer_combine(t_loop_2, t_body_star);
1890  t_loop_2 = transformer_combine(t_loop_2, t_body);
1891  t_loop_2 = transformer_combine(t_loop_2, t_exit);
1892 
1893  //ct = transformer_convex_hull(t_loop_1, t_loop_2);
1894  tfl = two_transformers_to_list(t_loop_1, t_loop_2);
1895 
1896  free_transformer(t_body);
1897  free_transformer(pre_body);
1898  free_transformer(t_init);
1899  free_transformer(t_enter);
1900  free_transformer(t_skip);
1901  free_transformer(t_exit);
1902  free_transformer(t_inc);
1903 
1904  //free_transformer(t_loop_1);
1905  //free_transformer(t_loop_2);
1906 
1907  return tfl;
1908 }
#define whileloop_body(x)
Definition: ri.h:3162
#define whileloop_condition(x)
Definition: ri.h:3160

References complete_statement_transformer(), condition_to_transformer(), copy_transformer(), free_transformer(), load_statement_transformer(), NIL, transformer_apply(), transformer_combine(), transformer_empty(), transformer_identity(), transformer_undefined, two_transformers_to_list(), whileloop_body, and whileloop_condition.

Referenced by complete_repeatloop_transformer(), and complete_whileloop_transformer_list().

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

◆ complete_whileloop_transformer()

transformer complete_whileloop_transformer ( transformer  ltf,
transformer  pre,
whileloop  wl 
)

FI: I'm not sure this function is useful.

Parameters
ltftf
prere
wll

Definition at line 2183 of file loop.c.

2186 {
2189 
2190  if(evaluation_before_p(lt))
2191  t = new_complete_whileloop_transformer(ltf, pre, wl, false);
2192  else
2193  t = complete_repeatloop_transformer(ltf, pre, wl);
2194 
2195  return t;
2196 }
#define whileloop_evaluation(x)
Definition: ri.h:3166
#define evaluation_before_p(x)
Definition: ri.h:1159
transformer new_complete_whileloop_transformer(transformer t_body_star, transformer pre, whileloop wl, bool entered_p)
entered_p is used to for the execution of at least one iteration
Definition: loop.c:1833
transformer complete_repeatloop_transformer(transformer t_body_star, transformer pre, whileloop wl)
Definition: loop.c:1910

References complete_repeatloop_transformer(), evaluation_before_p, new_complete_whileloop_transformer(), transformer_undefined, and whileloop_evaluation.

Referenced by old_complete_whileloop_transformer().

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

◆ complete_whileloop_transformer_list()

list complete_whileloop_transformer_list ( transformer  ltf,
transformer  pre,
whileloop  wl 
)
Parameters
ltftf
prere
wll

Definition at line 2198 of file loop.c.

2201 {
2202  list tfl = NIL;
2204 
2205  if(evaluation_before_p(lt))
2206  tfl = new_complete_whileloop_transformer_list(ltf, pre, wl, false);
2207  else
2208  tfl = complete_repeatloop_transformer_list(ltf, pre, wl);
2209 
2210  return tfl;
2211 }
list new_complete_whileloop_transformer_list(transformer t_body_star, transformer pre, whileloop wl, bool entered_p __attribute__((__unused__)))
entered_p is used to for the execution of at least one iteration
Definition: loop.c:1781

References complete_repeatloop_transformer_list(), evaluation_before_p, new_complete_whileloop_transformer_list(), NIL, and whileloop_evaluation.

Referenced by instruction_to_transformer_list().

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

◆ forloop_to_postcondition()

transformer forloop_to_postcondition ( transformer  pre,
forloop  fl,
transformer  t_body_star 
)

This function does not seem to exist because we only used statement effects in the past and because those are stored in the database.

An effort could be made to compute the precondition for t_exit, especially if the precondition to t_inc is available.

An effort could be made to compute the precondition for t_inc

Clean up memory

Parameters
prere
fll
t_body_star_body_star

Definition at line 2707 of file loop.c.

2708 {
2710 
2711  statement body_s = forloop_body(fl);
2712  transformer t_body = load_statement_transformer(body_s);
2713 
2714  expression init_e = forloop_initialization(fl);
2715  /* This function does not seem to exist because we only used
2716  statement effects in the past and because those are stored in the
2717  database. */
2718  transformer t_init = safe_expression_to_transformer(init_e, pre);
2719  transformer post_init = transformer_apply(t_init, pre);
2720 
2721  expression cond_e = forloop_condition(fl);
2722  transformer t_skip = condition_to_transformer(cond_e, post_init, false);
2723  transformer t_enter = condition_to_transformer(cond_e, post_init, true);
2724 /* An effort could be made to compute the precondition for t_exit,
2725  especially if the precondition to t_inc is available. */
2726  transformer t_continue = condition_to_transformer(cond_e, transformer_undefined, true);
2728 
2729  expression inc_e = forloop_increment(fl);
2730  /* An effort could be made to compute the precondition for t_inc */
2732 
2733  transformer t_next = transformer_combine(transformer_dup(t_inc), t_continue);
2734 
2735  post = any_loop_to_postcondition(body_s,
2736  t_init,
2737  t_enter,
2738  t_skip,
2739  t_body_star,
2740  t_body,
2741  t_next,
2742  t_inc,
2743  t_exit,
2744  pre);
2745 
2746  /* Clean up memory */
2747 
2748  free_transformer(t_init);
2749  free_transformer(post_init);
2750  free_transformer(t_skip);
2751  free_transformer(t_enter);
2752  free_transformer(t_continue);
2753  free_transformer(t_exit);
2754  free_transformer(t_inc);
2755  free_transformer(t_next);
2756 
2757  return post;
2758 }
transformer any_loop_to_postcondition(statement body, transformer t_init, transformer t_enter, transformer t_skip, transformer t_body_star, transformer t_body, transformer t_next, transformer t_inc, transformer t_exit, transformer pre)
Definition: loop.c:2634

References any_loop_to_postcondition(), condition_to_transformer(), forloop_body, forloop_condition, forloop_increment, forloop_initialization, free_transformer(), load_statement_transformer(), safe_expression_to_transformer(), transformer_apply(), transformer_combine(), transformer_dup(), and transformer_undefined.

Referenced by instruction_to_postcondition().

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

◆ forloop_to_transformer()

transformer forloop_to_transformer ( forloop  fl,
transformer  pre,
list  flel 
)

effects of forloop fl

t_body_star = t_init ; t_enter ;(t_body ; t_next)*

Deal with initialization expression

Deal with condition expression

An effort could be made to compute the precondition for t_continue, especially if the precondition to t_inc is available.

Deal with increment expression

An effort could be made to compute the precondition for t_inc

Let's clean up the memory

Parameters
fll
prere
flellel

Definition at line 326 of file loop.c.

329 {
330  /* t_body_star = t_init ; t_enter ;(t_body ; t_next)* */
331  transformer t_body_star = transformer_undefined;
332  statement body_s = forloop_body(fl);
333 
334  /* Deal with initialization expression */
335  expression init_e = forloop_initialization(fl);
336  transformer t_init = safe_expression_to_transformer(init_e, pre);
337  transformer post_init = transformer_apply(t_init, pre);
338 
339  /* Deal with condition expression */
340  expression cond_e = forloop_condition(fl);
341  transformer t_enter = condition_to_transformer(cond_e, post_init, true);
342  /* An effort could be made to compute the precondition for t_continue,
343  especially if the precondition to t_inc is available. */
344  transformer p_continue = transformer_identity();
345  transformer t_continue = condition_to_transformer(cond_e, p_continue, true);
346 
347  /* Deal with increment expression */
348  expression inc_e = forloop_increment(fl);
349  /* An effort could be made to compute the precondition for t_inc */
351  transformer t_next = transformer_combine(t_inc, t_continue);
352 
353  t_body_star = any_loop_to_transformer(t_init, t_enter, t_next, body_s, flel, post_init);
354 
355  /* Let's clean up the memory */
356 
357  free_transformer(p_continue);
358 
359  free_transformer(t_init);
360  free_transformer(post_init);
361 
362  free_transformer(t_enter);
363  free_transformer(t_continue);
364 
365  // free_transformer(t_inc); it is absorbed by t_next
366  free_transformer(t_next);
367 
368  return t_body_star;
369 }
transformer any_loop_to_transformer(transformer t_init, transformer t_enter, transformer t_next, statement body, list __attribute__((unused)) lel, transformer post_init)
Definition: loop.c:316

References any_loop_to_transformer(), condition_to_transformer(), forloop_body, forloop_condition, forloop_increment, forloop_initialization, free_transformer(), safe_expression_to_transformer(), transformer_apply(), transformer_combine(), transformer_identity(), and transformer_undefined.

Referenced by instruction_to_transformer().

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

◆ forloop_to_transformer_list()

list forloop_to_transformer_list ( forloop l   __attribute__(unused),
transformer pre   __attribute__(unused),
list e   __attribute__(unused) 
)

Definition at line 371 of file loop.c.

374 {
375  list tfl = NIL;
376  pips_internal_error("Not implemented yet.");
377  return tfl;
378 }

References NIL, and pips_internal_error.

◆ loop_body_transformer_add_entry_and_iteration_information()

static transformer loop_body_transformer_add_entry_and_iteration_information ( transformer  tfb,
transformer  pre 
)
static

FI: I do not have one test case to show that this function is of some use.

add information about the old value of tfb as convex hull of the entry precondition and of tfb's own image. For instance, if variable I is equal to 0 on entry and set ot either 0 or 1, the loop is always started with in [0, 1]

Definition at line 2412 of file loop.c.

2413 {
2414  /* add information about the old value of tfb as convex hull of the
2415  entry precondition and of tfb's own image. For instance, if variable
2416  I is equal to 0 on entry and set ot either 0 or 1, the loop is always
2417  started with in [0, 1] */
2418  transformer initial = transformer_range(pre);
2419  transformer next = transformer_range(tfb);
2420  transformer pre_body = transformer_convex_hull(initial, next);
2421 
2422 
2423  ifdebug(8) {
2424  pips_debug(5, "Begin with body transformer:\n");
2425  print_transformer(tfb);
2426  pips_debug(5, "initial precondition:\n");
2427  print_transformer(initial);
2428  pips_debug(5, "next precondition:\n");
2429  print_transformer(next);
2430  pips_debug(5, "body precondition:\n");
2431  print_transformer(pre_body);
2432  }
2433 
2434 
2435  tfb = transformer_domain_intersection(tfb, pre_body);
2436 
2437  free_transformer(initial);
2438  free_transformer(next);
2439  free_transformer(pre_body);
2440 
2441  ifdebug(8) {
2442  pips_debug(5, "End with new body transformer:\n");
2443  print_transformer(tfb);
2444  }
2445 
2446  return tfb;
2447 }
transformer transformer_domain_intersection(transformer tf, transformer pre)
Restrict the domain of the relation tf with pre.
Definition: transformer.c:661

References free_transformer(), ifdebug, pips_debug, print_transformer, transformer_convex_hull(), transformer_domain_intersection(), and transformer_range().

Referenced by standard_whileloop_to_transformer().

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

◆ loop_bound_evaluation_to_transformer()

transformer loop_bound_evaluation_to_transformer ( loop  l,
transformer  pre 
)

Side effects in loop bounds and increment are taken into account.

The conditions on the loop index are given by the range of this transformer.

Parameters
prere

Definition at line 1203 of file loop.c.

1204 {
1206  entity i = loop_index(l);
1207 
1208  //pips_assert("No temporary variables are allocated",
1209  // number_of_temporary_values()==0);
1210 
1211  if(entity_has_values_p(i)) {
1212  expression lbe = range_lower(loop_range(l));
1215  transformer lbt = any_expression_to_transformer(lbv, lbe, pre, true);
1216 
1217  transformer preub = transformer_safe_apply(iit, pre);
1218  expression ube = range_upper(loop_range(l));
1220  transformer ubt = any_expression_to_transformer(ubv, ube, preub, true);
1221 
1222  transformer prei = transformer_safe_apply(ubt, preub);
1225  transformer it = any_expression_to_transformer(iv, ie, prei, true);
1226  transformer pre_inc = transformer_safe_intersection(prei, it);
1227  entity ni = entity_to_new_value(i);
1228  int inc_lb = 0;
1229  int inc_ub = 0;
1230  expression eiv = entity_to_expression(iv);
1231 
1232  expression_and_precondition_to_integer_interval(eiv, pre_inc, &inc_lb, &inc_ub);
1233  free_expression(eiv);
1234 
1235  if(inc_lb>0 || inc_ub<0) {
1236  Pvecteur lb_ineq = vect_new((Variable) ni, VALUE_MONE);
1237  Pvecteur ub_ineq = vect_new((Variable) ni, VALUE_ONE);
1238 
1239  vect_add_elem(&lb_ineq, (Variable) lbv, VALUE_ONE);
1240  vect_add_elem(&ub_ineq, (Variable) ubv, VALUE_MONE);
1241 
1242  if(inc_ub<0) {
1243  lb_ineq = vect_multiply(lb_ineq, VALUE_MONE);
1244  ub_ineq = vect_multiply(ub_ineq, VALUE_MONE);
1245  }
1246  r = transformer_safe_apply(it, prei);
1249  r = transformer_inequality_add(r, lb_ineq);
1250  r = transformer_inequality_add(r, ub_ineq);
1252  }
1254  }
1255  return r;
1256 }
void free_expression(expression p)
Definition: ri.c:853
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
Pvecteur vect_multiply(Pvecteur v, Value x)
Pvecteur vect_multiply(Pvecteur v, Value x): multiplication du vecteur v par le scalaire x,...
Definition: scalaires.c:123
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
transformer loop_initialization_to_transformer(loop l, transformer pre)
Note: It used to be implemented by computing the effect list of the lower bound expression and and ne...
Definition: loop.c:1266
transformer transformer_safe_apply(transformer tf, transformer pre)
Definition: transformer.c:1627
transformer transformer_safe_intersection(transformer t1, transformer t2)
Allocate a new transformer.
Definition: transformer.c:639
transformer transformer_safe_image_intersection(transformer t1, transformer t2)
Allocate a new transformer.
Definition: transformer.c:647

References any_expression_to_transformer(), entity_has_values_p(), entity_to_expression(), entity_to_new_value(), entity_type, expression_and_precondition_to_integer_interval(), free_expression(), loop_index, loop_initialization_to_transformer(), loop_range, make_local_temporary_value_entity(), range_increment, range_lower, range_upper, reset_temporary_value_counter(), transformer_inequality_add(), transformer_safe_apply(), transformer_safe_image_intersection(), transformer_safe_intersection(), transformer_temporary_value_projection(), transformer_undefined, VALUE_MONE, VALUE_ONE, vect_add_elem(), vect_multiply(), and vect_new().

Referenced by add_good_loop_conditions().

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

◆ loop_initialization_to_transformer()

transformer loop_initialization_to_transformer ( loop  l,
transformer  pre 
)

Note: It used to be implemented by computing the effect list of the lower bound expression and and new allocated effect for the loop index definition.

It turns out to be very heavy, because cells must be of kind preference to be usable by several functions because macro effect_reference() expects so without testing it.

However, it is also difficult to add a variable to the transformer t_init because of aliasing. So let's stick to the initial implementation.

over-approximation of effects

free_effects() is not enough, because it is a persistant reference

Parameters
prere

Definition at line 1266 of file loop.c.

1267 {
1273  list l_init_e = CONS(EFFECT, init_e, NIL);
1274  //list l_expr_e = expression_to_proper_effects(range_lower(loop_range(l)));
1275  expression lbe = range_lower(loop_range(l));
1277  list el = list_undefined;
1278 
1279  transformer r_pre = transformer_safe_range(pre);
1281 
1282  ifdebug(9) {
1283  print_effects(l_init_e);
1284  print_effects(l_expr_e);
1285  }
1286 
1287  el = gen_nconc(l_init_e, l_expr_e);
1288 
1289  ifdebug(9) {
1290  print_effects(el);
1291  }
1292 
1293  t_init =
1295  range_lower(loop_range(l)),
1296  el, /* over-approximation of effects */
1297  r_pre);
1298 
1299  ifdebug(9) {
1300  print_effects(el);
1301  }
1302 
1303  gen_free_list(el);
1304  /* free_effects() is not enough, because it is a persistant reference */
1306  free_effect(init_e);
1307  free_transformer(r_pre);
1308 
1309  return t_init;
1310 }
void free_effect(effect p)
Definition: effects.c:451
cell make_cell(enum cell_utype tag, void *val)
Definition: effects.c:290
approximation make_approximation_exact(void)
Definition: effects.c:185
effect make_effect(cell a1, action a2, approximation a3, descriptor a4)
Definition: effects.c:484
descriptor make_descriptor_none(void)
Definition: effects.c:442
void free_reference(reference p)
Definition: ri.c:2050
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
preference make_preference(reference a1)
Definition: ri.c:1862
action make_action_write_memory(void)
To ease the extension of action with action_kind.
Definition: effects.c:1011
#define cell_preference(x)
Definition: effects.h:472
@ is_cell_preference
Definition: effects.h:446
#define EFFECT(x)
EFFECT.
Definition: effects.h:608
#define effect_cell(x)
Definition: effects.h:640
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#define print_effects(e)
Definition: print.c:334
#define preference_reference(x)
Definition: ri.h:2102
transformer transformer_safe_range(transformer tf)
Definition: transformer.c:743

References any_scalar_assign_to_transformer(), cell_preference, CONS, EFFECT, effect_cell, expression_to_proper_constant_path_effects(), free_effect(), free_reference(), free_transformer(), gen_free_list(), gen_nconc(), ifdebug, is_cell_preference, list_undefined, loop_index, loop_range, make_action_write_memory(), make_approximation_exact(), make_cell(), make_descriptor_none(), make_effect(), make_preference(), make_reference(), NIL, preference_reference, print_effects, range_lower, transformer_safe_range(), and transformer_undefined.

Referenced by loop_bound_evaluation_to_transformer(), loop_to_postcondition(), loop_to_total_precondition(), and loop_to_transformer().

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

◆ loop_to_continue_transformer()

transformer loop_to_continue_transformer ( loop  l,
transformer  pre 
)

FI: the function transformer_add_loop_index_incrementation should be rewritten to exploit preconditions better.

Parameters
prere

Definition at line 1501 of file loop.c.

1502 {
1504  /* FI: the function transformer_add_loop_index_incrementation should
1505  be rewritten to exploit preconditions better. */
1508  t = transformer_combine(t, et);
1509  free_transformer(et);
1510  return t;
1511 }
transformer loop_to_enter_transformer(loop l, transformer pre)
Transformer expressiong the conditions between the index and the loop bounds according to the sign of...
Definition: loop.c:1442
transformer transformer_add_loop_index_incrementation(transformer tf, loop l, transformer pre)
Definition: loop.c:1136

References free_transformer(), loop_to_enter_transformer(), transformer_add_loop_index_incrementation(), transformer_combine(), and transformer_identity().

Referenced by new_loop_to_transformer().

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

◆ loop_to_enter_transformer()

transformer loop_to_enter_transformer ( loop  l,
transformer  pre 
)

Transformer expressiong the conditions between the index and the loop bounds according to the sign of the increment.

A zero increment is not legal because the Fortran standard imposes a division by the increment.

Only the loop bopy statement number is available...

Assumption: no side effect in loop bound expressions

The increment is strictly positive

The increment is strictly negative

The sign of the increment is unknown, no information is available

No information is available for loop indices that are not integer

This could be improved, but floating point indices should never be used.

Parameters
prere

Definition at line 1442 of file loop.c.

1443 {
1444  entity i = loop_index(l);
1445  range r = loop_range(l);
1446  expression low = range_lower(r);
1447  expression up = range_upper(r);
1448  expression inc = range_increment(r);
1449  int il, iu;
1451 
1453 
1455 
1456  if(il==iu && il==0) {
1457  /* A zero increment is not legal because the Fortran standard
1458  imposes a division by the increment. */
1459  /* Only the loop bopy statement number is available... */
1460  pips_user_error("Null increment for DO loop detected.\n");
1461  }
1462  else if(il>0||iu<0) {
1463  /* Assumption: no side effect in loop bound expressions */
1465  transformer lt = safe_integer_expression_to_transformer(lv, low, pre, true);
1467  transformer ut = safe_integer_expression_to_transformer(uv, up, pre, true);
1468 
1469  if(il>0) {
1470  /* The increment is strictly positive */
1471  t = transformer_add_inequality_with_linear_term(t, lv, i, 1, true);
1472  t = transformer_add_inequality_with_linear_term(t, i, uv, 1, true);
1473  }
1474  else if(iu<0) {
1475  /* The increment is strictly negative */
1476  t = transformer_add_inequality_with_linear_term(t, uv, i, 1, true);
1477  t = transformer_add_inequality_with_linear_term(t, i, lv, 1, true);
1478  }
1479  t = transformer_intersection(t, lt);
1480  t = transformer_intersection(t, ut);
1482  //t = transformer_normalize(t, 0);
1483  t = transformer_normalize(t, 1);
1484  free_transformers(lt, ut, NULL);
1485  }
1486  else {
1487  /* The sign of the increment is unknown, no information is available */
1488  ;
1489  }
1490  }
1491  else {
1492  /* No information is available for loop indices that are not integer */
1493  /* This could be improved, but floating point indices should never
1494  be used. */
1495  ;
1496  }
1497 
1498  return t;
1499 }
transformer transformer_add_inequality_with_linear_term(transformer tf, entity v, entity x, int a, bool less_than_p)
Add the inequality v <= a x or v >= a x.
Definition: basic.c:530
void free_transformers(transformer t,...)
Definition: basic.c:73
bool scalar_integer_type_p(type)
Definition: type.c:3276
transformer safe_integer_expression_to_transformer(entity v, expression expr, transformer pre, bool is_internal)
Always return a defined transformer, using effects in case a more precise analysis fails.
Definition: expression.c:3552
void integer_expression_and_precondition_to_integer_interval(expression, transformer, int *, int *)
Could be used for bool expressions too? Extended to any kind of expression?
Definition: utils.c:386
transformer transformer_intersection(transformer t1, transformer t2)
tf is a new transformer that receives the constraints in t1 and t2.
Definition: transformer.c:600

References entity_type, free_transformers(), integer_expression_and_precondition_to_integer_interval(), loop_index, loop_range, make_local_temporary_value_entity(), pips_user_error, range_increment, range_lower, range_upper, safe_integer_expression_to_transformer(), scalar_integer_type_p(), transformer_add_inequality_with_linear_term(), transformer_identity(), transformer_intersection(), transformer_normalize(), and transformer_temporary_value_projection().

Referenced by loop_to_continue_transformer(), and new_loop_to_transformer().

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

◆ loop_to_initialization_transformer()

transformer loop_to_initialization_transformer ( loop  l,
transformer  pre 
)

Transformer expression the loop initialization.

Parameters
prere

Definition at line 1430 of file loop.c.

1431 {
1432  entity i = loop_index(l);
1433  range r = loop_range(l);
1434  expression low = range_lower(r);
1436  return t;
1437 }
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...

References assigned_expression_to_transformer(), loop_index, loop_range, and range_lower.

Referenced by new_loop_to_transformer().

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

◆ loop_to_postcondition()

transformer loop_to_postcondition ( transformer  pre,
loop  l,
transformer  tf 
)

pips_internal_error("Equality option not implemented");

the standard version should be OK for SEMANTICS_EQUALITY_INVARIANTS...

basic cheap version: add information on loop index in pre and propagate preb downwards in the loop body; compute the loop postcondition independently using the loop transformer

preb = precondition for loop body; includes a lousy fix-point

Get rid of information related to variables modified in iterations of the loop body (including loop indices).

Apparently, the loop index incrementation is not in tf... according to a test with DO I = I, N although it should be... according to the caller of this function and the display of loop transformers!

Triolet's good loop algorithm

It might be useful to normalize preb and to detect unfeasibility. I choose not to do it because:

  • it almost never happens in user code
  • it's time consuming
  • when it happens in automatically generated code, dead code elimination is performed.

So basically, I shift the burden from precondition computation to dead code elimination. Dead loop testing must use a strong feasibility test.

If this decision is reversed, dead code elimination can be speeded-up.

Note that add_good_loop_conditions() can test trivial cases automatically generated.

Decision reverted: Francois Irigoin, 4 June 1997

preb can now be used to obtain a refined tf, for instance to show that a variable is monotonically increasing.

FI: this is not correct when an invariant is found; we should add one more incrementation of I (to modify the output of the invariant and express the fact that the loop bound is no more true, at least when the increment is one. 6 July 1993

Note 1: this comments was wrong! See Validation/Semantics/induc1.f Note 2: but the result was wrong anyway because it assumed that at least one iteration always was performed. Note 3: This is fixed by reverting the above decision.

propagate an impossible precondition in the loop body

The loop body precondition is not useful any longer

propagate preconditions in the loop body and compute its postcondition...

... or compute directly the postcondition using the loop body transformer. This second approach is slightly less precise because the transformer cannot use preconditions to avoid some convex approximations.

post = transformer_apply(tf, pre);

The loop body effects should be passed as fourth argument to check that the value of the upper bound expression is not modified when the body is executed. But it is not available and it is not yet used by ad_loop_index_exit_value()!

First version: OK, but could be better!

transformer postloop = transformer_apply(tf, pre);

pre must be copied because sc_convex_hull updates is arguments and may make them inconsistent when the two bases are merged to perform the convex hull in a common vector space

Second version: assume it is empty or non-empty and perform the convex hull of both (should be checked on Validation/Semantics/induc1.f)

propagate preconditions in the loop body

post_al = transformer_apply(tf, pre);

We should add (when possible) the non-entry condition in post_ne! For instance, DO I = 1, N leads to N <= 0

FI: Cannot be freed because it was stored for statement s: transformer_free(preb); did I mean to free pre, which is useless since it was changed into preb?

Parameters
prere
tff

Definition at line 2841 of file loop.c.

2844 {
2846  statement s = loop_body(l);
2847  range r = loop_range(l);
2848 
2849  pips_debug(8,"begin\n");
2850 
2852  pips_internal_error("Halbwachs not implemented");
2853  }
2854  else {
2855  /* pips_internal_error("Equality option not implemented"); */
2856  /* the standard version should be OK for SEMANTICS_EQUALITY_INVARIANTS... */
2857 
2858  /* basic cheap version: add information on loop index in pre
2859  and propagate preb downwards in the loop body; compute the
2860  loop postcondition independently using the loop transformer */
2861  /* preb = precondition for loop body; includes a lousy fix-point */
2862  transformer preb = transformer_dup(pre);
2863 
2864  /* Get rid of information related to variables modified in
2865  * iterations of the loop body (including loop indices).
2866  *
2867  * Apparently, the loop index incrementation is not in tf...
2868  * according to a test with DO I = I, N
2869  * although it should be... according to the caller of this function
2870  * and the display of loop transformers!
2871  */
2872  preb = transformer_combine(preb, tf);
2873 
2874  /* Triolet's good loop algorithm */
2875  preb = add_good_loop_conditions(preb, l);
2876 
2877  /* It might be useful to normalize preb and to detect unfeasibility.
2878  * I choose not to do it because:
2879  * - it almost never happens in user code
2880  * - it's time consuming
2881  * - when it happens in automatically generated code,
2882  * dead code elimination is performed.
2883  *
2884  * So basically, I shift the burden from precondition computation
2885  * to dead code elimination. Dead loop testing must use a strong
2886  * feasibility test.
2887  *
2888  * If this decision is reversed, dead code elimination can be
2889  * speeded-up.
2890  *
2891  * Note that add_good_loop_conditions() can test trivial cases
2892  * automatically generated.
2893  *
2894  * Decision reverted: Francois Irigoin, 4 June 1997
2895  */
2896 
2897  /* preb can now be used to obtain a refined tf, for instance to show that a
2898  variable is monotonically increasing. */
2899  if(get_bool_property("SEMANTICS_RECOMPUTE_FIX_POINTS_WITH_PRECONDITIONS")) {
2900  transformer new_tf = recompute_loop_transformer(l, preb);
2901 
2902  free_transformer(preb);
2903  preb = transformer_dup(pre);
2904  preb = transformer_combine(preb, new_tf);
2905  preb = add_good_loop_conditions(preb, l);
2906  }
2907 
2908 
2909  /* FI: this is not correct when an invariant is found; we should add one
2910  * more incrementation of I (to modify the output of the invariant and
2911  * express the fact that the loop bound is no more true, at least when
2912  * the increment is one. 6 July 1993
2913  *
2914  * Note 1: this comments was wrong! See Validation/Semantics/induc1.f
2915  * Note 2: but the result was wrong anyway because it assumed that at
2916  * least one iteration always was performed.
2917  * Note 3: This is fixed by reverting the above decision.
2918  */
2919  if(empty_range_wrt_precondition_p(r, pre)) {
2920  pips_debug(8, "The loop is never executed\n");
2921 
2922  /* propagate an impossible precondition in the loop body */
2924  /* The loop body precondition is not useful any longer */
2925  free_transformer(preb);
2926 
2927  transformer tmp = transformer_dup(pre);
2928  post = add_loop_index_initialization(tmp, l, pre);
2929  transformer_free(tmp);
2930  }
2931  else if(non_empty_range_wrt_precondition_p(r, pre)) {
2932  debug(8, "loop_to_postcondition", "The loop certainly is executed\n");
2933 
2934  /* propagate preconditions in the loop body and compute its postcondition... */
2935  post = statement_to_postcondition(preb, s);
2936 
2937  /* ... or compute directly the postcondition using the loop body transformer.
2938  * This second approach is slightly less precise because the transformer
2939  * cannot use preconditions to avoid some convex approximations. */
2940  /* post = transformer_apply(tf, pre); */
2941 
2942  /* The loop body effects should be passed as fourth argument
2943  * to check that the value of the upper bound expression is
2944  * not modified when the body is executed. But it is not available
2945  * and it is not yet used by ad_loop_index_exit_value()!
2946  */
2947  transformer tmp = post;
2948  post = add_loop_index_exit_value(post, l, pre);
2949  transformer_free(tmp);
2950  }
2951  else {
2952  /* First version: OK, but could be better! */
2953  /* transformer postloop = transformer_apply(tf, pre); */
2954  /* pre must be copied because sc_convex_hull updates is arguments
2955  * and may make them inconsistent when the two bases are merged
2956  * to perform the convex hull in a common vector space
2957  */
2958  /*
2959  transformer preloop = transformer_dup(pre);
2960  debug(8, "loop_to_postcondition", "The loop may be executed or not\n");
2961 
2962  post = transformer_convex_hull(postloop, preloop);
2963  transformer_free(postloop);
2964  transformer_free(preloop);
2965  */
2966 
2967  /* Second version: assume it is empty or non-empty and perform
2968  * the convex hull of both
2969  * (should be checked on Validation/Semantics/induc1.f)
2970  */
2972  transformer post_ne = transformer_apply(t_init, pre);
2974  transformer lpre = transformer_range(post_ne);
2975 
2976  pips_debug(8, "The loop may be executed or not\n");
2977 
2978  /* propagate preconditions in the loop body */
2979  post_al = statement_to_postcondition(preb, s);
2980  /* post_al = transformer_apply(tf, pre); */
2981 
2982  /* We should add (when possible) the non-entry condition in post_ne!
2983  * For instance, DO I = 1, N leads to N <= 0
2984  */
2985  post_ne = add_loop_skip_condition(post_ne, l, lpre);
2986  // FI: already done with t_init
2987  //post_ne = add_loop_index_initialization(post_ne, l, lpre);
2988  free_transformer(lpre);
2989 
2990  transformer tmp = post_al;
2991  post_al = add_loop_index_exit_value(post_al, l, post_al);
2992  transformer_free(tmp);
2993 
2994  ifdebug(8) {
2995  (void) fprintf(stderr,"%s: %s\n","[loop_to_postcondition]",
2996  "Never executed: post_ne %p =");
2997  (void) print_transformer(post_ne);
2998  (void) fprintf(stderr,"%s: %s\n","[loop_to_postcondition]",
2999  "Always executed: post_al %p = ");
3000  (void) print_transformer(post_al);
3001  }
3002  post = transformer_convex_hull(post_ne, post_al);
3003  transformer_free(post_ne);
3004  transformer_free(post_al);
3005  }
3006 
3007  /* FI: Cannot be freed because it was stored for statement s:
3008  transformer_free(preb);
3009  did I mean to free pre, which is useless since it was changed into
3010  preb?
3011  */
3012  }
3013 
3014  ifdebug(8) {
3015  (void) fprintf(stderr,"%s: %s\n","[loop_to_postcondition]",
3016  "resultat post =");
3017  (void) print_transformer(post);
3018  }
3019  pips_debug(8,"end\n");
3020  return post;
3021 }
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
#define SEMANTICS_FIX_POINT
#define pips_flag_p(p)
for upwards compatibility with Francois's modified version
#define SEMANTICS_INEQUALITY_INVARIANT
static transformer add_good_loop_conditions(transformer pre, loop l)
Definition: loop.c:790
static transformer recompute_loop_transformer(loop l, transformer pre)
Recompute a fixpoint conditionnally to a valid precondition for all iterations.
Definition: loop.c:2310

References add_good_loop_conditions(), add_loop_index_exit_value(), add_loop_index_initialization(), add_loop_skip_condition(), debug(), empty_range_wrt_precondition_p(), fprintf(), free_transformer(), get_bool_property(), ifdebug, loop_body, loop_initialization_to_transformer(), loop_range, non_empty_range_wrt_precondition_p(), pips_debug, pips_flag_p, pips_internal_error, print_transformer, recompute_loop_transformer(), SEMANTICS_FIX_POINT, SEMANTICS_INEQUALITY_INVARIANT, statement_to_postcondition(), transformer_apply(), transformer_combine(), transformer_convex_hull(), transformer_dup(), transformer_empty(), transformer_free(), transformer_range(), and transformer_undefined.

Referenced by instruction_to_postcondition().

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

◆ loop_to_total_precondition()

transformer loop_to_total_precondition ( transformer  t_post,
loop  l,
transformer  tf,
transformer  context 
)

Triolet's good loop algorithm

preb = transformer_dup(pre);

The loop is never executed

impact of loop index initialization, i.e. I = IT(J),.. or I = K/L,..

the loop may be entered for sure, or entered or not

We need a fix_point without the initial condition but with the exit condition

Also performs last incrementation

free_transformer(b_t_pre); it is associated to the loop body!

The loop is always entered

The loop may be skipped or entered

skipped case computed here too

Parameters
t_post_post
tff
contextontext

Definition at line 3023 of file loop.c.

3028 {
3030  statement b = loop_body(l);
3031  range r = loop_range(l);
3032 
3033  pips_debug(8,"begin\n");
3034 
3035  if(get_bool_property("SEMANTICS_RECOMPUTE_FIX_POINTS_WITH_PRECONDITIONS")) {
3038 
3039  preb = transformer_combine(preb, tf);
3040 
3041  /* Triolet's good loop algorithm */
3042  preb = add_good_loop_conditions(preb, l);
3043 
3044  new_tf = recompute_loop_transformer(l, preb);
3045 
3046  free_transformer(preb);
3047  /* preb = transformer_dup(pre); */
3048  preb = transformer_combine(preb, new_tf);
3049  preb = add_good_loop_conditions(preb, l);
3050  }
3051 
3052  if(empty_range_wrt_precondition_p(r, context)) { /* The loop is never executed */
3054  transformer tf_empty = transformer_empty();
3056 
3057  pips_debug(8, "The loop is never executed\n");
3058 
3059  b_t_pre = statement_to_total_precondition(tf_empty, b);
3060  pips_assert("The body total precondition is consistent",
3061  transformer_consistency_p(b_t_pre));
3062 
3063  /* impact of loop index initialization, i.e. I = IT(J),.. or I = K/L,.. */
3064  t_pre = transformer_inverse_apply(tf_init, t_post);
3065  t_pre = transformer_to_domain(t_pre);
3066 
3067  free_transformer(tf_empty);
3068  free_transformer(tf_init);
3069  }
3070  else /* the loop may be entered for sure, or entered or not */ {
3071 
3074  /* We need a fix_point without the initial condition but with the exit
3075  condition */
3081 
3083  ltf = (* transformer_fix_point_operator)(btf);
3084  ltf = add_loop_index_exit_value(ltf, l, context); /* Also performs
3085  last
3086  incrementation */
3087  b_t_post = transformer_inverse_apply(ltf, t_post);
3088  b_t_post = transformer_to_domain(b_t_post);
3089  b_t_pre = statement_to_total_precondition(b_t_post, b);
3090  pips_assert("The body total precondition is consistent",
3091  transformer_consistency_p(b_t_pre));
3092  t_pre_al = transformer_inverse_apply(tf_init, b_t_pre);
3093  t_pre_al = transformer_to_domain(t_pre_al);
3094 
3095  /* free_transformer(b_t_pre); it is associated to the loop body!*/
3096  free_transformer(b_t_post);
3097  free_transformer(btf);
3098  free_transformer(ltf);
3099 
3101  /* The loop is always entered */
3102  t_pre = t_pre_al;
3103 
3104  pips_debug(8, "The loop certainly is executed\n");
3105  }
3106  else /* The loop may be skipped or entered */ {
3107 
3108  pips_debug(8, "The loop may be executed or not\n");
3109 
3110  /* skipped case computed here too */
3111  t_pre_ne = transformer_inverse_apply(tf_init, t_post);
3112  t_pre_ne = transformer_to_domain(t_pre_ne);
3113  t_pre_ne = add_loop_skip_condition(t_pre_ne, l, context);
3114 
3115 
3116  ifdebug(8) {
3117  (void) fprintf(stderr,"%s: %s\n","[loop_to_postcondition]",
3118  "Never executed: t_pre_ne =");
3119  (void) print_transformer(t_pre_ne);
3120  (void) fprintf(stderr,"%s: %s\n","[loop_to_postcondition]",
3121  "Always executed: post_al =");
3122  (void) print_transformer(t_pre_al);
3123  }
3124 
3125  t_pre = transformer_convex_hull(t_pre_ne, t_pre_al);
3126  transformer_free(t_pre_ne);
3127  transformer_free(t_pre_al);
3128  }
3129  free_transformer(tf_init);
3130  }
3131 
3132  ifdebug(8) {
3133  pips_debug(8, "resultat t_pre =%p", t_pre);
3134  (void) print_transformer(t_pre);
3135  pips_debug(8,"end\n");
3136  }
3137  return t_pre;
3138 }
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
transformer statement_to_total_precondition(transformer, statement)
semantical analysis
Definition: delay.c:253
transformer transformer_inverse_apply(transformer tf, transformer post)
transformer transformer_inverse_apply(transformer tf, transformer post): apply transformer tf on prec...
Definition: transformer.c:1657
transformer transformer_to_domain(transformer tf)
Return the domain of relation tf in a newly allocated transformer.
Definition: transformer.c:772

References add_good_loop_conditions(), add_loop_index_exit_value(), add_loop_skip_condition(), empty_range_wrt_precondition_p(), fprintf(), free_transformer(), get_bool_property(), ifdebug, load_statement_transformer(), loop_body, loop_initialization_to_transformer(), loop_range, non_empty_range_wrt_precondition_p(), pips_assert, pips_debug, print_transformer, recompute_loop_transformer(), statement_to_total_precondition(), transformer_add_loop_index_incrementation(), transformer_combine(), transformer_consistency_p(), transformer_convex_hull(), transformer_dup(), transformer_empty(), transformer_free(), transformer_inverse_apply(), transformer_to_domain(), and transformer_undefined.

Referenced by instruction_to_total_precondition().

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

◆ loop_to_transformer()

transformer loop_to_transformer ( loop  l,
transformer  pre,
list  e 
)

The transformer associated to a DO loop does not include the exit condition because it is used to compute the precondition for any loop iteration.

There is only one attachment for the unbounded transformer and for the bounded one.

loop transformer tf = tfb* or tf = tfb+ or ...

loop body transformer

approximate loop transformer, including loop index updates

loop body precondition

Information about loop local variables is lost

range r = loop_range(l);

eliminate all information about local variables

Mostly useful for Fortran code.

In C, variables declared in the loop body do not exist before the loop is entered and so do not have to be projected. But local variables may have been introduced by a privatization phase.

compute the loop body transformer under loop body precondition preb

add indexation step under loop precondition pre

compute tfb's fix point according to pips flags

restrict the domain of tf by the range of pre, except for the loop index which is assigned in between

add initialization for the unconditional initialization of the loop index variable

we have a problem here: to compute preconditions within the loop body we need a tf using private variables; to return the loop transformer, we need a filtered out tf; only one hook is available in the ri..; let'a assume there are no private variables and that if they are privatizable they are not going to get in our way

Parameters
prere

Definition at line 1319 of file loop.c.

1321 {
1322  /* loop transformer tf = tfb* or tf = tfb+ or ... */
1324  /* loop body transformer */
1326  /* approximate loop transformer, including loop index updates */
1328  /* loop body precondition */
1329  transformer preb = invariant_wrt_transformer(pre, abtf);
1330  /* Information about loop local variables is lost */
1331  list lv = loop_locals(l);
1332  /* range r = loop_range(l); */
1333  statement b = loop_body(l);
1336 
1337  pips_debug(8,"begin with precondition pre=%p\n", pre);
1338  ifdebug(8) {
1339  (void) print_transformer(pre);
1340  }
1341 
1342  /* eliminate all information about local variables
1343  *
1344  * Mostly useful for Fortran code.
1345  *
1346  * In C, variables declared in the loop body do not exist before the
1347  * loop is entered and so do not have to be projected. But local
1348  * variables may have been introduced by a privatization phase.
1349  */
1350  preb = safe_transformer_projection(preb, lv);
1351 
1352  /* compute the loop body transformer under loop body precondition preb */
1353  if(!transformer_undefined_p(preb))
1354  preb = add_good_loop_conditions(preb, l);
1355 
1356  pips_debug(8,"body precondition preb=%p\n", preb);
1357  ifdebug(8) {
1358  (void) print_transformer(preb);
1359  }
1360 
1361  tfb = statement_to_transformer(b, preb);
1362  /* add indexation step under loop precondition pre */
1363  tfb = transformer_add_loop_index_incrementation(tfb, l, pre);
1364 
1365  pips_debug(8,"body transformer tfb=%p\n", tfb);
1366  ifdebug(8) {
1367  (void) print_transformer(tfb);
1368  }
1369 
1370  /* compute tfb's fix point according to pips flags */
1371  tf = (* transformer_fix_point_operator)(tfb);
1372 
1373  free_transformer(tfb);
1374 
1375  ifdebug(8) {
1376  pips_debug(8, "intermediate fix-point tf=\n");
1378  }
1379 
1380  /* restrict the domain of tf by the range of pre, except for the loop
1381  index which is assigned in between */
1382  if(!transformer_undefined_p(pre)
1383  && get_bool_property("SEMANTICS_COMPUTE_TRANSFORMERS_IN_CONTEXT")) {
1384  list li = CONS(ENTITY, loop_index(l), NIL);
1386  transformer r_pre = transformer_range(preb);
1387 
1388  tf = transformer_domain_intersection(tf, r_pre);
1389  free_transformer(r_pre);
1390  free_transformer(preb);
1391  gen_free_list(li);
1392  }
1393 
1394  /* add initialization for the unconditional initialization of the loop
1395  index variable */
1396  t_init = loop_initialization_to_transformer(l, pre);
1397  old_tf = tf;
1398  tf = transformer_combine(t_init, tf);
1401  free_transformer(old_tf);
1402 
1403  /* we have a problem here: to compute preconditions within the
1404  loop body we need a tf using private variables; to return
1405  the loop transformer, we need a filtered out tf; only
1406  one hook is available in the ri..; let'a assume there
1407  are no private variables and that if they are privatizable
1408  they are not going to get in our way */
1409 
1410  ifdebug(8) {
1411  (void) fprintf(stderr,"%s: %s\n","loop_to_transformer",
1412  "resultat tf =");
1413  (void) (void) print_transformer(tf);
1414  pips_debug(8,"end\n");
1415  }
1416 
1417  return tf;
1418 }
#define loop_locals(x)
Definition: ri.h:1650
transformer transformer_filter(transformer t, list args)
transformer transformer_filter(transformer t, cons * args): projection of t along the hyperplane defi...
Definition: transformer.c:1716
transformer invariant_wrt_transformer(transformer p, transformer tf)
transformer invariant_wrt_transformer(transformer p, transformer tf): Assume that tf is a fix-point o...
Definition: transformer.c:1948

References add_good_loop_conditions(), add_index_range_conditions(), CONS, effects_to_transformer(), ENTITY, external_value_name(), fprint_transformer(), fprintf(), free_transformer(), gen_free_list(), get_bool_property(), ifdebug, invariant_wrt_transformer(), load_statement_transformer(), loop_body, loop_index, loop_initialization_to_transformer(), loop_locals, loop_range, NIL, pips_debug, print_transformer, safe_transformer_projection(), statement_to_transformer(), transformer_add_loop_index_incrementation(), transformer_combine(), transformer_domain_intersection(), transformer_dup(), transformer_filter(), transformer_range(), transformer_undefined, and transformer_undefined_p.

Referenced by instruction_to_transformer().

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

◆ loop_to_transformer_list()

list loop_to_transformer_list ( loop l   __attribute__(unused),
transformer pre   __attribute__(unused),
list e   __attribute__(unused) 
)

Definition at line 1420 of file loop.c.

1423 {
1424  list tfl = NIL;
1425  pips_internal_error("Not implemented yet.");
1426  return tfl;
1427 }

References NIL, and pips_internal_error.

◆ new_complete_whileloop_transformer()

transformer new_complete_whileloop_transformer ( transformer  t_body_star,
transformer  pre,
whileloop  wl,
bool  entered_p 
)

entered_p is used to for the execution of at least one iteration

Parameters
t_body_star_body_star
prere
wll
entered_pntered_p

Definition at line 1833 of file loop.c.

1837 {
1838  list tfl =
1839  new_complete_whileloop_transformer_list(t_body_star, pre, wl, entered_p);
1841  // tfl is destroyed by transformer_list_to_transformer()
1842  return ct;
1843 }

References new_complete_whileloop_transformer_list(), and transformer_list_to_transformer().

Referenced by complete_whileloop_transformer(), and generic_complete_statement_transformer().

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

◆ new_complete_whileloop_transformer_list()

list new_complete_whileloop_transformer_list ( transformer  t_body_star,
transformer  pre,
whileloop  wl,
bool entered_p   __attribute__(__unused__) 
)

entered_p is used to for the execution of at least one iteration

An effort could be made to compute the preconditions for t_continue and t_exit: see while04.c.

Make sure you have the effective statement transformer: it is not stored for loops and this is key for nested loops.

Should we instead compute recursively a transformer list?

Definition at line 1781 of file loop.c.

1785 {
1786  list tfl = NIL;
1787  //transformer ct = transformer_undefined;
1788  statement body_s = whileloop_body(wl);
1789  transformer t_body = load_statement_transformer(body_s);
1792  transformer post_body = transformer_undefined;
1793  transformer t_init = transformer_identity();
1794  expression cond_e = whileloop_condition(wl);
1795  //transformer t_skip = entered_p?
1796  // transformer_empty() : condition_to_transformer(cond_e, pre, false);
1797  transformer t_skip = condition_to_transformer(cond_e, pre, false);
1798  transformer t_enter = condition_to_transformer(cond_e, pre, true);
1799  /* An effort could be made to compute the preconditions for t_continue and t_exit: see while04.c. */
1800  //transformer t_continue = condition_to_transformer(cond_e, transformer_undefined, true);
1801  //transformer t_exit = condition_to_transformer(cond_e, transformer_undefined, false);
1802  transformer t_continue = transformer_undefined;
1805 
1806  /* Make sure you have the effective statement transformer: it is not
1807  stored for loops and this is key for nested loops. */
1808  pre_body = transformer_apply(t_body_star, pre);
1809  /* Should we instead compute recursively a transformer list? */
1810  ct_body = complete_statement_transformer(t_body, pre_body, body_s);
1811 
1812  post_body = transformer_apply(ct_body, pre_body);
1813  t_continue = condition_to_transformer(cond_e, post_body, true);
1814  t_exit = condition_to_transformer(cond_e, post_body, false);
1815 
1816  tfl = complete_any_loop_transformer_list(t_init, t_skip, t_body_star,
1817  ct_body, t_inc, t_exit);
1818 
1819  free_transformer(ct_body);
1820  free_transformer(pre_body);
1821  free_transformer(post_body);
1822  free_transformer(t_init);
1823  free_transformer(t_skip);
1824  free_transformer(t_enter);
1825  free_transformer(t_continue);
1826  free_transformer(t_exit);
1827  free_transformer(t_inc);
1828 
1829  return tfl;
1830 }

References complete_any_loop_transformer_list(), complete_statement_transformer(), condition_to_transformer(), free_transformer(), load_statement_transformer(), NIL, transformer_apply(), transformer_identity(), transformer_undefined, whileloop_body, and whileloop_condition.

Referenced by complete_whileloop_transformer_list(), and new_complete_whileloop_transformer().

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

◆ new_loop_to_transformer()

transformer new_loop_to_transformer ( loop  l,
transformer  pre,
list  lel 
)

loop_to_transformer() was developed first but is not as powerful as the new algorithm used for all kinds of loops.

See flip-flop01.c.

Equation:

t_body_star = t_init ; t_enter ;(t_body ; t_inc; t_continue)*

t_init, t_enter and t_continue, which includes t_inc, must be computed from the loop and its precondition, pre, and extended body effects, lel. In case the loop index appears in the bound or increment expressions, the Fortran standard should be used to determine the precondition to use. The same is true in case of side-effects in the loop expressions.

t_body must be computed from the loop body and a preliminary loop invariant.

Deal with initialization expression, which may be included in the condition as in while(i++, j=0, i<m)? No because the expression is going to be evaluated at each cycle. The ised effects must be part of the condition transformer, tcond

Deal with enter transformers

An effort could be made to compute the precondition for t_continue. Precondition pre and the loop effect list lel could be used.

approximate loop transformer, including loop index updates

first approximation of the loop body precondition

FI: could do better with body_transformer

Let's clean up the memory

Parameters
prere
lelel

Definition at line 1516 of file loop.c.

1518 {
1519  /* Equation:
1520  *
1521  * t_body_star = t_init ; t_enter ;(t_body ; t_inc; t_continue)*
1522  *
1523  * t_init, t_enter and t_continue, which includes t_inc, must be
1524  * computed from the loop and its precondition, pre, and extended
1525  * body effects, lel. In case the loop index appears in the bound or
1526  * increment expressions, the Fortran standard should be used to
1527  * determine the precondition to use. The same is true in case of
1528  * side-effects in the loop expressions.
1529  *
1530  * t_body must be computed from the loop body and a preliminary loop
1531  * invariant.
1532  */
1533  transformer t_body_star = transformer_undefined;
1534  statement body_s = loop_body(l);
1535 
1536  /* Deal with initialization expression, which may be included in
1537  the condition as in while(i++, j=0, i<m)? No because the
1538  expression is going to be evaluated at each cycle. The ised
1539  effects must be part of the condition transformer, tcond */
1541  // FI Memory leak
1542  transformer post_i = transformer_range(transformer_apply(t_init, pre));
1543 
1544  /* Deal with enter transformers */
1545  transformer t_enter = loop_to_enter_transformer(l, post_i);
1546  transformer pre_b = transformer_apply(t_enter, post_i);
1547 
1548  /* An effort could be made to compute the precondition for t_continue.
1549  * Precondition pre and the loop effect list lel could be used.
1550  */
1551  //transformer p_continue = transformer_identity();
1552  /* approximate loop transformer, including loop index updates */
1553  transformer abtf = effects_to_transformer(lel);
1554  /* first approximation of the loop body precondition */
1555  // invariant_wrt_transformer() seems to add arguments to the
1556  // filtered precondition...
1557  // FI: memory leak
1558  transformer p_continue = transformer_range(invariant_wrt_transformer(pre_b, abtf));
1559  /* FI: could do better with body_transformer */
1560  transformer t_continue = loop_to_continue_transformer(l, p_continue);
1561 
1562  t_body_star = any_loop_to_transformer(t_init, t_enter, t_continue, body_s, lel, pre_b);
1563 
1564  /* Let's clean up the memory */
1565 
1566  free_transformer(p_continue);
1567  free_transformer(t_enter);
1568  free_transformer(t_continue);
1569  free_transformer(post_i);
1570  free_transformer(pre_b);
1571 
1572  return t_body_star;
1573 }
transformer loop_to_continue_transformer(loop l, transformer pre)
Definition: loop.c:1501
transformer loop_to_initialization_transformer(loop l, transformer pre)
Transformer expression the loop initialization.
Definition: loop.c:1430

References any_loop_to_transformer(), effects_to_transformer(), free_transformer(), invariant_wrt_transformer(), loop_body, loop_to_continue_transformer(), loop_to_enter_transformer(), loop_to_initialization_transformer(), transformer_apply(), transformer_range(), and transformer_undefined.

+ Here is the call graph for this function:

◆ new_whileloop_to_k_transformer()

transformer new_whileloop_to_k_transformer ( whileloop  wl,
transformer  pre,
list  wlel,
int  k 
)

t_body_star = t_init ; t_enter ;(t_body ; t_next)*

Deal with initialization expression

Deal with condition expression

An effort could be made to compute the precondition for t_continue.

Let's clean up the memory

Parameters
wll
prere
wlellel
keffects of whileloop wl

Definition at line 416 of file loop.c.

422 {
423  /* t_body_star = t_init ; t_enter ;(t_body ; t_next)* */
424  transformer t_body_star = transformer_undefined;
425  statement body_s = whileloop_body(wl);
426 
427  /* Deal with initialization expression */
429 
430  /* Deal with condition expression */
431  expression cond_e = whileloop_condition(wl);
432  transformer t_enter = condition_to_transformer(cond_e, pre, true);
433  /* An effort could be made to compute the precondition for t_continue. */
434  transformer p_continue = transformer_identity();
435  transformer t_continue = condition_to_transformer(cond_e, p_continue, true);
436 
437  t_body_star = any_loop_to_k_transformer(t_init, t_enter, t_continue, body_s, wlel, pre, k);
438 
439  /* Let's clean up the memory */
440 
441  free_transformer(p_continue);
442 
443  free_transformer(t_enter);
444  free_transformer(t_continue);
445 
446  return t_body_star;
447 }

References any_loop_to_k_transformer(), condition_to_transformer(), free_transformer(), transformer_identity(), transformer_undefined, whileloop_body, and whileloop_condition.

Referenced by whileloop_to_k_transformer().

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

◆ new_whileloop_to_transformer()

transformer new_whileloop_to_transformer ( whileloop  wl,
transformer  pre,
list  wlel 
)

effects of whileloop wl

Equation:

t_body_star = t_init ; t_enter ;(t_body ; t_continue)*

Deal with initialization expression, which may be included in the condition as in while(i++, j=0, i<m)? No because the expression is going to be evaluated at each cycle. The ised effects must be part of the condition transformer, tcond

Deal with condition expression

An effort could be made to compute the precondition for t_continue.

Let's clean up the memory

Parameters
wll
prere
wlellel

Definition at line 380 of file loop.c.

383 {
384  /* Equation:
385  *
386  * t_body_star = t_init ; t_enter ;(t_body ; t_continue)*
387  */
388  transformer t_body_star = transformer_undefined;
389  statement body_s = whileloop_body(wl);
390 
391  /* Deal with initialization expression, which may be included in
392  the condition as in while(i++, j=0, i<m)? No because the
393  expression is going to be evaluated at each cycle. The ised
394  effects must be part of the condition transformer, tcond */
396 
397  /* Deal with condition expression */
398  expression cond_e = whileloop_condition(wl);
399  transformer t_enter = condition_to_transformer(cond_e, pre, true);
400  /* An effort could be made to compute the precondition for t_continue. */
401  transformer p_continue = transformer_identity();
402  transformer t_continue = condition_to_transformer(cond_e, p_continue, true);
403 
404  t_body_star = any_loop_to_transformer(t_init, t_enter, t_continue, body_s, wlel, pre);
405 
406  /* Let's clean up the memory */
407 
408  free_transformer(p_continue);
409 
410  free_transformer(t_enter);
411  free_transformer(t_continue);
412 
413  return t_body_star;
414 }

References any_loop_to_transformer(), condition_to_transformer(), free_transformer(), transformer_identity(), transformer_undefined, whileloop_body, and whileloop_condition.

Referenced by whileloop_to_transformer().

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

◆ old_complete_whileloop_transformer()

transformer old_complete_whileloop_transformer ( transformer  ltf,
transformer  pre,
whileloop  l 
)

loop body transformer

Recompute the exact loop body transformer. This is weird: it should have already been done by statement_to_transformer and propagated bask. However, we need to recompute it because it has not been stored and cannot be retrieved. It might be better to use complete_statement_transformer(retrieved t, preb, s).

Since it is not stored, we need to go down recursively. A way to avoid this would be to always have sequences as loop bodies... Let's hope that perfectly nested loops are neither frequent nor deep!

The proper transformer has been stored.

btf = transformer_add_condition_information(btf, cond, preb, true);

add the exit condition

add initialization for the unconditional initialization of the loop index variable

It might be better not to compute useless transformer, but it's more readable that way. Since pre is information free, only loops with constant lower and upper bound and constant increment can benefit from this.

Parameters
ltftf
prere

Definition at line 2213 of file loop.c.

2216 {
2220  /* loop body transformer */
2222  expression cond = whileloop_condition(l);
2223  statement s = whileloop_body(l);
2224  transformer preb = invariant_wrt_transformer(pre, ltf);
2225 
2226  pips_debug(8,"begin with whileloop precondition\n");
2227  ifdebug(8) {
2228  (void) print_transformer(pre);
2229  pips_debug(8,"and whileloop transformer:\n");
2230  (void) print_transformer(ltf);
2231  }
2232 
2233  /* Recompute the exact loop body transformer. This is weird: it
2234  should have already been done by statement_to_transformer and
2235  propagated bask. However, we need to recompute it because it has
2236  not been stored and cannot be retrieved. It might be better to
2237  use complete_statement_transformer(retrieved t, preb, s). */
2238  if(statement_loop_p(s)) {
2239  /* Since it is not stored, we need to go down recursively. A way to
2240  avoid this would be to always have sequences as loop
2241  bodies... Let's hope that perfectly nested loops are neither
2242  frequent nor deep! */
2245  }
2246  else if(statement_whileloop_p(s)) {
2249  }
2250  else { /* The proper transformer has been stored. */
2252  }
2253 
2254  /* btf = transformer_add_condition_information(btf, cond, preb, true); */
2255  t_enter = transformer_combine(transformer_dup(ltf), btf);
2256 
2257  ifdebug(8) {
2258  pips_debug(8, "entered loop transformer t_enter=\n");
2260  }
2261 
2262  /* add the exit condition */
2263  t_enter = transformer_add_condition_information(t_enter, cond, preb, false);
2264 
2265  ifdebug(8) {
2266  pips_debug(8, "entered and exited loop transformer t_enter=\n");
2268  }
2269 
2270  /* add initialization for the unconditional initialization of the loop
2271  index variable */
2272  t_skip = transformer_undefined_p(pre)?
2274  transformer_dup(pre);
2275  t_skip = transformer_add_condition_information(t_skip, cond, pre, false);
2276 
2277  ifdebug(8) {
2278  pips_debug(8, "skipped loop transformer t_skip=\n");
2280  }
2281 
2282  /* It might be better not to compute useless transformer, but it's more
2283  readable that way. Since pre is information free, only loops with
2284  constant lower and upper bound and constant increment can benefit
2285  from this. */
2287  tf = t_skip;
2288  free_transformer(t_enter);
2289  }
2290  else if(!transformer_undefined_p(pre) && condition_true_wrt_precondition_p(cond, pre)) {
2291  tf = t_enter;
2292  free_transformer(t_skip);
2293  }
2294  else {
2295  tf = transformer_convex_hull(t_enter, t_skip);
2296  free_transformer(t_enter);
2297  free_transformer(t_skip);
2298  }
2299 
2300  ifdebug(8) {
2301  pips_debug(8, "full refined loop transformer tf=\n");
2303  pips_debug(8, "end\n");
2304  }
2305 
2306  return tf;
2307 }
bool statement_whileloop_p(statement)
Definition: statement.c:354
#define instruction_whileloop(x)
Definition: ri.h:1523
transformer transformer_add_condition_information(transformer pre, expression c, transformer context, bool veracity)
Definition: expression.c:1092
transformer complete_whileloop_transformer(transformer ltf, transformer pre, whileloop wl)
FI: I'm not sure this function is useful.
Definition: loop.c:2183
bool condition_true_wrt_precondition_p(expression, transformer)
A condition cannot be tested exactly wrt a precondition You can try to prove that it is always true (...
Definition: utils.c:276
bool condition_false_wrt_precondition_p(expression, transformer)
Definition: utils.c:285

References complete_loop_transformer(), complete_whileloop_transformer(), condition_false_wrt_precondition_p(), condition_true_wrt_precondition_p(), external_value_name(), fprint_transformer(), free_transformer(), ifdebug, instruction_loop, instruction_whileloop, invariant_wrt_transformer(), load_statement_transformer(), pips_debug, print_transformer, statement_instruction, statement_loop_p(), statement_whileloop_p(), transformer_add_condition_information(), transformer_combine(), transformer_convex_hull(), transformer_dup(), transformer_identity(), transformer_undefined, transformer_undefined_p, whileloop_body, and whileloop_condition.

+ Here is the call graph for this function:

◆ precondition_filter_old_values()

transformer precondition_filter_old_values ( transformer  pre)
Parameters
prere

Definition at line 1065 of file loop.c.

1066 {
1068  Pbase b = BASE_UNDEFINED;
1069 
1070  for(b = sc_base(sc); !BASE_NULLE_P(b); b = vecteur_succ(b)) {
1071  entity old_v = (entity) vecteur_var(b);
1072 
1073  if(old_value_entity_p(old_v)) {
1074  pips_assert("No old values are left", false);
1075  }
1076  }
1077 
1078  return pre;
1079 }
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
#define predicate_system(x)
Definition: ri.h:2069
bool old_value_entity_p(entity)
Definition: value.c:936
#define vecteur_var(v)
#define vecteur_succ(v)
#define BASE_UNDEFINED
#define BASE_NULLE_P(b)

References BASE_NULLE_P, BASE_UNDEFINED, old_value_entity_p(), pips_assert, predicate_system, transformer_relation, vecteur_succ, and vecteur_var.

+ Here is the call graph for this function:

◆ recompute_loop_transformer()

static transformer recompute_loop_transformer ( loop  l,
transformer  pre 
)
static

Recompute a fixpoint conditionnally to a valid precondition for all iterations.

get rid of information modified by the loop body or the loop header

get rid of old values in preb which are meaning less in tf

do not try to eliminate the same variable twice

Not all values can be projected in preb because some may appear in tf and not in preb

add the remaining conditional information to the loop transformer

Definition at line 2310 of file loop.c.

2311 {
2312  statement s = loop_body(l);
2313  entity i = loop_index(l);
2314  list list_mod = list_undefined;
2315  list list_old = list_undefined;
2316  list list_projectable = list_undefined;
2317  list list_val = list_undefined;
2321  transformer preb = transformer_dup(pre);
2322  Psysteme sc_pre = SC_UNDEFINED;
2324 
2325  ifdebug(5) {
2326  pips_debug(5, "Begin with precondition:\n");
2327  print_transformer(pre);
2328  pips_assert("Precondition pre is consistent",
2330  pips_debug(5, "and transformer:\n");
2331  print_transformer(tf);
2332  }
2333 
2334  /* get rid of information modified by the loop body or the loop header */
2335  list_mod = dup_arguments(transformer_arguments(tf));
2336  arguments_add_entity(list_mod, i);
2337  gen_list_and(&list_mod, transformer_arguments(preb));
2338  ifdebug(5) {
2339  pips_debug(5, "Variables eliminated from the preconditions"
2340  " because they are modified by tf:");
2341  print_arguments(list_mod);
2342  }
2343  list_val = variables_to_values(list_mod);
2344  /* get rid of old values in preb which are meaning less in tf */
2346  transformer_arguments(tf));
2347  ifdebug(5) {
2348  pips_debug(5, "Variables eliminated from the preconditions"
2349  " because they are linked to the module entry point:");
2350  print_arguments(list_old);
2351  }
2352  /* do not try to eliminate the same variable twice */
2353  gen_list_and_not(&list_old, list_mod);
2354 
2355  list_val = gen_nconc(list_val, variables_to_old_values(list_old));
2356  ifdebug(5) {
2357  pips_debug(5, "Values which should be eliminated from the preconditions:");
2358  print_arguments(list_val);
2359  }
2360  /* Not all values can be projected in preb because some may appear in tf
2361  and not in preb */
2362  list_projectable = transformer_projectable_values(preb);
2363  gen_list_and(&list_val, list_projectable);
2364  ifdebug(5) {
2365  pips_debug(5, "Values which can be eliminated from the preconditions:");
2366  print_arguments(list_val);
2367  }
2368  preb = transformer_projection(preb, list_val);
2369 
2370  /* add the remaining conditional information to the loop transformer */
2371  sc_pre = predicate_system(transformer_relation(preb));
2372  sc = sc_append(sc, sc_pre);
2374  ifdebug(1) {
2376  print_transformer(tfb);
2377  sc_fprint(stderr, sc, (char * (*)(Variable)) external_value_name);
2378  }
2379  pips_assert("Conditional loop body transformer is consistent",
2381  }
2382 
2383  tfb = transformer_add_loop_index_incrementation(tfb, l, pre);
2384 
2385  new_tf = (* transformer_fix_point_operator)(tfb);
2386  new_tf = transformer_add_loop_index_initialization(new_tf, l, pre);
2387 
2388  free_transformer(preb);
2389  gen_free_list(list_mod);
2390  gen_free_list(list_val);
2391 
2392  ifdebug(5) {
2393  pips_debug(5, "End with fixpoint:\n");
2394  print_transformer(new_tf);
2395  }
2396 
2397  return new_tf;
2398 }
cons * dup_arguments(cons *args)
Definition: arguments.c:225
cons * arguments_difference(cons *a1, cons *a2)
set difference: a1 - a2 ; similar to set intersection
Definition: arguments.c:233
list transformer_projectable_values(transformer tf)
Definition: basic.c:827
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
void gen_list_and(list *a, const list b)
Compute A = A inter B: complexity in O(n2)
Definition: list.c:941
void gen_list_and_not(list *a, const list b)
Compute A = A inter non B:
Definition: list.c:963
void print_arguments(list args)
Definition: naming.c:228
Psysteme sc_append(Psysteme s1, Psysteme s2)
Psysteme sc_append(Psysteme s1, Psysteme s2): calcul de l'intersection des polyedres definis par s1 e...
void sc_fprint(FILE *fp, Psysteme ps, get_variable_name_t nom_var)
void sc_fprint(FILE * f, Psysteme ps, char * (*nom_var)()): cette fonction imprime dans le fichier po...
Definition: sc_io.c:220
transformer transformer_add_loop_index_initialization(transformer tf, loop l, transformer pre)
The loop initialization is performed before tf.
Definition: loop.c:1082
list variables_to_values(list list_mod)
Definition: mappings.c:966
list variables_to_old_values(list list_mod)
Definition: mappings.c:1024
transformer transformer_projection(transformer t, list args)
values in args must be in t's base
Definition: transformer.c:1267

References arguments_add_entity(), arguments_difference(), dup_arguments(), external_value_name(), free_transformer(), gen_free_list(), gen_list_and(), gen_list_and_not(), gen_nconc(), ifdebug, list_undefined, load_statement_transformer(), loop_body, loop_index, pips_assert, pips_debug, predicate_system, print_arguments(), print_transformer, sc_append(), sc_fprint(), transformer_add_loop_index_incrementation(), transformer_add_loop_index_initialization(), transformer_arguments, transformer_dup(), transformer_internal_consistency_p(), transformer_projectable_values(), transformer_projection(), transformer_relation, transformer_undefined, variables_to_old_values(), and variables_to_values().

Referenced by loop_to_postcondition(), and loop_to_total_precondition().

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

◆ repeatloop_to_postcondition()

transformer repeatloop_to_postcondition ( transformer  pre,
whileloop  wl,
transformer  t_body_star 
)

An effort could be made to compute the precondition for t_exit, especially if the precondition to t_inc is available.

The repeat loop does not fit well in the current generic approach. Most of the basic transformers such as t_init, t_skip, t_enter,... are meaningless. Instead of dealing with zero or at least one iteration, we have to deal with one or at least two.

post = (t_body_c ; t_exit)(pre) + (t_body_c ; t_continue ; t_body_star ; t_body_c ; t_exit)(pre)

where we assume that t_body_star includes the continuation condition.

Clean up memory

Parameters
prere
wll
t_body_star_body_star

Definition at line 2760 of file loop.c.

2761 {
2763 
2764  statement body_s = whileloop_body(wl);
2765  transformer t_body = load_statement_transformer(body_s);
2766  transformer t_body_c = complete_statement_transformer(t_body, pre, body_s);
2767  transformer t_init = transformer_identity();
2768  transformer post_init = copy_transformer(pre);
2769  expression cond_e = whileloop_condition(wl);
2770  transformer t_continue = condition_to_transformer(cond_e, transformer_undefined, true);
2772  transformer t_skip = transformer_empty();
2773  //transformer t_skip = transformer_combine(copy_transformer(t_body), t_exit);
2774  transformer t_enter = transformer_identity();
2775  //transformer t_enter = transformer_combine(copy_transformer(t_body), t_continue);
2776  /* An effort could be made to compute the precondition for t_exit,
2777  especially if the precondition to t_inc is available. */
2785 
2786  post = any_loop_to_postcondition(body_s,
2787  t_init,
2788  t_enter,
2789  t_skip,
2790  t_body_star,
2791  t_body_c,
2792  t_continue, //since t_inc is ineffective
2793  t_inc,
2794  t_exit,
2795  pre);
2796 
2797  /* The repeat loop does not fit well in the current generic
2798  * approach. Most of the basic transformers such as t_init, t_skip,
2799  * t_enter,... are meaningless. Instead of dealing with zero or at
2800  * least one iteration, we have to deal with one or at least two.
2801  *
2802  * post = (t_body_c ; t_exit)(pre) +
2803  * (t_body_c ; t_continue ; t_body_star ; t_body_c ; t_exit)(pre)
2804  *
2805  * where we assume that t_body_star includes the continuation condition.
2806  */
2807 
2808  free_transformer(post);
2809 
2810  post_1 = transformer_apply(t_body_c, pre);
2811  post_2 = transformer_apply(t_exit, post_1);
2812 
2813  post_3 = transformer_apply(t_continue, post_1);
2814  post_4 = transformer_apply(t_body_star, post_3);
2815  post_5 = transformer_apply(t_body_c, post_4);
2816  post_6 = transformer_apply(t_exit, post_5);
2817 
2818  post = transformer_convex_hull(post_2, post_6);
2819 
2820  /* Clean up memory */
2821 
2822  free_transformer(t_init);
2823  free_transformer(post_init);
2824  free_transformer(t_skip);
2825  free_transformer(t_enter);
2826  free_transformer(t_continue);
2827  free_transformer(t_exit);
2828  free_transformer(t_inc);
2829  free_transformer(t_body_c);
2830 
2831  free_transformer(post_1);
2832  free_transformer(post_2);
2833  free_transformer(post_3);
2834  free_transformer(post_4);
2835  free_transformer(post_5);
2836  free_transformer(post_6);
2837 
2838  return post;
2839 }

References any_loop_to_postcondition(), complete_statement_transformer(), condition_to_transformer(), copy_transformer(), free_transformer(), load_statement_transformer(), transformer_apply(), transformer_convex_hull(), transformer_empty(), transformer_identity(), transformer_undefined, whileloop_body, and whileloop_condition.

Referenced by instruction_to_postcondition().

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

◆ repeatloop_to_transformer()

transformer repeatloop_to_transformer ( whileloop  wl,
transformer  pre,
list  wlel 
)

effects of whileloop wl

t_body_star = t_init ; t_enter ; (t_body ; t_next)+

t_once = t_body; t_exit

t_repeat = t_body_star + t_once

An effort could be made to compute the precondition for t_continue, especially if the precondition to t_inc is available.

FI: it should be computed with the postcondition of the body

The loop is executed at least twice; FI: I'm note sure the twice is captured

FI: example dowhile02 seems to show this is wrong with t_next empty, in spite of the star

The loop is executed only once

global transformer

Parameters
wll
prere
wlellel

Definition at line 449 of file loop.c.

452 {
453  /* t_body_star = t_init ; t_enter ; (t_body ; t_next)+
454  *
455  * t_once = t_body; t_exit
456  *
457  * t_repeat = t_body_star + t_once
458  */
459  transformer t_body_star = transformer_undefined;
460  statement body_s = whileloop_body(wl);
461  transformer t_body = transformer_undefined; // load_statement_transformer(body_s);
463  expression cond_e = whileloop_condition(wl);
464  transformer t_enter = transformer_identity();
465  /* An effort could be made to compute the precondition for t_continue,
466  especially if the precondition to t_inc is available. */
467  transformer t_continue = condition_to_transformer(cond_e, transformer_undefined, true);
468  /* FI: it should be computed with the postcondition of the body */
470  //transformer t_inc = transformer_identity();
471  transformer t_next = t_continue;
472 
473  /* The loop is executed at least twice; FI: I'm note sure the twice is captured */
474  /* FI: example dowhile02 seems to show this is wrong with t_next
475  empty, in spite of the star */
476  t_body_star = any_loop_to_transformer(t_init, t_enter, t_next, body_s, wlel, pre);
477 
478  /* The loop is executed only once */
479  // any_loop_to_transformer() has computed the body transformer
480  t_body = load_statement_transformer(body_s);
481  transformer t_once = transformer_combine(copy_transformer(t_body), t_exit);
482 
483  /* global transformer */
484  transformer t_repeat = transformer_convex_hull(t_once, t_body_star);
485 
486  // free_transformer(t_once), free_transformer(t_body_star), free_transformer(t_next), free_transformer(t_exit), free_transformer(t_enter);
487 
488  return t_repeat;
489 }

References any_loop_to_transformer(), condition_to_transformer(), copy_transformer(), load_statement_transformer(), transformer_combine(), transformer_convex_hull(), transformer_identity(), transformer_undefined, whileloop_body, and whileloop_condition.

Referenced by whileloop_to_transformer().

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

◆ simple_dead_loop_p()

bool simple_dead_loop_p ( expression  lower,
expression  upper 
)
Parameters
lowerower
upperpper

Definition at line 1028 of file loop.c.

1029 {
1030  bool dead_loop_p = false;
1031  normalized n_lower = NORMALIZE_EXPRESSION(lower);
1032  normalized n_upper = NORMALIZE_EXPRESSION(upper);
1033 
1034  if(normalized_linear_p(n_upper) && normalized_linear_p(n_lower)) {
1035  Pvecteur v_lower = normalized_linear(n_lower);
1036  Pvecteur v_upper = normalized_linear(n_upper);
1037 
1038  if(VECTEUR_NUL_P(v_lower)) {
1039  if (!VECTEUR_NUL_P(v_upper)) {
1040  if(term_cst(v_upper)
1041  && VECTEUR_NUL_P(vecteur_succ(v_upper))) {
1042  dead_loop_p = value_neg_p(vecteur_val(v_upper));
1043  }
1044  }
1045  }
1046  else if(VECTEUR_NUL_P(v_upper)) {
1047  if (!VECTEUR_NUL_P(v_lower)) {
1048  if(term_cst(v_lower)
1049  && VECTEUR_NUL_P(vecteur_succ(v_lower))) {
1050  dead_loop_p = value_pos_p(vecteur_val(v_lower));
1051  }
1052  }
1053  }
1054  else if(term_cst(v_upper) && term_cst(v_lower)
1055  && VECTEUR_NUL_P(vecteur_succ(v_upper))
1056  && VECTEUR_NUL_P(vecteur_succ(v_lower))) {
1057  dead_loop_p =
1058  value_gt(vecteur_val(v_lower),vecteur_val(v_upper));
1059  }
1060  }
1061 
1062  return dead_loop_p;
1063 }
#define value_pos_p(val)
#define value_gt(v1, v2)
#define value_neg_p(val)
#define vecteur_val(v)
#define VECTEUR_NUL_P(v)
#define term_cst(varval)

References NORMALIZE_EXPRESSION, normalized_linear, normalized_linear_p, term_cst, value_gt, value_neg_p, value_pos_p, VECTEUR_NUL_P, vecteur_succ, and vecteur_val.

Referenced by add_index_range_conditions().

+ Here is the caller graph for this function:

◆ standard_whileloop_to_transformer()

transformer standard_whileloop_to_transformer ( whileloop  l,
transformer  pre,
list  e 
)

This function computes the effect of K loop iteration, with K positive.

This function does not take the loop exit into account because its result is used to compute the precondition of the loop body. Hence the loop exit condition only is added when preconditions are computed. This is confusing when transformers are prettyprinted with the source code.

loop transformer tf = tfb* or tf = tfb+ or ...

loop body transformer

Make sure not to leave too much information in pre. Perform a very simplistic fix point based on effects.

If the while entry condition is usable, it must be added on the old values

I'd like to use pre_n as context to evaluate the condition cond, but I'm not sure it's safe (Francois Irigoin)

Side effects in cond are ignored!

compute the whileloop body transformer, including the initial conditions

The convex hull of the image of pre and of the image of tfb can be added as conditions on tfb's domain, if some information is available in pre

compute tfb's fix point according to pips flags

The second clause is probably stronger than the first one

The loop is never entered

Side effects of the condition evaluation should be taken into account

A temporary variable is expected as first argument. There is something to fix.

tf = any_expression_to_transformer();

The loop is never exited, e.g. because there is a STOP or an infinite loop inside

Dirty looking fix for a fix point computation error: sometimes, the basis is restricted to a subset of the integer scalar variables. Should be useless with proper fixpoint opertors.

we have a problem here: to compute preconditions within the whileloop body we need a tf using private variables; to return the loop transformer, we need a filtered out tf; only one hook is available in the ri..; let'a assume there are no private variables and that if they are privatizable they are not going to get in our way

basic cheap version: do not use the whileloop body transformer and avoid fix-points; local variables do not have to be filtered out because this was already done while computing effects

The loop body transformers could benefit from pre_n instead of transformer_undefined, but who would think of combining these two options?

Parameters
prere

Definition at line 2456 of file loop.c.

2459 {
2460  /* loop transformer tf = tfb* or tf = tfb+ or ... */
2461  transformer tf;
2462  /* loop body transformer */
2463  transformer tfb;
2464  expression cond = whileloop_condition(l);
2465  statement s = whileloop_body(l);
2466 
2467  pips_debug(8,"begin\n");
2468 
2471 
2472  if(transformer_undefined_p(pre)) {
2473  pre_n = transformer_identity();
2474  }
2475  else {
2476  /* Make sure not to leave too much information in pre. Perform a very
2477  simplistic fix point based on effects. */
2478  transformer tf_star = effects_to_transformer(e);
2479 
2480  pre_n = invariant_wrt_transformer(pre, tf_star);
2481  free_transformer(tf_star);
2482  }
2483  /* If the while entry condition is usable, it must be added
2484  * on the old values
2485  */
2486  /* I'd like to use pre_n as context to evaluate the condition cond,
2487  but I'm not sure it's safe (Francois Irigoin) */
2488  /* Side effects in cond are ignored! */
2489  pre_n = precondition_add_condition_information(pre_n, cond,
2490  transformer_undefined, true);
2491 
2492  ifdebug(8) {
2493  pips_debug(8, "Precondition for loop body pre_n=\n");
2495  }
2496 
2497  /* compute the whileloop body transformer, including the initial conditions */
2498  tfb = transformer_dup(statement_to_transformer(s, pre_n));
2499 
2500  /* The convex hull of the image of pre and of the image of tfb can be
2501  added as conditions on tfb's domain, if some information is available in pre */
2502  if(!transformer_undefined_p(pre))
2504 
2505  /* compute tfb's fix point according to pips flags */
2508  }
2509  else if ((!transformer_undefined_p(pre)
2510  && condition_false_wrt_precondition_p(cond, pre))
2511  /* The second clause is probably stronger than the first one */
2512  || transformer_empty_p(pre_n)) {
2513  /* The loop is never entered */
2514  /* Side effects of the condition evaluation should be taken into account */
2515  tf = transformer_identity();
2516  /* A temporary variable is expected as first argument. There is something to fix. */
2517  /* tf = any_expression_to_transformer(); */
2518  }
2519  else if(transformer_empty_p(tfb)) {
2520  /* The loop is never exited, e.g. because there is a STOP or an infinite loop inside */
2521  tf = transformer_empty();
2522  }
2523  else {
2524  transformer ftf = (* transformer_fix_point_operator)(tfb);
2525 
2528  Psysteme sc = SC_UNDEFINED;
2529 
2530  /* Dirty looking fix for a fix point computation error:
2531  * sometimes, the basis is restricted to a subset of
2532  * the integer scalar variables. Should be useless with proper
2533  * fixpoint opertors.
2534  */
2535  tf = effects_to_transformer(e);
2537 
2538  sc = sc_append(sc, fsc);
2539 
2540  free_transformer(ftf);
2541  }
2542  else {
2543  tf = ftf;
2544  }
2545 
2546  ifdebug(8) {
2547  pips_debug(8, "intermediate fix-point tf=\n");
2549  }
2550 
2551  }
2552 
2553  free_transformer(pre_n);
2554 
2555  /* we have a problem here: to compute preconditions within the
2556  whileloop body we need a tf using private variables; to return
2557  the loop transformer, we need a filtered out tf; only
2558  one hook is available in the ri..; let'a assume there
2559  are no private variables and that if they are privatizable
2560  they are not going to get in our way */
2561  }
2562  else {
2563  /* basic cheap version: do not use the whileloop body transformer and
2564  avoid fix-points; local variables do not have to be filtered out
2565  because this was already done while computing effects */
2566 
2567  /* The loop body transformers could benefit from pre_n instead of
2568  transformer_undefined, but who would think of combining these
2569  two options? */
2571  tf = effects_to_transformer(e);
2572  }
2573 
2574  ifdebug(8) {
2575  (void) fprintf(stderr,"%s: %s\n","standard_whileloop_to_transformer",
2576  "resultat tf =");
2577  (void) print_transformer(tf);
2578  }
2579  pips_debug(8,"end\n");
2580  return tf;
2581 }
transformer transformer_equality_fix_point(transformer)
Let A be the affine loop transfert function.
Definition: fix_point.c:266
transformer(* transformer_fix_point_operator)(transformer)
Interface between the untyped database manager and clean code and between pipsmake and clean code.
Definition: fix_point.c:114
transformer transformer_halbwachs_fix_point(transformer tf)
Definition: fix_point.c:143
struct Ssysteme * Psysteme
transformer precondition_add_condition_information(transformer pre, expression c, transformer context, bool veracity)
context might be derivable from pre as transformer_range(pre) but this is sometimes very computationa...
Definition: expression.c:1111
static transformer loop_body_transformer_add_entry_and_iteration_information(transformer tfb, transformer pre)
FI: I do not have one test case to show that this function is of some use.
Definition: loop.c:2412
bool transformer_empty_p(transformer t)
If true is returned, the transformer certainly is empty.
Definition: transformer.c:2455

References condition_false_wrt_precondition_p(), effects_to_transformer(), external_value_name(), fprint_transformer(), fprintf(), free_transformer(), ifdebug, invariant_wrt_transformer(), loop_body_transformer_add_entry_and_iteration_information(), pips_debug, pips_flag_p, precondition_add_condition_information(), predicate_system, print_transformer, sc_append(), SEMANTICS_FIX_POINT, SEMANTICS_INEQUALITY_INVARIANT, statement_to_transformer(), transformer_dup(), transformer_empty(), transformer_empty_p(), transformer_equality_fix_point(), transformer_fix_point_operator, transformer_halbwachs_fix_point(), transformer_identity(), transformer_relation, transformer_undefined, transformer_undefined_p, whileloop_body, and whileloop_condition.

+ Here is the call graph for this function:

◆ transformer_add_loop_index_incrementation()

transformer transformer_add_loop_index_incrementation ( transformer  tf,
loop  l,
transformer  pre 
)

SHOULD BE REWRITTEN WITH EXPRESSION_TO_TRANSFORMER

it does not contain the loop index update the loop increment expression must be linear to find inductive variables related to the loop index

Parameters
tff
prere

Definition at line 1136 of file loop.c.

1139 {
1140  entity i = loop_index(l);
1141  range r = loop_range(l);
1142  expression incr = range_increment(r);
1143  Pvecteur v_incr = VECTEUR_UNDEFINED;
1144 
1145  /* SHOULD BE REWRITTEN WITH EXPRESSION_TO_TRANSFORMER */
1146 
1147  pips_assert("To please the compiler", pre==pre);
1148 
1149  pips_assert("Transformer tf is consistent before update",
1151 
1152  /* it does not contain the loop index update the loop increment
1153  expression must be linear to find inductive variables related to
1154  the loop index */
1155  if(!VECTEUR_UNDEFINED_P(v_incr = expression_to_affine(incr))) {
1156  if(entity_has_values_p(i)) {
1158  tf = transformer_add_variable_incrementation(tf, i, v_incr);
1159  }
1160  else {
1161  entity i_old = entity_to_old_value(i);
1162  entity i_new = entity_to_new_value(i);
1164  Pbase b = sc_base(sc);
1165 
1167  b = base_add_variable(b, (Variable) i_old);
1168  b = base_add_variable(b, (Variable) i_new);
1169  sc_base(sc) = b;
1170  sc_dimension(sc) = base_dimension(sc_base(sc));
1171  }
1172  }
1173  else {
1174  pips_user_warning("non-integer or equivalenced loop index %s?\n",
1175  entity_local_name(i));
1176  }
1177  }
1178  else {
1179  if(entity_has_values_p(i)) {
1180  entity i_old = entity_to_old_value(i);
1181  entity i_new = entity_to_new_value(i);
1183  Pbase b = sc_base(sc);
1184 
1186  b = base_add_variable(b, (Variable) i_old);
1187  b = base_add_variable(b, (Variable) i_new);
1188  sc_base(sc) = b;
1189  sc_dimension(sc) = base_dimension(sc_base(sc));
1190  }
1191  }
1192 
1193  pips_assert("Transformer tf is consistent after update",
1195 
1196  return tf;
1197 }
Pbase base_add_variable(Pbase b, Variable var)
Pbase base_add_variable(Pbase b, Variable v): add variable v as a new dimension to basis b at the end...
Definition: base.c:88
transformer transformer_add_variable_incrementation(transformer t, entity i, Pvecteur incr)
transformer transformer_add_loop_index(transformer t, entity i, Pvecteur incr): add the index increme...
Definition: basic.c:260
#define pips_user_warning
Definition: misc-local.h:146
Pvecteur expression_to_affine(expression e)
Definition: normalize.c:461
entity entity_to_old_value(entity)
Definition: value.c:869
#define base_dimension(b)
#define VECTEUR_UNDEFINED_P(v)

References arguments_add_entity(), base_add_variable(), base_dimension, entity_has_values_p(), entity_local_name(), entity_to_new_value(), entity_to_old_value(), expression_to_affine(), loop_index, loop_range, pips_assert, pips_user_warning, predicate_system, range_increment, transformer_add_variable_incrementation(), transformer_arguments, transformer_consistency_p(), transformer_relation, value_mappings_compatible_vector_p(), VECTEUR_UNDEFINED, and VECTEUR_UNDEFINED_P.

Referenced by loop_to_continue_transformer(), loop_to_total_precondition(), loop_to_transformer(), and recompute_loop_transformer().

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

◆ transformer_add_loop_index_initialization()

transformer transformer_add_loop_index_initialization ( transformer  tf,
loop  l,
transformer  pre 
)

The loop initialization is performed before tf.

EXPRESSION_TO_TRANSFORMER SHOULD BE USED

The new variables in eq must be added to sc; otherwise, further consistency checks core dump. bc.

sc_add_egalite(sc, eq);

The call to sc_projection_with_eq frees eq

FI: a NULL is not acceptable; I assume that we cannot end up with a SC_EMPTY...

Get rid of the initial value since it is unknowable

Parameters
tff
prere

Definition at line 1082 of file loop.c.

1085 {
1086  entity i = loop_index(l);
1087  range r = loop_range(l);
1089 
1090  /* EXPRESSION_TO_TRANSFORMER SHOULD BE USED */
1091  pips_assert("To please the compiler", pre==pre);
1092 
1093  if(entity_has_values_p(i) && normalized_linear_p(nlb)) {
1096  Pvecteur v_lb = vect_dup(normalized_linear(nlb));
1097  Pbase b_tmp, b_lb = make_base_from_vect(v_lb);
1098  entity i_init = entity_to_old_value(i);
1099 
1100  vect_add_elem(&v_lb, (Variable) i_init, VALUE_MONE);
1101  eq = contrainte_make(v_lb);
1102  /* The new variables in eq must be added to sc; otherwise,
1103  * further consistency checks core dump. bc.
1104  */
1105  /* sc_add_egalite(sc, eq); */
1106  /* The call to sc_projection_with_eq frees eq */
1107  sc = sc_projection_by_eq(sc, eq, (Variable) i_init);
1108  b_tmp = sc_base(sc);
1109  sc_base(sc) = base_union(b_tmp, b_lb);
1110  sc_dimension(sc) = base_dimension(sc_base(sc));
1111  base_rm(b_tmp);
1112  base_rm(b_lb);
1113  if(SC_RN_P(sc)) {
1114  /* FI: a NULL is not acceptable; I assume that we cannot
1115  * end up with a SC_EMPTY...
1116  */
1120  }
1121  else
1123  newgen_Psysteme(sc);
1124  }
1125  else if(entity_has_values_p(i)) {
1126  /* Get rid of the initial value since it is unknowable */
1127  entity i_init = entity_to_old_value(i);
1128  list l_i_init = CONS(ENTITY, i_init, NIL);
1129 
1130  tf = transformer_projection(tf, l_i_init);
1131  }
1132 
1133 return tf;
1134 }
Pbase make_base_from_vect(Pvecteur pv)
Definition: base.c:109
Pbase base_union(Pbase b1, Pbase b2)
Pbase base_union(Pbase b1, Pbase b2): compute a new basis containing all elements of b1 and all eleme...
Definition: base.c:428
#define CONTRAINTE_UNDEFINED
Pcontrainte contrainte_make(Pvecteur pv)
Pcontrainte contrainte_make(Pvecteur pv): allocation et initialisation d'une contrainte avec un vecte...
Definition: alloc.c:73
#define newgen_Psysteme(p)
Definition: effects.h:47
#define predicate_system_(x)
Definition: ri.h:2068
Psysteme sc_make(Pcontrainte leg, Pcontrainte lineg)
Psysteme sc_make(Pcontrainte leg, Pcontrainte lineg): allocation et initialisation d'un systeme d'equ...
Definition: sc.c:78
Pcontrainte eq
element du vecteur colonne du systeme donne par l'analyse
Definition: sc_gram.c:108
#define base_rm(b)

References base_dimension, base_rm, base_union(), CONS, contrainte_make(), CONTRAINTE_UNDEFINED, ENTITY, entity_has_values_p(), entity_to_old_value(), eq, loop_index, loop_range, make_base_from_vect(), newgen_Psysteme, NIL, NORMALIZE_EXPRESSION, normalized_linear, normalized_linear_p, pips_assert, predicate_system, predicate_system_, range_lower, sc_make(), transformer_projection(), transformer_relation, VALUE_MONE, vect_add_elem(), and vect_dup().

Referenced by recompute_loop_transformer().

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

◆ whileloop_to_k_transformer()

transformer whileloop_to_k_transformer ( whileloop  l,
transformer  pre,
list  e,
int  k 
)
Parameters
prere
keffects of whileloop l

Definition at line 2617 of file loop.c.

2622 {
2625 
2626  if(evaluation_before_p(lt))
2627  t = new_whileloop_to_k_transformer(l, pre, e, k);
2628  else
2629  pips_internal_error("repeatloop_to_k_transformer() not implemented.");
2630  //t = repeatloop_to_k_transformer(l, pre, e);
2631  return t;
2632 }
transformer new_whileloop_to_k_transformer(whileloop wl, transformer pre, list wlel, int k)
Definition: loop.c:416

References evaluation_before_p, new_whileloop_to_k_transformer(), pips_internal_error, transformer_undefined, and whileloop_evaluation.

Referenced by whileloop_to_postcondition().

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

◆ whileloop_to_postcondition()

transformer whileloop_to_postcondition ( transformer  pre,
whileloop  l,
transformer  tf 
)

propagate an impossible precondition in the loop body

do not add the exit condition since it is redundant with pre, but take care of side effects in the condition c

transformer_apply() generates a lot of warnings

The loop may be entered at least once.

The standard transformer tb is not enough, especially if the loop body s is a loop since then it is not even the statement transformer, but more generally we do not want the identity to be taken into account in tb since it is already added with P0. So we would like to guarantee that at least one state change occurs: we are not interested in identity iterations. For instance, if s is a loop, this means that the loop is entered, except if the loop condition has side effects.

To recompute this transformer, we use a pre_fuzzy=T*(P0) because we have nothing better.

complete_statement_transformer() is not really useful here because we usually do not have tighly nested while loops.

Nothing special in the loop body: no tests, no while,...

Recompute the body transformer without taking identity transformers into account. This is not enough because the decision about "activity" should be made dimension by dimension. We cannot get good result in general with a convex hull performed here: only specific cases are handled. We need instead a complex formulae to compute the loop precondition as a function of p_0 and all t_i

btl is copied because the function below frees at least its components

The loop fix point transformer T* could be used to obtain the set of stores for any number of iterations, including 0. Instead, use T+ and a convex hull with the precondition for the first iteration, which preserves more information when the fixpoint is not precise:

P^* = P_0 U cond(c)(tb(cond(c)(tb^*(P_0))))

Bertrand Jeannet suggests that we compute P0 U T(P0) U T^2(P0) U T_3(P0) where T_3 is the transitive closure obtained for iterations 3 to infinity by setting the initial iteration number k to 3 before projection. NSAD 2010. No test case has been forwarded to show that this would be useful.

We need the loop effects to recompute the unrolled transformer. Let's use NIL to start with... disaster. Let's use the body effects and hope for no side effects in loop condition.

FI: since pre_next is no longer useful, pre_next2 could be avoided. It just makes debugging easier.

propagate preconditions in the loop body and get its postcondition

At least one iteration is executed. The postcondition can be computed into three different ways:

  • use the loop body postcondition and apply the loop exit condition transformer or precondition_add_condition_information;
  • or use the loop precondition, the loop transformer, the loop entry condition, the loop body transformer and the loop exit transformer;

or use both and use their intersection as unique postcondition (the added redundant information seems to result in less information after a projection for w09.f, Halbwachs car example).

The second way is more likely to suffer from non-convexity as it uses many more steps.

Also, note that precondition_add_condition_information() is more geared towards Fortran as it assumes no side effects in the condition evaluation. However, it is better at handling non-convex condition than condition_to_transformer(), but condition_to_transformer(), which is built on top of precondition_add_condition_information() could be improved/might be improvable... In case the condition is not convex, there is no single transformer which fits it. But the postcondition can be updated with different convex components and then different results united in a unique postcondition by a convex hull.

Let's execute the last iteration since it certainly exists

Assume the loop is entered, post_al, or not, post_ne, and perform the convex hull of both

The loop is executed at least once: let's execute the last iteration

The loop is never executed

Parameters
prere
tff

Definition at line 3141 of file loop.c.

3145 {
3147  statement s = whileloop_body(l);
3149 
3150  pips_debug(8, "begin\n");
3151 
3154  pips_internal_error("Halbwachs not implemented");
3155  }
3156 
3158  transformer c_t = condition_to_transformer(c, pre, false);
3159  pips_debug(8, "The loop is never executed\n");
3160 
3161  /* propagate an impossible precondition in the loop body */
3163  /* do not add the exit condition since it is redundant with pre,
3164  but take care of side effects in the condition c */
3165  /* transformer_apply() generates a lot of warnings */
3166  post = transformer_combine(copy_transformer(pre), c_t);
3167  //post = transformer_apply(c_t, pre);
3168  free_transformer(c_t);
3169  }
3170  else { /* The loop may be entered at least once. */
3171  transformer pre_next = transformer_dup(pre);
3172  transformer pre_init =
3174  c, pre, true);
3175  // FI: this should work but is not compatible with the following
3176  //code; by definition, tf also include the side effect of pre
3177  //transformer pre_init = transformer_apply(c_t, pre);
3178  transformer preb = transformer_undefined; // body precondition
3179  transformer postb = transformer_undefined; // body postcondition
3180  transformer tb = load_statement_transformer(s); // body transformer
3181  int k = get_int_property("SEMANTICS_K_FIX_POINT");
3182 
3183  /* The standard transformer tb is not enough, especially if the
3184  loop body s is a loop since then it is not even the statement
3185  transformer, but more generally we do not want the identity to
3186  be taken into account in tb since it is already added with
3187  P0. So we would like to guarantee that at least one state change
3188  occurs: we are not interested in identity iterations. For
3189  instance, if s is a loop, this means that the loop is entered,
3190  except if the loop condition has side effects.
3191 
3192  To recompute this transformer, we use a pre_fuzzy=T*(P0)
3193  because we have nothing better.
3194 
3195  complete_statement_transformer() is not really useful here
3196  because we usually do not have tighly nested while loops.
3197  */
3198  transformer pre_fuzzy = transformer_apply(tf, pre);
3199  //tb = complete_non_identity_statement_transformer(tb, pre_fuzzy, s);
3200  list btl = list_undefined;
3201  int fbtll = 0;
3202 
3203  if(get_bool_property("SEMANTICS_USE_TRANSFORMER_LISTS")) {
3204  list fbtl = statement_to_transformer_list(s, pre_fuzzy);
3205  fbtll = (int) gen_length(fbtl);
3206  // filter out transformers that do not modify the state
3207  // FI: this is not a general approach since it depends on the
3208  // framework used and on the other variables, but it helps!
3210  gen_full_free_list(fbtl);
3211 
3212  if(gen_length(btl)==0) {
3214  }
3215  else if(gen_length(btl)==1) {
3216  /* Nothing special in the loop body: no tests, no while,... */
3217  if(fbtll==1)
3218  tb = complete_statement_transformer(tb, pre_fuzzy, s);
3219  else
3220  // FI: not to sure about reuse and memory leaks...
3221  tb = copy_transformer(TRANSFORMER(CAR(btl)));
3222  }
3223  else {
3224  /* Recompute the body transformer without taking identity
3225  transformers into account. This is not enough because the
3226  decision about "activity" should be made dimension by
3227  dimension. We cannot get good result in general with a
3228  convex hull performed here: only specific cases are
3229  handled. We need instead a complex formulae to compute the
3230  loop precondition as a function of p_0 and all t_i*/
3231  /* btl is copied because the function below frees at least
3232  its components */
3234  }
3235  }
3236  else {
3237  tb = complete_statement_transformer(tb, pre_fuzzy, s);
3238  }
3239 
3240  pips_debug(8, "The loop may be executed and preconditions must"
3241  " be propagated in the loop body\n");
3242 
3243  if(k==1) {
3244  if(!get_bool_property("SEMANTICS_USE_TRANSFORMER_LISTS")
3245  || gen_length(btl)==1) {
3246  /* The loop fix point transformer T* could be used to obtain the
3247  * set of stores for any number of iterations, including
3248  * 0. Instead, use T+ and a convex hull with the precondition for
3249  * the first iteration, which preserves more information when the
3250  * fixpoint is not precise:
3251  *
3252  * P^* = P_0 U cond(c)(tb(cond(c)(tb^*(P_0))))
3253  *
3254  * Bertrand Jeannet suggests that we compute P0 U T(P0) U
3255  * T^2(P0) U T_3(P0) where T_3 is the transitive closure
3256  * obtained for iterations 3 to infinity by setting the initial
3257  * iteration number k to 3 before projection. NSAD 2010. No test
3258  * case has been forwarded to show that this would be useful.
3259  */
3260  // FI: I do not know why pre_next==pre is used instead of
3261  // pre_init==P_0 in the statement just below
3262  pre_next = transformer_combine(pre_next, tf);
3263  pre_next = precondition_add_condition_information(pre_next, c,
3264  pre_next, true);
3265  pre_next = transformer_combine(pre_next, tb);
3266  pre_next = precondition_add_condition_information(pre_next, c,
3267  pre_next, true);
3268  preb = transformer_convex_hull(pre_init, pre_next);
3269  }
3270  else { // transformer lists are used and at least two
3271  // transformers have been found
3272  transformer c_t = condition_to_transformer(c, pre_fuzzy, true);
3273  //transformer preb1 = transformer_list_closure_to_precondition(btl, c_t, pre_init);
3275  //pre_next = transformer_combine(pre_next, tf);
3276  //pre_next = precondition_add_condition_information(pre_next, c,
3277  // pre_next, true);
3278  //pre_next = transformer_combine(pre_next, tb);
3279  //pre_next = precondition_add_condition_information(pre_next, c,
3280  // pre_next, true);
3281  //transformer preb2 = transformer_convex_hull(pre_init, pre_next);
3282  //pips_assert("The two preconditions have the same arguments",
3283  // arguments_equal_p(transformer_arguments(preb1),
3284  // transformer_arguments(preb2)));
3285  // FI: the intersection generates overflows
3286  //preb = transformer_intersection(preb1, preb2);
3287  preb = preb1;
3288  }
3289  }
3290  else if (k==2) {
3291  /* We need the loop effects to recompute the unrolled
3292  transformer. Let's use NIL to start with... disaster.
3293  Let's use the body effects and hope for no side effects in
3294  loop condition.
3295  */
3296  list bel = load_cumulated_rw_effects_list(s); // Should be lel
3297  transformer tf2 = whileloop_to_k_transformer(l, pre, bel, 2);
3298  transformer pre_next2 = transformer_undefined;
3299  pre_next = transformer_combine(pre_next, tf2);
3300  pre_next = precondition_add_condition_information(pre_next, c,
3301  pre_next, true);
3302  pre_next = transformer_combine(pre_next, tb);
3303  pre_next = precondition_add_condition_information(pre_next, c,
3304  pre_next, true);
3305  preb = transformer_convex_hull(pre_init, pre_next);
3306 
3307  /* FI: since pre_next is no longer useful, pre_next2 could be
3308  avoided. It just makes debugging easier. */
3309  pre_next2 = copy_transformer(pre_next);
3310  pre_next2 = precondition_add_condition_information(pre_next2, c,
3311  pre_next2, true);
3312  pre_next2 = transformer_combine(pre_next2, tb);
3313  pre_next2 = precondition_add_condition_information(pre_next2, c,
3314  pre_next2, true);
3315  preb = transformer_convex_hull(preb, pre_next2);
3316  free_transformer(tf2);
3317  free_transformer(pre_next2);
3318  }
3319  else
3320  pips_user_error("Unexpected value %d for k.\n", k);
3321 
3322  free_transformer(pre_fuzzy);
3323 
3324  /* propagate preconditions in the loop body and get its postcondition */
3325 
3326  postb = statement_to_postcondition(preb, s);
3327 
3328  if(true_condition_wrt_precondition_p(c, pre)) {
3329  /* At least one iteration is executed. The postcondition can be
3330  * computed into three different ways:
3331  *
3332  * - use the loop body postcondition and apply the loop exit
3333  * condition transformer or precondition_add_condition_information;
3334  *
3335  * - or use the loop precondition, the loop transformer, the loop
3336  * entry condition, the loop body transformer and the loop exit
3337  * transformer;
3338  *
3339  * - or use both and use their intersection as unique
3340  * postcondition (the added redundant information seems to
3341  * result in *less* information after a projection for w09.f,
3342  * Halbwachs car example).
3343  *
3344  * The second way is more likely to suffer from non-convexity as
3345  * it uses many more steps.
3346  *
3347  * Also, note that precondition_add_condition_information() is
3348  * more geared towards Fortran as it assumes no side effects in
3349  * the condition evaluation. However, it is better at handling
3350  * non-convex condition than condition_to_transformer(), but
3351  * condition_to_transformer(), which is built on top of
3352  * precondition_add_condition_information() could be
3353  * improved/might be improvable... In case the condition is not
3354  * convex, there is no single transformer which fits it. But the
3355  * postcondition can be updated with different convex components
3356  * and then different results united in a unique postcondition
3357  * by a convex hull.
3358  */
3359 
3360  pips_debug(8, "The loop certainly is executed.\n");
3361 
3362  if(false) {
3364  transformer cpost = transformer_undefined; // combined postcondition
3365  ntl = transformer_apply(tf, pre);
3366  /* Let's execute the last iteration since it certainly exists */
3367  ntl = precondition_add_condition_information(ntl, c, ntl, true);
3368  post = transformer_apply(tb, ntl);
3369  free_transformer(ntl);
3370  post = precondition_add_condition_information(post, c, post, false);
3371 
3372  postb = precondition_add_condition_information(postb, c, postb, false);
3373 
3374  cpost = transformer_intersection(post, postb);
3375 
3376  free_transformer(post);
3377  free_transformer(postb);
3378 
3379  post = cpost;
3380  }
3381  else {
3382  // FI: does not work with side effects
3383  //post = precondition_add_condition_information(postb, c, postb, false);
3384  transformer pre_c = transformer_range(postb);
3385  transformer ctf = condition_to_transformer(c, pre_c, false);
3386  post = transformer_apply(ctf, postb);
3387  free_transformer(pre_c);
3388  free_transformer(ctf);
3389  }
3390  }
3391  else {
3392  /* Assume the loop is entered, post_al, or not, post_ne, and perform
3393  * the convex hull of both
3394  */
3395  transformer post_ne = transformer_dup(pre);
3397  //transformer tb = load_statement_transformer(s);
3398 
3399  pips_debug(8, "The loop may be executed or not\n");
3400 
3401  /* The loop is executed at least once: let's execute the last iteration */
3402  //post_al = transformer_apply(tb, preb);
3403 
3404  // FI: does not work with side effects
3405  //post = precondition_add_condition_information(postb, c, postb, false);
3406  transformer pre_c = transformer_range(postb);
3407  transformer ctf = condition_to_transformer(c, pre_c, false);
3408  // Mmeory leak? Do we still need postb?
3409  post_al = transformer_apply(ctf, postb);
3410  free_transformer(pre_c);
3411  free_transformer(ctf);
3412  // post_al = precondition_add_condition_information(postb, c, postb, false);
3413 
3414  /* The loop is never executed */
3415  // FI: does not work with side effects
3416  // post_ne = precondition_add_condition_information(post_ne, c, post_ne, false);
3417  pre_c = transformer_range(post_ne);
3418  ctf = condition_to_transformer(c, pre_c, false);
3419  // Mmeory leak
3420  post_ne = transformer_apply(ctf, post_ne);
3421  free_transformer(pre_c);
3422  free_transformer(ctf);
3423 
3424  post = transformer_convex_hull(post_ne, post_al);
3425  // free for postb too? hidden within post_al?
3426  transformer_free(post_ne);
3427  transformer_free(post_al);
3428  }
3429  }
3430 
3431  ifdebug(8) {
3432  pips_debug(8, "resultat post =");
3433  (void) print_transformer(post);
3434  }
3435  pips_debug(8, "end\n");
3436  return post;
3437 }
int get_int_property(const string)
void const char const char const int
transformer empty_transformer(transformer t)
Do not allocate an empty transformer, but transform an allocated transformer into an empty_transforme...
Definition: basic.c:144
void gen_full_free_list(list l)
Definition: genClib.c:1023
size_t gen_length(const list l)
Definition: list.c:150
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
#define TRANSFORMER(x)
TRANSFORMER.
Definition: ri.h:2841
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 false_condition_wrt_precondition_p(expression c, transformer pre)
Definition: expression.c:5891
bool true_condition_wrt_precondition_p(expression c, transformer pre)
Definition: expression.c:5900
transformer whileloop_to_k_transformer(whileloop l, transformer pre, list e, int k)
Definition: loop.c:2617
transformer transformer_list_multiple_closure_to_precondition(list, transformer, transformer)
When some variables are not modified by some transformers, use projections on subsets to increase the...
list transformer_list_to_active_transformer_list(list)
transformer active_transformer_list_to_transformer(list)
Reduce the sublist of active transformers in the transformer list ltl to one transformer using the co...

References active_transformer_list_to_transformer(), CAR, complete_statement_transformer(), condition_to_transformer(), copy_transformer(), empty_transformer(), false_condition_wrt_precondition_p(), free_transformer(), gen_full_copy_list(), gen_full_free_list(), gen_length(), get_bool_property(), get_int_property(), ifdebug, int, list_undefined, load_cumulated_rw_effects_list(), load_statement_transformer(), pips_debug, pips_flag_p, pips_internal_error, pips_user_error, precondition_add_condition_information(), print_transformer, SEMANTICS_FIX_POINT, SEMANTICS_INEQUALITY_INVARIANT, statement_to_postcondition(), statement_to_transformer_list(), TRANSFORMER, transformer_apply(), transformer_combine(), transformer_convex_hull(), transformer_dup(), transformer_empty(), transformer_free(), transformer_identity(), transformer_intersection(), transformer_list_multiple_closure_to_precondition(), transformer_list_to_active_transformer_list(), transformer_range(), transformer_undefined, true_condition_wrt_precondition_p(), whileloop_body, whileloop_condition, and whileloop_to_k_transformer().

Referenced by instruction_to_postcondition().

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

◆ whileloop_to_total_precondition()

transformer whileloop_to_total_precondition ( transformer  t_post,
whileloop  l,
transformer  tf,
transformer  context 
)

transformer_dup(pre)

Apply the loop fix point transformer T* to obtain the set of stores for any number of iteration, including 0.

propagate an impossible precondition in the loop body

The loop body precondition is not useful any longer

do not add the exit condition since it is redundant with pre

post = transformer_dup(pre);

At least one iteration is executed. The transformer of the loop body is not useful!

transformer tb = load_statement_transformer(s);

propagate preconditions in the loop body

ntl = transformer_apply(tf, pre);

Let's execute the last iteration since it certainly exists

post = transformer_apply(tb, ntl);

post = precondition_add_condition_information(post, c, post, false);

Assume the loop is entered, post_al, or not, post_ne, and perform the convex hull of both

= transformer_dup(pre)

propagate preconditions in the loop body

The loop is executed at least once: let's execute the last iteration

The loop is never executed

post = transformer_convex_hull(post_ne, post_al);

Parameters
t_post_post
tff
contextontext

Definition at line 3439 of file loop.c.

3444 {
3446  statement s = whileloop_body(l);
3448 
3449  pips_assert("not implemented yet", false && t_post==t_post);
3450 
3451  pips_debug(8,"begin\n");
3452 
3454  pips_internal_error("Halbwachs not implemented");
3455  }
3456  else {
3457  transformer preb = transformer_undefined /*= transformer_dup(pre)*/ ;
3458 
3459  /* Apply the loop fix point transformer T* to obtain the set of stores
3460  * for any number of iteration, including 0.
3461  */
3462  preb = transformer_combine(preb, tf);
3463 
3465  pips_debug(8, "The loop is never executed\n");
3466 
3467  /* propagate an impossible precondition in the loop body */
3469  /* The loop body precondition is not useful any longer */
3470  free_transformer(preb);
3471  /* do not add the exit condition since it is redundant with pre */
3472  /* post = transformer_dup(pre); */
3473  }
3475  /* At least one iteration is executed. The transformer of
3476  * the loop body is not useful!
3477  */
3478  /* transformer tb = load_statement_transformer(s); */
3480 
3481  pips_debug(8, "The loop certainly is executed\n");
3482 
3483  /* propagate preconditions in the loop body */
3484  preb = precondition_add_condition_information(preb, c, preb, true);
3485  (void) statement_to_postcondition(preb, s);
3486 
3487  /* ntl = transformer_apply(tf, pre); */
3488  /* Let's execute the last iteration since it certainly exists */
3489  ntl = precondition_add_condition_information(ntl, c, ntl, true);
3490  /* post = transformer_apply(tb, ntl); */
3491  free_transformer(ntl);
3492  /* post = precondition_add_condition_information(post, c, post, false); */
3493  }
3494  else {
3495  /* Assume the loop is entered, post_al, or not, post_ne, and perform
3496  * the convex hull of both
3497  */
3498  transformer post_ne = transformer_undefined /* = transformer_dup(pre) */ ;
3501 
3502  pips_debug(8, "The loop may be executed or not\n");
3503 
3504  /* propagate preconditions in the loop body */
3505  precondition_add_condition_information(preb, c, preb, true);
3506  (void) statement_to_postcondition(preb, s);
3507 
3508  /* The loop is executed at least once: let's execute the last iteration */
3509  post_al = transformer_apply(tb, preb);
3510  post_al = precondition_add_condition_information(post_al, c, post_al, false);
3511 
3512  /* The loop is never executed */
3513  post_ne = precondition_add_condition_information(post_ne, c, post_ne, false);
3514 
3515  /* post = transformer_convex_hull(post_ne, post_al); */
3516  transformer_free(post_ne);
3517  transformer_free(post_al);
3518  }
3519  }
3520 
3521  ifdebug(8) {
3522  pips_debug(8, "resultat t_pre=%p\n", t_pre);
3523  (void) print_transformer(t_pre);
3524  pips_debug(8,"end\n");
3525  }
3526 
3527  return t_pre;
3528 }

References false_condition_wrt_precondition_p(), free_transformer(), ifdebug, load_statement_transformer(), pips_assert, pips_debug, pips_flag_p, pips_internal_error, precondition_add_condition_information(), print_transformer, SEMANTICS_FIX_POINT, SEMANTICS_INEQUALITY_INVARIANT, statement_to_postcondition(), transformer_apply(), transformer_combine(), transformer_empty(), transformer_free(), transformer_undefined, true_condition_wrt_precondition_p(), whileloop_body, and whileloop_condition.

Referenced by instruction_to_total_precondition().

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

◆ whileloop_to_transformer()

transformer whileloop_to_transformer ( whileloop  l,
transformer  pre,
list  e 
)

effects of whileloop l

Parameters
prere

Definition at line 2583 of file loop.c.

2586 {
2589 
2590  if(evaluation_before_p(lt))
2591  t = new_whileloop_to_transformer(l, pre, e);
2592  else
2593  t = repeatloop_to_transformer(l, pre, e);
2594  return t;
2595 }
transformer repeatloop_to_transformer(whileloop wl, transformer pre, list wlel)
effects of whileloop wl
Definition: loop.c:449
transformer new_whileloop_to_transformer(whileloop wl, transformer pre, list wlel)
effects of whileloop wl
Definition: loop.c:380

References evaluation_before_p, new_whileloop_to_transformer(), repeatloop_to_transformer(), transformer_undefined, and whileloop_evaluation.

Referenced by instruction_to_transformer().

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