1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2013 Vadim Girlin <vadimgirlin@gmail.com>
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub
8bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom
9bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE.
22bf215546Sopenharmony_ci *
23bf215546Sopenharmony_ci * Authors:
24bf215546Sopenharmony_ci *      Vadim Girlin
25bf215546Sopenharmony_ci */
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "sb_bc.h"
28bf215546Sopenharmony_ci#include "sb_shader.h"
29bf215546Sopenharmony_ci#include "sb_pass.h"
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_cinamespace r600_sb {
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_cibool node::accept(vpass& p, bool enter) { return p.visit(*this, enter); }
34bf215546Sopenharmony_cibool container_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); }
35bf215546Sopenharmony_cibool alu_group_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); }
36bf215546Sopenharmony_cibool alu_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); }
37bf215546Sopenharmony_cibool cf_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); }
38bf215546Sopenharmony_cibool fetch_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); }
39bf215546Sopenharmony_cibool region_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); }
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_cibool repeat_node::accept(vpass& p, bool enter) {
42bf215546Sopenharmony_ci	return p.visit(*this, enter);
43bf215546Sopenharmony_ci}
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_cibool depart_node::accept(vpass& p, bool enter) {
46bf215546Sopenharmony_ci	return p.visit(*this, enter);
47bf215546Sopenharmony_ci}
48bf215546Sopenharmony_cibool if_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); }
49bf215546Sopenharmony_cibool bb_node::accept(vpass& p, bool enter) { return p.visit(*this, enter); }
50bf215546Sopenharmony_cibool alu_packed_node::accept(vpass& p, bool enter) {
51bf215546Sopenharmony_ci	return p.visit(*this, enter);
52bf215546Sopenharmony_ci}
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_civoid alu_packed_node::init_args(bool repl) {
55bf215546Sopenharmony_ci	alu_node *p = static_cast<alu_node*>(first);
56bf215546Sopenharmony_ci	assert(p->is_valid());
57bf215546Sopenharmony_ci	while (p) {
58bf215546Sopenharmony_ci		dst.insert(dst.end(), p->dst.begin(), p->dst.end());
59bf215546Sopenharmony_ci		src.insert(src.end(), p->src.begin(), p->src.end());
60bf215546Sopenharmony_ci		p = static_cast<alu_node*>(p->next);
61bf215546Sopenharmony_ci	}
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_ci	value *replicated_value = NULL;
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_ci	for (vvec::iterator I = dst.begin(), E = dst.end(); I != E; ++I) {
66bf215546Sopenharmony_ci		value *v = *I;
67bf215546Sopenharmony_ci		if (v) {
68bf215546Sopenharmony_ci			if (repl) {
69bf215546Sopenharmony_ci				if (replicated_value)
70bf215546Sopenharmony_ci					v->assign_source(replicated_value);
71bf215546Sopenharmony_ci				else
72bf215546Sopenharmony_ci					replicated_value = v;
73bf215546Sopenharmony_ci			}
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci			v->def = this;
76bf215546Sopenharmony_ci		}
77bf215546Sopenharmony_ci	}
78bf215546Sopenharmony_ci}
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_civoid container_node::insert_node_before(node* s, node* n) {
81bf215546Sopenharmony_ci	if (s->prev) {
82bf215546Sopenharmony_ci		node *sp = s->prev;
83bf215546Sopenharmony_ci		sp->next = n;
84bf215546Sopenharmony_ci		n->prev = sp;
85bf215546Sopenharmony_ci		n->next = s;
86bf215546Sopenharmony_ci		s->prev = n;
87bf215546Sopenharmony_ci	} else {
88bf215546Sopenharmony_ci		n->next = s;
89bf215546Sopenharmony_ci		s->prev = n;
90bf215546Sopenharmony_ci		first = n;
91bf215546Sopenharmony_ci	}
92bf215546Sopenharmony_ci	n->parent = this;
93bf215546Sopenharmony_ci}
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_civoid container_node::insert_node_after(node* s, node* n) {
96bf215546Sopenharmony_ci	if (s->next) {
97bf215546Sopenharmony_ci		node *sn = s->next;
98bf215546Sopenharmony_ci		sn->prev = n;
99bf215546Sopenharmony_ci		n->next = sn;
100bf215546Sopenharmony_ci		n->prev = s;
101bf215546Sopenharmony_ci		s->next = n;
102bf215546Sopenharmony_ci	} else {
103bf215546Sopenharmony_ci		n->prev = s;
104bf215546Sopenharmony_ci		s->next = n;
105bf215546Sopenharmony_ci		last = n;
106bf215546Sopenharmony_ci	}
107bf215546Sopenharmony_ci	n->parent = this;
108bf215546Sopenharmony_ci}
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_civoid container_node::move(iterator b, iterator e) {
111bf215546Sopenharmony_ci	assert(b != e);
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci	container_node *source_container = b->parent;
114bf215546Sopenharmony_ci	node *l = source_container->cut(b, e);
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ci	first = last = l;
117bf215546Sopenharmony_ci	first->parent = this;
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_ci	while (last->next) {
120bf215546Sopenharmony_ci		last = last->next;
121bf215546Sopenharmony_ci		last->parent = this;
122bf215546Sopenharmony_ci	}
123bf215546Sopenharmony_ci}
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_cinode* container_node::cut(iterator b, iterator e) {
126bf215546Sopenharmony_ci	assert(!*b || b->parent == this);
127bf215546Sopenharmony_ci	assert(!*e || e->parent == this);
128bf215546Sopenharmony_ci	assert(b != e);
129bf215546Sopenharmony_ci
130bf215546Sopenharmony_ci	if (b->prev) {
131bf215546Sopenharmony_ci		b->prev->next = *e;
132bf215546Sopenharmony_ci	} else {
133bf215546Sopenharmony_ci		first = *e;
134bf215546Sopenharmony_ci	}
135bf215546Sopenharmony_ci
136bf215546Sopenharmony_ci	if (*e) {
137bf215546Sopenharmony_ci		e->prev->next = NULL;
138bf215546Sopenharmony_ci		e->prev = b->prev;
139bf215546Sopenharmony_ci	} else {
140bf215546Sopenharmony_ci		last->next = NULL;
141bf215546Sopenharmony_ci		last = b->prev;
142bf215546Sopenharmony_ci	}
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_ci	b->prev = NULL;
145bf215546Sopenharmony_ci
146bf215546Sopenharmony_ci	return *b;
147bf215546Sopenharmony_ci}
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ciunsigned container_node::count() {
150bf215546Sopenharmony_ci	unsigned c = 0;
151bf215546Sopenharmony_ci	node *t = first;
152bf215546Sopenharmony_ci	while (t) {
153bf215546Sopenharmony_ci		t = t->next;
154bf215546Sopenharmony_ci		c++;
155bf215546Sopenharmony_ci	}
156bf215546Sopenharmony_ci	return c;
157bf215546Sopenharmony_ci}
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_civoid container_node::remove_node(node *n) {
160bf215546Sopenharmony_ci	if (n->prev)
161bf215546Sopenharmony_ci		n->prev->next = n->next;
162bf215546Sopenharmony_ci	else
163bf215546Sopenharmony_ci		first = n->next;
164bf215546Sopenharmony_ci	if (n->next)
165bf215546Sopenharmony_ci		n->next->prev = n->prev;
166bf215546Sopenharmony_ci	else
167bf215546Sopenharmony_ci		last = n->prev;
168bf215546Sopenharmony_ci	n->parent = NULL;
169bf215546Sopenharmony_ci}
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_civoid container_node::expand(container_node *n) {
172bf215546Sopenharmony_ci	if (!n->empty()) {
173bf215546Sopenharmony_ci		node *e0 = n->first;
174bf215546Sopenharmony_ci		node *e1 = n->last;
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci		e0->prev = n->prev;
177bf215546Sopenharmony_ci		if (e0->prev) {
178bf215546Sopenharmony_ci			e0->prev->next = e0;
179bf215546Sopenharmony_ci		} else {
180bf215546Sopenharmony_ci			first = e0;
181bf215546Sopenharmony_ci		}
182bf215546Sopenharmony_ci
183bf215546Sopenharmony_ci		e1->next = n->next;
184bf215546Sopenharmony_ci		if (e1->next)
185bf215546Sopenharmony_ci			e1->next->prev = e1;
186bf215546Sopenharmony_ci		else
187bf215546Sopenharmony_ci			last = e1;
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci		do {
190bf215546Sopenharmony_ci			e0->parent = this;
191bf215546Sopenharmony_ci			e0 = e0->next;
192bf215546Sopenharmony_ci		} while (e0 != e1->next);
193bf215546Sopenharmony_ci	} else
194bf215546Sopenharmony_ci		remove_node(n);
195bf215546Sopenharmony_ci}
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_civoid container_node::push_back(node *n) {
198bf215546Sopenharmony_ci	if (last) {
199bf215546Sopenharmony_ci		last->next = n;
200bf215546Sopenharmony_ci		n->next = NULL;
201bf215546Sopenharmony_ci		n->prev = last;
202bf215546Sopenharmony_ci		last = n;
203bf215546Sopenharmony_ci	} else {
204bf215546Sopenharmony_ci		assert(!first);
205bf215546Sopenharmony_ci		first = last = n;
206bf215546Sopenharmony_ci		n->prev = n->next = NULL;
207bf215546Sopenharmony_ci	}
208bf215546Sopenharmony_ci	n->parent = this;
209bf215546Sopenharmony_ci}
210bf215546Sopenharmony_civoid container_node::push_front(node *n) {
211bf215546Sopenharmony_ci	if (first) {
212bf215546Sopenharmony_ci		first->prev = n;
213bf215546Sopenharmony_ci		n->prev = NULL;
214bf215546Sopenharmony_ci		n->next = first;
215bf215546Sopenharmony_ci		first = n;
216bf215546Sopenharmony_ci	} else {
217bf215546Sopenharmony_ci		assert(!last);
218bf215546Sopenharmony_ci		first = last = n;
219bf215546Sopenharmony_ci		n->prev = n->next = NULL;
220bf215546Sopenharmony_ci	}
221bf215546Sopenharmony_ci	n->parent = this;
222bf215546Sopenharmony_ci}
223bf215546Sopenharmony_ci
224bf215546Sopenharmony_civoid node::insert_before(node* n) {
225bf215546Sopenharmony_ci	 parent->insert_node_before(this, n);
226bf215546Sopenharmony_ci}
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_civoid node::insert_after(node* n) {
229bf215546Sopenharmony_ci	 parent->insert_node_after(this, n);
230bf215546Sopenharmony_ci}
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_civoid node::replace_with(node* n) {
233bf215546Sopenharmony_ci	n->prev = prev;
234bf215546Sopenharmony_ci	n->next = next;
235bf215546Sopenharmony_ci	n->parent = parent;
236bf215546Sopenharmony_ci	if (prev)
237bf215546Sopenharmony_ci		prev->next = n;
238bf215546Sopenharmony_ci	if (next)
239bf215546Sopenharmony_ci		next->prev = n;
240bf215546Sopenharmony_ci
241bf215546Sopenharmony_ci	if (parent->first == this)
242bf215546Sopenharmony_ci		parent->first = n;
243bf215546Sopenharmony_ci
244bf215546Sopenharmony_ci	if (parent->last == this)
245bf215546Sopenharmony_ci		parent->last = n;
246bf215546Sopenharmony_ci
247bf215546Sopenharmony_ci	parent = NULL;
248bf215546Sopenharmony_ci	next = prev = NULL;
249bf215546Sopenharmony_ci}
250bf215546Sopenharmony_ci
251bf215546Sopenharmony_civoid container_node::expand() {
252bf215546Sopenharmony_ci	 parent->expand(this);
253bf215546Sopenharmony_ci}
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_civoid node::remove() {parent->remove_node(this);
256bf215546Sopenharmony_ci}
257bf215546Sopenharmony_ci
258bf215546Sopenharmony_civalue_hash node::hash_src() const {
259bf215546Sopenharmony_ci
260bf215546Sopenharmony_ci	value_hash h = 12345;
261bf215546Sopenharmony_ci
262bf215546Sopenharmony_ci	for (int k = 0, e = src.size(); k < e; ++k) {
263bf215546Sopenharmony_ci		value *s = src[k];
264bf215546Sopenharmony_ci		if (s)
265bf215546Sopenharmony_ci			h ^=  (s->hash());
266bf215546Sopenharmony_ci	}
267bf215546Sopenharmony_ci
268bf215546Sopenharmony_ci	return h;
269bf215546Sopenharmony_ci}
270bf215546Sopenharmony_ci
271bf215546Sopenharmony_ci
272bf215546Sopenharmony_civalue_hash node::hash() const {
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_ci	if (parent && parent->subtype == NST_LOOP_PHI_CONTAINER)
275bf215546Sopenharmony_ci		return 47451;
276bf215546Sopenharmony_ci
277bf215546Sopenharmony_ci	return hash_src() ^ (subtype << 13) ^ (type << 3);
278bf215546Sopenharmony_ci}
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_civoid r600_sb::container_node::append_from(container_node* c) {
281bf215546Sopenharmony_ci	if (!c->first)
282bf215546Sopenharmony_ci		return;
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci	node *b = c->first;
285bf215546Sopenharmony_ci
286bf215546Sopenharmony_ci	if (last) {
287bf215546Sopenharmony_ci		last->next = c->first;
288bf215546Sopenharmony_ci		last->next->prev = last;
289bf215546Sopenharmony_ci	} else {
290bf215546Sopenharmony_ci		first = c->first;
291bf215546Sopenharmony_ci	}
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci	last = c->last;
294bf215546Sopenharmony_ci	c->first = NULL;
295bf215546Sopenharmony_ci	c->last = NULL;
296bf215546Sopenharmony_ci
297bf215546Sopenharmony_ci	while (b) {
298bf215546Sopenharmony_ci		b->parent = this;
299bf215546Sopenharmony_ci		b = b->next;
300bf215546Sopenharmony_ci	}
301bf215546Sopenharmony_ci}
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_cibool node::fold_dispatch(expr_handler* ex) { return ex->fold(*this); }
304bf215546Sopenharmony_cibool container_node::fold_dispatch(expr_handler* ex) { return ex->fold(*this); }
305bf215546Sopenharmony_cibool alu_node::fold_dispatch(expr_handler* ex) { return ex->fold(*this); }
306bf215546Sopenharmony_cibool alu_packed_node::fold_dispatch(expr_handler* ex) { return ex->fold(*this); }
307bf215546Sopenharmony_cibool fetch_node::fold_dispatch(expr_handler* ex) { return ex->fold(*this); }
308bf215546Sopenharmony_cibool cf_node::fold_dispatch(expr_handler* ex) { return ex->fold(*this); }
309bf215546Sopenharmony_ci
310bf215546Sopenharmony_ciunsigned alu_packed_node::get_slot_mask() {
311bf215546Sopenharmony_ci	unsigned mask = 0;
312bf215546Sopenharmony_ci	for (node_iterator I = begin(), E = end(); I != E; ++I)
313bf215546Sopenharmony_ci		mask |= 1 << static_cast<alu_node*>(*I)->bc.slot;
314bf215546Sopenharmony_ci	return mask;
315bf215546Sopenharmony_ci}
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_civoid alu_packed_node::update_packed_items(sb_context &ctx) {
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci	vvec::iterator SI(src.begin()), DI(dst.begin());
320bf215546Sopenharmony_ci
321bf215546Sopenharmony_ci	assert(first);
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_ci	alu_node *c = static_cast<alu_node*>(first);
324bf215546Sopenharmony_ci	unsigned flags = c->bc.op_ptr->flags;
325bf215546Sopenharmony_ci	unsigned slot_flags = c->bc.slot_flags;
326bf215546Sopenharmony_ci
327bf215546Sopenharmony_ci	// fixup dst for instructions that replicate output
328bf215546Sopenharmony_ci	if (((flags & AF_REPL) && slot_flags == AF_4V) ||
329bf215546Sopenharmony_ci			(ctx.is_cayman() && slot_flags == AF_S)) {
330bf215546Sopenharmony_ci
331bf215546Sopenharmony_ci		value *swp[4] = {};
332bf215546Sopenharmony_ci
333bf215546Sopenharmony_ci		unsigned chan;
334bf215546Sopenharmony_ci
335bf215546Sopenharmony_ci		for (vvec::iterator I2 = dst.begin(), E2 = dst.end();
336bf215546Sopenharmony_ci				I2 != E2; ++I2) {
337bf215546Sopenharmony_ci			value *v = *I2;
338bf215546Sopenharmony_ci			if (v) {
339bf215546Sopenharmony_ci				chan = v->get_final_chan();
340bf215546Sopenharmony_ci				assert(!swp[chan] || swp[chan] == v);
341bf215546Sopenharmony_ci				swp[chan] = v;
342bf215546Sopenharmony_ci			}
343bf215546Sopenharmony_ci		}
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci		chan = 0;
346bf215546Sopenharmony_ci		for (vvec::iterator I2 = dst.begin(), E2 = dst.end();
347bf215546Sopenharmony_ci				I2 != E2; ++I2, ++chan) {
348bf215546Sopenharmony_ci			*I2 = swp[chan];
349bf215546Sopenharmony_ci		}
350bf215546Sopenharmony_ci	}
351bf215546Sopenharmony_ci
352bf215546Sopenharmony_ci	for (node_iterator I = begin(), E = end(); I != E; ++I) {
353bf215546Sopenharmony_ci		alu_node *n = static_cast<alu_node*>(*I);
354bf215546Sopenharmony_ci		assert(n);
355bf215546Sopenharmony_ci
356bf215546Sopenharmony_ci		for (vvec::iterator I2 = n->src.begin(), E2 = n->src.end();
357bf215546Sopenharmony_ci				I2 != E2; ++I2, ++SI) {
358bf215546Sopenharmony_ci			*I2 = *SI;
359bf215546Sopenharmony_ci		}
360bf215546Sopenharmony_ci		for (vvec::iterator I2 = n->dst.begin(), E2 = n->dst.end();
361bf215546Sopenharmony_ci				I2 != E2; ++I2, ++DI) {
362bf215546Sopenharmony_ci			*I2 = *DI;
363bf215546Sopenharmony_ci		}
364bf215546Sopenharmony_ci	}
365bf215546Sopenharmony_ci}
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_cibool node::is_cf_op(unsigned op) {
368bf215546Sopenharmony_ci	if (!is_cf_inst())
369bf215546Sopenharmony_ci		return false;
370bf215546Sopenharmony_ci	cf_node *c = static_cast<cf_node*>(this);
371bf215546Sopenharmony_ci	return c->bc.op == op;
372bf215546Sopenharmony_ci}
373bf215546Sopenharmony_ci
374bf215546Sopenharmony_cibool node::is_alu_op(unsigned op) {
375bf215546Sopenharmony_ci	if (!is_alu_inst())
376bf215546Sopenharmony_ci		return false;
377bf215546Sopenharmony_ci	alu_node *c = static_cast<alu_node*>(this);
378bf215546Sopenharmony_ci	return c->bc.op == op;
379bf215546Sopenharmony_ci}
380bf215546Sopenharmony_ci
381bf215546Sopenharmony_cibool node::is_fetch_op(unsigned op) {
382bf215546Sopenharmony_ci	if (!is_fetch_inst())
383bf215546Sopenharmony_ci		return false;
384bf215546Sopenharmony_ci	fetch_node *c = static_cast<fetch_node*>(this);
385bf215546Sopenharmony_ci	return c->bc.op == op;
386bf215546Sopenharmony_ci}
387bf215546Sopenharmony_ci
388bf215546Sopenharmony_ci
389bf215546Sopenharmony_ci
390bf215546Sopenharmony_cibool node::is_mova() {
391bf215546Sopenharmony_ci	if (!is_alu_inst())
392bf215546Sopenharmony_ci		return false;
393bf215546Sopenharmony_ci	alu_node *a = static_cast<alu_node*>(this);
394bf215546Sopenharmony_ci	return (a->bc.op_ptr->flags & AF_MOVA);
395bf215546Sopenharmony_ci}
396bf215546Sopenharmony_ci
397bf215546Sopenharmony_cibool node::is_pred_set() {
398bf215546Sopenharmony_ci	if (!is_alu_inst())
399bf215546Sopenharmony_ci		return false;
400bf215546Sopenharmony_ci	alu_node *a = static_cast<alu_node*>(this);
401bf215546Sopenharmony_ci	return (a->bc.op_ptr->flags & AF_ANY_PRED);
402bf215546Sopenharmony_ci}
403bf215546Sopenharmony_ci
404bf215546Sopenharmony_ciunsigned node::cf_op_flags() {
405bf215546Sopenharmony_ci	assert(is_cf_inst());
406bf215546Sopenharmony_ci	cf_node *c = static_cast<cf_node*>(this);
407bf215546Sopenharmony_ci	return c->bc.op_ptr->flags;
408bf215546Sopenharmony_ci}
409bf215546Sopenharmony_ci
410bf215546Sopenharmony_ciunsigned node::alu_op_flags() {
411bf215546Sopenharmony_ci	assert(is_alu_inst());
412bf215546Sopenharmony_ci	alu_node *c = static_cast<alu_node*>(this);
413bf215546Sopenharmony_ci	return c->bc.op_ptr->flags;
414bf215546Sopenharmony_ci}
415bf215546Sopenharmony_ci
416bf215546Sopenharmony_ciunsigned node::fetch_op_flags() {
417bf215546Sopenharmony_ci	assert(is_fetch_inst());
418bf215546Sopenharmony_ci	fetch_node *c = static_cast<fetch_node*>(this);
419bf215546Sopenharmony_ci	return c->bc.op_ptr->flags;
420bf215546Sopenharmony_ci}
421bf215546Sopenharmony_ci
422bf215546Sopenharmony_ciunsigned node::alu_op_slot_flags() {
423bf215546Sopenharmony_ci	assert(is_alu_inst());
424bf215546Sopenharmony_ci	alu_node *c = static_cast<alu_node*>(this);
425bf215546Sopenharmony_ci	return c->bc.slot_flags;
426bf215546Sopenharmony_ci}
427bf215546Sopenharmony_ci
428bf215546Sopenharmony_ciregion_node* node::get_parent_region() {
429bf215546Sopenharmony_ci	node *p = this;
430bf215546Sopenharmony_ci	while ((p = p->parent))
431bf215546Sopenharmony_ci		if (p->is_region())
432bf215546Sopenharmony_ci			return static_cast<region_node*>(p);
433bf215546Sopenharmony_ci	return NULL;
434bf215546Sopenharmony_ci}
435bf215546Sopenharmony_ci
436bf215546Sopenharmony_ciunsigned container_node::real_alu_count() {
437bf215546Sopenharmony_ci	unsigned c = 0;
438bf215546Sopenharmony_ci	node *t = first;
439bf215546Sopenharmony_ci	while (t) {
440bf215546Sopenharmony_ci		if (t->is_alu_inst())
441bf215546Sopenharmony_ci			++c;
442bf215546Sopenharmony_ci		else if (t->is_alu_packed())
443bf215546Sopenharmony_ci			c += static_cast<container_node*>(t)->count();
444bf215546Sopenharmony_ci		t = t->next;
445bf215546Sopenharmony_ci	}
446bf215546Sopenharmony_ci	return c;
447bf215546Sopenharmony_ci}
448bf215546Sopenharmony_ci
449bf215546Sopenharmony_civoid container_node::collect_stats(node_stats& s) {
450bf215546Sopenharmony_ci
451bf215546Sopenharmony_ci	for (node_iterator I = begin(), E = end(); I != E; ++I) {
452bf215546Sopenharmony_ci		node *n = *I;
453bf215546Sopenharmony_ci		if (n->is_container()) {
454bf215546Sopenharmony_ci			static_cast<container_node*>(n)->collect_stats(s);
455bf215546Sopenharmony_ci		}
456bf215546Sopenharmony_ci
457bf215546Sopenharmony_ci		if (n->is_alu_inst()) {
458bf215546Sopenharmony_ci			++s.alu_count;
459bf215546Sopenharmony_ci			alu_node *a = static_cast<alu_node*>(n);
460bf215546Sopenharmony_ci			if (a->bc.op_ptr->flags & AF_KILL)
461bf215546Sopenharmony_ci				++s.alu_kill_count;
462bf215546Sopenharmony_ci			else if (a->is_copy_mov())
463bf215546Sopenharmony_ci				++s.alu_copy_mov_count;
464bf215546Sopenharmony_ci                       if (a->uses_ar())
465bf215546Sopenharmony_ci                          s.uses_ar = true;
466bf215546Sopenharmony_ci		} else if (n->is_fetch_inst())
467bf215546Sopenharmony_ci			++s.fetch_count;
468bf215546Sopenharmony_ci		else if (n->is_cf_inst())
469bf215546Sopenharmony_ci			++s.cf_count;
470bf215546Sopenharmony_ci		else if (n->is_region()) {
471bf215546Sopenharmony_ci			++s.region_count;
472bf215546Sopenharmony_ci			region_node *r = static_cast<region_node*>(n);
473bf215546Sopenharmony_ci			if(r->is_loop())
474bf215546Sopenharmony_ci				++s.loop_count;
475bf215546Sopenharmony_ci
476bf215546Sopenharmony_ci			if (r->phi)
477bf215546Sopenharmony_ci				s.phi_count += r->phi->count();
478bf215546Sopenharmony_ci			if (r->loop_phi)
479bf215546Sopenharmony_ci				s.loop_phi_count += r->loop_phi->count();
480bf215546Sopenharmony_ci		}
481bf215546Sopenharmony_ci		else if (n->is_depart())
482bf215546Sopenharmony_ci			++s.depart_count;
483bf215546Sopenharmony_ci		else if (n->is_repeat())
484bf215546Sopenharmony_ci			++s.repeat_count;
485bf215546Sopenharmony_ci		else if (n->is_if())
486bf215546Sopenharmony_ci			++s.if_count;
487bf215546Sopenharmony_ci	}
488bf215546Sopenharmony_ci}
489bf215546Sopenharmony_ci
490bf215546Sopenharmony_civoid region_node::expand_depart(depart_node *d) {
491bf215546Sopenharmony_ci	depart_vec::iterator I = departs.begin() + d->dep_id, E;
492bf215546Sopenharmony_ci	I = departs.erase(I);
493bf215546Sopenharmony_ci	E = departs.end();
494bf215546Sopenharmony_ci	while (I != E) {
495bf215546Sopenharmony_ci		--(*I)->dep_id;
496bf215546Sopenharmony_ci		++I;
497bf215546Sopenharmony_ci	}
498bf215546Sopenharmony_ci	d->expand();
499bf215546Sopenharmony_ci}
500bf215546Sopenharmony_ci
501bf215546Sopenharmony_civoid region_node::expand_repeat(repeat_node *r) {
502bf215546Sopenharmony_ci	repeat_vec::iterator I = repeats.begin() + r->rep_id - 1, E;
503bf215546Sopenharmony_ci	I = repeats.erase(I);
504bf215546Sopenharmony_ci	E = repeats.end();
505bf215546Sopenharmony_ci	while (I != E) {
506bf215546Sopenharmony_ci		--(*I)->rep_id;
507bf215546Sopenharmony_ci		++I;
508bf215546Sopenharmony_ci	}
509bf215546Sopenharmony_ci	r->expand();
510bf215546Sopenharmony_ci}
511bf215546Sopenharmony_ci
512bf215546Sopenharmony_civoid node_stats::dump() {
513bf215546Sopenharmony_ci	sblog << "  alu_count : " << alu_count << "\n";
514bf215546Sopenharmony_ci	sblog << "  alu_kill_count : " << alu_kill_count << "\n";
515bf215546Sopenharmony_ci	sblog << "  alu_copy_mov_count : " << alu_copy_mov_count << "\n";
516bf215546Sopenharmony_ci	sblog << "  cf_count : " << cf_count << "\n";
517bf215546Sopenharmony_ci	sblog << "  fetch_count : " << fetch_count << "\n";
518bf215546Sopenharmony_ci	sblog << "  region_count : " << region_count << "\n";
519bf215546Sopenharmony_ci	sblog << "  loop_count : " << loop_count << "\n";
520bf215546Sopenharmony_ci	sblog << "  phi_count : " << phi_count << "\n";
521bf215546Sopenharmony_ci	sblog << "  loop_phi_count : " << loop_phi_count << "\n";
522bf215546Sopenharmony_ci	sblog << "  depart_count : " << depart_count << "\n";
523bf215546Sopenharmony_ci	sblog << "  repeat_count : " << repeat_count << "\n";
524bf215546Sopenharmony_ci	sblog << "  if_count : " << if_count << "\n";
525bf215546Sopenharmony_ci}
526bf215546Sopenharmony_ci
527bf215546Sopenharmony_ciunsigned alu_node::interp_param() {
528bf215546Sopenharmony_ci	if (!(bc.op_ptr->flags & AF_INTERP))
529bf215546Sopenharmony_ci		return 0;
530bf215546Sopenharmony_ci	unsigned param;
531bf215546Sopenharmony_ci	if (bc.op_ptr->src_count == 2) {
532bf215546Sopenharmony_ci		param = src[1]->select.sel();
533bf215546Sopenharmony_ci	} else {
534bf215546Sopenharmony_ci		param = src[0]->select.sel();
535bf215546Sopenharmony_ci	}
536bf215546Sopenharmony_ci	return param + 1;
537bf215546Sopenharmony_ci}
538bf215546Sopenharmony_ci
539bf215546Sopenharmony_cialu_group_node* alu_node::get_alu_group_node() {
540bf215546Sopenharmony_ci	node *p = parent;
541bf215546Sopenharmony_ci	if (p) {
542bf215546Sopenharmony_ci		if (p->subtype == NST_ALU_PACKED_INST) {
543bf215546Sopenharmony_ci			assert(p->parent && p->parent->subtype == NST_ALU_GROUP);
544bf215546Sopenharmony_ci			p = p->parent;
545bf215546Sopenharmony_ci		}
546bf215546Sopenharmony_ci		return static_cast<alu_group_node*>(p);
547bf215546Sopenharmony_ci	}
548bf215546Sopenharmony_ci	return NULL;
549bf215546Sopenharmony_ci}
550bf215546Sopenharmony_ci
551bf215546Sopenharmony_ci} // namespace r600_sb
552