nir,intel: lower if (cond) demote() to new intrinsic demote_if(cond)
authorDaniel Schürmann <daniel@schuermann.dev>
Thu, 18 Jul 2019 11:39:49 +0000 (13:39 +0200)
committerJason Ekstrand <jason@jlekstrand.net>
Wed, 24 Jul 2019 18:02:18 +0000 (13:02 -0500)
This will effectively enable the optimization in anv.

Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
src/compiler/nir/nir_gather_info.c
src/compiler/nir/nir_intrinsics.py
src/compiler/nir/nir_opt_conditional_discard.c
src/compiler/nir/nir_opt_constant_folding.c
src/intel/compiler/brw_fs_nir.cpp

index a7e258d6d9d8d85a3354f196b889b0a8082687c3..b6e6b0afd1f2da62c23445645302d6db8fef8778 100644 (file)
@@ -199,6 +199,7 @@ gather_intrinsic_info(nir_intrinsic_instr *instr, nir_shader *shader,
 {
    switch (instr->intrinsic) {
    case nir_intrinsic_demote:
+   case nir_intrinsic_demote_if:
    case nir_intrinsic_discard:
    case nir_intrinsic_discard_if:
       assert(shader->info.stage == MESA_SHADER_FRAGMENT);
index 373153a8db48feec0fcfe6344fe0836577850760..50823a1532cea01d1889830219b55cbd9a9871e4 100644 (file)
@@ -241,8 +241,9 @@ barrier("memory_barrier_shared")
 barrier("begin_invocation_interlock")
 barrier("end_invocation_interlock")
 
-# A conditional discard, with a single boolean source.
+# A conditional discard/demote, with a single boolean source.
 intrinsic("discard_if", src_comp=[1])
+intrinsic("demote_if", src_comp=[1])
 
 # ARB_shader_group_vote intrinsics
 intrinsic("vote_any", src_comp=[1], dest_comp=1, flags=[CAN_ELIMINATE])
index 3605eaf272f9ad922056e1e1b2421bb57f7f130e..781438df06ea63945097bd540b58d1b82a44de82 100644 (file)
@@ -26,7 +26,9 @@
 
 /** @file nir_opt_conditional_discard.c
  *
- * Handles optimization of lowering if (cond) discard to discard_if(cond).
+ * Handles optimization of lowering of
+ *  - if (cond) discard to discard_if(cond) and
+ *  - if (cond) demote to demote_if(cond)
  */
 
 static bool
@@ -73,30 +75,37 @@ nir_opt_conditional_discard_block(nir_builder *b, nir_block *block)
    }
 
    /* Get the first instruction in the then block and confirm it is
-    * a discard or a discard_if
+    * a discard or a demote instruction.
     */
    nir_instr *instr = nir_block_first_instr(then_block);
    if (instr->type != nir_instr_type_intrinsic)
       return false;
 
    nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
-   if (intrin->intrinsic != nir_intrinsic_discard &&
-       intrin->intrinsic != nir_intrinsic_discard_if)
-      return false;
-
-   nir_src cond;
-
+   nir_intrinsic_op op = intrin->intrinsic;
+   assert(if_stmt->condition.is_ssa);
+   nir_ssa_def *cond = if_stmt->condition.ssa;
    b->cursor = nir_before_cf_node(prev_node);
-   if (intrin->intrinsic == nir_intrinsic_discard)
-      cond = if_stmt->condition;
-   else
-      cond = nir_src_for_ssa(nir_iand(b,
-                                      nir_ssa_for_src(b, if_stmt->condition, 1),
-                                      nir_ssa_for_src(b, intrin->src[0], 1)));
+
+   switch (intrin->intrinsic) {
+   case nir_intrinsic_discard:
+      op = nir_intrinsic_discard_if;
+      break;
+   case nir_intrinsic_demote:
+      op = nir_intrinsic_demote_if;
+      break;
+   case nir_intrinsic_discard_if:
+   case nir_intrinsic_demote_if:
+      assert(intrin->src[0].is_ssa);
+      cond = nir_iand(b, cond, intrin->src[0].ssa);
+      break;
+   default:
+      return false;
+   }
 
    nir_intrinsic_instr *discard_if =
-      nir_intrinsic_instr_create(b->shader, nir_intrinsic_discard_if);
-   nir_src_copy(&discard_if->src[0], &cond, discard_if);
+      nir_intrinsic_instr_create(b->shader, op);
+   discard_if->src[0] = nir_src_for_ssa(cond);
 
    nir_instr_insert_before_cf(prev_node, &discard_if->instr);
    nir_instr_remove(&intrin->instr);
index 84dbce5ac30364403b14c127b63cc6246e91a67c..38d011536bb43a186cacc6431baa3ad1b7eab6ac 100644 (file)
@@ -119,7 +119,8 @@ constant_fold_intrinsic_instr(nir_intrinsic_instr *instr)
 {
    bool progress = false;
 
-   if (instr->intrinsic == nir_intrinsic_discard_if &&
+   if ((instr->intrinsic == nir_intrinsic_demote_if ||
+        instr->intrinsic == nir_intrinsic_discard_if) &&
        nir_src_is_const(instr->src[0])) {
       if (nir_src_as_bool(instr->src[0])) {
          /* This method of getting a nir_shader * from a nir_instr is
@@ -131,9 +132,11 @@ constant_fold_intrinsic_instr(nir_intrinsic_instr *instr)
          nir_function_impl *impl = nir_cf_node_get_function(cf_node);
          nir_shader *shader = impl->function->shader;
 
-         nir_intrinsic_instr *discard =
-            nir_intrinsic_instr_create(shader, nir_intrinsic_discard);
-         nir_instr_insert_before(&instr->instr, &discard->instr);
+         nir_intrinsic_op op = instr->intrinsic == nir_intrinsic_discard_if ?
+                               nir_intrinsic_discard :
+                               nir_intrinsic_demote;
+         nir_intrinsic_instr *new_instr = nir_intrinsic_instr_create(shader, op);
+         nir_instr_insert_before(&instr->instr, &new_instr->instr);
          nir_instr_remove(&instr->instr);
          progress = true;
       } else {
index 6ea012c74b62361165b2efaba04a93a830ddcebd..0b3982737dd2c86394dba75fa3b237dc19867f6b 100644 (file)
@@ -3568,6 +3568,7 @@ fs_visitor::nir_emit_fs_intrinsic(const fs_builder &bld,
 
    case nir_intrinsic_demote:
    case nir_intrinsic_discard:
+   case nir_intrinsic_demote_if:
    case nir_intrinsic_discard_if: {
       /* We track our discarded pixels in f0.1.  By predicating on it, we can
        * update just the flag bits that aren't yet discarded.  If there's no
@@ -3575,7 +3576,8 @@ fs_visitor::nir_emit_fs_intrinsic(const fs_builder &bld,
        * channels will get turned off.
        */
       fs_inst *cmp = NULL;
-      if (instr->intrinsic == nir_intrinsic_discard_if) {
+      if (instr->intrinsic == nir_intrinsic_demote_if ||
+          instr->intrinsic == nir_intrinsic_discard_if) {
          nir_alu_instr *alu = nir_src_as_alu_instr(instr->src[0]);
 
          if (alu != NULL &&