• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- mesa-c++  -*-
2  *
3  * Copyright (c) 2022 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 #ifndef INSTRALU_H
28 #define INSTRALU_H
29 
30 #include "sfn_instr.h"
31 
32 #include <unordered_set>
33 
34 struct nir_alu_instr;
35 
36 namespace r600 {
37 
38 class Shader;
39 class ValueFactory;
40 
41 class AluInstr : public Instr {
42 public:
43    using SrcValues = std::vector<PVirtualValue, Allocator<PVirtualValue>>;
44 
45    enum Op2Options {
46       op2_opt_none = 0,
47       op2_opt_reverse = 1,
48       op2_opt_neg_src1 = 1 << 1,
49       op2_opt_abs_src0 = 1 << 2
50    };
51 
52    enum SourceMod {
53       mod_none = 0,
54       mod_abs = 1,
55       mod_neg = 2
56    };
57 
58 
59    static constexpr const AluBankSwizzle bs[6] = {
60       alu_vec_012, alu_vec_021, alu_vec_120, alu_vec_102, alu_vec_201, alu_vec_210};
61 
62    static const AluModifiers src_abs_flags[2];
63    static const AluModifiers src_neg_flags[3];
64    static const AluModifiers src_rel_flags[3];
65 
66    AluInstr(EAluOp opcode);
67    AluInstr(EAluOp opcode, int chan);
68    AluInstr(EAluOp opcode,
69             PRegister dest,
70             SrcValues src0,
71             const std::set<AluModifiers>& flags,
72             int alu_slot);
73 
74    AluInstr(EAluOp opcode,
75             PRegister dest,
76             PVirtualValue src0,
77             const std::set<AluModifiers>& flags);
78 
79    AluInstr(EAluOp opcode,
80             PRegister dest,
81             PVirtualValue src0,
82             PVirtualValue src1,
83             const std::set<AluModifiers>& flags);
84 
85    AluInstr(EAluOp opcode,
86             PRegister dest,
87             PVirtualValue src0,
88             PVirtualValue src1,
89             PVirtualValue src2,
90             const std::set<AluModifiers>& flags);
91 
92    AluInstr(ESDOp op, PVirtualValue src0, PVirtualValue src1, PVirtualValue address);
93    AluInstr(ESDOp op, const SrcValues& src, const std::set<AluModifiers>& flags);
94 
95    void accept(ConstInstrVisitor& visitor) const override;
96    void accept(InstrVisitor& visitor) override;
97 
opcode()98    auto opcode() const
99    {
100       assert(!has_alu_flag(alu_is_lds));
101       return m_opcode;
102    }
lds_opcode()103    auto lds_opcode() const
104    {
105       assert(has_alu_flag(alu_is_lds));
106       return m_lds_opcode;
107    }
108 
109    bool can_propagate_src() const;
110    bool can_propagate_dest() const;
111 
112    bool replace_source(PRegister old_src, PVirtualValue new_src) override;
113    bool replace_dest(PRegister new_dest, AluInstr *move_instr) override;
114 
115    bool can_replace_source(PRegister old_src, PVirtualValue new_src);
116    bool do_replace_source(PRegister old_src, PVirtualValue new_src);
117 
set_op(EAluOp op)118    void set_op(EAluOp op) { m_opcode = op; }
119 
dest()120    PRegister dest() const { return m_dest; }
n_sources()121    unsigned n_sources() const { return m_src.size(); }
122 
dest_chan()123    int dest_chan() const { return m_dest ? m_dest->chan() : m_fallback_chan; }
124 
psrc(unsigned i)125    const VirtualValue *psrc(unsigned i) const { return i < m_src.size() ? m_src[i] : nullptr; }
psrc(unsigned i)126    PVirtualValue psrc(unsigned i) { return i < m_src.size() ? m_src[i] : nullptr; }
src(unsigned i)127    VirtualValue& src(unsigned i)
128    {
129       assert(i < m_src.size() && m_src[i]);
130       return *m_src[i];
131    }
src(unsigned i)132    const VirtualValue& src(unsigned i) const
133    {
134       assert(i < m_src.size() && m_src[i]);
135       return *m_src[i];
136    }
137 
138    void set_sources(SrcValues src);
sources()139    const SrcValues& sources() const { return m_src; }
140    void pin_sources_to_chan();
141 
142    int register_priority() const;
143 
reset_alu_flag(AluModifiers flag)144    void reset_alu_flag(AluModifiers flag) { m_alu_flags.reset(flag); }
set_alu_flag(AluModifiers flag)145    void set_alu_flag(AluModifiers flag) { m_alu_flags.set(flag); }
has_alu_flag(AluModifiers f)146    bool has_alu_flag(AluModifiers f) const { return m_alu_flags.test(f); }
147 
cf_type()148    ECFAluOpCode cf_type() const { return m_cf_type; }
set_cf_type(ECFAluOpCode cf_type)149    void set_cf_type(ECFAluOpCode cf_type) { m_cf_type = cf_type; }
set_bank_swizzle(AluBankSwizzle swz)150    void set_bank_swizzle(AluBankSwizzle swz) { m_bank_swizzle = swz; }
bank_swizzle()151    AluBankSwizzle bank_swizzle() const { return m_bank_swizzle; }
152 
set_index_offset(unsigned offs)153    void set_index_offset(unsigned offs) { m_idx_offset = offs; }
index_offset()154    auto index_offset() const { return m_idx_offset; }
155 
156    bool is_equal_to(const AluInstr& lhs) const;
157 
158    bool has_lds_access() const;
159    bool has_lds_queue_read() const;
160    bool is_kill() const;
161 
162    static const std::map<ECFAluOpCode, std::string> cf_map;
163    static const std::map<AluBankSwizzle, std::string> bank_swizzle_map;
164    static Instr::Pointer
165    from_string(std::istream& is, ValueFactory& value_factory, AluGroup *, bool is_cayman);
166    static bool from_nir(nir_alu_instr *alu, Shader& shader);
167 
alu_slots()168    int alu_slots() const { return m_alu_slots; }
169 
170    AluGroup *split(ValueFactory& vf);
171 
end_group()172    bool end_group() const override { return m_alu_flags.test(alu_last_instr); }
173 
174    static const std::set<AluModifiers> empty;
175    static const std::set<AluModifiers> write;
176    static const std::set<AluModifiers> last;
177    static const std::set<AluModifiers> last_write;
178 
179    std::tuple<PRegister, bool, PRegister> indirect_addr() const;
180    void update_indirect_addr(PRegister old_reg, PRegister reg) override;
181 
182    void add_extra_dependency(PVirtualValue reg);
183 
set_required_slots(int nslots)184    void set_required_slots(int nslots) { m_required_slots = nslots; }
required_slots()185    unsigned required_slots() const { return m_required_slots; }
186 
add_priority(int priority)187    void add_priority(int priority) { m_priority += priority; }
priority()188    int priority() const { return m_priority; }
inc_priority()189    void inc_priority() { ++m_priority; }
190 
set_parent_group(AluGroup * group)191    void set_parent_group(AluGroup *group) { m_parent_group = group; }
parent_group()192    AluGroup *parent_group() { return m_parent_group;}
193 
as_alu()194    AluInstr *as_alu() override { return this; }
195 
196    uint8_t allowed_src_chan_mask() const override;
allowed_dest_chan_mask()197    uint8_t allowed_dest_chan_mask() const {return m_allowed_dest_mask;}
198 
inc_ar_uses()199    void inc_ar_uses() { ++m_num_ar_uses;}
num_ar_uses()200    auto num_ar_uses() const {return m_num_ar_uses;}
201 
202    bool replace_src(int i, PVirtualValue new_src, uint32_t to_set,
203                     SourceMod to_clear);
204 
set_source_mod(int src,SourceMod mod)205    void set_source_mod(int src, SourceMod mod) {
206       m_source_modifiers |= mod << (2 * src);
207    }
has_source_mod(int src,SourceMod mod)208    auto has_source_mod(int src, SourceMod mod) const {
209       return (m_source_modifiers & (mod << (2 * src))) != 0;
210    }
reset_source_mod(int src,SourceMod mod)211    void reset_source_mod(int src, SourceMod mod) {
212       m_source_modifiers &= ~(mod << (2 * src));
213    }
214 
215 private:
216    friend class AluGroup;
217 
218    void update_uses();
219 
220    bool do_ready() const override;
221 
222    bool can_copy_propagate() const;
223 
224    bool check_readport_validation(PRegister old_src, PVirtualValue new_src) const;
225 
set_alu_flags(const AluOpFlags & flags)226    void set_alu_flags(const AluOpFlags& flags) { m_alu_flags = flags; }
227    bool propagate_death() override;
228 
229    void do_print(std::ostream& os) const override;
230 
231    union {
232       EAluOp m_opcode;
233       ESDOp m_lds_opcode;
234    };
235 
236    PRegister m_dest{nullptr};
237    SrcValues m_src;
238 
239    AluOpFlags m_alu_flags;
240    AluBankSwizzle m_bank_swizzle{alu_vec_unknown};
241    ECFAluOpCode m_cf_type{cf_alu};
242    int m_alu_slots{1};
243    int m_fallback_chan{0};
244    unsigned m_idx_offset{0};
245    int m_required_slots{0};
246    int m_priority{0};
247    std::set<PRegister, std::less<PRegister>, Allocator<PRegister>> m_extra_dependencies;
248    AluGroup *m_parent_group{nullptr};
249    unsigned m_allowed_dest_mask{0xf};
250    unsigned m_num_ar_uses{0};
251    uint32_t m_source_modifiers{0};
252 };
253 
254 class AluInstrVisitor : public InstrVisitor {
255 public:
256    void visit(AluGroup *instr) override;
257    void visit(Block *instr) override;
258    void visit(IfInstr *instr) override;
259 
visit(TexInstr * instr)260    void visit(TexInstr *instr) override { (void)instr; }
visit(ExportInstr * instr)261    void visit(ExportInstr *instr) override { (void)instr; }
visit(FetchInstr * instr)262    void visit(FetchInstr *instr) override { (void)instr; }
visit(ControlFlowInstr * instr)263    void visit(ControlFlowInstr *instr) override { (void)instr; }
visit(ScratchIOInstr * instr)264    void visit(ScratchIOInstr *instr) override { (void)instr; }
visit(StreamOutInstr * instr)265    void visit(StreamOutInstr *instr) override { (void)instr; }
visit(MemRingOutInstr * instr)266    void visit(MemRingOutInstr *instr) override { (void)instr; }
visit(EmitVertexInstr * instr)267    void visit(EmitVertexInstr *instr) override { (void)instr; }
visit(GDSInstr * instr)268    void visit(GDSInstr *instr) override { (void)instr; };
visit(WriteTFInstr * instr)269    void visit(WriteTFInstr *instr) override { (void)instr; };
visit(LDSAtomicInstr * instr)270    void visit(LDSAtomicInstr *instr) override { (void)instr; };
visit(LDSReadInstr * instr)271    void visit(LDSReadInstr *instr) override { (void)instr; };
visit(RatInstr * instr)272    void visit(RatInstr *instr) override { (void)instr; };
273 };
274 
275 } // namespace r600
276 #endif // INSTRALU_H
277