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
#define VT_DEBUG 0
28
 
29
#if VT_DEBUG
30
#define VT_DUMP(q) do { q } while (0)
31
#else
32
#define VT_DUMP(q)
33
#endif
34
 
35
#include 
36
 
37
#include "sb_shader.h"
38
#include "sb_pass.h"
39
 
40
namespace r600_sb {
41
 
42
static const char * chans = "xyzw01?_";
43
 
44
sb_ostream& operator << (sb_ostream &o, value &v) {
45
 
46
	bool dead = v.flags & VLF_DEAD;
47
 
48
	if (dead)
49
		o << "{";
50
 
51
	switch (v.kind) {
52
	case VLK_SPECIAL_REG: {
53
		switch (v.select.sel()) {
54
			case SV_AR_INDEX: o << "AR"; break;
55
			case SV_ALU_PRED: o << "PR"; break;
56
			case SV_EXEC_MASK: o << "EM"; break;
57
			case SV_VALID_MASK: o << "VM"; break;
58
			default: o << "???specialreg"; break;
59
		}
60
		break;
61
	}
62
 
63
	case VLK_REG:
64
		o << "R" << v.select.sel() << "."
65
			<< chans[v.select.chan()];
66
 
67
		break;
68
	case VLK_KCACHE: {
69
		o << "C" << v.select.sel() << "." << chans[v.select.chan()];
70
	}
71
		break;
72
	case VLK_CONST:
73
		o << v.literal_value.f << "|";
74
		o.print_zw_hex(v.literal_value.u, 8);
75
		break;
76
	case VLK_PARAM:
77
		o << "Param" << (v.select.sel() - ALU_SRC_PARAM_OFFSET)
78
			<< chans[v.select.chan()];
79
		break;
80
	case VLK_TEMP:
81
		o << "t" << v.select.sel() - shader::temp_regid_offset;
82
		break;
83
	case VLK_REL_REG:
84
 
85
		o << "A" << v.select;
86
		o << "[";
87
		o << *v.rel;
88
		o << "]";
89
 
90
		o << "_" << v.uid;
91
 
92
		break;
93
	case VLK_UNDEF:
94
		o << "undef";
95
		break;
96
	default:
97
		o << v.kind << "?????";
98
		break;
99
	}
100
 
101
	if (v.version)
102
		o << "." << v.version;
103
 
104
	if (dead)
105
		o << "}";
106
 
107
	if (v.is_global())
108
		o << "||";
109
	if (v.is_fixed())
110
		o << "F";
111
	if (v.is_prealloc())
112
		o << "P";
113
 
114
	sel_chan g;
115
 
116
	if (v.is_rel()) {
117
		g = v.array->gpr;
118
	} else {
119
		g = v.gpr;
120
	}
121
 
122
	if (g) {
123
		o << "@R" << g.sel() << "." << chans[g.chan()];
124
	}
125
 
126
	return o;
127
}
128
 
129
void value_table::add_value(value* v) {
130
 
131
	if (v->gvn_source) {
132
		return;
133
	}
134
 
135
	VT_DUMP(
136
		sblog << "gvn add_value ";
137
		dump::dump_val(v);
138
	);
139
 
140
	value_hash hash = v->hash();
141
	vt_item & vti = hashtable[hash & size_mask];
142
	vti.push_back(v);
143
	++cnt;
144
 
145
	if (v->def && ex.try_fold(v)) {
146
		VT_DUMP(
147
			sblog << " folded: ";
148
			dump::dump_val(v->gvn_source);
149
			sblog << "\n";
150
		);
151
		return;
152
	}
153
 
154
	int n = 0;
155
	for (vt_item::iterator I = vti.begin(), E = vti.end(); I != E; ++I, ++n) {
156
		value *c = *I;
157
 
158
		if (c == v)
159
			break;
160
 
161
		if (expr_equal(c, v)) {
162
			v->gvn_source = c->gvn_source;
163
 
164
			VT_DUMP(
165
				sblog << " found : equal to ";
166
				dump::dump_val(v->gvn_source);
167
				sblog << "\n";
168
			);
169
			return;
170
		}
171
	}
172
 
173
	v->gvn_source = v;
174
	VT_DUMP(
175
		sblog << " added new\n";
176
	);
177
}
178
 
179
value_hash value::hash() {
180
	if (ghash)
181
		return ghash;
182
	if (is_rel())
183
		ghash = rel_hash();
184
	else if (def)
185
		ghash = def->hash();
186
	else
187
		ghash = ((uintptr_t)this) | 1;
188
 
189
	return ghash;
190
}
191
 
192
value_hash value::rel_hash() {
193
	value_hash h = rel ? rel->hash() : 0;
194
	h |= select << 10;
195
	h |= array->hash();
196
	return h;
197
}
198
 
199
bool value_table::expr_equal(value* l, value* r) {
200
	return ex.equal(l, r);
201
}
202
 
203
void value_table::get_values(vvec& v) {
204
	v.resize(cnt);
205
 
206
	vvec::iterator T = v.begin();
207
 
208
	for(vt_table::iterator I = hashtable.begin(), E = hashtable.end();
209
			I != E; ++I) {
210
		T = std::copy(I->begin(), I->end(), T);
211
	}
212
}
213
 
214
void value::add_use(node* n, use_kind kind, int arg) {
215
	if (0) {
216
	sblog << "add_use ";
217
	dump::dump_val(this);
218
	sblog << "   =>  ";
219
	dump::dump_op(n);
220
	sblog << "     kind " << kind << "    arg " << arg << "\n";
221
	}
222
	uses = new use_info(n, kind, arg, uses);
223
}
224
 
225
unsigned value::use_count() {
226
	use_info *u = uses;
227
	unsigned c = 0;
228
	while (u) {
229
		++c;
230
		u = u->next;
231
	}
232
	return c;
233
}
234
 
235
bool value::is_global() {
236
	if (chunk)
237
		return chunk->is_global();
238
	return flags & VLF_GLOBAL;
239
}
240
 
241
void value::set_global() {
242
	assert(is_sgpr());
243
	flags |= VLF_GLOBAL;
244
	if (chunk)
245
		chunk->set_global();
246
}
247
 
248
void value::set_prealloc() {
249
	assert(is_sgpr());
250
	flags |= VLF_PREALLOC;
251
	if (chunk)
252
		chunk->set_prealloc();
253
}
254
 
255
bool value::is_fixed() {
256
	if (array && array->gpr)
257
		return true;
258
	if (chunk)
259
		return chunk->is_fixed();
260
	return flags & VLF_FIXED;
261
}
262
 
263
void value::fix() {
264
	if (chunk)
265
		chunk->fix();
266
	flags |= VLF_FIXED;
267
}
268
 
269
bool value::is_prealloc() {
270
	if (chunk)
271
		return chunk->is_prealloc();
272
	return flags & VLF_PREALLOC;
273
}
274
 
275
void value::delete_uses() {
276
	use_info *u, *c = uses;
277
	while (c) {
278
		u = c->next;
279
		delete c;
280
		c = u;
281
	}
282
	uses = NULL;
283
}
284
 
285
void ra_constraint::update_values() {
286
	for (vvec::iterator I = values.begin(), E = values.end(); I != E; ++I) {
287
		assert(!(*I)->constraint);
288
		(*I)->constraint = this;
289
	}
290
}
291
 
292
void* sb_pool::allocate(unsigned sz) {
293
	sz = (sz + SB_POOL_ALIGN - 1) & ~(SB_POOL_ALIGN - 1);
294
	assert (sz < (block_size >> 6) && "too big allocation size for sb_pool");
295
 
296
	unsigned offset = total_size % block_size;
297
	unsigned capacity = block_size * blocks.size();
298
 
299
	if (total_size + sz > capacity) {
300
		total_size = capacity;
301
		void * nb = malloc(block_size);
302
		blocks.push_back(nb);
303
		offset = 0;
304
	}
305
 
306
	total_size += sz;
307
	return ((char*)blocks.back() + offset);
308
}
309
 
310
void sb_pool::free_all() {
311
	for (block_vector::iterator I = blocks.begin(), E = blocks.end(); I != E;
312
			++I) {
313
		free(*I);
314
	}
315
}
316
 
317
value* sb_value_pool::create(value_kind k, sel_chan regid,
318
                             unsigned ver) {
319
	void* np = allocate(aligned_elt_size);
320
	value *v = new (np) value(size(), k, regid, ver);
321
	return v;
322
}
323
 
324
void sb_value_pool::delete_all() {
325
	unsigned bcnt = blocks.size();
326
	unsigned toffset = 0;
327
	for (unsigned b = 0; b < bcnt; ++b) {
328
		char *bstart = (char*)blocks[b];
329
		for (unsigned offset = 0; offset < block_size;
330
				offset += aligned_elt_size) {
331
			((value*)(bstart + offset))->~value();
332
			toffset += aligned_elt_size;
333
			if (toffset >= total_size)
334
				return;
335
		}
336
	}
337
}
338
 
339
bool sb_bitset::get(unsigned id) {
340
	assert(id < bit_size);
341
	unsigned w = id / bt_bits;
342
	unsigned b = id % bt_bits;
343
	return (data[w] >> b) & 1;
344
}
345
 
346
void sb_bitset::set(unsigned id, bool bit) {
347
	assert(id < bit_size);
348
	unsigned w = id / bt_bits;
349
	unsigned b = id % bt_bits;
350
	if (w >= data.size())
351
		data.resize(w + 1);
352
 
353
	if (bit)
354
		data[w] |= (1 << b);
355
	else
356
		data[w] &= ~(1 << b);
357
}
358
 
359
inline bool sb_bitset::set_chk(unsigned id, bool bit) {
360
	assert(id < bit_size);
361
	unsigned w = id / bt_bits;
362
	unsigned b = id % bt_bits;
363
	basetype d = data[w];
364
	basetype dn = (d & ~(1 << b)) | (bit << b);
365
	bool r = (d != dn);
366
	data[w] = r ? dn : data[w];
367
	return r;
368
}
369
 
370
void sb_bitset::clear() {
371
	std::fill(data.begin(), data.end(), 0);
372
}
373
 
374
void sb_bitset::resize(unsigned size) {
375
	unsigned cur_data_size = data.size();
376
	unsigned new_data_size = (size + bt_bits - 1) / bt_bits;
377
 
378
 
379
	if (new_data_size != cur_data_size)
380
		data.resize(new_data_size);
381
 
382
	// make sure that new bits in the existing word are cleared
383
	if (cur_data_size && size > bit_size && bit_size % bt_bits) {
384
		basetype clear_mask = (~(basetype)0u) << (bit_size % bt_bits);
385
		data[cur_data_size - 1] &= ~clear_mask;
386
	}
387
 
388
	bit_size = size;
389
}
390
 
391
unsigned sb_bitset::find_bit(unsigned start) {
392
	assert(start < bit_size);
393
	unsigned w = start / bt_bits;
394
	unsigned b = start % bt_bits;
395
	unsigned sz = data.size();
396
 
397
	while (w < sz) {
398
		basetype d = data[w] >> b;
399
		if (d != 0) {
400
			unsigned pos = __builtin_ctz(d) + b + w * bt_bits;
401
			return pos;
402
		}
403
 
404
		b = 0;
405
		++w;
406
	}
407
 
408
	return bit_size;
409
}
410
 
411
sb_value_set::iterator::iterator(shader& sh, sb_value_set* s, unsigned nb)
412
	: vp(sh.get_value_pool()), s(s), nb(nb) {}
413
 
414
bool sb_value_set::add_set_checked(sb_value_set& s2) {
415
	if (bs.size() < s2.bs.size())
416
		bs.resize(s2.bs.size());
417
	sb_bitset nbs = bs | s2.bs;
418
	if (bs != nbs) {
419
		bs.swap(nbs);
420
		return true;
421
	}
422
	return false;
423
}
424
 
425
void r600_sb::sb_value_set::remove_set(sb_value_set& s2) {
426
	bs.mask(s2.bs);
427
}
428
 
429
bool sb_value_set::add_val(value* v) {
430
	assert(v);
431
	if (bs.size() < v->uid)
432
		bs.resize(v->uid + 32);
433
 
434
	return bs.set_chk(v->uid - 1, 1);
435
}
436
 
437
bool sb_value_set::remove_vec(vvec& vv) {
438
	bool modified = false;
439
	for (vvec::iterator I = vv.begin(), E = vv.end(); I != E; ++I) {
440
		if (*I)
441
			modified |= remove_val(*I);
442
	}
443
	return modified;
444
}
445
 
446
void sb_value_set::clear() {
447
	bs.clear();
448
}
449
 
450
bool sb_value_set::remove_val(value* v) {
451
	assert(v);
452
	if (bs.size() < v->uid)
453
		return false;
454
	return bs.set_chk(v->uid - 1, 0);
455
}
456
 
457
bool r600_sb::sb_value_set::add_vec(vvec& vv) {
458
	bool modified = false;
459
	for (vvec::iterator I = vv.begin(), E = vv.end(); I != E; ++I) {
460
		value *v = *I;
461
		if (v)
462
			modified |= add_val(v);
463
	}
464
	return modified;
465
}
466
 
467
bool r600_sb::sb_value_set::contains(value* v) {
468
	unsigned b = v->uid - 1;
469
	if (b < bs.size())
470
		return bs.get(v->uid - 1);
471
	else
472
		return false;
473
}
474
 
475
bool sb_value_set::empty() {
476
	return bs.size() == 0 || bs.find_bit(0) == bs.size();
477
}
478
 
479
void sb_bitset::swap(sb_bitset& bs2) {
480
	std::swap(data, bs2.data);
481
	std::swap(bit_size, bs2.bit_size);
482
}
483
 
484
bool sb_bitset::operator ==(const sb_bitset& bs2) {
485
	if (bit_size != bs2.bit_size)
486
		return false;
487
 
488
	for (unsigned i = 0, c = data.size(); i < c; ++i) {
489
		if (data[i] != bs2.data[i])
490
			return false;
491
	}
492
	return true;
493
}
494
 
495
sb_bitset& sb_bitset::operator &=(const sb_bitset& bs2) {
496
	if (bit_size > bs2.bit_size) {
497
		resize(bs2.bit_size);
498
	}
499
 
500
	for (unsigned i = 0, c = std::min(data.size(), bs2.data.size()); i < c;
501
			++i) {
502
		data[i] &= bs2.data[i];
503
	}
504
	return *this;
505
}
506
 
507
sb_bitset& sb_bitset::mask(const sb_bitset& bs2) {
508
	if (bit_size < bs2.bit_size) {
509
		resize(bs2.bit_size);
510
	}
511
 
512
	for (unsigned i = 0, c = data.size(); i < c;
513
			++i) {
514
		data[i] &= ~bs2.data[i];
515
	}
516
	return *this;
517
}
518
 
519
bool ra_constraint::check() {
520
	assert(kind == CK_SAME_REG);
521
 
522
	unsigned reg = 0;
523
 
524
	for (vvec::iterator I = values.begin(), E = values.end(); I != E; ++I) {
525
		value *v = *I;
526
		if (!v)
527
			continue;
528
 
529
		if (!v->gpr)
530
			return false;
531
 
532
		if (reg == 0)
533
			reg = v->gpr.sel() + 1;
534
		else if (reg != v->gpr.sel() + 1)
535
			return false;
536
 
537
		if (v->is_chan_pinned()) {
538
			if (v->pin_gpr.chan() != v->gpr.chan())
539
				return false;
540
		}
541
	}
542
	return true;
543
}
544
 
545
bool gpr_array::is_dead() {
546
	return false;
547
}
548
 
549
} // namespace r600_sb