nir: strip as we serialize to remove the nir_shader_clone call
authorMarek Olšák <marek.olsak@amd.com>
Mon, 4 Nov 2019 23:09:26 +0000 (18:09 -0500)
committerMarek Olšák <marek.olsak@amd.com>
Thu, 21 Nov 2019 23:49:57 +0000 (18:49 -0500)
Serializing stripped NIR is faster now.

Reviewed-by: Connor Abbott <cwabbott0@gmail.com>
src/compiler/Makefile.sources
src/compiler/nir/meson.build
src/compiler/nir/nir.h
src/compiler/nir/nir_serialize.c
src/compiler/nir/nir_strip.c [deleted file]

index 7b593059834a337fb32c62f5cbe06b29a864c1e1..0ca94d41d29b2052743e7710f11ecace91fa572c 100644 (file)
@@ -331,7 +331,6 @@ NIR_FILES = \
        nir/nir_search_helpers.h \
        nir/nir_serialize.c \
        nir/nir_serialize.h \
-       nir/nir_strip.c \
        nir/nir_split_per_member_structs.c \
        nir/nir_split_var_copies.c \
        nir/nir_split_vars.c \
index b114623d3b3eea47b2646d1f0ef80a21299cd7df..0a5440c806bee254d0ceb931d872063046036da6 100644 (file)
@@ -213,7 +213,6 @@ files_libnir = files(
   'nir_search_helpers.h',
   'nir_serialize.c',
   'nir_serialize.h',
-  'nir_strip.c',
   'nir_split_per_member_structs.c',
   'nir_split_var_copies.c',
   'nir_split_vars.c',
index bae8c821243fb5b35ae863b98cd21218200b6da0..1333a49c66fc64240cf4d3d1b1e4222f5fcda6ba 100644 (file)
@@ -4192,8 +4192,6 @@ bool nir_opt_vectorize(nir_shader *shader);
 
 bool nir_opt_conditional_discard(nir_shader *shader);
 
-void nir_strip(nir_shader *shader);
-
 void nir_sweep(nir_shader *shader);
 
 void nir_remap_dual_slot_attributes(nir_shader *shader,
index 183985452202fcffcfe628004908f94eb292ea4e..b8422209e7d6f7d8cec9a01083e9725ec58557f8 100644 (file)
@@ -49,6 +49,9 @@ typedef struct {
     * be resolved in the second pass.
     */
    struct util_dynarray phi_fixups;
+
+   /* Don't write optional data such as variable names. */
+   bool strip;
 } write_ctx;
 
 typedef struct {
@@ -159,7 +162,7 @@ write_variable(write_ctx *ctx, const nir_variable *var)
    union packed_var flags;
    flags.u32 = 0;
 
-   flags.u.has_name = !!(var->name);
+   flags.u.has_name = !ctx->strip && var->name;
    flags.u.has_constant_initializer = !!(var->constant_initializer);
    flags.u.has_interface_type = !!(var->interface_type);
    flags.u.num_state_slots = var->num_state_slots;
@@ -167,9 +170,21 @@ write_variable(write_ctx *ctx, const nir_variable *var)
 
    blob_write_uint32(ctx->blob, flags.u32);
 
-   if (var->name)
+   if (flags.u.has_name)
       blob_write_string(ctx->blob, var->name);
-   blob_write_bytes(ctx->blob, (uint8_t *) &var->data, sizeof(var->data));
+
+   struct nir_variable_data data = var->data;
+
+   /* When stripping, we expect that the location is no longer needed,
+    * which is typically after shaders are linked.
+    */
+   if (ctx->strip &&
+       data.mode != nir_var_shader_in &&
+       data.mode != nir_var_shader_out)
+      data.location = 0;
+
+   blob_write_bytes(ctx->blob, &data, sizeof(data));
+
    for (unsigned i = 0; i < var->num_state_slots; i++) {
       blob_write_bytes(ctx->blob, &var->state_slots[i],
                        sizeof(var->state_slots[i]));
@@ -258,8 +273,8 @@ write_register(write_ctx *ctx, const nir_register *reg)
    blob_write_uint32(ctx->blob, reg->bit_size);
    blob_write_uint32(ctx->blob, reg->num_array_elems);
    blob_write_uint32(ctx->blob, reg->index);
-   blob_write_uint32(ctx->blob, !!(reg->name));
-   if (reg->name)
+   blob_write_uint32(ctx->blob, !ctx->strip && reg->name);
+   if (!ctx->strip && reg->name)
       blob_write_string(ctx->blob, reg->name);
 }
 
@@ -357,7 +372,7 @@ write_dest(write_ctx *ctx, const nir_dest *dst)
 {
    uint32_t val = dst->is_ssa;
    if (dst->is_ssa) {
-      val |= !!(dst->ssa.name) << 1;
+      val |= (!ctx->strip && dst->ssa.name) << 1;
       val |= dst->ssa.num_components << 2;
       val |= dst->ssa.bit_size << 5;
    } else {
@@ -366,7 +381,7 @@ write_dest(write_ctx *ctx, const nir_dest *dst)
    blob_write_uint32(ctx->blob, val);
    if (dst->is_ssa) {
       write_add_object(ctx, &dst->ssa);
-      if (dst->ssa.name)
+      if (!ctx->strip && dst->ssa.name)
          blob_write_string(ctx->blob, dst->ssa.name);
    } else {
       blob_write_uint32(ctx->blob, write_lookup_object(ctx, dst->reg.reg));
@@ -1120,40 +1135,36 @@ read_function(read_ctx *ctx)
       fxn->impl = NIR_SERIALIZE_FUNC_HAS_IMPL;
 }
 
+/**
+ * Serialize NIR into a binary blob.
+ *
+ * \param strip  Don't serialize information only useful for debugging,
+ *               such as variable names, making cache hits from similar
+ *               shaders more likely.
+ */
 void
 nir_serialize(struct blob *blob, const nir_shader *nir, bool strip)
 {
-   nir_shader *stripped = NULL;
-
-   if (strip) {
-      /* Drop unnecessary information (like variable names), so the serialized
-       * NIR is smaller, and also to let us detect more isomorphic shaders
-       * when hashing, increasing cache hits.
-       */
-      stripped = nir_shader_clone(NULL, nir);
-      nir_strip(stripped);
-      nir = stripped;
-   }
-
    write_ctx ctx;
    ctx.remap_table = _mesa_pointer_hash_table_create(NULL);
    ctx.next_idx = 0;
    ctx.blob = blob;
    ctx.nir = nir;
+   ctx.strip = strip;
    util_dynarray_init(&ctx.phi_fixups, NULL);
 
    size_t idx_size_offset = blob_reserve_uint32(blob);
 
    struct shader_info info = nir->info;
    uint32_t strings = 0;
-   if (info.name)
+   if (!strip && info.name)
       strings |= 0x1;
-   if (info.label)
+   if (!strip && info.label)
       strings |= 0x2;
    blob_write_uint32(blob, strings);
-   if (info.name)
+   if (!strip && info.name)
       blob_write_string(blob, info.name);
-   if (info.label)
+   if (!strip && info.label)
       blob_write_string(blob, info.label);
    info.name = info.label = NULL;
    blob_write_bytes(blob, (uint8_t *) &info, sizeof(info));
@@ -1189,9 +1200,6 @@ nir_serialize(struct blob *blob, const nir_shader *nir, bool strip)
 
    _mesa_hash_table_destroy(ctx.remap_table, NULL);
    util_dynarray_fini(&ctx.phi_fixups);
-
-   if (strip)
-      ralloc_free(stripped);
 }
 
 nir_shader *
diff --git a/src/compiler/nir/nir_strip.c b/src/compiler/nir/nir_strip.c
deleted file mode 100644 (file)
index ba7465c..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright © 2019 Valve Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- */
-
-#include "nir.h"
-#include "util/debug.h"
-
-/* This pass removes information which is only useful for debugging,
- * making cache hits from similar shaders more likely.
- */
-
-static void
-strip_variable(nir_variable *var)
-{
-   var->name = NULL;
-
-   if (var->data.mode != nir_var_shader_in &&
-       var->data.mode != nir_var_shader_out) {
-      /* We assume that this is called after nir_lower_io(), at which point
-       * the original user-facing location is irrelevant except for inputs and
-       * outputs.
-       */
-      var->data.location = 0;
-   }
-}
-
-static void
-strip_register(nir_register *reg)
-{
-   reg->name = NULL;
-}
-
-static bool
-strip_def(nir_ssa_def *def, void *_unused)
-{
-   (void) _unused;
-   def->name = NULL;
-   return true;
-}
-
-static void
-strip_impl(nir_function_impl *impl)
-{
-   nir_index_ssa_defs(impl);
-
-   nir_foreach_variable(var, &impl->locals)
-      strip_variable(var);
-   nir_foreach_register(reg, &impl->registers)
-      strip_register(reg);
-   nir_foreach_block(block, impl) {
-      nir_foreach_instr(instr, block) {
-         nir_foreach_ssa_def(instr, strip_def, NULL);
-      }
-   }
-}
-
-void
-nir_strip(nir_shader *shader)
-{
-   static int should_strip = -1;
-   if (should_strip < 0)
-      should_strip = env_var_as_boolean("NIR_STRIP", true);
-   if (!should_strip)
-      return;
-
-   shader->info.name = NULL;
-   shader->info.label = NULL;
-
-   nir_foreach_variable(var, &shader->uniforms)
-      strip_variable(var);
-   nir_foreach_variable(var, &shader->inputs)
-      strip_variable(var);
-   nir_foreach_variable(var, &shader->outputs)
-      strip_variable(var);
-   nir_foreach_variable(var, &shader->system_values)
-      strip_variable(var);
-   nir_foreach_variable(var, &shader->globals)
-      strip_variable(var);
-
-   nir_foreach_function(func, shader) {
-      if (func->impl)
-         strip_impl(func->impl);
-   }
-}