PIPS
freia_transformations.c
Go to the documentation of this file.
1 /*
2 
3  $Id: freia_transformations.c 23495 2018-10-24 09:19:47Z coelho $
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 
25 #ifdef HAVE_CONFIG_H
26 #include "pips_config.h"
27 #endif
28 
29 #include "genC.h"
30 #include "linear.h"
31 
32 // newgen
33 #include "ri.h"
34 #include "effects.h"
35 
36 #include "misc.h"
37 #include "ri-util.h"
38 #include "effects-util.h"
39 #include "callgraph.h"
40 #include "properties.h"
41 
42 #include "resources.h"
43 #include "pipsdbm.h"
44 
45 #include "control.h" // for clean_up_sequences
46 #include "effects-generic.h" // {set,reset}_proper_rw_effects
47 
48 #include "freia.h"
49 #include "hwac.h"
50 
51 /********************************************************************* UTILS */
52 
53 /* remove "register" qualifier from qualifier list
54  */
56 {
57  FOREACH(qualifier, q, lq)
58  {
59  if (qualifier_register_p(q))
60  {
61  gen_remove_once(&lq, q);
62  // register may be there once
63  return lq;
64  }
65  }
66  return lq;
67 }
68 
69 // this should exists somewhere???
70 // top-down so that it is in ascending order?
71 // I'm not sure that it makes much sense, as
72 // the statement number is expected to be the source code line number?
73 
74 static bool sr_flt(statement s, int * number)
75 {
78  // it seems that sequences are expected not to have a number
79  // just in case, force the property
82  // just add a number if none are available?
83  // otherwise, the initial number is kept
84  statement_number(s) = (*number)++;
85  return true;
86 }
87 
88 static void stmt_renumber(statement s)
89 {
90  int number=1;
92 }
93 
94 /* look for a variable
95  */
96 typedef struct
97 {
98  bool used;
100 } vis_ctx;
101 
102 static void vis_rwt(const reference r, vis_ctx * ctx)
103 {
104  if (reference_variable(r)==ctx->var)
105  {
106  ctx->used = true;
107  gen_recurse_stop(NULL);
108  }
109 }
110 
111 static bool variable_is_used(statement s, entity var)
112 {
113  vis_ctx ctx = { false, var };
115  return ctx.used;
116 }
117 
118 /*********************************** UNROLL FREIA CONVERGENCE LOOPS FOR SPOC */
119 
120 /*
121  The purpose of this transformation is to unroll a special case of
122  while convergence loop by an appropriate amount in order to fill-in
123  the spoc pipeline.
124 
125  The implementation is quick and dirty, could be improved if needed.
126 
127  More could be done on these line if the pipeline before the while is not
128  full, some iterations could be moved there as well. However, the information
129  available when this transformation is applied is not sufficient to decide
130  to do so.
131 
132  The two volumes to be compared are taken from the two last stages.
133  */
134 
135 typedef struct {
136  int morpho;
137  int comp;
138  int vol;
139  bool bad_stuff;
140 } fcs_ctx;
141 
142 static bool fcs_count(statement s, fcs_ctx * ctx)
143 {
144  if (!statement_call_p(s))
145  {
146  ctx->bad_stuff = true;
147  gen_recurse_stop(NULL);
148  }
149  else
150  {
152  if (c)
153  {
154  const char* called = entity_local_name(call_function(c));
155  // could be: dilate + inf + vol or erode + sup + vol
156  if (same_string_p(called, AIPO "erode_8c") ||
157  same_string_p(called, AIPO "erode_6c") ||
158  same_string_p(called, AIPO "dilate_8c") ||
159  same_string_p(called, AIPO "dilate_6c"))
160  ctx->morpho++;
161  else if (same_string_p(called, AIPO "inf") ||
162  same_string_p(called, AIPO "sup"))
163  ctx->comp++;
164  else if (same_string_p(called, AIPO "global_vol"))
165  ctx->vol++;
166  // else { // should do more filtering!
167  // ctx->bad_stuff = true;
168  // gen_recurse_stop(NULL);
169  // }
170  }
171  }
172  return false;
173 }
174 
175 /* @return whether sq contains freia simple calls to E/D, </>, vol, =
176  * this is rather an over approximation of whether it is a convergence
177  * sequence, should be refined...
178  */
180 {
181  fcs_ctx ctx = { 0, 0, 0, false };
183  return ctx.morpho==1 && ctx.comp==1 && ctx.vol==1 && !ctx.bad_stuff;
184 }
185 
186 /* util defined somewhere ?????? */
187 typedef struct { entity ovar, nvar; } subs_ctx;
188 
189 static void ref_rwt(reference r, subs_ctx * ctx)
190 {
191  if (reference_variable(r)==ctx->ovar)
192  reference_variable(r)=ctx->nvar;
193 }
194 
196 {
197  subs_ctx ctx = { ovar, nvar };
199 }
200 
201 static void maybe_unroll_while_rwt(whileloop wl, bool * changed)
202 {
204  {
207  {
208  // unroll!
209  int factor = get_int_property(spoc_depth_prop);
210  pips_assert("some unrolling factor", factor>0);
211  list ol = sequence_statements(sq);
212 
213  // sorry, just a hack to avoid a precise pattern matching
214  statement first = STATEMENT(CAR(ol));
215  pips_assert("s is an assignement", statement_call_p(first));
216  gen_remove_once(&ol, first);
217  list col = gen_copy_seq(ol), nl = NIL;
218  list lass = call_arguments(statement_call(first));
219  entity
220  previous = expression_variable(EXPRESSION(CAR(lass))),
222 
223  // cleanup vol from col
225  FOREACH(statement, s, col)
226  {
229  AIPO "global_vol"))
230  {
231  gen_remove_once(&col, s);
232  vols = copy_statement(s);
233  break;
234  }
235  }
236  pips_assert("vol statement found", vols!=statement_undefined);
237 
238  // do factor-1
239  while (--factor)
240  nl = gen_nconc(gen_full_copy_list(col), nl);
241 
242  // compute "previous" volume for comparison
243  substitute_reference_variable(vols, current, previous);
244 
245  // swith off "register" on previous, if need be...
246  variable v = type_variable(entity_type(previous));
248 
249  // then reuse initial list for the last one
250  sequence_statements(sq) = gen_nconc(nl, CONS(statement, vols, ol));
251 
252  // cleanup temporary list
254 
255  // must renumber...
256  *changed = true;
257  }
258  }
259 }
260 
262 {
263  bool changed = false;
264  gen_context_recurse(s, &changed,
266  return changed;
267 }
268 
269 bool freia_unroll_while(const string module)
270 {
271  // sanity check
272  int factor = get_int_property(spoc_depth_prop);
273  if (factor<=1)
274  {
275  pips_user_warning("cannot unroll with factor=%d\n", factor);
276  return true;
277  }
278 
279  // else, do the job
280  debug_on("PIPS_HWAC_DEBUG_LEVEL");
281  pips_debug(1, "considering module %s\n", module);
282 
283  // else do the stuff
285  (statement) db_get_memory_resource(DBR_CODE, module, true);
288 
289  // do the job
290  bool changed = freia_unroll_while_for_spoc(mod_stat);
291 
292  // update if changed
293  if (changed)
294  {
298  }
299 
300  // cleanup
303  debug_off();
304  return true;
305 }
306 
307 /********************** SPECIAL CASE SCALAR WW DEPENDENCY HANDLING FOR FREIA */
308 /*
309  When switching do-while to while on FREIA convergence loops, the code
310  generates a scalar WW dependency within the sequence which prevents an
311  operation to be merged. Pips is designed to be intelligent about loops
312  for parallelization, whereas I really need some cleverness in sequences
313  for FREIA compilation.
314 
315  The following code, where the reduction is a volume computation in our case:
316 
317  reductionl(image1, &something);
318  somethingelse = something;
319  reduction(image2, &something);
320 
321  should be replaced by:
322 
323  reduction(image1, &somethingelse);
324  reduction(image2, &something);
325 
326  I'm not sure how this transformation could be generalized, possibly
327  based on chains...
328  Moreover, I'm not really sure how much I can rely on effects
329  because of the pointers involved.
330  So this is just a quick hack for my particular case.
331 */
332 
333 /* return the freia reduction entity, or NULL if it does not apply
334  */
336 {
338  {
339  const call c = freia_statement_to_call(s);
340  const string called = (const string) entity_local_name(call_function(c));
341  if (same_string_p(called, AIPO "global_min") ||
342  same_string_p(called, AIPO "global_max") ||
343  same_string_p(called, AIPO "global_min_coord") ||
344  same_string_p(called, AIPO "global_max_coord") ||
345  same_string_p(called, AIPO "global_vol"))
346  {
347  const expression last = EXPRESSION(CAR(gen_last(call_arguments(c))));
348  // should be a call to "&" operator
349  if (expression_address_of_p(last))
350  {
351  const expression arg =
354  return expression_variable(arg);
355  }
356  }
357  }
358  // not found!
359  return NULL;
360 }
361 
362 static void sww_seq_rwt(const sequence sq, bool * changed)
363 {
364  // current status of search
365  statement previous_reduction = NULL;
366  entity previous_variable = NULL;
367  statement assignment = NULL;
368  entity assigned = NULL;
369 
370  // this is a partial O(n) implementation
371  // beware that we may have VERY LONG sequences...
373  {
374  bool tocheck = true;
376  if (red)
377  {
378  if (previous_reduction && assignment && red==previous_variable)
379  {
380  // matched!
381  // replace variable in first reduction
382  hash_table replacements = hash_table_make(hash_pointer, 0);
383  hash_put(replacements, previous_variable, assigned);
384  replace_entities(previous_reduction, replacements);
385  hash_table_free(replacements);
386  // and now useless remove assignment
389  // make assigned NOT a register... just in case
390  variable v = type_variable(entity_type(assigned));
392  // we did something
393  *changed = true;
394  }
395 
396  // restart current status with new found reduction
397  previous_reduction = s;
398  previous_variable = red;
399  assignment = NULL;
400  assigned = NULL;
401  tocheck = false;
402  }
403 
404  // detect reduction variable assignment
405  if (previous_reduction && !assignment &&
407  {
409  expression e1 = EXPRESSION(CAR(args)), e2 = EXPRESSION(CAR(CDR(args)));
411  reference_variable(expression_reference(e2))==previous_variable)
412  {
413  assignment = s;
415  tocheck = false;
416  }
417  }
418 
419  if (tocheck && previous_variable && variable_is_used(s, previous_variable))
420  {
421  // full cleanup
422  previous_reduction = NULL;
423  previous_variable = NULL;
424  assignment = NULL;
425  assigned = NULL;
426  }
427  }
428 }
429 
431 {
432  debug_on("PIPS_HWAC_DEBUG_LEVEL");
433  pips_debug(1, "considering module %s\n", module);
434 
435  // else do the stuff
437  (statement) db_get_memory_resource(DBR_CODE, module, true);
440 
441  // do the job
442  bool changed = false;
443  gen_context_recurse(mod_stat, &changed,
445 
446  // update database if changed
447  if (changed)
448  // stmt_renumber(mod_stat); module_reorder(mod_stat);
450 
453  debug_off();
454  return true;
455 }
456 
457 /********************************************** CLEANUP SOME SCALAR POINTERS */
458 /*
459  // this break assumptions about "simple" deps made in the freia compiler
460  int * foo; // declaration
461  foo = &bla; // only definition
462  *foo = XXX; // only use
463 
464  // remove declaration & definition, and replace assign by
465  bla = XXX;
466 */
467 
468 typedef struct {
469  // entity -> entity
471  // entity -> statement
472  // hash_table declared;
473  // entity -> call
475  // entity -> expression
477  // of entities
480 } rssp_ctx;
481 
482 /* "&v"? return v, else return NULL
483  */
485 {
486  if (!expression_call_p(e)) return NULL;
487  call c = expression_call(e);
488  if (!ENTITY_ADDRESS_OF_P(call_function(c))) return NULL;
489  list la = call_arguments(c);
490  pips_assert("one argument to &", gen_length(la)==1);
491  expression a = EXPRESSION(CAR(la));
492  if (!expression_reference_p(a)) return NULL;
494  if (reference_indices(r)) return NULL;
495  entity v = reference_variable(r);
496  if (entity_scalar_p(v))
497  return v;
498  return NULL;
499 }
500 
501 static bool pointer_candidate_p(entity var)
502 {
503  // other checks?
504  pips_debug(5, "entity %s %d\n", entity_name(var), entity_pointer_p(var));
505  return entity_pointer_p(var);
506 }
507 
508 static void rssp_ref(reference r, rssp_ctx * ctx)
509 {
510  string what = "unknown";
511  entity var = reference_variable(r);
512  pips_debug(8, "reference %p to %s\n", r, entity_name(var));
513  if (pointer_candidate_p(var) && !reference_indices(r))
514  set_add_element(ctx->candidates, ctx->candidates, var);
515  if (set_belong_p(ctx->candidates, var))
516  {
518  if (enc && expression_reference_p(enc) && expression_reference(enc)==r)
519  {
520  call called = (call) gen_get_ancestor(call_domain, enc);
521 
522  pips_debug(8, "called=%p %s\n", called, called?
523  entity_name(call_function(called)): "<nope>");
524 
525  if (called &&
526  ENTITY_ASSIGN_P(call_function(called)) &&
527  EXPRESSION(CAR(call_arguments(called)))==enc)
528  {
529  // is it a definition: var = ...
530  list args = call_arguments(called);
531  pips_assert("2 args to assign", gen_length(args)==2);
532  entity v2 =
534  if (v2)
535  {
536  if (!hash_defined_p(ctx->points_to, var))
537  hash_put(ctx->points_to, var, v2),
538  hash_put(ctx->defined, var, called),
539  what="! var = &YYY";
540  else
541  set_add_element(ctx->invalidated, ctx->invalidated, var),
542  what="already defined";
543  }
544  else
545  set_add_element(ctx->invalidated, ctx->invalidated, var),
546  what="no v2";
547  }
548  else if (called && ENTITY_DEREFERENCING_P(call_function(called)))
549  {
550  // *var ...
551  call upper = (call) gen_get_ancestor(call_domain, called);
552  expression first = (upper && call_arguments(upper))?
553  EXPRESSION(CAR(call_arguments(upper))): NULL;
554 
555  pips_debug(8, "upper=%p first=%p %s\n", upper, first, upper?
556  entity_name(call_function(upper)): "<nope>");
557 
558  if (upper && first &&
559  ENTITY_ASSIGN_P(call_function(upper)) &&
560  expression_call_p(first) &&
561  expression_call(first) == called &&
562  !hash_defined_p(ctx->dereferenced, var))
563  // *var = XXX
564  hash_put(ctx->dereferenced, var, first),
565  what="! *var = XXX";
566  else
567  set_add_element(ctx->invalidated, ctx->invalidated, var),
568  what="not *var = ...";
569  }
570  else
571  set_add_element(ctx->invalidated, ctx->invalidated, var),
572  what="not = or *";
573  }
574  else
575  set_add_element(ctx->invalidated, ctx->invalidated, var),
576  what="not enc";
577  }
578  else
579  what="not candidate";
580  pips_debug(5, "candidate %s: %s\n", entity_name(var), what);
581  //return true;
582 }
583 
585 {
586  debug_on("PIPS_HWAC_DEBUG_LEVEL");
587  pips_debug(1, "considering module %s\n", module);
588 
589  // else do the stuff
591  (statement) db_get_memory_resource(DBR_CODE, module, true);
594 
595  rssp_ctx ctx;
601 
602  // get candidates
604  {
605  if (pointer_candidate_p(var))
606  {
607  set_add_element(ctx.candidates, ctx.candidates, var);
609  {
611  entity v2 = address_of_scalar(e);
612  if (v2)
613  {
614  hash_put(ctx.points_to, var, v2);
615  hash_put(ctx.defined, var, expression_call(e));
616  }
617  }
618  }
619  }
620 
621 
622  // check condition
624  (mod_stat, &ctx,
626  // ignore sizeof
628  NULL);
629 
630  bool changed = false;
631  // apply transformation
632  SET_FOREACH(entity, var, ctx.candidates)
633  {
634  pips_debug(2, "considering entity %s inv=%d dr=%d def=%d pt=%d\n",
635  entity_name(var), set_belong_p(ctx.invalidated, var),
636  hash_defined_p(ctx.dereferenced, var),
637  hash_defined_p(ctx.defined, var),
638  hash_defined_p(ctx.points_to, var));
639 
640  if (!set_belong_p(ctx.invalidated, var) &&
641  hash_defined_p(ctx.dereferenced, var) &&
642  hash_defined_p(ctx.defined, var) &&
643  hash_defined_p(ctx.points_to, var))
644  {
645  changed = true;
646  // replace use
647  expression deref = (expression) hash_get(ctx.dereferenced, var);
649  (make_reference((entity) hash_get(ctx.points_to, var), NIL));
650  // drop definition
651  call definition = (call) hash_get(ctx.defined, var);
652  gen_free_list(call_arguments(definition)),
653  call_arguments(definition) = NIL;
655  // declaration cleanup?
656  }
657  }
658 
659  // result
660  if (changed)
662 
663  // cleanup
664  set_free(ctx.candidates);
665  set_free(ctx.invalidated);
671  debug_off();
672 
673  return true;
674 }
675 
676 /************************************************************ SHUFFLE FORWARD */
677 /*
678  * Move forward image pointer assignments and cleanup... that is change
679  *
680  * y = x;
681  * z = y;
682  * op(z);
683  *
684  * to:
685  *
686  * op(x);
687  *
688  * This kind of simple image shuffling is generated by function inlining,
689  * especially image returning functions from smil to freia conversion.
690  * The code is too simplistic, it should rely on effects...
691  *
692  * TODO: handle declaration & initialization
693  */
694 
695 typedef struct {
696  int changed; // number of substitutions
697  int removed; // number of removed assignments
698  list assigns; // list of found image assignments
699  hash_table equal; // entity -> entity
701 
702 #define starts_with(s1, s2) (strncmp(s1, s2, strlen(s2))==0) /* a la java */
703 
704 #define entity_update_p(e) \
705  (ENTITY_MULTIPLY_UPDATE_P(e) || ENTITY_DIVIDE_UPDATE_P(e) || \
706  ENTITY_MODULO_UPDATE_P(e) || ENTITY_PLUS_UPDATE_P(e) || \
707  ENTITY_MINUS_UPDATE_P(e) || ENTITY_LEFT_SHIFT_UPDATE_P(e) || \
708  ENTITY_RIGHT_SHIFT_UPDATE_P(e) || ENTITY_BITWISE_AND_UPDATE_P(e) || \
709  ENTITY_BITWISE_XOR_UPDATE_P(e) || ENTITY_BITWISE_OR_UPDATE_P(e))
710 
711 // only visit = and freia functions (what about others? gen_true???)
713 {
714  entity f = call_function(c);
715  return ENTITY_ASSIGN_P(f) || entity_update_p(f) ||
716  hwac_freia_api(entity_local_name(f)) != NULL ||
717  // hmmm... also freia_common_ functions
718  starts_with(entity_local_name(f), "freia_common_");
719 }
720 
721 // substitute with image assignment in reference
723 {
724  if (reference_indices(r) != NIL)
725  return;
726  entity v = reference_variable(r);
727  if (hash_defined_p(ctx->equal, v))
728  {
729  reference_variable(r) = hash_get(ctx->equal, v);
730  ctx->changed++;
731  }
732 }
733 
734 // substititute images in some cases
736 {
740  NULL);
741 }
742 
743 /*
744  * Forward substitute simple image pointer assignments in a sequence.
745  *
746  * TODO: deal with declaration initialization
747  */
748 static void seq_rwt(sequence sq, shuffle_context * ctx)
749 {
750  ctx->equal = hash_table_make(hash_pointer, 10);
751 
753  {
754  if (statement_call_p(s))
755  {
756  call c = statement_call(s);
757  list args = call_arguments(c);
759  {
760  // ... = ...
761  pips_assert("2 arguments", gen_length(args)==2);
762  expression e1 = EXPRESSION(CAR(args)), e2 = EXPRESSION(CAR(CDR(args)));
763  if (expression_reference_p(e1))
764  {
765  entity v1 = expression_variable(e1);
766  if (freia_image_variable_p(v1))
767  {
768  // is the second image an image?
769  entity v2 = NULL;
770  if (expression_reference_p(e2))
771  {
772  v2 = expression_variable(e2);
773  if (!freia_image_variable_p(v2))
774  v2 = NULL;
775  }
776 
777  // img = ...
778  // cleanup all equalities with img, but not on img=img
779  if (v1 != v2)
780  {
781  list delete = CONS(entity, v1, NIL);
782  HASH_FOREACH(entity, k, entity, v, ctx->equal)
783  // maybe could replace by other equal if any?
784  if (v == v1)
785  delete = CONS(entity, k, delete);
786  FOREACH(entity, e, delete)
787  (void) hash_del(ctx->equal, e);
788  gen_free_list(delete), delete = NIL;
789  }
790 
791  // image assignement
792  if (v2 != NULL)
793  {
794  // img1 = img2
795  ctx->assigns = CONS(statement, s, ctx->assigns);
796  if (v1 != v2) // distinct images
797  {
798  // point to prior image if any
799  if (hash_defined_p(ctx->equal, v2))
800  {
801  entity end = hash_get(ctx->equal, v2);
803  hash_put(ctx->equal, v1, end);
804  }
805  else
806  hash_put(ctx->equal, v1, v2);
807  }
808  // else skip silently "img = img;"
809  }
810  // else no image on rhs
811  }
812  else // not image assignment
813  {
815  }
816  }
817  }
818  else // a call, but not an assignment
819  {
821  }
822  }
823  else // not a call
824  {
825  // hmmm... safe option for now, cleanup current equalities
826  // ??? could keep those on which there is no effect?
827  hash_table_clear(ctx->equal);
828  }
829  }
830  hash_table_free(ctx->equal); ctx->equal = NULL;
831 }
832 
833 // count use references, but left part of assignments is skipped
834 static void ref_count_rwt(reference r, hash_table counts)
835 {
836  entity v = reference_variable(r);
837  if (freia_image_variable_p(v))
838  {
839  if (hash_defined_p(counts, v))
840  {
841  _int count = (_int) hash_get(counts, v) + 1;
842  hash_update(counts, v, (void *) count);
843  }
844  else
845  hash_put(counts, v, (void *) (_int) 1);
846  }
847 }
848 
849 // skip left part of assignments, or useless assignments
850 static bool call_count_flt(call c, _UNUSED_ hash_table counts)
851 {
853  {
854  list args = call_arguments(c);
855  pips_assert(gen_length(args) == 2, "2 args to assign");
856  expression e1 = EXPRESSION(CAR(args));
857  if (expression_reference_p(e1))
858  {
860  gen_recurse_stop(r1);
861  // deal with x = x
862  expression e2 = EXPRESSION(CAR(CDR(args)));
863  if (expression_reference_p(e2))
864  {
866  if (reference_variable(r1) == reference_variable(r2) &&
867  reference_indices(r1) == NIL &&
868  reference_indices(r2) == NIL)
869  return false;
870  }
871  }
872  }
873  return true;
874 }
875 
877 {
878  shuffle_context ctx = { 0, 0, NIL, NULL };
879  // forward substitude simple image assignments
881  // remove image assignments that are not used
882  // TODO ??? initializations...
883  // count image read references
884  hash_table reads = hash_table_make(hash_pointer, 100); // entity -> _int
885  gen_context_multi_recurse(s, reads,
888  NULL);
889  // cleanup assignments of unused images
890  FOREACH(statement, sa, ctx.assigns)
891  {
892  // be safe
893  pips_assert(statement_call_p(sa), "statement is a call");
894  call c = statement_call(sa);
895  pips_assert(ENTITY_ASSIGN_P(call_function(c)), "call is assign");
896  list args = call_arguments(c);
897  pips_assert(gen_length(args) == 2, "2 args to assign");
898  expression e1 = EXPRESSION(CAR(args));
899  pips_assert(expression_reference_p(e1), "expr is reference");
901  entity img = reference_variable(r);
902  pips_assert(reference_indices(r) == NIL, "no array reference");
903  pips_assert(freia_image_variable_p(img), "reference an image");
904 
905  // cleanup unused images
906  if (!hash_defined_p(reads, img))
907  {
908  // remove assignment of unused image pointer
911  // coldly cleanup corresponding effects... (free effects not needed?)
914  // ??? what about proper effects?
915  // stats
916  ctx.removed ++;
917  }
918  }
919  hash_table_free(reads), reads = NULL;
920 
921  // be verbose because I'm not sure of the pass
922  if (ctx.changed != 0 || ctx.removed != 0)
923  pips_user_warning("%d subsitution(s) and %d assignment(s) removed",
924  ctx.changed, ctx.removed);
925 
926  gen_free_list(ctx.assigns), ctx.assigns = NIL;
927 }
int get_int_property(const string)
statement copy_statement(statement p)
STATEMENT.
Definition: ri.c:2186
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
void free_instruction(instruction p)
Definition: ri.c:1118
syntax make_syntax_reference(reference _field_)
Definition: ri.c:2494
static int count
Definition: SDG.c:519
struct _newgen_struct_expression_ * expression
Definition: alias_private.h:21
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
effects delete_cumulated_rw_effects(statement)
void store_cumulated_rw_effects_list(statement, list)
const freia_api_t * hwac_freia_api(const char *function)
freia-utils.c
Definition: freia-utils.c:455
bool freia_image_variable_p(const entity var)
rather approximative?
Definition: freia-utils.c:768
call freia_statement_to_call(const statement s)
return the actual function call from a statement, dealing with assign and returns....
Definition: freia-utils.c:973
bool freia_statement_aipo_call_p(const statement s)
returns whether the statement is a FREIA call.
Definition: freia-utils.c:814
#define AIPO
Definition: freia.h:51
#define spoc_depth_prop
Definition: freia_spoc.h:185
#define starts_with(s1, s2)
#define entity_update_p(e)
bool freia_remove_scalar_ww_deps(const string module)
static bool fcs_count(statement s, fcs_ctx *ctx)
static void substitute_reference_variable(statement s, entity ovar, entity nvar)
static void maybe_unroll_while_rwt(whileloop wl, bool *changed)
static bool sr_flt(statement s, int *number)
static list remove_register(list lq)
remove "register" qualifier from qualifier list
static void sww_seq_rwt(const sequence sq, bool *changed)
static void rssp_ref(reference r, rssp_ctx *ctx)
static void ref_rwt(reference r, subs_ctx *ctx)
static entity address_of_scalar(expression e)
"&v"? return v, else return NULL
static void substitute_image_occurrences(void *s, shuffle_context *ctx)
static void sio_ref_rwt(reference r, shuffle_context *ctx)
static entity freia_reduction_variable(const statement s)
return the freia reduction entity, or NULL if it does not apply
static bool call_count_flt(call c, _UNUSED_ hash_table counts)
bool freia_unroll_while(const string module)
freia_transformations.c
static bool freia_unroll_while_for_spoc(statement s)
static void ref_count_rwt(reference r, hash_table counts)
static void seq_rwt(sequence sq, shuffle_context *ctx)
void freia_shuffle_move_forward(statement s)
static bool sio_call_flt(call c, _UNUSED_ shuffle_context *ctx)
static bool variable_is_used(statement s, entity var)
static bool pointer_candidate_p(entity var)
bool remove_simple_scalar_pointers(const string module)
static bool freia_convergence_sequence_p(sequence sq)
static void vis_rwt(const reference r, vis_ctx *ctx)
static void stmt_renumber(statement s)
#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
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
void replace_entities(void *s, hash_table ht)
Recursively substitute a set of entities in a statement.
Definition: replace.c:91
void gen_recurse_stop(void *obj)
Tells the recursion not to go in this object.
Definition: genClib.c:3251
void gen_context_multi_recurse(void *o, void *context,...)
Multi-recursion with context function visitor.
Definition: genClib.c:3373
gen_chunk * gen_get_ancestor(int, const void *)
return the first ancestor object found of the given type.
Definition: genClib.c:3560
void gen_null2(__attribute__((unused)) void *u1, __attribute__((unused)) void *u2)
idem with 2 args, to please overpeaky compiler checks
Definition: genClib.c:2758
bool gen_false(__attribute__((unused)) gen_chunk *unused)
Return false and ignore the argument.
Definition: genClib.c:2796
bool gen_true2(__attribute__((unused)) gen_chunk *u1, __attribute__((unused)) void *u2)
Definition: genClib.c:2785
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
instruction make_continue_instruction()
Creates a CONTINUE instruction, that is the FORTRAN nop, the ";" in C or the "pass" in Python for exa...
Definition: instruction.c:79
bool instruction_assign_p(instruction i)
Test if an instruction is an assignment.
Definition: instruction.c:164
void gen_remove_once(list *pl, const void *o)
Remove the first occurence of o in list pl:
Definition: list.c:691
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
list gen_copy_seq(list l)
Copy a list structure.
Definition: list.c:501
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 CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
list gen_last(list l)
Return the last element of a list.
Definition: list.c:578
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
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
sequence statement_sequence(statement)
Get the sequence of a statement sequence.
Definition: statement.c:1328
call statement_call(statement)
Get the call of a statement.
Definition: statement.c:1406
bool statement_call_p(statement)
Definition: statement.c:364
bool statement_sequence_p(statement)
Statement classes induced from instruction type.
Definition: statement.c:335
char end
Definition: gtk_status.c:82
hash_table hash_table_make(hash_key_type key_type, size_t size)
Definition: hash.c:294
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
void hash_update(hash_table htp, const void *key, const void *val)
update key->val in htp, that MUST be pre-existent.
Definition: hash.c:491
void hash_table_free(hash_table htp)
this function deletes a hash table that is no longer useful.
Definition: hash.c:327
bool hash_defined_p(const hash_table htp, const void *key)
true if key has e value in htp.
Definition: hash.c:484
void * hash_del(hash_table htp, const void *key)
this function removes from the hash table pointed to by htp the couple whose key is equal to key.
Definition: hash.c:439
void hash_table_clear(hash_table htp)
Clears all entries of a hash table HTP.
Definition: hash.c:305
static statement mod_stat
We want to keep track of the current statement inside the recurse.
Definition: impact_check.c:41
#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 debug_off()
Definition: misc-local.h:160
@ hash_pointer
Definition: newgen_hash.h:32
#define HASH_FOREACH(key_type, k, value_type, v, ht)
Definition: newgen_hash.h:71
#define same_string_p(s1, s2)
#define SET_FOREACH(type_name, the_item, the_set)
enumerate set elements in their internal order.
Definition: newgen_set.h:78
void set_free(set)
Definition: set.c:332
bool set_belong_p(const set, const void *)
Definition: set.c:194
@ set_pointer
Definition: newgen_set.h:44
set set_make(set_type)
Create an empty set of any type but hash_private.
Definition: set.c:102
set set_add_element(set, const set, const void *)
Definition: set.c:152
char * string
STRING.
Definition: newgen_types.h:39
intptr_t _int
_INT
Definition: newgen_types.h:53
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
static char * module
Definition: pips.c:74
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244
#define ENTITY_ASSIGN_P(e)
#define ENTITY_DEREFERENCING_P(e)
#define STATEMENT_NUMBER_UNDEFINED
default values
#define entity_declarations(e)
MISC: newgen shorthands.
#define ENTITY_ADDRESS_OF_P(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
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
bool entity_pointer_p(entity e)
Definition: entity.c:745
bool expression_address_of_p(expression e)
Definition: expression.c:420
bool expression_call_p(expression e)
Definition: expression.c:415
call expression_call(expression e)
Definition: expression.c:445
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
entity expression_variable(expression e)
Definition: expression.c:532
bool entity_scalar_p(entity)
The concrete type of e is a scalar type.
Definition: variable.c:1113
entity make_integer_constant_entity(_int)
entity make_integer_constant_entity(int c) make entity for integer constant c
Definition: variable.c:1345
#define qualifier_register_p(x)
Definition: ri.h:2185
#define syntax_reference_p(x)
Definition: ri.h:2728
#define expression_domain
newgen_execution_domain_defined
Definition: ri.h:154
#define instruction_sequence_p(x)
Definition: ri.h:1512
#define call_function(x)
Definition: ri.h:709
#define reference_variable(x)
Definition: ri.h:2326
#define type_variable(x)
Definition: ri.h:2949
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define reference_domain
newgen_range_domain_defined
Definition: ri.h:338
#define entity_name(x)
Definition: ri.h:2790
#define sizeofexpression_domain
newgen_sequence_domain_defined
Definition: ri.h:354
struct _newgen_struct_call_ * call
Definition: ri.h:63
#define sequence_statements(x)
Definition: ri.h:2360
#define reference_indices(x)
Definition: ri.h:2328
#define variable_qualifiers(x)
Definition: ri.h:3124
#define whileloop_body(x)
Definition: ri.h:3162
#define whileloop_domain
newgen_variable_domain_defined
Definition: ri.h:466
#define statement_instruction(x)
Definition: ri.h:2458
#define instruction_call(x)
Definition: ri.h:1529
#define call_arguments(x)
Definition: ri.h:711
#define entity_type(x)
Definition: ri.h:2792
#define statement_number(x)
Definition: ri.h:2452
#define value_expression_p(x)
Definition: ri.h:3080
#define expression_syntax(x)
Definition: ri.h:1247
#define sequence_domain
newgen_reference_domain_defined
Definition: ri.h:346
#define value_expression(x)
Definition: ri.h:3082
#define statement_undefined
Definition: ri.h:2419
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define entity_initial(x)
Definition: ri.h:2796
static size_t current
Definition: string.c:115
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: freia.c:53
hash_table points_to
hash_table dereferenced
hash_table defined
util defined somewhere ??????
look for a variable