aboutsummaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/r600/sb/sb_ra_checker.cpp
diff options
context:
space:
mode:
authorVadim Girlin <[email protected]>2013-04-30 20:51:36 +0400
committerVadim Girlin <[email protected]>2013-04-30 21:50:47 +0400
commit2cd769179345799d383f92dd615991755ec24be1 (patch)
tree9863c9e92e645cad35a861b7de76f0c98d64b0d0 /src/gallium/drivers/r600/sb/sb_ra_checker.cpp
parentfbb065d629d2f79a6224fc3e5e89d5acc275e3b4 (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.cpp277
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