1bf215546Sopenharmony_ci/* -*- mesa-c++  -*-
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright (c) 2022 Collabora LTD
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * Author: Gert Wollny <gert.wollny@collabora.com>
6bf215546Sopenharmony_ci *
7bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
8bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
9bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
10bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub
11bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom
12bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
15bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
16bf215546Sopenharmony_ci * Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci */
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "sfn_shader.h"
28bf215546Sopenharmony_ci#include "sfn_instr.h"
29bf215546Sopenharmony_ci#include "sfn_instr_alugroup.h"
30bf215546Sopenharmony_ci#include "sfn_instr_export.h"
31bf215546Sopenharmony_ci#include "sfn_instr_fetch.h"
32bf215546Sopenharmony_ci#include "sfn_instr_lds.h"
33bf215546Sopenharmony_ci#include "sfn_instr_mem.h"
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_ci#include "sfn_instr_controlflow.h"
36bf215546Sopenharmony_ci#include "sfn_liverangeevaluator.h"
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci#include "sfn_shader_cs.h"
39bf215546Sopenharmony_ci#include "sfn_shader_fs.h"
40bf215546Sopenharmony_ci#include "sfn_shader_vs.h"
41bf215546Sopenharmony_ci#include "sfn_shader_gs.h"
42bf215546Sopenharmony_ci#include "sfn_shader_tess.h"
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_ci#include "sfn_debug.h"
45bf215546Sopenharmony_ci#include "gallium/drivers/r600/r600_shader.h"
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_ci#include "tgsi/tgsi_from_mesa.h"
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci#include "nir.h"
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci#include <numeric>
52bf215546Sopenharmony_ci#include <sstream>
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_cinamespace r600 {
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ciusing std::string;
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_cistd::pair<unsigned, unsigned>
59bf215546Sopenharmony_cir600_get_varying_semantic(unsigned varying_location)
60bf215546Sopenharmony_ci{
61bf215546Sopenharmony_ci   std::pair<unsigned, unsigned> result;
62bf215546Sopenharmony_ci   tgsi_get_gl_varying_semantic(static_cast<gl_varying_slot>(varying_location),
63bf215546Sopenharmony_ci                                true, &result.first, &result.second);
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_ci   if (result.first == TGSI_SEMANTIC_GENERIC) {
66bf215546Sopenharmony_ci      result.second += 9;
67bf215546Sopenharmony_ci   } else if (result.first == TGSI_SEMANTIC_PCOORD) {
68bf215546Sopenharmony_ci      result.second = 8;
69bf215546Sopenharmony_ci   }
70bf215546Sopenharmony_ci   return result;
71bf215546Sopenharmony_ci}
72bf215546Sopenharmony_ci
73bf215546Sopenharmony_civoid ShaderIO::set_sid(int sid)
74bf215546Sopenharmony_ci{
75bf215546Sopenharmony_ci   m_sid = sid;
76bf215546Sopenharmony_ci   switch (m_name) {
77bf215546Sopenharmony_ci   case TGSI_SEMANTIC_POSITION:
78bf215546Sopenharmony_ci   case TGSI_SEMANTIC_PSIZE:
79bf215546Sopenharmony_ci   case TGSI_SEMANTIC_EDGEFLAG:
80bf215546Sopenharmony_ci   case TGSI_SEMANTIC_FACE:
81bf215546Sopenharmony_ci   case TGSI_SEMANTIC_SAMPLEMASK:
82bf215546Sopenharmony_ci   case TGSI_SEMANTIC_CLIPVERTEX:
83bf215546Sopenharmony_ci      m_spi_sid = 0;
84bf215546Sopenharmony_ci   break;
85bf215546Sopenharmony_ci   case TGSI_SEMANTIC_GENERIC:
86bf215546Sopenharmony_ci   case TGSI_SEMANTIC_TEXCOORD:
87bf215546Sopenharmony_ci   case TGSI_SEMANTIC_PCOORD:
88bf215546Sopenharmony_ci      m_spi_sid = m_sid + 1;
89bf215546Sopenharmony_ci   break;
90bf215546Sopenharmony_ci   default:
91bf215546Sopenharmony_ci      /* For non-generic params - pack name and sid into 8 bits */
92bf215546Sopenharmony_ci      m_spi_sid = (0x80 | (m_name << 3) | m_sid) + 1;
93bf215546Sopenharmony_ci   }
94bf215546Sopenharmony_ci}
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_civoid ShaderIO::override_spi_sid(int spi)
97bf215546Sopenharmony_ci{
98bf215546Sopenharmony_ci   m_spi_sid = spi;
99bf215546Sopenharmony_ci}
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_civoid ShaderIO::print(std::ostream& os) const
102bf215546Sopenharmony_ci{
103bf215546Sopenharmony_ci   os << m_type << " LOC:" << m_location << " NAME:" << m_name;
104bf215546Sopenharmony_ci   do_print(os);
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci   if (m_sid > 0) {
107bf215546Sopenharmony_ci      os << " SID:" << m_sid << " SPI_SID:" << m_spi_sid;
108bf215546Sopenharmony_ci   }
109bf215546Sopenharmony_ci}
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_ci
112bf215546Sopenharmony_ciShaderIO::ShaderIO(const char *type, int loc, int name):
113bf215546Sopenharmony_ci   m_type(type),
114bf215546Sopenharmony_ci   m_location(loc),
115bf215546Sopenharmony_ci   m_name(name)
116bf215546Sopenharmony_ci{
117bf215546Sopenharmony_ci}
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_ciShaderOutput::ShaderOutput():
120bf215546Sopenharmony_ci   ShaderIO("OUTPUT", -1, -1)
121bf215546Sopenharmony_ci{
122bf215546Sopenharmony_ci}
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ciShaderOutput::ShaderOutput(int location, int name, int writemask):
125bf215546Sopenharmony_ci   ShaderIO("OUTPUT", location, name),
126bf215546Sopenharmony_ci   m_writemask(writemask)
127bf215546Sopenharmony_ci{
128bf215546Sopenharmony_ci
129bf215546Sopenharmony_ci}
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_civoid ShaderOutput::do_print(std::ostream& os) const
132bf215546Sopenharmony_ci{
133bf215546Sopenharmony_ci   os << " MASK:" << m_writemask;
134bf215546Sopenharmony_ci}
135bf215546Sopenharmony_ci
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ciShaderInput::ShaderInput(int location, int name):
138bf215546Sopenharmony_ci   ShaderIO("INPUT", location, name)
139bf215546Sopenharmony_ci{
140bf215546Sopenharmony_ci}
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ciShaderInput::ShaderInput():
143bf215546Sopenharmony_ci   ShaderInput(-1, -1)
144bf215546Sopenharmony_ci{
145bf215546Sopenharmony_ci}
146bf215546Sopenharmony_ci
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_civoid ShaderInput::do_print(std::ostream& os) const
149bf215546Sopenharmony_ci{
150bf215546Sopenharmony_ci   if (m_interpolator)
151bf215546Sopenharmony_ci      os << " INTERP:" << m_interpolator;
152bf215546Sopenharmony_ci   if (m_interpolate_loc)
153bf215546Sopenharmony_ci      os << " ILOC:" << m_interpolate_loc;
154bf215546Sopenharmony_ci   if (m_uses_interpolate_at_centroid)
155bf215546Sopenharmony_ci      os << " USE_CENTROID";
156bf215546Sopenharmony_ci}
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_civoid ShaderInput::set_interpolator(int interp, int interp_loc, bool uses_interpolate_at_centroid)
159bf215546Sopenharmony_ci{
160bf215546Sopenharmony_ci   m_interpolator = interp;
161bf215546Sopenharmony_ci   m_interpolate_loc = interp_loc;
162bf215546Sopenharmony_ci   m_uses_interpolate_at_centroid = uses_interpolate_at_centroid;
163bf215546Sopenharmony_ci}
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_civoid ShaderInput::set_uses_interpolate_at_centroid()
166bf215546Sopenharmony_ci{
167bf215546Sopenharmony_ci   m_uses_interpolate_at_centroid = true;
168bf215546Sopenharmony_ci}
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ciShader::Shader(const char *type_id):
171bf215546Sopenharmony_ci   m_current_block(nullptr),
172bf215546Sopenharmony_ci   m_type_id(type_id),
173bf215546Sopenharmony_ci   m_chip_class(ISA_CC_R600),
174bf215546Sopenharmony_ci   m_next_block(0)
175bf215546Sopenharmony_ci{
176bf215546Sopenharmony_ci   m_instr_factory = new InstrFactory();
177bf215546Sopenharmony_ci   m_chain_instr.this_shader = this;
178bf215546Sopenharmony_ci   start_new_block(0);
179bf215546Sopenharmony_ci}
180bf215546Sopenharmony_ci
181bf215546Sopenharmony_civoid Shader::set_input_gpr(int driver_lcation, int gpr)
182bf215546Sopenharmony_ci{
183bf215546Sopenharmony_ci   auto i = m_inputs.find(driver_lcation);
184bf215546Sopenharmony_ci   assert(i != m_inputs.end());
185bf215546Sopenharmony_ci   i->second.set_gpr(gpr);
186bf215546Sopenharmony_ci}
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_cibool Shader::add_info_from_string(std::istream& is)
189bf215546Sopenharmony_ci{
190bf215546Sopenharmony_ci   std::string type;
191bf215546Sopenharmony_ci   is >> type;
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci   if (type == "CHIPCLASS")
194bf215546Sopenharmony_ci      return read_chipclass(is);
195bf215546Sopenharmony_ci   if (type == "OUTPUT")
196bf215546Sopenharmony_ci      return read_output(is);
197bf215546Sopenharmony_ci   if (type == "INPUT")
198bf215546Sopenharmony_ci      return read_input(is);
199bf215546Sopenharmony_ci   if (type == "PROP")
200bf215546Sopenharmony_ci      return read_prop(is);
201bf215546Sopenharmony_ci   if (type == "SYSVALUES")
202bf215546Sopenharmony_ci      return allocate_registers_from_string(is, pin_fully);
203bf215546Sopenharmony_ci   if (type == "REGISTERS")
204bf215546Sopenharmony_ci      return allocate_registers_from_string(is, pin_free);
205bf215546Sopenharmony_ci   if (type == "ARRAYS")
206bf215546Sopenharmony_ci      return allocate_arrays_from_string(is);
207bf215546Sopenharmony_ci
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_ci   return false;
210bf215546Sopenharmony_ci}
211bf215546Sopenharmony_ci
212bf215546Sopenharmony_civoid Shader::emit_instruction_from_string(const std::string& s)
213bf215546Sopenharmony_ci{
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_ci   sfn_log << SfnLog::instr << "Create Instr from '" << s << "'\n";
216bf215546Sopenharmony_ci   if (s == "BLOCK_START") {
217bf215546Sopenharmony_ci      if (!m_current_block->empty()) {
218bf215546Sopenharmony_ci         start_new_block(m_current_block->nesting_offset());
219bf215546Sopenharmony_ci         sfn_log << SfnLog::instr << "   Emit start block\n";
220bf215546Sopenharmony_ci      }
221bf215546Sopenharmony_ci      return;
222bf215546Sopenharmony_ci   }
223bf215546Sopenharmony_ci
224bf215546Sopenharmony_ci   if (s == "BLOCK_END") {
225bf215546Sopenharmony_ci      return;
226bf215546Sopenharmony_ci   }
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ci   auto ir = m_instr_factory->from_string(s, m_current_block->nesting_depth());
229bf215546Sopenharmony_ci   if (ir) {
230bf215546Sopenharmony_ci      emit_instruction(ir);
231bf215546Sopenharmony_ci      if (ir->end_block())
232bf215546Sopenharmony_ci         start_new_block(ir->nesting_offset());
233bf215546Sopenharmony_ci      sfn_log << SfnLog::instr << "   " << *ir << "\n";
234bf215546Sopenharmony_ci   }
235bf215546Sopenharmony_ci}
236bf215546Sopenharmony_ci
237bf215546Sopenharmony_cibool Shader::read_output(std::istream& is)
238bf215546Sopenharmony_ci{
239bf215546Sopenharmony_ci   string value;
240bf215546Sopenharmony_ci   is >> value;
241bf215546Sopenharmony_ci   int pos = int_from_string_with_prefix(value, "LOC:");
242bf215546Sopenharmony_ci   is >> value;
243bf215546Sopenharmony_ci   int name = int_from_string_with_prefix(value, "NAME:");
244bf215546Sopenharmony_ci   is >> value;
245bf215546Sopenharmony_ci   int mask = int_from_string_with_prefix(value, "MASK:");
246bf215546Sopenharmony_ci   ShaderOutput output(pos, name, mask);
247bf215546Sopenharmony_ci
248bf215546Sopenharmony_ci   value.clear();
249bf215546Sopenharmony_ci   is >> value;
250bf215546Sopenharmony_ci   if (!value.empty()) {
251bf215546Sopenharmony_ci      int sid = int_from_string_with_prefix(value, "SID:");
252bf215546Sopenharmony_ci      output.set_sid(sid);
253bf215546Sopenharmony_ci      is >> value;
254bf215546Sopenharmony_ci      int spi_sid = int_from_string_with_prefix(value, "SPI_SID:");
255bf215546Sopenharmony_ci      assert(spi_sid == output.spi_sid());
256bf215546Sopenharmony_ci   }
257bf215546Sopenharmony_ci
258bf215546Sopenharmony_ci   add_output(output);
259bf215546Sopenharmony_ci   return true;
260bf215546Sopenharmony_ci}
261bf215546Sopenharmony_ci
262bf215546Sopenharmony_ci
263bf215546Sopenharmony_cibool Shader::read_input(std::istream& is)
264bf215546Sopenharmony_ci{
265bf215546Sopenharmony_ci   string value;
266bf215546Sopenharmony_ci   is >> value;
267bf215546Sopenharmony_ci   int pos = int_from_string_with_prefix(value, "LOC:");
268bf215546Sopenharmony_ci   is >> value;
269bf215546Sopenharmony_ci   int name = int_from_string_with_prefix(value, "NAME:");
270bf215546Sopenharmony_ci
271bf215546Sopenharmony_ci   value.clear();
272bf215546Sopenharmony_ci
273bf215546Sopenharmony_ci   ShaderInput input(pos, name);
274bf215546Sopenharmony_ci
275bf215546Sopenharmony_ci   int interp = 0;
276bf215546Sopenharmony_ci   int interp_loc = 0;
277bf215546Sopenharmony_ci   bool use_centroid = false;
278bf215546Sopenharmony_ci
279bf215546Sopenharmony_ci   is >> value;
280bf215546Sopenharmony_ci   while (!value.empty()) {
281bf215546Sopenharmony_ci      if (value.substr(0, 4) == "SID:") {
282bf215546Sopenharmony_ci         int sid = int_from_string_with_prefix(value, "SID:");
283bf215546Sopenharmony_ci         input.set_sid(sid);
284bf215546Sopenharmony_ci      } else if (value.substr(0, 8) == "SPI_SID:") {
285bf215546Sopenharmony_ci         int spi_sid = int_from_string_with_prefix(value, "SPI_SID:");
286bf215546Sopenharmony_ci         assert(spi_sid == input.spi_sid());
287bf215546Sopenharmony_ci      } else if (value.substr(0, 7) == "INTERP:") {
288bf215546Sopenharmony_ci         interp = int_from_string_with_prefix(value, "INTERP:");
289bf215546Sopenharmony_ci      } else if (value.substr(0, 5) == "ILOC:") {
290bf215546Sopenharmony_ci         interp_loc = int_from_string_with_prefix(value, "ILOC:");
291bf215546Sopenharmony_ci      } else if (value == "USE_CENTROID") {
292bf215546Sopenharmony_ci         use_centroid = true;
293bf215546Sopenharmony_ci      } else {
294bf215546Sopenharmony_ci         std::cerr << "Unknown parse value '" << value << "'";
295bf215546Sopenharmony_ci         assert(!value.c_str());
296bf215546Sopenharmony_ci      }
297bf215546Sopenharmony_ci      value.clear();
298bf215546Sopenharmony_ci      is >> value;
299bf215546Sopenharmony_ci   }
300bf215546Sopenharmony_ci
301bf215546Sopenharmony_ci   input.set_interpolator(interp, interp_loc, use_centroid);
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_ci   add_input(input);
304bf215546Sopenharmony_ci   return true;
305bf215546Sopenharmony_ci}
306bf215546Sopenharmony_ci
307bf215546Sopenharmony_cibool Shader::allocate_registers_from_string(std::istream& is, Pin pin)
308bf215546Sopenharmony_ci{
309bf215546Sopenharmony_ci   std::string line;
310bf215546Sopenharmony_ci   if (!std::getline(is, line))
311bf215546Sopenharmony_ci      return false;
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_ci   std::istringstream iline(line);
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_ci   while (!iline.eof())  {
316bf215546Sopenharmony_ci      string reg_str;
317bf215546Sopenharmony_ci      iline >> reg_str;
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci      if (reg_str.empty())
320bf215546Sopenharmony_ci         break;
321bf215546Sopenharmony_ci
322bf215546Sopenharmony_ci      if (strchr(reg_str.c_str(), '@')) {
323bf215546Sopenharmony_ci         value_factory().dest_from_string(reg_str);
324bf215546Sopenharmony_ci      } else {
325bf215546Sopenharmony_ci         RegisterVec4::Swizzle swz = {0,1,2,3};
326bf215546Sopenharmony_ci         auto regs = value_factory().dest_vec4_from_string(reg_str, swz, pin);
327bf215546Sopenharmony_ci         for (int i = 0; i < 4; ++i) {
328bf215546Sopenharmony_ci            if (swz[i] < 4 && pin == pin_fully) {
329bf215546Sopenharmony_ci               regs[i]->pin_live_range(true, false);
330bf215546Sopenharmony_ci            }
331bf215546Sopenharmony_ci         }
332bf215546Sopenharmony_ci      }
333bf215546Sopenharmony_ci   }
334bf215546Sopenharmony_ci   return true;
335bf215546Sopenharmony_ci}
336bf215546Sopenharmony_ci
337bf215546Sopenharmony_cibool Shader::allocate_arrays_from_string(std::istream& is)
338bf215546Sopenharmony_ci{
339bf215546Sopenharmony_ci   std::string line;
340bf215546Sopenharmony_ci   if (!std::getline(is, line))
341bf215546Sopenharmony_ci      return false;
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci   std::istringstream iline(line);
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci   while (!iline.eof())  {
346bf215546Sopenharmony_ci      string reg_str;
347bf215546Sopenharmony_ci      iline >> reg_str;
348bf215546Sopenharmony_ci
349bf215546Sopenharmony_ci      if (reg_str.empty())
350bf215546Sopenharmony_ci         break;
351bf215546Sopenharmony_ci
352bf215546Sopenharmony_ci      value_factory().array_from_string(reg_str);
353bf215546Sopenharmony_ci   }
354bf215546Sopenharmony_ci   return true;
355bf215546Sopenharmony_ci}
356bf215546Sopenharmony_ci
357bf215546Sopenharmony_cibool Shader::read_chipclass(std::istream& is)
358bf215546Sopenharmony_ci{
359bf215546Sopenharmony_ci   string name;
360bf215546Sopenharmony_ci   is >> name;
361bf215546Sopenharmony_ci   if (name == "R600")
362bf215546Sopenharmony_ci      m_chip_class = ISA_CC_R600;
363bf215546Sopenharmony_ci   else if (name == "R700")
364bf215546Sopenharmony_ci      m_chip_class = ISA_CC_R700;
365bf215546Sopenharmony_ci   else if (name == "EVERGREEN")
366bf215546Sopenharmony_ci      m_chip_class = ISA_CC_EVERGREEN;
367bf215546Sopenharmony_ci   else if (name == "CAYMAN")
368bf215546Sopenharmony_ci      m_chip_class = ISA_CC_CAYMAN;
369bf215546Sopenharmony_ci   else
370bf215546Sopenharmony_ci      return false;
371bf215546Sopenharmony_ci   return true;
372bf215546Sopenharmony_ci}
373bf215546Sopenharmony_ci
374bf215546Sopenharmony_civoid Shader::allocate_reserved_registers()
375bf215546Sopenharmony_ci{
376bf215546Sopenharmony_ci   m_instr_factory->value_factory().set_virtual_register_base(0);
377bf215546Sopenharmony_ci   auto reserved_registers_end = do_allocate_reserved_registers();
378bf215546Sopenharmony_ci   m_instr_factory->value_factory().set_virtual_register_base(reserved_registers_end);
379bf215546Sopenharmony_ci   if (!m_atomics.empty()) {
380bf215546Sopenharmony_ci      m_atomic_update = value_factory().temp_register();
381bf215546Sopenharmony_ci      auto alu = new AluInstr(op1_mov, m_atomic_update,
382bf215546Sopenharmony_ci                              value_factory().one_i(),
383bf215546Sopenharmony_ci                              AluInstr::last_write);
384bf215546Sopenharmony_ci      alu->set_alu_flag(alu_no_schedule_bias);
385bf215546Sopenharmony_ci      emit_instruction(alu);
386bf215546Sopenharmony_ci   }
387bf215546Sopenharmony_ci
388bf215546Sopenharmony_ci   if(m_flags.test(sh_needs_sbo_ret_address)) {
389bf215546Sopenharmony_ci      m_rat_return_address = value_factory().temp_register(0);
390bf215546Sopenharmony_ci      auto temp0 = value_factory().temp_register(0);
391bf215546Sopenharmony_ci      auto temp1 = value_factory().temp_register(1);
392bf215546Sopenharmony_ci      auto temp2 = value_factory().temp_register(2);
393bf215546Sopenharmony_ci
394bf215546Sopenharmony_ci      auto group = new AluGroup();
395bf215546Sopenharmony_ci      group->add_instruction(new AluInstr(op1_mbcnt_32lo_accum_prev_int, temp0, value_factory().literal(-1), {alu_write}));
396bf215546Sopenharmony_ci      group->add_instruction(new AluInstr(op1_mbcnt_32hi_int, temp1, value_factory().literal(-1), {alu_write}));
397bf215546Sopenharmony_ci      emit_instruction(group);
398bf215546Sopenharmony_ci      emit_instruction(new AluInstr(op3_muladd_uint24, temp2, value_factory().inline_const(ALU_SRC_SE_ID, 0),
399bf215546Sopenharmony_ci                                          value_factory().literal(256), value_factory().inline_const(ALU_SRC_HW_WAVE_ID, 0), {alu_write, alu_last_instr}));
400bf215546Sopenharmony_ci      emit_instruction(new AluInstr(op3_muladd_uint24, m_rat_return_address,
401bf215546Sopenharmony_ci                                    temp2, value_factory().literal(0x40), temp0,
402bf215546Sopenharmony_ci                                    {alu_write, alu_last_instr}));
403bf215546Sopenharmony_ci   }
404bf215546Sopenharmony_ci}
405bf215546Sopenharmony_ci
406bf215546Sopenharmony_ciShader *Shader::translate_from_nir(nir_shader *nir, const pipe_stream_output_info *so_info,
407bf215546Sopenharmony_ci                                   struct r600_shader* gs_shader,
408bf215546Sopenharmony_ci                                   r600_shader_key& key, r600_chip_class chip_class)
409bf215546Sopenharmony_ci{
410bf215546Sopenharmony_ci   Shader *shader = nullptr;
411bf215546Sopenharmony_ci
412bf215546Sopenharmony_ci   switch (nir->info.stage) {
413bf215546Sopenharmony_ci   case MESA_SHADER_FRAGMENT:
414bf215546Sopenharmony_ci      if (chip_class >= ISA_CC_EVERGREEN)
415bf215546Sopenharmony_ci         shader = new FragmentShaderEG(key);
416bf215546Sopenharmony_ci      else
417bf215546Sopenharmony_ci         shader = new FragmentShaderR600(key);
418bf215546Sopenharmony_ci   break;
419bf215546Sopenharmony_ci   case MESA_SHADER_VERTEX:
420bf215546Sopenharmony_ci      shader = new VertexShader(so_info, gs_shader, key);
421bf215546Sopenharmony_ci   break;
422bf215546Sopenharmony_ci   case MESA_SHADER_GEOMETRY:
423bf215546Sopenharmony_ci      shader = new GeometryShader(key);
424bf215546Sopenharmony_ci   break;
425bf215546Sopenharmony_ci   case MESA_SHADER_TESS_CTRL:
426bf215546Sopenharmony_ci      shader = new TCSShader(key);
427bf215546Sopenharmony_ci      break;
428bf215546Sopenharmony_ci   case MESA_SHADER_TESS_EVAL:
429bf215546Sopenharmony_ci      shader = new TESShader(so_info, gs_shader, key);
430bf215546Sopenharmony_ci      break;
431bf215546Sopenharmony_ci   case MESA_SHADER_COMPUTE:
432bf215546Sopenharmony_ci      shader = new ComputeShader(key);
433bf215546Sopenharmony_ci      break;
434bf215546Sopenharmony_ci   default:
435bf215546Sopenharmony_ci      return nullptr;
436bf215546Sopenharmony_ci   }
437bf215546Sopenharmony_ci
438bf215546Sopenharmony_ci   shader->set_info(nir);
439bf215546Sopenharmony_ci
440bf215546Sopenharmony_ci   shader->set_chip_class(chip_class);
441bf215546Sopenharmony_ci   if (!shader->process(nir))
442bf215546Sopenharmony_ci      return nullptr;
443bf215546Sopenharmony_ci
444bf215546Sopenharmony_ci   return shader;
445bf215546Sopenharmony_ci}
446bf215546Sopenharmony_ci
447bf215546Sopenharmony_civoid Shader::set_info(nir_shader *nir)
448bf215546Sopenharmony_ci{
449bf215546Sopenharmony_ci   m_scratch_size = nir->scratch_size;
450bf215546Sopenharmony_ci}
451bf215546Sopenharmony_ci
452bf215546Sopenharmony_ciValueFactory& Shader::value_factory()
453bf215546Sopenharmony_ci{
454bf215546Sopenharmony_ci   return m_instr_factory->value_factory();
455bf215546Sopenharmony_ci}
456bf215546Sopenharmony_ci
457bf215546Sopenharmony_ci
458bf215546Sopenharmony_cibool Shader::process(nir_shader *nir)
459bf215546Sopenharmony_ci{
460bf215546Sopenharmony_ci   m_ssbo_image_offset = nir->info.num_images;
461bf215546Sopenharmony_ci
462bf215546Sopenharmony_ci   if (nir->info.use_legacy_math_rules)
463bf215546Sopenharmony_ci      set_flag(sh_legacy_math_rules);
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_ci   nir_foreach_uniform_variable(var, nir)
466bf215546Sopenharmony_ci         scan_uniforms(var);
467bf215546Sopenharmony_ci
468bf215546Sopenharmony_ci   // at this point all functions should be inlined
469bf215546Sopenharmony_ci   const nir_function *func = reinterpret_cast<const nir_function *>(exec_list_get_head_const(&nir->functions));
470bf215546Sopenharmony_ci
471bf215546Sopenharmony_ci   if (!scan_shader(func))
472bf215546Sopenharmony_ci      return false;
473bf215546Sopenharmony_ci
474bf215546Sopenharmony_ci   allocate_reserved_registers();
475bf215546Sopenharmony_ci
476bf215546Sopenharmony_ci   allocate_local_registers(&func->impl->registers);
477bf215546Sopenharmony_ci
478bf215546Sopenharmony_ci   sfn_log << SfnLog::trans << "Process shader \n";
479bf215546Sopenharmony_ci   foreach_list_typed(nir_cf_node, node, node, &func->impl->body) {
480bf215546Sopenharmony_ci      if (!process_cf_node(node))
481bf215546Sopenharmony_ci         return false;
482bf215546Sopenharmony_ci   }
483bf215546Sopenharmony_ci
484bf215546Sopenharmony_ci   finalize();
485bf215546Sopenharmony_ci
486bf215546Sopenharmony_ci   return true;
487bf215546Sopenharmony_ci}
488bf215546Sopenharmony_ci
489bf215546Sopenharmony_civoid Shader::allocate_local_registers(const exec_list *registers)
490bf215546Sopenharmony_ci{
491bf215546Sopenharmony_ci   if (value_factory().allocate_registers(registers))
492bf215546Sopenharmony_ci      m_indirect_files |= 1 << TGSI_FILE_TEMPORARY;
493bf215546Sopenharmony_ci}
494bf215546Sopenharmony_ci
495bf215546Sopenharmony_cibool Shader::scan_shader(const nir_function *func)
496bf215546Sopenharmony_ci{
497bf215546Sopenharmony_ci
498bf215546Sopenharmony_ci   nir_foreach_block(block, func->impl) {
499bf215546Sopenharmony_ci      nir_foreach_instr(instr, block) {
500bf215546Sopenharmony_ci         if (!scan_instruction(instr)) {
501bf215546Sopenharmony_ci            fprintf(stderr, "Unhandled sysvalue access ");
502bf215546Sopenharmony_ci            nir_print_instr(instr, stderr);
503bf215546Sopenharmony_ci            fprintf(stderr, "\n");
504bf215546Sopenharmony_ci            return false;
505bf215546Sopenharmony_ci         }
506bf215546Sopenharmony_ci      }
507bf215546Sopenharmony_ci   }
508bf215546Sopenharmony_ci
509bf215546Sopenharmony_ci   int lds_pos = 0;
510bf215546Sopenharmony_ci   for (auto& [index, input] : m_inputs) {
511bf215546Sopenharmony_ci      if (input.need_lds_pos()) {
512bf215546Sopenharmony_ci         if (chip_class() < ISA_CC_EVERGREEN)
513bf215546Sopenharmony_ci            input.set_gpr(lds_pos);
514bf215546Sopenharmony_ci         input.set_lds_pos(lds_pos++);
515bf215546Sopenharmony_ci      }
516bf215546Sopenharmony_ci   }
517bf215546Sopenharmony_ci
518bf215546Sopenharmony_ci   int param_id = 0;
519bf215546Sopenharmony_ci   for (auto& [index, out] : m_outputs) {
520bf215546Sopenharmony_ci      if (out.is_param())
521bf215546Sopenharmony_ci         out.set_pos(param_id++);
522bf215546Sopenharmony_ci   }
523bf215546Sopenharmony_ci
524bf215546Sopenharmony_ci   return true;
525bf215546Sopenharmony_ci}
526bf215546Sopenharmony_ci
527bf215546Sopenharmony_cibool Shader::scan_uniforms(nir_variable *uniform)
528bf215546Sopenharmony_ci{
529bf215546Sopenharmony_ci   if (uniform->type->contains_atomic()) {
530bf215546Sopenharmony_ci      int natomics = uniform->type->atomic_size() / ATOMIC_COUNTER_SIZE;
531bf215546Sopenharmony_ci      m_nhwatomic += natomics;
532bf215546Sopenharmony_ci
533bf215546Sopenharmony_ci      if (uniform->type->is_array())
534bf215546Sopenharmony_ci         m_indirect_files |= 1 << TGSI_FILE_HW_ATOMIC;
535bf215546Sopenharmony_ci
536bf215546Sopenharmony_ci      m_flags.set(sh_uses_atomics);
537bf215546Sopenharmony_ci
538bf215546Sopenharmony_ci      r600_shader_atomic atom = {0};
539bf215546Sopenharmony_ci
540bf215546Sopenharmony_ci      atom.buffer_id = uniform->data.binding;
541bf215546Sopenharmony_ci      atom.hw_idx = m_atomic_base + m_next_hwatomic_loc;
542bf215546Sopenharmony_ci
543bf215546Sopenharmony_ci      atom.start = uniform->data.offset >> 2;
544bf215546Sopenharmony_ci      atom.end = atom.start + natomics - 1;
545bf215546Sopenharmony_ci
546bf215546Sopenharmony_ci      if (m_atomic_base_map.find(uniform->data.binding) ==
547bf215546Sopenharmony_ci          m_atomic_base_map.end())
548bf215546Sopenharmony_ci         m_atomic_base_map[uniform->data.binding] = m_next_hwatomic_loc;
549bf215546Sopenharmony_ci
550bf215546Sopenharmony_ci      m_next_hwatomic_loc += natomics;
551bf215546Sopenharmony_ci
552bf215546Sopenharmony_ci      m_atomic_file_count += atom.end  - atom.start + 1;
553bf215546Sopenharmony_ci
554bf215546Sopenharmony_ci      sfn_log << SfnLog::io << "HW_ATOMIC file count: "
555bf215546Sopenharmony_ci              << m_atomic_file_count << "\n";
556bf215546Sopenharmony_ci
557bf215546Sopenharmony_ci      m_atomics.push_back(atom);
558bf215546Sopenharmony_ci   }
559bf215546Sopenharmony_ci
560bf215546Sopenharmony_ci   auto type = uniform->type->is_array() ? uniform->type->without_array(): uniform->type;
561bf215546Sopenharmony_ci   if (type->is_image() || uniform->data.mode == nir_var_mem_ssbo) {
562bf215546Sopenharmony_ci      m_flags.set(sh_uses_images);
563bf215546Sopenharmony_ci      if (uniform->type->is_array() && ! (uniform->data.mode == nir_var_mem_ssbo))
564bf215546Sopenharmony_ci         m_indirect_files |= 1 << TGSI_FILE_IMAGE;
565bf215546Sopenharmony_ci   }
566bf215546Sopenharmony_ci
567bf215546Sopenharmony_ci   return true;
568bf215546Sopenharmony_ci}
569bf215546Sopenharmony_ci
570bf215546Sopenharmony_ci
571bf215546Sopenharmony_cibool Shader::scan_instruction(nir_instr *instr)
572bf215546Sopenharmony_ci{
573bf215546Sopenharmony_ci   if (do_scan_instruction(instr))
574bf215546Sopenharmony_ci      return true;
575bf215546Sopenharmony_ci
576bf215546Sopenharmony_ci   if (instr->type != nir_instr_type_intrinsic)
577bf215546Sopenharmony_ci      return true;
578bf215546Sopenharmony_ci
579bf215546Sopenharmony_ci   auto intr = nir_instr_as_intrinsic(instr);
580bf215546Sopenharmony_ci
581bf215546Sopenharmony_ci   // handle unhandled instructions
582bf215546Sopenharmony_ci   switch (intr->intrinsic) {
583bf215546Sopenharmony_ci   case nir_intrinsic_ssbo_atomic_add:
584bf215546Sopenharmony_ci   case nir_intrinsic_ssbo_atomic_comp_swap:
585bf215546Sopenharmony_ci   case nir_intrinsic_ssbo_atomic_or:
586bf215546Sopenharmony_ci   case nir_intrinsic_ssbo_atomic_xor:
587bf215546Sopenharmony_ci   case nir_intrinsic_ssbo_atomic_imax:
588bf215546Sopenharmony_ci   case nir_intrinsic_ssbo_atomic_imin:
589bf215546Sopenharmony_ci   case nir_intrinsic_ssbo_atomic_umax:
590bf215546Sopenharmony_ci   case nir_intrinsic_ssbo_atomic_umin:
591bf215546Sopenharmony_ci   case nir_intrinsic_ssbo_atomic_and:
592bf215546Sopenharmony_ci   case nir_intrinsic_ssbo_atomic_exchange:
593bf215546Sopenharmony_ci   case nir_intrinsic_image_load:
594bf215546Sopenharmony_ci   case nir_intrinsic_image_atomic_add:
595bf215546Sopenharmony_ci   case nir_intrinsic_image_atomic_and:
596bf215546Sopenharmony_ci   case nir_intrinsic_image_atomic_or:
597bf215546Sopenharmony_ci   case nir_intrinsic_image_atomic_xor:
598bf215546Sopenharmony_ci   case nir_intrinsic_image_atomic_exchange:
599bf215546Sopenharmony_ci   case nir_intrinsic_image_atomic_comp_swap:
600bf215546Sopenharmony_ci   case nir_intrinsic_image_atomic_umin:
601bf215546Sopenharmony_ci   case nir_intrinsic_image_atomic_umax:
602bf215546Sopenharmony_ci   case nir_intrinsic_image_atomic_imin:
603bf215546Sopenharmony_ci   case nir_intrinsic_image_atomic_imax:
604bf215546Sopenharmony_ci      m_flags.set(sh_needs_sbo_ret_address);
605bf215546Sopenharmony_ci      FALLTHROUGH;
606bf215546Sopenharmony_ci   case nir_intrinsic_image_store:
607bf215546Sopenharmony_ci   case nir_intrinsic_store_ssbo:
608bf215546Sopenharmony_ci      m_flags.set(sh_writes_memory);
609bf215546Sopenharmony_ci      m_flags.set(sh_uses_images);
610bf215546Sopenharmony_ci      break;
611bf215546Sopenharmony_ci   case nir_intrinsic_memory_barrier_image:
612bf215546Sopenharmony_ci   case nir_intrinsic_memory_barrier_buffer:
613bf215546Sopenharmony_ci   case nir_intrinsic_memory_barrier:
614bf215546Sopenharmony_ci   case nir_intrinsic_group_memory_barrier:
615bf215546Sopenharmony_ci      m_chain_instr.prepare_mem_barrier = true;
616bf215546Sopenharmony_ci   default:
617bf215546Sopenharmony_ci      ;
618bf215546Sopenharmony_ci   }
619bf215546Sopenharmony_ci   return true;
620bf215546Sopenharmony_ci}
621bf215546Sopenharmony_ci
622bf215546Sopenharmony_cibool Shader::process_cf_node(nir_cf_node *node)
623bf215546Sopenharmony_ci{
624bf215546Sopenharmony_ci   SFN_TRACE_FUNC(SfnLog::flow, "CF");
625bf215546Sopenharmony_ci
626bf215546Sopenharmony_ci   switch (node->type) {
627bf215546Sopenharmony_ci   case nir_cf_node_block:
628bf215546Sopenharmony_ci   return process_block(nir_cf_node_as_block(node));
629bf215546Sopenharmony_ci   case nir_cf_node_if:
630bf215546Sopenharmony_ci   return process_if(nir_cf_node_as_if(node));
631bf215546Sopenharmony_ci   case nir_cf_node_loop:
632bf215546Sopenharmony_ci   return process_loop(nir_cf_node_as_loop(node));
633bf215546Sopenharmony_ci   default:
634bf215546Sopenharmony_ci   return false;
635bf215546Sopenharmony_ci   }
636bf215546Sopenharmony_ci
637bf215546Sopenharmony_ci}
638bf215546Sopenharmony_ci
639bf215546Sopenharmony_cistatic bool
640bf215546Sopenharmony_cichild_block_empty (const exec_list& list)
641bf215546Sopenharmony_ci{
642bf215546Sopenharmony_ci   if (list.is_empty())
643bf215546Sopenharmony_ci      return true;
644bf215546Sopenharmony_ci
645bf215546Sopenharmony_ci   bool result = true;
646bf215546Sopenharmony_ci
647bf215546Sopenharmony_ci   foreach_list_typed(nir_cf_node, n, node, &list) {
648bf215546Sopenharmony_ci
649bf215546Sopenharmony_ci      if (n->type == nir_cf_node_block) {
650bf215546Sopenharmony_ci         if (!nir_cf_node_as_block(n)->instr_list.is_empty())
651bf215546Sopenharmony_ci            return false;
652bf215546Sopenharmony_ci      }
653bf215546Sopenharmony_ci      if (n->type == nir_cf_node_if)
654bf215546Sopenharmony_ci         return false;
655bf215546Sopenharmony_ci   }
656bf215546Sopenharmony_ci   return result;
657bf215546Sopenharmony_ci}
658bf215546Sopenharmony_ci
659bf215546Sopenharmony_cibool Shader::process_if(nir_if *if_stmt)
660bf215546Sopenharmony_ci{
661bf215546Sopenharmony_ci   SFN_TRACE_FUNC(SfnLog::flow, "IF");
662bf215546Sopenharmony_ci
663bf215546Sopenharmony_ci   if (!emit_if_start(if_stmt))
664bf215546Sopenharmony_ci      return false;
665bf215546Sopenharmony_ci
666bf215546Sopenharmony_ci   foreach_list_typed(nir_cf_node, n, node, &if_stmt->then_list) {
667bf215546Sopenharmony_ci      SFN_TRACE_FUNC(SfnLog::flow, "IF-then");
668bf215546Sopenharmony_ci         if (!process_cf_node(n))
669bf215546Sopenharmony_ci            return false;
670bf215546Sopenharmony_ci   }
671bf215546Sopenharmony_ci
672bf215546Sopenharmony_ci   if (!child_block_empty(if_stmt->else_list)) {
673bf215546Sopenharmony_ci      if (!emit_control_flow(ControlFlowInstr::cf_else))
674bf215546Sopenharmony_ci         return false;
675bf215546Sopenharmony_ci      foreach_list_typed(nir_cf_node, n, node, &if_stmt->else_list)
676bf215546Sopenharmony_ci            if (!process_cf_node(n)) return false;
677bf215546Sopenharmony_ci   }
678bf215546Sopenharmony_ci
679bf215546Sopenharmony_ci   if (!emit_control_flow(ControlFlowInstr::cf_endif))
680bf215546Sopenharmony_ci      return false;
681bf215546Sopenharmony_ci
682bf215546Sopenharmony_ci   return true;
683bf215546Sopenharmony_ci}
684bf215546Sopenharmony_ci
685bf215546Sopenharmony_cibool Shader::emit_if_start(nir_if *if_stmt)
686bf215546Sopenharmony_ci{
687bf215546Sopenharmony_ci   auto value = value_factory().src(if_stmt->condition, 0);
688bf215546Sopenharmony_ci   AluInstr *pred = new AluInstr(op2_pred_setne_int, value_factory().temp_register(),
689bf215546Sopenharmony_ci                                 value, value_factory().zero(), AluInstr::last);
690bf215546Sopenharmony_ci   pred->set_alu_flag(alu_update_exec);
691bf215546Sopenharmony_ci   pred->set_alu_flag(alu_update_pred);
692bf215546Sopenharmony_ci   pred->set_cf_type(cf_alu_push_before);
693bf215546Sopenharmony_ci
694bf215546Sopenharmony_ci   IfInstr *ir = new IfInstr(pred);
695bf215546Sopenharmony_ci   emit_instruction(ir);
696bf215546Sopenharmony_ci   start_new_block(1);
697bf215546Sopenharmony_ci   return true;
698bf215546Sopenharmony_ci}
699bf215546Sopenharmony_ci
700bf215546Sopenharmony_cibool Shader::emit_control_flow(ControlFlowInstr::CFType type)
701bf215546Sopenharmony_ci{
702bf215546Sopenharmony_ci   auto ir = new ControlFlowInstr(type);
703bf215546Sopenharmony_ci   emit_instruction(ir);
704bf215546Sopenharmony_ci   int depth = 0;
705bf215546Sopenharmony_ci   switch (type) {
706bf215546Sopenharmony_ci   case ControlFlowInstr::cf_loop_begin:
707bf215546Sopenharmony_ci      m_loops.push_back(ir);
708bf215546Sopenharmony_ci      m_nloops++;
709bf215546Sopenharmony_ci      depth = 1;
710bf215546Sopenharmony_ci   break;
711bf215546Sopenharmony_ci   case ControlFlowInstr::cf_loop_end:
712bf215546Sopenharmony_ci      m_loops.pop_back();
713bf215546Sopenharmony_ci      FALLTHROUGH;
714bf215546Sopenharmony_ci   case ControlFlowInstr::cf_endif:
715bf215546Sopenharmony_ci      depth = -1;
716bf215546Sopenharmony_ci   break;
717bf215546Sopenharmony_ci   default:
718bf215546Sopenharmony_ci      ;
719bf215546Sopenharmony_ci   }
720bf215546Sopenharmony_ci
721bf215546Sopenharmony_ci   start_new_block(depth);
722bf215546Sopenharmony_ci   return true;
723bf215546Sopenharmony_ci}
724bf215546Sopenharmony_ci
725bf215546Sopenharmony_cibool Shader::process_loop(nir_loop *node)
726bf215546Sopenharmony_ci{
727bf215546Sopenharmony_ci   SFN_TRACE_FUNC(SfnLog::flow, "LOOP");
728bf215546Sopenharmony_ci   if (!emit_control_flow(ControlFlowInstr::cf_loop_begin))
729bf215546Sopenharmony_ci      return false;
730bf215546Sopenharmony_ci
731bf215546Sopenharmony_ci   foreach_list_typed(nir_cf_node, n, node, &node->body)
732bf215546Sopenharmony_ci         if (!process_cf_node(n)) return false;
733bf215546Sopenharmony_ci
734bf215546Sopenharmony_ci   if (!emit_control_flow(ControlFlowInstr::cf_loop_end))
735bf215546Sopenharmony_ci      return false;
736bf215546Sopenharmony_ci
737bf215546Sopenharmony_ci   return true;
738bf215546Sopenharmony_ci}
739bf215546Sopenharmony_ci
740bf215546Sopenharmony_cibool Shader::process_block(nir_block *block)
741bf215546Sopenharmony_ci{
742bf215546Sopenharmony_ci   SFN_TRACE_FUNC(SfnLog::flow, "BLOCK");
743bf215546Sopenharmony_ci
744bf215546Sopenharmony_ci   nir_foreach_instr(instr, block) {
745bf215546Sopenharmony_ci      sfn_log << SfnLog::instr << "FROM:" << *instr << "\n";
746bf215546Sopenharmony_ci      bool r = process_instr(instr);
747bf215546Sopenharmony_ci      if (!r) {
748bf215546Sopenharmony_ci         sfn_log << SfnLog::err << "R600: Unsupported instruction: "
749bf215546Sopenharmony_ci                 << *instr << "\n";
750bf215546Sopenharmony_ci         return false;
751bf215546Sopenharmony_ci      }
752bf215546Sopenharmony_ci   }
753bf215546Sopenharmony_ci   return true;
754bf215546Sopenharmony_ci}
755bf215546Sopenharmony_ci
756bf215546Sopenharmony_cibool Shader::process_instr(nir_instr *instr)
757bf215546Sopenharmony_ci{
758bf215546Sopenharmony_ci   return m_instr_factory->from_nir(instr, *this);
759bf215546Sopenharmony_ci}
760bf215546Sopenharmony_ci
761bf215546Sopenharmony_cibool Shader::process_intrinsic(nir_intrinsic_instr *intr)
762bf215546Sopenharmony_ci{
763bf215546Sopenharmony_ci   if (process_stage_intrinsic(intr))
764bf215546Sopenharmony_ci      return true;
765bf215546Sopenharmony_ci
766bf215546Sopenharmony_ci   if (GDSInstr::emit_atomic_counter(intr, *this)) {
767bf215546Sopenharmony_ci      set_flag(sh_writes_memory);
768bf215546Sopenharmony_ci      return true;
769bf215546Sopenharmony_ci   }
770bf215546Sopenharmony_ci
771bf215546Sopenharmony_ci   if (RatInstr::emit(intr, *this))
772bf215546Sopenharmony_ci      return true;
773bf215546Sopenharmony_ci
774bf215546Sopenharmony_ci   switch (intr->intrinsic) {
775bf215546Sopenharmony_ci   case nir_intrinsic_store_output: return store_output(intr);
776bf215546Sopenharmony_ci   case nir_intrinsic_load_input: return load_input(intr);
777bf215546Sopenharmony_ci   case nir_intrinsic_load_uniform: return load_uniform(intr);
778bf215546Sopenharmony_ci   case nir_intrinsic_load_ubo_vec4: return load_ubo(intr);
779bf215546Sopenharmony_ci   case nir_intrinsic_store_scratch: return emit_store_scratch(intr);
780bf215546Sopenharmony_ci   case nir_intrinsic_load_scratch: return emit_load_scratch(intr);
781bf215546Sopenharmony_ci   case nir_intrinsic_store_local_shared_r600: return emit_local_store(intr);
782bf215546Sopenharmony_ci   case nir_intrinsic_load_local_shared_r600: return emit_local_load(intr);
783bf215546Sopenharmony_ci   case nir_intrinsic_load_tcs_in_param_base_r600: return emit_load_tcs_param_base(intr, 0);
784bf215546Sopenharmony_ci   case nir_intrinsic_load_tcs_out_param_base_r600: return emit_load_tcs_param_base(intr, 16);
785bf215546Sopenharmony_ci      // We only emit the group barrier, barriers across work groups
786bf215546Sopenharmony_ci      // are not yet implemented
787bf215546Sopenharmony_ci   case nir_intrinsic_control_barrier:
788bf215546Sopenharmony_ci   case nir_intrinsic_memory_barrier_tcs_patch:
789bf215546Sopenharmony_ci   case nir_intrinsic_memory_barrier_shared:
790bf215546Sopenharmony_ci      return emit_barrier(intr);
791bf215546Sopenharmony_ci   case nir_intrinsic_memory_barrier_atomic_counter:
792bf215546Sopenharmony_ci      return true;
793bf215546Sopenharmony_ci   case nir_intrinsic_group_memory_barrier:
794bf215546Sopenharmony_ci   case nir_intrinsic_memory_barrier_image:
795bf215546Sopenharmony_ci   case nir_intrinsic_memory_barrier_buffer:
796bf215546Sopenharmony_ci   case nir_intrinsic_memory_barrier:
797bf215546Sopenharmony_ci      return emit_wait_ack();
798bf215546Sopenharmony_ci
799bf215546Sopenharmony_ci   case nir_intrinsic_shared_atomic_add:
800bf215546Sopenharmony_ci   case nir_intrinsic_shared_atomic_and:
801bf215546Sopenharmony_ci   case nir_intrinsic_shared_atomic_or:
802bf215546Sopenharmony_ci   case nir_intrinsic_shared_atomic_imax:
803bf215546Sopenharmony_ci   case nir_intrinsic_shared_atomic_umax:
804bf215546Sopenharmony_ci   case nir_intrinsic_shared_atomic_imin:
805bf215546Sopenharmony_ci   case nir_intrinsic_shared_atomic_umin:
806bf215546Sopenharmony_ci   case nir_intrinsic_shared_atomic_xor:
807bf215546Sopenharmony_ci   case nir_intrinsic_shared_atomic_exchange:
808bf215546Sopenharmony_ci   case nir_intrinsic_shared_atomic_comp_swap:
809bf215546Sopenharmony_ci      return emit_atomic_local_shared(intr);
810bf215546Sopenharmony_ci   case nir_intrinsic_shader_clock:
811bf215546Sopenharmony_ci      return emit_shader_clock(intr);
812bf215546Sopenharmony_ci
813bf215546Sopenharmony_ci   default:
814bf215546Sopenharmony_ci   return false;
815bf215546Sopenharmony_ci   }
816bf215546Sopenharmony_ci}
817bf215546Sopenharmony_ci
818bf215546Sopenharmony_cistatic ESDOp
819bf215546Sopenharmony_cilds_op_from_intrinsic(nir_intrinsic_op op, bool ret) {
820bf215546Sopenharmony_ci   switch (op) {
821bf215546Sopenharmony_ci   case nir_intrinsic_shared_atomic_add:
822bf215546Sopenharmony_ci      return ret ? LDS_ADD_RET : LDS_ADD;
823bf215546Sopenharmony_ci   case nir_intrinsic_shared_atomic_and:
824bf215546Sopenharmony_ci      return ret ? LDS_AND_RET : LDS_AND;
825bf215546Sopenharmony_ci   case nir_intrinsic_shared_atomic_or:
826bf215546Sopenharmony_ci      return ret ? LDS_OR_RET : LDS_OR;
827bf215546Sopenharmony_ci   case nir_intrinsic_shared_atomic_imax:
828bf215546Sopenharmony_ci      return ret ? LDS_MAX_INT_RET : LDS_MAX_INT;
829bf215546Sopenharmony_ci   case nir_intrinsic_shared_atomic_umax:
830bf215546Sopenharmony_ci      return ret ? LDS_MAX_UINT_RET : LDS_MAX_UINT;
831bf215546Sopenharmony_ci   case nir_intrinsic_shared_atomic_imin:
832bf215546Sopenharmony_ci      return ret ? LDS_MIN_INT_RET : LDS_MIN_INT;
833bf215546Sopenharmony_ci   case nir_intrinsic_shared_atomic_umin:
834bf215546Sopenharmony_ci      return ret ? LDS_MIN_UINT_RET : LDS_MIN_UINT;
835bf215546Sopenharmony_ci   case nir_intrinsic_shared_atomic_xor:
836bf215546Sopenharmony_ci      return ret ? LDS_XOR_RET : LDS_XOR;
837bf215546Sopenharmony_ci   case nir_intrinsic_shared_atomic_exchange:
838bf215546Sopenharmony_ci      return LDS_XCHG_RET;
839bf215546Sopenharmony_ci   case nir_intrinsic_shared_atomic_comp_swap:
840bf215546Sopenharmony_ci      return LDS_CMP_XCHG_RET;
841bf215546Sopenharmony_ci   default:
842bf215546Sopenharmony_ci      unreachable("Unsupported shared atomic opcode");
843bf215546Sopenharmony_ci   }
844bf215546Sopenharmony_ci}
845bf215546Sopenharmony_ci
846bf215546Sopenharmony_ciPRegister Shader::emit_load_to_register(PVirtualValue src)
847bf215546Sopenharmony_ci{
848bf215546Sopenharmony_ci   assert(src);
849bf215546Sopenharmony_ci   PRegister dest = src->as_register();
850bf215546Sopenharmony_ci
851bf215546Sopenharmony_ci   if (!dest) {
852bf215546Sopenharmony_ci      dest = value_factory().temp_register();
853bf215546Sopenharmony_ci      emit_instruction(new AluInstr(op1_mov, dest, src, AluInstr::last_write));
854bf215546Sopenharmony_ci   }
855bf215546Sopenharmony_ci   return dest;
856bf215546Sopenharmony_ci}
857bf215546Sopenharmony_ci
858bf215546Sopenharmony_cibool Shader::emit_atomic_local_shared(nir_intrinsic_instr* instr)
859bf215546Sopenharmony_ci{
860bf215546Sopenharmony_ci   bool uses_retval = !instr->dest.is_ssa || !list_is_empty(&instr->dest.ssa.uses);
861bf215546Sopenharmony_ci
862bf215546Sopenharmony_ci   auto& vf = value_factory();
863bf215546Sopenharmony_ci
864bf215546Sopenharmony_ci   auto dest_value = uses_retval ? vf.dest(instr->dest, 0, pin_free) : nullptr;
865bf215546Sopenharmony_ci
866bf215546Sopenharmony_ci   auto op = lds_op_from_intrinsic(instr->intrinsic, uses_retval);
867bf215546Sopenharmony_ci
868bf215546Sopenharmony_ci   auto address = vf.src(instr->src[0], 0);
869bf215546Sopenharmony_ci
870bf215546Sopenharmony_ci   AluInstr::SrcValues src;
871bf215546Sopenharmony_ci   src.push_back(vf.src(instr->src[1], 0));
872bf215546Sopenharmony_ci
873bf215546Sopenharmony_ci   if (unlikely(instr->intrinsic ==nir_intrinsic_shared_atomic_comp_swap))
874bf215546Sopenharmony_ci      src.push_back(vf.src(instr->src[2], 0));
875bf215546Sopenharmony_ci   emit_instruction(new LDSAtomicInstr(op, dest_value, address, src));
876bf215546Sopenharmony_ci   return true;
877bf215546Sopenharmony_ci}
878bf215546Sopenharmony_ci
879bf215546Sopenharmony_ciauto Shader::evaluate_resource_offset(nir_intrinsic_instr *instr, int src_id) -> std::pair<int, PRegister>
880bf215546Sopenharmony_ci{
881bf215546Sopenharmony_ci   auto& vf = value_factory();
882bf215546Sopenharmony_ci
883bf215546Sopenharmony_ci   PRegister uav_id{nullptr};
884bf215546Sopenharmony_ci   int offset = 0;
885bf215546Sopenharmony_ci
886bf215546Sopenharmony_ci   auto uav_id_const = nir_src_as_const_value(instr->src[src_id]);
887bf215546Sopenharmony_ci   if (uav_id_const) {
888bf215546Sopenharmony_ci      offset += uav_id_const->u32;
889bf215546Sopenharmony_ci   } else {
890bf215546Sopenharmony_ci      auto uav_id_val = vf.src(instr->src[src_id], 0);
891bf215546Sopenharmony_ci      if (uav_id_val->as_register()) {
892bf215546Sopenharmony_ci         uav_id = uav_id_val->as_register();
893bf215546Sopenharmony_ci      } else {
894bf215546Sopenharmony_ci         uav_id = vf.temp_register();
895bf215546Sopenharmony_ci         emit_instruction(new AluInstr(op1_mov, uav_id, uav_id_val,
896bf215546Sopenharmony_ci                                 AluInstr::last_write));
897bf215546Sopenharmony_ci      }
898bf215546Sopenharmony_ci   }
899bf215546Sopenharmony_ci   return std::make_pair(offset, uav_id);
900bf215546Sopenharmony_ci}
901bf215546Sopenharmony_ci
902bf215546Sopenharmony_ci
903bf215546Sopenharmony_cibool Shader::emit_store_scratch(nir_intrinsic_instr *intr)
904bf215546Sopenharmony_ci{
905bf215546Sopenharmony_ci   auto& vf = m_instr_factory->value_factory();
906bf215546Sopenharmony_ci
907bf215546Sopenharmony_ci   int writemask = nir_intrinsic_write_mask(intr);
908bf215546Sopenharmony_ci
909bf215546Sopenharmony_ci
910bf215546Sopenharmony_ci   RegisterVec4::Swizzle swz = {7,7,7,7};
911bf215546Sopenharmony_ci
912bf215546Sopenharmony_ci   for (unsigned i = 0; i < intr->num_components; ++i)
913bf215546Sopenharmony_ci      swz[i] = (1 << i) & writemask ? i : 7;
914bf215546Sopenharmony_ci
915bf215546Sopenharmony_ci   auto value = vf.temp_vec4(pin_group, swz);
916bf215546Sopenharmony_ci   AluInstr *ir = nullptr;
917bf215546Sopenharmony_ci   for (unsigned i = 0; i < intr->num_components; ++i) {
918bf215546Sopenharmony_ci      if (value[i]->chan() < 4) {
919bf215546Sopenharmony_ci         ir = new AluInstr(op1_mov, value[i], vf.src(intr->src[0], i), AluInstr::write);
920bf215546Sopenharmony_ci         ir->set_alu_flag(alu_no_schedule_bias);
921bf215546Sopenharmony_ci         emit_instruction(ir);
922bf215546Sopenharmony_ci      }
923bf215546Sopenharmony_ci   }
924bf215546Sopenharmony_ci   if (!ir)
925bf215546Sopenharmony_ci      return true;
926bf215546Sopenharmony_ci
927bf215546Sopenharmony_ci   ir->set_alu_flag(alu_last_instr);
928bf215546Sopenharmony_ci
929bf215546Sopenharmony_ci   auto address = vf.src(intr->src[1], 0);
930bf215546Sopenharmony_ci
931bf215546Sopenharmony_ci
932bf215546Sopenharmony_ci   int align = nir_intrinsic_align_mul(intr);
933bf215546Sopenharmony_ci   int align_offset = nir_intrinsic_align_offset(intr);
934bf215546Sopenharmony_ci
935bf215546Sopenharmony_ci   ScratchIOInstr *ws_ir = nullptr;
936bf215546Sopenharmony_ci
937bf215546Sopenharmony_ci   int offset = -1;
938bf215546Sopenharmony_ci   if (address->as_literal()) {
939bf215546Sopenharmony_ci      offset = address->as_literal()->value();
940bf215546Sopenharmony_ci   } else if (address->as_inline_const()) {
941bf215546Sopenharmony_ci      auto il = address->as_inline_const();
942bf215546Sopenharmony_ci      if (il->sel() == ALU_SRC_0)
943bf215546Sopenharmony_ci         offset = 0;
944bf215546Sopenharmony_ci      else if (il->sel() == ALU_SRC_1_INT)
945bf215546Sopenharmony_ci         offset = 1;
946bf215546Sopenharmony_ci   }
947bf215546Sopenharmony_ci
948bf215546Sopenharmony_ci   if (offset >= 0) {
949bf215546Sopenharmony_ci      ws_ir = new ScratchIOInstr(value, offset, align, align_offset, writemask);
950bf215546Sopenharmony_ci   } else {
951bf215546Sopenharmony_ci      auto addr_temp  = vf.temp_register(0);
952bf215546Sopenharmony_ci      auto load_addr = new AluInstr(op1_mov, addr_temp, address, AluInstr::last_write);
953bf215546Sopenharmony_ci      load_addr->set_alu_flag(alu_no_schedule_bias);
954bf215546Sopenharmony_ci      emit_instruction(load_addr);
955bf215546Sopenharmony_ci
956bf215546Sopenharmony_ci      ws_ir = new ScratchIOInstr(value, addr_temp, align, align_offset, writemask, m_scratch_size);
957bf215546Sopenharmony_ci   }
958bf215546Sopenharmony_ci   emit_instruction(ws_ir);
959bf215546Sopenharmony_ci
960bf215546Sopenharmony_ci   m_flags.set(sh_needs_scratch_space);
961bf215546Sopenharmony_ci   return true;
962bf215546Sopenharmony_ci}
963bf215546Sopenharmony_ci
964bf215546Sopenharmony_cibool Shader::emit_load_scratch(nir_intrinsic_instr *intr)
965bf215546Sopenharmony_ci{
966bf215546Sopenharmony_ci   auto addr = value_factory().src(intr->src[0], 0);
967bf215546Sopenharmony_ci   auto dest = value_factory().dest_vec4(intr->dest, pin_group);
968bf215546Sopenharmony_ci
969bf215546Sopenharmony_ci   if (chip_class() >= ISA_CC_R700) {
970bf215546Sopenharmony_ci      RegisterVec4::Swizzle dest_swz = {7,7,7,7};
971bf215546Sopenharmony_ci
972bf215546Sopenharmony_ci      for (unsigned i = 0; i < intr->num_components; ++i)
973bf215546Sopenharmony_ci         dest_swz[i] = i;
974bf215546Sopenharmony_ci
975bf215546Sopenharmony_ci      auto *ir = new LoadFromScratch(dest, dest_swz, addr, m_scratch_size);
976bf215546Sopenharmony_ci      emit_instruction(ir);
977bf215546Sopenharmony_ci      chain_scratch_read(ir);
978bf215546Sopenharmony_ci   } else {
979bf215546Sopenharmony_ci      int align = nir_intrinsic_align_mul(intr);
980bf215546Sopenharmony_ci      int align_offset = nir_intrinsic_align_offset(intr);
981bf215546Sopenharmony_ci
982bf215546Sopenharmony_ci
983bf215546Sopenharmony_ci      int offset = -1;
984bf215546Sopenharmony_ci      if (addr->as_literal()) {
985bf215546Sopenharmony_ci         offset = addr->as_literal()->value();
986bf215546Sopenharmony_ci      } else if (addr->as_inline_const()) {
987bf215546Sopenharmony_ci         auto il = addr->as_inline_const();
988bf215546Sopenharmony_ci         if (il->sel() == ALU_SRC_0)
989bf215546Sopenharmony_ci            offset = 0;
990bf215546Sopenharmony_ci         else if (il->sel() == ALU_SRC_1_INT)
991bf215546Sopenharmony_ci            offset = 1;
992bf215546Sopenharmony_ci      }
993bf215546Sopenharmony_ci
994bf215546Sopenharmony_ci      ScratchIOInstr *ir = nullptr;
995bf215546Sopenharmony_ci      if (offset >= 0) {
996bf215546Sopenharmony_ci         ir = new ScratchIOInstr(dest, offset, align, align_offset, 0xf, true);
997bf215546Sopenharmony_ci      } else {
998bf215546Sopenharmony_ci         auto addr_temp  = value_factory().temp_register(0);
999bf215546Sopenharmony_ci         auto load_addr = new AluInstr(op1_mov, addr_temp, addr, AluInstr::last_write);
1000bf215546Sopenharmony_ci         load_addr->set_alu_flag(alu_no_schedule_bias);
1001bf215546Sopenharmony_ci         emit_instruction(load_addr);
1002bf215546Sopenharmony_ci
1003bf215546Sopenharmony_ci         ir = new ScratchIOInstr(dest, addr_temp, align, align_offset, 0xf,
1004bf215546Sopenharmony_ci                                 m_scratch_size, true);
1005bf215546Sopenharmony_ci      }
1006bf215546Sopenharmony_ci      emit_instruction(ir);
1007bf215546Sopenharmony_ci   }
1008bf215546Sopenharmony_ci
1009bf215546Sopenharmony_ci
1010bf215546Sopenharmony_ci   m_flags.set(sh_needs_scratch_space);
1011bf215546Sopenharmony_ci
1012bf215546Sopenharmony_ci   return true;
1013bf215546Sopenharmony_ci
1014bf215546Sopenharmony_ci}
1015bf215546Sopenharmony_ci
1016bf215546Sopenharmony_cibool Shader::emit_local_store(nir_intrinsic_instr *instr)
1017bf215546Sopenharmony_ci{
1018bf215546Sopenharmony_ci   unsigned write_mask = nir_intrinsic_write_mask(instr);
1019bf215546Sopenharmony_ci
1020bf215546Sopenharmony_ci   auto address = value_factory().src(instr->src[1], 0);
1021bf215546Sopenharmony_ci   int swizzle_base = 0;
1022bf215546Sopenharmony_ci   unsigned w = write_mask;
1023bf215546Sopenharmony_ci   while (!(w & 1)) {
1024bf215546Sopenharmony_ci      ++swizzle_base;
1025bf215546Sopenharmony_ci      w >>= 1;
1026bf215546Sopenharmony_ci   }
1027bf215546Sopenharmony_ci   write_mask = write_mask >> swizzle_base;
1028bf215546Sopenharmony_ci
1029bf215546Sopenharmony_ci   if ((write_mask & 3) != 3) {
1030bf215546Sopenharmony_ci      auto value = value_factory().src(instr->src[0], swizzle_base);
1031bf215546Sopenharmony_ci      emit_instruction(new LDSAtomicInstr(LDS_WRITE, nullptr, address, {value}));
1032bf215546Sopenharmony_ci   } else {
1033bf215546Sopenharmony_ci      auto value = value_factory().src(instr->src[0], swizzle_base);
1034bf215546Sopenharmony_ci      auto value1 = value_factory().src(instr->src[0], swizzle_base + 1);
1035bf215546Sopenharmony_ci      emit_instruction(new LDSAtomicInstr(LDS_WRITE_REL, nullptr, address, {value, value1}));
1036bf215546Sopenharmony_ci   }
1037bf215546Sopenharmony_ci   return true;
1038bf215546Sopenharmony_ci}
1039bf215546Sopenharmony_ci
1040bf215546Sopenharmony_cibool Shader::emit_local_load(nir_intrinsic_instr* instr)
1041bf215546Sopenharmony_ci{
1042bf215546Sopenharmony_ci   auto address = value_factory().src_vec(instr->src[0], instr->num_components);
1043bf215546Sopenharmony_ci   auto dest_value = value_factory().dest_vec(instr->dest, instr->num_components);
1044bf215546Sopenharmony_ci   emit_instruction(new LDSReadInstr(dest_value, address));
1045bf215546Sopenharmony_ci   return true;
1046bf215546Sopenharmony_ci}
1047bf215546Sopenharmony_ci
1048bf215546Sopenharmony_civoid Shader::chain_scratch_read(Instr *instr)
1049bf215546Sopenharmony_ci{
1050bf215546Sopenharmony_ci   m_chain_instr.apply(instr, &m_chain_instr.last_scratch_instr);
1051bf215546Sopenharmony_ci}
1052bf215546Sopenharmony_ci
1053bf215546Sopenharmony_civoid Shader::chain_ssbo_read(Instr *instr)
1054bf215546Sopenharmony_ci{
1055bf215546Sopenharmony_ci   m_chain_instr.apply(instr, &m_chain_instr.last_ssbo_instr);
1056bf215546Sopenharmony_ci}
1057bf215546Sopenharmony_ci
1058bf215546Sopenharmony_cibool Shader::emit_wait_ack()
1059bf215546Sopenharmony_ci{
1060bf215546Sopenharmony_ci   start_new_block(0);
1061bf215546Sopenharmony_ci   emit_instruction(new ControlFlowInstr(ControlFlowInstr::cf_wait_ack));
1062bf215546Sopenharmony_ci   start_new_block(0);
1063bf215546Sopenharmony_ci   return true;
1064bf215546Sopenharmony_ci}
1065bf215546Sopenharmony_ci
1066bf215546Sopenharmony_civoid Shader::InstructionChain::visit(ScratchIOInstr *instr)
1067bf215546Sopenharmony_ci{
1068bf215546Sopenharmony_ci   apply(instr, &last_scratch_instr);
1069bf215546Sopenharmony_ci}
1070bf215546Sopenharmony_ci
1071bf215546Sopenharmony_civoid Shader::InstructionChain::visit(GDSInstr *instr)
1072bf215546Sopenharmony_ci{
1073bf215546Sopenharmony_ci   apply(instr, &last_gds_instr);
1074bf215546Sopenharmony_ci   for (auto& loop : this_shader->m_loops) {
1075bf215546Sopenharmony_ci      loop->set_instr_flag(Instr::vpm);
1076bf215546Sopenharmony_ci   }
1077bf215546Sopenharmony_ci}
1078bf215546Sopenharmony_ci
1079bf215546Sopenharmony_civoid Shader::InstructionChain::visit(RatInstr *instr)
1080bf215546Sopenharmony_ci{
1081bf215546Sopenharmony_ci   apply(instr, &last_ssbo_instr);
1082bf215546Sopenharmony_ci   for (auto& loop : this_shader->m_loops) {
1083bf215546Sopenharmony_ci      loop->set_instr_flag(Instr::vpm);
1084bf215546Sopenharmony_ci   }
1085bf215546Sopenharmony_ci
1086bf215546Sopenharmony_ci   if (prepare_mem_barrier)
1087bf215546Sopenharmony_ci      instr->set_ack();
1088bf215546Sopenharmony_ci
1089bf215546Sopenharmony_ci   if (this_shader->m_current_block->inc_rat_emitted() > 15)
1090bf215546Sopenharmony_ci      this_shader->start_new_block(0);
1091bf215546Sopenharmony_ci}
1092bf215546Sopenharmony_ci
1093bf215546Sopenharmony_civoid Shader::InstructionChain::apply(Instr *current, Instr **last) {
1094bf215546Sopenharmony_ci   if (*last)
1095bf215546Sopenharmony_ci      current->add_required_instr(*last);
1096bf215546Sopenharmony_ci   *last = current;
1097bf215546Sopenharmony_ci}
1098bf215546Sopenharmony_ci
1099bf215546Sopenharmony_civoid Shader::emit_instruction(PInst instr)
1100bf215546Sopenharmony_ci{
1101bf215546Sopenharmony_ci   sfn_log << SfnLog::instr << "   " << *instr << "\n";
1102bf215546Sopenharmony_ci   instr->accept(m_chain_instr);
1103bf215546Sopenharmony_ci   m_current_block->push_back(instr);
1104bf215546Sopenharmony_ci}
1105bf215546Sopenharmony_ci
1106bf215546Sopenharmony_cibool Shader::load_uniform(nir_intrinsic_instr *intr)
1107bf215546Sopenharmony_ci{
1108bf215546Sopenharmony_ci   auto literal = nir_src_as_const_value(intr->src[0]);
1109bf215546Sopenharmony_ci
1110bf215546Sopenharmony_ci   if (literal) {
1111bf215546Sopenharmony_ci      AluInstr *ir = nullptr;
1112bf215546Sopenharmony_ci      auto pin = intr->dest.is_ssa && nir_dest_num_components(intr->dest) == 1 ?
1113bf215546Sopenharmony_ci               pin_free : pin_none;
1114bf215546Sopenharmony_ci      for (unsigned i = 0; i < nir_dest_num_components(intr->dest); ++i) {
1115bf215546Sopenharmony_ci
1116bf215546Sopenharmony_ci         sfn_log << SfnLog::io << "uniform "
1117bf215546Sopenharmony_ci                 << intr->dest.ssa.index << " const["<< i << "]: "<< intr->const_index[i] << "\n";
1118bf215546Sopenharmony_ci
1119bf215546Sopenharmony_ci         auto uniform = value_factory().uniform(intr, i);
1120bf215546Sopenharmony_ci         ir = new AluInstr(op1_mov, value_factory().dest(intr->dest, i, pin),
1121bf215546Sopenharmony_ci                           uniform, {alu_write});
1122bf215546Sopenharmony_ci         emit_instruction(ir);
1123bf215546Sopenharmony_ci      }
1124bf215546Sopenharmony_ci      if (ir)
1125bf215546Sopenharmony_ci         ir->set_alu_flag(alu_last_instr);
1126bf215546Sopenharmony_ci      return true;
1127bf215546Sopenharmony_ci   } else {
1128bf215546Sopenharmony_ci      auto addr = value_factory().src(intr->src[0], 0);
1129bf215546Sopenharmony_ci      return load_uniform_indirect(intr, addr, 16 * nir_intrinsic_base(intr), 0);
1130bf215546Sopenharmony_ci   }
1131bf215546Sopenharmony_ci}
1132bf215546Sopenharmony_ci
1133bf215546Sopenharmony_cibool Shader::load_uniform_indirect(nir_intrinsic_instr *intr, PVirtualValue addr,
1134bf215546Sopenharmony_ci                                   int offset , int buffer_id)
1135bf215546Sopenharmony_ci{
1136bf215546Sopenharmony_ci   auto addr_reg = addr->as_register();
1137bf215546Sopenharmony_ci   if (!addr) {
1138bf215546Sopenharmony_ci      auto tmp = value_factory().temp_register();
1139bf215546Sopenharmony_ci      emit_instruction(new AluInstr(op1_mov, tmp, addr, AluInstr::last_write));
1140bf215546Sopenharmony_ci      addr = tmp;
1141bf215546Sopenharmony_ci   }
1142bf215546Sopenharmony_ci
1143bf215546Sopenharmony_ci   RegisterVec4 dest = value_factory().dest_vec4(intr->dest, pin_group);
1144bf215546Sopenharmony_ci
1145bf215546Sopenharmony_ci   auto ir = new LoadFromBuffer(dest, {0,1,2,3}, addr_reg, offset, buffer_id,
1146bf215546Sopenharmony_ci                                nullptr, fmt_32_32_32_32_float);
1147bf215546Sopenharmony_ci   emit_instruction(ir);
1148bf215546Sopenharmony_ci   m_flags.set(sh_indirect_const_file);
1149bf215546Sopenharmony_ci   return true;
1150bf215546Sopenharmony_ci}
1151bf215546Sopenharmony_ci
1152bf215546Sopenharmony_cibool Shader::emit_load_tcs_param_base(nir_intrinsic_instr* instr, int offset)
1153bf215546Sopenharmony_ci{
1154bf215546Sopenharmony_ci   auto src = value_factory().temp_register();
1155bf215546Sopenharmony_ci   emit_instruction(new AluInstr(op1_mov, src, value_factory().zero(),
1156bf215546Sopenharmony_ci                                 AluInstr::last_write));
1157bf215546Sopenharmony_ci
1158bf215546Sopenharmony_ci   auto dest = value_factory().dest_vec4(instr->dest, pin_group);
1159bf215546Sopenharmony_ci   auto fetch = new LoadFromBuffer(dest, {0,1,2,3}, src, offset,
1160bf215546Sopenharmony_ci                                   R600_LDS_INFO_CONST_BUFFER, nullptr,
1161bf215546Sopenharmony_ci                                   fmt_32_32_32_32);
1162bf215546Sopenharmony_ci
1163bf215546Sopenharmony_ci   fetch->set_fetch_flag(LoadFromBuffer::srf_mode);
1164bf215546Sopenharmony_ci   emit_instruction(fetch);
1165bf215546Sopenharmony_ci
1166bf215546Sopenharmony_ci   return true;
1167bf215546Sopenharmony_ci}
1168bf215546Sopenharmony_ci
1169bf215546Sopenharmony_cibool Shader::emit_shader_clock(nir_intrinsic_instr* instr)
1170bf215546Sopenharmony_ci{
1171bf215546Sopenharmony_ci   auto& vf = value_factory();
1172bf215546Sopenharmony_ci   auto group = new AluGroup();
1173bf215546Sopenharmony_ci   group->add_instruction(new AluInstr(op1_mov, vf.dest(instr->dest, 0, pin_chan),
1174bf215546Sopenharmony_ci                                       vf.inline_const(ALU_SRC_TIME_LO, 0), AluInstr::write));
1175bf215546Sopenharmony_ci   group->add_instruction(new AluInstr(op1_mov, vf.dest(instr->dest, 1, pin_chan),
1176bf215546Sopenharmony_ci                                       vf.inline_const(ALU_SRC_TIME_HI, 0), AluInstr::last_write));
1177bf215546Sopenharmony_ci   emit_instruction(group);
1178bf215546Sopenharmony_ci   return true;
1179bf215546Sopenharmony_ci}
1180bf215546Sopenharmony_ci
1181bf215546Sopenharmony_ci
1182bf215546Sopenharmony_cibool Shader::emit_barrier(nir_intrinsic_instr* intr)
1183bf215546Sopenharmony_ci{
1184bf215546Sopenharmony_ci   (void)intr;
1185bf215546Sopenharmony_ci   /* Put barrier into it's own block, so that optimizers and the
1186bf215546Sopenharmony_ci    * scheduler don't move code */
1187bf215546Sopenharmony_ci   start_new_block(0);
1188bf215546Sopenharmony_ci   auto op = new AluInstr(op0_group_barrier, 0);
1189bf215546Sopenharmony_ci   op->set_alu_flag(alu_last_instr);
1190bf215546Sopenharmony_ci   emit_instruction(op);
1191bf215546Sopenharmony_ci   start_new_block(0);
1192bf215546Sopenharmony_ci   return true;
1193bf215546Sopenharmony_ci}
1194bf215546Sopenharmony_ci
1195bf215546Sopenharmony_cibool Shader::load_ubo(nir_intrinsic_instr *instr)
1196bf215546Sopenharmony_ci{
1197bf215546Sopenharmony_ci   auto bufid = nir_src_as_const_value(instr->src[0]);
1198bf215546Sopenharmony_ci   auto buf_offset = nir_src_as_const_value(instr->src[1]);
1199bf215546Sopenharmony_ci
1200bf215546Sopenharmony_ci   if (!buf_offset) {
1201bf215546Sopenharmony_ci      /* TODO: if bufid is constant then this can also be solved by using the CF indes
1202bf215546Sopenharmony_ci       * on the ALU block, and this would probably make sense when there are more then one
1203bf215546Sopenharmony_ci       * loads with the same buffer ID. */
1204bf215546Sopenharmony_ci
1205bf215546Sopenharmony_ci      auto addr = value_factory().src(instr->src[1], 0)->as_register();
1206bf215546Sopenharmony_ci      RegisterVec4::Swizzle dest_swz {7,7,7,7};
1207bf215546Sopenharmony_ci      auto dest = value_factory().dest_vec4(instr->dest, pin_group);
1208bf215546Sopenharmony_ci
1209bf215546Sopenharmony_ci      for (unsigned i = 0; i < nir_dest_num_components(instr->dest); ++i) {
1210bf215546Sopenharmony_ci         dest_swz[i] = i + nir_intrinsic_component(instr);
1211bf215546Sopenharmony_ci      }
1212bf215546Sopenharmony_ci
1213bf215546Sopenharmony_ci      LoadFromBuffer *ir;
1214bf215546Sopenharmony_ci      if (bufid) {
1215bf215546Sopenharmony_ci         ir = new LoadFromBuffer(dest, dest_swz, addr, 0, 1 + bufid->u32,
1216bf215546Sopenharmony_ci                                 nullptr, fmt_32_32_32_32_float);
1217bf215546Sopenharmony_ci      } else {
1218bf215546Sopenharmony_ci         auto buffer_id = emit_load_to_register(value_factory().src(instr->src[0], 0));
1219bf215546Sopenharmony_ci         ir = new LoadFromBuffer(dest, dest_swz, addr, 0, 1, buffer_id,
1220bf215546Sopenharmony_ci                                 fmt_32_32_32_32_float);
1221bf215546Sopenharmony_ci      }
1222bf215546Sopenharmony_ci      emit_instruction(ir);
1223bf215546Sopenharmony_ci      return true;
1224bf215546Sopenharmony_ci   }
1225bf215546Sopenharmony_ci
1226bf215546Sopenharmony_ci   /* direct load using the constant cache */
1227bf215546Sopenharmony_ci   if (bufid) {
1228bf215546Sopenharmony_ci      int buf_cmp = nir_intrinsic_component(instr);
1229bf215546Sopenharmony_ci
1230bf215546Sopenharmony_ci      AluInstr *ir = nullptr;
1231bf215546Sopenharmony_ci      auto pin = instr->dest.is_ssa && nir_dest_num_components(instr->dest) == 1 ?
1232bf215546Sopenharmony_ci                    pin_free : pin_none;
1233bf215546Sopenharmony_ci      for (unsigned i = 0; i < nir_dest_num_components(instr->dest); ++i) {
1234bf215546Sopenharmony_ci
1235bf215546Sopenharmony_ci         sfn_log << SfnLog::io << "UBO[" << bufid << "] "
1236bf215546Sopenharmony_ci                 << instr->dest.ssa.index << " const["<< i << "]: "<< instr->const_index[i] << "\n";
1237bf215546Sopenharmony_ci
1238bf215546Sopenharmony_ci         auto uniform = value_factory().uniform(512 +  buf_offset->u32, i + buf_cmp, bufid->u32 + 1);
1239bf215546Sopenharmony_ci         ir = new AluInstr(op1_mov, value_factory().dest(instr->dest, i, pin),
1240bf215546Sopenharmony_ci                           uniform, {alu_write});
1241bf215546Sopenharmony_ci         emit_instruction(ir);
1242bf215546Sopenharmony_ci      }
1243bf215546Sopenharmony_ci      if (ir)
1244bf215546Sopenharmony_ci         ir->set_alu_flag(alu_last_instr);
1245bf215546Sopenharmony_ci      return true;
1246bf215546Sopenharmony_ci   } else {
1247bf215546Sopenharmony_ci      int buf_cmp = nir_intrinsic_component(instr);
1248bf215546Sopenharmony_ci      AluInstr *ir = nullptr;
1249bf215546Sopenharmony_ci      auto kc_id = value_factory().src(instr->src[0], 0);
1250bf215546Sopenharmony_ci
1251bf215546Sopenharmony_ci      for (unsigned i = 0; i < nir_dest_num_components(instr->dest); ++i) {
1252bf215546Sopenharmony_ci         int cmp = buf_cmp + i;
1253bf215546Sopenharmony_ci         auto u = new UniformValue(512 +  buf_offset->u32, cmp, kc_id);
1254bf215546Sopenharmony_ci         auto dest = value_factory().dest(instr->dest, i, pin_none);
1255bf215546Sopenharmony_ci         ir = new AluInstr(op1_mov,  dest, u, AluInstr::write);
1256bf215546Sopenharmony_ci         emit_instruction(ir);
1257bf215546Sopenharmony_ci      }
1258bf215546Sopenharmony_ci      if (ir)
1259bf215546Sopenharmony_ci         ir->set_alu_flag(alu_last_instr);
1260bf215546Sopenharmony_ci      m_indirect_files |= 1 << TGSI_FILE_CONSTANT;
1261bf215546Sopenharmony_ci      return true;
1262bf215546Sopenharmony_ci   }
1263bf215546Sopenharmony_ci}
1264bf215546Sopenharmony_ci
1265bf215546Sopenharmony_civoid Shader::start_new_block(int depth)
1266bf215546Sopenharmony_ci{
1267bf215546Sopenharmony_ci   int depth_offset = m_current_block ? m_current_block->nesting_depth() : 0;
1268bf215546Sopenharmony_ci   m_current_block = new Block(depth + depth_offset, m_next_block++);
1269bf215546Sopenharmony_ci   m_root.push_back(m_current_block);
1270bf215546Sopenharmony_ci}
1271bf215546Sopenharmony_ci
1272bf215546Sopenharmony_cibool Shader::emit_simple_mov(nir_dest& dest, int chan, PVirtualValue src, Pin pin)
1273bf215546Sopenharmony_ci{
1274bf215546Sopenharmony_ci   auto dst = value_factory().dest(dest, chan, pin);
1275bf215546Sopenharmony_ci   emit_instruction(new AluInstr(op1_mov, dst, src, AluInstr::last_write));
1276bf215546Sopenharmony_ci   return true;
1277bf215546Sopenharmony_ci}
1278bf215546Sopenharmony_ci
1279bf215546Sopenharmony_civoid Shader::print(std::ostream& os) const
1280bf215546Sopenharmony_ci{
1281bf215546Sopenharmony_ci   print_header(os);
1282bf215546Sopenharmony_ci
1283bf215546Sopenharmony_ci   for (auto& [dummy, i]: m_inputs) {
1284bf215546Sopenharmony_ci      i.print(os);
1285bf215546Sopenharmony_ci      os << "\n";
1286bf215546Sopenharmony_ci   }
1287bf215546Sopenharmony_ci
1288bf215546Sopenharmony_ci   for (auto& [dummy, o]: m_outputs) {
1289bf215546Sopenharmony_ci      o.print(os);
1290bf215546Sopenharmony_ci      os << "\n";
1291bf215546Sopenharmony_ci   }
1292bf215546Sopenharmony_ci
1293bf215546Sopenharmony_ci   os << "SHADER\n";
1294bf215546Sopenharmony_ci   for (auto& b : m_root)
1295bf215546Sopenharmony_ci      b->print(os);
1296bf215546Sopenharmony_ci}
1297bf215546Sopenharmony_ci
1298bf215546Sopenharmony_ciconst char *chip_class_names[] = {
1299bf215546Sopenharmony_ci   "R600",
1300bf215546Sopenharmony_ci   "R700",
1301bf215546Sopenharmony_ci   "EVERGREEN",
1302bf215546Sopenharmony_ci   "CAYMAN"
1303bf215546Sopenharmony_ci};
1304bf215546Sopenharmony_ci
1305bf215546Sopenharmony_civoid Shader::print_header(std::ostream& os) const
1306bf215546Sopenharmony_ci{
1307bf215546Sopenharmony_ci   assert(m_chip_class <= ISA_CC_CAYMAN);
1308bf215546Sopenharmony_ci   os << m_type_id << "\n";
1309bf215546Sopenharmony_ci   os << "CHIPCLASS " << chip_class_names[m_chip_class] << "\n";
1310bf215546Sopenharmony_ci   print_properties(os);
1311bf215546Sopenharmony_ci}
1312bf215546Sopenharmony_ci
1313bf215546Sopenharmony_civoid Shader::print_properties(std::ostream& os) const
1314bf215546Sopenharmony_ci{
1315bf215546Sopenharmony_ci   do_print_properties(os);
1316bf215546Sopenharmony_ci}
1317bf215546Sopenharmony_ci
1318bf215546Sopenharmony_cibool Shader::equal_to(const Shader& other) const
1319bf215546Sopenharmony_ci{
1320bf215546Sopenharmony_ci   if (m_root.size() != other.m_root.size())
1321bf215546Sopenharmony_ci      return false;
1322bf215546Sopenharmony_ci   return std::inner_product(m_root.begin(), m_root.end(),
1323bf215546Sopenharmony_ci                             other.m_root.begin(),
1324bf215546Sopenharmony_ci                             true,
1325bf215546Sopenharmony_ci                             [](bool lhs, bool rhs){ return lhs & rhs;},
1326bf215546Sopenharmony_ci                             [](const Block::Pointer lhs, const Block::Pointer rhs) -> bool {
1327bf215546Sopenharmony_ci                                return lhs->is_equal_to(*rhs);
1328bf215546Sopenharmony_ci                             });
1329bf215546Sopenharmony_ci}
1330bf215546Sopenharmony_ci
1331bf215546Sopenharmony_civoid Shader::get_shader_info(r600_shader *sh_info)
1332bf215546Sopenharmony_ci{
1333bf215546Sopenharmony_ci   sh_info->ninput = m_inputs.size();
1334bf215546Sopenharmony_ci   int lds_pos = 0;
1335bf215546Sopenharmony_ci   int input_array_array_loc = 0;
1336bf215546Sopenharmony_ci   for (auto& [index, info] : m_inputs) {
1337bf215546Sopenharmony_ci      r600_shader_io& io = sh_info->input[input_array_array_loc++];
1338bf215546Sopenharmony_ci
1339bf215546Sopenharmony_ci      io.sid = info.sid();
1340bf215546Sopenharmony_ci      io.gpr = info.gpr();
1341bf215546Sopenharmony_ci      io.spi_sid = info.spi_sid();
1342bf215546Sopenharmony_ci      io.ij_index = info.ij_index();
1343bf215546Sopenharmony_ci      io.name = info.name();
1344bf215546Sopenharmony_ci      io.interpolate = info.interpolator();
1345bf215546Sopenharmony_ci      io.interpolate_location = info.interpolate_loc();
1346bf215546Sopenharmony_ci      if (info.need_lds_pos())
1347bf215546Sopenharmony_ci         io.lds_pos = lds_pos++;
1348bf215546Sopenharmony_ci      else
1349bf215546Sopenharmony_ci         io.lds_pos = 0;
1350bf215546Sopenharmony_ci
1351bf215546Sopenharmony_ci      io.ring_offset = info.ring_offset();
1352bf215546Sopenharmony_ci      io.uses_interpolate_at_centroid = info.uses_interpolate_at_centroid();
1353bf215546Sopenharmony_ci
1354bf215546Sopenharmony_ci      sfn_log << SfnLog::io << "Emit Input [" << index << "] sid:" << io.sid << " spi_sid:" << io.spi_sid << "\n";
1355bf215546Sopenharmony_ci      assert(io.spi_sid >= 0);
1356bf215546Sopenharmony_ci   }
1357bf215546Sopenharmony_ci
1358bf215546Sopenharmony_ci   sh_info->nlds = lds_pos;
1359bf215546Sopenharmony_ci   sh_info->noutput = m_outputs.size();
1360bf215546Sopenharmony_ci   sh_info->num_loops = m_nloops;
1361bf215546Sopenharmony_ci   int output_array_array_loc = 0;
1362bf215546Sopenharmony_ci
1363bf215546Sopenharmony_ci   for (auto& [index, info] : m_outputs) {
1364bf215546Sopenharmony_ci      r600_shader_io& io = sh_info->output[output_array_array_loc++];
1365bf215546Sopenharmony_ci      io.sid = info.sid();
1366bf215546Sopenharmony_ci      io.gpr = info.gpr();
1367bf215546Sopenharmony_ci      io.spi_sid = info.spi_sid();
1368bf215546Sopenharmony_ci      io.name = info.name();
1369bf215546Sopenharmony_ci      io.write_mask = info.writemask();
1370bf215546Sopenharmony_ci
1371bf215546Sopenharmony_ci      sfn_log << SfnLog::io << "Emit output[" << index << "] sid:" << io.sid << " spi_sid:" << io.spi_sid << "\n";
1372bf215546Sopenharmony_ci      assert(io.spi_sid >= 0);
1373bf215546Sopenharmony_ci   }
1374bf215546Sopenharmony_ci
1375bf215546Sopenharmony_ci   sh_info->nhwatomic = m_nhwatomic;
1376bf215546Sopenharmony_ci   sh_info->atomic_base = m_atomic_base;
1377bf215546Sopenharmony_ci   sh_info->nhwatomic_ranges = m_atomics.size();
1378bf215546Sopenharmony_ci   for (unsigned i = 0; i < m_atomics.size(); ++i)
1379bf215546Sopenharmony_ci      sh_info->atomics[i] = m_atomics[i];
1380bf215546Sopenharmony_ci
1381bf215546Sopenharmony_ci   if (m_flags.test(sh_indirect_const_file))
1382bf215546Sopenharmony_ci         sh_info->indirect_files |= 1 << TGSI_FILE_CONSTANT;
1383bf215546Sopenharmony_ci
1384bf215546Sopenharmony_ci   if (m_flags.test(sh_indirect_atomic))
1385bf215546Sopenharmony_ci      sh_info->indirect_files |= 1 << TGSI_FILE_HW_ATOMIC;
1386bf215546Sopenharmony_ci
1387bf215546Sopenharmony_ci   sh_info->uses_tex_buffers = m_flags.test(sh_uses_tex_buffer);
1388bf215546Sopenharmony_ci
1389bf215546Sopenharmony_ci   value_factory().get_shader_info(sh_info);
1390bf215546Sopenharmony_ci
1391bf215546Sopenharmony_ci   sh_info->needs_scratch_space = m_flags.test(sh_needs_scratch_space);
1392bf215546Sopenharmony_ci   sh_info->uses_images = m_flags.test(sh_uses_images);
1393bf215546Sopenharmony_ci   sh_info->uses_atomics = m_flags.test(sh_uses_atomics);
1394bf215546Sopenharmony_ci   sh_info->has_txq_cube_array_z_comp = m_flags.test(sh_txs_cube_array_comp);
1395bf215546Sopenharmony_ci   sh_info->indirect_files = m_indirect_files;
1396bf215546Sopenharmony_ci   do_get_shader_info(sh_info);
1397bf215546Sopenharmony_ci}
1398bf215546Sopenharmony_ci
1399bf215546Sopenharmony_ciPRegister Shader::atomic_update()
1400bf215546Sopenharmony_ci{
1401bf215546Sopenharmony_ci   assert(m_atomic_update);
1402bf215546Sopenharmony_ci   return m_atomic_update;
1403bf215546Sopenharmony_ci}
1404bf215546Sopenharmony_ci
1405bf215546Sopenharmony_ciint Shader::remap_atomic_base(int base)
1406bf215546Sopenharmony_ci{
1407bf215546Sopenharmony_ci   return m_atomic_base_map[base];
1408bf215546Sopenharmony_ci}
1409bf215546Sopenharmony_ci
1410bf215546Sopenharmony_civoid Shader::do_get_shader_info(r600_shader *sh_info)
1411bf215546Sopenharmony_ci{
1412bf215546Sopenharmony_ci   sh_info->uses_atomics = m_nhwatomic > 0;
1413bf215546Sopenharmony_ci}
1414bf215546Sopenharmony_ci
1415bf215546Sopenharmony_ci
1416bf215546Sopenharmony_ciconst ShaderInput& Shader::input(int base) const
1417bf215546Sopenharmony_ci{
1418bf215546Sopenharmony_ci   auto io = m_inputs.find(base);
1419bf215546Sopenharmony_ci   assert(io != m_inputs.end());
1420bf215546Sopenharmony_ci   return io->second;
1421bf215546Sopenharmony_ci}
1422bf215546Sopenharmony_ci
1423bf215546Sopenharmony_ciconst ShaderOutput& Shader::output(int base) const
1424bf215546Sopenharmony_ci{
1425bf215546Sopenharmony_ci   auto io = m_outputs.find(base);
1426bf215546Sopenharmony_ci   assert(io != m_outputs.end());
1427bf215546Sopenharmony_ci   return io->second;
1428bf215546Sopenharmony_ci}
1429bf215546Sopenharmony_ci
1430bf215546Sopenharmony_ciLiveRangeMap Shader::prepare_live_range_map()
1431bf215546Sopenharmony_ci{
1432bf215546Sopenharmony_ci   return m_instr_factory->value_factory().prepare_live_range_map();
1433bf215546Sopenharmony_ci
1434bf215546Sopenharmony_ci}
1435bf215546Sopenharmony_ci
1436bf215546Sopenharmony_civoid Shader::reset_function(ShaderBlocks& new_root)
1437bf215546Sopenharmony_ci{
1438bf215546Sopenharmony_ci   std::swap(m_root, new_root);
1439bf215546Sopenharmony_ci}
1440bf215546Sopenharmony_ci
1441bf215546Sopenharmony_civoid Shader::finalize()
1442bf215546Sopenharmony_ci{
1443bf215546Sopenharmony_ci   do_finalize();
1444bf215546Sopenharmony_ci}
1445bf215546Sopenharmony_ci
1446bf215546Sopenharmony_civoid Shader::do_finalize()
1447bf215546Sopenharmony_ci{
1448bf215546Sopenharmony_ci
1449bf215546Sopenharmony_ci}
1450bf215546Sopenharmony_ci
1451bf215546Sopenharmony_ci}
1452