diff options
author | Paul Berry <[email protected]> | 2013-11-27 17:57:19 -0800 |
---|---|---|
committer | Paul Berry <[email protected]> | 2013-12-09 10:54:26 -0800 |
commit | 2c17f97fe6a40e4a963fb4eec0ea0555f562b1be (patch) | |
tree | 2211956818d4250465da8176f800654016802188 /src/mesa/program | |
parent | 97d8b770549584a2cd6b14956f15beeef0d83cad (diff) |
glsl/loops: consolidate bounded loop handling into a lowering pass.
Previously, all of the back-ends (ir_to_mesa, st_glsl_to_tgsi, and the
i965 fs and vec4 visitors) had nearly identical logic for handling
bounded loops. This replaces the duplicate logic with an equivalent
lowering pass that is used by all the back-ends.
Note: on i965, there is a slight increase in instruction count. For
example, a loop like this:
for (int i = 0; i < 100; i++) {
total += i;
}
would previously compile down to this (vec4) native code:
mov(8) g4<1>.xD 0D
mov(8) g8<1>.xD 0D
loop:
cmp.ge.f0(8) null g8<4;4,1>.xD 100D
(+f0) break(8)
add(8) g5<1>.xD g5<4;4,1>.xD g4<4;4,1>.xD
add(8) g8<1>.xD g8<4;4,1>.xD 1D
add(8) g4<1>.xD g4<4;4,1>.xD 1D
while(8) loop
After this patch, the "(+f0) break(8)" turns into:
(+f0) if(8)
break(8)
endif(8)
because the back-end isn't smart enough to recognize that "if
(condition) break;" can be done using a conditional break instruction.
However, it should be relatively easy for a future peephole
optimization to properly optimize this.
Reviewed-by: Jordan Justen <[email protected]>
Reviewed-by: Ian Romanick <[email protected]>
Diffstat (limited to 'src/mesa/program')
-rw-r--r-- | src/mesa/program/ir_to_mesa.cpp | 42 |
1 files changed, 4 insertions, 38 deletions
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index c833a12f2aa..9fd10d1d91c 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -759,49 +759,13 @@ ir_to_mesa_visitor::visit(ir_variable *ir) void ir_to_mesa_visitor::visit(ir_loop *ir) { - ir_dereference_variable *counter = NULL; - - if (ir->counter != NULL) - counter = new(mem_ctx) ir_dereference_variable(ir->counter); - - if (ir->from != NULL) { - assert(ir->counter != NULL); - - ir_assignment *a = - new(mem_ctx) ir_assignment(counter, ir->from, NULL); - - a->accept(this); - } + /* Any bounded loops should have been lowered by lower_bounded_loops(). */ + assert(ir->counter == NULL); emit(NULL, OPCODE_BGNLOOP); - if (ir->to) { - ir_expression *e = - new(mem_ctx) ir_expression(ir->cmp, glsl_type::bool_type, - counter, ir->to); - ir_if *if_stmt = new(mem_ctx) ir_if(e); - - ir_loop_jump *brk = - new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break); - - if_stmt->then_instructions.push_tail(brk); - - if_stmt->accept(this); - } - visit_exec_list(&ir->body_instructions, this); - if (ir->increment) { - ir_expression *e = - new(mem_ctx) ir_expression(ir_binop_add, counter->type, - counter, ir->increment); - - ir_assignment *a = - new(mem_ctx) ir_assignment(counter, e, NULL); - - a->accept(this); - } - emit(NULL, OPCODE_ENDLOOP); } @@ -3091,6 +3055,8 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) progress = lower_vector_insert(ir, true) || progress; } while (progress); + lower_bounded_loops(ir); + validate_ir_tree(ir); } |