• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
28 #ifndef VALUEFACTORY_H
29 #define VALUEFACTORY_H
30 
31 #include "sfn_virtualvalues.h"
32 #include "sfn_alu_defines.h"
33 
34 #include "nir.h"
35 
36 #include <unordered_map>
37 #include <cassert>
38 #include <ostream>
39 #include <unordered_map>
40 #include <list>
41 
42 struct r600_shader;
43 
44 namespace r600 {
45 
46 struct LiveRangeEntry {
47    enum EUse {
48       use_export,
49       use_unspecified
50    };
51 
LiveRangeEntryLiveRangeEntry52    LiveRangeEntry (Register *reg): m_register(reg) {}
53    int m_start{-1};
54    int m_end{-1};
55    int m_index{-1};
56    int m_color{-1};
57    std::bitset<use_unspecified> m_use;
58    Register *m_register;
59 
printLiveRangeEntry60    void print(std::ostream& os) const {
61       os << *m_register << "(" << m_index << ", " <<  m_color << ") ["
62          << m_start << ":" << m_end << "]";
63    }
64 };
65 
66 inline std::ostream& operator << (std::ostream& os, const LiveRangeEntry& lre)
67 {
68    lre.print(os);
69    return os;
70 }
71 
72 class LiveRangeMap {
73 public:
74    using ChannelLiveRange = std::vector<LiveRangeEntry>;
75 
operator()76    LiveRangeEntry& operator()(int index, int chan) {
77       assert(chan  < 4);
78       return m_life_ranges[chan].at(index);
79    }
80 
81    void append_register(Register *reg);
82 
set_life_range(const Register & reg,int start,int end)83    void set_life_range(const Register& reg, int start, int end) {
84       auto& entry = m_life_ranges[reg.chan()].at(reg.index());
85       entry.m_start = start;
86       entry.m_end = end;
87    }
88 
89    std::array<size_t, 4> sizes() const;
90 
component(int i)91    ChannelLiveRange& component(int i) {
92       return m_life_ranges[i];
93    }
94 
component(int i)95    const ChannelLiveRange& component(int i) const {
96       return m_life_ranges[i];
97    }
98 
99 private:
100 
101    std::array<ChannelLiveRange, 4> m_life_ranges;
102 };
103 
104 std::ostream& operator <<  (std::ostream& os, const LiveRangeMap& lrm);
105 
106 bool operator == (const LiveRangeMap& lhs, const LiveRangeMap& rhs);
107 
108 inline bool operator != (const LiveRangeMap& lhs, const LiveRangeMap& rhs)
109 {
110    return !(lhs == rhs);
111 }
112 
113 enum EValuePool {
114    vp_ssa,
115    vp_register,
116    vp_temp,
117    vp_array,
118    vp_ignore
119 };
120 
121 union RegisterKey {
122     struct  {
123         uint32_t index;
124         uint32_t chan : 29;
125         EValuePool pool : 3;
126     } value;
127     uint64_t hash;
128 
RegisterKey(uint32_t index,uint32_t chan,EValuePool pool)129     RegisterKey(uint32_t index, uint32_t chan, EValuePool pool)
130     {
131         value.index = index;
132         value.chan = chan;
133         value.pool = pool;
134     }
135 
print(std::ostream & os)136     void print(std::ostream& os) const {
137         os << "(" << value.index
138            << ", " << value.chan
139            << ", ";
140         switch (value.pool) {
141         case vp_ssa: os << "ssa"; break;
142         case vp_register: os << "reg"; break;
143         case vp_temp: os << "temp"; break;
144         case vp_array : os << "array"; break;
145         case vp_ignore : break;
146         }
147         os << ")";
148     }
149 };
150 
151 
152 inline bool operator == (const RegisterKey& lhs, const RegisterKey& rhs) {
153     return lhs.hash == rhs.hash;
154 }
155 
156 inline std::ostream& operator << (std::ostream& os, const RegisterKey& key) {
157     key.print(os);
158     return os;
159 }
160 
161 struct register_key_hash {
operatorregister_key_hash162     std::size_t operator () (const RegisterKey& key) const {
163         return key.hash;
164     }
165 };
166 
167 class ChannelCounts {
168 public:
inc_count(int chan)169    void inc_count(int chan) {++m_counts[chan];}
least_used()170    int least_used() const  {
171       int least_used = 0;
172       uint32_t count = m_counts[0];
173       for (int i = 1; i < 4; ++i) {
174          if (count > m_counts[i]) {
175             count = m_counts[i];
176             least_used = i;
177          }
178       }
179       return least_used;
180    }
print(std::ostream & os)181    void print(std::ostream& os) const {
182       os << "CC:" << m_counts[0] << " " << m_counts[1]
183          << " " << m_counts[2] << " " << m_counts[3];
184    }
185 private:
186    std::array<uint32_t, 4> m_counts{0,0,0,0};
187 };
188 
189 inline std::ostream& operator << (std::ostream& os, const ChannelCounts& cc)
190 {
191    cc.print(os);
192    return os;
193 }
194 
195 class ValueFactory : public Allocate {
196 public:
197     ValueFactory();
198 
199     void clear();
200 
201     ValueFactory(const ValueFactory& orig) = delete;
202     ValueFactory& operator = (const ValueFactory& orig) = delete;
203 
204     void set_virtual_register_base(int base);
205 
206     bool allocate_registers(const exec_list *registers);
207     PRegister allocate_pinned_register(int sel, int chan);
208     RegisterVec4 allocate_pinned_vec4(int sel, bool is_ssa);
209 
210     void inject_value(const nir_dest& dest, int chan, PVirtualValue value);
211 
212     std::vector<PRegister, Allocator<PRegister>>  dest_vec(const nir_dest& dest, int num_components);
213     std::vector<PRegister, Allocator<PRegister>>  dest_vector(const nir_src& src,
214                                                               const std::vector<int>& components);
215 
216 
217     PRegister dest(const nir_alu_dest& dest, int chan, Pin pin_channel);
218     PRegister dest(const nir_dest& dest, int chan, Pin pin_channel);
219     PRegister dest(const nir_ssa_def& dest, int chan, Pin pin_channel);
220 
221     PRegister dummy_dest(unsigned chan);
222     PRegister temp_register(int pinned_channel = -1, bool is_ssa = true);
223     RegisterVec4 temp_vec4(Pin pin, const RegisterVec4::Swizzle& swizzle = {0,1,2,3});
224     RegisterVec4 dest_vec4(const nir_dest& dest, Pin pin);
225 
226     RegisterVec4 src_vec4(const nir_src& src, Pin pin, const RegisterVec4::Swizzle &swz = {0,1,2,3});
227 
228     PVirtualValue src(const nir_alu_src& alu_src, int chan);
229     PVirtualValue src64(const nir_alu_src& alu_src, int chan, int comp);
230     PVirtualValue src(const nir_src& src, int chan);
231     PVirtualValue src(const nir_tex_src& tex_src, int chan);
232     PVirtualValue literal(uint32_t value);
233     PVirtualValue uniform(nir_intrinsic_instr *load_uniform, int chan);
234     PVirtualValue uniform(uint32_t index, int chan, int kcache);
235 
236     void allocate_const(nir_load_const_instr *load_const);
237 
238     PRegister dest_from_string(const std::string& s);
239     RegisterVec4 dest_vec4_from_string(const std::string& s, RegisterVec4::Swizzle &swz,
240                                        Pin pin = pin_none);
241     PVirtualValue src_from_string(const std::string& s);
242     RegisterVec4 src_vec4_from_string(const std::string& s);
243 
244     LocalArray *array_from_string(const std::string& s);
245 
246     std::vector<PVirtualValue, Allocator<PVirtualValue>> src_vec(const nir_src& src, int components);
247 
248     PInlineConstant inline_const(AluInlineConstants sel, int chan);
249 
250     void get_shader_info(r600_shader *sh_info);
251 
252     PRegister undef(int index, int chan);
253     PVirtualValue zero();
254     PVirtualValue one();
255     PVirtualValue one_i();
256 
257     LiveRangeMap prepare_live_range_map();
258 
259     void clear_pins();
260 
next_register_index()261     int next_register_index() const { return m_next_register_index; }
262 private:
263 
264     PVirtualValue ssa_src(const nir_ssa_def &dest, int chan);
265 
266     PRegister local_register(const nir_reg_dest& dest, int chan);
267     PRegister local_register(const nir_reg_src& dest, int chan);
268     PRegister resolve_array(nir_register *reg, nir_src *indirect,
269                             int base_offset, int chan);
270 
271     int m_next_register_index;
272     int m_next_temp_channel{0};
273 
274     template <typename Key, typename T>
275     using unordered_map_alloc = std::unordered_map<Key, T, std::hash<Key>, std::equal_to<Key>,
276     Allocator<std::pair<const Key, T>>>;
277 
278     template <typename Key, typename T>
279     using unordered_reg_map_alloc = std::unordered_map<Key, T, register_key_hash, std::equal_to<Key>,
280     Allocator<std::pair<const Key, T>>>;
281 
282     using RegisterMap = unordered_reg_map_alloc<RegisterKey, PRegister>;
283     using ROValueMap = unordered_reg_map_alloc<RegisterKey, PVirtualValue>;
284 
285     RegisterMap m_registers;
286     std::list<PRegister, Allocator<PRegister>> m_pinned_registers;
287     ROValueMap m_values;
288     unordered_map_alloc<uint32_t, PLiteralVirtualValue> m_literal_values;
289     unordered_map_alloc<uint32_t, InlineConstant::Pointer> m_inline_constants;
290     unordered_map_alloc<uint32_t, uint32_t> m_ssa_index_to_sel;
291 
292     uint32_t m_nowrite_idx;
293 
294     RegisterVec4 m_dummy_dest_pinned{126, pin_chan, {0,1,2,3}};
295     ChannelCounts m_channel_counts;
296 };
297 
298 }
299 
300 #endif // VALUEFACTORY_H
301