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_ra_checker.cpp | |
parent | fbb065d629d2f79a6224fc3e5e89d5acc275e3b4 (diff) |
r600g/sb: initial commit of the optimizing shader backend
Diffstat (limited to 'src/gallium/drivers/r600/sb/sb_ra_checker.cpp')
-rw-r--r-- | src/gallium/drivers/r600/sb/sb_ra_checker.cpp | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/src/gallium/drivers/r600/sb/sb_ra_checker.cpp b/src/gallium/drivers/r600/sb/sb_ra_checker.cpp new file mode 100644 index 00000000000..83510b02158 --- /dev/null +++ b/src/gallium/drivers/r600/sb/sb_ra_checker.cpp @@ -0,0 +1,277 @@ +/* + * 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 + */ + +#include <sstream> + +#include "sb_shader.h" +#include "sb_pass.h" + +namespace r600_sb { + +using std::cerr; + +int ra_checker::run() { + + rm_stack.clear(); + rm_stack.resize(1); + rm_stk_level = 0; + + process_op_dst(sh.root); + + run_on(sh.root); + + assert(rm_stk_level == 0); + + dump_all_errors(); + + assert(sh.errors.empty()); + + return 0; +} + +void ra_checker::dump_error(const error_info &e) { + + cerr << "error at : "; + dump::dump_op(e.n); + + cerr << "\n"; + cerr << " : " << e.message << "\n"; +} + +void ra_checker::dump_all_errors() { + for (error_map::iterator I = sh.errors.begin(), E = sh.errors.end(); + I != E; ++I) { + dump_error(I->second); + } +} + + +void ra_checker::error(node *n, unsigned id, std::string msg) { + error_info e; + e.n = n; + e.arg_index = id; + e.message = msg; + sh.errors.insert(std::make_pair(n, e)); +} + +void ra_checker::push_stack() { + ++rm_stk_level; + if (rm_stack.size() == rm_stk_level) + rm_stack.push_back(rm_stack.back()); + else + rm_stack[rm_stk_level] = rm_stack[rm_stk_level - 1]; +} + +void ra_checker::pop_stack() { + --rm_stk_level; +} + +void ra_checker::kill_alu_only_regs() { + // TODO +} + +void ra_checker::check_value_gpr(node *n, unsigned id, value *v) { + sel_chan gpr = v->gpr; + if (!gpr) { + std::ostringstream o; + o << "operand value " << *v << " is not allocated"; + error(n, id, o.str()); + return; + } + reg_value_map::iterator F = rmap().find(v->gpr); + if (F == rmap().end()) { + std::ostringstream o; + o << "operand value " << *v << " was not previously written to its gpr"; + error(n, id, o.str()); + return; + } + if (!F->second->v_equal(v)) { + std::ostringstream o; + o << "expected operand value " << *v + << ", gpr contains " << *(F->second); + error(n, id, o.str()); + return; + } + + +} + +void ra_checker::check_src_vec(node *n, unsigned id, vvec &vv, bool src) { + + for (vvec::iterator I = vv.begin(), E = vv.end(); I != E; ++I) { + value *v = *I; + if (!v || !v->is_sgpr()) + continue; + + if (v->is_rel()) { + if (!v->rel) { + std::ostringstream o; + o << "expected relative offset in " << *v; + error(n, id, o.str()); + return; + } + } else if (src) { + check_value_gpr(n, id, v); + } + } +} + +void ra_checker::check_op_src(node *n) { + check_src_vec(n, 0, n->dst, false); + check_src_vec(n, 100, n->src, true); +} + +void ra_checker::process_op_dst(node *n) { + + unsigned id = 0; + + for (vvec::iterator I = n->dst.begin(), E = n->dst.end(); I != E; ++I) { + value *v = *I; + + ++id; + + if (!v) + continue; + + if (v->is_sgpr()) { + + if (!v->gpr) { + std::ostringstream o; + o << "destination operand " << *v << " is not allocated"; + error(n, id, o.str()); + return; + } + + rmap()[v->gpr] = v; + } else if (v->is_rel()) { + if (v->rel->is_const()) { + rmap()[v->get_final_gpr()] = v; + } else { + unsigned sz = v->array->array_size; + unsigned start = v->array->gpr; + for (unsigned i = 0; i < sz; ++i) { + rmap()[start + (i << 2)] = v; + } + } + } + } +} + +void ra_checker::check_phi_src(container_node *p, unsigned id) { + for (node_iterator I = p->begin(), E = p->end(); I != E; ++I) { + node *n = *I; + value *s = n->src[id]; + if (s->is_sgpr()) + check_value_gpr(n, id, s); + } +} + +void ra_checker::process_phi_dst(container_node *p) { + for (node_iterator I = p->begin(), E = p->end(); I != E; ++I) { + node *n = *I; + process_op_dst(n); + } +} + +void ra_checker::check_alu_group(alu_group_node *g) { + + for (node_iterator I = g->begin(), E = g->end(); I != E; ++I) { + node *a = *I; + if (!a->is_alu_inst()) { + std::ostringstream o; + o << "non-alu node inside alu group"; + error(a, 0, o.str()); + return; + } + + check_op_src(a); + } + + std::fill(prev_dst, prev_dst + 5, (value*)NULL); + + for (node_iterator I = g->begin(), E = g->end(); I != E; ++I) { + alu_node *a = static_cast<alu_node*>(*I); + + process_op_dst(a); + + unsigned slot = a->bc.slot; + prev_dst[slot] = a->dst[0]; + } +} + +void ra_checker::run_on(container_node* c) { + + if (c->is_region()) { + region_node *r = static_cast<region_node*>(c); + if (r->loop_phi) { + check_phi_src(r->loop_phi, 0); + process_phi_dst(r->loop_phi); + } + } else if (c->is_depart()) { + + push_stack(); + + } else if (c->is_repeat()) { + + push_stack(); + + } + + for (node_iterator I = c->begin(), E = c->end(); I != E; ++I) { + node *n = *I; + + if(n->is_cf_inst() || n->is_fetch_inst()) { + check_op_src(n); + process_op_dst(n); + } + + if (n->is_container()) { + if (n->is_alu_group()) { + check_alu_group(static_cast<alu_group_node*>(n)); + } else { + container_node *nc = static_cast<container_node*>(n); + run_on(nc); + } + } + } + + if (c->is_depart()) { + depart_node *r = static_cast<depart_node*>(c); + check_phi_src(r->target->phi, r->dep_id); + pop_stack(); + } else if (c->is_repeat()) { + repeat_node *r = static_cast<repeat_node*>(c); + assert (r->target->loop_phi); + + pop_stack(); + } else if (c->is_region()) { + region_node *r = static_cast<region_node*>(c); + if (r->phi) + process_phi_dst(r->phi); + } +} + +} // namespace r600_sb |