aboutsummaryrefslogtreecommitdiffstats
path: root/src/mesa
diff options
context:
space:
mode:
authorPaul Berry <[email protected]>2013-11-27 17:57:19 -0800
committerPaul Berry <[email protected]>2013-12-09 10:54:26 -0800
commit2c17f97fe6a40e4a963fb4eec0ea0555f562b1be (patch)
tree2211956818d4250465da8176f800654016802188 /src/mesa
parent97d8b770549584a2cd6b14956f15beeef0d83cad (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')
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_visitor.cpp33
-rw-r--r--src/mesa/drivers/dri/i965/brw_shader.cpp2
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp34
-rw-r--r--src/mesa/program/ir_to_mesa.cpp42
-rw-r--r--src/mesa/state_tracker/st_glsl_to_tgsi.cpp46
5 files changed, 14 insertions, 143 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
index a28dc6cdffe..3e32f6e0eba 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
@@ -2181,39 +2181,16 @@ fs_visitor::visit(ir_if *ir)
void
fs_visitor::visit(ir_loop *ir)
{
- fs_reg counter = reg_undef;
+ /* Any bounded loops should have been lowered by lower_bounded_loops(). */
+ assert(ir->counter == NULL);
if (brw->gen < 6 && dispatch_width == 16) {
fail("Can't support (non-uniform) control flow on 16-wide\n");
}
- if (ir->counter) {
- this->base_ir = ir->counter;
- ir->counter->accept(this);
- counter = *(variable_storage(ir->counter));
-
- if (ir->from) {
- this->base_ir = ir->from;
- ir->from->accept(this);
-
- emit(MOV(counter, this->result));
- }
- }
-
this->base_ir = NULL;
emit(BRW_OPCODE_DO);
- if (ir->to) {
- this->base_ir = ir->to;
- ir->to->accept(this);
-
- emit(CMP(reg_null_d, counter, this->result,
- brw_conditional_for_comparison(ir->cmp)));
-
- fs_inst *inst = emit(BRW_OPCODE_BREAK);
- inst->predicate = BRW_PREDICATE_NORMAL;
- }
-
foreach_list(node, &ir->body_instructions) {
ir_instruction *ir = (ir_instruction *)node;
@@ -2221,12 +2198,6 @@ fs_visitor::visit(ir_loop *ir)
ir->accept(this);
}
- if (ir->increment) {
- this->base_ir = ir->increment;
- ir->increment->accept(this);
- emit(ADD(counter, counter, this->result));
- }
-
this->base_ir = NULL;
emit(BRW_OPCODE_WHILE);
}
diff --git a/src/mesa/drivers/dri/i965/brw_shader.cpp b/src/mesa/drivers/dri/i965/brw_shader.cpp
index 88aa169fc1f..12035c26793 100644
--- a/src/mesa/drivers/dri/i965/brw_shader.cpp
+++ b/src/mesa/drivers/dri/i965/brw_shader.cpp
@@ -213,6 +213,8 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *shProg)
|| progress;
} while (progress);
+ lower_bounded_loops(shader->ir);
+
/* Make a pass over the IR to add state references for any built-in
* uniforms that are used. This has to be done now (during linking).
* Code generation doesn't happen until the first time this shader is
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
index b599c29d475..cf62e7ed0b0 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
@@ -1007,48 +1007,18 @@ vec4_visitor::visit(ir_variable *ir)
void
vec4_visitor::visit(ir_loop *ir)
{
- dst_reg counter;
+ /* Any bounded loops should have been lowered by lower_bounded_loops(). */
+ assert(ir->counter == NULL);
/* We don't want debugging output to print the whole body of the
* loop as the annotation.
*/
this->base_ir = NULL;
- if (ir->counter != NULL) {
- this->base_ir = ir->counter;
- ir->counter->accept(this);
- counter = *(variable_storage(ir->counter));
-
- if (ir->from != NULL) {
- this->base_ir = ir->from;
- ir->from->accept(this);
-
- emit(MOV(counter, this->result));
- }
- }
-
emit(BRW_OPCODE_DO);
- if (ir->to) {
- this->base_ir = ir->to;
- ir->to->accept(this);
-
- emit(CMP(dst_null_d(), src_reg(counter), this->result,
- brw_conditional_for_comparison(ir->cmp)));
-
- vec4_instruction *inst = emit(BRW_OPCODE_BREAK);
- inst->predicate = BRW_PREDICATE_NORMAL;
- }
-
visit_instructions(&ir->body_instructions);
-
- if (ir->increment) {
- this->base_ir = ir->increment;
- ir->increment->accept(this);
- emit(ADD(counter, src_reg(counter), this->result));
- }
-
emit(BRW_OPCODE_WHILE);
}
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);
}
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index ac95968d6f5..f748ed85092 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -1137,53 +1137,13 @@ glsl_to_tgsi_visitor::visit(ir_variable *ir)
void
glsl_to_tgsi_visitor::visit(ir_loop *ir)
{
- ir_dereference_variable *counter = NULL;
-
- if (ir->counter != NULL)
- counter = new(ir) ir_dereference_variable(ir->counter);
-
- if (ir->from != NULL) {
- assert(ir->counter != NULL);
-
- ir_assignment *a = new(ir) ir_assignment(counter, ir->from, NULL);
-
- a->accept(this);
- delete a;
- }
+ /* Any bounded loops should have been lowered by lower_bounded_loops(). */
+ assert(ir->counter == NULL);
emit(NULL, TGSI_OPCODE_BGNLOOP);
- if (ir->to) {
- ir_expression *e =
- new(ir) ir_expression(ir->cmp, glsl_type::bool_type,
- counter, ir->to);
- ir_if *if_stmt = new(ir) ir_if(e);
-
- ir_loop_jump *brk = new(ir) ir_loop_jump(ir_loop_jump::jump_break);
-
- if_stmt->then_instructions.push_tail(brk);
-
- if_stmt->accept(this);
-
- delete if_stmt;
- delete e;
- delete brk;
- }
-
visit_exec_list(&ir->body_instructions, this);
- if (ir->increment) {
- ir_expression *e =
- new(ir) ir_expression(ir_binop_add, counter->type,
- counter, ir->increment);
-
- ir_assignment *a = new(ir) ir_assignment(counter, e, NULL);
-
- a->accept(this);
- delete a;
- delete e;
- }
-
emit(NULL, TGSI_OPCODE_ENDLOOP);
}
@@ -5345,6 +5305,8 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
} while (progress);
+ lower_bounded_loops(ir);
+
validate_ir_tree(ir);
}