c612e6c4ec69978c1944bc7d129a103480f48de6
[mesa.git] / src / gallium / drivers / r600 / sb / sb_ir.h
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 #ifndef R600_SB_IR_H_
28 #define R600_SB_IR_H_
29
30 #include <algorithm>
31 #include <stdint.h>
32 #include <vector>
33 #include <set>
34 #include <algorithm>
35
36 #include "sb_bc.h"
37
38 namespace r600_sb {
39
40 enum special_regs {
41 SV_ALU_PRED = 128,
42 SV_EXEC_MASK,
43 SV_AR_INDEX,
44 SV_VALID_MASK,
45 SV_GEOMETRY_EMIT
46 };
47
48 class node;
49 class value;
50 class shader;
51
52 struct sel_chan
53 {
54 unsigned id;
55
56 sel_chan(unsigned id = 0) : id(id) {}
57 sel_chan(unsigned sel, unsigned chan) : id(((sel << 2) | chan) + 1) {}
58
59 unsigned sel() const { return sel(id); }
60 unsigned chan() const {return chan(id); }
61 operator unsigned() const {return id;}
62
63 static unsigned sel(unsigned idx) { return (idx-1) >> 2; }
64 static unsigned chan(unsigned idx) { return (idx-1) & 3; }
65
66 sel_chan(unsigned bank, unsigned index,
67 unsigned chan, alu_kcache_index_mode index_mode)
68 : id(sel_chan((bank << 12) | index | ((unsigned)index_mode << 28), chan).id) {}
69 unsigned kcache_index_mode() const { return sel() >> 28; }
70 unsigned kcache_sel() const { return sel() & 0x0fffffffu; }
71 unsigned kcache_bank() const { return kcache_sel() >> 12; }
72 };
73
74 inline sb_ostream& operator <<(sb_ostream& o, sel_chan r) {
75 static const char * ch = "xyzw";
76 o << r.sel() << "." << ch[r.chan()];
77 return o;
78 }
79
80 typedef std::vector<value*> vvec;
81
82 class sb_pool {
83 protected:
84 static const unsigned SB_POOL_ALIGN = 8;
85 static const unsigned SB_POOL_DEFAULT_BLOCK_SIZE = (1 << 16);
86
87 typedef std::vector<void*> block_vector;
88
89 unsigned block_size;
90 block_vector blocks;
91 unsigned total_size;
92
93 public:
94 sb_pool(unsigned block_size = SB_POOL_DEFAULT_BLOCK_SIZE)
95 : block_size(block_size), blocks(), total_size() {}
96
97 virtual ~sb_pool() { free_all(); }
98
99 void* allocate(unsigned sz);
100
101 protected:
102 void free_all();
103 };
104
105 template <typename V, typename Comp = std::less<V> >
106 class sb_set {
107 typedef std::vector<V> data_vector;
108 data_vector vec;
109 public:
110
111 typedef typename data_vector::iterator iterator;
112 typedef typename data_vector::const_iterator const_iterator;
113
114 sb_set() : vec() {}
115 ~sb_set() { }
116
117 iterator begin() { return vec.begin(); }
118 iterator end() { return vec.end(); }
119 const_iterator begin() const { return vec.begin(); }
120 const_iterator end() const { return vec.end(); }
121
122 void add_set(const sb_set& s) {
123 data_vector t;
124 t.reserve(vec.size() + s.vec.size());
125 std::set_union(vec.begin(), vec.end(), s.vec.begin(), s.vec.end(),
126 std::inserter(t, t.begin()), Comp());
127 vec.swap(t);
128 }
129
130 iterator lower_bound(const V& v) {
131 return std::lower_bound(vec.begin(), vec.end(), v, Comp());
132 }
133
134 std::pair<iterator, bool> insert(const V& v) {
135 iterator P = lower_bound(v);
136 if (P != vec.end() && is_equal(*P, v))
137 return std::make_pair(P, false);
138 return std::make_pair(vec.insert(P, v), true);
139 }
140
141 unsigned erase(const V& v) {
142 iterator P = lower_bound(v);
143 if (P == vec.end() || !is_equal(*P, v))
144 return 0;
145 vec.erase(P);
146 return 1;
147 }
148
149 void clear() { vec.clear(); }
150
151 bool empty() { return vec.empty(); }
152
153 bool is_equal(const V& v1, const V& v2) {
154 return !Comp()(v1, v2) && !Comp()(v2, v1);
155 }
156
157 iterator find(const V& v) {
158 iterator P = lower_bound(v);
159 return (P != vec.end() && is_equal(*P, v)) ? P : vec.end();
160 }
161
162 unsigned size() { return vec.size(); }
163 void erase(iterator I) { vec.erase(I); }
164 };
165
166 template <typename K, typename V, typename KComp = std::less<K> >
167 class sb_map {
168 typedef std::pair<K, V> datatype;
169
170 struct Comp {
171 bool operator()(const datatype &v1, const datatype &v2) {
172 return KComp()(v1.first, v2.first);
173 }
174 };
175
176 typedef sb_set<datatype, Comp> dataset;
177
178 dataset set;
179
180 public:
181
182 sb_map() : set() {}
183
184 typedef typename dataset::iterator iterator;
185
186 iterator begin() { return set.begin(); }
187 iterator end() { return set.end(); }
188
189 void clear() { set.clear(); }
190
191 V& operator[](const K& key) {
192 datatype P = std::make_pair(key, V());
193 iterator F = set.find(P);
194 if (F == set.end()) {
195 return (*(set.insert(P).first)).second;
196 } else {
197 return (*F).second;
198 }
199 }
200
201 std::pair<iterator, bool> insert(const datatype& d) {
202 return set.insert(d);
203 }
204
205 iterator find(const K& key) {
206 return set.find(std::make_pair(key, V()));
207 }
208
209 unsigned erase(const K& key) {
210 return set.erase(std::make_pair(key, V()));
211 }
212
213 void erase(iterator I) {
214 set.erase(I);
215 }
216 };
217
218 class sb_bitset {
219 typedef uint32_t basetype;
220 static const unsigned bt_bits = sizeof(basetype) << 3;
221 std::vector<basetype> data;
222 unsigned bit_size;
223
224 public:
225
226 sb_bitset() : data(), bit_size() {}
227
228 bool get(unsigned id);
229 void set(unsigned id, bool bit = true);
230 bool set_chk(unsigned id, bool bit = true);
231
232 void clear();
233 void resize(unsigned size);
234
235 unsigned size() { return bit_size; }
236
237 unsigned find_bit(unsigned start = 0);
238
239 void swap(sb_bitset & bs2);
240
241 bool operator==(const sb_bitset &bs2);
242 bool operator!=(const sb_bitset &bs2) { return !(*this == bs2); }
243
244 sb_bitset& operator|=(const sb_bitset &bs2) {
245 if (bit_size < bs2.bit_size) {
246 resize(bs2.bit_size);
247 }
248
249 for (unsigned i = 0, c = std::min(data.size(), bs2.data.size()); i < c;
250 ++i) {
251 data[i] |= bs2.data[i];
252 }
253 return *this;
254 }
255
256 sb_bitset& operator&=(const sb_bitset &bs2);
257 sb_bitset& mask(const sb_bitset &bs2);
258
259 friend sb_bitset operator|(const sb_bitset &b1, const sb_bitset &b2) {
260 sb_bitset nbs(b1);
261 nbs |= b2;
262 return nbs;
263 }
264 };
265
266 class value;
267
268 enum value_kind {
269 VLK_REG,
270 VLK_REL_REG,
271 VLK_SPECIAL_REG,
272 VLK_TEMP,
273
274 VLK_CONST,
275 VLK_KCACHE,
276 VLK_PARAM,
277 VLK_SPECIAL_CONST,
278
279 VLK_UNDEF
280 };
281
282
283
284 class sb_value_pool : protected sb_pool {
285 unsigned aligned_elt_size;
286
287 public:
288 sb_value_pool(unsigned elt_size, unsigned block_elts = 256)
289 : sb_pool(block_elts * (aligned_elt_size = ((elt_size +
290 SB_POOL_ALIGN - 1) & ~(SB_POOL_ALIGN - 1)))) {}
291
292 virtual ~sb_value_pool() { delete_all(); }
293
294 value* create(value_kind k, sel_chan regid, unsigned ver);
295
296 value* operator[](unsigned id) {
297 unsigned offset = id * aligned_elt_size;
298 unsigned block_id;
299 if (offset < block_size) {
300 block_id = 0;
301 } else {
302 block_id = offset / block_size;
303 offset = offset % block_size;
304 }
305 return (value*)((char*)blocks[block_id] + offset);
306 }
307
308 unsigned size() { return total_size / aligned_elt_size; }
309
310 protected:
311 void delete_all();
312 };
313
314
315
316
317
318 class sb_value_set {
319
320 sb_bitset bs;
321
322 public:
323 sb_value_set() : bs() {}
324
325 class iterator {
326 sb_value_pool &vp;
327 sb_value_set *s;
328 unsigned nb;
329 public:
330 iterator(shader &sh, sb_value_set *s, unsigned nb = 0);
331
332
333 iterator& operator++() {
334 if (nb + 1 < s->bs.size())
335 nb = s->bs.find_bit(nb + 1);
336 else
337 nb = s->bs.size();
338 return *this;
339 }
340 bool operator !=(const iterator &i) {
341 return s != i.s || nb != i.nb;
342 }
343 bool operator ==(const iterator &i) { return !(*this != i); }
344 value* operator *() {
345 return vp[nb];
346 }
347
348
349 };
350
351 iterator begin(shader &sh) {
352 return iterator(sh, this, bs.size() ? bs.find_bit(0) : 0);
353 }
354 iterator end(shader &sh) { return iterator(sh, this, bs.size()); }
355
356 bool add_set_checked(sb_value_set & s2);
357
358 void add_set(sb_value_set & s2) {
359 if (bs.size() < s2.bs.size())
360 bs.resize(s2.bs.size());
361 bs |= s2.bs;
362 }
363
364 void remove_set(sb_value_set & s2);
365
366 bool add_vec(vvec &vv);
367
368 bool add_val(value *v);
369 bool contains(value *v);
370
371 bool remove_val(value *v);
372
373 bool remove_vec(vvec &vv);
374
375 void clear();
376
377 bool empty();
378 };
379
380 typedef sb_value_set val_set;
381
382 struct gpr_array {
383 sel_chan base_gpr; // original gpr
384 sel_chan gpr; // assigned by regalloc
385 unsigned array_size;
386
387 gpr_array(sel_chan base_gpr, unsigned array_size) : base_gpr(base_gpr),
388 array_size(array_size) {}
389
390 unsigned hash() { return (base_gpr << 10) * array_size; }
391
392 val_set interferences;
393 vvec refs;
394
395 bool is_dead();
396
397 };
398
399 typedef std::vector<gpr_array*> regarray_vec;
400
401 enum value_flags {
402 VLF_UNDEF = (1 << 0),
403 VLF_READONLY = (1 << 1),
404 VLF_DEAD = (1 << 2),
405
406 VLF_PIN_REG = (1 << 3),
407 VLF_PIN_CHAN = (1 << 4),
408
409 // opposite to alu clause local value - goes through alu clause boundary
410 // (can't use temp gpr, can't recolor in the alu scheduler, etc)
411 VLF_GLOBAL = (1 << 5),
412 VLF_FIXED = (1 << 6),
413 VLF_PVPS = (1 << 7),
414
415 VLF_PREALLOC = (1 << 8)
416 };
417
418 inline value_flags operator |(value_flags l, value_flags r) {
419 return (value_flags)((unsigned)l|(unsigned)r);
420 }
421 inline value_flags operator &(value_flags l, value_flags r) {
422 return (value_flags)((unsigned)l&(unsigned)r);
423 }
424 inline value_flags operator ~(value_flags l) {
425 return (value_flags)(~(unsigned)l);
426 }
427 inline value_flags& operator |=(value_flags &l, value_flags r) {
428 l = l | r;
429 return l;
430 }
431 inline value_flags& operator &=(value_flags &l, value_flags r) {
432 l = l & r;
433 return l;
434 }
435
436 struct value;
437
438 sb_ostream& operator << (sb_ostream &o, value &v);
439
440 typedef uint32_t value_hash;
441
442 enum use_kind {
443 UK_SRC,
444 UK_SRC_REL,
445 UK_DST_REL,
446 UK_MAYDEF,
447 UK_MAYUSE,
448 UK_PRED,
449 UK_COND
450 };
451
452 struct use_info {
453 use_info *next;
454 node *op;
455 use_kind kind;
456 int arg;
457
458 use_info(node *n, use_kind kind, int arg, use_info* next)
459 : next(next), op(n), kind(kind), arg(arg) {}
460 };
461
462 enum constraint_kind {
463 CK_SAME_REG,
464 CK_PACKED_BS,
465 CK_PHI
466 };
467
468 class shader;
469 class sb_value_pool;
470 class ra_chunk;
471 class ra_constraint;
472
473 class value {
474 protected:
475 value(unsigned sh_id, value_kind k, sel_chan select, unsigned ver = 0)
476 : kind(k), flags(),
477 rel(), array(),
478 version(ver), select(select), pin_gpr(select), gpr(),
479 gvn_source(), ghash(),
480 def(), adef(), uses(), constraint(), chunk(),
481 literal_value(), uid(sh_id) {}
482
483 ~value() { delete_uses(); }
484
485 friend class sb_value_pool;
486 public:
487 value_kind kind;
488 value_flags flags;
489
490 vvec mdef;
491 vvec muse;
492 value *rel;
493 gpr_array *array;
494
495 unsigned version;
496
497 sel_chan select;
498 sel_chan pin_gpr;
499 sel_chan gpr;
500
501 value *gvn_source;
502 value_hash ghash;
503
504 node *def, *adef;
505 use_info *uses;
506
507 ra_constraint *constraint;
508 ra_chunk *chunk;
509
510 literal literal_value;
511
512 bool is_const() { return kind == VLK_CONST || kind == VLK_UNDEF; }
513
514 bool is_AR() {
515 return is_special_reg() && select == sel_chan(SV_AR_INDEX, 0);
516 }
517 bool is_geometry_emit() {
518 return is_special_reg() && select == sel_chan(SV_GEOMETRY_EMIT, 0);
519 }
520
521 node* any_def() {
522 assert(!(def && adef));
523 return def ? def : adef;
524 }
525
526 value* gvalue() {
527 value *v = this;
528 while (v->gvn_source && v != v->gvn_source)
529 // FIXME we really shouldn't have such chains
530 v = v->gvn_source;
531 return v;
532 }
533
534 bool is_float_0_or_1() {
535 value *v = gvalue();
536 return v->is_const() && (v->literal_value == literal(0)
537 || v->literal_value == literal(1.0f));
538 }
539
540 bool is_undef() { return gvalue()->kind == VLK_UNDEF; }
541
542 bool is_any_gpr() {
543 return (kind == VLK_REG || kind == VLK_TEMP);
544 }
545
546 bool is_agpr() {
547 return array && is_any_gpr();
548 }
549
550 // scalar gpr, as opposed to element of gpr array
551 bool is_sgpr() {
552 return !array && is_any_gpr();
553 }
554
555 bool is_special_reg() { return kind == VLK_SPECIAL_REG; }
556 bool is_any_reg() { return is_any_gpr() || is_special_reg(); }
557 bool is_kcache() { return kind == VLK_KCACHE; }
558 bool is_rel() { return kind == VLK_REL_REG; }
559 bool is_readonly() { return flags & VLF_READONLY; }
560
561 bool is_chan_pinned() { return flags & VLF_PIN_CHAN; }
562 bool is_reg_pinned() { return flags & VLF_PIN_REG; }
563
564 bool is_global();
565 void set_global();
566 void set_prealloc();
567
568 bool is_prealloc();
569
570 bool is_fixed();
571 void fix();
572
573 bool is_dead() { return flags & VLF_DEAD; }
574
575 literal & get_const_value() {
576 value *v = gvalue();
577 assert(v->is_const());
578 return v->literal_value;
579 }
580
581 // true if needs to be encoded as literal in alu
582 bool is_literal() {
583 return is_const()
584 && literal_value != literal(0)
585 && literal_value != literal(1)
586 && literal_value != literal(-1)
587 && literal_value != literal(0.5)
588 && literal_value != literal(1.0);
589 }
590
591 void add_use(node *n, use_kind kind, int arg);
592
593 value_hash hash();
594 value_hash rel_hash();
595
596 void assign_source(value *v) {
597 assert(!gvn_source || gvn_source == this);
598 gvn_source = v->gvalue();
599 }
600
601 bool v_equal(value *v) { return gvalue() == v->gvalue(); }
602
603 unsigned use_count();
604 void delete_uses();
605
606 sel_chan get_final_gpr() {
607 if (array && array->gpr) {
608 int reg_offset = select.sel() - array->base_gpr.sel();
609 if (rel && rel->is_const())
610 reg_offset += rel->get_const_value().i;
611 return array->gpr + (reg_offset << 2);
612 } else {
613 return gpr;
614 }
615 }
616
617 unsigned get_final_chan() {
618 if (array) {
619 assert(array->gpr);
620 return array->gpr.chan();
621 } else {
622 assert(gpr);
623 return gpr.chan();
624 }
625 }
626
627 val_set interferences;
628 unsigned uid;
629 };
630
631 class expr_handler;
632
633 class value_table {
634 typedef std::vector<value*> vt_item;
635 typedef std::vector<vt_item> vt_table;
636
637 expr_handler &ex;
638
639 unsigned size_bits;
640 unsigned size;
641 unsigned size_mask;
642
643 vt_table hashtable;
644
645 unsigned cnt;
646
647 public:
648
649 value_table(expr_handler &ex, unsigned size_bits = 10)
650 : ex(ex), size_bits(size_bits), size(1u << size_bits),
651 size_mask(size - 1), hashtable(size), cnt() {}
652
653 ~value_table() {}
654
655 void add_value(value* v);
656
657 bool expr_equal(value* l, value* r);
658
659 unsigned count() { return cnt; }
660
661 void get_values(vvec & v);
662 };
663
664 class sb_context;
665
666 enum node_type {
667 NT_UNKNOWN,
668 NT_LIST,
669 NT_OP,
670 NT_REGION,
671 NT_REPEAT,
672 NT_DEPART,
673 NT_IF,
674 };
675
676 enum node_subtype {
677 NST_UNKNOWN,
678 NST_LIST,
679 NST_ALU_GROUP,
680 NST_ALU_CLAUSE,
681 NST_ALU_INST,
682 NST_ALU_PACKED_INST,
683 NST_CF_INST,
684 NST_FETCH_INST,
685 NST_TEX_CLAUSE,
686 NST_VTX_CLAUSE,
687
688 NST_BB,
689
690 NST_PHI,
691 NST_PSI,
692 NST_COPY,
693
694 NST_LOOP_PHI_CONTAINER,
695 NST_LOOP_CONTINUE,
696 NST_LOOP_BREAK
697 };
698
699 enum node_flags {
700 NF_EMPTY = 0,
701 NF_DEAD = (1 << 0),
702 NF_REG_CONSTRAINT = (1 << 1),
703 NF_CHAN_CONSTRAINT = (1 << 2),
704 NF_ALU_4SLOT = (1 << 3),
705 NF_CONTAINER = (1 << 4),
706
707 NF_COPY_MOV = (1 << 5),
708
709 NF_DONT_KILL = (1 << 6),
710 NF_DONT_HOIST = (1 << 7),
711 NF_DONT_MOVE = (1 << 8),
712
713 // for KILLxx - we want to schedule them as early as possible
714 NF_SCHEDULE_EARLY = (1 << 9),
715
716 // for ALU_PUSH_BEFORE - when set, replace with PUSH + ALU
717 NF_ALU_STACK_WORKAROUND = (1 << 10)
718 };
719
720 inline node_flags operator |(node_flags l, node_flags r) {
721 return (node_flags)((unsigned)l|(unsigned)r);
722 }
723 inline node_flags& operator |=(node_flags &l, node_flags r) {
724 l = l | r;
725 return l;
726 }
727
728 inline node_flags& operator &=(node_flags &l, node_flags r) {
729 l = (node_flags)((unsigned)l & (unsigned)r);
730 return l;
731 }
732
733 inline node_flags operator ~(node_flags r) {
734 return (node_flags)~(unsigned)r;
735 }
736
737 struct node_stats {
738 unsigned alu_count;
739 unsigned alu_kill_count;
740 unsigned alu_copy_mov_count;
741 unsigned cf_count;
742 unsigned fetch_count;
743 unsigned region_count;
744 unsigned loop_count;
745 unsigned phi_count;
746 unsigned loop_phi_count;
747 unsigned depart_count;
748 unsigned repeat_count;
749 unsigned if_count;
750
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() {}
755
756 void dump();
757 };
758
759 class shader;
760
761 class vpass;
762
763 class container_node;
764 class region_node;
765
766 class node {
767
768 protected:
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() {}
773
774 virtual ~node() {};
775
776 public:
777 node *prev, *next;
778 container_node *parent;
779
780 node_type type;
781 node_subtype subtype;
782 node_flags flags;
783
784 value *pred;
785
786 vvec dst;
787 vvec src;
788
789 virtual bool is_valid() { return true; }
790 virtual bool accept(vpass &p, bool enter);
791
792 void insert_before(node *n);
793 void insert_after(node *n);
794 void replace_with(node *n);
795 void remove();
796
797 virtual value_hash hash();
798 value_hash hash_src();
799
800 virtual bool fold_dispatch(expr_handler *ex);
801
802 bool is_container() { return flags & NF_CONTAINER; }
803
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; }
808
809 bool is_fetch_clause() {
810 return subtype == NST_TEX_CLAUSE || subtype == NST_VTX_CLAUSE;
811 }
812
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(); }
816
817 bool is_fetch_inst() { return subtype == NST_FETCH_INST; }
818 bool is_cf_inst() { return subtype == NST_CF_INST; }
819
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; }
825
826 bool is_phi() { return subtype == NST_PHI; }
827
828 bool is_dead() { return flags & NF_DEAD; }
829
830 bool is_cf_op(unsigned op);
831 bool is_alu_op(unsigned op);
832 bool is_fetch_op(unsigned op);
833
834 unsigned cf_op_flags();
835 unsigned alu_op_flags();
836 unsigned alu_op_slot_flags();
837 unsigned fetch_op_flags();
838
839 bool is_mova();
840 bool is_pred_set();
841
842 bool vec_uses_ar(vvec &vv) {
843 for (vvec::iterator I = vv.begin(), E = vv.end(); I != E; ++I) {
844 value *v = *I;
845 if (v && v->rel && !v->rel->is_const())
846 return true;
847 }
848 return false;
849 }
850
851 bool uses_ar() {
852 return vec_uses_ar(dst) || vec_uses_ar(src);
853 }
854
855
856 region_node* get_parent_region();
857
858 friend class shader;
859 };
860
861 class container_node : public node {
862 public:
863
864 container_node(node_type nt = NT_LIST, node_subtype nst = NST_LIST,
865 node_flags flags = NF_EMPTY)
866 : node(nt, nst, flags | NF_CONTAINER), first(), last(),
867 live_after(), live_before() {}
868
869 // child items list
870 node *first, *last;
871
872 val_set live_after;
873 val_set live_before;
874
875 class iterator {
876 node *p;
877 public:
878 iterator(node *pp = NULL) : p(pp) {}
879 iterator & operator ++() { p = p->next; return *this;}
880 iterator & operator --() { p = p->prev; return *this;}
881 node* operator *() { return p; }
882 node* operator ->() { return p; }
883 const iterator advance(int n) {
884 if (!n) return *this;
885 iterator I(p);
886 if (n > 0) while (n--) ++I;
887 else while (n++) --I;
888 return I;
889 }
890 const iterator operator +(int n) { return advance(n); }
891 const iterator operator -(int n) { return advance(-n); }
892 bool operator !=(const iterator &i) { return p != i.p; }
893 bool operator ==(const iterator &i) { return p == i.p; }
894 };
895
896 class riterator {
897 iterator i;
898 public:
899 riterator(node *p = NULL) : i(p) {}
900 riterator & operator ++() { --i; return *this;}
901 riterator & operator --() { ++i; return *this;}
902 node* operator *() { return *i; }
903 node* operator ->() { return *i; }
904 bool operator !=(const riterator &r) { return i != r.i; }
905 bool operator ==(const riterator &r) { return i == r.i; }
906 };
907
908 iterator begin() { return first; }
909 iterator end() { return NULL; }
910 riterator rbegin() { return last; }
911 riterator rend() { return NULL; }
912
913 bool empty() { assert(first != NULL || first == last); return !first; }
914 unsigned count();
915
916 // used with node containers that represent shceduling queues
917 // ignores copies and takes into account alu_packed_node items
918 unsigned real_alu_count();
919
920 void push_back(node *n);
921 void push_front(node *n);
922
923 void insert_node_before(node *s, node *n);
924 void insert_node_after(node *s, node *n);
925
926 void append_from(container_node *c);
927
928 // remove range [b..e) from some container and assign to this container
929 void move(iterator b, iterator e);
930
931 void expand();
932 void expand(container_node *n);
933 void remove_node(node *n);
934
935 node *cut(iterator b, iterator e);
936
937 void clear() { first = last = NULL; }
938
939 virtual bool is_valid() { return true; }
940 virtual bool accept(vpass &p, bool enter);
941 virtual bool fold_dispatch(expr_handler *ex);
942
943 node* front() { return first; }
944 node* back() { return last; }
945
946 void collect_stats(node_stats &s);
947
948 friend class shader;
949
950
951 };
952
953 typedef container_node::iterator node_iterator;
954 typedef container_node::riterator node_riterator;
955
956 class alu_group_node : public container_node {
957 protected:
958 alu_group_node() : container_node(NT_LIST, NST_ALU_GROUP), literals() {}
959 public:
960
961 std::vector<literal> literals;
962
963 virtual bool is_valid() { return subtype == NST_ALU_GROUP; }
964 virtual bool accept(vpass &p, bool enter);
965
966
967 unsigned literal_chan(literal l) {
968 std::vector<literal>::iterator F =
969 std::find(literals.begin(), literals.end(), l);
970 assert(F != literals.end());
971 return F - literals.begin();
972 }
973
974 friend class shader;
975 };
976
977 class cf_node : public container_node {
978 protected:
979 cf_node() : container_node(NT_OP, NST_CF_INST), jump_target(),
980 jump_after_target() { memset(&bc, 0, sizeof(bc_cf)); };
981 public:
982 bc_cf bc;
983
984 cf_node *jump_target;
985 bool jump_after_target;
986
987 virtual bool is_valid() { return subtype == NST_CF_INST; }
988 virtual bool accept(vpass &p, bool enter);
989 virtual bool fold_dispatch(expr_handler *ex);
990
991 void jump(cf_node *c) { jump_target = c; jump_after_target = false; }
992 void jump_after(cf_node *c) { jump_target = c; jump_after_target = true; }
993
994 friend class shader;
995 };
996
997 class alu_node : public node {
998 protected:
999 alu_node() : node(NT_OP, NST_ALU_INST) { memset(&bc, 0, sizeof(bc_alu)); };
1000 public:
1001 bc_alu bc;
1002
1003 virtual bool is_valid() { return subtype == NST_ALU_INST; }
1004 virtual bool accept(vpass &p, bool enter);
1005 virtual bool fold_dispatch(expr_handler *ex);
1006
1007 unsigned forced_bank_swizzle() {
1008 return ((bc.op_ptr->flags & AF_INTERP) && (bc.slot_flags == AF_4V)) ?
1009 VEC_210 : 0;
1010 }
1011
1012 // return param index + 1 if instruction references interpolation param,
1013 // otherwise 0
1014 unsigned interp_param();
1015
1016 alu_group_node *get_alu_group_node();
1017
1018 friend class shader;
1019 };
1020
1021 // for multi-slot instrs - DOT/INTERP/... (maybe useful for 64bit pairs later)
1022 class alu_packed_node : public container_node {
1023 protected:
1024 alu_packed_node() : container_node(NT_OP, NST_ALU_PACKED_INST) {}
1025 public:
1026
1027 const alu_op_info* op_ptr() {
1028 return static_cast<alu_node*>(first)->bc.op_ptr;
1029 }
1030 unsigned op() { return static_cast<alu_node*>(first)->bc.op; }
1031 void init_args(bool repl);
1032
1033 virtual bool is_valid() { return subtype == NST_ALU_PACKED_INST; }
1034 virtual bool accept(vpass &p, bool enter);
1035 virtual bool fold_dispatch(expr_handler *ex);
1036
1037 unsigned get_slot_mask();
1038 void update_packed_items(sb_context &ctx);
1039
1040 friend class shader;
1041 };
1042
1043 class fetch_node : public node {
1044 protected:
1045 fetch_node() : node(NT_OP, NST_FETCH_INST) { memset(&bc, 0, sizeof(bc_fetch)); };
1046 public:
1047 bc_fetch bc;
1048
1049 virtual bool is_valid() { return subtype == NST_FETCH_INST; }
1050 virtual bool accept(vpass &p, bool enter);
1051 virtual bool fold_dispatch(expr_handler *ex);
1052
1053 bool uses_grad() { return bc.op_ptr->flags & FF_USEGRAD; }
1054
1055 friend class shader;
1056 };
1057
1058 class region_node;
1059
1060 class repeat_node : public container_node {
1061 protected:
1062 repeat_node(region_node *target, unsigned id)
1063 : container_node(NT_REPEAT, NST_LIST), target(target), rep_id(id) {}
1064 public:
1065 region_node *target;
1066 unsigned rep_id;
1067
1068 virtual bool accept(vpass &p, bool enter);
1069
1070 friend class shader;
1071 };
1072
1073 class depart_node : public container_node {
1074 protected:
1075 depart_node(region_node *target, unsigned id)
1076 : container_node(NT_DEPART, NST_LIST), target(target), dep_id(id) {}
1077 public:
1078 region_node *target;
1079 unsigned dep_id;
1080
1081 virtual bool accept(vpass &p, bool enter);
1082
1083 friend class shader;
1084 };
1085
1086 class if_node : public container_node {
1087 protected:
1088 if_node() : container_node(NT_IF, NST_LIST), cond() {};
1089 public:
1090 value *cond; // glued to pseudo output (dst[2]) of the PRED_SETxxx
1091
1092 virtual bool accept(vpass &p, bool enter);
1093
1094 friend class shader;
1095 };
1096
1097 typedef std::vector<depart_node*> depart_vec;
1098 typedef std::vector<repeat_node*> repeat_vec;
1099
1100 class region_node : public container_node {
1101 protected:
1102 region_node(unsigned id) : container_node(NT_REGION, NST_LIST), region_id(id),
1103 loop_phi(), phi(), vars_defined(), departs(), repeats(), src_loop()
1104 {}
1105 public:
1106 unsigned region_id;
1107
1108 container_node *loop_phi;
1109 container_node *phi;
1110
1111 val_set vars_defined;
1112
1113 depart_vec departs;
1114 repeat_vec repeats;
1115
1116 // true if region was created for loop in the parser, sometimes repeat_node
1117 // may be optimized away so we need to remember this information
1118 bool src_loop;
1119
1120 virtual bool accept(vpass &p, bool enter);
1121
1122 unsigned dep_count() { return departs.size(); }
1123 unsigned rep_count() { return repeats.size() + 1; }
1124
1125 bool is_loop() { return src_loop || !repeats.empty(); }
1126
1127 container_node* get_entry_code_location() {
1128 node *p = first;
1129 while (p && (p->is_depart() || p->is_repeat()))
1130 p = static_cast<container_node*>(p)->first;
1131
1132 container_node *c = static_cast<container_node*>(p);
1133 if (c->is_bb())
1134 return c;
1135 else
1136 return c->parent;
1137 }
1138
1139 void expand_depart(depart_node *d);
1140 void expand_repeat(repeat_node *r);
1141
1142 friend class shader;
1143 };
1144
1145 class bb_node : public container_node {
1146 protected:
1147 bb_node(unsigned id, unsigned loop_level)
1148 : container_node(NT_LIST, NST_BB), id(id), loop_level(loop_level) {}
1149 public:
1150 unsigned id;
1151 unsigned loop_level;
1152
1153 virtual bool accept(vpass &p, bool enter);
1154
1155 friend class shader;
1156 };
1157
1158
1159 typedef std::vector<region_node*> regions_vec;
1160 typedef std::vector<bb_node*> bbs_vec;
1161 typedef std::list<node*> sched_queue;
1162 typedef sched_queue::iterator sq_iterator;
1163 typedef std::vector<node*> node_vec;
1164 typedef std::list<node*> node_list;
1165 typedef std::set<node*> node_set;
1166
1167
1168
1169 } // namespace r600_sb
1170
1171 #endif /* R600_SB_IR_H_ */