PIPS
directives.c
Go to the documentation of this file.
1 /*
2 
3  $Id: directives.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 by Fabien COELHO
28  *
29  * These functions deal with HPF directives.
30  * (just a big hack, but few lines of code and neither lex nor yacc:-)
31  * I'm definitely happy with this. FC.
32  */
33 
34 #include "defines-local.h"
35 
36 #include "resources.h"
37 #include "control.h"
38 
39 /* several phases are used to analyze the directives.
40  * 1: static directives
41  * 2: special management of prescriptive mappings
42  * 3: dynamic mappings
43  */
44 static int analysis_phase = 0;
45 
46 /***************************************************************** UTILITIES */
47 
48 /* list of statements to be cleaned. the operation is delayed because
49  * the directives are needed in place to stop the dynamic updates.
50  */
51 static list /* of statements */ to_be_cleaned = NIL;
52 
53 /* the directive is freed and replaced by a continue call or
54  * a copy loop nest, depending on the renamings.
55  */
56 static void clean_statement(statement s)
57 {
59 
60  pips_assert("call", instruction_call_p(i));
61 
64 
65  if (bound_renamings_p(s))
66  {
67  list /* of renamings */ lr = load_renamings(s),
68  /* of statements */ block = NIL;
69 
70  MAP(RENAMING, r,
71  {
72  entity o = renaming_old(r);
73  entity n = renaming_new(r);
74 
76  },
77  lr);
78 
81  /* Do not forget to move forbidden information associated with
82  block: */
84  }
85  else
86  instruction_call(i) =
88 }
89 
91 {
93 }
94 
95 /* local primary dynamics
96  */
97 GENERIC_STATIC_STATUS(extern, the_dynamics, list, NIL, gen_free_list)
98 
100 {
101  the_dynamics_object = gen_once(c, the_dynamics_object);
102 }
103 
104 /* the local stack is used to retrieve the current statement while
105  * scanning the AST with gen_recurse.
106  */
108 
110 {
111  error_reset_current_stmt_stack();
112 }
113 
114 /* management of PROCESSORS and TEMPLATE directives.
115  *
116  * just changes the basic type to overloaded and
117  * stores the entity as a processor or a template.
118  */
120 {
121  basic b = entity_basic(e);
122  pips_assert("basic defined", b!=basic_undefined);
124 }
125 
126 static void new_processor(expression e)
127 {
130  set_processor(p);
131 
132  pips_debug(3, "entity is %s\n", entity_name(p));
133 }
134 
135 static void new_template(expression e)
136 {
139  set_template(t);
140 
141  pips_debug(3, "entity is %s\n", entity_name(t));
142 }
143 
144 static void new_dynamic(expression e)
145 {
148  add_a_dynamic(a);
149 
150  pips_debug(3, "entity is %s\n", entity_name(a));
151 }
152 
154 {
156 }
157 
159 {
161 }
162 
164 {
166 }
167 
168 /* array is to be seen as a template. aligned to itself...
169  */
171 {
172  int ndim = NumberOfDimension(array);
173  list /* of alignment */ l = NIL;
174 
177 
178  for(; ndim>0; ndim--)
179  l = CONS(ALIGNMENT, make_alignment(ndim, ndim,
181  int_to_expression(0)), l);
182 
184 }
185 
186 /* one simple ALIGN directive is handled.
187  * retrieve the alignment from references array and template
188  */
189 /* true if the template dimension subscript is an alignment.
190  * false if the dimension is replicated.
191  */
192 static bool
193 alignment_p(list /* of expressions */ align_src,
195  int *padim, Value *prate, Value *pshift)
196 {
198  Pvecteur v, v_src;
199  int size, array_dim;
200 
201  if (normalized_complex_p(n)) return false;
202 
203  /* else the subscript is affine
204  */
205  v = normalized_linear(n);
206  size = vect_size(v);
207  *pshift = vect_coeff(TCST, v);
208 
209  /* the alignment should be a simple affine expression
210  */
211  pips_user_assert("affine align subscript", *pshift==0 ? size<=1 : size<=2);
212 
213  /* constant alignment case
214  */
215  if (size==0 || (*pshift!=0 && size==1))
216  {
217  *padim = 0, *prate = 0;
218  return true;
219  }
220 
221  /* affine alignment case
222  */
223  for(array_dim = 1; !ENDP(align_src); POP(align_src), array_dim++)
224  {
225  n = expression_normalized(EXPRESSION(CAR(align_src)));
226  if (normalized_linear_p(n))
227  {
228  v_src = normalized_linear(n);
229 
230  pips_user_assert("simple index",
231  vect_size(v_src)==1 && var_of(v_src)!=TCST);
232 
233  *prate = vect_coeff(var_of(v_src), v);
234 
235  if (*prate!=0)
236  {
237  *padim = array_dim;
238  return true; /* alignment ok */
239  }
240  }
241  }
242 
243  /* matching array dimension not found, replicated!
244  */
245  *padim = 0, *prate = 0;
246  return false;
247 }
248 
249 /* builds an align from the alignee and template references.
250  * used by both align and realign management.
251  */
252 static align
254  reference alignee,
255  reference temp,
256  list /* of expression */ lopt)
257 {
258  list/* of alignments */ aligns = NIL,
259  /* of expressions */ align_src = reference_indices(alignee),
260  align_sub = reference_indices(temp);
261  entity template = reference_variable(temp),
262  array = reference_variable(alignee);
263  int array_dim, template_dim, tndim, andim;
264  Value rate, shift;
265 
266  if (!entity_template_p(template))
267  array_as_template(template);
268 
269  pips_user_assert("align with a template", entity_template_p(template));
270  pips_user_assert("one set of indices", !(lopt && align_src));
271 
272  if (lopt) align_src = lopt;
273 
274  tndim = NumberOfDimension(template);
275  andim = NumberOfDimension(array);
276 
277  /* each array dimension is looked for a possible alignment
278  */
279 
280  if (ENDP(align_src)) /* align A with T - implicit alignment */
281  {
282  int dim, ndim, tlower, alower, unused;
283 
284  pips_user_assert("no template subscripts", ENDP(align_sub));
285  ndim=MIN(andim, tndim);
286 
287  for (dim=1; dim<=ndim; dim++)
288  {
289  get_entity_dimensions(template, dim, &tlower, &unused);
290  get_entity_dimensions(array, dim, &alower, &unused);
291 
292  aligns = CONS(ALIGNMENT,
293  make_alignment(dim, dim,
295  int_to_expression(-alower+tlower)),
296  aligns);
297  }
298  }
299  else /* explicit alignment */
300  {
301  pips_user_assert("align-source-list length = rank",
302  (int)gen_length(align_src) == andim);
303  pips_user_assert("align-subscript-list length = rank",
304  (int)gen_length(align_sub) == tndim);
305 
306  for(template_dim=1; !ENDP(align_sub); POP(align_sub), template_dim++)
307  {
308  if (alignment_p(align_src, EXPRESSION(CAR(align_sub)),
309  &array_dim, &rate, &shift))
310  aligns = CONS(ALIGNMENT,
311  make_alignment(array_dim,
312  template_dim,
313  Value_to_expression(rate),
314  Value_to_expression(shift)),
315  aligns);
316  }
317  }
318 
319  /* for an alignment tree I should check here whether template is
320  * aligned to sg, and update accordingly. Also backtracking already
321  * built alignments when a "template" happens to be aligned would be
322  * useful. Some day...
323  */
324  /* built align is returned. should be normalized?
325  */
326  return make_align(aligns, template);
327 }
328 
329 /* handle s as the initial alignment...
330  * to be called after the dynamics arrays...
331  */
333 {
334  MAP(ENTITY, array,
335  {
337  {
338  propagate_synonym(s, array, array, true);
340  load_renamings(s)));
341 
343  /* a formal is considered as used to force the remapping
344  */
346  }
347  },
348  get_the_dynamics());
349 }
350 
351 /* handle a simple (re)align directive.
352  * store the mappings in internal data structures.
353  */
354 static void
356  reference alignee,/* the array */
357  reference temp, /* the template */
358  list /* of expressions */ lopt,
359  bool dynamic) /* realign or align */
360 {
361  entity template = reference_variable(temp),
362  array = reference_variable(alignee);
363  align a;
364 
365  pips_debug(3, "%s %saligned with %s\n", entity_name(array),
366  dynamic ? "re" : "", entity_name(template));
367 
368  a = extract_the_align(alignee, temp, lopt);
370 
371  ifdebug(8) print_align(a);
372 
373  if (dynamic)
374  {
376  entity new_array;
377 
378  pips_user_assert("dynamic array realignment",
380 
381  new_array = array_synonym_aligned_as(array, a);
382  propagate_synonym(current, array, new_array, true);
384  CONS(RENAMING, make_renaming(array, new_array),
386  }
387  else
388  {
390  {
393  }
394  else
395  {
396  /* a variable in a common can be declared several alignments
397  * that MUST be the same...
398  */
399  pips_assert("some alignment", bound_hpf_alignment_p(array));
400  }
401  }
402 }
403 
404 /* hack, the common indices of a free form align is stored in a BLOCK()
405  */
407 {
409 }
410 
411 /* handle a full (re)align directive.
412  * just decompose into simple alignments...
413  */
414 static void
416  _UNUSED_ entity f,
417  list /* of expressions */ args,
418  bool dynamic)
419 {
420  list /* of expression */ last = gen_last(args), lopt=NIL;
421  reference template;
422  expression first;
423 
424  /* last points to the last item of args, which should be the template
425  */
426  pips_user_assert("align sg with sg", gen_length(args)>=2);
427  template = expression_to_reference(EXPRESSION(CAR(last)));
428 
430 
431  if (dynamic) store_renamings(current_stmt_head(), NIL);
432 
433  first = EXPRESSION(CAR(args));
435  {
436  pips_debug(5, "external align indices\n");
438  POP(args);
439  }
440 
441  for(; args!=last; POP(args))
443  template, lopt, dynamic);
444 }
445 
446 /* one DISTRIBUTE directive management
447  */
448 /* returns the expected style tag for the given distribution format,
449  * plus a pointer to the list of arguments.
450  */
452  list /* of expressions */ *pl)
453 {
454  syntax s = expression_syntax(e);
455  entity function;
456  const char* name;
457  call c;
458 
459  pips_assert("valid distribution format", syntax_call_p(s));
460 
461  c = syntax_call(s);
462  function = call_function(c);
463  *pl = call_arguments(c);
464 
465  pips_assert("valid distribution format", hpf_directive_entity_p(function));
466 
467  name = entity_local_name(function);
468 
469  if (same_string_p(name, HPF_PREFIX BLOCK_SUFFIX)) /* BLOCK() */
470  return is_style_block;
471  else
472  if (same_string_p(name, HPF_PREFIX CYCLIC_SUFFIX)) /* CYCLIC() */
473  return is_style_cyclic;
474  else
475  if (same_string_p(name, HPF_PREFIX STAR_SUFFIX)) /* * [star] */
476  return is_style_none;
477  else
478  pips_user_error("invalid distribution format");
479 
480  return 0; /* just to avoid a gcc warning */
481 }
482 
483 /* builds the distribute from the distributee and processor references.
484  */
485 static distribute
487 {
489  entity processor = reference_variable(proc),
490  template = reference_variable(distributee);
491  list/* of expressions */ largs,
492  lformat = reference_indices(distributee)? /* keep the non empty one */
493  reference_indices(distributee): reference_indices(proc),
494  /* of distributions */ ldist = NIL;
495  int npdim, ntdim;
496  tag format;
497 
498  if (!entity_template_p(template))
499  array_as_template(template);
500 
501  ntdim = NumberOfDimension(template);
502  npdim = NumberOfDimension(processor);
503 
504  pips_user_assert("more template dimensions than processor dimensions",
505  ntdim>=npdim);
506 
507  /* the template arguments are scanned to build the distribution
508  */
509  if (ENDP(lformat)) /* distribute T onto P - implicit */
510  {
511  int dim;
512  for (dim=1; dim<=npdim; dim++)
513  ldist = CONS(DISTRIBUTION,
516  ldist);
517  }
518  else /* explicit distribution */
519  {
520  for(; !ENDP(lformat); POP(lformat))
521  {
522  format = distribution_format(EXPRESSION(CAR(lformat)), &largs);
523 
524  switch (format)
525  {
526  case is_style_block:
527  case is_style_cyclic:
528  pips_assert("valid distribution", gen_length(largs)<=1);
529 
530  parameter = ENDP(largs) ?
531  expression_undefined : /* implicit size */
532  copy_expression(EXPRESSION(CAR(largs))); /* explicit size */
533 
534  break;
535  case is_style_none:
537  break;
538  default:
539  pips_internal_error("unexpected style tag (%d)", format);
540  }
541 
542  ldist = CONS(DISTRIBUTION,
544  ldist);
545  }
546  }
547 
548  return make_distribute(gen_nreverse(ldist), processor);
549 }
550 
551 /* handles a simple (one template) distribute or redistribute directive.
552  */
553 static void
555  reference distributee, /* the template */
556  reference proc, /* the processor arrangement */
557  bool dynamic) /* redistribute or distribute */
558 {
559  entity processor = reference_variable(proc),
560  template = reference_variable(distributee);
561  distribute d = extract_the_distribute(distributee, proc);
562 
563  pips_user_assert("no indices to processor or :: syntax",
564  ENDP(reference_indices(proc)) || ENDP(reference_indices(distributee)));
565 
566  normalize_distribute(template, d);
567 
568  pips_debug(3, "%s %sdistributed onto %s\n", entity_name(template),
569  dynamic ? "re" : "", entity_name(processor));
570 
571  if (dynamic)
572  {
574  entity new_t;
575 
576  pips_user_assert("dynamic template redistribution",
577  entity_template_p(template) && dynamic_entity_p(template));
578 
579  new_t = template_synonym_distributed_as(template, d);
580  propagate_synonym(current, template, new_t, false);
581 
582  /* the new template may be an array, thus auto-aligned
583  */
584  if (array_distributed_p(template) && !bound_hpf_alignment_p(new_t))
585  array_as_template(new_t);
586 
587  /* all arrays aligned to template are propagated in turn.
588  */
589  MAP(ENTITY, array,
590  {
591  align a;
592  entity new_array;
593 
594  pips_debug(7, "array 0x%p\n", array);
595  pips_debug(7, "alive array %s\n", entity_name(array));
596 
598  new_array = array_synonym_aligned_as(array, a);
599 
600  propagate_synonym(current, array, new_array, true);
602  CONS(RENAMING, make_renaming(array, new_array),
604 
605  pips_debug(9, "done with %s->%s\n",
606  entity_name(array), entity_name(new_array));
607  },
608  alive_arrays(current, template));
609  }
610  else
611  store_hpf_distribution(template, d);
612 
613  pips_debug(4, "out\n");
614 }
615 
616 /* handles a full distribute or redistribute directive.
617  */
618 static void
620  _UNUSED_ entity f,
621  list args, // of expressions
622  bool dynamic)
623 {
624  list /* of expression */ last = gen_last(args);
625  reference proc;
626 
627  if (dynamic) store_renamings(current_stmt_head(), NIL);
628 
629  /* last points to the last item of args, which should be the processors
630  */
631  pips_user_assert("distribute sg with sg", gen_length(args)>=2);
632  proc = expression_to_reference(EXPRESSION(CAR(last)));
634 
635  /* calls the simple case handler.
636  */
637  for(; args!=last; POP(args))
639  proc, dynamic);
640 }
641 
642 
643 /******************************************************* DIRECTIVE HANDLERS */
644 
645 /* each directive is handled by a function here.
646  * these handlers may use the statement stack to proceed.
647  * I may add some handlers for private directives?
648  */
649 
650 #define HANDLER(name) handle_##name##_directive
651 
652 // default case issues an error.
653 static void
655 {
656  pips_user_error("unexpected hpf directive\n");
657 }
658 
659 static void
661 {
662  gen_map((gen_iter_func_t)new_processor, args); /* see new_processor */
663 }
664 
665 static void
667 {
668  gen_map((gen_iter_func_t)new_template, args); /* see new_template */
669 }
670 
671 static void
673 {
675 }
676 
677 static void
679 {
681 }
682 
683 /* I chose not to modify the ri to add reductions as private variables.
684  * the reason is the following: locals are not well placed (they should
685  * be attached to statements?), I won't add one more misplaced sg.
686  * Also I would have to update *all* make_loop() within PIPS...
687  */
688 static void
690 {
691  list /* of entity */ l = expressions_to_entities(args);
692  statement s;
693 
695 
696  while(next_ctrl_graph_travel(&s))
697  {
699  {
700  if (!bound_hpf_reductions_p(s))
702  else
703  {
706  }
708  return;
709  }
710  }
711 
713  pips_user_error("some loop not found!\n");
714 }
715 
716 /* ??? I wait for the next statements in a particular order, what
717  * should not be necessary. Means I should deal with independent
718  * directives on the PARSED_CODE rather than after the CONTROLIZED.
719  */
720 static void
722 {
723  list /* of entities */ l = expressions_to_entities(args);
724  statement s;
725 
726  pips_debug(2, "%zd index(es)\n", gen_length(l));
727 
728  /* travels thru the full control graph to find the loops
729  * and tag them as parallel.
730  */
732 
733  while(next_ctrl_graph_travel(&s))
734  {
736 
737  if (instruction_loop_p(i)) /* what we're looking for */
738  {
739  loop o = instruction_loop(i);
740  entity index = loop_index(o);
741 
742  if (ENDP(l)) /* simple independent case, first loop is tagged // */
743  {
744  pips_debug(3, "parallel loop\n");
745 
748  return;
749  }
750  /* else general independent case (with a list of indexes)
751  */
752  if (gen_in_list_p(index, l))
753  {
754  pips_debug(3, "parallel loop (%s)\n", entity_name(index));
755 
757  gen_remove(&l, index);
758 
759  if (ENDP(l)) /* the end */
760  {
762  return;
763  }
764  }
765  }
766  }
767 
769  pips_user_error("some loop not found!\n");
770 }
771 
772 /* ??? not implemented and not used. The independent directive is trusted
773  * by the compiler to apply its optimizations...
774  */
775 static void
777 {
778  hpfc_warning("not implemented\n");
779  return; /* (that's indeed a first implementation:-) */
780 }
781 
782 static void
784 {
785  gen_map((gen_iter_func_t)new_dynamic, args); /* see new_dynamic */
786 }
787 
788 /* may be used to declare functions as pure.
789  * ??? it is not a directive in HPF, but I put it this way in F77.
790  * ??? pure declarations are not yet used by HPFC.
791  */
792 static void
794 {
796 
797  if (ENDP(args))
799  else
801 }
802 
803 static void
805 {
807  if (ENDP(args))
809  else
811 }
812 
813 static void
815 {
817  if (ENDP(args))
819  else
821 }
822 
823 static void
825 {
827 }
828 
829 static void
831 {
833 }
834 
835 /*********************************************** handlers for FCD directives */
836 
837 static void
839 {
840  if (get_bool_property(FCD_IGNORE_PREFIX "SYNCHRO"))
842 }
843 
844 /* for both timeon and timeoff
845  */
846 static void
848 {
851 }
852 
853 static void
855 {
856  pips_debug(8, "host section\n");
857  return;
858 }
859 
860 /* for both setbool and setint
861  * ??? looks like a hack:-)
862  */
863 static void
865 {
867  {
868  expression arg1, arg2;
869  string property;
870  int val, i;
871 
872  pips_user_assert("two args", gen_length(args)==2);
873  arg1 = EXPRESSION(CAR(args));
874  arg2 = EXPRESSION(CAR(CDR(args)));
875  pips_user_assert("constant args",
876  expression_is_constant_p(arg1) &&
878 
879  /* property name.
880  * ??? moved to uppers because hpfc_directives put lowers.
881  * ??? plus having to deal with quotes that are put in the name!
882  */
885  for (i=0; property[i]; i++) property[i]=toupper(property[i]);
886  property[i-1]='\0';
887 
888  val = HpfcExpressionToInt(arg2);
889 
891  set_bool_property(property+1, val);
892  else
893  set_int_property(property+1, val);
894 
895  free(property);
896  }
897 
899 }
900 
901 /* prescriptive mappings before a call.
902  * another kind of remapping, as realign and redistribute.
903  */
904 static void
906 {
908  entity array, new_array;
909 
911  new_array = expression_to_entity(EXPRESSION(CAR(CDR(args))));
912 
913  propagate_synonym(current, array, new_array, true);
914 
915  /* only one renaming per rename directive!
916  */
918  CONS(RENAMING, make_renaming(array, new_array), NIL));
919 
920 }
921 
922 /* tells the compiler that the array values are dead from now on.
923  * can be used by the propagation to stop the process...
924  * and mark at this point all copies as live! pretty simple handling!
925  * I let the call as a marker for itself, and it will be removed later
926  * on at the compilation stage *only*...
927  */
928 static void
930 {
931  pips_debug(4, "dead directive encountered");
932 }
933 
934 static void
936 {
937  pips_debug(4, "skipping entity %s\n", entity_name(f));
938 }
939 
940 /******************************************************** DIRECTIVE HANDLING */
941 
942 /* finds the handler for a given entity.
943  * the link between directive names and handlers is stored in the
944  * handlers static table. Some "directives" (BLOCK, CYCLIC) are
945  * unexpected because they cannot appear after the chpf$...
946  * Ok, they are not directives, but I put them here as if.
947  */
949 {
950  string name; /* all names must start with the HPF_PREFIX */
951  int phase; /* which pass should consider the directive */
952  void (*handler)(entity, list); /* handler for directive "name" */
953 };
954 
955 static struct DirectiveHandler handlers[] =
956 {
957  /* special functions for HPF keywords are not expected at this level
958  */
962 
963  /* FC (== Fabien Coelho:-) directives
964  */
965  {HPF_PREFIX SYNCHRO_SUFFIX, 1, HANDLER(synchro) },
966  {HPF_PREFIX TIMEON_SUFFIX, 1, HANDLER(time) },
967  {HPF_PREFIX TIMEOFF_SUFFIX, 1, HANDLER(time) },
968  {HPF_PREFIX HOSTSECTION_SUFFIX, 1, HANDLER(host_section) },
971  {HPF_PREFIX HPFCIO_SUFFIX, 1, HANDLER(io) },
972  {HPF_PREFIX FAKE_SUFFIX, 1, HANDLER(fake) },
973 
974  /* HPF directives
975  */
978  {HPF_PREFIX PROCESSORS_SUFFIX, 1, HANDLER(processors) },
979  {HPF_PREFIX TEMPLATE_SUFFIX, 1, HANDLER(template) },
980  {HPF_PREFIX PURE_SUFFIX, 1, HANDLER(pure) },
981 
982  {HPF_PREFIX DYNAMIC_SUFFIX, 3, HANDLER(dynamic) },
983  {HPF_PREFIX REALIGN_SUFFIX, 3, HANDLER(realign) },
984  {HPF_PREFIX REDISTRIBUTE_SUFFIX, 3, HANDLER(redistribute) },
985  {HPF_PREFIX INDEPENDENT_SUFFIX, 3, HANDLER(independent) },
986  {HPF_PREFIX NEW_SUFFIX, 3, HANDLER(new) },
988  {HPF_PREFIX DEAD_SUFFIX, 3, HANDLER(kill) },
989 
990  // remappings before/after a call. internal management.
991 
992  {HPF_PREFIX RENAME_SUFFIX, 3, HANDLER(prescriptive) },
993  {HPF_PREFIX TELL_SUFFIX, 1, HANDLER(nothing) },
994 
995  // default issues an error
996  {(string) NULL, 0, HANDLER(unexpected) }
997 };
998 
999 /* returns the handler for directive name.
1000  * assumes that name should point to a directive.
1001  */
1002 static void (*directive_handler(const char* name))(entity, list)
1003 {
1004  struct DirectiveHandler *x=handlers;
1005  while (x->name && strcmp(name, x->name)) x++;
1006  return (!x->phase || x->phase==analysis_phase)?
1007  x->handler: HANDLER(nothing);
1008 }
1009 
1010 static bool directive_managed_now_p(const char* name)
1011 {
1012  return directive_handler(name)!=HANDLER(nothing);
1013 }
1014 
1015 /* newgen recursion thru the IR.
1016  */
1017 static bool directive_filter(call c)
1018 {
1019  entity f = call_function(c);
1020 
1021  // DIRECTIVES
1023  {
1024  const char* name = entity_local_name(f);
1025  pips_debug(8, "hpfc entity is %s\n", entity_name(f));
1026 
1027  // call the appropriate handler for the directive.
1028  (directive_handler(name))(f, call_arguments(c));
1029 
1030  // the current statement will have to be cleaned.
1033  }
1034 
1035  return false; // no instructions within a call!
1036 }
1037 
1039 {
1040  entity f = call_function(c);
1041 
1043  {
1044  pips_debug(5, "distributed call to %s\n", entity_name(f));
1046  }
1047 
1048  return false;
1049 }
1050 
1051 /* void handle_hpf_directives(s)
1052  * statement s;
1053  *
1054  * what: handles the HPF directives in statement s.
1055  * how: recurses thru the AST, looking for special "directive calls".
1056  * when found, a special handler is called for the given directive.
1057  * input: the code statement s
1058  * output: none
1059  * side effects: (many)
1060  * - the hpfc data structures are set/updated to store the hpf mapping.
1061  * - parallel loops are tagged parallel.
1062  * - a static stack is used to retrieve the current statement.
1063  * - the ctrl_graph travelling is used, so should be initialized.
1064  * - the special calls are freed and replaced by continues.
1065  * bugs or features:
1066  * - the "new" directive is not used to tag private variables.
1067  * - a non hpf "pure" directive is parsed.
1068  */
1070 {
1071  /* INITIALIZE needed static stuff
1072  */
1073  make_current_stmt_stack();
1074  to_be_cleaned = NIL;
1075 
1076  if (!dyn)
1077  {
1078  /* PHASE 1
1079  */
1080  pips_debug(1, "starting phase 1\n");
1081  analysis_phase = 1;
1083  statement_domain, current_stmt_filter, current_stmt_rewrite,
1086  NULL);
1087  }
1088  else
1089  {
1090  /* PHASE 2
1091  */
1094  store_renamings(s, NIL);
1095 
1096  pips_debug(1, "starting phase 2\n");
1097  analysis_phase = 2;
1099  statement_domain, current_stmt_filter, current_stmt_rewrite,
1101  NULL);
1102 
1103  DEBUG_STAT(7, "between phase 2 and 3", s);
1104 
1105 
1106  /* PHASE 3
1107  */
1108  pips_debug(1, "starting phase 3\n");
1109  analysis_phase = 3;
1112  statement_domain, current_stmt_filter, current_stmt_rewrite,
1115  NULL);
1116 
1117  initial_alignment(s);
1118 
1119  ifdebug(7) dump_current_remapping_graph("after phase 3");
1120  DEBUG_STAT(7, "after phase 3", s);
1121 
1122  /* OPTIMIZATION
1123  */
1124  if (get_bool_property("HPFC_OPTIMIZE_REMAPPINGS"))
1125  {
1126  pips_debug(1, "starting optimization phase\n");
1128  }
1129 
1130  clean_ctrl_graph();
1131 
1133 
1136 
1137  DEBUG_STAT(7, "after optimization phase", s);
1138  }
1139 
1140  /* CLEAN
1141  */
1143  pips_assert("empty stack", current_stmt_empty_p());
1145  free_current_stmt_stack();
1146 
1147  DEBUG_CODE(5, "resulting code", get_current_module_entity(), s);
1148 }
1149 
1150 /* that is all
1151  */
distribution make_distribution(style a1, expression a2)
Definition: hpf.c:178
distribute make_distribute(list a1, entity a2)
Definition: hpf.c:136
alignment make_alignment(intptr_t a1, intptr_t a2, expression a3, expression a4)
Definition: hpf.c:94
align make_align(list a1, entity a2)
Definition: hpf.c:52
style make_style(enum style_utype tag, void *val)
Definition: hpf.c:228
entities make_entities(list a)
Definition: hpf_private.c:250
renaming make_renaming(entity a1, entity a2)
Definition: hpf_private.c:881
call make_call(entity a1, list a2)
Definition: ri.c:269
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
void free_instruction(instruction p)
Definition: ri.c:1118
void free_call(call p)
Definition: ri.c:236
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
#define MIN(x, y)
minimum and maximum if they are defined somewhere else, they are very likely to be defined the same w...
int Value
bool expression_is_constant_p(expression e)
BEGIN_EOLE.
Definition: constant.c:666
void build_full_ctrl_graph(statement)
Definition: graph.c:238
bool next_ctrl_graph_travel(statement *)
Definition: graph.c:325
void init_ctrl_graph_travel(statement, bool(*)(statement))
Definition: graph.c:315
void clean_ctrl_graph(void)
global mapping from statements to their control in the full control graph
Definition: graph.c:53
void close_ctrl_graph_travel(void)
Definition: graph.c:340
void print_align(align a)
this is a set of functions to help hpfc debugging
Definition: debug-util.c:38
void close_dynamic_locals()
Definition: dynamic.c:817
list alive_arrays(statement s, entity t)
what: returns the list of alive arrays for statement s and template t.
Definition: dynamic.c:1504
void init_dynamic_locals()
DYNAMIC LOCAL DATA.
Definition: dynamic.c:806
void hpfc_translate_call_with_distributed_args(statement s, call c)
??? only simple calls are handled.
Definition: dynamic.c:687
bool(* dynamic_entity_p)(entity)
as expected, true if entity e is dynamic.
Definition: dynamic.c:145
void dump_current_remapping_graph(string when)
Definition: dynamic.c:1440
void simplify_remapping_graph(void)
void simplify_remapping_graph()
Definition: dynamic.c:1467
void propagate_synonym(statement s, entity old, entity new, bool is_array)
Definition: dynamic.c:1096
bool hpfc_call_with_distributed_args_p(call c)
whether call c inplies a distributed argument
Definition: dynamic.c:645
void set_entity_as_dynamic(entity e)
a new dynamic entity is stored.
Definition: dynamic.c:130
void hpfc_check_for_similarities(list le)
check all dynamic arrays for some similars...
Definition: dynamic.c:269
void add_as_a_used_dynamic_to_statement(statement s, entity e)
Definition: dynamic.c:904
align new_align_with_template(align a, entity t)
Definition: dynamic.c:474
entity template_synonym_distributed_as(entity temp, distribute d)
what: finds or creates a new entity distributed as needed.
Definition: dynamic.c:491
statement generate_copy_loop_nest(entity src, entity trg)
statement generate_copy_loop_nest(src, trg) entity src, trg;
Definition: dynamic.c:1568
entity array_synonym_aligned_as(entity array, align a)
entity array_synonym_aligned_as(array, a) entity array; align a;
Definition: dynamic.c:449
static statement current_stmt
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
void free(void *)
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
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 gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
instruction make_instruction_block(list statements)
Build an instruction block from a list of statements.
Definition: instruction.c:106
#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
void gen_remove(list *cpp, const void *o)
remove all occurences of item o from list *cpp, which is thus modified.
Definition: list.c:685
#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
list gen_once(const void *vo, list l)
Prepend an item to a list only if it is not already in the list.
Definition: list.c:722
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
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 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
void fix_sequence_statement_attributes(statement)
Since blocks are not represented in Fortran, they cannot carry a label.
Definition: statement.c:2016
#define DISTRIBUTION(x)
DISTRIBUTION.
Definition: hpf.h:180
#define ALIGNMENT(x)
ALIGNMENT.
Definition: hpf.h:102
@ is_style_cyclic
Definition: hpf.h:239
@ is_style_block
Definition: hpf.h:238
@ is_style_none
Definition: hpf.h:237
#define renaming_old(x)
Definition: hpf_private.h:969
#define entities_list(x)
Definition: hpf_private.h:414
#define renaming_new(x)
Definition: hpf_private.h:971
#define RENAMING(x)
RENAMING.
Definition: hpf_private.h:939
void get_entity_dimensions(entity e, int dim, int *plow, int *pup)
Definition: hpfc-util.c:651
int HpfcExpressionToInt(expression e)
HpfcExpressionToInt(e)
Definition: hpfc-util.c:569
void normalize_align(_UNUSED_ entity e, align a)
Definition: declarations.c:426
void normalize_distribute(entity t, distribute d)
Definition: declarations.c:408
#define RENAME_SUFFIX
#define hpfc_warning
WARNING.
#define DEBUG_STAT(D, W, S)
#define DEBUG_CODE(D, W, M, S)
static bool directive_managed_now_p(const char *name)
Definition: directives.c:1010
static void handle_unexpected_directive(_UNUSED_ entity f, _UNUSED_ list args)
Definition: directives.c:654
static void handle_time_directive(_UNUSED_ entity f, _UNUSED_ list args)
for both timeon and timeoff
Definition: directives.c:847
static void handle_host_section_directive(_UNUSED_ entity f, _UNUSED_ list args)
Definition: directives.c:854
static struct DirectiveHandler handlers[]
Definition: directives.c:955
#define HANDLER(name)
each directive is handled by a function here.
Definition: directives.c:650
static void one_align_directive(reference alignee, reference temp, list lopt, bool dynamic)
handle a simple (re)align directive.
Definition: directives.c:355
static distribute extract_the_distribute(reference distributee, reference proc)
builds the distribute from the distributee and processor references.
Definition: directives.c:486
static void handle_distribute_directive(entity f, list args)
Definition: directives.c:678
static void handle_new_directive(_UNUSED_ entity f, _UNUSED_ list args)
??? not implemented and not used.
Definition: directives.c:776
void add_a_dynamic(entity c)
local primary dynamics
Definition: directives.c:99
static bool align_indices_p(entity f)
hack, the common indices of a free form align is stored in a BLOCK()
Definition: directives.c:406
static void array_as_template(entity array)
array is to be seen as a template.
Definition: directives.c:170
static void handle_dynamic_directive(_UNUSED_ entity f, list args)
Definition: directives.c:783
static void new_processor(expression e)
Definition: directives.c:126
static void initial_alignment(statement s)
handle s as the initial alignment...
Definition: directives.c:332
static void new_fake_function(expression e)
Definition: directives.c:158
static void handle_kill_directive(_UNUSED_ entity f, _UNUSED_ list args)
tells the compiler that the array values are dead from now on.
Definition: directives.c:929
static void new_pure_function(expression e)
Definition: directives.c:163
static void handle_realign_directive(entity f, list args)
Definition: directives.c:824
static void handle_redistribute_directive(entity f, list args)
Definition: directives.c:830
static void handle_processors_directive(_UNUSED_ entity f, list args)
Definition: directives.c:660
static void handle_reduction_directive(_UNUSED_ entity f, list args)
I chose not to modify the ri to add reductions as private variables.
Definition: directives.c:689
static void handle_prescriptive_directive(_UNUSED_ entity f, list args)
prescriptive mappings before a call.
Definition: directives.c:905
static void(*)(entity, list) directive_handler(const char *name)
returns the handler for directive name.
Definition: directives.c:1002
static void handle_template_directive(_UNUSED_ entity f, list args)
Definition: directives.c:666
static bool prescription_filter(call c)
Definition: directives.c:1038
static void add_statement_to_clean(statement s)
Definition: directives.c:90
static void handle_independent_directive(_UNUSED_ entity f, list args)
??? I wait for the next statements in a particular order, what should not be necessary.
Definition: directives.c:721
static bool directive_filter(call c)
newgen recursion thru the IR.
Definition: directives.c:1017
static void handle_align_directive(entity f, list args)
Definition: directives.c:672
static void new_template(expression e)
Definition: directives.c:135
static void handle_pure_directive(_UNUSED_ entity f, list args)
may be used to declare functions as pure.
Definition: directives.c:793
void hpfc_directives_error_handler()
the local stack is used to retrieve the current statement while scanning the AST with gen_recurse.
Definition: directives.c:109
static tag distribution_format(expression e, list *pl)
one DISTRIBUTE directive management
Definition: directives.c:451
static void one_distribute_directive(reference distributee, reference proc, bool dynamic)
handles a simple (one template) distribute or redistribute directive.
Definition: directives.c:554
static void handle_align_and_realign_directive(_UNUSED_ entity f, list args, bool dynamic)
handle a full (re)align directive.
Definition: directives.c:415
static align extract_the_align(reference alignee, reference temp, list lopt)
builds an align from the alignee and template references.
Definition: directives.c:253
static void handle_synchro_directive(_UNUSED_ entity f, _UNUSED_ list args)
Definition: directives.c:838
static void handle_nothing_directive(entity f, _UNUSED_ list args)
Definition: directives.c:935
static void handle_distribute_and_redistribute_directive(_UNUSED_ entity f, list args, bool dynamic)
handles a full distribute or redistribute directive.
Definition: directives.c:619
static bool alignment_p(list align_src, expression subscript, int *padim, Value *prate, Value *pshift)
one simple ALIGN directive is handled.
Definition: directives.c:193
static int analysis_phase
HPFC module by Fabien COELHO.
Definition: directives.c:44
static void new_io_function(expression e)
Definition: directives.c:153
static void handle_set_directive(entity f, list args)
for both setbool and setint ??? looks like a hack:-)
Definition: directives.c:864
static void switch_basic_type_to_overloaded(entity e)
management of PROCESSORS and TEMPLATE directives.
Definition: directives.c:119
static void handle_io_directive(_UNUSED_ entity f, list args)
Definition: directives.c:804
static void handle_fake_directive(_UNUSED_ entity f, list args)
Definition: directives.c:814
static void new_dynamic(expression e)
Definition: directives.c:144
static list to_be_cleaned
list of statements to be cleaned.
Definition: directives.c:51
static void clean_statement(statement s)
the directive is freed and replaced by a continue call or a copy loop nest, depending on the renaming...
Definition: directives.c:56
void handle_hpf_directives(statement s, bool dyn)
void handle_hpf_directives(s) statement s;
Definition: directives.c:1069
void add_an_io_function(entity f)
Definition: hpfc.c:74
void add_a_pure(entity f)
Definition: hpfc.c:62
void add_a_fake_function(entity f)
Definition: hpfc.c:88
bool bound_hpf_reductions_p(statement)
bool bound_renamings_p(statement)
void store_hpf_distribution(entity, distribute)
list load_renamings(statement)
bool entity_template_p(entity)
void set_template(entity)
list get_the_dynamics(void)
void store_hpf_alignment(entity, align)
void update_renamings(statement, list)
void close_the_dynamics(void)
entities load_hpf_reductions(statement)
align load_hpf_alignment(entity)
void init_the_dynamics(void)
bool bound_hpf_alignment_p(entity)
void set_array_as_distributed(entity)
void store_renamings(statement, list)
void store_hpf_reductions(statement, entities)
bool array_distributed_p(entity)
void set_processor(entity)
#define current_stmt_head()
We want to keep track of the current statement inside the recurse.
Definition: icfg_scan.c:76
int vect_size(Pvecteur v)
package vecteur - reductions
Definition: reductions.c:47
static void unexpected(void)
Definition: lowlevel.c:61
#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
#define pips_user_assert(what, predicate)
Definition: misc-local.h:181
#define pips_user_error
Definition: misc-local.h:147
#define GENERIC_STATIC_STATUS(PREFIX, name, type, init, cloze)
#define DEFINE_LOCAL_STACK(name, type)
#define same_string_p(s1, s2)
int tag
TAG.
Definition: newgen_types.h:92
char * string
STRING.
Definition: newgen_types.h:39
void(* gen_iter_func_t)(void *)
Definition: newgen_types.h:116
#define UU
Definition: newgen_types.h:98
struct cons * list
Definition: newgen_types.h:106
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
void normalize_all_expressions_of(void *obj)
Definition: normalize.c:668
static char * module
Definition: pips.c:74
static hash_table pl
properties are stored in this hash table (string -> property) for fast accesses.
Definition: properties.c:783
void set_bool_property(const char *, bool)
void set_int_property(const char *, int)
struct _newgen_struct_property_ * property
Definition: property.h:15
#define DEAD_SUFFIX
#define HPF_PREFIX
moved here because needed by syntax:-(
#define TIMEON_SUFFIX
#define SYNCHRO_SUFFIX
#define FCD_IGNORE_PREFIX
property prefix for ignoring FCD directives TIME, SYNCHRO and SET exists.
#define REALIGN_SUFFIX
#define CYCLIC_SUFFIX
#define REDISTRIBUTE_SUFFIX
#define INDEPENDENT_SUFFIX
#define FAKE_SUFFIX
#define HOSTSECTION_SUFFIX
#define BLOCK_SUFFIX
suffixies for encoded hpf keywords
#define SETINT_SUFFIX
#define DYNAMIC_SUFFIX
#define DISTRIBUTE_SUFFIX
#define PURE_SUFFIX
#define CONTINUE_FUNCTION_NAME
#define TIMEOFF_SUFFIX
#define HPFCIO_SUFFIX
#define TELL_SUFFIX
suffixes for my own (FCD:-) directives.
#define REDUCTION_SUFFIX
#define SETBOOL_SUFFIX
#define PROCESSORS_SUFFIX
#define TEMPLATE_SUFFIX
#define STAR_SUFFIX
#define ALIGN_SUFFIX
suffixes for HPF directives managed by HPFC
#define NEW_SUFFIX
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
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
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
reference expression_to_reference(expression e)
Definition: expression.c:212
list expressions_to_entities(list expressions)
map expression_to_entity on expressions
Definition: expression.c:3161
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
expression Value_to_expression(Value v)
added interface for linear stuff.
Definition: expression.c:1251
entity expression_to_entity(expression e)
just returns the entity of an expression, or entity_undefined
Definition: expression.c:3140
bool hpf_directive_entity_p(entity e)
Definition: hpfc.c:56
bool keep_directive_in_code_p(const char *s)
whether an entity must be kept in the code.
Definition: hpfc.c:101
int NumberOfDimension(entity)
Definition: size.c:588
#define execution_tag(x)
Definition: ri.h:1207
@ is_basic_overloaded
Definition: ri.h:574
#define expression_domain
newgen_execution_domain_defined
Definition: ri.h:154
#define loop_execution(x)
Definition: ri.h:1648
#define storage_formal_p(x)
Definition: ri.h:2522
#define normalized_complex_p(x)
Definition: ri.h:1782
#define normalized_linear_p(x)
Definition: ri.h:1779
#define instruction_loop_p(x)
Definition: ri.h:1518
#define call_function(x)
Definition: ri.h:709
#define reference_variable(x)
Definition: ri.h:2326
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define syntax_call_p(x)
Definition: ri.h:2734
#define instruction_loop(x)
Definition: ri.h:1520
#define basic_tag(x)
Definition: ri.h:613
#define entity_storage(x)
Definition: ri.h:2794
#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 basic_undefined
Definition: ri.h:556
#define expression_undefined
Definition: ri.h:1223
#define entity_name(x)
Definition: ri.h:2790
#define expression_normalized(x)
Definition: ri.h:1249
#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 statement_instruction(x)
Definition: ri.h:2458
#define instruction_call(x)
Definition: ri.h:1529
@ is_execution_parallel
Definition: ri.h:1190
#define call_arguments(x)
Definition: ri.h:711
#define call_undefined
Definition: ri.h:685
#define normalized_linear(x)
Definition: ri.h:1781
#define expression_syntax(x)
Definition: ri.h:1247
#define loop_index(x)
Definition: ri.h:1640
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
char * strdup()
#define ifdebug(n)
Definition: sg.c:47
static entity array
static char * x
Definition: split_file.c:159
static size_t current
Definition: string.c:115
finds the handler for a given entity.
Definition: directives.c:949
int phase
all names must start with the HPF_PREFIX
Definition: directives.c:951
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
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
#define TCST
VARIABLE REPRESENTANT LE TERME CONSTANT.
#define var_of(varval)
Value vect_coeff(Variable var, Pvecteur vect)
Variable vect_coeff(Variable var, Pvecteur vect): coefficient de coordonnee var du vecteur vect —> So...
Definition: unaires.c:228