2 /**------ ( ----------------------------------------------------------**
4 **----- / ) --------------------------------------------------------**
5 ** ( * ( dependence.c **
6 **---- \#/ --------------------------------------------------------**
7 ** .-"#'-. First version: september 18th 2003 **
8 **--- |"-.-"| -------------------------------------------------------**
11 ******** | | *************************************************************
12 * CAnDL '-._,-' the Chunky Analyzer for Dependences in Loops (experimental) *
13 ******************************************************************************
15 * Copyright (C) 2003-2008 Cedric Bastoul *
17 * This is free software; you can redistribute it and/or modify it under the *
18 * terms of the GNU Lesser General Public License as published by the Free *
19 * Software Foundation; either version 3 of the License, or (at your option) *
20 * any later version. *
22 * This software is distributed in the hope that it will be useful, but *
23 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
24 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
27 * You should have received a copy of the GNU Lesser General Public License *
28 * along with software; if not, write to the Free Software Foundation, Inc., *
29 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
31 * CAnDL, the Chunky Dependence Analyzer *
32 * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr *
34 ******************************************************************************/
37 * \author Cedric Bastoul and Louis-Noel Pouchet
43 #include <candl/candl.h>
44 #include <candl/dependence.h>
45 #include <candl/scop.h>
46 #include <candl/statement.h>
47 #include <candl/util.h>
48 #include <candl/matrix.h>
49 #include <candl/piplib-wrapper.h>
50 #include <osl/macros.h>
52 #include <osl/statement.h>
53 #include <osl/relation.h>
54 #include <osl/names.h>
59 #ifdef CANDL_SUPPORTS_ISL
60 # undef Q // Thank you polylib...
62 # include <isl/constraint.h>
70 * candl_dependence_get_relation_ref_source_in_dep function:
71 * This function return the corresponding osl_relation_p of
75 candl_dependence_get_relation_ref_source_in_dep(osl_dependence_p tmp
) {
76 if (tmp
->ref_source_access_ptr
!= NULL
)
77 return tmp
->ref_source_access_ptr
;
79 osl_relation_p elt
= NULL
;
80 osl_relation_list_p access
;
81 access
= tmp
->stmt_source_ptr
->access
;
82 for (; access
!= NULL
; access
= access
->next
) {
84 if (count
== tmp
->ref_source
)
88 tmp
->ref_source_access_ptr
= elt
;
93 * candl_dependence_get_relation_ref_target_in_dep function:
94 * same as candl_dependence_get_relation_ref_source_in_dep but for the target
97 candl_dependence_get_relation_ref_target_in_dep(osl_dependence_p tmp
) {
98 if (tmp
->ref_target_access_ptr
!= NULL
)
99 return tmp
->ref_target_access_ptr
;
101 osl_relation_list_p access
;
102 osl_relation_p elt
= NULL
;
103 access
= tmp
->stmt_target_ptr
->access
;
104 for (; access
!= NULL
; access
= access
->next
) {
106 if (count
== tmp
->ref_target
)
110 tmp
->ref_target_access_ptr
= elt
;
117 * candl_dependence_get_array_refs_in_dep function:
118 * This function return the array indices referenced in the
121 void candl_dependence_get_array_refs_in_dep(osl_dependence_p tmp
,
122 int* refs
, int* reft
) {
126 osl_relation_p src
, targ
;
128 int precision
= tmp
->domain
->precision
;
130 src
= candl_dependence_get_relation_ref_source_in_dep(tmp
);
131 targ
= candl_dependence_get_relation_ref_target_in_dep(tmp
);
133 row
= candl_relation_get_line(src
, 0);
134 *refs
= osl_int_get_si(precision
,
138 row
= candl_relation_get_line(targ
, 0);
139 *reft
= osl_int_get_si(precision
,
145 /* osl_dependence_pprint function:
146 * This function prints the content of a osl_dependence_p structure (dependence)
147 * into a file (file, possibly stdout) as a Graphviz input file.
148 * See http://www.graphviz.org
149 * - 08/12/2005: first version.
151 void candl_dependence_pprint(FILE * file
, osl_dependence_p dependence
) {
154 fprintf(file
, "digraph G {\n");
156 fprintf(file
, "# Data Dependence Graph\n");
157 fprintf(file
, "# Generated by Candl "CANDL_RELEASE
" "CANDL_VERSION
" bits\n");
158 while (dependence
!= NULL
) {
159 fprintf(file
, " S%d -> S%d [label=\" ", dependence
->label_source
,
160 dependence
->label_target
);
161 switch (dependence
->type
) {
162 case OSL_UNDEFINED
: fprintf(file
, "UNSET"); break;
163 case OSL_DEPENDENCE_RAW
: fprintf(file
, "RAW") ; break;
164 case OSL_DEPENDENCE_WAR
: fprintf(file
, "WAR") ; break;
165 case OSL_DEPENDENCE_WAW
: fprintf(file
, "WAW") ; break;
166 case OSL_DEPENDENCE_RAR
: fprintf(file
, "RAR") ; break;
167 case OSL_DEPENDENCE_RAW_SCALPRIV
:
168 fprintf(file
, "RAW_SCALPRIV (scalar-priv)") ; break;
169 default : fprintf(file
, "unknown"); break;
171 fprintf(file
, " depth %d, ref %d->%d \"];\n", dependence
->depth
,
172 dependence
->ref_source
,
173 dependence
->ref_target
);
174 dependence
= dependence
->next
;
179 fprintf(file
, "# Number of edges = %i\n}\n", i
);
181 fprintf(file
, "}\n");
185 /* candl_dependence_view function:
186 * This function uses dot (see http://www.graphviz.org) and gv (see
187 * http://wwwthep.physik.uni-mainz.de/~plass/gv) tools to display the
189 * - 20/03/2006: first version.
191 void candl_dependence_view(osl_dependence_p dep
) {
193 temp_output
= fopen(CANDL_TEMP_OUTPUT
,"w+");
194 candl_dependence_pprint(temp_output
, dep
);
196 /* check the return to remove the warning compilation */
197 if(system("dot -Tps "CANDL_TEMP_OUTPUT
" | gv - && rm -f "CANDL_TEMP_OUTPUT
" &"))
202 #ifdef CANDL_SUPPORTS_ISL
204 struct isl_set
* isl_set_from_piplib_matrix(struct isl_ctx
* ctx
,
205 osl_relation_p matrix
,
207 osl_relation_p
isl_set_to_piplib_matrix(struct isl_ctx
* ctx
,
211 * candl_dependence_isl_simplify function:
213 * This function uses ISL to simplify the dependence polyhedra.
214 * Useful for polyhedra that contain large coefficient values.
217 osl_dependence_p
candl_dependence_isl_simplify(osl_dependence_p dep
,
219 if (dep
== NULL
|| scop
== NULL
)
222 osl_dependence_p tmp
;
223 osl_relation_p context
= scop
->context
;
224 int nparam
= context
->nb_parameters
;
226 struct isl_ctx
* ctx
= isl_ctx_alloc();
228 for (tmp
= dep
; tmp
; tmp
= tmp
->next
) {
229 // 1- Convert the dependence polyhedron into ISL set.
231 struct isl_set
* set
= isl_set_from_piplib_matrix(ctx
, tmp
->domain
, nparam
);
233 // 2- Simplify the ISL set.
234 set
= isl_set_detect_equalities(set
);
236 // 3- Convert back into Candl matrix representation.
237 osl_relation_p newdom
= isl_set_to_piplib_matrix(ctx
, set
, nparam
);
239 newdom
->nb_output_dims
= tmp
->domain
->nb_output_dims
;
240 newdom
->nb_input_dims
= tmp
->domain
->nb_input_dims
;
241 newdom
->nb_local_dims
= tmp
->domain
->nb_local_dims
;
242 newdom
->nb_parameters
= tmp
->domain
->nb_parameters
;
243 osl_relation_free(tmp
->domain
);
244 tmp
->domain
= newdom
;
247 /// FIXME: Some dead ref.
248 //isl_ctx_free (ctx);
256 /* candl_dependence_init_fields:
257 * Set the various other fields of the dependence structure
259 void candl_dependence_init_fields(osl_scop_p scop
, osl_dependence_p dep
) {
261 osl_statement_p iter
;
262 candl_statement_usr_p usr
;
263 osl_relation_p array_s
, array_t
;
265 /* source statement */
266 iter
= scop
->statement
;
267 for (; iter
!= NULL
; iter
= iter
->next
) {
269 if (usr
->label
== dep
->label_source
) {
270 dep
->stmt_source_ptr
= iter
;
275 fprintf(stderr
, "[Candl] Can't find the %dth label\n", dep
->label_source
);
279 /* target statement */
280 iter
= scop
->statement
;
281 for (; iter
!= NULL
; iter
= iter
->next
) {
283 if (usr
->label
== dep
->label_target
) {
284 dep
->stmt_target_ptr
= iter
;
289 fprintf(stderr
, "[Candl] Can't find the %dth label\n", dep
->label_target
);
293 array_s
= candl_dependence_get_relation_ref_source_in_dep(dep
);
294 if (array_s
== NULL
) {
295 fprintf(stderr
, "[Candl] Can't find the %dth access of the statement :\n",
297 osl_statement_dump(stderr
, dep
->stmt_source_ptr
);
301 array_t
= candl_dependence_get_relation_ref_source_in_dep(dep
);
302 if (array_t
== NULL
) {
303 fprintf(stderr
, "[Candl] Can't find the %dth access of the statement :\n",
305 osl_statement_dump(stderr
, dep
->stmt_target_ptr
);
309 dep
->source_nb_output_dims_domain
= dep
->stmt_source_ptr
->domain
->nb_output_dims
;
310 dep
->source_nb_output_dims_access
= array_s
->nb_output_dims
;
312 dep
->target_nb_output_dims_domain
= dep
->stmt_target_ptr
->domain
->nb_output_dims
;
313 dep
->target_nb_output_dims_access
= array_t
->nb_output_dims
;
315 dep
->source_nb_local_dims_domain
= dep
->stmt_source_ptr
->domain
->nb_local_dims
;
316 dep
->source_nb_local_dims_access
= array_s
->nb_local_dims
;
317 dep
->target_nb_local_dims_domain
= dep
->stmt_target_ptr
->domain
->nb_local_dims
;
318 dep
->target_nb_local_dims_access
= array_t
->nb_local_dims
;
325 static int candl_dependence_gcd(int a
, int b
) {
355 static int candl_dependence_gcd_test_context(osl_relation_p system
, int id
) {
356 /* FIXME: implement me! */
363 * candl_dependence_gcd_test function:
364 * This functions performs a GCD test on a dependence polyhedra
365 * represented exactly by a set of constraints 'system' organized in
367 * - first lines: iteration domain of 'source'
368 * - then: iteration domain of 'target'
369 * - then: array access equality(ies)
370 * - then (optional): precedence constraint inequality.
372 * The function returns false if the dependence is impossible, true
373 * otherwise. A series of simple checks (SIV/ZIV/MIV/bounds checking)
374 * are also performed before the actual GCD test.
377 int candl_dependence_gcd_test(osl_statement_p source
,
378 osl_statement_p target
,
379 osl_relation_p system
,
385 int null_iter
, null_param
, null_cst
, pos_iter
, neg_iter
;
386 int precision
= source
->domain
->precision
;
387 candl_statement_usr_p s_usr
= source
->usr
;
388 candl_statement_usr_p t_usr
= target
->usr
;
390 /* Check that the precedence constraint, if any, is not strict in a
392 /* int strict_pred; */
393 /* if (source == target && */
394 /* CANDL_get_si(system->p[system->NbRows - 1][0]) == 1 && */
395 /* CANDL_get_si(system->p[system->NbRows - 1][system->NbColumns - 1]) == -1) */
396 /* strict_pred = 1; */
398 /* strict_pred = 0; */
400 /* Inspect the array access function equalities. */
401 for (id
= source
->domain
->nb_rows
+ target
->domain
->nb_rows
;
402 id
< system
->nb_rows
&&
403 osl_int_zero(precision
, system
->m
[id
], 0);
405 /* Inspect which parts of the access function equality are null,
406 positive or negative. */
407 null_iter
= null_param
= null_cst
= pos_iter
= neg_iter
= 0;
409 for (i
= 1; i
< s_usr
->depth
+ t_usr
->depth
+ 1 &&
410 osl_int_zero(precision
, system
->m
[id
], i
); ++i
)
413 if (i
== s_usr
->depth
+ t_usr
->depth
+ 1)
416 for (pos_iter
= 1, neg_iter
= 1;
417 i
< s_usr
->depth
+ t_usr
->depth
+ 1; ++i
) {
418 if (osl_int_neg(precision
, system
->m
[id
], i
))
420 else if (osl_int_pos(precision
, system
->m
[id
], i
))
423 for (; i
< system
->nb_columns
- 1 &&
424 osl_int_zero(precision
, system
->m
[id
], i
) == 0; ++i
)
426 if (i
== system
->nb_columns
- 1)
428 null_cst
= osl_int_zero(precision
, system
->m
[id
], system
->nb_columns
- 1);
430 /* Some useful ZIV/SIV/MIV tests. */
431 if (null_iter
&& null_param
&& !null_cst
)
434 if (! candl_dependence_gcd_test_context(system
, id
))
436 if (null_cst
|| !null_param
)
438 /* FIXME: implement the loop bound check. */
439 /* /\* A clever test on access bounds. *\/ */
440 /* if (null_param && pos_iter && */
441 /* CANDL_get_si(system->p[id][system->NbColumns - 1]) > 0) */
443 /* if (null_param && neg_iter && */
444 /* CANDL_get_si(system->p[id][system->NbColumns - 1]) < 0) */
447 /* Compute GCD test for the array access equality. */
448 for (i
= 1, gcd
= osl_int_get_si(precision
, system
->m
[id
], i
);
449 i
< s_usr
->depth
+ t_usr
->depth
; ++i
)
450 gcd
= candl_dependence_gcd(gcd
, osl_int_get_si(precision
,
454 value
= osl_int_get_si(precision
, system
->m
[id
], system
->nb_columns
- 1);
455 value
= value
< 0 ? -value
: value
;
456 if ((gcd
== 0 && value
!= 0) || value
% gcd
)
465 * candl_dependence_build_system function:
466 * this function builds the constraint system corresponding to a data
467 * dependence, for a given statement couple (with iteration domains "source"
468 * and "target"), for a given reference couple (the source reference is array
469 * "ref_s" in "array_s" and the target reference is the array "ref_t" in
470 * "array_t"), at a given depth "depth" and knowing if the source is textually
471 * before the target (boolean "before"). The system is built... as always !
472 * See the [bastoul and Feautrier, PPL 2005] paper for details !
473 * - source is the source iteration domain,
474 * - target is the target iteration domain,
475 * - array_s is the access array for the source,
476 * - array_t is the access array for the target,
477 * - depth is the dependence depth,
478 * - before is 1 if the source is textually before the target, 0 otherwise,
480 * - 13/12/2005: first version (extracted from candl_dependence_system).
481 * - 23/02/2006: a stupid bug corrected in the subscript equality.
482 * - 07/04/2007: fix the precedence condition to respect C. Bastoul PhD thesis
484 static osl_dependence_p
candl_dependence_build_system(
485 osl_statement_p source
, osl_statement_p target
,
486 osl_relation_p array_s
, osl_relation_p array_t
,
487 int depth
, int before
) {
488 osl_dependence_p dependence
;
489 osl_relation_p system
;
492 int precision
= source
->domain
->precision
;
493 int nb_output_dims
; // source column
494 int nb_input_dims
; // target column
497 int nb_rows
, nb_columns
;
498 int ind_source_local_domain
;
499 int ind_source_local_access
;
500 int ind_target_local_domain
;
501 int ind_target_local_access
;
505 /* Create a new dependence structure */
506 dependence
= osl_dependence_malloc();
508 /* Compute the maximal common depth. */
509 min_depth
= CANDL_min(array_s
->nb_output_dims
, array_t
->nb_output_dims
);
511 /* Compute the system size */
512 dependence
->source_nb_output_dims_domain
= source
->domain
->nb_output_dims
;
513 dependence
->source_nb_output_dims_access
= array_s
->nb_output_dims
;
515 dependence
->target_nb_output_dims_domain
= target
->domain
->nb_output_dims
;
516 dependence
->target_nb_output_dims_access
= array_t
->nb_output_dims
;
518 dependence
->source_nb_local_dims_domain
= source
->domain
->nb_local_dims
;
519 dependence
->source_nb_local_dims_access
= array_s
->nb_local_dims
;
520 dependence
->target_nb_local_dims_domain
= target
->domain
->nb_local_dims
;
521 dependence
->target_nb_local_dims_access
= array_t
->nb_local_dims
;
523 nb_par
= source
->domain
->nb_parameters
;
524 nb_local_dims
= dependence
->source_nb_local_dims_domain
+
525 dependence
->source_nb_local_dims_access
+
526 dependence
->target_nb_local_dims_domain
+
527 dependence
->target_nb_local_dims_access
;
528 nb_output_dims
= dependence
->source_nb_output_dims_domain
+
529 dependence
->source_nb_output_dims_access
;
530 nb_input_dims
= dependence
->target_nb_output_dims_domain
+
531 dependence
->target_nb_output_dims_access
;
533 nb_columns
= nb_output_dims
+ nb_input_dims
+ nb_local_dims
+ nb_par
+ 2;
534 nb_rows
= source
->domain
->nb_rows
+ target
->domain
->nb_rows
+
535 array_s
->nb_rows
+ array_t
->nb_rows
+
539 system
= osl_relation_pmalloc(precision
, nb_rows
, nb_columns
);
541 /* Compute some indexes */
542 ind_source_local_domain
= 1 + nb_output_dims
+ nb_input_dims
;
543 ind_source_local_access
= ind_source_local_domain
+ dependence
->source_nb_local_dims_domain
;
544 ind_target_local_domain
= ind_source_local_access
+ dependence
->source_nb_local_dims_access
;
545 ind_target_local_access
= ind_target_local_domain
+ dependence
->target_nb_local_dims_domain
;
546 ind_params
= ind_target_local_access
+ dependence
->target_nb_local_dims_access
;
548 /* 1. Copy the source domain */
549 for (i
= 0 ; i
< source
->domain
->nb_rows
; i
++) {
551 osl_int_assign(precision
,
552 system
->m
[constraint
], 0,
553 source
->domain
->m
[i
], 0);
557 for (c
= source
->domain
->nb_output_dims
; c
> 0 ; c
--, k
++, j
++)
558 osl_int_assign(precision
,
559 system
->m
[constraint
], k
,
560 source
->domain
->m
[i
], j
);
561 /* local dims (no input in domain, so j is the same) */
562 k
= ind_source_local_domain
;
563 for (c
= source
->domain
->nb_local_dims
; c
> 0 ; c
--, k
++, j
++)
564 osl_int_assign(precision
,
565 system
->m
[constraint
], k
,
566 source
->domain
->m
[i
], j
);
569 for (c
= nb_par
+1 ; c
> 0 ; c
--, k
++, j
++)
570 osl_int_assign(precision
,
571 system
->m
[constraint
], k
,
572 source
->domain
->m
[i
], j
);
576 /* 2. Copy the target domain */
577 for (i
= 0 ; i
< target
->domain
->nb_rows
; i
++) {
579 osl_int_assign(precision
,
580 system
->m
[constraint
], 0,
581 target
->domain
->m
[i
], 0);
583 k
= 1 + nb_output_dims
;
585 for (c
= target
->domain
->nb_output_dims
; c
> 0 ; c
--, k
++, j
++)
586 osl_int_assign(precision
,
587 system
->m
[constraint
], k
,
588 target
->domain
->m
[i
], j
);
589 /* local dims (no input in domain, so j is the same) */
590 k
= ind_target_local_domain
;
591 for (c
= target
->domain
->nb_local_dims
; c
> 0 ; c
--, k
++, j
++)
592 osl_int_assign(precision
,
593 system
->m
[constraint
], k
,
594 target
->domain
->m
[i
], j
);
597 for (c
= nb_par
+1 ; c
> 0 ; c
--, k
++, j
++)
598 osl_int_assign(precision
,
599 system
->m
[constraint
], k
,
600 target
->domain
->m
[i
], j
);
604 /* 3. Copy the source access */
605 for (i
= 0 ; i
< array_s
->nb_rows
; i
++) {
607 osl_int_assign(precision
,
608 system
->m
[constraint
], 0,
611 k
= 1 + source
->domain
->nb_output_dims
;
613 for (c
= array_s
->nb_output_dims
; c
> 0 ; c
--, k
++, j
++)
614 osl_int_assign(precision
,
615 system
->m
[constraint
], k
,
617 /* link input dims access to the output dims domain */
619 for (c
= array_s
->nb_input_dims
; c
> 0 ; c
--, k
++, j
++)
620 osl_int_assign(precision
,
621 system
->m
[constraint
], k
,
624 k
= ind_source_local_access
;
625 for (c
= array_s
->nb_local_dims
; c
> 0 ; c
--, k
++, j
++)
626 osl_int_assign(precision
,
627 system
->m
[constraint
], k
,
631 for (c
= nb_par
+1 ; c
> 0 ; c
--, k
++, j
++)
632 osl_int_assign(precision
,
633 system
->m
[constraint
], k
,
639 /* 4. Copy the target access */
640 for (i
= 0 ; i
< array_t
->nb_rows
; i
++) {
642 osl_int_assign(precision
,
643 system
->m
[constraint
], 0,
646 k
= 1 + nb_output_dims
+ target
->domain
->nb_output_dims
;
648 for (c
= array_t
->nb_output_dims
; c
> 0 ; c
--, k
++, j
++) {
649 osl_int_assign(precision
,
650 system
->m
[constraint
], k
,
652 osl_int_oppose(precision
,
653 system
->m
[constraint
], k
,
654 system
->m
[constraint
], k
);
656 /* link input dims access to the output dims domain */
657 k
= 1 + nb_output_dims
;
658 for (c
= array_t
->nb_input_dims
; c
> 0 ; c
--, k
++, j
++) {
659 osl_int_assign(precision
,
660 system
->m
[constraint
], k
,
662 osl_int_oppose(precision
,
663 system
->m
[constraint
], k
,
664 system
->m
[constraint
], k
);
667 k
= ind_target_local_access
;
668 for (c
= array_t
->nb_local_dims
; c
> 0 ; c
--, k
++, j
++) {
669 osl_int_assign(precision
,
670 system
->m
[constraint
], k
,
672 osl_int_oppose(precision
,
673 system
->m
[constraint
], k
,
674 system
->m
[constraint
], k
);
678 for (c
= nb_par
+1 ; c
> 0 ; c
--, k
++, j
++) {
679 osl_int_assign(precision
,
680 system
->m
[constraint
], k
,
682 osl_int_oppose(precision
,
683 system
->m
[constraint
], k
,
684 system
->m
[constraint
], k
);
690 /* 5. Set the equality between the output access */
691 /* Note here that the equality between the 2 Arr are necessarily equal */
692 k
= 1 + source
->domain
->nb_output_dims
;
693 j
= 1 + nb_output_dims
+ target
->domain
->nb_output_dims
;
694 for (i
= 0 ; i
< min_depth
; i
++, k
++, j
++) {
695 osl_int_set_si(precision
, system
->m
[constraint
], k
, -1);
696 osl_int_set_si(precision
, system
->m
[constraint
], j
, 1);
700 /* 6. The precedence constraints */
702 while (min_dim
< ((candl_statement_usr_p
)source
->usr
)->depth
&&
703 min_dim
< ((candl_statement_usr_p
)target
->usr
)->depth
&&
704 ((candl_statement_usr_p
)source
->usr
)->index
[min_dim
] ==
705 ((candl_statement_usr_p
)target
->usr
)->index
[min_dim
])
709 j
= 1 + nb_output_dims
;
710 for (i
= 0; i
< depth
; i
++, k
++, j
++) {
711 /* i = i' for all dimension less than depth. */
712 osl_int_set_si(precision
, system
->m
[constraint
], k
, -1);
713 osl_int_set_si(precision
, system
->m
[constraint
], j
, 1);
714 if (i
== depth
- 1) {
715 /* i <= i' at dimension depth if source is textually before target. */
716 osl_int_set_si(precision
, system
->m
[constraint
], 0, 1);
717 /* If source is textually after target, this is obviously i < i'. */
718 if (before
|| depth
< min_dim
) // sub 1 for the Arr dim
719 osl_int_set_si(precision
, system
->m
[constraint
], nb_columns
- 1, -1);
725 system
->nb_output_dims
= nb_output_dims
;
726 system
->nb_input_dims
= nb_input_dims
;
727 system
->nb_parameters
= nb_par
;
728 system
->nb_local_dims
= nb_local_dims
;
729 system
->type
= OSL_UNDEFINED
;
731 dependence
->domain
= system
;
738 * candl_dependence_system function :
739 * this function builds a node of the dependence graph: it studies a dependence
740 * between a given statement couple, reference couple, type and depth. If a
741 * data dependence actually exists, it returns a dependence structure, it
742 * returns NULL otherwise.
743 * - source is the source statement,
744 * - target is the target statement,
745 * - context is the program context (contraints on global parameters),
746 * - array_s is the array list for the source,
747 * - array_t is the array list for the target,
748 * - ref_s is the position of the source reference in array_s,
749 * - ref_s is the position of the target reference in array_t,
750 * - depth is the dependence depth,
751 * - type is the dependence type (RAW, WAW, WAR or RAR).
753 * - 18/09/2003: first version.
754 * - 09/12/2005: few corrections and polishing.
756 osl_dependence_p
candl_dependence_system(osl_statement_p source
,
757 osl_statement_p target
,
758 osl_relation_p context
,
759 osl_relation_p array_s
,
760 osl_relation_p array_t
,
761 int ref_s
, int ref_t
,
762 int type
, int depth
) {
763 candl_statement_usr_p s_usr
= source
->usr
;
764 candl_statement_usr_p t_usr
= target
->usr
;
765 osl_dependence_p dependence
= NULL
;
767 /* First, a trivial case: for two different statements at depth 0, there is
768 * a dependence only if the source is textually before the target.
770 if ((source
!= target
) && (depth
== 0) &&
771 (s_usr
->label
> t_usr
->label
))
774 /* We build the system of constraints. */
775 dependence
= candl_dependence_build_system(source
, target
,
781 /* We start by simple SIV/ZIV/GCD tests. */
782 if (!candl_dependence_gcd_test(source
, target
, dependence
->domain
, depth
)) {
783 osl_dependence_free(dependence
);
787 if (pip_has_rational_point(dependence
->domain
, context
, 1)) {
788 /* We set the various fields with corresponding values. */
789 dependence
->ref_source
= ref_s
;
790 dependence
->ref_target
= ref_t
;
791 dependence
->label_source
= ((candl_statement_usr_p
)source
->usr
)->label
;
792 dependence
->label_target
= ((candl_statement_usr_p
)target
->usr
)->label
;
793 dependence
->type
= type
;
794 dependence
->depth
= depth
;
795 dependence
->stmt_source_ptr
= source
;
796 dependence
->stmt_target_ptr
= target
;
797 dependence
->ref_source_access_ptr
= array_s
;
798 dependence
->ref_target_access_ptr
= array_t
;
800 osl_dependence_free(dependence
);
809 * candl_dependence_between function :
810 * this function builds the dependence list from the statement "source" to
811 * statement "target": it will study the dependence for each reference and for
812 * each depth, under a particular context (context) and according to some
814 * - 18/09/2003: first version.
815 * - 07/12/2005: (debug) correction of depth bounds.
816 * - 09/12/2005: We may take commutativity into consideration.
818 osl_dependence_p
candl_dependence_between(osl_statement_p source
,
819 osl_statement_p target
,
820 osl_relation_p context
,
821 candl_options_p options
) {
822 osl_dependence_p
new;
823 osl_dependence_p dependence
= NULL
;
824 osl_dependence_p now
;
825 osl_relation_list_p access_src
, access_targ
;
826 osl_relation_p elt_src
, elt_targ
;
827 candl_statement_usr_p s_usr
= source
->usr
;
828 candl_statement_usr_p t_usr
= target
->usr
;
829 int i
, min_depth
, max_depth
;
830 int precision
= source
->scattering
->precision
;
831 int row_src
, row_targ
;
834 /* If the statements commute and the user asks to use this information to
835 * simplify the dependence graph, we return no dependences.
837 if (options
->commute
&& candl_util_statement_commute(source
, target
))
840 /* In the case of a self-dependence, the dependence depth can be as low as 1
841 * (not 0 because at depth 0 there is no loop, thus there is only one
842 * instance of the statement !) and as high as the statement depth.
843 * In the case of different statements, the dependence depth can be as low
844 * as 0 and as high as the number of shared loops.
846 if (source
== target
) {
848 max_depth
= s_usr
->depth
;
850 /* Depth 0 is for statements that don't share any loop. */
851 if (s_usr
->depth
> 0 && t_usr
->depth
> 0)
852 min_depth
= (s_usr
->index
[0] == t_usr
->index
[0]) ? 1 : 0;
857 while ((max_depth
< s_usr
->depth
) &&
858 (max_depth
< t_usr
->depth
) &&
859 (s_usr
->index
[max_depth
] == t_usr
->index
[max_depth
]))
864 access_src
= source
->access
;
866 for (; access_src
!= NULL
; access_src
= access_src
->next
, ref_s
++) {
867 elt_src
= access_src
->elt
;
868 row_src
= candl_relation_get_line(elt_src
, 0);
870 switch(elt_src
->type
) {
872 /* Anti and input-dependences analysis. */
873 case OSL_TYPE_READ
: /* source READ */
874 if (!options
->war
&& !options
->rar
)
876 access_targ
= target
->access
;
878 for (; access_targ
!= NULL
; access_targ
= access_targ
->next
, ref_t
++) {
879 elt_targ
= access_targ
->elt
;
880 row_targ
= candl_relation_get_line(elt_targ
, 0);
882 /* Anti-dependences analysis. */
883 if (elt_targ
->type
!= OSL_TYPE_READ
) { /* target WRITE | MAY_WRITE */
885 osl_int_eq(precision
,
886 elt_src
->m
[row_src
], elt_src
->nb_columns
-1,
887 elt_targ
->m
[row_targ
], elt_targ
->nb_columns
-1)) {
888 for (i
= min_depth
; i
<= max_depth
; i
++) {
889 new = candl_dependence_system(source
, target
, context
,
892 OSL_DEPENDENCE_WAR
, i
);
893 osl_dependence_add(&dependence
, &now
, new);
897 /* Input-dependences analysis. */
898 else { /* target READ */
900 osl_int_eq(precision
,
901 elt_src
->m
[row_src
], elt_src
->nb_columns
-1,
902 elt_targ
->m
[row_targ
], elt_targ
->nb_columns
-1)) {
903 for (i
= min_depth
; i
<= max_depth
; i
++) {
904 new = candl_dependence_system(source
, target
, context
,
907 OSL_DEPENDENCE_RAR
, i
);
908 osl_dependence_add(&dependence
, &now
, new);
915 default: /* source WRITE | MAY-WRITE */
916 if (!options
->raw
&& !options
->waw
)
918 access_targ
= target
->access
;
920 for (; access_targ
!= NULL
; access_targ
= access_targ
->next
, ref_t
++) {
921 elt_targ
= access_targ
->elt
;
922 row_targ
= candl_relation_get_line(elt_targ
, 0);
924 /* Anti-dependences analysis. */
925 if (elt_targ
->type
!= OSL_TYPE_READ
) { /* target WRITE | MAY_WRITE */
927 osl_int_eq(precision
,
928 elt_src
->m
[row_src
], elt_src
->nb_columns
-1,
929 elt_targ
->m
[row_targ
], elt_targ
->nb_columns
-1)) {
930 for (i
= min_depth
; i
<= max_depth
; i
++) {
931 new = candl_dependence_system(source
, target
, context
,
934 OSL_DEPENDENCE_WAW
, i
);
935 osl_dependence_add(&dependence
, &now
, new);
939 /* Input-dependences analysis. */
940 else { /* target READ */
942 osl_int_eq(precision
,
943 elt_src
->m
[row_src
], elt_src
->nb_columns
-1,
944 elt_targ
->m
[row_targ
], elt_targ
->nb_columns
-1)) {
945 for (i
= min_depth
; i
<= max_depth
; i
++) {
946 new = candl_dependence_system(source
, target
, context
,
949 OSL_DEPENDENCE_RAW
, i
);
950 osl_dependence_add(&dependence
, &now
, new);
964 * candl_dependence function:
965 * this function builds the dependence graph of a scop
966 * according to some user options (options).
967 * - 18/09/2003: first version.
969 osl_dependence_p
candl_dependence(osl_scop_p scop
, candl_options_p options
) {
970 osl_dependence_p dependence
= NULL
;
971 osl_dependence_p
new = NULL
;
972 osl_dependence_p now
;
973 osl_statement_p stmt_i
, stmt_j
;
974 osl_relation_p context
= scop
->context
;
976 if (options
->scalar_privatization
|| options
->scalar_expansion
)
977 candl_dependence_analyze_scalars(scop
, options
);
979 stmt_i
= scop
->statement
;
980 for (; stmt_i
!= NULL
; stmt_i
= stmt_i
->next
) {
981 /* We add self dependence. */
983 new = candl_dependence_between(stmt_i
, stmt_i
, context
, options
);
984 osl_dependence_add(&dependence
, &now
, new);
986 stmt_j
= stmt_i
->next
;
987 for (; stmt_j
!= NULL
; stmt_j
= stmt_j
->next
) {
988 /* And dependences with other statements. */
990 new = candl_dependence_between(stmt_i
, stmt_j
, context
, options
);
991 osl_dependence_add(&dependence
, &now
, new);
994 new = candl_dependence_between(stmt_j
, stmt_i
, context
, options
);
995 osl_dependence_add(&dependence
, &now
, new);
999 /* If scalar analysis is called, remove some useless dependences. */
1000 /* LNP: This is subsubmed by the updated prune-with-privatization function. */
1001 /* if (options->scalar_privatization || options->scalar_expansion || */
1002 /* options->scalar_renaming) */
1003 /* candl_dependence_prune_scalar_waw(scop, options, &dependence); */
1005 /* Final treatment for scalar analysis. */
1007 if (options
->scalar_renaming
)
1008 check
= candl_dependence_scalar_renaming(scop
, options
, &dependence
);
1010 if (! check
&& options
->scalar_privatization
)
1011 candl_dependence_prune_with_privatization(scop
, options
, &dependence
);
1013 /* Compute the last writer */
1014 if (options
->lastwriter
)
1015 candl_compute_last_writer(dependence
, scop
);
1017 #if defined(CANDL_COMPILE_PRUNNING_C)
1018 /* Remove some transitively covered dependences (experimental). */
1019 if (options
->prune_dups
)
1020 dependence
= candl_dependence_prune_transitively_covered(dependence
);
1027 /******************************************************************************
1028 * Scalar analysis functions *
1029 ******************************************************************************/
1032 * candl_dependence_var_is_scalar function:
1033 * This function returns true if the variable indexed by 'var_index'
1034 * is a scalar in the whole scop.
1036 int candl_dependence_var_is_scalar(osl_scop_p scop
, int var_index
) {
1037 osl_statement_p statement
;
1038 osl_relation_list_p access
;
1040 int precision
= scop
->context
->precision
;
1044 statement
= scop
->statement
;
1045 while (statement
!= NULL
) {
1046 access
= statement
->access
;
1047 while (access
!= NULL
) {
1049 row
= candl_relation_get_line(elt
, 0);
1050 if (osl_int_get_si(precision
, elt
->m
[row
], elt
->nb_columns
-1) ==
1052 /* Ensure it is not an array. */
1053 if (elt
->nb_output_dims
> 1)
1055 /* Ensure the access function is '0'. */
1056 if (!osl_int_zero(precision
, elt
->m
[row
], 0))
1058 for (i
= 2; i
< elt
->nb_columns
-2; ++i
) /* jmp the 'Arr' */
1059 if (!osl_int_zero(precision
, elt
->m
[row
], i
))
1062 access
= access
->next
;
1064 statement
= statement
->next
;
1072 * candl_dependence_expand_scalar function:
1073 * Expand the variable of index 'scalar_idx' by adding one
1074 * dimension (x becomes x[0]) to each access matrix refering this
1075 * variable in the statement list.
1078 static void candl_dependence_expand_scalar(osl_statement_p
* sl
,
1080 osl_relation_list_p access
;
1084 int precision
= sl
[0]->scattering
->precision
;
1087 /* Iterate on all statements of the list. */
1088 for (i
= 0; sl
[i
] != NULL
; ++i
) {
1090 /* Check if the scalar is referenced in the 'read' access
1092 access
= sl
[i
]->access
;
1093 for (; access
!= NULL
; access
= access
->next
) {
1095 row
= candl_relation_get_line(elt
, 0);
1096 tmp
= osl_int_get_si(precision
,
1099 if (tmp
== scalar_idx
) {
1101 osl_relation_insert_blank_row(elt
, row
);
1102 osl_relation_insert_blank_column(elt
, 1 + elt
->nb_output_dims
);
1103 osl_int_set_si(precision
, elt
->m
[row
], 1 + elt
->nb_output_dims
, -1);
1104 elt
->nb_output_dims
++;
1112 * candl_dependence_refvar_chain function:
1113 * This function returns a chain of statements as a feshly allocated
1114 * array of pointer on statements, of all statements reading or
1115 * writing the variable 'var_index', surrounded by the 'level' common
1117 * Output is a NULL-terminated array. We don't create a chained list,
1118 * because it demands to clone every statements each time, and we need
1119 * to clone the field usr too.
1121 osl_statement_p
* candl_dependence_refvar_chain(osl_scop_p scop
,
1122 osl_statement_p dom
, int var_index
, int level
) {
1123 /* No or empty scop -> no chain! */
1124 if (scop
== NULL
|| scop
->statement
== NULL
)
1127 osl_statement_p
* res
; /* not a chained list, but an array of statement */
1128 osl_statement_p statement
;
1129 osl_relation_p scattering
, scattering_dom
;
1130 candl_statement_usr_p dom_usr
;
1131 candl_statement_usr_p stmt_usr
;
1133 int buffer_size
= 64;
1136 /* If no dominator is provided, assume we start with the first statement. */
1138 dom
= scop
->statement
;
1142 statement
= scop
->statement
;
1143 while (statement
!= NULL
&& statement
!= dom
)
1144 statement
= statement
->next
;
1146 /* The dominator is not in the list of statements. */
1147 if (statement
== NULL
)
1150 CANDL_malloc(res
, osl_statement_p
*, sizeof(osl_statement_p
) * buffer_size
);
1151 scattering_dom
= dom
->scattering
;
1153 for (; statement
!= NULL
; statement
= statement
->next
) {
1154 stmt_usr
= statement
->usr
;
1156 /* We look for exactly 'level' common loops. */
1157 if (stmt_usr
->depth
< level
)
1160 /* Ensure it has 'level' common loop(s) with the dominator. */
1161 scattering
= statement
->scattering
;
1162 for (i
= 0; i
< level
&&
1163 stmt_usr
->index
[i
] == dom_usr
->index
[i
];
1170 /* Ensure the variable is referenced. */
1171 if (candl_dependence_var_is_ref(statement
, var_index
) != CANDL_VAR_UNDEF
) {
1172 if (count
== buffer_size
) {
1174 CANDL_realloc(res
, osl_statement_p
*,
1175 sizeof(osl_statement_p
) * buffer_size
);
1177 res
[count
++] = statement
;
1181 CANDL_realloc(res
, osl_statement_p
*,
1182 sizeof(osl_statement_p
) * (count
+1));
1190 * candl_dependence_var_is_ref function:
1191 * This function checks if a var 'var_index' is referenced (DEF or
1192 * USE) by the statement.
1194 int candl_dependence_var_is_ref(osl_statement_p s
, int var_index
) {
1195 osl_relation_list_p access
;
1198 int ret
= CANDL_VAR_UNDEF
;
1203 while (access
!= NULL
) {
1205 if (elt
->type
== OSL_TYPE_READ
) {
1206 row
= candl_relation_get_line(elt
, 0);
1207 if (osl_int_get_si(elt
->precision
, elt
->m
[row
], elt
->nb_columns
-1) ==
1209 ret
= CANDL_VAR_IS_USED
;
1213 access
= access
->next
;
1218 while (access
!= NULL
) {
1220 if (elt
->type
!= OSL_TYPE_READ
) {
1221 row
= candl_relation_get_line(elt
, 0);
1222 if (osl_int_get_si(elt
->precision
, elt
->m
[row
], elt
->nb_columns
-1) ==
1224 if (ret
== CANDL_VAR_IS_USED
)
1225 ret
= CANDL_VAR_IS_DEF_USED
;
1227 ret
= CANDL_VAR_IS_DEF
;
1231 access
= access
->next
;
1240 * candl_dependence_compute_lb function:
1241 * This function assigns to the Entier 'lb' the lexmin of variable
1242 * 'col'-1 in the polyhedron 'm'.
1244 static void candl_dependence_compute_lb(osl_relation_p m
, Entier
* lb
, int col
) {
1245 PipOptions
* options
;
1248 options
= pip_options_init();
1249 options
->Simplify
= 1;
1250 options
->Urs_parms
= -1;
1251 options
->Urs_unknowns
= -1;
1252 /* Compute lexmin. */
1253 solution
= pip_solve_osl(m
, NULL
, -1, options
);
1255 if ((solution
!= NULL
) &&
1256 ((solution
->list
!= NULL
) || (solution
->condition
!= NULL
))) {
1260 CANDL_assign(*lb
, l
->vector
->the_vector
[0]);
1262 pip_options_free(options
);
1263 pip_quast_free(solution
);
1268 * candl_dependence_check_domain_is_included function:
1269 * This function checks if the 'level'-first iterators of 2 domains
1270 * are in such a way that s1 is larger or equal to s2, for the
1271 * considered iterator dimensions.
1274 int candl_dependence_check_domain_is_included(osl_statement_p s1
,
1276 osl_relation_p context
,
1278 candl_statement_usr_p s1_usr
= s1
->usr
;
1279 candl_statement_usr_p s2_usr
= s2
->usr
;
1280 osl_relation_p matrix
;
1283 int precision
= s2
->domain
->precision
;
1287 if (s1_usr
->depth
< max
) max
= s1_usr
->depth
;
1288 if (s2_usr
->depth
< max
) max
= s2_usr
->depth
;
1290 matrix
= osl_relation_pmalloc(precision
,
1291 s2
->domain
->nb_rows
+ s2_usr
->depth
- max
+ 1,
1292 s2
->domain
->nb_columns
);
1294 /* Duplicate s2 to the dest matrix. */
1295 for (i
= 0; i
< s2
->domain
->nb_rows
; ++i
) {
1296 for (j
= 0; j
< s2
->domain
->nb_columns
; ++j
)
1297 osl_int_assign(precision
,
1299 s2
->domain
->m
[i
], j
);
1302 /* Make useless dimensions equal to 1. */
1303 for (j
= 0; j
< s2_usr
->depth
- max
; ++j
) {
1304 candl_dependence_compute_lb(s2
->domain
, &lb
, j
+ 1 + max
);
1305 osl_int_assign(precision
,
1306 matrix
->m
[i
], matrix
->nb_columns
-1,
1308 osl_int_set_si(precision
,
1309 matrix
->m
[i
++], j
+1+max
,
1313 /* Iterate on all constraints of s1, and check them. */
1314 for (i
= 0; i
< s1
->domain
->nb_rows
; ++i
) {
1315 /* Skip constraints defining other iterators. */
1316 for (j
= max
+ 1; j
<= s1_usr
->depth
; ++j
) {
1317 if (!osl_int_zero(precision
, s1
->domain
->m
[i
], j
))
1320 if (j
<= s1_usr
->depth
)
1322 /* Invert the constraint, and add it to matrix. */
1323 for (j
= 0; j
<= max
; ++j
) {
1324 osl_int_assign(precision
,
1325 matrix
->m
[matrix
->nb_rows
-1], j
,
1326 s1
->domain
->m
[i
], j
);
1327 osl_int_oppose(precision
,
1328 matrix
->m
[matrix
->nb_rows
-1], j
,
1329 matrix
->m
[matrix
->nb_rows
-1], j
);
1331 for (j
= s1_usr
->depth
+ 1; j
< s1
->domain
->nb_columns
; ++j
) {
1332 osl_int_assign(precision
,
1333 matrix
->m
[matrix
->nb_rows
-1],
1334 j
- s1_usr
->depth
+ s2_usr
->depth
,
1335 s1
->domain
->m
[i
], j
);
1336 osl_int_oppose(precision
,
1337 matrix
->m
[matrix
->nb_rows
-1],
1338 j
- s1_usr
->depth
+ s2_usr
->depth
,
1339 matrix
->m
[matrix
->nb_rows
-1],
1340 j
- s1_usr
->depth
+ s2_usr
->depth
);
1342 /* Make the inequality strict. */
1343 osl_int_decrement(precision
,
1344 matrix
->m
[matrix
->nb_rows
-1], matrix
->nb_columns
-1,
1345 matrix
->m
[matrix
->nb_rows
-1], matrix
->nb_columns
-1);
1347 if (candl_matrix_check_point(matrix
, context
)) {
1348 /* There is a point. dom(s1) - dom(s2) > 0. */
1350 osl_relation_free(matrix
);
1356 osl_relation_free(matrix
);
1363 * candl_dependence_extract_scalar_variables function:
1364 * This functions returns a -1-terminated array of the scop scalar
1367 int* candl_dependence_extract_scalar_variables(osl_scop_p scop
) {
1368 osl_statement_p statement
;
1370 osl_relation_list_p access
;
1371 int scalars
[1024]; /* FIXME: implement a real buffer. */
1375 int count_s
= 0, count_c
= 0;
1377 /* Detect all scalar variables. */
1378 statement
= scop
->statement
;
1379 while (statement
!= NULL
) {
1380 access
= statement
->access
;
1381 while (access
!= NULL
) {
1383 row
= candl_relation_get_line(elt
, 0);
1384 idx
= osl_int_get_si(elt
->precision
,
1388 for (i
= 0; i
< count_s
&& scalars
[i
] != idx
; ++i
)
1391 for (i
= 0; i
< count_c
&& checked
[i
] != idx
; ++i
)
1394 if (candl_dependence_var_is_scalar(scop
, idx
))
1395 scalars
[count_s
++] = idx
;
1397 checked
[count_c
++] = idx
;
1399 if (count_s
== 1024 || count_c
== 1024)
1400 CANDL_error("Error: Buffer size too small");
1402 access
= access
->next
;
1404 statement
= statement
->next
;
1407 /* Rearrange the array to the exact size. */
1409 CANDL_malloc(res
, int*, (count_s
+ 1) * sizeof(int));
1410 for (i
= 0; i
< count_s
; ++i
)
1411 res
[i
] = scalars
[i
];
1419 * osl_dependence_prune_scalar_waw function:
1420 * This function removes all WAW dependences between the same scalar
1421 * (they are useless dependences).
1423 void osl_dependence_prune_scalar_waw(osl_scop_p scop
,
1424 candl_options_p options
,
1425 osl_dependence_p
* deps
) {
1429 osl_dependence_p tmp
;
1430 osl_dependence_p next
;
1431 osl_dependence_p pred
= NULL
;
1433 if (options
->verbose
)
1434 fprintf (stderr
, "[Candl] Scalar Analysis: Remove all WAW between the same"
1437 scalars
= candl_dependence_extract_scalar_variables(scop
);
1439 for (tmp
= *deps
; tmp
; ) {
1440 candl_dependence_get_array_refs_in_dep(tmp
, &refs
, &reft
);
1441 if (refs
== reft
&& tmp
->type
== OSL_DEPENDENCE_WAW
) {
1442 for (i
= 0; scalars
[i
] != -1 && scalars
[i
] != refs
; ++i
)
1444 if (scalars
[i
] != -1) {
1445 osl_relation_free(tmp
->domain
);
1465 * candl_dependence_scalar_renaming function:
1466 * This function renames scalars in the program. In case scalars have
1467 * been renamed, the dependence analysis is re-run.
1469 int candl_dependence_scalar_renaming(osl_scop_p scop
,
1470 candl_options_p options
,
1471 osl_dependence_p
* deps
) {
1472 osl_statement_p
*statement
; /* not a chained list */
1473 osl_statement_p iter
;
1474 osl_statement_p defs
[1024];
1475 osl_statement_p uses
[1024];
1476 osl_statement_p last_def
;
1477 osl_statement_p
*current
; /* not a chained list */
1479 osl_relation_list_p access
;
1480 candl_statement_usr_p usr
;
1481 candl_statement_usr_p last_usr
;
1483 int nb_statements
= 0;
1487 int precision
= scop
->context
->precision
;
1489 int tmp
, has_changed
= 0;
1492 if (options
->verbose
)
1493 fprintf (stderr
, "[Candl] Scalar Analysis: Perform scalar renaming\n");
1495 /* Compute the first free variable index seed. */
1496 for (iter
= scop
->statement
; iter
!= NULL
; iter
= iter
->next
) {
1497 access
= iter
->access
;
1498 for (; access
!= NULL
; access
= access
->next
) {
1500 row
= candl_relation_get_line(elt
, 0);
1501 tmp
= osl_int_get_si(precision
,
1511 CANDL_malloc(current
, osl_statement_p
*, sizeof(osl_statement_p
) * nb_statements
);
1512 CANDL_malloc(parts
, int*, sizeof(int) * nb_statements
);
1514 /* Get the list of scalars. */
1515 scalars
= candl_dependence_extract_scalar_variables(scop
);
1517 /* Iterate on all scalars. */
1518 for (i
= 0; scalars
[i
] != -1; ++i
) {
1519 /* Get all statements referencing the scalar. */
1520 statement
= candl_dependence_refvar_chain(scop
, NULL
, scalars
[i
], 0);
1522 /* If the chain starts by a USE, we can't do anything. */
1523 if (statement
[0] == NULL
||
1524 candl_dependence_var_is_ref(statement
[0], scalars
[i
])
1525 != CANDL_VAR_IS_DEF
) {
1530 /* Get all defs and all uses. */
1533 for (j
= 0; statement
[j
]; ++j
) {
1534 tmp
= candl_dependence_var_is_ref(statement
[j
], scalars
[i
]);
1536 case CANDL_VAR_IS_USED
:
1537 case CANDL_VAR_IS_DEF_USED
:
1538 uses
[uses_c
++] = statement
[j
];
1540 case CANDL_VAR_IS_DEF
:
1541 defs
[defs_c
++] = statement
[j
];
1548 for (iter
= scop
->statement
; iter
!= NULL
; iter
= iter
->next
)
1549 current
[j
++] = NULL
;
1553 /* Iterate on all DEFs. */
1555 for (j
= 0; j
< defs_c
; ++j
) {
1556 if (last_def
== NULL
) {
1559 /* Ensure the current DEF covers all iterations covered
1560 by the last checked one. */
1561 last_usr
= last_def
->usr
;
1563 for (k
= 0; k
< last_usr
->depth
&& k
< usr
->depth
&&
1564 last_usr
->index
[k
] == usr
->index
[k
];
1567 /* We only need to check when there are common loops. */
1568 if (k
&& ! candl_dependence_check_domain_is_included
1569 (last_def
, defs
[j
], scop
->context
, k
+ 1)) {
1571 current
[usr
->label
] = last_def
;
1577 /* Create DEF-USE table. */
1578 for (k
= 0; k
< uses_c
; ++k
) {
1580 if (usr
->label
> ((candl_statement_usr_p
)defs
[j
]->usr
)->label
)
1581 current
[usr
->label
] = defs
[j
];
1585 /* Initialize partition table. */
1586 for (j
= 0; j
< nb_statements
; ++j
)
1589 /* Create partitions. */
1590 for (j
= 0; j
< defs_c
; ++j
) {
1592 for (k
= 0; k
< nb_statements
; ++k
)
1593 if ((current
[k
] && current
[k
] == defs
[j
]) ||
1594 (k
== usr
->label
&& current
[usr
->label
] == NULL
))
1598 /* Check if it is needed to rename the scalar. */
1600 for (j
= 0; j
< nb_statements
; ++j
)
1605 if (parts
[j
] != -1 && tmp
!= parts
[j
])
1609 /* Rename scalar variable. */
1610 if (j
!= nb_statements
) {
1613 for (iter
= scop
->statement
; iter
!= NULL
; iter
= iter
->next
) {
1614 if (parts
[j
] != -1) {
1617 else if (tmp
!= parts
[j
])
1620 access
= iter
->access
;
1621 for (; access
!= NULL
; access
= access
->next
) {
1623 row
= candl_relation_get_line(elt
, 0);
1624 tmp
= osl_int_get_si(precision
,
1627 if (tmp
== scalars
[i
]) {
1628 if (options
->verbose
)
1629 fprintf (stderr
, "[Candl] Scalar analysis: Renamed "
1630 "variable %d to %d at statement S%d\n",
1631 scalars
[i
], newvar
+ parts
[j
], j
);
1632 osl_int_set_si(precision
,
1642 } /* end Iterate on all scalars */
1644 /* Redo the full dependence analysis, if needed. */
1646 int bopt
= options
->scalar_renaming
;
1647 options
->scalar_renaming
= 0;
1648 if (options
->scalar_privatization
)
1649 free(((candl_scop_usr_p
)scop
->usr
)->scalars_privatizable
);
1650 osl_dependence_free(*deps
);
1651 *deps
= candl_dependence(scop
, options
);
1652 options
->scalar_renaming
= bopt
;
1664 * candl_dependence_is_loop_carried function:
1665 * This function returns true if the dependence 'dep' is loop-carried
1666 * for loop 'loop_index', false otherwise.
1668 int candl_dependence_is_loop_carried(osl_scop_p scop
,
1669 osl_dependence_p dep
,
1671 osl_relation_p msrc
= NULL
, mtarg
= NULL
;
1672 candl_statement_usr_p s_usr
= dep
->stmt_source_ptr
->usr
;
1673 candl_statement_usr_p t_usr
= dep
->stmt_target_ptr
->usr
;
1677 int precision
= scop
->context
->precision
;
1679 /* Ensure source and sink share common loop 'loop_index', and that
1680 dependence depth is consistent with the considered loop. */
1681 for (i
= 0; i
< s_usr
->depth
; ++i
)
1682 if (s_usr
->index
[i
] == loop_index
)
1684 if (i
!= dep
->depth
- 1 || i
>= t_usr
->depth
)
1686 for (j
= 0; j
< t_usr
->depth
; ++j
)
1687 if (t_usr
->index
[j
] == loop_index
)
1692 msrc
= candl_dependence_get_relation_ref_source_in_dep(dep
);
1693 mtarg
= candl_dependence_get_relation_ref_target_in_dep(dep
);
1695 /* plus one for the Arr output dim */
1696 int src_ref_iter
= (candl_relation_get_line(msrc
, i
+1) != -1);
1697 int dst_ref_iter
= (candl_relation_get_line(mtarg
,j
+1) != -1);
1699 /* Ensure it is not a basic loop-independent dependence (pure
1700 equality of the access functions for the surrounding iterators +
1701 parameters + constant, no occurence of the inner loop iterators,
1702 and contain the current loop iterator. */
1704 k
= 1; // start after the Arr column
1705 row_k
= candl_relation_get_line(msrc
, k
);
1706 while (!must_test
&&
1707 k
< msrc
->nb_output_dims
&&
1708 osl_int_zero(precision
, msrc
->m
[row_k
], 0)) {
1710 // Ensure the reference do reference the current loop iterator
1712 if (!osl_int_zero(precision
, msrc
->m
[row_k
], i
)) {
1714 row_kp
= candl_relation_get_line(mtarg
, kp
);
1716 while (!must_test
&&
1717 kp
< mtarg
->nb_output_dims
&&
1718 osl_int_zero(precision
, mtarg
->m
[row_kp
], 0)) {
1720 if (!osl_int_zero(precision
, mtarg
->m
[row_kp
], j
)) {
1721 // Ensure the access functions are equal for the
1722 // surrounding loop iterators, and no inner iterator
1724 if (!osl_int_eq(precision
,
1726 mtarg
->m
[row_kp
], 0)) {
1729 for (l
= 1; l
<= i
; ++l
)
1730 if (!osl_int_eq(precision
,
1731 msrc
->m
[row_k
], msrc
->nb_output_dims
+ l
,
1732 mtarg
->m
[row_kp
], mtarg
->nb_output_dims
+ l
)) {
1739 for (; l
<= s_usr
->depth
+1; ++l
)
1740 if (!osl_int_zero(precision
, msrc
->m
[row_k
], msrc
->nb_output_dims
+ l
)) {
1745 for (; m
<= t_usr
->depth
+1; ++m
)
1746 if (!osl_int_zero(precision
, mtarg
->m
[row_kp
], mtarg
->nb_output_dims
+ m
)) {
1751 for (; l
< msrc
->nb_columns
-1; ++l
, ++m
)
1752 if (!osl_int_eq(precision
,
1753 msrc
->m
[row_k
], msrc
->nb_output_dims
+ l
,
1754 mtarg
->m
[row_kp
], mtarg
->nb_output_dims
+ m
)) {
1760 row_kp
= candl_relation_get_line(mtarg
, kp
);
1764 row_k
= candl_relation_get_line(msrc
, k
);
1767 if (src_ref_iter
&& dst_ref_iter
&& !must_test
)
1770 /* Final check. For loop i, the dependence is loop carried if there exists
1771 x_i^R != x_i^S in the dependence polyhedron, with
1772 x_{1..i-1}^R = x_{1..i-1}^S
1775 osl_relation_p mat
= dep
->domain
;
1777 osl_relation_p testsyst
= osl_relation_pmalloc(precision
,
1778 mat
->nb_rows
+ 1 + s_usr
->depth
,
1780 for (pos
= 0; pos
< mat
->nb_rows
; ++pos
)
1781 for (j
= 0; j
< mat
->nb_columns
; ++j
)
1782 osl_int_assign(precision
,
1783 testsyst
->m
[pos
], j
,
1785 for (j
= 0; j
< i
; ++j
) {
1786 osl_int_set_si(precision
, testsyst
->m
[pos
+j
+1], 0, 0);
1787 osl_int_set_si(precision
, testsyst
->m
[pos
+j
+1], 1+j
, -1);
1788 osl_int_set_si(precision
, testsyst
->m
[pos
+j
+1], 1+j
+mat
->nb_output_dims
, 1);
1793 osl_int_set_si(precision
,testsyst
->m
[pos
], 0, 1);
1794 osl_int_set_si(precision
,testsyst
->m
[pos
], testsyst
->nb_columns
-1, -1);
1795 osl_int_set_si(precision
,testsyst
->m
[pos
], 1+i
, 1);
1796 osl_int_set_si(precision
,testsyst
->m
[pos
], 1+i
+mat
->nb_output_dims
, -1);
1798 has_pt
= pip_has_rational_point(testsyst
, NULL
, 1);
1801 osl_int_set_si(precision
, testsyst
->m
[pos
], 1+i
, -1);
1802 osl_int_set_si(precision
, testsyst
->m
[pos
], 1+i
+mat
->nb_output_dims
, 1);
1803 has_pt
= pip_has_rational_point(testsyst
, NULL
, 1);
1808 /* LNP: OLD VERSION */
1809 /* The above is more robust. */
1810 /* /\* Final check. The dependence exists only because the loop */
1811 /* iterates. Make the loop not iterate and check if there's still */
1812 /* dependent iterations. *\/ */
1813 /* CandlMatrix* m = candl_matrix_malloc(dep->domain->NbRows + 2, */
1814 /* dep->domain->NbColumns); */
1815 /* CANDL_set_si(m->p[m->NbRows - 2][i + 1], -1); */
1816 /* CANDL_set_si(m->p[m->NbRows - 1][dep->source->depth + 1 + j], -1); */
1817 /* /\* Copy the rest of the matrix. *\/ */
1819 /* for (ii = 0; ii < dep->domain->NbRows; ++ii) */
1820 /* for (jj = 0; jj < dep->domain->NbColumns; ++jj) */
1821 /* CANDL_assign(m->p[ii][jj], dep->domain->p[ii][jj]); */
1822 /* /\* Compute real lb of loops. *\/ */
1823 /* Entier lb; CANDL_init(lb); */
1824 /* candl_dependence_compute_lb (m, &lb, i + 1); */
1825 /* CANDL_assign(m->p[m->NbRows - 2][m->NbColumns - 1], lb); */
1826 /* candl_dependence_compute_lb (m, &lb, dep->source->depth + 1 + j); */
1827 /* CANDL_assign(m->p[m->NbRows - 1][m->NbColumns - 1], lb); */
1828 /* int ret = candl_matrix_check_point(m, program->context); */
1829 /* CANDL_clear(lb); */
1831 /* /\* Be clean. *\/ */
1832 /* candl_matrix_free(m); */
1839 * candl_dependence_prune_with_privatization function: This function
1840 * prunes the dependence graph 'deps' by removing loop-carried
1841 * dependences involving a scalar variable privatizable for that loop.
1843 void candl_dependence_prune_with_privatization(osl_scop_p scop
,
1844 candl_options_p options
,
1845 osl_dependence_p
* deps
) {
1846 osl_dependence_p next
;
1847 osl_dependence_p tmp
;
1848 osl_dependence_p pred
= NULL
;
1849 candl_statement_usr_p s_usr
;
1850 candl_statement_usr_p t_usr
;
1851 candl_scop_usr_p scop_usr
= scop
->usr
;
1858 int precision
= scop
->context
->precision
;
1860 if (options
->verbose
)
1861 fprintf (stderr
, "[Candl] Scalar Analysis: Remove loop-carried dependences"
1862 " on privatizable scalars\n");
1864 if (scop
->statement
== NULL
)
1867 /* Perform the scalar analysis, if not done before. */
1868 if (scop_usr
->scalars_privatizable
== NULL
) {
1869 candl_options_p options
= candl_options_malloc();
1870 options
->scalar_privatization
= 1;
1871 candl_dependence_analyze_scalars(scop
, options
);
1872 candl_options_free(options
);
1875 for (tmp
= *deps
; tmp
; ) {
1876 s_usr
= tmp
->stmt_source_ptr
->usr
;
1877 t_usr
= tmp
->stmt_target_ptr
->usr
;
1879 /* Check if the dependence is involving a privatizable scalar. */
1881 candl_dependence_get_array_refs_in_dep(tmp
, &refs
, &reft
);
1882 for (i
= 0; i
< s_usr
->depth
; ++i
) {
1883 if (candl_dependence_scalar_is_privatizable_at(scop
, refs
,
1887 if (i
== s_usr
->depth
) {
1888 for (i
= 0; i
< t_usr
->depth
; ++i
) {
1889 if (candl_dependence_scalar_is_privatizable_at
1890 (scop
, reft
, t_usr
->index
[i
]))
1893 if (i
== t_usr
->depth
)
1896 loop_idx
= t_usr
->index
[i
];
1898 loop_idx
= s_usr
->index
[i
];
1902 /* Check if the dependence is loop-carried at loop i. */
1903 if (is_priv
&& candl_dependence_is_loop_carried(scop
, tmp
, loop_idx
)) {
1904 /* If so, make the dependence loop-independent. */
1905 row
= tmp
->domain
->nb_rows
;
1906 osl_relation_insert_blank_row(tmp
->domain
, row
);
1907 osl_int_set_si(precision
,
1908 tmp
->domain
->m
[row
], 1 + loop_pos_priv
,
1910 osl_int_set_si(precision
,
1911 tmp
->domain
->m
[row
], 1 + loop_pos_priv
+
1915 /* Set the type of the dependence as special
1916 scalar-privatization one. */
1917 if (tmp
->type
== OSL_DEPENDENCE_RAW
)
1918 tmp
->type
= OSL_DEPENDENCE_RAW_SCALPRIV
;
1920 if (!candl_matrix_check_point(tmp
->domain
, NULL
)) {
1921 /* It is, the dependence can be removed. */
1922 osl_relation_free(tmp
->domain
);
1934 /* Go to the next victim. */
1942 * candl_dependence_is_privatizable function:
1943 * This function checks if a given scalar 'var_index' is privatizable
1944 * for loop 'loop_index'.
1946 int candl_dependence_scalar_is_privatizable_at(osl_scop_p scop
,
1949 candl_scop_usr_p scop_usr
= scop
->usr
;
1952 /* If the scalar analysis wasn't performed yet, do it. */
1953 if (scop_usr
->scalars_privatizable
== NULL
) {
1954 candl_options_p options
= candl_options_malloc();
1955 options
->scalar_privatization
= 1;
1956 candl_dependence_analyze_scalars(scop
, options
);
1957 candl_options_free(options
);
1961 while (scop_usr
->scalars_privatizable
[i
] != -1)
1964 /* Check in the array of privatizable scalar variables for the tuple
1966 for (i
= 0; scop_usr
->scalars_privatizable
[i
] != -1; i
+= 2)
1967 if (scop_usr
->scalars_privatizable
[i
] == var_index
&&
1968 scop_usr
->scalars_privatizable
[i
+ 1] == loop_index
)
1976 * candl_dependence_analyze_scalars function:
1977 * This function checks, for all scalar variables of the scop, and
1978 * all loop levels, if the scalar can be privatized at that level.
1980 int candl_dependence_analyze_scalars(osl_scop_p scop
,
1981 candl_options_p options
) {
1983 osl_statement_p
* statement
; /* not a chained list, but an array of */
1984 osl_statement_p
* fullchain
; /* statement to not realloc the usr field */
1986 osl_statement_p curlast
;
1987 osl_statement_p last
;
1988 osl_statement_p iter
; /* used to iterate on the scop */
1989 osl_relation_list_p access
;
1991 candl_scop_usr_p scop_usr
= scop
->usr
;
1992 candl_statement_usr_p stmt_usr
;
1994 int max
, is_priv
, offset
, was_priv
;
1996 int priv_buff_size
= 64;
1999 /* Initialize the list of privatizable scalars to empty. */
2000 if (options
->scalar_privatization
) {
2001 CANDL_malloc(scop_usr
->scalars_privatizable
, int*, 2 * sizeof(int));
2002 scop_usr
->scalars_privatizable
[0] = -1;
2003 scop_usr
->scalars_privatizable
[1] = -1;
2006 /* Retrieve all scalar variables. */
2007 scalars
= candl_dependence_extract_scalar_variables(scop
);
2009 /* For each of those, detect (at any level) if it can be privatized
2010 / expanded / renamed. */
2011 for (i
= 0; scalars
[i
] != -1; ++i
) {
2012 /* Go to the first statement referencing the scalar in the scop. */
2013 for (iter
= scop
->statement
; iter
!= NULL
; iter
= iter
->next
) {
2014 if (candl_dependence_var_is_ref(iter
, scalars
[i
])
2019 /* A weird error occured. */
2023 /* Take all statements referencing the scalar. */
2024 fullchain
= candl_dependence_refvar_chain(scop
, iter
, scalars
[i
], 0);
2026 /* Compute the maximum loop depth of the chain. */
2028 for (k
= 0; fullchain
[k
]; ++k
) {
2029 stmt_usr
= fullchain
[k
]->usr
;
2030 if (max
< stmt_usr
->depth
)
2031 max
= stmt_usr
->depth
;
2033 last
= fullchain
[k
-1];
2035 /* Initialize the offset for expansion. */
2039 /* Iterate on all possible depth for analysis. */
2040 for (j
= 1; j
<= max
; ++j
) {
2049 /* Take all statements dominated by s referencing the
2050 current scalar variable. */
2051 statement
= candl_dependence_refvar_chain(scop
, s
, scalars
[i
], j
);
2053 /* No more statement in the chain, exit. */
2054 if (statement
[0] == NULL
) {
2061 is_priv
= candl_dependence_var_is_ref(statement
[0], scalars
[i
]) ==
2064 /* Ensure we have a use in the chain. */
2065 /* here statement[c] is not NULL */
2066 for (k
= c
+ 1; statement
[k
]; ++k
) {
2067 if (candl_dependence_var_is_ref(statement
[k
], scalars
[i
]) ==
2072 if (statement
[k
] == NULL
)
2075 /* Check for privatization, while the entry of the chain
2077 while (statement
[c
] && candl_dependence_var_is_ref
2078 (statement
[c
], scalars
[i
]) == CANDL_VAR_IS_DEF
) {
2079 /* From the current DEF node, ensure the rest of the
2080 chain covers not more than the iteration domain
2082 for (k
= c
+ 1; statement
[k
]; ++k
) {
2083 /* FIXME: we should deal with
2084 def_1->use->def_2->use chains where dom(def_2)
2086 if (! candl_dependence_check_domain_is_included
2087 (statement
[c
], statement
[k
], scop
->context
, j
)) {
2088 /* dom(use) - dom(def) > 0. Check if there is
2089 another DEF to test at the entry of the
2091 if (candl_dependence_var_is_ref
2092 (statement
[c
+1], scalars
[i
]) != CANDL_VAR_IS_DEF
)
2093 /* No. The variable is not privatizable. */
2099 if (! is_priv
|| ! statement
[k
])
2102 /* The chain dominated by statement is not
2103 privatizable. Go for the next DEF at the
2104 beginning of the block, if any. */
2109 /* Perform the privatization / expansion. */
2110 if (options
->verbose
)
2111 fprintf(stderr
, "[Candl] Scalar Analysis: The variable %d"
2112 " can be privatized at loop %d\n",
2114 ((candl_statement_usr_p
)statement
[0]->usr
)->index
[j
-1]);
2116 if (options
->scalar_expansion
) {
2117 int precision
= scop
->context
->precision
;
2118 /* Traverse all statements in the chain. */
2119 for (k
= c
; statement
[k
]; ++k
) {
2120 /* It's not the first expansion of the scalar,
2121 we need to increase its dimension all along
2123 if (!offset
&& !was_priv
)
2124 candl_dependence_expand_scalar(fullchain
,
2126 /* Perform scalar expansion in the array
2127 access functions. */
2128 access
= statement
[k
]->access
;
2129 for (; access
!= NULL
; access
= access
->next
) {
2131 row
= candl_relation_get_line(elt
, 0);
2133 osl_int_get_si(precision
, elt
->m
[row
], elt
->nb_columns
-1)) {
2134 row
= candl_relation_get_line(elt
, offset
+1);
2135 osl_int_set_si(precision
, elt
->m
[row
], elt
->nb_output_dims
+ j
, 1);
2142 if (options
->scalar_privatization
) {
2143 /* Memory management for the array of
2144 privatizable scalars. */
2146 free(scop_usr
->scalars_privatizable
);
2147 CANDL_malloc(scop_usr
->scalars_privatizable
,
2148 int*, priv_buff_size
* sizeof(int));
2149 for (k
= 0; k
< priv_buff_size
; ++k
)
2150 scop_usr
->scalars_privatizable
[k
] = -1;
2153 if (nb_priv
== priv_buff_size
) {
2154 CANDL_realloc(scop_usr
->scalars_privatizable
,
2155 int*, (priv_buff_size
*= 2) * sizeof(int));
2156 for (k
= nb_priv
; k
< priv_buff_size
; ++k
)
2157 scop_usr
->scalars_privatizable
[k
] = -1;
2160 /* Memorize the scalar information in the
2161 privatizable list. */
2162 scop_usr
->scalars_privatizable
[nb_priv
++] = scalars
[i
];
2163 scop_usr
->scalars_privatizable
[nb_priv
++] =
2164 ((candl_statement_usr_p
)statement
[0]->usr
)->index
[j
- 1];
2170 /* Go to the next block, if any. */
2171 for (k
= 0; statement
[k
]; ++k
)
2173 curlast
= statement
[k
-1];
2175 if (curlast
!= last
) {
2176 for (k
= 0; fullchain
[k
]; ++k
) {
2177 if (fullchain
[k
] == curlast
) {
2185 } while (curlast
!= last
);
2187 } // end iterate all possible depth
2191 } // end iterate scalars
2198 * Compute last writer for a given dependence; does not make sense if the
2199 * supplied dependence is not a RAW or WAW dependence
2201 * Returns 0 if lastwriter is computed successfully and dep domain updated,
2202 * returns 1 otherwise
2205 int candl_dep_compute_lastwriter(osl_dependence_p
*dep
, osl_scop_p scop
) {
2207 PipOptions
*pipOptions
= pip_options_init();
2208 candl_statement_usr_p s_usr
= (*dep
)->stmt_source_ptr
->usr
;
2209 candl_statement_usr_p t_usr
= (*dep
)->stmt_target_ptr
->usr
;
2210 osl_relation_p new_domain
;
2212 int npar
= scop
->context
->nb_parameters
;
2215 #if defined(LINEAR_VALUE_IS_INT)
2216 precision
= OSL_PRECISION_SP
;
2217 #elif defined(LINEAR_VALUE_IS_LONGLONG)
2218 precision
= OSL_PRECISION_DP
;
2219 #elif defined(LINEAR_VALUE_IS_MP)
2220 precision
= OSL_PRECISION_MP
;
2223 if (precision
!= scop
->context
->precision
) {
2224 CANDL_error("Precision not compatible with piplib ! (pip_relation2matrix)");
2227 /* We do a parametric lexmax on the source iterators
2228 * keeping the target iterators as parameters */
2229 pipOptions
->Maximize
= 1;
2230 pipOptions
->Simplify
= 1;
2231 // pipOptions->Deepest_cut = 1;
2232 // pipOptions->Urs_unknowns = -1;
2233 // pipOptions->Urs_parms = -1;
2235 /* Build a context with equalities /inequalities only on the target
2237 osl_relation_p context
= osl_relation_pmalloc(precision
,
2238 (*dep
)->domain
->nb_rows
,
2239 (*dep
)->stmt_target_ptr
->domain
->nb_columns
);
2241 for (i
= 0; i
< (*dep
)->domain
->nb_rows
; i
++) {
2242 for (j
= 1; j
< s_usr
->depth
+1; j
++) {
2244 // FIXME : new domain structure for dependence
2246 if (!osl_int_zero(precision
, (*dep
)->domain
->m
[i
], j
))
2250 if (j
== t_usr
->depth
+1) {
2251 /* Include this in the context */
2252 osl_int_assign(precision
,
2253 context
->m
[nrows
], 0,
2254 (*dep
)->domain
->m
[i
], 0);
2256 for (j
= 1; j
< (*dep
)->stmt_target_ptr
->domain
->nb_columns
; j
++)
2257 osl_int_assign(precision
,
2258 context
->m
[nrows
], j
,
2259 (*dep
)->domain
->m
[i
], s_usr
->depth
+j
);
2265 /* Parameteric lexmax */
2266 lexmax
= pip_solve_osl((*dep
)->domain
, context
, -1, pipOptions
);
2268 pip_options_free(pipOptions
);
2270 if (lexmax
== NULL
) {
2271 CANDL_warning("last writer failed (mostly invalid dependence): bailing out"
2272 "safely without modification");
2273 osl_relation_print(stderr
, context
);
2274 osl_relation_print(stderr
, (*dep
)->domain
);
2279 osl_relation_p qp
= pip_quast_to_polyhedra(lexmax
, s_usr
->depth
,
2280 t_usr
->depth
+ npar
);
2282 /* Update the dependence domains */
2284 osl_relation_p iter
;
2285 osl_relation_p original_domain
= (*dep
)->domain
;
2286 for (iter
= qp
; iter
!= NULL
; iter
= iter
->next
) {
2288 new_domain
= osl_relation_pmalloc(precision
,
2289 original_domain
->nb_rows
+
2291 original_domain
->nb_columns
);
2293 for (i
= 0; i
< original_domain
->nb_rows
; i
++)
2294 for (j
= 0; j
< original_domain
->nb_columns
; j
++)
2295 osl_int_assign(precision
,
2296 new_domain
->m
[i
], j
,
2297 original_domain
->m
[i
], j
);
2299 for (i
= 0; i
< qp
->nb_rows
; i
++)
2300 for (j
= 0; j
< original_domain
->nb_columns
; j
++)
2301 osl_int_assign(precision
,
2302 new_domain
->m
[i
+original_domain
->nb_rows
], j
,
2305 (*dep
)->domain
= new_domain
;
2306 /* More than 1 pipmatrix from the quast, we need to insert
2307 new dependences to have the union of domains. */
2308 if (qp
->next
!= NULL
) {
2309 osl_dependence_p newdep
= osl_dependence_malloc();
2310 newdep
->stmt_source_ptr
= (*dep
)->stmt_source_ptr
;
2311 newdep
->stmt_target_ptr
= (*dep
)->stmt_target_ptr
;
2312 newdep
->depth
= (*dep
)->depth
;
2313 newdep
->type
= (*dep
)->type
;
2314 newdep
->label_source
= (*dep
)->label_source
;
2315 newdep
->label_target
= (*dep
)->label_target
;
2316 newdep
->ref_source
= (*dep
)->ref_source
;
2317 newdep
->ref_target
= (*dep
)->ref_target
;
2318 newdep
->usr
= (*dep
)->usr
;
2319 newdep
->source_nb_output_dims_domain
= (*dep
)->source_nb_output_dims_domain
;
2320 newdep
->source_nb_output_dims_access
= (*dep
)->source_nb_output_dims_access
;
2321 newdep
->target_nb_output_dims_domain
= (*dep
)->target_nb_output_dims_domain
;
2322 newdep
->target_nb_output_dims_access
= (*dep
)->target_nb_output_dims_access
;
2323 newdep
->source_nb_local_dims_domain
= (*dep
)->source_nb_local_dims_domain
;
2324 newdep
->source_nb_local_dims_access
= (*dep
)->source_nb_local_dims_access
;
2325 newdep
->target_nb_local_dims_domain
= (*dep
)->target_nb_local_dims_domain
;
2326 newdep
->target_nb_local_dims_access
= (*dep
)->target_nb_local_dims_access
;
2327 newdep
->next
= (*dep
)->next
;
2328 (*dep
)->next
= newdep
;
2333 osl_relation_free(original_domain
);
2334 osl_relation_free(qp
);
2337 pip_quast_free(lexmax
);
2338 osl_relation_free(qp
);
2339 osl_relation_free(context
);
2345 * Compute the last writer for each RAW, WAW, and RAR dependence. This will
2346 * modify the dependence polyhedra. Be careful of any references to the old
2347 * dependence polyhedra. They are freed and new ones allocated.
2349 void candl_compute_last_writer(osl_dependence_p dep
, osl_scop_p scop
) {
2351 while (dep
!= NULL
) {
2352 if (dep
->type
!= OSL_DEPENDENCE_WAR
) {
2353 // printf("Last writer for dep %d: %d %d\n", count++, dep->source->usr->depth, dep->target->usr->depth);
2354 // candl_matrix_print(stdout, dep->domain);
2355 candl_dep_compute_lastwriter(&dep
, scop
);
2356 // candl_matrix_print(stdout, dep->domain);