PIPS
loop_bound_minimization.c
Go to the documentation of this file.
1 /*
2 
3  $Id: loop_bound_minimization.c 23495 2018-10-24 09:19:47Z coelho $
4 
5  Copyright 1989-2014 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 
25 // do not compile unless required
26 #include "phases.h"
27 #if defined(BUILDER_LOOP_BOUND_MINIMIZATION_WITH_OUT_REGIONS) || \
28  defined(BUILDER_DEAD_CODE_ELIMINATION) // also used here...
29 
30 #ifdef HAVE_CONFIG_H
31  #include "pips_config.h"
32 #endif
33 
34 /**
35  * Pass: LOOP_BOUND_MINIMIZATION_WITH_OUT_REGIONS
36  * Debug mode: LOOP_BOUND_MINIMIZATION_DEBUG_LEVEL
37  * Properties used:
38  * - FLAG_LOOPS_DO_LOOPS_ONLY (not implemented with FALSE, can really be implemented?)
39  * Resource needed:
40  * - preconditions
41  * - out_regions
42  *
43  */
44 
45 #include <stdlib.h>
46 #include <stdio.h>
47 
48 #include "genC.h"
49 #include "linear.h"
50 
51 #include "misc.h"
52 #include "pipsdbm.h"
53 #include "properties.h"
54 
55 #include "ri.h"
56 #include "ri-util.h"
57 #include "prettyprint.h" // for debugging
58 
59 #include "effects.h"
60 #include "effects-util.h"
61 
62 #include "semantics.h" // used
63 #include "effects-generic.h" // used
64 #include "effects-convex.h" // print_inout_regions
65 
66 #include "transformer.h" // print_any_transformer
67 #include "conversion.h" // constraints_to_loop_bound
68 
69 typedef struct ctx_lbm {
70  bool do_loop_only_p;
71 } ctx_lbm_t;
72 
73 static void loop_bound_minimization(statement s, _UNUSED_ ctx_lbm_t ctx) {
74  pips_debug(1, "begin\n");
75  loop l = statement_loop(s);
76  entity index = loop_index(l);
77  range r = loop_range(l);
78  statement body = loop_body(l);
79 
80  //precondition of the loop to determine the lower/upper bounds of the initial loop
81  // The precondition permit to not recompute the lower/upper bounds and build the sc
82  transformer body_prec = load_statement_precondition(body);
83 
84  //OUT regions of the loop body to find if the useful index are the same that the lower/upper bounds
85  list loutregion_body = load_statement_out_regions(body);
86 
87  Psysteme loop_sc = predicate_system(transformer_relation(body_prec));
88  // loop_sc must already be normalized (else the transformer must also be disgusting)
89  //loop_sc = sc_safe_normalize(loop_sc);
90 
91  ifdebug(2) {
92  pips_debug(2, "statement:\n");
93  print_statement(s);
94  pips_debug(2, "loutregion_body:\n");
95  print_inout_regions(loutregion_body);
96  pips_debug(2, "body_prec:\n");
97  print_any_transformer(body_prec);
98  }
99 
100  // sc_useful represent the useful value for the index
101  // initialize it with the empty set
102  // then add foreach OUT regions, add the region of the index that can be use with union (convex_hull)
103  Pbase base_index = base_add_variable(BASE_NULLE, (Variable) index);
104  Psysteme sc_useful = sc_empty(base_copy(base_index));
105 
106  //For each OUT Regions find the lower/upper index used
107  VOLATILE_FOREACH(EFFECT, reg, loutregion_body) {
108  //if anywhere effect, can say nothing
109  if (anywhere_effect_p(reg)) {
110  // sc_useful as the whole world, ie. with no constraint
111  sc_useful = sc_free(sc_useful);
112  sc_useful = sc_rn(base_copy(base_index));
113  break;
114  }
115 
116  descriptor d = effect_descriptor(reg);
117  if (descriptor_none_p(d)) {
118  //Nothing to do
119  //This case can really happens?
120  }
121  else if (descriptor_convex_p(d)) {
122  Psysteme local_sc_useful = descriptor_convex(d);
123 
124  ifdebug(3) {
125  pips_debug(3, "before projection local_sc_useful:\n");
127  pips_debug(3, "Nb_eq %d , Nb_ineq %d, dimension %d\n",
128  (local_sc_useful)->nb_eq, (local_sc_useful)->nb_ineq,
129  (local_sc_useful)->dimension);
130  }
131 
132  // remove the PHI variable
136  {
137  entity indexent = expression_to_entity(index);
139  pips_user_warning("overflow_error: Not managed..., "
140  "Need some normalization?\nDon't do any minimization");
141  sc_useful = sc_free(sc_useful);
142  sc_useful = sc_rn(base_copy(base_index));
143  break;
144  }
145  TRY {
146  ifdebug(3) {
147  print_entity_variable(indexent);
149  }
150  sc_and_base_projection_along_variable_ofl_ctrl(&local_sc_useful, indexent, FWD_OFL_CTRL);
152  }
153  }
154 
155  ifdebug(3) {
156  pips_debug(3, "after projection local_sc_useful:\n");
158  pips_debug(3, "Nb_eq %d , Nb_ineq %d, dimension %d\n",
159  (local_sc_useful)->nb_eq, (local_sc_useful)->nb_ineq,
160  (local_sc_useful)->dimension);
161  }
162 
163  // Union of local_sc_useful and sc_useful
164  Psysteme temp = sc_useful; //for memory leak
165  sc_useful = sc_cute_convex_hull(temp, local_sc_useful);
166  temp = sc_free(temp);
167  }
168  else if (descriptor_convexunion_p(d)) {
169  // Really occur?
170  pips_user_warning("Not done yet...\n");
171  }
172  else {
173  pips_internal_error("This case never occurs\n descriptor = %d\n",
174  descriptor_tag(d));
175  }
176  }
177  ifdebug(2) {
178  pips_debug(2, "Union sc_useful:\n");
180  pips_debug(2, "Nb_eq %d , Nb_ineq %d, dimension %d\n", (sc_useful)->nb_eq, (sc_useful)->nb_ineq, (sc_useful)->dimension);
181 
182  pips_debug(2, "loop_sc:\n");
184  pips_debug(2, "Nb_eq %d , Nb_ineq %d, dimension %d\n", (loop_sc)->nb_eq, (loop_sc)->nb_ineq, (loop_sc)->dimension);
185  }
186 
187  //Intersection of sc_useful with loop_sc to be sure that will not add iteration,
188  // it's made with an append follow by a feasibility to check that the sc is correct
189  if (sc_empty_p(sc_useful) || sc_rn_p(sc_useful)) {
190  if (sc_empty_p(sc_useful)) {
191  pips_user_warning("Do we really enter the loop? Isn't an unreachable loop?\n"
192  "lower=%s, upper=%s, inc=%s\n",
194  ifdebug(3)
195  print_statement(s);
196  }
197  sc_useful = sc_free(sc_useful);
198  sc_useful = loop_sc;
199  }
200  else {
201  bool feasible = true;
202  sc_useful = sc_safe_append(sc_safe_normalize(sc_useful), loop_sc);
203  sc_useful = sc_safe_normalize(sc_useful);
204 
205  ifdebug(3) {
206  pips_debug(3, "after sc_safe_append and normalization of sc_useful:\n");
208  pips_debug(3, "Nb_eq %d , Nb_ineq %d, dimension %d\n", (sc_useful)->nb_eq, (sc_useful)->nb_ineq, (sc_useful)->dimension);
209  }
210 
212  {
213  pips_user_warning("overflow error, do nothing for loop bound.\n");
214  sc_useful = sc_free(sc_useful);
215  sc_useful = loop_sc;
216  feasible = true;
217  }
218  TRY
219  {
220  feasible = sc_integer_feasibility_ofl_ctrl(sc_useful,
221  FWD_OFL_CTRL, true);
223  }
224 
225  // This case normally never occur, the intersection must always be feasible
226  if (!feasible) {
227  pips_user_warning("intersection NULL, this case never happen? \n");
228  ifdebug(1) {
229  pips_debug(1, "unfeasibility sc_useful:\n");
231  pips_debug(1, "Nb_eq %d , Nb_ineq %d, dimension %d\n", (sc_useful)->nb_eq, (sc_useful)->nb_ineq, (sc_useful)->dimension);
232 
233  pips_debug(1, "unfeasibility loop_sc:\n");
235  pips_debug(1, "Nb_eq %d , Nb_ineq %d, dimension %d\n", (loop_sc)->nb_eq, (loop_sc)->nb_ineq, (loop_sc)->dimension);
236  }
237  sc_useful = sc_free(sc_useful);
238  sc_useful = loop_sc;
239  }
240 
241  }
242  ifdebug(2) {
243  pips_debug(2, "after check feasibility sc_useful:\n");
245  pips_debug(2, "Nb_eq %d , Nb_ineq %d, dimension %d\n", (sc_useful)->nb_eq, (sc_useful)->nb_ineq, (sc_useful)->dimension);
246  }
247 
248  //Try to improve the loop bounds
249  //if sc_useful == loop_sc, nothing to do to improve loop bound
250  if (sc_useful != loop_sc && !sc_equal_p(sc_useful, loop_sc)) {
251  //Make a row_echelon to only keep constraint for index
252  //(It's may have other way to do that)
253  pips_debug(3, "sc_useful != loop_sc\n");
254  Psysteme condition = SC_UNDEFINED,
255  enumeration = SC_UNDEFINED;
256 
257  pips_debug(5, "algorithm_row_echelon_generic start\n");
258  algorithm_row_echelon(sc_useful, base_index,
259  &condition, &enumeration);
260  pips_debug(5, "algorithm_row_echelon_generic end\n");
261 
262  ifdebug(5) {
263  pips_debug(5, "result of algorithm_row_echelon_generic:\n");
264  pips_debug(5, "base_index:\n");
266 
267  pips_debug(5, "sc_useful:\n");
269  pips_debug(5, "Nb_eq %d , Nb_ineq %d, dimension %d\n", (sc_useful)->nb_eq, (sc_useful)->nb_ineq, (sc_useful)->dimension);
270 
271  pips_debug(5, "condition:\n");
273  pips_debug(5, "Nb_eq %d , Nb_ineq %d, dimension %d\n", (condition)->nb_eq, (condition)->nb_ineq, (condition)->dimension);
274 
275  pips_debug(5, "enumeration:\n");
277  pips_debug(5, "Nb_eq %d , Nb_ineq %d, dimension %d\n", (enumeration)->nb_eq, (enumeration)->nb_ineq, (enumeration)->dimension);
278  }
279 
280  //determine new lower/upper bound
281  // code inspire from systeme_to_loop_nest
282  Pcontrainte c, lower, upper;
283  Variable var = (Variable) index;
285  sc_transform_eg_in_ineg(enumeration); /* ??? could do a better job with = */
286  c = sc_inegalites(enumeration);
287  pips_assert("no equalities, now", sc_nbre_egalites(enumeration)==0);
288 
289  constraints_for_bounds(var, &c, &lower, &upper);
290  sc_inegalites(enumeration) = c;
291 
292  //new lower bound
293  if( !CONTRAINTE_UNDEFINED_P(lower) ) {
294  expression new_lower_exp =
295  constraints_to_loop_bound(lower, var, true, divide);
296  expression low = range_lower(r); //for memory leak
297  range_lower(r) = new_lower_exp;
298  free_expression(low);
299  ifdebug(3) {
300  pips_debug(3, "new_lower_exp:\n");
301  print_expression(new_lower_exp);
302  }
303  }
304  //new upper bound
305  if( !CONTRAINTE_UNDEFINED_P(upper) ) {
306  expression new_upper_exp =
307  constraints_to_loop_bound(upper, var, false, divide);
308  expression upper = range_upper(r); //for memory leak
309  range_upper(r) = new_upper_exp;
310  free_expression(upper);
311  ifdebug(3) {
312  pips_debug(3, "new_upper_exp:\n");
313  print_expression(new_upper_exp);
314  }
315  }
316 
317  //free the memory
318  lower = contraintes_free(lower);
319  upper = contraintes_free(upper);
320  sc_useful = sc_free(sc_useful);
321  enumeration = sc_free(enumeration);
322  condition = sc_free(condition);
323  }
324 
325  pips_debug(1, "end\n");
326 }
327 
328 static void statement_loop_bound_minimization(statement s, ctx_lbm_t *ctx) {
330  if (instruction_loop_p(i)) {
331  loop_bound_minimization(s, *ctx);
332  }
333  else if (!ctx->do_loop_only_p &&
335  pips_user_warning("Not implemented. Can only treat DO loop kind of loop.\n");
336  }
337 }
338 
339 
341  bool good_result_p = true;
342 
343  ctx_lbm_t ctx;
344  ctx.do_loop_only_p = get_bool_property("FLAG_LOOPS_DO_LOOPS_ONLY");
345 
347  statement_domain, gen_true2, statement_loop_bound_minimization);
348 
349  return good_result_p;
350 }
351 
352 /**
353  * PIPS pass
354  */
356  //entity module;
358  bool good_result_p = true;
359 
360  debug_on("LOOP_BOUND_MINIMIZATION_DEBUG_LEVEL");
361  pips_debug(1, "begin\n");
362 
363  //-- configure environment --//
365  //module = get_current_module_entity();
366 
368  db_get_memory_resource(DBR_CODE, module_name, true) );
370 
371  pips_assert("Statement should be OK before...",
373 
375 
376 
377  //-- get dependencies --//
379  db_get_memory_resource(DBR_OUT_REGIONS, module_name, true));
381  db_get_memory_resource(DBR_PRECONDITIONS, module_name, true) );
382 
383 
384  //-- Make the job -- //
386 
387  pips_assert("Statement should be OK after...",
389 
390 
391  //-- Save modified code to database --//
393 
399 
400  pips_debug(1, "end\n");
401  debug_off();
402 
403  return (good_result_p);
404 }
405 
406 #endif // BUILDER_LOOP_BOUND_MINIMIZATION_WITH_OUT_REGIONS && others...
bool statement_consistent_p(statement p)
Definition: ri.c:2195
void free_expression(expression p)
Definition: ri.c:853
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
static statement module_statement
Definition: alias_check.c:125
#define CATCH(what)
@ overflow_error
#define UNCATCH(what)
#define TRY
#define divide(a, b)
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
#define CONTRAINTE_UNDEFINED_P(c)
Pcontrainte contraintes_free(Pcontrainte pc)
Pcontrainte contraintes_free(Pcontrainte pc): desallocation de toutes les contraintes de la liste pc.
Definition: alloc.c:226
void constraints_for_bounds(Variable, Pcontrainte *, Pcontrainte *, Pcontrainte *)
void constraints_for_bounds(var, pinit, plower, pupper) Variable var; Pcontrainte *pinit,...
Definition: unaires.c:176
expression constraints_to_loop_bound(Pcontrainte, Variable, bool, entity)
expression constraints_to_loop_bound(c, var, is_lower)
void print_inout_regions(list)
void reset_out_effects(void)
void set_out_effects(statement_effects)
list load_statement_out_regions(statement)
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
const char * pips_region_user_name(entity)
char * pips_region_user_name(entity ent) output : the name of entity.
Definition: prettyprint.c:169
bool anywhere_effect_p(effect)
Is it an anywhere effect? ANYMMODULE:ANYWHERE
Definition: effects.c:346
#define descriptor_tag(x)
Definition: effects.h:595
#define descriptor_convex_p(x)
Definition: effects.h:599
#define effect_descriptor(x)
Definition: effects.h:646
#define descriptor_convexunion_p(x)
Definition: effects.h:596
#define descriptor_convex(x)
Definition: effects.h:601
#define descriptor_none_p(x)
Definition: effects.h:602
#define EFFECT(x)
EFFECT.
Definition: effects.h:608
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
#define gen_context_recurse(start, ctxt, domain_number, flt, rwt)
Definition: genC.h:285
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
void reset_current_module_statement(void)
Reset the current module statement.
Definition: static.c:221
statement set_current_module_statement(statement)
Set the current module statement.
Definition: static.c:165
statement get_current_module_statement(void)
Get the current module statement.
Definition: static.c:208
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
bool gen_true2(__attribute__((unused)) gen_chunk *u1, __attribute__((unused)) void *u2)
Definition: genClib.c:2785
#define VOLATILE_FOREACH(_fe_CASTER, _fe_item, _fe_list)
Definition: newgen_list.h:186
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
loop statement_loop(statement)
Get the loop of a statement.
Definition: statement.c:1374
static list indices
Definition: icm.c:204
void base_fprint(FILE *f, Pbase b, get_variable_name_t variable_name)
void base_fprint(FILE * f, Pbase b, char * (*variable_name)()): impression d'une base sur le fichier ...
Definition: io.c:342
#define debug_on(env)
Definition: misc-local.h:157
#define _UNUSED_
Definition: misc-local.h:232
#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 pips_internal_error
Definition: misc-local.h:149
#define debug_off()
Definition: misc-local.h:160
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
transformer print_any_transformer(transformer tf)
For debugging without problem from temporary values.
Definition: io.c:56
Psysteme sc_cute_convex_hull(Psysteme, Psysteme)
returns s1 v s2.
Definition: sc_enveloppe.c:369
void print_entity_variable(entity e)
print_entity_variable(e)
Definition: entity.c:56
void print_expression(expression e)
no file descriptor is passed to make is easier to use in a debugging stage.
Definition: expression.c:58
string expression_to_string(expression e)
Definition: expression.c:77
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
#define DIVIDE_OPERATOR_NAME
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
entity expression_to_entity(expression e)
just returns the entity of an expression, or entity_undefined
Definition: expression.c:3140
#define loop_body(x)
Definition: ri.h:1644
#define instruction_loop_p(x)
Definition: ri.h:1518
#define range_upper(x)
Definition: ri.h:2290
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define range_increment(x)
Definition: ri.h:2292
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define instruction_forloop_p(x)
Definition: ri.h:1536
#define transformer_relation(x)
Definition: ri.h:2873
#define reference_indices(x)
Definition: ri.h:2328
#define range_lower(x)
Definition: ri.h:2288
#define statement_instruction(x)
Definition: ri.h:2458
#define instruction_whileloop_p(x)
Definition: ri.h:1521
#define loop_range(x)
Definition: ri.h:1642
#define predicate_system(x)
Definition: ri.h:2069
#define loop_index(x)
Definition: ri.h:1640
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
Psysteme sc_empty(Pbase b)
Psysteme sc_empty(Pbase b): build a Psysteme with one unfeasible constraint to define the empty subsp...
Definition: sc_alloc.c:319
Psysteme sc_rn(Pbase b)
Psysteme sc_rn(Pbase b): build a Psysteme without constraints to define R^n, where n is b's dimension...
Definition: sc_alloc.c:336
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
bool sc_integer_feasibility_ofl_ctrl(Psysteme sc, int ofl_ctrl, bool ofl_res)
Psysteme sc_safe_append(Psysteme s1, Psysteme s2)
Psysteme sc_safe_append(Psysteme s1, Psysteme s2) input : output : calcul de l'intersection des polye...
void sc_print(Psysteme ps, get_variable_name_t nom_var)
void sc_print()
Definition: sc_io.c:194
Psysteme sc_free(Psysteme in_ps)
Psysteme sc_free( in_ps ) AL 30/05/94 Free of in_ps.
Definition: sc_list.c:112
char * strdup()
void algorithm_row_echelon(Psysteme scn, Pbase base_index, Psysteme *pcondition, Psysteme *penumeration)
see comments above.
Psysteme sc_safe_normalize(Psysteme ps)
Psysteme sc_safe_normalize(Psysteme ps) output : ps, normalized.
void sc_transform_eg_in_ineg(Psysteme sc)
Package sc.
transformer load_statement_precondition(statement)
void reset_precondition_map(void)
void set_precondition_map(statement_mapping)
else
Definition: set.c:239
#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
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
bool loop_bound_minimization_with_out_regions(const char *)
bool loop_bound_minimization_with_out_regions_on_statement(statement)
loop_bound_minimization.c
#define sc_equal_p(ps1, ps2)
Definition: union-local.h:83
char *(* get_variable_name_t)(Variable)
Definition: vecteur-local.h:62
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
#define FWD_OFL_CTRL
#define BASE_NULLE
MACROS SUR LES BASES.
Pbase base_copy(Pbase b)
Direct duplication.
Definition: alloc.c:300