summaryrefslogtreecommitdiffstats
path: root/src/compiler/nir
diff options
context:
space:
mode:
authorDaniel Schürmann <[email protected]>2019-08-14 18:52:50 +0200
committerDaniel Schürmann <[email protected]>2019-08-20 17:39:52 +0200
commit204846ad062fe4e154406fa2d9093cdab4461ea2 (patch)
tree95dde9abaa04420aeea83d02d61366c317262523 /src/compiler/nir
parent7c56a68c8bd45208ef7c7e6e61bfeb6147ded4b6 (diff)
nir/lcssa: handle deref instructions properly
Reviewed-by: Jason Ekstrand <[email protected]> Fixes: 414148cdc124 "nir: Support deref instructions in loop_analyze"
Diffstat (limited to 'src/compiler/nir')
-rw-r--r--src/compiler/nir/nir_deref.c12
-rw-r--r--src/compiler/nir/nir_to_lcssa.c28
2 files changed, 26 insertions, 14 deletions
diff --git a/src/compiler/nir/nir_deref.c b/src/compiler/nir/nir_deref.c
index da66c5f0487..f7a07c6b465 100644
--- a/src/compiler/nir/nir_deref.c
+++ b/src/compiler/nir/nir_deref.c
@@ -216,17 +216,15 @@ nir_deref_instr_has_complex_use(nir_deref_instr *deref)
unsigned
nir_deref_instr_ptr_as_array_stride(nir_deref_instr *deref)
{
- assert(deref->deref_type == nir_deref_type_ptr_as_array);
- nir_deref_instr *parent = nir_deref_instr_parent(deref);
- switch (parent->deref_type) {
+ switch (deref->deref_type) {
case nir_deref_type_array:
- return glsl_get_explicit_stride(nir_deref_instr_parent(parent)->type);
+ return glsl_get_explicit_stride(nir_deref_instr_parent(deref)->type);
case nir_deref_type_ptr_as_array:
- return nir_deref_instr_ptr_as_array_stride(parent);
+ return nir_deref_instr_ptr_as_array_stride(nir_deref_instr_parent(deref));
case nir_deref_type_cast:
- return parent->cast.ptr_stride;
+ return deref->cast.ptr_stride;
default:
- unreachable("Invalid parent for ptr_as_array deref");
+ return 0;
}
}
diff --git a/src/compiler/nir/nir_to_lcssa.c b/src/compiler/nir/nir_to_lcssa.c
index 7948b117927..6057c66586d 100644
--- a/src/compiler/nir/nir_to_lcssa.c
+++ b/src/compiler/nir/nir_to_lcssa.c
@@ -111,9 +111,6 @@ convert_loop_exit_for_ssa(nir_ssa_def *def, void *void_state)
if (all_uses_inside_loop)
return true;
- /* We don't want derefs ending up in phi sources */
- assert(def->parent_instr->type != nir_instr_type_deref);
-
/* Initialize a phi-instruction */
nir_phi_instr *phi = nir_phi_instr_create(state->shader);
nir_ssa_dest_init(&phi->instr, &phi->dest,
@@ -131,6 +128,25 @@ convert_loop_exit_for_ssa(nir_ssa_def *def, void *void_state)
}
nir_instr_insert_before_block(block_after_loop, &phi->instr);
+ nir_ssa_def *dest = &phi->dest.ssa;
+
+ /* deref instructions need a cast after the phi */
+ if (def->parent_instr->type == nir_instr_type_deref) {
+ nir_deref_instr *cast =
+ nir_deref_instr_create(state->shader, nir_deref_type_cast);
+
+ nir_deref_instr *instr = nir_instr_as_deref(def->parent_instr);
+ cast->mode = instr->mode;
+ cast->type = instr->type;
+ cast->parent = nir_src_for_ssa(&phi->dest.ssa);
+ cast->cast.ptr_stride = nir_deref_instr_ptr_as_array_stride(instr);
+
+ nir_ssa_dest_init(&cast->instr, &cast->dest,
+ phi->dest.ssa.num_components,
+ phi->dest.ssa.bit_size, NULL);
+ nir_instr_insert(nir_after_phis(block_after_loop), &cast->instr);
+ dest = &cast->dest.ssa;
+ }
/* Run through all uses and rewrite those outside the loop to point to
* the phi instead of pointing to the ssa-def.
@@ -142,15 +158,13 @@ convert_loop_exit_for_ssa(nir_ssa_def *def, void *void_state)
}
if (!is_use_inside_loop(use, state->loop)) {
- nir_instr_rewrite_src(use->parent_instr, use,
- nir_src_for_ssa(&phi->dest.ssa));
+ nir_instr_rewrite_src(use->parent_instr, use, nir_src_for_ssa(dest));
}
}
nir_foreach_if_use_safe(use, def) {
if (!is_if_use_inside_loop(use, state->loop)) {
- nir_if_rewrite_condition(use->parent_if,
- nir_src_for_ssa(&phi->dest.ssa));
+ nir_if_rewrite_condition(use->parent_if, nir_src_for_ssa(dest));
}
}