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