On Sun, Apr 8, 2018 at 1:38 PM, Rob Clark <robdcl...@gmail.com> wrote: > On Tue, Apr 3, 2018 at 2:32 PM, Jason Ekstrand <ja...@jlekstrand.net> wrote: >> This commit adds a new instruction type to NIR for handling derefs. >> Nothing uses it yet but this adds the data structure as well as all of >> the code to validate, print, clone, and [de]serialize them. >> --- >> src/compiler/nir/nir.c | 50 +++++++++++++++++++ >> src/compiler/nir/nir.h | 58 ++++++++++++++++++++- >> src/compiler/nir/nir_clone.c | 42 ++++++++++++++++ >> src/compiler/nir/nir_instr_set.c | 78 +++++++++++++++++++++++++++++ >> src/compiler/nir/nir_opt_copy_propagate.c | 62 +++++++++++++++++++---- >> src/compiler/nir/nir_opt_dce.c | 7 +++ >> src/compiler/nir/nir_print.c | 56 +++++++++++++++++++++ >> src/compiler/nir/nir_serialize.c | 81 >> ++++++++++++++++++++++++++++++ >> src/compiler/nir/nir_validate.c | 83 >> +++++++++++++++++++++++++++++++ >> 9 files changed, 506 insertions(+), 11 deletions(-) >> >> diff --git a/src/compiler/nir/nir.c b/src/compiler/nir/nir.c >> index 8364197..a538f22 100644 >> --- a/src/compiler/nir/nir.c >> +++ b/src/compiler/nir/nir.c >> @@ -470,6 +470,26 @@ nir_alu_instr_create(nir_shader *shader, nir_op op) >> return instr; >> } >> >> +nir_deref_instr * >> +nir_deref_instr_create(nir_shader *shader, nir_deref_type deref_type) >> +{ >> + nir_deref_instr *instr = >> + rzalloc_size(shader, sizeof(nir_deref_instr)); >> + >> + instr_init(&instr->instr, nir_instr_type_deref); >> + >> + instr->deref_type = deref_type; >> + if (deref_type != nir_deref_type_var) >> + src_init(&instr->parent); >> + >> + if (deref_type == nir_deref_type_array) >> + src_init(&instr->arr.index); >> + >> + dest_init(&instr->dest); >> + >> + return instr; >> +} >> + >> nir_jump_instr * >> nir_jump_instr_create(nir_shader *shader, nir_jump_type type) >> { >> @@ -1199,6 +1219,12 @@ visit_alu_dest(nir_alu_instr *instr, >> nir_foreach_dest_cb cb, void *state) >> } >> >> static bool >> +visit_deref_dest(nir_deref_instr *instr, nir_foreach_dest_cb cb, void >> *state) >> +{ >> + return cb(&instr->dest, state); >> +} >> + >> +static bool >> visit_intrinsic_dest(nir_intrinsic_instr *instr, nir_foreach_dest_cb cb, >> void *state) >> { >> @@ -1239,6 +1265,8 @@ nir_foreach_dest(nir_instr *instr, nir_foreach_dest_cb >> cb, void *state) >> switch (instr->type) { >> case nir_instr_type_alu: >> return visit_alu_dest(nir_instr_as_alu(instr), cb, state); >> + case nir_instr_type_deref: >> + return visit_deref_dest(nir_instr_as_deref(instr), cb, state); >> case nir_instr_type_intrinsic: >> return visit_intrinsic_dest(nir_instr_as_intrinsic(instr), cb, state); >> case nir_instr_type_tex: >> @@ -1284,6 +1312,7 @@ nir_foreach_ssa_def(nir_instr *instr, >> nir_foreach_ssa_def_cb cb, void *state) >> { >> switch (instr->type) { >> case nir_instr_type_alu: >> + case nir_instr_type_deref: >> case nir_instr_type_tex: >> case nir_instr_type_intrinsic: >> case nir_instr_type_phi: >> @@ -1350,6 +1379,23 @@ visit_alu_src(nir_alu_instr *instr, >> nir_foreach_src_cb cb, void *state) >> } >> >> static bool >> +visit_deref_instr_src(nir_deref_instr *instr, >> + nir_foreach_src_cb cb, void *state) >> +{ >> + if (instr->deref_type != nir_deref_type_var) { >> + if (!visit_src(&instr->parent, cb, state)) >> + return false; >> + } >> + >> + if (instr->deref_type == nir_deref_type_array) { >> + if (!visit_src(&instr->arr.index, cb, state)) >> + return false; >> + } >> + >> + return true; >> +} >> + >> +static bool >> visit_tex_src(nir_tex_instr *instr, nir_foreach_src_cb cb, void *state) >> { >> for (unsigned i = 0; i < instr->num_srcs; i++) { >> @@ -1437,6 +1483,10 @@ nir_foreach_src(nir_instr *instr, nir_foreach_src_cb >> cb, void *state) >> if (!visit_alu_src(nir_instr_as_alu(instr), cb, state)) >> return false; >> break; >> + case nir_instr_type_deref: >> + if (!visit_deref_instr_src(nir_instr_as_deref(instr), cb, state)) >> + return false; >> + break; >> case nir_instr_type_intrinsic: >> if (!visit_intrinsic_src(nir_instr_as_intrinsic(instr), cb, state)) >> return false; >> diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h >> index cc7c401..db7dc91 100644 >> --- a/src/compiler/nir/nir.h >> +++ b/src/compiler/nir/nir.h >> @@ -427,6 +427,7 @@ typedef struct nir_register { >> >> typedef enum { >> nir_instr_type_alu, >> + nir_instr_type_deref, >> nir_instr_type_call, >> nir_instr_type_tex, >> nir_instr_type_intrinsic, >> @@ -894,7 +895,9 @@ bool nir_alu_srcs_equal(const nir_alu_instr *alu1, const >> nir_alu_instr *alu2, >> typedef enum { >> nir_deref_type_var, >> nir_deref_type_array, >> - nir_deref_type_struct >> + nir_deref_type_array_wildcard, >> + nir_deref_type_struct, >> + nir_deref_type_cast, >> } nir_deref_type; >> >> typedef struct nir_deref { >> @@ -956,6 +959,56 @@ nir_deref_tail(nir_deref *deref) >> typedef struct { >> nir_instr instr; >> >> + /** The type of this deref instruction */ >> + nir_deref_type deref_type; >> + >> + /** The mode of the underlying variable */ >> + nir_variable_mode mode; > > In fact, it seems like deref->mode is unused outside of nir_print and > nir_validate.. for logical addressing we can get the mode from the > deref_var->var at the start of the chain, and deref->mode has no > meaning for physical addressing (where the mode comes from the > pointer). > > So maybe just drop deref->mode?
Isn't it still useful with logical addressing in case a var is not immediately available? (think VK_KHR_variable_pointers) Also I could see this being useful in physical addressing too to avoid all passes working with derefs needing to do the constant folding? - Bas > > BR, > -R > >> + /** The dereferenced type of the resulting pointer value */ >> + const struct glsl_type *type; >> + >> + union { >> + /** Variable being dereferenced if deref_type is a deref_var */ >> + nir_variable *var; >> + >> + /** Parent deref if deref_type is not deref_var */ >> + nir_src parent; >> + }; >> + >> + /** Additional deref parameters */ >> + union { >> + struct { >> + nir_src index; >> + } arr; >> + >> + struct { >> + unsigned index; >> + } strct; >> + }; >> + >> + /** Destination to store the resulting "pointer" */ >> + nir_dest dest; >> +} nir_deref_instr; >> + >> +NIR_DEFINE_CAST(nir_instr_as_deref, nir_instr, nir_deref_instr, instr, >> + type, nir_instr_type_deref) >> + >> +static inline nir_deref_instr * >> +nir_src_as_deref(nir_src src) >> +{ >> + if (!src.is_ssa) >> + return NULL; >> + >> + if (src.ssa->parent_instr->type != nir_instr_type_deref) >> + return NULL; >> + >> + return nir_instr_as_deref(src.ssa->parent_instr); >> +} >> + >> +typedef struct { >> + nir_instr instr; >> + >> unsigned num_params; >> nir_deref_var **params; >> nir_deref_var *return_deref; >> @@ -2044,6 +2097,9 @@ 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(nir_shader *shader, nir_op op); >> >> +nir_deref_instr *nir_deref_instr_create(nir_shader *shader, >> + nir_deref_type deref_type); >> + >> nir_jump_instr *nir_jump_instr_create(nir_shader *shader, nir_jump_type >> type); >> >> nir_load_const_instr *nir_load_const_instr_create(nir_shader *shader, >> diff --git a/src/compiler/nir/nir_clone.c b/src/compiler/nir/nir_clone.c >> index bcfdaa7..20eaaff 100644 >> --- a/src/compiler/nir/nir_clone.c >> +++ b/src/compiler/nir/nir_clone.c >> @@ -346,6 +346,46 @@ clone_alu(clone_state *state, const nir_alu_instr *alu) >> return nalu; >> } >> >> +static nir_deref_instr * >> +clone_deref_instr(clone_state *state, const nir_deref_instr *deref) >> +{ >> + nir_deref_instr *nderef = >> + nir_deref_instr_create(state->ns, deref->deref_type); >> + >> + __clone_dst(state, &nderef->instr, &nderef->dest, &deref->dest); >> + >> + nderef->mode = deref->mode; >> + nderef->type = deref->type; >> + >> + if (deref->deref_type == nir_deref_type_var) { >> + nderef->var = remap_var(state, deref->var); >> + return nderef; >> + } >> + >> + __clone_src(state, &nderef->instr, &nderef->parent, &deref->parent); >> + >> + switch (deref->deref_type) { >> + case nir_deref_type_struct: >> + nderef->strct.index = deref->strct.index; >> + break; >> + >> + case nir_deref_type_array: >> + __clone_src(state, &nderef->instr, >> + &nderef->arr.index, &deref->arr.index); >> + break; >> + >> + case nir_deref_type_array_wildcard: >> + case nir_deref_type_cast: >> + /* Nothing to do */ >> + break; >> + >> + default: >> + unreachable("Invalid instruction deref type"); >> + } >> + >> + return nderef; >> +} >> + >> static nir_intrinsic_instr * >> clone_intrinsic(clone_state *state, const nir_intrinsic_instr *itr) >> { >> @@ -502,6 +542,8 @@ clone_instr(clone_state *state, const nir_instr *instr) >> switch (instr->type) { >> case nir_instr_type_alu: >> return &clone_alu(state, nir_instr_as_alu(instr))->instr; >> + case nir_instr_type_deref: >> + return &clone_deref_instr(state, nir_instr_as_deref(instr))->instr; >> case nir_instr_type_intrinsic: >> return &clone_intrinsic(state, nir_instr_as_intrinsic(instr))->instr; >> case nir_instr_type_load_const: >> diff --git a/src/compiler/nir/nir_instr_set.c >> b/src/compiler/nir/nir_instr_set.c >> index 9cb9ed4..939ddcc 100644 >> --- a/src/compiler/nir/nir_instr_set.c >> +++ b/src/compiler/nir/nir_instr_set.c >> @@ -79,6 +79,40 @@ hash_alu(uint32_t hash, const nir_alu_instr *instr) >> } >> >> static uint32_t >> +hash_deref(uint32_t hash, const nir_deref_instr *instr) >> +{ >> + hash = HASH(hash, instr->deref_type); >> + hash = HASH(hash, instr->mode); >> + hash = HASH(hash, instr->type); >> + >> + if (instr->deref_type == nir_deref_type_var) >> + return HASH(hash, instr->var); >> + >> + hash = hash_src(hash, &instr->parent); >> + >> + switch (instr->deref_type) { >> + case nir_deref_type_struct: >> + hash = HASH(hash, instr->strct.index); >> + break; >> + >> + case nir_deref_type_array: >> + hash = hash_src(hash, &instr->arr.index); >> + break; >> + >> + case nir_deref_type_var: >> + case nir_deref_type_array_wildcard: >> + case nir_deref_type_cast: >> + /* Nothing to do */ >> + break; >> + >> + default: >> + unreachable("Invalid instruction deref type"); >> + } >> + >> + return hash; >> +} >> + >> +static uint32_t >> hash_load_const(uint32_t hash, const nir_load_const_instr *instr) >> { >> hash = HASH(hash, instr->def.num_components); >> @@ -182,6 +216,9 @@ hash_instr(const void *data) >> case nir_instr_type_alu: >> hash = hash_alu(hash, nir_instr_as_alu(instr)); >> break; >> + case nir_instr_type_deref: >> + hash = hash_deref(hash, nir_instr_as_deref(instr)); >> + break; >> case nir_instr_type_load_const: >> hash = hash_load_const(hash, nir_instr_as_load_const(instr)); >> break; >> @@ -289,6 +326,43 @@ nir_instrs_equal(const nir_instr *instr1, const >> nir_instr *instr2) >> } >> return true; >> } >> + case nir_instr_type_deref: { >> + nir_deref_instr *deref1 = nir_instr_as_deref(instr1); >> + nir_deref_instr *deref2 = nir_instr_as_deref(instr2); >> + >> + if (deref1->deref_type != deref2->deref_type || >> + deref1->mode != deref2->mode || >> + deref1->type != deref2->type) >> + return false; >> + >> + if (deref1->deref_type == nir_deref_type_var) >> + return deref1->var == deref2->var; >> + >> + if (!nir_srcs_equal(deref1->parent, deref2->parent)) >> + return false; >> + >> + switch (deref1->deref_type) { >> + case nir_deref_type_struct: >> + if (deref1->strct.index != deref2->strct.index) >> + return false; >> + break; >> + >> + case nir_deref_type_array: >> + if (!nir_srcs_equal(deref1->arr.index, deref2->arr.index)) >> + return false; >> + break; >> + >> + case nir_deref_type_var: >> + case nir_deref_type_array_wildcard: >> + case nir_deref_type_cast: >> + /* Nothing to do */ >> + break; >> + >> + default: >> + unreachable("Invalid instruction deref type"); >> + } >> + break; >> + } >> case nir_instr_type_tex: { >> nir_tex_instr *tex1 = nir_instr_as_tex(instr1); >> nir_tex_instr *tex2 = nir_instr_as_tex(instr2); >> @@ -430,6 +504,7 @@ instr_can_rewrite(nir_instr *instr) >> >> switch (instr->type) { >> case nir_instr_type_alu: >> + case nir_instr_type_deref: >> case nir_instr_type_load_const: >> case nir_instr_type_phi: >> return true; >> @@ -468,6 +543,9 @@ nir_instr_get_dest_ssa_def(nir_instr *instr) >> case nir_instr_type_alu: >> assert(nir_instr_as_alu(instr)->dest.dest.is_ssa); >> return &nir_instr_as_alu(instr)->dest.dest.ssa; >> + case nir_instr_type_deref: >> + assert(nir_instr_as_deref(instr)->dest.is_ssa); >> + return &nir_instr_as_deref(instr)->dest.ssa; >> case nir_instr_type_load_const: >> return &nir_instr_as_load_const(instr)->def; >> case nir_instr_type_phi: >> diff --git a/src/compiler/nir/nir_opt_copy_propagate.c >> b/src/compiler/nir/nir_opt_copy_propagate.c >> index c4001fa..594727c 100644 >> --- a/src/compiler/nir/nir_opt_copy_propagate.c >> +++ b/src/compiler/nir/nir_opt_copy_propagate.c >> @@ -99,6 +99,22 @@ is_swizzleless_move(nir_alu_instr *instr) >> } >> >> static bool >> +is_trivial_deref_cast(nir_deref_instr *cast) >> +{ >> + nir_deref_instr *parent = nir_src_as_deref(cast->parent); >> + if (!parent) >> + return false; >> + >> + if (cast->deref_type != nir_deref_type_cast) >> + return false; >> + >> + return cast->mode == parent->mode && >> + cast->type == parent->type && >> + cast->dest.ssa.num_components == parent->dest.ssa.num_components >> && >> + cast->dest.ssa.bit_size == parent->dest.ssa.bit_size; >> +} >> + >> +static bool >> copy_prop_src(nir_src *src, nir_instr *parent_instr, nir_if *parent_if, >> unsigned num_components) >> { >> @@ -109,23 +125,31 @@ copy_prop_src(nir_src *src, nir_instr *parent_instr, >> nir_if *parent_if, >> } >> >> nir_instr *src_instr = src->ssa->parent_instr; >> - if (src_instr->type != nir_instr_type_alu) >> - return false; >> + nir_ssa_def *copy_def; >> + if (src_instr->type == nir_instr_type_alu) { >> + nir_alu_instr *alu_instr = nir_instr_as_alu(src_instr); >> + if (!is_swizzleless_move(alu_instr)) >> + return false; >> >> - nir_alu_instr *alu_instr = nir_instr_as_alu(src_instr); >> - if (!is_swizzleless_move(alu_instr)) >> - return false; >> + if (alu_instr->src[0].src.ssa->num_components != num_components) >> + return false; >> >> - if (alu_instr->src[0].src.ssa->num_components != num_components) >> + copy_def= alu_instr->src[0].src.ssa; >> + } else if (src_instr->type == nir_instr_type_deref) { >> + nir_deref_instr *deref_instr = nir_instr_as_deref(src_instr); >> + if (!is_trivial_deref_cast(deref_instr)) >> + return false; >> + >> + copy_def = deref_instr->parent.ssa; >> + } else { >> return false; >> + } >> >> if (parent_instr) { >> - nir_instr_rewrite_src(parent_instr, src, >> - nir_src_for_ssa(alu_instr->src[0].src.ssa)); >> + nir_instr_rewrite_src(parent_instr, src, nir_src_for_ssa(copy_def)); >> } else { >> assert(src == &parent_if->condition); >> - nir_if_rewrite_condition(parent_if, >> - nir_src_for_ssa(alu_instr->src[0].src.ssa)); >> + nir_if_rewrite_condition(parent_if, nir_src_for_ssa(copy_def)); >> } >> >> return true; >> @@ -234,6 +258,24 @@ copy_prop_instr(nir_instr *instr) >> return progress; >> } >> >> + case nir_instr_type_deref: { >> + nir_deref_instr *deref = nir_instr_as_deref(instr); >> + >> + if (deref->deref_type != nir_deref_type_var) { >> + assert(deref->dest.is_ssa); >> + const unsigned comps = deref->dest.ssa.num_components; >> + while (copy_prop_src(&deref->parent, instr, NULL, comps)) >> + progress = true; >> + } >> + >> + if (deref->deref_type == nir_deref_type_array) { >> + while (copy_prop_src(&deref->arr.index, instr, NULL, 1)) >> + progress = true; >> + } >> + >> + return progress; >> + } >> + >> case nir_instr_type_tex: { >> nir_tex_instr *tex = nir_instr_as_tex(instr); >> for (unsigned i = 0; i < tex->num_srcs; i++) { >> diff --git a/src/compiler/nir/nir_opt_dce.c b/src/compiler/nir/nir_opt_dce.c >> index 570e430..c9b3388 100644 >> --- a/src/compiler/nir/nir_opt_dce.c >> +++ b/src/compiler/nir/nir_opt_dce.c >> @@ -52,6 +52,7 @@ static void >> init_instr(nir_instr *instr, nir_instr_worklist *worklist) >> { >> nir_alu_instr *alu_instr; >> + nir_deref_instr *deref_instr; >> nir_intrinsic_instr *intrin_instr; >> nir_tex_instr *tex_instr; >> >> @@ -73,6 +74,12 @@ init_instr(nir_instr *instr, nir_instr_worklist *worklist) >> mark_and_push(worklist, instr); >> break; >> >> + case nir_instr_type_deref: >> + deref_instr = nir_instr_as_deref(instr); >> + if (!deref_instr->dest.is_ssa) >> + mark_and_push(worklist, instr); >> + break; >> + >> case nir_instr_type_intrinsic: >> intrin_instr = nir_instr_as_intrinsic(instr); >> if (nir_intrinsic_infos[intrin_instr->intrinsic].flags & >> diff --git a/src/compiler/nir/nir_print.c b/src/compiler/nir/nir_print.c >> index 21f1309..64fdfb2 100644 >> --- a/src/compiler/nir/nir_print.c >> +++ b/src/compiler/nir/nir_print.c >> @@ -488,6 +488,58 @@ print_var_decl(nir_variable *var, print_state *state) >> } >> >> static void >> +print_deref_instr(nir_deref_instr *instr, print_state *state) >> +{ >> + FILE *fp = state->fp; >> + >> + print_dest(&instr->dest, state); >> + >> + if (instr->deref_type == nir_deref_type_var) { >> + fprintf(fp, " = deref %s", get_var_name(instr->var, state)); >> + return; >> + } else if (instr->deref_type == nir_deref_type_cast) { >> + fprintf(fp, " = deref (%s) (%s *)&", >> + get_variable_mode_str(instr->mode), >> + glsl_get_type_name(instr->type)); >> + print_src(&instr->parent, state); >> + return; >> + } >> + >> + fprintf(fp, " = deref (%s) &", get_variable_mode_str(instr->mode)); >> + print_src(&instr->parent, state); >> + >> + assert(instr->parent.is_ssa); >> + nir_deref_instr *parent = >> + nir_instr_as_deref(instr->parent.ssa->parent_instr); >> + >> + switch (instr->deref_type) { >> + case nir_deref_type_struct: >> + fprintf(fp, "->%s", >> + glsl_get_struct_elem_name(parent->type, instr->strct.index)); >> + break; >> + >> + case nir_deref_type_array: { >> + nir_const_value *const_index = >> nir_src_as_const_value(instr->arr.index); >> + if (const_index) { >> + fprintf(fp, "[%u]", const_index->u32[0]); >> + } else { >> + fprintf(fp, "["); >> + print_src(&instr->arr.index, state); >> + fprintf(fp, "]"); >> + } >> + break; >> + } >> + >> + case nir_deref_type_array_wildcard: >> + fprintf(fp, "[*]"); >> + break; >> + >> + default: >> + unreachable("Invalid deref instruction type"); >> + } >> +} >> + >> +static void >> print_var(nir_variable *var, print_state *state) >> { >> FILE *fp = state->fp; >> @@ -924,6 +976,10 @@ print_instr(const nir_instr *instr, print_state *state, >> unsigned tabs) >> print_alu_instr(nir_instr_as_alu(instr), state); >> break; >> >> + case nir_instr_type_deref: >> + print_deref_instr(nir_instr_as_deref(instr), state); >> + break; >> + >> case nir_instr_type_call: >> print_call_instr(nir_instr_as_call(instr), state); >> break; >> diff --git a/src/compiler/nir/nir_serialize.c >> b/src/compiler/nir/nir_serialize.c >> index 00df49c..834a65b 100644 >> --- a/src/compiler/nir/nir_serialize.c >> +++ b/src/compiler/nir/nir_serialize.c >> @@ -479,6 +479,81 @@ read_alu(read_ctx *ctx) >> } >> >> static void >> +write_deref(write_ctx *ctx, const nir_deref_instr *deref) >> +{ >> + blob_write_uint32(ctx->blob, deref->deref_type); >> + >> + blob_write_uint32(ctx->blob, deref->mode); >> + encode_type_to_blob(ctx->blob, deref->type); >> + >> + write_dest(ctx, &deref->dest); >> + >> + if (deref->deref_type == nir_deref_type_var) { >> + write_object(ctx, deref->var); >> + return; >> + } >> + >> + write_src(ctx, &deref->parent); >> + >> + switch (deref->deref_type) { >> + case nir_deref_type_struct: >> + blob_write_uint32(ctx->blob, deref->strct.index); >> + break; >> + >> + case nir_deref_type_array: >> + write_src(ctx, &deref->arr.index); >> + break; >> + >> + case nir_deref_type_array_wildcard: >> + case nir_deref_type_cast: >> + /* Nothing to do */ >> + break; >> + >> + default: >> + unreachable("Invalid deref type"); >> + } >> +} >> + >> +static nir_deref_instr * >> +read_deref(read_ctx *ctx) >> +{ >> + nir_deref_type deref_type = blob_read_uint32(ctx->blob); >> + nir_deref_instr *deref = nir_deref_instr_create(ctx->nir, deref_type); >> + >> + deref->mode = blob_read_uint32(ctx->blob); >> + deref->type = decode_type_from_blob(ctx->blob); >> + >> + read_dest(ctx, &deref->dest, &deref->instr); >> + >> + if (deref_type == nir_deref_type_var) { >> + deref->var = read_object(ctx); >> + return deref; >> + } >> + >> + read_src(ctx, &deref->parent, &deref->instr); >> + >> + switch (deref->deref_type) { >> + case nir_deref_type_struct: >> + deref->strct.index = blob_read_uint32(ctx->blob); >> + break; >> + >> + case nir_deref_type_array: >> + read_src(ctx, &deref->arr.index, &deref->instr); >> + break; >> + >> + case nir_deref_type_array_wildcard: >> + case nir_deref_type_cast: >> + /* Nothing to do */ >> + break; >> + >> + default: >> + unreachable("Invalid deref type"); >> + } >> + >> + return deref; >> +} >> + >> +static void >> write_intrinsic(write_ctx *ctx, const nir_intrinsic_instr *intrin) >> { >> blob_write_uint32(ctx->blob, intrin->intrinsic); >> @@ -803,6 +878,9 @@ write_instr(write_ctx *ctx, const nir_instr *instr) >> case nir_instr_type_alu: >> write_alu(ctx, nir_instr_as_alu(instr)); >> break; >> + case nir_instr_type_deref: >> + write_deref(ctx, nir_instr_as_deref(instr)); >> + break; >> case nir_instr_type_intrinsic: >> write_intrinsic(ctx, nir_instr_as_intrinsic(instr)); >> break; >> @@ -840,6 +918,9 @@ read_instr(read_ctx *ctx, nir_block *block) >> case nir_instr_type_alu: >> instr = &read_alu(ctx)->instr; >> break; >> + case nir_instr_type_deref: >> + instr = &read_deref(ctx)->instr; >> + break; >> case nir_instr_type_intrinsic: >> instr = &read_intrinsic(ctx)->instr; >> break; >> diff --git a/src/compiler/nir/nir_validate.c >> b/src/compiler/nir/nir_validate.c >> index d05b982..527abde 100644 >> --- a/src/compiler/nir/nir_validate.c >> +++ b/src/compiler/nir/nir_validate.c >> @@ -471,6 +471,85 @@ validate_deref_var(void *parent_mem_ctx, nir_deref_var >> *deref, validate_state *s >> } >> >> static void >> +validate_deref_instr(nir_deref_instr *instr, validate_state *state) >> +{ >> + if (instr->deref_type == nir_deref_type_var) { >> + /* Variable dereferences are stupid simple. */ >> + validate_assert(state, instr->mode == instr->var->data.mode); >> + validate_assert(state, instr->type == instr->var->type); >> + validate_var_use(instr->var, state); >> + } else if (instr->deref_type == nir_deref_type_cast) { >> + /* For cast, we simply have to trust the instruction. It's up to >> + * lowering passes and front/back-ends to make them sane. >> + */ >> + validate_src(&instr->parent, state, 0, 0); >> + >> + /* We just validate that the type and mode are there */ >> + validate_assert(state, instr->mode); >> + validate_assert(state, instr->type); >> + } else { >> + /* We require the parent to be SSA. This may be lifted in the future >> */ >> + validate_assert(state, instr->parent.is_ssa); >> + >> + /* The parent pointer value must have the same number of components >> + * as the destination. >> + */ >> + validate_src(&instr->parent, state, nir_dest_bit_size(instr->dest), >> + nir_dest_num_components(instr->dest)); >> + >> + nir_instr *parent_instr = instr->parent.ssa->parent_instr; >> + >> + /* The parent must come from another deref instruction */ >> + validate_assert(state, parent_instr->type == nir_instr_type_deref); >> + >> + nir_deref_instr *parent = nir_instr_as_deref(parent_instr); >> + >> + validate_assert(state, instr->mode == parent->mode); >> + >> + switch (instr->deref_type) { >> + case nir_deref_type_struct: >> + validate_assert(state, glsl_type_is_struct(parent->type)); >> + validate_assert(state, >> + instr->strct.index < glsl_get_length(parent->type)); >> + validate_assert(state, instr->type == >> + glsl_get_struct_field(parent->type, instr->strct.index)); >> + break; >> + >> + case nir_deref_type_array: >> + case nir_deref_type_array_wildcard: >> + if (instr->mode == nir_var_shared) { >> + /* Shared variables have a bit more relaxed rules because we >> need >> + * to be able to handle array derefs on vectors. Fortunately, >> + * nir_lower_io handles these just fine. >> + */ >> + validate_assert(state, glsl_type_is_array(parent->type) || >> + glsl_type_is_matrix(parent->type) || >> + glsl_type_is_vector(parent->type)); >> + } else { >> + /* Most of NIR cannot handle array derefs on vectors */ >> + validate_assert(state, glsl_type_is_array(parent->type) || >> + glsl_type_is_matrix(parent->type)); >> + } >> + validate_assert(state, >> + instr->type == glsl_get_array_element(parent->type)); >> + >> + if (instr->deref_type == nir_deref_type_array) >> + validate_src(&instr->arr.index, state, 32, 1); >> + break; >> + >> + default: >> + unreachable("Invalid deref instruction type"); >> + } >> + } >> + >> + /* We intentionally don't validate the size of the destination because we >> + * want to let other compiler components such as SPIR-V decide how big >> + * pointers should be. >> + */ >> + validate_dest(&instr->dest, state, 0, 0); >> +} >> + >> +static void >> validate_intrinsic_instr(nir_intrinsic_instr *instr, validate_state *state) >> { >> unsigned dest_bit_size = 0; >> @@ -624,6 +703,10 @@ validate_instr(nir_instr *instr, validate_state *state) >> validate_alu_instr(nir_instr_as_alu(instr), state); >> break; >> >> + case nir_instr_type_deref: >> + validate_deref_instr(nir_instr_as_deref(instr), state); >> + break; >> + >> case nir_instr_type_call: >> validate_call_instr(nir_instr_as_call(instr), state); >> break; >> -- >> 2.5.0.400.gff86faf >> >> _______________________________________________ >> mesa-dev mailing list >> mesa-dev@lists.freedesktop.org >> https://lists.freedesktop.org/mailman/listinfo/mesa-dev > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev