brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.5 KiB · e225a71 Raw
375 lines · plain
1/* Copyright 2016-2017 Tobias Grosser2 *3 * Use of this software is governed by the MIT license4 *5 * Written by Tobias Grosser, Weststrasse 47, CH-8003, Zurich6 */7 8#ifndef IS_TRUE9#define IS_TRUE(b)	(b)10#endif11#ifndef SIZE_VAL12#define SIZE_VAL(s)	(s)13#endif14 15/* Test the pointer interface for interaction between isl C and C++ types.16 *17 * This tests:18 * - construction from an isl C object19 * - check that constructed objects are non-null20 * - get a non-owned C pointer from an isl C++ object usable in __isl_keep21 *   methods22 * - use copy to get an owned C pointer from an isl C++ object which is usable23 *   in __isl_take methods. Verify that the original C++ object retains a valid24 *   pointer.25 * - use release to get an owned C pointer from an isl C++ object which is26 *   usable in __isl_take methods. Verify that the original C++ object gave up27 *   its pointer and now is null.28 */29void test_pointer(isl::ctx ctx)30{31	isl_set *c_empty = isl_set_read_from_str(ctx.get(), "{ : false }");32	isl::set empty = isl::manage(c_empty);33	assert(IS_TRUE(empty.is_empty()));34	assert(isl_set_is_empty(empty.get()));35 36	assert(!empty.is_null());37	isl_set_free(empty.copy());38	assert(!empty.is_null());39	isl_set_free(empty.release());40	assert(empty.is_null());41}42 43/* Test that isl objects can be constructed.44 *45 * This tests:46 *  - construction of a null object47 *  - construction from a string48 *  - construction from an integer49 *  - static constructor without a parameter50 *  - conversion construction (implicit)51 *  - conversion construction (explicit)52 *  - construction of empty union set53 *54 *  The tests to construct from integers and strings cover functionality that55 *  is also tested in the parameter type tests, but here we verify that56 *  multiple overloaded constructors are available and that overload resolution57 *  works as expected.58 *59 *  Construction from an isl C pointer is tested in test_pointer.60 */61void test_constructors(isl::ctx ctx)62{63	isl::val null;64	assert(null.is_null());65 66	isl::val zero_from_str = isl::val(ctx, "0");67	assert(IS_TRUE(zero_from_str.is_zero()));68 69	isl::val zero_int_con = isl::val(ctx, 0);70	assert(IS_TRUE(zero_int_con.is_zero()));71 72	isl::val zero_static_con = isl::val::zero(ctx);73	assert(IS_TRUE(zero_static_con.is_zero()));74 75	isl::basic_set bs(ctx, "{ [1] }");76	isl::set result(ctx, "{ [1] }");77	isl::set s = bs;78	assert(IS_TRUE(s.is_equal(result)));79	isl::set s2(bs);80	assert(IS_TRUE(s.unite(s2).is_equal(result)));81 82	isl::union_set us(ctx, "{ A[1]; B[2, 3] }");83	isl::union_set empty = isl::union_set::empty(ctx);84	assert(IS_TRUE(us.is_equal(us.unite(empty))));85}86 87/* Test integer function parameters.88 *89 * Verify that extreme values and zero work.90 */91void test_parameters_int(isl::ctx ctx)92{93	isl::val long_max_str(ctx, std::to_string(LONG_MAX));94	isl::val long_max_int(ctx, LONG_MAX);95	assert(IS_TRUE(long_max_str.eq(long_max_int)));96 97	isl::val long_min_str(ctx, std::to_string(LONG_MIN));98	isl::val long_min_int(ctx, LONG_MIN);99	assert(IS_TRUE(long_min_str.eq(long_min_int)));100 101	isl::val long_zero_str = isl::val(ctx, std::to_string(0));102	isl::val long_zero_int = isl::val(ctx, 0);103	assert(IS_TRUE(long_zero_str.eq(long_zero_int)));104}105 106/* Test isl objects parameters.107 *108 * Verify that isl objects can be passed as lvalue and rvalue parameters.109 * Also verify that isl object parameters are automatically type converted if110 * there is an inheritance relation. Finally, test function calls without111 * any additional parameters, apart from the isl object on which112 * the method is called.113 */114void test_parameters_obj(isl::ctx ctx)115{116	isl::set a(ctx, "{ [0] }");117	isl::set b(ctx, "{ [1] }");118	isl::set c(ctx, "{ [2] }");119	isl::set expected(ctx, "{ [i] : 0 <= i <= 2 }");120 121	isl::set tmp = a.unite(b);122	isl::set res_lvalue_param = tmp.unite(c);123	assert(IS_TRUE(res_lvalue_param.is_equal(expected)));124 125	isl::set res_rvalue_param = a.unite(b).unite(c);126	assert(IS_TRUE(res_rvalue_param.is_equal(expected)));127 128	isl::basic_set a2(ctx, "{ [0] }");129	assert(IS_TRUE(a.is_equal(a2)));130 131	isl::val two(ctx, 2);132	isl::val half(ctx, "1/2");133	isl::val res_only_this_param = two.inv();134	assert(IS_TRUE(res_only_this_param.eq(half)));135}136 137/* Test different kinds of parameters to be passed to functions.138 *139 * This includes integer and isl C++ object parameters.140 */141void test_parameters(isl::ctx ctx)142{143	test_parameters_int(ctx);144	test_parameters_obj(ctx);145}146 147/* Test that isl objects are returned correctly.148 *149 * This only tests that after combining two objects, the result is successfully150 * returned.151 */152void test_return_obj(isl::ctx ctx)153{154	isl::val one(ctx, "1");155	isl::val two(ctx, "2");156	isl::val three(ctx, "3");157 158	isl::val res = one.add(two);159 160	assert(IS_TRUE(res.eq(three)));161}162 163/* Test that integer values are returned correctly.164 */165void test_return_int(isl::ctx ctx)166{167	isl::val one(ctx, "1");168	isl::val neg_one(ctx, "-1");169	isl::val zero(ctx, "0");170 171	assert(one.sgn() > 0);172	assert(neg_one.sgn() < 0);173	assert(zero.sgn() == 0);174}175 176/* Test that strings are returned correctly.177 * Do so by calling overloaded isl::ast_build::from_expr methods.178 */179void test_return_string(isl::ctx ctx)180{181	isl::set context(ctx, "[n] -> { : }");182	isl::ast_build build = isl::ast_build::from_context(context);183	isl::pw_aff pw_aff(ctx, "[n] -> { [n] }");184	isl::set set(ctx, "[n] -> { : n >= 0 }");185 186	isl::ast_expr expr = build.expr_from(pw_aff);187	const char *expected_string = "n";188	assert(expected_string == expr.to_C_str());189 190	expr = build.expr_from(set);191	expected_string = "n >= 0";192	assert(expected_string == expr.to_C_str());193}194 195/* Test the functionality of "every" functions196 * that does not depend on the type of C++ bindings.197 */198static void test_every_generic(isl::ctx ctx)199{200	isl::union_set us(ctx, "{ A[i]; B[j] }");201 202	auto is_empty = [] (isl::set s) {203		return s.is_empty();204	};205	assert(!IS_TRUE(us.every_set(is_empty)));206 207	auto is_non_empty = [] (isl::set s) {208		return !s.is_empty();209	};210	assert(IS_TRUE(us.every_set(is_non_empty)));211 212	auto in_A = [] (isl::set s) {213		return s.is_subset(isl::set(s.ctx(), "{ A[x] }"));214	};215	assert(!IS_TRUE(us.every_set(in_A)));216 217	auto not_in_A = [] (isl::set s) {218		return !s.is_subset(isl::set(s.ctx(), "{ A[x] }"));219	};220	assert(!IS_TRUE(us.every_set(not_in_A)));221}222 223/* Check basic construction of spaces.224 */225static void test_space(isl::ctx ctx)226{227	isl::space unit = isl::space::unit(ctx);228	isl::space set_space = unit.add_named_tuple("A", 3);229	isl::space map_space = set_space.add_named_tuple("B", 2);230 231	isl::set set = isl::set::universe(set_space);232	isl::map map = isl::map::universe(map_space);233	assert(IS_TRUE(set.is_equal(isl::set(ctx, "{ A[*,*,*] }"))));234	assert(IS_TRUE(map.is_equal(isl::map(ctx, "{ A[*,*,*] -> B[*,*] }"))));235}236 237/* Construct a simple schedule tree with an outer sequence node and238 * a single-dimensional band node in each branch, with one of them239 * marked coincident.240 */241static isl::schedule construct_schedule_tree(isl::ctx ctx)242{243	isl::union_set A(ctx, "{ A[i] : 0 <= i < 10 }");244	isl::union_set B(ctx, "{ B[i] : 0 <= i < 20 }");245 246	auto node = isl::schedule_node::from_domain(A.unite(B));247	node = node.child(0);248 249	isl::union_set_list filters(ctx, 0);250	filters = filters.add(A).add(B);251	node = node.insert_sequence(filters);252 253	isl::multi_union_pw_aff f_A(ctx, "[ { A[i] -> [i] } ]");254	node = node.child(0);255	node = node.child(0);256	node = node.insert_partial_schedule(f_A);257	auto band = node.as<isl::schedule_node_band>();258	band = band.member_set_coincident(0, true);259	node = band.ancestor(2);260 261	isl::multi_union_pw_aff f_B(ctx, "[ { B[i] -> [i] } ]");262	node = node.child(1);263	node = node.child(0);264	node = node.insert_partial_schedule(f_B);265	node = node.ancestor(2);266 267	return node.schedule();268}269 270/* Test basic schedule tree functionality that is independent271 * of the type of bindings.272 *273 * In particular, create a simple schedule tree and274 * - check that the root node is a domain node275 * - check that an object of a subclass can be used as one of the superclass276 * - test map_descendant_bottom_up in the successful case277 */278static isl::schedule_node test_schedule_tree_generic(isl::ctx ctx)279{280	auto schedule = construct_schedule_tree(ctx);281	auto root = schedule.root();282 283	assert(IS_TRUE(root.isa<isl::schedule_node_domain>()));284	root = root.as<isl::schedule_node_domain>().child(0).parent();285 286	int count = 0;287	auto inc_count = [&count](isl::schedule_node node) {288		count++;289		return node;290	};291	root = root.map_descendant_bottom_up(inc_count);292	assert(count == 8);293 294	return root;295}296 297/* Test marking band members for unrolling.298 * "schedule" is the schedule created by construct_schedule_tree.299 * It schedules two statements, with 10 and 20 instances, respectively.300 * Unrolling all band members therefore results in 30 at-domain calls301 * by the AST generator.302 */303static void test_ast_build_unroll(isl::schedule schedule)304{305	auto root = schedule.root();306	auto mark_unroll = [](isl::schedule_node node) {307		if (IS_TRUE(node.isa<isl::schedule_node_band>())) {308			auto band = node.as<isl::schedule_node_band>();309			node = band.member_set_ast_loop_unroll(0);310		}311		return node;312	};313	root = root.map_descendant_bottom_up(mark_unroll);314	schedule = root.schedule();315 316	int count_ast = 0;317	auto inc_count_ast =318	    [&count_ast](isl::ast_node node, isl::ast_build build) {319		count_ast++;320		return node;321	};322	auto build = isl::ast_build(schedule.ctx());323	build = build.set_at_each_domain(inc_count_ast);324	auto ast = build.node_from(schedule);325	assert(count_ast == 30);326}327 328/* Test basic AST generation from a schedule tree that is independent329 * of the type of bindings.330 *331 * In particular, create a simple schedule tree and332 * - generate an AST from the schedule tree333 * - test at_each_domain in the successful case334 * - test unrolling335 */336static isl::schedule test_ast_build_generic(isl::ctx ctx)337{338	auto schedule = construct_schedule_tree(ctx);339 340	int count_ast = 0;341	auto inc_count_ast =342	    [&count_ast](isl::ast_node node, isl::ast_build build) {343		count_ast++;344		return node;345	};346	auto build = isl::ast_build(ctx);347	auto build_copy = build.set_at_each_domain(inc_count_ast);348	auto ast = build.node_from(schedule);349	assert(count_ast == 0);350	count_ast = 0;351	ast = build_copy.node_from(schedule);352	assert(count_ast == 2);353	build = build_copy;354	count_ast = 0;355	ast = build.node_from(schedule);356	assert(count_ast == 2);357 358	test_ast_build_unroll(schedule);359 360	return schedule;361}362 363/* Test basic AST expression generation from an affine expression.364 */365static void test_ast_build_expr(isl::ctx ctx)366{367	isl::pw_aff pa(ctx, "[n] -> { [n + 1] }");368	isl::ast_build build = isl::ast_build::from_context(pa.domain());369 370	auto expr = build.expr_from(pa);371	auto op = expr.as<isl::ast_expr_op>();372	assert(IS_TRUE(op.isa<isl::ast_expr_op_add>()));373	assert(SIZE_VAL(op.n_arg()) == 2);374}375