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             auto gpr = new GPRValue(base + i, j);
284             /* If we want to use sb, we have to keep arrays
285              * alife for the whole shader range, otherwise the sb scheduler
286              * thinks is not capable to rename non-array uses of these registers */
287             gpr->set_as_input();
288             gpr->set_keep_alive();
289             m_values[i].set_reg_i(j, PValue(gpr));
290 
291          }
292       }
293    }
294 }
295 
sel() const296 uint32_t GPRArray::sel() const
297 {
298    return m_base_index;
299 }
300 
301 static const char *compchar = "xyzw";
do_print(std::ostream & os) const302 void GPRArray::do_print(std::ostream& os) const
303 {
304    os << "ARRAY[R" << sel() << "..R" << sel() + m_values.size()  - 1 << "].";
305    for (int j = 0; j < 4; ++j) {
306       if (m_component_mask & (1 << j))
307          os << compchar[j];
308    }
309 }
310 
is_equal_to(const Value & other) const311 bool GPRArray::is_equal_to(const Value& other) const
312 {
313    const GPRArray& o = static_cast<const GPRArray&>(other);
314    return o.sel() == sel() &&
315          o.m_values.size() == m_values.size() &&
316          o.m_component_mask == m_component_mask;
317 }
318 
sel() const319 uint32_t GPRArrayValue::sel() const
320 {
321    return m_value->sel();
322 }
323 
get_indirect(unsigned index,PValue indirect,unsigned component)324 PValue GPRArray::get_indirect(unsigned index, PValue indirect, unsigned component)
325 {
326    assert(index < m_values.size());
327    assert(m_component_mask & (1 << (component + m_frac)));
328 
329    sfn_log << SfnLog::reg << "Create indirect register from " << *this;
330 
331    PValue v = m_values[index].reg_i(component + m_frac);
332    assert(v);
333 
334    sfn_log << SfnLog::reg << " ->  " << *v;
335 
336    if (indirect) {
337       sfn_log << SfnLog::reg << "["  << *indirect << "]";
338       switch (indirect->type()) {
339       case Value::literal: {
340          const LiteralValue& lv = static_cast<const LiteralValue&>(*indirect);
341          v = m_values[lv.value()].reg_i(component + m_frac);
342          break;
343       }
344       case Value::gpr:  {
345          v = PValue(new GPRArrayValue(v, indirect, this));
346          sfn_log << SfnLog::reg << "(" << *v << ")";
347          break;
348       }
349       default:
350          assert(0 && !"Indirect addressing must be literal value or GPR");
351       }
352    }
353    sfn_log << SfnLog::reg <<"  -> " << *v << "\n";
354    return v;
355 }
356 
record_read(LiverangeEvaluator & ev,int chan) const357 void GPRArray::record_read(LiverangeEvaluator& ev, int chan) const
358 {
359    for (auto& v: m_values)
360       ev.record_read(*v.reg_i(chan), true);
361 }
362 
record_write(LiverangeEvaluator & ev,int chan) const363 void GPRArray::record_write(LiverangeEvaluator& ev, int chan) const
364 {
365    for (auto& v: m_values)
366       ev.record_write(*v.reg_i(chan), true);
367 }
368 
collect_registers(ValueMap & output) const369 void GPRArray::collect_registers(ValueMap& output) const
370 {
371    for (auto& v: m_values) {
372       for (int i = 0; i < 4; ++i) {
373          auto vv = v.reg_i(i);
374          if (vv)
375             output.insert(vv);
376       }
377    }
378 }
379 
380 }
381