PIPS
freia.c
Go to the documentation of this file.
1 /*
2 
3  $Id: freia.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 <stdint.h>
30 #include <stdlib.h>
31 
32 #include "genC.h"
33 #include "misc.h"
34 
35 #include "freia.h"
36 
37 #include "linear.h"
38 #include "pipsdbm.h"
39 
40 #include "ri.h"
41 #include "effects.h"
42 #include "ri-util.h"
43 #include "prettyprint.h"
44 #include "effects-util.h"
45 #include "properties.h"
46 #include "c_syntax.h"
47 
48 #include "freia_spoc_private.h"
49 #include "hwac.h"
50 
51 /************************************************************ CLEANUP STATUS */
52 
53 typedef struct {
54  // entities: variables used to hold freia status returns
56  // entities: set of generated helper functions, may be NULL
58 } fcs_ctx;
59 
60 static bool fcs_call_flt(call c, fcs_ctx * ctx)
61 {
62  entity called = call_function(c);
63  if (freia_assignment_p(called))
64  {
65  list largs = call_arguments(c);
66  pips_assert("two arguments to = or |=", gen_length(largs)==2);
67  expression erhs = EXPRESSION(CAR(CDR(largs)));
68 
69  // catch and eat-up "foo |= 0;"
70  _int val;
71  if (ENTITY_BITWISE_OR_UPDATE_P(called) &&
72  expression_integer_value(erhs, &val) && val==0)
73  {
76  return false;
77  }
78 
79  // else, is it a call to some aipo or helper function?
80  syntax op = expression_syntax(erhs);
81  if (!syntax_call_p(op))
82  return false;
83 
84  // is it an aipo or helper call?
85  call rhs = syntax_call(op);
87  (ctx->helper_functions &&
89  {
90  // record scrapped status variable
91  syntax slhs = expression_syntax(EXPRESSION(CAR(largs)));
92  pips_assert("left hand side is a scalar reference",
93  syntax_reference_p(slhs) &&
97 
98  // and scrap its assignement!
99  call_function(c) = call_function(rhs);
100  call_arguments(c) = call_arguments(rhs);
101 
102  // hmmm... small memory leak in assigned lhs,
103  // but I'm not sure of effect references...
104  call_arguments(rhs) = NIL;
105  free_call(rhs);
106  gen_free_list(largs);
107  }
108  }
109  // no second level anyway? what about ","?
110  return false;
111 }
112 
113 /*
114  foo |= freia_aipo_* or helpers -> freia_aipo_* or helpers
115  foo = freia_aipo_* or helpers -> freia_aipo_* or helpers
116  foo |= 0 -> <nope>
117  declaration: foo = 0 (FREIA_OK), if it is not initialized.
118  ??? not managed: freia_aipo_ calls in declarations, return, ","?
119 */
120 static void freia_cleanup_status(statement s, set helpers)
121 {
122  fcs_ctx ctx = { set_make(set_pointer), helpers };
123 
124  // cleanup statements
126 
127  // fix status variable initializations
129  {
131  {
133  entity_initial(var) =
135  }
136  }
137 
138  // cleanup
140 }
141 
142 /**************************************************** LOOK FOR IMAGE SHUFFLE */
143 
144 typedef struct {
146 } fis_ctx;
147 
148 static bool fis_call_flt(call c, fis_ctx * ctx)
149 {
150  list args = call_arguments(c);
152  {
153  pips_assert("assign takes two args", gen_length(args)==2);
156  if (a2!=entity_undefined &&
158  {
159  set_add_element(ctx->shuffled, ctx->shuffled, a1);
160  set_add_element(ctx->shuffled, ctx->shuffled, a2);
161  return false;
162  }
163  }
164  return true;
165 }
166 
167 /* @return whether there is an image shuffle, i.e. image pointer assignments
168  */
169 static bool freia_image_shuffle(statement s, set shuffled)
170 {
171  fis_ctx ctx = { shuffled };
173  return set_size(shuffled)!=0;
174 }
175 
176 /******************************************************* SWITCH CAST TO COPY */
177 
178 static void sctc_call_rwt(call c, int * count)
179 {
180  entity func = call_function(c);
181  if (same_string_p(entity_local_name(func), AIPO "cast"))
182  {
184  (*count)++;
185  }
186 }
187 
188 /* @brief switch all image casts to image copies in "s"
189  */
191 {
192  int count = 0;
194  // ??? I may have look into declarations? freia calls in declarations
195  // are not really implemented yet.
196  pips_user_warning("freia_cast switched to freia_copy: %d\n", count);
197 }
198 
199 
200 /*************************************************************** BASIC UTILS */
201 
202 static bool freia_stmt_free_p(const statement s)
203 {
205  const char* called = c? entity_user_name(call_function(c)): "";
206  return same_string_p(called, FREIA_FREE);
207 }
208 
209 static bool freia_alloc_call_p(const call c)
210 {
211  entity f = call_function(c);
212  const char *called = entity_user_name(f);
213  return same_string_p(called, FREIA_ALLOC) ||
214  same_string_p(called, FREIA_FREE);
215 }
216 
217 static bool freia_alloc_stat_p(const statement s)
218 {
220  if (c == NULL)
221  return false;
222  entity f = call_function(c);
223  if (ENTITY_CONTINUE_P(f))
224  {
226  {
227  value val = entity_initial(var);
228  if (value_expression_p(val))
229  {
231  if (expression_call_p(eval) &&
233  return false;
234  }
235  else if (!value_unknown_p(val))
236  return false;
237  }
238  return true;
239  }
240  else
241  return freia_alloc_call_p(c);
242 }
243 
244 /* move statements in l ahead of s in sq
245  * note that ls is in reverse order...
246  */
247 static void move_ahead(list ls, statement target, sequence sq)
248 {
249  // for faster list inclusion test
250  set tomove = set_make(set_pointer);
251  set_append_list(tomove, ls);
252 
253  // build new sequence list in reverse order
254  list nsq = NIL;
256  {
257  if (set_belong_p(tomove, s))
258  continue; // skip!
259  if (s==target)
260  // insert list now!
261  nsq = gen_nconc(gen_copy_seq(ls), nsq);
262  // and keep current statement
263  nsq = CONS(statement, s, nsq);
264  }
265 
266  // update sequence with new list
269 
270  // clean up
271  set_free(tomove);
272 }
273 
274 /******************************************************** REORDER STATEMENTS */
275 
276 /* order two statements for qsort.
277  * s1 before s2 => -1
278  */
279 static int freia_cmp_statement(const statement * s1, const statement * s2)
280 {
281  const call
282  c1 = statement_call_p(*s1)?
284  c2 = statement_call_p(*s2)?
286  bool
287  s1r = c1? ENTITY_C_RETURN_P(call_function(c1)): false,
288  s2r = c2? ENTITY_C_RETURN_P(call_function(c2)): false,
289  s1a = is_freia_alloc(*s1), s2a = is_freia_alloc(*s2),
290  s1d = is_freia_dealloc(*s1), s2d = is_freia_dealloc(*s2);
291  if (s1r || s2r) pips_assert("one return in sequence", s1r ^ s2r);
292 
293  pips_debug(9, "%"_intFMT" %s is %d %d %d\n", statement_number(*s1),
294  c1? entity_name(call_function(c1)): "", s1r, s1a, s1d);
295  pips_debug(9, "%"_intFMT" %s is %d %d %d\n", statement_number(*s2),
296  c2? entity_name(call_function(c2)): "", s2r, s2a, s2d);
297 
298  int order = 0;
299  string why = "";
300 
301  // return at the back, obviously...
302  if (s1r) order = 1, why = "return1";
303  else if (s2r) order = -1, why = "return2";
304  // allocs at the front (there may be in initialisations, which up front)
305  else if (s1a && !s2a) order = -1, why = "alloc1";
306  else if (s2a && !s1a) order = 1, why = "alloc2";
307  // deallocs at the back
308  else if (s1d && !s2d) order = 1, why = "free1";
309  else if (s2d && !s1d) order = -1, why = "free2";
310  // else keep statement initial order
311  else order = statement_number(*s1)-statement_number(*s2), why = "stat";
312 
313  pips_assert("total order", order!=0);
314 
315  pips_debug(7, "%"_intFMT" %s %"_intFMT" (%s)\n", statement_number(*s1),
316  order==-1? "<": ">", statement_number(*s2), why);
317 
318  return order;
319 }
320 
321 /* debug helper */
322 static string stmt_nb(void * s)
323 {
324  return i2a((int) statement_number((statement) s));
325 }
326 
327 /* remove non aipo statements at the head of ls
328  @return updated list
329 */
331 {
332  list head = ls, prev = NIL;
333  while (ls && !freia_statement_aipo_call_p(STATEMENT(CAR(ls))))
334  prev = ls, ls = CDR(ls);
335  if (prev) CDR(prev) = NIL, gen_free_list(head);
336  return ls;
337 }
338 
339 /* remove unrelated stuff at head & tail, so that it does not come in later on
340  and possibly trouble the compilation.
341  @return updated list
342 */
344 {
346 }
347 
348 /* reorder a little bit statements, so that allocs & deallocs are up
349  * front or in the back, and may be removed by the previous function.
350  */
351 static void sort_subsequence(list ls, sequence sq)
352 {
353  ifdebug(8) {
354  pips_debug(8, "input: ");
355  gen_fprint(stderr, "ls", ls, (gen_string_func_t) stmt_nb);
356  }
357 
358  set cmp = set_make(set_pointer);
359  set_assign_list(cmp, ls);
360 
361  // sort ls
363 
364  // extract sub sequence in a separate list
365  list head = NIL, lcmp = NIL, tail = NIL;
367  {
368  if (set_belong_p(cmp, s))
369  lcmp = CONS(statement, s, lcmp);
370  else
371  if (!lcmp)
372  head = CONS(statement, s, head);
373  else
374  tail = CONS(statement, s, tail);
375  }
376 
377  // sort subsequence
379 
380  // rebuild sequence
382  sequence_statements(sq) =
383  gen_nconc(gen_nreverse(head), gen_nconc(lcmp, gen_nreverse(tail)));
384 
385  set_free(cmp);
386 
387  ifdebug(8) {
388  pips_debug(8, "output: ");
389  gen_fprint(stderr, "ls", ls, (gen_string_func_t) stmt_nb);
390  }
391 }
392 
393 /*********************************************************** LOOK AT EFFECTS */
394 
395 #include "effects-generic.h"
396 
397 /* tell whether a statement has no effects on images.
398  * if so, it may be included somehow in the pipeline
399  * and just skipped, provided stat scalar dependencies
400  * are taken care of.
401  */
403 {
404  int img_effect = false;
406  FOREACH(effect, e, cumu)
407  {
409  {
410  img_effect = true;
411  break;
412  }
413  }
414  return img_effect;
415 }
416 
417 /* update the set of written variables, as seen from effects, with a statement
418  * this is really to rebuild a poor's man dependency graph in order to move
419  * some statements around...
420  */
422 {
424  FOREACH(effect, e, cumu)
425  if (effect_write_p(e))
427  ifdebug(9)
428  set_fprint(stderr, "written", written,
430 }
431 
432 /* @return whether statement depends on some written variables
433  */
435 {
436  bool depends = false;
438  FOREACH(effect, e, cumu)
439  {
441  {
442  depends = true;
443  break;
444  }
445  }
446  return depends;
447 }
448 
449 /************************************ RECURSION HELPERS TO EXTRACT SEQUENCES */
450 
451 typedef struct {
452  // list of list of statements extracted from sequences
454  // list of statement (from seqs) -> its owner sequence if any
456  // count kept while recursing
458  // elements in the list encountered in potential inclosing loops,
459  // which impacts recomputed use-def dependencies that can be loop-carried.
461 } freia_info;
462 
463 static bool fsi_loop_flt( __attribute__((unused)) gen_chunk * o,
464  freia_info * fsip)
465 {
466  fsip->enclosing_loops++;
467  return true;
468 }
469 
470 static void fsi_loop_rwt( __attribute__((unused)) gen_chunk * o,
471  freia_info * fsip)
472 {
473  fsip->enclosing_loops--;
474 }
475 
476 /**
477  * @brief Transpose a structuring element expression
478  */
480  // get the structuring element array
483 
484  // reverse it...
485  list vals_rev = gen_nreverse(gen_full_copy_list(vals));
486 
487  // build the expression
488  return make_expression(make_syntax_call(make_call(fun, vals_rev)),
490 }
491 
492 /**
493  * @brief Detect a call to a se transposition function and
494  * transpose the arguments
495  *
496  * The expected function should have the following signature
497  * transpose_func(int kernelOut[9], const int kernelIn[9], ...)
498  */
500 
501  if (statement_call_p(s)) {
502  call c = statement_call(s);
503  if (c) {
504  entity called = call_function(c);
505 
506  // extract transposition calls
507  if (same_string_p(entity_local_name(called),
508  get_string_property("FREIA_TRANSPOSE_KERNEL_FUNC"))) {
509 
510  list args = call_arguments(c);
511  pips_assert("an expected transposition function should have at least "
512  "two arguments",
513  gen_length(args) >= 2);
514 
515  // get the argument entities
517  entity trse = expression_to_entity(EXPRESSION(CAR(args)));
518 
520  // get the expression value of the initial structuring element
522  // effectively transpose structuring element
523  expression trseval = freia_transpose_kernel(seval);
524 
525  // set the value of the transposed structuring element
526  set_entity_initial(trse, trseval);
527 
528  pips_debug(9, "%s: out %s, in %s\n", entity_local_name(called),
529  expression_to_string(trseval),
530  expression_to_string(seval));
531  }
532 
533  return true;
534  }
535  }
536  }
537  return false;
538 }
539 
540 /* detect one lone aipo statement out of a sequence...
541  */
542 static bool fsi_stmt_flt(statement s, freia_info * fsip)
543 {
546  {
548  if (i && instruction_sequence_p(i)) return false;
549  // not a sequence handled by fsi_seq_flt...
550  list ls = CONS(statement, s, NIL);
551  fsip->seqs = CONS(list, ls, fsip->seqs);
552  if (fsip->enclosing_loops)
553  set_add_element(fsip->in_loops, fsip->in_loops, ls);
554  }
555  return true;
556 }
557 
558 /** consider a sequence */
559 static bool fsi_seq_flt(sequence sq, freia_info * fsip)
560 {
561  pips_debug(9, "considering sequence...\n");
562 
563  list /* of statements */ ls = NIL, ltail = NIL, lup = NIL;
564 
565  // use a copy, because the sequence is rewritten inside the loop...
566  // see sort_subsequence. I guess should rather delay it...
568 
570 
571  FOREACH(statement, s, lseq)
572  {
573  bool freia_api = freia_statement_aipo_call_p(s);
574  // the statement is kept if
575  bool keep_stat =
576  // it is an AIPO call
577  freia_api ||
578  // it follows kept calls and
579  (ls && (
580  // it is an (image) allocation in the middle of the code
581  freia_alloc_stat_p(s) ||
582  // or it has no image effects
584 
585  // quick fix for performance: stop on timer calls
586  if (keep_stat && statement_call_p(s))
587  {
588  entity called = call_function(statement_call(s));
589  if (same_string_p(entity_local_name(called), "gettimeofday") ||
590  same_string_p(entity_local_name(called), "freia_common_wait"))
591  keep_stat = false;
592  }
593 
594  pips_debug(7, "statement %"_intFMT": %skept\n",
595  statement_number(s), keep_stat? "": "not ");
596 
597  // FREIA API & "intermediate" statements are kept
598  if (keep_stat)
599  {
600  if (freia_api)
601  {
602  ls = gen_nconc(ltail, ls), ltail = NIL;
603  ls = CONS(statement, s, ls);
605  }
606  else // else accumulate in the "other list" waiting for something...
607  {
608  if (statement_depends_p(written, s) ||
609  (statement_call_p(s) &&
611  // free are kept in the tail... not caught as a W effect?
613  {
614  pips_debug(8, "statement %d in ltail\n", (int) statement_number(s));
615  ltail = CONS(statement, s, ltail);
617  }
618  else
619  {
620  pips_debug(8, "statement %d in lup\n", (int) statement_number(s));
621  // we can move it up...
622  lup = CONS(statement, s, lup);
623  }
624  }
625  }
626  else // the sequence must be cut on this statement
627  {
628  if (lup && ls)
629  move_ahead(lup, STATEMENT(CAR(gen_last(ls))), sq);
630  if (lup) gen_free_list(lup), lup = NIL;
631  if (ls!=NIL)
632  {
633  sort_subsequence(ls, sq);
635  fsip->seqs = CONS(list, ls, fsip->seqs);
636  hash_put(fsip->sequence, ls, sq);
637  if (fsip->enclosing_loops)
638  set_add_element(fsip->in_loops, fsip->in_loops, ls);
639  ls = NIL;
640  }
641  if (ltail) gen_free_list(ltail), ltail = NIL;
643  }
644  }
645 
646  // end of sequence reached
647  if (ls!=NIL)
648  {
649  if (lup && ls)
650  move_ahead(lup, STATEMENT(CAR(gen_last(ls))), sq);
651  sort_subsequence(ls, sq);
653  fsip->seqs = CONS(list, ls, fsip->seqs);
654  hash_put(fsip->sequence, ls, sq);
655  if (fsip->enclosing_loops)
656  set_add_element(fsip->in_loops, fsip->in_loops, ls);
657  ls = NIL;
658  }
659 
660  // cleanup
661  if (ltail) gen_free_list(ltail), ltail = NIL;
662  if (lup) gen_free_list(lup), lup = NIL;
663  gen_free_list(lseq);
664  set_free(written);
665  return true;
666 }
667 
668 /****************************************** SORT LIST OF EXTRACTED SEQUENCES */
669 
671 {
672  _int min = -1;
673  FOREACH(statement, s, ls)
674  min = (min==-1)? statement_number(s):
676  return min;
677 }
678 
679 static hash_table fsi_number = NULL;
680 
681 static int fsi_cmp(const list * l1, const list * l2)
682 {
683  return (int) ((_int) hash_get(fsi_number, *l1) -
684  (_int) hash_get(fsi_number, *l2));
685 }
686 
687 static void fsi_sort(list lls)
688 {
689  pips_assert("static fsi_number is clean", !fsi_number);
691  FOREACH(list, ls, lls)
692  hash_put(fsi_number, ls, (void*) min_statement(ls));
695 }
696 
697 /********************************************************** SEQUENCE CLEANUP */
698 /*
699  some more cleanup added to the main sequence.
700  some existing passes could do a better job, but they would require
701  working helper effects and managing pointers. Moreover, I know that I can
702  ignore deallocations.
703 */
704 
706 {
707  entity var = reference_variable(r);
710 }
711 
713 {
714  //fprintf(stderr, "[freia_cleanup_main_sequence] %p\n", modstat);
715  bool changed = false;
716  instruction i = statement_instruction(modstat);
717 
718  if (instruction_sequence_p(i))
719  {
722  // set of referenced images
723 
724  FOREACH(statement, s, rstats)
725  {
726  // handle seqs in seqs with an explicit recursion
727  if (statement_sequence_p(s))
729  else if (freia_statement_aipo_call_p(s))
730  {
732  const freia_api_t * api =
734  if (api->arg_img_out==1)
735  {
737  //fprintf(stderr, "considering %s on %s\n",
738  // api->function_name, entity_local_name(img));
739  if (!set_belong_p(referenced, img) &&
740  // hey, we keep written parameters!
741  // ??? what about global images, if any?
742  !formal_parameter_p(img))
743  {
744  changed = true;
747  }
748  }
749  }
750  // update seen variables, but must skip deallocations!
751  // ??? what about skipping alloc as well?
752  if (!is_freia_dealloc(s))
754  // could also do loop indexes, but no images
756  // also look in initializations
760 
761  }
762 
763  gen_free_list(rstats);
764  }
765  return changed;
766 }
767 
769 {
771  bool changed = freia_cleanup_sequence_rec(modstat, referenced);
773  return changed;
774 }
775 
776 /**************************************************************** DO THE JOB */
777 
778 /* freia_compile:
779  * compile freia module & statement for target
780  * - do some cleanup on sequences
781  * - collect sequences of freia operations
782  * - create file for generated functions
783  * - call hardware-specific code generation for each sequence
784  */
785 string freia_compile(string module, statement mod_stat, string target)
786 {
787  pips_assert("we need some dependable effects for our purpose",
788  !get_bool_property("CONSTANT_PATH_EFFECTS"));
789 
790  if (!freia_valid_target_p(target))
791  pips_internal_error("unexpected target %s", target);
792 
793  // deal with some simple image shuff cases by forward substitution
795 
796  // check for remaining image shuffles...
797  set shuffled = set_make(set_pointer);
798  if (freia_image_shuffle(mod_stat, shuffled))
799  {
800  if (get_bool_property("FREIA_ALLOW_IMAGE_SHUFFLE"))
801  pips_user_warning("image shuffle found in %s, "
802  "freia compilation may result in wrong code!\n",
803  module);
804  else
805  pips_user_error("image shuffle found in %s, "
806  "see FREIA_ALLOW_IMAGE_SHUFFLE property to continue.\n",
807  module);
808  }
809 
810  // freia_aipo_cast -> freia_aipo_copy before further compilation
811  if (get_bool_property("FREIA_CAST_IS_COPY"))
813 
814  freia_info fsi =
817 
818  // collect freia api functions...
820  // collect sequences
823  // just count potential enclosing loops...
828  NULL);
829 
830  // check safe return
831  pips_assert("loop count back to zero", fsi.enclosing_loops==0);
832 
833  // sort sequences by increasing statement numbers
834  fsi_sort(fsi.seqs);
835 
836  // output file if any
837  string file = NULL;
838  set helpers = NULL;
839  FILE * helper = NULL;
840  if (freia_spoc_p(target) || freia_terapix_p(target) ||
841  freia_opencl_p(target) || freia_sigmac_p(target) || freia_mppa_p(target))
842  {
843  file = helper_file_name(module, "c");
844  if (file_readable_p(file))
845  pips_user_error("file '%s' already exists: "
846  "cannot reapply transformation\n", file);
847  helper = safe_fopen(file, "w");
848  pips_debug(1, "generating file '%s'\n", file);
849 
850  // we will also record created helpers
851  helpers = set_make(set_pointer);
852  }
853 
854  // headers
855  if (freia_spoc_p(target))
856  fprintf(helper, "%s", FREIA_SPOC_INCLUDES);
857  else if (freia_terapix_p(target))
858  fprintf(helper, "%s", FREIA_TRPX_INCLUDES);
859  else if (freia_opencl_p(target))
860  fprintf(helper, "%s", FREIA_OPENCL_INCLUDES);
861  else if (freia_sigmac_p(target))
862  fprintf(helper, "%s", FREIA_SIGMAC_INCLUDES);
863  else if (freia_mppa_p(target))
864  fprintf(helper, "%s", FREIA_MPPA_INCLUDES);
865 
866  // hmmm... should rely on use-defs
867  hash_table occs = freia_build_image_occurrences(mod_stat, NULL, NULL, NULL);
868  set output_images = freia_compute_current_output_images();
869  // hmmm... panic mode
870  set_union(output_images, output_images, shuffled);
871 
872  // first explicitely build and fix the list of dags,
873  // with some reverse order hocus-pocus for outputs computations...
874  list lsi = gen_nreverse(gen_copy_seq(fsi.seqs));
875  list ldags = NIL;
876  int n_dags = gen_length(fsi.seqs);
877  FOREACH(list, ls, lsi)
878  {
879  dag d = freia_build_dag(module, ls, --n_dags, occs, output_images, ldags,
880  set_belong_p(fsi.in_loops, ls));
881  ldags = CONS(dag, d, ldags);
882  }
883  gen_free_list(lsi), lsi = NIL;
884 
885  list lcurrent = ldags;
886  // signatures definition must be cross-dag because of
887  // dilate/erode helper reuse with OpenCL
888  hash_table signatures = hash_table_make(hash_pointer, 0);
889  n_dags = 0;
890  bool compile_lone = get_bool_property("FREIA_COMPILE_LONE_OPERATIONS");
891  FOREACH(list, ls, fsi.seqs)
892  {
893  // get corresponding dag, which should be destroyed by the called compiler
894  dag d = DAG(CAR(lcurrent));
895  lcurrent = CDR(lcurrent);
896 
897  // maybe skip lone operations
898  if (!compile_lone && gen_length(ls)==1)
899  {
900  n_dags++;
901  gen_free_list(ls);
902  continue;
903  }
904 
905  list allocated = NIL;
906  hash_table exchanges = NULL;
907  sequence sq = NULL;
908  if (hash_defined_p(fsi.sequence, ls))
909  {
910  exchanges = hash_table_make(hash_pointer, 0);
911  sq = hash_get(fsi.sequence, ls);
912  }
913 
914  if (freia_spoc_p(target))
915  allocated = freia_spoc_compile_calls(module, d, sq, ls, occs, exchanges,
916  output_images, helper, helpers, n_dags);
917  else if (freia_terapix_p(target))
918  allocated = freia_trpx_compile_calls(module, d, sq, ls, occs, exchanges,
919  output_images, helper, helpers, n_dags);
920  else if (freia_opencl_p(target))
921  allocated = freia_opencl_compile_calls(module, d, sq, ls, occs, exchanges,
922  output_images, helper, helpers, n_dags, signatures);
923  else if (freia_sigmac_p(target))
924  allocated = freia_sigmac_compile_calls(module, d, sq, ls, occs, exchanges,
925  output_images, helper, helpers, n_dags, gen_length(fsi.seqs));
926  else if (freia_mppa_p(target))
927  allocated =
928  freia_mppa_compile_calls(module, d, sq, ls, occs, exchanges,
929  output_images, helper, helpers, n_dags);
930  else if (freia_aipo_p(target))
931  allocated = freia_aipo_compile_calls(module, d, ls, occs, exchanges,
932  n_dags);
933 
934  if (exchanges)
935  {
937  HASH_FOREACH(dagvtx, v1, dagvtx, v2, exchanges)
939  }
940 
941  if (allocated)
942  {
943  FOREACH(entity, img, allocated)
945  gen_free_list(allocated);
946  }
947 
948  n_dags++;
949 
950  // cleanup list contents on the fly
951  gen_free_list(ls);
952  free_dag(d);
953  if (exchanges) hash_table_free(exchanges);
954  }
955 
956  // some code cleanup
958 
959  // some more code cleanup
960  if (get_bool_property("FREIA_CLEANUP_STATUS"))
961  // remove err = or err |= freia & helper functions
962  freia_cleanup_status(mod_stat, helpers);
963 
964  // cleanup
967  set_free(output_images), output_images = NULL;
968  set_free(shuffled), shuffled = NULL;
969  if (helpers) set_free(helpers), helpers = NULL;
970  gen_free_list(fsi.seqs);
971  set_free(fsi.in_loops);
973  hash_table_free(signatures);
974  gen_free_list(ldags);
975  if (helper) safe_fclose(helper, file);
976 
977  return file;
978 }
float a2sf[2] __attribute__((aligned(16)))
USER generates a user error (i.e., non fatal) by printing the given MSG according to the FMT.
Definition: 3dnow.h:3
void free_dag(dag p)
call make_call(entity a1, list a2)
Definition: ri.c:269
value make_value_expression(expression _field_)
Definition: ri.c:2850
syntax make_syntax_call(call _field_)
Definition: ri.c:2500
expression make_expression(syntax a1, normalized a2)
Definition: ri.c:886
void free_instruction(instruction p)
Definition: ri.c:1118
void free_call(call p)
Definition: ri.c:236
void free_value(value p)
Definition: ri.c:2787
static int count
Definition: SDG.c:519
static bool written
Definition: alias_check.c:512
void set_entity_initial(entity, expression)
Be careful if the initial value has already been set.
Definition: util.c:3469
dag freia_build_dag(string module, list ls, int number, const hash_table occurrences, const set output_images, const list ld, bool inloop)
build a full dag from list of statements ls.
Definition: dag-utils.c:2476
statement dagvtx_statement(const dagvtx v)
return statement if any, or NULL (for input nodes).
Definition: dag-utils.c:56
#define min(a, b)
effects load_cumulated_rw_effects(statement)
#define effect_write_p(eff)
#define effect_read_p(eff)
#define effect_scalar_p(eff) entity_scalar_p(effect_entity(eff))
#define effect_variable(e)
For COMPATIBILITY purpose only - DO NOT USE anymore.
#define effects_effects(x)
Definition: effects.h:710
FILE * safe_fopen(const char *filename, const char *what)
Definition: file.c:67
char * get_string_property(const char *)
int safe_fclose(FILE *stream, const char *filename)
Definition: file.c:77
bool file_readable_p(char *name)
Definition: file.c:428
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
bool entity_freia_api_p(const entity f)
returns whether the entity is a freia API (AIPO) function.
Definition: freia-utils.c:806
const freia_api_t * hwac_freia_api(const char *function)
freia-utils.c
Definition: freia-utils.c:455
bool is_freia_dealloc(const statement s)
Definition: freia-utils.c:1007
bool is_freia_alloc(const statement s)
Definition: freia-utils.c:1002
string helper_file_name(string func_name, string suffix)
return malloc'ed "foo.database/Src/%{module}_helper_functions.c" should it depend on the target?...
Definition: freia-utils.c:2029
bool freia_image_variable_p(const entity var)
rather approximative?
Definition: freia-utils.c:768
hash_table freia_build_image_occurrences(statement s, set image_occs_stats, hash_table image_stats, const hash_table signatures)
Definition: freia-utils.c:1388
void freia_close_dep_cache(void)
Definition: freia-utils.c:915
call freia_ok(void)
build all is well freia constant
Definition: freia-utils.c:695
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
void freia_init_dep_cache(void)
Definition: freia-utils.c:909
set freia_compute_current_output_images(void)
Definition: freia-utils.c:1885
bool freia_assignment_p(const entity e)
tell whether it is an assignment to ignore?
Definition: freia-utils.c:703
bool freia_statement_aipo_call_p(const statement s)
returns whether the statement is a FREIA call.
Definition: freia-utils.c:814
void freia_clean_image_occurrences(hash_table occs)
cleanup occurrence data structure
Definition: freia-utils.c:1407
bool freia_is_transpose_call(statement s)
Detect a call to a se transposition function and transpose the arguments.
Definition: freia.c:499
static bool freia_cleanup_sequence_rec(statement modstat, set referenced)
Definition: freia.c:712
static int freia_cmp_statement(const statement *s1, const statement *s2)
order two statements for qsort.
Definition: freia.c:279
static _int min_statement(list ls)
Definition: freia.c:670
static bool statement_depends_p(set written, statement s)
Definition: freia.c:434
static bool freia_alloc_call_p(const call c)
Definition: freia.c:209
static string stmt_nb(void *s)
debug helper
Definition: freia.c:322
expression freia_transpose_kernel(const expression se)
Transpose a structuring element expression.
Definition: freia.c:479
static void update_written_variables(set written, statement s)
update the set of written variables, as seen from effects, with a statement this is really to rebuild...
Definition: freia.c:421
static void sctc_call_rwt(call c, int *count)
Definition: freia.c:178
static bool freia_image_shuffle(statement s, set shuffled)
Definition: freia.c:169
static bool fsi_stmt_flt(statement s, freia_info *fsip)
detect one lone aipo statement out of a sequence...
Definition: freia.c:542
bool freia_some_effects_on_images(statement s)
tell whether a statement has no effects on images.
Definition: freia.c:402
static bool fsi_seq_flt(sequence sq, freia_info *fsip)
consider a sequence
Definition: freia.c:559
string freia_compile(string module, statement mod_stat, string target)
freia_compile: compile freia module & statement for target
Definition: freia.c:785
static bool fsi_loop_flt(__attribute__((unused)) gen_chunk *o, freia_info *fsip)
Definition: freia.c:463
static list clean_statement_list_for_aipo(list ls)
remove unrelated stuff at head & tail, so that it does not come in later on and possibly trouble the ...
Definition: freia.c:343
static void fsi_sort(list lls)
Definition: freia.c:687
static int fsi_cmp(const list *l1, const list *l2)
Definition: freia.c:681
static bool freia_alloc_stat_p(const statement s)
Definition: freia.c:217
static bool fis_call_flt(call c, fis_ctx *ctx)
Definition: freia.c:148
static hash_table fsi_number
Definition: freia.c:679
static void switch_cast_to_copy(statement s)
switch all image casts to image copies in "s"
Definition: freia.c:190
static bool freia_cleanup_main_sequence(statement modstat)
Definition: freia.c:768
static void sort_subsequence(list ls, sequence sq)
reorder a little bit statements, so that allocs & deallocs are up front or in the back,...
Definition: freia.c:351
static bool fcs_call_flt(call c, fcs_ctx *ctx)
Definition: freia.c:60
static void freia_cleanup_status(statement s, set helpers)
Definition: freia.c:120
static bool freia_stmt_free_p(const statement s)
Definition: freia.c:202
static void move_ahead(list ls, statement target, sequence sq)
move statements in l ahead of s in sq note that ls is in reverse order...
Definition: freia.c:247
static list clean_list_head(list ls)
remove non aipo statements at the head of ls
Definition: freia.c:330
static void collect_images(reference r, set referenced)
Definition: freia.c:705
static void fsi_loop_rwt(__attribute__((unused)) gen_chunk *o, freia_info *fsip)
Definition: freia.c:470
#define freia_opencl_p(s)
Definition: freia.h:61
#define freia_sigmac_p(s)
Definition: freia.h:62
#define AIPO
Definition: freia.h:51
#define FREIA_FREE
Definition: freia.h:49
#define freia_mppa_p(s)
Definition: freia.h:63
#define FREIA_ALLOC
Definition: freia.h:48
#define freia_aipo_p(s)
Definition: freia.h:58
#define freia_spoc_p(s)
Definition: freia.h:59
#define freia_terapix_p(s)
Definition: freia.h:60
#define freia_valid_target_p(s)
Definition: freia.h:65
list freia_aipo_compile_calls(string module, dag fulld, list ls, const hash_table occs, hash_table exchanges, int number)
freia_aipo.c
Definition: freia_aipo.c:49
list freia_mppa_compile_calls(string module, dag fulld, sequence sq, list ls, const hash_table occs, hash_table exchanges, const set output_images, FILE *helper_file, __attribute__((__unused__)) set helpers, int number)
Compile one dag with AIPO optimizations.
Definition: freia_mppa.c:711
#define FREIA_MPPA_INCLUDES
Definition: freia_mppa.h:26
list freia_opencl_compile_calls(string module, dag fulld, sequence sq, list ls, const hash_table occs, hash_table exchanges, const set output_images, FILE *helper_file, set helpers, int number, hash_table signatures)
freia_opencl.c
#define FREIA_OPENCL_INCLUDES
Definition: freia_opencl.h:40
static int n_dags
Definition: freia_sigmac.c:56
#define FREIA_SIGMAC_INCLUDES
Definition: freia_sigmac.h:41
list freia_spoc_compile_calls(string module, dag fulld, sequence sq, list ls, const hash_table occs, hash_table exchanges, const set output_images, FILE *helper_file, set helpers, int number)
generate helpers for statements in ls of module output resulting functions in helper,...
Definition: freia_spoc.c:2247
#define FREIA_SPOC_INCLUDES
Definition: freia_spoc.h:188
#define DAG(x)
newgen_vtxcontent_domain_defined
list freia_trpx_compile_calls(string module, dag fulld, sequence sq, list ls, const hash_table occs, hash_table exchanges, const set output_images, FILE *helper_file, set helpers, int number)
do compile a list of statements for terapix
#define FREIA_TRPX_INCLUDES
Definition: freia_terapix.h:54
void freia_shuffle_move_forward(statement s)
#define gen_context_recurse(start, ctxt, domain_number, flt, rwt)
Definition: genC.h:285
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_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
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
void gen_fprint(FILE *out, string name, const list l, gen_string_func_t item_name)
Definition: list.c:873
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
void gen_exchange_in_list(list l, const void *i1, const void *i2)
exchange items i1 & i2 in the list
Definition: list.c:651
#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
void gen_sort_list(list l, gen_cmp_func_t compare)
Sorts a list of gen_chunks in place, to avoid allocations...
Definition: list.c:796
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
statement add_declaration_statement(statement, entity)
Definition: statement.c:2790
static Value eval(Pvecteur pv, Value val, Variable var)
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_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
list freia_sigmac_compile_calls(string, dag, sequence, list, const hash_table, hash_table, const set, FILE *, set, int, int)
freia_sigmac.c
static statement mod_stat
We want to keep track of the current statement inside the recurse.
Definition: impact_check.c:41
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_user_warning
Definition: misc-local.h:146
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
#define pips_user_error
Definition: misc-local.h:147
char * i2a(int)
I2A (Integer TO Ascii) yields a string for a given Integer.
Definition: string.c:121
@ 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)
set set_assign_list(set, const list)
assigns a list contents to a set all duplicated elements are lost
Definition: set.c:474
int set_size(const set)
returns the number of items in s.
Definition: set.c:359
#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
set set_clear(set)
Assign the empty set to s s := {}.
Definition: set.c:326
bool set_belong_p(const set, const void *)
Definition: set.c:194
set set_union(set, const set, const set)
Definition: set.c:211
void set_fprint(FILE *, string, const set, gen_string_func_t)
print set s to file stream out.
Definition: set.c:524
@ set_pointer
Definition: newgen_set.h:44
set set_append_list(set, const list)
add list l items to set s, which is returned.
Definition: set.c:460
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
string(* gen_string_func_t)(const void *)
Definition: newgen_types.h:111
#define _intFMT
Definition: newgen_types.h:57
intptr_t _int
_INT
Definition: newgen_types.h:53
int(* gen_cmp_func_t)(const void *, const void *)
Definition: newgen_types.h:114
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
string expression_to_string(expression e)
Definition: expression.c:77
static list referenced
returns the list of referenced variables
Definition: utils.c:60
#define ENTITY_ASSIGN_P(e)
#define ENTITY_CONTINUE_P(e)
#define ENTITY_BITWISE_OR_UPDATE_P(e)
#define CONTINUE_FUNCTION_NAME
#define ENTITY_C_RETURN_P(e)
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
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 local_name_to_top_level_entity(const char *n)
This function try to find a top-level entity from a local name.
Definition: entity.c:1450
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
bool expression_integer_value(expression e, intptr_t *pval)
Definition: eval.c:792
bool expression_call_p(expression e)
Definition: expression.c:415
call expression_call(expression e)
Definition: expression.c:445
entity expression_to_entity(expression e)
just returns the entity of an expression, or entity_undefined
Definition: expression.c:3140
expression call_to_expression(call c)
Build an expression that call a function or procedure.
Definition: expression.c:309
bool formal_parameter_p(entity)
Definition: variable.c:1489
#define forloop_domain
newgen_extensions_domain_defined
Definition: ri.h:178
#define syntax_reference_p(x)
Definition: ri.h:2728
#define instruction_sequence_p(x)
Definition: ri.h:1512
#define unstructured_domain
newgen_type_domain_defined
Definition: ri.h:442
#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 syntax_call_p(x)
Definition: ri.h:2734
#define value_unknown_p(x)
Definition: ri.h:3077
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define instruction_domain
newgen_functional_domain_defined
Definition: ri.h:202
#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_undefined
Definition: ri.h:2761
#define entity_name(x)
Definition: ri.h:2790
#define expression_normalized(x)
Definition: ri.h:1249
#define sequence_statements(x)
Definition: ri.h:2360
#define reference_indices(x)
Definition: ri.h:2328
struct _newgen_struct_instruction_ * instruction
Definition: ri.h:207
#define instruction_sequence(x)
Definition: ri.h:1514
#define syntax_call(x)
Definition: ri.h:2736
#define whileloop_domain
newgen_variable_domain_defined
Definition: ri.h:466
#define statement_declarations(x)
Definition: ri.h:2460
#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 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(x)
STATEMENT.
Definition: ri.h:2413
#define entity_initial(x)
Definition: ri.h:2796
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
s1
Definition: set.c:247
#define ifdebug(n)
Definition: sg.c:47
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
set used_for_status
Definition: freia.c:55
set helper_functions
Definition: freia.c:57
Definition: freia.c:144
set shuffled
Definition: freia.c:145
FREIA API function name -> SPoC hardware description (and others?)
Definition: freia.h:71
unsigned int arg_img_out
Definition: freia.h:79
list seqs
Definition: freia.c:453
hash_table sequence
Definition: freia.c:455
int enclosing_loops
Definition: freia.c:457
set in_loops
Definition: freia.c:460
A gen_chunk is used to store every object.
Definition: genC.h:58