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