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
#include "sb_shader.h"
28
 
29
#include "sb_pass.h"
30
 
31
namespace r600_sb {
32
 
33
bool r600_sb::psi_ops::visit(alu_node& n, bool enter) {
34
	if (enter) {
35
	}
36
	return false;
37
}
38
 
39
bool psi_ops::visit(node& n, bool enter) {
40
	if (enter) {
41
		assert(n.subtype == NST_PSI);
42
 
43
		try_inline(n);
44
 
45
		// TODO eliminate predication until there is full support in all passes
46
		// unpredicate instructions and replace psi-nodes with conditional moves
47
		eliminate(n);
48
	}
49
	return false;
50
}
51
 
52
value* get_pred_val(node &n) {
53
	value *pred_val = NULL;
54
 
55
	for (vvec::iterator I = n.src.begin(), E = n.src.end(); I != E; I += 3) {
56
		value* &pred = *I;
57
		if (pred) {
58
			if (!pred_val)
59
				pred_val = pred;
60
			else {
61
				assert(pred == pred_val);
62
			}
63
		}
64
	}
65
	return pred_val;
66
}
67
 
68
// for now we'll never inline psi's with different predicate values,
69
// so psi node may only contain the refs to one predicate value.
70
bool psi_ops::try_inline(node& n) {
71
	assert(n.subtype == NST_PSI);
72
 
73
	vvec &ns = n.src;
74
 
75
	int sz = ns.size();
76
	assert(sz && (sz % 3 == 0));
77
 
78
	value *pred_val = get_pred_val(n);
79
 
80
	int ps_mask = 0;
81
 
82
	bool r = false;
83
 
84
	for (int i = sz - 1; i >= 0; i -= 3) {
85
 
86
		if (ps_mask == 3) {
87
			ns.erase(ns.begin(), ns.begin() + i + 1);
88
			return r;
89
		}
90
 
91
		value* val = ns[i];
92
		value* predsel = ns[i-1];
93
		int ps = !predsel ? 3 : predsel == sh.get_pred_sel(0) ? 1 : 2;
94
 
95
		assert(val->def);
96
 
97
		if (val->def->subtype == NST_PSI && ps == 3) {
98
			if (get_pred_val(*val->def) != pred_val)
99
				continue;
100
 
101
			vvec &ds = val->def->src;
102
 
103
			ns.insert(ns.begin() + i + 1, ds.begin(), ds.end());
104
			ns.erase(ns.begin() + i - 2, ns.begin() + i + 1);
105
			i += ds.size();
106
			r = true;
107
 
108
		} else {
109
			if ((ps_mask & ps) == ps) {
110
				// this predicate select is subsumed by already handled ops
111
				ns.erase(ns.begin() + i - 2, ns.begin() + i + 1);
112
			} else {
113
				ps_mask |= ps;
114
			}
115
		}
116
	}
117
	return r;
118
}
119
 
120
bool psi_ops::try_reduce(node& n) {
121
	assert(n.subtype == NST_PSI);
122
	assert(n.src.size() % 3 == 0);
123
 
124
	// TODO
125
 
126
	return false;
127
}
128
 
129
void psi_ops::unpredicate(node *n) {
130
 
131
	if (!n->is_alu_inst())
132
		return;
133
 
134
	alu_node *a = static_cast(n);
135
	a->pred = NULL;
136
}
137
 
138
bool psi_ops::eliminate(node& n) {
139
	assert(n.subtype == NST_PSI);
140
	assert(n.src.size() == 6);
141
 
142
	value *d = n.dst[0];
143
 
144
	value *s1 = n.src[2];
145
	value *s2 = n.src[5];
146
 
147
	value *pred = n.src[3];
148
 
149
	bool psel = n.src[4] == sh.get_pred_sel(0);
150
 
151
	value *sel = get_select_value_for_em(sh, pred);
152
 
153
	if (s1->is_undef()) {
154
		if (s2->is_undef()) {
155
 
156
		} else {
157
			n.insert_after(sh.create_mov(d, s2));
158
		}
159
	} else if (s2->is_undef()) {
160
		n.insert_after(sh.create_mov(d, s1));
161
	} else {
162
		alu_node *a = sh.create_alu();
163
		a->bc.set_op(ALU_OP3_CNDE_INT);
164
 
165
		a->dst.push_back(d);
166
		a->src.push_back(sel);
167
 
168
		if (psel) {
169
			a->src.push_back(s1);
170
			a->src.push_back(s2);
171
		} else {
172
			a->src.push_back(s2);
173
			a->src.push_back(s1);
174
		}
175
 
176
		n.insert_after(a);
177
	}
178
 
179
	n.remove();
180
 
181
	if (s1->is_any_gpr() && !s1->is_undef() && s1->def)
182
		unpredicate(s1->def);
183
	if (s2->is_any_gpr() && !s2->is_undef() && s2->def)
184
		unpredicate(s2->def);
185
 
186
	return false;
187
}
188
 
189
} // namespace r600_sb