X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglsl%2Fnir%2Fnir.h;h=70af06e69713e5dc8be6b3b74b8196c4fa1daa68;hb=6a7ca4ef2cd3f39d3b5e77051cb3f3175e9e60df;hp=8887c5815e71c1377e31985129465916916567e2;hpb=dfb3abbaecfbe30b8858a5428c604f9d90f65505;p=mesa.git diff --git a/src/glsl/nir/nir.h b/src/glsl/nir/nir.h index 8887c5815e7..70af06e6971 100644 --- a/src/glsl/nir/nir.h +++ b/src/glsl/nir/nir.h @@ -28,19 +28,25 @@ #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 +#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,13 +392,13 @@ 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 { @@ -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); +} -#define nir_instr_prev(instr) \ - exec_node_data(nir_instr, (instr)->node.prev, 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)); +} + +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]; @@ -620,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, @@ -670,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; @@ -694,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; @@ -701,7 +852,14 @@ 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]; @@ -718,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 @@ -763,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]; @@ -786,8 +944,13 @@ typedef enum { nir_tex_src_ddx, nir_tex_src_ddy, nir_tex_src_sampler_offset, /* < dynamically uniform indirect offset */ - nir_num_texinput_types -} nir_texinput_type; + 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 */ @@ -810,8 +973,7 @@ typedef struct { 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; @@ -827,6 +989,9 @@ 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, @@ -843,7 +1008,8 @@ typedef struct { 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: @@ -861,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 @@ -898,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; @@ -918,22 +1088,9 @@ typedef struct { typedef struct { nir_instr instr; - union { - nir_const_value value; - nir_const_value *array; - }; - - unsigned num_components; + nir_const_value value; - /** - * 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; - - nir_dest dest; + nir_ssa_def def; } nir_load_const_instr; typedef enum { @@ -956,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; @@ -971,18 +1135,20 @@ 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) @@ -1027,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; /* @@ -1037,6 +1205,7 @@ typedef struct nir_block { */ struct nir_block *successors[2]; + /* Set of nir_block predecessors in the CFG */ struct set *predecessors; /* @@ -1049,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) @@ -1067,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 @@ -1140,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) @@ -1184,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; @@ -1193,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 */ - struct hash_table *inputs; + /** hash table of name -> input nir_variable */ + struct exec_list inputs; - /** hash table of name -> output */ - struct hash_table *outputs; + /** hash table of name -> output nir_variable */ + struct exec_list 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; @@ -1225,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); @@ -1276,25 +1542,27 @@ void nir_metadata_require(nir_function_impl *impl, nir_metadata required); 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); @@ -1302,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); @@ -1316,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); @@ -1339,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); @@ -1348,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); @@ -1365,35 +1651,62 @@ 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); @@ -1406,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