total instructions in shared programs: 6496326 -> 6492315 (-0.06%) instructions in affected programs: 159282 -> 155271 (-2.52%) helped: 411 --- src/mesa/drivers/dri/i965/Makefile.sources | 1 + src/mesa/drivers/dri/i965/brw_fs.cpp | 1 + src/mesa/drivers/dri/i965/brw_predicate_block.cpp | 104 ++++++++++++++++++++++ src/mesa/drivers/dri/i965/brw_shader.h | 6 +- src/mesa/drivers/dri/i965/brw_vec4.cpp | 1 + 5 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 src/mesa/drivers/dri/i965/brw_predicate_block.cpp
diff --git a/src/mesa/drivers/dri/i965/Makefile.sources b/src/mesa/drivers/dri/i965/Makefile.sources index cc3ecaf..9b1a039 100644 --- a/src/mesa/drivers/dri/i965/Makefile.sources +++ b/src/mesa/drivers/dri/i965/Makefile.sources @@ -90,6 +90,7 @@ i965_FILES = \ brw_packed_float.c \ brw_performance_monitor.c \ brw_pipe_control.c \ + brw_predicate_block.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 5ca5c26..7c7cb0d 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp @@ -4844,6 +4844,7 @@ fs_visitor::optimize() OPT(opt_cmod_propagation); OPT(dead_code_eliminate); OPT(opt_peephole_sel); + OPT(opt_predicate_block, this); OPT(dead_control_flow_eliminate, this); OPT(opt_register_renaming); OPT(opt_redundant_discard_jumps); diff --git a/src/mesa/drivers/dri/i965/brw_predicate_block.cpp b/src/mesa/drivers/dri/i965/brw_predicate_block.cpp new file mode 100644 index 0000000..4973172 --- /dev/null +++ b/src/mesa/drivers/dri/i965/brw_predicate_block.cpp @@ -0,0 +1,104 @@ +/* + * Copyright © 2015 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" + +/** @file brw_predicate_block.cpp + * + * This file contains the opt_predicate_block() optimization pass that moves a + * small block of instructions from inside an IF/ENDIF block to before the IF + * instruction by predicating them. For example, + * + * Before: + * + * CMP.f0 + * (+f0) IF + * MUL ... + * ADD ... + * ENDIF + * + * After: + * + * CMP.f0 + * (+f0) MUL ... + * (+f0) ADD ... + * (+f0) IF + * ENDIF + * + * dead_control_flow_eliminate() is then able to remove the IF/ENDIF pair and + * combine basic blocks. + */ + +bool +opt_predicate_block(backend_shader *s) +{ + bool progress = false; + + foreach_block_safe(block, s->cfg) { + if (block->num == 0 || block->num == s->cfg->num_blocks - 1) + continue; + + if (block->end_ip - block->start_ip > 3) + continue; + + bblock_t *if_block = block->prev(); + backend_instruction *if_inst = if_block->end(); + if (if_inst->opcode != BRW_OPCODE_IF || + if_inst->conditional_mod != BRW_CONDITIONAL_NONE) + continue; + + backend_instruction *endif_inst = block->next()->start(); + if (endif_inst->opcode != BRW_OPCODE_ENDIF) + continue; + + bool skip = false; + + foreach_inst_in_block(backend_instruction, inst, block) { + if (inst->opcode <= BRW_OPCODE_NOP && !inst->is_control_flow()) { + skip = skip || inst->writes_flag() || inst->reads_flag(); + } else { + skip = true; + } + + if (skip) + break; + } + + if (skip) + continue; + + foreach_inst_in_block_safe(backend_instruction, inst, block) { + inst->remove(block); + if_inst->insert_before(if_block, inst); + inst->predicate = if_inst->predicate; + inst->predicate_inverse = if_inst->predicate_inverse; + } + + 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 9c4bdee..ca0c635 100644 --- a/src/mesa/drivers/dri/i965/brw_shader.h +++ b/src/mesa/drivers/dri/i965/brw_shader.h @@ -231,7 +231,7 @@ enum instruction_scheduler_mode { SCHEDULE_POST, }; -class backend_shader { +struct backend_shader { protected: backend_shader(const struct brw_compiler *compiler, @@ -292,6 +292,8 @@ public: uint32_t brw_texture_offset(int *offsets, unsigned num_components); +#else +struct backend_shader; #endif /* __cplusplus */ enum brw_reg_type brw_type_for_base_type(const struct glsl_type *type); @@ -302,6 +304,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_predicate_block(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 c61b385..cf22340 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4.cpp @@ -1874,6 +1874,7 @@ vec4_visitor::run() OPT(opt_reduce_swizzle); OPT(dead_code_eliminate); + OPT(opt_predicate_block, this); OPT(dead_control_flow_eliminate, this); OPT(opt_copy_propagation); OPT(opt_cse); -- 2.4.9 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev