nir: add support for user defined loop control
authorTimothy Arceri <tarceri@itsqueeze.com>
Wed, 20 Mar 2019 02:39:36 +0000 (13:39 +1100)
committerTimothy Arceri <tarceri@itsqueeze.com>
Wed, 27 Mar 2019 02:39:12 +0000 (02:39 +0000)
This will allow us to make use of the loop control support in
spirv and the GL support provided by EXT_control_flow_attributes.

Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=108841

src/compiler/nir/nir.h
src/compiler/nir/nir_clone.c
src/compiler/nir/nir_opt_loop_unroll.c

index e53b501d95966dcb4c42f1b420494f174240d807..6e9b30a0e17c7f2c6eec61b2ce6a22cd0cc1389a 100644 (file)
@@ -1968,12 +1968,19 @@ typedef struct {
    struct list_head loop_terminator_list;
 } nir_loop_info;
 
+typedef enum {
+   nir_loop_control_none = 0x0,
+   nir_loop_control_unroll = 0x1,
+   nir_loop_control_dont_unroll = 0x2,
+} nir_loop_control;
+
 typedef struct {
    nir_cf_node cf_node;
 
    struct exec_list body; /** < list of nir_cf_node */
 
    nir_loop_info *info;
+   nir_loop_control control;
    bool partially_unrolled;
 } nir_loop;
 
index 9594eb8044d430d8cc2f5fbff2baaee1582301ad..2dbab60d28bfc686ffa1ebf879975603e8c05d03 100644 (file)
@@ -552,6 +552,7 @@ static nir_loop *
 clone_loop(clone_state *state, struct exec_list *cf_list, const nir_loop *loop)
 {
    nir_loop *nloop = nir_loop_create(state->ns);
+   nloop->control = loop->control;
    nloop->partially_unrolled = loop->partially_unrolled;
 
    nir_cf_node_insert_end(cf_list, &nloop->cf_node);
index b2696d4aadbbbd4bd99e7582ec010b3edbb3043d..c01983907495d5d4e57303252c85fdfc87466cad 100644 (file)
@@ -770,11 +770,20 @@ partial_unroll(nir_shader *shader, nir_loop *loop, unsigned trip_count)
    _mesa_hash_table_destroy(remap_table, NULL);
 }
 
+/*
+ * Returns true if we should unroll the loop, otherwise false.
+ */
 static bool
-is_loop_small_enough_to_unroll(nir_shader *shader, nir_loop_info *li)
+check_unrolling_restrictions(nir_shader *shader, nir_loop *loop)
 {
-   unsigned max_iter = shader->options->max_unroll_iterations;
+   if (loop->control == nir_loop_control_unroll)
+      return true;
 
+   if (loop->control == nir_loop_control_dont_unroll)
+      return false;
+
+   nir_loop_info *li = loop->info;
+   unsigned max_iter = shader->options->max_unroll_iterations;
    unsigned trip_count =
       li->max_trip_count ? li->max_trip_count : li->guessed_trip_count;
 
@@ -822,7 +831,7 @@ process_loops(nir_shader *sh, nir_cf_node *cf_node, bool *has_nested_loop_out)
    /* Don't attempt to unroll a second inner loop in this pass, wait until the
     * next pass as we have altered the cf.
     */
-   if (!progress) {
+   if (!progress && loop->control != nir_loop_control_dont_unroll) {
 
       /* Check for the classic
        *
@@ -848,7 +857,7 @@ process_loops(nir_shader *sh, nir_cf_node *cf_node, bool *has_nested_loop_out)
          unsigned num_lt = list_length(&loop->info->loop_terminator_list);
          if (!has_nested_loop && num_lt == 1 && !loop->partially_unrolled &&
              loop->info->guessed_trip_count &&
-             is_loop_small_enough_to_unroll(sh, loop->info)) {
+             check_unrolling_restrictions(sh, loop)) {
             partial_unroll(sh, loop, loop->info->guessed_trip_count);
             progress = true;
          }
@@ -857,7 +866,7 @@ process_loops(nir_shader *sh, nir_cf_node *cf_node, bool *has_nested_loop_out)
       if (has_nested_loop || !loop->info->limiting_terminator)
          goto exit;
 
-      if (!is_loop_small_enough_to_unroll(sh, loop->info))
+      if (!check_unrolling_restrictions(sh, loop))
          goto exit;
 
       if (loop->info->exact_trip_count_known) {