/* 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. * If there is only one graft in the list and if its guard * depends on the current level, then we eliminate this level and * return the result. * * Otherwise, we return the unshifted simple hull of the guards. * In order to be able to hoist as many constraints as possible, * but at the same time avoid hoisting constraints that did not * appear in the guards in the first place, we intersect the guards * with all the information that is available (i.e., the domain * from the build and the enforced constraints of the graft) and * compute the unshifted hull of the result using only constraints * from the original guards. * In particular, intersecting the guards with other known information * allows us to hoist guards that are only explicit is some of * the grafts and implicit in the others. * * 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. */ __isl_give isl_set *isl_ast_graft_list_extract_hoistable_guard( __isl_keep isl_ast_graft_list *list, __isl_keep isl_ast_build *build) { int i, n; int equal; isl_ctx *ctx; isl_set *guard; isl_set_list *set_list; isl_basic_set *hull; 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; if (equal || n == 1) { isl_ast_graft *graft_0; graft_0 = isl_ast_graft_list_get_ast_graft(list, 0); if (!graft_0) return NULL; guard = isl_set_copy(graft_0->guard); if (!equal) guard = hoist_guard(guard, build); isl_ast_graft_free(graft_0); return guard; } ctx = isl_ast_build_get_ctx(build); set_list = isl_set_list_alloc(ctx, n); guard = isl_set_empty(isl_ast_build_get_space(build, 1)); for (i = 0; i < n; ++i) { isl_ast_graft *graft; isl_basic_set *enforced; isl_set *guard_i; graft = isl_ast_graft_list_get_ast_graft(list, i); enforced = isl_ast_graft_get_enforced(graft); guard_i = isl_set_copy(graft->guard); isl_ast_graft_free(graft); set_list = isl_set_list_add(set_list, isl_set_copy(guard_i)); guard_i = isl_set_intersect(guard_i, isl_set_from_basic_set(enforced)); guard_i = isl_set_intersect(guard_i, isl_ast_build_get_domain(build)); guard = isl_set_union(guard, guard_i); } hull = isl_set_unshifted_simple_hull_from_set_list(guard, set_list); guard = isl_set_from_basic_set(hull); return hoist_guard(guard, build); }
/* Return "lhs && rhs", defined on the shared definition domain. */ __isl_give isl_pw_aff *pet_and(__isl_take isl_pw_aff *lhs, __isl_take isl_pw_aff *rhs) { isl_set *cond; isl_set *dom; dom = isl_set_intersect(isl_pw_aff_domain(isl_pw_aff_copy(lhs)), isl_pw_aff_domain(isl_pw_aff_copy(rhs))); cond = isl_set_intersect(isl_pw_aff_non_zero_set(lhs), isl_pw_aff_non_zero_set(rhs)); return indicator_function(cond, dom); }
/* Return the result of applying the comparison operator "type" * to "pa1" and "pa2". * * In particular, construct an isl_pw_aff that is equal to 1 * on the subset of the shared domain of "pa1" and "pa2" where * the comparison holds and 0 on the other part of the shared domain. * * If "pa1" or "pa2" involve any NaN, then return NaN. */ __isl_give isl_pw_aff *pet_comparison(enum pet_op_type type, __isl_take isl_pw_aff *pa1, __isl_take isl_pw_aff *pa2) { isl_set *dom; isl_set *cond; isl_pw_aff *res; if (!pa1 || !pa2) goto error; if (isl_pw_aff_involves_nan(pa1) || isl_pw_aff_involves_nan(pa2)) { isl_space *space = isl_pw_aff_get_domain_space(pa1); isl_local_space *ls = isl_local_space_from_space(space); isl_pw_aff_free(pa1); isl_pw_aff_free(pa2); return isl_pw_aff_nan_on_domain(ls); } dom = isl_pw_aff_domain(isl_pw_aff_copy(pa1)); dom = isl_set_intersect(dom, isl_pw_aff_domain(isl_pw_aff_copy(pa2))); switch (type) { case pet_op_lt: cond = isl_pw_aff_lt_set(pa1, pa2); break; case pet_op_le: cond = isl_pw_aff_le_set(pa1, pa2); break; case pet_op_gt: cond = isl_pw_aff_gt_set(pa1, pa2); break; case pet_op_ge: cond = isl_pw_aff_ge_set(pa1, pa2); break; case pet_op_eq: cond = isl_pw_aff_eq_set(pa1, pa2); break; case pet_op_ne: cond = isl_pw_aff_ne_set(pa1, pa2); break; default: isl_die(isl_pw_aff_get_ctx(pa1), isl_error_internal, "not a comparison operator", cond = NULL); isl_pw_aff_free(pa1); isl_pw_aff_free(pa2); } cond = isl_set_coalesce(cond); res = indicator_function(cond, dom); return res; error: isl_pw_aff_free(pa1); isl_pw_aff_free(pa2); return NULL; }