PIPS
array_bound_check_top_down.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "genC.h"
#include "linear.h"
#include "ri.h"
#include "effects.h"
#include "alias_private.h"
#include "ri-util.h"
#include "prettyprint.h"
#include "effects-util.h"
#include "database.h"
#include "pipsdbm.h"
#include "resources.h"
#include "misc.h"
#include "control.h"
#include "transformer.h"
#include "properties.h"
#include "pipsmake.h"
#include "instrumentation.h"
#include "abc_private.h"
#include "effects-generic.h"
#include "effects-convex.h"
#include "effects-simple.h"
#include "conversion.h"
+ Include dependency graph for array_bound_check_top_down.c:

Go to the source code of this file.

Data Structures

struct  top_down_abc_context_t
 The following data structure is the context of top_down_abc: The read_marked_list marks if one bound of one array's dimension is tested or not, for the READ regions. More...
 
struct  Bound_test
 

Typedefs

typedef struct top_down_abc_context_ttop_down_abc_context_p
 
typedef struct Bound_test Bound_test
 

Functions

static string read_or_write (bool a)
 
string bool_to_bound (bool b)
 array_bound_check_top_down.c More...
 
static void initialize_top_down_abc_statistics ()
 
static void display_top_down_abc_statistics ()
 
static abc_checked initiliaze_marked_list ()
 
static void set_array_dimension_checked (top_down_abc_context_p context, bool action, entity array, int dim, bool bound)
 
static Psysteme my_system_remove_variables (Psysteme ps)
 
static void top_down_abc_insert_before_statement (statement s, statement s1, top_down_abc_context_p context)
 
static list top_down_abc_call (call c, entity array, dimension dim_i, int i, bool bound)
 
static Bound_test top_down_abc_not_exact_case (statement s, top_down_abc_context_p context, bool action, entity array, dimension dim_i, int i, bool bound)
 
static Bound_test top_down_abc_dimension (statement s, top_down_abc_context_p context, region re, bool action, entity array, int i, bool bound)
 
static bool max_statement_write_flt (statement s)
 
static int maximum_ordering (entity a, statement s)
 search for the maximum ordering of statement (after s) that writes on a More...
 
static bool min_statement_write_flt (statement s)
 
static int minimum_ordering (entity a, statement s)
 search for the minimum ordering of statement (after s) that writes on a More...
 
static bool is_first_written_array_p (entity a, list l, statement s)
 
static entity find_first_written_array (list l, statement s)
 
static void top_down_abc_array (entity array, region re, statement s, top_down_abc_context_p context)
 
static bool top_down_abc_flt (statement s, top_down_abc_context_p context)
 The old algorithm is false in the case of incorrect code, because regions are computed with the assumption that the code is correct. More...
 
static void top_down_abc_rwt (statement s, top_down_abc_context_p context)
 
static bool store_mapping (control c, top_down_abc_context_p context)
 
static bool push_uns (unstructured u, top_down_abc_context_p context)
 
static void pop_uns (unstructured __attribute__((unused)) u, top_down_abc_context_p context)
 
static void top_down_abc_statement (statement module_statement)
 
bool array_bound_check_top_down (const char *module_name)
 

Variables

static int number_of_added_tests
 Statistic variables: More...
 
static int number_of_bound_violations
 
static entity current_entity = entity_undefined
 
static int current_max
 
static int current_min = 0
 
static statement test_sequence = statement_undefined
 
static bool godown = false
 
static list lexp = NIL
 

Typedef Documentation

◆ Bound_test

typedef struct Bound_test Bound_test

◆ top_down_abc_context_p

Function Documentation

◆ array_bound_check_top_down()

bool array_bound_check_top_down ( const char *  module_name)

set and get the current properties concerning regions

Get the code of the module.

Get the READ and WRITE regions of the module

Reorder the module, because the bound checks have been added

Parameters
module_nameodule_name

Definition at line 1129 of file array_bound_check_top_down.c.

1130 {
1134  "MUST_REGIONS"))
1135  pips_user_warning("\n MUST REGIONS not selected - "
1136  "\n Do not expect wonderful results\n");
1137  /* set and get the current properties concerning regions */
1138  set_bool_property("MUST_REGIONS", true);
1139  set_bool_property("EXACT_REGIONS", true);
1141  /* Get the code of the module. */
1143  module_name,
1144  true);
1147  /* Get the READ and WRITE regions of the module */
1149  db_get_memory_resource(DBR_REGIONS, module_name, true));
1151  db_get_memory_resource(DBR_PROPER_EFFECTS,
1152  module_name,true));
1153  debug_on("ARRAY_BOUND_CHECK_TOP_DOWN_DEBUG_LEVEL");
1154  pips_debug(1, " Region based ABC, Begin for %s\n", module_name);
1155  pips_assert("Statement is consistent ...",
1160  /* Reorder the module, because the bound checks have been added */
1162  pips_debug(1, "end\n");
1163  debug_off();
1169  reset_rw_effects();
1170  return true;
1171 }
bool statement_consistent_p(statement p)
Definition: ri.c:2195
static statement module_statement
Definition: alias_check.c:125
static void display_top_down_abc_statistics()
static void top_down_abc_statement(statement module_statement)
static void initialize_top_down_abc_statistics()
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
void get_regions_properties(void)
void set_rw_effects(statement_effects)
void reset_proper_rw_effects(void)
void set_proper_rw_effects(statement_effects)
void reset_rw_effects(void)
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
void reset_current_module_statement(void)
Reset the current module statement.
Definition: static.c:221
statement set_current_module_statement(statement)
Set the current module statement.
Definition: static.c:165
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
string db_get_memory_resource(const char *rname, const char *oname, bool pure)
Return the pointer to the resource, whatever it is.
Definition: database.c:755
#define DB_PUT_MEMORY_RESOURCE(res_name, own_name, res_val)
conform to old interface.
Definition: pipsdbm-local.h:66
#define rule_phase(x)
Definition: makefile.h:244
#define debug_on(env)
Definition: misc-local.h:157
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_user_warning
Definition: misc-local.h:146
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define debug_off()
Definition: misc-local.h:160
#define same_string_p(s1, s2)
hash_table set_ordering_to_statement(statement s)
To be used instead of initialize_ordering_to_statement() to make sure that the hash table ots is in s...
Definition: ordering.c:172
void reset_ordering_to_statement(void)
Reset the mapping from ordering to statement.
Definition: ordering.c:185
rule find_rule_by_resource(const char *rname)
This function returns the active rule to produce resource rname.
Definition: pipsmake.c:694
void set_bool_property(const char *, bool)
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
entity local_name_to_top_level_entity(const char *n)
This function try to find a top-level entity from a local name.
Definition: entity.c:1450

References db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug_off, debug_on, display_top_down_abc_statistics(), find_rule_by_resource(), get_regions_properties(), initialize_top_down_abc_statistics(), local_name_to_top_level_entity(), module_name(), module_reorder(), module_statement, pips_assert, pips_debug, pips_user_warning, reset_current_module_entity(), reset_current_module_statement(), reset_ordering_to_statement(), reset_proper_rw_effects(), reset_rw_effects(), rule_phase, same_string_p, set_bool_property(), set_current_module_entity(), set_current_module_statement(), set_ordering_to_statement(), set_proper_rw_effects(), set_rw_effects(), statement_consistent_p(), and top_down_abc_statement().

+ Here is the call graph for this function:

◆ bool_to_bound()

string bool_to_bound ( bool  b)

array_bound_check_top_down.c

Definition at line 115 of file array_bound_check_top_down.c.

116 {
117  if (b)
118  return ", lower bound, ";
119  return ", upper bound, ";
120 }

Referenced by make_bottom_up_abc_tests(), and top_down_abc_array().

+ Here is the caller graph for this function:

◆ display_top_down_abc_statistics()

static void display_top_down_abc_statistics ( )
static

Definition at line 133 of file array_bound_check_top_down.c.

