isl: isl-0.17.1-164-gcbba1b6

This is a regular maintenance update to ensure the latest version of isl is
tested.

Interesting Changes:

  - AST nodes and expressions are now printed as YAML

llvm-svn: 274614
This commit is contained in:
Tobias Grosser 2016-07-06 09:11:00 +00:00
parent 5a4f2476fd
commit 932ec01328
43 changed files with 1456 additions and 709 deletions

View File

@ -585,11 +585,11 @@ void IslAstInfo::printScop(raw_ostream &OS, Scop &S) const {
Options = isl_ast_print_options_set_print_for(Options, cbPrintFor, nullptr);
isl_printer *P = isl_printer_to_str(S.getIslCtx());
P = isl_printer_set_output_format(P, ISL_FORMAT_C);
P = isl_printer_print_ast_expr(P, RunCondition);
RtCStr = isl_printer_get_str(P);
P = isl_printer_flush(P);
P = isl_printer_indent(P, 4);
P = isl_printer_set_output_format(P, ISL_FORMAT_C);
P = isl_ast_node_print(RootNode, P, Options);
AstStr = isl_printer_get_str(P);

View File

@ -1 +1 @@
isl-0.17.1-84-g72ffe88
isl-0.17.1-164-gcbba1b6

View File

@ -348,11 +348,13 @@ EXTRA_DIST = \
isl_multi_hash.c \
isl_multi_intersect.c \
print_templ.c \
print_templ_yaml.c \
isl_power_templ.c \
isl_pw_macro.h \
isl_pw_templ.c \
isl_pw_hash.c \
isl_pw_union_opt.c \
isl_tab_lexopt_templ.c \
isl_union_macro.h \
isl_union_templ.c \
isl_union_single.c \

View File

@ -1104,11 +1104,13 @@ EXTRA_DIST = \
isl_multi_hash.c \
isl_multi_intersect.c \
print_templ.c \
print_templ_yaml.c \
isl_power_templ.c \
isl_pw_macro.h \
isl_pw_templ.c \
isl_pw_hash.c \
isl_pw_union_opt.c \
isl_tab_lexopt_templ.c \
isl_union_macro.h \
isl_union_templ.c \
isl_union_single.c \

View File

@ -18243,6 +18243,31 @@ $as_echo "#define initializeBuiltins InitializeBuiltins" >>confdefs.h
fi
rm -f conftest*
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <clang/Frontend/CompilerInstance.h>
int
main ()
{
using namespace clang;
CompilerInstance *Clang;
TargetOptions TO;
llvm::Triple T(TO.Triple);
PreprocessorOptions PO;
CompilerInvocation::setLangDefaults(Clang->getLangOpts(), IK_C,
T, PO, LangStandard::lang_unspecified);
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_compile "$LINENO"; then :
$as_echo "#define SETLANGDEFAULTS_TAKES_5_ARGUMENTS /**/" >>confdefs.h
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'

View File

@ -231,6 +231,16 @@ system)
[clang/Basic/Builtins.h], [],
[AC_DEFINE([initializeBuiltins], [InitializeBuiltins],
[Define to InitializeBuiltins for older versions of clang])])
AC_TRY_COMPILE([#include <clang/Frontend/CompilerInstance.h>], [
using namespace clang;
CompilerInstance *Clang;
TargetOptions TO;
llvm::Triple T(TO.Triple);
PreprocessorOptions PO;
CompilerInvocation::setLangDefaults(Clang->getLangOpts(), IK_C,
T, PO, LangStandard::lang_unspecified);
], [AC_DEFINE([SETLANGDEFAULTS_TAKES_5_ARGUMENTS], [],
[Define if HeaderSearchOptions::AddPath takes 4 arguments])])
AC_LANG_POP
CPPFLAGS="$SAVE_CPPFLAGS"

View File

@ -473,6 +473,18 @@ See \autoref{s:online} for the detection
and exploitation of symmetries that appear during the course of
the dual simplex method.
Note that the replacement of the $b_i(\vec p)$ by $u$ may lose
information if the parameters that occur in $b_i(\vec p)$ also
occur in other constraints. The replacement is therefore currently
only applied when all the parameters in all of the $b_i(\vec p)$
only occur in a single constraint, i.e., the one in which
the parameter is removed.
This is the case for the examples from \textcite{Bygde2010licentiate}
in \autoref{t:comparison}.
The version of {\tt isl} that was used during the experiments
of \autoref{s:pip:experiments} did not take into account
this single-occurrence constraint.
\subsubsection{Parameter Compression}\label{s:compression}
It may in some cases be apparent from the equalities in the problem
@ -678,7 +690,7 @@ as an \emph{integer} affine combination of other variables is
propagated to the main tableau, where it is used to eliminate that
integer division.
\subsection{Experiments}
\subsection{Experiments}\label{s:pip:experiments}
\autoref{t:comparison} compares the execution times of {\tt isl}
(with both types of context tableau)

Binary file not shown.

View File

@ -253,6 +253,18 @@ is now obtained by turning on the C<schedule_serialize_sccs> option.
=back
=head3 Changes since isl-0.17
=over
=item * The function C<isl_printer_print_ast_expr> no longer prints
in C format by default. To print in C format, the output format
of the printer needs to have been explicitly set to C<ISL_FORMAT_C>.
As a result, the function C<isl_ast_expr_to_str> no longer prints
the expression in C format. Use C<isl_ast_expr_to_C_str> instead.
=back
=head1 License
C<isl> is released under the MIT license.
@ -3672,6 +3684,8 @@ in isl format.
__isl_keep isl_multi_val *mv);
#include <isl/set.h>
__isl_give char *isl_basic_set_to_str(
__isl_keep isl_basic_set *bset);
__isl_give char *isl_set_to_str(
__isl_keep isl_set *set);
@ -3680,6 +3694,8 @@ in isl format.
__isl_keep isl_union_set *uset);
#include <isl/map.h>
__isl_give char *isl_basic_map_to_str(
__isl_keep isl_basic_map *bmap);
__isl_give char *isl_map_to_str(
__isl_keep isl_map *map);
@ -3704,6 +3720,16 @@ in isl format.
__isl_give char *isl_multi_union_pw_aff_to_str(
__isl_keep isl_multi_union_pw_aff *mupa);
#include <isl/point.h>
__isl_give char *isl_point_to_str(
__isl_keep isl_point *pnt);
#include <isl/polynomial.h>
__isl_give char *isl_pw_qpolynomial_to_str(
__isl_keep isl_pw_qpolynomial *pwqp);
__isl_give char *isl_union_pw_qpolynomial_to_str(
__isl_keep isl_union_pw_qpolynomial *upwqp);
=head2 Properties
=head3 Unary Properties
@ -5018,6 +5044,8 @@ NaN if the problem is empty.
__isl_take isl_set *set, int pos);
__isl_give isl_pw_aff *isl_set_dim_max(
__isl_take isl_set *set, int pos);
__isl_give isl_pw_aff *isl_map_dim_min(
__isl_take isl_map *map, int pos);
__isl_give isl_pw_aff *isl_map_dim_max(
__isl_take isl_map *map, int pos);
@ -7664,7 +7692,7 @@ A filter node does not impose any ordering, but rather intersects
the set of domain elements that the current subtree refers to
with a given union set. The subtree of the filter node only
refers to domain elements in the intersection.
A filter node is typically only used a child of a sequence or
A filter node is typically only used as a child of a sequence or
set node.
=item C<isl_schedule_node_leaf>
@ -9714,6 +9742,16 @@ Basic printing can be performed using the following functions.
__isl_keep isl_ast_node *node);
__isl_give char *isl_ast_expr_to_str(
__isl_keep isl_ast_expr *expr);
__isl_give char *isl_ast_node_to_str(
__isl_keep isl_ast_node *node);
__isl_give char *isl_ast_expr_to_C_str(
__isl_keep isl_ast_expr *expr);
__isl_give char *isl_ast_node_to_C_str(
__isl_keep isl_ast_node *node);
The functions C<isl_ast_expr_to_C_str> and
C<isl_ast_node_to_C_str> are convenience functions
that return a string representation of the input in C format.
More advanced printing can be performed using the following functions.
@ -10080,7 +10118,8 @@ This option may also be set directly using
C<isl_schedule_node_band_member_set_isolate_ast_loop_type>.
The atomic/separate/unroll choice for the remaining part is determined
by the regular C<atomic>, C<separate> or C<unroll> option.
The use of the C<isolate> option causes any tree containing the node
Since the C<isolate> option references outer schedule dimensions,
its use in a band node causes any tree containing the node
to be considered anchored.
As an example, consider the isolation of full tiles from partial tiles

View File

