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