__isl_give isl_ast_expr *isl_ast_expr_div(
__isl_take isl_ast_expr *expr1,
__isl_take isl_ast_expr *expr2);
+ __isl_give isl_ast_expr *isl_ast_expr_pdiv_q(
+ __isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
+ __isl_give isl_ast_expr *isl_ast_expr_pdiv_r(
+ __isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
__isl_give isl_ast_expr *isl_ast_expr_and(
__isl_take isl_ast_expr *expr1,
__isl_take isl_ast_expr *expr2)
+ __isl_give isl_ast_expr *isl_ast_expr_and_then(
+ __isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2)
__isl_give isl_ast_expr *isl_ast_expr_or(
__isl_take isl_ast_expr *expr1,
__isl_take isl_ast_expr *expr2)
+ __isl_give isl_ast_expr *isl_ast_expr_or_else(
+ __isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2)
__isl_give isl_ast_expr *isl_ast_expr_eq(
__isl_take isl_ast_expr *expr1,
__isl_take isl_ast_expr *expr2);
__isl_give isl_ast_expr *isl_ast_expr_access(
__isl_take isl_ast_expr *array,
__isl_take isl_ast_expr_list *indices);
+ __isl_give isl_ast_expr *isl_ast_expr_call(
+ __isl_take isl_ast_expr *function,
+ __isl_take isl_ast_expr_list *arguments);
The function C<isl_ast_expr_address_of> can be applied to an
C<isl_ast_expr> of type C<isl_ast_op_access> only. It is meant
-to represent the address of the C<isl_ast_expr_access>.
+to represent the address of the C<isl_ast_expr_access>. The function
+C<isl_ast_expr_and_then> as well as C<isl_ast_expr_or_else> are short-circuit
+versions of C<isl_ast_expr_and> and C<isl_ast_expr_or>, respectively.
#include <isl/ast_build.h>
+ __isl_give isl_ast_expr *isl_ast_build_expr_from_set(
+ __isl_keep isl_ast_build *build,
+ __isl_take isl_set *set);
__isl_give isl_ast_expr *isl_ast_build_expr_from_pw_aff(
__isl_keep isl_ast_build *build,
__isl_take isl_pw_aff *pa);
__isl_keep isl_ast_build *build,
__isl_take isl_multi_pw_aff *mpa);
-The domains of C<pa>, C<mpa> and C<pma> should correspond
+The set <set> and
+the domains of C<pa>, C<mpa> and C<pma> should correspond
to the schedule space of C<build>.
The tuple id of C<mpa> or C<pma> is used as the array being accessed or
the function being called.
__isl_take isl_ast_expr *expr2);
__isl_give isl_ast_expr *isl_ast_expr_div(__isl_take isl_ast_expr *expr1,
__isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_pdiv_q(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_pdiv_r(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
__isl_give isl_ast_expr *isl_ast_expr_and(__isl_take isl_ast_expr *expr1,
__isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_and_then(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
__isl_give isl_ast_expr *isl_ast_expr_or(__isl_take isl_ast_expr *expr1,
__isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_or_else(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
__isl_give isl_ast_expr *isl_ast_expr_le(__isl_take isl_ast_expr *expr1,
__isl_take isl_ast_expr *expr2);
__isl_give isl_ast_expr *isl_ast_expr_lt(__isl_take isl_ast_expr *expr1,
__isl_take isl_ast_expr *expr2);
__isl_give isl_ast_expr *isl_ast_expr_access(__isl_take isl_ast_expr *array,
__isl_take isl_ast_expr_list *indices);
+__isl_give isl_ast_expr *isl_ast_expr_call(__isl_take isl_ast_expr *function,
+ __isl_take isl_ast_expr_list *arguments);
__isl_give isl_ast_expr *isl_ast_expr_address_of(__isl_take isl_ast_expr *expr);
__isl_give isl_ast_expr *isl_ast_expr_copy(__isl_keep isl_ast_expr *expr);
__isl_give isl_ast_node *(*fn)(__isl_take isl_ast_build *build,
void *user), void *user);
+__isl_give isl_ast_expr *isl_ast_build_expr_from_set(
+ __isl_keep isl_ast_build *build, __isl_take isl_set *set);
__isl_give isl_ast_expr *isl_ast_build_expr_from_pw_aff(
__isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa);
__isl_give isl_ast_expr *isl_ast_build_access_from_pw_multi_aff(
return isl_ast_expr_alloc_binary(isl_ast_op_div, expr1, expr2);
}
+/* Create an expression representing the quotient of the integer
+ * division of "expr1" by "expr2", where "expr1" is known to be
+ * non-negative.
+ */
+__isl_give isl_ast_expr *isl_ast_expr_pdiv_q(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2)
+{
+ return isl_ast_expr_alloc_binary(isl_ast_op_pdiv_q, expr1, expr2);
+}
+
+/* Create an expression representing the remainder of the integer
+ * division of "expr1" by "expr2", where "expr1" is known to be
+ * non-negative.
+ */
+__isl_give isl_ast_expr *isl_ast_expr_pdiv_r(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2)
+{
+ return isl_ast_expr_alloc_binary(isl_ast_op_pdiv_r, expr1, expr2);
+}
+
/* Create an expression representing the conjunction of "expr1" and "expr2".
*/
__isl_give isl_ast_expr *isl_ast_expr_and(__isl_take isl_ast_expr *expr1,
return isl_ast_expr_alloc_binary(isl_ast_op_and, expr1, expr2);
}
+/* Create an expression representing the conjunction of "expr1" and "expr2",
+ * where "expr2" is evaluated only if "expr1" is evaluated to true.
+ */
+__isl_give isl_ast_expr *isl_ast_expr_and_then(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2)
+{
+ return isl_ast_expr_alloc_binary(isl_ast_op_and_then, expr1, expr2);
+}
+
/* Create an expression representing the disjunction of "expr1" and "expr2".
*/
__isl_give isl_ast_expr *isl_ast_expr_or(__isl_take isl_ast_expr *expr1,
return isl_ast_expr_alloc_binary(isl_ast_op_or, expr1, expr2);
}
+/* Create an expression representing the disjunction of "expr1" and "expr2",
+ * where "expr2" is evaluated only if "expr1" is evaluated to false.
+ */
+__isl_give isl_ast_expr *isl_ast_expr_or_else(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2)
+{
+ return isl_ast_expr_alloc_binary(isl_ast_op_or_else, expr1, expr2);
+}
+
/* Create an expression representing "expr1" less than or equal to "expr2".
*/
__isl_give isl_ast_expr *isl_ast_expr_le(__isl_take isl_ast_expr *expr1,
return isl_ast_expr_alloc_binary(isl_ast_op_eq, expr1, expr2);
}
-/* Create an expression representing an access to "array" with index
- * expressions "indices".
+/* Create an expression of type "type" with as arguments "arg0" followed
+ * by "arguments".
*/
-__isl_give isl_ast_expr *isl_ast_expr_access(__isl_take isl_ast_expr *array,
- __isl_take isl_ast_expr_list *indices)
+static __isl_give isl_ast_expr *ast_expr_with_arguments(
+ enum isl_ast_op_type type, __isl_take isl_ast_expr *arg0,
+ __isl_take isl_ast_expr_list *arguments)
{
int i, n;
isl_ctx *ctx;
- isl_ast_expr *access = NULL;
+ isl_ast_expr *res = NULL;
- if (!array || !indices)
+ if (!arg0 || !arguments)
goto error;
- ctx = isl_ast_expr_get_ctx(array);
- n = isl_ast_expr_list_n_ast_expr(indices);
- access = isl_ast_expr_alloc_op(ctx, isl_ast_op_access, 1 + n);
- if (!access)
+ ctx = isl_ast_expr_get_ctx(arg0);
+ n = isl_ast_expr_list_n_ast_expr(arguments);
+ res = isl_ast_expr_alloc_op(ctx, type, 1 + n);
+ if (!res)
goto error;
for (i = 0; i < n; ++i) {
- isl_ast_expr *index;
- index = isl_ast_expr_list_get_ast_expr(indices, i);
- access->u.op.args[1 + i] = index;
- if (!index)
+ isl_ast_expr *arg;
+ arg = isl_ast_expr_list_get_ast_expr(arguments, i);
+ res->u.op.args[1 + i] = arg;
+ if (!arg)
goto error;
}
- access->u.op.args[0] = array;
+ res->u.op.args[0] = arg0;
- isl_ast_expr_list_free(indices);
- return access;
+ isl_ast_expr_list_free(arguments);
+ return res;
error:
- isl_ast_expr_free(array);
- isl_ast_expr_list_free(indices);
- isl_ast_expr_free(access);
+ isl_ast_expr_free(arg0);
+ isl_ast_expr_list_free(arguments);
+ isl_ast_expr_free(res);
return NULL;
}
+/* Create an expression representing an access to "array" with index
+ * expressions "indices".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_access(__isl_take isl_ast_expr *array,
+ __isl_take isl_ast_expr_list *indices)
+{
+ return ast_expr_with_arguments(isl_ast_op_access, array, indices);
+}
+
+/* Create an expression representing a call to "function" with argument
+ * expressions "arguments".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_call(__isl_take isl_ast_expr *function,
+ __isl_take isl_ast_expr_list *arguments)
+{
+ return ast_expr_with_arguments(isl_ast_op_call, function, arguments);
+}
+
/* For each subexpression of "expr" of type isl_ast_expr_id,
* if it appears in "id2expr", then replace it by the corresponding
* expression.
if (!build)
goto error;
- set = isl_set_preimage_multi_aff(set,
+ if (!isl_set_is_params(set))
+ set = isl_set_preimage_multi_aff(set,
isl_multi_aff_copy(build->values));
set = isl_set_gist(set, isl_set_copy(build->domain));
* The result is simplified in terms of build->domain.
*
* If "set" is an (obviously) empty set, then return the expression "0".
+ *
+ * "set" lives in the internal schedule space.
*/
-__isl_give isl_ast_expr *isl_ast_build_expr_from_set(
+__isl_give isl_ast_expr *isl_ast_build_expr_from_set_internal(
__isl_keep isl_ast_build *build, __isl_take isl_set *set)
{
struct isl_expr_from_set_data data = { build, 1, NULL };
return data.res;
}
+/* Construct an isl_ast_expr that evaluates the conditions defining "set".
+ * The result is simplified in terms of build->domain.
+ *
+ * If "set" is an (obviously) empty set, then return the expression "0".
+ *
+ * "set" lives in the external schedule space.
+ *
+ * The internal AST expression generation assumes that there are
+ * no unknown divs, so make sure an explicit representation is available.
+ * Since the set comes from the outside, it may have constraints that
+ * are redundant with respect to the build domain. Remove them first.
+ */
+__isl_give isl_ast_expr *isl_ast_build_expr_from_set(
+ __isl_keep isl_ast_build *build, __isl_take isl_set *set)
+{
+ if (isl_ast_build_need_schedule_map(build)) {
+ isl_multi_aff *ma;
+ ma = isl_ast_build_get_schedule_map_multi_aff(build);
+ set = isl_set_preimage_multi_aff(set, ma);
+ }
+
+ set = isl_set_compute_divs(set);
+ set = isl_ast_build_compute_gist(build, set);
+ return isl_ast_build_expr_from_set_internal(build, set);
+}
+
struct isl_from_pw_aff_data {
isl_ast_build *build;
int n;
ternary = isl_ast_expr_alloc_op(ctx, isl_ast_op_select, 3);
gist = isl_set_gist(isl_set_copy(set), isl_set_copy(data->dom));
- arg = isl_ast_build_expr_from_set(data->build, gist);
+ arg = isl_ast_build_expr_from_set_internal(data->build, gist);
ternary = isl_ast_expr_set_op_arg(ternary, 0, arg);
build = isl_ast_build_copy(data->build);
build = isl_ast_build_restrict_generated(build, set);
__isl_give isl_ast_expr *isl_ast_build_expr_from_basic_set(
__isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset);
-__isl_give isl_ast_expr *isl_ast_build_expr_from_set(
+__isl_give isl_ast_expr *isl_ast_build_expr_from_set_internal(
__isl_keep isl_ast_build *build, __isl_take isl_set *set);
__isl_give isl_ast_expr *isl_ast_build_expr_from_pw_aff_internal(
if (!graft)
return NULL;
- cond = isl_ast_build_expr_from_set(build, isl_set_copy(set));
+ cond = isl_ast_build_expr_from_set_internal(build, isl_set_copy(set));
graft->node->u.f.cond = cond;
if (!graft->node->u.f.cond)
return isl_ast_graft_free(graft);
isl_ast_node *if_node;
isl_ast_expr *expr;
- expr = isl_ast_build_expr_from_set(build, guard);
+ expr = isl_ast_build_expr_from_set_internal(build, guard);
if_node = isl_ast_node_alloc_if(expr);
return isl_ast_node_if_set_then(if_node, node);