PIPS
special_cases.c
Go to the documentation of this file.
1 /*
2 
3  $Id: special_cases.c 23065 2016-03-02 09:05:50Z 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 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 /* HPFC module, Fabien Coelho, May 1993.
28  */
29 
30 #include "defines-local.h"
31 
32 #include "conversion.h"
33 #include "effects-generic.h"
34 #include "effects-simple.h"
35 #include "effects-convex.h"
36 
37 /************************************************************** REDUCTIONS */
38 
39 #define MAX_REDUCTION 1
40 #define MIN_REDUCTION 2
41 #define SUM_REDUCTION 3
42 
43 typedef struct t_reduction
44 {
45  char *name;
46  int kind;
47  int ndim;
49 
51 {
52  {"REDMIN", MIN_REDUCTION, -1},
53  {"REDMIN1", MIN_REDUCTION, 1},
54  {"REDMIN2", MIN_REDUCTION, 2},
55  {"REDMIN3", MIN_REDUCTION, 3},
56  {"REDMAX", MAX_REDUCTION, -1},
57  {"REDMAX1", MAX_REDUCTION, 1},
58  {"REDMAX2", MAX_REDUCTION, 2},
59  {"REDMAX3", MAX_REDUCTION, 3},
60  {0, 0, 0}
61 };
62 
63 /* static t_reduction *find_reduction(c)
64  *
65  * look for the presence of the reduction in the reduction list.
66  */
67 static t_reduction *find_reduction(const char *s)
68 {
69  t_reduction *red;
70 
71  for (red=all_reductions; red->kind; red++)
72  if (same_string_p(s, red->name)) return red;
73 
74  return NULL;
75  }
76 
77 /* bool call_reduction_p(c)
78  *
79  * true if a given call is a call to reduction function.
80  * ??? a generic function name should be managed here?
81  */
83 {
84  return find_reduction(module_local_name(e)) != NULL;
85 }
86 
88 {
90 }
91 
92 /*
93  * void reduction_parameters(c, pred, pb, pdim)
94  *
95  * extract the informations needed to generate the distributed code.
96  */
97 static void reduction_parameters(c, pred, pb, pdim, pe, pl)
98 call c;
99 t_reduction **pred;
100 basic *pb;
101 int *pdim;
102 entity *pe;
103 list *pl;
104 {
105  expression
106  arg = EXPRESSION(CAR(call_arguments(c)));
107 
109 
111  *pl = CDR(call_arguments(c));
112  *pdim = NumberOfDimension(*pe);
114  *pb = entity_basic(*pe);
115 }
116 
117 static char *reduction_name(kind)
118 int kind;
119 {
120  static char *reduction_names[] = {"MAX", "MIN", "SUM"};
121  pips_assert("valid kind", kind>=0 && kind<3);
122  return(reduction_names[kind-1]);
123 }
124 
125 /* find or create an entity for the reduction function...
126  */
127 static entity
129  string prefix,
130  int ndim,
131  int kind,
132  basic base,
133  int nargs)
134 {
135  char buffer[100];
136 
137  (void) sprintf(buffer, "%sRED %d %s %s",
138  prefix, ndim, pvm_what_options(base), reduction_name(kind));
139 
141 }
142 
143 /* bool compile_reduction(initial, phost, pnode)
144  *
145  * true is the compiler succeeded in compiling the reduction that way.
146  * ??? many conditions are not yet checked...
147  */
148 bool compile_reduction(initial, phost, pnode)
149 statement initial, *phost, *pnode;
150 {
151  instruction i = statement_instruction(initial);
152  list args = NIL;
153  expression ref, cll;
154  call reduction;
155  t_reduction *red ;
156  basic b;
157  int dim = 0, arraynum = -1;
158  list largs = NIL;
159  entity array, hostfunction, nodefunction;
160 
161  pips_assert("assignment",
162  (instruction_call_p(i) &&
165 
166  args = call_arguments(instruction_call(i));
167  ref = EXPRESSION(CAR(args));
168  cll = EXPRESSION(CAR(CDR(args)));
169 
172 
174 
175  pips_debug(7, "call to %s\n", entity_name(call_function(reduction)));
176 
177  pips_assert("reduction call", call_reduction_p(reduction));
178 
179  reduction_parameters(reduction, &red, &b, &dim, &array, &largs);
180 
181  /*
182  * the array must be distributed accross the processors, not replicated,
183  * and the reference variable mustn't be distributed.
184  */
185 
186  if (!array_distributed_p(array) ||
189  return(false);
190 
191  arraynum = load_hpf_number(array);
192 
193  hostfunction = make_reduction_function("H", dim, red->kind, b, 0);
194  nodefunction = make_reduction_function("N", dim, red->kind, b, 4*dim+2);
195 
197  make_call_expression(hostfunction, NIL));
198  *pnode =
200  ( copy_expression(ref),
202  (nodefunction,
204  CONS(EXPRESSION, int_to_expression(arraynum),
206  largs)))));
207 
208  return(true);
209 }
210 
211 /******************************************** REDUCTION DIRECTIVE HANDLING */
212 /* hpfc_reductions =
213  * initial:entity x replacement:entity x operator:reduction ;
214  * reduction = { min , max , sum , prod , and , or } ;
215  */
216 
217 /* looking for the reduction operator is a basic recursion. no check.
218  */
222 
223 static bool ref_filter(reference r)
224 {
225  entity fun;
226 
227  if (searched_variable!=reference_variable(r)) return false;
228 
229  /* get the call just above -- well, what about intermediate casts ??? */
230  fun = call_function(current_call_head());
231 
232  if (ENTITY_PLUS_P(fun)||ENTITY_MINUS_P(fun))
234  else if (ENTITY_MULTIPLY_P(fun))
236  else if (ENTITY_MIN_P(fun)||ENTITY_MIN0_P(fun))
238  else if (ENTITY_MAX_P(fun)||ENTITY_MAX0_P(fun))
240  else if (ENTITY_AND_P(fun))
242  else if (ENTITY_OR_P(fun))
244 
245  return false;
246 }
247 
249 {
250  make_current_call_stack();
252  searched_variable = e;
254  call_domain, current_call_filter, current_call_rewrite,
256  NULL);
257  free_current_call_stack();
258 
259  pips_assert("some operator found", found_operator!=tag_undefined);
261 }
262 
263 /* finally, I can do without replacement:
264  * the host keeps and contributes the initial value!
265  */
267 {
268  pips_debug(5, "considering %s in %p\n", entity_name(e), s);
269 
271 }
272 
273 list /* of hpfc_reductions */
275 {
276  list /* of hpfc_reductions */ lr = NIL;
277 
278  MAP(ENTITY, e,
279  lr = CONS(HPFC_REDUCTIONS, reduction_of_in(e, s), lr),
281 
282  return lr;
283 }
284 
285 /* for reduction directive:
286  */
288 {
289  if (reduction_operator_sum_p(op))
290  return "SUM";
291  else if (reduction_operator_prod_p(op))
292  return "PROD";
293  else if (reduction_operator_min_p(op))
294  return "MIN";
295  else if (reduction_operator_max_p(op))
296  return "MAX";
297  else if (reduction_operator_and_p(op))
298  return "AND";
299  else if (reduction_operator_or_p(op))
300  return "OR";
301  else
302  pips_internal_error("unexpected reduction_operator tag (%d)",
304 
305  return "unknown";
306 }
307 
308 /* name is {H,N}{PRE,POST}_{SUM,PROD,MIN,...}_{REAL4,INTERGER4,...}
309  */
310 static entity
313  bool prolog,
314  bool host,
315  basic base)
316 {
317  char buffer[100];
318 
319  (void) sprintf(buffer, "%s", concatenate
320  (host? "H": "N", prolog? "PRE": "POST", " ",
321  new_reduction_name(op), " ", pvm_what_options(base), NULL));
322 
324 }
325 
326 static statement
328  hpfc_reductions red,
329  bool prolog,
330  bool host)
331 {
332  entity var = hpfc_reductions_initial(red);
333 
334  return call_to_statement
336  (hpfc_reductions_operator(red), prolog, host, entity_basic(var)),
341  NIL))));
342 }
343 
344 /*
345  */
346 list /* of statement */
348  list /* of hpfc_reductions */ lr,
349  bool prolog,
350  bool host)
351 {
352  list /* of statement */ ls = NIL;
353  MAP(HPFC_REDUCTIONS, r,
354  ls = CONS(STATEMENT, compile_one_reduction(r, prolog, host), ls),
355  lr);
356  return ls;
357 }
358 
359 /******************************************************** SUB ARRAY SHIFTS */
360 
361 /* bool subarray_shift_p(s, pe, plvect)
362  * statement s;
363  * entity *pe;
364  * list *plvect;
365  *
366  * checks whether a loop nest is a subarray shift,
367  * that is a parallel loop nest with one assign in the body
368  * which is a 1D shift of a locally constant value.
369  * returns false if this dimension is not distributed, because
370  * the overlap analysis will make a better job.
371  * should also check that the accessed subarray is a section.
372  * and that it is a block distribution.
373  * ??? should also check for a 1 alignment
374  *
375  * the entity returned *pe is the shifted array
376  * the list returned is the list of the vector shifts for each dimension
377  */
378 
379 #define expression_complex_p(e) \
380  (normalized_complex_p(expression_normalized(e)))
381 
383 {
385  gen_free_list(l);
386 }
387 
388 
389 /* some static variables used for the detection...
390  */
391 static bool subarray_shift_ok = true;
394 
396 {
397  for(; v!=NULL; v=v->succ)
398  if (var_of(v)!=TCST && written_effect_p((entity) var_of(v),
400  return false;
401 
402  return true;
403 }
404 
406 {
407  list lhs_ind, rhs_ind, args = call_arguments(c);
408  expression
409  lhs = EXPRESSION(CAR(args)),
410  rhs = EXPRESSION(CAR(CDR(args)));
411  reference lhs_ref, rhs_ref;
412  bool shift_was_seen = false;
413  int dim;
414 
415  /* LHS *must* be a reference
416  */
417  pips_assert("reference", expression_reference_p(lhs));
418 
419  /* is RHS a reference?
420  */
421  if (!expression_reference_p(rhs)) return false;
422 
423  lhs_ref = syntax_reference(expression_syntax(lhs)),
424  rhs_ref = syntax_reference(expression_syntax(rhs));
425  array = reference_variable(lhs_ref);
426 
427  /* same array, and a block-distributed one ?
428  */
429  if (array!=reference_variable(rhs_ref) ||
432  return false;
433 
434  lhs_ind = reference_indices(lhs_ref),
435  rhs_ind = reference_indices(rhs_ref);
436 
437  pips_assert("same arity", gen_length(lhs_ind)==gen_length(rhs_ind));
438 
439  /* compute the difference of every indices, if possible.
440  */
441  for(;
442  !ENDP(lhs_ind);
443  lhs_ind=CDR(lhs_ind), rhs_ind=CDR(rhs_ind))
444  {
445  expression
446  il = EXPRESSION(CAR(lhs_ind)),
447  ir = EXPRESSION(CAR(rhs_ind));
448 
450  {
452  return false;
453  }
454 
455  /* else compute the difference */
456  lvect =
457  CONS(PVECTOR, (VECTOR)
460  lvect);
461  }
462 
464 
465  /* now checks for a constant shift on a distributed dimension
466  * and that's all.
467  * ??? I could deal with other constant shifts on non distributed dims
468  */
469  dim = 0;
470  MAPL(cv,
471  {
472  Pvecteur v = (Pvecteur) PVECTOR(CAR(cv));
473  int p;
474 
475  dim++;
476 
477  if (vecteur_nul_p(v)) continue;
478 
479  /* else the vector is not null
480  */
481  if (shift_was_seen ||
482  !ith_dim_distributed_p(array, dim, &p) ||
484  {
485  pips_debug(7, "false on array %s, dimension %d\n",
486  entity_local_name(array), dim);
488  lvect = NIL;
489  return false;
490  }
491 
492  shift_was_seen = true;
493  },
494  lvect);
495 
496  return true;
497 }
498 
499 static bool loop_filter(loop l)
500 {
502  return subarray_shift_ok = subarray_shift_ok && (stride==1 || stride==-1);
503 }
504 
505 static bool call_filter(call c)
506 {
507  entity e = call_function(c);
508 
509  pips_debug(9, "function: %s\n", entity_name(e));
510 
511  if (ENTITY_CONTINUE_P(e)) return false;
512  if (ENTITY_ASSIGN_P(e))
513  {
514  if (ref_to_dist_array_p(c))
517  /* else: private variable assigned in a parallel loop, ok?! */
518  }
519  else
520  subarray_shift_ok = false;
521 
522  return false;
523 }
524 
525 static bool cannot_be_a_shift(_UNUSED_ void * x)
526 {
527  return subarray_shift_ok = false;
528 }
529 
530 bool subarray_shift_p(s, pe, plvect)
531 statement s;
532 entity *pe;
533 list *plvect;
534 {
536  subarray_shift_ok = true;
537  lvect = NIL;
539 
540  DEBUG_STAT(8, "considering statement", s);
541 
547  NULL);
548 
551 
552  if (subarray_shift_ok)
553  *pe = array,
554  *plvect = lvect;
555  else
558 
559  pips_debug(8, "returning %s\n", subarray_shift_ok? "TRUE": "FALSE");
560  return subarray_shift_ok;
561 }
562 
563 /* generates the needed subroutine
564  */
566 {
567  char buffer[100];
568  type t;
569  variable v;
570  int ndim;
571 
572  pips_assert("defined", !entity_undefined_p(var)); t = entity_type(var);
573  pips_assert("variable", type_variable_p(t)); v = type_variable(t);
574 
575  ndim = gen_length(variable_dimensions(v));
576 
577  (void) sprintf(buffer, "%s SHIFT %d",
579  ndim);
580 
581  return MakeRunTimeSupportSubroutine(buffer, ndim*4+4);
582 }
583 
585 {
586  MAP(EFFECT, e,
587  {
588  if (action_read_p(effect_action(e)) &&
590  return effect_system(e);
591  },
592  le);
593 
594  return SC_UNDEFINED;
595 }
596 
598 {
599  list l = NIL;
600  Psysteme
602  var));
604  Variable idx;
607 
609  c = sc_inegalites(s);
610  sc_inegalites(s) = (Pcontrainte)NULL,
611  sc_rm(s);
612 
613  for(; dim>0; dim--)
614  {
615  idx = (Variable) get_ith_region_dummy(dim);
616 
617  constraints_for_bounds(idx, &c, &lower, &upper);
618 
619  l = CONS(EXPRESSION, constraints_to_loop_bound(lower, idx, true, div),
620  CONS(EXPRESSION, constraints_to_loop_bound(upper, idx, false, div),
621  l));
622 
623  (void) contraintes_free(lower), lower=NULL;
624  (void) contraintes_free(upper), upper=NULL;
625  }
626 
627  (void) contraintes_free(c);
628 
629  return l;
630 }
631 
632 /* statement generate_subarray_shift(s, var, lshift)
633  * statement s;
634  * entity var;
635  * list lshift;
636  *
637  * generates a call to the runtime library shift subroutine
638  * for the given array, the given shift and the corresponding
639  * region in statement s.
640  * this function assumes that subarray_shift_p was true on s,
641  * and does not checks the conditions again.
642  */
644 {
645  entity subroutine = make_shift_subroutine(var);
646  int array_number = load_hpf_number(array), shifted_dim = 0;
648  list ldecl = array_lower_upper_bounds_list(array), largs;
649  Pvecteur v;
650 
651  /* gets the shifted dimension and the shift
652  */
653  MAPL(cv,
654  {
655  v = (Pvecteur) PVECTOR(CAR(cv));
656  shifted_dim++;
657 
658  if (!vecteur_nul_p(v))
659  {
660  shift = make_vecteur_expression(v);
661  break;
662  }
663  },
664  lshift);
665 
666  pips_assert("shift defined", shift!=expression_undefined);
667  free_vector_list(lshift);
668 
669  /* all the arguments
670  */
671  largs =
673  CONS(EXPRESSION, int_to_expression(array_number),
674  CONS(EXPRESSION, int_to_expression(shifted_dim),
675  CONS(EXPRESSION, shift,
676  gen_nconc(ldecl, make_rectangular_area(s, var))))));
677 
678  return hpfc_make_call_statement(subroutine, largs);
679 }
680 
681 /************************************************************* FULL COPIES */
682 
683 /* tests whether a loop nest is a full copy loop nest,
684  * i.e. it copies an array into another, both being aligned.
685  * ??? it should share some code with the subarray shift detection...
686  * ??? another quick hack for testing purposes (remappings).
687  */
688 
689 /* statement simple_statement(statement s)
690  *
691  * what: tells whether s is (after simplification) a simple statement,
692  * i.e. a call, and returns it (may be hidden by blocks and continues).
693  * how: recursion thru the IR.
694  * input: statement s
695  * output: returned statement, or NULL if not simple...
696  * side effects:
697  * - uses some static data
698  * bugs or features:
699  */
700 
702 static bool ok;
704 
706 {
707  error_reset_current_stmt_stack();
708  error_reset_current_call_stack();
709 }
710 
711 static bool not_simple(_UNUSED_ void * x)
712 {
713  ok = false;
714  gen_recurse_stop(NULL);
715  return false;
716 }
717 
718 static bool check_simple(call c)
719 {
722  {
723  if (simple_found)
724  {
725  ok = false;
726  gen_recurse_stop(NULL);
727  }
728  else
730  }
731 
732  return false;
733 }
734 
736 {
737  ok = true;
738  simple_found = (statement) NULL;
739  make_current_stmt_stack();
740 
742  (s,
743  statement_domain, current_stmt_filter, current_stmt_rewrite,
748  NULL);
749 
750  free_current_stmt_stack();
751 
752  return (ok && simple_found) ? simple_found : NULL;
753 }
754 
755 /* bool full_define_p (reference r, list ll)
756  *
757  * what: true if the loop nest ll fully scans r
758  * how: not very beautiful.
759  * input: r and ll
760  * output: the bool result
761  * side effects: none
762  * bugs or features:
763  */
764 
765 static loop find_loop(entity index, list /* of loops */ ll)
766 {
767  MAP(LOOP, l, if (loop_index(l)==index) return l, ll);
768  return (loop) NULL; /* if not found */
769 }
770 
771 bool full_define_p(reference r, list /* of loops */ ll)
772 {
774  list /* of expression */ li = reference_indices(r),
775  /* of dimension */ ld,
776  /* of entity */ lseen = NIL;
777  int ndim;
778 
779  pips_assert("variable", entity_variable_p(array));
780 
782  pips_assert("same arity", gen_length(ll)==gen_length(ld));
783 
784  /* checks that the indices are *simply* the loop indexes,
785  * and that the whole dimension is scanned. Also avoids (i,i)...
786  */
787  for(ndim=1; li; POP(li), POP(ld), ndim++)
788  {
790  entity index;
791  dimension dim;
792  range rg;
793  loop l;
794  expression inc;
795 
796  if (!syntax_reference_p(s))
797  {
798  gen_free_list(lseen);
799  return false;
800  }
801 
803 
804  if (gen_in_list_p(index, lseen))
805  {
806  gen_free_list(lseen);
807  return false;
808  }
809 
810  lseen = CONS(ENTITY, index, lseen);
811 
812  l = find_loop(index, ll);
813 
814  if (!l)
815  {
816  gen_free_list(lseen);
817  return false;
818  }
819 
820  /* checks that the loop range scans the whole dimension */
821 
822  rg = loop_range(l);
823  inc = range_increment(rg);
824  dim = DIMENSION(CAR(ld));
825 
826  /* increment must be 1.
827  * lowers and uppers must be equal.
828  */
829  if (!integer_constant_expression_p(inc) ||
833  {
834  pips_debug(9, "incomplete scan of %s[dim=%d]\n",
835  entity_name(array), ndim);
836  gen_free_list(lseen);
837  return false;
838  }
839  }
840 
841  gen_free_list(lseen);
842  return true;
843 }
844 
845 /* bool full_copy_p(statement s, reference * pleft, reference * pright)
846  *
847  * what: tells whether a loop nest is a 'full copy' one, that is it fully
848  * define an array from another, with perfect alignment.
849  * how: pattern matching of what we are looking for...
850  * input: the statement
851  * output: the bool result, plus both references.
852  * side effects:
853  * - uses some static data
854  * bugs or features:
855  * - pattern matching done this way is just a hack...
856  */
857 #define XDEBUG(msg) \
858  pips_debug(6, "statement %p: " msg "\n", (void*) s)
859 
860 static int
862  list /* of statement */ ls)
863 {
864  int n = 0;
865  MAP(STATEMENT, s, if (!empty_code_p(s)) n++, ls);
866  return n;
867 }
868 
869 bool full_copy_p(statement s, reference * pleft, reference * pright)
870 {
871  list /* of lists */ lb = NIL, l,
872  /* of loops */ ll = NIL,
873  /* of expressions */ la = NIL;
874  statement body = parallel_loop_nest_to_body(s, &lb, &ll), simple;
875  expression e;
876  reference left, right;
877  int len;
878 
879  DEBUG_STAT(6, "considering statement", s);
880 
881  /* the loop nest must be perfect... !!!
882  * should check for continues?
883  */
884  for (l=lb; l; POP(l))
886  {
887  XDEBUG("non perfectly nested");
888  gen_free_list(lb), gen_free_list(ll); return false;
889  }
890 
891  gen_free_list(lb), lb = NIL;
892 
893  /* the body must be a simple assignment
894  */
895  simple = simple_statement(body);
896 
898  {
899  XDEBUG("body not simple"); gen_free_list(ll); return false;
900  }
901 
903  pips_assert("2 arguments to assign", gen_length(la)==2);
904 
905  left = expression_reference(EXPRESSION(CAR(la)));
906  e = EXPRESSION(CAR(CDR(la)));
907 
908  if (!expression_reference_p(e))
909  {
910  XDEBUG("rhs not a reference"); gen_free_list(ll); return false;
911  }
912 
913  right = expression_reference(e);
914 
915  /* compatible arities
916  */
917  len = (int) gen_length(ll); /* number of enclosing loops */
918 
919  if ((int) gen_length(reference_indices(left))!=len ||
920  (int) gen_length(reference_indices(right))!=len)
921  {
922  XDEBUG("incompatible arities"); gen_free_list(ll); return false;
923  }
924 
925  /* the lhs should be fully defined by the loop nest...
926  * but it does not matter for the rhs!
927  */
928  if (!full_define_p(left, ll))
929  {
930  XDEBUG("lhs not fully defined"); gen_free_list(ll); return false;
931  }
932 
933  gen_free_list(ll);
934 
935  /* both lhs and rhs references must be aligned
936  */
937  if (!references_aligned_p(left, right))
938  {
939  XDEBUG("references not aligned"); return false;
940  }
941 
942  /* ??? should check the new declarations...
943  */
944 
945  XDEBUG("ok");
946  *pleft = left;
947  *pright = right;
948  return true;
949 }
950 
951 /* statement generate_full_copy(reference left, reference right)
952  *
953  * what: copies directly right into left, that must conform...
954  * how: direct loop nest on local data
955  * input: both entities
956  * output: the returned statement
957  * side effects:
958  * bugs or features:
959  * - assumes that the references are ok, that is they come from
960  * a full_copy_p execution.
961  * - code generated based on the original entities. thus the
962  * code cleaning pass is trusted.
963  */
965 {
966  statement body;
967  int ndim, i;
968  list /* of entity */ lindexes, l,
969  /* of dimension */ ld;
971  new_array = load_new_node(array);
972 
974 
977 
978  /* indexes are reused. bounds are taken from the node entity declaration.
979  */
980  lindexes = expressions_to_entities(reference_indices(left));
982 
983  for(i=1, l=lindexes; i<=ndim; i++, POP(lindexes), POP(ld))
984  {
985  dimension d = DIMENSION(CAR(ld));
986 
988  (ENTITY(CAR(lindexes)),
991  int_to_expression(1)),
992  body,
995  NIL));
996  }
997 
998  gen_free_list(l);
999  return body;
1000 }
1001 
1002 /* That is all
1003  */
hpfc_reductions make_hpfc_reductions(entity a1, entity a2, reduction_operator a3)
Definition: hpf_private.c:448
reduction_operator make_reduction_operator(enum reduction_operator_utype tag, void *val)
execution make_execution(enum execution_utype tag, void *val)
Definition: ri.c:838
call make_call(entity a1, list a2)
Definition: ri.c:269
loop make_loop(entity a1, range a2, statement a3, entity a4, execution a5, list a6)
Definition: ri.c:1301
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
reference copy_reference(reference p)
REFERENCE.
Definition: ri.c:2047
range make_range(expression a1, expression a2, expression a3)
Definition: ri.c:2041
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
static call current_call
Definition: alias_check.c:123
void const char const char const int
bdt base
Current expression.
Definition: bdt_read_paf.c:100
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
statement parallel_loop_nest_to_body(statement loop_nest, list *pblocks, list *ploops)
bool vecteur_nul_p(Pvecteur v)
Definition: constraint.c:56
#define CONTRAINTE_UNDEFINED
struct Scontrainte * Pcontrainte
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)
static statement current_stmt
bool rectangular_must_region_p(entity, statement)
list load_statement_local_regions(statement)
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
#define effect_system(e)
#define effect_action(x)
Definition: effects.h:642
#define action_read_p(x)
Definition: effects.h:311
#define EFFECT(x)
EFFECT.
Definition: effects.h:608
#define CONSP(x)
Definition: genC.h:88
void gen_recurse_stop(void *obj)
Tells the recursion not to go in this object.
Definition: genClib.c:3251
void gen_multi_recurse(void *o,...)
Multi recursion visitor function.
Definition: genClib.c:3428
bool gen_false(__attribute__((unused)) gen_chunk *unused)
Return false and ignore the argument.
Definition: genClib.c:2796
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
bool instruction_assign_p(instruction i)
Test if an instruction is an assignment.
Definition: instruction.c:164
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
void gen_map(gen_iter_func_t fp, const list l)
Definition: list.c:172
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
bool gen_in_list_p(const void *vo, const list lx)
tell whether vo belongs to lx
Definition: list.c:734
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
#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
#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
statement make_assign_statement(expression, expression)
Definition: statement.c:583
bool empty_code_p(statement)
statement.c
Definition: statement.c:86
#define hpfc_reductions_initial(x)
Definition: hpf_private.h:576
#define entities_list(x)
Definition: hpf_private.h:414
#define hpfc_reductions_operator(x)
Definition: hpf_private.h:580
#define HPFC_REDUCTIONS(x)
HPFC_REDUCTIONS.
Definition: hpf_private.h:545
int HpfcExpressionToInt(expression e)
HpfcExpressionToInt(e)
Definition: hpfc-util.c:569
bool ith_dim_distributed_p(entity array, int i, int *pprocdim)
whether a dimension is distributed or not.
Definition: hpfc-util.c:160
bool ref_to_dist_array_p(void *obj)
this file describe a few functions usefull to the compiler to manage the hpfc data structures.
Definition: hpfc-util.c:48
bool references_aligned_p(reference r1, reference r2)
Definition: hpfc-util.c:726
bool written_effect_p(entity var, list le)
written_effects_to_dist_arrays_p
Definition: hpfc-util.c:58
#define IDIVIDE
#define DEBUG_STAT(D, W, S)
#define VECTOR
Definition: defines-local.h:73
#define PVECTOR(v)
Definition: defines-local.h:72
entity hpfc_name_to_entity(const char *)
Definition: run-time.c:817
entity load_new_node(entity)
entity MakeRunTimeSupportFunction(string, int, tag)
list array_lower_upper_bounds_list(entity)
of expressions
Definition: run-time.c:539
bool block_distributed_p(entity)
o-analysis.c
Definition: o-analysis.c:44
entity get_ith_region_dummy(int)
statement hpfc_make_call_statement(entity, list)
statement hpfc_make_call_statement(e, l) generate a call statement to function e, with expression lis...
Definition: run-time.c:318
entities load_hpf_reductions(statement)
entity MakeRunTimeSupportSubroutine(string, int)
run-time.c
string pvm_what_options(basic)
string pvm_what_options(b)
Definition: run-time.c:86
intptr_t load_hpf_number(entity)
bool array_distributed_p(entity)
#define current_stmt_head()
We want to keep track of the current statement inside the recurse.
Definition: icfg_scan.c:76
#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_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
#define DEFINE_LOCAL_STACK(name, type)
#define same_string_p(s1, s2)
int tag
TAG.
Definition: newgen_types.h:92
void(* gen_iter_func_t)(void *)
Definition: newgen_types.h:116
#define tag_undefined
Definition: newgen_types.h:93
#define UU
Definition: newgen_types.h:98
static hash_table pl
properties are stored in this hash table (string -> property) for fast accesses.
Definition: properties.c:783
#define reduction_operator_sum_p(x)
@ is_reduction_operator_min
@ is_reduction_operator_max
@ is_reduction_operator_prod
@ is_reduction_operator_or
@ is_reduction_operator_and
@ is_reduction_operator_sum
#define reduction_operator_min_p(x)
#define reduction_operator_tag(x)
struct _newgen_struct_reduction_ * reduction
#define reduction_operator_prod_p(x)
#define reduction_operator_or_p(x)
#define reduction_operator_and_p(x)
#define reduction_operator_max_p(x)
static const char * prefix
#define ENTITY_OR_P(e)
#define loop_to_statement(l)
#define ENTITY_AND_P(e)
#define ENTITY_MAX0_P(e)
#define ENTITY_ASSIGN_P(e)
#define ENTITY_MINUS_P(e)
#define ENTITY_PLUS_P(e)
#define ENTITY_MULTIPLY_P(e)
#define ENTITY_CONTINUE_P(e)
#define call_to_statement(c)
#define ENTITY_MAX_P(e)
#define CONTINUE_FUNCTION_NAME
#define entity_variable_p(e)
An entity_variable_p(e) may hide a typedef and hence a functional type.
#define ENTITY_MIN0_P(e)
#define ENTITY_MIN_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 entity_empty_label(void)
Definition: entity.c:1105
basic entity_basic(entity e)
return the basic associated to entity e if it's a function/variable/constant basic_undefined otherwis...
Definition: entity.c:1380
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
expression make_vecteur_expression(Pvecteur pv)
make expression for vector (Pvecteur)
Definition: expression.c:1650
expression reference_to_expression(reference r)
Definition: expression.c:196
list expressions_to_entities(list expressions)
map expression_to_entity on expressions
Definition: expression.c:3161
expression make_call_expression(entity e, list l)
Build an expression that call an function entity with an argument list.
Definition: expression.c:321
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
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
bool integer_constant_expression_p(expression e)
positive integer constant expression: call to a positive constant or to a sum of positive integer con...
Definition: expression.c:903
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
bool same_expression_p(expression e1, expression e2)
this is slightly different from expression_equal_p, as it will return true for a+b vs b+a
Definition: expression.c:1426
int integer_constant_expression_value(expression e)
Definition: expression.c:1545
int element_number(basic, list)
END_EOLE.
Definition: size.c:391
int NumberOfDimension(entity)
Definition: size.c:588
#define test_domain
newgen_entity_domain_defined
Definition: ri.h:418
#define syntax_reference_p(x)
Definition: ri.h:2728
#define expression_domain
newgen_execution_domain_defined
Definition: ri.h:154
#define LOOP(x)
LOOP.
Definition: ri.h:1606
#define syntax_reference(x)
Definition: ri.h:2730
#define call_function(x)
Definition: ri.h:709
#define reference_variable(x)
Definition: ri.h:2326
#define loop_domain
newgen_language_domain_defined
Definition: ri.h:218
#define range_upper(x)
Definition: ri.h:2290
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define syntax_call_p(x)
Definition: ri.h:2734
#define dimension_lower(x)
Definition: ri.h:980
#define basic_tag(x)
Definition: ri.h:613
#define type_variable(x)
Definition: ri.h:2949
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define range_increment(x)
Definition: ri.h:2292
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define entity_undefined_p(x)
Definition: ri.h:2762
#define reference_domain
newgen_range_domain_defined
Definition: ri.h:338
#define entity_undefined
Definition: ri.h:2761
#define expression_undefined
Definition: ri.h:1223
#define entity_name(x)
Definition: ri.h:2790
#define expression_normalized(x)
Definition: ri.h:1249
#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 instruction_call_p(x)
Definition: ri.h:1527
#define range_lower(x)
Definition: ri.h:2288
#define variable_dimensions(x)
Definition: ri.h:3122
#define statement_instruction(x)
Definition: ri.h:2458
#define instruction_call(x)
Definition: ri.h:1529
#define loop_range(x)
Definition: ri.h:1642
@ is_execution_sequential
Definition: ri.h:1189
#define call_arguments(x)
Definition: ri.h:711
#define entity_type(x)
Definition: ri.h:2792
#define normalized_linear(x)
Definition: ri.h:1781
#define expression_syntax(x)
Definition: ri.h:1247
#define type_variable_p(x)
Definition: ri.h:2947
#define loop_index(x)
Definition: ri.h:1640
#define variable_basic(x)
Definition: ri.h:3120
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
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
void sc_transform_eg_in_ineg(Psysteme sc)
Package sc.
static bool check_simple(call c)
statement generate_full_copy(reference left, reference right)
statement generate_full_copy(reference left, reference right)
static statement compile_one_reduction(hpfc_reductions red, bool prolog, bool host)
list handle_hpf_reduction(statement s)
of hpfc_reductions
static bool ok
struct t_reduction t_reduction
void free_vector_list(list l)
static bool loop_filter(loop l)
bool call_reduction_p(call c)
Definition: special_cases.c:87
#define MIN_REDUCTION
Definition: special_cases.c:40
static bool locally_constant_vector_p(Pvecteur v)
static bool subarray_shift_ok
some static variables used for the detection...
static tag found_operator
static void reduction_parameters(call c, t_reduction **pred, basic *pb, int *pdim, entity *pe, list *pl)
Definition: special_cases.c:97
#define XDEBUG(msg)
bool full_copy_p(statement s, reference * pleft, reference * pright)
static entity make_shift_subroutine(entity var)
generates the needed subroutine
bool subarray_shift_p(statement s, entity *pe, list *plvect)
static statement simple_found
tests whether a loop nest is a full copy loop nest, i.e.
static t_reduction * find_reduction(const char *s)
static t_reduction *find_reduction(c)
Definition: special_cases.c:67
bool full_copy_p(statement s, reference *pleft, reference *pright)
static t_reduction all_reductions[]
Definition: special_cases.c:50
static char * reduction_name(int kind)
list make_rectangular_area(statement st, entity var)
static entity make_reduction_function(string prefix, int ndim, int kind, basic base, int nargs)
find or create an entity for the reduction function...
static list lvect
#define expression_complex_p(e)
bool subarray_shift_p(s, pe, plvect) statement s; entity *pe; list *plvect;
static loop find_loop(entity index, list ll)
bool full_define_p (reference r, list ll)
static string new_reduction_name(reduction_operator op)
for reduction directive:
statement simple_statement(statement s)
static bool not_simple(_UNUSED_ void *x)
void hpfc_special_cases_error_handler()
static bool subarray_shift_assignment_p(call c)
statement generate_subarray_shift(statement s, entity var, list lshift)
statement generate_subarray_shift(s, var, lshift) statement s; entity var; list lshift;
static hpfc_reductions reduction_of_in(entity e, statement s)
finally, I can do without replacement: the host keeps and contributes the initial value!
static list current_regions
static bool cannot_be_a_shift(_UNUSED_ void *x)
static entity searched_variable
hpfc_reductions = initial:entity x replacement:entity x operator:reduction ; reduction = { min ,...
static bool call_filter(call c)
#define MAX_REDUCTION
HPFC module, Fabien Coelho, May 1993.
Definition: special_cases.c:39
list compile_hpf_reduction(list lr, bool prolog, bool host)
of statement
static entity array
bool compile_reduction(statement initial, statement *phost, statement *pnode)
bool compile_reduction(initial, phost, pnode)
Psysteme get_read_effect_area(list le, entity var)
bool full_define_p(reference r, list ll)
bool hpfc_entity_reduction_p(entity e)
bool call_reduction_p(c)
Definition: special_cases.c:82
static reduction_operator get_operator(entity e, statement s)
static bool ref_filter(reference r)
static entity make_new_reduction_function(reduction_operator op, bool prolog, bool host, basic base)
name is {H,N}{PRE,POST}_{SUM,PROD,MIN,...}_{REAL4,INTERGER4,...}
static int number_of_non_empty_statements(list ls)
static char * x
Definition: split_file.c:159
static string buffer
Definition: string.c:113
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
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
#define TCST
VARIABLE REPRESENTANT LE TERME CONSTANT.
struct Svecteur * Pvecteur
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 var_of(varval)
void vect_rm(Pvecteur v)
void vect_rm(Pvecteur v): desallocation des couples de v;
Definition: alloc.c:78
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