From d66de1bb4966de870d3349f52e0465a0ebda493e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Fri, 6 Feb 2026 13:22:05 +0100 Subject: [PATCH] glsl_to_nir: emit loop continue construct Part-of: --- src/compiler/glsl/ast.h | 2 -- src/compiler/glsl/ast_to_hir.cpp | 40 ++++---------------------- src/compiler/glsl/glsl_to_nir.cpp | 4 +++ src/compiler/glsl/ir.h | 2 ++ src/compiler/glsl/ir_basic_block.cpp | 1 + src/compiler/glsl/ir_clone.cpp | 3 ++ src/compiler/glsl/ir_hv_accept.cpp | 4 +++ src/compiler/glsl/ir_print_visitor.cpp | 6 ++++ 8 files changed, 25 insertions(+), 37 deletions(-) diff --git a/src/compiler/glsl/ast.h b/src/compiler/glsl/ast.h index 99bc01087a8..cded74361f3 100644 --- a/src/compiler/glsl/ast.h +++ b/src/compiler/glsl/ast.h @@ -1224,8 +1224,6 @@ public: ast_node *condition; ast_expression *rest_expression; - ir_exec_list rest_instructions; - ast_node *body; /** diff --git a/src/compiler/glsl/ast_to_hir.cpp b/src/compiler/glsl/ast_to_hir.cpp index 77f27a1f837..b62034af5c0 100644 --- a/src/compiler/glsl/ast_to_hir.cpp +++ b/src/compiler/glsl/ast_to_hir.cpp @@ -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(); diff --git a/src/compiler/glsl/glsl_to_nir.cpp b/src/compiler/glsl/glsl_to_nir.cpp index 55b59374d87..306fd66126d 100644 --- a/src/compiler/glsl/glsl_to_nir.cpp +++ b/src/compiler/glsl/glsl_to_nir.cpp @@ -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); } diff --git a/src/compiler/glsl/ir.h b/src/compiler/glsl/ir.h index 40360100c5c..eab911f9925 100644 --- a/src/compiler/glsl/ir.h +++ b/src/compiler/glsl/ir.h @@ -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; }; diff --git a/src/compiler/glsl/ir_basic_block.cpp b/src/compiler/glsl/ir_basic_block.cpp index a206631dfa3..3a0919e62ca 100644 --- a/src/compiler/glsl/ir_basic_block.cpp +++ b/src/compiler/glsl/ir_basic_block.cpp @@ -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; diff --git a/src/compiler/glsl/ir_clone.cpp b/src/compiler/glsl/ir_clone.cpp index d209caa2336..a50481b9553 100644 --- a/src/compiler/glsl/ir_clone.cpp +++ b/src/compiler/glsl/ir_clone.cpp @@ -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; } diff --git a/src/compiler/glsl/ir_hv_accept.cpp b/src/compiler/glsl/ir_hv_accept.cpp index 89a4c3a466e..48bcaf50cbc 100644 --- a/src/compiler/glsl/ir_hv_accept.cpp +++ b/src/compiler/glsl/ir_hv_accept.cpp @@ -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); } diff --git a/src/compiler/glsl/ir_print_visitor.cpp b/src/compiler/glsl/ir_print_visitor.cpp index 2c6d0061957..f077905cb1f 100644 --- a/src/compiler/glsl/ir_print_visitor.cpp +++ b/src/compiler/glsl/ir_print_visitor.cpp @@ -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");