PIPS
code.c
Go to the documentation of this file.
1 /*
2 
3  $Id: code.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  /* Code Generation for Distributed Memory Machines
28  *
29  * Code generating routine for a given partitioning and a given loop nest
30  *
31  * File: code.c
32  *
33  * PUMA, ESPRIT contract 2701
34  *
35  * Francois Irigoin, Corinne Ancourt, Lei Zhou
36  * 1991
37  */
38 
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 
44 #include "linear.h"
45 
46 #include "genC.h"
47 #include "misc.h"
48 #include "ri.h"
49 #include "effects.h"
50 
51 #include "matrice.h"
52 #include "tiling.h"
53 
54 #include "dg.h"
57 #include "graph.h"
58 #include "ri-util.h"
59 #include "prettyprint.h"
60 #include "effects-util.h"
61 #include "text-util.h"
62 /* #include "generation.h" */
63 #include "movements.h"
64 
65 #include "wp65.h"
66 
69 
71 static bool ref_in_statement1;
74 
76 {
80 
81 }
82 
84 {
86  ref_in_statement1 = false;
87  gen_recurse(l,
89  gen_true,
90  ref_found_p);
91  return(ref_in_statement1);
92 }
93 
94 
95 static void eval_var(reference ref)
96 {
97  cons * ind1;
100  cons *expr=NIL;
101  Value coeff = VALUE_ZERO;
102  bool debut=true;
103  ind1 = reference_indices(ref);
104 
105  if (ind1) {
106  for (debut =true; ind1 != NULL; ind1 = CDR(ind1))
107  { normalized norm1;
108  expr1 = EXPRESSION(CAR(ind1));
109  norm1 = (normalized) NORMALIZE_EXPRESSION(expr1);
110  if (normalized_linear_p(norm1)) {
111  Pvecteur pv1 = (Pvecteur) normalized_linear(norm1);
112  fprintf(stderr,"\n expression->vecteur:");
113  vect_fprint(stderr,pv1,(string(*)(Variable))entity_local_name);
114  if (value_notzero_p(coeff = vect_coeff(var_to_evaluate,pv1)))
115  {
117  vect_add_elem(&pv1,TCST,
118  value_mult(var_minmax,coeff));
119  fprintf(stderr,"\n nouvelle expression:");
120  vect_fprint(stderr,pv1,(string(*)(Variable))entity_local_name);
121  expr2 = make_vecteur_expression(pv1);
122  }
123  else expr2 = expr1;
124  print_words(stderr,Words_Expression(expr2));
125  }
126 
127  if (debut) {
128  expr = CONS(EXPRESSION,expr2,NIL);
129  print_words(stderr,Words_Expression(expr2));
130  debut = false;
131  }
132  else expr = gen_nconc(expr,CONS(EXPRESSION,expr2,NIL));
133 
134  }
135  reference_indices(ref) = expr;
136  }
137 
138 }
139 
140 
142 {
143  var_to_evaluate = v;
144  var_minmax = min;
145  ifdebug(8) {
146  (void) fprintf(stderr, "Loop body :\n");
148  }
149  gen_recurse(s,
151  gen_true,
152  eval_var);
153  ifdebug(8) {
154  (void) fprintf(stderr, "New loop body :\n");
156  }
157 
158 }
159 
160 
161 void tile_change_of_basis(Psysteme tile_domain,Pbase initial_basis,Pbase tile_basis,
162 Pbase tile_init_basis,tiling tile)
163 {
164  int dim = base_dimension(initial_basis);
165  int l,c;
166  for(l=1; l <= dim; l++) {
167  Pcontrainte eq;
168  Pvecteur v = VECTEUR_NUL;
169  int td = base_dimension(tile_basis);
170  for(c=1; c<=td; c++)
171  vect_add_elem(&v, variable_of_rank(tile_basis, c),
172  (Value) ACCESS((matrice) tiling_tile(tile), dim, l, c));
173 
174  vect_add_elem(&v, variable_of_rank(tile_init_basis, l), VALUE_MONE);
175  vect_add_elem(&v, TCST,
176  vect_coeff(variable_of_rank(initial_basis, l),
177  (Pvecteur) tiling_origin(tile)));
178  eq = contrainte_make(v);
179  sc_add_egalite(tile_domain, eq);
180  }
181 }
182 
183 
184 
185 
186 ␌
187 /* make_scanning_over_tiles()
188  *
189  * generates a nest of loops to enumerate all tiles containing at
190  * least one iteration in iteration_domain, and even sometimes
191  * zero because a rational projection is used; empty tiles
192  * are taken care of at a lower level to make sure that no iterations
193  * are performed.
194  *
195  * The following system is built:
196  *
197  * -> ->
198  * B i <= b
199  *
200  * -> --> ->
201  * t1 = P t0 + o
202  *
203  * -> -1 -> --> ---->
204  * 0 <= k P ( i - t1 ) <= (k-1)
205  *
206  * where (B,b) defines the iteration domain, t1 is the tile origin in the
207  * initial basis, t0 is the tile origin in the tile basis, P is the
208  * partitioning matrix, o is the partitioning origin, i is an iteration,
209  * and k is the denominator of the inverse of P.
210  *
211  * i and t1 are eliminated to obtain constraints on t0 only. These constraints
212  * are used to derive the loop bounds.
213  *
214  * This piece of code could also be used to generate tiled code for
215  * a shared memory machine without any change.
216  *
217  * Notes:
218  * - the outermost loop is assumed parallel;
219  * - the outermost loop is statically distributed over the processors
220  * if proc_id is defined as a formal parameter (compute code)
221  * - proc_id has to be derived from the outermost loop index for the
222  * memory code, when it is a local variable
223  *
224  * Algorithm described in PPoPP'91
225  */
226 statement
228  entity module,
229  list body,
230  entity proc_id,
231  int pn,
232  tiling tile,
233  Pbase initial_basis,
234  Pbase tile_basis_in_tile_basis,
235  Pbase tile_basis_in_initial_basis,
236  Psysteme iteration_domain,
237  int first_parallel_level,
238  int last_parallel_level)
239 {
240  pips_assert("true", last_parallel_level==last_parallel_level);
242  entity ind;
243  Psysteme tile_domain = sc_dup(iteration_domain);
244  Psysteme ordered_tile_domain = SC_UNDEFINED;
245  Psysteme sctmp;
246  int id = base_dimension(initial_basis);
247  int td = base_dimension(tile_basis_in_tile_basis);
248  int l,t;
249  int keep_indice[11];
250  Value min,max;
251  int first_indice;
252  debug(8,"make_scanning_over_tiles", "begin for module %s\n",
254 
255  /* only fully-dimensional partitioning for the time being */
256  pips_assert("make_scanning_over_tiles",id==td);
257 
258  /* add change of basis equations to iteration domain:
259  tile_basis_in_tile_basis to tile_basis_in_initial_basis;
260  they would be of no use for a shared memory machine */
261 
262  tile_change_of_basis(tile_domain,initial_basis,
263  tile_basis_in_tile_basis,
264  tile_basis_in_initial_basis,tile);
265 
266  /* add the tile membership inequalities */
267  tile_domain = sc_append(tile_domain,
269  tile_basis_in_initial_basis,
270  initial_basis));
271 
272  /* update the basis for system tile_domain */
273  base_rm(sc_base(tile_domain));
274  sc_base(tile_domain) = BASE_NULLE;
275  sc_creer_base(tile_domain);
276 
277  tile_domain=sc_normalize(tile_domain);
278 
279  ifdebug(8) {
280  (void) fprintf(stderr, "Tile basis -> initial basis:\n");
281  sc_fprint(stderr, tile_domain,(string(*)(Variable)) entity_local_name);
282  }
283 
284  /* get rid of initial indices; they would be preserved to generate
285  shared memory code */
286  for(l=1; l <= id; l++) {
287  entity ind = (entity) variable_of_rank(initial_basis, l);
288  tile_domain = sc_projection_pure(tile_domain, (Variable) ind);
289  }
290 
291  /* get rid of tile_basis_in_initial_basis; we might as well (?) keep
292  them and get rid of tile_basis_in_tile_basis */
293  for(l=1; l <= td; l++) {
294  entity ind = (entity) variable_of_rank(tile_basis_in_initial_basis, l);
295  tile_domain = sc_projection_pure(tile_domain, (Variable) ind);
296  }
297 
298  ifdebug(8) {
299  (void) fprintf(stderr, "Constraints on tile indices:\n");
300  sc_fprint(stderr, tile_domain, (string(*)(Variable))entity_local_name);
301  }
302 
303  /* apply a row echelon transformation */
304  ordered_tile_domain =
305  new_loop_bound(tile_domain, tile_basis_in_tile_basis);
306  sc_transform_eg_in_ineg(ordered_tile_domain);
307 
308  ifdebug(8) {
309  (void) fprintf(stderr, "Ordered constraints on tile indices:\n");
310  sc_fprint(stderr, ordered_tile_domain, (string(*)(Variable))entity_local_name);
311  }
312 
313 
314 
315  /* transform these constraints into a loop nest with the right body,
316  starting with the innermost loop */
317  s = make_block_statement(body);
318 
319  pips_debug(9, "body statement:");
321 
322  for(t = td; t >= 1; t--) {
323  keep_indice[t]=true;
324  sctmp = sc_dup(ordered_tile_domain);
325  sc_minmax_of_variable(sctmp,
326  variable_of_rank(tile_basis_in_tile_basis, t),
327  &min,
328  &max);
329  ind = (entity) variable_of_rank(tile_basis_in_tile_basis, t);
330  if ( value_eq(min,max) && !reference_in_statement_p(s,ind)) {
331  fprintf(stderr,"indice de tuile inutile %d, %s\n",t,
332  entity_local_name(ind));
333  keep_indice[t] = false;
334  }
335  }
336 
337  for (t=1;t<=td && keep_indice[t]== false;t++);
338  first_indice = (t==td+1) ? td:t;
339  ifdebug(7)
340  fprintf(stderr,"first tile index %d, %s\n",first_indice,
342  ((entity) variable_of_rank(tile_basis_in_tile_basis, t)));
343 
344  for(t = td; t >= 1; t--)
345  {
346  expression lower;
347  expression upper;
348  range r;
349  loop new_l;
350  entity new_label;
353 
354  ind = (entity) variable_of_rank(tile_basis_in_tile_basis, t);
355 
356  /* optimization : Loop indices that are constant and
357  don't appear in the program body are not generated */
358 
359  if (keep_indice[t]){
360 
362  tile_basis_in_tile_basis,
363  ordered_tile_domain,
364  &lower, &upper);
365 
366  /* distribute work statically on processors using the outermost
367  loop (assumed parallel!) if proc_id is properly defined;
368  this should not be the case for bank tiles */
369  if(t !=first_parallel_level ||
370  !storage_formal_p(entity_storage(proc_id)))
371  r = make_range(lower, upper, int_to_expression(1));
372  else {
373  normalized n = NORMALIZE_EXPRESSION(lower);
374  if(normalized_linear_p(n)
376  lower = entity_to_expression(proc_id);
377  else
378  lower = MakeBinaryCall
380  lower,
381  entity_to_expression(proc_id));
382  r = make_range(lower, upper, int_to_expression(pn));
383  }
384 
385  /* I may need a definition for PROC_ID = MOD(I_0, PROCESSOR_NUMBER) */
386  if(t==first_parallel_level &&
387  !storage_formal_p(entity_storage(proc_id))) {
389  (entity_to_expression(proc_id),
393  int_to_expression(pn)));
394  }
395  else ps = statement_undefined;
396 
397  /* I need new labels and new continues for my loops!
398  make_loop_label() needs (at least) a module name */
399  new_label = make_loop_label(9000, module);
400  cs = make_continue_statement(new_label);
401 
404  CONS(STATEMENT, cs, NIL));
405  else
407  CONS(STATEMENT, cs,
408  NIL)));
409 
410  /* Now, s is certainly a block; prefix it with proc_id def */
411  if(ps != statement_undefined)
413  CONS(STATEMENT, ps,
415 
416  new_l = make_loop(ind, r, s,
417  new_label,
419  NIL);
420  s = loop_to_statement(new_l);
421  }
422  }
423 
424  statement_comments(s) =
425  strdup(concatenate("\nC To scan the tile set for ",
426  module_local_name(module), "\n", NULL));
427 
428  ifdebug(8) {
429  (void) fprintf(stderr, "Loop nest over tiles:\n");
431  }
432 
433  pips_debug(8,"end\n");
434 
435  return s;
436 }
437 
438 /* make_scanning_over_one_tile():
439  *
440  * generates a nest of loops to enumerate all iterations contained in
441  * one tile; the loop bounds are such that empty tiles execute no
442  * iteration at all;
443  *
444  * The following system is built:
445  *
446  * -> ->
447  * B i <= b
448  *
449  * -> --> ->
450  * t1 = P t0 + o
451  *
452  * -> --> ->
453  * i = t1 + l
454  *
455  * -> -1 -> --> ---->
456  * 0 <= k P ( i - t1 ) <= (k-1)
457  *
458  * where (B,b) defines the iteration domain, t1 is the tile origin in the
459  * initial basis, t0 is the tile origin in the tile basis, P is the
460  * partitioning matrix, o is the partitioning origin, i is an iteration,
461  * and k is the denominator of the inverse of P. l is an iteration in
462  * the local (to the current tile) basis.
463  *
464  * Because the loops over the tiles are built with t1 and because we need
465  * to access the copy with local coordinates, i and t0 are eliminated.
466  *
467  * A few changes would make this function generate loops for a shared
468  * memory machine. The local_basis would be useless and the initial
469  * basis should be chosen as indices for the loops so as not to have
470  * to update the loop body. So l would not be introduced and i would
471  * not be projected.
472  *
473  * Algorithm described in PPoPP'91.
474  */
476  tile, initial_basis, local_basis,
477  tile_basis_in_tile_basis,
478  tile_basis_in_initial_basis,
479  iteration_domain,
480  first_parallel_level,
481  last_parallel_level)
482 entity module;
483 statement body;
484 tiling tile;
485 Pbase initial_basis;
486 Pbase local_basis;
487 Pbase tile_basis_in_tile_basis;
488 Pbase tile_basis_in_initial_basis;
489 Psysteme iteration_domain;
490 int first_parallel_level,last_parallel_level;
491 {
492  pips_assert("true", first_parallel_level==first_parallel_level);
493  Psysteme tile_domain = sc_dup(iteration_domain);
494  Psysteme ordered_tile_domain = SC_UNDEFINED;
495  Psysteme origin_domain = SC_UNDEFINED;
496  int id = base_dimension(initial_basis);
497  int td = base_dimension(tile_basis_in_tile_basis);
498  int l,t,i;
500  Pvecteur pv;
501 
502  debug(8,"make_scanning_over_one_tile", "begin for module %s\n",
504 
505  /* only fully-dimensional partitioning for the time being */
506  pips_assert("make_scanning_over_one_tile",id==td);
507 
508  /* add change of basis equations to iteration domain:
509  tile_basis_in_tile_basis to tile_basis_in_initial_basis */
510 
511 
512  tile_change_of_basis(tile_domain,initial_basis,
513  tile_basis_in_tile_basis,
514  tile_basis_in_initial_basis,tile);
515 
516  /* add translation equations from initial basis to local basis
517  using tile_basis_in_initial_basis: i == t1 + l */
518 
519  for(l=1; l <= id; l++) {
520  Pcontrainte eq;
521  Pvecteur v = VECTEUR_NUL;
522  vect_add_elem(&v, variable_of_rank(initial_basis, l), VALUE_ONE);
523  vect_add_elem(&v, variable_of_rank(tile_basis_in_initial_basis, l),
524  VALUE_MONE);
525  vect_add_elem(&v, variable_of_rank(local_basis, l), VALUE_MONE);
526  eq = contrainte_make(v);
527  sc_add_egalite(tile_domain, eq);
528  }
529 
530 
531  /* add the tile membership inequalities */
532  tile_domain = sc_append(tile_domain,
534  tile_basis_in_initial_basis,
535  initial_basis));
536 
537  /* update the basis for system tile_domain */
538  base_rm(sc_base(tile_domain));
539  sc_base(tile_domain) = BASE_NULLE;
540  sc_creer_base(tile_domain);
541 
542  ifdebug(8) {
543  (void) fprintf(stderr, "Full system before projections:\n");
544  sc_fprint(stderr, tile_domain,(string(*)(Variable)) entity_local_name);
545  }
546 
547  /* get rid of tile_basis_in_initial_basis; we might as well (?) keep
548  them and get rid of tile_basis_in_tile_basis */
549  for(l=1; l <= td; l++) {
550  entity ind = (entity) variable_of_rank(tile_basis_in_initial_basis, l);
551  tile_domain = sc_projection_pure(tile_domain, (Variable) ind);
552  }
553 
554  ifdebug(8) {
555  (void) fprintf(stderr,
556  "Constraints on local tile indices parametrized by tile origin and initial indices:\n");
557  sc_fprint(stderr, tile_domain,(string(*)(Variable)) entity_local_name);
558  }
559 
560  /* get rid of initial indices */
561  for(l=1; l <= id; l++) {
562  entity ind = (entity) variable_of_rank(initial_basis, l);
563  tile_domain = sc_projection_pure(tile_domain, (Variable) ind);
564  }
565 
566  ifdebug(8) {
567  (void) fprintf(stderr,
568  "Constraints on local tile indices parametrized by tile origin:\n");
569  sc_fprint(stderr, tile_domain, (string(*)(Variable))entity_local_name);
570  }
571 
572  /* TEMPTATIVE */
573 
574  /* compute general information on loop bound origins
575  this is done to take into account information carried by the
576  outer loops, scanning the tile set */
577  origin_domain = sc_dup(tile_domain);
578 
579  /* get rid of local indices */
580  for(l=1; l <= id; l++) {
581  entity ind = (entity) variable_of_rank(local_basis, l);
582  origin_domain = sc_projection_pure(origin_domain, (Variable) ind);
583  }
584 
585  ifdebug(8) {
586  (void) fprintf(stderr,
587  "Absolute constraints on tile origins:\n");
588  sc_fprint(stderr, origin_domain,(string(*)(Variable)) entity_local_name);
589  }
590 
591  /* inject this redundant information */
592  tile_domain = sc_append(origin_domain, tile_domain);
593 
594  ifdebug(8) {
595  (void) fprintf(stderr,
596  "Constraints on local tile indices parametrized by tile origin, with redundant information:\n");
597  sc_fprint(stderr, tile_domain,(string(*)(Variable)) entity_local_name);
598  }
599 
600  pv =tile_basis_in_tile_basis;
601  for (i=1; i<= last_parallel_level && !VECTEUR_NUL_P(pv); i++, pv = pv->succ);
602 
603  for ( ; !VECTEUR_NUL_P(pv); pv = pv->succ) {
604  sc_force_variable_to_zero(tile_domain,vecteur_var(pv));
605  }
606 
607 
608  /* END OF TEMPTATIVE SECTION */
609 
610  /* apply a row echelon transformation */
611  ordered_tile_domain = new_loop_bound(tile_domain, local_basis);
612  sc_transform_eg_in_ineg(ordered_tile_domain);
613 
614  ifdebug(8) {
615  (void) fprintf(stderr, "Ordered constraints on local indices:\n");
616  sc_fprint(stderr, ordered_tile_domain,(string(*)(Variable)) entity_local_name);
617  }
618 
619  /* transform these constraints into a loop nest with the right body,
620  starting with the innermost loop */
621 
622  s = body;
623 
624  /* test pour optimiser le nid de boucles genere */
625  for (t =id; t >= 1; t--) {
626  Value min,max;
627  Variable var = variable_of_rank(local_basis, t);
628 
629  Psysteme sctmp = sc_dup(ordered_tile_domain);
630  sc_minmax_of_variable(sctmp,var,&min,&max);
631  }
632 
633 
634  for(t = id; t >= 1; t--) {
635  expression lower;
636  expression upper;
637  range r;
638  loop new_l;
639  entity ind;
640  entity new_label;
641  statement cs;
642 
643  ind = (entity) variable_of_rank(local_basis, t);
645  local_basis,
646  ordered_tile_domain,
647  &lower, &upper);
648  r = make_range(lower, upper, int_to_expression(1));
649  /* I need new labels and new continues for my loops!
650  make_loop_label() needs (at least) a module name */
651  new_label = make_loop_label(9000, module);
652  cs = make_continue_statement(new_label);
655  CONS(STATEMENT, cs, NIL));
656  else
658  CONS(STATEMENT, cs, NIL)));
659 
660  new_l = make_loop(ind, r, s,
661  new_label,
663  s = loop_to_statement( new_l);
664  }
665  statement_comments(s) =
666  strdup("C To scan each iteration of the current tile\n");
667  ifdebug(8) {
668  (void) fprintf(stderr, "Loop nest over tiles:\n");
670  }
671 
672  debug(8,"make_scanning_over_one_tile", "end\n");
673 
674  return s;
675 }
676 ␌
677 
678 
679 list make_compute_block(module, body, offsets, r_to_llv,
680  tile, initial_basis, local_basis,
681  tile_basis_in_tile_basis,
682  tile_basis_in_initial_basis,
683  iteration_domain,first_parallel_level,last_parallel_level)
684 entity module;
685 statement body; /* IN,
686  but modified by side effect to avoid copying statements */
687 Pvecteur offsets;
688 hash_table r_to_llv;
689 tiling tile;
690 Pbase initial_basis;
691 Pbase local_basis;
692 Pbase tile_basis_in_tile_basis;
693 Pbase tile_basis_in_initial_basis;
694 Psysteme iteration_domain;
695 int first_parallel_level,last_parallel_level;
696 {
697  statement s;
698 
699  list lt = NIL;
700  lt = reference_conversion_statement(module,body, &lt, r_to_llv, offsets, initial_basis,
701  tile_basis_in_tile_basis,local_basis,tile);
704  tile, initial_basis, local_basis,
705  tile_basis_in_tile_basis,
706  tile_basis_in_initial_basis,
707  iteration_domain,first_parallel_level,last_parallel_level);
708 
709  return CONS(STATEMENT, s, NIL);
710 }
711 
712 /* void reference_conversion_statement(body, r_to_llv, offsets, initial_basis,
713  * local_basis):
714  *
715  * All references in body which appear in r_to_llv
716  * are replaced by references to one of the local variables
717  * associated via the r_to_llv hash_table; the choice of one specific
718  * local variable is a function of offsets, which is used to generate
719  * pipelined code (not implemented).
720  *
721  * Statement numbers are set to STATEMENT_NUMBER_UNDEFINED.
722  */
723 list reference_conversion_statement(module,body, lt,r_to_llv, offsets, initial_basis,
724  tile_indices,local_basis,tile)
725 
726 entity module;
727 statement body;
728 list *lt;
729 hash_table r_to_llv;
730 Pvecteur offsets;
731 Pbase initial_basis,tile_indices,local_basis;
732 tiling tile;
733 {
735 
736  pips_debug(8, "begin statement: \n");
737  ifdebug(8) {
739  }
740 
742 
743  switch(instruction_tag(i)) {
745  MAPL(cs, {
747  r_to_llv, offsets,
748  initial_basis,tile_indices, local_basis,tile);
749  },
750  instruction_block(i));
751  return(*lt);
752  break;
753  case is_instruction_test:
754  pips_internal_error("Reference conversion not implemented for tests");
755  break;
756  case is_instruction_loop:
757 
758 
761  lt, r_to_llv, offsets,
762  initial_basis,
763  tile_indices,local_basis,tile);
764  return(*lt);
765  break;
766  case is_instruction_goto:
767  pips_internal_error("Unexpected goto (in restructured code)");
768  break;
769  case is_instruction_call:
770  /* the function is assumed to be unchanged */
772  {
774  initial_basis,
775  tile_indices,
776  local_basis, tile);
778  r_to_llv, offsets,
779  initial_basis, local_basis);
780  },
782  return(*lt);
783  break;
785  pips_internal_error("Reference conversion not implemented for unstructureds");
786  break;
787  default:
788  break;
789  }
790 
791  debug(8,"reference_conversion_statement", "return statement: \n");
792  ifdebug(8) {
794  }
795  return(*lt);
796 }
797 
798 
800  entity compute_module,
801  list *lt,
802  expression expr,
803  Pbase initial_basis,
804  Pbase tile_indices,
805  Pbase tile_local_indices,
806  tiling tile)
807 {
808  syntax s = expression_syntax(expr);
809 
810  switch(syntax_tag(s)) {
811  case is_syntax_reference: {
813  entity rv = reference_variable(r);
814  int i;
815 
816  if((i=rank_of_variable(initial_basis, (Variable) rv)) > 0) {
817 
818  entity ent1 = make_new_module_variable(compute_module,200);
819  Pvecteur pv2 = vect_new((Variable) ent1, VALUE_ONE);
820  Pvecteur pvt = VECTEUR_NUL;
821  expression exp1,exp2;
823  Pvecteur pv = make_loop_indice_equation(initial_basis,tile, pvt,
824  tile_indices,
825  tile_local_indices,i);
826  AddEntityToDeclarations(ent1,compute_module);
827  reference_variable(r) = ent1 ;
828  exp1= make_vecteur_expression(pv);
829  exp2 = make_vecteur_expression(pv2);
830  stat = make_assign_statement(exp2,exp1);
831  *lt = gen_nconc(*lt,CONS(STATEMENT,stat,NIL));
832  }
833  return (*lt);
834  break;
835  }
836  case is_syntax_call:
837  /* the called function is assumed to be unchanged */
838  MAPL(ce, {
839  *lt = reference_conversion_computation(compute_module,lt,
840  EXPRESSION(CAR(ce)),initial_basis,
841  tile_indices, tile_local_indices,tile);
842  },
844  return (*lt);
845  break;
846  default:
847  pips_internal_error("Unexpected syntax tag %d", syntax_tag(s));
848  break;
849  }
850  return(*lt);
851 }
852 ␌
853 
854 entity
855 reference_translation(reference r,Pbase initial_basis,Pbase local_basis)
856 {
857  int i;
858  entity rv = reference_variable(r);
859  if((i=rank_of_variable(initial_basis, (Variable) rv)) > 0)
860  return((entity) variable_of_rank(local_basis, i));
861  else return(entity_undefined);
862 }
863 
864 void reference_conversion_expression(e, r_to_llv, offsets, initial_basis,
865  local_basis)
866 expression e;
867 hash_table r_to_llv;
868 Pvecteur offsets;
869 Pbase initial_basis;
870 Pbase local_basis;
871 {
872  syntax s = expression_syntax(e);
873  int i;
874  debug(8,"reference_conversion_expression", "begin expression:");
875  ifdebug(8) {
876  print_words(stderr, Words_Expression(e));
877  (void) fputc('\n', stderr);
878  }
879 
880  switch(syntax_tag(s)) {
881  case is_syntax_reference: {
883  entity rv = reference_variable(r);
884  list llv;
885 
886  if((llv = (list) hash_get(r_to_llv, (char *) r))
887  != (list) HASH_UNDEFINED_VALUE) {
888  /* no pipeline, select the first entity by default */
889  entity new_v = ENTITY(CAR(llv));
890  reference_variable(r) = new_v;
891  }
892  else
893  if ((i=rank_of_variable(initial_basis,
894  (Variable) rv)) > 0)
895 
897  (entity) variable_of_rank(local_basis, i);
898 
899  MAPL(ce, {
901  r_to_llv, offsets,
902  initial_basis, local_basis);
903  },
904  reference_indices(r));
905  break;
906  }
907  case is_syntax_range:
908  pips_internal_error("Ranges are not (yet) handled");
909  break;
910  case is_syntax_call:
911  /* the called function is assumed to be unchanged */
912  MAPL(ce, {
914  r_to_llv, offsets,
915  initial_basis, local_basis);
916  },
918  break;
919  default:
920  pips_internal_error("Unexpected syntax tag %d", syntax_tag(s));
921  break;
922  }
923 
924  debug(8,"reference_conversion_expression", "end expression:\n");
925  ifdebug(8) {
926  print_words(stderr, Words_Expression(e));
927  (void) fputc('\n', stderr);
928  }
929 }
930 ␌
931 /* This function checks if two references have a uniform dependence.
932  * It assumes that some verifications have been made before. The two
933  * references r1 and r2 must reference the same array with the same
934  * dimension.
935  *
936  * FI: could/should be moved in ri-util/expression.c
937  */
938 
940 reference r1,r2;
941 {
942 
943  bool uniform = true;
944  cons * ind1, *ind2;
945 
946  debug(8,"uniform_dependence_p", "begin\n");
947 
948  ind1 = reference_indices(r1);
949  ind2 = reference_indices(r2);
950  for (; uniform && ind1 != NULL && ind2!= NULL;
951  ind1 = CDR(ind1), ind2=CDR(ind2))
952  {
953  expression expr1= EXPRESSION(CAR(ind1));
954  expression expr2= EXPRESSION(CAR(ind2));
955  normalized norm1 = (normalized) NORMALIZE_EXPRESSION(expr1);
956  normalized norm2 = (normalized) NORMALIZE_EXPRESSION(expr2);
957  if (normalized_linear_p(norm1) && normalized_linear_p(norm2)) {
958  Pvecteur pv1 = (Pvecteur) normalized_linear(norm1);
959  Pvecteur pv2 = (Pvecteur) normalized_linear(norm2);
960  Pvecteur pv3 = vect_substract(pv1,pv2);
961  if (vect_size(pv3) >1 ||
962  ((vect_size (pv3)==1) && (vecteur_var(pv3) != TCST)))
963  uniform = false;
964  vect_rm(pv3);
965  }
966  }
967  debug(8,"uniform_dependence_p", "end\n");
968  return(uniform);
969 }
970 ␌
971 
972 /* This function classifies the references in lists. All the references
973  * belonging to the same list are uniform dependent references
974 */
976 list llr;
977 reference r;
978 {
979  list plr,lr,bllr,lr2;
980  list blr = NIL;
981  bool trouve = false;
982  reference r2;
983 
984  debug(8,"classify_reference", "begin\n");
985  for (plr = llr,bllr = NIL; plr != NIL && !trouve; plr = CDR(plr)) {
986  for (lr = LIST(CAR(plr)), blr=NIL; lr!= NIL && !trouve;
987  lr = CDR(lr)) {
988  r2 = REFERENCE(CAR(lr));
989  if (uniform_dependence_p(r2,r))
990  trouve = true;
991  }
992  blr = (trouve) ? CONS(REFERENCE,r,LIST(CAR(plr))) :
993  LIST(CAR(plr));
994  bllr = CONS(LIST,blr,bllr);
995  }
996  if (!trouve) {
997  lr2 = CONS(REFERENCE,r,NIL);
998  bllr = CONS(LIST,lr2,bllr);
999  }
1000  debug(8,"classify_reference", "end\n");
1001  return(bllr);
1002 
1003 }
1004 ␌
1005 /* build_sc_with_several_uniform_ref():
1006  *
1007  * Build the set of constraints describing the array function for the
1008  * set of uniform references to the array and update the system
1009  * describing the domain with constraints on new variables
1010  */
1012 entity module;
1013 cons * lr;
1014 Psysteme sc_domain;
1015 Pbase *new_index_base;
1016 {
1017  cons * expr;
1018 
1019  Psysteme sc_array_function = sc_new();
1020  Psysteme sc2;
1021  Pcontrainte pc,pc3=NULL;
1022  Pvecteur pv,pv1,pv2,pv3;
1023  Pvecteur pv_sup = VECTEUR_NUL;
1024  normalized norm;
1025  reference r;
1026  cons * ind;
1028  Value cst = VALUE_ZERO;
1029  Pcontrainte pc1,pc2;
1030  expression expr1;
1031 
1032  debug(8,"build_sc_with_several_uniform_ref", "begin\n");
1033  ifdebug(8) {
1034  list crefs;
1035  (void) fprintf(stderr, "Associated reference list:");
1036  for(crefs=lr; !ENDP(crefs); POP(crefs)) {
1037  reference r1 = REFERENCE(CAR(crefs));
1038  print_reference(r1);
1039  if(ENDP(CDR(crefs)))
1040  (void) putc('\n', stderr);
1041  else
1042  (void) putc(',', stderr);
1043  }
1044  }
1045 
1046 
1047  r= REFERENCE(CAR(lr));
1048  ind = reference_indices(r);
1049 
1050  /* build the system of constraints describing the array function.
1051  One constraint for each dimension of the array is built.
1052  This constraint is put in the system of inequalities of
1053  sc_array_function */
1054 
1055  for (expr = ind;expr!= NULL; expr = CDR(expr)) {
1056  expr1 = EXPRESSION(CAR(expr));
1058  if (normalized_linear_p(norm)) {
1059  pv1 = (Pvecteur) normalized_linear(norm);
1060  pc = contrainte_make(vect_dup(pv1));
1061  if (sc_array_function->inegalites == NULL) {
1062  sc_array_function->inegalites = pc;
1063  }
1064  else pc3->succ = pc;
1065  pc3=pc;
1066  sc_array_function->nb_ineq ++;
1067  }
1068  else {
1069  pips_internal_error("Non-linear subscript expression");
1070  }
1071  }
1072  sc_creer_base(sc_array_function);
1073 
1074  /* update the system describing the image function with the others array
1075  functions having a uniform dependence with the first one
1076  for example, assume we have A(i,j) and A(i+2,j+3)
1077  then the final system will be :
1078  i + 2 X1 <= 0
1079  j - 3 X1 <= 0
1080  X1 is new variable
1081  */
1082  sc2 =sc_dup(sc_dup(sc_array_function));
1083  for (lr = CDR(lr); lr != NIL;lr = CDR(lr)) {
1084  bool new_variable = false;
1085  r= REFERENCE(CAR(lr));
1086  ind = reference_indices(r);
1087  for (expr = ind,pc = sc_array_function->inegalites,
1088  pc2 = sc2->inegalites;
1089  expr!= NULL; expr = CDR(expr), pc=pc->succ,pc2 = pc2->succ) {
1090 
1092  pv1 = (Pvecteur) normalized_linear(norm);
1093  pv3 = vect_substract(pv1,pc2->vecteur);
1094  if (vect_size(pv3) == 1) {
1095  if (value_notzero_p(cst=vecteur_val(pv3))) {
1096  if (!new_variable) {
1097  new_variable = true;
1099  sc_array_function);
1100 
1101  vect_chg_coeff(&pv_sup,var,VALUE_ONE);
1102  }
1103  vect_chg_coeff(&pc->vecteur,var,cst);
1104  }
1105  }
1106  else if (vect_size(pv3) >1)
1107  pips_internal_error("Non uniform dependent references");
1108  }
1109  }
1110 
1111  /* add to the system of constraints describing the domain the
1112  set of constraints on the new variables. If X1,X2,...Xn are these
1113  new variables the set of constraints added is:
1114  0 <= X1 <= 1
1115  0 <= X2 <= 1 - X1
1116  0 <= X3 <= 1 - X1 -X2
1117  0<= Xn <= 1 - X1 - X2 ... -Xn-1
1118  */
1119  for (pv = pv_sup; !VECTEUR_NUL_P(pv); pv = pv->succ) {
1120  sc_domain->base = vect_add_variable(sc_domain->base,pv->var);
1121  sc_domain->dimension++;
1122  *new_index_base = vect_add_variable(*new_index_base,pv->var);
1123  pv1 = vect_dup(pv);
1125  pc1= contrainte_make(pv1);
1126  sc_add_ineg(sc_domain,pc1);
1127  pv2 = vect_dup(pv);
1128  vect_chg_sgn(pv2);
1129  pc2 = contrainte_make(pv2);
1130  sc_add_ineg(sc_domain,pc2);
1131  }
1132 
1133  ifdebug(8) {
1134  (void) fprintf(stderr," The array function :\n");
1135  (void) sc_fprint(stderr,sc_array_function,(string(*)(Variable))entity_local_name);
1136  }
1137 
1138  debug(8,"build_sc_with_several_uniform_ref", "end\n");
1139 
1140 
1141  return(sc_array_function);
1142 }
1143 
1144 static void initialize_offsets(list lt)
1145 {
1146  list ltmp = LIST(CAR(lt));
1147  reference ref1 = REFERENCE(CAR(ltmp));
1148  list lind = reference_indices(ref1);
1149  expression expr1 = EXPRESSION(CAR(lind));
1152 
1153  offset_dim1 = vect_coeff(TCST,pv1);
1154  if (CDR(lind) != NIL) {
1155  expr1 = EXPRESSION(CAR(CDR(lind)));
1157  pv1 = (Pvecteur) normalized_linear(norm);
1158  offset_dim2 = vect_coeff(TCST,pv1);
1159  }
1160 
1161 }
1162 
1163 static void nullify_offsets()
1165 
1167 entity initial_module,
1168 entity compute_module,
1169 entity memory_module,
1170 entity var, /* entity */
1171 entity shared_variable, /* emulated shared variable for example ES_A */
1172 entity local_variable, /* local variable for example L_A_1_1*/
1173 list lrefs,
1174 hash_table r_to_ud,
1175 Psysteme sc_domain, /* domain of iteration */
1176 Pbase index_base, /* index basis */
1177 Pbase bank_indices, /* contains the index describing the bank:
1178  bank_id, L (ligne of bank) and O (offset in
1179  the ligne) */
1180 Pbase tile_indices, /* contains the local indices LI, LJ of tile */
1181 Pbase loop_body_indices,
1182 entity Proc_id, /* corresponds to a processeur identicator */
1183 int pn, int bn, int ls, /* bank number and line size (depends on the
1184  machine) */
1185 statement * store_block,
1186 statement * bank_store_block,
1187 int first_parallel_level,
1188 int last_parallel_level)
1189 {
1190  pips_assert("true", last_parallel_level==last_parallel_level
1191  && first_parallel_level==first_parallel_level);
1192  list ldr;
1193  list lldr = NIL;
1194  list lrs;
1195  Psysteme sc_image,sc_array_function;
1196  int n,dim_h;
1197  Pbase const_base;
1198  Pbase new_index_base= BASE_NULLE;
1199  Pbase new_tile_indices = BASE_NULLE;
1200  reference r;
1201  bool bank_code; /* is true if it is the generation
1202  of code for bank false if it is
1203  for engine */
1204  bool receive_code; /* is true if the generated code
1205  must be a RECEIVE, false if it
1206  must be a SEND*/
1207  statement stat1,stat2,sb,bsb;
1208  cons * bst_sb = NIL;
1209  cons * bst_bsb = NIL;
1210  Pbase var_id;
1211  Pvecteur ppid = vect_new((char *) Proc_id, VALUE_ONE);
1212  Psysteme sc_image2= SC_UNDEFINED;
1213  debug(8,"make_store_blocks",
1214  "begin variable=%s, shared_variable=%s, local_variable=%s\n",
1215  entity_local_name(var), entity_local_name(shared_variable),
1216  entity_local_name(local_variable));
1217 
1218  ifdebug(8) {
1219  list crefs;
1220  (void) fprintf(stderr, "Associated reference list:");
1221  for(crefs=lrefs; !ENDP(crefs); POP(crefs)) {
1222  reference r1 = REFERENCE(CAR(crefs));
1223  print_reference(r1);
1224  if(ENDP(CDR(crefs)))
1225  (void) putc('\n', stderr);
1226  else
1227  (void) putc(',', stderr);
1228  }
1229  }
1230 
1231 
1232  /* Cases where the references are scalar variables */
1233 
1234  for (lrs =lrefs ; !ENDP(lrs) ; POP(lrs)) {
1235  r = REFERENCE(CAR(lrs));
1236  if (reference_indices(r) ==NIL) {
1237  receive_code = false;
1238  *store_block=make_movement_scalar_wp65(compute_module,
1239  receive_code,
1240  r,Proc_id);
1241  receive_code = true;
1242  *bank_store_block=
1243  make_movement_scalar_wp65(memory_module,receive_code,
1244  r,(entity) bank_indices->var);
1245  return;
1246  }
1247  }
1248 
1249  /* In the other cases the references must be classified in lists of
1250  uniform dependent references */
1251 
1252  for ( lrs = lrefs; lrs != NIL ; lrs = CDR(lrs) ) {
1253  r = REFERENCE(CAR(lrefs));
1254  if ( (intptr_t)hash_get(r_to_ud, r) == (intptr_t)is_action_write)
1255  lldr = classify_reference(lldr,r);
1256  }
1257 
1258  /* For each list of uniform dependent references, "store_block" and
1259  "bank_store_block" are computed */
1260 
1261  for (ldr = lldr;ldr != NIL;ldr = CDR(ldr)) {
1262 
1263  sc_array_function=
1264  build_sc_with_several_uniform_ref(initial_module,
1265  LIST(CAR(ldr)),
1266  sc_domain,&new_index_base);
1267  new_index_base = vect_add(new_index_base,
1268  vect_dup(index_base));
1269 
1270  sc_image = sc_image_computation(initial_module,
1271  var,sc_domain,
1272  sc_array_function,new_index_base,
1273  &const_base,Proc_id,bank_indices,
1274  tile_indices,&new_tile_indices,
1275  pn,bn,ls,
1276  &n,&dim_h);
1277  nullify_offsets();
1278  sc_image2 = sc_dup(sc_image);
1279  bank_code = true ;
1280  receive_code = true;
1281  var_id = (Pbase) vect_new(vecteur_var(ppid),
1282  vecteur_val(ppid));
1283  stat1 = movement_computation(memory_module,false,bank_code,
1284  receive_code,
1285  shared_variable,sc_image,
1286  const_base,bank_indices,
1287  new_tile_indices,
1288  var_id,loop_body_indices,n,dim_h);
1289  initialize_offsets(ldr);
1290  bank_code = false ;
1291  receive_code = false;
1292  var_id = (Pbase) vect_new(vecteur_var(bank_indices),
1293  vecteur_val(bank_indices));
1294  stat2 = movement_computation(compute_module,false,bank_code,
1295  receive_code,
1296  local_variable,sc_image2,
1297  const_base,bank_indices,
1298  new_tile_indices,
1299  var_id,loop_body_indices,n,dim_h);
1300 
1301  bst_sb = CONS(STATEMENT,stat2,bst_sb);
1302  bst_bsb =CONS(STATEMENT,stat1,bst_bsb);
1303  }
1304  sb = make_block_statement(bst_sb);
1305  bsb=make_block_statement(bst_bsb);
1306  *store_block = sb;
1307  *bank_store_block = bsb;
1308 
1309  debug(8,"make_store_blocks", "end\n");
1310 }
1311 ␌
1312 void make_load_blocks(initial_module,compute_module,memory_module,var,shared_variable,local_variable,lrefs,
1313  r_to_ud,sc_domain,
1314  index_base,bank_indices,tile_indices,loop_body_indices, Proc_id,
1315  pn,bn,ls,
1316  load_block, bank_load_block,first_parallel_level,last_parallel_level
1317 )
1318 entity initial_module;
1319 entity compute_module;
1320 entity memory_module;
1321 entity var; /* entity */
1322 entity shared_variable; /* emulated shared variable for example ES_A */
1323 entity local_variable; /* local variable for example L_A_1_1*/
1324 list lrefs; /* list of references associated to the local
1325  variable */
1326 hash_table r_to_ud;
1327 Psysteme sc_domain; /* domain of iteration */
1328 Pbase index_base; /* index basis */
1329 Pbase bank_indices; /* contains the index describing the bank:
1330  bank_id, L (ligne of bank) and O (offset in
1331  the ligne) */
1332 Pbase tile_indices; /* contains the local indices LI, LJ of tile */
1333 Pbase loop_body_indices;
1334 entity Proc_id; /* corresponds to a processeur identicator */
1335 int pn,bn,ls; /* bank number and line size (depends on the
1336  machine) */
1337 statement * load_block;
1338 statement * bank_load_block;
1339 int first_parallel_level,last_parallel_level;
1340 {
1341  pips_assert("true", last_parallel_level==last_parallel_level &&
1342  first_parallel_level==first_parallel_level);
1343  list lur;
1344  list llur = NIL;
1345  list lrs = lrefs;
1346  Psysteme sc_image,sc_array_function;
1347  int n,dim_h;
1348  Pbase const_base;
1349  Pbase new_index_base = BASE_NULLE;
1350  Pbase new_tile_indices = BASE_NULLE;
1351  bool bank_code; /* is true if it is the generation
1352  of code for bank false if it is
1353  for engine */
1354  bool receive_code; /* is true if the generated code
1355  must be a RECEIVE, false if it
1356  must be a SEND*/
1357  reference r;
1358  statement stat1,stat2,lb,blb;
1359  cons * bst_lb= NIL;
1360  cons * bst_blb= NIL;
1361  Pbase var_id;
1362  Pvecteur ppid = vect_new((char *) Proc_id, VALUE_ONE);
1363  Psysteme sc_image2= SC_UNDEFINED;
1364  debug(8,"make_load_blocks",
1365  "begin variable=%s, shared_variable=%s, local_variable=%s\n",
1366  entity_local_name(var), entity_local_name(shared_variable),
1367  entity_local_name(local_variable));
1368 
1369  ifdebug(8) {
1370  list crefs;
1371  (void) fprintf(stderr, "Associated reference list:");
1372  for(crefs=lrefs; !ENDP(crefs); POP(crefs)) {
1373  reference r1 = REFERENCE(CAR(crefs));
1374  print_reference(r1);
1375  if(ENDP(CDR(crefs)))
1376  (void) putc('\n', stderr);
1377  else
1378  (void) putc(',', stderr);
1379  }
1380  }
1381 
1382 
1383  /* Cases where the references are scalar variables */
1384 
1385  for (lrs =lrefs ; !ENDP(lrs) ; POP(lrs)) {
1386  r = REFERENCE(CAR(lrs));
1387  if (reference_indices(r) ==NIL) {
1388 
1389  receive_code = true;
1390  *load_block =make_movement_scalar_wp65(compute_module,receive_code,
1391  r,Proc_id);
1392  receive_code = false;
1393  *bank_load_block=
1394  make_movement_scalar_wp65(memory_module,receive_code,
1395  r,(entity) bank_indices->var);
1396  return;
1397  }
1398  }
1399  /* In the other cases the references must be classified in lists of
1400  uniform dependent references */
1401 
1402  for (lrs =lrefs ; !ENDP(lrs) ; POP(lrs)) {
1403  r = REFERENCE(CAR(lrs));
1404  if ( (intptr_t) hash_get(r_to_ud, r) == (intptr_t)is_action_read)
1405  llur = classify_reference(llur,r);
1406  }
1407 
1408  /* For each list of uniform dependent references, "load_block" and
1409  "bank_load_block" are computed */
1410 
1411  for (lur=llur; lur != NIL; lur = CDR(lur)) {
1412  sc_array_function=
1413  build_sc_with_several_uniform_ref(initial_module,
1414  LIST(CAR(lur)),
1415  sc_domain,&new_index_base);
1416  new_index_base = vect_add(new_index_base,
1417  vect_dup(index_base));
1418 
1419  sc_image = sc_image_computation(initial_module,var,sc_domain,
1420  sc_array_function,new_index_base,
1421  &const_base,Proc_id,bank_indices,
1422  tile_indices,&new_tile_indices,
1423  pn,bn,ls,
1424  &n,&dim_h);
1425  nullify_offsets();
1426  sc_image2= sc_dup(sc_image);
1427  bank_code = true ;
1428  receive_code = false;
1429  var_id = (Pbase) vect_new(vecteur_var(ppid),
1430  vecteur_val(ppid));
1431  stat1 = movement_computation(memory_module,
1432  true,
1433  bank_code,
1434  receive_code,
1435  shared_variable,sc_image,
1436  const_base,bank_indices,new_tile_indices,
1437  var_id, loop_body_indices,n,dim_h);
1438  initialize_offsets(lur);
1439  bank_code = false ;
1440  receive_code = true;
1441  var_id = (Pbase) vect_new(vecteur_var(bank_indices),
1442  vecteur_val(bank_indices));
1443  stat2 = movement_computation(compute_module,
1444  true,
1445  bank_code,
1446  receive_code,
1447  local_variable,sc_image2,
1448  const_base,bank_indices,new_tile_indices,
1449  var_id, loop_body_indices,n,dim_h);
1450 
1451  bst_lb = CONS(STATEMENT,stat2,bst_lb);
1452  bst_blb = CONS(STATEMENT,stat1,bst_blb);
1453  }
1454 
1455  lb = make_block_statement(bst_lb);
1456  blb = make_block_statement(bst_blb);
1457  *load_block =lb;
1458  *bank_load_block=blb;
1459 
1460  debug(8,"make_load_blocks", "end\n");
1461 }
1462 ␌
1463 /* Psysteme tile_membership(P, origin, member):
1464  *
1465  * builds a linear constraint system to express the fact that iteration
1466  * "member" belongs to a P tile with origin "origin". "origin" and "member"
1467  * are expressed in the initial basis.
1468  */
1470 matrice P;
1471 Pbase origin;
1472 Pbase member;
1473 {
1474  Psysteme m = sc_new();
1475  int d = base_dimension(origin);
1476  matrice IP = matrice_new(d,d);
1477  Pcontrainte c1;
1478  int i, j;
1479  Value k;
1480 
1481  debug(8,"tile_membership", "begin\n");
1482 
1483  pips_assert("tile_membership", d == base_dimension(member));
1484  pips_assert("tile_membership", value_one_p(DENOMINATOR(P)));
1485 
1486  ifdebug(8) {
1487  (void) fprintf(stderr,"Partitioning matrix P:\n");
1488  matrice_fprint(stderr, P, d, d);
1489  }
1490 
1491  matrice_general_inversion(P, IP, d);
1492  matrice_normalize(IP, d, d);
1493  k = DENOMINATOR(IP);
1494 
1495 /* pips_assert("tile_membership", k > 1); */
1496 
1497  ifdebug(8) {
1498  (void) fprintf(stderr,"Inverse of partitioning matrix, IP:\n");
1499  matrice_fprint(stderr, IP, d, d);
1500  }
1501 
1502  for ( i=1; i<=d; i++) {
1504 
1505  for ( j=1; j<=d; j++) {
1508  value_uminus(ACCESS(IP, d, j, i)));
1511  ACCESS(IP, d, j, i));
1512  }
1513  sc_add_inegalite(m, c);
1514  c1 = contrainte_dup(c);
1515  contrainte_chg_sgn(c1);
1517  sc_add_inegalite(m, c1);
1518  }
1519 
1520  sc_creer_base(m);
1521  matrice_free(IP);
1522 
1523  ifdebug(8) {
1524  (void) fprintf(stderr,"Tile membership conditions:\n");
1525  sc_fprint(stderr, m, (string(*)(Variable))entity_local_name);
1526  }
1527 
1528  debug(8,"tile_membership", "end\n");
1529 
1530  return m;
1531 }
execution make_execution(enum execution_utype tag, void *val)
Definition: ri.c:838
loop make_loop(entity a1, range a2, statement a3, entity a4, execution a5, list a6)
Definition: ri.c:1301
range make_range(expression a1, expression a2, expression a3)
Definition: ri.c:2041
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
static bool member(region reg, list reg_list)
tests if reg and any member of reg_list are same_reg_ignore_action
#define VALUE_ZERO
#define value_minus(v1, v2)
#define value_notzero_p(val)
#define value_uminus(val)
unary operators on values
#define value_one_p(val)
#define VALUE_MONE
int Value
#define value_eq(v1, v2)
bool operators on values
#define VALUE_ONE
#define value_mult(v, w)
whether the default is protected or not this define makes no sense any more...
int rank_of_variable(Pbase base, Variable var)
this function returns the rank of the variable var in the base 0 encodes TCST, but I do not know why,...
Definition: base.c:497
Pbase vect_add_variable(Pbase b, Variable v)
package vecteur - routines sur les bases
Definition: base.c:61
Pvecteur make_loop_indice_equation(Pbase loop_indices, tiling tile, Pvecteur tile_delay, Pvecteur tile_indices, Pvecteur tile_local_indices, int rank)
PACKAGE MOVEMENTS.
Definition: build_sc_tile.c:51
Psysteme tile_membership(matrice P, Pbase origin, Pbase member)
Psysteme tile_membership(P, origin, member):
Definition: code.c:1469
static void ref_found_p(reference ref)
Definition: code.c:75
static Variable var_to_evaluate
Definition: code.c:73
Value offset_dim1
include "generation.h"
Definition: code.c:67
void eval_variable_in_statement(entity module, statement s, Variable v, int min)
Definition: code.c:141
void make_store_blocks(entity initial_module, entity compute_module, entity memory_module, entity var, entity shared_variable, entity local_variable, list lrefs, hash_table r_to_ud, Psysteme sc_domain, Pbase index_base, Pbase bank_indices, Pbase tile_indices, Pbase loop_body_indices, entity Proc_id, int pn, int bn, int ls, statement *store_block, statement *bank_store_block, int first_parallel_level, int last_parallel_level)
Definition: code.c:1166
void reference_conversion_expression(expression e, hash_table r_to_llv, Pvecteur offsets, Pbase initial_basis, Pbase local_basis)
Definition: code.c:864
static void initialize_offsets(list lt)
Definition: code.c:1144
dg_vertex_label vertex_label
Definition: code.c:56
static void eval_var(reference ref)
Definition: code.c:95
static bool ref_in_statement1
Definition: code.c:71
static Value var_minmax
Definition: code.c:72
dg_arc_label arc_label
Code Generation for Distributed Memory Machines.
Definition: code.c:55
statement make_scanning_over_tiles(entity module, list body, entity proc_id, int pn, tiling tile, Pbase initial_basis, Pbase tile_basis_in_tile_basis, Pbase tile_basis_in_initial_basis, Psysteme iteration_domain, int first_parallel_level, int last_parallel_level)
make_scanning_over_tiles()
Definition: code.c:227
list reference_conversion_statement(entity module, statement body, list *lt, hash_table r_to_llv, Pvecteur offsets, Pbase initial_basis, Pbase tile_indices, Pbase local_basis, tiling tile)
void reference_conversion_statement(body, r_to_llv, offsets, initial_basis, local_basis):
Definition: code.c:723
list classify_reference(list llr, reference r)
This function classifies the references in lists.
Definition: code.c:975
static entity tile_indice_entity1
Definition: code.c:70
static bool reference_in_statement_p(statement l, entity v)
Definition: code.c:83
void make_load_blocks(entity initial_module, entity compute_module, entity memory_module, entity var, entity shared_variable, entity local_variable, list lrefs, hash_table r_to_ud, Psysteme sc_domain, Pbase index_base, Pbase bank_indices, Pbase tile_indices, Pbase loop_body_indices, entity Proc_id, int pn, int bn, int ls, statement *load_block, statement *bank_load_block, int first_parallel_level, int last_parallel_level)
Definition: code.c:1312
Value offset_dim2
Definition: code.c:68
list reference_conversion_computation(entity compute_module, list *lt, expression expr, Pbase initial_basis, Pbase tile_indices, Pbase tile_local_indices, tiling tile)
Definition: code.c:799
static void nullify_offsets()
Definition: code.c:1163
entity reference_translation(reference r, Pbase initial_basis, Pbase local_basis)
Definition: code.c:855
void tile_change_of_basis(Psysteme tile_domain, Pbase initial_basis, Pbase tile_basis, Pbase tile_init_basis, tiling tile)
Definition: code.c:161
list make_compute_block(entity module, statement body, Pvecteur offsets, hash_table r_to_llv, tiling tile, Pbase initial_basis, Pbase local_basis, Pbase tile_basis_in_tile_basis, Pbase tile_basis_in_initial_basis, Psysteme iteration_domain, int first_parallel_level, int last_parallel_level)
Definition: code.c:679
statement make_scanning_over_one_tile(entity module, statement body, tiling tile, Pbase initial_basis, Pbase local_basis, Pbase tile_basis_in_tile_basis, Pbase tile_basis_in_initial_basis, Psysteme iteration_domain, int first_parallel_level, int last_parallel_level)
make_scanning_over_one_tile():
Definition: code.c:475
Psysteme build_sc_with_several_uniform_ref(entity module, cons *lr, Psysteme sc_domain, Pbase *new_index_base)
build_sc_with_several_uniform_ref():
Definition: code.c:1011
bool uniform_dependence_p(reference r1, reference r2)
This function checks if two references have a uniform dependence.
Definition: code.c:939
#define contrainte_vecteur(c)
passage au champ vecteur d'une contrainte "a la Newgen"
Pcontrainte contrainte_make(Pvecteur pv)
Pcontrainte contrainte_make(Pvecteur pv): allocation et initialisation d'une contrainte avec un vecte...
Definition: alloc.c:73
Pcontrainte contrainte_dup(Pcontrainte c_in)
Pcontrainte contrainte_dup(Pcontrainte c_in): allocation d'une contrainte c_out prenant la valeur de ...
Definition: alloc.c:132
Pcontrainte contrainte_new(void)
package contrainte - allocations et desallocations
Definition: alloc.c:47
void contrainte_chg_sgn(Pcontrainte)
void contrainte_chg_sgn(Pcontrainte eq): changement de signe d'une contrainte, i.e.
Definition: unaires.c:56
static entity new_variable
entity to be replaced, the primary?
Definition: dynamic.c:860
#define min(a, b)
#define max(a, b)
@ is_action_write
Definition: effects.h:293
@ is_action_read
Definition: effects.h:292
#define LIST(x)
Definition: genC.h:93
#define gen_recurse(start, domain_number, flt, rwt)
Definition: genC.h:283
statement make_block_statement(list)
Make a block statement from a list of statement.
Definition: statement.c:616
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#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
#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
#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
statement make_continue_statement(entity)
Definition: statement.c:953
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 vect_fprint(FILE *f, Pvecteur v, get_variable_name_t variable_name)
void vect_fprint(FILE * f, Pvecteur v, char * (*variable_name)()): impression d'un vecteur creux v su...
Definition: io.c:124
int vect_size(Pvecteur v)
package vecteur - reductions
Definition: reductions.c:47
void wp65_debug_print_text(entity m, statement s)
include "values.h"
statement make_movement_scalar_wp65(entity module, bool receive_code, reference r, entity var_id)
statement make_movement_scalar_wp65(receive_code,r)
#define DENOMINATOR(matrix)
int DENOMINATEUR(matrix): acces au denominateur global d'une matrice matrix La combinaison *(&()) est...
Definition: matrice-local.h:93
#define matrice_free(m)
Definition: matrice-local.h:78
#define ACCESS(matrix, column, i, j)
Macros d'acces aux elements d'une matrice.
Definition: matrice-local.h:86
#define matrice_new(n, m)
Allocation et desallocation d'une matrice.
Definition: matrice-local.h:77
Value * matrice
package matrice
Definition: matrice-local.h:71
void matrice_general_inversion(matrice a, matrice inv_a, int n)
void matrice_general_inversion(matrice a; matrice inv_a; int n) calcul de l'inversion du matrice gene...
Definition: inversion.c:222
void matrice_normalize(matrice a, int n, int m)
void matrice_normalize(matrice a, int n, int m)
Definition: matrice.c:125
void matrice_fprint(FILE *, matrice, int, int)
matrice_io.c
Definition: matrice_io.c:62
#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
void debug(const int the_expected_debug_level, const char *calling_function_name, const char *a_message_format,...)
ARARGS0.
Definition: debug.c:189
Psysteme sc_image_computation(entity module, entity entity_var, Psysteme sc_domain, Psysteme sc_array_function, Pbase index_base, Pbase *const_base, entity proc_id, Pbase bank_indices, Pbase tile_indices, Pbase *new_tile_indices, int pn, int bn, int ls, int *n, int *dim_h)
This function computes the system of constraints characterizing the image by the array function of th...
statement movement_computation(entity module, bool used_def, bool bank_code, bool receive_code, entity private_entity, Psysteme sc_image, Pbase const_base, Pbase bank_indices, Pbase tile_indices, Pbase ppid, Pbase loop_body_indices, int n, int dim_h)
Calcul des nouvelles bornes des boucles et de la nouvelle fonction d'acces a une reference d'un table...
Variable sc_add_new_variable_name(entity, Psysteme)
sc_add_variable.c
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
#define HASH_UNDEFINED_VALUE
value returned by hash_get() when the key is not found; could also be called HASH_KEY_NOT_FOUND,...
Definition: newgen_hash.h:56
#define true
Definition: newgen_types.h:81
#define false
Definition: newgen_types.h:80
#define UU
Definition: newgen_types.h:98
static char * module
Definition: pips.c:74
void print_reference(reference r)
Definition: expression.c:142
list Words_Expression(expression obj)
of string
Definition: misc.c:2616
static void norm(struct rproblem *RR)
cette procedure normalise la fonction cout, calcule les valeurs des seconds membres resultant d'une n...
Definition: r1.c:271
#define instruction_block_p(i)
#define loop_to_statement(l)
#define PLUS_OPERATOR_NAME
#define MOD_INTRINSIC_NAME
#define NORMALIZE_EXPRESSION(e)
#define STATEMENT_NUMBER_UNDEFINED
default values
#define is_instruction_block
soft block->sequence transition
#define instruction_block(i)
void make_bound_expression(Variable index, Pbase base, Psysteme sc, expression *lower, expression *upper)
void make_bound_expression(variable index, Pbase base, Psysteme sc, expression *lower,...
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 make_loop_label(int __attribute__((unused)) desired_number, entity module)
Definition: entity.c:370
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 entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
expression MakeBinaryCall(entity f, expression eg, expression ed)
Creates a call expression to a function with 2 arguments.
Definition: expression.c:354
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
entity make_new_module_variable(entity, int)
Make a new module integer variable of name X<d>.
Definition: variable.c:830
void AddEntityToDeclarations(entity, entity)
END_EOLE.
Definition: variable.c:108
#define loop_body(x)
Definition: ri.h:1644
#define REFERENCE(x)
REFERENCE.
Definition: ri.h:2296
#define storage_formal_p(x)
Definition: ri.h:2522
#define syntax_reference(x)
Definition: ri.h:2730
#define syntax_tag(x)
Definition: ri.h:2727
#define normalized_linear_p(x)
Definition: ri.h:1779
#define reference_variable(x)
Definition: ri.h:2326
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define instruction_loop(x)
Definition: ri.h:1520
#define entity_storage(x)
Definition: ri.h:2794
@ is_syntax_range
Definition: ri.h:2692
@ is_syntax_call
Definition: ri.h:2693
@ is_syntax_reference
Definition: ri.h:2691
#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 expression_undefined
Definition: ri.h:1223
@ is_instruction_goto
Definition: ri.h:1473
@ is_instruction_unstructured
Definition: ri.h:1475
@ is_instruction_test
Definition: ri.h:1470
@ is_instruction_call
Definition: ri.h:1474
@ is_instruction_loop
Definition: ri.h:1471
#define instruction_tag(x)
Definition: ri.h:1511
struct _newgen_struct_normalized_ * normalized
Definition: ri.h:247
#define reference_indices(x)
Definition: ri.h:2328
#define syntax_call(x)
Definition: ri.h:2736
#define statement_instruction(x)
Definition: ri.h:2458
#define statement_comments(x)
Definition: ri.h:2456
#define instruction_call(x)
Definition: ri.h:1529
@ is_execution_sequential
Definition: ri.h:1189
#define call_arguments(x)
Definition: ri.h:711
#define statement_number(x)
Definition: ri.h:2452
#define normalized_linear(x)
Definition: ri.h:1781
#define expression_syntax(x)
Definition: ri.h:1247
#define statement_undefined
Definition: ri.h:2419
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
void sc_creer_base(Psysteme ps)
void sc_creer_base(Psysteme ps): initialisation des parametres dimension et base d'un systeme lineair...
Definition: sc_alloc.c:129
void sc_add_egalite(Psysteme p, Pcontrainte e)
void sc_add_egalite(Psysteme p, Pcontrainte e): macro ajoutant une egalite e a un systeme p; la base ...
Definition: sc_alloc.c:389
Psysteme sc_new(void)
Psysteme sc_new(): alloue un systeme vide, initialise tous les champs avec des valeurs nulles,...
Definition: sc_alloc.c:55
void sc_add_inegalite(Psysteme p, Pcontrainte i)
void sc_add_inegalite(Psysteme p, Pcontrainte i): macro ajoutant une inegalite i a un systeme p; la b...
Definition: sc_alloc.c:406
Psysteme sc_dup(Psysteme ps)
Psysteme sc_dup(Psysteme ps): should becomes a link.
Definition: sc_alloc.c:176
void sc_force_variable_to_zero(Psysteme ps, Variable var)
void sc_force_variable_to_zero(Psysteme ps, Variable var): force la variable var a prendre la valeur ...
Definition: sc_eval.c:251
bool sc_minmax_of_variable(Psysteme ps, Variable var, Value *pmin, Value *pmax)
void sc_minmax_of_variable(Psysteme ps, Variable var, Value *pmin, *pmax): examine un systeme pour tr...
Definition: sc_eval.c:143
Pcontrainte eq
element du vecteur colonne du systeme donne par l'analyse
Definition: sc_gram.c:108
Variable variable_of_rank()
Psysteme sc_append(Psysteme s1, Psysteme s2)
Psysteme sc_append(Psysteme s1, Psysteme s2): calcul de l'intersection des polyedres definis par s1 e...
void sc_fprint(FILE *fp, Psysteme ps, get_variable_name_t nom_var)
void sc_fprint(FILE * f, Psysteme ps, char * (*nom_var)()): cette fonction imprime dans le fichier po...
Definition: sc_io.c:220
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
Psysteme new_loop_bound(Psysteme scn, Pbase base_index)
Psysteme new_loop_bound(Psysteme scn, Pbase base_index) computation of the new iteration space (given...
Psysteme sc_normalize(Psysteme ps)
Psysteme sc_normalize(Psysteme ps): normalisation d'un systeme d'equation et d'inequations lineaires ...
void sc_transform_eg_in_ineg(Psysteme sc)
Package sc.
void vect_chg_sgn(Pvecteur v)
void vect_chg_sgn(Pvecteur v): multiplie v par -1
Definition: scalaires.c:151
#define ifdebug(n)
Definition: sg.c:47
static statement origin
Definition: simdizer.c:411
#define intptr_t
Definition: stdint.in.h:294
Pvecteur vecteur
struct Scontrainte * succ
Pcontrainte inegalites
Definition: sc-local.h:71
Pbase base
Definition: sc-local.h:75
int dimension
Definition: sc-local.h:74
int nb_ineq
Definition: sc-local.h:73
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
Variable var
Definition: vecteur-local.h:90
struct Svecteur * succ
Definition: vecteur-local.h:92
Polymorphic argument.
Definition: printf-args.h:92
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: statement.c:4047
void print_words(FILE *fd, cons *lw)
Definition: print.c:263
#define tiling_origin(x)
Definition: tiling.h:70
#define tiling_tile(x)
Definition: tiling.h:68
#define TCST
VARIABLE REPRESENTANT LE TERME CONSTANT.
#define vecteur_val(v)
#define vecteur_var(v)
#define VECTEUR_NUL
DEFINITION DU VECTEUR NUL.
struct Svecteur * Pbase
struct Svecteur * Pvecteur
#define VECTEUR_NUL_P(v)
#define base_rm(b)
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 VARIABLE_UNDEFINED
Definition: vecteur-local.h:64
#define base_dimension(b)
#define BASE_NULLE
MACROS SUR LES BASES.
Pvecteur vect_dup(Pvecteur v_in)
Pvecteur vect_dup(Pvecteur v_in): duplication du vecteur v_in; allocation de et copie dans v_out;.
Definition: alloc.c:51
Pvecteur vect_new(Variable var, Value coeff)
Pvecteur vect_new(Variable var,Value coeff): allocation d'un vecteur colineaire au vecteur de base va...
Definition: alloc.c:110
void vect_rm(Pvecteur v)
void vect_rm(Pvecteur v): desallocation des couples de v;
Definition: alloc.c:78
Pvecteur vect_add(Pvecteur v1, Pvecteur v2)
package vecteur - operations binaires
Definition: binaires.c:53
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
void vect_add_elem(Pvecteur *pvect, Variable var, Value val)
void vect_add_elem(Pvecteur * pvect, Variable var, Value val): addition d'un vecteur colineaire au ve...
Definition: unaires.c:72
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
void vect_chg_coeff(Pvecteur *ppv, Variable var, Value val)
void vect_chg_coeff(Pvecteur *ppv, Variable var, Value val): mise de la coordonnee var du vecteur *pp...
Definition: unaires.c:143