/* 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_remove_divs_involving_dims(guard,
						isl_dim_set, depth, 1);
		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;
}
Example #2
0
/* 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);
}
Example #3
0
CloogInput *Cloog::buildCloogInput() {
  CloogDomain *Context =
    cloog_domain_from_isl_set(isl_set_copy(S->getContext()));
  CloogUnionDomain *Statements = buildCloogUnionDomain();
  CloogInput *Input = cloog_input_alloc (Context, Statements);
  return Input;
}
Example #4
0
/* Compute the size of a bounding box around the origin and "set",
 * where "set" is assumed to contain only non-negative elements.
 * In particular, compute the maximal value of "set" in each direction
 * and add one.
 */
__isl_give isl_multi_pw_aff *ppcg_size_from_extent(__isl_take isl_set *set)
{
	int i, n;
	isl_multi_pw_aff *mpa;

	n = isl_set_dim(set, isl_dim_set);
	mpa = isl_multi_pw_aff_zero(isl_set_get_space(set));
	for (i = 0; i < n; ++i) {
		isl_space *space;
		isl_aff *one;
		isl_pw_aff *bound;

		if (!isl_set_dim_has_upper_bound(set, isl_dim_set, i)) {
			const char *name;
			name = isl_set_get_tuple_name(set);
			if (!name)
				name = "";
			fprintf(stderr, "unable to determine extent of '%s' "
				"in dimension %d\n", name, i);
			set = isl_set_free(set);
		}
		bound = isl_set_dim_max(isl_set_copy(set), i);

		space = isl_pw_aff_get_domain_space(bound);
		one = isl_aff_zero_on_domain(isl_local_space_from_space(space));
		one = isl_aff_add_constant_si(one, 1);
		bound = isl_pw_aff_add(bound, isl_pw_aff_from_aff(one));
		mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, bound);
	}
	isl_set_free(set);

	return mpa;
}
Example #5
0
/* Check if the constraints in "set" imply any stride on set dimension "pos" and
 * store the results in data->stride and data->offset.
 *
 * In particular, compute the affine hull and then check if
 * any of the constraints in the hull impose any stride on the dimension.
 * If no such constraint can be found, then the offset is taken
 * to be the zero expression and the stride is taken to be one.
 */
static void set_detect_stride(__isl_keep isl_set *set, int pos,
	struct isl_detect_stride_data *data)
{
	isl_basic_set *hull;

	hull = isl_set_affine_hull(isl_set_copy(set));

	data->pos = pos;
	data->found = 0;
	data->stride = NULL;
	data->offset = NULL;
	if (isl_basic_set_foreach_constraint(hull, &detect_stride, data) < 0)
		goto error;

	if (!data->found) {
		data->stride = isl_val_one(isl_set_get_ctx(set));
		if (data->want_offset) {
			isl_space *space;
			isl_local_space *ls;

			space = isl_set_get_space(set);
			ls = isl_local_space_from_space(space);
			data->offset = isl_aff_zero_on_domain(ls);
		}
	}
	isl_basic_set_free(hull);
	return;
error:
	isl_basic_set_free(hull);
	data->stride = isl_val_free(data->stride);
	data->offset = isl_aff_free(data->offset);
}
Example #6
0
int isl_set_count_upto(__isl_keep isl_set *set, isl_int max, isl_int *count)
{
	struct isl_counter cnt = { { &increment_counter } };

	if (!set)
		return -1;

	isl_int_init(cnt.count);
	isl_int_init(cnt.max);

	isl_int_set_si(cnt.count, 0);
	isl_int_set(cnt.max, max);
	if (isl_set_scan(isl_set_copy(set), &cnt.callback) < 0 &&
	    isl_int_lt(cnt.count, cnt.max))
		goto error;

	isl_int_set(*count, cnt.count);
	isl_int_clear(cnt.max);
	isl_int_clear(cnt.count);

	return 0;
error:
	isl_int_clear(cnt.count);
	return -1;
}
Example #7
0
int isl_set_foreach_point(__isl_keep isl_set *set,
	int (*fn)(__isl_take isl_point *pnt, void *user), void *user)
{
	struct isl_foreach_point fp = { { &foreach_point }, fn, user };
	int i;

	if (!set)
		return -1;

	fp.dim = isl_set_get_dim(set);
	if (!fp.dim)
		return -1;

	set = isl_set_copy(set);
	set = isl_set_cow(set);
	set = isl_set_make_disjoint(set);
	set = isl_set_compute_divs(set);
	if (!set)
		goto error;

	for (i = 0; i < set->n; ++i)
		if (isl_basic_set_scan(isl_basic_set_copy(set->p[i]),
					&fp.callback) < 0)
			goto error;

	isl_set_free(set);
	isl_dim_free(fp.dim);

	return 0;
error:
	isl_set_free(set);
	isl_dim_free(fp.dim);
	return -1;
}
Example #8
0
/* 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);
}
Example #9
0
/* Given an index expression "test_index" for the if condition,
 * an index expression "skip_index" for the skip condition and
 * scops for the then and else branches, construct a scop for
 * computing "skip_index" within the context "pc".
 *
 * The computed scop contains a single statement that essentially does
 *
 *	skip_index = test_cond ? skip_cond_then : skip_cond_else
 *
 * If the skip conditions of the then and/or else branch are not affine,
 * then they need to be filtered by test_index.
 * If they are missing, then this means the skip condition is false.
 *
 * Since we are constructing a skip condition for the if statement,
 * the skip conditions on the then and else branches are removed.
 */
