PIPS
utils.c
Go to the documentation of this file.
1 /*
2 
3  $Id: utils.c 23155 2016-07-19 15:19:18Z irigoin $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 #include <stdio.h>
28 
29 #include "arithmetique.h"
30 #include "boolean.h"
31 #include "vecteur.h"
32 #include "contrainte.h"
33 #include "sc.h"
34 
35 #include "genC.h"
36 #include "linear.h"
37 #include "ri.h"
38 #include "effects.h"
39 #include "ri-util.h"
40 #include "effects-util.h"
41 
42 #include "misc.h"
43 #include "transformer.h"
44 #include "semantics.h"
45 
46 /* Return true if statement s is reachable according to its precondition. */
48  bool empty_p(transformer))
49 {
50  transformer pre;
51  bool feasible_p;
52 
54 
55  ifdebug(6) {
56  int so = statement_ordering(s);
57  debug(6, "parametric_statement_feasible_p",
58  "Begin for statement %d (%d,%d) and precondition %p\n",
60  ORDERING_NUMBER(so), ORDERING_STATEMENT(so), pre);
61  }
62 
63  feasible_p = !empty_p(pre);
64 
65  debug(6, "parametric_statement_feasible_p", " End with feasible_p = %d\n",
66  feasible_p);
67 
68  return feasible_p;
69 }
70 
71 /* Return false if precondition of statement s is transformer_empty() */
73 {
75  /* bool feasible_p = !transformer_empty_p(pre); */
76 
77  /* FI: this test is much stronger than I intended. I just wanted
78  * to check that the predicate of pre was exactly sc_empty()!
79  *
80  * Now I'm afraid to change it. suppress_dead_code isn't that slow
81  * on ocean. I'm not sure that I could validate Transformations.
82  */
83 
85 
86  bool feasible_p = !sc_empty_p(sc);
87 
88  return feasible_p;
89 }
90 
91 /* Return true if statement s is reachable according to its precondition. */
93 {
95  return feasible_p;
96 }
97 
98 /* Return true if statement s is reachable according to its precondition. */
100 {
101  bool feasible_p =
103  return feasible_p;
104 }
105 
106 ␌
107 /* A range cannot be tested exactly wrt a precondition
108  * You can try to prove that it is empty or you can
109  * try to prove that it is not empty. In both case, you may fail
110  * and be unable to decide emptiness or non-emptiness.
111  */
113 {
114  bool empty = false;
115 
116  empty = check_range_wrt_precondition(r, p, true);
117 
118  return empty;
119 }
120 
122 {
123  bool non_empty = false;
124 
125  non_empty = check_range_wrt_precondition(r, p, false);
126 
127  return non_empty;
128 }
129 
130 /* FI: this function is outdated because it does not compute the
131  transformers for the range expressions, because it does not take
132  side effects into account and ... We might need a
133  range_to_transformer() or loop_range_to_transformer() instead and
134  check that its range is empty. */
135 bool check_range_wrt_precondition(range r, transformer p, bool check_empty)
136 {
137  bool check = true;
138  expression lb_e = range_lower(r);
139  expression ub_e = range_upper(r);
140  expression incr_e = range_increment(r);
141  normalized lb_n = NORMALIZE_EXPRESSION(lb_e);
142  normalized ub_n = NORMALIZE_EXPRESSION(ub_e);
143  normalized incr_n = NORMALIZE_EXPRESSION(incr_e);
144  int incr_lb = 0;
145  int incr_ub = 0;
146 
147  pips_debug(8, "begins for check %s\n", check_empty? "empty" : "non-empty");
148 
149  if(normalized_undefined_p(lb_n)
150  || normalized_undefined_p(lb_n)
151  || normalized_undefined_p(lb_n)) {
152  user_error("check_range_wrt_precondition",
153  "Expression should have been normalized. "
154  "Maybe you have DOALL statements in your "
155  "supposedly sequential source code!\n");
156  }
157 
158  if(normalized_linear_p(lb_n)
159  && normalized_linear_p(ub_n)
160  && normalized_linear_p(incr_n)) {
161 
162  /* gather information about the increment sign */
163  expression_and_precondition_to_integer_interval(incr_e, p, &incr_lb, &incr_ub);
164 
165  if(incr_lb==0 && incr_ub==0) {
166  user_error("check_range_wrt_precondition",
167  "Range with illegal zero increment\n");
168  }
169 
170  if(incr_lb<=incr_ub) {
174 
175  if(check_empty) {
176  /* Try to prove that no iterations are performed */
177  if(incr_lb>=1) {
178  Pvecteur ni = vect_substract(lb_v, ub_v);
179 
180  ci = contrainte_make(ni);
181  }
182  else if(incr_ub<=-1) {
183  Pvecteur ni = vect_substract(ub_v, lb_v);
184 
185  ci = contrainte_make(ni);
186  }
187  else {
188  /* Without information about the increment sign,
189  * you cannot make a decision. Should we accept
190  * increments greater or equal to zero? Lesser
191  * or equal to zero?
192  */
193  check = false;
194  }
195  }
196  else {
197  /* Try to prove that at least one iteration is performed */
198  if(incr_lb>=1) {
199  Pvecteur ni = vect_substract(ub_v, lb_v);
200 
201  vect_add_elem(&ni, TCST, (Value) 1);
202  ci = contrainte_make(ni);
203  }
204  else if(incr_ub<=-1) {
205  Pvecteur ni = vect_substract(lb_v, ub_v);
206 
207  vect_add_elem(&ni, TCST, (Value) 1);
208  ci = contrainte_make(ni);
209  }
210  else {
211  /* Without information about the increment sign,
212  * you cannot make a decision. Should we accept
213  * increments greater or equal to zero? Lesser
214  * or equal to zero?
215  */
216  check = false;
217  }
218  }
219 
220  if(check) {
221  /* No decision has been made yet */
222  /* a numerical range may be empty although no information is available */
226 
227  s = sc_inequality_add(s, ci);
228 
229  ifdebug(8) {
230  debug(8, "check_range_wrt_precondition",
231  "Test feasibility for system:\n");
232  sc_fprint(stderr, s, (char * (*)(Variable)) dump_value_name);
233  }
234 
235  /* s = sc_strong_normalize4(s, (char * (*)(Variable)) entity_local_name); */
236  s = sc_strong_normalize5(s, (char * (*)(Variable)) entity_local_name);
237  /*s = sc_elim_redund(s);*/
238  ifdebug(8) {
239  debug(8, "check_range_wrt_precondition",
240  "System after normalization:\n");
241  sc_fprint(stderr, s, (char * (*)(Variable)) dump_value_name);
242  }
243 
244  if(SC_EMPTY_P(s)) {
245  check = true;
246  }
247  else {
248  sc_rm(s);
249  check = false;
250  }
251  }
252  }
253  else {
254  debug(8, "check_range_wrt_precondition",
255  "The loop is never executed because it is in a dead code section\n");
256  check = check_empty;
257  }
258  }
259  else {
260  debug(8, "check_range_wrt_precondition",
261  "No decision can be made because the increment sign is unknown\n");
262  check = false;
263  }
264 
265  debug(8, "check_range_wrt_precondition",
266  "ends with check=%s for check_empty=%s\n",
267  bool_to_string(check), bool_to_string(check_empty));
268 
269  return check;
270 }
271 ␌
272 /* A condition cannot be tested exactly wrt a precondition You can try to
273  * prove that it is always true (because it is never false) or you can try
274  * to prove that it is always false (because it is never true). In both
275  * case, you may fail and be unable to decide emptiness or non-emptiness. */
277 {
278  bool empty = false;
279 
281 
282  return empty;
283 }
284 
286 {
287  bool non_empty = false;
288 
289  non_empty = check_condition_wrt_precondition(c, p, false);
290 
291  return non_empty;
292 }
293 
295  transformer pre,
296  bool check_true)
297 {
298  bool check = true;
299  transformer twc = transformer_dup(pre);
300 
301  pips_debug(8, "begins for check %s\n",
302  bool_to_string(check_true));
303 
304  if(check_true) {
305  twc = transformer_add_condition_information(twc, c, pre, false);
306  }
307  else {
308  /* Check that is is always false in a store s such that p(s) */
309  twc = transformer_add_condition_information(twc, c, pre, true);
310  }
311  check = transformer_empty_p(twc);
312 
313  pips_debug(8, "ends with check=%s for check_true=%s\n",
314  bool_to_string(check), bool_to_string(check_true));
315 
316  return check;
317 }
318 ␌
319 /* Evaluate expression e in context p, assuming that e is an integer
320  * expression. If p is empty, return an empty interval.
321  *
322  * Could be more general, I'm lazy (FI).
323  */
324 void
326  transformer p,
327  int * plb,
328  int * pub)
329 {
331 
332  if(normalized_linear_p(n)) {
334  if(vect_constant_p(v)) {
335  if(VECTEUR_NUL_P(v)) {
336  *plb = 0;
337  }
338  else {
339  Value vi = vect_coeff(TCST, v);
340  *plb = VALUE_TO_INT(vi);
341  }
342  *pub = *plb;
343  }
344  else if(vect_size(v) == 1) {
348  Value lb = VALUE_ZERO, ub = VALUE_ZERO;
349  entity var = (entity) vecteur_var(v);
350 
351  if(sc_minmax_of_variable(s, (Variable) var,
352  &lb, &ub)) {
353  *plb = value_min_p(lb)? INT_MIN : VALUE_TO_INT(lb);
354  *pub = value_max_p(ub)? INT_MAX : VALUE_TO_INT(ub);
355  }
356  else {
357  /* precondition p is not feasible */
358  *plb = 1;
359  *pub = 0;
360  }
361  }
362  else {
363  /* OK, we could do something: add a pseudo-variable
364  * equal to expression e and check its min abd max values
365  */
366  *plb = INT_MIN;
367  *pub = INT_MAX;
368  }
369  }
370  else {
371  /* we are not handling an affine integer expression */
372  *plb = INT_MIN;
373  *pub = INT_MAX;
374  }
375 
376 }
377 
378 /* Could be used for bool expressions too? Extended to any kind of expression?
379  *
380  * p is assumed to be a real precondition, i.e. a transformer_range().
381  *
382  * This function is used by semantics as well as exported to other
383  * passes. To take care of debug_on()/debug_off(), set and
384  * reset_analyzed_types(), a different wrapper is needed.
385  */
387  transformer p,
388  int * plb,
389  int * pub)
390 {
391  debug_on("SEMANTICS_DEBUG_LEVEL");
392  // set_analyzed_types();
393  type t = expression_to_type(e);
395  transformer et = integer_expression_to_transformer(tmp, e, p, true);
396 
397  /* If expression e is transformer-wise side-effect free (i.e. the ABSTRACT store is not modified)*/
403  Value lb = VALUE_ZERO, ub = VALUE_ZERO;
404 
405  if(sc_minmax_of_variable(s, (Variable) tmp,
406  &lb, &ub)) {
407  *plb = value_min_p(lb)? INT_MIN : VALUE_TO_INT(lb);
408  *pub = value_max_p(ub)? INT_MAX : VALUE_TO_INT(ub);
409  }
410  else {
411  /* precondition p is not feasible */
412  *plb = 1;
413  *pub = 0;
414  }
415  }
416  else {
417  *plb = INT_MIN;
418  *pub = INT_MAX;
419  }
420  //reset_analyzed_types();
421  debug_off();
422 }
423 
424 /* Should be used by previous function,
425  * integer_expression_and_precondition_to_integer_interval()
426  */
428  transformer p,
429  int * plb,
430  int * pub)
431 {
435  Value lb = VALUE_ZERO, ub = VALUE_ZERO;
436 
437  if(sc_minmax_of_variable(s, (Variable) v,
438  &lb, &ub)) {
439  *plb = value_min_p(lb)? INT_MIN : VALUE_TO_INT(lb);
440  *pub = value_max_p(ub)? INT_MAX : VALUE_TO_INT(ub);
441  }
442  else {
443  /* precondition p is not feasible */
444  *plb = 1;
445  *pub = 0;
446  }
447 }
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
#define VALUE_ZERO
#define VALUE_TO_INT(val)
#define value_min_p(val)
int Value
#define value_max_p(val)
transformer transformer_dup(transformer t_in)
transformer package - basic routines
Definition: basic.c:49
#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
bool vect_constant_p(Pvecteur)
bool vect_constant_p(Pvecteur v): v contains only a constant term, may be zero
Definition: predicats.c:211
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
int vect_size(Pvecteur v)
package vecteur - reductions
Definition: reductions.c:47
#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 debug_off()
Definition: misc-local.h:160
#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
string bool_to_string(bool)
Definition: string.c:243
char * dump_value_name(entity e)
char * dump_value_name(e): used as functional argument because entity_name is a macro
Definition: io.c:128
#define ORDERING_NUMBER(o)
#define ORDERING_STATEMENT(o)
#define NORMALIZE_EXPRESSION(e)
const char * entity_local_name(entity e)
entity_local_name modified so that it does not core when used in vect_fprint, since someone thought t...
Definition: entity.c:453
type expression_to_type(expression)
For an array declared as int a[10][20], the type returned for a[i] is int [20].
Definition: type.c:2486
#define transformer_undefined_p(x)
Definition: ri.h:2848
#define normalized_linear_p(x)
Definition: ri.h:1779
#define range_upper(x)
Definition: ri.h:2290
#define statement_ordering(x)
Definition: ri.h:2454
#define range_increment(x)
Definition: ri.h:2292
#define transformer_relation(x)
Definition: ri.h:2873
#define transformer_arguments(x)
Definition: ri.h:2871
#define range_lower(x)
Definition: ri.h:2288
#define normalized_undefined_p(x)
Definition: ri.h:1746
#define statement_number(x)
Definition: ri.h:2452
#define normalized_linear(x)
Definition: ri.h:1781
#define predicate_system(x)
Definition: ri.h:2069
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
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
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
Psysteme sc_dup(Psysteme ps)
Psysteme sc_dup(Psysteme ps): should becomes a link.
Definition: sc_alloc.c:176
bool sc_minmax_of_variable(Psysteme ps, Variable var, Value *pmin, Value *pmax)
void sc_minmax_of_variable(Psysteme ps, Variable var, Value *pmin, *pmax): examine un systeme pour tr...
Definition: sc_eval.c:143
Psysteme sc_inequality_add(Psysteme sc, Pcontrainte c)
Definition: sc_insert_eq.c:108
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
Psysteme sc_strong_normalize5(Psysteme ps, char *(*variable_name)(Variable))
transformer transformer_add_condition_information(transformer pre, expression c, transformer context, bool veracity)
Definition: expression.c:1092
transformer integer_expression_to_transformer(entity v, expression expr, transformer pre, bool is_internal)
Do check wrt to value mappings...
Definition: expression.c:3476
bool empty_range_wrt_precondition_p(range r, transformer p)
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
static bool parametric_statement_feasible_p(statement s, bool empty_p(transformer))
Return true if statement s is reachable according to its precondition.
Definition: utils.c:47
void integer_expression_and_precondition_to_integer_interval(expression e, transformer p, int *plb, int *pub)
Could be used for bool expressions too? Extended to any kind of expression?
Definition: utils.c:386
bool statement_weakly_feasible_p(statement s)
Return false if precondition of statement s is transformer_empty()
Definition: utils.c:72
bool check_range_wrt_precondition(range r, transformer p, bool check_empty)
FI: this function is outdated because it does not compute the transformers for the range expressions,...
Definition: utils.c:135
bool condition_false_wrt_precondition_p(expression c, transformer p)
Definition: utils.c:285
bool condition_true_wrt_precondition_p(expression c, transformer p)
A condition cannot be tested exactly wrt a precondition You can try to prove that it is always true (...
Definition: utils.c:276
bool statement_feasible_p(statement s)
Return true if statement s is reachable according to its precondition.
Definition: utils.c:92
bool check_condition_wrt_precondition(expression c, transformer pre, bool check_true)
Definition: utils.c:294
void expression_and_precondition_to_integer_interval(expression e, transformer p, int *plb, int *pub)
Evaluate expression e in context p, assuming that e is an integer expression.
Definition: utils.c:325
void integer_value_and_precondition_to_integer_interval(entity v, transformer p, int *plb, int *pub)
Should be used by previous function, integer_expression_and_precondition_to_integer_interval()
Definition: utils.c:427
bool non_empty_range_wrt_precondition_p(range r, transformer p)
Definition: utils.c:121
bool statement_strongly_feasible_p(statement s)
Return true if statement s is reachable according to its precondition.
Definition: utils.c:99
transformer load_statement_precondition(statement)
#define ifdebug(n)
Definition: sg.c:47
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
bool transformer_strongly_empty_p(transformer t)
If true is returned, the transformer certainly is empty.
Definition: transformer.c:2465
bool transformer_empty_p(transformer t)
If true is returned, the transformer certainly is empty.
Definition: transformer.c:2455
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
entity make_local_temporary_value_entity(type)
Definition: value.c:605
@ empty
b1 < bj -> h1/hj = empty
Definition: union-local.h:64
#define TCST
VARIABLE REPRESENTANT LE TERME CONSTANT.
#define vecteur_var(v)
struct Svecteur * Pvecteur
#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
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
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
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
Value vect_coeff(Variable var, Pvecteur vect)
Variable vect_coeff(Variable var, Pvecteur vect): coefficient de coordonnee var du vecteur vect —> So...
Definition: unaires.c:228