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