xref: /aosp_15_r20/external/mesa3d/src/imagination/rogue/rogue.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2022 Imagination Technologies Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  */
23 
24 #ifndef ROGUE_H
25 #define ROGUE_H
26 
27 /**
28  * \file rogue.h
29  *
30  * \brief Main header.
31  */
32 
33 #define __pvr_address_type pvr_dev_addr_t
34 #define __pvr_get_address(pvr_dev_addr) (pvr_dev_addr).addr
35 /* clang-format off */
36 #define __pvr_make_address(addr_u64) PVR_DEV_ADDR(addr_u64)
37 /* clang-format on */
38 
39 #include "pvr_types.h"
40 #include "csbgen/rogue_hwdefs.h"
41 #include "vulkan/pvr_limits.h"
42 #include "vulkan/pvr_common.h"
43 
44 #include "compiler/nir/nir.h"
45 #include "compiler/shader_enums.h"
46 #include "compiler/spirv/nir_spirv.h"
47 #include "rogue_isa.h"
48 #include "util/bitscan.h"
49 #include "util/bitset.h"
50 #include "util/compiler.h"
51 #include "util/list.h"
52 #include "util/sparse_array.h"
53 #include "util/ralloc.h"
54 #include "util/u_dynarray.h"
55 #include "util/u_math.h"
56 
57 #include <limits.h>
58 #include <stdarg.h>
59 #include <stdbool.h>
60 #include <stdint.h>
61 
62 /* Coefficient registers are typically used in groups of 4. */
63 #define ROGUE_COEFF_ALIGN 4
64 
65 #define ROGUE_REG_UNUSED ~0
66 
67 /* All registers are 32-bit in size. */
68 #define ROGUE_REG_SIZE_BYTES 4
69 
70 /** Rogue register classes. */
71 enum rogue_reg_class {
72    ROGUE_REG_CLASS_INVALID = 0,
73 
74    ROGUE_REG_CLASS_SSA, /** SSA register. */
75 
76    ROGUE_REG_CLASS_TEMP, /** Temp register. */
77    ROGUE_REG_CLASS_COEFF, /** Coefficient register. */
78    ROGUE_REG_CLASS_SHARED, /** Shared register. */
79 
80    ROGUE_REG_CLASS_SPECIAL, /** Special register. */
81    ROGUE_REG_CLASS_INTERNAL, /** Internal register. */
82    ROGUE_REG_CLASS_CONST, /** Constant register. */
83    ROGUE_REG_CLASS_PIXOUT, /** Pixel output register. */
84 
85    ROGUE_REG_CLASS_VTXIN, /** Vertex input register. */
86    ROGUE_REG_CLASS_VTXOUT, /** Vertex output register. */
87 
88    ROGUE_REG_CLASS_COUNT,
89 } PACKED;
90 
91 typedef struct rogue_reg_info {
92    const char *name; /** Human-readable name. */
93    const char *str; /** Register prefix. */
94    unsigned num; /** Number of hardware registers available. */
95    uint64_t supported_io_srcs;
96 } rogue_reg_info;
97 
98 extern const rogue_reg_info rogue_reg_infos[ROGUE_REG_CLASS_COUNT];
99 
rogue_reg_bank_encoding(enum rogue_reg_class class)100 static inline enum reg_bank rogue_reg_bank_encoding(enum rogue_reg_class class)
101 {
102    switch (class) {
103    case ROGUE_REG_CLASS_TEMP:
104       return BANK_TEMP;
105    case ROGUE_REG_CLASS_COEFF:
106       return BANK_COEFF;
107    case ROGUE_REG_CLASS_SHARED:
108       return BANK_SHARED;
109    case ROGUE_REG_CLASS_SPECIAL:
110       return BANK_SPECIAL;
111    case ROGUE_REG_CLASS_VTXIN:
112       return BANK_VTXIN;
113 
114    default:
115       unreachable("Unsupported register class.");
116    }
117 }
118 
119 /* TODO: Do this dynamically by iterating
120  * through regarrays and matching sizes.
121  */
122 enum rogue_regalloc_class {
123    ROGUE_REGALLOC_CLASS_TEMP_1,
124    ROGUE_REGALLOC_CLASS_TEMP_2,
125    ROGUE_REGALLOC_CLASS_TEMP_4,
126 
127    ROGUE_REGALLOC_CLASS_COUNT,
128 };
129 
130 typedef struct rogue_regalloc_info {
131    enum rogue_reg_class class;
132    unsigned stride;
133 } rogue_regalloc_info;
134 
135 extern const rogue_regalloc_info regalloc_info[ROGUE_REGALLOC_CLASS_COUNT];
136 
137 #define ROGUE_ISA_DSTS 2
138 #define ROGUE_ISA_SRCS 6
139 #define ROGUE_ISA_ISSS 6
140 
141 #define ROGUE_ISA_ICACHE_ALIGN 8
142 
143 typedef struct rogue_reg_dst_info {
144    unsigned num_dsts;
145    unsigned bank_bits[ROGUE_ISA_DSTS];
146    unsigned index_bits[ROGUE_ISA_DSTS];
147    unsigned bytes;
148 } rogue_reg_dst_info;
149 
150 #define ROGUE_REG_DST_VARIANTS 5
151 extern const rogue_reg_dst_info rogue_reg_dst_infos[ROGUE_REG_DST_VARIANTS];
152 
153 typedef struct rogue_reg_src_info {
154    unsigned num_srcs;
155    unsigned mux_bits;
156    unsigned bank_bits[ROGUE_ISA_SRCS / 2];
157    unsigned index_bits[ROGUE_ISA_SRCS / 2];
158    unsigned bytes;
159 } rogue_reg_src_info;
160 
161 #define ROGUE_REG_SRC_VARIANTS 8
162 extern const rogue_reg_src_info
163    rogue_reg_lower_src_infos[ROGUE_REG_SRC_VARIANTS];
164 extern const rogue_reg_src_info
165    rogue_reg_upper_src_infos[ROGUE_REG_SRC_VARIANTS];
166 
167 typedef struct rogue_shader rogue_shader;
168 typedef struct rogue_reg rogue_reg;
169 typedef struct rogue_regarray rogue_regarray;
170 
171 /** Rogue register. */
172 typedef struct rogue_reg {
173    rogue_shader *shader; /** Pointer back to shader. */
174    enum rogue_reg_class class; /** Register class. */
175 
176    struct list_head link; /** Link in rogue_shader::regs. */
177    struct list_head writes; /** List of all writes to this register. */
178    struct list_head uses; /** List of all register uses. */
179 
180    rogue_regarray *regarray;
181 
182    bool dirty;
183    uint32_t index; /** Register index. */
184 
185    rogue_reg **cached;
186 } rogue_reg;
187 
188 #define rogue_foreach_reg(reg, shader, class) \
189    list_for_each_entry (rogue_reg, reg, &(shader)->regs[class], link)
190 
191 #define rogue_foreach_reg_safe(reg, shader, class) \
192    list_for_each_entry_safe (rogue_reg, reg, &(shader)->regs[class], link)
193 
194 #define REG_CACHE_KEY_COMPONENT_BITS 3
195 #define REG_CACHE_KEY_INDEX_BITS 28
196 #define REG_CACHE_KEY_VEC_BITS 1
197 
198 struct rogue_reg_cache_key {
199    union {
200       struct {
201          uint32_t component : REG_CACHE_KEY_COMPONENT_BITS;
202          uint32_t index : REG_CACHE_KEY_INDEX_BITS;
203          uint32_t vec : REG_CACHE_KEY_VEC_BITS;
204       } PACKED;
205 
206       uint32_t val;
207    } PACKED;
208 } PACKED;
209 static_assert(sizeof(struct rogue_reg_cache_key) == sizeof(uint32_t),
210               "sizeof(struct rogue_reg_cache_key) != sizeof(uint32_t)");
211 
212 static inline uint32_t
rogue_reg_cache_key(unsigned index,bool vec,unsigned component)213 rogue_reg_cache_key(unsigned index, bool vec, unsigned component)
214 {
215    assert(util_last_bit(component) <= REG_CACHE_KEY_COMPONENT_BITS);
216    assert(!vec || util_last_bit(index) <= REG_CACHE_KEY_INDEX_BITS);
217    assert(vec || util_last_bit(index) <= 32);
218    assert(util_last_bit(vec) <= REG_CACHE_KEY_VEC_BITS);
219 
220    if (!vec)
221       return index;
222 
223    return (struct rogue_reg_cache_key){ .component = component,
224                                         .index = index,
225                                         .vec = vec }
226       .val;
227 }
228 
rogue_reg_is_unused(rogue_reg * reg)229 static inline bool rogue_reg_is_unused(rogue_reg *reg)
230 {
231    return list_is_empty(&reg->uses) && list_is_empty(&reg->writes);
232 }
233 
234 struct rogue_regarray_cache_key {
235    union {
236       struct {
237          uint32_t start_index;
238          enum rogue_reg_class class;
239          uint16_t size;
240          uint8_t __pad;
241       } PACKED;
242 
243       uint64_t val;
244    } PACKED;
245 } PACKED;
246 static_assert(sizeof(struct rogue_regarray_cache_key) == sizeof(uint64_t),
247               "sizeof(struct rogue_regarray_cache_key) != sizeof(uint64_t)");
248 
rogue_regarray_cache_key(unsigned size,enum rogue_reg_class class,uint32_t start_index,bool vec,uint8_t component)249 static inline uint64_t rogue_regarray_cache_key(unsigned size,
250                                                 enum rogue_reg_class class,
251                                                 uint32_t start_index,
252                                                 bool vec,
253                                                 uint8_t component)
254 {
255    uint32_t reg_cache_key = rogue_reg_cache_key(start_index, vec, component);
256    return (struct rogue_regarray_cache_key){ .start_index = reg_cache_key,
257                                              .class = class,
258                                              .size = size }
259       .val;
260 }
261 
262 typedef struct rogue_regarray {
263    struct list_head link; /** Link in rogue_shader::regarrays. */
264    unsigned size; /** Number of registers in the array. */
265    rogue_regarray *parent;
266    struct list_head children; /** List of subarrays with this regarray as their
267                                  parent. */
268    struct list_head child_link; /** Link in rogue_regarray::children. */
269    rogue_reg **regs; /** Registers (allocated array if this is a parent, else
270                         pointer to inside parent regarray->regs). */
271    rogue_regarray **cached;
272 
273    struct list_head writes; /** List of all writes to this register array. */
274    struct list_head uses; /** List of all register array uses. */
275 } rogue_regarray;
276 
277 #define rogue_foreach_regarray(regarray, shader) \
278    list_for_each_entry (rogue_regarray, regarray, &(shader)->regarrays, link)
279 
280 #define rogue_foreach_regarray_safe(regarray, shader) \
281    list_for_each_entry_safe (rogue_regarray,          \
282                              regarray,                \
283                              &(shader)->regarrays,    \
284                              link)
285 
286 #define rogue_foreach_subarray(subarray, regarray) \
287    assert(!regarray->parent);                      \
288    list_for_each_entry (rogue_regarray,            \
289                         subarray,                  \
290                         &(regarray)->children,     \
291                         child_link)
292 
293 #define rogue_foreach_subarray_safe(subarray, regarray) \
294    assert(!regarray->parent);                           \
295    list_for_each_entry_safe (rogue_regarray,            \
296                              subarray,                  \
297                              &(regarray)->children,     \
298                              child_link)
299 
300 typedef struct rogue_instr rogue_instr;
301 
302 typedef struct rogue_regarray_write {
303    rogue_instr *instr;
304    unsigned dst_index;
305    struct list_head link; /** Link in rogue_regarray::writes. */
306 } rogue_regarray_write;
307 
308 #define rogue_foreach_regarray_write(write, regarray) \
309    list_for_each_entry (rogue_regarray_write, write, &(regarray)->writes, link)
310 
311 #define rogue_foreach_regarray_write_safe(write, regarray) \
312    list_for_each_entry_safe (rogue_regarray_write,         \
313                              write,                        \
314                              &(regarray)->writes,          \
315                              link)
316 
317 typedef struct rogue_regarray_use {
318    rogue_instr *instr;
319    unsigned src_index;
320    struct list_head link; /** Link in rogue_regarray::uses. */
321 } rogue_regarray_use;
322 
323 #define rogue_foreach_regarray_use(use, regarray) \
324    list_for_each_entry (rogue_regarray_use, use, &(regarray)->uses, link)
325 
326 #define rogue_foreach_regarray_use_safe(use, regarray) \
327    list_for_each_entry_safe (rogue_regarray_use, use, &(regarray)->uses, link)
328 
329 /** Instruction phases, used in bitset. */
330 enum rogue_instr_phase {
331    /** Main/ALU (and backend) instructions. */
332    ROGUE_INSTR_PHASE_0,
333    ROGUE_INSTR_PHASE_1,
334    ROGUE_INSTR_PHASE_2_PCK,
335    ROGUE_INSTR_PHASE_2_TST,
336    ROGUE_INSTR_PHASE_2_MOV,
337    ROGUE_INSTR_PHASE_BACKEND,
338 
339    ROGUE_INSTR_PHASE_COUNT,
340 
341    /** Control instructions (no co-issuing). */
342    ROGUE_INSTR_PHASE_CTRL = ROGUE_INSTR_PHASE_0,
343 
344    /** Bitwise instructions. */
345    ROGUE_INSTR_PHASE_0_BITMASK = ROGUE_INSTR_PHASE_0,
346    ROGUE_INSTR_PHASE_0_SHIFT1 = ROGUE_INSTR_PHASE_1,
347    ROGUE_INSTR_PHASE_0_COUNT = ROGUE_INSTR_PHASE_2_PCK,
348    ROGUE_INSTR_PHASE_1_LOGICAL = ROGUE_INSTR_PHASE_2_TST,
349    ROGUE_INSTR_PHASE_2_SHIFT2 = ROGUE_INSTR_PHASE_2_MOV,
350    ROGUE_INSTR_PHASE_2_TEST = ROGUE_INSTR_PHASE_BACKEND,
351 
352    ROGUE_INSTR_PHASE_INVALID = ~0,
353 };
354 
355 /* TODO: put into bitscan.h */
356 #define u_foreach_bit64_rev(b, dword)                  \
357    for (uint64_t __dword = (dword), b;                 \
358         ((b) = util_last_bit64(__dword) - 1, __dword); \
359         __dword &= ~(1ull << (b)))
360 
361 #define rogue_foreach_phase_in_set(p, phases) u_foreach_bit64(p, phases)
362 #define rogue_foreach_phase_in_set_rev(p, phases) u_foreach_bit64_rev(p, phases)
363 
364 #define rogue_foreach_mod_in_set(m, mods) u_foreach_bit64(m, mods)
365 
366 /** Rogue basic block. */
367 typedef struct rogue_block {
368    rogue_shader *shader; /** Shader containing this block. */
369    struct list_head instrs; /** Basic block instruction list. */
370    struct list_head link; /** Link in rogue_shader::blocks. */
371 
372    struct list_head uses; /** List of all block uses. */
373 
374    unsigned index; /** Block index. */
375    const char *label; /** Block label. */
376 } rogue_block;
377 
378 #define rogue_foreach_block(block, shader) \
379    list_for_each_entry (rogue_block, block, &(shader)->blocks, link)
380 
381 #define rogue_foreach_block_safe(block, shader) \
382    list_for_each_entry_safe (rogue_block, block, &(shader)->blocks, link)
383 
384 #define rogue_foreach_block_rev(block, shader) \
385    list_for_each_entry_rev (rogue_block, block, &(shader)->blocks, link)
386 
387 #define rogue_foreach_block_safe_rev(block, shader) \
388    list_for_each_entry_safe_rev (rogue_block, block, &(shader)->blocks, link)
389 
390 /** Rogue execution conditions. */
391 enum rogue_exec_cond {
392    ROGUE_EXEC_COND_INVALID = 0,
393 
394    ROGUE_EXEC_COND_PE_TRUE,
395    ROGUE_EXEC_COND_P0_TRUE,
396    ROGUE_EXEC_COND_PE_ANY,
397    ROGUE_EXEC_COND_P0_FALSE,
398 
399    ROGUE_EXEC_COND_COUNT,
400 };
401 
402 extern const char *rogue_exec_cond_str[ROGUE_EXEC_COND_COUNT];
403 
404 /** Rogue instruction type. */
405 enum rogue_instr_type {
406    ROGUE_INSTR_TYPE_INVALID = 0,
407 
408    ROGUE_INSTR_TYPE_ALU, /** ALU instruction. */
409    /* ROGUE_INSTR_TYPE_CMPLX, */ /** TODO: Complex/trig instruction (these take
410                                     up the whole pipeline). */
411    ROGUE_INSTR_TYPE_BACKEND, /** Backend instruction. */
412    ROGUE_INSTR_TYPE_CTRL, /** Control instruction. */
413    ROGUE_INSTR_TYPE_BITWISE, /** Bitwise instruction. */
414    /* ROGUE_INSTR_TYPE_F16SOP, */ /** TODO: F16 sum-of-products instruction. */
415 
416    ROGUE_INSTR_TYPE_COUNT,
417 };
418 
419 extern const char *rogue_instr_type_str[ROGUE_INSTR_TYPE_COUNT];
420 
421 enum rogue_alu {
422    ROGUE_ALU_INVALID = 0,
423 
424    ROGUE_ALU_MAIN,
425    ROGUE_ALU_BITWISE,
426    ROGUE_ALU_CONTROL,
427 
428    ROGUE_ALU_COUNT,
429 };
430 
431 extern const char *const rogue_alu_str[ROGUE_ALU_COUNT];
432 
433 extern const char
434    *const rogue_instr_phase_str[ROGUE_ALU_COUNT][ROGUE_INSTR_PHASE_COUNT];
435 
436 typedef struct rogue_instr_group rogue_instr_group;
437 
438 /** Rogue instruction. */
439 typedef struct rogue_instr {
440    enum rogue_instr_type type; /** Instruction type. */
441 
442    enum rogue_exec_cond exec_cond;
443    unsigned repeat;
444    bool end;
445 
446    union {
447       struct list_head link; /** Link in rogue_block::instrs. */
448       rogue_instr_group *group; /** Instruction group containing this
449                                    instruction. */
450    };
451 
452    rogue_block *block; /** Basic block containing this instruction. */
453 
454    bool group_next; /** Group next instruction with this one. */
455    unsigned index; /** Instruction index. */
456    char *comment; /** Comment string. */
457 } rogue_instr;
458 
rogue_set_instr_group_next(rogue_instr * instr,bool group_next)459 static inline void rogue_set_instr_group_next(rogue_instr *instr,
460                                               bool group_next)
461 {
462    instr->group_next = group_next;
463 }
464 
465 #define rogue_foreach_instr_in_block(instr, block) \
466    list_for_each_entry (rogue_instr, instr, &(block)->instrs, link)
467 
468 #define rogue_foreach_instr_in_block_safe(instr, block) \
469    list_for_each_entry_safe (rogue_instr, instr, &(block)->instrs, link)
470 
471 #define rogue_foreach_instr_in_block_rev(instr, block) \
472    list_for_each_entry_rev (rogue_instr, instr, &(block)->instrs, link)
473 
474 #define rogue_foreach_instr_in_block_safe_rev(instr, block) \
475    list_for_each_entry_safe_rev (rogue_instr, instr, &(block)->instrs, link)
476 
477 #define rogue_foreach_instr_in_shader(instr, shader) \
478    rogue_foreach_block (_block, (shader))            \
479       rogue_foreach_instr_in_block ((instr), _block)
480 
481 #define rogue_foreach_instr_in_shader_safe(instr, shader) \
482    rogue_foreach_block_safe (_block, (shader))            \
483       rogue_foreach_instr_in_block_safe ((instr), _block)
484 
485 #define rogue_foreach_instr_in_shader_rev(instr, shader) \
486    rogue_foreach_block_rev (_block, (shader))            \
487       rogue_foreach_instr_in_block_rev ((instr), _block)
488 
489 #define rogue_foreach_instr_in_shader_safe_rev(instr, shader) \
490    rogue_foreach_block_safe_rev (_block, (shader))            \
491       rogue_foreach_instr_in_block_safe_rev ((instr), _block)
492 
rogue_set_instr_exec_cond(rogue_instr * instr,enum rogue_exec_cond exec_cond)493 static inline void rogue_set_instr_exec_cond(rogue_instr *instr,
494                                              enum rogue_exec_cond exec_cond)
495 {
496    instr->exec_cond = exec_cond;
497 }
498 
rogue_set_instr_repeat(rogue_instr * instr,unsigned repeat)499 static inline void rogue_set_instr_repeat(rogue_instr *instr, unsigned repeat)
500 {
501    instr->repeat = repeat;
502 }
503 
rogue_add_instr_comment(rogue_instr * instr,const char * comment)504 static inline void rogue_add_instr_comment(rogue_instr *instr,
505                                            const char *comment)
506 {
507    if (!instr->comment)
508       instr->comment = ralloc_strdup(instr, comment);
509    else
510       ralloc_asprintf_append(&instr->comment, ", %s", comment);
511 }
512 
rogue_copy_instr_comment(rogue_instr * to,const rogue_instr * from)513 static inline void rogue_copy_instr_comment(rogue_instr *to,
514                                             const rogue_instr *from)
515 {
516    if (!from->comment)
517       return;
518 
519    rogue_add_instr_comment(to, from->comment);
520 }
521 
rogue_merge_instr_comment(rogue_instr * to,const rogue_instr * from,const char * comment)522 static inline void rogue_merge_instr_comment(rogue_instr *to,
523                                              const rogue_instr *from,
524                                              const char *comment)
525 {
526    rogue_copy_instr_comment(to, from);
527    rogue_add_instr_comment(to, comment);
528 }
529 
530 typedef union rogue_imm_t {
531    float f32;
532    int32_t s32;
533    uint32_t u32;
534 } rogue_imm_t;
535 
536 enum rogue_io {
537    ROGUE_IO_INVALID = 0,
538 
539    /* Lower sources. */
540    ROGUE_IO_S0,
541    ROGUE_IO_S1,
542    ROGUE_IO_S2,
543 
544    /* Upper sources. */
545    ROGUE_IO_S3,
546    ROGUE_IO_S4,
547    ROGUE_IO_S5,
548 
549    /* Destinations. */
550    ROGUE_IO_W0,
551    ROGUE_IO_W1,
552 
553    /* Internal selectors. */
554    ROGUE_IO_IS0,
555    ROGUE_IO_IS1,
556    ROGUE_IO_IS2,
557    ROGUE_IO_IS3,
558    ROGUE_IO_IS4,
559    ROGUE_IO_IS5,
560 
561    /* Feedthroughs. */
562    ROGUE_IO_FT0,
563    ROGUE_IO_FT1,
564    ROGUE_IO_FT2,
565    ROGUE_IO_FTE,
566 
567    /* Only used for bitwise instructions. */
568    ROGUE_IO_FT3,
569    ROGUE_IO_FT4,
570    ROGUE_IO_FT5,
571 
572    /* Test output feedthrough. */
573    ROGUE_IO_FTT,
574 
575    /* Predicate register. */
576    ROGUE_IO_P0,
577 
578    /* For optional instruction arguments. */
579    ROGUE_IO_NONE,
580 
581    ROGUE_IO_COUNT,
582 };
583 
rogue_io_is_src(enum rogue_io io)584 static inline bool rogue_io_is_src(enum rogue_io io)
585 {
586    return (io >= ROGUE_IO_S0 && io <= ROGUE_IO_S5);
587 }
588 
rogue_io_is_dst(enum rogue_io io)589 static inline bool rogue_io_is_dst(enum rogue_io io)
590 {
591    return (io >= ROGUE_IO_W0 && io <= ROGUE_IO_W1);
592 }
593 
rogue_io_is_iss(enum rogue_io io)594 static inline bool rogue_io_is_iss(enum rogue_io io)
595 {
596    return (io >= ROGUE_IO_IS0 && io <= ROGUE_IO_IS5);
597 }
598 
rogue_io_is_ft(enum rogue_io io)599 static inline bool rogue_io_is_ft(enum rogue_io io)
600 {
601    return (io >= ROGUE_IO_FT0 && io <= ROGUE_IO_FTE);
602 }
603 
rogue_io_is_none(enum rogue_io io)604 static inline bool rogue_io_is_none(enum rogue_io io)
605 {
606    return io == ROGUE_IO_NONE;
607 }
608 
609 typedef struct rogue_io_info {
610    const char *str;
611 } rogue_io_info;
612 
613 extern const rogue_io_info rogue_io_infos[ROGUE_IO_COUNT];
614 
rogue_io_supported(enum rogue_io io,uint64_t supported_ios)615 static inline bool rogue_io_supported(enum rogue_io io, uint64_t supported_ios)
616 {
617    return !!(BITFIELD64_BIT(io - 1) & supported_ios);
618 }
619 
620 #define ROGUE_DRCS 2
621 
622 typedef struct rogue_drc_trxn {
623    rogue_instr *acquire;
624    rogue_instr *release;
625    struct list_head link; /** Link in rogue_shader::drc_trxns[0/1]. */
626 } rogue_drc_trxn;
627 
628 #define rogue_foreach_drc_trxn(drc_trxn, shader, index) \
629    list_for_each_entry (rogue_drc_trxn,                 \
630                         drc_trxn,                       \
631                         &(shader)->drc_trxns[index],    \
632                         link)
633 
634 #define rogue_foreach_drc_trxn_safe(drc_trxn, shader, index) \
635    list_for_each_entry_safe (rogue_drc_trxn,                 \
636                              drc_trxn,                       \
637                              &(shader)->drc_trxns[index],    \
638                              link)
639 
640 enum rogue_ref_type {
641    ROGUE_REF_TYPE_INVALID = 0,
642 
643    ROGUE_REF_TYPE_VAL, /* Immediate that is not going to be replaced with a
644                           register reference. */
645 
646    ROGUE_REF_TYPE_REG,
647    ROGUE_REF_TYPE_REGARRAY,
648 
649    ROGUE_REF_TYPE_IMM, /* Immediate that is going to be replaced with a register
650                           reference. */
651 
652    ROGUE_REF_TYPE_IO,
653 
654    ROGUE_REF_TYPE_DRC,
655 
656    ROGUE_REF_TYPE_COUNT,
657 };
658 
659 typedef struct rogue_drc {
660    unsigned index;
661    union {
662       rogue_drc_trxn trxn;
663       rogue_drc_trxn *trxn_ptr;
664    };
665 } rogue_drc;
666 
667 typedef struct rogue_imm_use {
668    rogue_instr *instr;
669    unsigned src_index;
670    rogue_imm_t *imm;
671    struct list_head link; /** Link in rogue_shader::imm_uses. */
672 } rogue_imm_use;
673 
674 #define rogue_foreach_imm_use(imm_use, shader) \
675    list_for_each_entry (rogue_imm_use, imm_use, &(shader)->imm_uses, link)
676 
677 #define rogue_foreach_imm_use_safe(imm_use, shader) \
678    list_for_each_entry_safe (rogue_imm_use, imm_use, &(shader)->imm_uses, link)
679 
680 typedef struct rogue_imm {
681    rogue_imm_t imm;
682    rogue_imm_use use;
683 } rogue_imm;
684 
685 typedef struct rogue_ref {
686    enum rogue_ref_type type;
687 
688    union {
689       unsigned val;
690       rogue_imm imm;
691       rogue_reg *reg;
692       rogue_regarray *regarray;
693       enum rogue_io io;
694       rogue_drc drc;
695    };
696 } rogue_ref;
697 
rogue_ref_type_supported(enum rogue_ref_type type,uint64_t supported_types)698 static inline bool rogue_ref_type_supported(enum rogue_ref_type type,
699                                             uint64_t supported_types)
700 {
701    return !!(BITFIELD64_BIT(type - 1) & supported_types);
702 }
703 
704 /**
705  * \brief Returns a reference to a value.
706  *
707  * \param[in] val The value.
708  * \return The reference.
709  */
rogue_ref_val(unsigned val)710 static inline rogue_ref rogue_ref_val(unsigned val)
711 {
712    return (rogue_ref){
713       .type = ROGUE_REF_TYPE_VAL,
714       .val = val,
715    };
716 }
717 
718 /**
719  * \brief Returns a reference to a register.
720  *
721  * \param[in] reg The register.
722  * \return The reference.
723  */
rogue_ref_reg(rogue_reg * reg)724 static inline rogue_ref rogue_ref_reg(rogue_reg *reg)
725 {
726    return (rogue_ref){
727       .type = ROGUE_REF_TYPE_REG,
728       .reg = reg,
729    };
730 }
731 
732 /**
733  * \brief Returns a reference to a register array.
734  *
735  * \param[in] regarray The register array.
736  * \return The reference.
737  */
rogue_ref_regarray(rogue_regarray * regarray)738 static inline rogue_ref rogue_ref_regarray(rogue_regarray *regarray)
739 {
740    return (rogue_ref){
741       .type = ROGUE_REF_TYPE_REGARRAY,
742       .regarray = regarray,
743    };
744 }
745 
rogue_ref_imm(uint32_t imm)746 static inline rogue_ref rogue_ref_imm(uint32_t imm)
747 {
748    return (rogue_ref){
749       .type = ROGUE_REF_TYPE_IMM,
750       .imm.imm.u32 = imm,
751    };
752 }
753 
rogue_ref_io(enum rogue_io io)754 static inline rogue_ref rogue_ref_io(enum rogue_io io)
755 {
756    return (rogue_ref){
757       .type = ROGUE_REF_TYPE_IO,
758       .io = io,
759    };
760 }
761 
rogue_ref_drc(unsigned index)762 static inline rogue_ref rogue_ref_drc(unsigned index)
763 {
764    return (rogue_ref){
765       .type = ROGUE_REF_TYPE_DRC,
766       .drc.index = index,
767    };
768 }
769 
rogue_ref_drc_trxn(unsigned index,rogue_drc_trxn * drc_trxn)770 static inline rogue_ref rogue_ref_drc_trxn(unsigned index,
771                                            rogue_drc_trxn *drc_trxn)
772 {
773    return (rogue_ref){
774       .type = ROGUE_REF_TYPE_DRC,
775       .drc.index = index,
776       .drc.trxn_ptr = drc_trxn,
777    };
778 }
779 
rogue_ref_null(void)780 static inline rogue_ref rogue_ref_null(void)
781 {
782    return (rogue_ref){};
783 }
784 
rogue_ref_is_imm(const rogue_ref * ref)785 static inline bool rogue_ref_is_imm(const rogue_ref *ref)
786 {
787    return ref->type == ROGUE_REF_TYPE_IMM;
788 }
789 
rogue_ref_is_val(const rogue_ref * ref)790 static inline bool rogue_ref_is_val(const rogue_ref *ref)
791 {
792    return ref->type == ROGUE_REF_TYPE_VAL;
793 }
794 
rogue_ref_is_reg(const rogue_ref * ref)795 static inline bool rogue_ref_is_reg(const rogue_ref *ref)
796 {
797    return ref->type == ROGUE_REF_TYPE_REG;
798 }
799 
rogue_ref_is_special_reg(const rogue_ref * ref)800 static inline bool rogue_ref_is_special_reg(const rogue_ref *ref)
801 {
802    return rogue_ref_is_reg(ref) && ref->reg->class == ROGUE_REG_CLASS_SPECIAL;
803 }
804 
rogue_ref_is_regarray(const rogue_ref * ref)805 static inline bool rogue_ref_is_regarray(const rogue_ref *ref)
806 {
807    return ref->type == ROGUE_REF_TYPE_REGARRAY;
808 }
809 
rogue_ref_is_reg_or_regarray(const rogue_ref * ref)810 static inline bool rogue_ref_is_reg_or_regarray(const rogue_ref *ref)
811 {
812    return rogue_ref_is_reg(ref) || rogue_ref_is_regarray(ref);
813 }
814 
rogue_ref_is_io(const rogue_ref * ref)815 static inline bool rogue_ref_is_io(const rogue_ref *ref)
816 {
817    return ref->type == ROGUE_REF_TYPE_IO;
818 }
819 
rogue_ref_is_drc(const rogue_ref * ref)820 static inline bool rogue_ref_is_drc(const rogue_ref *ref)
821 {
822    return ref->type == ROGUE_REF_TYPE_DRC;
823 }
824 
rogue_ref_is_null(const rogue_ref * ref)825 static inline bool rogue_ref_is_null(const rogue_ref *ref)
826 {
827    return ref->type == ROGUE_REF_TYPE_INVALID;
828 }
829 
rogue_ref_get_reg_class(const rogue_ref * ref)830 static inline enum rogue_reg_class rogue_ref_get_reg_class(const rogue_ref *ref)
831 {
832    if (rogue_ref_is_regarray(ref))
833       return ref->regarray->regs[0]->class;
834    else if (rogue_ref_is_reg(ref))
835       return ref->reg->class;
836    unreachable("Ref is not a reg/regarray.");
837 }
838 
rogue_ref_get_reg_index(const rogue_ref * ref)839 static inline unsigned rogue_ref_get_reg_index(const rogue_ref *ref)
840 {
841    if (rogue_ref_is_regarray(ref))
842       return ref->regarray->regs[0]->index;
843    else if (rogue_ref_is_reg(ref))
844       return ref->reg->index;
845    unreachable("Ref is not a reg/regarray.");
846 }
847 
rogue_ref_get_regarray_size(const rogue_ref * ref)848 static inline unsigned rogue_ref_get_regarray_size(const rogue_ref *ref)
849 {
850    if (rogue_ref_is_regarray(ref))
851       return ref->regarray->size;
852    unreachable("Ref is not a regarray.");
853 }
854 
855 #define ROGUE_INTERNAL0_OFFSET 36
856 #define ROGUE_INTERNAL_GROUP 8
857 
858 #define ROGUE_PIXOUT0_OFFSET 32
859 #define ROGUE_PIXOUT4_OFFSET 164
860 #define ROGUE_PIXOUT_GROUP 4
861 
rogue_ref_is_pixout(rogue_ref * ref)862 static inline bool rogue_ref_is_pixout(rogue_ref *ref)
863 {
864    enum rogue_reg_class class;
865    unsigned index;
866 
867    if (!rogue_ref_is_reg(ref) && !rogue_ref_is_regarray(ref))
868       return false;
869 
870    class = rogue_ref_get_reg_class(ref);
871 
872    if (class == ROGUE_REG_CLASS_PIXOUT)
873       return true;
874    else if (class != ROGUE_REG_CLASS_SPECIAL)
875       return false;
876 
877    index = rogue_ref_get_reg_index(ref);
878 
879    return (index >= ROGUE_PIXOUT0_OFFSET &&
880            index < (ROGUE_PIXOUT0_OFFSET + ROGUE_PIXOUT_GROUP)) ||
881           (index >= ROGUE_PIXOUT4_OFFSET &&
882            index < (ROGUE_PIXOUT4_OFFSET + ROGUE_PIXOUT_GROUP));
883 }
884 
rogue_ref_get_io(const rogue_ref * ref)885 static inline enum rogue_io rogue_ref_get_io(const rogue_ref *ref)
886 {
887    assert(rogue_ref_is_io(ref));
888    return ref->io;
889 }
890 
rogue_ref_is_io_p0(const rogue_ref * ref)891 static inline bool rogue_ref_is_io_p0(const rogue_ref *ref)
892 {
893    return rogue_ref_get_io(ref) == ROGUE_IO_P0;
894 }
895 
rogue_ref_is_io_ftt(const rogue_ref * ref)896 static inline bool rogue_ref_is_io_ftt(const rogue_ref *ref)
897 {
898    return rogue_ref_get_io(ref) == ROGUE_IO_FTT;
899 }
900 
rogue_ref_is_io_none(const rogue_ref * ref)901 static inline bool rogue_ref_is_io_none(const rogue_ref *ref)
902 {
903    /* Special case - never assert. */
904    if (!rogue_ref_is_io(ref))
905       return false;
906 
907    return rogue_ref_get_io(ref) == ROGUE_IO_NONE;
908 }
909 
rogue_ref_get_io_src_index(const rogue_ref * ref)910 static inline unsigned rogue_ref_get_io_src_index(const rogue_ref *ref)
911 {
912    return rogue_ref_get_io(ref) - ROGUE_IO_S0;
913 }
914 
rogue_ref_get_drc_index(const rogue_ref * ref)915 static inline unsigned rogue_ref_get_drc_index(const rogue_ref *ref)
916 {
917    assert(rogue_ref_is_drc(ref));
918    return ref->drc.index;
919 }
920 
rogue_ref_get_drc(rogue_ref * ref)921 static inline rogue_drc *rogue_ref_get_drc(rogue_ref *ref)
922 {
923    assert(rogue_ref_is_drc(ref));
924    return &ref->drc;
925 }
926 
rogue_ref_get_val(const rogue_ref * ref)927 static inline unsigned rogue_ref_get_val(const rogue_ref *ref)
928 {
929    assert(rogue_ref_is_val(ref));
930    return ref->val;
931 }
932 
rogue_ref_get_imm(rogue_ref * ref)933 static inline rogue_imm *rogue_ref_get_imm(rogue_ref *ref)
934 {
935    assert(rogue_ref_is_imm(ref));
936    return &ref->imm;
937 }
938 
rogue_refs_equal(rogue_ref * a,rogue_ref * b)939 static inline bool rogue_refs_equal(rogue_ref *a, rogue_ref *b)
940 {
941    if (a->type != b->type)
942       return false;
943 
944    switch (a->type) {
945    case ROGUE_REF_TYPE_VAL:
946       return a->val == b->val;
947 
948    case ROGUE_REF_TYPE_REG:
949       return a->reg == b->reg;
950 
951    case ROGUE_REF_TYPE_REGARRAY:
952       return a->regarray == b->regarray;
953 
954    case ROGUE_REF_TYPE_IMM:
955       return a->imm.imm.u32 == b->imm.imm.u32;
956 
957    case ROGUE_REF_TYPE_IO:
958       return a->io == b->io;
959 
960    case ROGUE_REF_TYPE_DRC:
961       return a->drc.index == b->drc.index;
962 
963    default:
964       break;
965    }
966 
967    return false;
968 }
969 
970 typedef struct rogue_instr_dst {
971    rogue_ref ref;
972    uint64_t mod;
973    unsigned index;
974 } rogue_instr_dst;
975 
976 typedef struct rogue_instr_src {
977    rogue_ref ref;
978    uint64_t mod;
979    unsigned index;
980 } rogue_instr_src;
981 
rogue_instr_dst_src_equal(rogue_instr_dst * dst,rogue_instr_src * src)982 static inline bool rogue_instr_dst_src_equal(rogue_instr_dst *dst,
983                                              rogue_instr_src *src)
984 {
985    /* TODO: Take modifiers into account. */
986    if (dst->mod || src->mod)
987       return false;
988 
989    return rogue_refs_equal(&dst->ref, &src->ref);
990 }
991 
992 typedef struct rogue_reg_write {
993    rogue_instr *instr;
994    unsigned dst_index;
995    struct list_head link; /** Link in rogue_reg::writes. */
996 } rogue_reg_write;
997 
998 #define rogue_foreach_reg_write(write, reg) \
999    list_for_each_entry (rogue_reg_write, write, &(reg)->writes, link)
1000 
1001 #define rogue_foreach_reg_write_safe(write, reg) \
1002    list_for_each_entry_safe (rogue_reg_write, write, &(reg)->writes, link)
1003 
1004 typedef struct rogue_reg_use {
1005    rogue_instr *instr;
1006    unsigned src_index;
1007    struct list_head link; /** Link in rogue_reg::uses. */
1008 } rogue_reg_use;
1009 
1010 #define rogue_foreach_reg_use(use, reg) \
1011    list_for_each_entry (rogue_reg_use, use, &(reg)->uses, link)
1012 
1013 #define rogue_foreach_reg_use_safe(use, reg) \
1014    list_for_each_entry_safe (rogue_reg_use, use, &(reg)->uses, link)
1015 
1016 typedef union rogue_dst_write {
1017    rogue_reg_write reg;
1018    rogue_regarray_write regarray;
1019 } rogue_dst_write;
1020 
1021 typedef union rogue_src_use {
1022    rogue_reg_use reg;
1023    rogue_regarray_use regarray;
1024 } rogue_src_use;
1025 
1026 typedef struct rogue_block_use {
1027    rogue_instr *instr;
1028    struct list_head link; /** Link in rogue_block::uses. */
1029 } rogue_block_use;
1030 
1031 #define rogue_foreach_block_use(use, block) \
1032    list_for_each_entry (rogue_block_use, use, &(block)->uses, link)
1033 
1034 #define rogue_foreach_block_use_safe(use, block) \
1035    list_for_each_entry_safe (rogue_block_use, use, &(block)->uses, link)
1036 
1037 /** Rogue ALU instruction operations. */
1038 enum rogue_alu_op {
1039    ROGUE_ALU_OP_INVALID = 0,
1040 
1041    /* Real instructions. */
1042 
1043    ROGUE_ALU_OP_MBYP,
1044 
1045    ROGUE_ALU_OP_FADD,
1046    ROGUE_ALU_OP_FMUL,
1047    ROGUE_ALU_OP_FMAD,
1048 
1049    ROGUE_ALU_OP_ADD64,
1050 
1051    ROGUE_ALU_OP_TST,
1052    ROGUE_ALU_OP_MOVC,
1053 
1054    ROGUE_ALU_OP_PCK_U8888,
1055 
1056    /* Pseudo-instructions. */
1057    ROGUE_ALU_OP_PSEUDO,
1058    ROGUE_ALU_OP_MOV = ROGUE_ALU_OP_PSEUDO,
1059    ROGUE_ALU_OP_CMOV, /** Conditional move. */
1060 
1061    ROGUE_ALU_OP_FABS,
1062    ROGUE_ALU_OP_FNEG,
1063    ROGUE_ALU_OP_FNABS,
1064 
1065    ROGUE_ALU_OP_FMAX,
1066    ROGUE_ALU_OP_FMIN,
1067 
1068    ROGUE_ALU_OP_COUNT,
1069 };
1070 
1071 enum rogue_alu_op_mod {
1072    /* In order of priority */
1073    ROGUE_ALU_OP_MOD_LP, /* Low-precision modifier (force 13 lsbs of all sources
1074                            to zero before op, and of result after op). */
1075    ROGUE_ALU_OP_MOD_SAT, /* Saturate output. */
1076 
1077    ROGUE_ALU_OP_MOD_SCALE, /* Scale to [0, 1]. */
1078    ROGUE_ALU_OP_MOD_ROUNDZERO, /* Round to zero. */
1079 
1080    ROGUE_ALU_OP_MOD_Z, /** Test == 0. */
1081    ROGUE_ALU_OP_MOD_GZ, /** Test > 0. */
1082    ROGUE_ALU_OP_MOD_GEZ, /** Test >= 0. */
1083    ROGUE_ALU_OP_MOD_C, /** Test integer carry-out. */
1084    ROGUE_ALU_OP_MOD_E, /** Test a == b. */
1085    ROGUE_ALU_OP_MOD_G, /** Test a > b. */
1086    ROGUE_ALU_OP_MOD_GE, /** Test a >= b. */
1087    ROGUE_ALU_OP_MOD_NE, /** Test a != b. */
1088    ROGUE_ALU_OP_MOD_L, /** Test a < b. */
1089    ROGUE_ALU_OP_MOD_LE, /** Test a <= b. */
1090 
1091    ROGUE_ALU_OP_MOD_F32,
1092    ROGUE_ALU_OP_MOD_U16,
1093    ROGUE_ALU_OP_MOD_S16,
1094    ROGUE_ALU_OP_MOD_U8,
1095    ROGUE_ALU_OP_MOD_S8,
1096    ROGUE_ALU_OP_MOD_U32,
1097    ROGUE_ALU_OP_MOD_S32,
1098 
1099    ROGUE_ALU_OP_MOD_COUNT,
1100 };
1101 
1102 typedef struct rogue_alu_op_mod_info {
1103    const char *str;
1104    uint64_t exclude; /* Can't use this op mod with any of these. */
1105    uint64_t require; /* Required op mods for this to be used (OR). */
1106 } rogue_alu_op_mod_info;
1107 
1108 extern const rogue_alu_op_mod_info
1109    rogue_alu_op_mod_infos[ROGUE_ALU_OP_MOD_COUNT];
1110 
rogue_mods_supported(uint64_t mods,uint64_t supported_mods)1111 static inline bool rogue_mods_supported(uint64_t mods, uint64_t supported_mods)
1112 {
1113    return !(mods & ~supported_mods);
1114 }
1115 
1116 enum rogue_alu_dst_mod {
1117    ROGUE_ALU_DST_MOD_E0,
1118    ROGUE_ALU_DST_MOD_E1,
1119    ROGUE_ALU_DST_MOD_E2,
1120    ROGUE_ALU_DST_MOD_E3,
1121 
1122    ROGUE_ALU_DST_MOD_COUNT,
1123 };
1124 
1125 typedef struct rogue_alu_dst_mod_info {
1126    const char *str;
1127 } rogue_alu_dst_mod_info;
1128 
1129 extern const rogue_alu_dst_mod_info
1130    rogue_alu_dst_mod_infos[ROGUE_ALU_DST_MOD_COUNT];
1131 
1132 enum rogue_alu_src_mod {
1133    /* In order of priority, i.e. if all NEG, ABS, and FLR are all set, FLR will
1134       happen first, then ABS, then NEG. */
1135    ROGUE_ALU_SRC_MOD_FLR,
1136    ROGUE_ALU_SRC_MOD_ABS,
1137    ROGUE_ALU_SRC_MOD_NEG,
1138 
1139    ROGUE_ALU_SRC_MOD_E0,
1140    ROGUE_ALU_SRC_MOD_E1,
1141    ROGUE_ALU_SRC_MOD_E2,
1142    ROGUE_ALU_SRC_MOD_E3,
1143 
1144    ROGUE_ALU_SRC_MOD_COUNT,
1145 };
1146 
1147 typedef struct rogue_alu_src_mod_info {
1148    const char *str;
1149 } rogue_alu_src_mod_info;
1150 
1151 extern const rogue_alu_src_mod_info
1152    rogue_alu_src_mod_infos[ROGUE_ALU_SRC_MOD_COUNT];
1153 
1154 enum rogue_ctrl_op {
1155    ROGUE_CTRL_OP_INVALID = 0,
1156 
1157    /* Real instructions. */
1158    ROGUE_CTRL_OP_NOP,
1159    ROGUE_CTRL_OP_WOP,
1160    ROGUE_CTRL_OP_BR, /* Branch: relative (to block). */
1161    ROGUE_CTRL_OP_BA, /* Branch: absolute (to address). */
1162    ROGUE_CTRL_OP_WDF,
1163 
1164    /* Pseudo-instructions. */
1165    ROGUE_CTRL_OP_PSEUDO,
1166    ROGUE_CTRL_OP_END = ROGUE_CTRL_OP_PSEUDO,
1167 
1168    ROGUE_CTRL_OP_COUNT,
1169 };
1170 
1171 enum rogue_ctrl_op_mod {
1172    /* In order of priority */
1173    ROGUE_CTRL_OP_MOD_LINK,
1174 
1175    ROGUE_CTRL_OP_MOD_ALLINST,
1176    ROGUE_CTRL_OP_MOD_ANYINST,
1177 
1178    ROGUE_CTRL_OP_MOD_END,
1179 
1180    ROGUE_CTRL_OP_MOD_COUNT,
1181 };
1182 
1183 typedef struct rogue_ctrl_op_mod_info {
1184    const char *str;
1185    uint64_t exclude; /* Can't use this op mod with any of these. */
1186    uint64_t require; /* Required op mods for this to be used (OR). */
1187 } rogue_ctrl_op_mod_info;
1188 
1189 extern const rogue_ctrl_op_mod_info
1190    rogue_ctrl_op_mod_infos[ROGUE_CTRL_OP_MOD_COUNT];
1191 
1192 #define ROGUE_CTRL_OP_MAX_SRCS 7
1193 #define ROGUE_CTRL_OP_MAX_DSTS 2
1194 
1195 typedef struct rogue_ctrl_op_info {
1196    const char *str;
1197 
1198    bool has_target; /* Has a block as a target. */
1199    bool ends_block; /* Can be the instruction at the end of a block. */
1200    bool has_srcs; /* Has encodable sources. */
1201    bool has_dsts; /* Has encodable destinations. */
1202 
1203    unsigned num_dsts;
1204    unsigned num_srcs;
1205 
1206    uint64_t supported_op_mods;
1207    uint64_t supported_dst_mods[ROGUE_CTRL_OP_MAX_DSTS];
1208    uint64_t supported_src_mods[ROGUE_CTRL_OP_MAX_SRCS];
1209 
1210    uint64_t supported_dst_types[ROGUE_CTRL_OP_MAX_DSTS];
1211    uint64_t supported_src_types[ROGUE_CTRL_OP_MAX_SRCS];
1212 
1213    unsigned dst_stride[ROGUE_CTRL_OP_MAX_DSTS];
1214    unsigned src_stride[ROGUE_CTRL_OP_MAX_SRCS];
1215 
1216    uint64_t dst_repeat_mask;
1217    uint64_t src_repeat_mask;
1218 } rogue_ctrl_op_info;
1219 
1220 extern const rogue_ctrl_op_info rogue_ctrl_op_infos[ROGUE_CTRL_OP_COUNT];
1221 
rogue_ctrl_op_has_srcs(enum rogue_ctrl_op op)1222 static inline bool rogue_ctrl_op_has_srcs(enum rogue_ctrl_op op)
1223 {
1224    const rogue_ctrl_op_info *info = &rogue_ctrl_op_infos[op];
1225    return info->has_srcs;
1226 }
1227 
rogue_ctrl_op_has_dsts(enum rogue_ctrl_op op)1228 static inline bool rogue_ctrl_op_has_dsts(enum rogue_ctrl_op op)
1229 {
1230    const rogue_ctrl_op_info *info = &rogue_ctrl_op_infos[op];
1231    return info->has_dsts;
1232 }
1233 
1234 /* ALU instructions have at most 5 sources. */
1235 #define ROGUE_ALU_OP_MAX_SRCS 5
1236 #define ROGUE_ALU_OP_MAX_DSTS 3
1237 
1238 typedef struct rogue_alu_io_info {
1239    enum rogue_io dst[ROGUE_ALU_OP_MAX_DSTS];
1240    enum rogue_io src[ROGUE_ALU_OP_MAX_SRCS];
1241 } rogue_alu_io_info;
1242 
1243 /** Rogue ALU instruction operation info. */
1244 typedef struct rogue_alu_op_info {
1245    const char *str;
1246 
1247    unsigned num_dsts;
1248    unsigned num_srcs;
1249 
1250    uint64_t supported_phases;
1251    rogue_alu_io_info phase_io[ROGUE_INSTR_PHASE_COUNT];
1252 
1253    uint64_t supported_op_mods;
1254    uint64_t supported_dst_mods[ROGUE_ALU_OP_MAX_DSTS];
1255    uint64_t supported_src_mods[ROGUE_ALU_OP_MAX_SRCS];
1256 
1257    uint64_t supported_dst_types[ROGUE_ALU_OP_MAX_DSTS];
1258    uint64_t supported_src_types[ROGUE_ALU_OP_MAX_SRCS];
1259 
1260    unsigned dst_stride[ROGUE_CTRL_OP_MAX_DSTS];
1261    unsigned src_stride[ROGUE_CTRL_OP_MAX_SRCS];
1262 
1263    uint64_t dst_repeat_mask;
1264    uint64_t src_repeat_mask;
1265 } rogue_alu_op_info;
1266 
1267 extern const rogue_alu_op_info rogue_alu_op_infos[ROGUE_ALU_OP_COUNT];
1268 
1269 /** Rogue ALU instruction. */
1270 typedef struct rogue_alu_instr {
1271    rogue_instr instr;
1272 
1273    enum rogue_alu_op op;
1274 
1275    uint64_t mod;
1276 
1277    rogue_instr_dst dst[ROGUE_ALU_OP_MAX_DSTS];
1278    rogue_dst_write dst_write[ROGUE_ALU_OP_MAX_DSTS];
1279 
1280    rogue_instr_src src[ROGUE_ALU_OP_MAX_SRCS];
1281    rogue_src_use src_use[ROGUE_ALU_OP_MAX_SRCS];
1282 } rogue_alu_instr;
1283 
rogue_set_alu_op_mod(rogue_alu_instr * alu,enum rogue_alu_op_mod mod)1284 static inline void rogue_set_alu_op_mod(rogue_alu_instr *alu,
1285                                         enum rogue_alu_op_mod mod)
1286 {
1287    alu->mod |= BITFIELD64_BIT(mod);
1288 }
1289 
rogue_alu_op_mod_is_set(const rogue_alu_instr * alu,enum rogue_alu_op_mod mod)1290 static inline bool rogue_alu_op_mod_is_set(const rogue_alu_instr *alu,
1291                                            enum rogue_alu_op_mod mod)
1292 {
1293    return !!(alu->mod & BITFIELD64_BIT(mod));
1294 }
1295 
rogue_set_alu_dst_mod(rogue_alu_instr * alu,unsigned dst_index,enum rogue_alu_dst_mod mod)1296 static inline void rogue_set_alu_dst_mod(rogue_alu_instr *alu,
1297                                          unsigned dst_index,
1298                                          enum rogue_alu_dst_mod mod)
1299 {
1300    alu->dst[dst_index].mod |= BITFIELD64_BIT(mod);
1301 }
1302 
rogue_alu_dst_mod_is_set(const rogue_alu_instr * alu,unsigned dst_index,enum rogue_alu_dst_mod mod)1303 static inline bool rogue_alu_dst_mod_is_set(const rogue_alu_instr *alu,
1304                                             unsigned dst_index,
1305                                             enum rogue_alu_dst_mod mod)
1306 {
1307    return !!(alu->dst[dst_index].mod & BITFIELD64_BIT(mod));
1308 }
1309 
rogue_set_alu_src_mod(rogue_alu_instr * alu,unsigned src_index,enum rogue_alu_src_mod mod)1310 static inline void rogue_set_alu_src_mod(rogue_alu_instr *alu,
1311                                          unsigned src_index,
1312                                          enum rogue_alu_src_mod mod)
1313 {
1314    alu->src[src_index].mod |= BITFIELD64_BIT(mod);
1315 }
1316 
rogue_alu_src_mod_is_set(const rogue_alu_instr * alu,unsigned src_index,enum rogue_alu_src_mod mod)1317 static inline bool rogue_alu_src_mod_is_set(const rogue_alu_instr *alu,
1318                                             unsigned src_index,
1319                                             enum rogue_alu_src_mod mod)
1320 {
1321    return !!(alu->src[src_index].mod & BITFIELD64_BIT(mod));
1322 }
1323 
1324 /**
1325  * \brief Allocates and initializes a new ALU instruction.
1326  *
1327  * \param[in] block The block which will contain the instruction.
1328  * \param[in] op The ALU instruction operation.
1329  * \return The new instruction.
1330  */
1331 rogue_alu_instr *rogue_alu_instr_create(rogue_block *block,
1332                                         enum rogue_alu_op op);
1333 
1334 #define ROGUE_BACKEND_OP_MAX_SRCS 6
1335 #define ROGUE_BACKEND_OP_MAX_DSTS 2
1336 
1337 enum rogue_backend_op {
1338    ROGUE_BACKEND_OP_INVALID = 0,
1339 
1340    ROGUE_BACKEND_OP_UVSW_WRITE,
1341    ROGUE_BACKEND_OP_UVSW_EMIT,
1342    /* ROGUE_BACKEND_OP_UVSW_CUT, */
1343    /* ROGUE_BACKEND_OP_UVSW_EMITTHENCUT, */
1344    ROGUE_BACKEND_OP_UVSW_ENDTASK,
1345    ROGUE_BACKEND_OP_UVSW_EMITTHENENDTASK,
1346    ROGUE_BACKEND_OP_UVSW_WRITETHENEMITTHENENDTASK,
1347 
1348    ROGUE_BACKEND_OP_IDF,
1349 
1350    ROGUE_BACKEND_OP_EMITPIX,
1351 
1352    ROGUE_BACKEND_OP_LD,
1353    ROGUE_BACKEND_OP_ST,
1354 
1355    ROGUE_BACKEND_OP_FITR_PIXEL,
1356    /* ROGUE_BACKEND_OP_SAMPLE, */
1357    /* ROGUE_BACKEND_OP_CENTROID, */
1358    ROGUE_BACKEND_OP_FITRP_PIXEL,
1359    /* ROGUE_BACKEND_OP_FITRP_SAMPLE, */
1360    /* ROGUE_BACKEND_OP_FITRP_CENTROID, */
1361 
1362    ROGUE_BACKEND_OP_SMP1D,
1363    ROGUE_BACKEND_OP_SMP2D,
1364    ROGUE_BACKEND_OP_SMP3D,
1365 
1366    ROGUE_BACKEND_OP_PSEUDO,
1367    ROGUE_BACKEND_OP_COUNT = ROGUE_BACKEND_OP_PSEUDO,
1368 };
1369 
1370 typedef struct rogue_backend_io_info {
1371    enum rogue_io dst[ROGUE_BACKEND_OP_MAX_DSTS];
1372    enum rogue_io src[ROGUE_BACKEND_OP_MAX_SRCS];
1373 } rogue_backend_io_info;
1374 
1375 typedef struct rogue_backend_op_info {
1376    const char *str;
1377 
1378    unsigned num_dsts;
1379    unsigned num_srcs;
1380 
1381    /* supported_phases not needed as it's always going to be in the backend
1382     * phase. */
1383    rogue_backend_io_info phase_io;
1384 
1385    uint64_t supported_op_mods;
1386    uint64_t supported_dst_mods[ROGUE_BACKEND_OP_MAX_DSTS];
1387    uint64_t supported_src_mods[ROGUE_BACKEND_OP_MAX_SRCS];
1388 
1389    uint64_t supported_dst_types[ROGUE_BACKEND_OP_MAX_DSTS];
1390    uint64_t supported_src_types[ROGUE_BACKEND_OP_MAX_SRCS];
1391 
1392    unsigned dst_stride[ROGUE_CTRL_OP_MAX_DSTS];
1393    unsigned src_stride[ROGUE_CTRL_OP_MAX_SRCS];
1394 
1395    uint64_t dst_repeat_mask;
1396    uint64_t src_repeat_mask;
1397 } rogue_backend_op_info;
1398 
1399 extern const rogue_backend_op_info
1400    rogue_backend_op_infos[ROGUE_BACKEND_OP_COUNT];
1401 
1402 enum rogue_backend_op_mod {
1403    /* In order of priority */
1404    ROGUE_BACKEND_OP_MOD_PROJ, /* Projection (send T co-ordinate). */
1405    ROGUE_BACKEND_OP_MOD_FCNORM, /* Fixed-point texture data (convert to float).
1406                                  */
1407    ROGUE_BACKEND_OP_MOD_NNCOORDS, /* Non-normalised co-ordinates. */
1408 
1409    ROGUE_BACKEND_OP_MOD_BIAS, /* LOD mode: bias. */
1410    ROGUE_BACKEND_OP_MOD_REPLACE, /* LOD mode: replace. */
1411    ROGUE_BACKEND_OP_MOD_GRADIENT, /* LOD mode: gradient. */
1412 
1413    ROGUE_BACKEND_OP_MOD_PPLOD, /* Per-pixel LOD. */
1414    ROGUE_BACKEND_OP_MOD_TAO, /* Texture address override. */
1415    ROGUE_BACKEND_OP_MOD_SOO, /* Sample offset supplied. */
1416    ROGUE_BACKEND_OP_MOD_SNO, /* Sample number supplied. */
1417    ROGUE_BACKEND_OP_MOD_WRT, /* SMP write. */
1418 
1419    ROGUE_BACKEND_OP_MOD_DATA, /* Sample bypass mode: data. */
1420    ROGUE_BACKEND_OP_MOD_INFO, /* Sample bypass mode: info. */
1421    ROGUE_BACKEND_OP_MOD_BOTH, /* Sample bypass mode: both. */
1422 
1423    ROGUE_BACKEND_OP_MOD_TILED, /* Tiled LD/ST. */
1424 
1425    ROGUE_BACKEND_OP_MOD_BYPASS, /* MCU cache mode (read): bypass. */
1426    ROGUE_BACKEND_OP_MOD_FORCELINEFILL, /* MCU cache mode (read): force line
1427                                         * fill.
1428                                         */
1429 
1430    ROGUE_BACKEND_OP_MOD_WRITETHROUGH, /* MCU cache mode (write): write through
1431                                        * L1 & SLC.
1432                                        */
1433    ROGUE_BACKEND_OP_MOD_WRITEBACK, /* MCU cache mode (write): write back. */
1434    ROGUE_BACKEND_OP_MOD_LAZYWRITEBACK, /* MCU cache mode (write): lazy write
1435                                         * back.
1436                                         */
1437 
1438    ROGUE_BACKEND_OP_MOD_SLCBYPASS, /* SLC cache mode: bypass.*/
1439    ROGUE_BACKEND_OP_MOD_SLCWRITEBACK, /* SLC cache mode: write back */
1440    ROGUE_BACKEND_OP_MOD_SLCWRITETHROUGH, /* SLC cache mode: write through. */
1441    ROGUE_BACKEND_OP_MOD_SLCNOALLOC, /* SLC cache mode: cached reads/no
1442                                      * allocation on miss.
1443                                      */
1444 
1445    ROGUE_BACKEND_OP_MOD_ARRAY, /* Sample data contains array index/texture
1446                                 * arrays enabled.
1447                                 */
1448    ROGUE_BACKEND_OP_MOD_INTEGER, /* Integer co-ordinates and sample data. */
1449    ROGUE_BACKEND_OP_MOD_SCHEDSWAP, /* Deschedule slot after instruction. */
1450 
1451    ROGUE_BACKEND_OP_MOD_F16, /* Return packed F16 data. */
1452 
1453    ROGUE_BACKEND_OP_MOD_SAT, /* Saturate output. */
1454 
1455    ROGUE_BACKEND_OP_MOD_FREEP, /* Free partition. */
1456 
1457    ROGUE_BACKEND_OP_MOD_COUNT,
1458 };
1459 
1460 typedef struct rogue_backend_op_mod_info {
1461    const char *str;
1462    uint64_t exclude; /* Can't use this op mod with any of these. */
1463    uint64_t require; /* Required op mods for this to be used (OR). */
1464 } rogue_backend_op_mod_info;
1465 
1466 extern const rogue_backend_op_mod_info
1467    rogue_backend_op_mod_infos[ROGUE_BACKEND_OP_MOD_COUNT];
1468 
1469 typedef struct rogue_backend_instr {
1470    rogue_instr instr;
1471 
1472    enum rogue_backend_op op;
1473 
1474    uint64_t mod;
1475 
1476    /* Backend instructions don't have source/dest modifiers. */
1477 
1478    rogue_instr_dst dst[ROGUE_BACKEND_OP_MAX_DSTS];
1479    rogue_dst_write dst_write[ROGUE_BACKEND_OP_MAX_DSTS];
1480 
1481    rogue_instr_src src[ROGUE_BACKEND_OP_MAX_SRCS];
1482    rogue_src_use src_use[ROGUE_BACKEND_OP_MAX_SRCS];
1483 } rogue_backend_instr;
1484 
rogue_set_backend_op_mod(rogue_backend_instr * backend,enum rogue_backend_op_mod mod)1485 static inline void rogue_set_backend_op_mod(rogue_backend_instr *backend,
1486                                             enum rogue_backend_op_mod mod)
1487 {
1488    backend->mod |= BITFIELD64_BIT(mod);
1489 }
1490 
1491 static inline bool
rogue_backend_op_mod_is_set(const rogue_backend_instr * backend,enum rogue_backend_op_mod mod)1492 rogue_backend_op_mod_is_set(const rogue_backend_instr *backend,
1493                             enum rogue_backend_op_mod mod)
1494 {
1495    return !!(backend->mod & BITFIELD64_BIT(mod));
1496 }
1497 
1498 rogue_backend_instr *rogue_backend_instr_create(rogue_block *block,
1499                                                 enum rogue_backend_op op);
1500 
1501 typedef struct rogue_ctrl_instr {
1502    rogue_instr instr;
1503 
1504    enum rogue_ctrl_op op;
1505 
1506    uint64_t mod;
1507 
1508    /* Control instructions don't have source/dest modifiers. */
1509 
1510    rogue_instr_dst dst[ROGUE_CTRL_OP_MAX_DSTS];
1511    rogue_dst_write dst_write[ROGUE_CTRL_OP_MAX_DSTS];
1512 
1513    rogue_instr_src src[ROGUE_CTRL_OP_MAX_SRCS];
1514    rogue_src_use src_use[ROGUE_CTRL_OP_MAX_SRCS];
1515 
1516    rogue_block *target_block;
1517    rogue_block_use block_use;
1518 } rogue_ctrl_instr;
1519 
rogue_set_ctrl_op_mod(rogue_ctrl_instr * ctrl,enum rogue_ctrl_op_mod mod)1520 static inline void rogue_set_ctrl_op_mod(rogue_ctrl_instr *ctrl,
1521                                          enum rogue_ctrl_op_mod mod)
1522 {
1523    ctrl->mod |= BITFIELD64_BIT(mod);
1524 }
1525 
rogue_ctrl_op_mod_is_set(const rogue_ctrl_instr * ctrl,enum rogue_ctrl_op_mod mod)1526 static inline bool rogue_ctrl_op_mod_is_set(const rogue_ctrl_instr *ctrl,
1527                                             enum rogue_ctrl_op_mod mod)
1528 {
1529    return !!(ctrl->mod & BITFIELD64_BIT(mod));
1530 }
1531 
1532 /**
1533  * \brief Allocates and initializes a new control instruction.
1534  *
1535  * \param[in] block The block which will contain the instruction.
1536  * \param[in] op The ALU instruction operation.
1537  * \return The new instruction.
1538  */
1539 rogue_ctrl_instr *rogue_ctrl_instr_create(rogue_block *block,
1540                                           enum rogue_ctrl_op op);
1541 
1542 enum rogue_bitwise_op {
1543    ROGUE_BITWISE_OP_INVALID = 0,
1544 
1545    /* Real instructions. */
1546    ROGUE_BITWISE_OP_BYP0,
1547 
1548    /* Pseudo-instructions. */
1549    ROGUE_BITWISE_OP_PSEUDO,
1550    ROGUE_BITWISE_OP_ = ROGUE_BITWISE_OP_PSEUDO,
1551 
1552    ROGUE_BITWISE_OP_COUNT,
1553 };
1554 
1555 enum rogue_bitwise_op_mod {
1556    /* In order of priority */
1557    ROGUE_BITWISE_OP_MOD_TWB, /* Top word break. */
1558    ROGUE_BITWISE_OP_MOD_PWB, /* Partial word break. */
1559    ROGUE_BITWISE_OP_MOD_MTB, /* Mask top break. */
1560    ROGUE_BITWISE_OP_MOD_FTB, /* Find top break. */
1561 
1562    ROGUE_BITWISE_OP_MOD_COUNT,
1563 };
1564 
1565 typedef struct rogue_bitwise_op_mod_info {
1566    const char *str;
1567    uint64_t exclude; /* Can't use this op mod with any of these. */
1568    uint64_t require; /* Required op mods for this to be used (OR). */
1569 } rogue_bitwise_op_mod_info;
1570 
1571 extern const rogue_bitwise_op_mod_info
1572    rogue_bitwise_op_mod_infos[ROGUE_BITWISE_OP_MOD_COUNT];
1573 
1574 #define ROGUE_BITWISE_OP_MAX_SRCS 7
1575 #define ROGUE_BITWISE_OP_MAX_DSTS 2
1576 
1577 typedef struct rogue_bitwise_op_info {
1578    const char *str;
1579 
1580    unsigned num_dsts;
1581    unsigned num_srcs;
1582 
1583    uint64_t supported_phases;
1584    rogue_alu_io_info phase_io[ROGUE_INSTR_PHASE_COUNT];
1585 
1586    uint64_t supported_op_mods;
1587    uint64_t supported_dst_mods[ROGUE_BITWISE_OP_MAX_DSTS];
1588    uint64_t supported_src_mods[ROGUE_BITWISE_OP_MAX_SRCS];
1589 
1590    uint64_t supported_dst_types[ROGUE_BITWISE_OP_MAX_DSTS];
1591    uint64_t supported_src_types[ROGUE_BITWISE_OP_MAX_SRCS];
1592 
1593    unsigned dst_stride[ROGUE_CTRL_OP_MAX_DSTS];
1594    unsigned src_stride[ROGUE_CTRL_OP_MAX_SRCS];
1595 
1596    uint64_t dst_repeat_mask;
1597    uint64_t src_repeat_mask;
1598 } rogue_bitwise_op_info;
1599 
1600 extern const rogue_bitwise_op_info
1601    rogue_bitwise_op_infos[ROGUE_BITWISE_OP_COUNT];
1602 
1603 typedef struct rogue_bitwise_dst {
1604    rogue_ref ref;
1605    unsigned index;
1606 } rogue_bitwise_dst;
1607 
1608 typedef struct rogue_bitwise_src {
1609    rogue_ref ref;
1610    unsigned index;
1611 } rogue_bitwise_src;
1612 
1613 typedef struct rogue_bitwise_instr {
1614    rogue_instr instr;
1615 
1616    enum rogue_bitwise_op op;
1617 
1618    uint64_t mod;
1619 
1620    /* TODO NEXT: source/dest modifiers */
1621 
1622    rogue_instr_dst dst[ROGUE_BITWISE_OP_MAX_DSTS];
1623    rogue_dst_write dst_write[ROGUE_BITWISE_OP_MAX_DSTS];
1624 
1625    rogue_instr_src src[ROGUE_BITWISE_OP_MAX_SRCS];
1626    rogue_src_use src_use[ROGUE_BITWISE_OP_MAX_SRCS];
1627 } rogue_bitwise_instr;
1628 
rogue_set_bitwise_op_mod(rogue_bitwise_instr * bitwise,enum rogue_bitwise_op_mod mod)1629 static inline void rogue_set_bitwise_op_mod(rogue_bitwise_instr *bitwise,
1630                                             enum rogue_bitwise_op_mod mod)
1631 {
1632    bitwise->mod |= BITFIELD64_BIT(mod);
1633 }
1634 
1635 static inline bool
rogue_bitwise_op_mod_is_set(const rogue_bitwise_instr * bitwise,enum rogue_bitwise_op_mod mod)1636 rogue_bitwise_op_mod_is_set(const rogue_bitwise_instr *bitwise,
1637                             enum rogue_bitwise_op_mod mod)
1638 {
1639    return !!(bitwise->mod & BITFIELD64_BIT(mod));
1640 }
1641 
1642 /**
1643  * \brief Allocates and initializes a new bitwise instruction.
1644  *
1645  * \param[in] op The ALU instruction operation.
1646  * \return The new instruction.
1647  */
1648 rogue_bitwise_instr *rogue_bitwise_instr_create(rogue_block *block,
1649                                                 enum rogue_bitwise_op op);
1650 
1651 /** Defines a cast function
1652  *
1653  * This macro defines a cast function from in_type to out_type where
1654  * out_type is some structure type that contains a field of type out_type.
1655  *
1656  * Note that you have to be a bit careful as the generated cast function
1657  * destroys constness.
1658  */
1659 #define ROGUE_DEFINE_CAST(name,                           \
1660                           in_type,                        \
1661                           out_type,                       \
1662                           field,                          \
1663                           type_field,                     \
1664                           type_value)                     \
1665    static inline out_type *name(const in_type *parent)    \
1666    {                                                      \
1667       assert(parent && parent->type_field == type_value); \
1668       return list_entry(parent, out_type, field);         \
1669    }
1670 
ROGUE_DEFINE_CAST(rogue_instr_as_alu,rogue_instr,rogue_alu_instr,instr,type,ROGUE_INSTR_TYPE_ALU)1671 ROGUE_DEFINE_CAST(rogue_instr_as_alu,
1672                   rogue_instr,
1673                   rogue_alu_instr,
1674                   instr,
1675                   type,
1676                   ROGUE_INSTR_TYPE_ALU)
1677 ROGUE_DEFINE_CAST(rogue_instr_as_backend,
1678                   rogue_instr,
1679                   rogue_backend_instr,
1680                   instr,
1681                   type,
1682                   ROGUE_INSTR_TYPE_BACKEND)
1683 ROGUE_DEFINE_CAST(rogue_instr_as_ctrl,
1684                   rogue_instr,
1685                   rogue_ctrl_instr,
1686                   instr,
1687                   type,
1688                   ROGUE_INSTR_TYPE_CTRL)
1689 ROGUE_DEFINE_CAST(rogue_instr_as_bitwise,
1690                   rogue_instr,
1691                   rogue_bitwise_instr,
1692                   instr,
1693                   type,
1694                   ROGUE_INSTR_TYPE_BITWISE)
1695 
1696 static inline enum rogue_io rogue_instr_src_io_src(const rogue_instr *instr,
1697                                                    enum rogue_instr_phase phase,
1698                                                    unsigned src_index)
1699 {
1700    switch (instr->type) {
1701    case ROGUE_INSTR_TYPE_ALU: {
1702       const rogue_alu_instr *alu = rogue_instr_as_alu(instr);
1703       const rogue_alu_op_info *info = &rogue_alu_op_infos[alu->op];
1704       return info->phase_io[phase].src[src_index];
1705    }
1706 
1707    case ROGUE_INSTR_TYPE_BACKEND: {
1708       const rogue_backend_instr *backend = rogue_instr_as_backend(instr);
1709       const rogue_backend_op_info *info = &rogue_backend_op_infos[backend->op];
1710       return info->phase_io.src[src_index];
1711    }
1712 
1713    case ROGUE_INSTR_TYPE_CTRL: {
1714       /* TODO after phase_io is added to relevant control instructions as well.
1715        */
1716       break;
1717    }
1718 
1719    default:
1720       unreachable("Unsupported instruction type.");
1721       break;
1722    }
1723 
1724    return ROGUE_IO_INVALID;
1725 }
1726 
1727 /* Maps sources and destinations ("inputs"/"outputs") to registers. */
1728 typedef struct rogue_instr_group_io_sel {
1729    rogue_ref srcs[ROGUE_ISA_SRCS]; /** Upper + lower sources. */
1730    rogue_ref dsts[ROGUE_ISA_DSTS]; /** Destinations. */
1731    rogue_ref iss[ROGUE_ISA_ISSS]; /** Internal source selector (includes
1732                                      IS0/MUX). */
1733 } rogue_instr_group_io_sel;
1734 
1735 static inline rogue_ref *
rogue_instr_group_io_sel_ref(rogue_instr_group_io_sel * map,enum rogue_io io)1736 rogue_instr_group_io_sel_ref(rogue_instr_group_io_sel *map, enum rogue_io io)
1737 {
1738    if (rogue_io_is_src(io))
1739       return &map->srcs[io - ROGUE_IO_S0];
1740    else if (rogue_io_is_dst(io))
1741       return &map->dsts[io - ROGUE_IO_W0];
1742    else if (rogue_io_is_iss(io))
1743       return &map->iss[io - ROGUE_IO_IS0];
1744    unreachable("Unsupported io.");
1745 }
1746 
1747 /** Rogue instruction group. */
1748 typedef struct rogue_instr_group {
1749    rogue_block *block;
1750    struct list_head link; /** Link in rogue_block::instrs. */
1751 
1752    rogue_instr *instrs[ROGUE_INSTR_PHASE_COUNT]; /** Instructions in group. */
1753    rogue_instr_group_io_sel io_sel; /** Source, destination, internal source
1754                                        selector maps. */
1755 
1756    struct {
1757       uint64_t phases; /** Instructions phases present. */
1758 
1759       enum rogue_exec_cond exec_cond;
1760       enum rogue_alu alu;
1761 
1762       bool end; /** Shader end flag. */
1763       unsigned repeat;
1764    } header;
1765 
1766    struct {
1767       unsigned header;
1768       unsigned instrs[ROGUE_INSTR_PHASE_COUNT];
1769       unsigned lower_srcs;
1770       unsigned upper_srcs;
1771       unsigned iss;
1772       unsigned dsts;
1773       unsigned word_padding; /* Padding to make total size a word (% 2 == 0) */
1774       unsigned align_padding; /* Padding to align instruction position in memory
1775                                */
1776       unsigned total;
1777 
1778       unsigned offset;
1779    } size;
1780 
1781    struct {
1782       unsigned lower_src_index;
1783       unsigned upper_src_index;
1784       unsigned dst_index;
1785    } encode_info;
1786 
1787    unsigned index; /** For debug purposes. */
1788 } rogue_instr_group;
1789 
1790 #define rogue_foreach_instr_group_in_block(group, block) \
1791    list_for_each_entry (rogue_instr_group, group, &(block)->instrs, link)
1792 
1793 #define rogue_foreach_instr_group_in_block_safe(group, block) \
1794    list_for_each_entry_safe (rogue_instr_group, group, &(block)->instrs, link)
1795 
1796 #define rogue_foreach_instr_group_in_shader(group, shader) \
1797    rogue_foreach_block (_block, (shader))                  \
1798       rogue_foreach_instr_group_in_block ((group), _block)
1799 
1800 #define rogue_foreach_instr_group_in_shader_safe(group, shader) \
1801    rogue_foreach_block_safe (_block, (shader))                  \
1802       rogue_foreach_instr_group_in_block_safe ((group), _block)
1803 
rogue_instr_group_create(rogue_block * block,enum rogue_alu alu)1804 static inline rogue_instr_group *rogue_instr_group_create(rogue_block *block,
1805                                                           enum rogue_alu alu)
1806 {
1807    rogue_instr_group *group = rzalloc_size(block, sizeof(*group));
1808    group->header.alu = alu;
1809    group->block = block;
1810    return group;
1811 }
1812 
1813 typedef struct rogue_build_ctx rogue_build_ctx;
1814 
1815 /** Rogue shader object. */
1816 typedef struct rogue_shader {
1817    gl_shader_stage stage; /** Shader stage. */
1818 
1819    rogue_build_ctx *ctx; /** Build context. */
1820 
1821    unsigned next_instr; /** Next instruction index. */
1822    unsigned next_block; /** Next block index. */
1823 
1824    struct list_head blocks; /** List of basic blocks. */
1825    struct list_head regs[ROGUE_REG_CLASS_COUNT]; /** List of registers used by
1826                                                     the shader. */
1827    BITSET_WORD *regs_used[ROGUE_REG_CLASS_COUNT]; /** Bitset of register numbers
1828                                                      used. */
1829    struct util_sparse_array reg_cache[ROGUE_REG_CLASS_COUNT];
1830 
1831    struct list_head regarrays; /** List of register arrays used by the shader.
1832                                 */
1833    struct util_sparse_array regarray_cache;
1834 
1835    struct list_head drc_trxns[ROGUE_DRCS]; /** List of drc transactions. */
1836 
1837    struct list_head imm_uses; /** List of immediate value uses. */
1838 
1839    bool is_grouped; /** Whether the instructions are grouped. */
1840 
1841    const char *name; /** Shader name. */
1842 } rogue_shader;
1843 
rogue_set_shader_name(rogue_shader * shader,const char * name)1844 static inline void rogue_set_shader_name(rogue_shader *shader, const char *name)
1845 {
1846    shader->name = ralloc_strdup(shader, name);
1847 }
1848 
rogue_reg_is_used(const rogue_shader * shader,enum rogue_reg_class class,unsigned index)1849 static inline bool rogue_reg_is_used(const rogue_shader *shader,
1850                                      enum rogue_reg_class class,
1851                                      unsigned index)
1852 {
1853    return BITSET_TEST(shader->regs_used[class], index);
1854 }
1855 
rogue_set_reg_use(rogue_shader * shader,enum rogue_reg_class class,unsigned index)1856 static inline void rogue_set_reg_use(rogue_shader *shader,
1857                                      enum rogue_reg_class class,
1858                                      unsigned index)
1859 {
1860    BITSET_SET(shader->regs_used[class], index);
1861 }
1862 
rogue_clear_reg_use(rogue_shader * shader,enum rogue_reg_class class,unsigned index)1863 static inline void rogue_clear_reg_use(rogue_shader *shader,
1864                                        enum rogue_reg_class class,
1865                                        unsigned index)
1866 {
1867    BITSET_CLEAR(shader->regs_used[class], index);
1868 }
1869 
1870 /**
1871  * \brief Allocates and initializes a new rogue_shader object.
1872  *
1873  * \param[in] mem_ctx The parent memory context.
1874  * \param[in] stage The shader stage.
1875  * \return The new shader.
1876  */
1877 rogue_shader *rogue_shader_create(void *mem_ctx, gl_shader_stage stage);
1878 
1879 rogue_reg *rogue_ssa_reg(rogue_shader *shader, unsigned index);
1880 
1881 rogue_reg *rogue_temp_reg(rogue_shader *shader, unsigned index);
1882 
1883 rogue_reg *rogue_coeff_reg(rogue_shader *shader, unsigned index);
1884 
1885 rogue_reg *rogue_shared_reg(rogue_shader *shader, unsigned index);
1886 
1887 rogue_reg *rogue_const_reg(rogue_shader *shader, unsigned index);
1888 
1889 rogue_reg *rogue_pixout_reg(rogue_shader *shader, unsigned index);
1890 
1891 rogue_reg *rogue_special_reg(rogue_shader *shader, unsigned index);
1892 
1893 rogue_reg *rogue_vtxin_reg(rogue_shader *shader, unsigned index);
1894 
1895 rogue_reg *rogue_vtxout_reg(rogue_shader *shader, unsigned index);
1896 
1897 rogue_reg *
1898 rogue_ssa_vec_reg(rogue_shader *shader, unsigned index, unsigned component);
1899 
1900 void rogue_reg_delete(rogue_reg *reg);
1901 
1902 rogue_regarray *
1903 rogue_ssa_regarray(rogue_shader *shader, unsigned size, unsigned start_index);
1904 
1905 rogue_regarray *
1906 rogue_temp_regarray(rogue_shader *shader, unsigned size, unsigned start_index);
1907 
1908 rogue_regarray *
1909 rogue_coeff_regarray(rogue_shader *shader, unsigned size, unsigned start_index);
1910 
1911 rogue_regarray *rogue_shared_regarray(rogue_shader *shader,
1912                                       unsigned size,
1913                                       unsigned start_index);
1914 
1915 rogue_regarray *rogue_ssa_vec_regarray(rogue_shader *shader,
1916                                        unsigned size,
1917                                        unsigned start_index,
1918                                        unsigned component);
1919 
1920 rogue_regarray *rogue_regarray_cached(rogue_shader *shader,
1921                                       unsigned size,
1922                                       enum rogue_reg_class class,
1923                                       uint32_t start_index);
1924 
1925 rogue_regarray *rogue_vec_regarray_cached(rogue_shader *shader,
1926                                           unsigned size,
1927                                           enum rogue_reg_class class,
1928                                           uint32_t start_index,
1929                                           uint8_t component);
1930 
rogue_regarray_is_unused(rogue_regarray * regarray)1931 static inline bool rogue_regarray_is_unused(rogue_regarray *regarray)
1932 {
1933    return list_is_empty(&regarray->uses) && list_is_empty(&regarray->writes);
1934 }
1935 
rogue_regarray_delete(rogue_regarray * regarray)1936 static void rogue_regarray_delete(rogue_regarray *regarray)
1937 {
1938    assert(rogue_regarray_is_unused(regarray));
1939 
1940    if (!regarray->parent) {
1941       for (unsigned u = 0; u < regarray->size; ++u)
1942          rogue_reg_delete(regarray->regs[u]);
1943    }
1944 
1945    if (regarray->cached && *regarray->cached == regarray)
1946       *regarray->cached = NULL;
1947 
1948    list_del(&regarray->link);
1949    if (regarray->parent)
1950       list_del(&regarray->child_link);
1951    ralloc_free(regarray);
1952 }
1953 
rogue_reset_reg_usage(rogue_shader * shader,enum rogue_reg_class class)1954 static inline void rogue_reset_reg_usage(rogue_shader *shader,
1955                                          enum rogue_reg_class class)
1956 {
1957    const rogue_reg_info *info = &rogue_reg_infos[class];
1958 
1959    if (info->num) {
1960       memset(shader->regs_used[class],
1961              0,
1962              sizeof(*shader->regs_used[class]) * BITSET_WORDS(info->num));
1963    }
1964 
1965    rogue_foreach_reg (reg, shader, class) {
1966       reg->dirty = false;
1967    }
1968 }
1969 
1970 bool rogue_reg_set(rogue_shader *shader,
1971                    rogue_reg *reg,
1972                    enum rogue_reg_class class,
1973                    unsigned index);
1974 
1975 bool rogue_reg_rewrite(rogue_shader *shader,
1976                        rogue_reg *reg,
1977                        enum rogue_reg_class class,
1978                        unsigned index);
1979 
1980 bool rogue_regarray_set(rogue_shader *shader,
1981                         rogue_regarray *regarray,
1982                         enum rogue_reg_class class,
1983                         unsigned base_index,
1984                         bool set_regs);
1985 
1986 bool rogue_regarray_rewrite(rogue_shader *shader,
1987                             rogue_regarray *regarray,
1988                             enum rogue_reg_class class,
1989                             unsigned base_index);
1990 
1991 /** Cursor for Rogue instructions/groups and basic blocks. */
1992 typedef struct rogue_cursor {
1993    bool block;
1994    struct list_head *prev; /** Linked-list pointer to before the object. */
1995    bool first; /** Whether the cursor is pointing to the first element. */
1996 } rogue_cursor;
1997 
1998 /**
1999  * \brief Returns a cursor set to the beginning of the shader.
2000  *
2001  * \param[in] shader The shader.
2002  * \return The cursor.
2003  */
rogue_cursor_before_shader(rogue_shader * shader)2004 static inline rogue_cursor rogue_cursor_before_shader(rogue_shader *shader)
2005 {
2006    return (rogue_cursor){
2007       .block = true,
2008       .prev = &shader->blocks,
2009       .first = true,
2010    };
2011 }
2012 
2013 /**
2014  * \brief Returns a cursor set to before a block.
2015  *
2016  * \param[in] block The block.
2017  * \return The cursor.
2018  */
rogue_cursor_before_block(rogue_block * block)2019 static inline rogue_cursor rogue_cursor_before_block(rogue_block *block)
2020 {
2021    return (rogue_cursor){
2022       .block = true,
2023       .prev = block->link.prev,
2024       .first = (block->link.prev == &block->shader->blocks),
2025    };
2026 }
2027 
2028 /**
2029  * \brief Returns a cursor set to after a block.
2030  *
2031  * \param[in] block The block.
2032  * \return The cursor.
2033  */
rogue_cursor_after_block(rogue_block * block)2034 static inline rogue_cursor rogue_cursor_after_block(rogue_block *block)
2035 {
2036    return (rogue_cursor){
2037       .block = true,
2038       .prev = &block->link,
2039    };
2040 }
2041 
2042 /**
2043  * \brief Returns a cursor set to before an instruction.
2044  *
2045  * \param[in] instr The instruction.
2046  * \return The cursor.
2047  */
rogue_cursor_before_instr(rogue_instr * instr)2048 static inline rogue_cursor rogue_cursor_before_instr(rogue_instr *instr)
2049 {
2050    return (rogue_cursor){
2051       .block = false,
2052       .prev = instr->link.prev,
2053       .first = (instr->link.prev == &instr->block->instrs),
2054    };
2055 }
2056 
2057 /**
2058  * \brief Returns a cursor set to after an instruction.
2059  *
2060  * \param[in] instr The instruction.
2061  * \return The cursor.
2062  */
rogue_cursor_after_instr(rogue_instr * instr)2063 static inline rogue_cursor rogue_cursor_after_instr(rogue_instr *instr)
2064 {
2065    return (rogue_cursor){
2066       .block = false,
2067       .prev = &instr->link,
2068    };
2069 }
2070 
2071 /**
2072  * \brief Allocates and initializes a new rogue_block object.
2073  *
2074  * \param[in] shader The shader which will contain the block.
2075  * \param[in] label The (optional) block label.
2076  * \return The new block.
2077  */
2078 rogue_block *rogue_block_create(rogue_shader *shader, const char *label);
2079 
2080 /**
2081  * \brief Returns the block currently being pointed to by the cursor.
2082  *
2083  * If the cursor is currently pointing to a block, this function will
2084  * directly return said block. If it is pointing to an instruction, it
2085  * will return the block that said instruction is a part of.
2086  *
2087  * \param[in] cursor A cursor.
2088  * \return The the block being pointed to.
2089  */
rogue_cursor_block(rogue_cursor cursor)2090 static inline rogue_block *rogue_cursor_block(rogue_cursor cursor)
2091 {
2092    rogue_block *block = NULL;
2093 
2094    if (cursor.block) {
2095       assert(!cursor.first && "Cursor is not pointing at a block.");
2096       block = list_entry(cursor.prev, rogue_block, link);
2097    } else {
2098       block = cursor.first ? list_entry(cursor.prev, rogue_block, instrs)
2099                            : list_entry(cursor.prev, rogue_instr, link)->block;
2100    }
2101 
2102    return block;
2103 }
2104 
2105 /**
2106  * \brief Inserts a basic block at the specified cursor position.
2107  *
2108  * \param[in] block The basic block to insert.
2109  * \param[in] cursor The cursor.
2110  */
rogue_block_insert(rogue_block * block,rogue_cursor cursor)2111 static inline void rogue_block_insert(rogue_block *block, rogue_cursor cursor)
2112 {
2113    struct list_head *list = cursor.prev;
2114 
2115    /* If the cursor is pointing at an instruction, the block
2116     * is always going to be inserted *after* the block
2117     * that the instruction is in.
2118     */
2119    if (!cursor.block)
2120       list = &rogue_cursor_block(cursor)->link;
2121 
2122    list_add(&block->link, list);
2123 }
2124 
2125 void rogue_link_instr_write(rogue_instr *instr);
2126 
2127 void rogue_link_instr_use(rogue_instr *instr);
2128 
2129 void rogue_unlink_instr_write(rogue_instr *instr);
2130 
2131 void rogue_unlink_instr_use(rogue_instr *instr);
2132 
2133 /**
2134  * \brief Inserts an instruction at the specified cursor position.
2135  *
2136  * \param[in] instr The instruction to insert.
2137  * \param[in] cursor The cursor.
2138  */
rogue_instr_insert(rogue_instr * instr,rogue_cursor cursor)2139 static inline void rogue_instr_insert(rogue_instr *instr, rogue_cursor cursor)
2140 {
2141    struct list_head *list = cursor.prev;
2142 
2143    /* If the cursor is pointing at block, the instruction
2144     * is always going to be inserted at the end of any other
2145     * instructions in the block.
2146     */
2147    if (cursor.block)
2148       list = rogue_cursor_block(cursor)->instrs.prev;
2149 
2150    list_add(&instr->link, list);
2151 
2152    rogue_link_instr_write(instr);
2153    rogue_link_instr_use(instr);
2154 }
2155 
rogue_instr_delete(rogue_instr * instr)2156 static inline void rogue_instr_delete(rogue_instr *instr)
2157 {
2158    rogue_unlink_instr_use(instr);
2159    rogue_unlink_instr_write(instr);
2160 
2161    list_del(&instr->link);
2162 
2163    ralloc_free(instr);
2164 }
2165 
2166 static inline void
rogue_link_drc_trxn(rogue_shader * shader,rogue_instr * instr,rogue_drc * drc)2167 rogue_link_drc_trxn(rogue_shader *shader, rogue_instr *instr, rogue_drc *drc)
2168 {
2169    unsigned index = drc->index;
2170    assert(index < ROGUE_DRCS);
2171 
2172    drc->trxn.acquire = instr;
2173    list_addtail(&drc->trxn.link, &shader->drc_trxns[index]);
2174 }
2175 
2176 static inline void
rogue_unlink_drc_trxn(rogue_shader * shader,rogue_instr * instr,rogue_drc * drc)2177 rogue_unlink_drc_trxn(rogue_shader *shader, rogue_instr *instr, rogue_drc *drc)
2178 {
2179    ASSERTED unsigned index = drc->index;
2180    assert(index < ROGUE_DRCS);
2181    assert(drc->trxn.acquire == instr);
2182 
2183    if (drc->trxn.release)
2184       rogue_instr_delete(drc->trxn.release);
2185 
2186    list_del(&drc->trxn.link);
2187 }
2188 
rogue_link_imm_use(rogue_shader * shader,rogue_instr * instr,unsigned src_index,rogue_imm * imm)2189 static inline void rogue_link_imm_use(rogue_shader *shader,
2190                                       rogue_instr *instr,
2191                                       unsigned src_index,
2192                                       rogue_imm *imm)
2193 {
2194    rogue_imm_use *imm_use = &imm->use;
2195 
2196    imm_use->instr = instr;
2197    imm_use->src_index = src_index;
2198    imm_use->imm = &imm->imm;
2199 
2200    list_addtail(&imm_use->link, &shader->imm_uses);
2201 }
2202 
rogue_unlink_imm_use(rogue_instr * instr,rogue_imm_use * imm_use)2203 static inline void rogue_unlink_imm_use(rogue_instr *instr,
2204                                         rogue_imm_use *imm_use)
2205 {
2206    assert(imm_use->instr == instr);
2207    list_del(&imm_use->link);
2208 }
2209 
rogue_link_instr_write_reg(rogue_instr * instr,rogue_reg_write * write,rogue_reg * reg,unsigned dst_index)2210 static inline void rogue_link_instr_write_reg(rogue_instr *instr,
2211                                               rogue_reg_write *write,
2212                                               rogue_reg *reg,
2213                                               unsigned dst_index)
2214 {
2215    write->instr = instr;
2216    write->dst_index = dst_index;
2217    list_addtail(&write->link, &reg->writes);
2218 }
2219 
rogue_unlink_instr_write_reg(rogue_instr * instr,rogue_reg_write * write)2220 static inline void rogue_unlink_instr_write_reg(rogue_instr *instr,
2221                                                 rogue_reg_write *write)
2222 {
2223    assert(write->instr == instr);
2224    write->instr = NULL;
2225    list_del(&write->link);
2226 }
2227 
rogue_link_instr_write_regarray(rogue_instr * instr,rogue_regarray_write * write,rogue_regarray * regarray,unsigned dst_index)2228 static inline void rogue_link_instr_write_regarray(rogue_instr *instr,
2229                                                    rogue_regarray_write *write,
2230                                                    rogue_regarray *regarray,
2231                                                    unsigned dst_index)
2232 {
2233    write->instr = instr;
2234    write->dst_index = dst_index;
2235    list_addtail(&write->link, &regarray->writes);
2236 }
2237 
2238 static inline void
rogue_unlink_instr_write_regarray(rogue_instr * instr,rogue_regarray_write * write)2239 rogue_unlink_instr_write_regarray(rogue_instr *instr,
2240                                   rogue_regarray_write *write)
2241 {
2242    assert(write->instr == instr);
2243    write->instr = NULL;
2244    list_del(&write->link);
2245 }
2246 
rogue_link_instr_use_reg(rogue_instr * instr,rogue_reg_use * use,rogue_reg * reg,unsigned src_index)2247 static inline void rogue_link_instr_use_reg(rogue_instr *instr,
2248                                             rogue_reg_use *use,
2249                                             rogue_reg *reg,
2250                                             unsigned src_index)
2251 {
2252    use->instr = instr;
2253    use->src_index = src_index;
2254    list_addtail(&use->link, &reg->uses);
2255 }
2256 
rogue_unlink_instr_use_reg(rogue_instr * instr,rogue_reg_use * use)2257 static inline void rogue_unlink_instr_use_reg(rogue_instr *instr,
2258                                               rogue_reg_use *use)
2259 {
2260    assert(use->instr == instr);
2261    use->instr = NULL;
2262    list_del(&use->link);
2263 }
2264 
rogue_link_instr_use_regarray(rogue_instr * instr,rogue_regarray_use * use,rogue_regarray * regarray,unsigned src_index)2265 static inline void rogue_link_instr_use_regarray(rogue_instr *instr,
2266                                                  rogue_regarray_use *use,
2267                                                  rogue_regarray *regarray,
2268                                                  unsigned src_index)
2269 {
2270    use->instr = instr;
2271    use->src_index = src_index;
2272    list_addtail(&use->link, &regarray->uses);
2273 }
2274 
rogue_unlink_instr_use_regarray(rogue_instr * instr,rogue_regarray_use * use)2275 static inline void rogue_unlink_instr_use_regarray(rogue_instr *instr,
2276                                                    rogue_regarray_use *use)
2277 {
2278    assert(use->instr == instr);
2279    use->instr = NULL;
2280    list_del(&use->link);
2281 }
2282 
rogue_link_instr_use_block(rogue_instr * instr,rogue_block_use * block_use,rogue_block * target_block)2283 static inline void rogue_link_instr_use_block(rogue_instr *instr,
2284                                               rogue_block_use *block_use,
2285                                               rogue_block *target_block)
2286 {
2287    assert(!block_use->instr);
2288    block_use->instr = instr;
2289    list_addtail(&block_use->link, &target_block->uses);
2290 }
2291 
rogue_unlink_instr_use_block(rogue_instr * instr,rogue_block_use * block_use)2292 static inline void rogue_unlink_instr_use_block(rogue_instr *instr,
2293                                                 rogue_block_use *block_use)
2294 {
2295    assert(block_use->instr == instr);
2296    list_del(&block_use->link);
2297 }
2298 
rogue_dst_reg_replace(rogue_reg_write * write,rogue_reg * new_reg)2299 static inline bool rogue_dst_reg_replace(rogue_reg_write *write,
2300                                          rogue_reg *new_reg)
2301 {
2302    unsigned dst_index = write->dst_index;
2303    rogue_instr *instr = write->instr;
2304    rogue_ref *ref;
2305 
2306    switch (instr->type) {
2307    case ROGUE_INSTR_TYPE_ALU:
2308       ref = &rogue_instr_as_alu(instr)->dst[dst_index].ref;
2309       break;
2310 
2311    case ROGUE_INSTR_TYPE_BACKEND:
2312       ref = &rogue_instr_as_backend(instr)->dst[dst_index].ref;
2313       break;
2314 
2315    case ROGUE_INSTR_TYPE_CTRL:
2316       ref = &rogue_instr_as_ctrl(instr)->dst[dst_index].ref;
2317       break;
2318 
2319    case ROGUE_INSTR_TYPE_BITWISE:
2320       ref = &rogue_instr_as_bitwise(instr)->dst[dst_index].ref;
2321       break;
2322 
2323    default:
2324       unreachable("Unsupported instruction type.");
2325       return false;
2326    }
2327 
2328    /* We don't want to be modifying regarrays. */
2329    assert(rogue_ref_is_reg(ref));
2330 
2331    if (ref->reg == new_reg)
2332       return false;
2333 
2334    rogue_unlink_instr_write_reg(instr, write);
2335    *ref = rogue_ref_reg(new_reg);
2336    rogue_link_instr_write_reg(instr, write, new_reg, dst_index);
2337 
2338    return true;
2339 }
2340 
rogue_src_reg_replace(rogue_reg_use * use,rogue_reg * new_reg)2341 static inline bool rogue_src_reg_replace(rogue_reg_use *use, rogue_reg *new_reg)
2342 {
2343    unsigned src_index = use->src_index;
2344    rogue_instr *instr = use->instr;
2345    rogue_ref *ref;
2346 
2347    switch (instr->type) {
2348    case ROGUE_INSTR_TYPE_ALU:
2349       ref = &rogue_instr_as_alu(instr)->src[src_index].ref;
2350       break;
2351 
2352    case ROGUE_INSTR_TYPE_BACKEND:
2353       ref = &rogue_instr_as_backend(instr)->src[src_index].ref;
2354       break;
2355 
2356    case ROGUE_INSTR_TYPE_CTRL:
2357       ref = &rogue_instr_as_ctrl(instr)->src[src_index].ref;
2358       break;
2359 
2360    default:
2361       unreachable("Unsupported instruction type.");
2362       return false;
2363    }
2364 
2365    /* We don't want to be modifying regarrays. */
2366    assert(rogue_ref_is_reg(ref));
2367 
2368    if (ref->reg == new_reg)
2369       return false;
2370 
2371    rogue_unlink_instr_use_reg(instr, use);
2372    *ref = rogue_ref_reg(new_reg);
2373    rogue_link_instr_use_reg(instr, use, new_reg, src_index);
2374 
2375    return true;
2376 }
2377 
rogue_reg_replace(rogue_reg * old_reg,rogue_reg * new_reg)2378 static inline bool rogue_reg_replace(rogue_reg *old_reg, rogue_reg *new_reg)
2379 {
2380    bool replaced = true;
2381 
2382    rogue_foreach_reg_write_safe (write, old_reg) {
2383       replaced &= rogue_dst_reg_replace(write, new_reg);
2384    }
2385 
2386    rogue_foreach_reg_use_safe (use, old_reg) {
2387       replaced &= rogue_src_reg_replace(use, new_reg);
2388    }
2389 
2390    if (replaced)
2391       rogue_reg_delete(old_reg);
2392 
2393    return replaced;
2394 }
2395 
2396 /* TODO: try and commonise this with the reg one! */
rogue_dst_regarray_replace(rogue_regarray_write * write,rogue_regarray * new_regarray)2397 static inline bool rogue_dst_regarray_replace(rogue_regarray_write *write,
2398                                               rogue_regarray *new_regarray)
2399 {
2400    unsigned dst_index = write->dst_index;
2401    rogue_instr *instr = write->instr;
2402    rogue_ref *ref;
2403 
2404    switch (instr->type) {
2405    case ROGUE_INSTR_TYPE_ALU:
2406       ref = &rogue_instr_as_alu(instr)->dst[dst_index].ref;
2407       break;
2408 
2409    case ROGUE_INSTR_TYPE_BACKEND:
2410       ref = &rogue_instr_as_backend(instr)->dst[dst_index].ref;
2411       break;
2412 
2413    case ROGUE_INSTR_TYPE_CTRL:
2414       ref = &rogue_instr_as_ctrl(instr)->dst[dst_index].ref;
2415       break;
2416 
2417    case ROGUE_INSTR_TYPE_BITWISE:
2418       ref = &rogue_instr_as_bitwise(instr)->dst[dst_index].ref;
2419       break;
2420 
2421    default:
2422       unreachable("Unsupported instruction type.");
2423       return false;
2424    }
2425 
2426    /* We don't want to be modifying regs. */
2427    assert(rogue_ref_is_regarray(ref));
2428 
2429    if (ref->regarray == new_regarray)
2430       return false;
2431 
2432    rogue_unlink_instr_write_regarray(instr, write);
2433    *ref = rogue_ref_regarray(new_regarray);
2434    rogue_link_instr_write_regarray(instr, write, new_regarray, dst_index);
2435 
2436    return true;
2437 }
2438 
rogue_src_regarray_replace(rogue_regarray_use * use,rogue_regarray * new_regarray)2439 static inline bool rogue_src_regarray_replace(rogue_regarray_use *use,
2440                                               rogue_regarray *new_regarray)
2441 {
2442    unsigned src_index = use->src_index;
2443    rogue_instr *instr = use->instr;
2444    rogue_ref *ref;
2445 
2446    switch (instr->type) {
2447    case ROGUE_INSTR_TYPE_ALU:
2448       ref = &rogue_instr_as_alu(instr)->src[src_index].ref;
2449       break;
2450 
2451    case ROGUE_INSTR_TYPE_BACKEND:
2452       ref = &rogue_instr_as_backend(instr)->src[src_index].ref;
2453       break;
2454 
2455    case ROGUE_INSTR_TYPE_CTRL:
2456       ref = &rogue_instr_as_ctrl(instr)->src[src_index].ref;
2457       break;
2458 
2459    default:
2460       unreachable("Unsupported instruction type.");
2461       return false;
2462    }
2463 
2464    /* We don't want to be modifying reg. */
2465    assert(rogue_ref_is_regarray(ref));
2466 
2467    if (ref->regarray == new_regarray)
2468       return false;
2469 
2470    rogue_unlink_instr_use_regarray(instr, use);
2471    *ref = rogue_ref_regarray(new_regarray);
2472    rogue_link_instr_use_regarray(instr, use, new_regarray, src_index);
2473 
2474    return true;
2475 }
2476 
rogue_regarray_replace(rogue_shader * shader,rogue_regarray * old_regarray,rogue_regarray * new_regarray)2477 static inline bool rogue_regarray_replace(rogue_shader *shader,
2478                                           rogue_regarray *old_regarray,
2479                                           rogue_regarray *new_regarray)
2480 {
2481    bool replaced = true;
2482 
2483    assert(!old_regarray->parent);
2484    assert(!new_regarray->parent);
2485 
2486    rogue_foreach_regarray_write_safe (write, old_regarray) {
2487       replaced &= rogue_dst_regarray_replace(write, new_regarray);
2488    }
2489 
2490    rogue_foreach_regarray_use_safe (use, old_regarray) {
2491       replaced &= rogue_src_regarray_replace(use, new_regarray);
2492    }
2493 
2494    enum rogue_reg_class new_class = new_regarray->regs[0]->class;
2495    unsigned new_base_index = new_regarray->regs[0]->index;
2496 
2497    /* Replace subarrays. */
2498    rogue_foreach_subarray_safe (old_subarray, old_regarray) {
2499       unsigned idx_offset =
2500          old_subarray->regs[0]->index - old_regarray->regs[0]->index;
2501       rogue_regarray *new_subarray =
2502          rogue_regarray_cached(shader,
2503                                old_subarray->size,
2504                                new_class,
2505                                new_base_index + idx_offset);
2506 
2507       rogue_foreach_regarray_write_safe (write, old_subarray) {
2508          replaced &= rogue_dst_regarray_replace(write, new_subarray);
2509       }
2510 
2511       rogue_foreach_regarray_use_safe (use, old_subarray) {
2512          replaced &= rogue_src_regarray_replace(use, new_subarray);
2513       }
2514 
2515       rogue_regarray_delete(old_subarray);
2516    }
2517 
2518    rogue_regarray_delete(old_regarray);
2519 
2520    return replaced;
2521 }
2522 
rogue_src_imm_replace(rogue_imm_use * imm_use,rogue_reg * new_reg)2523 static inline bool rogue_src_imm_replace(rogue_imm_use *imm_use,
2524                                          rogue_reg *new_reg)
2525 {
2526    unsigned src_index = imm_use->src_index;
2527    rogue_instr *instr = imm_use->instr;
2528    rogue_ref *ref;
2529    rogue_reg_use *reg_use;
2530 
2531    switch (instr->type) {
2532    case ROGUE_INSTR_TYPE_ALU:
2533       ref = &rogue_instr_as_alu(instr)->src[src_index].ref;
2534       reg_use = &rogue_instr_as_alu(instr)->src_use[src_index].reg;
2535       break;
2536 
2537    case ROGUE_INSTR_TYPE_BACKEND:
2538       ref = &rogue_instr_as_backend(instr)->src[src_index].ref;
2539       reg_use = &rogue_instr_as_backend(instr)->src_use[src_index].reg;
2540       break;
2541 
2542    case ROGUE_INSTR_TYPE_CTRL:
2543       ref = &rogue_instr_as_ctrl(instr)->src[src_index].ref;
2544       reg_use = &rogue_instr_as_ctrl(instr)->src_use[src_index].reg;
2545       break;
2546 
2547    default:
2548       unreachable("Unsupported instruction type.");
2549       return false;
2550    }
2551 
2552    assert(rogue_ref_is_imm(ref));
2553 
2554    rogue_unlink_imm_use(instr, imm_use);
2555    *ref = rogue_ref_reg(new_reg);
2556    rogue_link_instr_use_reg(instr, reg_use, new_reg, src_index);
2557 
2558    return true;
2559 }
2560 
rogue_instr_is_nop_end(const rogue_instr * instr)2561 static inline bool rogue_instr_is_nop_end(const rogue_instr *instr)
2562 {
2563    if (instr->type != ROGUE_INSTR_TYPE_CTRL)
2564       return false;
2565 
2566    const rogue_ctrl_instr *ctrl = rogue_instr_as_ctrl(instr);
2567 
2568    if (ctrl->op != ROGUE_CTRL_OP_NOP)
2569       return false;
2570 
2571    return rogue_ctrl_op_mod_is_set(ctrl, ROGUE_CTRL_OP_MOD_END);
2572 }
2573 
rogue_instr_supported_phases(const rogue_instr * instr)2574 static inline unsigned rogue_instr_supported_phases(const rogue_instr *instr)
2575 {
2576    uint64_t supported_phases = 0;
2577 
2578    switch (instr->type) {
2579    case ROGUE_INSTR_TYPE_ALU: {
2580       rogue_alu_instr *alu = rogue_instr_as_alu(instr);
2581       if (alu->op >= ROGUE_ALU_OP_PSEUDO)
2582          return 0;
2583 
2584       const rogue_alu_op_info *info = &rogue_alu_op_infos[alu->op];
2585       supported_phases = info->supported_phases;
2586       break;
2587    }
2588 
2589    case ROGUE_INSTR_TYPE_BACKEND: {
2590       rogue_backend_instr *backend = rogue_instr_as_backend(instr);
2591       if (backend->op >= ROGUE_BACKEND_OP_PSEUDO)
2592          return 0;
2593 
2594       supported_phases = BITFIELD_BIT(ROGUE_INSTR_PHASE_BACKEND);
2595       break;
2596    }
2597 
2598    case ROGUE_INSTR_TYPE_CTRL: {
2599       /* Control instructions can't be co-issued; just make sure this isn't a
2600        * pseudo-instruction. */
2601       rogue_ctrl_instr *ctrl = rogue_instr_as_ctrl(instr);
2602       if (ctrl->op >= ROGUE_CTRL_OP_PSEUDO)
2603          return 0;
2604 
2605       supported_phases = BITFIELD_BIT(ROGUE_INSTR_PHASE_CTRL);
2606       break;
2607    }
2608 
2609    case ROGUE_INSTR_TYPE_BITWISE: {
2610       rogue_bitwise_instr *bitwise = rogue_instr_as_bitwise(instr);
2611       if (bitwise->op >= ROGUE_BITWISE_OP_PSEUDO)
2612          return 0;
2613 
2614       const rogue_bitwise_op_info *info = &rogue_bitwise_op_infos[bitwise->op];
2615       supported_phases = info->supported_phases;
2616       break;
2617    }
2618 
2619    default:
2620       unreachable("Unsupported instruction type.");
2621    }
2622 
2623    return supported_phases;
2624 }
2625 
2626 /* Loop through and find first unused phase that's supported, then return its
2627  * enum. */
2628 static inline enum rogue_instr_phase
rogue_get_supported_phase(uint64_t supported_phases,uint64_t occupied_phases)2629 rogue_get_supported_phase(uint64_t supported_phases, uint64_t occupied_phases)
2630 {
2631    rogue_foreach_phase_in_set (p, supported_phases) {
2632       if (!(BITFIELD_BIT(p) & occupied_phases))
2633          return p;
2634    }
2635 
2636    return ROGUE_INSTR_PHASE_INVALID;
2637 }
2638 
rogue_phase_occupied(enum rogue_instr_phase phase,uint64_t occupied_phases)2639 static inline bool rogue_phase_occupied(enum rogue_instr_phase phase,
2640                                         uint64_t occupied_phases)
2641 {
2642    return !!(BITFIELD_BIT(phase) & occupied_phases);
2643 }
2644 
rogue_can_replace_reg_use(rogue_reg_use * use,const rogue_reg * new_reg)2645 static inline bool rogue_can_replace_reg_use(rogue_reg_use *use,
2646                                              const rogue_reg *new_reg)
2647 {
2648    bool can_replace = false;
2649    const rogue_reg_info *reg_info = &rogue_reg_infos[new_reg->class];
2650    const rogue_instr *instr = use->instr;
2651 
2652    rogue_foreach_phase_in_set (p, rogue_instr_supported_phases(instr)) {
2653       enum rogue_io io_src = rogue_instr_src_io_src(instr, p, use->src_index);
2654       can_replace &= rogue_io_supported(io_src, reg_info->supported_io_srcs);
2655    }
2656 
2657    return can_replace;
2658 }
2659 
2660 #define ROGUE_NO_CONST_REG ~0
2661 
2662 unsigned rogue_constreg_lookup(rogue_imm_t imm);
2663 
2664 /* Printing */
2665 
2666 void rogue_print_color(bool print_color);
2667 
2668 /**
2669  * \brief Prints a shader's Rogue IR/assembly.
2670  *
2671  * \param[in] fp The file pointer to use for printing.
2672  * \param[in] shader The shader to print.
2673  */
2674 void rogue_print_shader(FILE *fp, const rogue_shader *shader);
2675 
2676 /**
2677  * \brief Prints an instruction.
2678  *
2679  * \param[in] fp The file pointer to use for printing.
2680  * \param[in] instr The instruction to print.
2681  */
2682 void rogue_print_instr(FILE *fp, const rogue_instr *instr);
2683 
2684 void rogue_print_reg_writes(FILE *fp, const rogue_shader *shader);
2685 
2686 void rogue_print_reg_uses(FILE *fp, const rogue_shader *shader);
2687 
2688 void rogue_print_block_uses(FILE *fp, const rogue_shader *shader);
2689 
2690 void rogue_print_drc_trxns(FILE *fp, const rogue_shader *shader);
2691 
2692 /* Validation */
2693 bool rogue_validate_shader(rogue_shader *shader, const char *when);
2694 
2695 /* Debug. */
2696 enum rogue_debug {
2697    ROGUE_DEBUG_NIR = BITFIELD_BIT(0),
2698    ROGUE_DEBUG_NIR_PASSES = BITFIELD_BIT(1),
2699    ROGUE_DEBUG_IR = BITFIELD_BIT(2),
2700    ROGUE_DEBUG_IR_PASSES = BITFIELD_BIT(3),
2701    ROGUE_DEBUG_IR_DETAILS = BITFIELD_BIT(4),
2702    ROGUE_DEBUG_VLD_SKIP = BITFIELD_BIT(5),
2703    ROGUE_DEBUG_VLD_NONFATAL = BITFIELD_BIT(6),
2704 };
2705 
2706 extern unsigned long rogue_debug;
2707 
2708 #define ROGUE_DEBUG(flag) unlikely(!!(rogue_debug & (ROGUE_DEBUG_##flag)))
2709 
2710 extern bool rogue_color;
2711 
2712 void rogue_debug_init(void);
2713 
2714 static inline void
rogue_print_pass_debug(rogue_shader * shader,const char * pass,FILE * fp)2715 rogue_print_pass_debug(rogue_shader *shader, const char *pass, FILE *fp)
2716 {
2717    fprintf(fp, "%s\n", pass);
2718    rogue_print_shader(fp, shader);
2719    if (ROGUE_DEBUG(IR_DETAILS)) {
2720       rogue_print_reg_writes(fp, shader);
2721       rogue_print_reg_uses(fp, shader);
2722       rogue_print_block_uses(fp, shader);
2723       rogue_print_drc_trxns(fp, shader);
2724    }
2725 }
2726 
2727 /* Passes */
2728 #define ROGUE_PASS(progress, shader, pass, ...)            \
2729    do {                                                    \
2730       if (pass((shader), ##__VA_ARGS__)) {                 \
2731          if (ROGUE_DEBUG(IR_PASSES))                       \
2732             rogue_print_pass_debug(shader, #pass, stdout); \
2733          rogue_validate_shader(shader, #pass);             \
2734          progress = true;                                  \
2735       }                                                    \
2736    } while (0)
2737 
2738 #define ROGUE_PASS_V(shader, pass, ...)                    \
2739    do {                                                    \
2740       if (pass((shader), ##__VA_ARGS__)) {                 \
2741          if (ROGUE_DEBUG(IR_PASSES))                       \
2742             rogue_print_pass_debug(shader, #pass, stdout); \
2743          rogue_validate_shader(shader, #pass);             \
2744       }                                                    \
2745    } while (0)
2746 
2747 bool rogue_constreg(rogue_shader *shader);
2748 
2749 bool rogue_copy_prop(rogue_shader *shader);
2750 
2751 bool rogue_dce(rogue_shader *shader);
2752 
2753 bool rogue_lower_late_ops(rogue_shader *shader);
2754 
2755 bool rogue_lower_pseudo_ops(rogue_shader *shader);
2756 
2757 bool rogue_regalloc(rogue_shader *shader);
2758 
2759 bool rogue_schedule_instr_groups(rogue_shader *shader, bool multi_instr_groups);
2760 
2761 bool rogue_schedule_uvsw(rogue_shader *shader, bool latency_hiding);
2762 
2763 bool rogue_schedule_wdf(rogue_shader *shader, bool latency_hiding);
2764 
2765 bool rogue_trim(rogue_shader *shader);
2766 
2767 void rogue_shader_passes(rogue_shader *shader);
2768 
2769 struct pvr_device_info;
2770 
2771 /**
2772  * \brief Compiler context.
2773  */
2774 typedef struct rogue_compiler {
2775    const struct pvr_device_info *dev_info;
2776 } rogue_compiler;
2777 
2778 rogue_compiler *rogue_compiler_create(const struct pvr_device_info *dev_info);
2779 
2780 /* Max number of I/O varying variables.
2781  * Fragment shader: MAX_VARYING + 1 (W coefficient).
2782  * Vertex shader: MAX_VARYING + 1 (position slot).
2783  */
2784 #define ROGUE_MAX_IO_VARYING_VARS (MAX_VARYING + 1)
2785 
2786 /* VERT_ATTRIB_GENERIC0-15 */
2787 #define ROGUE_MAX_IO_ATTRIB_VARS 16
2788 
2789 /* Max buffers entries that can be used. */
2790 /* TODO: Currently UBOs are the only supported buffers. */
2791 #define ROGUE_MAX_BUFFERS 24
2792 
2793 /**
2794  * \brief UBO data.
2795  */
2796 typedef struct rogue_ubo_data {
2797    unsigned num_ubo_entries;
2798    unsigned desc_set[ROGUE_MAX_BUFFERS];
2799    unsigned binding[ROGUE_MAX_BUFFERS];
2800    unsigned dest[ROGUE_MAX_BUFFERS];
2801    unsigned size[ROGUE_MAX_BUFFERS];
2802 } rogue_ubo_data;
2803 
2804 /**
2805  * \brief Compile time constants that need uploading.
2806  */
2807 typedef struct rogue_compile_time_consts_data {
2808    /* TODO: Output these from the compiler. */
2809    /* TODO: Add the other types. */
2810    struct {
2811       unsigned num;
2812       unsigned dest;
2813       /* TODO: This should probably be bigger. Big enough to account for all
2814        * available writable special constant regs.
2815        */
2816       uint32_t value[ROGUE_MAX_BUFFERS];
2817    } static_consts;
2818 } rogue_compile_time_consts_data;
2819 
2820 /**
2821  * \brief Per-stage common build data.
2822  */
2823 typedef struct rogue_common_build_data {
2824    unsigned temps;
2825    unsigned internals;
2826    unsigned coeffs;
2827    unsigned shareds;
2828 
2829    rogue_ubo_data ubo_data;
2830    rogue_compile_time_consts_data compile_time_consts_data;
2831 } rogue_common_build_data;
2832 
2833 /**
2834  * \brief Arguments for the FPU iterator(s)
2835  * (produces varyings for the fragment shader).
2836  */
2837 typedef struct rogue_iterator_args {
2838    uint32_t num_fpu_iterators;
2839    uint32_t fpu_iterators[ROGUE_MAX_IO_VARYING_VARS];
2840    uint32_t destination[ROGUE_MAX_IO_VARYING_VARS];
2841    unsigned base[ROGUE_MAX_IO_VARYING_VARS];
2842    unsigned components[ROGUE_MAX_IO_VARYING_VARS];
2843 } rogue_iterator_args;
2844 
2845 /**
2846  * \brief Vertex input register allocations.
2847  */
2848 typedef struct rogue_vertex_inputs {
2849    unsigned num_input_vars;
2850    unsigned base[ROGUE_MAX_IO_ATTRIB_VARS];
2851    unsigned components[ROGUE_MAX_IO_ATTRIB_VARS];
2852 } rogue_vertex_inputs;
2853 
2854 /**
2855  * \brief Vertex output allocations.
2856  */
2857 typedef struct rogue_vertex_outputs {
2858    unsigned num_output_vars;
2859    unsigned base[ROGUE_MAX_IO_VARYING_VARS];
2860    unsigned components[ROGUE_MAX_IO_VARYING_VARS];
2861 } rogue_vertex_outputs;
2862 
2863 enum rogue_msaa_mode {
2864    ROGUE_MSAA_MODE_UNDEF = 0, /* explicitly treat 0 as undefined */
2865    /* One task for all samples. */
2866    ROGUE_MSAA_MODE_PIXEL,
2867    /* For on-edge pixels only: separate tasks for each sample. */
2868    ROGUE_MSAA_MODE_SELECTIVE,
2869    /* For all pixels: separate tasks for each sample. */
2870    ROGUE_MSAA_MODE_FULL,
2871 };
2872 
2873 /**
2874  * \brief Stage-specific build data.
2875  */
2876 typedef struct rogue_build_data {
2877    struct rogue_fs_build_data {
2878       rogue_iterator_args iterator_args;
2879       enum rogue_msaa_mode msaa_mode;
2880       bool phas; /* Indicates the presence of PHAS instruction. */
2881    } fs;
2882    struct rogue_vs_build_data {
2883       /* TODO: Should these be removed since the driver allocates the vertex
2884        * inputs?
2885        */
2886       rogue_vertex_inputs inputs;
2887       unsigned num_vertex_input_regs; /* Final number of inputs. */
2888 
2889       rogue_vertex_outputs outputs;
2890       unsigned num_vertex_outputs; /* Final number of outputs. */
2891 
2892       unsigned num_varyings; /* Final number of varyings. */
2893    } vs;
2894 } rogue_build_data;
2895 
2896 /**
2897  * \brief Shared multi-stage build context.
2898  */
2899 typedef struct rogue_build_ctx {
2900    rogue_compiler *compiler;
2901 
2902    /* Shaders in various stages of compilations. */
2903    nir_shader *nir[MESA_SHADER_FRAGMENT + 1];
2904    rogue_shader *rogue[MESA_SHADER_FRAGMENT + 1];
2905    struct util_dynarray binary[MESA_SHADER_FRAGMENT + 1];
2906 
2907    rogue_common_build_data common_data[MESA_SHADER_FRAGMENT + 1];
2908    rogue_build_data stage_data;
2909    struct pvr_pipeline_layout *pipeline_layout;
2910    unsigned next_ssa_idx;
2911 } rogue_build_ctx;
2912 
2913 rogue_build_ctx *
2914 rogue_build_context_create(rogue_compiler *compiler,
2915                            struct pvr_pipeline_layout *pipeline_layout);
2916 
2917 void rogue_collect_io_data(rogue_build_ctx *ctx, nir_shader *nir);
2918 
2919 unsigned rogue_count_used_regs(const rogue_shader *shader,
2920                                enum rogue_reg_class class);
2921 
2922 unsigned rogue_coeff_index_fs(rogue_iterator_args *args,
2923                               gl_varying_slot location,
2924                               unsigned component);
2925 
2926 unsigned rogue_output_index_vs(rogue_vertex_outputs *outputs,
2927                                gl_varying_slot location,
2928                                unsigned component);
2929 
2930 unsigned rogue_ubo_reg(rogue_ubo_data *ubo_data,
2931                        unsigned desc_set,
2932                        unsigned binding,
2933                        unsigned offset_bytes);
2934 
2935 nir_shader *rogue_spirv_to_nir(rogue_build_ctx *ctx,
2936                                gl_shader_stage stage,
2937                                const char *entry,
2938                                unsigned spirv_size,
2939                                const uint32_t *spirv_data,
2940                                unsigned num_spec,
2941                                struct nir_spirv_specialization *spec);
2942 
2943 /* Custom NIR passes. */
2944 void rogue_nir_pfo(nir_shader *shader);
2945 
2946 bool rogue_nir_lower_io(nir_shader *shader);
2947 
2948 rogue_shader *rogue_nir_to_rogue(rogue_build_ctx *ctx, const nir_shader *nir);
2949 
2950 /* Encode/decode */
2951 
2952 void rogue_encode_shader(rogue_build_ctx *ctx,
2953                          rogue_shader *shader,
2954                          struct util_dynarray *binary);
2955 
2956 #endif /* ROGUE_H */
2957