diff --git a/.pick_status.json b/.pick_status.json index 6279a28c303..afe5dbf6eaf 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -84,7 +84,7 @@ "description": "aco: skip continue_or_break LCSSA phis when not needed", "nominated": true, "nomination_type": 1, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": "bbe46524307e5e834d5b3d593763b72120d6a3ee", "notes": null diff --git a/src/amd/compiler/aco_instruction_selection.cpp b/src/amd/compiler/aco_instruction_selection.cpp index 2749ac4f4da..43e5e238726 100644 --- a/src/amd/compiler/aco_instruction_selection.cpp +++ b/src/amd/compiler/aco_instruction_selection.cpp @@ -10446,6 +10446,17 @@ lcssa_workaround(isel_context* ctx, nir_loop* loop) std::map renames; nir_foreach_block_in_cf_node (block, &loop->cf_node) { + /* These values are reachable from the loop exit even when continue_or_break is used. We + * shouldn't create phis with undef operands in case the contents are important even if exec + * is zero (for example, memory access addresses). */ + if (nir_block_dominates(block, nir_loop_last_block(loop))) + continue; + + /* Definitions in this block are not reachable from the loop exit, and so all uses are inside + * the loop. */ + if (!nir_block_dominates(block, block_after_loop)) + continue; + nir_foreach_instr (instr, block) { nir_def* def = nir_instr_def(instr); if (!def) diff --git a/src/amd/compiler/aco_instruction_selection_setup.cpp b/src/amd/compiler/aco_instruction_selection_setup.cpp index ba45464d063..e06b872ed65 100644 --- a/src/amd/compiler/aco_instruction_selection_setup.cpp +++ b/src/amd/compiler/aco_instruction_selection_setup.cpp @@ -288,7 +288,7 @@ init_context(isel_context* ctx, nir_shader* shader) nir_metadata_preserve(impl, nir_metadata_none); /* we'll need these for isel */ - nir_metadata_require(impl, nir_metadata_block_index); + nir_metadata_require(impl, nir_metadata_block_index | nir_metadata_dominance); if (ctx->options->dump_preoptir) { fprintf(stderr, "NIR shader before instruction selection:\n");