i965/fs: New peephole optimization to flatten IF/BREAK/ENDIF.

total instructions in shared programs: 1550713 -> 1550449 (-0.02%)
instructions in affected programs:     7931 -> 7667 (-3.33%)

Reviewed-by: Paul Berry <stereotype441@gmail.com>
This commit is contained in:
Matt Turner
2013-10-22 17:51:28 -07:00
parent 9658b04fc4
commit d30b2ed5f8
4 changed files with 99 additions and 0 deletions
@@ -60,6 +60,7 @@ i965_FILES = \
brw_fs_fp.cpp \
brw_fs_generator.cpp \
brw_fs_live_variables.cpp \
brw_fs_peephole_predicated_break.cpp \
brw_fs_reg_allocate.cpp \
brw_fs_sel_peephole.cpp \
brw_fs_vector_splitting.cpp \
+1
View File
@@ -3172,6 +3172,7 @@ fs_visitor::run()
progress = opt_cse() || progress;
progress = opt_copy_propagate() || progress;
progress = opt_peephole_sel() || progress;
progress = opt_peephole_predicated_break() || progress;
progress = dead_code_eliminate() || progress;
progress = dead_code_eliminate_local() || progress;
progress = dead_control_flow_eliminate(this) || progress;
+1
View File
@@ -364,6 +364,7 @@ public:
bool try_emit_mad(ir_expression *ir, int mul_arg);
void try_replace_with_sel();
bool opt_peephole_sel();
bool opt_peephole_predicated_break();
void emit_bool_to_cond_code(ir_rvalue *condition);
void emit_if_gen6(ir_if *ir);
void emit_unspill(fs_inst *inst, fs_reg reg, uint32_t spill_offset,
@@ -0,0 +1,96 @@
/*
* 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"
/** @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.
*/
bool
fs_visitor::opt_peephole_predicated_break()
{
bool progress = false;
cfg_t cfg(&instructions);
for (int b = 0; b < cfg.num_blocks; b++) {
bblock_t *block = cfg.blocks[b];
/* BREAK and CONTINUE instructions, by definition, can only be found at
* the ends of basic blocks.
*/
fs_inst *inst = (fs_inst *) block->end;
if (inst->opcode != BRW_OPCODE_BREAK && inst->opcode != BRW_OPCODE_CONTINUE)
continue;
fs_inst *if_inst = (fs_inst *) inst->prev;
if (if_inst->opcode != BRW_OPCODE_IF)
continue;
fs_inst *endif_inst = (fs_inst *) inst->next;
if (endif_inst->opcode != BRW_OPCODE_ENDIF)
continue;
/* For Sandybridge with IF with embedded comparison we need to emit an
* instruction to set the flag register.
*/
if (brw->gen == 6 && if_inst->conditional_mod) {
fs_inst *cmp_inst = CMP(reg_null_d, if_inst->src[0], if_inst->src[1],
if_inst->conditional_mod);
if_inst->insert_before(cmp_inst);
inst->predicate = BRW_PREDICATE_NORMAL;
} else {
inst->predicate = if_inst->predicate;
inst->predicate_inverse = if_inst->predicate_inverse;
}
if_inst->remove();
endif_inst->remove();
/* By removing the ENDIF instruction we removed a basic block. Skip over
* it for the next iteration.
*/
b++;
progress = true;
}
if (progress)
invalidate_live_intervals();
return progress;
}