[Polly] Update ISL to isl-0.25-193-g8621c60c.

The bugfix https://reviews.llvm.org/D142308 might already have been
fixed upstream.
This commit is contained in:
Michael Kruse
2023-01-25 09:56:22 -06:00
parent eebb2e31b4
commit a749e09e18
172 changed files with 11102 additions and 5926 deletions

View File

@@ -254,6 +254,8 @@ if (POLLY_BUNDLED_ISL)
isl/isl_schedule_read.c
isl/isl_schedule_tree.c
isl/isl_scheduler.c
isl/isl_scheduler_clustering.c
isl/isl_scheduler_scc.c
isl/isl_seq.c
isl/isl_set_list.c
isl/isl_set_to_ast_graft_list.c

View File

@@ -23,17 +23,22 @@ isl was written by
Domaine de Voluceau - Rocquencourt, B.P. 105
78153 Le Chesnay
France
2015-2020 Polly Labs
2018-2020 Cerebras Systems
2015-2022 Polly Labs
2018-2021 Cerebras Systems
175 S San Antonio Rd
Los Altos, CA
USA
2021-2022 Cerebras Systems
1237 E Arques Ave
Sunnyvale, CA
USA
Contributions by
Mythri Alle
Riyadh Baghdadi
Serge Belyshev
Basile Clement
Albert Cohen
Ray Donnelly
Johannes Doerfert
@@ -49,6 +54,7 @@ Michael Kruse
Manjunath Kudlur
Alexander Matz
Chielo Newctle
Riccardo Mori
Sebastian Pop
Louis-Noel Pouchet
Benoit Pradelle
@@ -59,6 +65,7 @@ Malhar Thakkar
Sergei Trofimovich
Miheer Vaidya
Sven van Haastregt
Matt Whitlock
Oleksandr Zinenko
The merge sort implementation was written by Jeffrey Stedfast.

View File

@@ -1,3 +1,10 @@
version: 0.25
date: Sat 02 Jul 2022 11:14:57 AM CEST
changes:
- support (type safe) user object on id in bindings
- more exports to (templated C++) bindings
- add some convenience functions
---
version: 0.24
date: Sun 25 Apr 2021 03:56:37 PM CEST
changes:

View File

@@ -1 +1 @@
isl-0.24-69-g54aac5ac
isl-0.25-193-g8621c60c

View File

@@ -1,4 +1,5 @@
#include <isl/id.h>
#include <isl/id_to_id.h>
#include <isl/space.h>
#include <isl/val.h>
#include <isl/aff.h>

View File

