*num_variables = 0;
    *num_blocks = 0;
 
-   nir_foreach_variable(var, &shader->Program->nir->uniforms) {
+   nir_foreach_variable_in_shader(var, shader->Program->nir) {
       if (block_type == BLOCK_UBO && !nir_variable_is_in_ubo(var))
          continue;
 
    unsigned variable_index = 0;
    struct gl_uniform_block *blks = *blocks;
 
-   nir_foreach_variable(var, &shader->Program->nir->uniforms) {
+   nir_foreach_variable_in_shader(var, shader->Program->nir) {
       if (block_type == BLOCK_UBO && !nir_variable_is_in_ubo(var))
          continue;
 
 
 };
 
 #define nir_foreach_gl_uniform_variable(var, shader) \
-   nir_foreach_variable(var, &(shader)->uniforms)
+   nir_foreach_variable_with_modes(var, shader, nir_var_uniform | \
+                                                nir_var_mem_ubo | \
+                                                nir_var_mem_ssbo)
 
 bool gl_nir_link_spirv(struct gl_context *ctx,
                        struct gl_shader_program *prog,
 
 {
    nir_shader *shader = rzalloc(mem_ctx, nir_shader);
 
-   exec_list_make_empty(&shader->uniforms);
-   exec_list_make_empty(&shader->inputs);
-   exec_list_make_empty(&shader->outputs);
-   exec_list_make_empty(&shader->shared);
+   exec_list_make_empty(&shader->variables);
 
    shader->options = options;
 
    }
 
    exec_list_make_empty(&shader->functions);
-   exec_list_make_empty(&shader->globals);
-   exec_list_make_empty(&shader->system_values);
 
    shader->num_inputs = 0;
    shader->num_outputs = 0;
    exec_node_remove(®->node);
 }
 
-struct exec_list *
-nir_variable_list_for_mode(nir_shader *shader, nir_variable_mode mode)
+void
+nir_shader_add_variable(nir_shader *shader, nir_variable *var)
 {
-   switch (mode) {
+   switch (var->data.mode) {
    case nir_var_function_temp:
       assert(!"nir_shader_add_variable cannot be used for local variables");
-      return NULL;
+      return;
 
    case nir_var_shader_temp:
-      return &shader->globals;
-
    case nir_var_shader_in:
-      return &shader->inputs;
-
    case nir_var_shader_out:
-      return &shader->outputs;
-
    case nir_var_uniform:
    case nir_var_mem_ubo:
    case nir_var_mem_ssbo:
-      return &shader->uniforms;
-
    case nir_var_mem_shared:
-      assert(gl_shader_stage_is_compute(shader->info.stage));
-      return &shader->shared;
+   case nir_var_system_value:
+      break;
 
    case nir_var_mem_global:
       assert(!"nir_shader_add_variable cannot be used for global memory");
-      return NULL;
-
-   case nir_var_system_value:
-      return &shader->system_values;
+      return;
 
    case nir_var_mem_push_const:
       assert(!"nir_var_push_constant is not supposed to be used for variables");
-      return NULL;
+      return;
 
    default:
       assert(!"invalid mode");
-      return NULL;
+      return;
    }
-}
 
-void
-nir_shader_add_variable(nir_shader *shader, nir_variable *var)
-{
-   struct exec_list *var_list =
-      nir_variable_list_for_mode(shader, var->data.mode);
-   if (var_list)
-      exec_list_push_tail(var_list, &var->node);
+   exec_list_push_tail(&shader->variables, &var->node);
 }
 
 nir_variable *
    return index;
 }
 
-static void
-index_var_list(struct exec_list *list, unsigned *count)
-{
-   nir_foreach_variable(var, list)
-      var->index = (*count)++;
-}
-
 unsigned
 nir_shader_index_vars(nir_shader *shader, nir_variable_mode modes)
 {
    unsigned count = 0;
-   if (modes & nir_var_shader_temp)
-      index_var_list(&shader->globals, &count);
-
-   if (modes & nir_var_shader_in)
-      index_var_list(&shader->inputs, &count);
-
-   if (modes & nir_var_shader_out)
-      index_var_list(&shader->outputs, &count);
-
-   if (modes & (nir_var_uniform | nir_var_mem_ubo | nir_var_mem_ssbo))
-      index_var_list(&shader->uniforms, &count);
-
-   if (modes & nir_var_mem_shared)
-      index_var_list(&shader->shared, &count);
-
-   if (modes & nir_var_system_value)
-      index_var_list(&shader->system_values, &count);
-
+   nir_foreach_variable_with_modes(var, shader, modes)
+      var->index = count++;
    return count;
 }
 
 nir_function_impl_index_vars(nir_function_impl *impl)
 {
    unsigned count = 0;
-   index_var_list(&impl->locals, &count);
+   nir_foreach_function_temp_variable(var, impl)
+      var->index = count++;
    return count;
 }
 
 
    struct nir_variable_data *members;
 } nir_variable;
 
-
 static inline bool
 _nir_shader_variable_has_mode(nir_variable *var, unsigned modes)
 {
    return var->data.mode & modes;
 }
 
-#define nir_foreach_variable(var, var_list) \
+#define nir_foreach_variable_in_list(var, var_list) \
    foreach_list_typed(nir_variable, var, node, var_list)
 
-#define nir_foreach_variable_safe(var, var_list) \
+#define nir_foreach_variable_in_list_safe(var, var_list) \
    foreach_list_typed_safe(nir_variable, var, node, var_list)
 
+#define nir_foreach_variable_in_shader(var, shader) \
+   nir_foreach_variable_in_list(var, &(shader)->variables)
+
+#define nir_foreach_variable_in_shader_safe(var, shader) \
+   nir_foreach_variable_in_list_safe(var, &(shader)->variables)
+
 #define nir_foreach_variable_with_modes(var, shader, modes) \
-   nir_foreach_variable(var, nir_variable_list_for_mode(shader, modes)) \
+   nir_foreach_variable_in_shader(var, shader) \
       if (_nir_shader_variable_has_mode(var, modes))
 
 #define nir_foreach_variable_with_modes_safe(var, shader, modes) \
-   nir_foreach_variable_safe(var, nir_variable_list_for_mode(shader, modes)) \
+   nir_foreach_variable_in_shader_safe(var, shader) \
       if (_nir_shader_variable_has_mode(var, modes))
 
 #define nir_foreach_shader_in_variable(var, shader) \
-   nir_foreach_variable(var, &(shader)->inputs)
+   nir_foreach_variable_with_modes(var, shader, nir_var_shader_in)
 
 #define nir_foreach_shader_in_variable_safe(var, shader) \
-   nir_foreach_variable_safe(var, &(shader)->inputs)
+   nir_foreach_variable_with_modes_safe(var, shader, nir_var_shader_in)
 
 #define nir_foreach_shader_out_variable(var, shader) \
-   nir_foreach_variable(var, &(shader)->outputs)
+   nir_foreach_variable_with_modes(var, shader, nir_var_shader_out)
 
 #define nir_foreach_shader_out_variable_safe(var, shader) \
-   nir_foreach_variable_safe(var, &(shader)->outputs)
+   nir_foreach_variable_with_modes_safe(var, shader, nir_var_shader_out)
 
 #define nir_foreach_uniform_variable(var, shader) \
-   nir_foreach_variable(var, &(shader)->uniforms) \
-      if (var->data.mode == nir_var_uniform)
+   nir_foreach_variable_with_modes(var, shader, nir_var_uniform)
 
 #define nir_foreach_uniform_variable_safe(var, shader) \
-   nir_foreach_variable_safe(var, &(shader)->uniforms) \
-      if (var->data.mode == nir_var_uniform)
+   nir_foreach_variable_with_modes_safe(var, shader, nir_var_uniform)
 
 static inline bool
 nir_variable_is_global(const nir_variable *var)
 
 typedef struct nir_shader {
    /** list of uniforms (nir_variable) */
-   struct exec_list uniforms;
-
-   /** list of inputs (nir_variable) */
-   struct exec_list inputs;
-
-   /** list of outputs (nir_variable) */
-   struct exec_list outputs;
-
-   /** list of shared compute variables (nir_variable) */
-   struct exec_list shared;
+   struct exec_list variables;
 
    /** Set of driver-specific options for the shader.
     *
    /** Various bits of compile-time information about a given shader */
    struct shader_info info;
 
-   /** list of global variables in the shader (nir_variable) */
-   struct exec_list globals;
-
-   /** list of system value variables in the shader (nir_variable) */
-   struct exec_list system_values;
-
    struct exec_list functions; /** < list of nir_function */
 
    /**
 
 void nir_reg_remove(nir_register *reg);
 
-struct exec_list *
-nir_variable_list_for_mode(nir_shader *shader, nir_variable_mode mode);
-
 /** Adds a variable to the appropriate list in nir_shader */
 void nir_shader_add_variable(nir_shader *shader, nir_variable *var);
 
 
    nir_shader *ns = nir_shader_create(mem_ctx, s->info.stage, s->options, NULL);
    state.ns = ns;
 
-   clone_var_list(&state, &ns->uniforms, &s->uniforms);
-   clone_var_list(&state, &ns->inputs,   &s->inputs);
-   clone_var_list(&state, &ns->outputs,  &s->outputs);
-   clone_var_list(&state, &ns->shared,   &s->shared);
-   clone_var_list(&state, &ns->globals,  &s->globals);
-   clone_var_list(&state, &ns->system_values, &s->system_values);
+   clone_var_list(&state, &ns->variables, &s->variables);
 
    /* Go through and clone functions */
    foreach_list_typed(nir_function, fxn, node, &s->functions)
    /* We have to move all the linked lists over separately because we need the
     * pointers in the list elements to point to the lists in dst and not src.
     */
-   exec_list_move_nodes_to(&src->uniforms,      &dst->uniforms);
-   exec_list_move_nodes_to(&src->inputs,        &dst->inputs);
-   exec_list_move_nodes_to(&src->outputs,       &dst->outputs);
-   exec_list_move_nodes_to(&src->shared,        &dst->shared);
-   exec_list_move_nodes_to(&src->globals,       &dst->globals);
-   exec_list_move_nodes_to(&src->system_values, &dst->system_values);
+   exec_list_move_nodes_to(&src->variables, &dst->variables);
 
    /* Now move the functions over.  This takes a tiny bit more work */
    exec_list_move_nodes_to(&src->functions, &dst->functions);
 
    uint64_t *used;
 
    assert(mode == nir_var_shader_in || mode == nir_var_shader_out);
-   struct exec_list *var_list = nir_variable_list_for_mode(shader, mode);
 
-   nir_foreach_variable_safe(var, var_list) {
+   nir_foreach_variable_with_modes_safe(var, shader, mode) {
       if (var->data.patch)
          used = used_by_other_stage_patches;
       else
          var->data.location = 0;
          var->data.mode = nir_var_shader_temp;
 
-         exec_node_remove(&var->node);
-         exec_list_push_tail(&shader->globals, &var->node);
-
          progress = true;
       }
    }
 static void
 insert_sorted(struct exec_list *var_list, nir_variable *new_var)
 {
-   nir_foreach_variable(var, var_list) {
+   nir_foreach_variable_in_list(var, var_list) {
       if (var->data.location > new_var->data.location) {
          exec_node_insert_node_before(&var->node, &new_var->node);
          return;
 
    int UNUSED last_loc = 0;
    bool last_partial = false;
-   nir_foreach_variable(var, &io_vars) {
+   nir_foreach_variable_in_list(var, &io_vars) {
       const struct glsl_type *type = var->type;
       if (nir_is_per_vertex_io(var, stage) || var->data.per_view) {
          assert(glsl_type_is_array(type));
    if (last_partial)
       location++;
 
-   struct exec_list *var_list = nir_variable_list_for_mode(shader, mode);
-   exec_list_append(var_list, &io_vars);
+   exec_list_append(&shader->variables, &io_vars);
    *size = location;
 }
 
 
    /* uniforms list actually includes ubo's and ssbo's: */
    int max_slot = 0;
 
-   nir_foreach_variable (var, &shader->uniforms) {
-      if (!(var->data.mode & (nir_var_mem_ubo | nir_var_mem_ssbo)))
-         continue;
-
+   nir_foreach_variable_with_modes (var, shader,
+                                    nir_var_mem_ubo | nir_var_mem_ssbo) {
       int base = var->data.binding;
       int size = MAX2(1, glsl_array_size(var->type));
 
    /* Figure out which UBOs or SSBOs are large enough to be
     * disqualified from imul24:
     */
-   nir_foreach_variable(var, &shader->uniforms) {
+   nir_foreach_variable_in_shader (var, shader) {
       if (var->data.mode == nir_var_mem_ubo) {
          if (is_large(&state, var)) {
             state.has_large_ubo = true;
 
    } else
       var->type = glsl_vec4_type();
 
-   if (output) {
-      exec_list_push_tail(&shader->outputs, &var->node);
-   }
-   else {
-      exec_list_push_tail(&shader->inputs, &var->node);
-   }
+   nir_shader_add_variable(shader, var);
    return var;
 }
 
       cv = nir_load_var(b, clipvertex ? clipvertex : position);
 
       if (clipvertex) {
-         exec_node_remove(&clipvertex->node);
          clipvertex->data.mode = nir_var_shader_temp;
-         exec_list_push_tail(&b->shader->globals, &clipvertex->node);
          nir_fixup_deref_modes(b->shader);
       }
    } else {
 
       }
    }
 
-   nir_foreach_variable_safe(var, &shader->globals) {
+   nir_foreach_variable_with_modes_safe(var, shader, nir_var_shader_temp) {
       struct hash_entry *entry = _mesa_hash_table_search(var_func_table, var);
       if (!entry)
          continue;
 
       nir_function_impl *impl = entry->data;
 
-      assert(var->data.mode == nir_var_shader_temp);
-
       if (impl != NULL) {
          exec_node_remove(&var->node);
          var->data.mode = nir_var_function_temp;
 
    default:
       unreachable("Unsupported mode");
    }
-   nir_foreach_variable(var, vars) {
+   nir_foreach_variable_in_list(var, vars) {
+      if (var->data.mode != mode)
+         continue;
+
       unsigned size, align;
       const struct glsl_type *explicit_type =
          glsl_get_explicit_type_for_size_align(var->type, type_info, &size, &align);
    bool progress = false;
 
    if (modes & nir_var_mem_shared)
-      progress |= lower_vars_to_explicit(shader, &shader->shared, nir_var_mem_shared, type_info);
+      progress |= lower_vars_to_explicit(shader, &shader->variables, nir_var_mem_shared, type_info);
    if (modes & nir_var_shader_temp)
-      progress |= lower_vars_to_explicit(shader, &shader->globals, nir_var_shader_temp, type_info);
+      progress |= lower_vars_to_explicit(shader, &shader->variables, nir_var_shader_temp, type_info);
 
    nir_foreach_function(function, shader) {
       if (function->impl) {
 
    return nvar;
 }
 
+static void
+move_variables_to_list(nir_shader *shader, nir_variable_mode mode,
+                       struct exec_list *dst_list)
+{
+   nir_foreach_variable_with_modes_safe(var, shader, mode) {
+      exec_node_remove(&var->node);
+      exec_list_push_tail(dst_list, &var->node);
+   }
+}
+
 void
 nir_lower_io_to_temporaries(nir_shader *shader, nir_function_impl *entrypoint,
                             bool outputs, bool inputs)
    state.entrypoint = entrypoint;
    state.input_map = _mesa_pointer_hash_table_create(NULL);
 
+   exec_list_make_empty(&state.old_inputs);
    if (inputs)
-      exec_list_move_nodes_to(&shader->inputs, &state.old_inputs);
-   else
-      exec_list_make_empty(&state.old_inputs);
+      move_variables_to_list(shader, nir_var_shader_in, &state.old_inputs);
 
+   exec_list_make_empty(&state.old_outputs);
    if (outputs)
-      exec_list_move_nodes_to(&shader->outputs, &state.old_outputs);
-   else
-      exec_list_make_empty(&state.old_outputs);
+      move_variables_to_list(shader, nir_var_shader_out, &state.old_outputs);
 
    exec_list_make_empty(&state.new_inputs);
    exec_list_make_empty(&state.new_outputs);
    /* Walk over all of the outputs turn each output into a temporary and
     * make a new variable for the actual output.
     */
-   nir_foreach_variable(var, &state.old_outputs) {
+   nir_foreach_variable_in_list(var, &state.old_outputs) {
       nir_variable *output = create_shadow_temp(&state, var);
       exec_list_push_tail(&state.new_outputs, &output->node);
    }
 
    /* and same for inputs: */
-   nir_foreach_variable(var, &state.old_inputs) {
+   nir_foreach_variable_in_list(var, &state.old_inputs) {
       nir_variable *input = create_shadow_temp(&state, var);
       exec_list_push_tail(&state.new_inputs, &input->node);
       _mesa_hash_table_insert(state.input_map, var, input);
                                             nir_metadata_dominance);
    }
 
-   exec_list_append(&shader->inputs, &state.new_inputs);
-   exec_list_append(&shader->outputs, &state.new_outputs);
-   exec_list_append(&shader->globals, &state.old_inputs);
-   exec_list_append(&shader->globals, &state.old_outputs);
+   exec_list_append(&shader->variables, &state.old_inputs);
+   exec_list_append(&shader->variables, &state.old_outputs);
+   exec_list_append(&shader->variables, &state.new_inputs);
+   exec_list_append(&shader->variables, &state.new_outputs);
 
    nir_fixup_deref_modes(shader);
 
 
    if (progress)
       nir_remove_dead_derefs(shader);
 
-   exec_list_make_empty(&shader->system_values);
+   nir_foreach_variable_with_modes_safe(var, shader, nir_var_system_value)
+      exec_node_remove(&var->node);
 
    return progress;
 }
 
 }
 
 static bool
-lower_const_initializer(struct nir_builder *b, struct exec_list *var_list)
+lower_const_initializer(struct nir_builder *b, struct exec_list *var_list,
+                        nir_variable_mode modes)
 {
    bool progress = false;
 
    b->cursor = nir_before_cf_list(&b->impl->body);
 
-   nir_foreach_variable(var, var_list) {
+   nir_foreach_variable_in_list(var, var_list) {
+      if (!(var->data.mode & modes))
+         continue;
+
       if (var->constant_initializer) {
          build_constant_load(b, nir_build_deref_var(b, var),
                              var->constant_initializer);
       nir_builder builder;
       nir_builder_init(&builder, function->impl);
 
-      if ((modes & nir_var_shader_out) && function->is_entrypoint)
-         impl_progress |= lower_const_initializer(&builder, &shader->outputs);
-
-      if ((modes & nir_var_shader_temp) && function->is_entrypoint)
-         impl_progress |= lower_const_initializer(&builder, &shader->globals);
-
-      if ((modes & nir_var_system_value) && function->is_entrypoint)
-         impl_progress |= lower_const_initializer(&builder, &shader->system_values);
+      if ((modes & ~nir_var_function_temp) && function->is_entrypoint) {
+         impl_progress |= lower_const_initializer(&builder,
+                                                  &shader->variables,
+                                                  modes);
+      }
 
-      if (modes & nir_var_function_temp)
-         impl_progress |= lower_const_initializer(&builder, &function->impl->locals);
+      if (modes & nir_var_function_temp) {
+         impl_progress |= lower_const_initializer(&builder,
+                                                  &function->impl->locals,
+                                                  nir_var_function_temp);
+      }
 
       if (impl_progress) {
          progress = true;
 
       }
    }
 
-   nir_foreach_variable(var, &shader->uniforms)
+   nir_foreach_variable_with_modes(var, shader, nir_var_uniform |
+                                                nir_var_mem_ubo |
+                                                nir_var_mem_ssbo)
       var_progress |= process_variable(&state, var);
 
    nir_foreach_function(func, shader) {
 
    if (!state->shader)
       return;
 
-   struct exec_list *var_list = NULL;
-
+   nir_variable_mode var_mode;
    switch (instr->intrinsic) {
    case nir_intrinsic_load_uniform:
-      var_list = &state->shader->uniforms;
+      var_mode = nir_var_uniform;
       break;
    case nir_intrinsic_load_input:
    case nir_intrinsic_load_interpolated_input:
    case nir_intrinsic_load_per_vertex_input:
-      var_list = &state->shader->inputs;
+      var_mode = nir_var_shader_in;
       break;
    case nir_intrinsic_load_output:
    case nir_intrinsic_store_output:
    case nir_intrinsic_store_per_vertex_output:
-      var_list = &state->shader->outputs;
+      var_mode = nir_var_shader_out;
       break;
    default:
       return;
    }
 
-   nir_foreach_variable(var, var_list) {
+   nir_foreach_variable_with_modes(var, state->shader, var_mode) {
       if ((var->data.driver_location == nir_intrinsic_base(instr)) &&
           (instr->intrinsic == nir_intrinsic_load_uniform ||
            (nir_intrinsic_component(instr) >= var->data.location_frac  &&
    if (shader->scratch_size)
       fprintf(fp, "scratch: %u\n", shader->scratch_size);
 
-   nir_foreach_variable(var, &shader->uniforms) {
+   nir_foreach_variable_in_shader(var, shader)
       print_var_decl(var, &state);
-   }
-
-   nir_foreach_variable(var, &shader->inputs) {
-      print_var_decl(var, &state);
-   }
-
-   nir_foreach_variable(var, &shader->outputs) {
-      print_var_decl(var, &state);
-   }
-
-   nir_foreach_variable(var, &shader->shared) {
-      print_var_decl(var, &state);
-   }
-
-   nir_foreach_variable(var, &shader->globals) {
-      print_var_decl(var, &state);
-   }
-
-   nir_foreach_variable(var, &shader->system_values) {
-      print_var_decl(var, &state);
-   }
 
    foreach_list_typed(nir_function, func, node, &shader->functions) {
       print_function(func, &state);
 
 {
    bool progress = false;
 
-   nir_foreach_variable_safe(var, var_list) {
+   nir_foreach_variable_in_list_safe(var, var_list) {
       if (!(var->data.mode & modes))
          continue;
 
 
    add_var_use_shader(shader, live, modes);
 
-   if (modes & nir_var_uniform) {
-      progress = remove_dead_vars(&shader->uniforms, modes, live, can_remove_var) ||
-         progress;
-   }
-
-   if (modes & nir_var_shader_in) {
-      progress = remove_dead_vars(&shader->inputs, modes, live, can_remove_var) ||
-         progress;
-   }
-
-   if (modes & nir_var_shader_out) {
-      progress = remove_dead_vars(&shader->outputs, modes, live, can_remove_var) ||
-         progress;
-   }
-
-   if (modes & nir_var_shader_temp) {
-      progress = remove_dead_vars(&shader->globals, modes, live, can_remove_var) ||
-         progress;
-   }
-
-   if (modes & nir_var_system_value) {
-      progress = remove_dead_vars(&shader->system_values, modes, live,
-                                  can_remove_var) || progress;
-   }
-
-   if (modes & nir_var_mem_shared) {
-      progress = remove_dead_vars(&shader->shared, modes, live, can_remove_var) ||
-         progress;
+   if (modes & ~nir_var_function_temp) {
+      progress = remove_dead_vars(&shader->variables, modes,
+                                  live, can_remove_var) || progress;
    }
 
    if (modes & nir_var_function_temp) {
 
    info.name = info.label = NULL;
    blob_write_bytes(blob, (uint8_t *) &info, sizeof(info));
 
-   write_var_list(&ctx, &nir->uniforms);
-   write_var_list(&ctx, &nir->inputs);
-   write_var_list(&ctx, &nir->outputs);
-   write_var_list(&ctx, &nir->shared);
-   write_var_list(&ctx, &nir->globals);
-   write_var_list(&ctx, &nir->system_values);
+   write_var_list(&ctx, &nir->variables);
 
    blob_write_uint32(blob, nir->num_inputs);
    blob_write_uint32(blob, nir->num_uniforms);
 
    ctx.nir->info = info;
 
-   read_var_list(&ctx, &ctx.nir->uniforms);
-   read_var_list(&ctx, &ctx.nir->inputs);
-   read_var_list(&ctx, &ctx.nir->outputs);
-   read_var_list(&ctx, &ctx.nir->shared);
-   read_var_list(&ctx, &ctx.nir->globals);
-   read_var_list(&ctx, &ctx.nir->system_values);
+   read_var_list(&ctx, &ctx.nir->variables);
 
    ctx.nir->num_inputs = blob_read_uint32(blob);
    ctx.nir->num_uniforms = blob_read_uint32(blob);
 
    /* To avoid list confusion (we'll be adding things as we split variables),
     * pull all of the variables we plan to split off of the list
     */
-   nir_foreach_variable_safe(var, vars) {
+   nir_foreach_variable_in_list_safe(var, vars) {
       if (var->data.mode != mode)
          continue;
 
       exec_list_push_tail(&split_vars, &var->node);
    }
 
-   nir_foreach_variable(var, &split_vars) {
+   nir_foreach_variable_in_list(var, &split_vars) {
       state.base_var = var;
 
       struct field *root_field = ralloc(mem_ctx, struct field);
    bool has_global_splits = false;
    if (modes & nir_var_shader_temp) {
       has_global_splits = split_var_list_structs(shader, NULL,
-                                                 &shader->globals,
+                                                 &shader->variables,
                                                  nir_var_shader_temp,
                                                  var_field_map,
                                                  &complex_vars,
 {
    bool has_array = false;
 
-   nir_foreach_variable(var, vars) {
+   nir_foreach_variable_in_list(var, vars) {
       if (var->data.mode != mode)
          continue;
 
    struct exec_list split_vars;
    exec_list_make_empty(&split_vars);
 
-   nir_foreach_variable_safe(var, vars) {
+   nir_foreach_variable_in_list_safe(var, vars) {
       if (var->data.mode != mode)
          continue;
 
       }
    }
 
-   nir_foreach_variable(var, &split_vars) {
+   nir_foreach_variable_in_list(var, &split_vars) {
       struct array_var_info *info = get_array_var_info(var, var_info_map);
       create_split_array_vars(info, 0, &info->root_split, var->name,
                               shader, impl, mem_ctx);
    bool has_global_array = false;
    if (modes & nir_var_shader_temp) {
       has_global_array = init_var_list_array_infos(shader,
-                                                   &shader->globals,
+                                                   &shader->variables,
                                                    nir_var_shader_temp,
                                                    var_info_map,
                                                    &complex_vars,
    bool has_global_splits = false;
    if (modes & nir_var_shader_temp) {
       has_global_splits = split_var_list_arrays(shader, NULL,
-                                                &shader->globals,
+                                                &shader->variables,
                                                 nir_var_shader_temp,
                                                 var_info_map, mem_ctx);
    }
     * Also, if we have a copy that to/from something we can't shrink, we need
     * to leave components and array_len of any wildcards alone.
     */
-   nir_foreach_variable(var, vars) {
+   nir_foreach_variable_in_list(var, vars) {
       if (var->data.mode != mode)
          continue;
 
    bool fp_progress;
    do {
       fp_progress = false;
-      nir_foreach_variable(var, vars) {
+      nir_foreach_variable_in_list(var, vars) {
          if (var->data.mode != mode)
             continue;
 
    } while (fp_progress);
 
    bool vars_shrunk = false;
-   nir_foreach_variable_safe(var, vars) {
+   nir_foreach_variable_in_list_safe(var, vars) {
       if (var->data.mode != mode)
          continue;
 
 {
    nir_shader *shader = impl->function->shader;
 
-   if ((modes & nir_var_shader_temp) && !exec_list_is_empty(&shader->globals))
-      return true;
+   if (modes & ~nir_var_function_temp) {
+      nir_foreach_variable_with_modes(var, shader,
+                                      modes & ~nir_var_function_temp)
+         return true;
+   }
 
    if ((modes & nir_var_function_temp) && !exec_list_is_empty(&impl->locals))
       return true;
 
    bool globals_shrunk = false;
    if (modes & nir_var_shader_temp) {
-      globals_shrunk = shrink_vec_var_list(&shader->globals,
+      globals_shrunk = shrink_vec_var_list(&shader->variables,
                                            nir_var_shader_temp,
                                            var_usage_map);
    }
 
       ralloc_steal(nir, (char *)nir->info.label);
 
    /* Variables and registers are not dead.  Steal them back. */
-   steal_list(nir, nir_variable, &nir->uniforms);
-   steal_list(nir, nir_variable, &nir->inputs);
-   steal_list(nir, nir_variable, &nir->outputs);
-   steal_list(nir, nir_variable, &nir->shared);
-   steal_list(nir, nir_variable, &nir->globals);
-   steal_list(nir, nir_variable, &nir->system_values);
+   steal_list(nir, nir_variable, &nir->variables);
 
    /* Recurse into functions, stealing their contents back. */
    foreach_list_typed(nir_function, func, node, &nir->functions) {
 
 
    state.shader = shader;
 
-   exec_list_validate(&shader->uniforms);
-   nir_foreach_variable(var, &shader->uniforms) {
-      validate_var_decl(var, nir_var_uniform |
-                             nir_var_mem_ubo |
-                             nir_var_mem_ssbo,
-                        &state);
-   }
-
-   exec_list_validate(&shader->inputs);
-   nir_foreach_variable(var, &shader->inputs) {
-     validate_var_decl(var, nir_var_shader_in, &state);
-   }
-
-   exec_list_validate(&shader->outputs);
-   nir_foreach_variable(var, &shader->outputs) {
-     validate_var_decl(var, nir_var_shader_out, &state);
-   }
-
-   exec_list_validate(&shader->shared);
-   nir_foreach_variable(var, &shader->shared) {
-      validate_var_decl(var, nir_var_mem_shared, &state);
-   }
-
-   exec_list_validate(&shader->globals);
-   nir_foreach_variable(var, &shader->globals) {
-     validate_var_decl(var, nir_var_shader_temp, &state);
-   }
-
-   exec_list_validate(&shader->system_values);
-   nir_foreach_variable(var, &shader->system_values) {
-     validate_var_decl(var, nir_var_system_value, &state);
-   }
+   nir_variable_mode valid_modes =
+      nir_var_shader_in |
+      nir_var_shader_out |
+      nir_var_shader_temp |
+      nir_var_uniform |
+      nir_var_mem_ubo |
+      nir_var_system_value |
+      nir_var_mem_ssbo |
+      nir_var_mem_shared;
+
+   exec_list_validate(&shader->variables);
+   nir_foreach_variable_in_shader(var, shader)
+     validate_var_decl(var, valid_modes, &state);
 
    exec_list_validate(&shader->functions);
    foreach_list_typed(nir_function, func, node, &shader->functions) {
 
    }
 
    unsigned count_shader_temp_vars(void) {
-      return exec_list_length(&b->shader->globals);
+      unsigned count = 0;
+      nir_foreach_variable_with_modes(var, b->shader, nir_var_shader_temp)
+         count++;
+      return count;
    }
 
    nir_intrinsic_instr *get_intrinsic(nir_intrinsic_op intrinsic,
 
        nir_variable *vertex_flags_out;
 
        struct exec_list old_outputs;
+       struct exec_list new_outputs;
        struct exec_list emit_outputs;
 
        /* tess ctrl shader on a650 gets the local primitive id at different bits: */
         * we copy the emit_outputs to the real outputs, so that we get
         * store_output in uniform control flow.
         */
-       exec_list_move_nodes_to(&shader->outputs, &state.old_outputs);
+       exec_list_make_empty(&state.old_outputs);
+       nir_foreach_shader_out_variable_safe(var, shader) {
+               exec_node_remove(&var->node);
+               exec_list_push_tail(&state.old_outputs, &var->node);
+       }
+       exec_list_make_empty(&state.new_outputs);
        exec_list_make_empty(&state.emit_outputs);
-       nir_foreach_variable(var, &state.old_outputs) {
+       nir_foreach_variable_in_list(var, &state.old_outputs) {
                /* Create a new output var by cloning the original output var and
                 * stealing the name.
                 */
                nir_variable *output = nir_variable_clone(var, shader);
-               exec_list_push_tail(&shader->outputs, &output->node);
+               exec_list_push_tail(&state.new_outputs, &output->node);
 
                /* Rewrite the original output to be a shadow variable. */
                var->name = ralloc_asprintf(var, "%s@gs-temp", output->name);
 
                nir_builder_instr_insert(&b, &discard_if->instr);
 
-               foreach_two_lists(dest_node, &shader->outputs, src_node, &state.emit_outputs) {
+               foreach_two_lists(dest_node, &state.new_outputs, src_node, &state.emit_outputs) {
                        nir_variable *dest = exec_node_data(nir_variable, dest_node, node);
                        nir_variable *src = exec_node_data(nir_variable, src_node, node);
                        nir_copy_var(&b, dest, src);
                }
        }
 
-       exec_list_append(&shader->globals, &state.old_outputs);
-       exec_list_append(&shader->globals, &state.emit_outputs);
+       exec_list_append(&shader->variables, &state.old_outputs);
+       exec_list_append(&shader->variables, &state.emit_outputs);
+       exec_list_append(&shader->variables, &state.new_outputs);
 
        nir_metadata_preserve(impl, 0);
 
 
 static void
 insert_sorted(struct exec_list *var_list, nir_variable *new_var)
 {
-       nir_foreach_variable(var, var_list) {
+       nir_foreach_variable_in_list(var, var_list) {
                if (var->data.location > new_var->data.location) {
                        exec_node_insert_node_before(&var->node, &new_var->node);
                        return;
                exec_node_remove(&var->node);
                insert_sorted(&new_list, var);
        }
-       exec_list_move_nodes_to(&new_list, var_list);
+       exec_list_append(&nir->variables, &new_list);
 }
 
 static void
 
       return false;
    }
 
-   exec_node_remove(&var->node);
    var->data.mode = nir_var_shader_temp;
-   exec_list_push_tail(&nir->globals, &var->node);
    nir->info.outputs_written &= ~VARYING_BIT_EDGE;
    nir->info.inputs_read &= ~VERT_BIT_EDGEFLAG;
    nir_fixup_deref_modes(nir);
 
 static void
 insert_sorted(struct exec_list *var_list, nir_variable *new_var)
 {
-   nir_foreach_variable(var, var_list) {
+   nir_foreach_variable_in_list(var, var_list) {
       if (var->data.location > new_var->data.location &&
           new_var->data.location >= 0) {
          exec_node_insert_node_before(&var->node, &new_var->node);
       exec_node_remove(&var->node);
       insert_sorted(&new_list, var);
    }
-   exec_list_move_nodes_to(&new_list, var_list);
+   exec_list_append(&nir->variables, &new_list);
 }
 
 static void
 
    }
 
    // scan declarations
-   nir_foreach_variable(variable, &sh->uniforms) {
+   nir_foreach_variable_with_modes(variable, sh, nir_var_uniform |
+                                                 nir_var_mem_ubo |
+                                                 nir_var_mem_ssbo) {
       if (!impl->process_uniforms(variable)) {
          fprintf(stderr, "R600: error parsing outputs varible %s\n", variable->name);
          return false;
 
 
    if (so_info)
       emit_so_info(&ctx, util_last_bit64(s->info.outputs_written), so_info, local_so_info);
-   nir_foreach_variable(var, &s->uniforms)
+   nir_foreach_variable_with_modes(var, s, nir_var_uniform |
+                                           nir_var_mem_ubo |
+                                           nir_var_mem_ssbo)
       emit_uniform(&ctx, var);
 
    if (s->info.stage == MESA_SHADER_FRAGMENT) {
 
    }
 
    ret->num_bindings = 0;
-   nir_foreach_variable(var, &nir->uniforms) {
+   nir_foreach_variable_with_modes(var, nir, nir_var_uniform |
+                                             nir_var_mem_ubo) {
       if (var->data.mode == nir_var_mem_ubo) {
          int binding = zink_binding(nir->info.stage,
                                     VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
 
 
    memset(wm_prog_data, 0, sizeof(*wm_prog_data));
 
-   assert(exec_list_is_empty(&nir->uniforms));
    wm_prog_data->base.nr_params = 0;
    wm_prog_data->base.param = NULL;
 
 
             util_bitcount64(nir->info.inputs_read &
                               BITFIELD64_MASK(var->data.location));
       } else {
-         /* Move unused input variables to the globals list (with no
+         /* Convert unused input variables to shader_temp (with no
           * initialization), to avoid confusing drivers looking through the
           * inputs array and expecting to find inputs with a driver_location
           * set.
           */
-         exec_node_remove(&var->node);
          var->data.mode = nir_var_shader_temp;
-         exec_list_push_tail(&nir->globals, &var->node);
          removed_inputs = true;
       }
    }