nir/opt_vectorize: Add a callback for filtering of vectorizing.
[mesa.git] / src / gallium / drivers / r600 / sfn / sfn_valuepool.h
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:
43 void insert(const PValue& v) {
44 auto idx = index_from(v->sel(), v->chan());
45 m_map[idx] = v;
46 }
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 }
56 std::map<uint32_t, PValue>::const_iterator begin() const {return m_map.begin();}
57 std::map<uint32_t, PValue>::const_iterator end() const {return m_map.end();}
58
59 private:
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
79 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 &reg, 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 &reg, array_list& arrays);
140
141 void allocate_arrays(array_list& arrays);
142
143
144 void increment_reserved_registers() {
145 ++m_next_register_index;
146 }
147
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 bool set_literal_constant(nir_load_const_instr* instr);
163
164 const nir_load_const_instr *get_literal_constant(int index);
165
166 void add_uniform(unsigned index, const PValue &value);
167
168 PValue uniform(unsigned index);
169
170 /** Create a new register with the given index and store it in the
171 * lookup map
172 */
173 PValue create_register_from_nir_src(const nir_src& sel, int comp);
174
175 ValueMap get_temp_registers() const;
176
177 PValue lookup_register(unsigned sel, unsigned swizzle, bool required);
178
179 size_t register_count() const {return m_next_register_index;}
180
181 PValue create_register(unsigned index, unsigned swizzle);
182
183 unsigned get_dst_ssa_register_index(const nir_ssa_def& ssa);
184
185 PValue literal(uint32_t value);
186
187 PValue get_temp_register(int channel = -1);
188
189 GPRVector get_temp_vec4();
190
191 private:
192
193 unsigned get_ssa_register_index(const nir_ssa_def& ssa) const;
194
195 unsigned get_local_register_index(const nir_register& reg);
196
197 unsigned get_local_register_index(const nir_register& reg) const;
198
199 void allocate_ssa_register(const nir_ssa_def& ssa);
200
201 void allocate_array(const nir_register& reg);
202
203
204 /** Allocate a register index with the given component mask.
205 * If one of the components is already been allocated the function
206 * will signal an error bz returning -1, otherwise a register index is
207 * returned.
208 */
209 int allocate_with_mask(unsigned index, unsigned mask, bool pre_alloc);
210
211 /** Allocate a register index with the given component.
212 * If the component is already been allocated the function
213 * will signal an error bz returning -1, otherwise a register index is
214 * returned.
215 */
216 int allocate_component(unsigned index, unsigned comp, bool pre_alloc);
217
218 /** search for a new register with the given index in the
219 * lookup map.
220 * \param sel register sel value
221 * \param swizzle register component, can also be 4,5, and 7
222 * \param required true: in debug mode assert when register doesn't exist
223 * false: return nullptr on failure
224 */
225
226 std::set<unsigned> m_ssa_undef;
227
228 LiteralBuffer m_literal_constants;
229
230 std::map<unsigned, unsigned> m_local_register_map;
231 std::map<unsigned, unsigned> m_ssa_register_map;
232
233 std::map<unsigned, PValue> m_uniforms;
234
235 std::map<unsigned, PValue> m_registers;
236
237 static PValue m_undef;
238
239 struct VRec {
240 unsigned index;
241 unsigned mask;
242 unsigned pre_alloc_mask;
243 };
244 std::map<unsigned, VRec> m_register_map;
245
246 unsigned m_next_register_index;
247
248 std::map<unsigned, PGPRArray> m_arrays_map;
249
250 std::map<uint32_t, PValue> m_literals;
251
252 int current_temp_reg_index;
253 int next_temp_reg_comp;
254 };
255
256 }
257
258 #endif // SFN_VALUEPOOL_H