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