+ [n] -> { A[i] -> [i] : 0 <= i <= 100, n }
+
+produces
+
+ for (int c0 = 0; c0 <= 100 && n >= c0; c0 += 1)
+ A(c0);
+
+When the option is turned on, the following AST is generated
+
+ for (int c0 = 0; c0 <= min(100, n); c0 += 1)
+ A(c0);
+
+=item * ast_build_prefer_pdiv
+
+If this option is turned off, then the AST generation will
+produce ASTs that may only contain C<isl_ast_op_fdiv_q>
+operators, but no C<isl_ast_op_pdiv_q> or
+C<isl_ast_op_pdiv_r> operators.
+If this options is turned on, then C<isl> will try to convert
+some of the C<isl_ast_op_fdiv_q> operators to (expressions containing)
+C<isl_ast_op_pdiv_q> or C<isl_ast_op_pdiv_r> operators.
+
+=item * ast_build_exploit_nested_bounds
+
+Simplify conditions based on bounds of nested for loops.
+In particular, remove conditions that are implied by the fact
+that one or more nested loops have at least one iteration,
+meaning that the upper bound is at least as large as the lower bound.
+For example, when this option is turned off, AST generation
+for the schedule
+
+ [N,M] -> { A[i,j] -> [i,j] : 0 <= i <= N and
+ 0 <= j <= M }
+
+produces
+
+ if (M >= 0)
+ for (int c0 = 0; c0 <= N; c0 += 1)
+ for (int c1 = 0; c1 <= M; c1 += 1)
+ A(c0, c1);
+
+When the option is turned on, the following AST is generated
+
+ for (int c0 = 0; c0 <= N; c0 += 1)
+ for (int c1 = 0; c1 <= M; c1 += 1)
+ A(c0, c1);
+
+=item * ast_build_group_coscheduled
+
+If two domain elements are assigned the same schedule point, then
+they may be executed in any order and they may even appear in different
+loops. If this options is set, then the AST generator will make
+sure that coscheduled domain elements do not appear in separate parts
+of the AST. This is useful in case of nested AST generation
+if the outer AST generation is given only part of a schedule
+and the inner AST generation should handle the domains that are
+coscheduled by this initial part of the schedule together.
+For example if an AST is generated for a schedule
+
+ { A[i] -> [0]; B[i] -> [0] }
+
+then the C<isl_ast_build_set_create_leaf> callback described
+below may get called twice, once for each domain.
+Setting this option ensures that the callback is only called once
+on both domains together.
+
+=item * ast_build_separation_bounds
+
+This option specifies which bounds to use during separation.
+If this option is set to C<ISL_AST_BUILD_SEPARATION_BOUNDS_IMPLICIT>
+then all (possibly implicit) bounds on the current dimension will
+be used during separation.
+If this option is set to C<ISL_AST_BUILD_SEPARATION_BOUNDS_EXPLICIT>
+then only those bounds that are explicitly available will
+be used during separation.
+
+=item * ast_build_scale_strides
+
+This option specifies whether the AST generator is allowed
+to scale down iterators of strided loops.
+
+=item * ast_build_allow_else
+
+This option specifies whether the AST generator is allowed
+to construct if statements with else branches.
+
+=item * ast_build_allow_or
+
+This option specifies whether the AST generator is allowed
+to construct if conditions with disjunctions.
+
+=back
+
+=head3 Fine-grained Control over AST Generation
+
+Besides specifying the constraints on the parameters,
+an C<isl_ast_build> object can be used to control
+various aspects of the AST generation process.
+The most prominent way of control is through ``options'',
+which can be set using the following function.
+
+ #include <isl/ast_build.h>
+ __isl_give isl_ast_build *
+ isl_ast_build_set_options(
+ __isl_take isl_ast_build *control,
+ __isl_take isl_union_map *options);
+
+The options are encoded in an <isl_union_map>.
+The domain of this union relation refers to the schedule domain,
+i.e., the range of the schedule passed to C<isl_ast_build_ast_from_schedule>.
+In the case of nested AST generation (see L</"Nested AST Generation">),
+the domain of C<options> should refer to the extra piece of the schedule.
+That is, it should be equal to the range of the wrapped relation in the
+range of the schedule.
+The range of the options can consist of elements in one or more spaces,
+the names of which determine the effect of the option.
+The values of the range typically also refer to the schedule dimension
+to which the option applies. In case of nested AST generation
+(see L</"Nested AST Generation">), these values refer to the position
+of the schedule dimension within the innermost AST generation.
+The constraints on the domain elements of
+the option should only refer to this dimension and earlier dimensions.
+We consider the following spaces.
+
+=over
+
+=item C<separation_class>
+
+This space is a wrapped relation between two one dimensional spaces.
+The input space represents the schedule dimension to which the option
+applies and the output space represents the separation class.
+While constructing a loop corresponding to the specified schedule
+dimension(s), the AST generator will try to generate separate loops
+for domain elements that are assigned different classes.
+If only some of the elements are assigned a class, then those elements
+that are not assigned any class will be treated as belonging to a class
+that is separate from the explicitly assigned classes.
+The typical use case for this option is to separate full tiles from
+partial tiles.
+The other options, described below, are applied after the separation
+into classes.
+
+As an example, consider the separation into full and partial tiles
+of a tiling of a triangular domain.
+Take, for example, the domain
+
+ { A[i,j] : 0 <= i,j and i + j <= 100 }
+
+and a tiling into tiles of 10 by 10. The input to the AST generator
+is then the schedule
+
+ { A[i,j] -> [([i/10]),[j/10],i,j] : 0 <= i,j and
+ i + j <= 100 }
+
+Without any options, the following AST is generated
+
+ for (int c0 = 0; c0 <= 10; c0 += 1)
+ for (int c1 = 0; c1 <= -c0 + 10; c1 += 1)
+ for (int c2 = 10 * c0;
+ c2 <= min(-10 * c1 + 100, 10 * c0 + 9);
+ c2 += 1)
+ for (int c3 = 10 * c1;
+ c3 <= min(10 * c1 + 9, -c2 + 100);
+ c3 += 1)
+ A(c2, c3);
+
+Separation into full and partial tiles can be obtained by assigning
+a class, say C<0>, to the full tiles. The full tiles are represented by those
+values of the first and second schedule dimensions for which there are
+values of the third and fourth dimensions to cover an entire tile.
+That is, we need to specify the following option
+
+ { [a,b,c,d] -> separation_class[[0]->[0]] :
+ exists b': 0 <= 10a,10b' and
+ 10a+9+10b'+9 <= 100;
+ [a,b,c,d] -> separation_class[[1]->[0]] :
+ 0 <= 10a,10b and 10a+9+10b+9 <= 100 }
+
+which simplifies to
+
+ { [a, b, c, d] -> separation_class[[1] -> [0]] :
+ a >= 0 and b >= 0 and b <= 8 - a;
+ [a, b, c, d] -> separation_class[[0] -> [0]] :
+ a >= 0 and a <= 8 }
+
+With this option, the generated AST is as follows
+
+ {
+ for (int c0 = 0; c0 <= 8; c0 += 1) {
+ for (int c1 = 0; c1 <= -c0 + 8; c1 += 1)
+ for (int c2 = 10 * c0;
+ c2 <= 10 * c0 + 9; c2 += 1)
+ for (int c3 = 10 * c1;
+ c3 <= 10 * c1 + 9; c3 += 1)
+ A(c2, c3);
+ for (int c1 = -c0 + 9; c1 <= -c0 + 10; c1 += 1)
+ for (int c2 = 10 * c0;
+ c2 <= min(-10 * c1 + 100, 10 * c0 + 9);
+ c2 += 1)
+ for (int c3 = 10 * c1;
+ c3 <= min(-c2 + 100, 10 * c1 + 9);
+ c3 += 1)
+ A(c2, c3);
+ }
+ for (int c0 = 9; c0 <= 10; c0 += 1)
+ for (int c1 = 0; c1 <= -c0 + 10; c1 += 1)
+ for (int c2 = 10 * c0;
+ c2 <= min(-10 * c1 + 100, 10 * c0 + 9);
+ c2 += 1)
+ for (int c3 = 10 * c1;
+ c3 <= min(10 * c1 + 9, -c2 + 100);
+ c3 += 1)
+ A(c2, c3);
+ }
+
+=item C<separate>
+
+This is a single-dimensional space representing the schedule dimension(s)
+to which ``separation'' should be applied. Separation tries to split
+a loop into several pieces if this can avoid the generation of guards
+inside the loop.
+See also the C<atomic> option.
+
+=item C<atomic>
+
+This is a single-dimensional space representing the schedule dimension(s)
+for which the domains should be considered ``atomic''. That is, the
+AST generator will make sure that any given domain space will only appear
+in a single loop at the specified level.
+
+Consider the following schedule
+
+ { a[i] -> [i] : 0 <= i < 10;
+ b[i] -> [i+1] : 0 <= i < 10 }
+
+If the following option is specified
+
+ { [i] -> separate[x] }
+
+then the following AST will be generated
+
+ {
+ a(0);
+ for (int c0 = 1; c0 <= 9; c0 += 1) {
+ a(c0);
+ b(c0 - 1);
+ }
+ b(9);
+ }
+
+If, on the other hand, the following option is specified
+
+ { [i] -> atomic[x] }
+
+then the following AST will be generated
+
+ for (int c0 = 0; c0 <= 10; c0 += 1) {
+ if (c0 <= 9)
+ a(c0);
+ if (c0 >= 1)
+ b(c0 - 1);
+ }
+
+If neither C<atomic> nor C<separate> is specified, then the AST generator
+may produce either of these two results or some intermediate form.
+
+=item C<unroll>
+
+This is a single-dimensional space representing the schedule dimension(s)
+that should be I<completely> unrolled.
+To obtain a partial unrolling, the user should apply an additional
+strip-mining to the schedule and fully unroll the inner loop.
+
+=back
+
+Additional control is available through the following functions.
+
+ #include <isl/ast_build.h>
+ __isl_give isl_ast_build *
+ isl_ast_build_set_iterators(
+ __isl_take isl_ast_build *control,
+ __isl_take isl_id_list *iterators);
+
+The function C<isl_ast_build_set_iterators> allows the user to
+specify a list of iterator C<isl_id>s to be used as iterators.
+If the input schedule is injective, then
+the number of elements in this list should be as large as the dimension
+of the schedule space, but no direct correspondence should be assumed
+between dimensions and elements.
+If the input schedule is not injective, then an additional number
+of C<isl_id>s equal to the largest dimension of the input domains
+may be required.
+If the number of provided C<isl_id>s is insufficient, then additional
+names are automatically generated.
+
+ #include <isl/ast_build.h>
+ __isl_give isl_ast_build *
+ isl_ast_build_set_create_leaf(
+ __isl_take isl_ast_build *control,
+ __isl_give isl_ast_node *(*fn)(
+ __isl_take isl_ast_build *build,
+ void *user), void *user);
+
+The
+C<isl_ast_build_set_create_leaf> function allows for the
+specification of a callback that should be called whenever the AST
+generator arrives at an element of the schedule domain.
+The callback should return an AST node that should be inserted
+at the corresponding position of the AST. The default action (when
+the callback is not set) is to continue generating parts of the AST to scan
+all the domain elements associated to the schedule domain element
+and to insert user nodes, ``calling'' the domain element, for each of them.
+The C<build> argument contains the current state of the C<isl_ast_build>.
+To ease nested AST generation (see L</"Nested AST Generation">),
+all control information that is
+specific to the current AST generation such as the options and
+the callbacks has been removed from this C<isl_ast_build>.
+The callback would typically return the result of a nested
+AST generation or a
+user defined node created using the following function.
+
+ #include <isl/ast.h>
+ __isl_give isl_ast_node *isl_ast_node_alloc_user(
+ __isl_take isl_ast_expr *expr);
+
+ #include <isl/ast_build.h>
+ __isl_give isl_ast_build *
+ isl_ast_build_set_at_each_domain(
+ __isl_take isl_ast_build *build,
+ __isl_give isl_ast_node *(*fn)(
+ __isl_take isl_ast_node *node,
+ __isl_keep isl_ast_build *build,
+ void *user), void *user);
+ __isl_give isl_ast_build *
+ isl_ast_build_set_before_each_for(
+ __isl_take isl_ast_build *build,
+ __isl_give isl_id *(*fn)(
+ __isl_keep isl_ast_build *build,
+ void *user), void *user);
+ __isl_give isl_ast_build *
+ isl_ast_build_set_after_each_for(
+ __isl_take isl_ast_build *build,
+ __isl_give isl_ast_node *(*fn)(
+ __isl_take isl_ast_node *node,
+ __isl_keep isl_ast_build *build,
+ void *user), void *user);
+
+The callback set by C<isl_ast_build_set_at_each_domain> will
+be called for each domain AST node.
+The callbacks set by C<isl_ast_build_set_before_each_for>
+and C<isl_ast_build_set_after_each_for> will be called
+for each for AST node. The first will be called in depth-first
+pre-order, while the second will be called in depth-first post-order.
+Since C<isl_ast_build_set_before_each_for> is called before the for
+node is actually constructed, it is only passed an C<isl_ast_build>.
+The returned C<isl_id> will be added as an annotation (using
+C<isl_ast_node_set_annotation>) to the constructed for node.
+In particular, if the user has also specified an C<after_each_for>
+callback, then the annotation can be retrieved from the node passed to
+that callback using C<isl_ast_node_get_annotation>.
+All callbacks should C<NULL> on failure.
+The given C<isl_ast_build> can be used to create new
+C<isl_ast_expr> objects using C<isl_ast_build_expr_from_pw_aff>
+or C<isl_ast_build_call_from_pw_multi_aff>.
+
+=head3 Nested AST Generation
+
+C<isl> allows the user to create an AST within the context
+of another AST. These nested ASTs are created using the
+same C<isl_ast_build_ast_from_schedule> function that is used to create the
+outer AST. The C<build> argument should be an C<isl_ast_build>
+passed to a callback set by
+C<isl_ast_build_set_create_leaf>.
+The space of the range of the C<schedule> argument should refer
+to this build. In particular, the space should be a wrapped
+relation and the domain of this wrapped relation should be the
+same as that of the range of the schedule returned by
+C<isl_ast_build_get_schedule> below.
+In practice, the new schedule is typically
+created by calling C<isl_union_map_range_product> on the old schedule
+and some extra piece of the schedule.
+The space of the schedule domain is also available from
+the C<isl_ast_build>.
+
+ #include <isl/ast_build.h>
+ __isl_give isl_union_map *isl_ast_build_get_schedule(
+ __isl_keep isl_ast_build *build);
+ __isl_give isl_space *isl_ast_build_get_schedule_space(
+ __isl_keep isl_ast_build *build);
+ __isl_give isl_ast_build *isl_ast_build_restrict(
+ __isl_take isl_ast_build *build,
+ __isl_take isl_set *set);
+
+The C<isl_ast_build_get_schedule> function returns a (partial)
+schedule for the domains elements for which part of the AST still needs to
+be generated in the current build.
+In particular, the domain elements are mapped to those iterations of the loops
+enclosing the current point of the AST generation inside which
+the domain elements are executed.
+No direct correspondence between
+the input schedule and this schedule should be assumed.
+The space obtained from C<isl_ast_build_get_schedule_space> can be used
+to create a set for C<isl_ast_build_restrict> to intersect
+with the current build. In particular, the set passed to
+C<isl_ast_build_restrict> can have additional parameters.
+The ids of the set dimensions in the space returned by
+C<isl_ast_build_get_schedule_space> correspond to the
+iterators of the already generated loops.
+The user should not rely on the ids of the output dimensions
+of the relations in the union relation returned by
+C<isl_ast_build_get_schedule> having any particular value.