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
GPRValue(uint32_t sel,uint32_t chan,int base_offset)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 m_pin_to_channel(false),
43 m_keep_alive(false)
44 {
45 }
46
GPRValue(uint32_t sel,uint32_t chan)47 GPRValue::GPRValue(uint32_t sel, uint32_t chan):
48 Value(Value::gpr, chan),
49 m_sel(sel),
50 m_base_offset(0),
51 m_input(false),
52 m_pin_to_channel(false),
53 m_keep_alive(false)
54 {
55 }
56
sel() const57 uint32_t GPRValue::sel() const
58 {
59 return m_sel;
60 }
61
do_print(std::ostream & os) const62 void GPRValue::do_print(std::ostream& os) const
63 {
64 os << 'R';
65 os << m_sel;
66 os << '.' << component_names[chan()];
67 }
68
is_equal_to(const Value & other) const69 bool GPRValue::is_equal_to(const Value& other) const
70 {
71 assert(other.type() == Value::Type::gpr);
72 const auto& rhs = static_cast<const GPRValue&>(other);
73 return (sel() == rhs.sel() &&
74 chan() == rhs.chan());
75 }
76
do_print(std::ostream & os,UNUSED const PrintFlags & flags) const77 void GPRValue::do_print(std::ostream& os, UNUSED const PrintFlags& flags) const
78 {
79 os << 'R';
80 os << m_sel;
81 os << '.' << component_names[chan()];
82 }
83
GPRVector(const GPRVector & orig)84 GPRVector::GPRVector(const GPRVector& orig):
85 Value(gpr_vector),
86 m_elms(orig.m_elms),
87 m_valid(orig.m_valid)
88 {
89 }
90
GPRVector(std::array<PValue,4> elms)91 GPRVector::GPRVector(std::array<PValue,4> elms):
92 Value(gpr_vector),
93 m_elms(elms),
94 m_valid(false)
95 {
96 for (unsigned i = 0; i < 4; ++i)
97 if (!m_elms[i] || (m_elms[i]->type() != Value::gpr)) {
98 assert(0 && "GPR vector not valid because element missing or nit a GPR");
99 return;
100 }
101 unsigned sel = m_elms[0]->sel();
102 for (unsigned i = 1; i < 4; ++i)
103 if (m_elms[i]->sel() != sel) {
104 assert(0 && "GPR vector not valid because sel is not equal for all elements");
105 return;
106 }
107 m_valid = true;
108 }
109
GPRVector(uint32_t sel,std::array<uint32_t,4> swizzle)110 GPRVector::GPRVector(uint32_t sel, std::array<uint32_t,4> swizzle):
111 Value (gpr_vector),
112 m_valid(true)
113 {
114 for (int i = 0; i < 4; ++i)
115 m_elms[i] = PValue(new GPRValue(sel, swizzle[i]));
116 }
117
GPRVector(const GPRVector & orig,const std::array<uint8_t,4> & swizzle)118 GPRVector::GPRVector(const GPRVector& orig, const std::array<uint8_t,4>& swizzle)
119 {
120 for (int i = 0; i < 4; ++i)
121 m_elms[i] = orig.reg_i(swizzle[i]);
122 m_valid = orig.m_valid;
123 }
124
validate() const125 void GPRVector::validate() const
126 {
127 assert(m_elms[0]);
128 uint32_t sel = m_elms[0]->sel();
129 if (sel >= 124)
130 return;
131
132 for (unsigned i = 1; i < 4; ++i) {
133 assert(m_elms[i]);
134 if (sel != m_elms[i]->sel())
135 return;
136 }
137
138 m_valid = true;
139 }
140
sel() const141 uint32_t GPRVector::sel() const
142 {
143 validate();
144 assert(m_valid);
145 return m_elms[0] ? m_elms[0]->sel() : 999;
146 }
147
set_reg_i(int i,PValue reg)148 void GPRVector::set_reg_i(int i, PValue reg)
149 {
150 m_elms[i] = reg;
151 }
152
pin_to_channel(int i)153 void GPRVector::pin_to_channel(int i)
154 {
155 auto& v = static_cast<GPRValue&>(*m_elms[i]);
156 v.set_pin_to_channel();
157 }
158
pin_all_to_channel()159 void GPRVector::pin_all_to_channel()
160 {
161 for (auto& v: m_elms) {
162 auto& c = static_cast<GPRValue&>(*v);
163 c.set_pin_to_channel();
164 }
165 }
166
do_print(std::ostream & os) const167 void GPRVector::do_print(std::ostream& os) const
168 {
169 os << "R" << sel() << ".";
170 for (int i = 0; i < 4; ++i)
171 os << (m_elms[i] ? component_names[m_elms[i]->chan() < 8 ? m_elms[i]->chan() : 8] : '?');
172 }
173
swizzle(const Swizzle & swz)174 void GPRVector::swizzle(const Swizzle& swz)
175 {
176 Values v(m_elms);
177 for (uint32_t i = 0; i < 4; ++i)
178 if (i != swz[i]) {
179 assert(swz[i] < 4);
180 m_elms[i] = v[swz[i]];
181 }
182 }
183
is_equal_to(const Value & other) const184 bool GPRVector::is_equal_to(const Value& other) const
185 {
186 if (other.type() != gpr_vector) {
187 std::cerr << "t";
188 return false;
189 }
190
191 const GPRVector& o = static_cast<const GPRVector&>(other);
192
193 for (int i = 0; i < 4; ++i) {
194 if (*m_elms[i] != *o.m_elms[i]) {
195 std::cerr << "elm" << i;
196 return false;
197 }
198 }
199 return true;
200 }
201
202
GPRArrayValue(PValue value,PValue addr,GPRArray * array)203 GPRArrayValue::GPRArrayValue(PValue value, PValue addr, GPRArray *array):
204 Value(gpr_array_value, value->chan()),
205 m_value(value),
206 m_addr(addr),
207 m_array(array)
208 {
209 }
210
GPRArrayValue(PValue value,GPRArray * array)211 GPRArrayValue::GPRArrayValue(PValue value, GPRArray *array):
212 Value(gpr_array_value, value->chan()),
213 m_value(value),
214 m_array(array)
215 {
216 }
217
218 static const char *swz_char = "xyzw01_";
219
do_print(std::ostream & os) const220 void GPRArrayValue::do_print(std::ostream& os) const
221 {
222 assert(m_array);
223 os << "R" << m_value->sel();
224 if (m_addr) {
225 os << "[" << *m_addr << "] ";
226 }
227 os << swz_char[m_value->chan()];
228
229 os << "(" << *m_array << ")";
230 }
231
is_equal_to(const Value & other) const232 bool GPRArrayValue::is_equal_to(const Value& other) const
233 {
234 const GPRArrayValue& v = static_cast<const GPRArrayValue&>(other);
235
236 return *m_value == *v.m_value &&
237 *m_array == *v.m_array;
238 }
239
record_read(LiverangeEvaluator & ev) const240 void GPRArrayValue::record_read(LiverangeEvaluator& ev) const
241 {
242 if (m_addr) {
243 ev.record_read(*m_addr);
244 unsigned chan = m_value->chan();
245 assert(m_array);
246 m_array->record_read(ev, chan);
247 } else
248 ev.record_read(*m_value);
249 }
250
record_write(LiverangeEvaluator & ev) const251 void GPRArrayValue::record_write(LiverangeEvaluator& ev) const
252 {
253 if (m_addr) {
254 ev.record_read(*m_addr);
255 unsigned chan = m_value->chan();
256 assert(m_array);
257 m_array->record_write(ev, chan);
258 } else
259 ev.record_write(*m_value);
260 }
261
reset_value(PValue new_value)262 void GPRArrayValue::reset_value(PValue new_value)
263 {
264 m_value = new_value;
265 }
266
reset_addr(PValue new_addr)267 void GPRArrayValue::reset_addr(PValue new_addr)
268 {
269 m_addr = new_addr;
270 }
271
272
GPRArray(int base,int size,int mask,int frac)273 GPRArray::GPRArray(int base, int size, int mask, int frac):
274 Value (gpr_vector),
275 m_base_index(base),
276 m_component_mask(mask),
277 m_frac(frac)
278 {
279 m_values.resize(size);
280 for (int i = 0; i < size; ++i) {
281 for (int j = 0; j < 4; ++j) {
282 if (mask & (1 << j))
283 m_values[i].set_reg_i(j, PValue(new GPRValue(base + i, j)));
284 }
285 }
286 }
287
sel() const288 uint32_t GPRArray::sel() const
289 {
290 return m_base_index;
291 }
292
293 static const char *compchar = "xyzw";
do_print(std::ostream & os) const294 void GPRArray::do_print(std::ostream& os) const
295 {
296 os << "ARRAY[R" << sel() << "..R" << sel() + m_values.size() - 1 << "].";
297 for (int j = 0; j < 4; ++j) {
298 if (m_component_mask & (1 << j))
299 os << compchar[j];
300 }
301 }
302
is_equal_to(const Value & other) const303 bool GPRArray::is_equal_to(const Value& other) const
304 {
305 const GPRArray& o = static_cast<const GPRArray&>(other);
306 return o.sel() == sel() &&
307 o.m_values.size() == m_values.size() &&
308 o.m_component_mask == m_component_mask;
309 }
310
sel() const311 uint32_t GPRArrayValue::sel() const
312 {
313 return m_value->sel();
314 }
315
get_indirect(unsigned index,PValue indirect,unsigned component)316 PValue GPRArray::get_indirect(unsigned index, PValue indirect, unsigned component)
317 {
318 assert(index < m_values.size());
319 assert(m_component_mask & (1 << (component + m_frac)));
320
321 sfn_log << SfnLog::reg << "Create indirect register from " << *this;
322
323 PValue v = m_values[index].reg_i(component + m_frac);
324 assert(v);
325
326 sfn_log << SfnLog::reg << " -> " << *v;
327
328 if (indirect) {
329 sfn_log << SfnLog::reg << "[" << *indirect << "]";
330 switch (indirect->type()) {
331 case Value::literal: {
332 const LiteralValue& lv = static_cast<const LiteralValue&>(*indirect);
333 v = m_values[lv.value()].reg_i(component + m_frac);
334 break;
335 }
336 case Value::gpr: {
337 v = PValue(new GPRArrayValue(v, indirect, this));
338 sfn_log << SfnLog::reg << "(" << *v << ")";
339 break;
340 }
341 default:
342 assert(0 && !"Indirect addressing must be literal value or GPR");
343 }
344 }
345 sfn_log << SfnLog::reg <<" -> " << *v << "\n";
346 return v;
347 }
348
record_read(LiverangeEvaluator & ev,int chan) const349 void GPRArray::record_read(LiverangeEvaluator& ev, int chan) const
350 {
351 for (auto& v: m_values)
352 ev.record_read(*v.reg_i(chan), true);
353 }
354
record_write(LiverangeEvaluator & ev,int chan) const355 void GPRArray::record_write(LiverangeEvaluator& ev, int chan) const
356 {
357 for (auto& v: m_values)
358 ev.record_write(*v.reg_i(chan), true);
359 }
360
collect_registers(ValueMap & output) const361 void GPRArray::collect_registers(ValueMap& output) const
362 {
363 for (auto& v: m_values) {
364 for (int i = 0; i < 4; ++i) {
365 auto vv = v.reg_i(i);
366 if (vv)
367 output.insert(vv);
368 }
369 }
370 }
371
372 }
373