Ejemplo n.º 1
0
/* Merge pairs of consecutive leaves in "leaves" taking into account
 * the intersection of validity and proximity schedule constraints "dep".
 *
 * If a leaf has been merged with the next leaf, then the combination
 * is checked again for merging with the next leaf.
 * That is, if the leaves are A, B and C, then B may not have been
 * merged with C, but after merging A and B, it could still be useful
 * to merge the combination AB with C.
 *
 * Two leaves A and B are merged if there are instances of at least
 * one pair of statements, one statement in A and one B, such that
 * the validity and proximity schedule constraints between them
 * make them suitable for merging according to check_merge.
 *
 * Return the final number of leaves in the sequence, or -1 on error.
 */
static int merge_leaves(int n, struct ppcg_grouping_leaf leaves[n],
	__isl_keep isl_union_map *dep)
{
	int i;
	struct ppcg_merge_leaves_data data;

	for (i = n - 1; i >= 0; --i) {
		isl_union_map *dep_i;
		isl_stat ok;

		if (i + 1 >= n)
			continue;

		dep_i = isl_union_map_copy(dep);
		dep_i = isl_union_map_intersect_domain(dep_i,
				isl_union_set_copy(leaves[i].domain));
		dep_i = isl_union_map_intersect_range(dep_i,
				isl_union_set_copy(leaves[i + 1].domain));
		data.merge = 0;
		data.src = &leaves[i];
		data.dst = &leaves[i + 1];
		ok = isl_union_map_foreach_map(dep_i, &check_merge, &data);
		isl_union_map_free(dep_i);
		if (ok < 0 && !data.merge)
			return -1;
		if (!data.merge)
			continue;
		if (merge_pair(n, leaves, i) < 0)
			return -1;
		--n;
		++i;
	}

	return n;
}
/**
 * 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;
}