return state.progress;
 }
 
+static void
+nir_deref_instr_fixup_child_types(nir_deref_instr *parent)
+{
+   nir_foreach_use(use, &parent->dest.ssa) {
+      if (use->parent_instr->type != nir_instr_type_deref)
+         continue;
+
+      nir_deref_instr *child = nir_instr_as_deref(use->parent_instr);
+      switch (child->deref_type) {
+      case nir_deref_type_var:
+         unreachable("nir_deref_type_var cannot be a child");
+
+      case nir_deref_type_array:
+      case nir_deref_type_array_wildcard:
+         child->type = glsl_get_array_element(parent->type);
+         break;
+
+      case nir_deref_type_ptr_as_array:
+         child->type = parent->type;
+         break;
+
+      case nir_deref_type_struct:
+         child->type = glsl_get_struct_field(parent->type,
+                                             child->strct.index);
+         break;
+
+      case nir_deref_type_cast:
+         /* We stop the recursion here */
+         continue;
+      }
+
+      /* Recurse into children */
+      nir_deref_instr_fixup_child_types(child);
+   }
+}
+
 static bool
 is_trivial_array_deref_cast(nir_deref_instr *cast)
 {
    return true;
 }
 
+static bool
+opt_remove_sampler_cast(nir_deref_instr *cast)
+{
+   assert(cast->deref_type == nir_deref_type_cast);
+   nir_deref_instr *parent = nir_src_as_deref(cast->parent);
+   if (parent == NULL)
+      return false;
+
+   /* Strip both types down to their non-array type and bail if there are any
+    * discrepancies in array lengths.
+    */
+   const struct glsl_type *parent_type = parent->type;
+   const struct glsl_type *cast_type = cast->type;
+   while (glsl_type_is_array(parent_type) && glsl_type_is_array(cast_type)) {
+      if (glsl_get_length(parent_type) != glsl_get_length(cast_type))
+         return false;
+      parent_type = glsl_get_array_element(parent_type);
+      cast_type = glsl_get_array_element(cast_type);
+   }
+
+   if (glsl_type_is_array(parent_type) || glsl_type_is_array(cast_type))
+      return false;
+
+   if (!glsl_type_is_sampler(parent_type) ||
+       cast_type != glsl_bare_sampler_type())
+      return false;
+
+   /* We're a cast from a more detailed sampler type to a bare sampler */
+   nir_ssa_def_rewrite_uses(&cast->dest.ssa,
+                            nir_src_for_ssa(&parent->dest.ssa));
+   nir_instr_remove(&cast->instr);
+
+   /* Recursively crawl the deref tree and clean up types */
+   nir_deref_instr_fixup_child_types(parent);
+
+   return true;
+}
+
 /**
  * Is this casting a struct to a contained struct.
  * struct a { struct b field0 };
    if (opt_replace_struct_wrapper_cast(b, cast))
       return true;
 
+   if (opt_remove_sampler_cast(cast))
+      return true;
+
    progress = opt_remove_cast_cast(cast);
    if (!is_trivial_deref_cast(cast))
       return progress;