• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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()88    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()97    bool is_dead() const {return m_instr_flags.test(dead);}
is_scheduled()98    bool is_scheduled() const {return m_instr_flags.test(scheduled);}
keep()99    bool keep() const {return m_instr_flags.test(always_keep);}
has_uses()100    bool has_uses() const {return m_use_count > 0;}
101 
has_instr_flag(Flags f)102    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()108    virtual int nesting_corr() const { return 0;}
109 
end_block()110    virtual bool end_block() const { return false;}
nesting_offset()111    virtual int nesting_offset() const { return 0;}
112 
113    void set_blockid(int id, int index);
block_id()114    int block_id() const {return m_block_id;}
index()115    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()122    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()130    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()179    const_iterator begin() const { return m_instructions.begin();}
end()180    const_iterator end() const { return m_instructions.end();}
181 
empty()182    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()191    int nesting_depth() const { return m_nesting_depth;}
192 
id()193    int id() const {return m_id;}
194 
type()195    auto type() const {return m_blocK_type; }
196    void set_type(Type t);
remaining_slots()197    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()209    size_t size() const { return m_instructions.size();}
210 
kcache_reservation_failed()211    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 
do_ready()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)247    int dest_swizzle(int i) const { return m_dest_swizzle[i];}
all_dest_swizzle()248    const RegisterVec4::Swizzle&  all_dest_swizzle() const { return m_dest_swizzle;}
dst()249    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 
262 inline bool operator == (const Instr& lhs, const Instr& rhs) {
263    return lhs.equal_to(rhs);
264 }
265 
266 inline bool operator != (const Instr& lhs, const Instr& rhs) {
267    return !(lhs == rhs);
268 }
269 
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>>>
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