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 44 using SrcValues = std::vector<PVirtualValue, Allocator<PVirtualValue>>; 45 46 enum Op2Options { 47 op2_opt_none = 0, 48 op2_opt_reverse = 1, 49 op2_opt_neg_src1 = 1 << 1, 50 op2_opt_abs_src0 = 1 << 2 51 }; 52 53 static constexpr const AluBankSwizzle bs[6] = { 54 alu_vec_012, 55 alu_vec_021, 56 alu_vec_120, 57 alu_vec_102, 58 alu_vec_201, 59 alu_vec_210 60 }; 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, PRegister dest, 69 SrcValues src0, 70 const std::set<AluModifiers>& flags, int alu_slot); 71 72 AluInstr(EAluOp opcode, PRegister dest, PVirtualValue src0, 73 const std::set<AluModifiers>& flags); 74 75 AluInstr(EAluOp opcode, PRegister dest, 76 PVirtualValue src0, PVirtualValue src1, 77 const std::set<AluModifiers>& flags); 78 79 AluInstr(EAluOp opcode, PRegister dest, PVirtualValue src0, PVirtualValue src1, 80 PVirtualValue src2, 81 const std::set<AluModifiers>& flags); 82 83 AluInstr(ESDOp op, PVirtualValue src0, PVirtualValue src1, PVirtualValue address); 84 AluInstr(ESDOp op, const SrcValues& src, const std::set<AluModifiers>& flags); 85 86 void accept(ConstInstrVisitor& visitor) const override; 87 void accept(InstrVisitor& visitor) override; 88 opcode()89 auto opcode() const {assert(!has_alu_flag(alu_is_lds)); return m_opcode;} lds_opcode()90 auto lds_opcode() const {assert(has_alu_flag(alu_is_lds)); return m_lds_opcode;} 91 92 bool can_propagate_src() const; 93 bool can_propagate_dest() const; 94 95 bool replace_source(PRegister old_src, PVirtualValue new_src) override; 96 bool replace_dest(PRegister new_dest, AluInstr *move_instr) override; 97 set_op(EAluOp op)98 void set_op(EAluOp op) {m_opcode = op;} 99 dest()100 PRegister dest() const {return m_dest;} n_sources()101 unsigned n_sources() const {return m_src.size();} 102 dest_chan()103 int dest_chan() const {return m_dest ? m_dest->chan() : m_fallback_chan;} 104 psrc(unsigned i)105 PVirtualValue psrc(unsigned i) {return i < m_src.size() ? m_src[i] : nullptr;} src(unsigned i)106 VirtualValue& src(unsigned i) {assert(i < m_src.size() && m_src[i]); return *m_src[i];} src(unsigned i)107 const VirtualValue& src(unsigned i) const {assert(i < m_src.size() && m_src[i]); return *m_src[i];} 108 109 void set_sources(SrcValues src); sources()110 const SrcValues& sources() const {return m_src;} 111 void pin_sources_to_chan(); 112 113 int register_priority() const; 114 reset_alu_flag(AluModifiers flag)115 void reset_alu_flag(AluModifiers flag) {m_alu_flags.reset(flag);} set_alu_flag(AluModifiers flag)116 void set_alu_flag(AluModifiers flag) {m_alu_flags.set(flag);} has_alu_flag(AluModifiers f)117 bool has_alu_flag(AluModifiers f) const {return m_alu_flags.test(f);} 118 cf_type()119 ECFAluOpCode cf_type() const {return m_cf_type;} set_cf_type(ECFAluOpCode cf_type)120 void set_cf_type(ECFAluOpCode cf_type){ m_cf_type = cf_type; } set_bank_swizzle(AluBankSwizzle swz)121 void set_bank_swizzle(AluBankSwizzle swz) {m_bank_swizzle = swz;} bank_swizzle()122 AluBankSwizzle bank_swizzle() const {return m_bank_swizzle;} 123 set_index_offset(unsigned offs)124 void set_index_offset(unsigned offs) {m_idx_offset = offs;} index_offset()125 auto index_offset() const {return m_idx_offset;} 126 127 bool is_equal_to(const AluInstr& lhs) const; 128 129 bool has_lds_access() const; 130 bool has_lds_queue_read() const; 131 132 static const std::map<ECFAluOpCode, std::string> cf_map; 133 static const std::map<AluBankSwizzle, std::string> bank_swizzle_map; 134 static Instr::Pointer from_string(std::istream &is, ValueFactory& value_factory, AluGroup *); 135 static bool from_nir(nir_alu_instr *alu, Shader& shader); 136 alu_slots()137 int alu_slots() const {return m_alu_slots;} 138 139 AluGroup *split(ValueFactory &vf); 140 end_group()141 bool end_group() const override { return m_alu_flags.test(alu_last_instr);} 142 143 static const std::set<AluModifiers> empty; 144 static const std::set<AluModifiers> write; 145 static const std::set<AluModifiers> last; 146 static const std::set<AluModifiers> last_write; 147 148 std::tuple<PRegister, bool, bool> indirect_addr() const; 149 150 void add_extra_dependency(PVirtualValue reg); 151 set_required_slots(int nslots)152 void set_required_slots(int nslots) { m_required_slots = nslots;} required_slots()153 unsigned required_slots() const { return m_required_slots;} 154 add_priority(int priority)155 void add_priority(int priority) { m_priority += priority;} priority()156 int priority() const { return m_priority;} inc_priority()157 void inc_priority() { ++m_priority;} 158 set_parent_group(AluGroup * group)159 void set_parent_group(AluGroup *group) { m_parent_group = group;} 160 161 private: 162 friend class AluGroup; 163 164 void update_uses(); 165 166 bool do_ready() const override; 167 168 bool can_copy_propagate() const; 169 170 bool check_readport_validation(PRegister old_src, PVirtualValue new_src) const; 171 set_alu_flags(const AluOpFlags & flags)172 void set_alu_flags(const AluOpFlags& flags) { m_alu_flags = flags; } 173 bool propagate_death() override; 174 175 void do_print(std::ostream& os) const override; 176 177 union { 178 EAluOp m_opcode; 179 ESDOp m_lds_opcode; 180 }; 181 182 PRegister m_dest{nullptr}; 183 SrcValues m_src; 184 185 AluOpFlags m_alu_flags; 186 AluBankSwizzle m_bank_swizzle{alu_vec_unknown}; 187 ECFAluOpCode m_cf_type{cf_alu}; 188 int m_alu_slots{1}; 189 int m_fallback_chan{0}; 190 unsigned m_idx_offset{0}; 191 unsigned m_required_slots{0}; 192 int m_priority{0}; 193 std::set<PRegister, std::less<PRegister>, Allocator<PRegister>> m_extra_dependencies; 194 AluGroup *m_parent_group{nullptr}; 195 }; 196 197 class AluInstrVisitor : public InstrVisitor { 198 public: 199 void visit(AluGroup *instr) override; 200 void visit(Block *instr) override; 201 void visit(IfInstr *instr) override; 202 visit(TexInstr * instr)203 void visit(TexInstr *instr) override {(void)instr;} visit(ExportInstr * instr)204 void visit(ExportInstr *instr) override {(void)instr;} visit(FetchInstr * instr)205 void visit(FetchInstr *instr) override {(void)instr;} visit(ControlFlowInstr * instr)206 void visit(ControlFlowInstr *instr) override {(void)instr;} visit(ScratchIOInstr * instr)207 void visit(ScratchIOInstr *instr) override {(void)instr;} visit(StreamOutInstr * instr)208 void visit(StreamOutInstr *instr) override {(void)instr;} visit(MemRingOutInstr * instr)209 void visit(MemRingOutInstr *instr) override {(void)instr;} visit(EmitVertexInstr * instr)210 void visit(EmitVertexInstr *instr) override {(void)instr;} visit(GDSInstr * instr)211 void visit(GDSInstr *instr) override {(void)instr;}; visit(WriteTFInstr * instr)212 void visit(WriteTFInstr *instr) override {(void)instr;}; visit(LDSAtomicInstr * instr)213 void visit(LDSAtomicInstr *instr) override {(void)instr;}; visit(LDSReadInstr * instr)214 void visit(LDSReadInstr *instr) override {(void)instr;}; visit(RatInstr * instr)215 void visit(RatInstr *instr) override {(void)instr;}; 216 }; 217 218 219 } 220 #endif // INSTRALU_H 221