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