From b4bc59e37ec0969d70e87d233e4e82431ec2e092 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Alejandro=20Pi=C3=B1eiro?= Date: Tue, 19 Nov 2019 11:13:15 +0100 Subject: [PATCH] v3d: adds an extra MOV for any sig.ld* Specifically when we are in non-uniform control flow, as we would need to set the condition for the last instruction. If (for example) a image atomic load stores directly their value on a NIR register, last_inst would be a nop, and would fail when set the condition. Fixes piglit test: spec/glsl-es-3.10/execution/cs-ssbo-atomic-if-else-2.shader_test Fixes: 6281f26f064ada ("v3d: Add support for shader_image_load_store.") v2: (Changes suggested by Eric Anholt) * Cover all sig.ld* signals, not just ldunif and ldtmu, as all of them have the same restriction. * Update comment explaining why we add a MOV in that case * Tweak commit message. v3: * Drop extra set of parens (Eric) * Add missing ld signal to is_ld_signal to fix shader-db regression. Reviewed-by: Eric Anholt --- src/broadcom/compiler/nir_to_vir.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/broadcom/compiler/nir_to_vir.c b/src/broadcom/compiler/nir_to_vir.c index 7af5fdebd8f..6c079bda6af 100644 --- a/src/broadcom/compiler/nir_to_vir.c +++ b/src/broadcom/compiler/nir_to_vir.c @@ -409,6 +409,20 @@ ntq_init_ssa_def(struct v3d_compile *c, nir_ssa_def *def) return qregs; } +static bool +is_ld_signal(const struct v3d_qpu_sig *sig) +{ + return (sig->ldunif || + sig->ldunifa || + sig->ldunifrf || + sig->ldunifarf || + sig->ldtmu || + sig->ldvary || + sig->ldvpm || + sig->ldtlb || + sig->ldtlbu); +} + /** * This function is responsible for getting VIR results into the associated * storage for a NIR instruction. @@ -456,11 +470,12 @@ ntq_store_dest(struct v3d_compile *c, nir_dest *dest, int chan, _mesa_hash_table_search(c->def_ht, reg); struct qreg *qregs = entry->data; - /* Insert a MOV if the source wasn't an SSA def in the - * previous instruction. + /* If the previous instruction can't be predicated for + * the store into the nir_register, then emit a MOV + * that can be. */ - if ((vir_in_nonuniform_control_flow(c) && - c->defs[last_inst->dst.index]->qpu.sig.ldunif)) { + if (vir_in_nonuniform_control_flow(c) && + is_ld_signal(&c->defs[last_inst->dst.index]->qpu.sig)) { result = vir_MOV(c, result); last_inst = c->defs[result.index]; } -- 2.30.2