Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/*
2
 * Copyright 2013 Vadim Girlin 
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 
31
#include 
32
#include 
33
#include 
34
#include 
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  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 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  >
98
class sb_set {
99
	typedef std::vector 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 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  >
159
class sb_map {
160
	typedef std::pair 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 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 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 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 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 vt_item;
624
	typedef std::vector 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
 
706
inline node_flags operator |(node_flags l, node_flags r) {
707
	return (node_flags)((unsigned)l|(unsigned)r);
708
}
709
inline node_flags& operator |=(node_flags &l, node_flags r) {
710
	l = l | r;
711
	return l;
712
}
713
 
714
inline node_flags& operator &=(node_flags &l, node_flags r) {
715
	l = (node_flags)((unsigned)l & (unsigned)r);
716
	return l;
717
}
718
 
719
inline node_flags operator ~(node_flags r) {
720
	return (node_flags)~(unsigned)r;
721
}
722
 
723
struct node_stats {
724
	unsigned alu_count;
725
	unsigned alu_kill_count;
726
	unsigned alu_copy_mov_count;
727
	unsigned cf_count;
728
	unsigned fetch_count;
729
	unsigned region_count;
730
	unsigned loop_count;
731
	unsigned phi_count;
732
	unsigned loop_phi_count;
733
	unsigned depart_count;
734
	unsigned repeat_count;
735
	unsigned if_count;
736
 
737
	node_stats() : alu_count(), alu_kill_count(), alu_copy_mov_count(),
738
			cf_count(), fetch_count(), region_count(),
739
			loop_count(), phi_count(), loop_phi_count(), depart_count(),
740
			repeat_count(), if_count() {}
741
 
742
	void dump();
743
};
744
 
745
class shader;
746
 
747
class vpass;
748
 
749
class container_node;
750
class region_node;
751
 
752
class node {
753
 
754
protected:
755
	node(node_type nt, node_subtype nst, node_flags flags = NF_EMPTY)
756
	: prev(), next(), parent(),
757
	  type(nt), subtype(nst), flags(flags),
758
	  pred(), dst(), src() {}
759
 
760
	virtual ~node() {};
761
 
762
public:
763
	node *prev, *next;
764
	container_node *parent;
765
 
766
	node_type type;
767
	node_subtype subtype;
768
	node_flags flags;
769
 
770
	value *pred;
771
 
772
	vvec dst;
773
	vvec src;
774
 
775
	virtual bool is_valid() { return true; }
776
	virtual bool accept(vpass &p, bool enter);
777
 
778
	void insert_before(node *n);
779
	void insert_after(node *n);
780
	void replace_with(node *n);
781
	void remove();
782
 
783
	virtual value_hash hash();
784
	value_hash hash_src();
785
 
786
	virtual bool fold_dispatch(expr_handler *ex);
787
 
788
	bool is_container() { return flags & NF_CONTAINER; }
789
 
790
	bool is_alu_packed() { return subtype == NST_ALU_PACKED_INST; }
791
	bool is_alu_inst() { return subtype == NST_ALU_INST; }
792
	bool is_alu_group() { return subtype == NST_ALU_GROUP; }
793
	bool is_alu_clause() { return subtype == NST_ALU_CLAUSE; }
794
 
795
	bool is_fetch_clause() {
796
		return subtype == NST_TEX_CLAUSE || subtype == NST_VTX_CLAUSE;
797
	}
798
 
799
	bool is_copy() { return subtype == NST_COPY; }
800
	bool is_copy_mov() { return flags & NF_COPY_MOV; }
801
	bool is_any_alu() { return is_alu_inst() || is_alu_packed() || is_copy(); }
802
 
803
	bool is_fetch_inst() { return subtype == NST_FETCH_INST; }
804
	bool is_cf_inst() { return subtype == NST_CF_INST; }
805
 
806
	bool is_region() { return type == NT_REGION; }
807
	bool is_depart() { return type == NT_DEPART; }
808
	bool is_repeat() { return type == NT_REPEAT; }
809
	bool is_if() { return type == NT_IF; }
810
	bool is_bb() { return subtype == NST_BB; }
811
 
812
	bool is_phi() { return subtype == NST_PHI; }
813
 
814
	bool is_dead() { return flags & NF_DEAD; }
815
 
816
	bool is_cf_op(unsigned op);
817
	bool is_alu_op(unsigned op);
818
	bool is_fetch_op(unsigned op);
819
 
820
	unsigned cf_op_flags();
821
	unsigned alu_op_flags();
822
	unsigned alu_op_slot_flags();
823
	unsigned fetch_op_flags();
824
 
825
	bool is_mova();
826
	bool is_pred_set();
827
 
828
	bool vec_uses_ar(vvec &vv) {
829
		for (vvec::iterator I = vv.begin(), E = vv.end(); I != E; ++I) {
830
			value *v = *I;
831
			if (v && v->rel && !v->rel->is_const())
832
				return true;
833
		}
834
		return false;
835
	}
836
 
837
	bool uses_ar() {
838
		return vec_uses_ar(dst) || vec_uses_ar(src);
839
	}
840
 
841
 
842
	region_node* get_parent_region();
843
 
844
	friend class shader;
845
};
846
 
847
class container_node : public node {
848
public:
849
 
850
	container_node(node_type nt = NT_LIST, node_subtype nst = NST_LIST,
851
	               node_flags flags = NF_EMPTY)
852
	: node(nt, nst, flags | NF_CONTAINER), first(), last(),
853
	  live_after(), live_before() {}
854
 
855
	// child items list
856
	node *first, *last;
857
 
858
	val_set live_after;
859
	val_set live_before;
860
 
861
	class iterator {
862
		node *p;
863
	public:
864
		iterator(node *pp = NULL) : p(pp) {}
865
		iterator & operator ++() { p = p->next; return *this;}
866
		iterator & operator --() { p = p->prev; return *this;}
867
		node* operator *() { return p; }
868
		node* operator ->() { return p; }
869
		const iterator advance(int n) {
870
			if (!n) return *this;
871
			iterator I(p);
872
			if (n > 0) while (n--) ++I;
873
			else while (n++) --I;
874
			return I;
875
		}
876
		const iterator operator +(int n) { return advance(n); }
877
		const iterator operator -(int n) { return advance(-n); }
878
		bool operator !=(const iterator &i) { return p != i.p; }
879
		bool operator ==(const iterator &i) { return p == i.p; }
880
	};
881
 
882
	class riterator {
883
		iterator i;
884
	public:
885
		riterator(node *p = NULL) : i(p) {}
886
		riterator & operator ++() { --i; return *this;}
887
		riterator & operator --() { ++i; return *this;}
888
		node* operator *() { return *i; }
889
		node* operator ->() { return *i; }
890
		bool operator !=(const riterator &r) { return i != r.i; }
891
		bool operator ==(const riterator &r) { return i == r.i; }
892
	};
893
 
894
	iterator begin() { return first; }
895
	iterator end() { return NULL; }
896
	riterator rbegin() { return last; }
897
	riterator rend() { return NULL; }
898
 
899
	bool empty() { assert(first != NULL || first == last); return !first; }
900
	unsigned count();
901
 
902
	// used with node containers that represent shceduling queues
903
	// ignores copies and takes into account alu_packed_node items
904
	unsigned real_alu_count();
905
 
906
	void push_back(node *n);
907
	void push_front(node *n);
908
 
909
	void insert_node_before(node *s, node *n);
910
	void insert_node_after(node *s, node *n);
911
 
912
	void append_from(container_node *c);
913
 
914
	// remove range [b..e) from some container and assign to this container
915
	void move(iterator b, iterator e);
916
 
917
	void expand();
918
	void expand(container_node *n);
919
	void remove_node(node *n);
920
 
921
	node *cut(iterator b, iterator e);
922
 
923
	void clear() { first = last = NULL; }
924
 
925
	virtual bool is_valid() { return true; }
926
	virtual bool accept(vpass &p, bool enter);
927
	virtual bool fold_dispatch(expr_handler *ex);
928
 
929
	node* front() { return first; }
930
	node* back() { return last; }
931
 
932
	void collect_stats(node_stats &s);
933
 
934
	friend class shader;
935
 
936
 
937
};
938
 
939
typedef container_node::iterator node_iterator;
940
typedef container_node::riterator node_riterator;
941
 
942
class alu_group_node : public container_node {
943
protected:
944
	alu_group_node() : container_node(NT_LIST, NST_ALU_GROUP), literals() {}
945
public:
946
 
947
	std::vector literals;
948
 
949
	virtual bool is_valid() { return subtype == NST_ALU_GROUP; }
950
	virtual bool accept(vpass &p, bool enter);
951
 
952
 
953
	unsigned literal_chan(literal l) {
954
		std::vector::iterator F =
955
				std::find(literals.begin(), literals.end(), l);
956
		assert(F != literals.end());
957
		return F - literals.begin();
958
	}
959
 
960
	friend class shader;
961
};
962
 
963
class cf_node : public container_node {
964
protected:
965
	cf_node() : container_node(NT_OP, NST_CF_INST), jump_target(),
966
		jump_after_target() {};
967
public:
968
	bc_cf bc;
969
 
970
	cf_node *jump_target;
971
	bool jump_after_target;
972
 
973
	virtual bool is_valid() { return subtype == NST_CF_INST; }
974
	virtual bool accept(vpass &p, bool enter);
975
	virtual bool fold_dispatch(expr_handler *ex);
976
 
977
	void jump(cf_node *c) { jump_target = c; jump_after_target = false; }
978
	void jump_after(cf_node *c) { jump_target = c; jump_after_target = true; }
979
 
980
	friend class shader;
981
};
982
 
983
class alu_node : public node {
984
protected:
985
	alu_node() : node(NT_OP, NST_ALU_INST) {};
986
public:
987
	bc_alu bc;
988
 
989
	virtual bool is_valid() { return subtype == NST_ALU_INST; }
990
	virtual bool accept(vpass &p, bool enter);
991
	virtual bool fold_dispatch(expr_handler *ex);
992
 
993
	unsigned forced_bank_swizzle() {
994
		return ((bc.op_ptr->flags & AF_INTERP) && (bc.slot_flags == AF_4V)) ?
995
				VEC_210 : 0;
996
	}
997
 
998
	// return param index + 1 if instruction references interpolation param,
999
	// otherwise 0
1000
	unsigned interp_param();
1001
 
1002
	alu_group_node *get_alu_group_node();
1003
 
1004
	friend class shader;
1005
};
1006
 
1007
// for multi-slot instrs - DOT/INTERP/... (maybe useful for 64bit pairs later)
1008
class alu_packed_node : public container_node {
1009
protected:
1010
	alu_packed_node() : container_node(NT_OP, NST_ALU_PACKED_INST) {}
1011
public:
1012
 
1013
	const alu_op_info* op_ptr() {
1014
		return static_cast(first)->bc.op_ptr;
1015
	}
1016
	unsigned op() { return static_cast(first)->bc.op; }
1017
	void init_args(bool repl);
1018
 
1019
	virtual bool is_valid() { return subtype == NST_ALU_PACKED_INST; }
1020
	virtual bool accept(vpass &p, bool enter);
1021
	virtual bool fold_dispatch(expr_handler *ex);
1022
 
1023
	unsigned get_slot_mask();
1024
	void update_packed_items(sb_context &ctx);
1025
 
1026
	friend class shader;
1027
};
1028
 
1029
class fetch_node : public node {
1030
protected:
1031
	fetch_node() : node(NT_OP, NST_FETCH_INST) {};
1032
public:
1033
	bc_fetch bc;
1034
 
1035
	virtual bool is_valid() { return subtype == NST_FETCH_INST; }
1036
	virtual bool accept(vpass &p, bool enter);
1037
	virtual bool fold_dispatch(expr_handler *ex);
1038
 
1039
	bool uses_grad() { return bc.op_ptr->flags & FF_USEGRAD; }
1040
 
1041
	friend class shader;
1042
};
1043
 
1044
class region_node;
1045
 
1046
class repeat_node : public container_node {
1047
protected:
1048
	repeat_node(region_node *target, unsigned id)
1049
	: container_node(NT_REPEAT, NST_LIST), target(target), rep_id(id) {}
1050
public:
1051
	region_node *target;
1052
	unsigned rep_id;
1053
 
1054
	virtual bool accept(vpass &p, bool enter);
1055
 
1056
	friend class shader;
1057
};
1058
 
1059
class depart_node : public container_node {
1060
protected:
1061
	depart_node(region_node *target, unsigned id)
1062
	: container_node(NT_DEPART, NST_LIST), target(target), dep_id(id) {}
1063
public:
1064
	region_node *target;
1065
	unsigned dep_id;
1066
 
1067
	virtual bool accept(vpass &p, bool enter);
1068
 
1069
	friend class shader;
1070
};
1071
 
1072
class if_node : public container_node {
1073
protected:
1074
	if_node() : container_node(NT_IF, NST_LIST), cond() {};
1075
public:
1076
	value *cond; // glued to pseudo output (dst[2]) of the PRED_SETxxx
1077
 
1078
	virtual bool accept(vpass &p, bool enter);
1079
 
1080
	friend class shader;
1081
};
1082
 
1083
typedef std::vector depart_vec;
1084
typedef std::vector repeat_vec;
1085
 
1086
class region_node : public container_node {
1087
protected:
1088
	region_node(unsigned id) : container_node(NT_REGION, NST_LIST), region_id(id),
1089
			loop_phi(), phi(), vars_defined(), departs(), repeats() {}
1090
public:
1091
	unsigned region_id;
1092
 
1093
	container_node *loop_phi;
1094
	container_node *phi;
1095
 
1096
	val_set vars_defined;
1097
 
1098
	depart_vec departs;
1099
	repeat_vec repeats;
1100
 
1101
	virtual bool accept(vpass &p, bool enter);
1102
 
1103
	unsigned dep_count() { return departs.size(); }
1104
	unsigned rep_count() { return repeats.size() + 1; }
1105
 
1106
	bool is_loop() { return !repeats.empty(); }
1107
 
1108
	container_node* get_entry_code_location() {
1109
		node *p = first;
1110
		while (p && (p->is_depart() || p->is_repeat()))
1111
			p = static_cast(p)->first;
1112
 
1113
		container_node *c = static_cast(p);
1114
		if (c->is_bb())
1115
			return c;
1116
		else
1117
			return c->parent;
1118
	}
1119
 
1120
	void expand_depart(depart_node *d);
1121
	void expand_repeat(repeat_node *r);
1122
 
1123
	friend class shader;
1124
};
1125
 
1126
class bb_node : public container_node {
1127
protected:
1128
	bb_node(unsigned id, unsigned loop_level)
1129
		: container_node(NT_LIST, NST_BB), id(id), loop_level(loop_level) {}
1130
public:
1131
	unsigned id;
1132
	unsigned loop_level;
1133
 
1134
	virtual bool accept(vpass &p, bool enter);
1135
 
1136
	friend class shader;
1137
};
1138
 
1139
 
1140
typedef std::vector regions_vec;
1141
typedef std::vector bbs_vec;
1142
typedef std::list sched_queue;
1143
typedef sched_queue::iterator sq_iterator;
1144
typedef std::vector node_vec;
1145
typedef std::list node_list;
1146
typedef std::set node_set;
1147
 
1148
 
1149
 
1150
} // namespace r600_sb
1151
 
1152
#endif /* R600_SB_IR_H_ */