Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 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 GVN_DEBUG 0
28
 
29
#if GVN_DEBUG
30
#define GVN_DUMP(q) do { q } while (0)
31
#else
32
#define GVN_DUMP(q)
33
#endif
34
 
35
#include "sb_shader.h"
36
#include "sb_pass.h"
37
#include "sb_sched.h"
38
 
39
namespace r600_sb {
40
 
41
bool gvn::visit(node& n, bool enter) {
42
	if (enter) {
43
 
44
 
45
		bool rewrite = true;
46
 
47
		if (n.dst[0]->is_agpr()) {
48
			rewrite = false;
49
		}
50
 
51
 
52
		process_op(n, rewrite);
53
 
54
		assert(n.parent);
55
 
56
		if (n.parent->subtype == NST_LOOP_PHI_CONTAINER) {
57
			// There is a problem - sometimes with nested loops
58
			// loop counter initialization for inner loop is incorrectly hoisted
59
			// out of the outer loop
60
 
61
			// FIXME not sure if this is enough to fix a problem completely,
62
			// possibly more complete fix is needed (anyway, the
63
			// problem was seen only in relatively complex
64
			// case involving nested loops and
65
			// indirect access to loop counters (without proper array info
66
			// loop counters may be considered as array elements too),
67
			// was not seen in any tests
68
			// or real apps when proper array information is available in TGSI).
69
 
70
			// For now just mark the instructions that initialize loop counters
71
			// with DONT_HOIST flag to prevent the insts like MOV r, 0
72
			// (initialization of inner loop's counter with const)
73
			// from being hoisted out of the outer loop
74
 
75
			assert(!n.src.empty());
76
			value *v = n.src[0];
77
 
78
			if (v->is_any_gpr() && v->def)
79
				v->def->flags |= NF_DONT_HOIST;
80
		}
81
 
82
	} else {
83
	}
84
	return true;
85
}
86
 
87
bool gvn::visit(cf_node& n, bool enter) {
88
	if (enter) {
89
		process_op(n);
90
	} else {
91
	}
92
	return true;
93
}
94
 
95
bool gvn::visit(alu_node& n, bool enter) {
96
	if (enter) {
97
		process_op(n);
98
	} else {
99
	}
100
	return true;
101
}
102
 
103
bool gvn::visit(alu_packed_node& n, bool enter) {
104
	if (enter) {
105
		process_op(n);
106
	} else {
107
	}
108
	return false;
109
}
110
 
111
bool gvn::visit(fetch_node& n, bool enter) {
112
	if (enter) {
113
		process_op(n);
114
	} else {
115
	}
116
	return true;
117
}
118
 
119
bool gvn::visit(region_node& n, bool enter) {
120
	if (enter) {
121
// FIXME: loop_phi sources are undefined yet (except theone from the preceding
122
// code), can we handle that somehow?
123
//		if (n.loop_phi)
124
//			run_on(*n.loop_phi);
125
	} else {
126
		if (n.loop_phi)
127
			run_on(*n.loop_phi);
128
 
129
		if (n.phi)
130
			run_on(*n.phi);
131
	}
132
	return true;
133
}
134
 
135
bool gvn::process_src(value* &v, bool rewrite) {
136
	if (!v->gvn_source)
137
		sh.vt.add_value(v);
138
 
139
	if (rewrite && !v->gvn_source->is_rel()) {
140
		v = v->gvn_source;
141
		return true;
142
	}
143
	return false;
144
}
145
 
146
// FIXME: maybe handle it in the scheduler?
147
void gvn::process_alu_src_constants(node &n, value* &v) {
148
	if (n.src.size() < 3) {
149
		process_src(v, true);
150
		return;
151
	}
152
 
153
	if (!v->gvn_source)
154
		sh.vt.add_value(v);
155
 
156
	rp_kcache_tracker kc(sh);
157
 
158
	if (v->gvn_source->is_kcache())
159
		kc.try_reserve(v->gvn_source->select);
160
 
161
	// don't propagate 3rd constant to the trans-only instruction
162
	if (!n.is_alu_packed()) {
163
		alu_node *a = static_cast(&n);
164
		if (a->bc.op_ptr->src_count == 3 && !(a->bc.slot_flags & AF_V)) {
165
			unsigned const_count = 0;
166
			for (vvec::iterator I = n.src.begin(), E = n.src.end(); I != E;
167
					++I) {
168
				value *c = (*I);
169
				if (c && c->is_readonly() && ++const_count == 2) {
170
					process_src(v, false);
171
					return;
172
				}
173
			}
174
		}
175
	}
176
 
177
	for (vvec::iterator I = n.src.begin(), E = n.src.end(); I != E; ++I) {
178
		value *c = (*I);
179
 
180
		if (c->is_kcache() && !kc.try_reserve(c->select)) {
181
			process_src(v, false);
182
			return;
183
		}
184
	}
185
	process_src(v, true);
186
}
187
 
188
void gvn::process_op(node& n, bool rewrite) {
189
 
190
	for(vvec::iterator I = n.src.begin(), E = n.src.end(); I != E; ++I) {
191
		value* &v = *I;
192
		if (v) {
193
			if (v->rel) {
194
				process_src(v->rel, rewrite);
195
			}
196
 
197
			if (rewrite && v->gvn_source && v->gvn_source->is_readonly() &&
198
					n.is_any_alu()) {
199
				process_alu_src_constants(n, v);
200
			} else if (rewrite && v->gvn_source && v->gvn_source->is_const() &&
201
					(n.is_fetch_op(FETCH_OP_VFETCH) ||
202
							n.is_fetch_op(FETCH_OP_SEMFETCH)))
203
				process_src(v, false);
204
			else
205
				process_src(v, rewrite);
206
		}
207
	}
208
	if (n.pred)
209
		process_src(n.pred, false);
210
 
211
	if (n.type == NT_IF) {
212
		if_node &i = (if_node&)n;
213
		if (i.cond)
214
			process_src(i.cond, false);
215
	}
216
 
217
	for(vvec::iterator I = n.dst.begin(), E = n.dst.end(); I != E; ++I) {
218
		value *v = *I;
219
		if (v) {
220
			if (v->rel)
221
				process_src(v->rel, rewrite);
222
			sh.vt.add_value(v);
223
		}
224
	}
225
}
226
 
227
} // namespace r600_sb