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