diff --git a/src/panfrost/bifrost/bifrost_compile.c b/src/panfrost/bifrost/bifrost_compile.c index 3712cae7099..04a9735eec4 100644 --- a/src/panfrost/bifrost/bifrost_compile.c +++ b/src/panfrost/bifrost/bifrost_compile.c @@ -3932,6 +3932,55 @@ bi_emit_tex(bi_builder *b, nir_tex_instr *instr) bi_emit_texc(b, instr); } +static void +bi_emit_phi(bi_builder *b, nir_phi_instr *instr) +{ + unsigned nr_srcs = exec_list_length(&instr->srcs); + bi_instr *I = bi_phi_to(b, bi_dest_index(&instr->dest), nr_srcs); + + /* Deferred */ + I->phi = instr; +} + +/* Look up the AGX block corresponding to a given NIR block. Used when + * translating phi nodes after emitting all blocks. + */ +static bi_block * +bi_from_nir_block(bi_context *ctx, nir_block *block) +{ + return ctx->indexed_nir_blocks[block->index]; +} + +static void +bi_emit_phi_deferred(bi_context *ctx, bi_block *block, bi_instr *I) +{ + nir_phi_instr *phi = I->phi; + + /* Guaranteed by lower_phis_to_scalar */ + assert(phi->dest.ssa.num_components == 1); + + nir_foreach_phi_src(src, phi) { + bi_block *pred = bi_from_nir_block(ctx, src->pred); + unsigned i = bi_predecessor_index(block, pred); + assert(i < I->nr_srcs); + + I->src[i] = bi_src_index(&src->src); + } + + I->phi = NULL; +} + +static void +bi_emit_phis_deferred(bi_context *ctx) +{ + bi_foreach_block(ctx, block) { + bi_foreach_instr_in_block(block, I) { + if (I->op == BI_OPCODE_PHI) + bi_emit_phi_deferred(ctx, block, I); + } + } +} + static void bi_emit_instr(bi_builder *b, struct nir_instr *instr) { @@ -3956,6 +4005,10 @@ bi_emit_instr(bi_builder *b, struct nir_instr *instr) bi_emit_jump(b, nir_instr_as_jump(instr)); break; + case nir_instr_type_phi: + bi_emit_phi(b, nir_instr_as_phi(instr)); + break; + default: unreachable("should've been lowered"); } @@ -3986,6 +4039,8 @@ emit_block(bi_context *ctx, nir_block *block) bi_builder _b = bi_init_builder(ctx, bi_after_block(ctx->current_block)); + ctx->indexed_nir_blocks[block->index] = ctx->current_block; + nir_foreach_instr(instr, block) { bi_emit_instr(&_b, instr); } @@ -4989,10 +5044,16 @@ bi_compile_variant_nir(nir_shader *nir, if (!func->impl) continue; + nir_index_blocks(func->impl); + + ctx->indexed_nir_blocks = + rzalloc_array(ctx, bi_block *, func->impl->num_blocks); + ctx->ssa_alloc += func->impl->ssa_alloc; ctx->reg_alloc += func->impl->reg_alloc; emit_cf_list(ctx, &func->impl->body); + bi_emit_phis_deferred(ctx); break; /* TODO: Multi-function shaders */ } diff --git a/src/panfrost/bifrost/compiler.h b/src/panfrost/bifrost/compiler.h index 2d70b2f91dc..9ca858ec135 100644 --- a/src/panfrost/bifrost/compiler.h +++ b/src/panfrost/bifrost/compiler.h @@ -378,8 +378,15 @@ typedef struct { uint8_t nr_srcs; uint8_t nr_dests; - /* For a branch */ - struct bi_block *branch_target; + union { + /* For a branch */ + struct bi_block *branch_target; + + /* For a phi node that hasn't been translated yet. This is only + * used during NIR->BIR + */ + nir_phi_instr *phi; + }; /* These don't fit neatly with anything else.. */ enum bi_register_format register_format; @@ -810,6 +817,7 @@ typedef struct { bi_block *after_block; bi_block *break_block; bi_block *continue_block; + bi_block **indexed_nir_blocks; bool emitted_atest; /* During NIR->BIR, the coverage bitmap. If this is NULL, the default