static struct pet_scop *extract_skip_if(__isl_take isl_multi_pw_aff *test_index,
	__isl_take isl_multi_pw_aff *skip_index,
	struct pet_scop *scop_then, struct pet_scop *scop_else, int have_else,
	enum pet_skip type, __isl_keep pet_context *pc, struct pet_state *state)
{
	pet_expr *expr_then, *expr_else, *expr, *expr_skip;
	pet_tree *tree;
	struct pet_stmt *stmt;
	struct pet_scop *scop;
	isl_ctx *ctx;
	isl_set *domain;

	if (!scop_then)
		goto error;
	if (have_else && !scop_else)
		goto error;

	ctx = isl_multi_pw_aff_get_ctx(test_index);

	if (pet_scop_has_skip(scop_then, type)) {
		expr_then = pet_scop_get_skip_expr(scop_then, type);
		pet_scop_reset_skip(scop_then, type);
		if (!pet_expr_is_affine(expr_then))
			expr_then = pet_expr_filter(expr_then,
					isl_multi_pw_aff_copy(test_index), 1);
	} else
		expr_then = universally_false(pet_context_get_space(pc));

	if (have_else && pet_scop_has_skip(scop_else, type)) {
		expr_else = pet_scop_get_skip_expr(scop_else, type);
		pet_scop_reset_skip(scop_else, type);
		if (!pet_expr_is_affine(expr_else))
			expr_else = pet_expr_filter(expr_else,
					isl_multi_pw_aff_copy(test_index), 0);
	} else
		expr_else = universally_false(pet_context_get_space(pc));

	expr = pet_expr_from_index(test_index);
	expr = pet_expr_new_ternary(expr, expr_then, expr_else);
	expr_skip = pet_expr_from_index(isl_multi_pw_aff_copy(skip_index));
	expr_skip = pet_expr_access_set_write(expr_skip, 1);
	expr_skip = pet_expr_access_set_read(expr_skip, 0);
	expr = pet_expr_new_binary(1, pet_op_assign, expr_skip, expr);
	domain = pet_context_get_domain(pc);
	tree = pet_tree_new_expr(expr);
	stmt = pet_stmt_from_pet_tree(isl_set_copy(domain),
					state->n_stmt++, tree);

	scop = pet_scop_from_pet_stmt(pet_context_get_space(pc), stmt);
	scop = pet_scop_add_boolean_array(scop, domain, skip_index,
					state->int_size);

	return scop;
error:
	isl_multi_pw_aff_free(test_index);
	isl_multi_pw_aff_free(skip_index);
	return NULL;
}
Example #10
0
/* Construct a scop for computing the skip condition of the given type and
 * with index expression "skip_index" for a sequence of two scops "scop1"
 * and "scop2".  Do so within the context "pc".
 *
 * The computed scop contains a single statement that essentially does
 *
 *	skip_index = skip_cond_1 ? 1 : skip_cond_2
 *
 * or, in other words, skip_cond1 || skip_cond2.
 * In this expression, skip_cond_2 is filtered to reflect that it is
 * only evaluated when skip_cond_1 is false.
 *
 * The skip condition on scop1 is not removed because it still needs
 * to be applied to scop2 when these two scops are combined.
 */
