PIPS
broadcast.c
Go to the documentation of this file.
1 /*
2 
3  $Id: broadcast.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 /*
28  * -- broadcast.c
29  *
30  * package prgm_mapping : Alexis Platonoff, april 1993 --
31  *
32  * This file contains the functions used for the broadcast detection.
33  *
34  */
35 
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 
40 /* Newgen includes */
41 #include "genC.h"
42 
43 /* C3 includes */
44 #include "boolean.h"
45 #include "arithmetique.h"
46 #include "vecteur.h"
47 #include "contrainte.h"
48 #include "ray_dte.h"
49 #include "sommet.h"
50 #include "sg.h"
51 #include "sc.h"
52 #include "polyedre.h"
53 #include "union.h"
54 #include "matrice.h"
55 #include "matrix.h"
56 
57 #include "ri.h"
58 #include "ri-util.h"
59 #include "graph.h"
60 #include "dg.h"
61 #include "paf_ri.h"
62 #include "constants.h"
63 #include "misc.h"
64 #include "static_controlize.h"
65 #include "paf-util.h"
66 #include "array_dfg.h"
67 #include "prgm_mapping.h"
68 
69 /* Local defines */
72 
73 /* global variables */
74 extern list prgm_parameter_l;
75 
76 /* ======================================================================== */
77 /*
78  * void broadcast(graph g) : This function walks through all the node list of
79  * the graph "g" (it is a DFG) and for each dataflow it detects if it is a
80  * broadcast or not. If so the communication field of the dataflow is updated
81  * with the broadcast vector.
82  *
83  * The detection on each dataflow is done with broadcast_of_dataflow() that
84  * needs the dataflow itself and the corresponding sink statement.
85  */
86 void
88  graph g;
89 {
90  list nodes_l, /* List of the nodes of the DFG */
91  su_l, /* List of successors of one node */
92  df_l; /* List of dataflows of one successor */
93  int sink_stmt; /* Statement number associated with one
94  * successor */
95 
96  /* We look for broadcasts on all nodes */
97  for (nodes_l = graph_vertices(g); nodes_l != NIL; nodes_l = CDR(nodes_l)) {
98  su_l = vertex_successors(VERTEX(CAR(nodes_l)));
99 
100  /* We look for broadcasts on all successors of one node */
101  for (; su_l != NIL; su_l = CDR(su_l)) {
102  successor su = SUCCESSOR(CAR(su_l));
103  vertex sv = successor_vertex(su);
104 
107 
108  /* We look for broadcasts on all dataflows of one successor */
109  for (; df_l != NIL; df_l = CDR(df_l))
111  }
112  }
113 }
114 
115 
116 /* ======================================================================== */
117 /*
118  * entity base_find_var_with_rank(Pbase b, int r): returns the entity
119  * corresponding to the variable of the Pbase at the rth position.
120  */
121 entity
123  Pbase b;
124  int r;
125 {
126  int i;
127  Pvecteur v = (Pvecteur) b;
128 
129  if (r > base_dimension(b))
130  pips_internal_error("rank %d too high", r);
131 
132  for (i = 1; i < r; v = v->succ, i++);
133 
134  return ((entity) v->var);
135 }
136 
137 
138 /* ======================================================================== */
139 /*
140  * void broadcast_of_dataflow(dataflow df, int stmt, predicate exec_domain):
141  *
142  * detects if the dataflow "df" can produce a broadcast communication. "stmt"
143  * gives the sink statement corresponding to this dataflow, it is used to get
144  * the indices of the englobing loops. "exec_domain" gives the execution
145  * domain of the sink instruction.
146  *
147  * A broadcast corresponds to the fact that the same memory cell is read by
148  * different instances (or operations) of an instruction. An operation is
149  * represented by the name of the instruction and a vector of iteration (that
150  * gives the value of the indices of the englobing loops).
151  *
152  * One field of the dataflow is "transformations" which gives a list of
153  * expressions each representing the value of a source index function of the
154  * sink indices. Let s be the source indices and d the sink indices,
155  * "transformations" represents a system like: A.d = s
156  *
157  * A dataflow is a broadcast if and only if, the source indices fixed, their
158  * exist several possible values for the sink indices. This means to find the
159  * solution of a system of linear integer equations: d = d0 + KerA, KerA is
160  * the kernel of the linear application associated to matrix A, so, a basis
161  * of KerA gives the direction of the broadcast.
162  *
163  * We solve this system with the hermite reduction ([Min83]): P.A.Q = H,
164  * where P and Q are unimodular and H is the hermite form. Let r be the rank
165  * of H and Q_r a sub-matrix of Q (the m-r last columns). [Min83] gives the
166  * solution as: d = d0 + Q_r.y where y is a vector of arbitrary integers.
167  * Then Q_r gives a basis of KerA.
168  */
169 void
170 broadcast_of_dataflow(df, stmt, exec_domain)
171  dataflow df;
172  int stmt;
173  predicate exec_domain;
174 {
175  matrice A, /* Matrix of transformation equations (n x m) */
176  B, P, /* Left matrix for the hermite decomposition
177  * (n x n) */
178  Q, /* Right matrix for the hermite decomposition
179  * (m x m) */
180  H, /* Matrix of Hermite (n x m) */
181  Q_r; /* Sub-matrix of Q: the m-r last columns */
182  int n, /* Number of transformation equations */
183  m, /* Number of englobing loops */
184  r, /* Rank of H */
185  i, j;
186  Value det_p, det_q;
187  predicate new_pred, /* Equations of broadcast vectors */
188  gov_pred; /* Governing predicate */
189  communication comm; /* Communication of the dataflow */
190  Pbase b_loop_ind; /* Base of index of the englobing loops */
191  Psysteme sc_trans, /* Equations of transformations */
192  diff_sc; /* Equations of broadcast vectors */
193  list trans_l, /* List of the transformations */
194  li, lp;
195  static_control stct;
196 
199  comm = dataflow_communication(df);
200  diff_sc = sc_new();
201 
202  /* Transformation system of equations */
204 
205  /* Englobing loops indices (li) and structure parameters (lp) */
207  li = static_control_to_indices(stct);
209 
210  /* Base of the index of the englobing loops */
211  b_loop_ind = list_to_base(li);
212 
213  /* We compute the size the matrix A */
214  n = sc_trans->nb_eq;
215  m = base_dimension(b_loop_ind);
216 
217  if (n == 0) {
218  /*
219  * The number of equations is zero (no equations for the transformation
220  * means that the source instruction is not inside a loop body) then each
221  * index of the base (indices of the loop nest containing the sink
222  * instruction) loop is a broadcast vector.
223  */
224  for (j = 1; j <= m; j++) {
225  entity ent = base_find_var_with_rank(b_loop_ind, j);
226  sc_add_egalite(diff_sc, contrainte_make(vect_new((char *) ent, 1)));
227  }
228  } else if (m == 0) {
229  /*
230  * There is no englobing index for the sink statement, this means that
231  * this statement is not inside a loop body, so, it is not a broadcast.
232  */
233  } else {
234  /*
235  * n > 0: we compute the matrix H and the associated matrices P and Q.
236  * The kernal of A is not of dim 0 only if its rank (r) is less than its
237  * number of columns (m).
238  */
239  A = matrice_new(n, m);
240  B = matrice_new(n, 1);
241  pu_contraintes_to_matrices(sc_trans->egalites, b_loop_ind, A, B, n, m);
242 
243  P = matrice_new(n, n);
244  Q = matrice_new(m, m);
245  H = matrice_new(n, m);
246  matrice_hermite(A, n, m, P, H, Q, &det_p, &det_q);
247 
248  r = matrice_hermite_rank(H, n, m);
249  if (r > n)
250  r = n;
251  if (r > m)
252  r = m;
253 
254  if (m - r > 0) {
255  Q_r = matrice_new(m, m - r);
256  for (i = 1; i <= m; i++)
257  for (j = 1; j <= m - r; j++)
258  ACCESS(Q_r, m, i, j) = ACCESS(Q, m, i, j + r);
259  Q_r[0] = DENOMINATOR(Q);
260 
261  for (j = 1; j <= m - r; j++) {
262  Pvecteur vect = NULL;
263  for (i = 1; i <= m; i++) {
264  entity ent = base_find_var_with_rank(b_loop_ind, i);
265  vect = vect_add(vect_new((char *) ent, ACCESS(Q_r, m, i, j)), vect);
266  }
267  sc_add_egalite(diff_sc, contrainte_make(vect));
268  }
269  }
270  }
271 
272  /*
273  * We update the dataflow communication of "df" only if the systeme has at
274  * least one equation, i.e. one broadcast vector.
275  */
276  if (diff_sc->nb_eq != 0) {
277  Psysteme sc_ed, sc_gp, df_domain, impl_sc;
278  Pcontrainte pd, pdprec;
279 
280  /*
281  * We make sure that each broadcast vector is a real one, i.e. the set of
282  * values it can take has strictly more than one value. For this, we get
283  * the implicit equation of the dataflow domain, the execution domain of
284  * the sink intersection the governing predicate.
285  */
286  if (exec_domain == predicate_undefined)
287  sc_ed = sc_new();
288  else
289  sc_ed = (Psysteme) predicate_system(exec_domain);
291  sc_gp = sc_new();
292  else
294 
295  df_domain = sc_new();
296  df_domain = sc_intersection(df_domain, sc_ed, sc_gp);
297 
298  impl_sc = find_implicit_equation(df_domain);
299 
300  if (impl_sc != NULL) {
301  for (pd = diff_sc->egalites, pdprec = NULL; pd != NULL; pd = pd->succ) {
302  Psysteme aux_ps = sc_dup(impl_sc);
303 
305  aux_ps->base = NULL;
306  sc_creer_base(aux_ps);
307  aux_ps = sc_normalize(aux_ps);
308 
309  /*
310  * We remove the current diffusion vector if it corresponds to one of
311  * the implicit equations.
312  */
313  if ((aux_ps == NULL) || (aux_ps->nb_eq == impl_sc->nb_eq)) {
314  diff_sc->nb_eq = diff_sc->nb_eq - 1;
315  if (pdprec == NULL)
316  diff_sc->egalites = pd->succ;
317  else {
318  pdprec->succ = pd->succ;
319  }
320  } else
321  pdprec = pd;
322  }
323  }
324  if (diff_sc->nb_eq != 0) {
325 
326  /* Create the basis of the new sc */
327  sc_creer_base(diff_sc);
328 
329  new_pred = make_predicate((char *) diff_sc);
330  if (comm == communication_undefined)
331  comm = make_communication(new_pred, predicate_undefined,
333  else
334  communication_broadcast(comm) = new_pred;
335 
336  dataflow_communication(df) = comm;
337  } else
338  sc_rm(diff_sc);
339  } else
340  sc_rm(diff_sc);
341 }
342 
343 
344 /* ======================================================================== */
345 list
347  Pcontrainte pc;
348 {
349  Pcontrainte cpc, spc;
350  list l_pc = NIL;
351 
352  for (cpc = pc; cpc != NULL;) {
353  spc = cpc;
354  cpc = cpc->succ;
355  spc->succ = NULL;
356  l_pc = gen_nconc(l_pc, CONS(CHUNK, (chunk *) spc, NIL));
357  }
358  return (l_pc);
359 }
360 
361 
362 /* ======================================================================== */
365  list l_pc;
366 {
368  list l;
369 
370  for (l = l_pc; !ENDP(l); POP(l)) {
371  Pcontrainte spc = (Pcontrainte) CHUNK(CAR(l));
372  if (CONTRAINTE_UNDEFINED_P(pc)) {
373  pc = spc;
374  cpc = pc;
375  } else {
376  cpc->succ = spc;
377  cpc = spc;
378  }
379  }
380  return (pc);
381 }
382 
383 
384 /* ======================================================================== */
385 /*
386  * bool compare_eq_occ(eq1, eq2):
387  *
388  * "eq1" and "eq2" are two Pcontrainte(s). This function returns true if the
389  * field "eq_sat" of "eq1" is greater or equal to the one of "eq2". This
390  * field represents the number of occurences of the equations in a list of
391  * systems.
392  */
393 boolean
394 compare_eq_occ(eq1, eq2)
395  chunk *eq1, *eq2;
396 {
397  Pcontrainte c1, c2;
398  c1 = (Pcontrainte) eq1;
399  c2 = (Pcontrainte) eq2;
400 
401  return (*(c1->eq_sat) >= *(c2->eq_sat));
402 }
403 
404 
405 /* ======================================================================== */
406 void
408  FILE *fp;
409  list l_ps;
410 {
411  list l;
412  int i = 1;
413  for (l = l_ps; !ENDP(l); POP(l)) {
414  fprintf(fp, "Syst %d:\n", i++);
415  fprint_psysteme(fp, (Psysteme) CHUNK(CAR(l)));
416  }
417 }
418 
419 
420 /* ======================================================================== */
421 /*
422  * void count_eq_occ(list l_ps):
423  *
424  * We have a list of systems "l_ps", each
425  * system is a list of equations. This function counts for each equations the
426  * number of systems in which it appears. As each equation is represented
427  * with the Pcontrainte data structure, the result is put into the "eq_sat"
428  * field.
429  */
430 void
432  list l_ps;
433 {
434  list l, ll;
435  int c = 0, cc;
436 
437  /* Initialization of eq_sat to 1, each equation appears at least once. */
438  for (l = l_ps; !ENDP(l); POP(l)) {
439  Psysteme ps = (Psysteme) CHUNK(CAR(l));
440  Pcontrainte pc = ps->egalites;
441  for (; pc != NULL; pc = pc->succ) {
442  pc->eq_sat = (int *) malloc(sizeof(int));
443  *(pc->eq_sat) = 1;
444  }
445  }
446 
447  /* We count the occurence of each equation in all the others systems */
448  for (l = l_ps; !ENDP(l); POP(l)) {
449  Psysteme ps = (Psysteme) CHUNK(CAR(l));
450  Pcontrainte pc = ps->egalites;
451  c++;
452  for (; pc != NULL; pc = pc->succ) {
453  Pvecteur pv = pc->vecteur;
454  cc = 0;
455  for (ll = l_ps; !ENDP(ll); POP(ll)) {
456  cc++;
457  if (cc > c) {
458  Psysteme pps = (Psysteme) CHUNK(CAR(ll));
459  Pcontrainte ppc = pps->egalites;
460  for (; ppc != NULL; ppc = ppc->succ) {
461  Pvecteur ppv = ppc->vecteur;
462  if ((vect_substract(pv, ppv) == VECTEUR_NUL) ||
463  (vect_add(pv, ppv) == VECTEUR_NUL)) {
464  (*(ppc->eq_sat))++;
465  (*(pc->eq_sat))++;
466  }
467  }
468  }
469  }
470  }
471  }
472 }
473 
474 
475 /* ======================================================================== */
476 /*
477  * void sort_eq_in_systems(list l_ps):
478  *
479  * We have a list of systems, each
480  * system is a list of equations. We sort each list of equations so as to
481  * have first the equations that appear the most often in all the systems.
482  *
483  * For example, with the two following list of systems L = (S1, S2), S1 = {x1 =
484  * 0, x2 = 0} and S2 = {x3 = 0, x2 = 0}, the lists of equations of S1 and S2
485  * are reordered as follows: S1 = {x2 = 0, x1 = 0} and S2 = {x2 = 0, x3 = 0}.
486  *
487  * Note: We do not sort anything if there is only one system in "l_ps".
488  */
489 void
491  list l_ps;
492 {
493  list l, l_eq, sl_eq;
494  Psysteme crt_ps;
495 
496  if (gen_length(l_ps) <= 1)
497  return;
498 
499  /* We count the occurence of each equation */
500  count_eq_occ(l_ps);
501 
502  /* We sort the list of equations of each systems using these numbers */
503  for (l = l_ps; !ENDP(l); POP(l)) {
504  crt_ps = (Psysteme) CHUNK(CAR(l));
505 
506  /*
507  * Our sorting function (general_merge_sort()) works upon NewGen
508  * lists. So we have to transform our chained Pcontrainte(s) into a
509  * list of Pcontrainte(s), each Pcontrainte having no successor. After
510  * sorting, we transform it back into chained Pcontrainte(s). */
511  l_eq = contraintes_to_list(crt_ps->egalites);
512  sl_eq = general_merge_sort(l_eq, compare_eq_occ);
513  crt_ps->egalites = list_to_contraintes(sl_eq);
514  }
515 }
516 
517 
518 /* ======================================================================== */
519 /*
520  * void mapping_on_broadcast(int stmt, Psysteme K)
521  *
522  * This function constructs some dimension of the placement function, of
523  * statement "stmt", by mapping on them some of the broadcast directions given
524  * in "K".
525  *
526  * First, it gets the dimensions already mapped, they constitutes a space A.
527  * Second, it looks for the greatest subspace K' of K (the broadcast space)
528  * such as A and K' are disjoint.
529  * Third, it maps some of the remaining dimensions of the placement function
530  * with some of the dimension of K'.
531  */
533 int stmt;
534 Psysteme K;
535 {
536  extern plc pfunc;
538 
539  list plcs, ind_l, mu_list, la_list;
540  Psysteme A, Kp;
541  placement stmt_plc = placement_undefined;
542  static_control stct;
543  Pbase ind_base;
544  int p_dim;
545 
546 if (get_debug_level() > 5) {
547 fprintf(stderr, "[mapping_on_broadcast] BEGIN **********\n");
548 fprintf(stderr, "[mapping_on_broadcast] with stmt %d and K: \n", stmt);
549 fprint_psysteme(stderr, K);
550 }
551 
552  /* We get the placement function of statement "stmt". */
553  for(plcs = plc_placements(pfunc); stmt_plc == placement_undefined; POP(plcs)) {
554  placement crt_plc = PLACEMENT(CAR(plcs));
555  if(stmt == placement_statement(crt_plc))
556  stmt_plc = crt_plc;
557  }
558 
559  /* Don't do anything if all the placement function dimensions' are already
560  * mapped.
561  */
562  p_dim = (int) hash_get(StmtToPdim, (char *) stmt);
563 
564 if (get_debug_level() > 5) {
565 fprintf(stderr, "[mapping_on_broadcast] dim(PLC) = %d, already mapped:\n", p_dim);
566 fprint_pla_pp_dims(stderr, stmt_plc);
567 }
568 
569  if(gen_length(placement_dims(stmt_plc)) == p_dim)
570  return;
571 
573  ind_l = static_control_to_indices(stct);
574  ind_base = list_to_base(ind_l);
575 
576  mu_list = (list) hash_get(StmtToMu, (char *) stmt);
577 
578 if (get_debug_level() > 5) {
579 fprintf(stderr, "[mapping_on_broadcast] Mu :");
580 fprint_entity_list(stderr, mu_list);
581 fprintf(stderr, "\n");
582 }
583 
584 /* First, it gets the dimensions already mapped, they constitutes a space A. */
585  A = broadcast_dimensions(stmt_plc, mu_list);
586 
587 if (get_debug_level() > 5) {
588 fprintf(stderr, "[mapping_on_broadcast] Space A:\n");
589 fprint_psysteme(stderr, A);
590 }
591 
592 /* Second, it looks for the greatest subspace K' of K (the broadcast space)
593  * such as A and K' are disjoint.
594  */
595 {
596  Pcontrainte K_dims;
597  Psysteme Ps;
598 
599  if( (A != SC_EMPTY) && (A->nb_eq != 0) ) {
600  Kp = sc_new();
601 
602  for(K_dims = K->egalites; K_dims != NULL; K_dims = K_dims->succ) {
603  Ps = sc_dup(A);
604 
605  sc_add_egalite(Ps, contrainte_dup(K_dims));
606 
607  if(vecteurs_libres_p(Ps, ind_base, BASE_NULLE))
608  sc_add_egalite(Kp, contrainte_dup(K_dims));
609 
610  sc_rm(Ps);
611  }
612  }
613  else
614  Kp = K;
615 }
616 
617  sc_rm(A);
618 
619 if (get_debug_level() > 5) {
620 fprintf(stderr, "[mapping_on_broadcast] Space K':\n");
621 fprint_psysteme(stderr, Kp);
622 }
623 
624 /* Third, it maps some of the remaining dimensions of the placement function
625  * with some of the dimension of K'.
626  */
627  if(Kp->nb_eq != 0) {
628  list new_dims = NIL, mu_l, par_l;
629  Pcontrainte Kp_dims;
630  int count_dim, i;
631 
632 
633  /* To each dimension of the placement function, we have associated a
634  * variable mu.
635  */
636  mu_l = mu_list;
637  la_list = (list) hash_get(StmtToLamb, (char *) stmt);
638 
639 if (get_debug_level() > 5) {
640 fprintf(stderr, "[mapping_on_broadcast] Mu :");
641 fprint_entity_list(stderr, mu_l);
642 fprintf(stderr, "\n");
643 fprintf(stderr, "[mapping_on_broadcast] Lambda :");
644 fprint_entity_list(stderr, la_list);
645 fprintf(stderr, "\n");
646 }
647 
648 
649  Kp_dims = Kp->egalites;
650  count_dim = gen_length(placement_dims(stmt_plc));
651  for(i = 0; i<count_dim; i++) { POP(mu_l); }
652  for(; (Kp_dims != NULL) && (count_dim < p_dim); Kp_dims = Kp_dims->succ) {
653  Ppolynome new_pp;
654  list lam_l = la_list;
655 
656  par_l = gen_append(prgm_parameter_l, NIL);
657 
658 if (get_debug_level() > 5) {
659 fprintf(stderr, "[mapping_on_broadcast] Params :");
660 fprint_entity_list(stderr, par_l);
661 fprintf(stderr, "\n");
662 }
663 
664  new_pp = make_polynome(1.0, (Variable) ENTITY(CAR(lam_l)), (Value) 1);
665 
666  for(i = 0; i<=gen_length(ind_l); i++) { POP(lam_l); }
667  for(; !ENDP(lam_l); POP(lam_l), POP(par_l)) {
668  polynome_add(&new_pp,
670  (Variable) ENTITY(CAR(par_l)),
671  (Value) 1),
672  make_polynome(1.0,
673  (Variable) ENTITY(CAR(lam_l)),
674  (Value) 1)));
675  }
676  polynome_add(&new_pp,
678  (Variable) ENTITY(CAR(mu_l)),
679  (Value) 1),
680  vecteur_to_polynome(Kp_dims->vecteur)));
681 
682  new_dims = gen_nconc(new_dims, CONS(CHUNK, (chunk *) new_pp, NIL));
683 
684 if (get_debug_level() > 5) {
685 fprintf(stderr, "[mapping_on_broadcast] K' current dim : ");
686 pu_vect_fprint(stderr, Kp_dims->vecteur);
687 fprintf(stderr, "\n");
688 fprintf(stderr, "[mapping_on_broadcast] PLC added dim %d : ", count_dim);
690 fprintf(stderr, "\n");
691 }
692 
693  POP(mu_l);
694  count_dim++;
695  }
696 
697  placement_dims(stmt_plc) = gen_nconc(placement_dims(stmt_plc), new_dims);
698  }
699 
700 if (get_debug_level() > 5) {
701 fprintf(stderr, "[mapping_on_broadcast] Dims now mapped:\n");
702 fprint_pla_pp_dims(stderr, stmt_plc);
703 
704 fprintf(stderr, "[mapping_on_broadcast] END **********\n\n");
705 }
706 
707 }
708 
709 
710 /* ======================================================================== */
711 /*
712  * list broadcast_conditions(list lambda, list df_l, list *sigma):
713  *
714  * processes a list of dataflows "df_l" with the broadcast conditions. The
715  * dataflows not processed are returned.
716  *
717  * The goal is to accept conditions upon variables (in "lambda"). These
718  * conditions are the broadcast conditiions. There is one condition for each
719  * edge with a broadcast. Each condition is a system of equations. We'll say
720  * that a condition is accepted iff at least one equation is accepted. An
721  * equation is accepted iff it does not make trivial any of the prototypes.
722  * For triviality, see is_not_trivial_p().
723  *
724  * An accepted equation can be represented as a substitution that expresses
725  * one variable function of the others.
726  */
727 list
728 broadcast_conditions(lambda, df_l, sigma)
729  list lambda, df_l, *sigma;
730 {
732 
733  list l, rem_df_l = NIL, acc_df_l = NIL, l_M_local = NIL, ml, dl;
734 
735  for (l = df_l; !ENDP(l); POP(l)) {
736  dataflow df = DATAFLOW(CAR(l));
739 
740  if (get_debug_level() > 4) {
741  fprintf(stderr, "[broadcast_conditions] \t\t\tDF: ");
742  fprint_dataflow(stderr, 0, df);
743  fprintf(stderr, "\n");
744  }
745  if (is_broadcast_p(df)) {
746  bp = communication_broadcast(com);
747  }
748  if (get_debug_level() > 4) {
749  fprintf(stderr, "[broadcast_conditions] \t\t\tComm pred: ");
750  if (bp == predicate_undefined)
751  fprintf(stderr, "predicate_undefined");
752  else
753  fprint_pred(stderr, bp);
754  fprintf(stderr, "\n");
755  }
756  if (bp == predicate_undefined)
757  rem_df_l = gen_nconc(rem_df_l, CONS(DATAFLOW, df, NIL));
758  else {
759  list ind_l, par_l, proto_lambda, l_bdir, bl;
760  Psysteme ps_pdir = (Psysteme) predicate_system(bp), ps_bdir;
761  Pcontrainte pc, prec_pc, new_pc;
762  int stmt = (int) hash_get(DtfToSink, (char *) df),
763  n, m1, m2, i,
764  j, k, p_dim;
766  matrice A, B, inv_A, R, Rt, Bz;
767 
768  k = ps_pdir->nb_eq;
769  ind_l = static_control_to_indices(stct);
770  par_l = gen_append(prgm_parameter_l, NIL);
771  m1 = gen_length(ind_l);
772  m2 = gen_length(par_l) + 1; /* add 1, because of TCST */
773 
774  p_dim = (int) hash_get(StmtToPdim, (char *) stmt);
775  l_bdir = stmt_bdt_directions(stmt, ind_l, par_l);
776 
777  /* We remove broadcast vectors contained in the time space */
778  for (bl = l_bdir; !ENDP(bl); POP(bl)) {
779  ps_bdir = (Psysteme) CHUNK(CAR(bl));
780  if (ps_bdir->nb_eq > 0) {
781  prec_pc = NULL;
782  for (pc = ps_pdir->egalites; pc != NULL; pc = pc->succ) {
783  Psysteme ps_aux = sc_dup(ps_bdir);
784  sc_add_egalite(ps_aux, contrainte_make(pc->vecteur));
785 
786  if (vecteurs_libres_p(ps_aux, list_to_base(ind_l),
787  list_to_base(par_l))) {
788  prec_pc = pc;
789  } else {
790  (ps_pdir->nb_eq)--;
791  if (prec_pc == NULL) {
792  ps_pdir->egalites = pc->succ;
793  } else {
794  prec_pc->succ = pc->succ;
795  }
796  }
797  }
798 
799  if (get_debug_level() > 4) {
800  fprintf(stderr, "[broadcast_conditions] \t\t\tk before elim bdt = %d\n", k);
801  }
802  k = ps_pdir->nb_eq;
803  }
804  }
805 
806  if (get_debug_level() > 4) {
807  fprintf(stderr, "[broadcast_conditions] \t\t\tk = %d\n", k);
808  }
809  if (k == m1) {
810  /* No condition: broadcast on all the processors */
811  } else if (k == 0) {
812  /* No condition yet, we'll try to zero out its distance */
813  rem_df_l = gen_nconc(rem_df_l, CONS(DATAFLOW, df, NIL));
814  } else {
815  Psysteme M_local, ps_eps;
816 
817  acc_df_l = gen_nconc(acc_df_l, CONS(DATAFLOW, df, NIL));
818 
819  ps_eps = completer_base(ps_pdir, ind_l, par_l);
820 
821  if (get_debug_level() > 4) {
822  fprintf(stderr, "[broadcast_conditions] \t\t\tFull sys\n");
823  fprint_psysteme(stderr, ps_eps);
824  fprintf(stderr, "\n");
825  }
826  n = ps_eps->nb_eq;
827  if (m1 != n)
828  user_error("broadcast_conditions", "m1 should be equal to n\n");
829 
830  A = matrice_new(n, n);
831  B = matrice_new(n, m2);
833  list_to_base(ind_l),
834  list_to_base(par_l), A, B, n, n, m2);
835 
836  inv_A = matrice_new(n, n);
837  matrice_general_inversion(A, inv_A, n);
838 
839  /* R is a sub-matrix of inv_A containing the (n-k) last columns. */
840  R = matrice_new(n, n - k);
841  for (i = 1; i <= n; i++)
842  for (j = 1; j <= (n - k); j++)
843  ACCESS(R, n, i, j) = ACCESS(inv_A, n, i, j + k);
844  R[0] = 1;
845 
846  Rt = matrice_new((n - k), n);
847  matrice_transpose(R, Rt, n, (n - k));
848 
849  proto_lambda = get_stmt_index_coeff(stmt, StmtToLamb);
850 
851  Bz = matrice_new((n - k), 1);
852  matrice_nulle(Bz, (n - k), 1);
853  pu_matrices_to_contraintes(&new_pc, list_to_base(proto_lambda),
854  Rt, Bz, (n - k), n);
855 
856  matrice_free(A);
857  matrice_free(B);
858  matrice_free(inv_A);
859  matrice_free(R);
860  matrice_free(Rt);
861  matrice_free(Bz);
862 
863  M_local = sc_make(new_pc, NULL);
864 
865  if (get_debug_level() > 4) {
866  fprintf(stderr, "[broadcast_conditions] \t\t\tM_local:\n");
867  fprint_psysteme(stderr, M_local);
868  fprintf(stderr, "\n");
869  }
870  l_M_local = gen_nconc(l_M_local, CONS(CHUNK, (chunk *) M_local, NIL));
871  }
872  }
873  }
874  /*
875  * We have a list of systems, each system is a list of equations. We sort
876  * each list of equations so as to have first the equations that appear the
877  * most often in all the systems.
878  *
879  * Thus, these equations are treated first.
880  */
881  sort_eq_in_systems(l_M_local);
882 
883  for (dl = acc_df_l, ml = l_M_local; !ENDP(dl); POP(dl), POP(ml)) {
884  dataflow df = DATAFLOW(CAR(dl));
885  Psysteme M_local = (Psysteme) CHUNK(CAR(ml));
886 
887  if (get_debug_level() > 4) {
888  fprintf(stderr, "[broadcast_conditions] \t\t\tSIGMA before:\n");
889  fprint_vvs(stderr, *sigma);
890  fprintf(stderr, "\n");
891  }
892  /* If one condition is not are satisfied, we try to cut this edge AND we
893  * try to ensure that a subspace of the distribution space will coincide
894  * with a subspace of the broadcast space.
895  */
896  if (!solve_system_by_succ_elim(M_local, sigma)) {
897  int stmt = (int) hash_get(DtfToSink, (char *) df);
898 
899  rem_df_l = gen_nconc(rem_df_l, CONS(DATAFLOW, df, NIL));
903  (dataflow_communication(df))));
904  }
905 
906  if (get_debug_level() > 4) {
907  fprintf(stderr, "[broadcast_conditions] \t\t\tSIGMA after:\n");
908  fprint_vvs(stderr, *sigma);
909  fprintf(stderr, "\n");
910  }
911  }
912 
913  return (rem_df_l);
914 }
915 
916 
917 /* ========================================================================= */
918 list
919 stmt_bdt_directions(stmt, ind_l, par_l)
920  int stmt;
921  list ind_l, par_l;
922 {
923  extern bdt the_bdt;
924  list l_dirs = NIL;
925 
926  if (the_bdt != bdt_undefined) {
927  list bl;
928  bool sc_found = false;
929  for (bl = bdt_schedules(the_bdt); (bl != NIL) && (!sc_found); bl = CDR(bl)) {
930  schedule sc = SCHEDULE(CAR(bl));
931  if (schedule_statement(sc) == stmt) {
932  list dl;
933  Psysteme ps = sc_new();
934  for (dl = schedule_dims(sc); dl != NIL; dl = CDR(dl)) {
935  expression e = EXPRESSION(CAR(dl));
936  if (!expression_constant_p(e)) {
937  list l;
938  bool ind_not_null;
939  Pvecteur pv;
940 
943 
944  ind_not_null = false;
945  for (l = ind_l; (!ENDP(l)) && (!ind_not_null); POP(l)) {
946  entity var = ENTITY(CAR(l));
947  if (vect_coeff((Variable) var, pv) != 0)
948  ind_not_null = true;
949  }
950  if (ind_not_null) {
951  Psysteme aux_ps = sc_dup(ps);
952  sc_add_egalite(aux_ps, contrainte_make(pv));
953 
954  if (vecteurs_libres_p(aux_ps, list_to_base(ind_l), list_to_base(par_l))) {
955  ps = aux_ps;
956  } else {
957  }
958  }
959  }
960  }
961  sc_creer_base(ps);
962  l_dirs = gen_nconc(l_dirs, CONS(CHUNK, (chunk *) ps, NIL));
963  }
964  }
965  }
966  return (l_dirs);
967 }
communication make_communication(predicate a1, predicate a2, predicate a3)
Definition: paf_ri.c:96
predicate make_predicate(Psysteme a1)
Definition: ri.c:1820
static int sink_stmt
Current source node.
Definition: adg_read_paf.c:160
static list trans_l
Current list of nodes.
Definition: adg_read_paf.c:168
static predicate gov_pred
Current expression.
Definition: adg_read_paf.c:165
statement adg_number_to_statement(int in_nb)
======================================================================
Definition: adg_utils.c:461
void const char const char const int
int Value
Pcontrainte list_to_contraintes(list l_pc)
========================================================================
Definition: broadcast.c:364
dfg_arc_label arc_label
Definition: broadcast.c:71
entity base_find_var_with_rank(Pbase b, int r)
========================================================================
Definition: broadcast.c:122
boolean compare_eq_occ(chunk *eq1, chunk *eq2)
========================================================================
Definition: broadcast.c:394
void broadcast(graph g)
========================================================================
Definition: broadcast.c:87
void count_eq_occ(list l_ps)
========================================================================
Definition: broadcast.c:431
list prgm_parameter_l
global variables
Definition: prgm_mapping.c:115
list stmt_bdt_directions(int stmt, list ind_l, list par_l)
=========================================================================
Definition: broadcast.c:919
void broadcast_of_dataflow(dataflow df, int stmt, predicate exec_domain)
========================================================================
Definition: broadcast.c:170
dfg_vertex_label vertex_label
Newgen includes
Definition: broadcast.c:70
void mapping_on_broadcast(int stmt, Psysteme K)
========================================================================
Definition: broadcast.c:532
void fprint_l_psysteme(FILE *fp, list l_ps)
========================================================================
Definition: broadcast.c:407
void sort_eq_in_systems(list l_ps)
========================================================================
Definition: broadcast.c:490
list broadcast_conditions(list lambda, list df_l, list *sigma)
========================================================================
Definition: broadcast.c:728
list contraintes_to_list(Pcontrainte pc)
========================================================================
Definition: broadcast.c:346
#define A(i, j)
comp_matrice.c
Definition: comp_matrice.c:63
#define CONTRAINTE_UNDEFINED_P(c)
#define CONTRAINTE_UNDEFINED
struct Scontrainte * Pcontrainte
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
#define CHUNK(x)
Definition: genC.h:90
void * malloc(YYSIZE_T)
#define successor_vertex(x)
Definition: graph.h:118
#define successor_arc_label(x)
Definition: graph.h:116
#define vertex_successors(x)
Definition: graph.h:154
#define SUCCESSOR(x)
SUCCESSOR.
Definition: graph.h:86
#define graph_vertices(x)
Definition: graph.h:82
#define VERTEX(x)
VERTEX.
Definition: graph.h:122
#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
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
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
list gen_append(list l1, const list l2)
Definition: list.c:471
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
bool expression_constant_p(expression)
HPFC module by Fabien COELHO.
Definition: expression.c:2453
void fprint_entity_list(FILE *fp, list l)
void fprint_entity_list(FILE *fp,list l): prints a list of entities on file fp.
Definition: entity.c:3188
#define B(A)
Definition: iabrev.h:61
#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
int matrice_hermite_rank(matrice a, int n, int m __attribute__((unused)))
int matrice_hermite_rank(matrice a, int n, int m): rang d'une matrice en forme de hermite
Definition: hermite.c:178
void matrice_hermite(Value *MAT, int n, int m, Value *P, Value *H, Value *Q, Value *det_p, Value *det_q)
package matrice
Definition: hermite.c:78
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_transpose(matrice a, matrice a_t, int n, int m)
package matrice
Definition: matrice.c:48
void matrice_nulle(matrice Z, int n, int m)
void matrice_nulle(matrice Z, int n, int m): Initialisation de la matrice Z a la valeur matrice nulle
Definition: matrice.c:311
#define pips_internal_error
Definition: misc-local.h:149
#define user_error(fn,...)
Definition: misc-local.h:265
int get_debug_level(void)
GET_DEBUG_LEVEL returns the current debugging level.
Definition: debug.c:67
Pbase list_to_base(list l)
Pbase list_to_base(list l): returns the Pbase that contains the variables of list "l",...
struct cons * list
Definition: newgen_types.h:106
const char * pu_variable_name(Variable)
package mapping : Alexis Platonoff, april 1993
Definition: print.c:421
list general_merge_sort(list, bool(*)(void))
Psysteme make_expression_equalities(list)
===========================================================================
Definition: utils.c:931
int vertex_int_stmt(vertex)
===========================================================================
Definition: utils.c:866
void contraintes_with_sym_cst_to_matrices(Pcontrainte, Pbase, Pbase, matrice, matrice, int, int, int)
Creation de la matrice A correspondant au systeme lineaire et de la matrice correspondant a la partie...
Definition: utils.c:446
void pu_vect_fprint(FILE *, Pvecteur)
===========================================================================
Definition: print.c:446
list static_control_to_indices(static_control)
package mapping : Alexis Platonoff, july 1993
Definition: utils.c:1037
Psysteme find_implicit_equation(Psysteme)
========================================================================
Definition: utils.c:2350
static_control get_stco_from_current_map(statement)
========================================================================
Definition: utils.c:2429
bool pu_is_inferior_var(Variable, Variable)
void fprint_psysteme(FILE *, Psysteme)
===========================================================================
Definition: print.c:302
void fprint_pred(FILE *, predicate)
===========================================================================
Definition: print.c:287
void pu_contraintes_to_matrices(Pcontrainte, Pbase, matrice, matrice, int, int)
===========================================================================
Definition: utils.c:408
void fprint_dataflow(FILE *, int, dataflow)
===========================================================================
Definition: print.c:229
void pu_matrices_to_contraintes(Pcontrainte *, Pbase, matrice, matrice, int, int)
utils.c
Definition: utils.c:350
#define plc_placements(x)
Definition: paf_ri.h:557
#define dataflow_communication(x)
Definition: paf_ri.h:346
#define DATAFLOW(x)
DATAFLOW.
Definition: paf_ri.h:308
#define dataflow_transformation(x)
Definition: paf_ri.h:342
#define placement_undefined
Definition: paf_ri.h:499
#define placement_dims(x)
Definition: paf_ri.h:525
#define SCHEDULE(x)
SCHEDULE.
Definition: paf_ri.h:682
#define dfg_arc_label_dataflows(x)
Definition: paf_ri.h:378
#define communication_undefined
Definition: paf_ri.h:236
#define PLACEMENT(x)
PLACEMENT.
Definition: paf_ri.h:493
#define dataflow_governing_pred(x)
Definition: paf_ri.h:344
#define bdt_schedules(x)
Definition: paf_ri.h:226
#define schedule_dims(x)
Definition: paf_ri.h:717
#define schedule_statement(x)
Definition: paf_ri.h:713
#define communication_broadcast(x)
Definition: paf_ri.h:261
#define placement_statement(x)
Definition: paf_ri.h:523
#define bdt_undefined
Definition: paf_ri.h:204
#define Q
Definition: pip__type.h:39
Ppolynome make_polynome(float coeff, Variable var, Value expo)
Ppolynome make_polynome(float coeff, Variable var, Value expo) PRIVATE allocates space for,...
Definition: pnome-alloc.c:100
Ppolynome vecteur_to_polynome(Pvecteur pv)
===========================================================================
Definition: pnome-bin.c:406
Ppolynome polynome_mult(Ppolynome pp1, Ppolynome pp2)
Ppolynome polynome_mult(Ppolynome pp1, Ppolynome pp2) returns pp1 * pp2.
Definition: pnome-bin.c:287
void polynome_add(Ppolynome *ppp, Ppolynome pp2)
void polynome_add(Ppolynome* ppp, Ppolynome pp2) (*ppp) = (*ppp) + pp2.
Definition: pnome-bin.c:171
void polynome_fprint(FILE *fd, Ppolynome pp, char *(*variable_name)(Variable), int *is_inferior_var)
void polynome_fprint(FILE* fd, Ppolynome pp, char* (*variable_name)(), bool (*is_inferior_var)()) Out...
Definition: pnome-io.c:173
#define VERTEX_DOMAIN(v)
void fprint_pla_pp_dims(FILE *fp, placement one_placement)
========================================================================
Definition: print.c:204
bool is_broadcast_p(dataflow df)
========================================================================
Definition: utils.c:1088
list get_stmt_index_coeff(int stmt, hash_table StoL)
========================================================================
Definition: utils.c:792
Psysteme completer_base(Psysteme sys, list var_l, list par_l)
========================================================================
Definition: utils.c:832
bool vecteurs_libres_p(Psysteme sys, Pbase v_base, Pbase c_base)
========================================================================
Definition: utils.c:903
hash_table StmtToPdim
Mapping from a statement (int) to its prototype.
Definition: prgm_mapping.c:107
bool solve_system_by_succ_elim(Psysteme sys, list *sigma)
========================================================================
Psysteme broadcast_dimensions(placement pla, list mu_list)
=========================================================================
hash_table DtfToSink
The number of dataflows in the DFG.
Definition: prgm_mapping.c:103
plc pfunc
Internal variables
Definition: prgm_mapping.c:98
hash_table StmtToMu
Mapping from a stmt to its lambda coeff.
Definition: prgm_mapping.c:111
hash_table StmtToLamb
Mapping from a stmt to its iteration space dim.
Definition: prgm_mapping.c:110
bdt the_bdt
The data flow graph.
Definition: prgm_mapping.c:100
#define NORMALIZE_EXPRESSION(e)
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define predicate_undefined
Definition: ri.h:2046
#define expression_normalized(x)
Definition: ri.h:1249
#define normalized_linear(x)
Definition: ri.h:1781
#define predicate_system(x)
Definition: ri.h:2069
struct Ssysteme * Psysteme
Psysteme sc_make(Pcontrainte leg, Pcontrainte lineg)
Psysteme sc_make(Pcontrainte leg, Pcontrainte lineg): allocation et initialisation d'un systeme d'equ...
Definition: sc.c:78
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_rm(Psysteme ps)
void sc_rm(Psysteme ps): liberation de l'espace memoire occupe par le systeme de contraintes ps;
Definition: sc_alloc.c:277
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
Psysteme sc_dup(Psysteme ps)
Psysteme sc_dup(Psysteme ps): should becomes a link.
Definition: sc_alloc.c:176
Psysteme sc_intersection(Psysteme s1, Psysteme s2, Psysteme s3)
Psysteme sc_intersection(Psysteme s1, Psysteme s2, Psysteme s3): calcul d'un systeme de contraintes s...
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
Psysteme sc_normalize(Psysteme ps)
Psysteme sc_normalize(Psysteme ps): normalisation d'un systeme d'equation et d'inequations lineaires ...
Definition: pip__tab.h:25
Pvecteur vecteur
struct Scontrainte * succ
Pcontrainte egalites
Definition: sc-local.h:70
Pbase base
Definition: sc-local.h:75
int nb_eq
Definition: sc-local.h:72
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
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: statement.c:54
#define VECTEUR_NUL
DEFINITION DU VECTEUR NUL.
struct Svecteur * Pvecteur
void * Variable
arithmetique is a requirement for vecteur, but I do not want to inforce it in all pips files....
Definition: vecteur-local.h:60
#define 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
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
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 fprint_vvs(FILE *fp, list vvs)
========================================================================
Definition: vvs.c:146