From 8f2214f4892acb994d13531d555196bd8f242dad Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 13 Sep 2010 14:25:26 -0700 Subject: [PATCH] glsl2: Add pass to remove redundant jumps --- src/glsl/Makefile | 1 + src/glsl/Makefile.am | 3 +- src/glsl/SConscript | 1 + src/glsl/glsl_parser_extras.cpp | 2 + src/glsl/ir_optimization.h | 1 + src/glsl/opt_redundant_jumps.cpp | 111 +++++++++++++++++++++++++++++++ 6 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 src/glsl/opt_redundant_jumps.cpp diff --git a/src/glsl/Makefile b/src/glsl/Makefile index a0e7c05d67f..1746e18ad69 100644 --- a/src/glsl/Makefile +++ b/src/glsl/Makefile @@ -76,6 +76,7 @@ CXX_SOURCES = \ loop_controls.cpp \ loop_unroll.cpp \ lower_noise.cpp \ + opt_redundant_jumps.cpp \ s_expression.cpp LIBS = \ diff --git a/src/glsl/Makefile.am b/src/glsl/Makefile.am index 3ce8e21b0cb..f62a85e8930 100644 --- a/src/glsl/Makefile.am +++ b/src/glsl/Makefile.am @@ -66,7 +66,8 @@ glsl_SOURCES = \ loop_analysis.cpp \ loop_controls.cpp \ loop_unroll.cpp \ - lower_noise.cpp + lower_noise.cpp \ + opt_redundant_jumps.cpp BUILT_SOURCES = glsl_parser.h glsl_parser.cpp glsl_lexer.cpp CLEANFILES = $(BUILT_SOURCES) diff --git a/src/glsl/SConscript b/src/glsl/SConscript index bd324eefef5..6e2ef2d61f1 100644 --- a/src/glsl/SConscript +++ b/src/glsl/SConscript @@ -73,6 +73,7 @@ sources = [ 'loop_controls.cpp', 'loop_unroll.cpp', 'lower_noise.cpp', + 'opt_redundant_jumps.cpp', 's_expression.cpp', ] diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp index 28241f7dd3f..4ac062b42c1 100644 --- a/src/glsl/glsl_parser_extras.cpp +++ b/src/glsl/glsl_parser_extras.cpp @@ -716,6 +716,8 @@ do_common_optimization(exec_list *ir, bool linked, unsigned max_unroll_iteration progress = do_swizzle_swizzle(ir) || progress; progress = do_noop_swizzle(ir) || progress; + progress = optimize_redundant_jumps(ir) || progress; + loop_state *ls = analyze_loop_variables(ir); progress = set_loop_controls(ir, ls) || progress; progress = unroll_loops(ir, ls, max_unroll_iterations) || progress; diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h index 726a6ad97dd..b365ed2b235 100644 --- a/src/glsl/ir_optimization.h +++ b/src/glsl/ir_optimization.h @@ -56,3 +56,4 @@ bool do_tree_grafting(exec_list *instructions); bool do_vec_index_to_cond_assign(exec_list *instructions); bool do_vec_index_to_swizzle(exec_list *instructions); bool lower_noise(exec_list *instructions); +bool optimize_redundant_jumps(exec_list *instructions); diff --git a/src/glsl/opt_redundant_jumps.cpp b/src/glsl/opt_redundant_jumps.cpp new file mode 100644 index 00000000000..edf4bb6c224 --- /dev/null +++ b/src/glsl/opt_redundant_jumps.cpp @@ -0,0 +1,111 @@ +/* + * Copyright © 2010 Intel Corporation + * + * 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 opt_redundant_jumps.cpp + * Remove certain types of redundant jumps + */ + +#include "ir.h" + +class redundant_jumps_visitor : public ir_hierarchical_visitor { +public: + redundant_jumps_visitor() + { + this->progress = false; + } + + virtual ir_visitor_status visit_leave(ir_if *); + virtual ir_visitor_status visit_leave(ir_loop *); + + bool progress; +}; + + +ir_visitor_status +redundant_jumps_visitor::visit_leave(ir_if *ir) +{ + /* If the last instruction in both branches is a 'break' or a 'continue', + * pull it out of the branches and insert it after the if-statment. Note + * that both must be the same type (either 'break' or 'continue'). + */ + ir_instruction *const last_then = + (ir_instruction *) ir->then_instructions.get_tail(); + ir_instruction *const last_else = + (ir_instruction *) ir->else_instructions.get_tail(); + + if ((last_then == NULL) || (last_else == NULL)) + return visit_continue; + + if ((last_then->ir_type != ir_type_loop_jump) + || (last_else->ir_type != ir_type_loop_jump)) + return visit_continue; + + ir_loop_jump *const then_jump = (ir_loop_jump *) last_then; + ir_loop_jump *const else_jump = (ir_loop_jump *) last_else; + + if (then_jump->mode != else_jump->mode) + return visit_continue; + + then_jump->remove(); + else_jump->remove(); + this->progress = true; + + ir->insert_after(then_jump); + + /* If both branchs of the if-statement are now empty, remove the + * if-statement. + */ + if (ir->then_instructions.is_empty() && ir->else_instructions.is_empty()) + ir->remove(); + + return visit_continue; +} + + +ir_visitor_status +redundant_jumps_visitor::visit_leave(ir_loop *ir) +{ + /* If the last instruction of a loop body is a 'continue', remove it. + */ + ir_instruction *const last = + (ir_instruction *) ir->body_instructions.get_tail(); + + if (last && (last->ir_type == ir_type_loop_jump) + && (((ir_loop_jump *) last)->mode == ir_loop_jump::jump_continue)) { + last->remove(); + this->progress = true; + } + + return visit_continue; +} + + +bool +optimize_redundant_jumps(exec_list *instructions) +{ + redundant_jumps_visitor v; + + v.run(instructions); + return v.progress; +} -- 2.30.2