static struct pet_scop *extract_skip_seq(
	__isl_take isl_multi_pw_aff *skip_index,
	struct pet_scop *scop1, struct pet_scop *scop2, enum pet_skip type,
	__isl_keep pet_context *pc, struct pet_state *state)
{
	pet_expr *expr1, *expr2, *expr, *expr_skip;
	pet_tree *tree;
	struct pet_stmt *stmt;
	struct pet_scop *scop;
	isl_ctx *ctx;
	isl_set *domain;

	if (!scop1 || !scop2)
		goto error;

	ctx = isl_multi_pw_aff_get_ctx(skip_index);

	expr1 = pet_scop_get_skip_expr(scop1, type);
	expr2 = pet_scop_get_skip_expr(scop2, type);
	pet_scop_reset_skip(scop2, type);

	expr2 = pet_expr_filter(expr2, pet_expr_access_get_index(expr1), 0);

	expr = universally_true(pet_context_get_space(pc));
	expr = pet_expr_new_ternary(expr1, expr, expr2);
	expr_skip = pet_expr_from_index(isl_multi_pw_aff_copy(skip_index));
	expr_skip = pet_expr_access_set_write(expr_skip, 1);
	expr_skip = pet_expr_access_set_read(expr_skip, 0);
	expr = pet_expr_new_binary(1, pet_op_assign, expr_skip, expr);
	domain = pet_context_get_domain(pc);
	tree = pet_tree_new_expr(expr);
	stmt = pet_stmt_from_pet_tree(isl_set_copy(domain),
					state->n_stmt++, tree);

	scop = pet_scop_from_pet_stmt(pet_context_get_space(pc), stmt);
	scop = pet_scop_add_boolean_array(scop, domain, skip_index,
					state->int_size);

	return scop;
error:
	isl_multi_pw_aff_free(skip_index);
	return NULL;
}
Example #11
0
CloogUnionDomain *Cloog::buildCloogUnionDomain() {
  CloogUnionDomain *DU = cloog_union_domain_alloc(S->getNumParams());

  for (Scop::iterator SI = S->begin(), SE = S->end(); SI != SE; ++SI) {
    ScopStmt *Stmt = *SI;

    if (Stmt->isFinalRead())
      continue;

    CloogScattering *Scattering=
      cloog_scattering_from_isl_map(isl_map_copy(Stmt->getScattering()));
    CloogDomain *Domain =
      cloog_domain_from_isl_set(isl_set_copy(Stmt->getDomain()));

    std::string entryName = Stmt->getBaseName();
    char *Name = (char*)malloc(sizeof(char) * (entryName.size() + 1));
    strcpy(Name, entryName.c_str());

    DU = cloog_union_domain_add_domain(DU, Name, Domain, Scattering, Stmt);
  }

  return DU;
}
Example #12
0
static void *isl_obj_set_copy(void *v)
{
	return isl_set_copy((struct isl_set *)v);
}
/**
 * Converts a SCoP as extracted by PolyOpt's auto-scop detection
 * into ISL representation.
 *
 * bugs/limitations:
 *    (a) not robust to union of iteration domains in scoplib
 *    (b) code is leaking, need proper copy constructor that duplicates all
 *          ISL structures.
 */
