glsl_to_nir: fix crashes with int16 shifts
[mesa.git] / src / compiler / nir / nir_opt_dead_write_vars.c
index ffe0de771daf8584ec39896612d074b3b853b33e..b9d167a878e795d21c0703db2326df647157d509 100644 (file)
@@ -122,7 +122,8 @@ remove_dead_write_vars_local(void *mem_ctx, nir_block *block)
                                                 nir_var_shader_temp |
                                                 nir_var_function_temp |
                                                 nir_var_mem_ssbo |
-                                                nir_var_mem_shared);
+                                                nir_var_mem_shared |
+                                                nir_var_mem_global);
          continue;
       }
 
@@ -131,24 +132,30 @@ 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_mem_ssbo |
-                                                nir_var_mem_shared);
+                                                nir_var_mem_shared |
+                                                nir_var_mem_global);
          break;
       }
 
       case nir_intrinsic_memory_barrier_buffer:
-      case nir_intrinsic_memory_barrier_atomic_counter:
-         clear_unused_for_modes(&unused_writes, nir_var_mem_ssbo);
+         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_scoped_memory_barrier: {
+      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));
@@ -170,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;
@@ -179,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);
@@ -217,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;