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