From 5a360dcad1fdb91f9129cb21775b9af60cbf57e4 Mon Sep 17 00:00:00 2001 From: Matt Turner Date: Fri, 2 Oct 2015 20:30:41 -0700 Subject: i965: Generalize predicated break pass for use in vec4 backend. instructions in affected programs: 44204 -> 43762 (-1.00%) helped: 221 Reviewed-by: Jason Ekstrand --- src/mesa/drivers/dri/i965/Makefile.sources | 2 +- src/mesa/drivers/dri/i965/brw_fs.cpp | 2 +- .../dri/i965/brw_fs_peephole_predicated_break.cpp | 149 --------------------- src/mesa/drivers/dri/i965/brw_predicated_break.cpp | 148 ++++++++++++++++++++ src/mesa/drivers/dri/i965/brw_shader.h | 6 +- src/mesa/drivers/dri/i965/brw_vec4.cpp | 1 + 6 files changed, 156 insertions(+), 152 deletions(-) delete mode 100644 src/mesa/drivers/dri/i965/brw_fs_peephole_predicated_break.cpp create mode 100644 src/mesa/drivers/dri/i965/brw_predicated_break.cpp (limited to 'src') diff --git a/src/mesa/drivers/dri/i965/Makefile.sources b/src/mesa/drivers/dri/i965/Makefile.sources index eb8196d4845..6f97f735add 100644 --- a/src/mesa/drivers/dri/i965/Makefile.sources +++ b/src/mesa/drivers/dri/i965/Makefile.sources @@ -55,7 +55,6 @@ i965_FILES = \ brw_fs_live_variables.cpp \ brw_fs_live_variables.h \ brw_fs_nir.cpp \ - brw_fs_peephole_predicated_break.cpp \ brw_fs_reg_allocate.cpp \ brw_fs_register_coalesce.cpp \ brw_fs_saturate_propagation.cpp \ @@ -91,6 +90,7 @@ i965_FILES = \ brw_packed_float.c \ brw_performance_monitor.c \ brw_pipe_control.c \ + brw_predicated_break.cpp \ brw_primitive_restart.c \ brw_program.c \ brw_program.h \ diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp index 03206882ebf..1187c6765cd 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp @@ -4823,7 +4823,7 @@ fs_visitor::optimize() OPT(opt_algebraic); OPT(opt_cse); OPT(opt_copy_propagate); - OPT(opt_peephole_predicated_break); + OPT(opt_predicated_break, this); OPT(opt_cmod_propagation); OPT(dead_code_eliminate); OPT(opt_peephole_sel); diff --git a/src/mesa/drivers/dri/i965/brw_fs_peephole_predicated_break.cpp b/src/mesa/drivers/dri/i965/brw_fs_peephole_predicated_break.cpp deleted file mode 100644 index 29f21680655..00000000000 --- a/src/mesa/drivers/dri/i965/brw_fs_peephole_predicated_break.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright © 2013 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. - */ - -#include "brw_fs.h" -#include "brw_cfg.h" - -using namespace brw; - -/** @file brw_fs_peephole_predicated_break.cpp - * - * Loops are often structured as - * - * loop: - * CMP.f0 - * (+f0) IF - * BREAK - * ENDIF - * ... - * WHILE loop - * - * This peephole pass removes the IF and ENDIF instructions and predicates the - * BREAK, dropping two instructions from the loop body. - * - * If the loop was a DO { ... } WHILE loop, it looks like - * - * loop: - * ... - * CMP.f0 - * (+f0) IF - * BREAK - * ENDIF - * WHILE loop - * - * and we can remove the BREAK instruction and predicate the WHILE. - */ - -bool -fs_visitor::opt_peephole_predicated_break() -{ - bool progress = false; - - foreach_block (block, cfg) { - if (block->start_ip != block->end_ip) - continue; - - /* BREAK and CONTINUE instructions, by definition, can only be found at - * the ends of basic blocks. - */ - backend_instruction *jump_inst = block->end(); - if (jump_inst->opcode != BRW_OPCODE_BREAK && - jump_inst->opcode != BRW_OPCODE_CONTINUE) - continue; - - backend_instruction *if_inst = block->prev()->end(); - if (if_inst->opcode != BRW_OPCODE_IF) - continue; - - backend_instruction *endif_inst = block->next()->start(); - if (endif_inst->opcode != BRW_OPCODE_ENDIF) - continue; - - bblock_t *jump_block = block; - bblock_t *if_block = jump_block->prev(); - bblock_t *endif_block = jump_block->next(); - - jump_inst->predicate = if_inst->predicate; - jump_inst->predicate_inverse = if_inst->predicate_inverse; - - bblock_t *earlier_block = if_block; - if (if_block->start_ip == if_block->end_ip) { - earlier_block = if_block->prev(); - } - - if_inst->remove(if_block); - - bblock_t *later_block = endif_block; - if (endif_block->start_ip == endif_block->end_ip) { - later_block = endif_block->next(); - } - endif_inst->remove(endif_block); - - if (!earlier_block->ends_with_control_flow()) { - earlier_block->children.make_empty(); - earlier_block->add_successor(cfg->mem_ctx, jump_block); - } - - if (!later_block->starts_with_control_flow()) { - later_block->parents.make_empty(); - } - jump_block->add_successor(cfg->mem_ctx, later_block); - - if (earlier_block->can_combine_with(jump_block)) { - earlier_block->combine_with(jump_block); - - block = earlier_block; - } - - /* Now look at the first instruction of the block following the BREAK. If - * it's a WHILE, we can delete the break, predicate the WHILE, and join - * the two basic blocks. - */ - bblock_t *while_block = earlier_block->next(); - backend_instruction *while_inst = while_block->start(); - - if (jump_inst->opcode == BRW_OPCODE_BREAK && - while_inst->opcode == BRW_OPCODE_WHILE && - while_inst->predicate == BRW_PREDICATE_NONE) { - jump_inst->remove(earlier_block); - while_inst->predicate = jump_inst->predicate; - while_inst->predicate_inverse = !jump_inst->predicate_inverse; - - earlier_block->children.make_empty(); - earlier_block->add_successor(cfg->mem_ctx, while_block); - - assert(earlier_block->can_combine_with(while_block)); - earlier_block->combine_with(while_block); - - earlier_block->next()->parents.make_empty(); - earlier_block->add_successor(cfg->mem_ctx, earlier_block->next()); - } - - progress = true; - } - - if (progress) - invalidate_live_intervals(); - - return progress; -} diff --git a/src/mesa/drivers/dri/i965/brw_predicated_break.cpp b/src/mesa/drivers/dri/i965/brw_predicated_break.cpp new file mode 100644 index 00000000000..607715dace4 --- /dev/null +++ b/src/mesa/drivers/dri/i965/brw_predicated_break.cpp @@ -0,0 +1,148 @@ +/* + * Copyright © 2013 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. + */ + +#include "brw_cfg.h" + +using namespace brw; + +/** @file brw_predicated_break.cpp + * + * Loops are often structured as + * + * loop: + * CMP.f0 + * (+f0) IF + * BREAK + * ENDIF + * ... + * WHILE loop + * + * This peephole pass removes the IF and ENDIF instructions and predicates the + * BREAK, dropping two instructions from the loop body. + * + * If the loop was a DO { ... } WHILE loop, it looks like + * + * loop: + * ... + * CMP.f0 + * (+f0) IF + * BREAK + * ENDIF + * WHILE loop + * + * and we can remove the BREAK instruction and predicate the WHILE. + */ + +bool +opt_predicated_break(backend_shader *s) +{ + bool progress = false; + + foreach_block (block, s->cfg) { + if (block->start_ip != block->end_ip) + continue; + + /* BREAK and CONTINUE instructions, by definition, can only be found at + * the ends of basic blocks. + */ + backend_instruction *jump_inst = block->end(); + if (jump_inst->opcode != BRW_OPCODE_BREAK && + jump_inst->opcode != BRW_OPCODE_CONTINUE) + continue; + + backend_instruction *if_inst = block->prev()->end(); + if (if_inst->opcode != BRW_OPCODE_IF) + continue; + + backend_instruction *endif_inst = block->next()->start(); + if (endif_inst->opcode != BRW_OPCODE_ENDIF) + continue; + + bblock_t *jump_block = block; + bblock_t *if_block = jump_block->prev(); + bblock_t *endif_block = jump_block->next(); + + jump_inst->predicate = if_inst->predicate; + jump_inst->predicate_inverse = if_inst->predicate_inverse; + + bblock_t *earlier_block = if_block; + if (if_block->start_ip == if_block->end_ip) { + earlier_block = if_block->prev(); + } + + if_inst->remove(if_block); + + bblock_t *later_block = endif_block; + if (endif_block->start_ip == endif_block->end_ip) { + later_block = endif_block->next(); + } + endif_inst->remove(endif_block); + + if (!earlier_block->ends_with_control_flow()) { + earlier_block->children.make_empty(); + earlier_block->add_successor(s->cfg->mem_ctx, jump_block); + } + + if (!later_block->starts_with_control_flow()) { + later_block->parents.make_empty(); + } + jump_block->add_successor(s->cfg->mem_ctx, later_block); + + if (earlier_block->can_combine_with(jump_block)) { + earlier_block->combine_with(jump_block); + + block = earlier_block; + } + + /* Now look at the first instruction of the block following the BREAK. If + * it's a WHILE, we can delete the break, predicate the WHILE, and join + * the two basic blocks. + */ + bblock_t *while_block = earlier_block->next(); + backend_instruction *while_inst = while_block->start(); + + if (jump_inst->opcode == BRW_OPCODE_BREAK && + while_inst->opcode == BRW_OPCODE_WHILE && + while_inst->predicate == BRW_PREDICATE_NONE) { + jump_inst->remove(earlier_block); + while_inst->predicate = jump_inst->predicate; + while_inst->predicate_inverse = !jump_inst->predicate_inverse; + + earlier_block->children.make_empty(); + earlier_block->add_successor(s->cfg->mem_ctx, while_block); + + assert(earlier_block->can_combine_with(while_block)); + earlier_block->combine_with(while_block); + + earlier_block->next()->parents.make_empty(); + earlier_block->add_successor(s->cfg->mem_ctx, earlier_block->next()); + } + + progress = true; + } + + if (progress) + s->invalidate_live_intervals(); + + return progress; +} diff --git a/src/mesa/drivers/dri/i965/brw_shader.h b/src/mesa/drivers/dri/i965/brw_shader.h index fd96740526b..b6c070ef4c7 100644 --- a/src/mesa/drivers/dri/i965/brw_shader.h +++ b/src/mesa/drivers/dri/i965/brw_shader.h @@ -219,7 +219,7 @@ enum instruction_scheduler_mode { SCHEDULE_POST, }; -class backend_shader { +struct backend_shader { protected: backend_shader(const struct brw_compiler *compiler, @@ -273,6 +273,8 @@ void brw_setup_image_uniform_values(gl_shader_stage stage, unsigned param_start_index, const gl_uniform_storage *storage); +#else +struct backend_shader; #endif /* __cplusplus */ enum brw_reg_type brw_type_for_base_type(const struct glsl_type *type); @@ -283,6 +285,8 @@ bool brw_saturate_immediate(enum brw_reg_type type, struct brw_reg *reg); bool brw_negate_immediate(enum brw_reg_type type, struct brw_reg *reg); bool brw_abs_immediate(enum brw_reg_type type, struct brw_reg *reg); +bool opt_predicated_break(struct backend_shader *s); + #ifdef __cplusplus extern "C" { #endif diff --git a/src/mesa/drivers/dri/i965/brw_vec4.cpp b/src/mesa/drivers/dri/i965/brw_vec4.cpp index 7e94cc3ef4a..76ce0c46198 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4.cpp @@ -1862,6 +1862,7 @@ vec4_visitor::run() pass_num = 0; iteration++; + OPT(opt_predicated_break, this); OPT(opt_reduce_swizzle); OPT(dead_code_eliminate); OPT(dead_control_flow_eliminate, this); -- cgit v1.2.3