@@ -155,8 +155,7 @@ struct isl_tab *isl_tab_compute_reduced_basis(struct isl_tab *tab)
GBR_lp_get_obj_val(lp, &F_new);
fixed = GBR_lp_is_fixed(lp);
GBR_set_ui(alpha, 0);
} else
if (use_saved) {
} else if (use_saved) {
row = GBR_lp_next_row(lp);
GBR_set(F_new, F_saved);
fixed = fixed_saved;

View File

@@ -17,6 +17,11 @@
#include <string>
#include <type_traits>
#if __cplusplus >= 201703L
#include <any>
#include <optional>
#endif
namespace isl {
namespace checked {
@@ -95,18 +100,23 @@ inline boolean manage(isl_bool val) {
}
class ctx {
isl_ctx *ptr;
isl_ctx *ptr;
public:
/* implicit */ ctx(isl_ctx *ctx)
: ptr(ctx) {}
isl_ctx *release() {
auto tmp = ptr;
ptr = nullptr;
return tmp;
}
isl_ctx *get() {
return ptr;
}
/* implicit */ ctx(isl_ctx *ctx) : ptr(ctx) {}
isl_ctx *release() {
auto tmp = ptr;
ptr = nullptr;
return tmp;
}
isl_ctx *get() {
return ptr;
}
#if __cplusplus >= 201703L
static void free_user(void *user) {
std::any *p = static_cast<std::any *>(user);
delete p;
}
#endif
};
/* Class encapsulating an isl_stat value.

View File

@@ -18,6 +18,11 @@
#include <string>
#include <type_traits>
#if __cplusplus >= 201703L
#include <any>
#include <optional>
#endif
/* ISL_USE_EXCEPTIONS should be defined to 1 if exceptions are available.
* gcc and clang define __cpp_exceptions; MSVC and xlC define _CPPUNWIND.
* Older versions of gcc (e.g., 4.9) only define __EXCEPTIONS.
@@ -46,6 +51,12 @@ public:
isl_ctx *get() {
return ptr;
}
#if __cplusplus >= 201703L
static void free_user(void *user) {
std::any *p = static_cast<std::any *>(user);
delete p;
}
#endif
};
/* Macros hiding try/catch.

View File

@@ -198,7 +198,7 @@
@misc{barvinok-0.22,
author = {Sven Verdoolaege},
title = {{\texttt{barvinok}}, version 0.22},
howpublished = {Available from \url{http://barvinok.gforge.inria.fr/}},
howpublished = {Available from \url{https://barvinok.sourceforge.io/}},
year = 2006
}
@@ -437,7 +437,7 @@ their correctness.
year = 2014,
month = Jan,
address = {Vienna, Austria},
url = {http://impact.gforge.inria.fr/impact2014/papers/impact2014-verdoolaege.pdf},
url = {https://acohen.gitlabpages.inria.fr/impact/impact2014/papers/impact2014-verdoolaege.pdf},
abstract = {
Schedules in the polyhedral model, both those that represent the original
execution order and those produced by scheduling algorithms, naturally have the

View File

@@ -343,7 +343,7 @@ under the MIT license.
The source of C<isl> can be obtained either as a tarball
or from the git repository. Both are available from
L<http://isl.gforge.inria.fr/>.
L<https://libisl.sourceforge.io/>.
The installation process depends on how you obtained
the source.
@@ -422,11 +422,11 @@ for values out of the 32 bit range. In most applications, C<isl> will run
fastest with the C<imath-32> option, followed by C<gmp> and C<imath>, the
slowest.
=item C<--with-gmp-prefix>
=item C<--with-gmp-prefix=>I<path>
Installation prefix for C<GMP> (architecture-independent files).
=item C<--with-gmp-exec-prefix>
=item C<--with-gmp-exec-prefix=>I<path>
Installation prefix for C<GMP> (architecture-dependent files).
@@ -436,12 +436,47 @@ Installation prefix for C<GMP> (architecture-dependent files).
make
=item 4 Install (optional)
=item 4 Test (optional)
make check
=item 5 Install (optional)
make install
=back
=head2 Building the foreign language bindings
The tarball already contains the generated foreign language bindings,
but they are not included in the git repository.
Building the C++ and Python bindings relies on the LLVM/clang libraries,
see C<http://clang.llvm.org/get_started.html>.
The C<configure> script will not assume that these are available
on the system.
To enable building the foreign language bindings,
one of the following options needs to be specified.
=over
=item C<--with-clang=system>
Use the system clang libraries (installed in a default location).
=item C<--with-clang-prefix=>I<path>
Use the system clang libraries installed in I<path>.
=back
It is best to use the latest release of the clang libraries (14.0),
although any release since 2.9 should work as well.
Note that if you build the clang libraries from source,
then you need to make sure they are also installed (using C<make install>).
If the compiler that was used to compile the clang libraries
is different from the default C++ compiler, then use C<CXX_FOR_BUILD>
to specify this non-default C++ compiler when running C<isl>'s C<./configure>.
=head1 Integer Set Library
=head2 Memory Management
@@ -971,6 +1006,8 @@ using the following functions.
__isl_give isl_id *isl_id_set_free_user(
__isl_take isl_id *id,
void (*free_user)(void *user));
void (*isl_id_get_free_user(__isl_keep isl_id *id))
(void *user);
__isl_give isl_id *isl_id_copy(isl_id *id);
__isl_null isl_id *isl_id_free(__isl_take isl_id *id);
@@ -982,6 +1019,7 @@ using the following functions.
The callback set by C<isl_id_set_free_user> is called on the user
pointer when the last reference to the C<isl_id> is freed.
This callback can be retrieved using C<isl_id_get_free_user>.
Note that C<isl_id_get_name> returns a pointer to some internal
data structure, so the result can only be used while the
corresponding C<isl_id> is alive.
@@ -3739,6 +3777,9 @@ then create a piecewise expression over a given domain.
__isl_give isl_pw_aff *isl_pw_aff_val_on_domain(
__isl_take isl_set *domain,
__isl_take isl_val *v);
__isl_give isl_pw_aff *isl_set_pw_aff_on_domain_val(
__isl_take isl_set *domain,
__isl_take isl_val *v);
__isl_give isl_pw_multi_aff *
isl_pw_multi_aff_multi_val_on_domain(
__isl_take isl_set *domain,
@@ -3750,9 +3791,17 @@ then create a piecewise expression over a given domain.
__isl_give isl_pw_aff *isl_pw_aff_param_on_domain_id(
__isl_take isl_set *domain,
__isl_take isl_id *id);
__isl_give isl_pw_aff *isl_set_param_pw_aff_on_domain_id(
__isl_take isl_set *domain,
__isl_take isl_id *id);
C<isl_set_pw_multi_aff_on_domain_multi_val> is an alternative name
for C<isl_pw_multi_aff_multi_val_on_domain>.
C<isl_set_pw_aff_on_domain_val> is an alternative name
for C<isl_pw_aff_val_on_domain>.
Similarly for the pair
C<isl_set_pw_multi_aff_on_domain_multi_val> and
C<isl_pw_multi_aff_multi_val_on_domain> and
for the pair C<isl_set_param_pw_aff_on_domain_id> and
C<isl_pw_aff_param_on_domain_id>.
As a convenience, a piecewise multiple expression can
also be created from a piecewise expression.
@@ -4300,6 +4349,10 @@ Objects can be read from input using the following functions.
__isl_give isl_multi_val *isl_multi_val_read_from_str(
isl_ctx *ctx, const char *str);
#include <isl/space.h>
__isl_give isl_space *isl_space_read_from_str(
isl_ctx *ctx, const char *str);
#include <isl/set.h>
__isl_give isl_basic_set *isl_basic_set_read_from_file(
isl_ctx *ctx, FILE *input);
@@ -4435,6 +4488,9 @@ To actually print something, use
#include <isl/val.h>
__isl_give isl_printer *isl_printer_print_val(
__isl_take isl_printer *p, __isl_keep isl_val *v);
__isl_give isl_printer *isl_printer_print_multi_val(
__isl_take isl_printer *p,
__isl_keep isl_multi_val *mv);
#include <isl/set.h>
__isl_give isl_printer *isl_printer_print_basic_set(
@@ -4462,11 +4518,6 @@ To actually print something, use
__isl_take isl_printer *p,
__isl_keep isl_union_map *umap);
#include <isl/val.h>
__isl_give isl_printer *isl_printer_print_multi_val(
__isl_take isl_printer *p,
__isl_keep isl_multi_val *mv);
#include <isl/id.h>
__isl_give isl_printer *isl_printer_print_multi_id(
__isl_take isl_printer *p,
@@ -4801,6 +4852,8 @@ can be found then assign C<1> to C<*modulo> and C<1> to C<*residue>.
__isl_keep isl_set *set, int pos);
__isl_give isl_val *isl_set_get_stride(
__isl_keep isl_set *set, int pos);
__isl_give isl_fixed_box *isl_set_get_lattice_tile(
__isl_keep isl_set *set);
#include <isl/map.h>
__isl_give isl_stride_info *
@@ -4831,6 +4884,8 @@ can be extracted from the returned
C<isl_fixed_box> using the functions described under "Box hull" in
L</"Unary Operations">. Note that the C<isl_fixed_box> object returned by
C<isl_map_get_range_lattice_tile> is always valid.
The function C<isl_set_get_lattice_tile> collects the same stride
information over all set dimensions.
For the other functions,
the stride and offset can be extracted from the returned object
using the following functions.
@@ -5484,6 +5539,18 @@ in the domain of the input function.
__isl_take isl_space *space);
__isl_give isl_space *isl_space_params(
__isl_take isl_space *space);
__isl_give isl_space *
isl_space_domain_wrapped_domain(
__isl_take isl_space *space);
__isl_give isl_space *
isl_space_domain_wrapped_range(
__isl_take isl_space *space);
__isl_give isl_space *
isl_space_range_wrapped_domain(
__isl_take isl_space *space);
__isl_give isl_space *
isl_space_range_wrapped_range(
__isl_take isl_space *space);
#include <isl/local_space.h>
__isl_give isl_local_space *isl_local_space_domain(
@@ -5514,6 +5581,8 @@ in the domain of the input function.
__isl_take isl_basic_set *bset);
__isl_give isl_set *isl_set_params(__isl_take isl_set *set);
The function C<isl_space_domain_wrapped_domain> returns the domain
of the binary relation wrapped inside the domain of the input.
The function C<isl_set_project_onto_map> returns a relation
that projects the input set onto the given set dimensions.
@@ -5521,6 +5590,12 @@ that projects the input set onto the given set dimensions.
__isl_give isl_basic_map *isl_basic_map_project_out(
__isl_take isl_basic_map *bmap,
enum isl_dim_type type, unsigned first, unsigned n);
__isl_give isl_map *isl_map_project_out_param_id(
__isl_take isl_map *map,
__isl_take isl_id *id);
__isl_give isl_map *isl_map_project_out_param_id_list(
__isl_take isl_map *map,
__isl_take isl_id_list *list);
__isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
enum isl_dim_type type, unsigned first, unsigned n);
__isl_give isl_map *isl_map_project_out_all_params(
@@ -5550,6 +5625,14 @@ The function C<isl_union_set_project_out> can only project out
parameters.
#include <isl/union_map.h>
__isl_give isl_union_map *
isl_union_map_project_out_param_id(
__isl_take isl_union_map *umap,
__isl_take isl_id *id);
__isl_give isl_union_map *
isl_union_map_project_out_param_id_list(
__isl_take isl_union_map *umap,
__isl_take isl_id_list *list);
__isl_give isl_union_map *isl_union_map_project_out(
__isl_take isl_union_map *umap,
enum isl_dim_type type, unsigned first, unsigned n);
@@ -6527,6 +6610,10 @@ there is one, negative infinity or infinity if the problem is unbounded and
NaN if the problem is empty.
#include <isl/ilp.h>
__isl_give isl_val *isl_pw_aff_min_val(
__isl_take isl_pw_aff *pa);
__isl_give isl_val *isl_pw_aff_max_val(
__isl_take isl_pw_aff *pa);
__isl_give isl_multi_val *
isl_pw_multi_aff_min_multi_val(
__isl_take isl_pw_multi_aff *pma);
@@ -7361,6 +7448,14 @@ the same (number of) parameters.
isl_map_intersect_range_factor_range(
__isl_take isl_map *map,
__isl_take isl_map *factor);
__isl_give isl_map *
isl_map_intersect_domain_wrapped_domain(
__isl_take isl_map *map,
__isl_take isl_set *domain);
__isl_give isl_map *
isl_map_intersect_range_wrapped_domain(
__isl_take isl_map *map,
__isl_take isl_set *domain);
#include <isl/union_set.h>
__isl_give isl_union_set *isl_union_set_intersect_params(
@@ -7415,6 +7510,14 @@ the same (number of) parameters.
isl_union_map_intersect_range_factor_range(
__isl_take isl_union_map *umap,
__isl_take isl_union_map *factor);
__isl_give isl_union_map *
isl_union_map_intersect_domain_wrapped_domain_union_set(
__isl_take isl_union_map *umap,
__isl_take isl_union_set *domain);
__isl_give isl_union_map *
isl_union_map_intersect_range_wrapped_domain_union_set(
__isl_take isl_union_map *umap,
__isl_take isl_union_set *domain);
#include <isl/aff.h>
__isl_give isl_pw_aff *isl_pw_aff_intersect_domain(
@@ -9053,6 +9156,10 @@ only defined on the shared definition domain of the arguments.
isl_multi_aff_scale_down_multi_val(
__isl_take isl_multi_aff *ma,
__isl_take isl_multi_val *mv);
__isl_give isl_pw_multi_aff *
isl_pw_multi_aff_scale_down_multi_val(
__isl_take isl_pw_multi_aff *pma,
__isl_take isl_multi_val *mv);
__isl_give isl_multi_pw_aff *
isl_multi_pw_aff_scale_down_multi_val(
__isl_take isl_multi_pw_aff *mpa,
@@ -9331,6 +9438,9 @@ Lists can be created, copied, modified and freed using the following functions.
unsigned pos1, unsigned pos2);
__isl_give isl_set_list *isl_set_list_reverse(
__isl_take isl_set_list *list);
__isl_give isl_set_list *isl_set_list_set_at(
__isl_take isl_set_list *list, int index,
__isl_take isl_set *set);
__isl_give isl_set_list *isl_set_list_set_set(
__isl_take isl_set_list *list, int index,
__isl_take isl_set *set);
@@ -9358,6 +9468,7 @@ C<isl_set_list_from_set> performs the same operation.
C<isl_set_list_clear> removes all elements from a list.
C<isl_set_list_swap> swaps the elements at the specified locations.
C<isl_set_list_reverse> reverses the elements in the list.
C<isl_set_list_set_set> is an alternative name for C<isl_set_list_set_at>.
Lists can be inspected using the following functions.
@@ -9493,6 +9604,11 @@ Associative arrays can be inspected using the following functions.
isl_stat (*fn)(__isl_take isl_id *key,
__isl_take isl_ast_expr *val, void *user),
void *user);
isl_bool isl_id_to_ast_expr_every(
__isl_keep isl_id_to_ast_expr *id2expr,
isl_bool (*test)(__isl_keep isl_id *key,
__isl_keep isl_ast_expr *val, void *user),
void *user);
The function C<isl_id_to_ast_expr_try_get> returns a structure
containing two elements, C<valid> and C<value>.
@@ -9516,12 +9632,33 @@ Associative arrays can be modified using the following functions.
__isl_take isl_id_to_ast_expr *id2expr,
__isl_take isl_id *key);
Associative arrays can be printed using the following function.
Associative arrays can be checked for (obvious) equality
using the following function.
#include <isl/id_to_ast_expr.h>
isl_bool isl_id_to_ast_expr_is_equal(
__isl_take isl_id_to_ast_expr *id2expr1,
__isl_take isl_id_to_ast_expr *id2expr2);
Note that depending on how the keys and values are being compared,
for other types of keys and/or values, this function may be called
C<plain_is_equal> rather than C<is_equal>.
Associative arrays can be printed using the following functions.
#include <isl/id_to_ast_expr.h>
__isl_give isl_printer *isl_printer_print_id_to_ast_expr(
__isl_take isl_printer *p,
__isl_keep isl_id_to_ast_expr *id2expr);
__isl_give char *isl_id_to_ast_expr_to_str(
__isl_keep isl_id_to_ast_expr *id2expr);
They can be read from input using the following function.
#include <isl/id_to_ast_expr.h>
__isl_give isl_id_to_ast_expr *
isl_id_to_ast_expr_read_from_str(isl_ctx *ctx,
const char *str);
=head2 Vectors
@@ -10089,6 +10226,9 @@ exists.
__isl_keep isl_schedule_node *node);
__isl_give isl_schedule_node *isl_schedule_node_parent(
__isl_take isl_schedule_node *node);
__isl_give isl_schedule_node *
isl_schedule_node_grandparent(
__isl_take isl_schedule_node *node);
__isl_give isl_schedule_node *isl_schedule_node_root(
__isl_take isl_schedule_node *node);
__isl_give isl_schedule_node *isl_schedule_node_ancestor(
@@ -10100,6 +10240,10 @@ exists.
__isl_take isl_schedule_node *node, int pos);
isl_bool isl_schedule_node_has_children(
__isl_keep isl_schedule_node *node);
__isl_give isl_schedule_node *
isl_schedule_node_grandchild(
__isl_take isl_schedule_node *node,
int pos1, int pos2);
__isl_give isl_schedule_node *isl_schedule_node_first_child(
__isl_take isl_schedule_node *node);
isl_bool isl_schedule_node_has_previous_sibling(
@@ -10541,19 +10685,26 @@ introduced expansion node. Grouping instances of different statements
ensures that they will be treated as a single statement by the
AST generator up to the point of the expansion node.
The following function can be used to flatten a nested
The following functions can be used to flatten a nested
sequence.
#include <isl/schedule_node.h>
__isl_give isl_schedule_node *
isl_schedule_node_sequence_splice_child(
__isl_take isl_schedule_node *node, int pos);
__isl_give isl_schedule_node *
isl_schedule_node_sequence_splice_children(
__isl_take isl_schedule_node *node);
That is, given a sequence node C<node> that has another sequence node
in its child at position C<pos> (in particular, the child of that filter
node is a sequence node), attach the children of that other sequence
node is a sequence node), the function
C<isl_schedule_node_sequence_splice_child>
attaches the children of that other sequence
node as children of C<node>, replacing the original child at position
C<pos>.
C<isl_schedule_node_sequence_splice_children> does this for all
such children.
The partial schedule of a band node can be scaled (down) or reduced using
the following functions.
@@ -11747,6 +11898,10 @@ A member access.
This operation has two arguments, a structure and the name of
the member of the structure being accessed.
=item C<isl_ast_expr_op_address_of>
The address of its single argument, which is always an array access.
=back
#include <isl/ast.h>
@@ -11922,6 +12077,18 @@ subexpressions of C<expr> of type C<isl_ast_expr_id>
by the corresponding expression in C<id2expr>, if there is any.
The following function can be used to modify the descendants
of a specific node in an AST using a depth-first post-order
traversal of those descendants (including the node itself).
#include <isl/ast.h>
__isl_give isl_ast_node *
isl_ast_node_map_descendant_bottom_up(
__isl_take isl_ast_node *node,
__isl_give isl_ast_node *(*fn)(
__isl_take isl_ast_node *node,
void *user), void *user);
User specified data can be attached to an C<isl_ast_node> and obtained
from the same C<isl_ast_node> using the following functions.
@@ -12693,9 +12860,22 @@ AST generation or a
user defined node created using the following function.
#include <isl/ast.h>
__isl_give isl_ast_node *isl_ast_node_user_from_expr(
__isl_take isl_ast_expr *expr);
__isl_give isl_ast_node *isl_ast_node_alloc_user(
__isl_take isl_ast_expr *expr);
C<isl_ast_node_alloc_user> is an alternative name for
C<isl_ast_node_user_from_expr>.
In some cases, a single user defined node is not enough,
in which case the following function can be used
to create a block node from multiple AST nodes.
#include <isl/ast.h>
__isl_give isl_ast_node *isl_ast_node_block_from_children(
__isl_take isl_ast_node_list *list);
#include <isl/ast_build.h>
__isl_give isl_ast_build *
isl_ast_build_set_at_each_domain(

View File

@@ -13,17 +13,17 @@
* Return KEY_ERROR on error, i.e., if "tok" does not
* correspond to any known key.
*/
static KEY extract_key(__isl_keep isl_stream *s, struct isl_token *tok)
static KEY KEY_EXTRACT(__isl_keep isl_stream *s, struct isl_token *tok)
{
int type;
isl_bool has_string;
char *name;
KEY key;
isl_ctx *ctx;
if (!tok)
has_string = isl_token_has_str(tok);
if (has_string < 0)
return KEY_ERROR;
type = isl_token_get_type(tok);
if (type != ISL_TOKEN_IDENT && type != ISL_TOKEN_STRING) {
if (!has_string) {
isl_stream_error(s, tok, "expecting key");
return KEY_ERROR;
}
@@ -34,7 +34,7 @@ static KEY extract_key(__isl_keep isl_stream *s, struct isl_token *tok)
return KEY_ERROR;
for (key = 0; key < KEY_END; ++key) {
if (!strcmp(name, key_str[key]))
if (KEY_STR[key] && !strcmp(name, KEY_STR[key]))
break;
}
free(name);
@@ -49,13 +49,13 @@ static KEY extract_key(__isl_keep isl_stream *s, struct isl_token *tok)
* Return KEY_ERROR on error, i.e., if the first token
* on the stream does not correspond to any known key.
*/
static KEY get_key(__isl_keep isl_stream *s)
static KEY KEY_GET(__isl_keep isl_stream *s)
{
struct isl_token *tok;
KEY key;
tok = isl_stream_next_token(s);
key = extract_key(s, tok);
key = KEY_EXTRACT(s, tok);
isl_token_free(tok);
return key;

View File

@@ -59,7 +59,7 @@ static FILE *open_or_die(const char *filename)
*/
int main(int argc, char **argv)
{
int more;
isl_bool more;
isl_ctx *ctx;
struct options *options;
FILE *input1, *input2;
@@ -77,15 +77,15 @@ int main(int argc, char **argv)
s1 = isl_stream_new_file(ctx, input1);
s2 = isl_stream_new_file(ctx, input2);
if (isl_stream_yaml_read_start_mapping(s1))
if (isl_stream_yaml_read_start_mapping(s1) < 0)
isl_die(ctx, isl_error_unknown, "arg1 not a YAML mapping",
return EXIT_FAILURE);
if (isl_stream_yaml_read_start_mapping(s2))
if (isl_stream_yaml_read_start_mapping(s2) < 0)
isl_die(ctx, isl_error_unknown, "arg2 not a YAML mapping",
return EXIT_FAILURE);
while ((more = isl_stream_yaml_next(s1)) > 0) {
int more2;
while ((more = isl_stream_yaml_next(s1)) == isl_bool_true) {
isl_bool more2;
isl_bool equal;
isl_union_map *umap1, *umap2;
@@ -121,14 +121,10 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
if (isl_stream_yaml_read_end_mapping(s1) < 0) {
isl_stream_error(s1, NULL, "unexpected extra elements");
if (isl_stream_yaml_read_end_mapping(s1) < 0)
return EXIT_FAILURE;
}
if (isl_stream_yaml_read_end_mapping(s2) < 0) {
isl_stream_error(s2, NULL, "unexpected extra elements");
if (isl_stream_yaml_read_end_mapping(s2) < 0)
return EXIT_FAILURE;
}
isl_stream_free(s1);
isl_stream_free(s2);

View File

@@ -153,6 +153,7 @@ __isl_give isl_aff *isl_aff_align_params(__isl_take isl_aff *aff,
__isl_export
__isl_give isl_aff *isl_aff_gist(__isl_take isl_aff *aff,
__isl_take isl_set *context);
__isl_export
__isl_give isl_aff *isl_aff_gist_params(__isl_take isl_aff *aff,
__isl_take isl_set *context);
@@ -230,8 +231,14 @@ __isl_give isl_pw_aff *isl_pw_aff_nan_on_domain(__isl_take isl_local_space *ls);
__isl_give isl_pw_aff *isl_pw_aff_val_on_domain(__isl_take isl_set *domain,
__isl_take isl_val *v);
__isl_overload
__isl_give isl_pw_aff *isl_set_pw_aff_on_domain_val(__isl_take isl_set *domain,
__isl_take isl_val *v);
__isl_overload
__isl_give isl_pw_aff *isl_pw_aff_param_on_domain_id(
__isl_take isl_set *domain, __isl_take isl_id *id);
__isl_overload
__isl_give isl_pw_aff *isl_set_param_pw_aff_on_domain_id(
__isl_take isl_set *domain, __isl_take isl_id *id);
__isl_export
__isl_give isl_pw_aff *isl_set_indicator_function(__isl_take isl_set *set);
@@ -379,6 +386,7 @@ __isl_give isl_pw_aff *isl_pw_aff_coalesce(__isl_take isl_pw_aff *pa);
__isl_export
__isl_give isl_pw_aff *isl_pw_aff_gist(__isl_take isl_pw_aff *pwaff,
__isl_take isl_set *context);
__isl_export
__isl_give isl_pw_aff *isl_pw_aff_gist_params(__isl_take isl_pw_aff *pwaff,
__isl_take isl_set *context);
@@ -529,6 +537,7 @@ __isl_give isl_multi_val *isl_multi_aff_get_constant_multi_val(
__isl_export
__isl_give isl_multi_aff *isl_multi_aff_floor(__isl_take isl_multi_aff *ma);
__isl_export
__isl_give isl_multi_aff *isl_multi_aff_gist_params(
__isl_take isl_multi_aff *maff, __isl_take isl_set *context);
__isl_export
@@ -738,8 +747,12 @@ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_val(
__isl_overload
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_down_val(
__isl_take isl_pw_multi_aff *pma, __isl_take isl_val *v);
__isl_overload
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_multi_val(
__isl_take isl_pw_multi_aff *pma, __isl_take isl_multi_val *mv);
__isl_overload
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_down_multi_val(
__isl_take isl_pw_multi_aff *pma, __isl_take isl_multi_val *mv);
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_lexmin(
__isl_take isl_pw_multi_aff *pma1,
@@ -795,6 +808,7 @@ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_drop_unused_params(
__isl_export
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_coalesce(
__isl_take isl_pw_multi_aff *pma);
__isl_export
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_gist_params(
__isl_take isl_pw_multi_aff *pma, __isl_take isl_set *set);
__isl_export

View File

@@ -103,6 +103,9 @@ __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_constructor
__isl_give isl_ast_node *isl_ast_node_user_from_expr(
__isl_take 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);
__isl_null isl_ast_node *isl_ast_node_free(__isl_take isl_ast_node *node);
@@ -150,6 +153,9 @@ __isl_give isl_ast_node *isl_ast_node_if_get_else_node(
__isl_give isl_ast_node *isl_ast_node_if_get_else(
__isl_keep isl_ast_node *node);
__isl_constructor
__isl_give isl_ast_node *isl_ast_node_block_from_children(
__isl_take isl_ast_node_list *list);
__isl_export
__isl_give isl_ast_node_list *isl_ast_node_block_get_children(
__isl_keep isl_ast_node *node);
@@ -167,6 +173,10 @@ __isl_give isl_ast_expr *isl_ast_node_user_get_expr(
isl_stat isl_ast_node_foreach_descendant_top_down(
__isl_keep isl_ast_node *node,
isl_bool (*fn)(__isl_keep isl_ast_node *node, void *user), void *user);
__isl_export
__isl_give isl_ast_node *isl_ast_node_map_descendant_bottom_up(
__isl_take isl_ast_node *node, __isl_give isl_ast_node *(*fn)(
__isl_take isl_ast_node *node, void *user), void *user);
__isl_give isl_printer *isl_printer_print_ast_node(__isl_take isl_printer *p,
__isl_keep isl_ast_node *node);

View File

@@ -67,6 +67,8 @@ struct isl_hash_table_entry *isl_hash_table_find(struct isl_ctx *ctx,
const void *val, int reserve);
isl_stat isl_hash_table_foreach(isl_ctx *ctx, struct isl_hash_table *table,
isl_stat (*fn)(void **entry, void *user), void *user);
isl_bool isl_hash_table_every(isl_ctx *ctx, struct isl_hash_table *table,
isl_bool (*test)(void **entry, void *user), void *user);
void isl_hash_table_remove(struct isl_ctx *ctx,
struct isl_hash_table *table,
struct isl_hash_table_entry *entry);

View File

@@ -11,9 +11,10 @@ extern "C" {
#define ISL_xFN(TYPE,NAME) TYPE ## _ ## NAME
#define ISL_FN(TYPE,NAME) ISL_xFN(TYPE,NAME)
struct ISL_HMAP;
struct __isl_export ISL_HMAP;
typedef struct ISL_HMAP ISL_HMAP;
__isl_constructor
__isl_give ISL_HMAP *ISL_FN(ISL_HMAP,alloc)(isl_ctx *ctx, int min_size);
__isl_give ISL_HMAP *ISL_FN(ISL_HMAP,copy)(__isl_keep ISL_HMAP *hmap);
__isl_null ISL_HMAP *ISL_FN(ISL_HMAP,free)(__isl_take ISL_HMAP *hmap);
@@ -26,6 +27,7 @@ isl_bool ISL_FN(ISL_HMAP,has)(__isl_keep ISL_HMAP *hmap,
__isl_keep ISL_KEY *key);
__isl_give ISL_VAL *ISL_FN(ISL_HMAP,get)(__isl_keep ISL_HMAP *hmap,
__isl_take ISL_KEY *key);
__isl_export
__isl_give ISL_HMAP *ISL_FN(ISL_HMAP,set)(__isl_take ISL_HMAP *hmap,
__isl_take ISL_KEY *key, __isl_take ISL_VAL *val);
__isl_give ISL_HMAP *ISL_FN(ISL_HMAP,drop)(__isl_take ISL_HMAP *hmap,
@@ -35,7 +37,23 @@ isl_stat ISL_FN(ISL_HMAP,foreach)(__isl_keep ISL_HMAP *hmap,
isl_stat (*fn)(__isl_take ISL_KEY *key, __isl_take ISL_VAL *val,
void *user),
void *user);
isl_bool ISL_FN(ISL_HMAP,every)(__isl_keep ISL_HMAP *hmap,
isl_bool (*test)(__isl_keep ISL_KEY *key, __isl_keep ISL_VAL *val,
void *user),
void *user);
#ifdef ISL_HMAP_IS_EQUAL
__isl_export
isl_bool ISL_HMAP_IS_EQUAL(__isl_keep ISL_HMAP *hmap1,
__isl_keep ISL_HMAP *hmap2);
#endif
#ifdef ISL_HMAP_HAVE_READ_FROM_STR
__isl_constructor
__isl_give ISL_HMAP *ISL_FN(ISL_HMAP,read_from_str)(isl_ctx *ctx,
const char *str);
#endif
__isl_give char *ISL_FN(ISL_HMAP,to_str)(__isl_keep ISL_HMAP *hmap);
__isl_give isl_printer *ISL_FN(isl_printer_print,ISL_HMAP_SUFFIX)(
__isl_take isl_printer *p, __isl_keep ISL_HMAP *hmap);
void ISL_FN(ISL_HMAP,dump)(__isl_keep ISL_HMAP *hmap);

View File

@@ -12,6 +12,7 @@
#include <isl/ctx.h>
#include <isl/hash.h>
#include <isl/stream.h>
#define ISL_xCAT(A,B) A ## B
#define ISL_CAT(A,B) ISL_xCAT(A,B)
@@ -322,7 +323,7 @@ error:
return ISL_FN(ISL_HMAP,free)(hmap);
}
/* Internal data structure for isl_map_to_basic_set_foreach.
/* Internal data structure for isl_*_to_*_foreach.
*
* fn is the function that should be called on each entry.
* user is the user-specified final argument to fn.
@@ -360,6 +361,83 @@ isl_stat ISL_FN(ISL_HMAP,foreach)(__isl_keep ISL_HMAP *hmap,
&call_on_copy, &data);
}
/* Internal data structure for isl_*_to_*_every.
*
* "test" is the function that should be called on each entry,
* until any invocation returns isl_bool_false.
* "test_user" is the user-specified final argument to "test".
*/
ISL_S(every_data) {
isl_bool (*test)(__isl_keep ISL_KEY *key, __isl_keep ISL_VAL *val,
void *user);
void *test_user;
};
/* Call data->test on the key and value in *entry.
*/
static isl_bool call_on_pair(void **entry, void *user)
{
ISL_S(pair) *pair = *entry;
ISL_S(every_data) *data = (ISL_S(every_data) *) user;
return data->test(pair->key, pair->val, data->test_user);
}
/* Does "test" succeed on every entry of "hmap"?
*/
isl_bool ISL_FN(ISL_HMAP,every)(__isl_keep ISL_HMAP *hmap,
isl_bool (*test)(__isl_keep ISL_KEY *key, __isl_keep ISL_VAL *val,
void *user),
void *user)
{
ISL_S(every_data) data = { test, user };
if (!hmap)
return isl_bool_error;
return isl_hash_table_every(hmap->ctx, &hmap->table,
&call_on_pair, &data);
}
#ifdef ISL_HMAP_IS_EQUAL
/* Does "hmap" have an entry with key "key" and value "val"?
*/
static isl_bool has_entry(__isl_keep ISL_KEY *key, __isl_keep ISL_VAL *val,
void *user)
{
ISL_HMAP *hmap = user;
ISL_MAYBE(ISL_VAL) maybe_val;
isl_bool equal;
maybe_val = ISL_FN(ISL_HMAP,try_get)(hmap, key);
if (maybe_val.valid < 0 || !maybe_val.valid)
return maybe_val.valid;
equal = ISL_VAL_IS_EQUAL(maybe_val.value, val);
ISL_FN(ISL_VAL,free)(maybe_val.value);
return equal;
}
/* Is "hmap1" (obviously) equal to "hmap2"?
*
* In particular, do the two associative arrays have
* the same number of entries and does every entry of the first
* also appear in the second?
*/
isl_bool ISL_HMAP_IS_EQUAL(__isl_keep ISL_HMAP *hmap1,
__isl_keep ISL_HMAP *hmap2)
{
if (!hmap1 || !hmap2)
return isl_bool_error;
if (hmap1 == hmap2)
return isl_bool_true;
if (hmap1->table.n != hmap2->table.n)
return isl_bool_false;
return ISL_FN(ISL_HMAP,every)(hmap1, &has_entry, hmap2);
}
#endif
/* Internal data structure for print_pair.
*
* p is the printer on which the associative array is being printed.
@@ -423,3 +501,83 @@ void ISL_FN(ISL_HMAP,dump)(__isl_keep ISL_HMAP *hmap)
isl_printer_free(printer);
}
/* Return a string representation of "hmap".
*/
__isl_give char *ISL_FN(ISL_HMAP,to_str)(__isl_keep ISL_HMAP *hmap)
{
isl_printer *p;
char *s;
if (!hmap)
return NULL;
p = isl_printer_to_str(ISL_FN(ISL_HMAP,get_ctx)(hmap));
p = ISL_FN(isl_printer_print,ISL_HMAP_SUFFIX)(p, hmap);
s = isl_printer_get_str(p);
isl_printer_free(p);
return s;
}
#ifdef ISL_HMAP_HAVE_READ_FROM_STR
/* Read an associative array from "s".
* The input format corresponds to the way associative arrays are printed
* by isl_printer_print_*_to_*.
* In particular, each key-value pair is separated by a colon,
* the key-value pairs are separated by a comma and
* the entire associative array is surrounded by braces.
*/
__isl_give ISL_HMAP *ISL_FN(isl_stream_read,ISL_HMAP_SUFFIX)(isl_stream *s)
{
isl_ctx *ctx;
ISL_HMAP *hmap;
if (!s)
return NULL;
ctx = isl_stream_get_ctx(s);
hmap = ISL_FN(ISL_HMAP,alloc)(ctx, 0);
if (!hmap)
return NULL;
if (isl_stream_eat(s, '{') < 0)
return ISL_FN(ISL_HMAP,free)(hmap);
if (isl_stream_eat_if_available(s, '}'))
return hmap;
do {
ISL_KEY *key;
ISL_VAL *val = NULL;
key = ISL_KEY_READ(s);
if (isl_stream_eat(s, ':') >= 0)
val = ISL_VAL_READ(s);
hmap = ISL_FN(ISL_HMAP,set)(hmap, key, val);
if (!hmap)
return NULL;
} while (isl_stream_eat_if_available(s, ','));
if (isl_stream_eat(s, '}') < 0)
return ISL_FN(ISL_HMAP,free)(hmap);
return hmap;
}
/* Read an associative array from the string "str".
* The input format corresponds to the way associative arrays are printed
* by isl_printer_print_*_to_*.
* In particular, each key-value pair is separated by a colon,
* the key-value pairs are separated by a comma and
* the entire associative array is surrounded by braces.
*/
__isl_give ISL_HMAP *ISL_FN(ISL_HMAP,read_from_str)(isl_ctx *ctx,
const char *str)
{
ISL_HMAP *hmap;
isl_stream *s;
s = isl_stream_new_str(ctx, str);
if (!s)
return NULL;
hmap = ISL_FN(isl_stream_read,ISL_HMAP_SUFFIX)(s);
isl_stream_free(s);
return hmap;
}
#endif

View File

@@ -31,6 +31,7 @@ __isl_keep const char *isl_id_get_name(__isl_keep isl_id *id);
__isl_give isl_id *isl_id_set_free_user(__isl_take isl_id *id,
void (*free_user)(void *user));
void (*isl_id_get_free_user(__isl_keep isl_id *id))(void *user);
__isl_constructor
__isl_give isl_id *isl_id_read_from_str(isl_ctx *ctx, const char *str);

View File

@@ -9,10 +9,14 @@
#define ISL_VAL isl_ast_expr
#define ISL_HMAP_SUFFIX id_to_ast_expr
#define ISL_HMAP isl_id_to_ast_expr
#define ISL_HMAP_HAVE_READ_FROM_STR
#define ISL_HMAP_IS_EQUAL isl_id_to_ast_expr_is_equal
#include <isl/hmap.h>
#undef ISL_KEY
#undef ISL_VAL
#undef ISL_HMAP_SUFFIX
#undef ISL_HMAP
#undef ISL_HMAP_HAVE_READ_FROM_STR
#undef ISL_HMAP_IS_EQUAL
#endif

View File

@@ -8,10 +8,14 @@
#define ISL_VAL isl_id
#define ISL_HMAP_SUFFIX id_to_id
#define ISL_HMAP isl_id_to_id
#define ISL_HMAP_HAVE_READ_FROM_STR
#define ISL_HMAP_IS_EQUAL isl_id_to_id_is_equal
#include <isl/hmap.h>
#undef ISL_KEY
#undef ISL_VAL
#undef ISL_HMAP_SUFFIX
#undef ISL_HMAP
#undef ISL_HMAP_HAVE_READ_FROM_STR
#undef ISL_HMAP_IS_EQUAL
#endif

View File

@@ -9,10 +9,14 @@
#define ISL_VAL isl_pw_aff
#define ISL_HMAP_SUFFIX id_to_pw_aff
#define ISL_HMAP isl_id_to_pw_aff
#define ISL_HMAP_HAVE_READ_FROM_STR
#define ISL_HMAP_IS_EQUAL isl_id_to_pw_aff_plain_is_equal
#include <isl/hmap.h>
#undef ISL_KEY
#undef ISL_VAL
#undef ISL_HMAP_SUFFIX
#undef ISL_HMAP
#undef ISL_HMAP_HAVE_READ_FROM_STR
#undef ISL_HMAP_IS_EQUAL
#endif

View File

@@ -31,6 +31,10 @@ __isl_give isl_val *isl_set_max_val(__isl_keep isl_set *set,
__isl_give isl_multi_val *isl_union_set_min_multi_union_pw_aff(
__isl_keep isl_union_set *uset, __isl_keep isl_multi_union_pw_aff *obj);
__isl_export
__isl_give isl_val *isl_pw_aff_min_val(__isl_take isl_pw_aff *pa);
__isl_export
__isl_give isl_val *isl_pw_aff_max_val(__isl_take isl_pw_aff *pa);
__isl_export
__isl_give isl_multi_val *isl_pw_multi_aff_min_multi_val(
__isl_take isl_pw_multi_aff *pma);

View File

@@ -69,6 +69,10 @@ __isl_give isl_##EL *isl_##EL##_list_get_at( \
__isl_keep isl_##EL##_list *list, int index); \
__isl_give struct isl_##EL *isl_##EL##_list_get_##EL( \
__isl_keep isl_##EL##_list *list, int index); \
EXPORT \
__isl_give isl_##EL##_list *isl_##EL##_list_set_at( \
__isl_take isl_##EL##_list *list, int index, \
__isl_take isl_##EL *el); \
__isl_give struct isl_##EL##_list *isl_##EL##_list_set_##EL( \
__isl_take struct isl_##EL##_list *list, int index, \
__isl_take struct isl_##EL *el); \
@@ -89,9 +93,10 @@ __isl_give isl_##EL##_list *isl_##EL##_list_sort( \
int (*cmp)(__isl_keep struct isl_##EL *a, \
__isl_keep struct isl_##EL *b, \
void *user), void *user); \
EXPORT \
isl_stat isl_##EL##_list_foreach_scc(__isl_keep isl_##EL##_list *list, \
isl_bool (*follows)(__isl_keep struct isl_##EL *a, \
__isl_keep struct isl_##EL *b, void *user), \
isl_bool (*follows)(__isl_keep isl_##EL *a, \
__isl_keep isl_##EL *b, void *user), \
void *follows_user, \
isl_stat (*fn)(__isl_take isl_##EL##_list *scc, void *user), \
void *fn_user); \

View File

@@ -354,6 +354,12 @@ __isl_export
__isl_give isl_map *isl_map_intersect_range_factor_range(
__isl_take isl_map *map, __isl_take isl_map *factor);
__isl_export
__isl_give isl_map *isl_map_intersect_domain_wrapped_domain(
__isl_take isl_map *map, __isl_take isl_set *domain);
__isl_export
__isl_give isl_map *isl_map_intersect_range_wrapped_domain(
__isl_take isl_map *map, __isl_take isl_set *domain);
__isl_export
__isl_give isl_map *isl_map_apply_domain(
__isl_take isl_map *map1,
__isl_take isl_map *map2);
@@ -479,6 +485,12 @@ __isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
__isl_give isl_basic_map *isl_basic_map_project_out(
__isl_take isl_basic_map *bmap,
enum isl_dim_type type, unsigned first, unsigned n);
__isl_overload
__isl_give isl_map *isl_map_project_out_param_id(__isl_take isl_map *map,
__isl_take isl_id *id);
__isl_overload
__isl_give isl_map *isl_map_project_out_param_id_list(__isl_take isl_map *map,
__isl_take isl_id_list *list);
__isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
enum isl_dim_type type, unsigned first, unsigned n);
__isl_export
@@ -676,6 +688,7 @@ __isl_give isl_map *isl_map_gist_domain(__isl_take isl_map *map,
__isl_take isl_set *context);
__isl_give isl_map *isl_map_gist_range(__isl_take isl_map *map,
__isl_take isl_set *context);
__isl_export
__isl_give isl_map *isl_map_gist_params(__isl_take isl_map *map,
__isl_take isl_set *context);
__isl_give isl_map *isl_map_gist_basic_map(__isl_take isl_map *map,
@@ -706,6 +719,7 @@ isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map,
__isl_give isl_basic_map_list *isl_map_get_basic_map_list(
__isl_keep isl_map *map);
__isl_overload
__isl_give isl_map *isl_map_fixed_power_val(__isl_take isl_map *map,
__isl_take isl_val *exp);
__isl_give isl_map *isl_map_power(__isl_take isl_map *map, isl_bool *exact);

View File

@@ -9,10 +9,14 @@
#define ISL_VAL isl_basic_set
#define ISL_HMAP_SUFFIX map_to_basic_set
#define ISL_HMAP isl_map_to_basic_set
#define ISL_HMAP_HAVE_READ_FROM_STR
#define ISL_HMAP_IS_EQUAL isl_map_to_basic_set_plain_is_equal
#include <isl/hmap.h>
#undef ISL_KEY
#undef ISL_VAL
#undef ISL_HMAP_SUFFIX
#undef ISL_HMAP
#undef ISL_HMAP_HAVE_READ_FROM_STR
#undef ISL_HMAP_IS_EQUAL
#endif

View File

@@ -1,6 +1,9 @@
#ifndef ISL_POLYNOMIAL_TYPE_H
#define ISL_POLYNOMIAL_TYPE_H
#include <isl/ctx.h>
#include <isl/list.h>
struct isl_qpolynomial;
typedef struct isl_qpolynomial isl_qpolynomial;

View File

@@ -8,6 +8,7 @@
#include <isl/val_type.h>
#include <isl/space_type.h>
#include <isl/id_type.h>
#include <isl/set_type.h>
#if defined(__cplusplus)
extern "C" {
@@ -91,12 +92,16 @@ __isl_give isl_schedule_node *isl_schedule_node_root(
__isl_export
__isl_give isl_schedule_node *isl_schedule_node_parent(
__isl_take isl_schedule_node *node);
__isl_give isl_schedule_node *isl_schedule_node_grandparent(
__isl_take isl_schedule_node *node);
__isl_export
__isl_give isl_schedule_node *isl_schedule_node_ancestor(
__isl_take isl_schedule_node *node, int generation);
__isl_export
__isl_give isl_schedule_node *isl_schedule_node_child(
__isl_take isl_schedule_node *node, int pos);
__isl_give isl_schedule_node *isl_schedule_node_grandchild(
__isl_take isl_schedule_node *node, int pos1, int pos2);
__isl_export
__isl_give isl_schedule_node *isl_schedule_node_first_child(
__isl_take isl_schedule_node *node);
@@ -116,6 +121,8 @@ __isl_give isl_schedule_node *isl_schedule_node_group(
__isl_give isl_schedule_node *isl_schedule_node_sequence_splice_child(
__isl_take isl_schedule_node *node, int pos);
__isl_give isl_schedule_node *isl_schedule_node_sequence_splice_children(
__isl_take isl_schedule_node *node);
__isl_give isl_space *isl_schedule_node_band_get_space(
__isl_keep isl_schedule_node *node);

View File

@@ -488,6 +488,7 @@ __isl_give isl_set *isl_set_gist_basic_set(__isl_take isl_set *set,
__isl_export
__isl_give isl_set *isl_set_gist(__isl_take isl_set *set,
__isl_take isl_set *context);
__isl_export
__isl_give isl_set *isl_set_gist_params(__isl_take isl_set *set,
__isl_take isl_set *context);
isl_stat isl_set_dim_residue_class_val(__isl_keep isl_set *set,
@@ -498,6 +499,8 @@ __isl_give isl_stride_info *isl_set_get_stride_info(__isl_keep isl_set *set,
__isl_export
__isl_give isl_val *isl_set_get_stride(__isl_keep isl_set *set, int pos);
__isl_export
__isl_give isl_fixed_box *isl_set_get_lattice_tile(__isl_keep isl_set *set);
__isl_export
__isl_give isl_fixed_box *isl_set_get_simple_fixed_box_hull(
__isl_keep isl_set *set);

View File

@@ -119,6 +119,14 @@ __isl_give isl_space *isl_space_range_factor_domain(
__isl_take isl_space *space);
__isl_give isl_space *isl_space_range_factor_range(
__isl_take isl_space *space);
__isl_give isl_space *isl_space_domain_wrapped_domain(
__isl_take isl_space *space);
__isl_give isl_space *isl_space_domain_wrapped_range(
__isl_take isl_space *space);
__isl_give isl_space *isl_space_range_wrapped_domain(
__isl_take isl_space *space);
__isl_give isl_space *isl_space_range_wrapped_range(
__isl_take isl_space *space);
__isl_export
__isl_give isl_space *isl_space_map_from_set(__isl_take isl_space *space);
__isl_give isl_space *isl_space_map_from_domain_and_range(
@@ -205,6 +213,9 @@ __isl_give isl_space *isl_space_flatten_domain(__isl_take isl_space *space);
__isl_export
__isl_give isl_space *isl_space_flatten_range(__isl_take isl_space *space);
__isl_constructor
__isl_give isl_space *isl_space_read_from_str(isl_ctx *ctx,
const char *str);
__isl_give char *isl_space_to_str(__isl_keep isl_space *space);
__isl_give isl_printer *isl_printer_print_space(__isl_take isl_printer *p,
__isl_keep isl_space *space);

View File

@@ -44,6 +44,7 @@ enum isl_token_type { ISL_TOKEN_ERROR = -1,
struct isl_token;
__isl_give isl_val *isl_token_get_val(isl_ctx *ctx, struct isl_token *tok);
isl_bool isl_token_has_str(struct isl_token *tok);
__isl_give char *isl_token_get_str(isl_ctx *ctx, struct isl_token *tok);
int isl_token_get_type(struct isl_token *tok);
void isl_token_free(struct isl_token *tok);
@@ -75,21 +76,23 @@ enum isl_token_type isl_stream_register_keyword(__isl_keep isl_stream *s,
const char *name);
struct isl_obj isl_stream_read_obj(__isl_keep isl_stream *s);
__isl_give isl_id *isl_stream_read_id(__isl_keep isl_stream *s);
__isl_give isl_val *isl_stream_read_val(__isl_keep isl_stream *s);
__isl_give isl_multi_aff *isl_stream_read_multi_aff(__isl_keep isl_stream *s);
__isl_give isl_map *isl_stream_read_map(__isl_keep isl_stream *s);
__isl_give isl_set *isl_stream_read_set(__isl_keep isl_stream *s);
__isl_give isl_basic_set *isl_stream_read_basic_set(__isl_keep isl_stream *s);
__isl_give isl_pw_qpolynomial *isl_stream_read_pw_qpolynomial(
__isl_keep isl_stream *s);
__isl_give isl_union_set *isl_stream_read_union_set(__isl_keep isl_stream *s);
__isl_give isl_union_map *isl_stream_read_union_map(__isl_keep isl_stream *s);
__isl_give isl_schedule *isl_stream_read_schedule(isl_stream *s);
int isl_stream_yaml_read_start_mapping(__isl_keep isl_stream *s);
int isl_stream_yaml_read_end_mapping(__isl_keep isl_stream *s);
int isl_stream_yaml_read_start_sequence(__isl_keep isl_stream *s);
int isl_stream_yaml_read_end_sequence(__isl_keep isl_stream *s);
int isl_stream_yaml_next(__isl_keep isl_stream *s);
isl_stat isl_stream_yaml_read_start_mapping(__isl_keep isl_stream *s);
isl_stat isl_stream_yaml_read_end_mapping(__isl_keep isl_stream *s);
isl_stat isl_stream_yaml_read_start_sequence(__isl_keep isl_stream *s);
isl_stat isl_stream_yaml_read_end_sequence(__isl_keep isl_stream *s);
isl_bool isl_stream_yaml_next(__isl_keep isl_stream *s);
#if defined(__cplusplus)
}

View File

@@ -5,7 +5,7 @@
#ifndef ISL_STRIDE_INFO_H
#define ISL_STRIDE_INFO_H
#include <isl/val.h>
#include <isl/val_type.h>
#include <isl/aff_type.h>
#if defined(__cplusplus)

View File

@@ -178,6 +178,14 @@ __isl_give isl_union_map *isl_union_map_intersect_range_factor_domain(
__isl_export
__isl_give isl_union_map *isl_union_map_intersect_range_factor_range(
__isl_take isl_union_map *umap, __isl_take isl_union_map *factor);
__isl_overload
__isl_give isl_union_map *
isl_union_map_intersect_domain_wrapped_domain_union_set(
__isl_take isl_union_map *umap, __isl_take isl_union_set *domain);
__isl_overload
__isl_give isl_union_map *
isl_union_map_intersect_range_wrapped_domain_union_set(
__isl_take isl_union_map *umap, __isl_take isl_union_set *domain);
__isl_export
__isl_give isl_union_map *isl_union_map_subtract_domain(
@@ -234,6 +242,12 @@ __isl_give isl_union_map *isl_union_map_deltas_map(
__isl_export
__isl_give isl_union_map *isl_union_set_identity(__isl_take isl_union_set *uset);
__isl_overload
__isl_give isl_union_map *isl_union_map_project_out_param_id(
__isl_take isl_union_map *umap, __isl_take isl_id *id);
__isl_overload
__isl_give isl_union_map *isl_union_map_project_out_param_id_list(
__isl_take isl_union_map *umap, __isl_take isl_id_list *list);
__isl_give isl_union_map *isl_union_map_project_out(
__isl_take isl_union_map *umap,
enum isl_dim_type type, unsigned first, unsigned n);

View File

@@ -20,7 +20,7 @@ OBJEXT="$BUILD_OBJEXT"
AX_CXX_COMPILE_STDCXX_11_NO_OVERRIDE
AC_DISABLE_SHARED
AC_PROG_LIBTOOL
LT_INIT
AX_DETECT_CLANG

View File

@@ -649,11 +649,11 @@ void cpp_generator::class_printer::print_method_header(
else
os << cppstring;
method.print_cpp_arg_list(os, [&] (int i) {
method.print_cpp_arg_list(os, [&] (int i, int arg) {
std::string name = method.fd->getParamDecl(i)->getName().str();
ParmVarDecl *param = method.get_param(i);
QualType type = param->getOriginalType();
string cpptype = type_printer.param(i, type);
string cpptype = type_printer.param(arg, type);
if (!method.param_needs_copy(i))
os << "const " << cpptype << " &" << name;
@@ -928,6 +928,24 @@ bool cpp_generator::is_implicit_conversion(const Method &cons)
return false;
}
/* Construct a list combiner for printing a list.
*/
Method::list_combiner Method::print_combiner(std::ostream &os)
{
return {
[&] () { os << "("; },
[&] () { os << ", "; },
[&] () { os << ")"; }
};
}
/* Construct a list combiner for simply iterating over a list.
*/
Method::list_combiner Method::empty_combiner()
{
return { [&] () { }, [&] () { }, [&] () { } };
}
/* Get kind of "method" in "clazz".
*
* Given the declaration of a static or member method, returns its kind.
@@ -942,20 +960,20 @@ static Method::Kind get_kind(const isl_class &clazz, FunctionDecl *method)
return Method::Kind::member_method;
}
/* Return the callback argument of "fd", if there is any.
* Return NULL otherwise.
/* Return the callback arguments of "fd".
*/
static ParmVarDecl *find_callback_arg(FunctionDecl *fd)
static std::vector<ParmVarDecl *> find_callback_args(FunctionDecl *fd)
{
std::vector<ParmVarDecl *> callbacks;
int num_params = fd->getNumParams();
for (int i = 0; i < num_params; ++i) {
ParmVarDecl *param = fd->getParamDecl(i);
if (generator::is_callback(param->getType()))
return param;
callbacks.emplace_back(param);
}
return NULL;
return callbacks;
}
/* Construct a C++ method object from the class to which is belongs,
@@ -968,7 +986,7 @@ Method::Method(const isl_class &clazz, FunctionDecl *fd,
const std::string &name) :
clazz(clazz), fd(fd), name(rename_method(name)),
kind(get_kind(clazz, fd)),
callback(find_callback_arg(fd))
callbacks(find_callback_args(fd))
{
}
@@ -985,19 +1003,13 @@ Method::Method(const isl_class &clazz, FunctionDecl *fd) :
/* Return the number of parameters of the corresponding C function.
*
* If the method has a callback argument, we reduce the number of parameters
* that are exposed by one to hide the user pointer from the interface. On
* the C++ side no user pointer is needed, as arguments can be forwarded
* as part of the std::function argument which specifies the callback function.
*
* The user pointer is also removed from the number of parameters
* of the C function because the pair of callback and user pointer
* is considered as a single argument that is printed as a whole
* by Method::print_param_use.
* This number includes any possible user pointers that follow callback
* arguments. These are skipped by Method::print_fd_arg_list
* during the actual argument printing.
*/
int Method::c_num_params() const
{
return fd->getNumParams() - (callback != NULL);
return fd->getNumParams();
}
/* Return the number of parameters of the method
@@ -1011,30 +1023,128 @@ int Method::num_params() const
return c_num_params();
}
/* Call "on_arg_skip_next" on the arguments from "start" (inclusive)
* to "end" (exclusive), calling the methods of "combiner"
* before, between and after the arguments.
* If "on_arg_skip_next" returns true then the next argument is skipped.
*/
void Method::on_arg_list(int start, int end,
const Method::list_combiner &combiner,
const std::function<bool(int i)> &on_arg_skip_next)
{
combiner.before();
for (int i = start; i < end; ++i) {
if (i != start)
combiner.between();
if (on_arg_skip_next(i))
++i;
}
combiner.after();
}
/* Print the arguments from "start" (inclusive) to "end" (exclusive)
* as arguments to a method of C function call, using "print_arg_skip_next"
* to print each individual argument. If this callback return true
* then the next argument is skipped.
*/
void Method::print_arg_list(std::ostream &os, int start, int end,
const std::function<bool(int i)> &print_arg_skip_next)
{
on_arg_list(start, end, print_combiner(os), [&] (int i) {
return print_arg_skip_next(i);
});
}
/* Call "on_arg" on the arguments from "start" (inclusive) to "end" (exclusive),
* calling the methods of "combiner" before, between and after the arguments.
* The first argument to "on_arg" is the position of the argument
* in this->fd.
* The second argument is the (first) position in the list of arguments
* with all callback arguments spliced in.
*
* Call on_arg_list to do the actual iteration over the arguments, skipping
* the user argument that comes after every callback argument.
* On the C++ side no user pointer is needed, as arguments can be forwarded
* as part of the std::function argument which specifies the callback function.
* The user pointer is also removed from the number of parameters
* of the C function because the pair of callback and user pointer
* is considered as a single argument that is printed as a whole
* by Method::print_param_use.
*
* In case of a callback argument, the second argument to "print_arg"
* is also adjusted to account for the spliced-in arguments of the callback.
* The return value takes the place of the callback itself,
* while the arguments (excluding the final user pointer)
* take the following positions.
*/
void Method::on_fd_arg_list(int start, int end,
const Method::list_combiner &combiner,
const std::function<void(int i, int arg)> &on_arg) const
{
int arg = start;
on_arg_list(start, end, combiner, [this, &on_arg, &arg] (int i) {
auto type = fd->getParamDecl(i)->getType();
on_arg(i, arg++);
if (!generator::is_callback(type))
return false;
arg += generator::prototype_n_args(type) - 1;
return true;
});
}
/* Print the arguments from "start" (inclusive) to "end" (exclusive)
* as arguments to a method of C function call, using "print_arg"
* to print each individual argument.
* The first argument to this callback is the position of the argument
* in this->fd.
* The second argument is the (first) position in the list of arguments
* with all callback arguments spliced in.
*/
void Method::print_arg_list(std::ostream &os, int start, int end,
const std::function<void(int i)> &print_arg)
void Method::print_fd_arg_list(std::ostream &os, int start, int end,
const std::function<void(int i, int arg)> &print_arg) const
{
os << "(";
for (int i = start; i < end; ++i) {
if (i != start)
os << ", ";
print_arg(i);
}
os << ")";
on_fd_arg_list(start, end, print_combiner(os), print_arg);
}
/* Call "on_arg" on the arguments to the method call,
* calling the methods of "combiner" before, between and after the arguments.
* The first argument to "on_arg" is the position of the argument
* in this->fd.
* The second argument is the (first) position in the list of arguments
* with all callback arguments spliced in.
*/
void Method::on_cpp_arg_list(const Method::list_combiner &combiner,
const std::function<void(int i, int arg)> &on_arg) const
{
int first_param = kind == member_method ? 1 : 0;
on_fd_arg_list(first_param, num_params(), combiner, on_arg);
}
/* Call "on_arg" on the arguments to the method call.
* The first argument to "on_arg" is the position of the argument
* in this->fd.
* The second argument is the (first) position in the list of arguments
* with all callback arguments spliced in.
*/
void Method::on_cpp_arg_list(
const std::function<void(int i, int arg)> &on_arg) const
{
on_cpp_arg_list(empty_combiner(), on_arg);
}
/* Print the arguments to the method call, using "print_arg"
* to print each individual argument.
* The first argument to this callback is the position of the argument
* in this->fd.
* The second argument is the (first) position in the list of arguments
* with all callback arguments spliced in.
*/
void Method::print_cpp_arg_list(std::ostream &os,
const std::function<void(int i)> &print_arg) const
const std::function<void(int i, int arg)> &print_arg) const
{
int first_param = kind == member_method ? 1 : 0;
print_arg_list(os, first_param, num_params(), print_arg);
on_cpp_arg_list(print_combiner(os), print_arg);
}
/* Should the parameter at position "pos" be a copy (rather than

View File

@@ -14,7 +14,7 @@
* "name" is the name of the method, which may be different
* from the default name derived from "fd".
* "kind" is the type of the method.
* "callback" stores the callback argument, if any, or NULL.
* "callbacks" stores the callback arguments.
*/
struct Method {
enum Kind {
@@ -23,6 +23,10 @@ struct Method {
constructor,
};
struct list_combiner;
static list_combiner print_combiner(std::ostream &os);
static list_combiner empty_combiner();
Method(const isl_class &clazz, FunctionDecl *fd,
const std::string &name);
Method(const isl_class &clazz, FunctionDecl *fd);
@@ -33,16 +37,41 @@ struct Method {
virtual clang::ParmVarDecl *get_param(int pos) const;
virtual void print_param_use(ostream &os, int pos) const;
bool is_subclass_mutator() const;
static void on_arg_list(int start, int end,
const list_combiner &combiner,
const std::function<bool(int i)> &on_arg_skip_next);
static void print_arg_list(std::ostream &os, int start, int end,
const std::function<void(int i)> &print_arg);
const std::function<bool(int i)> &print_arg_skip_next);
void on_fd_arg_list(int start, int end,
const list_combiner &combiner,
const std::function<void(int i, int arg)> &on_arg) const;
void print_fd_arg_list(std::ostream &os, int start, int end,
const std::function<void(int i, int arg)> &print_arg) const;
void on_cpp_arg_list(const list_combiner &combiner,
const std::function<void(int i, int arg)> &on_arg) const;
void on_cpp_arg_list(
const std::function<void(int i, int arg)> &on_arg) const;
void print_cpp_arg_list(std::ostream &os,
const std::function<void(int i)> &print_arg) const;
const std::function<void(int i, int arg)> &print_arg) const;
const isl_class &clazz;
FunctionDecl *const fd;
const std::string name;
const enum Kind kind;
ParmVarDecl *const callback;
const std::vector<ParmVarDecl *> callbacks;
};
/* A data structure expressing how Method::on_arg_list should combine
* the arguments.
*
* In particular, "before" is called before any argument is handled;
* "between" is called between two arguments and
* "after" is called after all arguments have been handled.
*/
struct Method::list_combiner {
const std::function<void()> before;
const std::function<void()> between;
const std::function<void()> after;
};
/* A method that does not require its isl type parameters to be a copy.

View File

@@ -109,7 +109,7 @@ static llvm::cl::opt<string> OutputLanguage(llvm::cl::Required,
llvm::cl::value_desc("name"));
static const char *ResourceDir =
CLANG_PREFIX "/lib/clang/" CLANG_VERSION_MAJOR_STRING;
CLANG_PREFIX "/lib/clang/" CLANG_VERSION_STRING;
/* Does decl have an attribute of the following form?
*
@@ -428,7 +428,7 @@ static void set_lang_defaults(CompilerInstance *Clang)
PreprocessorOptions &PO = Clang->getPreprocessorOpts();
TargetOptions &TO = Clang->getTargetOpts();
llvm::Triple T(TO.Triple);
CompilerInvocation::setLangDefaults(Clang->getLangOpts(), IK_C, T,
SETLANGDEFAULTS::setLangDefaults(Clang->getLangOpts(), IK_C, T,
setLangDefaultsArg4(PO),
LangStandard::lang_unspecified);
}

View File

@@ -735,6 +735,16 @@ bool generator::is_callback(QualType type)
return type->isFunctionType();
}
/* Is the parameter at position "i" of "fd" a pointer to a function?
*/
bool generator::is_callback_arg(FunctionDecl *fd, int i)
{
ParmVarDecl *param = fd->getParamDecl(i);
QualType type = param->getOriginalType();
return is_callback(type);
}
/* Is "type" that of "char *" of "const char *"?
*/
bool generator::is_string(QualType type)
@@ -781,6 +791,14 @@ const FunctionProtoType *generator::extract_prototype(QualType type)
return type->getPointeeType()->getAs<FunctionProtoType>();
}
/* Given the type of a function pointer, return the number of arguments
* of the corresponding function prototype.
*/
int generator::prototype_n_args(QualType type)
{
return extract_prototype(type)->getNumArgs();
}
/* Return the function name suffix for the type of "param".
*
* If the type of "param" is an isl object type,

View File

@@ -190,11 +190,13 @@ public:
static bool is_isl_size(QualType type);
static bool is_long(QualType type);
static bool is_callback(QualType type);
static bool is_callback_arg(FunctionDecl *fd, int i);
static bool is_string(QualType type);
static bool is_static(const isl_class &clazz, FunctionDecl *method);
static bool is_mutator(const isl_class &clazz, FunctionDecl *fd);
static string extract_type(QualType type);
static const FunctionProtoType *extract_prototype(QualType type);
static int prototype_n_args(QualType type);
static ParmVarDecl *persistent_callback_arg(FunctionDecl *fd);
};

View File

@@ -261,17 +261,7 @@ void plain_cpp_generator::print_class(ostream &os, const isl_class &clazz)
printer.print_protected_constructors();
osprintf(os, "\n");
osprintf(os, "public:\n");
printer.print_public_constructors();
printer.print_constructors();
printer.print_copy_assignment();
printer.print_destructor();
printer.print_ptr();
printer.print_downcast();
printer.print_ctx();
osprintf(os, "\n");
printer.print_persistent_callbacks();
printer.print_methods();
printer.print_set_enums();
printer.print_public_methods();
osprintf(os, "};\n");
}
@@ -380,6 +370,23 @@ void plain_cpp_generator::decl_printer::print_method(const Method &method)
print_full_method_header(method);
}
/* Print a declaration for a constructor for the "id" class
* that takes a user object.
*/
void plain_cpp_generator::decl_printer::print_id_constructor_user()
{
print_id_constructor_user_header();
}
/* Print a declaration for an "id" method
* for retrieving the user object associated to the identifier.
* If "optional" is set, the method returns a std::optional user object.
*/
void plain_cpp_generator::decl_printer::print_id_user(bool optional)
{
print_id_user_header(optional);
}
/* Print declarations of copy assignment operator.
*
* Each class has one assignment operator.
@@ -515,6 +522,13 @@ void plain_cpp_generator::decl_printer::print_ctx()
osprintf(os, " inline %sctx ctx() const;\n", ns.c_str());
}
/* Print a separator between groups of method declarations.
*/
void plain_cpp_generator::decl_printer::print_method_separator()
{
os << "\n";
}
/* Add a space to the return type "type" if needed,
* i.e., if it is not the type of a pointer.
*/
@@ -648,17 +662,8 @@ void plain_cpp_generator::print_class_impl(ostream &os, const isl_class &clazz)
osprintf(os, "// implementations for isl::%s", cppname);
printer.print_class_factory();
printer.print_public_constructors();
printer.print_protected_constructors();
printer.print_constructors();
printer.print_copy_assignment();
printer.print_destructor();
printer.print_ptr();
printer.print_downcast();
printer.print_ctx();
printer.print_persistent_callbacks();
printer.print_methods();
printer.print_set_enums();
printer.print_public_methods();
printer.print_stream_insertion();
}
@@ -768,8 +773,7 @@ void plain_cpp_generator::impl_printer::print_check_ptr_start(const char *ptr)
return;
print_check_ptr(ptr);
osprintf(os, " auto saved_ctx = %s_get_ctx(%s);\n",
clazz.name.c_str(), ptr);
print_save_ctx(clazz.name + "_get_ctx(" + ptr + ")");
print_on_error_continue();
}
@@ -929,12 +933,12 @@ void plain_cpp_generator::impl_printer::print_method(const Method &method)
print_save_ctx(method);
print_on_error_continue();
if (method.callback)
print_callback_local(method.callback);
for (const auto &callback : method.callbacks)
print_callback_local(callback);
osprintf(os, " auto res = %s", methodname.c_str());
Method::print_arg_list(os, 0, num_params, [&] (int i) {
method.print_fd_arg_list(os, 0, num_params, [&] (int i, int arg) {
method.print_param_use(os, i);
});
osprintf(os, ";\n");
@@ -1002,7 +1006,7 @@ void plain_cpp_generator::impl_printer::print_method(
print_check_ptr("ptr");
osprintf(os, " return ");
method.print_call(os, generator.isl_namespace());
method.print_cpp_arg_list(os, [&] (int i) {
method.print_cpp_arg_list(os, [&] (int i, int arg) {
ParmVarDecl *param = method.fd->getParamDecl(i);
print_arg_conversion(param, method.get_param(i));
@@ -1011,6 +1015,82 @@ void plain_cpp_generator::impl_printer::print_method(
osprintf(os, "}\n");
}
/* Print a definition for a constructor for the "id" class
* that takes a user object.
*
* The user object is taken as a std::any and copied into
* a new std::any object on the heap.
* A pointer to this heap object is stored in the isl_id and
* is scheduled to be freed when the reference count of the isl_id
* drops to zero.
* If the allocation of the isl_id fails, then the heap object
* will not be freed automatically, so it needs to be freed manually.
*
* Unless checked C++ bindings are being generated,
* the ctx argument is copied into the save_ctx variable
* for use by print_throw_last_error, which throws an exception
* if the construction fails.
* During the function call, isl is made not to print any error message
* because the error message is included in the exception.
*/
void plain_cpp_generator::impl_printer::print_id_constructor_user()
{
print_id_constructor_user_header();
os << "{\n";
if (!generator.checked) {
print_save_ctx("ctx");
print_on_error_continue();
}
os << " std::any *p = new std::any(any);\n";
os << " auto res = isl_id_alloc(ctx.get(), str.c_str(), p);\n";
os << " res = isl_id_set_free_user(res, &ctx::free_user);\n";
os << " if (!res) {\n";
os << " delete p;\n";
if (!generator.checked)
print_throw_last_error(os);
os << " }\n";
os << " ptr = res;\n";
os << "}\n";
}
/* Print a definition for an "id" method
* for retrieving the user object associated to the identifier.
* If "optional" is set, the method returns a std::optional user object.
* The returned object is of a type specified by template parameter T.
*
* The isl_id needs to have been created by the constructor generated
* by print_id_constructor_user. That is, it needs to have a user pointer and
* it needs to have its free_user callback set to &ctx::free_user.
* The object stored in the std::any also needs to be of the required type.
*
* If "optional" is set, return a std::nullopt if any of the checks fail.
* Otherwise, throw an exception_invalid (or call isl_die and
* return a default T in the checked C++ bindings).
*/
void plain_cpp_generator::impl_printer::print_id_user(bool optional)
{
auto fail = [&] (const char *msg) {
if (optional)
os << " return std::nullopt;\n";
else
generator.print_invalid(os, 4, msg, "return T()");
};
os << "\n";
print_id_user_header(optional);
os << "{\n";
print_check_ptr("ptr");
os << " std::any *p = (std::any *) isl_id_get_user(ptr);\n";
os << " if (!p)\n";
fail("no user pointer");
os << " if (isl_id_get_free_user(ptr) != &ctx::free_user)\n";
fail("user pointer not attached by C++ interface");
os << " T *res = std::any_cast<T>(p);\n";
os << " if (!res)\n";
fail("user pointer not of given type");
os << " return *res;\n";
os << "}\n";
}
/* Print implementation of copy assignment operator.
*
* If the class has any persistent callbacks, then copy them
@@ -1171,6 +1251,14 @@ void plain_cpp_generator::impl_printer::print_ctx()
osprintf(os, "}\n");
}
/* Print a separator between groups of method definitions.
*
* No additional separator is required between method definitions.
*/
void plain_cpp_generator::impl_printer::print_method_separator()
{
}
/* Print the implementations of the methods needed for the persistent callbacks
* of the class.
*/
@@ -1272,6 +1360,13 @@ void plain_cpp_generator::impl_printer::print_argument_validity_check(
print_throw_NULL_input(os);
}
/* Print code for saving a copy of "ctx" in a "saved_ctx" variable.
*/
void plain_cpp_generator::impl_printer::print_save_ctx(const std::string &ctx)
{
os << " auto saved_ctx = " << ctx << ";\n";
}
/* Print code for saving a copy of the isl::ctx available at the start
* of the method "method" in a "saved_ctx" variable,
* for use in exception handling.
@@ -1292,17 +1387,10 @@ void plain_cpp_generator::impl_printer::print_save_ctx(const Method &method)
if (generator.checked)
return;
if (method.kind == Method::Kind::member_method) {
osprintf(os, " auto saved_ctx = ctx();\n");
return;
}
if (is_isl_ctx(type)) {
std::string name;
name = param->getName().str();
osprintf(os, " auto saved_ctx = %s;\n", name.c_str());
return;
}
if (method.kind == Method::Kind::member_method)
return print_save_ctx("ctx()");
if (is_isl_ctx(type))
return print_save_ctx(param->getName().str());
n = method.num_params();
for (int i = 0; i < n; ++i) {
ParmVarDecl *param = method.fd->getParamDecl(i);
@@ -1310,8 +1398,7 @@ void plain_cpp_generator::impl_printer::print_save_ctx(const Method &method)
if (!is_isl_type(type))
continue;
osprintf(os, " auto saved_ctx = %s.ctx();\n",
param->getName().str().c_str());
print_save_ctx(param->getName().str() + ".ctx()");
return;
}
}
@@ -1393,10 +1480,10 @@ void plain_cpp_generator::impl_printer::print_exceptional_execution_check(
print_persistent_callback_exceptional_execution_check(os, method);
if (method.callback) {
for (const auto &callback : method.callbacks) {
std::string name;
name = method.callback->getName().str();
name = callback->getName().str();
osprintf(os, " if (%s_data.eptr)\n", name.c_str());
osprintf(os, " std::rethrow_exception(%s_data.eptr);\n",
name.c_str());
@@ -1715,6 +1802,100 @@ bool plain_cpp_generator::plain_printer::want_descendent_overloads(
return methods.size() > 1;
}
/* Print the header of the constructor for the "id" class
* that takes a user object.
*
* The user object is taken as a std::any.
*/
void plain_cpp_generator::plain_printer::print_id_constructor_user_header()
{
if (declarations)
os << " inline explicit ";
else
os << "id::";
os << "id(" << generator.isl_namespace() << "ctx ctx, "
<< "const std::string &str, const std::any &any)";
if (declarations)
os << ";";
os << "\n";
}
/* Print the header of the "id" method
* for retrieving the user object associated to the identifier.
* If "optional" is set, the method returns a std::optional user object.
* The returned object is of a type specified by template parameter T.
*/
void plain_cpp_generator::plain_printer::print_id_user_header(bool optional)
{
auto indent = declarations ? " " : "";
os << indent << "template <class T>\n";
os << indent << (optional ? "std::optional<T> " : "T ");
if (!declarations)
os << "id::";
os << (optional ? "try_" : "");
os << "user() const";
if (declarations)
os << ";";
os << "\n";
}
/* Perform printing by "fn" in a context that only gets compiled
* by C++17 compilers.
*/
static void on_cplusplus17(ostream &os, const std::function<void(void)> &fn)
{
os << "#if __cplusplus >= 201703L\n";
fn();
os << "#endif\n";
}
/* Print declarations or definitions of the special methods of the "id" class
* that are not automatically derived from the C interface.
*
* In particular, print a constructor that takes a user pointer
* as well as methods for retrieving this user pointer.
*
* These methods require C++17 features.
*/
void plain_cpp_generator::plain_printer::print_special_id()
{
os << "\n";
on_cplusplus17(os, [this] () {
print_id_constructor_user();
print_id_user(true);
print_id_user(false);
});
}
/* Print declarations or definitions of any special methods of this class
* not automatically derived from the C interface.
*
* In particular, print special methods for the "id" class.
*/
void plain_cpp_generator::plain_printer::print_special()
{
if (clazz.name == "isl_id")
print_special_id();
}
/* Print declarations or definitions of the public methods.
*/
void plain_cpp_generator::plain_printer::print_public_methods()
{
print_public_constructors();
print_constructors();
print_copy_assignment();
print_destructor();
print_ptr();
print_downcast();
print_ctx();
print_method_separator();
print_persistent_callbacks();
print_methods();
print_set_enums();
print_special();
}
/* Print the body of C function callback with the given indentation
* that can be use as an argument to "param" for marshalling
* the corresponding C++ callback.

View File

@@ -81,6 +81,21 @@ struct plain_cpp_generator::plain_printer : public cpp_generator::class_printer
void print_callback_data_decl(ParmVarDecl *param, const string &name);
virtual bool want_descendent_overloads(const function_set &methods)
override;
virtual void print_public_constructors() = 0;
virtual void print_copy_assignment() = 0;
virtual void print_destructor() = 0;
virtual void print_ptr() = 0;
virtual void print_downcast() = 0;
virtual void print_ctx() = 0;
virtual void print_method_separator() = 0;
virtual void print_persistent_callbacks() = 0;
void print_public_methods();
void print_id_constructor_user_header();
void print_id_user_header(bool optional);
virtual void print_id_constructor_user() = 0;
virtual void print_id_user(bool optional) = 0;
void print_special_id();
void print_special();
};
/* A helper class for printing method declarations of a class.
@@ -95,18 +110,21 @@ struct plain_cpp_generator::decl_printer :
void print_subclass_type();
void print_class_factory(const std::string &prefix = std::string());
void print_protected_constructors();
void print_copy_assignment();
void print_public_constructors();
void print_destructor();
void print_ptr();
virtual void print_copy_assignment() override;
virtual void print_public_constructors() override;
virtual void print_destructor() override;
virtual void print_ptr() override;
void print_isa_type_template(int indent, const isl_class &super);
void print_downcast();
void print_ctx();
virtual void print_downcast() override;
virtual void print_ctx() override;
virtual void print_method_separator() override;
void print_persistent_callback_data(FunctionDecl *method);
void print_persistent_callbacks();
virtual void print_persistent_callbacks() override;
virtual void print_method(const Method &method) override;
virtual void print_method(const ConversionMethod &method) override;
virtual void print_get_method(FunctionDecl *fd) override;
virtual void print_id_constructor_user() override;
virtual void print_id_user(bool optional) override;
};
/* A helper class for printing method definitions of a class.
@@ -127,15 +145,17 @@ struct plain_cpp_generator::impl_printer :
void print_check_ptr_end(const char *ptr);
void print_class_factory();
void print_protected_constructors();
void print_public_constructors();
void print_copy_assignment();
void print_destructor();
void print_ptr();
void print_downcast();
void print_ctx();
virtual void print_public_constructors() override;
virtual void print_copy_assignment() override;
virtual void print_destructor() override;
virtual void print_ptr() override;
virtual void print_downcast() override;
virtual void print_ctx() override;
virtual void print_method_separator() override;
void print_set_persistent_callback(const Method &method);
void print_persistent_callbacks();
virtual void print_persistent_callbacks() override;
void print_argument_validity_check(const Method &method);
void print_save_ctx(const std::string &ctx);
void print_save_ctx(const Method &method);
void print_on_error_continue();
void print_exceptional_execution_check(const Method &method);
@@ -147,6 +167,8 @@ struct plain_cpp_generator::impl_printer :
void print_callback_body(int indent, ParmVarDecl *param,
const string &name);
void print_callback_local(ParmVarDecl *param);
virtual void print_id_constructor_user() override;
virtual void print_id_user(bool optional) override;
};
#endif

View File

@@ -195,8 +195,7 @@ void python_generator::print_copy(QualType type)
}
/* Construct a wrapper for callback argument "param" (at position "arg").
* Assign the wrapper to "cb". We assume here that a function call
* has at most one callback argument.
* Assign the wrapper to "cb{arg}".
*
* The wrapper converts the arguments of the callback to python types,
* taking a copy if the C callback does not take its arguments.
@@ -272,7 +271,7 @@ void python_generator::print_callback(ParmVarDecl *param, int arg)
print_copy(return_type);
printf("(res.ptr)\n");
}
printf(" cb = fn(cb_func)\n");
printf(" cb%d = fn(cb_func)\n", arg);
}
/* Print the argument at position "arg" in call to "fd".
@@ -284,7 +283,7 @@ void python_generator::print_callback(ParmVarDecl *param, int arg)
* assuming that the caller has made the context available
* in a "ctx" variable.
* Otherwise, if the argument is a callback, then print a reference to
* the callback wrapper "cb".
* the corresponding callback wrapper.
* Otherwise, if the argument is marked as consuming a reference,
* then pass a copy of the pointer stored in the corresponding
* argument passed to the Python method.
@@ -302,7 +301,7 @@ void python_generator::print_arg_in_call(FunctionDecl *fd, const char *fmt,
if (is_isl_ctx(type)) {
printf("ctx");
} else if (is_callback(type)) {
printf("cb");
printf("cb%d", arg - skip);
} else if (takes(param)) {
print_copy(type);
printf("(");
@@ -372,6 +371,8 @@ static void print_persistent_callback_failure_check(int indent,
* then keep track of the constructed C callback (such that it doesn't
* get destroyed) and the data structure that holds the captured exception
* (such that it can be raised again).
* The callback appears in position 1 and the C callback is therefore
* called "cb1".
*
* If the return type is a (const) char *, then convert the result
* to a Python string, raising an error on NULL and freeing
@@ -406,14 +407,14 @@ void python_generator::print_method_return(int indent, const isl_class &clazz,
string callback_name;
callback_name = clazz.persistent_callback_name(method);
print_indent(indent, "obj.%s = { 'func': cb, "
print_indent(indent, "obj.%s = { 'func': cb1, "
"'exc_info': exc_info }\n",
callback_name.c_str());
}
print_indent(indent, "return obj\n");
} else if (is_string(return_type)) {
print_indent(indent, "if res == 0:\n");
print_indent(indent, " raise\n");
print_indent(indent, " raise Error\n");
print_indent(indent, "string = "
"cast(res, c_char_p).value.decode('ascii')\n");
@@ -423,7 +424,7 @@ void python_generator::print_method_return(int indent, const isl_class &clazz,
print_indent(indent, "return string\n");
} else if (is_isl_neg_error(return_type)) {
print_indent(indent, "if res < 0:\n");
print_indent(indent, " raise\n");
print_indent(indent, " raise Error\n");
if (is_isl_bool(return_type))
print_indent(indent, "return bool(res)\n");
else if (is_isl_size(return_type))
@@ -456,20 +457,19 @@ void python_generator::print_get_method(const isl_class &clazz,
/* Print a call to "method", along with the corresponding
* return statement, with the given indentation.
* "drop_ctx" is set if the first argument is an isl_ctx.
* "drop_user" is set if the last argument is a "user" argument
* corresponding to a callback argument.
*
* A "ctx" variable is first initialized as it may be needed
* in the first call to print_arg_in_call and in print_method_return.
*
* If the method has a callback function, then any exception
* thrown in the callback also need to be rethrown.
* If the method has any callback function, then any exception
* thrown in any callback also need to be rethrown.
*/
void python_generator::print_method_call(int indent, const isl_class &clazz,
FunctionDecl *method, const char *fmt, int drop_ctx, int drop_user)
FunctionDecl *method, const char *fmt, int drop_ctx)
{
string fullname = method->getName().str();
int num_params = method->getNumParams();
int drop_user = 0;
if (drop_ctx) {
print_indent(indent, "ctx = Context.getDefaultInstance()\n");
@@ -479,16 +479,19 @@ void python_generator::print_method_call(int indent, const isl_class &clazz,
printf(".ctx\n");
}
print_indent(indent, "res = isl.%s(", fullname.c_str());
for (int i = 0; i < num_params - drop_user; ++i) {
for (int i = 0; i < num_params; ++i) {
if (i > 0)
printf(", ");
print_arg_in_call(method, fmt, i, drop_ctx);
}
if (drop_user)
print_arg_in_call(method, fmt, i, drop_ctx + drop_user);
if (!is_callback_arg(method, i))
continue;
++drop_user;
++i;
printf(", None");
}
printf(")\n");
if (drop_user)
if (drop_user > 0)
print_rethrow(indent, "exc_info[0]");
print_method_return(indent, clazz, method, fmt);
@@ -506,10 +509,10 @@ void python_generator::print_method_call(int indent, const isl_class &clazz,
* If, moreover, this first argument is an isl_ctx, then remove
* it from the arguments of the Python method.
*
* If the function has a callback argument, then it also has a "user"
* argument. Since Python has closures, there is no need for such
* a user argument in the Python interface, so we simply drop it.
* We also create a wrapper ("cb") for the callback.
* If the function has any callback arguments, then it also has corresponding
* "user" arguments. Since Python has closures, there is no need for such
* user arguments in the Python interface, so we simply drop them.
* We also create a wrapper ("cb{arg}") for each callback.
*
* If the function consumes a reference, then we pass it a copy of
* the actual argument.
@@ -527,25 +530,25 @@ void python_generator::print_method(const isl_class &clazz,
int drop_ctx = first_arg_is_isl_ctx(method);
for (int i = 1; i < num_params; ++i) {
ParmVarDecl *param = method->getParamDecl(i);
QualType type = param->getOriginalType();
if (is_callback(type))
drop_user = 1;
if (is_callback_arg(method, i))
drop_user += 1;
}
print_method_header(is_static(clazz, method), cname,
num_params - drop_ctx - drop_user);
print_type_checks(cname, method, drop_ctx,
num_params - drop_user, super);
num_params, super);
drop_user = 0;
for (int i = 1; i < num_params; ++i) {
ParmVarDecl *param = method->getParamDecl(i);
QualType type = param->getOriginalType();
if (!is_callback(type))
continue;
print_callback(param, i - drop_ctx);
print_callback(param, i - drop_ctx - drop_user);
drop_user += 1;
}
print_method_call(8, clazz, method, fixed_arg_fmt, drop_ctx, drop_user);
print_method_call(8, clazz, method, fixed_arg_fmt, drop_ctx);
if (clazz.is_get_method(method))
print_get_method(clazz, method);
@@ -568,9 +571,18 @@ static void print_argument_check(QualType type, int i)
}
}
/* Is any element of "vector" set?
*/
static bool any(const std::vector<bool> &vector)
{
return std::find(vector.begin(), vector.end(), true) != vector.end();
}
/* Print a test that checks whether the arguments passed
* to the Python method correspond to the arguments
* expected by "fd".
* expected by "fd" and
* check if the object on which the method is called, if any,
* is of the right type.
* "drop_ctx" is set if the first argument of "fd" is an isl_ctx,
* which does not appear as an argument to the Python method.
*
@@ -579,14 +591,17 @@ static void print_argument_check(QualType type, int i)
* to be of the type as prescribed by the second input argument
* of the conversion function.
* The corresponding arguments are then converted to the expected types
* if needed. The argument tuple first needs to be converted to a list
* if needed.
* The object on which the method is called is also converted if needed.
* The argument tuple first needs to be converted to a list
* in order to be able to modify the entries.
*/
void python_generator::print_argument_checks(const isl_class &clazz,
FunctionDecl *fd, int drop_ctx)
{
int num_params = fd->getNumParams();
int first = generator::is_static(clazz, fd) ? drop_ctx : 1;
bool is_static = generator::is_static(clazz, fd);
int first = is_static ? drop_ctx : 1;
std::vector<bool> convert(num_params);
printf(" if len(args) == %d", num_params - drop_ctx);
@@ -610,14 +625,16 @@ void python_generator::print_argument_checks(const isl_class &clazz,
}
printf(":\n");
if (std::find(convert.begin(), convert.end(), true) == convert.end())
if (is_static && !any(convert))
return;
print_indent(12, "args = list(args)\n");
first = is_static ? drop_ctx : 0;
for (int i = first; i < num_params; ++i) {
bool is_self = !is_static && i == 0;
ParmVarDecl *param = fd->getParamDecl(i);
string type;
if (!convert[i])
if (!is_self && !convert[i])
continue;
type = type2python(extract_type(param->getOriginalType()));
print_type_check(12, type, var_arg_fmt,
@@ -639,7 +656,7 @@ void python_generator::print_method_overload(const isl_class &clazz,
int drop_ctx = first_arg_is_isl_ctx(method);
print_argument_checks(clazz, method, drop_ctx);
print_method_call(12, clazz, method, var_arg_fmt, drop_ctx, 0);
print_method_call(12, clazz, method, var_arg_fmt, drop_ctx);
}
/* Print a python method with a name derived from "fullname"
@@ -755,6 +772,83 @@ void python_generator::print_constructor(const isl_class &clazz,
printf(" return\n");
}
/* The definition of the part of constructor for the "id" class
* that construct an object from a name and a user object,
* without the initial newline.
*
* Just like the parts generated by python_generator::print_constructor,
* the result of the isl_id_alloc call is stored in self.ptr and
* a reference to the default context is stored in self.ctx.
* Also, just like any other constructor or method with a string argument,
* the python string is first encoded as a byte sequence,
* using 'ascii' as encoding.
*
* Since the isl_id keeps a reference to the Python user object,
* the reference count of the Python object needs to be incremented,
* but only if the construction of the isl_id is successful.
* The reference count of the Python object is decremented again
* by Context.free_user when the reference count of the isl_id
* drops to zero.
*/
static const char *const id_constructor_user = &R"(
if len(args) == 2 and type(args[0]) == str:
self.ctx = Context.getDefaultInstance()
name = args[0].encode('ascii')
self.ptr = isl.isl_id_alloc(self.ctx, name, args[1])
self.ptr = isl.isl_id_set_free_user(self.ptr, Context.free_user)
if self.ptr is not None:
pythonapi.Py_IncRef(py_object(args[1]))
return
)"[1];
/* Print any special constructor parts of this class that are not
* automatically derived from the C interface.
*
* In particular, print a special constructor part for the "id" class.
*/
void python_generator::print_special_constructors(const isl_class &clazz)
{
if (clazz.name != "isl_id")
return;
printf("%s", id_constructor_user);
}
/* The definition of an "id" method
* for retrieving the user object associated to the identifier,
* without the initial newline.
*
* The isl_id needs to have been created by the constructor
* in id_constructor_user. That is, it needs to have a user pointer and
* it needs to have its free_user callback set to Context.free_user.
* The functions need to be cast to c_void_p to be able to compare
* the addresses.
*
* Return None if any of the checks fail.
* Note that isl_id_get_user returning NULL automatically results in None.
*/
static const char *const id_user = &R"(
def user(self):
free_user = cast(Context.free_user, c_void_p)
id_free_user = cast(isl.isl_id_get_free_user(self.ptr), c_void_p)
if id_free_user.value != free_user.value:
return None
return isl.isl_id_get_user(self.ptr)
)"[1];
/* Print any special methods of this class that are not
* automatically derived from the C interface.
*
* In particular, print a special method for the "id" class.
*/
void python_generator::print_special_methods(const isl_class &clazz)
{
if (clazz.name != "isl_id")
return;
printf("%s", id_user);
}
/* If "clazz" has a type function describing subclasses,
* then add constructors that allow each of these subclasses
* to be treated as an object to the superclass.
@@ -824,34 +918,37 @@ void python_generator::print_restype(FunctionDecl *fd)
}
/* Tell ctypes about the types of the arguments of the function "fd".
*
* Any callback argument is followed by a user pointer argument.
* Each such pair or arguments is handled together.
*/
void python_generator::print_argtypes(FunctionDecl *fd)
{
string fullname = fd->getName().str();
int n = fd->getNumParams();
int drop_user = 0;
printf("isl.%s.argtypes = [", fullname.c_str());
for (int i = 0; i < n - drop_user; ++i) {
for (int i = 0; i < n; ++i) {
ParmVarDecl *param = fd->getParamDecl(i);
QualType type = param->getOriginalType();
if (is_callback(type))
drop_user = 1;
if (i)
printf(", ");
if (is_isl_ctx(type))
printf("Context");
else if (is_isl_type(type) || is_callback(type))
else if (is_isl_type(type))
printf("c_void_p");
else if (is_callback(type))
printf("c_void_p, c_void_p");
else if (is_string(type))
printf("c_char_p");
else if (is_long(type))
printf("c_long");
else
printf("c_int");
if (is_callback(type))
++i;
}
if (drop_user)
printf(", c_void_p");
printf("]\n");
}
@@ -867,7 +964,8 @@ void python_generator::print_method_type(FunctionDecl *fd)
* if it is one of those type subclasses, then print a __new__ method.
*
* In the superclass, the __new__ method constructs an object
* of the subclass type specified by the type function.
* of the subclass type specified by the type function,
* raising an error on an error type.
* In the subclass, the __new__ method reverts to the original behavior.
*/
void python_generator::print_new(const isl_class &clazz,
@@ -891,7 +989,7 @@ void python_generator::print_new(const isl_class &clazz,
printf(" return %s(**keywords)\n",
type2python(i->second).c_str());
}
printf(" raise\n");
printf(" raise Error\n");
}
printf(" return super(%s, cls).__new__(cls)\n",
@@ -1003,9 +1101,11 @@ void python_generator::print_method_types(const isl_class &clazz)
*
* Then we print a constructor with several cases, one for constructing
* a Python object from a return value, one for each function that
* was marked as a constructor and for each type based subclass.
* was marked as a constructor, a class specific constructor, if any, and
* one for each type based subclass.
*
* Next, we print out some common methods and the methods corresponding
* Next, we print out some common methods, class specific methods and
* the methods corresponding
* to functions that are not marked as constructors, including those
* that set a persistent callback and those that set an enum value.
*
@@ -1016,9 +1116,6 @@ void python_generator::print_method_types(const isl_class &clazz)
void python_generator::print(const isl_class &clazz)
{
string p_name = type2python(clazz.subclass_name);
function_set::const_iterator in;
map<string, function_set>::const_iterator it;
map<FunctionDecl *, vector<set_enum> >::const_iterator ie;
vector<string> super = find_superclasses(clazz.type);
const set<FunctionDecl *> &callbacks = clazz.persistent_callbacks;
@@ -1038,9 +1135,9 @@ void python_generator::print(const isl_class &clazz)
printf(" self.ptr = keywords[\"ptr\"]\n");
printf(" return\n");
for (in = clazz.constructors.begin(); in != clazz.constructors.end();
++in)
print_constructor(clazz, *in);
for (const auto &cons : clazz.constructors)
print_constructor(clazz, cons);
print_special_constructors(clazz);
print_upcast_constructors(clazz);
printf(" raise Error\n");
printf(" def __del__(self):\n");
@@ -1051,12 +1148,13 @@ void python_generator::print(const isl_class &clazz)
print_representation(clazz, p_name);
print_copy_callbacks(clazz);
for (in = callbacks.begin(); in != callbacks.end(); ++in)
print_method(clazz, *in, super);
for (it = clazz.methods.begin(); it != clazz.methods.end(); ++it)
print_method(clazz, it->first, it->second, super);
for (ie = clazz.set_enums.begin(); ie != clazz.set_enums.end(); ++ie)
print_set_enum(clazz, ie->first, super);
print_special_methods(clazz);
for (const auto &callback : callbacks)
print_method(clazz, callback, super);
for (const auto &kvp : clazz.methods)
print_method(clazz, kvp.first, kvp.second, super);
for (const auto &kvp : clazz.set_enums)
print_set_enum(clazz, kvp.first, super);
printf("\n");

View File

@@ -38,6 +38,8 @@ private:
void print_restype(FunctionDecl *fd);
void print(map<string, isl_class> &classes, set<string> &done);
void print_constructor(const isl_class &clazz, FunctionDecl *method);
void print_special_constructors(const isl_class &clazz);
void print_special_methods(const isl_class &clazz);
void print_upcast_constructors(const isl_class &clazz);
void print_new(const isl_class &clazz,
const string &python_name);
@@ -51,7 +53,7 @@ private:
vector<string> super);
void print_method_call(int indent, const isl_class &clazz,
FunctionDecl *method, const char *fmt,
int drop_ctx, int drop_user);
int drop_ctx);
void print_argument_checks(const isl_class &clazz, FunctionDecl *fd,
int drop_ctx);
void print_method_overload(const isl_class &clazz,

View File

@@ -429,6 +429,12 @@ static Signature bin_map_domain =
{ { Domain, Range }, { { Domain, Range }, { Domain } } };
static Signature bin_map_range =
{ { Domain, Range }, { { Domain, Range }, { Range } } };
static Signature bin_map_domain_wrapped_domain =
{ { { Domain, Domain2 }, Range },
{ { { Domain, Domain2 }, Range }, { Domain } } };
static Signature bin_map_range_wrapped_domain =
{ { Domain, { Range, Range2 } },
{ { Domain, { Range, Range2 } }, { Range } } };
/* Signatures for binary operations, where the second argument
* is an identifier (with an anonymous tuple).
@@ -529,6 +535,24 @@ static Signature each_map =
{ { Res }, { { Domain, Range }, { Res }, { Domain, Range } } };
static std::vector<Signature> each = { each_params, each_set, each_map };
/* Signatures for isl_*_list_foreach_scc.
*
* The first callback takes two elements with the same tuple kinds.
* The second callback takes a list with the same tuple kinds.
*/
static Signature each_scc_params =
{ { Res }, { { }, { Res }, { }, { }, { Res }, { } } };
static Signature each_scc_set =
{ { Res }, { { Domain },
{ Res }, { Domain }, { Domain },
{ Res }, { Domain } } };
static Signature each_scc_map =
{ { Res }, { { Domain, Range },
{ Res }, { Domain, Range }, { Domain, Range },
{ Res }, { Domain, Range } } };
static std::vector<Signature> each_scc =
{ each_scc_params, each_scc_set, each_scc_map };
/* Signature for creating a map from a range,
* where the domain is given by an extra argument.
*/
@@ -779,7 +803,7 @@ member_methods {
{ "ceil", fn_un_op },
{ "coalesce", un_op },
{ "cond", fn_ter_op },
{ "constant_multi_val", range_op },
{ "constant", range_op },
{ "curry", { curry } },
{ "deltas", { transformation_domain } },
{ "detect_equalities", un_op },
@@ -798,10 +822,12 @@ member_methods {
{ "flatten_range", flatten_range },
{ "floor", fn_un_op },
{ "foreach", each },
{ "foreach_scc", each_scc },
{ "ge_set", { set_join } },
{ "gt_set", { set_join } },
{ "gist", bin_op },
{ "gist_domain", { bin_map_domain } },
{ "gist_params", { bin_set_params, bin_map_params } },
{ "identity", { un_map, set_to_map } },
{ "identity_on_domain", { set_to_map } },
{ "indicator_function", anonymous_from_domain },
@@ -809,7 +835,12 @@ member_methods {
{ "intersect", bin_op },
{ "intersect_params", { bin_set_params, bin_map_params } },
{ "intersect_domain", { bin_map_domain } },
{ "intersect_domain_wrapped_domain",
{ bin_map_domain_wrapped_domain } },
{ "intersect_range", { bin_map_range } },
{ "intersect_range_wrapped_domain",
{ bin_map_range_wrapped_domain } },
{ "lattice_tile", { un_set } },
{ "le_set", { set_join } },
{ "lt_set", { set_join } },
{ "lex_le_at", { map_cmp } },
@@ -822,8 +853,10 @@ member_methods {
{ "lower_bound", fn_bin_op },
{ "map_from_set", { set_to_map } },
{ "max", min_max },
{ "max_val", range_op },
{ "max_multi_val", range_op },
{ "min", min_max },
{ "min_val", range_op },
{ "min_multi_val", range_op },
{ "mod", bin_val },
{ "on_domain", { map_from_domain_and_range } },
@@ -1020,22 +1053,34 @@ static std::vector<Kind> add_name(const std::vector<Kind> &tuples)
return named;
}
/* Add a template class called "name", of which the methods are described
* by "clazz" and where the corresponding base type has kinds "base_kinds".
/* Look up the (initial) specializations of the class called "name".
* If no specializations have been defined, then return an empty vector.
*
* Start from the initial specializations of the corresponding base type.
* If this template class is a multi-expression, then it was derived
* from an anonymous function type. Replace the final Anonymous
* tuple kind by a placeholder in this case.
*/
static std::vector<Kind> lookup_class_tuples(const std::string &name)
{
std::string base = base_type(name);
if (base_kinds.count(base) == 0)
return { };
if (name.find("multi_") != std::string::npos)
return add_name(base_kinds.at(base));
return base_kinds.at(base);
}
/* Add a template class called "name", of which the methods are described
* by "clazz" and the initial specializations by "class_tuples".
*/
void template_cpp_generator::add_template_class(const isl_class &clazz,
const std::string &name, const std::vector<Kind> &base_kinds)
const std::string &name, const std::vector<Kind> &class_tuples)
{
auto isl_namespace = cpp_type_printer().isl_namespace();
auto super = isl_namespace + name;
auto class_tuples = base_kinds;
if (name.find("multi_") != std::string::npos)
class_tuples = add_name(class_tuples);
template_classes.emplace(name,
template_class{name, super, clazz, class_tuples});
}
@@ -1061,11 +1106,11 @@ template_cpp_generator::template_cpp_generator(clang::SourceManager &SM,
for (const auto &kvp : classes) {
const auto &clazz = kvp.second;
std::string name = type2cpp(clazz);
std::string base = base_type(name);
const auto &class_tuples = lookup_class_tuples(name);
if (base_kinds.count(base) == 0)
if (class_tuples.empty())
continue;
add_template_class(clazz, name, base_kinds.at(base));
add_template_class(clazz, name, class_tuples);
}
}
@@ -1556,22 +1601,25 @@ void template_cpp_generator::method_decl_printer::print_method_sig(
}
/* Return the total number of arguments in the signature for "method",
* taking into account a possible callback argument.
* taking into account any possible callback arguments.
*
* In particular, if the method has a callback argument,
* then the return kind of the callback appears at the position
* of the callback and the kinds of the arguments (except
* the user pointer argument) appear in the following positions.
* The user pointer argument that follows the callback argument
* is also removed.
*/
static int total_params(const Method &method)
{
int n = method.num_params();
if (method.callback) {
auto callback_type = method.callback->getType();
auto callback = generator::extract_prototype(callback_type);
for (const auto &callback : method.callbacks) {
auto callback_type = callback->getType();
auto proto = generator::extract_prototype(callback_type);
n += callback->getNumArgs() - 1;
n += proto->getNumArgs() - 1;
n -= 1;
}
return n;
@@ -1631,7 +1679,7 @@ void template_cpp_generator::method_impl_printer::print_constructor_body(
const auto &base_name = instance.base_name();
os << " : " << base_name;
method.print_cpp_arg_list(os, [&] (int i) {
method.print_cpp_arg_list(os, [&] (int i, int arg) {
os << method.fd->getParamDecl(i)->getName().str();
});
os << "\n";
@@ -1644,6 +1692,7 @@ void template_cpp_generator::method_impl_printer::print_constructor_body(
* calling "print_arg" with the type and the name of the arguments,
* where the type is obtained from "type_printer" with argument positions
* shifted by "shift".
* None of the arguments should be skipped.
*/
static void print_callback_args(std::ostream &os,
const FunctionProtoType *callback, const cpp_type_printer &type_printer,
@@ -1659,40 +1708,34 @@ static void print_callback_args(std::ostream &os,
auto cpptype = type_printer.param(shift + i, type);
print_arg(cpptype, name);
return false;
});
}
/* Print a lambda for passing to the plain method corresponding to "method"
* with signature "sig".
*
* The method is assumed to have only the callback as argument,
* which means the arguments of the callback are shifted by 2
* with respect to the arguments of the signature
* (one for the position of the callback argument plus
* one for the return kind of the callback).
/* Print a lambda corresponding to "callback"
* with signature "sig" and argument positions shifted by "shift".
*
* The lambda takes arguments with plain isl types and
* calls the callback of "method" with templated arguments.
*/
static void print_callback_lambda(std::ostream &os, const Method &method,
const Signature &sig)
static void print_callback_lambda(std::ostream &os, ParmVarDecl *callback,
const Signature &sig, int shift)
{
auto callback_type = method.callback->getType();
auto callback_name = method.callback->getName().str();
auto callback = generator::extract_prototype(callback_type);
auto callback_type = callback->getType();
auto callback_name = callback->getName().str();
auto proto = generator::extract_prototype(callback_type);
if (method.num_params() != 2)
generator::die("callback is assumed to be single argument");
os << " auto lambda = [&] ";
print_callback_args(os, callback, cpp_type_printer(), 2,
os << " auto lambda_" << callback_name << " = [&] ";
print_callback_args(os, proto, cpp_type_printer(), shift,
[&] (const std::string &type, const std::string &name) {
os << type << " " << name;
});
os << " {\n";
os << " return " << callback_name;
print_callback_args(os, callback, template_cpp_arg_type_printer(sig), 2,
print_callback_args(os, proto, template_cpp_arg_type_printer(sig),
shift,
[&] (const std::string &type, const std::string &name) {
os << type << "(" << name << ")";
});
@@ -1701,13 +1744,40 @@ static void print_callback_lambda(std::ostream &os, const Method &method,
os << " };\n";
}
/* Print lambdas for passing to the plain method corresponding to "method"
* with signature "sig".
*
* The method is assumed to have only callbacks as argument,
* which means the arguments of the first callback are shifted by 2
* with respect to the arguments of the signature
* (one for the position of the callback argument plus
* one for the return kind of the callback).
* The arguments of a subsequent callback are shifted by
* the number of arguments of the previous callback minus one
* for the user pointer plus one for the return kind.
*/
static void print_callback_lambdas(std::ostream &os, const Method &method,
const Signature &sig)
{
int shift;
if (method.num_params() != 1 + 2 * method.callbacks.size())
generator::die("callbacks are assumed to be only arguments");
shift = 2;
for (const auto &callback : method.callbacks) {
print_callback_lambda(os, callback, sig, shift);
shift += generator::prototype_n_args(callback->getType());
}
}
/* Print a definition of the member method "method", which is known
* to have a callback argument, with signature "sig".
*
* First print a lambda for passing to the corresponding plain method and
* First print lambdas for passing to the corresponding plain method and
* calling the callback of "method" with templated arguments.
* Then call the plain method, replacing the original callback
* by the lambda.
* Then call the plain method, replacing the original callbacks
* by the lambdas.
*
* The return value is assumed to be isl_bool or isl_stat
* so that no conversion to a template type is required.
@@ -1723,17 +1793,16 @@ void template_cpp_generator::method_impl_printer::print_callback_method_body(
os << "{\n";
print_callback_lambda(os, method, sig);
print_callback_lambdas(os, method, sig);
os << " return ";
os << base_name << "::" << method.name;
method.print_cpp_arg_list(os, [&] (int i) {
method.print_cpp_arg_list(os, [&] (int i, int arg) {
auto param = method.fd->getParamDecl(i);
if (param == method.callback)
os << "lambda";
else
os << param->getName().str();
if (generator::is_callback(param->getType()))
os << "lambda_";
os << param->getName().str();
});
os << ";\n";
@@ -1755,7 +1824,7 @@ void template_cpp_generator::method_impl_printer::print_method_body(
os << "{\n";
os << " auto res = ";
os << base_name << "::" << method.name;
method.print_cpp_arg_list(os, [&] (int i) {
method.print_cpp_arg_list(os, [&] (int i, int arg) {
os << method.fd->getParamDecl(i)->getName().str();
});
os << ";\n";
@@ -1775,7 +1844,7 @@ void template_cpp_generator::method_impl_printer::print_method_body(
* Otherwise print the method header, preceded by the template parameters,
* if needed.
* The body depends on whether the method is a constructor or
* takes a callback.
* takes any callbacks.
*/
void template_cpp_generator::method_impl_printer::print_method_sig(
const Method &method, const Signature &sig, bool deleted)
@@ -1789,7 +1858,7 @@ void template_cpp_generator::method_impl_printer::print_method_sig(
os << "\n";
if (method.kind == Method::Kind::constructor)
print_constructor_body(method, sig);
else if (method.callback)
else if (method.callbacks.size() != 0)
print_callback_method_body(method, sig);
else
print_method_body(method, sig);
@@ -2282,6 +2351,79 @@ void template_cpp_generator::class_printer::add_specialization(
instance.template_class.add_specialization(maybe_unified.second);
}
/* Does the type of the parameter at position "i" of "method" necessarily
* have a final Anonymous tuple?
*
* If the parameter is not of an isl type or if no specializations
* have been defined for the type, then it can be considered anonymous.
* Otherwise, if any specialization represents an anonymous function,
* then every specialization does, so simply check
* the first specialization.
*/
static bool param_is_anon(const Method &method, int i)
{
ParmVarDecl *param = method.get_param(i);
QualType type = param->getOriginalType();
if (cpp_generator::is_isl_type(type)) {
const auto &name = type->getPointeeType().getAsString();
const auto &cpp = cpp_generator::type2cpp(name);
const auto &tuples = lookup_class_tuples(cpp);
if (tuples.empty())
return true;
return tuples[0].is_anon();
}
return true;
}
/* Replace the final tuple of "arg_kind" by Anonymous in "sig" and
* return the update signature,
* unless this would affect the class instance "instance_kind".
*
* If the original "instance_kind" is a special case
* of the result of the substitution, then "instance_kind"
* is not affected and the substitution can be applied
* to the entire signature.
*/
static Signature specialize_anonymous_arg(const Signature &sig,
const Kind &arg_kind, const Kind &instance_kind)
{
const auto &subs = compute_unifier(arg_kind.back(), Anonymous);
const auto &specialized_instance = instance_kind.apply(subs);
if (!specializer(specialized_instance, instance_kind).first)
return sig;
return sig.apply(subs);
}
/* If any of the arguments of "method" is of a type that necessarily
* has a final Anonymous tuple, but the corresponding entry
* in the signature "sig" is not Anonymous, then replace
* that entry by Anonymous and return the updated signature,
* unless this would affect the class instance "instance_kind".
*/
static Signature specialize_anonymous_args(const Signature &sig,
const Method &method, const Kind &instance_kind)
{
auto specialized_sig = sig;
method.on_cpp_arg_list([&] (int i, int arg) {
const auto &arg_kind = sig.args[arg];
if (arg_kind.is_anon())
return;
if (!param_is_anon(method, i))
return;
specialized_sig = specialize_anonymous_arg(specialized_sig,
arg_kind, instance_kind);
});
return specialized_sig;
}
/* Print a declaration or definition of the method "method"
* if the template class specialization matches "match_arg".
* Return true if so.
@@ -2294,6 +2436,7 @@ void template_cpp_generator::class_printer::add_specialization(
* If the template class specialization is a special case of
* (the renamed) "match_arg"
* then apply the specializer to the complete (renamed) signature,
* specialize any anonymous arguments,
* check that the return kind is allowed and, if so,
* print the declaration or definition using the specialized signature.
*
@@ -2310,6 +2453,8 @@ bool template_cpp_generator::class_printer::print_matching_method(
if (maybe_specializer.first) {
const auto &specializer = maybe_specializer.second;
auto specialized_sig = sig.apply(rename).apply(specializer);
specialized_sig = specialize_anonymous_args(specialized_sig,
method, instance.kind);
if (!is_return_kind(method, specialized_sig.ret))
return false;
@@ -2532,15 +2677,15 @@ const std::string name_without_return(const Method &method)
}
/* If this method has a callback, then remove the type
* of the first argument of the callback from the name of the method.
* of the first argument of the first callback from the name of the method.
* Otherwise, simply return the name of the method.
*/
const std::string callback_name(const Method &method)
{
if (!method.callback)
if (method.callbacks.size() == 0)
return method.name;
auto type = method.callback->getType();
auto type = method.callbacks.at(0)->getType();
auto callback = cpp_generator::extract_prototype(type);
auto arg_type = plain_type(callback->getArgType(0));
return generator::drop_suffix(method.name, "_" + arg_type);

View File

@@ -99,7 +99,7 @@ class template_cpp_generator : public cpp_generator {
struct class_impl_printer;
void add_template_class(const isl_class &clazz, const std::string &name,
const std::vector<Kind> &base_kinds);
const std::vector<Kind> &class_tuples);
public:
template_cpp_generator(clang::SourceManager &SM,
std::set<clang::RecordDecl *> &exported_types,

File diff suppressed because it is too large Load Diff

View File

@@ -427,6 +427,9 @@ __isl_give isl_set *isl_pw_multi_aff_as_set(__isl_take isl_pw_multi_aff *pma)
* of the piecewise affine expressions to the range of "mpa"
* with each dimension in the range equated to the
* corresponding piecewise affine expression.
*
* If "mpa" has an explicit domain (i.e., it is zero-dimensional),
* then return a set or map with the same (parameter) domain.
*/
static __isl_give isl_map *map_from_multi_pw_aff(
__isl_take isl_multi_pw_aff *mpa)
@@ -459,6 +462,8 @@ static __isl_give isl_map *map_from_multi_pw_aff(
map = isl_map_reset_space(map, isl_multi_pw_aff_get_space(mpa));
map = isl_map_intersect_multi_pw_aff_explicit_domain(map, mpa);
isl_multi_pw_aff_free(mpa);
return map;
error:

View File

@@ -113,6 +113,8 @@ __isl_give isl_pw_aff *isl_pw_aff_reset_domain_space(
__isl_give isl_pw_aff *isl_pw_aff_add_disjoint(
__isl_take isl_pw_aff *pwaff1, __isl_take isl_pw_aff *pwaff2);
__isl_keep isl_aff *isl_pw_aff_peek_base_at(__isl_keep isl_pw_aff *pa, int pos);
__isl_give isl_pw_aff *isl_pw_aff_domain_factor_domain(
__isl_take isl_pw_aff *pa);
@@ -157,6 +159,9 @@ __isl_give isl_multi_aff *isl_multi_aff_from_aff_mat(
#include <isl_list_templ.h>
__isl_keep isl_multi_aff *isl_pw_multi_aff_peek_base_at(
__isl_keep isl_pw_multi_aff *pma, int pos);
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_move_dims(
__isl_take isl_pw_multi_aff *pma,
enum isl_dim_type dst_type, unsigned dst_pos,

File diff suppressed because it is too large Load Diff

View File

@@ -1910,14 +1910,14 @@ error:
/* Does "aff" only attain non-negative values over build->domain?
* That is, does it not attain any negative values?
*/
int isl_ast_build_aff_is_nonneg(__isl_keep isl_ast_build *build,
isl_bool isl_ast_build_aff_is_nonneg(__isl_keep isl_ast_build *build,
__isl_keep isl_aff *aff)
{
isl_set *test;
int empty;
isl_bool empty;
if (!build)
return -1;
return isl_bool_error;
aff = isl_aff_copy(aff);
test = isl_set_from_basic_set(isl_aff_neg_basic_set(aff));

File diff suppressed because it is too large Load Diff

View File

@@ -290,7 +290,7 @@ __isl_give isl_pw_multi_aff *isl_ast_build_compute_gist_pw_multi_aff(
__isl_give isl_union_map *isl_ast_build_substitute_values_union_map_domain(
__isl_keep isl_ast_build *build, __isl_take isl_union_map *umap);
int isl_ast_build_aff_is_nonneg(__isl_keep isl_ast_build *build,
isl_bool isl_ast_build_aff_is_nonneg(__isl_keep isl_ast_build *build,
__isl_keep isl_aff *aff);
isl_bool isl_ast_build_has_stride(__isl_keep isl_ast_build *build, int pos);

View File

@@ -702,8 +702,6 @@ static __isl_give isl_ast_expr *reduce_list(enum isl_ast_expr_op_type type,
ctx = isl_pw_aff_list_get_ctx(list);
expr = isl_ast_expr_alloc_op(ctx, type, n);
if (!expr)
return NULL;
list = isl_pw_aff_list_copy(list);
list = isl_pw_aff_list_sort(list, &reduce_list_cmp, NULL);
@@ -715,17 +713,11 @@ static __isl_give isl_ast_expr *reduce_list(enum isl_ast_expr_op_type type,
expr_i = isl_ast_build_expr_from_pw_aff_internal(build,
isl_pw_aff_list_get_pw_aff(list, i));
if (!expr_i)
goto error;
expr->u.op.args[i] = expr_i;
expr = isl_ast_expr_op_add_arg(expr, expr_i);
}
isl_pw_aff_list_free(list);
return expr;
error:
isl_pw_aff_list_free(list);
isl_ast_expr_free(expr);
return NULL;
}
/* Add guards implied by the "generated constraints",
@@ -794,15 +786,16 @@ static __isl_give isl_ast_graft *refine_degenerate(
__isl_keep isl_ast_build *sub_build)
{
isl_pw_aff *value;
isl_ast_expr *init;
if (!graft || !sub_build)
return isl_ast_graft_free(graft);
value = isl_pw_aff_copy(sub_build->value);
graft->node->u.f.init = isl_ast_build_expr_from_pw_aff_internal(build,
value);
if (!graft->node->u.f.init)
init = isl_ast_build_expr_from_pw_aff_internal(build, value);
graft->node = isl_ast_node_for_set_init(graft->node, init);
if (!graft->node)
return isl_ast_graft_free(graft);
return graft;
@@ -1031,10 +1024,10 @@ static __isl_give isl_ast_graft *set_for_cond_from_list(
bound = reduce_list(isl_ast_expr_op_min, list, build);
iterator = isl_ast_expr_copy(graft->node->u.f.iterator);
cond = isl_ast_expr_alloc_binary(type, iterator, bound);
graft->node->u.f.cond = cond;
graft->node = isl_ast_node_for_set_cond(graft->node, cond);
isl_pw_aff_list_free(list);
if (!graft->node->u.f.cond)
if (!graft->node)
return isl_ast_graft_free(graft);
return graft;
}
@@ -1052,8 +1045,8 @@ static __isl_give isl_ast_graft *set_for_cond_from_set(
return NULL;
cond = isl_ast_build_expr_from_set_internal(build, isl_set_copy(set));
graft->node->u.f.cond = cond;
if (!graft->node->u.f.cond)
graft->node = isl_ast_node_for_set_cond(graft->node, cond);
if (!graft->node)
return isl_ast_graft_free(graft);
return graft;
}
@@ -1120,18 +1113,16 @@ static __isl_give isl_ast_graft *set_for_node_expressions(
int use_list, __isl_keep isl_pw_aff_list *upper_list,
__isl_keep isl_set *upper_set, __isl_keep isl_ast_build *build)
{
isl_ast_node *node;
isl_ast_expr *init;
if (!graft)
return NULL;
build = isl_ast_build_copy(build);
init = reduce_list(isl_ast_expr_op_max, lower, build);
graft->node = isl_ast_node_for_set_init(graft->node, init);
graft->node = isl_ast_node_for_set_inc(graft->node, for_inc(build));
node = graft->node;
node->u.f.init = reduce_list(isl_ast_expr_op_max, lower, build);
node->u.f.inc = for_inc(build);
if (!node->u.f.init || !node->u.f.inc)
if (!graft->node)
graft = isl_ast_graft_free(graft);
if (use_list)
@@ -1139,8 +1130,6 @@ static __isl_give isl_ast_graft *set_for_node_expressions(
else
graft = set_for_cond_from_set(graft, upper_set, build);
isl_ast_build_free(build);
return graft;
}
@@ -1247,7 +1236,7 @@ struct isl_ast_count_constraints_data {
};
/* Increment data->n_indep, data->lower or data->upper depending
* on whether "c" is independenct of dimensions data->pos,
* on whether "c" is independent of dimensions data->pos,
* a lower bound or an upper bound.
*/
static isl_stat count_constraints(__isl_take isl_constraint *c, void *user)

View File

@@ -14,6 +14,7 @@
#include <isl/id.h>
#include <isl/space.h>
#include <isl/stream.h>
#include <isl_ast_private.h>
#include <isl_ast_build_expr.h>
#include <isl_ast_build_private.h>
@@ -22,11 +23,14 @@
static __isl_give isl_ast_graft *isl_ast_graft_copy(
__isl_keep isl_ast_graft *graft);
static __isl_give isl_ast_graft *isl_stream_read_ast_graft(
__isl_keep isl_stream *s);
#undef EL_BASE
#define EL_BASE ast_graft
#include <isl_list_templ.c>
#include <isl_list_read_templ.c>
#undef BASE
#define BASE ast_graft
@@ -45,39 +49,56 @@ __isl_give isl_ast_node *isl_ast_graft_get_node(
return graft ? isl_ast_node_copy(graft->node) : NULL;
}
/* Create a graft for "node" with no guards and no enforced conditions.
/* Create a graft for "node" with guards "guard" and
* enforced conditions "enforced".
*/
__isl_give isl_ast_graft *isl_ast_graft_alloc(
__isl_take isl_ast_node *node, __isl_keep isl_ast_build *build)
static isl_ast_graft *graft_alloc(__isl_take isl_ast_node *node,
__isl_take isl_set *guard, __isl_take isl_basic_set *enforced)
{
isl_ctx *ctx;
isl_space *space;
isl_ast_graft *graft;
if (!node)
return NULL;
if (!node || !guard || !enforced)
goto error;
ctx = isl_ast_node_get_ctx(node);
graft = isl_calloc_type(ctx, isl_ast_graft);
if (!graft)
goto error;
space = isl_ast_build_get_space(build, 1);
graft->ref = 1;
graft->node = node;
graft->guard = isl_set_universe(isl_space_copy(space));
graft->enforced = isl_basic_set_universe(space);
if (!graft->guard || !graft->enforced)
return isl_ast_graft_free(graft);
graft->guard = guard;
graft->enforced = enforced;
return graft;
error:
isl_ast_node_free(node);
isl_set_free(guard);
isl_basic_set_free(enforced);
return NULL;
}
/* Create a graft for "node" with no guards and no enforced conditions.
*/
__isl_give isl_ast_graft *isl_ast_graft_alloc(
__isl_take isl_ast_node *node, __isl_keep isl_ast_build *build)
{
isl_space *space;
isl_set *guard;
isl_basic_set *enforced;
if (!node)
return NULL;
space = isl_ast_build_get_space(build, 1);
guard = isl_set_universe(isl_space_copy(space));
enforced = isl_basic_set_universe(space);
return graft_alloc(node, guard, enforced);
}
/* Create a graft with no guards and no enforced conditions
* encapsulating a call to the domain element specified by "executed".
* "executed" is assumed to be single-valued.
@@ -364,9 +385,7 @@ static __isl_give isl_ast_graft *insert_if_node(
return graft;
}
build = isl_ast_build_copy(build);
graft->node = ast_node_insert_if(graft->node, guard, build);
isl_ast_build_free(build);
if (!graft->node)
return isl_ast_graft_free(graft);
@@ -1443,6 +1462,25 @@ __isl_give isl_ast_graft_list *isl_ast_graft_list_group_on_guard(
return list;
}
/* An enumeration of the keys that appear in the textual representation
* of an isl_sat_graft object.
*/
enum isl_graft_key {
isl_graft_key_error = -1,
isl_graft_key_guard,
isl_graft_key_enforced,
isl_graft_key_node,
isl_graft_key_end
};
/* Textual representations of the keys for an isl_sat_graft object.
*/
static char *key_str[] = {
[isl_graft_key_guard] = "guard",
[isl_graft_key_enforced] = "enforced",
[isl_graft_key_node] = "node",
};
__isl_give isl_printer *isl_printer_print_ast_graft(__isl_take isl_printer *p,
__isl_keep isl_ast_graft *graft)
{
@@ -1452,15 +1490,91 @@ __isl_give isl_printer *isl_printer_print_ast_graft(__isl_take isl_printer *p,
return isl_printer_free(p);
p = isl_printer_print_str(p, "(");
p = isl_printer_print_str(p, "guard: ");
p = isl_printer_print_str(p, key_str[isl_graft_key_guard]);
p = isl_printer_print_str(p, ": ");
p = isl_printer_print_set(p, graft->guard);
p = isl_printer_print_str(p, ", ");
p = isl_printer_print_str(p, "enforced: ");
p = isl_printer_print_str(p, key_str[isl_graft_key_enforced]);
p = isl_printer_print_str(p, ": ");
p = isl_printer_print_basic_set(p, graft->enforced);
p = isl_printer_print_str(p, ", ");
p = isl_printer_print_str(p, "node: ");
p = isl_printer_print_str(p, key_str[isl_graft_key_node]);
p = isl_printer_print_str(p, ": ");
p = isl_printer_print_ast_node(p, graft->node);
p = isl_printer_print_str(p, ")");
return p;
}
#undef KEY
#define KEY enum isl_graft_key
#undef KEY_ERROR
#define KEY_ERROR isl_graft_key_error
#undef KEY_END
#define KEY_END isl_graft_key_end
#undef KEY_STR
#define KEY_STR key_str
#undef KEY_EXTRACT
#define KEY_EXTRACT extract_key
#undef KEY_GET
#define KEY_GET get_key
#include "extract_key.c"
/* Read the key "key" from "s", along with the subsequent colon.
*/
static isl_stat read_key(__isl_keep isl_stream *s, enum isl_graft_key key)
{
enum isl_graft_key extracted;
extracted = get_key(s);
if (extracted < 0)
return isl_stat_error;
if (extracted != key)
isl_die(isl_stream_get_ctx(s), isl_error_invalid,
"expecting different field", return isl_stat_error);
if (isl_stream_eat(s, ':') < 0)
return isl_stat_error;
return isl_stat_ok;
}
/* Read an isl_ast_graft object from "s".
*
* Read the pieces in the way they are printed in isl_printer_print_ast_graft.
*/
static __isl_give isl_ast_graft *isl_stream_read_ast_graft(
__isl_keep isl_stream *s)
{
isl_set *guard;
isl_basic_set *enforced = NULL;
isl_ast_node *node = NULL;
if (isl_stream_eat(s, '(') < 0)
return NULL;
if (read_key(s, isl_graft_key_guard) < 0)
return NULL;
guard = isl_stream_read_set(s);
if (!guard)
goto error;
if (isl_stream_eat(s, ',') < 0)
goto error;
if (read_key(s, isl_graft_key_enforced) < 0)
goto error;
enforced = isl_stream_read_basic_set(s);
if (!enforced)
goto error;
if (isl_stream_eat(s, ',') < 0)
goto error;
if (read_key(s, isl_graft_key_node) < 0)
goto error;
node = isl_stream_read_ast_node(s);
if (!node)
goto error;
if (isl_stream_eat(s, ')') < 0)
goto error;
return graft_alloc(node, guard, enforced);
error:
isl_set_free(guard);
isl_basic_set_free(enforced);
isl_ast_node_free(node);
return NULL;
}

View File

@@ -6,6 +6,7 @@
#include <isl/set.h>
#include <isl/list.h>
#include <isl/printer.h>
#include <isl/stream.h>
struct isl_ast_graft;
typedef struct isl_ast_graft isl_ast_graft;
@@ -102,4 +103,6 @@ __isl_give isl_ast_graft_list *isl_ast_graft_list_gist_guards(
__isl_give isl_printer *isl_printer_print_ast_graft(__isl_take isl_printer *p,
__isl_keep isl_ast_graft *graft);
__isl_give isl_ast_graft_list *isl_stream_read_ast_graft_list(isl_stream *s);
#endif

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2012 Ecole Normale Superieure
*
* Use of this software is governed by the MIT license
*
* Written by Sven Verdoolaege,
* Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
*/
#define xFN(TYPE,NAME) TYPE ## _ ## NAME
#define FN(TYPE,NAME) xFN(TYPE,NAME)
/* Replace the field FIELD of "node" by "field",
* where the field may or may not have already been set in "node".
* However, if the field has not already been set,
* then "node" is required to have a single reference.
* In this case the call to isl_ast_node_cow has no effect.
*/
__isl_give isl_ast_node *FN(FN(FN(isl_ast_node,NODE_TYPE),set),FIELD_NAME)(
__isl_take isl_ast_node *node, __isl_take FIELD_TYPE *field)
{
if (FN(isl_ast_node_check,NODE_TYPE)(node) < 0 || !field)
goto error;
if (node->FIELD == field) {
FN(FIELD_TYPE,free)(field);
return node;
}
node = isl_ast_node_cow(node);
if (!node)
goto error;
FN(FIELD_TYPE,free)(node->FIELD);
node->FIELD = field;
return node;
error:
isl_ast_node_free(node);
FN(FIELD_TYPE,free)(field);
return NULL;
}

View File

@@ -7,6 +7,12 @@
#include <isl/map.h>
#include <isl/vec.h>
#include <isl/list.h>
#include <isl/stream.h>
#undef EL
#define EL isl_ast_expr
#include <isl_list_templ.h>
/* An expression is either an integer, an identifier or an operation
* with zero or more arguments.
@@ -23,24 +29,22 @@ struct isl_ast_expr {
isl_id *id;
struct {
enum isl_ast_expr_op_type op;
unsigned n_arg;
isl_ast_expr **args;
isl_ast_expr_list *args;
} op;
} u;
};
#undef EL
#define EL isl_ast_expr
#include <isl_list_templ.h>
__isl_give isl_ast_expr *isl_ast_expr_alloc_int_si(isl_ctx *ctx, int i);
__isl_give isl_ast_expr *isl_ast_expr_alloc_op(isl_ctx *ctx,
enum isl_ast_expr_op_type op, int n_arg);
__isl_give isl_ast_expr *isl_ast_expr_op_add_arg(__isl_take isl_ast_expr *expr,
__isl_take isl_ast_expr *arg);
__isl_give isl_ast_expr *isl_ast_expr_alloc_binary(
enum isl_ast_expr_op_type type,
__isl_take isl_ast_expr *expr1, __isl_take isl_ast_expr *expr2);
__isl_give isl_ast_expr *isl_stream_read_ast_expr(__isl_keep isl_stream *s);
#undef EL
#define EL isl_ast_node
@@ -96,11 +100,19 @@ __isl_give isl_ast_node *isl_ast_node_alloc_mark(__isl_take isl_id *id,
__isl_take isl_ast_node *node);
__isl_give isl_ast_node *isl_ast_node_from_ast_node_list(
__isl_take isl_ast_node_list *list);
__isl_give isl_ast_node *isl_ast_node_for_set_init(
__isl_take isl_ast_node *node, __isl_take isl_ast_expr *init);
__isl_give isl_ast_node *isl_ast_node_for_set_cond(
__isl_take isl_ast_node *node, __isl_take isl_ast_expr *init);
__isl_give isl_ast_node *isl_ast_node_for_set_inc(
__isl_take isl_ast_node *node, __isl_take isl_ast_expr *init);
__isl_give isl_ast_node *isl_ast_node_for_set_body(
__isl_take isl_ast_node *node, __isl_take isl_ast_node *body);
__isl_give isl_ast_node *isl_ast_node_if_set_then(
__isl_take isl_ast_node *node, __isl_take isl_ast_node *child);
__isl_give isl_ast_node *isl_stream_read_ast_node(__isl_keep isl_stream *s);
struct isl_ast_print_options {
int ref;
isl_ctx *ctx;

View File

@@ -409,6 +409,24 @@ __isl_give isl_fixed_box *isl_map_get_range_simple_fixed_box_hull(
return box;
}
/* Compute a fixed box from "set" using "map_box" by treating it as a map
* with a zero-dimensional domain and
* project out the domain again from the result.
*/
static __isl_give isl_fixed_box *fixed_box_as_map(__isl_keep isl_set *set,
__isl_give isl_fixed_box *(*map_box)(__isl_keep isl_map *map))
{
isl_map *map;
isl_fixed_box *box;
map = isl_map_from_range(isl_set_copy(set));
box = map_box(map);
isl_map_free(map);
box = isl_fixed_box_project_domain_on_params(box);
return box;
}
/* Try and construct a fixed-size rectangular box with an offset
* in terms of the parameters of "set" that contains "set".
* If no such box can be constructed, then return an invalidated box,
@@ -421,15 +439,7 @@ __isl_give isl_fixed_box *isl_map_get_range_simple_fixed_box_hull(
__isl_give isl_fixed_box *isl_set_get_simple_fixed_box_hull(
__isl_keep isl_set *set)
{
isl_map *map;
isl_fixed_box *box;
map = isl_map_from_range(isl_set_copy(set));
box = isl_map_get_range_simple_fixed_box_hull(map);
isl_map_free(map);
box = isl_fixed_box_project_domain_on_params(box);
return box;
return fixed_box_as_map(set, &isl_map_get_range_simple_fixed_box_hull);
}
/* Check whether the output elements lie on a rectangular lattice,
@@ -474,6 +484,20 @@ __isl_give isl_fixed_box *isl_map_get_range_lattice_tile(
return box;
}
/* Check whether the elements lie on a rectangular lattice,
* possibly depending on the parameters.
* Return a tile in this lattice.
* If no stride information can be found, then return a tile of size 1
* (and offset 0).
*
* Consider the set as a map with a zero-dimensional domain and
* obtain a lattice tile of that map.
*/
__isl_give isl_fixed_box *isl_set_get_lattice_tile(__isl_keep isl_set *set)
{
return fixed_box_as_map(set, &isl_map_get_range_lattice_tile);
}
#undef BASE
#define BASE multi_val
#include "print_yaml_field_templ.c"

View File

@@ -1554,6 +1554,8 @@ static isl_stat add_selected_wraps_around_facet(struct isl_wraps *wraps,
if (isl_tab_detect_redundant(info->tab) < 0)
return isl_stat_error;
if (info->tab->empty) {
if (isl_tab_rollback(info->tab, snap) < 0)
return isl_stat_error;
if (!add_valid)
return wraps_mark_failed(wraps);
return isl_stat_ok;
@@ -3178,7 +3180,7 @@ static isl_stat tab_insert_divs(struct isl_coalesce_info *info,
return isl_stat_error;
info->bmap = isl_basic_map_cow(info->bmap);
info->bmap = isl_basic_map_free_inequality(info->bmap, 2 * n);
if (info->bmap < 0)
if (!info->bmap)
return isl_stat_error;
return fix_constant_divs(info, n, expanded);

View File

@@ -291,7 +291,7 @@ void isl_ctx_free(struct isl_ctx *ctx)
return;
if (ctx->ref != 0)
isl_die(ctx, isl_error_invalid,
"isl_ctx freed, but some objects still reference it",
"isl_ctx not freed as some objects still reference it",
return);
if (ctx->opt->print_stats)

View File

@@ -243,7 +243,7 @@ __isl_give isl_dim_map *isl_dim_map_from_reordering(
if (!dim_map)
return NULL;
for (i = 0; i < exp->len; ++i) {
for (i = 0; i < exp->src_len; ++i) {
dim_map->m[1 + exp->pos[i]].pos = 1 + i;
dim_map->m[1 + exp->pos[i]].sgn = 1;
}

View File

@@ -1873,6 +1873,12 @@ __isl_give char *isl_union_access_info_to_str(
#define KEY_ERROR isl_ai_key_error
#undef KEY_END
#define KEY_END isl_ai_key_end
#undef KEY_STR
#define KEY_STR key_str
#undef KEY_EXTRACT
#define KEY_EXTRACT extract_key
#undef KEY_GET
#define KEY_GET get_key
#include "extract_key.c"
#undef BASE
@@ -1893,17 +1899,18 @@ __isl_give isl_union_access_info *isl_stream_read_union_access_info(
{
isl_ctx *ctx;
isl_union_access_info *info;
int more;
isl_bool more;
int sink_set = 0;
int schedule_set = 0;
if (isl_stream_yaml_read_start_mapping(s))
if (isl_stream_yaml_read_start_mapping(s) < 0)
return NULL;
ctx = isl_stream_get_ctx(s);
info = isl_union_access_info_alloc(ctx);
while ((more = isl_stream_yaml_next(s)) > 0) {
while ((more = isl_stream_yaml_next(s)) == isl_bool_true) {
enum isl_ai_key key;
enum isl_access_type type;
isl_union_map *access, *schedule_map;
isl_schedule *schedule;
@@ -1919,8 +1926,9 @@ __isl_give isl_union_access_info *isl_stream_read_union_access_info(
case isl_ai_key_must_source:
case isl_ai_key_may_source:
case isl_ai_key_kill:
type = (enum isl_access_type) key;
access = read_union_map(s);
info = isl_union_access_info_set(info, key, access);
info = isl_union_access_info_set(info, type, access);
if (!info)
return NULL;
break;
@@ -1945,10 +1953,8 @@ __isl_give isl_union_access_info *isl_stream_read_union_access_info(
if (more < 0)
return isl_union_access_info_free(info);
if (isl_stream_yaml_read_end_mapping(s) < 0) {
isl_stream_error(s, NULL, "unexpected extra elements");
if (isl_stream_yaml_read_end_mapping(s) < 0)
return isl_union_access_info_free(info);
}
if (!sink_set) {
isl_stream_error(s, NULL, "no sink specified");

View File

@@ -951,7 +951,10 @@ static __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_zero_in_space(
#define DEFAULT_IS_ZERO 1
#include <isl_pw_templ.c>
#include <isl_pw_add_disjoint_templ.c>
#include <isl_pw_eval.c>
#include <isl_pw_fix_templ.c>
#include <isl_pw_from_range_templ.c>
#include <isl_pw_insert_dims_templ.c>
#include <isl_pw_lift_templ.c>
#include <isl_pw_morph_templ.c>
@@ -961,8 +964,6 @@ static __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_zero_in_space(
#undef BASE
#define BASE pw_qpolynomial_fold
#define NO_SUB
#include <isl_union_single.c>
#include <isl_union_eval.c>

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2013 Ecole Normale Superieure
*
* Use of this software is governed by the MIT license
*
* Written by Sven Verdoolaege,
* Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
*/
/* Convert an object defined over a parameter domain
* into one that is defined over a zero-dimensional set.
*/
__isl_give TYPE *FN(TYPE,from_range)(__isl_take TYPE *obj)
{
isl_space *space;
if (!obj)
return NULL;
if (!isl_space_is_set(FN(TYPE,peek_space)(obj)))
isl_die(FN(TYPE,get_ctx)(obj), isl_error_invalid,
"not living in a set space",
return FN(TYPE,free)(obj));
space = FN(TYPE,get_space)(obj);
space = isl_space_from_range(space);
obj = FN(TYPE,reset_space)(obj, space);
return obj;
}

View File

@@ -8,7 +8,7 @@
*/
#include <stdlib.h>
#include <isl/hash.h>
#include <isl_hash_private.h>
#include <isl/ctx.h>
#include "isl_config.h"
@@ -192,6 +192,26 @@ struct isl_hash_table_entry *isl_hash_table_find(struct isl_ctx *ctx,
return &table->entries[h];
}
/* Return the first entry containing data in "table".
* Return isl_hash_table_entry_none is there is no such entry and
* NULL on error.
*/
struct isl_hash_table_entry *isl_hash_table_first(struct isl_hash_table *table)
{
size_t size;
uint32_t h;
if (!table->entries)
return NULL;
size = 1 << table->bits;
for (h = 0; h < size; ++ h)
if (table->entries[h].data)
return &table->entries[h];
return isl_hash_table_entry_none;
}
isl_stat isl_hash_table_foreach(isl_ctx *ctx, struct isl_hash_table *table,
isl_stat (*fn)(void **entry, void *user), void *user)
{
@@ -210,6 +230,31 @@ isl_stat isl_hash_table_foreach(isl_ctx *ctx, struct isl_hash_table *table,
return isl_stat_ok;
}
/* Does "test" succeed on every (non-empty) entry of "table"?
*/
isl_bool isl_hash_table_every(isl_ctx *ctx, struct isl_hash_table *table,
isl_bool (*test)(void **entry, void *user), void *user)
{
size_t size;
uint32_t h;
if (!table->entries)
return isl_bool_error;
size = 1 << table->bits;
for (h = 0; h < size; ++ h) {
isl_bool r;
if (!table->entries[h].data)
continue;
r = test(&table->entries[h].data, user);
if (r < 0 || !r)
return r;
}
return isl_bool_true;
}
void isl_hash_table_remove(struct isl_ctx *ctx,
struct isl_hash_table *table,
struct isl_hash_table_entry *entry)

View File

@@ -0,0 +1,8 @@
#ifndef ISL_HASH_PRIVATE_H
#define ISL_HASH_PRIVATE_H
#include <isl/hash.h>
struct isl_hash_table_entry *isl_hash_table_first(struct isl_hash_table *table);
#endif

View File

@@ -191,6 +191,16 @@ __isl_give isl_id *isl_id_set_free_user(__isl_take isl_id *id,
return id;
}
/* Retrieve the callback set by isl_id_set_free_user,
* or NULL if no such callback was set.
*/
void (*isl_id_get_free_user(__isl_keep isl_id *id))(void *user)
{
if (!id)
return NULL;
return id->free_user;
}
/* If the id has a negative refcount, then it is a static isl_id
* and should not be freed.
*/
@@ -273,18 +283,9 @@ __isl_give isl_id *isl_stream_read_id(__isl_keep isl_stream *s)
return id;
}
/* Read an isl_id object from the string "str".
*/
__isl_give isl_id *isl_id_read_from_str(isl_ctx *ctx, const char *str)
{
isl_id *id;
isl_stream *s = isl_stream_new_str(ctx, str);
if (!s)
return NULL;
id = isl_stream_read_id(s);
isl_stream_free(s);
return id;
}
#undef TYPE_BASE
#define TYPE_BASE id
#include "isl_read_from_str_templ.c"
/* Is "id1" (obviously) equal to "id2"?
*

View File

@@ -36,7 +36,6 @@ struct isl_id {
uint32_t isl_hash_id(uint32_t hash, __isl_keep isl_id *id);
int isl_id_cmp(__isl_keep isl_id *id1, __isl_keep isl_id *id2);
__isl_give isl_id *isl_stream_read_id(__isl_keep isl_stream *s);
extern isl_id isl_id_none;

View File

@@ -1,6 +1,7 @@
#include <isl/id_to_ast_expr.h>
#include <isl/id.h>
#include <isl/ast.h>
#include "isl_ast_private.h"
#define isl_id_is_equal(id1,id2) isl_bool_ok(id1 == id2)
@@ -8,9 +9,13 @@
#define ISL_VAL isl_ast_expr
#define ISL_HMAP_SUFFIX id_to_ast_expr
#define ISL_HMAP isl_id_to_ast_expr
#define ISL_HMAP_IS_EQUAL isl_id_to_ast_expr_is_equal
#define ISL_KEY_IS_EQUAL isl_id_is_equal
#define ISL_VAL_IS_EQUAL isl_ast_expr_is_equal
#define ISL_KEY_PRINT isl_printer_print_id
#define ISL_VAL_PRINT isl_printer_print_ast_expr
#define ISL_HMAP_HAVE_READ_FROM_STR
#define ISL_KEY_READ isl_stream_read_id
#define ISL_VAL_READ isl_stream_read_ast_expr
#include <isl/hmap_templ.c>

View File

@@ -8,9 +8,13 @@
#define ISL_VAL isl_id
#define ISL_HMAP_SUFFIX id_to_id
#define ISL_HMAP isl_id_to_id
#define ISL_HMAP_IS_EQUAL isl_id_to_id_is_equal
#define ISL_KEY_IS_EQUAL isl_id_is_equal
#define ISL_VAL_IS_EQUAL isl_id_is_equal
#define ISL_KEY_PRINT isl_printer_print_id
#define ISL_VAL_PRINT isl_printer_print_id
#define ISL_HMAP_HAVE_READ_FROM_STR
#define ISL_KEY_READ isl_stream_read_id
#define ISL_VAL_READ isl_stream_read_id
#include <isl/hmap_templ.c>

View File

@@ -1,6 +1,7 @@
#include <isl/id_to_pw_aff.h>
#include <isl/id.h>
#include <isl/aff.h>
#include "isl_aff_private.h"
#define isl_id_is_equal(id1,id2) isl_bool_ok(id1 == id2)
@@ -8,9 +9,13 @@
#define ISL_VAL isl_pw_aff
#define ISL_HMAP_SUFFIX id_to_pw_aff
#define ISL_HMAP isl_id_to_pw_aff
#define ISL_HMAP_IS_EQUAL isl_id_to_pw_aff_plain_is_equal
#define ISL_KEY_IS_EQUAL isl_id_is_equal
#define ISL_VAL_IS_EQUAL isl_pw_aff_plain_is_equal
#define ISL_KEY_PRINT isl_printer_print_id
#define ISL_VAL_PRINT isl_printer_print_pw_aff
#define ISL_HMAP_HAVE_READ_FROM_STR
#define ISL_KEY_READ isl_stream_read_id
#define ISL_VAL_READ isl_stream_read_pw_aff
#include <isl/hmap_templ.c>

View File

@@ -695,6 +695,10 @@ static __isl_give isl_val *isl_pw_aff_opt_val(__isl_take isl_pw_aff *pa,
return data.res;
}
#undef TYPE
#define TYPE isl_pw_aff
#include "isl_ilp_opt_fn_val_templ.c"
#undef TYPE
#define TYPE isl_pw_multi_aff
#include "isl_ilp_opt_multi_val_templ.c"
@@ -752,27 +756,9 @@ static __isl_give isl_val *isl_union_pw_aff_opt_val(
return data.res;
}
/* Return the minimum of the integer piecewise affine
* expression "upa" over its definition domain.
*
* Return negative infinity if the optimal value is unbounded and
* NaN if the domain of the expression is empty.
*/
__isl_give isl_val *isl_union_pw_aff_min_val(__isl_take isl_union_pw_aff *upa)
{
return isl_union_pw_aff_opt_val(upa, 0);
}
/* Return the maximum of the integer piecewise affine
* expression "upa" over its definition domain.
*
* Return infinity if the optimal value is unbounded and
* NaN if the domain of the expression is empty.
*/
__isl_give isl_val *isl_union_pw_aff_max_val(__isl_take isl_union_pw_aff *upa)
{
return isl_union_pw_aff_opt_val(upa, 1);
}
#undef TYPE
#define TYPE isl_union_pw_aff
#include "isl_ilp_opt_fn_val_templ.c"
/* Return a list of minima (maxima if "max" is set)
* for each of the expressions in "mupa" over their domains.

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2018 Sven Verdoolaege
*
* Use of this software is governed by the MIT license
*
* Written by Sven Verdoolaege.
*/
#define xFN(TYPE,NAME) TYPE ## _ ## NAME
#define FN(TYPE,NAME) xFN(TYPE,NAME)
/* Return the minimum of the integer piecewise affine
* expression "f" over its definition domain.
*
* Return negative infinity if the optimal value is unbounded and
* NaN if the domain of the expression is empty.
*/
__isl_give isl_val *FN(TYPE,min_val)(__isl_take TYPE *f)
{
return FN(TYPE,opt_val)(f, 0);
}
/* Return the maximum of the integer piecewise affine
* expression "f" over its definition domain.
*
* Return infinity if the optimal value is unbounded and
* NaN if the domain of the expression is empty.
*/
__isl_give isl_val *FN(TYPE,max_val)(__isl_take TYPE *f)
{
return FN(TYPE,opt_val)(f, 1);
}

File diff suppressed because it is too large Load Diff

View File

@@ -868,6 +868,7 @@ inline void isl_sioimath_tdiv_q(isl_sioimath_ptr dst, isl_sioimath_src lhs,
isl_sioimath_bigarg_src(rhs, &rhsscratch),
isl_sioimath_reinit_big(dst), NULL);
isl_sioimath_try_demote(dst);
return;
}
/* Divide lhs by an unsigned long rhs, rounding to zero (Truncate).

View File

@@ -16,7 +16,7 @@
* In particular, the elements are separated by a comma and
* the entire list is surrounded by parentheses.
*/
static __isl_give LIST(EL) *FN(isl_stream_read,LIST(EL_BASE))(isl_stream *s)
__isl_give LIST(EL) *FN(isl_stream_read,LIST(EL_BASE))(isl_stream *s)
{
isl_ctx *ctx;
LIST(EL) *list;
@@ -44,22 +44,6 @@ static __isl_give LIST(EL) *FN(isl_stream_read,LIST(EL_BASE))(isl_stream *s)
return list;
}
/* Read a list of elements of type EL from the string "str".
* The input format corresponds to the way lists are printed
* by isl_printer_print_list_*.
* In particular, the elements are separated by a comma and
* the entire list is surrounded by parentheses.
*/
__isl_give LIST(EL) *FN(LIST(EL),read_from_str)(isl_ctx *ctx,
const char *str)
{
LIST(EL) *list;
isl_stream *s;
s = isl_stream_new_str(ctx, str);
if (!s)
return NULL;
list = FN(isl_stream_read,LIST(EL_BASE))(s);
isl_stream_free(s);
return list;
}
#undef TYPE_BASE
#define TYPE_BASE LIST(EL_BASE)
#include "isl_read_from_str_templ.c"

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2013 Ecole Normale Superieure
*
* Use of this software is governed by the MIT license
*
* Written by Sven Verdoolaege,
* Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
*/
#include <isl/stream.h>
#include <isl_list_macro.h>
/* Read a sequence of EL objects and return them as a list.
*/
static __isl_give LIST(EL) *FN(isl_stream_yaml_read,LIST(EL_BASE))(
isl_stream *s)
{
isl_ctx *ctx;
LIST(EL) *list;
isl_bool more;
ctx = isl_stream_get_ctx(s);
if (isl_stream_yaml_read_start_sequence(s) < 0)
return NULL;
list = FN(LIST(EL),alloc)(ctx, 0);
while ((more = isl_stream_yaml_next(s)) == isl_bool_true) {
EL *el;
el = FN(isl_stream_read,EL_BASE)(s);
list = FN(LIST(EL),add)(list, el);
}
if (more < 0 || isl_stream_yaml_read_end_sequence(s) < 0)
return FN(LIST(EL),free)(list);
return list;
}

View File

@@ -289,7 +289,7 @@ __isl_give EL *FN(FN(LIST(EL),get),EL_BASE)(__isl_keep LIST(EL) *list,
/* Replace the element at position "index" in "list" by "el".
*/
__isl_give LIST(EL) *FN(FN(LIST(EL),set),EL_BASE)(__isl_take LIST(EL) *list,
__isl_give LIST(EL) *FN(LIST(EL),set_at)(__isl_take LIST(EL) *list,
int index, __isl_take EL *el)
{
if (!list || !el)
@@ -312,6 +312,14 @@ error:
return NULL;
}
/* This is an alternative name for the function above.
*/
__isl_give LIST(EL) *FN(FN(LIST(EL),set),EL_BASE)(__isl_take LIST(EL) *list,
int index, __isl_take EL *el)
{
return FN(LIST(EL),set_at)(list, index, el);
}
/* Return the element at position "index" of "list".
* This may be either a copy or the element itself
* if there is only one reference to "list".

View File

@@ -1,6 +1,7 @@
/*
* Copyright 2011 INRIA Saclay
* Copyright 2014 Ecole Normale Superieure
* Copyright 2015 Sven Verdoolaege
*
* Use of this software is governed by the MIT license
*
@@ -38,6 +39,13 @@ __isl_give isl_local *isl_local_alloc_from_mat(__isl_take isl_mat *mat)
return mat;
}
/* Return a new reference to "local".
*/
__isl_give isl_local *isl_local_copy(__isl_keep isl_local *local)
{
return isl_local_alloc_from_mat(isl_mat_copy(local));
}
/* Free "local" and return NULL.
*/
__isl_null isl_local *isl_local_free(__isl_take isl_local *local)
@@ -222,6 +230,32 @@ int isl_local_cmp(__isl_keep isl_local *local1, __isl_keep isl_local *local2)
return 0;
}
/* Return the position of the variables of the given type
* within the sequence of variables of "local".
*
* Only the position of the local variables can be obtained.
* It is equal to the total number of variables minus
* the number of local variables.
*/
isl_size isl_local_var_offset(__isl_keep isl_local *local,
enum isl_dim_type type)
{
isl_size n_div, n_all;
if (!local)
return isl_size_error;
if (type != isl_dim_div)
isl_die(isl_local_get_ctx(local), isl_error_unsupported,
"only the offset of the local variables "
"can be obtained", return isl_size_error);
n_div = isl_local_dim(local, isl_dim_div);
n_all = isl_local_dim(local, isl_dim_all);
if (n_div < 0 || n_all < 0)
return isl_size_error;
return n_all - n_div;
}
/* Reorder the columns of the given local variables according to the
* given reordering.
* The order of the local variables themselves is assumed not to change.
@@ -231,19 +265,13 @@ __isl_give isl_local *isl_local_reorder(__isl_take isl_local *local,
{
isl_mat *div = local;
int i, j;
isl_size dim;
isl_space *space;
isl_mat *mat;
int extra;
if (!local || !r)
goto error;
space = isl_reordering_peek_space(r);
dim = isl_space_dim(space, isl_dim_all);
if (dim < 0)
goto error;
extra = dim + div->n_row - r->len;
extra = r->dst_len - r->src_len;
mat = isl_mat_alloc(div->ctx, div->n_row, div->n_col + extra);
if (!mat)
goto error;
@@ -251,7 +279,7 @@ __isl_give isl_local *isl_local_reorder(__isl_take isl_local *local,
for (i = 0; i < div->n_row; ++i) {
isl_seq_cpy(mat->row[i], div->row[i], 2);
isl_seq_clr(mat->row[i] + 2, mat->n_col - 2);
for (j = 0; j < r->len; ++j)
for (j = 0; j < r->src_len; ++j)
isl_int_set(mat->row[i][2 + r->pos[j]],
div->row[i][2 + j]);
}
@@ -265,6 +293,32 @@ error:
return NULL;
}
/* Move the "n" variables starting at "src_pos" of "local" to "dst_pos".
*
* Moving local variables is not allowed.
*/
__isl_give isl_local *isl_local_move_vars(__isl_take isl_local *local,
unsigned dst_pos, unsigned src_pos, unsigned n)
{
isl_mat *mat = local;
isl_size v_div;
v_div = isl_local_var_offset(local, isl_dim_div);
if (v_div < 0)
return isl_local_free(local);
if (n == 0)
return local;
if (dst_pos >= v_div || src_pos >= v_div)
isl_die(isl_local_get_ctx(local), isl_error_invalid,
"cannot move local variables",
return isl_local_free(local));
mat = isl_mat_move_cols(mat, 2 + dst_pos, 2 + src_pos, n);
return isl_local_alloc_from_mat(mat);
}
/* Extend a vector "v" representing an integer point
* in the domain space of "local"
* to one that also includes values for the local variables.

View File

@@ -6,6 +6,7 @@
typedef isl_mat isl_local;
__isl_give isl_local *isl_local_copy(__isl_keep isl_local *local);
__isl_null isl_local *isl_local_free(__isl_take isl_local *local);
isl_bool isl_local_div_is_marked_unknown(__isl_keep isl_local *local, int pos);
@@ -14,9 +15,15 @@ isl_bool isl_local_divs_known(__isl_keep isl_local *local);
int isl_local_cmp(__isl_keep isl_local *local1, __isl_keep isl_local *local2);
isl_size isl_local_var_offset(__isl_keep isl_local *local,
enum isl_dim_type type);
__isl_give isl_local *isl_local_reorder(__isl_take isl_local *local,
__isl_take isl_reordering *r);
__isl_give isl_local *isl_local_move_vars(__isl_take isl_local *local,
unsigned dst_pos, unsigned src_pos, unsigned n);
__isl_give isl_vec *isl_local_extend_point_vec(__isl_keep isl_local *local,
__isl_take isl_vec *v);

View File

@@ -245,22 +245,44 @@ isl_size isl_local_space_dim(__isl_keep isl_local_space *ls,
#define TYPE isl_local_space
#include "check_type_range_templ.c"
unsigned isl_local_space_offset(__isl_keep isl_local_space *ls,
/* Return the position of the variables of the given type
* within the sequence of variables of "ls".
*/
isl_size isl_local_space_var_offset(__isl_keep isl_local_space *ls,
enum isl_dim_type type)
{
isl_space *space;
space = isl_local_space_peek_space(ls);
if (space < 0)
return isl_size_error;
switch (type) {
case isl_dim_param:
case isl_dim_in:
case isl_dim_out: return isl_space_offset(space, type);
case isl_dim_div: return isl_space_dim(space, isl_dim_all);
case isl_dim_cst:
default:
isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
"invalid dimension type", return isl_size_error);
}
}
/* Return the position of the coefficients of the variables of the given type
* within the sequence of coefficients of "ls".
*/
unsigned isl_local_space_offset(__isl_keep isl_local_space *ls,
enum isl_dim_type type)
{
if (!ls)
return 0;
space = ls->dim;
switch (type) {
case isl_dim_cst: return 0;
case isl_dim_param: return 1;
case isl_dim_in: return 1 + space->nparam;
case isl_dim_out: return 1 + space->nparam + space->n_in;
case isl_dim_div:
return 1 + space->nparam + space->n_in + space->n_out;
case isl_dim_param:
case isl_dim_in:
case isl_dim_out:
case isl_dim_div: return 1 + isl_local_space_var_offset(ls, type);
default: return 0;
}
}
@@ -464,6 +486,66 @@ __isl_keep isl_local *isl_local_space_peek_local(__isl_keep isl_local_space *ls)
return ls ? ls->div : NULL;
}
/* Return a copy of the local variables of "ls".
*/
__isl_keep isl_local *isl_local_space_get_local(__isl_keep isl_local_space *ls)
{
return isl_local_copy(isl_local_space_peek_local(ls));
}
/* Return the local variables of "ls".
* This may be either a copy or the local variables itself
* if there is only one reference to "ls".
* This allows the local variables to be modified inplace
* if both the local space and its local variables have only a single reference.
* The caller is not allowed to modify "ls" between this call and
* the subsequent call to isl_local_space_restore_local.
* The only exception is that isl_local_space_free can be called instead.
*/
static __isl_give isl_local *isl_local_space_take_local(
__isl_keep isl_local_space *ls)
{
isl_local *local;
if (!ls)
return NULL;
if (ls->ref != 1)
return isl_local_space_get_local(ls);
local = ls->div;
ls->div = NULL;
return local;
}
/* Set the local variables of "ls" to "local",
* where the local variables of "ls" may be missing
* due to a preceding call to isl_local_space_take_local.
* However, in this case, "ls" only has a single reference and
* then the call to isl_local_space_cow has no effect.
*/
static __isl_give isl_local_space *isl_local_space_restore_local(
__isl_take isl_local_space *ls, __isl_take isl_local *local)
{
if (!ls || !local)
goto error;
if (ls->div == local) {
isl_local_free(local);
return ls;
}
ls = isl_local_space_cow(ls);
if (!ls)
goto error;
isl_local_free(ls->div);
ls->div = local;
return ls;
error:
isl_local_space_free(ls);
isl_local_free(local);
return NULL;
}
/* Replace the identifier of the tuple of type "type" by "id".
*/
__isl_give isl_local_space *isl_local_space_set_tuple_id(
@@ -551,22 +633,16 @@ error:
__isl_give isl_local_space *isl_local_space_realign(
__isl_take isl_local_space *ls, __isl_take isl_reordering *r)
{
ls = isl_local_space_cow(ls);
if (!ls || !r)
goto error;
isl_local *local;
ls->div = isl_local_reorder(ls->div, isl_reordering_copy(r));
if (!ls->div)
goto error;
local = isl_local_space_take_local(ls);
local = isl_local_reorder(local, isl_reordering_copy(r));
ls = isl_local_space_restore_local(ls, local);
ls = isl_local_space_reset_space(ls, isl_reordering_get_space(r));
isl_reordering_free(r);
return ls;
error:
isl_local_space_free(ls);
isl_reordering_free(r);
return NULL;
}
__isl_give isl_local_space *isl_local_space_add_div(
@@ -1557,6 +1633,9 @@ __isl_give isl_local_space *isl_local_space_move_dims(
enum isl_dim_type dst_type, unsigned dst_pos,
enum isl_dim_type src_type, unsigned src_pos, unsigned n)
{
isl_space *space;
isl_local *local;
isl_size v_src, v_dst;
unsigned g_dst_pos;
unsigned g_src_pos;
@@ -1584,21 +1663,23 @@ __isl_give isl_local_space *isl_local_space_move_dims(
"moving dims within the same type not supported",
return isl_local_space_free(ls));
ls = isl_local_space_cow(ls);
if (!ls)
return NULL;
g_src_pos = 1 + isl_local_space_offset(ls, src_type) + src_pos;
g_dst_pos = 1 + isl_local_space_offset(ls, dst_type) + dst_pos;
v_src = isl_local_space_var_offset(ls, src_type);
v_dst = isl_local_space_var_offset(ls, dst_type);
if (v_src < 0 || v_dst < 0)
return isl_local_space_free(ls);
g_src_pos = v_src + src_pos;
g_dst_pos = v_dst + dst_pos;
if (dst_type > src_type)
g_dst_pos -= n;
ls->div = isl_mat_move_cols(ls->div, g_dst_pos, g_src_pos, n);
if (!ls->div)
return isl_local_space_free(ls);
ls->dim = isl_space_move_dims(ls->dim, dst_type, dst_pos,
local = isl_local_space_take_local(ls);
local = isl_local_move_vars(local, g_dst_pos, g_src_pos, n);
ls = isl_local_space_restore_local(ls, local);
space = isl_local_space_take_space(ls);
space = isl_space_move_dims(space, dst_type, dst_pos,
src_type, src_pos, n);
if (!ls->dim)
return isl_local_space_free(ls);
ls = isl_local_space_restore_space(ls, space);
return ls;
}

View File

@@ -34,6 +34,8 @@ int isl_mat_cmp_div(__isl_keep isl_mat *div, int i, int j);
__isl_give isl_mat *isl_merge_divs(__isl_keep isl_mat *div1,
__isl_keep isl_mat *div2, int *exp1, int *exp2);
isl_size isl_local_space_var_offset(__isl_keep isl_local_space *ls,
enum isl_dim_type type);
unsigned isl_local_space_offset(__isl_keep isl_local_space *ls,
enum isl_dim_type type);

View File

@@ -22,7 +22,7 @@
#include <bset_to_bmap.c>
#include <set_to_map.c>
enum isl_lp_result isl_tab_solve_lp(__isl_keep isl_basic_map *bmap,
static enum isl_lp_result isl_tab_solve_lp(__isl_keep isl_basic_map *bmap,
int maximize, isl_int *f, isl_int denom, isl_int *opt,
isl_int *opt_denom, __isl_give isl_vec **sol)
{

View File

@@ -1464,14 +1464,7 @@ __isl_give isl_basic_set *isl_basic_set_dup(__isl_keep isl_basic_set *bset)
__isl_give isl_basic_set *isl_basic_set_copy(__isl_keep isl_basic_set *bset)
{
if (!bset)
return NULL;
if (ISL_F_ISSET(bset, ISL_BASIC_SET_FINAL)) {
bset->ref++;
return bset;
}
return isl_basic_set_dup(bset);
return bset_from_bmap(isl_basic_map_copy(bset_to_bmap(bset)));
}
__isl_give isl_set *isl_set_copy(__isl_keep isl_set *set)
@@ -4622,6 +4615,7 @@ error:
#undef TYPE
#define TYPE isl_map
#include "isl_project_out_all_params_templ.c"
#include "isl_project_out_param_templ.c"
/* Turn all the dimensions of type "type", except the "n" starting at "first"
* into existentially quantified variables.
@@ -4655,19 +4649,7 @@ __isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
__isl_give isl_set *isl_set_project_out_param_id(__isl_take isl_set *set,
__isl_take isl_id *id)
{
int pos;
if (!set || !id)
goto error;
pos = isl_set_find_dim_by_id(set, isl_dim_param, id);
isl_id_free(id);
if (pos < 0)
return set;
return isl_set_project_out(set, isl_dim_param, pos, 1);
error:
isl_set_free(set);
isl_id_free(id);
return NULL;
return set_from_map(isl_map_project_out_param_id(set_to_map(set), id));
}
/* If "set" involves any of the parameters with identifiers in "list",
@@ -4676,25 +4658,11 @@ error:
__isl_give isl_set *isl_set_project_out_param_id_list(__isl_take isl_set *set,
__isl_take isl_id_list *list)
{
int i;
isl_size n;
isl_map *map;
n = isl_id_list_size(list);
if (n < 0)
goto error;
for (i = 0; i < n; ++i) {
isl_id *id;
id = isl_id_list_get_at(list, i);
set = isl_set_project_out_param_id(set, id);
}
isl_id_list_free(list);
return set;
error:
isl_id_list_free(list);
isl_set_free(set);
return NULL;
map = set_to_map(set);
map = isl_map_project_out_param_id_list(map, list);
return set_from_map(map);
}
/* Project out all parameters from "set" by existentially quantifying
@@ -8587,6 +8555,46 @@ __isl_give isl_set *isl_set_intersect_factor_range(__isl_take isl_set *set,
set_to_map(range), &control));
}
/* Given a map "map" in a space [A -> B] -> C and a set "domain"
* in the space A, return the intersection.
*
* The set "domain" is extended to a set living in the space [A -> B] and
* the domain of "map" is intersected with this set.
*/
__isl_give isl_map *isl_map_intersect_domain_wrapped_domain(
__isl_take isl_map *map, __isl_take isl_set *domain)
{
isl_space *space;
isl_set *factor;
isl_map_align_params_set(&map, &domain);
space = isl_map_get_space(map);
space = isl_space_domain_wrapped_range(space);
factor = isl_set_universe(space);
domain = isl_set_product(domain, factor);
return isl_map_intersect_domain(map, domain);
}
/* Given a map "map" in a space A -> [B -> C] and a set "domain"
* in the space B, return the intersection.
*
* The set "domain" is extended to a set living in the space [B -> C] and
* the range of "map" is intersected with this set.
*/
__isl_give isl_map *isl_map_intersect_range_wrapped_domain(
__isl_take isl_map *map, __isl_take isl_set *domain)
{
isl_space *space;
isl_set *factor;
isl_map_align_params_set(&map, &domain);
space = isl_map_get_space(map);
space = isl_space_range_wrapped_range(space);
factor = isl_set_universe(space);
domain = isl_set_product(domain, factor);
return isl_map_intersect_range(map, domain);
}
__isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
__isl_take isl_map *map2)
{
@@ -10361,6 +10369,18 @@ int isl_basic_map_plain_cmp(__isl_keep isl_basic_map *bmap1,
return cmp;
}
for (i = 0; i < bmap1->n_div; ++i) {
isl_bool unknown1, unknown2;
unknown1 = isl_basic_map_div_is_marked_unknown(bmap1, i);
unknown2 = isl_basic_map_div_is_marked_unknown(bmap2, i);
if (unknown1 < 0 || unknown2 < 0)
return -1;
if (unknown1 && unknown2)
continue;
if (unknown1)
return 1;
if (unknown2)
return -1;
cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
if (cmp)
return cmp;
@@ -12469,10 +12489,11 @@ __isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
if (aligned < 0)
goto error;
if (!aligned) {
isl_space *space;
isl_reordering *exp;
exp = isl_parameter_alignment_reordering(map->dim, model);
exp = isl_reordering_extend_space(exp, isl_map_get_space(map));
space = isl_map_peek_space(map);
exp = isl_parameter_alignment_reordering(space, model);
map = isl_map_realign(map, exp);
}
@@ -12498,6 +12519,7 @@ __isl_give isl_basic_map *isl_basic_map_align_params(
{
isl_ctx *ctx;
isl_bool equal_params;
isl_space *bmap_space;
if (!bmap || !model)
goto error;
@@ -12508,16 +12530,15 @@ __isl_give isl_basic_map *isl_basic_map_align_params(
"model has unnamed parameters", goto error);
if (isl_basic_map_check_named_params(bmap) < 0)
goto error;
equal_params = isl_space_has_equal_params(bmap->dim, model);
bmap_space = isl_basic_map_peek_space(bmap);
equal_params = isl_space_has_equal_params(bmap_space, model);
if (equal_params < 0)
goto error;
if (!equal_params) {
isl_reordering *exp;
struct isl_dim_map *dim_map;
exp = isl_parameter_alignment_reordering(bmap->dim, model);
exp = isl_reordering_extend_space(exp,
isl_basic_map_get_space(bmap));
exp = isl_parameter_alignment_reordering(bmap_space, model);
dim_map = isl_dim_map_from_reordering(exp);
bmap = isl_basic_map_realign(bmap,
isl_reordering_get_space(exp),

View File

@@ -1198,7 +1198,7 @@ static isl_bool better_div_constraint(__isl_keep isl_basic_map *bmap,
* a "better" expression for a div for which we already have an expression.
* "sum" is the sum of the constant terms of the constraints.
* If this sum is strictly smaller than the coefficient of one
* of the divs, then this pair can be used define the div.
* of the divs, then this pair can be used to define the div.
* To avoid the introduction of circular definitions of divs, we
* do not use the pair if the resulting expression would refer to
* any other undefined divs or if any known div is defined in

View File

@@ -235,8 +235,8 @@ static int tab_freeze_constraints(struct isl_tab *tab)
}
/* Check for redundant constraints starting at offset.
* Put the indices of the redundant constraints in index
* and return the number of redundant constraints.
* Put the indices of the non-redundant constraints in index
* and return the number of non-redundant constraints.
*/
static int n_non_redundant(isl_ctx *ctx, struct isl_tab *tab,
int offset, int **index)

View File

@@ -6,9 +6,13 @@
#define ISL_VAL isl_basic_set
#define ISL_HMAP_SUFFIX map_to_basic_set
#define ISL_HMAP isl_map_to_basic_set
#define ISL_HMAP_IS_EQUAL isl_map_to_basic_set_plain_is_equal
#define ISL_KEY_IS_EQUAL isl_map_plain_is_equal
#define ISL_VAL_IS_EQUAL isl_basic_set_plain_is_equal
#define ISL_KEY_PRINT isl_printer_print_map
#define ISL_VAL_PRINT isl_printer_print_basic_set
#define ISL_HMAP_HAVE_READ_FROM_STR
#define ISL_KEY_READ isl_stream_read_map
#define ISL_VAL_READ isl_stream_read_basic_set
#include <isl/hmap_templ.c>

View File

@@ -15,31 +15,16 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),add_constant_val)(
__isl_take MULTI(BASE) *multi, __isl_take isl_val *v)
{
isl_bool zero;
isl_size n;
int i;
zero = isl_val_is_zero(v);
n = FN(MULTI(BASE),size)(multi);
if (zero < 0 || n < 0)
if (zero < 0)
goto error;
if (zero || n == 0) {
if (zero) {
isl_val_free(v);
return multi;
}
multi = FN(MULTI(BASE),cow)(multi);
if (!multi)
goto error;
for (i = 0; i < n; ++i) {
multi->u.p[i] = FN(EL,add_constant_val)(multi->u.p[i],
isl_val_copy(v));
if (!multi->u.p[i])
goto error;
}
isl_val_free(v);
return multi;
return FN(MULTI(BASE),fn_val)(multi, &FN(EL,add_constant_val), v);
error:
FN(MULTI(BASE),free)(multi);
isl_val_free(v);
@@ -52,40 +37,19 @@ error:
__isl_give MULTI(BASE) *FN(MULTI(BASE),add_constant_multi_val)(
__isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
{
isl_space *multi_space, *mv_space;
isl_bool zero, equal;
isl_size n;
int i;
isl_bool zero;
zero = isl_multi_val_is_zero(mv);
n = FN(MULTI(BASE),size)(multi);
multi_space = FN(MULTI(BASE),peek_space)(multi);
mv_space = isl_multi_val_peek_space(mv);
equal = isl_space_tuple_is_equal(multi_space, isl_dim_out,
mv_space, isl_dim_out);
if (zero < 0 || n < 0 || equal < 0)
if (zero < 0)
goto error;
if (!equal)
isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
"spaces don't match", goto error);
if (zero || n == 0) {
if (zero) {
isl_multi_val_free(mv);
return multi;
}
multi = FN(MULTI(BASE),cow)(multi);
if (!multi)
goto error;
return FN(MULTI(BASE),fn_multi_val)(multi, &FN(EL,add_constant_val),
mv);
for (i = 0; i < n; ++i) {
isl_val *v = isl_multi_val_get_at(mv, i);
multi->u.p[i] = FN(EL,add_constant_val)(multi->u.p[i], v);
if (!multi->u.p[i])
goto error;
}
isl_multi_val_free(mv);
return multi;
error:
FN(MULTI(BASE),free)(multi);
isl_multi_val_free(mv);

View File

@@ -19,24 +19,19 @@ __isl_give MULTI(BASE) *FN(FN(MULTI(BASE),apply_aligned),APPLY_DOMBASE)(
__isl_take MULTI(BASE) *multi, __isl_take APPLY_DOM *set,
__isl_give EL *(*fn)(EL *el, __isl_take APPLY_DOM *set))
{
isl_size n;
int i;
if (!multi || !set)
n = FN(MULTI(BASE),size)(multi);
if (n < 0 || !set)
goto error;
if (multi->n == 0) {
FN(APPLY_DOM,free)(set);
return multi;
}
for (i = 0; i < n; ++i) {
EL *el;
multi = FN(MULTI(BASE),cow)(multi);
if (!multi)
goto error;
for (i = 0; i < multi->n; ++i) {
multi->u.p[i] = fn(multi->u.p[i], FN(APPLY_DOM,copy)(set));
if (!multi->u.p[i])
goto error;
el = FN(MULTI(BASE),take_at)(multi, i);
el = fn(el, FN(APPLY_DOM,copy)(set));
multi = FN(MULTI(BASE),restore_at)(multi, i, el);
}
FN(APPLY_DOM,free)(set);

View File

@@ -29,13 +29,13 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),sub)(__isl_take MULTI(BASE) *multi1,
return FN(MULTI(BASE),bin_op)(multi1, multi2, &FN(EL,sub));
}
/* Multiply the elements of "multi" by "v" and return the result.
/* Depending on "fn", multiply or divide the elements of "multi" by "v" and
* return the result.
*/
__isl_give MULTI(BASE) *FN(MULTI(BASE),scale_val)(__isl_take MULTI(BASE) *multi,
__isl_take isl_val *v)
static __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_val_fn)(
__isl_take MULTI(BASE) *multi, __isl_take isl_val *v,
__isl_give EL *(*fn)(__isl_take EL *el, __isl_take isl_val *v))
{
int i;
if (!multi || !v)
goto error;
@@ -48,59 +48,31 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),scale_val)(__isl_take MULTI(BASE) *multi,
isl_die(isl_val_get_ctx(v), isl_error_invalid,
"expecting rational factor", goto error);
multi = FN(MULTI(BASE),cow)(multi);
if (!multi)
return NULL;
for (i = 0; i < multi->n; ++i) {
multi->u.p[i] = FN(EL,scale_val)(multi->u.p[i],
isl_val_copy(v));
if (!multi->u.p[i])
goto error;
}
isl_val_free(v);
return multi;
return FN(MULTI(BASE),fn_val)(multi, fn, v);
error:
isl_val_free(v);
return FN(MULTI(BASE),free)(multi);
}
/* Multiply the elements of "multi" by "v" and return the result.
*/
__isl_give MULTI(BASE) *FN(MULTI(BASE),scale_val)(__isl_take MULTI(BASE) *multi,
__isl_take isl_val *v)
{
return FN(MULTI(BASE),scale_val_fn)(multi, v, &FN(EL,scale_val));
}
/* Divide the elements of "multi" by "v" and return the result.
*/
__isl_give MULTI(BASE) *FN(MULTI(BASE),scale_down_val)(
__isl_take MULTI(BASE) *multi, __isl_take isl_val *v)
{
int i;
if (!multi || !v)
if (!v)
goto error;
if (isl_val_is_one(v)) {
isl_val_free(v);
return multi;
}
if (!isl_val_is_rat(v))
isl_die(isl_val_get_ctx(v), isl_error_invalid,
"expecting rational factor", goto error);
if (isl_val_is_zero(v))
isl_die(isl_val_get_ctx(v), isl_error_invalid,
"cannot scale down by zero", goto error);
multi = FN(MULTI(BASE),cow)(multi);
if (!multi)
return NULL;
for (i = 0; i < multi->n; ++i) {
multi->u.p[i] = FN(EL,scale_down_val)(multi->u.p[i],
isl_val_copy(v));
if (!multi->u.p[i])
goto error;
}
isl_val_free(v);
return multi;
return FN(MULTI(BASE),scale_val_fn)(multi, v, &FN(EL,scale_down_val));
error:
isl_val_free(v);
return FN(MULTI(BASE),free)(multi);
@@ -112,34 +84,7 @@ error:
__isl_give MULTI(BASE) *FN(MULTI(BASE),scale_multi_val)(
__isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
{
int i;
if (!multi || !mv)
goto error;
if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
mv->space, isl_dim_set))
isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
"spaces don't match", goto error);
multi = FN(MULTI(BASE),cow)(multi);
if (!multi)
goto error;
for (i = 0; i < multi->n; ++i) {
isl_val *v;
v = isl_multi_val_get_val(mv, i);
multi->u.p[i] = FN(EL,scale_val)(multi->u.p[i], v);
if (!multi->u.p[i])
goto error;
}
isl_multi_val_free(mv);
return multi;
error:
isl_multi_val_free(mv);
return FN(MULTI(BASE),free)(multi);
return FN(MULTI(BASE),fn_multi_val)(multi, &FN(EL,scale_val), mv);
}
/* Divide the elements of "multi" by the corresponding element of "mv"
@@ -148,34 +93,7 @@ error:
__isl_give MULTI(BASE) *FN(MULTI(BASE),scale_down_multi_val)(
__isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
{
int i;
if (!multi || !mv)
goto error;
if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
mv->space, isl_dim_set))
isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
"spaces don't match", goto error);
multi = FN(MULTI(BASE),cow)(multi);
if (!multi)
return NULL;
for (i = 0; i < multi->n; ++i) {
isl_val *v;
v = isl_multi_val_get_val(mv, i);
multi->u.p[i] = FN(EL,scale_down_val)(multi->u.p[i], v);
if (!multi->u.p[i])
goto error;
}
isl_multi_val_free(mv);
return multi;
error:
isl_multi_val_free(mv);
return FN(MULTI(BASE),free)(multi);
return FN(MULTI(BASE),fn_multi_val)(multi, &FN(EL,scale_down_val), mv);
}
/* Compute the residues of the elements of "multi" modulo
@@ -184,51 +102,12 @@ error:
__isl_give MULTI(BASE) *FN(MULTI(BASE),mod_multi_val)(
__isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
{
int i;
if (!multi || !mv)
goto error;
if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
mv->space, isl_dim_set))
isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
"spaces don't match", goto error);
multi = FN(MULTI(BASE),cow)(multi);
if (!multi)
goto error;
for (i = 0; i < multi->n; ++i) {
isl_val *v;
v = isl_multi_val_get_val(mv, i);
multi->u.p[i] = FN(EL,mod_val)(multi->u.p[i], v);
if (!multi->u.p[i])
goto error;
}
isl_multi_val_free(mv);
return multi;
error:
isl_multi_val_free(mv);
return FN(MULTI(BASE),free)(multi);
return FN(MULTI(BASE),fn_multi_val)(multi, &FN(EL,mod_val), mv);
}
/* Return the opposite of "multi".
*/
__isl_give MULTI(BASE) *FN(MULTI(BASE),neg)(__isl_take MULTI(BASE) *multi)
{
int i;
multi = FN(MULTI(BASE),cow)(multi);
if (!multi)
return NULL;
for (i = 0; i < multi->n; ++i) {
multi->u.p[i] = FN(EL,neg)(multi->u.p[i]);
if (!multi->u.p[i])
return FN(MULTI(BASE),free)(multi);
}
return multi;
return FN(MULTI(BASE),un_op)(multi, &FN(EL,neg));
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2013 Ecole Normale Superieure
*
* Use of this software is governed by the MIT license
*
* Written by Sven Verdoolaege,
* Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
*/
/* Apply "fn" to each of the elements of "multi" with as second argument "v".
*/
static __isl_give MULTI(BASE) *FN(MULTI(BASE),fn_val)(
__isl_take MULTI(BASE) *multi,
__isl_give EL *(*fn)(__isl_take EL *el, __isl_take isl_val *v),
__isl_take isl_val *v)
{
isl_size n;
int i;
n = FN(MULTI(BASE),size)(multi);
if (n < 0 || !v)
goto error;
for (i = 0; i < n; ++i) {
EL *el;
el = FN(MULTI(BASE),take_at)(multi, i);
el = fn(el, isl_val_copy(v));
multi = FN(MULTI(BASE),restore_at)(multi, i, el);
}
isl_val_free(v);
return multi;
error:
isl_val_free(v);
FN(MULTI(BASE),free)(multi);
return NULL;
}
#undef TYPE
#define TYPE MULTI(BASE)
#include "isl_type_check_match_range_multi_val.c"
/* Elementwise apply "fn" to "multi" and "mv".
*/
static __isl_give MULTI(BASE) *FN(MULTI(BASE),fn_multi_val)(
__isl_take MULTI(BASE) *multi,
__isl_give EL *(*fn)(__isl_take EL *el, __isl_take isl_val *v),
__isl_take isl_multi_val *mv)
{
isl_size n;
int i;
n = FN(MULTI(BASE),size)(multi);
if (n < 0 || FN(MULTI(BASE),check_match_range_multi_val)(multi, mv) < 0)
goto error;
for (i = 0; i < n; ++i) {
isl_val *v;
EL *el;
v = isl_multi_val_get_val(mv, i);
el = FN(MULTI(BASE),take_at)(multi, i);
el = fn(el, v);
multi = FN(MULTI(BASE),restore_at)(multi, i, el);
}
isl_multi_val_free(mv);
return multi;
error:
isl_multi_val_free(mv);
return FN(MULTI(BASE),free)(multi);
}

View File

@@ -47,26 +47,12 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),set_dim_name)(
__isl_take MULTI(BASE) *multi,
enum isl_dim_type type, unsigned pos, const char *s)
{
int i;
isl_space *space;
multi = FN(MULTI(BASE),cow)(multi);
if (!multi)
return NULL;
space = FN(MULTI(BASE),get_space)(multi);
space = isl_space_set_dim_name(space, type, pos, s);
multi->space = isl_space_set_dim_name(multi->space, type, pos, s);
if (!multi->space)
return FN(MULTI(BASE),free)(multi);
if (type == isl_dim_out)
return multi;
for (i = 0; i < multi->n; ++i) {
multi->u.p[i] = FN(EL,set_dim_name)(multi->u.p[i],
type, pos, s);
if (!multi->u.p[i])
return FN(MULTI(BASE),free)(multi);
}
return multi;
return FN(MULTI(BASE),reset_space)(multi, space);
}
/* Set the id of the given dimension of "multi" to "id".
@@ -77,16 +63,8 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),set_dim_id)(
{
isl_space *space;
multi = FN(MULTI(BASE),cow)(multi);
if (!multi || !id)
goto error;
space = FN(MULTI(BASE),get_space)(multi);
space = isl_space_set_dim_id(space, type, pos, id);
return FN(MULTI(BASE),reset_space)(multi, space);
error:
isl_id_free(id);
FN(MULTI(BASE),free)(multi);
return NULL;
}

View File

@@ -45,10 +45,13 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),insert_dims)(
__isl_take MULTI(BASE) *multi,
enum isl_dim_type type, unsigned first, unsigned n)
{
isl_space *space;
isl_size size;
int i;
if (!multi)
return NULL;
size = FN(MULTI(BASE),size)(multi);
if (size < 0)
return FN(MULTI(BASE),free)(multi);
if (type == isl_dim_out)
isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
"cannot insert output/set dimensions",
@@ -56,24 +59,20 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),insert_dims)(
if (n == 0 && !isl_space_is_named_or_nested(multi->space, type))
return multi;
multi = FN(MULTI(BASE),cow)(multi);
if (!multi)
return NULL;
space = FN(MULTI(BASE),take_space)(multi);
space = isl_space_insert_dims(space, type, first, n);
multi = FN(MULTI(BASE),restore_space)(multi, space);
multi->space = isl_space_insert_dims(multi->space, type, first, n);
if (!multi->space)
return FN(MULTI(BASE),free)(multi);
if (FN(MULTI(BASE),has_explicit_domain)(multi))
multi = FN(MULTI(BASE),insert_explicit_domain_dims)(multi,
type, first, n);
if (!multi)
return NULL;
for (i = 0; i < multi->n; ++i) {
multi->u.p[i] = FN(EL,insert_dims)(multi->u.p[i],
type, first, n);
if (!multi->u.p[i])
return FN(MULTI(BASE),free)(multi);
for (i = 0; i < size; ++i) {
EL *el;
el = FN(MULTI(BASE),take_at)(multi, i);
el = FN(EL,insert_dims)(el, type, first, n);
multi = FN(MULTI(BASE),restore_at)(multi, i, el);
}
return multi;

View File

@@ -13,17 +13,5 @@
*/
__isl_give MULTI(BASE) *FN(MULTI(BASE),floor)(__isl_take MULTI(BASE) *multi)
{
int i;
multi = FN(MULTI(BASE),cow)(multi);
if (!multi)
return NULL;
for (i = 0; i < multi->n; ++i) {
multi->u.p[i] = FN(EL,floor)(multi->u.p[i]);
if (!multi->u.p[i])
return FN(MULTI(BASE),free)(multi);
}
return multi;
return FN(MULTI(BASE),un_op)(multi, &FN(EL,floor));
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2011 Sven Verdoolaege
* Copyright 2012 Ecole Normale Superieure
*
* Use of this software is governed by the MIT license
*
* Written by Sven Verdoolaege,
* Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
*/
#include <isl_multi_macro.h>
/* Extract a multi expression with domain space "dom_space"
* from a tuple "tuple" that was read by read_tuple.
*
* Check that none of the expressions depend on any other output/set dimensions.
*/
static MULTI(BASE) *FN(MULTI(BASE),from_tuple)(
__isl_take isl_space *dom_space, __isl_take isl_multi_pw_aff *tuple)
{
int i;
isl_size dim, n;
isl_space *space;
MULTI(BASE) *multi;
n = isl_multi_pw_aff_dim(tuple, isl_dim_out);
dim = isl_space_dim(dom_space, isl_dim_all);
if (n < 0 || dim < 0)
dom_space = isl_space_free(dom_space);
space = isl_space_range(isl_multi_pw_aff_get_space(tuple));
space = isl_space_align_params(space, isl_space_copy(dom_space));
if (!isl_space_is_params(dom_space))
space = isl_space_map_from_domain_and_range(
isl_space_copy(dom_space), space);
isl_space_free(dom_space);
multi = FN(MULTI(BASE),alloc)(space);
for (i = 0; i < n; ++i) {
isl_pw_aff *pa;
pa = isl_multi_pw_aff_get_pw_aff(tuple, i);
multi = FN(MULTI(BASE),set_tuple_entry)(multi, pa, i, dim, n);
}
isl_multi_pw_aff_free(tuple);
return multi;
}

View File

@@ -20,10 +20,13 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),move_dims)(__isl_take MULTI(BASE) *multi,
enum isl_dim_type dst_type, unsigned dst_pos,
enum isl_dim_type src_type, unsigned src_pos, unsigned n)
{
isl_space *space;
isl_size size;
int i;
if (!multi)
return NULL;
size = FN(MULTI(BASE),size)(multi);
if (size < 0)
return FN(MULTI(BASE),free)(multi);
if (n == 0 &&
!isl_space_is_named_or_nested(multi->space, src_type) &&
@@ -45,26 +48,22 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),move_dims)(__isl_take MULTI(BASE) *multi,
"moving dims within the same type not supported",
return FN(MULTI(BASE),free)(multi));
multi = FN(MULTI(BASE),cow)(multi);
if (!multi)
return NULL;
multi->space = isl_space_move_dims(multi->space, dst_type, dst_pos,
space = FN(MULTI(BASE),take_space)(multi);
space = isl_space_move_dims(space, dst_type, dst_pos,
src_type, src_pos, n);
if (!multi->space)
return FN(MULTI(BASE),free)(multi);
multi = FN(MULTI(BASE),restore_space)(multi, space);
if (FN(MULTI(BASE),has_explicit_domain)(multi))
multi = FN(MULTI(BASE),move_explicit_domain_dims)(multi,
dst_type, dst_pos, src_type, src_pos, n);
if (!multi)
return NULL;
for (i = 0; i < multi->n; ++i) {
multi->u.p[i] = FN(EL,move_dims)(multi->u.p[i],
dst_type, dst_pos,
for (i = 0; i < size; ++i) {
EL *el;
el = FN(MULTI(BASE),take_at)(multi, i);
el = FN(EL,move_dims)(el, dst_type, dst_pos,
src_type, src_pos, n);
if (!multi->u.p[i])
return FN(MULTI(BASE),free)(multi);
multi = FN(MULTI(BASE),restore_at)(multi, i, el);
}
return multi;

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2013 Ecole Normale Superieure
*
* Use of this software is governed by the MIT license
*
* Written by Sven Verdoolaege,
* Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
*/
#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)
#undef SUFFIX
#define SUFFIX BASE
#undef ARG1
#define ARG1 isl_multi_pw_aff
#undef ARG2
#define ARG2 TYPE
static
#include "isl_align_params_templ.c"
/* Compute the pullback of "mpa" by the function represented by "fn".
* In other words, plug in "fn" in "mpa".
*
* If "mpa" has an explicit domain, then it is this domain
* that needs to undergo a pullback, i.e., a preimage.
*/
__isl_give isl_multi_pw_aff *FN(isl_multi_pw_aff_pullback,BASE)(
__isl_take isl_multi_pw_aff *mpa, __isl_take TYPE *fn)
{
int i;
isl_size n;
isl_space *space = NULL;
FN(isl_multi_pw_aff_align_params,BASE)(&mpa, &fn);
mpa = isl_multi_pw_aff_cow(mpa);
n = isl_multi_pw_aff_size(mpa);
if (n < 0 || !fn)
goto error;
space = isl_space_join(FN(TYPE,get_space)(fn),
isl_multi_pw_aff_get_space(mpa));
for (i = 0; i < n; ++i) {
isl_pw_aff *pa;
pa = isl_multi_pw_aff_take_at(mpa, i);
pa = FN(isl_pw_aff_pullback,BASE)(pa, FN(TYPE,copy)(fn));
mpa = isl_multi_pw_aff_restore_at(mpa, i, pa);
if (!mpa)
goto error;
}
if (isl_multi_pw_aff_has_explicit_domain(mpa)) {
mpa->u.dom = FN(isl_set_preimage,BASE)(mpa->u.dom,
FN(TYPE,copy)(fn));
if (!mpa->u.dom)
goto error;
}
FN(TYPE,free)(fn);
isl_multi_pw_aff_restore_space(mpa, space);
return mpa;
error:
isl_space_free(space);
isl_multi_pw_aff_free(mpa);
FN(TYPE,free)(fn);
return NULL;
}

View File

@@ -79,16 +79,6 @@ error:
return NULL;
}
/* Read a multi expression from "str".
*/
__isl_give MULTI(BASE) *FN(MULTI(BASE),read_from_str)(isl_ctx *ctx,
const char *str)
{
MULTI(BASE) *multi;
isl_stream *s = isl_stream_new_str(ctx, str);
if (!s)
return NULL;
multi = FN(isl_stream_read_multi,BASE)(s);
isl_stream_free(s);
return multi;
}
#undef TYPE_BASE
#define TYPE_BASE CAT(multi_,BASE)
#include "isl_read_from_str_templ.c"

View File

@@ -138,6 +138,56 @@ __isl_null MULTI(BASE) *FN(MULTI(BASE),free)(__isl_take MULTI(BASE) *multi)
return NULL;
}
/* Return the space of "multi".
* The caller is not allowed to modify "multi" between this call
* and the call to *_restore_space because the number
* of references needs to stay the same.
* The only exception is that isl_multi_*_free can be called instead.
* No copy is taken of multi->space if "multi" has only one reference
* such that it can be modified inplace if both have only a single reference.
*/
__isl_give isl_space *FN(MULTI(BASE),take_space)(__isl_keep MULTI(BASE) *multi)
{
isl_space *space;
if (!multi)
return NULL;
if (multi->ref != 1)
return FN(MULTI(BASE),get_space)(multi);
space = multi->space;
multi->space = NULL;
return space;
}
/* Set the space of "multi" to "space", where the space of "multi"
* may be missing due to a preceding call to isl_multi_*_take_space.
* However, in this case, "multi" only has a single reference and
* then the call to isl_multi_*_cow has no effect.
*/
__isl_give MULTI(BASE) *FN(MULTI(BASE),restore_space)(
__isl_take MULTI(BASE) *multi, __isl_take isl_space *space)
{
if (!multi || !space)
goto error;
if (multi->space == space) {
isl_space_free(space);
return multi;
}
multi = FN(MULTI(BASE),cow)(multi);
if (!multi)
goto error;
isl_space_free(multi->space);
multi->space = space;
return multi;
error:
FN(MULTI(BASE),free)(multi);
isl_space_free(space);
return NULL;
}
isl_size FN(MULTI(BASE),dim)(__isl_keep MULTI(BASE) *multi,
enum isl_dim_type type)
{
@@ -156,16 +206,21 @@ isl_size FN(MULTI(BASE),size)(__isl_keep MULTI(BASE) *multi)
static
#include "check_type_range_templ.c"
/* Return the base expression at position "pos" in "multi".
*/
static __isl_give EL *FN(MULTI(BASE),peek_at)(__isl_keep MULTI(BASE) *multi,
int pos)
{
if (FN(MULTI(BASE),check_range)(multi, isl_dim_out, pos, 1) < 0)
return NULL;
return multi->u.p[pos];
}
/* Return a copy of the base expression at position "pos" in "multi".
*/
__isl_give EL *FN(MULTI(BASE),get_at)(__isl_keep MULTI(BASE) *multi, int pos)
{
isl_ctx *ctx;
if (FN(MULTI(BASE),check_range)(multi, isl_dim_out, pos, 1) < 0)
return NULL;
ctx = FN(MULTI(BASE),get_ctx)(multi);
return FN(EL,copy)(multi->u.p[pos]);
return FN(EL,copy)(FN(MULTI(BASE),peek_at)(multi, pos));
}
/* This is an alternative name for the function above.
@@ -176,17 +231,48 @@ __isl_give EL *FN(FN(MULTI(BASE),get),BASE)(__isl_keep MULTI(BASE) *multi,
return FN(MULTI(BASE),get_at)(multi, pos);
}
/* Return the base expression at position "pos" in "multi".
* This may be either a copy or the base expression itself
* if there is only one reference to "multi".
* This allows the base expression to be modified inplace
* if both the multi expression and this base expression
* have only a single reference.
* The caller is not allowed to modify "multi" between this call and
* the subsequent call to isl_multi_*_restore_at_*.
* The only exception is that isl_multi_*_free can be called instead.
*/
static __isl_give EL *FN(MULTI(BASE),take_at)(__isl_keep MULTI(BASE) *multi,
int pos)
{
EL *el;
if (!multi)
return NULL;
if (multi->ref != 1)
return FN(MULTI(BASE),get_at)(multi, pos);
if (FN(MULTI(BASE),check_range)(multi, isl_dim_out, pos, 1) < 0)
return NULL;
el = multi->u.p[pos];
multi->u.p[pos] = NULL;
return el;
}
/* Set the element at position "pos" of "multi" to "el",
* where the position may be empty if "multi" has only a single reference.
*/
static __isl_give MULTI(BASE) *FN(MULTI(BASE),restore)(
static __isl_give MULTI(BASE) *FN(MULTI(BASE),restore_at)(
__isl_take MULTI(BASE) *multi, int pos, __isl_take EL *el)
{
multi = FN(MULTI(BASE),cow)(multi);
if (!multi || !el)
if (FN(MULTI(BASE),check_range)(multi, isl_dim_out, pos, 1) < 0 || !el)
goto error;
if (FN(MULTI(BASE),check_range)(multi, isl_dim_out, pos, 1) < 0)
if (multi->u.p[pos] == el) {
FN(EL,free)(el);
return multi;
}
multi = FN(MULTI(BASE),cow)(multi);
if (!multi)
goto error;
FN(EL,free)(multi->u.p[pos]);
@@ -212,7 +298,7 @@ static __isl_give MULTI(BASE) *FN(MULTI(BASE),restore_check_space)(
space = FN(MULTI(BASE),peek_space)(multi);
if (FN(EL,check_match_domain_space)(el, space) < 0)
multi = FN(MULTI(BASE),free)(multi);
return FN(MULTI(BASE),restore)(multi, pos, el);
return FN(MULTI(BASE),restore_at)(multi, pos, el);
}
/* Replace the base expression at position "pos" in "multi" with "el".
@@ -293,27 +379,26 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),reset_space_and_domain)(
__isl_take MULTI(BASE) *multi, __isl_take isl_space *space,
__isl_take isl_space *domain)
{
isl_size n;
int i;
multi = FN(MULTI(BASE),cow)(multi);
if (!multi || !space || !domain)
n = FN(MULTI(BASE),size)(multi);
if (n < 0 || !space || !domain)
goto error;
for (i = 0; i < multi->n; ++i) {
multi->u.p[i] = FN(EL,reset_domain_space)(multi->u.p[i],
isl_space_copy(domain));
if (!multi->u.p[i])
goto error;
for (i = 0; i < n; ++i) {
EL *el;
el = FN(MULTI(BASE),take_at)(multi, i);
el = FN(EL,reset_domain_space)(el, isl_space_copy(domain));
multi = FN(MULTI(BASE),restore_at)(multi, i, el);
}
if (FN(MULTI(BASE),has_explicit_domain)(multi)) {
if (FN(MULTI(BASE),has_explicit_domain)(multi))
multi = FN(MULTI(BASE),reset_explicit_domain_space)(multi,
isl_space_copy(domain));
if (!multi)
goto error;
}
isl_space_free(domain);
isl_space_free(multi->space);
multi->space = space;
multi = FN(MULTI(BASE),restore_space)(multi, space);
return multi;
error:
@@ -326,10 +411,11 @@ error:
__isl_give MULTI(BASE) *FN(MULTI(BASE),reset_domain_space)(
__isl_take MULTI(BASE) *multi, __isl_take isl_space *domain)
{
isl_space *space;
isl_space *space, *multi_space;
multi_space = FN(MULTI(BASE),get_space)(multi);
space = isl_space_extend_domain_with_range(isl_space_copy(domain),
isl_space_copy(multi->space));
multi_space);
return FN(MULTI(BASE),reset_space_and_domain)(multi, space, domain);
}
@@ -360,17 +446,19 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),realign_domain)(
__isl_take MULTI(BASE) *multi, __isl_take isl_reordering *exp)
{
int i;
isl_size n;
isl_space *space;
multi = FN(MULTI(BASE),cow)(multi);
if (!multi || !exp)
n = FN(MULTI(BASE),size)(multi);
if (n < 0 || !exp)
goto error;
for (i = 0; i < multi->n; ++i) {
multi->u.p[i] = FN(EL,realign_domain)(multi->u.p[i],
isl_reordering_copy(exp));
if (!multi->u.p[i])
goto error;
for (i = 0; i < n; ++i) {
EL *el;
el = FN(MULTI(BASE),take_at)(multi, i);
el = FN(EL,realign_domain)(el, isl_reordering_copy(exp));
multi = FN(MULTI(BASE),restore_at)(multi, i, el);
}
space = isl_reordering_get_space(exp);
@@ -394,6 +482,7 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),align_params)(
{
isl_ctx *ctx;
isl_bool equal_params;
isl_space *domain_space;
isl_reordering *exp;
if (!multi || !model)
@@ -421,9 +510,9 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),align_params)(
if (!multi)
goto error;
}
exp = isl_parameter_alignment_reordering(multi->space, model);
exp = isl_reordering_extend_space(exp,
FN(MULTI(BASE),get_domain_space)(multi));
domain_space = FN(MULTI(BASE),get_domain_space)(multi);
exp = isl_parameter_alignment_reordering(domain_space, model);
isl_space_free(domain_space);
multi = FN(MULTI(BASE),realign_domain)(multi, exp);
isl_space_free(model);
@@ -488,42 +577,60 @@ __isl_give MULTI(BASE) *FN(isl_space_multi,BASE)(__isl_take isl_space *space,
return FN(FN(MULTI(BASE),from),LIST(BASE))(space, list);
}
__isl_give MULTI(BASE) *FN(MULTI(BASE),drop_dims)(
__isl_take MULTI(BASE) *multi,
enum isl_dim_type type, unsigned first, unsigned n)
/* Drop the "n" output dimensions of "multi" starting at "first",
* where the space is assumed to have been adjusted already.
*/
static __isl_give MULTI(BASE) *FN(MULTI(BASE),drop_output_dims)(
__isl_take MULTI(BASE) *multi, unsigned first, unsigned n)
{
int i;
multi = FN(MULTI(BASE),cow)(multi);
if (!multi)
return NULL;
for (i = 0; i < n; ++i)
FN(EL,free)(multi->u.p[first + i]);
for (i = first; i + n < multi->n; ++i)
multi->u.p[i] = multi->u.p[i + n];
multi->n -= n;
if (n > 0 && FN(MULTI(BASE),has_explicit_domain)(multi))
multi = FN(MULTI(BASE),init_explicit_domain)(multi);
return multi;
}
__isl_give MULTI(BASE) *FN(MULTI(BASE),drop_dims)(
__isl_take MULTI(BASE) *multi,
enum isl_dim_type type, unsigned first, unsigned n)
{
isl_space *space;
isl_size size;
int i;
if (FN(MULTI(BASE),check_range)(multi, type, first, n) < 0)
return FN(MULTI(BASE),free)(multi);
multi->space = isl_space_drop_dims(multi->space, type, first, n);
if (!multi->space)
return FN(MULTI(BASE),free)(multi);
space = FN(MULTI(BASE),take_space)(multi);
space = isl_space_drop_dims(space, type, first, n);
multi = FN(MULTI(BASE),restore_space)(multi, space);
if (type == isl_dim_out) {
for (i = 0; i < n; ++i)
FN(EL,free)(multi->u.p[first + i]);
for (i = first; i + n < multi->n; ++i)
multi->u.p[i] = multi->u.p[i + n];
multi->n -= n;
if (n > 0 && FN(MULTI(BASE),has_explicit_domain)(multi))
multi = FN(MULTI(BASE),init_explicit_domain)(multi);
return multi;
}
if (type == isl_dim_out)
return FN(MULTI(BASE),drop_output_dims)(multi, first, n);
if (FN(MULTI(BASE),has_explicit_domain)(multi))
multi = FN(MULTI(BASE),drop_explicit_domain_dims)(multi,
type, first, n);
if (!multi)
return NULL;
for (i = 0; i < multi->n; ++i) {
multi->u.p[i] = FN(EL,drop_dims)(multi->u.p[i], type, first, n);
if (!multi->u.p[i])
return FN(MULTI(BASE),free)(multi);
size = FN(MULTI(BASE),size)(multi);
if (size < 0)
return FN(MULTI(BASE),free)(multi);
for (i = 0; i < size; ++i) {
EL *el;
el = FN(MULTI(BASE),take_at)(multi, i);
el = FN(EL,drop_dims)(el, type, first, n);
multi = FN(MULTI(BASE),restore_at)(multi, i, el);
}
return multi;
@@ -678,19 +785,11 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),factor_range)(
__isl_give MULTI(BASE) *FN(MULTI(BASE),flatten_range)(
__isl_take MULTI(BASE) *multi)
{
if (!multi)
return NULL;
isl_space *space;
if (!multi->space->nested[1])
return multi;
multi = FN(MULTI(BASE),cow)(multi);
if (!multi)
return NULL;
multi->space = isl_space_flatten_range(multi->space);
if (!multi->space)
return FN(MULTI(BASE),free)(multi);
space = FN(MULTI(BASE),take_space)(multi);
space = isl_space_flatten_range(space);
multi = FN(MULTI(BASE),restore_space)(multi, space);
return multi;
}
@@ -773,18 +872,21 @@ static __isl_give MULTI(BASE) *FN(MULTI(BASE),bin_op)(
__isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2,
__isl_give EL *(*fn)(__isl_take EL *, __isl_take EL *))
{
isl_size n;
int i;
FN(MULTI(BASE),align_params_bin)(&multi1, &multi2);
multi1 = FN(MULTI(BASE),cow)(multi1);
if (FN(MULTI(BASE),check_equal_space)(multi1, multi2) < 0)
n = FN(MULTI(BASE),size)(multi1);
if (n < 0 || FN(MULTI(BASE),check_equal_space)(multi1, multi2) < 0)
goto error;
for (i = 0; i < multi1->n; ++i) {
multi1->u.p[i] = fn(multi1->u.p[i],
FN(EL,copy)(multi2->u.p[i]));
if (!multi1->u.p[i])
goto error;
for (i = 0; i < n; ++i) {
EL *el1, *el2;
el2 = FN(MULTI(BASE),get_at)(multi2, i);
el1 = FN(MULTI(BASE),take_at)(multi1, i);
el1 = fn(el1, el2);
multi1 = FN(MULTI(BASE),restore_at)(multi1, i, el1);
}
if (FN(MULTI(BASE),has_explicit_domain)(multi2))
@@ -851,27 +953,9 @@ static isl_bool FN(MULTI(BASE),every)(__isl_keep MULTI(BASE) *multi,
return isl_bool_true;
}
/* Convert a multiple expression defined over a parameter domain
* into one that is defined over a zero-dimensional set.
*/
__isl_give MULTI(BASE) *FN(MULTI(BASE),from_range)(
__isl_take MULTI(BASE) *multi)
{
isl_space *space;
if (!multi)
return NULL;
if (!isl_space_is_set(multi->space))
isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
"not living in a set space",
return FN(MULTI(BASE),free)(multi));
space = FN(MULTI(BASE),get_space)(multi);
space = isl_space_from_range(space);
multi = FN(MULTI(BASE),reset_space)(multi, space);
return multi;
}
#undef TYPE
#define TYPE MULTI(BASE)
#include "isl_from_range_templ.c"
/* Are "multi1" and "multi2" obviously equal?
*/

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2014 Ecole Normale Superieure
*
* Use of this software is governed by the MIT license
*
* Written by Sven Verdoolaege,
* Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
*/
#include <isl_multi_macro.h>
/* Apply "fn" to each of the base expressions of "multi".
*/
static __isl_give MULTI(BASE) *FN(MULTI(BASE),un_op)(
__isl_take MULTI(BASE) *multi, __isl_give EL *(*fn)(__isl_take EL *el))
{
int i;
isl_size n;
n = FN(MULTI(BASE),size)(multi);
if (n < 0)
return FN(MULTI(BASE),free)(multi);
for (i = 0; i < n; ++i) {
EL *el;
el = FN(MULTI(BASE),take_at)(multi, i);
el = fn(el);
multi = FN(MULTI(BASE),restore_at)(multi, i, el);
}
return multi;
}

View File

@@ -1456,8 +1456,8 @@ static __isl_give isl_printer *print_split_map(__isl_take isl_printer *p,
return p;
}
static __isl_give isl_printer *isl_map_print_isl_body(__isl_keep isl_map *map,
__isl_take isl_printer *p)
static __isl_give isl_printer *print_body_map(__isl_take isl_printer *p,
__isl_keep isl_map *map)
{
struct isl_print_space_data data = { 0 };
struct isl_aff_split *split = NULL;
@@ -1486,7 +1486,7 @@ static __isl_give isl_printer *isl_map_print_isl(__isl_keep isl_map *map,
p = print_param_tuple(p, map->dim, &data);
p = isl_printer_print_str(p, s_open_set[0]);
p = isl_map_print_isl_body(map, p);
p = print_body_map(p, map);
p = isl_printer_print_str(p, s_close_set[0]);
return p;
}
@@ -1617,37 +1617,9 @@ struct isl_union_print_data {
int first;
};
static isl_stat print_map_body(__isl_take isl_map *map, void *user)
{
struct isl_union_print_data *data;
data = (struct isl_union_print_data *)user;
if (!data->first)
data->p = isl_printer_print_str(data->p, "; ");
data->first = 0;
data->p = isl_map_print_isl_body(map, data->p);
isl_map_free(map);
return isl_stat_ok;
}
/* Print the body of "umap" (everything except the parameter declarations)
* to "p" in isl format.
*/
static __isl_give isl_printer *isl_printer_print_union_map_isl_body(
__isl_take isl_printer *p, __isl_keep isl_union_map *umap)
{
struct isl_union_print_data data;
p = isl_printer_print_str(p, s_open_set[0]);
data.p = p;
data.first = 1;
isl_union_map_foreach_map(umap, &print_map_body, &data);
p = data.p;
p = isl_printer_print_str(p, s_close_set[0]);
return p;
}
#undef BASE
#define BASE map
#include "isl_union_print_templ.c"
/* Print the body of "uset" (everything except the parameter declarations)
* to "p" in isl format.
@@ -1655,24 +1627,7 @@ static __isl_give isl_printer *isl_printer_print_union_map_isl_body(
static __isl_give isl_printer *isl_printer_print_union_set_isl_body(
__isl_take isl_printer *p, __isl_keep isl_union_set *uset)
{
return isl_printer_print_union_map_isl_body(p, uset_to_umap(uset));
}
/* Print the isl_union_map "umap" to "p" in isl format.
*/
static __isl_give isl_printer *isl_union_map_print_isl(
__isl_keep isl_union_map *umap, __isl_take isl_printer *p)
{
struct isl_print_space_data space_data = { 0 };
isl_space *space;
space = isl_union_map_get_space(umap);
p = print_param_tuple(p, space, &space_data);
isl_space_free(space);
p = isl_printer_print_union_map_isl_body(p, umap);
return p;
return print_body_union_map(p, uset_to_umap(uset));
}
static isl_stat print_latex_map_body(__isl_take isl_map *map, void *user)
@@ -1706,7 +1661,7 @@ __isl_give isl_printer *isl_printer_print_union_map(__isl_take isl_printer *p,
goto error;
if (p->output_format == ISL_FORMAT_ISL)
return isl_union_map_print_isl(umap, p);
return print_union_map_isl(p, umap);
if (p->output_format == ISL_FORMAT_LATEX)
return isl_union_map_print_latex(umap, p);
@@ -1724,7 +1679,7 @@ __isl_give isl_printer *isl_printer_print_union_set(__isl_take isl_printer *p,
goto error;
if (p->output_format == ISL_FORMAT_ISL)
return isl_union_map_print_isl(uset_to_umap(uset), p);
return print_union_map_isl(p, uset_to_umap(uset));
if (p->output_format == ISL_FORMAT_LATEX)
return isl_union_map_print_latex(uset_to_umap(uset), p);
@@ -2028,7 +1983,7 @@ void isl_qpolynomial_fold_print(__isl_keep isl_qpolynomial_fold *fold,
isl_printer_free(p);
}
static __isl_give isl_printer *isl_pwqp_print_isl_body(
static __isl_give isl_printer *print_body_pw_qpolynomial(
__isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp)
{
struct isl_print_space_data data = { 0 };
@@ -2069,7 +2024,7 @@ static __isl_give isl_printer *print_pw_qpolynomial_isl(
}
p = isl_printer_print_str(p, "0");
}
p = isl_pwqp_print_isl_body(p, pwqp);
p = print_body_pw_qpolynomial(p, pwqp);
p = isl_printer_print_str(p, " }");
return p;
error:
@@ -2092,7 +2047,7 @@ void isl_pw_qpolynomial_print(__isl_keep isl_pw_qpolynomial *pwqp, FILE *out,
isl_printer_free(p);
}
static __isl_give isl_printer *isl_pwf_print_isl_body(
static __isl_give isl_printer *print_body_pw_qpolynomial_fold(
__isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf)
{
struct isl_print_space_data data = { 0 };
@@ -2130,7 +2085,7 @@ static __isl_give isl_printer *print_pw_qpolynomial_fold_isl(
}
p = isl_printer_print_str(p, "0");
}
p = isl_pwf_print_isl_body(p, pwf);
p = print_body_pw_qpolynomial_fold(p, pwf);
p = isl_printer_print_str(p, " }");
return p;
}
@@ -2287,40 +2242,9 @@ error:
return NULL;
}
static isl_stat print_pwqp_body(__isl_take isl_pw_qpolynomial *pwqp, void *user)
{
struct isl_union_print_data *data;
data = (struct isl_union_print_data *)user;
if (!data->first)
data->p = isl_printer_print_str(data->p, "; ");
data->first = 0;
data->p = isl_pwqp_print_isl_body(data->p, pwqp);
isl_pw_qpolynomial_free(pwqp);
return isl_stat_ok;
}
static __isl_give isl_printer *print_union_pw_qpolynomial_isl(
__isl_take isl_printer *p, __isl_keep isl_union_pw_qpolynomial *upwqp)
{
struct isl_union_print_data data;
struct isl_print_space_data space_data = { 0 };
isl_space *space;
space = isl_union_pw_qpolynomial_get_space(upwqp);
p = print_param_tuple(p, space, &space_data);
isl_space_free(space);
p = isl_printer_print_str(p, "{ ");
data.p = p;
data.first = 1;
isl_union_pw_qpolynomial_foreach_pw_qpolynomial(upwqp, &print_pwqp_body,
&data);
p = data.p;
p = isl_printer_print_str(p, " }");
return p;
}
#undef BASE
#define BASE pw_qpolynomial
#include "isl_union_print_templ.c"
__isl_give isl_printer *isl_printer_print_union_pw_qpolynomial(
__isl_take isl_printer *p, __isl_keep isl_union_pw_qpolynomial *upwqp)
@@ -2447,42 +2371,9 @@ void isl_pw_qpolynomial_fold_print(__isl_keep isl_pw_qpolynomial_fold *pwf,
isl_printer_free(p);
}
static isl_stat print_pwf_body(__isl_take isl_pw_qpolynomial_fold *pwf,
void *user)
{
struct isl_union_print_data *data;
data = (struct isl_union_print_data *)user;
if (!data->first)
data->p = isl_printer_print_str(data->p, "; ");
data->first = 0;
data->p = isl_pwf_print_isl_body(data->p, pwf);
isl_pw_qpolynomial_fold_free(pwf);
return isl_stat_ok;
}
static __isl_give isl_printer *print_union_pw_qpolynomial_fold_isl(
__isl_take isl_printer *p,
__isl_keep isl_union_pw_qpolynomial_fold *upwf)
{
struct isl_union_print_data data;
struct isl_print_space_data space_data = { 0 };
isl_space *space;
space = isl_union_pw_qpolynomial_fold_get_space(upwf);
p = print_param_tuple(p, space, &space_data);
isl_space_free(space);
p = isl_printer_print_str(p, "{ ");
data.p = p;
data.first = 1;
isl_union_pw_qpolynomial_fold_foreach_pw_qpolynomial_fold(upwf,
&print_pwf_body, &data);
p = data.p;
p = isl_printer_print_str(p, " }");
return p;
}
#undef BASE
#define BASE pw_qpolynomial_fold
#include "isl_union_print_templ.c"
__isl_give isl_printer *isl_printer_print_union_pw_qpolynomial_fold(
__isl_take isl_printer *p,
@@ -2806,7 +2697,7 @@ static __isl_give isl_printer *print_aff_body(__isl_take isl_printer *p,
return p;
}
static __isl_give isl_printer *print_aff(__isl_take isl_printer *p,
static __isl_give isl_printer *print_body_aff(__isl_take isl_printer *p,
__isl_keep isl_aff *aff)
{
struct isl_print_space_data data = { 0 };
@@ -2834,7 +2725,7 @@ static __isl_give isl_printer *print_aff_isl(__isl_take isl_printer *p,
p = print_param_tuple(p, aff->ls->dim, &data);
p = isl_printer_print_str(p, "{ ");
p = print_aff(p, aff);
p = print_body_aff(p, aff);
p = isl_printer_print_str(p, " }");
return p;
error:
@@ -2842,48 +2733,9 @@ error:
return NULL;
}
/* Print the body of an isl_pw_aff, i.e., a semicolon delimited
* sequence of affine expressions, each followed by constraints.
*/
static __isl_give isl_printer *print_pw_aff_body(
__isl_take isl_printer *p, __isl_keep isl_pw_aff *pa)
{
int i;
if (!pa)
return isl_printer_free(p);
for (i = 0; i < pa->n; ++i) {
isl_space *space;
if (i)
p = isl_printer_print_str(p, "; ");
p = print_aff(p, pa->p[i].aff);
space = isl_aff_get_domain_space(pa->p[i].aff);
p = print_disjuncts(set_to_map(pa->p[i].set), space, p, 0);
isl_space_free(space);
}
return p;
}
static __isl_give isl_printer *print_pw_aff_isl(__isl_take isl_printer *p,
__isl_keep isl_pw_aff *pwaff)
{
struct isl_print_space_data data = { 0 };
if (!pwaff)
goto error;
p = print_param_tuple(p, pwaff->dim, &data);
p = isl_printer_print_str(p, "{ ");
p = print_pw_aff_body(p, pwaff);
p = isl_printer_print_str(p, " }");
return p;
error:
isl_printer_free(p);
return NULL;
}
#undef BASE
#define BASE aff
#include "isl_pw_print_templ.c"
static __isl_give isl_printer *print_ls_name_c(__isl_take isl_printer *p,
__isl_keep isl_local_space *ls, enum isl_dim_type type, unsigned pos)
@@ -3048,64 +2900,9 @@ error:
return NULL;
}
/* Print "pa" in a sequence of isl_pw_affs delimited by semicolons.
* Each isl_pw_aff itself is also printed as semicolon delimited
* sequence of pieces.
* If data->first = 1, then this is the first in the sequence.
* Update data->first to tell the next element that it is not the first.
*/
static isl_stat print_pw_aff_body_wrap(__isl_take isl_pw_aff *pa,
void *user)
{
struct isl_union_print_data *data;
data = (struct isl_union_print_data *) user;
if (!data->first)
data->p = isl_printer_print_str(data->p, "; ");
data->first = 0;
data->p = print_pw_aff_body(data->p, pa);
isl_pw_aff_free(pa);
return data->p ? isl_stat_ok : isl_stat_error;
}
/* Print the body of an isl_union_pw_aff, i.e., a semicolon delimited
* sequence of affine expressions, each followed by constraints,
* with the sequence enclosed in braces.
*/
static __isl_give isl_printer *print_union_pw_aff_body(
__isl_take isl_printer *p, __isl_keep isl_union_pw_aff *upa)
{
struct isl_union_print_data data = { p, 1 };
p = isl_printer_print_str(p, s_open_set[0]);
data.p = p;
if (isl_union_pw_aff_foreach_pw_aff(upa,
&print_pw_aff_body_wrap, &data) < 0)
data.p = isl_printer_free(data.p);
p = data.p;
p = isl_printer_print_str(p, s_close_set[0]);
return p;
}
/* Print the isl_union_pw_aff "upa" to "p" in isl format.
*
* The individual isl_pw_affs are delimited by a semicolon.
*/
static __isl_give isl_printer *print_union_pw_aff_isl(
__isl_take isl_printer *p, __isl_keep isl_union_pw_aff *upa)
{
struct isl_print_space_data data = { 0 };
isl_space *space;
space = isl_union_pw_aff_get_space(upa);
p = print_param_tuple(p, space, &data);
isl_space_free(space);
p = print_union_pw_aff_body(p, upa);
return p;
}
#undef BASE
#define BASE pw_aff
#include "isl_union_print_templ.c"
/* Print the isl_union_pw_aff "upa" to "p".
*
@@ -3153,7 +2950,7 @@ static __isl_give isl_printer *print_dim_ma(__isl_take isl_printer *p,
return p;
}
static __isl_give isl_printer *print_multi_aff(__isl_take isl_printer *p,
static __isl_give isl_printer *print_body_multi_aff(__isl_take isl_printer *p,
__isl_keep isl_multi_aff *maff)
{
struct isl_print_space_data data = { 0 };
@@ -3173,7 +2970,7 @@ static __isl_give isl_printer *print_multi_aff_isl(__isl_take isl_printer *p,
p = print_param_tuple(p, maff->space, &data);
p = isl_printer_print_str(p, "{ ");
p = print_multi_aff(p, maff);
p = print_body_multi_aff(p, maff);
p = isl_printer_print_str(p, " }");
return p;
error:
@@ -3196,47 +2993,9 @@ error:
return NULL;
}
static __isl_give isl_printer *print_pw_multi_aff_body(
__isl_take isl_printer *p, __isl_keep isl_pw_multi_aff *pma)
{
int i;
if (!pma)
goto error;
for (i = 0; i < pma->n; ++i) {
isl_space *space;
if (i)
p = isl_printer_print_str(p, "; ");
p = print_multi_aff(p, pma->p[i].maff);
space = isl_multi_aff_get_domain_space(pma->p[i].maff);
p = print_disjuncts(set_to_map(pma->p[i].set), space, p, 0);
isl_space_free(space);
}
return p;
error:
isl_printer_free(p);
return NULL;
}
static __isl_give isl_printer *print_pw_multi_aff_isl(__isl_take isl_printer *p,
__isl_keep isl_pw_multi_aff *pma)
{
struct isl_print_space_data data = { 0 };
if (!pma)
goto error;
p = print_param_tuple(p, pma->dim, &data);
p = isl_printer_print_str(p, "{ ");
p = print_pw_multi_aff_body(p, pma);
p = isl_printer_print_str(p, " }");
return p;
error:
isl_printer_free(p);
return NULL;
}
#undef BASE
#define BASE multi_aff
#include "isl_pw_print_templ.c"
/* Print the unnamed, single-dimensional piecewise multi affine expression "pma"
* to "p".
@@ -3311,41 +3070,9 @@ error:
return NULL;
}
static isl_stat print_pw_multi_aff_body_wrap(__isl_take isl_pw_multi_aff *pma,
void *user)
{
struct isl_union_print_data *data;
data = (struct isl_union_print_data *) user;
if (!data->first)
data->p = isl_printer_print_str(data->p, "; ");
data->first = 0;
data->p = print_pw_multi_aff_body(data->p, pma);
isl_pw_multi_aff_free(pma);
return isl_stat_ok;
}
static __isl_give isl_printer *print_union_pw_multi_aff_isl(
__isl_take isl_printer *p, __isl_keep isl_union_pw_multi_aff *upma)
{
struct isl_union_print_data data;
struct isl_print_space_data space_data = { 0 };
isl_space *space;
space = isl_union_pw_multi_aff_get_space(upma);
p = print_param_tuple(p, space, &space_data);
isl_space_free(space);
p = isl_printer_print_str(p, s_open_set[0]);
data.p = p;
data.first = 1;
isl_union_pw_multi_aff_foreach_pw_multi_aff(upma,
&print_pw_multi_aff_body_wrap, &data);
p = data.p;
p = isl_printer_print_str(p, s_close_set[0]);
return p;
}
#undef BASE
#define BASE pw_multi_aff
#include "isl_union_print_templ.c"
__isl_give isl_printer *isl_printer_print_union_pw_multi_aff(
__isl_take isl_printer *p, __isl_keep isl_union_pw_multi_aff *upma)
@@ -3580,7 +3307,7 @@ static __isl_give isl_printer *print_union_pw_aff_dim(__isl_take isl_printer *p,
isl_union_pw_aff *upa;
upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, pos);
p = print_union_pw_aff_body(p, upa);
p = print_body_union_pw_aff(p, upa);
isl_union_pw_aff_free(upa);
return p;

Some files were not shown because too many files have changed in this diff Show More