xref: /aosp_15_r20/external/mesa3d/src/imagination/rogue/rogue.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2022 Imagination Technologies Ltd.
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
5*61046927SAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to deal
6*61046927SAndroid Build Coastguard Worker  * in the Software without restriction, including without limitation the rights
7*61046927SAndroid Build Coastguard Worker  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8*61046927SAndroid Build Coastguard Worker  * copies of the Software, and to permit persons to whom the Software is
9*61046927SAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18*61046927SAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20*61046927SAndroid Build Coastguard Worker  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21*61046927SAndroid Build Coastguard Worker  * SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  */
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker #include "compiler/glsl_types.h"
25*61046927SAndroid Build Coastguard Worker #include "rogue.h"
26*61046927SAndroid Build Coastguard Worker #include "util/list.h"
27*61046927SAndroid Build Coastguard Worker #include "util/macros.h"
28*61046927SAndroid Build Coastguard Worker #include "util/ralloc.h"
29*61046927SAndroid Build Coastguard Worker #include "util/sparse_array.h"
30*61046927SAndroid Build Coastguard Worker 
31*61046927SAndroid Build Coastguard Worker #include <stdbool.h>
32*61046927SAndroid Build Coastguard Worker 
33*61046927SAndroid Build Coastguard Worker /**
34*61046927SAndroid Build Coastguard Worker  * \file rogue.c
35*61046927SAndroid Build Coastguard Worker  *
36*61046927SAndroid Build Coastguard Worker  * \brief Contains general Rogue IR functions.
37*61046927SAndroid Build Coastguard Worker  */
38*61046927SAndroid Build Coastguard Worker 
39*61046927SAndroid Build Coastguard Worker /* TODO: Tweak these? */
40*61046927SAndroid Build Coastguard Worker #define ROGUE_REG_CACHE_NODE_SIZE 512
41*61046927SAndroid Build Coastguard Worker #define ROGUE_REGARRAY_CACHE_NODE_SIZE 512
42*61046927SAndroid Build Coastguard Worker 
43*61046927SAndroid Build Coastguard Worker /**
44*61046927SAndroid Build Coastguard Worker  * \brief Sets an existing register to a (new) class and/or index.
45*61046927SAndroid Build Coastguard Worker  *
46*61046927SAndroid Build Coastguard Worker  * \param[in] shader The shader containing the register.
47*61046927SAndroid Build Coastguard Worker  * \param[in] reg The register being changed.
48*61046927SAndroid Build Coastguard Worker  * \param[in] class The new register class.
49*61046927SAndroid Build Coastguard Worker  * \param[in] index The new register index.
50*61046927SAndroid Build Coastguard Worker  * \return True if the register was updated, else false.
51*61046927SAndroid Build Coastguard Worker  */
52*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_reg_set(rogue_shader * shader,rogue_reg * reg,enum rogue_reg_class class,unsigned index)53*61046927SAndroid Build Coastguard Worker bool rogue_reg_set(rogue_shader *shader,
54*61046927SAndroid Build Coastguard Worker                    rogue_reg *reg,
55*61046927SAndroid Build Coastguard Worker                    enum rogue_reg_class class,
56*61046927SAndroid Build Coastguard Worker                    unsigned index)
57*61046927SAndroid Build Coastguard Worker {
58*61046927SAndroid Build Coastguard Worker    bool changed = true;
59*61046927SAndroid Build Coastguard Worker 
60*61046927SAndroid Build Coastguard Worker    if (reg->class == class && reg->index == index)
61*61046927SAndroid Build Coastguard Worker       changed = false;
62*61046927SAndroid Build Coastguard Worker 
63*61046927SAndroid Build Coastguard Worker    const rogue_reg_info *info = &rogue_reg_infos[class];
64*61046927SAndroid Build Coastguard Worker 
65*61046927SAndroid Build Coastguard Worker    if (info->num) {
66*61046927SAndroid Build Coastguard Worker       assert(index < info->num);
67*61046927SAndroid Build Coastguard Worker       rogue_set_reg_use(shader, class, index);
68*61046927SAndroid Build Coastguard Worker    }
69*61046927SAndroid Build Coastguard Worker 
70*61046927SAndroid Build Coastguard Worker    if (reg->class != class) {
71*61046927SAndroid Build Coastguard Worker       list_del(&reg->link);
72*61046927SAndroid Build Coastguard Worker       list_addtail(&reg->link, &shader->regs[class]);
73*61046927SAndroid Build Coastguard Worker    }
74*61046927SAndroid Build Coastguard Worker 
75*61046927SAndroid Build Coastguard Worker    reg->class = class;
76*61046927SAndroid Build Coastguard Worker    reg->index = index;
77*61046927SAndroid Build Coastguard Worker    reg->dirty = true;
78*61046927SAndroid Build Coastguard Worker 
79*61046927SAndroid Build Coastguard Worker    /* Clear the old cache entry. */
80*61046927SAndroid Build Coastguard Worker    if (reg->cached && *reg->cached == reg)
81*61046927SAndroid Build Coastguard Worker       *reg->cached = NULL;
82*61046927SAndroid Build Coastguard Worker 
83*61046927SAndroid Build Coastguard Worker    /* Set new cache entry. */
84*61046927SAndroid Build Coastguard Worker    rogue_reg **reg_cached =
85*61046927SAndroid Build Coastguard Worker       util_sparse_array_get(&shader->reg_cache[class], index);
86*61046927SAndroid Build Coastguard Worker    *reg_cached = reg;
87*61046927SAndroid Build Coastguard Worker    reg->cached = reg_cached;
88*61046927SAndroid Build Coastguard Worker 
89*61046927SAndroid Build Coastguard Worker    return changed;
90*61046927SAndroid Build Coastguard Worker }
91*61046927SAndroid Build Coastguard Worker 
92*61046927SAndroid Build Coastguard Worker /**
93*61046927SAndroid Build Coastguard Worker  * \brief Sets an existing register to a (new) class and/or index, and updates
94*61046927SAndroid Build Coastguard Worker  * its usage bitset.
95*61046927SAndroid Build Coastguard Worker  *
96*61046927SAndroid Build Coastguard Worker  * \param[in] shader The shader containing the register.
97*61046927SAndroid Build Coastguard Worker  * \param[in] reg The register being changed.
98*61046927SAndroid Build Coastguard Worker  * \param[in] class The new register class.
99*61046927SAndroid Build Coastguard Worker  * \param[in] index The new register index.
100*61046927SAndroid Build Coastguard Worker  * \return True if the register was updated, else false.
101*61046927SAndroid Build Coastguard Worker  */
102*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_reg_rewrite(rogue_shader * shader,rogue_reg * reg,enum rogue_reg_class class,unsigned index)103*61046927SAndroid Build Coastguard Worker bool rogue_reg_rewrite(rogue_shader *shader,
104*61046927SAndroid Build Coastguard Worker                        rogue_reg *reg,
105*61046927SAndroid Build Coastguard Worker                        enum rogue_reg_class class,
106*61046927SAndroid Build Coastguard Worker                        unsigned index)
107*61046927SAndroid Build Coastguard Worker {
108*61046927SAndroid Build Coastguard Worker    const rogue_reg_info *info = &rogue_reg_infos[reg->class];
109*61046927SAndroid Build Coastguard Worker    if (info->num) {
110*61046927SAndroid Build Coastguard Worker       assert(rogue_reg_is_used(shader, reg->class, reg->index) &&
111*61046927SAndroid Build Coastguard Worker              "Register not in use!");
112*61046927SAndroid Build Coastguard Worker       rogue_clear_reg_use(shader, reg->class, reg->index);
113*61046927SAndroid Build Coastguard Worker    }
114*61046927SAndroid Build Coastguard Worker 
115*61046927SAndroid Build Coastguard Worker    return rogue_reg_set(shader, reg, class, index);
116*61046927SAndroid Build Coastguard Worker }
117*61046927SAndroid Build Coastguard Worker 
118*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_regarray_set(rogue_shader * shader,rogue_regarray * regarray,enum rogue_reg_class class,unsigned base_index,bool set_regs)119*61046927SAndroid Build Coastguard Worker bool rogue_regarray_set(rogue_shader *shader,
120*61046927SAndroid Build Coastguard Worker                         rogue_regarray *regarray,
121*61046927SAndroid Build Coastguard Worker                         enum rogue_reg_class class,
122*61046927SAndroid Build Coastguard Worker                         unsigned base_index,
123*61046927SAndroid Build Coastguard Worker                         bool set_regs)
124*61046927SAndroid Build Coastguard Worker {
125*61046927SAndroid Build Coastguard Worker    bool updated = true;
126*61046927SAndroid Build Coastguard Worker 
127*61046927SAndroid Build Coastguard Worker    if (set_regs) {
128*61046927SAndroid Build Coastguard Worker       for (unsigned u = 0; u < regarray->size; ++u) {
129*61046927SAndroid Build Coastguard Worker          updated &=
130*61046927SAndroid Build Coastguard Worker             rogue_reg_set(shader, regarray->regs[u], class, base_index + u);
131*61046927SAndroid Build Coastguard Worker       }
132*61046927SAndroid Build Coastguard Worker    }
133*61046927SAndroid Build Coastguard Worker 
134*61046927SAndroid Build Coastguard Worker    if (regarray->cached && *regarray->cached == regarray)
135*61046927SAndroid Build Coastguard Worker       *regarray->cached = NULL;
136*61046927SAndroid Build Coastguard Worker 
137*61046927SAndroid Build Coastguard Worker    uint64_t key =
138*61046927SAndroid Build Coastguard Worker       rogue_regarray_cache_key(regarray->size, class, base_index, false, 0);
139*61046927SAndroid Build Coastguard Worker 
140*61046927SAndroid Build Coastguard Worker    rogue_regarray **regarray_cached =
141*61046927SAndroid Build Coastguard Worker       util_sparse_array_get(&shader->regarray_cache, key);
142*61046927SAndroid Build Coastguard Worker    assert(*regarray_cached == NULL);
143*61046927SAndroid Build Coastguard Worker 
144*61046927SAndroid Build Coastguard Worker    *regarray_cached = regarray;
145*61046927SAndroid Build Coastguard Worker    regarray->cached = regarray_cached;
146*61046927SAndroid Build Coastguard Worker 
147*61046927SAndroid Build Coastguard Worker    return updated;
148*61046927SAndroid Build Coastguard Worker }
149*61046927SAndroid Build Coastguard Worker 
rogue_regarray_rewrite(rogue_shader * shader,rogue_regarray * regarray,enum rogue_reg_class class,unsigned base_index)150*61046927SAndroid Build Coastguard Worker bool rogue_regarray_rewrite(rogue_shader *shader,
151*61046927SAndroid Build Coastguard Worker                             rogue_regarray *regarray,
152*61046927SAndroid Build Coastguard Worker                             enum rogue_reg_class class,
153*61046927SAndroid Build Coastguard Worker                             unsigned base_index)
154*61046927SAndroid Build Coastguard Worker {
155*61046927SAndroid Build Coastguard Worker    bool progress = true;
156*61046927SAndroid Build Coastguard Worker 
157*61046927SAndroid Build Coastguard Worker    enum rogue_reg_class orig_class = regarray->regs[0]->class;
158*61046927SAndroid Build Coastguard Worker    unsigned orig_base_index = regarray->regs[0]->index;
159*61046927SAndroid Build Coastguard Worker    const rogue_reg_info *info = &rogue_reg_infos[orig_class];
160*61046927SAndroid Build Coastguard Worker 
161*61046927SAndroid Build Coastguard Worker    assert(!regarray->parent);
162*61046927SAndroid Build Coastguard Worker 
163*61046927SAndroid Build Coastguard Worker    if (info->num) {
164*61046927SAndroid Build Coastguard Worker       for (unsigned u = 0; u < regarray->size; ++u) {
165*61046927SAndroid Build Coastguard Worker          assert(rogue_reg_is_used(shader, orig_class, orig_base_index) &&
166*61046927SAndroid Build Coastguard Worker                 "Register not in use!");
167*61046927SAndroid Build Coastguard Worker          rogue_clear_reg_use(shader, orig_class, orig_base_index);
168*61046927SAndroid Build Coastguard Worker       }
169*61046927SAndroid Build Coastguard Worker    }
170*61046927SAndroid Build Coastguard Worker 
171*61046927SAndroid Build Coastguard Worker    progress &= rogue_regarray_set(shader, regarray, class, base_index, true);
172*61046927SAndroid Build Coastguard Worker 
173*61046927SAndroid Build Coastguard Worker    rogue_foreach_subarray (subarray, regarray) {
174*61046927SAndroid Build Coastguard Worker       unsigned idx_offset = subarray->regs[0]->index - regarray->regs[0]->index;
175*61046927SAndroid Build Coastguard Worker       progress &= rogue_regarray_set(shader,
176*61046927SAndroid Build Coastguard Worker                                      subarray,
177*61046927SAndroid Build Coastguard Worker                                      class,
178*61046927SAndroid Build Coastguard Worker                                      base_index + idx_offset,
179*61046927SAndroid Build Coastguard Worker                                      false);
180*61046927SAndroid Build Coastguard Worker    }
181*61046927SAndroid Build Coastguard Worker 
182*61046927SAndroid Build Coastguard Worker    assert(progress);
183*61046927SAndroid Build Coastguard Worker    return progress;
184*61046927SAndroid Build Coastguard Worker }
185*61046927SAndroid Build Coastguard Worker 
rogue_shader_destructor(void * ptr)186*61046927SAndroid Build Coastguard Worker static void rogue_shader_destructor(void *ptr)
187*61046927SAndroid Build Coastguard Worker {
188*61046927SAndroid Build Coastguard Worker    rogue_shader *shader = ptr;
189*61046927SAndroid Build Coastguard Worker    for (unsigned u = 0; u < ARRAY_SIZE(shader->reg_cache); ++u)
190*61046927SAndroid Build Coastguard Worker       util_sparse_array_finish(&shader->reg_cache[u]);
191*61046927SAndroid Build Coastguard Worker 
192*61046927SAndroid Build Coastguard Worker    util_sparse_array_finish(&shader->regarray_cache);
193*61046927SAndroid Build Coastguard Worker }
194*61046927SAndroid Build Coastguard Worker 
195*61046927SAndroid Build Coastguard Worker /**
196*61046927SAndroid Build Coastguard Worker  * \brief Allocates and initializes a new rogue_shader object.
197*61046927SAndroid Build Coastguard Worker  *
198*61046927SAndroid Build Coastguard Worker  * \param[in] mem_ctx The new shader's memory context.
199*61046927SAndroid Build Coastguard Worker  * \param[in] stage The new shader's stage.
200*61046927SAndroid Build Coastguard Worker  * \return The new shader.
201*61046927SAndroid Build Coastguard Worker  */
202*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_shader_create(void * mem_ctx,gl_shader_stage stage)203*61046927SAndroid Build Coastguard Worker rogue_shader *rogue_shader_create(void *mem_ctx, gl_shader_stage stage)
204*61046927SAndroid Build Coastguard Worker {
205*61046927SAndroid Build Coastguard Worker    rogue_debug_init();
206*61046927SAndroid Build Coastguard Worker 
207*61046927SAndroid Build Coastguard Worker    rogue_shader *shader = rzalloc_size(mem_ctx, sizeof(*shader));
208*61046927SAndroid Build Coastguard Worker 
209*61046927SAndroid Build Coastguard Worker    shader->stage = stage;
210*61046927SAndroid Build Coastguard Worker 
211*61046927SAndroid Build Coastguard Worker    list_inithead(&shader->blocks);
212*61046927SAndroid Build Coastguard Worker 
213*61046927SAndroid Build Coastguard Worker    for (enum rogue_reg_class class = 0; class < ROGUE_REG_CLASS_COUNT;
214*61046927SAndroid Build Coastguard Worker         ++class) {
215*61046927SAndroid Build Coastguard Worker       list_inithead(&shader->regs[class]);
216*61046927SAndroid Build Coastguard Worker 
217*61046927SAndroid Build Coastguard Worker       const rogue_reg_info *info = &rogue_reg_infos[class];
218*61046927SAndroid Build Coastguard Worker       if (info->num) {
219*61046927SAndroid Build Coastguard Worker          unsigned bitset_size =
220*61046927SAndroid Build Coastguard Worker             sizeof(*shader->regs_used[class]) * BITSET_WORDS(info->num);
221*61046927SAndroid Build Coastguard Worker          shader->regs_used[class] = rzalloc_size(shader, bitset_size);
222*61046927SAndroid Build Coastguard Worker       }
223*61046927SAndroid Build Coastguard Worker    }
224*61046927SAndroid Build Coastguard Worker 
225*61046927SAndroid Build Coastguard Worker    for (unsigned u = 0; u < ARRAY_SIZE(shader->reg_cache); ++u)
226*61046927SAndroid Build Coastguard Worker       util_sparse_array_init(&shader->reg_cache[u],
227*61046927SAndroid Build Coastguard Worker                              sizeof(rogue_reg *),
228*61046927SAndroid Build Coastguard Worker                              ROGUE_REG_CACHE_NODE_SIZE);
229*61046927SAndroid Build Coastguard Worker 
230*61046927SAndroid Build Coastguard Worker    list_inithead(&shader->regarrays);
231*61046927SAndroid Build Coastguard Worker 
232*61046927SAndroid Build Coastguard Worker    util_sparse_array_init(&shader->regarray_cache,
233*61046927SAndroid Build Coastguard Worker                           sizeof(rogue_regarray *),
234*61046927SAndroid Build Coastguard Worker                           ROGUE_REGARRAY_CACHE_NODE_SIZE);
235*61046927SAndroid Build Coastguard Worker 
236*61046927SAndroid Build Coastguard Worker    for (unsigned u = 0; u < ARRAY_SIZE(shader->drc_trxns); ++u)
237*61046927SAndroid Build Coastguard Worker       list_inithead(&shader->drc_trxns[u]);
238*61046927SAndroid Build Coastguard Worker 
239*61046927SAndroid Build Coastguard Worker    list_inithead(&shader->imm_uses);
240*61046927SAndroid Build Coastguard Worker 
241*61046927SAndroid Build Coastguard Worker    ralloc_set_destructor(shader, rogue_shader_destructor);
242*61046927SAndroid Build Coastguard Worker 
243*61046927SAndroid Build Coastguard Worker    return shader;
244*61046927SAndroid Build Coastguard Worker }
245*61046927SAndroid Build Coastguard Worker 
246*61046927SAndroid Build Coastguard Worker /**
247*61046927SAndroid Build Coastguard Worker  * \brief Allocates and initializes a new rogue_reg object.
248*61046927SAndroid Build Coastguard Worker  *
249*61046927SAndroid Build Coastguard Worker  * \param[in] shader The shader which will contain the register.
250*61046927SAndroid Build Coastguard Worker  * \param[in] class The register class.
251*61046927SAndroid Build Coastguard Worker  * \param[in] index The register index.
252*61046927SAndroid Build Coastguard Worker  * \param[in] reg_cached The shader register cache.
253*61046927SAndroid Build Coastguard Worker  * \return The new register.
254*61046927SAndroid Build Coastguard Worker  */
rogue_reg_create(rogue_shader * shader,enum rogue_reg_class class,uint32_t index,rogue_reg ** reg_cached)255*61046927SAndroid Build Coastguard Worker static rogue_reg *rogue_reg_create(rogue_shader *shader,
256*61046927SAndroid Build Coastguard Worker                                    enum rogue_reg_class class,
257*61046927SAndroid Build Coastguard Worker                                    uint32_t index,
258*61046927SAndroid Build Coastguard Worker                                    rogue_reg **reg_cached)
259*61046927SAndroid Build Coastguard Worker {
260*61046927SAndroid Build Coastguard Worker    rogue_reg *reg = rzalloc_size(shader, sizeof(*reg));
261*61046927SAndroid Build Coastguard Worker 
262*61046927SAndroid Build Coastguard Worker    reg->shader = shader;
263*61046927SAndroid Build Coastguard Worker    reg->class = class;
264*61046927SAndroid Build Coastguard Worker    reg->index = index;
265*61046927SAndroid Build Coastguard Worker    reg->cached = reg_cached;
266*61046927SAndroid Build Coastguard Worker 
267*61046927SAndroid Build Coastguard Worker    list_addtail(&reg->link, &shader->regs[class]);
268*61046927SAndroid Build Coastguard Worker    list_inithead(&reg->writes);
269*61046927SAndroid Build Coastguard Worker    list_inithead(&reg->uses);
270*61046927SAndroid Build Coastguard Worker 
271*61046927SAndroid Build Coastguard Worker    const rogue_reg_info *info = &rogue_reg_infos[class];
272*61046927SAndroid Build Coastguard Worker    if (info->num) {
273*61046927SAndroid Build Coastguard Worker       assert(index < info->num);
274*61046927SAndroid Build Coastguard Worker       assert(!rogue_reg_is_used(shader, class, index) &&
275*61046927SAndroid Build Coastguard Worker              "Register already in use!");
276*61046927SAndroid Build Coastguard Worker       rogue_set_reg_use(shader, class, index);
277*61046927SAndroid Build Coastguard Worker    }
278*61046927SAndroid Build Coastguard Worker 
279*61046927SAndroid Build Coastguard Worker    return reg;
280*61046927SAndroid Build Coastguard Worker }
281*61046927SAndroid Build Coastguard Worker 
282*61046927SAndroid Build Coastguard Worker /**
283*61046927SAndroid Build Coastguard Worker  * \brief Deletes and frees a Rogue register.
284*61046927SAndroid Build Coastguard Worker  *
285*61046927SAndroid Build Coastguard Worker  * \param[in] reg The register to delete.
286*61046927SAndroid Build Coastguard Worker  */
287*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_reg_delete(rogue_reg * reg)288*61046927SAndroid Build Coastguard Worker void rogue_reg_delete(rogue_reg *reg)
289*61046927SAndroid Build Coastguard Worker {
290*61046927SAndroid Build Coastguard Worker    assert(rogue_reg_is_unused(reg));
291*61046927SAndroid Build Coastguard Worker    const rogue_reg_info *info = &rogue_reg_infos[reg->class];
292*61046927SAndroid Build Coastguard Worker    if (info->num) {
293*61046927SAndroid Build Coastguard Worker       assert(rogue_reg_is_used(reg->shader, reg->class, reg->index) &&
294*61046927SAndroid Build Coastguard Worker              "Register not in use!");
295*61046927SAndroid Build Coastguard Worker       rogue_clear_reg_use(reg->shader, reg->class, reg->index);
296*61046927SAndroid Build Coastguard Worker    }
297*61046927SAndroid Build Coastguard Worker 
298*61046927SAndroid Build Coastguard Worker    if (reg->cached && *reg->cached == reg)
299*61046927SAndroid Build Coastguard Worker       *reg->cached = NULL;
300*61046927SAndroid Build Coastguard Worker 
301*61046927SAndroid Build Coastguard Worker    list_del(&reg->link);
302*61046927SAndroid Build Coastguard Worker    ralloc_free(reg);
303*61046927SAndroid Build Coastguard Worker }
304*61046927SAndroid Build Coastguard Worker 
rogue_reg_cached_common(rogue_shader * shader,enum rogue_reg_class class,uint32_t index,uint8_t component,bool vec)305*61046927SAndroid Build Coastguard Worker static inline rogue_reg *rogue_reg_cached_common(rogue_shader *shader,
306*61046927SAndroid Build Coastguard Worker                                                  enum rogue_reg_class class,
307*61046927SAndroid Build Coastguard Worker                                                  uint32_t index,
308*61046927SAndroid Build Coastguard Worker                                                  uint8_t component,
309*61046927SAndroid Build Coastguard Worker                                                  bool vec)
310*61046927SAndroid Build Coastguard Worker {
311*61046927SAndroid Build Coastguard Worker    uint32_t key = rogue_reg_cache_key(index, vec, component);
312*61046927SAndroid Build Coastguard Worker 
313*61046927SAndroid Build Coastguard Worker    rogue_reg **reg_cached =
314*61046927SAndroid Build Coastguard Worker       util_sparse_array_get(&shader->reg_cache[class], key);
315*61046927SAndroid Build Coastguard Worker    if (!*reg_cached)
316*61046927SAndroid Build Coastguard Worker       *reg_cached = rogue_reg_create(shader, class, key, reg_cached);
317*61046927SAndroid Build Coastguard Worker 
318*61046927SAndroid Build Coastguard Worker    return *reg_cached;
319*61046927SAndroid Build Coastguard Worker }
320*61046927SAndroid Build Coastguard Worker 
rogue_reg_cached(rogue_shader * shader,enum rogue_reg_class class,uint32_t index)321*61046927SAndroid Build Coastguard Worker static inline rogue_reg *rogue_reg_cached(rogue_shader *shader,
322*61046927SAndroid Build Coastguard Worker                                           enum rogue_reg_class class,
323*61046927SAndroid Build Coastguard Worker                                           uint32_t index)
324*61046927SAndroid Build Coastguard Worker {
325*61046927SAndroid Build Coastguard Worker    return rogue_reg_cached_common(shader, class, index, 0, false);
326*61046927SAndroid Build Coastguard Worker }
327*61046927SAndroid Build Coastguard Worker 
rogue_vec_reg_cached(rogue_shader * shader,enum rogue_reg_class class,unsigned index,unsigned component)328*61046927SAndroid Build Coastguard Worker static inline rogue_reg *rogue_vec_reg_cached(rogue_shader *shader,
329*61046927SAndroid Build Coastguard Worker                                               enum rogue_reg_class class,
330*61046927SAndroid Build Coastguard Worker                                               unsigned index,
331*61046927SAndroid Build Coastguard Worker                                               unsigned component)
332*61046927SAndroid Build Coastguard Worker {
333*61046927SAndroid Build Coastguard Worker    return rogue_reg_cached_common(shader, class, index, component, true);
334*61046927SAndroid Build Coastguard Worker }
335*61046927SAndroid Build Coastguard Worker 
336*61046927SAndroid Build Coastguard Worker /* TODO: Static inline in rogue.h? */
337*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_ssa_reg(rogue_shader * shader,unsigned index)338*61046927SAndroid Build Coastguard Worker rogue_reg *rogue_ssa_reg(rogue_shader *shader, unsigned index)
339*61046927SAndroid Build Coastguard Worker {
340*61046927SAndroid Build Coastguard Worker    return rogue_reg_cached(shader, ROGUE_REG_CLASS_SSA, index);
341*61046927SAndroid Build Coastguard Worker }
342*61046927SAndroid Build Coastguard Worker 
343*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_temp_reg(rogue_shader * shader,unsigned index)344*61046927SAndroid Build Coastguard Worker rogue_reg *rogue_temp_reg(rogue_shader *shader, unsigned index)
345*61046927SAndroid Build Coastguard Worker {
346*61046927SAndroid Build Coastguard Worker    return rogue_reg_cached(shader, ROGUE_REG_CLASS_TEMP, index);
347*61046927SAndroid Build Coastguard Worker }
348*61046927SAndroid Build Coastguard Worker 
349*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_coeff_reg(rogue_shader * shader,unsigned index)350*61046927SAndroid Build Coastguard Worker rogue_reg *rogue_coeff_reg(rogue_shader *shader, unsigned index)
351*61046927SAndroid Build Coastguard Worker {
352*61046927SAndroid Build Coastguard Worker    return rogue_reg_cached(shader, ROGUE_REG_CLASS_COEFF, index);
353*61046927SAndroid Build Coastguard Worker }
354*61046927SAndroid Build Coastguard Worker 
355*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_shared_reg(rogue_shader * shader,unsigned index)356*61046927SAndroid Build Coastguard Worker rogue_reg *rogue_shared_reg(rogue_shader *shader, unsigned index)
357*61046927SAndroid Build Coastguard Worker {
358*61046927SAndroid Build Coastguard Worker    return rogue_reg_cached(shader, ROGUE_REG_CLASS_SHARED, index);
359*61046927SAndroid Build Coastguard Worker }
360*61046927SAndroid Build Coastguard Worker 
361*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_const_reg(rogue_shader * shader,unsigned index)362*61046927SAndroid Build Coastguard Worker rogue_reg *rogue_const_reg(rogue_shader *shader, unsigned index)
363*61046927SAndroid Build Coastguard Worker {
364*61046927SAndroid Build Coastguard Worker    return rogue_reg_cached(shader, ROGUE_REG_CLASS_CONST, index);
365*61046927SAndroid Build Coastguard Worker }
366*61046927SAndroid Build Coastguard Worker 
367*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_pixout_reg(rogue_shader * shader,unsigned index)368*61046927SAndroid Build Coastguard Worker rogue_reg *rogue_pixout_reg(rogue_shader *shader, unsigned index)
369*61046927SAndroid Build Coastguard Worker {
370*61046927SAndroid Build Coastguard Worker    return rogue_reg_cached(shader, ROGUE_REG_CLASS_PIXOUT, index);
371*61046927SAndroid Build Coastguard Worker }
372*61046927SAndroid Build Coastguard Worker 
373*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_special_reg(rogue_shader * shader,unsigned index)374*61046927SAndroid Build Coastguard Worker rogue_reg *rogue_special_reg(rogue_shader *shader, unsigned index)
375*61046927SAndroid Build Coastguard Worker {
376*61046927SAndroid Build Coastguard Worker    return rogue_reg_cached(shader, ROGUE_REG_CLASS_SPECIAL, index);
377*61046927SAndroid Build Coastguard Worker }
378*61046927SAndroid Build Coastguard Worker 
379*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_vtxin_reg(rogue_shader * shader,unsigned index)380*61046927SAndroid Build Coastguard Worker rogue_reg *rogue_vtxin_reg(rogue_shader *shader, unsigned index)
381*61046927SAndroid Build Coastguard Worker {
382*61046927SAndroid Build Coastguard Worker    return rogue_reg_cached(shader, ROGUE_REG_CLASS_VTXIN, index);
383*61046927SAndroid Build Coastguard Worker }
384*61046927SAndroid Build Coastguard Worker 
385*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_vtxout_reg(rogue_shader * shader,unsigned index)386*61046927SAndroid Build Coastguard Worker rogue_reg *rogue_vtxout_reg(rogue_shader *shader, unsigned index)
387*61046927SAndroid Build Coastguard Worker {
388*61046927SAndroid Build Coastguard Worker    return rogue_reg_cached(shader, ROGUE_REG_CLASS_VTXOUT, index);
389*61046927SAndroid Build Coastguard Worker }
390*61046927SAndroid Build Coastguard Worker 
391*61046927SAndroid Build Coastguard Worker PUBLIC
392*61046927SAndroid Build Coastguard Worker rogue_reg *
rogue_ssa_vec_reg(rogue_shader * shader,unsigned index,unsigned component)393*61046927SAndroid Build Coastguard Worker rogue_ssa_vec_reg(rogue_shader *shader, unsigned index, unsigned component)
394*61046927SAndroid Build Coastguard Worker {
395*61046927SAndroid Build Coastguard Worker    return rogue_vec_reg_cached(shader, ROGUE_REG_CLASS_SSA, index, component);
396*61046927SAndroid Build Coastguard Worker }
397*61046927SAndroid Build Coastguard Worker 
rogue_find_common_regarray(rogue_regarray * regarray,bool * is_parent,rogue_reg *** parent_regptr)398*61046927SAndroid Build Coastguard Worker static rogue_regarray *rogue_find_common_regarray(rogue_regarray *regarray,
399*61046927SAndroid Build Coastguard Worker                                                   bool *is_parent,
400*61046927SAndroid Build Coastguard Worker                                                   rogue_reg ***parent_regptr)
401*61046927SAndroid Build Coastguard Worker {
402*61046927SAndroid Build Coastguard Worker    rogue_regarray *common_regarray = NULL;
403*61046927SAndroid Build Coastguard Worker 
404*61046927SAndroid Build Coastguard Worker    for (unsigned u = 0; u < regarray->size; ++u) {
405*61046927SAndroid Build Coastguard Worker       if (regarray->regs[u]->regarray) {
406*61046927SAndroid Build Coastguard Worker          if (common_regarray && regarray->regs[u]->regarray != common_regarray)
407*61046927SAndroid Build Coastguard Worker             unreachable("Can't have overlapping regarrays.");
408*61046927SAndroid Build Coastguard Worker          else if (!common_regarray)
409*61046927SAndroid Build Coastguard Worker             common_regarray = regarray->regs[u]->regarray;
410*61046927SAndroid Build Coastguard Worker       }
411*61046927SAndroid Build Coastguard Worker    }
412*61046927SAndroid Build Coastguard Worker 
413*61046927SAndroid Build Coastguard Worker    if (common_regarray) {
414*61046927SAndroid Build Coastguard Worker       unsigned min_index = regarray->regs[0]->index;
415*61046927SAndroid Build Coastguard Worker       unsigned max_index = min_index + regarray->size - 1;
416*61046927SAndroid Build Coastguard Worker 
417*61046927SAndroid Build Coastguard Worker       unsigned min_common_index = common_regarray->regs[0]->index;
418*61046927SAndroid Build Coastguard Worker       unsigned max_common_index = min_common_index + common_regarray->size - 1;
419*61046927SAndroid Build Coastguard Worker 
420*61046927SAndroid Build Coastguard Worker       /* TODO: Create a new parent array that encapsulates both ranges? */
421*61046927SAndroid Build Coastguard Worker       /* Ensure that the new regarray doesn't occupy only part of its parent,
422*61046927SAndroid Build Coastguard Worker        * and also registers *beyond* its parent. */
423*61046927SAndroid Build Coastguard Worker       if ((min_index > min_common_index && max_index > max_common_index) ||
424*61046927SAndroid Build Coastguard Worker           (min_index < min_common_index && max_index < max_common_index))
425*61046927SAndroid Build Coastguard Worker          unreachable("Can't have overflowing partial regarrays.");
426*61046927SAndroid Build Coastguard Worker 
427*61046927SAndroid Build Coastguard Worker       *is_parent = regarray->size > common_regarray->size;
428*61046927SAndroid Build Coastguard Worker       const rogue_regarray *parent_regarray = *is_parent ? regarray
429*61046927SAndroid Build Coastguard Worker                                                          : common_regarray;
430*61046927SAndroid Build Coastguard Worker       const rogue_regarray *child_regarray = *is_parent ? common_regarray
431*61046927SAndroid Build Coastguard Worker                                                         : regarray;
432*61046927SAndroid Build Coastguard Worker 
433*61046927SAndroid Build Coastguard Worker       for (unsigned u = 0; u < parent_regarray->size; ++u) {
434*61046927SAndroid Build Coastguard Worker          if (child_regarray->regs[0]->index ==
435*61046927SAndroid Build Coastguard Worker              parent_regarray->regs[u]->index) {
436*61046927SAndroid Build Coastguard Worker             *parent_regptr = &parent_regarray->regs[u];
437*61046927SAndroid Build Coastguard Worker             break;
438*61046927SAndroid Build Coastguard Worker          }
439*61046927SAndroid Build Coastguard Worker       }
440*61046927SAndroid Build Coastguard Worker    }
441*61046927SAndroid Build Coastguard Worker 
442*61046927SAndroid Build Coastguard Worker    return common_regarray;
443*61046927SAndroid Build Coastguard Worker }
444*61046927SAndroid Build Coastguard Worker 
rogue_regarray_create(rogue_shader * shader,unsigned size,enum rogue_reg_class class,unsigned start_index,uint8_t component,bool vec,rogue_regarray ** regarray_cached)445*61046927SAndroid Build Coastguard Worker static rogue_regarray *rogue_regarray_create(rogue_shader *shader,
446*61046927SAndroid Build Coastguard Worker                                              unsigned size,
447*61046927SAndroid Build Coastguard Worker                                              enum rogue_reg_class class,
448*61046927SAndroid Build Coastguard Worker                                              unsigned start_index,
449*61046927SAndroid Build Coastguard Worker                                              uint8_t component,
450*61046927SAndroid Build Coastguard Worker                                              bool vec,
451*61046927SAndroid Build Coastguard Worker                                              rogue_regarray **regarray_cached)
452*61046927SAndroid Build Coastguard Worker {
453*61046927SAndroid Build Coastguard Worker    rogue_regarray *regarray = rzalloc_size(shader, sizeof(*regarray));
454*61046927SAndroid Build Coastguard Worker    regarray->regs = rzalloc_size(regarray, sizeof(*regarray->regs) * size);
455*61046927SAndroid Build Coastguard Worker    regarray->size = size;
456*61046927SAndroid Build Coastguard Worker    regarray->cached = regarray_cached;
457*61046927SAndroid Build Coastguard Worker    list_inithead(&regarray->children);
458*61046927SAndroid Build Coastguard Worker    list_inithead(&regarray->writes);
459*61046927SAndroid Build Coastguard Worker    list_inithead(&regarray->uses);
460*61046927SAndroid Build Coastguard Worker 
461*61046927SAndroid Build Coastguard Worker    for (unsigned u = 0; u < size; ++u) {
462*61046927SAndroid Build Coastguard Worker       regarray->regs[u] =
463*61046927SAndroid Build Coastguard Worker          vec ? rogue_vec_reg_cached(shader, class, start_index, component + u)
464*61046927SAndroid Build Coastguard Worker              : rogue_reg_cached(shader, class, start_index + u);
465*61046927SAndroid Build Coastguard Worker    }
466*61046927SAndroid Build Coastguard Worker 
467*61046927SAndroid Build Coastguard Worker    bool is_parent = false;
468*61046927SAndroid Build Coastguard Worker    rogue_reg **parent_regptr = NULL;
469*61046927SAndroid Build Coastguard Worker    rogue_regarray *common_regarray =
470*61046927SAndroid Build Coastguard Worker       rogue_find_common_regarray(regarray, &is_parent, &parent_regptr);
471*61046927SAndroid Build Coastguard Worker 
472*61046927SAndroid Build Coastguard Worker    if (!common_regarray) {
473*61046927SAndroid Build Coastguard Worker       /* We don't share any registers with another regarray. */
474*61046927SAndroid Build Coastguard Worker       for (unsigned u = 0; u < size; ++u)
475*61046927SAndroid Build Coastguard Worker          regarray->regs[u]->regarray = regarray;
476*61046927SAndroid Build Coastguard Worker    } else {
477*61046927SAndroid Build Coastguard Worker       if (is_parent) {
478*61046927SAndroid Build Coastguard Worker          /* We share registers with another regarray, and it is a subset of us.
479*61046927SAndroid Build Coastguard Worker           */
480*61046927SAndroid Build Coastguard Worker          for (unsigned u = 0; u < common_regarray->size; ++u)
481*61046927SAndroid Build Coastguard Worker             common_regarray->regs[u]->regarray = regarray;
482*61046927SAndroid Build Coastguard Worker 
483*61046927SAndroid Build Coastguard Worker          /* Steal its children. */
484*61046927SAndroid Build Coastguard Worker          rogue_foreach_subarray_safe (subarray, common_regarray) {
485*61046927SAndroid Build Coastguard Worker             unsigned parent_index = common_regarray->regs[0]->index;
486*61046927SAndroid Build Coastguard Worker             unsigned child_index = subarray->regs[0]->index;
487*61046927SAndroid Build Coastguard Worker             assert(child_index >= parent_index);
488*61046927SAndroid Build Coastguard Worker 
489*61046927SAndroid Build Coastguard Worker             subarray->parent = regarray;
490*61046927SAndroid Build Coastguard Worker             subarray->regs = &parent_regptr[child_index - parent_index];
491*61046927SAndroid Build Coastguard Worker 
492*61046927SAndroid Build Coastguard Worker             list_del(&subarray->child_link);
493*61046927SAndroid Build Coastguard Worker             list_addtail(&subarray->child_link, &regarray->children);
494*61046927SAndroid Build Coastguard Worker          }
495*61046927SAndroid Build Coastguard Worker 
496*61046927SAndroid Build Coastguard Worker          common_regarray->parent = regarray;
497*61046927SAndroid Build Coastguard Worker          ralloc_free(common_regarray->regs);
498*61046927SAndroid Build Coastguard Worker          common_regarray->regs = parent_regptr;
499*61046927SAndroid Build Coastguard Worker          list_addtail(&common_regarray->child_link, &regarray->children);
500*61046927SAndroid Build Coastguard Worker       } else {
501*61046927SAndroid Build Coastguard Worker          /* We share registers with another regarray, and we are a subset of it.
502*61046927SAndroid Build Coastguard Worker           */
503*61046927SAndroid Build Coastguard Worker          regarray->parent = common_regarray;
504*61046927SAndroid Build Coastguard Worker          ralloc_free(regarray->regs);
505*61046927SAndroid Build Coastguard Worker          regarray->regs = parent_regptr;
506*61046927SAndroid Build Coastguard Worker          assert(list_is_empty(&regarray->children));
507*61046927SAndroid Build Coastguard Worker          list_addtail(&regarray->child_link, &common_regarray->children);
508*61046927SAndroid Build Coastguard Worker       }
509*61046927SAndroid Build Coastguard Worker    }
510*61046927SAndroid Build Coastguard Worker 
511*61046927SAndroid Build Coastguard Worker    list_addtail(&regarray->link, &shader->regarrays);
512*61046927SAndroid Build Coastguard Worker 
513*61046927SAndroid Build Coastguard Worker    return regarray;
514*61046927SAndroid Build Coastguard Worker }
515*61046927SAndroid Build Coastguard Worker 
516*61046927SAndroid Build Coastguard Worker static inline rogue_regarray *
rogue_regarray_cached_common(rogue_shader * shader,unsigned size,enum rogue_reg_class class,uint32_t start_index,uint8_t component,bool vec)517*61046927SAndroid Build Coastguard Worker rogue_regarray_cached_common(rogue_shader *shader,
518*61046927SAndroid Build Coastguard Worker                              unsigned size,
519*61046927SAndroid Build Coastguard Worker                              enum rogue_reg_class class,
520*61046927SAndroid Build Coastguard Worker                              uint32_t start_index,
521*61046927SAndroid Build Coastguard Worker                              uint8_t component,
522*61046927SAndroid Build Coastguard Worker                              bool vec)
523*61046927SAndroid Build Coastguard Worker {
524*61046927SAndroid Build Coastguard Worker    uint64_t key =
525*61046927SAndroid Build Coastguard Worker       rogue_regarray_cache_key(size, class, start_index, vec, component);
526*61046927SAndroid Build Coastguard Worker 
527*61046927SAndroid Build Coastguard Worker    rogue_regarray **regarray_cached =
528*61046927SAndroid Build Coastguard Worker       util_sparse_array_get(&shader->regarray_cache, key);
529*61046927SAndroid Build Coastguard Worker    if (!*regarray_cached)
530*61046927SAndroid Build Coastguard Worker       *regarray_cached = rogue_regarray_create(shader,
531*61046927SAndroid Build Coastguard Worker                                                size,
532*61046927SAndroid Build Coastguard Worker                                                class,
533*61046927SAndroid Build Coastguard Worker                                                start_index,
534*61046927SAndroid Build Coastguard Worker                                                component,
535*61046927SAndroid Build Coastguard Worker                                                vec,
536*61046927SAndroid Build Coastguard Worker                                                regarray_cached);
537*61046927SAndroid Build Coastguard Worker 
538*61046927SAndroid Build Coastguard Worker    return *regarray_cached;
539*61046927SAndroid Build Coastguard Worker }
540*61046927SAndroid Build Coastguard Worker 
541*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_regarray_cached(rogue_shader * shader,unsigned size,enum rogue_reg_class class,uint32_t start_index)542*61046927SAndroid Build Coastguard Worker rogue_regarray *rogue_regarray_cached(rogue_shader *shader,
543*61046927SAndroid Build Coastguard Worker                                       unsigned size,
544*61046927SAndroid Build Coastguard Worker                                       enum rogue_reg_class class,
545*61046927SAndroid Build Coastguard Worker                                       uint32_t start_index)
546*61046927SAndroid Build Coastguard Worker {
547*61046927SAndroid Build Coastguard Worker    return rogue_regarray_cached_common(shader,
548*61046927SAndroid Build Coastguard Worker                                        size,
549*61046927SAndroid Build Coastguard Worker                                        class,
550*61046927SAndroid Build Coastguard Worker                                        start_index,
551*61046927SAndroid Build Coastguard Worker                                        0,
552*61046927SAndroid Build Coastguard Worker                                        false);
553*61046927SAndroid Build Coastguard Worker }
554*61046927SAndroid Build Coastguard Worker 
555*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_vec_regarray_cached(rogue_shader * shader,unsigned size,enum rogue_reg_class class,uint32_t start_index,uint8_t component)556*61046927SAndroid Build Coastguard Worker rogue_regarray *rogue_vec_regarray_cached(rogue_shader *shader,
557*61046927SAndroid Build Coastguard Worker                                           unsigned size,
558*61046927SAndroid Build Coastguard Worker                                           enum rogue_reg_class class,
559*61046927SAndroid Build Coastguard Worker                                           uint32_t start_index,
560*61046927SAndroid Build Coastguard Worker                                           uint8_t component)
561*61046927SAndroid Build Coastguard Worker {
562*61046927SAndroid Build Coastguard Worker    return rogue_regarray_cached_common(shader,
563*61046927SAndroid Build Coastguard Worker                                        size,
564*61046927SAndroid Build Coastguard Worker                                        class,
565*61046927SAndroid Build Coastguard Worker                                        start_index,
566*61046927SAndroid Build Coastguard Worker                                        component,
567*61046927SAndroid Build Coastguard Worker                                        true);
568*61046927SAndroid Build Coastguard Worker }
569*61046927SAndroid Build Coastguard Worker 
570*61046927SAndroid Build Coastguard Worker PUBLIC
571*61046927SAndroid Build Coastguard Worker rogue_regarray *
rogue_ssa_regarray(rogue_shader * shader,unsigned size,unsigned start_index)572*61046927SAndroid Build Coastguard Worker rogue_ssa_regarray(rogue_shader *shader, unsigned size, unsigned start_index)
573*61046927SAndroid Build Coastguard Worker {
574*61046927SAndroid Build Coastguard Worker    return rogue_regarray_cached(shader, size, ROGUE_REG_CLASS_SSA, start_index);
575*61046927SAndroid Build Coastguard Worker }
576*61046927SAndroid Build Coastguard Worker 
577*61046927SAndroid Build Coastguard Worker PUBLIC
578*61046927SAndroid Build Coastguard Worker rogue_regarray *
rogue_temp_regarray(rogue_shader * shader,unsigned size,unsigned start_index)579*61046927SAndroid Build Coastguard Worker rogue_temp_regarray(rogue_shader *shader, unsigned size, unsigned start_index)
580*61046927SAndroid Build Coastguard Worker {
581*61046927SAndroid Build Coastguard Worker    return rogue_regarray_cached(shader, size, ROGUE_REG_CLASS_TEMP, start_index);
582*61046927SAndroid Build Coastguard Worker }
583*61046927SAndroid Build Coastguard Worker 
584*61046927SAndroid Build Coastguard Worker PUBLIC
585*61046927SAndroid Build Coastguard Worker rogue_regarray *
rogue_coeff_regarray(rogue_shader * shader,unsigned size,unsigned start_index)586*61046927SAndroid Build Coastguard Worker rogue_coeff_regarray(rogue_shader *shader, unsigned size, unsigned start_index)
587*61046927SAndroid Build Coastguard Worker {
588*61046927SAndroid Build Coastguard Worker    return rogue_regarray_cached(shader,
589*61046927SAndroid Build Coastguard Worker                                 size,
590*61046927SAndroid Build Coastguard Worker                                 ROGUE_REG_CLASS_COEFF,
591*61046927SAndroid Build Coastguard Worker                                 start_index);
592*61046927SAndroid Build Coastguard Worker }
593*61046927SAndroid Build Coastguard Worker 
594*61046927SAndroid Build Coastguard Worker PUBLIC
595*61046927SAndroid Build Coastguard Worker rogue_regarray *
rogue_shared_regarray(rogue_shader * shader,unsigned size,unsigned start_index)596*61046927SAndroid Build Coastguard Worker rogue_shared_regarray(rogue_shader *shader, unsigned size, unsigned start_index)
597*61046927SAndroid Build Coastguard Worker {
598*61046927SAndroid Build Coastguard Worker    return rogue_regarray_cached(shader,
599*61046927SAndroid Build Coastguard Worker                                 size,
600*61046927SAndroid Build Coastguard Worker                                 ROGUE_REG_CLASS_SHARED,
601*61046927SAndroid Build Coastguard Worker                                 start_index);
602*61046927SAndroid Build Coastguard Worker }
603*61046927SAndroid Build Coastguard Worker 
604*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_ssa_vec_regarray(rogue_shader * shader,unsigned size,unsigned start_index,unsigned component)605*61046927SAndroid Build Coastguard Worker rogue_regarray *rogue_ssa_vec_regarray(rogue_shader *shader,
606*61046927SAndroid Build Coastguard Worker                                        unsigned size,
607*61046927SAndroid Build Coastguard Worker                                        unsigned start_index,
608*61046927SAndroid Build Coastguard Worker                                        unsigned component)
609*61046927SAndroid Build Coastguard Worker {
610*61046927SAndroid Build Coastguard Worker    return rogue_vec_regarray_cached(shader,
611*61046927SAndroid Build Coastguard Worker                                     size,
612*61046927SAndroid Build Coastguard Worker                                     ROGUE_REG_CLASS_SSA,
613*61046927SAndroid Build Coastguard Worker                                     start_index,
614*61046927SAndroid Build Coastguard Worker                                     component);
615*61046927SAndroid Build Coastguard Worker }
616*61046927SAndroid Build Coastguard Worker 
617*61046927SAndroid Build Coastguard Worker /**
618*61046927SAndroid Build Coastguard Worker  * \brief Allocates and initializes a new rogue_block object.
619*61046927SAndroid Build Coastguard Worker  *
620*61046927SAndroid Build Coastguard Worker  * \param[in] shader The shader that the new block belongs to.
621*61046927SAndroid Build Coastguard Worker  * \param[in] label The (optional) block label.
622*61046927SAndroid Build Coastguard Worker  * \return The new block.
623*61046927SAndroid Build Coastguard Worker  */
624*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_block_create(rogue_shader * shader,const char * label)625*61046927SAndroid Build Coastguard Worker rogue_block *rogue_block_create(rogue_shader *shader, const char *label)
626*61046927SAndroid Build Coastguard Worker {
627*61046927SAndroid Build Coastguard Worker    rogue_block *block = rzalloc_size(shader, sizeof(*block));
628*61046927SAndroid Build Coastguard Worker 
629*61046927SAndroid Build Coastguard Worker    block->shader = shader;
630*61046927SAndroid Build Coastguard Worker    list_inithead(&block->instrs);
631*61046927SAndroid Build Coastguard Worker    list_inithead(&block->uses);
632*61046927SAndroid Build Coastguard Worker    block->index = shader->next_block++;
633*61046927SAndroid Build Coastguard Worker    block->label = ralloc_strdup(block, label);
634*61046927SAndroid Build Coastguard Worker 
635*61046927SAndroid Build Coastguard Worker    return block;
636*61046927SAndroid Build Coastguard Worker }
637*61046927SAndroid Build Coastguard Worker 
638*61046927SAndroid Build Coastguard Worker /**
639*61046927SAndroid Build Coastguard Worker  * \brief Initialises a Rogue instruction.
640*61046927SAndroid Build Coastguard Worker  *
641*61046927SAndroid Build Coastguard Worker  * \param[in] instr The instruction to initialise.
642*61046927SAndroid Build Coastguard Worker  * \param[in] type The instruction type.
643*61046927SAndroid Build Coastguard Worker  * \param[in] block The block which will contain the instruction.
644*61046927SAndroid Build Coastguard Worker  */
rogue_instr_init(rogue_instr * instr,enum rogue_instr_type type,rogue_block * block)645*61046927SAndroid Build Coastguard Worker static inline void rogue_instr_init(rogue_instr *instr,
646*61046927SAndroid Build Coastguard Worker                                     enum rogue_instr_type type,
647*61046927SAndroid Build Coastguard Worker                                     rogue_block *block)
648*61046927SAndroid Build Coastguard Worker {
649*61046927SAndroid Build Coastguard Worker    instr->type = type;
650*61046927SAndroid Build Coastguard Worker    instr->exec_cond = ROGUE_EXEC_COND_PE_TRUE;
651*61046927SAndroid Build Coastguard Worker    instr->repeat = 1;
652*61046927SAndroid Build Coastguard Worker    instr->index = block->shader->next_instr++;
653*61046927SAndroid Build Coastguard Worker    instr->block = block;
654*61046927SAndroid Build Coastguard Worker }
655*61046927SAndroid Build Coastguard Worker 
656*61046927SAndroid Build Coastguard Worker /**
657*61046927SAndroid Build Coastguard Worker  * \brief Allocates and initializes a new rogue_alu_instr object.
658*61046927SAndroid Build Coastguard Worker  *
659*61046927SAndroid Build Coastguard Worker  * \param[in] block The block that the new ALU instruction belongs to.
660*61046927SAndroid Build Coastguard Worker  * \param[in] op The ALU operation.
661*61046927SAndroid Build Coastguard Worker  * \return The new ALU instruction.
662*61046927SAndroid Build Coastguard Worker  */
663*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_alu_instr_create(rogue_block * block,enum rogue_alu_op op)664*61046927SAndroid Build Coastguard Worker rogue_alu_instr *rogue_alu_instr_create(rogue_block *block,
665*61046927SAndroid Build Coastguard Worker                                         enum rogue_alu_op op)
666*61046927SAndroid Build Coastguard Worker {
667*61046927SAndroid Build Coastguard Worker    rogue_alu_instr *alu = rzalloc_size(block, sizeof(*alu));
668*61046927SAndroid Build Coastguard Worker    rogue_instr_init(&alu->instr, ROGUE_INSTR_TYPE_ALU, block);
669*61046927SAndroid Build Coastguard Worker    alu->op = op;
670*61046927SAndroid Build Coastguard Worker 
671*61046927SAndroid Build Coastguard Worker    return alu;
672*61046927SAndroid Build Coastguard Worker }
673*61046927SAndroid Build Coastguard Worker 
674*61046927SAndroid Build Coastguard Worker /**
675*61046927SAndroid Build Coastguard Worker  * \brief Allocates and initializes a new rogue_backend_instr object.
676*61046927SAndroid Build Coastguard Worker  *
677*61046927SAndroid Build Coastguard Worker  * \param[in] block The block that the new backend instruction belongs to.
678*61046927SAndroid Build Coastguard Worker  * \param[in] op The backend operation.
679*61046927SAndroid Build Coastguard Worker  * \return The new backend instruction.
680*61046927SAndroid Build Coastguard Worker  */
681*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_backend_instr_create(rogue_block * block,enum rogue_backend_op op)682*61046927SAndroid Build Coastguard Worker rogue_backend_instr *rogue_backend_instr_create(rogue_block *block,
683*61046927SAndroid Build Coastguard Worker                                                 enum rogue_backend_op op)
684*61046927SAndroid Build Coastguard Worker {
685*61046927SAndroid Build Coastguard Worker    rogue_backend_instr *backend = rzalloc_size(block, sizeof(*backend));
686*61046927SAndroid Build Coastguard Worker    rogue_instr_init(&backend->instr, ROGUE_INSTR_TYPE_BACKEND, block);
687*61046927SAndroid Build Coastguard Worker    backend->op = op;
688*61046927SAndroid Build Coastguard Worker 
689*61046927SAndroid Build Coastguard Worker    return backend;
690*61046927SAndroid Build Coastguard Worker }
691*61046927SAndroid Build Coastguard Worker 
692*61046927SAndroid Build Coastguard Worker /**
693*61046927SAndroid Build Coastguard Worker  * \brief Allocates and initializes a new rogue_ctrl_instr object.
694*61046927SAndroid Build Coastguard Worker  *
695*61046927SAndroid Build Coastguard Worker  * \param[in] block The block that the new control instruction belongs to.
696*61046927SAndroid Build Coastguard Worker  * \param[in] op The control operation.
697*61046927SAndroid Build Coastguard Worker  * \return The new control instruction.
698*61046927SAndroid Build Coastguard Worker  */
699*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_ctrl_instr_create(rogue_block * block,enum rogue_ctrl_op op)700*61046927SAndroid Build Coastguard Worker rogue_ctrl_instr *rogue_ctrl_instr_create(rogue_block *block,
701*61046927SAndroid Build Coastguard Worker                                           enum rogue_ctrl_op op)
702*61046927SAndroid Build Coastguard Worker {
703*61046927SAndroid Build Coastguard Worker    rogue_ctrl_instr *ctrl = rzalloc_size(block, sizeof(*ctrl));
704*61046927SAndroid Build Coastguard Worker    rogue_instr_init(&ctrl->instr, ROGUE_INSTR_TYPE_CTRL, block);
705*61046927SAndroid Build Coastguard Worker    ctrl->op = op;
706*61046927SAndroid Build Coastguard Worker 
707*61046927SAndroid Build Coastguard Worker    return ctrl;
708*61046927SAndroid Build Coastguard Worker }
709*61046927SAndroid Build Coastguard Worker 
710*61046927SAndroid Build Coastguard Worker /**
711*61046927SAndroid Build Coastguard Worker  * \brief Allocates and initializes a new rogue_bitwise_instr object.
712*61046927SAndroid Build Coastguard Worker  *
713*61046927SAndroid Build Coastguard Worker  * \param[in] block The block that the new bitwise instruction belongs to.
714*61046927SAndroid Build Coastguard Worker  * \param[in] op The bitwise operation.
715*61046927SAndroid Build Coastguard Worker  * \return The new bitwise instruction.
716*61046927SAndroid Build Coastguard Worker  */
717*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_bitwise_instr_create(rogue_block * block,enum rogue_bitwise_op op)718*61046927SAndroid Build Coastguard Worker rogue_bitwise_instr *rogue_bitwise_instr_create(rogue_block *block,
719*61046927SAndroid Build Coastguard Worker                                                 enum rogue_bitwise_op op)
720*61046927SAndroid Build Coastguard Worker {
721*61046927SAndroid Build Coastguard Worker    rogue_bitwise_instr *bitwise = rzalloc_size(block, sizeof(*bitwise));
722*61046927SAndroid Build Coastguard Worker    rogue_instr_init(&bitwise->instr, ROGUE_INSTR_TYPE_BITWISE, block);
723*61046927SAndroid Build Coastguard Worker    bitwise->op = op;
724*61046927SAndroid Build Coastguard Worker 
725*61046927SAndroid Build Coastguard Worker    return bitwise;
726*61046927SAndroid Build Coastguard Worker }
727*61046927SAndroid Build Coastguard Worker 
728*61046927SAndroid Build Coastguard Worker /**
729*61046927SAndroid Build Coastguard Worker  * \brief Tracks/links objects that are written to/modified by an instruction.
730*61046927SAndroid Build Coastguard Worker  *
731*61046927SAndroid Build Coastguard Worker  * \param[in] instr The instruction.
732*61046927SAndroid Build Coastguard Worker  */
733*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_link_instr_write(rogue_instr * instr)734*61046927SAndroid Build Coastguard Worker void rogue_link_instr_write(rogue_instr *instr)
735*61046927SAndroid Build Coastguard Worker {
736*61046927SAndroid Build Coastguard Worker    switch (instr->type) {
737*61046927SAndroid Build Coastguard Worker    case ROGUE_INSTR_TYPE_ALU: {
738*61046927SAndroid Build Coastguard Worker       rogue_alu_instr *alu = rogue_instr_as_alu(instr);
739*61046927SAndroid Build Coastguard Worker       const unsigned num_dsts = rogue_alu_op_infos[alu->op].num_dsts;
740*61046927SAndroid Build Coastguard Worker 
741*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_dsts; ++i) {
742*61046927SAndroid Build Coastguard Worker          if (rogue_ref_is_reg(&alu->dst[i].ref)) {
743*61046927SAndroid Build Coastguard Worker             rogue_reg_write *write = &alu->dst_write[i].reg;
744*61046927SAndroid Build Coastguard Worker             rogue_reg *reg = alu->dst[i].ref.reg;
745*61046927SAndroid Build Coastguard Worker             rogue_link_instr_write_reg(instr, write, reg, i);
746*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_regarray(&alu->dst[i].ref)) {
747*61046927SAndroid Build Coastguard Worker             rogue_regarray_write *write = &alu->dst_write[i].regarray;
748*61046927SAndroid Build Coastguard Worker             rogue_regarray *regarray = alu->dst[i].ref.regarray;
749*61046927SAndroid Build Coastguard Worker             rogue_link_instr_write_regarray(instr, write, regarray, i);
750*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_io(&alu->dst[i].ref)) { /* TODO: check WHICH IO
751*61046927SAndroid Build Coastguard Worker                                                             IT IS */
752*61046927SAndroid Build Coastguard Worker          } else {
753*61046927SAndroid Build Coastguard Worker             unreachable("Unsupported destination reference type.");
754*61046927SAndroid Build Coastguard Worker          }
755*61046927SAndroid Build Coastguard Worker       }
756*61046927SAndroid Build Coastguard Worker 
757*61046927SAndroid Build Coastguard Worker       break;
758*61046927SAndroid Build Coastguard Worker    }
759*61046927SAndroid Build Coastguard Worker 
760*61046927SAndroid Build Coastguard Worker    case ROGUE_INSTR_TYPE_BACKEND: {
761*61046927SAndroid Build Coastguard Worker       rogue_backend_instr *backend = rogue_instr_as_backend(instr);
762*61046927SAndroid Build Coastguard Worker       const unsigned num_dsts = rogue_backend_op_infos[backend->op].num_dsts;
763*61046927SAndroid Build Coastguard Worker 
764*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_dsts; ++i) {
765*61046927SAndroid Build Coastguard Worker          if (rogue_ref_is_reg(&backend->dst[i].ref)) {
766*61046927SAndroid Build Coastguard Worker             rogue_reg_write *write = &backend->dst_write[i].reg;
767*61046927SAndroid Build Coastguard Worker             rogue_reg *reg = backend->dst[i].ref.reg;
768*61046927SAndroid Build Coastguard Worker             rogue_link_instr_write_reg(instr, write, reg, i);
769*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_regarray(&backend->dst[i].ref)) {
770*61046927SAndroid Build Coastguard Worker             rogue_regarray_write *write = &backend->dst_write[i].regarray;
771*61046927SAndroid Build Coastguard Worker             rogue_regarray *regarray = backend->dst[i].ref.regarray;
772*61046927SAndroid Build Coastguard Worker             rogue_link_instr_write_regarray(instr, write, regarray, i);
773*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_io(&backend->dst[i].ref)) { /* TODO: check
774*61046927SAndroid Build Coastguard Worker                                                                 WHICH IO IT IS
775*61046927SAndroid Build Coastguard Worker                                                               */
776*61046927SAndroid Build Coastguard Worker          } else {
777*61046927SAndroid Build Coastguard Worker             unreachable("Unsupported destination reference type.");
778*61046927SAndroid Build Coastguard Worker          }
779*61046927SAndroid Build Coastguard Worker       }
780*61046927SAndroid Build Coastguard Worker 
781*61046927SAndroid Build Coastguard Worker       break;
782*61046927SAndroid Build Coastguard Worker    }
783*61046927SAndroid Build Coastguard Worker 
784*61046927SAndroid Build Coastguard Worker    case ROGUE_INSTR_TYPE_CTRL: {
785*61046927SAndroid Build Coastguard Worker       rogue_ctrl_instr *ctrl = rogue_instr_as_ctrl(instr);
786*61046927SAndroid Build Coastguard Worker       const unsigned num_dsts = rogue_ctrl_op_infos[ctrl->op].num_dsts;
787*61046927SAndroid Build Coastguard Worker 
788*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_dsts; ++i) {
789*61046927SAndroid Build Coastguard Worker          if (rogue_ref_is_reg(&ctrl->dst[i].ref)) {
790*61046927SAndroid Build Coastguard Worker             rogue_reg_write *write = &ctrl->dst_write[i].reg;
791*61046927SAndroid Build Coastguard Worker             rogue_reg *reg = ctrl->dst[i].ref.reg;
792*61046927SAndroid Build Coastguard Worker             rogue_link_instr_write_reg(instr, write, reg, i);
793*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_regarray(&ctrl->dst[i].ref)) {
794*61046927SAndroid Build Coastguard Worker             rogue_regarray_write *write = &ctrl->dst_write[i].regarray;
795*61046927SAndroid Build Coastguard Worker             rogue_regarray *regarray = ctrl->dst[i].ref.regarray;
796*61046927SAndroid Build Coastguard Worker             rogue_link_instr_write_regarray(instr, write, regarray, i);
797*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_io(&ctrl->dst[i].ref)) { /* TODO: check WHICH
798*61046927SAndroid Build Coastguard Worker                                                              IO IT IS */
799*61046927SAndroid Build Coastguard Worker          } else {
800*61046927SAndroid Build Coastguard Worker             unreachable("Unsupported destination reference type.");
801*61046927SAndroid Build Coastguard Worker          }
802*61046927SAndroid Build Coastguard Worker       }
803*61046927SAndroid Build Coastguard Worker 
804*61046927SAndroid Build Coastguard Worker       break;
805*61046927SAndroid Build Coastguard Worker    }
806*61046927SAndroid Build Coastguard Worker 
807*61046927SAndroid Build Coastguard Worker    case ROGUE_INSTR_TYPE_BITWISE: {
808*61046927SAndroid Build Coastguard Worker       rogue_bitwise_instr *bitwise = rogue_instr_as_bitwise(instr);
809*61046927SAndroid Build Coastguard Worker       const unsigned num_dsts = rogue_bitwise_op_infos[bitwise->op].num_dsts;
810*61046927SAndroid Build Coastguard Worker 
811*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_dsts; ++i) {
812*61046927SAndroid Build Coastguard Worker          if (rogue_ref_is_reg(&bitwise->dst[i].ref)) {
813*61046927SAndroid Build Coastguard Worker             rogue_reg_write *write = &bitwise->dst_write[i].reg;
814*61046927SAndroid Build Coastguard Worker             rogue_reg *reg = bitwise->dst[i].ref.reg;
815*61046927SAndroid Build Coastguard Worker             rogue_link_instr_write_reg(instr, write, reg, i);
816*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_regarray(&bitwise->dst[i].ref)) {
817*61046927SAndroid Build Coastguard Worker             rogue_regarray_write *write = &bitwise->dst_write[i].regarray;
818*61046927SAndroid Build Coastguard Worker             rogue_regarray *regarray = bitwise->dst[i].ref.regarray;
819*61046927SAndroid Build Coastguard Worker             rogue_link_instr_write_regarray(instr, write, regarray, i);
820*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_io(&bitwise->dst[i].ref)) { /* TODO: check
821*61046927SAndroid Build Coastguard Worker                                                                 WHICH IO IT IS
822*61046927SAndroid Build Coastguard Worker                                                               */
823*61046927SAndroid Build Coastguard Worker          } else {
824*61046927SAndroid Build Coastguard Worker             unreachable("Unsupported destination reference type.");
825*61046927SAndroid Build Coastguard Worker          }
826*61046927SAndroid Build Coastguard Worker       }
827*61046927SAndroid Build Coastguard Worker 
828*61046927SAndroid Build Coastguard Worker       break;
829*61046927SAndroid Build Coastguard Worker    }
830*61046927SAndroid Build Coastguard Worker 
831*61046927SAndroid Build Coastguard Worker    default:
832*61046927SAndroid Build Coastguard Worker       unreachable("Unsupported instruction type.");
833*61046927SAndroid Build Coastguard Worker    }
834*61046927SAndroid Build Coastguard Worker }
835*61046927SAndroid Build Coastguard Worker 
836*61046927SAndroid Build Coastguard Worker /**
837*61046927SAndroid Build Coastguard Worker  * \brief Tracks/links objects that are used by/read from an instruction.
838*61046927SAndroid Build Coastguard Worker  *
839*61046927SAndroid Build Coastguard Worker  * \param[in] instr The instruction.
840*61046927SAndroid Build Coastguard Worker  */
841*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_link_instr_use(rogue_instr * instr)842*61046927SAndroid Build Coastguard Worker void rogue_link_instr_use(rogue_instr *instr)
843*61046927SAndroid Build Coastguard Worker {
844*61046927SAndroid Build Coastguard Worker    switch (instr->type) {
845*61046927SAndroid Build Coastguard Worker    case ROGUE_INSTR_TYPE_ALU: {
846*61046927SAndroid Build Coastguard Worker       rogue_alu_instr *alu = rogue_instr_as_alu(instr);
847*61046927SAndroid Build Coastguard Worker       const unsigned num_srcs = rogue_alu_op_infos[alu->op].num_srcs;
848*61046927SAndroid Build Coastguard Worker 
849*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_srcs; ++i) {
850*61046927SAndroid Build Coastguard Worker          if (rogue_ref_is_reg(&alu->src[i].ref)) {
851*61046927SAndroid Build Coastguard Worker             rogue_reg_use *use = &alu->src_use[i].reg;
852*61046927SAndroid Build Coastguard Worker             rogue_reg *reg = alu->src[i].ref.reg;
853*61046927SAndroid Build Coastguard Worker             rogue_link_instr_use_reg(instr, use, reg, i);
854*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_regarray(&alu->src[i].ref)) {
855*61046927SAndroid Build Coastguard Worker             rogue_regarray_use *use = &alu->src_use[i].regarray;
856*61046927SAndroid Build Coastguard Worker             rogue_regarray *regarray = alu->src[i].ref.regarray;
857*61046927SAndroid Build Coastguard Worker             rogue_link_instr_use_regarray(instr, use, regarray, i);
858*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_imm(&alu->src[i].ref)) {
859*61046927SAndroid Build Coastguard Worker             rogue_link_imm_use(instr->block->shader,
860*61046927SAndroid Build Coastguard Worker                                instr,
861*61046927SAndroid Build Coastguard Worker                                i,
862*61046927SAndroid Build Coastguard Worker                                rogue_ref_get_imm(&alu->src[i].ref));
863*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_io(&alu->src[i].ref)) { /* TODO: check WHICH IO
864*61046927SAndroid Build Coastguard Worker                                                             IT IS */
865*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_val(&alu->src[i].ref)) {
866*61046927SAndroid Build Coastguard Worker          } else {
867*61046927SAndroid Build Coastguard Worker             unreachable("Unsupported source reference type.");
868*61046927SAndroid Build Coastguard Worker          }
869*61046927SAndroid Build Coastguard Worker       }
870*61046927SAndroid Build Coastguard Worker 
871*61046927SAndroid Build Coastguard Worker       break;
872*61046927SAndroid Build Coastguard Worker    }
873*61046927SAndroid Build Coastguard Worker 
874*61046927SAndroid Build Coastguard Worker    case ROGUE_INSTR_TYPE_BACKEND: {
875*61046927SAndroid Build Coastguard Worker       rogue_backend_instr *backend = rogue_instr_as_backend(instr);
876*61046927SAndroid Build Coastguard Worker       const unsigned num_srcs = rogue_backend_op_infos[backend->op].num_srcs;
877*61046927SAndroid Build Coastguard Worker 
878*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_srcs; ++i) {
879*61046927SAndroid Build Coastguard Worker          if (rogue_ref_is_reg(&backend->src[i].ref)) {
880*61046927SAndroid Build Coastguard Worker             rogue_reg_use *use = &backend->src_use[i].reg;
881*61046927SAndroid Build Coastguard Worker             rogue_reg *reg = backend->src[i].ref.reg;
882*61046927SAndroid Build Coastguard Worker             rogue_link_instr_use_reg(instr, use, reg, i);
883*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_regarray(&backend->src[i].ref)) {
884*61046927SAndroid Build Coastguard Worker             rogue_regarray_use *use = &backend->src_use[i].regarray;
885*61046927SAndroid Build Coastguard Worker             rogue_regarray *regarray = backend->src[i].ref.regarray;
886*61046927SAndroid Build Coastguard Worker             rogue_link_instr_use_regarray(instr, use, regarray, i);
887*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_drc(&backend->src[i].ref)) {
888*61046927SAndroid Build Coastguard Worker             rogue_link_drc_trxn(instr->block->shader,
889*61046927SAndroid Build Coastguard Worker                                 instr,
890*61046927SAndroid Build Coastguard Worker                                 rogue_ref_get_drc(&backend->src[i].ref));
891*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_io(&backend->src[i].ref)) { /* TODO: check
892*61046927SAndroid Build Coastguard Worker                                                                 WHICH IO IT IS
893*61046927SAndroid Build Coastguard Worker                                                               */
894*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_val(&backend->src[i].ref)) {
895*61046927SAndroid Build Coastguard Worker          } else {
896*61046927SAndroid Build Coastguard Worker             unreachable("Unsupported source reference type.");
897*61046927SAndroid Build Coastguard Worker          }
898*61046927SAndroid Build Coastguard Worker       }
899*61046927SAndroid Build Coastguard Worker 
900*61046927SAndroid Build Coastguard Worker       break;
901*61046927SAndroid Build Coastguard Worker    }
902*61046927SAndroid Build Coastguard Worker 
903*61046927SAndroid Build Coastguard Worker    case ROGUE_INSTR_TYPE_CTRL: {
904*61046927SAndroid Build Coastguard Worker       rogue_ctrl_instr *ctrl = rogue_instr_as_ctrl(instr);
905*61046927SAndroid Build Coastguard Worker       const unsigned num_srcs = rogue_ctrl_op_infos[ctrl->op].num_srcs;
906*61046927SAndroid Build Coastguard Worker 
907*61046927SAndroid Build Coastguard Worker       /* Branch instruction. */
908*61046927SAndroid Build Coastguard Worker       if (!num_srcs && ctrl->target_block) {
909*61046927SAndroid Build Coastguard Worker          rogue_link_instr_use_block(instr,
910*61046927SAndroid Build Coastguard Worker                                     &ctrl->block_use,
911*61046927SAndroid Build Coastguard Worker                                     ctrl->target_block);
912*61046927SAndroid Build Coastguard Worker          break;
913*61046927SAndroid Build Coastguard Worker       }
914*61046927SAndroid Build Coastguard Worker 
915*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_srcs; ++i) {
916*61046927SAndroid Build Coastguard Worker          if (rogue_ref_is_reg(&ctrl->src[i].ref)) {
917*61046927SAndroid Build Coastguard Worker             rogue_reg_use *use = &ctrl->src_use[i].reg;
918*61046927SAndroid Build Coastguard Worker             rogue_reg *reg = ctrl->src[i].ref.reg;
919*61046927SAndroid Build Coastguard Worker             rogue_link_instr_use_reg(instr, use, reg, i);
920*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_regarray(&ctrl->src[i].ref)) {
921*61046927SAndroid Build Coastguard Worker             rogue_regarray_use *use = &ctrl->src_use[i].regarray;
922*61046927SAndroid Build Coastguard Worker             rogue_regarray *regarray = ctrl->src[i].ref.regarray;
923*61046927SAndroid Build Coastguard Worker             rogue_link_instr_use_regarray(instr, use, regarray, i);
924*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_drc(&ctrl->src[i].ref)) {
925*61046927SAndroid Build Coastguard Worker             /* WDF instructions consume/release drcs, handled independently. */
926*61046927SAndroid Build Coastguard Worker             if (ctrl->op != ROGUE_CTRL_OP_WDF)
927*61046927SAndroid Build Coastguard Worker                rogue_link_drc_trxn(instr->block->shader,
928*61046927SAndroid Build Coastguard Worker                                    instr,
929*61046927SAndroid Build Coastguard Worker                                    rogue_ref_get_drc(&ctrl->src[i].ref));
930*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_io(&ctrl->src[i].ref)) { /* TODO: check WHICH
931*61046927SAndroid Build Coastguard Worker                                                              IO IT IS */
932*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_val(&ctrl->src[i].ref)) {
933*61046927SAndroid Build Coastguard Worker          } else {
934*61046927SAndroid Build Coastguard Worker             unreachable("Unsupported source reference type.");
935*61046927SAndroid Build Coastguard Worker          }
936*61046927SAndroid Build Coastguard Worker       }
937*61046927SAndroid Build Coastguard Worker 
938*61046927SAndroid Build Coastguard Worker       break;
939*61046927SAndroid Build Coastguard Worker    }
940*61046927SAndroid Build Coastguard Worker 
941*61046927SAndroid Build Coastguard Worker    case ROGUE_INSTR_TYPE_BITWISE: {
942*61046927SAndroid Build Coastguard Worker       rogue_bitwise_instr *bitwise = rogue_instr_as_bitwise(instr);
943*61046927SAndroid Build Coastguard Worker       const unsigned num_srcs = rogue_bitwise_op_infos[bitwise->op].num_srcs;
944*61046927SAndroid Build Coastguard Worker 
945*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_srcs; ++i) {
946*61046927SAndroid Build Coastguard Worker          if (rogue_ref_is_reg(&bitwise->src[i].ref)) {
947*61046927SAndroid Build Coastguard Worker             rogue_reg_use *use = &bitwise->src_use[i].reg;
948*61046927SAndroid Build Coastguard Worker             rogue_reg *reg = bitwise->src[i].ref.reg;
949*61046927SAndroid Build Coastguard Worker             rogue_link_instr_use_reg(instr, use, reg, i);
950*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_regarray(&bitwise->src[i].ref)) {
951*61046927SAndroid Build Coastguard Worker             rogue_regarray_use *use = &bitwise->src_use[i].regarray;
952*61046927SAndroid Build Coastguard Worker             rogue_regarray *regarray = bitwise->src[i].ref.regarray;
953*61046927SAndroid Build Coastguard Worker             rogue_link_instr_use_regarray(instr, use, regarray, i);
954*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_drc(&bitwise->src[i].ref)) {
955*61046927SAndroid Build Coastguard Worker             rogue_link_drc_trxn(instr->block->shader,
956*61046927SAndroid Build Coastguard Worker                                 instr,
957*61046927SAndroid Build Coastguard Worker                                 rogue_ref_get_drc(&bitwise->src[i].ref));
958*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_io(&bitwise->src[i].ref)) { /* TODO: check
959*61046927SAndroid Build Coastguard Worker                                                                 WHICH IO IT IS
960*61046927SAndroid Build Coastguard Worker                                                               */
961*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_val(&bitwise->src[i].ref)) {
962*61046927SAndroid Build Coastguard Worker          } else {
963*61046927SAndroid Build Coastguard Worker             unreachable("Unsupported source reference type.");
964*61046927SAndroid Build Coastguard Worker          }
965*61046927SAndroid Build Coastguard Worker       }
966*61046927SAndroid Build Coastguard Worker 
967*61046927SAndroid Build Coastguard Worker       break;
968*61046927SAndroid Build Coastguard Worker    }
969*61046927SAndroid Build Coastguard Worker 
970*61046927SAndroid Build Coastguard Worker    default:
971*61046927SAndroid Build Coastguard Worker       unreachable("Unsupported instruction type.");
972*61046927SAndroid Build Coastguard Worker    }
973*61046927SAndroid Build Coastguard Worker }
974*61046927SAndroid Build Coastguard Worker 
975*61046927SAndroid Build Coastguard Worker /**
976*61046927SAndroid Build Coastguard Worker  * \brief Untracks/unlinks objects that are written to/modified by an
977*61046927SAndroid Build Coastguard Worker  * instruction.
978*61046927SAndroid Build Coastguard Worker  *
979*61046927SAndroid Build Coastguard Worker  * \param[in] instr The instruction.
980*61046927SAndroid Build Coastguard Worker  */
981*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_unlink_instr_write(rogue_instr * instr)982*61046927SAndroid Build Coastguard Worker void rogue_unlink_instr_write(rogue_instr *instr)
983*61046927SAndroid Build Coastguard Worker {
984*61046927SAndroid Build Coastguard Worker    switch (instr->type) {
985*61046927SAndroid Build Coastguard Worker    case ROGUE_INSTR_TYPE_ALU: {
986*61046927SAndroid Build Coastguard Worker       rogue_alu_instr *alu = rogue_instr_as_alu(instr);
987*61046927SAndroid Build Coastguard Worker       const unsigned num_dsts = rogue_alu_op_infos[alu->op].num_dsts;
988*61046927SAndroid Build Coastguard Worker 
989*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_dsts; ++i) {
990*61046927SAndroid Build Coastguard Worker          if (rogue_ref_is_reg(&alu->dst[i].ref)) {
991*61046927SAndroid Build Coastguard Worker             rogue_reg_write *write = &alu->dst_write[i].reg;
992*61046927SAndroid Build Coastguard Worker             rogue_unlink_instr_write_reg(instr, write);
993*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_regarray(&alu->dst[i].ref)) {
994*61046927SAndroid Build Coastguard Worker             rogue_regarray_write *write = &alu->dst_write[i].regarray;
995*61046927SAndroid Build Coastguard Worker             rogue_unlink_instr_write_regarray(instr, write);
996*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_io(&alu->dst[i].ref)) { /* TODO: check WHICH IO
997*61046927SAndroid Build Coastguard Worker                                                             IT IS */
998*61046927SAndroid Build Coastguard Worker          } else {
999*61046927SAndroid Build Coastguard Worker             unreachable("Unsupported destination reference type.");
1000*61046927SAndroid Build Coastguard Worker          }
1001*61046927SAndroid Build Coastguard Worker       }
1002*61046927SAndroid Build Coastguard Worker 
1003*61046927SAndroid Build Coastguard Worker       break;
1004*61046927SAndroid Build Coastguard Worker    }
1005*61046927SAndroid Build Coastguard Worker 
1006*61046927SAndroid Build Coastguard Worker    case ROGUE_INSTR_TYPE_BACKEND: {
1007*61046927SAndroid Build Coastguard Worker       rogue_backend_instr *backend = rogue_instr_as_backend(instr);
1008*61046927SAndroid Build Coastguard Worker       const unsigned num_dsts = rogue_backend_op_infos[backend->op].num_dsts;
1009*61046927SAndroid Build Coastguard Worker 
1010*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_dsts; ++i) {
1011*61046927SAndroid Build Coastguard Worker          if (rogue_ref_is_reg(&backend->dst[i].ref)) {
1012*61046927SAndroid Build Coastguard Worker             rogue_reg_write *write = &backend->dst_write[i].reg;
1013*61046927SAndroid Build Coastguard Worker             rogue_unlink_instr_write_reg(instr, write);
1014*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_regarray(&backend->dst[i].ref)) {
1015*61046927SAndroid Build Coastguard Worker             rogue_regarray_write *write = &backend->dst_write[i].regarray;
1016*61046927SAndroid Build Coastguard Worker             rogue_unlink_instr_write_regarray(instr, write);
1017*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_io(&backend->dst[i].ref)) { /* TODO: check
1018*61046927SAndroid Build Coastguard Worker                                                                 WHICH IO IT IS
1019*61046927SAndroid Build Coastguard Worker                                                               */
1020*61046927SAndroid Build Coastguard Worker          } else {
1021*61046927SAndroid Build Coastguard Worker             unreachable("Unsupported destination reference type.");
1022*61046927SAndroid Build Coastguard Worker          }
1023*61046927SAndroid Build Coastguard Worker       }
1024*61046927SAndroid Build Coastguard Worker 
1025*61046927SAndroid Build Coastguard Worker       break;
1026*61046927SAndroid Build Coastguard Worker    }
1027*61046927SAndroid Build Coastguard Worker 
1028*61046927SAndroid Build Coastguard Worker    case ROGUE_INSTR_TYPE_CTRL: {
1029*61046927SAndroid Build Coastguard Worker       rogue_ctrl_instr *ctrl = rogue_instr_as_ctrl(instr);
1030*61046927SAndroid Build Coastguard Worker       const unsigned num_dsts = rogue_ctrl_op_infos[ctrl->op].num_dsts;
1031*61046927SAndroid Build Coastguard Worker 
1032*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_dsts; ++i) {
1033*61046927SAndroid Build Coastguard Worker          if (rogue_ref_is_reg(&ctrl->dst[i].ref)) {
1034*61046927SAndroid Build Coastguard Worker             rogue_reg_write *write = &ctrl->dst_write[i].reg;
1035*61046927SAndroid Build Coastguard Worker             rogue_unlink_instr_write_reg(instr, write);
1036*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_regarray(&ctrl->dst[i].ref)) {
1037*61046927SAndroid Build Coastguard Worker             rogue_regarray_write *write = &ctrl->dst_write[i].regarray;
1038*61046927SAndroid Build Coastguard Worker             rogue_unlink_instr_write_regarray(instr, write);
1039*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_io(&ctrl->dst[i].ref)) { /* TODO: check WHICH
1040*61046927SAndroid Build Coastguard Worker                                                              IO IT IS */
1041*61046927SAndroid Build Coastguard Worker          } else {
1042*61046927SAndroid Build Coastguard Worker             unreachable("Unsupported destination reference type.");
1043*61046927SAndroid Build Coastguard Worker          }
1044*61046927SAndroid Build Coastguard Worker       }
1045*61046927SAndroid Build Coastguard Worker 
1046*61046927SAndroid Build Coastguard Worker       break;
1047*61046927SAndroid Build Coastguard Worker    }
1048*61046927SAndroid Build Coastguard Worker 
1049*61046927SAndroid Build Coastguard Worker    case ROGUE_INSTR_TYPE_BITWISE: {
1050*61046927SAndroid Build Coastguard Worker       rogue_bitwise_instr *bitwise = rogue_instr_as_bitwise(instr);
1051*61046927SAndroid Build Coastguard Worker       const unsigned num_dsts = rogue_bitwise_op_infos[bitwise->op].num_dsts;
1052*61046927SAndroid Build Coastguard Worker 
1053*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_dsts; ++i) {
1054*61046927SAndroid Build Coastguard Worker          if (rogue_ref_is_reg(&bitwise->dst[i].ref)) {
1055*61046927SAndroid Build Coastguard Worker             rogue_reg_write *write = &bitwise->dst_write[i].reg;
1056*61046927SAndroid Build Coastguard Worker             rogue_unlink_instr_write_reg(instr, write);
1057*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_regarray(&bitwise->dst[i].ref)) {
1058*61046927SAndroid Build Coastguard Worker             rogue_regarray_write *write = &bitwise->dst_write[i].regarray;
1059*61046927SAndroid Build Coastguard Worker             rogue_unlink_instr_write_regarray(instr, write);
1060*61046927SAndroid Build Coastguard Worker          } else {
1061*61046927SAndroid Build Coastguard Worker             unreachable("Invalid destination reference type.");
1062*61046927SAndroid Build Coastguard Worker          }
1063*61046927SAndroid Build Coastguard Worker       }
1064*61046927SAndroid Build Coastguard Worker 
1065*61046927SAndroid Build Coastguard Worker       break;
1066*61046927SAndroid Build Coastguard Worker    }
1067*61046927SAndroid Build Coastguard Worker 
1068*61046927SAndroid Build Coastguard Worker    default:
1069*61046927SAndroid Build Coastguard Worker       unreachable("Unsupported instruction type.");
1070*61046927SAndroid Build Coastguard Worker    }
1071*61046927SAndroid Build Coastguard Worker }
1072*61046927SAndroid Build Coastguard Worker 
1073*61046927SAndroid Build Coastguard Worker /**
1074*61046927SAndroid Build Coastguard Worker  * \brief Untracks/unlinks objects that are used by/read from an instruction.
1075*61046927SAndroid Build Coastguard Worker  *
1076*61046927SAndroid Build Coastguard Worker  * \param[in] instr The instruction.
1077*61046927SAndroid Build Coastguard Worker  */
1078*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_unlink_instr_use(rogue_instr * instr)1079*61046927SAndroid Build Coastguard Worker void rogue_unlink_instr_use(rogue_instr *instr)
1080*61046927SAndroid Build Coastguard Worker {
1081*61046927SAndroid Build Coastguard Worker    switch (instr->type) {
1082*61046927SAndroid Build Coastguard Worker    case ROGUE_INSTR_TYPE_ALU: {
1083*61046927SAndroid Build Coastguard Worker       rogue_alu_instr *alu = rogue_instr_as_alu(instr);
1084*61046927SAndroid Build Coastguard Worker       const unsigned num_srcs = rogue_alu_op_infos[alu->op].num_srcs;
1085*61046927SAndroid Build Coastguard Worker 
1086*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_srcs; ++i) {
1087*61046927SAndroid Build Coastguard Worker          if (rogue_ref_is_reg(&alu->src[i].ref)) {
1088*61046927SAndroid Build Coastguard Worker             rogue_reg_use *use = &alu->src_use[i].reg;
1089*61046927SAndroid Build Coastguard Worker             rogue_unlink_instr_use_reg(instr, use);
1090*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_regarray(&alu->src[i].ref)) {
1091*61046927SAndroid Build Coastguard Worker             rogue_regarray_use *use = &alu->src_use[i].regarray;
1092*61046927SAndroid Build Coastguard Worker             rogue_unlink_instr_use_regarray(instr, use);
1093*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_imm(&alu->src[i].ref)) {
1094*61046927SAndroid Build Coastguard Worker             rogue_unlink_imm_use(instr,
1095*61046927SAndroid Build Coastguard Worker                                  &rogue_ref_get_imm(&alu->src[i].ref)->use);
1096*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_io(&alu->src[i].ref)) { /* TODO: check WHICH IO
1097*61046927SAndroid Build Coastguard Worker                                                             IT IS */
1098*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_val(&alu->src[i].ref)) {
1099*61046927SAndroid Build Coastguard Worker          } else {
1100*61046927SAndroid Build Coastguard Worker             unreachable("Unsupported source reference type.");
1101*61046927SAndroid Build Coastguard Worker          }
1102*61046927SAndroid Build Coastguard Worker       }
1103*61046927SAndroid Build Coastguard Worker 
1104*61046927SAndroid Build Coastguard Worker       break;
1105*61046927SAndroid Build Coastguard Worker    }
1106*61046927SAndroid Build Coastguard Worker 
1107*61046927SAndroid Build Coastguard Worker    case ROGUE_INSTR_TYPE_BACKEND: {
1108*61046927SAndroid Build Coastguard Worker       rogue_backend_instr *backend = rogue_instr_as_backend(instr);
1109*61046927SAndroid Build Coastguard Worker       const unsigned num_srcs = rogue_backend_op_infos[backend->op].num_srcs;
1110*61046927SAndroid Build Coastguard Worker 
1111*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_srcs; ++i) {
1112*61046927SAndroid Build Coastguard Worker          if (rogue_ref_is_reg(&backend->src[i].ref)) {
1113*61046927SAndroid Build Coastguard Worker             rogue_reg_use *use = &backend->src_use[i].reg;
1114*61046927SAndroid Build Coastguard Worker             rogue_unlink_instr_use_reg(instr, use);
1115*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_regarray(&backend->src[i].ref)) {
1116*61046927SAndroid Build Coastguard Worker             rogue_regarray_use *use = &backend->src_use[i].regarray;
1117*61046927SAndroid Build Coastguard Worker             rogue_unlink_instr_use_regarray(instr, use);
1118*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_drc(&backend->src[i].ref)) {
1119*61046927SAndroid Build Coastguard Worker             rogue_unlink_drc_trxn(instr->block->shader,
1120*61046927SAndroid Build Coastguard Worker                                   instr,
1121*61046927SAndroid Build Coastguard Worker                                   rogue_ref_get_drc(&backend->src[i].ref));
1122*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_io(&backend->src[i].ref)) { /* TODO: check
1123*61046927SAndroid Build Coastguard Worker                                                                 WHICH IO IT IS
1124*61046927SAndroid Build Coastguard Worker                                                               */
1125*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_val(&backend->src[i].ref)) {
1126*61046927SAndroid Build Coastguard Worker          } else {
1127*61046927SAndroid Build Coastguard Worker             unreachable("Unsupported source reference type.");
1128*61046927SAndroid Build Coastguard Worker          }
1129*61046927SAndroid Build Coastguard Worker       }
1130*61046927SAndroid Build Coastguard Worker 
1131*61046927SAndroid Build Coastguard Worker       break;
1132*61046927SAndroid Build Coastguard Worker    }
1133*61046927SAndroid Build Coastguard Worker 
1134*61046927SAndroid Build Coastguard Worker    case ROGUE_INSTR_TYPE_CTRL: {
1135*61046927SAndroid Build Coastguard Worker       rogue_ctrl_instr *ctrl = rogue_instr_as_ctrl(instr);
1136*61046927SAndroid Build Coastguard Worker       const unsigned num_srcs = rogue_ctrl_op_infos[ctrl->op].num_srcs;
1137*61046927SAndroid Build Coastguard Worker 
1138*61046927SAndroid Build Coastguard Worker       /* Branch instruction. */
1139*61046927SAndroid Build Coastguard Worker       if (!num_srcs && ctrl->target_block) {
1140*61046927SAndroid Build Coastguard Worker          rogue_unlink_instr_use_block(instr, &ctrl->block_use);
1141*61046927SAndroid Build Coastguard Worker          break;
1142*61046927SAndroid Build Coastguard Worker       }
1143*61046927SAndroid Build Coastguard Worker 
1144*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_srcs; ++i) {
1145*61046927SAndroid Build Coastguard Worker          if (rogue_ref_is_reg(&ctrl->src[i].ref)) {
1146*61046927SAndroid Build Coastguard Worker             rogue_reg_use *use = &ctrl->src_use[i].reg;
1147*61046927SAndroid Build Coastguard Worker             rogue_unlink_instr_use_reg(instr, use);
1148*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_regarray(&ctrl->src[i].ref)) {
1149*61046927SAndroid Build Coastguard Worker             rogue_regarray_use *use = &ctrl->src_use[i].regarray;
1150*61046927SAndroid Build Coastguard Worker             rogue_unlink_instr_use_regarray(instr, use);
1151*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_drc(&ctrl->src[i].ref)) {
1152*61046927SAndroid Build Coastguard Worker             /* WDF instructions consume/release drcs, handled independently. */
1153*61046927SAndroid Build Coastguard Worker             if (ctrl->op != ROGUE_CTRL_OP_WDF)
1154*61046927SAndroid Build Coastguard Worker                rogue_unlink_drc_trxn(instr->block->shader,
1155*61046927SAndroid Build Coastguard Worker                                      instr,
1156*61046927SAndroid Build Coastguard Worker                                      rogue_ref_get_drc(&ctrl->src[i].ref));
1157*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_io(&ctrl->src[i].ref)) { /* TODO: check WHICH
1158*61046927SAndroid Build Coastguard Worker                                                              IO IT IS */
1159*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_val(&ctrl->src[i].ref)) {
1160*61046927SAndroid Build Coastguard Worker          } else {
1161*61046927SAndroid Build Coastguard Worker             unreachable("Unsupported source reference type.");
1162*61046927SAndroid Build Coastguard Worker          }
1163*61046927SAndroid Build Coastguard Worker       }
1164*61046927SAndroid Build Coastguard Worker 
1165*61046927SAndroid Build Coastguard Worker       break;
1166*61046927SAndroid Build Coastguard Worker    }
1167*61046927SAndroid Build Coastguard Worker 
1168*61046927SAndroid Build Coastguard Worker    case ROGUE_INSTR_TYPE_BITWISE: {
1169*61046927SAndroid Build Coastguard Worker       rogue_bitwise_instr *bitwise = rogue_instr_as_bitwise(instr);
1170*61046927SAndroid Build Coastguard Worker       const unsigned num_srcs = rogue_bitwise_op_infos[bitwise->op].num_srcs;
1171*61046927SAndroid Build Coastguard Worker 
1172*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_srcs; ++i) {
1173*61046927SAndroid Build Coastguard Worker          if (rogue_ref_is_reg(&bitwise->src[i].ref)) {
1174*61046927SAndroid Build Coastguard Worker             rogue_reg_use *use = &bitwise->src_use[i].reg;
1175*61046927SAndroid Build Coastguard Worker             rogue_unlink_instr_use_reg(instr, use);
1176*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_regarray(&bitwise->src[i].ref)) {
1177*61046927SAndroid Build Coastguard Worker             rogue_regarray_use *use = &bitwise->src_use[i].regarray;
1178*61046927SAndroid Build Coastguard Worker             rogue_unlink_instr_use_regarray(instr, use);
1179*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_drc(&bitwise->src[i].ref)) {
1180*61046927SAndroid Build Coastguard Worker             rogue_unlink_drc_trxn(instr->block->shader,
1181*61046927SAndroid Build Coastguard Worker                                   instr,
1182*61046927SAndroid Build Coastguard Worker                                   rogue_ref_get_drc(&bitwise->src[i].ref));
1183*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_io(&bitwise->src[i].ref)) { /* TODO: check
1184*61046927SAndroid Build Coastguard Worker                                                                 WHICH IO IT IS
1185*61046927SAndroid Build Coastguard Worker                                                               */
1186*61046927SAndroid Build Coastguard Worker          } else if (rogue_ref_is_val(&bitwise->src[i].ref)) {
1187*61046927SAndroid Build Coastguard Worker          } else {
1188*61046927SAndroid Build Coastguard Worker             unreachable("Unsupported source reference type.");
1189*61046927SAndroid Build Coastguard Worker          }
1190*61046927SAndroid Build Coastguard Worker       }
1191*61046927SAndroid Build Coastguard Worker 
1192*61046927SAndroid Build Coastguard Worker       break;
1193*61046927SAndroid Build Coastguard Worker    }
1194*61046927SAndroid Build Coastguard Worker 
1195*61046927SAndroid Build Coastguard Worker    default:
1196*61046927SAndroid Build Coastguard Worker       unreachable("Unsupported instruction type.");
1197*61046927SAndroid Build Coastguard Worker    }
1198*61046927SAndroid Build Coastguard Worker }
1199*61046927SAndroid Build Coastguard Worker 
rogue_compiler_destructor(UNUSED void * ptr)1200*61046927SAndroid Build Coastguard Worker static void rogue_compiler_destructor(UNUSED void *ptr)
1201*61046927SAndroid Build Coastguard Worker {
1202*61046927SAndroid Build Coastguard Worker    glsl_type_singleton_decref();
1203*61046927SAndroid Build Coastguard Worker }
1204*61046927SAndroid Build Coastguard Worker 
1205*61046927SAndroid Build Coastguard Worker /**
1206*61046927SAndroid Build Coastguard Worker  * \brief Creates and sets up a Rogue compiler context.
1207*61046927SAndroid Build Coastguard Worker  *
1208*61046927SAndroid Build Coastguard Worker  * \param[in] dev_info Device info pointer.
1209*61046927SAndroid Build Coastguard Worker  * \return A pointer to the new compiler context, or NULL on failure.
1210*61046927SAndroid Build Coastguard Worker  */
1211*61046927SAndroid Build Coastguard Worker PUBLIC
rogue_compiler_create(const struct pvr_device_info * dev_info)1212*61046927SAndroid Build Coastguard Worker rogue_compiler *rogue_compiler_create(const struct pvr_device_info *dev_info)
1213*61046927SAndroid Build Coastguard Worker {
1214*61046927SAndroid Build Coastguard Worker    rogue_compiler *compiler;
1215*61046927SAndroid Build Coastguard Worker 
1216*61046927SAndroid Build Coastguard Worker    rogue_debug_init();
1217*61046927SAndroid Build Coastguard Worker 
1218*61046927SAndroid Build Coastguard Worker    compiler = rzalloc_size(NULL, sizeof(*compiler));
1219*61046927SAndroid Build Coastguard Worker    if (!compiler)
1220*61046927SAndroid Build Coastguard Worker       return NULL;
1221*61046927SAndroid Build Coastguard Worker 
1222*61046927SAndroid Build Coastguard Worker    compiler->dev_info = dev_info;
1223*61046927SAndroid Build Coastguard Worker 
1224*61046927SAndroid Build Coastguard Worker    /* TODO: Additional compiler setup (e.g. number of internal registers, BRNs,
1225*61046927SAndroid Build Coastguard Worker     * and other hw-specific info). */
1226*61046927SAndroid Build Coastguard Worker 
1227*61046927SAndroid Build Coastguard Worker    glsl_type_singleton_init_or_ref();
1228*61046927SAndroid Build Coastguard Worker 
1229*61046927SAndroid Build Coastguard Worker    ralloc_set_destructor(compiler, rogue_compiler_destructor);
1230*61046927SAndroid Build Coastguard Worker 
1231*61046927SAndroid Build Coastguard Worker    return compiler;
1232*61046927SAndroid Build Coastguard Worker }
1233*61046927SAndroid Build Coastguard Worker 
1234*61046927SAndroid Build Coastguard Worker /**
1235*61046927SAndroid Build Coastguard Worker  * \brief Creates and sets up a shared multi-stage build context.
1236*61046927SAndroid Build Coastguard Worker  *
1237*61046927SAndroid Build Coastguard Worker  * \param[in] compiler The compiler context.
1238*61046927SAndroid Build Coastguard Worker  * \return A pointer to the new build context, or NULL on failure.
1239*61046927SAndroid Build Coastguard Worker  */
1240*61046927SAndroid Build Coastguard Worker PUBLIC
1241*61046927SAndroid Build Coastguard Worker rogue_build_ctx *
rogue_build_context_create(rogue_compiler * compiler,struct pvr_pipeline_layout * pipeline_layout)1242*61046927SAndroid Build Coastguard Worker rogue_build_context_create(rogue_compiler *compiler,
1243*61046927SAndroid Build Coastguard Worker                            struct pvr_pipeline_layout *pipeline_layout)
1244*61046927SAndroid Build Coastguard Worker {
1245*61046927SAndroid Build Coastguard Worker    rogue_build_ctx *ctx;
1246*61046927SAndroid Build Coastguard Worker 
1247*61046927SAndroid Build Coastguard Worker    ctx = rzalloc_size(NULL, sizeof(*ctx));
1248*61046927SAndroid Build Coastguard Worker    if (!ctx)
1249*61046927SAndroid Build Coastguard Worker       return NULL;
1250*61046927SAndroid Build Coastguard Worker 
1251*61046927SAndroid Build Coastguard Worker    ctx->compiler = compiler;
1252*61046927SAndroid Build Coastguard Worker    ctx->pipeline_layout = pipeline_layout;
1253*61046927SAndroid Build Coastguard Worker 
1254*61046927SAndroid Build Coastguard Worker    /* nir/rogue/binary shaders need to be default-zeroed;
1255*61046927SAndroid Build Coastguard Worker     * this is taken care of by rzalloc_size.
1256*61046927SAndroid Build Coastguard Worker     */
1257*61046927SAndroid Build Coastguard Worker 
1258*61046927SAndroid Build Coastguard Worker    /* Setup non-zero defaults. */
1259*61046927SAndroid Build Coastguard Worker    ctx->stage_data.fs.msaa_mode = ROGUE_MSAA_MODE_PIXEL;
1260*61046927SAndroid Build Coastguard Worker 
1261*61046927SAndroid Build Coastguard Worker    return ctx;
1262*61046927SAndroid Build Coastguard Worker }
1263