nir: add support for user defined select control
authorTimothy Arceri <tarceri@itsqueeze.com>
Wed, 20 Mar 2019 04:42:56 +0000 (15:42 +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 selection control support in
spirv and the GL support provided by EXT_control_flow_attributes.

Note this only supports if-statements as we dont support switches
in NIR.

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

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

index 0daafc4936daa77a28199536d3fb348e0d523567..73645912897f443a65f64538ef9f836a53d3dd88 100644 (file)
@@ -365,6 +365,8 @@ nir_if_create(nir_shader *shader)
 {
    nir_if *if_stmt = ralloc(shader, nir_if);
 
+   if_stmt->control = nir_selection_control_none;
+
    cf_init(&if_stmt->cf_node, nir_cf_node_if);
    src_init(&if_stmt->condition);
 
index 6e9b30a0e17c7f2c6eec61b2ce6a22cd0cc1389a..4285458cdf2a14af6d6ba9f97c7a315563492c65 100644 (file)
@@ -1902,9 +1902,16 @@ nir_block_ends_in_jump(nir_block *block)
 #define nir_foreach_instr_reverse_safe(instr, block) \
    foreach_list_typed_reverse_safe(nir_instr, instr, node, &(block)->instr_list)
 
+typedef enum {
+   nir_selection_control_none = 0x0,
+   nir_selection_control_flatten = 0x1,
+   nir_selection_control_dont_flatten = 0x2,
+} nir_selection_control;
+
 typedef struct nir_if {
    nir_cf_node cf_node;
    nir_src condition;
+   nir_selection_control control;
 
    struct exec_list then_list; /** < list of nir_cf_node */
    struct exec_list else_list; /** < list of nir_cf_node */
index 2dbab60d28bfc686ffa1ebf879975603e8c05d03..99aa1da4dc81fe0802a1249d3ae726ea5f7cacf2 100644 (file)
@@ -537,6 +537,7 @@ static nir_if *
 clone_if(clone_state *state, struct exec_list *cf_list, const nir_if *i)
 {
    nir_if *ni = nir_if_create(state->ns);
+   ni->control = i->control;
 
    __clone_src(state, ni, &ni->condition, &i->condition);
 
index 1deb02a380ea4489913293ab540b6dd11d3143be..a4020c83aca19684fa1bb2d38cfd0d326c020bc9 100644 (file)
@@ -191,6 +191,10 @@ nir_opt_peephole_select_block(nir_block *block, nir_shader *shader,
       return false;
 
    nir_if *if_stmt = nir_cf_node_as_if(prev_node);
+
+   if (if_stmt->control == nir_selection_control_dont_flatten)
+      return false;
+
    nir_block *then_block = nir_if_first_then_block(if_stmt);
    nir_block *else_block = nir_if_first_else_block(if_stmt);
 
@@ -199,6 +203,12 @@ nir_opt_peephole_select_block(nir_block *block, nir_shader *shader,
        nir_if_last_else_block(if_stmt) != else_block)
       return false;
 
+   if (if_stmt->control == nir_selection_control_flatten) {
+      /* Override driver defaults */
+      indirect_load_ok = true;
+      expensive_alu_ok = true;
+   }
+
    /* ... and those blocks must only contain "allowed" instructions. */
    unsigned count = 0;
    if (!block_check_for_allowed_instrs(then_block, &count, limit != 0,
@@ -207,7 +217,7 @@ nir_opt_peephole_select_block(nir_block *block, nir_shader *shader,
                                        indirect_load_ok, expensive_alu_ok))
       return false;
 
-   if (count > limit)
+   if (count > limit && if_stmt->control != nir_selection_control_flatten)
       return false;
 
    /* At this point, we know that the previous CFG node is an if-then