134 {
135  if (number_of_added_tests > 0)
136  user_log("* There %s %d array bound check%s added *\n",
137  number_of_added_tests > 1 ? "are" : "is",
139  number_of_added_tests > 1 ? "s" : "");
140 
142  user_log("* There %s %d bound violation%s *\n",
143  number_of_bound_violations > 1 ? "are" : "is",
145  number_of_bound_violations > 1 ? "s" : "");
146 }
void user_log(const char *format,...)
Definition: message.c:234
static int number_of_added_tests
Statistic variables:
static int number_of_bound_violations

References number_of_added_tests, number_of_bound_violations, and user_log().

Referenced by array_bound_check_top_down().

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

◆ find_first_written_array()

static entity find_first_written_array ( list  l,
statement  s 
)
static

Definition at line 716 of file array_bound_check_top_down.c.

717 {
718  list l_tmp = gen_full_copy_list(l);
719  MAP(ENTITY,a,
720  {
721  if (is_first_written_array_p(a,l,s))
722  return a;
723  },l_tmp);
724  return entity_undefined;
725 }
static bool is_first_written_array_p(entity a, list l, statement s)
#define MAP(_map_CASTER, _map_item, _map_code, _map_list)
Apply/map an instruction block on all the elements of a list (old fashioned)
Definition: newgen_list.h:226
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define entity_undefined
Definition: ri.h:2761
The structure used to build lists in NewGen.
Definition: newgen_list.h:41

References ENTITY, entity_undefined, gen_full_copy_list(), is_first_written_array_p(), and MAP.

Referenced by top_down_abc_flt().

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

◆ initialize_top_down_abc_statistics()

static void initialize_top_down_abc_statistics ( )
static

Definition at line 127 of file array_bound_check_top_down.c.

128 {
131 }

References number_of_added_tests, and number_of_bound_violations.

Referenced by array_bound_check_top_down().

+ Here is the caller graph for this function:

◆ initiliaze_marked_list()

static abc_checked initiliaze_marked_list ( )
static

Definition at line 148 of file array_bound_check_top_down.c.

