Merge remote-tracking branch 'mesa-public/master' into vulkan
[mesa.git] / src / glsl / nir / nir.h
index e6ddb7ee6a7de83e6482829b82c8728f27d124cb..70af06e69713e5dc8be6b3b74b8196c4fa1daa68 100644 (file)
 #pragma once
 
 #include "util/hash_table.h"
-#include "main/set.h"
 #include "../list.h"
 #include "GL/gl.h" /* GLenum */
+#include "util/list.h"
 #include "util/ralloc.h"
-#include "main/mtypes.h"
-#include "main/bitset.h"
+#include "util/set.h"
+#include "util/bitset.h"
 #include "nir_types.h"
+#include "glsl/shader_enums.h"
 #include <stdio.h>
 
+#include "nir_opcodes.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+struct gl_program;
+struct gl_shader_program;
+
 #define NIR_FALSE 0u
 #define NIR_TRUE (~0u)
 
@@ -62,6 +68,7 @@ name(const in_type *parent)                              \
 struct nir_function_overload;
 struct nir_function;
 struct nir_shader;
+struct nir_instr;
 
 
 /**
@@ -80,6 +87,7 @@ typedef enum {
    nir_var_global,
    nir_var_local,
    nir_var_uniform,
+   nir_var_shader_storage,
    nir_var_system_value
 } nir_variable_mode;
 
@@ -98,7 +106,7 @@ typedef struct nir_constant {
     * Value of the constant.
     *
     * The field used to back the values supplied by the constant is determined
-    * by the type associated with the \c ir_instruction.  Constants may be
+    * by the type associated with the \c nir_variable.  Constants may be
     * scalars, vectors, or matrices.
     */
    union nir_constant_data value;
