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#pragma once
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci#include "sfn_virtualvalues.h"
30bf215546Sopenharmony_ci#include "sfn_alu_defines.h"
31bf215546Sopenharmony_ci#include "sfn_defines.h"
32bf215546Sopenharmony_ci#include <set>
33bf215546Sopenharmony_ci#include <list>
34bf215546Sopenharmony_ci#include <iostream>
35bf215546Sopenharmony_ci
36bf215546Sopenharmony_cinamespace r600 {
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ciclass ConstInstrVisitor;
39bf215546Sopenharmony_ci
40bf215546Sopenharmony_ciclass InstrVisitor;
41bf215546Sopenharmony_ciclass AluInstr;
42bf215546Sopenharmony_ciclass AluGroup;
43bf215546Sopenharmony_ciclass TexInstr;
44bf215546Sopenharmony_ciclass ExportInstr;
45bf215546Sopenharmony_ciclass FetchInstr;
46bf215546Sopenharmony_ciclass ControlFlowInstr;
47bf215546Sopenharmony_ciclass IfInstr;
48bf215546Sopenharmony_ciclass ScratchIOInstr;
49bf215546Sopenharmony_ciclass StreamOutInstr;
50bf215546Sopenharmony_ciclass MemRingOutInstr;
51bf215546Sopenharmony_ciclass EmitVertexInstr;
52bf215546Sopenharmony_ciclass GDSInstr;
53bf215546Sopenharmony_ciclass WriteTFInstr;
54bf215546Sopenharmony_ciclass LDSAtomicInstr;
55bf215546Sopenharmony_ciclass LDSReadInstr;
56bf215546Sopenharmony_ciclass RatInstr;
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_ci
59bf215546Sopenharmony_ciint int_from_string_with_prefix(const std::string& str, const std::string& prefix);
60bf215546Sopenharmony_ciint sel_and_szw_from_string(const std::string& str, RegisterVec4::Swizzle& swz, bool& is_ssa);
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_ciclass Instr : public Allocate {
63bf215546Sopenharmony_cipublic:
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_ci   enum Flags {
66bf215546Sopenharmony_ci      always_keep,
67bf215546Sopenharmony_ci      dead,
68bf215546Sopenharmony_ci      scheduled,
69bf215546Sopenharmony_ci      vpm,
70bf215546Sopenharmony_ci      force_cf,
71bf215546Sopenharmony_ci      ack_rat_return_write,
72bf215546Sopenharmony_ci      nflags
73bf215546Sopenharmony_ci      };
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci   Instr();
76bf215546Sopenharmony_ci
77bf215546Sopenharmony_ci   Instr(const Instr& orig) = default;
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_ci   virtual ~Instr();
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_ci   using Pointer = R600_POINTER_TYPE(Instr);
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci   void print(std::ostream& os) const;
84bf215546Sopenharmony_ci   bool equal_to(const Instr& lhs) const;
85bf215546Sopenharmony_ci
86bf215546Sopenharmony_ci   virtual void accept(ConstInstrVisitor& visitor) const = 0;
87bf215546Sopenharmony_ci   virtual void accept(InstrVisitor& visitor) = 0;
88bf215546Sopenharmony_ci   virtual bool end_group() const { return true;}
89bf215546Sopenharmony_ci
90bf215546Sopenharmony_ci   virtual bool is_last() const;
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ci   void set_always_keep() {m_instr_flags.set(always_keep);}
93bf215546Sopenharmony_ci   bool set_dead();
94bf215546Sopenharmony_ci   virtual void set_scheduled() { m_instr_flags.set(scheduled); forward_set_scheduled();}
95bf215546Sopenharmony_ci   void add_use() {++m_use_count;}
96bf215546Sopenharmony_ci   void dec_use() {assert(m_use_count > 0); --m_use_count;}
97bf215546Sopenharmony_ci   bool is_dead() const {return m_instr_flags.test(dead);}
98bf215546Sopenharmony_ci   bool is_scheduled() const {return m_instr_flags.test(scheduled);}
99bf215546Sopenharmony_ci   bool keep() const {return m_instr_flags.test(always_keep);}
100bf215546Sopenharmony_ci   bool has_uses() const {return m_use_count > 0;}
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci   bool has_instr_flag(Flags f) const  {return m_instr_flags.test(f);}
103bf215546Sopenharmony_ci   void set_instr_flag(Flags f) { m_instr_flags.set(f);}
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci   virtual bool replace_source(PRegister old_src, PVirtualValue new_src);
106bf215546Sopenharmony_ci   virtual bool replace_dest(PRegister new_dest, AluInstr *move_instr);
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_ci   virtual int nesting_corr() const { return 0;}
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci   virtual bool end_block() const { return false;}
111bf215546Sopenharmony_ci   virtual int nesting_offset() const { return 0;}
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci   void set_blockid(int id, int index);
114bf215546Sopenharmony_ci   int block_id() const {return m_block_id;}
115bf215546Sopenharmony_ci   int index() const { return m_index;}
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_ci   void add_required_instr(Instr *instr);
118bf215546Sopenharmony_ci   void replace_required_instr(Instr *old_instr, Instr *new_instr);
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci   bool ready() const;
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci   virtual uint32_t slots() const {return 0;};
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci   using InstrList = std::list<Instr *, Allocator<Instr *>>;
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_ci   const InstrList& dependend_instr() { return m_dependend_instr;}
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ciprotected:
129bf215546Sopenharmony_ci
130bf215546Sopenharmony_ci   const InstrList& required_instr() const {return m_required_instr; }
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ciprivate:
133bf215546Sopenharmony_ci   virtual void forward_set_blockid(int id, int index);
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci   virtual bool do_ready() const = 0;
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci   virtual void do_print(std::ostream& os) const = 0;
138bf215546Sopenharmony_ci   virtual bool propagate_death();
139bf215546Sopenharmony_ci   virtual void forward_set_scheduled() {}
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci   InstrList m_required_instr;
142bf215546Sopenharmony_ci   InstrList m_dependend_instr;
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_ci   int m_use_count;
145bf215546Sopenharmony_ci   int m_block_id;
146bf215546Sopenharmony_ci   int m_index;
147bf215546Sopenharmony_ci   std::bitset<nflags> m_instr_flags{0};
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci};
150bf215546Sopenharmony_ciusing PInst = Instr::Pointer;
151bf215546Sopenharmony_ci
152bf215546Sopenharmony_ciclass Block : public Instr {
153bf215546Sopenharmony_cipublic:
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_ci   enum Type {
156bf215546Sopenharmony_ci      cf,
157bf215546Sopenharmony_ci      alu,
158bf215546Sopenharmony_ci      tex,
159bf215546Sopenharmony_ci      vtx,
160bf215546Sopenharmony_ci      gds,
161bf215546Sopenharmony_ci      unknown
162bf215546Sopenharmony_ci   };
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_ci   using Instructions = std::list<Instr *, Allocator<Instr *>>;
165bf215546Sopenharmony_ci   using Pointer = R600_POINTER_TYPE(Block);
166bf215546Sopenharmony_ci   using iterator = Instructions::iterator;
167bf215546Sopenharmony_ci   using reverse_iterator = Instructions::reverse_iterator;
168bf215546Sopenharmony_ci   using const_iterator = Instructions::const_iterator;
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ci   Block(int nesting_depth, int id);
171bf215546Sopenharmony_ci   Block(const Block& orig) = delete;
172bf215546Sopenharmony_ci
173bf215546Sopenharmony_ci   void push_back(PInst instr);
174bf215546Sopenharmony_ci   iterator begin() { return m_instructions.begin(); }
175bf215546Sopenharmony_ci   iterator end() { return m_instructions.end(); }
176bf215546Sopenharmony_ci   reverse_iterator rbegin() { return m_instructions.rbegin(); }
177bf215546Sopenharmony_ci   reverse_iterator rend() { return m_instructions.rend(); }
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci   const_iterator begin() const { return m_instructions.begin();}
180bf215546Sopenharmony_ci   const_iterator end() const { return m_instructions.end();}
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_ci   bool empty() const { return m_instructions.empty();}
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ci   void erase(iterator node);
185bf215546Sopenharmony_ci
186bf215546Sopenharmony_ci   bool is_equal_to(const Block& lhs) const;
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_ci   void accept(ConstInstrVisitor& visitor) const override;
189bf215546Sopenharmony_ci   void accept(InstrVisitor& visitor) override;
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_ci   int nesting_depth() const { return m_nesting_depth;}
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci   int id() const {return m_id;}
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_ci   auto type() const {return m_blocK_type; }
196bf215546Sopenharmony_ci   void set_type(Type t);
197bf215546Sopenharmony_ci   uint32_t remaining_slots() const { return m_remaining_slots;}
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci   bool try_reserve_kcache(const AluGroup& instr);
200bf215546Sopenharmony_ci   bool try_reserve_kcache(const AluInstr& group);
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ci   auto last_lds_instr() {return m_last_lds_instr;}
203bf215546Sopenharmony_ci   void set_last_lds_instr(Instr *instr) {m_last_lds_instr = instr;}
204bf215546Sopenharmony_ci
205bf215546Sopenharmony_ci   void lds_group_start(AluInstr *alu);
206bf215546Sopenharmony_ci   void lds_group_end();
207bf215546Sopenharmony_ci   bool lds_group_active() { return m_lds_group_start != nullptr;}
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_ci   size_t size() const { return m_instructions.size();}
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci   bool kcache_reservation_failed() const { return m_kcache_alloc_failed;}
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci   int inc_rat_emitted() { return  ++m_emitted_rat_instr;}
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_ci   static void set_chipclass(r600_chip_class chip_class);
216bf215546Sopenharmony_ci
217bf215546Sopenharmony_ciprivate:
218bf215546Sopenharmony_ci   bool try_reserve_kcache(const UniformValue& u,
219bf215546Sopenharmony_ci                           std::array<KCacheLine, 4>& kcache) const;
220bf215546Sopenharmony_ci
221bf215546Sopenharmony_ci   bool do_ready() const override {return true;};
222bf215546Sopenharmony_ci   void do_print(std::ostream& os) const override;
223bf215546Sopenharmony_ci   Instructions m_instructions;
224bf215546Sopenharmony_ci   int m_nesting_depth;
225bf215546Sopenharmony_ci   int m_id;
226bf215546Sopenharmony_ci   int m_next_index;
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ci   Type m_blocK_type{unknown};
229bf215546Sopenharmony_ci   uint32_t m_remaining_slots{0xffff};
230bf215546Sopenharmony_ci
231bf215546Sopenharmony_ci   std::array<KCacheLine, 4> m_kcache;
232bf215546Sopenharmony_ci   bool m_kcache_alloc_failed{false};
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_ci   Instr *m_last_lds_instr{nullptr};
235bf215546Sopenharmony_ci
236bf215546Sopenharmony_ci   int m_lds_group_requirement{0};
237bf215546Sopenharmony_ci   AluInstr *m_lds_group_start{nullptr};
238bf215546Sopenharmony_ci   static unsigned s_max_kcache_banks;
239bf215546Sopenharmony_ci   int m_emitted_rat_instr{0};
240bf215546Sopenharmony_ci};
241bf215546Sopenharmony_ci
242bf215546Sopenharmony_ciclass InstrWithVectorResult : public Instr {
243bf215546Sopenharmony_cipublic:
244bf215546Sopenharmony_ci   InstrWithVectorResult(const RegisterVec4& dest, const RegisterVec4::Swizzle& dest_swizzle);
245bf215546Sopenharmony_ci
246bf215546Sopenharmony_ci   void set_dest_swizzle(const RegisterVec4::Swizzle& swz) {m_dest_swizzle = swz;}
247bf215546Sopenharmony_ci   int dest_swizzle(int i) const { return m_dest_swizzle[i];}
248bf215546Sopenharmony_ci   const RegisterVec4::Swizzle&  all_dest_swizzle() const { return m_dest_swizzle;}
249bf215546Sopenharmony_ci   const RegisterVec4& dst() const {return m_dest;}
250bf215546Sopenharmony_ci
251bf215546Sopenharmony_ciprotected:
252bf215546Sopenharmony_ci   InstrWithVectorResult(const InstrWithVectorResult& orig);
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci   void print_dest(std::ostream& os) const;
255bf215546Sopenharmony_ci   bool comp_dest(const RegisterVec4& dest, const RegisterVec4::Swizzle& dest_swizzle) const;
256bf215546Sopenharmony_ci
257bf215546Sopenharmony_ciprivate:
258bf215546Sopenharmony_ci   RegisterVec4 m_dest;
259bf215546Sopenharmony_ci   RegisterVec4::Swizzle m_dest_swizzle;
260bf215546Sopenharmony_ci};
261bf215546Sopenharmony_ci
262bf215546Sopenharmony_ciinline bool operator == (const Instr& lhs, const Instr& rhs) {
263bf215546Sopenharmony_ci   return lhs.equal_to(rhs);
264bf215546Sopenharmony_ci}
265bf215546Sopenharmony_ci
266bf215546Sopenharmony_ciinline bool operator != (const Instr& lhs, const Instr& rhs) {
267bf215546Sopenharmony_ci   return !(lhs == rhs);
268bf215546Sopenharmony_ci}
269bf215546Sopenharmony_ci
270bf215546Sopenharmony_ciinline std::ostream& operator << (std::ostream& os, const Instr& instr)
271bf215546Sopenharmony_ci{
272bf215546Sopenharmony_ci   instr.print(os);
273bf215546Sopenharmony_ci   return os;
274bf215546Sopenharmony_ci}
275bf215546Sopenharmony_ci
276bf215546Sopenharmony_citemplate <typename T, typename = std::enable_if_t<std::is_base_of_v<Instr, T>>>
277bf215546Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const T& instr) {
278bf215546Sopenharmony_ci  instr.print(os);
279bf215546Sopenharmony_ci  return os;
280bf215546Sopenharmony_ci}
281bf215546Sopenharmony_ci
282bf215546Sopenharmony_ciclass ConstInstrVisitor {
283bf215546Sopenharmony_cipublic:
284bf215546Sopenharmony_ci   virtual void visit(const AluInstr& instr) = 0;
285bf215546Sopenharmony_ci   virtual void visit(const AluGroup& instr) = 0;
286bf215546Sopenharmony_ci   virtual void visit(const TexInstr& instr) = 0;
287bf215546Sopenharmony_ci   virtual void visit(const ExportInstr& instr) = 0;
288bf215546Sopenharmony_ci   virtual void visit(const FetchInstr& instr) = 0;
289bf215546Sopenharmony_ci   virtual void visit(const Block& instr) = 0;
290bf215546Sopenharmony_ci   virtual void visit(const ControlFlowInstr& instr) = 0;
291bf215546Sopenharmony_ci   virtual void visit(const IfInstr& instr) = 0;
292bf215546Sopenharmony_ci   virtual void visit(const ScratchIOInstr& instr) = 0;
293bf215546Sopenharmony_ci   virtual void visit(const StreamOutInstr& instr) = 0;
294bf215546Sopenharmony_ci   virtual void visit(const MemRingOutInstr& instr) = 0;
295bf215546Sopenharmony_ci   virtual void visit(const EmitVertexInstr& instr) = 0;
296bf215546Sopenharmony_ci   virtual void visit(const GDSInstr& instr) = 0;
297bf215546Sopenharmony_ci   virtual void visit(const WriteTFInstr& instr) = 0;
298bf215546Sopenharmony_ci   virtual void visit(const LDSAtomicInstr& instr) = 0;
299bf215546Sopenharmony_ci   virtual void visit(const LDSReadInstr& instr) = 0;
300bf215546Sopenharmony_ci   virtual void visit(const RatInstr& instr) = 0;
301bf215546Sopenharmony_ci};
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_ciclass InstrVisitor {
304bf215546Sopenharmony_cipublic:
305bf215546Sopenharmony_ci   virtual void visit(AluInstr  *instr) = 0;
306bf215546Sopenharmony_ci   virtual void visit(AluGroup *instr) = 0;
307bf215546Sopenharmony_ci   virtual void visit(TexInstr *instr) = 0;
308bf215546Sopenharmony_ci   virtual void visit(ExportInstr *instr) = 0;
309bf215546Sopenharmony_ci   virtual void visit(FetchInstr *instr) = 0;
310bf215546Sopenharmony_ci   virtual void visit(Block *instr) = 0;
311bf215546Sopenharmony_ci   virtual void visit(ControlFlowInstr *instr) = 0;
312bf215546Sopenharmony_ci   virtual void visit(IfInstr *instr) = 0;
313bf215546Sopenharmony_ci   virtual void visit(ScratchIOInstr *instr) = 0;
314bf215546Sopenharmony_ci   virtual void visit(StreamOutInstr *instr) = 0;
315bf215546Sopenharmony_ci   virtual void visit(MemRingOutInstr *instr) = 0;
316bf215546Sopenharmony_ci   virtual void visit(EmitVertexInstr *instr) = 0;
317bf215546Sopenharmony_ci   virtual void visit(GDSInstr *instr) = 0;
318bf215546Sopenharmony_ci   virtual void visit(WriteTFInstr *instr) = 0;
319bf215546Sopenharmony_ci   virtual void visit(LDSAtomicInstr *instr) = 0;
320bf215546Sopenharmony_ci   virtual void visit(LDSReadInstr *instr) = 0;
321bf215546Sopenharmony_ci   virtual void visit(RatInstr *instr) = 0;
322bf215546Sopenharmony_ci};
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_ci
325bf215546Sopenharmony_ci} // ns r600
326