return -1;
}
+static int compute_component_schedule(isl_ctx *ctx,
+ struct isl_sched_graph *graph);
+
+/* Is the schedule row "sol" trivial on node "node"?
+ * That is, is the solution zero on the dimensions orthogonal to
+ * the previously found solutions?
+ * Each coefficient is represented as the difference between
+ * two non-negative values in "sol". The coefficient is then
+ * zero if those two values are equal to each other.
+ */
+static int is_trivial(struct isl_sched_node *node, __isl_keep isl_vec *sol)
+{
+ int i;
+ int pos;
+ int len;
+
+ pos = 1 + node->start + 1 + 2 * (node->nparam + node->rank);
+ len = 2 * (node->nvar - node->rank);
+
+ if (len == 0)
+ return 0;
+
+ for (i = 0; i < len; i += 2)
+ if (isl_int_ne(sol->el[pos + i], sol->el[pos + i + 1]))
+ return 0;
+
+ return 1;
+}
+
+/* Is the schedule row "sol" trivial on any node where it should
+ * not be trivial?
+ */
+static int is_any_trivial(struct isl_sched_graph *graph,
+ __isl_keep isl_vec *sol)
+{
+ int i;
+
+ for (i = 0; i < graph->n; ++i) {
+ struct isl_sched_node *node = &graph->node[i];
+
+ if (!needs_row(graph, node))
+ continue;
+ if (is_trivial(node, sol))
+ return 1;
+ }
+
+ return 0;
+}
+
/* Construct a schedule row for each node such that as many dependences
* as possible are carried and then continue with the next band.
+ *
+ * If the computed schedule row turns out to be trivial on one or
+ * more nodes where it should not be trivial, then we throw it away
+ * and try again on each component separately.
*/
static int carry_dependences(isl_ctx *ctx, struct isl_sched_graph *graph)
{
"unable to carry dependences", return -1);
}
+ if (is_any_trivial(graph, sol)) {
+ isl_vec_free(sol);
+ if (graph->scc > 1)
+ return compute_component_schedule(ctx, graph);
+ isl_die(ctx, isl_error_unknown,
+ "unable to construct non-trivial solution", return -1);
+ }
+
if (update_schedule(graph, sol, 0, 0) < 0)
return -1;
return 0;
}
-int test_special_schedule(isl_ctx *ctx, const char *domain,
- const char *validity, const char *proximity, const char *expected_sched)
+static __isl_give isl_union_map *compute_schedule(isl_ctx *ctx,
+ const char *domain, const char *validity, const char *proximity)
{
isl_union_set *dom;
isl_union_map *dep;
isl_union_map *prox;
- isl_union_map *sched1, *sched2;
isl_schedule *schedule;
- int equal;
+ isl_union_map *sched;
dom = isl_union_set_read_from_str(ctx, domain);
dep = isl_union_map_read_from_str(ctx, validity);
prox = isl_union_map_read_from_str(ctx, proximity);
schedule = isl_union_set_compute_schedule(dom, dep, prox);
- sched1 = isl_schedule_get_map(schedule);
+ sched = isl_schedule_get_map(schedule);
isl_schedule_free(schedule);
+ return sched;
+}
+
+/* Check that a schedule can be constructed on the given domain
+ * with the given validity and proximity constraints.
+ */
+static int test_has_schedule(isl_ctx *ctx, const char *domain,
+ const char *validity, const char *proximity)
+{
+ isl_union_map *sched;
+
+ sched = compute_schedule(ctx, domain, validity, proximity);
+ if (!sched)
+ return -1;
+
+ isl_union_map_free(sched);
+ return 0;
+}
+
+int test_special_schedule(isl_ctx *ctx, const char *domain,
+ const char *validity, const char *proximity, const char *expected_sched)
+{
+ isl_union_map *sched1, *sched2;
+ int equal;
+
+ sched1 = compute_schedule(ctx, domain, validity, proximity);
sched2 = isl_union_map_read_from_str(ctx, expected_sched);
equal = isl_union_map_is_equal(sched1, sched2);
if (test_special_schedule(ctx, D, V, P, S) < 0)
return -1;
ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
- return test_special_schedule(ctx, D, V, P, S);
+ if (test_special_schedule(ctx, D, V, P, S) < 0)
+ return -1;
+
+ D = "{ A[a]; B[] }";
+ V = "{}";
+ P = "{ A[a] -> B[] }";
+ if (test_has_schedule(ctx, D, V, P) < 0)
+ return -1;
+
+ return 0;
}
int test_plain_injective(isl_ctx *ctx, const char *str, int injective)