@@ -175,7 +183,7 @@ typedef struct {
       /**
        * Interpolation mode for shader inputs / outputs
        *
-       * \sa ir_variable_interpolation
+       * \sa glsl_interp_qualifier
        */
       unsigned interpolation:2;
 
@@ -200,8 +208,8 @@ typedef struct {
       /**
        * Was an initial binding explicitly set in the shader?
        *
-       * If so, constant_value contains an integer ir_constant representing the
-       * initial binding point.
+       * If so, constant_initializer contains an integer nir_constant
+       * representing the initial binding point.
        */
       unsigned explicit_binding:1;
 
@@ -293,6 +301,7 @@ typedef struct {
        *
        * For array types, this represents the binding point for the first element.
        */
+      int descriptor_set;
       int binding;
 
       /**
@@ -342,18 +351,8 @@ typedef struct {
    nir_state_slot *state_slots;  /**< State descriptors. */
    /*@}*/
 
-   /**
-    * Value assigned in the initializer of a variable declared "const"
-    */
-   nir_constant *constant_value;
-
    /**
     * Constant expression assigned in the initializer of the variable
-    *
-    * \warning
-    * This field and \c ::constant_value are distinct.  Even if the two fields
-    * refer to constants with the same value, they must point to separate
-    * objects.
     */
    nir_constant *constant_initializer;
 
@@ -393,19 +392,19 @@ typedef struct {
    bool is_packed;
 
    /** set of nir_instr's where this register is used (read from) */
-   struct set *uses;
+   struct list_head uses;
 
    /** set of nir_instr's where this register is defined (written to) */
-   struct set *defs;
+   struct list_head defs;
 
-   /** set of ifs where this register is used as a condition */
-   struct set *if_uses;
+   /** set of nir_if's where this register is used as a condition */
+   struct list_head if_uses;
 } nir_register;
 
 typedef enum {
    nir_instr_type_alu,
    nir_instr_type_call,
-   nir_instr_type_texture,
+   nir_instr_type_tex,
    nir_instr_type_intrinsic,
    nir_instr_type_load_const,
    nir_instr_type_jump,
@@ -414,20 +413,48 @@ typedef enum {
    nir_instr_type_parallel_copy,
 } nir_instr_type;
 
-typedef struct {
+typedef struct nir_instr {
    struct exec_node node;
    nir_instr_type type;
    struct nir_block *block;
 
-   /* flag for dead code elimination (see nir_opt_dce.c) */
-   bool live;
+   /* A temporary for optimization and analysis passes to use for storing
+    * flags.  For instance, DCE uses this to store the "dead/live" info.
+    */
+   uint8_t pass_flags;
 } nir_instr;
 
-#define nir_instr_next(instr) \
-   exec_node_data(nir_instr, (instr)->node.next, node)
+static inline nir_instr *
+nir_instr_next(nir_instr *instr)
+{
+   struct exec_node *next = exec_node_get_next(&instr->node);
+   if (exec_node_is_tail_sentinel(next))
+      return NULL;
+   else
+      return exec_node_data(nir_instr, next, node);
+}
+
+static inline nir_instr *
+nir_instr_prev(nir_instr *instr)
+{
+   struct exec_node *prev = exec_node_get_prev(&instr->node);
+   if (exec_node_is_head_sentinel(prev))
+      return NULL;
+   else
+      return exec_node_data(nir_instr, prev, node);
+}
+
+static inline bool
+nir_instr_is_first(nir_instr *instr)
+{
+   return exec_node_is_head_sentinel(exec_node_get_prev(&instr->node));
+}
 
-#define nir_instr_prev(instr) \
-   exec_node_data(nir_instr, (instr)->node.prev, node)
+static inline bool
+nir_instr_is_last(nir_instr *instr)
+{
+   return exec_node_is_tail_sentinel(exec_node_get_next(&instr->node));
+}
 
 typedef struct {
    /** for debugging only, can be NULL */
@@ -441,8 +468,11 @@ typedef struct {
 
    nir_instr *parent_instr;
 
-   struct set *uses;
-   struct set *if_uses;
+   /** set of nir_instr's where this register is used (read from) */
+   struct list_head uses;
+
+   /** set of nir_if's where this register is used as a condition */
+   struct list_head if_uses;
 
    uint8_t num_components;
 } nir_ssa_def;
@@ -458,6 +488,9 @@ typedef struct {
 } nir_reg_src;
 
 typedef struct {
+   nir_instr *parent_instr;
+   struct list_head def_link;
+
    nir_register *reg;
    struct nir_src *indirect; /** < NULL for no indirect offset */
    unsigned base_offset;
@@ -465,7 +498,16 @@ typedef struct {
    /* TODO def-use chain goes here */
 } nir_reg_dest;
 
+struct nir_if;
+
 typedef struct nir_src {
+   union {
+      nir_instr *parent_instr;
+      struct nir_if *parent_if;
+   };
+
+   struct list_head use_link;
+
    union {
       nir_reg_src reg;
       nir_ssa_def *ssa;
@@ -474,6 +516,24 @@ typedef struct nir_src {
    bool is_ssa;
 } nir_src;
 
+#ifdef __cplusplus
+#  define NIR_SRC_INIT nir_src()
+#else
+#  define NIR_SRC_INIT (nir_src) { { NULL } }
+#endif
+
+#define nir_foreach_use(reg_or_ssa_def, src) \
+   list_for_each_entry(nir_src, src, &(reg_or_ssa_def)->uses, use_link)
+
+#define nir_foreach_use_safe(reg_or_ssa_def, src) \
+   list_for_each_entry_safe(nir_src, src, &(reg_or_ssa_def)->uses, use_link)
+
+#define nir_foreach_if_use(reg_or_ssa_def, src) \
+   list_for_each_entry(nir_src, src, &(reg_or_ssa_def)->if_uses, use_link)
+
+#define nir_foreach_if_use_safe(reg_or_ssa_def, src) \
+   list_for_each_entry_safe(nir_src, src, &(reg_or_ssa_def)->if_uses, use_link)
+
 typedef struct {
    union {
       nir_reg_dest reg;
@@ -483,8 +543,54 @@ typedef struct {
    bool is_ssa;
 } nir_dest;
 
-nir_src nir_src_copy(nir_src src, void *mem_ctx);
-nir_dest nir_dest_copy(nir_dest dest, void *mem_ctx);
+#ifdef __cplusplus
+#  define NIR_DEST_INIT nir_dest()
+#else
+#  define NIR_DEST_INIT (nir_dest) { { { NULL } } }
+#endif
+
+#define nir_foreach_def(reg, dest) \
+   list_for_each_entry(nir_dest, dest, &(reg)->defs, reg.def_link)
+
+#define nir_foreach_def_safe(reg, dest) \
+   list_for_each_entry_safe(nir_dest, dest, &(reg)->defs, reg.def_link)
+
+static inline nir_src
+nir_src_for_ssa(nir_ssa_def *def)
+{
+   nir_src src = NIR_SRC_INIT;
+
+   src.is_ssa = true;
+   src.ssa = def;
+
+   return src;
+}
+
+static inline nir_src
+nir_src_for_reg(nir_register *reg)
+{
+   nir_src src = NIR_SRC_INIT;
+
+   src.is_ssa = false;
+   src.reg.reg = reg;
+   src.reg.indirect = NULL;
+   src.reg.base_offset = 0;
+
+   return src;
+}
+
+static inline nir_dest
+nir_dest_for_reg(nir_register *reg)
+{
+   nir_dest dest = NIR_DEST_INIT;
+
+   dest.reg.reg = reg;
+
+   return dest;
+}
+
+void nir_src_copy(nir_src *dest, const nir_src *src, void *mem_ctx);
+void nir_dest_copy(nir_dest *dest, const nir_dest *src, void *mem_ctx);
 
 typedef struct {
    nir_src src;
@@ -494,8 +600,8 @@ typedef struct {
     */
    /*@{*/
    /**
-    * For inputs interpreted as a floating point, flips the sign bit. For inputs
-    * interpreted as an integer, performs the two's complement negation.
+    * For inputs interpreted as floating point, flips the sign bit. For
+    * inputs interpreted as integers, performs the two's complement negation.
     */
    bool negate;
 
@@ -533,72 +639,67 @@ typedef struct {
    unsigned write_mask : 4; /* ignored if dest.is_ssa is true */
 } nir_alu_dest;
 
-#define OPCODE(name, num_inputs, per_component, output_size, output_type, \
-               input_sizes, input_types) \
-   nir_op_##name,
-
-#define LAST_OPCODE(name) nir_last_opcode = nir_op_##name,
-
-typedef enum {
-#include "nir_opcodes.h"
-   nir_num_opcodes = nir_last_opcode + 1
-} nir_op;
-
-#undef OPCODE
-#undef LAST_OPCODE
+void nir_alu_src_copy(nir_alu_src *dest, const nir_alu_src *src, void *mem_ctx);
+void nir_alu_dest_copy(nir_alu_dest *dest, const nir_alu_dest *src,
+                       void *mem_ctx);
 
 typedef enum {
+   nir_type_invalid = 0, /* Not a valid type */
    nir_type_float,
    nir_type_int,
    nir_type_unsigned,
    nir_type_bool
 } nir_alu_type;
 
+typedef enum {
+   NIR_OP_IS_COMMUTATIVE = (1 << 0),
+   NIR_OP_IS_ASSOCIATIVE = (1 << 1),
+} nir_op_algebraic_property;
+
 typedef struct {
    const char *name;
 
    unsigned num_inputs;
 
    /**
-    * If true, the opcode acts in the standard, per-component manner; the
-    * operation is performed on each component (except the ones that are masked
-    * out) with the input being taken from the input swizzle for that component.
+    * The number of components in the output
     *
-    * If false, the size of the output and inputs are explicitly given; swizzle
-    * and writemask are still in effect, but if the output component is masked
-    * out, then the input component may still be in use.
+    * If non-zero, this is the size of the output and input sizes are
+    * explicitly given; swizzle and writemask are still in effect, but if
+    * the output component is masked out, then the input component may
+    * still be in use.
     *
-    * The size of some of the inputs may be given (i.e. non-zero) even though
-    * per_component is false; in that case, each component of the input acts
-    * per-component, while the rest of the inputs and the output are normal.
-    * For example, for conditional select the condition is per-component but
-    * everything else is normal.
-    */
-   bool per_component;
-
-   /**
-    * If per_component is false, the number of components in the output.
+    * If zero, the opcode acts in the standard, per-component manner; the
+    * operation is performed on each component (except the ones that are
+    * masked out) with the input being taken from the input swizzle for
+    * that component.
+    *
+    * The size of some of the inputs may be given (i.e. non-zero) even
+    * though output_size is zero; in that case, the inputs with a zero
+    * size act per-component, while the inputs with non-zero size don't.
     */
    unsigned output_size;
 
    /**
-    * The type of vector that the instruction outputs. Note that this
-    * determines whether the saturate modifier is allowed.
+    * The type of vector that the instruction outputs. Note that the
+    * staurate modifier is only allowed on outputs with the float type.
     */
 
    nir_alu_type output_type;
 
    /**
-    * If per_component is false, the number of components in each input.
+    * The number of components in each input
     */
    unsigned input_sizes[4];
 
    /**
-    * The type of vector that each input takes. Note that negate is only
-    * allowed on inputs with int or float type, and behaves differently on the
-    * two, and absolute value is only allowed on float type inputs.
+    * The type of vector that each input takes. Note that negate and
+    * absolute value are only allowed on inputs with int or float type and
+    * behave differently on the two.
     */
    nir_alu_type input_types[4];
+
+   nir_op_algebraic_property algebraic_properties;
 } nir_op_info;
 
 extern const nir_op_info nir_op_infos[nir_num_opcodes];
@@ -606,8 +707,6 @@ extern const nir_op_info nir_op_infos[nir_num_opcodes];
 typedef struct nir_alu_instr {
    nir_instr instr;
    nir_op op;
-   bool has_predicate;
-   nir_src predicate;
    nir_alu_dest dest;
    nir_alu_src src[];
 } nir_alu_instr;
@@ -622,6 +721,21 @@ nir_alu_instr_channel_used(nir_alu_instr *instr, unsigned src, unsigned channel)
    return (instr->dest.write_mask >> channel) & 1;
 }
 
+/*
+ * For instructions whose destinations are SSA, get the number of channels
+ * used for a source
+ */
+static inline unsigned
+nir_ssa_alu_instr_src_components(nir_alu_instr *instr, unsigned src)
+{
+   assert(instr->dest.dest.is_ssa);
+
+   if (nir_op_infos[instr->op].input_sizes[src] > 0)
+      return nir_op_infos[instr->op].input_sizes[src];
+
+   return instr->dest.dest.ssa.num_components;
+}
+
 typedef enum {
    nir_deref_type_var,
    nir_deref_type_array,
@@ -672,6 +786,15 @@ NIR_DEFINE_CAST(nir_deref_as_var, nir_deref, nir_deref_var, deref)
 NIR_DEFINE_CAST(nir_deref_as_array, nir_deref, nir_deref_array, deref)
 NIR_DEFINE_CAST(nir_deref_as_struct, nir_deref, nir_deref_struct, deref)
 
+/** Returns the tail of a deref chain */
+static inline nir_deref *
+nir_deref_tail(nir_deref *deref)
+{
+   while (deref->child)
+      deref = deref->child;
+   return deref;
+}
+
 typedef struct {
    nir_instr instr;
 
@@ -679,9 +802,6 @@ typedef struct {
    nir_deref_var **params;
    nir_deref_var *return_deref;
 
-   bool has_predicate;
-   nir_src predicate;
-
    struct nir_function_overload *callee;
 } nir_call_instr;
 
@@ -699,6 +819,32 @@ typedef enum {
 #undef INTRINSIC
 #undef LAST_INTRINSIC
 
+/** Represents an intrinsic
+ *
+ * An intrinsic is an instruction type for handling things that are
+ * more-or-less regular operations but don't just consume and produce SSA
+ * values like ALU operations do.  Intrinsics are not for things that have
+ * special semantic meaning such as phi nodes and parallel copies.
+ * Examples of intrinsics include variable load/store operations, system
+ * value loads, and the like.  Even though texturing more-or-less falls
+ * under this category, texturing is its own instruction type because
+ * trying to represent texturing with intrinsics would lead to a
+ * combinatorial explosion of intrinsic opcodes.
+ *
+ * By having a single instruction type for handling a lot of different
+ * cases, optimization passes can look for intrinsics and, for the most
+ * part, completely ignore them.  Each intrinsic type also has a few
+ * possible flags that govern whether or not they can be reordered or
+ * eliminated.  That way passes like dead code elimination can still work
+ * on intrisics without understanding the meaning of each.
+ *
+ * Each intrinsic has some number of constant indices, some number of
+ * variables, and some number of sources.  What these sources, variables,
+ * and indices mean depends on the intrinsic and is documented with the
+ * intrinsic declaration in nir_intrinsics.h.  Intrinsics and texture
+ * instructions are the only types of instruction that can operate on
+ * variables.
+ */
 typedef struct {
    nir_instr instr;
 
@@ -706,16 +852,20 @@ typedef struct {
 
    nir_dest dest;
 
-   /** number of components if this is a vectorized intrinsic */
+   /** number of components if this is a vectorized intrinsic
+    *
+    * Similarly to ALU operations, some intrinsics are vectorized.
+    * An intrinsic is vectorized if nir_intrinsic_infos.dest_components == 0.
+    * For vectorized intrinsics, the num_components field specifies the
+    * number of destination components and the number of source components
+    * for all sources with nir_intrinsic_infos.src_components[i] == 0.
+    */
    uint8_t num_components;
 
    int const_index[3];
 
    nir_deref_var *variables[2];
 
-   bool has_predicate;
-   nir_src predicate;
-
    nir_src src[];
 } nir_intrinsic_instr;
 
@@ -726,20 +876,20 @@ typedef struct {
  *
  * \sa nir_intrinsic_info::flags
  */
-/*@{*/
-/**
- * whether the intrinsic can be safely eliminated if none of its register
* outputs are being used.
- */
-#define NIR_INTRINSIC_CAN_ELIMINATE (1 << 0)
+typedef enum {
+   /**
+    * whether the intrinsic can be safely eliminated if none of its output
   * value is not being used.
   */
+   NIR_INTRINSIC_CAN_ELIMINATE = (1 << 0),
 
-/**
- * Whether the intrinsic can be reordered with respect to any other intrinsic,
* i.e. whether the only reodering dependencies of the intrinsic are due to the
* register reads/writes.
- */
-#define NIR_INTRINSIC_CAN_REORDER   (1 << 1)
-/*@}*/
+   /**
+    * Whether the intrinsic can be reordered with respect to any other
   * intrinsic, i.e. whether the only reordering dependencies of the
   * intrinsic are due to the register reads/writes.
   */
+   NIR_INTRINSIC_CAN_REORDER = (1 << 1),
+} nir_intrinsic_semantic_flag;
 
 #define NIR_INTRINSIC_MAX_INPUTS 4
 
@@ -771,7 +921,7 @@ typedef struct {
    unsigned num_indices;
 
    /** semantic flags for calls to this intrinsic */
-   unsigned flags;
+   nir_intrinsic_semantic_flag flags;
 } nir_intrinsic_info;
 
 extern const nir_intrinsic_info nir_intrinsic_infos[nir_num_intrinsics];
@@ -793,9 +943,14 @@ typedef enum {
    nir_tex_src_ms_index, /* MSAA sample index */
    nir_tex_src_ddx,
    nir_tex_src_ddy,
-   nir_tex_src_sampler_index, /* < dynamically uniform indirect index */
-   nir_num_texinput_types
-} nir_texinput_type;
+   nir_tex_src_sampler_offset, /* < dynamically uniform indirect offset */
+   nir_num_tex_src_types
+} nir_tex_src_type;
+
+typedef struct {
+   nir_src src;
+   nir_tex_src_type src_type;
+} nir_tex_src;
 
 typedef enum {
    nir_texop_tex,                /**< Regular texture look-up */
@@ -813,16 +968,12 @@ typedef enum {
 typedef struct {
    nir_instr instr;
 
-   bool has_predicate;
-   nir_src predicate;
-
    enum glsl_sampler_dim sampler_dim;
    nir_alu_type dest_type;
 
    nir_texop op;
    nir_dest dest;
-   nir_src src[4];
-   nir_texinput_type src_type[4];
+   nir_tex_src *src;
    unsigned num_srcs, coord_components;
    bool is_array, is_shadow;
 
@@ -838,14 +989,27 @@ typedef struct {
    /* gather component selector */
    unsigned component : 2;
 
+   /* The descriptor set containing this texture */
+   unsigned sampler_set;
+
+   /** The sampler index
+    *
+    * If this texture instruction has a nir_tex_src_sampler_offset source,
+    * then the sampler index is given by sampler_index + sampler_offset.
+    */
    unsigned sampler_index;
+
+   /** The size of the sampler array or 0 if it's not an array */
+   unsigned sampler_array_size;
+
    nir_deref_var *sampler; /* if this is NULL, use sampler_index instead */
 } nir_tex_instr;
 
 static inline unsigned
 nir_tex_instr_dest_size(nir_tex_instr *instr)
 {
-   if (instr->op == nir_texop_txs) {
+   switch (instr->op) {
+   case nir_texop_txs: {
       unsigned ret;
       switch (instr->sampler_dim) {
          case GLSL_SAMPLER_DIM_1D:
@@ -863,33 +1027,37 @@ nir_tex_instr_dest_size(nir_tex_instr *instr)
             ret = 3;
             break;
          default:
-            assert(0);
-            break;
+            unreachable("not reached");
       }
       if (instr->is_array)
          ret++;
       return ret;
    }
 
-   if (instr->op == nir_texop_query_levels)
+   case nir_texop_lod:
       return 2;
 
-   if (instr->is_shadow && instr->is_new_style_shadow)
+   case nir_texop_query_levels:
       return 1;
 
-   return 4;
+   default:
+      if (instr->is_shadow && instr->is_new_style_shadow)
+         return 1;
+
+      return 4;
+   }
 }
 
 static inline unsigned
 nir_tex_instr_src_size(nir_tex_instr *instr, unsigned src)
 {
-   if (instr->src_type[src] == nir_tex_src_coord)
+   if (instr->src[src].src_type == nir_tex_src_coord)
       return instr->coord_components;
 
 
-   if (instr->src_type[src] == nir_tex_src_offset ||
-       instr->src_type[src] == nir_tex_src_ddx ||
-       instr->src_type[src] == nir_tex_src_ddy) {
+   if (instr->src[src].src_type == nir_tex_src_offset ||
+       instr->src[src].src_type == nir_tex_src_ddx ||
+       instr->src[src].src_type == nir_tex_src_ddy) {
       if (instr->is_array)
          return instr->coord_components - 1;
       else
@@ -900,10 +1068,10 @@ nir_tex_instr_src_size(nir_tex_instr *instr, unsigned src)
 }
 
 static inline int
-nir_tex_instr_src_index(nir_tex_instr *instr, nir_texinput_type type)
+nir_tex_instr_src_index(nir_tex_instr *instr, nir_tex_src_type type)
 {
    for (unsigned i = 0; i < instr->num_srcs; i++)
-      if (instr->src_type[i] == type)
+      if (instr->src[i].src_type == type)
          return (int) i;
 
    return -1;
@@ -920,25 +1088,9 @@ typedef struct {
 typedef struct {
    nir_instr instr;
 
-   union {
-      nir_const_value value;
-      nir_const_value *array;
-   };
-
-   unsigned num_components;
-
-   /**
-    * The number of constant array elements to be copied into the variable. If
-    * this != 0, then value.array holds the array of size array_elems;
-    * otherwise, value.value holds the single vector constant (the more common
-    * case, and the only case for SSA destinations).
-    */
-   unsigned array_elems;
-
-   bool has_predicate;
-   nir_src predicate;
+   nir_const_value value;
 
-   nir_dest dest;
+   nir_ssa_def def;
 } nir_load_const_instr;
 
 typedef enum {
@@ -961,14 +1113,21 @@ typedef struct {
 
 typedef struct {
    struct exec_node node;
+
+   /* The predecessor block corresponding to this source */
    struct nir_block *pred;
+
    nir_src src;
 } nir_phi_src;
 
+#define nir_foreach_phi_src(phi, entry) \
+   foreach_list_typed(nir_phi_src, entry, node, &(phi)->srcs)
+
 typedef struct {
    nir_instr instr;
 
-   struct exec_list srcs;
+   struct exec_list srcs; /** < list of nir_phi_src */
+
    nir_dest dest;
 } nir_phi_instr;
 
@@ -976,24 +1135,26 @@ typedef struct {
    struct exec_node node;
    nir_src src;
    nir_dest dest;
-} nir_parallel_copy_copy;
+} nir_parallel_copy_entry;
+
+#define nir_foreach_parallel_copy_entry(pcopy, entry) \
+   foreach_list_typed(nir_parallel_copy_entry, entry, node, &(pcopy)->entries)
 
 typedef struct {
    nir_instr instr;
 
-   /* Indicates that this is the parallel copy at the end of the block.
-    * When isolating phi nodes, we create 2 parallel copies in most blocks;
-    * this flag helps tell them apart.
+   /* A list of nir_parallel_copy_entry's.  The sources of all of the
+    * entries are copied to the corresponding destinations "in parallel".
+    * In other words, if we have two entries: a -> b and b -> a, the values
+    * get swapped.
     */
-   bool at_end;
-
-   struct exec_list copies;
+   struct exec_list entries;
 } nir_parallel_copy_instr;
 
 NIR_DEFINE_CAST(nir_instr_as_alu, nir_instr, nir_alu_instr, instr)
 NIR_DEFINE_CAST(nir_instr_as_call, nir_instr, nir_call_instr, instr)
 NIR_DEFINE_CAST(nir_instr_as_jump, nir_instr, nir_jump_instr, instr)
-NIR_DEFINE_CAST(nir_instr_as_texture, nir_instr, nir_tex_instr, instr)
+NIR_DEFINE_CAST(nir_instr_as_tex, nir_instr, nir_tex_instr, instr)
 NIR_DEFINE_CAST(nir_instr_as_intrinsic, nir_instr, nir_intrinsic_instr, instr)
 NIR_DEFINE_CAST(nir_instr_as_load_const, nir_instr, nir_load_const_instr, instr)
 NIR_DEFINE_CAST(nir_instr_as_ssa_undef, nir_instr, nir_ssa_undef_instr, instr)
@@ -1032,8 +1193,10 @@ typedef struct nir_cf_node {
 
 typedef struct nir_block {
    nir_cf_node cf_node;
-   struct exec_list instr_list;
 
+   struct exec_list instr_list; /** < list of nir_instr */
+
+   /** generic block index; generated by nir_index_blocks */
    unsigned index;
 
    /*
@@ -1042,6 +1205,7 @@ typedef struct nir_block {
     */
    struct nir_block *successors[2];
 
+   /* Set of nir_block predecessors in the CFG */
    struct set *predecessors;
 
    /*
@@ -1054,17 +1218,35 @@ typedef struct nir_block {
    unsigned num_dom_children;
    struct nir_block **dom_children;
 
+   /* Set of nir_block's on the dominance frontier of this block */
    struct set *dom_frontier;
 
+   /*
+    * These two indices have the property that dom_{pre,post}_index for each
+    * child of this block in the dominance tree will always be between
+    * dom_pre_index and dom_post_index for this block, which makes testing if
+    * a given block is dominated by another block an O(1) operation.
+    */
+   unsigned dom_pre_index, dom_post_index;
+
    /* live in and out for this block; used for liveness analysis */
    BITSET_WORD *live_in;
    BITSET_WORD *live_out;
 } nir_block;
 
-#define nir_block_first_instr(block) \
-   exec_node_data(nir_instr, exec_list_get_head(&(block)->instr_list), node)
-#define nir_block_last_instr(block) \
-   exec_node_data(nir_instr, exec_list_get_tail(&(block)->instr_list), node)
+static inline nir_instr *
+nir_block_first_instr(nir_block *block)
+{
+   struct exec_node *head = exec_list_get_head(&block->instr_list);
+   return exec_node_data(nir_instr, head, node);
+}
+
+static inline nir_instr *
+nir_block_last_instr(nir_block *block)
+{
+   struct exec_node *tail = exec_list_get_tail(&block->instr_list);
+   return exec_node_data(nir_instr, tail, node);
+}
 
 #define nir_foreach_instr(block, instr) \
    foreach_list_typed(nir_instr, instr, node, &(block)->instr_list)
@@ -1072,32 +1254,62 @@ typedef struct nir_block {
    foreach_list_typed_reverse(nir_instr, instr, node, &(block)->instr_list)
 #define nir_foreach_instr_safe(block, instr) \
    foreach_list_typed_safe(nir_instr, instr, node, &(block)->instr_list)
+#define nir_foreach_instr_safe_reverse(block, instr) \
+   foreach_list_typed_safe_reverse(nir_instr, instr, node, &(block)->instr_list)
 
-typedef struct {
+typedef struct nir_if {
    nir_cf_node cf_node;
    nir_src condition;
-   struct exec_list then_list;
-   struct exec_list else_list;
+
+   struct exec_list then_list; /** < list of nir_cf_node */
+   struct exec_list else_list; /** < list of nir_cf_node */
 } nir_if;
 
-#define nir_if_first_then_node(if) \
-   exec_node_data(nir_cf_node, exec_list_get_head(&(if)->then_list), node)
-#define nir_if_last_then_node(if) \
-   exec_node_data(nir_cf_node, exec_list_get_tail(&(if)->then_list), node)
-#define nir_if_first_else_node(if) \
-   exec_node_data(nir_cf_node, exec_list_get_head(&(if)->else_list), node)
-#define nir_if_last_else_node(if) \
-   exec_node_data(nir_cf_node, exec_list_get_tail(&(if)->else_list), node)
+static inline nir_cf_node *
+nir_if_first_then_node(nir_if *if_stmt)
+{
+   struct exec_node *head = exec_list_get_head(&if_stmt->then_list);
+   return exec_node_data(nir_cf_node, head, node);
+}
+
+static inline nir_cf_node *
+nir_if_last_then_node(nir_if *if_stmt)
+{
+   struct exec_node *tail = exec_list_get_tail(&if_stmt->then_list);
+   return exec_node_data(nir_cf_node, tail, node);
+}
+
+static inline nir_cf_node *
+nir_if_first_else_node(nir_if *if_stmt)
+{
+   struct exec_node *head = exec_list_get_head(&if_stmt->else_list);
+   return exec_node_data(nir_cf_node, head, node);
+}
+
+static inline nir_cf_node *
+nir_if_last_else_node(nir_if *if_stmt)
+{
+   struct exec_node *tail = exec_list_get_tail(&if_stmt->else_list);
+   return exec_node_data(nir_cf_node, tail, node);
+}
 
 typedef struct {
    nir_cf_node cf_node;
-   struct exec_list body;
+
+   struct exec_list body; /** < list of nir_cf_node */
 } nir_loop;
 
-#define nir_loop_first_cf_node(loop) \
-   exec_node_data(nir_cf_node, exec_list_get_head(&(loop)->body), node)
-#define nir_loop_last_cf_node(loop) \
-   exec_node_data(nir_cf_node, exec_list_get_tail(&(loop)->body), node)
+static inline nir_cf_node *
+nir_loop_first_cf_node(nir_loop *loop)
+{
+   return exec_node_data(nir_cf_node, exec_list_get_head(&loop->body), node);
+}
+
+static inline nir_cf_node *
+nir_loop_last_cf_node(nir_loop *loop)
+{
+   return exec_node_data(nir_cf_node, exec_list_get_tail(&loop->body), node);
+}
 
 /**
  * Various bits of metadata that can may be created or required by
@@ -1145,17 +1357,37 @@ typedef struct {
    nir_metadata valid_metadata;
 } nir_function_impl;
 
-#define nir_cf_node_next(_node) \
-   exec_node_data(nir_cf_node, exec_node_get_next(&(_node)->node), node)
+static inline nir_cf_node *
+nir_cf_node_next(nir_cf_node *node)
+{
+   struct exec_node *next = exec_node_get_next(&node->node);
+   if (exec_node_is_tail_sentinel(next))
+      return NULL;
+   else
+      return exec_node_data(nir_cf_node, next, node);
+}
 
-#define nir_cf_node_prev(_node) \
-   exec_node_data(nir_cf_node, exec_node_get_prev(&(_node)->node), node)
+static inline nir_cf_node *
+nir_cf_node_prev(nir_cf_node *node)
+{
+   struct exec_node *prev = exec_node_get_prev(&node->node);
+   if (exec_node_is_head_sentinel(prev))
+      return NULL;
+   else
+      return exec_node_data(nir_cf_node, prev, node);
+}
 
-#define nir_cf_node_is_first(_node) \
-   exec_node_is_head_sentinel((_node)->node.prev)
+static inline bool
+nir_cf_node_is_first(const nir_cf_node *node)
+{
+   return exec_node_is_head_sentinel(node->node.prev);
+}
 
-#define nir_cf_node_is_last(_node) \
-   exec_node_is_tail_sentinel((_node)->node.next)
+static inline bool
+nir_cf_node_is_last(const nir_cf_node *node)
+{
+   return exec_node_is_tail_sentinel(node->node.next);
+}
 
 NIR_DEFINE_CAST(nir_cf_node_as_block, nir_cf_node, nir_block, cf_node)
 NIR_DEFINE_CAST(nir_cf_node_as_if, nir_cf_node, nir_if, cf_node)
@@ -1189,7 +1421,7 @@ typedef struct nir_function_overload {
 typedef struct nir_function {
    struct exec_node node;
 
-   struct exec_list overload_list;
+   struct exec_list overload_list; /** < list of nir_function_overload */
    const char *name;
    struct nir_shader *shader;
 } nir_function;
@@ -1198,30 +1430,55 @@ typedef struct nir_function {
    exec_node_data(nir_function_overload, \
                   exec_list_get_head(&(func)->overload_list), node)
 
+typedef struct nir_shader_compiler_options {
+   bool lower_ffma;
+   bool lower_flrp;
+   bool lower_fpow;
+   bool lower_fsat;
+   bool lower_fsqrt;
+   /** lowers fneg and ineg to fsub and isub. */
+   bool lower_negate;
+   /** lowers fsub and isub to fadd+fneg and iadd+ineg. */
+   bool lower_sub;
+
+   /* lower {slt,sge,seq,sne} to {flt,fge,feq,fne} + b2f: */
+   bool lower_scmp;
+
+   /**
+    * Does the driver support real 32-bit integers?  (Otherwise, integers
+    * are simulated by floats.)
+    */
+   bool native_integers;
+} nir_shader_compiler_options;
+
 typedef struct nir_shader {
-   /** hash table of name -> uniform */
-   struct hash_table *uniforms;
+   /** hash table of name -> uniform nir_variable */
+   struct exec_list uniforms;
+
+   /** hash table of name -> input nir_variable */
+   struct exec_list inputs;
 
-   /** hash table of name -> input */
-   struct hash_table *inputs;
+   /** hash table of name -> output nir_variable */
+   struct exec_list outputs;
 
-   /** hash table of name -> output */
-   struct hash_table *outputs;
+   /** Set of driver-specific options for the shader.
+    *
+    * The memory for the options is expected to be kept in a single static
+    * copy by the driver.
+    */
+   const struct nir_shader_compiler_options *options;
 
    /** list of global variables in the shader */
    struct exec_list globals;
 
+   /** list of system value variables in the shader */
    struct exec_list system_values;
 
-   struct exec_list functions;
+   struct exec_list functions; /** < list of nir_function */
 
-   /** list of global registers in the shader */
+   /** list of global register in the shader */
    struct exec_list registers;
 
-   /** structures used in this shader */
-   unsigned num_user_structures;
-   struct glsl_type **user_structures;
-
    /** next available global register index */
    unsigned reg_alloc;
 
@@ -1230,14 +1487,18 @@ typedef struct nir_shader {
     * access plus one
     */
    unsigned num_inputs, num_uniforms, num_outputs;
+
+   /** the number of uniforms that are only accessed directly */
+   unsigned num_direct_uniforms;
 } nir_shader;
 
-#define nir_foreach_overload(shader, overload) \
+#define nir_foreach_overload(shader, overload)                        \
    foreach_list_typed(nir_function, func, node, &(shader)->functions) \
       foreach_list_typed(nir_function_overload, overload, node, \
                          &(func)->overload_list)
 
-nir_shader *nir_shader_create(void *mem_ctx);
+nir_shader *nir_shader_create(void *mem_ctx,
+                              const nir_shader_compiler_options *options);
 
 /** creates a register, including assigning it an index and adding it to the list */
 nir_register *nir_global_reg_create(nir_shader *shader);
@@ -1278,28 +1539,30 @@ void nir_cf_node_remove(nir_cf_node *node);
 /** requests that the given pieces of metadata be generated */
 void nir_metadata_require(nir_function_impl *impl, nir_metadata required);
 /** dirties all but the preserved metadata */
-void nir_metadata_dirty(nir_function_impl *impl, nir_metadata preserved);
+void nir_metadata_preserve(nir_function_impl *impl, nir_metadata preserved);
 
 /** creates an instruction with default swizzle/writemask/etc. with NULL registers */
-nir_alu_instr *nir_alu_instr_create(void *mem_ctx, nir_op op);
+nir_alu_instr *nir_alu_instr_create(nir_shader *shader, nir_op op);
 
-nir_jump_instr *nir_jump_instr_create(void *mem_ctx, nir_jump_type type);
+nir_jump_instr *nir_jump_instr_create(nir_shader *shader, nir_jump_type type);
 
-nir_load_const_instr *nir_load_const_instr_create(void *mem_ctx);
+nir_load_const_instr *nir_load_const_instr_create(nir_shader *shader,
+                                                  unsigned num_components);
 
-nir_intrinsic_instr *nir_intrinsic_instr_create(void *mem_ctx,
+nir_intrinsic_instr *nir_intrinsic_instr_create(nir_shader *shader,
                                                 nir_intrinsic_op op);
 
-nir_call_instr *nir_call_instr_create(void *mem_ctx,
+nir_call_instr *nir_call_instr_create(nir_shader *shader,
                                       nir_function_overload *callee);
 
-nir_tex_instr *nir_tex_instr_create(void *mem_ctx, unsigned num_srcs);
+nir_tex_instr *nir_tex_instr_create(nir_shader *shader, unsigned num_srcs);
 
-nir_phi_instr *nir_phi_instr_create(void *mem_ctx);
+nir_phi_instr *nir_phi_instr_create(nir_shader *shader);
 
-nir_parallel_copy_instr *nir_parallel_copy_instr_create(void *mem_ctx);
+nir_parallel_copy_instr *nir_parallel_copy_instr_create(nir_shader *shader);
 
-nir_ssa_undef_instr *nir_ssa_undef_instr_create(void *mem_ctx);
+nir_ssa_undef_instr *nir_ssa_undef_instr_create(nir_shader *shader,
+                                                unsigned num_components);
 
 nir_deref_var *nir_deref_var_create(void *mem_ctx, nir_variable *var);
 nir_deref_array *nir_deref_array_create(void *mem_ctx);
@@ -1307,6 +1570,9 @@ nir_deref_struct *nir_deref_struct_create(void *mem_ctx, unsigned field_index);
 
 nir_deref *nir_copy_deref(void *mem_ctx, nir_deref *deref);
 
+nir_load_const_instr *
+nir_deref_get_const_initializer_load(nir_shader *shader, nir_deref_var *deref);
+
 void nir_instr_insert_before(nir_instr *instr, nir_instr *before);
 void nir_instr_insert_after(nir_instr *instr, nir_instr *after);
 
@@ -1321,15 +1587,22 @@ void nir_instr_insert_after_cf_list(struct exec_list *list, nir_instr *after);
 
 void nir_instr_remove(nir_instr *instr);
 
+typedef bool (*nir_foreach_ssa_def_cb)(nir_ssa_def *def, void *state);
 typedef bool (*nir_foreach_dest_cb)(nir_dest *dest, void *state);
 typedef bool (*nir_foreach_src_cb)(nir_src *src, void *state);
+bool nir_foreach_ssa_def(nir_instr *instr, nir_foreach_ssa_def_cb cb,
+                         void *state);
 bool nir_foreach_dest(nir_instr *instr, nir_foreach_dest_cb cb, void *state);
 bool nir_foreach_src(nir_instr *instr, nir_foreach_src_cb cb, void *state);
 
 nir_const_value *nir_src_as_const_value(nir_src src);
 bool nir_srcs_equal(nir_src src1, nir_src src2);
 void nir_instr_rewrite_src(nir_instr *instr, nir_src *src, nir_src new_src);
+void nir_instr_move_src(nir_instr *dest_instr, nir_src *dest, nir_src *src);
+void nir_if_rewrite_condition(nir_if *if_stmt, nir_src new_src);
 
+void nir_ssa_dest_init(nir_instr *instr, nir_dest *dest,
+                       unsigned num_components, const char *name);
 void nir_ssa_def_init(nir_instr *instr, nir_ssa_def *def,
                       unsigned num_components, const char *name);
 void nir_ssa_def_rewrite_uses(nir_ssa_def *def, nir_src new_src, void *mem_ctx);
@@ -1344,7 +1617,7 @@ bool nir_foreach_block_reverse(nir_function_impl *impl, nir_foreach_block_cb cb,
 /* If the following CF node is an if, this function returns that if.
  * Otherwise, it returns NULL.
  */
-nir_if *nir_block_following_if(nir_block *block);
+nir_if *nir_block_get_following_if(nir_block *block);
 
 void nir_index_local_regs(nir_function_impl *impl);
 void nir_index_global_regs(nir_shader *shader);
@@ -1353,12 +1626,20 @@ void nir_index_ssa_defs(nir_function_impl *impl);
 void nir_index_blocks(nir_function_impl *impl);
 
 void nir_print_shader(nir_shader *shader, FILE *fp);
+void nir_print_instr(const nir_instr *instr, FILE *fp);
 
+#ifdef DEBUG
 void nir_validate_shader(nir_shader *shader);
+#else
+static inline void nir_validate_shader(nir_shader *shader) { (void) shader; }
+#endif /* DEBUG */
 
 void nir_calc_dominance_impl(nir_function_impl *impl);
 void nir_calc_dominance(nir_shader *shader);
 
+nir_block *nir_dominance_lca(nir_block *b1, nir_block *b2);
+bool nir_block_dominates(nir_block *parent, nir_block *child);
+
 void nir_dump_dom_tree_impl(nir_function_impl *impl, FILE *fp);
 void nir_dump_dom_tree(nir_shader *shader, FILE *fp);
 
@@ -1370,33 +1651,63 @@ void nir_dump_cfg(nir_shader *shader, FILE *fp);
 
 void nir_split_var_copies(nir_shader *shader);
 
+void nir_lower_var_copy_instr(nir_intrinsic_instr *copy, void *mem_ctx);
+void nir_lower_var_copies(nir_shader *shader);
+
 void nir_lower_global_vars_to_local(nir_shader *shader);
 
 void nir_lower_locals_to_regs(nir_shader *shader);
 
-void nir_lower_io(nir_shader *shader);
+void nir_assign_var_locations(struct exec_list *var_list,
+                              unsigned *size,
+                              bool is_scalar);
+void nir_assign_var_locations_direct_first(nir_shader *shader,
+                                           struct exec_list *var_list,
+                                           unsigned *direct_size,
+                                           unsigned *size,
+                                           bool is_scalar);
+
+void nir_lower_io(nir_shader *shader, bool is_scalar);
 
-void nir_lower_variables(nir_shader *shader);
+void nir_lower_vars_to_ssa(nir_shader *shader);
 
 void nir_remove_dead_variables(nir_shader *shader);
 
 void nir_lower_vec_to_movs(nir_shader *shader);
+void nir_lower_alu_to_scalar(nir_shader *shader);
+void nir_lower_load_const_to_scalar(nir_shader *shader);
+
+void nir_lower_phis_to_scalar(nir_shader *shader);
 
 void nir_lower_samplers(nir_shader *shader,
-                        struct gl_shader_program *shader_program,
-                        struct gl_program *prog);
+                        const struct gl_shader_program *shader_program,
+                        gl_shader_stage stage);
+void nir_lower_samplers_for_vk(nir_shader *shader);
 
 void nir_lower_system_values(nir_shader *shader);
+void nir_lower_tex_projector(nir_shader *shader);
+void nir_lower_idiv(nir_shader *shader);
 
 void nir_lower_atomics(nir_shader *shader);
 void nir_lower_to_source_mods(nir_shader *shader);
 
+void nir_normalize_cubemap_coords(nir_shader *shader);
+
 void nir_live_variables_impl(nir_function_impl *impl);
 bool nir_ssa_defs_interfere(nir_ssa_def *a, nir_ssa_def *b);
 
 void nir_convert_to_ssa_impl(nir_function_impl *impl);
 void nir_convert_to_ssa(nir_shader *shader);
-void nir_convert_from_ssa(nir_shader *shader);
+
+/* If phi_webs_only is true, only convert SSA values involved in phi nodes to
+ * registers.  If false, convert all values (even those not involved in a phi
+ * node) to registers.
+ */
+void nir_convert_from_ssa(nir_shader *shader, bool phi_webs_only);
+
+bool nir_opt_algebraic(nir_shader *shader);
+bool nir_opt_algebraic_late(nir_shader *shader);
+bool nir_opt_constant_folding(nir_shader *shader);
 
 bool nir_opt_global_to_local(nir_shader *shader);
 
@@ -1408,9 +1719,17 @@ bool nir_opt_cse(nir_shader *shader);
 bool nir_opt_dce_impl(nir_function_impl *impl);
 bool nir_opt_dce(nir_shader *shader);
 
+void nir_opt_gcm(nir_shader *shader);
+
 bool nir_opt_peephole_select(nir_shader *shader);
 bool nir_opt_peephole_ffma(nir_shader *shader);
 
+bool nir_opt_remove_phis(nir_shader *shader);
+
+bool nir_opt_undef(nir_shader *shader);
+
+void nir_sweep(nir_shader *shader);
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif