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:
@@ -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 \
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user