int
PolyOptISLRepresentation::convertScoplibToISL (scoplib_scop_p scop)
{
  int i;
  isl_union_map* all_reads = NULL;
  isl_union_map* all_writes = NULL;
  isl_union_map* all_scheds = NULL;
  isl_ctx* ctxt = isl_ctx_alloc();

  // 1. Prepare the arrays of unique names for statements and arrays.
  char buffer[32];
  int nb_statements;
  scoplib_statement_p s;
  for (nb_statements = 0, s = scop->statement; s; s = s->next, nb_statements++)
    ;
  char* stmt_names[nb_statements];
  for (i = 0; i < nb_statements; ++i)
    {
      sprintf (buffer, "S_%d", i);
      stmt_names[i] = strdup (buffer);
    }
  char* array_names[scop->nb_arrays];
  for (i = 0; i < scop->nb_arrays; ++i)
    array_names[i] =
      strdup (((SgVariableSymbol*)(scop->arrays[i]))->get_name().str());

  isl_union_map* umap;
  int stmt_id;
  for (s = scop->statement, stmt_id = 0; s; s = s->next, ++stmt_id)
    {
      isl_union_map* all_reads_stmt = NULL;
      isl_union_map* all_writes_stmt = NULL;
      isl_space* sp = NULL;
      for (i = 0; i < scop->nb_arrays; ++i)
	{
	  sp = build_isl_space (scop, s, i+1, ctxt);

	  // 1. Handle access matrices.
	  scoplib_matrix_p m;
	  int k;
	  for (k = 0, m = s->read, umap = all_reads_stmt; k < 2;
	       k++, m = s->write, umap = all_writes_stmt)
	    {
	      isl_map* acc_map = NULL;
	      int row_pos = 0;
	      do
		{
		  acc_map = build_access_function
		    (scop, s, m, sp, ctxt, &row_pos, i+1);
		  if (acc_map)
		    {
		      acc_map = isl_map_set_tuple_name
			(acc_map, isl_dim_in, stmt_names[stmt_id]);
		      acc_map = isl_map_set_tuple_name
			(acc_map, isl_dim_out, array_names[i]);
		      if (umap == NULL)
			umap = isl_union_map_from_map (isl_map_copy (acc_map));
		      else
			umap = isl_union_map_union
			  (umap, isl_union_map_from_map (isl_map_copy (acc_map)));
		      isl_map_free (acc_map);
		    }
		}
	      while (acc_map != NULL);
	      if (k == 0)
		all_reads_stmt = umap;
	      else
		all_writes_stmt = umap;
	    }
	}
      // Store the union of access functions of statement i.
      stmt_accfunc_read.push_back (all_reads_stmt);
      stmt_accfunc_write.push_back (all_writes_stmt);

      // 2. Handle iteration domains.
      isl_set* dom = build_iteration_domain (scop, s, sp, ctxt);
      dom = isl_set_set_tuple_name (dom, stmt_names[stmt_id]);
      if (all_reads_stmt != NULL)
	all_reads_stmt = isl_union_map_intersect_domain
	  (isl_union_map_copy (all_reads_stmt),
	   isl_union_set_from_set (isl_set_copy (dom)));
      if (all_writes_stmt != NULL)
	all_writes_stmt = isl_union_map_intersect_domain
	  (all_writes_stmt, isl_union_set_from_set (isl_set_copy (dom)));

      // Store the iteration domain of statement i.
      stmt_iterdom.push_back (dom);
      // Store the union of access functions of statement i after intersection by domain.
      stmt_read_domain.push_back (all_reads_stmt);
      stmt_write_domain.push_back (all_writes_stmt);

      // Unionize the result.
      if (all_reads == NULL)
	all_reads = isl_union_map_copy (all_reads_stmt);
      else
	all_reads = isl_union_map_union
	  (all_reads, isl_union_map_copy (all_reads_stmt));
      if (all_writes == NULL)
	all_writes = isl_union_map_copy (all_writes_stmt);
      else
	all_writes = isl_union_map_union
	  (all_writes, isl_union_map_copy (all_writes_stmt));
      // isl_union_map_free (all_reads_stmt);
      // isl_union_map_free (all_writes_stmt);

      // 3. Handle schedules.
      isl_map* sched = build_schedule (scop, s, sp, ctxt);
      sched = isl_map_set_tuple_name (sched, isl_dim_in, stmt_names[stmt_id]);
      if (all_scheds == NULL)
	all_scheds = isl_union_map_from_map (isl_map_copy (sched));
      else
	all_scheds = isl_union_map_union
	  (all_scheds, isl_union_map_from_map (isl_map_copy (sched)));
      // Store the schedule of statement i.
      stmt_schedule.push_back (sched);

      // 4. Finalize info about the statement.
      stmt_body.push_back (((SgNode*)(s->body))->unparseToCompleteString());
      stmt_body_ir.push_back ((SgNode*)(s->body));
    }

  // // Debug.
  // isl_printer* pr = isl_printer_to_file (ctxt, stdout);
  // std::cout << "UNION MAP READS" << std::endl;
  // isl_printer_print_union_map(pr, all_reads);
  // printf ("\n");
  // std::cout << "UNION MAP WRITES" << std::endl;
  // isl_printer_print_union_map(pr, all_writes);
  // printf ("\n");
  // std::cout << "UNION MAP SCHEDULES" << std::endl;
  // isl_printer_print_union_map(pr, all_scheds);
  // printf ("\n");
  for (std::vector<std::string>::iterator i = stmt_body.begin();
       i != stmt_body.end(); ++i)
    std::cout << "stmt body: " << *i << std::endl;
  // Finalize SCoP representation.
  scop_nb_arrays = scop->nb_arrays;
  scop_nb_statements = stmt_schedule.size();
  scop_reads = all_reads;
  scop_writes = all_writes;
  scop_scheds = all_scheds;

  return EXIT_SUCCESS;
}