diff --git a/src/compiler/nir/nir_lower_shader_calls.c b/src/compiler/nir/nir_lower_shader_calls.c index 4a2f36b2c89..155ba35e932 100644 --- a/src/compiler/nir/nir_lower_shader_calls.c +++ b/src/compiler/nir/nir_lower_shader_calls.c @@ -729,6 +729,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 @@ -948,7 +963,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 */