• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- mesa-c++  -*-
2  *
3  * Copyright (c) 2021 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 
28 #include "sfn_valuefactory.h"
29 #include "sfn_instr.h"
30 #include "sfn_debug.h"
31 
32 #include "gallium/drivers/r600/r600_shader.h"
33 
34 #include <iostream>
35 #include <sstream>
36 #include <queue>
37 #include <algorithm>
38 
39 namespace r600 {
40 
41 using std::istringstream;
42 using std::string;
43 
44 
ValueFactory()45 ValueFactory::ValueFactory():
46    m_next_register_index(VirtualValue::virtual_register_base),
47    m_nowrite_idx(0)
48 {
49 }
50 
set_virtual_register_base(int base)51 void ValueFactory::set_virtual_register_base(int base)
52 {
53    m_next_register_index = base;
54 }
55 
allocate_registers(const exec_list * registers)56 bool ValueFactory::allocate_registers(const exec_list *registers)
57 {
58    bool has_arrays = false;
59    struct  array_entry {
60       unsigned index;
61       unsigned length;
62       unsigned ncomponents;
63 
64       bool operator ()(const array_entry& a, const array_entry& b) const {
65          return a.length < b.length || (a.length == b.length && a.ncomponents > b.ncomponents);
66       }
67    };
68 
69    using array_list = std::priority_queue<array_entry, std::vector<array_entry>,
70                                           array_entry>;
71 
72    array_list arrays;
73 
74 
75    foreach_list_typed(nir_register, reg, node, registers) {
76       if (reg->num_array_elems) {
77          array_entry ae = {reg->index, reg->num_array_elems, reg->bit_size / 32 * reg->num_components};
78          arrays.push(ae);
79          has_arrays = true;
80       }
81    }
82 
83    int ncomponents = 0;
84    int sel = m_next_register_index;
85    unsigned length = 0;
86 
87    while (!arrays.empty()) {
88       auto a = arrays.top();
89       arrays.pop();
90 
91       /* This is a bit hackish, return an id that encodes the array merge. To make sure
92        * that the mapping doesn't go wrong we have to make sure the arrays is longer than
93        * the number of instances in this arrays slot */
94       if (a.ncomponents + ncomponents > 4 ||
95           a.length > length) {
96          sel = m_next_register_index;
97          ncomponents = 0;
98          length = 0;
99       }
100 
101       if (ncomponents == 0)
102          m_next_register_index += a.length;
103 
104       uint32_t frac = ncomponents;
105       auto array = new LocalArray( sel, a.ncomponents, a.length, frac);
106 
107       for (unsigned i = 0; i < a.ncomponents; ++i) {
108          RegisterKey key(a.index, i, vp_array);
109          m_channel_counts.inc_count(i);
110          m_registers[key] = array;
111          sfn_log << SfnLog::reg << __func__ << ": Allocate array " << key << ":" << *array << "\n";
112       }
113 
114       ncomponents += a.ncomponents;
115       length = a.length;
116    }
117 
118    foreach_list_typed(nir_register, reg, node, registers) {
119       if (!reg->num_array_elems) {
120          uint32_t sel = m_next_register_index++;
121          unsigned num_components = reg->num_components * reg->bit_size / 32;
122          for (auto chan = 0u; chan < num_components; ++chan) {
123             RegisterKey key(reg->index, chan, vp_register);
124             m_channel_counts.inc_count(chan);
125             m_registers[key] = new Register( sel, chan, num_components > 1 ? pin_none : pin_free);
126             sfn_log << SfnLog::reg << "allocate register " << key << ":" << *m_registers[key] << "\n";
127          }
128       }
129    }
130    return has_arrays;
131 }
132 
allocate_pinned_register(int sel,int chan)133 PRegister ValueFactory::allocate_pinned_register(int sel, int chan)
134 {
135    if (m_next_register_index <= sel)
136       m_next_register_index = sel + 1;
137 
138    auto reg = new Register(sel, chan, pin_fully);
139    m_pinned_registers.push_back(reg);
140    return reg;
141 }
142 
allocate_pinned_vec4(int sel,bool is_ssa)143 RegisterVec4 ValueFactory::allocate_pinned_vec4(int sel, bool is_ssa)
144 {
145    if (m_next_register_index <= sel)
146       m_next_register_index = sel + 1;
147 
148    RegisterVec4 retval(sel, is_ssa, {0,1,2,3}, pin_fully);
149    for (int i = 0; i < 4; ++i)
150       m_pinned_registers.push_back(retval[i]);
151    return retval;
152 }
153 
154 
inject_value(const nir_dest & dest,int chan,PVirtualValue value)155 void ValueFactory::inject_value(const nir_dest& dest, int chan, PVirtualValue value)
156 {
157    assert(dest.is_ssa);
158    RegisterKey key(dest.ssa.index, chan, vp_ssa);
159    sfn_log << SfnLog::reg << "Inject value with key " << key << "\n";
160    assert(m_values.find(key) == m_values.end());
161    m_values[key] = value;
162 }
163 
dest(const nir_alu_dest & dst,int chan,Pin pin_channel)164 PRegister ValueFactory::dest(const nir_alu_dest& dst, int chan,
165                              Pin pin_channel)
166 {
167    sfn_log << SfnLog::reg << "Search (ref) " << &dst << "\n";
168    return dest(dst.dest, chan, pin_channel);
169 }
170 
171 class TranslateRegister: public RegisterVisitor {
172 public:
visit(VirtualValue & value)173    void visit(VirtualValue& value) {(void)value;}
visit(Register & value)174    void visit(Register& value) {(void)value;};
visit(LocalArray & value)175    void visit(LocalArray& value) { m_value = value.element(m_offset, m_addr, m_chan);}
visit(LocalArrayValue & value)176    void visit(LocalArrayValue& value) {(void)value;}
visit(UniformValue & value)177    void visit(UniformValue& value) {(void)value;}
visit(LiteralConstant & value)178    void visit(LiteralConstant& value) {(void)value;}
visit(InlineConstant & value)179    void visit(InlineConstant& value) {(void)value;}
180 
TranslateRegister(int offset,PVirtualValue addr,int chan)181    TranslateRegister(int offset, PVirtualValue addr, int chan): m_addr(addr),
182       m_value(nullptr), m_offset(offset), m_chan(chan) {}
183 
184    PVirtualValue m_addr;
185    PRegister m_value;
186    int m_offset;
187    int m_chan;
188 };
189 
resolve_array(nir_register * reg,nir_src * indirect,int base_offset,int chan)190 PRegister ValueFactory::resolve_array(nir_register *reg, nir_src *indirect,
191                                       int base_offset, int chan)
192 {
193    PVirtualValue addr = nullptr;
194    auto type = reg->num_array_elems ? vp_array : vp_register;
195    RegisterKey key(reg->index, chan, type);
196    auto ireg = m_registers.find(key);
197    if (ireg == m_registers.end()) {
198       std::cerr << "Key " << key << " not found\n";
199       assert(0);
200    }
201 
202    if (reg->num_array_elems) {
203 
204       if (indirect)
205          addr = src(*indirect, 0);
206 
207       TranslateRegister array_resolution(base_offset, addr, chan);
208 
209       ireg->second->accept(array_resolution);
210       assert(array_resolution.m_value);
211       return array_resolution.m_value;
212    } else {
213       return ireg->second;
214    }
215 }
216 
dest(const nir_dest & dst,int chan,Pin pin_channel)217 PRegister ValueFactory::dest(const nir_dest& dst, int chan, Pin pin_channel)
218 {
219    if (dst.is_ssa) {
220       return dest(dst.ssa, chan, pin_channel);
221    } else {
222       return resolve_array(dst.reg.reg, dst.reg.indirect,
223                            dst.reg.base_offset, chan);
224    }
225 }
226 
allocate_const(nir_load_const_instr * load_const)227 void ValueFactory::allocate_const(nir_load_const_instr *load_const)
228 {
229    assert(load_const->def.bit_size == 32);
230    for (int i = 0; i < load_const->def.num_components; ++i) {
231       RegisterKey key(load_const->def.index, i, vp_ssa);
232       m_values[key] = literal(load_const->value[i].i32);
233       sfn_log << SfnLog::reg << "Add const with key " << key << " as " << m_values[key] << "\n";
234    }
235 }
236 
uniform(nir_intrinsic_instr * load_uniform,int chan)237 PVirtualValue ValueFactory::uniform(nir_intrinsic_instr *load_uniform, int chan)
238 {
239    auto literal = nir_src_as_const_value(load_uniform->src[0]);
240    assert(literal);
241 
242    int index = nir_intrinsic_base(load_uniform) +  + literal->u32 + 512;
243 
244    return uniform(index, chan, 0);
245 }
246 
uniform(uint32_t index,int chan,int kcache)247 PVirtualValue ValueFactory::uniform(uint32_t index, int chan, int kcache)
248 {
249    return new UniformValue( index, chan, kcache);
250 }
251 
temp_register(int pinned_channel,bool is_ssa)252 PRegister ValueFactory::temp_register(int pinned_channel, bool is_ssa)
253 {
254    int sel = m_next_register_index++;
255    int chan = (pinned_channel >= 0) ?
256             pinned_channel : m_channel_counts.least_used();
257 
258    auto reg = new Register( sel, chan,
259                             pinned_channel >= 0 ? pin_chan : pin_free);
260    m_channel_counts.inc_count(chan);
261 
262    reg->set_is_ssa(is_ssa);
263    m_registers[RegisterKey(sel, chan, vp_temp)] = reg;
264    return reg;
265 }
266 
temp_vec4(Pin pin,const RegisterVec4::Swizzle & swizzle)267 RegisterVec4 ValueFactory::temp_vec4(Pin pin, const RegisterVec4::Swizzle &swizzle)
268 {
269    int sel = m_next_register_index++;
270 
271    if (pin == pin_free)
272       pin = pin_chan;
273 
274    PRegister vec4[4];
275 
276    for (int i = 0; i < 4; ++i) {
277       vec4[i] = new Register( sel, swizzle[i], pin);
278       vec4[i]->set_is_ssa(true);
279       m_registers[RegisterKey(sel, swizzle[i], vp_temp)] = vec4[i];
280    }
281    return RegisterVec4(vec4[0], vec4[1], vec4[2], vec4[3], pin);
282 }
283 
dest_vec4(const nir_dest & dst,Pin pin)284 RegisterVec4 ValueFactory::dest_vec4(const nir_dest& dst, Pin pin)
285 {
286    if (pin != pin_group && pin != pin_chgr)
287       pin = pin_chan;
288    if (dst.is_ssa) {
289       PRegister x = dest(dst, 0, pin);
290       PRegister y = dest(dst, 1, pin);
291       PRegister z = dest(dst, 2, pin);
292       PRegister w = dest(dst, 3, pin);
293       return RegisterVec4(x, y, z, w, pin);
294    } else {
295       assert(!dst.reg.indirect);
296       PRegister v[4];
297       int sel = -1;
298       for (int i = 0; i < 4; ++i) {
299          RegisterKey key(dst.reg.reg->index, i, vp_register);
300          v[i] = m_registers[key];
301          assert(sel >= 0 || v[i]);
302          if (sel < 0)
303             sel = v[i]->sel();
304 
305          if (!v[i]) {
306             v[i] = m_registers[key] = new Register(sel, i, pin_group);
307          }
308       }
309       return RegisterVec4(v[0], v[1], v[2], v[3], pin);
310    }
311    unreachable("unsupported");
312 }
313 
src(const nir_alu_src & alu_src,int chan)314 PVirtualValue ValueFactory::src(const nir_alu_src& alu_src, int chan)
315 {
316    return src(alu_src.src, alu_src.swizzle[chan]);
317 }
318 
src64(const nir_alu_src & alu_src,int chan,int comp)319 PVirtualValue ValueFactory::src64(const nir_alu_src& alu_src, int chan, int comp)
320 {
321    return src(alu_src.src, 2 * alu_src.swizzle[chan] + comp);
322 }
323 
src(const nir_src & src,int chan)324 PVirtualValue ValueFactory::src(const nir_src& src, int chan)
325 {
326    sfn_log << SfnLog::reg << "search (ref) " << (void *)&src << "\n";
327 
328    if (src.is_ssa) {
329       sfn_log << SfnLog::reg << "search ssa " << src.ssa->index << " c:" << chan << " got ";
330       auto val = ssa_src(*src.ssa, chan);
331       sfn_log << *val << "\n";
332       return val;
333    } else {
334       sfn_log << SfnLog::reg << "search reg " << src.reg.reg->index << "\n";
335       return local_register(src.reg, chan);
336    }
337 }
338 
src(const nir_tex_src & tex_src,int chan)339 PVirtualValue ValueFactory::src(const nir_tex_src& tex_src, int chan)
340 {
341    return src(tex_src.src, chan);
342 }
343 
dummy_dest(unsigned chan)344 PRegister ValueFactory::dummy_dest(unsigned chan)
345 {
346    assert(chan < 4);
347    return m_dummy_dest_pinned[chan];
348 }
349 
350 PRegister
dest(const nir_ssa_def & ssa,int chan,Pin pin_channel)351 ValueFactory::dest(const nir_ssa_def& ssa, int chan, Pin pin_channel)
352 {
353    RegisterKey key(ssa.index, chan, vp_ssa);
354 
355    /* dirty workaround for Cayman trans ops, because we may request
356     * the same sa reg more than once, but only write to it once.  */
357    auto ireg = m_registers.find(key);
358    if (ireg != m_registers.end())
359       return ireg->second;
360 
361    auto isel = m_ssa_index_to_sel.find(ssa.index);
362    int sel;
363    if (isel != m_ssa_index_to_sel.end())
364       sel = isel->second;
365    else {
366       sel = m_next_register_index++;
367       m_ssa_index_to_sel[ssa.index] = sel;
368    }
369 
370    if (pin_channel == pin_free)
371       chan = m_channel_counts.least_used();
372 
373    auto vreg = new Register( sel, chan, pin_channel);
374    m_channel_counts.inc_count(chan);
375    vreg->set_is_ssa(true);
376    m_registers[key] = vreg;
377    sfn_log << SfnLog::reg << "allocate Ssa " << key << ":" << *vreg << "\n";
378    return vreg;
379 }
380 
zero()381 PVirtualValue ValueFactory::zero()
382 {
383    return inline_const(ALU_SRC_0, 0);
384 }
385 
one()386 PVirtualValue ValueFactory::one()
387 {
388    return inline_const(ALU_SRC_1, 0);
389 }
390 
one_i()391 PVirtualValue ValueFactory::one_i()
392 {
393    return inline_const(ALU_SRC_1_INT, 0);
394 }
395 
undef(int index,int chan)396 PRegister ValueFactory::undef(int index, int chan)
397 {
398    RegisterKey key(index, chan, vp_ssa);
399    PRegister reg = new Register(m_next_register_index++, 0, pin_free);
400    reg->set_is_ssa(true);
401    m_registers[key] = reg;
402    return reg;
403 }
404 
405 PVirtualValue
ssa_src(const nir_ssa_def & ssa,int chan)406 ValueFactory::ssa_src(const nir_ssa_def& ssa, int chan)
407 {
408    RegisterKey key(ssa.index, chan, vp_ssa);
409    sfn_log << SfnLog::reg << "search src with key" << key << "\n";
410 
411    auto ireg = m_registers.find(key);
412    if (ireg != m_registers.end())
413       return ireg->second;
414 
415    auto ival = m_values.find(key);
416    if (ival != m_values.end())
417       return ival->second;
418 
419    std::cerr << "Didn't find source with key " << key << "\n";
420    unreachable("Source values should always exist");
421 }
422 
local_register(const nir_reg_dest & dst,int chan)423 PRegister ValueFactory::local_register(const nir_reg_dest& dst, int chan)
424 {
425    return resolve_array(dst.reg, dst.indirect,
426                         dst.base_offset, chan);
427 }
428 
local_register(const nir_reg_src & src,int chan)429 PRegister ValueFactory::local_register(const nir_reg_src& src, int chan)
430 {
431    return resolve_array(src.reg, src.indirect,
432                         src.base_offset, chan);
433 }
434 
literal(uint32_t value)435 PVirtualValue ValueFactory::literal(uint32_t value)
436 {
437    auto iv = m_literal_values.find(value);
438    if (iv != m_literal_values.end())
439       return iv->second;
440 
441    auto v = new LiteralConstant( value);
442    m_literal_values[value] = v;
443    return v;
444 }
445 
inline_const(AluInlineConstants sel,int chan)446 PInlineConstant ValueFactory::inline_const(AluInlineConstants sel, int chan)
447 {
448    int hash = (sel << 3) | chan;
449    auto iv = m_inline_constants.find(hash);
450    if (iv !=  m_inline_constants.end())
451       return iv->second;
452    auto v = new InlineConstant( sel, chan);
453    m_inline_constants[hash] = v;
454    return v;
455 }
456 
src_vec(const nir_src & source,int components)457  std::vector<PVirtualValue, Allocator<PVirtualValue>> ValueFactory::src_vec(const nir_src& source, int components)
458 {
459    std::vector<PVirtualValue, Allocator<PVirtualValue>> retval;
460    retval.reserve(components);
461    for (int i = 0; i < components;  ++i)
462       retval.push_back(src(source, i));
463    return retval;
464 }
465 
466 std::vector<PRegister, Allocator<PRegister>>
dest_vec(const nir_dest & dst,int num_components)467 ValueFactory::dest_vec(const nir_dest& dst, int num_components)
468 {
469    std::vector<PRegister, Allocator<PRegister>> retval;
470    retval.reserve(num_components);
471    for (int i = 0; i < num_components;  ++i)
472       retval.push_back(dest(dst, i, num_components > 1 ? pin_chan : pin_free));
473    return retval;
474 }
475 
src_vec4(const nir_src & source,Pin pin,const RegisterVec4::Swizzle & swz)476 RegisterVec4 ValueFactory::src_vec4(const nir_src& source, Pin pin, const RegisterVec4::Swizzle& swz)
477 {
478    auto sx = swz[0] < 4 ? src(source, swz[0])->as_register() : nullptr;
479    auto sy = swz[1] < 4 ? src(source, swz[1])->as_register() : nullptr;
480    auto sz = swz[2] < 4 ? src(source, swz[2])->as_register() : nullptr;
481    auto sw = swz[3] < 4 ? src(source, swz[3])->as_register() : nullptr;
482 
483    assert(sx || sy || sz || sw);
484 
485    int sel = sx ? sx->sel() : (sy ? sy->sel() : (sz ? sz->sel() : sw ? sw->sel() : -1));
486    if (sel < 0)
487       unreachable("source vector without valid components");
488 
489    if (!sx) sx = new Register(sel, 7, pin);
490    if (!sy) sy = new Register(sel, 7, pin);
491    if (!sz) sz = new Register(sel, 7, pin);
492    if (!sw) sw = new Register(sel, 7, pin);
493 
494    return RegisterVec4(sx, sy, sz, sw, pin);
495 }
496 
497 static Pin
pin_from_string(const std::string & pinstr)498 pin_from_string(const std::string& pinstr)
499 {
500    if (pinstr == "chan")
501       return pin_chan;
502    if (pinstr == "array")
503       return pin_array;
504    if (pinstr == "fully")
505       return pin_fully;
506    if (pinstr == "group")
507       return pin_group;
508    if (pinstr == "chgr")
509       return pin_chgr;
510    if (pinstr == "free")
511       return pin_free;
512    return pin_none;
513 }
514 
chan_from_char(char chan)515 static int chan_from_char(char chan)
516 {
517    switch (chan) {
518    case 'x' : return 0;
519    case 'y' : return 1;
520    case 'z' : return 2;
521    case 'w' : return 3;
522    case '0' : return 4;
523    case '1' : return 5;
524    case '_' : return 7;
525    }
526    unreachable("Unknown swizzle char");
527 }
528 
529 static int
str_to_int(const string & s)530 str_to_int(const string& s)
531 {
532    istringstream ss(s);
533    int retval;
534    ss >> retval;
535    return retval;
536 }
537 
538 static bool
split_register_string(const string & s,string & index_str,string & size_str,string & swizzle_str,string & pin_str)539 split_register_string(const string& s,
540                       string& index_str,
541                       string& size_str,
542                       string& swizzle_str,
543                       string& pin_str)
544 {
545    int type = 0;
546    for (unsigned i = 1; i < s.length(); ++i) {
547       if (s[i] == '.' && type != 3) {
548          type = 1;
549          continue;
550       } else if (s[i] == '@' && type != 3) {
551          type = 2;
552          continue;
553       } else if (s[i] == '[') {
554          type = 3;
555          continue;
556       } else if (s[i] == ']') {
557          if (type != 3)
558             std::cerr << "s=" << s
559                       << ": type=" << type
560                       << ": i=" << i
561                       << "\n";
562          assert(type == 3);
563 
564          type = 4;
565          continue;
566       }
567 
568       switch (type) {
569       case 0: index_str.append(1, s[i]); break;
570       case 1: swizzle_str.append(1, s[i]); break;
571       case 2: pin_str.append(1, s[i]); break;
572       case 3: size_str.append(1, s[i]); break;
573       default:
574          unreachable("Malformed Array allocation string");
575       }
576    }
577    return true;
578 }
579 
dest_from_string(const std::string & s)580 PRegister ValueFactory::dest_from_string(const std::string& s)
581 {
582    assert(s.length() >= 4);
583 
584    assert(strchr("ARS_", s[0]));
585 
586    string index_str;
587    string size_str;
588    string swizzle_str;
589    string pin_str;
590 
591    split_register_string(s, index_str, size_str,
592                          swizzle_str, pin_str);
593 
594    int sel = 0;
595    if (s[0] == '_') {
596       /* Since these instructions still may use or switch to a different channel
597        * we have to create a new instance for each occurance */
598       sel = std::numeric_limits<int>::max() - m_nowrite_idx++;
599    } else {
600       std::istringstream n(index_str);
601       n >> sel;
602    }
603 
604    auto p = pin_from_string(pin_str);
605    char chan = chan_from_char(swizzle_str[0]);
606 
607    EValuePool pool = vp_temp;
608    switch (s[0]) {
609    case 'A': pool = vp_array; break;
610    case 'R': pool = vp_register; break;
611    case '_': pool = vp_ignore; break;
612    case 'S': pool = vp_ssa; break;
613    default:
614    unreachable("Unknown value type");
615    }
616 
617    bool is_ssa = s[0] == 'S';
618 
619    RegisterKey key (sel, chan, pool);
620 
621    sfn_log << SfnLog::reg << "Search register with key " << key << "\n";
622 
623    auto ireg = m_registers.find(key);
624    if ( ireg == m_registers.end()) {
625       auto reg = new Register(sel, chan, p);
626       reg->set_is_ssa(is_ssa);
627       if (p == pin_fully)
628          reg->pin_live_range(true);
629       m_registers[key] = reg;
630       return reg;
631    } else  if (pool == vp_ignore) {
632       assert(ireg->second->sel() == std::numeric_limits<int>::max());
633       return ireg->second;
634    } else {
635       assert(!is_ssa || s[0] == '_');
636 
637       if (size_str.length()) {
638          auto array = static_cast<LocalArray *>(ireg->second);
639          PVirtualValue addr = nullptr;
640          int offset = 0;
641          if (size_str[0] == 'S' || size_str[0] == 'R') {
642             addr = src_from_string(size_str);
643          } else {
644             istringstream num_str(size_str);
645             num_str >> offset;
646          }
647 
648          return array->element(offset, addr, chan - array->frac());
649       } else
650          return ireg->second;
651    }
652 }
653 
src_from_string(const std::string & s)654 PVirtualValue ValueFactory::src_from_string(const std::string& s)
655 {
656    switch (s[0]) {
657    case 'A':
658    case 'S':
659    case 'R': break;
660    case 'L': return LiteralConstant::from_string(s);
661    case 'K': return UniformValue::from_string(s);
662    case 'P': return InlineConstant::param_from_string(s);
663    case 'I': return InlineConstant::from_string(s);
664 
665    default:
666       std::cerr << "'" << s << "'";
667       unreachable("Unknown register type");
668    }
669 
670    assert(strchr("ARS_", s[0]));
671 
672    string index_str;
673    string size_str;
674    string swizzle_str;
675    string pin_str;
676 
677    split_register_string(s, index_str, size_str,
678                          swizzle_str, pin_str);
679 
680    int sel = 0;
681    if (s[0] == '_') {
682       sel = std::numeric_limits<int>::max();
683    } else {
684       std::istringstream n(index_str);
685       n >> sel;
686    }
687 
688    auto p = pin_from_string(pin_str);
689    char chan = chan_from_char(swizzle_str[0]);
690 
691    EValuePool pool = vp_temp;
692    switch (s[0]) {
693    case 'A': pool = vp_array; break;
694    case 'R': pool = vp_register; break;
695    case '_': pool = vp_ignore; break;
696    case 'S': pool = vp_ssa; break;
697    default:
698    unreachable("Unknown value type");
699    }
700 
701    RegisterKey key (sel, chan, pool);
702 
703    auto ireg = m_registers.find(key);
704    if (ireg != m_registers.end()) {
705       if (pool != vp_ssa && size_str.length()) {
706          auto array = static_cast<LocalArray *>(ireg->second);
707          PVirtualValue addr = nullptr;
708          int offset = 0;
709          if (size_str[0] == 'S' || size_str[0] == 'R') {
710             addr = src_from_string(size_str);
711          } else {
712             istringstream num_str(size_str);
713             num_str >> offset;
714          }
715          return array->element(offset, addr, chan - array->frac());
716       } else {
717          return ireg->second;
718       }
719    } else  {
720       if (sel != std::numeric_limits<int>::max()) {
721          std::cerr << "register " << key << "not found \n";
722          unreachable("Source register should exist");
723       } else {
724          auto reg = new Register( sel, chan, p);
725          m_registers[key] = reg;
726          return reg;
727       }
728    }
729 }
730 
dest_vec4_from_string(const std::string & s,RegisterVec4::Swizzle & swz,Pin pin)731 RegisterVec4 ValueFactory::dest_vec4_from_string(const std::string& s,
732                                                  RegisterVec4::Swizzle& swz,
733                                                  Pin pin)
734 {
735    bool is_ssa = false;
736    int sel = sel_and_szw_from_string(s, swz, is_ssa);
737 
738    PRegister v[4];
739 
740    for (int i = 0; i < 4; ++i) {
741       auto pool = is_ssa ? vp_ssa : vp_register;
742       if (swz[i] > 3)
743          pool = vp_ignore;
744 
745       RegisterKey  key(sel, i, pool);
746       auto ireg = m_registers.find(key);
747       if (ireg != m_registers.end()) {
748          v[i] = ireg->second;
749          assert(!is_ssa || pool == vp_ignore);
750       } else {
751          v[i] = new Register( sel, i, pin);
752          v[i]->set_is_ssa(is_ssa);
753          m_registers[key] = v[i];
754       }
755    }
756    return RegisterVec4(v[0], v[1], v[2], v[3], pin);
757 }
758 
src_vec4_from_string(const std::string & s)759 RegisterVec4 ValueFactory::src_vec4_from_string(const std::string& s)
760 {
761    RegisterVec4::Swizzle swz;
762    bool is_ssa = false;
763    int sel = sel_and_szw_from_string(s, swz, is_ssa);
764 
765    PRegister v[4];
766 
767    PRegister used_reg = nullptr;
768    for (int i = 0; i < 4; ++i) {
769       if (swz[i] < 4) {
770          RegisterKey  key(sel, swz[i], is_ssa ? vp_ssa : vp_register);
771          auto ireg = m_registers.find(key);
772          if (ireg == m_registers.end()) {
773             std::cerr << s << ": Register with key " << key << " not found\n";
774             assert(0);
775          }
776          used_reg = v[i] = ireg->second;
777       } else {
778          v[i] = nullptr;
779       }
780    }
781    sel = used_reg ? used_reg->sel() : 0;
782    Pin pin = used_reg ? used_reg->pin() : pin_group;
783 
784    for (int i = 0; i < 4; ++i) {
785       if (!v[i]) {
786          v[i] = new Register( sel, swz[i], pin);
787          v[i]->set_is_ssa(is_ssa);
788       } else {
789          if (v[i]->pin() == pin_none)
790             v[i]->set_pin(pin_group);
791       }
792    }
793    return RegisterVec4(v[0], v[1], v[2], v[3], pin);
794 }
795 
array_from_string(const std::string & s)796 LocalArray *ValueFactory::array_from_string(const std::string& s)
797 {
798    assert(s[0] == 'A');
799    string index_str;
800    string size_str;
801    string swizzle_str;
802    string pin_str;
803 
804 
805    int type = 0;
806    for (unsigned i = 1; i < s.length(); ++i) {
807       if (s[i] == '.') {
808          type = 1;
809          continue;
810       } else if (s[i] == '@') {
811          type = 2;
812          continue;
813       } else if (s[i] == '[') {
814          type = 3;
815          continue;
816       } else if (s[i] == ']') {
817          assert(type == 3);
818          type = 4;
819          continue;
820       }
821 
822       switch (type) {
823       case 0: index_str.append(1, s[i]); break;
824       case 1: swizzle_str.append(1, s[i]); break;
825       case 2: pin_str.append(1, s[i]); break;
826       case 3: size_str.append(1, s[i]); break;
827       default:
828          unreachable("Malformed Array allocation string");
829       }
830    }
831 
832    int sel = str_to_int(index_str);
833    int size = str_to_int(size_str);
834    int ncomp = swizzle_str.length();
835 
836    if (ncomp > 4 || ncomp <= 0) {
837       std::cerr << "Error reading array from '" << s << ": ";
838       std::cerr << "index:'" << index_str << "' -> '" << sel
839                 << "' size:'" << size_str << "' -> '" << size
840                 << " swizzle:'" << swizzle_str << "' -> '" << ncomp << "'\n";
841       assert(0);
842    }
843 
844    const char *swz = "xyzw";
845    const char *first_swz = strchr(swz, swizzle_str[0]);
846    long frac = first_swz - swz;
847    assert(frac >= 0 && frac <= 4 - ncomp);
848 
849    auto array = new LocalArray( sel, ncomp, size, frac);
850 
851    for (int i = 0; i < ncomp; ++i) {
852       RegisterKey key(sel, i + frac, vp_array);
853       m_registers[key] = array;
854    }
855    return array;
856 }
857 
append_register(Register * reg)858 void LiveRangeMap::append_register(Register *reg)
859 {
860    sfn_log << SfnLog::merge << __func__ << ": " << *reg << "\n";
861 
862    auto chan = reg->chan();
863    auto& ranges = m_life_ranges[chan];
864 
865    LiveRangeEntry entry(reg);
866    ranges.emplace_back(entry);
867 }
868 
sizes() const869 std::array<size_t, 4> LiveRangeMap::sizes() const
870 {
871    std::array<size_t, 4> result;
872    std::transform(m_life_ranges.begin(), m_life_ranges.end(),
873                   result.begin(), [](auto lr) {return lr.size(); });
874    return result;
875 }
876 
prepare_live_range_map()877 LiveRangeMap ValueFactory::prepare_live_range_map()
878 {
879    LiveRangeMap result;
880 
881    for (auto [key, reg] : m_registers) {
882       if (key.value.pool == vp_ignore)
883          continue;
884 
885       if (key.value.pool == vp_array) {
886          if (key.value.chan == 0) {
887             auto array = static_cast<LocalArray *>(reg);
888             for (auto& a : *array)  {
889                result.append_register(a);
890             }
891          }
892       } else {
893          if (reg->chan() < 4)
894             result.append_register(reg);
895       }
896    }
897 
898    for (auto r : m_pinned_registers) {
899       result.append_register(r);
900    }
901 
902    for (int i = 0; i < 4; ++i) {
903       auto& comp = result.component(i);
904       std::sort(comp.begin(), comp.end(),
905                 [](const LiveRangeEntry& lhs, const LiveRangeEntry& rhs) {
906          return lhs.m_register->sel() < rhs.m_register->sel();
907       });
908       for(size_t j = 0; j < comp.size(); ++j)
909          comp[j].m_register->set_index(j);
910    }
911 
912    return result;
913 }
914 
clear_pins()915 void ValueFactory::clear_pins()
916 {
917    for (auto [key, reg] : m_registers)
918       reg->set_pin(pin_none);
919 
920    for (auto reg : m_pinned_registers)
921       reg->set_pin(pin_none);
922 }
923 
clear()924 void ValueFactory::clear()
925 {
926    m_registers.clear();
927    m_values.clear();
928    m_literal_values.clear();
929    m_inline_constants.clear();
930    m_ssa_index_to_sel.clear();
931 }
932 
get_shader_info(r600_shader * sh_info)933 void ValueFactory::get_shader_info(r600_shader *sh_info)
934 {
935    std::set<LocalArray*> arrays;
936 
937    for (auto& [key, reg] : m_registers) {
938       if (key.value.pool == vp_array)
939          arrays.insert(static_cast<LocalArray *>(reg));
940    }
941 
942    if (!arrays.empty()) {
943 
944       sh_info->num_arrays = arrays.size();
945       sh_info->arrays = new r600_shader_array[arrays.size()];
946 
947       for (auto& arr : arrays) {
948          sh_info->arrays->gpr_start = arr->sel();
949          sh_info->arrays->gpr_count = arr->size();
950          sh_info->arrays->comp_mask =
951                ((1 << arr->nchannels()) - 1)
952                << arr->frac();
953       }
954       sh_info->indirect_files |= 1 << TGSI_FILE_TEMPORARY;
955    }
956 }
957 
958 
959 }
960