1 /* -*- mesa-c++ -*-
2 *
3 * Copyright (c) 2021 Collabora LTD
4 *
5 * Author: Gert Wollny <gert.wollny@collabora.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * on the rights to use, copy, modify, merge, publish, distribute, sub
11 * license, and/or sell copies of the Software, and to permit persons to whom
12 * the Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27 #pragma once
28
29 #include "sfn_virtualvalues.h"
30 #include "sfn_alu_defines.h"
31 #include "sfn_defines.h"
32 #include <set>
33 #include <list>
34 #include <iostream>
35
36 namespace r600 {
37
38 class ConstInstrVisitor;
39
40 class InstrVisitor;
41 class AluInstr;
42 class AluGroup;
43 class TexInstr;
44 class ExportInstr;
45 class FetchInstr;
46 class ControlFlowInstr;
47 class IfInstr;
48 class ScratchIOInstr;
49 class StreamOutInstr;
50 class MemRingOutInstr;
51 class EmitVertexInstr;
52 class GDSInstr;
53 class WriteTFInstr;
54 class LDSAtomicInstr;
55 class LDSReadInstr;
56 class RatInstr;
57
58
59 int int_from_string_with_prefix(const std::string& str, const std::string& prefix);
60 int sel_and_szw_from_string(const std::string& str, RegisterVec4::Swizzle& swz, bool& is_ssa);
61
62 class Instr : public Allocate {
63 public:
64
65 enum Flags {
66 always_keep,
67 dead,
68 scheduled,
69 vpm,
70 force_cf,
71 ack_rat_return_write,
72 nflags
73 };
74
75 Instr();
76
77 Instr(const Instr& orig) = default;
78
79 virtual ~Instr();
80
81 using Pointer = R600_POINTER_TYPE(Instr);
82
83 void print(std::ostream& os) const;
84 bool equal_to(const Instr& lhs) const;
85
86 virtual void accept(ConstInstrVisitor& visitor) const = 0;
87 virtual void accept(InstrVisitor& visitor) = 0;
end_group() const88 virtual bool end_group() const { return true;}
89
90 virtual bool is_last() const;
91
set_always_keep()92 void set_always_keep() {m_instr_flags.set(always_keep);}
93 bool set_dead();
set_scheduled()94 virtual void set_scheduled() { m_instr_flags.set(scheduled); forward_set_scheduled();}
add_use()95 void add_use() {++m_use_count;}
dec_use()96 void dec_use() {assert(m_use_count > 0); --m_use_count;}
is_dead() const97 bool is_dead() const {return m_instr_flags.test(dead);}
is_scheduled() const98 bool is_scheduled() const {return m_instr_flags.test(scheduled);}
keep() const99 bool keep() const {return m_instr_flags.test(always_keep);}
has_uses() const100 bool has_uses() const {return m_use_count > 0;}
101
has_instr_flag(Flags f) const102 bool has_instr_flag(Flags f) const {return m_instr_flags.test(f);}
set_instr_flag(Flags f)103 void set_instr_flag(Flags f) { m_instr_flags.set(f);}
104
105 virtual bool replace_source(PRegister old_src, PVirtualValue new_src);
106 virtual bool replace_dest(PRegister new_dest, AluInstr *move_instr);
107
nesting_corr() const108 virtual int nesting_corr() const { return 0;}
109
end_block() const110 virtual bool end_block() const { return false;}
nesting_offset() const111 virtual int nesting_offset() const { return 0;}
112
113 void set_blockid(int id, int index);
block_id() const114 int block_id() const {return m_block_id;}
index() const115 int index() const { return m_index;}
116
117 void add_required_instr(Instr *instr);
118 void replace_required_instr(Instr *old_instr, Instr *new_instr);
119
120 bool ready() const;
121
slots() const122 virtual uint32_t slots() const {return 0;};
123
124 using InstrList = std::list<Instr *, Allocator<Instr *>>;
125
dependend_instr()126 const InstrList& dependend_instr() { return m_dependend_instr;}
127
128 protected:
129
required_instr() const130 const InstrList& required_instr() const {return m_required_instr; }
131
132 private:
133 virtual void forward_set_blockid(int id, int index);
134
135 virtual bool do_ready() const = 0;
136
137 virtual void do_print(std::ostream& os) const = 0;
138 virtual bool propagate_death();
forward_set_scheduled()139 virtual void forward_set_scheduled() {}
140
141 InstrList m_required_instr;
142 InstrList m_dependend_instr;
143
144 int m_use_count;
145 int m_block_id;
146 int m_index;
147 std::bitset<nflags> m_instr_flags{0};
148
149 };
150 using PInst = Instr::Pointer;
151
152 class Block : public Instr {
153 public:
154
155 enum Type {
156 cf,
157 alu,
158 tex,
159 vtx,
160 gds,
161 unknown
162 };
163
164 using Instructions = std::list<Instr *, Allocator<Instr *>>;
165 using Pointer = R600_POINTER_TYPE(Block);
166 using iterator = Instructions::iterator;
167 using reverse_iterator = Instructions::reverse_iterator;
168 using const_iterator = Instructions::const_iterator;
169
170 Block(int nesting_depth, int id);
171 Block(const Block& orig) = delete;
172
173 void push_back(PInst instr);
begin()174 iterator begin() { return m_instructions.begin(); }
end()175 iterator end() { return m_instructions.end(); }
rbegin()176 reverse_iterator rbegin() { return m_instructions.rbegin(); }
rend()177 reverse_iterator rend() { return m_instructions.rend(); }
178
begin() const179 const_iterator begin() const { return m_instructions.begin();}
end() const180 const_iterator end() const { return m_instructions.end();}
181
empty() const182 bool empty() const { return m_instructions.empty();}
183
184 void erase(iterator node);
185
186 bool is_equal_to(const Block& lhs) const;
187
188 void accept(ConstInstrVisitor& visitor) const override;
189 void accept(InstrVisitor& visitor) override;
190
nesting_depth() const191 int nesting_depth() const { return m_nesting_depth;}
192
id() const193 int id() const {return m_id;}
194
type() const195 auto type() const {return m_blocK_type; }
196 void set_type(Type t);
remaining_slots() const197 uint32_t remaining_slots() const { return m_remaining_slots;}
198
199 bool try_reserve_kcache(const AluGroup& instr);
200 bool try_reserve_kcache(const AluInstr& group);
201
last_lds_instr()202 auto last_lds_instr() {return m_last_lds_instr;}
set_last_lds_instr(Instr *instr)203 void set_last_lds_instr(Instr *instr) {m_last_lds_instr = instr;}
204
205 void lds_group_start(AluInstr *alu);
206 void lds_group_end();
lds_group_active()207 bool lds_group_active() { return m_lds_group_start != nullptr;}
208
size() const209 size_t size() const { return m_instructions.size();}
210
kcache_reservation_failed() const211 bool kcache_reservation_failed() const { return m_kcache_alloc_failed;}
212
inc_rat_emitted()213 int inc_rat_emitted() { return ++m_emitted_rat_instr;}
214
215 static void set_chipclass(r600_chip_class chip_class);
216
217 private:
218 bool try_reserve_kcache(const UniformValue& u,
219 std::array<KCacheLine, 4>& kcache) const;
220
221 bool do_ready() const override {return true;};
222 void do_print(std::ostream& os) const override;
223 Instructions m_instructions;
224 int m_nesting_depth;
225 int m_id;
226 int m_next_index;
227
228 Type m_blocK_type{unknown};
229 uint32_t m_remaining_slots{0xffff};
230
231 std::array<KCacheLine, 4> m_kcache;
232 bool m_kcache_alloc_failed{false};
233
234 Instr *m_last_lds_instr{nullptr};
235
236 int m_lds_group_requirement{0};
237 AluInstr *m_lds_group_start{nullptr};
238 static unsigned s_max_kcache_banks;
239 int m_emitted_rat_instr{0};
240 };
241
242 class InstrWithVectorResult : public Instr {
243 public:
244 InstrWithVectorResult(const RegisterVec4& dest, const RegisterVec4::Swizzle& dest_swizzle);
245
set_dest_swizzle(const RegisterVec4::Swizzle& swz)246 void set_dest_swizzle(const RegisterVec4::Swizzle& swz) {m_dest_swizzle = swz;}
dest_swizzle(int i) const247 int dest_swizzle(int i) const { return m_dest_swizzle[i];}
all_dest_swizzle() const248 const RegisterVec4::Swizzle& all_dest_swizzle() const { return m_dest_swizzle;}
dst() const249 const RegisterVec4& dst() const {return m_dest;}
250
251 protected:
252 InstrWithVectorResult(const InstrWithVectorResult& orig);
253
254 void print_dest(std::ostream& os) const;
255 bool comp_dest(const RegisterVec4& dest, const RegisterVec4::Swizzle& dest_swizzle) const;
256
257 private:
258 RegisterVec4 m_dest;
259 RegisterVec4::Swizzle m_dest_swizzle;
260 };
261
operator ==(const Instr& lhs, const Instr& rhs)262 inline bool operator == (const Instr& lhs, const Instr& rhs) {
263 return lhs.equal_to(rhs);
264 }
265
operator !=(const Instr& lhs, const Instr& rhs)266 inline bool operator != (const Instr& lhs, const Instr& rhs) {
267 return !(lhs == rhs);
268 }
269
operator <<(std::ostream& os, const Instr& instr)270 inline std::ostream& operator << (std::ostream& os, const Instr& instr)
271 {
272 instr.print(os);
273 return os;
274 }
275
276 template <typename T, typename = std::enable_if_t<std::is_base_of_v<Instr, T>>>
operator <<(std::ostream& os, const T& instr)277 std::ostream& operator<<(std::ostream& os, const T& instr) {
278 instr.print(os);
279 return os;
280 }
281
282 class ConstInstrVisitor {
283 public:
284 virtual void visit(const AluInstr& instr) = 0;
285 virtual void visit(const AluGroup& instr) = 0;
286 virtual void visit(const TexInstr& instr) = 0;
287 virtual void visit(const ExportInstr& instr) = 0;
288 virtual void visit(const FetchInstr& instr) = 0;
289 virtual void visit(const Block& instr) = 0;
290 virtual void visit(const ControlFlowInstr& instr) = 0;
291 virtual void visit(const IfInstr& instr) = 0;
292 virtual void visit(const ScratchIOInstr& instr) = 0;
293 virtual void visit(const StreamOutInstr& instr) = 0;
294 virtual void visit(const MemRingOutInstr& instr) = 0;
295 virtual void visit(const EmitVertexInstr& instr) = 0;
296 virtual void visit(const GDSInstr& instr) = 0;
297 virtual void visit(const WriteTFInstr& instr) = 0;
298 virtual void visit(const LDSAtomicInstr& instr) = 0;
299 virtual void visit(const LDSReadInstr& instr) = 0;
300 virtual void visit(const RatInstr& instr) = 0;
301 };
302
303 class InstrVisitor {
304 public:
305 virtual void visit(AluInstr *instr) = 0;
306 virtual void visit(AluGroup *instr) = 0;
307 virtual void visit(TexInstr *instr) = 0;
308 virtual void visit(ExportInstr *instr) = 0;
309 virtual void visit(FetchInstr *instr) = 0;
310 virtual void visit(Block *instr) = 0;
311 virtual void visit(ControlFlowInstr *instr) = 0;
312 virtual void visit(IfInstr *instr) = 0;
313 virtual void visit(ScratchIOInstr *instr) = 0;
314 virtual void visit(StreamOutInstr *instr) = 0;
315 virtual void visit(MemRingOutInstr *instr) = 0;
316 virtual void visit(EmitVertexInstr *instr) = 0;
317 virtual void visit(GDSInstr *instr) = 0;
318 virtual void visit(WriteTFInstr *instr) = 0;
319 virtual void visit(LDSAtomicInstr *instr) = 0;
320 virtual void visit(LDSReadInstr *instr) = 0;
321 virtual void visit(RatInstr *instr) = 0;
322 };
323
324
325 } // ns r600
326