summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/compiler/spirv/vtn_cfg.c62
1 files changed, 26 insertions, 36 deletions
diff --git a/src/compiler/spirv/vtn_cfg.c b/src/compiler/spirv/vtn_cfg.c
index aef1b7e18fb..dc57e41feb0 100644
--- a/src/compiler/spirv/vtn_cfg.c
+++ b/src/compiler/spirv/vtn_cfg.c
@@ -852,6 +852,30 @@ vtn_emit_branch(struct vtn_builder *b, enum vtn_branch_type branch_type,
}
}
+static nir_ssa_def *
+vtn_switch_case_condition(struct vtn_builder *b, struct vtn_switch *swtch,
+ nir_ssa_def *sel, struct vtn_case *cse)
+{
+ if (cse->is_default) {
+ nir_ssa_def *any = nir_imm_false(&b->nb);
+ list_for_each_entry(struct vtn_case, other, &swtch->cases, link) {
+ if (other->is_default)
+ continue;
+
+ any = nir_ior(&b->nb, any,
+ vtn_switch_case_condition(b, swtch, sel, other));
+ }
+ return nir_inot(&b->nb, any);
+ } else {
+ nir_ssa_def *cond = nir_imm_false(&b->nb);
+ util_dynarray_foreach(&cse->values, uint64_t, val) {
+ nir_ssa_def *imm = nir_imm_intN_t(&b->nb, *val, sel->bit_size);
+ cond = nir_ior(&b->nb, cond, nir_ieq(&b->nb, sel, imm));
+ }
+ return cond;
+ }
+}
+
static void
vtn_emit_cf_list(struct vtn_builder *b, struct list_head *cf_list,
nir_variable *switch_fall_var, bool *has_switch_break,
@@ -978,46 +1002,13 @@ vtn_emit_cf_list(struct vtn_builder *b, struct list_head *cf_list,
nir_local_variable_create(b->nb.impl, glsl_bool_type(), "fall");
nir_store_var(&b->nb, fall_var, nir_imm_false(&b->nb), 1);
- /* Next, we gather up all of the conditions. We have to do this
- * up-front because we also need to build an "any" condition so
- * that we can use !any for default.
- */
- const int num_cases = list_length(&vtn_switch->cases);
- NIR_VLA(nir_ssa_def *, conditions, num_cases);
-
nir_ssa_def *sel = vtn_ssa_value(b, vtn_switch->selector)->def;
- /* An accumulation of all conditions. Used for the default */
- nir_ssa_def *any = NULL;
-
- int i = 0;
- list_for_each_entry(struct vtn_case, cse, &vtn_switch->cases, link) {
- if (cse->is_default) {
- conditions[i++] = NULL;
- continue;
- }
-
- nir_ssa_def *cond = NULL;
- util_dynarray_foreach(&cse->values, uint64_t, val) {
- nir_ssa_def *imm = nir_imm_intN_t(&b->nb, *val, sel->bit_size);
- nir_ssa_def *is_val = nir_ieq(&b->nb, sel, imm);
-
- cond = cond ? nir_ior(&b->nb, cond, is_val) : is_val;
- }
-
- any = any ? nir_ior(&b->nb, any, cond) : cond;
- conditions[i++] = cond;
- }
- vtn_assert(i == num_cases);
/* Now we can walk the list of cases and actually emit code */
- i = 0;
list_for_each_entry(struct vtn_case, cse, &vtn_switch->cases, link) {
/* Figure out the condition */
- nir_ssa_def *cond = conditions[i++];
- if (cse->is_default) {
- vtn_assert(cond == NULL);
- cond = nir_inot(&b->nb, any);
- }
+ nir_ssa_def *cond =
+ vtn_switch_case_condition(b, vtn_switch, sel, cse);
/* Take fallthrough into account */
cond = nir_ior(&b->nb, cond, nir_load_var(&b->nb, fall_var));
@@ -1030,7 +1021,6 @@ vtn_emit_cf_list(struct vtn_builder *b, struct list_head *cf_list,
nir_pop_if(&b->nb, case_if);
}
- vtn_assert(i == num_cases);
break;
}