PIPS
interchange.c
Go to the documentation of this file.
1 /*
2 
3  $Id: interchange.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 
25 // do not compile unless required
26 #include "phases.h"
27 #ifdef BUILDER_LOOP_INTERCHANGE
28 
29 /* functions to perform loop interchange */
30 #ifdef HAVE_CONFIG_H
31  #include "pips_config.h"
32 #endif
33 
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 
38 #include "genC.h"
39 #include "linear.h"
40 
41 // obsolete linear librarices...
42 #include "matrice.h" // needed for sparse_sc
43 #include "sparse_sc.h" // sys_matrice_index / matrice_index_sys
44 
45 #include "misc.h"
46 
47 #include "ri.h"
48 #include "ri-util.h"
49 
50 #include "conversion.h" // various utils
51 #include "transformations.h" // interactive_loop_transformation
52 
54 
55 /* statement gener_DOSEQ(cons *lls,Pvecteur pvg[], Pbase base_oldindex,
56  * Pbase base_newindex)
57  * generation of loops interchange code for the nested loops (cons *lls).
58  * the new nested loops will be ;
59  * DOSEQ Ip = ...
60  * DOSEQ Jp = ...
61  * DOSEQ Kp = ...
62  * ...
63  * ENDDO
64  */
65 static statement
66 gener_DOSEQ(
67  list lls,
68  Pvecteur *pvg,
69  Pbase base_oldindex,
70  Pbase base_newindex,
72 {
73  statement state_lhyp = statement_undefined;
75  loop l_old = loop_undefined;
76  loop l_hyp = loop_undefined;
82  Pbase pb = BASE_NULLE;
83 
85  statement_newbase(bl,pvg,base_oldindex);
86  /* make the parallel loops from inner loop to upper loop*/
87 
88  for(pb=base_reversal(base_newindex);lls!=NIL; lls=CDR(lls)) {
89  /* traitement of current loop */
90  s_loop = STATEMENT(CAR(lls));
91  l_old = instruction_loop(statement_instruction(s_loop));
92 
93  /*new bounds de new index correspondant a old index de cet loop*/
94  make_bound_expression(pb->var,base_newindex,sc_newbase,&lower,&upper);
95  rl = make_range(lower,upper,int_to_expression(1));
96 
97 
98  if (CDR(lls)!=NULL) {
99  /* make the inner sequential loops
100  they will be the inner parallel loops after
101  integration the phase of parallelization*/
102  l_hyp = make_loop(pb->var,
103  rl,
104  bl,
105  loop_label(l_old),
107  loop_locals(l_old));
108  bl = makeloopbody(l_hyp,s_loop, true);
109  pb=pb->succ;
110  }
111  }
112 
113  /* Make the last outer loop which is sequential and can be labelled */
114 
115  l_hyp = make_loop(pb->var,rl,bl,loop_label(l_old),
117  loop_locals(l_old));
118  instr_lhyp = make_instruction(is_instruction_loop,l_hyp);
119  state_lhyp = make_statement(statement_label(s_loop),
120  statement_number(s_loop),
121  statement_ordering(s_loop),
122  statement_comments(s_loop),
123  instr_lhyp,NIL,NULL,
125  return(state_lhyp);
126 }
127 
128 /* Implementation of the loops interchange method. The outer most loop
129  * is exchanged with the inner most one. The legality of the
130  * transformation is not checked against the data dependencies nor
131  * against the control flow nor against the local declarations.
132  *
133  * "lls" is the list of nested loops. The user loop selection is used to
134  * build lls, a list of loop statements. The innermost loop is first
135  * in lls and the outermost loop is last in lls.
136  *
137  * If the innermost and outermost loops have the same loop label, the
138  * code generation is OK.
139  *
140  * If neither the innermost nor the outermost loop has a loop label,
141  * the code generation is OK.
142  *
143  * If both loops have different non-empty labels, the innermost label
144  * must be preserved in case it is the target of a goto. And the
145  * outermost loop label, if any, has to be moved inside the nested
146  * loop body. So the initial innermost loop must be made labelless.
147  *
148  * Note: the initial outermost loop label cannot be the target of a
149  * goto because the loop nest would not be a loop nest after
150  * controlization.
151  *
152  * FI: should be replaced by interchange_two_loops(lls, 1, n)
153  * FI: used to be called "interchange()"
154  */
155 
157  __attribute__((unused)) bool (*unused)(statement))
158 {
159  int n = gen_length(lls);
160  /* might be 0 and n-1*/
161  statement s = interchange_two_loops(lls, 1, n);
162  return s;
163 }
164 
165 #if 0
166 static statement old_interchange_inner_outermost_loops(list lls,
167  __attribute__((unused)) bool (*unused)(statement))
168 {
169  Psysteme sci; /* sc initial */
170  Psysteme scn; /* sc nouveau */
171  Psysteme sc_row_echelon;
173  Pbase base_oldindex = NULL;
174  Pbase base_newindex = NULL;
175  matrice A;
176  matrice G;
177  matrice AG;
178  int n ; /* number of indices */
179  int m ; /* number of constraints */
180  statement s_lhyp;
181  Pvecteur *pvg;
182  Pbase pb;
183  expression lower, upper;
184  Pvecteur pv1, pv2;
185  loop l;
186  /* Initially, the outermost loop. Stays the outermost loop. */
187  loop oml =
189  /* The initial outermost loop label */
190  entity omll = loop_label(oml);
191  /* Initially, the innermost loop. Stays the innermost loop. */
192  loop iml =
194  /* The initial innermost loop label */
195  entity imll = loop_label(iml);
196 
197  debug_on("LOOP_INTERCHANGE_DEBUG_LEVEL");
198  pips_debug(8,"begin:\n");
199 
200  /* make the system "sc" of constraints of iteration space */
201  sci = loop_iteration_domaine_to_sc(lls, &base_oldindex);
202 
203  /* create the matrix A of coefficients of index in (Psysteme)sci */
204  n = base_dimension(base_oldindex);
205  m = sci->nb_ineq;
206  A = matrice_new(m,n);
207  sys_matrice_index(sci, base_oldindex, A, n, m);
208 
209  /* computation of the matrix of basis change for loops interchange */
210  G = matrice_new(n,n);
211  matrice_identite(G,n,0);
212  matrice_swap_columns(G,n,n,1,n);
213 
214  /* the new matrice of constraints AG = A * G */
215  AG = matrice_new(m,n);
216  matrice_multiply(A,G,AG,m,n,n);
217 
218  /* create the new system of constraintes (Psysteme scn) with
219  AG and sci */
220  scn = sc_dup(sci);
221  matrice_index_sys(scn,base_oldindex,AG,n,m);
222 
223  /* computation of the new iteration space in the new basis G */
224  sc_row_echelon = new_loop_bound(scn,base_oldindex);
225 
226  /* change of basis for index */
227  change_of_base_index(base_oldindex,&base_newindex);
228  sc_newbase=sc_change_baseindex(sc_dup(sc_row_echelon),
229  base_oldindex,base_newindex);
230 
231  /* generation of interchange code */
232  /* generation of bounds */
233  for (pb=base_newindex; pb!=NULL; pb=pb->succ) {
234  make_bound_expression(pb->var,base_newindex,sc_newbase,&lower,&upper);
235  }
236 
237  /* loop body generation */
238  pvg = (Pvecteur *)malloc((unsigned)n*sizeof(Svecteur));
239  scanning_base_to_vect(G,n,base_newindex,pvg);
240  pv1 = sc_row_echelon->inegalites->succ->vecteur;
241  pv2 = vect_change_base(pv1,base_oldindex,pvg);
242 
244  lower = range_upper(loop_range(l));
245  upper= expression_to_expression_newbase(lower, pvg, base_oldindex);
246 
247 
248  s_lhyp = gener_DOSEQ(lls,pvg,base_oldindex,base_newindex,sc_newbase);
249 
250  /* Fix Fortran loop labels. Should this be made part of gener_DOSEQ? */
252  && (!entity_empty_label_p(omll) || gen_length(lls)>2)
253  && omll!=imll) {
254  /* A corresponding continue should be added to the loop nest
255  body, the body of the initial innermost loop , iml */
256  statement nlb = loop_body(iml);
257  /* The initial continue statements are assumed lost when lls is
258  built and transformed. */
259  list lll = CONS(ENTITY, imll, NIL); // loop label list
260  FOREACH(STATEMENT, ls, CDR(lls)) {
261  entity ll = loop_label(statement_loop(ls));
262  if(!entity_empty_label_p(ll) && !gen_in_list_p(ll, lll)) {
264  insert_statement(nlb, cs, false);
265  lll = CONS(ENTITY, ll, lll);
266  }
267  }
268  /* get rid of the innermost loop label? */
269  //loop_label(iml) = entity_empty_label();
270  }
271 
272  pips_debug(8,"end\n");
273  debug_off();
274 
275  return s_lhyp;
276 }
277 #endif
278 
279 /* See comments for interchange_inner_outermost_loops(). Continue
280  statements for loop labels are not fixed. */
281 statement interchange_two_loops(list lls, int n1, int n2)
282 {
283  Psysteme sci; /* sc initial */
284  Psysteme scn; /* sc nouveau */
285  Psysteme sc_row_echelon;
287  Pbase base_oldindex = NULL;
288  Pbase base_newindex = NULL;
289  matrice A;
290  matrice G;
291  matrice AG;
292  int n = gen_length(lls); /* number of loops and loop indices */
293  int m ; /* number of constraints */
294  statement s_lhyp;
295  Pvecteur *pvg;
296  Pbase pb;
297  expression lower, upper;
298  Pvecteur pv1 ;
299  loop l;
300  statement s1 = STATEMENT(gen_nth(n1-1,lls));
301  statement s2 = STATEMENT(gen_nth(n2-1,lls));
302  loop l1 = statement_loop(s1);
303  loop l2 = statement_loop(s2);
304  entity ll1 = loop_label(l1);
305  entity ll2 = loop_label(l2);
306  //execution e1 = copy_execution(loop_execution(l1));
307  //execution e2 = copy_execution(loop_execution(l2));
308  execution e[n];
309 
310  debug_on("LOOP_INTERCHANGE_DEBUG_LEVEL");
311  pips_debug(8,"\n begin: n1=%d, n2=%d\n", n1, n2);
312 
313  /* Preserve the parallelism information */
314  int ln = 0;
315  FOREACH(STATEMENT, ls, lls) {
316  loop l = statement_loop(ls);
317  e[ln] = copy_execution(loop_execution(l));
318  ln++;
319  }
320 
321  /* Build the system "sci" with the constraints of the iteration
322  space defined by lls */
323  sci = loop_iteration_domaine_to_sc(lls, &base_oldindex);
324 
325  /* create the matrix A of coefficients for the loop indices in
326  (Psysteme)sci */
327  n = base_dimension(base_oldindex);
328  m = sci->nb_ineq;
329  A = matrice_new(m,n);
330  sys_matrice_index(sci, base_oldindex, A, n, m);
331 
332  /* Computate of the unimodular matrix for loop interchange */
333  G = matrice_new(n,n);
334  matrice_identite(G,n,0);
335  matrice_swap_columns(G,n,n, n1, n2);
336 
337  /* the new matrice of constraints AG = A * G */
338  AG = matrice_new(m,n);
339  matrice_multiply(A,G,AG,m,n,n);
340 
341  /* create the new system of constraintes (Psysteme scn) with AG
342  and sci */
343  scn = sc_dup(sci);
344  matrice_index_sys(scn,base_oldindex,AG,n,m);
345 
346  /* computation of the new iteration space in the new basis G */
347  sc_row_echelon = new_loop_bound(scn,base_oldindex);
348 
349  /* changeof basis for index */
350  change_of_base_index(base_oldindex,&base_newindex);
351  sc_newbase =
352  sc_change_baseindex(sc_dup(sc_row_echelon),
353  base_oldindex,base_newindex);
354 
355  /* generation of interchange code */
356  /* generation of bounds */
357  for (pb=base_newindex; pb!=NULL; pb=pb->succ) {
358  make_bound_expression(pb->var,base_newindex,sc_newbase,&lower,&upper);
359  }
360 
361  /* loop body generation */
362  pvg = (Pvecteur *)malloc((unsigned)n*sizeof(Svecteur));
363  scanning_base_to_vect(G,n,base_newindex,pvg);
364  pv1 = sc_row_echelon->inegalites->succ->vecteur;
365  (void)vect_change_base(pv1,base_oldindex,pvg);
366 
368  lower = range_upper(loop_range(l));
369  upper= expression_to_expression_newbase(lower, pvg, base_oldindex);
370 
371 
372  s_lhyp = gener_DOSEQ(lls,pvg,base_oldindex,base_newindex,sc_newbase);
373 
374  /* Fix Fortran loop labels. Should this be made part of gener_DOSEQ? */
376  && (!entity_empty_label_p(ll2) || gen_length(lls)>2)
377  && ll1!=ll2) {
378  /* A corresponding continue should be added to the loop nest
379  body, the body of the initial innermost loop , iml */
380  list nlsl = statement_to_loop_statement_list(s_lhyp);
381  loop iml = statement_loop(STATEMENT(CAR(gen_last(nlsl))));
382  statement nlb = loop_body(iml);
383  /* The initial continue statements are assumed lost when lls is
384  built and transformed, except for the innermost loop. */
385  entity imll = loop_label(iml);
386  list lll = CONS(ENTITY, imll, NIL); // loop label list
387  nlsl = gen_nreverse(nlsl);
388  FOREACH(STATEMENT, ls, nlsl) {
389  entity ll = loop_label(statement_loop(ls));
390  if(!entity_empty_label_p(ll) && !gen_in_list_p(ll, lll)) {
392  insert_statement(nlb, cs, false);
393  lll = CONS(ENTITY, ll, lll);
394  }
395  }
396  gen_free_list(nlsl);
397  gen_free_list(lll);
398  /* get rid of the innermost loop label? */
399  //loop_label(iml) = entity_empty_label();
400  }
401 
402  /* Add the parallelism information */
403  ln = 0;
404  list nlsl = statement_to_loop_statement_list(s_lhyp);
405  pips_assert("The loop list retrieved has the expected lenght",
406  ((int) gen_length(nlsl))==n);
407  FOREACH(STATEMENT, ls, nlsl) {
408  loop l = statement_loop(ls);
410  if(ln==n1-1)
411  loop_execution(l) = e[n2-1];
412  else if(ln==n2-1)
413  loop_execution(l) = e[n1-1];
414  else
415  loop_execution(l) = e[ln];
416  ln++;
417  }
418 
419  pips_assert("Statement s_lhyp is consistent",
420  statement_consistent_p(s_lhyp));
421 
422  pips_debug(8, "end\n");
423  debug_off();
424 
425  return s_lhyp;
426 }
427 
428 bool loop_interchange(const string module_name)
429 {
430  bool return_status = false;
431 
432  return_status =
435 
436  return return_status;
437 }
438 
439 #endif // BUILDER_LOOP_INTERCHANGE
float a2sf[2] __attribute__((aligned(16)))
USER generates a user error (i.e., non fatal) by printing the given MSG according to the FMT.
Definition: 3dnow.h:3
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
bool statement_consistent_p(statement p)
Definition: ri.c:2195
statement make_statement(entity a1, intptr_t a2, intptr_t a3, string a4, instruction a5, list a6, string a7, extensions a8, synchronization a9)
Definition: ri.c:2222
instruction make_instruction(enum instruction_utype tag, void *val)
Definition: ri.c:1166
void free_execution(execution p)
Definition: ri.c:798
synchronization make_synchronization_none(void)
Definition: ri.c:2424
execution copy_execution(execution p)
EXECUTION.
Definition: ri.c:795
range make_range(expression a1, expression a2, expression a3)
Definition: ri.c:2041
Pbase base_reversal(Pbase b_in)
Pbase base_reversal(Pbase b_in): produces a basis b_out, having the same basis vectors as b_in,...
Definition: base.c:221
void change_of_base_index(Pbase base_oldindex, Pbase *base_newindex)
void change_of_base_index(Pbase base_oldindex, Pbase *base_newindex) change of variable index from ba...
Psysteme sc_change_baseindex(Psysteme sc, Pbase base_old, Pbase base_new)
Psysteme sc_change_baseindex(Psysteme sc, Pbase base_old, Pbase base_new) le changement de base d'ind...
expression expression_to_expression_newbase(expression e_old, pvg, Pbase base_oldindex)
expression expression_to_expression_newbase(expression e_old,Pvecteur pvg[], Pbase base_oldindex) com...
Pvecteur vect_change_base(Pvecteur pv_old, Pbase base_oldindex, pvg)
Pvecteur vect_change_base(Pvecteur pv_old, Pvecteur pvg[], Pbase base_oldindex, Pbase base_newindex) ...
void scanning_base_to_vect(matrice G, int n, Pbase base, pvg)
void scanning_base_to_vect(matrice G,int n,Pbase base,Pvecteur pvg[n]) compute G*base and put the res...
void statement_newbase(statement s, pvg, Pbase base_oldindex)
statement_newbase(statement s, Pvecteur pvg[], Pbase base_oldindex) compute the new statement by perf...
#define A(i, j)
comp_matrice.c
Definition: comp_matrice.c:63
Psysteme loop_iteration_domaine_to_sc(list, Pbase *)
loop_iteration_domaine_to_sc.c
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
void * malloc(YYSIZE_T)
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
list statement_to_loop_statement_list(statement s)
If statement s is a perfectly loop nest, return the corresponding loop list.
Definition: loop.c:893
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
#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
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
list gen_last(list l)
Return the last element of a list.
Definition: list.c:578
bool gen_in_list_p(const void *vo, const list lx)
tell whether vo belongs to lx
Definition: list.c:734
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
gen_chunk gen_nth(int n, const list l)
to be used as ENTITY(gen_nth(3, l))...
Definition: list.c:710
loop statement_loop(statement)
Get the loop of a statement.
Definition: statement.c:1374
statement makeloopbody(loop, statement, bool)
statement makeloopbody(l, s_old) make a statement for a loop body, using the fields of a previously e...
Definition: statement.c:1641
void insert_statement(statement, statement, bool)
This is the normal entry point.
Definition: statement.c:2570
statement make_continue_statement(entity)
Definition: statement.c:953
Psysteme sc_newbase
include <sys/ddi.h>
bool interactive_loop_transformation(const char *module_name, statement(*loop_transformation)(list, bool(*)(statement)))
#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_multiply(matrice a, matrice b, matrice c, int p, int q, int r)
void matrice_multiply(matrice a, matrice b, matrice c, int p, int q, int r): multiply rational matrix...
Definition: matrice.c:82
void matrice_swap_columns(matrice matrix, int n, int m, int c1, int c2)
void matrice_swap_columns(matrice matrix, int n, int m, int c1, int c2): exchange columns c1,...
Definition: matrice.c:200
void matrice_identite(matrice, int, int)
void matrice_identite(matrice ID, int n, int level) Construction d'une sous-matrice identite dans ID(...
Definition: sous-matrice.c:322
#define debug_on(env)
Definition: misc-local.h:157
#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 debug_off()
Definition: misc-local.h:160
#define UU
Definition: newgen_types.h:98
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,...
bool entity_empty_label_p(entity e)
Definition: entity.c:666
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
bool c_language_module_p(entity m)
Definition: module.c:447
#define loop_body(x)
Definition: ri.h:1644
#define loop_execution(x)
Definition: ri.h:1648
#define loop_undefined
Definition: ri.h:1612
#define range_upper(x)
Definition: ri.h:2290
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define instruction_loop(x)
Definition: ri.h:1520
#define statement_ordering(x)
Definition: ri.h:2454
#define range_undefined
Definition: ri.h:2263
#define instruction_undefined
Definition: ri.h:1454
#define statement_label(x)
Definition: ri.h:2450
#define expression_undefined
Definition: ri.h:1223
@ is_instruction_loop
Definition: ri.h:1471
#define statement_extensions(x)
Definition: ri.h:2464
#define loop_label(x)
Definition: ri.h:1646
#define loop_locals(x)
Definition: ri.h:1650
#define statement_instruction(x)
Definition: ri.h:2458
#define statement_comments(x)
Definition: ri.h:2456
#define loop_range(x)
Definition: ri.h:1642
@ is_execution_sequential
Definition: ri.h:1189
#define statement_number(x)
Definition: ri.h:2452
#define statement_undefined
Definition: ri.h:2419
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
Psysteme sc_dup(Psysteme ps)
Psysteme sc_dup(Psysteme ps): should becomes a link.
Definition: sc_alloc.c:176
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...
#define G(j, a, b)
maybe most of them should be functions?
s1
Definition: set.c:247
void sys_matrice_index(Psysteme, Pbase, matrice, int, int)
Warning! Do not modify this file that is automatically generated!
void matrice_index_sys(Psysteme, Pbase, matrice, int, int)
void matrice_index_sys(Psysteme sc, Pbase base_index, matrice AG, int n, int m) replace the coefficie...
Definition: pip__tab.h:25
Pvecteur vecteur
struct Scontrainte * succ
Pcontrainte inegalites
Definition: sc-local.h:71
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
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
statement interchange_two_loops(list, int, int)
bool loop_interchange(const string)
statement interchange_inner_outermost_loops(list, bool(*)(statement))
interchange.c
#define base_dimension(b)
#define BASE_NULLE
MACROS SUR LES BASES.
struct Svecteur Svecteur
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique