Files
clang-p2996/polly/lib/External/isl/isl_schedule_read.c
Michael Kruse e8227804ac [Polly] Update ISL to isl-0.22.1-87-gfee05a13.
The primary motivation is to fix an assertion failure in
isl_basic_map_alloc_equality:

    isl_assert(ctx, room_for_con(bmap, 1), return -1);

Although the assertion does not occur anymore, I could not identify
which of ISL's commits fixed it.

Compared to the previous ISL version, Polly requires some changes for this update

 * Since ISL commit
   20d3574 "perform parameter alignment by modifying both arguments to function"
   isl_*_gist_* and similar functions do not always align the paramter
   list anymore. This caused the parameter lists in JScop files to
   become out-of-sync. Since many regression tests use JScop files with
   a fixed parameter list and order, we explicitly call align_params to
   ensure a predictable parameter list.

 * ISL changed some return types to isl_size, a typedef of (signed) int.
   This caused some issues where the return type was unsigned int before:
   - No overload for std::max(unsigned,isl_size)
   - It cause additional 'mixed signed/unsigned comparison' warnings.
     Since they do not break compilation, and sizes larger than 2^31
     were never supported, I am going to fix it separately.

 * With the change to isl_size, commit
   57d547 "isl_*_list_size: return isl_size"
   also changed the return value in case of an error from 0 to -1. This
   caused undefined looping over isl_iterator since the 'end iterator'
   got index -1, never reached from the 'begin iterator' with index 0.

 * Some internal changes in ISL caused the number of operations to
   increase when determining access ranges to determine aliasing
   overlaps. In one test, this caused exceeding the default limit of
   800000. The operations-limit was disabled for this test.
2020-02-10 19:03:08 -06:00

780 lines
18 KiB
C

