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.
60 sel_chan(unsigned id
= 0) : id(id
) {}
61 sel_chan(unsigned sel
, unsigned chan
) : id(((sel
<< 2) | chan
) + 1) {}
63 unsigned sel() const { return sel(id
); }
64 unsigned chan() const {return chan(id
); }
65 operator unsigned() const {return id
;}
67 static unsigned sel(unsigned idx
) { return (idx
-1) >> 2; }
68 static unsigned chan(unsigned idx
) { return (idx
-1) & 3; }
70 sel_chan(unsigned bank
, unsigned index
,
71 unsigned chan
, alu_kcache_index_mode index_mode
)
72 : id(sel_chan((bank
<< 12) | index
| ((unsigned)index_mode
<< 28), chan
).id
) {}
73 unsigned kcache_index_mode() const { return sel() >> 28; }
74 unsigned kcache_sel() const { return sel() & 0x0fffffffu
; }
75 unsigned kcache_bank() const { return kcache_sel() >> 12; }
78 inline sb_ostream
& operator <<(sb_ostream
& o
, sel_chan r
) {
79 static const char * ch
= "xyzw";
80 o
<< r
.sel() << "." << ch
[r
.chan()];
84 typedef std::vector
<value
*> vvec
;
88 static const unsigned SB_POOL_ALIGN
= 8;
89 static const unsigned SB_POOL_DEFAULT_BLOCK_SIZE
= (1 << 16);
91 typedef std::vector
<void*> block_vector
;
98 sb_pool(unsigned block_size
= SB_POOL_DEFAULT_BLOCK_SIZE
)
99 : block_size(block_size
), blocks(), total_size() {}
101 virtual ~sb_pool() { free_all(); }
103 void* allocate(unsigned sz
);
109 template <typename V
, typename Comp
= std::less
<V
> >
111 typedef std::vector
<V
> data_vector
;
115 typedef typename
data_vector::iterator iterator
;
116 typedef typename
data_vector::const_iterator const_iterator
;
121 iterator
begin() { return vec
.begin(); }
122 iterator
end() { return vec
.end(); }
123 const_iterator
begin() const { return vec
.begin(); }
124 const_iterator
end() const { return vec
.end(); }
126 void add_set(const sb_set
& s
) {
128 t
.reserve(vec
.size() + s
.vec
.size());
129 std::set_union(vec
.begin(), vec
.end(), s
.vec
.begin(), s
.vec
.end(),
130 std::inserter(t
, t
.begin()), Comp());
134 iterator
lower_bound(const V
& v
) {
135 return std::lower_bound(vec
.begin(), vec
.end(), v
, Comp());
138 std::pair
<iterator
, bool> insert(const V
& v
) {
139 iterator P
= lower_bound(v
);
140 if (P
!= vec
.end() && is_equal(*P
, v
))
141 return std::make_pair(P
, false);
142 return std::make_pair(vec
.insert(P
, v
), true);
145 unsigned erase(const V
& v
) {
146 iterator P
= lower_bound(v
);
147 if (P
== vec
.end() || !is_equal(*P
, v
))
153 void clear() { vec
.clear(); }
155 bool empty() { return vec
.empty(); }
157 bool is_equal(const V
& v1
, const V
& v2
) {
158 return !Comp()(v1
, v2
) && !Comp()(v2
, v1
);
161 iterator
find(const V
& v
) {
162 iterator P
= lower_bound(v
);
163 return (P
!= vec
.end() && is_equal(*P
, v
)) ? P
: vec
.end();
166 unsigned size() { return vec
.size(); }
167 void erase(iterator I
) { vec
.erase(I
); }
170 template <typename K
, typename V
, typename KComp
= std::less
<K
> >
172 typedef std::pair
<K
, V
> datatype
;
175 bool operator()(const datatype
&v1
, const datatype
&v2
) {
176 return KComp()(v1
.first
, v2
.first
);
180 typedef sb_set
<datatype
, Comp
> dataset
;
188 typedef typename
dataset::iterator iterator
;
190 iterator
begin() { return set
.begin(); }
191 iterator
end() { return set
.end(); }
193 void clear() { set
.clear(); }
195 V
& operator[](const K
& key
) {
196 datatype P
= std::make_pair(key
, V());
197 iterator F
= set
.find(P
);
198 if (F
== set
.end()) {
199 return (*(set
.insert(P
).first
)).second
;
205 std::pair
<iterator
, bool> insert(const datatype
& d
) {
206 return set
.insert(d
);
209 iterator
find(const K
& key
) {
210 return set
.find(std::make_pair(key
, V()));
213 unsigned erase(const K
& key
) {
214 return set
.erase(std::make_pair(key
, V()));
217 void erase(iterator I
) {
223 typedef uint32_t basetype
;
224 static const unsigned bt_bits
= sizeof(basetype
) << 3;
225 std::vector
<basetype
> data
;
230 sb_bitset() : data(), bit_size() {}
232 bool get(unsigned id
);
233 void set(unsigned id
, bool bit
= true);
234 bool set_chk(unsigned id
, bool bit
= true);
237 void resize(unsigned size
);
239 unsigned size() { return bit_size
; }
241 unsigned find_bit(unsigned start
= 0);
243 void swap(sb_bitset
& bs2
);
245 bool operator==(const sb_bitset
&bs2
);
246 bool operator!=(const sb_bitset
&bs2
) { return !(*this == bs2
); }
248 sb_bitset
& operator|=(const sb_bitset
&bs2
) {
249 if (bit_size
< bs2
.bit_size
) {
250 resize(bs2
.bit_size
);
253 for (unsigned i
= 0, c
= std::min(data
.size(), bs2
.data
.size()); i
< c
;
255 data
[i
] |= bs2
.data
[i
];
260 sb_bitset
& operator&=(const sb_bitset
&bs2
);
261 sb_bitset
& mask(const sb_bitset
&bs2
);
263 friend sb_bitset
operator|(const sb_bitset
&b1
, const sb_bitset
&b2
) {
286 class sb_value_pool
: protected sb_pool
{
287 unsigned aligned_elt_size
;
290 sb_value_pool(unsigned elt_size
, unsigned block_elts
= 256)
291 : sb_pool(block_elts
* (aligned_elt_size
= ((elt_size
+
292 SB_POOL_ALIGN
- 1) & ~(SB_POOL_ALIGN
- 1)))) {}
294 virtual ~sb_value_pool() { delete_all(); }
296 value
* create(value_kind k
, sel_chan regid
, unsigned ver
);
298 value
* operator[](unsigned id
) {
299 unsigned offset
= id
* aligned_elt_size
;
301 if (offset
< block_size
) {
304 block_id
= offset
/ block_size
;
305 offset
= offset
% block_size
;
307 return (value
*)((char*)blocks
[block_id
] + offset
);
310 unsigned size() { return total_size
/ aligned_elt_size
; }
325 sb_value_set() : bs() {}
332 iterator(shader
&sh
, sb_value_set
*s
, unsigned nb
= 0);
335 iterator
& operator++() {
336 if (nb
+ 1 < s
->bs
.size())
337 nb
= s
->bs
.find_bit(nb
+ 1);
342 bool operator !=(const iterator
&i
) {
343 return s
!= i
.s
|| nb
!= i
.nb
;
345 bool operator ==(const iterator
&i
) { return !(*this != i
); }
346 value
* operator *() {
353 iterator
begin(shader
&sh
) {
354 return iterator(sh
, this, bs
.size() ? bs
.find_bit(0) : 0);
356 iterator
end(shader
&sh
) { return iterator(sh
, this, bs
.size()); }
358 bool add_set_checked(sb_value_set
& s2
);
360 void add_set(sb_value_set
& s2
) {
361 if (bs
.size() < s2
.bs
.size())
362 bs
.resize(s2
.bs
.size());
366 void remove_set(sb_value_set
& s2
);
368 bool add_vec(vvec
&vv
);
370 bool add_val(value
*v
);
371 bool contains(value
*v
);
373 bool remove_val(value
*v
);
375 bool remove_vec(vvec
&vv
);
382 typedef sb_value_set val_set
;
385 sel_chan base_gpr
; // original gpr
386 sel_chan gpr
; // assigned by regalloc
389 gpr_array(sel_chan base_gpr
, unsigned array_size
) : base_gpr(base_gpr
),
390 array_size(array_size
) {}
392 unsigned hash() { return (base_gpr
<< 10) * array_size
; }
394 val_set interferences
;
401 typedef std::vector
<gpr_array
*> regarray_vec
;
404 VLF_UNDEF
= (1 << 0),
405 VLF_READONLY
= (1 << 1),
408 VLF_PIN_REG
= (1 << 3),
409 VLF_PIN_CHAN
= (1 << 4),
411 // opposite to alu clause local value - goes through alu clause boundary
412 // (can't use temp gpr, can't recolor in the alu scheduler, etc)
413 VLF_GLOBAL
= (1 << 5),
414 VLF_FIXED
= (1 << 6),
417 VLF_PREALLOC
= (1 << 8)
420 inline value_flags
operator |(value_flags l
, value_flags r
) {
421 return (value_flags
)((unsigned)l
|(unsigned)r
);
423 inline value_flags
operator &(value_flags l
, value_flags r
) {
424 return (value_flags
)((unsigned)l
&(unsigned)r
);
426 inline value_flags
operator ~(value_flags l
) {
427 return (value_flags
)(~(unsigned)l
);
429 inline value_flags
& operator |=(value_flags
&l
, value_flags r
) {
433 inline value_flags
& operator &=(value_flags
&l
, value_flags r
) {
438 sb_ostream
& operator << (sb_ostream
&o
, value
&v
);
440 typedef uint32_t value_hash
;
442 typedef std::list
< node
* > uselist
;
444 enum constraint_kind
{
457 value(unsigned sh_id
, value_kind k
, sel_chan select
, unsigned ver
= 0)
460 version(ver
), select(select
), pin_gpr(select
), gpr(),
461 gvn_source(), ghash(),
462 def(), adef(), uses(), constraint(), chunk(),
463 literal_value(), uid(sh_id
) {}
465 ~value() { delete_uses(); }
467 friend class sb_value_pool
;
489 ra_constraint
*constraint
;
492 literal literal_value
;
494 bool is_const() { return kind
== VLK_CONST
|| kind
== VLK_UNDEF
; }
497 return is_special_reg() && select
== sel_chan(SV_AR_INDEX
, 0);
499 bool is_geometry_emit() {
500 return is_special_reg() && select
== sel_chan(SV_GEOMETRY_EMIT
, 0);
502 bool is_lds_access() {
503 return is_special_reg() && select
== sel_chan(SV_LDS_RW
, 0);
506 return is_special_reg() && (select
== sel_chan(SV_LDS_OQA
, 0) || select
== sel_chan(SV_LDS_OQB
, 0));
510 assert(!(def
&& adef
));
511 return def
? def
: adef
;
516 while (v
->gvn_source
&& v
!= v
->gvn_source
)
517 // FIXME we really shouldn't have such chains
522 return is_special_reg() && select
== sel_chan(SV_SCRATCH
, 0);
525 bool is_float_0_or_1() {
527 return v
->is_const() && (v
->literal_value
== literal(0)
528 || v
->literal_value
== literal(1.0f
));
531 bool is_undef() { return gvalue()->kind
== VLK_UNDEF
; }
534 return (kind
== VLK_REG
|| kind
== VLK_TEMP
);
538 return array
&& is_any_gpr();
541 // scalar gpr, as opposed to element of gpr array
543 return !array
&& is_any_gpr();
546 bool is_special_reg() { return kind
== VLK_SPECIAL_REG
; }
547 bool is_any_reg() { return is_any_gpr() || is_special_reg(); }
548 bool is_kcache() { return kind
== VLK_KCACHE
; }
549 bool is_rel() { return kind
== VLK_REL_REG
; }
550 bool is_readonly() { return flags
& VLF_READONLY
; }
552 bool is_chan_pinned() { return flags
& VLF_PIN_CHAN
; }
553 bool is_reg_pinned() { return flags
& VLF_PIN_REG
; }
564 bool is_dead() { return flags
& VLF_DEAD
; }
566 literal
& get_const_value() {
568 assert(v
->is_const());
569 return v
->literal_value
;
572 // true if needs to be encoded as literal in alu
575 && literal_value
!= literal(0)
576 && literal_value
!= literal(1)
577 && literal_value
!= literal(-1)
578 && literal_value
!= literal(0.5)
579 && literal_value
!= literal(1.0);
582 void add_use(node
*n
);
583 void remove_use(const node
*n
);
586 value_hash
rel_hash();
588 void assign_source(value
*v
) {
589 assert(!gvn_source
|| gvn_source
== this);
590 gvn_source
= v
->gvalue();
593 bool v_equal(value
*v
) { return gvalue() == v
->gvalue(); }
595 unsigned use_count();
598 sel_chan
get_final_gpr() {
599 if (array
&& array
->gpr
) {
600 int reg_offset
= select
.sel() - array
->base_gpr
.sel();
601 if (rel
&& rel
->is_const())
602 reg_offset
+= rel
->get_const_value().i
;
603 return array
->gpr
+ (reg_offset
<< 2);
609 unsigned get_final_chan() {
612 return array
->gpr
.chan();
619 /* Check whether copy-propagation of src into this would create an access
620 * conflict with relative addressing, i.e. an operation that tries to access
621 * array elements with different address register values.
623 bool no_reladdr_conflict_with(value
*src
);
625 val_set interferences
;
632 typedef std::vector
<value
*> vt_item
;
633 typedef std::vector
<vt_item
> vt_table
;
647 value_table(expr_handler
&ex
, unsigned size_bits
= 10)
648 : ex(ex
), size_bits(size_bits
), size(1u << size_bits
),
649 size_mask(size
- 1), hashtable(size
), cnt() {}
653 void add_value(value
* v
);
655 bool expr_equal(value
* l
, value
* r
);
657 unsigned count() { return cnt
; }
659 void get_values(vvec
& v
);
693 NST_LOOP_PHI_CONTAINER
,
701 NF_REG_CONSTRAINT
= (1 << 1),
702 NF_CHAN_CONSTRAINT
= (1 << 2),
703 NF_ALU_4SLOT
= (1 << 3),
704 NF_CONTAINER
= (1 << 4),
706 NF_COPY_MOV
= (1 << 5),
708 NF_DONT_KILL
= (1 << 6),
709 NF_DONT_HOIST
= (1 << 7),
710 NF_DONT_MOVE
= (1 << 8),
712 // for KILLxx - we want to schedule them as early as possible
713 NF_SCHEDULE_EARLY
= (1 << 9),
715 // for ALU_PUSH_BEFORE - when set, replace with PUSH + ALU
716 NF_ALU_STACK_WORKAROUND
= (1 << 10)
719 inline node_flags
operator |(node_flags l
, node_flags r
) {
720 return (node_flags
)((unsigned)l
|(unsigned)r
);
722 inline node_flags
& operator |=(node_flags
&l
, node_flags r
) {
727 inline node_flags
& operator &=(node_flags
&l
, node_flags r
) {
728 l
= (node_flags
)((unsigned)l
& (unsigned)r
);
732 inline node_flags
operator ~(node_flags r
) {
733 return (node_flags
)~(unsigned)r
;
738 unsigned alu_kill_count
;
739 unsigned alu_copy_mov_count
;
741 unsigned fetch_count
;
742 unsigned region_count
;
745 unsigned loop_phi_count
;
746 unsigned depart_count
;
747 unsigned repeat_count
;
751 node_stats() : alu_count(), alu_kill_count(), alu_copy_mov_count(),
752 cf_count(), fetch_count(), region_count(),
753 loop_count(), phi_count(), loop_phi_count(), depart_count(),
754 repeat_count(), if_count(), uses_ar(false) {}
763 class container_node
;
769 node(node_type nt
, node_subtype nst
, node_flags flags
= NF_EMPTY
)
770 : prev(), next(), parent(),
771 type(nt
), subtype(nst
), flags(flags
),
772 pred(), dst(), src() {}
778 container_node
*parent
;
781 node_subtype subtype
;
789 virtual bool is_valid() { return true; }
790 virtual bool accept(vpass
&p
, bool enter
);
792 void insert_before(node
*n
);
793 void insert_after(node
*n
);
794 void replace_with(node
*n
);
797 virtual value_hash
hash() const;
798 value_hash
hash_src() const;
800 virtual bool fold_dispatch(expr_handler
*ex
);
802 bool is_container() { return flags
& NF_CONTAINER
; }
804 bool is_alu_packed() { return subtype
== NST_ALU_PACKED_INST
; }
805 bool is_alu_inst() { return subtype
== NST_ALU_INST
; }
806 bool is_alu_group() { return subtype
== NST_ALU_GROUP
; }
807 bool is_alu_clause() { return subtype
== NST_ALU_CLAUSE
; }
809 bool is_fetch_clause() {
810 return subtype
== NST_TEX_CLAUSE
|| subtype
== NST_VTX_CLAUSE
|| subtype
== NST_GDS_CLAUSE
;
813 bool is_copy() { return subtype
== NST_COPY
; }
814 bool is_copy_mov() { return flags
& NF_COPY_MOV
; }
815 bool is_any_alu() { return is_alu_inst() || is_alu_packed() || is_copy(); }
817 bool is_fetch_inst() { return subtype
== NST_FETCH_INST
; }
818 bool is_cf_inst() { return subtype
== NST_CF_INST
; }
820 bool is_region() { return type
== NT_REGION
; }
821 bool is_depart() { return type
== NT_DEPART
; }
822 bool is_repeat() { return type
== NT_REPEAT
; }
823 bool is_if() { return type
== NT_IF
; }
824 bool is_bb() { return subtype
== NST_BB
; }
826 bool is_phi() { return subtype
== NST_PHI
; }
828 bool is_dead() { return flags
& NF_DEAD
; }
830 bool is_cf_op(unsigned op
);
831 bool is_alu_op(unsigned op
);
832 bool is_fetch_op(unsigned op
);
834 unsigned cf_op_flags();
835 unsigned alu_op_flags();
836 unsigned alu_op_slot_flags();
837 unsigned fetch_op_flags();
842 bool vec_uses_ar(vvec
&vv
) {
843 for (vvec::iterator I
= vv
.begin(), E
= vv
.end(); I
!= E
; ++I
) {
845 if (v
&& v
->rel
&& !v
->rel
->is_const())
852 return vec_uses_ar(dst
) || vec_uses_ar(src
);
855 bool vec_uses_lds_oq(vvec
&vv
) {
856 for (vvec::iterator I
= vv
.begin(), E
= vv
.end(); I
!= E
; ++I
) {
858 if (v
&& v
->is_lds_oq())
864 bool consumes_lds_oq() {
865 return vec_uses_lds_oq(src
);
868 bool produces_lds_oq() {
869 return vec_uses_lds_oq(dst
);
872 region_node
* get_parent_region();
877 class container_node
: public node
{
880 container_node(node_type nt
= NT_LIST
, node_subtype nst
= NST_LIST
,
881 node_flags flags
= NF_EMPTY
)
882 : node(nt
, nst
, flags
| NF_CONTAINER
), first(), last(),
883 live_after(), live_before() {}
894 iterator(node
*pp
= NULL
) : p(pp
) {}
895 iterator
& operator ++() { p
= p
->next
; return *this;}
896 iterator
& operator --() { p
= p
->prev
; return *this;}
897 node
* operator *() { return p
; }
898 node
* operator ->() { return p
; }
899 const iterator
advance(int n
) {
900 if (!n
) return *this;
902 if (n
> 0) while (n
--) ++I
;
903 else while (n
++) --I
;
906 const iterator
operator +(int n
) { return advance(n
); }
907 const iterator
operator -(int n
) { return advance(-n
); }
908 bool operator !=(const iterator
&i
) { return p
!= i
.p
; }
909 bool operator ==(const iterator
&i
) { return p
== i
.p
; }
915 riterator(node
*p
= NULL
) : i(p
) {}
916 riterator
& operator ++() { --i
; return *this;}
917 riterator
& operator --() { ++i
; return *this;}
918 node
* operator *() { return *i
; }
919 node
* operator ->() { return *i
; }
920 bool operator !=(const riterator
&r
) { return i
!= r
.i
; }
921 bool operator ==(const riterator
&r
) { return i
== r
.i
; }
924 iterator
begin() { return first
; }
925 iterator
end() { return NULL
; }
926 riterator
rbegin() { return last
; }
927 riterator
rend() { return NULL
; }
929 bool empty() { assert(first
!= NULL
|| first
== last
); return !first
; }
932 // used with node containers that represent shceduling queues
933 // ignores copies and takes into account alu_packed_node items
934 unsigned real_alu_count();
936 void push_back(node
*n
);
937 void push_front(node
*n
);
939 void insert_node_before(node
*s
, node
*n
);
940 void insert_node_after(node
*s
, node
*n
);
942 void append_from(container_node
*c
);
944 // remove range [b..e) from some container and assign to this container
945 void move(iterator b
, iterator e
);
948 void expand(container_node
*n
);
949 void remove_node(node
*n
);
951 node
*cut(iterator b
, iterator e
);
953 void clear() { first
= last
= NULL
; }
955 virtual bool is_valid() { return true; }
956 virtual bool accept(vpass
&p
, bool enter
);
957 virtual bool fold_dispatch(expr_handler
*ex
);
959 node
* front() { return first
; }
960 node
* back() { return last
; }
962 void collect_stats(node_stats
&s
);
969 typedef container_node::iterator node_iterator
;
970 typedef container_node::riterator node_riterator
;
972 class alu_group_node
: public container_node
{
974 alu_group_node() : container_node(NT_LIST
, NST_ALU_GROUP
), literals() {}
977 std::vector
<literal
> literals
;
979 virtual bool is_valid() { return subtype
== NST_ALU_GROUP
; }
980 virtual bool accept(vpass
&p
, bool enter
);
983 unsigned literal_chan(literal l
) {
984 std::vector
<literal
>::iterator F
=
985 std::find(literals
.begin(), literals
.end(), l
);
986 assert(F
!= literals
.end());
987 return F
- literals
.begin();
993 class cf_node
: public container_node
{
995 cf_node() : container_node(NT_OP
, NST_CF_INST
), jump_target(),
996 jump_after_target() { memset(&bc
, 0, sizeof(bc_cf
)); };
1000 cf_node
*jump_target
;
1001 bool jump_after_target
;
1003 virtual bool is_valid() { return subtype
== NST_CF_INST
; }
1004 virtual bool accept(vpass
&p
, bool enter
);
1005 virtual bool fold_dispatch(expr_handler
*ex
);
1007 void jump(cf_node
*c
) { jump_target
= c
; jump_after_target
= false; }
1008 void jump_after(cf_node
*c
) { jump_target
= c
; jump_after_target
= true; }
1010 friend class shader
;
1013 class alu_node
: public node
{
1015 alu_node() : node(NT_OP
, NST_ALU_INST
) { memset(&bc
, 0, sizeof(bc_alu
)); }
1019 virtual bool is_valid() { return subtype
== NST_ALU_INST
; }
1020 virtual bool accept(vpass
&p
, bool enter
);
1021 virtual bool fold_dispatch(expr_handler
*ex
);
1023 unsigned forced_bank_swizzle() {
1024 return ((bc
.op_ptr
->flags
& AF_INTERP
) && (bc
.slot_flags
== AF_4V
)) ?
1028 // return param index + 1 if instruction references interpolation param,
1030 unsigned interp_param();
1032 alu_group_node
*get_alu_group_node();
1034 friend class shader
;
1037 // for multi-slot instrs - DOT/INTERP/... (maybe useful for 64bit pairs later)
1038 class alu_packed_node
: public container_node
{
1040 alu_packed_node() : container_node(NT_OP
, NST_ALU_PACKED_INST
) {}
1043 const alu_op_info
* op_ptr() {
1044 return static_cast<alu_node
*>(first
)->bc
.op_ptr
;
1046 unsigned op() { return static_cast<alu_node
*>(first
)->bc
.op
; }
1047 void init_args(bool repl
);
1049 virtual bool is_valid() { return subtype
== NST_ALU_PACKED_INST
; }
1050 virtual bool accept(vpass
&p
, bool enter
);
1051 virtual bool fold_dispatch(expr_handler
*ex
);
1053 unsigned get_slot_mask();
1054 void update_packed_items(sb_context
&ctx
);
1056 friend class shader
;
1059 class fetch_node
: public node
{
1061 fetch_node() : node(NT_OP
, NST_FETCH_INST
) { memset(&bc
, 0, sizeof(bc_fetch
)); };
1065 virtual bool is_valid() { return subtype
== NST_FETCH_INST
; }
1066 virtual bool accept(vpass
&p
, bool enter
);
1067 virtual bool fold_dispatch(expr_handler
*ex
);
1069 bool uses_grad() { return bc
.op_ptr
->flags
& FF_USEGRAD
; }
1071 friend class shader
;
1076 class repeat_node
: public container_node
{
1078 repeat_node(region_node
*target
, unsigned id
)
1079 : container_node(NT_REPEAT
, NST_LIST
), target(target
), rep_id(id
) {}
1081 region_node
*target
;
1084 virtual bool accept(vpass
&p
, bool enter
);
1086 friend class shader
;
1089 class depart_node
: public container_node
{
1091 depart_node(region_node
*target
, unsigned id
)
1092 : container_node(NT_DEPART
, NST_LIST
), target(target
), dep_id(id
) {}
1094 region_node
*target
;
1097 virtual bool accept(vpass
&p
, bool enter
);
1099 friend class shader
;
1102 class if_node
: public container_node
{
1104 if_node() : container_node(NT_IF
, NST_LIST
), cond() {};
1106 value
*cond
; // glued to pseudo output (dst[2]) of the PRED_SETxxx
1108 virtual bool accept(vpass
&p
, bool enter
);
1110 friend class shader
;
1113 typedef std::vector
<depart_node
*> depart_vec
;
1114 typedef std::vector
<repeat_node
*> repeat_vec
;
1116 class region_node
: public container_node
{
1118 region_node(unsigned id
) : container_node(NT_REGION
, NST_LIST
), region_id(id
),
1119 loop_phi(), phi(), vars_defined(), departs(), repeats(), src_loop()
1124 container_node
*loop_phi
;
1125 container_node
*phi
;
1127 val_set vars_defined
;
1132 // true if region was created for loop in the parser, sometimes repeat_node
1133 // may be optimized away so we need to remember this information
1136 virtual bool accept(vpass
&p
, bool enter
);
1138 unsigned dep_count() { return departs
.size(); }
1139 unsigned rep_count() { return repeats
.size() + 1; }
1141 bool is_loop() { return src_loop
|| !repeats
.empty(); }
1143 container_node
* get_entry_code_location() {
1145 while (p
&& (p
->is_depart() || p
->is_repeat()))
1146 p
= static_cast<container_node
*>(p
)->first
;
1148 container_node
*c
= static_cast<container_node
*>(p
);
1155 void expand_depart(depart_node
*d
);
1156 void expand_repeat(repeat_node
*r
);
1158 friend class shader
;
1161 class bb_node
: public container_node
{
1163 bb_node(unsigned id
, unsigned loop_level
)
1164 : container_node(NT_LIST
, NST_BB
), id(id
), loop_level(loop_level
) {}
1167 unsigned loop_level
;
1169 virtual bool accept(vpass
&p
, bool enter
);
1171 friend class shader
;
1175 typedef std::vector
<region_node
*> regions_vec
;
1176 typedef std::vector
<bb_node
*> bbs_vec
;
1177 typedef std::list
<node
*> sched_queue
;
1178 typedef sched_queue::iterator sq_iterator
;
1179 typedef std::vector
<node
*> node_vec
;
1180 typedef std::list
<node
*> node_list
;
1181 typedef std::set
<node
*> node_set
;
1185 } // namespace r600_sb
1187 #endif /* R600_SB_IR_H_ */