diff --git a/src/amd/compiler/aco_instruction_selection.cpp b/src/amd/compiler/aco_instruction_selection.cpp index cac1ccafb39..cd5fda96ff0 100644 --- a/src/amd/compiler/aco_instruction_selection.cpp +++ b/src/amd/compiler/aco_instruction_selection.cpp @@ -10317,8 +10317,6 @@ rename_temp(const std::map& renames, Temp tmp) static void lcssa_workaround(isel_context* ctx, nir_loop* loop) { - assert(ctx->block->linear_preds.size() == ctx->block->logical_preds.size() + 1); - nir_block* block_before_loop = nir_cf_node_as_block(nir_cf_node_prev(&loop->cf_node)); nir_block* block_after_loop = nir_cf_node_as_block(nir_cf_node_next(&loop->cf_node)); @@ -10334,11 +10332,10 @@ lcssa_workaround(isel_context* ctx, nir_loop* loop) continue; Temp new_tmp = ctx->program->allocateTmp(tmp.regClass()); - aco_ptr phi(create_instruction(aco_opcode::p_linear_phi, Format::PSEUDO, - ctx->block->linear_preds.size(), 1)); + aco_ptr phi(create_instruction(aco_opcode::p_phi, Format::PSEUDO, + ctx->block->logical_preds.size(), 1)); for (unsigned i = 0; i < ctx->block->logical_preds.size(); i++) phi->operands[i] = Operand(new_tmp); - phi->operands.back() = Operand(tmp.regClass()); phi->definitions[0] = Definition(tmp); ctx->block->instructions.emplace(ctx->block->instructions.begin(), std::move(phi)); diff --git a/src/amd/compiler/tests/test_isel.cpp b/src/amd/compiler/tests/test_isel.cpp index 5e454eb9617..2674b4f322a 100644 --- a/src/amd/compiler/tests/test_isel.cpp +++ b/src/amd/compiler/tests/test_isel.cpp @@ -878,6 +878,128 @@ BEGIN_TEST(isel.cf.hidden_break) finish_isel_test(); END_TEST +/** + * loop { + * if (divergent) { + * a = loop_invariant_sgpr + * break + * } + * discard_if + * } + * use(a) + */ +BEGIN_TEST(isel.cf.hidden_break_no_lcssa) + if (!setup_nir_cs(GFX11)) + return; + + nir_def* val; + nir_push_loop(nb); + { + //>> BB1 + //! /* logical preds: BB0, BB9, / linear preds: BB0, BB11, / kind: loop-header, branch, */ + //! s1: %val_header_phi = p_linear_phi s1: undef, %val_invert_phi + + nir_push_if(nb, nir_unit_test_divergent_amd(nb, 1, 1, .base = 1)); + { + //>> BB2 + //! /* logical preds: BB1, / linear preds: BB1, / kind: break, */ + //! p_logical_start + //! s1: %val = p_parallelcopy 0 + val = nir_imm_zero(nb, 1, 32); + nir_jump(nb, nir_jump_break); + } + nir_pop_if(nb, NULL); + + //>> BB6 + //! /* logical preds: / linear preds: BB4, BB5, / kind: invert, */ + //! s1: %val_invert_phi = p_linear_phi %val, %val_header_phi + //>> BB9 + //! /* logical preds: BB7, / linear preds: BB7, BB8, / kind: uniform, continue_or_break, merge, discard, */ + nir_discard_if(nb, nir_unit_test_divergent_amd(nb, 1, 1, .base = 2)); + } + nir_pop_loop(nb, NULL); + + //>> BB12 + //! /* logical preds: BB2, / linear preds: BB3, BB10, / kind: uniform, top-level, loop-exit, */ + //! s1: %val_exit_phi = p_linear_phi %val, %val_invert_phi + //! p_logical_start + //! p_unit_test 0, %val_exit_phi + nir_unit_test_amd(nb, val, .base = 0); + + finish_isel_test(); +END_TEST + +/** + * loop { + * use(phi(, a)) + * discard_if + * loop { + * if (uniform) { + * a = loop_invariant_sgpr + * break + * } + * } + * } + */ +BEGIN_TEST(isel.cf.hidden_break_no_lcssa_header_phi) + if (!setup_nir_cs(GFX11)) + return; + + //>> p_startpgm + //! p_logical_start + //! s1: %init = p_unit_test 0 + nir_def* init = nir_unit_test_uniform_amd(nb, 1, 32, .base = 0); + + nir_def* val; + nir_phi_instr* phi; + nir_loop *loop = nir_push_loop(nb); + { + //>> BB1 + //! /* logical preds: BB0, BB11, / linear preds: BB0, BB13, / kind: uniform, loop-preheader, loop-header, discard, */ + //! s1: %phi = p_linear_phi %init, %val_lcssa + //! p_logical_start + //! p_unit_test 1, %phi + phi = nir_phi_instr_create(nb->shader); + nir_def_init(&phi->instr, &phi->def, 1, 32); + nir_phi_instr_add_src(phi, init->parent_instr->block, init); + nir_unit_test_amd(nb, &phi->def, .base = 1); + + nir_discard_if(nb, nir_unit_test_divergent_amd(nb, 1, 1, .base = 2)); + + //>> BB2 + //! /* logical preds: BB1, BB5, / linear preds: BB1, BB7, / kind: uniform, loop-header, */ + nir_push_loop(nb); + { + nir_push_if(nb, nir_unit_test_uniform_amd(nb, 1, 1, .base = 3)); + { + //>> BB3 + //! /* logical preds: BB2, / linear preds: BB2, / kind: uniform, break, */ + //! p_logical_start + //! s1: %val = p_parallelcopy 0 + val = nir_imm_zero(nb, 1, 32); + nir_jump(nb, nir_jump_break); + } + nir_pop_if(nb, NULL); + //>> BB5 + //! /* logical preds: BB4, / linear preds: BB4, / kind: uniform, continue_or_break, */ + } + nir_pop_loop(nb, NULL); + //>> BB8 + //! /* logical preds: BB3, / linear preds: BB3, BB6, / kind: uniform, loop-exit, */ + //! s1: %val_lcssa = p_linear_phi %val, s1: undef + //>> BB11 + //! /* logical preds: BB10, / linear preds: BB10, / kind: uniform, continue_or_break, */ + + nir_phi_instr_add_src(phi, nir_cursor_current_block(nb->cursor), val); + } + nir_pop_loop(nb, NULL); + + nb->cursor = nir_after_phis(nir_loop_first_block(loop)); + nir_builder_instr_insert(nb, &phi->instr); + + finish_isel_test(); +END_TEST + /** * if (divergent) { * a =