1bf215546Sopenharmony_ci/* -*- mesa-c++  -*-
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright (c) 2021 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_instr_alugroup.h"
28bf215546Sopenharmony_ci#include "sfn_instr_export.h"
29bf215546Sopenharmony_ci#include "sfn_instr_fetch.h"
30bf215546Sopenharmony_ci#include "sfn_instr_mem.h"
31bf215546Sopenharmony_ci#include "sfn_instr_lds.h"
32bf215546Sopenharmony_ci#include "sfn_instr_tex.h"
33bf215546Sopenharmony_ci#include "sfn_instr_controlflow.h"
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_ci#include <iostream>
36bf215546Sopenharmony_ci#include <sstream>
37bf215546Sopenharmony_ci#include <numeric>
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_cinamespace r600 {
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ciusing std::string;
42bf215546Sopenharmony_ciusing std::vector;
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_ciInstr::Instr():
45bf215546Sopenharmony_ci   m_use_count(0),
46bf215546Sopenharmony_ci   m_block_id(std::numeric_limits<int>::max()),
47bf215546Sopenharmony_ci   m_index(std::numeric_limits<int>::max())
48bf215546Sopenharmony_ci{
49bf215546Sopenharmony_ci}
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ciInstr::~Instr()
52bf215546Sopenharmony_ci{
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci}
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_civoid Instr::print(std::ostream& os) const
57bf215546Sopenharmony_ci{
58bf215546Sopenharmony_ci   do_print(os);
59bf215546Sopenharmony_ci}
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_cibool Instr::ready() const
62bf215546Sopenharmony_ci{
63bf215546Sopenharmony_ci   for (auto& i : m_required_instr)
64bf215546Sopenharmony_ci      if (!i->ready())
65bf215546Sopenharmony_ci         return false;
66bf215546Sopenharmony_ci   return do_ready();
67bf215546Sopenharmony_ci}
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_ciint int_from_string_with_prefix(const std::string& str, const std::string& prefix)
70bf215546Sopenharmony_ci{
71bf215546Sopenharmony_ci   if (str.substr(0, prefix.length()) != prefix) {
72bf215546Sopenharmony_ci      std::cerr << "Expect '" << prefix << "' as start of '" << str << "'\n";
73bf215546Sopenharmony_ci      assert(0);
74bf215546Sopenharmony_ci   }
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci   std::stringstream help(str.substr(prefix.length()));
77bf215546Sopenharmony_ci   int retval;
78bf215546Sopenharmony_ci   help >> retval;
79bf215546Sopenharmony_ci   return retval;
80bf215546Sopenharmony_ci}
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_ciint sel_and_szw_from_string(const std::string& str, RegisterVec4::Swizzle &swz, bool& is_ssa)
83bf215546Sopenharmony_ci{
84bf215546Sopenharmony_ci   assert(str[0] == 'R' || str[0] == '_' || str[0] == 'S');
85bf215546Sopenharmony_ci   int sel = 0;
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci   auto istr = str.begin() + 1;
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci   if (str[0] == '_') {
90bf215546Sopenharmony_ci      while (istr != str.end() && *istr == '_')
91bf215546Sopenharmony_ci         ++istr;
92bf215546Sopenharmony_ci      sel = std::numeric_limits<int>::max();
93bf215546Sopenharmony_ci   } else {
94bf215546Sopenharmony_ci      while (istr != str.end() && isdigit(*istr)) {
95bf215546Sopenharmony_ci         sel *= 10;
96bf215546Sopenharmony_ci         sel += *istr - '0';
97bf215546Sopenharmony_ci         ++istr;
98bf215546Sopenharmony_ci      }
99bf215546Sopenharmony_ci   }
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci   assert(*istr == '.');
102bf215546Sopenharmony_ci   istr++;
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_ci   int i = 0;
105bf215546Sopenharmony_ci   while (istr != str.end()) {
106bf215546Sopenharmony_ci      switch (*istr) {
107bf215546Sopenharmony_ci      case 'x': swz[i] = 0; break;
108bf215546Sopenharmony_ci      case 'y': swz[i] = 1; break;
109bf215546Sopenharmony_ci      case 'z': swz[i] = 2; break;
110bf215546Sopenharmony_ci      case 'w': swz[i] = 3; break;
111bf215546Sopenharmony_ci      case '0': swz[i] = 4; break;
112bf215546Sopenharmony_ci      case '1': swz[i] = 5; break;
113bf215546Sopenharmony_ci      case '_': swz[i] = 7; break;
114bf215546Sopenharmony_ci      default:
115bf215546Sopenharmony_ci         unreachable("Unknown swizzle character");
116bf215546Sopenharmony_ci      }
117bf215546Sopenharmony_ci      ++istr;
118bf215546Sopenharmony_ci      ++i;
119bf215546Sopenharmony_ci   }
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci   is_ssa = str[0] == 'S';
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci   return sel;
124bf215546Sopenharmony_ci}
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_cibool Instr::is_last() const
127bf215546Sopenharmony_ci{
128bf215546Sopenharmony_ci   return true;
129bf215546Sopenharmony_ci}
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_cibool Instr::set_dead()
132bf215546Sopenharmony_ci{
133bf215546Sopenharmony_ci   if (m_instr_flags.test(always_keep))
134bf215546Sopenharmony_ci      return false;
135bf215546Sopenharmony_ci   bool is_dead = propagate_death();
136bf215546Sopenharmony_ci   m_instr_flags.set(dead);
137bf215546Sopenharmony_ci   return is_dead;
138bf215546Sopenharmony_ci}
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_cibool Instr::propagate_death()
141bf215546Sopenharmony_ci{
142bf215546Sopenharmony_ci   return true;
143bf215546Sopenharmony_ci}
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_cibool Instr::replace_source(PRegister old_src, PVirtualValue new_src)
146bf215546Sopenharmony_ci{
147bf215546Sopenharmony_ci   (void)old_src;
148bf215546Sopenharmony_ci   (void)new_src;
149bf215546Sopenharmony_ci   return false;
150bf215546Sopenharmony_ci}
151bf215546Sopenharmony_ci
152bf215546Sopenharmony_civoid Instr::add_required_instr(Instr *instr)
153bf215546Sopenharmony_ci{
154bf215546Sopenharmony_ci   assert(instr);
155bf215546Sopenharmony_ci   m_required_instr.push_back(instr);
156bf215546Sopenharmony_ci   instr->m_dependend_instr.push_back(this);
157bf215546Sopenharmony_ci}
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_civoid Instr::replace_required_instr(Instr *old_instr, Instr *new_instr)
160bf215546Sopenharmony_ci{
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci   for (auto i = m_required_instr.begin(); i != m_required_instr.end(); ++i) {
163bf215546Sopenharmony_ci      if (*i == old_instr)
164bf215546Sopenharmony_ci         *i = new_instr;
165bf215546Sopenharmony_ci   }
166bf215546Sopenharmony_ci}
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_cibool Instr::replace_dest(PRegister new_dest, r600::AluInstr *move_instr)
169bf215546Sopenharmony_ci{
170bf215546Sopenharmony_ci   (void)new_dest;
171bf215546Sopenharmony_ci   (void)move_instr;
172bf215546Sopenharmony_ci   return false;
173bf215546Sopenharmony_ci}
174bf215546Sopenharmony_ci
175bf215546Sopenharmony_civoid Instr::set_blockid(int id, int index)
176bf215546Sopenharmony_ci{
177bf215546Sopenharmony_ci   m_block_id = id;
178bf215546Sopenharmony_ci   m_index = index;
179bf215546Sopenharmony_ci   forward_set_blockid(id, index);
180bf215546Sopenharmony_ci}
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_ci
183bf215546Sopenharmony_civoid Instr::forward_set_blockid(int id, int index)
184bf215546Sopenharmony_ci{
185bf215546Sopenharmony_ci   (void)id;
186bf215546Sopenharmony_ci   (void)index;
187bf215546Sopenharmony_ci}
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ciInstrWithVectorResult::InstrWithVectorResult(const RegisterVec4& dest,
190bf215546Sopenharmony_ci                                             const RegisterVec4::Swizzle& dest_swizzle):
191bf215546Sopenharmony_ci   m_dest(dest),
192bf215546Sopenharmony_ci   m_dest_swizzle(dest_swizzle)
193bf215546Sopenharmony_ci{
194bf215546Sopenharmony_ci   for (int i = 0; i < 4; ++i) {
195bf215546Sopenharmony_ci      if (m_dest_swizzle[i] < 6)
196bf215546Sopenharmony_ci         m_dest[i]->add_parent(this);
197bf215546Sopenharmony_ci   }
198bf215546Sopenharmony_ci}
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_civoid InstrWithVectorResult::print_dest(std::ostream& os) const
201bf215546Sopenharmony_ci{
202bf215546Sopenharmony_ci   os << (m_dest[0]->is_ssa() ? 'S' : 'R' ) << m_dest.sel();
203bf215546Sopenharmony_ci   os << ".";
204bf215546Sopenharmony_ci   for (int i = 0; i < 4; ++i)
205bf215546Sopenharmony_ci      os << VirtualValue::chanchar[m_dest_swizzle[i]];
206bf215546Sopenharmony_ci}
207bf215546Sopenharmony_ci
208bf215546Sopenharmony_cibool InstrWithVectorResult::comp_dest(const RegisterVec4& dest,
209bf215546Sopenharmony_ci                                      const RegisterVec4::Swizzle& dest_swizzle) const
210bf215546Sopenharmony_ci{
211bf215546Sopenharmony_ci   for(int i = 0; i < 4; ++i) {
212bf215546Sopenharmony_ci      if (!m_dest[i]->equal_to(*dest[i])) {
213bf215546Sopenharmony_ci         return false;
214bf215546Sopenharmony_ci      }
215bf215546Sopenharmony_ci      if (m_dest_swizzle[i] != dest_swizzle[i])
216bf215546Sopenharmony_ci         return false;
217bf215546Sopenharmony_ci   }
218bf215546Sopenharmony_ci   return true;
219bf215546Sopenharmony_ci}
220bf215546Sopenharmony_ci
221bf215546Sopenharmony_civoid Block::do_print(std::ostream& os) const
222bf215546Sopenharmony_ci{
223bf215546Sopenharmony_ci   for (int j = 0; j < 2 * m_nesting_depth; ++j)
224bf215546Sopenharmony_ci      os << ' ';
225bf215546Sopenharmony_ci   os << "BLOCK START\n";
226bf215546Sopenharmony_ci   for (auto& i : m_instructions) {
227bf215546Sopenharmony_ci      for (int j = 0; j < 2 * (m_nesting_depth + i->nesting_corr()) + 2; ++j)
228bf215546Sopenharmony_ci         os << ' ';
229bf215546Sopenharmony_ci      os << *i << "\n";
230bf215546Sopenharmony_ci   }
231bf215546Sopenharmony_ci   for (int j = 0; j < 2 * m_nesting_depth; ++j)
232bf215546Sopenharmony_ci      os << ' ';
233bf215546Sopenharmony_ci   os << "BLOCK END\n";
234bf215546Sopenharmony_ci}
235bf215546Sopenharmony_ci
236bf215546Sopenharmony_cibool Block::is_equal_to(const Block& lhs) const
237bf215546Sopenharmony_ci{
238bf215546Sopenharmony_ci   if (m_id != lhs.m_id || m_nesting_depth != lhs.m_nesting_depth)
239bf215546Sopenharmony_ci      return false;
240bf215546Sopenharmony_ci
241bf215546Sopenharmony_ci   if (m_instructions.size() != lhs.m_instructions.size())
242bf215546Sopenharmony_ci      return false;
243bf215546Sopenharmony_ci
244bf215546Sopenharmony_ci   return std::inner_product(m_instructions.begin(), m_instructions.end(), lhs.m_instructions.begin(),
245bf215546Sopenharmony_ci                             true,
246bf215546Sopenharmony_ci                             [] (bool l, bool r) { return l && r;},
247bf215546Sopenharmony_ci   [](PInst l, PInst r) { return l->equal_to(*r);});
248bf215546Sopenharmony_ci}
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ciinline bool operator != (const Block& lhs, const Block& rhs)
251bf215546Sopenharmony_ci{
252bf215546Sopenharmony_ci   return !lhs.is_equal_to(rhs);
253bf215546Sopenharmony_ci}
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_civoid Block::erase(iterator node)
256bf215546Sopenharmony_ci{
257bf215546Sopenharmony_ci   m_instructions.erase(node);
258bf215546Sopenharmony_ci}
259bf215546Sopenharmony_ci
260bf215546Sopenharmony_civoid Block::set_type(Type t)
261bf215546Sopenharmony_ci{
262bf215546Sopenharmony_ci   m_blocK_type = t;
263bf215546Sopenharmony_ci   switch (t) {
264bf215546Sopenharmony_ci   case vtx:
265bf215546Sopenharmony_ci   case gds:
266bf215546Sopenharmony_ci   case tex: m_remaining_slots = 8; break; /* TODO: 16 for >= EVERGREEN */
267bf215546Sopenharmony_ci   default:
268bf215546Sopenharmony_ci      m_remaining_slots = 0xffff;
269bf215546Sopenharmony_ci   }
270bf215546Sopenharmony_ci}
271bf215546Sopenharmony_ci
272bf215546Sopenharmony_ciBlock::Block(int nesting_depth, int id):
273bf215546Sopenharmony_ci   m_nesting_depth(nesting_depth),
274bf215546Sopenharmony_ci   m_id(id),
275bf215546Sopenharmony_ci   m_next_index(0)
276bf215546Sopenharmony_ci{
277bf215546Sopenharmony_ci   assert(!has_instr_flag(force_cf));
278bf215546Sopenharmony_ci}
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_civoid Block::accept(ConstInstrVisitor& visitor) const
281bf215546Sopenharmony_ci{
282bf215546Sopenharmony_ci   visitor.visit(*this);
283bf215546Sopenharmony_ci}
284bf215546Sopenharmony_ci
285bf215546Sopenharmony_civoid Block::accept(InstrVisitor& visitor)
286bf215546Sopenharmony_ci{
287bf215546Sopenharmony_ci   visitor.visit(this);
288bf215546Sopenharmony_ci}
289bf215546Sopenharmony_ci
290bf215546Sopenharmony_civoid Block::push_back(PInst instr)
291bf215546Sopenharmony_ci{
292bf215546Sopenharmony_ci   instr->set_blockid(m_id, m_next_index++);
293bf215546Sopenharmony_ci   if (m_remaining_slots != 0xffff) {
294bf215546Sopenharmony_ci      uint32_t new_slots = instr->slots();
295bf215546Sopenharmony_ci      m_remaining_slots -= new_slots;
296bf215546Sopenharmony_ci   }
297bf215546Sopenharmony_ci   if (m_lds_group_start)
298bf215546Sopenharmony_ci      m_lds_group_requirement += instr->slots();
299bf215546Sopenharmony_ci
300bf215546Sopenharmony_ci   m_instructions.push_back(instr);
301bf215546Sopenharmony_ci}
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_cibool Block::try_reserve_kcache(const AluGroup& group)
304bf215546Sopenharmony_ci{
305bf215546Sopenharmony_ci   auto kcache = m_kcache;
306bf215546Sopenharmony_ci
307bf215546Sopenharmony_ci   auto kcache_constants = group.get_kconsts();
308bf215546Sopenharmony_ci   for (auto& kc : kcache_constants)  {
309bf215546Sopenharmony_ci      auto u = kc->as_uniform();
310bf215546Sopenharmony_ci      assert(u);
311bf215546Sopenharmony_ci      if (!try_reserve_kcache(*u, kcache)) {
312bf215546Sopenharmony_ci         m_kcache_alloc_failed = true;
313bf215546Sopenharmony_ci         return false;
314bf215546Sopenharmony_ci      }
315bf215546Sopenharmony_ci   }
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_ci   m_kcache = kcache;
318bf215546Sopenharmony_ci   m_kcache_alloc_failed = false;
319bf215546Sopenharmony_ci   return true;
320bf215546Sopenharmony_ci}
321bf215546Sopenharmony_ci
322bf215546Sopenharmony_cibool Block::try_reserve_kcache(const AluInstr& instr)
323bf215546Sopenharmony_ci{
324bf215546Sopenharmony_ci   auto kcache = m_kcache;
325bf215546Sopenharmony_ci
326bf215546Sopenharmony_ci   for (auto& src : instr.sources()) {
327bf215546Sopenharmony_ci      auto u = src->as_uniform();
328bf215546Sopenharmony_ci      if (u) {
329bf215546Sopenharmony_ci         if (!try_reserve_kcache(*u, kcache)) {
330bf215546Sopenharmony_ci            m_kcache_alloc_failed = true;
331bf215546Sopenharmony_ci            return false;
332bf215546Sopenharmony_ci         }
333bf215546Sopenharmony_ci      }
334bf215546Sopenharmony_ci   }
335bf215546Sopenharmony_ci   m_kcache = kcache;
336bf215546Sopenharmony_ci   m_kcache_alloc_failed = false;
337bf215546Sopenharmony_ci   return true;
338bf215546Sopenharmony_ci}
339bf215546Sopenharmony_ci
340bf215546Sopenharmony_civoid Block::set_chipclass(r600_chip_class chip_class)
341bf215546Sopenharmony_ci{
342bf215546Sopenharmony_ci   if (chip_class < ISA_CC_EVERGREEN)
343bf215546Sopenharmony_ci      s_max_kcache_banks = 2;
344bf215546Sopenharmony_ci   else
345bf215546Sopenharmony_ci      s_max_kcache_banks = 4;
346bf215546Sopenharmony_ci}
347bf215546Sopenharmony_ci
348bf215546Sopenharmony_ciunsigned Block::s_max_kcache_banks = 4;
349bf215546Sopenharmony_ci
350bf215546Sopenharmony_cibool Block::try_reserve_kcache(const UniformValue& u,
351bf215546Sopenharmony_ci                               std::array<KCacheLine, 4>& kcache) const
352bf215546Sopenharmony_ci{
353bf215546Sopenharmony_ci   const int kcache_banks = s_max_kcache_banks; // TODO: handle pre-evergreen
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_ci   int bank = u.kcache_bank();
356bf215546Sopenharmony_ci   int sel  = (u.sel() - 512);
357bf215546Sopenharmony_ci   int line = sel >> 4;
358bf215546Sopenharmony_ci
359bf215546Sopenharmony_ci   bool found = false;
360bf215546Sopenharmony_ci
361bf215546Sopenharmony_ci   for (int i = 0; i < kcache_banks && !found; ++i) {
362bf215546Sopenharmony_ci      if (kcache[i].mode) {
363bf215546Sopenharmony_ci         if (kcache[i].bank < bank)
364bf215546Sopenharmony_ci            continue;
365bf215546Sopenharmony_ci
366bf215546Sopenharmony_ci         if ((kcache[i].bank == bank &&
367bf215546Sopenharmony_ci              kcache[i].addr > line  + 1) ||
368bf215546Sopenharmony_ci             kcache[i].bank > bank) {
369bf215546Sopenharmony_ci            if (kcache[kcache_banks - 1].mode)
370bf215546Sopenharmony_ci               return false;
371bf215546Sopenharmony_ci
372bf215546Sopenharmony_ci            memmove(&kcache[i+1],&kcache[i], (kcache_banks-i-1)*sizeof(KCacheLine));
373bf215546Sopenharmony_ci            kcache[i].mode = KCacheLine::lock_1;
374bf215546Sopenharmony_ci            kcache[i].bank = bank;
375bf215546Sopenharmony_ci            kcache[i].addr = line;
376bf215546Sopenharmony_ci            return true;
377bf215546Sopenharmony_ci         }
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_ci         int d = line - kcache[i].addr;
380bf215546Sopenharmony_ci
381bf215546Sopenharmony_ci         if (d == -1) {
382bf215546Sopenharmony_ci            kcache[i].addr--;
383bf215546Sopenharmony_ci            if (kcache[i].mode == KCacheLine::lock_2) {
384bf215546Sopenharmony_ci               /* we are prepending the line to the current set,
385bf215546Sopenharmony_ci                * discarding the existing second line,
386bf215546Sopenharmony_ci                * so we'll have to insert line+2 after it */
387bf215546Sopenharmony_ci               line += 2;
388bf215546Sopenharmony_ci               continue;
389bf215546Sopenharmony_ci            } else if (kcache[i].mode == KCacheLine::lock_1) {
390bf215546Sopenharmony_ci               kcache[i].mode = KCacheLine::lock_2;
391bf215546Sopenharmony_ci               return true;
392bf215546Sopenharmony_ci            } else {
393bf215546Sopenharmony_ci               /* V_SQ_CF_KCACHE_LOCK_LOOP_INDEX is not supported */
394bf215546Sopenharmony_ci               return false;
395bf215546Sopenharmony_ci            }
396bf215546Sopenharmony_ci         } else if (d == 1) {
397bf215546Sopenharmony_ci            kcache[i].mode = KCacheLine::lock_2;
398bf215546Sopenharmony_ci            return true;
399bf215546Sopenharmony_ci         } else if (d == 0) {
400bf215546Sopenharmony_ci            return true;
401bf215546Sopenharmony_ci         }
402bf215546Sopenharmony_ci      } else { /* free kcache set - use it */
403bf215546Sopenharmony_ci         kcache[i].mode = KCacheLine::lock_1;
404bf215546Sopenharmony_ci         kcache[i].bank = bank;
405bf215546Sopenharmony_ci         kcache[i].addr = line;
406bf215546Sopenharmony_ci         return true;
407bf215546Sopenharmony_ci      }
408bf215546Sopenharmony_ci   }
409bf215546Sopenharmony_ci   return false;
410bf215546Sopenharmony_ci}
411bf215546Sopenharmony_ci
412bf215546Sopenharmony_civoid Block::lds_group_start(AluInstr *alu)
413bf215546Sopenharmony_ci{
414bf215546Sopenharmony_ci   assert(!m_lds_group_start);
415bf215546Sopenharmony_ci   m_lds_group_start = alu;
416bf215546Sopenharmony_ci   m_lds_group_requirement = 0;
417bf215546Sopenharmony_ci}
418bf215546Sopenharmony_ci
419bf215546Sopenharmony_civoid Block::lds_group_end()
420bf215546Sopenharmony_ci{
421bf215546Sopenharmony_ci   assert(m_lds_group_start);
422bf215546Sopenharmony_ci   m_lds_group_start->set_required_slots(m_lds_group_requirement);
423bf215546Sopenharmony_ci   m_lds_group_start = 0;
424bf215546Sopenharmony_ci}
425bf215546Sopenharmony_ci
426bf215546Sopenharmony_ciInstrWithVectorResult::InstrWithVectorResult(const InstrWithVectorResult& orig):
427bf215546Sopenharmony_ci   m_dest(orig.m_dest),
428bf215546Sopenharmony_ci   m_dest_swizzle(orig.m_dest_swizzle)
429bf215546Sopenharmony_ci{
430bf215546Sopenharmony_ci}
431bf215546Sopenharmony_ci
432bf215546Sopenharmony_ciclass InstrComparer : public ConstInstrVisitor {
433bf215546Sopenharmony_cipublic:
434bf215546Sopenharmony_ci   InstrComparer() = default;
435bf215546Sopenharmony_ci   bool result {false};
436bf215546Sopenharmony_ci
437bf215546Sopenharmony_ci#define DECLARE_MEMBER(TYPE)         \
438bf215546Sopenharmony_ci    InstrComparer(const TYPE *instr) \
439bf215546Sopenharmony_ci    {                                \
440bf215546Sopenharmony_ci       this_ ## TYPE = instr;        \
441bf215546Sopenharmony_ci    }                                \
442bf215546Sopenharmony_ci                                     \
443bf215546Sopenharmony_ci    void visit(const TYPE& instr)    \
444bf215546Sopenharmony_ci    {                                \
445bf215546Sopenharmony_ci       result = false;               \
446bf215546Sopenharmony_ci       if (!this_ ## TYPE)           \
447bf215546Sopenharmony_ci         return;                     \
448bf215546Sopenharmony_ci      result = this_ ## TYPE->is_equal_to(instr); \
449bf215546Sopenharmony_ci   }                                 \
450bf215546Sopenharmony_ci                                     \
451bf215546Sopenharmony_ci   const TYPE *this_ ## TYPE{nullptr};
452bf215546Sopenharmony_ci
453bf215546Sopenharmony_ci   DECLARE_MEMBER(AluInstr);
454bf215546Sopenharmony_ci   DECLARE_MEMBER(AluGroup);
455bf215546Sopenharmony_ci   DECLARE_MEMBER(TexInstr);
456bf215546Sopenharmony_ci   DECLARE_MEMBER(ExportInstr);
457bf215546Sopenharmony_ci   DECLARE_MEMBER(FetchInstr);
458bf215546Sopenharmony_ci   DECLARE_MEMBER(Block);
459bf215546Sopenharmony_ci   DECLARE_MEMBER(ControlFlowInstr);
460bf215546Sopenharmony_ci   DECLARE_MEMBER(IfInstr);
461bf215546Sopenharmony_ci   DECLARE_MEMBER(ScratchIOInstr);
462bf215546Sopenharmony_ci   DECLARE_MEMBER(StreamOutInstr);
463bf215546Sopenharmony_ci   DECLARE_MEMBER(MemRingOutInstr);
464bf215546Sopenharmony_ci   DECLARE_MEMBER(EmitVertexInstr);
465bf215546Sopenharmony_ci   DECLARE_MEMBER(GDSInstr);
466bf215546Sopenharmony_ci   DECLARE_MEMBER(WriteTFInstr);
467bf215546Sopenharmony_ci   DECLARE_MEMBER(LDSAtomicInstr);
468bf215546Sopenharmony_ci   DECLARE_MEMBER(LDSReadInstr);
469bf215546Sopenharmony_ci   DECLARE_MEMBER(RatInstr);
470bf215546Sopenharmony_ci};
471bf215546Sopenharmony_ci
472bf215546Sopenharmony_ciclass InstrCompareForward: public ConstInstrVisitor {
473bf215546Sopenharmony_cipublic:
474bf215546Sopenharmony_ci
475bf215546Sopenharmony_ci   void visit(const AluInstr& instr) override {
476bf215546Sopenharmony_ci      m_comparer = InstrComparer(&instr);
477bf215546Sopenharmony_ci   }
478bf215546Sopenharmony_ci
479bf215546Sopenharmony_ci   void visit(const AluGroup& instr) override {
480bf215546Sopenharmony_ci      m_comparer = InstrComparer(&instr);
481bf215546Sopenharmony_ci   }
482bf215546Sopenharmony_ci
483bf215546Sopenharmony_ci   void visit(const TexInstr& instr) override {
484bf215546Sopenharmony_ci      m_comparer = InstrComparer(&instr);
485bf215546Sopenharmony_ci   }
486bf215546Sopenharmony_ci
487bf215546Sopenharmony_ci   void visit(const ExportInstr& instr) override {
488bf215546Sopenharmony_ci      m_comparer = InstrComparer(&instr);
489bf215546Sopenharmony_ci   }
490bf215546Sopenharmony_ci
491bf215546Sopenharmony_ci   void visit(const FetchInstr& instr) override {
492bf215546Sopenharmony_ci      m_comparer = InstrComparer(&instr);
493bf215546Sopenharmony_ci   }
494bf215546Sopenharmony_ci
495bf215546Sopenharmony_ci   void visit(const Block& instr) override {
496bf215546Sopenharmony_ci      m_comparer = InstrComparer(&instr);
497bf215546Sopenharmony_ci   }
498bf215546Sopenharmony_ci
499bf215546Sopenharmony_ci   void visit(const ControlFlowInstr& instr) override {
500bf215546Sopenharmony_ci      m_comparer = InstrComparer(&instr);
501bf215546Sopenharmony_ci   }
502bf215546Sopenharmony_ci
503bf215546Sopenharmony_ci   void visit(const IfInstr& instr) override {
504bf215546Sopenharmony_ci      m_comparer = InstrComparer(&instr);
505bf215546Sopenharmony_ci   }
506bf215546Sopenharmony_ci
507bf215546Sopenharmony_ci   void visit(const ScratchIOInstr& instr) override {
508bf215546Sopenharmony_ci      m_comparer = InstrComparer(&instr);
509bf215546Sopenharmony_ci   }
510bf215546Sopenharmony_ci
511bf215546Sopenharmony_ci   void visit(const StreamOutInstr& instr) override {
512bf215546Sopenharmony_ci      m_comparer = InstrComparer(&instr);
513bf215546Sopenharmony_ci   }
514bf215546Sopenharmony_ci
515bf215546Sopenharmony_ci   void visit(const MemRingOutInstr& instr) override {
516bf215546Sopenharmony_ci      m_comparer = InstrComparer(&instr);
517bf215546Sopenharmony_ci   }
518bf215546Sopenharmony_ci
519bf215546Sopenharmony_ci   void visit(const EmitVertexInstr& instr) override {
520bf215546Sopenharmony_ci      m_comparer = InstrComparer(&instr);
521bf215546Sopenharmony_ci   }
522bf215546Sopenharmony_ci
523bf215546Sopenharmony_ci   void visit(const GDSInstr& instr) override {
524bf215546Sopenharmony_ci      m_comparer = InstrComparer(&instr);
525bf215546Sopenharmony_ci   }
526bf215546Sopenharmony_ci
527bf215546Sopenharmony_ci   void visit(const WriteTFInstr& instr) override {
528bf215546Sopenharmony_ci      m_comparer = InstrComparer(&instr);
529bf215546Sopenharmony_ci   }
530bf215546Sopenharmony_ci
531bf215546Sopenharmony_ci   void visit(const LDSAtomicInstr& instr) override {
532bf215546Sopenharmony_ci      m_comparer = InstrComparer(&instr);
533bf215546Sopenharmony_ci   }
534bf215546Sopenharmony_ci
535bf215546Sopenharmony_ci   void visit(const LDSReadInstr& instr) override {
536bf215546Sopenharmony_ci         m_comparer = InstrComparer(&instr);
537bf215546Sopenharmony_ci   }
538bf215546Sopenharmony_ci
539bf215546Sopenharmony_ci   void visit(const RatInstr& instr) override {
540bf215546Sopenharmony_ci         m_comparer = InstrComparer(&instr);
541bf215546Sopenharmony_ci   }
542bf215546Sopenharmony_ci
543bf215546Sopenharmony_ci   InstrComparer m_comparer;
544bf215546Sopenharmony_ci};
545bf215546Sopenharmony_ci
546bf215546Sopenharmony_ci
547bf215546Sopenharmony_cibool Instr::equal_to(const Instr& lhs) const
548bf215546Sopenharmony_ci{
549bf215546Sopenharmony_ci   InstrCompareForward cmp;
550bf215546Sopenharmony_ci   accept(cmp);
551bf215546Sopenharmony_ci   lhs.accept(cmp.m_comparer);
552bf215546Sopenharmony_ci
553bf215546Sopenharmony_ci   return cmp.m_comparer.result;
554bf215546Sopenharmony_ci}
555bf215546Sopenharmony_ci
556bf215546Sopenharmony_ci
557bf215546Sopenharmony_ci
558bf215546Sopenharmony_ci
559bf215546Sopenharmony_ci} // ns r600
560