10 #include <isl/constraint.h>
13 #include "translation.h"
19 static void set_prefix(pdg::node
*node
, const vector
<int>& prefix
, int l
)
21 node
->prefix
.resize(0);
22 for (int j
= 0; j
< l
-1; ++j
) {
23 node
->prefix
.push_back(prefix
[j
]);
24 node
->prefix
.push_back(-1);
26 node
->prefix
.push_back(prefix
[l
-1]);
29 /* A comparison function for sorting pdg::nodes based on their prefix.
31 struct earlier_prefix
:
32 public std::binary_function
<pdg::node
*, pdg::node
*, bool> {
33 bool operator()(pdg::node
*x
, pdg::node
*y
) {
34 for (int i
= 0; i
< x
->prefix
.size(); ++i
) {
35 if (x
->prefix
[i
] == -1 && y
->prefix
[i
] == -1)
37 assert(x
->prefix
[i
] != -1 && y
->prefix
[i
] != -1);
38 if (x
->prefix
[i
] < y
->prefix
[i
])
40 if (x
->prefix
[i
] > y
->prefix
[i
])
47 /* Normalize prefix to be an alternation between statement
48 * level dimensions and loop level dimensions.
49 * Return the number of statement level dimension.
51 * Since the algorithm assumes the input prefixes are ordered
52 * lexicographically, we perform it on a sorted list of nodes.
54 int normalize_prefix(PDG
*pdg
)
58 vector
<pdg::node
*> nodes
;
60 if (pdg
->nodes
.size() == 0)
63 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
)
64 nodes
.push_back(pdg
->nodes
[i
]);
65 std::sort(nodes
.begin(), nodes
.end(), earlier_prefix());
68 for (int j
= 0; j
< nodes
[0]->prefix
.size(); ++j
)
69 if (nodes
[0]->prefix
[j
] == -1)
73 for (i
= 1; i
< nodes
.size(); ++i
) {
75 pdg::node
*old_node
= nodes
[i
-1];
76 pdg::node
*node
= nodes
[i
];
80 for (int j
= 0; j
< node
->prefix
.size(); ++j
) {
82 assert(old_node
->prefix
[j
] <= node
->prefix
[j
]);
83 if (old_node
->prefix
[j
] != node
->prefix
[j
])
86 if (node
->prefix
[j
] == -1)
93 set_prefix(old_node
, prefix
, old_l
);
97 for (int j
= change_l
+1; j
< prefix
.size(); ++j
)
100 pdg::node
*node
= nodes
[nodes
.size()-1];
101 set_prefix(node
, prefix
, l
);
105 void set_schedule_from_prefix(PDG
*pdg
)
107 int statement_dims
= normalize_prefix(pdg
);
108 int dim
= 2 * statement_dims
- 1;
109 int nparam
= pdg
->params
.size();
110 isl_ctx
*ctx
= pdg
->get_isl_ctx();
112 assert(pdg
->dimension
== 0);
113 assert(pdg
->dimension
== pdg
->statement_dimensions
.size());
114 pdg
->dimension
= dim
;
115 for (int i
= 0; i
< dim
; ++i
)
116 pdg
->statement_dimensions
.push_back(1-(i
%2));
118 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
) {
119 pdg::node
*node
= pdg
->nodes
[i
];
120 isl_set
*set
= node
->source
->get_isl_set(ctx
);
121 isl_space
*space
= isl_set_get_space(set
);
124 if (isl_space_is_wrapping(space
))
125 space
= isl_space_domain(isl_space_unwrap(space
));
126 map
= isl_map_identity(isl_space_map_from_set(space
));
127 for (int j
= 0; 2 * j
< node
->prefix
.size(); ++j
) {
128 map
= isl_map_insert_dims(map
, isl_dim_out
, 2 * j
, 1);
129 map
= isl_map_fix_si(map
, isl_dim_out
, 2 * j
, node
->prefix
[2*j
]);
131 map
= isl_map_add_dims(map
, isl_dim_out
,
132 2 * statement_dims
- 1 - node
->prefix
.size());
133 for (int j
= node
->prefix
.size(); j
< 2 * statement_dims
- 1; ++j
)
134 map
= isl_map_fix_si(map
, isl_dim_out
, j
, 0);
135 node
->schedule
= new pdg::IslMap(map
);
139 /* Create a schedule for the domains "source" based on "pos" and "scale".
140 * The "extra" dimensions of source do not appear in the schedule
141 * since they have a unique value determined by the values of the "actual"
143 * If "source" has filters (in the range of the wrapped map), then
144 * we project out the filters so that the created schedule only applies
145 * to the actual iteration domain.
147 static pdg::IslMap
*create_schedule(PDG
*pdg
, pdg::IslSet
*source
,
148 vector
<int>& pos
, vector
<int>& scale
)
151 isl_ctx
*ctx
= pdg
->get_isl_ctx();
152 isl_set
*set
= source
->get_isl_set(ctx
);
153 isl_space
*space
= isl_set_get_space(set
);
158 if (isl_space_is_wrapping(space
))
159 space
= isl_space_domain(isl_space_unwrap(space
));
160 space
= isl_space_from_domain(space
);
162 space
= isl_space_add_dims(space
, isl_dim_out
, pdg
->dimension
);
163 bmap
= isl_basic_map_universe(isl_space_copy(space
));
164 ls
= isl_local_space_from_space(space
);
165 for (int i
= 0; i
< pdg
->dimension
; ++i
) {
167 c
= isl_equality_alloc(isl_local_space_copy(ls
));
168 isl_constraint_set_coefficient_si(c
, isl_dim_out
, i
, -1);
170 isl_constraint_set_coefficient_si(c
, isl_dim_in
,
172 bmap
= isl_basic_map_add_constraint(bmap
, c
);
174 isl_local_space_free(ls
);
176 map
= isl_map_from_basic_map(bmap
);
177 s
= new pdg::IslMap(map
);
182 static pdg::IslMap
*pull_back_schedule(PDG
*pdg
, pdg::IslSet
*source
,
183 pdg::IslMap
*schedule
, __isl_keep isl_map
*map
)
185 isl_ctx
*ctx
= pdg
->get_isl_ctx();
186 isl_map
*scat
= schedule
->get_isl_map(ctx
);
189 int dim
= pdg
->dimension
;
190 int this_dim
= isl_map_dim(map
, isl_dim_in
);
191 vector
<int> pos(dim
);
192 vector
<int> scale(dim
);
193 // k: position in pos
197 map
= isl_map_copy(map
);
198 map
= isl_map_apply_range(map
, scat
);
199 aff
= isl_map_affine_hull(map
);
200 aff
= isl_basic_map_remove_divs(aff
);
201 mat
= isl_basic_map_equalities_matrix(aff
, isl_dim_in
, isl_dim_out
,
202 isl_dim_div
, isl_dim_param
, isl_dim_cst
);
203 isl_basic_map_free(aff
);
205 for (j
= 0; j
< this_dim
; ++j
) {
209 int max_m
= j
+ dim
- this_dim
;
211 for (m
= min_m
; m
<= max_m
; ++m
) {
213 for (row
= 0; row
< isl_mat_rows(mat
); ++row
) {
215 v
= isl_mat_get_element_val(mat
,
217 s_v
= isl_val_get_num_si(v
);
221 v
= isl_mat_get_element_val(mat
, row
, j
);
222 i_v
= isl_val_get_num_si(v
);
232 else if (i_v
% s_v
== 0)
238 if (row
< isl_mat_rows(mat
))
251 for ( ; j
< this_dim
; ++j
) {
255 for ( ; k
< dim
; ++k
)
258 return create_schedule(pdg
, source
, pos
, scale
);
261 /* Return the dimension of the iteration domain of "node".
262 * If node->source is a wrapped map, then the iteration domain
263 * is in the domain of that map.
265 static int source_dim(pdg::node
*node
)
267 isl_space
*space
= node
->source
->get_dim();
270 if (isl_space_is_wrapping(space
)) {
271 space
= isl_space_unwrap(space
);
272 d
= isl_space_dim(space
, isl_dim_in
);
274 d
= isl_space_dim(space
, isl_dim_set
);
275 isl_space_free(space
);
279 void common_dimension(PDG
*pdg
)
281 isl_ctx
*ctx
= pdg
->get_isl_ctx();
282 int dim
= pdg
->dimension
;
283 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
) {
284 pdg::node
*node
= pdg
->nodes
[i
];
285 int dim_i
= source_dim(node
);
289 assert(pdg
->dimension
== pdg
->statement_dimensions
.size());
290 for (int i
= pdg
->dimension
; i
< dim
; ++i
)
291 pdg
->statement_dimensions
.push_back(0);
292 pdg
->dimension
= dim
;
293 vector
<int> pos(dim
);
294 vector
<int> scale(dim
);
295 for (int i
= 0; i
< dim
; ++i
) {
300 int todo
= pdg
->nodes
.size();
301 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
) {
302 pdg::node
*node
= pdg
->nodes
[i
];
303 if (source_dim(node
) != dim
)
305 node
->schedule
= create_schedule(pdg
, node
->source
, pos
, scale
);
311 pdg::dependence
*maxdep
= NULL
;
322 for (int i
= 0; i
< pdg
->dependences
.size(); ++i
) {
323 pdg::dependence
*dep
= pdg
->dependences
[i
];
324 if (dep
->type
== pdg::dependence::uninitialized
)
326 pdg::IslMap
*rel
= dep
->relation
;
327 if (dep
->to
->schedule
&& !dep
->from
->schedule
) {
328 w
[0] = rel
->output();
331 } else if (dep
->from
->schedule
&& !dep
->to
->schedule
) {
333 w
[1] = rel
->output();
337 w
[3] = dep
->array
? dep
->array
->dims
.size() : 0;
343 pdg::dependence
*dep
= maxdep
;
347 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
) {
348 pdg::node
*node
= pdg
->nodes
[i
];
352 dim_i
= source_dim(node
);
353 if (dim_i
> maxdim
) {
359 pdg::node
*node
= pdg
->nodes
[maxi
];
360 for (int i
= node
->source
->dim(); i
< pos
.size(); ++i
)
362 node
->schedule
= create_schedule(pdg
, node
->source
, pos
, scale
);
363 for (int i
= node
->source
->dim(); i
< pos
.size(); ++i
)
365 fprintf(stderr
, "WARNING: disconnected dependence graph\n");
367 isl_map
*dep_map
= dep
->relation
->get_isl_map(ctx
);
368 if (dep
->to
->schedule
) {
369 dep
->from
->schedule
= pull_back_schedule(pdg
,
371 dep
->to
->schedule
, dep_map
);
373 dep_map
= isl_map_reverse(dep_map
);
374 dep
->to
->schedule
= pull_back_schedule(pdg
,
376 dep
->from
->schedule
, dep_map
);
378 isl_map_free(dep_map
);
388 dvector() : d(NULL
) {}
389 dvector(__isl_take isl_set
*d
) : d(d
) {}
390 dvector(const dvector
©
) {
391 d
= isl_set_copy(copy
.d
);
393 dvector
&operator= (const dvector
&other
) {
395 d
= isl_set_copy(other
.d
);
402 bool combine(const dvector
&dv
, const dvector
&offset
);
405 void operator-= (dvector
&d1
, const dvector
&d2
)
407 isl_set
*neg
= isl_set_neg(isl_set_copy(d2
.d
));
408 d1
.d
= isl_set_sum(d1
.d
, neg
);
411 dvector
operator- (const dvector
&d
)
413 return dvector(isl_set_neg(isl_set_copy(d
.d
)));
416 void operator+= (dvector
&d1
, const dvector
&d2
)
418 d1
.d
= isl_set_sum(d1
.d
, isl_set_copy(d2
.d
));
421 dvector
operator+ (const dvector
&d1
, const dvector
&d2
)
423 return dvector(isl_set_sum(isl_set_copy(d1
.d
), isl_set_copy(d2
.d
)));
426 /* replace by dv + offset if dv + offset is smaller
427 * return true if dv + offset was smaller
429 bool dvector::combine(const dvector
&dv
, const dvector
&offset
)
432 dvector new_v
= dv
+ offset
;
433 new_v
.d
= isl_set_union(new_v
.d
, isl_set_copy(d
));
434 new_v
.d
= isl_set_lexmin(new_v
.d
);
435 equal
= isl_set_is_equal(new_v
.d
, d
);
439 new_v
.d
= isl_set_remove_divs(new_v
.d
);
440 new_v
.d
= isl_set_lexmin(new_v
.d
);
445 struct wdvector
: dvector
{
448 wdvector() : w(0), dvector(NULL
) {}
449 wdvector(int w
, __isl_take isl_set
*d
) : w(w
), dvector(d
) {}
452 wdvector
operator+ (const wdvector
&d1
, const dvector
&d2
)
454 return wdvector(d1
.w
,
455 isl_set_sum(isl_set_copy(d1
.d
), isl_set_copy(d2
.d
)));
458 /* Fairly arbitrary, but deterministic sorting of the nodes.
459 * In particular, the order does not depend on pointer values.
461 struct smaller_node_nr
463 bool operator()(const pdg::node
* n1
, const pdg::node
* n2
) const {
464 return n1
->nr
< n2
->nr
;
468 typedef map
<pdg::node
*,
469 map
<pdg::node
*, wdvector
, smaller_node_nr
>,
470 smaller_node_nr
>::iterator d_graph_iterator
;
474 map
<pdg::node
*, wdvector
, smaller_node_nr
>, smaller_node_nr
> data
;
476 void update(pdg::node
*from
, pdg::node
*to
, __isl_take isl_set
*ddv
,
480 void collect_related_nodes(set
<pdg::node
*> &nodes
, pdg::node
*node
);
483 void d_graph::update(pdg::node
*from
, pdg::node
*to
,
484 __isl_take isl_set
*ddv
, int weight
)
487 if (data
[from
].find(to
) == data
[from
].end())
488 data
[from
][to
] = wdvector(weight
, ddv
);
490 data
[from
][to
].w
+= weight
;
491 data
[from
][to
].d
= isl_set_union(data
[from
][to
].d
, ddv
);
495 void d_graph::minimize()
498 for (i
= data
.begin(); i
!= data
.end(); ++i
) {
499 pdg::node
*from
= (*i
).first
;
500 map
<pdg::node
*, wdvector
>::iterator j
;
501 for (j
= data
[from
].begin(); j
!= data
[from
].end(); ++j
) {
502 (*j
).second
.d
= isl_set_lexmin((*j
).second
.d
);
503 (*j
).second
.d
= isl_set_remove_divs((*j
).second
.d
);
504 (*j
).second
.d
= isl_set_lexmin((*j
).second
.d
);
505 (*j
).second
.d
= isl_set_coalesce((*j
).second
.d
);
510 void d_graph::collect_related_nodes(set
<pdg::node
*> &nodes
,
513 vector
<pdg::node
*> todo
;
515 todo
.push_back(node
);
517 while (!todo
.empty()) {
518 pdg::node
*node
= todo
.back();
520 if (nodes
.find(node
) != nodes
.end())
526 map
<pdg::node
*, wdvector
>::iterator j
;
527 for (j
= data
[node
].begin(); j
!= data
[node
].end(); ++j
) {
528 pdg::node
*node2
= (*j
).first
;
529 if (nodes
.find(node2
) != nodes
.end())
531 todo
.push_back(node2
);
533 for (i
= data
.begin(); i
!= data
.end(); ++i
) {
534 pdg::node
*node2
= (*i
).first
;
535 if (nodes
.find(node2
) != nodes
.end())
537 if ((*i
).second
.find(node
) == (*i
).second
.end())
539 todo
.push_back(node2
);
547 /* dependence distance offsets used during moving */
548 map
<pdg::node
*, dvector
> move_offsets
;
549 /* the relative offsets */
550 map
<pdg::node
*, map
<pdg::node
*, dvector
> > delays
;
551 /* the original distance vectors */
552 map
<pdg::node
*, map
<pdg::node
*, dvector
> > distances
;
553 /* the final offsets */
554 map
<pdg::node
*, dvector
> offsets
;
557 /* space of schedule domain */
560 combiner(PDG
*pdg
, d_graph
& distances
, int n_nodes
, bool move
,
561 __isl_keep isl_space
*space
) :
562 pdg(pdg
), graph(distances
), n_nodes(n_nodes
), move(move
),
567 void compute_move_offsets();
568 dvector
compute_relative_offset(pdg::node
* from
, pdg::node
*to
,
570 void set_relative_offset(pdg::node
* from
, pdg::node
*to
);
571 void update_graph(pdg::node
* from
, pdg::node
*to
);
572 void compute_absolute_offsets();
573 void handle_zero_dependences();
574 void handle_negative_offsets();
577 static __isl_give isl_set
*zero_set(__isl_take isl_space
*dim
)
580 int n
= isl_space_dim(dim
, isl_dim_set
);
581 set
= isl_set_universe(dim
);
582 for (int i
= 0; i
< n
; ++i
)
583 set
= isl_set_fix_si(set
, isl_dim_set
, i
, 0);
587 dvector
combiner::compute_relative_offset(pdg::node
* from
,
588 pdg::node
*to
, bool do_move
)
591 map
<pdg::node
*, dvector
> d
;
592 bool progress
= true;
593 map
<pdg::node
*, dvector
>::iterator i
;
595 d
[from
] = dvector(zero_set(isl_set_get_space(graph
.data
[from
][to
].d
)));
597 for (int k
= 0; k
< n_nodes
&& progress
; ++k
) {
598 map
<pdg::node
*, wdvector
>::iterator j
;
600 for (i
= d
.begin(); i
!= d
.end(); ++i
) {
601 pdg::node
*a
= (*i
).first
;
602 for (j
= graph
.data
[a
].begin();
603 j
!= graph
.data
[a
].end(); ++j
) {
604 pdg::node
*b
= (*j
).first
;
606 move_offsets
.find(a
) != move_offsets
.end())
607 (*j
).second
-= move_offsets
[a
];
608 if (d
.find(b
) == d
.end()) {
610 d
[b
] = (*j
).second
+ d
[a
];
613 p
= d
[b
].combine((*j
).second
, d
[a
]);
614 progress
= progress
|| p
;
617 move_offsets
.find(a
) != move_offsets
.end())
618 (*j
).second
+= move_offsets
[a
];
623 /* d[from] + d[from] < d[from] iff d[from] < 0 */
624 bool lexneg
= d
[from
].combine(d
[from
], d
[from
]);
634 void combiner::set_relative_offset(pdg::node
* from
, pdg::node
*to
)
638 delay
= compute_relative_offset(from
, to
, true);
640 delay
= compute_relative_offset(from
, to
, false);
642 delays
[from
][to
] = delay
;
645 void combiner::update_graph(pdg::node
* from
, pdg::node
*to
)
647 dvector offset
= delays
[from
][to
];
648 dvector neg_offset
= -offset
;
650 map
<pdg::node
*, wdvector
>::iterator j
;
651 for (j
= graph
.data
[to
].begin(); j
!= graph
.data
[to
].end(); ++j
) {
652 if ((*j
).first
== from
)
654 if (graph
.data
[from
].find((*j
).first
) == graph
.data
[from
].end())
655 graph
.data
[from
][(*j
).first
] = (*j
).second
+ neg_offset
;
657 graph
.data
[from
][(*j
).first
].combine((*j
).second
,
661 graph
.data
.erase(to
);
664 for (i
= graph
.data
.begin(); i
!= graph
.data
.end(); ++i
) {
665 if ((*i
).second
.find(to
) == (*i
).second
.end())
667 if ((*i
).first
!= from
) {
668 if ((*i
).second
.find(from
) == (*i
).second
.end())
669 (*i
).second
[from
] = (*i
).second
[to
] + offset
;
671 (*i
).second
[from
].combine((*i
).second
[to
], offset
);
673 (*i
).second
.erase(to
);
679 void combiner::compute_absolute_offsets()
681 pdg::node
*init
= (*graph
.data
.begin()).first
;
682 vector
<pdg::node
*> todo
;
683 todo
.push_back(init
);
684 offsets
[init
] = dvector(zero_set(isl_space_copy(space
)));
686 while (!todo
.empty()) {
687 pdg::node
*n
= todo
.back();
689 if (delays
.find(n
) == delays
.end())
692 map
<pdg::node
*, dvector
>::iterator i
;
693 for (i
= delays
[n
].begin(); i
!= delays
[n
].end(); ++i
) {
694 offsets
[(*i
).first
] = offsets
[n
] + (*i
).second
;
695 todo
.push_back((*i
).first
);
700 void combiner::handle_zero_dependences()
702 map
<pdg::node
*, set
<pdg::node
*> > succ
;
703 map
<pdg::node
*, int > prec
;
704 map
<pdg::node
*, map
<pdg::node
*, dvector
> >::iterator i
;
705 map
<pdg::node
*, dvector
>::iterator j
;
706 for (j
= offsets
.begin(); j
!= offsets
.end(); ++j
)
707 prec
[(*j
).first
] = 0;
709 for (i
= distances
.begin(); i
!= distances
.end(); ++i
)
710 for (j
= (*i
).second
.begin(); j
!= (*i
).second
.end(); ++j
) {
711 distances
[(*i
).first
][(*j
).first
] +=
713 distances
[(*i
).first
][(*j
).first
] -=
715 isl_set
*test
= distances
[(*i
).first
][(*j
).first
].d
;
716 isl_set
*zero
= zero_set(isl_set_get_space(test
));
717 zero
= isl_set_intersect(zero
, isl_set_copy(test
));
718 int has_zero
= !isl_set_is_empty(zero
);
721 succ
[(*i
).first
].insert((*j
).first
);
726 map
<pdg::node
*, int> final
;
727 for (j
= offsets
.begin(); j
!= offsets
.end(); ++j
) {
728 final
[(*j
).first
] = 0;
731 while (!prec
.empty()) {
732 map
<pdg::node
*, int >::iterator i
;
733 for (i
= prec
.begin(); (*i
).second
> 0; ++i
)
735 set
<pdg::node
*>::iterator j
;
736 for (j
= succ
[(*i
).first
].begin();
737 j
!= succ
[(*i
).first
].end(); ++j
) {
739 if (final
[(*j
)] <= final
[(*i
).first
])
740 final
[(*j
)] = final
[(*i
).first
] + 1;
745 int dim
= isl_set_dim((*offsets
.begin()).second
.d
, isl_dim_set
);
746 for (j
= offsets
.begin(); j
!= offsets
.end(); ++j
) {
747 (*j
).second
.d
= isl_set_add_dims((*j
).second
.d
, isl_dim_set
, 1);
748 (*j
).second
.d
= isl_set_fix_si((*j
).second
.d
, isl_dim_set
, dim
,
753 /* Remove negative offsets by shifting all offsets over the opposite
754 * of the most negative offsets in each direction.
756 void combiner::handle_negative_offsets()
758 int dim
= isl_set_dim((*offsets
.begin()).second
.d
, isl_dim_set
);
762 map
<pdg::node
*, dvector
>::iterator j
;
764 space
= isl_set_get_space((*offsets
.begin()).second
.d
);
765 set
= isl_set_universe(isl_space_copy(space
));
766 space
= isl_space_params(space
);
767 space
= isl_space_add_dims(space
, isl_dim_set
, 0);
768 shift
= isl_set_universe(space
);
770 for (int i
= 0; i
< dim
; ++i
)
771 set
= isl_set_fix_si(set
, isl_dim_set
, i
, 0);
773 for (j
= offsets
.begin(); j
!= offsets
.end(); ++j
)
774 set
= isl_set_union(set
, isl_set_copy((*j
).second
.d
));
776 for (int i
= 0; i
< dim
; ++i
) {
777 isl_pw_aff
*pa
= isl_set_dim_min(isl_set_copy(set
), i
);
778 pa
= isl_pw_aff_coalesce(pa
);
779 isl_set
*shift_i
= isl_set_from_pw_aff(pa
);
780 shift
= isl_set_flat_product(shift
, shift_i
);
783 shift
= isl_set_neg(shift
);
784 shift
= isl_set_gist_params(shift
, pdg
->get_context_isl_set());
785 for (j
= offsets
.begin(); j
!= offsets
.end(); ++j
)
786 (*j
).second
.d
= isl_set_sum((*j
).second
.d
, isl_set_copy(shift
));
792 /* Builds a relation that connects iterations of D to the next iteration */
793 static __isl_give isl_map
*next_iteration_map(__isl_take isl_set
*dom
)
795 isl_space
*dims
= isl_set_get_space(dom
);
796 isl_map
*lt
= isl_map_lex_lt(dims
);
797 lt
= isl_map_intersect_domain(lt
, isl_set_copy(dom
));
798 lt
= isl_map_intersect_range(lt
, isl_set_copy(dom
));
799 lt
= isl_map_partial_lexmax(lt
, dom
, NULL
);
803 void combiner::compute_move_offsets()
806 isl_ctx
*ctx
= pdg
->get_isl_ctx();
808 for (i
= graph
.data
.begin(); i
!= graph
.data
.end(); ++i
) {
809 pdg::node
*node
= (*i
).first
;
810 isl_set
*dom
= node
->source
->get_isl_set(ctx
);
811 isl_set
*context
= pdg
->get_context_isl_set();
812 dom
= isl_set_intersect_params(dom
, context
);
813 isl_map
*scat
= (*i
).first
->schedule
->get_isl_map(ctx
);
814 dom
= isl_set_apply(dom
, scat
);
815 isl_map
*next
= next_iteration_map(dom
);
816 isl_set
*step
= isl_map_deltas(next
);
817 step
= isl_set_lexmin(step
);
818 if (isl_set_is_empty(step
))
821 move_offsets
[node
] = dvector(step
);
825 void combiner::combine()
828 map
<pdg::node
*, wdvector
>::iterator j
;
831 compute_move_offsets();
833 for (i
= graph
.data
.begin(); i
!= graph
.data
.end(); ++i
)
834 for (j
= (*i
).second
.begin(); j
!= (*i
).second
.end(); ++j
)
835 distances
[(*i
).first
][(*j
).first
] = (*j
).second
;
837 while (n_nodes
> 1) {
839 pdg::node
* max_from
= NULL
;
840 pdg::node
* max_to
= NULL
;
842 map
<pdg::node
*, wdvector
>::iterator j
;
843 for (i
= graph
.data
.begin(); i
!= graph
.data
.end(); ++i
)
844 for (j
= (*i
).second
.begin();
845 j
!= (*i
).second
.end(); ++j
) {
846 if ((*j
).second
.w
<= max
)
849 max_from
= (*i
).first
;
854 set_relative_offset(max_from
, max_to
);
855 update_graph(max_from
, max_to
);
858 compute_absolute_offsets();
859 handle_zero_dependences();
860 handle_negative_offsets();
863 bool translate(PDG
*pdg
, bool move
)
865 isl_ctx
*ctx
= pdg
->get_isl_ctx();
869 if (pdg
->nodes
.size() == 0)
872 space
= isl_map_get_space(pdg
->nodes
[0]->schedule
->map
);
873 space
= isl_space_range(space
);
875 for (int i
= 0; i
< pdg
->dependences
.size(); ++i
) {
876 pdg::dependence
*dep
= pdg
->dependences
[i
];
877 if (dep
->type
== pdg::dependence::uninitialized
)
879 if (dep
->from
== dep
->to
)
881 int weight
= dep
->type
== pdg::dependence::anti
? 0 : 1;
882 pdg::node
* from
= dep
->from
;
883 pdg::node
* to
= dep
->to
;
886 isl_map
*dep_map
= dep
->relation
->get_isl_map(ctx
);
887 scat
= from
->schedule
->get_isl_map(ctx
);
888 dep_map
= isl_map_apply_domain(dep_map
, scat
);
889 scat
= to
->schedule
->get_isl_map(ctx
);
890 dep_map
= isl_map_apply_range(dep_map
, scat
);
891 ddv
= isl_map_deltas(dep_map
);
892 distances
.update(from
, to
, ddv
, weight
);
895 distances
.minimize();
897 set
<pdg::node
*> nodes_done
;
898 /* split the dependence graph into connected subgraphs
899 * and compute offsets in each subgraph
901 while (nodes_done
.size() < pdg
->nodes
.size()) {
902 set
<pdg::node
*> current_nodes
;
903 d_graph current_distances
;
906 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
) {
907 node
= pdg
->nodes
[i
];
908 if (nodes_done
.find(node
) != nodes_done
.end())
913 distances
.collect_related_nodes(current_nodes
, node
);
915 set
<pdg::node
*>::iterator i
;
916 for (i
= current_nodes
.begin(); i
!= current_nodes
.end(); ++i
) {
917 current_distances
.data
[(*i
)] = distances
.data
[(*i
)];
920 combiner
c(pdg
, current_distances
, current_nodes
.size(),
924 for (i
= current_nodes
.begin(); i
!= current_nodes
.end(); ++i
) {
925 pdg::node
*node
= *i
;
926 nodes_done
.insert(node
);
928 isl_map
*s
= node
->schedule
->get_isl_map(ctx
);
930 isl_space
*dim
= isl_set_get_space(c
.offsets
[node
].d
);
931 int d
= isl_space_dim(dim
, isl_dim_set
) - 1;
932 isl_map
*id
= isl_map_identity(
933 isl_space_map_from_set(isl_space_copy(dim
)));
934 isl_set
*u
= isl_set_universe(dim
);
935 isl_map
*off
= isl_map_from_domain_and_range(u
,
936 isl_set_copy(c
.offsets
[node
].d
));
937 id
= isl_map_project_out(id
, isl_dim_in
, d
, 1);
938 id
= isl_map_fix_si(id
, isl_dim_out
, d
, 0);
939 off
= isl_map_project_out(off
, isl_dim_in
, d
, 1);
940 off
= isl_map_sum(id
, off
);
941 s
= isl_map_apply_range(s
, off
);
943 delete node
->schedule
;
944 node
->schedule
= new IslMap(s
);
948 pdg
->statement_dimensions
.push_back(1);
951 isl_space_free(space
);