• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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