r600g/sb: initial commit of the optimizing shader backend
[mesa.git] / src / gallium / drivers / r600 / sb / sb_def_use.cpp
1 /*
2 * Copyright 2013 Vadim Girlin <vadimgirlin@gmail.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Vadim Girlin
25 */
26
27 #include "sb_shader.h"
28
29 #include "sb_pass.h"
30
31 namespace r600_sb {
32
33 using std::cerr;
34
35 int def_use::run() {
36 run_on(sh.root, true);
37 run_on(sh.root, false);
38 return 0;
39 }
40
41 void def_use::process_phi(container_node *c, bool defs, bool uses) {
42
43 for (node_iterator I = c->begin(), E = c->end(); I != E; ++I) {
44 node *n = *I;
45 if (uses)
46 process_uses(n);
47 if (defs)
48 process_defs(n, n->dst, false);
49 }
50 }
51
52 void def_use::run_on(node* n, bool defs) {
53
54 bool is_region = (n->type == NT_REGION);
55 bool is_op = (n->type == NT_OP || n->type == NT_IF);
56
57 if (is_op) {
58
59 if (0) {
60 cerr << "def_use processing op ";
61 dump::dump_op(n);
62 cerr << "\n";
63 }
64
65 if (defs)
66 process_defs(n, n->dst, false);
67 else
68 process_uses(n);
69 } else if (is_region & defs) {
70 region_node *r = static_cast<region_node*>(n);
71 if (r->loop_phi)
72 process_phi(r->loop_phi, true, false);
73 }
74
75 if (n->is_container() && n->subtype != NST_ALU_PACKED_INST) {
76 container_node *c = static_cast<container_node*>(n);
77 for (node_iterator I = c->begin(), E = c->end(); I != E; ++I) {
78 run_on(*I, defs);
79 }
80 }
81
82 if (is_region) {
83 region_node *r = static_cast<region_node*>(n);
84 if (r->phi)
85 process_phi(r->phi, defs, !defs);
86 if (r->loop_phi && !defs)
87 process_phi(r->loop_phi, false, true);
88 }
89 }
90
91 void def_use::process_defs(node *n, vvec &vv, bool arr_def) {
92
93 for (vvec::iterator I = vv.begin(), E = vv.end(); I != E; ++I) {
94 value *v = *I;
95 if (!v)
96 continue;
97
98 if (arr_def)
99 v->adef = n;
100 else
101 v->def = n;
102
103 v->delete_uses();
104
105 if (v->is_rel()) {
106 process_defs(n, v->mdef, true);
107 }
108 }
109 }
110
111 void def_use::process_uses(node* n) {
112 unsigned k = 0;
113
114 for (vvec::iterator I = n->src.begin(), E = n->src.end(); I != E;
115 ++I, ++k) {
116 value *v = *I;
117 if (!v || v->is_readonly())
118 continue;
119
120 if (v->is_rel()) {
121 if (!v->rel->is_readonly())
122 v->rel->add_use(n, UK_SRC_REL, k);
123
124 unsigned k2 = 0;
125 for (vvec::iterator I = v->muse.begin(), E = v->muse.end();
126 I != E; ++I, ++k2) {
127 value *v = *I;
128 if (!v)
129 continue;
130
131 v->add_use(n, UK_MAYUSE, k2);
132 }
133 } else
134 v->add_use(n, UK_SRC, k);
135 }
136
137 k = 0;
138 for (vvec::iterator I = n->dst.begin(), E = n->dst.end(); I != E;
139 ++I, ++k) {
140 value *v = *I;
141 if (!v || !v->is_rel())
142 continue;
143
144 if (!v->rel->is_readonly())
145 v->rel->add_use(n, UK_DST_REL, k);
146 unsigned k2 = 0;
147 for (vvec::iterator I = v->muse.begin(), E = v->muse.end();
148 I != E; ++I, ++k2) {
149 value *v = *I;
150 if (!v)
151 continue;
152
153 v->add_use(n, UK_MAYDEF, k2);
154 }
155 }
156
157 if (n->pred)
158 n->pred->add_use(n, UK_PRED, 0);
159
160 if (n->type == NT_IF) {
161 if_node *i = static_cast<if_node*>(n);
162 if (i->cond)
163 i->cond->add_use(i, UK_COND, 0);
164 }
165 }
166
167 } // namespace r600_sb