7 /* Do we need to construct a skip condition of the given type
8 * on an if statement, given that the if condition is non-affine?
10 * pet_scop_filter_skip can only handle the case where the if condition
11 * holds (the then branch) and the skip condition is universal.
12 * In any other case, we need to construct a new skip condition.
14 static int if_need_skip_non(struct pet_scop
*scop_then
,
15 struct pet_scop
*scop_else
, int have_else
, enum pet_skip type
)
17 if (have_else
&& scop_else
&& pet_scop_has_skip(scop_else
, type
))
19 if (scop_then
&& pet_scop_has_skip(scop_then
, type
) &&
20 !pet_scop_has_universal_skip(scop_then
, type
))
25 /* Do we need to construct a skip condition of the given type
26 * on an if statement, given that the if condition is affine?
28 * There is no need to construct a new skip condition if all
29 * the skip conditions are affine.
31 static int if_need_skip_aff(struct pet_scop
*scop_then
,
32 struct pet_scop
*scop_else
, int have_else
, enum pet_skip type
)
34 if (scop_then
&& pet_scop_has_var_skip(scop_then
, type
))
36 if (have_else
&& scop_else
&& pet_scop_has_var_skip(scop_else
, type
))
41 /* Do we need to construct a skip condition of the given type
44 static int if_need_skip(struct pet_scop
*scop_then
, struct pet_scop
*scop_else
,
45 int have_else
, enum pet_skip type
, int affine
)
48 return if_need_skip_aff(scop_then
, scop_else
, have_else
, type
);
50 return if_need_skip_non(scop_then
, scop_else
, have_else
, type
);
53 /* Construct an affine expression pet_expr that evaluates
54 * to the constant "val" on "space".
56 static __isl_give pet_expr
*universally(__isl_take isl_space
*space
, int val
)
61 isl_multi_pw_aff
*mpa
;
63 ctx
= isl_space_get_ctx(space
);
64 ls
= isl_local_space_from_space(space
);
65 aff
= isl_aff_val_on_domain(ls
, isl_val_int_from_si(ctx
, val
));
66 mpa
= isl_multi_pw_aff_from_pw_aff(isl_pw_aff_from_aff(aff
));
68 return pet_expr_from_index(mpa
);
71 /* Construct an affine expression pet_expr that evaluates
72 * to the constant 1 on "space".
74 static __isl_give pet_expr
*universally_true(__isl_take isl_space
*space
)
76 return universally(space
, 1);
79 /* Construct an affine expression pet_expr that evaluates
80 * to the constant 0 on "space".
82 static __isl_give pet_expr
*universally_false(__isl_take isl_space
*space
)
84 return universally(space
, 0);
87 /* Given an index expression "test_index" for the if condition,
88 * an index expression "skip_index" for the skip condition and
89 * scops for the then and else branches, construct a scop for
90 * computing "skip_index" within the context "pc".
92 * The computed scop contains a single statement that essentially does
94 * skip_index = test_cond ? skip_cond_then : skip_cond_else
96 * If the skip conditions of the then and/or else branch are not affine,
97 * then they need to be filtered by test_index.
98 * If they are missing, then this means the skip condition is false.
100 * Since we are constructing a skip condition for the if statement,
101 * the skip conditions on the then and else branches are removed.
103 static struct pet_scop
*extract_skip_if(__isl_take isl_multi_pw_aff
*test_index
,
104 __isl_take isl_multi_pw_aff
*skip_index
,
105 struct pet_scop
*scop_then
, struct pet_scop
*scop_else
, int have_else
,
106 enum pet_skip type
, __isl_keep pet_context
*pc
, struct pet_state
*state
)
108 pet_expr
*expr_then
, *expr_else
, *expr
, *expr_skip
;
110 struct pet_stmt
*stmt
;
111 struct pet_scop
*scop
;
117 if (have_else
&& !scop_else
)
120 ctx
= isl_multi_pw_aff_get_ctx(test_index
);
122 if (pet_scop_has_skip(scop_then
, type
)) {
123 expr_then
= pet_scop_get_skip_expr(scop_then
, type
);
124 pet_scop_reset_skip(scop_then
, type
);
125 if (!pet_expr_is_affine(expr_then
))
126 expr_then
= pet_expr_filter(expr_then
,
127 isl_multi_pw_aff_copy(test_index
), 1);
129 expr_then
= universally_false(pet_context_get_space(pc
));
131 if (have_else
&& pet_scop_has_skip(scop_else
, type
)) {
132 expr_else
= pet_scop_get_skip_expr(scop_else
, type
);
133 pet_scop_reset_skip(scop_else
, type
);
134 if (!pet_expr_is_affine(expr_else
))
135 expr_else
= pet_expr_filter(expr_else
,
136 isl_multi_pw_aff_copy(test_index
), 0);
138 expr_else
= universally_false(pet_context_get_space(pc
));
140 expr
= pet_expr_from_index(test_index
);
141 expr
= pet_expr_new_ternary(expr
, expr_then
, expr_else
);
142 expr_skip
= pet_expr_from_index(isl_multi_pw_aff_copy(skip_index
));
143 expr_skip
= pet_expr_access_set_write(expr_skip
, 1);
144 expr_skip
= pet_expr_access_set_read(expr_skip
, 0);
145 expr
= pet_expr_new_binary(1, pet_op_assign
, expr_skip
, expr
);
146 domain
= pet_context_get_domain(pc
);
147 tree
= pet_tree_new_expr(expr
);
148 stmt
= pet_stmt_from_pet_tree(isl_set_copy(domain
),
149 state
->n_stmt
++, tree
);
151 scop
= pet_scop_from_pet_stmt(pet_context_get_space(pc
), stmt
);
152 scop
= pet_scop_add_boolean_array(scop
, domain
, skip_index
,
157 isl_multi_pw_aff_free(test_index
);
158 isl_multi_pw_aff_free(skip_index
);
162 /* Is scop's skip_now condition equal to its skip_later condition?
163 * In particular, this means that it either has no skip_now condition
164 * or both a skip_now and a skip_later condition (that are equal to each other).
166 static int skip_equals_skip_later(struct pet_scop
*scop
)
168 int has_skip_now
, has_skip_later
;
170 isl_multi_pw_aff
*skip_now
, *skip_later
;
174 has_skip_now
= pet_scop_has_skip(scop
, pet_skip_now
);
175 has_skip_later
= pet_scop_has_skip(scop
, pet_skip_later
);
176 if (has_skip_now
!= has_skip_later
)
181 skip_now
= pet_scop_get_skip(scop
, pet_skip_now
);
182 skip_later
= pet_scop_get_skip(scop
, pet_skip_later
);
183 equal
= isl_multi_pw_aff_is_equal(skip_now
, skip_later
);
184 isl_multi_pw_aff_free(skip_now
);
185 isl_multi_pw_aff_free(skip_later
);
190 /* Drop the skip conditions of type pet_skip_later from scop1 and scop2.
192 static void drop_skip_later(struct pet_scop
*scop1
, struct pet_scop
*scop2
)
194 pet_scop_reset_skip(scop1
, pet_skip_later
);
195 pet_scop_reset_skip(scop2
, pet_skip_later
);
198 /* Do we need to construct any skip condition?
200 int pet_skip_info_has_skip(struct pet_skip_info
*skip
)
202 return skip
->skip
[pet_skip_now
] || skip
->skip
[pet_skip_later
];
205 /* Initialize a pet_skip_info_if structure based on the then and else branches
206 * and based on whether the if condition is affine or not.
208 void pet_skip_info_if_init(struct pet_skip_info
*skip
, isl_ctx
*ctx
,
209 struct pet_scop
*scop_then
, struct pet_scop
*scop_else
,
210 int have_else
, int affine
)
213 skip
->type
= have_else
? pet_skip_if_else
: pet_skip_if
;
214 skip
->u
.i
.scop_then
= scop_then
;
215 skip
->u
.i
.scop_else
= scop_else
;
217 skip
->skip
[pet_skip_now
] =
218 if_need_skip(scop_then
, scop_else
, have_else
, pet_skip_now
, affine
);
219 skip
->equal
= skip
->skip
[pet_skip_now
] &&
220 skip_equals_skip_later(scop_then
) &&
221 (!have_else
|| skip_equals_skip_later(scop_else
));
222 skip
->skip
[pet_skip_later
] = skip
->skip
[pet_skip_now
] &&
224 if_need_skip(scop_then
, scop_else
, have_else
,
225 pet_skip_later
, affine
);
228 /* If we need to construct a skip condition of the given type,
229 * then do so now, within the context "pc".
231 * "mpa" represents the if condition.
233 static void pet_skip_info_if_extract_type(struct pet_skip_info
*skip
,
234 __isl_keep isl_multi_pw_aff
*mpa
, enum pet_skip type
,
235 __isl_keep pet_context
*pc
, struct pet_state
*state
)
239 if (!skip
->skip
[type
])
242 space
= pet_context_get_space(pc
);
243 skip
->index
[type
] = pet_create_test_index(space
, state
->n_test
++);
244 skip
->scop
[type
] = extract_skip_if(isl_multi_pw_aff_copy(mpa
),
245 isl_multi_pw_aff_copy(skip
->index
[type
]),
246 skip
->u
.i
.scop_then
, skip
->u
.i
.scop_else
,
247 skip
->type
== pet_skip_if_else
, type
,
251 /* Construct the required skip conditions within the context "pc",
252 * given the if condition "index".
254 void pet_skip_info_if_extract_index(struct pet_skip_info
*skip
,
255 __isl_keep isl_multi_pw_aff
*index
, __isl_keep pet_context
*pc
,
256 struct pet_state
*state
)
258 pet_skip_info_if_extract_type(skip
, index
, pet_skip_now
, pc
, state
);
259 pet_skip_info_if_extract_type(skip
, index
, pet_skip_later
, pc
, state
);
261 drop_skip_later(skip
->u
.i
.scop_then
, skip
->u
.i
.scop_else
);
264 /* Construct the required skip conditions within the context "pc",
265 * given the if condition "cond".
267 void pet_skip_info_if_extract_cond(struct pet_skip_info
*skip
,
268 __isl_keep isl_pw_aff
*cond
, __isl_keep pet_context
*pc
,
269 struct pet_state
*state
)
271 isl_multi_pw_aff
*test
;
273 if (!skip
->skip
[pet_skip_now
] && !skip
->skip
[pet_skip_later
])
276 test
= isl_multi_pw_aff_from_pw_aff(isl_pw_aff_copy(cond
));
277 pet_skip_info_if_extract_index(skip
, test
, pc
, state
);
278 isl_multi_pw_aff_free(test
);
281 /* Add the computed skip condition of the give type to "main" and
282 * add the scop for computing the condition at the given offset.
284 * If equal is set, then we only computed a skip condition for pet_skip_now,
285 * but we also need to set it as main's pet_skip_later.
287 struct pet_scop
*pet_skip_info_if_add_type(struct pet_skip_info
*skip
,
288 struct pet_scop
*main
, enum pet_skip type
, int offset
)
290 if (!skip
->skip
[type
])
293 skip
->scop
[type
] = pet_scop_prefix(skip
->scop
[type
], offset
);
294 main
= pet_scop_add_par(skip
->ctx
, main
, skip
->scop
[type
]);
295 skip
->scop
[type
] = NULL
;
298 main
= pet_scop_set_skip(main
, pet_skip_later
,
299 isl_multi_pw_aff_copy(skip
->index
[type
]));
301 main
= pet_scop_set_skip(main
, type
, skip
->index
[type
]);
302 skip
->index
[type
] = NULL
;
307 /* Add the computed skip conditions to "main" and
308 * add the scops for computing the conditions at the given offset.
310 struct pet_scop
*pet_skip_info_if_add(struct pet_skip_info
*skip
,
311 struct pet_scop
*scop
, int offset
)
313 scop
= pet_skip_info_if_add_type(skip
, scop
, pet_skip_now
, offset
);
314 scop
= pet_skip_info_if_add_type(skip
, scop
, pet_skip_later
, offset
);
319 /* Do we need to construct a skip condition of the given type
320 * on a sequence of statements?
322 * There is no need to construct a new skip condition if only
323 * only of the two statements has a skip condition or if both
324 * of their skip conditions are affine.
326 * In principle we also don't need a new continuation variable if
327 * the continuation of scop2 is affine, but then we would need
328 * to allow more complicated forms of continuations.
330 static int seq_need_skip(struct pet_scop
*scop1
, struct pet_scop
*scop2
,
333 if (!scop1
|| !pet_scop_has_skip(scop1
, type
))
335 if (!scop2
|| !pet_scop_has_skip(scop2
, type
))
337 if (pet_scop_has_affine_skip(scop1
, type
) &&
338 pet_scop_has_affine_skip(scop2
, type
))
343 /* Construct a scop for computing the skip condition of the given type and
344 * with index expression "skip_index" for a sequence of two scops "scop1"
345 * and "scop2". Do so within the context "pc".
347 * The computed scop contains a single statement that essentially does
349 * skip_index = skip_cond_1 ? 1 : skip_cond_2
351 * or, in other words, skip_cond1 || skip_cond2.
352 * In this expression, skip_cond_2 is filtered to reflect that it is
353 * only evaluated when skip_cond_1 is false.
355 * The skip condition on scop1 is not removed because it still needs
356 * to be applied to scop2 when these two scops are combined.
358 static struct pet_scop
*extract_skip_seq(
359 __isl_take isl_multi_pw_aff
*skip_index
,
360 struct pet_scop
*scop1
, struct pet_scop
*scop2
, enum pet_skip type
,
361 __isl_keep pet_context
*pc
, struct pet_state
*state
)
363 pet_expr
*expr1
, *expr2
, *expr
, *expr_skip
;
365 struct pet_stmt
*stmt
;
366 struct pet_scop
*scop
;
370 if (!scop1
|| !scop2
)
373 ctx
= isl_multi_pw_aff_get_ctx(skip_index
);
375 expr1
= pet_scop_get_skip_expr(scop1
, type
);
376 expr2
= pet_scop_get_skip_expr(scop2
, type
);
377 pet_scop_reset_skip(scop2
, type
);
379 expr2
= pet_expr_filter(expr2
, pet_expr_access_get_index(expr1
), 0);
381 expr
= universally_true(pet_context_get_space(pc
));
382 expr
= pet_expr_new_ternary(expr1
, expr
, expr2
);
383 expr_skip
= pet_expr_from_index(isl_multi_pw_aff_copy(skip_index
));
384 expr_skip
= pet_expr_access_set_write(expr_skip
, 1);
385 expr_skip
= pet_expr_access_set_read(expr_skip
, 0);
386 expr
= pet_expr_new_binary(1, pet_op_assign
, expr_skip
, expr
);
387 domain
= pet_context_get_domain(pc
);
388 tree
= pet_tree_new_expr(expr
);
389 stmt
= pet_stmt_from_pet_tree(isl_set_copy(domain
),
390 state
->n_stmt
++, tree
);
392 scop
= pet_scop_from_pet_stmt(pet_context_get_space(pc
), stmt
);
393 scop
= pet_scop_add_boolean_array(scop
, domain
, skip_index
,
398 isl_multi_pw_aff_free(skip_index
);
402 /* Initialize a pet_skip_info_seq structure based on
403 * on the two statements that are going to be combined.
405 void pet_skip_info_seq_init(struct pet_skip_info
*skip
, isl_ctx
*ctx
,
406 struct pet_scop
*scop1
, struct pet_scop
*scop2
)
409 skip
->type
= pet_skip_seq
;
410 skip
->u
.s
.scop1
= scop1
;
411 skip
->u
.s
.scop2
= scop2
;
413 skip
->skip
[pet_skip_now
] = seq_need_skip(scop1
, scop2
, pet_skip_now
);
414 skip
->equal
= skip
->skip
[pet_skip_now
] &&
415 skip_equals_skip_later(scop1
) && skip_equals_skip_later(scop2
);
416 skip
->skip
[pet_skip_later
] = skip
->skip
[pet_skip_now
] && !skip
->equal
&&
417 seq_need_skip(scop1
, scop2
, pet_skip_later
);
420 /* If we need to construct a skip condition of the given type,
421 * then do so now, within the context "pc".
423 static void pet_skip_info_seq_extract_type(struct pet_skip_info
*skip
,
424 enum pet_skip type
, __isl_keep pet_context
*pc
, struct pet_state
*state
)
428 if (!skip
->skip
[type
])
431 space
= pet_context_get_space(pc
);
432 skip
->index
[type
] = pet_create_test_index(space
, state
->n_test
++);
433 skip
->scop
[type
] = extract_skip_seq(
434 isl_multi_pw_aff_copy(skip
->index
[type
]),
435 skip
->u
.s
.scop1
, skip
->u
.s
.scop2
, type
,
439 /* Construct the required skip conditions within the context "pc".
441 void pet_skip_info_seq_extract(struct pet_skip_info
*skip
,
442 __isl_keep pet_context
*pc
, struct pet_state
*state
)
444 pet_skip_info_seq_extract_type(skip
, pet_skip_now
, pc
, state
);
445 pet_skip_info_seq_extract_type(skip
, pet_skip_later
, pc
, state
);
447 drop_skip_later(skip
->u
.s
.scop1
, skip
->u
.s
.scop2
);
450 /* Add the computed skip condition of the given type to "main" and
451 * add the scop for computing the condition at the given offset (the statement
452 * number). Within this offset, the condition is computed at position 1
453 * to ensure that it is computed after the corresponding statement.
455 * If equal is set, then we only computed a skip condition for pet_skip_now,
456 * but we also need to set it as main's pet_skip_later.
458 struct pet_scop
*pet_skip_info_seq_add_type(struct pet_skip_info
*skip
,
459 struct pet_scop
*main
, enum pet_skip type
, int offset
)
461 if (!skip
->skip
[type
])
464 skip
->scop
[type
] = pet_scop_prefix(skip
->scop
[type
], 1);
465 skip
->scop
[type
] = pet_scop_prefix(skip
->scop
[type
], offset
);
466 main
= pet_scop_add_par(skip
->ctx
, main
, skip
->scop
[type
]);
467 skip
->scop
[type
] = NULL
;
470 main
= pet_scop_set_skip(main
, pet_skip_later
,
471 isl_multi_pw_aff_copy(skip
->index
[type
]));
473 main
= pet_scop_set_skip(main
, type
, skip
->index
[type
]);
474 skip
->index
[type
] = NULL
;
479 /* Add the computed skip conditions to "main" and
480 * add the scops for computing the conditions at the given offset.
482 struct pet_scop
*pet_skip_info_seq_add(struct pet_skip_info
*skip
,
483 struct pet_scop
*scop
, int offset
)
485 scop
= pet_skip_info_seq_add_type(skip
, scop
, pet_skip_now
, offset
);
486 scop
= pet_skip_info_seq_add_type(skip
, scop
, pet_skip_later
, offset
);