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.
28 #include "sb_shader.h"
33 bool node::accept(vpass
& p
, bool enter
) { return p
.visit(*this, enter
); }
34 bool container_node::accept(vpass
& p
, bool enter
) { return p
.visit(*this, enter
); }
35 bool alu_group_node::accept(vpass
& p
, bool enter
) { return p
.visit(*this, enter
); }
36 bool alu_node::accept(vpass
& p
, bool enter
) { return p
.visit(*this, enter
); }
37 bool cf_node::accept(vpass
& p
, bool enter
) { return p
.visit(*this, enter
); }
38 bool fetch_node::accept(vpass
& p
, bool enter
) { return p
.visit(*this, enter
); }
39 bool region_node::accept(vpass
& p
, bool enter
) { return p
.visit(*this, enter
); }
41 bool repeat_node::accept(vpass
& p
, bool enter
) {
42 return p
.visit(*this, enter
);
45 bool depart_node::accept(vpass
& p
, bool enter
) {
46 return p
.visit(*this, enter
);
48 bool if_node::accept(vpass
& p
, bool enter
) { return p
.visit(*this, enter
); }
49 bool bb_node::accept(vpass
& p
, bool enter
) { return p
.visit(*this, enter
); }
50 bool alu_packed_node::accept(vpass
& p
, bool enter
) {
51 return p
.visit(*this, enter
);
54 void alu_packed_node::init_args(bool repl
) {
55 alu_node
*p
= static_cast<alu_node
*>(first
);
56 assert(p
->is_valid());
58 dst
.insert(dst
.end(), p
->dst
.begin(), p
->dst
.end());
59 src
.insert(src
.end(), p
->src
.begin(), p
->src
.end());
60 p
= static_cast<alu_node
*>(p
->next
);
63 value
*replicated_value
= NULL
;
65 for (vvec::iterator I
= dst
.begin(), E
= dst
.end(); I
!= E
; ++I
) {
70 v
->assign_source(replicated_value
);
80 void container_node::insert_node_before(node
* s
, node
* n
) {
95 void container_node::insert_node_after(node
* s
, node
* n
) {
110 void container_node::move(iterator b
, iterator e
) {
113 container_node
*source_container
= b
->parent
;
114 node
*l
= source_container
->cut(b
, e
);
117 first
->parent
= this;
125 node
* container_node::cut(iterator b
, iterator e
) {
126 assert(!*b
|| b
->parent
== this);
127 assert(!*e
|| e
->parent
== this);
137 e
->prev
->next
= NULL
;
149 unsigned container_node::count() {
159 void container_node::remove_node(node
*n
) {
161 n
->prev
->next
= n
->next
;
165 n
->next
->prev
= n
->prev
;
171 void container_node::expand(container_node
*n
) {
192 } while (e0
!= e1
->next
);
197 void container_node::push_back(node
*n
) {
206 n
->prev
= n
->next
= NULL
;
210 void container_node::push_front(node
*n
) {
219 n
->prev
= n
->next
= NULL
;
224 void node::insert_before(node
* n
) {
225 parent
->insert_node_before(this, n
);
228 void node::insert_after(node
* n
) {
229 parent
->insert_node_after(this, n
);
232 void node::replace_with(node
* n
) {
241 if (parent
->first
== this)
244 if (parent
->last
== this)
251 void container_node::expand() {
252 parent
->expand(this);
255 void node::remove() {parent
->remove_node(this);
258 value_hash
node::hash_src() const {
260 value_hash h
= 12345;
262 for (int k
= 0, e
= src
.size(); k
< e
; ++k
) {
272 value_hash
node::hash() const {
274 if (parent
&& parent
->subtype
== NST_LOOP_PHI_CONTAINER
)
277 return hash_src() ^ (subtype
<< 13) ^ (type
<< 3);
280 void r600_sb::container_node::append_from(container_node
* c
) {
287 last
->next
= c
->first
;
288 last
->next
->prev
= last
;
303 bool node::fold_dispatch(expr_handler
* ex
) { return ex
->fold(*this); }
304 bool container_node::fold_dispatch(expr_handler
* ex
) { return ex
->fold(*this); }
305 bool alu_node::fold_dispatch(expr_handler
* ex
) { return ex
->fold(*this); }
306 bool alu_packed_node::fold_dispatch(expr_handler
* ex
) { return ex
->fold(*this); }
307 bool fetch_node::fold_dispatch(expr_handler
* ex
) { return ex
->fold(*this); }
308 bool cf_node::fold_dispatch(expr_handler
* ex
) { return ex
->fold(*this); }
310 unsigned alu_packed_node::get_slot_mask() {
312 for (node_iterator I
= begin(), E
= end(); I
!= E
; ++I
)
313 mask
|= 1 << static_cast<alu_node
*>(*I
)->bc
.slot
;
317 void alu_packed_node::update_packed_items(sb_context
&ctx
) {
319 vvec::iterator
SI(src
.begin()), DI(dst
.begin());
323 alu_node
*c
= static_cast<alu_node
*>(first
);
324 unsigned flags
= c
->bc
.op_ptr
->flags
;
325 unsigned slot_flags
= c
->bc
.slot_flags
;
327 // fixup dst for instructions that replicate output
328 if (((flags
& AF_REPL
) && slot_flags
== AF_4V
) ||
329 (ctx
.is_cayman() && slot_flags
== AF_S
)) {
335 for (vvec::iterator I2
= dst
.begin(), E2
= dst
.end();
339 chan
= v
->get_final_chan();
340 assert(!swp
[chan
] || swp
[chan
] == v
);
346 for (vvec::iterator I2
= dst
.begin(), E2
= dst
.end();
347 I2
!= E2
; ++I2
, ++chan
) {
352 for (node_iterator I
= begin(), E
= end(); I
!= E
; ++I
) {
353 alu_node
*n
= static_cast<alu_node
*>(*I
);
356 for (vvec::iterator I2
= n
->src
.begin(), E2
= n
->src
.end();
357 I2
!= E2
; ++I2
, ++SI
) {
360 for (vvec::iterator I2
= n
->dst
.begin(), E2
= n
->dst
.end();
361 I2
!= E2
; ++I2
, ++DI
) {
367 bool node::is_cf_op(unsigned op
) {
370 cf_node
*c
= static_cast<cf_node
*>(this);
371 return c
->bc
.op
== op
;
374 bool node::is_alu_op(unsigned op
) {
377 alu_node
*c
= static_cast<alu_node
*>(this);
378 return c
->bc
.op
== op
;
381 bool node::is_fetch_op(unsigned op
) {
382 if (!is_fetch_inst())
384 fetch_node
*c
= static_cast<fetch_node
*>(this);
385 return c
->bc
.op
== op
;
390 bool node::is_mova() {
393 alu_node
*a
= static_cast<alu_node
*>(this);
394 return (a
->bc
.op_ptr
->flags
& AF_MOVA
);
397 bool node::is_pred_set() {
400 alu_node
*a
= static_cast<alu_node
*>(this);
401 return (a
->bc
.op_ptr
->flags
& AF_ANY_PRED
);
404 unsigned node::cf_op_flags() {
405 assert(is_cf_inst());
406 cf_node
*c
= static_cast<cf_node
*>(this);
407 return c
->bc
.op_ptr
->flags
;
410 unsigned node::alu_op_flags() {
411 assert(is_alu_inst());
412 alu_node
*c
= static_cast<alu_node
*>(this);
413 return c
->bc
.op_ptr
->flags
;
416 unsigned node::fetch_op_flags() {
417 assert(is_fetch_inst());
418 fetch_node
*c
= static_cast<fetch_node
*>(this);
419 return c
->bc
.op_ptr
->flags
;
422 unsigned node::alu_op_slot_flags() {
423 assert(is_alu_inst());
424 alu_node
*c
= static_cast<alu_node
*>(this);
425 return c
->bc
.slot_flags
;
428 region_node
* node::get_parent_region() {
430 while ((p
= p
->parent
))
432 return static_cast<region_node
*>(p
);
436 unsigned container_node::real_alu_count() {
440 if (t
->is_alu_inst())
442 else if (t
->is_alu_packed())
443 c
+= static_cast<container_node
*>(t
)->count();
449 void container_node::collect_stats(node_stats
& s
) {
451 for (node_iterator I
= begin(), E
= end(); I
!= E
; ++I
) {
453 if (n
->is_container()) {
454 static_cast<container_node
*>(n
)->collect_stats(s
);
457 if (n
->is_alu_inst()) {
459 alu_node
*a
= static_cast<alu_node
*>(n
);
460 if (a
->bc
.op_ptr
->flags
& AF_KILL
)
462 else if (a
->is_copy_mov())
463 ++s
.alu_copy_mov_count
;
466 } else if (n
->is_fetch_inst())
468 else if (n
->is_cf_inst())
470 else if (n
->is_region()) {
472 region_node
*r
= static_cast<region_node
*>(n
);
477 s
.phi_count
+= r
->phi
->count();
479 s
.loop_phi_count
+= r
->loop_phi
->count();
481 else if (n
->is_depart())
483 else if (n
->is_repeat())
490 void region_node::expand_depart(depart_node
*d
) {
491 depart_vec::iterator I
= departs
.begin() + d
->dep_id
, E
;
492 I
= departs
.erase(I
);
501 void region_node::expand_repeat(repeat_node
*r
) {
502 repeat_vec::iterator I
= repeats
.begin() + r
->rep_id
- 1, E
;
503 I
= repeats
.erase(I
);
512 void node_stats::dump() {
513 sblog
<< " alu_count : " << alu_count
<< "\n";
514 sblog
<< " alu_kill_count : " << alu_kill_count
<< "\n";
515 sblog
<< " alu_copy_mov_count : " << alu_copy_mov_count
<< "\n";
516 sblog
<< " cf_count : " << cf_count
<< "\n";
517 sblog
<< " fetch_count : " << fetch_count
<< "\n";
518 sblog
<< " region_count : " << region_count
<< "\n";
519 sblog
<< " loop_count : " << loop_count
<< "\n";
520 sblog
<< " phi_count : " << phi_count
<< "\n";
521 sblog
<< " loop_phi_count : " << loop_phi_count
<< "\n";
522 sblog
<< " depart_count : " << depart_count
<< "\n";
523 sblog
<< " repeat_count : " << repeat_count
<< "\n";
524 sblog
<< " if_count : " << if_count
<< "\n";
527 unsigned alu_node::interp_param() {
528 if (!(bc
.op_ptr
->flags
& AF_INTERP
))
531 if (bc
.op_ptr
->src_count
== 2) {
532 param
= src
[1]->select
.sel();
534 param
= src
[0]->select
.sel();
539 alu_group_node
* alu_node::get_alu_group_node() {
542 if (p
->subtype
== NST_ALU_PACKED_INST
) {
543 assert(p
->parent
&& p
->parent
->subtype
== NST_ALU_GROUP
);
546 return static_cast<alu_group_node
*>(p
);
551 } // namespace r600_sb