1 /* -*- mesa-c++ -*- 2 * 3 * Copyright (c) 2018 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 28 #ifndef SFN_VALUEPOOL_H 29 #define SFN_VALUEPOOL_H 30 31 #include "sfn_value.h" 32 #include "sfn_value_gpr.h" 33 34 #include <set> 35 #include <queue> 36 37 namespace r600 { 38 39 using LiteralBuffer = std::map<unsigned, const nir_load_const_instr *>; 40 41 class ValueMap { 42 public: insert(const PValue & v)43 void insert(const PValue& v) { 44 auto idx = index_from(v->sel(), v->chan()); 45 m_map[idx] = v; 46 } get_or_inject(uint32_t index,uint32_t chan)47 PValue get_or_inject(uint32_t index, uint32_t chan) { 48 auto idx = index_from(index, chan); 49 auto v = m_map.find(idx); 50 if (v == m_map.end()) { 51 insert(PValue(new GPRValue(index, chan))); 52 v = m_map.find(idx); 53 } 54 return v->second; 55 } begin()56 std::map<uint32_t, PValue>::const_iterator begin() const {return m_map.begin();} end()57 std::map<uint32_t, PValue>::const_iterator end() const {return m_map.end();} 58 59 private: index_from(uint32_t index,uint32_t chan)60 uint32_t index_from(uint32_t index, uint32_t chan) { 61 return (index << 3) + chan; 62 } 63 std::map<uint32_t, PValue> m_map; 64 }; 65 66 /** \brief Class to keep track of registers, uniforms, and literals 67 * This class holds the references to the uniforms and the literals 68 * and is responsible for allocating the registers. 69 */ 70 class ValuePool 71 { 72 public: 73 74 struct array_entry { 75 unsigned index; 76 unsigned length; 77 unsigned ncomponents; 78 operatorarray_entry79 bool operator ()(const array_entry& a, const array_entry& b) const { 80 return a.length < b.length || (a.length == b.length && a.ncomponents > b.ncomponents); 81 } 82 }; 83 84 using array_list = std::priority_queue<array_entry, std::vector<array_entry>, 85 array_entry>; 86 87 ValuePool(); 88 89 90 GPRVector vec_from_nir(const nir_dest& dst, int num_components); 91 92 std::vector<PValue> varvec_from_nir(const nir_dest& src, int num_components); 93 std::vector<PValue> varvec_from_nir(const nir_src& src, int num_components); 94 95 PValue from_nir(const nir_src& v, unsigned component, unsigned swizzled); 96 97 PValue from_nir(const nir_src& v, unsigned component); 98 /** Get a register that is used as source register in an ALU instruction 99 * The PValue holds one componet as specified. If the register refers to 100 * a GPR it must already have been allocated, uniforms and literals on 101 * the other hand might be pre-loaded. 102 */ 103 PValue from_nir(const nir_alu_src& v, unsigned component); 104 105 /** Get a register that is used as source register in an Texture instruction 106 * The PValue holds one componet as specified. 107 */ 108 PValue from_nir(const nir_tex_src& v, unsigned component); 109 110 /** Allocate a register that is used as destination register in an ALU 111 * instruction. The PValue holds one componet as specified. 112 */ 113 PValue from_nir(const nir_alu_dest& v, unsigned component); 114 115 /** Allocate a register that is used as destination register in any 116 * instruction. The PValue holds one componet as specified. 117 */ 118 PValue from_nir(const nir_dest& v, unsigned component); 119 120 121 /** Inject a register into a given ssa index position 122 * This is used to redirect loads from system values and vertex attributes 123 * that are already loaded into registers */ 124 bool inject_register(unsigned sel, unsigned swizzle, const PValue ®, bool map); 125 126 /** Reserve space for a local register */ 127 void allocate_local_register(const nir_register& reg); 128 void allocate_local_register(const nir_register ®, array_list& arrays); 129 130 void allocate_arrays(array_list& arrays); 131 132 increment_reserved_registers()133 void increment_reserved_registers() { 134 ++m_next_register_index; 135 } 136 set_reserved_registers(unsigned rr)137 void set_reserved_registers(unsigned rr) { 138 m_next_register_index =rr; 139 } 140 141 /** Reserve a undef register, currently it uses (0,7), 142 * \todo should be eliminated in the final pass 143 */ 144 bool create_undef(nir_ssa_undef_instr* instr); 145 146 /** Create a new register with the given index and store it in the 147 * lookup map 148 */ 149 PValue create_register_from_nir_src(const nir_src& sel, int comp); 150 151 ValueMap get_temp_registers() const; 152 153 PValue lookup_register(unsigned sel, unsigned swizzle, bool required); 154 register_count()155 size_t register_count() const {return m_next_register_index;} 156 157 PValue literal(uint32_t value); 158 159 PGPRValue get_temp_register(int channel = -1); 160 161 GPRVector get_temp_vec4(const GPRVector::Swizzle &swizzle = {0,1,2,3}); 162 163 protected: 164 std::vector<PGPRArray> m_reg_arrays; 165 166 private: 167 168 /** Get the register index mapped from the NIR code to the r600 ir 169 * \param index NIR index of register 170 * \returns r600 ir inxex 171 */ 172 int lookup_register_index(const nir_src& src) const; 173 174 /** Get the register index mapped from the NIR code to the r600 ir 175 * \param index NIR index of register 176 * \returns r600 ir inxex 177 */ 178 int lookup_register_index(const nir_dest& dst); 179 180 /** Allocate a register that is is needed for lowering an instruction 181 * that requires complex calculations, 182 */ 183 int allocate_temp_register(); 184 185 186 PValue create_register(unsigned index, unsigned swizzle); 187 188 unsigned get_dst_ssa_register_index(const nir_ssa_def& ssa); 189 190 unsigned get_ssa_register_index(const nir_ssa_def& ssa) const; 191 192 unsigned get_local_register_index(const nir_register& reg); 193 194 unsigned get_local_register_index(const nir_register& reg) const; 195 196 void allocate_ssa_register(const nir_ssa_def& ssa); 197 198 void allocate_array(const nir_register& reg); 199 200 201 /** Allocate a register index with the given component mask. 202 * If one of the components is already been allocated the function 203 * will signal an error bz returning -1, otherwise a register index is 204 * returned. 205 */ 206 int allocate_with_mask(unsigned index, unsigned mask, bool pre_alloc); 207 208 /** search for a new register with the given index in the 209 * lookup map. 210 * \param sel register sel value 211 * \param swizzle register component, can also be 4,5, and 7 212 * \param required true: in debug mode assert when register doesn't exist 213 * false: return nullptr on failure 214 */ 215 216 std::set<unsigned> m_ssa_undef; 217 218 std::map<unsigned, unsigned> m_ssa_register_map; 219 220 std::map<unsigned, PValue> m_registers; 221 222 static PValue m_undef; 223 224 struct VRec { 225 unsigned index; 226 unsigned mask; 227 unsigned pre_alloc_mask; 228 }; 229 std::map<unsigned, VRec> m_register_map; 230 231 unsigned m_next_register_index; 232 233 234 std::map<uint32_t, PValue> m_literals; 235 236 int current_temp_reg_index; 237 int next_temp_reg_comp; 238 }; 239 240 } 241 242 #endif // SFN_VALUEPOOL_H 243