xref: /aosp_15_r20/external/mesa3d/src/asahi/compiler/agx_compiler.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright 2021 Alyssa Rosenzweig
3*61046927SAndroid Build Coastguard Worker  * Copyright 2020 Collabora Ltd.
4*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
5*61046927SAndroid Build Coastguard Worker  */
6*61046927SAndroid Build Coastguard Worker 
7*61046927SAndroid Build Coastguard Worker #pragma once
8*61046927SAndroid Build Coastguard Worker 
9*61046927SAndroid Build Coastguard Worker #include "compiler/nir/nir.h"
10*61046927SAndroid Build Coastguard Worker #include "util/half_float.h"
11*61046927SAndroid Build Coastguard Worker #include "util/u_dynarray.h"
12*61046927SAndroid Build Coastguard Worker #include "util/u_math.h"
13*61046927SAndroid Build Coastguard Worker #include "util/u_worklist.h"
14*61046927SAndroid Build Coastguard Worker #include "agx_compile.h"
15*61046927SAndroid Build Coastguard Worker #include "agx_minifloat.h"
16*61046927SAndroid Build Coastguard Worker #include "agx_opcodes.h"
17*61046927SAndroid Build Coastguard Worker 
18*61046927SAndroid Build Coastguard Worker #ifdef __cplusplus
19*61046927SAndroid Build Coastguard Worker extern "C" {
20*61046927SAndroid Build Coastguard Worker #endif
21*61046927SAndroid Build Coastguard Worker 
22*61046927SAndroid Build Coastguard Worker /* r0-r127 inclusive, as pairs of 16-bits, gives 256 registers */
23*61046927SAndroid Build Coastguard Worker #define AGX_NUM_REGS (256)
24*61046927SAndroid Build Coastguard Worker 
25*61046927SAndroid Build Coastguard Worker /* u0-u255 inclusive, as pairs of 16-bits */
26*61046927SAndroid Build Coastguard Worker #define AGX_NUM_UNIFORMS (512)
27*61046927SAndroid Build Coastguard Worker 
28*61046927SAndroid Build Coastguard Worker /* Semi-arbitrary limit for spill slot allocation */
29*61046927SAndroid Build Coastguard Worker #define AGX_NUM_MODELED_REGS (2048)
30*61046927SAndroid Build Coastguard Worker 
31*61046927SAndroid Build Coastguard Worker /* Limit on number of sources for non-phi instructions */
32*61046927SAndroid Build Coastguard Worker #define AGX_MAX_NORMAL_SOURCES (16)
33*61046927SAndroid Build Coastguard Worker 
34*61046927SAndroid Build Coastguard Worker enum agx_index_type {
35*61046927SAndroid Build Coastguard Worker    AGX_INDEX_NULL = 0,
36*61046927SAndroid Build Coastguard Worker    AGX_INDEX_NORMAL = 1,
37*61046927SAndroid Build Coastguard Worker    AGX_INDEX_IMMEDIATE = 2,
38*61046927SAndroid Build Coastguard Worker    AGX_INDEX_UNIFORM = 3,
39*61046927SAndroid Build Coastguard Worker    AGX_INDEX_REGISTER = 4,
40*61046927SAndroid Build Coastguard Worker    AGX_INDEX_UNDEF = 5,
41*61046927SAndroid Build Coastguard Worker };
42*61046927SAndroid Build Coastguard Worker 
43*61046927SAndroid Build Coastguard Worker enum agx_size { AGX_SIZE_16 = 0, AGX_SIZE_32 = 1, AGX_SIZE_64 = 2 };
44*61046927SAndroid Build Coastguard Worker 
45*61046927SAndroid Build Coastguard Worker static inline unsigned
agx_size_align_16(enum agx_size size)46*61046927SAndroid Build Coastguard Worker agx_size_align_16(enum agx_size size)
47*61046927SAndroid Build Coastguard Worker {
48*61046927SAndroid Build Coastguard Worker    switch (size) {
49*61046927SAndroid Build Coastguard Worker    case AGX_SIZE_16:
50*61046927SAndroid Build Coastguard Worker       return 1;
51*61046927SAndroid Build Coastguard Worker    case AGX_SIZE_32:
52*61046927SAndroid Build Coastguard Worker       return 2;
53*61046927SAndroid Build Coastguard Worker    case AGX_SIZE_64:
54*61046927SAndroid Build Coastguard Worker       return 4;
55*61046927SAndroid Build Coastguard Worker    }
56*61046927SAndroid Build Coastguard Worker 
57*61046927SAndroid Build Coastguard Worker    unreachable("Invalid size");
58*61046927SAndroid Build Coastguard Worker }
59*61046927SAndroid Build Coastguard Worker 
60*61046927SAndroid Build Coastguard Worker /* Keep synced with hash_index */
61*61046927SAndroid Build Coastguard Worker typedef struct {
62*61046927SAndroid Build Coastguard Worker    /* Sufficient for as many SSA values, immediates, and uniforms as we need. */
63*61046927SAndroid Build Coastguard Worker    uint32_t value;
64*61046927SAndroid Build Coastguard Worker 
65*61046927SAndroid Build Coastguard Worker    /* Indicates that this source kills the referenced value (because it is the
66*61046927SAndroid Build Coastguard Worker     * last use in a block and the source is not live after the block). Set by
67*61046927SAndroid Build Coastguard Worker     * liveness analysis.
68*61046927SAndroid Build Coastguard Worker     */
69*61046927SAndroid Build Coastguard Worker    bool kill : 1;
70*61046927SAndroid Build Coastguard Worker 
71*61046927SAndroid Build Coastguard Worker    /* Cache hints */
72*61046927SAndroid Build Coastguard Worker    bool cache   : 1;
73*61046927SAndroid Build Coastguard Worker    bool discard : 1;
74*61046927SAndroid Build Coastguard Worker 
75*61046927SAndroid Build Coastguard Worker    /* src - float modifiers */
76*61046927SAndroid Build Coastguard Worker    bool abs : 1;
77*61046927SAndroid Build Coastguard Worker    bool neg : 1;
78*61046927SAndroid Build Coastguard Worker 
79*61046927SAndroid Build Coastguard Worker    /* Register class */
80*61046927SAndroid Build Coastguard Worker    bool memory : 1;
81*61046927SAndroid Build Coastguard Worker 
82*61046927SAndroid Build Coastguard Worker    unsigned channels_m1     : 3;
83*61046927SAndroid Build Coastguard Worker    enum agx_size size       : 2;
84*61046927SAndroid Build Coastguard Worker    enum agx_index_type type : 3;
85*61046927SAndroid Build Coastguard Worker    unsigned padding         : 18;
86*61046927SAndroid Build Coastguard Worker } agx_index;
87*61046927SAndroid Build Coastguard Worker 
88*61046927SAndroid Build Coastguard Worker static inline unsigned
agx_channels(agx_index idx)89*61046927SAndroid Build Coastguard Worker agx_channels(agx_index idx)
90*61046927SAndroid Build Coastguard Worker {
91*61046927SAndroid Build Coastguard Worker    return idx.channels_m1 + 1;
92*61046927SAndroid Build Coastguard Worker }
93*61046927SAndroid Build Coastguard Worker 
94*61046927SAndroid Build Coastguard Worker static inline unsigned
agx_index_size_16(agx_index idx)95*61046927SAndroid Build Coastguard Worker agx_index_size_16(agx_index idx)
96*61046927SAndroid Build Coastguard Worker {
97*61046927SAndroid Build Coastguard Worker    return agx_size_align_16(idx.size) * agx_channels(idx);
98*61046927SAndroid Build Coastguard Worker }
99*61046927SAndroid Build Coastguard Worker 
100*61046927SAndroid Build Coastguard Worker static inline agx_index
agx_get_vec_index(unsigned value,enum agx_size size,unsigned channels)101*61046927SAndroid Build Coastguard Worker agx_get_vec_index(unsigned value, enum agx_size size, unsigned channels)
102*61046927SAndroid Build Coastguard Worker {
103*61046927SAndroid Build Coastguard Worker    return (agx_index){
104*61046927SAndroid Build Coastguard Worker       .value = value,
105*61046927SAndroid Build Coastguard Worker       .channels_m1 = channels - 1,
106*61046927SAndroid Build Coastguard Worker       .size = size,
107*61046927SAndroid Build Coastguard Worker       .type = AGX_INDEX_NORMAL,
108*61046927SAndroid Build Coastguard Worker    };
109*61046927SAndroid Build Coastguard Worker }
110*61046927SAndroid Build Coastguard Worker 
111*61046927SAndroid Build Coastguard Worker static inline agx_index
agx_get_index(unsigned value,enum agx_size size)112*61046927SAndroid Build Coastguard Worker agx_get_index(unsigned value, enum agx_size size)
113*61046927SAndroid Build Coastguard Worker {
114*61046927SAndroid Build Coastguard Worker    return agx_get_vec_index(value, size, 1);
115*61046927SAndroid Build Coastguard Worker }
116*61046927SAndroid Build Coastguard Worker 
117*61046927SAndroid Build Coastguard Worker static inline agx_index
agx_immediate(uint32_t imm)118*61046927SAndroid Build Coastguard Worker agx_immediate(uint32_t imm)
119*61046927SAndroid Build Coastguard Worker {
120*61046927SAndroid Build Coastguard Worker    assert(imm < (1 << 16) && "overflowed immediate");
121*61046927SAndroid Build Coastguard Worker 
122*61046927SAndroid Build Coastguard Worker    return (agx_index){
123*61046927SAndroid Build Coastguard Worker       .value = imm,
124*61046927SAndroid Build Coastguard Worker       .size = AGX_SIZE_16,
125*61046927SAndroid Build Coastguard Worker       .type = AGX_INDEX_IMMEDIATE,
126*61046927SAndroid Build Coastguard Worker    };
127*61046927SAndroid Build Coastguard Worker }
128*61046927SAndroid Build Coastguard Worker 
129*61046927SAndroid Build Coastguard Worker static inline agx_index
agx_immediate_f(float f)130*61046927SAndroid Build Coastguard Worker agx_immediate_f(float f)
131*61046927SAndroid Build Coastguard Worker {
132*61046927SAndroid Build Coastguard Worker    assert(agx_minifloat_exact(f));
133*61046927SAndroid Build Coastguard Worker    return agx_immediate(agx_minifloat_encode(f));
134*61046927SAndroid Build Coastguard Worker }
135*61046927SAndroid Build Coastguard Worker 
136*61046927SAndroid Build Coastguard Worker /* in half-words, specify r0h as 1, r1 as 2... */
137*61046927SAndroid Build Coastguard Worker static inline agx_index
agx_register(uint32_t imm,enum agx_size size)138*61046927SAndroid Build Coastguard Worker agx_register(uint32_t imm, enum agx_size size)
139*61046927SAndroid Build Coastguard Worker {
140*61046927SAndroid Build Coastguard Worker    assert(imm < AGX_NUM_REGS);
141*61046927SAndroid Build Coastguard Worker 
142*61046927SAndroid Build Coastguard Worker    return (agx_index){
143*61046927SAndroid Build Coastguard Worker       .value = imm,
144*61046927SAndroid Build Coastguard Worker       .size = size,
145*61046927SAndroid Build Coastguard Worker       .type = AGX_INDEX_REGISTER,
146*61046927SAndroid Build Coastguard Worker    };
147*61046927SAndroid Build Coastguard Worker }
148*61046927SAndroid Build Coastguard Worker 
149*61046927SAndroid Build Coastguard Worker static inline agx_index
agx_memory_register(uint32_t imm,enum agx_size size)150*61046927SAndroid Build Coastguard Worker agx_memory_register(uint32_t imm, enum agx_size size)
151*61046927SAndroid Build Coastguard Worker {
152*61046927SAndroid Build Coastguard Worker    return (agx_index){
153*61046927SAndroid Build Coastguard Worker       .value = imm,
154*61046927SAndroid Build Coastguard Worker       .memory = true,
155*61046927SAndroid Build Coastguard Worker       .size = size,
156*61046927SAndroid Build Coastguard Worker       .type = AGX_INDEX_REGISTER,
157*61046927SAndroid Build Coastguard Worker    };
158*61046927SAndroid Build Coastguard Worker }
159*61046927SAndroid Build Coastguard Worker 
160*61046927SAndroid Build Coastguard Worker static inline agx_index
agx_register_like(uint32_t imm,agx_index like)161*61046927SAndroid Build Coastguard Worker agx_register_like(uint32_t imm, agx_index like)
162*61046927SAndroid Build Coastguard Worker {
163*61046927SAndroid Build Coastguard Worker    return (agx_index){
164*61046927SAndroid Build Coastguard Worker       .value = imm,
165*61046927SAndroid Build Coastguard Worker       .memory = like.memory,
166*61046927SAndroid Build Coastguard Worker       .channels_m1 = like.channels_m1,
167*61046927SAndroid Build Coastguard Worker       .size = like.size,
168*61046927SAndroid Build Coastguard Worker       .type = AGX_INDEX_REGISTER,
169*61046927SAndroid Build Coastguard Worker    };
170*61046927SAndroid Build Coastguard Worker }
171*61046927SAndroid Build Coastguard Worker 
172*61046927SAndroid Build Coastguard Worker static inline agx_index
agx_undef(enum agx_size size)173*61046927SAndroid Build Coastguard Worker agx_undef(enum agx_size size)
174*61046927SAndroid Build Coastguard Worker {
175*61046927SAndroid Build Coastguard Worker    return (agx_index){
176*61046927SAndroid Build Coastguard Worker       .size = size,
177*61046927SAndroid Build Coastguard Worker       .type = AGX_INDEX_UNDEF,
178*61046927SAndroid Build Coastguard Worker    };
179*61046927SAndroid Build Coastguard Worker }
180*61046927SAndroid Build Coastguard Worker 
181*61046927SAndroid Build Coastguard Worker /* Also in half-words */
182*61046927SAndroid Build Coastguard Worker static inline agx_index
agx_uniform(uint32_t imm,enum agx_size size)183*61046927SAndroid Build Coastguard Worker agx_uniform(uint32_t imm, enum agx_size size)
184*61046927SAndroid Build Coastguard Worker {
185*61046927SAndroid Build Coastguard Worker    assert(imm < AGX_NUM_UNIFORMS);
186*61046927SAndroid Build Coastguard Worker 
187*61046927SAndroid Build Coastguard Worker    return (agx_index){
188*61046927SAndroid Build Coastguard Worker       .value = imm,
189*61046927SAndroid Build Coastguard Worker       .size = size,
190*61046927SAndroid Build Coastguard Worker       .type = AGX_INDEX_UNIFORM,
191*61046927SAndroid Build Coastguard Worker    };
192*61046927SAndroid Build Coastguard Worker }
193*61046927SAndroid Build Coastguard Worker 
194*61046927SAndroid Build Coastguard Worker static inline agx_index
agx_null()195*61046927SAndroid Build Coastguard Worker agx_null()
196*61046927SAndroid Build Coastguard Worker {
197*61046927SAndroid Build Coastguard Worker    return (agx_index){.type = AGX_INDEX_NULL};
198*61046927SAndroid Build Coastguard Worker }
199*61046927SAndroid Build Coastguard Worker 
200*61046927SAndroid Build Coastguard Worker static inline agx_index
agx_zero()201*61046927SAndroid Build Coastguard Worker agx_zero()
202*61046927SAndroid Build Coastguard Worker {
203*61046927SAndroid Build Coastguard Worker    return agx_immediate(0);
204*61046927SAndroid Build Coastguard Worker }
205*61046927SAndroid Build Coastguard Worker 
206*61046927SAndroid Build Coastguard Worker /* IEEE 754 additive identity -0.0, stored as an 8-bit AGX minifloat: mantissa
207*61046927SAndroid Build Coastguard Worker  * = exponent = 0, sign bit set */
208*61046927SAndroid Build Coastguard Worker 
209*61046927SAndroid Build Coastguard Worker static inline agx_index
agx_negzero()210*61046927SAndroid Build Coastguard Worker agx_negzero()
211*61046927SAndroid Build Coastguard Worker {
212*61046927SAndroid Build Coastguard Worker    return agx_immediate(0x80);
213*61046927SAndroid Build Coastguard Worker }
214*61046927SAndroid Build Coastguard Worker 
215*61046927SAndroid Build Coastguard Worker static inline agx_index
agx_abs(agx_index idx)216*61046927SAndroid Build Coastguard Worker agx_abs(agx_index idx)
217*61046927SAndroid Build Coastguard Worker {
218*61046927SAndroid Build Coastguard Worker    idx.abs = true;
219*61046927SAndroid Build Coastguard Worker    idx.neg = false;
220*61046927SAndroid Build Coastguard Worker    return idx;
221*61046927SAndroid Build Coastguard Worker }
222*61046927SAndroid Build Coastguard Worker 
223*61046927SAndroid Build Coastguard Worker static inline agx_index
agx_neg(agx_index idx)224*61046927SAndroid Build Coastguard Worker agx_neg(agx_index idx)
225*61046927SAndroid Build Coastguard Worker {
226*61046927SAndroid Build Coastguard Worker    idx.neg ^= true;
227*61046927SAndroid Build Coastguard Worker    return idx;
228*61046927SAndroid Build Coastguard Worker }
229*61046927SAndroid Build Coastguard Worker 
230*61046927SAndroid Build Coastguard Worker /* Replaces an index, preserving any modifiers */
231*61046927SAndroid Build Coastguard Worker 
232*61046927SAndroid Build Coastguard Worker static inline agx_index
agx_replace_index(agx_index old,agx_index replacement)233*61046927SAndroid Build Coastguard Worker agx_replace_index(agx_index old, agx_index replacement)
234*61046927SAndroid Build Coastguard Worker {
235*61046927SAndroid Build Coastguard Worker    replacement.abs = old.abs;
236*61046927SAndroid Build Coastguard Worker    replacement.neg = old.neg;
237*61046927SAndroid Build Coastguard Worker    return replacement;
238*61046927SAndroid Build Coastguard Worker }
239*61046927SAndroid Build Coastguard Worker 
240*61046927SAndroid Build Coastguard Worker static inline bool
agx_is_null(agx_index idx)241*61046927SAndroid Build Coastguard Worker agx_is_null(agx_index idx)
242*61046927SAndroid Build Coastguard Worker {
243*61046927SAndroid Build Coastguard Worker    return idx.type == AGX_INDEX_NULL;
244*61046927SAndroid Build Coastguard Worker }
245*61046927SAndroid Build Coastguard Worker 
246*61046927SAndroid Build Coastguard Worker /* Compares equivalence as references */
247*61046927SAndroid Build Coastguard Worker 
248*61046927SAndroid Build Coastguard Worker static inline bool
agx_is_equiv(agx_index left,agx_index right)249*61046927SAndroid Build Coastguard Worker agx_is_equiv(agx_index left, agx_index right)
250*61046927SAndroid Build Coastguard Worker {
251*61046927SAndroid Build Coastguard Worker    return (left.type == right.type) && (left.value == right.value);
252*61046927SAndroid Build Coastguard Worker }
253*61046927SAndroid Build Coastguard Worker 
254*61046927SAndroid Build Coastguard Worker enum agx_icond {
255*61046927SAndroid Build Coastguard Worker    AGX_ICOND_UEQ = 0,
256*61046927SAndroid Build Coastguard Worker    AGX_ICOND_ULT = 1,
257*61046927SAndroid Build Coastguard Worker    AGX_ICOND_UGT = 2,
258*61046927SAndroid Build Coastguard Worker    /* unknown */
259*61046927SAndroid Build Coastguard Worker    AGX_ICOND_SEQ = 4,
260*61046927SAndroid Build Coastguard Worker    AGX_ICOND_SLT = 5,
261*61046927SAndroid Build Coastguard Worker    AGX_ICOND_SGT = 6,
262*61046927SAndroid Build Coastguard Worker    /* unknown */
263*61046927SAndroid Build Coastguard Worker };
264*61046927SAndroid Build Coastguard Worker 
265*61046927SAndroid Build Coastguard Worker enum agx_fcond {
266*61046927SAndroid Build Coastguard Worker    AGX_FCOND_EQ = 0,
267*61046927SAndroid Build Coastguard Worker    AGX_FCOND_LT = 1,
268*61046927SAndroid Build Coastguard Worker    AGX_FCOND_GT = 2,
269*61046927SAndroid Build Coastguard Worker    AGX_FCOND_LTN = 3,
270*61046927SAndroid Build Coastguard Worker    /* unknown */
271*61046927SAndroid Build Coastguard Worker    AGX_FCOND_GE = 5,
272*61046927SAndroid Build Coastguard Worker    AGX_FCOND_LE = 6,
273*61046927SAndroid Build Coastguard Worker    AGX_FCOND_GTN = 7,
274*61046927SAndroid Build Coastguard Worker };
275*61046927SAndroid Build Coastguard Worker 
276*61046927SAndroid Build Coastguard Worker enum agx_round {
277*61046927SAndroid Build Coastguard Worker    AGX_ROUND_RTZ = 0,
278*61046927SAndroid Build Coastguard Worker    AGX_ROUND_RTE = 1,
279*61046927SAndroid Build Coastguard Worker };
280*61046927SAndroid Build Coastguard Worker 
281*61046927SAndroid Build Coastguard Worker enum agx_convert {
282*61046927SAndroid Build Coastguard Worker    AGX_CONVERT_U8_TO_F = 0,
283*61046927SAndroid Build Coastguard Worker    AGX_CONVERT_S8_TO_F = 1,
284*61046927SAndroid Build Coastguard Worker    AGX_CONVERT_F_TO_U16 = 4,
285*61046927SAndroid Build Coastguard Worker    AGX_CONVERT_F_TO_S16 = 5,
286*61046927SAndroid Build Coastguard Worker    AGX_CONVERT_U16_TO_F = 6,
287*61046927SAndroid Build Coastguard Worker    AGX_CONVERT_S16_TO_F = 7,
288*61046927SAndroid Build Coastguard Worker    AGX_CONVERT_F_TO_U32 = 8,
289*61046927SAndroid Build Coastguard Worker    AGX_CONVERT_F_TO_S32 = 9,
290*61046927SAndroid Build Coastguard Worker    AGX_CONVERT_U32_TO_F = 10,
291*61046927SAndroid Build Coastguard Worker    AGX_CONVERT_S32_TO_F = 11
292*61046927SAndroid Build Coastguard Worker };
293*61046927SAndroid Build Coastguard Worker 
294*61046927SAndroid Build Coastguard Worker enum agx_lod_mode {
295*61046927SAndroid Build Coastguard Worker    AGX_LOD_MODE_AUTO_LOD = 0,
296*61046927SAndroid Build Coastguard Worker    AGX_LOD_MODE_AUTO_LOD_BIAS_UNIFORM = 1,
297*61046927SAndroid Build Coastguard Worker    AGX_LOD_MODE_LOD_MIN_UNIFORM = 2,
298*61046927SAndroid Build Coastguard Worker    AGX_LOD_MODE_AUTO_LOD_BIAS = 5,
299*61046927SAndroid Build Coastguard Worker    AGX_LOD_MODE_LOD_GRAD = 4,
300*61046927SAndroid Build Coastguard Worker    AGX_LOD_MODE_LOD_MIN = 6,
301*61046927SAndroid Build Coastguard Worker    AGX_LOD_MODE_AUTO_LOD_BIAS_MIN_UNIFORM = 9,
302*61046927SAndroid Build Coastguard Worker    AGX_LOD_MODE_LOD_GRAD_MIN = 12,
303*61046927SAndroid Build Coastguard Worker    AGX_LOD_MODE_AUTO_LOD_BIAS_MIN = 13,
304*61046927SAndroid Build Coastguard Worker };
305*61046927SAndroid Build Coastguard Worker 
306*61046927SAndroid Build Coastguard Worker /* Forward declare for branch target */
307*61046927SAndroid Build Coastguard Worker struct agx_block;
308*61046927SAndroid Build Coastguard Worker 
309*61046927SAndroid Build Coastguard Worker /* Keep synced with hash_instr */
310*61046927SAndroid Build Coastguard Worker typedef struct {
311*61046927SAndroid Build Coastguard Worker    /* Must be first */
312*61046927SAndroid Build Coastguard Worker    struct list_head link;
313*61046927SAndroid Build Coastguard Worker 
314*61046927SAndroid Build Coastguard Worker    /* The sources list. */
315*61046927SAndroid Build Coastguard Worker    agx_index *src;
316*61046927SAndroid Build Coastguard Worker 
317*61046927SAndroid Build Coastguard Worker    /* Data flow */
318*61046927SAndroid Build Coastguard Worker    agx_index *dest;
319*61046927SAndroid Build Coastguard Worker 
320*61046927SAndroid Build Coastguard Worker    enum agx_opcode op;
321*61046927SAndroid Build Coastguard Worker 
322*61046927SAndroid Build Coastguard Worker    uint8_t nr_dests;
323*61046927SAndroid Build Coastguard Worker    uint8_t nr_srcs;
324*61046927SAndroid Build Coastguard Worker 
325*61046927SAndroid Build Coastguard Worker    /* TODO: More efficient */
326*61046927SAndroid Build Coastguard Worker    union {
327*61046927SAndroid Build Coastguard Worker       enum agx_icond icond;
328*61046927SAndroid Build Coastguard Worker       enum agx_fcond fcond;
329*61046927SAndroid Build Coastguard Worker    };
330*61046927SAndroid Build Coastguard Worker 
331*61046927SAndroid Build Coastguard Worker    union {
332*61046927SAndroid Build Coastguard Worker       uint64_t imm;
333*61046927SAndroid Build Coastguard Worker       uint32_t writeout;
334*61046927SAndroid Build Coastguard Worker       uint32_t truth_table;
335*61046927SAndroid Build Coastguard Worker       uint32_t component;
336*61046927SAndroid Build Coastguard Worker       uint32_t channels;
337*61046927SAndroid Build Coastguard Worker       uint32_t bfi_mask;
338*61046927SAndroid Build Coastguard Worker       uint16_t pixel_offset;
339*61046927SAndroid Build Coastguard Worker       uint16_t zs;
340*61046927SAndroid Build Coastguard Worker       int16_t stack_size;
341*61046927SAndroid Build Coastguard Worker       enum agx_sr sr;
342*61046927SAndroid Build Coastguard Worker       enum agx_round round;
343*61046927SAndroid Build Coastguard Worker       enum agx_atomic_opc atomic_opc;
344*61046927SAndroid Build Coastguard Worker       enum agx_lod_mode lod_mode;
345*61046927SAndroid Build Coastguard Worker       enum agx_simd_op simd_op;
346*61046927SAndroid Build Coastguard Worker       struct agx_block *target;
347*61046927SAndroid Build Coastguard Worker 
348*61046927SAndroid Build Coastguard Worker       /* As a special case to workaround ordering issues when translating phis,
349*61046927SAndroid Build Coastguard Worker        * if nr_srcs == 0 and the opcode is PHI, points to the NIR phi.
350*61046927SAndroid Build Coastguard Worker        */
351*61046927SAndroid Build Coastguard Worker       nir_phi_instr *phi;
352*61046927SAndroid Build Coastguard Worker    };
353*61046927SAndroid Build Coastguard Worker 
354*61046927SAndroid Build Coastguard Worker    /* For local access */
355*61046927SAndroid Build Coastguard Worker    enum agx_format format;
356*61046927SAndroid Build Coastguard Worker 
357*61046927SAndroid Build Coastguard Worker    /* Number of nested control flow layers to jump by. TODO: Optimize */
358*61046927SAndroid Build Coastguard Worker    uint32_t nest;
359*61046927SAndroid Build Coastguard Worker 
360*61046927SAndroid Build Coastguard Worker    /* Invert icond/fcond */
361*61046927SAndroid Build Coastguard Worker    bool invert_cond : 1;
362*61046927SAndroid Build Coastguard Worker 
363*61046927SAndroid Build Coastguard Worker    /* TODO: Handle tex ops more efficient */
364*61046927SAndroid Build Coastguard Worker    enum agx_dim dim       : 4;
365*61046927SAndroid Build Coastguard Worker    bool offset            : 1;
366*61046927SAndroid Build Coastguard Worker    bool shadow            : 1;
367*61046927SAndroid Build Coastguard Worker    bool query_lod         : 1;
368*61046927SAndroid Build Coastguard Worker    enum agx_gather gather : 3;
369*61046927SAndroid Build Coastguard Worker 
370*61046927SAndroid Build Coastguard Worker    /* TODO: Handle tilebuffer ops more efficient */
371*61046927SAndroid Build Coastguard Worker    bool explicit_coords : 1;
372*61046927SAndroid Build Coastguard Worker 
373*61046927SAndroid Build Coastguard Worker    /* TODO: Handle iter ops more efficient */
374*61046927SAndroid Build Coastguard Worker    enum agx_interpolation interpolation : 2;
375*61046927SAndroid Build Coastguard Worker 
376*61046927SAndroid Build Coastguard Worker    /* Final st_vary op */
377*61046927SAndroid Build Coastguard Worker    bool last : 1;
378*61046927SAndroid Build Coastguard Worker 
379*61046927SAndroid Build Coastguard Worker    /* Shift for a bitwise or memory op (conflicts with format for memory ops) */
380*61046927SAndroid Build Coastguard Worker    unsigned shift : 4;
381*61046927SAndroid Build Coastguard Worker 
382*61046927SAndroid Build Coastguard Worker    /* Scoreboard index, 0 or 1. Leave as 0 for instructions that do not require
383*61046927SAndroid Build Coastguard Worker     * scoreboarding (everything but memory load/store and texturing). */
384*61046927SAndroid Build Coastguard Worker    unsigned scoreboard : 1;
385*61046927SAndroid Build Coastguard Worker 
386*61046927SAndroid Build Coastguard Worker    /* Output modifiers */
387*61046927SAndroid Build Coastguard Worker    bool saturate : 1;
388*61046927SAndroid Build Coastguard Worker    unsigned mask : 4;
389*61046927SAndroid Build Coastguard Worker 
390*61046927SAndroid Build Coastguard Worker    unsigned padding : 8;
391*61046927SAndroid Build Coastguard Worker } agx_instr;
392*61046927SAndroid Build Coastguard Worker 
393*61046927SAndroid Build Coastguard Worker static inline void
agx_replace_src(agx_instr * I,unsigned src_index,agx_index replacement)394*61046927SAndroid Build Coastguard Worker agx_replace_src(agx_instr *I, unsigned src_index, agx_index replacement)
395*61046927SAndroid Build Coastguard Worker {
396*61046927SAndroid Build Coastguard Worker    I->src[src_index] = agx_replace_index(I->src[src_index], replacement);
397*61046927SAndroid Build Coastguard Worker }
398*61046927SAndroid Build Coastguard Worker 
399*61046927SAndroid Build Coastguard Worker struct agx_block;
400*61046927SAndroid Build Coastguard Worker 
401*61046927SAndroid Build Coastguard Worker typedef struct agx_block {
402*61046927SAndroid Build Coastguard Worker    /* Link to next block. Must be first */
403*61046927SAndroid Build Coastguard Worker    struct list_head link;
404*61046927SAndroid Build Coastguard Worker 
405*61046927SAndroid Build Coastguard Worker    /* List of instructions emitted for the current block */
406*61046927SAndroid Build Coastguard Worker    struct list_head instructions;
407*61046927SAndroid Build Coastguard Worker 
408*61046927SAndroid Build Coastguard Worker    /* Index of the block in source order */
409*61046927SAndroid Build Coastguard Worker    unsigned index;
410*61046927SAndroid Build Coastguard Worker 
411*61046927SAndroid Build Coastguard Worker    /* Control flow graph */
412*61046927SAndroid Build Coastguard Worker    struct agx_block *successors[2];
413*61046927SAndroid Build Coastguard Worker    struct util_dynarray predecessors;
414*61046927SAndroid Build Coastguard Worker    bool unconditional_jumps;
415*61046927SAndroid Build Coastguard Worker 
416*61046927SAndroid Build Coastguard Worker    /* Liveness analysis results */
417*61046927SAndroid Build Coastguard Worker    BITSET_WORD *live_in;
418*61046927SAndroid Build Coastguard Worker    BITSET_WORD *live_out;
419*61046927SAndroid Build Coastguard Worker 
420*61046927SAndroid Build Coastguard Worker    /* For visited blocks during register assignment and live-out registers, the
421*61046927SAndroid Build Coastguard Worker     * mapping of registers to SSA names at the end of the block. This is dense,
422*61046927SAndroid Build Coastguard Worker     * unlike its inverse.
423*61046927SAndroid Build Coastguard Worker     */
424*61046927SAndroid Build Coastguard Worker    uint32_t *reg_to_ssa_out[2];
425*61046927SAndroid Build Coastguard Worker 
426*61046927SAndroid Build Coastguard Worker    /* Is this block a loop header? If not, all of its predecessors precede it in
427*61046927SAndroid Build Coastguard Worker     * source order.
428*61046927SAndroid Build Coastguard Worker     */
429*61046927SAndroid Build Coastguard Worker    bool loop_header;
430*61046927SAndroid Build Coastguard Worker 
431*61046927SAndroid Build Coastguard Worker    /* Offset of the block in the emitted binary */
432*61046927SAndroid Build Coastguard Worker    off_t offset, last_offset;
433*61046927SAndroid Build Coastguard Worker 
434*61046927SAndroid Build Coastguard Worker    /** Available for passes to use for metadata */
435*61046927SAndroid Build Coastguard Worker    uint8_t pass_flags;
436*61046927SAndroid Build Coastguard Worker } agx_block;
437*61046927SAndroid Build Coastguard Worker 
438*61046927SAndroid Build Coastguard Worker typedef struct {
439*61046927SAndroid Build Coastguard Worker    nir_shader *nir;
440*61046927SAndroid Build Coastguard Worker    gl_shader_stage stage;
441*61046927SAndroid Build Coastguard Worker    bool is_preamble;
442*61046927SAndroid Build Coastguard Worker    unsigned scratch_size;
443*61046927SAndroid Build Coastguard Worker 
444*61046927SAndroid Build Coastguard Worker    struct list_head blocks; /* list of agx_block */
445*61046927SAndroid Build Coastguard Worker    struct agx_shader_info *out;
446*61046927SAndroid Build Coastguard Worker    struct agx_shader_key *key;
447*61046927SAndroid Build Coastguard Worker 
448*61046927SAndroid Build Coastguard Worker    /* Maximum block index */
449*61046927SAndroid Build Coastguard Worker    unsigned num_blocks;
450*61046927SAndroid Build Coastguard Worker 
451*61046927SAndroid Build Coastguard Worker    /* For creating temporaries */
452*61046927SAndroid Build Coastguard Worker    unsigned alloc;
453*61046927SAndroid Build Coastguard Worker 
454*61046927SAndroid Build Coastguard Worker    /* Does the shader statically use scratch memory? */
455*61046927SAndroid Build Coastguard Worker    bool any_scratch;
456*61046927SAndroid Build Coastguard Worker 
457*61046927SAndroid Build Coastguard Worker    /* I don't really understand how writeout ops work yet */
458*61046927SAndroid Build Coastguard Worker    bool did_writeout;
459*61046927SAndroid Build Coastguard Worker 
460*61046927SAndroid Build Coastguard Worker    /* Has r0l been zeroed yet due to control flow? */
461*61046927SAndroid Build Coastguard Worker    bool any_cf;
462*61046927SAndroid Build Coastguard Worker 
463*61046927SAndroid Build Coastguard Worker    /* Do we need r0h zero throughout the program to handle quad-divergent
464*61046927SAndroid Build Coastguard Worker     * shuffle?
465*61046927SAndroid Build Coastguard Worker     */
466*61046927SAndroid Build Coastguard Worker    bool any_quad_divergent_shuffle;
467*61046927SAndroid Build Coastguard Worker 
468*61046927SAndroid Build Coastguard Worker    /* Number of nested control flow structures within the innermost loop. Since
469*61046927SAndroid Build Coastguard Worker     * NIR is just loop and if-else, this is the number of nested if-else
470*61046927SAndroid Build Coastguard Worker     * statements in the loop */
471*61046927SAndroid Build Coastguard Worker    unsigned loop_nesting;
472*61046927SAndroid Build Coastguard Worker 
473*61046927SAndroid Build Coastguard Worker    /* Total nesting across all loops, to determine if we need push_exec */
474*61046927SAndroid Build Coastguard Worker    unsigned total_nesting;
475*61046927SAndroid Build Coastguard Worker 
476*61046927SAndroid Build Coastguard Worker    /* Whether loop being emitted used any `continue` jumps */
477*61046927SAndroid Build Coastguard Worker    bool loop_continues;
478*61046927SAndroid Build Coastguard Worker 
479*61046927SAndroid Build Coastguard Worker    /* During instruction selection, for inserting control flow */
480*61046927SAndroid Build Coastguard Worker    agx_block *current_block;
481*61046927SAndroid Build Coastguard Worker    agx_block *continue_block;
482*61046927SAndroid Build Coastguard Worker    agx_block *break_block;
483*61046927SAndroid Build Coastguard Worker    agx_block *after_block;
484*61046927SAndroid Build Coastguard Worker    agx_block **indexed_nir_blocks;
485*61046927SAndroid Build Coastguard Worker 
486*61046927SAndroid Build Coastguard Worker    /* During instruction selection, map from vector agx_index to its scalar
487*61046927SAndroid Build Coastguard Worker     * components, populated by a split. */
488*61046927SAndroid Build Coastguard Worker    struct hash_table_u64 *allocated_vec;
489*61046927SAndroid Build Coastguard Worker 
490*61046927SAndroid Build Coastguard Worker    /* During instruction selection, preloaded values or NULL if it hasn't been
491*61046927SAndroid Build Coastguard Worker     * preloaded.
492*61046927SAndroid Build Coastguard Worker     */
493*61046927SAndroid Build Coastguard Worker    agx_index preloaded[AGX_NUM_REGS];
494*61046927SAndroid Build Coastguard Worker 
495*61046927SAndroid Build Coastguard Worker    /* Beginning of our stack allocation used for spilling, below that is
496*61046927SAndroid Build Coastguard Worker     * NIR-level scratch.
497*61046927SAndroid Build Coastguard Worker     */
498*61046927SAndroid Build Coastguard Worker    unsigned spill_base;
499*61046927SAndroid Build Coastguard Worker 
500*61046927SAndroid Build Coastguard Worker    /* Beginning of stack allocation used for parallel copy lowering */
501*61046927SAndroid Build Coastguard Worker    bool has_spill_pcopy_reserved;
502*61046927SAndroid Build Coastguard Worker    unsigned spill_pcopy_base;
503*61046927SAndroid Build Coastguard Worker 
504*61046927SAndroid Build Coastguard Worker    /* Stats for shader-db */
505*61046927SAndroid Build Coastguard Worker    unsigned loop_count;
506*61046927SAndroid Build Coastguard Worker    unsigned max_reg;
507*61046927SAndroid Build Coastguard Worker } agx_context;
508*61046927SAndroid Build Coastguard Worker 
509*61046927SAndroid Build Coastguard Worker static inline void
agx_remove_instruction(agx_instr * ins)510*61046927SAndroid Build Coastguard Worker agx_remove_instruction(agx_instr *ins)
511*61046927SAndroid Build Coastguard Worker {
512*61046927SAndroid Build Coastguard Worker    list_del(&ins->link);
513*61046927SAndroid Build Coastguard Worker }
514*61046927SAndroid Build Coastguard Worker 
515*61046927SAndroid Build Coastguard Worker static inline agx_index
agx_vec_temp(agx_context * ctx,enum agx_size size,unsigned channels)516*61046927SAndroid Build Coastguard Worker agx_vec_temp(agx_context *ctx, enum agx_size size, unsigned channels)
517*61046927SAndroid Build Coastguard Worker {
518*61046927SAndroid Build Coastguard Worker    return agx_get_vec_index(ctx->alloc++, size, channels);
519*61046927SAndroid Build Coastguard Worker }
520*61046927SAndroid Build Coastguard Worker 
521*61046927SAndroid Build Coastguard Worker static inline agx_index
agx_temp(agx_context * ctx,enum agx_size size)522*61046927SAndroid Build Coastguard Worker agx_temp(agx_context *ctx, enum agx_size size)
523*61046927SAndroid Build Coastguard Worker {
524*61046927SAndroid Build Coastguard Worker    return agx_get_index(ctx->alloc++, size);
525*61046927SAndroid Build Coastguard Worker }
526*61046927SAndroid Build Coastguard Worker 
527*61046927SAndroid Build Coastguard Worker static inline agx_index
agx_temp_like(agx_context * ctx,agx_index idx)528*61046927SAndroid Build Coastguard Worker agx_temp_like(agx_context *ctx, agx_index idx)
529*61046927SAndroid Build Coastguard Worker {
530*61046927SAndroid Build Coastguard Worker    idx.value = ctx->alloc++;
531*61046927SAndroid Build Coastguard Worker    return idx;
532*61046927SAndroid Build Coastguard Worker }
533*61046927SAndroid Build Coastguard Worker 
534*61046927SAndroid Build Coastguard Worker static enum agx_size
agx_size_for_bits(unsigned bits)535*61046927SAndroid Build Coastguard Worker agx_size_for_bits(unsigned bits)
536*61046927SAndroid Build Coastguard Worker {
537*61046927SAndroid Build Coastguard Worker    switch (bits) {
538*61046927SAndroid Build Coastguard Worker    case 1:
539*61046927SAndroid Build Coastguard Worker    case 8:
540*61046927SAndroid Build Coastguard Worker    case 16:
541*61046927SAndroid Build Coastguard Worker       return AGX_SIZE_16;
542*61046927SAndroid Build Coastguard Worker    case 32:
543*61046927SAndroid Build Coastguard Worker       return AGX_SIZE_32;
544*61046927SAndroid Build Coastguard Worker    case 64:
545*61046927SAndroid Build Coastguard Worker       return AGX_SIZE_64;
546*61046927SAndroid Build Coastguard Worker    default:
547*61046927SAndroid Build Coastguard Worker       unreachable("Invalid bitsize");
548*61046927SAndroid Build Coastguard Worker    }
549*61046927SAndroid Build Coastguard Worker }
550*61046927SAndroid Build Coastguard Worker 
551*61046927SAndroid Build Coastguard Worker static inline agx_index
agx_def_index(nir_def * ssa)552*61046927SAndroid Build Coastguard Worker agx_def_index(nir_def *ssa)
553*61046927SAndroid Build Coastguard Worker {
554*61046927SAndroid Build Coastguard Worker    return agx_get_vec_index(ssa->index, agx_size_for_bits(ssa->bit_size),
555*61046927SAndroid Build Coastguard Worker                             ssa->num_components);
556*61046927SAndroid Build Coastguard Worker }
557*61046927SAndroid Build Coastguard Worker 
558*61046927SAndroid Build Coastguard Worker static inline agx_index
agx_src_index(nir_src * src)559*61046927SAndroid Build Coastguard Worker agx_src_index(nir_src *src)
560*61046927SAndroid Build Coastguard Worker {
561*61046927SAndroid Build Coastguard Worker    return agx_def_index(src->ssa);
562*61046927SAndroid Build Coastguard Worker }
563*61046927SAndroid Build Coastguard Worker 
564*61046927SAndroid Build Coastguard Worker static inline agx_index
agx_vec_for_def(agx_context * ctx,nir_def * def)565*61046927SAndroid Build Coastguard Worker agx_vec_for_def(agx_context *ctx, nir_def *def)
566*61046927SAndroid Build Coastguard Worker {
567*61046927SAndroid Build Coastguard Worker    return agx_vec_temp(ctx, agx_size_for_bits(def->bit_size),
568*61046927SAndroid Build Coastguard Worker                        def->num_components);
569*61046927SAndroid Build Coastguard Worker }
570*61046927SAndroid Build Coastguard Worker 
571*61046927SAndroid Build Coastguard Worker static inline agx_index
agx_vec_for_intr(agx_context * ctx,nir_intrinsic_instr * instr)572*61046927SAndroid Build Coastguard Worker agx_vec_for_intr(agx_context *ctx, nir_intrinsic_instr *instr)
573*61046927SAndroid Build Coastguard Worker {
574*61046927SAndroid Build Coastguard Worker    return agx_vec_for_def(ctx, &instr->def);
575*61046927SAndroid Build Coastguard Worker }
576*61046927SAndroid Build Coastguard Worker 
577*61046927SAndroid Build Coastguard Worker static inline unsigned
agx_num_predecessors(agx_block * block)578*61046927SAndroid Build Coastguard Worker agx_num_predecessors(agx_block *block)
579*61046927SAndroid Build Coastguard Worker {
580*61046927SAndroid Build Coastguard Worker    return util_dynarray_num_elements(&block->predecessors, agx_block *);
581*61046927SAndroid Build Coastguard Worker }
582*61046927SAndroid Build Coastguard Worker 
583*61046927SAndroid Build Coastguard Worker static inline unsigned
agx_num_successors(agx_block * block)584*61046927SAndroid Build Coastguard Worker agx_num_successors(agx_block *block)
585*61046927SAndroid Build Coastguard Worker {
586*61046927SAndroid Build Coastguard Worker    STATIC_ASSERT(ARRAY_SIZE(block->successors) == 2);
587*61046927SAndroid Build Coastguard Worker    return (block->successors[0] ? 1 : 0) + (block->successors[1] ? 1 : 0);
588*61046927SAndroid Build Coastguard Worker }
589*61046927SAndroid Build Coastguard Worker 
590*61046927SAndroid Build Coastguard Worker static inline agx_block *
agx_start_block(agx_context * ctx)591*61046927SAndroid Build Coastguard Worker agx_start_block(agx_context *ctx)
592*61046927SAndroid Build Coastguard Worker {
593*61046927SAndroid Build Coastguard Worker    agx_block *first = list_first_entry(&ctx->blocks, agx_block, link);
594*61046927SAndroid Build Coastguard Worker    assert(agx_num_predecessors(first) == 0);
595*61046927SAndroid Build Coastguard Worker    return first;
596*61046927SAndroid Build Coastguard Worker }
597*61046927SAndroid Build Coastguard Worker 
598*61046927SAndroid Build Coastguard Worker static inline agx_block *
agx_end_block(agx_context * ctx)599*61046927SAndroid Build Coastguard Worker agx_end_block(agx_context *ctx)
600*61046927SAndroid Build Coastguard Worker {
601*61046927SAndroid Build Coastguard Worker    agx_block *last = list_last_entry(&ctx->blocks, agx_block, link);
602*61046927SAndroid Build Coastguard Worker    assert(agx_num_successors(last) == 0);
603*61046927SAndroid Build Coastguard Worker    return last;
604*61046927SAndroid Build Coastguard Worker }
605*61046927SAndroid Build Coastguard Worker 
606*61046927SAndroid Build Coastguard Worker void agx_block_add_successor(agx_block *block, agx_block *successor);
607*61046927SAndroid Build Coastguard Worker 
608*61046927SAndroid Build Coastguard Worker /* Iterators for AGX IR */
609*61046927SAndroid Build Coastguard Worker 
610*61046927SAndroid Build Coastguard Worker #define agx_foreach_block(ctx, v)                                              \
611*61046927SAndroid Build Coastguard Worker    list_for_each_entry(agx_block, v, &ctx->blocks, link)
612*61046927SAndroid Build Coastguard Worker 
613*61046927SAndroid Build Coastguard Worker #define agx_foreach_block_safe(ctx, v)                                         \
614*61046927SAndroid Build Coastguard Worker    list_for_each_entry_safe(agx_block, v, &ctx->blocks, link)
615*61046927SAndroid Build Coastguard Worker 
616*61046927SAndroid Build Coastguard Worker #define agx_foreach_block_rev(ctx, v)                                          \
617*61046927SAndroid Build Coastguard Worker    list_for_each_entry_rev(agx_block, v, &ctx->blocks, link)
618*61046927SAndroid Build Coastguard Worker 
619*61046927SAndroid Build Coastguard Worker #define agx_foreach_block_from(ctx, from, v)                                   \
620*61046927SAndroid Build Coastguard Worker    list_for_each_entry_from(agx_block, v, from, &ctx->blocks, link)
621*61046927SAndroid Build Coastguard Worker 
622*61046927SAndroid Build Coastguard Worker #define agx_foreach_block_from_rev(ctx, from, v)                               \
623*61046927SAndroid Build Coastguard Worker    list_for_each_entry_from_rev(agx_block, v, from, &ctx->blocks, link)
624*61046927SAndroid Build Coastguard Worker 
625*61046927SAndroid Build Coastguard Worker #define agx_foreach_instr_in_block(block, v)                                   \
626*61046927SAndroid Build Coastguard Worker    list_for_each_entry(agx_instr, v, &(block)->instructions, link)
627*61046927SAndroid Build Coastguard Worker 
628*61046927SAndroid Build Coastguard Worker #define agx_foreach_instr_in_block_rev(block, v)                               \
629*61046927SAndroid Build Coastguard Worker    list_for_each_entry_rev(agx_instr, v, &(block)->instructions, link)
630*61046927SAndroid Build Coastguard Worker 
631*61046927SAndroid Build Coastguard Worker #define agx_foreach_instr_in_block_safe(block, v)                              \
632*61046927SAndroid Build Coastguard Worker    list_for_each_entry_safe(agx_instr, v, &(block)->instructions, link)
633*61046927SAndroid Build Coastguard Worker 
634*61046927SAndroid Build Coastguard Worker #define agx_foreach_instr_in_block_safe_rev(block, v)                          \
635*61046927SAndroid Build Coastguard Worker    list_for_each_entry_safe_rev(agx_instr, v, &(block)->instructions, link)
636*61046927SAndroid Build Coastguard Worker 
637*61046927SAndroid Build Coastguard Worker #define agx_foreach_instr_in_block_from(block, v, from)                        \
638*61046927SAndroid Build Coastguard Worker    list_for_each_entry_from(agx_instr, v, from, &(block)->instructions, link)
639*61046927SAndroid Build Coastguard Worker 
640*61046927SAndroid Build Coastguard Worker #define agx_foreach_instr_in_block_from_rev(block, v, from)                    \
641*61046927SAndroid Build Coastguard Worker    list_for_each_entry_from_rev(agx_instr, v, from, &(block)->instructions,    \
642*61046927SAndroid Build Coastguard Worker                                 link)
643*61046927SAndroid Build Coastguard Worker 
644*61046927SAndroid Build Coastguard Worker #define agx_foreach_instr_global(ctx, v)                                       \
645*61046927SAndroid Build Coastguard Worker    agx_foreach_block(ctx, v_block)                                             \
646*61046927SAndroid Build Coastguard Worker       agx_foreach_instr_in_block(v_block, v)
647*61046927SAndroid Build Coastguard Worker 
648*61046927SAndroid Build Coastguard Worker #define agx_foreach_instr_global_rev(ctx, v)                                   \
649*61046927SAndroid Build Coastguard Worker    agx_foreach_block_rev(ctx, v_block)                                         \
650*61046927SAndroid Build Coastguard Worker       agx_foreach_instr_in_block_rev(v_block, v)
651*61046927SAndroid Build Coastguard Worker 
652*61046927SAndroid Build Coastguard Worker #define agx_foreach_instr_global_safe(ctx, v)                                  \
653*61046927SAndroid Build Coastguard Worker    agx_foreach_block(ctx, v_block)                                             \
654*61046927SAndroid Build Coastguard Worker       agx_foreach_instr_in_block_safe(v_block, v)
655*61046927SAndroid Build Coastguard Worker 
656*61046927SAndroid Build Coastguard Worker #define agx_foreach_instr_global_safe_rev(ctx, v)                              \
657*61046927SAndroid Build Coastguard Worker    agx_foreach_block_rev(ctx, v_block)                                         \
658*61046927SAndroid Build Coastguard Worker       agx_foreach_instr_in_block_safe_rev(v_block, v)
659*61046927SAndroid Build Coastguard Worker 
660*61046927SAndroid Build Coastguard Worker /* Based on set_foreach, expanded with automatic type casts */
661*61046927SAndroid Build Coastguard Worker 
662*61046927SAndroid Build Coastguard Worker #define agx_foreach_successor(blk, v)                                          \
663*61046927SAndroid Build Coastguard Worker    agx_block *v;                                                               \
664*61046927SAndroid Build Coastguard Worker    agx_block **_v;                                                             \
665*61046927SAndroid Build Coastguard Worker    for (_v = (agx_block **)&blk->successors[0], v = *_v;                       \
666*61046927SAndroid Build Coastguard Worker         v != NULL && _v < (agx_block **)&blk->successors[2]; _v++, v = *_v)
667*61046927SAndroid Build Coastguard Worker 
668*61046927SAndroid Build Coastguard Worker #define agx_foreach_predecessor(blk, v)                                        \
669*61046927SAndroid Build Coastguard Worker    util_dynarray_foreach(&blk->predecessors, agx_block *, v)
670*61046927SAndroid Build Coastguard Worker 
671*61046927SAndroid Build Coastguard Worker #define agx_foreach_src(ins, v) for (unsigned v = 0; v < ins->nr_srcs; ++v)
672*61046927SAndroid Build Coastguard Worker 
673*61046927SAndroid Build Coastguard Worker #define agx_foreach_src_rev(ins, v)                                            \
674*61046927SAndroid Build Coastguard Worker    for (signed v = ins->nr_srcs - 1; v >= 0; --v)
675*61046927SAndroid Build Coastguard Worker 
676*61046927SAndroid Build Coastguard Worker #define agx_foreach_dest(ins, v) for (unsigned v = 0; v < ins->nr_dests; ++v)
677*61046927SAndroid Build Coastguard Worker 
678*61046927SAndroid Build Coastguard Worker #define agx_foreach_dest_rev(ins, v)                                           \
679*61046927SAndroid Build Coastguard Worker    for (signed v = ins->nr_dests - 1; v >= 0; --v)
680*61046927SAndroid Build Coastguard Worker 
681*61046927SAndroid Build Coastguard Worker #define agx_foreach_ssa_src(ins, v)                                            \
682*61046927SAndroid Build Coastguard Worker    agx_foreach_src(ins, v)                                                     \
683*61046927SAndroid Build Coastguard Worker       if (ins->src[v].type == AGX_INDEX_NORMAL)
684*61046927SAndroid Build Coastguard Worker 
685*61046927SAndroid Build Coastguard Worker #define agx_foreach_ssa_src_rev(ins, v)                                        \
686*61046927SAndroid Build Coastguard Worker    agx_foreach_src_rev(ins, v)                                                 \
687*61046927SAndroid Build Coastguard Worker       if (ins->src[v].type == AGX_INDEX_NORMAL)
688*61046927SAndroid Build Coastguard Worker 
689*61046927SAndroid Build Coastguard Worker #define agx_foreach_ssa_dest(ins, v)                                           \
690*61046927SAndroid Build Coastguard Worker    agx_foreach_dest(ins, v)                                                    \
691*61046927SAndroid Build Coastguard Worker       if (ins->dest[v].type == AGX_INDEX_NORMAL)
692*61046927SAndroid Build Coastguard Worker 
693*61046927SAndroid Build Coastguard Worker #define agx_foreach_ssa_dest_rev(ins, v)                                       \
694*61046927SAndroid Build Coastguard Worker    agx_foreach_dest_rev(ins, v)                                                \
695*61046927SAndroid Build Coastguard Worker       if (ins->dest[v].type == AGX_INDEX_NORMAL)
696*61046927SAndroid Build Coastguard Worker 
697*61046927SAndroid Build Coastguard Worker /* Phis only come at the start (after else instructions) so we stop as soon as
698*61046927SAndroid Build Coastguard Worker  * we hit a non-phi
699*61046927SAndroid Build Coastguard Worker  */
700*61046927SAndroid Build Coastguard Worker #define agx_foreach_phi_in_block(block, v)                                     \
701*61046927SAndroid Build Coastguard Worker    agx_foreach_instr_in_block(block, v)                                        \
702*61046927SAndroid Build Coastguard Worker       if (v->op == AGX_OPCODE_ELSE_ICMP || v->op == AGX_OPCODE_ELSE_FCMP)      \
703*61046927SAndroid Build Coastguard Worker          continue;                                                             \
704*61046927SAndroid Build Coastguard Worker       else if (v->op != AGX_OPCODE_PHI)                                        \
705*61046927SAndroid Build Coastguard Worker          break;                                                                \
706*61046927SAndroid Build Coastguard Worker       else
707*61046927SAndroid Build Coastguard Worker 
708*61046927SAndroid Build Coastguard Worker #define agx_foreach_phi_in_block_safe(block, v)                                \
709*61046927SAndroid Build Coastguard Worker    agx_foreach_instr_in_block_safe(block, v)                                   \
710*61046927SAndroid Build Coastguard Worker       if (v->op == AGX_OPCODE_ELSE_ICMP || v->op == AGX_OPCODE_ELSE_FCMP)      \
711*61046927SAndroid Build Coastguard Worker          continue;                                                             \
712*61046927SAndroid Build Coastguard Worker       else if (v->op != AGX_OPCODE_PHI)                                        \
713*61046927SAndroid Build Coastguard Worker          break;                                                                \
714*61046927SAndroid Build Coastguard Worker       else
715*61046927SAndroid Build Coastguard Worker 
716*61046927SAndroid Build Coastguard Worker /*
717*61046927SAndroid Build Coastguard Worker  * Find the index of a predecessor, used as the implicit order of phi sources.
718*61046927SAndroid Build Coastguard Worker  */
719*61046927SAndroid Build Coastguard Worker static inline unsigned
agx_predecessor_index(agx_block * succ,agx_block * pred)720*61046927SAndroid Build Coastguard Worker agx_predecessor_index(agx_block *succ, agx_block *pred)
721*61046927SAndroid Build Coastguard Worker {
722*61046927SAndroid Build Coastguard Worker    unsigned index = 0;
723*61046927SAndroid Build Coastguard Worker 
724*61046927SAndroid Build Coastguard Worker    agx_foreach_predecessor(succ, x) {
725*61046927SAndroid Build Coastguard Worker       if (*x == pred)
726*61046927SAndroid Build Coastguard Worker          return index;
727*61046927SAndroid Build Coastguard Worker 
728*61046927SAndroid Build Coastguard Worker       index++;
729*61046927SAndroid Build Coastguard Worker    }
730*61046927SAndroid Build Coastguard Worker 
731*61046927SAndroid Build Coastguard Worker    unreachable("Invalid predecessor");
732*61046927SAndroid Build Coastguard Worker }
733*61046927SAndroid Build Coastguard Worker 
734*61046927SAndroid Build Coastguard Worker static inline agx_block *
agx_prev_block(agx_block * ins)735*61046927SAndroid Build Coastguard Worker agx_prev_block(agx_block *ins)
736*61046927SAndroid Build Coastguard Worker {
737*61046927SAndroid Build Coastguard Worker    return list_last_entry(&(ins->link), agx_block, link);
738*61046927SAndroid Build Coastguard Worker }
739*61046927SAndroid Build Coastguard Worker 
740*61046927SAndroid Build Coastguard Worker static inline agx_instr *
agx_prev_op(agx_instr * ins)741*61046927SAndroid Build Coastguard Worker agx_prev_op(agx_instr *ins)
742*61046927SAndroid Build Coastguard Worker {
743*61046927SAndroid Build Coastguard Worker    return list_last_entry(&(ins->link), agx_instr, link);
744*61046927SAndroid Build Coastguard Worker }
745*61046927SAndroid Build Coastguard Worker 
746*61046927SAndroid Build Coastguard Worker static inline agx_instr *
agx_first_instr(agx_block * block)747*61046927SAndroid Build Coastguard Worker agx_first_instr(agx_block *block)
748*61046927SAndroid Build Coastguard Worker {
749*61046927SAndroid Build Coastguard Worker    if (list_is_empty(&block->instructions))
750*61046927SAndroid Build Coastguard Worker       return NULL;
751*61046927SAndroid Build Coastguard Worker    else
752*61046927SAndroid Build Coastguard Worker       return list_first_entry(&block->instructions, agx_instr, link);
753*61046927SAndroid Build Coastguard Worker }
754*61046927SAndroid Build Coastguard Worker 
755*61046927SAndroid Build Coastguard Worker static inline agx_instr *
agx_last_instr(agx_block * block)756*61046927SAndroid Build Coastguard Worker agx_last_instr(agx_block *block)
757*61046927SAndroid Build Coastguard Worker {
758*61046927SAndroid Build Coastguard Worker    if (list_is_empty(&block->instructions))
759*61046927SAndroid Build Coastguard Worker       return NULL;
760*61046927SAndroid Build Coastguard Worker    else
761*61046927SAndroid Build Coastguard Worker       return list_last_entry(&block->instructions, agx_instr, link);
762*61046927SAndroid Build Coastguard Worker }
763*61046927SAndroid Build Coastguard Worker 
764*61046927SAndroid Build Coastguard Worker static inline agx_instr *
agx_next_op(agx_instr * ins)765*61046927SAndroid Build Coastguard Worker agx_next_op(agx_instr *ins)
766*61046927SAndroid Build Coastguard Worker {
767*61046927SAndroid Build Coastguard Worker    return list_first_entry(&(ins->link), agx_instr, link);
768*61046927SAndroid Build Coastguard Worker }
769*61046927SAndroid Build Coastguard Worker 
770*61046927SAndroid Build Coastguard Worker static inline agx_block *
agx_next_block(agx_block * block)771*61046927SAndroid Build Coastguard Worker agx_next_block(agx_block *block)
772*61046927SAndroid Build Coastguard Worker {
773*61046927SAndroid Build Coastguard Worker    return list_first_entry(&(block->link), agx_block, link);
774*61046927SAndroid Build Coastguard Worker }
775*61046927SAndroid Build Coastguard Worker 
776*61046927SAndroid Build Coastguard Worker static inline agx_block *
agx_exit_block(agx_context * ctx)777*61046927SAndroid Build Coastguard Worker agx_exit_block(agx_context *ctx)
778*61046927SAndroid Build Coastguard Worker {
779*61046927SAndroid Build Coastguard Worker    agx_block *last = list_last_entry(&ctx->blocks, agx_block, link);
780*61046927SAndroid Build Coastguard Worker    assert(!last->successors[0] && !last->successors[1]);
781*61046927SAndroid Build Coastguard Worker    return last;
782*61046927SAndroid Build Coastguard Worker }
783*61046927SAndroid Build Coastguard Worker 
784*61046927SAndroid Build Coastguard Worker #define agx_worklist_init(ctx, w)        u_worklist_init(w, ctx->num_blocks, ctx)
785*61046927SAndroid Build Coastguard Worker #define agx_worklist_push_head(w, block) u_worklist_push_head(w, block, index)
786*61046927SAndroid Build Coastguard Worker #define agx_worklist_push_tail(w, block) u_worklist_push_tail(w, block, index)
787*61046927SAndroid Build Coastguard Worker #define agx_worklist_peek_head(w)        u_worklist_peek_head(w, agx_block, index)
788*61046927SAndroid Build Coastguard Worker #define agx_worklist_pop_head(w)         u_worklist_pop_head(w, agx_block, index)
789*61046927SAndroid Build Coastguard Worker #define agx_worklist_peek_tail(w)        u_worklist_peek_tail(w, agx_block, index)
790*61046927SAndroid Build Coastguard Worker #define agx_worklist_pop_tail(w)         u_worklist_pop_tail(w, agx_block, index)
791*61046927SAndroid Build Coastguard Worker 
792*61046927SAndroid Build Coastguard Worker /* Like in NIR, for use with the builder */
793*61046927SAndroid Build Coastguard Worker 
794*61046927SAndroid Build Coastguard Worker enum agx_cursor_option {
795*61046927SAndroid Build Coastguard Worker    agx_cursor_after_block,
796*61046927SAndroid Build Coastguard Worker    agx_cursor_before_instr,
797*61046927SAndroid Build Coastguard Worker    agx_cursor_after_instr
798*61046927SAndroid Build Coastguard Worker };
799*61046927SAndroid Build Coastguard Worker 
800*61046927SAndroid Build Coastguard Worker typedef struct {
801*61046927SAndroid Build Coastguard Worker    enum agx_cursor_option option;
802*61046927SAndroid Build Coastguard Worker 
803*61046927SAndroid Build Coastguard Worker    union {
804*61046927SAndroid Build Coastguard Worker       agx_block *block;
805*61046927SAndroid Build Coastguard Worker       agx_instr *instr;
806*61046927SAndroid Build Coastguard Worker    };
807*61046927SAndroid Build Coastguard Worker } agx_cursor;
808*61046927SAndroid Build Coastguard Worker 
809*61046927SAndroid Build Coastguard Worker static inline bool
agx_cursors_equal(agx_cursor a,agx_cursor b)810*61046927SAndroid Build Coastguard Worker agx_cursors_equal(agx_cursor a, agx_cursor b)
811*61046927SAndroid Build Coastguard Worker {
812*61046927SAndroid Build Coastguard Worker    if (a.option != b.option)
813*61046927SAndroid Build Coastguard Worker       return false;
814*61046927SAndroid Build Coastguard Worker 
815*61046927SAndroid Build Coastguard Worker    if (a.option == agx_cursor_after_block)
816*61046927SAndroid Build Coastguard Worker       return a.block == b.block;
817*61046927SAndroid Build Coastguard Worker    else
818*61046927SAndroid Build Coastguard Worker       return a.instr == b.instr;
819*61046927SAndroid Build Coastguard Worker }
820*61046927SAndroid Build Coastguard Worker 
821*61046927SAndroid Build Coastguard Worker static inline agx_cursor
agx_after_block(agx_block * block)822*61046927SAndroid Build Coastguard Worker agx_after_block(agx_block *block)
823*61046927SAndroid Build Coastguard Worker {
824*61046927SAndroid Build Coastguard Worker    return (agx_cursor){
825*61046927SAndroid Build Coastguard Worker       .option = agx_cursor_after_block,
826*61046927SAndroid Build Coastguard Worker       .block = block,
827*61046927SAndroid Build Coastguard Worker    };
828*61046927SAndroid Build Coastguard Worker }
829*61046927SAndroid Build Coastguard Worker 
830*61046927SAndroid Build Coastguard Worker static inline agx_cursor
agx_before_instr(agx_instr * instr)831*61046927SAndroid Build Coastguard Worker agx_before_instr(agx_instr *instr)
832*61046927SAndroid Build Coastguard Worker {
833*61046927SAndroid Build Coastguard Worker    return (agx_cursor){
834*61046927SAndroid Build Coastguard Worker       .option = agx_cursor_before_instr,
835*61046927SAndroid Build Coastguard Worker       .instr = instr,
836*61046927SAndroid Build Coastguard Worker    };
837*61046927SAndroid Build Coastguard Worker }
838*61046927SAndroid Build Coastguard Worker 
839*61046927SAndroid Build Coastguard Worker static inline agx_cursor
agx_after_instr(agx_instr * instr)840*61046927SAndroid Build Coastguard Worker agx_after_instr(agx_instr *instr)
841*61046927SAndroid Build Coastguard Worker {
842*61046927SAndroid Build Coastguard Worker    return (agx_cursor){
843*61046927SAndroid Build Coastguard Worker       .option = agx_cursor_after_instr,
844*61046927SAndroid Build Coastguard Worker       .instr = instr,
845*61046927SAndroid Build Coastguard Worker    };
846*61046927SAndroid Build Coastguard Worker }
847*61046927SAndroid Build Coastguard Worker 
848*61046927SAndroid Build Coastguard Worker static inline agx_cursor
agx_before_nonempty_block(agx_block * block)849*61046927SAndroid Build Coastguard Worker agx_before_nonempty_block(agx_block *block)
850*61046927SAndroid Build Coastguard Worker {
851*61046927SAndroid Build Coastguard Worker    agx_instr *I = list_first_entry(&block->instructions, agx_instr, link);
852*61046927SAndroid Build Coastguard Worker    assert(I != NULL);
853*61046927SAndroid Build Coastguard Worker 
854*61046927SAndroid Build Coastguard Worker    return agx_before_instr(I);
855*61046927SAndroid Build Coastguard Worker }
856*61046927SAndroid Build Coastguard Worker 
857*61046927SAndroid Build Coastguard Worker static inline agx_cursor
agx_before_block(agx_block * block)858*61046927SAndroid Build Coastguard Worker agx_before_block(agx_block *block)
859*61046927SAndroid Build Coastguard Worker {
860*61046927SAndroid Build Coastguard Worker    if (list_is_empty(&block->instructions))
861*61046927SAndroid Build Coastguard Worker       return agx_after_block(block);
862*61046927SAndroid Build Coastguard Worker    else
863*61046927SAndroid Build Coastguard Worker       return agx_before_nonempty_block(block);
864*61046927SAndroid Build Coastguard Worker }
865*61046927SAndroid Build Coastguard Worker 
866*61046927SAndroid Build Coastguard Worker static inline bool
instr_after_logical_end(const agx_instr * I)867*61046927SAndroid Build Coastguard Worker instr_after_logical_end(const agx_instr *I)
868*61046927SAndroid Build Coastguard Worker {
869*61046927SAndroid Build Coastguard Worker    switch (I->op) {
870*61046927SAndroid Build Coastguard Worker    case AGX_OPCODE_JMP_EXEC_ANY:
871*61046927SAndroid Build Coastguard Worker    case AGX_OPCODE_JMP_EXEC_NONE:
872*61046927SAndroid Build Coastguard Worker    case AGX_OPCODE_POP_EXEC:
873*61046927SAndroid Build Coastguard Worker    case AGX_OPCODE_BREAK:
874*61046927SAndroid Build Coastguard Worker    case AGX_OPCODE_IF_ICMP:
875*61046927SAndroid Build Coastguard Worker    case AGX_OPCODE_WHILE_ICMP:
876*61046927SAndroid Build Coastguard Worker    case AGX_OPCODE_IF_FCMP:
877*61046927SAndroid Build Coastguard Worker    case AGX_OPCODE_WHILE_FCMP:
878*61046927SAndroid Build Coastguard Worker    case AGX_OPCODE_STOP:
879*61046927SAndroid Build Coastguard Worker    case AGX_OPCODE_EXPORT:
880*61046927SAndroid Build Coastguard Worker       return true;
881*61046927SAndroid Build Coastguard Worker    default:
882*61046927SAndroid Build Coastguard Worker       return false;
883*61046927SAndroid Build Coastguard Worker    }
884*61046927SAndroid Build Coastguard Worker }
885*61046927SAndroid Build Coastguard Worker 
886*61046927SAndroid Build Coastguard Worker /*
887*61046927SAndroid Build Coastguard Worker  * Get a cursor inserting at the logical end of the block. In particular, this
888*61046927SAndroid Build Coastguard Worker  * is before branches or control flow instructions, which occur after the
889*61046927SAndroid Build Coastguard Worker  * logical end but before the physical end.
890*61046927SAndroid Build Coastguard Worker  */
891*61046927SAndroid Build Coastguard Worker static inline agx_cursor
agx_after_block_logical(agx_block * block)892*61046927SAndroid Build Coastguard Worker agx_after_block_logical(agx_block *block)
893*61046927SAndroid Build Coastguard Worker {
894*61046927SAndroid Build Coastguard Worker    /* Search for the first instruction that's not past the logical end */
895*61046927SAndroid Build Coastguard Worker    agx_foreach_instr_in_block_rev(block, I) {
896*61046927SAndroid Build Coastguard Worker       if (!instr_after_logical_end(I))
897*61046927SAndroid Build Coastguard Worker          return agx_after_instr(I);
898*61046927SAndroid Build Coastguard Worker    }
899*61046927SAndroid Build Coastguard Worker 
900*61046927SAndroid Build Coastguard Worker    /* If we got here, the block is either empty or entirely control flow */
901*61046927SAndroid Build Coastguard Worker    return agx_before_block(block);
902*61046927SAndroid Build Coastguard Worker }
903*61046927SAndroid Build Coastguard Worker 
904*61046927SAndroid Build Coastguard Worker /* Get a cursor at the start of a function, after any preloads */
905*61046927SAndroid Build Coastguard Worker static inline agx_cursor
agx_before_function(agx_context * ctx)906*61046927SAndroid Build Coastguard Worker agx_before_function(agx_context *ctx)
907*61046927SAndroid Build Coastguard Worker {
908*61046927SAndroid Build Coastguard Worker    agx_block *block = agx_start_block(ctx);
909*61046927SAndroid Build Coastguard Worker 
910*61046927SAndroid Build Coastguard Worker    agx_foreach_instr_in_block(block, I) {
911*61046927SAndroid Build Coastguard Worker       if (I->op != AGX_OPCODE_PRELOAD)
912*61046927SAndroid Build Coastguard Worker          return agx_before_instr(I);
913*61046927SAndroid Build Coastguard Worker    }
914*61046927SAndroid Build Coastguard Worker 
915*61046927SAndroid Build Coastguard Worker    /* The whole block is preloads, so insert at the end */
916*61046927SAndroid Build Coastguard Worker    return agx_after_block(block);
917*61046927SAndroid Build Coastguard Worker }
918*61046927SAndroid Build Coastguard Worker 
919*61046927SAndroid Build Coastguard Worker /* IR builder in terms of cursor infrastructure */
920*61046927SAndroid Build Coastguard Worker 
921*61046927SAndroid Build Coastguard Worker typedef struct {
922*61046927SAndroid Build Coastguard Worker    agx_context *shader;
923*61046927SAndroid Build Coastguard Worker    agx_cursor cursor;
924*61046927SAndroid Build Coastguard Worker } agx_builder;
925*61046927SAndroid Build Coastguard Worker 
926*61046927SAndroid Build Coastguard Worker static inline agx_builder
agx_init_builder(agx_context * ctx,agx_cursor cursor)927*61046927SAndroid Build Coastguard Worker agx_init_builder(agx_context *ctx, agx_cursor cursor)
928*61046927SAndroid Build Coastguard Worker {
929*61046927SAndroid Build Coastguard Worker    return (agx_builder){
930*61046927SAndroid Build Coastguard Worker       .shader = ctx,
931*61046927SAndroid Build Coastguard Worker       .cursor = cursor,
932*61046927SAndroid Build Coastguard Worker    };
933*61046927SAndroid Build Coastguard Worker }
934*61046927SAndroid Build Coastguard Worker 
935*61046927SAndroid Build Coastguard Worker /* Insert an instruction at the cursor and move the cursor */
936*61046927SAndroid Build Coastguard Worker 
937*61046927SAndroid Build Coastguard Worker static inline void
agx_builder_insert(agx_cursor * cursor,agx_instr * I)938*61046927SAndroid Build Coastguard Worker agx_builder_insert(agx_cursor *cursor, agx_instr *I)
939*61046927SAndroid Build Coastguard Worker {
940*61046927SAndroid Build Coastguard Worker    switch (cursor->option) {
941*61046927SAndroid Build Coastguard Worker    case agx_cursor_after_instr:
942*61046927SAndroid Build Coastguard Worker       list_add(&I->link, &cursor->instr->link);
943*61046927SAndroid Build Coastguard Worker       cursor->instr = I;
944*61046927SAndroid Build Coastguard Worker       return;
945*61046927SAndroid Build Coastguard Worker 
946*61046927SAndroid Build Coastguard Worker    case agx_cursor_after_block:
947*61046927SAndroid Build Coastguard Worker       list_addtail(&I->link, &cursor->block->instructions);
948*61046927SAndroid Build Coastguard Worker       cursor->option = agx_cursor_after_instr;
949*61046927SAndroid Build Coastguard Worker       cursor->instr = I;
950*61046927SAndroid Build Coastguard Worker       return;
951*61046927SAndroid Build Coastguard Worker 
952*61046927SAndroid Build Coastguard Worker    case agx_cursor_before_instr:
953*61046927SAndroid Build Coastguard Worker       list_addtail(&I->link, &cursor->instr->link);
954*61046927SAndroid Build Coastguard Worker       cursor->option = agx_cursor_after_instr;
955*61046927SAndroid Build Coastguard Worker       cursor->instr = I;
956*61046927SAndroid Build Coastguard Worker       return;
957*61046927SAndroid Build Coastguard Worker    }
958*61046927SAndroid Build Coastguard Worker 
959*61046927SAndroid Build Coastguard Worker    unreachable("Invalid cursor option");
960*61046927SAndroid Build Coastguard Worker }
961*61046927SAndroid Build Coastguard Worker 
962*61046927SAndroid Build Coastguard Worker bool agx_instr_accepts_uniform(enum agx_opcode op, unsigned src_index,
963*61046927SAndroid Build Coastguard Worker                                unsigned value, enum agx_size size);
964*61046927SAndroid Build Coastguard Worker 
965*61046927SAndroid Build Coastguard Worker /* Routines defined for AIR */
966*61046927SAndroid Build Coastguard Worker void agx_print_index(agx_index index, bool is_float, FILE *fp);
967*61046927SAndroid Build Coastguard Worker void agx_print_instr(const agx_instr *I, FILE *fp);
968*61046927SAndroid Build Coastguard Worker void agx_print_block(const agx_block *block, FILE *fp);
969*61046927SAndroid Build Coastguard Worker void agx_print_shader(const agx_context *ctx, FILE *fp);
970*61046927SAndroid Build Coastguard Worker void agx_optimizer(agx_context *ctx);
971*61046927SAndroid Build Coastguard Worker void agx_lower_divergent_shuffle(agx_context *ctx);
972*61046927SAndroid Build Coastguard Worker void agx_lower_pseudo(agx_context *ctx);
973*61046927SAndroid Build Coastguard Worker void agx_lower_spill(agx_context *ctx);
974*61046927SAndroid Build Coastguard Worker void agx_lower_uniform_sources(agx_context *ctx);
975*61046927SAndroid Build Coastguard Worker void agx_opt_cse(agx_context *ctx);
976*61046927SAndroid Build Coastguard Worker void agx_opt_compact_constants(agx_context *ctx);
977*61046927SAndroid Build Coastguard Worker void agx_opt_promote_constants(agx_context *ctx);
978*61046927SAndroid Build Coastguard Worker void agx_dce(agx_context *ctx, bool partial);
979*61046927SAndroid Build Coastguard Worker void agx_pressure_schedule(agx_context *ctx);
980*61046927SAndroid Build Coastguard Worker void agx_spill(agx_context *ctx, unsigned k);
981*61046927SAndroid Build Coastguard Worker void agx_repair_ssa(agx_context *ctx);
982*61046927SAndroid Build Coastguard Worker void agx_reindex_ssa(agx_context *ctx);
983*61046927SAndroid Build Coastguard Worker void agx_ra(agx_context *ctx);
984*61046927SAndroid Build Coastguard Worker void agx_lower_64bit_postra(agx_context *ctx);
985*61046927SAndroid Build Coastguard Worker void agx_insert_waits(agx_context *ctx);
986*61046927SAndroid Build Coastguard Worker void agx_opt_empty_else(agx_context *ctx);
987*61046927SAndroid Build Coastguard Worker void agx_opt_break_if(agx_context *ctx);
988*61046927SAndroid Build Coastguard Worker void agx_opt_jmp_none(agx_context *ctx);
989*61046927SAndroid Build Coastguard Worker void agx_pack_binary(agx_context *ctx, struct util_dynarray *emission);
990*61046927SAndroid Build Coastguard Worker 
991*61046927SAndroid Build Coastguard Worker #ifndef NDEBUG
992*61046927SAndroid Build Coastguard Worker void agx_validate(agx_context *ctx, const char *after_str);
993*61046927SAndroid Build Coastguard Worker #else
994*61046927SAndroid Build Coastguard Worker static inline void
agx_validate(UNUSED agx_context * ctx,UNUSED const char * after_str)995*61046927SAndroid Build Coastguard Worker agx_validate(UNUSED agx_context *ctx, UNUSED const char *after_str)
996*61046927SAndroid Build Coastguard Worker {
997*61046927SAndroid Build Coastguard Worker    return;
998*61046927SAndroid Build Coastguard Worker }
999*61046927SAndroid Build Coastguard Worker #endif
1000*61046927SAndroid Build Coastguard Worker 
1001*61046927SAndroid Build Coastguard Worker enum agx_size agx_split_width(const agx_instr *I);
1002*61046927SAndroid Build Coastguard Worker bool agx_allows_16bit_immediate(agx_instr *I);
1003*61046927SAndroid Build Coastguard Worker 
1004*61046927SAndroid Build Coastguard Worker static inline bool
agx_is_float_src(const agx_instr * I,unsigned s)1005*61046927SAndroid Build Coastguard Worker agx_is_float_src(const agx_instr *I, unsigned s)
1006*61046927SAndroid Build Coastguard Worker {
1007*61046927SAndroid Build Coastguard Worker    struct agx_opcode_info info = agx_opcodes_info[I->op];
1008*61046927SAndroid Build Coastguard Worker    bool fcmp = (I->op == AGX_OPCODE_FCMPSEL || I->op == AGX_OPCODE_FCMP);
1009*61046927SAndroid Build Coastguard Worker 
1010*61046927SAndroid Build Coastguard Worker    /* fcmp takes first 2 as floats but returns an integer */
1011*61046927SAndroid Build Coastguard Worker    return info.is_float || (s < 2 && fcmp);
1012*61046927SAndroid Build Coastguard Worker }
1013*61046927SAndroid Build Coastguard Worker 
1014*61046927SAndroid Build Coastguard Worker struct agx_copy {
1015*61046927SAndroid Build Coastguard Worker    /* Base register destination of the copy */
1016*61046927SAndroid Build Coastguard Worker    unsigned dest;
1017*61046927SAndroid Build Coastguard Worker 
1018*61046927SAndroid Build Coastguard Worker    /* Destination is memory */
1019*61046927SAndroid Build Coastguard Worker    bool dest_mem;
1020*61046927SAndroid Build Coastguard Worker 
1021*61046927SAndroid Build Coastguard Worker    /* Source of the copy */
1022*61046927SAndroid Build Coastguard Worker    agx_index src;
1023*61046927SAndroid Build Coastguard Worker 
1024*61046927SAndroid Build Coastguard Worker    /* Whether the copy has been handled. Callers must leave to false. */
1025*61046927SAndroid Build Coastguard Worker    bool done;
1026*61046927SAndroid Build Coastguard Worker };
1027*61046927SAndroid Build Coastguard Worker 
1028*61046927SAndroid Build Coastguard Worker void agx_emit_parallel_copies(agx_builder *b, struct agx_copy *copies,
1029*61046927SAndroid Build Coastguard Worker                               unsigned n);
1030*61046927SAndroid Build Coastguard Worker 
1031*61046927SAndroid Build Coastguard Worker void agx_compute_liveness(agx_context *ctx);
1032*61046927SAndroid Build Coastguard Worker void agx_liveness_ins_update(BITSET_WORD *live, agx_instr *I);
1033*61046927SAndroid Build Coastguard Worker 
1034*61046927SAndroid Build Coastguard Worker bool agx_nir_opt_preamble(nir_shader *s, unsigned *preamble_size);
1035*61046927SAndroid Build Coastguard Worker bool agx_nir_lower_load_mask(nir_shader *shader);
1036*61046927SAndroid Build Coastguard Worker bool agx_nir_lower_address(nir_shader *shader);
1037*61046927SAndroid Build Coastguard Worker bool agx_nir_lower_ubo(nir_shader *shader);
1038*61046927SAndroid Build Coastguard Worker bool agx_nir_lower_shared_bitsize(nir_shader *shader);
1039*61046927SAndroid Build Coastguard Worker bool agx_nir_lower_frag_sidefx(nir_shader *s);
1040*61046927SAndroid Build Coastguard Worker 
1041*61046927SAndroid Build Coastguard Worker struct agx_cycle_estimate {
1042*61046927SAndroid Build Coastguard Worker    /* ALU throughput */
1043*61046927SAndroid Build Coastguard Worker    unsigned alu;
1044*61046927SAndroid Build Coastguard Worker 
1045*61046927SAndroid Build Coastguard Worker    /* Floating point and SCIB (select, conditional, integer, and boolean)
1046*61046927SAndroid Build Coastguard Worker     * throughput.
1047*61046927SAndroid Build Coastguard Worker     */
1048*61046927SAndroid Build Coastguard Worker    unsigned f_scib;
1049*61046927SAndroid Build Coastguard Worker 
1050*61046927SAndroid Build Coastguard Worker    /* IC (Integer and complex) throughput */
1051*61046927SAndroid Build Coastguard Worker    unsigned ic;
1052*61046927SAndroid Build Coastguard Worker };
1053*61046927SAndroid Build Coastguard Worker 
1054*61046927SAndroid Build Coastguard Worker struct agx_cycle_estimate agx_estimate_cycles(agx_context *ctx);
1055*61046927SAndroid Build Coastguard Worker 
1056*61046927SAndroid Build Coastguard Worker extern int agx_compiler_debug;
1057*61046927SAndroid Build Coastguard Worker 
1058*61046927SAndroid Build Coastguard Worker #ifdef __cplusplus
1059*61046927SAndroid Build Coastguard Worker } /* extern C */
1060*61046927SAndroid Build Coastguard Worker #endif
1061