@ -83,6 +83,8 @@ __isl_give isl_printer *isl_printer_print_ast_expr(__isl_take isl_printer *p,
__isl_keep isl_ast_expr *expr);
void isl_ast_expr_dump(__isl_keep isl_ast_expr *expr);
__isl_give char *isl_ast_expr_to_str(__isl_keep isl_ast_expr *expr);
__isl_export
__isl_give char *isl_ast_expr_to_C_str(__isl_keep isl_ast_expr *expr);
__isl_give isl_ast_node *isl_ast_node_alloc_user(__isl_take isl_ast_expr *expr);
__isl_give isl_ast_node *isl_ast_node_copy(__isl_keep isl_ast_node *node);
@ -132,6 +134,7 @@ isl_stat isl_ast_node_foreach_descendant_top_down(
__isl_give isl_printer *isl_printer_print_ast_node(__isl_take isl_printer *p,
__isl_keep isl_ast_node *node);
void isl_ast_node_dump(__isl_keep isl_ast_node *node);
__isl_give char *isl_ast_node_to_str(__isl_keep isl_ast_node *node);
__isl_give isl_ast_print_options *isl_ast_print_options_alloc(isl_ctx *ctx);
__isl_give isl_ast_print_options *isl_ast_print_options_copy(
@ -180,6 +183,9 @@ __isl_give isl_printer *isl_ast_node_if_print(__isl_keep isl_ast_node *node,
__isl_take isl_printer *p,
__isl_take isl_ast_print_options *options);
__isl_export
__isl_give char *isl_ast_node_to_C_str(__isl_keep isl_ast_node *node);
#if defined(__cplusplus)
}
#endif

View File

@ -10,7 +10,7 @@
extern "C" {
#endif
struct isl_ast_build;
struct __isl_export isl_ast_build;
typedef struct isl_ast_build isl_ast_build;
@ -45,7 +45,9 @@ int isl_options_get_ast_build_allow_or(isl_ctx *ctx);
isl_ctx *isl_ast_build_get_ctx(__isl_keep isl_ast_build *build);
__isl_constructor
__isl_give isl_ast_build *isl_ast_build_alloc(isl_ctx *ctx);
__isl_export
__isl_give isl_ast_build *isl_ast_build_from_context(__isl_take isl_set *set);
__isl_give isl_space *isl_ast_build_get_schedule_space(
@ -92,21 +94,28 @@ __isl_give isl_ast_build *isl_ast_build_set_create_leaf(
__isl_give isl_ast_node *(*fn)(__isl_take isl_ast_build *build,
void *user), void *user);
__isl_export
__isl_give isl_ast_expr *isl_ast_build_expr_from_set(
__isl_keep isl_ast_build *build, __isl_take isl_set *set);
__isl_export
__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_export
__isl_give isl_ast_expr *isl_ast_build_access_from_pw_multi_aff(
__isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma);
__isl_export
__isl_give isl_ast_expr *isl_ast_build_access_from_multi_pw_aff(
__isl_keep isl_ast_build *build, __isl_take isl_multi_pw_aff *mpa);
__isl_export
__isl_give isl_ast_expr *isl_ast_build_call_from_pw_multi_aff(
__isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma);
__isl_export
__isl_give isl_ast_expr *isl_ast_build_call_from_multi_pw_aff(
__isl_keep isl_ast_build *build, __isl_take isl_multi_pw_aff *mpa);
__isl_give isl_ast_node *isl_ast_build_node_from_schedule(
__isl_keep isl_ast_build *build, __isl_take isl_schedule *schedule);
__isl_export
__isl_give isl_ast_node *isl_ast_build_node_from_schedule_map(
__isl_keep isl_ast_build *build, __isl_take isl_union_map *schedule);
__isl_give isl_ast_node *isl_ast_build_ast_from_schedule(

View File

@ -7,10 +7,10 @@
extern "C" {
#endif
struct isl_ast_expr;
struct __isl_export isl_ast_expr;
typedef struct isl_ast_expr isl_ast_expr;
struct isl_ast_node;
struct __isl_export isl_ast_node;
typedef struct isl_ast_node isl_ast_node;
enum isl_ast_op_type {

View File

@ -205,6 +205,7 @@ __isl_constructor
__isl_give isl_map *isl_map_read_from_str(isl_ctx *ctx, const char *str);
void isl_basic_map_dump(__isl_keep isl_basic_map *bmap);
void isl_map_dump(__isl_keep isl_map *map);
__isl_give char *isl_basic_map_to_str(__isl_keep isl_basic_map *bmap);
__isl_give isl_printer *isl_printer_print_basic_map(
__isl_take isl_printer *printer, __isl_keep isl_basic_map *bmap);
__isl_give char *isl_map_to_str(__isl_keep isl_map *map);
@ -671,6 +672,7 @@ __isl_give isl_basic_map *isl_basic_map_from_aff_list(
__isl_give isl_map *isl_map_from_aff(__isl_take isl_aff *aff);
__isl_give isl_map *isl_map_from_multi_aff(__isl_take isl_multi_aff *maff);
__isl_give isl_pw_aff *isl_map_dim_min(__isl_take isl_map *map, int pos);
__isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos);
ISL_DECLARE_LIST_FN(basic_map)

View File

@ -34,6 +34,7 @@ isl_bool isl_point_is_void(__isl_keep isl_point *pnt);
__isl_give isl_printer *isl_printer_print_point(
__isl_take isl_printer *printer, __isl_keep isl_point *pnt);
__isl_give char *isl_point_to_str(__isl_keep isl_point *pnt);
void isl_point_dump(__isl_keep isl_point *pnt);
#if defined(__cplusplus)

View File

@ -173,6 +173,7 @@ int isl_pw_qpolynomial_find_dim_by_name(__isl_keep isl_pw_qpolynomial *pwqp,
__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_reset_user(
__isl_take isl_pw_qpolynomial *pwqp);
__isl_export
__isl_give isl_set *isl_pw_qpolynomial_domain(__isl_take isl_pw_qpolynomial *pwqp);
__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_intersect_domain(
__isl_take isl_pw_qpolynomial *pwpq, __isl_take isl_set *set);
@ -226,6 +227,7 @@ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_fix_val(
__isl_take isl_pw_qpolynomial *pwqp,
enum isl_dim_type type, unsigned n, __isl_take isl_val *v);
__isl_export
__isl_give isl_val *isl_pw_qpolynomial_eval(
__isl_take isl_pw_qpolynomial *pwqp, __isl_take isl_point *pnt);
@ -248,6 +250,7 @@ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_read_from_str(isl_ctx *ctx,
const char *str);
__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_read_from_file(isl_ctx *ctx,
FILE *input);
__isl_give char *isl_pw_qpolynomial_to_str(__isl_keep isl_pw_qpolynomial *pwqp);
__isl_give isl_printer *isl_printer_print_pw_qpolynomial(
__isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp);
void isl_pw_qpolynomial_print(__isl_keep isl_pw_qpolynomial *pwqp, FILE *out,
@ -475,6 +478,8 @@ __isl_null isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_free(
__isl_constructor
__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_read_from_str(
isl_ctx *ctx, const char *str);
__isl_give char *isl_union_pw_qpolynomial_to_str(
__isl_keep isl_union_pw_qpolynomial *upwqp);
__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_neg(
__isl_take isl_union_pw_qpolynomial *upwqp);
@ -493,6 +498,7 @@ __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_scale_val(
__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_scale_down_val(
__isl_take isl_union_pw_qpolynomial *upwqp, __isl_take isl_val *v);
__isl_export
__isl_give isl_union_set *isl_union_pw_qpolynomial_domain(
__isl_take isl_union_pw_qpolynomial *upwqp);
__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_intersect_domain(
@ -522,6 +528,7 @@ __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_drop_dims(
__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_reset_user(
__isl_take isl_union_pw_qpolynomial *upwqp);
__isl_export
__isl_give isl_val *isl_union_pw_qpolynomial_eval(
__isl_take isl_union_pw_qpolynomial *upwqp, __isl_take isl_point *pnt);

View File

@ -241,7 +241,9 @@ __isl_constructor
__isl_give isl_set *isl_set_from_basic_set(__isl_take isl_basic_set *bset);
__isl_export
__isl_give isl_basic_set *isl_set_sample(__isl_take isl_set *set);
__isl_export
__isl_give isl_point *isl_basic_set_sample_point(__isl_take isl_basic_set *bset);
__isl_export
__isl_give isl_point *isl_set_sample_point(__isl_take isl_set *set);
__isl_export
__isl_give isl_set *isl_set_detect_equalities(__isl_take isl_set *set);
@ -502,6 +504,7 @@ __isl_give isl_basic_set *isl_set_solutions(__isl_take isl_set *set);
__isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos);
__isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos);
__isl_give char *isl_basic_set_to_str(__isl_keep isl_basic_set *bset);
__isl_give char *isl_set_to_str(__isl_keep isl_set *set);
#if defined(__cplusplus)

View File

@ -156,8 +156,8 @@ isl_bool isl_space_is_equal(__isl_keep isl_space *space1,
isl_bool isl_space_tuple_is_equal(__isl_keep isl_space *space1,
enum isl_dim_type type1, __isl_keep isl_space *space2,
enum isl_dim_type type2);
int isl_space_match(__isl_keep isl_space *dim1, enum isl_dim_type dim1_type,
__isl_keep isl_space *dim2, enum isl_dim_type dim2_type);
isl_bool isl_space_match(__isl_keep isl_space *space1, enum isl_dim_type type1,
__isl_keep isl_space *space2, enum isl_dim_type type2);
ISL_DEPRECATED
int isl_space_tuple_match(__isl_keep isl_space *space1, enum isl_dim_type type1,
__isl_keep isl_space *space2, enum isl_dim_type type2);

View File

@ -8,3 +8,4 @@
#include <isl/flow.h>
#include <isl/schedule.h>
#include <isl/schedule_node.h>
#include <isl/ast_build.h>

View File

@ -1403,7 +1403,7 @@ isl_stat isl_ast_node_foreach_descendant_top_down(
/* Textual C representation of the various operators.
*/
static char *op_str[] = {
static char *op_str_c[] = {
[isl_ast_op_and] = "&&",
[isl_ast_op_and_then] = "&&",
[isl_ast_op_or] = "||",
@ -1514,6 +1514,9 @@ static int is_div_mod(enum isl_ast_op_type op)
op == isl_ast_op_zdiv_r;
}
static __isl_give isl_printer *print_ast_expr_c(__isl_take isl_printer *p,
__isl_keep isl_ast_expr *expr);
/* Do we need/want parentheses around "expr" as a subexpression of
* an "op" operation? If "left" is set, then "expr" is the left-most
* operand.
@ -1554,10 +1557,10 @@ static int sub_expr_need_parens(enum isl_ast_op_type op,
return 0;
}
/* Print "expr" as a subexpression of an "op" operation.
/* Print "expr" as a subexpression of an "op" operation in C format.
* If "left" is set, then "expr" is the left-most operand.
*/
static __isl_give isl_printer *print_sub_expr(__isl_take isl_printer *p,
static __isl_give isl_printer *print_sub_expr_c(__isl_take isl_printer *p,
enum isl_ast_op_type op, __isl_keep isl_ast_expr *expr, int left)
{
int need_parens;
@ -1566,7 +1569,7 @@ static __isl_give isl_printer *print_sub_expr(__isl_take isl_printer *p,
if (need_parens)
p = isl_printer_print_str(p, "(");
p = isl_printer_print_ast_expr(p, expr);
p = print_ast_expr_c(p, expr);
if (need_parens)
p = isl_printer_print_str(p, ")");
return p;
@ -1575,7 +1578,7 @@ static __isl_give isl_printer *print_sub_expr(__isl_take isl_printer *p,
#define isl_ast_op_last isl_ast_op_address_of
/* Data structure that holds the user-specified textual
* representations for the operators.
* representations for the operators in C format.
* The entries are either NULL or copies of strings.
* A NULL entry means that the default name should be used.
*/
@ -1700,13 +1703,13 @@ __isl_give isl_printer *isl_ast_op_type_set_print_name(
return p;
}
/* Return the textual representation of "type".
/* Return the textual representation of "type" in C format.
*
* If there is a user-specified name in an isl_ast_op_names note
* associated to "p", then return that.
* Otherwise, return the default name in op_str.
*/
static const char *get_op_str(__isl_keep isl_printer *p,
static const char *get_op_str_c(__isl_keep isl_printer *p,
enum isl_ast_op_type type)
{
isl_id *id;
@ -1720,76 +1723,73 @@ static const char *get_op_str(__isl_keep isl_printer *p,
isl_id_free(id);
if (names && names->op_str[type])
return names->op_str[type];
return op_str[type];
return op_str_c[type];
}
/* Print a min or max reduction "expr".
/* Print a min or max reduction "expr" in C format.
*/
static __isl_give isl_printer *print_min_max(__isl_take isl_printer *p,
static __isl_give isl_printer *print_min_max_c(__isl_take isl_printer *p,
__isl_keep isl_ast_expr *expr)
{
int i = 0;
for (i = 1; i < expr->u.op.n_arg; ++i) {
p = isl_printer_print_str(p, get_op_str(p, expr->u.op.op));
p = isl_printer_print_str(p, get_op_str_c(p, expr->u.op.op));
p = isl_printer_print_str(p, "(");
}
p = isl_printer_print_ast_expr(p, expr->u.op.args[0]);
for (i = 1; i < expr->u.op.n_arg; ++i) {
p = isl_printer_print_str(p, ", ");
p = isl_printer_print_ast_expr(p, expr->u.op.args[i]);
p = print_ast_expr_c(p, expr->u.op.args[i]);
p = isl_printer_print_str(p, ")");
}
return p;
}
/* Print a function call "expr".
/* Print a function call "expr" in C format.
*
* The first argument represents the function to be called.
*/
static __isl_give isl_printer *print_call(__isl_take isl_printer *p,
static __isl_give isl_printer *print_call_c(__isl_take isl_printer *p,
__isl_keep isl_ast_expr *expr)
{
int i = 0;
p = isl_printer_print_ast_expr(p, expr->u.op.args[0]);
p = print_ast_expr_c(p, expr->u.op.args[0]);
p = isl_printer_print_str(p, "(");
for (i = 1; i < expr->u.op.n_arg; ++i) {
if (i != 1)
p = isl_printer_print_str(p, ", ");
p = isl_printer_print_ast_expr(p, expr->u.op.args[i]);
p = print_ast_expr_c(p, expr->u.op.args[i]);
}
p = isl_printer_print_str(p, ")");
return p;
}
/* Print an array access "expr".
/* Print an array access "expr" in C format.
*
* The first argument represents the array being accessed.
*/
static __isl_give isl_printer *print_access(__isl_take isl_printer *p,
static __isl_give isl_printer *print_access_c(__isl_take isl_printer *p,
__isl_keep isl_ast_expr *expr)
{
int i = 0;
p = isl_printer_print_ast_expr(p, expr->u.op.args[0]);
p = print_ast_expr_c(p, expr->u.op.args[0]);
for (i = 1; i < expr->u.op.n_arg; ++i) {
p = isl_printer_print_str(p, "[");
p = isl_printer_print_ast_expr(p, expr->u.op.args[i]);
p = print_ast_expr_c(p, expr->u.op.args[i]);
p = isl_printer_print_str(p, "]");
}
return p;
}
/* Print "expr" to "p".
*
* If we are printing in isl format, then we also print an indication
* of the size of the expression (if it was computed).
/* Print "expr" to "p" in C format.
*/
__isl_give isl_printer *isl_printer_print_ast_expr(__isl_take isl_printer *p,
static __isl_give isl_printer *print_ast_expr_c(__isl_take isl_printer *p,
__isl_keep isl_ast_expr *expr)
{
if (!p)
@ -1800,55 +1800,55 @@ __isl_give isl_printer *isl_printer_print_ast_expr(__isl_take isl_printer *p,
switch (expr->type) {
case isl_ast_expr_op:
if (expr->u.op.op == isl_ast_op_call) {
p = print_call(p, expr);
p = print_call_c(p, expr);
break;
}
if (expr->u.op.op == isl_ast_op_access) {
p = print_access(p, expr);
p = print_access_c(p, expr);
break;
}
if (expr->u.op.n_arg == 1) {
p = isl_printer_print_str(p,
get_op_str(p, expr->u.op.op));
p = print_sub_expr(p, expr->u.op.op,
get_op_str_c(p, expr->u.op.op));
p = print_sub_expr_c(p, expr->u.op.op,
expr->u.op.args[0], 0);
break;
}
if (expr->u.op.op == isl_ast_op_fdiv_q) {
const char *name = get_op_str(p, isl_ast_op_fdiv_q);
const char *name = get_op_str_c(p, isl_ast_op_fdiv_q);
p = isl_printer_print_str(p, name);
p = isl_printer_print_str(p, "(");
p = isl_printer_print_ast_expr(p, expr->u.op.args[0]);
p = print_ast_expr_c(p, expr->u.op.args[0]);
p = isl_printer_print_str(p, ", ");
p = isl_printer_print_ast_expr(p, expr->u.op.args[1]);
p = print_ast_expr_c(p, expr->u.op.args[1]);
p = isl_printer_print_str(p, ")");
break;
}
if (expr->u.op.op == isl_ast_op_max ||
expr->u.op.op == isl_ast_op_min) {
p = print_min_max(p, expr);
p = print_min_max_c(p, expr);
break;
}
if (expr->u.op.op == isl_ast_op_cond ||
expr->u.op.op == isl_ast_op_select) {
p = isl_printer_print_ast_expr(p, expr->u.op.args[0]);
p = print_ast_expr_c(p, expr->u.op.args[0]);
p = isl_printer_print_str(p, " ? ");
p = isl_printer_print_ast_expr(p, expr->u.op.args[1]);
p = print_ast_expr_c(p, expr->u.op.args[1]);
p = isl_printer_print_str(p, " : ");
p = isl_printer_print_ast_expr(p, expr->u.op.args[2]);
p = print_ast_expr_c(p, expr->u.op.args[2]);
break;
}
if (expr->u.op.n_arg != 2)
isl_die(isl_printer_get_ctx(p), isl_error_internal,
"operation should have two arguments",
goto error);
p = print_sub_expr(p, expr->u.op.op, expr->u.op.args[0], 1);
return isl_printer_free(p));
p = print_sub_expr_c(p, expr->u.op.op, expr->u.op.args[0], 1);
if (expr->u.op.op != isl_ast_op_member)
p = isl_printer_print_str(p, " ");
p = isl_printer_print_str(p, get_op_str(p, expr->u.op.op));
p = isl_printer_print_str(p, get_op_str_c(p, expr->u.op.op));
if (expr->u.op.op != isl_ast_op_member)
p = isl_printer_print_str(p, " ");
p = print_sub_expr(p, expr->u.op.op, expr->u.op.args[1], 0);
p = print_sub_expr_c(p, expr->u.op.op, expr->u.op.args[1], 0);
break;
case isl_ast_expr_id:
p = isl_printer_print_str(p, isl_id_get_name(expr->u.id));
@ -1861,67 +1861,267 @@ __isl_give isl_printer *isl_printer_print_ast_expr(__isl_take isl_printer *p,
}
return p;
error:
isl_printer_free(p);
return NULL;
}
/* Textual representation of the isl_ast_op_type elements
* for use in a YAML representation of an isl_ast_expr.
*/
static char *op_str[] = {
[isl_ast_op_and] = "and",
[isl_ast_op_and_then] = "and_then",
[isl_ast_op_or] = "or",
[isl_ast_op_or_else] = "or_else",
[isl_ast_op_max] = "max",
[isl_ast_op_min] = "min",
[isl_ast_op_minus] = "minus",
[isl_ast_op_add] = "add",
[isl_ast_op_sub] = "sub",
[isl_ast_op_mul] = "mul",
[isl_ast_op_div] = "div",
[isl_ast_op_fdiv_q] = "fdiv_q",
[isl_ast_op_pdiv_q] = "pdiv_q",
[isl_ast_op_pdiv_r] = "pdiv_r",
[isl_ast_op_zdiv_r] = "zdiv_r",
[isl_ast_op_cond] = "cond",
[isl_ast_op_select] = "select",
[isl_ast_op_eq] = "eq",
[isl_ast_op_le] = "le",
[isl_ast_op_lt] = "lt",
[isl_ast_op_ge] = "ge",
[isl_ast_op_gt] = "gt",
[isl_ast_op_call] = "call",
[isl_ast_op_access] = "access",
[isl_ast_op_member] = "member",
[isl_ast_op_address_of] = "address_of"
};
static __isl_give isl_printer *print_ast_expr_isl(__isl_take isl_printer *p,
__isl_keep isl_ast_expr *expr);
/* Print the arguments of "expr" to "p" in isl format.
*
* If there are no arguments, then nothing needs to be printed.
* Otherwise add an "args" key to the current mapping with as value
* the list of arguments of "expr".
*/
static __isl_give isl_printer *print_arguments(__isl_take isl_printer *p,
__isl_keep isl_ast_expr *expr)
{
int i, n;
n = isl_ast_expr_get_op_n_arg(expr);
if (n < 0)
return isl_printer_free(p);
if (n == 0)
return p;
p = isl_printer_print_str(p, "args");
p = isl_printer_yaml_next(p);
p = isl_printer_yaml_start_sequence(p);
for (i = 0; i < n; ++i) {
isl_ast_expr *arg;
arg = isl_ast_expr_get_op_arg(expr, i);
p = print_ast_expr_isl(p, arg);
isl_ast_expr_free(arg);
p = isl_printer_yaml_next(p);
}
p = isl_printer_yaml_end_sequence(p);
return p;
}
/* Print "expr" to "p" in isl format.
*
* In particular, print the isl_ast_expr as a YAML document.
*/
static __isl_give isl_printer *print_ast_expr_isl(__isl_take isl_printer *p,
__isl_keep isl_ast_expr *expr)
{
enum isl_ast_expr_type type;
enum isl_ast_op_type op;
isl_id *id;
isl_val *v;
if (!expr)
return isl_printer_free(p);
p = isl_printer_yaml_start_mapping(p);
type = isl_ast_expr_get_type(expr);
switch (type) {
case isl_ast_expr_error:
return isl_printer_free(p);
case isl_ast_expr_op:
op = isl_ast_expr_get_op_type(expr);
if (op == isl_ast_op_error)
return isl_printer_free(p);
p = isl_printer_print_str(p, "op");
p = isl_printer_yaml_next(p);
p = isl_printer_print_str(p, op_str[op]);
p = isl_printer_yaml_next(p);
p = print_arguments(p, expr);
break;
case isl_ast_expr_id:
p = isl_printer_print_str(p, "id");
p = isl_printer_yaml_next(p);
id = isl_ast_expr_get_id(expr);
p = isl_printer_print_id(p, id);
isl_id_free(id);
break;
case isl_ast_expr_int:
p = isl_printer_print_str(p, "val");
p = isl_printer_yaml_next(p);
v = isl_ast_expr_get_val(expr);
p = isl_printer_print_val(p, v);
isl_val_free(v);
break;
}
p = isl_printer_yaml_end_mapping(p);
return p;
}
/* Print "expr" to "p".
*
* Only an isl and a C format are supported.
*/
__isl_give isl_printer *isl_printer_print_ast_expr(__isl_take isl_printer *p,
__isl_keep isl_ast_expr *expr)
{
int format;
if (!p)
return NULL;
format = isl_printer_get_output_format(p);
switch (format) {
case ISL_FORMAT_ISL:
p = print_ast_expr_isl(p, expr);
break;
case ISL_FORMAT_C:
p = print_ast_expr_c(p, expr);
break;
default:
isl_die(isl_printer_get_ctx(p), isl_error_unsupported,
"output format not supported for ast_expr",
return isl_printer_free(p));
}
return p;
}
static __isl_give isl_printer *print_ast_node_isl(__isl_take isl_printer *p,
__isl_keep isl_ast_node *node);
/* Print a YAML sequence containing the entries in "list" to "p".
*/
static __isl_give isl_printer *print_ast_node_list(__isl_take isl_printer *p,
__isl_keep isl_ast_node_list *list)
{
int i, n;
n = isl_ast_node_list_n_ast_node(list);
if (n < 0)
return isl_printer_free(p);
p = isl_printer_yaml_start_sequence(p);
for (i = 0; i < n; ++i) {
isl_ast_node *node;
node = isl_ast_node_list_get_ast_node(list, i);
p = print_ast_node_isl(p, node);
isl_ast_node_free(node);
p = isl_printer_yaml_next(p);
}
p = isl_printer_yaml_end_sequence(p);
return p;
}
/* Print "node" to "p" in "isl format".
*
* In particular, print the isl_ast_node as a YAML document.
*/
static __isl_give isl_printer *print_ast_node_isl(__isl_take isl_printer *p,
__isl_keep isl_ast_node *node)
{
p = isl_printer_print_str(p, "(");
switch (node->type) {
case isl_ast_node_for:
p = isl_printer_yaml_start_mapping(p);
p = isl_printer_print_str(p, "iterator");
p = isl_printer_yaml_next(p);
p = isl_printer_print_ast_expr(p, node->u.f.iterator);
p = isl_printer_yaml_next(p);
if (node->u.f.degenerate) {
p = isl_printer_print_str(p, "value");
p = isl_printer_yaml_next(p);
p = isl_printer_print_ast_expr(p, node->u.f.init);
p = isl_printer_yaml_next(p);
} else {
p = isl_printer_print_str(p, "init: ");
p = isl_printer_print_str(p, "init");
p = isl_printer_yaml_next(p);
p = isl_printer_print_ast_expr(p, node->u.f.init);
p = isl_printer_print_str(p, ", ");
p = isl_printer_print_str(p, "cond: ");
p = isl_printer_yaml_next(p);
p = isl_printer_print_str(p, "cond");
p = isl_printer_yaml_next(p);
p = isl_printer_print_ast_expr(p, node->u.f.cond);
p = isl_printer_print_str(p, ", ");
p = isl_printer_print_str(p, "inc: ");
p = isl_printer_yaml_next(p);
p = isl_printer_print_str(p, "inc");
p = isl_printer_yaml_next(p);
p = isl_printer_print_ast_expr(p, node->u.f.inc);
p = isl_printer_yaml_next(p);
}
if (node->u.f.body) {
p = isl_printer_print_str(p, ", ");
p = isl_printer_print_str(p, "body: ");
p = isl_printer_print_str(p, "body");
p = isl_printer_yaml_next(p);
p = isl_printer_print_ast_node(p, node->u.f.body);
p = isl_printer_yaml_next(p);
}
p = isl_printer_yaml_end_mapping(p);
break;
case isl_ast_node_mark:
p = isl_printer_print_str(p, "mark: ");
p = isl_printer_yaml_start_mapping(p);
p = isl_printer_print_str(p, "mark");
p = isl_printer_yaml_next(p);
p = isl_printer_print_id(p, node->u.m.mark);
p = isl_printer_print_str(p, ", ");
p = isl_printer_print_str(p, "node: ");
p = isl_printer_yaml_next(p);
p = isl_printer_print_str(p, "node");
p = isl_printer_yaml_next(p);
p = isl_printer_print_ast_node(p, node->u.m.node);
p = isl_printer_yaml_end_mapping(p);
break;
case isl_ast_node_user:
p = isl_printer_yaml_start_mapping(p);
p = isl_printer_print_str(p, "user");
p = isl_printer_yaml_next(p);
p = isl_printer_print_ast_expr(p, node->u.e.expr);
p = isl_printer_yaml_end_mapping(p);
break;
case isl_ast_node_if:
p = isl_printer_print_str(p, "guard: ");
p = isl_printer_yaml_start_mapping(p);
p = isl_printer_print_str(p, "guard");
p = isl_printer_yaml_next(p);
p = isl_printer_print_ast_expr(p, node->u.i.guard);
p = isl_printer_yaml_next(p);
if (node->u.i.then) {
p = isl_printer_print_str(p, ", ");
p = isl_printer_print_str(p, "then: ");
p = isl_printer_print_str(p, "then");
p = isl_printer_yaml_next(p);
p = isl_printer_print_ast_node(p, node->u.i.then);
p = isl_printer_yaml_next(p);
}
if (node->u.i.else_node) {
p = isl_printer_print_str(p, ", ");
p = isl_printer_print_str(p, "else: ");
p = isl_printer_print_str(p, "else");
p = isl_printer_yaml_next(p);
p = isl_printer_print_ast_node(p, node->u.i.else_node);
}
p = isl_printer_yaml_end_mapping(p);
break;
case isl_ast_node_block:
p = isl_printer_print_ast_node_list(p, node->u.b.children);
p = print_ast_node_list(p, node->u.b.children);
break;
case isl_ast_node_error:
break;
}
p = isl_printer_print_str(p, ")");
return p;
}
@ -2480,7 +2680,7 @@ __isl_give isl_printer *isl_ast_op_type_print_macro(
case isl_ast_op_min:
p = isl_printer_start_line(p);
p = isl_printer_print_str(p, "#define ");
p = isl_printer_print_str(p, get_op_str(p, type));
p = isl_printer_print_str(p, get_op_str_c(p, type));
p = isl_printer_print_str(p,
"(x,y) ((x) < (y) ? (x) : (y))");
p = isl_printer_end_line(p);
@ -2488,7 +2688,7 @@ __isl_give isl_printer *isl_ast_op_type_print_macro(
case isl_ast_op_max:
p = isl_printer_start_line(p);
p = isl_printer_print_str(p, "#define ");
p = isl_printer_print_str(p, get_op_str(p, type));
p = isl_printer_print_str(p, get_op_str_c(p, type));
p = isl_printer_print_str(p,
"(x,y) ((x) > (y) ? (x) : (y))");
p = isl_printer_end_line(p);
@ -2496,7 +2696,7 @@ __isl_give isl_printer *isl_ast_op_type_print_macro(
case isl_ast_op_fdiv_q:
p = isl_printer_start_line(p);
p = isl_printer_print_str(p, "#define ");
p = isl_printer_print_str(p, get_op_str(p, type));
p = isl_printer_print_str(p, get_op_str_c(p, type));
p = isl_printer_print_str(p,
"(n,d) "
"(((n)<0) ? -((-(n)+(d)-1)/(d)) : (n)/(d))");
@ -2587,3 +2787,45 @@ __isl_give isl_printer *isl_ast_node_print_macros(
return isl_printer_free(p);
return p;
}
/* Return a string containing C code representing this isl_ast_expr.
*/
__isl_give char *isl_ast_expr_to_C_str(__isl_keep isl_ast_expr *expr)
{
isl_printer *p;
char *str;
if (!expr)
return NULL;
p = isl_printer_to_str(isl_ast_expr_get_ctx(expr));
p = isl_printer_set_output_format(p, ISL_FORMAT_C);
p = isl_printer_print_ast_expr(p, expr);
str = isl_printer_get_str(p);
isl_printer_free(p);
return str;
}
/* Return a string containing C code representing this isl_ast_node.
*/
__isl_give char *isl_ast_node_to_C_str(__isl_keep isl_ast_node *node)
{
isl_printer *p;
char *str;
if (!node)
return NULL;
p = isl_printer_to_str(isl_ast_node_get_ctx(node));
p = isl_printer_set_output_format(p, ISL_FORMAT_C);
p = isl_printer_print_ast_node(p, node);
str = isl_printer_get_str(p);
isl_printer_free(p);
return str;
}

View File

@ -149,6 +149,9 @@
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define if HeaderSearchOptions::AddPath takes 4 arguments */
#undef SETLANGDEFAULTS_TAKES_5_ARGUMENTS
/* The size of `char', as computed by sizeof. */
#undef SIZEOF_CHAR

View File

@ -200,12 +200,12 @@ int isl_map_compatible_domain(struct isl_map *map, struct isl_set *set)
set->dim, isl_dim_set);
}
int isl_basic_map_compatible_domain(struct isl_basic_map *bmap,
struct isl_basic_set *bset)
isl_bool isl_basic_map_compatible_domain(__isl_keep isl_basic_map *bmap,
__isl_keep isl_basic_set *bset)
{
int m;
isl_bool m;
if (!bmap || !bset)
return -1;
return isl_bool_error;
m = isl_space_match(bmap->dim, isl_dim_param, bset->dim, isl_dim_param);
if (m < 0 || !m)
return m;
@ -1830,6 +1830,14 @@ void isl_basic_map_swap_div(struct isl_basic_map *bmap, int a, int b)
ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
}
/* Swap divs "a" and "b" in "bset" and adjust the constraints and
* div definitions accordingly.
*/
void isl_basic_set_swap_div(__isl_keep isl_basic_set *bset, int a, int b)
{
isl_basic_map_swap_div(bset, a, b);
}
/* Eliminate the specified n dimensions starting at first from the
* constraints, without removing the dimensions from the space.
* If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
@ -2310,25 +2318,40 @@ isl_bool isl_set_involves_dims(__isl_keep isl_set *set,
return isl_map_involves_dims(set, type, first, n);
}
/* Return true if the definition of the given div is unknown or depends
* on unknown divs.
/* Does local variable "div" of "bmap" have a complete explicit representation?
* Having a complete explicit representation requires not only
* an explicit representation, but also that all local variables
* that appear in this explicit representation in turn have
* a complete explicit representation.
*/
static int div_is_unknown(__isl_keep isl_basic_map *bmap, int div)
isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div)
{
int i;
unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
isl_bool marked;
if (isl_int_is_zero(bmap->div[div][0]))
return 1;
marked = isl_basic_map_div_is_marked_unknown(bmap, div);
if (marked < 0 || marked)
return isl_bool_not(marked);
for (i = bmap->n_div - 1; i >= 0; --i) {
isl_bool known;
if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
continue;
if (div_is_unknown(bmap, i))
return 1;
known = isl_basic_map_div_is_known(bmap, i);
if (known < 0 || !known)
return known;
}
return 0;
return isl_bool_true;
}
/* Does local variable "div" of "bset" have a complete explicit representation?
*/
isl_bool isl_basic_set_div_is_known(__isl_keep isl_basic_set *bset, int div)
{
return isl_basic_map_div_is_known(bset, div);
}
/* Remove all divs that are unknown or defined in terms of unknown divs.
@ -2342,7 +2365,7 @@ __isl_give isl_basic_map *isl_basic_map_remove_unknown_divs(
return NULL;
for (i = bmap->n_div - 1; i >= 0; --i) {
if (!div_is_unknown(bmap, i))
if (isl_basic_map_div_is_known(bmap, i))
continue;
bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
if (!bmap)
@ -6043,95 +6066,6 @@ error:
return NULL;
}
static struct isl_map *isl_basic_map_partial_lexopt(
struct isl_basic_map *bmap, struct isl_basic_set *dom,
struct isl_set **empty, int max)
{
return isl_tab_basic_map_partial_lexopt(bmap, dom, empty, max);
}
struct isl_map *isl_basic_map_partial_lexmax(
struct isl_basic_map *bmap, struct isl_basic_set *dom,
struct isl_set **empty)
{
return isl_basic_map_partial_lexopt(bmap, dom, empty, 1);
}
struct isl_map *isl_basic_map_partial_lexmin(
struct isl_basic_map *bmap, struct isl_basic_set *dom,
struct isl_set **empty)
{
return isl_basic_map_partial_lexopt(bmap, dom, empty, 0);
}
struct isl_set *isl_basic_set_partial_lexmin(
struct isl_basic_set *bset, struct isl_basic_set *dom,
struct isl_set **empty)
{
return (struct isl_set *)
isl_basic_map_partial_lexmin((struct isl_basic_map *)bset,
dom, empty);
}
struct isl_set *isl_basic_set_partial_lexmax(
struct isl_basic_set *bset, struct isl_basic_set *dom,
struct isl_set **empty)
{
return (struct isl_set *)
isl_basic_map_partial_lexmax((struct isl_basic_map *)bset,
dom, empty);
}
__isl_give isl_pw_multi_aff *isl_basic_map_partial_lexmin_pw_multi_aff(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty)
{
return isl_basic_map_partial_lexopt_pw_multi_aff(bmap, dom, empty, 0);
}
__isl_give isl_pw_multi_aff *isl_basic_map_partial_lexmax_pw_multi_aff(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty)
{
return isl_basic_map_partial_lexopt_pw_multi_aff(bmap, dom, empty, 1);
}
__isl_give isl_pw_multi_aff *isl_basic_set_partial_lexmin_pw_multi_aff(
__isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty)
{
return isl_basic_map_partial_lexmin_pw_multi_aff(bset, dom, empty);
}
__isl_give isl_pw_multi_aff *isl_basic_set_partial_lexmax_pw_multi_aff(
__isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty)
{
return isl_basic_map_partial_lexmax_pw_multi_aff(bset, dom, empty);
}
__isl_give isl_pw_multi_aff *isl_basic_map_lexopt_pw_multi_aff(
__isl_take isl_basic_map *bmap, int max)
{
isl_basic_set *dom = NULL;
isl_space *dom_space;
if (!bmap)
goto error;
dom_space = isl_space_domain(isl_space_copy(bmap->dim));
dom = isl_basic_set_universe(dom_space);
return isl_basic_map_partial_lexopt_pw_multi_aff(bmap, dom, NULL, max);
error:
isl_basic_map_free(bmap);
return NULL;
}
__isl_give isl_pw_multi_aff *isl_basic_map_lexmin_pw_multi_aff(
__isl_take isl_basic_map *bmap)
{
return isl_basic_map_lexopt_pw_multi_aff(bmap, 0);
}
#undef TYPE
#define TYPE isl_pw_multi_aff
#undef SUFFIX
@ -6147,6 +6081,9 @@ __isl_give isl_pw_multi_aff *isl_basic_map_lexmin_pw_multi_aff(
* in the form of an isl_pw_multi_aff.
* If "empty" is not NULL, then set *empty to those elements in dom that
* do not have an image element.
* If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
* should be computed over the domain of "map". "empty" is also NULL
* in this case.
*
* We first compute the lexicographically minimal or maximal element
* in the first basic map. This results in a partial solution "res"
@ -6158,13 +6095,15 @@ __isl_give isl_pw_multi_aff *isl_basic_map_lexmin_pw_multi_aff(
*/
static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
__isl_take isl_map *map, __isl_take isl_set *dom,
__isl_give isl_set **empty, int max)
__isl_give isl_set **empty, unsigned flags)
{
int i;
int full;
isl_pw_multi_aff *res;
isl_set *todo;
if (!map || !dom)
full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
if (!map || (!full && !dom))
goto error;
if (isl_map_plain_is_empty(map)) {
@ -6177,7 +6116,7 @@ static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
res = basic_map_partial_lexopt_pw_multi_aff(
isl_basic_map_copy(map->p[0]),
isl_set_copy(dom), empty, max);
isl_set_copy(dom), empty, flags);
if (empty)
todo = *empty;
@ -6186,9 +6125,9 @@ static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
res_i = basic_map_partial_lexopt_pw_multi_aff(
isl_basic_map_copy(map->p[i]),
isl_set_copy(dom), empty, max);
isl_set_copy(dom), empty, flags);
if (max)
if (ISL_FL_ISSET(flags, ISL_OPT_MAX))
res = isl_pw_multi_aff_union_lexmax(res, res_i);
else
res = isl_pw_multi_aff_union_lexmin(res, res_i);
@ -6227,6 +6166,9 @@ error:
* in the form of an isl_map.
* If "empty" is not NULL, then set *empty to those elements in "dom" that
* do not have an image element.
* If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
* should be computed over the domain of "map". "empty" is also NULL
* in this case.
*
* If the input consists of more than one disjunct, then first
* compute the desired result in the form of an isl_pw_multi_aff and
@ -6243,13 +6185,15 @@ error:
* even more splintering.
*/
static __isl_give isl_map *isl_map_partial_lexopt_aligned(
__isl_take isl_map *map, __isl_take isl_set *dom,
__isl_give isl_set **empty, int max)
__isl_take isl_map *map, __isl_take isl_set *dom,
__isl_give isl_set **empty, unsigned flags)
{
int full;
struct isl_map *res;
isl_pw_multi_aff *pma;
if (!map || !dom)
full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
if (!map || (!full && !dom))
goto error;
if (isl_map_plain_is_empty(map)) {
@ -6262,12 +6206,13 @@ static __isl_give isl_map *isl_map_partial_lexopt_aligned(
if (map->n == 1) {
res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
dom, empty, max);
dom, empty, flags);
isl_map_free(map);
return res;
}
pma = isl_map_partial_lexopt_aligned_pw_multi_aff(map, dom, empty, max);
pma = isl_map_partial_lexopt_aligned_pw_multi_aff(map, dom, empty,
flags);
return isl_map_from_pw_multi_aff(pma);
error:
if (empty)
@ -6281,7 +6226,7 @@ __isl_give isl_map *isl_map_partial_lexmax(
__isl_take isl_map *map, __isl_take isl_set *dom,
__isl_give isl_set **empty)
{
return isl_map_partial_lexopt(map, dom, empty, 1);
return isl_map_partial_lexopt(map, dom, empty, ISL_OPT_MAX);
}
__isl_give isl_map *isl_map_partial_lexmin(
@ -6309,43 +6254,18 @@ __isl_give isl_set *isl_set_partial_lexmax(
dom, empty);
}
/* Compute the lexicographic minimum (or maximum if "max" is set)
* of "bmap" over its domain.
*
* Since we are not interested in the part of the domain space where
* there is no solution, we initialize the domain to those constraints
* of "bmap" that only involve the parameters and the input dimensions.
* This relieves the parametric programming engine from detecting those
* inequalities and transferring them to the context. More importantly,
* it ensures that those inequalities are transferred first and not
* intermixed with inequalities that actually split the domain.
/* Compute the lexicographic minimum (or maximum if "flags" includes
* ISL_OPT_MAX) of "bset" over its parametric domain.
*/
__isl_give isl_map *isl_basic_map_lexopt(__isl_take isl_basic_map *bmap, int max)
__isl_give isl_set *isl_basic_set_lexopt(__isl_take isl_basic_set *bset,
unsigned flags)
{
int n_div;
int n_out;
isl_basic_map *copy;
isl_basic_set *dom;
n_div = isl_basic_map_dim(bmap, isl_dim_div);
n_out = isl_basic_map_dim(bmap, isl_dim_out);
copy = isl_basic_map_copy(bmap);
copy = isl_basic_map_drop_constraints_involving_dims(copy,
isl_dim_div, 0, n_div);
copy = isl_basic_map_drop_constraints_involving_dims(copy,
isl_dim_out, 0, n_out);
dom = isl_basic_map_domain(copy);
return isl_basic_map_partial_lexopt(bmap, dom, NULL, max);
}
__isl_give isl_map *isl_basic_map_lexmin(__isl_take isl_basic_map *bmap)
{
return isl_basic_map_lexopt(bmap, 0);
return isl_basic_map_lexopt(bset, flags);
}
__isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
{
return isl_basic_map_lexopt(bmap, 1);
return isl_basic_map_lexopt(bmap, ISL_OPT_MAX);
}
__isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
@ -6358,6 +6278,18 @@ __isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
return (isl_set *)isl_basic_map_lexmax((isl_basic_map *)bset);
}
/* Compute the lexicographic minimum of "bset" over its parametric domain
* for the purpose of quantifier elimination.
* That is, find an explicit representation for all the existentially
* quantified variables in "bset" by computing their lexicographic
* minimum.
*/
static __isl_give isl_set *isl_basic_set_lexmin_compute_divs(
__isl_take isl_basic_set *bset)
{
return isl_basic_set_lexopt(bset, ISL_OPT_QE);
}
/* Extract the first and only affine expression from list
* and then add it to *pwaff with the given dom.
* This domain is known to be disjoint from other domains
@ -6455,6 +6387,15 @@ static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
return pwaff;
}
/* Compute the minimum of the given output dimension as a function of the
* parameters and input dimensions, but independently of
* the other output dimensions.
*/
__isl_give isl_pw_aff *isl_map_dim_min(__isl_take isl_map *map, int pos)
{
return map_dim_opt(map, pos, 0);
}
/* Compute the maximum of the given output dimension as a function of the
* parameters and input dimensions, but independently of
* the other output dimensions.
@ -6669,7 +6610,7 @@ static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
if (!bset)
return NULL;
if (bset->n_eq == 0)
return isl_basic_set_lexmin(bset);
return isl_basic_set_lexmin_compute_divs(bset);
morph1 = isl_basic_set_parameter_compression(bset);
bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
@ -6679,7 +6620,7 @@ static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
n = isl_basic_set_dim(bset, isl_dim_set);
bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
set = isl_basic_set_lexmin(bset);
set = isl_basic_set_lexmin_compute_divs(bset);
set = isl_morph_set(isl_morph_inverse(morph1), set);
@ -6924,12 +6865,12 @@ error:
__isl_give isl_basic_map *isl_basic_map_mark_div_unknown(
__isl_take isl_basic_map *bmap, int div)
{
isl_bool known;
isl_bool unknown;
known = isl_basic_map_div_is_known(bmap, div);
if (known < 0)
unknown = isl_basic_map_div_is_marked_unknown(bmap, div);
if (unknown < 0)
return isl_basic_map_free(bmap);
if (!known)
if (unknown)
return bmap;
bmap = isl_basic_map_cow(bmap);
@ -6939,16 +6880,22 @@ __isl_give isl_basic_map *isl_basic_map_mark_div_unknown(
return bmap;
}
/* Does local variable "div" of "bmap" have an explicit representation?
/* Is local variable "div" of "bmap" marked as not having an explicit
* representation?
* Note that even if "div" is not marked in this way and therefore
* has an explicit representation, this representation may still
* depend (indirectly) on other local variables that do not
* have an explicit representation.
*/
isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div)
isl_bool isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map *bmap,
int div)
{
if (!bmap)
return isl_bool_error;
if (div < 0 || div >= isl_basic_map_dim(bmap, isl_dim_div))
isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
"position out of bounds", return isl_bool_error);
return !isl_int_is_zero(bmap->div[div][0]);
return isl_int_is_zero(bmap->div[div][0]);
}
/* Return the position of the first local variable that does not
@ -7904,8 +7851,18 @@ static isl_bool map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
return is_subset;
}
/* Is "map1" equal to "map2"?
*
* First check if they are obviously equal.
* If not, then perform a more detailed analysis.
*/
isl_bool isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
{
isl_bool equal;
equal = isl_map_plain_is_equal(map1, map2);
if (equal < 0 || equal)
return equal;
return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
}
@ -8248,7 +8205,7 @@ __isl_give isl_basic_map *isl_basic_map_expand_divs(
j++;
} else {
isl_seq_cpy(bmap->div[i], div->row[i], div->n_col);
if (!isl_basic_map_div_is_known(bmap, i))
if (isl_basic_map_div_is_marked_unknown(bmap, i))
continue;
if (isl_basic_map_add_div_constraints(bmap, i) < 0)
goto error;

View File

@ -17,24 +17,84 @@
#define xSF(TYPE,SUFFIX) TYPE ## SUFFIX
#define SF(TYPE,SUFFIX) xSF(TYPE,SUFFIX)
/* Compute the lexicographic minimum (or maximum if "flags" includes
* ISL_OPT_MAX) of "bmap" over the domain "dom" and return the result.
* If "empty" is not NULL, then *empty is assigned a set that
* contains those parts of the domain where there is no solution.
* If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
* should be computed over the domain of "bmap". "empty" is also NULL
* in this case.
* If "bmap" is marked as rational (ISL_BASIC_MAP_RATIONAL),
* then the rational optimum is computed. Otherwise, the integral optimum
* is computed.
*/
static __isl_give TYPE *SF(isl_basic_map_partial_lexopt,SUFFIX)(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty, unsigned flags)
{
return SF(isl_tab_basic_map_partial_lexopt,SUFFIX)(bmap, dom, empty,
flags);
}
__isl_give TYPE *SF(isl_basic_map_partial_lexmax,SUFFIX)(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty)
{
unsigned flags = ISL_OPT_MAX;
return SF(isl_basic_map_partial_lexopt,SUFFIX)(bmap, dom, empty, flags);
}
__isl_give TYPE *SF(isl_basic_map_partial_lexmin,SUFFIX)(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty)
{
unsigned flags = 0;
return SF(isl_basic_map_partial_lexopt,SUFFIX)(bmap, dom, empty, flags);
}
__isl_give TYPE *SF(isl_basic_set_partial_lexmin,SUFFIX)(
__isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty)
{
return SF(isl_basic_map_partial_lexmin,SUFFIX)(bset, dom, empty);
}
__isl_give TYPE *SF(isl_basic_set_partial_lexmax,SUFFIX)(
__isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty)
{
return SF(isl_basic_map_partial_lexmax,SUFFIX)(bset, dom, empty);
}
/* Given a basic map "bmap", compute the lexicographically minimal
* (or maximal) image element for each domain element in dom.
* If empty is not NULL, then set *empty to those elements in dom
* that do not have an image element.
* If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
* should be computed over the domain of "bmap". "empty" is also NULL
* in this case.
*
* We first make sure the basic sets in dom are disjoint and then
* simply collect the results over each of the basic sets separately.
* We could probably improve the efficiency a bit by moving the union
* domain down into the parametric integer programming.
*
* If a full optimum is being computed (i.e., "flags" includes ISL_OPT_FULL),
* then no domain is given and there is then also no need to consider
* the disjuncts of the domain.
*/
static __isl_give TYPE *SF(basic_map_partial_lexopt,SUFFIX)(
__isl_take isl_basic_map *bmap, __isl_take isl_set *dom,
__isl_give isl_set **empty, int max)
__isl_give isl_set **empty, unsigned flags)
{
int i;
TYPE *res;
isl_set *all_empty;
if (ISL_FL_ISSET(flags, ISL_OPT_FULL))
return SF(isl_basic_map_partial_lexopt,SUFFIX)(bmap, NULL,
empty, flags);
dom = isl_set_make_disjoint(dom);
if (!dom)
goto error;
@ -50,7 +110,7 @@ static __isl_give TYPE *SF(basic_map_partial_lexopt,SUFFIX)(
}
res = SF(isl_basic_map_partial_lexopt,SUFFIX)(isl_basic_map_copy(bmap),
isl_basic_set_copy(dom->p[0]), empty, max);
isl_basic_set_copy(dom->p[0]), empty, flags);
if (empty)
all_empty = *empty;
@ -59,7 +119,7 @@ static __isl_give TYPE *SF(basic_map_partial_lexopt,SUFFIX)(
res_i = SF(isl_basic_map_partial_lexopt,SUFFIX)(
isl_basic_map_copy(bmap),
isl_basic_set_copy(dom->p[i]), empty, max);
isl_basic_set_copy(dom->p[i]), empty, flags);
res = ADD(res, res_i);
if (empty)
@ -79,9 +139,29 @@ error:
return NULL;
}
/* Compute the lexicographic minimum (or maximum if "flags" includes
* ISL_OPT_MAX) of "bmap" over its domain.
*/
__isl_give TYPE *SF(isl_basic_map_lexopt,SUFFIX)(
__isl_take isl_basic_map *bmap, unsigned flags)
{
ISL_FL_SET(flags, ISL_OPT_FULL);
return SF(isl_basic_map_partial_lexopt,SUFFIX)(bmap, NULL, NULL, flags);
}
__isl_give TYPE *SF(isl_basic_map_lexmin,SUFFIX)(__isl_take isl_basic_map *bmap)
{
return SF(isl_basic_map_lexopt,SUFFIX)(bmap, 0);
}
static __isl_give TYPE *SF(isl_map_partial_lexopt_aligned,SUFFIX)(
__isl_take isl_map *map, __isl_take isl_set *dom,
__isl_give isl_set **empty, int max);
__isl_give isl_set **empty, unsigned flags);
/* This function is currently only used when TYPE is defined as isl_map. */
static __isl_give TYPE *SF(isl_map_partial_lexopt,SUFFIX)(
__isl_take isl_map *map, __isl_take isl_set *dom,
__isl_give isl_set **empty, unsigned flags)
__attribute__ ((unused));
/* Given a map "map", compute the lexicographically minimal
* (or maximal) image element for each domain element in dom.
@ -91,20 +171,21 @@ static __isl_give TYPE *SF(isl_map_partial_lexopt_aligned,SUFFIX)(
*/
static __isl_give TYPE *SF(isl_map_partial_lexopt,SUFFIX)(
__isl_take isl_map *map, __isl_take isl_set *dom,
__isl_give isl_set **empty, int max)
__isl_give isl_set **empty, unsigned flags)
{
if (!map || !dom)
goto error;
if (isl_space_match(map->dim, isl_dim_param, dom->dim, isl_dim_param))
return SF(isl_map_partial_lexopt_aligned,SUFFIX)(map, dom,
empty, max);
empty, flags);
if (!isl_space_has_named_params(map->dim) ||
!isl_space_has_named_params(dom->dim))
isl_die(map->ctx, isl_error_invalid,
"unaligned unnamed parameters", goto error);
map = isl_map_align_params(map, isl_map_get_space(dom));
dom = isl_map_align_params(dom, isl_map_get_space(map));
return SF(isl_map_partial_lexopt_aligned,SUFFIX)(map, dom, empty, max);
return SF(isl_map_partial_lexopt_aligned,SUFFIX)(map, dom, empty,
flags);
error:
if (empty)
*empty = NULL;
@ -113,19 +194,15 @@ error:
return NULL;
}
__isl_give TYPE *SF(isl_map_lexopt,SUFFIX)(__isl_take isl_map *map, int max)
/* Compute the lexicographic minimum (or maximum if "flags" includes
* ISL_OPT_MAX) of "map" over its domain.
*/
__isl_give TYPE *SF(isl_map_lexopt,SUFFIX)(__isl_take isl_map *map,
unsigned flags)
{
isl_set *dom = NULL;
isl_space *dom_space;
if (!map)
goto error;
dom_space = isl_space_domain(isl_space_copy(map->dim));
dom = isl_set_universe(dom_space);
return SF(isl_map_partial_lexopt,SUFFIX)(map, dom, NULL, max);
error:
isl_map_free(map);
return NULL;
ISL_FL_SET(flags, ISL_OPT_FULL);
return SF(isl_map_partial_lexopt_aligned,SUFFIX)(map, NULL, NULL,
flags);
}
__isl_give TYPE *SF(isl_map_lexmin,SUFFIX)(__isl_take isl_map *map)
@ -135,7 +212,7 @@ __isl_give TYPE *SF(isl_map_lexmin,SUFFIX)(__isl_take isl_map *map)
__isl_give TYPE *SF(isl_map_lexmax,SUFFIX)(__isl_take isl_map *map)
{
return SF(isl_map_lexopt,SUFFIX)(map, 1);
return SF(isl_map_lexopt,SUFFIX)(map, ISL_OPT_MAX);
}
__isl_give TYPE *SF(isl_set_lexmin,SUFFIX)(__isl_take isl_set *set)

View File

@ -189,8 +189,8 @@ unsigned isl_basic_set_offset(struct isl_basic_set *bset,
int isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap);
int isl_map_may_be_set(__isl_keep isl_map *map);
int isl_map_compatible_domain(struct isl_map *map, struct isl_set *set);
int isl_basic_map_compatible_domain(struct isl_basic_map *bmap,
struct isl_basic_set *bset);
isl_bool isl_basic_map_compatible_domain(__isl_keep isl_basic_map *bmap,
__isl_keep isl_basic_set *bset);
int isl_basic_map_compatible_range(struct isl_basic_map *bmap,
struct isl_basic_set *bset);
@ -262,6 +262,7 @@ struct isl_basic_map *isl_basic_map_set_to_empty(struct isl_basic_map *bmap);
struct isl_basic_set *isl_basic_set_set_to_empty(struct isl_basic_set *bset);
struct isl_basic_set *isl_basic_set_order_divs(struct isl_basic_set *bset);
void isl_basic_map_swap_div(struct isl_basic_map *bmap, int a, int b);
void isl_basic_set_swap_div(struct isl_basic_set *bset, int a, int b);
struct isl_basic_map *isl_basic_map_order_divs(struct isl_basic_map *bmap);
__isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map);
struct isl_basic_map *isl_basic_map_align_divs(
@ -422,6 +423,9 @@ __isl_give isl_basic_map *isl_basic_map_expand_divs(
__isl_give isl_basic_map *isl_basic_map_mark_div_unknown(
__isl_take isl_basic_map *bmap, int div);
isl_bool isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map *bmap,
int div);
isl_bool isl_basic_set_div_is_known(__isl_keep isl_basic_set *bset, int div);
isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div);
int isl_basic_map_first_unknown_div(__isl_keep isl_basic_map *bmap);
isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap);

View File

@ -4983,7 +4983,7 @@ static __isl_give isl_basic_map *isl_basic_map_preimage_vars(
if (preimage(bmap->ineq[i] + 1 + pos, T) < 0)
goto error;
for (i = 0; i < bmap->n_div; ++i) {
if (!isl_basic_map_div_is_known(bmap, i))
if (isl_basic_map_div_is_marked_unknown(bmap, i))
continue;
if (preimage(bmap->div[i] + 1 + 1 + pos, T) < 0)
goto error;

View File

@ -1725,6 +1725,25 @@ void isl_mat_gcd(__isl_keep isl_mat *mat, isl_int *gcd)
isl_int_clear(g);
}
/* Return the result of scaling "mat" by a factor of "m".
*/
__isl_give isl_mat *isl_mat_scale(__isl_take isl_mat *mat, isl_int m)
{
int i;
if (isl_int_is_one(m))
return mat;
mat = isl_mat_cow(mat);
if (!mat)
return NULL;
for (i = 0; i < mat->n_row; ++i)
isl_seq_scale(mat->row[i], mat->row[i], m, mat->n_col);
return mat;
}
__isl_give isl_mat *isl_mat_scale_down(__isl_take isl_mat *mat, isl_int m)
{
int i;

View File

@ -32,6 +32,7 @@ void isl_mat_sub_neg(struct isl_ctx *ctx, isl_int **dst, isl_int **src,
unsigned n_row, unsigned dst_col, unsigned src_col, unsigned n_col);
__isl_give isl_mat *isl_mat_diag(isl_ctx *ctx, unsigned n_row, isl_int d);
__isl_give isl_mat *isl_mat_scale(__isl_take isl_mat *mat, isl_int m);
__isl_give isl_mat *isl_mat_scale_down_row(__isl_take isl_mat *mat, int row,
isl_int m);

View File

@ -599,9 +599,13 @@ static __isl_give isl_printer *print_constraints(__isl_keep isl_basic_map *bmap,
unsigned total = isl_basic_map_total_dim(bmap);
unsigned o_div = isl_basic_map_offset(bmap, isl_dim_div);
int first = 1;
int dump;
if (!p)
return NULL;
bmap = isl_basic_map_copy(bmap);
if (!p->dump)
dump = p->dump;
if (!dump)
bmap = isl_basic_map_sort_constraints(bmap);
if (!bmap)
goto error;
@ -633,7 +637,7 @@ static __isl_give isl_printer *print_constraints(__isl_keep isl_basic_map *bmap,
const char *op;
if (l < 0)
continue;
if (!p->dump && l >= o_div &&
if (!dump && l >= o_div &&
can_print_div_expr(p, div, l - o_div) &&
isl_basic_map_is_div_constraint(bmap, bmap->ineq[i],
l - o_div))
@ -646,7 +650,7 @@ static __isl_give isl_printer *print_constraints(__isl_keep isl_basic_map *bmap,
isl_seq_neg(c->el, bmap->ineq[i], 1 + total);
if (strict)
isl_int_set_si(c->el[0], 0);
if (!p->dump && next_is_opposite(bmap, i, l)) {
if (!dump && next_is_opposite(bmap, i, l)) {
op = constraint_op(-s, strict, latex);
p = print_half_constraint(bmap, space, div, p, c->el, l,
op, first, latex);
@ -748,23 +752,25 @@ static isl_bool need_exists(__isl_keep isl_printer *p,
static __isl_give isl_printer *print_disjunct(__isl_keep isl_basic_map *bmap,
__isl_keep isl_space *space, __isl_take isl_printer *p, int latex)
{
int dump;
isl_mat *div;
isl_bool exists;
if (!p)
return NULL;
dump = p->dump;
div = isl_basic_map_get_divs(bmap);
if (p->dump)
if (dump)
exists = bmap->n_div > 0;
else
exists = need_exists(p, bmap, div);
if (exists >= 0 && exists) {
p = isl_printer_print_str(p, s_open_exists[latex]);
p = print_div_list(p, space, div, latex, p->dump);
p = print_div_list(p, space, div, latex, dump);
p = isl_printer_print_str(p, ": ");
}
if (p->dump)
if (dump)
div = isl_mat_free(div);
p = print_constraints(bmap, space, div, p, latex);
isl_mat_free(div);
@ -1194,6 +1200,8 @@ static __isl_give isl_printer *isl_map_print_isl_body(__isl_keep isl_map *map,
struct isl_aff_split *split = NULL;
int rational;
if (!p || !map)
return isl_printer_free(p);
if (!p->dump && map->n > 0)
split = split_aff(map);
if (split) {

View File

@ -669,9 +669,17 @@ __isl_give isl_printer *isl_printer_end_line(__isl_take isl_printer *p)
return p->ops->end_line(p);
}
char *isl_printer_get_str(__isl_keep isl_printer *printer)
/* Return a copy of the string constructed by the string printer "printer".
*/
__isl_give char *isl_printer_get_str(__isl_keep isl_printer *printer)
{
if (!printer || !printer->buf)
if (!printer)
return NULL;
if (printer->ops != &str_ops)
isl_die(isl_printer_get_ctx(printer), isl_error_invalid,
"isl_printer_get_str can only be called on a string "
"printer", return NULL);
if (!printer->buf)
return NULL;
return strdup(printer->buf);
}

View File

@ -1150,36 +1150,6 @@ __isl_give isl_printer *isl_printer_print_schedule(__isl_take isl_printer *p,
return p;
}
void isl_schedule_dump(__isl_keep isl_schedule *schedule)
{
isl_printer *printer;
if (!schedule)
return;
printer = isl_printer_to_file(isl_schedule_get_ctx(schedule), stderr);
printer = isl_printer_set_yaml_style(printer, ISL_YAML_STYLE_BLOCK);
printer = isl_printer_print_schedule(printer, schedule);
isl_printer_free(printer);
}
/* Return a string representation of "schedule".
* Print the schedule in flow format.
*/
__isl_give char *isl_schedule_to_str(__isl_keep isl_schedule *schedule)
{
isl_printer *printer;
char *s;
if (!schedule)
return NULL;
printer = isl_printer_to_str(isl_schedule_get_ctx(schedule));
printer = isl_printer_set_yaml_style(printer, ISL_YAML_STYLE_FLOW);
printer = isl_printer_print_schedule(printer, schedule);
s = isl_printer_get_str(printer);
isl_printer_free(printer);
return s;
}
#undef BASE
#define BASE schedule
#include <print_templ_yaml.c>

View File

@ -672,10 +672,11 @@ int isl_space_find_dim_by_name(__isl_keep isl_space *space,
offset = isl_space_offset(space, type);
n = isl_space_dim(space, type);
for (i = 0; i < n && offset + i < space->n_id; ++i)
if (space->ids[offset + i]->name &&
!strcmp(space->ids[offset + i]->name, name))
for (i = 0; i < n && offset + i < space->n_id; ++i) {
isl_id *id = get_id(space, type, i);
if (id && id->name && !strcmp(id->name, name))
return i;
}
return -1;
}
@ -829,34 +830,34 @@ int isl_space_tuple_match(__isl_keep isl_space *space1, enum isl_dim_type type1,
return isl_space_tuple_is_equal(space1, type1, space2, type2);
}
static int match(__isl_keep isl_space *dim1, enum isl_dim_type dim1_type,
__isl_keep isl_space *dim2, enum isl_dim_type dim2_type)
static int match(__isl_keep isl_space *space1, enum isl_dim_type type1,
__isl_keep isl_space *space2, enum isl_dim_type type2)
{
int i;
if (dim1 == dim2 && dim1_type == dim2_type)
if (space1 == space2 && type1 == type2)
return 1;
if (!isl_space_tuple_is_equal(dim1, dim1_type, dim2, dim2_type))
if (!isl_space_tuple_is_equal(space1, type1, space2, type2))
return 0;
if (!dim1->ids && !dim2->ids)
if (!space1->ids && !space2->ids)
return 1;
for (i = 0; i < n(dim1, dim1_type); ++i) {
if (get_id(dim1, dim1_type, i) != get_id(dim2, dim2_type, i))
for (i = 0; i < n(space1, type1); ++i) {
if (get_id(space1, type1, i) != get_id(space2, type2, i))
return 0;
}
return 1;
}
int isl_space_match(__isl_keep isl_space *dim1, enum isl_dim_type dim1_type,
__isl_keep isl_space *dim2, enum isl_dim_type dim2_type)
isl_bool isl_space_match(__isl_keep isl_space *space1, enum isl_dim_type type1,
__isl_keep isl_space *space2, enum isl_dim_type type2)
{
if (!dim1 || !dim2)
return -1;
if (!space1 || !space2)
return isl_bool_error;
return match(dim1, dim1_type, dim2, dim2_type);
return match(space1, type1, space2, type2);
}
static void get_ids(__isl_keep isl_space *dim, enum isl_dim_type type,

View File

@ -3236,7 +3236,7 @@ int isl_tab_is_redundant(struct isl_tab *tab, int con)
return tab->con[con].is_row && tab->con[con].index < tab->n_redundant;
}
/* Take a snapshot of the tableau that can be restored by s call to
/* Take a snapshot of the tableau that can be restored by a call to
* isl_tab_rollback.
*/
struct isl_tab_undo *isl_tab_snap(struct isl_tab *tab)
@ -3247,6 +3247,31 @@ struct isl_tab_undo *isl_tab_snap(struct isl_tab *tab)
return tab->top;
}
/* Does "tab" need to keep track of undo information?
* That is, was a snapshot taken that may need to be restored?
*/
isl_bool isl_tab_need_undo(struct isl_tab *tab)
{
if (!tab)
return isl_bool_error;
return tab->need_undo;
}
/* Remove all tracking of undo information from "tab", invalidating
* any snapshots that may have been taken of the tableau.
* Since all snapshots have been invalidated, there is also
* no need to start keeping track of undo information again.
*/
void isl_tab_clear_undo(struct isl_tab *tab)
{
if (!tab)
return;
free_undo(tab);
tab->need_undo = 0;
}
/* Undo the operation performed by isl_tab_relax.
*/
static int unrelax(struct isl_tab *tab, struct isl_tab_var *var) WARN_UNUSED;

View File

@ -235,6 +235,8 @@ enum isl_ineq_type isl_tab_ineq_type(struct isl_tab *tab, isl_int *ineq);
struct isl_tab_undo *isl_tab_snap(struct isl_tab *tab);
int isl_tab_rollback(struct isl_tab *tab, struct isl_tab_undo *snap) WARN_UNUSED;
isl_bool isl_tab_need_undo(struct isl_tab *tab);
void isl_tab_clear_undo(struct isl_tab *tab);
int isl_tab_relax(struct isl_tab *tab, int con) WARN_UNUSED;
int isl_tab_select_facet(struct isl_tab *tab, int con) WARN_UNUSED;
@ -242,12 +244,18 @@ int isl_tab_unrestrict(struct isl_tab *tab, int con) WARN_UNUSED;
void isl_tab_dump(__isl_keep struct isl_tab *tab);
struct isl_map *isl_tab_basic_map_partial_lexopt(
struct isl_basic_map *bmap, struct isl_basic_set *dom,
struct isl_set **empty, int max);
__isl_give isl_pw_multi_aff *isl_basic_map_partial_lexopt_pw_multi_aff(
/* Compute maximum instead of minimum. */
#define ISL_OPT_MAX (1 << 0)
/* Compute full instead of partial optimum; also, domain argument is NULL. */
#define ISL_OPT_FULL (1 << 1)
/* Result should be free of (unknown) quantified variables. */
#define ISL_OPT_QE (1 << 2)
__isl_give isl_map *isl_tab_basic_map_partial_lexopt(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty, int max);
__isl_give isl_set **empty, unsigned flags);
__isl_give isl_pw_multi_aff *isl_tab_basic_map_partial_lexopt_pw_multi_aff(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty, unsigned flags);
/* An isl_region represents a sequence of consecutive variables.
* pos is the location (starting at 0) of the first variable in the sequence.

View File

@ -0,0 +1,230 @@
/*
* Copyright 2008-2009 Katholieke Universiteit Leuven
* Copyright 2010 INRIA Saclay
* Copyright 2011 Sven Verdoolaege
*
* Use of this software is governed by the MIT license
*
* Written by Sven Verdoolaege, K.U.Leuven, Departement
* Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
* and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
* ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
*/
#define xSF(TYPE,SUFFIX) TYPE ## SUFFIX
#define SF(TYPE,SUFFIX) xSF(TYPE,SUFFIX)
/* Given a basic map with at least two parallel constraints (as found
* by the function parallel_constraints), first look for more constraints
* parallel to the two constraint and replace the found list of parallel
* constraints by a single constraint with as "input" part the minimum
* of the input parts of the list of constraints. Then, recursively call
* basic_map_partial_lexopt (possibly finding more parallel constraints)
* and plug in the definition of the minimum in the result.
*
* As in parallel_constraints, only inequality constraints that only
* involve input variables that do not occur in any other inequality
* constraints are considered.
*
* More specifically, given a set of constraints
*
* a x + b_i(p) >= 0
*
* Replace this set by a single constraint
*
* a x + u >= 0
*
* with u a new parameter with constraints
*
* u <= b_i(p)
*
* Any solution to the new system is also a solution for the original system
* since
*
* a x >= -u >= -b_i(p)
*
* Moreover, m = min_i(b_i(p)) satisfies the constraints on u and can
* therefore be plugged into the solution.
*/
static TYPE *SF(basic_map_partial_lexopt_symm,SUFFIX)(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty, int max, int first, int second)
{
int i, n, k;
int *list = NULL;
unsigned n_in, n_out, n_div;
isl_ctx *ctx;
isl_vec *var = NULL;
isl_mat *cst = NULL;
isl_space *map_space, *set_space;
map_space = isl_basic_map_get_space(bmap);
set_space = empty ? isl_basic_set_get_space(dom) : NULL;
n_in = isl_basic_map_dim(bmap, isl_dim_param) +
isl_basic_map_dim(bmap, isl_dim_in);
n_out = isl_basic_map_dim(bmap, isl_dim_all) - n_in;
ctx = isl_basic_map_get_ctx(bmap);
list = isl_alloc_array(ctx, int, bmap->n_ineq);
var = isl_vec_alloc(ctx, n_out);
if ((bmap->n_ineq && !list) || (n_out && !var))
goto error;
list[0] = first;
list[1] = second;
isl_seq_cpy(var->el, bmap->ineq[first] + 1 + n_in, n_out);
for (i = second + 1, n = 2; i < bmap->n_ineq; ++i) {
if (isl_seq_eq(var->el, bmap->ineq[i] + 1 + n_in, n_out) &&
all_single_occurrence(bmap, i, n_in))
list[n++] = i;
}
cst = isl_mat_alloc(ctx, n, 1 + n_in);
if (!cst)
goto error;
for (i = 0; i < n; ++i)
isl_seq_cpy(cst->row[i], bmap->ineq[list[i]], 1 + n_in);
bmap = isl_basic_map_cow(bmap);
if (!bmap)
goto error;
for (i = n - 1; i >= 0; --i)
if (isl_basic_map_drop_inequality(bmap, list[i]) < 0)
goto error;
bmap = isl_basic_map_add_dims(bmap, isl_dim_in, 1);
bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
k = isl_basic_map_alloc_inequality(bmap);
if (k < 0)
goto error;
isl_seq_clr(bmap->ineq[k], 1 + n_in);
isl_int_set_si(bmap->ineq[k][1 + n_in], 1);
isl_seq_cpy(bmap->ineq[k] + 1 + n_in + 1, var->el, n_out);
bmap = isl_basic_map_finalize(bmap);
n_div = isl_basic_set_dim(dom, isl_dim_div);
dom = isl_basic_set_add_dims(dom, isl_dim_set, 1);
dom = isl_basic_set_extend_constraints(dom, 0, n);
for (i = 0; i < n; ++i) {
k = isl_basic_set_alloc_inequality(dom);
if (k < 0)
goto error;
isl_seq_cpy(dom->ineq[k], cst->row[i], 1 + n_in);
isl_int_set_si(dom->ineq[k][1 + n_in], -1);
isl_seq_clr(dom->ineq[k] + 1 + n_in + 1, n_div);
}
isl_vec_free(var);
free(list);
return SF(basic_map_partial_lexopt_symm_core,SUFFIX)(bmap, dom, empty,
max, cst, map_space, set_space);
error:
isl_space_free(map_space);
isl_space_free(set_space);
isl_mat_free(cst);
isl_vec_free(var);
free(list);
isl_basic_set_free(dom);
isl_basic_map_free(bmap);
return NULL;
}
/* Recursive part of isl_tab_basic_map_partial_lexopt*, after detecting
* equalities and removing redundant constraints.
*
* We first check if there are any parallel constraints (left).
* If not, we are in the base case.
* If there are parallel constraints, we replace them by a single
* constraint in basic_map_partial_lexopt_symm_pma and then call
* this function recursively to look for more parallel constraints.
*/
static __isl_give TYPE *SF(basic_map_partial_lexopt,SUFFIX)(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty, int max)
{
int par = 0;
int first, second;
if (!bmap)
goto error;
if (bmap->ctx->opt->pip_symmetry)
par = parallel_constraints(bmap, &first, &second);
if (par < 0)
goto error;
if (!par)
return SF(basic_map_partial_lexopt_base,SUFFIX)(bmap, dom,
empty, max);
return SF(basic_map_partial_lexopt_symm,SUFFIX)(bmap, dom, empty, max,
first, second);
error:
isl_basic_set_free(dom);
isl_basic_map_free(bmap);
return NULL;
}
/* Compute the lexicographic minimum (or maximum if "flags" includes
* ISL_OPT_MAX) of "bmap" over the domain "dom" and return the result as
* either a map or a piecewise multi-affine expression depending on TYPE.
* If "empty" is not NULL, then *empty is assigned a set that
* contains those parts of the domain where there is no solution.
* If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
* should be computed over the domain of "bmap". "empty" is also NULL
* in this case.
* If "bmap" is marked as rational (ISL_BASIC_MAP_RATIONAL),
* then we compute the rational optimum. Otherwise, we compute
* the integral optimum.
*
* We perform some preprocessing. As the PILP solver does not
* handle implicit equalities very well, we first make sure all
* the equalities are explicitly available.
*
* We also add context constraints to the basic map and remove
* redundant constraints. This is only needed because of the
* way we handle simple symmetries. In particular, we currently look
* for symmetries on the constraints, before we set up the main tableau.
* It is then no good to look for symmetries on possibly redundant constraints.
* If the domain was extracted from the basic map, then there is
* no need to add back those constraints again.
*/
__isl_give TYPE *SF(isl_tab_basic_map_partial_lexopt,SUFFIX)(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty, unsigned flags)
{
int max, full;
isl_bool compatible;
if (empty)
*empty = NULL;
full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
if (full)
dom = extract_domain(bmap, flags);
compatible = isl_basic_map_compatible_domain(bmap, dom);
if (compatible < 0)
goto error;
if (!compatible)
isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
"domain does not match input", goto error);
max = ISL_FL_ISSET(flags, ISL_OPT_MAX);
if (isl_basic_set_dim(dom, isl_dim_all) == 0)
return SF(basic_map_partial_lexopt,SUFFIX)(bmap, dom, empty,
max);
if (!full)
bmap = isl_basic_map_intersect_domain(bmap,
isl_basic_set_copy(dom));
bmap = isl_basic_map_detect_equalities(bmap);
bmap = isl_basic_map_remove_redundancies(bmap);
return SF(basic_map_partial_lexopt,SUFFIX)(bmap, dom, empty, max);
error:
isl_basic_set_free(dom);
isl_basic_map_free(bmap);
return NULL;
}

View File

@ -1,6 +1,7 @@
/*
* Copyright 2008-2009 Katholieke Universiteit Leuven
* Copyright 2010 INRIA Saclay
* Copyright 2016 Sven Verdoolaege
*
* Use of this software is governed by the MIT license
*
@ -18,6 +19,7 @@
#include <isl_mat_private.h>
#include <isl_vec_private.h>
#include <isl_aff_private.h>
#include <isl_constraint_private.h>
#include <isl_options_private.h>
#include <isl_config.h>
@ -3088,6 +3090,9 @@ static int last_non_zero_var_col(struct isl_tab *tab, isl_int *p)
* that is one or negative one, we use it to kill a column
* in the main tableau. Otherwise, we discard the tentatively
* added row.
* This tentative addition of equality constraints turns
* on the undo facility of the tableau. Turn it off again
* at the end, assuming it was turned off to begin with.
*
* Return 0 on success and -1 on failure.
*/
@ -3096,7 +3101,11 @@ static int propagate_equalities(struct isl_context_gbr *cgbr,
{
int i;
struct isl_vec *eq = NULL;
isl_bool needs_undo;
needs_undo = isl_tab_need_undo(tab);
if (needs_undo < 0)
goto error;
eq = isl_vec_alloc(tab->mat->ctx, 1 + tab->n_var);
if (!eq)
goto error;
@ -3139,6 +3148,8 @@ static int propagate_equalities(struct isl_context_gbr *cgbr,
goto error;
}
if (!needs_undo)
isl_tab_clear_undo(tab);
isl_vec_free(eq);
return 0;
@ -3359,7 +3370,7 @@ struct isl_context_op isl_context_gbr_op = {
context_gbr_free,
};
static struct isl_context *isl_context_gbr_alloc(struct isl_basic_set *dom)
static struct isl_context *isl_context_gbr_alloc(__isl_keep isl_basic_set *dom)
{
struct isl_context_gbr *cgbr;
@ -3386,7 +3397,7 @@ error:
return NULL;
}
static struct isl_context *isl_context_alloc(struct isl_basic_set *dom)
static struct isl_context *isl_context_alloc(__isl_keep isl_basic_set *dom)
{
if (!dom)
return NULL;
@ -4107,7 +4118,7 @@ error:
* because they will be added one by one in the given order
* during the construction of the solution map.
*/
static struct isl_sol *basic_map_partial_lexopt_base(
static struct isl_sol *basic_map_partial_lexopt_base_sol(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty, int max,
struct isl_sol *(*init)(__isl_keep isl_basic_map *bmap,
@ -4152,9 +4163,9 @@ error:
/* Base case of isl_tab_basic_map_partial_lexopt, after removing
* some obvious symmetries.
*
* We call basic_map_partial_lexopt_base and extract the results.
* We call basic_map_partial_lexopt_base_sol and extract the results.
*/
static __isl_give isl_map *basic_map_partial_lexopt_base_map(
static __isl_give isl_map *basic_map_partial_lexopt_base(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty, int max)
{
@ -4162,8 +4173,8 @@ static __isl_give isl_map *basic_map_partial_lexopt_base_map(
struct isl_sol *sol;
struct isl_sol_map *sol_map;
sol = basic_map_partial_lexopt_base(bmap, dom, empty, max,
&sol_map_init);
sol = basic_map_partial_lexopt_base_sol(bmap, dom, empty, max,
&sol_map_init);
if (!sol)
return NULL;
sol_map = (struct isl_sol_map *) sol;
@ -4175,6 +4186,74 @@ static __isl_give isl_map *basic_map_partial_lexopt_base_map(
return result;
}
/* Return a count of the number of occurrences of the "n" first
* variables in the inequality constraints of "bmap".
*/
static __isl_give int *count_occurrences(__isl_keep isl_basic_map *bmap,
int n)
{
int i, j;
isl_ctx *ctx;
int *occurrences;
if (!bmap)
return NULL;
ctx = isl_basic_map_get_ctx(bmap);
occurrences = isl_calloc_array(ctx, int, n);
if (!occurrences)
return NULL;
for (i = 0; i < bmap->n_ineq; ++i) {
for (j = 0; j < n; ++j) {
if (!isl_int_is_zero(bmap->ineq[i][1 + j]))
occurrences[j]++;
}
}
return occurrences;
}
/* Do all of the "n" variables with non-zero coefficients in "c"
* occur in exactly a single constraint.
* "occurrences" is an array of length "n" containing the number
* of occurrences of each of the variables in the inequality constraints.
*/
static int single_occurrence(int n, isl_int *c, int *occurrences)
{
int i;
for (i = 0; i < n; ++i) {
if (isl_int_is_zero(c[i]))
continue;
if (occurrences[i] != 1)
return 0;
}
return 1;
}
/* Do all of the "n" initial variables that occur in inequality constraint
* "ineq" of "bmap" only occur in that constraint?
*/
static int all_single_occurrence(__isl_keep isl_basic_map *bmap, int ineq,
int n)
{
int i, j;
for (i = 0; i < n; ++i) {
if (isl_int_is_zero(bmap->ineq[ineq][1 + i]))
continue;
for (j = 0; j < bmap->n_ineq; ++j) {
if (j == ineq)
continue;
if (!isl_int_is_zero(bmap->ineq[j][1 + i]))
return 0;
}
}
return 1;
}
/* Structure used during detection of parallel constraints.
* n_in: number of "input" variables: isl_dim_param + isl_dim_in
* n_out: number of "output" variables: isl_dim_out + isl_dim_div
@ -4203,7 +4282,8 @@ static int constraint_equal(const void *entry, const void *val)
* Note that the coefficients of the existentially quantified
* variables need to be zero since the existentially quantified
* of the result are usually not the same as those of the input.
* the isl_dim_out and isl_dim_div dimensions.
* Furthermore, check that each of the input variables that occur
* in those constraints does not occur in any other constraint.
* If so, return 1 and return the row indices of the two constraints
* in *first and *second.
*/
@ -4212,6 +4292,7 @@ static int parallel_constraints(__isl_keep isl_basic_map *bmap,
{
int i;
isl_ctx *ctx;
int *occurrences = NULL;
struct isl_hash_table *table = NULL;
struct isl_hash_table_entry *entry;
struct isl_constraint_equal_info info;
@ -4225,6 +4306,9 @@ static int parallel_constraints(__isl_keep isl_basic_map *bmap,
info.n_in = isl_basic_map_dim(bmap, isl_dim_param) +
isl_basic_map_dim(bmap, isl_dim_in);
occurrences = count_occurrences(bmap, info.n_in);
if (info.n_in && !occurrences)
goto error;
info.bmap = bmap;
n_out = isl_basic_map_dim(bmap, isl_dim_out);
n_div = isl_basic_map_dim(bmap, isl_dim_div);
@ -4237,6 +4321,9 @@ static int parallel_constraints(__isl_keep isl_basic_map *bmap,
continue;
if (isl_seq_first_non_zero(info.val + n_out, n_div) >= 0)
continue;
if (!single_occurrence(info.n_in, bmap->ineq[i] + 1,
occurrences))
continue;
hash = isl_seq_get_hash(info.val, info.n_out);
entry = isl_hash_table_find(ctx, table, hash,
constraint_equal, &info, 1);
@ -4253,10 +4340,12 @@ static int parallel_constraints(__isl_keep isl_basic_map *bmap,
}
isl_hash_table_free(ctx, table);
free(occurrences);
return i < bmap->n_ineq;
error:
isl_hash_table_free(ctx, table);
free(occurrences);
return -1;
}
@ -4523,12 +4612,6 @@ static __isl_give isl_map *basic_map_partial_lexopt(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty, int max);
union isl_lex_res {
void *p;
isl_map *map;
isl_pw_multi_aff *pma;
};
/* This function is called from basic_map_partial_lexopt_symm.
* The last variable of "bmap" and "dom" corresponds to the minimum
* of the bounds in "cst". "map_space" is the space of the original
@ -4538,14 +4621,13 @@ union isl_lex_res {
* We recursively call basic_map_partial_lexopt and then plug in
* the definition of the minimum in the result.
*/
static __isl_give union isl_lex_res basic_map_partial_lexopt_symm_map_core(
static __isl_give isl_map *basic_map_partial_lexopt_symm_core(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty, int max, __isl_take isl_mat *cst,
__isl_take isl_space *map_space, __isl_take isl_space *set_space)
{
isl_map *opt;
isl_set *min_expr;
union isl_lex_res res;
min_expr = set_minimum(isl_basic_set_get_space(dom), isl_mat_copy(cst));
@ -4560,215 +4642,54 @@ static __isl_give union isl_lex_res basic_map_partial_lexopt_symm_map_core(
opt = split_domain(opt, min_expr, cst);
opt = isl_map_reset_space(opt, map_space);
res.map = opt;
return res;
return opt;
}
/* Given a basic map with at least two parallel constraints (as found
* by the function parallel_constraints), first look for more constraints
* parallel to the two constraint and replace the found list of parallel
* constraints by a single constraint with as "input" part the minimum
* of the input parts of the list of constraints. Then, recursively call
* basic_map_partial_lexopt (possibly finding more parallel constraints)
* and plug in the definition of the minimum in the result.
/* Extract a domain from "bmap" for the purpose of computing
* a lexicographic optimum.
*
* More specifically, given a set of constraints
* This function is only called when the caller wants to compute a full
* lexicographic optimum, i.e., without specifying a domain. In this case,
* the caller is not interested in the part of the domain space where
* there is no solution and the domain can be initialized to those constraints
* of "bmap" that only involve the parameters and the input dimensions.
* This relieves the parametric programming engine from detecting those
* inequalities and transferring them to the context. More importantly,
* it ensures that those inequalities are transferred first and not
* intermixed with inequalities that actually split the domain.
*
* a x + b_i(p) >= 0
*
* Replace this set by a single constraint
*
* a x + u >= 0
*
* with u a new parameter with constraints
*
* u <= b_i(p)
*
* Any solution to the new system is also a solution for the original system
* since
*
* a x >= -u >= -b_i(p)
*
* Moreover, m = min_i(b_i(p)) satisfies the constraints on u and can
* therefore be plugged into the solution.
* If the caller does not require the absence of existentially quantified
* variables in the result (i.e., if ISL_OPT_QE is not set in "flags"),
* then the actual domain of "bmap" can be used. This ensures that
* the domain does not need to be split at all just to separate out
* pieces of the domain that do not have a solution from piece that do.
* This domain cannot be used in general because it may involve
* (unknown) existentially quantified variables which will then also
* appear in the solution.
*/
static union isl_lex_res basic_map_partial_lexopt_symm(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty, int max, int first, int second,
__isl_give union isl_lex_res (*core)(__isl_take isl_basic_map *bmap,
__isl_take isl_basic_set *dom,
__isl_give isl_set **empty,
int max, __isl_take isl_mat *cst,
__isl_take isl_space *map_space,
__isl_take isl_space *set_space))
static __isl_give isl_basic_set *extract_domain(__isl_keep isl_basic_map *bmap,
unsigned flags)
{
int i, n, k;
int *list = NULL;
unsigned n_in, n_out, n_div;
isl_ctx *ctx;
isl_vec *var = NULL;
isl_mat *cst = NULL;
isl_space *map_space, *set_space;
union isl_lex_res res;
int n_div;
int n_out;
map_space = isl_basic_map_get_space(bmap);
set_space = empty ? isl_basic_set_get_space(dom) : NULL;
n_in = isl_basic_map_dim(bmap, isl_dim_param) +
isl_basic_map_dim(bmap, isl_dim_in);
n_out = isl_basic_map_dim(bmap, isl_dim_all) - n_in;
ctx = isl_basic_map_get_ctx(bmap);
list = isl_alloc_array(ctx, int, bmap->n_ineq);
var = isl_vec_alloc(ctx, n_out);
if ((bmap->n_ineq && !list) || (n_out && !var))
goto error;
list[0] = first;
list[1] = second;
isl_seq_cpy(var->el, bmap->ineq[first] + 1 + n_in, n_out);
for (i = second + 1, n = 2; i < bmap->n_ineq; ++i) {
if (isl_seq_eq(var->el, bmap->ineq[i] + 1 + n_in, n_out))
list[n++] = i;
n_div = isl_basic_map_dim(bmap, isl_dim_div);
n_out = isl_basic_map_dim(bmap, isl_dim_out);
bmap = isl_basic_map_copy(bmap);
if (ISL_FL_ISSET(flags, ISL_OPT_QE)) {
bmap = isl_basic_map_drop_constraints_involving_dims(bmap,
isl_dim_div, 0, n_div);
bmap = isl_basic_map_drop_constraints_involving_dims(bmap,
isl_dim_out, 0, n_out);
}
cst = isl_mat_alloc(ctx, n, 1 + n_in);
if (!cst)
goto error;
for (i = 0; i < n; ++i)
isl_seq_cpy(cst->row[i], bmap->ineq[list[i]], 1 + n_in);
bmap = isl_basic_map_cow(bmap);
if (!bmap)
goto error;
for (i = n - 1; i >= 0; --i)
if (isl_basic_map_drop_inequality(bmap, list[i]) < 0)
goto error;
bmap = isl_basic_map_add_dims(bmap, isl_dim_in, 1);
bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
k = isl_basic_map_alloc_inequality(bmap);
if (k < 0)
goto error;
isl_seq_clr(bmap->ineq[k], 1 + n_in);
isl_int_set_si(bmap->ineq[k][1 + n_in], 1);
isl_seq_cpy(bmap->ineq[k] + 1 + n_in + 1, var->el, n_out);
bmap = isl_basic_map_finalize(bmap);
n_div = isl_basic_set_dim(dom, isl_dim_div);
dom = isl_basic_set_add_dims(dom, isl_dim_set, 1);
dom = isl_basic_set_extend_constraints(dom, 0, n);
for (i = 0; i < n; ++i) {
k = isl_basic_set_alloc_inequality(dom);
if (k < 0)
goto error;
isl_seq_cpy(dom->ineq[k], cst->row[i], 1 + n_in);
isl_int_set_si(dom->ineq[k][1 + n_in], -1);
isl_seq_clr(dom->ineq[k] + 1 + n_in + 1, n_div);
}
isl_vec_free(var);
free(list);
return core(bmap, dom, empty, max, cst, map_space, set_space);
error:
isl_space_free(map_space);
isl_space_free(set_space);
isl_mat_free(cst);
isl_vec_free(var);
free(list);
isl_basic_set_free(dom);
isl_basic_map_free(bmap);
res.p = NULL;
return res;
return isl_basic_map_domain(bmap);
}
static __isl_give isl_map *basic_map_partial_lexopt_symm_map(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty, int max, int first, int second)
{
return basic_map_partial_lexopt_symm(bmap, dom, empty, max,
first, second, &basic_map_partial_lexopt_symm_map_core).map;
}
/* Recursive part of isl_tab_basic_map_partial_lexopt, after detecting
* equalities and removing redundant constraints.
*
* We first check if there are any parallel constraints (left).
* If not, we are in the base case.
* If there are parallel constraints, we replace them by a single
* constraint in basic_map_partial_lexopt_symm and then call
* this function recursively to look for more parallel constraints.
*/
static __isl_give isl_map *basic_map_partial_lexopt(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty, int max)
{
int par = 0;
int first, second;
if (!bmap)
goto error;
if (bmap->ctx->opt->pip_symmetry)
par = parallel_constraints(bmap, &first, &second);
if (par < 0)
goto error;
if (!par)
return basic_map_partial_lexopt_base_map(bmap, dom, empty, max);
return basic_map_partial_lexopt_symm_map(bmap, dom, empty, max,
first, second);
error:
isl_basic_set_free(dom);
isl_basic_map_free(bmap);
return NULL;
}
/* Compute the lexicographic minimum (or maximum if "max" is set)
* of "bmap" over the domain "dom" and return the result as a map.
* If "empty" is not NULL, then *empty is assigned a set that
* contains those parts of the domain where there is no solution.
* If "bmap" is marked as rational (ISL_BASIC_MAP_RATIONAL),
* then we compute the rational optimum. Otherwise, we compute
* the integral optimum.
*
* We perform some preprocessing. As the PILP solver does not
* handle implicit equalities very well, we first make sure all
* the equalities are explicitly available.
*
* We also add context constraints to the basic map and remove
* redundant constraints. This is only needed because of the
* way we handle simple symmetries. In particular, we currently look
* for symmetries on the constraints, before we set up the main tableau.
* It is then no good to look for symmetries on possibly redundant constraints.
*/
struct isl_map *isl_tab_basic_map_partial_lexopt(
struct isl_basic_map *bmap, struct isl_basic_set *dom,
struct isl_set **empty, int max)
{
if (empty)
*empty = NULL;
if (!bmap || !dom)
goto error;
isl_assert(bmap->ctx,
isl_basic_map_compatible_domain(bmap, dom), goto error);
if (isl_basic_set_dim(dom, isl_dim_all) == 0)
return basic_map_partial_lexopt(bmap, dom, empty, max);
bmap = isl_basic_map_intersect_domain(bmap, isl_basic_set_copy(dom));
bmap = isl_basic_map_detect_equalities(bmap);
bmap = isl_basic_map_remove_redundancies(bmap);
return basic_map_partial_lexopt(bmap, dom, empty, max);
error:
isl_basic_set_free(dom);
isl_basic_map_free(bmap);
return NULL;
}
#undef TYPE
#define TYPE isl_map
#undef SUFFIX
#define SUFFIX
#include "isl_tab_lexopt_templ.c"
struct isl_sol_for {
struct isl_sol sol;
@ -5381,33 +5302,192 @@ error:
sol->sol.error = 1;
}
/* Given a basic map "dom" that represents the context and an affine
* matrix "M" that maps the dimensions of the context to the
* output variables, construct an isl_pw_multi_aff with a single
* cell corresponding to "dom" and affine expressions copied from "M".
/* Return the equality constraint in "bset" that defines existentially
* quantified variable "pos" in terms of earlier dimensions.
* The equality constraint is guaranteed to exist by the caller.
* If "c" is not NULL, then it is the result of a previous call
* to this function for the same variable, so simply return the input "c"
* in that case.
*/
static void sol_pma_add(struct isl_sol_pma *sol,
__isl_take isl_basic_set *dom, __isl_take isl_mat *M)
static __isl_give isl_constraint *get_equality(__isl_keep isl_basic_set *bset,
int pos, __isl_take isl_constraint *c)
{
int i;
isl_local_space *ls;
isl_aff *aff;
isl_multi_aff *maff;
isl_pw_multi_aff *pma;
int r;
maff = isl_multi_aff_alloc(isl_pw_multi_aff_get_space(sol->pma));
ls = isl_basic_set_get_local_space(dom);
if (c)
return c;
r = isl_basic_set_has_defining_equality(bset, isl_dim_div, pos, &c);
if (r < 0)
return NULL;
if (!r)
isl_die(isl_basic_set_get_ctx(bset), isl_error_internal,
"unexpected missing equality", return NULL);
return c;
}
/* Given a set "dom", of which only the first "n_known" existentially
* quantified variables have a known explicit representation, and
* a matrix "M", the rows of which are defined in terms of the dimensions
* of "dom", eliminate all references to the existentially quantified
* variables without a known explicit representation from "M"
* by exploiting the equality constraints of "dom".
*
* In particular, for each of those existentially quantified variables,
* if there are non-zero entries in the corresponding column of "M",
* then look for an equality constraint of "dom" that defines that variable
* in terms of earlier variables and use it to clear the entries.
*
* In particular, if the equality is of the form
*
* f() + a alpha = 0
*
* while the matrix entry is b/d (with d the global denominator of "M"),
* then first scale the matrix such that the entry becomes b'/d' with
* b' a multiple of a. Do this by multiplying the entire matrix
* by abs(a/gcd(a,b)). Then subtract the equality multiplied by b'/a
* from the row of "M" to clear the entry.
*/
static __isl_give isl_mat *eliminate_unknown_divs(__isl_take isl_mat *M,
__isl_keep isl_basic_set *dom, int n_known)
{
int i, j, n_div, off;
isl_int t;
isl_constraint *c = NULL;
if (!M)
return NULL;
n_div = isl_basic_set_dim(dom, isl_dim_div);
off = M->n_col - n_div;
isl_int_init(t);
for (i = n_div - 1; i >= n_known; --i) {
for (j = 1; j < M->n_row; ++j) {
if (isl_int_is_zero(M->row[j][off + i]))
continue;
c = get_equality(dom, i, c);
if (!c)
goto error;
isl_int_gcd(t, M->row[j][off + i], c->v->el[off + i]);
isl_int_divexact(t, c->v->el[off + i], t);
isl_int_abs(t, t);
M = isl_mat_scale(M, t);
M = isl_mat_cow(M);
if (!M)
goto error;
isl_int_divexact(t,
M->row[j][off + i], c->v->el[off + i]);
isl_seq_submul(M->row[j], t, c->v->el, M->n_col);
}
c = isl_constraint_free(c);
}
isl_int_clear(t);
return M;
error:
isl_int_clear(t);
isl_constraint_free(c);
isl_mat_free(M);
return NULL;
}
/* Return the index of the last known div of "bset" after "start" and
* up to (but not including) "end".
* Return "start" if there is no such known div.
*/
static int last_known_div_after(__isl_keep isl_basic_set *bset,
int start, int end)
{
for (end = end - 1; end > start; --end) {
if (isl_basic_set_div_is_known(bset, end))
return end;
}
return start;
}
/* Set the affine expressions in "ma" according to the rows in "M", which
* are defined over the local space "ls".
* The matrix "M" may have extra (zero) columns beyond the number
* of variables in "ls".
*/
static __isl_give isl_multi_aff *set_from_affine_matrix(
__isl_take isl_multi_aff *ma, __isl_take isl_local_space *ls,
__isl_take isl_mat *M)
{
int i, dim;
isl_aff *aff;
dim = isl_local_space_dim(ls, isl_dim_all);
for (i = 1; i < M->n_row; ++i) {
aff = isl_aff_alloc(isl_local_space_copy(ls));
if (aff) {
isl_int_set(aff->v->el[0], M->row[0][0]);
isl_seq_cpy(aff->v->el + 1, M->row[i], M->n_col);
isl_seq_cpy(aff->v->el + 1, M->row[i], 1 + dim);
}
aff = isl_aff_normalize(aff);
maff = isl_multi_aff_set_aff(maff, i - 1, aff);
ma = isl_multi_aff_set_aff(ma, i - 1, aff);
}
isl_local_space_free(ls);
isl_mat_free(M);
return ma;
}
/* Given a basic map "dom" that represents the context and an affine
* matrix "M" that maps the dimensions of the context to the
* output variables, construct an isl_pw_multi_aff with a single
* cell corresponding to "dom" and affine expressions copied from "M".
*
* Note that the description of the initial context may have involved
* existentially quantified variables, in which case they also appear
* in "dom". These need to be removed before creating the affine
* expression because an affine expression cannot be defined in terms
* of existentially quantified variables without a known representation.
* In particular, they are first moved to the end in both "dom" and "M" and
* then ignored in "M". In principle, the final columns of "M"
* (i.e., those that will be ignored) should be zero at this stage
* because align_context_divs adds the existentially quantified
* variables of the context to the main tableau without any constraints.
* The computed minimal value can therefore not depend on these variables.
* However, additional integer divisions that get added for parametric cuts
* get added to the end and they may happen to be equal to some affine
* expression involving the original existentially quantified variables.
* These equality constraints are then propagated to the main tableau
* such that the computed minimum can in fact depend on those existentially
* quantified variables. This dependence can however be removed again
* by exploiting the equality constraints in "dom".
* eliminate_unknown_divs takes care of this.
*/
static void sol_pma_add(struct isl_sol_pma *sol,
__isl_take isl_basic_set *dom, __isl_take isl_mat *M)
{
isl_local_space *ls;
isl_multi_aff *maff;
isl_pw_multi_aff *pma;
int n_div, n_known, end, off;
n_div = isl_basic_set_dim(dom, isl_dim_div);
off = M->n_col - n_div;
end = n_div;
for (n_known = 0; n_known < end; ++n_known) {
if (isl_basic_set_div_is_known(dom, n_known))
continue;
end = last_known_div_after(dom, n_known, end);
if (end == n_known)
break;
isl_basic_set_swap_div(dom, n_known, end);
M = isl_mat_swap_cols(M, off + n_known, off + end);
}
dom = isl_basic_set_gauss(dom, NULL);
if (n_known < n_div)
M = eliminate_unknown_divs(M, dom, n_known);
maff = isl_multi_aff_alloc(isl_pw_multi_aff_get_space(sol->pma));
ls = isl_basic_set_get_local_space(dom);
ls = isl_local_space_drop_dims(ls, isl_dim_div,
n_known, n_div - n_known);
maff = set_from_affine_matrix(maff, ls, M);
dom = isl_basic_set_simplify(dom);
dom = isl_basic_set_finalize(dom);
pma = isl_pw_multi_aff_alloc(isl_set_from_basic_set(dom), maff);
@ -5486,9 +5566,9 @@ error:
/* Base case of isl_tab_basic_map_partial_lexopt, after removing
* some obvious symmetries.
*
* We call basic_map_partial_lexopt_base and extract the results.
* We call basic_map_partial_lexopt_base_sol and extract the results.
*/
static __isl_give isl_pw_multi_aff *basic_map_partial_lexopt_base_pma(
static __isl_give isl_pw_multi_aff *basic_map_partial_lexopt_base_pw_multi_aff(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty, int max)
{
@ -5496,8 +5576,8 @@ static __isl_give isl_pw_multi_aff *basic_map_partial_lexopt_base_pma(
struct isl_sol *sol;
struct isl_sol_pma *sol_pma;
sol = basic_map_partial_lexopt_base(bmap, dom, empty, max,
&sol_pma_init);
sol = basic_map_partial_lexopt_base_sol(bmap, dom, empty, max,
&sol_pma_init);
if (!sol)
return NULL;
sol_pma = (struct isl_sol_pma *) sol;
@ -5655,7 +5735,7 @@ error:
return NULL;
}
static __isl_give isl_pw_multi_aff *basic_map_partial_lexopt_pma(
static __isl_give isl_pw_multi_aff *basic_map_partial_lexopt_pw_multi_aff(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty, int max);
@ -5668,7 +5748,8 @@ static __isl_give isl_pw_multi_aff *basic_map_partial_lexopt_pma(
* We recursively call basic_map_partial_lexopt and then plug in
* the definition of the minimum in the result.
*/
static __isl_give union isl_lex_res basic_map_partial_lexopt_symm_pma_core(
static __isl_give isl_pw_multi_aff *
basic_map_partial_lexopt_symm_core_pw_multi_aff(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty, int max, __isl_take isl_mat *cst,
__isl_take isl_space *map_space, __isl_take isl_space *set_space)
@ -5676,13 +5757,12 @@ static __isl_give union isl_lex_res basic_map_partial_lexopt_symm_pma_core(
isl_pw_multi_aff *opt;
isl_pw_aff *min_expr_pa;
isl_set *min_expr;
union isl_lex_res res;
min_expr = set_minimum(isl_basic_set_get_space(dom), isl_mat_copy(cst));
min_expr_pa = set_minimum_pa(isl_basic_set_get_space(dom),
isl_mat_copy(cst));
opt = basic_map_partial_lexopt_pma(bmap, dom, empty, max);
opt = basic_map_partial_lexopt_pw_multi_aff(bmap, dom, empty, max);
if (empty) {
*empty = split(*empty,
@ -5693,93 +5773,11 @@ static __isl_give union isl_lex_res basic_map_partial_lexopt_symm_pma_core(
opt = split_domain_pma(opt, min_expr_pa, min_expr, cst);
opt = isl_pw_multi_aff_reset_space(opt, map_space);
res.pma = opt;
return res;
return opt;
}
static __isl_give isl_pw_multi_aff *basic_map_partial_lexopt_symm_pma(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty, int max, int first, int second)
{
return basic_map_partial_lexopt_symm(bmap, dom, empty, max,
first, second, &basic_map_partial_lexopt_symm_pma_core).pma;
}
/* Recursive part of isl_basic_map_partial_lexopt_pw_multi_aff, after detecting
* equalities and removing redundant constraints.
*
* We first check if there are any parallel constraints (left).
* If not, we are in the base case.
* If there are parallel constraints, we replace them by a single
* constraint in basic_map_partial_lexopt_symm_pma and then call
* this function recursively to look for more parallel constraints.
*/
static __isl_give isl_pw_multi_aff *basic_map_partial_lexopt_pma(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty, int max)
{
int par = 0;
int first, second;
if (!bmap)
goto error;
if (bmap->ctx->opt->pip_symmetry)
par = parallel_constraints(bmap, &first, &second);
if (par < 0)
goto error;
if (!par)
return basic_map_partial_lexopt_base_pma(bmap, dom, empty, max);
return basic_map_partial_lexopt_symm_pma(bmap, dom, empty, max,
first, second);
error:
isl_basic_set_free(dom);
isl_basic_map_free(bmap);
return NULL;
}
/* Compute the lexicographic minimum (or maximum if "max" is set)
* of "bmap" over the domain "dom" and return the result as a piecewise
* multi-affine expression.
* If "empty" is not NULL, then *empty is assigned a set that
* contains those parts of the domain where there is no solution.
* If "bmap" is marked as rational (ISL_BASIC_MAP_RATIONAL),
* then we compute the rational optimum. Otherwise, we compute
* the integral optimum.
*
* We perform some preprocessing. As the PILP solver does not
* handle implicit equalities very well, we first make sure all
* the equalities are explicitly available.
*
* We also add context constraints to the basic map and remove
* redundant constraints. This is only needed because of the
* way we handle simple symmetries. In particular, we currently look
* for symmetries on the constraints, before we set up the main tableau.
* It is then no good to look for symmetries on possibly redundant constraints.
*/
__isl_give isl_pw_multi_aff *isl_basic_map_partial_lexopt_pw_multi_aff(
__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
__isl_give isl_set **empty, int max)
{
if (empty)
*empty = NULL;
if (!bmap || !dom)
goto error;
isl_assert(bmap->ctx,
isl_basic_map_compatible_domain(bmap, dom), goto error);
if (isl_basic_set_dim(dom, isl_dim_all) == 0)
return basic_map_partial_lexopt_pma(bmap, dom, empty, max);
bmap = isl_basic_map_intersect_domain(bmap, isl_basic_set_copy(dom));
bmap = isl_basic_map_detect_equalities(bmap);
bmap = isl_basic_map_remove_redundancies(bmap);
return basic_map_partial_lexopt_pma(bmap, dom, empty, max);
error:
isl_basic_set_free(dom);
isl_basic_map_free(bmap);
return NULL;
}
#undef TYPE
#define TYPE isl_pw_multi_aff
#undef SUFFIX
#define SUFFIX _pw_multi_aff
#include "isl_tab_lexopt_templ.c"

View File

@ -2230,8 +2230,50 @@ static int test_lex(struct isl_ctx *ctx)
return 0;
}
/* Inputs for isl_map_lexmin tests.
* "map" is the input and "lexmin" is the expected result.
*/
struct {
const char *map;
const char *lexmin;
} lexmin_tests [] = {
{ "{ [x] -> [y] : x <= y <= 10; [x] -> [5] : -8 <= x <= 8 }",
"{ [x] -> [5] : 6 <= x <= 8; "
"[x] -> [x] : x <= 5 or (9 <= x <= 10) }" },
{ "{ [x] -> [y] : 4y = x or 4y = -1 + x or 4y = -2 + x }",
"{ [x] -> [y] : 4y = x or 4y = -1 + x or 4y = -2 + x }" },
{ "{ [x] -> [y] : x = 4y; [x] -> [y] : x = 2y }",
"{ [x] -> [y] : (4y = x and x >= 0) or "
"(exists (e0 = [(x)/4], e1 = [(-2 + x)/4]: 2y = x and "
"4e1 = -2 + x and 4e0 <= -1 + x and 4e0 >= -3 + x)) or "
"(exists (e0 = [(x)/4]: 2y = x and 4e0 = x and x <= -4)) }" },
{ "{ T[a] -> S[b, c] : a = 4b-2c and c >= b }",
"{ T[a] -> S[b, c] : 2b = a and 2c = a }" },
/* Check that empty pieces are properly combined. */
{ "[K, N] -> { [x, y] -> [a, b] : K+2<=N<=K+4 and x>=4 and "
"2N-6<=x<K+N and N-1<=a<=K+N-1 and N+b-6<=a<=2N-4 and "
"b<=2N-3K+a and 3b<=4N-K+1 and b>=N and a>=x+1 }",
"[K, N] -> { [x, y] -> [1 + x, N] : x >= -6 + 2N and "
"x <= -5 + 2N and x >= -1 + 3K - N and x <= -2 + K + N and "
"x >= 4 }" },
{ "{ [i, k, j] -> [a, b, c, d] : 8*floor((b)/8) = b and k <= 255 and "
"a <= 255 and c <= 255 and d <= 255 - j and "
"255 - j <= 7d <= 7 - i and 240d <= 239 + a and "
"247d <= 247 + k - j and 247d <= 247 + k - b and "
"247d <= 247 + i and 248 - b <= 248d <= c and "
"254d >= i - a + b and 254d >= -a + b and "
"255d >= -i + a - b and 1792d >= -63736 + 257b }",
"{ [i, k, j] -> "
"[-127762 + i + 502j, -62992 + 248j, 63240 - 248j, 255 - j] : "
"k <= 255 and 7j >= 1778 + i and 246j >= 62738 - k and "
"247j >= 62738 - i and 509j <= 129795 + i and "
"742j >= 188724 - i; "
"[0, k, j] -> [1, 0, 248, 1] : k <= 255 and 248 <= j <= 254, k }" },
};
static int test_lexmin(struct isl_ctx *ctx)
{
int i;
int equal;
const char *str;
isl_basic_map *bmap;
@ -2266,35 +2308,20 @@ static int test_lexmin(struct isl_ctx *ctx)
assert(!isl_set_is_empty(set));
isl_set_free(set);
str = "{ [x] -> [y] : x <= y <= 10; [x] -> [5] : -8 <= x <= 8 }";
map = isl_map_read_from_str(ctx, str);
map = isl_map_lexmin(map);
str = "{ [x] -> [5] : 6 <= x <= 8; "
"[x] -> [x] : x <= 5 or (9 <= x <= 10) }";
map2 = isl_map_read_from_str(ctx, str);
assert(isl_map_is_equal(map, map2));
isl_map_free(map);
isl_map_free(map2);
for (i = 0; i < ARRAY_SIZE(lexmin_tests); ++i) {
map = isl_map_read_from_str(ctx, lexmin_tests[i].map);
map = isl_map_lexmin(map);
map2 = isl_map_read_from_str(ctx, lexmin_tests[i].lexmin);
equal = isl_map_is_equal(map, map2);
isl_map_free(map);
isl_map_free(map2);
str = "{ [x] -> [y] : 4y = x or 4y = -1 + x or 4y = -2 + x }";
map = isl_map_read_from_str(ctx, str);
map2 = isl_map_copy(map);
map = isl_map_lexmin(map);
assert(isl_map_is_equal(map, map2));
isl_map_free(map);
isl_map_free(map2);
str = "{ [x] -> [y] : x = 4y; [x] -> [y] : x = 2y }";
map = isl_map_read_from_str(ctx, str);
map = isl_map_lexmin(map);
str = "{ [x] -> [y] : (4y = x and x >= 0) or "
"(exists (e0 = [(x)/4], e1 = [(-2 + x)/4]: 2y = x and "
"4e1 = -2 + x and 4e0 <= -1 + x and 4e0 >= -3 + x)) or "
"(exists (e0 = [(x)/4]: 2y = x and 4e0 = x and x <= -4)) }";
map2 = isl_map_read_from_str(ctx, str);
assert(isl_map_is_equal(map, map2));
isl_map_free(map);
isl_map_free(map2);
if (equal < 0)
return -1;
if (!equal)
isl_die(ctx, isl_error_unknown,
"unexpected result", return -1);
}
str = "{ [i] -> [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and "
" 8i' <= i and 8i' >= -7 + i }";
@ -2306,29 +2333,6 @@ static int test_lexmin(struct isl_ctx *ctx)
isl_map_free(map);
isl_map_free(map2);
str = "{ T[a] -> S[b, c] : a = 4b-2c and c >= b }";
map = isl_map_read_from_str(ctx, str);
map = isl_map_lexmin(map);
str = "{ T[a] -> S[b, c] : 2b = a and 2c = a }";
map2 = isl_map_read_from_str(ctx, str);
assert(isl_map_is_equal(map, map2));
isl_map_free(map);
isl_map_free(map2);
/* Check that empty pieces are properly combined. */
str = "[K, N] -> { [x, y] -> [a, b] : K+2<=N<=K+4 and x>=4 and "
"2N-6<=x<K+N and N-1<=a<=K+N-1 and N+b-6<=a<=2N-4 and "
"b<=2N-3K+a and 3b<=4N-K+1 and b>=N and a>=x+1 }";
map = isl_map_read_from_str(ctx, str);
map = isl_map_lexmin(map);
str = "[K, N] -> { [x, y] -> [1 + x, N] : x >= -6 + 2N and "
"x <= -5 + 2N and x >= -1 + 3K - N and x <= -2 + K + N and "
"x >= 4 }";
map2 = isl_map_read_from_str(ctx, str);
assert(isl_map_is_equal(map, map2));
isl_map_free(map);
isl_map_free(map2);
str = "[i] -> { [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and "
" 8i' <= i and 8i' >= -7 + i }";
set = isl_set_read_from_str(ctx, str);
@ -5519,7 +5523,7 @@ static int test_ast(isl_ctx *ctx)
expr = isl_ast_expr_neg(expr);
expr2 = isl_ast_expr_neg(expr2);
equal = isl_ast_expr_is_equal(expr, expr2);
str = isl_ast_expr_to_str(expr);
str = isl_ast_expr_to_C_str(expr);
ok = str ? !strcmp(str, "-(A + B)") : -1;
free(str);
isl_ast_expr_free(expr);
@ -5539,7 +5543,7 @@ static int test_ast(isl_ctx *ctx)
expr = isl_ast_expr_add(expr1, expr2);
expr3 = isl_ast_expr_from_id(isl_id_alloc(ctx, "C", NULL));
expr = isl_ast_expr_sub(expr3, expr);
str = isl_ast_expr_to_str(expr);
str = isl_ast_expr_to_C_str(expr);
ok = str ? !strcmp(str, "C - (A + B)") : -1;
free(str);
isl_ast_expr_free(expr);

View File

@ -94,30 +94,43 @@ static struct isl_basic_set *to_parameter_domain(struct isl_basic_set *context)
return context;
}
isl_basic_set *plug_in_parameters(isl_basic_set *bset, struct isl_vec *params)
/* Plug in the initial values of "params" for the parameters in "bset" and
* return the result. The remaining entries in "params", if any,
* correspond to the existentially quantified variables in the description
* of the original context and can be ignored.
*/
static __isl_give isl_basic_set *plug_in_parameters(
__isl_take isl_basic_set *bset, __isl_take isl_vec *params)
{
int i;
int i, n;
for (i = 0; i < params->size - 1; ++i)
n = isl_basic_set_dim(bset, isl_dim_param);
for (i = 0; i < n; ++i)
bset = isl_basic_set_fix(bset,
isl_dim_param, i, params->el[1 + i]);
bset = isl_basic_set_remove_dims(bset,
isl_dim_param, 0, params->size - 1);
bset = isl_basic_set_remove_dims(bset, isl_dim_param, 0, n);
isl_vec_free(params);
return bset;
}
isl_set *set_plug_in_parameters(isl_set *set, struct isl_vec *params)
/* Plug in the initial values of "params" for the parameters in "set" and
* return the result. The remaining entries in "params", if any,
* correspond to the existentially quantified variables in the description
* of the original context and can be ignored.
*/
static __isl_give isl_set *set_plug_in_parameters(__isl_take isl_set *set,
__isl_take isl_vec *params)
{
int i;
int i, n;
for (i = 0; i < params->size - 1; ++i)
n = isl_set_dim(set, isl_dim_param);
for (i = 0; i < n; ++i)
set = isl_set_fix(set, isl_dim_param, i, params->el[1 + i]);
set = isl_set_remove_dims(set, isl_dim_param, 0, params->size - 1);
set = isl_set_remove_dims(set, isl_dim_param, 0, n);
isl_vec_free(params);
@ -128,10 +141,11 @@ isl_set *set_plug_in_parameters(isl_set *set, struct isl_vec *params)
* element of bset for the given values of the parameters, by
* successively solving an ilp problem in each direction.
*/
struct isl_vec *opt_at(struct isl_basic_set *bset,
struct isl_vec *params, int max)
static __isl_give isl_vec *opt_at(__isl_take isl_basic_set *bset,
__isl_take isl_vec *params, int max)
{
unsigned dim;
isl_ctx *ctx;
struct isl_vec *opt;
struct isl_vec *obj;
int i;
@ -140,16 +154,17 @@ struct isl_vec *opt_at(struct isl_basic_set *bset,
bset = plug_in_parameters(bset, params);
ctx = isl_basic_set_get_ctx(bset);
if (isl_basic_set_plain_is_empty(bset)) {
opt = isl_vec_alloc(bset->ctx, 0);
opt = isl_vec_alloc(ctx, 0);
isl_basic_set_free(bset);
return opt;
}
opt = isl_vec_alloc(bset->ctx, 1 + dim);
opt = isl_vec_alloc(ctx, 1 + dim);
assert(opt);
obj = isl_vec_alloc(bset->ctx, 1 + dim);
obj = isl_vec_alloc(ctx, 1 + dim);
assert(obj);
isl_int_set_si(opt->el[0], 1);
@ -174,7 +189,7 @@ struct isl_vec *opt_at(struct isl_basic_set *bset,
return opt;
empty:
isl_vec_free(opt);
opt = isl_vec_alloc(bset->ctx, 0);
opt = isl_vec_alloc(ctx, 0);
isl_basic_set_free(bset);
isl_vec_free(obj);

View File

@ -9,6 +9,8 @@ PIP_TESTS="\
esced.pip \
ex2.pip \
ex.pip \
exist.pip \
exist2.pip \
fimmel.pip \
max.pip \
negative.pip \

View File

@ -100,7 +100,7 @@
#include <print_templ.c>
#undef BASE
#define BASE ast_expr
#include <print_templ.c>
#include <print_templ_yaml.c>
#undef BASE
#define BASE ast_node
#include <print_templ.c>
#include <print_templ_yaml.c>

View File

@ -0,0 +1,39 @@
#define xCAT(A,B) A ## B
#define CAT(A,B) xCAT(A,B)
#undef TYPE
#define TYPE CAT(isl_,BASE)
#define xFN(TYPE,NAME) TYPE ## _ ## NAME
#define FN(TYPE,NAME) xFN(TYPE,NAME)
void FN(TYPE,dump)(__isl_keep TYPE *obj)
{
isl_printer *p;
if (!obj)
return;
p = isl_printer_to_file(FN(TYPE,get_ctx)(obj), stderr);
p = isl_printer_set_yaml_style(p, ISL_YAML_STYLE_BLOCK);
p = FN(isl_printer_print,BASE)(p, obj);
isl_printer_free(p);
}
/* Return a string representation of "obj".
* Print the object in flow format.
*/
__isl_give char *FN(TYPE,to_str)(__isl_keep TYPE *obj)
{
isl_printer *p;
char *s;
if (!obj)
return NULL;
p = isl_printer_to_str(FN(TYPE,get_ctx)(obj));
p = isl_printer_set_yaml_style(p, ISL_YAML_STYLE_FLOW);
p = FN(isl_printer_print,BASE)(p, obj);
s = isl_printer_get_str(p);
isl_printer_free(p);
return s;
}

View File

@ -0,0 +1,3 @@
if (P >= Q + 1 || Q >= P + 1)
for (int c0 = 0; c0 < N; c0 += 1)
S(c0);

View File

@ -0,0 +1,4 @@
# Check that the loop is generated only once with an outer disjunctive condition
domain: "[N, Q, P] -> { S[i0] : 0 <= i0 < N and (P > Q or P < Q) }"
child:
schedule: "[N, Q, P] -> [{ S[i0] -> [(i0)] }]"

View File

@ -0,0 +1,5 @@
[n] -> { : n mod 2 = 0 }
-1
[n] -> { [i] : n <= i }

View File

@ -0,0 +1,5 @@
[n, a, b] -> { : exists e : 1 <= a <= 7e and 9e <= b <= n }
-1
[n, a, b] -> { [i] : n <= 2i }