From 32aaf89823de11e98cb59d5ec78c66cd3e74bcd4 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Mon, 15 Nov 2010 14:35:46 -0800 Subject: glsl: Rename various ir_* files to lower_* and opt_*. This helps distinguish between lowering passes, optimization passes, and other compiler code. --- src/glsl/lower_jumps.cpp | 544 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 544 insertions(+) create mode 100644 src/glsl/lower_jumps.cpp (limited to 'src/glsl/lower_jumps.cpp') diff --git a/src/glsl/lower_jumps.cpp b/src/glsl/lower_jumps.cpp new file mode 100644 index 0000000000..b69cc1ec31 --- /dev/null +++ b/src/glsl/lower_jumps.cpp @@ -0,0 +1,544 @@ +/* + * Copyright © 2010 Luca Barbieri + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file ir_lower_jumps.cpp + */ + +#include "glsl_types.h" +#include +#include "ir.h" + +enum jump_strength +{ + strength_none, + strength_always_clears_execute_flag, + strength_continue, + strength_break, + strength_return, + strength_discard +}; + +struct block_record +{ + /* minimum jump strength (of lowered IR, not pre-lowering IR) + * + * If the block ends with a jump, must be the strength of the jump. + * Otherwise, the jump would be dead and have been deleted before) + * + * If the block doesn't end with a jump, it can be different than strength_none if all paths before it lead to some jump + * (e.g. an if with a return in one branch, and a break in the other, while not lowering them) + * Note that identical jumps are usually unified though. + */ + jump_strength min_strength; + + /* can anything clear the execute flag? */ + bool may_clear_execute_flag; + + block_record() + { + this->min_strength = strength_none; + this->may_clear_execute_flag = false; + } +}; + +struct loop_record +{ + ir_function_signature* signature; + ir_loop* loop; + + /* used to avoid lowering the break used to represent lowered breaks */ + unsigned nesting_depth; + bool in_if_at_the_end_of_the_loop; + + bool may_set_return_flag; + + ir_variable* break_flag; + ir_variable* execute_flag; /* cleared to emulate continue */ + + loop_record(ir_function_signature* p_signature = 0, ir_loop* p_loop = 0) + { + this->signature = p_signature; + this->loop = p_loop; + this->nesting_depth = 0; + this->in_if_at_the_end_of_the_loop = false; + this->may_set_return_flag = false; + this->break_flag = 0; + this->execute_flag = 0; + } + + ir_variable* get_execute_flag() + { + /* also supported for the "function loop" */ + if(!this->execute_flag) { + exec_list& list = this->loop ? this->loop->body_instructions : signature->body; + this->execute_flag = new(this->signature) ir_variable(glsl_type::bool_type, "execute_flag", ir_var_temporary); + list.push_head(new(this->signature) ir_assignment(new(this->signature) ir_dereference_variable(execute_flag), new(this->signature) ir_constant(true), 0)); + list.push_head(this->execute_flag); + } + return this->execute_flag; + } + + ir_variable* get_break_flag() + { + assert(this->loop); + if(!this->break_flag) { + this->break_flag = new(this->signature) ir_variable(glsl_type::bool_type, "break_flag", ir_var_temporary); + this->loop->insert_before(this->break_flag); + this->loop->insert_before(new(this->signature) ir_assignment(new(this->signature) ir_dereference_variable(break_flag), new(this->signature) ir_constant(false), 0)); + } + return this->break_flag; + } +}; + +struct function_record +{ + ir_function_signature* signature; + ir_variable* return_flag; /* used to break out of all loops and then jump to the return instruction */ + ir_variable* return_value; + bool is_main; + unsigned nesting_depth; + + function_record(ir_function_signature* p_signature = 0) + { + this->signature = p_signature; + this->return_flag = 0; + this->return_value = 0; + this->nesting_depth = 0; + this->is_main = this->signature && (strcmp(this->signature->function_name(), "main") == 0); + } + + ir_variable* get_return_flag() + { + if(!this->return_flag) { + this->return_flag = new(this->signature) ir_variable(glsl_type::bool_type, "return_flag", ir_var_temporary); + this->signature->body.push_head(new(this->signature) ir_assignment(new(this->signature) ir_dereference_variable(return_flag), new(this->signature) ir_constant(false), 0)); + this->signature->body.push_head(this->return_flag); + } + return this->return_flag; + } + + ir_variable* get_return_value() + { + if(!this->return_value) { + assert(!this->signature->return_type->is_void()); + return_value = new(this->signature) ir_variable(this->signature->return_type, "return_value", ir_var_temporary); + this->signature->body.push_head(this->return_value); + } + return this->return_value; + } +}; + +struct ir_lower_jumps_visitor : public ir_control_flow_visitor { + bool progress; + + struct function_record function; + struct loop_record loop; + struct block_record block; + + bool pull_out_jumps; + bool lower_continue; + bool lower_break; + bool lower_sub_return; + bool lower_main_return; + + ir_lower_jumps_visitor() + { + this->progress = false; + } + + void truncate_after_instruction(exec_node *ir) + { + if (!ir) + return; + + while (!ir->get_next()->is_tail_sentinel()) { + ((ir_instruction *)ir->get_next())->remove(); + this->progress = true; + } + } + + void move_outer_block_inside(ir_instruction *ir, exec_list *inner_block) + { + while (!ir->get_next()->is_tail_sentinel()) { + ir_instruction *move_ir = (ir_instruction *)ir->get_next(); + + move_ir->remove(); + inner_block->push_tail(move_ir); + } + } + + virtual void visit(class ir_loop_jump * ir) + { + truncate_after_instruction(ir); + this->block.min_strength = ir->is_break() ? strength_break : strength_continue; + } + + virtual void visit(class ir_return * ir) + { + truncate_after_instruction(ir); + this->block.min_strength = strength_return; + } + + virtual void visit(class ir_discard * ir) + { + truncate_after_instruction(ir); + this->block.min_strength = strength_discard; + } + + enum jump_strength get_jump_strength(ir_instruction* ir) + { + if(!ir) + return strength_none; + else if(ir->ir_type == ir_type_loop_jump) { + if(((ir_loop_jump*)ir)->is_break()) + return strength_break; + else + return strength_continue; + } else if(ir->ir_type == ir_type_return) + return strength_return; + else if(ir->ir_type == ir_type_discard) + return strength_discard; + else + return strength_none; + } + + bool should_lower_jump(ir_jump* ir) + { + unsigned strength = get_jump_strength(ir); + bool lower; + switch(strength) + { + case strength_none: + lower = false; /* don't change this, code relies on it */ + break; + case strength_continue: + lower = lower_continue; + break; + case strength_break: + assert(this->loop.loop); + /* never lower "canonical break" */ + if(ir->get_next()->is_tail_sentinel() && (this->loop.nesting_depth == 0 + || (this->loop.nesting_depth == 1 && this->loop.in_if_at_the_end_of_the_loop))) + lower = false; + else + lower = lower_break; + break; + case strength_return: + /* never lower return at the end of a this->function */ + if(this->function.nesting_depth == 0 && ir->get_next()->is_tail_sentinel()) + lower = false; + else if (this->function.is_main) + lower = lower_main_return; + else + lower = lower_sub_return; + break; + case strength_discard: + lower = false; /* probably nothing needs this lowered */ + break; + } + return lower; + } + + block_record visit_block(exec_list* list) + { + block_record saved_block = this->block; + this->block = block_record(); + visit_exec_list(list, this); + block_record ret = this->block; + this->block = saved_block; + return ret; + } + + virtual void visit(ir_if *ir) + { + if(this->loop.nesting_depth == 0 && ir->get_next()->is_tail_sentinel()) + this->loop.in_if_at_the_end_of_the_loop = true; + + ++this->function.nesting_depth; + ++this->loop.nesting_depth; + + block_record block_records[2]; + ir_jump* jumps[2]; + + block_records[0] = visit_block(&ir->then_instructions); + block_records[1] = visit_block(&ir->else_instructions); + +retry: /* we get here if we put code after the if inside a branch */ + for(unsigned i = 0; i < 2; ++i) { + exec_list& list = i ? ir->else_instructions : ir->then_instructions; + jumps[i] = 0; + if(!list.is_empty() && get_jump_strength((ir_instruction*)list.get_tail())) + jumps[i] = (ir_jump*)list.get_tail(); + } + + for(;;) { + jump_strength jump_strengths[2]; + + for(unsigned i = 0; i < 2; ++i) { + if(jumps[i]) { + jump_strengths[i] = block_records[i].min_strength; + assert(jump_strengths[i] == get_jump_strength(jumps[i])); + } else + jump_strengths[i] = strength_none; + } + + /* move both jumps out if possible */ + if(pull_out_jumps && jump_strengths[0] == jump_strengths[1]) { + bool unify = true; + if(jump_strengths[0] == strength_continue) + ir->insert_after(new(ir) ir_loop_jump(ir_loop_jump::jump_continue)); + else if(jump_strengths[0] == strength_break) + ir->insert_after(new(ir) ir_loop_jump(ir_loop_jump::jump_break)); + /* FINISHME: unify returns with identical expressions */ + else if(jump_strengths[0] == strength_return && this->function.signature->return_type->is_void()) + ir->insert_after(new(ir) ir_return(NULL)); + /* FINISHME: unify discards */ + else + unify = false; + + if(unify) { + jumps[0]->remove(); + jumps[1]->remove(); + this->progress = true; + + jumps[0] = 0; + jumps[1] = 0; + block_records[0].min_strength = strength_none; + block_records[1].min_strength = strength_none; + break; + } + } + + /* lower a jump: if both need to lowered, start with the strongest one, so that + * we might later unify the lowered version with the other one + */ + bool should_lower[2]; + for(unsigned i = 0; i < 2; ++i) + should_lower[i] = should_lower_jump(jumps[i]); + + int lower; + if(should_lower[1] && should_lower[0]) + lower = jump_strengths[1] > jump_strengths[0]; + else if(should_lower[0]) + lower = 0; + else if(should_lower[1]) + lower = 1; + else + break; + + if(jump_strengths[lower] == strength_return) { + ir_variable* return_flag = this->function.get_return_flag(); + if(!this->function.signature->return_type->is_void()) { + ir_variable* return_value = this->function.get_return_value(); + jumps[lower]->insert_before(new(ir) ir_assignment(new (ir) ir_dereference_variable(return_value), ((ir_return*)jumps[lower])->value, NULL)); + } + jumps[lower]->insert_before(new(ir) ir_assignment(new (ir) ir_dereference_variable(return_flag), new (ir) ir_constant(true), NULL)); + this->loop.may_set_return_flag = true; + if(this->loop.loop) { + ir_loop_jump* lowered = 0; + lowered = new(ir) ir_loop_jump(ir_loop_jump::jump_break); + block_records[lower].min_strength = strength_break; + jumps[lower]->replace_with(lowered); + jumps[lower] = lowered; + } else + goto lower_continue; + this->progress = true; + } else if(jump_strengths[lower] == strength_break) { + /* We can't lower to an actual continue because that would execute the increment. + * + * In the lowered code, we instead put the break check between the this->loop body and the increment, + * which is impossible with a real continue as defined by the GLSL IR currently. + * + * Smarter options (such as undoing the increment) are possible but it's not worth implementing them, + * because if break is lowered, continue is almost surely lowered too. + */ + jumps[lower]->insert_before(new(ir) ir_assignment(new (ir) ir_dereference_variable(this->loop.get_break_flag()), new (ir) ir_constant(true), 0)); + goto lower_continue; + } else if(jump_strengths[lower] == strength_continue) { +lower_continue: + ir_variable* execute_flag = this->loop.get_execute_flag(); + jumps[lower]->replace_with(new(ir) ir_assignment(new (ir) ir_dereference_variable(execute_flag), new (ir) ir_constant(false), 0)); + jumps[lower] = 0; + block_records[lower].min_strength = strength_always_clears_execute_flag; + block_records[lower].may_clear_execute_flag = true; + this->progress = true; + break; + } + } + + /* move out a jump out if possible */ + if(pull_out_jumps) { + int move_out = -1; + if(jumps[0] && block_records[1].min_strength >= strength_continue) + move_out = 0; + else if(jumps[1] && block_records[0].min_strength >= strength_continue) + move_out = 1; + + if(move_out >= 0) + { + jumps[move_out]->remove(); + ir->insert_after(jumps[move_out]); + jumps[move_out] = 0; + block_records[move_out].min_strength = strength_none; + this->progress = true; + } + } + + if(block_records[0].min_strength < block_records[1].min_strength) + this->block.min_strength = block_records[0].min_strength; + else + this->block.min_strength = block_records[1].min_strength; + this->block.may_clear_execute_flag = this->block.may_clear_execute_flag || block_records[0].may_clear_execute_flag || block_records[1].may_clear_execute_flag; + + if(this->block.min_strength) + truncate_after_instruction(ir); + else if(this->block.may_clear_execute_flag) + { + int move_into = -1; + if(block_records[0].min_strength && !block_records[1].may_clear_execute_flag) + move_into = 1; + else if(block_records[1].min_strength && !block_records[0].may_clear_execute_flag) + move_into = 0; + + if(move_into >= 0) { + assert(!block_records[move_into].min_strength && !block_records[move_into].may_clear_execute_flag); /* otherwise, we just truncated */ + + exec_list* list = move_into ? &ir->else_instructions : &ir->then_instructions; + exec_node* next = ir->get_next(); + if(!next->is_tail_sentinel()) { + move_outer_block_inside(ir, list); + + exec_list list; + list.head = next; + block_records[move_into] = visit_block(&list); + + this->progress = true; + goto retry; + } + } else { + ir_instruction* ir_after; + for(ir_after = (ir_instruction*)ir->get_next(); !ir_after->is_tail_sentinel();) + { + ir_if* ir_if = ir_after->as_if(); + if(ir_if && ir_if->else_instructions.is_empty()) { + ir_dereference_variable* ir_if_cond_deref = ir_if->condition->as_dereference_variable(); + if(ir_if_cond_deref && ir_if_cond_deref->var == this->loop.execute_flag) { + ir_instruction* ir_next = (ir_instruction*)ir_after->get_next(); + ir_after->insert_before(&ir_if->then_instructions); + ir_after->remove(); + ir_after = ir_next; + continue; + } + } + ir_after = (ir_instruction*)ir_after->get_next(); + + /* only set this if we find any unprotected instruction */ + this->progress = true; + } + + if(!ir->get_next()->is_tail_sentinel()) { + assert(this->loop.execute_flag); + ir_if* if_execute = new(ir) ir_if(new(ir) ir_dereference_variable(this->loop.execute_flag)); + move_outer_block_inside(ir, &if_execute->then_instructions); + ir->insert_after(if_execute); + } + } + } + --this->loop.nesting_depth; + --this->function.nesting_depth; + } + + virtual void visit(ir_loop *ir) + { + ++this->function.nesting_depth; + loop_record saved_loop = this->loop; + this->loop = loop_record(this->function.signature, ir); + + block_record body = visit_block(&ir->body_instructions); + + if(body.min_strength >= strength_break) { + /* FINISHME: turn the this->loop into an if, or replace it with its body */ + } + + if(this->loop.break_flag) { + ir_if* break_if = new(ir) ir_if(new(ir) ir_dereference_variable(this->loop.break_flag)); + break_if->then_instructions.push_tail(new(ir) ir_loop_jump(ir_loop_jump::jump_break)); + ir->body_instructions.push_tail(break_if); + } + + if(this->loop.may_set_return_flag) { + assert(this->function.return_flag); + ir_if* return_if = new(ir) ir_if(new(ir) ir_dereference_variable(this->function.return_flag)); + return_if->then_instructions.push_tail(new(ir) ir_loop_jump(saved_loop.loop ? ir_loop_jump::jump_break : ir_loop_jump::jump_continue)); + ir->insert_after(return_if); + } + + this->loop = saved_loop; + --this->function.nesting_depth; + } + + virtual void visit(ir_function_signature *ir) + { + /* these are not strictly necessary */ + assert(!this->function.signature); + assert(!this->loop.loop); + + function_record saved_function = this->function; + loop_record saved_loop = this->loop; + this->function = function_record(ir); + this->loop = loop_record(ir); + + assert(!this->loop.loop); + visit_block(&ir->body); + + if(this->function.return_value) + ir->body.push_tail(new(ir) ir_return(new (ir) ir_dereference_variable(this->function.return_value))); + + this->loop = saved_loop; + this->function = saved_function; + } + + virtual void visit(class ir_function * ir) + { + visit_block(&ir->signatures); + } +}; + +bool +do_lower_jumps(exec_list *instructions, bool pull_out_jumps, bool lower_sub_return, bool lower_main_return, bool lower_continue, bool lower_break) +{ + ir_lower_jumps_visitor v; + v.pull_out_jumps = pull_out_jumps; + v.lower_continue = lower_continue; + v.lower_break = lower_break; + v.lower_sub_return = lower_sub_return; + v.lower_main_return = lower_main_return; + + do { + v.progress = false; + visit_exec_list(instructions, &v); + } while (v.progress); + + return v.progress; +} -- cgit v1.2.3 From df883eb1575a740bf91e01cbe2eaa4dbc1f9f154 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Wed, 17 Nov 2010 10:43:10 -0800 Subject: glsl: Fix Doxygen tag \file in recently renamed files --- src/glsl/lower_div_to_mul_rcp.cpp | 2 +- src/glsl/lower_explog_to_explog2.cpp | 2 +- src/glsl/lower_if_to_cond_assign.cpp | 2 +- src/glsl/lower_jumps.cpp | 2 +- src/glsl/lower_mat_op_to_vec.cpp | 2 +- src/glsl/lower_mod_to_fract.cpp | 2 +- src/glsl/lower_sub_to_add_neg.cpp | 2 +- src/glsl/lower_vec_index_to_cond_assign.cpp | 2 +- src/glsl/lower_vec_index_to_swizzle.cpp | 2 +- src/glsl/opt_algebraic.cpp | 2 +- src/glsl/opt_constant_folding.cpp | 2 +- src/glsl/opt_constant_propagation.cpp | 2 +- src/glsl/opt_constant_variable.cpp | 2 +- src/glsl/opt_copy_propagation.cpp | 2 +- src/glsl/opt_dead_code.cpp | 2 +- src/glsl/opt_dead_code_local.cpp | 2 +- src/glsl/opt_dead_functions.cpp | 2 +- src/glsl/opt_function_inlining.cpp | 2 +- src/glsl/opt_if_simplification.cpp | 2 +- src/glsl/opt_noop_swizzle.cpp | 2 +- src/glsl/opt_structure_splitting.cpp | 2 +- src/glsl/opt_swizzle_swizzle.cpp | 2 +- src/glsl/opt_tree_grafting.cpp | 2 +- 23 files changed, 23 insertions(+), 23 deletions(-) (limited to 'src/glsl/lower_jumps.cpp') diff --git a/src/glsl/lower_div_to_mul_rcp.cpp b/src/glsl/lower_div_to_mul_rcp.cpp index 640d5d64f9..d34c4bc46d 100644 --- a/src/glsl/lower_div_to_mul_rcp.cpp +++ b/src/glsl/lower_div_to_mul_rcp.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_div_to_mul_rcp.cpp + * \file lower_div_to_mul_rcp.cpp * * Breaks an ir_unop_div expression down to op0 * (rcp(op1)). * diff --git a/src/glsl/lower_explog_to_explog2.cpp b/src/glsl/lower_explog_to_explog2.cpp index 78694a2029..8ad0262544 100644 --- a/src/glsl/lower_explog_to_explog2.cpp +++ b/src/glsl/lower_explog_to_explog2.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_explog_to_explog2.cpp + * \file lower_explog_to_explog2.cpp * * Many GPUs don't have a base e log or exponent instruction, but they * do have base 2 versions, so this pass converts exp and log to exp2 diff --git a/src/glsl/lower_if_to_cond_assign.cpp b/src/glsl/lower_if_to_cond_assign.cpp index 0b87413941..cf48cfb8d6 100644 --- a/src/glsl/lower_if_to_cond_assign.cpp +++ b/src/glsl/lower_if_to_cond_assign.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_if_to_cond_assign.cpp + * \file lower_if_to_cond_assign.cpp * * This attempts to flatten all if statements to conditional * assignments for GPUs that don't do control flow. diff --git a/src/glsl/lower_jumps.cpp b/src/glsl/lower_jumps.cpp index b69cc1ec31..e1e7a5b007 100644 --- a/src/glsl/lower_jumps.cpp +++ b/src/glsl/lower_jumps.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_lower_jumps.cpp + * \file lower_jumps.cpp */ #include "glsl_types.h" diff --git a/src/glsl/lower_mat_op_to_vec.cpp b/src/glsl/lower_mat_op_to_vec.cpp index 244fe48928..4965df8976 100644 --- a/src/glsl/lower_mat_op_to_vec.cpp +++ b/src/glsl/lower_mat_op_to_vec.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_mat_op_to_vec.cpp + * \file lower_mat_op_to_vec.cpp * * Breaks matrix operation expressions down to a series of vector operations. * diff --git a/src/glsl/lower_mod_to_fract.cpp b/src/glsl/lower_mod_to_fract.cpp index c82a1f64fd..ff907ae97c 100644 --- a/src/glsl/lower_mod_to_fract.cpp +++ b/src/glsl/lower_mod_to_fract.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_mod_to_fract.cpp + * \file lower_mod_to_fract.cpp * * Breaks an ir_unop_mod expression down to (op1 * fract(op0 / op1)) * diff --git a/src/glsl/lower_sub_to_add_neg.cpp b/src/glsl/lower_sub_to_add_neg.cpp index 7ed8c1495e..9e4019709b 100644 --- a/src/glsl/lower_sub_to_add_neg.cpp +++ b/src/glsl/lower_sub_to_add_neg.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_sub_to_add_neg.cpp + * \file lower_sub_to_add_neg.cpp * * Breaks an ir_binop_sub expression down to add(op0, neg(op1)) * diff --git a/src/glsl/lower_vec_index_to_cond_assign.cpp b/src/glsl/lower_vec_index_to_cond_assign.cpp index cd8dedf2fe..f8011a16e5 100644 --- a/src/glsl/lower_vec_index_to_cond_assign.cpp +++ b/src/glsl/lower_vec_index_to_cond_assign.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_vec_index_to_cond_assign.cpp + * \file lower_vec_index_to_cond_assign.cpp * * Turns indexing into vector types to a series of conditional moves * of each channel's swizzle into a temporary. diff --git a/src/glsl/lower_vec_index_to_swizzle.cpp b/src/glsl/lower_vec_index_to_swizzle.cpp index 969dc8f94a..9ae43c0db1 100644 --- a/src/glsl/lower_vec_index_to_swizzle.cpp +++ b/src/glsl/lower_vec_index_to_swizzle.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_vec_index_to_swizzle.cpp + * \file lower_vec_index_to_swizzle.cpp * * Turns constant indexing into vector types to swizzles. This will * let other swizzle-aware optimization passes catch these constructs, diff --git a/src/glsl/opt_algebraic.cpp b/src/glsl/opt_algebraic.cpp index c7f5c3b4d6..88b6c485d3 100644 --- a/src/glsl/opt_algebraic.cpp +++ b/src/glsl/opt_algebraic.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_algebraic.cpp + * \file opt_algebraic.cpp * * Takes advantage of association, commutivity, and other algebraic * properties to simplify expressions. diff --git a/src/glsl/opt_constant_folding.cpp b/src/glsl/opt_constant_folding.cpp index 554c54fae3..d69ca75fe0 100644 --- a/src/glsl/opt_constant_folding.cpp +++ b/src/glsl/opt_constant_folding.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_constant_folding.cpp + * \file opt_constant_folding.cpp * Replace constant-valued expressions with references to constant values. */ diff --git a/src/glsl/opt_constant_propagation.cpp b/src/glsl/opt_constant_propagation.cpp index 5d875b7be0..6719fc8186 100644 --- a/src/glsl/opt_constant_propagation.cpp +++ b/src/glsl/opt_constant_propagation.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_constant_propagation.cpp + * \file opt_constant_propagation.cpp * * Tracks assignments of constants to channels of variables, and * usage of those constant channels with direct usage of the constants. diff --git a/src/glsl/opt_constant_variable.cpp b/src/glsl/opt_constant_variable.cpp index 1fb73e765e..8068d0c143 100644 --- a/src/glsl/opt_constant_variable.cpp +++ b/src/glsl/opt_constant_variable.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_constant_variable.cpp + * \file opt_constant_variable.cpp * * Marks variables assigned a single constant value over the course * of the program as constant. diff --git a/src/glsl/opt_copy_propagation.cpp b/src/glsl/opt_copy_propagation.cpp index 0fe8fa6c41..8d07fefbfd 100644 --- a/src/glsl/opt_copy_propagation.cpp +++ b/src/glsl/opt_copy_propagation.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_copy_propagation.cpp + * \file opt_copy_propagation.cpp * * Moves usage of recently-copied variables to the previous copy of * the variable. diff --git a/src/glsl/opt_dead_code.cpp b/src/glsl/opt_dead_code.cpp index 5cf5e99add..cb500d2d10 100644 --- a/src/glsl/opt_dead_code.cpp +++ b/src/glsl/opt_dead_code.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_dead_code.cpp + * \file opt_dead_code.cpp * * Eliminates dead assignments and variable declarations from the code. */ diff --git a/src/glsl/opt_dead_code_local.cpp b/src/glsl/opt_dead_code_local.cpp index 4bbedf0ff9..5689e7d20d 100644 --- a/src/glsl/opt_dead_code_local.cpp +++ b/src/glsl/opt_dead_code_local.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_dead_code_local.cpp + * \file opt_dead_code_local.cpp * * Eliminates local dead assignments from the code. * diff --git a/src/glsl/opt_dead_functions.cpp b/src/glsl/opt_dead_functions.cpp index 16037a2632..cf91cb6d36 100644 --- a/src/glsl/opt_dead_functions.cpp +++ b/src/glsl/opt_dead_functions.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_dead_functions.cpp + * \file opt_dead_functions.cpp * * Eliminates unused functions from the linked program. */ diff --git a/src/glsl/opt_function_inlining.cpp b/src/glsl/opt_function_inlining.cpp index 147c1824c1..169fd82688 100644 --- a/src/glsl/opt_function_inlining.cpp +++ b/src/glsl/opt_function_inlining.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_function_inlining.cpp + * \file opt_function_inlining.cpp * * Replaces calls to functions with the body of the function. */ diff --git a/src/glsl/opt_if_simplification.cpp b/src/glsl/opt_if_simplification.cpp index 021615ebd1..618bacfecf 100644 --- a/src/glsl/opt_if_simplification.cpp +++ b/src/glsl/opt_if_simplification.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_if_simplification.cpp + * \file opt_if_simplification.cpp * * Moves constant branches of if statements out to the surrounding * instruction stream. diff --git a/src/glsl/opt_noop_swizzle.cpp b/src/glsl/opt_noop_swizzle.cpp index 0403dfa4e9..0a906aaf1d 100644 --- a/src/glsl/opt_noop_swizzle.cpp +++ b/src/glsl/opt_noop_swizzle.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_noop_swizzle.cpp + * \file opt_noop_swizzle.cpp * * If a swizzle doesn't change the order or count of components, then * remove the swizzle so that other optimization passes see the value diff --git a/src/glsl/opt_structure_splitting.cpp b/src/glsl/opt_structure_splitting.cpp index ff3ec936eb..d6191002c2 100644 --- a/src/glsl/opt_structure_splitting.cpp +++ b/src/glsl/opt_structure_splitting.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_structure_splitting.cpp + * \file opt_structure_splitting.cpp * * If a structure is only ever referenced by its components, then * split those components out to individual variables so they can be diff --git a/src/glsl/opt_swizzle_swizzle.cpp b/src/glsl/opt_swizzle_swizzle.cpp index 0ffb4fa313..bc442fa869 100644 --- a/src/glsl/opt_swizzle_swizzle.cpp +++ b/src/glsl/opt_swizzle_swizzle.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_swizzle_swizzle.cpp + * \file opt_swizzle_swizzle.cpp * * Eliminates the second swizzle in a swizzle chain. */ diff --git a/src/glsl/opt_tree_grafting.cpp b/src/glsl/opt_tree_grafting.cpp index 9b569b8284..9917c045b1 100644 --- a/src/glsl/opt_tree_grafting.cpp +++ b/src/glsl/opt_tree_grafting.cpp @@ -22,7 +22,7 @@ */ /** - * \file ir_tree_grafting.cpp + * \file opt_tree_grafting.cpp * * Takes assignments to variables that are dereferenced only once and * pastes the RHS expression into where the variable is dereferenced. -- cgit v1.2.3 From 1802cb9bafc4125300870be51e8b22ddd795d61e Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Mon, 29 Nov 2010 10:59:16 -0800 Subject: glsl: Remove "discard" support from lower_jumps. The new lower_discard and opt_discard_simplification passes should handle all the necessary transformations, so lower_jumps doesn't need to support it. Also, lower_jumps incorrectly handled conditional discards - it would unconditionally truncate all code after the discard. Rather than fixing the bug, simply remove the code. NOTE: This is a candidate for the 7.9 branch. --- src/glsl/lower_jumps.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'src/glsl/lower_jumps.cpp') diff --git a/src/glsl/lower_jumps.cpp b/src/glsl/lower_jumps.cpp index e1e7a5b007..beacfaf8b0 100644 --- a/src/glsl/lower_jumps.cpp +++ b/src/glsl/lower_jumps.cpp @@ -36,7 +36,6 @@ enum jump_strength strength_continue, strength_break, strength_return, - strength_discard }; struct block_record @@ -202,8 +201,6 @@ struct ir_lower_jumps_visitor : public ir_control_flow_visitor { virtual void visit(class ir_discard * ir) { - truncate_after_instruction(ir); - this->block.min_strength = strength_discard; } enum jump_strength get_jump_strength(ir_instruction* ir) @@ -217,8 +214,6 @@ struct ir_lower_jumps_visitor : public ir_control_flow_visitor { return strength_continue; } else if(ir->ir_type == ir_type_return) return strength_return; - else if(ir->ir_type == ir_type_discard) - return strength_discard; else return strength_none; } @@ -253,9 +248,6 @@ struct ir_lower_jumps_visitor : public ir_control_flow_visitor { else lower = lower_sub_return; break; - case strength_discard: - lower = false; /* probably nothing needs this lowered */ - break; } return lower; } @@ -313,9 +305,8 @@ retry: /* we get here if we put code after the if inside a branch */ /* FINISHME: unify returns with identical expressions */ else if(jump_strengths[0] == strength_return && this->function.signature->return_type->is_void()) ir->insert_after(new(ir) ir_return(NULL)); - /* FINISHME: unify discards */ - else - unify = false; + else + unify = false; if(unify) { jumps[0]->remove(); -- cgit v1.2.3 From d2d7a273c51127677d394d1bb9484a2d85c5dcd2 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Mon, 29 Nov 2010 11:00:10 -0800 Subject: glsl: Add comments to lower_jumps (from the commit message). This is essentially Luca's commit message, but placed at the top of the file. --- src/glsl/lower_jumps.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'src/glsl/lower_jumps.cpp') diff --git a/src/glsl/lower_jumps.cpp b/src/glsl/lower_jumps.cpp index beacfaf8b0..9cd15ef736 100644 --- a/src/glsl/lower_jumps.cpp +++ b/src/glsl/lower_jumps.cpp @@ -23,6 +23,37 @@ /** * \file lower_jumps.cpp + * + * This pass lowers jumps (break, continue, and return) to if/else structures. + * + * It can be asked to: + * 1. Pull jumps out of ifs where possible + * 2. Remove all "continue"s, replacing them with an "execute flag" + * 3. Replace all "break" with a single conditional one at the end of the loop + * 4. Replace all "return"s with a single return at the end of the function, + * for the main function and/or other functions + * + * Applying this pass gives several benefits: + * 1. All functions can be inlined. + * 2. nv40 and other pre-DX10 chips without "continue" can be supported + * 3. nv30 and other pre-DX10 chips with no control flow at all are better + * supported + * + * Continues are lowered by adding a per-loop "execute flag", initialized to + * true, that when cleared inhibits all execution until the end of the loop. + * + * Breaks are lowered to continues, plus setting a "break flag" that is checked + * at the end of the loop, and trigger the unique "break". + * + * Returns are lowered to breaks/continues, plus adding a "return flag" that + * causes loops to break again out of their enclosing loops until all the + * loops are exited: then the "execute flag" logic will ignore everything + * until the end of the function. + * + * Note that "continue" and "return" can also be implemented by adding + * a dummy loop and using break. + * However, this is bad for hardware with limited nesting depth, and + * prevents further optimization, and thus is not currently performed. */ #include "glsl_types.h" -- cgit v1.2.3 From ef534f3838f23d757a40426728789183ed36c3bb Mon Sep 17 00:00:00 2001 From: Fabian Bieler Date: Wed, 1 Dec 2010 14:44:58 +0100 Subject: glsl: fix lowering conditional returns in subroutines this fix applies to the lower_sub_return 'branch' of the lower_jumps pass Fixes piglit tests glsl-functions-5 and glsl-functions-6. --- src/glsl/lower_jumps.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/glsl/lower_jumps.cpp') diff --git a/src/glsl/lower_jumps.cpp b/src/glsl/lower_jumps.cpp index 9cd15ef736..d99e0aa739 100644 --- a/src/glsl/lower_jumps.cpp +++ b/src/glsl/lower_jumps.cpp @@ -512,7 +512,11 @@ lower_continue: if(this->loop.may_set_return_flag) { assert(this->function.return_flag); ir_if* return_if = new(ir) ir_if(new(ir) ir_dereference_variable(this->function.return_flag)); - return_if->then_instructions.push_tail(new(ir) ir_loop_jump(saved_loop.loop ? ir_loop_jump::jump_break : ir_loop_jump::jump_continue)); + saved_loop.may_set_return_flag = true; + if(saved_loop.loop) + return_if->then_instructions.push_tail(new(ir) ir_loop_jump(ir_loop_jump::jump_break)); + else + move_outer_block_inside(ir, &return_if->else_instructions); ir->insert_after(return_if); } -- cgit v1.2.3