scheduler: replace split_parallel by split_scaled option
authorSven Verdoolaege <skimo@kotnet.org>
Sun, 29 Jan 2012 13:42:16 +0000 (14:42 +0100)
committerSven Verdoolaege <skimo@kotnet.org>
Mon, 30 Jan 2012 15:20:17 +0000 (16:20 +0100)
The split_parallel option was ill-conceived.
The condition split_parallel looked for was too specific
and the implementation was wrong.  Part of this has been fixed
in 1b2fdb6 (schedule.c: split_parallel: avoid invalid memory accesses,
Mon Jan 30 15:23:18 2012 +0100), but the code could in principle
still produce an incorrect schedule because it didn't check the sizes
of the constant terms.

The new option essentially applies strip-mining and should therefore
be safe.  In particular, it is applied when the linear parts of the
schedules have a non-trivial common divisor.  The strip-mining is
then performed with respect to this common divisor.

Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
doc/user.pod
include/isl/schedule.h
isl_options.c
isl_options_private.h
isl_schedule.c

index e620391..0acc8ab 100644 (file)
@@ -153,6 +153,15 @@ dimension manipulation on the result.
 
 =back
 
+=head3 Changes since isl-0.09
+
+=over
+
+=item * The C<schedule_split_parallel> option has been replaced
+by the C<schedule_split_scaled> option.
+
+=back
+
 =head1 Installation
 
 The source of C<isl> can be obtained either as a tarball
@@ -4205,9 +4214,9 @@ A representation of the band can be printed using
                isl_ctx *ctx, int val);
        int isl_options_get_schedule_outer_zero_distance(
                isl_ctx *ctx);
-       int isl_options_set_schedule_split_parallel(
+       int isl_options_set_schedule_split_scaled(
                isl_ctx *ctx, int val);
-       int isl_options_get_schedule_split_parallel(
+       int isl_options_get_schedule_split_scaled(
                isl_ctx *ctx);
        int isl_options_set_schedule_algorithm(
                isl_ctx *ctx, int val);
@@ -4240,13 +4249,14 @@ where the outermost scheduling dimension in each band
 results in a zero dependence distance over the proximity
 dependences.
 
-=item * schedule_split_parallel
+=item * schedule_split_scaled
 
 If this option is set, then we try to construct schedules in which the
 constant term is split off from the linear part if the linear parts of
-the scheduling rows for all nodes in the graphs are the same.
+the scheduling rows for all nodes in the graphs have a common non-trivial
+divisor.
 The constant term is then placed in a separate band and the linear
-part is simplified.
+part is reduced.
 
 =item * schedule_algorithm
 
index 05f9f2a..a4fee32 100644 (file)
@@ -21,8 +21,8 @@ int isl_options_get_schedule_maximize_band_depth(isl_ctx *ctx);
 int isl_options_set_schedule_outer_zero_distance(isl_ctx *ctx, int val);
 int isl_options_get_schedule_outer_zero_distance(isl_ctx *ctx);
 
-int isl_options_set_schedule_split_parallel(isl_ctx *ctx, int val);
-int isl_options_get_schedule_split_parallel(isl_ctx *ctx);
+int isl_options_set_schedule_split_scaled(isl_ctx *ctx, int val);
+int isl_options_get_schedule_split_scaled(isl_ctx *ctx);
 
 #define                ISL_SCHEDULE_FUSE_MAX                   0
 #define                ISL_SCHEDULE_FUSE_MIN                   1
index fe6a696..7d82b08 100644 (file)
@@ -150,9 +150,9 @@ ISL_ARG_BOOL(struct isl_options, schedule_outer_zero_distance, 0,
 ISL_ARG_BOOL(struct isl_options, schedule_maximize_band_depth, 0,
        "schedule-maximize-band-depth", 0,
        "maximize the number of scheduling dimensions in a band")
-ISL_ARG_BOOL(struct isl_options, schedule_split_parallel, 0,
-       "schedule-split-parallel", 1,
-       "split non-tilable bands with parallel schedules")
+ISL_ARG_BOOL(struct isl_options, schedule_split_scaled, 0,
+       "schedule-split-scaled", 1,
+       "split non-tilable bands with scaled schedules")
 ISL_ARG_CHOICE(struct isl_options, schedule_algorithm, 0,
        "schedule-algorithm", isl_schedule_algorithm_choice,
        ISL_SCHEDULE_ALGORITHM_ISL, "scheduling algorithm to use")
@@ -189,9 +189,9 @@ ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
        schedule_maximize_band_depth)
 
 ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
-       schedule_split_parallel)
+       schedule_split_scaled)
 ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
-       schedule_split_parallel)
+       schedule_split_scaled)
 
 ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
        schedule_outer_zero_distance)
