diff options
author | Vadim Girlin <[email protected]> | 2013-04-30 20:51:36 +0400 |
---|---|---|
committer | Vadim Girlin <[email protected]> | 2013-04-30 21:50:47 +0400 |
commit | 2cd769179345799d383f92dd615991755ec24be1 (patch) | |
tree | 9863c9e92e645cad35a861b7de76f0c98d64b0d0 /src/gallium/drivers/r600/sb/sb_peephole.cpp | |
parent | fbb065d629d2f79a6224fc3e5e89d5acc275e3b4 (diff) |
r600g/sb: initial commit of the optimizing shader backend
Diffstat (limited to 'src/gallium/drivers/r600/sb/sb_peephole.cpp')
-rw-r--r-- | src/gallium/drivers/r600/sb/sb_peephole.cpp | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/src/gallium/drivers/r600/sb/sb_peephole.cpp b/src/gallium/drivers/r600/sb/sb_peephole.cpp new file mode 100644 index 00000000000..444765e8779 --- /dev/null +++ b/src/gallium/drivers/r600/sb/sb_peephole.cpp @@ -0,0 +1,232 @@ +/* + * Copyright 2013 Vadim Girlin <[email protected]> + * + * 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 + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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. + * + * Authors: + * Vadim Girlin + */ + +#define PPH_DEBUG 0 + +#if PPH_DEBUG +#define PPH_DUMP(q) do { q } while (0) +#else +#define PPH_DUMP(q) +#endif + +#include "sb_shader.h" + +#include "sb_pass.h" + +namespace r600_sb { + +using std::cerr; + +int peephole::run() { + + run_on(sh.root); + + return 0; +} + +void peephole::run_on(container_node* c) { + + for (node_riterator I = c->rbegin(), E = c->rend(); I != E; ++I) { + node *n = *I; + + if (n->is_container()) + run_on(static_cast<container_node*>(n)); + else { + + if (n->is_alu_inst()) { + alu_node *a = static_cast<alu_node*>(n); + + if (a->bc.op_ptr->flags & AF_CC_MASK) { + optimize_cc_op(a); + } else if (a->bc.op == ALU_OP1_FLT_TO_INT) { + + alu_node *s = a; + if (get_bool_flt_to_int_source(s)) { + convert_float_setcc(a, s); + } + } + } + } + } +} + +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); + } else if (aflags & AF_CMOV) { + optimize_CNDcc_op(a); + } +} + +void peephole::convert_float_setcc(alu_node *f2i, alu_node *s) { + alu_node *ns = sh.clone(s); + + ns->dst[0] = f2i->dst[0]; + ns->dst[0]->def = ns; + ns->bc.set_op(ns->bc.op + (ALU_OP2_SETE_DX10 - ALU_OP2_SETE)); + f2i->insert_after(ns); + f2i->remove(); +} + +void peephole::optimize_SETcc_op(alu_node* a) { + + unsigned flags = a->bc.op_ptr->flags; + unsigned cc = flags & AF_CC_MASK; + 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 + + 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) { + + value *s = a->src[0]; + + bool_op_info bop = {}; + + PPH_DUMP( + cerr << "optSETcc "; + dump::dump_op(a); + cerr << "\n"; + ); + + if (!get_bool_op_info(s, bop)) + return; + + if (cc == AF_CC_E) + bop.invert = !bop.invert; + + bool swap_args = false; + + cc = bop.n->bc.op_ptr->flags & AF_CC_MASK; + + if (bop.invert) + cc = invert_setcc_condition(cc, swap_args); + + if (bop.int_cvt) { + assert(cmp_type != AF_FLOAT_CMP); + cmp_type = AF_FLOAT_CMP; + } + + PPH_DUMP( + cerr << "boi node: "; + dump::dump_op(bop.n); + cerr << " invert: " << bop.invert << " int_cvt: " << bop.int_cvt; + cerr <<"\n"; + ); + + unsigned newop = is_pred ? get_predsetcc_opcode(cc, cmp_type) : + get_setcc_opcode(cc, cmp_type, dst_type != AF_FLOAT_DST); + + a->bc.set_op(newop); + + if (swap_args) { + a->src[0] = bop.n->src[1]; + a->src[1] = bop.n->src[0]; + a->bc.src[0] = bop.n->bc.src[1]; + a->bc.src[1] = bop.n->bc.src[0]; + + } else { + a->src[0] = bop.n->src[0]; + a->src[1] = bop.n->src[1]; + a->bc.src[0] = bop.n->bc.src[0]; + a->bc.src[1] = bop.n->bc.src[1]; + } + } +} + +void peephole::optimize_CNDcc_op(alu_node* a) { + + //TODO +} + +bool peephole::get_bool_flt_to_int_source(alu_node* &a) { + + if (a->bc.op == ALU_OP1_FLT_TO_INT) { + + if (a->bc.src[0].neg || a->bc.src[0].abs || a->bc.src[0].rel) + return false; + + value *s = a->src[0]; + if (!s || !s->def || !s->def->is_alu_inst()) + return false; + + alu_node *dn = static_cast<alu_node*>(s->def); + + if (dn->is_alu_op(ALU_OP1_TRUNC)) { + s = dn->src[0]; + if (!s || !s->def || !s->def->is_alu_inst()) + return false; + + if (dn->bc.src[0].neg != 1 || dn->bc.src[0].abs != 0 || + dn->bc.src[0].rel != 0) { + return false; + } + + dn = static_cast<alu_node*>(s->def); + + } + + if (dn->bc.op_ptr->flags & AF_SET) { + a = dn; + return true; + } + } + return false; +} + +bool peephole::get_bool_op_info(value* b, bool_op_info& bop) { + + node *d = b->def; + + if (!d || !d->is_alu_inst()) + return false; + + alu_node *dn = static_cast<alu_node*>(d); + + if (dn->bc.op_ptr->flags & AF_SET) { + bop.n = dn; + + if (dn->bc.op_ptr->flags & AF_DX10) + bop.int_cvt = true; + + return true; + } + + if (get_bool_flt_to_int_source(dn)) { + bop.n = dn; + bop.int_cvt = true; + return true; + } + + return false; +} + +} // namespace r600_sb |