diff --git a/.pick_status.json b/.pick_status.json index 83364c1b8d4..3bb060a6033 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -1876,7 +1876,7 @@ "description": "nir/lower_shader_calls: don't insert code after break/continue", "nominated": true, "nomination_type": 1, - "resolution": 0, + "resolution": 1, "because_sha": "8dfb240b1f063307aa5e53fb1bd0865105eef986" }, { diff --git a/src/compiler/nir/nir_lower_shader_calls.c b/src/compiler/nir/nir_lower_shader_calls.c index c06bae2eca8..0b3cf616763 100644 --- a/src/compiler/nir/nir_lower_shader_calls.c +++ b/src/compiler/nir/nir_lower_shader_calls.c @@ -728,6 +728,21 @@ rewrite_phis_to_pred(nir_block *block, nir_block *pred) } } +static bool +cursor_is_after_jump(nir_cursor cursor) +{ + switch (cursor.option) { + case nir_cursor_before_instr: + case nir_cursor_before_block: + return false; + case nir_cursor_after_instr: + return cursor.instr->type == nir_instr_type_jump; + case nir_cursor_after_block: + return nir_block_ends_in_jump(cursor.block);; + } + unreachable("Invalid cursor option"); +} + /** Flattens if ladders leading up to a resume * * Given a resume_instr, this function flattens any if ladders leading to the @@ -947,7 +962,18 @@ found_resume: nir_cf_extract(&cf_list, nir_after_instr(resume_instr), nir_after_cf_list(child_list)); } - b->cursor = nir_cf_reinsert(&cf_list, b->cursor); + + if (cursor_is_after_jump(b->cursor)) { + /* If the resume instruction is in a loop, it's possible cf_list ends + * in a break or continue instruction, in which case we don't want to + * insert anything. It's also possible we have an early return if + * someone hasn't lowered those yet. In either case, nothing after that + * point executes in this context so we can delete it. + */ + nir_cf_delete(&cf_list); + } else { + b->cursor = nir_cf_reinsert(&cf_list, b->cursor); + } if (!resume_node) { /* We want the resume to be the first "interesting" instruction */