glsl_to_nir: emit loop continue construct
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39777>
This commit is contained in:
Daniel Schürmann 2026-02-06 13:22:05 +01:00 committed by Marge Bot
parent 143370f1a7
commit d66de1bb49
8 changed files with 25 additions and 37 deletions

View file

@ -1224,8 +1224,6 @@ public:
ast_node *condition;
ast_expression *rest_expression;
ir_exec_list rest_instructions;
ast_node *body;
/**

View file

@ -6806,23 +6806,6 @@ ast_jump_statement::hir(ir_exec_list *instructions,
_mesa_glsl_error(& loc, state,
"break may only appear in a loop or a switch");
} else {
/* For a loop, inline the for loop expression again, since we don't
* know where near the end of the loop body the normal copy of it is
* going to be placed. Same goes for the condition for a do-while
* loop.
*/
if (state->loop_nesting_ast != NULL &&
mode == ast_continue && !state->switch_state.is_switch_innermost) {
if (state->loop_nesting_ast->rest_expression) {
clone_ir_list(linalloc, instructions,
&state->loop_nesting_ast->rest_instructions);
}
if (state->loop_nesting_ast->mode ==
ast_iteration_statement::ast_do_while) {
state->loop_nesting_ast->condition_to_hir(instructions, state);
}
}
if (state->switch_state.is_switch_innermost &&
mode == ast_continue) {
/* Set 'continue_inside' to true. */
@ -7061,16 +7044,6 @@ ast_switch_statement::hir(ir_exec_list *instructions,
ir_if *irif = new(linalloc) ir_if(deref_continue_inside);
ir_loop_jump *jump = new(linalloc) ir_loop_jump(ir_loop_jump::jump_continue);
if (state->loop_nesting_ast != NULL) {
if (state->loop_nesting_ast->rest_expression) {
clone_ir_list(linalloc, &irif->then_instructions,
&state->loop_nesting_ast->rest_instructions);
}
if (state->loop_nesting_ast->mode ==
ast_iteration_statement::ast_do_while) {
state->loop_nesting_ast->condition_to_hir(&irif->then_instructions, state);
}
}
irif->then_instructions.push_tail(jump);
instructions->push_tail(irif);
}
@ -7419,27 +7392,24 @@ ast_iteration_statement::hir(ir_exec_list *instructions,
bool saved_is_switch_innermost = state->switch_state.is_switch_innermost;
state->switch_state.is_switch_innermost = false;
if (rest_expression != NULL)
rest_expression->hir(&stmt->continue_instructions, state);
if (mode != ast_do_while)
condition_to_hir(&stmt->body_instructions, state);
if (rest_expression != NULL)
rest_expression->hir(&rest_instructions, state);
if (body != NULL) {
if (mode == ast_do_while)
state->symbols->push_scope();
body->hir(& stmt->body_instructions, state);
body->hir(&stmt->body_instructions, state);
if (mode == ast_do_while)
state->symbols->pop_scope();
}
if (rest_expression != NULL)
stmt->body_instructions.append_list(&rest_instructions);
if (mode == ast_do_while)
condition_to_hir(&stmt->body_instructions, state);
condition_to_hir(&stmt->continue_instructions, state);
if (mode != ast_do_while)
state->symbols->pop_scope();

View file

@ -189,6 +189,8 @@ glsl_to_nir(struct gl_shader *gl_shader,
ralloc_free(gl_shader->ir);
gl_shader->ir = NULL;
nir_lower_continue_constructs(shader);
nir_validate_shader(shader, "after glsl to nir, before function inline");
if (should_print_nir(shader)) {
printf("glsl_to_nir\n");
@ -789,6 +791,8 @@ nir_visitor::visit(ir_loop *ir)
{
nir_push_loop(&b);
visit_exec_list(&ir->body_instructions, this);
nir_push_continue(&b, NULL);
visit_exec_list(&ir->continue_instructions, this);
nir_pop_loop(&b, NULL);
}

View file

@ -1466,6 +1466,8 @@ public:
/** List of ir_instruction that make up the body of the loop. */
ir_exec_list body_instructions;
/** List of ir_instruction that make up the continue construct. */
ir_exec_list continue_instructions;
};

View file

@ -74,6 +74,7 @@ void call_for_basic_blocks(ir_exec_list *instructions,
callback(leader, ir, data);
leader = NULL;
call_for_basic_blocks(&ir_loop->body_instructions, callback, data);
call_for_basic_blocks(&ir_loop->continue_instructions, callback, data);
} else if (ir->as_jump() || ir->as_call()) {
callback(leader, ir, data);
leader = NULL;

View file

@ -140,6 +140,9 @@ ir_loop::clone(linear_ctx *linalloc, struct hash_table *ht) const
ir_foreach_in_list(ir_instruction, ir, &this->body_instructions) {
new_loop->body_instructions.push_tail(ir->clone(linalloc, ht));
}
ir_foreach_in_list(ir_instruction, ir, &this->continue_instructions) {
new_loop->continue_instructions.push_tail(ir->clone(linalloc, ht));
}
return new_loop;
}

View file

@ -90,6 +90,10 @@ ir_loop::accept(ir_hierarchical_visitor *v)
if (s == visit_stop)
return s;
s = visit_list_elements(v, &this->continue_instructions);
if (s == visit_stop)
return s;
return v->visit_leave(this);
}

View file

@ -652,6 +652,12 @@ ir_print_visitor::visit(ir_loop *ir)
inst->accept(this);
fprintf(f, "\n");
}
fprintf(stderr, ") continue (\n");
ir_foreach_in_list(ir_instruction, inst, &ir->continue_instructions) {
indent();
inst->accept(this);
fprintf(f, "\n");
}
indentation--;
indent();
fprintf(f, "))\n");