3 * Copyright (c) 2018 Collabora LTD
5 * Author: Gert Wollny <gert.wollny@collabora.com>
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:
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
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.
28 #ifndef SFN_VALUEPOOL_H
29 #define SFN_VALUEPOOL_H
31 #include "sfn_value.h"
32 #include "sfn_value_gpr.h"
39 using LiteralBuffer
= std::map
<unsigned, const nir_load_const_instr
*>;
43 void insert(const PValue
& v
) {
44 auto idx
= index_from(v
->sel(), v
->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
)));
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();}
60 uint32_t index_from(uint32_t index
, uint32_t chan
) {
61 return (index
<< 3) + chan
;
63 std::map
<uint32_t, PValue
> m_map
;
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.
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
);
84 using array_list
= std::priority_queue
<array_entry
, std::vector
<array_entry
>,
90 GPRVector
vec_from_nir(const nir_dest
& dst
, int num_components
);
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
);
95 PValue
from_nir(const nir_src
& v
, unsigned component
, unsigned swizzled
);
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.
103 PValue
from_nir(const nir_alu_src
& v
, unsigned component
);
105 /** Get a register that is used as source register in an Texture instruction
106 * The PValue holds one componet as specified.
108 PValue
from_nir(const nir_tex_src
& v
, unsigned component
);
110 /** Allocate a register that is used as destination register in an ALU
111 * instruction. The PValue holds one componet as specified.
113 PValue
from_nir(const nir_alu_dest
& v
, unsigned component
);
115 /** Allocate a register that is used as destination register in any
116 * instruction. The PValue holds one componet as specified.
118 PValue
from_nir(const nir_dest
& v
, unsigned component
);
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
124 int lookup_register_index(const nir_src
& src
) const;
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
130 int lookup_register_index(const nir_dest
& dst
);
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
);
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
);
141 void allocate_arrays(array_list
& arrays
);
144 void increment_reserved_registers() {
145 ++m_next_register_index
;
148 void set_reserved_registers(unsigned rr
) {
149 m_next_register_index
=rr
;
152 /** Allocate a register that is is needed for lowering an instruction
153 * that requires complex calculations,
155 int allocate_temp_register();
157 /** Reserve a undef register, currently it uses (0,7),
158 * \todo should be eliminated in the final pass
160 bool create_undef(nir_ssa_undef_instr
* instr
);
162 bool set_literal_constant(nir_load_const_instr
* instr
);
164 const nir_load_const_instr
*get_literal_constant(int index
);
166 void add_uniform(unsigned index
, const PValue
&value
);
168 PValue
uniform(unsigned index
);
170 /** Create a new register with the given index and store it in the
173 PValue
create_register_from_nir_src(const nir_src
& sel
, int comp
);
175 ValueMap
get_temp_registers() const;
177 PValue
lookup_register(unsigned sel
, unsigned swizzle
, bool required
);
179 size_t register_count() const {return m_next_register_index
;}
181 PValue
create_register(unsigned index
, unsigned swizzle
);
183 unsigned get_dst_ssa_register_index(const nir_ssa_def
& ssa
);
185 PValue
literal(uint32_t value
);
187 PValue
get_temp_register(int channel
= -1);
189 GPRVector
get_temp_vec4();
193 unsigned get_ssa_register_index(const nir_ssa_def
& ssa
) const;
195 unsigned get_local_register_index(const nir_register
& reg
);
197 unsigned get_local_register_index(const nir_register
& reg
) const;
199 void allocate_ssa_register(const nir_ssa_def
& ssa
);
201 void allocate_array(const nir_register
& reg
);
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
209 int allocate_with_mask(unsigned index
, unsigned mask
, bool pre_alloc
);
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
216 int allocate_component(unsigned index
, unsigned comp
, bool pre_alloc
);
218 /** search for a new register with the given index in the
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
226 std::set
<unsigned> m_ssa_undef
;
228 LiteralBuffer m_literal_constants
;
230 std::map
<unsigned, unsigned> m_local_register_map
;
231 std::map
<unsigned, unsigned> m_ssa_register_map
;
233 std::map
<unsigned, PValue
> m_uniforms
;
235 std::map
<unsigned, PValue
> m_registers
;
237 static PValue m_undef
;
242 unsigned pre_alloc_mask
;
244 std::map
<unsigned, VRec
> m_register_map
;
246 unsigned m_next_register_index
;
248 std::map
<unsigned, PGPRArray
> m_arrays_map
;
250 std::map
<uint32_t, PValue
> m_literals
;
252 int current_temp_reg_index
;
253 int next_temp_reg_comp
;
258 #endif // SFN_VALUEPOOL_H