nir: Use a switch in nir_inline_function_impl
[mesa.git] / src / compiler / nir / nir_inline_functions.c
index 4e0bb8fcba138a6ece15a58c2b60980cab21b368..03a26e0dbf3e79b21832157d1bcc0bc2c8e0a891 100644 (file)
 #include "nir_control_flow.h"
 #include "nir_vla.h"
 
+void nir_inline_function_impl(struct nir_builder *b,
+                              const nir_function_impl *impl,
+                              nir_ssa_def **params)
+{
+   nir_function_impl *copy = nir_function_impl_clone(b->shader, impl);
+
+   /* Insert a nop at the cursor so we can keep track of where things are as
+    * we add/remove stuff from the CFG.
+    */
+   nir_intrinsic_instr *nop =
+      nir_intrinsic_instr_create(b->shader, nir_intrinsic_nop);
+   nir_builder_instr_insert(b, &nop->instr);
+
+   exec_list_append(&b->impl->locals, &copy->locals);
+   exec_list_append(&b->impl->registers, &copy->registers);
+
+   nir_foreach_block(block, copy) {
+      nir_foreach_instr_safe(instr, block) {
+         switch (instr->type) {
+         case nir_instr_type_intrinsic: {
+            nir_intrinsic_instr *load = nir_instr_as_intrinsic(instr);
+            if (load->intrinsic != nir_intrinsic_load_param)
+               break;
+
+            unsigned param_idx = nir_intrinsic_param_idx(load);
+            assert(param_idx < impl->function->num_params);
+            assert(load->dest.is_ssa);
+            nir_ssa_def_rewrite_uses(&load->dest.ssa,
+                                     nir_src_for_ssa(params[param_idx]));
+
+            /* Remove any left-over load_param intrinsics because they're soon
+             * to be in another function and therefore no longer valid.
+             */
+            nir_instr_remove(&load->instr);
+            break;
+         }
+
+         case nir_instr_type_jump:
+            /* Returns have to be lowered for this to work */
+            assert(nir_instr_as_jump(instr)->type != nir_jump_return);
+            break;
+
+         default:
+            break;
+         }
+      }
+   }
+
+   /* Pluck the body out of the function and place it here */
+   nir_cf_list body;
+   nir_cf_list_extract(&body, &copy->body);
+   nir_cf_reinsert(&body, nir_before_instr(&nop->instr));
+
+   b->cursor = nir_instr_remove(&nop->instr);
+}
+
 static bool inline_function_impl(nir_function_impl *impl, struct set *inlined);
 
 static bool
@@ -49,16 +105,10 @@ inline_functions_block(nir_block *block, nir_builder *b,
       nir_call_instr *call = nir_instr_as_call(instr);
       assert(call->callee->impl);
 
+      /* Make sure that the function we're calling is already inlined */
       inline_function_impl(call->callee->impl, inlined);
 
-      nir_function_impl *callee_copy =
-         nir_function_impl_clone(call->callee->impl);
-      callee_copy->function = call->callee;
-
-      exec_list_append(&b->impl->locals, &callee_copy->locals);
-      exec_list_append(&b->impl->registers, &callee_copy->registers);
-
-      b->cursor = nir_before_instr(&call->instr);
+      b->cursor = nir_instr_remove(&call->instr);
 
       /* Rewrite all of the uses of the callee's parameters to use the call
        * instructions sources.  In order to ensure that the "load" happens
@@ -72,34 +122,7 @@ inline_functions_block(nir_block *block, nir_builder *b,
                                      call->callee->params[i].num_components);
       }
 
-      nir_foreach_block(block, callee_copy) {
-         nir_foreach_instr_safe(instr, block) {
-            if (instr->type != nir_instr_type_intrinsic)
-               continue;
-
-            nir_intrinsic_instr *load = nir_instr_as_intrinsic(instr);
-            if (load->intrinsic != nir_intrinsic_load_param)
-               continue;
-
-            unsigned param_idx = nir_intrinsic_param_idx(load);
-            assert(param_idx < num_params);
-            assert(load->dest.is_ssa);
-            nir_ssa_def_rewrite_uses(&load->dest.ssa,
-                                     nir_src_for_ssa(params[param_idx]));
-
-            /* Remove any left-over load_param intrinsics because they're soon
-             * to be in another function and therefore no longer valid.
-             */
-            nir_instr_remove(&load->instr);
-         }
-      }
-
-      /* Pluck the body out of the function and place it here */
-      nir_cf_list body;
-      nir_cf_list_extract(&body, &callee_copy->body);
-      nir_cf_reinsert(&body, b->cursor);
-
-      nir_instr_remove(&call->instr);
+      nir_inline_function_impl(b, call->callee->impl, params);
    }
 
    return progress;
@@ -126,9 +149,7 @@ inline_function_impl(nir_function_impl *impl, struct set *inlined)
 
       nir_metadata_preserve(impl, nir_metadata_none);
    } else {
-#ifndef NDEBUG
-      impl->valid_metadata &= ~nir_metadata_not_properly_reset;
-#endif
+      nir_metadata_preserve(impl, nir_metadata_all);
    }
 
    _mesa_set_add(inlined, impl);
@@ -141,7 +162,7 @@ inline_function_impl(nir_function_impl *impl, struct set *inlined)
  * For most use-cases, function inlining is a multi-step process.  The general
  * pattern employed by SPIR-V consumers and others is as follows:
  *
- *  1. nir_lower_constant_initializers(shader, nir_var_function)
+ *  1. nir_lower_variable_initializers(shader, nir_var_function_temp)
  *
  *     This is needed because local variables from the callee are simply added
  *     to the locals list for the caller and the information about where the
@@ -196,7 +217,7 @@ inline_function_impl(nir_function_impl *impl, struct set *inlined)
  *    spirv_to_nir returns the root function and so we can just use == whereas
  *    with GL, you may have to look for a function named "main".
  *
- *  6. nir_lower_constant_initializers(shader, ~nir_var_function)
+ *  6. nir_lower_variable_initializers(shader, ~nir_var_function_temp)
  *
  *     Lowering constant initializers on inputs, outputs, global variables,
  *     etc. requires that we know the main entrypoint so that we know where to