2 * Copyright 2013 Vadim Girlin <vadimgirlin@gmail.com>
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:
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
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.
27 #include "sb_shader.h"
33 #define LIV_DUMP(a) do { a } while (0)
40 bool liveness::visit(container_node
& n
, bool enter
) {
51 bool liveness::visit(bb_node
& n
, bool enter
) {
60 bool liveness::visit(alu_group_node
& n
, bool enter
) {
67 bool liveness::visit(cf_node
& n
, bool enter
) {
69 if (n
.bc
.op
== CF_OP_CF_END
) {
74 update_interferences();
82 bool liveness::visit(alu_node
& n
, bool enter
) {
84 update_interferences();
91 bool liveness::visit(alu_packed_node
& n
, bool enter
) {
93 update_interferences();
101 bool liveness::visit(fetch_node
& n
, bool enter
) {
103 update_interferences();
110 bool liveness::visit(region_node
& n
, bool enter
) {
114 update_interferences();
117 process_phi_outs(n
.phi
);
124 n
.live_before
.clear();
127 assert(n
.count() == 1);
128 run_on(*static_cast<container_node
*>(*n
.begin()));
130 // second pass for loops
132 process_phi_outs(n
.loop_phi
);
133 n
.live_before
= live
;
135 run_on(*static_cast<container_node
*>(*n
.begin()));
137 update_interferences(); // FIXME is it required
139 process_phi_outs(n
.loop_phi
);
140 process_phi_branch(n
.loop_phi
, 0);
143 update_interferences(); // FIXME is it required
146 n
.live_before
= live
;
151 bool liveness::visit(repeat_node
& n
, bool enter
) {
153 live
= n
.target
->live_before
;
154 process_phi_branch(n
.target
->loop_phi
, n
.rep_id
);
160 bool liveness::visit(depart_node
& n
, bool enter
) {
162 live
= n
.target
->live_after
;
164 process_phi_branch(n
.target
->phi
, n
.dep_id
);
170 bool liveness::visit(if_node
& n
, bool enter
) {
172 assert(n
.count() == 1);
175 run_on(*static_cast<container_node
*>(*n
.begin()));
178 live
.add_set(n
.live_after
);
183 void liveness::update_interferences() {
184 if (!sh
.compute_interferences
)
192 dump::dump_set(sh
, live
);
197 for(val_set::iterator I
= s
.begin(sh
), E
= s
.end(sh
); I
!= E
; ++I
) {
202 v
->array
->interferences
.add_set(s
);
205 v
->interferences
.add_set(s
);
206 v
->interferences
.remove_val(v
);
209 sblog
<< "interferences updated for ";
212 dump::dump_set(sh
, v
->interferences
);
216 live_changed
= false;
219 bool liveness::remove_val(value
*v
) {
220 if (live
.remove_val(v
)) {
221 v
->flags
&= ~VLF_DEAD
;
224 v
->flags
|= VLF_DEAD
;
228 bool liveness::process_maydef(value
*v
) {
230 vvec::iterator
S(v
->muse
.begin());
232 for (vvec::iterator I
= v
->mdef
.begin(), E
= v
->mdef
.end(); I
!= E
;
234 value
*&d
= *I
, *&u
= *S
;
240 bool alive
= remove_val(d
);
251 bool liveness::remove_vec(vvec
&vv
) {
253 for (vvec::reverse_iterator I
= vv
.rbegin(), E
= vv
.rend(); I
!= E
; ++I
) {
259 r
|= process_maydef(v
);
266 bool r600_sb::liveness::visit(node
& n
, bool enter
) {
268 update_interferences();
274 bool liveness::process_outs(node
& n
) {
275 bool alive
= remove_vec(n
.dst
);
281 bool liveness::add_vec(vvec
&vv
, bool src
) {
283 for (vvec::iterator I
= vv
.begin(), E
= vv
.end(); I
!= E
; ++I
) {
285 if (!v
|| v
->is_readonly())
289 r
|= add_vec(v
->muse
, true);
290 if (v
->rel
->is_any_reg())
291 r
|= live
.add_val(v
->rel
);
294 r
|= live
.add_val(v
);
301 void liveness::process_ins(node
& n
) {
302 if (!(n
.flags
& NF_DEAD
)) {
304 live_changed
|= add_vec(n
.src
, true);
305 live_changed
|= add_vec(n
.dst
, false);
307 if (n
.type
== NT_IF
) {
308 if_node
&in
= (if_node
&)n
;
310 live_changed
|= live
.add_val(in
.cond
);
313 live_changed
|= live
.add_val(n
.pred
);
317 void liveness::process_op(node
& n
) {
320 sblog
<< "process_op: ";
323 sblog
<< "process_op: live_after:";
324 dump::dump_set(sh
, live
);
328 if(!n
.dst
.empty() || n
.is_cf_op(CF_OP_CALL_FS
)) {
329 if (!process_outs(n
)) {
330 if (!(n
.flags
& NF_DONT_KILL
))
339 sblog
<< "process_op: live_before:";
340 dump::dump_set(sh
, live
);
345 int liveness::init() {
347 if (sh
.compute_interferences
) {
348 gpr_array_vec
&vv
= sh
.arrays();
349 for (gpr_array_vec::iterator I
= vv
.begin(), E
= vv
.end(); I
!= E
;
352 a
->interferences
.clear();
359 void liveness::update_src_vec(vvec
&vv
, bool src
) {
360 for (vvec::iterator I
= vv
.begin(), E
= vv
.end(); I
!= E
; ++I
) {
363 if (!v
|| !v
->is_sgpr())
366 if (v
->rel
&& v
->rel
->is_dead())
367 v
->rel
->flags
&= ~VLF_DEAD
;
369 if (src
&& v
->is_dead()) {
370 v
->flags
&= ~VLF_DEAD
;
375 void liveness::process_phi_outs(container_node
*phi
) {
376 for (node_iterator I
= phi
->begin(), E
= phi
->end(); I
!= E
; ++I
) {
378 if (!process_outs(*n
)) {
381 n
->flags
&= ~NF_DEAD
;
382 update_src_vec(n
->src
, true);
383 update_src_vec(n
->dst
, false);
388 void liveness::process_phi_branch(container_node
* phi
, unsigned id
) {
390 for (node_iterator I
= phi
->begin(), E
= phi
->end(); I
!= E
; ++I
) {
395 value
*v
= n
->src
[id
];
397 if (!v
->is_readonly()) {
398 live_changed
|= s
.add_val(v
);
399 v
->flags
&= ~VLF_DEAD
;
404 } //namespace r600_sb