diff options
author | Vadim Girlin <[email protected]> | 2013-05-27 04:00:03 +0400 |
---|---|---|
committer | Vadim Girlin <[email protected]> | 2013-05-27 15:19:20 +0400 |
commit | 725671a83a67cc8cf16c0913f6e1835fb272c2fb (patch) | |
tree | 29b9fa66f25675bdf3c64b504dbc010a03ad87a7 /src/gallium/drivers/r600/sb/sb_peephole.cpp | |
parent | 5285c4c88e4beab653660e8a5b51ce9a779fc0d2 (diff) |
r600g/sb: improve optimization of conditional instructions
Signed-off-by: Vadim Girlin <[email protected]>
Diffstat (limited to 'src/gallium/drivers/r600/sb/sb_peephole.cpp')
-rw-r--r-- | src/gallium/drivers/r600/sb/sb_peephole.cpp | 53 |
1 files changed, 40 insertions, 13 deletions
diff --git a/src/gallium/drivers/r600/sb/sb_peephole.cpp b/src/gallium/drivers/r600/sb/sb_peephole.cpp index 6373b5c3a61..cb423c9b224 100644 --- a/src/gallium/drivers/r600/sb/sb_peephole.cpp +++ b/src/gallium/drivers/r600/sb/sb_peephole.cpp @@ -46,7 +46,7 @@ int peephole::run() { void peephole::run_on(container_node* c) { - for (node_riterator I = c->rbegin(), E = c->rend(); I != E; ++I) { + for (node_iterator I = c->begin(), E = c->end(); I != E; ++I) { node *n = *I; if (n->is_container()) @@ -56,7 +56,8 @@ void peephole::run_on(container_node* c) { if (n->is_alu_inst()) { alu_node *a = static_cast<alu_node*>(n); - if (a->bc.op_ptr->flags & (AF_PRED | AF_SET | AF_CMOV)) { + if (a->bc.op_ptr->flags & + (AF_PRED | AF_SET | AF_CMOV | AF_KILL)) { optimize_cc_op(a); } else if (a->bc.op == ALU_OP1_FLT_TO_INT) { @@ -73,8 +74,8 @@ void peephole::run_on(container_node* c) { void peephole::optimize_cc_op(alu_node* a) { unsigned aflags = a->bc.op_ptr->flags; - if (aflags & (AF_PRED | AF_SET)) { - optimize_SETcc_op(a); + if (aflags & (AF_PRED | AF_SET | AF_KILL)) { + optimize_cc_op2(a); } else if (aflags & AF_CMOV) { optimize_CNDcc_op(a); } @@ -90,26 +91,37 @@ void peephole::convert_float_setcc(alu_node *f2i, alu_node *s) { f2i->remove(); } -void peephole::optimize_SETcc_op(alu_node* a) { +void peephole::optimize_cc_op2(alu_node* a) { unsigned flags = a->bc.op_ptr->flags; unsigned cc = flags & AF_CC_MASK; + + if ((cc != AF_CC_E && cc != AF_CC_NE) || a->pred) + return; + unsigned cmp_type = flags & AF_CMP_TYPE_MASK; unsigned dst_type = flags & AF_DST_TYPE_MASK; - bool is_pred = flags & AF_PRED; - // TODO handle other cases + int op_kind = (flags & AF_PRED) ? 1 : + (flags & AF_SET) ? 2 : + (flags & AF_KILL) ? 3 : 0; + + bool swapped = false; - if (a->src[1]->is_const() && (cc == AF_CC_E || cc == AF_CC_NE) && - a->src[1]->literal_value == literal(0) && - a->bc.src[0].neg == 0 && a->bc.src[0].abs == 0) { + if (a->src[0]->is_const() && a->src[0]->literal_value == literal(0)) { + std::swap(a->src[0],a->src[1]); + swapped = true; + } + + if (swapped || (a->src[1]->is_const() && + a->src[1]->literal_value == literal(0))) { value *s = a->src[0]; bool_op_info bop = {}; PPH_DUMP( - sblog << "optSETcc "; + sblog << "cc_op2: "; dump::dump_op(a); sblog << "\n"; ); @@ -139,8 +151,23 @@ void peephole::optimize_SETcc_op(alu_node* a) { sblog <<"\n"; ); - unsigned newop = is_pred ? get_predsetcc_opcode(cc, cmp_type) : - get_setcc_opcode(cc, cmp_type, dst_type != AF_FLOAT_DST); + unsigned newop; + + switch(op_kind) { + case 1: + newop = get_predsetcc_op(cc, cmp_type); + break; + case 2: + newop = get_setcc_op(cc, cmp_type, dst_type != AF_FLOAT_DST); + break; + case 3: + newop = get_killcc_op(cc, cmp_type); + break; + default: + newop = ALU_OP0_NOP; + assert(!"invalid op kind"); + break; + } a->bc.set_op(newop); |