summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/compiler/spirv/vtn_cfg.c2
-rw-r--r--src/compiler/spirv/vtn_private.h13
-rw-r--r--src/compiler/spirv/vtn_variables.c90
3 files changed, 34 insertions, 71 deletions
diff --git a/src/compiler/spirv/vtn_cfg.c b/src/compiler/spirv/vtn_cfg.c
index 6406f4911df..47273b2d27a 100644
--- a/src/compiler/spirv/vtn_cfg.c
+++ b/src/compiler/spirv/vtn_cfg.c
@@ -1053,6 +1053,8 @@ vtn_function_emit(struct vtn_builder *b, struct vtn_function *func,
vtn_foreach_instruction(b, func->start_block->label, func->end,
vtn_handle_phi_second_pass);
+ nir_rematerialize_derefs_in_use_blocks_impl(func->impl);
+
/* Continue blocks for loops get inserted before the body of the loop
* but instructions in the continue may use SSA defs in the loop body.
* Therefore, we need to repair SSA to insert the needed phi nodes.
diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h
index da7a04ce59f..defcbb8e69d 100644
--- a/src/compiler/spirv/vtn_private.h
+++ b/src/compiler/spirv/vtn_private.h
@@ -443,20 +443,9 @@ struct vtn_pointer {
*/
struct vtn_variable *var;
- /** The deref at the base of the chain
- *
- * This field may be NULL if the pointer uses a (block_index, offset) pair
- * instead of an access chain or if the access chain starts at a variable.
- */
+ /** The NIR deref corresponding to this pointer */
nir_deref_instr *deref;
- /** An access chain describing how to get from var to the referenced data
- *
- * This field may be NULL if the pointer references the entire variable or
- * if a (block_index, offset) pair is used instead of an access chain.
- */
- struct vtn_access_chain *chain;
-
/** A (block_index, offset) pair representing a UBO or SSBO position. */
struct nir_ssa_def *block_index;
struct nir_ssa_def *offset;
diff --git a/src/compiler/spirv/vtn_variables.c b/src/compiler/spirv/vtn_variables.c
index 23fcd8b54d2..d50e445778e 100644
--- a/src/compiler/spirv/vtn_variables.c
+++ b/src/compiler/spirv/vtn_variables.c
@@ -43,21 +43,6 @@ vtn_access_chain_create(struct vtn_builder *b, unsigned length)
return chain;
}
-static struct vtn_access_chain *
-vtn_access_chain_extend(struct vtn_builder *b, struct vtn_access_chain *old,
- unsigned new_ids)
-{
- struct vtn_access_chain *chain;
-
- unsigned old_len = old ? old->length : 0;
- chain = vtn_access_chain_create(b, old_len + new_ids);
-
- for (unsigned i = 0; i < old_len; i++)
- chain->link[i] = old->link[i];
-
- return chain;
-}
-
static bool
vtn_pointer_uses_ssa_offset(struct vtn_builder *b,
struct vtn_pointer *ptr)
@@ -82,29 +67,42 @@ vtn_pointer_is_external_block(struct vtn_builder *b,
/* Dereference the given base pointer by the access chain */
static struct vtn_pointer *
-vtn_access_chain_pointer_dereference(struct vtn_builder *b,
- struct vtn_pointer *base,
- struct vtn_access_chain *deref_chain)
+vtn_nir_deref_pointer_dereference(struct vtn_builder *b,
+ struct vtn_pointer *base,
+ struct vtn_access_chain *deref_chain)
{
- struct vtn_access_chain *chain =
- vtn_access_chain_extend(b, base->chain, deref_chain->length);
struct vtn_type *type = base->type;
enum gl_access_qualifier access = base->access;
+ nir_deref_instr *tail;
+ if (base->deref) {
+ tail = base->deref;
+ } else {
+ assert(base->var && base->var->var);
+ tail = nir_build_deref_var(&b->nb, base->var->var);
+ }
+
/* OpPtrAccessChain is only allowed on things which support variable
* pointers. For everything else, the client is expected to just pass us
* the right access chain.
*/
vtn_assert(!deref_chain->ptr_as_array);
- unsigned start = base->chain ? base->chain->length : 0;
for (unsigned i = 0; i < deref_chain->length; i++) {
- chain->link[start + i] = deref_chain->link[i];
-
if (glsl_type_is_struct(type->type)) {
vtn_assert(deref_chain->link[i].mode == vtn_access_mode_literal);
- type = type->members[deref_chain->link[i].id];
+ unsigned idx = deref_chain->link[i].id;
+ tail = nir_build_deref_struct(&b->nb, tail, idx);
+ type = type->members[idx];
} else {
+ nir_ssa_def *index;
+ if (deref_chain->link[i].mode == vtn_access_mode_literal) {
+ index = nir_imm_int(&b->nb, deref_chain->link[i].id);
+ } else {
+ vtn_assert(deref_chain->link[i].mode == vtn_access_mode_id);
+ index = vtn_ssa_value(b, deref_chain->link[i].id)->def;
+ }
+ tail = nir_build_deref_array(&b->nb, tail, index);
type = type->array_element;
}
@@ -115,8 +113,7 @@ vtn_access_chain_pointer_dereference(struct vtn_builder *b,
ptr->mode = base->mode;
ptr->type = type;
ptr->var = base->var;
- ptr->deref = base->deref;
- ptr->chain = chain;
+ ptr->deref = tail;
ptr->access = access;
return ptr;
@@ -362,7 +359,7 @@ vtn_pointer_dereference(struct vtn_builder *b,
if (vtn_pointer_uses_ssa_offset(b, base)) {
return vtn_ssa_offset_pointer_dereference(b, base, deref_chain);
} else {
- return vtn_access_chain_pointer_dereference(b, base, deref_chain);
+ return vtn_nir_deref_pointer_dereference(b, base, deref_chain);
}
}
@@ -412,39 +409,15 @@ vtn_pointer_to_deref(struct vtn_builder *b, struct vtn_pointer *ptr)
if (ptr->var && ptr->var->copy_prop_sampler)
return vtn_pointer_to_deref(b, ptr->var->copy_prop_sampler);
- nir_deref_instr *tail;
- if (ptr->deref) {
- tail = ptr->deref;
- } else {
- assert(ptr->var && ptr->var->var);
- tail = nir_build_deref_var(&b->nb, ptr->var->var);
- }
-
- /* Raw variable access */
- if (!ptr->chain)
- return tail;
-
- struct vtn_access_chain *chain = ptr->chain;
- vtn_assert(chain);
-
- for (unsigned i = 0; i < chain->length; i++) {
- if (glsl_type_is_struct(tail->type)) {
- vtn_assert(chain->link[i].mode == vtn_access_mode_literal);
- unsigned idx = chain->link[i].id;
- tail = nir_build_deref_struct(&b->nb, tail, idx);
- } else {
- nir_ssa_def *index;
- if (chain->link[i].mode == vtn_access_mode_literal) {
- index = nir_imm_int(&b->nb, chain->link[i].id);
- } else {
- vtn_assert(chain->link[i].mode == vtn_access_mode_id);
- index = vtn_ssa_value(b, chain->link[i].id)->def;
- }
- tail = nir_build_deref_array(&b->nb, tail, index);
- }
+ vtn_assert(!vtn_pointer_uses_ssa_offset(b, ptr));
+ if (!ptr->deref) {
+ struct vtn_access_chain chain = {
+ .length = 0,
+ };
+ ptr = vtn_nir_deref_pointer_dereference(b, ptr, &chain);
}
- return tail;
+ return ptr->deref;
}
static void
@@ -1447,7 +1420,6 @@ var_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
if (val->value_type == vtn_value_type_pointer) {
assert(val->pointer->var == void_var);
- assert(val->pointer->chain == NULL);
assert(member == -1);
} else {
assert(val->value_type == vtn_value_type_type);