#include <isl/id.h>
#include <isl/val.h>
#include <isl/schedule.h>
#include <isl/stream.h>
#include <isl_schedule_private.h>
#include <isl_schedule_tree.h>
/* An enumeration of the various keys that may appear in a YAML mapping
* of a schedule.
*/
enum isl_schedule_key {
isl_schedule_key_error = -1,
isl_schedule_key_child,
isl_schedule_key_coincident,
isl_schedule_key_context,
isl_schedule_key_contraction,
isl_schedule_key_domain,
isl_schedule_key_expansion,
isl_schedule_key_extension,
isl_schedule_key_filter,
isl_schedule_key_guard,
isl_schedule_key_leaf,
isl_schedule_key_mark,
isl_schedule_key_options,
isl_schedule_key_permutable,
isl_schedule_key_schedule,
isl_schedule_key_sequence,
isl_schedule_key_set,
isl_schedule_key_end
};
/* Textual representations of the YAML keys for an isl_schedule object.
*/
static char *key_str[] = {
[isl_schedule_key_child] = "child",
[isl_schedule_key_coincident] = "coincident",
[isl_schedule_key_context] = "context",
[isl_schedule_key_contraction] = "contraction",
[isl_schedule_key_domain] = "domain",
[isl_schedule_key_expansion] = "expansion",
[isl_schedule_key_extension] = "extension",
[isl_schedule_key_filter] = "filter",
[isl_schedule_key_guard] = "guard",
[isl_schedule_key_leaf] = "leaf",
[isl_schedule_key_mark] = "mark",
[isl_schedule_key_options] = "options",
[isl_schedule_key_permutable] = "permutable",
[isl_schedule_key_schedule] = "schedule",
[isl_schedule_key_sequence] = "sequence",
[isl_schedule_key_set] = "set",
};
#undef KEY
#define KEY enum isl_schedule_key
#undef KEY_ERROR
#define KEY_ERROR isl_schedule_key_error
#undef KEY_END
#define KEY_END isl_schedule_key_end
#include "extract_key.c"
static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
__isl_keep isl_stream *s);
/* Read a subtree with context root node from "s".
*/
static __isl_give isl_schedule_tree *read_context(__isl_keep isl_stream *s)
{
isl_set *context = NULL;
isl_schedule_tree *tree;
isl_ctx *ctx;
struct isl_token *tok;
enum isl_schedule_key key;
char *str;
int more;
ctx = isl_stream_get_ctx(s);
key = get_key(s);
if (isl_stream_yaml_next(s) < 0)
return NULL;
tok = isl_stream_next_token(s);
if (!tok) {
isl_stream_error(s, NULL, "unexpected EOF");
return NULL;
}
str = isl_token_get_str(ctx, tok);
context = isl_set_read_from_str(ctx, str);
free(str);
isl_token_free(tok);
more = isl_stream_yaml_next(s);
if (more < 0)
goto error;
if (!more) {
tree = isl_schedule_tree_from_context(context);
} else {
key = get_key(s);
if (key != isl_schedule_key_child)
isl_die(ctx, isl_error_invalid, "expecting child",
goto error);
if (isl_stream_yaml_next(s) < 0)
goto error;
tree = isl_stream_read_schedule_tree(s);
tree = isl_schedule_tree_insert_context(tree, context);
}
return tree;
error:
isl_set_free(context);
return NULL;
}
/* Read a subtree with domain root node from "s".
*/
static __isl_give isl_schedule_tree *read_domain(__isl_keep isl_stream *s)
{
isl_union_set *domain = NULL;
isl_schedule_tree *tree;
isl_ctx *ctx;
struct isl_token *tok;
enum isl_schedule_key key;
char *str;
int more;
ctx = isl_stream_get_ctx(s);
key = get_key(s);
if (isl_stream_yaml_next(s) < 0)
return NULL;
tok = isl_stream_next_token(s);
if (!tok) {
isl_stream_error(s, NULL, "unexpected EOF");
return NULL;
}
str = isl_token_get_str(ctx, tok);
domain = isl_union_set_read_from_str(ctx, str);
free(str);
isl_token_free(tok);
more = isl_stream_yaml_next(s);
if (more < 0)
goto error;
if (!more) {
tree = isl_schedule_tree_from_domain(domain);
} else {
key = get_key(s);
if (key != isl_schedule_key_child)
isl_die(ctx, isl_error_invalid, "expecting child",
goto error);
if (isl_stream_yaml_next(s) < 0)
goto error;
tree = isl_stream_read_schedule_tree(s);
tree = isl_schedule_tree_insert_domain(tree, domain);
}
return tree;
error:
isl_union_set_free(domain);
return NULL;
}
/* Read a subtree with expansion root node from "s".
*/
static __isl_give isl_schedule_tree *read_expansion(isl_stream *s)
{
isl_ctx *ctx;
isl_union_pw_multi_aff *contraction = NULL;
isl_union_map *expansion = NULL;
isl_schedule_tree *tree = NULL;
int more;
ctx = isl_stream_get_ctx(s);
do {
struct isl_token *tok;
enum isl_schedule_key key;
char *str;
key = get_key(s);
if (isl_stream_yaml_next(s) < 0)
goto error;
switch (key) {
case isl_schedule_key_contraction:
isl_union_pw_multi_aff_free(contraction);
tok = isl_stream_next_token(s);
str = isl_token_get_str(ctx, tok);
contraction = isl_union_pw_multi_aff_read_from_str(ctx,
str);
free(str);
isl_token_free(tok);
if (!contraction)
goto error;
break;
case isl_schedule_key_expansion:
isl_union_map_free(expansion);
tok = isl_stream_next_token(s);
str = isl_token_get_str(ctx, tok);
expansion = isl_union_map_read_from_str(ctx, str);
free(str);
isl_token_free(tok);
if (!expansion)
goto error;
break;
case isl_schedule_key_child:
isl_schedule_tree_free(tree);
tree = isl_stream_read_schedule_tree(s);
if (!tree)
goto error;
break;
default:
isl_die(ctx, isl_error_invalid, "unexpected key",
goto error);
}
} while ((more = isl_stream_yaml_next(s)) > 0);
if (more < 0)
goto error;
if (!contraction)
isl_die(ctx, isl_error_invalid, "missing contraction",
goto error);
if (!expansion)
isl_die(ctx, isl_error_invalid, "missing expansion",
goto error);
if (!tree)
return isl_schedule_tree_from_expansion(contraction, expansion);
return isl_schedule_tree_insert_expansion(tree, contraction, expansion);
error:
isl_schedule_tree_free(tree);
isl_union_pw_multi_aff_free(contraction);
isl_union_map_free(expansion);
return NULL;
}
/* Read a subtree with extension root node from "s".
*/
static __isl_give isl_schedule_tree *read_extension(isl_stream *s)
{
isl_union_map *extension = NULL;
isl_schedule_tree *tree;
isl_ctx *ctx;
struct isl_token *tok;
enum isl_schedule_key key;
char *str;
int more;
ctx = isl_stream_get_ctx(s);
key = get_key(s);
if (isl_stream_yaml_next(s) < 0)
return NULL;
tok = isl_stream_next_token(s);
if (!tok) {
isl_stream_error(s, NULL, "unexpected EOF");
return NULL;
}
str = isl_token_get_str(ctx, tok);
extension = isl_union_map_read_from_str(ctx, str);
free(str);
isl_token_free(tok);
more = isl_stream_yaml_next(s);
if (more < 0)
goto error;
if (!more) {
tree = isl_schedule_tree_from_extension(extension);
} else {
key = get_key(s);
if (key != isl_schedule_key_child)
isl_die(ctx, isl_error_invalid, "expecting child",
goto error);
if (isl_stream_yaml_next(s) < 0)
goto error;
tree = isl_stream_read_schedule_tree(s);
tree = isl_schedule_tree_insert_extension(tree, extension);
}
return tree;
error:
isl_union_map_free(extension);
return NULL;
}
/* Read a subtree with filter root node from "s".
*/
static __isl_give isl_schedule_tree *read_filter(__isl_keep isl_stream *s)
{
isl_union_set *filter = NULL;
isl_schedule_tree *tree;
isl_ctx *ctx;
struct isl_token *tok;
enum isl_schedule_key key;
char *str;
int more;
ctx = isl_stream_get_ctx(s);
key = get_key(s);
if (isl_stream_yaml_next(s) < 0)
return NULL;
tok = isl_stream_next_token(s);
if (!tok) {
isl_stream_error(s, NULL, "unexpected EOF");
return NULL;
}
str = isl_token_get_str(ctx, tok);
filter = isl_union_set_read_from_str(ctx, str);
free(str);
isl_token_free(tok);
more = isl_stream_yaml_next(s);
if (more < 0)
goto error;
if (!more) {
tree = isl_schedule_tree_from_filter(filter);
} else {
key = get_key(s);
if (key != isl_schedule_key_child)
isl_die(ctx, isl_error_invalid, "expecting child",
goto error);
if (isl_stream_yaml_next(s) < 0)
goto error;
tree = isl_stream_read_schedule_tree(s);
tree = isl_schedule_tree_insert_filter(tree, filter);
}
return tree;
error:
isl_union_set_free(filter);
return NULL;
}
/* Read a subtree with guard root node from "s".
*/
static __isl_give isl_schedule_tree *read_guard(isl_stream *s)
{
isl_set *guard = NULL;
isl_schedule_tree *tree;
isl_ctx *ctx;
struct isl_token *tok;
enum isl_schedule_key key;
char *str;
int more;
ctx = isl_stream_get_ctx(s);
key = get_key(s);
if (isl_stream_yaml_next(s) < 0)
return NULL;
tok = isl_stream_next_token(s);
if (!tok) {
isl_stream_error(s, NULL, "unexpected EOF");
return NULL;
}
str = isl_token_get_str(ctx, tok);
guard = isl_set_read_from_str(ctx, str);
free(str);
isl_token_free(tok);
more = isl_stream_yaml_next(s);
if (more < 0)
goto error;
if (!more) {
tree = isl_schedule_tree_from_guard(guard);
} else {
key = get_key(s);
if (key != isl_schedule_key_child)
isl_die(ctx, isl_error_invalid, "expecting child",
goto error);
if (isl_stream_yaml_next(s) < 0)
goto error;
tree = isl_stream_read_schedule_tree(s);
tree = isl_schedule_tree_insert_guard(tree, guard);
}
return tree;
error:
isl_set_free(guard);
return NULL;
}
/* Read a subtree with mark root node from "s".
*/
static __isl_give isl_schedule_tree *read_mark(isl_stream *s)
{
isl_id *mark;
isl_schedule_tree *tree;
isl_ctx *ctx;
struct isl_token *tok;
enum isl_schedule_key key;
char *str;
int more;
ctx = isl_stream_get_ctx(s);
key = get_key(s);
if (isl_stream_yaml_next(s) < 0)
return NULL;
tok = isl_stream_next_token(s);
if (!tok) {
isl_stream_error(s, NULL, "unexpected EOF");
return NULL;
}
str = isl_token_get_str(ctx, tok);
mark = isl_id_alloc(ctx, str, NULL);
free(str);
isl_token_free(tok);
more = isl_stream_yaml_next(s);
if (more < 0)
goto error;
if (!more) {
isl_die(ctx, isl_error_invalid, "expecting child",
goto error);
} else {
key = get_key(s);
if (key != isl_schedule_key_child)
isl_die(ctx, isl_error_invalid, "expecting child",
goto error);
if (isl_stream_yaml_next(s) < 0)
goto error;
tree = isl_stream_read_schedule_tree(s);
tree = isl_schedule_tree_insert_mark(tree, mark);
}
return tree;
error:
isl_id_free(mark);
return NULL;
}
/* Read a sequence of integers from "s" (representing the coincident
* property of a band node).
*/
static __isl_give isl_val_list *read_coincident(__isl_keep isl_stream *s)
{
isl_ctx *ctx;
isl_val_list *list;
int more;
ctx = isl_stream_get_ctx(s);
if (isl_stream_yaml_read_start_sequence(s) < 0)
return NULL;
list = isl_val_list_alloc(ctx, 0);
while ((more = isl_stream_yaml_next(s)) > 0) {
isl_val *val;
val = isl_stream_read_val(s);
list = isl_val_list_add(list, val);
}
if (more < 0 || isl_stream_yaml_read_end_sequence(s))
list = isl_val_list_free(list);
return list;
}
/* Set the (initial) coincident properties of "band" according to
* the (initial) elements of "coincident".
*/
static __isl_give isl_schedule_band *set_coincident(
__isl_take isl_schedule_band *band, __isl_take isl_val_list *coincident)
{
int i;
isl_size n, m;
n = isl_schedule_band_n_member(band);
m = isl_val_list_n_val(coincident);
if (n < 0 || m < 0)
band = isl_schedule_band_free(band);
for (i = 0; i < n && i < m; ++i) {
isl_val *v;
v = isl_val_list_get_val(coincident, i);
if (!v)
band = isl_schedule_band_free(band);
band = isl_schedule_band_member_set_coincident(band, i,
!isl_val_is_zero(v));
isl_val_free(v);
}
isl_val_list_free(coincident);
return band;
}
/* Read a subtree with band root node from "s".
*/
static __isl_give isl_schedule_tree *read_band(isl_stream *s)
{
isl_multi_union_pw_aff *schedule = NULL;
isl_schedule_tree *tree = NULL;
isl_val_list *coincident = NULL;
isl_union_set *options = NULL;
isl_ctx *ctx;
isl_schedule_band *band;
int permutable = 0;
int more;
ctx = isl_stream_get_ctx(s);
do {
struct isl_token *tok;
enum isl_schedule_key key;
char *str;
isl_val *v;
key = get_key(s);
if (isl_stream_yaml_next(s) < 0)
goto error;
switch (key) {
case isl_schedule_key_schedule:
schedule = isl_multi_union_pw_aff_free(schedule);
tok = isl_stream_next_token(s);
if (!tok) {
isl_stream_error(s, NULL, "unexpected EOF");
goto error;
}
str = isl_token_get_str(ctx, tok);
schedule = isl_multi_union_pw_aff_read_from_str(ctx,
str);
free(str);
isl_token_free(tok);
if (!schedule)
goto error;
break;
case isl_schedule_key_coincident:
coincident = read_coincident(s);
if (!coincident)
goto error;
break;
case isl_schedule_key_permutable:
v = isl_stream_read_val(s);
permutable = !isl_val_is_zero(v);
isl_val_free(v);
break;
case isl_schedule_key_options:
isl_union_set_free(options);
tok = isl_stream_next_token(s);
str = isl_token_get_str(ctx, tok);
options = isl_union_set_read_from_str(ctx, str);
free(str);
isl_token_free(tok);
if (!options)
goto error;
break;
case isl_schedule_key_child:
isl_schedule_tree_free(tree);
tree = isl_stream_read_schedule_tree(s);
if (!tree)
goto error;
break;
default:
isl_die(ctx, isl_error_invalid, "unexpected key",
goto error);
}
} while ((more = isl_stream_yaml_next(s)) > 0);
if (more < 0)
goto error;
if (!schedule)
isl_die(ctx, isl_error_invalid, "missing schedule", goto error);
band = isl_schedule_band_from_multi_union_pw_aff(schedule);
band = isl_schedule_band_set_permutable(band, permutable);
if (coincident)
band = set_coincident(band, coincident);
if (options)
band = isl_schedule_band_set_ast_build_options(band, options);
if (tree)
tree = isl_schedule_tree_insert_band(tree, band);
else
tree = isl_schedule_tree_from_band(band);
return tree;
error:
isl_val_list_free(coincident);
isl_union_set_free(options);
isl_schedule_tree_free(tree);
isl_multi_union_pw_aff_free(schedule);
return NULL;
}
/* Read a subtree with root node of type "type" from "s".
* The node is represented by a sequence of children.
*/
static __isl_give isl_schedule_tree *read_children(isl_stream *s,
enum isl_schedule_node_type type)
{
isl_ctx *ctx;
isl_schedule_tree_list *list;
int more;
ctx = isl_stream_get_ctx(s);
isl_token_free(isl_stream_next_token(s));
if (isl_stream_yaml_next(s) < 0)
return NULL;
if (isl_stream_yaml_read_start_sequence(s))
return NULL;
list = isl_schedule_tree_list_alloc(ctx, 0);
while ((more = isl_stream_yaml_next(s)) > 0) {
isl_schedule_tree *tree;
tree = isl_stream_read_schedule_tree(s);
list = isl_schedule_tree_list_add(list, tree);
}
if (more < 0 || isl_stream_yaml_read_end_sequence(s))
list = isl_schedule_tree_list_free(list);
return isl_schedule_tree_from_children(type, list);
}
/* Read a subtree with sequence root node from "s".
*/
static __isl_give isl_schedule_tree *read_sequence(isl_stream *s)
{
return read_children(s, isl_schedule_node_sequence);
}
/* Read a subtree with set root node from "s".
*/
static __isl_give isl_schedule_tree *read_set(isl_stream *s)
{
return read_children(s, isl_schedule_node_set);
}
/* Read a schedule (sub)tree from "s".
*
* We first determine the type of the root node based on the first
* mapping key and then hand over to a function tailored to reading
* nodes of this type.
*/
static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
struct isl_stream *s)
{
enum isl_schedule_key key;
struct isl_token *tok;
isl_schedule_tree *tree = NULL;
int more;
if (isl_stream_yaml_read_start_mapping(s))
return NULL;
more = isl_stream_yaml_next(s);
if (more < 0)
return NULL;
if (!more) {
isl_stream_error(s, NULL, "missing key");
return NULL;
}
tok = isl_stream_next_token(s);
key = extract_key(s, tok);
isl_stream_push_token(s, tok);
if (key < 0)
return NULL;
switch (key) {
case isl_schedule_key_context:
tree = read_context(s);
break;
case isl_schedule_key_domain:
tree = read_domain(s);
break;
case isl_schedule_key_contraction:
case isl_schedule_key_expansion:
tree = read_expansion(s);
break;
case isl_schedule_key_extension:
tree = read_extension(s);
break;
case isl_schedule_key_filter:
tree = read_filter(s);
break;
case isl_schedule_key_guard:
tree = read_guard(s);
break;
case isl_schedule_key_leaf:
isl_token_free(isl_stream_next_token(s));
tree = isl_schedule_tree_leaf(isl_stream_get_ctx(s));
break;
case isl_schedule_key_mark:
tree = read_mark(s);
break;
case isl_schedule_key_sequence:
tree = read_sequence(s);
break;
case isl_schedule_key_set:
tree = read_set(s);
break;
case isl_schedule_key_schedule:
case isl_schedule_key_coincident:
case isl_schedule_key_options:
case isl_schedule_key_permutable:
tree = read_band(s);
break;
case isl_schedule_key_child:
isl_die(isl_stream_get_ctx(s), isl_error_unsupported,
"cannot identify node type", return NULL);
case isl_schedule_key_end:
case isl_schedule_key_error:
return NULL;
}
if (isl_stream_yaml_read_end_mapping(s) < 0) {
isl_stream_error(s, NULL, "unexpected extra elements");
return isl_schedule_tree_free(tree);
}
return tree;
}
/* Read an isl_schedule from "s".
*/
__isl_give isl_schedule *isl_stream_read_schedule(isl_stream *s)
{
isl_ctx *ctx;
isl_schedule_tree *tree;
if (!s)
return NULL;
ctx = isl_stream_get_ctx(s);
tree = isl_stream_read_schedule_tree(s);
return isl_schedule_from_schedule_tree(ctx, tree);
}
/* Read an isl_schedule from "input".
*/
__isl_give isl_schedule *isl_schedule_read_from_file(isl_ctx *ctx, FILE *input)
{
struct isl_stream *s;
isl_schedule *schedule;
s = isl_stream_new_file(ctx, input);
if (!s)
return NULL;
schedule = isl_stream_read_schedule(s);
isl_stream_free(s);
return schedule;
}
/* Read an isl_schedule from "str".
*/
__isl_give isl_schedule *isl_schedule_read_from_str(isl_ctx *ctx,
const char *str)
{
struct isl_stream *s;
isl_schedule *schedule;
s = isl_stream_new_str(ctx, str);
if (!s)
return NULL;
schedule = isl_stream_read_schedule(s);
isl_stream_free(s);
return schedule;
}