15 #include "translation.h"
21 static void set_prefix(pdg::node
*node
, const vector
<int>& prefix
, int l
)
23 node
->prefix
.resize(0);
24 for (int j
= 0; j
< l
-1; ++j
) {
25 node
->prefix
.push_back(prefix
[j
]);
26 node
->prefix
.push_back(-1);
28 node
->prefix
.push_back(prefix
[l
-1]);
31 /* A comparison function for sorting pdg::nodes based on their prefix.
33 struct earlier_prefix
{
34 bool operator()(pdg::node
*x
, pdg::node
*y
) {
35 for (int i
= 0; i
< x
->prefix
.size(); ++i
) {
36 if (x
->prefix
[i
] == -1 && y
->prefix
[i
] == -1)
38 assert(x
->prefix
[i
] != -1 && y
->prefix
[i
] != -1);
39 if (x
->prefix
[i
] < y
->prefix
[i
])
41 if (x
->prefix
[i
] > y
->prefix
[i
])
48 /* Normalize prefix to be an alternation between statement
49 * level dimensions and loop level dimensions.
50 * Return the number of statement level dimension.
52 * Since the algorithm assumes the input prefixes are ordered
53 * lexicographically, we perform it on a sorted list of nodes.
55 int normalize_prefix(PDG
*pdg
)
59 vector
<pdg::node
*> nodes
;
61 if (pdg
->nodes
.size() == 0)
64 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
)
65 nodes
.push_back(pdg
->nodes
[i
]);
66 std::sort(nodes
.begin(), nodes
.end(), earlier_prefix());
69 for (int j
= 0; j
< nodes
[0]->prefix
.size(); ++j
)
70 if (nodes
[0]->prefix
[j
] == -1)
74 for (i
= 1; i
< nodes
.size(); ++i
) {
76 pdg::node
*old_node
= nodes
[i
-1];
77 pdg::node
*node
= nodes
[i
];
81 for (int j
= 0; j
< node
->prefix
.size(); ++j
) {
83 assert(old_node
->prefix
[j
] <= node
->prefix
[j
]);
84 if (old_node
->prefix
[j
] != node
->prefix
[j
])
87 if (node
->prefix
[j
] == -1)
94 set_prefix(old_node
, prefix
, old_l
);
98 for (int j
= change_l
+1; j
< prefix
.size(); ++j
)
101 pdg::node
*node
= nodes
[nodes
.size()-1];
102 set_prefix(node
, prefix
, l
);
106 void set_schedule_from_prefix(PDG
*pdg
)
108 int statement_dims
= normalize_prefix(pdg
);
109 int dim
= 2 * statement_dims
- 1;
110 int nparam
= pdg
->params
.size();
111 isl_ctx
*ctx
= pdg
->get_isl_ctx();
113 assert(pdg
->dimension
== 0);
114 assert(pdg
->dimension
== pdg
->statement_dimensions
.size());
115 pdg
->dimension
= dim
;
116 for (int i
= 0; i
< dim
; ++i
)
117 pdg
->statement_dimensions
.push_back(1-(i
%2));
119 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
) {
120 pdg::node
*node
= pdg
->nodes
[i
];
121 isl_set
*set
= node
->source
->get_isl_set(ctx
);
122 isl_space
*space
= isl_set_get_space(set
);
125 if (isl_space_is_wrapping(space
))
126 space
= isl_space_domain(isl_space_unwrap(space
));
127 map
= isl_map_identity(isl_space_map_from_set(space
));
128 for (int j
= 0; 2 * j
< node
->prefix
.size(); ++j
) {
129 map
= isl_map_insert_dims(map
, isl_dim_out
, 2 * j
, 1);
130 map
= isl_map_fix_si(map
, isl_dim_out
, 2 * j
, node
->prefix
[2*j
]);
132 map
= isl_map_add_dims(map
, isl_dim_out
,
133 2 * statement_dims
- 1 - node
->prefix
.size());
134 for (int j
= node
->prefix
.size(); j
< 2 * statement_dims
- 1; ++j
)
135 map
= isl_map_fix_si(map
, isl_dim_out
, j
, 0);
136 node
->schedule
= new pdg::IslMap(map
);
140 /* Create a schedule for the domains "source" based on "pos" and "scale".
141 * The "extra" dimensions of source do not appear in the schedule
142 * since they have a unique value determined by the values of the "actual"
144 * If "source" has filters (in the range of the wrapped map), then
145 * we project out the filters so that the created schedule only applies
146 * to the actual iteration domain.
148 static pdg::IslMap
*create_schedule(PDG
*pdg
, pdg::IslSet
*source
,
149 vector
<int>& pos
, vector
<int>& scale
)
152 isl_ctx
*ctx
= pdg
->get_isl_ctx();
153 isl_set
*set
= source
->get_isl_set(ctx
);
154 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 ma
= isl_multi_aff_zero(space
);
164 for (int i
= 0; i
< pdg
->dimension
; ++i
) {
169 aff
= isl_multi_aff_get_aff(ma
, i
);
170 aff
= isl_aff_set_coefficient_si(aff
, isl_dim_in
,
172 ma
= isl_multi_aff_set_aff(ma
, i
, aff
);
175 map
= isl_map_from_multi_aff(ma
);
176 s
= new pdg::IslMap(map
);
181 static pdg::IslMap
*pull_back_schedule(PDG
*pdg
, pdg::IslSet
*source
,
182 pdg::IslMap
*schedule
, __isl_keep isl_map
*map
)
184 isl_ctx
*ctx
= pdg
->get_isl_ctx();
185 isl_map
*scat
= schedule
->get_isl_map(ctx
);
188 int dim
= pdg
->dimension
;
189 int this_dim
= isl_map_dim(map
, isl_dim_in
);
190 vector
<int> pos(dim
);
191 vector
<int> scale(dim
);
192 // k: position in pos
196 map
= isl_map_copy(map
);
197 map
= isl_map_apply_range(map
, scat
);
198 aff
= isl_map_affine_hull(map
);
199 aff
= isl_basic_map_remove_divs(aff
);
200 mat
= isl_basic_map_equalities_matrix(aff
, isl_dim_in
, isl_dim_out
,
201 isl_dim_div
, isl_dim_param
, isl_dim_cst
);
202 isl_basic_map_free(aff
);
204 for (j
= 0; j
< this_dim
; ++j
) {
208 int max_m
= j
+ dim
- this_dim
;
210 for (m
= min_m
; m
<= max_m
; ++m
) {
212 for (row
= 0; row
< isl_mat_rows(mat
); ++row
) {
214 v
= isl_mat_get_element_val(mat
,
216 s_v
= isl_val_get_num_si(v
);
220 v
= isl_mat_get_element_val(mat
, row
, j
);
221 i_v
= isl_val_get_num_si(v
);
231 else if (i_v
% s_v
== 0)
237 if (row
< isl_mat_rows(mat
))
250 for ( ; j
< this_dim
; ++j
) {
254 for ( ; k
< dim
; ++k
)
257 return create_schedule(pdg
, source
, pos
, scale
);
260 /* Return the dimension of the iteration domain of "node".
261 * If node->source is a wrapped map, then the iteration domain
262 * is in the domain of that map.
264 static int source_dim(pdg::node
*node
)
266 isl_space
*space
= node
->source
->get_dim();
269 if (isl_space_is_wrapping(space
)) {
270 space
= isl_space_unwrap(space
);
271 d
= isl_space_dim(space
, isl_dim_in
);
273 d
= isl_space_dim(space
, isl_dim_set
);
274 isl_space_free(space
);
278 void common_dimension(PDG
*pdg
)
280 isl_ctx
*ctx
= pdg
->get_isl_ctx();
281 int dim
= pdg
->dimension
;
282 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
) {
283 pdg::node
*node
= pdg
->nodes
[i
];
284 int dim_i
= source_dim(node
);
288 assert(pdg
->dimension
== pdg
->statement_dimensions
.size());
289 for (int i
= pdg
->dimension
; i
< dim
; ++i
)
290 pdg
->statement_dimensions
.push_back(0);
291 pdg
->dimension
= dim
;
292 vector
<int> pos(dim
);
293 vector
<int> scale(dim
);
294 for (int i
= 0; i
< dim
; ++i
) {
299 int todo
= pdg
->nodes
.size();
300 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
) {
301 pdg::node
*node
= pdg
->nodes
[i
];
302 if (source_dim(node
) != dim
)
304 node
->schedule
= create_schedule(pdg
, node
->source
, pos
, scale
);
310 pdg::dependence
*maxdep
= NULL
;
321 for (int i
= 0; i
< pdg
->dependences
.size(); ++i
) {
322 pdg::dependence
*dep
= pdg
->dependences
[i
];
323 if (dep
->type
== pdg::dependence::uninitialized
)
325 pdg::IslMap
*rel
= dep
->relation
;
326 if (dep
->to
->schedule
&& !dep
->from
->schedule
) {
327 w
[0] = rel
->output();
330 } else if (dep
->from
->schedule
&& !dep
->to
->schedule
) {
332 w
[1] = rel
->output();
336 w
[3] = dep
->array
? dep
->array
->dims
.size() : 0;
342 pdg::dependence
*dep
= maxdep
;
346 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
) {
347 pdg::node
*node
= pdg
->nodes
[i
];
351 dim_i
= source_dim(node
);
352 if (dim_i
> maxdim
) {
358 pdg::node
*node
= pdg
->nodes
[maxi
];
359 for (int i
= node
->source
->dim(); i
< pos
.size(); ++i
)
361 node
->schedule
= create_schedule(pdg
, node
->source
, pos
, scale
);
362 for (int i
= node
->source
->dim(); i
< pos
.size(); ++i
)
364 fprintf(stderr
, "WARNING: disconnected dependence graph\n");
366 isl_map
*dep_map
= dep
->relation
->get_isl_map(ctx
);
367 if (dep
->to
->schedule
) {
368 dep
->from
->schedule
= pull_back_schedule(pdg
,
370 dep
->to
->schedule
, dep_map
);
372 dep_map
= isl_map_reverse(dep_map
);
373 dep
->to
->schedule
= pull_back_schedule(pdg
,
375 dep
->from
->schedule
, dep_map
);
377 isl_map_free(dep_map
);
387 dvector() : d(NULL
) {}
388 dvector(__isl_take isl_set
*d
) : d(d
) {}
389 dvector(const dvector
©
) {
390 d
= isl_set_copy(copy
.d
);
392 dvector
&operator= (const dvector
&other
) {
394 d
= isl_set_copy(other
.d
);
401 bool combine(const dvector
&dv
, const dvector
&offset
);
404 void operator-= (dvector
&d1
, const dvector
&d2
)
406 isl_set
*neg
= isl_set_neg(isl_set_copy(d2
.d
));
407 d1
.d
= isl_set_sum(d1
.d
, neg
);
410 dvector
operator- (const dvector
&d
)
412 return dvector(isl_set_neg(isl_set_copy(d
.d
)));
415 void operator+= (dvector
&d1
, const dvector
&d2
)
417 d1
.d
= isl_set_sum(d1
.d
, isl_set_copy(d2
.d
));
420 dvector
operator+ (const dvector
&d1
, const dvector
&d2
)
422 return dvector(isl_set_sum(isl_set_copy(d1
.d
), isl_set_copy(d2
.d
)));
425 /* replace by dv + offset if dv + offset is smaller
426 * return true if dv + offset was smaller
428 bool dvector::combine(const dvector
&dv
, const dvector
&offset
)
431 dvector new_v
= dv
+ offset
;
432 new_v
.d
= isl_set_union(new_v
.d
, isl_set_copy(d
));
433 new_v
.d
= isl_set_lexmin(new_v
.d
);
434 equal
= isl_set_is_equal(new_v
.d
, d
);
438 new_v
.d
= isl_set_remove_divs(new_v
.d
);
439 new_v
.d
= isl_set_lexmin(new_v
.d
);
444 struct wdvector
: dvector
{
447 wdvector() : w(0), dvector(NULL
) {}
448 wdvector(int w
, __isl_take isl_set
*d
) : w(w
), dvector(d
) {}
451 wdvector
operator+ (const wdvector
&d1
, const dvector
&d2
)
453 return wdvector(d1
.w
,
454 isl_set_sum(isl_set_copy(d1
.d
), isl_set_copy(d2
.d
)));
457 /* Fairly arbitrary, but deterministic sorting of the nodes.
458 * In particular, the order does not depend on pointer values.
460 struct smaller_node_nr
462 bool operator()(const pdg::node
* n1
, const pdg::node
* n2
) const {
463 return n1
->nr
< n2
->nr
;
467 typedef map
<pdg::node
*,
468 map
<pdg::node
*, wdvector
, smaller_node_nr
>,
469 smaller_node_nr
>::iterator d_graph_iterator
;
473 map
<pdg::node
*, wdvector
, smaller_node_nr
>, smaller_node_nr
> data
;
475 void update(pdg::node
*from
, pdg::node
*to
, __isl_take isl_set
*ddv
,
479 void collect_related_nodes(set
<pdg::node
*> &nodes
, pdg::node
*node
);
482 void d_graph::update(pdg::node
*from
, pdg::node
*to
,
483 __isl_take isl_set
*ddv
, int weight
)
486 if (data
[from
].find(to
) == data
[from
].end())
487 data
[from
][to
] = wdvector(weight
, ddv
);
489 data
[from
][to
].w
+= weight
;
490 data
[from
][to
].d
= isl_set_union(data
[from
][to
].d
, ddv
);
494 void d_graph::minimize()
497 for (i
= data
.begin(); i
!= data
.end(); ++i
) {
498 pdg::node
*from
= (*i
).first
;
499 map
<pdg::node
*, wdvector
>::iterator j
;
500 for (j
= data
[from
].begin(); j
!= data
[from
].end(); ++j
) {
501 (*j
).second
.d
= isl_set_lexmin((*j
).second
.d
);
502 (*j
).second
.d
= isl_set_remove_divs((*j
).second
.d
);
503 (*j
).second
.d
= isl_set_lexmin((*j
).second
.d
);
504 (*j
).second
.d
= isl_set_coalesce((*j
).second
.d
);
509 void d_graph::collect_related_nodes(set
<pdg::node
*> &nodes
,
512 vector
<pdg::node
*> todo
;
514 todo
.push_back(node
);
516 while (!todo
.empty()) {
517 pdg::node
*node
= todo
.back();
519 if (nodes
.find(node
) != nodes
.end())
525 map
<pdg::node
*, wdvector
>::iterator j
;
526 for (j
= data
[node
].begin(); j
!= data
[node
].end(); ++j
) {
527 pdg::node
*node2
= (*j
).first
;
528 if (nodes
.find(node2
) != nodes
.end())
530 todo
.push_back(node2
);
532 for (i
= data
.begin(); i
!= data
.end(); ++i
) {
533 pdg::node
*node2
= (*i
).first
;
534 if (nodes
.find(node2
) != nodes
.end())
536 if ((*i
).second
.find(node
) == (*i
).second
.end())
538 todo
.push_back(node2
);
546 /* dependence distance offsets used during moving */
547 map
<pdg::node
*, dvector
> move_offsets
;
548 /* the relative offsets */
549 map
<pdg::node
*, map
<pdg::node
*, dvector
> > delays
;
550 /* the original distance vectors */
551 map
<pdg::node
*, map
<pdg::node
*, dvector
> > distances
;
552 /* the final offsets */
553 map
<pdg::node
*, dvector
> offsets
;
556 /* space of schedule domain */
559 combiner(PDG
*pdg
, d_graph
& distances
, int n_nodes
, bool move
,
560 __isl_keep isl_space
*space
) :
561 pdg(pdg
), graph(distances
), n_nodes(n_nodes
), move(move
),
566 void compute_move_offsets();
567 dvector
compute_relative_offset(pdg::node
* from
, pdg::node
*to
,
569 void set_relative_offset(pdg::node
* from
, pdg::node
*to
);
570 void update_graph(pdg::node
* from
, pdg::node
*to
);
571 void compute_absolute_offsets();
572 void handle_zero_dependences();
573 void handle_negative_offsets();
576 static __isl_give isl_set
*zero_set(__isl_take isl_space
*dim
)
579 int n
= isl_space_dim(dim
, isl_dim_set
);
580 set
= isl_set_universe(dim
);
581 for (int i
= 0; i
< n
; ++i
)
582 set
= isl_set_fix_si(set
, isl_dim_set
, i
, 0);
586 dvector
combiner::compute_relative_offset(pdg::node
* from
,
587 pdg::node
*to
, bool do_move
)
590 map
<pdg::node
*, dvector
> d
;
591 bool progress
= true;
592 map
<pdg::node
*, dvector
>::iterator i
;
594 d
[from
] = dvector(zero_set(isl_set_get_space(graph
.data
[from
][to
].d
)));
596 for (int k
= 0; k
< n_nodes
&& progress
; ++k
) {
597 map
<pdg::node
*, wdvector
>::iterator j
;
599 for (i
= d
.begin(); i
!= d
.end(); ++i
) {
600 pdg::node
*a
= (*i
).first
;
601 for (j
= graph
.data
[a
].begin();
602 j
!= graph
.data
[a
].end(); ++j
) {
603 pdg::node
*b
= (*j
).first
;
605 move_offsets
.find(a
) != move_offsets
.end())
606 (*j
).second
-= move_offsets
[a
];
607 if (d
.find(b
) == d
.end()) {
609 d
[b
] = (*j
).second
+ d
[a
];
612 p
= d
[b
].combine((*j
).second
, d
[a
]);
613 progress
= progress
|| p
;
616 move_offsets
.find(a
) != move_offsets
.end())
617 (*j
).second
+= move_offsets
[a
];
622 /* d[from] + d[from] < d[from] iff d[from] < 0 */
623 bool lexneg
= d
[from
].combine(d
[from
], d
[from
]);
633 void combiner::set_relative_offset(pdg::node
* from
, pdg::node
*to
)
637 delay
= compute_relative_offset(from
, to
, true);
639 delay
= compute_relative_offset(from
, to
, false);
641 delays
[from
][to
] = delay
;
644 void combiner::update_graph(pdg::node
* from
, pdg::node
*to
)
646 dvector offset
= delays
[from
][to
];
647 dvector neg_offset
= -offset
;
649 map
<pdg::node
*, wdvector
>::iterator j
;
650 for (j
= graph
.data
[to
].begin(); j
!= graph
.data
[to
].end(); ++j
) {
651 if ((*j
).first
== from
)
653 if (graph
.data
[from
].find((*j
).first
) == graph
.data
[from
].end())
654 graph
.data
[from
][(*j
).first
] = (*j
).second
+ neg_offset
;
656 graph
.data
[from
][(*j
).first
].combine((*j
).second
,
660 graph
.data
.erase(to
);
663 for (i
= graph
.data
.begin(); i
!= graph
.data
.end(); ++i
) {
664 if ((*i
).second
.find(to
) == (*i
).second
.end())
666 if ((*i
).first
!= from
) {
667 if ((*i
).second
.find(from
) == (*i
).second
.end())
668 (*i
).second
[from
] = (*i
).second
[to
] + offset
;
670 (*i
).second
[from
].combine((*i
).second
[to
], offset
);
672 (*i
).second
.erase(to
);
678 void combiner::compute_absolute_offsets()
680 pdg::node
*init
= (*graph
.data
.begin()).first
;
681 vector
<pdg::node
*> todo
;
682 todo
.push_back(init
);
683 offsets
[init
] = dvector(zero_set(isl_space_copy(space
)));
685 while (!todo
.empty()) {
686 pdg::node
*n
= todo
.back();
688 if (delays
.find(n
) == delays
.end())
691 map
<pdg::node
*, dvector
>::iterator i
;
692 for (i
= delays
[n
].begin(); i
!= delays
[n
].end(); ++i
) {
693 offsets
[(*i
).first
] = offsets
[n
] + (*i
).second
;
694 todo
.push_back((*i
).first
);
699 void combiner::handle_zero_dependences()
701 map
<pdg::node
*, set
<pdg::node
*> > succ
;
702 map
<pdg::node
*, int > prec
;
703 map
<pdg::node
*, map
<pdg::node
*, dvector
> >::iterator i
;
704 map
<pdg::node
*, dvector
>::iterator j
;
705 for (j
= offsets
.begin(); j
!= offsets
.end(); ++j
)
706 prec
[(*j
).first
] = 0;
708 for (i
= distances
.begin(); i
!= distances
.end(); ++i
)
709 for (j
= (*i
).second
.begin(); j
!= (*i
).second
.end(); ++j
) {
710 distances
[(*i
).first
][(*j
).first
] +=
712 distances
[(*i
).first
][(*j
).first
] -=
714 isl_set
*test
= distances
[(*i
).first
][(*j
).first
].d
;
715 isl_set
*zero
= zero_set(isl_set_get_space(test
));
716 zero
= isl_set_intersect(zero
, isl_set_copy(test
));
717 int has_zero
= !isl_set_is_empty(zero
);
720 succ
[(*i
).first
].insert((*j
).first
);
725 map
<pdg::node
*, int> final
;
726 for (j
= offsets
.begin(); j
!= offsets
.end(); ++j
) {
727 final
[(*j
).first
] = 0;
730 while (!prec
.empty()) {
731 map
<pdg::node
*, int >::iterator i
;
732 for (i
= prec
.begin(); (*i
).second
> 0; ++i
)
734 set
<pdg::node
*>::iterator j
;
735 for (j
= succ
[(*i
).first
].begin();
736 j
!= succ
[(*i
).first
].end(); ++j
) {
738 if (final
[(*j
)] <= final
[(*i
).first
])
739 final
[(*j
)] = final
[(*i
).first
] + 1;
744 int dim
= isl_set_dim((*offsets
.begin()).second
.d
, isl_dim_set
);
745 for (j
= offsets
.begin(); j
!= offsets
.end(); ++j
) {
746 (*j
).second
.d
= isl_set_add_dims((*j
).second
.d
, isl_dim_set
, 1);
747 (*j
).second
.d
= isl_set_fix_si((*j
).second
.d
, isl_dim_set
, dim
,
752 /* Remove negative offsets by shifting all offsets over the opposite
753 * of the most negative offsets in each direction.
755 void combiner::handle_negative_offsets()
757 int dim
= isl_set_dim((*offsets
.begin()).second
.d
, isl_dim_set
);
761 map
<pdg::node
*, dvector
>::iterator j
;
763 space
= isl_set_get_space((*offsets
.begin()).second
.d
);
764 set
= isl_set_universe(isl_space_copy(space
));
765 space
= isl_space_params(space
);
766 space
= isl_space_add_unnamed_tuple_ui(space
, 0);
767 shift
= isl_set_universe(space
);
769 for (int i
= 0; i
< dim
; ++i
)
770 set
= isl_set_fix_si(set
, isl_dim_set
, i
, 0);
772 for (j
= offsets
.begin(); j
!= offsets
.end(); ++j
)
773 set
= isl_set_union(set
, isl_set_copy((*j
).second
.d
));
775 for (int i
= 0; i
< dim
; ++i
) {
776 isl_pw_aff
*pa
= isl_set_dim_min(isl_set_copy(set
), i
);
777 pa
= isl_pw_aff_coalesce(pa
);
778 isl_set
*shift_i
= isl_set_from_pw_aff(pa
);
779 shift
= isl_set_flat_product(shift
, shift_i
);
782 shift
= isl_set_neg(shift
);
783 shift
= isl_set_gist_params(shift
, pdg
->get_context_isl_set());
784 for (j
= offsets
.begin(); j
!= offsets
.end(); ++j
)
785 (*j
).second
.d
= isl_set_sum((*j
).second
.d
, isl_set_copy(shift
));
791 /* Builds a relation that connects iterations of D to the next iteration */
792 static __isl_give isl_map
*next_iteration_map(__isl_take isl_set
*dom
)
794 isl_space
*dims
= isl_set_get_space(dom
);
795 isl_map
*lt
= isl_map_lex_lt(dims
);
796 lt
= isl_map_intersect_domain(lt
, isl_set_copy(dom
));
797 lt
= isl_map_intersect_range(lt
, isl_set_copy(dom
));
798 lt
= isl_map_partial_lexmax(lt
, dom
, NULL
);
802 void combiner::compute_move_offsets()
805 isl_ctx
*ctx
= pdg
->get_isl_ctx();
807 for (i
= graph
.data
.begin(); i
!= graph
.data
.end(); ++i
) {
808 pdg::node
*node
= (*i
).first
;
809 isl_set
*dom
= node
->source
->get_isl_set(ctx
);
810 isl_set
*context
= pdg
->get_context_isl_set();
811 dom
= isl_set_intersect_params(dom
, context
);
812 isl_map
*scat
= (*i
).first
->schedule
->get_isl_map(ctx
);
813 dom
= isl_set_apply(dom
, scat
);
814 isl_map
*next
= next_iteration_map(dom
);
815 isl_set
*step
= isl_map_deltas(next
);
816 step
= isl_set_lexmin(step
);
817 if (isl_set_is_empty(step
))
820 move_offsets
[node
] = dvector(step
);
824 void combiner::combine()
827 map
<pdg::node
*, wdvector
>::iterator j
;
830 compute_move_offsets();
832 for (i
= graph
.data
.begin(); i
!= graph
.data
.end(); ++i
)
833 for (j
= (*i
).second
.begin(); j
!= (*i
).second
.end(); ++j
)
834 distances
[(*i
).first
][(*j
).first
] = (*j
).second
;
836 while (n_nodes
> 1) {
838 pdg::node
* max_from
= NULL
;
839 pdg::node
* max_to
= NULL
;
841 map
<pdg::node
*, wdvector
>::iterator j
;
842 for (i
= graph
.data
.begin(); i
!= graph
.data
.end(); ++i
)
843 for (j
= (*i
).second
.begin();
844 j
!= (*i
).second
.end(); ++j
) {
845 if ((*j
).second
.w
<= max
)
848 max_from
= (*i
).first
;
853 set_relative_offset(max_from
, max_to
);
854 update_graph(max_from
, max_to
);
857 compute_absolute_offsets();
858 handle_zero_dependences();
859 handle_negative_offsets();
862 bool translate(PDG
*pdg
, bool move
)
864 isl_ctx
*ctx
= pdg
->get_isl_ctx();
868 if (pdg
->nodes
.size() == 0)
871 space
= isl_map_get_space(pdg
->nodes
[0]->schedule
->map
);
872 space
= isl_space_range(space
);
874 for (int i
= 0; i
< pdg
->dependences
.size(); ++i
) {
875 pdg::dependence
*dep
= pdg
->dependences
[i
];
876 if (dep
->type
== pdg::dependence::uninitialized
)
878 if (dep
->from
== dep
->to
)
880 int weight
= dep
->type
== pdg::dependence::anti
? 0 : 1;
881 pdg::node
* from
= dep
->from
;
882 pdg::node
* to
= dep
->to
;
885 isl_map
*dep_map
= dep
->relation
->get_isl_map(ctx
);
886 scat
= from
->schedule
->get_isl_map(ctx
);
887 dep_map
= isl_map_apply_domain(dep_map
, scat
);
888 scat
= to
->schedule
->get_isl_map(ctx
);
889 dep_map
= isl_map_apply_range(dep_map
, scat
);
890 ddv
= isl_map_deltas(dep_map
);
891 distances
.update(from
, to
, ddv
, weight
);
894 distances
.minimize();
896 set
<pdg::node
*> nodes_done
;
897 /* split the dependence graph into connected subgraphs
898 * and compute offsets in each subgraph
900 while (nodes_done
.size() < pdg
->nodes
.size()) {
901 set
<pdg::node
*> current_nodes
;
902 d_graph current_distances
;
905 for (int i
= 0; i
< pdg
->nodes
.size(); ++i
) {
906 node
= pdg
->nodes
[i
];
907 if (nodes_done
.find(node
) != nodes_done
.end())
912 distances
.collect_related_nodes(current_nodes
, node
);
914 set
<pdg::node
*>::iterator i
;
915 for (i
= current_nodes
.begin(); i
!= current_nodes
.end(); ++i
) {
916 current_distances
.data
[(*i
)] = distances
.data
[(*i
)];
919 combiner
c(pdg
, current_distances
, current_nodes
.size(),
923 for (i
= current_nodes
.begin(); i
!= current_nodes
.end(); ++i
) {
924 pdg::node
*node
= *i
;
925 nodes_done
.insert(node
);
927 isl_map
*s
= node
->schedule
->get_isl_map(ctx
);
929 isl_space
*dim
= isl_set_get_space(c
.offsets
[node
].d
);
930 int d
= isl_space_dim(dim
, isl_dim_set
) - 1;
931 isl_map
*id
= isl_map_identity(
932 isl_space_map_from_set(isl_space_copy(dim
)));
933 isl_set
*u
= isl_set_universe(dim
);
934 isl_map
*off
= isl_map_from_domain_and_range(u
,
935 isl_set_copy(c
.offsets
[node
].d
));
936 id
= isl_map_project_out(id
, isl_dim_in
, d
, 1);
937 id
= isl_map_fix_si(id
, isl_dim_out
, d
, 0);
938 off
= isl_map_project_out(off
, isl_dim_in
, d
, 1);
939 off
= isl_map_sum(id
, off
);
940 s
= isl_map_apply_range(s
, off
);
942 delete node
->schedule
;
943 node
->schedule
= new IslMap(s
);
947 pdg
->statement_dimensions
.push_back(1);
950 isl_space_free(space
);