r600/sfn: add live range evaluation for the GPR
[mesa.git] / src / gallium / drivers / r600 / sfn / sfn_value_gpr.cpp
1 /* -*- mesa-c++ -*-
2 *
3 * Copyright (c) 2018-2019 Collabora LTD
4 *
5 * Author: Gert Wollny <gert.wollny@collabora.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * on the rights to use, copy, modify, merge, publish, distribute, sub
11 * license, and/or sell copies of the Software, and to permit persons to whom
12 * the Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27 #include "sfn_value_gpr.h"
28 #include "sfn_valuepool.h"
29 #include "sfn_debug.h"
30 #include "sfn_liverange.h"
31
32 namespace r600 {
33
34 using std::vector;
35 using std::array;
36
37 GPRValue::GPRValue(uint32_t sel, uint32_t chan, int base_offset):
38 Value(Value::gpr, chan),
39 m_sel(sel),
40 m_base_offset(base_offset),
41 m_input(false)
42 {
43 }
44
45 GPRValue::GPRValue(uint32_t sel, uint32_t chan):
46 Value(Value::gpr, chan),
47 m_sel(sel),
48 m_base_offset(0),
49 m_input(false)
50 {
51 }
52
53 uint32_t GPRValue::sel() const
54 {
55 return m_sel;
56 }
57
58 void GPRValue::do_print(std::ostream& os) const
59 {
60 os << 'R';
61 os << m_sel;
62 os << '.' << component_names[chan()];
63 }
64
65 bool GPRValue::is_equal_to(const Value& other) const
66 {
67 assert(other.type() == Value::Type::gpr);
68 const auto& rhs = static_cast<const GPRValue&>(other);
69 return (sel() == rhs.sel() &&
70 chan() == rhs.chan());
71 }
72
73 void GPRValue::do_print(std::ostream& os, UNUSED const PrintFlags& flags) const
74 {
75 os << 'R';
76 os << m_sel;
77 os << '.' << component_names[chan()];
78 }
79
80 GPRVector::GPRVector(const GPRVector& orig):
81 Value(gpr_vector),
82 m_elms(orig.m_elms),
83 m_valid(orig.m_valid)
84 {
85 }
86
87 GPRVector::GPRVector(std::array<PValue,4> elms):
88 Value(gpr_vector),
89 m_elms(elms),
90 m_valid(false)
91 {
92 for (unsigned i = 0; i < 4; ++i)
93 if (!m_elms[i] || (m_elms[i]->type() != Value::gpr)) {
94 assert(0 && "GPR vector not valid because element missing or nit a GPR");
95 return;
96 }
97 unsigned sel = m_elms[0]->sel();
98 for (unsigned i = 1; i < 4; ++i)
99 if (m_elms[i]->sel() != sel) {
100 assert(0 && "GPR vector not valid because sel is not equal for all elements");
101 return;
102 }
103 m_valid = true;
104 }
105
106 GPRVector::GPRVector(uint32_t sel, std::array<uint32_t,4> swizzle):
107 Value (gpr_vector),
108 m_valid(true)
109 {
110 for (int i = 0; i < 4; ++i)
111 m_elms[i] = PValue(new GPRValue(sel, swizzle[i]));
112 }
113
114 GPRVector::GPRVector(const GPRVector& orig, const std::array<uint8_t,4>& swizzle)
115 {
116 for (int i = 0; i < 4; ++i)
117 m_elms[i] = orig.reg_i(swizzle[i]);
118 m_valid = orig.m_valid;
119 }
120
121 void GPRVector::validate() const
122 {
123 assert(m_elms[0]);
124 uint32_t sel = m_elms[0]->sel();
125 if (sel >= 124)
126 return;
127
128 for (unsigned i = 1; i < 4; ++i) {
129 assert(m_elms[i]);
130 if (sel != m_elms[i]->sel())
131 return;
132 }
133
134 m_valid = true;
135 }
136
137 uint32_t GPRVector::sel() const
138 {
139 validate();
140 assert(m_valid);
141 return m_elms[0] ? m_elms[0]->sel() : 999;
142 }
143
144 void GPRVector::set_reg_i(int i, PValue reg)
145 {
146 m_elms[i] = reg;
147 }
148
149 void GPRVector::do_print(std::ostream& os) const
150 {
151 os << "R" << sel() << ".";
152 for (int i = 0; i < 4; ++i)
153 os << (m_elms[i] ? component_names[m_elms[i]->chan() < 8 ? m_elms[i]->chan() : 8] : '?');
154 }
155
156 void GPRVector::swizzle(const Swizzle& swz)
157 {
158 Values v(m_elms);
159 for (uint32_t i = 0; i < 4; ++i)
160 if (i != swz[i]) {
161 assert(swz[i] < 4);
162 m_elms[i] = v[swz[i]];
163 }
164 }
165
166 bool GPRVector::is_equal_to(const Value& other) const
167 {
168 if (other.type() != gpr_vector) {
169 std::cerr << "t";
170 return false;
171 }
172
173 const GPRVector& o = static_cast<const GPRVector&>(other);
174
175 for (int i = 0; i < 4; ++i) {
176 if (*m_elms[i] != *o.m_elms[i]) {
177 std::cerr << "elm" << i;
178 return false;
179 }
180 }
181 return true;
182 }
183
184
185 GPRArrayValue::GPRArrayValue(PValue value, PValue addr, GPRArray *array):
186 Value(gpr_array_value, value->chan()),
187 m_value(value),
188 m_addr(addr),
189 m_array(array)
190 {
191 }
192
193 GPRArrayValue::GPRArrayValue(PValue value, GPRArray *array):
194 Value(gpr_array_value, value->chan()),
195 m_value(value),
196 m_array(array)
197 {
198 }
199
200 static const char *swz_char = "xyzw01_";
201
202 void GPRArrayValue::do_print(std::ostream& os) const
203 {
204 assert(m_array);
205 os << "R" << m_value->sel();
206 if (m_addr) {
207 os << "[" << *m_addr << "] ";
208 }
209 os << swz_char[m_value->chan()];
210
211 os << "(" << *m_array << ")";
212 }
213
214 bool GPRArrayValue::is_equal_to(const Value& other) const
215 {
216 const GPRArrayValue& v = static_cast<const GPRArrayValue&>(other);
217
218 return *m_value == *v.m_value &&
219 *m_array == *v.m_array;
220 }
221
222 void GPRArrayValue::record_read(LiverangeEvaluator& ev) const
223 {
224 if (m_addr) {
225 ev.record_read(*m_addr);
226 unsigned chan = m_value->chan();
227 assert(m_array);
228 m_array->record_read(ev, chan);
229 } else
230 ev.record_read(*m_value);
231 }
232
233 void GPRArrayValue::record_write(LiverangeEvaluator& ev) const
234 {
235 if (m_addr) {
236 ev.record_read(*m_addr);
237 unsigned chan = m_value->chan();
238 assert(m_array);
239 m_array->record_write(ev, chan);
240 } else
241 ev.record_write(*m_value);
242 }
243
244 void GPRArrayValue::reset_value(PValue new_value)
245 {
246 m_value = new_value;
247 }
248
249 void GPRArrayValue::reset_addr(PValue new_addr)
250 {
251 m_addr = new_addr;
252 }
253
254
255 GPRArray::GPRArray(int base, int size, int mask, int frac):
256 Value (gpr_vector),
257 m_base_index(base),
258 m_component_mask(mask),
259 m_frac(frac)
260 {
261 m_values.resize(size);
262 for (int i = 0; i < size; ++i) {
263 for (int j = 0; j < 4; ++j) {
264 if (mask & (1 << j))
265 m_values[i].set_reg_i(j, PValue(new GPRValue(base + i, j)));
266 }
267 }
268 }
269
270 uint32_t GPRArray::sel() const
271 {
272 return m_base_index;
273 }
274
275 static const char *compchar = "xyzw";
276 void GPRArray::do_print(std::ostream& os) const
277 {
278 os << "ARRAY[R" << sel() << "..R" << sel() + m_values.size() - 1 << "].";
279 for (int j = 0; j < 4; ++j) {
280 if (m_component_mask & (1 << j))
281 os << compchar[j];
282 }
283 }
284
285 bool GPRArray::is_equal_to(const Value& other) const
286 {
287 const GPRArray& o = dynamic_cast<const GPRArray&>(other);
288 return o.sel() == sel() &&
289 o.m_values.size() == m_values.size() &&
290 o.m_component_mask == m_component_mask;
291 }
292
293 uint32_t GPRArrayValue::sel() const
294 {
295 return m_value->sel();
296 }
297
298 PValue GPRArray::get_indirect(unsigned index, PValue indirect, unsigned component)
299 {
300 assert(index < m_values.size());
301 assert(m_component_mask & (1 << (component + m_frac)));
302
303 sfn_log << SfnLog::reg << "Create indirect register from " << *this;
304
305 PValue v = m_values[index].reg_i(component + m_frac);
306 assert(v);
307
308 sfn_log << SfnLog::reg << " -> " << *v;
309
310 if (indirect) {
311 sfn_log << SfnLog::reg << "[" << *indirect << "]";
312 switch (indirect->type()) {
313 case Value::literal: {
314 const LiteralValue& lv = static_cast<const LiteralValue&>(*indirect);
315 v = m_values[lv.value()].reg_i(component + m_frac);
316 break;
317 }
318 case Value::gpr: {
319 v = PValue(new GPRArrayValue(v, indirect, this));
320 sfn_log << SfnLog::reg << "(" << *v << ")";
321 break;
322 }
323 default:
324 assert(0 && !"Indirect addressing must be literal value or GPR");
325 }
326 }
327 sfn_log << SfnLog::reg <<" -> " << *v << "\n";
328 return v;
329 }
330
331 void GPRArray::record_read(LiverangeEvaluator& ev, int chan) const
332 {
333 for (auto& v: m_values)
334 ev.record_read(*v.reg_i(chan), true);
335 }
336
337 void GPRArray::record_write(LiverangeEvaluator& ev, int chan) const
338 {
339 for (auto& v: m_values)
340 ev.record_write(*v.reg_i(chan), true);
341 }
342
343 void GPRArray::collect_registers(ValueMap& output) const
344 {
345 for (auto& v: m_values) {
346 for (int i = 0; i < 4; ++i) {
347 auto vv = v.reg_i(i);
348 if (vv)
349 output.insert(vv);
350 }
351 }
352 }
353
354 }