diff options
author | Matt Turner <[email protected]> | 2014-09-04 13:25:15 -0700 |
---|---|---|
committer | Matt Turner <[email protected]> | 2014-09-30 17:09:34 -0700 |
commit | d13bcdb3a9f9b43010fe8cbb4efbfe7eec0b705b (patch) | |
tree | 059f377ec64b2f8ff543e0825cca4e8a057a5fa1 | |
parent | 6e7d36fd2c1185ae1b84b81b8630472ceb87356d (diff) |
i965/fs: Extend predicated break pass to predicate WHILE.
Helps a handful of programs in Serious Sam 3 that use do-while loops.
instructions in affected programs: 16114 -> 16075 (-0.24%)
Reviewed-by: Ian Romanick <[email protected]>
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs_peephole_predicated_break.cpp | 36 |
1 files changed, 36 insertions, 0 deletions
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 index 31b287aae36..b7a1d7e7722 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_peephole_predicated_break.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_peephole_predicated_break.cpp @@ -38,6 +38,18 @@ * * 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 @@ -107,6 +119,30 @@ fs_visitor::opt_peephole_predicated_break() 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(); + fs_inst *while_inst = (fs_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; } |