149 {
150  list retour = NIL;
151  // get list of entities in the declaration part
152  list ld =
154  MAP(ENTITY,e,
155  {
156  type t = entity_type(e);
157  if (type_variable_p(t))
158  {
160  int length = gen_length(ldim);
161  if (length > 0)
162  {
164  list dc_list = NIL;
165  int i;
167  for(i=1; i <= length; i++ )
168  {
169  dc = make_dimension_checked(i,false,false);
170  dc_list = gen_nconc(dc_list,
172  }
173  adc = make_array_dimension_checked(e, dc_list);
174  retour = gen_nconc(retour,CONS(ARRAY_DIMENSION_CHECKED,adc,NIL));
175  }
176  }
177  },
178  ld);
179  return make_abc_checked(retour);
180 }
dimension_checked make_dimension_checked(intptr_t a1, bool a2, bool a3)
Definition: abc_private.c:136
array_dimension_checked make_array_dimension_checked(entity a1, list a2)
Definition: abc_private.c:94
abc_checked make_abc_checked(list a)
Definition: abc_private.c:52
#define dimension_checked_undefined
Definition: abc_private.h:117
#define DIMENSION_CHECKED(x)
DIMENSION_CHECKED.
Definition: abc_private.h:111
#define ARRAY_DIMENSION_CHECKED(x)
ARRAY_DIMENSION_CHECKED.
Definition: abc_private.h:75
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
size_t gen_length(const list l)
Definition: list.c:150
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#define type_variable(x)
Definition: ri.h:2949
#define code_declarations(x)
Definition: ri.h:784
#define value_code(x)
Definition: ri.h:3067
#define variable_dimensions(x)
Definition: ri.h:3122
#define entity_type(x)
Definition: ri.h:2792
#define type_variable_p(x)
Definition: ri.h:2947
#define entity_initial(x)
Definition: ri.h:2796

References ARRAY_DIMENSION_CHECKED, code_declarations, CONS, DIMENSION_CHECKED, dimension_checked_undefined, ENTITY, entity_initial, entity_type, gen_length(), gen_nconc(), get_current_module_entity(), make_abc_checked(), make_array_dimension_checked(), make_dimension_checked(), MAP, NIL, type_variable, type_variable_p, value_code, and variable_dimensions.

Referenced by top_down_abc_statement().

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

◆ is_first_written_array_p()

static bool is_first_written_array_p ( entity  a,
list  l,
statement  s 
)
static

Definition at line 690 of file array_bound_check_top_down.c.

691 {
692  int max = maximum_ordering(a,s);
693  ifdebug(4)
694  fprintf(stderr, " max of %s = %d ", entity_name(a), max);
695  MAP(ENTITY,other,
696  {
697  if (strcmp(entity_name(a),entity_name(other))!=0)
698  {
699  int min = minimum_ordering(other,s);
700  ifdebug(4)
701  fprintf(stderr, " min of other %s = %d ", entity_name(other), min);
702  if (max >= min) return false;
703  }
704  },l);
705  return true;
706 }
static int maximum_ordering(entity a, statement s)
search for the maximum ordering of statement (after s) that writes on a
static int minimum_ordering(entity a, statement s)
search for the minimum ordering of statement (after s) that writes on a
#define min(a, b)
#define max(a, b)
if(!(yy_init))
Definition: genread_lex.c:1029
#define true
Definition: newgen_types.h:81
#define false
Definition: newgen_types.h:80
#define entity_name(x)
Definition: ri.h:2790
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
return(s1)
#define ifdebug(n)
Definition: sg.c:47

References ENTITY, entity_name, fprintf(), ifdebug, MAP, max, maximum_ordering(), min, and minimum_ordering().

Referenced by find_first_written_array().

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

◆ max_statement_write_flt()

static bool max_statement_write_flt ( statement  s)
static

Definition at line 599 of file array_bound_check_top_down.c.

600 {
601  list effects_list = load_proper_rw_effects_list(s);
602  MAP(EFFECT, eff,
603  {
604  action a = effect_action(eff);
605  if (action_write_p(a))
606  {
608  entity e = reference_variable(r);
609  ifdebug(4)
610  {
611  fprintf(stderr,"\n MAX Write on entity %s :\n",entity_name(e));
612  fprintf(stderr,"\n MAX Current entity %s :\n",entity_name(current_entity));
613  }
614  if (strcmp(entity_name(e),entity_name(current_entity))==0)
615  {
616  int n = statement_ordering(s);
617  ifdebug(4)
618  {
619  fprintf(stderr,"a variable = current entity !!");
620  fprintf(stderr,"This statement writes on %s with max ordering %d",
622  }
623  if (n>current_max) current_max = n;
624  break;
625  }
626  }
627  },
628  effects_list);
629  return true;
630 }
static int current_max
static entity current_entity
list load_proper_rw_effects_list(statement)
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
#define effect_action(x)
Definition: effects.h:642
#define action_write_p(x)
Definition: effects.h:314
#define EFFECT(x)
EFFECT.
Definition: effects.h:608
#define reference_variable(x)
Definition: ri.h:2326
#define statement_ordering(x)
Definition: ri.h:2454

References action_write_p, current_entity, current_max, EFFECT, effect_action, effect_any_reference, entity_name, fprintf(), ifdebug, load_proper_rw_effects_list(), MAP, reference_variable, and statement_ordering.

Referenced by maximum_ordering().

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

◆ maximum_ordering()

static int maximum_ordering ( entity  a,
statement  s 
)
static

search for the maximum ordering of statement (after s) that writes on a

Definition at line 633 of file array_bound_check_top_down.c.

634 {
635  current_entity = a;
636  current_max = 0;
638  ifdebug(4)
639  fprintf(stderr, " return current_max = %d of current entity %s ",
643 }
static bool max_statement_write_flt(statement s)
#define gen_recurse(start, domain_number, flt, rwt)
Definition: genC.h:283
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
static size_t current
Definition: string.c:115

References current_entity, current_max, entity_name, entity_undefined, fprintf(), gen_null(), gen_recurse, ifdebug, max_statement_write_flt(), and statement_domain.

Referenced by is_first_written_array_p().

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

◆ min_statement_write_flt()

static bool min_statement_write_flt ( statement  s)
static

Definition at line 645 of file array_bound_check_top_down.c.

646 {
647  list effects_list = load_proper_rw_effects_list(s);
648  MAP(EFFECT, eff,
649  {
650  action a = effect_action(eff);
651  if (action_write_p(a))
652  {
654  entity e = reference_variable(r);
655  ifdebug(4)
656  {
657  fprintf(stderr,"\n MIN Write on entity %s :\n",entity_name(e));
658  fprintf(stderr,"\n MIN Current entity %s :\n",entity_name(current_entity));
659  }
660  if (strcmp(entity_name(e),entity_name(current_entity))==0)
661  {
663  ifdebug(4)
664  {
665  fprintf(stderr,"a variable = current entity !!");
666  fprintf(stderr, " This statement writes on %s with min ordering %d",
668  }
669  return false;
670  }
671  }
672  },
673  effects_list);
674  return true;
675 }
static int current_min

References action_write_p, current_entity, current_min, EFFECT, effect_action, effect_any_reference, entity_name, fprintf(), ifdebug, load_proper_rw_effects_list(), MAP, reference_variable, and statement_ordering.

Referenced by minimum_ordering().

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

◆ minimum_ordering()

static int minimum_ordering ( entity  a,
statement  s 
)
static

search for the minimum ordering of statement (after s) that writes on a

Definition at line 678 of file array_bound_check_top_down.c.

679 {
680  current_entity = a;
681  current_min = 0;
683  ifdebug(4)
684  fprintf(stderr, " return current_min = %d of current entity %s",
688 }
static bool min_statement_write_flt(statement s)

References current_entity, current_min, entity_name, entity_undefined, fprintf(), gen_null(), gen_recurse, ifdebug, min_statement_write_flt(), and statement_domain.

Referenced by is_first_written_array_p().

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

◆ my_system_remove_variables()

static Psysteme my_system_remove_variables ( Psysteme  ps)
static

Project all PHI and init variables, ....in the system ps, there are 2 cases :

  1. The result is not sure , there are over flow Return the SC_UNDEFINED
  2. The result is sure, three small cases: 2.1 The system is always false sc_empty => no bounds violation 2.2 The system is always true sc_rn => bounds violation 2.3 The system is parametric => test to put

converts the phi list into a Pvecteur

Definition at line 224 of file array_bound_check_top_down.c.

225 {
226  /* Project all PHI and #init variables, ....in the system ps,
227  there are 2 cases :
228  1. The result is not sure , there are over flow
229  Return the SC_UNDEFINED
230  2. The result is sure, three small cases:
231  2.1 The system is always false sc_empty => no bounds violation
232  2.2 The system is always true sc_rn => bounds violation
233  2.3 The system is parametric => test to put*/
234 
235  if (!sc_empty_p(ps)&& !sc_rn_p(ps))
236  {
237  list l_phi = phi_entities_list(1,7);
238  list l_var = l_phi;
239  Pvecteur pv_var = NULL;
240  Pbase b = ps->base;
241  /* converts the phi list into a Pvecteur */
242  MAP(ENTITY, e,
243  {
244  if (base_contains_variable_p(ps->base, (Variable) e) )
245  vect_add_elem(&pv_var, (Variable) e, VALUE_ONE);
246  },l_var);
247 
248  for(; !VECTEUR_NUL_P(b);b = b->succ)
249  {
250  entity e = (entity) vecteur_var(b);
251  if (old_value_entity_p(e))
252  vect_add_elem(&pv_var, (Variable) e, VALUE_ONE);
253  }
254  ps = sc_system_projection_along_variables(ps, pv_var);
255  vect_rm(pv_var);
256  gen_free_list(l_phi);
257  }
258  return ps;
259 }
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
#define VALUE_ONE
bool base_contains_variable_p(Pbase b, Variable v)
bool base_contains_variable_p(Pbase b, Variable v): returns true if variable v is one of b's elements...
Definition: base.c:136
list phi_entities_list(int, int)
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
bool sc_rn_p(Psysteme sc)
bool sc_rn_p(Psysteme sc): check if the set associated to sc is the whole space, rn
Definition: sc_alloc.c:369
bool sc_empty_p(Psysteme sc)
bool sc_empty_p(Psysteme sc): check if the set associated to sc is the constant sc_empty or not.
Definition: sc_alloc.c:350
Pbase base
Definition: sc-local.h:75
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
struct Svecteur * succ
Definition: vecteur-local.h:92
bool old_value_entity_p(entity)
Definition: value.c:936
#define vecteur_var(v)
#define VECTEUR_NUL_P(v)
void * Variable
arithmetique is a requirement for vecteur, but I do not want to inforce it in all pips files....
Definition: vecteur-local.h:60
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 Ssysteme::base, base_contains_variable_p(), ENTITY, gen_free_list(), MAP, old_value_entity_p(), phi_entities_list(), sc_empty_p(), sc_rn_p(), Svecteur::succ, VALUE_ONE, vect_add_elem(), vect_rm(), VECTEUR_NUL_P, and vecteur_var.

Referenced by top_down_abc_dimension().

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

◆ pop_uns()

static void pop_uns ( unstructured __attribute__((unused))  u,
top_down_abc_context_p  context 
)
static

Definition at line 1095 of file array_bound_check_top_down.c.

1097 {
1098  stack_pop(context->uns);
1099 }
void * stack_pop(stack)
POPs one item from stack s.
Definition: stack.c:399
Definition: delay.c:253

References stack_pop().

Referenced by top_down_abc_statement().

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

◆ push_uns()

static bool push_uns ( unstructured  u,
top_down_abc_context_p  context 
)
static

Definition at line 1089 of file array_bound_check_top_down.c.

1090 {
1091  stack_push((char *) u, context->uns);
1092  return true;
1093 }
void stack_push(void *, stack)
stack use
Definition: stack.c:373

References stack_push().

Referenced by top_down_abc_statement().

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

◆ read_or_write()

◆ set_array_dimension_checked()

static void set_array_dimension_checked ( top_down_abc_context_p  context,
bool  action,
entity  array,
int  dim,
bool  bound 
)
static

Definition at line 182 of file array_bound_check_top_down.c.

184 {
185  if (action)
186  {
187  // read region
189  {
192  {
193  if (dimension_checked_dim(dc) == dim)
194  {
195  if (bound)
196  dimension_checked_lower(dc) = true;
197  else
198  dimension_checked_upper(dc) = true;
199  }
201  }, abc_checked_list(context->read_marked_list));
202  }
203  else
204  {
205  // write region
207  {
210  {
211  if (dimension_checked_dim(dc) == dim)
212  {
213  if (bound)
214  dimension_checked_lower(dc) = true;
215  else
216  dimension_checked_upper(dc) = true;
217  }
219  }, abc_checked_list(context->write_marked_list));
220  }
221 }
#define array_dimension_checked_dims(x)
Definition: abc_private.h:107
#define abc_checked_list(x)
Definition: abc_private.h:71
#define dimension_checked_dim(x)
Definition: abc_private.h:142
#define dimension_checked_upper(x)
Definition: abc_private.h:146
#define array_dimension_checked_array(x)
Definition: abc_private.h:105
#define dimension_checked_lower(x)
Definition: abc_private.h:144
bool same_entity_p(entity e1, entity e2)
predicates on entities
Definition: entity.c:1321
static entity array

References abc_checked_list, array, ARRAY_DIMENSION_CHECKED, array_dimension_checked_array, array_dimension_checked_dims, DIMENSION_CHECKED, dimension_checked_dim, dimension_checked_lower, dimension_checked_upper, MAP, and same_entity_p().

Referenced by top_down_abc_dimension(), and top_down_abc_not_exact_case().

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

◆ store_mapping()

static bool store_mapping ( control  c,
top_down_abc_context_p  context 
)
static

Definition at line 1082 of file array_bound_check_top_down.c.

1083 {
1085  control_statement(c), c);
1086  return true;
1087 }
void extend_persistant_statement_to_control(persistant_statement_to_control f, statement k, control v)
Definition: ri.c:1603
#define control_statement(x)
Definition: ri.h:941

References control_statement, and extend_persistant_statement_to_control().

Referenced by top_down_abc_statement().

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

◆ top_down_abc_array()

static void top_down_abc_array ( entity  array,
region  re,
statement  s,
top_down_abc_context_p  context 
)
static

if we have a region like: <A(PHI)-EXACT-{}> it means that all declared elements are touched, although this is implicit. this occurs with io effects of "PRINT *, A". in such a case, the declaration constraints MUST be appended before the translation, otherwise the result might be false.

potential bug : if the declaration system cannot be generated, the region should be turned to MAY for the translation?

The upper bound of the dimension i is not marked TRUE

There is bounds violation ! Insert a STOP before s (bug in Examples/perma.f if replace s by STOP

The lower bound of the dimension i is not marked TRUE

There is bounds violation ! Insert a STOP before s (bug in Examples/perma.f if replace s by STOP

insert the test after the generated tests, the order of tests is important

If one bound of the dimension is marked false, we have to go down

Definition at line 731 of file array_bound_check_top_down.c.

732 {
733  list marked_list = NIL;
734  list dc_list = NIL;
735  bool action = region_read_p(re);
736  if (action)
737  marked_list = abc_checked_list(context->read_marked_list);
738  else
739  marked_list = abc_checked_list(context->write_marked_list);
741  {
743  {
744  dc_list = array_dimension_checked_dims(adc);
745  break;
746  }
747  },
748  marked_list);
749  // traverse each dimension
750  while (!ENDP(dc_list)) {
751  dimension_checked dc = DIMENSION_CHECKED(CAR(dc_list));
752  int i = dimension_checked_dim(dc);
753  Bound_test lower, upper;
754  lower.test = expression_undefined;
755  upper.test = expression_undefined;
756  lower.bound = true;
757  upper.bound = true;
758 
759  /* if we have a region like: <A(PHI)-EXACT-{}>
760  * it means that all *declared* elements are touched, although
761  * this is implicit. this occurs with io effects of "PRINT *, A".
762  * in such a case, the declaration constraints MUST be appended
763  * before the translation, otherwise the result might be false.
764  *
765  * potential bug : if the declaration system cannot be generated,
766  * the region should be turned to MAY for the translation? */
768  if (!dimension_checked_upper(dc))
769  {
770  /* The upper bound of the dimension i is not marked TRUE*/
771  upper = top_down_abc_dimension(s,context,re,action,array,i,false);
772  if (!expression_undefined_p(upper.test))
773  {
774  statement sta;
775  test t;
776  string message =
777  strdup(concatenate("\'Bound violation:",
778  read_or_write(action), " array ",
780  bool_to_bound(false),
781  int_to_dimension(i),"\'",NULL));
782 
783  if (true_expression_p(upper.test))
784  {
785  /* There is bounds violation !
786  Insert a STOP before s (bug in Examples/perma.f if replace s by STOP*/
788  user_log("\n Bound violation !!! \n");
789  if (get_bool_property("PROGRAM_VERIFICATION_WITH_PRINT_MESSAGE"))
791  else
793  // top_down_abc_insert_before_statement(s,sta,context);
796  else
798  //return false; // follow the first strategy
799  }
800  // test if expression upper.test exists already in test_sequence
801  else
802  if (!same_expression_in_list_p(upper.test,lexp))
803  {
804  ifdebug(2)
805  {
806  fprintf(stderr, "\n The upper test");
807  print_expression(upper.test);
808  }
811  if (get_bool_property("PROGRAM_VERIFICATION_WITH_PRINT_MESSAGE"))
812  t = make_test(upper.test,
815  else
816  t = make_test(upper.test,
819  sta = test_to_statement(t);
822  else
824  }
825  }
826  }
827  if (!dimension_checked_lower(dc))
828  {
829  /* The lower bound of the dimension i is not marked TRUE*/
830  lower = top_down_abc_dimension(s,context,re,action,array,i,true);
831  if (!expression_undefined_p(lower.test))
832  {
833  statement sta;
834  test t;
835  string message =
836  strdup(concatenate("\'Bound violation:",
837  read_or_write(action)," array ",
839  bool_to_bound(true),
840  int_to_dimension(i),"\'",NULL));
841 
842  if (true_expression_p(lower.test))
843  {
844  /* There is bounds violation !
845  Insert a STOP before s (bug in Examples/perma.f if replace s by STOP*/
847  user_log("\n Bound violation !!! \n");
848  if (get_bool_property("PROGRAM_VERIFICATION_WITH_PRINT_MESSAGE"))
850  else
852  // top_down_abc_insert_before_statement(s,sta,context);
855  else
856  /* insert the test after the generated tests, the order of tests
857  is important */
859  // return false; // follow the first strategy
860  }
861  else
862  // test if expression lower.test exists already in test_sequence
863  if (!same_expression_in_list_p(lower.test,lexp))
864  {
865  ifdebug(2)
866  {
867  fprintf(stderr, "\n The lower test");
868  print_expression(lower.test);
869  }
872  if (get_bool_property("PROGRAM_VERIFICATION_WITH_PRINT_MESSAGE"))
873  t = make_test(lower.test,
876  else
877  t = make_test(lower.test,
880  sta = test_to_statement(t);
883  else
885  }
886  }
887  }
888  /* If one bound of the dimension is marked false,
889  we have to go down*/
890  if ((!lower.bound) || (!upper.bound)) godown = true;
891  dc_list = CDR(dc_list);
892  }
893 }
statement copy_statement(statement p)
STATEMENT.
Definition: ri.c:2186
test make_test(expression a1, statement a2, statement a3)
Definition: ri.c:2607
string int_to_dimension(int i)
Warning! Do not modify this file that is automatically generated!
static Bound_test top_down_abc_dimension(statement s, top_down_abc_context_p context, region re, bool action, entity array, int i, bool bound)
static list lexp
static statement test_sequence
string bool_to_bound(bool b)
array_bound_check_top_down.c
static bool godown
static string read_or_write(bool a)
#define region_read_p(reg)
useful region macros
void append_declaration_sc_if_exact_without_constraints(effect)
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
statement make_block_statement(list)
Make a block statement from a list of statement.
Definition: statement.c:616
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
statement make_print_statement(string)
Make a Fortran print statement.
Definition: statement.c:835
statement make_stop_statement(string)
This function returns a Fortran stop statement with an error message.
Definition: statement.c:908
void insert_statement(statement, statement, bool)
This is the normal entry point.
Definition: statement.c:2570
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
void print_expression(expression e)
no file descriptor is passed to make is easier to use in a debugging stage.
Definition: expression.c:58
#define test_to_statement(t)
bool same_expression_in_list_p(expression e, list le)
This function returns true, if there exists a same expression in the list false, otherwise.
Definition: expression.c:557
bool true_expression_p(expression e)
Definition: expression.c:1113
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define expression_undefined
Definition: ri.h:1223
#define expression_undefined_p(x)
Definition: ri.h:1224
#define statement_undefined_p(x)
Definition: ri.h:2420
char * strdup()

References abc_checked_list, append_declaration_sc_if_exact_without_constraints(), array, ARRAY_DIMENSION_CHECKED, array_dimension_checked_array, array_dimension_checked_dims, bool_to_bound(), Bound_test::bound, CAR, CDR, concatenate(), CONS, copy_statement(), DIMENSION_CHECKED, dimension_checked_dim, dimension_checked_lower, dimension_checked_upper, ENDP, entity_name, EXPRESSION, expression_undefined, expression_undefined_p, fprintf(), gen_nconc(), get_bool_property(), godown, ifdebug, insert_statement(), int_to_dimension(), lexp, make_block_statement(), make_print_statement(), make_stop_statement(), make_test(), MAP, NIL, number_of_added_tests, number_of_bound_violations, print_expression(), read_or_write(), region_read_p, same_entity_p(), same_expression_in_list_p(), statement_undefined_p, strdup(), Bound_test::test, test_sequence, test_to_statement, top_down_abc_dimension(), true_expression_p(), and user_log().

Referenced by top_down_abc_flt().

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

◆ top_down_abc_call()

static list top_down_abc_call ( call  c,
entity  array,
dimension  dim_i,
int  i,
bool  bound 
)
static

There is nothing to check here

Make expression : ith < lower_bound

Make expression : upper_bound < ith

Remark : Doesn't like the 1st version of abc, we don't have to put a test for ith in the indirect case. F.e : for A(B(i)) = 0.0, we have 2 regions : < B(PHI1)-R-EXACT-{PHI1==I} > < A(PHI1)-W-MAY-{} > when we check for the inexact case of A, we don't have to check for B.

In case if there is another access of array B in the same statement, the region of B may be MAY => we check it for the read region of B.

In case of A(A(i)) , we have the different regions for read and write effect ??????? => ????? ATT : example Indirection.f

Test if exp is trivial or not

  • If exp is always TRUE: there is certainly bound violation, return make_true_expression
  • If exp is always false, we don't have to add it to retour
  • Otherwise, we add it to retour.

Definition at line 316 of file array_bound_check_top_down.c.

318 {
319  list retour = NIL;
320  list args = call_arguments(c);
321  MAP(EXPRESSION,e,
322  {
323  syntax s = expression_syntax(e);
324  tag t = syntax_tag(s);
325  switch (t){
326  case is_syntax_call:
327  {
328  list tmp = top_down_abc_call(syntax_call(s),array,dim_i,i,bound);
329  if (tmp != NIL)
330  // add tmp to retour
331  MAP(EXPRESSION, exp,
332  {
333  if (!same_expression_in_list_p(exp,retour))
334  retour = gen_nconc(retour,CONS(EXPRESSION,exp,NIL));
335  },
336  tmp);
337  break;
338  }
339  case is_syntax_range:
340  /* There is nothing to check here*/
341  break;
342  case is_syntax_reference:
343  {
346  if (same_entity_p(arr,array))
347  {
348  list arrayinds = reference_indices(ref);
349  expression ith = find_ith_argument(arrayinds,i);
351  if (!expression_undefined_p(ith))
352  {
353  ifdebug(2)
354  {
355  fprintf(stderr, "\n The ith expression");
356  print_expression(ith);
357  fprintf(stderr, " \n array: %s ",entity_name(array));
358  }
359  if (bound)
360  {
361  /* Make expression : ith < lower_bound */
364  ifdebug(2)
365  {
366  fprintf(stderr, "\n The lower bound test");
368  }
369  }
370  else
371  // test if the upper bound is unbounded or not
372  if (!unbounded_dimension_p(dim_i))
373  {
374  /* Make expression : upper_bound < ith */
376  copy_expression(ith));
377  ifdebug(2)
378  {
379  fprintf(stderr, "\n The upper bound test");
381  }
382  }
383  }
384 
385  /* Remark : Doesn't like the 1st version of abc,
386  we don't have to put a test for ith in the indirect case.
387  F.e : for A(B(i)) = 0.0, we have 2 regions :
388  < B(PHI1)-R-EXACT-{PHI1==I} >
389  < A(PHI1)-W-MAY-{} >
390  when we check for the inexact case of A, we don't have
391  to check for B.
392 
393  In case if there is another access of array B in the same
394  statement, the region of B may be MAY => we check it for
395  the read region of B.
396 
397  In case of A(A(i)) , we have the different regions for read
398  and write effect ??????? => ?????
399  ATT : example Indirection.f */
400 
401  /* Test if exp is trivial or not
402  + If exp is always TRUE: there is certainly bound violation,
403  return make_true_expression
404  + If exp is always false, we don't have to add it to retour
405  + Otherwise, we add it to retour.*/
407  {
408  int tr = trivial_expression_p(exp);
409  switch(tr){
410  case 1:
412  case 0:
413  {
414  // test if exp is already in retour
415  if (!same_expression_in_list_p(exp,retour))
416  retour = gen_nconc(retour,CONS(EXPRESSION,exp,NIL));
417  break;
418  }
419  case -1:
420  break;
421  }
422  }
423  }
424  break;
425  }
426  }
427  },
428  args);
429  return retour;
430 }
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
dimension copy_dimension(dimension p)
DIMENSION.
Definition: ri.c:529
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
static list top_down_abc_call(call c, entity array, dimension dim_i, int i, bool bound)
int tag
TAG.
Definition: newgen_types.h:92
#define lt_expression(e1, e2)
int trivial_expression_p(expression e)
This function returns:
Definition: expression.c:679
expression find_ith_argument(list args, int n)
Definition: expression.c:1147
bool unbounded_dimension_p(dimension dim)
bool unbounded_dimension_p(dim) input : a dimension of an array entity.
Definition: expression.c:1130
expression make_true_expression()
Definition: expression.c:1103
#define syntax_reference(x)
Definition: ri.h:2730
#define syntax_tag(x)
Definition: ri.h:2727
#define dimension_lower(x)
Definition: ri.h:980
@ is_syntax_range
Definition: ri.h:2692
@ is_syntax_call
Definition: ri.h:2693
@ is_syntax_reference
Definition: ri.h:2691
#define dimension_upper(x)
Definition: ri.h:982
#define reference_indices(x)
Definition: ri.h:2328
#define syntax_call(x)
Definition: ri.h:2736
#define call_arguments(x)
Definition: ri.h:711
#define expression_syntax(x)
Definition: ri.h:1247
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207

References array, call_arguments, CONS, copy_dimension(), copy_expression(), dimension_lower, dimension_upper, entity_name, exp, EXPRESSION, expression_syntax, expression_undefined, expression_undefined_p, find_ith_argument(), fprintf(), gen_nconc(), ifdebug, is_syntax_call, is_syntax_range, is_syntax_reference, lt_expression, make_true_expression(), MAP, NIL, print_expression(), ref, reference_indices, reference_variable, same_entity_p(), same_expression_in_list_p(), syntax_call, syntax_reference, syntax_tag, trivial_expression_p(), and unbounded_dimension_p().

Referenced by top_down_abc_not_exact_case().

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

◆ top_down_abc_dimension()

static Bound_test top_down_abc_dimension ( statement  s,
top_down_abc_context_p  context,
region  re,
bool  action,
entity  array,
int  i,
bool  bound 
)
static

unbounded dimension, we don't have to check for this bound

try fast check

ok, redundant => there is certainly bound violation

ok, not feasible => there is no bound violation

no result, try slow version

Add the equation PHIi <= lower-1 (upper+1 <= PHIi) to the predicate of region re

Every expression is linear. Test the feasibility of P by using this function: sc_rational_feasibility_ofl_ctrl(sc, ofl_ctrl, ofl_res) in which

ofl_ctrl = OFL_CTRL means that the overflows are treated in the called procedure (sc_rational_feasibility_ofl_ctrl())

ofl_res = true means that if the overflows occur, function sc_rational_feasibility_ofl_ctrl will return the value TRUE we don't know if the system is feasible or not

The function sc_rational_feasibility_ofl_ctrl() is less expensive than the function sc_integer_feasibility_ofl_ctrl()

The system is not feasible (certainly) => no violation

The system is feasible or we don't know it is feasible or not Test if the region re is EXACT or MAY

EXACT region Remove all PHI variables, useless variables such as PIPS generated variables V::init, common variable from another subroutine ......

SUBROUTINE X CALL Y(I) <P(I) {I == FOO:J} END

SUBROUTINE Y(K) COMMON J K=J END

MAY region

Definition at line 461 of file array_bound_check_top_down.c.

464 {
465  Bound_test retour;
468  retour.bound = true;
469  retour.test = expression_undefined;
470  if (!bound && unbounded_dimension_p(dim_i))
471  /* unbounded dimension, we don't have to check for this bound */
473  else
474  {
475  Psysteme P = sc_dup(region_system(re));
479  expression exp_1 = int_to_expression(1);
480  if (bound)
483  exp_1);
484  else
487  exp_1);
489  // fast check: PHIi<=lower-1 (or upper+1<=PHIi) is trivial redundant wrt P or not
490  // transform exp to Pcontrainte con_exp
491  nexpr = NORMALIZE_EXPRESSION(exp);
492  if (normalized_linear_p(nexpr))
493  {
494  entity phi = make_phi_entity(i);
495  Pvecteur v1 = vect_new((Variable) phi, VALUE_ONE);
496  Pvecteur v2 = normalized_linear(nexpr);
497  Pvecteur vect;
498  if (bound)
499  vect = vect_substract(v1, v2);
500  else
501  vect = vect_substract(v2, v1);
502  vect_rm(v1);
503  con_exp = contrainte_make(vect);
504  switch (sc_check_inequality_redundancy(con_exp, P)) {/* try fast check */
505  case 1: /* ok, redundant => there is certainly bound violation */
506  {
508  retour.test = make_true_expression();
509  break;
510  }
511  case 2: /* ok, not feasible => there is no bound violation*/
512  {
514  break;
515  }
516  case 0: /* no result, try slow version */
517  {
518  /* Add the equation PHIi <= lower-1 (upper+1 <= PHIi)
519  to the predicate of region re */
520  if (sc_add_phi_equation(&P,exp,i,false,bound))
521  {
522  /* Every expression is linear.
523  * Test the feasibility of P by using this function:
524  * sc_rational_feasibility_ofl_ctrl(sc, ofl_ctrl, ofl_res) in which
525  *
526  * ofl_ctrl = OFL_CTRL means that the overflows are treated in the
527  * called procedure (sc_rational_feasibility_ofl_ctrl())
528  *
529  * ofl_res = true means that if the overflows occur, function
530  * sc_rational_feasibility_ofl_ctrl will return the value TRUE
531  * we don't know if the system is feasible or not
532  *
533  * The function sc_rational_feasibility_ofl_ctrl() is less
534  * expensive than the function sc_integer_feasibility_ofl_ctrl()*/
535 
537  /* The system is not feasible (certainly) => no violation */
539  else
540  {
541  /* The system is feasible or we don't know it is feasible or not
542  * Test if the region re is EXACT or MAY */
543  if (region_exact_p(re))
544  {
545  /* EXACT region
546  Remove all PHI variables, useless variables such as
547  PIPS generated variables V#init, common variable
548  from another subroutine ......
549 
550  SUBROUTINE X
551  CALL Y(I)
552  <P(I) {I == FOO:J}
553  END
554 
555  SUBROUTINE Y(K)
556  COMMON J
557  K=J
558  END */
560  if (ps == SC_UNDEFINED)
561  // the projection is not exact
562  retour = top_down_abc_not_exact_case (s,context,action,array,dim_i,i,bound);
563  else
564  {
565  // the projection is exact
567  if (!sc_empty_p(ps) && !sc_rn_p(ps))
568  // there is a test to put
569  // sc_normalized or sc_elim_redon ?????
570  retour.test = Psysteme_to_expression(ps);
571  else
572  if (sc_rn_p(ps))
573  // the system is trivial true, there are bounds violation
574  retour.test = make_true_expression();
575  //else, ps=sc_empty, the system is false, no bounds violation
576  }
577  }
578  else
579  /* MAY region */
580  retour = top_down_abc_not_exact_case(s,context,action,array,dim_i,i,bound);
581  }
582  }
583  else
584  // the exp is not linear, we can't add to P
585  retour.bound = false;
586  }
587  }
588  contrainte_free(con_exp);
589  }
590  sc_rm(P);
591  }
592  return retour;
593 }
static Psysteme my_system_remove_variables(Psysteme ps)
static void set_array_dimension_checked(top_down_abc_context_p context, bool action, entity array, int dim, bool bound)
static Bound_test top_down_abc_not_exact_case(statement s, top_down_abc_context_p context, bool action, entity array, dimension dim_i, int i, bool bound)
#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
Pcontrainte contrainte_free(Pcontrainte c)
Pcontrainte contrainte_free(Pcontrainte c): liberation de l'espace memoire alloue a la contrainte c a...
Definition: alloc.c:184
expression Psysteme_to_expression(Psysteme)
system_to_code.c
#define region_system(reg)
#define region_exact_p(reg)
entity make_phi_entity(int)
bool sc_add_phi_equation(Psysteme *, expression, int, bool, bool)
#define MINUS_OPERATOR_NAME
#define PLUS_OPERATOR_NAME
#define NORMALIZE_EXPRESSION(e)
#define binary_intrinsic_expression(name, e1, e2)
void clean_all_normalized(expression e)
Definition: expression.c:4102
expression int_to_expression(_int i)
transform an int into an expression and generate the corresponding entity if necessary; it is not cle...
Definition: expression.c:1188
dimension find_ith_dimension(list, int)
This function returns the ith dimension of a list of dimensions.
Definition: type.c:5621
#define normalized_undefined
Definition: ri.h:1745
#define normalized_linear_p(x)
Definition: ri.h:1779
#define normalized_linear(x)
Definition: ri.h:1781
void sc_rm(Psysteme ps)
void sc_rm(Psysteme ps): liberation de l'espace memoire occupe par le systeme de contraintes ps;
Definition: sc_alloc.c:277
Psysteme sc_dup(Psysteme ps)
Psysteme sc_dup(Psysteme ps): should becomes a link.
Definition: sc_alloc.c:176
int sc_check_inequality_redundancy(Pcontrainte ineq, Psysteme ps)
int sc_check_inequality_redundancy(Pcontrainte ineq, Psysteme ps) Check if an inequality ineq,...
bool sc_rational_feasibility_ofl_ctrl(Psysteme sc, int ofl_ctrl, bool ofl_res)
#define OFL_CTRL
I do thing that overflows are managed in a very poor manner.
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

References array, binary_intrinsic_expression, Bound_test::bound, clean_all_normalized(), contrainte_free(), contrainte_make(), CONTRAINTE_UNDEFINED, copy_dimension(), dimension_lower, dimension_upper, entity_type, exp, expression_undefined, find_ith_dimension(), int_to_expression(), make_phi_entity(), make_true_expression(), MINUS_OPERATOR_NAME, my_system_remove_variables(), NORMALIZE_EXPRESSION, normalized_linear, normalized_linear_p, normalized_undefined, OFL_CTRL, PLUS_OPERATOR_NAME, Psysteme_to_expression(), region_exact_p, region_system, sc_add_phi_equation(), sc_check_inequality_redundancy(), sc_dup(), sc_empty_p(), sc_rational_feasibility_ofl_ctrl(), sc_rm(), sc_rn_p(), set_array_dimension_checked(), Bound_test::test, top_down_abc_not_exact_case(), type_variable, unbounded_dimension_p(), VALUE_ONE, variable_dimensions, vect_new(), vect_rm(), and vect_substract().

Referenced by top_down_abc_array().

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

◆ top_down_abc_flt()

static bool top_down_abc_flt ( statement  s,
top_down_abc_context_p  context 
)
static

The old algorithm is false in the case of incorrect code, because regions are computed with the assumption that the code is correct.

Here is an anti-example:

COMMON ITAB(10),J REAL A(10) C <A(PHI1)-W-EXACT-{PHI1==11}> C <ITAB(PHI1)-W-MAY-{1<=PHI1}> READ *, M J = 11 C <ITAB(PHI1)-W-EXACT-{1<=PHI1, PHI1<=M, J==11}> DO I = 1, M C <ITAB(PHI1)-W-EXACT-{PHI1==I, J==11, 1<=I, I<=M}> ITAB(I) = 1 ENDDO C <A(PHI1)-W-EXACT-{PHI1==J, J==11, 1+M<=I, 1<=I}> A(J) = 0

The region for array A can be false if there is a bound violation in ITAB for example with M=12, ITAB(11)=1=J, there will be no violation on A but on ITAB. Based on this false region, the algorithm will tell that there is a violation on A.

To keep the algorithm safe, we must take into account the order in which arrays are writen (bound violations on read arrays do not make transformers and array regions false). If bound checks on ITAB are inserted before checks on A, tests are checked earlier, so the region of A is not false any more. The tests must be:

COMMON ITAB(10),J REAL A(10) READ *, M IF (M.GT.10) STOP "Bound violation ITAB" STOP "Bound violation A" J = 11 DO I = 1, M ITAB(I) = 1 ENDDO A(J) = 0

Modify the algorithm: At each statement s, take its list of regions:

  • If no array is written => apply the algorithm normally
  • Else
    • Find the writing order
    • Apply the algorithm for the first written array, and then the second, ...
    • If the order is not found at s, go to the substatements of s

Compute the list of written arrays

while (!ENDP(l_copy)) { region re = REGION(CAR(l_copy)); reference ref = effect_any_reference(re); entity array = reference_variable(ref); if (array_reference_p(ref) && array_need_bound_check_p(array) && region_write_p(re)) l_written_arrays = CONS(ENTITY,array,l_written_arrays); l_copy = CDR(l_copy); } ifdebug(3) { fprintf(stderr, "\n List of written arrays : \n "); print_list_entities(l_written_arrays); }

If no array is written

check all arrays in l_regions

Choose the first written array and then generate checks for the read and write regions of this array. We can check the second array only when all dimensions of the written regions of the first array are checked

if there is no array that is always written before the others, we have to go down to substatements of s

Definition at line 942 of file array_bound_check_top_down.c.

943 {
945  list l_copy = gen_full_copy_list(l_regions);
946  list l_written_arrays = NIL;
947  lexp = NIL;
949  godown = false;
950  ifdebug(3)
951  {
952  fprintf(stderr, "\n list of regions ");
953  print_effects(l_regions);
954  fprintf(stderr, "\n for the statement");
955  print_statement(s);
956  }
957  hash_put(context->read_saved_list,s,
958  copy_abc_checked(context->read_marked_list));
959  hash_put(context->write_saved_list,s,
960  copy_abc_checked(context->write_marked_list));
961 
962  /* Compute the list of written arrays */
963  /* while (!ENDP(l_copy))
964  {
965  region re = REGION(CAR(l_copy));
966  reference ref = effect_any_reference(re);
967  entity array = reference_variable(ref);
968  if (array_reference_p(ref)
969  && array_need_bound_check_p(array)
970  && region_write_p(re))
971  l_written_arrays = CONS(ENTITY,array,l_written_arrays);
972  l_copy = CDR(l_copy);
973  }
974  ifdebug(3)
975  {
976  fprintf(stderr, "\n List of written arrays : \n ");
977  print_list_entities(l_written_arrays);
978  }*/
979 
980  /* If no array is written */
981  if (ENDP(l_written_arrays))
982  {
983  /* check all arrays in l_regions*/
984  l_copy = gen_full_copy_list(l_regions);
985  while (!ENDP(l_copy))
986  {
987  region re = REGION(CAR(l_copy));
992  l_copy = CDR(l_copy);
993  }
994  }
995  else
996  {
997  /* Choose the first written array and then generate checks for
998  the read and write regions of this array. We can check the
999  second array only when all dimensions of the written regions
1000  of the first array are checked */
1001  while (!ENDP(l_written_arrays) && !godown)
1002  {
1003  entity first_array = find_first_written_array(l_written_arrays,s);
1004  /* if there is no array that is always written before the others,
1005  we have to go down to substatements of s*/
1007  godown = true;
1008  else
1009  {
1010  ifdebug(3)
1011  {
1012  fprintf(stderr, "\n First array: ");
1013  fprintf(stderr, "%s ", entity_name(first_array));
1014  }
1015  gen_remove_once(&l_written_arrays,first_array);
1016  // check for the first array here
1017  l_copy = gen_full_copy_list(l_regions);
1018  while (!ENDP(l_copy))
1019  {
1020  region re = REGION(CAR(l_copy));
1023  // if (same_entity_p(array,first_array))
1024  if (strcmp(entity_name(array),entity_name(first_array))==0)
1026  l_copy = CDR(l_copy);
1027  }
1028  }
1029  }
1030  }
1032  {
1033  ifdebug(3)
1034  {
1035  fprintf(stderr, "\n The sequence of test");
1037  }
1038  if (!godown)
1039  // godown = false, insert new tests for the statement s here
1041  else
1042  // insert new tests in function rwt
1043  hash_put(context->statement_check_list,s,test_sequence);
1044  }
1045  if (!godown)
1046  {
1047  context->read_marked_list =
1048  (abc_checked) hash_get(context->read_saved_list,s);
1049  context->write_marked_list =
1050  (abc_checked) hash_get(context->write_saved_list,s);
1051  }
1052  gen_free_list(l_regions);
1054  lexp = NIL;
1056  return godown;
1057 }
abc_checked copy_abc_checked(abc_checked p)
ABC_CHECKED.
Definition: abc_private.c:16
struct _newgen_struct_abc_checked_ * abc_checked
Definition: abc_private.h:22
bool array_need_bound_check_p(entity e)
This function returns true, if the array needs bound checks false, otherwise.
static void top_down_abc_insert_before_statement(statement s, statement s1, top_down_abc_context_p context)
static entity find_first_written_array(list l, statement s)
static void top_down_abc_array(entity array, region re, statement s, top_down_abc_context_p context)
#define REGION
#define region
simulation of the type region
list regions_dup(list)
list load_statement_local_regions(statement)
void gen_remove_once(list *pl, const void *o)
Remove the first occurence of o in list pl:
Definition: list.c:691
void * hash_get(const hash_table htp, const void *key)
this function retrieves in the hash table pointed to by htp the couple whose key is equal to key.
Definition: hash.c:449
void hash_put(hash_table htp, const void *key, const void *val)
This functions stores a couple (key,val) in the hash table pointed to by htp.
Definition: hash.c:364
entity first_array
une copie de l'un des nids de la sequence
#define print_effects(e)
Definition: print.c:334
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
bool array_reference_p(reference r)
predicates on references
Definition: expression.c:1861
#define entity_undefined_p(x)
Definition: ri.h:2762
#define statement_undefined
Definition: ri.h:2419

References array, array_need_bound_check_p(), array_reference_p(), CAR, CDR, copy_abc_checked(), effect_any_reference, ENDP, entity_name, entity_undefined_p, find_first_written_array(), first_array, fprintf(), gen_free_list(), gen_full_copy_list(), gen_remove_once(), godown, hash_get(), hash_put(), ifdebug, lexp, load_statement_local_regions(), NIL, print_effects, print_statement(), ref, reference_variable, region, REGION, regions_dup(), statement_undefined, statement_undefined_p, test_sequence, top_down_abc_array(), and top_down_abc_insert_before_statement().

Referenced by top_down_abc_statement().

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

◆ top_down_abc_insert_before_statement()

static void top_down_abc_insert_before_statement ( statement  s,
statement  s1,
top_down_abc_context_p  context 
)
static

If s is in an unstructured instruction, we must pay attetion when inserting s1 before s.

take the control qui has s as statement

take the unstructured correspond to the control c

for a consistent unstructured, a test must have 2 successors, so if s1 is a test, we transform it into sequence in order to avoid this constraint. Then we create a new control for it, with the predecessors are those of c and the only one successor is c. The new predecessors of c are only the new control

if c is the entry node of the correspond unstructured u, the newc will become the new entry node of u

Definition at line 261 of file array_bound_check_top_down.c.

263 {
264  /* If s is in an unstructured instruction, we must pay attetion
265  when inserting s1 before s. */
267  {
268  /* take the control qui has s as statement */
270  if (stack_size(context->uns)>0)
271  {
272  /* take the unstructured correspond to the control c */
274  control newc;
275  /* for a consistent unstructured, a test must have 2 successors,
276  so if s1 is a test, we transform it into sequence in order
277  to avoid this constraint.
278  Then we create a new control for it, with the predecessors
279  are those of c and the only one successor is c.
280  The new predecessors of c are only the new control*/
281  if (statement_test_p(s1))
282  {
283  list seq = CONS(STATEMENT,s1,NIL);
284  statement s2=
286  make_sequence(seq)));
288  }
289  else
291  // replace c by newc as successor of each predecessor of c
292  MAP(CONTROL, co,
293  {
294  MAPL(lc,
295  {
296  if (CONTROL(CAR(lc))==c) CONTROL_(CAR(lc)) = newc;
297  }, control_successors(co));
298  },control_predecessors(c));
300  /* if c is the entry node of the correspond unstructured u,
301  the newc will become the new entry node of u */
302  if (unstructured_control(u)==c)
303  unstructured_control(u) = newc;
304  gen_recurse_stop(newc); // ????????????
305  }
306  else
307  // there is no unstructured (?)
308  insert_statement(s,s1,true);
309  }
310  else
311  // structured case
312  insert_statement(s,s1,true);
313 }
control apply_persistant_statement_to_control(persistant_statement_to_control f, statement k)
Definition: ri.c:1597
instruction make_instruction(enum instruction_utype tag, void *val)
Definition: ri.c:1166
bool bound_persistant_statement_to_control_p(persistant_statement_to_control f, statement k)
Definition: ri.c:1609
sequence make_sequence(list a)
Definition: ri.c:2125
control make_control(statement a1, list a2, list a3)
Definition: ri.c:523
statement instruction_to_statement(instruction)
Build a statement from a give instruction.
Definition: statement.c:597
void gen_recurse_stop(void *obj)
Tells the recursion not to go in this object.
Definition: genClib.c:3251
#define MAPL(_map_list_cp, _code, _l)
Apply some code on the addresses of all the elements of a list.
Definition: newgen_list.h:203
bool statement_test_p(statement)
Definition: statement.c:343
void * stack_head(const stack)
returns the item on top of stack s
Definition: stack.c:420
int stack_size(const stack)
observers
#define unstructured_control
After the modification in Newgen: unstructured = entry:control x exit:control we have create a macro ...
#define CONTROL_(x)
Definition: ri.h:913
#define control_predecessors(x)
Definition: ri.h:943
struct _newgen_struct_unstructured_ * unstructured
Definition: ri.h:447
#define CONTROL(x)
CONTROL.
Definition: ri.h:910
@ is_instruction_sequence
Definition: ri.h:1469
#define control_successors(x)
Definition: ri.h:945
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
s1
Definition: set.c:247

References apply_persistant_statement_to_control(), bound_persistant_statement_to_control_p(), CAR, CONS, CONTROL, CONTROL_, control_predecessors, control_successors, gen_recurse_stop(), insert_statement(), instruction_to_statement(), is_instruction_sequence, make_control(), make_instruction(), make_sequence(), MAP, MAPL, NIL, s1, stack_head(), stack_size(), STATEMENT, statement_test_p(), and unstructured_control.

Referenced by top_down_abc_flt(), and top_down_abc_rwt().

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

◆ top_down_abc_not_exact_case()

static Bound_test top_down_abc_not_exact_case ( statement  s,
top_down_abc_context_p  context,
bool  action,
entity  array,
dimension  dim_i,
int  i,
bool  bound 
)
static

Test if s is a call (elementary statement)

generate a lower/upper bound test expression for all array reference of this dimension of array

s is not a call, no conclusion for this bound, continue to go down

Definition at line 432 of file array_bound_check_top_down.c.

435 {
436  Bound_test retour;
437  retour.test = expression_undefined;
438  retour.bound = true;
439 
440  /* Test if s is a call (elementary statement)*/
441  if (statement_call_p(s))
442  {
443  /* generate a lower/upper bound test expression for all
444  array reference of this dimension of array*/
446  list l = top_down_abc_call(c,array,dim_i,i,bound);
447  if (l!= NIL)
451  gen_free_list(l);
452  }
453  else
454  /* s is not a call, no conclusion for this bound,
455  continue to go down */
456  retour.bound = false;
457 
458  return retour;
459 }
bool statement_call_p(statement)
Definition: statement.c:364
#define OR_OPERATOR_NAME
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
expression expression_list_to_binary_operator_call(list l, entity op)
Definition: expression.c:1917
#define statement_instruction(x)
Definition: ri.h:2458
#define instruction_call(x)
Definition: ri.h:1529

References array, Bound_test::bound, entity_intrinsic(), expression_list_to_binary_operator_call(), expression_undefined, gen_free_list(), instruction_call, NIL, OR_OPERATOR_NAME, set_array_dimension_checked(), statement_call_p(), statement_instruction, Bound_test::test, and top_down_abc_call().

Referenced by top_down_abc_dimension().

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

◆ top_down_abc_rwt()

static void top_down_abc_rwt ( statement  s,
top_down_abc_context_p  context 
)
static

Definition at line 1059 of file array_bound_check_top_down.c.

1061 {
1063  context->read_marked_list =
1064  (abc_checked) hash_get(context->read_saved_list,s);
1065  context->write_marked_list =
1066  (abc_checked) hash_get(context->write_saved_list,s);
1067  test_sequence = (statement) hash_get(context->statement_check_list,s);
1069  {
1070  ifdebug(3)
1071  {
1072  fprintf(stderr, "\n Rewrite : The sequence of test");
1074  fprintf(stderr, "\n of statement");
1075  print_statement(s);
1076  }
1077  // insert the new sequence of tests before the current statement
1079  }
1080 }

References fprintf(), hash_get(), ifdebug, print_statement(), statement_undefined, statement_undefined_p, test_sequence, and top_down_abc_insert_before_statement().

Referenced by top_down_abc_statement().

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

◆ top_down_abc_statement()

static void top_down_abc_statement ( statement  module_statement)
static

Definition at line 1102 of file array_bound_check_top_down.c.

1103 {
1105  context.read_marked_list = initiliaze_marked_list();
1106  context.write_marked_list = copy_abc_checked(context.read_marked_list);
1107  context.read_saved_list = hash_table_make(hash_pointer, 0);
1108  context.write_saved_list = hash_table_make(hash_pointer, 0);
1109 
1110  context.statement_check_list = hash_table_make(hash_pointer, 0);
1113 
1118  NULL);
1119 
1120  free_abc_checked(context.read_marked_list);
1121  free_abc_checked(context.write_marked_list);
1122  hash_table_free(context.read_saved_list);
1123  hash_table_free(context.write_saved_list);
1124  hash_table_free(context.statement_check_list);
1126  stack_free(&context.uns);
1127 }
void free_abc_checked(abc_checked p)
Definition: abc_private.c:19
persistant_statement_to_control make_persistant_statement_to_control(void)
Definition: ri.c:1594
void free_persistant_statement_to_control(persistant_statement_to_control p)
Definition: ri.c:1561
static bool push_uns(unstructured u, top_down_abc_context_p context)
static bool top_down_abc_flt(statement s, top_down_abc_context_p context)
The old algorithm is false in the case of incorrect code, because regions are computed with the assum...
static bool store_mapping(control c, top_down_abc_context_p context)
static void top_down_abc_rwt(statement s, top_down_abc_context_p context)
static void pop_uns(unstructured __attribute__((unused)) u, top_down_abc_context_p context)
static abc_checked initiliaze_marked_list()
void gen_context_multi_recurse(void *o, void *context,...)
Multi-recursion with context function visitor.
Definition: genClib.c:3373
hash_table hash_table_make(hash_key_type key_type, size_t size)
Definition: hash.c:294
void hash_table_free(hash_table htp)
this function deletes a hash table that is no longer useful.
Definition: hash.c:327
@ hash_pointer
Definition: newgen_hash.h:32
void stack_free(stack *)
type, bucket_size, policy
Definition: stack.c:292
stack stack_make(int, int, int)
allocation
Definition: stack.c:246
#define unstructured_domain
newgen_type_domain_defined
Definition: ri.h:442
#define control_domain
newgen_controlmap_domain_defined
Definition: ri.h:98
The following data structure is the context of top_down_abc: The read_marked_list marks if one bound ...

References control_domain, copy_abc_checked(), free_abc_checked(), free_persistant_statement_to_control(), gen_context_multi_recurse(), gen_null(), hash_pointer, hash_table_free(), hash_table_make(), initiliaze_marked_list(), make_persistant_statement_to_control(), module_statement, pop_uns(), push_uns(), stack_free(), stack_make(), statement_domain, store_mapping(), top_down_abc_flt(), top_down_abc_rwt(), and unstructured_domain.

Referenced by array_bound_check_top_down().

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

Variable Documentation

◆ current_entity

◆ current_max

int current_max
static

◆ current_min

int current_min = 0
static

Definition at line 597 of file array_bound_check_top_down.c.

Referenced by min_statement_write_flt(), and minimum_ordering().

◆ godown

bool godown = false
static

Definition at line 728 of file array_bound_check_top_down.c.

Referenced by top_down_abc_array(), and top_down_abc_flt().

◆ lexp

◆ number_of_added_tests

int number_of_added_tests
static

◆ number_of_bound_violations

int number_of_bound_violations
static

◆ test_sequence

statement test_sequence = statement_undefined
static