10 #include <isl/polynomial.h>
11 #include <isl/printer.h>
12 #include <barvinok/isl.h>
14 #include "size_bernstein.h"
15 #include "size_simulate.h"
16 #include "size_options.h"
25 #ifndef USE_SIZE_SIMULATE
26 int selfloop_size_simulate(__isl_take isl_map
*dep
, __isl_take isl_set
*read
)
34 static bool is_rectangular_dependence(__isl_keep isl_map
*dep
)
39 ok
= isl_map_is_translation(dep
);
44 dom
= isl_map_domain(isl_map_copy(dep
));
45 ok
= isl_set_is_box(dom
);
52 /* Compute the number of tokens in the FIFO at the reference point(s) ref.
53 * That is, the number of dependences that have started but not finished
54 * before any point in ref. Note that the same read iteration may
55 * depend on several write iterations, so we cannot simply count the
56 * number of writes and reads and take the differences, as the total
57 * number of reads may be smaller than the total number of writes.
58 * Instead, we set up two mappings between the reference point
59 * and the dependences, one where the write happens before the
60 * reference point and one where the read happens before the reference
61 * point. We then take the set difference and then count the number
62 * of elements in this difference.
64 isl_pw_qpolynomial
*selfloop_tokens_in_fifo(__isl_take isl_map
*dep
,
65 __isl_take isl_set
*ref
)
69 isl_map
*read_before_ref
;
70 isl_map
*write_before_ref
;
72 dep
= isl_map_make_disjoint(dep
);
73 ref
= isl_set_make_disjoint(ref
);
75 d
= isl_map_dim(dep
, isl_dim_in
);
76 dep
= isl_map_move_dims(dep
, isl_dim_in
, d
, isl_dim_out
, 0, d
);
77 dep_set
= isl_map_domain(dep
);
79 read_before_ref
= isl_map_lex_gt(isl_set_get_space(ref
));
80 read_before_ref
= isl_map_intersect_domain(read_before_ref
, ref
);
81 write_before_ref
= isl_map_copy(read_before_ref
);
83 read_before_ref
= isl_map_insert_dims(read_before_ref
, isl_dim_out
, 0, d
);
84 write_before_ref
= isl_map_add_dims(write_before_ref
, isl_dim_out
, d
);
86 read_before_ref
= isl_map_intersect_range(read_before_ref
,
87 isl_set_copy(dep_set
));
88 write_before_ref
= isl_map_intersect_range(write_before_ref
, dep_set
);
90 write_before_ref
= isl_map_subtract(write_before_ref
, read_before_ref
);
92 return isl_map_card(write_before_ref
);
95 /* Compute the maximum of the difference in number of writes and number
96 * of reads before any read. The difference is equal to the number
97 * of token in the FIFO and the maximum is the buffer size of the FIFO.
98 * The procedure assumes that the dependence is non-parametric and
99 * may actually iterate over all reads to compute the maximum.
101 static int selfloop_size_full(__isl_take isl_map
*dep
,
102 __isl_take isl_set
*ref
)
104 isl_pw_qpolynomial
*qp_diff
;
108 qp_diff
= selfloop_tokens_in_fifo(dep
, ref
);
110 v
= isl_pw_qpolynomial_max(qp_diff
);
111 assert(isl_val_is_int(v
));
113 size
= isl_val_get_num_si(v
);
120 enumerator::operator pdg::enumerator
*() const
124 return new pdg::enumerator(v
);
127 isl_printer
*printer
;
130 printer
= isl_printer_to_str(pdg
->get_isl_ctx());
131 printer
= isl_printer_set_output_format(printer
, ISL_FORMAT_C
);
133 printer
= isl_printer_print_pw_qpolynomial(printer
, pwqp
);
135 printer
= isl_printer_print_pw_qpolynomial_fold(printer
, pwf
);
136 str
= isl_printer_get_str(printer
);
138 isl_printer_free(printer
);
140 return new pdg::enumerator(s
);
147 integer
*enumerator::evaluate() const
151 return new integer(v
);
159 dim
= isl_space_params_alloc(pdg
->get_isl_ctx(), pdg
->params
.size());
160 isl_dim_set_parameter_names(dim
, pdg
->params
);
161 pnt
= isl_point_zero(dim
);
162 for (int i
= 0; i
< pdg
->params
.size(); ++i
) {
163 int n
= pdg
->params
[i
]->value
->v
;
164 pnt
= isl_point_add_ui(pnt
, isl_dim_param
, i
, n
);
166 if (type
== enumerator::qp
)
167 n
= isl_pw_qpolynomial_eval(
168 isl_pw_qpolynomial_copy(pwqp
), pnt
);
170 n
= isl_pw_qpolynomial_fold_eval(
171 isl_pw_qpolynomial_fold_copy(pwf
), pnt
);
172 n
= isl_val_floor(n
);
173 v
= isl_val_get_num_si(n
);
175 return new integer(v
);
183 size::enumerator
*selfloop_size(pdg::PDG
*pdg
, __isl_take isl_map
*dep
,
184 size_options
*options
)
186 int nparam
= isl_map_dim(dep
, isl_dim_param
);
189 assert(isl_map_dim(dep
, isl_dim_in
) == isl_map_dim(dep
, isl_dim_out
));
191 read
= isl_map_range(isl_map_copy(dep
));
193 bool rect
= !nparam
&& is_rectangular_dependence(dep
);
195 size::enumerator
*e
= NULL
;
196 if (!nparam
&& options
->flags
!= SIZE_BERNSTEIN
) {
198 if (options
->flags
== SIZE_SIMULATE
) {
199 maxsize
= selfloop_size_simulate(dep
, read
);
201 maxsize
= selfloop_size_full(dep
, read
);
203 isl_set
*ref
= isl_set_lexmin(read
);
204 maxsize
= selfloop_size_full(dep
, ref
);
206 e
= new enumerator(maxsize
);
208 e
= selfloop_size_bernstein(pdg
, dep
, read
);