glsl_to_nir: fix crashes with int16 shifts
[mesa.git] / src / compiler / nir / nir_opt_dead_write_vars.c
index 2ae5f78b7911823c6c0ce03dd1ceaeffd90e54c6..b9d167a878e795d21c0703db2326df647157d509 100644 (file)
@@ -119,10 +119,11 @@ remove_dead_write_vars_local(void *mem_ctx, nir_block *block)
    nir_foreach_instr_safe(instr, block) {
       if (instr->type == nir_instr_type_call) {
          clear_unused_for_modes(&unused_writes, nir_var_shader_out |
-                                                nir_var_global |
-                                                nir_var_local |
-                                                nir_var_ssbo |
-                                                nir_var_shared);
+                                                nir_var_shader_temp |
+                                                nir_var_function_temp |
+                                                nir_var_mem_ssbo |
+                                                nir_var_mem_shared |
+                                                nir_var_mem_global);
          continue;
       }
 
@@ -131,11 +132,34 @@ remove_dead_write_vars_local(void *mem_ctx, nir_block *block)
 
       nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
       switch (intrin->intrinsic) {
-      case nir_intrinsic_barrier:
+      case nir_intrinsic_control_barrier:
+      case nir_intrinsic_group_memory_barrier:
       case nir_intrinsic_memory_barrier: {
          clear_unused_for_modes(&unused_writes, nir_var_shader_out |
-                                                nir_var_ssbo |
-                                                nir_var_shared);
+                                                nir_var_mem_ssbo |
+                                                nir_var_mem_shared |
+                                                nir_var_mem_global);
+         break;
+      }
+
+      case nir_intrinsic_memory_barrier_buffer:
+         clear_unused_for_modes(&unused_writes, nir_var_mem_ssbo |
+                                                nir_var_mem_global);
+         break;
+
+      case nir_intrinsic_memory_barrier_shared:
+         clear_unused_for_modes(&unused_writes, nir_var_mem_shared);
+         break;
+
+      case nir_intrinsic_memory_barrier_tcs_patch:
+         clear_unused_for_modes(&unused_writes, nir_var_shader_out);
+         break;
+
+      case nir_intrinsic_scoped_barrier: {
+         if (nir_intrinsic_memory_semantics(intrin) & NIR_MEMORY_RELEASE) {
+            clear_unused_for_modes(&unused_writes,
+                                   nir_intrinsic_memory_modes(intrin));
+         }
          break;
       }
 
@@ -153,6 +177,19 @@ remove_dead_write_vars_local(void *mem_ctx, nir_block *block)
 
       case nir_intrinsic_store_deref: {
          nir_deref_instr *dst = nir_src_as_deref(intrin->src[0]);
+
+         if (nir_intrinsic_access(intrin) & ACCESS_VOLATILE) {
+            /* Consider a volatile write to also be a sort of read.  This
+             * prevents us from deleting a non-volatile write just before a
+             * volatile write thanks to a non-volatile write afterwards.  It's
+             * quite the corner case, but this should be safer and more
+             * predictable for the programmer than allowing two non-volatile
+             * writes to be combined with a volatile write between them.
+             */
+            clear_unused_for_read(&unused_writes, dst);
+            break;
+         }
+
          nir_component_mask_t mask = nir_intrinsic_write_mask(intrin);
          progress |= update_unused_writes(&unused_writes, intrin, dst, mask);
          break;
@@ -162,6 +199,12 @@ remove_dead_write_vars_local(void *mem_ctx, nir_block *block)
          nir_deref_instr *src = nir_src_as_deref(intrin->src[1]);
          nir_deref_instr *dst = nir_src_as_deref(intrin->src[0]);
 
+         if (nir_intrinsic_dst_access(intrin) & ACCESS_VOLATILE) {
+            clear_unused_for_read(&unused_writes, src);
+            clear_unused_for_read(&unused_writes, dst);
+            break;
+         }
+
          /* Self-copy is removed. */
          if (nir_compare_derefs(src, dst) & nir_derefs_equal_bit) {
             nir_instr_remove(instr);
@@ -200,6 +243,8 @@ remove_dead_write_vars_impl(void *mem_ctx, nir_function_impl *impl)
    if (progress) {
       nir_metadata_preserve(impl, nir_metadata_block_index |
                                   nir_metadata_dominance);
+   } else {
+      nir_metadata_preserve(impl, nir_metadata_all);
    }
 
    return progress;