1 /* -*- mesa-c++ -*- 2 * Copyright 2021 Collabora LTD 3 * Author: Gert Wollny <gert.wollny@collabora.com> 4 * SPDX-License-Identifier: MIT 5 */ 6 7 #ifndef VALUEFACTORY_H 8 #define VALUEFACTORY_H 9 10 #include "nir.h" 11 #include "sfn_alu_defines.h" 12 #include "sfn_virtualvalues.h" 13 14 #include <cassert> 15 #include <list> 16 #include <ostream> 17 #include <unordered_map> 18 19 struct r600_shader; 20 21 namespace r600 { 22 23 struct LiveRangeEntry { 24 enum EUse { 25 use_export, 26 use_unspecified 27 }; 28 LiveRangeEntryLiveRangeEntry29 LiveRangeEntry(Register *reg): 30 m_register(reg) 31 { 32 } 33 int m_start{-1}; 34 int m_end{-1}; 35 int m_index{-1}; 36 int m_color{-1}; 37 bool m_alu_clause_local{false}; 38 std::bitset<use_unspecified> m_use; 39 Register *m_register; 40 printLiveRangeEntry41 void print(std::ostream& os) const 42 { 43 os << *m_register << "(" << m_index << ", " << m_color << ") [" << m_start << ":" 44 << m_end << "]"; 45 } 46 }; 47 48 inline std::ostream& 49 operator<<(std::ostream& os, const LiveRangeEntry& lre) 50 { 51 lre.print(os); 52 return os; 53 } 54 55 class LiveRangeMap { 56 public: 57 using ChannelLiveRange = std::vector<LiveRangeEntry>; 58 operator()59 LiveRangeEntry& operator()(int index, int chan) 60 { 61 assert(chan < 4); 62 return m_life_ranges[chan].at(index); 63 } 64 65 void append_register(Register *reg); 66 set_life_range(const Register & reg,int start,int end)67 void set_life_range(const Register& reg, int start, int end) 68 { 69 auto& entry = m_life_ranges[reg.chan()].at(reg.index()); 70 entry.m_start = start; 71 entry.m_end = end; 72 } 73 74 std::array<size_t, 4> sizes() const; 75 component(int i)76 ChannelLiveRange& component(int i) { return m_life_ranges[i]; } 77 component(int i)78 const ChannelLiveRange& component(int i) const { return m_life_ranges[i]; } 79 80 private: 81 std::array<ChannelLiveRange, 4> m_life_ranges; 82 }; 83 84 std::ostream& 85 operator<<(std::ostream& os, const LiveRangeMap& lrm); 86 87 bool 88 operator==(const LiveRangeMap& lhs, const LiveRangeMap& rhs); 89 90 inline bool 91 operator!=(const LiveRangeMap& lhs, const LiveRangeMap& rhs) 92 { 93 return !(lhs == rhs); 94 } 95 96 enum EValuePool { 97 vp_ssa, 98 vp_register, 99 vp_temp, 100 vp_array, 101 vp_ignore 102 }; 103 104 union RegisterKey { 105 struct { 106 uint32_t index; 107 uint32_t chan : 29; 108 EValuePool pool : 3; 109 } value; 110 uint64_t hash; 111 RegisterKey(uint32_t index,uint32_t chan,EValuePool pool)112 RegisterKey(uint32_t index, uint32_t chan, EValuePool pool) 113 { 114 value.index = index; 115 value.chan = chan; 116 value.pool = pool; 117 } 118 print(std::ostream & os)119 void print(std::ostream& os) const 120 { 121 os << "(" << value.index << ", " << value.chan << ", "; 122 switch (value.pool) { 123 case vp_ssa: 124 os << "ssa"; 125 break; 126 case vp_register: 127 os << "reg"; 128 break; 129 case vp_temp: 130 os << "temp"; 131 break; 132 case vp_array: 133 os << "array"; 134 break; 135 case vp_ignore: 136 break; 137 } 138 os << ")"; 139 } 140 }; 141 142 inline bool 143 operator==(const RegisterKey& lhs, const RegisterKey& rhs) 144 { 145 return lhs.hash == rhs.hash; 146 } 147 148 inline std::ostream& 149 operator<<(std::ostream& os, const RegisterKey& key) 150 { 151 key.print(os); 152 return os; 153 } 154 155 struct register_key_hash { operatorregister_key_hash156 std::size_t operator()(const RegisterKey& key) const { return key.hash; } 157 }; 158 159 class ChannelCounts { 160 public: inc_count(int chan)161 void inc_count(int chan) { ++m_counts[chan]; } inc_count(int chan,int n)162 void inc_count(int chan, int n) { m_counts[chan] += n; } least_used(uint8_t mask)163 int least_used(uint8_t mask) const 164 { 165 int least_used = 0; 166 uint32_t count = m_counts[0]; 167 for (int i = 1; i < 4; ++i) { 168 if (!((1 << i) & mask)) 169 continue; 170 if (count > m_counts[i]) { 171 count = m_counts[i]; 172 least_used = i; 173 } 174 } 175 return least_used; 176 } print(std::ostream & os)177 void print(std::ostream& os) const 178 { 179 os << "CC:" << m_counts[0] << " " << m_counts[1] << " " << m_counts[2] << " " 180 << m_counts[3]; 181 } 182 183 private: 184 std::array<uint32_t, 4> m_counts{0, 0, 0, 0}; 185 }; 186 187 inline std::ostream& 188 operator<<(std::ostream& os, const ChannelCounts& cc) 189 { 190 cc.print(os); 191 return os; 192 } 193 194 class ValueFactory : public Allocate { 195 public: 196 ValueFactory(); 197 198 void clear(); 199 200 ValueFactory(const ValueFactory& orig) = delete; 201 ValueFactory& operator=(const ValueFactory& orig) = delete; 202 203 void set_virtual_register_base(int base); 204 205 int new_register_index(); 206 207 using nir_intrinsic_instr_alloc = 208 std::list<nir_intrinsic_instr *, Allocator<nir_intrinsic_instr *>>; 209 210 /* Allocate registers */ 211 bool allocate_registers(const nir_intrinsic_instr_alloc& regs); 212 PRegister allocate_pinned_register(int sel, int chan); 213 RegisterVec4 allocate_pinned_vec4(int sel, bool is_ssa); 214 215 /* Inject a predefined value for a given dest value 216 * (usually the result of a sysvalue load) */ 217 void inject_value(const nir_def& def, int chan, PVirtualValue value); 218 219 /* Get or create a destination value of vector of values */ 220 PRegister 221 dest(const nir_def& def, int chan, Pin pin_channel, uint8_t chan_mask = 0xf); 222 223 RegisterVec4 dest_vec4(const nir_def& dest, Pin pin); 224 225 std::vector<PRegister, Allocator<PRegister>> dest_vec(const nir_def& dest, 226 int num_components); 227 228 PRegister dummy_dest(unsigned chan); 229 230 231 /* Create and get a temporary value */ 232 PRegister temp_register(int pinned_channel = -1, bool is_ssa = true); 233 RegisterVec4 temp_vec4(Pin pin, const RegisterVec4::Swizzle& swizzle = {0, 1, 2, 3}); 234 235 236 RegisterVec4 237 src_vec4(const nir_src& src, Pin pin, const RegisterVec4::Swizzle& swz = {0, 1, 2, 3}); 238 239 PVirtualValue src(const nir_alu_src& alu_src, int chan); 240 PVirtualValue src64(const nir_alu_src& alu_src, int chan, int comp); 241 PVirtualValue src(const nir_src& src, int chan); 242 PVirtualValue src(const nir_tex_src& tex_src, int chan); 243 PVirtualValue literal(uint32_t value); 244 PVirtualValue uniform(nir_intrinsic_instr *load_uniform, int chan); 245 PVirtualValue uniform(uint32_t index, int chan, int kcache); 246 std::vector<PVirtualValue, Allocator<PVirtualValue>> src_vec(const nir_src& src, 247 int components); 248 249 250 void allocate_const(nir_load_const_instr *load_const); 251 252 PRegister dest_from_string(const std::string& s); 253 RegisterVec4 dest_vec4_from_string(const std::string& s, 254 RegisterVec4::Swizzle& swz, 255 Pin pin = pin_none); 256 PVirtualValue src_from_string(const std::string& s); 257 RegisterVec4 src_vec4_from_string(const std::string& s); 258 259 LocalArray *array_from_string(const std::string& s); 260 261 262 PInlineConstant inline_const(AluInlineConstants sel, int chan); 263 264 void get_shader_info(r600_shader *sh_info); 265 266 PRegister undef(int index, int chan); 267 PVirtualValue zero(); 268 PVirtualValue one(); 269 PVirtualValue one_i(); 270 271 LiveRangeMap prepare_live_range_map(); 272 273 void clear_pins(); 274 next_register_index()275 int next_register_index() const { return m_next_register_index; } array_registers()276 uint32_t array_registers() const { return m_required_array_registers; } 277 278 PRegister addr(); 279 PRegister idx_reg(unsigned idx); 280 281 private: 282 PVirtualValue ssa_src(const nir_def& dest, int chan); 283 284 int m_next_register_index; 285 int m_next_temp_channel{0}; 286 287 template <typename Key, typename T> 288 using unordered_map_alloc = std::unordered_map<Key, 289 T, 290 std::hash<Key>, 291 std::equal_to<Key>, 292 Allocator<std::pair<const Key, T>>>; 293 294 template <typename Key, typename T> 295 using unordered_reg_map_alloc = std::unordered_map<Key, 296 T, 297 register_key_hash, 298 std::equal_to<Key>, 299 Allocator<std::pair<const Key, T>>>; 300 301 using RegisterMap = unordered_reg_map_alloc<RegisterKey, PRegister>; 302 using ROValueMap = unordered_reg_map_alloc<RegisterKey, PVirtualValue>; 303 304 RegisterMap m_registers; 305 std::list<PRegister, Allocator<PRegister>> m_pinned_registers; 306 ROValueMap m_values; 307 unordered_map_alloc<uint32_t, PLiteralVirtualValue> m_literal_values; 308 unordered_map_alloc<uint32_t, InlineConstant::Pointer> m_inline_constants; 309 unordered_map_alloc<uint32_t, uint32_t> m_ssa_index_to_sel; 310 311 uint32_t m_nowrite_idx; 312 313 RegisterVec4 m_dummy_dest_pinned{ 314 g_registers_end, pin_chan, {0, 1, 2, 3} 315 }; 316 ChannelCounts m_channel_counts; 317 uint32_t m_required_array_registers{0}; 318 319 AddressRegister *m_ar{nullptr}; 320 AddressRegister *m_idx0{nullptr}; 321 AddressRegister *m_idx1{nullptr}; 322 }; 323 324 } // namespace r600 325 326 #endif // VALUEFACTORY_H 327