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 /** Get the register index mapped from the NIR code to the r600 ir 121 * \param index NIR index of register 122 * \returns r600 ir inxex 123 */ 124 int lookup_register_index(const nir_src& src) const; 125 126 /** Get the register index mapped from the NIR code to the r600 ir 127 * \param index NIR index of register 128 * \returns r600 ir inxex 129 */ 130 int lookup_register_index(const nir_dest& dst); 131 132 /** Inject a register into a given ssa index position 133 * This is used to redirect loads from system values and vertex attributes 134 * that are already loaded into registers */ 135 bool inject_register(unsigned sel, unsigned swizzle, const PValue ®, bool map); 136 137 /** Reserve space for a local register */ 138 void allocate_local_register(const nir_register& reg); 139 void allocate_local_register(const nir_register ®, array_list& arrays); 140 141 void allocate_arrays(array_list& arrays); 142 143 increment_reserved_registers()144 void increment_reserved_registers() { 145 ++m_next_register_index; 146 } 147 set_reserved_registers(unsigned rr)148 void set_reserved_registers(unsigned rr) { 149 m_next_register_index =rr; 150 } 151 152 /** Allocate a register that is is needed for lowering an instruction 153 * that requires complex calculations, 154 */ 155 int allocate_temp_register(); 156 157 /** Reserve a undef register, currently it uses (0,7), 158 * \todo should be eliminated in the final pass 159 */ 160 bool create_undef(nir_ssa_undef_instr* instr); 161 162 /** Create a new register with the given index and store it in the 163 * lookup map 164 */ 165 PValue create_register_from_nir_src(const nir_src& sel, int comp); 166 167 ValueMap get_temp_registers() const; 168 169 PValue lookup_register(unsigned sel, unsigned swizzle, bool required); 170 register_count()171 size_t register_count() const {return m_next_register_index;} 172 173 PValue create_register(unsigned index, unsigned swizzle); 174 175 unsigned get_dst_ssa_register_index(const nir_ssa_def& ssa); 176 177 PValue literal(uint32_t value); 178 179 PGPRValue get_temp_register(int channel = -1); 180 181 GPRVector get_temp_vec4(); 182 183 private: 184 185 unsigned get_ssa_register_index(const nir_ssa_def& ssa) const; 186 187 unsigned get_local_register_index(const nir_register& reg); 188 189 unsigned get_local_register_index(const nir_register& reg) const; 190 191 void allocate_ssa_register(const nir_ssa_def& ssa); 192 193 void allocate_array(const nir_register& reg); 194 195 196 /** Allocate a register index with the given component mask. 197 * If one of the components is already been allocated the function 198 * will signal an error bz returning -1, otherwise a register index is 199 * returned. 200 */ 201 int allocate_with_mask(unsigned index, unsigned mask, bool pre_alloc); 202 203 /** Allocate a register index with the given component. 204 * If the component is already been allocated the function 205 * will signal an error bz returning -1, otherwise a register index is 206 * returned. 207 */ 208 int allocate_component(unsigned index, unsigned comp, bool pre_alloc); 209 210 /** search for a new register with the given index in the 211 * lookup map. 212 * \param sel register sel value 213 * \param swizzle register component, can also be 4,5, and 7 214 * \param required true: in debug mode assert when register doesn't exist 215 * false: return nullptr on failure 216 */ 217 218 std::set<unsigned> m_ssa_undef; 219 220 std::map<unsigned, unsigned> m_local_register_map; 221 std::map<unsigned, unsigned> m_ssa_register_map; 222 223 std::map<unsigned, PValue> m_registers; 224 225 static PValue m_undef; 226 227 struct VRec { 228 unsigned index; 229 unsigned mask; 230 unsigned pre_alloc_mask; 231 }; 232 std::map<unsigned, VRec> m_register_map; 233 234 unsigned m_next_register_index; 235 236 std::map<unsigned, PGPRArray> m_arrays_map; 237 238 std::map<uint32_t, PValue> m_literals; 239 240 int current_temp_reg_index; 241 int next_temp_reg_comp; 242 }; 243 244 } 245 246 #endif // SFN_VALUEPOOL_H 247