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
run()33 int dce_cleanup::run() {
34 int r;
35
36 // Run cleanup for as long as there are unused nodes.
37 do {
38 nodes_changed = false;
39 r = vpass::run();
40 } while (r == 0 && nodes_changed);
41
42 return r;
43 }
44
visit(node & n,bool enter)45 bool dce_cleanup::visit(node& n, bool enter) {
46 if (enter) {
47 } else {
48 if (n.flags & NF_DEAD)
49 n.remove();
50 else
51 cleanup_dst(n);
52 }
53 return true;
54 }
55
visit(alu_group_node & n,bool enter)56 bool dce_cleanup::visit(alu_group_node& n, bool enter) {
57 if (enter) {
58 } else {
59 n.expand();
60 }
61 return true;
62 }
63
visit(cf_node & n,bool enter)64 bool dce_cleanup::visit(cf_node& n, bool enter) {
65 if (enter) {
66 if (n.flags & NF_DEAD)
67 n.remove();
68 else
69 cleanup_dst(n);
70 } else {
71 if ((sh.dce_flags & DF_EXPAND) &&
72 (n.bc.op_ptr->flags & (CF_CLAUSE | CF_BRANCH | CF_LOOP)))
73 n.expand();
74 }
75 return true;
76 }
77
visit(alu_node & n,bool enter)78 bool dce_cleanup::visit(alu_node& n, bool enter) {
79 if (enter) {
80 } else {
81 if (n.flags & NF_DEAD)
82 n.remove();
83 else
84 cleanup_dst(n);
85 }
86 return true;
87 }
88
visit(alu_packed_node & n,bool enter)89 bool dce_cleanup::visit(alu_packed_node& n, bool enter) {
90 if (enter) {
91 } else {
92 if (n.flags & NF_DEAD)
93 n.remove();
94 else
95 cleanup_dst(n);
96 }
97 return false;
98 }
99
visit(fetch_node & n,bool enter)100 bool dce_cleanup::visit(fetch_node& n, bool enter) {
101 if (enter) {
102 } else {
103 if (n.flags & NF_DEAD)
104 n.remove();
105 else
106 cleanup_dst(n);
107 }
108 return true;
109 }
110
visit(region_node & n,bool enter)111 bool dce_cleanup::visit(region_node& n, bool enter) {
112 if (enter) {
113 if (n.loop_phi)
114 run_on(*n.loop_phi);
115 } else {
116 if (n.phi)
117 run_on(*n.phi);
118 }
119 return true;
120 }
121
cleanup_dst(node & n)122 void dce_cleanup::cleanup_dst(node& n) {
123 if (!cleanup_dst_vec(n.dst) && remove_unused &&
124 !n.dst.empty() && !(n.flags & NF_DONT_KILL) && n.parent)
125 {
126 // Delete use references to the removed node from the src values.
127 for (vvec::iterator I = n.src.begin(), E = n.src.end(); I != E; ++I) {
128 value* v = *I;
129 if (v && v->def && v->uses.size())
130 {
131 v->remove_use(&n);
132 }
133 }
134 n.remove();
135 nodes_changed = true;
136 }
137 }
138
visit(container_node & n,bool enter)139 bool dce_cleanup::visit(container_node& n, bool enter) {
140 if (enter)
141 cleanup_dst(n);
142 return true;
143 }
144
cleanup_dst_vec(vvec & vv)145 bool dce_cleanup::cleanup_dst_vec(vvec& vv) {
146 bool alive = false;
147
148 for (vvec::iterator I = vv.begin(), E = vv.end(); I != E; ++I) {
149 value* &v = *I;
150 if (!v)
151 continue;
152
153 if (v->gvn_source && v->gvn_source->is_dead())
154 v->gvn_source = NULL;
155
156 if (v->is_dead() || (remove_unused && !v->is_rel() && !v->uses.size()))
157 v = NULL;
158 else
159 alive = true;
160 }
161
162 return alive;
163 }
164
165 } // namespace r600_sb
166