add support for generating ASTs from schedule relations
authorSven Verdoolaege <skimo@kotnet.org>
Mon, 17 Sep 2012 20:11:06 +0000 (22:11 +0200)
committerSven Verdoolaege <skimo@kotnet.org>
Tue, 18 Sep 2012 13:08:21 +0000 (15:08 +0200)
This functionality is similar to that offered by CLooG and codegen(+).
The implementation in isl allows for a bit more control on how
the ASTs are generated by means of fairly flexible options.
It also has proper support for nested AST generation.

The outputs of all test cases have been verified by parsing them
using pet and then checking that the set of calls corresponds exactly
to the domain of the schedule and that they are called in an order
that matches the schedule.

Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
595 files changed:
Makefile.am
codegen.c [new file with mode: 0644]
codegen_test.sh.in [new file with mode: 0644]
configure.ac
doc/user.pod
include/isl/ast.h [new file with mode: 0644]
include/isl/ast_build.h [new file with mode: 0644]
isl_ast.c [new file with mode: 0644]
isl_ast_build.c [new file with mode: 0644]
isl_ast_build_expr.c [new file with mode: 0644]
isl_ast_build_expr.h [new file with mode: 0644]
isl_ast_build_private.h [new file with mode: 0644]
isl_ast_codegen.c [new file with mode: 0644]
isl_ast_graft.c [new file with mode: 0644]
isl_ast_graft_private.h [new file with mode: 0644]
isl_ast_private.h [new file with mode: 0644]
isl_options.c
isl_options_private.h
isl_test.c
print.c
test_inputs/codegen/atomic.c [new file with mode: 0644]
test_inputs/codegen/atomic.in [new file with mode: 0644]
test_inputs/codegen/cloog/0D-1.c [new file with mode: 0644]
test_inputs/codegen/cloog/0D-1.in [new file with mode: 0644]
test_inputs/codegen/cloog/0D-2.c [new file with mode: 0644]
test_inputs/codegen/cloog/0D-2.in [new file with mode: 0644]
test_inputs/codegen/cloog/0D-3.c [new file with mode: 0644]
test_inputs/codegen/cloog/0D-3.in [new file with mode: 0644]
test_inputs/codegen/cloog/1point-1.c [new file with mode: 0644]
test_inputs/codegen/cloog/1point-1.in [new file with mode: 0644]
test_inputs/codegen/cloog/1point-2.c [new file with mode: 0644]
test_inputs/codegen/cloog/1point-2.in [new file with mode: 0644]
test_inputs/codegen/cloog/4-param.c [new file with mode: 0644]
test_inputs/codegen/cloog/4-param.in [new file with mode: 0644]
test_inputs/codegen/cloog/README [new file with mode: 0644]
test_inputs/codegen/cloog/backtrack.c [new file with mode: 0644]
test_inputs/codegen/cloog/backtrack.in [new file with mode: 0644]
test_inputs/codegen/cloog/basic-bounds-1.c [new file with mode: 0644]
test_inputs/codegen/cloog/basic-bounds-1.in [new file with mode: 0644]
test_inputs/codegen/cloog/basic-bounds-2.c [new file with mode: 0644]
test_inputs/codegen/cloog/basic-bounds-2.in [new file with mode: 0644]
test_inputs/codegen/cloog/basic-bounds-3.c [new file with mode: 0644]
test_inputs/codegen/cloog/basic-bounds-3.in [new file with mode: 0644]
test_inputs/codegen/cloog/basic-bounds-4.c [new file with mode: 0644]
test_inputs/codegen/cloog/basic-bounds-4.in [new file with mode: 0644]
test_inputs/codegen/cloog/basic-bounds-5.c [new file with mode: 0644]
test_inputs/codegen/cloog/basic-bounds-5.in [new file with mode: 0644]
test_inputs/codegen/cloog/block.c [new file with mode: 0644]
test_inputs/codegen/cloog/block.in [new file with mode: 0644]
test_inputs/codegen/cloog/block2.c [new file with mode: 0644]
test_inputs/codegen/cloog/block2.in [new file with mode: 0644]
test_inputs/codegen/cloog/block3.c [new file with mode: 0644]
test_inputs/codegen/cloog/block3.in [new file with mode: 0644]
test_inputs/codegen/cloog/byu98-1-2-3.c [new file with mode: 0644]
test_inputs/codegen/cloog/byu98-1-2-3.in [new file with mode: 0644]
test_inputs/codegen/cloog/cholesky.c [new file with mode: 0644]
test_inputs/codegen/cloog/cholesky.in [new file with mode: 0644]
test_inputs/codegen/cloog/cholesky2.c [new file with mode: 0644]
test_inputs/codegen/cloog/cholesky2.in [new file with mode: 0644]
test_inputs/codegen/cloog/christian.c [new file with mode: 0644]
test_inputs/codegen/cloog/christian.in [new file with mode: 0644]
test_inputs/codegen/cloog/classen.c [new file with mode: 0644]
test_inputs/codegen/cloog/classen.in [new file with mode: 0644]
test_inputs/codegen/cloog/classen2.c [new file with mode: 0644]
test_inputs/codegen/cloog/classen2.in [new file with mode: 0644]
test_inputs/codegen/cloog/constant.c [new file with mode: 0644]
test_inputs/codegen/cloog/constant.in [new file with mode: 0644]
test_inputs/codegen/cloog/constbound.c [new file with mode: 0644]
test_inputs/codegen/cloog/constbound.in [new file with mode: 0644]
test_inputs/codegen/cloog/darte.c [new file with mode: 0644]
test_inputs/codegen/cloog/darte.in [new file with mode: 0644]
test_inputs/codegen/cloog/dealII.c [new file with mode: 0644]
test_inputs/codegen/cloog/dealII.in [new file with mode: 0644]
test_inputs/codegen/cloog/donotsimp.c [new file with mode: 0644]
test_inputs/codegen/cloog/donotsimp.in [new file with mode: 0644]
test_inputs/codegen/cloog/dot.c [new file with mode: 0644]
test_inputs/codegen/cloog/dot.in [new file with mode: 0644]
test_inputs/codegen/cloog/dot2.c [new file with mode: 0644]
test_inputs/codegen/cloog/dot2.in [new file with mode: 0644]
test_inputs/codegen/cloog/durbin_e_s.c [new file with mode: 0644]
test_inputs/codegen/cloog/durbin_e_s.in [new file with mode: 0644]
test_inputs/codegen/cloog/emploi.c [new file with mode: 0644]
test_inputs/codegen/cloog/emploi.in [new file with mode: 0644]
test_inputs/codegen/cloog/equality.c [new file with mode: 0644]
test_inputs/codegen/cloog/equality.in [new file with mode: 0644]
test_inputs/codegen/cloog/equality2.c [new file with mode: 0644]
test_inputs/codegen/cloog/equality2.in [new file with mode: 0644]
test_inputs/codegen/cloog/esced.c [new file with mode: 0644]
test_inputs/codegen/cloog/esced.in [new file with mode: 0644]
test_inputs/codegen/cloog/ex1.c [new file with mode: 0644]
test_inputs/codegen/cloog/ex1.in [new file with mode: 0644]
test_inputs/codegen/cloog/forwardsub-1-1-2.c [new file with mode: 0644]
test_inputs/codegen/cloog/forwardsub-1-1-2.in [new file with mode: 0644]
test_inputs/codegen/cloog/forwardsub-2-1-2-3.c [new file with mode: 0644]
test_inputs/codegen/cloog/forwardsub-2-1-2-3.in [new file with mode: 0644]
test_inputs/codegen/cloog/forwardsub-3-1-2.c [new file with mode: 0644]
test_inputs/codegen/cloog/forwardsub-3-1-2.in [new file with mode: 0644]
test_inputs/codegen/cloog/gauss.c [new file with mode: 0644]
test_inputs/codegen/cloog/gauss.in [new file with mode: 0644]
test_inputs/codegen/cloog/gesced.c [new file with mode: 0644]
test_inputs/codegen/cloog/gesced.in [new file with mode: 0644]
test_inputs/codegen/cloog/gesced2.c [new file with mode: 0644]
test_inputs/codegen/cloog/gesced2.in [new file with mode: 0644]
test_inputs/codegen/cloog/gesced3.c [new file with mode: 0644]
test_inputs/codegen/cloog/gesced3.in [new file with mode: 0644]
test_inputs/codegen/cloog/guide.c [new file with mode: 0644]
test_inputs/codegen/cloog/guide.in [new file with mode: 0644]
test_inputs/codegen/cloog/iftest.c [new file with mode: 0644]
test_inputs/codegen/cloog/iftest.in [new file with mode: 0644]
test_inputs/codegen/cloog/iftest2.c [new file with mode: 0644]
test_inputs/codegen/cloog/iftest2.in [new file with mode: 0644]
test_inputs/codegen/cloog/infinite2.c [new file with mode: 0644]
test_inputs/codegen/cloog/infinite2.in [new file with mode: 0644]
test_inputs/codegen/cloog/jacobi-shared.c [new file with mode: 0644]
test_inputs/codegen/cloog/jacobi-shared.in [new file with mode: 0644]
test_inputs/codegen/cloog/largeur.c [new file with mode: 0644]
test_inputs/codegen/cloog/largeur.in [new file with mode: 0644]
test_inputs/codegen/cloog/levenshtein-1-2-3.c [new file with mode: 0644]
test_inputs/codegen/cloog/levenshtein-1-2-3.in [new file with mode: 0644]
test_inputs/codegen/cloog/lex.c [new file with mode: 0644]
test_inputs/codegen/cloog/lex.in [new file with mode: 0644]
test_inputs/codegen/cloog/lineality-1-2.c [new file with mode: 0644]
test_inputs/codegen/cloog/lineality-1-2.in [new file with mode: 0644]
test_inputs/codegen/cloog/lineality-2-1-2.c [new file with mode: 0644]
test_inputs/codegen/cloog/lineality-2-1-2.in [new file with mode: 0644]
test_inputs/codegen/cloog/logo.c [new file with mode: 0644]
test_inputs/codegen/cloog/logo.in [new file with mode: 0644]
test_inputs/codegen/cloog/logopar.c [new file with mode: 0644]
test_inputs/codegen/cloog/logopar.in [new file with mode: 0644]
test_inputs/codegen/cloog/lu.c [new file with mode: 0644]
test_inputs/codegen/cloog/lu.in [new file with mode: 0644]
test_inputs/codegen/cloog/lu2.c [new file with mode: 0644]
test_inputs/codegen/cloog/lu2.in [new file with mode: 0644]
test_inputs/codegen/cloog/lux.c [new file with mode: 0644]
test_inputs/codegen/cloog/lux.in [new file with mode: 0644]
test_inputs/codegen/cloog/merge.c [new file with mode: 0644]
test_inputs/codegen/cloog/merge.in [new file with mode: 0644]
test_inputs/codegen/cloog/min-1-1.c [new file with mode: 0644]
test_inputs/codegen/cloog/min-1-1.in [new file with mode: 0644]
test_inputs/codegen/cloog/min-2-1.c [new file with mode: 0644]
test_inputs/codegen/cloog/min-2-1.in [new file with mode: 0644]
test_inputs/codegen/cloog/min-3-1.c [new file with mode: 0644]
test_inputs/codegen/cloog/min-3-1.in [new file with mode: 0644]
test_inputs/codegen/cloog/min-4-1.c [new file with mode: 0644]
test_inputs/codegen/cloog/min-4-1.in [new file with mode: 0644]
test_inputs/codegen/cloog/mod.c [new file with mode: 0644]
test_inputs/codegen/cloog/mod.in [new file with mode: 0644]
test_inputs/codegen/cloog/mod2.c [new file with mode: 0644]
test_inputs/codegen/cloog/mod2.in [new file with mode: 0644]
test_inputs/codegen/cloog/mod3.c [new file with mode: 0644]
test_inputs/codegen/cloog/mod3.in [new file with mode: 0644]
test_inputs/codegen/cloog/mod4.c [new file with mode: 0644]
test_inputs/codegen/cloog/mod4.in [new file with mode: 0644]
test_inputs/codegen/cloog/mode.c [new file with mode: 0644]
test_inputs/codegen/cloog/mode.in [new file with mode: 0644]
test_inputs/codegen/cloog/multi-mm-1.c [new file with mode: 0644]
test_inputs/codegen/cloog/multi-mm-1.in [new file with mode: 0644]
test_inputs/codegen/cloog/multi-stride.c [new file with mode: 0644]
test_inputs/codegen/cloog/multi-stride.in [new file with mode: 0644]
test_inputs/codegen/cloog/multi-stride2.c [new file with mode: 0644]
test_inputs/codegen/cloog/multi-stride2.in [new file with mode: 0644]
test_inputs/codegen/cloog/mxm-shared.c [new file with mode: 0644]
test_inputs/codegen/cloog/mxm-shared.in [new file with mode: 0644]
test_inputs/codegen/cloog/no_lindep.c [new file with mode: 0644]
test_inputs/codegen/cloog/no_lindep.in [new file with mode: 0644]
test_inputs/codegen/cloog/nul_basic1.c [new file with mode: 0644]
test_inputs/codegen/cloog/nul_basic1.in [new file with mode: 0644]
test_inputs/codegen/cloog/nul_basic2.c [new file with mode: 0644]
test_inputs/codegen/cloog/nul_basic2.in [new file with mode: 0644]
test_inputs/codegen/cloog/nul_complex1.c [new file with mode: 0644]
test_inputs/codegen/cloog/nul_complex1.in [new file with mode: 0644]
test_inputs/codegen/cloog/nul_lcpc.c [new file with mode: 0644]
test_inputs/codegen/cloog/nul_lcpc.in [new file with mode: 0644]
test_inputs/codegen/cloog/orc.c [new file with mode: 0644]
test_inputs/codegen/cloog/orc.in [new file with mode: 0644]
test_inputs/codegen/cloog/param-split.c [new file with mode: 0644]
test_inputs/codegen/cloog/param-split.in [new file with mode: 0644]
test_inputs/codegen/cloog/pouchet.c [new file with mode: 0644]
test_inputs/codegen/cloog/pouchet.in [new file with mode: 0644]
test_inputs/codegen/cloog/rectangle.c [new file with mode: 0644]
test_inputs/codegen/cloog/rectangle.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-QR.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-QR.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-bastoul3.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-bastoul3.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-cholesky2.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-cholesky2.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-fusion1.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-fusion1.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-fusion2.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-fusion2.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-jacobi2.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-jacobi2.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-jacobi3.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-jacobi3.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-lim-lam1.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-lim-lam1.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-lim-lam2.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-lim-lam2.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-lim-lam3.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-lim-lam3.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-lim-lam4.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-lim-lam4.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-lim-lam5.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-lim-lam5.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-lim-lam6.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-lim-lam6.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-liu-zhuge1.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-liu-zhuge1.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-loechner3.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-loechner3.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-loechner4.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-loechner4.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-loechner5.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-loechner5.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-mg-interp.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-mg-interp.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-mg-interp2.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-mg-interp2.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-mg-psinv.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-mg-psinv.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-mg-resid.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-mg-resid.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-mg-rprj3.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-mg-rprj3.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-pingali1.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-pingali1.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-pingali2.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-pingali2.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-pingali3.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-pingali3.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-pingali4.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-pingali4.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-pingali5.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-pingali5.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-pingali6.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-pingali6.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-stride.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-stride.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-stride2.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-stride2.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-tang-xue1.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-tang-xue1.in [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-two.c [new file with mode: 0644]
test_inputs/codegen/cloog/reservoir-two.in [new file with mode: 0644]
test_inputs/codegen/cloog/singleton.c [new file with mode: 0644]
test_inputs/codegen/cloog/singleton.in [new file with mode: 0644]
test_inputs/codegen/cloog/square+triangle-1-1-2-3.c [new file with mode: 0644]
test_inputs/codegen/cloog/square+triangle-1-1-2-3.in [new file with mode: 0644]
test_inputs/codegen/cloog/stride.c [new file with mode: 0644]
test_inputs/codegen/cloog/stride.in [new file with mode: 0644]
test_inputs/codegen/cloog/stride2.c [new file with mode: 0644]
test_inputs/codegen/cloog/stride2.in [new file with mode: 0644]
test_inputs/codegen/cloog/stride3.c [new file with mode: 0644]
test_inputs/codegen/cloog/stride3.in [new file with mode: 0644]
test_inputs/codegen/cloog/stride4.c [new file with mode: 0644]
test_inputs/codegen/cloog/stride4.in [new file with mode: 0644]
test_inputs/codegen/cloog/swim.c [new file with mode: 0644]
test_inputs/codegen/cloog/swim.in [new file with mode: 0644]
test_inputs/codegen/cloog/test.c [new file with mode: 0644]
test_inputs/codegen/cloog/test.in [new file with mode: 0644]
test_inputs/codegen/cloog/thomasset.c [new file with mode: 0644]
test_inputs/codegen/cloog/thomasset.in [new file with mode: 0644]
test_inputs/codegen/cloog/tiling.c [new file with mode: 0644]
test_inputs/codegen/cloog/tiling.in [new file with mode: 0644]
test_inputs/codegen/cloog/uday_scalars.c [new file with mode: 0644]
test_inputs/codegen/cloog/uday_scalars.in [new file with mode: 0644]
test_inputs/codegen/cloog/union.c [new file with mode: 0644]
test_inputs/codegen/cloog/union.in [new file with mode: 0644]
test_inputs/codegen/cloog/unroll.c [new file with mode: 0644]
test_inputs/codegen/cloog/unroll.in [new file with mode: 0644]
test_inputs/codegen/cloog/unroll2.c [new file with mode: 0644]
test_inputs/codegen/cloog/unroll2.in [new file with mode: 0644]
test_inputs/codegen/cloog/usvd_e_t.c [new file with mode: 0644]
test_inputs/codegen/cloog/usvd_e_t.in [new file with mode: 0644]
test_inputs/codegen/cloog/vasilache.c [new file with mode: 0644]
test_inputs/codegen/cloog/vasilache.in [new file with mode: 0644]
test_inputs/codegen/cloog/vivien.c [new file with mode: 0644]
test_inputs/codegen/cloog/vivien.in [new file with mode: 0644]
test_inputs/codegen/cloog/vivien2.c [new file with mode: 0644]
test_inputs/codegen/cloog/vivien2.in [new file with mode: 0644]
test_inputs/codegen/cloog/walters.c [new file with mode: 0644]
test_inputs/codegen/cloog/walters.in [new file with mode: 0644]
test_inputs/codegen/cloog/walters2.c [new file with mode: 0644]
test_inputs/codegen/cloog/walters2.in [new file with mode: 0644]
test_inputs/codegen/cloog/walters3.c [new file with mode: 0644]
test_inputs/codegen/cloog/walters3.in [new file with mode: 0644]
test_inputs/codegen/cloog/wavefront.c [new file with mode: 0644]
test_inputs/codegen/cloog/wavefront.in [new file with mode: 0644]
test_inputs/codegen/cloog/yosr.c [new file with mode: 0644]
test_inputs/codegen/cloog/yosr.in [new file with mode: 0644]
test_inputs/codegen/cloog/yosr2.c [new file with mode: 0644]
test_inputs/codegen/cloog/yosr2.in [new file with mode: 0644]
test_inputs/codegen/cloog/youcef.c [new file with mode: 0644]
test_inputs/codegen/cloog/youcef.in [new file with mode: 0644]
test_inputs/codegen/cloog/youcefn.c [new file with mode: 0644]
test_inputs/codegen/cloog/youcefn.in [new file with mode: 0644]
test_inputs/codegen/disjuncts.c [new file with mode: 0644]
test_inputs/codegen/disjuncts.in [new file with mode: 0644]
test_inputs/codegen/hoist.c [new file with mode: 0644]
test_inputs/codegen/hoist.in [new file with mode: 0644]
test_inputs/codegen/omega/README [new file with mode: 0644]
test_inputs/codegen/omega/basics-0.c [new file with mode: 0644]
test_inputs/codegen/omega/basics-0.in [new file with mode: 0644]
test_inputs/codegen/omega/basics-1.c [new file with mode: 0644]
test_inputs/codegen/omega/basics-1.in [new file with mode: 0644]
test_inputs/codegen/omega/chosol-0.c [new file with mode: 0644]
test_inputs/codegen/omega/chosol-0.in [new file with mode: 0644]
test_inputs/codegen/omega/chosol-1.c [new file with mode: 0644]
test_inputs/codegen/omega/chosol-1.in [new file with mode: 0644]
test_inputs/codegen/omega/code_gen-0.c [new file with mode: 0644]
test_inputs/codegen/omega/code_gen-0.in [new file with mode: 0644]
test_inputs/codegen/omega/code_gen-1.c [new file with mode: 0644]
test_inputs/codegen/omega/code_gen-1.in [new file with mode: 0644]
test_inputs/codegen/omega/code_gen-2.c [new file with mode: 0644]
test_inputs/codegen/omega/code_gen-2.in [new file with mode: 0644]
test_inputs/codegen/omega/collard-0.c [new file with mode: 0644]
test_inputs/codegen/omega/collard-0.in [new file with mode: 0644]
test_inputs/codegen/omega/dagstuhl1-0.c [new file with mode: 0644]
test_inputs/codegen/omega/dagstuhl1-0.in [new file with mode: 0644]
test_inputs/codegen/omega/dagstuhl1-1.c [new file with mode: 0644]
test_inputs/codegen/omega/dagstuhl1-1.in [new file with mode: 0644]
test_inputs/codegen/omega/fc1-0.c [new file with mode: 0644]
test_inputs/codegen/omega/fc1-0.in [new file with mode: 0644]
test_inputs/codegen/omega/fc1-1.c [new file with mode: 0644]
test_inputs/codegen/omega/fc1-1.in [new file with mode: 0644]
test_inputs/codegen/omega/fc1-2.c [new file with mode: 0644]
test_inputs/codegen/omega/fc1-2.in [new file with mode: 0644]
test_inputs/codegen/omega/fc2-0.c [new file with mode: 0644]
test_inputs/codegen/omega/fc2-0.in [new file with mode: 0644]
test_inputs/codegen/omega/fc2-1.c [new file with mode: 0644]
test_inputs/codegen/omega/fc2-1.in [new file with mode: 0644]
test_inputs/codegen/omega/floor_bound-0.c [new file with mode: 0644]
test_inputs/codegen/omega/floor_bound-0.in [new file with mode: 0644]
test_inputs/codegen/omega/floor_bound-1.c [new file with mode: 0644]
test_inputs/codegen/omega/floor_bound-1.in [new file with mode: 0644]
test_inputs/codegen/omega/floor_bound-2.c [new file with mode: 0644]
test_inputs/codegen/omega/floor_bound-2.in [new file with mode: 0644]
test_inputs/codegen/omega/floor_bound-3.c [new file with mode: 0644]
test_inputs/codegen/omega/floor_bound-3.in [new file with mode: 0644]
test_inputs/codegen/omega/floor_bound-4.c [new file with mode: 0644]
test_inputs/codegen/omega/floor_bound-4.in [new file with mode: 0644]
test_inputs/codegen/omega/floor_bound-5.c [new file with mode: 0644]
test_inputs/codegen/omega/floor_bound-5.in [new file with mode: 0644]
test_inputs/codegen/omega/floor_bound-6.c [new file with mode: 0644]
test_inputs/codegen/omega/floor_bound-6.in [new file with mode: 0644]
test_inputs/codegen/omega/gc-0.c [new file with mode: 0644]
test_inputs/codegen/omega/gc-0.in [new file with mode: 0644]
test_inputs/codegen/omega/ge-0.c [new file with mode: 0644]
test_inputs/codegen/omega/ge-0.in [new file with mode: 0644]
test_inputs/codegen/omega/ge-1.c [new file with mode: 0644]
test_inputs/codegen/omega/ge-1.in [new file with mode: 0644]
test_inputs/codegen/omega/gist-0.c [new file with mode: 0644]
test_inputs/codegen/omega/gist-0.in [new file with mode: 0644]
test_inputs/codegen/omega/gist-1.c [new file with mode: 0644]
test_inputs/codegen/omega/gist-1.in [new file with mode: 0644]
test_inputs/codegen/omega/gist-2.c [new file with mode: 0644]
test_inputs/codegen/omega/gist-2.in [new file with mode: 0644]
test_inputs/codegen/omega/gist-3.c [new file with mode: 0644]
test_inputs/codegen/omega/gist-3.in [new file with mode: 0644]
test_inputs/codegen/omega/gist-4.c [new file with mode: 0644]
test_inputs/codegen/omega/gist-4.in [new file with mode: 0644]
test_inputs/codegen/omega/gist-5.c [new file with mode: 0644]
test_inputs/codegen/omega/gist-5.in [new file with mode: 0644]
test_inputs/codegen/omega/guard1-0.c [new file with mode: 0644]
test_inputs/codegen/omega/guard1-0.in [new file with mode: 0644]
test_inputs/codegen/omega/guard1-1.c [new file with mode: 0644]
test_inputs/codegen/omega/guard1-1.in [new file with mode: 0644]
test_inputs/codegen/omega/hpf-0.c [new file with mode: 0644]
test_inputs/codegen/omega/hpf-0.in [new file with mode: 0644]
test_inputs/codegen/omega/if_then-0.c [new file with mode: 0644]
test_inputs/codegen/omega/if_then-0.in [new file with mode: 0644]
test_inputs/codegen/omega/if_then-1.c [new file with mode: 0644]
test_inputs/codegen/omega/if_then-1.in [new file with mode: 0644]
test_inputs/codegen/omega/if_then-2.c [new file with mode: 0644]
test_inputs/codegen/omega/if_then-2.in [new file with mode: 0644]
test_inputs/codegen/omega/if_then-3.c [new file with mode: 0644]
test_inputs/codegen/omega/if_then-3.in [new file with mode: 0644]
test_inputs/codegen/omega/if_then-4.c [new file with mode: 0644]
test_inputs/codegen/omega/if_then-4.in [new file with mode: 0644]
test_inputs/codegen/omega/if_then-5.c [new file with mode: 0644]
test_inputs/codegen/omega/if_then-5.in [new file with mode: 0644]
test_inputs/codegen/omega/iter1-0.c [new file with mode: 0644]
test_inputs/codegen/omega/iter1-0.in [new file with mode: 0644]
test_inputs/codegen/omega/iter2-0.c [new file with mode: 0644]
test_inputs/codegen/omega/iter2-0.in [new file with mode: 0644]
test_inputs/codegen/omega/iter3-0.c [new file with mode: 0644]
test_inputs/codegen/omega/iter3-0.in [new file with mode: 0644]
test_inputs/codegen/omega/iter4-0.c [new file with mode: 0644]
test_inputs/codegen/omega/iter4-0.in [new file with mode: 0644]
test_inputs/codegen/omega/iter5-0.c [new file with mode: 0644]
test_inputs/codegen/omega/iter5-0.in [new file with mode: 0644]
test_inputs/codegen/omega/iter6-0.c [new file with mode: 0644]
test_inputs/codegen/omega/iter6-0.in [new file with mode: 0644]
test_inputs/codegen/omega/iter6-1.c [new file with mode: 0644]
test_inputs/codegen/omega/iter6-1.in [new file with mode: 0644]
test_inputs/codegen/omega/iter7-0.c [new file with mode: 0644]
test_inputs/codegen/omega/iter7-0.in [new file with mode: 0644]
test_inputs/codegen/omega/iter8-0.c [new file with mode: 0644]
test_inputs/codegen/omega/iter8-0.in [new file with mode: 0644]
test_inputs/codegen/omega/iter9-0.c [new file with mode: 0644]
test_inputs/codegen/omega/iter9-0.in [new file with mode: 0644]
test_inputs/codegen/omega/lefur00-0.c [new file with mode: 0644]
test_inputs/codegen/omega/lefur00-0.in [new file with mode: 0644]
test_inputs/codegen/omega/lefur01-0.c [new file with mode: 0644]
test_inputs/codegen/omega/lefur01-0.in [new file with mode: 0644]
test_inputs/codegen/omega/lefur01-1.c [new file with mode: 0644]
test_inputs/codegen/omega/lefur01-1.in [new file with mode: 0644]
test_inputs/codegen/omega/lefur03-0.c [new file with mode: 0644]
test_inputs/codegen/omega/lefur03-0.in [new file with mode: 0644]
test_inputs/codegen/omega/lefur04-0.c [new file with mode: 0644]
test_inputs/codegen/omega/lefur04-0.in [new file with mode: 0644]
test_inputs/codegen/omega/lift1-0.c [new file with mode: 0644]
test_inputs/codegen/omega/lift1-0.in [new file with mode: 0644]
test_inputs/codegen/omega/lift1-1.c [new file with mode: 0644]
test_inputs/codegen/omega/lift1-1.in [new file with mode: 0644]
test_inputs/codegen/omega/lift1-2.c [new file with mode: 0644]
test_inputs/codegen/omega/lift1-2.in [new file with mode: 0644]
test_inputs/codegen/omega/lift1-3.c [new file with mode: 0644]
test_inputs/codegen/omega/lift1-3.in [new file with mode: 0644]
test_inputs/codegen/omega/lift1-4.c [new file with mode: 0644]
test_inputs/codegen/omega/lift1-4.in [new file with mode: 0644]
test_inputs/codegen/omega/lift1-5.c [new file with mode: 0644]
test_inputs/codegen/omega/lift1-5.in [new file with mode: 0644]
test_inputs/codegen/omega/lift2-0.c [new file with mode: 0644]
test_inputs/codegen/omega/lift2-0.in [new file with mode: 0644]
test_inputs/codegen/omega/lift2-1.c [new file with mode: 0644]
test_inputs/codegen/omega/lift2-1.in [new file with mode: 0644]
test_inputs/codegen/omega/lift2-2.c [new file with mode: 0644]
test_inputs/codegen/omega/lift2-2.in [new file with mode: 0644]
test_inputs/codegen/omega/lift2-3.c [new file with mode: 0644]
test_inputs/codegen/omega/lift2-3.in [new file with mode: 0644]
test_inputs/codegen/omega/lift2-4.c [new file with mode: 0644]
test_inputs/codegen/omega/lift2-4.in [new file with mode: 0644]
test_inputs/codegen/omega/lift2-5.c [new file with mode: 0644]
test_inputs/codegen/omega/lift2-5.in [new file with mode: 0644]
test_inputs/codegen/omega/lu-0.c [new file with mode: 0644]
test_inputs/codegen/omega/lu-0.in [new file with mode: 0644]
test_inputs/codegen/omega/lu-1.c [new file with mode: 0644]
test_inputs/codegen/omega/lu-1.in [new file with mode: 0644]
test_inputs/codegen/omega/lu-2.c [new file with mode: 0644]
test_inputs/codegen/omega/lu-2.in [new file with mode: 0644]
test_inputs/codegen/omega/lu-3.c [new file with mode: 0644]
test_inputs/codegen/omega/lu-3.in [new file with mode: 0644]
test_inputs/codegen/omega/lu_ijk-0.c [new file with mode: 0644]
test_inputs/codegen/omega/lu_ijk-0.in [new file with mode: 0644]
test_inputs/codegen/omega/lu_ijk-1.c [new file with mode: 0644]
test_inputs/codegen/omega/lu_ijk-1.in [new file with mode: 0644]
test_inputs/codegen/omega/lu_ijk-2.c [new file with mode: 0644]
test_inputs/codegen/omega/lu_ijk-2.in [new file with mode: 0644]
test_inputs/codegen/omega/lu_spmd-0.c [new file with mode: 0644]
test_inputs/codegen/omega/lu_spmd-0.in [new file with mode: 0644]
test_inputs/codegen/omega/lu_spmd-1.c [new file with mode: 0644]
test_inputs/codegen/omega/lu_spmd-1.in [new file with mode: 0644]
test_inputs/codegen/omega/m1-0.c [new file with mode: 0644]
test_inputs/codegen/omega/m1-0.in [new file with mode: 0644]
test_inputs/codegen/omega/m1-1.c [new file with mode: 0644]
test_inputs/codegen/omega/m1-1.in [new file with mode: 0644]
test_inputs/codegen/omega/m10-0.c [new file with mode: 0644]
test_inputs/codegen/omega/m10-0.in [new file with mode: 0644]
test_inputs/codegen/omega/m10-1.c [new file with mode: 0644]
test_inputs/codegen/omega/m10-1.in [new file with mode: 0644]
test_inputs/codegen/omega/m11-0.c [new file with mode: 0644]
test_inputs/codegen/omega/m11-0.in [new file with mode: 0644]
test_inputs/codegen/omega/m12-0.c [new file with mode: 0644]
test_inputs/codegen/omega/m12-0.in [new file with mode: 0644]
test_inputs/codegen/omega/m12-1.c [new file with mode: 0644]
test_inputs/codegen/omega/m12-1.in [new file with mode: 0644]
test_inputs/codegen/omega/m2-0.c [new file with mode: 0644]
test_inputs/codegen/omega/m2-0.in [new file with mode: 0644]
test_inputs/codegen/omega/m2-1.c [new file with mode: 0644]
test_inputs/codegen/omega/m2-1.in [new file with mode: 0644]
test_inputs/codegen/omega/m3-0.c [new file with mode: 0644]
test_inputs/codegen/omega/m3-0.in [new file with mode: 0644]
test_inputs/codegen/omega/m4-0.c [new file with mode: 0644]
test_inputs/codegen/omega/m4-0.in [new file with mode: 0644]
test_inputs/codegen/omega/m4-1.c [new file with mode: 0644]
test_inputs/codegen/omega/m4-1.in [new file with mode: 0644]
test_inputs/codegen/omega/m7-0.c [new file with mode: 0644]
test_inputs/codegen/omega/m7-0.in [new file with mode: 0644]
test_inputs/codegen/omega/m7-1.c [new file with mode: 0644]
test_inputs/codegen/omega/m7-1.in [new file with mode: 0644]
test_inputs/codegen/omega/m8-0.c [new file with mode: 0644]
test_inputs/codegen/omega/m8-0.in [new file with mode: 0644]
test_inputs/codegen/omega/m8-1.c [new file with mode: 0644]
test_inputs/codegen/omega/m8-1.in [new file with mode: 0644]
test_inputs/codegen/omega/m9-0.c [new file with mode: 0644]
test_inputs/codegen/omega/m9-0.in [new file with mode: 0644]
test_inputs/codegen/omega/m9-1.c [new file with mode: 0644]
test_inputs/codegen/omega/m9-1.in [new file with mode: 0644]
test_inputs/codegen/omega/olda-0.c [new file with mode: 0644]
test_inputs/codegen/omega/olda-0.in [new file with mode: 0644]
test_inputs/codegen/omega/olda-1.c [new file with mode: 0644]
test_inputs/codegen/omega/olda-1.in [new file with mode: 0644]
test_inputs/codegen/omega/p.delft-0.c [new file with mode: 0644]
test_inputs/codegen/omega/p.delft-0.in [new file with mode: 0644]
test_inputs/codegen/omega/p.delft2-0.c [new file with mode: 0644]
test_inputs/codegen/omega/p.delft2-0.in [new file with mode: 0644]
test_inputs/codegen/omega/p6-0.c [new file with mode: 0644]
test_inputs/codegen/omega/p6-0.in [new file with mode: 0644]
test_inputs/codegen/omega/p6-1.c [new file with mode: 0644]
test_inputs/codegen/omega/p6-1.in [new file with mode: 0644]
test_inputs/codegen/omega/stride1-0.c [new file with mode: 0644]
test_inputs/codegen/omega/stride1-0.in [new file with mode: 0644]
test_inputs/codegen/omega/stride2-0.c [new file with mode: 0644]
test_inputs/codegen/omega/stride2-0.in [new file with mode: 0644]
test_inputs/codegen/omega/stride3-0.c [new file with mode: 0644]
test_inputs/codegen/omega/stride3-0.in [new file with mode: 0644]
test_inputs/codegen/omega/stride4-0.c [new file with mode: 0644]
test_inputs/codegen/omega/stride4-0.in [new file with mode: 0644]
test_inputs/codegen/omega/stride5-0.c [new file with mode: 0644]
test_inputs/codegen/omega/stride5-0.in [new file with mode: 0644]
test_inputs/codegen/omega/stride6-0.c [new file with mode: 0644]
test_inputs/codegen/omega/stride6-0.in [new file with mode: 0644]
test_inputs/codegen/omega/stride6-1.c [new file with mode: 0644]
test_inputs/codegen/omega/stride6-1.in [new file with mode: 0644]
test_inputs/codegen/omega/stride6-2.c [new file with mode: 0644]
test_inputs/codegen/omega/stride6-2.in [new file with mode: 0644]
test_inputs/codegen/omega/stride7-0.c [new file with mode: 0644]
test_inputs/codegen/omega/stride7-0.in [new file with mode: 0644]
test_inputs/codegen/omega/stride7-1.c [new file with mode: 0644]
test_inputs/codegen/omega/stride7-1.in [new file with mode: 0644]
test_inputs/codegen/omega/substitution-0.c [new file with mode: 0644]
test_inputs/codegen/omega/substitution-0.in [new file with mode: 0644]
test_inputs/codegen/omega/substitution-1.c [new file with mode: 0644]
test_inputs/codegen/omega/substitution-1.in [new file with mode: 0644]
test_inputs/codegen/omega/substitution-2.c [new file with mode: 0644]
test_inputs/codegen/omega/substitution-2.in [new file with mode: 0644]
test_inputs/codegen/omega/substitution-3.c [new file with mode: 0644]
test_inputs/codegen/omega/substitution-3.in [new file with mode: 0644]
test_inputs/codegen/omega/substitution-4.c [new file with mode: 0644]
test_inputs/codegen/omega/substitution-4.in [new file with mode: 0644]
test_inputs/codegen/omega/syr2k-0.c [new file with mode: 0644]
test_inputs/codegen/omega/syr2k-0.in [new file with mode: 0644]
test_inputs/codegen/omega/syr2k-1.c [new file with mode: 0644]
test_inputs/codegen/omega/syr2k-1.in [new file with mode: 0644]
test_inputs/codegen/omega/syr2k-2.c [new file with mode: 0644]
test_inputs/codegen/omega/syr2k-2.in [new file with mode: 0644]
test_inputs/codegen/omega/syr2k-3.c [new file with mode: 0644]
test_inputs/codegen/omega/syr2k-3.in [new file with mode: 0644]
test_inputs/codegen/omega/ts1d-check-sblock-0.c [new file with mode: 0644]
test_inputs/codegen/omega/ts1d-check-sblock-0.in [new file with mode: 0644]
test_inputs/codegen/omega/ts1d-check0-0.c [new file with mode: 0644]
test_inputs/codegen/omega/ts1d-check0-0.in [new file with mode: 0644]
test_inputs/codegen/omega/ts1d-mp-i_ts-m_b-0.c [new file with mode: 0644]
test_inputs/codegen/omega/ts1d-mp-i_ts-m_b-0.in [new file with mode: 0644]
test_inputs/codegen/omega/ts1d-orig0-0.c [new file with mode: 0644]
test_inputs/codegen/omega/ts1d-orig0-0.in [new file with mode: 0644]
test_inputs/codegen/omega/wak1-0.c [new file with mode: 0644]
test_inputs/codegen/omega/wak1-0.in [new file with mode: 0644]
test_inputs/codegen/omega/wak1-1.c [new file with mode: 0644]
test_inputs/codegen/omega/wak1-1.in [new file with mode: 0644]
test_inputs/codegen/omega/wak2-0.c [new file with mode: 0644]
test_inputs/codegen/omega/wak2-0.in [new file with mode: 0644]
test_inputs/codegen/omega/wak2-1.c [new file with mode: 0644]
test_inputs/codegen/omega/wak2-1.in [new file with mode: 0644]
test_inputs/codegen/omega/wak3-0.c [new file with mode: 0644]
test_inputs/codegen/omega/wak3-0.in [new file with mode: 0644]
test_inputs/codegen/omega/wak3-1.c [new file with mode: 0644]
test_inputs/codegen/omega/wak3-1.in [new file with mode: 0644]
test_inputs/codegen/omega/wak4-0.c [new file with mode: 0644]
test_inputs/codegen/omega/wak4-0.in [new file with mode: 0644]
test_inputs/codegen/omega/wak4-1.c [new file with mode: 0644]
test_inputs/codegen/omega/wak4-1.in [new file with mode: 0644]
test_inputs/codegen/omega/x-0.c [new file with mode: 0644]
test_inputs/codegen/omega/x-0.in [new file with mode: 0644]
test_inputs/codegen/omega/x-1.c [new file with mode: 0644]
test_inputs/codegen/omega/x-1.in [new file with mode: 0644]
test_inputs/codegen/pldi2012/README [new file with mode: 0644]
test_inputs/codegen/pldi2012/figure7_b.c [new file with mode: 0644]
test_inputs/codegen/pldi2012/figure7_b.in [new file with mode: 0644]
test_inputs/codegen/pldi2012/figure7_c.c [new file with mode: 0644]
test_inputs/codegen/pldi2012/figure7_c.in [new file with mode: 0644]
test_inputs/codegen/pldi2012/figure7_d.c [new file with mode: 0644]
test_inputs/codegen/pldi2012/figure7_d.in [new file with mode: 0644]
test_inputs/codegen/pldi2012/figure8_a.c [new file with mode: 0644]
test_inputs/codegen/pldi2012/figure8_a.in [new file with mode: 0644]
test_inputs/codegen/pldi2012/figure8_b.c [new file with mode: 0644]
test_inputs/codegen/pldi2012/figure8_b.in [new file with mode: 0644]
test_inputs/codegen/separate.c [new file with mode: 0644]
test_inputs/codegen/separate.in [new file with mode: 0644]
test_inputs/codegen/separation_class.c [new file with mode: 0644]
test_inputs/codegen/separation_class.in [new file with mode: 0644]
test_inputs/codegen/shift.c [new file with mode: 0644]
test_inputs/codegen/shift.in [new file with mode: 0644]
test_inputs/codegen/shift_unroll.c [new file with mode: 0644]
test_inputs/codegen/shift_unroll.in [new file with mode: 0644]
test_inputs/codegen/stride.c [new file with mode: 0644]
test_inputs/codegen/stride.in [new file with mode: 0644]
test_inputs/codegen/stride5.c [new file with mode: 0644]
test_inputs/codegen/stride5.in [new file with mode: 0644]
test_inputs/codegen/unroll.c [new file with mode: 0644]
test_inputs/codegen/unroll.in [new file with mode: 0644]
test_inputs/codegen/unroll2.c [new file with mode: 0644]
test_inputs/codegen/unroll2.in [new file with mode: 0644]

index ec76af6..f8a623d 100644 (file)
@@ -11,8 +11,8 @@ lib_LTLIBRARIES = libisl.la
 noinst_PROGRAMS = isl_test isl_polyhedron_sample isl_pip \
        isl_polyhedron_minimize isl_polytope_scan \
        isl_polyhedron_detect_equalities isl_cat \
-       isl_closure isl_bound
-TESTS = isl_test pip_test.sh bound_test.sh
+       isl_closure isl_bound isl_codegen
+TESTS = isl_test codegen_test.sh pip_test.sh bound_test.sh
 
 if HAVE_PIPLIB
 ISL_PIPLIB = \
@@ -42,6 +42,15 @@ libisl_la_SOURCES = \
        isl_aff_private.h \
        isl_affine_hull.c \
        isl_arg.c \
+       isl_ast.c \
+       isl_ast_private.h \
+       isl_ast_build.c \
+       isl_ast_build_private.h \
+       isl_ast_build_expr.c \
+       isl_ast_build_expr.h \
+       isl_ast_codegen.c \
+       isl_ast_graft.c \
+       isl_ast_graft_private.h \
        isl_band.c \
        isl_band_private.h \
        isl_basis_reduction.h \
@@ -160,6 +169,12 @@ isl_pip_LDADD = libisl.la @GMP_LIBS@
 isl_pip_SOURCES = \
        pip.c
 
+isl_codegen_CPPFLAGS = $(INCLUDES) @GMP_CPPFLAGS@
+isl_codegen_LDFLAGS = @GMP_LDFLAGS@
+isl_codegen_LDADD = libisl.la @GMP_LIBS@
+isl_codegen_SOURCES = \
+       codegen.c
+
 isl_bound_CPPFLAGS = $(INCLUDES) @GMP_CPPFLAGS@
 isl_bound_LDFLAGS = @GMP_LDFLAGS@
 isl_bound_LDADD = libisl.la @GMP_LIBS@
@@ -199,6 +214,8 @@ pkginclude_HEADERS = \
        include/isl/aff.h \
        include/isl/aff_type.h \
        include/isl/arg.h \
+       include/isl/ast.h \
+       include/isl/ast_build.h \
        include/isl/band.h \
        include/isl/blk.h \
        include/isl/constraint.h \
diff --git a/codegen.c b/codegen.c
new file mode 100644 (file)
index 0000000..e9cd692
--- /dev/null
+++ b/codegen.c
@@ -0,0 +1,138 @@
+/*
+ * 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
+ */
+
+/* This program prints an AST that scans the domain elements of
+ * the domain of a given schedule in the order of their image(s).
+ *
+ * The input consists of three sets/relations.
+ * - a schedule
+ * - a context
+ * - a relation describing AST generation options
+ */
+
+#include <assert.h>
+#include <isl/ast.h>
+#include <isl/ast_build.h>
+#include <isl/options.h>
+#include <isl/set.h>
+
+struct options {
+       struct isl_options      *isl;
+       unsigned                 atomic;
+       unsigned                 separate;
+};
+
+ISL_ARGS_START(struct options, options_args)
+ISL_ARG_CHILD(struct options, isl, "isl", &isl_options_args, "isl options")
+ISL_ARG_BOOL(struct options, atomic, 0, "atomic", 0,
+       "globally set the atomic option")
+ISL_ARG_BOOL(struct options, separate, 0, "separate", 0,
+       "globally set the separate option")
+ISL_ARGS_END
+
+ISL_ARG_DEF(options, struct options, options_args)
+
+/* Return a universal, 1-dimensional set with the given name.
+ */
+static __isl_give isl_union_set *universe(isl_ctx *ctx, const char *name)
+{
+       isl_space *space;
+
+       space = isl_space_set_alloc(ctx, 0, 1);
+       space = isl_space_set_tuple_name(space, isl_dim_set, name);
+       return isl_union_set_from_set(isl_set_universe(space));
+}
+
+/* Set the "name" option for the entire schedule domain.
+ */
+static __isl_give isl_union_map *set_universe(__isl_take isl_union_map *opt,
+       __isl_keep isl_union_map *schedule, const char *name)
+{
+       isl_ctx *ctx;
+       isl_union_set *domain, *target;
+       isl_union_map *option;
+
+       ctx = isl_union_map_get_ctx(opt);
+
+       domain = isl_union_map_range(isl_union_map_copy(schedule));
+       domain = isl_union_set_universe(domain);
+       target = universe(ctx, name);
+       option = isl_union_map_from_domain_and_range(domain, target);
+       opt = isl_union_map_union(opt, option);
+
+       return opt;
+}
+
+/* Update the build options based on the user-specified options.
+ *
+ * If the --separate or --atomic options were specified, then
+ * we clear any separate or atomic options that may already exist in "opt".
+ */
+static __isl_give isl_ast_build *set_options(__isl_take isl_ast_build *build,
+       __isl_take isl_union_map *opt, struct options *options,
+       __isl_keep isl_union_map *schedule)
+{
+       if (options->separate || options->atomic) {
+               isl_ctx *ctx;
+               isl_union_set *target;
+
+               ctx = isl_union_map_get_ctx(schedule);
+
+               target = universe(ctx, "separate");
+               opt = isl_union_map_subtract_range(opt, target);
+               target = universe(ctx, "atomic");
+               opt = isl_union_map_subtract_range(opt, target);
+       }
+
+       if (options->separate)
+               opt = set_universe(opt, schedule, "separate");
+       if (options->atomic)
+               opt = set_universe(opt, schedule, "atomic");
+
+       build = isl_ast_build_set_options(build, opt);
+
+       return build;
+}
+
+int main(int argc, char **argv)
+{
+       isl_ctx *ctx;
+       isl_set *context;
+       isl_union_map *schedule;
+       isl_union_map *options_map;
+       isl_ast_build *build;
+       isl_ast_node *tree;
+       struct options *options;
+       isl_printer *p;
+
+       options = options_new_with_defaults();
+       assert(options);
+       argc = options_parse(options, argc, argv, ISL_ARG_ALL);
+
+       ctx = isl_ctx_alloc_with_options(&options_args, options);
+
+       schedule = isl_union_map_read_from_file(ctx, stdin);
+       context = isl_set_read_from_file(ctx, stdin);
+       options_map = isl_union_map_read_from_file(ctx, stdin);
+
+       build = isl_ast_build_from_context(context);
+       build = set_options(build, options_map, options, schedule);
+       tree = isl_ast_build_ast_from_schedule(build, schedule);
+       isl_ast_build_free(build);
+
+       p = isl_printer_to_file(ctx, stdout);
+       p = isl_printer_set_output_format(p, ISL_FORMAT_C);
+       p = isl_printer_print_ast_node(p, tree);
+       isl_printer_free(p);
+
+       isl_ast_node_free(tree);
+
+       isl_ctx_free(ctx);
+       return 0;
+}
diff --git a/codegen_test.sh.in b/codegen_test.sh.in
new file mode 100644 (file)
index 0000000..4a4852d
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+EXEEXT=@EXEEXT@
+srcdir=@srcdir@
+
+for i in $srcdir/test_inputs/codegen/*.in \
+               $srcdir/test_inputs/codegen/cloog/*.in \
+               $srcdir/test_inputs/codegen/omega/*.in \
+               $srcdir/test_inputs/codegen/pldi2012/*.in; do
+       echo $i;
+       test=test-`basename $i .in`.c
+       ref=${i%.in}.c
+       (./isl_codegen$EXEEXT < $i > $test &&
+        diff -uw $ref $test && rm $test) || exit
+done
index 59f0c91..68e3167 100644 (file)
@@ -197,6 +197,7 @@ if test $with_clang = system; then
        AC_CONFIG_FILES(interface/Makefile)
 fi
 AC_CONFIG_FILES([bound_test.sh], [chmod +x bound_test.sh])
+AC_CONFIG_FILES([codegen_test.sh], [chmod +x codegen_test.sh])
 AC_CONFIG_FILES([pip_test.sh], [chmod +x pip_test.sh])
 AC_CONFIG_COMMANDS_POST([
        dnl pass on arguments to subdir configures, but don't
index bed85d8..c9c0b39 100644 (file)
@@ -3055,7 +3055,7 @@ returning a basic set or relation.
 
 Lists are defined over several element types, including
 C<isl_id>, C<isl_aff>, C<isl_pw_aff>, C<isl_constraint>,
-C<isl_basic_set> and C<isl_set>.
+C<isl_basic_set>, C<isl_set>, C<isl_ast_expr> and C<isl_ast_node>.
 Here we take lists of C<isl_set>s as an example.
 Lists can be created, copied, modified and freed using the following functions.
 
@@ -5179,6 +5179,830 @@ schedules.
 
 =back
 
+=head2 AST Generation
+
+This section describes the C<isl> functionality for generating
+ASTs that visit all the elements
+in a domain in an order specified by a schedule.
+In particular, given a C<isl_union_map>, an AST is generated
+that visits all the elements in the domain of the C<isl_union_map>
+according to the lexicographic order of the corresponding image
+element(s).  If the range of the C<isl_union_map> consists of
+elements in more than one space, then each of these spaces is handled
+separately in an arbitrary order.
+It should be noted that the image elements only specify the I<order>
+in which the corresponding domain elements should be visited.
+No direct relation between the image elements and the loop iterators
+in the generated AST should be assumed.
+
+Each AST is generated within a build.  The initial build
+simply specifies the constraints on the parameters (if any)
+and can be created, inspected, copied and freed using the following functions.
+
+       #include <isl/ast_build.h>
+       __isl_give isl_ast_build *isl_ast_build_from_context(
+               __isl_take isl_set *set);
+       isl_ctx *isl_ast_build_get_ctx(
+               __isl_keep isl_ast_build *build);
+       __isl_give isl_ast_build *isl_ast_build_copy(
+               __isl_keep isl_ast_build *build);
+       void *isl_ast_build_free(
+               __isl_take isl_ast_build *build);
+
+The C<set> argument is usually a parameter set with zero or more parameters.
+More C<isl_ast_build> functions are described in L</"Nested AST Generation">
+and L</"Fine-grained Control over AST Generation">.
+Finally, the AST itself can be constructed using the following
+function.
+
+       #include <isl/ast_build.h>
+       __isl_give isl_ast_node *isl_ast_build_ast_from_schedule(
+               __isl_keep isl_ast_build *build,
+               __isl_take isl_union_map *schedule);
+
+=head3 Inspecting the AST
+
+The basic properties of an AST node can be obtained as follows.
+
+       #include <isl/ast.h>
+       isl_ctx *isl_ast_node_get_ctx(
+               __isl_keep isl_ast_node *node);
+       enum isl_ast_node_type isl_ast_node_get_type(
+               __isl_keep isl_ast_node *node);
+
+The type of an AST node is one of
+C<isl_ast_node_for>,
+C<isl_ast_node_if>,
+C<isl_ast_node_block> or
+C<isl_ast_node_user>.
+An C<isl_ast_node_for> represents a for node.
+An C<isl_ast_node_if> represents an if node.
+An C<isl_ast_node_block> represents a compound node.
+An C<isl_ast_node_user> represents an expression statement.
+An expression statement typically corresponds to a domain element, i.e.,
+one of the elements that is visited by the AST.
+
+Each type of node has its own additional properties.
+
+       #include <isl/ast.h>
+       __isl_give isl_ast_expr *isl_ast_node_for_get_iterator(
+               __isl_keep isl_ast_node *node);
+       __isl_give isl_ast_expr *isl_ast_node_for_get_init(
+               __isl_keep isl_ast_node *node);
+       __isl_give isl_ast_expr *isl_ast_node_for_get_cond(
+               __isl_keep isl_ast_node *node);
+       __isl_give isl_ast_expr *isl_ast_node_for_get_inc(
+               __isl_keep isl_ast_node *node);
+       __isl_give isl_ast_node *isl_ast_node_for_get_body(
+               __isl_keep isl_ast_node *node);
+       int isl_ast_node_for_is_degenerate(
+               __isl_keep isl_ast_node *node);
+
+An C<isl_ast_for> is considered degenerate if it is known to execute
+exactly once.
+
+       #include <isl/ast.h>
+       __isl_give isl_ast_expr *isl_ast_node_if_get_cond(
+               __isl_keep isl_ast_node *node);
+       __isl_give isl_ast_node *isl_ast_node_if_get_then(
+               __isl_keep isl_ast_node *node);
+       int isl_ast_node_if_has_else(
+               __isl_keep isl_ast_node *node);
+       __isl_give isl_ast_node *isl_ast_node_if_get_else(
+               __isl_keep isl_ast_node *node);
+
+       __isl_give isl_ast_node_list *
+       isl_ast_node_block_get_children(
+               __isl_keep isl_ast_node *node);
+
+       __isl_give isl_ast_expr *isl_ast_node_user_get_expr(
+               __isl_keep isl_ast_node *node);
+
+Each of the returned C<isl_ast_expr>s can in turn be inspected using
+the following functions.
+
+       #include <isl/ast.h>
+       isl_ctx *isl_ast_expr_get_ctx(
+               __isl_keep isl_ast_expr *expr);
+       enum isl_ast_expr_type isl_ast_expr_get_type(
+               __isl_keep isl_ast_expr *expr);
+
+The type of an AST expression is one of
+C<isl_ast_expr_op>,
+C<isl_ast_expr_id> or
+C<isl_ast_expr_int>.
+An C<isl_ast_expr_op> represents the result of an operation.
+An C<isl_ast_expr_id> represents an identifier.
+An C<isl_ast_expr_int> represents an integer value.
+
+Each type of expression has its own additional properties.
+
+       #include <isl/ast.h>
+       enum isl_ast_op_type isl_ast_expr_get_op_type(
+               __isl_keep isl_ast_expr *expr);
+       int isl_ast_expr_get_op_n_arg(__isl_keep isl_ast_expr *expr);
+       __isl_give isl_ast_expr *isl_ast_expr_get_op_arg(
+               __isl_keep isl_ast_expr *expr, int pos);
+       int isl_ast_node_foreach_ast_op_type(
+               __isl_keep isl_ast_node *node,
+               int (*fn)(enum isl_ast_op_type type, void *user),
+               void *user);
+
+C<isl_ast_expr_get_op_type> returns the type of the operation
+performed.  C<isl_ast_expr_get_op_n_arg> returns the number of
+arguments.  C<isl_ast_expr_get_op_arg> returns the specified
+argument.
+C<isl_ast_node_foreach_ast_op_type> calls C<fn> for each distinct
+C<isl_ast_op_type> that appears in C<node>.
+The operation type is one of the following.
+
+=over
+
+=item C<isl_ast_op_and>
+
+Logical I<and> of two arguments.
+Both arguments can be evaluated.
+
+=item C<isl_ast_op_and_then>
+
+Logical I<and> of two arguments.
+The second argument can only be evaluated if the first evaluates to true.
+
+=item C<isl_ast_op_or>
+
+Logical I<or> of two arguments.
+Both arguments can be evaluated.
+
+=item C<isl_ast_op_or_else>
+
+Logical I<or> of two arguments.
+The second argument can only be evaluated if the first evaluates to false.
+
+=item C<isl_ast_op_max>
+
+Maximum of two or more arguments.
+
+=item C<isl_ast_op_min>
+
+Minimum of two or more arguments.
+
+=item C<isl_ast_op_minus>
+
+Change sign.
+
+=item C<isl_ast_op_add>
+
+Sum of two arguments.
+
+=item C<isl_ast_op_sub>
+
+Difference of two arguments.
+
+=item C<isl_ast_op_mul>
+
+Product of two arguments.
+
+=item C<isl_ast_op_div>
+
+Exact division.  That is, the result is known to be an integer.
+
+=item C<isl_ast_op_fdiv_q>
+
+Result of integer division, rounded towards negative
+infinity.
+
+=item C<isl_ast_op_pdiv_q>
+
+Result of integer division, where dividend is known to be non-negative.
+
+=item C<isl_ast_op_pdiv_r>
+
+Remainder of integer division, where dividend is known to be non-negative.
+
+=item C<isl_ast_op_cond>
+
+Conditional operator defined on three arguments.
+If the first argument evaluates to true, then the result
+is equal to the second argument.  Otherwise, the result
+is equal to the third argument.
+The second and third argument may only be evaluated if
+the first argument evaluates to true and false, respectively.
+Corresponds to C<a ? b : c> in C.
+
+=item C<isl_ast_op_select>
+
+Conditional operator defined on three arguments.
+If the first argument evaluates to true, then the result
+is equal to the second argument.  Otherwise, the result
+is equal to the third argument.
+The second and third argument may be evaluated independently
+of the value of the first argument.
+Corresponds to C<a * b + (1 - a) * c> in C.
+
+=item C<isl_ast_op_eq>
+
+Equality relation.
+
+=item C<isl_ast_op_le>
+
+Less than or equal relation.
+
+=item C<isl_ast_op_ge>
+
+Greater than or equal relation.
+
+=item C<isl_ast_op_call>
+
+A function call.
+The number of arguments of the C<isl_ast_expr> is one more than
+the number of arguments in the function call, the first argument
+representing the function being called.
+
+=back
+
+       #include <isl/ast.h>
+       __isl_give isl_id *isl_ast_expr_get_id(
+               __isl_keep isl_ast_expr *expr);
+
+Return the identifier represented by the AST expression.
+
+       #include <isl/ast.h>
+       int isl_ast_expr_get_int(__isl_keep isl_ast_expr *expr,
+               isl_int *v);
+
+Return the integer represented by the AST expression.
+Note that the integer is returned through the C<v> argument.
+The return value of the function itself indicates whether the
+operation was performed successfully.
+
+=head3 Manipulating and printing the AST
+
+AST nodes can be copied and freed using the following functions.
+
+       #include <isl/ast.h>
+       __isl_give isl_ast_node *isl_ast_node_copy(
+               __isl_keep isl_ast_node *node);
+       void *isl_ast_node_free(__isl_take isl_ast_node *node);
+
+AST expressions can be copied and freed using the following functions.
+
+       #include <isl/ast.h>
+       __isl_give isl_ast_expr *isl_ast_expr_copy(
+               __isl_keep isl_ast_expr *expr);
+       void *isl_ast_expr_free(__isl_take isl_ast_expr *expr);
+
+New AST expressions can be created either directly or within
+the context of an C<isl_ast_build>.
+
+       #include <isl/ast.h>
+       __isl_give isl_ast_expr *isl_ast_expr_from_id(
+               __isl_take isl_id *id);
+       __isl_give isl_ast_expr *isl_ast_expr_neg(
+               __isl_take isl_ast_expr *expr);
+       __isl_give isl_ast_expr *isl_ast_expr_add(
+               __isl_take isl_ast_expr *expr1,
+               __isl_take isl_ast_expr *expr2);
+       __isl_give isl_ast_expr *isl_ast_expr_sub(
+               __isl_take isl_ast_expr *expr1,
+               __isl_take isl_ast_expr *expr2);
+       __isl_give isl_ast_expr *isl_ast_expr_mul(
+               __isl_take isl_ast_expr *expr1,
+               __isl_take isl_ast_expr *expr2);
+       __isl_give isl_ast_expr *isl_ast_expr_div(
+               __isl_take isl_ast_expr *expr1,
+               __isl_take isl_ast_expr *expr2);
+       __isl_give isl_ast_expr *isl_ast_expr_and(
+               __isl_take isl_ast_expr *expr1,
+               __isl_take isl_ast_expr *expr2)
+       __isl_give isl_ast_expr *isl_ast_expr_or(
+               __isl_take isl_ast_expr *expr1,
+               __isl_take isl_ast_expr *expr2)
+
+       #include <isl/ast_build.h>
+       __isl_give isl_ast_expr *isl_ast_build_expr_from_pw_aff(
+               __isl_keep isl_ast_build *build,
+               __isl_take isl_pw_aff *pa);
+       __isl_give isl_ast_expr *
+       isl_ast_build_call_from_pw_multi_aff(
+               __isl_keep isl_ast_build *build,
+               __isl_take isl_pw_multi_aff *pma);
+
+The domains of C<pa> and C<pma> should correspond
+to the schedule space of C<build>.
+The tuple id of C<pma> is used as the function being called.
+
+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.
+
+       #include <isl/ast.h>
+       __isl_give isl_ast_node *isl_ast_node_set_annotation(
+               __isl_take isl_ast_node *node,
+               __isl_take isl_id *annotation);
+       __isl_give isl_id *isl_ast_node_get_annotation(
+               __isl_keep isl_ast_node *node);
+
+Basic printing can be performed using the following functions.
+
+       #include <isl/ast.h>
+       __isl_give isl_printer *isl_printer_print_ast_expr(
+               __isl_take isl_printer *p,
+               __isl_keep isl_ast_expr *expr);
+       __isl_give isl_printer *isl_printer_print_ast_node(
+               __isl_take isl_printer *p,
+               __isl_keep isl_ast_node *node);
+
+More advanced printing can be performed using the following functions.
+
+       #include <isl/ast.h>
+       __isl_give isl_printer *isl_ast_op_type_print_macro(
+               enum isl_ast_op_type type,
+               __isl_take isl_printer *p);
+       __isl_give isl_printer *isl_ast_node_print_macros(
+               __isl_keep isl_ast_node *node,
+               __isl_take isl_printer *p);
+       __isl_give isl_printer *isl_ast_node_print(
+               __isl_keep isl_ast_node *node,
+               __isl_take isl_printer *p,
+               __isl_keep isl_ast_print_options *options);
+       __isl_give isl_printer *isl_ast_node_for_print(
+               __isl_keep isl_ast_node *node,
+               __isl_take isl_printer *p,
+               __isl_keep isl_ast_print_options *options);
+       __isl_give isl_printer *isl_ast_node_if_print(
+               __isl_keep isl_ast_node *node,
+               __isl_take isl_printer *p,
+               __isl_keep isl_ast_print_options *options);
+
+While printing an C<isl_ast_node> in C<ISL_FORMAT_C>,
+C<isl> may print out an AST that makes use of macros such
+as C<floord>, C<min> and C<max>.
+C<isl_ast_op_type_print_macro> prints out the macro
+corresponding to a specific C<isl_ast_op_type>.
+C<isl_ast_node_print_macros> scans the C<isl_ast_node>
+for expressions where these macros would be used and prints
+out the required macro definitions.
+Essentially, C<isl_ast_node_print_macros> calls
+C<isl_ast_node_foreach_ast_op_type> with C<isl_ast_op_type_print_macro>
+as function argument.
+C<isl_ast_node_print>, C<isl_ast_node_for_print> and
+C<isl_ast_node_if_print> print an C<isl_ast_node>
+in C<ISL_FORMAT_C>, but allow for some extra control
+through an C<isl_ast_print_options> object.
+This object can be created using the following functions.
+
+       #include <isl/ast.h>
+       __isl_give isl_ast_print_options *
+       isl_ast_print_options_alloc(isl_ctx *ctx);
+       void *isl_ast_print_options_free(
+               __isl_take isl_ast_print_options *options);
+
+       __isl_give isl_ast_print_options *
+       isl_ast_print_options_set_print_user(
+               __isl_take isl_ast_print_options *options,
+               __isl_give isl_printer *(*print_user)(
+                       __isl_take isl_printer *p,
+                       __isl_keep isl_ast_node *node, void *user),
+               void *user);
+       __isl_give isl_ast_print_options *
+       isl_ast_print_options_set_print_for(
+               __isl_take isl_ast_print_options *options,
+               __isl_give isl_printer *(*print_for)(
+                       __isl_take isl_printer *p,
+                       __isl_keep isl_ast_node *node, void *user),
+               void *user);
+
+The callback set by C<isl_ast_print_options_set_print_domain>
+is called whenever a node of type C<isl_ast_node_user> needs to
+be printed.
+The callback set by C<isl_ast_print_options_set_print_for>
+is called whenever a node of type C<isl_ast_node_for> needs to
+be printed.
+Note that C<isl_ast_node_for_print> will I<not> call the
+callback set by C<isl_ast_print_options_set_print_for> on the node
+on which C<isl_ast_node_for_print> is called, but only on nested
+nodes of type C<isl_ast_node_for>.  It is therefore safe to
+call C<isl_ast_node_for_print> from within the callback set by
+C<isl_ast_print_options_set_print_for>.
+
+The following option determines the type to be used for iterators
+while printing the AST.
+
+       int isl_options_set_ast_iterator_type(
+               isl_ctx *ctx, const char *val);
+       const char *isl_options_get_ast_iterator_type(
+               isl_ctx *ctx);
+
+=head3 Options
+
+       #include <isl/ast_build.h>
+       int isl_options_set_ast_build_atomic_upper_bound(
+               isl_ctx *ctx, int val);
+       int isl_options_get_ast_build_atomic_upper_bound(
+               isl_ctx *ctx);
+       int isl_options_set_ast_build_prefer_pdiv(isl_ctx *ctx,
+               int val);
+       int isl_options_get_ast_build_prefer_pdiv(isl_ctx *ctx);
+       int isl_options_set_ast_build_exploit_nested_bounds(
+               isl_ctx *ctx, int val);
+       int isl_options_get_ast_build_exploit_nested_bounds(
+               isl_ctx *ctx);
+       int isl_options_set_ast_build_group_coscheduled(
+               isl_ctx *ctx, int val);
+       int isl_options_get_ast_build_group_coscheduled(
+               isl_ctx *ctx);
+       int isl_options_set_ast_build_scale_strides(
+               isl_ctx *ctx, int val);
+       int isl_options_get_ast_build_scale_strides(
+               isl_ctx *ctx);
+
+=over
+
+=item * ast_build_atomic_upper_bound
+
+Generate loop upper bounds that consist of the current loop iterator,
+an operator and an expression not involving the iterator.
+If this option is not set, then the current loop iterator may appear
+several times in the upper bound.
+For example, when this option is turned off, AST generation
+for the schedule
+
+       [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.
+
+=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);
+
+The callback set by C<isl_ast_build_set_at_each_domain> will
+be called for each domain AST node.
+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.
+
 =head1 Applications
 
 Although C<isl> is mainly meant to be used as a library,
@@ -5218,3 +6042,10 @@ is given, then the constant should appear in the last column.
 
 Given a polytope, C<isl_polytope_scan> prints
 all integer points in the polytope.
+
+=head2 C<isl_codegen>
+
+Given a schedule, a context set and an options relation,
+C<isl_codegen> prints out an AST that scans the domain elements
+of the schedule in the order of their image(s) taking into account
+the constraints in the context set.
diff --git a/include/isl/ast.h b/include/isl/ast.h
new file mode 100644 (file)
index 0000000..4ddc913
--- /dev/null
@@ -0,0 +1,175 @@
+#ifndef ISL_AST_H
+#define ISL_AST_H
+
+#include <isl/ctx.h>
+#include <isl/id.h>
+#include <isl/list.h>
+#include <isl/printer.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_ast_expr;
+typedef struct isl_ast_expr isl_ast_expr;
+
+struct isl_ast_node;
+typedef struct isl_ast_node isl_ast_node;
+
+enum isl_ast_op_type {
+       isl_ast_op_error = -1,
+       isl_ast_op_and,
+       isl_ast_op_and_then,
+       isl_ast_op_or,
+       isl_ast_op_or_else,
+       isl_ast_op_max,
+       isl_ast_op_min,
+       isl_ast_op_minus,
+       isl_ast_op_add,
+       isl_ast_op_sub,
+       isl_ast_op_mul,
+       isl_ast_op_div,
+       isl_ast_op_fdiv_q,      /* Round towards -infty */
+       isl_ast_op_pdiv_q,      /* Dividend is non-negative */
+       isl_ast_op_pdiv_r,      /* Dividend is non-negative */
+       isl_ast_op_cond,
+       isl_ast_op_select,
+       isl_ast_op_eq,
+       isl_ast_op_le,
+       isl_ast_op_ge,
+       isl_ast_op_call
+};
+
+enum isl_ast_expr_type {
+       isl_ast_expr_error = -1,
+       isl_ast_expr_op,
+       isl_ast_expr_id,
+       isl_ast_expr_int
+};
+
+enum isl_ast_node_type {
+       isl_ast_node_error = -1,
+       isl_ast_node_for = 1,
+       isl_ast_node_if,
+       isl_ast_node_block,
+       isl_ast_node_user
+};
+
+struct isl_ast_print_options;
+typedef struct isl_ast_print_options isl_ast_print_options;
+
+ISL_DECLARE_LIST(ast_expr)
+ISL_DECLARE_LIST(ast_node)
+
+int isl_options_set_ast_iterator_type(isl_ctx *ctx, const char *val);
+const char *isl_options_get_ast_iterator_type(isl_ctx *ctx);
+
+__isl_give isl_ast_expr *isl_ast_expr_from_id(__isl_take isl_id *id);
+__isl_give isl_ast_expr *isl_ast_expr_neg(__isl_take isl_ast_expr *expr);
+__isl_give isl_ast_expr *isl_ast_expr_add(__isl_take isl_ast_expr *expr1,
+       __isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_sub(__isl_take isl_ast_expr *expr1,
+       __isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_mul(__isl_take isl_ast_expr *expr1,
+       __isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_div(__isl_take isl_ast_expr *expr1,
+       __isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_and(__isl_take isl_ast_expr *expr1,
+       __isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_or(__isl_take isl_ast_expr *expr1,
+       __isl_take isl_ast_expr *expr2);
+
+__isl_give isl_ast_expr *isl_ast_expr_copy(__isl_keep isl_ast_expr *expr);
+void *isl_ast_expr_free(__isl_take isl_ast_expr *expr);
+
+isl_ctx *isl_ast_expr_get_ctx(__isl_keep isl_ast_expr *expr);
+enum isl_ast_expr_type isl_ast_expr_get_type(__isl_keep isl_ast_expr *expr);
+int isl_ast_expr_get_int(__isl_keep isl_ast_expr *expr, isl_int *v);
+__isl_give isl_id *isl_ast_expr_get_id(__isl_keep isl_ast_expr *expr);
+
+enum isl_ast_op_type isl_ast_expr_get_op_type(__isl_keep isl_ast_expr *expr);
+int isl_ast_expr_get_op_n_arg(__isl_keep isl_ast_expr *expr);
+__isl_give isl_ast_expr *isl_ast_expr_get_op_arg(__isl_keep isl_ast_expr *expr,
+       int pos);
+
+__isl_give isl_printer *isl_printer_print_ast_expr(__isl_take isl_printer *p,
+       __isl_keep isl_ast_expr *expr);
+void isl_ast_expr_dump(__isl_keep isl_ast_expr *expr);
+__isl_give char *isl_ast_expr_to_str(__isl_keep isl_ast_expr *expr);
+
+__isl_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);
+void *isl_ast_node_free(__isl_take isl_ast_node *node);
+
+isl_ctx *isl_ast_node_get_ctx(__isl_keep isl_ast_node *node);
+enum isl_ast_node_type isl_ast_node_get_type(__isl_keep isl_ast_node *node);
+
+__isl_give isl_ast_node *isl_ast_node_set_annotation(
+       __isl_take isl_ast_node *node, __isl_take isl_id *annotation);
+__isl_give isl_id *isl_ast_node_get_annotation(__isl_keep isl_ast_node *node);
+
+__isl_give isl_ast_expr *isl_ast_node_for_get_iterator(
+       __isl_keep isl_ast_node *node);
+__isl_give isl_ast_expr *isl_ast_node_for_get_init(
+       __isl_keep isl_ast_node *node);
+__isl_give isl_ast_expr *isl_ast_node_for_get_cond(
+       __isl_keep isl_ast_node *node);
+__isl_give isl_ast_expr *isl_ast_node_for_get_inc(
+       __isl_keep isl_ast_node *node);
+__isl_give isl_ast_node *isl_ast_node_for_get_body(
+       __isl_keep isl_ast_node *node);
+int isl_ast_node_for_is_degenerate(__isl_keep isl_ast_node *node);
+
+__isl_give isl_ast_expr *isl_ast_node_if_get_cond(
+       __isl_keep isl_ast_node *node);
+__isl_give isl_ast_node *isl_ast_node_if_get_then(
+       __isl_keep isl_ast_node *node);
+int isl_ast_node_if_has_else(__isl_keep isl_ast_node *node);
+__isl_give isl_ast_node *isl_ast_node_if_get_else(
+       __isl_keep isl_ast_node *node);
+
+__isl_give isl_ast_node_list *isl_ast_node_block_get_children(
+       __isl_keep isl_ast_node *node);
+
+__isl_give isl_ast_expr *isl_ast_node_user_get_expr(
+       __isl_keep isl_ast_node *node);
+
+__isl_give isl_printer *isl_printer_print_ast_node(__isl_take isl_printer *p,
+       __isl_keep isl_ast_node *node);
+void isl_ast_node_dump(__isl_keep isl_ast_node *node);
+
+__isl_give isl_ast_print_options *isl_ast_print_options_alloc(isl_ctx *ctx);
+void *isl_ast_print_options_free(__isl_take isl_ast_print_options *options);
+
+__isl_give isl_ast_print_options *isl_ast_print_options_set_print_user(
+       __isl_take isl_ast_print_options *options,
+       __isl_give isl_printer *(*print_user)(__isl_take isl_printer *p,
+               __isl_keep isl_ast_node *node, void *user),
+       void *user);
+__isl_give isl_ast_print_options *isl_ast_print_options_set_print_for(
+       __isl_take isl_ast_print_options *options,
+       __isl_give isl_printer *(*print_for)(__isl_take isl_printer *p,
+               __isl_keep isl_ast_node *node, void *user),
+       void *user);
+
+int isl_ast_node_foreach_ast_op_type(__isl_keep isl_ast_node *node,
+       int (*fn)(enum isl_ast_op_type type, void *user), void *user);
+__isl_give isl_printer *isl_ast_op_type_print_macro(
+       enum isl_ast_op_type type, __isl_take isl_printer *p);
+__isl_give isl_printer *isl_ast_node_print_macros(
+       __isl_keep isl_ast_node *node, __isl_take isl_printer *p);
+__isl_give isl_printer *isl_ast_node_print(__isl_keep isl_ast_node *node,
+       __isl_take isl_printer *p,
+       __isl_keep isl_ast_print_options *options);
+__isl_give isl_printer *isl_ast_node_for_print(__isl_keep isl_ast_node *node,
+       __isl_take isl_printer *p,
+       __isl_keep isl_ast_print_options *options);
+__isl_give isl_printer *isl_ast_node_if_print(__isl_keep isl_ast_node *node,
+       __isl_take isl_printer *p,
+       __isl_keep isl_ast_print_options *options);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/include/isl/ast_build.h b/include/isl/ast_build.h
new file mode 100644 (file)
index 0000000..4bae4d1
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef ISL_AST_CONTEXT_H
+#define ISL_AST_CONTEXT_H
+
+#include <isl/ctx.h>
+#include <isl/set.h>
+#include <isl/ast.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_ast_build;
+typedef struct isl_ast_build isl_ast_build;
+
+
+int isl_options_set_ast_build_atomic_upper_bound(isl_ctx *ctx, int val);
+int isl_options_get_ast_build_atomic_upper_bound(isl_ctx *ctx);
+
+int isl_options_set_ast_build_prefer_pdiv(isl_ctx *ctx, int val);
+int isl_options_get_ast_build_prefer_pdiv(isl_ctx *ctx);
+
+int isl_options_set_ast_build_exploit_nested_bounds(isl_ctx *ctx, int val);
+int isl_options_get_ast_build_exploit_nested_bounds(isl_ctx *ctx);
+
+int isl_options_set_ast_build_group_coscheduled(isl_ctx *ctx, int val);
+int isl_options_get_ast_build_group_coscheduled(isl_ctx *ctx);
+
+#define ISL_AST_BUILD_SEPARATION_BOUNDS_EXPLICIT               0
+#define ISL_AST_BUILD_SEPARATION_BOUNDS_IMPLICIT               1
+int isl_options_set_ast_build_separation_bounds(isl_ctx *ctx, int val);
+int isl_options_get_ast_build_separation_bounds(isl_ctx *ctx);
+
+int isl_options_set_ast_build_scale_strides(isl_ctx *ctx, int val);
+int isl_options_get_ast_build_scale_strides(isl_ctx *ctx);
+
+
+isl_ctx *isl_ast_build_get_ctx(__isl_keep isl_ast_build *build);
+
+__isl_give isl_ast_build *isl_ast_build_from_context(__isl_take isl_set *set);
+
+__isl_give isl_space *isl_ast_build_get_schedule_space(
+       __isl_keep isl_ast_build *build);
+__isl_give isl_union_map *isl_ast_build_get_schedule(
+       __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);
+
+__isl_give isl_ast_build *isl_ast_build_copy(
+       __isl_keep isl_ast_build *build);
+void *isl_ast_build_free(__isl_take isl_ast_build *build);
+
+__isl_give isl_ast_build *isl_ast_build_set_options(
+       __isl_take isl_ast_build *build,
+       __isl_take isl_union_map *options);
+__isl_give isl_ast_build *isl_ast_build_set_iterators(
+       __isl_take isl_ast_build *build,
+       __isl_take isl_id_list *iterators);
+__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_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_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);
+__isl_give isl_ast_build *isl_ast_build_set_create_leaf(
+       __isl_take isl_ast_build *build,
+       __isl_give isl_ast_node *(*fn)(__isl_take isl_ast_build *build,
+               void *user), void *user);
+
+__isl_give isl_ast_expr *isl_ast_build_expr_from_pw_aff(
+       __isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa);
+__isl_give isl_ast_expr *isl_ast_build_call_from_pw_multi_aff(
+       __isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma);
+
+__isl_give isl_ast_node *isl_ast_build_ast_from_schedule(
+       __isl_keep isl_ast_build *build, __isl_take isl_union_map *schedule);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/isl_ast.c b/isl_ast.c
new file mode 100644 (file)
index 0000000..dbf3904
--- /dev/null
+++ b/isl_ast.c
@@ -0,0 +1,1683 @@
+#include <isl_ast_private.h>
+#include <isl_list_private.h>
+
+#undef BASE
+#define BASE ast_expr
+
+#include <isl_list_templ.c>
+
+#undef BASE
+#define BASE ast_node
+
+#include <isl_list_templ.c>
+
+__isl_give isl_ast_print_options *isl_ast_print_options_alloc(isl_ctx *ctx)
+{
+       return isl_calloc_type(ctx, isl_ast_print_options);
+}
+
+void *isl_ast_print_options_free(__isl_take isl_ast_print_options *options)
+{
+       free(options);
+       return NULL;
+}
+
+/* Set the print_user callback of "options" to "print_user".
+ *
+ * If this callback is set, then it used to print user nodes in the AST.
+ * Otherwise, the expression associated to the user node is printed.
+ */
+__isl_give isl_ast_print_options *isl_ast_print_options_set_print_user(
+       __isl_take isl_ast_print_options *options,
+       __isl_give isl_printer *(*print_user)(__isl_take isl_printer *p,
+               __isl_keep isl_ast_node *node, void *user),
+       void *user)
+{
+       if (!options)
+               return NULL;
+
+       options->print_user = print_user;
+       options->print_user_user = user;
+
+       return options;
+}
+
+/* Set the print_for callback of "options" to "print_for".
+ *
+ * If this callback is set, then it used to print for nodes in the AST.
+ */
+__isl_give isl_ast_print_options *isl_ast_print_options_set_print_for(
+       __isl_take isl_ast_print_options *options,
+       __isl_give isl_printer *(*print_for)(__isl_take isl_printer *p,
+               __isl_keep isl_ast_node *node, void *user),
+       void *user)
+{
+       if (!options)
+               return NULL;
+
+       options->print_for = print_for;
+       options->print_for_user = user;
+
+       return options;
+}
+
+__isl_give isl_ast_expr *isl_ast_expr_copy(__isl_keep isl_ast_expr *expr)
+{
+       if (!expr)
+               return NULL;
+
+       expr->ref++;
+       return expr;
+}
+
+__isl_give isl_ast_expr *isl_ast_expr_dup(__isl_keep isl_ast_expr *expr)
+{
+       int i;
+       isl_ctx *ctx;
+       isl_ast_expr *dup;
+
+       if (!expr)
+               return NULL;
+
+       ctx = isl_ast_expr_get_ctx(expr);
+       switch (expr->type) {
+       case isl_ast_expr_int:
+               dup = isl_ast_expr_alloc_int(ctx, expr->u.i);
+               break;
+       case isl_ast_expr_id:
+               dup = isl_ast_expr_from_id(isl_id_copy(expr->u.id));
+               break;
+       case isl_ast_expr_op:
+               dup = isl_ast_expr_alloc_op(ctx,
+                                           expr->u.op.op, expr->u.op.n_arg);
+               if (!dup)
+                       return NULL;
+               for (i = 0; i < expr->u.op.n_arg; ++i)
+                       dup->u.op.args[i] =
+                               isl_ast_expr_copy(expr->u.op.args[i]);
+               break;
+       case isl_ast_expr_error:
+               dup = NULL;
+       }
+
+       if (!dup)
+               return NULL;
+
+       return dup;
+}
+
+__isl_give isl_ast_expr *isl_ast_expr_cow(__isl_take isl_ast_expr *expr)
+{
+       if (!expr)
+               return NULL;
+
+       if (expr->ref == 1)
+               return expr;
+       expr->ref--;
+       return isl_ast_expr_dup(expr);
+}
+
+void *isl_ast_expr_free(__isl_take isl_ast_expr *expr)
+{
+       int i;
+
+       if (!expr)
+               return NULL;
+
+       if (--expr->ref > 0)
+               return NULL;
+
+       isl_ctx_deref(expr->ctx);
+
+       switch (expr->type) {
+       case isl_ast_expr_int:
+               isl_int_clear(expr->u.i);
+               break;
+       case isl_ast_expr_id:
+               isl_id_free(expr->u.id);
+               break;
+       case isl_ast_expr_op:
+               for (i = 0; i < expr->u.op.n_arg; ++i)
+                       isl_ast_expr_free(expr->u.op.args[i]);
+               free(expr->u.op.args);
+               break;
+       case isl_ast_expr_error:
+               break;
+       }
+
+       free(expr);
+       return NULL;
+}
+
+isl_ctx *isl_ast_expr_get_ctx(__isl_keep isl_ast_expr *expr)
+{
+       return expr ? expr->ctx : NULL;
+}
+
+enum isl_ast_expr_type isl_ast_expr_get_type(__isl_keep isl_ast_expr *expr)
+{
+       return expr ? expr->type : isl_ast_expr_error;
+}
+
+int isl_ast_expr_get_int(__isl_keep isl_ast_expr *expr, isl_int *v)
+{
+       if (!expr)
+               return -1;
+       if (expr->type != isl_ast_expr_int)
+               isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+                       "expression not an int", return -1);
+       isl_int_set(*v, expr->u.i);
+       return 0;
+}
+
+__isl_give isl_id *isl_ast_expr_get_id(__isl_keep isl_ast_expr *expr)
+{
+       if (!expr)
+               return NULL;
+       if (expr->type != isl_ast_expr_id)
+               isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+                       "expression not an identifier", return NULL);
+
+       return isl_id_copy(expr->u.id);
+}
+
+enum isl_ast_op_type isl_ast_expr_get_op_type(__isl_keep isl_ast_expr *expr)
+{
+       if (!expr)
+               return isl_ast_op_error;
+       if (expr->type != isl_ast_expr_op)
+               isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+                       "expression not an operation", return isl_ast_op_error);
+       return expr->u.op.op;
+}
+
+int isl_ast_expr_get_op_n_arg(__isl_keep isl_ast_expr *expr)
+{
+       if (!expr)
+               return -1;
+       if (expr->type != isl_ast_expr_op)
+               isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+                       "expression not an operation", return -1);
+       return expr->u.op.n_arg;
+}
+
+__isl_give isl_ast_expr *isl_ast_expr_get_op_arg(__isl_keep isl_ast_expr *expr,
+       int pos)
+{
+       if (!expr)
+               return NULL;
+       if (expr->type != isl_ast_expr_op)
+               isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+                       "expression not an operation", return NULL);
+       if (pos < 0 || pos >= expr->u.op.n_arg)
+               isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+                       "index out of bounds", return NULL);
+
+       return isl_ast_expr_copy(expr->u.op.args[pos]);
+}
+
+/* Replace the argument at position "pos" of "expr" by "arg".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_set_op_arg(__isl_take isl_ast_expr *expr,
+       int pos, __isl_take isl_ast_expr *arg)
+{
+       expr = isl_ast_expr_cow(expr);
+       if (!expr || !arg)
+               goto error;
+       if (expr->type != isl_ast_expr_op)
+               isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+                       "expression not an operation", goto error);
+       if (pos < 0 || pos >= expr->u.op.n_arg)
+               isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+                       "index out of bounds", goto error);
+
+       isl_ast_expr_free(expr->u.op.args[pos]);
+       expr->u.op.args[pos] = arg;
+
+       return expr;
+error:
+       isl_ast_expr_free(arg);
+       return isl_ast_expr_free(expr);
+}
+
+/* Create a new operation expression of operation type "op",
+ * with "n_arg" as yet unspecified arguments.
+ */
+__isl_give isl_ast_expr *isl_ast_expr_alloc_op(isl_ctx *ctx,
+       enum isl_ast_op_type op, int n_arg)
+{
+       isl_ast_expr *expr;
+
+       expr = isl_calloc_type(ctx, isl_ast_expr);
+       if (!expr)
+               return NULL;
+
+       expr->ctx = ctx;
+       isl_ctx_ref(ctx);
+       expr->ref = 1;
+       expr->type = isl_ast_expr_op;
+       expr->u.op.op = op;
+       expr->u.op.n_arg = n_arg;
+       expr->u.op.args = isl_calloc_array(ctx, isl_ast_expr *, n_arg);
+
+       if (!expr->u.op.args)
+               return isl_ast_expr_free(expr);
+
+       return expr;
+}
+
+/* Create a new id expression representing "id".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_from_id(__isl_take isl_id *id)
+{
+       isl_ctx *ctx;
+       isl_ast_expr *expr;
+
+       if (!id)
+               return NULL;
+
+       ctx = isl_id_get_ctx(id);
+       expr = isl_calloc_type(ctx, isl_ast_expr);
+       if (!expr)
+               return isl_id_free(id);
+
+       expr->ctx = ctx;
+       isl_ctx_ref(ctx);
+       expr->ref = 1;
+       expr->type = isl_ast_expr_id;
+       expr->u.id = id;
+
+       return expr;
+}
+
+/* Create a new integer expression representing "i".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_alloc_int_si(isl_ctx *ctx, int i)
+{
+       isl_ast_expr *expr;
+
+       expr = isl_calloc_type(ctx, isl_ast_expr);
+       if (!expr)
+               return NULL;
+
+       expr->ctx = ctx;
+       isl_ctx_ref(ctx);
+       expr->ref = 1;
+       expr->type = isl_ast_expr_int;
+
+       isl_int_init(expr->u.i);
+       isl_int_set_si(expr->u.i, i);
+
+       return expr;
+}
+
+/* Create a new integer expression representing "i".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_alloc_int(isl_ctx *ctx, isl_int i)
+{
+       isl_ast_expr *expr;
+
+       expr = isl_calloc_type(ctx, isl_ast_expr);
+       if (!expr)
+               return NULL;
+
+       expr->ctx = ctx;
+       isl_ctx_ref(ctx);
+       expr->ref = 1;
+       expr->type = isl_ast_expr_int;
+
+       isl_int_init(expr->u.i);
+       isl_int_set(expr->u.i, i);
+
+       return expr;
+}
+
+/* Create an expression representing the negation of "arg".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_neg(__isl_take isl_ast_expr *arg)
+{
+       isl_ctx *ctx;
+       isl_ast_expr *expr = NULL;
+
+       if (!arg)
+               return NULL;
+
+       ctx = isl_ast_expr_get_ctx(arg);
+       expr = isl_ast_expr_alloc_op(ctx, isl_ast_op_minus, 1);
+       if (!expr)
+               goto error;
+
+       expr->u.op.args[0] = arg;
+
+       return expr;
+error:
+       isl_ast_expr_free(arg);
+       return NULL;
+}
+
+/* Create an expression representing the binary operation "type"
+ * applied to "expr1" and "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_alloc_binary(enum isl_ast_op_type type,
+       __isl_take isl_ast_expr *expr1, __isl_take isl_ast_expr *expr2)
+{
+       isl_ctx *ctx;
+       isl_ast_expr *expr = NULL;
+
+       if (!expr1 || !expr2)
+               goto error;
+
+       ctx = isl_ast_expr_get_ctx(expr1);
+       expr = isl_ast_expr_alloc_op(ctx, type, 2);
+       if (!expr)
+               goto error;
+
+       expr->u.op.args[0] = expr1;
+       expr->u.op.args[1] = expr2;
+
+       return expr;
+error:
+       isl_ast_expr_free(expr1);
+       isl_ast_expr_free(expr2);
+       return NULL;
+}
+
+/* Create an expression representing the sum of "expr1" and "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_add(__isl_take isl_ast_expr *expr1,
+       __isl_take isl_ast_expr *expr2)
+{
+       return isl_ast_expr_alloc_binary(isl_ast_op_add, expr1, expr2);
+}
+
+/* Create an expression representing the difference of "expr1" and "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_sub(__isl_take isl_ast_expr *expr1,
+       __isl_take isl_ast_expr *expr2)
+{
+       return isl_ast_expr_alloc_binary(isl_ast_op_sub, expr1, expr2);
+}
+
+/* Create an expression representing the product of "expr1" and "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_mul(__isl_take isl_ast_expr *expr1,
+       __isl_take isl_ast_expr *expr2)
+{
+       return isl_ast_expr_alloc_binary(isl_ast_op_mul, expr1, expr2);
+}
+
+/* Create an expression representing the quotient of "expr1" and "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_div(__isl_take isl_ast_expr *expr1,
+       __isl_take isl_ast_expr *expr2)
+{
+       return isl_ast_expr_alloc_binary(isl_ast_op_div, expr1, expr2);
+}
+
+/* Create an expression representing the conjunction of "expr1" and "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_and(__isl_take isl_ast_expr *expr1,
+       __isl_take isl_ast_expr *expr2)
+{
+       return isl_ast_expr_alloc_binary(isl_ast_op_and, expr1, expr2);
+}
+
+/* Create an expression representing the disjunction of "expr1" and "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_or(__isl_take isl_ast_expr *expr1,
+       __isl_take isl_ast_expr *expr2)
+{
+       return isl_ast_expr_alloc_binary(isl_ast_op_or, expr1, expr2);
+}
+
+isl_ctx *isl_ast_node_get_ctx(__isl_keep isl_ast_node *node)
+{
+       return node ? node->ctx : NULL;
+}
+
+enum isl_ast_node_type isl_ast_node_get_type(__isl_keep isl_ast_node *node)
+{
+       return node ? node->type : isl_ast_node_error;
+}
+
+__isl_give isl_ast_node *isl_ast_node_alloc(isl_ctx *ctx,
+       enum isl_ast_node_type type)
+{
+       isl_ast_node *node;
+
+       node = isl_calloc_type(ctx, isl_ast_node);
+       if (!node)
+               return NULL;
+
+       node->ctx = ctx;
+       isl_ctx_ref(ctx);
+       node->ref = 1;
+       node->type = type;
+
+       return node;
+}
+
+/* Create an if node with the given guard.
+ *
+ * The then body needs to be filled in later.
+ */
+__isl_give isl_ast_node *isl_ast_node_alloc_if(__isl_take isl_ast_expr *guard)
+{
+       isl_ast_node *node;
+
+       if (!guard)
+               return NULL;
+
+       node = isl_ast_node_alloc(isl_ast_expr_get_ctx(guard), isl_ast_node_if);
+       if (!node)
+               goto error;
+       node->u.i.guard = guard;
+
+       return node;
+error:
+       isl_ast_expr_free(guard);
+       return NULL;
+}
+
+/* Create a for node with the given iterator.
+ *
+ * The remaining fields need to be filled in later.
+ */
+__isl_give isl_ast_node *isl_ast_node_alloc_for(__isl_take isl_id *id)
+{
+       isl_ast_node *node;
+       isl_ctx *ctx;
+
+       if (!id)
+               return NULL;
+
+       ctx = isl_id_get_ctx(id);
+       node = isl_ast_node_alloc(ctx, isl_ast_node_for);
+       if (!node)
+               return NULL;
+
+       node->u.f.iterator = isl_ast_expr_from_id(id);
+       if (!node->u.f.iterator)
+               return isl_ast_node_free(node);
+
+       return node;
+}
+
+/* Create a user node evaluating "expr".
+ */
+__isl_give isl_ast_node *isl_ast_node_alloc_user(__isl_take isl_ast_expr *expr)
+{
+       isl_ctx *ctx;
+       isl_ast_node *node;
+
+       if (!expr)
+               return NULL;
+
+       ctx = isl_ast_expr_get_ctx(expr);
+       node = isl_ast_node_alloc(ctx, isl_ast_node_user);
+       if (!node)
+               goto error;
+
+       node->u.e.expr = expr;
+
+       return node;
+error:
+       isl_ast_expr_free(expr);
+       return NULL;
+}
+
+/* Create a block node with the given children.
+ */
+__isl_give isl_ast_node *isl_ast_node_alloc_block(
+       __isl_take isl_ast_node_list *list)
+{
+       isl_ast_node *node;
+       isl_ctx *ctx;
+
+       if (!list)
+               return NULL;
+
+       ctx = isl_ast_node_list_get_ctx(list);
+       node = isl_ast_node_alloc(ctx, isl_ast_node_block);
+       if (!node)
+               goto error;
+
+       node->u.b.children = list;
+
+       return node;
+error:
+       isl_ast_node_list_free(list);
+       return NULL;
+}
+
+/* Represent the given list of nodes as a single node, either by
+ * extract the node from a single element list or by creating
+ * a block node with the list of nodes as children.
+ */
+__isl_give isl_ast_node *isl_ast_node_from_ast_node_list(
+       __isl_take isl_ast_node_list *list)
+{
+       isl_ast_node *node;
+
+       if (isl_ast_node_list_n_ast_node(list) != 1)
+               return isl_ast_node_alloc_block(list);
+
+       node = isl_ast_node_list_get_ast_node(list, 0);
+       isl_ast_node_list_free(list);
+
+       return node;
+}
+
+__isl_give isl_ast_node *isl_ast_node_copy(__isl_keep isl_ast_node *node)
+{
+       if (!node)
+               return NULL;
+
+       node->ref++;
+       return node;
+}
+
+__isl_give isl_ast_node *isl_ast_node_dup(__isl_keep isl_ast_node *node)
+{
+       isl_ast_node *dup;
+
+       if (!node)
+               return NULL;
+
+       dup = isl_ast_node_alloc(isl_ast_node_get_ctx(node), node->type);
+       if (!dup)
+               return NULL;
+
+       switch (node->type) {
+       case isl_ast_node_if:
+               dup->u.i.guard = isl_ast_expr_copy(node->u.i.guard);
+               dup->u.i.then = isl_ast_node_copy(node->u.i.then);
+               dup->u.i.else_node = isl_ast_node_copy(node->u.i.else_node);
+               if (!dup->u.i.guard  || !dup->u.i.then ||
+                   (node->u.i.else_node && !dup->u.i.else_node))
+                       return isl_ast_node_free(dup);
+               break;
+       case isl_ast_node_for:
+               dup->u.f.iterator = isl_ast_expr_copy(node->u.f.iterator);
+               dup->u.f.init = isl_ast_expr_copy(node->u.f.init);
+               dup->u.f.cond = isl_ast_expr_copy(node->u.f.cond);
+               dup->u.f.inc = isl_ast_expr_copy(node->u.f.inc);
+               dup->u.f.body = isl_ast_node_copy(node->u.f.body);
+               if (!dup->u.f.iterator || !dup->u.f.init || !dup->u.f.cond ||
+                   !dup->u.f.inc || !dup->u.f.body)
+                       return isl_ast_node_free(dup);
+               break;
+       case isl_ast_node_block:
+               dup->u.b.children = isl_ast_node_list_copy(node->u.b.children);
+               if (!dup->u.b.children)
+                       return isl_ast_node_free(dup);
+               break;
+       case isl_ast_node_user:
+               dup->u.e.expr = isl_ast_expr_copy(node->u.e.expr);
+               if (!dup->u.e.expr)
+                       return isl_ast_node_free(dup);
+               break;
+       case isl_ast_node_error:
+               break;
+       }
+
+       return dup;
+}
+
+__isl_give isl_ast_node *isl_ast_node_cow(__isl_take isl_ast_node *node)
+{
+       if (!node)
+               return NULL;
+
+       if (node->ref == 1)
+               return node;
+       node->ref--;
+       return isl_ast_node_dup(node);
+}
+
+void *isl_ast_node_free(__isl_take isl_ast_node *node)
+{
+       if (!node)
+               return NULL;
+
+       if (--node->ref > 0)
+               return NULL;
+
+       switch (node->type) {
+       case isl_ast_node_if:
+               isl_ast_expr_free(node->u.i.guard);
+               isl_ast_node_free(node->u.i.then);
+               isl_ast_node_free(node->u.i.else_node);
+               break;
+       case isl_ast_node_for:
+               isl_ast_expr_free(node->u.f.iterator);
+               isl_ast_expr_free(node->u.f.init);
+               isl_ast_expr_free(node->u.f.cond);
+               isl_ast_expr_free(node->u.f.inc);
+               isl_ast_node_free(node->u.f.body);
+               break;
+       case isl_ast_node_block:
+               isl_ast_node_list_free(node->u.b.children);
+               break;
+       case isl_ast_node_user:
+               isl_ast_expr_free(node->u.e.expr);
+               break;
+       case isl_ast_node_error:
+               break;
+       }
+
+       isl_id_free(node->annotation);
+       isl_ctx_deref(node->ctx);
+       free(node);
+
+       return NULL;
+}
+
+/* Replace the body of the for node "node" by "body".
+ */
+__isl_give isl_ast_node *isl_ast_node_for_set_body(
+       __isl_take isl_ast_node *node, __isl_take isl_ast_node *body)
+{
+       node = isl_ast_node_cow(node);
+       if (!node || !body)
+               goto error;
+       if (node->type != isl_ast_node_for)
+               isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+                       "not a for node", goto error);
+
+       isl_ast_node_free(node->u.f.body);
+       node->u.f.body = body;
+
+       return node;
+error:
+       isl_ast_node_free(node);
+       isl_ast_node_free(body);
+       return NULL;
+}
+
+__isl_give isl_ast_node *isl_ast_node_for_get_body(
+       __isl_keep isl_ast_node *node)
+{
+       if (!node)
+               return NULL;
+       if (node->type != isl_ast_node_for)
+               isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+                       "not a for node", return NULL);
+       return isl_ast_node_copy(node->u.f.body);
+}
+
+/* Mark the given for node as being degenerate.
+ */
+__isl_give isl_ast_node *isl_ast_node_for_mark_degenerate(
+       __isl_take isl_ast_node *node)
+{
+       node = isl_ast_node_cow(node);
+       if (!node)
+               return NULL;
+       node->u.f.degenerate = 1;
+       return node;
+}
+
+int isl_ast_node_for_is_degenerate(__isl_keep isl_ast_node *node)
+{
+       if (!node)
+               return -1;
+       if (node->type != isl_ast_node_for)
+               isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+                       "not a for node", return -1);
+       return node->u.f.degenerate;
+}
+
+__isl_give isl_ast_expr *isl_ast_node_for_get_iterator(
+       __isl_keep isl_ast_node *node)
+{
+       if (!node)
+               return NULL;
+       if (node->type != isl_ast_node_for)
+               isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+                       "not a for node", return NULL);
+       return isl_ast_expr_copy(node->u.f.iterator);
+}
+
+__isl_give isl_ast_expr *isl_ast_node_for_get_init(
+       __isl_keep isl_ast_node *node)
+{
+       if (!node)
+               return NULL;
+       if (node->type != isl_ast_node_for)
+               isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+                       "not a for node", return NULL);
+       return isl_ast_expr_copy(node->u.f.init);
+}
+
+/* Return the condition expression of the given for node.
+ *
+ * If the for node is degenerate, then the condition is not explicitly
+ * stored in the node.  Instead, it is constructed as
+ *
+ *     iterator <= init
+ */
+__isl_give isl_ast_expr *isl_ast_node_for_get_cond(
+       __isl_keep isl_ast_node *node)
+{
+       if (!node)
+               return NULL;
+       if (node->type != isl_ast_node_for)
+               isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+                       "not a for node", return NULL);
+       if (!node->u.f.degenerate)
+               return isl_ast_expr_copy(node->u.f.cond);
+
+       return isl_ast_expr_alloc_binary(isl_ast_op_le,
+                               isl_ast_expr_copy(node->u.f.iterator),
+                               isl_ast_expr_copy(node->u.f.init));
+}
+
+/* Return the increment of the given for node.
+ *
+ * If the for node is degenerate, then the increment is not explicitly
+ * stored in the node.  We simply return "1".
+ */
+__isl_give isl_ast_expr *isl_ast_node_for_get_inc(
+       __isl_keep isl_ast_node *node)
+{
+       if (!node)
+               return NULL;
+       if (node->type != isl_ast_node_for)
+               isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+                       "not a for node", return NULL);
+       if (!node->u.f.degenerate)
+               return isl_ast_expr_copy(node->u.f.inc);
+       return isl_ast_expr_alloc_int_si(isl_ast_node_get_ctx(node), 1);
+}
+
+/* Replace the then branch of the if node "node" by "child".
+ */
+__isl_give isl_ast_node *isl_ast_node_if_set_then(
+       __isl_take isl_ast_node *node, __isl_take isl_ast_node *child)
+{
+       node = isl_ast_node_cow(node);
+       if (!node || !child)
+               goto error;
+       if (node->type != isl_ast_node_if)
+               isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+                       "not an if node", goto error);
+
+       isl_ast_node_free(node->u.i.then);
+       node->u.i.then = child;
+
+       return node;
+error:
+       isl_ast_node_free(node);
+       isl_ast_node_free(child);
+       return NULL;
+}
+
+__isl_give isl_ast_node *isl_ast_node_if_get_then(
+       __isl_keep isl_ast_node *node)
+{
+       if (!node)
+               return NULL;
+       if (node->type != isl_ast_node_if)
+               isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+                       "not an if node", return NULL);
+       return isl_ast_node_copy(node->u.i.then);
+}
+
+int isl_ast_node_if_has_else(
+       __isl_keep isl_ast_node *node)
+{
+       if (!node)
+               return -1;
+       if (node->type != isl_ast_node_if)
+               isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+                       "not an if node", return -1);
+       return node->u.i.else_node != NULL;
+}
+
+__isl_give isl_ast_node *isl_ast_node_if_get_else(
+       __isl_keep isl_ast_node *node)
+{
+       if (!node)
+               return NULL;
+       if (node->type != isl_ast_node_if)
+               isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+                       "not an if node", return NULL);
+       return isl_ast_node_copy(node->u.i.else_node);
+}
+
+__isl_give isl_ast_expr *isl_ast_node_if_get_cond(
+       __isl_keep isl_ast_node *node)
+{
+       if (!node)
+               return NULL;
+       if (node->type != isl_ast_node_if)
+               isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+                       "not a guard node", return NULL);
+       return isl_ast_expr_copy(node->u.i.guard);
+}
+
+__isl_give isl_ast_node_list *isl_ast_node_block_get_children(
+       __isl_keep isl_ast_node *node)
+{
+       if (!node)
+               return NULL;
+       if (node->type != isl_ast_node_block)
+               isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+                       "not a block node", return NULL);
+       return isl_ast_node_list_copy(node->u.b.children);
+}
+
+__isl_give isl_ast_expr *isl_ast_node_user_get_expr(
+       __isl_keep isl_ast_node *node)
+{
+       if (!node)
+               return NULL;
+
+       return isl_ast_expr_copy(node->u.e.expr);
+}
+
+__isl_give isl_id *isl_ast_node_get_annotation(__isl_keep isl_ast_node *node)
+{
+       return node ? isl_id_copy(node->annotation) : NULL;
+}
+
+/* Replace node->annotation by "annotation".
+ */
+__isl_give isl_ast_node *isl_ast_node_set_annotation(
+       __isl_take isl_ast_node *node, __isl_take isl_id *annotation)
+{
+       node = isl_ast_node_cow(node);
+       if (!node || !annotation)
+               goto error;
+
+       isl_id_free(node->annotation);
+       node->annotation = annotation;
+
+       return node;
+error:
+       isl_id_free(annotation);
+       return isl_ast_node_free(node);
+}
+
+/* Textual C representation of the various operators.
+ */
+static char *op_str[] = {
+       [isl_ast_op_and] = "&&",
+       [isl_ast_op_and_then] = "&&",
+       [isl_ast_op_or] = "||",
+       [isl_ast_op_or_else] = "||",
+       [isl_ast_op_max] = "max",
+       [isl_ast_op_min] = "min",
+       [isl_ast_op_minus] = "-",
+       [isl_ast_op_add] = "+",
+       [isl_ast_op_sub] = "-",
+       [isl_ast_op_mul] = "*",
+       [isl_ast_op_pdiv_q] = "/",
+       [isl_ast_op_pdiv_r] = "%",
+       [isl_ast_op_div] = "/",
+       [isl_ast_op_eq] = "==",
+       [isl_ast_op_le] = "<=",
+       [isl_ast_op_ge] = ">="
+};
+
+/* Precedence in C of the various operators.
+ * Based on http://en.wikipedia.org/wiki/Operators_in_C_and_C++
+ * Lowest value means highest precedence.
+ */
+static int op_prec[] = {
+       [isl_ast_op_and] = 13,
+       [isl_ast_op_and_then] = 13,
+       [isl_ast_op_or] = 14,
+       [isl_ast_op_or_else] = 14,
+       [isl_ast_op_max] = 2,
+       [isl_ast_op_min] = 2,
+       [isl_ast_op_minus] = 3,
+       [isl_ast_op_add] = 6,
+       [isl_ast_op_sub] = 6,
+       [isl_ast_op_mul] = 5,
+       [isl_ast_op_div] = 5,
+       [isl_ast_op_fdiv_q] = 2,
+       [isl_ast_op_pdiv_q] = 5,
+       [isl_ast_op_pdiv_r] = 5,
+       [isl_ast_op_cond] = 15,
+       [isl_ast_op_select] = 15,
+       [isl_ast_op_eq] = 9,
+       [isl_ast_op_le] = 8,
+       [isl_ast_op_ge] = 8,
+       [isl_ast_op_call] = 2
+};
+
+/* Is the operator left-to-right associative?
+ */
+static int op_left[] = {
+       [isl_ast_op_and] = 1,
+       [isl_ast_op_and_then] = 1,
+       [isl_ast_op_or] = 1,
+       [isl_ast_op_or_else] = 1,
+       [isl_ast_op_max] = 1,
+       [isl_ast_op_min] = 1,
+       [isl_ast_op_minus] = 0,
+       [isl_ast_op_add] = 1,
+       [isl_ast_op_sub] = 1,
+       [isl_ast_op_mul] = 1,
+       [isl_ast_op_div] = 1,
+       [isl_ast_op_fdiv_q] = 1,
+       [isl_ast_op_pdiv_q] = 1,
+       [isl_ast_op_pdiv_r] = 1,
+       [isl_ast_op_cond] = 0,
+       [isl_ast_op_select] = 0,
+       [isl_ast_op_eq] = 1,
+       [isl_ast_op_le] = 1,
+       [isl_ast_op_ge] = 1,
+       [isl_ast_op_call] = 1
+};
+
+static int is_and(enum isl_ast_op_type op)
+{
+       return op == isl_ast_op_and || op == isl_ast_op_and_then;
+}
+
+static int is_or(enum isl_ast_op_type op)
+{
+       return op == isl_ast_op_or || op == isl_ast_op_or_else;
+}
+
+static int is_add_sub(enum isl_ast_op_type op)
+{
+       return op == isl_ast_op_add || op == isl_ast_op_sub;
+}
+
+static int is_div_mod(enum isl_ast_op_type op)
+{
+       return op == isl_ast_op_div || op == isl_ast_op_pdiv_r;
+}
+
+/* Do we need/want parentheses around "expr" as a subexpression of
+ * an "op" operation?  If "left" is set, then "expr" is the left-most
+ * operand.
+ *
+ * We only need parentheses if "expr" represents an operation.
+ *
+ * If op has a higher precedence than expr->u.op.op, then we need
+ * parentheses.
+ * If op and expr->u.op.op have the same precedence, but the operations
+ * are performed in an order that is different from the associativity,
+ * then we need parentheses.
+ *
+ * An and inside an or technically does not require parentheses,
+ * but some compilers complain about that, so we add them anyway.
+ *
+ * Computations such as "a / b * c" and "a % b + c" can be somewhat
+ * difficult to read, so we add parentheses for those as well.
+ */
+static int sub_expr_need_parens(enum isl_ast_op_type op,
+       __isl_keep isl_ast_expr *expr, int left)
+{
+       if (expr->type != isl_ast_expr_op)
+               return 0;
+
+       if (op_prec[expr->u.op.op] > op_prec[op])
+               return 1;
+       if (op_prec[expr->u.op.op] == op_prec[op] && left != op_left[op])
+               return 1;
+
+       if (is_or(op) && is_and(expr->u.op.op))
+               return 1;
+       if (op == isl_ast_op_mul && expr->u.op.op != isl_ast_op_mul &&
+           op_prec[expr->u.op.op] == op_prec[op])
+               return 1;
+       if (is_add_sub(op) && is_div_mod(expr->u.op.op))
+               return 1;
+
+       return 0;
+}
+
+/* Print "expr" as a subexpression of an "op" operation.
+ * If "left" is set, then "expr" is the left-most operand.
+ */
+static __isl_give isl_printer *print_sub_expr(__isl_take isl_printer *p,
+       enum isl_ast_op_type op, __isl_keep isl_ast_expr *expr, int left)
+{
+       int need_parens;
+
+       need_parens = sub_expr_need_parens(op, expr, left);
+
+       if (need_parens)
+               p = isl_printer_print_str(p, "(");
+       p = isl_printer_print_ast_expr(p, expr);
+       if (need_parens)
+               p = isl_printer_print_str(p, ")");
+       return p;
+}
+
+/* Print a min or max reduction "expr".
+ */
+static __isl_give isl_printer *print_min_max(__isl_take isl_printer *p,
+       __isl_keep isl_ast_expr *expr)
+{
+       int i = 0;
+
+       for (i = 1; i < expr->u.op.n_arg; ++i) {
+               p = isl_printer_print_str(p, op_str[expr->u.op.op]);
+               p = isl_printer_print_str(p, "(");
+       }
+       p = isl_printer_print_ast_expr(p, expr->u.op.args[0]);
+       for (i = 1; i < expr->u.op.n_arg; ++i) {
+               p = isl_printer_print_str(p, ", ");
+               p = isl_printer_print_ast_expr(p, expr->u.op.args[i]);
+               p = isl_printer_print_str(p, ")");
+       }
+
+       return p;
+}
+
+/* Print a function call "expr".
+ *
+ * The first argument represents the function to be called.
+ */
+static __isl_give isl_printer *print_call(__isl_take isl_printer *p,
+       __isl_keep isl_ast_expr *expr)
+{
+       int i = 0;
+
+       p = isl_printer_print_ast_expr(p, expr->u.op.args[0]);
+       p = isl_printer_print_str(p, "(");
+       for (i = 1; i < expr->u.op.n_arg; ++i) {
+               if (i != 1)
+                       p = isl_printer_print_str(p, ", ");
+               p = isl_printer_print_ast_expr(p, expr->u.op.args[i]);
+       }
+       p = isl_printer_print_str(p, ")");
+
+       return p;
+}
+
+/* Print "expr" to "p".
+ *
+ * If we are printing in isl format, then we also print an indication
+ * of the size of the expression (if it was computed).
+ */
+__isl_give isl_printer *isl_printer_print_ast_expr(__isl_take isl_printer *p,
+       __isl_keep isl_ast_expr *expr)
+{
+       if (!p)
+               return NULL;
+       if (!expr)
+               return isl_printer_free(p);
+
+       switch (expr->type) {
+       case isl_ast_expr_op:
+               if (expr->u.op.op == isl_ast_op_call) {
+                       p = print_call(p, expr);
+                       break;
+               }
+               if (expr->u.op.n_arg == 1) {
+                       p = isl_printer_print_str(p, op_str[expr->u.op.op]);
+                       p = print_sub_expr(p, expr->u.op.op,
+                                               expr->u.op.args[0], 0);
+                       break;
+               }
+               if (expr->u.op.op == isl_ast_op_fdiv_q) {
+                       p = isl_printer_print_str(p, "floord(");
+                       p = isl_printer_print_ast_expr(p, expr->u.op.args[0]);
+                       p = isl_printer_print_str(p, ", ");
+                       p = isl_printer_print_ast_expr(p, expr->u.op.args[1]);
+                       p = isl_printer_print_str(p, ")");
+                       break;
+               }
+               if (expr->u.op.op == isl_ast_op_max ||
+                   expr->u.op.op == isl_ast_op_min) {
+                       p = print_min_max(p, expr);
+                       break;
+               }
+               if (expr->u.op.op == isl_ast_op_cond ||
+                   expr->u.op.op == isl_ast_op_select) {
+                       p = isl_printer_print_ast_expr(p, expr->u.op.args[0]);
+                       p = isl_printer_print_str(p, " ? ");
+                       p = isl_printer_print_ast_expr(p, expr->u.op.args[1]);
+                       p = isl_printer_print_str(p, " : ");
+                       p = isl_printer_print_ast_expr(p, expr->u.op.args[2]);
+                       break;
+               }
+               if (expr->u.op.n_arg != 2)
+                       isl_die(isl_printer_get_ctx(p), isl_error_internal,
+                               "operation should have two arguments",
+                               goto error);
+               p = print_sub_expr(p, expr->u.op.op, expr->u.op.args[0], 1);
+               p = isl_printer_print_str(p, " ");
+               p = isl_printer_print_str(p, op_str[expr->u.op.op]);
+               p = isl_printer_print_str(p, " ");
+               p = print_sub_expr(p, expr->u.op.op, expr->u.op.args[1], 0);
+               break;
+       case isl_ast_expr_id:
+               p = isl_printer_print_str(p, isl_id_get_name(expr->u.id));
+               break;
+       case isl_ast_expr_int:
+               p = isl_printer_print_isl_int(p, expr->u.i);
+               break;
+       case isl_ast_expr_error:
+               break;
+       }
+
+       return p;
+error:
+       isl_printer_free(p);
+       return NULL;
+}
+
+/* Print "node" to "p" in "isl format".
+ */
+static __isl_give isl_printer *print_ast_node_isl(__isl_take isl_printer *p,
+       __isl_keep isl_ast_node *node)
+{
+       p = isl_printer_print_str(p, "(");
+       switch (node->type) {
+       case isl_ast_node_for:
+               if (node->u.f.degenerate) {
+                       p = isl_printer_print_ast_expr(p, node->u.f.init);
+               } else {
+                       p = isl_printer_print_str(p, "init: ");
+                       p = isl_printer_print_ast_expr(p, node->u.f.init);
+                       p = isl_printer_print_str(p, ", ");
+                       p = isl_printer_print_str(p, "cond: ");
+                       p = isl_printer_print_ast_expr(p, node->u.f.cond);
+                       p = isl_printer_print_str(p, ", ");
+                       p = isl_printer_print_str(p, "inc: ");
+                       p = isl_printer_print_ast_expr(p, node->u.f.inc);
+               }
+               if (node->u.f.body) {
+                       p = isl_printer_print_str(p, ", ");
+                       p = isl_printer_print_str(p, "body: ");
+                       p = isl_printer_print_ast_node(p, node->u.f.body);
+               }
+               break;
+       case isl_ast_node_user:
+               p = isl_printer_print_ast_expr(p, node->u.e.expr);
+               break;
+       case isl_ast_node_if:
+               p = isl_printer_print_str(p, "guard: ");
+               p = isl_printer_print_ast_expr(p, node->u.i.guard);
+               if (node->u.i.then) {
+                       p = isl_printer_print_str(p, ", ");
+                       p = isl_printer_print_str(p, "then: ");
+                       p = isl_printer_print_ast_node(p, node->u.i.then);
+               }
+               if (node->u.i.else_node) {
+                       p = isl_printer_print_str(p, ", ");
+                       p = isl_printer_print_str(p, "else: ");
+                       p = isl_printer_print_ast_node(p, node->u.i.else_node);
+               }
+               break;
+       case isl_ast_node_block:
+               p = isl_printer_print_ast_node_list(p, node->u.b.children);
+               break;
+       default:
+               break;
+       }
+       p = isl_printer_print_str(p, ")");
+       return p;
+}
+
+/* Do we need to print a block around the body "node" of a for or if node?
+ *
+ * If the node is a block, then we need to print a block.
+ * Also if the node is a degenerate for then we will print it as
+ * an assignment followed by the body of the for loop, so we need a block
+ * as well.
+ */
+static int need_block(__isl_keep isl_ast_node *node)
+{
+       if (node->type == isl_ast_node_block)
+               return 1;
+       if (node->type == isl_ast_node_for && node->u.f.degenerate)
+               return 1;
+       return 0;
+}
+
+static __isl_give isl_printer *print_ast_node_c(__isl_take isl_printer *p,
+       __isl_keep isl_ast_node *node,
+       __isl_keep isl_ast_print_options *options, int in_block);
+static __isl_give isl_printer *print_if_c(__isl_take isl_printer *p,
+       __isl_keep isl_ast_node *node,
+       __isl_keep isl_ast_print_options *options, int new_line);
+
+/* Print the body "node" of a for or if node.
+ * If "else_node" is set, then it is printed as well.
+ *
+ * We first check if we need to print out a block.
+ * We always print out a block if there is an else node to make
+ * sure that the else node is matched to the correct if node.
+ *
+ * If the else node is itself an if, then we print it as
+ *
+ *     } else if (..)
+ *
+ * Otherwise the else node is printed as
+ *
+ *     } else
+ *       node
+ */
+static __isl_give isl_printer *print_body_c(__isl_take isl_printer *p,
+       __isl_keep isl_ast_node *node, __isl_keep isl_ast_node *else_node,
+       __isl_keep isl_ast_print_options *options)
+{
+       if (!node)
+               return isl_printer_free(p);
+
+       if (!else_node && !need_block(node)) {
+               p = isl_printer_end_line(p);
+               p = isl_printer_indent(p, 2);
+               p = isl_ast_node_print(node, p, options);
+               p = isl_printer_indent(p, -2);
+               return p;
+       }
+
+       p = isl_printer_print_str(p, " {");
+       p = isl_printer_end_line(p);
+       p = isl_printer_indent(p, 2);
+       p = print_ast_node_c(p, node, options, 1);
+       p = isl_printer_indent(p, -2);
+       p = isl_printer_start_line(p);
+       p = isl_printer_print_str(p, "}");
+       if (else_node) {
+               if (else_node->type == isl_ast_node_if) {
+                       p = isl_printer_print_str(p, " else ");
+                       p = print_if_c(p, else_node, options, 0);
+               } else {
+                       p = isl_printer_print_str(p, " else");
+                       p = print_body_c(p, else_node, NULL, options);
+               }
+       } else
+               p = isl_printer_end_line(p);
+
+       return p;
+}
+
+/* Print the for node "node".
+ *
+ * If the for node is degenerate, it is printed as
+ *
+ *     type iterator = init;
+ *     body
+ *
+ * Otherwise, it is printed as
+ *
+ *     for (type iterator = init; cond; iterator += inc)
+ *             body
+ *
+ * "in_block" is set if we are currently inside a block.
+ * We simply pass it along to print_ast_node_c in case of a degenerate
+ * for loop.
+ */
+static __isl_give isl_printer *print_for_c(__isl_take isl_printer *p,
+       __isl_keep isl_ast_node *node,
+       __isl_keep isl_ast_print_options *options, int in_block)
+{
+       isl_id *id;
+       const char *name;
+       const char *type;
+
+       type = isl_options_get_ast_iterator_type(isl_printer_get_ctx(p));
+       if (!node->u.f.degenerate) {
+               id = isl_ast_expr_get_id(node->u.f.iterator);
+               name = isl_id_get_name(id);
+               isl_id_free(id);
+               p = isl_printer_start_line(p);
+               p = isl_printer_print_str(p, "for (");
+               p = isl_printer_print_str(p, type);
+               p = isl_printer_print_str(p, " ");
+               p = isl_printer_print_str(p, name);
+               p = isl_printer_print_str(p, " = ");
+               p = isl_printer_print_ast_expr(p, node->u.f.init);
+               p = isl_printer_print_str(p, "; ");
+               p = isl_printer_print_ast_expr(p, node->u.f.cond);
+               p = isl_printer_print_str(p, "; ");
+               p = isl_printer_print_str(p, name);
+               p = isl_printer_print_str(p, " += ");
+               p = isl_printer_print_ast_expr(p, node->u.f.inc);
+               p = isl_printer_print_str(p, ")");
+               p = print_body_c(p, node->u.f.body, NULL, options);
+       } else {
+               id = isl_ast_expr_get_id(node->u.f.iterator);
+               name = isl_id_get_name(id);
+               isl_id_free(id);
+               p = isl_printer_start_line(p);
+               p = isl_printer_print_str(p, type);
+               p = isl_printer_print_str(p, " ");
+               p = isl_printer_print_str(p, name);
+               p = isl_printer_print_str(p, " = ");
+               p = isl_printer_print_ast_expr(p, node->u.f.init);
+               p = isl_printer_print_str(p, ";");
+               p = isl_printer_end_line(p);
+               p = print_ast_node_c(p, node->u.f.body, options, in_block);
+       }
+
+       return p;
+}
+
+/* Print the if node "node".
+ * If "new_line" is set then the if node should be printed on a new line.
+ */
+static __isl_give isl_printer *print_if_c(__isl_take isl_printer *p,
+       __isl_keep isl_ast_node *node,
+       __isl_keep isl_ast_print_options *options, int new_line)
+{
+       if (new_line)
+               p = isl_printer_start_line(p);
+       p = isl_printer_print_str(p, "if (");
+       p = isl_printer_print_ast_expr(p, node->u.i.guard);
+       p = isl_printer_print_str(p, ")");
+       p = print_body_c(p, node->u.i.then, node->u.i.else_node, options);
+
+       return p;
+}
+
+/* Print the "node" to "p".
+ *
+ * "in_block" is set if we are currently inside a block.
+ * If so, we do not print a block around the children of a block node.
+ * We do this to avoid an extra block around the body of a degenerate
+ * for node.
+ */
+static __isl_give isl_printer *print_ast_node_c(__isl_take isl_printer *p,
+       __isl_keep isl_ast_node *node,
+       __isl_keep isl_ast_print_options *options, int in_block)
+{
+       switch (node->type) {
+       case isl_ast_node_for:
+               if (options->print_for)
+                       return options->print_for(p, node,
+                                                   options->print_for_user);
+               p = print_for_c(p, node, options, in_block);
+               break;
+       case isl_ast_node_if:
+               p = print_if_c(p, node, options, 1);
+               break;
+       case isl_ast_node_block:
+               if (!in_block) {
+                       p = isl_printer_start_line(p);
+                       p = isl_printer_print_str(p, "{");
+                       p = isl_printer_end_line(p);
+                       p = isl_printer_indent(p, 2);
+               }
+               p = isl_ast_node_list_print(node->u.b.children, p, options);
+               if (!in_block) {
+                       p = isl_printer_indent(p, -2);
+                       p = isl_printer_start_line(p);
+                       p = isl_printer_print_str(p, "}");
+                       p = isl_printer_end_line(p);
+               }
+               break;
+       case isl_ast_node_user:
+               if (options->print_user)
+                       return options->print_user(p, node,
+                                                   options->print_user_user);
+               p = isl_printer_start_line(p);
+               p = isl_printer_print_ast_expr(p, node->u.e.expr);
+               p = isl_printer_print_str(p, ";");
+               p = isl_printer_end_line(p);
+               break;
+       case isl_ast_node_error:
+               break;
+       }
+       return p;
+}
+
+/* Print the for node "node" to "p".
+ */
+__isl_give isl_printer *isl_ast_node_for_print(__isl_keep isl_ast_node *node,
+       __isl_take isl_printer *p, __isl_keep isl_ast_print_options *options)
+{
+       if (!node || !options)
+               goto error;
+       if (node->type != isl_ast_node_for)
+               isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+                       "not a for node", goto error);
+       return print_for_c(p, node, options, 0);
+error:
+       isl_printer_free(p);
+       return NULL;
+}
+
+/* Print the if node "node" to "p".
+ */
+__isl_give isl_printer *isl_ast_node_if_print(__isl_keep isl_ast_node *node,
+       __isl_take isl_printer *p, __isl_keep isl_ast_print_options *options)
+{
+       if (!node || !options)
+               goto error;
+       if (node->type != isl_ast_node_if)
+               isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+                       "not an if node", goto error);
+       return print_if_c(p, node, options, 1);
+error:
+       isl_printer_free(p);
+       return NULL;
+}
+
+/* Print "node" to "p".
+ */
+__isl_give isl_printer *isl_ast_node_print(__isl_keep isl_ast_node *node,
+       __isl_take isl_printer *p, __isl_keep isl_ast_print_options *options)
+{
+       if (!options || !node)
+               goto error;
+       return print_ast_node_c(p, node, options, 0);
+error:
+       isl_printer_free(p);
+       return NULL;
+}
+
+/* Print "node" to "p".
+ */
+__isl_give isl_printer *isl_printer_print_ast_node(__isl_take isl_printer *p,
+       __isl_keep isl_ast_node *node)
+{
+       int format;
+       isl_ast_print_options *options;
+
+       if (!p)
+               return NULL;
+
+       format = isl_printer_get_output_format(p);
+       switch (format) {
+       case ISL_FORMAT_ISL:
+               p = print_ast_node_isl(p, node);
+               break;
+       case ISL_FORMAT_C:
+               options = isl_ast_print_options_alloc(isl_printer_get_ctx(p));
+               p = isl_ast_node_print(node, p, options);
+               isl_ast_print_options_free(options);
+               break;
+       default:
+               isl_die(isl_printer_get_ctx(p), isl_error_unsupported,
+                       "output format not supported for ast_node",
+                       return isl_printer_free(p));
+       }
+
+       return p;
+}
+
+/* Print the list of nodes "list" to "p".
+ */
+__isl_give isl_printer *isl_ast_node_list_print(
+       __isl_keep isl_ast_node_list *list, __isl_take isl_printer *p,
+       __isl_keep isl_ast_print_options *options)
+{
+       int i;
+
+       if (!p || !list || !options)
+               return isl_printer_free(p);
+
+       for (i = 0; i < list->n; ++i)
+               p = print_ast_node_c(p, list->p[i], options, 1);
+
+       return p;
+}
+
+#define ISL_AST_MACRO_FLOORD   (1 << 0)
+#define ISL_AST_MACRO_MIN      (1 << 1)
+#define ISL_AST_MACRO_MAX      (1 << 2)
+#define ISL_AST_MACRO_ALL      (ISL_AST_MACRO_FLOORD | \
+                                ISL_AST_MACRO_MIN | \
+                                ISL_AST_MACRO_MAX)
+
+/* If "expr" contains an isl_ast_op_min, isl_ast_op_max or isl_ast_op_fdiv_q
+ * then set the corresponding bit in "macros".
+ */
+static int ast_expr_required_macros(__isl_keep isl_ast_expr *expr, int macros)
+{
+       int i;
+
+       if (macros == ISL_AST_MACRO_ALL)
+               return macros;
+
+       if (expr->type != isl_ast_expr_op)
+               return macros;
+
+       if (expr->u.op.op == isl_ast_op_min)
+               macros |= ISL_AST_MACRO_MIN;
+       if (expr->u.op.op == isl_ast_op_max)
+               macros |= ISL_AST_MACRO_MAX;
+       if (expr->u.op.op == isl_ast_op_fdiv_q)
+               macros |= ISL_AST_MACRO_FLOORD;
+
+       for (i = 0; i < expr->u.op.n_arg; ++i)
+               macros = ast_expr_required_macros(expr->u.op.args[i], macros);
+
+       return macros;
+}
+
+static int ast_node_list_required_macros(__isl_keep isl_ast_node_list *list,
+       int macros);
+
+/* If "node" contains an isl_ast_op_min, isl_ast_op_max or isl_ast_op_fdiv_q
+ * then set the corresponding bit in "macros".
+ */
+static int ast_node_required_macros(__isl_keep isl_ast_node *node, int macros)
+{
+       if (macros == ISL_AST_MACRO_ALL)
+               return macros;
+
+       switch (node->type) {
+       case isl_ast_node_for:
+               macros = ast_expr_required_macros(node->u.f.init, macros);
+               if (!node->u.f.degenerate) {
+                       macros = ast_expr_required_macros(node->u.f.cond,
+                                                               macros);
+                       macros = ast_expr_required_macros(node->u.f.inc,
+                                                               macros);
+               }
+               macros = ast_node_required_macros(node->u.f.body, macros);
+               break;
+       case isl_ast_node_if:
+               macros = ast_expr_required_macros(node->u.i.guard, macros);
+               macros = ast_node_required_macros(node->u.i.then, macros);
+               if (node->u.i.else_node)
+                       macros = ast_node_required_macros(node->u.i.else_node,
+                                                               macros);
+               break;
+       case isl_ast_node_block:
+               macros = ast_node_list_required_macros(node->u.b.children,
+                                                       macros);
+               break;
+       case isl_ast_node_user:
+               macros = ast_expr_required_macros(node->u.e.expr, macros);
+               break;
+       case isl_ast_node_error:
+               break;
+       }
+
+       return macros;
+}
+
+/* If "list" contains an isl_ast_op_min, isl_ast_op_max or isl_ast_op_fdiv_q
+ * then set the corresponding bit in "macros".
+ */
+static int ast_node_list_required_macros(__isl_keep isl_ast_node_list *list,
+       int macros)
+{
+       int i;
+
+       for (i = 0; i < list->n; ++i)
+               macros = ast_node_required_macros(list->p[i], macros);
+
+       return macros;
+}
+
+/* Print a macro definition for the operator "type".
+ */
+__isl_give isl_printer *isl_ast_op_type_print_macro(
+       enum isl_ast_op_type type, __isl_take isl_printer *p)
+{
+       switch (type) {
+       case isl_ast_op_min:
+               p = isl_printer_start_line(p);
+               p = isl_printer_print_str(p,
+                       "#define min(x,y)    ((x) < (y) ? (x) : (y))");
+               p = isl_printer_end_line(p);
+               break;
+       case isl_ast_op_max:
+               p = isl_printer_start_line(p);
+               p = isl_printer_print_str(p,
+                       "#define max(x,y)    ((x) > (y) ? (x) : (y))");
+               p = isl_printer_end_line(p);
+               break;
+       case isl_ast_op_fdiv_q:
+               p = isl_printer_start_line(p);
+               p = isl_printer_print_str(p,
+                       "#define floord(n,d) "
+                       "(((n)<0) ? -((-(n)+(d)-1)/(d)) : (n)/(d))");
+               p = isl_printer_end_line(p);
+               break;
+       default:
+               break;
+       }
+
+       return p;
+}
+
+/* Call "fn" for each type of operation that appears in "node"
+ * and that requires a macro definition.
+ */
+int isl_ast_node_foreach_ast_op_type(__isl_keep isl_ast_node *node,
+       int (*fn)(enum isl_ast_op_type type, void *user), void *user)
+{
+       int macros;
+
+       if (!node)
+               return -1;
+
+       macros = ast_node_required_macros(node, 0);
+
+       if (macros & ISL_AST_MACRO_MIN && fn(isl_ast_op_min, user) < 0)
+               return -1;
+       if (macros & ISL_AST_MACRO_MAX && fn(isl_ast_op_max, user) < 0)
+               return -1;
+       if (macros & ISL_AST_MACRO_FLOORD && fn(isl_ast_op_fdiv_q, user) < 0)
+               return -1;
+
+       return 0;
+}
+
+static int ast_op_type_print_macro(enum isl_ast_op_type type, void *user)
+{
+       isl_printer **p = user;
+
+       *p = isl_ast_op_type_print_macro(type, *p);
+
+       return 0;
+}
+
+/* Print macro definitions for all the macros used in the result
+ * of printing "node.
+ */
+__isl_give isl_printer *isl_ast_node_print_macros(
+       __isl_keep isl_ast_node *node, __isl_take isl_printer *p)
+{
+       if (isl_ast_node_foreach_ast_op_type(node,
+                                           &ast_op_type_print_macro, &p) < 0)
+               return isl_printer_free(p);
+       return p;
+}
diff --git a/isl_ast_build.c b/isl_ast_build.c
new file mode 100644 (file)
index 0000000..5209f1f
--- /dev/null
@@ -0,0 +1,2013 @@
+/*
+ * 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/map.h>
+#include <isl/aff.h>
+#include <isl/map.h>
+#include <isl_ast_build_private.h>
+#include <isl_ast_private.h>
+
+/* Construct a map that isolates the current dimension.
+ *
+ * Essentially, the current dimension of "set" is moved to the single output
+ * dimension in the result, with the current dimension in the domain replaced
+ * by an unconstrained variable.
+ */
+__isl_give isl_map *isl_ast_build_map_to_iterator(
+       __isl_keep isl_ast_build *build, __isl_take isl_set *set)
+{
+       isl_map *map;
+
+       map = isl_map_from_domain(set);
+       map = isl_map_add_dims(map, isl_dim_out, 1);
+
+       if (!build)
+               return isl_map_free(map);
+
+       map = isl_map_equate(map, isl_dim_in, build->depth, isl_dim_out, 0);
+       map = isl_map_eliminate(map, isl_dim_in, build->depth, 1);
+
+       return map;
+}
+
+/* Initialize the information derived during the AST generation to default
+ * values for a schedule domain in "space".
+ *
+ * We also check that the remaining fields are not NULL so that
+ * the calling functions don't have to perform this test.
+ */
+static __isl_give isl_ast_build *isl_ast_build_init_derived(
+       __isl_take isl_ast_build *build, __isl_take isl_space *space)
+{
+       isl_ctx *ctx;
+       isl_vec *strides;
+
+       build = isl_ast_build_cow(build);
+       if (!build)
+               goto error;
+
+       ctx = isl_ast_build_get_ctx(build);
+       strides = isl_vec_alloc(ctx, isl_space_dim(space, isl_dim_set));
+       strides = isl_vec_set_si(strides, 1);
+
+       isl_vec_free(build->strides);
+       build->strides = strides;
+
+       space = isl_space_map_from_set(space);
+       isl_multi_aff_free(build->offsets);
+       build->offsets = isl_multi_aff_zero(isl_space_copy(space));
+       isl_multi_aff_free(build->values);
+       build->values = isl_multi_aff_identity(space);
+
+       if (!build->iterators || !build->domain || !build->generated ||
+           !build->pending || !build->values ||
+           !build->strides || !build->offsets || !build->options)
+               return isl_ast_build_free(build);
+
+       return build;
+error:
+       isl_space_free(space);
+       return isl_ast_build_free(build);
+}
+
+/* Create an isl_ast_build with "set" as domain.
+ *
+ * The input set is usually a parameter domain, but we currently allow it to
+ * be any kind of set.  We set the domain of the returned isl_ast_build
+ * to "set" and initialize all the other field to default values.
+ */
+__isl_give isl_ast_build *isl_ast_build_from_context(__isl_take isl_set *set)
+{
+       int i, n;
+       isl_ctx *ctx;
+       isl_space *space;
+       isl_ast_build *build;
+
+       set = isl_set_compute_divs(set);
+       if (!set)
+               return NULL;
+
+       ctx = isl_set_get_ctx(set);
+
+       build = isl_calloc_type(ctx, isl_ast_build);
+       if (!build)
+               goto error;
+
+       build->ref = 1;
+       build->domain = set;
+       build->generated = isl_set_copy(build->domain);
+       build->pending = isl_set_universe(isl_set_get_space(build->domain));
+       build->options = isl_union_map_empty(isl_space_params_alloc(ctx, 0));
+       n = isl_set_dim(set, isl_dim_set);
+       build->depth = n;
+       build->iterators = isl_id_list_alloc(ctx, n);
+       for (i = 0; i < n; ++i) {
+               isl_id *id = isl_set_get_dim_id(set, isl_dim_set, i);
+               build->iterators = isl_id_list_add(build->iterators, id);
+       }
+       space = isl_set_get_space(set);
+       if (isl_space_is_params(space))
+               space = isl_space_set_from_params(space);
+
+       return isl_ast_build_init_derived(build, space);
+error:
+       isl_set_free(set);
+       return NULL;
+}
+
+__isl_give isl_ast_build *isl_ast_build_copy(__isl_keep isl_ast_build *build)
+{
+       if (!build)
+               return NULL;
+
+       build->ref++;
+       return build;
+}
+
+__isl_give isl_ast_build *isl_ast_build_dup(__isl_keep isl_ast_build *build)
+{
+       isl_ctx *ctx;
+       isl_ast_build *dup;
+
+       if (!build)
+               return NULL;
+
+       ctx = isl_ast_build_get_ctx(build);
+       dup = isl_calloc_type(ctx, isl_ast_build);
+       if (!dup)
+               return NULL;
+
+       dup->ref = 1;
+       dup->outer_pos = build->outer_pos;
+       dup->depth = build->depth;
+       dup->iterators = isl_id_list_copy(build->iterators);
+       dup->domain = isl_set_copy(build->domain);
+       dup->generated = isl_set_copy(build->generated);
+       dup->pending = isl_set_copy(build->pending);
+       dup->values = isl_multi_aff_copy(build->values);
+       dup->value = isl_pw_aff_copy(build->value);
+       dup->strides = isl_vec_copy(build->strides);
+       dup->offsets = isl_multi_aff_copy(build->offsets);
+       dup->executed = isl_union_map_copy(build->executed);
+       dup->options = isl_union_map_copy(build->options);
+       dup->at_each_domain = build->at_each_domain;
+       dup->at_each_domain_user = build->at_each_domain_user;
+       dup->create_leaf = build->create_leaf;
+       dup->create_leaf_user = build->create_leaf_user;
+
+       if (!dup->iterators || !dup->domain || !dup->generated ||
+           !dup->pending || !dup->values ||
+           !dup->strides || !dup->offsets || !dup->options ||
+           (build->executed && !dup->executed) ||
+           (build->value && !dup->value))
+               return isl_ast_build_free(dup);
+
+       return dup;
+}
+
+/* Align the parameters of "build" to those of "model", introducing
+ * additional parameters if needed.
+ */
+__isl_give isl_ast_build *isl_ast_build_align_params(
+       __isl_take isl_ast_build *build, __isl_take isl_space *model)
+{
+       build = isl_ast_build_cow(build);
+       if (!build)
+               goto error;
+
+       build->domain = isl_set_align_params(build->domain,
+                                               isl_space_copy(model));
+       build->generated = isl_set_align_params(build->generated,
+                                               isl_space_copy(model));
+       build->pending = isl_set_align_params(build->pending,
+                                               isl_space_copy(model));
+       build->values = isl_multi_aff_align_params(build->values,
+                                               isl_space_copy(model));
+       build->offsets = isl_multi_aff_align_params(build->offsets,
+                                               isl_space_copy(model));
+       build->options = isl_union_map_align_params(build->options,
+                                               isl_space_copy(model));
+       isl_space_free(model);
+
+       if (!build->domain || !build->values || !build->offsets ||
+           !build->options)
+               return isl_ast_build_free(build);
+
+       return build;
+error:
+       isl_space_free(model);
+       return NULL;
+}
+
+__isl_give isl_ast_build *isl_ast_build_cow(__isl_take isl_ast_build *build)
+{
+       if (!build)
+               return NULL;
+
+       if (build->ref == 1)
+               return build;
+       build->ref--;
+       return isl_ast_build_dup(build);
+}
+
+void *isl_ast_build_free(__isl_take isl_ast_build *build)
+{
+       if (!build)
+               return NULL;
+
+       if (--build->ref > 0)
+               return NULL;
+
+       isl_id_list_free(build->iterators);
+       isl_set_free(build->domain);
+       isl_set_free(build->generated);
+       isl_set_free(build->pending);
+       isl_multi_aff_free(build->values);
+       isl_pw_aff_free(build->value);
+       isl_vec_free(build->strides);
+       isl_multi_aff_free(build->offsets);
+       isl_multi_aff_free(build->schedule_map);
+       isl_union_map_free(build->executed);
+       isl_union_map_free(build->options);
+
+       free(build);
+
+       return NULL;
+}
+
+isl_ctx *isl_ast_build_get_ctx(__isl_keep isl_ast_build *build)
+{
+       return build ? isl_set_get_ctx(build->domain) : NULL;
+}
+
+/* Replace build->options by "options".
+ */
+__isl_give isl_ast_build *isl_ast_build_set_options(
+       __isl_take isl_ast_build *build, __isl_take isl_union_map *options)
+{
+       build = isl_ast_build_cow(build);
+
+       if (!build || !options)
+               goto error;
+
+       isl_union_map_free(build->options);
+       build->options = options;
+
+       return build;
+error:
+       isl_union_map_free(options);
+       return isl_ast_build_free(build);
+}
+
+/* Set the iterators for the next code generation.
+ *
+ * If we still have some iterators left from the previous code generation
+ * (if any) or if iterators have already been set by a previous
+ * call to this function, then we remove them first.
+ */
+__isl_give isl_ast_build *isl_ast_build_set_iterators(
+       __isl_take isl_ast_build *build, __isl_take isl_id_list *iterators)
+{
+       int dim, n_it;
+
+       build = isl_ast_build_cow(build);
+       if (!build)
+               goto error;
+
+       dim = isl_set_dim(build->domain, isl_dim_set);
+       n_it = isl_id_list_n_id(build->iterators);
+       if (n_it < dim)
+               isl_die(isl_ast_build_get_ctx(build), isl_error_internal,
+                       "isl_ast_build in inconsistent state", goto error);
+       if (n_it > dim)
+               build->iterators = isl_id_list_drop(build->iterators,
+                                                       dim, n_it - dim);
+       build->iterators = isl_id_list_concat(build->iterators, iterators);
+       if (!build->iterators)
+               return isl_ast_build_free(build);
+
+       return build;
+error:
+       isl_id_list_free(iterators);
+       return isl_ast_build_free(build);
+}
+
+/* Set the "at_each_domain" callback of "build" to "fn".
+ */
+__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)
+{
+       build = isl_ast_build_cow(build);
+
+       if (!build)
+               return NULL;
+
+       build->at_each_domain = fn;
+       build->at_each_domain_user = user;
+
+       return build;
+}
+
+/* Set the "create_leaf" callback of "build" to "fn".
+ */
+__isl_give isl_ast_build *isl_ast_build_set_create_leaf(
+       __isl_take isl_ast_build *build,
+       __isl_give isl_ast_node *(*fn)(__isl_take isl_ast_build *build,
+               void *user), void *user)
+{
+       build = isl_ast_build_cow(build);
+
+       if (!build)
+               return NULL;
+
+       build->create_leaf = fn;
+       build->create_leaf_user = user;
+
+       return build;
+}
+
+/* Clear all information that is specific to this code generation
+ * and that is (probably) not meaningful to any nested code generation.
+ */
+__isl_give isl_ast_build *isl_ast_build_clear_local_info(
+       __isl_take isl_ast_build *build)
+{
+       isl_space *space;
+
+       build = isl_ast_build_cow(build);
+       if (!build)
+               return NULL;
+
+       space = isl_union_map_get_space(build->options);
+       isl_union_map_free(build->options);
+       build->options = isl_union_map_empty(space);
+
+       build->at_each_domain = NULL;
+       build->at_each_domain_user = NULL;
+       build->create_leaf = NULL;
+       build->create_leaf_user = NULL;
+
+       if (!build->options)
+               return isl_ast_build_free(build);
+
+       return build;
+}
+
+/* Have any loops been eliminated?
+ * That is, do any of the original schedule dimensions have a fixed
+ * value that has been substituted?
+ */
+static int any_eliminated(isl_ast_build *build)
+{
+       int i;
+
+       for (i = 0; i < build->depth; ++i)
+               if (isl_ast_build_has_affine_value(build, i))
+                       return 1;
+
+       return 0;
+}
+
+/* Clear build->schedule_map.
+ * This function should be called whenever anything that might affect
+ * the result of isl_ast_build_get_schedule_map_multi_aff changes.
+ * In particular, it should be called when the depth is changed or
+ * when an iterator is determined to have a fixed value.
+ */
+static void isl_ast_build_reset_schedule_map(__isl_keep isl_ast_build *build)
+{
+       if (!build)
+               return;
+       isl_multi_aff_free(build->schedule_map);
+       build->schedule_map = NULL;
+}
+
+/* Do we need a (non-trivial) schedule map?
+ * That is, is the internal schedule space different from
+ * the external schedule space?
+ *
+ * The internal and external schedule spaces are only the same
+ * if code has been generated for the entire schedule and if none
+ * of the loops have been eliminated.
+ */
+__isl_give int isl_ast_build_need_schedule_map(__isl_keep isl_ast_build *build)
+{
+       int dim;
+
+       if (!build)
+               return -1;
+
+       dim = isl_set_dim(build->domain, isl_dim_set);
+       return build->depth != dim || any_eliminated(build);
+}
+
+/* Return a mapping from the internal schedule space to the external
+ * schedule space in the form of an isl_multi_aff.
+ * The internal schedule space originally corresponds to that of the
+ * input schedule.  This may change during the code generation if
+ * if isl_ast_build_insert_dim is ever called.
+ * The external schedule space corresponds to the
+ * loops that have been generated.
+ *
+ * Currently, the only difference between the internal schedule domain
+ * and the external schedule domain is that some dimensions are projected
+ * out in the external schedule domain.  In particular, the dimensions
+ * for which no code has been generated yet and the dimensions that correspond
+ * to eliminated loops.
+ *
+ * We cache a copy of the schedule_map in build->schedule_map.
+ * The cache is cleared through isl_ast_build_reset_schedule_map
+ * whenever anything changes that might affect the result of this function.
+ */
+__isl_give isl_multi_aff *isl_ast_build_get_schedule_map_multi_aff(
+       __isl_keep isl_ast_build *build)
+{
+       isl_space *space;
+       isl_multi_aff *ma;
+
+       if (!build)
+               return NULL;
+       if (build->schedule_map)
+               return isl_multi_aff_copy(build->schedule_map);
+
+       space = isl_ast_build_get_space(build, 1);
+       space = isl_space_map_from_set(space);
+       ma = isl_multi_aff_identity(space);
+       if (isl_ast_build_need_schedule_map(build)) {
+               int i;
+               int dim = isl_set_dim(build->domain, isl_dim_set);
+               ma = isl_multi_aff_drop_dims(ma, isl_dim_out,
+                                       build->depth, dim - build->depth);
+               for (i = build->depth - 1; i >= 0; --i)
+                       if (isl_ast_build_has_affine_value(build, i))
+                               ma = isl_multi_aff_drop_dims(ma,
+                                                       isl_dim_out, i, 1);
+       }
+
+       build->schedule_map = ma;
+       return isl_multi_aff_copy(build->schedule_map);
+}
+
+/* Return a mapping from the internal schedule space to the external
+ * schedule space in the form of an isl_map.
+ */
+__isl_give isl_map *isl_ast_build_get_schedule_map(
+       __isl_keep isl_ast_build *build)
+{
+       isl_multi_aff *ma;
+
+       ma = isl_ast_build_get_schedule_map_multi_aff(build);
+       return isl_map_from_multi_aff(ma);
+}
+
+/* Return the position of the dimension in build->domain for which
+ * an AST node is currently being generated.
+ */
+int isl_ast_build_get_depth(__isl_keep isl_ast_build *build)
+{
+       return build ? build->depth : -1;
+}
+
+/* Prepare for generating code for the next level.
+ * In particular, increase the depth and reset any information
+ * that is local to the current depth.
+ */
+__isl_give isl_ast_build *isl_ast_build_increase_depth(
+       __isl_take isl_ast_build *build)
+{
+       build = isl_ast_build_cow(build);
+       if (!build)
+               return NULL;
+       build->depth++;
+       isl_ast_build_reset_schedule_map(build);
+       build->value = isl_pw_aff_free(build->value);
+       return build;
+}
+
+void isl_ast_build_dump(__isl_keep isl_ast_build *build)
+{
+       if (!build)
+               return;
+
+       fprintf(stderr, "domain: ");
+       isl_set_dump(build->domain);
+       fprintf(stderr, "generated: ");
+       isl_set_dump(build->generated);
+       fprintf(stderr, "pending: ");
+       isl_set_dump(build->pending);
+       fprintf(stderr, "iterators: ");
+       isl_id_list_dump(build->iterators);
+       fprintf(stderr, "values: ");
+       isl_multi_aff_dump(build->values);
+       if (build->value) {
+               fprintf(stderr, "value: ");
+               isl_pw_aff_dump(build->value);
+       }
+       fprintf(stderr, "strides: ");
+       isl_vec_dump(build->strides);
+       fprintf(stderr, "offsets: ");
+       isl_multi_aff_dump(build->offsets);
+}
+
+/* Initialize "build" for AST construction in schedule space "space"
+ * in the case that build->domain is a parameter set.
+ *
+ * build->iterators is assumed to have been updated already.
+ */
+static __isl_give isl_ast_build *isl_ast_build_init(
+       __isl_take isl_ast_build *build, __isl_take isl_space *space)
+{
+       isl_set *set;
+
+       build = isl_ast_build_cow(build);
+       if (!build)
+               goto error;
+
+       set = isl_set_universe(isl_space_copy(space));
+       build->domain = isl_set_intersect_params(isl_set_copy(set),
+                                                   build->domain);
+       build->pending = isl_set_intersect_params(isl_set_copy(set),
+                                                   build->pending);
+       build->generated = isl_set_intersect_params(set, build->generated);
+
+       return isl_ast_build_init_derived(build, space);
+error:
+       isl_ast_build_free(build);
+       isl_space_free(space);
+       return NULL;
+}
+
+/* Assign "aff" to *user and return -1, effectively extracting
+ * the first (and presumably only) affine expression in the isl_pw_aff
+ * on which this function is used.
+ */
+static int extract_single_piece(__isl_take isl_set *set,
+       __isl_take isl_aff *aff, void *user)
+{
+       isl_aff **p = user;
+
+       *p = aff;
+       isl_set_free(set);
+
+       return -1;
+}
+
+/* Check if the given bounds on the current dimension imply that
+ * this current dimension attains only a single value (in terms of
+ * parameters and outer dimensions).
+ * If so, we record it in build->value.
+ * If, moreover, this value can be represented as a single affine expression,
+ * then we also update build->values, effectively marking the current
+ * dimension as "eliminated".
+ *
+ * When computing the gist of the fixed value that can be represented
+ * as a single affine expression, it is important to only take into
+ * account the domain constraints in the original AST build and
+ * not the domain of the affine expression itself.
+ * Otherwise, a [i/3] is changed into a i/3 because we know that i
+ * is a multiple of 3, but then we end up not expressing anywhere
+ * in the context that i is a multiple of 3.
+ */
+static __isl_give isl_ast_build *update_values(
+       __isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds)
+{
+       int sv;
+       isl_pw_multi_aff *pma;
+       isl_aff *aff = NULL;
+       isl_map *it_map;
+       isl_set *set;
+
+       set = isl_set_from_basic_set(bounds);
+       set = isl_set_intersect(set, isl_set_copy(build->domain));
+       it_map = isl_ast_build_map_to_iterator(build, set);
+
+       sv = isl_map_is_single_valued(it_map);
+       if (sv < 0)
+               build = isl_ast_build_free(build);
+       if (!build || !sv) {
+               isl_map_free(it_map);
+               return build;
+       }
+
+       pma = isl_pw_multi_aff_from_map(it_map);
+       build->value = isl_pw_multi_aff_get_pw_aff(pma, 0);
+       build->value = isl_ast_build_compute_gist_pw_aff(build, build->value);
+       build->value = isl_pw_aff_coalesce(build->value);
+       isl_pw_multi_aff_free(pma);
+
+       if (!build->value)
+               return isl_ast_build_free(build);
+
+       if (isl_pw_aff_n_piece(build->value) != 1)
+               return build;
+
+       isl_pw_aff_foreach_piece(build->value, &extract_single_piece, &aff);
+
+       build->values = isl_multi_aff_set_aff(build->values, build->depth, aff);
+       if (!build->values)
+               return isl_ast_build_free(build);
+       isl_ast_build_reset_schedule_map(build);
+       return build;
+}
+
+/* Update the AST build based on the given loop bounds for
+ * the current dimension.
+ *
+ * We first make sure that the bounds do not refer to any iterators
+ * that have already been eliminated.
+ * Then, we check if the bounds imply that the current iterator
+ * has a fixed value.
+ * If they do and if this fixed value can be expressed as a single
+ * affine expression, we eliminate the iterators from the bounds.
+ * Note that we cannot simply plug in this single value using
+ * isl_basic_set_preimage_multi_aff as the single value may only
+ * be defined on a subset of the domain.  Plugging in the value
+ * would restrict the build domain to this subset, while this
+ * restriction may not be reflected in the generated code.
+ * build->domain may, however, already refer to the current dimension
+ * due an earlier call to isl_ast_build_include_stride.  If so, we need
+ * to eliminate the dimension so that we do not introduce it in any other sets.
+ * Finally, we intersect build->domain with the updated bounds.
+ *
+ * Note that the check for a fixed value in update_values requires
+ * us to intersect the bounds with the current build domain.
+ * When we intersect build->domain with the updated bounds in
+ * the final step, we make sure that these updated bounds have
+ * not been intersected with the old build->domain.
+ * Otherwise, we would indirectly intersect the build domain with itself,
+ * which can lead to inefficiencies, in particular if the build domain
+ * contains any unknown divs.
+ */
+__isl_give isl_ast_build *isl_ast_build_set_loop_bounds(
+       __isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds)
+{
+       isl_set *set;
+
+       build = isl_ast_build_cow(build);
+       if (!build)
+               goto error;
+
+       bounds = isl_basic_set_preimage_multi_aff(bounds,
+                                       isl_multi_aff_copy(build->values));
+       build = update_values(build, isl_basic_set_copy(bounds));
+       if (!build)
+               goto error;
+       set = isl_set_from_basic_set(isl_basic_set_copy(bounds));
+       if (isl_ast_build_has_affine_value(build, build->depth)) {
+               set = isl_set_eliminate(set, isl_dim_set, build->depth, 1);
+               set = isl_set_compute_divs(set);
+               build->pending = isl_set_intersect(build->pending,
+                                                       isl_set_copy(set));
+               if (isl_ast_build_has_stride(build, build->depth))
+                       build->domain = isl_set_eliminate(build->domain,
+                                               isl_dim_set, build->depth, 1);
+       } else {
+               isl_basic_set *generated, *pending;
+
+               pending = isl_basic_set_copy(bounds);
+               pending = isl_basic_set_drop_constraints_involving_dims(pending,
+                                       isl_dim_set, build->depth, 1);
+               build->pending = isl_set_intersect(build->pending,
+                                       isl_set_from_basic_set(pending));
+               generated = isl_basic_set_copy(bounds);
+               generated = isl_basic_set_drop_constraints_not_involving_dims(
+                                   generated, isl_dim_set, build->depth, 1);
+               build->generated = isl_set_intersect(build->generated,
+                                       isl_set_from_basic_set(generated));
+       }
+       isl_basic_set_free(bounds);
+
+       build->domain = isl_set_intersect(build->domain, set);
+       if (!build->domain || !build->pending || !build->generated)
+               return isl_ast_build_free(build);
+
+       return build;
+error:
+       isl_ast_build_free(build);
+       isl_basic_set_free(bounds);
+       return NULL;
+}
+
+/* Update build->domain based on the constraints enforced by inner loops.
+ *
+ * The constraints in build->pending may end up not getting generated
+ * if they are implied by "enforced".  We therefore reconstruct
+ * build->domain from build->generated and build->pending, dropping
+ * those constraint in build->pending that may not get generated.
+ */
+__isl_give isl_ast_build *isl_ast_build_set_enforced(
+       __isl_take isl_ast_build *build, __isl_take isl_basic_set *enforced)
+{
+       isl_set *set;
+
+       build = isl_ast_build_cow(build);
+       if (!build)
+               goto error;
+
+       set = isl_set_from_basic_set(enforced);
+       set = isl_set_gist(isl_set_copy(build->pending), set);
+       set = isl_set_intersect(isl_set_copy(build->generated), set);
+
+       isl_set_free(build->domain);
+       build->domain = set;
+
+       if (!build->domain)
+               return isl_ast_build_free(build);
+
+       return build;
+error:
+       isl_basic_set_free(enforced);
+       return isl_ast_build_free(build);
+}
+
+/* Intersect build->domain with "set", where "set" is specified
+ * in terms of the internal schedule domain.
+ */
+static __isl_give isl_ast_build *isl_ast_build_restrict_internal(
+       __isl_take isl_ast_build *build, __isl_take isl_set *set)
+{
+       build = isl_ast_build_cow(build);
+       if (!build)
+               goto error;
+
+       set = isl_set_compute_divs(set);
+       build->domain = isl_set_intersect(build->domain, set);
+       build->domain = isl_set_coalesce(build->domain);
+
+       if (!build->domain)
+               return isl_ast_build_free(build);
+
+       return build;
+error:
+       isl_ast_build_free(build);
+       isl_set_free(set);
+       return NULL;
+}
+
+/* Intersect build->generated and build->domain with "set",
+ * where "set" is specified in terms of the internal schedule domain.
+ */
+__isl_give isl_ast_build *isl_ast_build_restrict_generated(
+       __isl_take isl_ast_build *build, __isl_take isl_set *set)
+{
+       set = isl_set_compute_divs(set);
+       build = isl_ast_build_restrict_internal(build, isl_set_copy(set));
+       build = isl_ast_build_cow(build);
+       if (!build)
+               goto error;
+
+       build->generated = isl_set_intersect(build->generated, set);
+       build->generated = isl_set_coalesce(build->generated);
+
+       if (!build->generated)
+               return isl_ast_build_free(build);
+
+       return build;
+error:
+       isl_ast_build_free(build);
+       isl_set_free(set);
+       return NULL;
+}
+
+/* Intersect build->pending and build->domain with "set",
+ * where "set" is specified in terms of the internal schedule domain.
+ */
+__isl_give isl_ast_build *isl_ast_build_restrict_pending(
+       __isl_take isl_ast_build *build, __isl_take isl_set *set)
+{
+       set = isl_set_compute_divs(set);
+       build = isl_ast_build_restrict_internal(build, isl_set_copy(set));
+       build = isl_ast_build_cow(build);
+       if (!build)
+               goto error;
+
+       build->pending = isl_set_intersect(build->pending, set);
+       build->pending = isl_set_coalesce(build->pending);
+
+       if (!build->pending)
+               return isl_ast_build_free(build);
+
+       return build;
+error:
+       isl_ast_build_free(build);
+       isl_set_free(set);
+       return NULL;
+}
+
+/* Intersect build->domain with "set", where "set" is specified
+ * in terms of the external schedule domain.
+ */
+__isl_give isl_ast_build *isl_ast_build_restrict(
+       __isl_take isl_ast_build *build, __isl_take isl_set *set)
+{
+       if (isl_set_is_params(set))
+               return isl_ast_build_restrict_generated(build, set);
+
+       if (isl_ast_build_need_schedule_map(build)) {
+               isl_multi_aff *ma;
+               ma = isl_ast_build_get_schedule_map_multi_aff(build);
+               set = isl_set_preimage_multi_aff(set, ma);
+       }
+       return isl_ast_build_restrict_generated(build, set);
+}
+
+/* Replace build->executed by "executed".
+ */
+__isl_give isl_ast_build *isl_ast_build_set_executed(
+       __isl_take isl_ast_build *build, __isl_take isl_union_map *executed)
+{
+       build = isl_ast_build_cow(build);
+       if (!build)
+               goto error;
+
+       isl_union_map_free(build->executed);
+       build->executed = executed;
+
+       return build;
+error:
+       isl_ast_build_free(build);
+       isl_union_map_free(executed);
+       return NULL;
+}
+
+/* Return a copy of the current schedule domain.
+ */
+__isl_give isl_set *isl_ast_build_get_domain(__isl_keep isl_ast_build *build)
+{
+       return build ? isl_set_copy(build->domain) : NULL;
+}
+
+/* Return the (schedule) space of "build".
+ *
+ * If "internal" is set, then this space is the space of the internal
+ * representation of the entire schedule, including those parts for
+ * which no code has been generated yet.
+ *
+ * If "internal" is not set, then this space is the external representation
+ * of the loops generated so far.
+ */
+__isl_give isl_space *isl_ast_build_get_space(__isl_keep isl_ast_build *build,
+       int internal)
+{
+       int i;
+       int dim;
+       isl_space *space;
+
+       if (!build)
+               return NULL;
+
+       space = isl_set_get_space(build->domain);
+       if (internal)
+               return space;
+
+       if (!isl_ast_build_need_schedule_map(build))
+               return space;
+
+       dim = isl_set_dim(build->domain, isl_dim_set);
+       space = isl_space_drop_dims(space, isl_dim_set,
+                                   build->depth, dim - build->depth);
+       for (i = build->depth - 1; i >= 0; --i)
+               if (isl_ast_build_has_affine_value(build, i))
+                       space = isl_space_drop_dims(space, isl_dim_set, i, 1);
+
+       return space;
+}
+
+/* Return the external representation of the schedule space of "build",
+ * i.e., a space with a dimension for each loop generated so far,
+ * with the names of the dimensions set to the loop iterators.
+ */
+__isl_give isl_space *isl_ast_build_get_schedule_space(
+       __isl_keep isl_ast_build *build)
+{
+       isl_space *space;
+       int i, skip;
+
+       if (!build)
+               return NULL;
+
+       space = isl_ast_build_get_space(build, 0);
+
+       skip = 0;
+       for (i = 0; i < build->depth; ++i) {
+               isl_id *id;
+
+               if (isl_ast_build_has_affine_value(build, i)) {
+                       skip++;
+                       continue;
+               }
+
+               id = isl_ast_build_get_iterator_id(build, i);
+               space = isl_space_set_dim_id(space, isl_dim_set, i - skip, id);
+       }
+
+       return space;
+}
+
+/* Return the current schedule, as stored in build->executed, in terms
+ * of the external schedule domain.
+ */
+__isl_give isl_union_map *isl_ast_build_get_schedule(
+       __isl_keep isl_ast_build *build)
+{
+       isl_union_map *executed;
+       isl_union_map *schedule;
+
+       if (!build)
+               return NULL;
+
+       executed = isl_union_map_copy(build->executed);
+       if (isl_ast_build_need_schedule_map(build)) {
+               isl_map *proj = isl_ast_build_get_schedule_map(build);
+               executed = isl_union_map_apply_domain(executed,
+                                       isl_union_map_from_map(proj));
+       }
+       schedule = isl_union_map_reverse(executed);
+
+       return schedule;
+}
+
+/* Return the iterator attached to the internal schedule dimension "pos".
+ */
+__isl_give isl_id *isl_ast_build_get_iterator_id(
+       __isl_keep isl_ast_build *build, int pos)
+{
+       if (!build)
+               return NULL;
+
+       return isl_id_list_get_id(build->iterators, pos);
+}
+
+/* Set the stride and offset of the current dimension to the given
+ * value and expression.
+ */
+static __isl_give isl_ast_build *set_stride(__isl_take isl_ast_build *build,
+       isl_int stride, __isl_take isl_aff *offset)
+{
+       int pos;
+
+       build = isl_ast_build_cow(build);
+       if (!build || !offset)
+               goto error;
+
+       pos = build->depth;
+       build->strides = isl_vec_set_element(build->strides, pos, stride);
+       build->offsets = isl_multi_aff_set_aff(build->offsets, pos, offset);
+       if (!build->strides || !build->offsets)
+               return isl_ast_build_free(build);
+
+       return build;
+error:
+       isl_aff_free(offset);
+       return isl_ast_build_free(build);
+}
+
+/* Return a set expressing the stride constraint at the current depth.
+ *
+ * In particular, if the current iterator (i) is known to attain values
+ *
+ *     f + s a
+ *
+ * where f is the offset and s is the stride, then the returned set
+ * expresses the constraint
+ *
+ *     (f - i) mod s = 0
+ */
+__isl_give isl_set *isl_ast_build_get_stride_constraint(
+       __isl_keep isl_ast_build *build)
+{
+       isl_aff *aff;
+       isl_set *set;
+       isl_int stride;
+       int pos;
+
+       if (!build)
+               return NULL;
+
+       pos = build->depth;
+
+       if (!isl_ast_build_has_stride(build, pos))
+               return isl_set_universe(isl_ast_build_get_space(build, 1));
+
+       isl_int_init(stride);
+
+       isl_ast_build_get_stride(build, pos, &stride);
+       aff = isl_ast_build_get_offset(build, pos);
+       aff = isl_aff_add_coefficient_si(aff, isl_dim_in, pos, -1);
+       aff = isl_aff_mod(aff, stride);
+       set = isl_set_from_basic_set(isl_aff_zero_basic_set(aff));
+
+       isl_int_clear(stride);
+
+       return set;
+}
+
+/* Return the expansion implied by the stride and offset at the current
+ * depth.
+ *
+ * That is, return the mapping
+ *
+ *     [i_0, ..., i_{d-1}, i_d, i_{d+1}, ...]
+ *             -> [i_0, ..., i_{d-1}, s * i_d + offset(i),  i_{d+1}, ...]
+ *
+ * where s is the stride at the current depth d and offset(i) is
+ * the corresponding offset.
+ */
+__isl_give isl_multi_aff *isl_ast_build_get_stride_expansion(
+       __isl_keep isl_ast_build *build)
+{
+       isl_space *space;
+       isl_multi_aff *ma;
+       int pos;
+       isl_aff *aff, *offset;
+       isl_int stride;
+
+       if (!build)
+               return NULL;
+
+       pos = isl_ast_build_get_depth(build);
+       space = isl_ast_build_get_space(build, 1);
+       space = isl_space_map_from_set(space);
+       ma = isl_multi_aff_identity(space);
+
+       if (!isl_ast_build_has_stride(build, pos))
+               return ma;
+
+       isl_int_init(stride);
+       offset = isl_ast_build_get_offset(build, pos);
+       isl_ast_build_get_stride(build, pos, &stride);
+       aff = isl_multi_aff_get_aff(ma, pos);
+       aff = isl_aff_scale(aff, stride);
+       aff = isl_aff_add(aff, offset);
+       ma = isl_multi_aff_set_aff(ma, pos, aff);
+       isl_int_clear(stride);
+
+       return ma;
+}
+
+/* Add constraints corresponding to any previously detected
+ * stride on the current dimension to build->domain.
+ */
+__isl_give isl_ast_build *isl_ast_build_include_stride(
+       __isl_take isl_ast_build *build)
+{
+       isl_set *set;
+
+       if (!build)
+               return NULL;
+       if (!isl_ast_build_has_stride(build, build->depth))
+               return build;
+       build = isl_ast_build_cow(build);
+       if (!build)
+               return NULL;
+
+       set = isl_ast_build_get_stride_constraint(build);
+
+       build->domain = isl_set_intersect(build->domain, isl_set_copy(set));
+       build->generated = isl_set_intersect(build->generated, set);
+       if (!build->domain || !build->generated)
+               return isl_ast_build_free(build);
+
+       return build;
+}
+
+/* Compute x, y and g such that g = gcd(a,b) and a*x+b*y = g */
+static void euclid(isl_int a, isl_int b, isl_int *x, isl_int *y, isl_int *g)
+{
+       isl_int c, d, e, f, tmp;
+
+       isl_int_init(c);
+       isl_int_init(d);
+       isl_int_init(e);
+       isl_int_init(f);
+       isl_int_init(tmp);
+       isl_int_abs(c, a);
+       isl_int_abs(d, b);
+       isl_int_set_si(e, 1);
+       isl_int_set_si(f, 0);
+       while (isl_int_is_pos(d)) {
+               isl_int_tdiv_q(tmp, c, d);
+               isl_int_mul(tmp, tmp, f);
+               isl_int_sub(e, e, tmp);
+               isl_int_tdiv_q(tmp, c, d);
+               isl_int_mul(tmp, tmp, d);
+               isl_int_sub(c, c, tmp);
+               isl_int_swap(c, d);
+               isl_int_swap(e, f);
+       }
+       isl_int_set(*g, c);
+       if (isl_int_is_zero(a))
+               isl_int_set_si(*x, 0);
+       else if (isl_int_is_pos(a))
+               isl_int_set(*x, e);
+       else
+               isl_int_neg(*x, e);
+       if (isl_int_is_zero(b))
+               isl_int_set_si(*y, 0);
+       else {
+               isl_int_mul(tmp, a, *x);
+               isl_int_sub(tmp, c, tmp);
+               isl_int_divexact(*y, tmp, b);
+       }
+       isl_int_clear(c);
+       isl_int_clear(d);
+       isl_int_clear(e);
+       isl_int_clear(f);
+       isl_int_clear(tmp);
+}
+
+/* Information used inside detect_stride.
+ *
+ * "build" may be updated by detect_stride to include stride information.
+ * "pos" is equal to build->depth.
+ */
+struct isl_detect_stride_data {
+       isl_ast_build *build;
+       int pos;
+};
+
+/* Check if constraint "c" imposes any stride on dimension data->pos
+ * and, if so, update the stride information in data->build.
+ *
+ * In order to impose a stride on the dimension, "c" needs to be an equality
+ * and it needs to involve the dimension.  Note that "c" may also be
+ * a div constraint and thus an inequality that we cannot use.
+ *
+ * Let c be of the form
+ *
+ *     h(p) + g * v * i + g * stride * f(alpha) = 0
+ *
+ * with h(p) an expression in terms of the parameters and outer dimensions
+ * and f(alpha) an expression in terms of the existentially quantified
+ * variables.  Note that the inner dimensions have been eliminated so
+ * they do not appear in "c".
+ *
+ * If "stride" is not zero and not one, then it represents a non-trivial stride
+ * on "i".  We compute a and b such that
+ *
+ *     a v + b stride = 1
+ *
+ * We have
+ *
+ *     g v i = -h(p) + g stride f(alpha)
+ *
+ *     a g v i = -a h(p) + g stride f(alpha)
+ *
+ *     a g v i + b g stride i = -a h(p) + g stride * (...)
+ *
+ *     g i = -a h(p) + g stride * (...)
+ *
+ *     i = -a h(p)/g + stride * (...)
+ *
+ * The expression "-a h(p)/g" can therefore be used as offset.
+ */
+static int detect_stride(__isl_take isl_constraint *c, void *user)
+{
+       struct isl_detect_stride_data *data = user;
+       int i, n_div;
+       isl_int v, gcd, stride, a, b, m;
+
+       if (!isl_constraint_is_equality(c) ||
+           !isl_constraint_involves_dims(c, isl_dim_set, data->pos, 1)) {
+               isl_constraint_free(c);
+               return 0;
+       }
+
+       isl_int_init(a);
+       isl_int_init(b);
+       isl_int_init(v);
+       isl_int_init(m);
+       isl_int_init(gcd);
+       isl_int_init(stride);
+
+       isl_int_set_si(gcd, 0);
+       n_div = isl_constraint_dim(c, isl_dim_div);
+       for (i = 0; i < n_div; ++i) {
+               isl_constraint_get_coefficient(c, isl_dim_div, i, &v);
+               isl_int_gcd(gcd, gcd, v);
+       }
+
+       isl_constraint_get_coefficient(c, isl_dim_set, data->pos, &v);
+       isl_int_gcd(m, v, gcd);
+       isl_int_divexact(stride, gcd, m);
+       isl_int_divexact(v, v, m);
+
+       if (!isl_int_is_zero(stride) && !isl_int_is_one(stride)) {
+               isl_aff *aff;
+
+               euclid(v, stride, &a, &b, &gcd);
+
+               aff = isl_constraint_get_aff(c);
+               for (i = 0; i < n_div; ++i)
+                       aff = isl_aff_set_coefficient_si(aff,
+                                                        isl_dim_div, i, 0);
+               aff = isl_aff_set_coefficient_si(aff, isl_dim_in, data->pos, 0);
+               isl_int_neg(a, a);
+               aff = isl_aff_scale(aff, a);
+               aff = isl_aff_scale_down(aff, m);
+               data->build = set_stride(data->build, stride, aff);
+       }
+
+       isl_int_clear(stride);
+       isl_int_clear(gcd);
+       isl_int_clear(m);
+       isl_int_clear(v);
+       isl_int_clear(b);
+       isl_int_clear(a);
+
+       isl_constraint_free(c);
+       return 0;
+}
+
+/* Check if the constraints in "set" imply any stride on the current
+ * dimension and, if so, record the stride information in "build"
+ * and return the updated "build".
+ *
+ * We compute the affine hull and then check if any of the constraints
+ * in the hull imposes any stride on the current dimension.
+ *
+ * We assume that inner dimensions have been eliminated from "set"
+ * by the caller.  This is needed because the common stride
+ * may be imposed by different inner dimensions on different parts of
+ * the domain.
+ */
+__isl_give isl_ast_build *isl_ast_build_detect_strides(
+       __isl_take isl_ast_build *build, __isl_take isl_set *set)
+{
+       isl_basic_set *hull;
+       struct isl_detect_stride_data data;
+
+       if (!build)
+               goto error;
+
+       data.build = build;
+       data.pos = isl_ast_build_get_depth(build);
+       hull = isl_set_affine_hull(set);
+
+       if (isl_basic_set_foreach_constraint(hull, &detect_stride, &data) < 0)
+               data.build = isl_ast_build_free(data.build);
+
+       isl_basic_set_free(hull);
+       return data.build;
+error:
+       isl_set_free(set);
+       return NULL;
+}
+
+struct isl_ast_build_involves_data {
+       int depth;
+       int involves;
+};
+
+/* Check if "map" involves the input dimension data->depth.
+ */
+static int involves_depth(__isl_take isl_map *map, void *user)
+{
+       struct isl_ast_build_involves_data *data = user;
+
+       data->involves = isl_map_involves_dims(map, isl_dim_in, data->depth, 1);
+       isl_map_free(map);
+
+       if (data->involves < 0 || data->involves)
+               return -1;
+       return 0;
+}
+
+/* Do any options depend on the value of the dimension at the current depth?
+ */
+int isl_ast_build_options_involve_depth(__isl_keep isl_ast_build *build)
+{
+       struct isl_ast_build_involves_data data;
+
+       if (!build)
+               return -1;
+
+       data.depth = build->depth;
+       data.involves = 0;
+
+       if (isl_union_map_foreach_map(build->options,
+                                       &involves_depth, &data) < 0) {
+               if (data.involves < 0 || !data.involves)
+                       return -1;
+       }
+
+       return data.involves;
+}
+
+/* Construct the map
+ *
+ *     { [i] -> [i] : i < pos; [i] -> [i + 1] : i >= pos }
+ *
+ * with "space" the parameter space of the constructed map.
+ */
+static __isl_give isl_map *construct_insertion_map(__isl_take isl_space *space,
+       int pos)
+{
+       isl_constraint *c;
+       isl_basic_map *bmap1, *bmap2;
+
+       space = isl_space_set_from_params(space);
+       space = isl_space_add_dims(space, isl_dim_set, 1);
+       space = isl_space_map_from_set(space);
+       c = isl_equality_alloc(isl_local_space_from_space(space));
+       c = isl_constraint_set_coefficient_si(c, isl_dim_in, 0, 1);
+       c = isl_constraint_set_coefficient_si(c, isl_dim_out, 0, -1);
+       bmap1 = isl_basic_map_from_constraint(isl_constraint_copy(c));
+       c = isl_constraint_set_constant_si(c, 1);
+       bmap2 = isl_basic_map_from_constraint(c);
+
+       bmap1 = isl_basic_map_upper_bound_si(bmap1, isl_dim_in, 0, pos - 1);
+       bmap2 = isl_basic_map_lower_bound_si(bmap2, isl_dim_in, 0, pos);
+
+       return isl_basic_map_union(bmap1, bmap2);
+}
+
+static const char *option_str[] = {
+       [atomic] = "atomic",
+       [unroll] = "unroll",
+       [separate] = "separate"
+};
+
+/* Update the "options" to reflect the insertion of a dimension
+ * at position "pos" in the schedule domain space.
+ * "space" is the original domain space before the insertion and
+ * may be named and/or structured.
+ *
+ * The (relevant) input options all have "space" as domain, which
+ * has to be mapped to the extended space.
+ * The values of the ranges also refer to the schedule domain positions
+ * and they therefore also need to be adjusted.  In particular, values
+ * smaller than pos do not need to change, while values greater than or
+ * equal to pos need to be incremented.
+ * That is, we need to apply the following map.
+ *
+ *     { atomic[i] -> atomic[i] : i < pos; [i] -> [i + 1] : i >= pos;
+ *       unroll[i] -> unroll[i] : i < pos; [i] -> [i + 1] : i >= pos;
+ *       separate[i] -> separate[i] : i < pos; [i] -> [i + 1] : i >= pos;
+ *       separation_class[[i] -> [c]]
+ *             -> separation_class[[i] -> [c]] : i < pos;
+ *       separation_class[[i] -> [c]]
+ *             -> separation_class[[i + 1] -> [c]] : i >= pos }
+ */
+static __isl_give isl_union_map *options_insert_dim(
+       __isl_take isl_union_map *options, __isl_take isl_space *space, int pos)
+{
+       isl_map *map;
+       isl_union_map *insertion;
+       enum isl_ast_build_domain_type type;
+       const char *name = "separation_class";
+
+       space = isl_space_map_from_set(space);
+       map = isl_map_identity(space);
+       map = isl_map_insert_dims(map, isl_dim_out, pos, 1);
+       options = isl_union_map_apply_domain(options,
+                                               isl_union_map_from_map(map));
+
+       if (!options)
+               return NULL;
+
+       map = construct_insertion_map(isl_union_map_get_space(options), pos);
+
+       insertion = isl_union_map_empty(isl_union_map_get_space(options));
+
+       for (type = atomic; type <= separate; ++type) {
+               isl_map *map_type = isl_map_copy(map);
+               const char *name = option_str[type];
+               map_type = isl_map_set_tuple_name(map_type, isl_dim_in, name);
+               map_type = isl_map_set_tuple_name(map_type, isl_dim_out, name);
+               insertion = isl_union_map_add_map(insertion, map_type);
+       }
+
+       map = isl_map_product(map, isl_map_identity(isl_map_get_space(map)));
+       map = isl_map_set_tuple_name(map, isl_dim_in, name);
+       map = isl_map_set_tuple_name(map, isl_dim_out, name);
+       insertion = isl_union_map_add_map(insertion, map);
+
+       options = isl_union_map_apply_range(options, insertion);
+
+       return options;
+}
+
+/* Insert a single dimension in the schedule domain at position "pos".
+ * The new dimension is given an isl_id with the empty string as name.
+ *
+ * The main difficulty is updating build->options to reflect the
+ * extra dimension.  This is handled in options_insert_dim.
+ *
+ * Note that because of the dimension manipulations, the resulting
+ * schedule domain space will always be unnamed and unstructured.
+ * However, the original schedule domain space may be named and/or
+ * structured, so we have to take this possibility into account
+ * while performing the transformations.
+ */
+__isl_give isl_ast_build *isl_ast_build_insert_dim(
+       __isl_take isl_ast_build *build, int pos)
+{
+       isl_ctx *ctx;
+       isl_space *space, *ma_space;
+       isl_id *id;
+       isl_multi_aff *ma;
+
+       build = isl_ast_build_cow(build);
+       if (!build)
+               return NULL;
+
+       ctx = isl_ast_build_get_ctx(build);
+       id = isl_id_alloc(ctx, "", NULL);
+       space = isl_ast_build_get_space(build, 1);
+       build->iterators = isl_id_list_insert(build->iterators, pos, id);
+       build->domain = isl_set_insert_dims(build->domain,
+                                               isl_dim_set, pos, 1);
+       build->generated = isl_set_insert_dims(build->generated,
+                                               isl_dim_set, pos, 1);
+       build->pending = isl_set_insert_dims(build->pending,
+                                               isl_dim_set, pos, 1);
+       build->strides = isl_vec_insert_els(build->strides, pos, 1);
+       build->strides = isl_vec_set_element_si(build->strides, pos, 1);
+       ma_space = isl_space_params(isl_multi_aff_get_space(build->offsets));
+       ma_space = isl_space_set_from_params(ma_space);
+       ma_space = isl_space_add_dims(ma_space, isl_dim_set, 1);
+       ma_space = isl_space_map_from_set(ma_space);
+       ma = isl_multi_aff_zero(isl_space_copy(ma_space));
+       build->offsets = isl_multi_aff_splice(build->offsets, pos, pos, ma);
+       ma = isl_multi_aff_identity(ma_space);
+       build->values = isl_multi_aff_splice(build->values, pos, pos, ma);
+       build->options = options_insert_dim(build->options, space, pos);
+
+       if (!build->iterators || !build->domain || !build->generated ||
+           !build->pending || !build->values ||
+           !build->strides || !build->offsets || !build->options)
+               return isl_ast_build_free(build);
+
+       return build;
+}
+
+/* Scale down the current dimension by a factor of "m".
+ * "umap" is an isl_union_map that implements the scaling down.
+ * That is, it is of the form
+ *
+ *     { [.... i ....] -> [.... i' ....] : i = m i' }
+ *
+ * This function is called right after the strides have been
+ * detected, but before any constraints on the current dimension
+ * have been included in build->domain.
+ * We therefore only need to update stride, offset and the options.
+ */
+__isl_give isl_ast_build *isl_ast_build_scale_down(
+       __isl_take isl_ast_build *build, isl_int m,
+       __isl_take isl_union_map *umap)
+{
+       isl_aff *aff;
+       isl_int v;
+       int depth;
+
+       build = isl_ast_build_cow(build);
+       if (!build || !umap)
+               goto error;
+
+       depth = build->depth;
+
+       isl_int_init(v);
+       if (isl_vec_get_element(build->strides, depth, &v) < 0)
+               build->strides = isl_vec_free(build->strides);
+       isl_int_divexact(v, v, m);
+       build->strides = isl_vec_set_element(build->strides, depth, v);
+       isl_int_clear(v);
+
+       aff = isl_multi_aff_get_aff(build->offsets, depth);
+       aff = isl_aff_scale_down(aff, m);
+       build->offsets = isl_multi_aff_set_aff(build->offsets, depth, aff);
+       build->options = isl_union_map_apply_domain(build->options, umap);
+       if (!build->strides || !build->offsets || !build->options)
+               return isl_ast_build_free(build);
+
+       return build;
+error:
+       isl_union_map_free(umap);
+       return isl_ast_build_free(build);
+}
+
+/* Return a list of "n" isl_ids called "c%d", with "%d" starting at "first".
+ * If an isl_id with such a name already appears among the parameters
+ * in build->domain, then adjust the name to "c%d_%d".
+ */
+static __isl_give isl_id_list *generate_names(isl_ctx *ctx, int n, int first,
+       __isl_keep isl_ast_build *build)
+{
+       int i, j;
+       char name[16];
+       isl_id_list *names;
+       isl_set *dom = build->domain;
+
+       names = isl_id_list_alloc(ctx, n);
+       for (i = 0; i < n; ++i) {
+               isl_id *id;
+
+               snprintf(name, sizeof(name), "c%d", first + i);
+               j = 0;
+               while (isl_set_find_dim_by_name(dom, isl_dim_param, name) >= 0)
+                       snprintf(name, sizeof(name), "c%d_%d", first + i, j++);
+               id = isl_id_alloc(ctx, name, NULL);
+               names = isl_id_list_add(names, id);
+       }
+
+       return names;
+}
+
+/* Embed "options" into the given isl_ast_build space.
+ *
+ * This function is called from within a nested call to
+ * isl_ast_build_ast_from_schedule.
+ * "options" refers to the additional schedule,
+ * while space refers to both the space of the outer isl_ast_build and
+ * that of the additional schedule.
+ * Specifically, space is of the form
+ *
+ *     [I -> S]
+ *
+ * while options lives in the space(s)
+ *
+ *     S -> *
+ *
+ * We compute
+ *
+ *     [I -> S] -> S
+ *
+ * and compose this with options, to obtain the new options
+ * living in the space(s)
+ *
+ *     [I -> S] -> *
+ */
+static __isl_give isl_union_map *embed_options(
+       __isl_take isl_union_map *options, __isl_take isl_space *space)
+{
+       isl_map *map;
+
+       map = isl_map_universe(isl_space_unwrap(space));
+       map = isl_map_range_map(map);
+
+       options = isl_union_map_apply_range(
+                               isl_union_map_from_map(map), options);
+
+       return options;
+}
+
+/* Update "build" for use in a (possibly nested) code generation.  That is,
+ * extend "build" from an AST build on some domain O to an AST build
+ * on domain [O -> S], with S corresponding to "space".
+ * If the original domain is a parameter domain, then the new domain is
+ * simply S.
+ * "iterators" is a list of iterators for S, but the number of elements
+ * may be smaller or greater than the number of set dimensions of S.
+ * If "keep_iterators" is set, then any extra ids in build->iterators
+ * are reused for S.  Otherwise, these extra ids are dropped.
+ *
+ * We first update build->outer_pos to the current depth.
+ * This depth is zero in case this is the outermost code generation.
+ *
+ * We then add additional ids such that the number of iterators is at least
+ * equal to the dimension of the new build domain.
+ *
+ * If the original domain is parametric, then we are constructing
+ * an isl_ast_build for the outer code generation and we pass control
+ * to isl_ast_build_init.
+ *
+ * Otherwise, we adjust the fields of "build" to include "space".
+ */
+__isl_give isl_ast_build *isl_ast_build_product(
+       __isl_take isl_ast_build *build, __isl_take isl_space *space)
+{
+       isl_ctx *ctx;
+       isl_vec *strides;
+       isl_set *set;
+       isl_multi_aff *embedding;
+       int dim, n_it;
+
+       build = isl_ast_build_cow(build);
+       if (!build)
+               goto error;
+
+       build->outer_pos = build->depth;
+
+       ctx = isl_ast_build_get_ctx(build);
+       dim = isl_set_dim(build->domain, isl_dim_set);
+       dim += isl_space_dim(space, isl_dim_set);
+       n_it = isl_id_list_n_id(build->iterators);
+       if (n_it < dim) {
+               isl_id_list *l;
+               l = generate_names(ctx, dim - n_it, n_it, build);
+               build->iterators = isl_id_list_concat(build->iterators, l);
+       }
+
+       if (isl_set_is_params(build->domain))
+               return isl_ast_build_init(build, space);
+
+       set = isl_set_universe(isl_space_copy(space));
+       build->domain = isl_set_product(build->domain, isl_set_copy(set));
+       build->pending = isl_set_product(build->pending, isl_set_copy(set));
+       build->generated = isl_set_product(build->generated, set);
+
+       strides = isl_vec_alloc(ctx, isl_space_dim(space, isl_dim_set));
+       strides = isl_vec_set_si(strides, 1);
+       build->strides = isl_vec_concat(build->strides, strides);
+
+       space = isl_space_map_from_set(space);
+       build->offsets = isl_multi_aff_align_params(build->offsets,
+                                                   isl_space_copy(space));
+       build->offsets = isl_multi_aff_product(build->offsets,
+                               isl_multi_aff_zero(isl_space_copy(space)));
+       build->values = isl_multi_aff_align_params(build->values,
+                                                   isl_space_copy(space));
+       embedding = isl_multi_aff_identity(space);
+       build->values = isl_multi_aff_product(build->values, embedding);
+
+       space = isl_ast_build_get_space(build, 1);
+       build->options = embed_options(build->options, space);
+
+       if (!build->iterators || !build->domain || !build->generated ||
+           !build->pending || !build->values ||
+           !build->strides || !build->offsets || !build->options)
+               return isl_ast_build_free(build);
+
+       return build;
+error:
+       isl_ast_build_free(build);
+       isl_space_free(space);
+       return NULL;
+}
+
+/* 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_keep isl_aff *aff)
+{
+       isl_set *test;
+       int empty;
+
+       if (!build)
+               return -1;
+
+       aff = isl_aff_copy(aff);
+       test = isl_set_from_basic_set(isl_aff_neg_basic_set(aff));
+       test = isl_set_intersect(test, isl_set_copy(build->domain));
+       empty = isl_set_is_empty(test);
+       isl_set_free(test);
+
+       return empty;
+}
+
+/* Does the dimension at (internal) position "pos" have a non-trivial stride?
+ */
+int isl_ast_build_has_stride(__isl_keep isl_ast_build *build, int pos)
+{
+       isl_int v;
+       int has_stride;
+
+       if (!build)
+               return -1;
+
+       isl_int_init(v);
+       isl_vec_get_element(build->strides, pos, &v);
+       has_stride = !isl_int_is_one(v);
+       isl_int_clear(v);
+
+       return has_stride;
+}
+
+/* Given that the dimension at position "pos" takes on values
+ *
+ *     f + s a
+ *
+ * with a an integer, return s through *stride.
+ */
+int isl_ast_build_get_stride(__isl_keep isl_ast_build *build, int pos,
+       isl_int *stride)
+{
+       if (!build)
+               return -1;
+
+       isl_vec_get_element(build->strides, pos, stride);
+
+       return 0;
+}
+
+/* Given that the dimension at position "pos" takes on values
+ *
+ *     f + s a
+ *
+ * with a an integer, return f.
+ */
+__isl_give isl_aff *isl_ast_build_get_offset(
+       __isl_keep isl_ast_build *build, int pos)
+{
+       if (!build)
+               return NULL;
+
+       return isl_multi_aff_get_aff(build->offsets, pos);
+}
+
+/* Is the dimension at position "pos" known to attain only a single
+ * value that, moreover, can be described by a single affine expression
+ * in terms of the outer dimensions and parameters?
+ *
+ * If not, then the correponding affine expression in build->values
+ * is set to be equal to the same input dimension.
+ * Otherwise, it is set to the requested expression in terms of
+ * outer dimensions and parameters.
+ */
+int isl_ast_build_has_affine_value(__isl_keep isl_ast_build *build,
+       int pos)
+{
+       isl_aff *aff;
+       int involves;
+
+       if (!build)
+               return -1;
+
+       aff = isl_multi_aff_get_aff(build->values, pos);
+       involves = isl_aff_involves_dims(aff, isl_dim_in, pos, 1);
+       isl_aff_free(aff);
+
+       if (involves < 0)
+               return -1;
+
+       return !involves;
+}
+
+/* Is the current dimension known to attain only a single value?
+ */
+int isl_ast_build_has_value(__isl_keep isl_ast_build *build)
+{
+       if (!build)
+               return -1;
+
+       return build->value != NULL;
+}
+
+/* Simplify the basic set "bset" based on what we know about
+ * the iterators of already generated loops.
+ *
+ * "bset" is assumed to live in the (internal) schedule domain.
+ */
+__isl_give isl_basic_set *isl_ast_build_compute_gist_basic_set(
+       __isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset)
+{
+       if (!build)
+               goto error;
+
+       bset = isl_basic_set_preimage_multi_aff(bset,
+                                       isl_multi_aff_copy(build->values));
+       bset = isl_basic_set_gist(bset,
+                       isl_set_simple_hull(isl_set_copy(build->domain)));
+
+       return bset;
+error:
+       isl_basic_set_free(bset);
+       return NULL;
+}
+
+/* Simplify the set "set" based on what we know about
+ * the iterators of already generated loops.
+ *
+ * "set" is assumed to live in the (internal) schedule domain.
+ */
+__isl_give isl_set *isl_ast_build_compute_gist(
+       __isl_keep isl_ast_build *build, __isl_take isl_set *set)
+{
+       if (!build)
+               goto error;
+
+       set = isl_set_preimage_multi_aff(set,
+                                       isl_multi_aff_copy(build->values));
+       set = isl_set_gist(set, isl_set_copy(build->domain));
+
+       return set;
+error:
+       isl_set_free(set);
+       return NULL;
+}
+
+/* Simplify the map "map" based on what we know about
+ * the iterators of already generated loops.
+ *
+ * The domain of "map" is assumed to live in the (internal) schedule domain.
+ */
+__isl_give isl_map *isl_ast_build_compute_gist_map_domain(
+       __isl_keep isl_ast_build *build, __isl_take isl_map *map)
+{
+       if (!build)
+               goto error;
+
+       map = isl_map_gist_domain(map, isl_set_copy(build->domain));
+
+       return map;
+error:
+       isl_map_free(map);
+       return NULL;
+}
+
+/* Simplify the affine expression "aff" based on what we know about
+ * the iterators of already generated loops.
+ *
+ * The domain of "aff" is assumed to live in the (internal) schedule domain.
+ */
+__isl_give isl_aff *isl_ast_build_compute_gist_aff(
+       __isl_keep isl_ast_build *build, __isl_take isl_aff *aff)
+{
+       if (!build)
+               goto error;
+
+       aff = isl_aff_gist(aff, isl_set_copy(build->domain));
+
+       return aff;
+error:
+       isl_aff_free(aff);
+       return NULL;
+}
+
+/* Simplify the piecewise affine expression "aff" based on what we know about
+ * the iterators of already generated loops.
+ *
+ * The domain of "pa" is assumed to live in the (internal) schedule domain.
+ */
+__isl_give isl_pw_aff *isl_ast_build_compute_gist_pw_aff(
+       __isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa)
+{
+       if (!build)
+               goto error;
+
+       pa = isl_pw_aff_pullback_multi_aff(pa,
+                                       isl_multi_aff_copy(build->values));
+       pa = isl_pw_aff_gist(pa, isl_set_copy(build->domain));
+
+       return pa;
+error:
+       isl_pw_aff_free(pa);
+       return NULL;
+}
+
+/* Simplify the piecewise multi-affine expression "aff" based on what
+ * we know about the iterators of already generated loops.
+ *
+ * The domain of "pma" is assumed to live in the (internal) schedule domain.
+ */
+__isl_give isl_pw_multi_aff *isl_ast_build_compute_gist_pw_multi_aff(
+       __isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma)
+{
+       if (!build)
+               goto error;
+
+       pma = isl_pw_multi_aff_pullback_multi_aff(pma,
+                                       isl_multi_aff_copy(build->values));
+       pma = isl_pw_multi_aff_gist(pma, isl_set_copy(build->domain));
+
+       return pma;
+error:
+       isl_pw_multi_aff_free(pma);
+       return NULL;
+}
+
+/* Extract the schedule domain of the given type from build->options
+ * at the current depth.
+ *
+ * In particular, find the subset of build->options that is of
+ * the following form
+ *
+ *     schedule_domain -> type[depth]
+ *
+ * and return the corresponding domain, after eliminating inner dimensions
+ * and divs that depend on the current dimension.
+ *
+ * Note that the domain of build->options has been reformulated
+ * in terms of the internal build space in embed_options,
+ * but the position is still that within the current code generation.
+ */
+__isl_give isl_set *isl_ast_build_get_option_domain(
+       __isl_keep isl_ast_build *build,
+       enum isl_ast_build_domain_type type)
+{
+       const char *name;
+       isl_space *space;
+       isl_map *option;
+       isl_set *domain;
+       int local_pos;
+
+       if (!build)
+               return NULL;
+
+       name = option_str[type];
+       local_pos = build->depth - build->outer_pos;
+
+       space = isl_ast_build_get_space(build, 1);
+       space = isl_space_from_domain(space);
+       space = isl_space_add_dims(space, isl_dim_out, 1);
+       space = isl_space_set_tuple_name(space, isl_dim_out, name);
+
+       option = isl_union_map_extract_map(build->options, space);
+       option = isl_map_fix_si(option, isl_dim_out, 0, local_pos);
+
+       domain = isl_map_domain(option);
+       domain = isl_ast_build_eliminate(build, domain);
+
+       return domain;
+}
+
+/* Extract the separation class mapping at the current depth.
+ *
+ * In particular, find and return the subset of build->options that is of
+ * the following form
+ *
+ *     schedule_domain -> separation_class[[depth] -> [class]]
+ *
+ * The caller is expected to eliminate inner dimensions from the domain.
+ *
+ * Note that the domain of build->options has been reformulated
+ * in terms of the internal build space in embed_options,
+ * but the position is still that within the current code generation.
+ */
+__isl_give isl_map *isl_ast_build_get_separation_class(
+       __isl_keep isl_ast_build *build)
+{
+       isl_ctx *ctx;
+       isl_space *space_sep, *space;
+       isl_map *res;
+       int local_pos;
+
+       if (!build)
+               return NULL;
+
+       local_pos = build->depth - build->outer_pos;
+       ctx = isl_ast_build_get_ctx(build);
+       space_sep = isl_space_alloc(ctx, 0, 1, 1);
+       space_sep = isl_space_wrap(space_sep);
+       space_sep = isl_space_set_tuple_name(space_sep, isl_dim_set,
+                                               "separation_class");
+       space = isl_ast_build_get_space(build, 1);
+       space_sep = isl_space_align_params(space_sep, isl_space_copy(space));
+       space = isl_space_map_from_domain_and_range(space, space_sep);
+
+       res = isl_union_map_extract_map(build->options, space);
+       res = isl_map_fix_si(res, isl_dim_out, 0, local_pos);
+       res = isl_map_coalesce(res);
+
+       return res;
+}
+
+/* Eliminate dimensions inner to the current dimension.
+ */
+__isl_give isl_set *isl_ast_build_eliminate_inner(
+       __isl_keep isl_ast_build *build, __isl_take isl_set *set)
+{
+       int dim;
+       int depth;
+
+       if (!build)
+               return isl_set_free(set);
+
+       dim = isl_set_dim(set, isl_dim_set);
+       depth = build->depth;
+       set = isl_set_detect_equalities(set);
+       set = isl_set_eliminate(set, isl_dim_set, depth + 1, dim - (depth + 1));
+
+       return set;
+}
+
+/* Eliminate unknown divs and divs that depend on the current dimension.
+ */
+__isl_give isl_set *isl_ast_build_eliminate_divs(
+       __isl_keep isl_ast_build *build, __isl_take isl_set *set)
+{
+       int depth;
+
+       if (!build)
+               return isl_set_free(set);
+
+       depth = build->depth;
+       set = isl_set_remove_divs_involving_dims(set, isl_dim_set, depth, 1);
+       set = isl_set_remove_unknown_divs(set);
+
+       return set;
+}
+
+/* Eliminate dimensions inner to the current dimension as well as
+ * unknown divs and divs that depend on the current dimension.
+ * The result then consists only of constraints that are independent
+ * of the current dimension and upper and lower bounds on the current
+ * dimension.
+ */
+__isl_give isl_set *isl_ast_build_eliminate(
+       __isl_keep isl_ast_build *build, __isl_take isl_set *domain)
+{
+       domain = isl_ast_build_eliminate_inner(build, domain);
+       domain = isl_ast_build_eliminate_divs(build, domain);
+       return domain;
+}
diff --git a/isl_ast_build_expr.c b/isl_ast_build_expr.c
new file mode 100644 (file)
index 0000000..adab2a2
--- /dev/null
@@ -0,0 +1,883 @@
+/*
+ * 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/ilp.h>
+#include <isl_ast_build_expr.h>
+#include <isl_ast_private.h>
+#include <isl_ast_build_private.h>
+
+/* Compute the minimum of the integer affine expression "obj" over the points
+ * in build->domain and put the result in *opt.
+ */
+enum isl_lp_result isl_ast_build_min(__isl_keep isl_ast_build *build,
+       __isl_keep isl_aff *obj, isl_int *opt)
+{
+       if (!build)
+               return isl_lp_error;
+
+       return isl_set_min(build->domain, obj, opt);
+}
+
+/* Compute the maximum of the integer affine expression "obj" over the points
+ * in build->domain and put the result in *opt.
+ */
+enum isl_lp_result isl_ast_build_max(__isl_keep isl_ast_build *build,
+       __isl_keep isl_aff *obj, isl_int *opt)
+{
+       if (!build)
+               return isl_lp_error;
+
+       return isl_set_max(build->domain, obj, opt);
+}
+
+/* Create an isl_ast_expr evaluating the div at position "pos" in "ls".
+ * The result is simplified in terms of build->domain.
+ * The size is computed by the caller.
+ *
+ * "ls" is known to be non-NULL.
+ *
+ * Let the div be of the form floor(e/d).
+ * If the ast_build_prefer_pdiv option is set then we check if "e"
+ * is non-negative, so that we can generate
+ *
+ *     (pdiv_q, expr(e), expr(d))
+ *
+ * instead of
+ *
+ *     (fdiv_q, expr(e), expr(d))
+ *
+ */
+static __isl_give isl_ast_expr *var_div(__isl_keep isl_local_space *ls,
+       int pos, __isl_keep isl_ast_build *build)
+{
+       isl_ctx *ctx = isl_local_space_get_ctx(ls);
+       isl_aff *aff;
+       isl_ast_expr *num, *den;
+       isl_int d;
+       enum isl_ast_op_type type;
+
+       aff = isl_local_space_get_div(ls, pos);
+       isl_int_init(d);
+       isl_aff_get_denominator(aff, &d);
+       aff = isl_aff_scale(aff, d);
+       den = isl_ast_expr_alloc_int(ctx, d);
+       isl_int_clear(d);
+
+       type = isl_ast_op_fdiv_q;
+       if (isl_options_get_ast_build_prefer_pdiv(ctx)) {
+               int non_neg = isl_ast_build_aff_is_nonneg(build, aff);
+               if (non_neg < 0)
+                       aff = isl_aff_free(aff);
+               else if (non_neg)
+                       type = isl_ast_op_pdiv_q;
+       }
+
+       num = isl_ast_expr_from_aff(aff, build);
+       return isl_ast_expr_alloc_binary(type, num, den);
+}
+
+/* Create an isl_ast_expr evaluating the specified dimension of "ls".
+ * The result is simplified in terms of build->domain.
+ * The size is computed by the caller.
+ *
+ * The isl_ast_expr is constructed based on the type of the dimension.
+ * - divs are constructed by var_div
+ * - set variables are constructed from the iterator isl_ids in "build"
+ * - parameters are constructed from the isl_ids in "ls"
+ */
+static __isl_give isl_ast_expr *var(__isl_keep isl_local_space *ls,
+       enum isl_dim_type type, int pos, __isl_keep isl_ast_build *build)
+{
+       isl_ctx *ctx = isl_local_space_get_ctx(ls);
+       isl_id *id;
+
+       if (type == isl_dim_div)
+               return var_div(ls, pos, build);
+
+       if (type == isl_dim_set) {
+               id = isl_ast_build_get_iterator_id(build, pos);
+               return isl_ast_expr_from_id(id);
+       }
+
+       if (!isl_local_space_has_dim_id(ls, type, pos))
+               isl_die(ctx, isl_error_internal, "unnamed dimension",
+                       return NULL);
+       id = isl_local_space_get_dim_id(ls, type, pos);
+       return isl_ast_expr_from_id(id);
+}
+
+/* Does "expr" represent the zero integer?
+ */
+static int ast_expr_is_zero(__isl_keep isl_ast_expr *expr)
+{
+       if (!expr)
+               return -1;
+       if (expr->type != isl_ast_expr_int)
+               return 0;
+       return isl_int_is_zero(expr->u.i);
+}
+
+/* Create an expression representing the sum of "expr1" and "expr2",
+ * provided neither of the two expressions is identically zero.
+ */
+static __isl_give isl_ast_expr *ast_expr_add(__isl_take isl_ast_expr *expr1,
+       __isl_take isl_ast_expr *expr2)
+{
+       if (!expr1 || !expr2)
+               goto error;
+
+       if (ast_expr_is_zero(expr1)) {
+               isl_ast_expr_free(expr1);
+               return expr2;
+       }
+
+       if (ast_expr_is_zero(expr2)) {
+               isl_ast_expr_free(expr2);
+               return expr1;
+       }
+
+       return isl_ast_expr_add(expr1, expr2);
+error:
+       isl_ast_expr_free(expr1);
+       isl_ast_expr_free(expr2);
+       return NULL;
+}
+
+/* Subtract expr2 from expr1.
+ *
+ * If expr2 is zero, we simply return expr1.
+ * If expr1 is zero, we return
+ *
+ *     (isl_ast_op_minus, expr2)
+ *
+ * Otherwise, we return
+ *
+ *     (isl_ast_op_sub, expr1, expr2)
+ */
+static __isl_give isl_ast_expr *ast_expr_sub(__isl_take isl_ast_expr *expr1,
+       __isl_take isl_ast_expr *expr2)
+{
+       if (!expr1 || !expr2)
+               goto error;
+
+       if (ast_expr_is_zero(expr2)) {
+               isl_ast_expr_free(expr2);
+               return expr1;
+       }
+
+       if (ast_expr_is_zero(expr1)) {
+               isl_ast_expr_free(expr1);
+               return isl_ast_expr_neg(expr2);
+       }
+
+       return isl_ast_expr_sub(expr1, expr2);
+error:
+       isl_ast_expr_free(expr1);
+       isl_ast_expr_free(expr2);
+       return NULL;
+}
+
+/* Return an isl_ast_expr that represents
+ *
+ *     v * (aff mod d)
+ *
+ * v is assumed to be non-negative.
+ * The result is simplified in terms of build->domain.
+ */
+static __isl_give isl_ast_expr *isl_ast_expr_mod(isl_int v,
+       __isl_keep isl_aff *aff, isl_int d, __isl_keep isl_ast_build *build)
+{
+       isl_ctx *ctx;
+       isl_ast_expr *expr;
+       isl_ast_expr *c;
+
+       if (!aff)
+               return NULL;
+
+       ctx = isl_aff_get_ctx(aff);
+       expr = isl_ast_expr_from_aff(isl_aff_copy(aff), build);
+
+       c = isl_ast_expr_alloc_int(ctx, d);
+       return isl_ast_expr_alloc_binary(isl_ast_op_pdiv_r, expr, c);
+}
+
+/* Create an isl_ast_expr evaluating "v" times the specified dimension of "ls".
+ * The result is simplified in terms of build->domain.
+ *
+ * Let e be the expression for the specified dimension.
+ * If v is 1, we simply return e.
+ * If v is -1, we return
+ *
+ *     (isl_ast_op_minus, e)
+ *
+ * Otherwise, we return
+ *
+ *     (isl_ast_op_mul, expr(v), e)
+ */
+static __isl_give isl_ast_expr *isl_ast_expr_term(
+       __isl_keep isl_local_space *ls, enum isl_dim_type type, int pos,
+       isl_int v, __isl_keep isl_ast_build *build)
+{
+       isl_ctx *ctx;
+       isl_ast_expr *expr;
+       isl_ast_expr *c;
+
+       if (!ls)
+               return NULL;
+
+       ctx = isl_local_space_get_ctx(ls);
+       expr = var(ls, type, pos, build);
+
+       if (!isl_int_is_one(v)) {
+               if (isl_int_is_negone(v)) {
+                       expr = isl_ast_expr_neg(expr);
+               } else {
+                       c = isl_ast_expr_alloc_int(ctx, v);
+                       expr = isl_ast_expr_mul(c, expr);
+               }
+       }
+
+       return expr;
+}
+
+/* Add an expression for "v" times the specified dimension of "ls"
+ * to expr.
+ *
+ * Let e be the expression for the specified dimension.
+ * If "v" is negative, we create
+ *
+ *     (isl_ast_op_sub, cons->expr, e)
+ *
+ * except when cons->expr is trivially zero, in which case we create
+ *
+ *     (isl_ast_op_mines, e)
+ *
+ * instead.
+ *
+ * If "v" is positive, we simply create
+ *
+ *     (isl_ast_op_add, cons->expr, e)
+ *
+ */
+static __isl_give isl_ast_expr *isl_ast_expr_add_term(
+       __isl_take isl_ast_expr *expr,
+       __isl_keep isl_local_space *ls, enum isl_dim_type type, int pos,
+       isl_int v, __isl_keep isl_ast_build *build)
+{
+       isl_ast_expr *term;
+
+       if (!expr)
+               return NULL;
+
+       if (isl_int_is_neg(v) && !ast_expr_is_zero(expr)) {
+               isl_int_neg(v, v);
+               term = isl_ast_expr_term(ls, type, pos, v, build);
+               return ast_expr_sub(expr, term);
+       } else {
+               term = isl_ast_expr_term(ls, type, pos, v, build);
+               return ast_expr_add(expr, term);
+       }
+}
+
+/* Add an expression for "v" to expr.
+ */
+static __isl_give isl_ast_expr *isl_ast_expr_add_int(
+       __isl_take isl_ast_expr *expr, isl_int v)
+{
+       isl_ctx *ctx;
+       isl_ast_expr *expr_int;
+
+       if (!expr)
+               return NULL;
+
+       if (isl_int_is_zero(v))
+               return expr;
+
+       ctx = isl_ast_expr_get_ctx(expr);
+       if (isl_int_is_neg(v) && !ast_expr_is_zero(expr)) {
+               isl_int_neg(v, v);
+               expr_int = isl_ast_expr_alloc_int(ctx, v);
+               return ast_expr_sub(expr, expr_int);
+       } else {
+               expr_int = isl_ast_expr_alloc_int(ctx, v);
+               return ast_expr_add(expr, expr_int);
+       }
+}
+
+/* Check if "aff" involves any (implicit) modulo computations.
+ * If so, remove them from aff and add expressions corresponding
+ * to those modulo computations to *pos and/or *neg.
+ * We only do this if the option ast_build_prefer_pdiv is set.
+ *
+ * A modulo expression is of the form
+ *
+ *     a mod m = a - m * floor(a / m)
+ *
+ * To detect them in aff, we look for terms of the form
+ *
+ *     (f * m * floor(a / m)) / d
+ *
+ * rewrite them as
+ *
+ *     (f * (a - (a mod m))) / d = (f * a) / d - (f * (a mod m)) / d
+ *
+ * and extract out -f * (a mod m).
+ * In particular, if f > 0, we add (f * (a mod m)) to *neg.
+ * If f < 0, we add ((-f) * (a mod m)) to *pos.
+ *
+ * The caller is responsible for dividing *neg and/or *pos by d.
+ */
+static __isl_give isl_aff *extract_modulos(__isl_take isl_aff *aff,
+       __isl_keep isl_ast_expr **pos, __isl_keep isl_ast_expr **neg,
+       __isl_keep isl_ast_build *build)
+{
+       isl_ctx *ctx;
+       int j, n;
+       isl_int v, d;
+       isl_local_space *ls;
+
+       if (!aff)
+               return NULL;
+
+       ctx = isl_aff_get_ctx(aff);
+       if (!isl_options_get_ast_build_prefer_pdiv(ctx))
+               return aff;
+
+       isl_int_init(v);
+       isl_int_init(d);
+       ls = isl_aff_get_domain_local_space(aff);
+
+       n = isl_aff_dim(aff, isl_dim_div);
+       for (j = 0; j < n; ++j) {
+               isl_ast_expr *expr;
+               isl_aff *div;
+               int s;
+               int mod;
+
+               isl_aff_get_coefficient(aff, isl_dim_div, j, &v);
+               if (isl_int_is_zero(v))
+                       continue;
+               div = isl_local_space_get_div(ls, j);
+               isl_aff_get_denominator(div, &d);
+               mod = isl_int_is_divisible_by(v, d);
+               if (mod)
+                       mod = isl_ast_build_aff_is_nonneg(build, div);
+               if (mod < 0) {
+                       aff = isl_aff_free(aff);
+                       isl_aff_free(div);
+                       break;
+               } else if (!mod) {
+                       isl_aff_free(div);
+                       continue;
+               }
+               div = isl_aff_scale(div, d);
+               isl_int_divexact(v, v, d);
+               s = isl_int_sgn(v);
+               isl_int_abs(v, v);
+               expr = isl_ast_expr_mod(v, div, d, build);
+               if (s > 0)
+                       *neg = ast_expr_add(*neg, expr);
+               else
+                       *pos = ast_expr_add(*pos, expr);
+               aff = isl_aff_set_coefficient_si(aff, isl_dim_div, j, 0);
+               if (s < 0)
+                       isl_int_neg(v, v);
+               div = isl_aff_scale(div, v);
+               isl_aff_get_denominator(aff, &d);
+               div = isl_aff_scale_down(div, d);
+               aff = isl_aff_add(aff, div);
+       }
+
+       isl_local_space_free(ls);
+       isl_int_clear(d);
+       isl_int_clear(v);
+
+       return aff;
+}
+
+/* Construct an isl_ast_expr that evaluates the affine expression "aff",
+ * The result is simplified in terms of build->domain.
+ *
+ * We first extract hidden modulo computations from the affine expression
+ * and then add terms for each variable with a non-zero coefficient.
+ * Finally, if the affine expression has a non-trivial denominator,
+ * we divide the resulting isl_ast_expr by this denominator.
+ */
+__isl_give isl_ast_expr *isl_ast_expr_from_aff(__isl_take isl_aff *aff,
+       __isl_keep isl_ast_build *build)
+{
+       int i, j;
+       isl_int v;
+       int n;
+       isl_ctx *ctx = isl_aff_get_ctx(aff);
+       isl_ast_expr *expr, *expr_neg;
+       enum isl_dim_type t[] = { isl_dim_param, isl_dim_in, isl_dim_div };
+       enum isl_dim_type l[] = { isl_dim_param, isl_dim_set, isl_dim_div };
+       isl_local_space *ls;
+
+       if (!aff)
+               return NULL;
+
+       expr = isl_ast_expr_alloc_int_si(ctx, 0);
+       expr_neg = isl_ast_expr_alloc_int_si(ctx, 0);
+
+       aff = extract_modulos(aff, &expr, &expr_neg, build);
+       expr = ast_expr_sub(expr, expr_neg);
+
+       isl_int_init(v);
+       ls = isl_aff_get_domain_local_space(aff);
+
+       for (i = 0; i < 3; ++i) {
+               n = isl_aff_dim(aff, t[i]);
+               for (j = 0; j < n; ++j) {
+                       isl_aff_get_coefficient(aff, t[i], j, &v);
+                       if (isl_int_is_zero(v))
+                               continue;
+                       expr = isl_ast_expr_add_term(expr,
+                                                       ls, l[i], j, v, build);
+               }
+       }
+
+       isl_aff_get_constant(aff, &v);
+       expr = isl_ast_expr_add_int(expr, v);
+
+       isl_aff_get_denominator(aff, &v);
+       if (!isl_int_is_one(v)) {
+               isl_ast_expr *d;
+               d = isl_ast_expr_alloc_int(ctx, v);
+               expr = isl_ast_expr_div(expr, d);
+       }
+
+       isl_local_space_free(ls);
+       isl_int_clear(v);
+       isl_aff_free(aff);
+       return expr;
+}
+
+/* Add terms to "expr" for each variable in "aff" with a coefficient
+ * with sign equal to "sign".
+ * The result is simplified in terms of build->domain.
+ */
+static __isl_give isl_ast_expr *add_signed_terms(__isl_take isl_ast_expr *expr,
+       __isl_keep isl_aff *aff, int sign, __isl_keep isl_ast_build *build)
+{
+       int i, j;
+       isl_int v;
+       enum isl_dim_type t[] = { isl_dim_param, isl_dim_in, isl_dim_div };
+       enum isl_dim_type l[] = { isl_dim_param, isl_dim_set, isl_dim_div };
+       isl_local_space *ls;
+
+       isl_int_init(v);
+       ls = isl_aff_get_domain_local_space(aff);
+
+       for (i = 0; i < 3; ++i) {
+               int n = isl_aff_dim(aff, t[i]);
+               for (j = 0; j < n; ++j) {
+                       isl_aff_get_coefficient(aff, t[i], j, &v);
+                       if (sign * isl_int_sgn(v) <= 0)
+                               continue;
+                       isl_int_abs(v, v);
+                       expr = isl_ast_expr_add_term(expr,
+                                               ls, l[i], j, v, build);
+               }
+       }
+
+       isl_aff_get_constant(aff, &v);
+       if (sign * isl_int_sgn(v) > 0) {
+               isl_int_abs(v, v);
+               expr = isl_ast_expr_add_int(expr, v);
+       }
+
+       isl_local_space_free(ls);
+       isl_int_clear(v);
+
+       return expr;
+}
+
+/* Construct an isl_ast_expr that evaluates the condition "constraint",
+ * The result is simplified in terms of build->domain.
+ *
+ * Let the constraint by either "a >= 0" or "a == 0".
+ * We first extract hidden modulo computations from "a"
+ * and then collect all the terms with a positive coefficient in cons_pos
+ * and the terms with a negative coefficient in cons_neg.
+ *
+ * The result is then of the form
+ *
+ *     (isl_ast_op_ge, expr(pos), expr(-neg)))
+ *
+ * or
+ *
+ *     (isl_ast_op_eq, expr(pos), expr(-neg)))
+ *
+ * However, if the first expression is an integer constant (and the second
+ * is not), then we swap the two expressions.  This ensures that we construct,
+ * e.g., "i <= 5" rather than "5 >= i".
+ */
+static __isl_give isl_ast_expr *isl_ast_expr_from_constraint(
+       __isl_take isl_constraint *constraint, __isl_keep isl_ast_build *build)
+{
+       isl_ctx *ctx;
+       isl_ast_expr *expr_pos;
+       isl_ast_expr *expr_neg;
+       isl_ast_expr *expr;
+       isl_aff *aff;
+       int eq;
+       enum isl_ast_op_type type;
+
+       if (!constraint)
+               return NULL;
+
+       aff = isl_constraint_get_aff(constraint);
+
+       ctx = isl_constraint_get_ctx(constraint);
+       expr_pos = isl_ast_expr_alloc_int_si(ctx, 0);
+       expr_neg = isl_ast_expr_alloc_int_si(ctx, 0);
+
+       aff = extract_modulos(aff, &expr_pos, &expr_neg, build);
+
+       expr_pos = add_signed_terms(expr_pos, aff, 1, build);
+       expr_neg = add_signed_terms(expr_neg, aff, -1, build);
+
+       eq = isl_constraint_is_equality(constraint);
+
+       if (isl_ast_expr_get_type(expr_pos) == isl_ast_expr_int &&
+           isl_ast_expr_get_type(expr_neg) != isl_ast_expr_int) {
+               type = eq ? isl_ast_op_eq : isl_ast_op_le;
+               expr = isl_ast_expr_alloc_binary(type, expr_neg, expr_pos);
+       } else {
+               type = eq ? isl_ast_op_eq : isl_ast_op_ge;
+               expr = isl_ast_expr_alloc_binary(type, expr_pos, expr_neg);
+       }
+
+       isl_constraint_free(constraint);
+       isl_aff_free(aff);
+       return expr;
+}
+
+struct isl_expr_from_basic_data {
+       isl_ast_build *build;
+       int first;
+       isl_ast_expr *res;
+};
+
+/* Construct an isl_ast_expr that evaluates the condition "c",
+ * except if it is a div constraint, and add it to the data->res.
+ * The result is simplified in terms of data->build->domain.
+ */
+static int expr_from_basic_set(__isl_take isl_constraint *c, void *user)
+{
+       struct isl_expr_from_basic_data *data = user;
+       isl_ast_expr *expr;
+
+       if (isl_constraint_is_div_constraint(c)) {
+               isl_constraint_free(c);
+               return 0;
+       }
+
+       expr = isl_ast_expr_from_constraint(c, data->build);
+       if (data->first)
+               data->res = expr;
+       else
+               data->res = isl_ast_expr_and(data->res, expr);
+
+       data->first = 0;
+
+       if (!data->res)
+               return -1;
+       return 0;
+}
+
+/* Construct an isl_ast_expr that evaluates the conditions defining "bset".
+ * The result is simplified in terms of build->domain.
+ *
+ * We filter out the div constraints during printing, so we do not know
+ * in advance how many constraints are going to be printed.
+ *
+ * If it turns out that there was no constraint, then we contruct
+ * the expression "1", i.e., "true".
+ */
+__isl_give isl_ast_expr *isl_ast_build_expr_from_basic_set(
+        __isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset)
+{
+       struct isl_expr_from_basic_data data = { build, 1, NULL };
+
+       if (isl_basic_set_foreach_constraint(bset,
+                                           &expr_from_basic_set, &data) < 0) {
+               data.res = isl_ast_expr_free(data.res);
+       } else if (data.res == NULL) {
+               isl_ctx *ctx = isl_basic_set_get_ctx(bset);
+               data.res = isl_ast_expr_alloc_int_si(ctx, 1);
+       }
+
+       isl_basic_set_free(bset);
+       return data.res;
+}
+
+struct isl_expr_from_set_data {
+       isl_ast_build *build;
+       int first;
+       isl_ast_expr *res;
+};
+
+/* Construct an isl_ast_expr that evaluates the conditions defining "bset"
+ * and add it to data->res.
+ * The result is simplified in terms of data->build->domain.
+ */
+static int expr_from_set(__isl_take isl_basic_set *bset, void *user)
+{
+       struct isl_expr_from_set_data *data = user;
+       isl_ast_expr *expr;
+
+       expr = isl_ast_build_expr_from_basic_set(data->build, bset);
+       if (data->first)
+               data->res = expr;
+       else
+               data->res = isl_ast_expr_or(data->res, expr);
+
+       data->first = 0;
+
+       if (!data->res)
+               return -1;
+       return 0;
+}
+
+/* Construct an isl_ast_expr that evaluates the conditions defining "set".
+ * The result is simplified in terms of build->domain.
+ */
+__isl_give isl_ast_expr *isl_ast_build_expr_from_set(
+       __isl_keep isl_ast_build *build, __isl_take isl_set *set)
+{
+       struct isl_expr_from_set_data data = { build, 1, NULL };
+
+       if (isl_set_foreach_basic_set(set, &expr_from_set, &data) < 0)
+               data.res = isl_ast_expr_free(data.res);
+
+       isl_set_free(set);
+       return data.res;
+}
+
+struct isl_from_pw_aff_data {
+       isl_ast_build *build;
+       int n;
+       isl_ast_expr **next;
+       isl_set *dom;
+};
+
+/* This function is called during the construction of an isl_ast_expr
+ * that evaluates an isl_pw_aff.
+ * Adjust data->next to take into account this piece.
+ *
+ * data->n is the number of pairs of set and aff to go.
+ * data->dom is the domain of the entire isl_pw_aff.
+ *
+ * If this is the last pair, then data->next is set to evaluate aff
+ * and the domain is ignored.
+ * Otherwise, data->next is set to a select operation that selects
+ * an isl_ast_expr correponding to "aff" on "set" and to an expression
+ * that will be filled in by later calls otherwise.
+ */
+static int ast_expr_from_pw_aff(__isl_take isl_set *set,
+       __isl_take isl_aff *aff, void *user)
+{
+       struct isl_from_pw_aff_data *data = user;
+       isl_ctx *ctx;
+
+       ctx = isl_set_get_ctx(set);
+       data->n--;
+       if (data->n == 0) {
+               *data->next = isl_ast_expr_from_aff(aff, data->build);
+               isl_set_free(set);
+               if (!*data->next)
+                       return -1;
+       } else {
+               isl_ast_expr *ternary, *arg;
+
+               ternary = isl_ast_expr_alloc_op(ctx, isl_ast_op_select, 3);
+               set = isl_set_gist(set, isl_set_copy(data->dom));
+               arg = isl_ast_build_expr_from_set(data->build, set);
+               ternary = isl_ast_expr_set_op_arg(ternary, 0, arg);
+               arg = isl_ast_expr_from_aff(aff, data->build);
+               ternary = isl_ast_expr_set_op_arg(ternary, 1, arg);
+               if (!ternary)
+                       return -1;
+
+               *data->next = ternary;
+               data->next = &ternary->u.op.args[2];
+       }
+
+       return 0;
+}
+
+/* Construct an isl_ast_expr that evaluates "pa".
+ * The result is simplified in terms of build->domain.
+ *
+ * The domain of "pa" lives in the internal schedule space.
+ */
+__isl_give isl_ast_expr *isl_ast_build_expr_from_pw_aff_internal(
+       __isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa)
+{
+       struct isl_from_pw_aff_data data;
+       isl_ast_expr *res = NULL;
+
+       if (!pa)
+               return NULL;
+
+       data.build = build;
+       data.n = isl_pw_aff_n_piece(pa);
+       data.next = &res;
+       data.dom = isl_pw_aff_domain(isl_pw_aff_copy(pa));
+
+       if (isl_pw_aff_foreach_piece(pa, &ast_expr_from_pw_aff, &data) < 0)
+               res = isl_ast_expr_free(res);
+       else if (!res)
+               isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
+                       "cannot handle void expression", res = NULL);
+
+       isl_pw_aff_free(pa);
+       isl_set_free(data.dom);
+       return res;
+}
+
+/* Construct an isl_ast_expr that evaluates "pa".
+ * The result is simplified in terms of build->domain.
+ *
+ * The domain of "pa" lives in the external schedule space.
+ */
+__isl_give isl_ast_expr *isl_ast_build_expr_from_pw_aff(
+       __isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa)
+{
+       isl_ast_expr *expr;
+
+       if (isl_ast_build_need_schedule_map(build)) {
+               isl_multi_aff *ma;
+               ma = isl_ast_build_get_schedule_map_multi_aff(build);
+               pa = isl_pw_aff_pullback_multi_aff(pa, ma);
+       }
+       expr = isl_ast_build_expr_from_pw_aff_internal(build, pa);
+       return expr;
+}
+
+/* Set the ids of the input dimensions of "pma" to the iterator ids
+ * of "build".
+ *
+ * The domain of "pma" is assumed to live in the internal schedule domain.
+ */
+static __isl_give isl_pw_multi_aff *set_iterator_names(
+       __isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma)
+{
+       int i, n;
+
+       n = isl_pw_multi_aff_dim(pma, isl_dim_in);
+       for (i = 0; i < n; ++i) {
+               isl_id *id;
+
+               id = isl_ast_build_get_iterator_id(build, i);
+               pma = isl_pw_multi_aff_set_dim_id(pma, isl_dim_in, i, id);
+       }
+
+       return pma;
+}
+
+/* Construct an isl_ast_expr that calls the domain element specified by "pma".
+ * The name of the function is obtained from the output tuple name.
+ * The arguments are given by the piecewise affine expressions.
+ *
+ * The domain of "pma" is assumed to live in the internal schedule domain.
+ */
+static __isl_give isl_ast_expr *isl_ast_build_call_from_pw_multi_aff_internal(
+       __isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma)
+{
+       int i, n;
+       isl_ctx *ctx;
+       isl_id *id;
+       isl_ast_expr *expr;
+
+       pma = set_iterator_names(build, pma);
+       if (!build || !pma)
+               return isl_pw_multi_aff_free(pma);
+
+       ctx = isl_ast_build_get_ctx(build);
+       n = isl_pw_multi_aff_dim(pma, isl_dim_out);
+       expr = isl_ast_expr_alloc_op(ctx, isl_ast_op_call, 1 + n);
+
+       if (isl_pw_multi_aff_has_tuple_id(pma, isl_dim_out))
+               id = isl_pw_multi_aff_get_tuple_id(pma, isl_dim_out);
+       else
+               id = isl_id_alloc(ctx, "", NULL);
+
+       expr = isl_ast_expr_set_op_arg(expr, 0, isl_ast_expr_from_id(id));
+       for (i = 0; i < n; ++i) {
+               isl_pw_aff *pa;
+               isl_ast_expr *arg;
+
+               pa = isl_pw_multi_aff_get_pw_aff(pma, i);
+               arg = isl_ast_build_expr_from_pw_aff_internal(build, pa);
+               expr = isl_ast_expr_set_op_arg(expr, 1 + i, arg);
+       }
+
+       isl_pw_multi_aff_free(pma);
+       return expr;
+}
+
+/* Construct an isl_ast_expr that calls the domain element specified by "pma".
+ * The name of the function is obtained from the output tuple name.
+ * The arguments are given by the piecewise affine expressions.
+ *
+ * The domain of "pma" is assumed to live in the external schedule domain.
+ */
+__isl_give isl_ast_expr *isl_ast_build_call_from_pw_multi_aff(
+       __isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma)
+{
+       int is_domain;
+       isl_ast_expr *expr;
+       isl_space *space_build, *space_pma;
+
+       space_build = isl_ast_build_get_space(build, 0);
+       space_pma = isl_pw_multi_aff_get_space(pma);
+       is_domain = isl_space_tuple_match(space_build, isl_dim_set,
+                                       space_pma, isl_dim_in);
+       isl_space_free(space_build);
+       isl_space_free(space_pma);
+       if (is_domain < 0)
+               return isl_pw_multi_aff_free(pma);
+       if (!is_domain)
+               isl_die(isl_ast_build_get_ctx(build), isl_error_invalid,
+                       "spaces don't match",
+                       return isl_pw_multi_aff_free(pma));
+
+       if (isl_ast_build_need_schedule_map(build)) {
+               isl_multi_aff *ma;
+               ma = isl_ast_build_get_schedule_map_multi_aff(build);
+               pma = isl_pw_multi_aff_pullback_multi_aff(pma, ma);
+       }
+
+       expr = isl_ast_build_call_from_pw_multi_aff_internal(build, pma);
+       return expr;
+}
+
+/* Construct an isl_ast_expr that calls the domain element
+ * specified by "executed".
+ *
+ * "executed" is assumed to be single-valued, with a domain that lives
+ * in the internal schedule space.
+ */
+__isl_give isl_ast_node *isl_ast_build_call_from_executed(
+       __isl_keep isl_ast_build *build, __isl_take isl_map *executed)
+{
+       isl_pw_multi_aff *iteration;
+       isl_ast_expr *expr;
+
+       iteration = isl_pw_multi_aff_from_map(executed);
+       iteration = isl_ast_build_compute_gist_pw_multi_aff(build, iteration);
+       iteration = isl_pw_multi_aff_intersect_domain(iteration,
+                                       isl_ast_build_get_domain(build));
+       expr = isl_ast_build_call_from_pw_multi_aff_internal(build, iteration);
+       return isl_ast_node_alloc_user(expr);
+}
diff --git a/isl_ast_build_expr.h b/isl_ast_build_expr.h
new file mode 100644 (file)
index 0000000..bf3af04
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef ISL_AST_BUILD_EXPR_PRIVATE_H
+#define ISL_AST_BUILD_EXPR_PRIVATE_H
+
+#include <isl/ast.h>
+#include <isl/ast_build.h>
+
+__isl_give isl_ast_expr *isl_ast_build_expr_from_basic_set(
+        __isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset);
+__isl_give isl_ast_expr *isl_ast_build_expr_from_set(
+       __isl_keep isl_ast_build *build, __isl_take isl_set *set);
+
+__isl_give isl_ast_expr *isl_ast_build_expr_from_pw_aff_internal(
+       __isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa);
+__isl_give isl_ast_expr *isl_ast_expr_from_aff(__isl_take isl_aff *aff,
+       __isl_keep isl_ast_build *build);
+__isl_give isl_ast_expr *isl_ast_expr_set_op_arg(__isl_take isl_ast_expr *expr,
+       int pos, __isl_take isl_ast_expr *arg);
+
+__isl_give isl_ast_node *isl_ast_build_call_from_executed(
+       __isl_keep isl_ast_build *build, __isl_take isl_map *executed);
+
+#endif
diff --git a/isl_ast_build_private.h b/isl_ast_build_private.h
new file mode 100644 (file)
index 0000000..0ee88c5
--- /dev/null
@@ -0,0 +1,232 @@
+#ifndef ISL_AST_BUILD_PRIVATE_H
+#define ISL_AST_BUILD_PRIVATE_H
+
+#include <isl/aff.h>
+#include <isl/ast.h>
+#include <isl/ast_build.h>
+#include <isl/set.h>
+#include <isl/list.h>
+
+enum isl_ast_build_domain_type {
+       atomic,
+       unroll,
+       separate
+};
+
+/* An isl_ast_build represents the context in which AST is being
+ * generated.  That is, it (mostly) contains information about outer
+ * loops that can be used to simplify inner loops.
+ *
+ * "domain" represents constraints on the internal schedule domain,
+ * corresponding to the context of the AST generation and the constraints
+ * implied by the loops that have already been generated.
+ * When an isl_ast_build is first created, outside any AST generation,
+ * the domain is typically a parameter set.  It is only when a AST
+ * generation phase is initiated that the domain of the isl_ast_build
+ * is changed to refer to the internal schedule domain.
+ * The domain then lives in a space of the form
+ *
+ *     S
+ *
+ *  or
+ *
+ *     [O -> S]
+ *
+ * O represents the loops generated in outer AST generations.
+ * S represents the loops (both generated and to be generated)
+ * of the current AST generation.
+ * Both include eliminated loops.
+ * "domain" is expected not to have any unknown divs because
+ * it is used as the context argument in a call to isl_basic_set_gist
+ * in isl_ast_build_compute_gist_basic_set.
+ *
+ * "depth" is equal to the number of loops that have already
+ * been generated (including those in outer AST generations).
+ * "outer_pos" is equal to the number of loops in outer AST generations.
+ *
+ * "generated" is a superset of "domain" corresponding to those
+ * constraints that were either given by the user or that have
+ * effectively been generated (as bounds on a for loop).
+ *
+ * "pending" is a superset of "domain" corresponding to the constraints
+ * that still need to be generated (as guards), but that may end up
+ * not getting generated if they are implied by any constraints
+ * enforced by inner loops.
+ *
+ * "strides" contains the stride of each loop.  The number of elements
+ * is equal to the number of dimensions in "domain".
+ * "offsets" constains the offsets of strided loops.  If s is the stride
+ * for a given dimension and f is the corresponding offset, then the
+ * dimension takes on values
+ *
+ *     f + s a
+ *
+ * with a an integer.  For non-strided loops, the offset is zero.
+ *
+ * "iterators" contains the loop iterators of both generated and
+ * to be generated loops.  The number of elements is at least as
+ * large as the dimension of the internal schedule domain.  The
+ * number may be larger, in which case the additional ids can be
+ * used in a nested AST generation should the schedule be non-injective.
+ *
+ * "values" lives in the space
+ *
+ *     [O -> S] -> [O -> S]            (or S -> S)
+ *
+ * and expresses (if possible) loop iterators in terms of parameters
+ * and outer loop iterators.  If the value of a given loop iterator
+ * cannot be expressed as an affine expression (either because the iterator
+ * attains multiple values or because the single value is a piecewise
+ * affine expression), then it is expressed in "values" as being equal
+ * to itself.
+ *
+ * "value" is the value of the loop iterator at the current depth.
+ * It is NULL if it has not been computed yet or if the value of the
+ * given loop iterator cannot be expressed as a piecewise affine expression
+ * (because the iterator attains multiple values).
+ *
+ * "schedule_map" maps the internal schedule domain to the external schedule
+ * domain.  It may be NULL if it hasn't been computed yet.
+ * See isl_ast_build_get_schedule_map_multi_aff.
+ *
+ * The "create_leaf" callback is called for every leaf in the generated AST.
+ * The callback is responsible for creating the node to be placed at those
+ * leaves.  If this callback is not set, then isl will generated user
+ * nodes with call expressions corresponding to an element of the domain.
+ *
+ * The "at_each_domain" callback is called on every node created to represent
+ * an element of the domain.  Each of these nodes is a user node
+ * with as expression a call expression.
+ *
+ * "executed" contains the inverse schedule at this point
+ * of the AST generation.
+ * It is currently only used in isl_ast_build_get_schedule, which is
+ * in turn only used by user code from within a callback.
+ * The value is set right before we may be calling such a callback.
+ */
+struct isl_ast_build {
+       int ref;
+
+       int outer_pos;
+       int depth;
+
+       isl_id_list *iterators;
+
+       isl_set *domain;
+       isl_set *generated;
+       isl_set *pending;
+       isl_multi_aff *values;
+
+       isl_pw_aff *value;
+
+       isl_vec *strides;
+       isl_multi_aff *offsets;
+
+       isl_multi_aff *schedule_map;
+
+       isl_union_map *options;
+
+       __isl_give isl_ast_node *(*at_each_domain)(
+               __isl_take isl_ast_node *node,
+               __isl_keep isl_ast_build *build, void *user);
+       void *at_each_domain_user;
+
+       __isl_give isl_ast_node *(*create_leaf)(
+               __isl_take isl_ast_build *build, void *user);
+       void *create_leaf_user;
+
+       isl_union_map *executed;
+};
+
+__isl_give isl_ast_build *isl_ast_build_clear_local_info(
+       __isl_take isl_ast_build *build);
+__isl_give isl_ast_build *isl_ast_build_increase_depth(
+       __isl_take isl_ast_build *build);
+int isl_ast_build_get_depth(__isl_keep isl_ast_build *build);
+__isl_give isl_space *isl_ast_build_get_space(
+       __isl_keep isl_ast_build *build, int internal);
+__isl_give isl_ast_build *isl_ast_build_align_params(
+       __isl_take isl_ast_build *build, __isl_take isl_space *model);
+__isl_give isl_ast_build *isl_ast_build_cow(
+       __isl_take isl_ast_build *build);
+__isl_give isl_ast_build *isl_ast_build_insert_dim(
+       __isl_take isl_ast_build *build, int pos);
+__isl_give isl_ast_build *isl_ast_build_scale_down(
+       __isl_take isl_ast_build *build, isl_int m,
+       __isl_take isl_union_map *umap);
+__isl_give isl_ast_build *isl_ast_build_product(
+       __isl_take isl_ast_build *build, __isl_take isl_space *embedding);
+__isl_give isl_ast_build *isl_ast_build_set_loop_bounds(
+       __isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds);
+__isl_give isl_ast_build *isl_ast_build_detect_strides(
+       __isl_take isl_ast_build *build, __isl_take isl_set *set);
+__isl_give isl_ast_build *isl_ast_build_include_stride(
+       __isl_take isl_ast_build *build);
+__isl_give isl_ast_build *isl_ast_build_set_executed(
+       __isl_take isl_ast_build *build,
+       __isl_take isl_union_map *executed);
+__isl_give isl_set *isl_ast_build_get_domain(
+       __isl_keep isl_ast_build *build);
+__isl_give isl_ast_build *isl_ast_build_restrict_generated(
+       __isl_take isl_ast_build *build, __isl_take isl_set *set);
+__isl_give isl_ast_build *isl_ast_build_restrict_pending(
+       __isl_take isl_ast_build *build, __isl_take isl_set *set);
+__isl_give isl_ast_build *isl_ast_build_set_enforced(
+       __isl_take isl_ast_build *build, __isl_take isl_basic_set *enforced);
+__isl_give int isl_ast_build_need_schedule_map(
+       __isl_keep isl_ast_build *build);
+__isl_give isl_multi_aff *isl_ast_build_get_schedule_map_multi_aff(
+       __isl_keep isl_ast_build *build);
+__isl_give isl_map *isl_ast_build_get_schedule_map(
+       __isl_keep isl_ast_build *build);
+int isl_ast_build_has_affine_value(__isl_keep isl_ast_build *build, int pos);
+int isl_ast_build_has_value(__isl_keep isl_ast_build *build);
+__isl_give isl_id *isl_ast_build_get_iterator_id(
+       __isl_keep isl_ast_build *build, int pos);
+
+__isl_give isl_basic_set *isl_ast_build_compute_gist_basic_set(
+       __isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset);
+__isl_give isl_set *isl_ast_build_compute_gist(
+       __isl_keep isl_ast_build *build, __isl_take isl_set *set);
+__isl_give isl_map *isl_ast_build_compute_gist_map_domain(
+       __isl_keep isl_ast_build *build, __isl_take isl_map *map);
+__isl_give isl_aff *isl_ast_build_compute_gist_aff(
+       __isl_keep isl_ast_build *build, __isl_take isl_aff *aff);
+__isl_give isl_pw_aff *isl_ast_build_compute_gist_pw_aff(
+       __isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa);
+__isl_give isl_pw_multi_aff *isl_ast_build_compute_gist_pw_multi_aff(
+       __isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma);
+
+int isl_ast_build_aff_is_nonneg(__isl_keep isl_ast_build *build,
+       __isl_keep isl_aff *aff);
+
+int isl_ast_build_has_stride(__isl_keep isl_ast_build *build, int pos);
+__isl_give isl_aff *isl_ast_build_get_offset(__isl_keep isl_ast_build *build,
+       int pos);
+int isl_ast_build_get_stride(__isl_keep isl_ast_build *build, int pos,
+       isl_int *stride);
+__isl_give isl_set *isl_ast_build_get_stride_constraint(
+       __isl_keep isl_ast_build *build);
+__isl_give isl_multi_aff *isl_ast_build_get_stride_expansion(
+       __isl_keep isl_ast_build *build);
+
+void isl_ast_build_dump(__isl_keep isl_ast_build *build);
+
+__isl_give isl_set *isl_ast_build_get_option_domain(
+       __isl_keep isl_ast_build *build,
+       enum isl_ast_build_domain_type type);
+__isl_give isl_map *isl_ast_build_get_separation_class(
+       __isl_keep isl_ast_build *build);
+__isl_give isl_set *isl_ast_build_eliminate(
+       __isl_keep isl_ast_build *build, __isl_take isl_set *domain);
+__isl_give isl_set *isl_ast_build_eliminate_inner(
+       __isl_keep isl_ast_build *build, __isl_take isl_set *set);
+__isl_give isl_set *isl_ast_build_eliminate_divs(
+       __isl_keep isl_ast_build *build, __isl_take isl_set *set);
+
+__isl_give isl_map *isl_ast_build_map_to_iterator(
+       __isl_keep isl_ast_build *build, __isl_take isl_set *set);
+
+int isl_ast_build_options_involve_depth(__isl_keep isl_ast_build *build);
+
+#endif
diff --git a/isl_ast_codegen.c b/isl_ast_codegen.c
new file mode 100644 (file)
index 0000000..c0afa0a
--- /dev/null
@@ -0,0 +1,3487 @@
+/*
+ * 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/aff.h>
+#include <isl/set.h>
+#include <isl/ilp.h>
+#include <isl/union_map.h>
+#include <isl_sort.h>
+#include <isl_tarjan.h>
+#include <isl_ast_private.h>
+#include <isl_ast_build_expr.h>
+#include <isl_ast_build_private.h>
+#include <isl_ast_graft_private.h>
+#include <isl_list_private.h>
+
+/* Add the constraint to the list that "user" points to, if it is not
+ * a div constraint.
+ */
+static int collect_constraint(__isl_take isl_constraint *constraint,
+       void *user)
+{
+       isl_constraint_list **list = user;
+
+       if (isl_constraint_is_div_constraint(constraint))
+               isl_constraint_free(constraint);
+       else
+               *list = isl_constraint_list_add(*list, constraint);
+
+       return 0;
+}
+
+/* Extract the constraints of "bset" (except the div constraints)
+ * and collect them in an isl_constraint_list.
+ */
+static __isl_give isl_constraint_list *isl_constraint_list_from_basic_set(
+       __isl_take isl_basic_set *bset)
+{
+       int n;
+       isl_ctx *ctx;
+       isl_constraint_list *list;
+
+       if (!bset)
+               return NULL;
+
+       ctx = isl_basic_set_get_ctx(bset);
+
+       n = isl_basic_set_n_constraint(bset);
+       list = isl_constraint_list_alloc(ctx, n);
+       if (isl_basic_set_foreach_constraint(bset,
+                                           &collect_constraint, &list) < 0)
+               list = isl_constraint_list_free(list);
+
+       isl_basic_set_free(bset);
+       return list;
+}
+
+/* Data used in generate_domain.
+ *
+ * "build" is the input build.
+ * "list" collects the results.
+ */
+struct isl_generate_domain_data {
+       isl_ast_build *build;
+
+       isl_ast_graft_list *list;
+};
+
+static __isl_give isl_ast_graft_list *generate_next_level(
+       __isl_take isl_union_map *executed,
+       __isl_take isl_ast_build *build);
+static __isl_give isl_ast_graft_list *generate_code(
+       __isl_take isl_union_map *executed, __isl_take isl_ast_build *build,
+       int internal);
+
+/* Generate an AST for a single domain based on
+ * the (non single valued) inverse schedule "executed".
+ *
+ * We extend the schedule with the iteration domain
+ * and continue generating through a call to generate_code.
+ *
+ * In particular, if executed has the form
+ *
+ *     S -> D
+ *
+ * then we continue generating code on
+ *
+ *     [S -> D] -> D
+ *
+ * The extended inverse schedule is clearly single valued
+ * ensuring that the nested generate_code will not reach this function,
+ * but will instead create calls to all elements of D that need
+ * to be executed from the current schedule domain.
+ */
+static int generate_non_single_valued(__isl_take isl_map *executed,
+       struct isl_generate_domain_data *data)
+{
+       isl_map *identity;
+       isl_ast_build *build;
+       isl_ast_graft_list *list;
+
+       build = isl_ast_build_copy(data->build);
+
+       identity = isl_set_identity(isl_map_range(isl_map_copy(executed)));
+       executed = isl_map_domain_product(executed, identity);
+
+       list = generate_code(isl_union_map_from_map(executed), build, 1);
+
+       data->list = isl_ast_graft_list_concat(data->list, list);
+
+       return 0;
+}
+
+/* Call the at_each_domain callback, if requested by the user,
+ * after recording the current inverse schedule in the build.
+ */
+static __isl_give isl_ast_graft *at_each_domain(__isl_take isl_ast_graft *graft,
+       __isl_keep isl_map *executed, __isl_keep isl_ast_build *build)
+{
+       if (!graft || !build)
+               return isl_ast_graft_free(graft);
+       if (!build->at_each_domain)
+               return graft;
+
+       build = isl_ast_build_copy(build);
+       build = isl_ast_build_set_executed(build,
+                       isl_union_map_from_map(isl_map_copy(executed)));
+       if (!build)
+               return isl_ast_graft_free(graft);
+
+       graft->node = build->at_each_domain(graft->node,
+                                       build, build->at_each_domain_user);
+       isl_ast_build_free(build);
+
+       if (!graft->node)
+               graft = isl_ast_graft_free(graft);
+
+       return graft;
+}
+
+/* Generate an AST for a single domain based on
+ * the inverse schedule "executed".
+ *
+ * If there is more than one domain element associated to the current
+ * schedule "time", then we need to continue the generation process
+ * in generate_non_single_valued.
+ * Note that the inverse schedule being single-valued may depend
+ * on constraints that are only available in the original context
+ * domain specified by the user.  If the bare inverse schedule
+ * is not single-valued, we double-check after introducing the constraints
+ * from data->build->domain.
+ *
+ * Otherwise, we generate a call expression for the single executed
+ * domain element and put a guard around it based on the (simplified)
+ * domain of "executed".
+ *
+ * If the user has set an at_each_domain callback, it is called
+ * on the constructed call expression node.
+ */
+static int generate_domain(__isl_take isl_map *executed, void *user)
+{
+       struct isl_generate_domain_data *data = user;
+       isl_ast_graft *graft;
+       isl_ast_graft_list *list;
+       isl_set *guard;
+       isl_map *map;
+       int sv;
+
+       sv = isl_map_is_single_valued(executed);
+       if (sv < 0)
+               goto error;
+       if (!sv) {
+               map = isl_map_copy(executed);
+               map = isl_map_intersect_domain(map,
+                                           isl_set_copy(data->build->domain));
+               sv = isl_map_is_single_valued(map);
+               isl_map_free(map);
+       }
+       if (!sv)
+               return generate_non_single_valued(executed, data);
+
+       executed = isl_map_coalesce(executed);
+       map = isl_map_copy(executed);
+       map = isl_ast_build_compute_gist_map_domain(data->build, map);
+       guard = isl_map_domain(isl_map_copy(map));
+       guard = isl_set_coalesce(guard);
+       guard = isl_ast_build_compute_gist(data->build, guard);
+       graft = isl_ast_graft_alloc_domain(map, data->build);
+       graft = at_each_domain(graft, executed, data->build);
+
+       isl_map_free(executed);
+       graft = isl_ast_graft_add_guard(graft, guard, data->build);
+
+       list = isl_ast_graft_list_from_ast_graft(graft);
+       data->list = isl_ast_graft_list_concat(data->list, list);
+
+       return 0;
+error:
+       isl_map_free(executed);
+       return -1;
+}
+
+/* Call build->create_leaf to a create "leaf" node in the AST,
+ * encapsulate the result in an isl_ast_graft and return the result
+ * as a 1-element list.
+ *
+ * Note that the node returned by the user may be an entire tree.
+ *
+ * Before we pass control to the user, we first clear some information
+ * from the build that is (presumbably) only meaningful
+ * for the current code generation.
+ * This includes the create_leaf callback itself, so we make a copy
+ * of the build first.
+ */
+static __isl_give isl_ast_graft_list *call_create_leaf(
+       __isl_take isl_union_map *executed, __isl_take isl_ast_build *build)
+{
+       isl_ast_node *node;
+       isl_ast_graft *graft;
+       isl_ast_build *user_build;
+
+       user_build = isl_ast_build_copy(build);
+       user_build = isl_ast_build_set_executed(user_build, executed);
+       user_build = isl_ast_build_clear_local_info(user_build);
+       if (!user_build)
+               node = NULL;
+       else
+               node = build->create_leaf(user_build, build->create_leaf_user);
+       graft = isl_ast_graft_alloc(node, build);
+       isl_ast_build_free(build);
+       return isl_ast_graft_list_from_ast_graft(graft);
+}
+
+/* Generate an AST after having handled the complete schedule
+ * of this call to the code generator.
+ *
+ * If the user has specified a create_leaf callback, control
+ * is passed to the user in call_create_leaf.
+ *
+ * Otherwise, we generate one or more calls for each individual
+ * domain in generate_domain.
+ */
+static __isl_give isl_ast_graft_list *generate_inner_level(
+       __isl_take isl_union_map *executed, __isl_take isl_ast_build *build)
+{
+       isl_ctx *ctx;
+       struct isl_generate_domain_data data = { build };
+
+       if (!build || !executed)
+               goto error;
+
+       if (build->create_leaf)
+               return call_create_leaf(executed, build);
+
+       ctx = isl_union_map_get_ctx(executed);
+       data.list = isl_ast_graft_list_alloc(ctx, 0);
+       if (isl_union_map_foreach_map(executed, &generate_domain, &data) < 0)
+               data.list = isl_ast_graft_list_free(data.list);
+
+       if (0)
+error:         data.list = NULL;
+       isl_ast_build_free(build);
+       isl_union_map_free(executed);
+       return data.list;
+}
+
+/* Eliminate the schedule dimension "pos" from "executed" and return
+ * the result.
+ */
+static __isl_give isl_union_map *eliminate(__isl_take isl_union_map *executed,
+       int pos, __isl_keep isl_ast_build *build)
+{
+       isl_space *space;
+       isl_map *elim;
+
+       space = isl_ast_build_get_space(build, 1);
+       space = isl_space_map_from_set(space);
+       elim = isl_map_identity(space);
+       elim = isl_map_eliminate(elim, isl_dim_in, pos, 1);
+
+       executed = isl_union_map_apply_domain(executed,
+                                               isl_union_map_from_map(elim));
+
+       return executed;
+}
+
+/* Check if the constraint "c" is a lower bound on dimension "pos",
+ * an upper bound, or independent of dimension "pos".
+ */
+static int constraint_type(isl_constraint *c, int pos)
+{
+       if (isl_constraint_is_lower_bound(c, isl_dim_set, pos))
+               return 1;
+       if (isl_constraint_is_upper_bound(c, isl_dim_set, pos))
+               return 2;
+       return 0;
+}
+
+/* Compare the types of the constraints "a" and "b",
+ * resulting in constraints that are independent of "depth"
+ * to be sorted before the lower bounds on "depth", which in
+ * turn are sorted before the upper bounds on "depth".
+ */
+static int cmp_constraint(const void *a, const void *b, void *user)
+{
+       int *depth = user;
+       isl_constraint * const *c1 = a;
+       isl_constraint * const *c2 = b;
+       int t1 = constraint_type(*c1, *depth);
+       int t2 = constraint_type(*c2, *depth);
+
+       return t1 - t2;
+}
+
+/* Extract a lower bound on dimension "pos" from constraint "c".
+ *
+ * If the constraint is of the form
+ *
+ *     a x + f(...) >= 0
+ *
+ * then we essentially return
+ *
+ *     l = ceil(-f(...)/a)
+ *
+ * However, if the current dimension is strided, then we need to make
+ * sure that the lower bound we construct is of the form
+ *
+ *     f + s a
+ *
+ * with f the offset and s the stride.
+ * We therefore compute
+ *
+ *     f + s * ceil((l - f)/s)
+ */
+static __isl_give isl_aff *lower_bound(__isl_keep isl_constraint *c,
+       int pos, __isl_keep isl_ast_build *build)
+{
+       isl_aff *aff;
+
+       aff = isl_constraint_get_bound(c, isl_dim_set, pos);
+       aff = isl_aff_ceil(aff);
+
+       if (isl_ast_build_has_stride(build, pos)) {
+               isl_aff *offset;
+               isl_int stride;
+
+               isl_int_init(stride);
+
+               offset = isl_ast_build_get_offset(build, pos);
+               isl_ast_build_get_stride(build, pos, &stride);
+
+               aff = isl_aff_sub(aff, isl_aff_copy(offset));
+               aff = isl_aff_scale_down(aff, stride);
+               aff = isl_aff_ceil(aff);
+               aff = isl_aff_scale(aff, stride);
+               aff = isl_aff_add(aff, offset);
+
+               isl_int_clear(stride);
+       }
+
+       aff = isl_ast_build_compute_gist_aff(build, aff);
+
+       return aff;
+}
+
+/* Return the exact lower bound (or upper bound if "upper" is set)
+ * of "domain" as a piecewise affine expression.
+ *
+ * If we are computing a lower bound (of a strided dimension), then
+ * we need to make sure it is of the form
+ *
+ *     f + s a
+ *
+ * where f is the offset and s is the stride.
+ * We therefore need to include the stride constraint before computing
+ * the minimum.
+ */
+static __isl_give isl_pw_aff *exact_bound(__isl_keep isl_set *domain,
+       __isl_keep isl_ast_build *build, int upper)
+{
+       isl_set *stride;
+       isl_map *it_map;
+       isl_pw_aff *pa;
+       isl_pw_multi_aff *pma;
+
+       domain = isl_set_copy(domain);
+       if (!upper) {
+               stride = isl_ast_build_get_stride_constraint(build);
+               domain = isl_set_intersect(domain, stride);
+       }
+       it_map = isl_ast_build_map_to_iterator(build, domain);
+       if (upper)
+               pma = isl_map_lexmax_pw_multi_aff(it_map);
+       else
+               pma = isl_map_lexmin_pw_multi_aff(it_map);
+       pa = isl_pw_multi_aff_get_pw_aff(pma, 0);
+       isl_pw_multi_aff_free(pma);
+       pa = isl_ast_build_compute_gist_pw_aff(build, pa);
+       pa = isl_pw_aff_coalesce(pa);
+
+       return pa;
+}
+
+/* Return a list of "n" lower bounds on dimension "pos"
+ * extracted from the "n" constraints starting at "constraint".
+ * If "n" is zero, then we extract a lower bound from "domain" instead.
+ */
+static __isl_give isl_pw_aff_list *lower_bounds(
+       __isl_keep isl_constraint **constraint, int n, int pos,
+       __isl_keep isl_set *domain, __isl_keep isl_ast_build *build)
+{
+       isl_ctx *ctx;
+       isl_pw_aff_list *list;
+       int i;
+
+       if (!build)
+               return NULL;
+
+       if (n == 0) {
+               isl_pw_aff *pa;
+               pa = exact_bound(domain, build, 0);
+               return isl_pw_aff_list_from_pw_aff(pa);
+       }
+
+       ctx = isl_ast_build_get_ctx(build);
+       list = isl_pw_aff_list_alloc(ctx,n);
+
+       for (i = 0; i < n; ++i) {
+               isl_aff *aff;
+
+               aff = lower_bound(constraint[i], pos, build);
+               list = isl_pw_aff_list_add(list, isl_pw_aff_from_aff(aff));
+       }
+
+       return list;
+}
+
+/* Return a list of "n" upper bounds on dimension "pos"
+ * extracted from the "n" constraints starting at "constraint".
+ * If "n" is zero, then we extract an upper bound from "domain" instead.
+ */
+static __isl_give isl_pw_aff_list *upper_bounds(
+       __isl_keep isl_constraint **constraint, int n, int pos,
+       __isl_keep isl_set *domain, __isl_keep isl_ast_build *build)
+{
+       isl_ctx *ctx;
+       isl_pw_aff_list *list;
+       int i;
+
+       if (n == 0) {
+               isl_pw_aff *pa;
+               pa = exact_bound(domain, build, 1);
+               return isl_pw_aff_list_from_pw_aff(pa);
+       }
+
+       ctx = isl_ast_build_get_ctx(build);
+       list = isl_pw_aff_list_alloc(ctx,n);
+
+       for (i = 0; i < n; ++i) {
+               isl_aff *aff;
+
+               aff = isl_constraint_get_bound(constraint[i], isl_dim_set, pos);
+               aff = isl_aff_floor(aff);
+               list = isl_pw_aff_list_add(list, isl_pw_aff_from_aff(aff));
+       }
+
+       return list;
+}
+
+/* Return an isl_ast_expr that performs the reduction of type "type"
+ * on AST expressions corresponding to the elements in "list".
+ *
+ * The list is assumed to contain at least one element.
+ * If the list contains exactly one element, then the returned isl_ast_expr
+ * simply computes that affine expression.
+ */
+static __isl_give isl_ast_expr *reduce_list(enum isl_ast_op_type type,
+       __isl_keep isl_pw_aff_list *list, __isl_keep isl_ast_build *build)
+{
+       int i, n;
+       isl_ctx *ctx;
+       isl_ast_expr *expr;
+
+       if (!list)
+               return NULL;
+
+       n = isl_pw_aff_list_n_pw_aff(list);
+
+       if (n == 1)
+               return isl_ast_build_expr_from_pw_aff_internal(build,
+                               isl_pw_aff_list_get_pw_aff(list, 0));
+
+       ctx = isl_pw_aff_list_get_ctx(list);
+       expr = isl_ast_expr_alloc_op(ctx, type, n);
+       if (!expr)
+               return NULL;
+
+       for (i = 0; i < n; ++i) {
+               isl_ast_expr *expr_i;
+
+               expr_i = isl_ast_build_expr_from_pw_aff_internal(build,
+                               isl_pw_aff_list_get_pw_aff(list, i));
+               if (!expr_i)
+                       return isl_ast_expr_free(expr);
+               expr->u.op.args[i] = expr_i;
+       }
+
+       return expr;
+}
+
+/* Add a guard to "graft" based on "bound" in the case of a degenerate
+ * level (including the special case of an eliminated level).
+ *
+ * We eliminate the current dimension, simplify the result in the current
+ * build and add the result as guards to the graft.
+ *
+ * Note that we cannot simply drop the constraints on the current dimension
+ * even in the eliminated case, because the single affine expression may
+ * not be explicitly available in "bounds".  Moreover, the single affine
+ * expression may only be defined on a subset of the build domain,
+ * so we do in some cases need to insert a guard even in the eliminated case.
+ */
+static __isl_give isl_ast_graft *add_degenerate_guard(
+       __isl_take isl_ast_graft *graft, __isl_keep isl_basic_set *bounds,
+       __isl_keep isl_ast_build *build)
+{
+       int depth;
+       isl_set *dom;
+
+       depth = isl_ast_build_get_depth(build);
+
+       dom = isl_set_from_basic_set(isl_basic_set_copy(bounds));
+       if (isl_ast_build_has_stride(build, depth)) {
+               isl_set *stride;
+
+               stride = isl_ast_build_get_stride_constraint(build);
+               dom = isl_set_intersect(dom, stride);
+       }
+       dom = isl_set_eliminate(dom, isl_dim_set, depth, 1);
+       dom = isl_ast_build_compute_gist(build, dom);
+
+       graft = isl_ast_graft_add_guard(graft, dom, build);
+
+       return graft;
+}
+
+/* Update "graft" based on "bounds" for the eliminated case.
+ *
+ * In the eliminated case, no for node is created, so we only need
+ * to check if "bounds" imply any guards that need to be inserted.
+ */
+static __isl_give isl_ast_graft *refine_eliminated(
+       __isl_take isl_ast_graft *graft, __isl_keep isl_basic_set *bounds,
+       __isl_keep isl_ast_build *build)
+{
+       return add_degenerate_guard(graft, bounds, build);
+}
+
+/* Update "graft" based on "bounds" and "sub_build" for the degenerate case.
+ *
+ * "build" is the build in which graft->node was created
+ * "sub_build" contains information about the current level itself,
+ * including the single value attained.
+ *
+ * We first set the initialization part of the for loop to the single
+ * value attained by the current dimension.
+ * The increment and condition are not strictly needed as the are known
+ * to be "1" and "iterator <= value" respectively.
+ * Then we set the size of the iterator and
+ * check if "bounds" imply any guards that need to be inserted.
+ */
+static __isl_give isl_ast_graft *refine_degenerate(
+       __isl_take isl_ast_graft *graft, __isl_keep isl_basic_set *bounds,
+       __isl_keep isl_ast_build *build,
+       __isl_keep isl_ast_build *sub_build)
+{
+       isl_pw_aff *value;
+
+       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)
+               return isl_ast_graft_free(graft);
+
+       graft = add_degenerate_guard(graft, bounds, build);
+
+       return graft;
+}
+
+/* Return the intersection of the "n" constraints starting at "constraint"
+ * as a set.
+ */
+static __isl_give isl_set *intersect_constraints(isl_ctx *ctx,
+       __isl_keep isl_constraint **constraint, int n)
+{
+       int i;
+       isl_basic_set *bset;
+
+       if (n < 1)
+               isl_die(ctx, isl_error_internal,
+                       "expecting at least one constraint", return NULL);
+
+       bset = isl_basic_set_from_constraint(
+                               isl_constraint_copy(constraint[0]));
+       for (i = 1; i < n; ++i) {
+               isl_basic_set *bset_i;
+
+               bset_i = isl_basic_set_from_constraint(
+                                       isl_constraint_copy(constraint[i]));
+               bset = isl_basic_set_intersect(bset, bset_i);
+       }
+
+       return isl_set_from_basic_set(bset);
+}
+
+/* Compute the constraints on the outer dimensions enforced by
+ * graft->node and add those constraints to graft->enforced,
+ * in case the upper bound is expressed as a set "upper".
+ *
+ * In particular, if l(...) is a lower bound in "lower", and
+ *
+ *     -a i + f(...) >= 0              or      a i <= f(...)
+ *
+ * is an upper bound ocnstraint on the current dimension i,
+ * then the for loop enforces the constraint
+ *
+ *     -a l(...) + f(...) >= 0         or      a l(...) <= f(...)
+ *
+ * We therefore simply take each lower bound in turn, plug it into
+ * the upper bounds and compute the intersection over all lower bounds.
+ *
+ * If a lower bound is a rational expression, then
+ * isl_basic_set_preimage_multi_aff will force this rational
+ * expression to have only integer values.  However, the loop
+ * itself does not enforce this integrality constraint.  We therefore
+ * use the ceil of the lower bounds instead of the lower bounds themselves.
+ * Other constraints will make sure that the for loop is only executed
+ * when each of the lower bounds attains an integral value.
+ * In particular, potentially rational values only occur in
+ * lower_bound if the offset is a (seemingly) rational expression,
+ * but then outer conditions will make sure that this rational expression
+ * only attains integer values.
+ */
+static __isl_give isl_ast_graft *set_enforced_from_set(
+       __isl_take isl_ast_graft *graft,
+       __isl_keep isl_pw_aff_list *lower, int pos, __isl_keep isl_set *upper)
+{
+       isl_space *space;
+       isl_basic_set *enforced;
+       isl_pw_multi_aff *pma;
+       int i, n;
+
+       if (!graft || !lower)
+               return isl_ast_graft_free(graft);
+
+       space = isl_set_get_space(upper);
+       enforced = isl_basic_set_universe(isl_space_copy(space));
+
+       space = isl_space_map_from_set(space);
+       pma = isl_pw_multi_aff_identity(space);
+
+       n = isl_pw_aff_list_n_pw_aff(lower);
+       for (i = 0; i < n; ++i) {
+               isl_pw_aff *pa;
+               isl_set *enforced_i;
+               isl_basic_set *hull;
+               isl_pw_multi_aff *pma_i;
+
+               pa = isl_pw_aff_list_get_pw_aff(lower, i);
+               pa = isl_pw_aff_ceil(pa);
+               pma_i = isl_pw_multi_aff_copy(pma);
+               pma_i = isl_pw_multi_aff_set_pw_aff(pma_i, pos, pa);
+               enforced_i = isl_set_copy(upper);
+               enforced_i = isl_set_preimage_pw_multi_aff(enforced_i, pma_i);
+               hull = isl_set_simple_hull(enforced_i);
+               enforced = isl_basic_set_intersect(enforced, hull);
+       }
+
+       isl_pw_multi_aff_free(pma);
+
+       graft = isl_ast_graft_enforce(graft, enforced);
+
+       return graft;
+}
+
+/* Compute the constraints on the outer dimensions enforced by
+ * graft->node and add those constraints to graft->enforced,
+ * in case the upper bound is expressed as
+ * a list of affine expressions "upper".
+ *
+ * The enforced condition is that each lower bound expression is less
+ * than or equal to each upper bound expression.
+ */
+static __isl_give isl_ast_graft *set_enforced_from_list(
+       __isl_take isl_ast_graft *graft,
+       __isl_keep isl_pw_aff_list *lower, __isl_keep isl_pw_aff_list *upper)
+{
+       isl_set *cond;
+       isl_basic_set *enforced;
+
+       lower = isl_pw_aff_list_copy(lower);
+       upper = isl_pw_aff_list_copy(upper);
+       cond = isl_pw_aff_list_le_set(lower, upper);
+       enforced = isl_set_simple_hull(cond);
+       graft = isl_ast_graft_enforce(graft, enforced);
+
+       return graft;
+}
+
+/* Set the condition part of the for node graft->node in case
+ * the upper bound is represented as a list of piecewise affine expressions.
+ *
+ * In particular, set the condition to
+ *
+ *     iterator <= min(list of upper bounds)
+ */
+static __isl_give isl_ast_graft *set_for_cond_from_list(
+       __isl_take isl_ast_graft *graft, __isl_keep isl_pw_aff_list *list,
+       __isl_keep isl_ast_build *build)
+{
+       isl_ast_expr *bound, *iterator, *cond;
+
+       if (!graft || !list)
+               return isl_ast_graft_free(graft);
+
+       bound = reduce_list(isl_ast_op_min, list, build);
+       iterator = isl_ast_expr_copy(graft->node->u.f.iterator);
+       cond = isl_ast_expr_alloc_binary(isl_ast_op_le, iterator, bound);
+       graft->node->u.f.cond = cond;
+
+       if (!graft->node->u.f.cond)
+               return isl_ast_graft_free(graft);
+       return graft;
+}
+
+/* Set the condition part of the for node graft->node in case
+ * the upper bound is represented as a set.
+ */
+static __isl_give isl_ast_graft *set_for_cond_from_set(
+       __isl_take isl_ast_graft *graft, __isl_keep isl_set *set,
+       __isl_keep isl_ast_build *build)
+{
+       isl_ast_expr *cond;
+
+       if (!graft)
+               return NULL;
+
+       cond = isl_ast_build_expr_from_set(build, isl_set_copy(set));
+       graft->node->u.f.cond = cond;
+       if (!graft->node->u.f.cond)
+               return isl_ast_graft_free(graft);
+       return graft;
+}
+
+/* Construct an isl_ast_expr for the increment (i.e., stride) of
+ * the current dimension.
+ */
+static __isl_give isl_ast_expr *for_inc(__isl_keep isl_ast_build *build)
+{
+       int depth;
+       isl_int v;
+       isl_ctx *ctx;
+       isl_ast_expr *inc;
+
+       ctx = isl_ast_build_get_ctx(build);
+       depth = isl_ast_build_get_depth(build);
+
+       if (!isl_ast_build_has_stride(build, depth))
+               return isl_ast_expr_alloc_int_si(ctx, 1);
+
+       isl_int_init(v);
+       isl_ast_build_get_stride(build, depth, &v);
+       inc = isl_ast_expr_alloc_int(ctx, v);
+       isl_int_clear(v);
+
+       return inc;
+}
+
+/* Should we express the loop condition as
+ *
+ *     iterator <= min(list of upper bounds)
+ *
+ * or as a conjunction of constraints?
+ *
+ * The first is constructed from a list of upper bounds.
+ * The second is constructed from a set.
+ *
+ * If there are no upper bounds in "constraints", then this could mean
+ * that "domain" simply doesn't have an upper bound or that we didn't
+ * pick any upper bound.  In the first case, we want to generate the
+ * loop condition as a(n empty) conjunction of constraints
+ * In the second case, we will compute
+ * a single upper bound from "domain" and so we use the list form.
+ *
+ * If there are upper bounds in "constraints",
+ * then we use the list form iff the atomic_upper_bound option is set.
+ */
+static int use_upper_bound_list(isl_ctx *ctx, int n_upper,
+       __isl_keep isl_set *domain, int depth)
+{
+       if (n_upper > 0)
+               return isl_options_get_ast_build_atomic_upper_bound(ctx);
+       else
+               return isl_set_dim_has_upper_bound(domain, isl_dim_set, depth);
+}
+
+/* Fill in the expressions of the for node in graft->node.
+ *
+ * In particular,
+ * - set the initialization part of the loop to the maximum of the lower bounds
+ * - set the size of the iterator based on the values attained by the iterator
+ * - extract the increment from the stride of the current dimension
+ * - construct the for condition either based on a list of upper bounds
+ *     or on a set of upper bound constraints.
+ */
+static __isl_give isl_ast_graft *set_for_node_expressions(
+       __isl_take isl_ast_graft *graft, __isl_keep isl_pw_aff_list *lower,
+       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;
+
+       if (!graft)
+               return NULL;
+
+       build = isl_ast_build_copy(build);
+       build = isl_ast_build_set_enforced(build,
+                                       isl_ast_graft_get_enforced(graft));
+
+       node = graft->node;
+       node->u.f.init = reduce_list(isl_ast_op_max, lower, build);
+       node->u.f.inc = for_inc(build);
+
+       if (use_list)
+               graft = set_for_cond_from_list(graft, upper_list, build);
+       else
+               graft = set_for_cond_from_set(graft, upper_set, build);
+
+       isl_ast_build_free(build);
+
+       if (!node->u.f.iterator || !node->u.f.init ||
+           !node->u.f.cond || !node->u.f.inc)
+               return isl_ast_graft_free(graft);
+
+       return graft;
+}
+
+/* Update "graft" based on "bounds" and "domain" for the generic,
+ * non-degenerate, case.
+ *
+ * "constraints" contains the "n_lower" lower and "n_upper" upper bounds
+ * that the loop node should express.
+ * "domain" is the subset of the intersection of the constraints
+ * for which some code is executed.
+ *
+ * There may be zero lower bounds or zero upper bounds in "constraints"
+ * in case the list of constraints was created
+ * based on the atomic option or based on separation with explicit bounds.
+ * In that case, we use "domain" to derive lower and/or upper bounds.
+ *
+ * We first compute a list of one or more lower bounds.
+ *
+ * Then we decide if we want to express the condition as
+ *
+ *     iterator <= min(list of upper bounds)
+ *
+ * or as a conjunction of constraints.
+ *
+ * The set of enforced constraints is then computed either based on
+ * a list of upper bounds or on a set of upper bound constraints.
+ * We do not compute any enforced constraints if we were forced
+ * to compute a lower or upper bound using exact_bound.  The domains
+ * of the resulting expressions may imply some bounds on outer dimensions
+ * that we do not want to appear in the enforced constraints since
+ * they are not actually enforced by the corresponding code.
+ *
+ * Finally, we fill in the expressions of the for node.
+ */
+static __isl_give isl_ast_graft *refine_generic_bounds(
+       __isl_take isl_ast_graft *graft,
+       __isl_keep isl_constraint **constraint, int n_lower, int n_upper,
+       __isl_keep isl_set *domain, __isl_keep isl_ast_build *build)
+{
+       int depth;
+       isl_ctx *ctx;
+       isl_pw_aff_list *lower;
+       int use_list;
+       isl_set *upper_set = NULL;
+       isl_pw_aff_list *upper_list = NULL;
+
+       if (!graft || !build)
+               return isl_ast_graft_free(graft);
+
+       depth = isl_ast_build_get_depth(build);
+       ctx = isl_ast_graft_get_ctx(graft);
+
+       use_list = use_upper_bound_list(ctx, n_upper, domain, depth);
+
+       lower = lower_bounds(constraint, n_lower, depth, domain, build);
+
+       if (use_list)
+               upper_list = upper_bounds(constraint + n_lower, n_upper, depth,
+                                           domain, build);
+       else if (n_upper > 0)
+               upper_set = intersect_constraints(ctx, constraint + n_lower,
+                                                       n_upper);
+       else
+               upper_set = isl_set_universe(isl_set_get_space(domain));
+
+       if (n_lower == 0 || n_upper == 0)
+               ;
+       else if (use_list)
+               graft = set_enforced_from_list(graft, lower, upper_list);
+       else
+               graft = set_enforced_from_set(graft, lower, depth, upper_set);
+
+       graft = set_for_node_expressions(graft, lower, use_list, upper_list,
+                                       upper_set, build);
+
+       isl_pw_aff_list_free(lower);
+       isl_pw_aff_list_free(upper_list);
+       isl_set_free(upper_set);
+
+       return graft;
+}
+
+/* How many constraints in the "constraint" array, starting at position "first"
+ * are of the give type?  "n" represents the total number of elements
+ * in the array.
+ */
+static int count_constraints(isl_constraint **constraint, int n, int first,
+       int pos, int type)
+{
+       int i;
+
+       constraint += first;
+
+       for (i = 0; first + i < n; i++)
+               if (constraint_type(constraint[i], pos) != type)
+                       break;
+
+       return i;
+}
+
+/* Update "graft" based on "bounds" and "domain" for the generic,
+ * non-degenerate, case.
+ *
+ * "list" respresent the list of bounds that need to be encoded by
+ * the for loop (or a guard around the for loop).
+ * "domain" is the subset of the intersection of the constraints
+ * for which some code is executed.
+ * "build" is the build in which graft->node was created.
+ *
+ * We separate lower bounds, upper bounds and constraints that
+ * are independent of the loop iterator.
+ *
+ * The actual for loop bounds are generated in refine_generic_bounds.
+ * If there are any constraints that are independent of the loop iterator,
+ * we need to put a guard around the for loop (which may get hoisted up
+ * to higher levels) and we call refine_generic_bounds in a build
+ * where this guard is enforced.
+ */
+static __isl_give isl_ast_graft *refine_generic_split(
+       __isl_take isl_ast_graft *graft, __isl_keep isl_constraint_list *list,
+       __isl_keep isl_set *domain, __isl_keep isl_ast_build *build)
+{
+       isl_ctx *ctx;
+       isl_ast_build *for_build;
+       isl_set *guard;
+       int n_indep, n_lower, n_upper;
+       int pos;
+       int n;
+
+       if (!list)
+               return isl_ast_graft_free(graft);
+
+       pos = isl_ast_build_get_depth(build);
+
+       if (isl_sort(list->p, list->n, sizeof(isl_constraint *),
+                       &cmp_constraint, &pos) < 0)
+               return isl_ast_graft_free(graft);
+
+       n = list->n;
+       n_indep = count_constraints(list->p, n, 0, pos, 0);
+       n_lower = count_constraints(list->p, n, n_indep, pos, 1);
+       n_upper = count_constraints(list->p, n, n_indep + n_lower, pos, 2);
+
+       if (n_indep == 0)
+               return refine_generic_bounds(graft,
+                    list->p + n_indep, n_lower, n_upper, domain, build);
+
+       ctx = isl_ast_graft_get_ctx(graft);
+       guard = intersect_constraints(ctx, list->p, n_indep);
+
+       for_build = isl_ast_build_copy(build);
+       for_build = isl_ast_build_restrict_pending(for_build,
+                                               isl_set_copy(guard));
+       graft = refine_generic_bounds(graft,
+                    list->p + n_indep, n_lower, n_upper, domain, for_build);
+       isl_ast_build_free(for_build);
+
+       graft = isl_ast_graft_add_guard(graft, guard, build);
+
+       return graft;
+}
+
+/* Update "graft" based on "bounds" and "domain" for the generic,
+ * non-degenerate, case.
+ *
+ * "bounds" respresent the bounds that need to be encoded by
+ * the for loop (or a guard around the for loop).
+ * "domain" is the subset of "bounds" for which some code is executed.
+ * "build" is the build in which graft->node was created.
+ *
+ * We break up "bounds" into a list of constraints and continue with
+ * refine_generic_split.
+ */
+static __isl_give isl_ast_graft *refine_generic(
+       __isl_take isl_ast_graft *graft,
+       __isl_keep isl_basic_set *bounds, __isl_keep isl_set *domain,
+       __isl_keep isl_ast_build *build)
+{
+       isl_constraint_list *list;
+
+       if (!build || !graft)
+               return isl_ast_graft_free(graft);
+
+       bounds = isl_basic_set_copy(bounds);
+       bounds = isl_ast_build_compute_gist_basic_set(build, bounds);
+       list = isl_constraint_list_from_basic_set(bounds);
+
+       graft = refine_generic_split(graft, list, domain, build);
+
+       isl_constraint_list_free(list);
+       return graft;
+}
+
+/* Create a for node for the current level.
+ *
+ * Mark the for node degenerate if "degenerate" is set.
+ */
+static __isl_give isl_ast_node *create_for(__isl_keep isl_ast_build *build,
+       int degenerate)
+{
+       int depth;
+       isl_id *id;
+       isl_ast_node *node;
+
+       if (!build)
+               return NULL;
+
+       depth = isl_ast_build_get_depth(build);
+       id = isl_ast_build_get_iterator_id(build, depth);
+       node = isl_ast_node_alloc_for(id);
+       if (degenerate)
+               node = isl_ast_node_for_mark_degenerate(node);
+
+       return node;
+}
+
+/* Create an AST node for the current dimension based on
+ * the schedule domain "bounds" and return the node encapsulated
+ * in an isl_ast_graft.
+ *
+ * "executed" is the current inverse schedule, taking into account
+ * the bounds in "bounds"
+ * "domain" is the domain of "executed", with inner dimensions projected out.
+ * It may be a strict subset of "bounds" in case "bounds" was created
+ * based on the atomic option or based on separation with explicit bounds.
+ *
+ * "domain" may satisfy additional equalities that result
+ * from intersecting "executed" with "bounds" in add_node.
+ * It may also satisfy some global constraints that were dropped out because
+ * we performed separation with explicit bounds.
+ * The very first step is then to copy these constraints to "bounds".
+ *
+ * We consider three builds,
+ * "build" is the one in which the current level is created,
+ * "body_build" is the build in which the next level is created,
+ * "sub_build" is essentially the same as "body_build", except that
+ * the depth has not been increased yet.
+ *
+ * "build" already contains information (in strides and offsets)
+ * about the strides at the current level, but this information is not
+ * reflected in the build->domain.
+ * We first add this information and the "bounds" to the sub_build->domain.
+ * isl_ast_build_set_loop_bounds checks whether the current dimension attains
+ * only a single value and whether this single value can be represented using
+ * a single affine expression.
+ * In the first case, the current level is considered "degenerate".
+ * In the second, sub-case, the current level is considered "eliminated".
+ * Eliminated level don't need to be reflected in the AST since we can
+ * simply plug in the affine expression.  For degenerate, but non-eliminated,
+ * levels, we do introduce a for node, but mark is as degenerate so that
+ * it can be printed as an assignment of the single value to the loop
+ * "iterator".
+ *
+ * If the current level is eliminated, we eliminate the current dimension
+ * from the inverse schedule to make sure no inner dimensions depend
+ * on the current dimension.  Otherwise, we create a for node, marking
+ * it degenerate if appropriate.  The initial for node is still incomplete
+ * and will be completed in either refine_degenerate or refine_generic.
+ *
+ * We then generate a sequence of grafts for the next level,
+ * create a surrounding graft for the current level and insert
+ * the for node we created (if the current level is not eliminated).
+ *
+ * Finally, we set the bounds of the for loop and insert guards
+ * (either in the AST or in the graft) in one of
+ * refine_eliminated, refine_degenerate or refine_generic.
+ */
+static __isl_give isl_ast_graft *create_node_scaled(
+       __isl_take isl_union_map *executed,
+       __isl_take isl_basic_set *bounds, __isl_take isl_set *domain,
+       __isl_take isl_ast_build *build)
+{
+       int depth;
+       int degenerate, eliminated;
+       isl_basic_set *hull;
+       isl_ast_node *node = NULL;
+       isl_ast_graft *graft;
+       isl_ast_graft_list *children;
+       isl_ast_build *sub_build;
+       isl_ast_build *body_build;
+
+       domain = isl_ast_build_eliminate_divs(build, domain);
+       domain = isl_set_detect_equalities(domain);
+       hull = isl_set_unshifted_simple_hull(isl_set_copy(domain));
+       bounds = isl_basic_set_intersect(bounds, hull);
+
+       depth = isl_ast_build_get_depth(build);
+       sub_build = isl_ast_build_copy(build);
+       sub_build = isl_ast_build_include_stride(sub_build);
+       sub_build = isl_ast_build_set_loop_bounds(sub_build,
+                                               isl_basic_set_copy(bounds));
+       degenerate = isl_ast_build_has_value(sub_build);
+       eliminated = isl_ast_build_has_affine_value(sub_build, depth);
+       if (degenerate < 0 || eliminated < 0)
+               executed = isl_union_map_free(executed);
+       if (eliminated)
+               executed = eliminate(executed, depth, build);
+       else
+               node = create_for(build, degenerate);
+
+       body_build = isl_ast_build_copy(sub_build);
+       body_build = isl_ast_build_increase_depth(body_build);
+       children = generate_next_level(executed,
+                                   isl_ast_build_copy(body_build));
+
+       graft = isl_ast_graft_alloc_level(children, sub_build);
+       if (!eliminated)
+               graft = isl_ast_graft_insert_for(graft, node);
+       if (eliminated)
+               graft = refine_eliminated(graft, bounds, build);
+       else if (degenerate)
+               graft = refine_degenerate(graft, bounds, build, sub_build);
+       else
+               graft = refine_generic(graft, bounds, domain, build);
+
+       isl_ast_build_free(body_build);
+       isl_ast_build_free(sub_build);
+       isl_ast_build_free(build);
+       isl_basic_set_free(bounds);
+       isl_set_free(domain);
+
+       return graft;
+}
+
+/* Internal data structure for checking if all constraints involving
+ * the input dimension "depth" are such that the other coefficients
+ * are multiples of "m", reducing "m" if they are not.
+ * If "m" is reduced all the way down to "1", then the check has failed
+ * and we break out of the iteration.
+ * "d" is an initialized isl_int that can be used internally.
+ */
+struct isl_check_scaled_data {
+       int depth;
+       isl_int m, d;
+};
+
+/* If constraint "c" involves the input dimension data->depth,
+ * then make sure that all the other coefficients are multiples of data->m,
+ * reducing data->m if needed.
+ * Break out of the iteration if data->m has become equal to "1".
+ */
+static int constraint_check_scaled(__isl_take isl_constraint *c, void *user)
+{
+       struct isl_check_scaled_data *data = user;
+       int i, j, n;
+       enum isl_dim_type t[] = { isl_dim_param, isl_dim_in, isl_dim_out,
+                                   isl_dim_div };
+
+       if (!isl_constraint_involves_dims(c, isl_dim_in, data->depth, 1)) {
+               isl_constraint_free(c);
+               return 0;
+       }
+
+       for (i = 0; i < 4; ++i) {
+               n = isl_constraint_dim(c, t[i]);
+               for (j = 0; j < n; ++j) {
+                       if (t[i] == isl_dim_in && j == data->depth)
+                               continue;
+                       if (!isl_constraint_involves_dims(c, t[i], j, 1))
+                               continue;
+                       isl_constraint_get_coefficient(c, t[i], j, &data->d);
+                       isl_int_gcd(data->m, data->m, data->d);
+                       if (isl_int_is_one(data->m))
+                               break;
+               }
+               if (j < n)
+                       break;
+       }
+
+       isl_constraint_free(c);
+
+       return i < 4 ? -1 : 0;
+}
+
+/* For each constraint of "bmap" that involves the input dimension data->depth,
+ * make sure that all the other coefficients are multiples of data->m,
+ * reducing data->m if needed.
+ * Break out of the iteration if data->m has become equal to "1".
+ */
+static int basic_map_check_scaled(__isl_take isl_basic_map *bmap, void *user)
+{
+       int r;
+
+       r = isl_basic_map_foreach_constraint(bmap,
+                                               &constraint_check_scaled, user);
+       isl_basic_map_free(bmap);
+
+       return r;
+}
+
+/* For each constraint of "map" that involves the input dimension data->depth,
+ * make sure that all the other coefficients are multiples of data->m,
+ * reducing data->m if needed.
+ * Break out of the iteration if data->m has become equal to "1".
+ */
+static int map_check_scaled(__isl_take isl_map *map, void *user)
+{
+       int r;
+
+       r = isl_map_foreach_basic_map(map, &basic_map_check_scaled, user);
+       isl_map_free(map);
+
+       return r;
+}
+
+/* Create an AST node for the current dimension based on
+ * the schedule domain "bounds" and return the node encapsulated
+ * in an isl_ast_graft.
+ *
+ * "executed" is the current inverse schedule, taking into account
+ * the bounds in "bounds"
+ * "domain" is the domain of "executed", with inner dimensions projected out.
+ *
+ *
+ * Before moving on to the actual AST node construction in create_node_scaled,
+ * we first check if the current dimension is strided and if we can scale
+ * down this stride.  Note that we only do this if the ast_build_scale_strides
+ * option is set.
+ *
+ * In particular, let the current dimension take on values
+ *
+ *     f + s a
+ *
+ * with a an integer.  We check if we can find an integer m that (obviouly)
+ * divides both f and s.
+ *
+ * If so, we check if the current dimension only appears in constraints
+ * where the coefficients of the other variables are multiples of m.
+ * We perform this extra check to avoid the risk of introducing
+ * divisions by scaling down the current dimension.
+ *
+ * If so, we scale the current dimension down by a factor of m.
+ * That is, we plug in
+ *
+ *     i = m i'                                                        (1)
+ *
+ * Note that in principle we could always scale down strided loops
+ * by plugging in
+ *
+ *     i = f + s i'
+ *
+ * but this may result in i' taking on larger values than the original i,
+ * due to the shift by "f".
+ * By constrast, the scaling in (1) can only reduce the (absolute) value "i".
+ */
+static __isl_give isl_ast_graft *create_node(__isl_take isl_union_map *executed,
+       __isl_take isl_basic_set *bounds, __isl_take isl_set *domain,
+       __isl_take isl_ast_build *build)
+{
+       struct isl_check_scaled_data data;
+       isl_ctx *ctx;
+       isl_aff *offset;
+
+       ctx = isl_ast_build_get_ctx(build);
+       if (!isl_options_get_ast_build_scale_strides(ctx))
+               return create_node_scaled(executed, bounds, domain, build);
+
+       data.depth = isl_ast_build_get_depth(build);
+       if (!isl_ast_build_has_stride(build, data.depth))
+               return create_node_scaled(executed, bounds, domain, build);
+
+       isl_int_init(data.m);
+       isl_int_init(data.d);
+
+       offset = isl_ast_build_get_offset(build, data.depth);
+       if (isl_ast_build_get_stride(build, data.depth, &data.m) < 0)
+               offset = isl_aff_free(offset);
+       offset = isl_aff_scale_down(offset, data.m);
+       if (isl_aff_get_denominator(offset, &data.d) < 0)
+               executed = isl_union_map_free(executed);
+
+       if (isl_int_is_divisible_by(data.m, data.d))
+               isl_int_divexact(data.m, data.m, data.d);
+       else
+               isl_int_set_si(data.m, 1);
+
+       if (!isl_int_is_one(data.m)) {
+               if (isl_union_map_foreach_map(executed, &map_check_scaled,
+                                               &data) < 0 &&
+                   !isl_int_is_one(data.m))
+                       executed = isl_union_map_free(executed);
+       }
+
+       if (!isl_int_is_one(data.m)) {
+               isl_space *space;
+               isl_multi_aff *ma;
+               isl_aff *aff;
+               isl_map *map;
+               isl_union_map *umap;
+
+               space = isl_ast_build_get_space(build, 1);
+               space = isl_space_map_from_set(space);
+               ma = isl_multi_aff_identity(space);
+               aff = isl_multi_aff_get_aff(ma, data.depth);
+               aff = isl_aff_scale(aff, data.m);
+               ma = isl_multi_aff_set_aff(ma, data.depth, aff);
+
+               bounds = isl_basic_set_preimage_multi_aff(bounds,
+                                               isl_multi_aff_copy(ma));
+               domain = isl_set_preimage_multi_aff(domain,
+                                               isl_multi_aff_copy(ma));
+               map = isl_map_reverse(isl_map_from_multi_aff(ma));
+               umap = isl_union_map_from_map(map);
+               executed = isl_union_map_apply_domain(executed,
+                                               isl_union_map_copy(umap));
+               build = isl_ast_build_scale_down(build, data.m, umap);
+       }
+       isl_aff_free(offset);
+
+       isl_int_clear(data.d);
+       isl_int_clear(data.m);
+
+       return create_node_scaled(executed, bounds, domain, build);
+}
+
+/* Add the basic set to the list that "user" points to.
+ */
+static int collect_basic_set(__isl_take isl_basic_set *bset, void *user)
+{
+       isl_basic_set_list **list = user;
+
+       *list = isl_basic_set_list_add(*list, bset);
+
+       return 0;
+}
+
+/* Extract the basic sets of "set" and collect them in an isl_basic_set_list.
+ */
+static __isl_give isl_basic_set_list *isl_basic_set_list_from_set(
+       __isl_take isl_set *set)
+{
+       int n;
+       isl_ctx *ctx;
+       isl_basic_set_list *list;
+
+       if (!set)
+               return NULL;
+
+       ctx = isl_set_get_ctx(set);
+
+       n = isl_set_n_basic_set(set);
+       list = isl_basic_set_list_alloc(ctx, n);
+       if (isl_set_foreach_basic_set(set, &collect_basic_set, &list) < 0)
+               list = isl_basic_set_list_free(list);
+
+       isl_set_free(set);
+       return list;
+}
+
+/* Generate code for the schedule domain "bounds"
+ * and add the result to "list".
+ *
+ * We mainly detect strides and additional equalities here
+ * and then pass over control to create_node.
+ *
+ * "bounds" reflects the bounds on the current dimension and possibly
+ * some extra conditions on outer dimensions.
+ * It does not, however, include any divs involving the current dimension,
+ * so it does not capture any stride constraints.
+ * We therefore need to compute that part of the schedule domain that
+ * intersects with "bounds" and derive the strides from the result.
+ */
+static __isl_give isl_ast_graft_list *add_node(
+       __isl_take isl_ast_graft_list *list, __isl_take isl_union_map *executed,
+       __isl_take isl_basic_set *bounds, __isl_take isl_ast_build *build)
+{
+       isl_ast_graft *graft;
+       isl_set *domain = NULL;
+       isl_union_set *uset;
+       int empty;
+
+       uset = isl_union_set_from_basic_set(isl_basic_set_copy(bounds));
+       executed = isl_union_map_intersect_domain(executed, uset);
+       empty = isl_union_map_is_empty(executed);
+       if (empty < 0)
+               goto error;
+       if (empty)
+               goto done;
+
+       uset = isl_union_map_domain(isl_union_map_copy(executed));
+       domain = isl_set_from_union_set(uset);
+       domain = isl_ast_build_compute_gist(build, domain);
+       empty = isl_set_is_empty(domain);
+       if (empty < 0)
+               goto error;
+       if (empty)
+               goto done;
+
+       domain = isl_ast_build_eliminate_inner(build, domain);
+       build = isl_ast_build_detect_strides(build, isl_set_copy(domain));
+
+       graft = create_node(executed, bounds, domain,
+                               isl_ast_build_copy(build));
+       list = isl_ast_graft_list_add(list, graft);
+       isl_ast_build_free(build);
+       return list;
+error:
+       list = isl_ast_graft_list_free(list);
+done:
+       isl_set_free(domain);
+       isl_basic_set_free(bounds);
+       isl_union_map_free(executed);
+       isl_ast_build_free(build);
+       return list;
+}
+
+struct isl_domain_follows_at_depth_data {
+       int depth;
+       isl_basic_set **piece;
+};
+
+/* Does any element of i follow or coincide with any element of j
+ * at the current depth (data->depth) for equal values of the outer
+ * dimensions?
+ */
+static int domain_follows_at_depth(int i, int j, void *user)
+{
+       struct isl_domain_follows_at_depth_data *data = user;
+       isl_basic_map *test;
+       int empty;
+       int l;
+
+       test = isl_basic_map_from_domain_and_range(
+                       isl_basic_set_copy(data->piece[i]),
+                       isl_basic_set_copy(data->piece[j]));
+       for (l = 0; l < data->depth; ++l)
+               test = isl_basic_map_equate(test, isl_dim_in, l,
+                                               isl_dim_out, l);
+       test = isl_basic_map_order_ge(test, isl_dim_in, data->depth,
+                                       isl_dim_out, data->depth);
+       empty = isl_basic_map_is_empty(test);
+       isl_basic_map_free(test);
+
+       return empty < 0 ? -1 : !empty;
+}
+
+static __isl_give isl_ast_graft_list *generate_sorted_domains(
+       __isl_keep isl_basic_set_list *domain_list,
+       __isl_keep isl_union_map *executed,
+       __isl_keep isl_ast_build *build);
+
+/* Generate code for the "n" schedule domains in "domain_list"
+ * with positions specified by the entries of the "pos" array
+ * and add the results to "list".
+ *
+ * The "n" domains form a strongly connected component in the ordering.
+ * If n is larger than 1, then this means that we cannot determine a valid
+ * ordering for the n domains in the component.  This should be fairly
+ * rare because the individual domains have been made disjoint first.
+ * The problem is that the domains may be integrally disjoint but not
+ * rationally disjoint.  For example, we may have domains
+ *
+ *     { [i,i] : 0 <= i <= 1 }         and     { [i,1-i] : 0 <= i <= 1 }
+ *
+ * These two domains have an empty intersection, but their rational
+ * relaxations do intersect.  It is impossible to order these domains
+ * in the second dimension because the first should be ordered before
+ * the second for outer dimension equal to 0, while it should be ordered
+ * after for outer dimension equal to 1.
+ *
+ * This may happen in particular in case of unrolling since the domain
+ * of each slice is replaced by its simple hull.
+ *
+ * We collect the basic sets in the component, call isl_set_make_disjoint
+ * and try again.  Note that we rely here on isl_set_make_disjoint also
+ * making the basic sets rationally disjoint.  If the basic sets
+ * are rationally disjoint, then the ordering problem does not occur.
+ * To see this, there can only be a problem if there are points
+ * (i,a) and (j,b) in one set and (i,c) and (j,d) in the other with
+ * a < c and b > d.  This means that either the interval spanned
+ * by a en b lies inside that spanned by c and or the other way around.
+ * In either case, there is a point inside both intervals with the
+ * convex combination in terms of a and b and in terms of c and d.
+ * Taking the same combination of i and j gives a point in the intersection.
+ */
+static __isl_give isl_ast_graft_list *add_nodes(
+       __isl_take isl_ast_graft_list *list, int *pos, int n,
+       __isl_keep isl_basic_set_list *domain_list,
+       __isl_keep isl_union_map *executed,
+       __isl_keep isl_ast_build *build)
+{
+       int i;
+       isl_basic_set *bset;
+       isl_set *set;
+
+       bset = isl_basic_set_list_get_basic_set(domain_list, pos[0]);
+       if (n == 1)
+               return add_node(list, isl_union_map_copy(executed), bset,
+                               isl_ast_build_copy(build));
+
+       set = isl_set_from_basic_set(bset);
+       for (i = 1; i < n; ++i) {
+               bset = isl_basic_set_list_get_basic_set(domain_list, pos[i]);
+               set = isl_set_union(set, isl_set_from_basic_set(bset));
+       }
+
+       set = isl_set_make_disjoint(set);
+       if (isl_set_n_basic_set(set) == n)
+               isl_die(isl_ast_graft_list_get_ctx(list), isl_error_internal,
+                       "unable to separate loop parts", goto error);
+       domain_list = isl_basic_set_list_from_set(set);
+       list = isl_ast_graft_list_concat(list,
+                   generate_sorted_domains(domain_list, executed, build));
+       isl_basic_set_list_free(domain_list);
+
+       return list;
+error:
+       isl_set_free(set);
+       return isl_ast_graft_list_free(list);
+}
+
+/* Sort the domains in "domain_list" according to the execution order
+ * at the current depth (for equal values of the outer dimensions),
+ * generate code for each of them, collecting the results in a list.
+ * If no code is generated (because the intersection of the inverse schedule
+ * with the domains turns out to be empty), then an empty list is returned.
+ *
+ * The caller is responsible for ensuring that the basic sets in "domain_list"
+ * are pair-wise disjoint.  It can, however, in principle happen that
+ * two basic sets should be ordered one way for one value of the outer
+ * dimensions and the other way for some other value of the outer dimensions.
+ * We therefore play safe and look for strongly connected components.
+ * The function add_nodes takes care of handling non-trivial components.
+ */
+static __isl_give isl_ast_graft_list *generate_sorted_domains(
+       __isl_keep isl_basic_set_list *domain_list,
+       __isl_keep isl_union_map *executed, __isl_keep isl_ast_build *build)
+{
+       isl_ctx *ctx;
+       isl_ast_graft_list *list;
+       struct isl_domain_follows_at_depth_data data;
+       struct isl_tarjan_graph *g;
+       int i, n;
+
+       if (!domain_list)
+               return NULL;
+
+       ctx = isl_basic_set_list_get_ctx(domain_list);
+       n = isl_basic_set_list_n_basic_set(domain_list);
+       list = isl_ast_graft_list_alloc(ctx, n);
+       if (n == 0)
+               return list;
+       if (n == 1)
+               return add_node(list, isl_union_map_copy(executed),
+                       isl_basic_set_list_get_basic_set(domain_list, 0),
+                       isl_ast_build_copy(build));
+
+       data.depth = isl_ast_build_get_depth(build);
+       data.piece = domain_list->p;
+       g = isl_tarjan_graph_init(ctx, n, &domain_follows_at_depth, &data);
+
+       i = 0;
+       while (list && n) {
+               int first;
+
+               if (g->order[i] == -1)
+                       isl_die(ctx, isl_error_internal, "cannot happen",
+                               goto error);
+               first = i;
+               while (g->order[i] != -1) {
+                       ++i; --n;
+               }
+               list = add_nodes(list, g->order + first, i - first,
+                                       domain_list, executed, build);
+               ++i;
+       }
+
+       if (0)
+error:         list = isl_ast_graft_list_free(list);
+       isl_tarjan_graph_free(g);
+
+       return list;
+}
+
+struct isl_shared_outer_data {
+       int depth;
+       isl_basic_set **piece;
+};
+
+/* Do elements i and j share any values for the outer dimensions?
+ */
+static int shared_outer(int i, int j, void *user)
+{
+       struct isl_shared_outer_data *data = user;
+       isl_basic_map *test;
+       int empty;
+       int l;
+
+       test = isl_basic_map_from_domain_and_range(
+                       isl_basic_set_copy(data->piece[i]),
+                       isl_basic_set_copy(data->piece[j]));
+       for (l = 0; l < data->depth; ++l)
+               test = isl_basic_map_equate(test, isl_dim_in, l,
+                                               isl_dim_out, l);
+       empty = isl_basic_map_is_empty(test);
+       isl_basic_map_free(test);
+
+       return empty < 0 ? -1 : !empty;
+}
+
+/* Call generate_sorted_domains on a list containing the elements
+ * of "domain_list indexed by the first "n" elements of "pos".
+ */
+static __isl_give isl_ast_graft_list *generate_sorted_domains_part(
+       __isl_keep isl_basic_set_list *domain_list, int *pos, int n,
+       __isl_keep isl_union_map *executed,
+       __isl_keep isl_ast_build *build)
+{
+       int i;
+       isl_ctx *ctx;
+       isl_basic_set_list *slice;
+       isl_ast_graft_list *list;
+
+       ctx = isl_ast_build_get_ctx(build);
+       slice = isl_basic_set_list_alloc(ctx, n);
+       for (i = 0; i < n; ++i) {
+               isl_basic_set *bset;
+
+               bset = isl_basic_set_copy(domain_list->p[pos[i]]);
+               slice = isl_basic_set_list_add(slice, bset);
+       }
+
+       list = generate_sorted_domains(slice, executed, build);
+       isl_basic_set_list_free(slice);
+
+       return list;
+}
+
+/* Look for any (weakly connected) components in the "domain_list"
+ * of domains that share some values of the outer dimensions.
+ * That is, domains in different components do not share any values
+ * of the outer dimensions.  This means that these components
+ * can be freely reorderd.
+ * Within each of the components, we sort the domains according
+ * to the execution order at the current depth.
+ *
+ * We fuse the result of each call to generate_sorted_domains_part
+ * into a list with either zero or one graft and collect these (at most)
+ * single element lists into a bigger list. This means that the elements of the
+ * final list can be freely reordered.  In particular, we sort them
+ * according to an arbitrary but fixed ordering to ease merging of
+ * graft lists from different components.
+ */
+static __isl_give isl_ast_graft_list *generate_parallel_domains(
+       __isl_keep isl_basic_set_list *domain_list,
+       __isl_keep isl_union_map *executed, __isl_keep isl_ast_build *build)
+{
+       int i, n;
+       isl_ctx *ctx;
+       isl_ast_graft_list *list;
+       struct isl_shared_outer_data data;
+       struct isl_tarjan_graph *g;
+
+       if (!domain_list)
+               return NULL;
+
+       n = isl_basic_set_list_n_basic_set(domain_list);
+       if (n <= 1)
+               return generate_sorted_domains(domain_list, executed, build);
+
+       ctx = isl_basic_set_list_get_ctx(domain_list);
+
+       data.depth = isl_ast_build_get_depth(build);
+       data.piece = domain_list->p;
+       g = isl_tarjan_graph_init(ctx, n, &shared_outer, &data);
+       if (!g)
+               return NULL;
+
+       i = 0;
+       do {
+               int first;
+               isl_ast_graft_list *list_c;
+
+               if (g->order[i] == -1)
+                       isl_die(ctx, isl_error_internal, "cannot happen",
+                               break);
+               first = i;
+               while (g->order[i] != -1) {
+                       ++i; --n;
+               }
+               if (first == 0 && n == 0) {
+                       isl_tarjan_graph_free(g);
+                       return generate_sorted_domains(domain_list,
+                                                       executed, build);
+               }
+               list_c = generate_sorted_domains_part(domain_list,
+                               g->order + first, i - first, executed, build);
+               list_c = isl_ast_graft_list_fuse(list_c, build);
+               if (first == 0)
+                       list = list_c;
+               else
+                       list = isl_ast_graft_list_concat(list, list_c);
+               ++i;
+       } while (list && n);
+
+       if (n > 0)
+               list = isl_ast_graft_list_free(list);
+
+       list = isl_ast_graft_list_sort(list);
+
+       isl_tarjan_graph_free(g);
+
+       return list;
+}
+
+/* Internal data for separate_domain.
+ *
+ * "explicit" is set if we only want to use explicit bounds.
+ *
+ * "domain" collects the separated domains.
+ */
+struct isl_separate_domain_data {
+       isl_ast_build *build;
+       int explicit;
+       isl_set *domain;
+};
+
+/* Extract implicit bounds on the current dimension for the executed "map".
+ *
+ * The domain of "map" may involve inner dimensions, so we
+ * need to eliminate them.
+ */
+static __isl_give isl_set *implicit_bounds(__isl_take isl_map *map,
+       __isl_keep isl_ast_build *build)
+{
+       isl_set *domain;
+
+       domain = isl_map_domain(map);
+       domain = isl_ast_build_eliminate(build, domain);
+
+       return domain;
+}
+
+/* Extract explicit bounds on the current dimension for the executed "map".
+ *
+ * Rather than eliminating the inner dimensions as in implicit_bounds,
+ * we simply drop any constraints involving those inner dimensions.
+ * The idea is that most bounds that are implied by constraints on the
+ * inner dimensions will be enforced by for loops and not by explicit guards.
+ * There is then no need to separate along those bounds.
+ */
+static __isl_give isl_set *explicit_bounds(__isl_take isl_map *map,
+       __isl_keep isl_ast_build *build)
+{
+       isl_set *domain;
+       int depth, dim;
+
+       dim = isl_map_dim(map, isl_dim_out);
+       map = isl_map_drop_constraints_involving_dims(map, isl_dim_out, 0, dim);
+
+       domain = isl_map_domain(map);
+       depth = isl_ast_build_get_depth(build);
+       dim = isl_set_dim(domain, isl_dim_set);
+       domain = isl_set_detect_equalities(domain);
+       domain = isl_set_drop_constraints_involving_dims(domain,
+                               isl_dim_set, depth + 1, dim - (depth + 1));
+       domain = isl_set_remove_divs_involving_dims(domain,
+                               isl_dim_set, depth, 1);
+       domain = isl_set_remove_unknown_divs(domain);
+
+       return domain;
+}
+
+/* Split data->domain into pieces that intersect with the range of "map"
+ * and pieces that do not intersect with the range of "map"
+ * and then add that part of the range of "map" that does not intersect
+ * with data->domain.
+ */
+static int separate_domain(__isl_take isl_map *map, void *user)
+{
+       struct isl_separate_domain_data *data = user;
+       isl_set *domain;
+       isl_set *d1, *d2;
+
+       if (data->explicit)
+               domain = explicit_bounds(map, data->build);
+       else
+               domain = implicit_bounds(map, data->build);
+
+       domain = isl_set_coalesce(domain);
+       domain = isl_set_make_disjoint(domain);
+       d1 = isl_set_subtract(isl_set_copy(domain), isl_set_copy(data->domain));
+       d2 = isl_set_subtract(isl_set_copy(data->domain), isl_set_copy(domain));
+       data->domain = isl_set_intersect(data->domain, domain);
+       data->domain = isl_set_union(data->domain, d1);
+       data->domain = isl_set_union(data->domain, d2);
+
+       return 0;
+}
+
+/* Separate the schedule domains of "executed".
+ *
+ * That is, break up the domain of "executed" into basic sets,
+ * such that for each basic set S, every element in S is associated with
+ * the same domain spaces.
+ *
+ * "space" is the (single) domain space of "executed".
+ */
+static __isl_give isl_set *separate_schedule_domains(
+       __isl_take isl_space *space, __isl_take isl_union_map *executed,
+       __isl_keep isl_ast_build *build)
+{
+       struct isl_separate_domain_data data = { build };
+       isl_ctx *ctx;
+
+       ctx = isl_ast_build_get_ctx(build);
+       data.explicit = isl_options_get_ast_build_separation_bounds(ctx) ==
+                                   ISL_AST_BUILD_SEPARATION_BOUNDS_EXPLICIT;
+       data.domain = isl_set_empty(space);
+       if (isl_union_map_foreach_map(executed, &separate_domain, &data) < 0)
+               data.domain = isl_set_free(data.domain);
+
+       isl_union_map_free(executed);
+       return data.domain;
+}
+
+/* Temporary data used during the search for a lower bound for unrolling.
+ *
+ * "domain" is the original set for which to find a lower bound
+ * "depth" is the dimension for which to find a lower boudn
+ *
+ * "lower" is the best lower bound found so far.  It is NULL if we have not
+ * found any yet.
+ * "n" is the corresponding size.  If lower is NULL, then the value of n
+ * is undefined.
+ *
+ * "tmp" is a temporary initialized isl_int.
+ */
+struct isl_find_unroll_data {
+       isl_set *domain;
+       int depth;
+
+       isl_aff *lower;
+       int *n;
+       isl_int tmp;
+};
+
+/* Check if we can use "c" as a lower bound and if it is better than
+ * any previously found lower bound.
+ *
+ * If "c" does not involve the dimension at the current depth,
+ * then we cannot use it.
+ * Otherwise, let "c" be of the form
+ *
+ *     i >= f(j)/a
+ *
+ * We compute the maximal value of
+ *
+ *     -ceil(f(j)/a)) + i + 1
+ *
+ * over the domain.  If there is such a value "n", then we know
+ *
+ *     -ceil(f(j)/a)) + i + 1 <= n
+ *
+ * or
+ *
+ *     i < ceil(f(j)/a)) + n
+ *
+ * meaning that we can use ceil(f(j)/a)) as a lower bound for unrolling.
+ * We just need to check if we have found any lower bound before and
+ * if the new lower bound is better (smaller n) than the previously found
+ * lower bounds.
+ */
+static int update_unrolling_lower_bound(struct isl_find_unroll_data *data,
+       __isl_keep isl_constraint *c)
+{
+       isl_aff *aff, *lower;
+       enum isl_lp_result res;
+
+       if (!isl_constraint_is_lower_bound(c, isl_dim_set, data->depth))
+               return 0;
+
+       lower = isl_constraint_get_bound(c, isl_dim_set, data->depth);
+       lower = isl_aff_ceil(lower);
+       aff = isl_aff_copy(lower);
+       aff = isl_aff_neg(aff);
+       aff = isl_aff_add_coefficient_si(aff, isl_dim_in, data->depth, 1);
+       aff = isl_aff_add_constant_si(aff, 1);
+       res = isl_set_max(data->domain, aff, &data->tmp);
+       isl_aff_free(aff);
+
+       if (res == isl_lp_error)
+               goto error;
+       if (res == isl_lp_unbounded) {
+               isl_aff_free(lower);
+               return 0;
+       }
+
+       if (!data->lower || isl_int_cmp_si(data->tmp, *data->n) < 0) {
+               isl_aff_free(data->lower);
+               data->lower = lower;
+               *data->n = isl_int_get_si(data->tmp);
+       } else
+               isl_aff_free(lower);
+
+       return 1;
+error:
+       isl_aff_free(lower);
+       return -1;
+}
+
+/* Check if we can use "c" as a lower bound and if it is better than
+ * any previously found lower bound.
+ */
+static int constraint_find_unroll(__isl_take isl_constraint *c, void *user)
+{
+       struct isl_find_unroll_data *data;
+       int r;
+
+       data = (struct isl_find_unroll_data *) user;
+       r = update_unrolling_lower_bound(data, c);
+       isl_constraint_free(c);
+
+       return r;
+}
+
+/* Look for a lower bound l(i) on the dimension at "depth"
+ * and a size n such that "domain" is a subset of
+ *
+ *     { [i] : l(i) <= i_d < l(i) + n }
+ *
+ * where d is "depth" and l(i) depends only on earlier dimensions.
+ * Furthermore, try and find a lower bound such that n is as small as possible.
+ * In particular, "n" needs to be finite.
+ *
+ * Inner dimensions have been eliminated from "domain" by the caller.
+ *
+ * We first construct a collection of lower bounds on the input set
+ * by computing its simple hull.  We then iterate through them,
+ * discarding those that we cannot use (either because they do not
+ * involve the dimension at "depth" or because they have no corresponding
+ * upper bound, meaning that "n" would be unbounded) and pick out the
+ * best from the remaining ones.
+ *
+ * If we cannot find a suitable lower bound, then we consider that
+ * to be an error.
+ */
+static __isl_give isl_aff *find_unroll_lower_bound(__isl_keep isl_set *domain,
+       int depth, int *n)
+{
+       struct isl_find_unroll_data data = { domain, depth, NULL, n };
+       isl_basic_set *hull;
+
+       isl_int_init(data.tmp);
+       hull = isl_set_simple_hull(isl_set_copy(domain));
+
+       if (isl_basic_set_foreach_constraint(hull,
+                                           &constraint_find_unroll, &data) < 0)
+               goto error;
+
+       isl_basic_set_free(hull);
+       isl_int_clear(data.tmp);
+
+       if (!data.lower)
+               isl_die(isl_set_get_ctx(domain), isl_error_invalid,
+                       "cannot find lower bound for unrolling", return NULL);
+
+       return data.lower;
+error:
+       isl_basic_set_free(hull);
+       isl_int_clear(data.tmp);
+       return isl_aff_free(data.lower);
+}
+
+/* Intersect "set" with the constraint
+ *
+ *     i_"depth" = aff + offset
+ */
+static __isl_give isl_set *at_offset(__isl_take isl_set *set, int depth,
+       __isl_keep isl_aff *aff, int offset)
+{
+       isl_constraint *eq;
+
+       aff = isl_aff_copy(aff);
+       aff = isl_aff_add_coefficient_si(aff, isl_dim_in, depth, -1);
+       aff = isl_aff_add_constant_si(aff, offset);
+       eq = isl_equality_from_aff(aff);
+       set = isl_set_add_constraint(set, eq);
+
+       return set;
+}
+
+/* Return a list of basic sets, one for each value of the current dimension
+ * in "domain".
+ * The divs that involve the current dimension have not been projected out
+ * from this domain.
+ *
+ * Since we are going to be iterating over the individual values,
+ * we first check if there are any strides on the current dimension.
+ * If there is, we rewrite the current dimension i as
+ *
+ *             i = stride i' + offset
+ *
+ * and then iterate over individual values of i' instead.
+ *
+ * We then look for a lower bound on i' and a size such that the domain
+ * is a subset of
+ *
+ *     { [j,i'] : l(j) <= i' < l(j) + n }
+ *
+ * and then take slices of the domain at values of i'
+ * between l(j) and l(j) + n - 1.
+ *
+ * We compute the unshifted simple hull of each slice to ensure that
+ * we have a single basic set per offset.  The slicing constraint
+ * is preserved by taking the unshifted simple hull, so these basic sets
+ * remain disjoint.  The constraints that are dropped by taking the hull
+ * will be taken into account at the next level, as in the case of the
+ * atomic option.
+ *
+ * Finally, we map i' back to i and add each basic set to the list.
+ */
+static __isl_give isl_basic_set_list *do_unroll(__isl_take isl_set *domain,
+       __isl_keep isl_ast_build *build)
+{
+       int i, n;
+       int depth;
+       isl_ctx *ctx;
+       isl_aff *lower;
+       isl_basic_set_list *list;
+       isl_multi_aff *expansion;
+       isl_basic_map *bmap;
+
+       if (!domain)
+               return NULL;
+
+       ctx = isl_set_get_ctx(domain);
+       depth = isl_ast_build_get_depth(build);
+       build = isl_ast_build_copy(build);
+       domain = isl_ast_build_eliminate_inner(build, domain);
+       build = isl_ast_build_detect_strides(build, isl_set_copy(domain));
+       expansion = isl_ast_build_get_stride_expansion(build);
+
+       domain = isl_set_preimage_multi_aff(domain,
+                                           isl_multi_aff_copy(expansion));
+       domain = isl_ast_build_eliminate_divs(build, domain);
+
+       isl_ast_build_free(build);
+
+       list = isl_basic_set_list_alloc(ctx, 0);
+
+       lower = find_unroll_lower_bound(domain, depth, &n);
+       if (!lower)
+               list = isl_basic_set_list_free(list);
+
+       bmap = isl_basic_map_from_multi_aff(expansion);
+
+       for (i = 0; list && i < n; ++i) {
+               isl_set *set;
+               isl_basic_set *bset;
+
+               set = at_offset(isl_set_copy(domain), depth, lower, i);
+               bset = isl_set_unshifted_simple_hull(set);
+               bset = isl_basic_set_apply(bset, isl_basic_map_copy(bmap));
+               list = isl_basic_set_list_add(list, bset);
+       }
+
+       isl_aff_free(lower);
+       isl_set_free(domain);
+       isl_basic_map_free(bmap);
+
+       return list;
+}
+
+/* Data structure for storing the results and the intermediate objects
+ * of compute_domains.
+ *
+ * "list" is the main result of the function and contains a list
+ * of disjoint basic sets for which code should be generated.
+ *
+ * "executed" and "build" are inputs to compute_domains.
+ * "schedule_domain" is the domain of "executed".
+ *
+ * "option" constains the domains at the current depth that should by
+ * atomic, separated or unrolled.  These domains are as specified by
+ * the user, except that inner dimensions have been eliminated and
+ * that they have been made pair-wise disjoint.
+ *
+ * "includes_schedule_domain" is set if the "class_domain" (not stored
+ * in this structure, but passed to the various functions) has been
+ * intersected with "schedule_domain".
+ *
+ * "sep_class" contains the user-specified split into separation classes
+ * specialized to the current depth.
+ * "done" contains the union of th separation domains that have already
+ * been handled.
+ */
+struct isl_codegen_domains {
+       isl_basic_set_list *list;
+
+       isl_union_map *executed;
+       isl_ast_build *build;
+       isl_set *schedule_domain;
+
+       isl_set *option[3];
+
+       int includes_schedule_domain;
+
+       isl_map *sep_class;
+       isl_set *done;
+};
+
+/* Add domains to domains->list for each individual value of the current
+ * dimension, for that part of the schedule domain that lies in the
+ * intersection of the option domain and the class domain.
+ *
+ * "domain" is the intersection of the class domain and the schedule domain.
+ * The divs that involve the current dimension have not been projected out
+ * from this domain.
+ *
+ * We first break up the unroll option domain into individual pieces
+ * and then handle each of them separately.  The unroll option domain
+ * has been made disjoint in compute_domains_init_options,
+ *
+ * Note that we actively want to combine different pieces of the
+ * schedule domain that have the same value at the current dimension.
+ * We therefore need to break up the unroll option domain before
+ * intersecting with class and schedule domain, hoping that the
+ * unroll option domain specified by the user is relatively simple.
+ */
+static int compute_unroll_domains(struct isl_codegen_domains *domains,
+       __isl_keep isl_set *domain)
+{
+       isl_set *unroll_domain;
+       isl_basic_set_list *unroll_list;
+       int i, n;
+       int empty;
+
+       empty = isl_set_is_empty(domains->option[unroll]);
+       if (empty < 0)
+               return -1;
+       if (empty)
+               return 0;
+
+       unroll_domain = isl_set_copy(domains->option[unroll]);
+       unroll_list = isl_basic_set_list_from_set(unroll_domain);
+
+       n = isl_basic_set_list_n_basic_set(unroll_list);
+       for (i = 0; i < n; ++i) {
+               isl_basic_set *bset;
+               isl_basic_set_list *list;
+
+               bset = isl_basic_set_list_get_basic_set(unroll_list, i);
+               unroll_domain = isl_set_from_basic_set(bset);
+               unroll_domain = isl_set_intersect(unroll_domain,
+                                                   isl_set_copy(domain));
+
+               empty = isl_set_is_empty(unroll_domain);
+               if (empty >= 0 && empty) {
+                       isl_set_free(unroll_domain);
+                       continue;
+               }
+
+               list = do_unroll(unroll_domain, domains->build);
+               domains->list = isl_basic_set_list_concat(domains->list, list);
+       }
+
+       isl_basic_set_list_free(unroll_list);
+
+       return 0;
+}
+
+/* Construct a single basic set that includes the intersection of
+ * the schedule domain, the atomic option domain and the class domain.
+ * Add the resulting basic set to domains->list.
+ *
+ * We construct a single domain rather than trying to combine
+ * the schedule domains of individual domains because we are working
+ * within a single component so that non-overlapping schedule domains
+ * should already have been separated.
+ * Note, though, that this does not take into account the class domain.
+ * So, it is possible for a class domain to carve out a piece of the
+ * schedule domain with independent pieces and then we would only
+ * generate a single domain for them.  If this proves to be problematic
+ * for some users, then this function will have to be adjusted.
+ *
+ * "domain" is the intersection of the schedule domain and the class domain,
+ * with inner dimensions projected out.
+ */
+static int compute_atomic_domain(struct isl_codegen_domains *domains,
+       __isl_keep isl_set *domain)
+{
+       isl_basic_set *bset;
+       isl_set *atomic_domain;
+       int empty;
+
+       atomic_domain = isl_set_copy(domains->option[atomic]);
+       atomic_domain = isl_set_intersect(atomic_domain, isl_set_copy(domain));
+       empty = isl_set_is_empty(atomic_domain);
+       if (empty < 0 || empty) {
+               isl_set_free(atomic_domain);
+               return empty < 0 ? -1 : 0;
+       }
+
+       atomic_domain = isl_set_coalesce(atomic_domain);
+       bset = isl_set_unshifted_simple_hull(atomic_domain);
+       domains->list = isl_basic_set_list_add(domains->list, bset);
+
+       return 0;
+}
+
+/* Split up the schedule domain into uniform basic sets,
+ * in the sense that each element in a basic set is associated to
+ * elements of the same domains, and add the result to domains->list.
+ * Do this for that part of the schedule domain that lies in the
+ * intersection of "class_domain" and the separate option domain.
+ *
+ * "class_domain" may or may not include the constraints
+ * of the schedule domain, but this does not make a difference
+ * since we are going to intersect it with the domain of the inverse schedule.
+ * If it includes schedule domain constraints, then they may involve
+ * inner dimensions, but we will eliminate them in separation_domain.
+ */
+static int compute_separate_domain(struct isl_codegen_domains *domains,
+       __isl_keep isl_set *class_domain)
+{
+       isl_space *space;
+       isl_set *domain;
+       isl_union_map *executed;
+       isl_basic_set_list *list;
+       int empty;
+
+       domain = isl_set_copy(domains->option[separate]);
+       domain = isl_set_intersect(domain, isl_set_copy(class_domain));
+       executed = isl_union_map_copy(domains->executed);
+       executed = isl_union_map_intersect_domain(executed,
+                                   isl_union_set_from_set(domain));
+       empty = isl_union_map_is_empty(executed);
+       if (empty < 0 || empty) {
+               isl_union_map_free(executed);
+               return empty < 0 ? -1 : 0;
+       }
+
+       space = isl_set_get_space(class_domain);
+       domain = separate_schedule_domains(space, executed, domains->build);
+
+       list = isl_basic_set_list_from_set(domain);
+       domains->list = isl_basic_set_list_concat(domains->list, list);
+
+       return 0;
+}
+
+/* Split up the domain at the current depth into disjoint
+ * basic sets for which code should be generated separately
+ * for the given separation class domain.
+ *
+ * We first make sure that the class domain is disjoint from
+ * previously considered class domains.
+ *
+ * The separate domains can be computed directly from the "class_domain".
+ *
+ * The unroll, atomic and remainder domains need the constraints
+ * from the schedule domain.
+ *
+ * For unrolling, the actual schedule domain is needed (with divs that
+ * may refer to the current dimension) so that stride detection can be
+ * performed.
+ *
+ * For atomic and remainder domains, inner dimensions and divs involving
+ * the current dimensions should be eliminated.
+ *
+ * If anything is left after handling separate, unroll and atomic,
+ * we split it up into basic sets and append the basic sets to domains->list.
+ */
+static int compute_partial_domains(struct isl_codegen_domains *domains,
+       __isl_take isl_set *class_domain)
+{
+       isl_basic_set_list *list;
+
+       class_domain = isl_set_subtract(class_domain,
+                                       isl_set_copy(domains->done));
+       domains->done = isl_set_union(domains->done,
+                                       isl_set_copy(class_domain));
+
+       if (compute_separate_domain(domains, class_domain) < 0)
+               goto error;
+       class_domain = isl_set_subtract(class_domain,
+                                   isl_set_copy(domains->option[separate]));
+
+       if (!domains->includes_schedule_domain)
+               class_domain = isl_set_intersect(class_domain,
+                                       isl_set_copy(domains->schedule_domain));
+
+       if (compute_unroll_domains(domains, class_domain) < 0)
+               goto error;
+       class_domain = isl_set_subtract(class_domain,
+                                   isl_set_copy(domains->option[unroll]));
+
+       class_domain = isl_ast_build_eliminate(domains->build,
+                                       class_domain);
+
+       if (compute_atomic_domain(domains, class_domain) < 0)
+               goto error;
+       class_domain = isl_set_subtract(class_domain,
+                                   isl_set_copy(domains->option[atomic]));
+
+       class_domain = isl_set_coalesce(class_domain);
+       class_domain = isl_set_make_disjoint(class_domain);
+
+       list = isl_basic_set_list_from_set(class_domain);
+       domains->list = isl_basic_set_list_concat(domains->list, list);
+
+       return 0;
+error:
+       isl_set_free(class_domain);
+       return -1;
+}
+
+/* Split up the domain at the current depth into disjoint
+ * basic sets for which code should be generated separately
+ * for the separation class identified by "pnt".
+ *
+ * We extract the corresponding class domain from domains->sep_class,
+ * eliminate inner dimensions and pass control to compute_partial_domains.
+ */
+static int compute_class_domains(__isl_take isl_point *pnt, void *user)
+{
+       struct isl_codegen_domains *domains = user;
+       isl_set *class_set;
+       isl_set *domain;
+       int disjoint;
+
+       class_set = isl_set_from_point(pnt);
+       domain = isl_map_domain(isl_map_intersect_range(
+                               isl_map_copy(domains->sep_class), class_set));
+       domain = isl_ast_build_eliminate(domains->build, domain);
+
+       disjoint = isl_set_plain_is_disjoint(domain, domains->schedule_domain);
+       if (disjoint < 0)
+               return -1;
+       if (disjoint) {
+               isl_set_free(domain);
+               return 0;
+       }
+
+       domains->includes_schedule_domain = 0;
+       return compute_partial_domains(domains, domain);
+}
+
+/* Extract the domains at the current depth that should be atomic,
+ * separated or unrolled and store them in option.
+ *
+ * The domains specified by the user might overlap, so we make
+ * them disjoint by subtracting earlier domains from later domains.
+ */
+static void compute_domains_init_options(isl_set *option[3],
+       __isl_keep isl_ast_build *build)
+{
+       enum isl_ast_build_domain_type type, type2;
+
+       for (type = atomic; type <= separate; ++type) {
+               option[type] = isl_ast_build_get_option_domain(build, type);
+               for (type2 = atomic; type2 < type; ++type2)
+                       option[type] = isl_set_subtract(option[type],
+                                               isl_set_copy(option[type2]));
+       }
+
+       option[unroll] = isl_set_coalesce(option[unroll]);
+       option[unroll] = isl_set_make_disjoint(option[unroll]);
+}
+
+/* Split up the domain at the current depth into disjoint
+ * basic sets for which code should be generated separately,
+ * based on the user-specified options.
+ * Return the list of disjoint basic sets.
+ *
+ * There are three kinds of domains that we need to keep track of.
+ * - the "schedule domain" is the domain of "executed"
+ * - the "class domain" is the domain corresponding to the currrent
+ *     separation class
+ * - the "option domain" is the domain corresponding to one of the options
+ *     atomic, unroll or separate
+ *
+ * We first consider the individial values of the separation classes
+ * and split up the domain for each of them separately.
+ * Finally, we consider the remainder.  If no separation classes were
+ * specified, then we call compute_partial_domains with the universe
+ * "class_domain".  Otherwise, we take the "schedule_domain" as "class_domain"
+ * and set includes_schedule_domain to reflect that the schedule domain
+ * has already been taken into account.  We do this because we want to
+ * avoid computing the complement of the class domains (i.e., the difference
+ * between the universe and domains->done).
+ */
+static __isl_give isl_basic_set_list *compute_domains(
+       __isl_keep isl_union_map *executed, __isl_keep isl_ast_build *build)
+{
+       struct isl_codegen_domains domains;
+       isl_ctx *ctx;
+       isl_set *domain;
+       isl_union_set *schedule_domain;
+       isl_set *classes;
+       isl_space *space;
+       int n_param;
+       enum isl_ast_build_domain_type type;
+
+       ctx = isl_union_map_get_ctx(executed);
+       domains.list = isl_basic_set_list_alloc(ctx, 0);
+
+       schedule_domain = isl_union_map_domain(isl_union_map_copy(executed));
+       domain = isl_set_from_union_set(schedule_domain);
+
+       compute_domains_init_options(domains.option, build);
+
+       domains.sep_class = isl_ast_build_get_separation_class(build);
+       classes = isl_map_range(isl_map_copy(domains.sep_class));
+       n_param = isl_set_dim(classes, isl_dim_param);
+       classes = isl_set_project_out(classes, isl_dim_param, 0, n_param);
+
+       space = isl_set_get_space(domain);
+       domains.build = build;
+       domains.schedule_domain = isl_set_copy(domain);
+       domains.executed = executed;
+       domains.done = isl_set_empty(space);
+
+       if (isl_set_foreach_point(classes, &compute_class_domains, &domains) < 0)
+               domains.list = isl_basic_set_list_free(domains.list);
+       isl_set_free(classes);
+
+       if (!domains.done)
+               domains.list = isl_basic_set_list_free(domains.list);
+       domains.includes_schedule_domain = !isl_set_is_empty(domains.done);
+       if (!domains.includes_schedule_domain) {
+               isl_set_free(domain);
+               domain = isl_set_universe(isl_set_get_space(domains.done));
+       }
+       if (compute_partial_domains(&domains, domain) < 0)
+               domains.list = isl_basic_set_list_free(domains.list);
+
+       isl_set_free(domains.schedule_domain);
+       isl_set_free(domains.done);
+       isl_map_free(domains.sep_class);
+       for (type = atomic; type <= separate; ++type)
+               isl_set_free(domains.option[type]);
+
+       return domains.list;
+}
+
+/* Generate code for a single component, after shifting (if any)
+ * has been applied.
+ *
+ * We first split up the domain at the current depth into disjoint
+ * basic sets based on the user-specified options.
+ * Then we generated code for each of them and concatenate the results.
+ */
+static __isl_give isl_ast_graft_list *generate_shifted_component(
+       __isl_take isl_union_map *executed, __isl_take isl_ast_build *build)
+{
+       isl_basic_set_list *domain_list;
+       isl_ast_graft_list *list = NULL;
+
+       domain_list = compute_domains(executed, build);
+       list = generate_parallel_domains(domain_list, executed, build);
+
+       isl_basic_set_list_free(domain_list);
+       isl_union_map_free(executed);
+       isl_ast_build_free(build);
+
+       return list;
+}
+
+struct isl_set_map_pair {
+       isl_set *set;
+       isl_map *map;
+};
+
+/* Given an array "domain" of isl_set_map_pairs and an array "order"
+ * of indices into the "domain" array,
+ * return the union of the "map" fields of the elements
+ * indexed by the first "n" elements of "order".
+ */
+static __isl_give isl_union_map *construct_component_executed(
+       struct isl_set_map_pair *domain, int *order, int n)
+{
+       int i;
+       isl_map *map;
+       isl_union_map *executed;
+
+       map = isl_map_copy(domain[order[0]].map);
+       executed = isl_union_map_from_map(map);
+       for (i = 1; i < n; ++i) {
+               map = isl_map_copy(domain[order[i]].map);
+               executed = isl_union_map_add_map(executed, map);
+       }
+
+       return executed;
+}
+
+/* Generate code for a single component, after shifting (if any)
+ * has been applied.
+ *
+ * The component inverse schedule is specified as the "map" fields
+ * of the elements of "domain" indexed by the first "n" elements of "order".
+ */
+static __isl_give isl_ast_graft_list *generate_shifted_component_from_list(
+       struct isl_set_map_pair *domain, int *order, int n,
+       __isl_take isl_ast_build *build)
+{
+       isl_union_map *executed;
+
+       executed = construct_component_executed(domain, order, n);
+       return generate_shifted_component(executed, build);
+}
+
+/* Given an array "domain" of isl_set_map_pairs and an array "order"
+ * of indices into the "domain" array,
+ * do all (except for at most one) of the "set" field of the elements
+ * indexed by the first "n" elements of "order" have a fixed value
+ * at position "depth"?
+ */
+static int at_most_one_non_fixed(struct isl_set_map_pair *domain,
+       int *order, int n, int depth)
+{
+       int i;
+       int non_fixed = -1;
+
+       for (i = 0; i < n; ++i) {
+               int f;
+
+               f = isl_set_plain_is_fixed(domain[order[i]].set,
+                                               isl_dim_set, depth, NULL);
+               if (f < 0)
+                       return -1;
+               if (f)
+                       continue;
+               if (non_fixed >= 0)
+                       return 0;
+               non_fixed = i;
+       }
+
+       return 1;
+}
+
+/* Given an array "domain" of isl_set_map_pairs and an array "order"
+ * of indices into the "domain" array,
+ * eliminate the inner dimensions from the "set" field of the elements
+ * indexed by the first "n" elements of "order", provided the current
+ * dimension does not have a fixed value.
+ *
+ * Return the index of the first element in "order" with a corresponding
+ * "set" field that does not have an (obviously) fixed value.
+ */
+static int eliminate_non_fixed(struct isl_set_map_pair *domain,
+       int *order, int n, int depth, __isl_keep isl_ast_build *build)
+{
+       int i;
+       int base = -1;
+
+       for (i = n - 1; i >= 0; --i) {
+               int f;
+               f = isl_set_plain_is_fixed(domain[order[i]].set,
+                                               isl_dim_set, depth, NULL);
+               if (f < 0)
+                       return -1;
+               if (f)
+                       continue;
+               domain[order[i]].set = isl_ast_build_eliminate_inner(build,
+                                                       domain[order[i]].set);
+               base = i;
+       }
+
+       return base;
+}
+
+/* Given an array "domain" of isl_set_map_pairs and an array "order"
+ * of indices into the "domain" array,
+ * find the element of "domain" (amongst those indexed by the first "n"
+ * elements of "order") with the "set" field that has the smallest
+ * value for the current iterator.
+ *
+ * Note that the domain with the smallest value may depend on the parameters
+ * and/or outer loop dimension.  Since the result of this function is only
+ * used as heuristic, we only make a reasonable attempt at finding the best
+ * domain, one that should work in case a single domain provides the smallest
+ * value for the current dimension over all values of the parameters
+ * and outer dimensions.
+ *
+ * In particular, we compute the smallest value of the first domain
+ * and replace it by that of any later domain if that later domain
+ * has a smallest value that is smaller for at least some value
+ * of the parameters and outer dimensions.
+ */
+static int first_offset(struct isl_set_map_pair *domain, int *order, int n,
+       __isl_keep isl_ast_build *build)
+{
+       int i;
+       isl_map *min_first;
+       int first = 0;
+
+       min_first = isl_ast_build_map_to_iterator(build,
+                                       isl_set_copy(domain[order[0]].set));
+       min_first = isl_map_lexmin(min_first);
+
+       for (i = 1; i < n; ++i) {
+               isl_map *min, *test;
+               int empty;
+
+               min = isl_ast_build_map_to_iterator(build,
+                                       isl_set_copy(domain[order[i]].set));
+               min = isl_map_lexmin(min);
+               test = isl_map_copy(min);
+               test = isl_map_apply_domain(isl_map_copy(min_first), test);
+               test = isl_map_order_lt(test, isl_dim_in, 0, isl_dim_out, 0);
+               empty = isl_map_is_empty(test);
+               isl_map_free(test);
+               if (empty >= 0 && !empty) {
+                       isl_map_free(min_first);
+                       first = i;
+                       min_first = min;
+               } else
+                       isl_map_free(min);
+
+               if (empty < 0)
+                       break;
+       }
+
+       isl_map_free(min_first);
+
+       return i < n ? -1 : first;
+}
+
+/* Construct a shifted inverse schedule based on the original inverse schedule,
+ * the stride and the offset.
+ *
+ * The original inverse schedule is specified as the "map" fields
+ * of the elements of "domain" indexed by the first "n" elements of "order".
+ *
+ * "stride" and "offset" are such that the difference
+ * between the values of the current dimension of domain "i"
+ * and the values of the current dimension for some reference domain are
+ * equal to
+ *
+ *     stride * integer + offset[i]
+ *
+ * Moreover, 0 <= offset[i] < stride.
+ *
+ * For each domain, we create a map
+ *
+ *     { [..., j, ...] -> [..., j - offset[i], offset[i], ....] }
+ *
+ * where j refers to the current dimension and the other dimensions are
+ * unchanged, and apply this map to the original schedule domain.
+ *
+ * For example, for the original schedule
+ *
+ *     { A[i] -> [2i]: 0 <= i < 10; B[i] -> [2i+1] : 0 <= i < 10 }
+ *
+ * and assuming the offset is 0 for the A domain and 1 for the B domain,
+ * we apply the mapping
+ *
+ *     { [j] -> [j, 0] }
+ *
+ * to the schedule of the "A" domain and the mapping
+ *
+ *     { [j - 1] -> [j, 1] }
+ *
+ * to the schedule of the "B" domain.
+ *
+ *
+ * Note that after the transformation, the differences between pairs
+ * of values of the current dimension over all domains are multiples
+ * of stride and that we have therefore exposed the stride.
+ *
+ *
+ * To see that the mapping preserves the lexicographic order,
+ * first note that each of the individual maps above preserves the order.
+ * If the value of the current iterator is j1 in one domain and j2 in another,
+ * then if j1 = j2, we know that the same map is applied to both domains
+ * and the order is preserved.
+ * Otherwise, let us assume, without loss of generality, that j1 < j2.
+ * If c1 >= c2 (with c1 and c2 the corresponding offsets), then
+ *
+ *     j1 - c1 < j2 - c2
+ *
+ * and the order is preserved.
+ * If c1 < c2, then we know
+ *
+ *     0 <= c2 - c1 < s
+ *
+ * We also have
+ *
+ *     j2 - j1 = n * s + r
+ *
+ * with n >= 0 and 0 <= r < s.
+ * In other words, r = c2 - c1.
+ * If n > 0, then
+ *
+ *     j1 - c1 < j2 - c2
+ *
+ * If n = 0, then
+ *
+ *     j1 - c1 = j2 - c2
+ *
+ * and so
+ *
+ *     (j1 - c1, c1) << (j2 - c2, c2)
+ *
+ * with "<<" the lexicographic order, proving that the order is preserved
+ * in all cases.
+ */
+static __isl_give isl_union_map *contruct_shifted_executed(
+       struct isl_set_map_pair *domain, int *order, int n, isl_int stride,
+       __isl_keep isl_vec *offset, __isl_keep isl_ast_build *build)
+{
+       int i;
+       isl_int v;
+       isl_union_map *executed;
+       isl_space *space;
+       isl_map *map;
+       int depth;
+       isl_constraint *c;
+
+       depth = isl_ast_build_get_depth(build);
+       space = isl_ast_build_get_space(build, 1);
+       executed = isl_union_map_empty(isl_space_copy(space));
+       space = isl_space_map_from_set(space);
+       map = isl_map_identity(isl_space_copy(space));
+       map = isl_map_eliminate(map, isl_dim_out, depth, 1);
+       map = isl_map_insert_dims(map, isl_dim_out, depth + 1, 1);
+       space = isl_space_insert_dims(space, isl_dim_out, depth + 1, 1);
+
+       c = isl_equality_alloc(isl_local_space_from_space(space));
+       c = isl_constraint_set_coefficient_si(c, isl_dim_in, depth, 1);
+       c = isl_constraint_set_coefficient_si(c, isl_dim_out, depth, -1);
+
+       isl_int_init(v);
+
+       for (i = 0; i < n; ++i) {
+               isl_map *map_i;
+
+               if (isl_vec_get_element(offset, i, &v) < 0)
+                       break;
+               map_i = isl_map_copy(map);
+               map_i = isl_map_fix(map_i, isl_dim_out, depth + 1, v);
+               isl_int_neg(v, v);
+               c = isl_constraint_set_constant(c, v);
+               map_i = isl_map_add_constraint(map_i, isl_constraint_copy(c));
+
+               map_i = isl_map_apply_domain(isl_map_copy(domain[order[i]].map),
+                                               map_i);
+               executed = isl_union_map_add_map(executed, map_i);
+       }
+
+       isl_constraint_free(c);
+       isl_map_free(map);
+
+       isl_int_clear(v);
+
+       if (i < n)
+               executed = isl_union_map_free(executed);
+
+       return executed;
+}
+
+/* Generate code for a single component, after exposing the stride,
+ * given that the schedule domain is "shifted strided".
+ *
+ * The component inverse schedule is specified as the "map" fields
+ * of the elements of "domain" indexed by the first "n" elements of "order".
+ *
+ * The schedule domain being "shifted strided" means that the differences
+ * between the values of the current dimension of domain "i"
+ * and the values of the current dimension for some reference domain are
+ * equal to
+ *
+ *     stride * integer + offset[i]
+ *
+ * We first look for the domain with the "smallest" value for the current
+ * dimension and adjust the offsets such that the offset of the "smallest"
+ * domain is equal to zero.  The other offsets are reduced modulo stride.
+ *
+ * Based on this information, we construct a new inverse schedule in
+ * contruct_shifted_executed that exposes the stride.
+ * Since this involves the introduction of a new schedule dimension,
+ * the build needs to be changed accodingly.
+ * After computing the AST, the newly introduced dimension needs
+ * to be removed again from the list of grafts.  We do this by plugging
+ * in a mapping that represents the new schedule domain in terms of the
+ * old schedule domain.
+ */
+static __isl_give isl_ast_graft_list *generate_shift_component(
+       struct isl_set_map_pair *domain, int *order, int n, isl_int stride,
+       __isl_keep isl_vec *offset, __isl_take isl_ast_build *build)
+{
+       isl_ast_graft_list *list;
+       int first;
+       int depth;
+       isl_ctx *ctx;
+       isl_int val;
+       isl_vec *v;
+       isl_space *space;
+       isl_multi_aff *ma, *zero;
+       isl_union_map *executed;
+
+       ctx = isl_ast_build_get_ctx(build);
+       depth = isl_ast_build_get_depth(build);
+
+       first = first_offset(domain, order, n, build);
+       if (first < 0)
+               return isl_ast_build_free(build);
+
+       isl_int_init(val);
+       v = isl_vec_alloc(ctx, n);
+       if (isl_vec_get_element(offset, first, &val) < 0)
+               v = isl_vec_free(v);
+       isl_int_neg(val, val);
+       v = isl_vec_set(v, val);
+       v = isl_vec_add(v, isl_vec_copy(offset));
+       v = isl_vec_fdiv_r(v, stride);
+
+       executed = contruct_shifted_executed(domain, order, n, stride, v,
+                                               build);
+       space = isl_ast_build_get_space(build, 1);
+       space = isl_space_map_from_set(space);
+       ma = isl_multi_aff_identity(isl_space_copy(space));
+       space = isl_space_from_domain(isl_space_domain(space));
+       space = isl_space_add_dims(space, isl_dim_out, 1);
+       zero = isl_multi_aff_zero(space);
+       ma = isl_multi_aff_range_splice(ma, depth + 1, zero);
+       build = isl_ast_build_insert_dim(build, depth + 1);
+       list = generate_shifted_component(executed, build);
+
+       list = isl_ast_graft_list_preimage_multi_aff(list, ma);
+
+       isl_vec_free(v);
+       isl_int_clear(val);
+
+       return list;
+}
+
+/* Generate code for a single component.
+ *
+ * The component inverse schedule is specified as the "map" fields
+ * of the elements of "domain" indexed by the first "n" elements of "order".
+ *
+ * This function may modify the "set" fields of "domain".
+ *
+ * Before proceeding with the actual code generation for the component,
+ * we first check if there are any "shifted" strides, meaning that
+ * the schedule domains of the individual domains are all strided,
+ * but that they have different offsets, resulting in the union
+ * of schedule domains not being strided anymore.
+ *
+ * The simplest example is the schedule
+ *
+ *     { A[i] -> [2i]: 0 <= i < 10; B[i] -> [2i+1] : 0 <= i < 10 }
+ *
+ * Both schedule domains are strided, but their union is not.
+ * This function detects such cases and then rewrites the schedule to
+ *
+ *     { A[i] -> [2i, 0]: 0 <= i < 10; B[i] -> [2i, 1] : 0 <= i < 10 }
+ *
+ * In the new schedule, the schedule domains have the same offset (modulo
+ * the stride), ensuring that the union of schedule domains is also strided.
+ *
+ *
+ * If there is only a single domain in the component, then there is
+ * nothing to do.   Similarly, if the current schedule dimension has
+ * a fixed value for almost all domains then there is nothing to be done.
+ * In particular, we need at least two domains where the current schedule
+ * dimension does not have a fixed value.
+ * Finally, if any of the options refer to the current schedule dimension,
+ * then we bail out as well.  It would be possible to reformulate the options
+ * in terms of the new schedule domain, but that would introduce constraints
+ * that separate the domains in the options and that is something we would
+ * like to avoid.
+ *
+ *
+ * To see if there is any shifted stride, we look at the differences
+ * between the values of the current dimension in pairs of domains
+ * for equal values of outer dimensions.  These differences should be
+ * of the form
+ *
+ *     m x + r
+ *
+ * with "m" the stride and "r" a constant.  Note that we cannot perform
+ * this analysis on individual domains as the lower bound in each domain
+ * may depend on parameters or outer dimensions and so the current dimension
+ * itself may not have a fixed remainder on division by the stride.
+ *
+ * In particular, we compare the first domain that does not have an
+ * obviously fixed value for the current dimension to itself and all
+ * other domains and collect the offsets and the gcd of the strides.
+ * If the gcd becomes one, then we failed to find shifted strides.
+ * If all the offsets are the same (for those domains that do not have
+ * an obviously fixed value for the current dimension), then we do not
+ * apply the transformation.
+ * If none of the domains were skipped, then there is nothing to do.
+ * If some of them were skipped, then if we apply separation, the schedule
+ * domain should get split in pieces with a (non-shifted) stride.
+ *
+ * Otherwise, we apply a shift to expose the stride in
+ * generate_shift_component.
+ */
+static __isl_give isl_ast_graft_list *generate_component(
+       struct isl_set_map_pair *domain, int *order, int n,
+       __isl_take isl_ast_build *build)
+{
+       int i, d;
+       int depth;
+       isl_ctx *ctx;
+       isl_map *map;
+       isl_set *deltas;
+       isl_int m, r, gcd;
+       isl_vec *v;
+       int fixed, skip;
+       int base;
+       isl_ast_graft_list *list;
+       int res = 0;
+
+       depth = isl_ast_build_get_depth(build);
+
+       skip = n == 1;
+       if (skip >= 0 && !skip)
+               skip = at_most_one_non_fixed(domain, order, n, depth);
+       if (skip >= 0 && !skip)
+               skip = isl_ast_build_options_involve_depth(build);
+       if (skip < 0)
+               return isl_ast_build_free(build);
+       if (skip)
+               return generate_shifted_component_from_list(domain,
+                                                           order, n, build);
+
+       base = eliminate_non_fixed(domain, order, n, depth, build);
+       if (base < 0)
+               return isl_ast_build_free(build);
+
+       ctx = isl_ast_build_get_ctx(build);
+
+       isl_int_init(m);
+       isl_int_init(r);
+       isl_int_init(gcd);
+       v = isl_vec_alloc(ctx, n);
+
+       fixed = 1;
+       for (i = 0; i < n; ++i) {
+               map = isl_map_from_domain_and_range(
+                                       isl_set_copy(domain[order[base]].set),
+                                       isl_set_copy(domain[order[i]].set));
+               for (d = 0; d < depth; ++d)
+                       map = isl_map_equate(map, isl_dim_in, d,
+                                                   isl_dim_out, d);
+               deltas = isl_map_deltas(map);
+               res = isl_set_dim_residue_class(deltas, depth, &m, &r);
+               isl_set_free(deltas);
+               if (res < 0)
+                       break;
+
+               if (i == 0)
+                       isl_int_set(gcd, m);
+               else
+                       isl_int_gcd(gcd, gcd, m);
+               if (isl_int_is_one(gcd))
+                       break;
+               v = isl_vec_set_element(v, i, r);
+
+               res = isl_set_plain_is_fixed(domain[order[i]].set,
+                                               isl_dim_set, depth, NULL);
+               if (res < 0)
+                       break;
+               if (res)
+                       continue;
+
+               if (fixed && i > base) {
+                       isl_vec_get_element(v, base, &m);
+                       if (isl_int_ne(m, r))
+                               fixed = 0;
+               }
+       }
+
+       if (res < 0) {
+               isl_ast_build_free(build);
+               list = NULL;
+       } else if (i < n || fixed) {
+               list = generate_shifted_component_from_list(domain,
+                                                           order, n, build);
+       } else {
+               list = generate_shift_component(domain, order, n, gcd, v,
+                                               build);
+       }
+
+       isl_vec_free(v);
+       isl_int_clear(gcd);
+       isl_int_clear(r);
+       isl_int_clear(m);
+
+       return list;
+}
+
+/* Store both "map" itself and its domain in the
+ * structure pointed to by *next and advance to the next array element.
+ */
+static int extract_domain(__isl_take isl_map *map, void *user)
+{
+       struct isl_set_map_pair **next = user;
+
+       (*next)->map = isl_map_copy(map);
+       (*next)->set = isl_map_domain(map);
+       (*next)++;
+
+       return 0;
+}
+
+/* Internal data for any_scheduled_after.
+ *
+ * "depth" is the number of loops that have already been generated
+ * "group_coscheduled" is a local copy of options->ast_build_group_coscheduled
+ * "domain" is an array of set-map pairs corresponding to the different
+ * iteration domains.  The set is the schedule domain, i.e., the domain
+ * of the inverse schedule, while the map is the inverse schedule itself.
+ */
+struct isl_any_scheduled_after_data {
+       int depth;
+       int group_coscheduled;
+       struct isl_set_map_pair *domain;
+};
+
+/* Is any element of domain "i" scheduled after any element of domain "j"
+ * (for a common iteration of the first data->depth loops)?
+ *
+ * data->domain[i].set contains the domain of the inverse schedule
+ * for domain "i", i.e., elements in the schedule domain.
+ *
+ * If data->group_coscheduled is set, then we also return 1 if there
+ * is any pair of elements in the two domains that are scheduled together.
+ */
+static int any_scheduled_after(int i, int j, void *user)
+{
+       struct isl_any_scheduled_after_data *data = user;
+       int dim = isl_set_dim(data->domain[i].set, isl_dim_set);
+       int pos;
+
+       for (pos = data->depth; pos < dim; ++pos) {
+               int follows;
+
+               follows = isl_set_follows_at(data->domain[i].set,
+                                               data->domain[j].set, pos);
+
+               if (follows < -1)
+                       return -1;
+               if (follows > 0)
+                       return 1;
+               if (follows < 0)
+                       return 0;
+       }
+
+       return data->group_coscheduled;
+}
+
+/* Look for independent components at the current depth and generate code
+ * for each component separately.  The resulting lists of grafts are
+ * merged in an attempt to combine grafts with identical guards.
+ *
+ * Code for two domains can be generated separately if all the elements
+ * of one domain are scheduled before (or together with) all the elements
+ * of the other domain.  We therefore consider the graph with as nodes
+ * the domains and an edge between two nodes if any element of the first
+ * node is scheduled after any element of the second node.
+ * If the ast_build_group_coscheduled is set, then we also add an edge if
+ * there is any pair of elements in the two domains that are scheduled
+ * together.
+ * Code is then generated (by generate_component)
+ * for each of the strongly connected components in this graph
+ * in their topological order.
+ *
+ * Since the test is performed on the domain of the inverse schedules of
+ * the different domains, we precompute these domains and store
+ * them in data.domain.
+ */
+static __isl_give isl_ast_graft_list *generate_components(
+       __isl_take isl_union_map *executed, __isl_take isl_ast_build *build)
+{
+       int i;
+       isl_ctx *ctx = isl_ast_build_get_ctx(build);
+       int n = isl_union_map_n_map(executed);
+       struct isl_any_scheduled_after_data data;
+       struct isl_set_map_pair *next;
+       struct isl_tarjan_graph *g = NULL;
+       isl_ast_graft_list *list = NULL;
+       int n_domain = 0;
+
+       data.domain = isl_calloc_array(ctx, struct isl_set_map_pair, n);
+       if (!data.domain)
+               goto error;
+       n_domain = n;
+
+       next = data.domain;
+       if (isl_union_map_foreach_map(executed, &extract_domain, &next) < 0)
+               goto error;
+
+       if (!build)
+               goto error;
+       data.depth = isl_ast_build_get_depth(build);
+       data.group_coscheduled = isl_options_get_ast_build_group_coscheduled(ctx);
+       g = isl_tarjan_graph_init(ctx, n, &any_scheduled_after, &data);
+
+       list = isl_ast_graft_list_alloc(ctx, 0);
+
+       i = 0;
+       while (list && n) {
+               isl_ast_graft_list *list_c;
+               int first = i;
+
+               if (g->order[i] == -1)
+                       isl_die(ctx, isl_error_internal, "cannot happen",
+                               goto error);
+               ++i; --n;
+               while (g->order[i] != -1) {
+                       ++i; --n;
+               }
+
+               list_c = generate_component(data.domain,
+                                           g->order + first, i - first,
+                                           isl_ast_build_copy(build));
+               list = isl_ast_graft_list_merge(list, list_c, build);
+
+               ++i;
+       }
+
+       if (0)
+error:         list = isl_ast_graft_list_free(list);
+       isl_tarjan_graph_free(g);
+       for (i = 0; i < n_domain; ++i) {
+               isl_map_free(data.domain[i].map);
+               isl_set_free(data.domain[i].set);
+       }
+       free(data.domain);
+       isl_union_map_free(executed);
+       isl_ast_build_free(build);
+
+       return list;
+}
+
+/* Generate code for the next level (and all inner levels).
+ *
+ * If "executed" is empty, i.e., no code needs to be generated,
+ * then we return an empty list.
+ *
+ * If we have already generated code for all loop levels, then we pass
+ * control to generate_inner_level.
+ *
+ * If "executed" lives in a single space, i.e., if code needs to be
+ * generated for a single domain, then there can only be a single
+ * component and we go directly to generate_shifted_component.
+ * Otherwise, we call generate_components to detect the components
+ * and to call generate_component on each of them separately.
+ */
+static __isl_give isl_ast_graft_list *generate_next_level(
+       __isl_take isl_union_map *executed, __isl_take isl_ast_build *build)
+{
+       int depth;
+
+       if (!build || !executed)
+               goto error;
+
+       if (isl_union_map_is_empty(executed)) {
+               isl_ctx *ctx = isl_ast_build_get_ctx(build);
+               isl_union_map_free(executed);
+               isl_ast_build_free(build);
+               return isl_ast_graft_list_alloc(ctx, 0);
+       }
+
+       depth = isl_ast_build_get_depth(build);
+       if (depth >= isl_set_dim(build->domain, isl_dim_set))
+               return generate_inner_level(executed, build);
+
+       if (isl_union_map_n_map(executed) == 1)
+               return generate_shifted_component(executed, build);
+
+       return generate_components(executed, build);
+error:
+       isl_union_map_free(executed);
+       isl_ast_build_free(build);
+       return NULL;
+}
+
+/* Internal data structure used by isl_ast_build_ast_from_schedule.
+ * internal, executed and build are the inputs to generate_code.
+ * list collects the output.
+ */
+struct isl_generate_code_data {
+       int internal;
+       isl_union_map *executed;
+       isl_ast_build *build;
+
+       isl_ast_graft_list *list;
+};
+
+/* Given an inverse schedule in terms of the external build schedule, i.e.,
+ *
+ *     [E -> S] -> D
+ *
+ * with E the external build schedule and S the additional schedule "space",
+ * reformulate the inverse schedule in terms of the internal schedule domain,
+ * i.e., return
+ *
+ *     [I -> S] -> D
+ *
+ * We first obtain a mapping
+ *
+ *     I -> E
+ *
+ * take the inverse and the product with S -> S, resulting in
+ *
+ *     [I -> S] -> [E -> S]
+ *
+ * Applying the map to the input produces the desired result.
+ */
+static __isl_give isl_union_map *internal_executed(
+       __isl_take isl_union_map *executed, __isl_keep isl_space *space,
+       __isl_keep isl_ast_build *build)
+{
+       isl_map *id, *proj;
+
+       proj = isl_ast_build_get_schedule_map(build);
+       proj = isl_map_reverse(proj);
+       space = isl_space_map_from_set(isl_space_copy(space));
+       id = isl_map_identity(space);
+       proj = isl_map_product(proj, id);
+       executed = isl_union_map_apply_domain(executed,
+                                               isl_union_map_from_map(proj));
+       return executed;
+}
+
+/* Generate an AST that visits the elements in the range of data->executed
+ * in the relative order specified by the corresponding image element(s)
+ * for those image elements that belong to "set".
+ * Add the result to data->list.
+ *
+ * The caller ensures that "set" is a universe domain.
+ * "space" is the space of the additional part of the schedule.
+ * It is equal to the space of "set" if build->domain is parametric.
+ * Otherwise, it is equal to the range of the wrapped space of "set".
+ *
+ * If the build space is not parametric and if isl_ast_build_ast_from_schedule
+ * was called from an outside user (data->internal not set), then
+ * the (inverse) schedule refers to the external build domain and needs to
+ * be transformed to refer to the internal build domain.
+ *
+ * The build is extended to include the additional part of the schedule.
+ * If the original build space was not parametric, then the options
+ * in data->build refer only to the additional part of the schedule
+ * and they need to be adjusted to refer to the complete AST build
+ * domain.
+ *
+ * After having adjusted inverse schedule and build, we start generating
+ * code with the outer loop of the current code generation
+ * in generate_next_level.
+ *
+ * If the original build space was not parametric, we undo the embedding
+ * on the resulting isl_ast_node_list so that it can be used within
+ * the outer AST build.
+ */
+static int generate_code_in_space(struct isl_generate_code_data *data,
+       __isl_take isl_set *set, __isl_take isl_space *space)
+{
+       isl_union_map *executed;
+       isl_ast_build *build;
+       isl_ast_graft_list *list;
+       int embed;
+
+       executed = isl_union_map_copy(data->executed);
+       executed = isl_union_map_intersect_domain(executed,
+                                                isl_union_set_from_set(set));
+
+       embed = !isl_set_is_params(data->build->domain);
+       if (embed && !data->internal)
+               executed = internal_executed(executed, space, data->build);
+
+       build = isl_ast_build_copy(data->build);
+       build = isl_ast_build_product(build, space);
+
+       list = generate_next_level(executed, build);
+
+       list = isl_ast_graft_list_unembed(list, embed);
+
+       data->list = isl_ast_graft_list_concat(data->list, list);
+
+       return 0;
+}
+
+/* Generate an AST that visits the elements in the range of data->executed
+ * in the relative order specified by the corresponding domain element(s)
+ * for those domain elements that belong to "set".
+ * Add the result to data->list.
+ *
+ * The caller ensures that "set" is a universe domain.
+ *
+ * If the build space S is not parametric, then the space of "set"
+ * need to be a wrapped relation with S as domain.  That is, it needs
+ * to be of the form
+ *
+ *     [S -> T]
+ *
+ * Check this property and pass control to generate_code_in_space
+ * passing along T.
+ * If the build space is not parametric, then T is the space of "set".
+ */
+static int generate_code_set(__isl_take isl_set *set, void *user)
+{
+       struct isl_generate_code_data *data = user;
+       isl_space *space, *build_space;
+       int is_domain;
+
+       space = isl_set_get_space(set);
+
+       if (isl_set_is_params(data->build->domain))
+               return generate_code_in_space(data, set, space);
+
+       build_space = isl_ast_build_get_space(data->build, data->internal);
+       space = isl_space_unwrap(space);
+       is_domain = isl_space_is_domain(build_space, space);
+       isl_space_free(build_space);
+       space = isl_space_range(space);
+
+       if (is_domain < 0)
+               goto error;
+       if (!is_domain)
+               isl_die(isl_set_get_ctx(set), isl_error_invalid,
+                       "invalid nested schedule space", goto error);
+
+       return generate_code_in_space(data, set, space);
+error:
+       isl_set_free(set);
+       isl_space_free(space);
+       return -1;
+}
+
+/* Generate an AST that visits the elements in the range of "executed"
+ * in the relative order specified by the corresponding domain element(s).
+ *
+ * "build" is an isl_ast_build that has either been constructed by
+ * isl_ast_build_from_context or passed to a callback set by
+ * isl_ast_build_set_create_leaf.
+ * In the first case, the space of the isl_ast_build is typically
+ * a parametric space, although this is currently not enforced.
+ * In the second case, the space is never a parametric space.
+ * If the space S is not parametric, then the domain space(s) of "executed"
+ * need to be wrapped relations with S as domain.
+ *
+ * If the domain of "executed" consists of several spaces, then an AST
+ * is generated for each of them (in arbitrary order) and the results
+ * are concatenated.
+ *
+ * If "internal" is set, then the domain "S" above refers to the internal
+ * schedule domain representation.  Otherwise, it refers to the external
+ * representation, as returned by isl_ast_build_get_schedule_space.
+ *
+ * We essentially run over all the spaces in the domain of "executed"
+ * and call generate_code_set on each of them.
+ */
+static __isl_give isl_ast_graft_list *generate_code(
+       __isl_take isl_union_map *executed, __isl_take isl_ast_build *build,
+       int internal)
+{
+       isl_ctx *ctx;
+       struct isl_generate_code_data data = { 0 };
+       isl_space *space;
+       isl_union_set *schedule_domain;
+       isl_union_map *universe;
+
+       if (!build)
+               goto error;
+       space = isl_ast_build_get_space(build, 1);
+       space = isl_space_align_params(space,
+                                   isl_union_map_get_space(executed));
+       space = isl_space_align_params(space,
+                                   isl_union_map_get_space(build->options));
+       build = isl_ast_build_align_params(build, isl_space_copy(space));
+       executed = isl_union_map_align_params(executed, space);
+       if (!executed || !build)
+               goto error;
+
+       ctx = isl_ast_build_get_ctx(build);
+
+       data.internal = internal;
+       data.executed = executed;
+       data.build = build;
+       data.list = isl_ast_graft_list_alloc(ctx, 0);
+
+       universe = isl_union_map_universe(isl_union_map_copy(executed));
+       schedule_domain = isl_union_map_domain(universe);
+       if (isl_union_set_foreach_set(schedule_domain, &generate_code_set,
+                                       &data) < 0)
+               data.list = isl_ast_graft_list_free(data.list);
+
+       isl_union_set_free(schedule_domain);
+       isl_union_map_free(executed);
+
+       isl_ast_build_free(build);
+       return data.list;
+error:
+       isl_union_map_free(executed);
+       isl_ast_build_free(build);
+       return NULL;
+}
+
+/* Generate an AST that visits the elements in the domain of "schedule"
+ * in the relative order specified by the corresponding image element(s).
+ *
+ * "build" is an isl_ast_build that has either been constructed by
+ * isl_ast_build_from_context or passed to a callback set by
+ * isl_ast_build_set_create_leaf.
+ * In the first case, the space of the isl_ast_build is typically
+ * a parametric space, although this is currently not enforced.
+ * In the second case, the space is never a parametric space.
+ * If the space S is not parametric, then the range space(s) of "schedule"
+ * need to be wrapped relations with S as domain.
+ *
+ * If the range of "schedule" consists of several spaces, then an AST
+ * is generated for each of them (in arbitrary order) and the results
+ * are concatenated.
+ *
+ * We first initialize the local copies of the relevant options.
+ * We do this here rather than when the isl_ast_build is created
+ * because the options may have changed between the construction
+ * of the isl_ast_build and the call to isl_generate_code.
+ *
+ * The main computation is performed on an inverse schedule (with
+ * the schedule domain in the domain and the elements to be executed
+ * in the range) called "executed".
+ */
+__isl_give isl_ast_node *isl_ast_build_ast_from_schedule(
+       __isl_keep isl_ast_build *build, __isl_take isl_union_map *schedule)
+{
+       isl_ast_graft_list *list;
+       isl_ast_node *node;
+       isl_union_map *executed;
+
+       executed = isl_union_map_reverse(schedule);
+       list = generate_code(executed, isl_ast_build_copy(build), 0);
+       node = isl_ast_node_from_graft_list(list, build);
+
+       return node;
+}
diff --git a/isl_ast_graft.c b/isl_ast_graft.c
new file mode 100644 (file)
index 0000000..11355bd
--- /dev/null
@@ -0,0 +1,1140 @@
+/*
+ * 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_list_private.h>
+#include <isl_ast_private.h>
+#include <isl_ast_build_expr.h>
+#include <isl_ast_build_private.h>
+#include <isl_ast_graft_private.h>
+
+static __isl_give isl_ast_graft *isl_ast_graft_copy(
+       __isl_keep isl_ast_graft *graft);
+
+#undef BASE
+#define BASE ast_graft
+
+#include <isl_list_templ.c>
+
+#undef BASE
+#define BASE ast_graft
+#include <print_templ.c>
+
+isl_ctx *isl_ast_graft_get_ctx(__isl_keep isl_ast_graft *graft)
+{
+       if (!graft)
+               return NULL;
+       return isl_basic_set_get_ctx(graft->enforced);
+}
+
+__isl_give isl_ast_node *isl_ast_graft_get_node(
+       __isl_keep isl_ast_graft *graft)
+{
+       return graft ? isl_ast_node_copy(graft->node) : 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_ctx *ctx;
+       isl_space *space;
+       isl_ast_graft *graft;
+
+       if (!node)
+               return NULL;
+
+       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);
+
+       return graft;
+error:
+       isl_ast_node_free(node);
+       return NULL;
+}
+
+/* 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.
+ */
+__isl_give isl_ast_graft *isl_ast_graft_alloc_domain(
+       __isl_take isl_map *executed, __isl_keep isl_ast_build *build)
+{
+       isl_ast_node *node;
+
+       node = isl_ast_build_call_from_executed(build, executed);
+
+       return isl_ast_graft_alloc(node, build);
+}
+
+static __isl_give isl_ast_graft *isl_ast_graft_copy(
+       __isl_keep isl_ast_graft *graft)
+{
+       if (!graft)
+               return NULL;
+
+       graft->ref++;
+       return graft;
+}
+
+/* Do all the grafts in "list" have the same guard and is this guard
+ * independent of the current depth?
+ */
+static int equal_independent_guards(__isl_keep isl_ast_graft_list *list,
+       __isl_keep isl_ast_build *build)
+{
+       int i, n;
+       int depth;
+       isl_ast_graft *graft_0;
+       int equal = 1;
+       int skip;
+
+       graft_0 = isl_ast_graft_list_get_ast_graft(list, 0);
+       if (!graft_0)
+               return -1;
+
+       depth = isl_ast_build_get_depth(build);
+       skip = isl_set_involves_dims(graft_0->guard, isl_dim_set, depth, 1);
+       if (skip < 0 || skip) {
+               isl_ast_graft_free(graft_0);
+               return skip < 0 ? -1 : 0;
+       }
+
+       n = isl_ast_graft_list_n_ast_graft(list);
+       for (i = 1; i < n; ++i) {
+               isl_ast_graft *graft;
+               graft = isl_ast_graft_list_get_ast_graft(list, i);
+               if (!graft)
+                       equal = -1;
+               else
+                       equal = isl_set_is_equal(graft_0->guard, graft->guard);
+               isl_ast_graft_free(graft);
+               if (equal < 0 || !equal)
+                       break;
+       }
+
+       isl_ast_graft_free(graft_0);
+
+       return equal;
+}
+
+/* Extract a common guard from the grafts in "list" that can be hoisted
+ * out of the current level.  If no such guard can be found, then return
+ * a universal set.
+ *
+ * If all the grafts in the list have the same guard and if this guard
+ * is independent of the current level, then it can be hoisted out.
+ * Otherwise, we return the unshifted simple hull of the guards.
+ *
+ * The special case for equal guards is needed in case those guards
+ * are non-convex.  Taking the simple hull would remove information
+ * and would not allow for these guards to be hoisted completely.
+ */
+static __isl_give isl_set *extract_hoistable_guard(
+       __isl_keep isl_ast_graft_list *list, __isl_keep isl_ast_build *build)
+{
+       int i, n;
+       int depth;
+       isl_ast_graft *graft_0;
+       int equal;
+       isl_set *guard;
+
+       if (!list || !build)
+               return NULL;
+
+       n = isl_ast_graft_list_n_ast_graft(list);
+       if (n == 0)
+               return isl_set_universe(isl_ast_build_get_space(build, 1));
+
+       equal = equal_independent_guards(list, build);
+       if (equal < 0)
+               return NULL;
+
+       graft_0 = isl_ast_graft_list_get_ast_graft(list, 0);
+       if (!graft_0)
+               return NULL;
+       guard = isl_set_copy(graft_0->guard);
+       isl_ast_graft_free(graft_0);
+       if (equal)
+               return guard;
+
+       depth = isl_ast_build_get_depth(build);
+       if (depth < isl_set_dim(guard, isl_dim_set)) {
+               guard = isl_set_eliminate(guard, isl_dim_set, depth, 1);
+               guard = isl_set_compute_divs(guard);
+       }
+
+       for (i = 1; i < n; ++i) {
+               isl_ast_graft *graft;
+               isl_basic_set *hull;
+               int is_universe;
+
+               is_universe = isl_set_plain_is_universe(guard);
+               if (is_universe < 0)
+                       guard = isl_set_free(guard);
+               if (is_universe)
+                       break;
+
+               graft = isl_ast_graft_list_get_ast_graft(list, i);
+               if (!graft) {
+                       guard = isl_set_free(guard);
+                       break;
+               }
+               guard = isl_set_union(guard, isl_set_copy(graft->guard));
+               hull = isl_set_unshifted_simple_hull(guard);
+               guard = isl_set_from_basic_set(hull);
+               isl_ast_graft_free(graft);
+       }
+
+       return guard;
+}
+
+/* Insert an if node around graft->node testing the condition encoded
+ * in guard "guard", assuming guard involves any conditions.
+ */
+static __isl_give isl_ast_graft *insert_if_node(
+       __isl_take isl_ast_graft *graft, __isl_take isl_set *guard,
+       __isl_keep isl_ast_build *build)
+{
+       int univ;
+       isl_ast_node *node;
+       isl_ast_expr *expr;
+
+       if (!graft)
+               goto error;
+
+       univ = isl_set_plain_is_universe(guard);
+       if (univ < 0)
+               goto error;
+       if (univ) {
+               isl_set_free(guard);
+               return graft;
+       }
+
+       build = isl_ast_build_copy(build);
+       build = isl_ast_build_set_enforced(build,
+                                       isl_ast_graft_get_enforced(graft));
+       expr = isl_ast_build_expr_from_set(build, guard);
+       isl_ast_build_free(build);
+
+       node = isl_ast_node_alloc_if(expr);
+       graft->node = isl_ast_node_if_set_then(node, graft->node);
+
+       if (!graft->node)
+               return isl_ast_graft_free(graft);
+
+       return graft;
+error:
+       isl_set_free(guard);
+       return isl_ast_graft_free(graft);
+}
+
+/* Insert an if node around graft->node testing the condition encoded
+ * in graft->guard, assuming graft->guard involves any conditions.
+ */
+static __isl_give isl_ast_graft *insert_pending_guard_node(
+       __isl_take isl_ast_graft *graft, __isl_keep isl_ast_build *build)
+{
+       if (!graft)
+               return NULL;
+
+       return insert_if_node(graft, isl_set_copy(graft->guard), build);
+}
+
+/* Replace graft->enforced by "enforced".
+ */
+__isl_give isl_ast_graft *isl_ast_graft_set_enforced(
+       __isl_take isl_ast_graft *graft, __isl_take isl_basic_set *enforced)
+{
+       if (!graft || !enforced)
+               goto error;
+
+       isl_basic_set_free(graft->enforced);
+       graft->enforced = enforced;
+
+       return graft;
+error:
+       isl_basic_set_free(enforced);
+       return isl_ast_graft_free(graft);
+}
+
+/* Update "enforced" such that it only involves constraints that are
+ * also enforced by "graft".
+ */
+static __isl_give isl_basic_set *update_enforced(
+       __isl_take isl_basic_set *enforced, __isl_keep isl_ast_graft *graft,
+       int depth)
+{
+       isl_basic_set *enforced_g;
+
+       enforced_g = isl_ast_graft_get_enforced(graft);
+       if (depth < isl_basic_set_dim(enforced_g, isl_dim_set))
+               enforced_g = isl_basic_set_eliminate(enforced_g,
+                                                       isl_dim_set, depth, 1);
+       enforced_g = isl_basic_set_remove_unknown_divs(enforced_g);
+       enforced_g = isl_basic_set_align_params(enforced_g,
+                               isl_basic_set_get_space(enforced));
+       enforced = isl_basic_set_align_params(enforced,
+                               isl_basic_set_get_space(enforced_g));
+       enforced = isl_set_simple_hull(isl_basic_set_union(enforced,
+                                               enforced_g));
+
+       return enforced;
+}
+
+/* Extend the node at *body with node.
+ *
+ * If body points to the else branch, then *body may still be NULL.
+ * If so, we simply attach node to this else branch.
+ * Otherwise, we attach a list containing the statements already
+ * attached at *body followed by node.
+ */
+static void extend_body(__isl_keep isl_ast_node **body,
+       __isl_take isl_ast_node *node)
+{
+       isl_ast_node_list *list;
+
+       if  (!*body) {
+               *body = node;
+               return;
+       }
+
+       if ((*body)->type == isl_ast_node_block) {
+               list = isl_ast_node_block_get_children(*body);
+               isl_ast_node_free(*body);
+       } else
+               list = isl_ast_node_list_from_ast_node(*body);
+       list = isl_ast_node_list_add(list, node);
+       *body = isl_ast_node_alloc_block(list);
+}
+
+/* Merge "graft" into the last graft of "list".
+ * body points to the then or else branch of an if node in that last graft.
+ *
+ * We attach graft->node to this branch and update the enforced
+ * set of the last graft of "list" to take into account the enforced
+ * set of "graft".
+ */
+static __isl_give isl_ast_graft_list *graft_extend_body(
+       __isl_take isl_ast_graft_list *list,
+       __isl_keep isl_ast_node **body, __isl_take isl_ast_graft *graft,
+       __isl_keep isl_ast_build *build)
+{
+       int n;
+       int depth;
+       isl_ast_graft *last;
+       isl_space *space;
+       isl_basic_set *enforced;
+
+       if (!list || !graft)
+               goto error;
+       extend_body(body, isl_ast_node_copy(graft->node));
+       if (!*body)
+               goto error;
+
+       n = isl_ast_graft_list_n_ast_graft(list);
+       last = isl_ast_graft_list_get_ast_graft(list, n - 1);
+
+       depth = isl_ast_build_get_depth(build);
+       space = isl_ast_build_get_space(build, 1);
+       enforced = isl_basic_set_empty(space);
+       enforced = update_enforced(enforced, last, depth);
+       enforced = update_enforced(enforced, graft, depth);
+       last = isl_ast_graft_set_enforced(last, enforced);
+
+       list = isl_ast_graft_list_set_ast_graft(list, n - 1, last);
+       isl_ast_graft_free(graft);
+       return list;
+error:
+       isl_ast_graft_free(graft);
+       return isl_ast_graft_list_free(list);
+}
+
+/* Merge "graft" into the last graft of "list", attaching graft->node
+ * to the then branch of "last_if".
+ */
+static __isl_give isl_ast_graft_list *extend_then(
+       __isl_take isl_ast_graft_list *list,
+       __isl_keep isl_ast_node *last_if, __isl_take isl_ast_graft *graft,
+       __isl_keep isl_ast_build *build)
+{
+       return graft_extend_body(list, &last_if->u.i.then, graft, build);
+}
+
+/* Merge "graft" into the last graft of "list", attaching graft->node
+ * to the else branch of "last_if".
+ */
+static __isl_give isl_ast_graft_list *extend_else(
+       __isl_take isl_ast_graft_list *list,
+       __isl_keep isl_ast_node *last_if, __isl_take isl_ast_graft *graft,
+       __isl_keep isl_ast_build *build)
+{
+       return graft_extend_body(list, &last_if->u.i.else_node, graft, build);
+}
+
+/* This data structure keeps track of an if node.
+ *
+ * "node" is the actual if-node
+ * "guard" is the original, non-simplified guard of the node
+ * "complement" is the complement of "guard" in the context of outer if nodes
+ */
+struct isl_if_node {
+       isl_ast_node *node;
+       isl_set *guard;
+       isl_set *complement;
+};
+
+/* Given a list of "n" if nodes, clear those starting at "first"
+ * and return "first" (i.e., the updated size of the array).
+ */
+static int clear_if_nodes(struct isl_if_node *if_node, int first, int n)
+{
+       int i;
+
+       for (i = first; i < n; ++i) {
+               isl_set_free(if_node[i].guard);
+               isl_set_free(if_node[i].complement);
+       }
+
+       return first;
+}
+
+/* For each graft in "list",
+ * insert an if node around graft->node testing the condition encoded
+ * in graft->guard, assuming graft->guard involves any conditions.
+ *
+ * We keep track of a list of generated if nodes that can be extended
+ * without changing the order of the elements in "list".
+ * If the guard of a graft is a subset of either the guard or its complement
+ * of one of those if nodes, then the node
+ * of the new graft is inserted into the then or else branch of the last graft
+ * and the current graft is discarded.
+ * The guard of the node is then simplified based on the conditions
+ * enforced at that then or else branch.
+ * Otherwise, the current graft is appended to the list.
+ */
+static __isl_give isl_ast_graft_list *insert_pending_guard_nodes(
+       __isl_take isl_ast_graft_list *list,
+       __isl_keep isl_ast_build *build)
+{
+       int i, j, n, n_if;
+       isl_ctx *ctx;
+       isl_ast_graft_list *res;
+       struct isl_if_node *if_node = NULL;
+
+       if (!build || !list)
+               return isl_ast_graft_list_free(list);
+
+       ctx = isl_ast_build_get_ctx(build);
+       n = isl_ast_graft_list_n_ast_graft(list);
+
+       n_if = 0;
+       if (n > 0) {
+               if_node = isl_alloc_array(ctx, struct isl_if_node, n - 1);
+               if (!if_node)
+                       return isl_ast_graft_list_free(list);
+       }
+
+       res = isl_ast_graft_list_alloc(ctx, n);
+
+       for (i = 0; i < n; ++i) {
+               isl_set *guard;
+               isl_ast_graft *graft;
+               int subset, found_then, found_else;
+               isl_ast_node *node;
+
+               graft = isl_ast_graft_list_get_ast_graft(list, i);
+               if (!graft)
+                       break;
+               subset = 0;
+               found_then = found_else = -1;
+               if (n_if > 0) {
+                       isl_set *test;
+                       test = isl_set_copy(graft->guard);
+                       test = isl_set_intersect(test,
+                                               isl_set_copy(build->domain));
+                       for (j = n_if - 1; j >= 0; --j) {
+                               subset = isl_set_is_subset(test,
+                                                       if_node[j].guard);
+                               if (subset < 0 || subset) {
+                                       found_then = j;
+                                       break;
+                               }
+                               subset = isl_set_is_subset(test,
+                                                       if_node[j].complement);
+                               if (subset < 0 || subset) {
+                                       found_else = j;
+                                       break;
+                               }
+                       }
+                       n_if = clear_if_nodes(if_node, j + 1, n_if);
+                       isl_set_free(test);
+               }
+               if (subset < 0) {
+                       graft = isl_ast_graft_free(graft);
+                       break;
+               }
+
+               guard = isl_set_copy(graft->guard);
+               if (found_then >= 0)
+                       graft->guard = isl_set_gist(graft->guard,
+                               isl_set_copy(if_node[found_then].guard));
+               else if (found_else >= 0)
+                       graft->guard = isl_set_gist(graft->guard,
+                               isl_set_copy(if_node[found_else].complement));
+
+               node = graft->node;
+               if (!graft->guard)
+                       graft = isl_ast_graft_free(graft);
+               graft = insert_pending_guard_node(graft, build);
+               if (graft && graft->node != node && i != n - 1) {
+                       isl_set *set;
+                       if_node[n_if].node = graft->node;
+                       if_node[n_if].guard = guard;
+                       if (found_then >= 0)
+                               set = if_node[found_then].guard;
+                       else if (found_else >= 0)
+                               set = if_node[found_else].complement;
+                       else
+                               set = build->domain;
+                       set = isl_set_copy(set);
+                       set = isl_set_subtract(set, isl_set_copy(guard));
+                       if_node[n_if].complement = set;
+                       n_if++;
+               } else
+                       isl_set_free(guard);
+               if (!graft)
+                       break;
+
+               if (found_then >= 0)
+                       res = extend_then(res, if_node[found_then].node,
+                                               graft, build);
+               else if (found_else >= 0)
+                       res = extend_else(res, if_node[found_else].node,
+                                               graft, build);
+               else
+                       res = isl_ast_graft_list_add(res, graft);
+       }
+       if (i < n)
+               res = isl_ast_graft_list_free(res);
+
+       isl_ast_graft_list_free(list);
+       clear_if_nodes(if_node, 0, n_if);
+       free(if_node);
+       return res;
+}
+
+/* Collect the nodes contained in the grafts in "list" in a node list.
+ */
+static __isl_give isl_ast_node_list *extract_node_list(
+       __isl_keep isl_ast_graft_list *list)
+{
+       int i, n;
+       isl_ctx *ctx;
+       isl_ast_node_list *node_list;
+
+       if (!list)
+               return NULL;
+       ctx = isl_ast_graft_list_get_ctx(list);
+       n = isl_ast_graft_list_n_ast_graft(list);
+       node_list = isl_ast_node_list_alloc(ctx, n);
+       for (i = 0; i < n; ++i) {
+               isl_ast_node *node;
+               isl_ast_graft *graft;
+
+               graft = isl_ast_graft_list_get_ast_graft(list, i);
+               node = isl_ast_graft_get_node(graft);
+               node_list = isl_ast_node_list_add(node_list, node);
+               isl_ast_graft_free(graft);
+       }
+
+       return node_list;
+}
+
+/* Look for shared enforced constraints by all the elements in "list"
+ * on outer loops (with respect to the current depth) and return the result.
+ *
+ * We assume that the number of children is at least one.
+ */
+static __isl_give isl_basic_set *extract_shared_enforced(
+       __isl_keep isl_ast_graft_list *list,
+       __isl_keep isl_ast_build *build)
+{
+       int i, n;
+       int depth;
+       isl_space *space;
+       isl_basic_set *enforced;
+
+       if (!list)
+               return NULL;
+
+       n = isl_ast_graft_list_n_ast_graft(list);
+       if (n == 0)
+               isl_die(isl_ast_graft_list_get_ctx(list), isl_error_invalid,
+                       "for node should have at least one child",
+                       return NULL);
+
+       space = isl_ast_build_get_space(build, 1);
+       enforced = isl_basic_set_empty(space);
+
+       depth = isl_ast_build_get_depth(build);
+       for (i = 0; i < n; ++i) {
+               isl_ast_graft *graft;
+
+               graft = isl_ast_graft_list_get_ast_graft(list, i);
+               enforced = update_enforced(enforced, graft, depth);
+               isl_ast_graft_free(graft);
+       }
+
+       return enforced;
+}
+
+/* Record "guard" in "graft" so that it will be enforced somewhere
+ * up the tree.  If the graft already has a guard, then it may be partially
+ * redundant in combination with the new guard and in the context
+ * of build->domain.  We therefore (re)compute the gist of the intersection.
+ */
+static __isl_give isl_ast_graft *store_guard(__isl_take isl_ast_graft *graft,
+       __isl_take isl_set *guard, __isl_keep isl_ast_build *build)
+{
+       int is_universe;
+
+       if (!graft)
+               goto error;
+
+       is_universe = isl_set_plain_is_universe(guard);
+       if (is_universe < 0)
+               goto error;
+       if (is_universe) {
+               isl_set_free(guard);
+               return graft;
+       }
+
+       graft->guard = isl_set_intersect(graft->guard, guard);
+       graft->guard = isl_ast_build_compute_gist(build, graft->guard);
+       if (!graft->guard)
+               return isl_ast_graft_free(graft);
+
+       return graft;
+error:
+       isl_set_free(guard);
+       return isl_ast_graft_free(graft);
+}
+
+/* For each graft in "list", replace its guard with the gist with
+ * respect to "context".
+ */
+static __isl_give isl_ast_graft_list *gist_guards(
+       __isl_take isl_ast_graft_list *list, __isl_keep isl_set *context)
+{
+       int i, n;
+
+       if (!list)
+               return NULL;
+
+       n = isl_ast_graft_list_n_ast_graft(list);
+       for (i = 0; i < n; ++i) {
+               isl_ast_graft *graft;
+
+               graft = isl_ast_graft_list_get_ast_graft(list, i);
+               if (!graft)
+                       break;
+               graft->guard = isl_set_gist(graft->guard,
+                                               isl_set_copy(context));
+               if (!graft->guard)
+                       graft = isl_ast_graft_free(graft);
+               list = isl_ast_graft_list_set_ast_graft(list, i, graft);
+       }
+       if (i < n)
+               return isl_ast_graft_list_free(list);
+
+       return list;
+}
+
+/* Combine the grafts in the list into a single graft.
+ *
+ * If "up" is set then the resulting graft will be used at an outer level.
+ *
+ * The guard is initialized to the shared guard of the list elements (if any),
+ * provided it does not depend on the current dimension.
+ * The guards in the elements are then simplified with respect to the
+ * hoisted guard and materialized as if nodes around the contained AST nodes.
+ *
+ * The enforced set is initialized to the simple hull of the enforced sets
+ * of the elements, provided the ast_build_exploit_nested_bounds option is set
+ * or the new graft will be used at the same level.
+ *
+ * The node is initialized to either a block containing the nodes of "list"
+ * or, if there is only a single element, the node of that element.
+ */
+static __isl_give isl_ast_graft *ast_graft_list_fuse(
+       __isl_take isl_ast_graft_list *list,
+       __isl_keep isl_ast_build *build, int up)
+{
+       isl_ctx *ctx;
+       isl_ast_node *node;
+       isl_ast_graft *graft;
+       isl_ast_node_list *node_list;
+       isl_set *guard;
+
+       if (!list)
+               return NULL;
+
+       ctx = isl_ast_build_get_ctx(build);
+       guard = extract_hoistable_guard(list, build);
+       list = gist_guards(list, guard);
+       list = insert_pending_guard_nodes(list, build);
+
+       node_list = extract_node_list(list);
+       node = isl_ast_node_from_ast_node_list(node_list);
+
+       graft = isl_ast_graft_alloc(node, build);
+
+       if (!up || isl_options_get_ast_build_exploit_nested_bounds(ctx)) {
+               isl_basic_set *enforced;
+               enforced = extract_shared_enforced(list, build);
+               graft = isl_ast_graft_enforce(graft, enforced);
+       }
+
+       graft = store_guard(graft, guard, build);
+
+       isl_ast_graft_list_free(list);
+       return graft;
+}
+
+/* Combine the grafts in the list into a single graft.
+ * Return a list containing this single graft.
+ * If the original list is empty, then return an empty list.
+ */
+__isl_give isl_ast_graft_list *isl_ast_graft_list_fuse(
+       __isl_take isl_ast_graft_list *list,
+       __isl_keep isl_ast_build *build)
+{
+       isl_ast_graft *graft;
+
+       if (!list)
+               return NULL;
+       if (isl_ast_graft_list_n_ast_graft(list) <= 1)
+               return list;
+       graft = ast_graft_list_fuse(list, build, 0);
+       return isl_ast_graft_list_from_ast_graft(graft);
+}
+
+/* Combine the two grafts into a single graft.
+ * Return a list containing this single graft.
+ */
+static __isl_give isl_ast_graft *isl_ast_graft_fuse(
+       __isl_take isl_ast_graft *graft1, __isl_take isl_ast_graft *graft2,
+       __isl_keep isl_ast_build *build)
+{
+       isl_ctx *ctx;
+       isl_ast_graft_list *list;
+
+       ctx = isl_ast_build_get_ctx(build);
+
+       list = isl_ast_graft_list_alloc(ctx, 2);
+       list = isl_ast_graft_list_add(list, graft1);
+       list = isl_ast_graft_list_add(list, graft2);
+
+       return ast_graft_list_fuse(list, build, 0);
+}
+
+/* Allocate a graft for the current level based on the list of grafts
+ * of the inner level.
+ *
+ * The node is initialized to either a block containing the nodes of "children"
+ * or, if there is only a single child, the node of that child.
+ * If the current level requires a for node, it should be inserted by
+ * a subsequent call to isl_ast_graft_insert_for.
+ */
+__isl_give isl_ast_graft *isl_ast_graft_alloc_level(
+       __isl_take isl_ast_graft_list *children,
+       __isl_keep isl_ast_build *build)
+{
+       return ast_graft_list_fuse(children, build, 1);
+}
+
+/* Insert a for node enclosing the current graft->node.
+ */
+__isl_give isl_ast_graft *isl_ast_graft_insert_for(
+       __isl_take isl_ast_graft *graft, __isl_take isl_ast_node *node)
+{
+       if (!graft)
+               goto error;
+
+       graft->node = isl_ast_node_for_set_body(node, graft->node);
+       if (!graft->node)
+               return isl_ast_graft_free(graft);
+
+       return graft;
+error:
+       isl_ast_node_free(node);
+       isl_ast_graft_free(graft);
+       return NULL;
+}
+
+/* Represent the graft list as an AST node.
+ * This operation drops the information about guards in the grafts, so
+ * if there are any pending guards, then they are materialized as if nodes.
+ */
+__isl_give isl_ast_node *isl_ast_node_from_graft_list(
+       __isl_take isl_ast_graft_list *list,
+       __isl_keep isl_ast_build *build)
+{
+       isl_ast_node_list *node_list;
+
+       list = insert_pending_guard_nodes(list, build);
+       node_list = extract_node_list(list);
+       isl_ast_graft_list_free(list);
+
+       return isl_ast_node_from_ast_node_list(node_list);
+}
+
+void *isl_ast_graft_free(__isl_take isl_ast_graft *graft)
+{
+       if (!graft)
+               return NULL;
+
+       if (--graft->ref > 0)
+               return NULL;
+
+       isl_ast_node_free(graft->node);
+       isl_set_free(graft->guard);
+       isl_basic_set_free(graft->enforced);
+       free(graft);
+
+       return NULL;
+}
+
+/* Record that the grafted tree enforces
+ * "enforced" by intersecting graft->enforced with "enforced".
+ */
+__isl_give isl_ast_graft *isl_ast_graft_enforce(
+       __isl_take isl_ast_graft *graft, __isl_take isl_basic_set *enforced)
+{
+       if (!graft || !enforced)
+               goto error;
+
+       enforced = isl_basic_set_align_params(enforced,
+                               isl_basic_set_get_space(graft->enforced));
+       graft->enforced = isl_basic_set_align_params(graft->enforced,
+                               isl_basic_set_get_space(enforced));
+       graft->enforced = isl_basic_set_intersect(graft->enforced, enforced);
+       if (!graft->enforced)
+               return isl_ast_graft_free(graft);
+
+       return graft;
+error:
+       isl_basic_set_free(enforced);
+       return isl_ast_graft_free(graft);
+}
+
+__isl_give isl_basic_set *isl_ast_graft_get_enforced(
+       __isl_keep isl_ast_graft *graft)
+{
+       return graft ? isl_basic_set_copy(graft->enforced) : NULL;
+}
+
+__isl_give isl_set *isl_ast_graft_get_guard(__isl_keep isl_ast_graft *graft)
+{
+       return graft ? isl_set_copy(graft->guard) : NULL;
+}
+
+/* Record that "guard" needs to be inserted in "graft".
+ *
+ * We first simplify the guard in the context of the enforced set and
+ * then we store the guard in case we may be able
+ * to hoist it to higher levels and/or combine it with those of other grafts.
+ */
+__isl_give isl_ast_graft *isl_ast_graft_add_guard(
+       __isl_take isl_ast_graft *graft,
+       __isl_take isl_set *guard, __isl_keep isl_ast_build *build)
+{
+       isl_basic_set *enforced;
+
+       if (!graft || !build)
+               goto error;
+
+       enforced = isl_basic_set_copy(graft->enforced);
+       guard = isl_set_gist(guard, isl_set_from_basic_set(enforced));
+
+       graft = store_guard(graft, guard, build);
+
+       return graft;
+error:
+       isl_set_free(guard);
+       isl_ast_graft_free(graft);
+       return NULL;
+}
+
+/* Reformulate the "graft", which was generated in the context
+ * of an inner code generation, in terms of the outer code generation
+ * AST build.
+ *
+ * If "product" is set, then the domain of the inner code generation build is
+ *
+ *     [O -> S]
+ *
+ * with O the domain of the outer code generation build.
+ * We essentially need to project out S.
+ *
+ * If "product" is not set, then we need to project the domains onto
+ * their parameter spaces.
+ */
+__isl_give isl_ast_graft *isl_ast_graft_unembed(__isl_take isl_ast_graft *graft,
+       int product)
+{
+       isl_basic_set *enforced;
+
+       if (!graft)
+               return NULL;
+
+       if (product) {
+               enforced = graft->enforced;
+               enforced = isl_basic_map_domain(isl_basic_set_unwrap(enforced));
+               graft->enforced = enforced;
+               graft->guard = isl_map_domain(isl_set_unwrap(graft->guard));
+       } else {
+               graft->enforced = isl_basic_set_params(graft->enforced);
+               graft->guard = isl_set_params(graft->guard);
+       }
+       graft->guard = isl_set_compute_divs(graft->guard);
+
+       if (!graft->enforced || !graft->guard)
+               return isl_ast_graft_free(graft);
+
+       return graft;
+}
+
+/* Reformulate the grafts in "list", which were generated in the context
+ * of an inner code generation, in terms of the outer code generation
+ * AST build.
+ */
+__isl_give isl_ast_graft_list *isl_ast_graft_list_unembed(
+       __isl_take isl_ast_graft_list *list, int product)
+{
+       int i, n;
+
+       n = isl_ast_graft_list_n_ast_graft(list);
+       for (i = 0; i < n; ++i) {
+               isl_ast_graft *graft;
+
+               graft = isl_ast_graft_list_get_ast_graft(list, i);
+               graft = isl_ast_graft_unembed(graft, product);
+               list = isl_ast_graft_list_set_ast_graft(list, i, graft);
+       }
+
+       return list;
+}
+
+/* Compute the preimage of "graft" under the function represented by "ma".
+ * In other words, plug in "ma" in "enforced" and "guard" fields of "graft".
+ */
+__isl_give isl_ast_graft *isl_ast_graft_preimage_multi_aff(
+       __isl_take isl_ast_graft *graft, __isl_take isl_multi_aff *ma)
+{
+       isl_basic_set *enforced;
+
+       if (!graft)
+               return NULL;
+
+       enforced = graft->enforced;
+       graft->enforced = isl_basic_set_preimage_multi_aff(enforced,
+                                               isl_multi_aff_copy(ma));
+       graft->guard = isl_set_preimage_multi_aff(graft->guard, ma);
+
+       if (!graft->enforced || !graft->guard)
+               return isl_ast_graft_free(graft);
+
+       return graft;
+}
+
+/* Compute the preimage of all the grafts in "list" under
+ * the function represented by "ma".
+ */
+__isl_give isl_ast_graft_list *isl_ast_graft_list_preimage_multi_aff(
+       __isl_take isl_ast_graft_list *list, __isl_take isl_multi_aff *ma)
+{
+       int i, n;
+
+       n = isl_ast_graft_list_n_ast_graft(list);
+       for (i = 0; i < n; ++i) {
+               isl_ast_graft *graft;
+
+               graft = isl_ast_graft_list_get_ast_graft(list, i);
+               graft = isl_ast_graft_preimage_multi_aff(graft,
+                                                   isl_multi_aff_copy(ma));
+               list = isl_ast_graft_list_set_ast_graft(list, i, graft);
+       }
+
+       isl_multi_aff_free(ma);
+       return list;
+}
+
+/* Compare two grafts based on their guards.
+ */
+static int cmp_graft(const void *a, const void *b)
+{
+       isl_ast_graft * const *g1 = a;
+       isl_ast_graft * const *g2 = b;
+
+       return isl_set_plain_cmp((*g1)->guard, (*g2)->guard);
+}
+
+/* Order the elements in "list" based on their guards.
+ */
+__isl_give isl_ast_graft_list *isl_ast_graft_list_sort(
+       __isl_take isl_ast_graft_list *list)
+{
+       if (!list)
+               return NULL;
+       if (list->n <= 1)
+               return list;
+
+       qsort(list->p, list->n, sizeof(list->p[0]), &cmp_graft);
+
+       return list;
+}
+
+/* Merge the given two lists into a single list of grafts,
+ * merging grafts with the same guard into a single graft.
+ *
+ * "list2" has been sorted using isl_ast_graft_list_sort.
+ * "list1" may be the result of a previous call to isl_ast_graft_list_merge
+ * and may therefore not be completely sorted.
+ *
+ * The elements in "list2" need to be executed after those in "list1",
+ * but if the guard of a graft in "list2" is disjoint from the guards
+ * of some final elements in "list1", then it can be moved up to before
+ * those final elements.
+ *
+ * In particular, we look at each element g of "list2" in turn
+ * and move it up beyond elements of "list1" that would be sorted
+ * after g as long as each of these elements has a guard that is disjoint
+ * from that of g.
+ *
+ * We do not allow the second or any later element of "list2" to be moved
+ * before a previous elements of "list2" even if the reason that
+ * that element didn't move up further was that its guard was not disjoint
+ * from that of the previous element in "list1".
+ */
+__isl_give isl_ast_graft_list *isl_ast_graft_list_merge(
+       __isl_take isl_ast_graft_list *list1,
+       __isl_take isl_ast_graft_list *list2,
+       __isl_keep isl_ast_build *build)
+{
+       int i, j, first;
+
+       if (!list1 || !list2 || !build)
+               goto error;
+       if (list2->n == 0) {
+               isl_ast_graft_list_free(list2);
+               return list1;
+       }
+       if (list1->n == 0) {
+               isl_ast_graft_list_free(list1);
+               return list2;
+       }
+
+       first = 0;
+       for (i = 0; i < list2->n; ++i) {
+               isl_ast_graft *graft;
+               graft = isl_ast_graft_list_get_ast_graft(list2, i);
+               if (!graft)
+                       break;
+
+               for (j = list1->n; j >= 0; --j) {
+                       int cmp, disjoint;
+                       isl_ast_graft *graft_j;
+
+                       if (j == first)
+                               cmp = -1;
+                       else
+                               cmp = isl_set_plain_cmp(list1->p[j - 1]->guard,
+                                                       graft->guard);
+                       if (cmp > 0) {
+                               disjoint = isl_set_is_disjoint(graft->guard,
+                                                       list1->p[j - 1]->guard);
+                               if (disjoint < 0) {
+                                       list1 = isl_ast_graft_list_free(list1);
+                                       break;
+                               }
+                               if (!disjoint)
+                                       cmp = -1;
+                       }
+                       if (cmp > 0)
+                               continue;
+                       if (cmp < 0) {
+                               list1 = isl_ast_graft_list_insert(list1, j,
+                                                               graft);
+                               break;
+                       }
+
+                       --j;
+
+                       graft_j = isl_ast_graft_list_get_ast_graft(list1, j);
+                       graft_j = isl_ast_graft_fuse(graft_j, graft, build);
+                       list1 = isl_ast_graft_list_set_ast_graft(list1, j,
+                                                               graft_j);
+                       break;
+               }
+
+               if (j < 0)
+                       isl_die(isl_ast_build_get_ctx(build),
+                               isl_error_internal,
+                               "element failed to get inserted", break);
+
+               first = j + 1;
+               if (!list1)
+                       break;
+       }
+       if (i < list2->n)
+               list1 = isl_ast_graft_list_free(list1);
+       isl_ast_graft_list_free(list2);
+
+       return list1;
+error:
+       isl_ast_graft_list_free(list1);
+       isl_ast_graft_list_free(list2);
+       return NULL;
+}
+
+__isl_give isl_printer *isl_printer_print_ast_graft(__isl_take isl_printer *p,
+       __isl_keep isl_ast_graft *graft)
+{
+       if (!p)
+               return NULL;
+       if (!graft)
+               return isl_printer_free(p);
+
+       p = isl_printer_print_str(p, "(");
+       p = isl_printer_print_str(p, "guard: ");
+       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_basic_set(p, graft->enforced);
+       p = isl_printer_print_str(p, ", ");
+       p = isl_printer_print_str(p, "node: ");
+       p = isl_printer_print_ast_node(p, graft->node);
+       p = isl_printer_print_str(p, ")");
+
+       return p;
+}
diff --git a/isl_ast_graft_private.h b/isl_ast_graft_private.h
new file mode 100644 (file)
index 0000000..93e2f24
--- /dev/null
@@ -0,0 +1,89 @@
+#ifndef ISL_AST_GRAFT_PRIVATE_H
+#define ISL_AST_GRAFT_PRIVATE_H
+
+#include <isl/ast.h>
+#include <isl/set.h>
+#include <isl/list.h>
+#include <isl/printer.h>
+
+struct isl_ast_graft;
+typedef struct isl_ast_graft isl_ast_graft;
+
+/* Representation of part of an AST ("node") with some additional polyhedral
+ * information about the tree.
+ *
+ * "guard" contains conditions that should still be enforced by
+ * some ancestor of the current tree.  In particular, the already
+ * generated tree assumes that these conditions hold, but may not
+ * enforced them itself.
+ * The guard should not contain any unknown divs as it will be used
+ * to generate an if condition.
+ *
+ * "enforced" expresses constraints that are already enforced by the for
+ * nodes in the current tree and that therefore do not need to be enforced
+ * by any ancestor.
+ * The constraints only involve outer loop iterators.
+ */
+struct isl_ast_graft {
+       int ref;
+
+       isl_ast_node *node;
+
+       isl_set *guard;
+       isl_basic_set *enforced;
+};
+
+ISL_DECLARE_LIST(ast_graft)
+
+#undef EL
+#define EL isl_ast_graft
+
+#include <isl_list_templ.h>
+
+isl_ctx *isl_ast_graft_get_ctx(__isl_keep isl_ast_graft *graft);
+
+__isl_give isl_ast_graft *isl_ast_graft_alloc(
+       __isl_take isl_ast_node *node, __isl_keep isl_ast_build *build);
+__isl_give isl_ast_graft *isl_ast_graft_alloc_level(
+       __isl_take isl_ast_graft_list *children,
+       __isl_keep isl_ast_build *build);
+__isl_give isl_ast_graft_list *isl_ast_graft_list_fuse(
+       __isl_take isl_ast_graft_list *children,
+       __isl_keep isl_ast_build *build);
+__isl_give isl_ast_graft *isl_ast_graft_alloc_domain(
+       __isl_take isl_map *schedule, __isl_keep isl_ast_build *build);
+void *isl_ast_graft_free(__isl_take isl_ast_graft *graft);
+__isl_give isl_ast_graft_list *isl_ast_graft_list_sort(
+       __isl_take isl_ast_graft_list *list);
+
+__isl_give isl_ast_graft_list *isl_ast_graft_list_merge(
+       __isl_take isl_ast_graft_list *list1,
+       __isl_take isl_ast_graft_list *list2,
+       __isl_keep isl_ast_build *build);
+
+__isl_give isl_ast_node *isl_ast_graft_get_node(
+       __isl_keep isl_ast_graft *graft);
+__isl_give isl_basic_set *isl_ast_graft_get_enforced(
+       __isl_keep isl_ast_graft *graft);
+__isl_give isl_set *isl_ast_graft_get_guard(__isl_keep isl_ast_graft *graft);
+
+__isl_give isl_ast_graft *isl_ast_graft_insert_for(
+       __isl_take isl_ast_graft *graft, __isl_take isl_ast_node *node);
+__isl_give isl_ast_graft *isl_ast_graft_add_guard(
+       __isl_take isl_ast_graft *graft,
+       __isl_take isl_set *guard, __isl_keep isl_ast_build *build);
+__isl_give isl_ast_graft *isl_ast_graft_enforce(
+       __isl_take isl_ast_graft *graft, __isl_take isl_basic_set *enforced);
+
+__isl_give isl_ast_graft_list *isl_ast_graft_list_unembed(
+       __isl_take isl_ast_graft_list *list, int product);
+__isl_give isl_ast_graft_list *isl_ast_graft_list_preimage_multi_aff(
+       __isl_take isl_ast_graft_list *list, __isl_take isl_multi_aff *ma);
+
+__isl_give isl_ast_node *isl_ast_node_from_graft_list(
+       __isl_take isl_ast_graft_list *list, __isl_keep isl_ast_build *build);
+
+__isl_give isl_printer *isl_printer_print_ast_graft(__isl_take isl_printer *p,
+       __isl_keep isl_ast_graft *graft);
+
+#endif
diff --git a/isl_ast_private.h b/isl_ast_private.h
new file mode 100644 (file)
index 0000000..8aef29a
--- /dev/null
@@ -0,0 +1,110 @@
+#ifndef ISL_AST_PRIVATE_H
+#define ISL_AST_PRIVATE_H
+
+#include <isl/aff.h>
+#include <isl/ast.h>
+#include <isl/set.h>
+#include <isl/map.h>
+#include <isl/vec.h>
+#include <isl/list.h>
+
+/* An expression is either an integer, an identifier or an operation
+ * with zero or more arguments.
+ */
+struct isl_ast_expr {
+       int ref;
+
+       isl_ctx *ctx;
+
+       enum isl_ast_expr_type type;
+
+       union {
+               isl_int i;
+               isl_id *id;
+               struct {
+                       enum isl_ast_op_type op;
+                       unsigned n_arg;
+                       isl_ast_expr **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(isl_ctx *ctx, isl_int i);
+__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_op_type op, int n_arg);
+__isl_give isl_ast_expr *isl_ast_expr_alloc_binary(enum isl_ast_op_type type,
+       __isl_take isl_ast_expr *expr1, __isl_take isl_ast_expr *expr2);
+
+#undef EL
+#define EL isl_ast_node
+
+#include <isl_list_templ.h>
+
+/* A node is either a block, an if, a for or a user node.
+ * "else_node" is NULL if the if node does not have an else branch.
+ * "cond" and "inc" are NULL for degenerate for nodes.
+ */
+struct isl_ast_node {
+       int ref;
+
+       isl_ctx *ctx;
+       enum isl_ast_node_type type;
+
+       union {
+               struct {
+                       isl_ast_node_list *children;
+               } b;
+               struct {
+                       isl_ast_expr *guard;
+                       isl_ast_node *then;
+                       isl_ast_node *else_node;
+               } i;
+               struct {
+                       unsigned degenerate : 1;
+                       isl_ast_expr *iterator;
+                       isl_ast_expr *init;
+                       isl_ast_expr *cond;
+                       isl_ast_expr *inc;
+                       isl_ast_node *body;
+               } f;
+               struct {
+                       isl_ast_expr *expr;
+               } e;
+       } u;
+
+       isl_id *annotation;
+};
+
+__isl_give isl_ast_node *isl_ast_node_alloc_for(__isl_take isl_id *id);
+__isl_give isl_ast_node *isl_ast_node_for_mark_degenerate(
+       __isl_take isl_ast_node *node);
+__isl_give isl_ast_node *isl_ast_node_alloc_if(__isl_take isl_ast_expr *guard);
+__isl_give isl_ast_node *isl_ast_node_alloc_block(
+       __isl_take isl_ast_node_list *list);
+__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_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);
+
+struct isl_ast_print_options {
+       __isl_give isl_printer *(*print_for)(__isl_take isl_printer *p,
+               __isl_keep isl_ast_node *node, void *user);
+       void *print_for_user;
+       __isl_give isl_printer *(*print_user)(__isl_take isl_printer *p,
+               __isl_keep isl_ast_node *node, void *user);
+       void *print_user_user;
+};
+
+__isl_give isl_printer *isl_ast_node_list_print(
+       __isl_keep isl_ast_node_list *list, __isl_take isl_printer *p,
+       __isl_keep isl_ast_print_options *options);
+
+#endif
index 5de67a3..159a782 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <isl/ctx.h>
 #include <isl_options_private.h>
+#include <isl/ast_build.h>
 #include <isl/schedule.h>
 #include <isl/version.h>
 
@@ -101,6 +102,12 @@ static struct isl_arg_choice fuse[] = {
        {0}
 };
 
+static struct isl_arg_choice separation_bounds[] = {
+       {"explicit",    ISL_AST_BUILD_SEPARATION_BOUNDS_EXPLICIT},
+       {"implicit",    ISL_AST_BUILD_SEPARATION_BOUNDS_IMPLICIT},
+       {0}
+};
+
 static void print_version(void)
 {
        printf("%s", isl_version());
@@ -169,6 +176,26 @@ ISL_ARG_CHOICE(struct isl_options, schedule_fuse, 0, "schedule-fuse", fuse,
        ISL_SCHEDULE_FUSE_MAX, "level of fusion during scheduling")
 ISL_ARG_BOOL(struct isl_options, tile_scale_tile_loops, 0,
        "tile-scale-tile-loops", 1, "scale tile loops")
+ISL_ARG_STR(struct isl_options, ast_iterator_type, 0,
+       "ast-iterator-type", "type", "int",
+       "type used for iterators during printing of AST")
+ISL_ARG_BOOL(struct isl_options, ast_build_atomic_upper_bound, 0,
+       "ast-build-atomic-upper-bound", 1, "generate atomic upper bounds")
+ISL_ARG_BOOL(struct isl_options, ast_build_prefer_pdiv, 0,
+       "ast-build-prefer-pdiv", 1, "prefer pdiv operation over fdiv")
+ISL_ARG_BOOL(struct isl_options, ast_build_exploit_nested_bounds, 0,
+       "ast-build-exploit-nested-bounds", 1,
+       "simplify conditions based on bounds of nested for loops")
+ISL_ARG_BOOL(struct isl_options, ast_build_group_coscheduled, 0,
+       "ast-build-group-coscheduled", 0,
+       "keep coscheduled domain elements together")
+ISL_ARG_CHOICE(struct isl_options, ast_build_separation_bounds, 0,
+       "ast-build-separation-bounds", separation_bounds,
+       ISL_AST_BUILD_SEPARATION_BOUNDS_EXPLICIT,
+       "bounds to use during separation")
+ISL_ARG_BOOL(struct isl_options, ast_build_scale_strides, 0,
+       "ast-build-scale-strides", 1,
+       "allow iterators of strided loops to be scaled down")
 ISL_ARG_VERSION(print_version)
 ISL_ARGS_END
 
@@ -238,3 +265,38 @@ ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
        tile_scale_tile_loops)
 ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
        tile_scale_tile_loops)
+
+ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+       ast_build_atomic_upper_bound)
+ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+       ast_build_atomic_upper_bound)
+
+ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+       ast_build_prefer_pdiv)
+ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+       ast_build_prefer_pdiv)
+
+ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+       ast_build_exploit_nested_bounds)
+ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+       ast_build_exploit_nested_bounds)
+
+ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+       ast_build_group_coscheduled)
+ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+       ast_build_group_coscheduled)
+
+ISL_CTX_SET_STR_DEF(isl_options, struct isl_options, isl_options_args,
+       ast_iterator_type)
+ISL_CTX_GET_STR_DEF(isl_options, struct isl_options, isl_options_args,
+       ast_iterator_type)
+
+ISL_CTX_SET_CHOICE_DEF(isl_options, struct isl_options, isl_options_args,
+       ast_build_separation_bounds)
+ISL_CTX_GET_CHOICE_DEF(isl_options, struct isl_options, isl_options_args,
+       ast_build_separation_bounds)
+
+ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+       ast_build_scale_strides)
+ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+       ast_build_scale_strides)
index 93563ec..0b1139a 100644 (file)
@@ -59,6 +59,14 @@ struct isl_options {
 
        int                     tile_scale_tile_loops;
 
+       char                    *ast_iterator_type;
+
+       int                     ast_build_atomic_upper_bound;
+       int                     ast_build_prefer_pdiv;
+       int                     ast_build_exploit_nested_bounds;
+       int                     ast_build_group_coscheduled;
+       int                     ast_build_separation_bounds;
+       int                     ast_build_scale_strides;
 };
 
 #endif
index a70c3d9..6f4149f 100644 (file)
@@ -22,6 +22,7 @@
 #include <isl/schedule.h>
 #include <isl_options_private.h>
 #include <isl/vertices.h>
+#include <isl/ast_build.h>
 
 #define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
 
@@ -3361,6 +3362,191 @@ static int test_pullback(isl_ctx *ctx)
        return 0;
 }
 
+/* Check that negation is printed correctly.
+ */
+static int test_ast(isl_ctx *ctx)
+{
+       isl_ast_expr *expr, *expr1, *expr2, *expr3;
+       char *str;
+       int ok;
+
+       expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL));
+       expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL));
+       expr = isl_ast_expr_add(expr1, expr2);
+       expr = isl_ast_expr_neg(expr);
+       str = isl_ast_expr_to_str(expr);
+       ok = !strcmp(str, "-(A + B)");
+       free(str);
+       isl_ast_expr_free(expr);
+
+       if (!ok)
+               isl_die(ctx, isl_error_unknown,
+                       "isl_ast_expr printed incorrectly", return -1);
+
+       expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL));
+       expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL));
+       expr = isl_ast_expr_add(expr1, expr2);
+       expr3 = isl_ast_expr_from_id(isl_id_alloc(ctx, "C", NULL));
+       expr = isl_ast_expr_sub(expr3, expr);
+       str = isl_ast_expr_to_str(expr);
+       ok = !strcmp(str, "C - (A + B)");
+       free(str);
+       isl_ast_expr_free(expr);
+
+       if (!ok)
+               isl_die(ctx, isl_error_unknown,
+                       "isl_ast_expr printed incorrectly", return -1);
+
+       return 0;
+}
+
+/* Check that the AST generator handles domains that are integrally disjoint
+ * but not ratinoally disjoint.
+ */
+static int test_ast_gen2(isl_ctx *ctx)
+{
+       const char *str;
+       isl_set *set;
+       isl_union_map *schedule;
+       isl_union_map *options;
+       isl_ast_build *build;
+       isl_ast_node *tree;
+
+       str = "{ A[i,j] -> [i,j] : 0 <= i,j <= 1 }";
+       schedule = isl_union_map_read_from_str(ctx, str);
+       set = isl_set_universe(isl_space_params_alloc(ctx, 0));
+       build = isl_ast_build_from_context(set);
+
+       str = "{ [i,j] -> atomic[1] : i + j = 1; [i,j] -> unroll[1] : i = j }";
+       options = isl_union_map_read_from_str(ctx, str);
+       build = isl_ast_build_set_options(build, options);
+       tree = isl_ast_build_ast_from_schedule(build, schedule);
+       isl_ast_build_free(build);
+       if (!tree)
+               return -1;
+       isl_ast_node_free(tree);
+
+       return 0;
+}
+
+/* Increment *user on each call.
+ */
+static __isl_give isl_ast_node *count_domains(__isl_take isl_ast_node *node,
+       __isl_keep isl_ast_build *build, void *user)
+{
+       int *n = user;
+
+       (*n)++;
+
+       return node;
+}
+
+/* Test that unrolling tries to minimize the number of instances.
+ * In particular, for the schedule given below, make sure it generates
+ * 3 nodes (rather than 101).
+ */
+static int test_ast_gen3(isl_ctx *ctx)
+{
+       const char *str;
+       isl_set *set;
+       isl_union_map *schedule;
+       isl_union_map *options;
+       isl_ast_build *build;
+       isl_ast_node *tree;
+       int n_domain = 0;
+
+       str = "[n] -> { A[i] -> [i] : 0 <= i <= 100 and n <= i <= n + 2 }";
+       schedule = isl_union_map_read_from_str(ctx, str);
+       set = isl_set_universe(isl_space_params_alloc(ctx, 0));
+
+       str = "{ [i] -> unroll[0] }";
+       options = isl_union_map_read_from_str(ctx, str);
+
+       build = isl_ast_build_from_context(set);
+       build = isl_ast_build_set_options(build, options);
+       build = isl_ast_build_set_at_each_domain(build,
+                       &count_domains, &n_domain);
+       tree = isl_ast_build_ast_from_schedule(build, schedule);
+       isl_ast_build_free(build);
+       if (!tree)
+               return -1;
+
+       isl_ast_node_free(tree);
+
+       if (n_domain != 3)
+               isl_die(ctx, isl_error_unknown,
+                       "unexpected number of for nodes", return -1);
+
+       return 0;
+}
+
+/* Check that if the ast_build_exploit_nested_bounds options is set,
+ * we do not get an outer if node in the generated AST,
+ * while we do get such an outer if node if the options is not set.
+ */
+static int test_ast_gen4(isl_ctx *ctx)
+{
+       const char *str;
+       isl_set *set;
+       isl_union_map *schedule;
+       isl_ast_build *build;
+       isl_ast_node *tree;
+       enum isl_ast_node_type type;
+       int enb;
+
+       enb = isl_options_get_ast_build_exploit_nested_bounds(ctx);
+       str = "[N,M] -> { A[i,j] -> [i,j] : 0 <= i <= N and 0 <= j <= M }";
+
+       isl_options_set_ast_build_exploit_nested_bounds(ctx, 1);
+
+       schedule = isl_union_map_read_from_str(ctx, str);
+       set = isl_set_universe(isl_space_params_alloc(ctx, 0));
+       build = isl_ast_build_from_context(set);
+       tree = isl_ast_build_ast_from_schedule(build, schedule);
+       isl_ast_build_free(build);
+       if (!tree)
+               return -1;
+
+       type = isl_ast_node_get_type(tree);
+       isl_ast_node_free(tree);
+
+       if (type == isl_ast_node_if)
+               isl_die(ctx, isl_error_unknown,
+                       "not expecting if node", return -1);
+
+       isl_options_set_ast_build_exploit_nested_bounds(ctx, 0);
+
+       schedule = isl_union_map_read_from_str(ctx, str);
+       set = isl_set_universe(isl_space_params_alloc(ctx, 0));
+       build = isl_ast_build_from_context(set);
+       tree = isl_ast_build_ast_from_schedule(build, schedule);
+       isl_ast_build_free(build);
+       if (!tree)
+               return -1;
+
+       type = isl_ast_node_get_type(tree);
+       isl_ast_node_free(tree);
+
+       if (type != isl_ast_node_if)
+               isl_die(ctx, isl_error_unknown,
+                       "expecting if node", return -1);
+
+       isl_options_set_ast_build_exploit_nested_bounds(ctx, enb);
+
+       return 0;
+}
+
+static int test_ast_gen(isl_ctx *ctx)
+{
+       if (test_ast_gen2(ctx) < 0)
+               return -1;
+       if (test_ast_gen3(ctx) < 0)
+               return -1;
+       if (test_ast_gen4(ctx) < 0)
+               return -1;
+       return 0;
+}
+
 struct {
        const char *name;
        int (*fn)(isl_ctx *ctx);
@@ -3370,6 +3556,8 @@ struct {
        { "align parameters", &test_align_parameters },
        { "preimage", &test_preimage },
        { "pullback", &test_pullback },
+       { "AST", &test_ast },
+       { "AST generation", &test_ast_gen },
        { "eliminate", &test_eliminate },
        { "reisdue class", &test_residue_class },
        { "div", &test_div },
diff --git a/print.c b/print.c
index abd8ad4..b4c9d23 100644 (file)
--- a/print.c
+++ b/print.c
@@ -10,6 +10,7 @@
 #include <isl/band.h>
 #include <isl/constraint.h>
 #include <isl/aff.h>
+#include <isl/ast.h>
 #include <isl/printer.h>
 
 #undef BASE
@@ -84,3 +85,9 @@
 #undef BASE
 #define BASE point
 #include <print_templ.c>
+#undef BASE
+#define BASE ast_expr
+#include <print_templ.c>
+#undef BASE
+#define BASE ast_node
+#include <print_templ.c>
diff --git a/test_inputs/codegen/atomic.c b/test_inputs/codegen/atomic.c
new file mode 100644 (file)
index 0000000..0b70279
--- /dev/null
@@ -0,0 +1,6 @@
+for (int c0 = 0; c0 <= 10; c0 += 1) {
+  if (c0 <= 9)
+    a(c0);
+  if (c0 >= 1)
+    b(c0 - 1);
+}
diff --git a/test_inputs/codegen/atomic.in b/test_inputs/codegen/atomic.in
new file mode 100644 (file)
index 0000000..754b3d0
--- /dev/null
@@ -0,0 +1,3 @@
+{ a[i] -> [i] : 0 <= i < 10; b[i] -> [i+1] : 0 <= i < 10 }
+{ : }
+{ [i] -> atomic[x] }
diff --git a/test_inputs/codegen/cloog/0D-1.c b/test_inputs/codegen/cloog/0D-1.c
new file mode 100644 (file)
index 0000000..7f22e2e
--- /dev/null
@@ -0,0 +1 @@
+S1();
diff --git a/test_inputs/codegen/cloog/0D-1.in b/test_inputs/codegen/cloog/0D-1.in
new file mode 100644 (file)
index 0000000..10e3e40
--- /dev/null
@@ -0,0 +1,3 @@
+{ S1[] -> [0] }
+{  :  }
+{ [i] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/0D-2.c b/test_inputs/codegen/cloog/0D-2.c
new file mode 100644 (file)
index 0000000..b87b57e
--- /dev/null
@@ -0,0 +1,2 @@
+if (M >= 0)
+  S1();
diff --git a/test_inputs/codegen/cloog/0D-2.in b/test_inputs/codegen/cloog/0D-2.in
new file mode 100644 (file)
index 0000000..3bbfd35
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[] -> [0] : M >= 0 }
+[M] -> {  :  }
+[M] -> { [i] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/0D-3.c b/test_inputs/codegen/cloog/0D-3.c
new file mode 100644 (file)
index 0000000..7f22e2e
--- /dev/null
@@ -0,0 +1 @@
+S1();
diff --git a/test_inputs/codegen/cloog/0D-3.in b/test_inputs/codegen/cloog/0D-3.in
new file mode 100644 (file)
index 0000000..f99dd34
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[] -> [0] : M >= 0 }
+[M] -> {  : M >= 0 }
+[M] -> { [i] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/1point-1.c b/test_inputs/codegen/cloog/1point-1.c
new file mode 100644 (file)
index 0000000..53dd893
--- /dev/null
@@ -0,0 +1 @@
+S1(2 * M, M);
diff --git a/test_inputs/codegen/cloog/1point-1.in b/test_inputs/codegen/cloog/1point-1.in
new file mode 100644 (file)
index 0000000..efd0a7f
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[2M, M] -> [2M, M, 0] }
+[M] -> {  :  }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/1point-2.c b/test_inputs/codegen/cloog/1point-2.c
new file mode 100644 (file)
index 0000000..0a8cbe3
--- /dev/null
@@ -0,0 +1 @@
+S1(2 * M, N + 2);
diff --git a/test_inputs/codegen/cloog/1point-2.in b/test_inputs/codegen/cloog/1point-2.in
new file mode 100644 (file)
index 0000000..de5157c
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S1[2M, 2 + N] -> [2M, 2 + N, 0] }
+[M, N] -> {  :  }
+[M, N] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/4-param.c b/test_inputs/codegen/cloog/4-param.c
new file mode 100644 (file)
index 0000000..598c994
--- /dev/null
@@ -0,0 +1,14 @@
+{
+  for (int c0 = m; c0 <= min(p - 1, n); c0 += 1)
+    S1(c0);
+  for (int c0 = p; c0 <= min(m - 1, q); c0 += 1)
+    S2(c0);
+  for (int c0 = max(m, p); c0 <= min(q, n); c0 += 1) {
+    S1(c0);
+    S2(c0);
+  }
+  for (int c0 = max(max(q + 1, m), p); c0 <= n; c0 += 1)
+    S1(c0);
+  for (int c0 = max(max(n + 1, m), p); c0 <= q; c0 += 1)
+    S2(c0);
+}
diff --git a/test_inputs/codegen/cloog/4-param.in b/test_inputs/codegen/cloog/4-param.in
new file mode 100644 (file)
index 0000000..7814076
--- /dev/null
@@ -0,0 +1,3 @@
+[m, n, p, q] -> { S1[i0] -> [i0, 0] : i0 >= m and i0 <= n; S2[i0] -> [i0, 1] : i0 >= p and i0 <= q }
+[m, n, p, q] -> {  :  }
+[m, n, p, q] -> { [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/README b/test_inputs/codegen/cloog/README
new file mode 100644 (file)
index 0000000..9250f11
--- /dev/null
@@ -0,0 +1,2 @@
+The tests in this directory have been adapted from the corresponding CLooG
+test cases.
diff --git a/test_inputs/codegen/cloog/backtrack.c b/test_inputs/codegen/cloog/backtrack.c
new file mode 100644 (file)
index 0000000..df0407a
--- /dev/null
@@ -0,0 +1 @@
+S1(0);
diff --git a/test_inputs/codegen/cloog/backtrack.in b/test_inputs/codegen/cloog/backtrack.in
new file mode 100644 (file)
index 0000000..b8ec466
--- /dev/null
@@ -0,0 +1,3 @@
+{ S1[0] -> [0, 0] }
+{  :  }
+{ [i, j] -> atomic[o0] }
diff --git a/test_inputs/codegen/cloog/basic-bounds-1.c b/test_inputs/codegen/cloog/basic-bounds-1.c
new file mode 100644 (file)
index 0000000..95eb5f7
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = 0; c0 <= 2; c0 += 1)
+  S1(c0);
diff --git a/test_inputs/codegen/cloog/basic-bounds-1.in b/test_inputs/codegen/cloog/basic-bounds-1.in
new file mode 100644 (file)
index 0000000..e5f8bfa
--- /dev/null
@@ -0,0 +1,3 @@
+{ S1[i0] -> [i0, 0] : i0 >= 0 and i0 <= 2 }
+{  :  }
+{ [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/basic-bounds-2.c b/test_inputs/codegen/cloog/basic-bounds-2.c
new file mode 100644 (file)
index 0000000..df0407a
--- /dev/null
@@ -0,0 +1 @@
+S1(0);
diff --git a/test_inputs/codegen/cloog/basic-bounds-2.in b/test_inputs/codegen/cloog/basic-bounds-2.in
new file mode 100644 (file)
index 0000000..7eb48f2
--- /dev/null
@@ -0,0 +1,3 @@
+{ S1[0] -> [0, 0] }
+{  :  }
+{ [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/basic-bounds-3.c b/test_inputs/codegen/cloog/basic-bounds-3.c
new file mode 100644 (file)
index 0000000..d0dd54b
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = 0; c0 <= M; c0 += 1)
+  S1(c0);
diff --git a/test_inputs/codegen/cloog/basic-bounds-3.in b/test_inputs/codegen/cloog/basic-bounds-3.in
new file mode 100644 (file)
index 0000000..59ce2c9
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[i0] -> [i0, 0] : i0 >= 0 and i0 <= M }
+[M] -> {  : M >= 0 }
+[M] -> { [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/basic-bounds-4.c b/test_inputs/codegen/cloog/basic-bounds-4.c
new file mode 100644 (file)
index 0000000..0ebb7cc
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = 0; c0 <= M + 1; c0 += 1)
+  S1(c0);
diff --git a/test_inputs/codegen/cloog/basic-bounds-4.in b/test_inputs/codegen/cloog/basic-bounds-4.in
new file mode 100644 (file)
index 0000000..5f79acf
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[i0] -> [i0, 0] : i0 >= 0 and i0 <= 1 + M }
+[M] -> {  : M >= 0 }
+[M] -> { [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/basic-bounds-5.c b/test_inputs/codegen/cloog/basic-bounds-5.c
new file mode 100644 (file)
index 0000000..09e8c42
--- /dev/null
@@ -0,0 +1 @@
+S1(1, floord(M + 1, 2));
diff --git a/test_inputs/codegen/cloog/basic-bounds-5.in b/test_inputs/codegen/cloog/basic-bounds-5.in
new file mode 100644 (file)
index 0000000..3a6f908
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[1, i1] -> [1, i1, 0] : 2i1 >= M and 2i1 <= 1 + M }
+[M] -> {  :  }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/block.c b/test_inputs/codegen/cloog/block.c
new file mode 100644 (file)
index 0000000..e24ef30
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  S1();
+  S3(0);
+  S2();
+  S3(1);
+}
diff --git a/test_inputs/codegen/cloog/block.in b/test_inputs/codegen/cloog/block.in
new file mode 100644 (file)
index 0000000..faf2af5
--- /dev/null
@@ -0,0 +1,3 @@
+{ S3[i0] -> [i0, 1] : i0 >= 0 and i0 <= 1; S1[] -> [0, 0]; S2[] -> [1, 0] }
+{  :  }
+{ [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/block2.c b/test_inputs/codegen/cloog/block2.c
new file mode 100644 (file)
index 0000000..d3fbbd7
--- /dev/null
@@ -0,0 +1,5 @@
+for (int c0 = 0; c0 <= 9; c0 += 1) {
+  S1(c0, 1);
+  S3(c0, 1);
+  S2(c0, 1);
+}
diff --git a/test_inputs/codegen/cloog/block2.in b/test_inputs/codegen/cloog/block2.in
new file mode 100644 (file)
index 0000000..d2b5db4
--- /dev/null
@@ -0,0 +1,3 @@
+{ S1[i0, 1] -> [i0, 1, 6] : i0 >= 0 and i0 <= 9; S2[i0, 1] -> [i0, 1, 11] : i0 >= 0 and i0 <= 9; S3[i0, 1] -> [i0, 1, 8] : i0 >= 0 and i0 <= 9 }
+{  :  }
+{ [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/block3.c b/test_inputs/codegen/cloog/block3.c
new file mode 100644 (file)
index 0000000..ff4d553
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  S1();
+  for (int c0 = 0; c0 <= 1; c0 += 1)
+    S3(c0);
+  S2();
+}
diff --git a/test_inputs/codegen/cloog/block3.in b/test_inputs/codegen/cloog/block3.in
new file mode 100644 (file)
index 0000000..39c0abb
--- /dev/null
@@ -0,0 +1,3 @@
+{ S2[] -> [1]; S3[i0] -> [i0] : i0 >= 0 and i0 <= 1; S1[] -> [0] }
+{  :  }
+{ [i] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/byu98-1-2-3.c b/test_inputs/codegen/cloog/byu98-1-2-3.c
new file mode 100644 (file)
index 0000000..8c4a081
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  for (int c0 = 2; c0 <= 3; c0 += 1)
+    for (int c1 = -c0 + 6; c1 <= 6; c1 += 1)
+      S1(c0, c1);
+  for (int c0 = 4; c0 <= 8; c0 += 1) {
+    if (c0 == 4) {
+      for (int c1 = 3; c1 <= 4; c1 += 1)
+        S1(4, c1);
+    } else if (c0 >= 6)
+      S2(c0, -c0 + 9);
+    if (c0 <= 5) {
+      S1(c0, -c0 + 9);
+      S2(c0, -c0 + 9);
+    }
+    for (int c1 = max(c0 - 1, -c0 + 10); c1 <= 6; c1 += 1)
+      S1(c0, c1);
+  }
+}
diff --git a/test_inputs/codegen/cloog/byu98-1-2-3.in b/test_inputs/codegen/cloog/byu98-1-2-3.in
new file mode 100644 (file)
index 0000000..9f98fb8
--- /dev/null
@@ -0,0 +1,3 @@
+{ S1[i0, i1] -> [i0, i1, 0] : i1 >= 6 - i0 and i0 >= 2 and i1 >= 3 and i1 <= 6 and i1 >= -1 + i0; S2[i0, 9 - i0] -> [i0, 9 - i0, 1] : i0 <= 8 and i0 >= 4 }
+{  :  }
+{ [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/cholesky.c b/test_inputs/codegen/cloog/cholesky.c
new file mode 100644 (file)
index 0000000..5a3d147
--- /dev/null
@@ -0,0 +1,12 @@
+for (int c0 = 1; c0 <= n; c0 += 1) {
+  S1(c0);
+  for (int c2 = 1; c2 <= c0 - 1; c2 += 1)
+    S2(c0, c2);
+  S3(c0);
+  for (int c2 = c0 + 1; c2 <= n; c2 += 1) {
+    S4(c0, c2);
+    for (int c4 = 1; c4 <= c0 - 1; c4 += 1)
+      S5(c0, c2, c4);
+    S6(c0, c2);
+  }
+}
diff --git a/test_inputs/codegen/cloog/cholesky.in b/test_inputs/codegen/cloog/cholesky.in
new file mode 100644 (file)
index 0000000..90b56c6
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { S1[i0] -> [i0, 1, 0, 0, 0, 0] : i0 >= 1 and i0 <= n; S2[i0, i1] -> [i0, 2, i1, 1, 0, 0] : i0 >= 1 and i0 <= n and i1 >= 1 and i1 <= -1 + i0; S6[i0, i1] -> [i0, 4, i1, 3, 0, 0] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n; S3[i0] -> [i0, 3, 0, 0, 0, 0] : i0 >= 1 and i0 <= n; S4[i0, i1] -> [i0, 4, i1, 1, 0, 0] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n; S5[i0, i1, i2] -> [i0, 4, i1, 2, i2, 1] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n and i2 >= 1 and i2 <= -1 + i0 }
+[n] -> {  :  }
+[n] -> { [i, j, k, l, m, n'] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/cholesky2.c b/test_inputs/codegen/cloog/cholesky2.c
new file mode 100644 (file)
index 0000000..56eb72e
--- /dev/null
@@ -0,0 +1,17 @@
+{
+  for (int c1 = 1; c1 <= M; c1 += 1) {
+    S1(c1);
+    for (int c2 = c1 + 1; c2 <= M; c2 += 1)
+      S4(c1, c2);
+  }
+  for (int c0 = 1; c0 <= 3 * M - 2; c0 += 3) {
+    S3((c0 + 2) / 3);
+    for (int c1 = (c0 + 5) / 3; c1 <= M; c1 += 1) {
+      S6((c0 + 2) / 3, c1);
+      for (int c4 = (c0 + 5) / 3; c4 <= c1 - 1; c4 += 1)
+        S5(c4, c1, (c0 + 2) / 3);
+    }
+    for (int c1 = (c0 + 5) / 3; c1 <= M; c1 += 1)
+      S2(c1, (c0 + 2) / 3);
+  }
+}
diff --git a/test_inputs/codegen/cloog/cholesky2.in b/test_inputs/codegen/cloog/cholesky2.in
new file mode 100644 (file)
index 0000000..b44b456
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [3i1, i0, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= -1 + i0; S4[i0, i1] -> [0, i0, i1] : i0 >= 1 and i0 <= M and i1 >= 1 + i0 and i1 <= M; S1[i0] -> [0, i0, 0] : i0 >= 1 and i0 <= M; S6[i0, i1] -> [-1 + 3i0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 + i0 and i1 <= M; S3[i0] -> [-2 + 3i0, 0, 0] : i0 >= 1 and i0 <= M; S5[i0, i1, i2] -> [-1 + 3i2, i1, i2] : i0 >= 1 and i0 <= M and i1 >= 1 + i0 and i1 <= M and i2 >= 1 and i2 <= -1 + i0 }
+[M] -> {  :  }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/christian.c b/test_inputs/codegen/cloog/christian.c
new file mode 100644 (file)
index 0000000..79ca949
--- /dev/null
@@ -0,0 +1,6 @@
+for (int c0 = -N + 1; c0 <= N; c0 += 1) {
+  for (int c1 = max(0, c0); c1 <= min(N - 1, N + c0 - 1); c1 += 1)
+    S1(c1, -c0 + c1);
+  for (int c1 = max(c0 - 1, 0); c1 <= min(N + c0 - 2, N - 1); c1 += 1)
+    S2(c1, -c0 + c1 + 1);
+}
diff --git a/test_inputs/codegen/cloog/christian.in b/test_inputs/codegen/cloog/christian.in
new file mode 100644 (file)
index 0000000..af3df07
--- /dev/null
@@ -0,0 +1,3 @@
+[N] -> { S1[i0, i1] -> [i0 - i1] : i0 >= 0 and i0 <= -1 + N and i1 >= 0 and i1 <= -1 + N; S2[i0, i1] -> [1 + i0 - i1] : i0 >= 0 and i0 <= -1 + N and i1 >= 0 and i1 <= -1 + N }
+[N] -> {  :  }
+[N] -> { [i] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/classen.c b/test_inputs/codegen/cloog/classen.c
new file mode 100644 (file)
index 0000000..9df75c7
--- /dev/null
@@ -0,0 +1,86 @@
+{
+  if (m == 1) {
+    S1(0, 1, 1, 1);
+    S8(0, 1);
+  } else if (m >= 2) {
+    S1(0, 1, 1, 1);
+    S4(0, 1, 2, 2, 1, 1, 2, 2);
+    S3(0, 1, 1, 2, 1, 1, 1, 2);
+    S2(0, 1, 1, 1, 1, 1, 2, 1);
+    S8(0, 1);
+  }
+  for (int c0 = 1; c0 <= 2 * m - 4; c0 += 1) {
+    if (c0 + 1 == m) {
+      S5(m - 2, 1, m - 1, 1, m - 1, 1, m, 1);
+      S1(m - 1, 1, m, 1);
+      S3(m - 1, 1, m, 2, m, 1, m, 2);
+    } else if (m >= c0 + 2) {
+      S5(c0 - 1, 1, c0, 1, c0, 1, c0 + 1, 1);
+      S1(c0, 1, c0 + 1, 1);
+      S4(c0, 1, c0 + 2, 2, c0 + 1, 1, c0 + 2, 2);
+      S3(c0, 1, c0 + 1, 2, c0 + 1, 1, c0 + 1, 2);
+      S2(c0, 1, c0 + 1, 1, c0 + 1, 1, c0 + 2, 1);
+    } else {
+      S5(c0 - 1, -m + c0 + 2, c0, -m + c0 + 2, m - 1, -m + c0 + 2, m, -m + c0 + 2);
+      S6(c0 - 1, -m + c0 + 1, c0, -m + c0 + 2, m, -m + c0 + 1, m, -m + c0 + 2);
+      S1(c0, -m + c0 + 2, m, -m + c0 + 2);
+      S3(c0, -m + c0 + 2, c0 + 1, -m + c0 + 3, m, -m + c0 + 2, m, -m + c0 + 3);
+    }
+    for (int c2 = max(-m + c0 + 3, 2); c2 <= min(c0, m - 1); c2 += 1) {
+      S5(c0 - 1, c2, c0, c2, c0 - c2 + 1, c2, c0 - c2 + 2, c2);
+      S7(c0 - 1, c2 - 1, c0 + 1, c2, c0 - c2 + 2, c2 - 1, c0 - c2 + 3, c2);
+      S6(c0 - 1, c2 - 1, c0, c2, c0 - c2 + 2, c2 - 1, c0 - c2 + 2, c2);
+      S1(c0, c2, c0 - c2 + 2, c2);
+      S3(c0, c2, c0 + 1, c2 + 1, c0 - c2 + 2, c2, c0 - c2 + 2, c2 + 1);
+      S2(c0, c2, c0 + 1, c2, c0 - c2 + 2, c2, c0 - c2 + 3, c2);
+      S4(c0, c2, c0 + 2, c2 + 1, c0 - c2 + 2, c2, c0 - c2 + 3, c2 + 1);
+    }
+    if (c0 + 1 == m) {
+      S6(m - 2, m - 1, m - 1, m, 1, m - 1, 1, m);
+      S7(m - 2, m - 1, m, m, 1, m - 1, 2, m);
+      S1(m - 1, m, 1, m);
+      S2(m - 1, m, m, m, 1, m, 2, m);
+    } else if (c0 >= m) {
+      S5(c0 - 1, m, c0, m, -m + c0 + 1, m, -m + c0 + 2, m);
+      S6(c0 - 1, m - 1, c0, m, -m + c0 + 2, m - 1, -m + c0 + 2, m);
+      S7(c0 - 1, m - 1, c0 + 1, m, -m + c0 + 2, m - 1, -m + c0 + 3, m);
+      S1(c0, m, -m + c0 + 2, m);
+      S2(c0, m, c0 + 1, m, -m + c0 + 2, m, -m + c0 + 3, m);
+    } else {
+      S7(c0 - 1, c0, c0 + 1, c0 + 1, 1, c0, 2, c0 + 1);
+      S6(c0 - 1, c0, c0, c0 + 1, 1, c0, 1, c0 + 1);
+      S1(c0, c0 + 1, 1, c0 + 1);
+      S3(c0, c0 + 1, c0 + 1, c0 + 2, 1, c0 + 1, 1, c0 + 2);
+      S2(c0, c0 + 1, c0 + 1, c0 + 1, 1, c0 + 1, 2, c0 + 1);
+      S4(c0, c0 + 1, c0 + 2, c0 + 2, 1, c0 + 1, 2, c0 + 2);
+    }
+    for (int c8 = max(-m + c0 + 2, 1); c8 <= min(c0 + 1, m); c8 += 1)
+      S8(c0, c8);
+  }
+  if (m >= 2) {
+    if (m >= 3) {
+      S5(2 * m - 4, m - 1, 2 * m - 3, m - 1, m - 1, m - 1, m, m - 1);
+      S6(2 * m - 4, m - 2, 2 * m - 3, m - 1, m, m - 2, m, m - 1);
+      S1(2 * m - 3, m - 1, m, m - 1);
+      S3(2 * m - 3, m - 1, 2 * m - 2, m, m, m - 1, m, m);
+      S5(2 * m - 4, m, 2 * m - 3, m, m - 2, m, m - 1, m);
+      S6(2 * m - 4, m - 1, 2 * m - 3, m, m - 1, m - 1, m - 1, m);
+      S7(2 * m - 4, m - 1, 2 * m - 2, m, m - 1, m - 1, m, m);
+      S1(2 * m - 3, m, m - 1, m);
+    } else {
+      S5(0, 1, 1, 1, 1, 1, 2, 1);
+      S1(1, 1, 2, 1);
+      S3(1, 1, 2, 2, 2, 1, 2, 2);
+      S6(0, 1, 1, 2, 1, 1, 1, 2);
+      S7(0, 1, 2, 2, 1, 1, 2, 2);
+      S1(1, 2, 1, 2);
+    }
+    S2(2 * m - 3, m, 2 * m - 2, m, m - 1, m, m, m);
+    for (int c8 = m - 1; c8 <= m; c8 += 1)
+      S8(2 * m - 3, c8);
+    S5(2 * m - 3, m, 2 * m - 2, m, m - 1, m, m, m);
+    S6(2 * m - 3, m - 1, 2 * m - 2, m, m, m - 1, m, m);
+    S1(2 * m - 2, m, m, m);
+    S8(2 * m - 2, m);
+  }
+}
diff --git a/test_inputs/codegen/cloog/classen.in b/test_inputs/codegen/cloog/classen.in
new file mode 100644 (file)
index 0000000..8dc0b76
--- /dev/null
@@ -0,0 +1,3 @@
+[m] -> { S2[i0, i1, 1 + i0, i1, 2 + i0 - i1, i1, 3 + i0 - i1, i1] -> [i0, 0, i1, 2, 2 + i0 - i1, i1, 1] : m >= 1 and i0 <= -3 + 2m and i0 >= 0 and i1 <= 1 + i0 and i1 <= m and i1 >= 3 - m + i0 and i1 >= 1; S4[i0, i1, 2 + i0, 1 + i1, 2 + i0 - i1, i1, 3 + i0 - i1, 1 + i1] -> [i0, 0, i1, 2, 2 + i0 - i1, i1, 1] : m >= 1 and i0 <= -4 + 2m and i0 >= 0 and i1 <= 1 + i0 and i1 <= -1 + m and i1 >= 3 - m + i0 and i1 >= 1; S5[i0, i1, 1 + i0, i1, 2 + i0 - i1, i1, 3 + i0 - i1, i1] -> [1 + i0, 0, i1, 0, 2 + i0 - i1, i1, 1] : m >= 1 and i0 <= -3 + 2m and i0 >= 0 and i1 <= 1 + i0 and i1 <= m and i1 >= 3 - m + i0 and i1 >= 1; S7[i0, i1, 2 + i0, 1 + i1, 2 + i0 - i1, i1, 3 + i0 - i1, 1 + i1] -> [1 + i0, 0, 1 + i1, 0, 2 + i0 - i1, i1, 1] : m >= 1 and i0 <= -4 + 2m and i0 >= 0 and i1 <= 1 + i0 and i1 <= -1 + m and i1 >= 3 - m + i0 and i1 >= 1; S6[i0, i1, 1 + i0, 1 + i1, 2 + i0 - i1, i1, 2 + i0 - i1, 1 + i1] -> [1 + i0, 0, 1 + i1, 0, 2 + i0 - i1, i1, 1] : m >= 1 and i0 <= -3 + 2m and i0 >= 0 and i1 <= 1 + i0 and i1 <= -1 + m and i1 >= 2 - m + i0 and i1 >= 1; S3[i0, i1, 1 + i0, 1 + i1, 2 + i0 - i1, i1, 2 + i0 - i1, 1 + i1] -> [i0, 0, i1, 2, 2 + i0 - i1, i1, 1] : m >= 1 and i0 <= -3 + 2m and i0 >= 0 and i1 <= 1 + i0 and i1 <= -1 + m and i1 >= 2 - m + i0 and i1 >= 1; S8[i0, i1] -> [i0, 1, 0, 0, 0, 0, 0] : i0 <= -2 + 2m and i0 >= 0 and i1 <= 1 + i0 and i1 <= m and i1 >= 2 - m + i0 and i1 >= 1; S1[i0, i1, 2 + i0 - i1, i1] -> [i0, 0, i1, 1, 0, 0, 0] : m >= 1 and i1 >= 2 - m + i0 and i1 <= 1 + i0 and i1 <= m and i1 >= 1 }
+[m] -> {  : m >= 0 }
+[m] -> { [i, j, k, l, m', n, o] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/classen2.c b/test_inputs/codegen/cloog/classen2.c
new file mode 100644 (file)
index 0000000..314eb1c
--- /dev/null
@@ -0,0 +1,4 @@
+for (int c0 = max(max(max(max(max(max(4, 10 * outerProcTileScatter1 - 2 * N + 2), 10 * outerProcTileScatter2 - N + 1), 5 * outerProcTileScatter2 + 1), 5 * outerTimeTileScatter), 5 * outerProcTileScatter1 + 5 * outerProcTileScatter2 - N), 5 * outerProcTileScatter1); c0 <= min(min(min(min(min(min(2 * M + 2 * N - 6, 5 * outerProcTileScatter2 + M + N), 5 * outerProcTileScatter1 + M + 2), 10 * outerProcTileScatter2 + N + 3), 10 * outerProcTileScatter1 + 4), 5 * outerTimeTileScatter + 4), 5 * outerProcTileScatter1 + 5 * outerProcTileScatter2 + 5); c0 += 1)
+  for (int c1 = max(max(max(max(-5 * outerProcTileScatter2 + c0 - 1, 5 * outerProcTileScatter1), 5 * outerProcTileScatter2 + 1), -M + c0 + 2), c0 - c0 / 2 + 2); c1 <= min(min(min(min(5 * outerProcTileScatter1 + 4, 5 * outerProcTileScatter2 + N + 2), c0), -5 * outerProcTileScatter2 + N + c0), N + c0 / 2 - 1); c1 += 1)
+    for (int c2 = max(max(5 * outerProcTileScatter2, -N + c1 + 2), c0 - c1 + 3); c2 <= min(min(5 * outerProcTileScatter2 + 4, N + c0 - c1), c1 - 1); c2 += 1)
+      S1(c0 - c1 + 1, -c0 + c1 + c2 - 2, c1 - c2, c0, c1, c2);
diff --git a/test_inputs/codegen/cloog/classen2.in b/test_inputs/codegen/cloog/classen2.in
new file mode 100644 (file)
index 0000000..8a74eaa
--- /dev/null
@@ -0,0 +1,3 @@
+[outerTimeTileScatter, outerProcTileScatter1, outerProcTileScatter2, M, N] -> { S1[i0, i1, i2, 2i0 + i1 + i2, 1 + i0 + i1 + i2, 1 + i0 + i1] -> [2i0 + i1 + i2, 1 + i0 + i1 + i2, 1 + i0 + i1] : N >= 3 and i2 <= 3 + 5outerProcTileScatter1 - i0 - i1 and i1 >= -1 + 5outerProcTileScatter2 - i0 and M >= 2 and i2 <= 4 + 5outerTimeTileScatter - 2i0 - i1 and i1 <= 3 + 5outerProcTileScatter2 - i0 and i2 >= 1 and i2 <= -2 + N and i1 >= 1 and i1 <= -2 + N and i0 >= 1 and i0 <= -1 + M and i2 >= 5outerTimeTileScatter - 2i0 - i1 and i2 >= -1 + 5outerProcTileScatter1 - i0 - i1 }
+[outerTimeTileScatter, outerProcTileScatter1, outerProcTileScatter2, M, N] -> {  :  }
+[outerTimeTileScatter, outerProcTileScatter1, outerProcTileScatter2, M, N] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/constant.c b/test_inputs/codegen/cloog/constant.c
new file mode 100644 (file)
index 0000000..b828143
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  for (int c1 = 0; c1 <= min(1023, M + 1024); c1 += 1) {
+    S1(c1);
+    S3(c1);
+  }
+  for (int c1 = max(M + 1025, 0); c1 <= 1023; c1 += 1) {
+    S2(c1);
+    S3(c1);
+  }
+  for (int c0 = 0; c0 <= min(1023, M + 1024); c0 += 1) {
+    S4(c0);
+    S6(c0);
+  }
+  for (int c0 = max(M + 1025, 0); c0 <= 1023; c0 += 1) {
+    S5(c0);
+    S6(c0);
+  }
+}
diff --git a/test_inputs/codegen/cloog/constant.in b/test_inputs/codegen/cloog/constant.in
new file mode 100644 (file)
index 0000000..7cd365a
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S5[i0] -> [i0, 0, 1] : i0 >= 0 and i0 <= 1023 and i0 >= 1025 + M; S1[i0] -> [-1, i0, 0] : i0 >= 0 and i0 <= 1023 and i0 <= 1024 + M; S3[i0] -> [-1, i0, 2] : i0 >= 0 and i0 <= 1023; S2[i0] -> [-1, i0, 1] : i0 >= 0 and i0 <= 1023 and i0 >= 1025 + M; S4[i0] -> [i0, 0, 0] : i0 >= 0 and i0 <= 1023 and i0 <= 1024 + M; S6[i0] -> [i0, 0, 2] : i0 >= 0 and i0 <= 1023 }
+[M] -> {  :  }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/constbound.c b/test_inputs/codegen/cloog/constbound.c
new file mode 100644 (file)
index 0000000..219165d
--- /dev/null
@@ -0,0 +1,8 @@
+for (int c0 = 0; c0 <= 199; c0 += 1) {
+  for (int c2 = 50 * c0; c2 <= 50 * c0 + 24; c2 += 1)
+    for (int c3 = 0; c3 <= c2; c3 += 1)
+      S1(c0, c2, c3);
+  for (int c2 = 50 * c0 + 25; c2 <= 50 * c0 + 49; c2 += 1)
+    for (int c3 = 0; c3 <= c2; c3 += 1)
+      S2(c0, c2, c3);
+}
diff --git a/test_inputs/codegen/cloog/constbound.in b/test_inputs/codegen/cloog/constbound.in
new file mode 100644 (file)
index 0000000..24727a8
--- /dev/null
@@ -0,0 +1,3 @@
+{ S2[i0, i1, i2] -> [i0, 1, i1, i2] : i1 >= 0 and i1 <= 9999 and i2 >= 0 and i2 <= i1 and i1 >= 25 + 50i0 and i1 <= 49 + 50i0; S1[i0, i1, i2] -> [i0, 0, i1, i2] : i1 >= 0 and i1 <= 9999 and i2 >= 0 and i2 <= i1 and i1 >= 50i0 and i1 <= 24 + 50i0 }
+{  :  }
+{ [i, j, k, l] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/darte.c b/test_inputs/codegen/cloog/darte.c
new file mode 100644 (file)
index 0000000..208aafb
--- /dev/null
@@ -0,0 +1,14 @@
+for (int c0 = -n + 1; c0 <= n; c0 += 1) {
+  if (c0 <= 0)
+    for (int c2 = -c0 + 4; c2 <= 2 * n - c0 + 2; c2 += 2)
+      S1(1, -c0 + 1, (c0 + c2 - 2) / 2);
+  for (int c1 = max(-c0 + 4, c0 + 2); c1 <= min(2 * n + c0, 2 * n - c0); c1 += 2) {
+    for (int c2 = c1 + 2; c2 <= 2 * n + c1; c2 += 2)
+      S1((c0 + c1) / 2, (-c0 + c1) / 2, (-c1 + c2) / 2);
+    for (int c2 = 1; c2 <= n; c2 += 1)
+      S2((c0 + c1 - 2) / 2, (-c0 + c1) / 2, c2);
+  }
+  if (c0 >= 1)
+    for (int c2 = 1; c2 <= n; c2 += 1)
+      S2(n, n - c0 + 1, c2);
+}
diff --git a/test_inputs/codegen/cloog/darte.in b/test_inputs/codegen/cloog/darte.in
new file mode 100644 (file)
index 0000000..55897a5
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { S2[i0, i1, i2] -> [1 + i0 - i1, 2 + i0 + i1, i2] : i0 >= 1 and i0 <= n and i1 >= 1 and i1 <= n and i2 >= 1 and i2 <= n; S1[i0, i1, i2] -> [i0 - i1, i0 + i1, i0 + i1 + 2i2] : i0 >= 1 and i0 <= n and i1 >= 1 and i1 <= n and i2 >= 1 and i2 <= n }
+[n] -> {  :  }
+[n] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/dealII.c b/test_inputs/codegen/cloog/dealII.c
new file mode 100644 (file)
index 0000000..87a8098
--- /dev/null
@@ -0,0 +1,12 @@
+{
+  for (int c0 = 0; c0 <= min(T_2 - 1, T_66); c0 += 1) {
+    S1(c0);
+    S2(c0);
+  }
+  for (int c0 = max(T_66 + 1, 0); c0 <= T_2 - 1; c0 += 1)
+    S1(c0);
+  if (T_67 == 0 && T_2 == 0)
+    S1(0);
+  for (int c0 = T_2; c0 <= min(T_66, T_67 - 1); c0 += 1)
+    S2(c0);
+}
diff --git a/test_inputs/codegen/cloog/dealII.in b/test_inputs/codegen/cloog/dealII.in
new file mode 100644 (file)
index 0000000..fc0310b
--- /dev/null
@@ -0,0 +1,3 @@
+[T_2, T_67, T_66] -> { S1[scat_0] -> [scat_0, 0] : (scat_0 <= -1 + T_2 and scat_0 >= 0) or (scat_0 <= -T_67 and scat_0 >= 0); S2[scat_0] -> [scat_0, 1] : (scat_0 <= -1 + T_2 and scat_0 >= 0 and scat_0 <= T_66) or (scat_0 <= -1 + T_67 and scat_0 >= 0 and scat_0 <= T_66) }
+[T_2, T_67, T_66] -> {  : T_2 <= 4 and T_2 >= 0 and T_67 <= 4 and T_67 >= 0 }
+[T_2, T_67, T_66] -> { [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/donotsimp.c b/test_inputs/codegen/cloog/donotsimp.c
new file mode 100644 (file)
index 0000000..4c482e2
--- /dev/null
@@ -0,0 +1,6 @@
+for (int c1 = 1; c1 <= 10; c1 += 1) {
+  for (int c3 = 1; c3 <= c1; c3 += 1)
+    S1(c1, c3);
+  for (int c3 = 11; c3 <= M; c3 += 1)
+    S2(c1, c3);
+}
diff --git a/test_inputs/codegen/cloog/donotsimp.in b/test_inputs/codegen/cloog/donotsimp.in
new file mode 100644 (file)
index 0000000..c1541cc
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [0, i0, 0, i1, 0] : i0 >= 1 and i0 <= 10 and i1 >= 11 and i1 <= M; S1[i0, i1] -> [0, i0, 0, i1, 0] : i0 >= 1 and i0 <= 10 and i1 >= 1 and i1 <= i0 }
+[M] -> {  : M >= 20 }
+[M] -> { [i, j, k, l, m] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/dot.c b/test_inputs/codegen/cloog/dot.c
new file mode 100644 (file)
index 0000000..b08de33
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    S1(0, c1);
+  for (int c0 = 1; c0 <= N; c0 += 1)
+    for (int c1 = 1; c1 <= M; c1 += 1)
+      S2(c0, c1);
+}
diff --git a/test_inputs/codegen/cloog/dot.in b/test_inputs/codegen/cloog/dot.in
new file mode 100644 (file)
index 0000000..37e1f14
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S1[0, i1] -> [0, i1, 0] : i1 <= M and N >= 0 and i1 >= 1; S2[i0, i1] -> [i0, i1, 1] : i0 >= 1 and i1 <= M and i0 <= N and i1 >= 1 }
+[M, N] -> {  : M >= 1 and N >= 1 }
+[M, N] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/dot2.c b/test_inputs/codegen/cloog/dot2.c
new file mode 100644 (file)
index 0000000..f36aae2
--- /dev/null
@@ -0,0 +1,12 @@
+{
+  for (int c0 = 1; c0 <= min(N, M); c0 += 1) {
+    S1(c0);
+    for (int c1 = 1; c1 <= M; c1 += 1)
+      S2(c0, c1);
+  }
+  for (int c0 = M + 1; c0 <= N; c0 += 1)
+    for (int c1 = 1; c1 <= M; c1 += 1)
+      S2(c0, c1);
+  for (int c0 = N + 1; c0 <= M; c0 += 1)
+    S1(c0);
+}
diff --git a/test_inputs/codegen/cloog/dot2.in b/test_inputs/codegen/cloog/dot2.in
new file mode 100644 (file)
index 0000000..8fa8381
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S2[i0, i1] -> [i0, i1, 1] : i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= M; S1[i0] -> [i0, 0, 0] : i0 >= 1 and i0 <= M }
+[M, N] -> {  : M >= 1 and N >= 1 }
+[M, N] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/durbin_e_s.c b/test_inputs/codegen/cloog/durbin_e_s.c
new file mode 100644 (file)
index 0000000..a47d319
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  S4(1, 0, 0);
+  S7(1, 0, 0);
+  S8(1, 0, 3);
+  for (int c0 = 2; c0 <= 9; c0 += 1) {
+    S2(c0, -7, 0);
+    for (int c1 = -7; c1 <= c0 - 9; c1 += 1)
+      S3(c0, c1, 1);
+    S6(c0, c0 - 9, 2);
+    S8(c0, 0, 3);
+    for (int c1 = 1; c1 <= c0 - 1; c1 += 1)
+      S5(c0, c1, 3);
+  }
+  S2(10, -7, 0);
+  for (int c1 = -7; c1 <= 1; c1 += 1)
+    S3(10, c1, 1);
+  S6(10, 1, 2);
+  for (int c1 = 1; c1 <= 9; c1 += 1) {
+    S5(10, c1, 3);
+    S1(10, c1, 4);
+  }
+  S1(10, 10, 4);
+}
diff --git a/test_inputs/codegen/cloog/durbin_e_s.in b/test_inputs/codegen/cloog/durbin_e_s.in
new file mode 100644 (file)
index 0000000..77d32ad
--- /dev/null
@@ -0,0 +1,3 @@
+{ S5[i0, i1, 3] -> [i0, i1, 3, 4] : i1 <= -1 + i0 and i0 <= 10 and i1 >= 1; S8[i0, 0, 3] -> [i0, 0, 3, 7] : i0 >= 1 and i0 <= 9; S2[i0, -7, 0] -> [i0, -7, 0, 1] : i0 >= 2 and i0 <= 10; S3[i0, i1, 1] -> [i0, i1, 1, 2] : i1 >= -7 and i0 <= 10 and i1 <= -9 + i0; S1[10, i1, 4] -> [10, i1, 4, 0] : i1 >= 1 and i1 <= 10; S7[1, 0, 0] -> [1, 0, 0, 6]; S4[1, 0, 0] -> [1, 0, 0, 3]; S6[i0, -9 + i0, 2] -> [i0, -9 + i0, 2, 5] : i0 >= 2 and i0 <= 10 }
+{  :  }
+{ [i, j, k, l] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/emploi.c b/test_inputs/codegen/cloog/emploi.c
new file mode 100644 (file)
index 0000000..80ee37d
--- /dev/null
@@ -0,0 +1,5 @@
+for (int c0 = 1; c0 <= n; c0 += 1) {
+  S1(c0);
+  for (int c1 = 1; c1 <= m; c1 += 1)
+    S2(c0, c1);
+}
diff --git a/test_inputs/codegen/cloog/emploi.in b/test_inputs/codegen/cloog/emploi.in
new file mode 100644 (file)
index 0000000..5701662
--- /dev/null
@@ -0,0 +1,3 @@
+[m, n] -> { S1[i0] -> [i0, 0, 0] : (i0 >= 1 and i0 <= n and i0 <= 2m) or (i0 >= 1 and i0 <= n and i0 >= m); S2[i0, i1] -> [i0, i1, 1] : i0 >= 1 and i0 <= n and i1 >= 1 and i1 <= m }
+[m, n] -> {  :  }
+[m, n] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/equality.c b/test_inputs/codegen/cloog/equality.c
new file mode 100644 (file)
index 0000000..2535b8b
--- /dev/null
@@ -0,0 +1,7 @@
+for (int c0 = 0; c0 <= 5; c0 += 1)
+  for (int c1 = c0 <= 2 ? 2 * c0 : 4; c1 <= (c0 >= 2 ? 2 * c0 : 4); c1 += 1) {
+    if (c1 == 2 * c0)
+      S1(c0, 2 * c0);
+    if (c1 == 4)
+      S2(c0, 4);
+  }
diff --git a/test_inputs/codegen/cloog/equality.in b/test_inputs/codegen/cloog/equality.in
new file mode 100644 (file)
index 0000000..677fa90
--- /dev/null
@@ -0,0 +1,3 @@
+{ S1[i0, 2i0] -> [i0, 2i0, 0] : i0 >= 0 and i0 <= 5; S2[i0, 4] -> [i0, 4, 1] : i0 >= 0 and i0 <= 5 }
+{  :  }
+{ [i, j, k] -> atomic[o0] }
diff --git a/test_inputs/codegen/cloog/equality2.c b/test_inputs/codegen/cloog/equality2.c
new file mode 100644 (file)
index 0000000..a9d2d9c
--- /dev/null
@@ -0,0 +1,8 @@
+for (int c0 = 1; c0 <= 10000; c0 += 1)
+  for (int c1 = 1000; c1 <= 1016; c1 += 1)
+    for (int c2 = 1; c2 <= 2 * c1 - 1999; c2 += 1) {
+      if (c2 + 1999 == 2 * c1 && c1 <= 1008)
+        S2(c0, c1, 2 * c1 - 1999, 1, c0, 2 * c1 - 1000, 1, 2, c0, c1 - 499, 2 * c1 - 1999, c0, 2 * c1 - 1999, c1 - 999, c1 - 999);
+      if (c1 % 2 == 0 && c2 == 1)
+        S1(c0, c1, 1, 2, c0, (c1 + 2) / 2, c1 - 999, c0, c1 - 999, (c1 - 998) / 2, (c1 - 998) / 2);
+    }
diff --git a/test_inputs/codegen/cloog/equality2.in b/test_inputs/codegen/cloog/equality2.in
new file mode 100644 (file)
index 0000000..95b3f79
--- /dev/null
@@ -0,0 +1,3 @@
+{ S1[i0, i1, 1, 2, i0, i5, -999 + i1, i0, -999 + i1, i9, i10] -> [i0, i1, 1, 2, i0, n, -999 + i1, i0, -999 + i1, r, s, 0, 0, 0, 0, 0] : 2s = -998 + i1 and 2n = 2 + i1 and 2i10 = -998 + i1 and 2i5 = 2 + i1 and 2i9 = -998 + i1 and 2r = -998 + i1 and i0 >= 1 and i0 <= 10000 and i1 >= 1000 and i1 <= 1016; S2[i0, i1, -1999 + 2i1, 1, i0, -1000 + 2i1, 1, 2, i0, -499 + i1, -1999 + 2i1, i0, -1999 + 2i1, -999 + i1, -999 + i1] -> [i0, i1, -1999 + 2i1, 1, i0, -1000 + 2i1, 1, 2, i0, -499 + i1, -1999 + 2i1, i0, -1999 + 2i1, -999 + i1, -999 + i1, 1] : i0 >= 1 and i0 <= 10000 and i1 >= 1000 and i1 <= 1008 }
+{  :  }
+{ [i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x] -> atomic[o0] }
diff --git a/test_inputs/codegen/cloog/esced.c b/test_inputs/codegen/cloog/esced.c
new file mode 100644 (file)
index 0000000..f7c7ee0
--- /dev/null
@@ -0,0 +1,5 @@
+for (int c0 = 1; c0 <= m; c0 += 1) {
+  S1(c0);
+  for (int c1 = 1; c1 <= n; c1 += 1)
+    S2(c0, c1);
+}
diff --git a/test_inputs/codegen/cloog/esced.in b/test_inputs/codegen/cloog/esced.in
new file mode 100644 (file)
index 0000000..3bef6fd
--- /dev/null
@@ -0,0 +1,3 @@
+[n, m] -> { S1[i0] -> [i0, 0, 0] : i0 >= 1 and i0 <= m; S2[i0, i1] -> [i0, i1, 1] : i0 >= 1 and i0 <= m and i1 >= 1 and i1 <= n }
+[n, m] -> {  :  }
+[n, m] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/ex1.c b/test_inputs/codegen/cloog/ex1.c
new file mode 100644 (file)
index 0000000..36ac7d9
--- /dev/null
@@ -0,0 +1,15 @@
+{
+  for (int c0 = 0; c0 <= 14; c0 += 1)
+    for (int c1 = 0; c1 <= n - 15; c1 += 1)
+      S1(c0, c1);
+  for (int c0 = 15; c0 <= n; c0 += 1) {
+    for (int c1 = 0; c1 <= 9; c1 += 1)
+      S1(c0, c1);
+    for (int c1 = 10; c1 <= n - 15; c1 += 1) {
+      S1(c0, c1);
+      S2(c0, c1);
+    }
+    for (int c1 = n - 14; c1 <= n; c1 += 1)
+      S2(c0, c1);
+  }
+}
diff --git a/test_inputs/codegen/cloog/ex1.in b/test_inputs/codegen/cloog/ex1.in
new file mode 100644 (file)
index 0000000..457b834
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { S2[i0, i1] -> [i0, i1, 1] : i0 >= 15 and i0 <= n and i1 >= 10 and i1 <= n; S1[i0, i1] -> [i0, i1, 0] : i0 >= 0 and i0 <= n and i1 >= 0 and i1 <= -15 + n }
+[n] -> {  : n >= 25 }
+[n] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/forwardsub-1-1-2.c b/test_inputs/codegen/cloog/forwardsub-1-1-2.c
new file mode 100644 (file)
index 0000000..ac071b4
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  S3(1, 1);
+  for (int c0 = 2; c0 <= M; c0 += 1) {
+    S1(c0, 1);
+    for (int c1 = 2; c1 <= c0 - 1; c1 += 1)
+      S2(c0, c1);
+    S4(c0, c0);
+  }
+}
diff --git a/test_inputs/codegen/cloog/forwardsub-1-1-2.in b/test_inputs/codegen/cloog/forwardsub-1-1-2.in
new file mode 100644 (file)
index 0000000..ede8856
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [i0, i1, 1] : i1 <= -1 + i0 and i1 >= 2 and i0 <= M; S4[i0, i0] -> [i0, i0, 3] : M >= 3 and i0 <= M and i0 >= 2; S1[i0, 1] -> [i0, 1, 0] : M >= 3 and i0 <= M and i0 >= 2; S3[1, 1] -> [1, 1, 2] : M >= 3 }
+[M] -> {  : M >= 3 }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/forwardsub-2-1-2-3.c b/test_inputs/codegen/cloog/forwardsub-2-1-2-3.c
new file mode 100644 (file)
index 0000000..cfc3e7d
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  S3(1, 0);
+  for (int c2 = 2; c2 <= M; c2 += 1)
+    S1(1, 1, c2);
+  for (int c0 = 2; c0 <= M; c0 += 1) {
+    S4(c0, 0);
+    for (int c2 = c0 + 1; c2 <= M; c2 += 1)
+      S2(c0, 1, c2);
+  }
+}
diff --git a/test_inputs/codegen/cloog/forwardsub-2-1-2-3.in b/test_inputs/codegen/cloog/forwardsub-2-1-2-3.in
new file mode 100644 (file)
index 0000000..57863cc
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[1, 1, i2] -> [1, 1, i2, 0] : M >= 3 and i2 <= M and i2 >= 2; S2[i0, 1, i2] -> [i0, 1, i2, 1] : i2 >= 1 + i0 and i0 >= 2 and i2 <= M; S4[i0, 0] -> [i0, 0, 0, 3] : i0 >= 2 and M >= 3 and i0 <= M; S3[1, 0] -> [1, 0, 0, 2] : M >= 3 }
+[M] -> {  : M >= 3 }
+[M] -> { [i, j, k, l] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/forwardsub-3-1-2.c b/test_inputs/codegen/cloog/forwardsub-3-1-2.c
new file mode 100644 (file)
index 0000000..d84fae8
--- /dev/null
@@ -0,0 +1,17 @@
+{
+  S3(2, 1);
+  S1(3, 1);
+  for (int c0 = 4; c0 <= M + 1; c0 += 1) {
+    S1(c0, 1);
+    for (int c1 = 2; c1 <= (c0 + 1) / 2 - 1; c1 += 1)
+      S2(c0, c1);
+    if (c0 % 2 == 0)
+      S4(c0, c0 / 2);
+  }
+  for (int c0 = M + 2; c0 <= 2 * M; c0 += 1) {
+    for (int c1 = -M + c0; c1 <= (c0 + 1) / 2 - 1; c1 += 1)
+      S2(c0, c1);
+    if (c0 % 2 == 0)
+      S4(c0, c0 / 2);
+  }
+}
diff --git a/test_inputs/codegen/cloog/forwardsub-3-1-2.in b/test_inputs/codegen/cloog/forwardsub-3-1-2.in
new file mode 100644 (file)
index 0000000..c40383d
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [i0, i1, 1] : 2i1 <= -1 + i0 and i1 >= 2 and i1 >= -M + i0; S4[i0, i1] -> [i0, j, 3] : 2j = i0 and 2i1 = i0 and M >= 3 and i0 <= 2M and i0 >= 4; S1[i0, 1] -> [i0, 1, 0] : M >= 3 and i0 <= 1 + M and i0 >= 3; S3[2, 1] -> [2, 1, 2] : M >= 3 }
+[M] -> {  : M >= 3 }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/gauss.c b/test_inputs/codegen/cloog/gauss.c
new file mode 100644 (file)
index 0000000..7b7a431
--- /dev/null
@@ -0,0 +1,7 @@
+for (int c0 = 1; c0 <= M - 1; c0 += 1)
+  for (int c1 = c0 + 1; c1 <= M; c1 += 1) {
+    for (int c3 = 1; c3 <= c0 - 1; c3 += 1)
+      S1(c0, c3, c1);
+    for (int c3 = c0 + 1; c3 <= M; c3 += 1)
+      S2(c0, c3, c1);
+  }
diff --git a/test_inputs/codegen/cloog/gauss.in b/test_inputs/codegen/cloog/gauss.in
new file mode 100644 (file)
index 0000000..439e72e
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1, i2] -> [i0, i2] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= -1 + i0 and i2 >= 1 + i0 and i2 <= M; S2[i0, i1, i2] -> [i0, i2] : i0 >= 1 and i0 <= M and i1 >= 1 + i0 and i1 <= M and i2 >= 1 + i0 and i2 <= M }
+[M] -> {  :  }
+[M] -> { [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/gesced.c b/test_inputs/codegen/cloog/gesced.c
new file mode 100644 (file)
index 0000000..a36715c
--- /dev/null
@@ -0,0 +1,16 @@
+{
+  for (int c0 = 1; c0 <= N; c0 += 1)
+    S1(c0);
+  for (int c0 = N + 1; c0 <= 2 * N; c0 += 1)
+    for (int c1 = 1; c1 <= N; c1 += 1)
+      S2(c1, -N + c0);
+  for (int c0 = 2 * N + 1; c0 <= M + N; c0 += 1) {
+    for (int c1 = 1; c1 <= N; c1 += 1)
+      S3(c1, -2 * N + c0);
+    for (int c1 = 1; c1 <= N; c1 += 1)
+      S2(c1, -N + c0);
+  }
+  for (int c0 = M + N + 1; c0 <= M + 2 * N; c0 += 1)
+    for (int c1 = 1; c1 <= N; c1 += 1)
+      S3(c1, -2 * N + c0);
+}
diff --git a/test_inputs/codegen/cloog/gesced.in b/test_inputs/codegen/cloog/gesced.in
new file mode 100644 (file)
index 0000000..6043f4b
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S3[i0, i1] -> [2N + i1] : i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= M; S2[i0, i1] -> [N + i1] : i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= M; S1[i0] -> [i0] : i0 >= 1 and i0 <= N }
+[M, N] -> {  : N <= M and M >= 2 and N >= 2 }
+[M, N] -> { [i] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/gesced2.c b/test_inputs/codegen/cloog/gesced2.c
new file mode 100644 (file)
index 0000000..a0fa2bf
--- /dev/null
@@ -0,0 +1,20 @@
+{
+  for (int c0 = 1; c0 <= 4; c0 += 1)
+    for (int c1 = 5; c1 <= M - 10; c1 += 1)
+      S1(c0, c1);
+  for (int c0 = 5; c0 <= M - 10; c0 += 1) {
+    for (int c1 = -c0 + 1; c1 <= 4; c1 += 1)
+      S2(c0 + c1, c0);
+    for (int c1 = 5; c1 <= min(M - c0, M - 10); c1 += 1) {
+      S1(c0, c1);
+      S2(c0 + c1, c0);
+    }
+    for (int c1 = M - c0 + 1; c1 <= M - 10; c1 += 1)
+      S1(c0, c1);
+    for (int c1 = M - 9; c1 <= M - c0; c1 += 1)
+      S2(c0 + c1, c0);
+  }
+  for (int c0 = M - 9; c0 <= M; c0 += 1)
+    for (int c1 = 5; c1 <= M - 10; c1 += 1)
+      S1(c0, c1);
+}
diff --git a/test_inputs/codegen/cloog/gesced2.in b/test_inputs/codegen/cloog/gesced2.in
new file mode 100644 (file)
index 0000000..a5d5bd2
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1] -> [i0, i1] : i0 >= 1 and i0 <= M and i1 >= 5 and i1 <= -10 + M; S2[i0, i1] -> [i1, i0 - i1] : i0 >= 1 and i0 <= M and i1 >= 5 and i1 <= -10 + M }
+[M] -> {  : M >= 16 }
+[M] -> { [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/gesced3.c b/test_inputs/codegen/cloog/gesced3.c
new file mode 100644 (file)
index 0000000..c163ed0
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  for (int c0 = M + 1; c0 <= 2 * M; c0 += 1)
+    S1(-M + c0);
+  for (int c0 = 2 * M + 1; c0 <= M + N; c0 += 1) {
+    S2(-2 * M + c0);
+    S1(-M + c0);
+  }
+  for (int c0 = M + N + 1; c0 <= 2 * M + N; c0 += 1)
+    S2(-2 * M + c0);
+}
diff --git a/test_inputs/codegen/cloog/gesced3.in b/test_inputs/codegen/cloog/gesced3.in
new file mode 100644 (file)
index 0000000..29f57f3
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S2[i0] -> [2M + i0] : i0 >= 1 and i0 <= N; S1[i0] -> [M + i0] : i0 >= 1 and i0 <= N }
+[M, N] -> {  : N >= M and M >= 2 }
+[M, N] -> { [i] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/guide.c b/test_inputs/codegen/cloog/guide.c
new file mode 100644 (file)
index 0000000..bc48f1e
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  for (int c0 = 1; c0 <= N; c0 += 1)
+    S1(c0);
+  for (int c0 = N + 1; c0 <= 2 * N; c0 += 1)
+    S2(c0);
+}
diff --git a/test_inputs/codegen/cloog/guide.in b/test_inputs/codegen/cloog/guide.in
new file mode 100644 (file)
index 0000000..38c418c
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0] -> [i0, 0] : (i0 >= 1 and i0 <= N and i0 <= 2M) or (i0 >= 1 and i0 <= N and i0 >= M); S2[i0] -> [i0, 1] : i0 >= 1 + N and i0 <= 2N }
+[M, N] -> {  :  }
+[M, N] -> { [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/iftest.c b/test_inputs/codegen/cloog/iftest.c
new file mode 100644 (file)
index 0000000..0f41fb7
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = 1; c0 <= n; c0 += 1)
+  S1(c0);
diff --git a/test_inputs/codegen/cloog/iftest.in b/test_inputs/codegen/cloog/iftest.in
new file mode 100644 (file)
index 0000000..741399d
--- /dev/null
@@ -0,0 +1,3 @@
+[m, n] -> { S1[i0] -> [i0, 0] : (i0 >= 1 and i0 <= n and i0 >= m) or (i0 >= 1 and i0 <= n and i0 <= 2m) }
+[m, n] -> {  :  }
+[m, n] -> { [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/iftest2.c b/test_inputs/codegen/cloog/iftest2.c
new file mode 100644 (file)
index 0000000..8e3e4c1
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= N; c0 += 1)
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    S1(c0, c1);
diff --git a/test_inputs/codegen/cloog/iftest2.in b/test_inputs/codegen/cloog/iftest2.in
new file mode 100644 (file)
index 0000000..a2e3212
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0, i1] -> [i0, i1, 0] : (i0 >= 1 and i0 <= N and i0 >= M and i1 >= 1 and i1 <= M) or (i0 >= 1 and i0 <= N and i0 <= 2M and i1 >= 1 and i1 <= M) }
+[M, N] -> {  :  }
+[M, N] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/infinite2.c b/test_inputs/codegen/cloog/infinite2.c
new file mode 100644 (file)
index 0000000..bbb6d6e
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  for (int c0 = 1; c0 <= N; c0 += 1) {
+    S1(c0);
+    for (int c1 = 1; c1 <= M; c1 += 1)
+      S2(c0, c1);
+  }
+  for (int c0 = N + 1; 1; c0 += 1)
+    S1(c0);
+}
diff --git a/test_inputs/codegen/cloog/infinite2.in b/test_inputs/codegen/cloog/infinite2.in
new file mode 100644 (file)
index 0000000..64fb5d5
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S2[i0, i1] -> [i0, i1, 1] : i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= M; S1[i0] -> [i0, 0, 0] : i0 >= 1 }
+[M, N] -> {  : M >= 1 and N >= 1 }
+[M, N] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/jacobi-shared.c b/test_inputs/codegen/cloog/jacobi-shared.c
new file mode 100644 (file)
index 0000000..fda697d
--- /dev/null
@@ -0,0 +1,3 @@
+if (2 * floord(h0 - 1, 2) + 1 == h0 && t1 >= 32 * floord(-g2 + t1 - 1, 32) + 3 && N + 32 * floord(-g2 + t1 - 1, 32) >= t1 + 1)
+  for (int c0 = max(t0 - 16 * floord(t0 - 1, 16), t0 - 16 * floord(g1 + t0 - 3, 16)); c0 <= min(32, N - g1 - 1); c0 += 16)
+    S1(g1 + c0 - 1, g2 + t1 + 32 * floord(-t1, 32) + 31);
diff --git a/test_inputs/codegen/cloog/jacobi-shared.in b/test_inputs/codegen/cloog/jacobi-shared.in
new file mode 100644 (file)
index 0000000..d615324
--- /dev/null
@@ -0,0 +1,3 @@
+[T, N, h0, b0, b1, g0, g1, g2, g3, g4, t0, t1] -> { S1[i0, i1] -> [1 - g1 + i0, 1 - g2 + i1, t0, t1] : exists (e0 = [(-1 + h0)/2], e1 = [(-2016b0 - g1)/2048], e2 = [(-992b1 - g2)/1024], e3 = [(-1 + t0 - i0)/16], e4 = [(-1 + t1 - i1)/32]: g0 = h0 and 2e0 = -1 + h0 and 2048e1 = -2016b0 - g1 and 1024e2 = -992b1 - g2 and 16e3 = -1 + t0 - i0 and 32e4 = -1 + t1 - i1 and h0 >= 1 and h0 <= -1 + 2T and i0 >= 2 and i0 <= -2 + N and i1 >= 2 and i1 <= -2 + N and b1 <= 31 and b1 >= 0 and b0 <= 63 and b0 >= 0 and i1 <= 31 + g2 and i1 >= g2 and N >= 4 and i0 >= g1 and i0 <= 31 + g1 and g2 <= -2 + N and g2 >= -29 and g1 <= -2 + N and g1 >= -29 and g1 >= 32b0 and g2 >= 32b1 and 32b0 <= -2 + N and 32b1 <= -2 + N and t0 >= 0 and t0 <= 15 and t1 >= 0 and t1 <= 31) }
+[T, N, h0, b0, b1, g0, g1, g2, g3, g4, t0, t1] -> {  : exists (e0 = [(-32b0 + g1)/2048], e1 = [(-32b1 + g2)/1024]: g0 = h0 and 2048e0 = -32b0 + g1 and 1024e1 = -32b1 + g2 and g2 <= -2 + N and g2 >= -29 and g1 <= -2 + N and g1 >= -29 and b1 >= 0 and b1 <= 31 and b0 <= 63 and 32b1 <= -2 + N and 32b0 <= -2 + N and b0 >= 0 and N >= 4 and h0 >= 0 and h0 <= -1 + 2T and g2 >= 32b1 and g1 >= 32b0 and t0 >= 0 and t0 <= 15 and t1 >= 0 and t1 <= 31) }
+[T, N, h0, b0, b1, g0, g1, g2, g3, g4, t0, t1] -> { [i, j, k, l] -> separate[x] : x >= 3 }
diff --git a/test_inputs/codegen/cloog/largeur.c b/test_inputs/codegen/cloog/largeur.c
new file mode 100644 (file)
index 0000000..faced0a
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= M; c0 += 1)
+  for (int c1 = 1; c1 <= c0; c1 += 1)
+    S1(c1, c0);
diff --git a/test_inputs/codegen/cloog/largeur.in b/test_inputs/codegen/cloog/largeur.in
new file mode 100644 (file)
index 0000000..3a25146
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1] -> [i1, i0] : i0 >= 1 and i0 <= M and i1 >= i0 and i1 <= M }
+[M] -> {  : M >= 0 }
+[M] -> { [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/levenshtein-1-2-3.c b/test_inputs/codegen/cloog/levenshtein-1-2-3.c
new file mode 100644 (file)
index 0000000..627eab7
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  S1(0, 0);
+  for (int c0 = 1; c0 <= N; c0 += 1) {
+    S2(c0, 0);
+    for (int c1 = 1; c1 <= c0 - 1; c1 += 1)
+      S6(c0, c1);
+    S3(c0, c0);
+  }
+  S7(N + 1, 0);
+  for (int c1 = 1; c1 <= N; c1 += 1) {
+    S6(N + 1, c1);
+    S8(N + 1, c1);
+  }
+  for (int c0 = N + 2; c0 <= 2 * M - N - 2; c0 += 1) {
+    S7(c0, -N + (N + c0 + 1) / 2 - 1);
+    if ((-N + c0) % 2 == 0) {
+      S5(c0, (-N + c0) / 2);
+      S8(c0, (-N + c0) / 2);
+    }
+    for (int c1 = c0 - (N + c0 + 1) / 2 + 1; c1 <= (N + c0 + 1) / 2 - 1; c1 += 1) {
+      S6(c0, c1);
+      S8(c0, c1);
+    }
+    if ((-N + c0) % 2 == 0) {
+      S4(c0, (N + c0) / 2);
+      S8(c0, (N + c0) / 2);
+    }
+  }
+  for (int c0 = 2 * M - N - 1; c0 <= 2 * M - 2; c0 += 1)
+    for (int c1 = -M + c0 + 1; c1 <= M - 1; c1 += 1)
+      S6(c0, c1);
+}
diff --git a/test_inputs/codegen/cloog/levenshtein-1-2-3.in b/test_inputs/codegen/cloog/levenshtein-1-2-3.in
new file mode 100644 (file)
index 0000000..dc94464
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S8[i0, i1] -> [i0, i1, 7] : i0 >= 1 + N and 2i1 <= N + i0 and 2i1 >= -N + i0 and i0 <= -2 + 2M - N and N <= -2 + M and N >= 1; S1[0, 0] -> [0, 0, 0] : N <= -2 + M and N >= 1; S5[i0, i1] -> [i0, j, 4] : 2j = -N + i0 and 2i1 = -N + i0 and i0 >= 2 + N and i0 <= -2 + 2M - N and N >= 1; S7[i0, i1] -> [i0, i1, 6] : i0 >= 1 + N and 2i1 <= -1 - N + i0 and i0 <= -2 + 2M - N and 2i1 >= -2 - N + i0 and N <= -2 + M and N >= 1; S2[i0, 0] -> [i0, 0, 1] : i0 >= 1 and i0 <= N and N <= -2 + M; S3[i0, i0] -> [i0, i0, 2] : i0 >= 1 and i0 <= N and N <= -2 + M; S4[i0, i1] -> [i0, j, 3] : 2j = N + i0 and 2i1 = N + i0 and i0 >= 2 + N and i0 <= -2 + 2M - N and N >= 1; S6[i0, i1] -> [i0, i1, 5] : 2i1 <= -1 + N + i0 and i1 <= -1 + i0 and i1 >= 1 - M + i0 and 2i1 >= 1 - N + i0 and i1 >= 1 and i1 <= -1 + M and N <= -2 + M }
+[M, N] -> {  : N <= -2 + M and N >= 1 }
+[M, N] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/lex.c b/test_inputs/codegen/cloog/lex.c
new file mode 100644 (file)
index 0000000..e81e97e
--- /dev/null
@@ -0,0 +1,4 @@
+for (int c0 = 0; c0 <= 10; c0 += 1) {
+  S2(c0);
+  S1(c0);
+}
diff --git a/test_inputs/codegen/cloog/lex.in b/test_inputs/codegen/cloog/lex.in
new file mode 100644 (file)
index 0000000..7a268b6
--- /dev/null
@@ -0,0 +1,3 @@
+{ S2[i0] -> [i0, -1, 0] : i0 >= 0 and i0 <= 10; S1[i0] -> [i0, 0, 0] : i0 >= 0 and i0 <= 10 }
+{  :  }
+{ [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/lineality-1-2.c b/test_inputs/codegen/cloog/lineality-1-2.c
new file mode 100644 (file)
index 0000000..b2921f1
--- /dev/null
@@ -0,0 +1,8 @@
+for (int c0 = 1; c0 <= M; c0 += 1) {
+  for (int c1 = 1; c1 <= c0 - 1; c1 += 1)
+    S1(c0, c1);
+  S1(c0, c0);
+  S2(c0, c0);
+  for (int c1 = c0 + 1; c1 <= M; c1 += 1)
+    S1(c0, c1);
+}
diff --git a/test_inputs/codegen/cloog/lineality-1-2.in b/test_inputs/codegen/cloog/lineality-1-2.in
new file mode 100644 (file)
index 0000000..b7d06d0
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i0] -> [i0, i0, 1] : i0 >= 1 and i0 <= M; S1[i0, i1] -> [i0, i1, 0] : i0 >= 1 and i1 >= 1 and i0 <= M and i1 <= M }
+[M] -> {  : M >= 2 }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/lineality-2-1-2.c b/test_inputs/codegen/cloog/lineality-2-1-2.c
new file mode 100644 (file)
index 0000000..2c97b94
--- /dev/null
@@ -0,0 +1,12 @@
+for (int c0 = 1; c0 <= M; c0 += 1) {
+  for (int c1 = 1; c1 <= min(c0 + 1, M); c1 += 1)
+    S1(c0, c1);
+  if (c0 + 1 >= M) {
+    S2(c0, c0 + 2);
+  } else {
+    S1(c0, c0 + 2);
+    S2(c0, c0 + 2);
+  }
+  for (int c1 = c0 + 3; c1 <= M; c1 += 1)
+    S1(c0, c1);
+}
diff --git a/test_inputs/codegen/cloog/lineality-2-1-2.in b/test_inputs/codegen/cloog/lineality-2-1-2.in
new file mode 100644 (file)
index 0000000..6ed9040
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, 2 + i0] -> [i0, 2 + i0, 1] : i0 >= 1 and i0 <= M; S1[i0, i1] -> [i0, i1, 0] : i0 >= 1 and i1 >= 1 and i0 <= M and i1 <= M }
+[M] -> {  : M >= 2 }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/logo.c b/test_inputs/codegen/cloog/logo.c
new file mode 100644 (file)
index 0000000..ea2a3c1
--- /dev/null
@@ -0,0 +1,17 @@
+{
+  for (int c1 = 0; c1 <= 7; c1 += 1)
+    S1(1, c1);
+  for (int c0 = 2; c0 <= 6; c0 += 1) {
+    for (int c1 = 0; c1 <= c0 - 2; c1 += 1)
+      S2(c0, c1);
+    for (int c1 = c0 - 1; c1 <= 4; c1 += 1) {
+      S1(c0, c1);
+      S2(c0, c1);
+    }
+    for (int c1 = 5; c1 <= 7; c1 += 1)
+      S1(c0, c1);
+  }
+  for (int c0 = 7; c0 <= 8; c0 += 1)
+    for (int c1 = c0 - 1; c1 <= 7; c1 += 1)
+      S1(c0, c1);
+}
diff --git a/test_inputs/codegen/cloog/logo.in b/test_inputs/codegen/cloog/logo.in
new file mode 100644 (file)
index 0000000..33e2d88
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [i0, i1, 1] : i0 >= 2 and i0 <= 6 and i1 >= 0 and i1 <= 4; S1[i0, i1] -> [i0, i1, 0] : i0 >= 1 and i1 <= 7 and i1 >= -1 + i0 }
+[M] -> {  :  }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/logopar.c b/test_inputs/codegen/cloog/logopar.c
new file mode 100644 (file)
index 0000000..e387357
--- /dev/null
@@ -0,0 +1,17 @@
+{
+  for (int c1 = 0; c1 <= m; c1 += 1)
+    S1(1, c1);
+  for (int c0 = 2; c0 <= n; c0 += 1) {
+    for (int c1 = 0; c1 <= c0 - 2; c1 += 1)
+      S2(c0, c1);
+    for (int c1 = c0 - 1; c1 <= n; c1 += 1) {
+      S1(c0, c1);
+      S2(c0, c1);
+    }
+    for (int c1 = n + 1; c1 <= m; c1 += 1)
+      S1(c0, c1);
+  }
+  for (int c0 = n + 1; c0 <= m + 1; c0 += 1)
+    for (int c1 = c0 - 1; c1 <= m; c1 += 1)
+      S1(c0, c1);
+}
diff --git a/test_inputs/codegen/cloog/logopar.in b/test_inputs/codegen/cloog/logopar.in
new file mode 100644 (file)
index 0000000..48b70fd
--- /dev/null
@@ -0,0 +1,3 @@
+[m, n] -> { S1[i0, i1] -> [i0, i1, 0] : i0 >= 1 and i1 <= m and i1 >= -1 + i0; S2[i0, i1] -> [i0, i1, 1] : i0 >= 2 and i0 <= n and i1 >= 0 and i1 <= n }
+[m, n] -> {  : n <= m and m >= 0 and n >= 2 }
+[m, n] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/lu.c b/test_inputs/codegen/cloog/lu.c
new file mode 100644 (file)
index 0000000..9159b1b
--- /dev/null
@@ -0,0 +1,7 @@
+for (int c0 = 1; c0 <= n; c0 += 1) {
+  for (int c1 = 2; c1 <= n; c1 += 1)
+    for (int c2 = 1; c2 <= min(c0 - 1, c1 - 1); c2 += 1)
+      S2(c2, c1, c0);
+  for (int c3 = c0 + 1; c3 <= n; c3 += 1)
+    S1(c0, c3);
+}
diff --git a/test_inputs/codegen/cloog/lu.in b/test_inputs/codegen/cloog/lu.in
new file mode 100644 (file)
index 0000000..49952cc
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { S2[i0, i1, i2] -> [i2, i1] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n and i2 >= 1 + i0 and i2 <= n; S1[i0, i1] -> [i0, n] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n }
+[n] -> {  :  }
+[n] -> { [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/lu2.c b/test_inputs/codegen/cloog/lu2.c
new file mode 100644 (file)
index 0000000..46fce50
--- /dev/null
@@ -0,0 +1,7 @@
+for (int c0 = 1; c0 <= n; c0 += 1) {
+  for (int c1 = 2; c1 <= n; c1 += 1)
+    for (int c2 = 1; c2 <= min(c0 - 1, c1 - 1); c2 += 1)
+      S2(c0, c1, c2, c1, c0);
+  for (int c3 = c0 + 1; c3 <= n; c3 += 1)
+    S1(c0, n, c0, c3);
+}
diff --git a/test_inputs/codegen/cloog/lu2.in b/test_inputs/codegen/cloog/lu2.in
new file mode 100644 (file)
index 0000000..5c71fc0
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { S1[i0, n, i0, i3] -> [i0, n, i0, i3, 0, 0] : i0 >= 1 and i0 <= n and i3 >= 1 + i0 and i3 <= n; S2[i0, i1, i2, i1, i0] -> [i0, i1, i2, i1, i0, 1] : i2 >= 1 and i2 <= n and i2 <= -1 + i1 and i1 <= n and i2 <= -1 + i0 and i0 <= n }
+[n] -> {  :  }
+[n] -> { [i, j, k, l, m, n'] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/lux.c b/test_inputs/codegen/cloog/lux.c
new file mode 100644 (file)
index 0000000..68cf881
--- /dev/null
@@ -0,0 +1,7 @@
+for (int c0 = 1; c0 <= M; c0 += 1) {
+  for (int c1 = 1; c1 <= c0 - 1; c1 += 1)
+    for (int c2 = c1 + 1; c2 <= M; c2 += 1)
+      S2(c0, c1, c2, c2, c0);
+  for (int c3 = c0 + 1; c3 <= M; c3 += 1)
+    S1(c0, c0, M, c3);
+}
diff --git a/test_inputs/codegen/cloog/lux.in b/test_inputs/codegen/cloog/lux.in
new file mode 100644 (file)
index 0000000..75ed7e2
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i0, M, i3] -> [i0, i0, M, i3, 0, 0] : i0 >= 1 and i0 <= M and i3 >= 1 + i0 and i3 <= M; S2[i0, i1, i2, i2, i0] -> [i0, i1, i2, i2, i0, 1] : i1 >= 1 and i1 <= M and i2 >= 1 + i1 and i2 <= M and i1 <= -1 + i0 and i0 <= M }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m, n] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/merge.c b/test_inputs/codegen/cloog/merge.c
new file mode 100644 (file)
index 0000000..64564ad
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  S1(0);
+  for (int c0 = 0; c0 <= 10; c0 += 1) {
+    if (c0 >= 2)
+      S2(c0);
+    S3(c0);
+  }
+}
diff --git a/test_inputs/codegen/cloog/merge.in b/test_inputs/codegen/cloog/merge.in
new file mode 100644 (file)
index 0000000..1747c44
--- /dev/null
@@ -0,0 +1,3 @@
+{ S3[i0] -> [i0, 2] : i0 >= 0 and i0 <= 10; S2[i0] -> [i0, 1] : i0 >= 2 and i0 <= 10; S1[0] -> [0, 0] }
+{  :  }
+{ [i, j] -> atomic[o0] }
diff --git a/test_inputs/codegen/cloog/min-1-1.c b/test_inputs/codegen/cloog/min-1-1.c
new file mode 100644 (file)
index 0000000..0580d1a
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= N; c0 += 1)
+  for (int c1 = 0; c1 <= min(min(N - c0, c0), M); c1 += 1)
+    S1(c0, c1);
diff --git a/test_inputs/codegen/cloog/min-1-1.in b/test_inputs/codegen/cloog/min-1-1.in
new file mode 100644 (file)
index 0000000..76e511f
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0, i1] -> [i0, i1, 0] : i0 >= 1 and i1 >= 0 and i1 <= M and i1 <= i0 and i1 <= N - i0 }
+[M, N] -> {  :  }
+[M, N] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/min-2-1.c b/test_inputs/codegen/cloog/min-2-1.c
new file mode 100644 (file)
index 0000000..bf5c9a7
--- /dev/null
@@ -0,0 +1,4 @@
+for (int c0 = 1; c0 <= N; c0 += 1)
+  for (int c1 = 0; c1 <= min(min(N - c0, c0), M); c1 += 1)
+    for (int c2 = 0; c2 <= min(min(M, N - c0), c0); c2 += 1)
+      S1(c0, c1, c2);
diff --git a/test_inputs/codegen/cloog/min-2-1.in b/test_inputs/codegen/cloog/min-2-1.in
new file mode 100644 (file)
index 0000000..aa0bcae
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0, i1, i2] -> [i0, i1, i2, 0] : i0 >= 1 and i1 >= 0 and i1 <= M and i1 <= i0 and i1 <= N - i0 and i2 >= 0 and i2 <= M and i2 <= i0 and i2 <= N - i0 }
+[M, N] -> {  :  }
+[M, N] -> { [i, j, k, l] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/min-3-1.c b/test_inputs/codegen/cloog/min-3-1.c
new file mode 100644 (file)
index 0000000..b50649e
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= min(M, 10); c0 += 1)
+  for (int c1 = 0; c1 <= min(10, M); c1 += 1)
+    S1(c0, c1);
diff --git a/test_inputs/codegen/cloog/min-3-1.in b/test_inputs/codegen/cloog/min-3-1.in
new file mode 100644 (file)
index 0000000..1676ac9
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1] -> [i0, i1, 0] : i0 >= 0 and i0 <= M and i0 <= 10 and i1 >= 0 and i1 <= M and i1 <= 10 }
+[M] -> {  : M >= 0 }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/min-4-1.c b/test_inputs/codegen/cloog/min-4-1.c
new file mode 100644 (file)
index 0000000..d8be184
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = max(-N, -M); c0 <= min(O, N); c0 += 1)
+  S1(c0);
diff --git a/test_inputs/codegen/cloog/min-4-1.in b/test_inputs/codegen/cloog/min-4-1.in
new file mode 100644 (file)
index 0000000..72fd012
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N, O] -> { S1[i0] -> [i0, 0] : i0 >= -M and i0 >= -N and i0 <= N and i0 <= O }
+[M, N, O] -> {  :  }
+[M, N, O] -> { [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/mod.c b/test_inputs/codegen/cloog/mod.c
new file mode 100644 (file)
index 0000000..cafe0b8
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= 3; c0 += 1)
+  if ((c0 + 1) % 3 >= 1)
+    S1(c0);
diff --git a/test_inputs/codegen/cloog/mod.in b/test_inputs/codegen/cloog/mod.in
new file mode 100644 (file)
index 0000000..2759c0e
--- /dev/null
@@ -0,0 +1,3 @@
+{ S1[i0] -> [i0, 0] : exists (e0 = [(1 + i0)/3]: i0 >= 0 and i0 <= 3 and 3e0 <= i0 and 3e0 >= -1 + i0) }
+{  :  }
+{ [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/mod2.c b/test_inputs/codegen/cloog/mod2.c
new file mode 100644 (file)
index 0000000..cafe0b8
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= 3; c0 += 1)
+  if ((c0 + 1) % 3 >= 1)
+    S1(c0);
diff --git a/test_inputs/codegen/cloog/mod2.in b/test_inputs/codegen/cloog/mod2.in
new file mode 100644 (file)
index 0000000..58134bb
--- /dev/null
@@ -0,0 +1,3 @@
+{ S1[i] -> [i, 0] : exists (e0 = [(i)/3]: i >= 0 and i <= 3 and 3e0 <= i and 3e0 >= -1 + i) }
+{  :  }
+{ [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/mod3.c b/test_inputs/codegen/cloog/mod3.c
new file mode 100644 (file)
index 0000000..996272d
--- /dev/null
@@ -0,0 +1,4 @@
+for (int c0 = max(0, 32 * h0 - 1991); c0 <= min(32 * h0 + 31, 999); c0 += 1)
+  if ((32 * h0 - c0 + 32) % 64 >= 1)
+    for (int c1 = 0; c1 <= 999; c1 += 1)
+      S1(c0, c1);
diff --git a/test_inputs/codegen/cloog/mod3.in b/test_inputs/codegen/cloog/mod3.in
new file mode 100644 (file)
index 0000000..bd0713e
--- /dev/null
@@ -0,0 +1,3 @@
+[h0] -> { S1[i0, i1] -> [i0, i1, 0] : exists (e0 = [(32 + 32h0 - i0)/64]: i0 >= 0 and i0 <= 999 and i0 >= -2015 + 32h0 and 32e0 >= -999 + 32h0 - i0 and i1 >= 0 and i1 <= 999 and 64e0 >= -31 + 32h0 - i0 and 64e0 <= 31 + 32h0 - i0 and i0 <= 32 + 32h0) }
+[h0] -> {  : h0 <= 93 and h0 >= 0 }
+[h0] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/mod4.c b/test_inputs/codegen/cloog/mod4.c
new file mode 100644 (file)
index 0000000..a5dca24
--- /dev/null
@@ -0,0 +1,5 @@
+for (int c0 = 2; c0 <= 10; c0 += 3) {
+  S1(c0, (c0 + 1) / 3, (c0 + 1) / 3, 2, (c0 - 2) / 3);
+  S2(c0, (c0 + 1) / 3, (c0 + 1) / 3, 2, (c0 - 2) / 3);
+  S3(c0, (c0 + 1) / 3, (c0 + 1) / 3, 2, (c0 - 2) / 3);
+}
diff --git a/test_inputs/codegen/cloog/mod4.in b/test_inputs/codegen/cloog/mod4.in
new file mode 100644 (file)
index 0000000..2002cef
--- /dev/null
@@ -0,0 +1,3 @@
+{ S2[j, div41, div42, 2, mod6_a] -> [j, div41, k, 2, m, 1] : 3k = 1 + j and 3div42 = 1 + j and 3m = -2 + j and 3mod6_a = -2 + j and 3div41 >= 1 + j and 3div41 <= 2 + j and j >= 1 and j <= 10; S1[j, div41, div42, 2, mod6_a] -> [j, div41, div42, 2, m, 0] : 3m = -2 + j and 3mod6_a = -2 + j and j >= 1 and j <= 10 and 3div41 >= j and 3div42 >= -1 + j and 3div42 <= 1 + j and 3div41 <= 2 + j; S3[j, div41, div42, 2, mod6_a] -> [j, div41, div42, 2, m, 2] : 3m = -2 + j and 3mod6_a = -2 + j and j >= 1 and j <= 10 and 3div41 >= j and 3div42 >= -1 + j and 3div42 <= 1 + j and 3div41 <= 2 + j }
+{  :  }
+{ [i, j, k, l, m, n] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/mode.c b/test_inputs/codegen/cloog/mode.c
new file mode 100644 (file)
index 0000000..c88622c
--- /dev/null
@@ -0,0 +1,10 @@
+for (int c0 = 0; c0 <= M; c0 += 1) {
+  for (int c1 = 0; c1 <= min(c0, N); c1 += 1) {
+    S1(c0, c1);
+    S2(c0, c1);
+  }
+  for (int c1 = max(0, N + 1); c1 <= c0; c1 += 1)
+    S1(c0, c1);
+  for (int c1 = c0 + 1; c1 <= N; c1 += 1)
+    S2(c0, c1);
+}
diff --git a/test_inputs/codegen/cloog/mode.in b/test_inputs/codegen/cloog/mode.in
new file mode 100644 (file)
index 0000000..914c37e
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0, i1] -> [i0, i1, 0] : i0 >= 0 and i0 <= M and i1 >= 0 and i1 <= i0; S2[i0, i1] -> [i0, i1, 1] : i0 >= 0 and i0 <= M and i1 >= 0 and i1 <= N }
+[M, N] -> {  :  }
+[M, N] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/multi-mm-1.c b/test_inputs/codegen/cloog/multi-mm-1.c
new file mode 100644 (file)
index 0000000..271d863
--- /dev/null
@@ -0,0 +1,8 @@
+for (int c0 = 0; c0 <= M; c0 += 1) {
+  for (int c1 = 0; c1 <= min(N, c0); c1 += 1) {
+    S1(c0, c1);
+    S2(c0, c1);
+  }
+  for (int c1 = N + 1; c1 <= c0; c1 += 1)
+    S1(c0, c1);
+}
diff --git a/test_inputs/codegen/cloog/multi-mm-1.in b/test_inputs/codegen/cloog/multi-mm-1.in
new file mode 100644 (file)
index 0000000..22bdd1b
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0, i1] -> [i0, i1, 0] : i1 >= 0 and i1 <= i0 and i0 <= M; S2[i0, i1] -> [i0, i1, 1] : i1 >= 0 and i1 <= i0 and i0 <= M and i1 <= N }
+[M, N] -> {  : N <= M and N >= 1 }
+[M, N] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/multi-stride.c b/test_inputs/codegen/cloog/multi-stride.c
new file mode 100644 (file)
index 0000000..2c63c08
--- /dev/null
@@ -0,0 +1,2 @@
+{
+}
diff --git a/test_inputs/codegen/cloog/multi-stride.in b/test_inputs/codegen/cloog/multi-stride.in
new file mode 100644 (file)
index 0000000..fdef8f9
--- /dev/null
@@ -0,0 +1,3 @@
+{ S1[i0, i1, i2] -> [i0, j, k, 0] : 2i1 = -1 + i0 and 2j = -1 + i0 and 6k = -2 + i0 and 6i2 = -2 + i0 and i0 >= 0 and i0 <= 100 }
+{  :  }
+{ [i, j, k, l] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/multi-stride2.c b/test_inputs/codegen/cloog/multi-stride2.c
new file mode 100644 (file)
index 0000000..14f8050
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = 5; c0 <= 100; c0 += 6)
+  S1(c0, (c0 - 1) / 2, (c0 - 2) / 3);
diff --git a/test_inputs/codegen/cloog/multi-stride2.in b/test_inputs/codegen/cloog/multi-stride2.in
new file mode 100644 (file)
index 0000000..d2c4bbc
--- /dev/null
@@ -0,0 +1,3 @@
+{ S1[i0, i1, i2] -> [i0, j, k, 0] : 2i1 = -1 + i0 and 2j = -1 + i0 and 3k = -2 + i0 and 3i2 = -2 + i0 and i0 >= 0 and i0 <= 100 }
+{  :  }
+{ [i, j, k, l] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/mxm-shared.c b/test_inputs/codegen/cloog/mxm-shared.c
new file mode 100644 (file)
index 0000000..0a1af52
--- /dev/null
@@ -0,0 +1,6 @@
+if (g4 == 0 && N >= g0 + t1 + 1 && t1 <= 7) {
+  for (int c0 = t0; c0 <= min(N - g1 - 1, 127); c0 += 16)
+    S1(g0 + t1, g1 + c0);
+} else if (g4 % 4 == 0 && N >= g0 + t1 + 1 && g4 >= 4 && t1 <= 7)
+  for (int c0 = t0; c0 <= min(127, N - g1 - 1); c0 += 16)
+    S1(g0 + t1, g1 + c0);
diff --git a/test_inputs/codegen/cloog/mxm-shared.in b/test_inputs/codegen/cloog/mxm-shared.in
new file mode 100644 (file)
index 0000000..a525e9c
--- /dev/null
@@ -0,0 +1,3 @@
+[N, b0, b1, g0, g1, g2, g3, g4, t0, t1] -> { S1[g0 + t1, i1] -> [-g1 + i1, t1, t0, t1] : (exists (e0 = [(-g1)/128], e1 = [(128b1 + 31g1)/4096], e2 = [(t0 - i1)/16], e3 = [(-120b0 - g0)/128]: g4 = 0 and g2 = 8b0 and g3 = 128b1 and 128e0 = -g1 and 4096e1 = 128b1 + 31g1 and 16e2 = t0 - i1 and 128e3 = -120b0 - g0 and g1 >= 128b1 and t1 <= -1 + N - g0 and g0 >= 8b0 and i1 <= -1 + N and b0 <= 15 and b0 >= 0 and b1 <= 31 and b1 >= 0 and i1 <= 127 + g1 and t1 >= 0 and t1 <= 7 and i1 >= g1 and t0 >= 0 and t0 <= 15)) or (exists (e0 = [(-g1)/128], e1 = [(128b1 + 31g1)/4096], e2 = [(t0 - i1)/16], e3 = [(-120b0 - g0)/128]: g4 = 0 and g2 = 8b0 and g3 = 128b1 and 128e0 = -g1 and 4096e1 = 128b1 + 31g1 and 16e2 = t0 - i1 and 128e3 = -120b0 - g0 and g1 >= 128b1 and t1 <= -1 + N - g0 and g0 >= 8b0 and i1 <= -1 + N and b0 <= 15 and b0 >= 0 and b1 <= 31 and b1 >= 0 and i1 <= 127 + g1 and t1 >= 0 and t1 <= 7 and i1 >= g1 and t0 >= 0 and t0 <= 15 and N >= 1)) or (exists (e0 = [(-g1)/128], e1 = [(128b1 + 31g1)/4096], e2 = [(t0 - i1)/16], e3 = [(-120b0 - g0)/128]: g4 = 0 and g2 = 8b0 and g3 = 128b1 and 128e0 = -g1 and 4096e1 = 128b1 + 31g1 and 16e2 = t0 - i1 and 128e3 = -120b0 - g0 and g0 >= 8b0 and t1 <= -1 + N - g0 and g1 >= 128b1 and i1 <= -1 + N and N >= 1 and t1 <= 7 and b1 <= 31 and b1 >= 0 and b0 <= 15 and b0 >= 0 and t0 <= 15 and i1 <= 127 + g1 and i1 >= g1 and t1 >= 0 and t0 >= 0)); S1[g0 + t1, i1] -> [-g1 + i1, t1, t0, t1] : exists (e0 = [(g4)/4], e1 = [(-g1)/128], e2 = [(128b1 + 31g1)/4096], e3 = [(t0 - i1)/16], e4 = [(-120b0 - g0)/128]: g3 = 128b1 and g2 = 8b0 and 4e0 = g4 and 128e1 = -g1 and 4096e2 = 128b1 + 31g1 and 16e3 = t0 - i1 and 128e4 = -120b0 - g0 and g0 >= 8b0 and t1 <= -1 + N - g0 and g1 >= 128b1 and i1 <= -1 + N and g4 <= -1 + N and t1 <= 7 and b1 <= 31 and b1 >= 0 and b0 <= 15 and b0 >= 0 and g4 >= 0 and i1 <= 127 + g1 and i1 >= g1 and t1 >= 0 and t0 >= 0 and t0 <= 15) }
+[N, b0, b1, g0, g1, g2, g3, g4, t0, t1] -> {  : exists (e0 = [(g0)/8], e1 = [(-128b1 + g1)/4096], e2 = [(8b0 - g0)/128]: g2 = 8b0 and g3 = 128b1 and 8e0 = g0 and 4096e1 = -128b1 + g1 and 128e2 = 8b0 - g0 and b0 >= 0 and g4 <= -1 + N and b0 <= 15 and g1 <= -1 + N and g4 >= 0 and b1 <= 31 and g0 <= -1 + N and g1 >= 128b1 and b1 >= 0 and g0 >= 8b0 and t0 >= 0 and t0 <= 15 and t1 >= 0 and t1 <= 15) }
+[N, b0, b1, g0, g1, g2, g3, g4, t0, t1] -> { [i, j, k, l] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/no_lindep.c b/test_inputs/codegen/cloog/no_lindep.c
new file mode 100644 (file)
index 0000000..1432b5e
--- /dev/null
@@ -0,0 +1 @@
+S1(N + 2);
diff --git a/test_inputs/codegen/cloog/no_lindep.in b/test_inputs/codegen/cloog/no_lindep.in
new file mode 100644 (file)
index 0000000..0789929
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S1[2 + N] -> [1 + M, N] }
+[M, N] -> {  :  }
+[M, N] -> { [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/nul_basic1.c b/test_inputs/codegen/cloog/nul_basic1.c
new file mode 100644 (file)
index 0000000..9293aef
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = 0; c0 <= M; c0 += 2)
+  S1(c0, c0 / 2);
diff --git a/test_inputs/codegen/cloog/nul_basic1.in b/test_inputs/codegen/cloog/nul_basic1.in
new file mode 100644 (file)
index 0000000..e10488f
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1] -> [i0, j, 0] : 2j = i0 and 2i1 = i0 and i0 >= 0 and i0 <= M }
+[M] -> {  :  }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/nul_basic2.c b/test_inputs/codegen/cloog/nul_basic2.c
new file mode 100644 (file)
index 0000000..2b7bb4d
--- /dev/null
@@ -0,0 +1,5 @@
+for (int c0 = 2; c0 <= n; c0 += 2) {
+  if (c0 % 4 == 0)
+    S2(c0, c0 / 4);
+  S1(c0, c0 / 2);
+}
diff --git a/test_inputs/codegen/cloog/nul_basic2.in b/test_inputs/codegen/cloog/nul_basic2.in
new file mode 100644 (file)
index 0000000..54f9374
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { S2[i0, i1] -> [i0, j, 1] : 4j = i0 and 4i1 = i0 and i0 >= 1 and i0 <= n; S1[i0, i1] -> [i0, j, 0] : 2j = i0 and 2i1 = i0 and i0 >= 1 and i0 <= n }
+[n] -> {  : n >= 2 }
+[n] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/nul_complex1.c b/test_inputs/codegen/cloog/nul_complex1.c
new file mode 100644 (file)
index 0000000..cdf5425
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= 5 * n; c0 += 1)
+  for (int c1 = max(((n + c0) % 2) - n + c0, ((c0 + c0 / 3) % 2) + c0 - c0 / 3); c1 <= min(n + c0 + floord(-n - c0, 3), c0); c1 += 2)
+    S1((-2 * c0 + 3 * c1) / 2, c0 - c1);
diff --git a/test_inputs/codegen/cloog/nul_complex1.in b/test_inputs/codegen/cloog/nul_complex1.in
new file mode 100644 (file)
index 0000000..277e62e
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { S1[i0, i1] -> [2i0 + 3i1, 2i0 + 2i1] : i0 >= 0 and i0 <= n and i1 >= 0 and i1 <= n }
+[n] -> {  :  }
+[n] -> { [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/nul_lcpc.c b/test_inputs/codegen/cloog/nul_lcpc.c
new file mode 100644 (file)
index 0000000..4766840
--- /dev/null
@@ -0,0 +1,13 @@
+{
+  for (int c0 = 1; c0 <= 5; c0 += 2) {
+    for (int c2 = 1; c2 <= c0; c2 += 1) {
+      S1(c0, (c0 - 1) / 2, c2);
+      S2(c0, (c0 - 1) / 2, c2);
+    }
+    for (int c2 = c0 + 1; c2 <= p; c2 += 1)
+      S1(c0, (c0 - 1) / 2, c2);
+  }
+  for (int c0 = 7; c0 <= m; c0 += 2)
+    for (int c2 = 1; c2 <= p; c2 += 1)
+      S1(c0, (c0 - 1) / 2, c2);
+}
diff --git a/test_inputs/codegen/cloog/nul_lcpc.in b/test_inputs/codegen/cloog/nul_lcpc.in
new file mode 100644 (file)
index 0000000..e3a4e99
--- /dev/null
@@ -0,0 +1,3 @@
+[m, n, p] -> { S1[i, k, j] -> [i, j', j, 0] : 2k = -1 + i and 2j' = -1 + i and i >= 1 and i <= m and j >= 1 and j <= p; S2[i, k, j] -> [i, j', j, 1] : 2k = -1 + i and 2j' = -1 + i and i >= 1 and i <= n and j >= 1 and j <= i }
+[m, n, p] -> {  : n = 6 and m >= 7 and p >= 7 }
+[m, n, p] -> { [i, j, k, l] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/orc.c b/test_inputs/codegen/cloog/orc.c
new file mode 100644 (file)
index 0000000..8ad0162
--- /dev/null
@@ -0,0 +1,16 @@
+{
+  for (int c1 = 0; c1 <= 2; c1 += 1) {
+    S1(c1);
+    for (int c2 = 0; c2 <= -c1 + 11; c2 += 1) {
+      S2(c1, c2);
+      S3(c1, c2);
+    }
+    S4(c1);
+  }
+  for (int c1 = 0; c1 <= 14; c1 += 1) {
+    S5(c1);
+    for (int c2 = 0; c2 <= 9; c2 += 1)
+      S6(c1, c2);
+    S7(c1);
+  }
+}
diff --git a/test_inputs/codegen/cloog/orc.in b/test_inputs/codegen/cloog/orc.in
new file mode 100644 (file)
index 0000000..d81bf47
--- /dev/null
@@ -0,0 +1,3 @@
+{ S2[i0, i1] -> [0, 1 + 3i0, 2i1] : i0 >= 0 and i0 <= 2 and i1 >= 0 and i1 <= 11 - i0; S4[i0] -> [0, 2 + 3i0, 0] : i0 >= 0 and i0 <= 2; S5[i0] -> [2, 3i0, 0] : i0 >= 0 and i0 <= 14; S6[i0, i1] -> [2, 1 + 3i0, i1] : i0 >= 0 and i0 <= 14 and i1 >= 0 and i1 <= 9; S1[i0] -> [0, 3i0, 0] : i0 >= 0 and i0 <= 2; S7[i0] -> [2, 2 + 3i0, 0] : i0 >= 0 and i0 <= 14; S3[i0, i1] -> [0, 1 + 3i0, 1 + 2i1] : i0 >= 0 and i0 <= 2 and i1 >= 0 and i1 <= 11 - i0 }
+{  :  }
+{ [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/param-split.c b/test_inputs/codegen/cloog/param-split.c
new file mode 100644 (file)
index 0000000..5da9c13
--- /dev/null
@@ -0,0 +1,6 @@
+for (int c0 = 0; c0 <= (M >= 0 ? M : 0); c0 += 1) {
+  if (M >= c0)
+    S1(c0);
+  if (c0 == 0)
+    S2(0);
+}
diff --git a/test_inputs/codegen/cloog/param-split.in b/test_inputs/codegen/cloog/param-split.in
new file mode 100644 (file)
index 0000000..7b8a59e
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[i0] -> [i0, 0] : i0 >= 0 and i0 <= M; S2[0] -> [0, 1] }
+[M] -> {  :  }
+[M] -> { [i, j] -> atomic[o0] }
diff --git a/test_inputs/codegen/cloog/pouchet.c b/test_inputs/codegen/cloog/pouchet.c
new file mode 100644 (file)
index 0000000..42c03a0
--- /dev/null
@@ -0,0 +1,10 @@
+for (int c0 = 1; c0 <= floord(Ny, 2) + 2; c0 += 1)
+  for (int c1 = max(c0 - (c0 + 1) / 2 + 1, c0 - 1); c1 <= min((Ny + 2 * c0) / 4, c0); c1 += 1)
+    if (Ny + 2 * c0 >= 4 * c1 + 1) {
+      for (int c2 = 1; c2 <= 2; c2 += 1) {
+        S1(c0 - c1, c1, 2 * c0 - 2 * c1, -2 * c0 + 4 * c1, c2);
+        S2(c0 - c1, c1, 2 * c0 - 2 * c1, -2 * c0 + 4 * c1 - 1, c2);
+      }
+    } else
+      for (int c2 = 1; c2 <= 2; c2 += 1)
+        S2((-Ny + 2 * c0) / 4, (Ny + 2 * c0) / 4, (-Ny + 2 * c0) / 2, Ny - 1, c2);
diff --git a/test_inputs/codegen/cloog/pouchet.in b/test_inputs/codegen/cloog/pouchet.in
new file mode 100644 (file)
index 0000000..95d59dc
--- /dev/null
@@ -0,0 +1,3 @@
+[Ny] -> { S1[i0, i1, 2i0, -2i0 + 2i1, i4] -> [i0 + i1, i1, i4, 2i0, -2i0 + 2i1, i4] : i0 >= 0 and i0 <= 1 and i1 >= 1 + i0 and 2i1 <= -1 + Ny + 2i0 and i4 >= 1 and i4 <= 2; S2[i0, i1, 2i0, -1 - 2i0 + 2i1, i4] -> [i0 + i1, i1, i4, 2i0, -2i0 + 2i1, 1 + i4] : i0 >= 0 and i0 <= 1 and i1 >= 1 + i0 and 2i1 <= Ny + 2i0 and i4 >= 1 and i4 <= 2 }
+[Ny] -> {  :  }
+[Ny] -> { [i, j, k, l, m, n] -> separate[x] : x >= 2 }
diff --git a/test_inputs/codegen/cloog/rectangle.c b/test_inputs/codegen/cloog/rectangle.c
new file mode 100644 (file)
index 0000000..a6ea93a
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= 2 * n; c0 += 1)
+  for (int c1 = max(0, -n + c0); c1 <= min(c0, n); c1 += 1)
+    S1(c1, c0 - c1);
diff --git a/test_inputs/codegen/cloog/rectangle.in b/test_inputs/codegen/cloog/rectangle.in
new file mode 100644 (file)
index 0000000..fab0f94
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { S1[i0, i1] -> [i0 + i1] : i0 >= 0 and i0 <= n and i1 >= 0 and i1 <= n }
+[n] -> {  : n >= 0 }
+[n] -> { [i] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-QR.c b/test_inputs/codegen/cloog/reservoir-QR.c
new file mode 100644 (file)
index 0000000..2b533dd
--- /dev/null
@@ -0,0 +1,54 @@
+if (N >= 1) {
+  S1(0);
+  if (N == 1) {
+    for (int c3 = 0; c3 <= M - 1; c3 += 1)
+      S2(0, c3);
+    S3(0);
+    for (int c3 = 0; c3 <= M - 1; c3 += 1)
+      S4(0, c3);
+    S10(0);
+    S5(0);
+  } else {
+    for (int c3 = 0; c3 <= M - 1; c3 += 1)
+      S2(0, c3);
+    S3(0);
+    for (int c3 = 0; c3 <= M - 1; c3 += 1)
+      S4(0, c3);
+    S10(0);
+    S1(1);
+    S5(0);
+  }
+  for (int c1 = 2; c1 <= N - 1; c1 += 1) {
+    for (int c3 = c1 - 1; c3 <= N - 1; c3 += 1) {
+      S6(c1 - 2, c3);
+      for (int c5 = c1 - 2; c5 <= M - 1; c5 += 1)
+        S7(c1 - 2, c3, c5);
+      S8(c1 - 2, c3);
+      for (int c5 = c1 - 2; c5 <= M - 1; c5 += 1)
+        S9(c1 - 2, c3, c5);
+    }
+    for (int c3 = c1 - 1; c3 <= M - 1; c3 += 1)
+      S2(c1 - 1, c3);
+    S3(c1 - 1);
+    for (int c3 = c1 - 1; c3 <= M - 1; c3 += 1)
+      S4(c1 - 1, c3);
+    S10(c1 - 1);
+    S1(c1);
+    S5(c1 - 1);
+  }
+  if (N >= 2) {
+    S6(N - 2, N - 1);
+    for (int c5 = N - 2; c5 <= M - 1; c5 += 1)
+      S7(N - 2, N - 1, c5);
+    S8(N - 2, N - 1);
+    for (int c5 = N - 2; c5 <= M - 1; c5 += 1)
+      S9(N - 2, N - 1, c5);
+    for (int c3 = N - 1; c3 <= M - 1; c3 += 1)
+      S2(N - 1, c3);
+    S3(N - 1);
+    for (int c3 = N - 1; c3 <= M - 1; c3 += 1)
+      S4(N - 1, c3);
+    S10(N - 1);
+    S5(N - 1);
+  }
+}
diff --git a/test_inputs/codegen/cloog/reservoir-QR.in b/test_inputs/codegen/cloog/reservoir-QR.in
new file mode 100644 (file)
index 0000000..b81c03d
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0] -> [0, i0, 5, 0, 0, 0, 0] : i0 >= 0 and i0 <= -1 + N; S9[i0, i1, i2] -> [0, 2 + i0, 0, i1, 3, i2, 0] : i0 >= 0 and i1 >= 1 + i0 and i1 <= -1 + N and i2 >= i0 and i2 <= -1 + M; S10[i0] -> [0, 1 + i0, 4, 0, 0, 0, 0] : i0 >= 0 and i0 <= -1 + N; S3[i0] -> [0, 1 + i0, 2, 0, 0, 0, 0] : i0 >= 0 and i0 <= -1 + N; S6[i0, i1] -> [0, 2 + i0, 0, i1, 0, 0, 0] : i0 >= 0 and i1 >= 1 + i0 and i1 <= -1 + N; S8[i0, i1] -> [0, 2 + i0, 0, i1, 2, 0, 0] : i0 >= 0 and i1 >= 1 + i0 and i1 <= -1 + N; S2[i0, i1] -> [0, 1 + i0, 1, i1, 0, 0, 0] : i0 >= 0 and i0 <= -1 + N and i1 >= i0 and i1 <= -1 + M; S4[i0, i1] -> [0, 1 + i0, 3, i1, 0, 0, 0] : i0 >= 0 and i0 <= -1 + N and i1 >= i0 and i1 <= -1 + M; S7[i0, i1, i2] -> [0, 2 + i0, 0, i1, 1, i2, 0] : i0 >= 0 and i1 >= 1 + i0 and i1 <= -1 + N and i2 >= i0 and i2 <= -1 + M; S5[i0] -> [0, 1 + i0, 6, 0, 0, 0, 0] : i0 >= 0 and i0 <= -1 + N }
+[M, N] -> {  :  }
+[M, N] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-bastoul3.c b/test_inputs/codegen/cloog/reservoir-bastoul3.c
new file mode 100644 (file)
index 0000000..05e95d2
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 3; c0 <= 9; c0 += 1)
+  for (int c1 = max(((c0 + 1) % 2) + 1, c0 - 6); c1 <= min(c0 - 2, 3); c1 += 2)
+    S1(c0, c1, (c0 - c1) / 2);
diff --git a/test_inputs/codegen/cloog/reservoir-bastoul3.in b/test_inputs/codegen/cloog/reservoir-bastoul3.in
new file mode 100644 (file)
index 0000000..a6a4ffc
--- /dev/null
@@ -0,0 +1,3 @@
+{ S1[i0, i1, i2] -> [i0, i1, k, 0] : 2k = i0 - i1 and 2i2 = i0 - i1 and i1 >= 1 and i1 <= 3 and i1 <= -2 + i0 and i1 >= -6 + i0 }
+{  :  }
+{ [i, j, k, l] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-cholesky2.c b/test_inputs/codegen/cloog/reservoir-cholesky2.c
new file mode 100644 (file)
index 0000000..c4d9185
--- /dev/null
@@ -0,0 +1,10 @@
+for (int c1 = 2; c1 <= 3 * M - 1; c1 += 1) {
+  if ((c1 - 2) % 3 == 0)
+    S1((c1 + 1) / 3);
+  for (int c3 = -floord(-c1 + 1, 3) + 1; c3 <= min(c1 - 2, M); c3 += 1)
+    for (int c5 = c1 - (c1 + c3) / 2 + 1; c5 <= min(c1 - c3, c3); c5 += 1)
+      S3(c1 - c3 - c5 + 1, c3, c5);
+  if (c1 + 1 >= 3 * ((c1 + floord(-c1 - 1, 3) + 1) / 2) && 3 * ((c1 + floord(-c1 - 1, 3) + 1) / 2) + 1 >= c1)
+    for (int c3 = ((c1 + floord(-c1 - 1, 3) + 1) % 2) - floord(-c1 - 1, 3) + 1; c3 <= min(c1, M); c3 += 2)
+      S2((c1 - c3 + 2) / 2, c3);
+}
diff --git a/test_inputs/codegen/cloog/reservoir-cholesky2.in b/test_inputs/codegen/cloog/reservoir-cholesky2.in
new file mode 100644 (file)
index 0000000..7f62b1f
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S3[i0, i1, i2] -> [0, -1 + i0 + i1 + i2, 1, i1, 1, i2, 0] : i0 >= 1 and i1 <= M and i2 >= 1 + i0 and i2 <= i1; S2[i0, i1] -> [0, -2 + 2i0 + i1, 2, i1, 0, 0, 0] : i0 >= 1 and i1 >= 1 + i0 and i1 <= M; S1[i0] -> [0, -1 + 3i0, 0, 0, 0, 0, 0] : i0 >= 1 and i0 <= M }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-fusion1.c b/test_inputs/codegen/cloog/reservoir-fusion1.c
new file mode 100644 (file)
index 0000000..201ffee
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  for (int c1 = 0; c1 <= M; c1 += 1)
+    S1(c1);
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    S2(c1);
+  for (int c1 = 0; c1 <= M; c1 += 1)
+    S3(c1);
+}
diff --git a/test_inputs/codegen/cloog/reservoir-fusion1.in b/test_inputs/codegen/cloog/reservoir-fusion1.in
new file mode 100644 (file)
index 0000000..ca4282e
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[i0] -> [0, i0, 0] : i0 >= 0 and i0 <= M; S3[i0] -> [2, i0, 0] : i0 >= 0 and i0 <= M; S2[i0] -> [1, i0, 0] : i0 >= 1 and i0 <= M }
+[M] -> {  : M >= 1 }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-fusion2.c b/test_inputs/codegen/cloog/reservoir-fusion2.c
new file mode 100644 (file)
index 0000000..13c3030
--- /dev/null
@@ -0,0 +1,12 @@
+if (N >= 1) {
+  for (int c3 = 1; c3 <= M; c3 += 1)
+    S1(1, c3);
+  for (int c1 = 2; c1 <= N; c1 += 1) {
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S2(c1 - 1, c3);
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S1(c1, c3);
+  }
+  for (int c3 = 1; c3 <= M; c3 += 1)
+    S2(N, c3);
+}
diff --git a/test_inputs/codegen/cloog/reservoir-fusion2.in b/test_inputs/codegen/cloog/reservoir-fusion2.in
new file mode 100644 (file)
index 0000000..53905d8
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S2[i0, i1] -> [0, 1 + i0, 0, i1, 0] : i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= M; S1[i0, i1] -> [0, i0, 1, i1, 0] : i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= M }
+[M, N] -> {  :  }
+[M, N] -> { [i, j, k, l, m] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-jacobi2.c b/test_inputs/codegen/cloog/reservoir-jacobi2.c
new file mode 100644 (file)
index 0000000..44b46ee
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c1 = 0; c1 <= M - 1; c1 += 1)
+  for (int c3 = 0; c3 <= M - 1; c3 += 1)
+    S1(c1, c3);
diff --git a/test_inputs/codegen/cloog/reservoir-jacobi2.in b/test_inputs/codegen/cloog/reservoir-jacobi2.in
new file mode 100644 (file)
index 0000000..ea86283
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1] -> [0, i0, 0, i1, 0] : i0 >= 0 and i0 <= -1 + M and i1 >= 0 and i1 <= -1 + M }
+[M] -> {  : M >= 1 }
+[M] -> { [i, j, k, l, m] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-jacobi3.c b/test_inputs/codegen/cloog/reservoir-jacobi3.c
new file mode 100644 (file)
index 0000000..011b912
--- /dev/null
@@ -0,0 +1,8 @@
+for (int c1 = 1; c1 <= M; c1 += 1) {
+  for (int c3 = 2; c3 <= N - 1; c3 += 1)
+    for (int c5 = 2; c5 <= N - 1; c5 += 1)
+      S1(c1, c3, c5);
+  for (int c3 = 2; c3 <= N - 1; c3 += 1)
+    for (int c5 = 2; c5 <= N - 1; c5 += 1)
+      S2(c1, c3, c5);
+}
diff --git a/test_inputs/codegen/cloog/reservoir-jacobi3.in b/test_inputs/codegen/cloog/reservoir-jacobi3.in
new file mode 100644 (file)
index 0000000..4f5cc77
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S2[i0, i1, i2] -> [0, 1 + 2i0, 1, i1, 0, i2, 0] : i0 >= 1 and i0 <= M and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + N; S1[i0, i1, i2] -> [0, 2i0, 0, i1, 0, i2, 0] : i0 >= 1 and i0 <= M and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + N }
+[M, N] -> {  :  }
+[M, N] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-lim-lam1.c b/test_inputs/codegen/cloog/reservoir-lim-lam1.c
new file mode 100644 (file)
index 0000000..8f93f15
--- /dev/null
@@ -0,0 +1,10 @@
+for (int c1 = -99; c1 <= 100; c1 += 1) {
+  if (c1 >= 1)
+    S2(c1, 1);
+  for (int c3 = max(1, -c1 + 1); c3 <= min(-c1 + 100, 99); c3 += 1) {
+    S1(c1 + c3, c3);
+    S2(c1 + c3, c3 + 1);
+  }
+  if (c1 <= 0)
+    S1(c1 + 100, 100);
+}
diff --git a/test_inputs/codegen/cloog/reservoir-lim-lam1.in b/test_inputs/codegen/cloog/reservoir-lim-lam1.in
new file mode 100644 (file)
index 0000000..b2338b0
--- /dev/null
@@ -0,0 +1,3 @@
+{ S2[i0, i1] -> [0, 1 + i0 - i1, 0, -1 + 2i1, 1] : i0 >= 1 and i0 <= 100 and i1 >= 1 and i1 <= 100; S1[i0, i1] -> [0, i0 - i1, 0, 2i1, 0] : i0 >= 1 and i0 <= 100 and i1 >= 1 and i1 <= 100 }
+{  :  }
+{ [i, j, k, l, m] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-lim-lam2.c b/test_inputs/codegen/cloog/reservoir-lim-lam2.c
new file mode 100644 (file)
index 0000000..5c8481c
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    S1(c1);
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    for (int c3 = 2; c3 <= N; c3 += 1)
+      S2(c1, c3);
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= N - 1; c3 += 1)
+      S3(c1, c3);
+}
diff --git a/test_inputs/codegen/cloog/reservoir-lim-lam2.in b/test_inputs/codegen/cloog/reservoir-lim-lam2.in
new file mode 100644 (file)
index 0000000..eb62bb7
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0] -> [0, i0, 0, 0, 0] : i0 >= 1 and i0 <= M; S2[i0, i1] -> [1, i0, 1, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 2 and i1 <= N; S3[i0, i1] -> [2, i0, 2, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= -1 + N }
+[M, N] -> {  : M >= 1 and N >= 1 }
+[M, N] -> { [i, j, k, l, m] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-lim-lam3.c b/test_inputs/codegen/cloog/reservoir-lim-lam3.c
new file mode 100644 (file)
index 0000000..1d6f994
--- /dev/null
@@ -0,0 +1,11 @@
+for (int c1 = 5; c1 <= 5 * M; c1 += 1) {
+  for (int c3 = max(2, -floord(M - c1 - 1, 4) - 1); c3 <= min((c1 + 1) / 3 - 3, M - 1); c3 += 1)
+    for (int c5 = max(c1 - c3 - (M + c1 + 1) / 2 - 2, 1); c5 <= min(c3 - 1, -2 * c3 + (c1 + c3) / 2 - 3); c5 += 1)
+      S1(c1 - 2 * c3 - 2 * c5 - 5, c3, c5);
+  for (int c3 = max(1, -floord(M - c1 - 1, 4) - 1); c3 <= (c1 + 1) / 5 - 1; c3 += 1)
+    S2(c1 - 4 * c3 - 3, c3);
+  if (c1 % 5 == 0)
+    S4(c1 / 5);
+  for (int c3 = max(-c1 - 3 * floord(-c1, 3) + 1, 2 * c1 - 3 * ((M + c1 + 1) / 2) + 1); c3 <= (c1 + 1) / 5 - 1; c3 += 3)
+    S3((c1 - 2 * c3 - 1) / 3, c3);
+}
diff --git a/test_inputs/codegen/cloog/reservoir-lim-lam3.in b/test_inputs/codegen/cloog/reservoir-lim-lam3.in
new file mode 100644 (file)
index 0000000..ebf78ae
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1, i2] -> [0, 5 + i0 + 2i1 + 2i2, 0, i1, 0, i2, 0] : i0 <= M and i1 <= -1 + i0 and i2 >= 1 and i2 <= -1 + i1; S3[i0, i1] -> [0, 1 + 3i0 + 2i1, 2, i1, 0, 0, 0] : i0 <= M and i1 >= 1 and i1 <= -1 + i0; S2[i0, i1] -> [0, 3 + i0 + 4i1, 1, i1, 1, 0, 0] : i0 <= M and i1 >= 1 and i1 <= -1 + i0; S4[i0] -> [0, 5i0, 2, 0, 0, 0, 0] : i0 >= 1 and i0 <= M }
+[M] -> {  : M >= 1 }
+[M] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-lim-lam4.c b/test_inputs/codegen/cloog/reservoir-lim-lam4.c
new file mode 100644 (file)
index 0000000..73603e6
--- /dev/null
@@ -0,0 +1,10 @@
+for (int c1 = 1; c1 <= 2 * M - 2; c1 += 1) {
+  for (int c3 = max(-c1 + 1, -M + 1); c3 <= -1; c3 += 1) {
+    for (int c7 = max(-M + c1 + 1, 1); c7 <= min(c1 + c3, M - 1); c7 += 1)
+      S1(c7, c1 + c3 - c7, -c3);
+    for (int c5 = max(-c3, -M + c1 + 1); c5 <= min(M - 1, c1 - 1); c5 += 1)
+      S2(c1 - c5, c3 + c5, c5);
+  }
+  for (int c7 = max(1, -M + c1 + 1); c7 <= min(c1, M - 1); c7 += 1)
+    S1(c7, c1 - c7, 0);
+}
diff --git a/test_inputs/codegen/cloog/reservoir-lim-lam4.in b/test_inputs/codegen/cloog/reservoir-lim-lam4.in
new file mode 100644 (file)
index 0000000..1bb684f
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1, i2] -> [0, i0 + i1 + i2, 0, -i2, 0, i2, 0] : i0 >= 1 and i0 <= -1 + M and i1 >= 0 and i2 >= 0 and i2 <= -1 + M - i1; S2[i0, i1, i2] -> [0, i0 + i2, 0, i1 - i2, 1, i2, 0] : i0 >= 1 and i0 <= -1 + M and i1 >= 0 and i2 >= 1 + i1 and i2 <= -1 + M }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-lim-lam5.c b/test_inputs/codegen/cloog/reservoir-lim-lam5.c
new file mode 100644 (file)
index 0000000..f476185
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S1(c1, c3);
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S2(c1, c3);
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S3(c1, c3);
+}
diff --git a/test_inputs/codegen/cloog/reservoir-lim-lam5.in b/test_inputs/codegen/cloog/reservoir-lim-lam5.in
new file mode 100644 (file)
index 0000000..2e2046f
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [1, i0, 0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M; S1[i0, i1] -> [0, i0, 0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M; S3[i0, i1] -> [2, i0, 0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-lim-lam6.c b/test_inputs/codegen/cloog/reservoir-lim-lam6.c
new file mode 100644 (file)
index 0000000..2cc5122
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  for (int c1 = 0; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S1(c1, c3);
+  for (int c1 = 0; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S2(c3, c1);
+}
diff --git a/test_inputs/codegen/cloog/reservoir-lim-lam6.in b/test_inputs/codegen/cloog/reservoir-lim-lam6.in
new file mode 100644 (file)
index 0000000..2699212
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [1, i1, 0, i0, 0] : i0 >= 1 and i0 <= M and i1 >= 0 and i1 <= M; S1[i0, i1] -> [0, i0, 0, i1, 0] : i0 >= 0 and i0 <= M and i1 >= 1 and i1 <= M }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-liu-zhuge1.c b/test_inputs/codegen/cloog/reservoir-liu-zhuge1.c
new file mode 100644 (file)
index 0000000..78712ca
--- /dev/null
@@ -0,0 +1,17 @@
+if (N >= 0 && M >= 0)
+  for (int c1 = -4; c1 <= 3 * M + N; c1 += 1) {
+    if (c1 >= 3 * M) {
+      S2(M, -3 * M + c1);
+    } else if (3 * floord(c1 - 2, 3) + 2 == c1 && c1 + 1 >= 0 && 3 * M >= c1 + 4)
+      S1((c1 + 4) / 3, 0);
+    for (int c3 = max(c1 - 3 * floord(c1, 3), -3 * M + c1 + 3); c3 <= min(c1, N - 1); c3 += 3) {
+      S2((c1 - c3) / 3, c3);
+      S1((c1 - c3 + 3) / 3, c3 + 1);
+    }
+    if (N + 3 * floord(-N + c1, 3) == c1 && c1 >= N && 3 * M + N >= c1 + 3) {
+      S2((-N + c1) / 3, N);
+    } else if (N >= c1 + 4)
+      S1(0, c1 + 4);
+    for (int c3 = max(-3 * M + c1, c1 - 3 * floord(c1, 3)); c3 <= min(N, c1); c3 += 3)
+      S3((c1 - c3) / 3, c3);
+  }
diff --git a/test_inputs/codegen/cloog/reservoir-liu-zhuge1.in b/test_inputs/codegen/cloog/reservoir-liu-zhuge1.in
new file mode 100644 (file)
index 0000000..fd4dcc8
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S2[i0, i1] -> [0, 3i0 + i1, 0, i1, 0] : i0 >= 0 and i0 <= M and i1 >= 0 and i1 <= N; S3[i0, i1] -> [0, 3i0 + i1, 1, i1, 0] : i0 >= 0 and i0 <= M and i1 >= 0 and i1 <= N; S1[i0, i1] -> [0, -4 + 3i0 + i1, 0, i1, 0] : i0 >= 0 and i0 <= M and i1 >= 0 and i1 <= N }
+[M, N] -> {  :  }
+[M, N] -> { [i, j, k, l, m] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-loechner3.c b/test_inputs/codegen/cloog/reservoir-loechner3.c
new file mode 100644 (file)
index 0000000..849724b
--- /dev/null
@@ -0,0 +1,4 @@
+for (int c1 = 1; c1 <= M; c1 += 1)
+  for (int c3 = 2; c3 <= M + c1; c3 += 1)
+    for (int c5 = max(-c1 + c3, 1); c5 <= min(M, c3 - 1); c5 += 1)
+      S1(c1, c5, c3 - c5);
diff --git a/test_inputs/codegen/cloog/reservoir-loechner3.in b/test_inputs/codegen/cloog/reservoir-loechner3.in
new file mode 100644 (file)
index 0000000..0373171
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1, i2] -> [0, i0, 0, i1 + i2, 0, i1, 0] : i0 <= M and i1 >= 1 and i1 <= M and i2 >= 1 and i2 <= i0 }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-loechner4.c b/test_inputs/codegen/cloog/reservoir-loechner4.c
new file mode 100644 (file)
index 0000000..bf48290
--- /dev/null
@@ -0,0 +1,5 @@
+for (int c1 = 2; c1 <= 2 * M; c1 += 1)
+  for (int c3 = 1; c3 <= M; c3 += 1)
+    for (int c5 = 1; c5 <= M; c5 += 1)
+      for (int c7 = max(1, -M + c1); c7 <= min(c1 - 1, M); c7 += 1)
+        S1(c5, c3, c7, c1 - c7);
diff --git a/test_inputs/codegen/cloog/reservoir-loechner4.in b/test_inputs/codegen/cloog/reservoir-loechner4.in
new file mode 100644 (file)
index 0000000..1a80702
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1, i2, i3] -> [0, i2 + i3, 0, i1, 0, i0, 0, i2, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M and i2 >= 1 and i2 <= M and i3 >= 1 and i3 <= M }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m, n, o, p, q] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-loechner5.c b/test_inputs/codegen/cloog/reservoir-loechner5.c
new file mode 100644 (file)
index 0000000..c5f8fcc
--- /dev/null
@@ -0,0 +1,5 @@
+for (int c1 = 1; c1 <= M; c1 += 1)
+  for (int c3 = 1; c3 <= M; c3 += 1)
+    for (int c5 = 1; c5 <= M; c5 += 1)
+      for (int c7 = 1; c7 <= M; c7 += 1)
+        S1(c3, c5, c1, c7);
diff --git a/test_inputs/codegen/cloog/reservoir-loechner5.in b/test_inputs/codegen/cloog/reservoir-loechner5.in
new file mode 100644 (file)
index 0000000..9122fc0
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1, i2, i3] -> [0, i2, 0, i0, 0, i1, 0, i3, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M and i2 >= 1 and i2 <= M and i3 >= 1 and i3 <= M }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m, n, o, p, q] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-mg-interp.c b/test_inputs/codegen/cloog/reservoir-mg-interp.c
new file mode 100644 (file)
index 0000000..697c849
--- /dev/null
@@ -0,0 +1,85 @@
+{
+  if (N >= 2)
+    for (int c1 = 1; c1 <= O - 1; c1 += 1) {
+      for (int c5 = 1; c5 <= M; c5 += 1)
+        S1(c1, 1, c5);
+      for (int c5 = 1; c5 <= M - 1; c5 += 1) {
+        S6(c1, 1, c5);
+        S7(c1, 1, c5);
+      }
+      if (N >= 3) {
+        for (int c5 = 1; c5 <= M; c5 += 1)
+          S3(c1, 1, c5);
+        for (int c5 = 1; c5 <= M; c5 += 1)
+          S1(c1, 2, c5);
+        for (int c5 = 1; c5 <= M - 1; c5 += 1) {
+          S6(c1, 2, c5);
+          S7(c1, 2, c5);
+        }
+        for (int c5 = 1; c5 <= M - 1; c5 += 1)
+          S11(c1, 1, c5);
+      } else {
+        for (int c5 = 1; c5 <= M; c5 += 1)
+          S3(c1, 1, c5);
+        for (int c5 = 1; c5 <= M - 1; c5 += 1)
+          S11(c1, 1, c5);
+      }
+      for (int c3 = 3; c3 <= 2 * N - 5; c3 += 2) {
+        for (int c5 = 1; c5 <= M - 1; c5 += 1)
+          S10(c1, (c3 - 1) / 2, c5);
+        for (int c5 = 1; c5 <= M; c5 += 1)
+          S3(c1, (c3 + 1) / 2, c5);
+        for (int c5 = 1; c5 <= M; c5 += 1)
+          S1(c1, (c3 + 3) / 2, c5);
+        for (int c5 = 1; c5 <= M - 1; c5 += 1) {
+          S6(c1, (c3 + 3) / 2, c5);
+          S7(c1, (c3 + 3) / 2, c5);
+        }
+        for (int c5 = 1; c5 <= M - 1; c5 += 1)
+          S11(c1, (c3 + 1) / 2, c5);
+      }
+      if (N >= 3) {
+        for (int c5 = 1; c5 <= M - 1; c5 += 1)
+          S10(c1, N - 2, c5);
+        for (int c5 = 1; c5 <= M; c5 += 1)
+          S3(c1, N - 1, c5);
+        for (int c5 = 1; c5 <= M - 1; c5 += 1)
+          S11(c1, N - 1, c5);
+      }
+      for (int c5 = 1; c5 <= M - 1; c5 += 1)
+        S10(c1, N - 1, c5);
+    }
+  for (int c1 = 1; c1 <= O - 1; c1 += 1)
+    for (int c3 = 1; c3 <= N - 1; c3 += 1) {
+      for (int c5 = 1; c5 <= M; c5 += 1)
+        S2(c1, c3, c5);
+      for (int c5 = 1; c5 <= M - 1; c5 += 1)
+        S8(c1, c3, c5);
+      for (int c5 = 1; c5 <= M - 1; c5 += 1)
+        S9(c1, c3, c5);
+    }
+  for (int c1 = 1; c1 <= O - 1; c1 += 1)
+    for (int c3 = 1; c3 <= N - 1; c3 += 1)
+      for (int c5 = 1; c5 <= M - 1; c5 += 1)
+        S4(c1, c3, c5);
+  for (int c1 = 1; c1 <= O - 1; c1 += 1)
+    for (int c3 = 1; c3 <= N - 1; c3 += 1)
+      for (int c5 = 1; c5 <= M - 1; c5 += 1)
+        S5(c1, c3, c5);
+  for (int c1 = R; c1 <= O - 1; c1 += 1)
+    for (int c3 = Q; c3 <= N - 1; c3 += 1)
+      for (int c5 = P; c5 <= M - 1; c5 += 1)
+        S12(c1, c3, c5);
+  for (int c1 = R; c1 <= O - 1; c1 += 1)
+    for (int c3 = Q; c3 <= N - 1; c3 += 1)
+      for (int c5 = 1; c5 <= M - 1; c5 += 1)
+        S13(c1, c3, c5);
+  for (int c1 = R; c1 <= O - 1; c1 += 1)
+    for (int c3 = 1; c3 <= N - 1; c3 += 1)
+      for (int c5 = P; c5 <= M - 1; c5 += 1)
+        S14(c1, c3, c5);
+  for (int c1 = R; c1 <= O - 1; c1 += 1)
+    for (int c3 = 1; c3 <= N - 1; c3 += 1)
+      for (int c5 = 1; c5 <= M - 1; c5 += 1)
+        S15(c1, c3, c5);
+}
diff --git a/test_inputs/codegen/cloog/reservoir-mg-interp.in b/test_inputs/codegen/cloog/reservoir-mg-interp.in
new file mode 100644 (file)
index 0000000..b7fdb69
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N, O, P, Q, R, S, T, U] -> { S8[i0, i1, i2] -> [1, i0, 0, 2i1, 1, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S11[i0, i1, i2] -> [0, i0, 0, 2i1, 4, i2, 1] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S6[i0, i1, i2] -> [0, i0, 0, -2 + 2i1, 2, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S9[i0, i1, i2] -> [1, i0, 0, 1 + 2i1, 3, i2, 1] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S1[i0, i1, i2] -> [0, i0, 0, -3 + 2i1, 2, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= M; S4[i0, i1, i2] -> [2, i0, 0, i1, 1, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S2[i0, i1, i2] -> [1, i0, 0, 2i1, 0, i2, 1] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= M; S7[i0, i1, i2] -> [0, i0, 0, -2 + 2i1, 2, i2, 1] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S10[i0, i1, i2] -> [0, i0, 0, 1 + 2i1, 0, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S3[i0, i1, i2] -> [0, i0, 0, -1 + 2i1, 1, i2, 2] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= M; S15[i0, i1, i2] -> [7, i0, 1, i1, 1, i2, 0] : i0 >= R and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S5[i0, i1, i2] -> [3, i0, 0, i1, 1, i2, 1] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S13[i0, i1, i2] -> [5, i0, 0, i1, 1, i2, 0] : i0 >= R and i0 <= -1 + O and i1 >= Q and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S12[i0, i1, i2] -> [4, i0, 0, i1, 0, i2, 0] : i0 >= R and i0 <= -1 + O and i1 >= Q and i1 <= -1 + N and i2 >= P and i2 <= -1 + M; S14[i0, i1, i2] -> [6, i0, 1, i1, 0, i2, 0] : i0 >= R and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= P and i2 <= -1 + M }
+[M, N, O, P, Q, R, S, T, U] -> {  :  }
+[M, N, O, P, Q, R, S, T, U] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-mg-interp2.c b/test_inputs/codegen/cloog/reservoir-mg-interp2.c
new file mode 100644 (file)
index 0000000..5a8a4fc
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  for (int c1 = 1; c1 <= O - 1; c1 += 1)
+    for (int c3 = Q; c3 <= N - 1; c3 += 1)
+      for (int c5 = P; c5 <= M - 1; c5 += 1)
+        S1(c1, c3, c5);
+  for (int c1 = 1; c1 <= O - 1; c1 += 1)
+    for (int c3 = Q; c3 <= N - 1; c3 += 1)
+      for (int c5 = 1; c5 <= M - 1; c5 += 1)
+        S2(c1, c3, c5);
+  for (int c1 = 1; c1 <= O - 1; c1 += 1)
+    for (int c3 = 1; c3 <= N - 1; c3 += 1)
+      for (int c5 = P; c5 <= M - 1; c5 += 1)
+        S3(c1, c3, c5);
+  for (int c1 = 1; c1 <= O - 1; c1 += 1)
+    for (int c3 = 1; c3 <= N - 1; c3 += 1)
+      for (int c5 = 1; c5 <= M - 1; c5 += 1)
+        S4(c1, c3, c5);
+}
diff --git a/test_inputs/codegen/cloog/reservoir-mg-interp2.in b/test_inputs/codegen/cloog/reservoir-mg-interp2.in
new file mode 100644 (file)
index 0000000..8a5dfb1
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N, O, P, Q, R, S, T, U] -> { S1[i0, i1, i2] -> [0, i0, 0, i1, 0, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= Q and i1 <= -1 + N and i2 >= P and i2 <= -1 + M; S4[i0, i1, i2] -> [3, i0, 1, i1, 1, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S2[i0, i1, i2] -> [1, i0, 0, i1, 1, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= Q and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S3[i0, i1, i2] -> [2, i0, 1, i1, 0, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= P and i2 <= -1 + M }
+[M, N, O, P, Q, R, S, T, U] -> {  :  }
+[M, N, O, P, Q, R, S, T, U] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-mg-psinv.c b/test_inputs/codegen/cloog/reservoir-mg-psinv.c
new file mode 100644 (file)
index 0000000..a7b3e87
--- /dev/null
@@ -0,0 +1,9 @@
+for (int c1 = 2; c1 <= O - 1; c1 += 1)
+  for (int c3 = 3; c3 <= 2 * N - 3; c3 += 2) {
+    for (int c5 = 1; c5 <= M; c5 += 1) {
+      S1(c1, (c3 + 1) / 2, c5);
+      S2(c1, (c3 + 1) / 2, c5);
+    }
+    for (int c5 = 2; c5 <= M - 1; c5 += 1)
+      S3(c1, (c3 + 1) / 2, c5);
+  }
diff --git a/test_inputs/codegen/cloog/reservoir-mg-psinv.in b/test_inputs/codegen/cloog/reservoir-mg-psinv.in
new file mode 100644 (file)
index 0000000..835f81a
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N, O] -> { S1[i0, i1, i2] -> [0, i0, 0, -1 + 2i1, 0, i2, 0] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 1 and i2 <= M; S2[i0, i1, i2] -> [0, i0, 0, -1 + 2i1, 0, i2, 1] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 1 and i2 <= M; S3[i0, i1, i2] -> [0, i0, 0, 2i1, 1, i2, 0] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + M }
+[M, N, O] -> {  :  }
+[M, N, O] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-mg-resid.c b/test_inputs/codegen/cloog/reservoir-mg-resid.c
new file mode 100644 (file)
index 0000000..a7b3e87
--- /dev/null
@@ -0,0 +1,9 @@
+for (int c1 = 2; c1 <= O - 1; c1 += 1)
+  for (int c3 = 3; c3 <= 2 * N - 3; c3 += 2) {
+    for (int c5 = 1; c5 <= M; c5 += 1) {
+      S1(c1, (c3 + 1) / 2, c5);
+      S2(c1, (c3 + 1) / 2, c5);
+    }
+    for (int c5 = 2; c5 <= M - 1; c5 += 1)
+      S3(c1, (c3 + 1) / 2, c5);
+  }
diff --git a/test_inputs/codegen/cloog/reservoir-mg-resid.in b/test_inputs/codegen/cloog/reservoir-mg-resid.in
new file mode 100644 (file)
index 0000000..835f81a
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N, O] -> { S1[i0, i1, i2] -> [0, i0, 0, -1 + 2i1, 0, i2, 0] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 1 and i2 <= M; S2[i0, i1, i2] -> [0, i0, 0, -1 + 2i1, 0, i2, 1] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 1 and i2 <= M; S3[i0, i1, i2] -> [0, i0, 0, 2i1, 1, i2, 0] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + M }
+[M, N, O] -> {  :  }
+[M, N, O] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-mg-rprj3.c b/test_inputs/codegen/cloog/reservoir-mg-rprj3.c
new file mode 100644 (file)
index 0000000..3e25bdc
--- /dev/null
@@ -0,0 +1,33 @@
+if (N >= 3 && M >= 2)
+  for (int c1 = 2; c1 <= O - 1; c1 += 1) {
+    for (int c5 = 2; c5 <= M; c5 += 1)
+      S1(c1, 2, c5);
+    for (int c3 = 3; c3 <= N - 1; c3 += 1) {
+      for (int c5 = 2; c5 <= M; c5 += 1)
+        S2(c1, c3 - 1, c5);
+      if (M >= 3) {
+        S4(c1, c3 - 1, 2);
+        for (int c5 = 2; c5 <= M - 2; c5 += 1) {
+          S3(c1, c3 - 1, c5);
+          S5(c1, c3 - 1, c5);
+          S4(c1, c3 - 1, c5 + 1);
+        }
+        S3(c1, c3 - 1, M - 1);
+        S5(c1, c3 - 1, M - 1);
+      }
+      for (int c5 = 2; c5 <= M; c5 += 1)
+        S1(c1, c3, c5);
+    }
+    for (int c5 = 2; c5 <= M; c5 += 1)
+      S2(c1, N - 1, c5);
+    if (M >= 3) {
+      S4(c1, N - 1, 2);
+      for (int c5 = 2; c5 <= M - 2; c5 += 1) {
+        S3(c1, N - 1, c5);
+        S5(c1, N - 1, c5);
+        S4(c1, N - 1, c5 + 1);
+      }
+      S3(c1, N - 1, M - 1);
+      S5(c1, N - 1, M - 1);
+    }
+  }
diff --git a/test_inputs/codegen/cloog/reservoir-mg-rprj3.in b/test_inputs/codegen/cloog/reservoir-mg-rprj3.in
new file mode 100644 (file)
index 0000000..03f4134
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N, O, P, Q, R] -> { S1[i0, i1, i2] -> [0, i0, 0, i1, 2, i2, 0] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= M; S4[i0, i1, i2] -> [0, i0, 0, 1 + i1, 1, -1 + i2, 2] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + M; S3[i0, i1, i2] -> [0, i0, 0, 1 + i1, 1, i2, 0] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + M; S5[i0, i1, i2] -> [0, i0, 0, 1 + i1, 1, i2, 1] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + M; S2[i0, i1, i2] -> [0, i0, 0, 1 + i1, 0, i2, 1] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= M }
+[M, N, O, P, Q, R] -> {  :  }
+[M, N, O, P, Q, R] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-pingali1.c b/test_inputs/codegen/cloog/reservoir-pingali1.c
new file mode 100644 (file)
index 0000000..cff4b8e
--- /dev/null
@@ -0,0 +1,7 @@
+for (int c1 = 1; c1 <= M; c1 += 1)
+  for (int c3 = 1; c3 <= 2 * N - 1; c3 += 1) {
+    for (int c5 = max(1, -N + c3); c5 <= (c3 + 1) / 2 - 1; c5 += 1)
+      S1(c1, c3 - c5, c5);
+    if ((c3 - 1) % 2 == 0)
+      S2(c1, (c3 + 1) / 2);
+  }
diff --git a/test_inputs/codegen/cloog/reservoir-pingali1.in b/test_inputs/codegen/cloog/reservoir-pingali1.in
new file mode 100644 (file)
index 0000000..ecbb320
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0, i1, i2] -> [0, i0, 0, i1 + i2, 0, i2, 0] : i0 >= 1 and i0 <= M and i1 <= N and i2 >= 1 and i2 <= -1 + i1; S2[i0, i1] -> [0, i0, 0, -1 + 2i1, 1, 0, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= N }
+[M, N] -> {  :  }
+[M, N] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-pingali2.c b/test_inputs/codegen/cloog/reservoir-pingali2.c
new file mode 100644 (file)
index 0000000..a407cad
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S1(c1, c3);
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S2(c1, c3);
+}
diff --git a/test_inputs/codegen/cloog/reservoir-pingali2.in b/test_inputs/codegen/cloog/reservoir-pingali2.in
new file mode 100644 (file)
index 0000000..9ba248f
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [1, i0, 1, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M; S1[i0, i1] -> [0, i0, 0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-pingali3.c b/test_inputs/codegen/cloog/reservoir-pingali3.c
new file mode 100644 (file)
index 0000000..c281b82
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S1(c1, c3);
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      for (int c5 = 1; c5 <= M; c5 += 1)
+        S2(c1, c3, c5);
+}
diff --git a/test_inputs/codegen/cloog/reservoir-pingali3.in b/test_inputs/codegen/cloog/reservoir-pingali3.in
new file mode 100644 (file)
index 0000000..70da8ea
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1, i2] -> [1, i0, 0, i1, 1, i2, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M and i2 >= 1 and i2 <= M; S1[i0, i1] -> [0, i0, 0, i1, 0, 0, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-pingali4.c b/test_inputs/codegen/cloog/reservoir-pingali4.c
new file mode 100644 (file)
index 0000000..a407cad
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S1(c1, c3);
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    for (int c3 = 1; c3 <= M; c3 += 1)
+      S2(c1, c3);
+}
diff --git a/test_inputs/codegen/cloog/reservoir-pingali4.in b/test_inputs/codegen/cloog/reservoir-pingali4.in
new file mode 100644 (file)
index 0000000..e975fae
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [1, i0, 0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M; S1[i0, i1] -> [0, i0, 0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M }
+[M] -> {  : M >= 2 }
+[M] -> { [i, j, k, l, m] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-pingali5.c b/test_inputs/codegen/cloog/reservoir-pingali5.c
new file mode 100644 (file)
index 0000000..1d337c0
--- /dev/null
@@ -0,0 +1,10 @@
+for (int c1 = 3; c1 <= 2 * M - 1; c1 += 1) {
+  for (int c3 = c1 - (c1 + 1) / 2 + 2; c3 <= M; c3 += 1)
+    for (int c7 = c1 - (c1 + 1) / 2 + 1; c7 <= min(c1 - 1, c3 - 1); c7 += 1)
+      S1(c7, c1 - c7, c3);
+  for (int c3 = max(1, -M + c1); c3 <= (c1 + 1) / 2 - 1; c3 += 1)
+    S2(c1 - c3, c3);
+  for (int c3 = c1 - (c1 + 1) / 2 + 2; c3 <= M; c3 += 1)
+    for (int c7 = c1 - (c1 + 1) / 2 + 1; c7 <= min(c1 - 1, c3 - 1); c7 += 1)
+      S3(c7, c1 - c7, c3);
+}
diff --git a/test_inputs/codegen/cloog/reservoir-pingali5.in b/test_inputs/codegen/cloog/reservoir-pingali5.in
new file mode 100644 (file)
index 0000000..1b77acd
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1, i2] -> [0, i0 + i1, 0, i2, 0, i2, 0] : i1 >= 1 and i1 <= -1 + i0 and i2 >= 1 + i0 and i2 <= M; S3[i0, i1, i2] -> [0, i0 + i1, 2, i2, 2, i2, 0] : i1 >= 1 and i1 <= -1 + i0 and i2 >= 1 + i0 and i2 <= M; S2[i0, i1] -> [0, i0 + i1, 1, i1, 1, 0, 0] : i0 <= M and i1 >= 1 and i1 <= -1 + i0 }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-pingali6.c b/test_inputs/codegen/cloog/reservoir-pingali6.c
new file mode 100644 (file)
index 0000000..011b912
--- /dev/null
@@ -0,0 +1,8 @@
+for (int c1 = 1; c1 <= M; c1 += 1) {
+  for (int c3 = 2; c3 <= N - 1; c3 += 1)
+    for (int c5 = 2; c5 <= N - 1; c5 += 1)
+      S1(c1, c3, c5);
+  for (int c3 = 2; c3 <= N - 1; c3 += 1)
+    for (int c5 = 2; c5 <= N - 1; c5 += 1)
+      S2(c1, c3, c5);
+}
diff --git a/test_inputs/codegen/cloog/reservoir-pingali6.in b/test_inputs/codegen/cloog/reservoir-pingali6.in
new file mode 100644 (file)
index 0000000..7a08ca7
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S2[i0, i1, i2] -> [0, 1 + 2i0, 1, i1, 0, i2, 0] : i0 >= 1 and i0 <= M and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + N; S1[i0, i1, i2] -> [0, 2i0, 0, i1, 0, i2, 0] : i0 >= 1 and i0 <= M and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + N }
+[M, N] -> {  : M >= 1 and N >= 1 }
+[M, N] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-stride.c b/test_inputs/codegen/cloog/reservoir-stride.c
new file mode 100644 (file)
index 0000000..104e262
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c1 = 2; c1 <= M; c1 += 7)
+  S1(c1, (c1 - 2) / 7);
diff --git a/test_inputs/codegen/cloog/reservoir-stride.in b/test_inputs/codegen/cloog/reservoir-stride.in
new file mode 100644 (file)
index 0000000..46a1c35
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1] -> [0, i0, 0, 0, 0] : 7i1 = -2 + i0 and i0 >= 2 and i0 <= M }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-stride2.c b/test_inputs/codegen/cloog/reservoir-stride2.c
new file mode 100644 (file)
index 0000000..104e262
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c1 = 2; c1 <= M; c1 += 7)
+  S1(c1, (c1 - 2) / 7);
diff --git a/test_inputs/codegen/cloog/reservoir-stride2.in b/test_inputs/codegen/cloog/reservoir-stride2.in
new file mode 100644 (file)
index 0000000..be6b197
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1] -> [0, i0, 0, 0, 0] : 7i1 = -2 + i0 and i0 >= 0 and i0 <= M }
+[M] -> {  :  }
+[M] -> { [i, j, k, l, m] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-tang-xue1.c b/test_inputs/codegen/cloog/reservoir-tang-xue1.c
new file mode 100644 (file)
index 0000000..230665a
--- /dev/null
@@ -0,0 +1,5 @@
+for (int c1 = 0; c1 <= 9; c1 += 2)
+  for (int c3 = 0; c3 <= min(c1 + 3, 4); c3 += 2)
+    for (int c5 = max(1, c1); c5 <= min(c1 - c3 + 4, c1 + 1); c5 += 1)
+      for (int c7 = max(-c1 + c3 + c5, 1); c7 <= min(4, -c1 + c3 + c5 + 1); c7 += 1)
+        S1(c1 / 2, (-c1 + c3) / 2, -c1 + c5, -c3 + c7);
diff --git a/test_inputs/codegen/cloog/reservoir-tang-xue1.in b/test_inputs/codegen/cloog/reservoir-tang-xue1.in
new file mode 100644 (file)
index 0000000..0c9ffc9
--- /dev/null
@@ -0,0 +1,3 @@
+{ S1[i0, i1, i2, i3] -> [0, 2i0, 0, 2i0 + 2i1, 0, 2i0 + i2, 0, 2i0 + 2i1 + i3, 0] : i3 <= 4 - 2i0 - 2i1 and i3 >= i2 and i2 <= 9 - 2i0 and i2 >= 0 and i2 >= 1 - 2i0 and i3 <= 1 + i2 and i2 <= 1 and i3 >= 1 - 2i0 - 2i1 }
+{  :  }
+{ [i, j, k, l, m, n, o, p, q] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/reservoir-two.c b/test_inputs/codegen/cloog/reservoir-two.c
new file mode 100644 (file)
index 0000000..3946c42
--- /dev/null
@@ -0,0 +1 @@
+S1(1, 1, 5);
diff --git a/test_inputs/codegen/cloog/reservoir-two.in b/test_inputs/codegen/cloog/reservoir-two.in
new file mode 100644 (file)
index 0000000..a7eb204
--- /dev/null
@@ -0,0 +1,3 @@
+{ S1[i0, i1, i2] -> [i0, j, k, 0] : 2i1 = 3 - i0 and 2j = 3 - i0 and 2k = 9 + i0 and 2i2 = 9 + i0 and i0 >= 0 and i0 <= 1 }
+{  :  }
+{ [i, j, k, l] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/singleton.c b/test_inputs/codegen/cloog/singleton.c
new file mode 100644 (file)
index 0000000..0023bc6
--- /dev/null
@@ -0,0 +1,4 @@
+{
+  S2();
+  S1();
+}
diff --git a/test_inputs/codegen/cloog/singleton.in b/test_inputs/codegen/cloog/singleton.in
new file mode 100644 (file)
index 0000000..a0a5a8a
--- /dev/null
@@ -0,0 +1,3 @@
+{ S2[] -> [-1]; S1[] -> [0] }
+{  :  }
+{ [i] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/square+triangle-1-1-2-3.c b/test_inputs/codegen/cloog/square+triangle-1-1-2-3.c
new file mode 100644 (file)
index 0000000..316213f
--- /dev/null
@@ -0,0 +1,9 @@
+for (int c0 = 1; c0 <= M; c0 += 1) {
+  S1(c0, 1);
+  for (int c1 = 2; c1 <= c0; c1 += 1) {
+    S1(c0, c1);
+    S2(c0, c1);
+  }
+  for (int c1 = c0 + 1; c1 <= M; c1 += 1)
+    S1(c0, c1);
+}
diff --git a/test_inputs/codegen/cloog/square+triangle-1-1-2-3.in b/test_inputs/codegen/cloog/square+triangle-1-1-2-3.in
new file mode 100644 (file)
index 0000000..028c792
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [i0, i1, 1] : i1 >= 2 and i1 <= i0 and i0 <= M; S1[i0, i1] -> [i0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M }
+[M] -> {  : M >= 1 }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/stride.c b/test_inputs/codegen/cloog/stride.c
new file mode 100644 (file)
index 0000000..9bd4ddf
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  for (int c0 = 3; c0 <= 24; c0 += 3)
+    S2(c0, c0 / 3);
+  S1(25);
+  for (int c0 = 27; c0 <= 100; c0 += 3)
+    S2(c0, c0 / 3);
+}
diff --git a/test_inputs/codegen/cloog/stride.in b/test_inputs/codegen/cloog/stride.in
new file mode 100644 (file)
index 0000000..410c684
--- /dev/null
@@ -0,0 +1,3 @@
+{ S1[25] -> [25, 0]; S2[i0, i1] -> [i0, j] : 3i1 = i0 and 3j = i0 and i0 >= 3 and i0 <= 100 }
+{  :  }
+{ [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/stride2.c b/test_inputs/codegen/cloog/stride2.c
new file mode 100644 (file)
index 0000000..c56af8e
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  for (int c0 = 3; c0 <= 26; c0 += 3)
+    S2(c0, c0 / 3);
+  S1(27);
+  S2(27, 9);
+  for (int c0 = 30; c0 <= 100; c0 += 3)
+    S2(c0, c0 / 3);
+}
diff --git a/test_inputs/codegen/cloog/stride2.in b/test_inputs/codegen/cloog/stride2.in
new file mode 100644 (file)
index 0000000..97e4086
--- /dev/null
@@ -0,0 +1,3 @@
+{ S1[27] -> [27, 0]; S2[i0, i1] -> [i0, j] : 3i1 = i0 and 3j = i0 and i0 >= 3 and i0 <= 100 }
+{  :  }
+{ [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/stride3.c b/test_inputs/codegen/cloog/stride3.c
new file mode 100644 (file)
index 0000000..d145938
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = max(1, m); c0 <= n; c0 += 1)
+  S1(c0);
diff --git a/test_inputs/codegen/cloog/stride3.in b/test_inputs/codegen/cloog/stride3.in
new file mode 100644 (file)
index 0000000..9b87b89
--- /dev/null
@@ -0,0 +1,3 @@
+[m, n] -> { S1[i0] -> [50i0, 0] : i0 >= 1 and i0 <= n and i0 >= m }
+[m, n] -> {  :  }
+[m, n] -> { [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/stride4.c b/test_inputs/codegen/cloog/stride4.c
new file mode 100644 (file)
index 0000000..d65e4b1
--- /dev/null
@@ -0,0 +1,3 @@
+if (t <= 15 && t >= 0)
+  for (int c0 = t; c0 <= 99; c0 += 16)
+    S1(c0, t);
diff --git a/test_inputs/codegen/cloog/stride4.in b/test_inputs/codegen/cloog/stride4.in
new file mode 100644 (file)
index 0000000..436cad3
--- /dev/null
@@ -0,0 +1,3 @@
+[t] -> { S1[i0, t] -> [i0, t, 0] : exists (e0 = [(t - i0)/16]: 16e0 = t - i0 and i0 >= 0 and i0 <= 99 and t >= 0 and t <= 15) }
+[t] -> {  :  }
+[t] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/swim.c b/test_inputs/codegen/cloog/swim.c
new file mode 100644 (file)
index 0000000..47b4ebe
--- /dev/null
@@ -0,0 +1,159 @@
+if (M == 1) {
+  S1();
+  S2();
+  S3();
+  S4();
+  S5();
+  S6();
+  S7();
+  S8();
+  S9();
+  S10();
+  S11();
+  S12();
+  S13();
+  S14();
+  S15();
+  S16();
+  S17();
+  S18();
+  S19();
+  S20();
+  S21();
+  S22();
+  S23();
+  S24();
+  S25();
+  S26();
+  S27();
+  for (int c1 = 1; c1 <= N; c1 += 1) {
+    for (int c3 = 1; c3 <= N; c3 += 1) {
+      S28(c1, c3);
+      S29(c1, c3);
+      S30(c1, c3);
+    }
+    S31(c1);
+  }
+  S32();
+  S33();
+  S34();
+  if (O <= 1)
+    S35();
+  S36();
+  S37();
+  for (int c1 = 2; c1 <= P; c1 += 1) {
+    S38(c1);
+    S39(c1);
+    for (int c3 = 1; c3 <= Q; c3 += 1)
+      for (int c5 = 1; c5 <= R; c5 += 1) {
+        S40(c1, c3, c5);
+        S41(c1, c3, c5);
+        S42(c1, c3, c5);
+        S43(c1, c3, c5);
+      }
+    for (int c3 = 1; c3 <= Q; c3 += 1) {
+      S44(c1, c3);
+      S45(c1, c3);
+      S46(c1, c3);
+      S47(c1, c3);
+    }
+    for (int c3 = 1; c3 <= R; c3 += 1) {
+      S48(c1, c3);
+      S49(c1, c3);
+      S50(c1, c3);
+      S51(c1, c3);
+    }
+    S52(c1);
+    S53(c1);
+    S54(c1);
+    S55(c1);
+    S56(c1);
+    S57(c1);
+    S58(c1);
+    for (int c3 = 1; c3 <= Q; c3 += 1)
+      for (int c5 = 1; c5 <= R; c5 += 1) {
+        S59(c1, c3, c5);
+        S60(c1, c3, c5);
+        S61(c1, c3, c5);
+      }
+    for (int c3 = 1; c3 <= Q; c3 += 1) {
+      S62(c1, c3);
+      S63(c1, c3);
+      S64(c1, c3);
+    }
+    for (int c3 = 1; c3 <= R; c3 += 1) {
+      S65(c1, c3);
+      S66(c1, c3);
+      S67(c1, c3);
+    }
+    S68(c1);
+    S69(c1);
+    S70(c1);
+    S71(c1);
+    S72(c1);
+    S73(c1);
+    S74(c1);
+    S75(c1);
+    S76(c1);
+    S77(c1);
+    S78(c1);
+    S79(c1);
+    S80(c1);
+    S81(c1);
+    S82(c1);
+    S83(c1);
+    S84(c1);
+    S85(c1);
+    S86(c1);
+    S87(c1);
+    S88(c1);
+    S89(c1);
+    S90(c1);
+    S91(c1);
+    S92(c1);
+    S93(c1);
+    S94(c1);
+    for (int c3 = 1; c3 <= N; c3 += 1) {
+      for (int c5 = 1; c5 <= N; c5 += 1) {
+        S95(c1, c3, c5);
+        S96(c1, c3, c5);
+        S97(c1, c3, c5);
+      }
+      S98(c1, c3);
+    }
+    S99(c1);
+    S100(c1);
+    S101(c1);
+    for (int c3 = 1; c3 <= Q; c3 += 1)
+      for (int c5 = 1; c5 <= R; c5 += 1) {
+        S102(c1, c3, c5);
+        S103(c1, c3, c5);
+        S104(c1, c3, c5);
+        S105(c1, c3, c5);
+        S106(c1, c3, c5);
+        S107(c1, c3, c5);
+      }
+    for (int c3 = 1; c3 <= Q; c3 += 1) {
+      S108(c1, c3);
+      S109(c1, c3);
+      S110(c1, c3);
+      S111(c1, c3);
+      S112(c1, c3);
+      S113(c1, c3);
+    }
+    for (int c3 = 1; c3 <= R; c3 += 1) {
+      S114(c1, c3);
+      S115(c1, c3);
+      S116(c1, c3);
+      S117(c1, c3);
+      S118(c1, c3);
+      S119(c1, c3);
+    }
+    S120(c1);
+    S121(c1);
+    S122(c1);
+    S123(c1);
+    S124(c1);
+    S125(c1);
+  }
+}
diff --git a/test_inputs/codegen/cloog/swim.in b/test_inputs/codegen/cloog/swim.in
new file mode 100644 (file)
index 0000000..4661ff0
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N, O, P, Q, R] -> { S84[i0] -> [34, i0, 31, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S6[] -> [5, 0, 0, 0, 0, 0, 0] : M = 1; S25[] -> [24, 0, 0, 0, 0, 0, 0] : M = 1; S115[i0, i1] -> [34, i0, 48, i1, 1, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S64[i0, i1] -> [34, i0, 13, i1, 2, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S62[i0, i1] -> [34, i0, 13, i1, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S40[i0, i1, i2] -> [34, i0, 2, i1, 0, i2, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S123[i0] -> [34, i0, 52, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S5[] -> [4, 0, 0, 0, 0, 0, 0] : M = 1; S15[] -> [14, 0, 0, 0, 0, 0, 0] : M = 1; S76[i0] -> [34, i0, 23, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S39[i0] -> [34, i0, 1, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S13[] -> [12, 0, 0, 0, 0, 0, 0] : M = 1; S28[i0, i1] -> [27, i0, 0, i1, 0, 0, 0] : M = 1 and i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= N; S70[i0] -> [34, i0, 17, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S53[i0] -> [34, i0, 6, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S121[i0] -> [34, i0, 50, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S47[i0, i1] -> [34, i0, 3, i1, 3, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S59[i0, i1, i2] -> [34, i0, 12, i1, 0, i2, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S71[i0] -> [34, i0, 18, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S77[i0] -> [34, i0, 24, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S63[i0, i1] -> [34, i0, 13, i1, 1, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S51[i0, i1] -> [34, i0, 4, i1, 3, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S100[i0] -> [34, i0, 44, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S22[] -> [21, 0, 0, 0, 0, 0, 0] : M = 1; S95[i0, i1, i2] -> [34, i0, 42, i1, 0, i2, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= N and i2 >= 1 and i2 <= N; S8[] -> [7, 0, 0, 0, 0, 0, 0] : M = 1; S120[i0] -> [34, i0, 49, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S50[i0, i1] -> [34, i0, 4, i1, 2, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S45[i0, i1] -> [34, i0, 3, i1, 1, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S72[i0] -> [34, i0, 19, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S52[i0] -> [34, i0, 5, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S7[] -> [6, 0, 0, 0, 0, 0, 0] : M = 1; S78[i0] -> [34, i0, 25, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S110[i0, i1] -> [34, i0, 47, i1, 2, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S124[i0] -> [34, i0, 53, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S60[i0, i1, i2] -> [34, i0, 12, i1, 0, i2, 1] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S27[] -> [26, 0, 0, 0, 0, 0, 0] : M = 1; S114[i0, i1] -> [34, i0, 48, i1, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S49[i0, i1] -> [34, i0, 4, i1, 1, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S94[i0] -> [34, i0, 41, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S57[i0] -> [34, i0, 10, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S66[i0, i1] -> [34, i0, 14, i1, 1, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S18[] -> [17, 0, 0, 0, 0, 0, 0] : M = 1; S92[i0] -> [34, i0, 39, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S3[] -> [2, 0, 0, 0, 0, 0, 0] : M = 1; S35[] -> [31, 0, 0, 0, 0, 0, 0] : M = 1 and O <= 1; S36[] -> [32, 0, 0, 0, 0, 0, 0] : M = 1; S10[] -> [9, 0, 0, 0, 0, 0, 0] : M = 1; S2[] -> [1, 0, 0, 0, 0, 0, 0] : M = 1; S48[i0, i1] -> [34, i0, 4, i1, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S30[i0, i1] -> [27, i0, 0, i1, 2, 0, 0] : M = 1 and i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= N; S75[i0] -> [34, i0, 22, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S83[i0] -> [34, i0, 30, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S87[i0] -> [34, i0, 34, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S88[i0] -> [34, i0, 35, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S33[] -> [29, 0, 0, 0, 0, 0, 0] : M = 1; S101[i0] -> [34, i0, 45, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S21[] -> [20, 0, 0, 0, 0, 0, 0] : M = 1; S32[] -> [28, 0, 0, 0, 0, 0, 0] : M = 1; S118[i0, i1] -> [34, i0, 48, i1, 4, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S79[i0] -> [34, i0, 26, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S38[i0] -> [34, i0, 0, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S108[i0, i1] -> [34, i0, 47, i1, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S65[i0, i1] -> [34, i0, 14, i1, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S91[i0] -> [34, i0, 38, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S17[] -> [16, 0, 0, 0, 0, 0, 0] : M = 1; S80[i0] -> [34, i0, 27, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S54[i0] -> [34, i0, 7, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S46[i0, i1] -> [34, i0, 3, i1, 2, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S68[i0] -> [34, i0, 15, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S116[i0, i1] -> [34, i0, 48, i1, 2, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S43[i0, i1, i2] -> [34, i0, 2, i1, 0, i2, 3] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S26[] -> [25, 0, 0, 0, 0, 0, 0] : M = 1; S31[i0] -> [27, i0, 1, 0, 0, 0, 0] : M = 1 and i0 >= 1 and i0 <= N; S69[i0] -> [34, i0, 16, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S24[] -> [23, 0, 0, 0, 0, 0, 0] : M = 1; S90[i0] -> [34, i0, 37, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S89[i0] -> [34, i0, 36, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S82[i0] -> [34, i0, 29, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S67[i0, i1] -> [34, i0, 14, i1, 2, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S58[i0] -> [34, i0, 11, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S109[i0, i1] -> [34, i0, 47, i1, 1, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S122[i0] -> [34, i0, 51, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S61[i0, i1, i2] -> [34, i0, 12, i1, 0, i2, 2] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S1[] -> [0, 0, 0, 0, 0, 0, 0] : M = 1; S4[] -> [3, 0, 0, 0, 0, 0, 0] : M = 1; S86[i0] -> [34, i0, 33, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S14[] -> [13, 0, 0, 0, 0, 0, 0] : M = 1; S93[i0] -> [34, i0, 40, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S56[i0] -> [34, i0, 9, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S37[] -> [33, 0, 0, 0, 0, 0, 0] : M = 1; S125[i0] -> [34, i0, 54, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S96[i0, i1, i2] -> [34, i0, 42, i1, 0, i2, 1] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= N and i2 >= 1 and i2 <= N; S9[] -> [8, 0, 0, 0, 0, 0, 0] : M = 1; S41[i0, i1, i2] -> [34, i0, 2, i1, 0, i2, 1] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S102[i0, i1, i2] -> [34, i0, 46, i1, 0, i2, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S112[i0, i1] -> [34, i0, 47, i1, 4, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S16[] -> [15, 0, 0, 0, 0, 0, 0] : M = 1; S85[i0] -> [34, i0, 32, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S42[i0, i1, i2] -> [34, i0, 2, i1, 0, i2, 2] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S12[] -> [11, 0, 0, 0, 0, 0, 0] : M = 1; S55[i0] -> [34, i0, 8, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S11[] -> [10, 0, 0, 0, 0, 0, 0] : M = 1; S19[] -> [18, 0, 0, 0, 0, 0, 0] : M = 1; S107[i0, i1, i2] -> [34, i0, 46, i1, 0, i2, 5] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S98[i0, i1] -> [34, i0, 42, i1, 1, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= N; S104[i0, i1, i2] -> [34, i0, 46, i1, 0, i2, 2] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S29[i0, i1] -> [27, i0, 0, i1, 1, 0, 0] : M = 1 and i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= N; S20[] -> [19, 0, 0, 0, 0, 0, 0] : M = 1; S103[i0, i1, i2] -> [34, i0, 46, i1, 0, i2, 1] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S105[i0, i1, i2] -> [34, i0, 46, i1, 0, i2, 3] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S97[i0, i1, i2] -> [34, i0, 42, i1, 0, i2, 2] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= N and i2 >= 1 and i2 <= N; S44[i0, i1] -> [34, i0, 3, i1, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S106[i0, i1, i2] -> [34, i0, 46, i1, 0, i2, 4] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S34[] -> [30, 0, 0, 0, 0, 0, 0] : M = 1; S111[i0, i1] -> [34, i0, 47, i1, 3, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S99[i0] -> [34, i0, 43, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S81[i0] -> [34, i0, 28, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S23[] -> [22, 0, 0, 0, 0, 0, 0] : M = 1; S117[i0, i1] -> [34, i0, 48, i1, 3, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S74[i0] -> [34, i0, 21, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S113[i0, i1] -> [34, i0, 47, i1, 5, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S119[i0, i1] -> [34, i0, 48, i1, 5, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S73[i0] -> [34, i0, 20, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P }
+[M, N, O, P, Q, R] -> {  :  }
+[M, N, O, P, Q, R] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/test.c b/test_inputs/codegen/cloog/test.c
new file mode 100644 (file)
index 0000000..84c8493
--- /dev/null
@@ -0,0 +1,17 @@
+{
+  for (int c0 = 1; c0 <= 2; c0 += 1)
+    for (int c1 = 1; c1 <= M; c1 += 1)
+      S1(c0, c1);
+  for (int c0 = 3; c0 <= N; c0 += 1) {
+    for (int c1 = 1; c1 <= min(M, c0 - 1); c1 += 1)
+      S1(c0, c1);
+    if (M >= c0) {
+      S1(c0, c0);
+      S2(c0, c0);
+    }
+    for (int c1 = c0 + 1; c1 <= M; c1 += 1)
+      S1(c0, c1);
+    if (c0 >= M + 1)
+      S2(c0, c0);
+  }
+}
diff --git a/test_inputs/codegen/cloog/test.in b/test_inputs/codegen/cloog/test.in
new file mode 100644 (file)
index 0000000..981d933
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0, i1] -> [i0, i1, 0] : i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= M; S2[i0, i0] -> [i0, i0, 1] : i0 >= 3 and i0 <= N }
+[M, N] -> {  : N >= M and M >= 4 }
+[M, N] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/thomasset.c b/test_inputs/codegen/cloog/thomasset.c
new file mode 100644 (file)
index 0000000..c5ad4ce
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  for (int c0 = 0; c0 <= floord(n - 1, 3); c0 += 1)
+    for (int c2 = 3 * c0 + 1; c2 <= min(n, 3 * c0 + 3); c2 += 1)
+      S1(c2, c0);
+  for (int c0 = floord(n, 3); c0 <= floord(n, 3) + floord(n, 3); c0 += 1)
+    for (int c1 = 0; c1 <= n - 1; c1 += 1)
+      for (int c3 = max(-n + 3 * c0, 1); c3 <= min(-n + 3 * c0 + 4, n); c3 += 1)
+        if (((3 * c0 - c3 + 2) % 3) + n + c3 >= 3 * c0 + 2 && 3 * c0 + 4 >= ((3 * c0 - c3 + 2) % 3) + n + c3)
+          S2(c1 + 1, c3, 0, n / 3, c0 - n / 3);
+}
diff --git a/test_inputs/codegen/cloog/thomasset.in b/test_inputs/codegen/cloog/thomasset.in
new file mode 100644 (file)
index 0000000..398e523
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { S2[i0, i1, 0, i3, i4] -> [i3 + i4, -1 + i0] : i0 <= n and i1 <= n and i1 >= 1 and i0 >= 1 and 3i4 <= i1 and 3i4 >= -2 + i1 and 3i3 <= n and 3i3 >= -2 + n; S1[i0, i1] -> [i1, 0] : i0 <= n and i0 >= 1 and 3i1 <= -1 + i0 and 3i1 >= -3 + i0 }
+[n] -> {  :  }
+[n] -> { [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/tiling.c b/test_inputs/codegen/cloog/tiling.c
new file mode 100644 (file)
index 0000000..971b988
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= n / 10; c0 += 1)
+  for (int c1 = 10 * c0; c1 <= min(n, 10 * c0 + 9); c1 += 1)
+    S1(c0, c1);
diff --git a/test_inputs/codegen/cloog/tiling.in b/test_inputs/codegen/cloog/tiling.in
new file mode 100644 (file)
index 0000000..6f0530f
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { S1[ii, i] -> [ii, i, 0] : i >= 0 and i <= n and i <= 9 + 10ii and i >= 10ii }
+[n] -> {  : n >= 0 }
+[n] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/uday_scalars.c b/test_inputs/codegen/cloog/uday_scalars.c
new file mode 100644 (file)
index 0000000..d8002a8
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  for (int c2 = 0; c2 <= n; c2 += 1)
+    S1(c2, 0, 0);
+  for (int c2 = 0; c2 <= n; c2 += 1)
+    S2(0, c2, 0);
+}
diff --git a/test_inputs/codegen/cloog/uday_scalars.in b/test_inputs/codegen/cloog/uday_scalars.in
new file mode 100644 (file)
index 0000000..ae29bb5
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { S1[i0, 0, 0] -> [0, 1, i0, 0] : i0 >= 0 and i0 <= n; S2[0, i1, 0] -> [1, 0, i1, 1] : i1 >= 0 and i1 <= n }
+[n] -> {  :  }
+[n] -> { [i, j, k, l] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/union.c b/test_inputs/codegen/cloog/union.c
new file mode 100644 (file)
index 0000000..6dc0a9b
--- /dev/null
@@ -0,0 +1,6 @@
+if (M >= 11) {
+  for (int c0 = -100; c0 <= 0; c0 += 1)
+    S1(-c0);
+} else
+  for (int c0 = 0; c0 <= 100; c0 += 1)
+    S1(c0);
diff --git a/test_inputs/codegen/cloog/union.in b/test_inputs/codegen/cloog/union.in
new file mode 100644 (file)
index 0000000..23b6cab
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S1[i0] -> [i0] : M <= 10 and i0 >= 0 and i0 <= 100; S1[i0] -> [-i0] : M >= 11 and i0 >= 0 and i0 <= 100 }
+[M] -> {  : M >= 1 or M <= -1 }
+[M] -> { [i] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/unroll.c b/test_inputs/codegen/cloog/unroll.c
new file mode 100644 (file)
index 0000000..83c4577
--- /dev/null
@@ -0,0 +1,13 @@
+{
+  S1(0);
+  S1(1);
+  S1(2);
+  S1(3);
+  S1(4);
+  S1(5);
+  S1(6);
+  S1(7);
+  S1(8);
+  S1(9);
+  S1(10);
+}
diff --git a/test_inputs/codegen/cloog/unroll.in b/test_inputs/codegen/cloog/unroll.in
new file mode 100644 (file)
index 0000000..1e449e0
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { S1[i] -> [i, 0] : i >= 0 and i <= 10 }
+[n] -> {  :  }
+[n] -> { [i, j] -> unroll[o0] }
diff --git a/test_inputs/codegen/cloog/unroll2.c b/test_inputs/codegen/cloog/unroll2.c
new file mode 100644 (file)
index 0000000..0a463c8
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  if (n <= 9 && n >= 0)
+    S1(n);
+  if (n <= 9 && n + 1 >= 0)
+    S1(n + 1);
+}
diff --git a/test_inputs/codegen/cloog/unroll2.in b/test_inputs/codegen/cloog/unroll2.in
new file mode 100644 (file)
index 0000000..eb71e07
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { S1[i] -> [i, 0] : i >= n and i <= 1 + n and n <= 9 and i >= 0 }
+[n] -> {  :  }
+[n] -> { [i, j] -> unroll[o0] }
diff --git a/test_inputs/codegen/cloog/usvd_e_t.c b/test_inputs/codegen/cloog/usvd_e_t.c
new file mode 100644 (file)
index 0000000..feb07ed
--- /dev/null
@@ -0,0 +1,348 @@
+{
+  for (int c0 = 0; c0 <= 2; c0 += 1) {
+    S1(c0, 0, 0);
+    for (int c1 = 0; c1 <= 4; c1 += 1)
+      S2(c0, c1, 0);
+  }
+  S1(3, 0, 0);
+  for (int c1 = 0; c1 <= 4; c1 += 1)
+    S2(3, c1, 0);
+  for (int c1 = 7; c1 <= 11; c1 += 1)
+    S8(3, c1, 0);
+  S1(4, 0, 0);
+  S2(4, 0, 0);
+  S3(4, 0, 0);
+  S5(4, 0, 0);
+  for (int c1 = 1; c1 <= 4; c1 += 1) {
+    S2(4, c1, 0);
+    S5(4, c1, 0);
+  }
+  for (int c1 = 7; c1 <= 11; c1 += 1)
+    S8(4, c1, 0);
+  for (int c0 = 5; c0 <= 6; c0 += 1) {
+    for (int c1 = -4; c1 <= c0 - 9; c1 += 1)
+      S6(c0, c1, 0);
+    for (int c1 = c0 - 9; c1 <= -1; c1 += 1)
+      S7(c0, c1, 0);
+    S3(c0, 0, 0);
+    S7(c0, 0, 0);
+    for (int c1 = 1; c1 <= c0 - 4; c1 += 1)
+      S4(c0, c1, -1);
+    for (int c1 = c0 - 4; c1 <= 4; c1 += 1)
+      S5(c0, c1, 0);
+    for (int c1 = 7; c1 <= 11; c1 += 1)
+      S8(c0, c1, 0);
+  }
+  for (int c1 = -4; c1 <= -2; c1 += 1)
+    S6(7, c1, 0);
+  for (int c1 = -2; c1 <= -1; c1 += 1)
+    S7(7, c1, 0);
+  S3(7, 0, 0);
+  S7(7, 0, 0);
+  for (int c1 = 1; c1 <= 3; c1 += 1)
+    S4(7, c1, -1);
+  for (int c1 = 3; c1 <= 4; c1 += 1)
+    S5(7, c1, 0);
+  S9(7, 4, 0);
+  S10(7, 4, 0);
+  S11(7, 4, 0);
+  S21(7, 4, 0);
+  S23(7, 4, 0);
+  S11(7, 4, 1);
+  S16(7, 4, 1);
+  S17(7, 4, 1);
+  for (int c2 = 2; c2 <= 4; c2 += 1)
+    S11(7, 4, c2);
+  S12(7, 5, 0);
+  S21(7, 5, 0);
+  S22(7, 5, 0);
+  S23(7, 5, 0);
+  S12(7, 5, 1);
+  S16(7, 5, 1);
+  S17(7, 5, 1);
+  for (int c2 = 2; c2 <= 4; c2 += 1)
+    S12(7, 5, c2);
+  S21(7, 6, 0);
+  S22(7, 6, 0);
+  S23(7, 6, 0);
+  for (int c1 = 7; c1 <= 8; c1 += 1) {
+    S8(7, c1, 0);
+    S21(7, c1, 0);
+    S22(7, c1, 0);
+    S23(7, c1, 0);
+  }
+  S8(7, 9, 0);
+  S22(7, 9, 0);
+  for (int c1 = 10; c1 <= 11; c1 += 1)
+    S8(7, c1, 0);
+  for (int c1 = -4; c1 <= -1; c1 += 1)
+    S6(8, c1, 0);
+  S7(8, -1, 0);
+  S3(8, 0, 0);
+  S7(8, 0, 0);
+  S19(8, 1, -2);
+  S4(8, 1, -1);
+  S19(8, 1, -1);
+  S19(8, 1, 0);
+  S15(8, 1, 4);
+  S18(8, 1, 4);
+  for (int c2 = -4; c2 <= -3; c2 += 1) {
+    S14(8, 2, c2);
+    S20(8, 2, c2);
+  }
+  S14(8, 2, -2);
+  S19(8, 2, -2);
+  S20(8, 2, -2);
+  S4(8, 2, -1);
+  S14(8, 2, -1);
+  S19(8, 2, -1);
+  S20(8, 2, -1);
+  S14(8, 2, 0);
+  S19(8, 2, 0);
+  S20(8, 2, 0);
+  S15(8, 2, 4);
+  S18(8, 2, 4);
+  for (int c2 = -4; c2 <= -2; c2 += 1) {
+    S14(8, 3, c2);
+    S20(8, 3, c2);
+  }
+  S4(8, 3, -1);
+  S14(8, 3, -1);
+  S20(8, 3, -1);
+  S14(8, 3, 0);
+  S20(8, 3, 0);
+  S15(8, 3, 4);
+  S18(8, 3, 4);
+  for (int c2 = -4; c2 <= -2; c2 += 1) {
+    S14(8, 4, c2);
+    S20(8, 4, c2);
+  }
+  S4(8, 4, -1);
+  S14(8, 4, -1);
+  S20(8, 4, -1);
+  S5(8, 4, 0);
+  S9(8, 4, 0);
+  S10(8, 4, 0);
+  S14(8, 4, 0);
+  S20(8, 4, 0);
+  S23(8, 4, 0);
+  S13(8, 4, 1);
+  S21(8, 4, 1);
+  S23(8, 4, 1);
+  S24(8, 4, 1);
+  S13(8, 4, 2);
+  S16(8, 4, 2);
+  S17(8, 4, 2);
+  S24(8, 4, 2);
+  S13(8, 4, 3);
+  S24(8, 4, 3);
+  S13(8, 4, 4);
+  S15(8, 4, 4);
+  S23(8, 5, 0);
+  S11(8, 5, 1);
+  S21(8, 5, 1);
+  S22(8, 5, 1);
+  S23(8, 5, 1);
+  S24(8, 5, 1);
+  S11(8, 5, 2);
+  S16(8, 5, 2);
+  S17(8, 5, 2);
+  S24(8, 5, 2);
+  S11(8, 5, 3);
+  S24(8, 5, 3);
+  S11(8, 5, 4);
+  S15(8, 5, 4);
+  S23(8, 6, 0);
+  S12(8, 6, 1);
+  S21(8, 6, 1);
+  S22(8, 6, 1);
+  S23(8, 6, 1);
+  S24(8, 6, 1);
+  S12(8, 6, 2);
+  S16(8, 6, 2);
+  S17(8, 6, 2);
+  S24(8, 6, 2);
+  S12(8, 6, 3);
+  S24(8, 6, 3);
+  S12(8, 6, 4);
+  for (int c1 = 7; c1 <= 8; c1 += 1) {
+    S23(8, c1, 0);
+    S21(8, c1, 1);
+    S22(8, c1, 1);
+    S23(8, c1, 1);
+    for (int c2 = 1; c2 <= 3; c2 += 1)
+      S24(8, c1, c2);
+  }
+  S22(8, 9, 1);
+  S7(9, 0, 0);
+  for (int c1 = 1; c1 <= 2; c1 += 1) {
+    for (int c2 = -1; c2 <= 0; c2 += 1)
+      S19(9, c1, c2);
+    for (int c2 = 4; c2 <= 5; c2 += 1) {
+      S15(9, c1, c2);
+      S18(9, c1, c2);
+    }
+  }
+  S20(9, 3, -4);
+  for (int c2 = -3; c2 <= -2; c2 += 1) {
+    S14(9, 3, c2);
+    S20(9, 3, c2);
+  }
+  for (int c2 = -1; c2 <= 0; c2 += 1) {
+    S14(9, 3, c2);
+    S19(9, 3, c2);
+    S20(9, 3, c2);
+  }
+  for (int c2 = 4; c2 <= 5; c2 += 1) {
+    S15(9, 3, c2);
+    S18(9, 3, c2);
+  }
+  S20(9, 4, -4);
+  for (int c2 = -3; c2 <= -1; c2 += 1) {
+    S14(9, 4, c2);
+    S20(9, 4, c2);
+  }
+  S9(9, 4, 0);
+  S10(9, 4, 0);
+  S14(9, 4, 0);
+  S20(9, 4, 0);
+  for (int c2 = 0; c2 <= 1; c2 += 1)
+    S23(9, 4, c2);
+  S13(9, 4, 2);
+  S21(9, 4, 2);
+  S23(9, 4, 2);
+  S24(9, 4, 2);
+  S13(9, 4, 3);
+  S16(9, 4, 3);
+  S17(9, 4, 3);
+  S24(9, 4, 3);
+  S13(9, 4, 4);
+  for (int c2 = 4; c2 <= 5; c2 += 1) {
+    S15(9, 4, c2);
+    S18(9, 4, c2);
+  }
+  for (int c2 = 0; c2 <= 1; c2 += 1)
+    S23(9, 5, c2);
+  S13(9, 5, 2);
+  S21(9, 5, 2);
+  S22(9, 5, 2);
+  S23(9, 5, 2);
+  S24(9, 5, 2);
+  S13(9, 5, 3);
+  S16(9, 5, 3);
+  S17(9, 5, 3);
+  S24(9, 5, 3);
+  S13(9, 5, 4);
+  for (int c2 = 4; c2 <= 5; c2 += 1)
+    S15(9, 5, c2);
+  for (int c2 = 0; c2 <= 1; c2 += 1)
+    S23(9, 6, c2);
+  S11(9, 6, 2);
+  S21(9, 6, 2);
+  S22(9, 6, 2);
+  S23(9, 6, 2);
+  S24(9, 6, 2);
+  S11(9, 6, 3);
+  S16(9, 6, 3);
+  S17(9, 6, 3);
+  S24(9, 6, 3);
+  S11(9, 6, 4);
+  for (int c2 = 0; c2 <= 1; c2 += 1)
+    S23(9, 7, c2);
+  S12(9, 7, 2);
+  S21(9, 7, 2);
+  S22(9, 7, 2);
+  S23(9, 7, 2);
+  S24(9, 7, 2);
+  S12(9, 7, 3);
+  S16(9, 7, 3);
+  S17(9, 7, 3);
+  S24(9, 7, 3);
+  S12(9, 7, 4);
+  for (int c2 = 0; c2 <= 1; c2 += 1)
+    S23(9, 8, c2);
+  S21(9, 8, 2);
+  S22(9, 8, 2);
+  S23(9, 8, 2);
+  for (int c2 = 2; c2 <= 3; c2 += 1)
+    S24(9, 8, c2);
+  S22(9, 9, 2);
+  for (int c1 = 1; c1 <= 3; c1 += 1) {
+    S19(10, c1, 0);
+    S26(10, c1, 3);
+    S15(10, c1, 4);
+    S18(10, c1, 4);
+    S25(10, c1, 4);
+    for (int c2 = 5; c2 <= 6; c2 += 1) {
+      S15(10, c1, c2);
+      S18(10, c1, c2);
+    }
+  }
+  for (int c2 = -4; c2 <= -3; c2 += 1)
+    S20(10, 4, c2);
+  for (int c2 = -2; c2 <= -1; c2 += 1) {
+    S14(10, 4, c2);
+    S20(10, 4, c2);
+  }
+  S9(10, 4, 0);
+  S10(10, 4, 0);
+  S14(10, 4, 0);
+  S19(10, 4, 0);
+  S20(10, 4, 0);
+  S13(10, 4, 3);
+  S21(10, 4, 3);
+  S24(10, 4, 3);
+  S26(10, 4, 3);
+  S13(10, 4, 4);
+  S15(10, 4, 4);
+  S16(10, 4, 4);
+  S17(10, 4, 4);
+  S18(10, 4, 4);
+  S25(10, 4, 4);
+  for (int c2 = 5; c2 <= 6; c2 += 1) {
+    S15(10, 4, c2);
+    S18(10, 4, c2);
+  }
+  S13(10, 5, 3);
+  S21(10, 5, 3);
+  S22(10, 5, 3);
+  S24(10, 5, 3);
+  S26(10, 5, 3);
+  S13(10, 5, 4);
+  S15(10, 5, 4);
+  S16(10, 5, 4);
+  S17(10, 5, 4);
+  S18(10, 5, 4);
+  S25(10, 5, 4);
+  for (int c2 = 5; c2 <= 6; c2 += 1) {
+    S15(10, 5, c2);
+    S18(10, 5, c2);
+  }
+  S13(10, 6, 3);
+  S21(10, 6, 3);
+  S22(10, 6, 3);
+  S24(10, 6, 3);
+  S13(10, 6, 4);
+  S16(10, 6, 4);
+  S17(10, 6, 4);
+  S11(10, 7, 3);
+  S21(10, 7, 3);
+  S22(10, 7, 3);
+  S24(10, 7, 3);
+  S11(10, 7, 4);
+  S16(10, 7, 4);
+  S17(10, 7, 4);
+  S12(10, 8, 3);
+  S21(10, 8, 3);
+  S22(10, 8, 3);
+  S24(10, 8, 3);
+  S12(10, 8, 4);
+  S16(10, 8, 4);
+  S17(10, 8, 4);
+  S22(10, 9, 3);
+  for (int c0 = 11; c0 <= 14; c0 += 1)
+    for (int c1 = 1; c1 <= 5; c1 += 1) {
+      S26(c0, c1, 3);
+      S25(c0, c1, 4);
+    }
+}
diff --git a/test_inputs/codegen/cloog/usvd_e_t.in b/test_inputs/codegen/cloog/usvd_e_t.in
new file mode 100644 (file)
index 0000000..feb8f08
--- /dev/null
@@ -0,0 +1,3 @@
+{ S19[i0, i1, i2] -> [i0, i1, i2, 18] : i0 >= 8 and i1 >= 1 and i2 <= 0 and i2 >= -10 + i0 and i1 <= -6 + i0; S21[i0, i1, -7 + i0] -> [i0, i1, -7 + i0, 20] : i0 <= 10 and i1 >= 4 and i1 <= 8 and i0 >= 7; S17[i0, i1, -6 + i0] -> [i0, i1, -6 + i0, 16] : i0 >= 7 and i1 >= 4 and i0 <= 10 and i1 <= -2 + i0; S4[i0, i1, -1] -> [i0, i1, -1, 3] : i0 <= 8 and i1 >= 1 and i1 <= -4 + i0; S1[i0, 0, 0] -> [i0, 0, 0, 0] : i0 >= 0 and i0 <= 4; S10[i0, 4, 0] -> [i0, 4, 0, 9] : i0 >= 7 and i0 <= 10; S16[i0, i1, -6 + i0] -> [i0, i1, -6 + i0, 15] : i0 <= 10 and i1 >= 4 and i0 >= 7 and i1 <= -2 + i0; S24[i0, i1, i2] -> [i0, i1, i2, 23] : i0 >= 8 and i1 >= 4 and i1 <= 8 and i2 <= 3 and i2 >= -7 + i0; S23[i0, i1, i2] -> [i0, i1, i2, 22] : i0 <= 9 and i1 >= 4 and i1 <= 8 and i2 >= 0 and i2 <= -7 + i0; S7[i0, i1, 0] -> [i0, i1, 0, 6] : i0 >= 5 and i1 <= 0 and i1 >= -9 + i0; S25[i0, i1, 4] -> [i0, i1, 4, 24] : i0 >= 10 and i0 <= 14 and i1 >= 1 and i1 <= 5; S18[i0, i1, i2] -> [i0, i1, i2, 17] : i0 <= 10 and i1 >= 1 and i2 >= 4 and i2 <= -4 + i0 and i1 <= -5 + i0; S14[i0, i1, i2] -> [i0, i1, i2, 13] : i0 >= 8 and i1 <= 4 and i2 <= 0 and i2 >= -12 + i0 and i1 >= -6 + i0; S6[i0, i1, 0] -> [i0, i1, 0, 5] : i0 <= 8 and i1 >= -4 and i1 <= -9 + i0; S8[i0, i1, 0] -> [i0, i1, 0, 7] : i0 >= 3 and i0 <= 7 and i1 >= 7 and i1 <= 11; S15[i0, i1, i2] -> [i0, i1, i2, 14] : i0 <= 10 and i1 >= 1 and i1 <= 5 and i2 >= 4 and i2 <= -4 + i0; S11[i0, -3 + i0, i2] -> [i0, -3 + i0, i2, 10] : i0 <= 10 and i0 >= 7 and i2 <= 4 and i2 >= -7 + i0; S20[i0, i1, i2] -> [i0, i1, i2, 19] : i0 >= 8 and i1 <= 4 and i2 >= -4 and i2 <= 0 and i1 >= -6 + i0; S12[i0, -2 + i0, i2] -> [i0, -2 + i0, i2, 11] : i0 >= 7 and i0 <= 10 and i2 <= 4 and i2 >= -7 + i0; S9[i0, 4, 0] -> [i0, 4, 0, 8] : i0 >= 7 and i0 <= 10; S22[i0, i1, -7 + i0] -> [i0, i1, -7 + i0, 21] : i0 >= 7 and i1 >= 5 and i1 <= 9 and i0 <= 10; S13[i0, i1, i2] -> [i0, i1, i2, 12] : i0 <= 10 and i1 >= 4 and i2 <= 4 and i2 >= -7 + i0 and i1 <= -4 + i0; S26[i0, i1, 3] -> [i0, i1, 3, 25] : i0 >= 10 and i0 <= 14 and i1 >= 1 and i1 <= 5; S3[i0, 0, 0] -> [i0, 0, 0, 2] : i0 >= 4 and i0 <= 8; S5[i0, i1, 0] -> [i0, i1, 0, 4] : i0 >= 4 and i1 <= 4 and i1 >= -4 + i0; S2[i0, i1, 0] -> [i0, i1, 0, 1] : i0 >= 0 and i0 <= 4 and i1 >= 0 and i1 <= 4 }
+{  :  }
+{ [i, j, k, l] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/vasilache.c b/test_inputs/codegen/cloog/vasilache.c
new file mode 100644 (file)
index 0000000..974dc04
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  S1();
+  S2();
+  for (int c1 = 0; c1 <= N - 1; c1 += 1)
+    for (int c3 = 0; c3 <= N - 1; c3 += 1) {
+      S4(c1, c3);
+      S5(c1, c3);
+    }
+  for (int c1 = 0; c1 <= N - 1; c1 += 1)
+    for (int c3 = 0; c3 <= N - 1; c3 += 1)
+      for (int c5 = 0; c5 <= (N - 1) / 32; c5 += 1) {
+        S7(c1, c3, c5, 32 * c5);
+        for (int c7 = 32 * c5 + 1; c7 <= min(N - 1, 32 * c5 + 31); c7 += 1) {
+          S6(c1, c3, c5, c7 - 1);
+          S7(c1, c3, c5, c7);
+        }
+        if (N >= 32 * c5 + 33) {
+          S6(c1, c3, c5, 32 * c5 + 31);
+        } else
+          S6(c1, c3, c5, N - 1);
+      }
+  S8();
+}
diff --git a/test_inputs/codegen/cloog/vasilache.in b/test_inputs/codegen/cloog/vasilache.in
new file mode 100644 (file)
index 0000000..a9b9860
--- /dev/null
@@ -0,0 +1,3 @@
+[M, N] -> { S4[i0, i1] -> [3, i0, 0, i1, 0, 0, 0, 0, 0] : i0 >= 0 and i0 <= -1 + N and i1 >= 0 and i1 <= -1 + N; S1[] -> [0, 0, 0, 0, 0, 0, 0, 0, 0]; S6[i0, i1, i2, i3] -> [4, i0, 0, i1, 0, i2, 0, 1 + i3, 0] : i0 >= 0 and i0 <= -1 + N and i1 >= 0 and i1 <= -1 + N and i3 >= 0 and i3 <= -1 + N and i3 >= 32i2 and i3 <= 31 + 32i2; S7[i0, i1, i2, i3] -> [4, i0, 0, i1, 0, i2, 0, i3, 1] : i0 >= 0 and i0 <= -1 + N and i1 >= 0 and i1 <= -1 + N and i3 >= 0 and i3 <= -1 + N and i3 >= 32i2 and i3 <= 31 + 32i2; S5[i0, i1] -> [3, i0, 0, i1, 1, 0, 0, 0, 0] : i0 >= 0 and i0 <= -1 + N and i1 >= 0 and i1 <= -1 + N; S2[] -> [1, 0, 0, 0, 0, 0, 0, 0, 0]; S8[] -> [5, 0, 0, 0, 0, 0, 0, 0, 0]; S3[] -> [2, 0, 0, 0, 0, 0, 0, 0, 0] : M >= 79 }
+[M, N] -> {  : M <= 3 and N >= 100 }
+[M, N] -> { [i, j, k, l, m, n, o, p, q] -> separate[x] : x >= 7 }
diff --git a/test_inputs/codegen/cloog/vivien.c b/test_inputs/codegen/cloog/vivien.c
new file mode 100644 (file)
index 0000000..025d870
--- /dev/null
@@ -0,0 +1,82 @@
+{
+  for (int c0 = -27 * n + 2; c0 <= 1; c0 += 1)
+    S1(c0 - 1);
+  for (int c0 = 2; c0 <= min(2 * n, n + 29); c0 += 1) {
+    if (2 * n >= c0 + 1 && c0 >= 3)
+      S4(c0 - c0 / 2 - 1, c0 / 2 + 1);
+    if (2 * n >= c0 + 1 && c0 + 2 >= 2 * n) {
+      for (int c2 = 1; c2 <= -n + c0 - 1; c2 += 1)
+        S5(-n + c0, n, c2);
+    } else if (2 * n >= c0 + 3 && c0 >= 5) {
+      S4(c0 - c0 / 2 - 2, c0 / 2 + 2);
+      for (int c2 = 1; c2 <= (c0 + 1) / 2 - 2; c2 += 1)
+        S5(c0 - c0 / 2 - 1, c0 / 2 + 1, c2);
+    }
+    for (int c1 = -((c0 + 1) / 2) + 3; c1 <= min(n - c0, -1); c1 += 1) {
+      S6(-c1 + 2, c0 + c1 - 2);
+      S4(-c1, c0 + c1);
+      for (int c2 = 1; c2 <= -c1; c2 += 1)
+        S5(-c1 + 1, c0 + c1 - 1, c2);
+    }
+    if (c0 >= n + 2 && 2 * n >= c0 + 3) {
+      S6(-n + c0 + 1, n - 1);
+      for (int c2 = 1; c2 <= -n + c0 - 1; c2 += 1)
+        S5(-n + c0, n, c2);
+    }
+    if (2 * n >= c0 + 1 && c0 >= n + 3)
+      S6(-n + c0, n);
+    if (c0 >= n + 3) {
+      S1(c0 - 1);
+    } else if (c0 == n + 2 && n >= 3) {
+      S6(2, n);
+      S1(n + 1);
+    } else {
+      if (c0 >= 5 && n + 1 >= c0) {
+        S6(2, c0 - 2);
+        S1(c0 - 1);
+      } else if (n + 1 >= c0 && c0 >= 3)
+        S1(c0 - 1);
+      if (c0 >= 3 && n + 1 >= c0)
+        S6(1, c0 - 1);
+    }
+    if (c0 == 2) {
+      S1(1);
+    } else if (c0 == 4 && n == 2)
+      S1(3);
+    if (c0 % 2 == 0)
+      S3(c0 / 2);
+    for (int c1 = max(-n + c0, 1); c1 <= (c0 + 1) / 2 - 1; c1 += 1)
+      S2(c0 - c1, c1);
+  }
+  for (int c0 = max(-27 * n + 2, 2 * n + 1); c0 <= n + 29; c0 += 1)
+    S1(c0 - 1);
+  for (int c0 = n + 30; c0 <= 2 * n; c0 += 1) {
+    if (2 * n >= c0 + 1) {
+      S4(c0 - c0 / 2 - 1, c0 / 2 + 1);
+      if (c0 + 2 >= 2 * n) {
+        for (int c2 = 1; c2 <= -n + c0 - 1; c2 += 1)
+          S5(-n + c0, n, c2);
+      } else {
+        S4(c0 - c0 / 2 - 2, c0 / 2 + 2);
+        for (int c2 = 1; c2 <= (c0 + 1) / 2 - 2; c2 += 1)
+          S5(c0 - c0 / 2 - 1, c0 / 2 + 1, c2);
+      }
+      for (int c1 = -((c0 + 1) / 2) + 3; c1 <= n - c0; c1 += 1) {
+        S6(-c1 + 2, c0 + c1 - 2);
+        S4(-c1, c0 + c1);
+        for (int c2 = 1; c2 <= -c1; c2 += 1)
+          S5(-c1 + 1, c0 + c1 - 1, c2);
+      }
+      if (2 * n >= c0 + 3) {
+        S6(-n + c0 + 1, n - 1);
+        for (int c2 = 1; c2 <= -n + c0 - 1; c2 += 1)
+          S5(-n + c0, n, c2);
+      }
+      S6(-n + c0, n);
+    }
+    if (c0 % 2 == 0)
+      S3(c0 / 2);
+    for (int c1 = -n + c0; c1 <= (c0 + 1) / 2 - 1; c1 += 1)
+      S2(c0 - c1, c1);
+  }
+}
diff --git a/test_inputs/codegen/cloog/vivien.in b/test_inputs/codegen/cloog/vivien.in
new file mode 100644 (file)
index 0000000..b591ef3
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { S6[i0, i1] -> [2i0 + 2i1, 2 - i0, 0] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n; S2[i0, i1] -> [1 + 2i0 + 2i1, i1, 0] : 29i1 >= 1 - i0 and i0 <= n and i1 >= 1 and i1 <= -1 + i0; S1[i0] -> [2 + 2i0, 0, 0] : i0 >= 1 - 27n and i0 <= 28 + n; S4[i0, i1] -> [2i0 + 2i1, -i0, 0] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n; S3[i0] -> [1 + 4i0, 0, 0] : i0 >= 1 and i0 <= n; S5[i0, i1, i2] -> [2i0 + 2i1, 1 - i0, i2] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n and i2 >= 1 and i2 <= -1 + i0 }
+[n] -> {  :  }
+[n] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/vivien2.c b/test_inputs/codegen/cloog/vivien2.c
new file mode 100644 (file)
index 0000000..a36ef35
--- /dev/null
@@ -0,0 +1,78 @@
+{
+  for (int c0 = -27 * n + 2; c0 <= 1; c0 += 1)
+    S1(c0 - 1);
+  for (int c0 = 2; c0 <= n + 29; c0 += 1) {
+    if (c0 >= 3) {
+      S4(c0 - c0 / 2 - 1, c0 / 2 + 1);
+      if (c0 + 2 >= 2 * n) {
+        for (int c2 = 1; c2 <= -n + c0 - 1; c2 += 1)
+          S5(-n + c0, n, c2);
+      } else if (c0 >= 5) {
+        S4(c0 - c0 / 2 - 2, c0 / 2 + 2);
+        for (int c2 = 1; c2 <= (c0 + 1) / 2 - 2; c2 += 1)
+          S5(c0 - c0 / 2 - 1, c0 / 2 + 1, c2);
+      }
+    }
+    for (int c1 = -((c0 + 1) / 2) + 3; c1 <= min(n - c0, -1); c1 += 1) {
+      S6(-c1 + 2, c0 + c1 - 2);
+      S4(-c1, c0 + c1);
+      for (int c2 = 1; c2 <= -c1; c2 += 1)
+        S5(-c1 + 1, c0 + c1 - 1, c2);
+    }
+    if (2 * n >= c0 + 3 && c0 >= n + 2) {
+      S6(-n + c0 + 1, n - 1);
+      for (int c2 = 1; c2 <= -n + c0 - 1; c2 += 1)
+        S5(-n + c0, n, c2);
+    }
+    if (c0 >= n + 3) {
+      S6(-n + c0, n);
+      S1(c0 - 1);
+    } else if (c0 == n + 2) {
+      S6(2, n);
+      S1(n + 1);
+    } else {
+      if (c0 >= 5) {
+        S6(2, c0 - 2);
+        S1(c0 - 1);
+      } else if (c0 >= 3)
+        S1(c0 - 1);
+      if (c0 >= 3)
+        S6(1, c0 - 1);
+    }
+    if (c0 == 2)
+      S1(1);
+    if (c0 % 2 == 0)
+      S3(c0 / 2);
+    for (int c1 = max(-n + c0, 1); c1 <= (c0 + 1) / 2 - 1; c1 += 1)
+      S2(c0 - c1, c1);
+  }
+  for (int c0 = n + 30; c0 <= 2 * n; c0 += 1) {
+    if (2 * n >= c0 + 1) {
+      S4(c0 - c0 / 2 - 1, c0 / 2 + 1);
+      if (c0 + 2 >= 2 * n) {
+        for (int c2 = 1; c2 <= -n + c0 - 1; c2 += 1)
+          S5(-n + c0, n, c2);
+      } else {
+        S4(c0 - c0 / 2 - 2, c0 / 2 + 2);
+        for (int c2 = 1; c2 <= (c0 + 1) / 2 - 2; c2 += 1)
+          S5(c0 - c0 / 2 - 1, c0 / 2 + 1, c2);
+      }
+      for (int c1 = -((c0 + 1) / 2) + 3; c1 <= n - c0; c1 += 1) {
+        S6(-c1 + 2, c0 + c1 - 2);
+        S4(-c1, c0 + c1);
+        for (int c2 = 1; c2 <= -c1; c2 += 1)
+          S5(-c1 + 1, c0 + c1 - 1, c2);
+      }
+      if (2 * n >= c0 + 3) {
+        S6(-n + c0 + 1, n - 1);
+        for (int c2 = 1; c2 <= -n + c0 - 1; c2 += 1)
+          S5(-n + c0, n, c2);
+      }
+      S6(-n + c0, n);
+    }
+    if (c0 % 2 == 0)
+      S3(c0 / 2);
+    for (int c1 = -n + c0; c1 <= (c0 + 1) / 2 - 1; c1 += 1)
+      S2(c0 - c1, c1);
+  }
+}
diff --git a/test_inputs/codegen/cloog/vivien2.in b/test_inputs/codegen/cloog/vivien2.in
new file mode 100644 (file)
index 0000000..d8b1b1a
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { S6[i0, i1] -> [2i0 + 2i1, 2 - i0, 0] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n; S2[i0, i1] -> [1 + 2i0 + 2i1, i1, 0] : 29i1 >= 1 - i0 and i0 <= n and i1 >= 1 and i1 <= -1 + i0; S1[i0] -> [2 + 2i0, 0, 0] : i0 >= 1 - 27n and i0 <= 28 + n; S4[i0, i1] -> [2i0 + 2i1, -i0, 0] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n; S3[i0] -> [1 + 4i0, 0, 0] : i0 >= 1 and i0 <= n; S5[i0, i1, i2] -> [2i0 + 2i1, 1 - i0, i2] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n and i2 >= 1 and i2 <= -1 + i0 }
+[n] -> {  : n >= 30 }
+[n] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/walters.c b/test_inputs/codegen/cloog/walters.c
new file mode 100644 (file)
index 0000000..2c1bd93
--- /dev/null
@@ -0,0 +1,15 @@
+{
+  S2(1, 0, 1, 0);
+  S4(1, 0, 1, 0);
+  S3(2, 0, 1, 1);
+  S4(2, 0, 1, 1);
+  for (int c0 = 3; c0 <= 10; c0 += 1) {
+    if (c0 % 3 == 0) {
+      S1(c0, c0 / 3, c0 / 3, c0 / 3);
+    } else if ((c0 - 1) % 3 == 0) {
+      S2(c0, (c0 - 1) / 3, (c0 + 2) / 3, (c0 - 1) / 3);
+    } else
+      S3(c0, (c0 - 2) / 3, (c0 + 1) / 3, (c0 + 1) / 3);
+    S4(c0, c0 / 3, (c0 - 1) / 3 + 1, c0 - (c0 - 1) / 3 - c0 / 3 - 1);
+  }
+}
diff --git a/test_inputs/codegen/cloog/walters.in b/test_inputs/codegen/cloog/walters.in
new file mode 100644 (file)
index 0000000..6e26451
--- /dev/null
@@ -0,0 +1,3 @@
+{ S2[i, div36, div37, div38] -> [i, div36, k, div38, 1] : 3div37 = 2 + i and 3k = 2 + i and i >= 1 and i <= 10 and 3div36 >= -2 + i and 3div38 <= 1 + i and 3div38 >= -1 + i and 3div36 <= i; S1[i, div36, div37, div38] -> [i, j, div37, div38, 0] : 3j = i and 3div36 = i and i >= 3 and i <= 10 and 3div37 >= i and 3div38 <= 1 + i and 3div37 <= 2 + i and 3div38 >= -1 + i; S3[i, div36, div37, div38] -> [i, div36, div37, l, 2] : 3l = 1 + i and 3div38 = 1 + i and i <= 10 and i >= 2 and 3div36 >= -2 + i and 3div37 <= 2 + i and 3div36 <= i and 3div37 >= i; S4[i, div36, div37, div38] -> [i, div36, div37, div38, 3] : i >= 1 and i <= 10 and 3div36 <= i and 3div36 >= -2 + i and 3div37 <= 2 + i and 3div37 >= i and 3div38 <= 1 + i and 3div38 >= -1 + i }
+{  :  }
+{ [i, j, k, l, m] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/walters2.c b/test_inputs/codegen/cloog/walters2.c
new file mode 100644 (file)
index 0000000..27565fb
--- /dev/null
@@ -0,0 +1,12 @@
+{
+  for (int c1 = 0; c1 <= 51; c1 += 1)
+    S2(0, c1);
+  for (int c0 = 1; c0 <= 24; c0 += 1) {
+    S2(c0, 0);
+    for (int c1 = 1; c1 <= 50; c1 += 1)
+      S1(c0, c1);
+    S2(c0, 51);
+  }
+  for (int c1 = 0; c1 <= 51; c1 += 1)
+    S2(25, c1);
+}
diff --git a/test_inputs/codegen/cloog/walters2.in b/test_inputs/codegen/cloog/walters2.in
new file mode 100644 (file)
index 0000000..ea01a10
--- /dev/null
@@ -0,0 +1,3 @@
+{ S1[j, i] -> [j, i, 0] : j >= 1 and j <= 24 and i >= 1 and i <= 50; S2[j, 51] -> [j, 51, 1] : j >= 1 and j <= 24; S2[25, i] -> [25, i, 1] : i >= 1 and i <= 51; S2[0, i] -> [0, i, 1] : i >= 0 and i <= 51; S2[j, 0] -> [j, 0, 1] : j >= 1 and j <= 25 }
+{  :  }
+{ [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/walters3.c b/test_inputs/codegen/cloog/walters3.c
new file mode 100644 (file)
index 0000000..bafb9ac
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  for (int c0 = 2; c0 <= 8; c0 += 2) {
+    S1(c0, c0 / 2, c0 / 2);
+    S2(c0, c0 / 2, c0 / 2);
+  }
+  S2(10, 5, 5);
+}
diff --git a/test_inputs/codegen/cloog/walters3.in b/test_inputs/codegen/cloog/walters3.in
new file mode 100644 (file)
index 0000000..802bd4f
--- /dev/null
@@ -0,0 +1,3 @@
+{ S2[j, a, b] -> [j, j', b, 1] : 2a = j and 2j' = j and j >= 1 and j <= 10 and 2b <= j and 2b >= -1 + j; S1[j, a, b] -> [j, j', k, 0] : 2a = j and 2j' = j and 2k = j and 2b = j and j <= 8 and j >= 2 }
+{  :  }
+{ [i, j, k, l] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/wavefront.c b/test_inputs/codegen/cloog/wavefront.c
new file mode 100644 (file)
index 0000000..7db0788
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 2; c0 <= n + m; c0 += 1)
+  for (int c1 = max(1, -m + c0); c1 <= min(n, c0 - 1); c1 += 1)
+    S1(c1, c0 - c1);
diff --git a/test_inputs/codegen/cloog/wavefront.in b/test_inputs/codegen/cloog/wavefront.in
new file mode 100644 (file)
index 0000000..61618c3
--- /dev/null
@@ -0,0 +1,3 @@
+[n, m] -> { S1[i0, i1] -> [i0 + i1, i0] : i0 >= 1 and i0 <= n and i1 >= 1 and i1 <= m }
+[n, m] -> {  :  }
+[n, m] -> { [i, j] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/yosr.c b/test_inputs/codegen/cloog/yosr.c
new file mode 100644 (file)
index 0000000..0f465ae
--- /dev/null
@@ -0,0 +1,12 @@
+{
+  for (int c0 = 1; c0 <= n - 1; c0 += 1) {
+    for (int c2 = c0 + 1; c2 <= n; c2 += 1)
+      S1(c0, c2);
+    for (int c1 = 1; c1 <= c0 - 1; c1 += 1)
+      for (int c2 = c1 + 1; c2 <= n; c2 += 1)
+        S2(c1, c2, c0);
+  }
+  for (int c1 = 1; c1 <= n - 1; c1 += 1)
+    for (int c2 = c1 + 1; c2 <= n; c2 += 1)
+      S2(c1, c2, n);
+}
diff --git a/test_inputs/codegen/cloog/yosr.in b/test_inputs/codegen/cloog/yosr.in
new file mode 100644 (file)
index 0000000..dcc93e5
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { S2[i0, i1, i2] -> [i2] : i0 >= 1 and i0 <= -1 + n and i1 >= 1 + i0 and i1 <= n and i2 >= 1 + i0 and i2 <= n; S1[i0, i1] -> [i0] : i0 >= 1 and i0 <= -1 + n and i1 >= 1 + i0 and i1 <= n }
+[n] -> {  :  }
+[n] -> { [i] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/yosr2.c b/test_inputs/codegen/cloog/yosr2.c
new file mode 100644 (file)
index 0000000..91d8f3e
--- /dev/null
@@ -0,0 +1,13 @@
+{
+  for (int c1 = 1; c1 <= M; c1 += 1)
+    S2(c1);
+  for (int c0 = 2; c0 <= M; c0 += 1) {
+    for (int c2 = 1; c2 <= c0 - 1; c2 += 1)
+      S1(c0, c2);
+    for (int c2 = c0 + 1; c2 <= M; c2 += 1)
+      for (int c3 = 1; c3 <= c0 - 1; c3 += 1)
+        S3(c0, c2, c3);
+    for (int c1 = 1; c1 <= c0 - 1; c1 += 1)
+      S4(c1, c0);
+  }
+}
diff --git a/test_inputs/codegen/cloog/yosr2.in b/test_inputs/codegen/cloog/yosr2.in
new file mode 100644 (file)
index 0000000..a07e149
--- /dev/null
@@ -0,0 +1,3 @@
+[M] -> { S3[i0, i1, i2] -> [i0] : i0 >= 1 and i0 <= M and i1 >= 1 + i0 and i1 <= M and i2 >= 1 and i2 <= -1 + i0; S4[i0, i1] -> [i1] : i0 >= 1 and i0 <= M and i1 >= 1 + i0 and i1 <= M; S1[i0, i1] -> [i0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= -1 + i0; S2[i0] -> [0] : i0 >= 1 and i0 <= M }
+[M] -> {  : M >= 2 }
+[M] -> { [i] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/youcef.c b/test_inputs/codegen/cloog/youcef.c
new file mode 100644 (file)
index 0000000..1bc7ffd
--- /dev/null
@@ -0,0 +1,6 @@
+for (int c0 = 0; c0 <= 5; c0 += 1) {
+  S1(c0, c0);
+  for (int c1 = c0; c1 <= 5; c1 += 1)
+    S2(c0, c1);
+  S3(c0, 5);
+}
diff --git a/test_inputs/codegen/cloog/youcef.in b/test_inputs/codegen/cloog/youcef.in
new file mode 100644 (file)
index 0000000..5164abe
--- /dev/null
@@ -0,0 +1,3 @@
+{ S1[i0, i0] -> [i0, i0, 0] : i0 >= 0 and i0 <= 5; S2[i0, i1] -> [i0, i1, 1] : i0 >= 0 and i0 <= 5 and i1 >= i0 and i1 <= 5; S3[i0, 5] -> [i0, 5, 2] : i0 >= 0 and i0 <= 5 }
+{  :  }
+{ [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/cloog/youcefn.c b/test_inputs/codegen/cloog/youcefn.c
new file mode 100644 (file)
index 0000000..1107790
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  for (int c0 = 1; c0 <= n; c0 += 1) {
+    S1(c0, c0);
+    for (int c1 = c0; c1 <= n; c1 += 1)
+      S2(c0, c1);
+    S3(c0, n);
+  }
+  for (int c0 = n + 1; c0 <= m; c0 += 1)
+    S3(c0, n);
+}
diff --git a/test_inputs/codegen/cloog/youcefn.in b/test_inputs/codegen/cloog/youcefn.in
new file mode 100644 (file)
index 0000000..b21e30d
--- /dev/null
@@ -0,0 +1,3 @@
+[n, m] -> { S3[i0, n] -> [i0, n, 2] : i0 >= 1 and i0 <= m; S2[i0, i1] -> [i0, i1, 1] : i0 >= 1 and i0 <= n and i1 >= i0 and i1 <= n; S1[i0, i0] -> [i0, i0, 0] : i0 >= 1 and i0 <= n }
+[n, m] -> {  : n >= 2 and m >= n }
+[n, m] -> { [i, j, k] -> separate[o0] }
diff --git a/test_inputs/codegen/disjuncts.c b/test_inputs/codegen/disjuncts.c
new file mode 100644 (file)
index 0000000..207e337
--- /dev/null
@@ -0,0 +1,10 @@
+for (int c0 = 0; c0 <= n; c0 += 1)
+  for (int c1 = 0; c1 <= n; c1 += 1)
+    if (c1 == n || c0 == n || c1 == 0 || c0 == 0) {
+      for (int c3 = 0; c3 <= n; c3 += 1)
+        for (int c4 = 0; c4 <= n; c4 += 1)
+          a(c0, c1, c3, c4);
+      for (int c3 = 0; c3 <= n; c3 += 1)
+        for (int c4 = 0; c4 <= n; c4 += 1)
+          b(c0, c1, c3, c4);
+    }
diff --git a/test_inputs/codegen/disjuncts.in b/test_inputs/codegen/disjuncts.in
new file mode 100644 (file)
index 0000000..0138670
--- /dev/null
@@ -0,0 +1,7 @@
+# Check that conditions are hoisted up from the innermost loop
+[n] -> { a[i,j,k,l] -> [i,j,0,k,l] :
+           0 <= i,j,k,l <= n and (i = 0 or j = 0 or i = n or j = n);
+        b[i,j,k,l] -> [i,j,1,k,l] :
+           0 <= i,j,k,l <= n and (i = 0 or j = 0 or i = n or j = n) }
+{ : }
+{ [i,j,t,k,l] -> atomic[x] }
diff --git a/test_inputs/codegen/hoist.c b/test_inputs/codegen/hoist.c
new file mode 100644 (file)
index 0000000..ba8e414
--- /dev/null
@@ -0,0 +1,45 @@
+if (ni >= t0 + 1 && nj >= t1 + 1)
+  for (int c2 = 0; c2 <= min(nk - 1, 15); c2 += 1) {
+    S_1(t0, t1, c2);
+    if (nj >= t1 + 17) {
+      S_1(t0, t1 + 16, c2);
+      if (nj >= t1 + 33) {
+        S_1(t0, t1 + 32, c2);
+        if (nj >= t1 + 49)
+          S_1(t0, t1 + 48, c2);
+      }
+    }
+    if (ni >= t0 + 17) {
+      S_1(t0 + 16, t1, c2);
+      if (nj >= t1 + 17) {
+        S_1(t0 + 16, t1 + 16, c2);
+        if (nj >= t1 + 33) {
+          S_1(t0 + 16, t1 + 32, c2);
+          if (nj >= t1 + 49)
+            S_1(t0 + 16, t1 + 48, c2);
+        }
+      }
+      if (ni >= t0 + 33) {
+        S_1(t0 + 32, t1, c2);
+        if (nj >= t1 + 17) {
+          S_1(t0 + 32, t1 + 16, c2);
+          if (nj >= t1 + 33) {
+            S_1(t0 + 32, t1 + 32, c2);
+            if (nj >= t1 + 49)
+              S_1(t0 + 32, t1 + 48, c2);
+          }
+        }
+        if (ni >= t0 + 49) {
+          S_1(t0 + 48, t1, c2);
+          if (nj >= t1 + 17) {
+            S_1(t0 + 48, t1 + 16, c2);
+            if (nj >= t1 + 33) {
+              S_1(t0 + 48, t1 + 32, c2);
+              if (nj >= t1 + 49)
+                S_1(t0 + 48, t1 + 48, c2);
+            }
+          }
+        }
+      }
+    }
+  }
diff --git a/test_inputs/codegen/hoist.in b/test_inputs/codegen/hoist.in
new file mode 100644 (file)
index 0000000..80a9052
--- /dev/null
@@ -0,0 +1,10 @@
+# check that the shared conditions ni >= t0 + 1 and nj >= t1 + 1
+# are hoisted out of the loop
+[ni, nj, nk, t0, t1] -> { S_1[i, j, k] -> [t0, t1, k, i, j] :
+       exists (e0 = [(-t0 + i)/16], e1 = [(-t1 + j)/16]:
+       16e0 = -t0 + i and 16e1 = -t1 + j and k >= 0 and j >= 0 and
+       j <= -1 + nj and i >= 0 and i <= -1 + ni and k <= -1 + nk and
+       ni >= 1 and nj >= 1 and nk >= 1 and j <= 63 and t1 >= 0 and
+       i <= 63 and k <= 15 and t0 >= 0 and t1 <= 15 and t0 <= 15) }
+[t0, t1] -> { : 0 <= t0, t1 <= 15 }
+{ [t0, t1, i5, i6, i7] -> unroll[x] : x >= 3}
diff --git a/test_inputs/codegen/omega/README b/test_inputs/codegen/omega/README
new file mode 100644 (file)
index 0000000..80e27fd
--- /dev/null
@@ -0,0 +1,5 @@
+The tests in this directory have been adapted from the corresponding omega+
+test cases.
+The options have been derived semi-automatically and may not always
+correspond to the intended meaning of the specified "effort" in the omega+
+test cases.
diff --git a/test_inputs/codegen/omega/basics-0.c b/test_inputs/codegen/omega/basics-0.c
new file mode 100644 (file)
index 0000000..53995e9
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  for (int c0 = 5; c0 <= 8; c0 += 1)
+    s0(c0);
+  for (int c0 = 10; c0 <= 16; c0 += 2)
+    s0(c0);
+  for (int c0 = 20; c0 <= 25; c0 += 1)
+    s0(c0);
+}
diff --git a/test_inputs/codegen/omega/basics-0.in b/test_inputs/codegen/omega/basics-0.in
new file mode 100644 (file)
index 0000000..025da3d
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1] -> [In_1] : (In_1 >= 5 and In_1 <= 8) or (exists (e0 = [(In_1)/2]: 2e0 = In_1 and In_1 >= 10 and In_1 <= 16)) or (In_1 >= 20 and In_1 <= 25) }
+{  :  }
+{ [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/test_inputs/codegen/omega/basics-1.c b/test_inputs/codegen/omega/basics-1.c
new file mode 100644 (file)
index 0000000..21a6f8e
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = -9; c0 <= 9; c0 += 1)
+  for (int c1 = max(-c0 + 1, 1); c1 <= min(-c0 + 10, 10); c1 += 1)
+    s0(c0, c1);
diff --git a/test_inputs/codegen/omega/basics-1.in b/test_inputs/codegen/omega/basics-1.in
new file mode 100644 (file)
index 0000000..82e1093
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, In_2] : In_2 >= 1 - In_1 and In_2 >= 1 and In_2 <= 10 - In_1 and In_2 <= 10 }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/chosol-0.c b/test_inputs/codegen/omega/chosol-0.c
new file mode 100644 (file)
index 0000000..f2f244e
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  for (int c1 = 2; c1 <= n; c1 += 1)
+    s0(c1);
+  for (int c1 = 1; c1 <= n - 1; c1 += 1) {
+    for (int c3 = c1 + 1; c3 <= n; c3 += 1)
+      s1(c3, c1);
+    s2(c1 + 1);
+  }
+}
diff --git a/test_inputs/codegen/omega/chosol-0.in b/test_inputs/codegen/omega/chosol-0.in
new file mode 100644 (file)
index 0000000..81fde50
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[i] -> [0, i, 0, 0] : i >= 2 and i <= n; s1[i, j] -> [1, j, 0, i] : j >= 1 and j <= -1 + i and i <= n; s2[i] -> [1, -1 + i, 1, 0] : i >= 2 and i <= n }
+{  :  }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2; [i0, i1, i2, i3] -> separate[o0] : o0 >= 3 }
diff --git a/test_inputs/codegen/omega/chosol-1.c b/test_inputs/codegen/omega/chosol-1.c
new file mode 100644 (file)
index 0000000..f2f244e
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  for (int c1 = 2; c1 <= n; c1 += 1)
+    s0(c1);
+  for (int c1 = 1; c1 <= n - 1; c1 += 1) {
+    for (int c3 = c1 + 1; c3 <= n; c3 += 1)
+      s1(c3, c1);
+    s2(c1 + 1);
+  }
+}
diff --git a/test_inputs/codegen/omega/chosol-1.in b/test_inputs/codegen/omega/chosol-1.in
new file mode 100644 (file)
index 0000000..b5abf29
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[i] -> [0, i, 0, 0] : i >= 2 and i <= n; s1[i, j] -> [1, j, 0, i] : j >= 1 and j <= -1 + i and i <= n; s2[i] -> [1, -1 + i, 1, 0] : i >= 2 and i <= n }
+{  :  }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 1; [i0, i1, i2, i3] -> separate[o0] : o0 >= 2 }
diff --git a/test_inputs/codegen/omega/code_gen-0.c b/test_inputs/codegen/omega/code_gen-0.c
new file mode 100644 (file)
index 0000000..6340134
--- /dev/null
@@ -0,0 +1,7 @@
+for (int c0 = 1; c0 <= 8; c0 += 1)
+  for (int c1 = 0; c1 <= 7; c1 += 1) {
+    if (c0 >= 2 && c0 <= 6 && c1 <= 4)
+      s1(c0, c1);
+    if (c1 + 1 >= c0)
+      s0(c0, c1);
+  }
diff --git a/test_inputs/codegen/omega/code_gen-0.in b/test_inputs/codegen/omega/code_gen-0.in
new file mode 100644 (file)
index 0000000..a3fa3b1
--- /dev/null
@@ -0,0 +1,3 @@
+{ s1[In_1, In_2] -> [In_1, In_2] : In_1 >= 2 and In_1 <= 6 and In_2 >= 0 and In_2 <= 4; s0[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_2 >= -1 + In_1 and In_2 <= 7 }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= 1; [i0, i1] -> separate[o0] : o0 >= 2 }
diff --git a/test_inputs/codegen/omega/code_gen-1.c b/test_inputs/codegen/omega/code_gen-1.c
new file mode 100644 (file)
index 0000000..80131bb
--- /dev/null
@@ -0,0 +1,16 @@
+for (int c0 = 1; c0 <= 8; c0 += 1) {
+  if (c0 <= 6)
+    for (int c1 = 0; c1 <= c0 - 2; c1 += 1)
+      s1(c0, c1);
+  if (c0 >= 2) {
+    for (int c1 = c0 - 1; c1 <= 4; c1 += 1) {
+      s1(c0, c1);
+      s0(c0, c1);
+    }
+    for (int c1 = max(c0 - 1, 5); c1 <= 7; c1 += 1)
+      s0(c0, c1);
+  }
+  if (c0 == 1)
+    for (int c1 = 0; c1 <= 7; c1 += 1)
+      s0(1, c1);
+}
diff --git a/test_inputs/codegen/omega/code_gen-1.in b/test_inputs/codegen/omega/code_gen-1.in
new file mode 100644 (file)
index 0000000..c6f7fa5
--- /dev/null
@@ -0,0 +1,3 @@
+{ s1[In_1, In_2] -> [In_1, In_2] : In_1 >= 2 and In_1 <= 6 and In_2 >= 0 and In_2 <= 4; s0[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_2 >= -1 + In_1 and In_2 <= 7 }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/code_gen-2.c b/test_inputs/codegen/omega/code_gen-2.c
new file mode 100644 (file)
index 0000000..e96c7c6
--- /dev/null
@@ -0,0 +1,17 @@
+{
+  for (int c1 = 0; c1 <= 7; c1 += 1)
+    s0(1, c1);
+  for (int c0 = 2; c0 <= 6; c0 += 1) {
+    for (int c1 = 0; c1 <= c0 - 2; c1 += 1)
+      s1(c0, c1);
+    for (int c1 = c0 - 1; c1 <= 4; c1 += 1) {
+      s1(c0, c1);
+      s0(c0, c1);
+    }
+    for (int c1 = 5; c1 <= 7; c1 += 1)
+      s0(c0, c1);
+  }
+  for (int c0 = 7; c0 <= 8; c0 += 1)
+    for (int c1 = c0 - 1; c1 <= 7; c1 += 1)
+      s0(c0, c1);
+}
diff --git a/test_inputs/codegen/omega/code_gen-2.in b/test_inputs/codegen/omega/code_gen-2.in
new file mode 100644 (file)
index 0000000..03a7b5d
--- /dev/null
@@ -0,0 +1,3 @@
+{ s1[In_1, In_2] -> [In_1, In_2] : In_1 >= 2 and In_1 <= 6 and In_2 >= 0 and In_2 <= 4; s0[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_2 >= -1 + In_1 and In_2 <= 7 }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= -1; [i0, i1] -> separate[o0] : o0 >= 0 }
diff --git a/test_inputs/codegen/omega/collard-0.c b/test_inputs/codegen/omega/collard-0.c
new file mode 100644 (file)
index 0000000..0664228
--- /dev/null
@@ -0,0 +1,16 @@
+{
+  for (int c4 = 1; c4 <= n; c4 += 1)
+    s2(c4);
+  for (int c1 = 1; c1 <= n - 1; c1 += 1) {
+    for (int c4 = 0; c4 <= n - c1 - 1; c4 += 1)
+      s0(c1, n - c4);
+    for (int c3 = 0; c3 <= n - c1 - 1; c3 += 1)
+      for (int c4 = c1 + 1; c4 <= n; c4 += 1)
+        s1(c1, n - c3, c4);
+  }
+  for (int c1 = 1; c1 <= n; c1 += 1) {
+    s4(c1);
+    for (int c3 = c1 + 1; c3 <= n; c3 += 1)
+      s3(c3, c1);
+  }
+}
diff --git a/test_inputs/codegen/omega/collard-0.in b/test_inputs/codegen/omega/collard-0.in
new file mode 100644 (file)
index 0000000..d803da7
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s1[i, j, k] -> [1, i, 1, n - j, k] : j >= 1 + i and k >= 1 + i and i >= 1 and j <= n and k <= n; s2[i] -> [0, 0, 0, 0, i] : i >= 1 and i <= n; s4[i] -> [2, i, 0, 0, 0] : i >= 1 and i <= n; s0[i, j] -> [1, i, 0, n - i, n - j] : i >= 1 and j >= 1 + i and j <= n; s3[i, j] -> [2, j, 1, i, j] : j >= 1 and j <= -1 + i and i <= n }
+{  :  }
+[n] -> { [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 4; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 3 }
diff --git a/test_inputs/codegen/omega/dagstuhl1-0.c b/test_inputs/codegen/omega/dagstuhl1-0.c
new file mode 100644 (file)
index 0000000..9a6333d
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = 0; c0 <= 99; c0 += 1)
+  s0(c0 - 10 * (9 * c0 / 10 / 9), 9 * c0 / 10 / 9);
diff --git a/test_inputs/codegen/omega/dagstuhl1-0.in b/test_inputs/codegen/omega/dagstuhl1-0.in
new file mode 100644 (file)
index 0000000..0c2b107
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [i + 10j] : i >= 0 and i <= 9 and j >= 0 and j <= 9 }
+{  :  }
+{ [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/test_inputs/codegen/omega/dagstuhl1-1.c b/test_inputs/codegen/omega/dagstuhl1-1.c
new file mode 100644 (file)
index 0000000..a725c91
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = 0; c0 <= 99; c0 += 1)
+  s0(c0, c0 + 10 * floord(-c0 - 1, 10) + 10, -floord(-c0 - 1, 10) - 1);
diff --git a/test_inputs/codegen/omega/dagstuhl1-1.in b/test_inputs/codegen/omega/dagstuhl1-1.in
new file mode 100644 (file)
index 0000000..e0c7273
--- /dev/null
@@ -0,0 +1,3 @@
+{s0[p,i,j] -> [p,i,j] : 0 <= i,j <= 9 && p = i+10j}
+{  :  }
+{ [p,i,j] -> separate[o0] : o0 >= 2; [p,i,j] -> atomic[o0] : o0 <= 1 }
diff --git a/test_inputs/codegen/omega/fc1-0.c b/test_inputs/codegen/omega/fc1-0.c
new file mode 100644 (file)
index 0000000..9fd2409
--- /dev/null
@@ -0,0 +1,7 @@
+for (int c0 = 0; c0 <= n - 2; c0 += 1) {
+  for (int c3 = 0; c3 <= n - c0 - 2; c3 += 1)
+    s0(c0 + 1, n - c3);
+  for (int c3 = 0; c3 <= n - c0 - 2; c3 += 1)
+    for (int c6 = c0 + 2; c6 <= n; c6 += 1)
+      s1(c0 + 1, n - c3, c6);
+}
diff --git a/test_inputs/codegen/omega/fc1-0.in b/test_inputs/codegen/omega/fc1-0.in
new file mode 100644 (file)
index 0000000..688f958
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[i, j] -> [-1 + i, 0, n - i, n - j] : i >= 1 and j >= 1 + i and j <= n; s1[i, j, k] -> [-1 + i, 1, n - i, n - j] : j >= 1 + i and k >= 1 + i and i >= 1 and j <= n and k <= n }
+{  :  }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2; [i0, i1, i2, i3] -> separate[o0] : o0 >= 3 }
diff --git a/test_inputs/codegen/omega/fc1-1.c b/test_inputs/codegen/omega/fc1-1.c
new file mode 100644 (file)
index 0000000..6ee68b4
--- /dev/null
@@ -0,0 +1,17 @@
+{
+  for (int c3 = 1; c3 <= n; c3 += 1)
+    s2(c3);
+  for (int c0 = 0; c0 <= n - 2; c0 += 1) {
+    for (int c3 = 0; c3 <= n - c0 - 2; c3 += 1)
+      s0(c0 + 1, n - c3);
+    for (int c3 = 0; c3 <= n - c0 - 2; c3 += 1)
+      for (int c6 = c0 + 2; c6 <= n; c6 += 1)
+        s1(c0 + 1, n - c3, c6);
+  }
+  for (int c0 = n - 1; c0 <= 2 * n - 2; c0 += 1) {
+    if (c0 >= n)
+      for (int c2 = -n + c0 + 2; c2 <= n; c2 += 1)
+        s3(c2, -n + c0 + 1);
+    s4(-n + c0 + 2);
+  }
+}
diff --git a/test_inputs/codegen/omega/fc1-1.in b/test_inputs/codegen/omega/fc1-1.in
new file mode 100644 (file)
index 0000000..c9135ff
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s1[i, j, k] -> [-1 + i, 1, n - i, n - j] : j >= 1 + i and k >= 1 + i and i >= 1 and j <= n and k <= n; s3[i, j] -> [-1 + n + j, 0, i, j] : j >= 1 and j <= -1 + i and i <= n; s4[i] -> [-2 + n + i, 1, 0, 0] : i >= 1 and i <= n; s0[i, j] -> [-1 + i, 0, n - i, n - j] : i >= 1 and j >= 1 + i and j <= n; s2[i] -> [0, 0, 0, i] : i >= 1 and i <= n }
+{  :  }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2; [i0, i1, i2, i3] -> separate[o0] : o0 >= 3 }
diff --git a/test_inputs/codegen/omega/fc1-2.c b/test_inputs/codegen/omega/fc1-2.c
new file mode 100644 (file)
index 0000000..6ee68b4
--- /dev/null
@@ -0,0 +1,17 @@
+{
+  for (int c3 = 1; c3 <= n; c3 += 1)
+    s2(c3);
+  for (int c0 = 0; c0 <= n - 2; c0 += 1) {
+    for (int c3 = 0; c3 <= n - c0 - 2; c3 += 1)
+      s0(c0 + 1, n - c3);
+    for (int c3 = 0; c3 <= n - c0 - 2; c3 += 1)
+      for (int c6 = c0 + 2; c6 <= n; c6 += 1)
+        s1(c0 + 1, n - c3, c6);
+  }
+  for (int c0 = n - 1; c0 <= 2 * n - 2; c0 += 1) {
+    if (c0 >= n)
+      for (int c2 = -n + c0 + 2; c2 <= n; c2 += 1)
+        s3(c2, -n + c0 + 1);
+    s4(-n + c0 + 2);
+  }
+}
diff --git a/test_inputs/codegen/omega/fc1-2.in b/test_inputs/codegen/omega/fc1-2.in
new file mode 100644 (file)
index 0000000..6d9a162
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s1[i, j, k] -> [-1 + i, 1, n - i, n - j] : j >= 1 + i and k >= 1 + i and i >= 1 and j <= n and k <= n; s3[i, j] -> [-1 + n + j, 0, i, j] : j >= 1 and j <= -1 + i and i <= n; s4[i] -> [-2 + n + i, 1, 0, 0] : i >= 1 and i <= n; s0[i, j] -> [-1 + i, 0, n - i, n - j] : i >= 1 and j >= 1 + i and j <= n; s2[i] -> [0, 0, 0, i] : i >= 1 and i <= n }
+{  :  }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 1; [i0, i1, i2, i3] -> separate[o0] : o0 >= 2 }
diff --git a/test_inputs/codegen/omega/fc2-0.c b/test_inputs/codegen/omega/fc2-0.c
new file mode 100644 (file)
index 0000000..9fd2409
--- /dev/null
@@ -0,0 +1,7 @@
+for (int c0 = 0; c0 <= n - 2; c0 += 1) {
+  for (int c3 = 0; c3 <= n - c0 - 2; c3 += 1)
+    s0(c0 + 1, n - c3);
+  for (int c3 = 0; c3 <= n - c0 - 2; c3 += 1)
+    for (int c6 = c0 + 2; c6 <= n; c6 += 1)
+      s1(c0 + 1, n - c3, c6);
+}
diff --git a/test_inputs/codegen/omega/fc2-0.in b/test_inputs/codegen/omega/fc2-0.in
new file mode 100644 (file)
index 0000000..688f958
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[i, j] -> [-1 + i, 0, n - i, n - j] : i >= 1 and j >= 1 + i and j <= n; s1[i, j, k] -> [-1 + i, 1, n - i, n - j] : j >= 1 + i and k >= 1 + i and i >= 1 and j <= n and k <= n }
+{  :  }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2; [i0, i1, i2, i3] -> separate[o0] : o0 >= 3 }
diff --git a/test_inputs/codegen/omega/fc2-1.c b/test_inputs/codegen/omega/fc2-1.c
new file mode 100644 (file)
index 0000000..6ee68b4
--- /dev/null
@@ -0,0 +1,17 @@
+{
+  for (int c3 = 1; c3 <= n; c3 += 1)
+    s2(c3);
+  for (int c0 = 0; c0 <= n - 2; c0 += 1) {
+    for (int c3 = 0; c3 <= n - c0 - 2; c3 += 1)
+      s0(c0 + 1, n - c3);
+    for (int c3 = 0; c3 <= n - c0 - 2; c3 += 1)
+      for (int c6 = c0 + 2; c6 <= n; c6 += 1)
+        s1(c0 + 1, n - c3, c6);
+  }
+  for (int c0 = n - 1; c0 <= 2 * n - 2; c0 += 1) {
+    if (c0 >= n)
+      for (int c2 = -n + c0 + 2; c2 <= n; c2 += 1)
+        s3(c2, -n + c0 + 1);
+    s4(-n + c0 + 2);
+  }
+}
diff --git a/test_inputs/codegen/omega/fc2-1.in b/test_inputs/codegen/omega/fc2-1.in
new file mode 100644 (file)
index 0000000..c9135ff
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s1[i, j, k] -> [-1 + i, 1, n - i, n - j] : j >= 1 + i and k >= 1 + i and i >= 1 and j <= n and k <= n; s3[i, j] -> [-1 + n + j, 0, i, j] : j >= 1 and j <= -1 + i and i <= n; s4[i] -> [-2 + n + i, 1, 0, 0] : i >= 1 and i <= n; s0[i, j] -> [-1 + i, 0, n - i, n - j] : i >= 1 and j >= 1 + i and j <= n; s2[i] -> [0, 0, 0, i] : i >= 1 and i <= n }
+{  :  }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2; [i0, i1, i2, i3] -> separate[o0] : o0 >= 3 }
diff --git a/test_inputs/codegen/omega/floor_bound-0.c b/test_inputs/codegen/omega/floor_bound-0.c
new file mode 100644 (file)
index 0000000..534b50e
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = -4 * floord(floord(-m, 3), 4); c0 <= floord(n, 3); c0 += 4)
+  s0(c0);
diff --git a/test_inputs/codegen/omega/floor_bound-0.in b/test_inputs/codegen/omega/floor_bound-0.in
new file mode 100644 (file)
index 0000000..45faa57
--- /dev/null
@@ -0,0 +1,3 @@
+[m, n] -> { s0[In_1] -> [In_1] : exists (e0 = [(In_1)/4]: 4e0 = In_1 and 3In_1 >= m and 3In_1 <= n) }
+{  :  }
+[m, n] -> { [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/test_inputs/codegen/omega/floor_bound-1.c b/test_inputs/codegen/omega/floor_bound-1.c
new file mode 100644 (file)
index 0000000..b1420ce
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = -floord(-m - 1, 4) - 1; c0 <= n; c0 += 1)
+  s0(c0);
diff --git a/test_inputs/codegen/omega/floor_bound-1.in b/test_inputs/codegen/omega/floor_bound-1.in
new file mode 100644 (file)
index 0000000..7ae72ab
--- /dev/null
@@ -0,0 +1,3 @@
+[m, n] -> { s0[In_1] -> [In_1] : 4In_1 >= -3 + m and In_1 <= n }
+{  :  }
+[m, n] -> { [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/test_inputs/codegen/omega/floor_bound-2.c b/test_inputs/codegen/omega/floor_bound-2.c
new file mode 100644 (file)
index 0000000..ff5f3c3
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = 4 * floord(m, 4); c0 <= n; c0 += 1)
+  s0(c0);
diff --git a/test_inputs/codegen/omega/floor_bound-2.in b/test_inputs/codegen/omega/floor_bound-2.in
new file mode 100644 (file)
index 0000000..73e1b8e
--- /dev/null
@@ -0,0 +1,3 @@
+[m, n] -> { s0[In_1] -> [In_1] : exists (e0 = [(m)/4]: 4e0 <= m and 4e0 >= -3 + m and 4e0 <= In_1 and In_1 <= n) }
+{  :  }
+[m, n] -> { [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/test_inputs/codegen/omega/floor_bound-3.c b/test_inputs/codegen/omega/floor_bound-3.c
new file mode 100644 (file)
index 0000000..e3c9728
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = 3 * floord(m, 3) + 4 * floord(m, 4); c0 <= n; c0 += 1)
+  s0(c0);
diff --git a/test_inputs/codegen/omega/floor_bound-3.in b/test_inputs/codegen/omega/floor_bound-3.in
new file mode 100644 (file)
index 0000000..1ff7e2c
--- /dev/null
@@ -0,0 +1,3 @@
+[m, n] -> { s0[In_1] -> [In_1] : exists (e0 = [(m)/3], e1 = [(m)/4]: 4e1 <= m and 3e0 <= m and 4e1 >= -3 + m and 3e0 >= -2 + m and In_1 <= n and 4e1 <= In_1 - 3e0) }
+{  :  }
+[m, n] -> { [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/test_inputs/codegen/omega/floor_bound-4.c b/test_inputs/codegen/omega/floor_bound-4.c
new file mode 100644 (file)
index 0000000..dc6ba0a
--- /dev/null
@@ -0,0 +1,3 @@
+if (n >= 3 * floord(n + 1, 3))
+  for (int c0 = m; c0 <= 5 * floord(n + 1, 3); c0 += 1)
+    s0(c0);
diff --git a/test_inputs/codegen/omega/floor_bound-4.in b/test_inputs/codegen/omega/floor_bound-4.in
new file mode 100644 (file)
index 0000000..7a726c3
--- /dev/null
@@ -0,0 +1,3 @@
+[n, m] -> { s0[In_1] -> [In_1] : exists (e0 = [(1 + n)/3]: In_1 >= m and 5e0 >= In_1 and 3e0 <= n and 3e0 >= -1 + n) }
+{  :  }
+[n, m] -> { [i0] -> atomic[o0] : o0 <= -1; [i0] -> separate[o0] : o0 >= 0 }
diff --git a/test_inputs/codegen/omega/floor_bound-5.c b/test_inputs/codegen/omega/floor_bound-5.c
new file mode 100644 (file)
index 0000000..3e9f47d
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = 4 * floord(m, 32); c0 <= n; c0 += 1)
+  s0(c0);
diff --git a/test_inputs/codegen/omega/floor_bound-5.in b/test_inputs/codegen/omega/floor_bound-5.in
new file mode 100644 (file)
index 0000000..cc24250
--- /dev/null
@@ -0,0 +1,3 @@
+[m, n] -> { s0[In_1] -> [In_1] : exists (e0 = [(m)/32]: 32e0 <= m and 32e0 >= -31 + m and 4e0 <= In_1 and In_1 <= n) }
+{  :  }
+[m, n] -> { [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/test_inputs/codegen/omega/floor_bound-6.c b/test_inputs/codegen/omega/floor_bound-6.c
new file mode 100644 (file)
index 0000000..06b32e5
--- /dev/null
@@ -0,0 +1,3 @@
+if (m >= 8 * floord(m + 1, 8))
+  for (int c0 = 4 * floord(floord(m + 1, 8), 4); c0 <= n; c0 += 1)
+    s0(c0);
diff --git a/test_inputs/codegen/omega/floor_bound-6.in b/test_inputs/codegen/omega/floor_bound-6.in
new file mode 100644 (file)
index 0000000..78d2be9
--- /dev/null
@@ -0,0 +1,3 @@
+[m, n] -> { s0[In_1] -> [In_1] : exists (e0 = [(1 + m)/8], e1 = [(e0)/4]: 8e0 <= m and 8e0 >= -6 + m and 4e1 <= In_1 and In_1 <= n and 32e1 <= 1 + m and 32e1 >= -30 + m) }
+{  :  }
+[m, n] -> { [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/test_inputs/codegen/omega/gc-0.c b/test_inputs/codegen/omega/gc-0.c
new file mode 100644 (file)
index 0000000..d8234a3
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = 2; c0 <= 8; c0 += 2)
+  s0(c0);
diff --git a/test_inputs/codegen/omega/gc-0.in b/test_inputs/codegen/omega/gc-0.in
new file mode 100644 (file)
index 0000000..063e353
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1] -> [In_1] : exists (e0 = [(In_1)/2]: 2e0 = In_1 and In_1 >= 2 and In_1 <= 8) }
+{  :  }
+{ [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/test_inputs/codegen/omega/ge-0.c b/test_inputs/codegen/omega/ge-0.c
new file mode 100644 (file)
index 0000000..4e57c57
--- /dev/null
@@ -0,0 +1,7 @@
+for (int c0 = 2; c0 <= n; c0 += 1)
+  for (int c1 = 1; c1 <= n; c1 += 1) {
+    for (int c3 = 1; c3 <= min(c0 - 1, c1 - 1); c3 += 1)
+      s1(c3, c0, c1);
+    if (c0 >= c1 + 1)
+      s0(c1, c0);
+  }
diff --git a/test_inputs/codegen/omega/ge-0.in b/test_inputs/codegen/omega/ge-0.in
new file mode 100644 (file)
index 0000000..edd7c36
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[k, i] -> [i, k, 1, 0] : k >= 1 and i >= 1 + k and i <= n; s1[k, i, j] -> [i, j, 0, k] : i >= 1 + k and j >= 1 + k and k >= 1 and i <= n and j <= n }
+{  :  }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2; [i0, i1, i2, i3] -> separate[o0] : o0 >= 3 }
diff --git a/test_inputs/codegen/omega/ge-1.c b/test_inputs/codegen/omega/ge-1.c
new file mode 100644 (file)
index 0000000..4e57c57
--- /dev/null
@@ -0,0 +1,7 @@
+for (int c0 = 2; c0 <= n; c0 += 1)
+  for (int c1 = 1; c1 <= n; c1 += 1) {
+    for (int c3 = 1; c3 <= min(c0 - 1, c1 - 1); c3 += 1)
+      s1(c3, c0, c1);
+    if (c0 >= c1 + 1)
+      s0(c1, c0);
+  }
diff --git a/test_inputs/codegen/omega/ge-1.in b/test_inputs/codegen/omega/ge-1.in
new file mode 100644 (file)
index 0000000..4a08142
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[k, i] -> [i, k, 1, 0] : k >= 1 and i >= 1 + k and i <= n; s1[k, i, j] -> [i, j, 0, k] : i >= 1 + k and j >= 1 + k and k >= 1 and i <= n and j <= n }
+{  :  }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 1; [i0, i1, i2, i3] -> separate[o0] : o0 >= 2 }
diff --git a/test_inputs/codegen/omega/gist-0.c b/test_inputs/codegen/omega/gist-0.c
new file mode 100644 (file)
index 0000000..4608d61
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= n; c0 += 4)
+  for (int c1 = c0; c1 <= n; c1 += 3)
+    s0(c0, c1);
diff --git a/test_inputs/codegen/omega/gist-0.in b/test_inputs/codegen/omega/gist-0.in
new file mode 100644 (file)
index 0000000..b2f3366
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(-1 + In_1)/4], e1 = [(-3 - In_1 + 4In_2)/12]: 4e0 = -1 + In_1 and 12e1 = -3 - In_1 + 4In_2 and In_1 >= 1 and In_2 >= In_1 and In_2 <= n) }
+{  :  }
+[n] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/gist-1.c b/test_inputs/codegen/omega/gist-1.c
new file mode 100644 (file)
index 0000000..8f1c692
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= n; c0 += 4)
+  for (int c1 = c0; c1 <= n; c1 += 8)
+    s0(c0, c1);
diff --git a/test_inputs/codegen/omega/gist-1.in b/test_inputs/codegen/omega/gist-1.in
new file mode 100644 (file)
index 0000000..ecbf8e7
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(-1 + In_1)/4], e1 = [(-In_1 + In_2)/8]: 4e0 = -1 + In_1 and 8e1 = -In_1 + In_2 and In_1 >= 1 and In_2 >= In_1 and In_2 <= n) }
+{  :  }
+[n] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/gist-2.c b/test_inputs/codegen/omega/gist-2.c
new file mode 100644 (file)
index 0000000..3174987
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= n; c0 += 256)
+  for (int c1 = c0; c1 <= n; c1 += 8)
+    s0(c0, c1);
diff --git a/test_inputs/codegen/omega/gist-2.in b/test_inputs/codegen/omega/gist-2.in
new file mode 100644 (file)
index 0000000..63edb52
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(-1 + In_1)/256], e1 = [(-1 + In_2)/8]: 256e0 = -1 + In_1 and 8e1 = -1 + In_2 and In_1 >= 1 and In_2 >= In_1 and In_2 <= n) }
+{  :  }
+[n] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/gist-3.c b/test_inputs/codegen/omega/gist-3.c
new file mode 100644 (file)
index 0000000..07ba418
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= n - 1; c0 += 4)
+  for (int c1 = c0 + 1; c1 <= n; c1 += 6)
+    s0(c0, c1);
diff --git a/test_inputs/codegen/omega/gist-3.in b/test_inputs/codegen/omega/gist-3.in
new file mode 100644 (file)
index 0000000..43cac12
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(-1 + In_1)/4], e1 = [(-1 - In_1 + In_2)/6]: 4e0 = -1 + In_1 and 6e1 = -1 - In_1 + In_2 and In_1 >= 1 and In_2 >= 1 + In_1 and In_2 <= n) }
+{  :  }
+[n] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/gist-4.c b/test_inputs/codegen/omega/gist-4.c
new file mode 100644 (file)
index 0000000..a6f6fd0
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= n; c0 += 6)
+  for (int c1 = c0; c1 <= n; c1 += 4)
+    s0(c0, c1);
diff --git a/test_inputs/codegen/omega/gist-4.in b/test_inputs/codegen/omega/gist-4.in
new file mode 100644 (file)
index 0000000..f67f837
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(-1 + In_1)/6], e1 = [(-2 - In_1 + 3In_2)/12]: 6e0 = -1 + In_1 and 12e1 = -2 - In_1 + 3In_2 and In_1 >= 1 and In_2 >= In_1 and In_2 <= n) }
+{  :  }
+[n] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/gist-5.c b/test_inputs/codegen/omega/gist-5.c
new file mode 100644 (file)
index 0000000..c2df61f
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= n; c0 += 12)
+  for (int c1 = c0; c1 <= n; c1 += 8)
+    s0(c0, c1);
diff --git a/test_inputs/codegen/omega/gist-5.in b/test_inputs/codegen/omega/gist-5.in
new file mode 100644 (file)
index 0000000..8b192c1
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(-1 + In_1)/12], e1 = [(-2 - In_1 + 3In_2)/24]: 12e0 = -1 + In_1 and 24e1 = -2 - In_1 + 3In_2 and In_1 >= 1 and In_2 >= In_1 and In_2 <= n) }
+{  :  }
+[n] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/guard1-0.c b/test_inputs/codegen/omega/guard1-0.c
new file mode 100644 (file)
index 0000000..484715e
--- /dev/null
@@ -0,0 +1,2 @@
+if (n + 3 * floord(-n + m - 2, 3) + 2 == m)
+  s0(n, m);
diff --git a/test_inputs/codegen/omega/guard1-0.in b/test_inputs/codegen/omega/guard1-0.in
new file mode 100644 (file)
index 0000000..52964e2
--- /dev/null
@@ -0,0 +1,3 @@
+[n, m] -> { s0[n, m] -> [n, m] : exists (e0 = [(-2 - n + m)/3]: 3e0 = -2 - n + m) }
+{  :  }
+[n, m] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/guard1-1.c b/test_inputs/codegen/omega/guard1-1.c
new file mode 100644 (file)
index 0000000..1d84fe2
--- /dev/null
@@ -0,0 +1,2 @@
+if (n + 2 * floord(-n + m - 1, 2) + 1 == m)
+  s0(n, m);
diff --git a/test_inputs/codegen/omega/guard1-1.in b/test_inputs/codegen/omega/guard1-1.in
new file mode 100644 (file)
index 0000000..141f585
--- /dev/null
@@ -0,0 +1,3 @@
+[n, m] -> { s0[n, m] -> [n, m] : exists (e0 = [(-1 - n + m)/2]: 2e0 = -1 - n + m) }
+{  :  }
+[n, m] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/hpf-0.c b/test_inputs/codegen/omega/hpf-0.c
new file mode 100644 (file)
index 0000000..2756b45
--- /dev/null
@@ -0,0 +1,4 @@
+if (P1 == P2 && P2 <= 3 && P2 >= 0)
+  for (int c0 = 0; c0 <= min(2, -P2 + 4); c0 += 1)
+    for (int c2 = -P2 - c0 - 3 * floord(-P2 - c0, 3); c2 <= 3; c2 += 3)
+      s0(c0, c0, c2, c2);
diff --git a/test_inputs/codegen/omega/hpf-0.in b/test_inputs/codegen/omega/hpf-0.in
new file mode 100644 (file)
index 0000000..e697792
--- /dev/null
@@ -0,0 +1,3 @@
+[P1, P2] -> { s0[In_1, In_1, In_3, In_3] -> [In_1, In_1, In_3, In_3] : exists (e0 = [(-2P2 - 2In_1 + In_3)/3]: P1 = P2 and 3e0 = -2P2 - 2In_1 + In_3 and P2 >= 0 and P2 <= 3 and In_1 <= 4 - P2 and In_1 >= 0 and In_1 <= 2 and In_3 >= 0 and In_3 <= 3) }
+{  :  }
+[P2, P1] -> { [i0, i1, i2, i3] -> separate[o0] : o0 >= 3; [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2 }
diff --git a/test_inputs/codegen/omega/if_then-0.c b/test_inputs/codegen/omega/if_then-0.c
new file mode 100644 (file)
index 0000000..bc8d337
--- /dev/null
@@ -0,0 +1,12 @@
+if (m <= 1) {
+  for (int c0 = 1; c0 <= n; c0 += 1)
+    for (int c1 = 1; c1 <= n; c1 += 1)
+      s2(c0, c1);
+} else if (n >= m + 1) {
+  for (int c0 = 1; c0 <= n; c0 += 1)
+    for (int c1 = 1; c1 <= n; c1 += 1)
+      s0(c0, c1);
+} else
+  for (int c0 = 1; c0 <= n; c0 += 1)
+    for (int c1 = 1; c1 <= n; c1 += 1)
+      s1(c0, c1);
diff --git a/test_inputs/codegen/omega/if_then-0.in b/test_inputs/codegen/omega/if_then-0.in
new file mode 100644 (file)
index 0000000..93f3f7c
--- /dev/null
@@ -0,0 +1,3 @@
+[n, m] -> { s2[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_1 <= n and In_2 >= 1 and In_2 <= n and m <= 1; s0[In_1, In_2] -> [In_1, In_2] : m >= 2 and m <= -1 + n and In_1 >= 1 and In_1 <= n and In_2 >= 1 and In_2 <= n; s1[In_1, In_2] -> [In_1, In_2] : In_1 <= n and In_2 <= n and m >= n and In_1 >= 1 and In_2 >= 1 and m >= 2 }
+{  :  }
+[n, m] -> { [i0, i1] -> atomic[o0] : o0 <= 1; [i0, i1] -> separate[o0] : o0 >= 2 }
diff --git a/test_inputs/codegen/omega/if_then-1.c b/test_inputs/codegen/omega/if_then-1.c
new file mode 100644 (file)
index 0000000..18ca370
--- /dev/null
@@ -0,0 +1,9 @@
+for (int c0 = 1; c0 <= 100; c0 += 1) {
+  if (n >= 2)
+    s0(c0);
+  for (int c1 = 1; c1 <= 100; c1 += 1) {
+    if (n >= 2)
+      s1(c0, c1);
+    s2(c0, c1);
+  }
+}
diff --git a/test_inputs/codegen/omega/if_then-1.in b/test_inputs/codegen/omega/if_then-1.in
new file mode 100644 (file)
index 0000000..0258439
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1] -> [In_1,0] : In_1 >= 1 and In_1 <= 100 and n >= 2; s1[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and n >= 2; s2[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 }
+{  :  }
+[n] -> { [i0,i1] -> separate[o0] : o0 >= 2; [i0,i1] -> atomic[o0] : o0 <= 1 }
diff --git a/test_inputs/codegen/omega/if_then-2.c b/test_inputs/codegen/omega/if_then-2.c
new file mode 100644 (file)
index 0000000..b372c86
--- /dev/null
@@ -0,0 +1,10 @@
+for (int c0 = 1; c0 <= 100; c0 += 1)
+  if (n >= 2) {
+    s0(c0);
+    for (int c1 = 1; c1 <= 100; c1 += 1) {
+      s1(c0, c1);
+      s2(c0, c1);
+    }
+  } else
+    for (int c1 = 1; c1 <= 100; c1 += 1)
+      s2(c0, c1);
diff --git a/test_inputs/codegen/omega/if_then-2.in b/test_inputs/codegen/omega/if_then-2.in
new file mode 100644 (file)
index 0000000..0a220ee
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1] -> [In_1,0] : In_1 >= 1 and In_1 <= 100 and n >= 2; s1[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and n >= 2; s2[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 }
+{  :  }
+[n] -> { [i0,i1] -> separate[o0] : o0 >= 1; [i0,i1] -> atomic[o0] : o0 <= 0 }
diff --git a/test_inputs/codegen/omega/if_then-3.c b/test_inputs/codegen/omega/if_then-3.c
new file mode 100644 (file)
index 0000000..570cbe5
--- /dev/null
@@ -0,0 +1,12 @@
+if (n >= 2) {
+  for (int c0 = 1; c0 <= 100; c0 += 1) {
+    s0(c0);
+    for (int c1 = 1; c1 <= 100; c1 += 1) {
+      s1(c0, c1);
+      s2(c0, c1);
+    }
+  }
+} else
+  for (int c0 = 1; c0 <= 100; c0 += 1)
+    for (int c1 = 1; c1 <= 100; c1 += 1)
+      s2(c0, c1);
diff --git a/test_inputs/codegen/omega/if_then-3.in b/test_inputs/codegen/omega/if_then-3.in
new file mode 100644 (file)
index 0000000..a0315f1
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1] -> [In_1,0] : In_1 >= 1 and In_1 <= 100 and n >= 2; s1[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and n >= 2; s2[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 }
+{  :  }
+[n] -> { [i0,i1] -> separate[o0] : o0 >= 0; [i0,i1] -> atomic[o0] : o0 <= -1 }
diff --git a/test_inputs/codegen/omega/if_then-4.c b/test_inputs/codegen/omega/if_then-4.c
new file mode 100644 (file)
index 0000000..fa81628
--- /dev/null
@@ -0,0 +1,7 @@
+for (int c0 = 4; c0 <= 100; c0 += 4) {
+  for (int c1 = 1; c1 <= 100; c1 += 1)
+    s0(c0, c1);
+  if (c0 >= 8 && c0 <= 96)
+    for (int c1 = 10; c1 <= 100; c1 += 1)
+      s1(c0 + 2, c1);
+}
diff --git a/test_inputs/codegen/omega/if_then-4.in b/test_inputs/codegen/omega/if_then-4.in
new file mode 100644 (file)
index 0000000..30dc8dc
--- /dev/null
@@ -0,0 +1,3 @@
+{ s1[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(-2 + In_1)/4]: 4e0 = -2 + In_1 and In_1 >= 10 and In_1 <= 98 and In_2 >= 10 and In_2 <= 100); s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(In_1)/4]: 4e0 = In_1 and In_1 >= 4 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100) }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= 1; [i0, i1] -> separate[o0] : o0 >= 2 }
diff --git a/test_inputs/codegen/omega/if_then-5.c b/test_inputs/codegen/omega/if_then-5.c
new file mode 100644 (file)
index 0000000..fa81628
--- /dev/null
@@ -0,0 +1,7 @@
+for (int c0 = 4; c0 <= 100; c0 += 4) {
+  for (int c1 = 1; c1 <= 100; c1 += 1)
+    s0(c0, c1);
+  if (c0 >= 8 && c0 <= 96)
+    for (int c1 = 10; c1 <= 100; c1 += 1)
+      s1(c0 + 2, c1);
+}
diff --git a/test_inputs/codegen/omega/if_then-5.in b/test_inputs/codegen/omega/if_then-5.in
new file mode 100644 (file)
index 0000000..87a40f4
--- /dev/null
@@ -0,0 +1,3 @@
+{ s1[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(-2 + In_1)/4]: 4e0 = -2 + In_1 and In_1 >= 10 and In_1 <= 98 and In_2 >= 10 and In_2 <= 100); s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(In_1)/4]: 4e0 = In_1 and In_1 >= 4 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100) }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/iter1-0.c b/test_inputs/codegen/omega/iter1-0.c
new file mode 100644 (file)
index 0000000..c15c86b
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = 2; c0 <= 9; c0 += 1)
+  s0(c0);
diff --git a/test_inputs/codegen/omega/iter1-0.in b/test_inputs/codegen/omega/iter1-0.in
new file mode 100644 (file)
index 0000000..8b87678
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1] -> [In_1] : In_1 >= 2 and In_1 <= 9 }
+{  :  }
+{ [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/test_inputs/codegen/omega/iter2-0.c b/test_inputs/codegen/omega/iter2-0.c
new file mode 100644 (file)
index 0000000..5506929
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= 10; c0 += 1)
+  for (int c1 = 10; c1 <= 100; c1 += 1)
+    s0(c0, c1);
diff --git a/test_inputs/codegen/omega/iter2-0.in b/test_inputs/codegen/omega/iter2-0.in
new file mode 100644 (file)
index 0000000..16ea0df
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_1 <= 10 and In_2 >= 10 and In_2 <= 100 }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/iter3-0.c b/test_inputs/codegen/omega/iter3-0.c
new file mode 100644 (file)
index 0000000..43b6e3a
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 2; c0 <= 8; c0 += 1)
+  for (int c1 = c0 + 1; c1 <= 9; c1 += 1)
+    s0(c0, c1);
diff --git a/test_inputs/codegen/omega/iter3-0.in b/test_inputs/codegen/omega/iter3-0.in
new file mode 100644 (file)
index 0000000..fc26493
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, In_2] : In_1 >= 2 and In_2 >= 1 + In_1 and In_2 <= 9 }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/iter4-0.c b/test_inputs/codegen/omega/iter4-0.c
new file mode 100644 (file)
index 0000000..65e3702
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 2; c0 <= 9; c0 += 1)
+  for (int c1 = c0 + 1; c1 <= 2 * c0; c1 += 1)
+    s0(c0, c1);
diff --git a/test_inputs/codegen/omega/iter4-0.in b/test_inputs/codegen/omega/iter4-0.in
new file mode 100644 (file)
index 0000000..94001d5
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, In_2] : In_1 >= 2 and In_2 >= 1 + In_1 and In_2 <= 2In_1 and In_1 <= 9 }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/iter5-0.c b/test_inputs/codegen/omega/iter5-0.c
new file mode 100644 (file)
index 0000000..d7566d6
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 2; c0 <= 9; c0 += 1)
+  for (int c1 = c0 + 1; c1 <= min(2 * c0, 16); c1 += 1)
+    s0(c0, c1);
diff --git a/test_inputs/codegen/omega/iter5-0.in b/test_inputs/codegen/omega/iter5-0.in
new file mode 100644 (file)
index 0000000..1e4f739
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, In_2] : In_1 >= 2 and In_2 >= 1 + In_1 and In_2 <= 2In_1 and In_2 <= 16 and In_1 <= 9 }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/iter6-0.c b/test_inputs/codegen/omega/iter6-0.c
new file mode 100644 (file)
index 0000000..a0346b6
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= 5; c0 += 1)
+  for (int c1 = 12; c1 <= 17; c1 += 1)
+    s0(c0, c1);
diff --git a/test_inputs/codegen/omega/iter6-0.in b/test_inputs/codegen/omega/iter6-0.in
new file mode 100644 (file)
index 0000000..1b8ed2b
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_1 <= 5 and In_2 >= 12 and In_2 <= 17 }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/iter6-1.c b/test_inputs/codegen/omega/iter6-1.c
new file mode 100644 (file)
index 0000000..daccd39
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = 46; c0 <= 70; c0 += 12)
+  s0(c0, (17 * c0 - 170) / 12);
diff --git a/test_inputs/codegen/omega/iter6-1.in b/test_inputs/codegen/omega/iter6-1.in
new file mode 100644 (file)
index 0000000..4ee2ad6
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, o1] : 12In_2 = -170 + 17In_1 and 12o1 = -170 + 17In_1 and In_1 >= 46 and In_1 <= 70 }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/iter7-0.c b/test_inputs/codegen/omega/iter7-0.c
new file mode 100644 (file)
index 0000000..2606890
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = 1; c0 <= 3; c0 += 2)
+  s0(c0, (-3 * c0 + 15) / 2);
diff --git a/test_inputs/codegen/omega/iter7-0.in b/test_inputs/codegen/omega/iter7-0.in
new file mode 100644 (file)
index 0000000..90d3efb
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, o1] : 2In_2 = 15 - 3In_1 and 2o1 = 15 - 3In_1 and In_1 <= 3 and In_1 >= 1 }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/iter8-0.c b/test_inputs/codegen/omega/iter8-0.c
new file mode 100644 (file)
index 0000000..280b706
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = max(exprVar2 - 8 * floord(exprVar2 - exprVar1, 8) + 1, exprVar2 + 1); c0 <= 16; c0 += 8)
+  s0(c0);
diff --git a/test_inputs/codegen/omega/iter8-0.in b/test_inputs/codegen/omega/iter8-0.in
new file mode 100644 (file)
index 0000000..6829280
--- /dev/null
@@ -0,0 +1,3 @@
+[exprVar2, exprVar3, exprVar1] -> { s0[In_1] -> [In_1] : exists (e0 = [(-1 - exprVar2 + In_1)/8]: exprVar3 = 0 and 8e0 = -1 - exprVar2 + In_1 and exprVar1 >= 1 and In_1 >= 1 + exprVar1 and In_1 <= 16 and In_1 >= 1 + exprVar2) }
+[exprVar3, exprVar2, exprVar1] -> {  : exists (e0: exprVar3 = 0 and 8e0 >= -15 + exprVar2 and exprVar2 <= 15 and exprVar1 >= 1 and 8e0 <= exprVar2 - exprVar1) }
+[exprVar2, exprVar3, exprVar1] -> { [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/test_inputs/codegen/omega/iter9-0.c b/test_inputs/codegen/omega/iter9-0.c
new file mode 100644 (file)
index 0000000..bf6b887
--- /dev/null
@@ -0,0 +1,11 @@
+for (int c0 = 1; c0 <= 15; c0 += 1)
+  if (8 * floord(7 * exprVar1 + 7, 8) + 8 >= 7 * exprVar1 + c0 || (exprVar1 + 8 * floord(-exprVar1 + c0 - 1, 8) + 1 == c0 && c0 >= exprVar1 + 1)) {
+    s5(c0);
+    if (8 * floord(7 * exprVar1 + 7, 8) + 8 >= 7 * exprVar1 + c0) {
+      s0(c0);
+      s4(c0);
+      s1(c0);
+      s3(c0);
+      s2(c0);
+    }
+  }
diff --git a/test_inputs/codegen/omega/iter9-0.in b/test_inputs/codegen/omega/iter9-0.in
new file mode 100644 (file)
index 0000000..9596d73
--- /dev/null
@@ -0,0 +1,3 @@
+[exprVar2, exprVar1] -> { s3[In_1] -> [In_1] : exists (e0: exprVar2 = 0 and 8e0 >= -15 + exprVar1 and exprVar1 <= 15 and In_1 >= 1 and 8e0 <= exprVar1 - In_1); s4[In_1] -> [In_1] : exists (e0: exprVar2 = 0 and 8e0 >= -15 + exprVar1 and exprVar1 <= 15 and In_1 >= 1 and 8e0 <= exprVar1 - In_1); s1[In_1] -> [In_1] : exists (e0: exprVar2 = 0 and 8e0 >= -15 + exprVar1 and exprVar1 <= 15 and In_1 >= 1 and 8e0 <= exprVar1 - In_1); s5[In_1] -> [In_1] : (exists (e0: exprVar2 = 0 and 8e0 >= -15 + exprVar1 and exprVar1 <= 15 and In_1 >= 1 and 8e0 <= exprVar1 - In_1)) or (exists (e0 = [(-1 - exprVar1 + In_1)/8]: exprVar2 = 0 and 8e0 = -1 - exprVar1 + In_1 and In_1 >= 1 + exprVar1 and In_1 >= 1 and In_1 <= 15)); s0[In_1] -> [In_1] : exists (e0: exprVar2 = 0 and 8e0 >= -15 + exprVar1 and exprVar1 <= 15 and In_1 >= 1 and 8e0 <= exprVar1 - In_1); s2[In_1] -> [In_1] : exists (e0: exprVar2 = 0 and 8e0 >= -15 + exprVar1 and exprVar1 <= 15 and In_1 >= 1 and 8e0 <= exprVar1 - In_1) }
+[exprVar2, exprVar1] -> {  : exprVar2 = 0 and exprVar1 <= 15 }
+[exprVar2, exprVar1] -> { [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/test_inputs/codegen/omega/lefur00-0.c b/test_inputs/codegen/omega/lefur00-0.c
new file mode 100644 (file)
index 0000000..4003e52
--- /dev/null
@@ -0,0 +1,5 @@
+for (int c0 = 0; c0 <= 15; c0 += 1)
+  for (int c1 = max(c0 - (c0 + 1) / 2, 2 * c0 - 15); c1 <= min(c0 + 1, 15); c1 += 1)
+    for (int c2 = max(max(max(67 * c0 - (c0 + 1) / 3, 133 * c0 - 67 * c1 - floord(-c0 - c1 + 1, 3) - 66), 67 * c1 - floord(c1 - 1, 3) - 1), 1); c2 <= min(min(133 * c0 - 67 * c1 + floord(c0 + c1 - 1, 3) + 133, 100 * c0 + 99), 1000); c2 += 1)
+      for (int c3 = max(max(200 * c0 - c2, 100 * c1 + c2 - c2 / 2), c2); c3 <= min(min(100 * c1 + (c2 + 1) / 2 + 99, 2 * c2 + 1), 200 * c0 - c2 + 199); c3 += 1)
+        s0(c0, c1, c2, c3);
diff --git a/test_inputs/codegen/omega/lefur00-0.in b/test_inputs/codegen/omega/lefur00-0.in
new file mode 100644 (file)
index 0000000..cf99c81
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4] -> [In_1, In_2, In_3, In_4] : In_3 >= 1 and In_4 >= In_3 and In_4 <= 1 + 2In_3 and In_3 <= 1000 and In_4 >= 200In_1 - In_3 and In_4 <= 199 + 200In_1 - In_3 and 2In_4 >= 200In_2 + In_3 and 2In_4 <= 199 + 200In_2 + In_3 }
+{  :  }
+{ [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2; [i0, i1, i2, i3] -> separate[o0] : o0 >= 3 }
diff --git a/test_inputs/codegen/omega/lefur01-0.c b/test_inputs/codegen/omega/lefur01-0.c
new file mode 100644 (file)
index 0000000..4003e52
--- /dev/null
@@ -0,0 +1,5 @@
+for (int c0 = 0; c0 <= 15; c0 += 1)
+  for (int c1 = max(c0 - (c0 + 1) / 2, 2 * c0 - 15); c1 <= min(c0 + 1, 15); c1 += 1)
+    for (int c2 = max(max(max(67 * c0 - (c0 + 1) / 3, 133 * c0 - 67 * c1 - floord(-c0 - c1 + 1, 3) - 66), 67 * c1 - floord(c1 - 1, 3) - 1), 1); c2 <= min(min(133 * c0 - 67 * c1 + floord(c0 + c1 - 1, 3) + 133, 100 * c0 + 99), 1000); c2 += 1)
+      for (int c3 = max(max(200 * c0 - c2, 100 * c1 + c2 - c2 / 2), c2); c3 <= min(min(100 * c1 + (c2 + 1) / 2 + 99, 2 * c2 + 1), 200 * c0 - c2 + 199); c3 += 1)
+        s0(c0, c1, c2, c3);
diff --git a/test_inputs/codegen/omega/lefur01-0.in b/test_inputs/codegen/omega/lefur01-0.in
new file mode 100644 (file)
index 0000000..cf99c81
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4] -> [In_1, In_2, In_3, In_4] : In_3 >= 1 and In_4 >= In_3 and In_4 <= 1 + 2In_3 and In_3 <= 1000 and In_4 >= 200In_1 - In_3 and In_4 <= 199 + 200In_1 - In_3 and 2In_4 >= 200In_2 + In_3 and 2In_4 <= 199 + 200In_2 + In_3 }
+{  :  }
+{ [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2; [i0, i1, i2, i3] -> separate[o0] : o0 >= 3 }
diff --git a/test_inputs/codegen/omega/lefur01-1.c b/test_inputs/codegen/omega/lefur01-1.c
new file mode 100644 (file)
index 0000000..6dd8625
--- /dev/null
@@ -0,0 +1,5 @@
+for (int c0 = 0; c0 <= 15; c0 += 1)
+  for (int c1 = max(c0 - (c0 + 1) / 2, 2 * c0 - 15); c1 <= min(c0 + 1, 15); c1 += 1)
+    for (int c2 = max(max(max(133 * c0 - 67 * c1 - floord(-c0 - c1 + 1, 3) - 66, 67 * c1 - floord(c1 - 1, 3) - 1), 67 * c0 - (c0 + 1) / 3), 1); c2 <= min(min(133 * c0 - 67 * c1 + floord(c0 + c1 - 1, 3) + 133, 100 * c0 + 99), 1000); c2 += 1)
+      for (int c3 = max(max(200 * c0 - c2, 100 * c1 + c2 - c2 / 2), c2); c3 <= min(min(100 * c1 + (c2 + 1) / 2 + 99, 2 * c2 + 1), 200 * c0 - c2 + 199); c3 += 1)
+        s0(c0, c1, c2, c3);
diff --git a/test_inputs/codegen/omega/lefur01-1.in b/test_inputs/codegen/omega/lefur01-1.in
new file mode 100644 (file)
index 0000000..bc9611d
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4] -> [In_1, In_2, In_3, In_4] : In_3 >= 1 and In_4 >= In_3 and In_4 <= 1 + 2In_3 and In_3 <= 1000 and In_4 >= 200In_1 - In_3 and In_4 <= 199 + 200In_1 - In_3 and 2In_4 >= 200In_2 + In_3 and 2In_4 <= 199 + 200In_2 + In_3 }
+{  :  }
+{ [i0, i1, i2, i3] -> atomic[o0] : o0 <= 1; [i0, i1, i2, i3] -> separate[o0] : o0 >= 2 }
diff --git a/test_inputs/codegen/omega/lefur03-0.c b/test_inputs/codegen/omega/lefur03-0.c
new file mode 100644 (file)
index 0000000..2560ade
--- /dev/null
@@ -0,0 +1,7 @@
+for (int c0 = 0; c0 <= 3; c0 += 1)
+  for (int c1 = max(0, 2 * c0 - 3); c1 <= min(c0 + c0 / 2 + 1, 3); c1 += 1)
+    for (int c2 = c0; c2 <= min(min(3, 3 * c1 + 2), 2 * c0 - c1 + 1); c2 += 1)
+      for (int c3 = max(max(max(c1 - floord(-c1, 3) - 1, 0), c1 + c2 - (3 * c1 + c2) / 6 - 1), 2 * c0 - (c0 + c1 + 1) / 3 - 1); c3 <= min(c0 + 1, 3); c3 += 1)
+        for (int c4 = max(max(max(max(-200 * c1 + 400 * c3 - 199, 333 * c1 - floord(-c1 - 1, 3) - 1), 333 * c2 - floord(-c2 + 1, 3)), 667 * c0 - 333 * c1 - (c0 + c1) / 3 - 333), 250 * c3 + 1); c4 <= min(min(min(min(500 * c0 + 499, -200 * c1 + 400 * c3 + 400), 333 * c3 + floord(c3 - 1, 3) + 334), 1000), 333 * c2 + floord(c2 - 1, 3) + 333); c4 += 1)
+          for (int c5 = max(max(max(1000 * c3 - 2 * c4 + 2, 1000 * c0 - c4), 500 * c1 + c4 - c4 / 2), c4); c5 <= min(min(min(1000 * c3 - 2 * c4 + 1001, 1000 * c0 - c4 + 999), 500 * c1 + (c4 + 1) / 2 + 499), 2 * c4 + 1); c5 += 1)
+            s0(c0, c1, c2, c3, c4, c5);
diff --git a/test_inputs/codegen/omega/lefur03-0.in b/test_inputs/codegen/omega/lefur03-0.in
new file mode 100644 (file)
index 0000000..890f413
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5, In_6] -> [In_1, In_2, In_3, In_4, In_5, In_6] : In_6 >= In_5 and In_6 <= 1 + 2In_5 and In_5 <= 1000 and In_6 >= 1000In_1 - In_5 and In_6 <= 999 + 1000In_1 - In_5 and In_6 >= 2 + 1000In_4 - 2In_5 and In_6 <= 1001 + 1000In_4 - 2In_5 and In_4 >= 0 and 2In_6 >= 1000In_2 + In_5 and 2In_6 <= 999 + 1000In_2 + In_5 and 3In_5 >= -1 + 1000In_3 and 3In_5 <= 998 + 1000In_3 }
+{  :  }
+{ [i0, i1, i2, i3, i4, i5] -> separate[o0] : o0 >= 5; [i0, i1, i2, i3, i4, i5] -> atomic[o0] : o0 <= 4 }
diff --git a/test_inputs/codegen/omega/lefur04-0.c b/test_inputs/codegen/omega/lefur04-0.c
new file mode 100644 (file)
index 0000000..91463e6
--- /dev/null
@@ -0,0 +1,8 @@
+for (int c0 = 0; c0 <= 3; c0 += 1)
+  for (int c1 = max(0, 2 * c0 - 3); c1 <= min(c0 + 1, 3); c1 += 1)
+    for (int c2 = c0; c2 <= min(min(3, 3 * c1 + 2), 2 * c0 - c1 + 1); c2 += 1)
+      for (int c3 = max(max(max(c2 - floord(c2 - 1, 3) - 1, c1 + c2 - (3 * c1 + c2) / 6 - 1), c1 - floord(-c1, 3) - 1), c0 - floord(-c2, 3) - 1); c3 <= min(c0 + c0 / 2 + 1, 3); c3 += 1)
+        for (int c5 = max(max(max(max(c1 - floord(-c1, 3) - 1, 0), 2 * c3 - 4), c3 - c3 / 3 - 1), c2 - c2 / 3 - 1); c5 <= min(min(-c2 + 2 * c3 + floord(-c2 - 1, 3) + 2, c1 + 1), c3); c5 += 1)
+          for (int c6 = max(max(max(max(max(250 * c3 + 1, 667 * c0 - 333 * c1 - (c0 + c1) / 3 - 333), -200 * c1 + 400 * c3 - 199), 333 * c1 - floord(-c1 - 1, 3) - 1), 1000 * c0 - 500 * c5 - 501), 333 * c2 - floord(-c2 + 1, 3)); c6 <= min(min(min(min(min(min(333 * c3 + floord(c3 - 1, 3) + 334, 1000), 333 * c2 + floord(c2 - 1, 3) + 333), 1000 * c0 - 500 * c5 + 997), 500 * c5 + 501), 500 * c0 + 499), -200 * c1 + 400 * c3 + 400); c6 += 1)
+            for (int c7 = max(max(max(max(c6, 500 * c1 + c6 - c6 / 2), 1000 * c0 - c6), 500 * c5 + 2), 1000 * c3 - 2 * c6 + 2); c7 <= min(min(min(min(500 * c5 + 501, 2 * c6 + 1), 1000 * c3 - 2 * c6 + 1001), 1000 * c0 - c6 + 999), 500 * c1 + (c6 + 1) / 2 + 499); c7 += 1)
+              s0(c0, c1, c2, c3, c2 / 3, c5, c6, c7);
diff --git a/test_inputs/codegen/omega/lefur04-0.in b/test_inputs/codegen/omega/lefur04-0.in
new file mode 100644 (file)
index 0000000..c50a0da
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5, In_6, In_7, In_8] -> [In_1, In_2, In_3, In_4, In_5, In_6, In_7, In_8] : In_7 >= 1000In_5 and In_8 >= In_7 and In_8 <= 501 + 500In_6 and In_8 <= 1 + 2In_7 and In_7 <= 999 + 1000In_5 and In_7 <= 1000 and In_8 >= 1000In_1 - In_7 and In_8 <= 999 + 1000In_1 - In_7 and 2In_8 >= 1000In_2 + In_7 and 2In_8 <= 999 + 1000In_2 + In_7 and 3In_7 >= -1 + 1000In_3 and 3In_7 <= 998 + 1000In_3 and In_8 >= 2 + 500In_6 and In_6 >= 0 and In_8 >= 2 + 1000In_4 - 2In_7 and In_8 <= 1001 + 1000In_4 - 2In_7 }
+{  :  }
+{ [i0, i1, i2, i3, i4, i5, i6, i7] -> atomic[o0] : o0 <= 6; [i0, i1, i2, i3, i4, i5, i6, i7] -> separate[o0] : o0 >= 7 }
diff --git a/test_inputs/codegen/omega/lift1-0.c b/test_inputs/codegen/omega/lift1-0.c
new file mode 100644 (file)
index 0000000..f7b1ae9
--- /dev/null
@@ -0,0 +1,9 @@
+for (int c0 = 1; c0 <= 100; c0 += 1)
+  for (int c1 = 1; c1 <= 100; c1 += 1)
+    for (int c2 = 1; c2 <= 100; c2 += 1)
+      for (int c3 = 1; c3 <= 100; c3 += 1)
+        for (int c4 = 1; c4 <= 100; c4 += 1) {
+          s1(c0, c1, c2, c3, c4);
+          if (c0 <= 60)
+            s0(c0, c1, c2, c3, c4);
+        }
diff --git a/test_inputs/codegen/omega/lift1-0.in b/test_inputs/codegen/omega/lift1-0.in
new file mode 100644 (file)
index 0000000..31ae11a
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{  :  }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 5; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 4 }
diff --git a/test_inputs/codegen/omega/lift1-1.c b/test_inputs/codegen/omega/lift1-1.c
new file mode 100644 (file)
index 0000000..a32e25f
--- /dev/null
@@ -0,0 +1,12 @@
+for (int c0 = 1; c0 <= 100; c0 += 1)
+  for (int c1 = 1; c1 <= 100; c1 += 1)
+    for (int c2 = 1; c2 <= 100; c2 += 1)
+      for (int c3 = 1; c3 <= 100; c3 += 1)
+        if (c0 >= 61) {
+          for (int c4 = 1; c4 <= 100; c4 += 1)
+            s1(c0, c1, c2, c3, c4);
+        } else
+          for (int c4 = 1; c4 <= 100; c4 += 1) {
+            s1(c0, c1, c2, c3, c4);
+            s0(c0, c1, c2, c3, c4);
+          }
diff --git a/test_inputs/codegen/omega/lift1-1.in b/test_inputs/codegen/omega/lift1-1.in
new file mode 100644 (file)
index 0000000..44de4ac
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{  :  }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 4; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 3 }
diff --git a/test_inputs/codegen/omega/lift1-2.c b/test_inputs/codegen/omega/lift1-2.c
new file mode 100644 (file)
index 0000000..aae7bfc
--- /dev/null
@@ -0,0 +1,13 @@
+for (int c0 = 1; c0 <= 100; c0 += 1)
+  for (int c1 = 1; c1 <= 100; c1 += 1)
+    for (int c2 = 1; c2 <= 100; c2 += 1)
+      if (c0 >= 61) {
+        for (int c3 = 1; c3 <= 100; c3 += 1)
+          for (int c4 = 1; c4 <= 100; c4 += 1)
+            s1(c0, c1, c2, c3, c4);
+      } else
+        for (int c3 = 1; c3 <= 100; c3 += 1)
+          for (int c4 = 1; c4 <= 100; c4 += 1) {
+            s1(c0, c1, c2, c3, c4);
+            s0(c0, c1, c2, c3, c4);
+          }
diff --git a/test_inputs/codegen/omega/lift1-2.in b/test_inputs/codegen/omega/lift1-2.in
new file mode 100644 (file)
index 0000000..241fbb9
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{  :  }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 3; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 2 }
diff --git a/test_inputs/codegen/omega/lift1-3.c b/test_inputs/codegen/omega/lift1-3.c
new file mode 100644 (file)
index 0000000..de9025b
--- /dev/null
@@ -0,0 +1,14 @@
+for (int c0 = 1; c0 <= 100; c0 += 1)
+  for (int c1 = 1; c1 <= 100; c1 += 1)
+    if (c0 >= 61) {
+      for (int c2 = 1; c2 <= 100; c2 += 1)
+        for (int c3 = 1; c3 <= 100; c3 += 1)
+          for (int c4 = 1; c4 <= 100; c4 += 1)
+            s1(c0, c1, c2, c3, c4);
+    } else
+      for (int c2 = 1; c2 <= 100; c2 += 1)
+        for (int c3 = 1; c3 <= 100; c3 += 1)
+          for (int c4 = 1; c4 <= 100; c4 += 1) {
+            s1(c0, c1, c2, c3, c4);
+            s0(c0, c1, c2, c3, c4);
+          }
diff --git a/test_inputs/codegen/omega/lift1-3.in b/test_inputs/codegen/omega/lift1-3.in
new file mode 100644 (file)
index 0000000..a50a9ec
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{  :  }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 2; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 1 }
diff --git a/test_inputs/codegen/omega/lift1-4.c b/test_inputs/codegen/omega/lift1-4.c
new file mode 100644 (file)
index 0000000..1b85969
--- /dev/null
@@ -0,0 +1,15 @@
+for (int c0 = 1; c0 <= 100; c0 += 1)
+  if (c0 >= 61) {
+    for (int c1 = 1; c1 <= 100; c1 += 1)
+      for (int c2 = 1; c2 <= 100; c2 += 1)
+        for (int c3 = 1; c3 <= 100; c3 += 1)
+          for (int c4 = 1; c4 <= 100; c4 += 1)
+            s1(c0, c1, c2, c3, c4);
+  } else
+    for (int c1 = 1; c1 <= 100; c1 += 1)
+      for (int c2 = 1; c2 <= 100; c2 += 1)
+        for (int c3 = 1; c3 <= 100; c3 += 1)
+          for (int c4 = 1; c4 <= 100; c4 += 1) {
+            s1(c0, c1, c2, c3, c4);
+            s0(c0, c1, c2, c3, c4);
+          }
diff --git a/test_inputs/codegen/omega/lift1-4.in b/test_inputs/codegen/omega/lift1-4.in
new file mode 100644 (file)
index 0000000..db7d85c
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{  :  }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 1; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 0 }
diff --git a/test_inputs/codegen/omega/lift1-5.c b/test_inputs/codegen/omega/lift1-5.c
new file mode 100644 (file)
index 0000000..2a24f68
--- /dev/null
@@ -0,0 +1,16 @@
+{
+  for (int c0 = 1; c0 <= 60; c0 += 1)
+    for (int c1 = 1; c1 <= 100; c1 += 1)
+      for (int c2 = 1; c2 <= 100; c2 += 1)
+        for (int c3 = 1; c3 <= 100; c3 += 1)
+          for (int c4 = 1; c4 <= 100; c4 += 1) {
+            s1(c0, c1, c2, c3, c4);
+            s0(c0, c1, c2, c3, c4);
+          }
+  for (int c0 = 61; c0 <= 100; c0 += 1)
+    for (int c1 = 1; c1 <= 100; c1 += 1)
+      for (int c2 = 1; c2 <= 100; c2 += 1)
+        for (int c3 = 1; c3 <= 100; c3 += 1)
+          for (int c4 = 1; c4 <= 100; c4 += 1)
+            s1(c0, c1, c2, c3, c4);
+}
diff --git a/test_inputs/codegen/omega/lift1-5.in b/test_inputs/codegen/omega/lift1-5.in
new file mode 100644 (file)
index 0000000..2f9d578
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{  :  }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 0; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= -1 }
diff --git a/test_inputs/codegen/omega/lift2-0.c b/test_inputs/codegen/omega/lift2-0.c
new file mode 100644 (file)
index 0000000..9658b92
--- /dev/null
@@ -0,0 +1,9 @@
+for (int c0 = 1; c0 <= 100; c0 += 1)
+  for (int c1 = 1; c1 <= 100; c1 += 1)
+    for (int c2 = 1; c2 <= 100; c2 += 1)
+      for (int c3 = 1; c3 <= 100; c3 += 1)
+        for (int c4 = 1; c4 <= 100; c4 += 1) {
+          s1(c0, c1, c2, c3, c4);
+          if (c0 <= 60 && c0 >= 5)
+            s0(c0, c1, c2, c3, c4);
+        }
diff --git a/test_inputs/codegen/omega/lift2-0.in b/test_inputs/codegen/omega/lift2-0.in
new file mode 100644 (file)
index 0000000..5df0444
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 5 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{  :  }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 5; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 4 }
diff --git a/test_inputs/codegen/omega/lift2-1.c b/test_inputs/codegen/omega/lift2-1.c
new file mode 100644 (file)
index 0000000..e799eae
--- /dev/null
@@ -0,0 +1,15 @@
+for (int c0 = 1; c0 <= 100; c0 += 1)
+  for (int c1 = 1; c1 <= 100; c1 += 1)
+    for (int c2 = 1; c2 <= 100; c2 += 1)
+      for (int c3 = 1; c3 <= 100; c3 += 1)
+        if (c0 >= 61) {
+          for (int c4 = 1; c4 <= 100; c4 += 1)
+            s1(c0, c1, c2, c3, c4);
+        } else if (c0 <= 4) {
+          for (int c4 = 1; c4 <= 100; c4 += 1)
+            s1(c0, c1, c2, c3, c4);
+        } else
+          for (int c4 = 1; c4 <= 100; c4 += 1) {
+            s1(c0, c1, c2, c3, c4);
+            s0(c0, c1, c2, c3, c4);
+          }
diff --git a/test_inputs/codegen/omega/lift2-1.in b/test_inputs/codegen/omega/lift2-1.in
new file mode 100644 (file)
index 0000000..7ef2a8d
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 5 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{  :  }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 4; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 3 }
diff --git a/test_inputs/codegen/omega/lift2-2.c b/test_inputs/codegen/omega/lift2-2.c
new file mode 100644 (file)
index 0000000..429733a
--- /dev/null
@@ -0,0 +1,17 @@
+for (int c0 = 1; c0 <= 100; c0 += 1)
+  for (int c1 = 1; c1 <= 100; c1 += 1)
+    for (int c2 = 1; c2 <= 100; c2 += 1)
+      if (c0 >= 61) {
+        for (int c3 = 1; c3 <= 100; c3 += 1)
+          for (int c4 = 1; c4 <= 100; c4 += 1)
+            s1(c0, c1, c2, c3, c4);
+      } else if (c0 <= 4) {
+        for (int c3 = 1; c3 <= 100; c3 += 1)
+          for (int c4 = 1; c4 <= 100; c4 += 1)
+            s1(c0, c1, c2, c3, c4);
+      } else
+        for (int c3 = 1; c3 <= 100; c3 += 1)
+          for (int c4 = 1; c4 <= 100; c4 += 1) {
+            s1(c0, c1, c2, c3, c4);
+            s0(c0, c1, c2, c3, c4);
+          }
diff --git a/test_inputs/codegen/omega/lift2-2.in b/test_inputs/codegen/omega/lift2-2.in
new file mode 100644 (file)
index 0000000..3e9a978
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 5 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{  :  }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 3; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 2 }
diff --git a/test_inputs/codegen/omega/lift2-3.c b/test_inputs/codegen/omega/lift2-3.c
new file mode 100644 (file)
index 0000000..b0818f1
--- /dev/null
@@ -0,0 +1,19 @@
+for (int c0 = 1; c0 <= 100; c0 += 1)
+  for (int c1 = 1; c1 <= 100; c1 += 1)
+    if (c0 >= 61) {
+      for (int c2 = 1; c2 <= 100; c2 += 1)
+        for (int c3 = 1; c3 <= 100; c3 += 1)
+          for (int c4 = 1; c4 <= 100; c4 += 1)
+            s1(c0, c1, c2, c3, c4);
+    } else if (c0 <= 4) {
+      for (int c2 = 1; c2 <= 100; c2 += 1)
+        for (int c3 = 1; c3 <= 100; c3 += 1)
+          for (int c4 = 1; c4 <= 100; c4 += 1)
+            s1(c0, c1, c2, c3, c4);
+    } else
+      for (int c2 = 1; c2 <= 100; c2 += 1)
+        for (int c3 = 1; c3 <= 100; c3 += 1)
+          for (int c4 = 1; c4 <= 100; c4 += 1) {
+            s1(c0, c1, c2, c3, c4);
+            s0(c0, c1, c2, c3, c4);
+          }
diff --git a/test_inputs/codegen/omega/lift2-3.in b/test_inputs/codegen/omega/lift2-3.in
new file mode 100644 (file)
index 0000000..0580f07
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 5 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{  :  }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 2; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 1 }
diff --git a/test_inputs/codegen/omega/lift2-4.c b/test_inputs/codegen/omega/lift2-4.c
new file mode 100644 (file)
index 0000000..5437c17
--- /dev/null
@@ -0,0 +1,21 @@
+for (int c0 = 1; c0 <= 100; c0 += 1)
+  if (c0 >= 61) {
+    for (int c1 = 1; c1 <= 100; c1 += 1)
+      for (int c2 = 1; c2 <= 100; c2 += 1)
+        for (int c3 = 1; c3 <= 100; c3 += 1)
+          for (int c4 = 1; c4 <= 100; c4 += 1)
+            s1(c0, c1, c2, c3, c4);
+  } else if (c0 <= 4) {
+    for (int c1 = 1; c1 <= 100; c1 += 1)
+      for (int c2 = 1; c2 <= 100; c2 += 1)
+        for (int c3 = 1; c3 <= 100; c3 += 1)
+          for (int c4 = 1; c4 <= 100; c4 += 1)
+            s1(c0, c1, c2, c3, c4);
+  } else
+    for (int c1 = 1; c1 <= 100; c1 += 1)
+      for (int c2 = 1; c2 <= 100; c2 += 1)
+        for (int c3 = 1; c3 <= 100; c3 += 1)
+          for (int c4 = 1; c4 <= 100; c4 += 1) {
+            s1(c0, c1, c2, c3, c4);
+            s0(c0, c1, c2, c3, c4);
+          }
diff --git a/test_inputs/codegen/omega/lift2-4.in b/test_inputs/codegen/omega/lift2-4.in
new file mode 100644 (file)
index 0000000..d64462a
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 5 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{  :  }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 1; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 0 }
diff --git a/test_inputs/codegen/omega/lift2-5.c b/test_inputs/codegen/omega/lift2-5.c
new file mode 100644 (file)
index 0000000..16bd6db
--- /dev/null
@@ -0,0 +1,22 @@
+{
+  for (int c0 = 1; c0 <= 4; c0 += 1)
+    for (int c1 = 1; c1 <= 100; c1 += 1)
+      for (int c2 = 1; c2 <= 100; c2 += 1)
+        for (int c3 = 1; c3 <= 100; c3 += 1)
+          for (int c4 = 1; c4 <= 100; c4 += 1)
+            s1(c0, c1, c2, c3, c4);
+  for (int c0 = 5; c0 <= 60; c0 += 1)
+    for (int c1 = 1; c1 <= 100; c1 += 1)
+      for (int c2 = 1; c2 <= 100; c2 += 1)
+        for (int c3 = 1; c3 <= 100; c3 += 1)
+          for (int c4 = 1; c4 <= 100; c4 += 1) {
+            s1(c0, c1, c2, c3, c4);
+            s0(c0, c1, c2, c3, c4);
+          }
+  for (int c0 = 61; c0 <= 100; c0 += 1)
+    for (int c1 = 1; c1 <= 100; c1 += 1)
+      for (int c2 = 1; c2 <= 100; c2 += 1)
+        for (int c3 = 1; c3 <= 100; c3 += 1)
+          for (int c4 = 1; c4 <= 100; c4 += 1)
+            s1(c0, c1, c2, c3, c4);
+}
diff --git a/test_inputs/codegen/omega/lift2-5.in b/test_inputs/codegen/omega/lift2-5.in
new file mode 100644 (file)
index 0000000..37a57be
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 5 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{  :  }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 0; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= -1 }
diff --git a/test_inputs/codegen/omega/lu-0.c b/test_inputs/codegen/omega/lu-0.c
new file mode 100644 (file)
index 0000000..9efe208
--- /dev/null
@@ -0,0 +1,10 @@
+for (int c0 = 1; c0 <= n - 1; c0 += 64)
+  for (int c1 = c0 - 1; c1 <= n; c1 += 64)
+    for (int c2 = c0; c2 <= n; c2 += 1) {
+      for (int c3 = c0; c3 <= min(min(c2 - 1, c0 + 63), c1 + 62); c3 += 1)
+        for (int c4 = max(c1, c3 + 1); c4 <= min(n, c1 + 63); c4 += 1)
+          s1(c3, c4, c2);
+      if (c0 + 63 >= c2)
+        for (int c4 = max(c1, c2 + 1); c4 <= min(c1 + 63, n); c4 += 1)
+          s0(c2, c4);
+    }
diff --git a/test_inputs/codegen/omega/lu-0.in b/test_inputs/codegen/omega/lu-0.in
new file mode 100644 (file)
index 0000000..510d677
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s1[k, i, j] -> [t1, t2, j, k, i] : exists (e0 = [(-1 + t1)/64], e1 = [(t2)/64]: 64e0 = -1 + t1 and 64e1 = t2 and t1 >= -63 + k and t1 <= k and t2 >= -63 + i and t2 <= i and i >= 1 + k and j >= 1 + k and k >= 1 and i <= n and j <= n); s0[k, i] -> [t1, t2, k, k, i] : exists (e0 = [(-1 + t1)/64], e1 = [(t2)/64]: 64e0 = -1 + t1 and 64e1 = t2 and t1 >= -63 + k and t1 <= k and t2 >= -63 + i and t2 <= i and k >= 1 and i >= 1 + k and i <= n) }
+{  :  }
+[n] -> { [t1, t2, i2, i3, i4] -> separate[o0] : o0 >= 5; [t1, t2, i2, i3, i4] -> atomic[o0] : o0 <= 4 }
diff --git a/test_inputs/codegen/omega/lu-1.c b/test_inputs/codegen/omega/lu-1.c
new file mode 100644 (file)
index 0000000..9efe208
--- /dev/null
@@ -0,0 +1,10 @@
+for (int c0 = 1; c0 <= n - 1; c0 += 64)
+  for (int c1 = c0 - 1; c1 <= n; c1 += 64)
+    for (int c2 = c0; c2 <= n; c2 += 1) {
+      for (int c3 = c0; c3 <= min(min(c2 - 1, c0 + 63), c1 + 62); c3 += 1)
+        for (int c4 = max(c1, c3 + 1); c4 <= min(n, c1 + 63); c4 += 1)
+          s1(c3, c4, c2);
+      if (c0 + 63 >= c2)
+        for (int c4 = max(c1, c2 + 1); c4 <= min(c1 + 63, n); c4 += 1)
+          s0(c2, c4);
+    }
diff --git a/test_inputs/codegen/omega/lu-1.in b/test_inputs/codegen/omega/lu-1.in
new file mode 100644 (file)
index 0000000..2e8f7ef
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s1[k, i, j] -> [t1, t2, j, k, i] : exists (e0 = [(-1 + t1)/64], e1 = [(t2)/64]: 64e0 = -1 + t1 and 64e1 = t2 and t1 >= -63 + k and t1 <= k and t2 >= -63 + i and t2 <= i and i >= 1 + k and j >= 1 + k and k >= 1 and i <= n and j <= n); s0[k, i] -> [t1, t2, k, k, i] : exists (e0 = [(-1 + t1)/64], e1 = [(t2)/64]: 64e0 = -1 + t1 and 64e1 = t2 and t1 >= -63 + k and t1 <= k and t2 >= -63 + i and t2 <= i and k >= 1 and i >= 1 + k and i <= n) }
+{  :  }
+[n] -> { [t1, t2, i2, i3, i4] -> separate[o0] : o0 >= 4; [t1, t2, i2, i3, i4] -> atomic[o0] : o0 <= 3 }
diff --git a/test_inputs/codegen/omega/lu-2.c b/test_inputs/codegen/omega/lu-2.c
new file mode 100644 (file)
index 0000000..9efe208
--- /dev/null
@@ -0,0 +1,10 @@
+for (int c0 = 1; c0 <= n - 1; c0 += 64)
+  for (int c1 = c0 - 1; c1 <= n; c1 += 64)
+    for (int c2 = c0; c2 <= n; c2 += 1) {
+      for (int c3 = c0; c3 <= min(min(c2 - 1, c0 + 63), c1 + 62); c3 += 1)
+        for (int c4 = max(c1, c3 + 1); c4 <= min(n, c1 + 63); c4 += 1)
+          s1(c3, c4, c2);
+      if (c0 + 63 >= c2)
+        for (int c4 = max(c1, c2 + 1); c4 <= min(c1 + 63, n); c4 += 1)
+          s0(c2, c4);
+    }
diff --git a/test_inputs/codegen/omega/lu-2.in b/test_inputs/codegen/omega/lu-2.in
new file mode 100644 (file)
index 0000000..ab2ec41
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s1[k, i, j] -> [t1, t2, j, k, i] : exists (e0 = [(-1 + t1)/64], e1 = [(t2)/64]: 64e0 = -1 + t1 and 64e1 = t2 and t1 >= -63 + k and t1 <= k and t2 >= -63 + i and t2 <= i and i >= 1 + k and j >= 1 + k and k >= 1 and i <= n and j <= n); s0[k, i] -> [t1, t2, k, k, i] : exists (e0 = [(-1 + t1)/64], e1 = [(t2)/64]: 64e0 = -1 + t1 and 64e1 = t2 and t1 >= -63 + k and t1 <= k and t2 >= -63 + i and t2 <= i and k >= 1 and i >= 1 + k and i <= n) }
+{  :  }
+[n] -> { [t1, t2, i2, i3, i4] -> separate[o0] : o0 >= 3; [t1, t2, i2, i3, i4] -> atomic[o0] : o0 <= 2 }
diff --git a/test_inputs/codegen/omega/lu-3.c b/test_inputs/codegen/omega/lu-3.c
new file mode 100644 (file)
index 0000000..36affb0
--- /dev/null
@@ -0,0 +1,14 @@
+for (int c0 = 1; c0 <= n - 1; c0 += 64)
+  for (int c1 = c0 - 1; c1 <= n; c1 += 64) {
+    for (int c2 = c0; c2 <= min(c0 + 63, n); c2 += 1) {
+      for (int c3 = c0; c3 <= min(c1 + 62, c2 - 1); c3 += 1)
+        for (int c4 = max(c1, c3 + 1); c4 <= min(n, c1 + 63); c4 += 1)
+          s1(c3, c4, c2);
+      for (int c4 = max(c1, c2 + 1); c4 <= min(c1 + 63, n); c4 += 1)
+        s0(c2, c4);
+    }
+    for (int c2 = c0 + 64; c2 <= n; c2 += 1)
+      for (int c3 = c0; c3 <= min(c0 + 63, c1 + 62); c3 += 1)
+        for (int c4 = max(c1, c3 + 1); c4 <= min(n, c1 + 63); c4 += 1)
+          s1(c3, c4, c2);
+  }
diff --git a/test_inputs/codegen/omega/lu-3.in b/test_inputs/codegen/omega/lu-3.in
new file mode 100644 (file)
index 0000000..817db46
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s1[k, i, j] -> [t1, t2, j, k, i] : exists (e0 = [(-1 + t1)/64], e1 = [(t2)/64]: 64e0 = -1 + t1 and 64e1 = t2 and t1 >= -63 + k and t1 <= k and t2 >= -63 + i and t2 <= i and i >= 1 + k and j >= 1 + k and k >= 1 and i <= n and j <= n); s0[k, i] -> [t1, t2, k, k, i] : exists (e0 = [(-1 + t1)/64], e1 = [(t2)/64]: 64e0 = -1 + t1 and 64e1 = t2 and t1 >= -63 + k and t1 <= k and t2 >= -63 + i and t2 <= i and k >= 1 and i >= 1 + k and i <= n) }
+{  :  }
+[n] -> { [t1, t2, i2, i3, i4] -> separate[o0] : o0 >= 2; [t1, t2, i2, i3, i4] -> atomic[o0] : o0 <= 1 }
diff --git a/test_inputs/codegen/omega/lu_ijk-0.c b/test_inputs/codegen/omega/lu_ijk-0.c
new file mode 100644 (file)
index 0000000..4c6ffc5
--- /dev/null
@@ -0,0 +1,7 @@
+for (int c0 = 1; c0 <= n; c0 += 1)
+  for (int c1 = 2; c1 <= n; c1 += 1) {
+    for (int c3 = 1; c3 <= min(c0 - 1, c1 - 1); c3 += 1)
+      s1(c3, c1, c0);
+    if (c1 >= c0 + 1)
+      s0(c0, c1);
+  }
diff --git a/test_inputs/codegen/omega/lu_ijk-0.in b/test_inputs/codegen/omega/lu_ijk-0.in
new file mode 100644 (file)
index 0000000..5aae58c
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[k, j] -> [k, j, 1, 0] : k >= 1 and j >= 1 + k and j <= n; s1[k, j, i] -> [i, j, 0, k] : j >= 1 + k and i >= 1 + k and k >= 1 and j <= n and i <= n }
+{  :  }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2; [i0, i1, i2, i3] -> separate[o0] : o0 >= 3 }
diff --git a/test_inputs/codegen/omega/lu_ijk-1.c b/test_inputs/codegen/omega/lu_ijk-1.c
new file mode 100644 (file)
index 0000000..4c6ffc5
--- /dev/null
@@ -0,0 +1,7 @@
+for (int c0 = 1; c0 <= n; c0 += 1)
+  for (int c1 = 2; c1 <= n; c1 += 1) {
+    for (int c3 = 1; c3 <= min(c0 - 1, c1 - 1); c3 += 1)
+      s1(c3, c1, c0);
+    if (c1 >= c0 + 1)
+      s0(c0, c1);
+  }
diff --git a/test_inputs/codegen/omega/lu_ijk-1.in b/test_inputs/codegen/omega/lu_ijk-1.in
new file mode 100644 (file)
index 0000000..06a860c
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[k, j] -> [k, j, 1, 0] : k >= 1 and j >= 1 + k and j <= n; s1[k, j, i] -> [i, j, 0, k] : j >= 1 + k and i >= 1 + k and k >= 1 and j <= n and i <= n }
+{  :  }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 1; [i0, i1, i2, i3] -> separate[o0] : o0 >= 2 }
diff --git a/test_inputs/codegen/omega/lu_ijk-2.c b/test_inputs/codegen/omega/lu_ijk-2.c
new file mode 100644 (file)
index 0000000..b7e3600
--- /dev/null
@@ -0,0 +1,11 @@
+if (n >= 2)
+  for (int c0 = 1; c0 <= n; c0 += 1) {
+    for (int c1 = 2; c1 <= c0; c1 += 1)
+      for (int c3 = 1; c3 <= c1 - 1; c3 += 1)
+        s1(c3, c1, c0);
+    for (int c1 = c0 + 1; c1 <= n; c1 += 1) {
+      for (int c3 = 1; c3 <= c0 - 1; c3 += 1)
+        s1(c3, c1, c0);
+      s0(c0, c1);
+    }
+  }
diff --git a/test_inputs/codegen/omega/lu_ijk-2.in b/test_inputs/codegen/omega/lu_ijk-2.in
new file mode 100644 (file)
index 0000000..6ad8a44
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[k, j] -> [k, j, 1, 0] : k >= 1 and j >= 1 + k and j <= n; s1[k, j, i] -> [i, j, 0, k] : j >= 1 + k and i >= 1 + k and k >= 1 and j <= n and i <= n }
+{  :  }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 0; [i0, i1, i2, i3] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/lu_spmd-0.c b/test_inputs/codegen/omega/lu_spmd-0.c
new file mode 100644 (file)
index 0000000..05e5699
--- /dev/null
@@ -0,0 +1,13 @@
+if (ub >= lb)
+  for (int c0 = 1; c0 <= ub; c0 += 1)
+    for (int c1 = c0; c1 <= n; c1 += 1) {
+      if (lb >= c0 + 1) {
+        s3(c0, c1, lb, c0, c1);
+      } else if (c1 >= c0 + 1) {
+        s0(c0, c1);
+        if (n >= ub + 1)
+          s2(c0, c1);
+      }
+      for (int c3 = max(c0, lb); c3 <= ub; c3 += 1)
+        s1(c0, c1, c3);
+    }
diff --git a/test_inputs/codegen/omega/lu_spmd-0.in b/test_inputs/codegen/omega/lu_spmd-0.in
new file mode 100644 (file)
index 0000000..0dd0953
--- /dev/null
@@ -0,0 +1,3 @@
+[n, lb, ub] -> { s1[k, i, j] -> [k, i, 1, j, 0, 0, 0, 0] : k >= 1 and j >= k and j <= n and j <= ub and i >= k and i <= n and j >= lb; s3[k, i, lb, k, i] -> [k, i, 1, lb, -1, k, i, 0] : k >= 1 and k <= -1 + lb and lb <= n and ub >= lb and i >= k and i <= n; s0[k, i] -> [k, i, 0, 0, 0, 0, 0, 0] : k >= 1 and k >= lb and i >= 1 + k and i <= n and k <= ub; s2[k, i] -> [k, i, 0, 0, 1, 0, 0, 0] : k >= 1 and k >= lb and k <= ub and ub <= -1 + n and i >= 1 + k and i <= n }
+[lb, n, ub] -> {  : ub <= n and lb >= 1 }
+[n, lb, ub] -> { [i0, i1, i2, i3, i4, i5, i6, i7] -> atomic[o0] : o0 <= 7; [i0, i1, i2, i3, i4, i5, i6, i7] -> separate[o0] : o0 >= 8 }
diff --git a/test_inputs/codegen/omega/lu_spmd-1.c b/test_inputs/codegen/omega/lu_spmd-1.c
new file mode 100644 (file)
index 0000000..05e5699
--- /dev/null
@@ -0,0 +1,13 @@
+if (ub >= lb)
+  for (int c0 = 1; c0 <= ub; c0 += 1)
+    for (int c1 = c0; c1 <= n; c1 += 1) {
+      if (lb >= c0 + 1) {
+        s3(c0, c1, lb, c0, c1);
+      } else if (c1 >= c0 + 1) {
+        s0(c0, c1);
+        if (n >= ub + 1)
+          s2(c0, c1);
+      }
+      for (int c3 = max(c0, lb); c3 <= ub; c3 += 1)
+        s1(c0, c1, c3);
+    }
diff --git a/test_inputs/codegen/omega/lu_spmd-1.in b/test_inputs/codegen/omega/lu_spmd-1.in
new file mode 100644 (file)
index 0000000..5d628be
--- /dev/null
@@ -0,0 +1,3 @@
+[n, lb, ub] -> { s1[k, i, j] -> [k, i, 1, j, 0, 0, 0, 0] : k >= 1 and j >= k and j <= n and j <= ub and i >= k and i <= n and j >= lb; s3[k, i, lb, k, i] -> [k, i, 1, lb, -1, k, i, 0] : k >= 1 and k <= -1 + lb and lb <= n and ub >= lb and i >= k and i <= n; s0[k, i] -> [k, i, 0, 0, 0, 0, 0, 0] : k >= 1 and k >= lb and i >= 1 + k and i <= n and k <= ub; s2[k, i] -> [k, i, 0, 0, 1, 0, 0, 0] : k >= 1 and k >= lb and k <= ub and ub <= -1 + n and i >= 1 + k and i <= n }
+[lb, n, ub] -> {  : ub <= n and lb >= 1 }
+[n, lb, ub] -> { [i0, i1, i2, i3, i4, i5, i6, i7] -> atomic[o0] : o0 <= 6; [i0, i1, i2, i3, i4, i5, i6, i7] -> separate[o0] : o0 >= 7 }
diff --git a/test_inputs/codegen/omega/m1-0.c b/test_inputs/codegen/omega/m1-0.c
new file mode 100644 (file)
index 0000000..bb14935
--- /dev/null
@@ -0,0 +1,6 @@
+for (int c0 = 1; c0 <= 9; c0 += 1)
+  for (int c1 = 1; c1 <= 9; c1 += 1) {
+    s0(c0, c1);
+    if (c0 == 5)
+      s1(5, c1);
+  }
diff --git a/test_inputs/codegen/omega/m1-0.in b/test_inputs/codegen/omega/m1-0.in
new file mode 100644 (file)
index 0000000..ca2b8a9
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [i, j, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[5, j] -> [5, j, 1] : j >= 1 and j <= 9 }
+{  :  }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 2; [i0, i1, i2] -> atomic[o0] : o0 <= 1 }
diff --git a/test_inputs/codegen/omega/m1-1.c b/test_inputs/codegen/omega/m1-1.c
new file mode 100644 (file)
index 0000000..8f57f56
--- /dev/null
@@ -0,0 +1,12 @@
+for (int c0 = 1; c0 <= 9; c0 += 1)
+  if (c0 >= 6) {
+    for (int c1 = 1; c1 <= 9; c1 += 1)
+      s0(c0, c1);
+  } else if (c0 <= 4) {
+    for (int c1 = 1; c1 <= 9; c1 += 1)
+      s0(c0, c1);
+  } else
+    for (int c1 = 1; c1 <= 9; c1 += 1) {
+      s0(5, c1);
+      s1(5, c1);
+    }
diff --git a/test_inputs/codegen/omega/m1-1.in b/test_inputs/codegen/omega/m1-1.in
new file mode 100644 (file)
index 0000000..08dbf45
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [i, j, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[5, j] -> [5, j, 1] : j >= 1 and j <= 9 }
+{  :  }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 1; [i0, i1, i2] -> atomic[o0] : o0 <= 0 }
diff --git a/test_inputs/codegen/omega/m10-0.c b/test_inputs/codegen/omega/m10-0.c
new file mode 100644 (file)
index 0000000..2b51c7b
--- /dev/null
@@ -0,0 +1,7 @@
+for (int c0 = 1; c0 <= 18; c0 += 1)
+  for (int c1 = 1; c1 <= 9; c1 += 1) {
+    if (c0 % 2 == 0)
+      s0(c1, c0 / 2);
+    if (c0 <= 9)
+      s1(c1, c0);
+  }
diff --git a/test_inputs/codegen/omega/m10-0.in b/test_inputs/codegen/omega/m10-0.in
new file mode 100644 (file)
index 0000000..3046811
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [4j, i, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[i, j] -> [2j, i, 1] : i >= 1 and i <= 9 and j >= 1 and j <= 9 }
+{  :  }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 2; [i0, i1, i2] -> atomic[o0] : o0 <= 1 }
diff --git a/test_inputs/codegen/omega/m10-1.c b/test_inputs/codegen/omega/m10-1.c
new file mode 100644 (file)
index 0000000..42478d1
--- /dev/null
@@ -0,0 +1,13 @@
+for (int c0 = 1; c0 <= 18; c0 += 1)
+  if (c0 >= 2 && c0 <= 9) {
+    for (int c1 = 1; c1 <= 9; c1 += 1) {
+      if (c0 % 2 == 0)
+        s0(c1, c0 / 2);
+      s1(c1, c0);
+    }
+  } else if (c0 == 1) {
+    for (int c1 = 1; c1 <= 9; c1 += 1)
+      s1(c1, 1);
+  } else if (c0 % 2 == 0)
+    for (int c1 = 1; c1 <= 9; c1 += 1)
+      s0(c1, c0 / 2);
diff --git a/test_inputs/codegen/omega/m10-1.in b/test_inputs/codegen/omega/m10-1.in
new file mode 100644 (file)
index 0000000..81dfc3b
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [4j, i, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[i, j] -> [2j, i, 1] : i >= 1 and i <= 9 and j >= 1 and j <= 9 }
+{  :  }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 1; [i0, i1, i2] -> atomic[o0] : o0 <= 0 }
diff --git a/test_inputs/codegen/omega/m11-0.c b/test_inputs/codegen/omega/m11-0.c
new file mode 100644 (file)
index 0000000..e0abe48
--- /dev/null
@@ -0,0 +1,6 @@
+for (int c0 = 1; c0 <= min(4, floord(2 * m - 1, 17) + 1); c0 += 1)
+  for (int c1 = 1; c1 <= 2; c1 += 1)
+    for (int c2 = 0; c2 <= min(-c1 + c1 / 2 + 3, -c0 - c1 + (2 * m + 3 * c0 + 10 * c1 + 6) / 20 + 1); c2 += 1)
+      for (int c3 = 9 * c0 - c0 / 2 - 8; c3 <= min(min(m - 5 * c1 - 10 * c2 + 5, 8 * c0 + c0 / 2), 30); c3 += 1)
+        for (int c4 = 5 * c1 + 10 * c2 - 4; c4 <= min(m - c3 + 1, 5 * c1 + 10 * c2); c4 += 1)
+          s0(c0, c1, c2, c3, c4, -9 * c0 + c3 + c0 / 2 + 9, -5 * c1 - 5 * c2 + c4 + 5);
diff --git a/test_inputs/codegen/omega/m11-0.in b/test_inputs/codegen/omega/m11-0.in
new file mode 100644 (file)
index 0000000..d85fcf2
--- /dev/null
@@ -0,0 +1,3 @@
+[m] -> { s0[In_1, In_2, In_3, In_4, In_5, In_6, 5 - 5In_2 - 5In_3 + In_5] -> [In_1, In_2, In_3, In_4, In_5, In_6, 5 - 5In_2 - 5In_3 + In_5] : In_2 >= 1 and 2In_3 >= 1 - In_2 and In_2 <= 2 and 2In_3 <= 6 - In_2 and In_4 <= 30 and In_1 >= 1 and 2In_6 <= 18 - 17In_1 + 2In_4 and 2In_6 >= 17 - 17In_1 + 2In_4 and In_5 <= 5In_2 + 10In_3 and In_5 >= -4 + 5In_2 + 10In_3 and 2In_4 <= 17In_1 and 2In_4 >= -16 + 17In_1 and In_5 <= 1 + m - In_4 }
+{  :  }
+[m] -> { [i0, i1, i2, i3, i4, i5, i6] -> atomic[o0] : o0 <= 5; [i0, i1, i2, i3, i4, i5, i6] -> separate[o0] : o0 >= 6 }
diff --git a/test_inputs/codegen/omega/m12-0.c b/test_inputs/codegen/omega/m12-0.c
new file mode 100644 (file)
index 0000000..2dc6ab1
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c1 = 1; c1 <= n; c1 += 1)
+  for (int c2 = 1; c2 <= m; c2 += 1)
+    s0(1, c1, c2, 0);
diff --git a/test_inputs/codegen/omega/m12-0.in b/test_inputs/codegen/omega/m12-0.in
new file mode 100644 (file)
index 0000000..0c988ab
--- /dev/null
@@ -0,0 +1,3 @@
+[m, n] -> { s0[1, In_2, In_3, 0] -> [1, In_2, In_3, 0] : In_3 >= 1 and In_3 <= m and In_2 >= 1 and In_2 <= n }
+{  :  }
+[m, n] -> { [i0, i1, i2, i3] -> separate[o0] : o0 >= 3; [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2 }
diff --git a/test_inputs/codegen/omega/m12-1.c b/test_inputs/codegen/omega/m12-1.c
new file mode 100644 (file)
index 0000000..555fbfb
--- /dev/null
@@ -0,0 +1,25 @@
+{
+  for (int c1 = 1; c1 <= n; c1 += 1)
+    for (int c2 = 1; c2 <= m; c2 += 1) {
+      s1(1, c1, c2, 0);
+      s0(1, c1, c2, 0);
+    }
+  for (int c1 = 1; c1 <= n; c1 += 1) {
+    s2(2, c1, 0, 0);
+    s3(2, c1, 0, 0);
+  }
+  for (int c1 = 1; c1 <= m; c1 += 1) {
+    for (int c3 = 1; c3 <= n; c3 += 1) {
+      s5(3, c1, 1, c3);
+      s4(3, c1, 1, c3);
+    }
+    for (int c3 = 1; c3 <= n; c3 += 1) {
+      s6(3, c1, 2, c3);
+      s7(3, c1, 2, c3);
+    }
+  }
+  for (int c1 = 1; c1 <= m; c1 += 1) {
+    s9(4, c1, 0, 0);
+    s8(4, c1, 0, 0);
+  }
+}
diff --git a/test_inputs/codegen/omega/m12-1.in b/test_inputs/codegen/omega/m12-1.in
new file mode 100644 (file)
index 0000000..355075f
--- /dev/null
@@ -0,0 +1,3 @@
+[m, n] -> { s1[1, In_2, In_3, 0] -> [1, In_2, In_3, 0] : In_3 >= 1 and In_3 <= m and In_2 >= 1 and In_2 <= n; s2[2, In_2, 0, 0] -> [2, In_2, 0, 0] : In_2 >= 1 and In_2 <= n; s3[2, In_2, 0, 0] -> [2, In_2, 0, 0] : In_2 >= 1 and In_2 <= n; s8[4, In_2, 0, 0] -> [4, In_2, 0, 0] : In_2 >= 1 and In_2 <= m; s0[1, In_2, In_3, 0] -> [1, In_2, In_3, 0] : In_3 >= 1 and In_3 <= m and In_2 >= 1 and In_2 <= n; s7[3, In_2, 2, In_4] -> [3, In_2, 2, In_4] : In_4 >= 1 and In_4 <= n and In_2 >= 1 and In_2 <= m; s4[3, In_2, 1, In_4] -> [3, In_2, 1, In_4] : In_4 >= 1 and In_4 <= n and In_2 >= 1 and In_2 <= m; s6[3, In_2, 2, In_4] -> [3, In_2, 2, In_4] : In_4 >= 1 and In_4 <= n and In_2 >= 1 and In_2 <= m; s9[4, In_2, 0, 0] -> [4, In_2, 0, 0] : In_2 >= 1 and In_2 <= m; s5[3, In_2, 1, In_4] -> [3, In_2, 1, In_4] : In_4 >= 1 and In_4 <= n and In_2 >= 1 and In_2 <= m }
+{  :  }
+[m, n] -> { [i0, i1, i2, i3] -> separate[o0] : o0 >= 3; [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2 }
diff --git a/test_inputs/codegen/omega/m2-0.c b/test_inputs/codegen/omega/m2-0.c
new file mode 100644 (file)
index 0000000..97fcb7b
--- /dev/null
@@ -0,0 +1,10 @@
+for (int c0 = 2; c0 <= 9; c0 += 1)
+  if (c0 >= 5) {
+    s1(c0, 1);
+    for (int c1 = 2; c1 <= 9; c1 += 1) {
+      s1(c0, c1);
+      s0(c0, c1);
+    }
+  } else
+    for (int c1 = 2; c1 <= 9; c1 += 1)
+      s0(c0, c1);
diff --git a/test_inputs/codegen/omega/m2-0.in b/test_inputs/codegen/omega/m2-0.in
new file mode 100644 (file)
index 0000000..ae7780e
--- /dev/null
@@ -0,0 +1,3 @@
+{ s1[In_1, In_2] -> [In_1, In_2] : In_1 >= 5 and In_1 <= 9 and In_2 >= 1 and In_2 <= 9; s0[In_1, In_2] -> [In_1, In_2] : In_1 >= 2 and In_1 <= 9 and In_2 >= 2 and In_2 <= 9 }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/m2-1.c b/test_inputs/codegen/omega/m2-1.c
new file mode 100644 (file)
index 0000000..09255e0
--- /dev/null
@@ -0,0 +1,12 @@
+{
+  for (int c0 = 2; c0 <= 4; c0 += 1)
+    for (int c1 = 2; c1 <= 9; c1 += 1)
+      s0(c0, c1);
+  for (int c0 = 5; c0 <= 9; c0 += 1) {
+    s1(c0, 1);
+    for (int c1 = 2; c1 <= 9; c1 += 1) {
+      s1(c0, c1);
+      s0(c0, c1);
+    }
+  }
+}
diff --git a/test_inputs/codegen/omega/m2-1.in b/test_inputs/codegen/omega/m2-1.in
new file mode 100644 (file)
index 0000000..32302bb
--- /dev/null
@@ -0,0 +1,3 @@
+{ s1[In_1, In_2] -> [In_1, In_2] : In_1 >= 5 and In_1 <= 9 and In_2 >= 1 and In_2 <= 9; s0[In_1, In_2] -> [In_1, In_2] : In_1 >= 2 and In_1 <= 9 and In_2 >= 2 and In_2 <= 9 }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= -1; [i0, i1] -> separate[o0] : o0 >= 0 }
diff --git a/test_inputs/codegen/omega/m3-0.c b/test_inputs/codegen/omega/m3-0.c
new file mode 100644 (file)
index 0000000..21a6f8e
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = -9; c0 <= 9; c0 += 1)
+  for (int c1 = max(-c0 + 1, 1); c1 <= min(-c0 + 10, 10); c1 += 1)
+    s0(c0, c1);
diff --git a/test_inputs/codegen/omega/m3-0.in b/test_inputs/codegen/omega/m3-0.in
new file mode 100644 (file)
index 0000000..82e1093
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, In_2] : In_2 >= 1 - In_1 and In_2 >= 1 and In_2 <= 10 - In_1 and In_2 <= 10 }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/m4-0.c b/test_inputs/codegen/omega/m4-0.c
new file mode 100644 (file)
index 0000000..a528073
--- /dev/null
@@ -0,0 +1,5 @@
+for (int c0 = 1; c0 <= 9; c0 += 1)
+  for (int c1 = 1; c1 <= 9; c1 += 1) {
+    s0(c1, c0);
+    s1(c1, c0);
+  }
diff --git a/test_inputs/codegen/omega/m4-0.in b/test_inputs/codegen/omega/m4-0.in
new file mode 100644 (file)
index 0000000..b7912a3
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [j, i, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[i, j] -> [j, i, 1] : i >= 1 and i <= 9 and j >= 1 and j <= 9 }
+{  :  }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 2; [i0, i1, i2] -> atomic[o0] : o0 <= 1 }
diff --git a/test_inputs/codegen/omega/m4-1.c b/test_inputs/codegen/omega/m4-1.c
new file mode 100644 (file)
index 0000000..a528073
--- /dev/null
@@ -0,0 +1,5 @@
+for (int c0 = 1; c0 <= 9; c0 += 1)
+  for (int c1 = 1; c1 <= 9; c1 += 1) {
+    s0(c1, c0);
+    s1(c1, c0);
+  }
diff --git a/test_inputs/codegen/omega/m4-1.in b/test_inputs/codegen/omega/m4-1.in
new file mode 100644 (file)
index 0000000..c9e17d9
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [j, i, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[i, j] -> [j, i, 1] : i >= 1 and i <= 9 and j >= 1 and j <= 9 }
+{  :  }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 1; [i0, i1, i2] -> atomic[o0] : o0 <= 0 }
diff --git a/test_inputs/codegen/omega/m7-0.c b/test_inputs/codegen/omega/m7-0.c
new file mode 100644 (file)
index 0000000..d9f93d9
--- /dev/null
@@ -0,0 +1,6 @@
+for (int c0 = 1; c0 <= 9; c0 += 1)
+  for (int c1 = 1; c1 <= 9; c1 += 1) {
+    s0(c1, c0);
+    if (c0 % 2 == 0)
+      s1(c1, c0);
+  }
diff --git a/test_inputs/codegen/omega/m7-0.in b/test_inputs/codegen/omega/m7-0.in
new file mode 100644 (file)
index 0000000..45a1850
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [j, i, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[i, j] -> [j, i, 1] : exists (e0 = [(j)/2]: 2e0 = j and i >= 1 and i <= 9 and j >= 2 and j <= 8) }
+{  :  }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 2; [i0, i1, i2] -> atomic[o0] : o0 <= 1 }
diff --git a/test_inputs/codegen/omega/m7-1.c b/test_inputs/codegen/omega/m7-1.c
new file mode 100644 (file)
index 0000000..690dc50
--- /dev/null
@@ -0,0 +1,9 @@
+for (int c0 = 1; c0 <= 9; c0 += 1)
+  if (c0 % 2 == 0) {
+    for (int c1 = 1; c1 <= 9; c1 += 1) {
+      s0(c1, c0);
+      s1(c1, c0);
+    }
+  } else
+    for (int c1 = 1; c1 <= 9; c1 += 1)
+      s0(c1, c0);
diff --git a/test_inputs/codegen/omega/m7-1.in b/test_inputs/codegen/omega/m7-1.in
new file mode 100644 (file)
index 0000000..f4b6f6f
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [j, i, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[i, j] -> [j, i, 1] : exists (e0 = [(j)/2]: 2e0 = j and i >= 1 and i <= 9 and j >= 2 and j <= 8) }
+{  :  }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 1; [i0, i1, i2] -> atomic[o0] : o0 <= 0 }
diff --git a/test_inputs/codegen/omega/m8-0.c b/test_inputs/codegen/omega/m8-0.c
new file mode 100644 (file)
index 0000000..9aaed9e
--- /dev/null
@@ -0,0 +1,6 @@
+for (int c0 = 2; c0 <= 8; c0 += 2)
+  for (int c1 = 1; c1 <= 9; c1 += 1) {
+    if (c0 % 4 == 0)
+      s0(c1, c0);
+    s1(c1, c0);
+  }
diff --git a/test_inputs/codegen/omega/m8-0.in b/test_inputs/codegen/omega/m8-0.in
new file mode 100644 (file)
index 0000000..e9a0e39
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [j, i, 0] : exists (e0 = [(j)/4]: 4e0 = j and i >= 1 and i <= 9 and j >= 4 and j <= 8); s1[i, j] -> [j, i, 1] : exists (e0 = [(j)/2]: 2e0 = j and i >= 1 and i <= 9 and j >= 2 and j <= 8) }
+{  :  }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 2; [i0, i1, i2] -> atomic[o0] : o0 <= 1 }
diff --git a/test_inputs/codegen/omega/m8-1.c b/test_inputs/codegen/omega/m8-1.c
new file mode 100644 (file)
index 0000000..a36f516
--- /dev/null
@@ -0,0 +1,9 @@
+for (int c0 = 2; c0 <= 8; c0 += 2)
+  if (c0 % 4 == 0) {
+    for (int c1 = 1; c1 <= 9; c1 += 1) {
+      s0(c1, c0);
+      s1(c1, c0);
+    }
+  } else
+    for (int c1 = 1; c1 <= 9; c1 += 1)
+      s1(c1, c0);
diff --git a/test_inputs/codegen/omega/m8-1.in b/test_inputs/codegen/omega/m8-1.in
new file mode 100644 (file)
index 0000000..80e57e4
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [j, i, 0] : exists (e0 = [(j)/4]: 4e0 = j and i >= 1 and i <= 9 and j >= 4 and j <= 8); s1[i, j] -> [j, i, 1] : exists (e0 = [(j)/2]: 2e0 = j and i >= 1 and i <= 9 and j >= 2 and j <= 8) }
+{  :  }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 1; [i0, i1, i2] -> atomic[o0] : o0 <= 0 }
diff --git a/test_inputs/codegen/omega/m9-0.c b/test_inputs/codegen/omega/m9-0.c
new file mode 100644 (file)
index 0000000..a528073
--- /dev/null
@@ -0,0 +1,5 @@
+for (int c0 = 1; c0 <= 9; c0 += 1)
+  for (int c1 = 1; c1 <= 9; c1 += 1) {
+    s0(c1, c0);
+    s1(c1, c0);
+  }
diff --git a/test_inputs/codegen/omega/m9-0.in b/test_inputs/codegen/omega/m9-0.in
new file mode 100644 (file)
index 0000000..fc38bf2
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [2j, i, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[i, j] -> [2j, i, 1] : i >= 1 and i <= 9 and j >= 1 and j <= 9 }
+{  :  }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 2; [i0, i1, i2] -> atomic[o0] : o0 <= 1 }
diff --git a/test_inputs/codegen/omega/m9-1.c b/test_inputs/codegen/omega/m9-1.c
new file mode 100644 (file)
index 0000000..a528073
--- /dev/null
@@ -0,0 +1,5 @@
+for (int c0 = 1; c0 <= 9; c0 += 1)
+  for (int c1 = 1; c1 <= 9; c1 += 1) {
+    s0(c1, c0);
+    s1(c1, c0);
+  }
diff --git a/test_inputs/codegen/omega/m9-1.in b/test_inputs/codegen/omega/m9-1.in
new file mode 100644 (file)
index 0000000..398e326
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [2j, i, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[i, j] -> [2j, i, 1] : i >= 1 and i <= 9 and j >= 1 and j <= 9 }
+{  :  }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 1; [i0, i1, i2] -> atomic[o0] : o0 <= 0 }
diff --git a/test_inputs/codegen/omega/olda-0.c b/test_inputs/codegen/omega/olda-0.c
new file mode 100644 (file)
index 0000000..b05f991
--- /dev/null
@@ -0,0 +1,8 @@
+for (int c0 = 1; c0 <= morb; c0 += 1)
+  for (int c1 = 1; c1 <= np; c1 += 1)
+    for (int c2 = 1; c2 <= np; c2 += 1) {
+      if (c2 >= c1)
+        s0(c2, c1, c0);
+      if (c1 >= c2)
+        s1(c1, c2, c0);
+    }
diff --git a/test_inputs/codegen/omega/olda-0.in b/test_inputs/codegen/omega/olda-0.in
new file mode 100644 (file)
index 0000000..88f86f5
--- /dev/null
@@ -0,0 +1,3 @@
+[np, morb] -> { s0[mp, mq, mi] -> [mi, mq, mp, 0] : mq >= 1 and mq <= mp and mp <= np and mi >= 1 and mi <= morb; s1[mp, mq, mi] -> [mi, mp, mq, 1] : mq >= 1 and mq <= mp and mp <= np and mi >= 1 and mi <= morb }
+{  :  }
+[np, morb] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2; [i0, i1, i2, i3] -> separate[o0] : o0 >= 3 }
diff --git a/test_inputs/codegen/omega/olda-1.c b/test_inputs/codegen/omega/olda-1.c
new file mode 100644 (file)
index 0000000..ab642fa
--- /dev/null
@@ -0,0 +1,9 @@
+for (int c0 = 1; c0 <= morb; c0 += 1)
+  for (int c1 = 1; c1 <= np; c1 += 1) {
+    for (int c2 = 1; c2 <= c1 - 1; c2 += 1)
+      s1(c1, c2, c0);
+    s0(c1, c1, c0);
+    s1(c1, c1, c0);
+    for (int c2 = c1 + 1; c2 <= np; c2 += 1)
+      s0(c2, c1, c0);
+  }
diff --git a/test_inputs/codegen/omega/olda-1.in b/test_inputs/codegen/omega/olda-1.in
new file mode 100644 (file)
index 0000000..a3a387f
--- /dev/null
@@ -0,0 +1,3 @@
+[np, morb] -> { s0[mp, mq, mi] -> [mi, mq, mp, 0] : mq >= 1 and mq <= mp and mp <= np and mi >= 1 and mi <= morb; s1[mp, mq, mi] -> [mi, mp, mq, 1] : mq >= 1 and mq <= mp and mp <= np and mi >= 1 and mi <= morb }
+{  :  }
+[np, morb] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 1; [i0, i1, i2, i3] -> separate[o0] : o0 >= 2 }
diff --git a/test_inputs/codegen/omega/p.delft-0.c b/test_inputs/codegen/omega/p.delft-0.c
new file mode 100644 (file)
index 0000000..2756b45
--- /dev/null
@@ -0,0 +1,4 @@
+if (P1 == P2 && P2 <= 3 && P2 >= 0)
+  for (int c0 = 0; c0 <= min(2, -P2 + 4); c0 += 1)
+    for (int c2 = -P2 - c0 - 3 * floord(-P2 - c0, 3); c2 <= 3; c2 += 3)
+      s0(c0, c0, c2, c2);
diff --git a/test_inputs/codegen/omega/p.delft-0.in b/test_inputs/codegen/omega/p.delft-0.in
new file mode 100644 (file)
index 0000000..5b277a1
--- /dev/null
@@ -0,0 +1,3 @@
+[P2, P1] -> { s0[In_1, In_1, In_3, In_3] -> [In_1, In_1, In_3, In_3] : exists (e0 = [(-2P2 - 2In_1 + In_3)/3]: P1 = P2 and 3e0 = -2P2 - 2In_1 + In_3 and P2 >= 0 and P2 <= 3 and In_1 <= 4 - P2 and In_1 >= 0 and In_1 <= 2 and In_3 >= 0 and In_3 <= 3) }
+{  :  }
+[P2, P1] -> { [i0, i1, i2, i3] -> separate[o0] : o0 >= 3; [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2 }
diff --git a/test_inputs/codegen/omega/p.delft2-0.c b/test_inputs/codegen/omega/p.delft2-0.c
new file mode 100644 (file)
index 0000000..3b0a246
--- /dev/null
@@ -0,0 +1,11 @@
+if ((2 * floord(P2, 2) == P2 && 2 * floord(P1, 2) == P1 && P2 >= 0 && P2 <= 3 && P1 >= 0 && P1 <= 3) || (2 * floord(P2, 2) == P2 && 2 * floord(P1 - 1, 2) + 1 == P1 && P2 >= 0 && P2 <= 3 && P1 >= 0 && P1 <= 3) || (2 * floord(P2 - 1, 2) + 1 == P2 && 2 * floord(P1, 2) == P1 && P2 >= 0 && P2 <= 3 && P1 >= 0 && P1 <= 3) || (2 * floord(P2 - 1, 2) + 1 == P2 && 2 * floord(P1 - 1, 2) + 1 == P1 && P2 >= 0 && P2 <= 3 && P1 >= 0 && P1 <= 3))
+  for (int c0 = P1 - 1; c0 <= 3; c0 += 1)
+    if ((2 * floord(c0, 2) == c0 && P2 % 2 == 0 && 2 * floord(P1 - 1, 2) + 1 == P1) || (2 * floord(c0, 2) == c0 && 2 * floord(P2 - 1, 2) + 1 == P2 && 2 * floord(P1 - 1, 2) + 1 == P1) || (2 * floord(c0 - 1, 2) + 1 == c0 && P2 % 2 == 0 && P1 % 2 == 0) || (2 * floord(c0 - 1, 2) + 1 == c0 && 2 * floord(P2 - 1, 2) + 1 == P2 && P1 % 2 == 0))
+      for (int c2 = 0; c2 <= floord(-P1 - 1, 4) + 8; c2 += 1)
+        if ((2 * floord(P2 - 1, 4) + 2 * (P2 / 4) + 2 == P2 && 2 * floord(P2 - 1, 2) + 2 == P2 && P2 <= 6 && 18 * floord(9 * P1 + 17 * c0 + 14 * c2 + 3, 18) + 1 >= 9 * P1 + 17 * c0 + 14 * c2) || (2 * floord(P2 - 1, 2) + 1 == P2 && P2 + 1 >= 0 && 18 * floord(9 * P1 + 17 * c0 + 14 * c2 + 3, 18) + 1 >= 9 * P1 + 17 * c0 + 14 * c2 && 4 * floord(P2 - 1, 4) + 3 >= P2))
+          for (int c3 = 0; c3 <= floord(-P2 - 1, 4) + 8; c3 += 1)
+            if ((5 * P2 + 2 * c3) % 9 <= 3 && 9 * ((4 * P2 + 3) / 9 / 2) + 7 >= 2 * P2 && 2 * P2 + 1 >= 9 * ((4 * P2 + 3) / 9 / 2))
+              if (c0 + 1 == P1 && (5 * P1 + 2 * c2) % 9 <= 2 && P1 >= 1) {
+                s0(P1 - 1, P2, c2, c3, ((5 * P1 + 2 * c2) % 9) + 1, -4 * P2 + 2 * c3 + 9 * floord(4 * P2 - 2 * c3 - 1, 9) + 9);
+              } else if (c2 % 4 == 0 && c0 == 3 && P1 == 0)
+                s0(3, P2, c2, c3, (-c2 + 12) / 4, -4 * P2 + 2 * c3 + 9 * floord(4 * P2 - 2 * c3 - 1, 9) + 9);
diff --git a/test_inputs/codegen/omega/p.delft2-0.in b/test_inputs/codegen/omega/p.delft2-0.in
new file mode 100644 (file)
index 0000000..f44b9bf
--- /dev/null
@@ -0,0 +1,3 @@
+[P1, P2] -> { s0[In_1, P2, In_3, In_4, In_5, In_6] -> [In_1, P2, In_3, In_4, In_5, In_6] : (exists (e0 = [(8 + 4In_1 + 16In_3 + In_5)/9], e1 = [(12 - 4P1 + 9e0)/16], e2 = [(-2In_1 - 2In_3 + In_5)/3], e3 = [(-5P2 - 2In_4 + In_6)/9]: 3e2 = -2In_1 - 2In_3 + In_5 and 9e3 = -5P2 - 2In_4 + In_6 and P1 >= 0 and In_1 >= 1 + P1 and In_1 <= 3 and P2 >= 0 and P2 <= 3 and In_6 >= 0 and In_6 <= 3 and In_5 >= 0 and In_5 <= 3 and In_5 >= 1 - 4In_1 - 16In_3 and In_5 <= 126 - 4In_1 - 16In_3 and In_6 <= 126 - 4P2 - 16In_4 and 16e1 <= -4P1 + 9e0 and 2In_6 <= P2 + 4In_4 and 9e0 <= 3 + 4In_1 + 16In_3 + In_5 and 9e0 >= 4In_1 + 16In_3 + In_5 and 16e1 >= -3 - 4P1 + 9e0)) or (exists (e0 = [(8 + 4In_1 + 16In_3 + In_5)/9], e1 = [(12 - 4P1 + 9e0)/16], e2 = [(-2In_1 - 2In_3 + In_5)/3], e3 = [(-5P2 - 2In_4 + In_6)/9]: 3e2 = -2In_1 - 2In_3 + In_5 and 9e3 = -5P2 - 2In_4 + In_6 and In_1 >= 0 and In_1 <= -1 + P1 and P1 <= 3 and In_6 >= 0 and In_6 <= 3 and In_6 <= 1 + 2In_4 and P2 >= 0 and P2 <= 3 and In_5 >= 0 and In_5 <= 3 and In_5 >= 1 - 4In_1 - 16In_3 and In_5 <= 126 - 4In_1 - 16In_3 and In_6 <= 126 - 4P2 - 16In_4 and 16e1 <= -4P1 + 9e0 and 9e0 <= 3 + 4In_1 + 16In_3 + In_5 and 9e0 >= 4In_1 + 16In_3 + In_5 and 16e1 >= -3 - 4P1 + 9e0)) }
+{  :  }
+[P1, P2] -> { [i0, i1, i2, i3, i4, i5] -> atomic[o0] : o0 <= 4; [i0, i1, i2, i3, i4, i5] -> separate[o0] : o0 >= 5 }
diff --git a/test_inputs/codegen/omega/p6-0.c b/test_inputs/codegen/omega/p6-0.c
new file mode 100644 (file)
index 0000000..53995e9
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  for (int c0 = 5; c0 <= 8; c0 += 1)
+    s0(c0);
+  for (int c0 = 10; c0 <= 16; c0 += 2)
+    s0(c0);
+  for (int c0 = 20; c0 <= 25; c0 += 1)
+    s0(c0);
+}
diff --git a/test_inputs/codegen/omega/p6-0.in b/test_inputs/codegen/omega/p6-0.in
new file mode 100644 (file)
index 0000000..025da3d
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1] -> [In_1] : (In_1 >= 5 and In_1 <= 8) or (exists (e0 = [(In_1)/2]: 2e0 = In_1 and In_1 >= 10 and In_1 <= 16)) or (In_1 >= 20 and In_1 <= 25) }
+{  :  }
+{ [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/test_inputs/codegen/omega/p6-1.c b/test_inputs/codegen/omega/p6-1.c
new file mode 100644 (file)
index 0000000..21a6f8e
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = -9; c0 <= 9; c0 += 1)
+  for (int c1 = max(-c0 + 1, 1); c1 <= min(-c0 + 10, 10); c1 += 1)
+    s0(c0, c1);
diff --git a/test_inputs/codegen/omega/p6-1.in b/test_inputs/codegen/omega/p6-1.in
new file mode 100644 (file)
index 0000000..82e1093
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, In_2] : In_2 >= 1 - In_1 and In_2 >= 1 and In_2 <= 10 - In_1 and In_2 <= 10 }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/stride1-0.c b/test_inputs/codegen/omega/stride1-0.c
new file mode 100644 (file)
index 0000000..c65c2e3
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = 3; c0 <= 9; c0 += 3)
+  s0(c0);
diff --git a/test_inputs/codegen/omega/stride1-0.in b/test_inputs/codegen/omega/stride1-0.in
new file mode 100644 (file)
index 0000000..e099087
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1] -> [In_1] : exists (e0 = [(In_1)/3]: 3e0 = In_1 and In_1 >= 3 and In_1 <= 9) }
+{  :  }
+{ [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/test_inputs/codegen/omega/stride2-0.c b/test_inputs/codegen/omega/stride2-0.c
new file mode 100644 (file)
index 0000000..0a7e8e7
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= n; c0 += 32)
+  for (int c1 = c0; c1 <= min(n, c0 + 31); c1 += 1)
+    s0(c0, c1);
diff --git a/test_inputs/codegen/omega/stride2-0.in b/test_inputs/codegen/omega/stride2-0.in
new file mode 100644 (file)
index 0000000..73dc13d
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(In_1)/32]: 32e0 = In_1 and In_2 <= 31 + In_1 and In_1 >= 0 and In_2 >= In_1 and In_2 <= n) }
+{  :  }
+[n] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/stride3-0.c b/test_inputs/codegen/omega/stride3-0.c
new file mode 100644 (file)
index 0000000..8913c80
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 3; c0 <= n; c0 += 32)
+  for (int c1 = c0; c1 <= min(n, c0 + 31); c1 += 1)
+    s0(c0, c1);
diff --git a/test_inputs/codegen/omega/stride3-0.in b/test_inputs/codegen/omega/stride3-0.in
new file mode 100644 (file)
index 0000000..360d7d0
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(-3 + In_1)/32]: 32e0 = -3 + In_1 and In_2 <= 31 + In_1 and In_1 >= 3 and In_2 >= In_1 and In_2 <= n) }
+{  :  }
+[n] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/stride4-0.c b/test_inputs/codegen/omega/stride4-0.c
new file mode 100644 (file)
index 0000000..ed62b59
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = 18; c0 <= 98; c0 += 5)
+  s0(c0);
diff --git a/test_inputs/codegen/omega/stride4-0.in b/test_inputs/codegen/omega/stride4-0.in
new file mode 100644 (file)
index 0000000..8779c3c
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1] -> [In_1] : exists (e0 = [(-3 + In_1)/5]: 5e0 = -3 + In_1 and In_1 >= 18 and In_1 <= 98) }
+{  :  }
+{ [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/test_inputs/codegen/omega/stride5-0.c b/test_inputs/codegen/omega/stride5-0.c
new file mode 100644 (file)
index 0000000..2eeeb5a
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 2; c0 <= min(100, -2 * n + 400); c0 += 2)
+  for (int c1 = 2 * n + c0; c1 <= 400; c1 += 2)
+    s0(c0, c1);
diff --git a/test_inputs/codegen/omega/stride5-0.in b/test_inputs/codegen/omega/stride5-0.in
new file mode 100644 (file)
index 0000000..c26c547
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(In_1)/2], e1 = [(In_2)/2]: 2e0 = In_1 and 2e1 = In_2 and In_1 >= 2 and In_1 <= 100 and In_2 <= 400 and In_2 >= 2n + In_1) }
+{  :  }
+[n] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/stride6-0.c b/test_inputs/codegen/omega/stride6-0.c
new file mode 100644 (file)
index 0000000..d6bd4d4
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= 101; c0 += 1)
+  for (int c1 = (c0 % 2) + c0; c1 <= 400; c1 += 2)
+    s0(c0, c1);
diff --git a/test_inputs/codegen/omega/stride6-0.in b/test_inputs/codegen/omega/stride6-0.in
new file mode 100644 (file)
index 0000000..16fda74
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(In_2)/2]: 2e0 = In_2 and In_1 >= 1 and In_2 >= In_1 and In_2 <= 400 and In_1 <= 101) }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/stride6-1.c b/test_inputs/codegen/omega/stride6-1.c
new file mode 100644 (file)
index 0000000..070028f
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 2; c0 <= 100; c0 += 2)
+  for (int c1 = c0; c1 <= 400; c1 += 2)
+    s0(c0, c1);
diff --git a/test_inputs/codegen/omega/stride6-1.in b/test_inputs/codegen/omega/stride6-1.in
new file mode 100644 (file)
index 0000000..91eaab2
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(In_1)/2], e1 = [(In_2)/2]: 2e0 = In_1 and 2e1 = In_2 and In_1 >= 2 and In_2 >= In_1 and In_2 <= 400 and In_1 <= 100) }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/stride6-2.c b/test_inputs/codegen/omega/stride6-2.c
new file mode 100644 (file)
index 0000000..070028f
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 2; c0 <= 100; c0 += 2)
+  for (int c1 = c0; c1 <= 400; c1 += 2)
+    s0(c0, c1);
diff --git a/test_inputs/codegen/omega/stride6-2.in b/test_inputs/codegen/omega/stride6-2.in
new file mode 100644 (file)
index 0000000..91eaab2
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(In_1)/2], e1 = [(In_2)/2]: 2e0 = In_1 and 2e1 = In_2 and In_1 >= 2 and In_2 >= In_1 and In_2 <= 400 and In_1 <= 100) }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/stride7-0.c b/test_inputs/codegen/omega/stride7-0.c
new file mode 100644 (file)
index 0000000..ba47689
--- /dev/null
@@ -0,0 +1,13 @@
+for (int c0 = 1; c0 <= 36; c0 += 1)
+  if (c0 <= 3) {
+    for (int c1 = 1; c1 <= 9; c1 += 1)
+      s1(c1, c0);
+  } else if (c0 <= 9) {
+    for (int c1 = 1; c1 <= 9; c1 += 1) {
+      if (c0 % 4 == 0)
+        s0(c1, c0 / 4);
+      s1(c1, c0);
+    }
+  } else if (c0 % 4 == 0)
+    for (int c1 = 1; c1 <= 9; c1 += 1)
+      s0(c1, c0 / 4);
diff --git a/test_inputs/codegen/omega/stride7-0.in b/test_inputs/codegen/omega/stride7-0.in
new file mode 100644 (file)
index 0000000..b84f204
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [4j, i, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[i, j] -> [j, i, 1] : i >= 1 and i <= 9 and j >= 1 and j <= 9 }
+{  :  }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 1; [i0, i1, i2] -> atomic[o0] : o0 <= 0 }
diff --git a/test_inputs/codegen/omega/stride7-1.c b/test_inputs/codegen/omega/stride7-1.c
new file mode 100644 (file)
index 0000000..e79d58d
--- /dev/null
@@ -0,0 +1,14 @@
+{
+  for (int c0 = 1; c0 <= 3; c0 += 1)
+    for (int c1 = 1; c1 <= 9; c1 += 1)
+      s1(c1, c0);
+  for (int c0 = 4; c0 <= 9; c0 += 1)
+    for (int c1 = 1; c1 <= 9; c1 += 1) {
+      if (c0 % 4 == 0)
+        s0(c1, c0 / 4);
+      s1(c1, c0);
+    }
+  for (int c0 = 3; c0 <= 9; c0 += 1)
+    for (int c1 = 1; c1 <= 9; c1 += 1)
+      s0(c1, c0);
+}
diff --git a/test_inputs/codegen/omega/stride7-1.in b/test_inputs/codegen/omega/stride7-1.in
new file mode 100644 (file)
index 0000000..3ec82b9
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [4j, i, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[i, j] -> [j, i, 1] : i >= 1 and i <= 9 and j >= 1 and j <= 9 }
+{  :  }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 0; [i0, i1, i2] -> atomic[o0] : o0 <= -1 }
diff --git a/test_inputs/codegen/omega/substitution-0.c b/test_inputs/codegen/omega/substitution-0.c
new file mode 100644 (file)
index 0000000..b12c07d
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= 10; c0 += 1)
+  for (int c1 = max(2 * c0 - 4, c0); c1 <= min(2 * c0, c0 + 6); c1 += 1)
+    s0(2 * c0 - c1, -c0 + c1);
diff --git a/test_inputs/codegen/omega/substitution-0.in b/test_inputs/codegen/omega/substitution-0.in
new file mode 100644 (file)
index 0000000..f4af716
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [i + j, i + 2j] : i >= 0 and i <= 4 and j >= 0 and j <= 6 }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/substitution-1.c b/test_inputs/codegen/omega/substitution-1.c
new file mode 100644 (file)
index 0000000..b394e5c
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= 14; c0 += 1)
+  for (int c1 = max(2 * c0 - 12, 2 * c0 - 3 * (c0 / 2)); c1 <= min(2 * c0, c0 / 2 + 9); c1 += 3)
+    s0((2 * c0 - c1) / 3, (-c0 + 2 * c1) / 3);
diff --git a/test_inputs/codegen/omega/substitution-1.in b/test_inputs/codegen/omega/substitution-1.in
new file mode 100644 (file)
index 0000000..504b220
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [2i + j, i + 2j] : i >= 0 and i <= 4 and j >= 0 and j <= 6 }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/substitution-2.c b/test_inputs/codegen/omega/substitution-2.c
new file mode 100644 (file)
index 0000000..9748950
--- /dev/null
@@ -0,0 +1,2 @@
+for (int c0 = -3; c0 <= 96; c0 += 1)
+  s0(c0, c0 + 4);
diff --git a/test_inputs/codegen/omega/substitution-2.in b/test_inputs/codegen/omega/substitution-2.in
new file mode 100644 (file)
index 0000000..bc9af0c
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[i, 4 + i] -> [i, 4 + i] : i >= -3 and i <= 96 }
+{  :  }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/substitution-3.c b/test_inputs/codegen/omega/substitution-3.c
new file mode 100644 (file)
index 0000000..86c197f
--- /dev/null
@@ -0,0 +1 @@
+s0(n + 19);
diff --git a/test_inputs/codegen/omega/substitution-3.in b/test_inputs/codegen/omega/substitution-3.in
new file mode 100644 (file)
index 0000000..ea1ac1a
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[19 + n] -> [19 + n] }
+{  :  }
+[n] -> { [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/test_inputs/codegen/omega/substitution-4.c b/test_inputs/codegen/omega/substitution-4.c
new file mode 100644 (file)
index 0000000..27b3199
--- /dev/null
@@ -0,0 +1 @@
+s0(n + 1);
diff --git a/test_inputs/codegen/omega/substitution-4.in b/test_inputs/codegen/omega/substitution-4.in
new file mode 100644 (file)
index 0000000..ecb07cd
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { s0[i] -> [i] : exists (e0 = [(-1 - n + i)/18]: 18e0 = -1 - n + i and i <= 16 + n and i >= 1 + n) }
+{  :  }
+[n] -> { [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/test_inputs/codegen/omega/syr2k-0.c b/test_inputs/codegen/omega/syr2k-0.c
new file mode 100644 (file)
index 0000000..820bd57
--- /dev/null
@@ -0,0 +1,4 @@
+for (int c0 = 1; c0 <= min(2 * b - 1, n); c0 += 1)
+  for (int c1 = max(-n + 1, -b + 1); c1 <= min(b - c0, n - c0); c1 += 1)
+    for (int c2 = max(c0 + c1, 1); c2 <= min(n + c1, n); c2 += 1)
+      s0(-c0 - c1 + c2 + 1, -c1 + c2, c2);
diff --git a/test_inputs/codegen/omega/syr2k-0.in b/test_inputs/codegen/omega/syr2k-0.in
new file mode 100644 (file)
index 0000000..28a7deb
--- /dev/null
@@ -0,0 +1,3 @@
+[n, b] -> { s0[i, j, k] -> [1 - i + j, -j + k, k] : i >= 1 and j >= i and j <= n and k >= 1 and k <= n and k <= -1 + b + i and k >= 1 - b + j }
+{  :  }
+[n, b] -> { [i0, i1, i2] -> separate[o0] : o0 >= 2; [i0, i1, i2] -> atomic[o0] : o0 <= 1 }
diff --git a/test_inputs/codegen/omega/syr2k-1.c b/test_inputs/codegen/omega/syr2k-1.c
new file mode 100644 (file)
index 0000000..fb20fb2
--- /dev/null
@@ -0,0 +1,4 @@
+for (int c0 = 1; c0 <= min(2 * b - 1, n); c0 += 1)
+  for (int c1 = -b + 1; c1 <= b - c0; c1 += 1)
+    for (int c2 = max(c0 + c1, 1); c2 <= min(n, n + c1); c2 += 1)
+      s0(-c0 - c1 + c2 + 1, -c1 + c2, c2);
diff --git a/test_inputs/codegen/omega/syr2k-1.in b/test_inputs/codegen/omega/syr2k-1.in
new file mode 100644 (file)
index 0000000..496aebe
--- /dev/null
@@ -0,0 +1,3 @@
+[n, b] -> { s0[i, j, k] -> [1 - i + j, -j + k, k] : i >= 1 and j >= i and j <= n and k >= 1 and k <= n and k <= -1 + b + i and k >= 1 - b + j }
+[b, n] -> {  : b >= 1 and n >= b }
+[n, b] -> { [i0, i1, i2] -> separate[o0] : o0 >= 2; [i0, i1, i2] -> atomic[o0] : o0 <= 1 }
diff --git a/test_inputs/codegen/omega/syr2k-2.c b/test_inputs/codegen/omega/syr2k-2.c
new file mode 100644 (file)
index 0000000..820bd57
--- /dev/null
@@ -0,0 +1,4 @@
+for (int c0 = 1; c0 <= min(2 * b - 1, n); c0 += 1)
+  for (int c1 = max(-n + 1, -b + 1); c1 <= min(b - c0, n - c0); c1 += 1)
+    for (int c2 = max(c0 + c1, 1); c2 <= min(n + c1, n); c2 += 1)
+      s0(-c0 - c1 + c2 + 1, -c1 + c2, c2);
diff --git a/test_inputs/codegen/omega/syr2k-2.in b/test_inputs/codegen/omega/syr2k-2.in
new file mode 100644 (file)
index 0000000..28a7deb
--- /dev/null
@@ -0,0 +1,3 @@
+[n, b] -> { s0[i, j, k] -> [1 - i + j, -j + k, k] : i >= 1 and j >= i and j <= n and k >= 1 and k <= n and k <= -1 + b + i and k >= 1 - b + j }
+{  :  }
+[n, b] -> { [i0, i1, i2] -> separate[o0] : o0 >= 2; [i0, i1, i2] -> atomic[o0] : o0 <= 1 }
diff --git a/test_inputs/codegen/omega/syr2k-3.c b/test_inputs/codegen/omega/syr2k-3.c
new file mode 100644 (file)
index 0000000..fb20fb2
--- /dev/null
@@ -0,0 +1,4 @@
+for (int c0 = 1; c0 <= min(2 * b - 1, n); c0 += 1)
+  for (int c1 = -b + 1; c1 <= b - c0; c1 += 1)
+    for (int c2 = max(c0 + c1, 1); c2 <= min(n, n + c1); c2 += 1)
+      s0(-c0 - c1 + c2 + 1, -c1 + c2, c2);
diff --git a/test_inputs/codegen/omega/syr2k-3.in b/test_inputs/codegen/omega/syr2k-3.in
new file mode 100644 (file)
index 0000000..496aebe
--- /dev/null
@@ -0,0 +1,3 @@
+[n, b] -> { s0[i, j, k] -> [1 - i + j, -j + k, k] : i >= 1 and j >= i and j <= n and k >= 1 and k <= n and k <= -1 + b + i and k >= 1 - b + j }
+[b, n] -> {  : b >= 1 and n >= b }
+[n, b] -> { [i0, i1, i2] -> separate[o0] : o0 >= 2; [i0, i1, i2] -> atomic[o0] : o0 <= 1 }
diff --git a/test_inputs/codegen/omega/ts1d-check-sblock-0.c b/test_inputs/codegen/omega/ts1d-check-sblock-0.c
new file mode 100644 (file)
index 0000000..ca13e21
--- /dev/null
@@ -0,0 +1,13 @@
+{
+  for (int c1 = 0; c1 <= 1; c1 += 1)
+    if (c1 == 1) {
+      s0(1, 1, 1, 0, 0);
+      s0(1, 1, 1, N - 1, 0);
+    } else
+      for (int c3 = 0; c3 <= N - 1; c3 += 1)
+        s0(1, 0, 1, c3, 0);
+  for (int c1 = 0; c1 <= floord(T - 1, 1000); c1 += 1)
+    for (int c2 = 1000 * c1 + 1; c2 <= min(N + 1000 * c1 + 997, N + T - 3); c2 += 1)
+      for (int c3 = max(-N - 1000 * c1 + c2 + 2, 0); c3 <= min(min(-1000 * c1 + c2 - 1, 999), T - 1000 * c1 - 1); c3 += 1)
+        s1(2, 1000 * c1 + c3, 1, -1000 * c1 + c2 - c3, 1);
+}
diff --git a/test_inputs/codegen/omega/ts1d-check-sblock-0.in b/test_inputs/codegen/omega/ts1d-check-sblock-0.in
new file mode 100644 (file)
index 0000000..b1f92ea
--- /dev/null
@@ -0,0 +1,3 @@
+[T, N] -> { s1[2, t, 1, i, 1] -> [2, tb, t + i, t - 1000tb, 0] : 1000tb <= t and 1000tb >= -999 + t and i >= 1 and i <= -2 + N and t >= 0 and t <= -1 + T; s0[1, 0, 1, In_4, 0] -> [1, 0, 1, In_4, 0] : In_4 >= 0 and In_4 <= -1 + N; s0[1, 1, 1, 0, 0] -> [1, 1, 1, 0, 0]; s0[1, 1, 1, -1 + N, 0] -> [1, 1, 1, -1 + N, 0] }
+[T, N] -> {  : T >= 0 and N >= 4 }
+[N] -> { [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 3; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 2 }
diff --git a/test_inputs/codegen/omega/ts1d-check0-0.c b/test_inputs/codegen/omega/ts1d-check0-0.c
new file mode 100644 (file)
index 0000000..cb854df
--- /dev/null
@@ -0,0 +1,13 @@
+{
+  for (int c1 = 0; c1 <= N - 1; c1 += 1)
+    s0(1, c1, 1, 0, 0);
+  for (int c1 = 0; c1 <= floord(T - 1, 500); c1 += 1)
+    for (int c2 = 1000 * c1; c2 <= min(N + 1000 * c1 + 997, N + 2 * T - 3); c2 += 1) {
+      for (int c3 = max(0, ((N + c2 + 1) % 2) - N - 1000 * c1 + c2 + 1); c3 <= min(min(2 * T - 1000 * c1 - 2, 998), -1000 * c1 + c2 - 2); c3 += 2) {
+        s1(2, 1000 * c1 + c3, 0, -1000 * c1 + c2 - c3, 1);
+        s2(2, 1000 * c1 + c3 + 1, 0, -1000 * c1 + c2 - c3 - 1, 1);
+      }
+      if (1000 * c1 + 999 >= c2 && 2 * T >= c2 + 1)
+        s1(2, -(c2 % 2) + c2, 0, c2 % 2, 1);
+    }
+}
diff --git a/test_inputs/codegen/omega/ts1d-check0-0.in b/test_inputs/codegen/omega/ts1d-check0-0.in
new file mode 100644 (file)
index 0000000..ce585b0
--- /dev/null
@@ -0,0 +1,3 @@
+[T, N] -> { s1[2, t, 0, i, 1] -> [2, tb, t + i, t - 1000tb, 1] : exists (e0 = [(t - 1000tb)/2]: 2e0 = t - 1000tb and 1000tb <= t and 1000tb >= -999 + t and i >= 0 and i <= -1 + N and t >= 0 and t <= -2 + 2T); s0[1, In_2, 1, 0, 0] -> [1, In_2, 1, 0, 0] : In_2 >= 0 and In_2 <= -1 + N; s2[2, t, 0, i, 1] -> [2, tb, t + i, t - 1000tb, 1] : exists (e0 = [(-1 + t - 1000tb)/2]: 2e0 = -1 + t - 1000tb and 1000tb <= t and 1000tb >= -999 + t and i >= 1 and i <= -2 + N and t >= 1 and t <= -1 + 2T) }
+[T, N] -> {  : T >= 0 and N >= 4 }
+[N] -> { [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 3; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 2 }
diff --git a/test_inputs/codegen/omega/ts1d-mp-i_ts-m_b-0.c b/test_inputs/codegen/omega/ts1d-mp-i_ts-m_b-0.c
new file mode 100644 (file)
index 0000000..f7ed369
--- /dev/null
@@ -0,0 +1,34 @@
+{
+  for (int c1 = -1; c1 <= (T >= 1 ? T - 1 : -1); c1 += 1)
+    for (int c2 = 0; c2 <= N - 1; c2 += 1)
+      if (c2 == 0 && c1 >= 0 && T >= c1 + 1) {
+        s0(1, c1, 0, 0, 0);
+      } else if (c2 + 1 == N && T >= c1 + 1 && c1 >= 0) {
+        s0(1, c1, N - 1, 0, 0);
+      } else if (c1 + 1 == 0 && c2 >= 0 && N >= c2 + 1)
+        s0(1, -1, c2, 0, 0);
+  for (int c1 = 0; c1 <= floord(T - 1, 500); c1 += 1) {
+    for (int c3 = -((c1 + 1) / 8) + 1; c3 <= floord(N - 500 * c1 - 3, 4000) + 1; c3 += 1)
+      for (int c4 = max(1000 * c1 + 4000 * c3 - 3999, 500 * c1 + 1); c4 <= min(min(2 * N - 4000 * c3 + 3995, N + T - 3), 1000 * c1 + 4000 * c3 - 3000); c4 += 1)
+        for (int c5 = max(-N - 500 * c1 + c4 + 2, 0); c5 <= min(min(T - 500 * c1 - 1, -500 * c1 + c4 - 1), -500 * c1 - 2000 * c3 + (c4 + 1) / 2 + 1999); c5 += 1)
+          s1(2, 500 * c1 + c5, 1, -500 * c1 + c4 - c5, 1);
+    for (int c3 = max(-((c1 + 1) / 8) + 1, -(T / 4000) + 1); c3 <= floord(N - 500 * c1 - 3, 4000) + 1; c3 += 1)
+      for (int c4 = max(-4000 * c3 + 4000, 1000 * c1 + 4000 * c3 - 3999); c4 <= min(min(2 * N - 4000 * c3 + 3995, 1000 * c1 + 4000 * c3 - 3000), 2 * T + 4000 * c3 - 4000); c4 += 1)
+        s2(2, -2000 * c3 + (c4 + 1) / 2 + 1999, 1, 2000 * c3 + c4 - (c4 + 1) / 2 - 1999, 1);
+    for (int c3 = -floord(c1 - 1, 8); c3 <= min(floord(N - 500 * c1 - 504, 4000) + 1, floord(N + T - 1000 * c1 - 1004, 4000) + 1); c3 += 1)
+      for (int c4 = max(1000 * c1 + 4000 * c3 - 2999, 500 * c1 + 1); c4 <= min(min(N + T - 3, N + 500 * c1 + 497), 1000 * c1 + 4000 * c3); c4 += 1)
+        for (int c5 = max(0, -N - 500 * c1 + c4 + 2); c5 <= min(min(T - 500 * c1 - 1, -500 * c1 + c4 - 1), 499); c5 += 1)
+          s3(2, 500 * c1 + c5, 1, -500 * c1 + c4 - c5, 1);
+    for (int c3 = max(-((c1 + 1) / 8), -(T / 4000)); c3 <= floord(N - 500 * c1 - 3, 4000); c3 += 1)
+      for (int c4 = max(-4000 * c3, 1000 * c1 + 4000 * c3 + 1); c4 <= min(min(2 * N - 4000 * c3 - 5, 1000 * c1 + 4000 * c3 + 1000), 2 * T + 4000 * c3); c4 += 1)
+        s4(2, -2000 * c3 + (c4 + 1) / 2 - 1, 1, 2000 * c3 + c4 - (c4 + 1) / 2 + 1, 1);
+    for (int c3 = -(c1 / 8); c3 <= min(floord(N - 500 * c1 + 496, 4000), floord(N + T - 1000 * c1 - 4, 4000)); c3 += 1)
+      for (int c4 = max(1000 * c1 + 4000 * c3 + 1, -4000 * c3 + 2); c4 <= min(min(min(1000 * c1 + 4000 * c3 + 998, N + 500 * c1 + 497), 2 * T + 4000 * c3 - 2), N + T - 3); c4 += 1)
+        for (int c5 = max(-N - 500 * c1 + c4 + 2, -500 * c1 - 2000 * c3 + c4 - c4 / 2); c5 <= min(min(T - 500 * c1 - 1, -500 * c1 + c4 - 1), 499); c5 += 1)
+          s5(2, 500 * c1 + c5, 1, -500 * c1 + c4 - c5, 1);
+  }
+  if (T >= 1)
+    for (int c3 = -floord(T - 2, 4000); c3 <= floord(N - T - 2, 4000) + 1; c3 += 1)
+      for (int c4 = max(2 * T + 4000 * c3 - 4001, T); c4 <= min(2 * T + 4000 * c3 - 2, N + T - 3); c4 += 1)
+        s6(2, T - 1, 1, -T + c4 + 1, 1);
+}
diff --git a/test_inputs/codegen/omega/ts1d-mp-i_ts-m_b-0.in b/test_inputs/codegen/omega/ts1d-mp-i_ts-m_b-0.in
new file mode 100644 (file)
index 0000000..0f86a1c
--- /dev/null
@@ -0,0 +1,3 @@
+[T, N] -> { s1[2, t, 1, i, 1] -> [2, tb, 1, proc, t + i, t - 500tb, 0] : 4000proc >= 3000 + t + i - 1000tb and 500tb <= t and 4000proc <= 3999 - t + i and i >= 1 and i <= -2 + N and t >= 0 and t <= -1 + T; s0[1, -1, c, 0, 0] -> [1, -1, c, 0, 0, 0, 0] : c >= 0 and c <= -1 + N; s0[1, b, 0, 0, 0] -> [1, b, 0, 0, 0, 0, 0] : b >= 0 and b <= -1 + T; s0[1, b, -1 + N, 0, 0] -> [1, b, -1 + N, 0, 0, 0, 0] : b >= 0 and b <= -1 + T; s6[2, -1 + T, 1, i, 1] -> [3, tb, 7, proc, -1 + T + i, -1 + T - 500tb, 0] : 500tb <= -1 + T and 500tb >= -500 + T and 4000proc >= 1 - T + i and 4000proc <= 4000 - T + i and i >= 1 and i <= -2 + N and T >= 1; s3[2, t, 1, i, 1] -> [2, tb, 3, proc, t + i, t - 500tb, 0] : 500tb <= t and 500tb >= -499 + t and 4000proc <= 2999 + t + i - 1000tb and 4000proc >= t + i - 1000tb and i >= 1 and i <= -2 + N and t >= 0 and t <= -1 + T; s2[2, t, 1, i, 1] -> [2, tb, 2, proc, t + i, t - 500tb, 0] : 500tb <= t and 500tb >= -499 + t and 4000proc <= 3999 - t + i and 4000proc >= 3998 - t + i and i >= 1 and i <= -2 + N and t >= 0 and t <= -1 + T; s4[2, t, 1, i, 1] -> [2, tb, 4, Out_4, t + i, t - 500tb, 0] : 500tb <= t and 500tb >= -499 + t and 4000Out_4 <= -1 - t + i and 4000Out_4 >= -2 - t + i and i >= 1 and i <= -2 + N and t >= 0 and t <= -1 + T; s5[2, t, 1, i, 1] -> [2, tb, 5, proc, t + i, t - 500tb, 0] : 500tb >= -499 + t and 4000proc <= -1 + t + i - 1000tb and 4000proc >= -t + i and i >= 1 and i <= -2 + N and t >= 0 and t <= -1 + T }
+[T, N] -> {  : T >= 0 and N >= 4 }
+[N, T] -> { [i0, i1, i2, i3, i4, i5, i6] -> atomic[o0] : o0 <= 5; [i0, i1, i2, i3, i4, i5, i6] -> separate[o0] : o0 >= 6 }
diff --git a/test_inputs/codegen/omega/ts1d-orig0-0.c b/test_inputs/codegen/omega/ts1d-orig0-0.c
new file mode 100644 (file)
index 0000000..13eb41c
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  for (int c1 = 0; c1 <= N - 1; c1 += 1)
+    s0(1, c1, 1, 0, 0);
+  for (int c1 = 0; c1 <= T - 1; c1 += 1) {
+    for (int c3 = 0; c3 <= N - 1; c3 += 1)
+      s1(2, c1, 0, c3, 1);
+    for (int c3 = 1; c3 <= N - 2; c3 += 1)
+      s2(2, c1, 1, c3, 1);
+  }
+}
diff --git a/test_inputs/codegen/omega/ts1d-orig0-0.in b/test_inputs/codegen/omega/ts1d-orig0-0.in
new file mode 100644 (file)
index 0000000..153ba7e
--- /dev/null
@@ -0,0 +1,3 @@
+[T, N] -> { s1[2, In_2, 0, In_4, 1] -> [2, In_2, 0, In_4, 1] : In_4 >= 0 and In_4 <= -1 + N and In_2 >= 0 and In_2 <= -1 + T; s0[1, In_2, 1, 0, 0] -> [1, In_2, 1, 0, 0] : In_2 >= 0 and In_2 <= -1 + N; s2[2, In_2, 1, In_4, 1] -> [2, In_2, 1, In_4, 1] : In_4 >= 1 and In_4 <= -2 + N and In_2 >= 0 and In_2 <= -1 + T }
+[T, N] -> {  : T >= 0 and N >= 4 }
+[N] -> { [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 4; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 3 }
diff --git a/test_inputs/codegen/omega/wak1-0.c b/test_inputs/codegen/omega/wak1-0.c
new file mode 100644 (file)
index 0000000..1ce4818
--- /dev/null
@@ -0,0 +1,27 @@
+{
+  for (int c0 = a3; c0 <= min(min(a2 - 1, a1 - 1), b3); c0 += 1)
+    s2(c0);
+  for (int c0 = a1; c0 <= min(a2 - 1, b1); c0 += 1) {
+    s0(c0);
+    if (c0 >= a3 && b3 >= c0)
+      s2(c0);
+  }
+  for (int c0 = max(max(b1 + 1, a1), a3); c0 <= min(a2 - 1, b3); c0 += 1)
+    s2(c0);
+  for (int c0 = a2; c0 <= b2; c0 += 1) {
+    if (c0 >= a1 && b1 >= c0)
+      s0(c0);
+    s1(c0);
+    if (c0 >= a3 && b3 >= c0)
+      s2(c0);
+  }
+  for (int c0 = max(max(b2 + 1, a3), a2); c0 <= min(a1 - 1, b3); c0 += 1)
+    s2(c0);
+  for (int c0 = max(max(b2 + 1, a1), a2); c0 <= b1; c0 += 1) {
+    s0(c0);
+    if (b3 >= c0 && c0 >= a3)
+      s2(c0);
+  }
+  for (int c0 = max(max(max(max(b1 + 1, b2 + 1), a1), a3), a2); c0 <= b3; c0 += 1)
+    s2(c0);
+}
diff --git a/test_inputs/codegen/omega/wak1-0.in b/test_inputs/codegen/omega/wak1-0.in
new file mode 100644 (file)
index 0000000..4cf37cb
--- /dev/null
@@ -0,0 +1,3 @@
+[a3, b3, a2, b2, a1, b1] -> { s2[i] -> [i, 2] : i >= a3 and i <= b3; s0[i] -> [i, 0] : i >= a1 and i <= b1; s1[i] -> [i, 1] : i >= a2 and i <= b2 }
+{  :  }
+[a1, b1] -> { [i0, i1] -> separate[o0] : o0 >= 2 }
diff --git a/test_inputs/codegen/omega/wak1-1.c b/test_inputs/codegen/omega/wak1-1.c
new file mode 100644 (file)
index 0000000..48a6f88
--- /dev/null
@@ -0,0 +1,55 @@
+{
+  for (int c0 = a2; c0 <= min(min(a3 - 1, a1 - 1), b2); c0 += 1)
+    s1(c0);
+  for (int c0 = a1; c0 <= min(min(a2 - 1, a3 - 1), b1); c0 += 1)
+    s0(c0);
+  for (int c0 = max(a1, a2); c0 <= min(min(a3 - 1, b2), b1); c0 += 1) {
+    s0(c0);
+    s1(c0);
+  }
+  for (int c0 = max(max(b1 + 1, a1), a2); c0 <= min(a3 - 1, b2); c0 += 1)
+    s1(c0);
+  for (int c0 = a3; c0 <= min(min(a2 - 1, a1 - 1), b3); c0 += 1)
+    s2(c0);
+  for (int c0 = max(a3, a2); c0 <= min(min(a1 - 1, b2), b3); c0 += 1) {
+    s1(c0);
+    s2(c0);
+  }
+  for (int c0 = max(max(b3 + 1, a3), a2); c0 <= min(a1 - 1, b2); c0 += 1)
+    s1(c0);
+  for (int c0 = max(a1, a3); c0 <= min(min(a2 - 1, b3), b1); c0 += 1) {
+    s0(c0);
+    s2(c0);
+  }
+  for (int c0 = max(max(b3 + 1, a1), a3); c0 <= min(a2 - 1, b1); c0 += 1)
+    s0(c0);
+  for (int c0 = max(max(a1, a3), a2); c0 <= min(min(b2, b3), b1); c0 += 1) {
+    s0(c0);
+    s1(c0);
+    s2(c0);
+  }
+  for (int c0 = max(max(max(b3 + 1, a1), a3), a2); c0 <= min(b2, b1); c0 += 1) {
+    s0(c0);
+    s1(c0);
+  }
+  for (int c0 = max(max(b1 + 1, a1), a3); c0 <= min(a2 - 1, b3); c0 += 1)
+    s2(c0);
+  for (int c0 = max(max(max(b1 + 1, a1), a3), a2); c0 <= min(b2, b3); c0 += 1) {
+    s1(c0);
+    s2(c0);
+  }
+  for (int c0 = max(max(max(max(b1 + 1, b3 + 1), a1), a3), a2); c0 <= b2; c0 += 1)
+    s1(c0);
+  for (int c0 = max(max(b2 + 1, a1), a2); c0 <= min(a3 - 1, b1); c0 += 1)
+    s0(c0);
+  for (int c0 = max(max(b2 + 1, a3), a2); c0 <= min(a1 - 1, b3); c0 += 1)
+    s2(c0);
+  for (int c0 = max(max(max(b2 + 1, a1), a3), a2); c0 <= min(b3, b1); c0 += 1) {
+    s0(c0);
+    s2(c0);
+  }
+  for (int c0 = max(max(max(max(b3 + 1, b2 + 1), a1), a3), a2); c0 <= b1; c0 += 1)
+    s0(c0);
+  for (int c0 = max(max(max(max(b1 + 1, b2 + 1), a1), a3), a2); c0 <= b3; c0 += 1)
+    s2(c0);
+}
diff --git a/test_inputs/codegen/omega/wak1-1.in b/test_inputs/codegen/omega/wak1-1.in
new file mode 100644 (file)
index 0000000..75c96d4
--- /dev/null
@@ -0,0 +1,3 @@
+[a3, b3, a2, b2, a1, b1] -> { s2[i] -> [i, 2] : i >= a3 and i <= b3; s0[i] -> [i, 0] : i >= a1 and i <= b1; s1[i] -> [i, 1] : i >= a2 and i <= b2 }
+{  :  }
+[a1, b1] -> { [i0, i1] -> separate[o0] : o0 >= 0 }
diff --git a/test_inputs/codegen/omega/wak2-0.c b/test_inputs/codegen/omega/wak2-0.c
new file mode 100644 (file)
index 0000000..e64b4ef
--- /dev/null
@@ -0,0 +1,26 @@
+{
+  for (int c0 = a1; c0 <= min(a2 - 1, b1); c0 += 1)
+    for (int c1_0 = c1; c1_0 <= d1; c1_0 += 1)
+      s0(c0, c1_0);
+  if (c2 >= d2 + 1) {
+    for (int c0 = max(a1, a2); c0 <= min(b2, b1); c0 += 1)
+      for (int c1_0 = c1; c1_0 <= d1; c1_0 += 1)
+        s0(c0, c1_0);
+  } else
+    for (int c0 = a2; c0 <= b2; c0 += 1) {
+      if (c0 >= a1 && b1 >= c0)
+        for (int c1_0 = c1; c1_0 <= min(c2 - 1, d1); c1_0 += 1)
+          s0(c0, c1_0);
+      for (int c1_0 = c2; c1_0 <= d2; c1_0 += 1) {
+        if (c0 >= a1 && b1 >= c0 && c1_0 >= c1 && d1 >= c1_0)
+          s0(c0, c1_0);
+        s1(c0, c1_0);
+      }
+      if (c0 >= a1 && b1 >= c0)
+        for (int c1_0 = max(c1, d2 + 1); c1_0 <= d1; c1_0 += 1)
+          s0(c0, c1_0);
+    }
+  for (int c0 = max(max(b2 + 1, a1), a2); c0 <= b1; c0 += 1)
+    for (int c1_0 = c1; c1_0 <= d1; c1_0 += 1)
+      s0(c0, c1_0);
+}
diff --git a/test_inputs/codegen/omega/wak2-0.in b/test_inputs/codegen/omega/wak2-0.in
new file mode 100644 (file)
index 0000000..da7a695
--- /dev/null
@@ -0,0 +1,3 @@
+[a2, b2, c2, d2, a1, b1, c1, d1] -> { s0[i, j] -> [i, j, 0] : i >= a1 and i <= b1 and j >= c1 and j <= d1; s1[i, j] -> [i, j, 1] : i >= a2 and i <= b2 and j >= c2 and j <= d2 }
+{  :  }
+[a1, b1, c1, d1] -> { [i0, i1, i2] -> separate[o0] : o0 >= 2 }
diff --git a/test_inputs/codegen/omega/wak2-1.c b/test_inputs/codegen/omega/wak2-1.c
new file mode 100644 (file)
index 0000000..f536cd7
--- /dev/null
@@ -0,0 +1,34 @@
+{
+  for (int c0 = a1; c0 <= min(a2 - 1, b1); c0 += 1)
+    for (int c1_0 = c1; c1_0 <= d1; c1_0 += 1)
+      s0(c0, c1_0);
+  if (c2 >= d2 + 1) {
+    for (int c0 = max(a1, a2); c0 <= min(b2, b1); c0 += 1)
+      for (int c1_0 = c1; c1_0 <= d1; c1_0 += 1)
+        s0(c0, c1_0);
+  } else
+    for (int c0 = a2; c0 <= b2; c0 += 1)
+      if (a1 >= c0 + 1) {
+        for (int c1_0 = c2; c1_0 <= d2; c1_0 += 1)
+          s1(c0, c1_0);
+      } else if (c0 >= b1 + 1) {
+        for (int c1_0 = c2; c1_0 <= d2; c1_0 += 1)
+          s1(c0, c1_0);
+      } else {
+        for (int c1_0 = c1; c1_0 <= min(c2 - 1, d1); c1_0 += 1)
+          s0(c0, c1_0);
+        for (int c1_0 = c2; c1_0 <= min(c1 - 1, d2); c1_0 += 1)
+          s1(c0, c1_0);
+        for (int c1_0 = max(c2, c1); c1_0 <= min(d1, d2); c1_0 += 1) {
+          s0(c0, c1_0);
+          s1(c0, c1_0);
+        }
+        for (int c1_0 = max(c1, d2 + 1); c1_0 <= d1; c1_0 += 1)
+          s0(c0, c1_0);
+        for (int c1_0 = max(max(c1, d1 + 1), c2); c1_0 <= d2; c1_0 += 1)
+          s1(c0, c1_0);
+      }
+  for (int c0 = max(max(b2 + 1, a1), a2); c0 <= b1; c0 += 1)
+    for (int c1_0 = c1; c1_0 <= d1; c1_0 += 1)
+      s0(c0, c1_0);
+}
diff --git a/test_inputs/codegen/omega/wak2-1.in b/test_inputs/codegen/omega/wak2-1.in
new file mode 100644 (file)
index 0000000..c92ac3c
--- /dev/null
@@ -0,0 +1,3 @@
+[a2, b2, c2, d2, a1, b1, c1, d1] -> { s0[i, j] -> [i, j, 0] : i >= a1 and i <= b1 and j >= c1 and j <= d1; s1[i, j] -> [i, j, 1] : i >= a2 and i <= b2 and j >= c2 and j <= d2 }
+{  :  }
+[a1, b1, c1, d1] -> { [i0, i1, i2] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/wak3-0.c b/test_inputs/codegen/omega/wak3-0.c
new file mode 100644 (file)
index 0000000..06be04a
--- /dev/null
@@ -0,0 +1,8 @@
+for (int c0 = a; c0 <= b + 20; c0 += 1) {
+  if (b >= c0)
+    s0(c0);
+  if (c0 >= a + 10 && b + 10 >= c0)
+    s1(c0);
+  if (c0 >= a + 20)
+    s2(c0);
+}
diff --git a/test_inputs/codegen/omega/wak3-0.in b/test_inputs/codegen/omega/wak3-0.in
new file mode 100644 (file)
index 0000000..a4c4de9
--- /dev/null
@@ -0,0 +1,3 @@
+[a, b] -> { s2[i] -> [i, 2] : i >= 20 + a and i <= 20 + b; s0[i] -> [i, 0] : i >= a and i <= b; s1[i] -> [i, 1] : i >= 10 + a and i <= 10 + b }
+{  :  }
+[a, b] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/test_inputs/codegen/omega/wak3-1.c b/test_inputs/codegen/omega/wak3-1.c
new file mode 100644 (file)
index 0000000..38d3d5c
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  for (int c0 = a; c0 <= min(b, a + 9); c0 += 1)
+    s0(c0);
+  for (int c0 = a + 10; c0 <= min(b, a + 19); c0 += 1) {
+    s0(c0);
+    s1(c0);
+  }
+  for (int c0 = max(a + 10, b + 1); c0 <= min(b + 10, a + 19); c0 += 1)
+    s1(c0);
+  for (int c0 = a + 20; c0 <= b; c0 += 1) {
+    s0(c0);
+    s1(c0);
+    s2(c0);
+  }
+  for (int c0 = max(a + 20, b + 1); c0 <= b + 10; c0 += 1) {
+    s1(c0);
+    s2(c0);
+  }
+  for (int c0 = max(a + 20, b + 11); c0 <= b + 20; c0 += 1)
+    s2(c0);
+}
diff --git a/test_inputs/codegen/omega/wak3-1.in b/test_inputs/codegen/omega/wak3-1.in
new file mode 100644 (file)
index 0000000..ae319e5
--- /dev/null
@@ -0,0 +1,3 @@
+[a, b] -> { s2[i] -> [i, 2] : i >= 20 + a and i <= 20 + b; s0[i] -> [i, 0] : i >= a and i <= b; s1[i] -> [i, 1] : i >= 10 + a and i <= 10 + b }
+{  :  }
+[a, b] -> { [i0, i1] -> atomic[o0] : o0 <= -1; [i0, i1] -> separate[o0] : o0 >= 0 }
diff --git a/test_inputs/codegen/omega/wak4-0.c b/test_inputs/codegen/omega/wak4-0.c
new file mode 100644 (file)
index 0000000..bf6eb22
--- /dev/null
@@ -0,0 +1,4 @@
+for (int c0 = max(max(max(max(a1, a2), a3), a4), a5); c0 <= min(min(min(min(b5, b4), b3), b2), b1); c0 += 1) {
+  s0(c0);
+  s1(c0);
+}
diff --git a/test_inputs/codegen/omega/wak4-0.in b/test_inputs/codegen/omega/wak4-0.in
new file mode 100644 (file)
index 0000000..9862df2
--- /dev/null
@@ -0,0 +1,3 @@
+[a1, a2, a3, a4, a5, b1, b2, b3, b4, b5] -> { s0[i] -> [i, 0] : i >= a1 and i >= a2 and i >= a3 and i >= a4 and i >= a5 and i <= b1 and i <= b2 and i <= b3 and i <= b4 and i <= b5; s1[i] -> [i, 1] : i >= a1 and i >= a2 and i >= a3 and i >= a4 and i >= a5 and i <= b1 and i <= b2 and i <= b3 and i <= b4 and i <= b5 }
+{  :  }
+[a1, a2, a3, a4, a5, b1, b2, b3, b4, b5] -> { [i0, i1] -> separate[o0] : o0 >= 1; [i0, i1] -> atomic[o0] : o0 <= 0 }
diff --git a/test_inputs/codegen/omega/wak4-1.c b/test_inputs/codegen/omega/wak4-1.c
new file mode 100644 (file)
index 0000000..bf6eb22
--- /dev/null
@@ -0,0 +1,4 @@
+for (int c0 = max(max(max(max(a1, a2), a3), a4), a5); c0 <= min(min(min(min(b5, b4), b3), b2), b1); c0 += 1) {
+  s0(c0);
+  s1(c0);
+}
diff --git a/test_inputs/codegen/omega/wak4-1.in b/test_inputs/codegen/omega/wak4-1.in
new file mode 100644 (file)
index 0000000..076cdd1
--- /dev/null
@@ -0,0 +1,3 @@
+[a1, a2, a3, a4, a5, b1, b2, b3, b4, b5] -> { s0[i] -> [i, 0] : i >= a1 and i >= a2 and i >= a3 and i >= a4 and i >= a5 and i <= b1 and i <= b2 and i <= b3 and i <= b4 and i <= b5; s1[i] -> [i, 1] : i >= a1 and i >= a2 and i >= a3 and i >= a4 and i >= a5 and i <= b1 and i <= b2 and i <= b3 and i <= b4 and i <= b5 }
+{  :  }
+[a1, a2, a3, a4, a5, b1, b2, b3, b4, b5] -> { [i0, i1] -> separate[o0] : o0 >= 0; [i0, i1] -> atomic[o0] : o0 <= -1 }
diff --git a/test_inputs/codegen/omega/x-0.c b/test_inputs/codegen/omega/x-0.c
new file mode 100644 (file)
index 0000000..16e6ed0
--- /dev/null
@@ -0,0 +1,14 @@
+for (int c0 = 1; c0 <= 11; c0 += 1) {
+  for (int c1 = max(-c0 + 9, 1); c1 <= min(c0 - 4, -c0 + 12); c1 += 1)
+    s0(c1, c0 + c1 - 8);
+  for (int c1 = max(1, c0 - 3); c1 <= min(c0, -c0 + 8); c1 += 1)
+    s1(c1, c0 - c1 + 1);
+  for (int c1 = max(-c0 + 9, c0 - 3); c1 <= min(c0, -c0 + 12); c1 += 1) {
+    s0(c1, c0 + c1 - 8);
+    s1(c1, c0 - c1 + 1);
+  }
+  for (int c1 = max(-c0 + 9, c0 + 1); c1 <= min(-c0 + 12, 8); c1 += 1)
+    s0(c1, c0 + c1 - 8);
+  for (int c1 = max(-c0 + 13, c0 - 3); c1 <= min(c0, 8); c1 += 1)
+    s1(c1, c0 - c1 + 1);
+}
diff --git a/test_inputs/codegen/omega/x-0.in b/test_inputs/codegen/omega/x-0.in
new file mode 100644 (file)
index 0000000..24340ef
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [8 - i + j, i, 0] : i >= 1 and i <= 8 and j >= 1 and j <= 4; s1[i, j] -> [-1 + i + j, i, 1] : i >= 1 and i <= 8 and j >= 1 and j <= 4 }
+{  :  }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 1; [i0, i1, i2] -> atomic[o0] : o0 <= 0 }
diff --git a/test_inputs/codegen/omega/x-1.c b/test_inputs/codegen/omega/x-1.c
new file mode 100644 (file)
index 0000000..16e6ed0
--- /dev/null
@@ -0,0 +1,14 @@
+for (int c0 = 1; c0 <= 11; c0 += 1) {
+  for (int c1 = max(-c0 + 9, 1); c1 <= min(c0 - 4, -c0 + 12); c1 += 1)
+    s0(c1, c0 + c1 - 8);
+  for (int c1 = max(1, c0 - 3); c1 <= min(c0, -c0 + 8); c1 += 1)
+    s1(c1, c0 - c1 + 1);
+  for (int c1 = max(-c0 + 9, c0 - 3); c1 <= min(c0, -c0 + 12); c1 += 1) {
+    s0(c1, c0 + c1 - 8);
+    s1(c1, c0 - c1 + 1);
+  }
+  for (int c1 = max(-c0 + 9, c0 + 1); c1 <= min(-c0 + 12, 8); c1 += 1)
+    s0(c1, c0 + c1 - 8);
+  for (int c1 = max(-c0 + 13, c0 - 3); c1 <= min(c0, 8); c1 += 1)
+    s1(c1, c0 - c1 + 1);
+}
diff --git a/test_inputs/codegen/omega/x-1.in b/test_inputs/codegen/omega/x-1.in
new file mode 100644 (file)
index 0000000..24340ef
--- /dev/null
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [8 - i + j, i, 0] : i >= 1 and i <= 8 and j >= 1 and j <= 4; s1[i, j] -> [-1 + i + j, i, 1] : i >= 1 and i <= 8 and j >= 1 and j <= 4 }
+{  :  }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 1; [i0, i1, i2] -> atomic[o0] : o0 <= 0 }
diff --git a/test_inputs/codegen/pldi2012/README b/test_inputs/codegen/pldi2012/README
new file mode 100644 (file)
index 0000000..316e838
--- /dev/null
@@ -0,0 +1,2 @@
+These examples are taken from the "Polyhedra Scanning Revisited" paper
+by Chun Chen.
diff --git a/test_inputs/codegen/pldi2012/figure7_b.c b/test_inputs/codegen/pldi2012/figure7_b.c
new file mode 100644 (file)
index 0000000..18ca370
--- /dev/null
@@ -0,0 +1,9 @@
+for (int c0 = 1; c0 <= 100; c0 += 1) {
+  if (n >= 2)
+    s0(c0);
+  for (int c1 = 1; c1 <= 100; c1 += 1) {
+    if (n >= 2)
+      s1(c0, c1);
+    s2(c0, c1);
+  }
+}
diff --git a/test_inputs/codegen/pldi2012/figure7_b.in b/test_inputs/codegen/pldi2012/figure7_b.in
new file mode 100644 (file)
index 0000000..9314917
--- /dev/null
@@ -0,0 +1,5 @@
+[n] -> { s0[i] -> [i,0] : 1 <= i <= 100 and n > 1;
+        s1[i,j] -> [i,j] : 1 <= i,j <= 100 and n > 1;
+        s2[i,j] -> [i,j] : 1 <= i,j <= 100 }
+[n] -> {  :  }
+[n] -> { [i,j] -> separate[x] : x >= 2 }
diff --git a/test_inputs/codegen/pldi2012/figure7_c.c b/test_inputs/codegen/pldi2012/figure7_c.c
new file mode 100644 (file)
index 0000000..b372c86
--- /dev/null
@@ -0,0 +1,10 @@
+for (int c0 = 1; c0 <= 100; c0 += 1)
+  if (n >= 2) {
+    s0(c0);
+    for (int c1 = 1; c1 <= 100; c1 += 1) {
+      s1(c0, c1);
+      s2(c0, c1);
+    }
+  } else
+    for (int c1 = 1; c1 <= 100; c1 += 1)
+      s2(c0, c1);
diff --git a/test_inputs/codegen/pldi2012/figure7_c.in b/test_inputs/codegen/pldi2012/figure7_c.in
new file mode 100644 (file)
index 0000000..06a3266
--- /dev/null
@@ -0,0 +1,5 @@
+[n] -> { s0[i] -> [i,0] : 1 <= i <= 100 and n > 1;
+        s1[i,j] -> [i,j] : 1 <= i,j <= 100 and n > 1;
+        s2[i,j] -> [i,j] : 1 <= i,j <= 100 }
+[n] -> {  :  }
+[n] -> { [i,j] -> separate[x] : x >= 1 }
diff --git a/test_inputs/codegen/pldi2012/figure7_d.c b/test_inputs/codegen/pldi2012/figure7_d.c
new file mode 100644 (file)
index 0000000..570cbe5
--- /dev/null
@@ -0,0 +1,12 @@
+if (n >= 2) {
+  for (int c0 = 1; c0 <= 100; c0 += 1) {
+    s0(c0);
+    for (int c1 = 1; c1 <= 100; c1 += 1) {
+      s1(c0, c1);
+      s2(c0, c1);
+    }
+  }
+} else
+  for (int c0 = 1; c0 <= 100; c0 += 1)
+    for (int c1 = 1; c1 <= 100; c1 += 1)
+      s2(c0, c1);
diff --git a/test_inputs/codegen/pldi2012/figure7_d.in b/test_inputs/codegen/pldi2012/figure7_d.in
new file mode 100644 (file)
index 0000000..339e39d
--- /dev/null
@@ -0,0 +1,5 @@
+[n] -> { s0[i] -> [i,0] : 1 <= i <= 100 and n > 1;
+        s1[i,j] -> [i,j] : 1 <= i,j <= 100 and n > 1;
+        s2[i,j] -> [i,j] : 1 <= i,j <= 100 }
+[n] -> {  :  }
+[n] -> { [i,j] -> separate[x] : x >= 0 }
diff --git a/test_inputs/codegen/pldi2012/figure8_a.c b/test_inputs/codegen/pldi2012/figure8_a.c
new file mode 100644 (file)
index 0000000..4608d61
--- /dev/null
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= n; c0 += 4)
+  for (int c1 = c0; c1 <= n; c1 += 3)
+    s0(c0, c1);
diff --git a/test_inputs/codegen/pldi2012/figure8_a.in b/test_inputs/codegen/pldi2012/figure8_a.in
new file mode 100644 (file)
index 0000000..df6543c
--- /dev/null
@@ -0,0 +1,4 @@
+[n] -> { s0[i,j] -> [i,j] : exists alpha, beta: 1 <= i <= n and i <= j <= n and
+                           i = 1 + 4 alpha and j = i + 3 beta}
+[n] -> { : }
+[n] -> {}
diff --git a/test_inputs/codegen/pldi2012/figure8_b.c b/test_inputs/codegen/pldi2012/figure8_b.c
new file mode 100644 (file)
index 0000000..21b90f2
--- /dev/null
@@ -0,0 +1,5 @@
+for (int c0 = 2; c0 <= n; c0 += 4) {
+  s1(c0);
+  if (n >= c0 + 2)
+    s0(c0 + 2);
+}
diff --git a/test_inputs/codegen/pldi2012/figure8_b.in b/test_inputs/codegen/pldi2012/figure8_b.in
new file mode 100644 (file)
index 0000000..2effb0a
--- /dev/null
@@ -0,0 +1,4 @@
+[n] -> { s0[i] -> [i] : exists alpha: 1 <= i <= n and i = 4 alpha;
+        s1[i] -> [i] : exists alpha: 1 <= i <= n and i = 4 alpha + 2 }
+[n] -> { : }
+[n] -> { }
diff --git a/test_inputs/codegen/separate.c b/test_inputs/codegen/separate.c
new file mode 100644 (file)
index 0000000..14d91be
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  a(0);
+  for (int c0 = 1; c0 <= 9; c0 += 1) {
+    a(c0);
+    b(c0 - 1);
+  }
+  b(9);
+}
diff --git a/test_inputs/codegen/separate.in b/test_inputs/codegen/separate.in
new file mode 100644 (file)
index 0000000..58486c3
--- /dev/null
@@ -0,0 +1,3 @@
+{ a[i] -> [i] : 0 <= i < 10; b[i] -> [i+1] : 0 <= i < 10 }
+{ : }
+{ [i] -> separate[x] }
diff --git a/test_inputs/codegen/separation_class.c b/test_inputs/codegen/separation_class.c
new file mode 100644 (file)
index 0000000..836f8b6
--- /dev/null
@@ -0,0 +1,17 @@
+{
+  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);
+}
diff --git a/test_inputs/codegen/separation_class.in b/test_inputs/codegen/separation_class.in
new file mode 100644 (file)
index 0000000..f42ea27
--- /dev/null
@@ -0,0 +1,6 @@
+{ A[i,j] -> [([i/10]),[j/10],i,j] : 0 <= i,j and i + j <= 100 }
+{ : }
+{ [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 }
diff --git a/test_inputs/codegen/shift.c b/test_inputs/codegen/shift.c
new file mode 100644 (file)
index 0000000..f4156bc
--- /dev/null
@@ -0,0 +1,4 @@
+for (int c0 = 0; c0 <= 9; c0 += 1) {
+  A(c0);
+  B(c0);
+}
diff --git a/test_inputs/codegen/shift.in b/test_inputs/codegen/shift.in
new file mode 100644 (file)
index 0000000..702c527
--- /dev/null
@@ -0,0 +1,3 @@
+{ A[i] -> [2i]: 0 <= i < 10; B[i] -> [2i+1] : 0 <= i < 10 }
+{ : }
+{ }
diff --git a/test_inputs/codegen/shift_unroll.c b/test_inputs/codegen/shift_unroll.c
new file mode 100644 (file)
index 0000000..2a38286
--- /dev/null
@@ -0,0 +1,14 @@
+for (int c0 = 0; c0 <= 9; c0 += 1) {
+  A(c0, 0);
+  A(c0, 1);
+  A(c0, 2);
+  A(c0, 3);
+  A(c0, 4);
+  A(c0, 5);
+  A(c0, 6);
+  A(c0, 7);
+  A(c0, 8);
+  A(c0, 9);
+  for (int c2 = 0; c2 <= 9; c2 += 1)
+    B(c0, c2);
+}
diff --git a/test_inputs/codegen/shift_unroll.in b/test_inputs/codegen/shift_unroll.in
new file mode 100644 (file)
index 0000000..4b773c2
--- /dev/null
@@ -0,0 +1,3 @@
+{ A[i,j] -> [2i,0,j]: 0 <= i,j < 10; B[i,j] -> [2i+1,1,j] : 0 <= i,j < 10 }
+{ : }
+{ [i,0,j] -> unroll[2] }
diff --git a/test_inputs/codegen/stride.c b/test_inputs/codegen/stride.c
new file mode 100644 (file)
index 0000000..5b68829
--- /dev/null
@@ -0,0 +1,6 @@
+for (int c0 = 0; c0 <= 100; c0 += 2) {
+  for (int c3 = 0; c3 <= 100; c3 += 1)
+    A(c0, c3);
+  for (int c2 = 0; c2 <= 100; c2 += 1)
+    B(c0, c2);
+}
diff --git a/test_inputs/codegen/stride.in b/test_inputs/codegen/stride.in
new file mode 100644 (file)
index 0000000..b01c566
--- /dev/null
@@ -0,0 +1,6 @@
+# Check that we find a common stride on the first dimension
+# even if it is imposed by different inner dimensions
+{ A[i,k] -> [i,0,j,k] : 0 <= i,k <= 100 and i = 2 j;
+  B[i,k] -> [i,1,k,j] : 0 <= i,k <= 100 and i = 2 j }
+{ : }
+{ }
diff --git a/test_inputs/codegen/stride5.c b/test_inputs/codegen/stride5.c
new file mode 100644 (file)
index 0000000..1e69f06
--- /dev/null
@@ -0,0 +1,3 @@
+if (2 * floord(n, 2) == n)
+  for (int c0 = (n - 4 * floord(n, 4)) / 2; c0 <= 100; c0 += 2)
+    S(c0);
diff --git a/test_inputs/codegen/stride5.in b/test_inputs/codegen/stride5.in
new file mode 100644 (file)
index 0000000..a67a802
--- /dev/null
@@ -0,0 +1,3 @@
+[n] -> { S[t] -> [t] : exists e : 2 t - n = 4e and 0 <= t <= 100 }
+[n] -> { : }
+{ }
diff --git a/test_inputs/codegen/unroll.c b/test_inputs/codegen/unroll.c
new file mode 100644 (file)
index 0000000..63594bb
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  A(0);
+  A(100000000);
+  A(200000000);
+}
diff --git a/test_inputs/codegen/unroll.in b/test_inputs/codegen/unroll.in
new file mode 100644 (file)
index 0000000..65561e2
--- /dev/null
@@ -0,0 +1,5 @@
+# Test that unrolling takes into account stride constraints.
+# If it didn't, it would run essentially forever on this example.
+[n] -> { A[i] -> [i] : exists a : i = 100000000 a and 0 <= a <= 2 }
+{:}
+{ [i] -> unroll[0] }
diff --git a/test_inputs/codegen/unroll2.c b/test_inputs/codegen/unroll2.c
new file mode 100644 (file)
index 0000000..7ae38be
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  A(0);
+  A(1);
+  A(2);
+  A(3);
+  for (int c0 = 4; c0 <= 99996; c0 += 1)
+    A(c0);
+  A(99997);
+  A(99998);
+  A(99999);
+}
diff --git a/test_inputs/codegen/unroll2.in b/test_inputs/codegen/unroll2.in
new file mode 100644 (file)
index 0000000..0fb36ab
--- /dev/null
@@ -0,0 +1,5 @@
+# Check that the different disjuncts in the unroll option
+# are handled separately.
+{ A[i] -> [i] : 0 <= i < 100000 }
+{ : }
+{ [i] -> unroll[0] : i < 4 or i > 99996 }