PIPS
align-checker.c
Go to the documentation of this file.
1 /*
2 
3  $Id: align-checker.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 /* Align Checker
28  *
29  * try to decide whether two references are aligned or not.
30  * if not, gives back the alignement shift vector of the
31  * second reference to the first one.
32  *
33  * this should use use-def chains, vectors and so on
34  *
35  * Fabien Coelho August 93
36  */
37 
38 #include "defines-local.h"
39 #include "prettyprint.h" // for print_expression, print_reference
40 #include "access_description.h"
41 #include "effects-generic.h"
42 #include "effects-simple.h"
43 #include "effects-convex.h"
44 
45 GENERIC_STATIC_OBJECT(extern, hpfc_current_statement, statement)
46 
47 #define REGION_TYPE EFFECT_TYPE
48 
49 static bool
51  entity e)
52 {
53  MAP(REGION, r,
54  if (region_entity(r)==e && region_write_p(r)) return true,
56 
57  return false;
58 }
59 
60 /* true is the expression is locally constant, that is in the whole loop nest,
61  * the reference is not written. ??? not very portable thru pips...
62  */
63 bool
65  expression e)
66 {
68 
69  if ((syntax_reference_p(s)) &&
71  {
73  if (write_on_entity_p(ent)) return false;
74  }
75 
76  return true;
77 }
78 
79 /* true if the expression is shift function
80  * of a loop nest index.
81  */
82 static bool shift_expression_of_loop_index_p(e, pe, pi)
83 expression e;
84 entity *pe;
85 int *pi;
86 {
88 
89  pips_assert("normalized", !normalized_undefined_p(n));
90 
91  switch (normalized_tag(n))
92  {
94  return(false);
95  break;
97  {
99  int s = vect_size(vp);
100  bool result;
101 
102  if (s!=1) return false;
103 
104  result = entity_loop_index_p((entity)var_of(vp)) &&
105  value_one_p(val_of(vp));
106 
107  if (result)
108  {
109  Value vi = vect_coeff(TCST, v);
110  *pe = (entity) var_of(vp);
111  *pi = VALUE_TO_INT(vi);
112  }
113 
114  vect_rm(vp);
115 
116  return result;
117  break;
118  }
119  default:
120  pips_internal_error("unexpected normalized tag");
121  break;
122  }
123 
124  return false; /* just to avoid a gcc warning */
125 }
126 
127 /* true if the expression is an affine function
128  * of a loop nest index.
129  */
130 static bool affine_expression_of_loop_index_p(e, pe, pi1, pi2)
131 expression e;
132 entity *pe;
133 int *pi1, *pi2;
134 {
136 
137  ifdebug(6)
138  {
139  fprintf(stderr, "[affine_expression_of_loop_index_p]\nexpression:\n");
140  print_expression(e);
141  }
142 
143  pips_assert("normalized", !normalized_undefined_p(n));
144 
145  switch (normalized_tag(n))
146  {
148  return(false);
149  break;
151  {
153  vp = vect_del_var(v, TCST);
154  int s = vect_size(vp);
155  bool result;
156 
157  if (s!=1) return(false);
158 
159  result = (entity_loop_index_p((entity)var_of(vp)) &&
160  value_notone_p(val_of(vp)));
161 
162  if (result)
163  {
164  Value v1 = vect_coeff(TCST, v);
165  *pe = (entity) var_of(vp);
166  *pi1 = VALUE_TO_INT(v1);
167  *pi2 = VALUE_TO_INT(val_of(vp));
168  }
169 
170  vect_rm(vp);
171 
172  return result;
173  break;
174  }
175  default:
176  pips_internal_error("unexpected normalized tag");
177  break;
178  }
179 
180  return(false); /* just to avoid a gcc warning */
181 }
182 
183 /* computes the shift vector that links the two references,
184  * true if every thing is ok, i.e. the vector is ok for the
185  * distributed dimensions...
186  * The vector considered here is just a list of integers.
187  * conditions: same template
188  */
189 bool
191  reference r1,
192  reference r2,
193  list *plvect,
194  list *plkind)
195 {
196  int procdim, i, ne2dim;
197  entity e1, e2;
198  align a1, a2;
199  bool ok = true;
200  list li1, li2;
201 
202  e1 = reference_variable(r1),
203  e2 = reference_variable(r2);
204  a1 = load_hpf_alignment(e1),
205  a2 = load_hpf_alignment(e2);
206  li1 = reference_indices(r1),
207  li2 = reference_indices(r2);
208  *plvect = NIL;
209  *plkind = NIL;
210 
211  pips_debug(7, "with references to %s[DIM=%zd] and %s[DIM=%zd]\n",
212  entity_name(e1), gen_length(li1), entity_name(e2), gen_length(li2));
213 
214  ne2dim = NumberOfDimension(e2);
215 
217  {
218  pips_debug(5, "different templates\n");
219 
220  for (i=1 ; i<=ne2dim ; i++)
221  if (ith_dim_distributed_p(e2, i, &procdim))
222  {
223  *plkind = gen_nconc(*plkind, CONS(INT, not_aligned, NIL));
224  *plvect = gen_nconc(*plvect, CONS(PVECTOR,
225  (VECTOR) VECTEUR_NUL, NIL));
226  }
227  else
228  {
229  *plkind = gen_nconc(*plkind, CONS(INT, local_star, NIL));
230  *plvect = gen_nconc(*plvect, CONS(PVECTOR,
231  (VECTOR) VECTEUR_NUL, NIL));
232  }
233 
234  return ok;
235  }
236 
237  ifdebug(8)
238  {
239  fprintf(stderr, "[align_check] references are: ");
240  print_reference(r1);
241  fprintf(stderr, " and ");
242  print_reference(r2);
243  fprintf(stderr, "\n");
244  }
245 
246  for (i=1 ; i<=ne2dim ; i++)
247  {
248  expression indice1, indice2;
249  int
250  affr1 = 1, /* default value, used in the shift case ! */
251  affr2 = 1,
252  shft1, shft2;
253  entity
254  index1 = NULL, /* default value, used in the const case ! */
255  index2 = NULL;
256  bool
257  baffin1, baffin2,
258  bshift1, bshift2,
259  bconst1, bconst2,
260  blcnst2=0;
261 
262  pips_debug(8, "considering dimension %d of %s\n", i, entity_name(e2));
263 
264  indice2 = EXPRESSION(gen_nth(i-1, li2));
265 
266  baffin2 = affine_expression_of_loop_index_p(indice2,
267  &index2, &shft2, &affr2);
268  bshift2 = shift_expression_of_loop_index_p(indice2, &index2, &shft2);
269  bconst2 = hpfc_integer_constant_expression_p(indice2, &shft2);
270  if (!(baffin2 || bshift2 || bconst2))
271  blcnst2 = local_integer_constant_expression(indice2);
272 
273  if (ith_dim_distributed_p(e2, i, &procdim))
274  {
275  alignment
276  a2 = FindArrayDimAlignmentOfArray(e2, i),
279  int
280  dim1=((a1!=alignment_undefined)?(alignment_arraydim(a1)):(-1)),
281  rate1, rate2,
282  cnst1, cnst2;
283 
284  rate2 = HpfcExpressionToInt(alignment_rate(a2));
286 
287  if ((dim1<0) || /* replication, say it is not aligned */
288  ((dim1==0) && (!bconst2))) /* replicated reference...*/
289  {
290  pips_debug(8, "%s[DIM=%d] not aligned aff %d shi %d cst %d\n",
291  entity_name(e2), i, baffin2, bshift2, bconst2);
292 
293  *plkind = gen_nconc(*plkind, CONS(INT, not_aligned, NIL));
294  *plvect = gen_nconc(*plvect, CONS(PVECTOR,
295  (VECTOR) VECTEUR_NUL, NIL));
296  }
297  else
298  if ((dim1==0) && (bconst2))
299  {
300  /* a(i) -> t(i,1), b(i,j)->t(i,j), should detect
301  * do i a(i) = b(i,1) as aligned...
302  *
303  * ??? this could be managed later in this function...
304  */
305 
307  t2 = rate2*shft2+cnst2;
308 
309  /* should be ok, even if a delta is induced, if it stays
310  * on the same processor along this dimension. The case
311  * should also be managed downward, when playing with
312  * local updates.
313  * ??? maybe there is also a consequence on the
314  * send/receive symetry, in order to put the message where it
315  * should be...
316  */
317 
318  /* it is checked later whether the data are on the same
319  * processor or not.
320  */
321 
322  *plkind = gen_nconc(*plkind, CONS(INT, aligned_constant, NIL));
323  *plvect = gen_nconc(*plvect,
324  CONS(PVECTOR, (VECTOR)
326  vect_new(DELTAV, int_to_value(t2-t1))),
327  NIL));
328  }
329  else
330  {
331  indice1 = EXPRESSION(gen_nth(dim1-1, li1));
332 
333  rate1 = HpfcExpressionToInt(alignment_rate(a1));
335 
337  (indice1, &index1, &shft1, &affr1);
339  (indice1, &index1, &shft1);
341  (indice1, &shft1);
342 
343  /* now we have everything to check whether it is aligned...
344  * and to compute the shift necessary to the overlap analysis.
345  */
346 
347  if (!((baffin1 || bshift1 || bconst1) &&
348  (baffin2 || bshift2 || bconst2)))
349  {
350  *plkind = gen_nconc(*plkind, CONS(INT, not_aligned, NIL));
351  *plvect = gen_nconc(*plvect, CONS(PVECTOR,(VECTOR)
352  VECTEUR_NUL, NIL));
353  }
354  else /* something is true! */
355  if (baffin1 || baffin2) /* just check whether aligned or not */
356  {
357  int
358  r1 = ((bconst1)?(0):(rate1*affr1)),
359  r2 = ((bconst2)?(0):(rate2*affr2)),
360  c1 = rate1*shft1+cnst1,
361  c2 = rate2*shft2+cnst2;
362 
363  /* even in the constant case ! not aligned */
364  if ((index1!=index2) ||
365  (r1!=r2) || (c1!=c2))
366  {
367  *plkind =
368  gen_nconc(*plkind, CONS(INT, not_aligned, NIL));
369  *plvect =
370  gen_nconc(*plvect, CONS(PVECTOR,
371  (VECTOR) VECTEUR_NUL, NIL));
372  }
373  else /* aligned... ???
374  * bug if not 1: later on, because decl shift
375  */
376  {
377  *plkind =
378  gen_nconc(*plkind, CONS(INT, aligned_star, NIL));
379  *plvect =
380  gen_nconc(*plvect, CONS(PVECTOR,
381  (VECTOR) VECTEUR_NUL, NIL));
382  }
383  }
384  else /* 4 cases study with bconst and bshift, plus the rates */
385  if (bconst1 && bconst2)
386  {
387  int
388  t1 = (rate1*shft1+cnst1),
389  t2 = (rate2*shft2+cnst2),
390  d = (t2-t1);
391 
392  /* what should be the relevent information(s) ???
393  * not only d, but shift2 and t2 may be usefull either
394  * ??? what about rates!=1 ? decl shift problem added.
395  */
396 
397  *plkind =
398  gen_nconc(*plkind, CONS(INT, aligned_constant, NIL));
399  *plvect =
400  gen_nconc(*plvect,
401  CONS(PVECTOR, (VECTOR)
403  DELTAV, int_to_value(d),
404  TEMPLATEV, int_to_value(t2),
405  TCST, int_to_value(shft2)),
406  NIL));
407  }
408  else /* say not aligned... */
409  if ((rate1!=1) || (rate2!=1) || (index1!=index2))
410  {
411  *plkind = gen_nconc(*plkind,
412  CONS(INT, not_aligned, NIL));
413  *plvect = gen_nconc(*plvect,
415  }
416  else
417  if (bshift1 && bshift2)
418  {
419  /* ??? decl shift problem may occur here as well */
420  int
421  tc1 = (shft1+cnst1),
422  tc2 = (shft2+cnst2),
423  shift = (tc2-tc1);
424 
425  *plkind = gen_nconc(*plkind, CONS(INT, aligned_shift, NIL));
426  *plvect = gen_nconc
427  (*plvect,
428  CONS(PVECTOR, (VECTOR)
430  TSHIFTV, int_to_value(shift),
431  (Variable) index1, VALUE_ONE,
432  TCST, int_to_value(shft2)),
433  NIL));
434  }
435  else /* ??? I should do something with blcnst2? */
436  {
437  /* well, say not aligned, but one to many or many to one
438  * communications may be used...
439  */
440  *plkind =
441  gen_nconc(*plkind, CONS(INT, not_aligned, NIL));
442  *plvect =
443  gen_nconc(*plvect,
445  }
446  }
447  }
448  else /* ith dimension of e2 is not distributed */
449  {
450  if (!(baffin2 || bshift2 || bconst2 || blcnst2))
451  {
452  *plkind = gen_nconc(*plkind, CONS(INT, local_star, NIL));
453  *plvect = gen_nconc(*plvect,
455  }
456  else
457  if (baffin2) /* may be used to generate RSDs */
458  {
459  *plkind = gen_nconc(*plkind, CONS(INT, local_affine, NIL));
460  *plvect =
461  gen_nconc(*plvect,
462  CONS(PVECTOR, (VECTOR)
464  (Variable) index2, int_to_value(affr2),
465  TCST, int_to_value(shft2)),
466  NIL));
467  }
468  else
469  if (bshift2)
470  {
471  *plkind = gen_nconc(*plkind, CONS(INT, local_shift, NIL));
472  *plvect =
473  gen_nconc(*plvect,
474  CONS(PVECTOR, (VECTOR)
476  (Variable) index2, VALUE_ONE,
477  TCST, int_to_value(shft2)),
478  NIL));
479  }
480  else
481  if (bconst2)
482  {
483  *plkind = gen_nconc(*plkind, CONS(INT, local_constant, NIL));
484  *plvect = gen_nconc(*plvect, CONS(PVECTOR, (VECTOR)
485  vect_new(TCST, int_to_value(shft2)),
486  NIL));
487  }
488  /* else the local constant should be detected, for onde24... */
489  else
490  if (blcnst2)
491  {
492  *plkind = gen_nconc(*plkind, CONS(INT, local_form_cst, NIL));
493  *plvect =
494  gen_nconc(*plvect,
495  CONS(PVECTOR, (VECTOR)
497  NIL));
498  }
499  }
500  }
501 
502  ifdebug(8)
503  {
504  list l;
505  fprintf(stderr, "[align_check] returning: ");
506  for (l=*plkind; l; POP(l))
507  fprintf(stderr, "%"PRIdPTR", ", INT(CAR(l)));
508  fprintf(stderr, "\n");
509  }
510 
511  return ok;
512 }
513 
515 expression e;
516 int *pi;
517 {
519 
520  if (normalized_undefined_p(n))
521  {
522  n = NORMALIZE_EXPRESSION(e);
523  }
524 
525  switch (normalized_tag(n))
526  {
528  return(false);
529  break;
531  {
533  vp = vect_del_var(v, TCST);
534  int s = vect_size(vp);
535  bool result = (s==0);
536 
537  vect_rm(vp);
538 
539  if (result)
540  {
541  Value vi = vect_coeff(TCST, v);
542  *pi = VALUE_TO_INT(vi);
543  }
544 
545  return(result);
546  break;
547  }
548  default:
549  pips_internal_error("unexpected normalized tag");
550  break;
551  }
552 
553  return(false); /* just to avoid a gcc warning */
554 }
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
#define local_affine
#define aligned_shift
#define not_aligned
#define aligned_star
#define local_form_cst
#define aligned_constant
#define local_star
#define local_constant
#define local_shift
bool local_integer_constant_expression(expression e)
true is the expression is locally constant, that is in the whole loop nest, the reference is not writ...
Definition: align-checker.c:64
static bool affine_expression_of_loop_index_p(expression e, entity *pe, int *pi1, int *pi2)
true if the expression is an affine function of a loop nest index.
static bool write_on_entity_p(entity e)
Definition: align-checker.c:50
bool align_check(reference r1, reference r2, list *plvect, list *plkind)
computes the shift vector that links the two references, true if every thing is ok,...
bool hpfc_integer_constant_expression_p(expression e, int *pi)
static bool shift_expression_of_loop_index_p(expression e, entity *pe, int *pi)
true if the expression is shift function of a loop nest index.
Definition: align-checker.c:82
#define int_to_value(i)
end LINEAR_VALUE_IS_INT
#define VALUE_TO_INT(val)
#define value_notone_p(val)
#define value_one_p(val)
int Value
#define VALUE_ONE
@ INT
Definition: atomic.c:48
bool entity_loop_index_p(entity e)
bool conformant_templates_p(entity t1, entity t2)
Definition: dynamic.c:405
#define region_write_p(reg)
#define region_entity(reg)
#define REGION
list load_statement_local_regions(statement)
#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
gen_chunk gen_nth(int n, const list l)
to be used as ENTITY(gen_nth(3, l))...
Definition: list.c:710
#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
#define alignment_templatedim(x)
Definition: hpf.h:136
#define alignment_undefined
Definition: hpf.h:108
#define alignment_constant(x)
Definition: hpf.h:140
#define align_template(x)
Definition: hpf.h:98
#define alignment_rate(x)
Definition: hpf.h:138
#define alignment_arraydim(x)
Definition: hpf.h:134
int HpfcExpressionToInt(expression e)
HpfcExpressionToInt(e)
Definition: hpfc-util.c:569
bool ith_dim_distributed_p(entity array, int i, int *pprocdim)
whether a dimension is distributed or not.
Definition: hpfc-util.c:160
#define FindArrayDimAlignmentOfArray(array, dim)
#define TEMPLATEV
Definition: defines-local.h:80
#define TSHIFTV
Definition: defines-local.h:81
#define FindTemplateDimAlignmentOfArray(array, dim)
#define DELTAV
??? very beurk!
Definition: defines-local.h:79
#define VECTOR
Definition: defines-local.h:73
#define PVECTOR(v)
Definition: defines-local.h:72
statement get_hpfc_current_statement(void)
align load_hpf_alignment(entity)
int vect_size(Pvecteur v)
package vecteur - reductions
Definition: reductions.c:47
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
#define GENERIC_STATIC_OBJECT(PREFIX, name, type)
Add the attribute ((unused)) for gcc to avoid warning if the functions are not used.
void print_expression(expression e)
no file descriptor is passed to make is easier to use in a debugging stage.
Definition: expression.c:58
void print_reference(reference r)
Definition: expression.c:142
#define NORMALIZE_EXPRESSION(e)
int NumberOfDimension(entity)
Definition: size.c:588
#define syntax_reference_p(x)
Definition: ri.h:2728
#define syntax_reference(x)
Definition: ri.h:2730
#define normalized_linear_p(x)
Definition: ri.h:1779
#define reference_variable(x)
Definition: ri.h:2326
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define entity_name(x)
Definition: ri.h:2790
#define normalized_tag(x)
Definition: ri.h:1778
#define expression_normalized(x)
Definition: ri.h:1249
#define reference_indices(x)
Definition: ri.h:2328
#define normalized_undefined_p(x)
Definition: ri.h:1746
#define normalized_linear(x)
Definition: ri.h:1781
#define expression_syntax(x)
Definition: ri.h:1247
@ is_normalized_linear
Definition: ri.h:1760
@ is_normalized_complex
Definition: ri.h:1761
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
#define ifdebug(n)
Definition: sg.c:47
static bool ok
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
#define TCST
VARIABLE REPRESENTANT LE TERME CONSTANT.
#define val_of(varval)
#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 var_of(varval)
Pvecteur vect_make(Pvecteur v, Variable var, Value val,...)
Pvecteur vect_make(v, [var, val,]* 0, val) Pvecteur v; // may be NULL, use assigne anyway Variable va...
Definition: alloc.c:165
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_del_var(Pvecteur v_in, Variable var)
Pvecteur vect_del_var(Pvecteur v_in, Variable var): allocation d'un nouveau vecteur egal a la project...
Definition: unaires.c:206
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