index 1d9aba9..60a6524 100644 (file)
@@ -49,7 +49,7 @@ struct isl_options {
        int                     schedule_parametric;
        int                     schedule_outer_zero_distance;
        int                     schedule_maximize_band_depth;
-       int                     schedule_split_parallel;
+       int                     schedule_split_scaled;
        unsigned                schedule_algorithm;
        int                     schedule_fuse;
 };
index 4b5c1f2..9a2d757 100644 (file)
@@ -2228,42 +2228,45 @@ static int setup_carry_lp(isl_ctx *ctx, struct isl_sched_graph *graph)
        return 0;
 }
 
-/* If the schedule_split_parallel option is set and if the linear
- * parts of the scheduling rows for all nodes in the graphs are the same,
- * then split off the constant term from the linear part.
+/* If the schedule_split_scaled option is set and if the linear
+ * parts of the scheduling rows for all nodes in the graphs have
+ * non-trivial common divisor, then split off the constant term
+ * from the linear part.
  * The constant term is then placed in a separate band and
- * the linear part is simplified.
+ * the linear part is reduced.
  */
-static int split_parallel(isl_ctx *ctx, struct isl_sched_graph *graph)
+static int split_scaled(isl_ctx *ctx, struct isl_sched_graph *graph)
 {
        int i;
-       int equal = 1;
-       int row, cols;
-       struct isl_sched_node *node0;
+       int row;
+       isl_int gcd, gcd_i;
 
-       if (!ctx->opt->schedule_split_parallel)
+       if (!ctx->opt->schedule_split_scaled)
                return 0;
        if (graph->n <= 1)
                return 0;
 
-       node0 = &graph->node[0];
-       row = isl_mat_rows(node0->sched) - 1;
-       cols = isl_mat_cols(node0->sched);
-       for (i = 1; i < graph->n; ++i) {
+       isl_int_init(gcd);
+       isl_int_init(gcd_i);
+
+       isl_int_set_si(gcd, 0);
+
+       row = isl_mat_rows(graph->node[0].sched) - 1;
+
+       for (i = 0; i < graph->n; ++i) {
                struct isl_sched_node *node = &graph->node[i];
+               int cols = isl_mat_cols(node->sched);
 
-               if (isl_mat_cols(node->sched) != cols)
-                       return 0;
-               if (!isl_seq_eq(node0->sched->row[row] + 1,
-                               node->sched->row[row] + 1, cols - 1))
-                       return 0;
-               if (equal &&
-                   isl_int_ne(node0->sched->row[row][0],
-                              node->sched->row[row][0]))
-                       equal = 0;
+               isl_seq_gcd(node->sched->row[row] + 1, cols - 1, &gcd_i);
+               isl_int_gcd(gcd, gcd, gcd_i);
        }
-       if (equal)
+
+       isl_int_clear(gcd_i);
+
+       if (isl_int_cmp_si(gcd, 1) <= 0) {
+               isl_int_clear(gcd);
                return 0;
+       }
 
        next_band(graph);
 
@@ -2274,19 +2277,26 @@ static int split_parallel(isl_ctx *ctx, struct isl_sched_graph *graph)
                node->sched_map = NULL;
                node->sched = isl_mat_add_zero_rows(node->sched, 1);
                if (!node->sched)
-                       return -1;
-               isl_int_set(node->sched->row[row + 1][0],
-                           node->sched->row[row][0]);
-               isl_int_set_si(node->sched->row[row][0], 0);
-               node->sched = isl_mat_normalize_row(node->sched, row);
+                       goto error;
+               isl_int_fdiv_r(node->sched->row[row + 1][0],
+                              node->sched->row[row][0], gcd);
+               isl_int_fdiv_q(node->sched->row[row][0],
+                              node->sched->row[row][0], gcd);
+               isl_int_mul(node->sched->row[row][0],
+                           node->sched->row[row][0], gcd);
+               node->sched = isl_mat_scale_down_row(node->sched, row, gcd);
                if (!node->sched)
-                       return -1;
+                       goto error;
                node->band[graph->n_total_row] = graph->n_band;
        }
 
        graph->n_total_row++;
 
+       isl_int_clear(gcd);
        return 0;
+error:
+       isl_int_clear(gcd);
+       return -1;
 }
 
 /* Construct a schedule row for each node such that as many dependences
@@ -2326,7 +2336,7 @@ static int carry_dependences(isl_ctx *ctx, struct isl_sched_graph *graph)
        if (update_schedule(graph, sol, 0, 0) < 0)
                return -1;
 
-       if (split_parallel(ctx, graph) < 0)
+       if (split_scaled(ctx, graph) < 0)
                return -1;
 
        return compute_next_band(ctx, graph);