nir: Avoid coalescing vars created by lower_io_to_temporaries
authorConnor Abbott <cwabbott0@gmail.com>
Wed, 15 May 2019 10:49:29 +0000 (12:49 +0200)
committerConnor Abbott <cwabbott0@gmail.com>
Mon, 8 Jul 2019 12:14:53 +0000 (14:14 +0200)
Right now nir_copy_prop_vars is effectively undoing
nir_lower_io_to_temporaries for inputs by propagating the original
variable through the copy created in lower_io_to_temporaries. A
theoretical variable coalescing pass would have the same issue with
output variables, although that doesn't exist yet. To fix this, add a
new bit to nir_variable, and disable copy propagation when it's set.

This doesn't seem to affect any drivers now, probably since since no one
uses lower_io_to_temporaries for inputs as well as copy_prop_vars, but
it will fix radv once we flip on lower_io_to_temporaries for fs inputs.

Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
src/compiler/nir/nir.h
src/compiler/nir/nir_lower_io_to_temporaries.c
src/compiler/nir/nir_opt_copy_prop_vars.c

index 3119e656e24209b5d7fc468fdbc6e705978c9ce4..a2b3d393f1249a872d0c7e77dfe1e0f4ddea3d63 100644 (file)
@@ -227,6 +227,17 @@ typedef struct nir_variable {
       unsigned patch:1;
       unsigned invariant:1;
 
+      /**
+       * Can this variable be coalesced with another?
+       *
+       * This is set by nir_lower_io_to_temporaries to say that any
+       * copies involving this variable should stay put. Propagating it can
+       * duplicate the resulting load/store, which is not wanted, and may
+       * result in a load/store of the variable with an indirect offset which
+       * the backend may not be able to handle.
+       */
+      unsigned cannot_coalesce:1;
+
       /**
        * When separate shader programs are enabled, only input/outputs between
        * the stages of a multi-stage separate program can be safely removed
index d2b069d3d68a2f562c68415cd685309df2f3adc4..1f1f7af62a17e4c86f856631c2d1debdba78a02a 100644 (file)
@@ -123,6 +123,7 @@ create_shadow_temp(struct lower_io_state *state, nir_variable *var)
 {
    nir_variable *nvar = ralloc(state->shader, nir_variable);
    memcpy(nvar, var, sizeof *nvar);
+   nvar->data.cannot_coalesce = true;
 
    /* The original is now the temporary */
    nir_variable *temp = var;
index a1c8ffabf7a519ae5eacec646a20d91e147250ea..c65beb227562137be5a868cd883ecd07af00ecf3 100644 (file)
@@ -997,6 +997,14 @@ copy_prop_vars_block(struct copy_prop_var_state *state,
             };
          }
 
+         nir_variable *src_var = nir_deref_instr_get_variable(src);
+         if (src_var && src_var->data.cannot_coalesce) {
+            /* The source cannot be coaleseced, which means we can't propagate
+             * this copy.
+             */
+            break;
+         }
+
          struct copy_entry *dst_entry =
             get_entry_and_kill_aliases(copies, dst, full_mask);
          value_set_from_value(&dst_entry->src, &value, 0, full_mask);