xref: /aosp_15_r20/external/mesa3d/src/panfrost/compiler/compiler.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright (C) 2020 Collabora Ltd.
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20*61046927SAndroid Build Coastguard Worker  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21*61046927SAndroid Build Coastguard Worker  * SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  *
23*61046927SAndroid Build Coastguard Worker  * Authors (Collabora):
24*61046927SAndroid Build Coastguard Worker  *      Alyssa Rosenzweig <[email protected]>
25*61046927SAndroid Build Coastguard Worker  */
26*61046927SAndroid Build Coastguard Worker 
27*61046927SAndroid Build Coastguard Worker #ifndef __BIFROST_COMPILER_H
28*61046927SAndroid Build Coastguard Worker #define __BIFROST_COMPILER_H
29*61046927SAndroid Build Coastguard Worker 
30*61046927SAndroid Build Coastguard Worker #include "compiler/nir/nir.h"
31*61046927SAndroid Build Coastguard Worker #include "panfrost/util/pan_ir.h"
32*61046927SAndroid Build Coastguard Worker #include "util/half_float.h"
33*61046927SAndroid Build Coastguard Worker #include "util/u_math.h"
34*61046927SAndroid Build Coastguard Worker #include "util/u_worklist.h"
35*61046927SAndroid Build Coastguard Worker #include "bi_opcodes.h"
36*61046927SAndroid Build Coastguard Worker #include "bifrost.h"
37*61046927SAndroid Build Coastguard Worker 
38*61046927SAndroid Build Coastguard Worker #ifdef __cplusplus
39*61046927SAndroid Build Coastguard Worker extern "C" {
40*61046927SAndroid Build Coastguard Worker #endif
41*61046927SAndroid Build Coastguard Worker 
42*61046927SAndroid Build Coastguard Worker /* Swizzles across bytes in a 32-bit word. Expresses swz in the XML directly.
43*61046927SAndroid Build Coastguard Worker  * To express widen, use the correpsonding replicated form, i.e. H01 = identity
44*61046927SAndroid Build Coastguard Worker  * for widen = none, H00 for widen = h0, B1111 for widen = b1. For lane, also
45*61046927SAndroid Build Coastguard Worker  * use the replicated form (interpretation is governed by the opcode). For
46*61046927SAndroid Build Coastguard Worker  * 8-bit lanes with two channels, use replicated forms for replicated forms
47*61046927SAndroid Build Coastguard Worker  * (TODO: what about others?). For 8-bit lanes with four channels using
48*61046927SAndroid Build Coastguard Worker  * matching form (TODO: what about others?).
49*61046927SAndroid Build Coastguard Worker  */
50*61046927SAndroid Build Coastguard Worker 
51*61046927SAndroid Build Coastguard Worker enum bi_swizzle {
52*61046927SAndroid Build Coastguard Worker    /* 16-bit swizzle ordering deliberate for fast compute */
53*61046927SAndroid Build Coastguard Worker    BI_SWIZZLE_H00 = 0, /* = B0101 */
54*61046927SAndroid Build Coastguard Worker    BI_SWIZZLE_H01 = 1, /* = B0123 = W0 */
55*61046927SAndroid Build Coastguard Worker    BI_SWIZZLE_H10 = 2, /* = B2301 */
56*61046927SAndroid Build Coastguard Worker    BI_SWIZZLE_H11 = 3, /* = B2323 */
57*61046927SAndroid Build Coastguard Worker 
58*61046927SAndroid Build Coastguard Worker    /* replication order should be maintained for fast compute */
59*61046927SAndroid Build Coastguard Worker    BI_SWIZZLE_B0000 = 4, /* single channel (replicate) */
60*61046927SAndroid Build Coastguard Worker    BI_SWIZZLE_B1111 = 5,
61*61046927SAndroid Build Coastguard Worker    BI_SWIZZLE_B2222 = 6,
62*61046927SAndroid Build Coastguard Worker    BI_SWIZZLE_B3333 = 7,
63*61046927SAndroid Build Coastguard Worker 
64*61046927SAndroid Build Coastguard Worker    /* totally special for explicit pattern matching */
65*61046927SAndroid Build Coastguard Worker    BI_SWIZZLE_B0011 = 8,  /* +SWZ.v4i8 */
66*61046927SAndroid Build Coastguard Worker    BI_SWIZZLE_B2233 = 9,  /* +SWZ.v4i8 */
67*61046927SAndroid Build Coastguard Worker    BI_SWIZZLE_B1032 = 10, /* +SWZ.v4i8 */
68*61046927SAndroid Build Coastguard Worker    BI_SWIZZLE_B3210 = 11, /* +SWZ.v4i8 */
69*61046927SAndroid Build Coastguard Worker 
70*61046927SAndroid Build Coastguard Worker    BI_SWIZZLE_B0022 = 12, /* for b02 lanes */
71*61046927SAndroid Build Coastguard Worker };
72*61046927SAndroid Build Coastguard Worker 
73*61046927SAndroid Build Coastguard Worker /* Given a packed i16vec2/i8vec4 constant, apply a swizzle. Useful for constant
74*61046927SAndroid Build Coastguard Worker  * folding and Valhall constant optimization. */
75*61046927SAndroid Build Coastguard Worker 
76*61046927SAndroid Build Coastguard Worker static inline uint32_t
bi_apply_swizzle(uint32_t value,enum bi_swizzle swz)77*61046927SAndroid Build Coastguard Worker bi_apply_swizzle(uint32_t value, enum bi_swizzle swz)
78*61046927SAndroid Build Coastguard Worker {
79*61046927SAndroid Build Coastguard Worker    const uint16_t *h = (const uint16_t *)&value;
80*61046927SAndroid Build Coastguard Worker    const uint8_t *b = (const uint8_t *)&value;
81*61046927SAndroid Build Coastguard Worker 
82*61046927SAndroid Build Coastguard Worker #define H(h0, h1) (h[h0] | ((uint32_t)h[h1] << 16))
83*61046927SAndroid Build Coastguard Worker #define B(b0, b1, b2, b3)                                                      \
84*61046927SAndroid Build Coastguard Worker    (b[b0] | ((uint32_t)b[b1] << 8) | ((uint32_t)b[b2] << 16) |                 \
85*61046927SAndroid Build Coastguard Worker     ((uint32_t)b[b3] << 24))
86*61046927SAndroid Build Coastguard Worker 
87*61046927SAndroid Build Coastguard Worker    switch (swz) {
88*61046927SAndroid Build Coastguard Worker    case BI_SWIZZLE_H00:
89*61046927SAndroid Build Coastguard Worker       return H(0, 0);
90*61046927SAndroid Build Coastguard Worker    case BI_SWIZZLE_H01:
91*61046927SAndroid Build Coastguard Worker       return H(0, 1);
92*61046927SAndroid Build Coastguard Worker    case BI_SWIZZLE_H10:
93*61046927SAndroid Build Coastguard Worker       return H(1, 0);
94*61046927SAndroid Build Coastguard Worker    case BI_SWIZZLE_H11:
95*61046927SAndroid Build Coastguard Worker       return H(1, 1);
96*61046927SAndroid Build Coastguard Worker    case BI_SWIZZLE_B0000:
97*61046927SAndroid Build Coastguard Worker       return B(0, 0, 0, 0);
98*61046927SAndroid Build Coastguard Worker    case BI_SWIZZLE_B1111:
99*61046927SAndroid Build Coastguard Worker       return B(1, 1, 1, 1);
100*61046927SAndroid Build Coastguard Worker    case BI_SWIZZLE_B2222:
101*61046927SAndroid Build Coastguard Worker       return B(2, 2, 2, 2);
102*61046927SAndroid Build Coastguard Worker    case BI_SWIZZLE_B3333:
103*61046927SAndroid Build Coastguard Worker       return B(3, 3, 3, 3);
104*61046927SAndroid Build Coastguard Worker    case BI_SWIZZLE_B0011:
105*61046927SAndroid Build Coastguard Worker       return B(0, 0, 1, 1);
106*61046927SAndroid Build Coastguard Worker    case BI_SWIZZLE_B2233:
107*61046927SAndroid Build Coastguard Worker       return B(2, 2, 3, 3);
108*61046927SAndroid Build Coastguard Worker    case BI_SWIZZLE_B1032:
109*61046927SAndroid Build Coastguard Worker       return B(1, 0, 3, 2);
110*61046927SAndroid Build Coastguard Worker    case BI_SWIZZLE_B3210:
111*61046927SAndroid Build Coastguard Worker       return B(3, 2, 1, 0);
112*61046927SAndroid Build Coastguard Worker    case BI_SWIZZLE_B0022:
113*61046927SAndroid Build Coastguard Worker       return B(0, 0, 2, 2);
114*61046927SAndroid Build Coastguard Worker    }
115*61046927SAndroid Build Coastguard Worker 
116*61046927SAndroid Build Coastguard Worker #undef H
117*61046927SAndroid Build Coastguard Worker #undef B
118*61046927SAndroid Build Coastguard Worker 
119*61046927SAndroid Build Coastguard Worker    unreachable("Invalid swizzle");
120*61046927SAndroid Build Coastguard Worker }
121*61046927SAndroid Build Coastguard Worker 
122*61046927SAndroid Build Coastguard Worker enum bi_index_type {
123*61046927SAndroid Build Coastguard Worker    BI_INDEX_NULL = 0,
124*61046927SAndroid Build Coastguard Worker    BI_INDEX_NORMAL = 1,
125*61046927SAndroid Build Coastguard Worker    BI_INDEX_REGISTER = 2,
126*61046927SAndroid Build Coastguard Worker    BI_INDEX_CONSTANT = 3,
127*61046927SAndroid Build Coastguard Worker    BI_INDEX_PASS = 4,
128*61046927SAndroid Build Coastguard Worker    BI_INDEX_FAU = 5
129*61046927SAndroid Build Coastguard Worker };
130*61046927SAndroid Build Coastguard Worker 
131*61046927SAndroid Build Coastguard Worker typedef struct {
132*61046927SAndroid Build Coastguard Worker    uint32_t value;
133*61046927SAndroid Build Coastguard Worker 
134*61046927SAndroid Build Coastguard Worker    /* modifiers, should only be set if applicable for a given instruction.
135*61046927SAndroid Build Coastguard Worker     * For *IDP.v4i8, abs plays the role of sign. For bitwise ops where
136*61046927SAndroid Build Coastguard Worker     * applicable, neg plays the role of not */
137*61046927SAndroid Build Coastguard Worker    bool abs : 1;
138*61046927SAndroid Build Coastguard Worker    bool neg : 1;
139*61046927SAndroid Build Coastguard Worker 
140*61046927SAndroid Build Coastguard Worker    /* The last use of a value, should be purged from the register cache.
141*61046927SAndroid Build Coastguard Worker     * Set by liveness analysis. */
142*61046927SAndroid Build Coastguard Worker    bool discard : 1;
143*61046927SAndroid Build Coastguard Worker 
144*61046927SAndroid Build Coastguard Worker    /* For a source, the swizzle. For a destination, acts a bit like a
145*61046927SAndroid Build Coastguard Worker     * write mask. Identity for the full 32-bit, H00 for only caring about
146*61046927SAndroid Build Coastguard Worker     * the lower half, other values unused. */
147*61046927SAndroid Build Coastguard Worker    enum bi_swizzle swizzle : 4;
148*61046927SAndroid Build Coastguard Worker    uint32_t offset         : 3;
149*61046927SAndroid Build Coastguard Worker    enum bi_index_type type : 3;
150*61046927SAndroid Build Coastguard Worker 
151*61046927SAndroid Build Coastguard Worker    /* Must be zeroed so we can hash the whole 64-bits at a time */
152*61046927SAndroid Build Coastguard Worker    unsigned padding : (32 - 13);
153*61046927SAndroid Build Coastguard Worker } bi_index;
154*61046927SAndroid Build Coastguard Worker 
155*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_get_index(unsigned value)156*61046927SAndroid Build Coastguard Worker bi_get_index(unsigned value)
157*61046927SAndroid Build Coastguard Worker {
158*61046927SAndroid Build Coastguard Worker    return (bi_index){
159*61046927SAndroid Build Coastguard Worker       .value = value,
160*61046927SAndroid Build Coastguard Worker       .swizzle = BI_SWIZZLE_H01,
161*61046927SAndroid Build Coastguard Worker       .type = BI_INDEX_NORMAL,
162*61046927SAndroid Build Coastguard Worker    };
163*61046927SAndroid Build Coastguard Worker }
164*61046927SAndroid Build Coastguard Worker 
165*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_register(unsigned reg)166*61046927SAndroid Build Coastguard Worker bi_register(unsigned reg)
167*61046927SAndroid Build Coastguard Worker {
168*61046927SAndroid Build Coastguard Worker    assert(reg < 64);
169*61046927SAndroid Build Coastguard Worker 
170*61046927SAndroid Build Coastguard Worker    return (bi_index){
171*61046927SAndroid Build Coastguard Worker       .value = reg,
172*61046927SAndroid Build Coastguard Worker       .swizzle = BI_SWIZZLE_H01,
173*61046927SAndroid Build Coastguard Worker       .type = BI_INDEX_REGISTER,
174*61046927SAndroid Build Coastguard Worker    };
175*61046927SAndroid Build Coastguard Worker }
176*61046927SAndroid Build Coastguard Worker 
177*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_imm_u32(uint32_t imm)178*61046927SAndroid Build Coastguard Worker bi_imm_u32(uint32_t imm)
179*61046927SAndroid Build Coastguard Worker {
180*61046927SAndroid Build Coastguard Worker    return (bi_index){
181*61046927SAndroid Build Coastguard Worker       .value = imm,
182*61046927SAndroid Build Coastguard Worker       .swizzle = BI_SWIZZLE_H01,
183*61046927SAndroid Build Coastguard Worker       .type = BI_INDEX_CONSTANT,
184*61046927SAndroid Build Coastguard Worker    };
185*61046927SAndroid Build Coastguard Worker }
186*61046927SAndroid Build Coastguard Worker 
187*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_imm_f32(float imm)188*61046927SAndroid Build Coastguard Worker bi_imm_f32(float imm)
189*61046927SAndroid Build Coastguard Worker {
190*61046927SAndroid Build Coastguard Worker    return bi_imm_u32(fui(imm));
191*61046927SAndroid Build Coastguard Worker }
192*61046927SAndroid Build Coastguard Worker 
193*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_null()194*61046927SAndroid Build Coastguard Worker bi_null()
195*61046927SAndroid Build Coastguard Worker {
196*61046927SAndroid Build Coastguard Worker    return (bi_index){.type = BI_INDEX_NULL};
197*61046927SAndroid Build Coastguard Worker }
198*61046927SAndroid Build Coastguard Worker 
199*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_zero()200*61046927SAndroid Build Coastguard Worker bi_zero()
201*61046927SAndroid Build Coastguard Worker {
202*61046927SAndroid Build Coastguard Worker    return bi_imm_u32(0);
203*61046927SAndroid Build Coastguard Worker }
204*61046927SAndroid Build Coastguard Worker 
205*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_passthrough(enum bifrost_packed_src value)206*61046927SAndroid Build Coastguard Worker bi_passthrough(enum bifrost_packed_src value)
207*61046927SAndroid Build Coastguard Worker {
208*61046927SAndroid Build Coastguard Worker    return (bi_index){
209*61046927SAndroid Build Coastguard Worker       .value = value,
210*61046927SAndroid Build Coastguard Worker       .swizzle = BI_SWIZZLE_H01,
211*61046927SAndroid Build Coastguard Worker       .type = BI_INDEX_PASS,
212*61046927SAndroid Build Coastguard Worker    };
213*61046927SAndroid Build Coastguard Worker }
214*61046927SAndroid Build Coastguard Worker 
215*61046927SAndroid Build Coastguard Worker /* Helps construct swizzles */
216*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_swz_16(bi_index idx,bool x,bool y)217*61046927SAndroid Build Coastguard Worker bi_swz_16(bi_index idx, bool x, bool y)
218*61046927SAndroid Build Coastguard Worker {
219*61046927SAndroid Build Coastguard Worker    assert(idx.swizzle == BI_SWIZZLE_H01);
220*61046927SAndroid Build Coastguard Worker    idx.swizzle = (enum bi_swizzle)(BI_SWIZZLE_H00 | (x << 1) | y);
221*61046927SAndroid Build Coastguard Worker    return idx;
222*61046927SAndroid Build Coastguard Worker }
223*61046927SAndroid Build Coastguard Worker 
224*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_half(bi_index idx,bool upper)225*61046927SAndroid Build Coastguard Worker bi_half(bi_index idx, bool upper)
226*61046927SAndroid Build Coastguard Worker {
227*61046927SAndroid Build Coastguard Worker    return bi_swz_16(idx, upper, upper);
228*61046927SAndroid Build Coastguard Worker }
229*61046927SAndroid Build Coastguard Worker 
230*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_byte(bi_index idx,unsigned lane)231*61046927SAndroid Build Coastguard Worker bi_byte(bi_index idx, unsigned lane)
232*61046927SAndroid Build Coastguard Worker {
233*61046927SAndroid Build Coastguard Worker    assert(idx.swizzle == BI_SWIZZLE_H01);
234*61046927SAndroid Build Coastguard Worker    assert(lane < 4);
235*61046927SAndroid Build Coastguard Worker    idx.swizzle = (enum bi_swizzle)(BI_SWIZZLE_B0000 + lane);
236*61046927SAndroid Build Coastguard Worker    return idx;
237*61046927SAndroid Build Coastguard Worker }
238*61046927SAndroid Build Coastguard Worker 
239*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_abs(bi_index idx)240*61046927SAndroid Build Coastguard Worker bi_abs(bi_index idx)
241*61046927SAndroid Build Coastguard Worker {
242*61046927SAndroid Build Coastguard Worker    idx.abs = true;
243*61046927SAndroid Build Coastguard Worker    return idx;
244*61046927SAndroid Build Coastguard Worker }
245*61046927SAndroid Build Coastguard Worker 
246*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_neg(bi_index idx)247*61046927SAndroid Build Coastguard Worker bi_neg(bi_index idx)
248*61046927SAndroid Build Coastguard Worker {
249*61046927SAndroid Build Coastguard Worker    idx.neg ^= true;
250*61046927SAndroid Build Coastguard Worker    return idx;
251*61046927SAndroid Build Coastguard Worker }
252*61046927SAndroid Build Coastguard Worker 
253*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_discard(bi_index idx)254*61046927SAndroid Build Coastguard Worker bi_discard(bi_index idx)
255*61046927SAndroid Build Coastguard Worker {
256*61046927SAndroid Build Coastguard Worker    idx.discard = true;
257*61046927SAndroid Build Coastguard Worker    return idx;
258*61046927SAndroid Build Coastguard Worker }
259*61046927SAndroid Build Coastguard Worker 
260*61046927SAndroid Build Coastguard Worker /* Additive identity in IEEE 754 arithmetic */
261*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_negzero()262*61046927SAndroid Build Coastguard Worker bi_negzero()
263*61046927SAndroid Build Coastguard Worker {
264*61046927SAndroid Build Coastguard Worker    return bi_neg(bi_zero());
265*61046927SAndroid Build Coastguard Worker }
266*61046927SAndroid Build Coastguard Worker 
267*61046927SAndroid Build Coastguard Worker /* Replaces an index, preserving any modifiers */
268*61046927SAndroid Build Coastguard Worker 
269*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_replace_index(bi_index old,bi_index replacement)270*61046927SAndroid Build Coastguard Worker bi_replace_index(bi_index old, bi_index replacement)
271*61046927SAndroid Build Coastguard Worker {
272*61046927SAndroid Build Coastguard Worker    replacement.abs = old.abs;
273*61046927SAndroid Build Coastguard Worker    replacement.neg = old.neg;
274*61046927SAndroid Build Coastguard Worker    replacement.swizzle = old.swizzle;
275*61046927SAndroid Build Coastguard Worker    replacement.discard = false; /* needs liveness analysis to set */
276*61046927SAndroid Build Coastguard Worker    return replacement;
277*61046927SAndroid Build Coastguard Worker }
278*61046927SAndroid Build Coastguard Worker 
279*61046927SAndroid Build Coastguard Worker /* Remove any modifiers. This has the property:
280*61046927SAndroid Build Coastguard Worker  *
281*61046927SAndroid Build Coastguard Worker  *     replace_index(x, strip_index(x)) = x
282*61046927SAndroid Build Coastguard Worker  *
283*61046927SAndroid Build Coastguard Worker  * This ensures it is suitable to use when lowering sources to moves */
284*61046927SAndroid Build Coastguard Worker 
285*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_strip_index(bi_index index)286*61046927SAndroid Build Coastguard Worker bi_strip_index(bi_index index)
287*61046927SAndroid Build Coastguard Worker {
288*61046927SAndroid Build Coastguard Worker    index.abs = index.neg = false;
289*61046927SAndroid Build Coastguard Worker    index.swizzle = BI_SWIZZLE_H01;
290*61046927SAndroid Build Coastguard Worker    return index;
291*61046927SAndroid Build Coastguard Worker }
292*61046927SAndroid Build Coastguard Worker 
293*61046927SAndroid Build Coastguard Worker /* For bitwise instructions */
294*61046927SAndroid Build Coastguard Worker #define bi_not(x) bi_neg(x)
295*61046927SAndroid Build Coastguard Worker 
296*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_imm_u8(uint8_t imm)297*61046927SAndroid Build Coastguard Worker bi_imm_u8(uint8_t imm)
298*61046927SAndroid Build Coastguard Worker {
299*61046927SAndroid Build Coastguard Worker    return bi_byte(bi_imm_u32(imm), 0);
300*61046927SAndroid Build Coastguard Worker }
301*61046927SAndroid Build Coastguard Worker 
302*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_imm_u16(uint16_t imm)303*61046927SAndroid Build Coastguard Worker bi_imm_u16(uint16_t imm)
304*61046927SAndroid Build Coastguard Worker {
305*61046927SAndroid Build Coastguard Worker    return bi_half(bi_imm_u32(imm), false);
306*61046927SAndroid Build Coastguard Worker }
307*61046927SAndroid Build Coastguard Worker 
308*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_imm_uintN(uint32_t imm,unsigned sz)309*61046927SAndroid Build Coastguard Worker bi_imm_uintN(uint32_t imm, unsigned sz)
310*61046927SAndroid Build Coastguard Worker {
311*61046927SAndroid Build Coastguard Worker    assert(sz == 8 || sz == 16 || sz == 32);
312*61046927SAndroid Build Coastguard Worker    return (sz == 8)    ? bi_imm_u8(imm)
313*61046927SAndroid Build Coastguard Worker           : (sz == 16) ? bi_imm_u16(imm)
314*61046927SAndroid Build Coastguard Worker                        : bi_imm_u32(imm);
315*61046927SAndroid Build Coastguard Worker }
316*61046927SAndroid Build Coastguard Worker 
317*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_imm_f16(float imm)318*61046927SAndroid Build Coastguard Worker bi_imm_f16(float imm)
319*61046927SAndroid Build Coastguard Worker {
320*61046927SAndroid Build Coastguard Worker    return bi_imm_u16(_mesa_float_to_half(imm));
321*61046927SAndroid Build Coastguard Worker }
322*61046927SAndroid Build Coastguard Worker 
323*61046927SAndroid Build Coastguard Worker static inline bool
bi_is_null(bi_index idx)324*61046927SAndroid Build Coastguard Worker bi_is_null(bi_index idx)
325*61046927SAndroid Build Coastguard Worker {
326*61046927SAndroid Build Coastguard Worker    return idx.type == BI_INDEX_NULL;
327*61046927SAndroid Build Coastguard Worker }
328*61046927SAndroid Build Coastguard Worker 
329*61046927SAndroid Build Coastguard Worker static inline bool
bi_is_ssa(bi_index idx)330*61046927SAndroid Build Coastguard Worker bi_is_ssa(bi_index idx)
331*61046927SAndroid Build Coastguard Worker {
332*61046927SAndroid Build Coastguard Worker    return idx.type == BI_INDEX_NORMAL;
333*61046927SAndroid Build Coastguard Worker }
334*61046927SAndroid Build Coastguard Worker 
335*61046927SAndroid Build Coastguard Worker /* Compares equivalence as references. Does not compare offsets, swizzles, or
336*61046927SAndroid Build Coastguard Worker  * modifiers. In other words, this forms bi_index equivalence classes by
337*61046927SAndroid Build Coastguard Worker  * partitioning memory. E.g. -abs(foo[1].yx) == foo.xy but foo != bar */
338*61046927SAndroid Build Coastguard Worker 
339*61046927SAndroid Build Coastguard Worker static inline bool
bi_is_equiv(bi_index left,bi_index right)340*61046927SAndroid Build Coastguard Worker bi_is_equiv(bi_index left, bi_index right)
341*61046927SAndroid Build Coastguard Worker {
342*61046927SAndroid Build Coastguard Worker    return (left.type == right.type) && (left.value == right.value);
343*61046927SAndroid Build Coastguard Worker }
344*61046927SAndroid Build Coastguard Worker 
345*61046927SAndroid Build Coastguard Worker /* A stronger equivalence relation that requires the indices access the
346*61046927SAndroid Build Coastguard Worker  * same offset, useful for RA/scheduling to see what registers will
347*61046927SAndroid Build Coastguard Worker  * correspond to */
348*61046927SAndroid Build Coastguard Worker 
349*61046927SAndroid Build Coastguard Worker static inline bool
bi_is_word_equiv(bi_index left,bi_index right)350*61046927SAndroid Build Coastguard Worker bi_is_word_equiv(bi_index left, bi_index right)
351*61046927SAndroid Build Coastguard Worker {
352*61046927SAndroid Build Coastguard Worker    return bi_is_equiv(left, right) && left.offset == right.offset;
353*61046927SAndroid Build Coastguard Worker }
354*61046927SAndroid Build Coastguard Worker 
355*61046927SAndroid Build Coastguard Worker /* An even stronger equivalence that checks if indices correspond to the
356*61046927SAndroid Build Coastguard Worker  * right value when evaluated
357*61046927SAndroid Build Coastguard Worker  */
358*61046927SAndroid Build Coastguard Worker static inline bool
bi_is_value_equiv(bi_index left,bi_index right)359*61046927SAndroid Build Coastguard Worker bi_is_value_equiv(bi_index left, bi_index right)
360*61046927SAndroid Build Coastguard Worker {
361*61046927SAndroid Build Coastguard Worker    if (left.type == BI_INDEX_CONSTANT && right.type == BI_INDEX_CONSTANT) {
362*61046927SAndroid Build Coastguard Worker       return (bi_apply_swizzle(left.value, left.swizzle) ==
363*61046927SAndroid Build Coastguard Worker               bi_apply_swizzle(right.value, right.swizzle)) &&
364*61046927SAndroid Build Coastguard Worker              (left.abs == right.abs) && (left.neg == right.neg);
365*61046927SAndroid Build Coastguard Worker    } else {
366*61046927SAndroid Build Coastguard Worker       return (left.value == right.value) && (left.abs == right.abs) &&
367*61046927SAndroid Build Coastguard Worker              (left.neg == right.neg) && (left.swizzle == right.swizzle) &&
368*61046927SAndroid Build Coastguard Worker              (left.offset == right.offset) && (left.type == right.type);
369*61046927SAndroid Build Coastguard Worker    }
370*61046927SAndroid Build Coastguard Worker }
371*61046927SAndroid Build Coastguard Worker 
372*61046927SAndroid Build Coastguard Worker #define BI_MAX_VEC   8
373*61046927SAndroid Build Coastguard Worker #define BI_MAX_DESTS 4
374*61046927SAndroid Build Coastguard Worker #define BI_MAX_SRCS  6
375*61046927SAndroid Build Coastguard Worker 
376*61046927SAndroid Build Coastguard Worker typedef struct {
377*61046927SAndroid Build Coastguard Worker    /* Must be first */
378*61046927SAndroid Build Coastguard Worker    struct list_head link;
379*61046927SAndroid Build Coastguard Worker    bi_index *dest;
380*61046927SAndroid Build Coastguard Worker    bi_index *src;
381*61046927SAndroid Build Coastguard Worker 
382*61046927SAndroid Build Coastguard Worker    enum bi_opcode op;
383*61046927SAndroid Build Coastguard Worker    uint8_t nr_srcs;
384*61046927SAndroid Build Coastguard Worker    uint8_t nr_dests;
385*61046927SAndroid Build Coastguard Worker 
386*61046927SAndroid Build Coastguard Worker    union {
387*61046927SAndroid Build Coastguard Worker       /* For a branch */
388*61046927SAndroid Build Coastguard Worker       struct bi_block *branch_target;
389*61046927SAndroid Build Coastguard Worker 
390*61046927SAndroid Build Coastguard Worker       /* For a phi node that hasn't been translated yet. This is only
391*61046927SAndroid Build Coastguard Worker        * used during NIR->BIR
392*61046927SAndroid Build Coastguard Worker        */
393*61046927SAndroid Build Coastguard Worker       nir_phi_instr *phi;
394*61046927SAndroid Build Coastguard Worker    };
395*61046927SAndroid Build Coastguard Worker 
396*61046927SAndroid Build Coastguard Worker    /* These don't fit neatly with anything else.. */
397*61046927SAndroid Build Coastguard Worker    enum bi_register_format register_format;
398*61046927SAndroid Build Coastguard Worker    enum bi_vecsize vecsize;
399*61046927SAndroid Build Coastguard Worker 
400*61046927SAndroid Build Coastguard Worker    /* Flow control associated with a Valhall instruction */
401*61046927SAndroid Build Coastguard Worker    uint8_t flow;
402*61046927SAndroid Build Coastguard Worker 
403*61046927SAndroid Build Coastguard Worker    /* Slot associated with a message-passing instruction */
404*61046927SAndroid Build Coastguard Worker    uint8_t slot;
405*61046927SAndroid Build Coastguard Worker 
406*61046927SAndroid Build Coastguard Worker    /* Can we spill the value written here? Used to prevent
407*61046927SAndroid Build Coastguard Worker     * useless double fills */
408*61046927SAndroid Build Coastguard Worker    bool no_spill;
409*61046927SAndroid Build Coastguard Worker 
410*61046927SAndroid Build Coastguard Worker    /* On Bifrost: A value of bi_table to override the table, inducing a
411*61046927SAndroid Build Coastguard Worker     * DTSEL_IMM pair if nonzero.
412*61046927SAndroid Build Coastguard Worker     *
413*61046927SAndroid Build Coastguard Worker     * On Valhall: the table index to use for resource instructions.
414*61046927SAndroid Build Coastguard Worker     *
415*61046927SAndroid Build Coastguard Worker     * These two interpretations are equivalent if you squint a bit.
416*61046927SAndroid Build Coastguard Worker     */
417*61046927SAndroid Build Coastguard Worker    unsigned table;
418*61046927SAndroid Build Coastguard Worker 
419*61046927SAndroid Build Coastguard Worker    /* Everything after this MUST NOT be accessed directly, since
420*61046927SAndroid Build Coastguard Worker     * interpretation depends on opcodes */
421*61046927SAndroid Build Coastguard Worker 
422*61046927SAndroid Build Coastguard Worker    /* Destination modifiers */
423*61046927SAndroid Build Coastguard Worker    union {
424*61046927SAndroid Build Coastguard Worker       enum bi_clamp clamp;
425*61046927SAndroid Build Coastguard Worker       bool saturate;
426*61046927SAndroid Build Coastguard Worker       bool not_result;
427*61046927SAndroid Build Coastguard Worker       unsigned dest_mod;
428*61046927SAndroid Build Coastguard Worker    };
429*61046927SAndroid Build Coastguard Worker 
430*61046927SAndroid Build Coastguard Worker    /* Immediates. All seen alone in an instruction, except for varying/texture
431*61046927SAndroid Build Coastguard Worker     * which are specified jointly for VARTEX */
432*61046927SAndroid Build Coastguard Worker    union {
433*61046927SAndroid Build Coastguard Worker       uint32_t shift;
434*61046927SAndroid Build Coastguard Worker       uint32_t fill;
435*61046927SAndroid Build Coastguard Worker       uint32_t index;
436*61046927SAndroid Build Coastguard Worker       uint32_t attribute_index;
437*61046927SAndroid Build Coastguard Worker 
438*61046927SAndroid Build Coastguard Worker       struct {
439*61046927SAndroid Build Coastguard Worker          uint32_t varying_index;
440*61046927SAndroid Build Coastguard Worker          uint32_t sampler_index;
441*61046927SAndroid Build Coastguard Worker          uint32_t texture_index;
442*61046927SAndroid Build Coastguard Worker       };
443*61046927SAndroid Build Coastguard Worker 
444*61046927SAndroid Build Coastguard Worker       /* TEXC, ATOM_CX: # of staging registers used */
445*61046927SAndroid Build Coastguard Worker       struct {
446*61046927SAndroid Build Coastguard Worker          uint32_t sr_count;
447*61046927SAndroid Build Coastguard Worker          uint32_t sr_count_2;
448*61046927SAndroid Build Coastguard Worker 
449*61046927SAndroid Build Coastguard Worker          union {
450*61046927SAndroid Build Coastguard Worker             /* Atomics effectively require all three */
451*61046927SAndroid Build Coastguard Worker             int32_t byte_offset;
452*61046927SAndroid Build Coastguard Worker 
453*61046927SAndroid Build Coastguard Worker             /* BLEND requires all three */
454*61046927SAndroid Build Coastguard Worker             int32_t branch_offset;
455*61046927SAndroid Build Coastguard Worker          };
456*61046927SAndroid Build Coastguard Worker       };
457*61046927SAndroid Build Coastguard Worker    };
458*61046927SAndroid Build Coastguard Worker 
459*61046927SAndroid Build Coastguard Worker    /* Modifiers specific to particular instructions are thrown in a union */
460*61046927SAndroid Build Coastguard Worker    union {
461*61046927SAndroid Build Coastguard Worker       enum bi_adj adj;           /* FEXP_TABLE.u4 */
462*61046927SAndroid Build Coastguard Worker       enum bi_atom_opc atom_opc; /* atomics */
463*61046927SAndroid Build Coastguard Worker       enum bi_func func;         /* FPOW_SC_DET */
464*61046927SAndroid Build Coastguard Worker       enum bi_function function; /* LD_VAR_FLAT */
465*61046927SAndroid Build Coastguard Worker       enum bi_mux mux;           /* MUX */
466*61046927SAndroid Build Coastguard Worker       enum bi_sem sem;           /* FMAX, FMIN */
467*61046927SAndroid Build Coastguard Worker       enum bi_source source;     /* LD_GCLK */
468*61046927SAndroid Build Coastguard Worker       bool scale;                /* VN_ASST2, FSINCOS_OFFSET */
469*61046927SAndroid Build Coastguard Worker       bool offset;               /* FSIN_TABLE, FOCS_TABLE */
470*61046927SAndroid Build Coastguard Worker       bool mask;                 /* CLZ */
471*61046927SAndroid Build Coastguard Worker       bool threads;              /* IMULD, IMOV_FMA */
472*61046927SAndroid Build Coastguard Worker       bool combine;              /* BRANCHC */
473*61046927SAndroid Build Coastguard Worker       bool format;               /* LEA_TEX */
474*61046927SAndroid Build Coastguard Worker 
475*61046927SAndroid Build Coastguard Worker       struct {
476*61046927SAndroid Build Coastguard Worker          enum bi_special special; /* FADD_RSCALE, FMA_RSCALE */
477*61046927SAndroid Build Coastguard Worker          enum bi_round round;     /* FMA, converts, FADD, _RSCALE, etc */
478*61046927SAndroid Build Coastguard Worker          bool ftz;                /* Flush-to-zero for F16_TO_F32 */
479*61046927SAndroid Build Coastguard Worker       };
480*61046927SAndroid Build Coastguard Worker 
481*61046927SAndroid Build Coastguard Worker       struct {
482*61046927SAndroid Build Coastguard Worker          enum bi_result_type result_type; /* FCMP, ICMP */
483*61046927SAndroid Build Coastguard Worker          enum bi_cmpf cmpf;               /* CSEL, FCMP, ICMP, BRANCH */
484*61046927SAndroid Build Coastguard Worker       };
485*61046927SAndroid Build Coastguard Worker 
486*61046927SAndroid Build Coastguard Worker       struct {
487*61046927SAndroid Build Coastguard Worker          enum bi_stack_mode stack_mode; /* JUMP_EX */
488*61046927SAndroid Build Coastguard Worker          bool test_mode;
489*61046927SAndroid Build Coastguard Worker       };
490*61046927SAndroid Build Coastguard Worker 
491*61046927SAndroid Build Coastguard Worker       struct {
492*61046927SAndroid Build Coastguard Worker          enum bi_seg seg;       /* LOAD, STORE, SEG_ADD, SEG_SUB */
493*61046927SAndroid Build Coastguard Worker          bool preserve_null;    /* SEG_ADD, SEG_SUB */
494*61046927SAndroid Build Coastguard Worker          enum bi_extend extend; /* LOAD, IMUL */
495*61046927SAndroid Build Coastguard Worker       };
496*61046927SAndroid Build Coastguard Worker 
497*61046927SAndroid Build Coastguard Worker       struct {
498*61046927SAndroid Build Coastguard Worker          enum bi_sample sample;             /* VAR_TEX, LD_VAR */
499*61046927SAndroid Build Coastguard Worker          enum bi_update update;             /* VAR_TEX, LD_VAR */
500*61046927SAndroid Build Coastguard Worker          enum bi_varying_name varying_name; /* LD_VAR_SPECIAL */
501*61046927SAndroid Build Coastguard Worker          bool skip;                         /* VAR_TEX, TEXS, TEXC */
502*61046927SAndroid Build Coastguard Worker          bool lod_mode; /* VAR_TEX, TEXS, implicitly for TEXC */
503*61046927SAndroid Build Coastguard Worker          enum bi_source_format source_format; /* LD_VAR_BUF */
504*61046927SAndroid Build Coastguard Worker 
505*61046927SAndroid Build Coastguard Worker          /* Used for valhall texturing */
506*61046927SAndroid Build Coastguard Worker          bool shadow;
507*61046927SAndroid Build Coastguard Worker          bool wide_indices;
508*61046927SAndroid Build Coastguard Worker          bool texel_offset;
509*61046927SAndroid Build Coastguard Worker          bool array_enable;
510*61046927SAndroid Build Coastguard Worker          bool integer_coordinates;
511*61046927SAndroid Build Coastguard Worker          enum bi_fetch_component fetch_component;
512*61046927SAndroid Build Coastguard Worker          enum bi_va_lod_mode va_lod_mode;
513*61046927SAndroid Build Coastguard Worker          enum bi_dimension dimension;
514*61046927SAndroid Build Coastguard Worker          enum bi_write_mask write_mask;
515*61046927SAndroid Build Coastguard Worker       };
516*61046927SAndroid Build Coastguard Worker 
517*61046927SAndroid Build Coastguard Worker       /* Maximum size, for hashing */
518*61046927SAndroid Build Coastguard Worker       unsigned flags[14];
519*61046927SAndroid Build Coastguard Worker 
520*61046927SAndroid Build Coastguard Worker       struct {
521*61046927SAndroid Build Coastguard Worker          enum bi_subgroup subgroup;               /* WMASK, CLPER */
522*61046927SAndroid Build Coastguard Worker          enum bi_inactive_result inactive_result; /* CLPER */
523*61046927SAndroid Build Coastguard Worker          enum bi_lane_op lane_op;                 /* CLPER */
524*61046927SAndroid Build Coastguard Worker       };
525*61046927SAndroid Build Coastguard Worker 
526*61046927SAndroid Build Coastguard Worker       struct {
527*61046927SAndroid Build Coastguard Worker          bool z;       /* ZS_EMIT */
528*61046927SAndroid Build Coastguard Worker          bool stencil; /* ZS_EMIT */
529*61046927SAndroid Build Coastguard Worker       };
530*61046927SAndroid Build Coastguard Worker 
531*61046927SAndroid Build Coastguard Worker       struct {
532*61046927SAndroid Build Coastguard Worker          bool h; /* VN_ASST1.f16 */
533*61046927SAndroid Build Coastguard Worker          bool l; /* VN_ASST1.f16 */
534*61046927SAndroid Build Coastguard Worker       };
535*61046927SAndroid Build Coastguard Worker 
536*61046927SAndroid Build Coastguard Worker       struct {
537*61046927SAndroid Build Coastguard Worker          bool bytes2; /* RROT_DOUBLE, FRSHIFT_DOUBLE */
538*61046927SAndroid Build Coastguard Worker          bool result_word;
539*61046927SAndroid Build Coastguard Worker          bool arithmetic; /* ARSHIFT_OR */
540*61046927SAndroid Build Coastguard Worker       };
541*61046927SAndroid Build Coastguard Worker 
542*61046927SAndroid Build Coastguard Worker       struct {
543*61046927SAndroid Build Coastguard Worker          bool sqrt; /* FREXPM */
544*61046927SAndroid Build Coastguard Worker          bool log;  /* FREXPM */
545*61046927SAndroid Build Coastguard Worker       };
546*61046927SAndroid Build Coastguard Worker 
547*61046927SAndroid Build Coastguard Worker       struct {
548*61046927SAndroid Build Coastguard Worker          enum bi_mode mode;           /* FLOG_TABLE */
549*61046927SAndroid Build Coastguard Worker          enum bi_precision precision; /* FLOG_TABLE */
550*61046927SAndroid Build Coastguard Worker          bool divzero;                /* FRSQ_APPROX, FRSQ */
551*61046927SAndroid Build Coastguard Worker       };
552*61046927SAndroid Build Coastguard Worker    };
553*61046927SAndroid Build Coastguard Worker } bi_instr;
554*61046927SAndroid Build Coastguard Worker 
555*61046927SAndroid Build Coastguard Worker static inline bool
bi_is_staging_src(const bi_instr * I,unsigned s)556*61046927SAndroid Build Coastguard Worker bi_is_staging_src(const bi_instr *I, unsigned s)
557*61046927SAndroid Build Coastguard Worker {
558*61046927SAndroid Build Coastguard Worker    return (s == 0 || s == 4) && bi_opcode_props[I->op].sr_read;
559*61046927SAndroid Build Coastguard Worker }
560*61046927SAndroid Build Coastguard Worker 
561*61046927SAndroid Build Coastguard Worker /*
562*61046927SAndroid Build Coastguard Worker  * Safe helpers to remove destinations/sources at the end of the
563*61046927SAndroid Build Coastguard Worker  * destination/source array when changing opcodes. Unlike adding
564*61046927SAndroid Build Coastguard Worker  * sources/destinations, this does not require reallocation.
565*61046927SAndroid Build Coastguard Worker  */
566*61046927SAndroid Build Coastguard Worker static inline void
bi_drop_dests(bi_instr * I,unsigned new_count)567*61046927SAndroid Build Coastguard Worker bi_drop_dests(bi_instr *I, unsigned new_count)
568*61046927SAndroid Build Coastguard Worker {
569*61046927SAndroid Build Coastguard Worker    assert(new_count < I->nr_dests);
570*61046927SAndroid Build Coastguard Worker 
571*61046927SAndroid Build Coastguard Worker    for (unsigned i = new_count; i < I->nr_dests; ++i)
572*61046927SAndroid Build Coastguard Worker       I->dest[i] = bi_null();
573*61046927SAndroid Build Coastguard Worker 
574*61046927SAndroid Build Coastguard Worker    I->nr_dests = new_count;
575*61046927SAndroid Build Coastguard Worker }
576*61046927SAndroid Build Coastguard Worker 
577*61046927SAndroid Build Coastguard Worker static inline void
bi_drop_srcs(bi_instr * I,unsigned new_count)578*61046927SAndroid Build Coastguard Worker bi_drop_srcs(bi_instr *I, unsigned new_count)
579*61046927SAndroid Build Coastguard Worker {
580*61046927SAndroid Build Coastguard Worker    assert(new_count < I->nr_srcs);
581*61046927SAndroid Build Coastguard Worker 
582*61046927SAndroid Build Coastguard Worker    for (unsigned i = new_count; i < I->nr_srcs; ++i)
583*61046927SAndroid Build Coastguard Worker       I->src[i] = bi_null();
584*61046927SAndroid Build Coastguard Worker 
585*61046927SAndroid Build Coastguard Worker    I->nr_srcs = new_count;
586*61046927SAndroid Build Coastguard Worker }
587*61046927SAndroid Build Coastguard Worker 
588*61046927SAndroid Build Coastguard Worker static inline void
bi_replace_src(bi_instr * I,unsigned src_index,bi_index replacement)589*61046927SAndroid Build Coastguard Worker bi_replace_src(bi_instr *I, unsigned src_index, bi_index replacement)
590*61046927SAndroid Build Coastguard Worker {
591*61046927SAndroid Build Coastguard Worker    I->src[src_index] = bi_replace_index(I->src[src_index], replacement);
592*61046927SAndroid Build Coastguard Worker }
593*61046927SAndroid Build Coastguard Worker 
594*61046927SAndroid Build Coastguard Worker /* Represents the assignment of slots for a given bi_tuple */
595*61046927SAndroid Build Coastguard Worker 
596*61046927SAndroid Build Coastguard Worker typedef struct {
597*61046927SAndroid Build Coastguard Worker    /* Register to assign to each slot */
598*61046927SAndroid Build Coastguard Worker    unsigned slot[4];
599*61046927SAndroid Build Coastguard Worker 
600*61046927SAndroid Build Coastguard Worker    /* Read slots can be disabled */
601*61046927SAndroid Build Coastguard Worker    bool enabled[2];
602*61046927SAndroid Build Coastguard Worker 
603*61046927SAndroid Build Coastguard Worker    /* Configuration for slots 2/3 */
604*61046927SAndroid Build Coastguard Worker    struct bifrost_reg_ctrl_23 slot23;
605*61046927SAndroid Build Coastguard Worker 
606*61046927SAndroid Build Coastguard Worker    /* Fast-Access-Uniform RAM index */
607*61046927SAndroid Build Coastguard Worker    uint8_t fau_idx;
608*61046927SAndroid Build Coastguard Worker 
609*61046927SAndroid Build Coastguard Worker    /* Whether writes are actually for the last instruction */
610*61046927SAndroid Build Coastguard Worker    bool first_instruction;
611*61046927SAndroid Build Coastguard Worker } bi_registers;
612*61046927SAndroid Build Coastguard Worker 
613*61046927SAndroid Build Coastguard Worker /* A bi_tuple contains two paired instruction pointers. If a slot is unfilled,
614*61046927SAndroid Build Coastguard Worker  * leave it NULL; the emitter will fill in a nop. Instructions reference
615*61046927SAndroid Build Coastguard Worker  * registers via slots which are assigned per tuple.
616*61046927SAndroid Build Coastguard Worker  */
617*61046927SAndroid Build Coastguard Worker 
618*61046927SAndroid Build Coastguard Worker typedef struct {
619*61046927SAndroid Build Coastguard Worker    uint8_t fau_idx;
620*61046927SAndroid Build Coastguard Worker    bi_registers regs;
621*61046927SAndroid Build Coastguard Worker    bi_instr *fma;
622*61046927SAndroid Build Coastguard Worker    bi_instr *add;
623*61046927SAndroid Build Coastguard Worker } bi_tuple;
624*61046927SAndroid Build Coastguard Worker 
625*61046927SAndroid Build Coastguard Worker struct bi_block;
626*61046927SAndroid Build Coastguard Worker 
627*61046927SAndroid Build Coastguard Worker typedef struct {
628*61046927SAndroid Build Coastguard Worker    struct list_head link;
629*61046927SAndroid Build Coastguard Worker 
630*61046927SAndroid Build Coastguard Worker    /* Link back up for branch calculations */
631*61046927SAndroid Build Coastguard Worker    struct bi_block *block;
632*61046927SAndroid Build Coastguard Worker 
633*61046927SAndroid Build Coastguard Worker    /* Architectural limit of 8 tuples/clause */
634*61046927SAndroid Build Coastguard Worker    unsigned tuple_count;
635*61046927SAndroid Build Coastguard Worker    bi_tuple tuples[8];
636*61046927SAndroid Build Coastguard Worker 
637*61046927SAndroid Build Coastguard Worker    /* For scoreboarding -- the clause ID (this is not globally unique!)
638*61046927SAndroid Build Coastguard Worker     * and its dependencies in terms of other clauses, computed during
639*61046927SAndroid Build Coastguard Worker     * scheduling and used when emitting code. Dependencies expressed as a
640*61046927SAndroid Build Coastguard Worker     * bitfield matching the hardware, except shifted by a clause (the
641*61046927SAndroid Build Coastguard Worker     * shift back to the ISA's off-by-one encoding is worked out when
642*61046927SAndroid Build Coastguard Worker     * emitting clauses) */
643*61046927SAndroid Build Coastguard Worker    unsigned scoreboard_id;
644*61046927SAndroid Build Coastguard Worker    uint8_t dependencies;
645*61046927SAndroid Build Coastguard Worker 
646*61046927SAndroid Build Coastguard Worker    /* See ISA header for description */
647*61046927SAndroid Build Coastguard Worker    enum bifrost_flow flow_control;
648*61046927SAndroid Build Coastguard Worker 
649*61046927SAndroid Build Coastguard Worker    /* Can we prefetch the next clause? Usually it makes sense, except for
650*61046927SAndroid Build Coastguard Worker     * clauses ending in unconditional branches */
651*61046927SAndroid Build Coastguard Worker    bool next_clause_prefetch;
652*61046927SAndroid Build Coastguard Worker 
653*61046927SAndroid Build Coastguard Worker    /* Assigned data register */
654*61046927SAndroid Build Coastguard Worker    unsigned staging_register;
655*61046927SAndroid Build Coastguard Worker 
656*61046927SAndroid Build Coastguard Worker    /* Corresponds to the usual bit but shifted by a clause */
657*61046927SAndroid Build Coastguard Worker    bool staging_barrier;
658*61046927SAndroid Build Coastguard Worker 
659*61046927SAndroid Build Coastguard Worker    /* Constants read by this clause. ISA limit. Must satisfy:
660*61046927SAndroid Build Coastguard Worker     *
661*61046927SAndroid Build Coastguard Worker     *      constant_count + tuple_count <= 13
662*61046927SAndroid Build Coastguard Worker     *
663*61046927SAndroid Build Coastguard Worker     * Also implicitly constant_count <= tuple_count since a tuple only
664*61046927SAndroid Build Coastguard Worker     * reads a single constant.
665*61046927SAndroid Build Coastguard Worker     */
666*61046927SAndroid Build Coastguard Worker    uint64_t constants[8];
667*61046927SAndroid Build Coastguard Worker    unsigned constant_count;
668*61046927SAndroid Build Coastguard Worker 
669*61046927SAndroid Build Coastguard Worker    /* Index of a constant to be PC-relative */
670*61046927SAndroid Build Coastguard Worker    unsigned pcrel_idx;
671*61046927SAndroid Build Coastguard Worker 
672*61046927SAndroid Build Coastguard Worker    /* Branches encode a constant offset relative to the program counter
673*61046927SAndroid Build Coastguard Worker     * with some magic flags. By convention, if there is a branch, its
674*61046927SAndroid Build Coastguard Worker     * constant will be last. Set this flag to indicate this is required.
675*61046927SAndroid Build Coastguard Worker     */
676*61046927SAndroid Build Coastguard Worker    bool branch_constant;
677*61046927SAndroid Build Coastguard Worker 
678*61046927SAndroid Build Coastguard Worker    /* Unique in a clause */
679*61046927SAndroid Build Coastguard Worker    enum bifrost_message_type message_type;
680*61046927SAndroid Build Coastguard Worker    bi_instr *message;
681*61046927SAndroid Build Coastguard Worker 
682*61046927SAndroid Build Coastguard Worker    /* Discard helper threads */
683*61046927SAndroid Build Coastguard Worker    bool td;
684*61046927SAndroid Build Coastguard Worker 
685*61046927SAndroid Build Coastguard Worker    /* Should flush-to-zero mode be enabled for this clause? */
686*61046927SAndroid Build Coastguard Worker    bool ftz;
687*61046927SAndroid Build Coastguard Worker } bi_clause;
688*61046927SAndroid Build Coastguard Worker 
689*61046927SAndroid Build Coastguard Worker #define BI_NUM_SLOTS 8
690*61046927SAndroid Build Coastguard Worker 
691*61046927SAndroid Build Coastguard Worker /* A model for the state of the scoreboard */
692*61046927SAndroid Build Coastguard Worker struct bi_scoreboard_state {
693*61046927SAndroid Build Coastguard Worker    /** Bitmap of registers read/written by a slot */
694*61046927SAndroid Build Coastguard Worker    uint64_t read[BI_NUM_SLOTS];
695*61046927SAndroid Build Coastguard Worker    uint64_t write[BI_NUM_SLOTS];
696*61046927SAndroid Build Coastguard Worker 
697*61046927SAndroid Build Coastguard Worker    /* Nonregister dependencies present by a slot */
698*61046927SAndroid Build Coastguard Worker    uint8_t varying : BI_NUM_SLOTS;
699*61046927SAndroid Build Coastguard Worker    uint8_t memory : BI_NUM_SLOTS;
700*61046927SAndroid Build Coastguard Worker };
701*61046927SAndroid Build Coastguard Worker 
702*61046927SAndroid Build Coastguard Worker typedef struct bi_block {
703*61046927SAndroid Build Coastguard Worker    /* Link to next block. Must be first for mir_get_block */
704*61046927SAndroid Build Coastguard Worker    struct list_head link;
705*61046927SAndroid Build Coastguard Worker 
706*61046927SAndroid Build Coastguard Worker    /* List of instructions emitted for the current block */
707*61046927SAndroid Build Coastguard Worker    struct list_head instructions;
708*61046927SAndroid Build Coastguard Worker 
709*61046927SAndroid Build Coastguard Worker    /* Index of the block in source order */
710*61046927SAndroid Build Coastguard Worker    unsigned index;
711*61046927SAndroid Build Coastguard Worker 
712*61046927SAndroid Build Coastguard Worker    /* Control flow graph */
713*61046927SAndroid Build Coastguard Worker    struct bi_block *successors[2];
714*61046927SAndroid Build Coastguard Worker    struct util_dynarray predecessors;
715*61046927SAndroid Build Coastguard Worker    bool unconditional_jumps;
716*61046927SAndroid Build Coastguard Worker    bool loop_header;
717*61046927SAndroid Build Coastguard Worker 
718*61046927SAndroid Build Coastguard Worker    /* Per 32-bit word live masks for the block indexed by node */
719*61046927SAndroid Build Coastguard Worker    uint8_t *live_in;
720*61046927SAndroid Build Coastguard Worker    uint8_t *live_out;
721*61046927SAndroid Build Coastguard Worker 
722*61046927SAndroid Build Coastguard Worker    /* Scalar liveness indexed by SSA index */
723*61046927SAndroid Build Coastguard Worker    BITSET_WORD *ssa_live_in;
724*61046927SAndroid Build Coastguard Worker    BITSET_WORD *ssa_live_out;
725*61046927SAndroid Build Coastguard Worker 
726*61046927SAndroid Build Coastguard Worker    /* If true, uses clauses; if false, uses instructions */
727*61046927SAndroid Build Coastguard Worker    bool scheduled;
728*61046927SAndroid Build Coastguard Worker    struct list_head clauses; /* list of bi_clause */
729*61046927SAndroid Build Coastguard Worker 
730*61046927SAndroid Build Coastguard Worker    /* Post-RA liveness */
731*61046927SAndroid Build Coastguard Worker    uint64_t reg_live_in, reg_live_out;
732*61046927SAndroid Build Coastguard Worker 
733*61046927SAndroid Build Coastguard Worker    /* Scoreboard state at the start/end of block */
734*61046927SAndroid Build Coastguard Worker    struct bi_scoreboard_state scoreboard_in, scoreboard_out;
735*61046927SAndroid Build Coastguard Worker 
736*61046927SAndroid Build Coastguard Worker    /* On Valhall, indicates we need a terminal NOP to implement jumps to
737*61046927SAndroid Build Coastguard Worker     * the end of the shader.
738*61046927SAndroid Build Coastguard Worker     */
739*61046927SAndroid Build Coastguard Worker    bool needs_nop;
740*61046927SAndroid Build Coastguard Worker 
741*61046927SAndroid Build Coastguard Worker    /* Flags available for pass-internal use */
742*61046927SAndroid Build Coastguard Worker    uint8_t pass_flags;
743*61046927SAndroid Build Coastguard Worker } bi_block;
744*61046927SAndroid Build Coastguard Worker 
745*61046927SAndroid Build Coastguard Worker static inline unsigned
bi_num_successors(bi_block * block)746*61046927SAndroid Build Coastguard Worker bi_num_successors(bi_block *block)
747*61046927SAndroid Build Coastguard Worker {
748*61046927SAndroid Build Coastguard Worker    STATIC_ASSERT(ARRAY_SIZE(block->successors) == 2);
749*61046927SAndroid Build Coastguard Worker    assert(block->successors[0] || !block->successors[1]);
750*61046927SAndroid Build Coastguard Worker 
751*61046927SAndroid Build Coastguard Worker    if (block->successors[1])
752*61046927SAndroid Build Coastguard Worker       return 2;
753*61046927SAndroid Build Coastguard Worker    else if (block->successors[0])
754*61046927SAndroid Build Coastguard Worker       return 1;
755*61046927SAndroid Build Coastguard Worker    else
756*61046927SAndroid Build Coastguard Worker       return 0;
757*61046927SAndroid Build Coastguard Worker }
758*61046927SAndroid Build Coastguard Worker 
759*61046927SAndroid Build Coastguard Worker static inline unsigned
bi_num_predecessors(bi_block * block)760*61046927SAndroid Build Coastguard Worker bi_num_predecessors(bi_block *block)
761*61046927SAndroid Build Coastguard Worker {
762*61046927SAndroid Build Coastguard Worker    return util_dynarray_num_elements(&block->predecessors, bi_block *);
763*61046927SAndroid Build Coastguard Worker }
764*61046927SAndroid Build Coastguard Worker 
765*61046927SAndroid Build Coastguard Worker static inline bi_block *
bi_start_block(struct list_head * blocks)766*61046927SAndroid Build Coastguard Worker bi_start_block(struct list_head *blocks)
767*61046927SAndroid Build Coastguard Worker {
768*61046927SAndroid Build Coastguard Worker    bi_block *first = list_first_entry(blocks, bi_block, link);
769*61046927SAndroid Build Coastguard Worker    assert(bi_num_predecessors(first) == 0);
770*61046927SAndroid Build Coastguard Worker    return first;
771*61046927SAndroid Build Coastguard Worker }
772*61046927SAndroid Build Coastguard Worker 
773*61046927SAndroid Build Coastguard Worker static inline bi_block *
bi_exit_block(struct list_head * blocks)774*61046927SAndroid Build Coastguard Worker bi_exit_block(struct list_head *blocks)
775*61046927SAndroid Build Coastguard Worker {
776*61046927SAndroid Build Coastguard Worker    bi_block *last = list_last_entry(blocks, bi_block, link);
777*61046927SAndroid Build Coastguard Worker    assert(bi_num_successors(last) == 0);
778*61046927SAndroid Build Coastguard Worker    return last;
779*61046927SAndroid Build Coastguard Worker }
780*61046927SAndroid Build Coastguard Worker 
781*61046927SAndroid Build Coastguard Worker static inline void
bi_block_add_successor(bi_block * block,bi_block * successor)782*61046927SAndroid Build Coastguard Worker bi_block_add_successor(bi_block *block, bi_block *successor)
783*61046927SAndroid Build Coastguard Worker {
784*61046927SAndroid Build Coastguard Worker    assert(block != NULL && successor != NULL);
785*61046927SAndroid Build Coastguard Worker 
786*61046927SAndroid Build Coastguard Worker    /* Cull impossible edges */
787*61046927SAndroid Build Coastguard Worker    if (block->unconditional_jumps)
788*61046927SAndroid Build Coastguard Worker       return;
789*61046927SAndroid Build Coastguard Worker 
790*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < ARRAY_SIZE(block->successors); ++i) {
791*61046927SAndroid Build Coastguard Worker       if (block->successors[i]) {
792*61046927SAndroid Build Coastguard Worker          if (block->successors[i] == successor)
793*61046927SAndroid Build Coastguard Worker             return;
794*61046927SAndroid Build Coastguard Worker          else
795*61046927SAndroid Build Coastguard Worker             continue;
796*61046927SAndroid Build Coastguard Worker       }
797*61046927SAndroid Build Coastguard Worker 
798*61046927SAndroid Build Coastguard Worker       block->successors[i] = successor;
799*61046927SAndroid Build Coastguard Worker       util_dynarray_append(&successor->predecessors, bi_block *, block);
800*61046927SAndroid Build Coastguard Worker       return;
801*61046927SAndroid Build Coastguard Worker    }
802*61046927SAndroid Build Coastguard Worker 
803*61046927SAndroid Build Coastguard Worker    unreachable("Too many successors");
804*61046927SAndroid Build Coastguard Worker }
805*61046927SAndroid Build Coastguard Worker 
806*61046927SAndroid Build Coastguard Worker /* Subset of pan_shader_info needed per-variant, in order to support IDVS */
807*61046927SAndroid Build Coastguard Worker struct bi_shader_info {
808*61046927SAndroid Build Coastguard Worker    struct panfrost_ubo_push *push;
809*61046927SAndroid Build Coastguard Worker    struct bifrost_shader_info *bifrost;
810*61046927SAndroid Build Coastguard Worker    unsigned tls_size;
811*61046927SAndroid Build Coastguard Worker    unsigned work_reg_count;
812*61046927SAndroid Build Coastguard Worker    unsigned push_offset;
813*61046927SAndroid Build Coastguard Worker };
814*61046927SAndroid Build Coastguard Worker 
815*61046927SAndroid Build Coastguard Worker /* State of index-driven vertex shading for current shader */
816*61046927SAndroid Build Coastguard Worker enum bi_idvs_mode {
817*61046927SAndroid Build Coastguard Worker    /* IDVS not in use */
818*61046927SAndroid Build Coastguard Worker    BI_IDVS_NONE = 0,
819*61046927SAndroid Build Coastguard Worker 
820*61046927SAndroid Build Coastguard Worker    /* IDVS in use. Compiling a position shader */
821*61046927SAndroid Build Coastguard Worker    BI_IDVS_POSITION = 1,
822*61046927SAndroid Build Coastguard Worker 
823*61046927SAndroid Build Coastguard Worker    /* IDVS in use. Compiling a varying shader */
824*61046927SAndroid Build Coastguard Worker    BI_IDVS_VARYING = 2,
825*61046927SAndroid Build Coastguard Worker };
826*61046927SAndroid Build Coastguard Worker 
827*61046927SAndroid Build Coastguard Worker typedef struct {
828*61046927SAndroid Build Coastguard Worker    const struct panfrost_compile_inputs *inputs;
829*61046927SAndroid Build Coastguard Worker    nir_shader *nir;
830*61046927SAndroid Build Coastguard Worker    struct bi_shader_info info;
831*61046927SAndroid Build Coastguard Worker    gl_shader_stage stage;
832*61046927SAndroid Build Coastguard Worker    struct list_head blocks; /* list of bi_block */
833*61046927SAndroid Build Coastguard Worker    uint32_t quirks;
834*61046927SAndroid Build Coastguard Worker    unsigned arch;
835*61046927SAndroid Build Coastguard Worker    enum bi_idvs_mode idvs;
836*61046927SAndroid Build Coastguard Worker    unsigned num_blocks;
837*61046927SAndroid Build Coastguard Worker 
838*61046927SAndroid Build Coastguard Worker    /* In any graphics shader, whether the "IDVS with memory
839*61046927SAndroid Build Coastguard Worker     * allocation" flow is used. This affects how varyings are loaded and
840*61046927SAndroid Build Coastguard Worker     * stored. Ignore for compute.
841*61046927SAndroid Build Coastguard Worker     */
842*61046927SAndroid Build Coastguard Worker    bool malloc_idvs;
843*61046927SAndroid Build Coastguard Worker 
844*61046927SAndroid Build Coastguard Worker    /* During NIR->BIR */
845*61046927SAndroid Build Coastguard Worker    bi_block *current_block;
846*61046927SAndroid Build Coastguard Worker    bi_block *after_block;
847*61046927SAndroid Build Coastguard Worker    bi_block *break_block;
848*61046927SAndroid Build Coastguard Worker    bi_block *continue_block;
849*61046927SAndroid Build Coastguard Worker    bi_block **indexed_nir_blocks;
850*61046927SAndroid Build Coastguard Worker    bool emitted_atest;
851*61046927SAndroid Build Coastguard Worker 
852*61046927SAndroid Build Coastguard Worker    /* During NIR->BIR, the coverage bitmap. If this is NULL, the default
853*61046927SAndroid Build Coastguard Worker     * coverage bitmap should be source from preloaded register r60. This is
854*61046927SAndroid Build Coastguard Worker     * written by ATEST and ZS_EMIT
855*61046927SAndroid Build Coastguard Worker     */
856*61046927SAndroid Build Coastguard Worker    bi_index coverage;
857*61046927SAndroid Build Coastguard Worker 
858*61046927SAndroid Build Coastguard Worker    /* During NIR->BIR, table of preloaded registers, or NULL if never
859*61046927SAndroid Build Coastguard Worker     * preloaded.
860*61046927SAndroid Build Coastguard Worker     */
861*61046927SAndroid Build Coastguard Worker    bi_index preloaded[64];
862*61046927SAndroid Build Coastguard Worker 
863*61046927SAndroid Build Coastguard Worker    /* For creating temporaries */
864*61046927SAndroid Build Coastguard Worker    unsigned ssa_alloc;
865*61046927SAndroid Build Coastguard Worker    unsigned reg_alloc;
866*61046927SAndroid Build Coastguard Worker 
867*61046927SAndroid Build Coastguard Worker    /* Mask of UBOs that need to be uploaded */
868*61046927SAndroid Build Coastguard Worker    uint32_t ubo_mask;
869*61046927SAndroid Build Coastguard Worker 
870*61046927SAndroid Build Coastguard Worker    /* During instruction selection, map from vector bi_index to its scalar
871*61046927SAndroid Build Coastguard Worker     * components, populated by a split.
872*61046927SAndroid Build Coastguard Worker     */
873*61046927SAndroid Build Coastguard Worker    struct hash_table_u64 *allocated_vec;
874*61046927SAndroid Build Coastguard Worker 
875*61046927SAndroid Build Coastguard Worker    /* Stats for shader-db */
876*61046927SAndroid Build Coastguard Worker    unsigned loop_count;
877*61046927SAndroid Build Coastguard Worker    unsigned spills;
878*61046927SAndroid Build Coastguard Worker    unsigned fills;
879*61046927SAndroid Build Coastguard Worker } bi_context;
880*61046927SAndroid Build Coastguard Worker 
881*61046927SAndroid Build Coastguard Worker static inline void
bi_remove_instruction(bi_instr * ins)882*61046927SAndroid Build Coastguard Worker bi_remove_instruction(bi_instr *ins)
883*61046927SAndroid Build Coastguard Worker {
884*61046927SAndroid Build Coastguard Worker    list_del(&ins->link);
885*61046927SAndroid Build Coastguard Worker }
886*61046927SAndroid Build Coastguard Worker 
887*61046927SAndroid Build Coastguard Worker enum bir_fau {
888*61046927SAndroid Build Coastguard Worker    BIR_FAU_ZERO = 0,
889*61046927SAndroid Build Coastguard Worker    BIR_FAU_LANE_ID = 1,
890*61046927SAndroid Build Coastguard Worker    BIR_FAU_WARP_ID = 2,
891*61046927SAndroid Build Coastguard Worker    BIR_FAU_CORE_ID = 3,
892*61046927SAndroid Build Coastguard Worker    BIR_FAU_FB_EXTENT = 4,
893*61046927SAndroid Build Coastguard Worker    BIR_FAU_ATEST_PARAM = 5,
894*61046927SAndroid Build Coastguard Worker    BIR_FAU_SAMPLE_POS_ARRAY = 6,
895*61046927SAndroid Build Coastguard Worker    BIR_FAU_BLEND_0 = 8,
896*61046927SAndroid Build Coastguard Worker    /* blend descs 1 - 7 */
897*61046927SAndroid Build Coastguard Worker    BIR_FAU_TYPE_MASK = 15,
898*61046927SAndroid Build Coastguard Worker 
899*61046927SAndroid Build Coastguard Worker    /* Valhall only */
900*61046927SAndroid Build Coastguard Worker    BIR_FAU_TLS_PTR = 16,
901*61046927SAndroid Build Coastguard Worker    BIR_FAU_WLS_PTR = 17,
902*61046927SAndroid Build Coastguard Worker    BIR_FAU_PROGRAM_COUNTER = 18,
903*61046927SAndroid Build Coastguard Worker 
904*61046927SAndroid Build Coastguard Worker    BIR_FAU_UNIFORM = (1 << 7),
905*61046927SAndroid Build Coastguard Worker    /* Look up table on Valhall */
906*61046927SAndroid Build Coastguard Worker    BIR_FAU_IMMEDIATE = (1 << 8),
907*61046927SAndroid Build Coastguard Worker 
908*61046927SAndroid Build Coastguard Worker };
909*61046927SAndroid Build Coastguard Worker 
910*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_fau(enum bir_fau value,bool hi)911*61046927SAndroid Build Coastguard Worker bi_fau(enum bir_fau value, bool hi)
912*61046927SAndroid Build Coastguard Worker {
913*61046927SAndroid Build Coastguard Worker    return (bi_index){
914*61046927SAndroid Build Coastguard Worker       .value = value,
915*61046927SAndroid Build Coastguard Worker       .swizzle = BI_SWIZZLE_H01,
916*61046927SAndroid Build Coastguard Worker       .offset = hi ? 1u : 0u,
917*61046927SAndroid Build Coastguard Worker       .type = BI_INDEX_FAU,
918*61046927SAndroid Build Coastguard Worker    };
919*61046927SAndroid Build Coastguard Worker }
920*61046927SAndroid Build Coastguard Worker 
921*61046927SAndroid Build Coastguard Worker /*
922*61046927SAndroid Build Coastguard Worker  * Builder for Valhall LUT entries. Generally, constants are modeled with
923*61046927SAndroid Build Coastguard Worker  * BI_INDEX_IMMEDIATE in the intermediate representation. This helper is only
924*61046927SAndroid Build Coastguard Worker  * necessary for passes running after lowering constants, as well as when
925*61046927SAndroid Build Coastguard Worker  * lowering constants.
926*61046927SAndroid Build Coastguard Worker  *
927*61046927SAndroid Build Coastguard Worker  */
928*61046927SAndroid Build Coastguard Worker static inline bi_index
va_lut(unsigned index)929*61046927SAndroid Build Coastguard Worker va_lut(unsigned index)
930*61046927SAndroid Build Coastguard Worker {
931*61046927SAndroid Build Coastguard Worker    return bi_fau((enum bir_fau)(BIR_FAU_IMMEDIATE | (index >> 1)), index & 1);
932*61046927SAndroid Build Coastguard Worker }
933*61046927SAndroid Build Coastguard Worker 
934*61046927SAndroid Build Coastguard Worker /*
935*61046927SAndroid Build Coastguard Worker  * va_lut_zero is like bi_zero but only works on Valhall. It is intended for
936*61046927SAndroid Build Coastguard Worker  * use by late passes that run after constants are lowered, specifically
937*61046927SAndroid Build Coastguard Worker  * register allocation. bi_zero() is preferred where possible.
938*61046927SAndroid Build Coastguard Worker  */
939*61046927SAndroid Build Coastguard Worker static inline bi_index
va_zero_lut()940*61046927SAndroid Build Coastguard Worker va_zero_lut()
941*61046927SAndroid Build Coastguard Worker {
942*61046927SAndroid Build Coastguard Worker    return va_lut(0);
943*61046927SAndroid Build Coastguard Worker }
944*61046927SAndroid Build Coastguard Worker 
945*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_temp(bi_context * ctx)946*61046927SAndroid Build Coastguard Worker bi_temp(bi_context *ctx)
947*61046927SAndroid Build Coastguard Worker {
948*61046927SAndroid Build Coastguard Worker    return bi_get_index(ctx->ssa_alloc++);
949*61046927SAndroid Build Coastguard Worker }
950*61046927SAndroid Build Coastguard Worker 
951*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_def_index(nir_def * def)952*61046927SAndroid Build Coastguard Worker bi_def_index(nir_def *def)
953*61046927SAndroid Build Coastguard Worker {
954*61046927SAndroid Build Coastguard Worker    return bi_get_index(def->index);
955*61046927SAndroid Build Coastguard Worker }
956*61046927SAndroid Build Coastguard Worker 
957*61046927SAndroid Build Coastguard Worker /* Inline constants automatically, will be lowered out by bi_lower_fau where a
958*61046927SAndroid Build Coastguard Worker  * constant is not allowed. load_const_to_scalar gaurantees that this makes
959*61046927SAndroid Build Coastguard Worker  * sense */
960*61046927SAndroid Build Coastguard Worker 
961*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_src_index(nir_src * src)962*61046927SAndroid Build Coastguard Worker bi_src_index(nir_src *src)
963*61046927SAndroid Build Coastguard Worker {
964*61046927SAndroid Build Coastguard Worker    if (nir_src_is_const(*src) && nir_src_bit_size(*src) <= 32) {
965*61046927SAndroid Build Coastguard Worker       return bi_imm_u32(nir_src_as_uint(*src));
966*61046927SAndroid Build Coastguard Worker    } else {
967*61046927SAndroid Build Coastguard Worker       return bi_def_index(src->ssa);
968*61046927SAndroid Build Coastguard Worker    }
969*61046927SAndroid Build Coastguard Worker }
970*61046927SAndroid Build Coastguard Worker 
971*61046927SAndroid Build Coastguard Worker /* Iterators for Bifrost IR */
972*61046927SAndroid Build Coastguard Worker 
973*61046927SAndroid Build Coastguard Worker #define bi_foreach_block(ctx, v)                                               \
974*61046927SAndroid Build Coastguard Worker    list_for_each_entry(bi_block, v, &ctx->blocks, link)
975*61046927SAndroid Build Coastguard Worker 
976*61046927SAndroid Build Coastguard Worker #define bi_foreach_block_rev(ctx, v)                                           \
977*61046927SAndroid Build Coastguard Worker    list_for_each_entry_rev(bi_block, v, &ctx->blocks, link)
978*61046927SAndroid Build Coastguard Worker 
979*61046927SAndroid Build Coastguard Worker #define bi_foreach_block_from(ctx, from, v)                                    \
980*61046927SAndroid Build Coastguard Worker    list_for_each_entry_from(bi_block, v, from, &ctx->blocks, link)
981*61046927SAndroid Build Coastguard Worker 
982*61046927SAndroid Build Coastguard Worker #define bi_foreach_block_from_rev(ctx, from, v)                                \
983*61046927SAndroid Build Coastguard Worker    list_for_each_entry_from_rev(bi_block, v, from, &ctx->blocks, link)
984*61046927SAndroid Build Coastguard Worker 
985*61046927SAndroid Build Coastguard Worker #define bi_foreach_instr_in_block(block, v)                                    \
986*61046927SAndroid Build Coastguard Worker    list_for_each_entry(bi_instr, v, &(block)->instructions, link)
987*61046927SAndroid Build Coastguard Worker 
988*61046927SAndroid Build Coastguard Worker #define bi_foreach_instr_in_block_rev(block, v)                                \
989*61046927SAndroid Build Coastguard Worker    list_for_each_entry_rev(bi_instr, v, &(block)->instructions, link)
990*61046927SAndroid Build Coastguard Worker 
991*61046927SAndroid Build Coastguard Worker #define bi_foreach_instr_in_block_safe(block, v)                               \
992*61046927SAndroid Build Coastguard Worker    list_for_each_entry_safe(bi_instr, v, &(block)->instructions, link)
993*61046927SAndroid Build Coastguard Worker 
994*61046927SAndroid Build Coastguard Worker #define bi_foreach_instr_in_block_safe_rev(block, v)                           \
995*61046927SAndroid Build Coastguard Worker    list_for_each_entry_safe_rev(bi_instr, v, &(block)->instructions, link)
996*61046927SAndroid Build Coastguard Worker 
997*61046927SAndroid Build Coastguard Worker #define bi_foreach_instr_in_block_from(block, v, from)                         \
998*61046927SAndroid Build Coastguard Worker    list_for_each_entry_from(bi_instr, v, from, &(block)->instructions, link)
999*61046927SAndroid Build Coastguard Worker 
1000*61046927SAndroid Build Coastguard Worker #define bi_foreach_instr_in_block_from_rev(block, v, from)                     \
1001*61046927SAndroid Build Coastguard Worker    list_for_each_entry_from_rev(bi_instr, v, from, &(block)->instructions, link)
1002*61046927SAndroid Build Coastguard Worker 
1003*61046927SAndroid Build Coastguard Worker #define bi_foreach_clause_in_block(block, v)                                   \
1004*61046927SAndroid Build Coastguard Worker    list_for_each_entry(bi_clause, v, &(block)->clauses, link)
1005*61046927SAndroid Build Coastguard Worker 
1006*61046927SAndroid Build Coastguard Worker #define bi_foreach_clause_in_block_rev(block, v)                               \
1007*61046927SAndroid Build Coastguard Worker    list_for_each_entry_rev(bi_clause, v, &(block)->clauses, link)
1008*61046927SAndroid Build Coastguard Worker 
1009*61046927SAndroid Build Coastguard Worker #define bi_foreach_clause_in_block_safe(block, v)                              \
1010*61046927SAndroid Build Coastguard Worker    list_for_each_entry_safe(bi_clause, v, &(block)->clauses, link)
1011*61046927SAndroid Build Coastguard Worker 
1012*61046927SAndroid Build Coastguard Worker #define bi_foreach_clause_in_block_from(block, v, from)                        \
1013*61046927SAndroid Build Coastguard Worker    list_for_each_entry_from(bi_clause, v, from, &(block)->clauses, link)
1014*61046927SAndroid Build Coastguard Worker 
1015*61046927SAndroid Build Coastguard Worker #define bi_foreach_clause_in_block_from_rev(block, v, from)                    \
1016*61046927SAndroid Build Coastguard Worker    list_for_each_entry_from_rev(bi_clause, v, from, &(block)->clauses, link)
1017*61046927SAndroid Build Coastguard Worker 
1018*61046927SAndroid Build Coastguard Worker #define bi_foreach_instr_global(ctx, v)                                        \
1019*61046927SAndroid Build Coastguard Worker    bi_foreach_block(ctx, v_block)                                              \
1020*61046927SAndroid Build Coastguard Worker       bi_foreach_instr_in_block(v_block, v)
1021*61046927SAndroid Build Coastguard Worker 
1022*61046927SAndroid Build Coastguard Worker #define bi_foreach_instr_global_rev(ctx, v)                                    \
1023*61046927SAndroid Build Coastguard Worker    bi_foreach_block_rev(ctx, v_block)                                          \
1024*61046927SAndroid Build Coastguard Worker       bi_foreach_instr_in_block_rev(v_block, v)
1025*61046927SAndroid Build Coastguard Worker 
1026*61046927SAndroid Build Coastguard Worker #define bi_foreach_instr_global_safe(ctx, v)                                   \
1027*61046927SAndroid Build Coastguard Worker    bi_foreach_block(ctx, v_block)                                              \
1028*61046927SAndroid Build Coastguard Worker       bi_foreach_instr_in_block_safe(v_block, v)
1029*61046927SAndroid Build Coastguard Worker 
1030*61046927SAndroid Build Coastguard Worker #define bi_foreach_instr_global_rev_safe(ctx, v)                               \
1031*61046927SAndroid Build Coastguard Worker    bi_foreach_block_rev(ctx, v_block)                                          \
1032*61046927SAndroid Build Coastguard Worker    bi_foreach_instr_in_block_rev_safe(v_block, v)
1033*61046927SAndroid Build Coastguard Worker 
1034*61046927SAndroid Build Coastguard Worker #define bi_foreach_instr_in_tuple(tuple, v)                                    \
1035*61046927SAndroid Build Coastguard Worker    for (bi_instr *v = (tuple)->fma ?: (tuple)->add; v != NULL;                 \
1036*61046927SAndroid Build Coastguard Worker         v = (v == (tuple)->add) ? NULL : (tuple)->add)
1037*61046927SAndroid Build Coastguard Worker 
1038*61046927SAndroid Build Coastguard Worker #define bi_foreach_successor(blk, v)                                           \
1039*61046927SAndroid Build Coastguard Worker    bi_block *v;                                                                \
1040*61046927SAndroid Build Coastguard Worker    bi_block **_v;                                                              \
1041*61046927SAndroid Build Coastguard Worker    for (_v = &blk->successors[0], v = *_v;                                     \
1042*61046927SAndroid Build Coastguard Worker         v != NULL && _v < &blk->successors[2]; _v++, v = *_v)
1043*61046927SAndroid Build Coastguard Worker 
1044*61046927SAndroid Build Coastguard Worker #define bi_foreach_predecessor(blk, v)                                         \
1045*61046927SAndroid Build Coastguard Worker    util_dynarray_foreach(&(blk)->predecessors, bi_block *, v)
1046*61046927SAndroid Build Coastguard Worker 
1047*61046927SAndroid Build Coastguard Worker #define bi_foreach_src(ins, v) for (unsigned v = 0; v < ins->nr_srcs; ++v)
1048*61046927SAndroid Build Coastguard Worker 
1049*61046927SAndroid Build Coastguard Worker #define bi_foreach_dest(ins, v) for (unsigned v = 0; v < ins->nr_dests; ++v)
1050*61046927SAndroid Build Coastguard Worker 
1051*61046927SAndroid Build Coastguard Worker #define bi_foreach_ssa_src(ins, v)                                             \
1052*61046927SAndroid Build Coastguard Worker    bi_foreach_src(ins, v)                                                      \
1053*61046927SAndroid Build Coastguard Worker       if (ins->src[v].type == BI_INDEX_NORMAL)
1054*61046927SAndroid Build Coastguard Worker 
1055*61046927SAndroid Build Coastguard Worker #define bi_foreach_ssa_dest(ins, v)                                            \
1056*61046927SAndroid Build Coastguard Worker    bi_foreach_dest(ins, v)                                                     \
1057*61046927SAndroid Build Coastguard Worker       if (ins->dest[v].type == BI_INDEX_NORMAL)
1058*61046927SAndroid Build Coastguard Worker 
1059*61046927SAndroid Build Coastguard Worker #define bi_foreach_instr_and_src_in_tuple(tuple, ins, s)                       \
1060*61046927SAndroid Build Coastguard Worker    bi_foreach_instr_in_tuple(tuple, ins)                                       \
1061*61046927SAndroid Build Coastguard Worker       bi_foreach_src(ins, s)
1062*61046927SAndroid Build Coastguard Worker 
1063*61046927SAndroid Build Coastguard Worker /*
1064*61046927SAndroid Build Coastguard Worker  * Find the index of a predecessor, used as the implicit order of phi sources.
1065*61046927SAndroid Build Coastguard Worker  */
1066*61046927SAndroid Build Coastguard Worker static inline unsigned
bi_predecessor_index(bi_block * succ,bi_block * pred)1067*61046927SAndroid Build Coastguard Worker bi_predecessor_index(bi_block *succ, bi_block *pred)
1068*61046927SAndroid Build Coastguard Worker {
1069*61046927SAndroid Build Coastguard Worker    unsigned index = 0;
1070*61046927SAndroid Build Coastguard Worker 
1071*61046927SAndroid Build Coastguard Worker    bi_foreach_predecessor(succ, x) {
1072*61046927SAndroid Build Coastguard Worker       if (*x == pred)
1073*61046927SAndroid Build Coastguard Worker          return index;
1074*61046927SAndroid Build Coastguard Worker 
1075*61046927SAndroid Build Coastguard Worker       index++;
1076*61046927SAndroid Build Coastguard Worker    }
1077*61046927SAndroid Build Coastguard Worker 
1078*61046927SAndroid Build Coastguard Worker    unreachable("Invalid predecessor");
1079*61046927SAndroid Build Coastguard Worker }
1080*61046927SAndroid Build Coastguard Worker 
1081*61046927SAndroid Build Coastguard Worker static inline bi_instr *
bi_prev_op(bi_instr * ins)1082*61046927SAndroid Build Coastguard Worker bi_prev_op(bi_instr *ins)
1083*61046927SAndroid Build Coastguard Worker {
1084*61046927SAndroid Build Coastguard Worker    return list_last_entry(&(ins->link), bi_instr, link);
1085*61046927SAndroid Build Coastguard Worker }
1086*61046927SAndroid Build Coastguard Worker 
1087*61046927SAndroid Build Coastguard Worker static inline bi_instr *
bi_next_op(bi_instr * ins)1088*61046927SAndroid Build Coastguard Worker bi_next_op(bi_instr *ins)
1089*61046927SAndroid Build Coastguard Worker {
1090*61046927SAndroid Build Coastguard Worker    return list_first_entry(&(ins->link), bi_instr, link);
1091*61046927SAndroid Build Coastguard Worker }
1092*61046927SAndroid Build Coastguard Worker 
1093*61046927SAndroid Build Coastguard Worker static inline bi_block *
bi_next_block(bi_block * block)1094*61046927SAndroid Build Coastguard Worker bi_next_block(bi_block *block)
1095*61046927SAndroid Build Coastguard Worker {
1096*61046927SAndroid Build Coastguard Worker    return list_first_entry(&(block->link), bi_block, link);
1097*61046927SAndroid Build Coastguard Worker }
1098*61046927SAndroid Build Coastguard Worker 
1099*61046927SAndroid Build Coastguard Worker static inline bi_block *
bi_entry_block(bi_context * ctx)1100*61046927SAndroid Build Coastguard Worker bi_entry_block(bi_context *ctx)
1101*61046927SAndroid Build Coastguard Worker {
1102*61046927SAndroid Build Coastguard Worker    return list_first_entry(&ctx->blocks, bi_block, link);
1103*61046927SAndroid Build Coastguard Worker }
1104*61046927SAndroid Build Coastguard Worker 
1105*61046927SAndroid Build Coastguard Worker /* BIR manipulation */
1106*61046927SAndroid Build Coastguard Worker 
1107*61046927SAndroid Build Coastguard Worker bool bi_has_arg(const bi_instr *ins, bi_index arg);
1108*61046927SAndroid Build Coastguard Worker unsigned bi_count_read_registers(const bi_instr *ins, unsigned src);
1109*61046927SAndroid Build Coastguard Worker unsigned bi_count_write_registers(const bi_instr *ins, unsigned dest);
1110*61046927SAndroid Build Coastguard Worker bool bi_is_regfmt_16(enum bi_register_format fmt);
1111*61046927SAndroid Build Coastguard Worker unsigned bi_writemask(const bi_instr *ins, unsigned dest);
1112*61046927SAndroid Build Coastguard Worker bi_clause *bi_next_clause(bi_context *ctx, bi_block *block, bi_clause *clause);
1113*61046927SAndroid Build Coastguard Worker bool bi_side_effects(const bi_instr *I);
1114*61046927SAndroid Build Coastguard Worker bool bi_reconverge_branches(bi_block *block);
1115*61046927SAndroid Build Coastguard Worker 
1116*61046927SAndroid Build Coastguard Worker bool bi_can_replace_with_csel(bi_instr *I);
1117*61046927SAndroid Build Coastguard Worker 
1118*61046927SAndroid Build Coastguard Worker void bi_print_instr(const bi_instr *I, FILE *fp);
1119*61046927SAndroid Build Coastguard Worker void bi_print_slots(bi_registers *regs, FILE *fp);
1120*61046927SAndroid Build Coastguard Worker void bi_print_tuple(bi_tuple *tuple, FILE *fp);
1121*61046927SAndroid Build Coastguard Worker void bi_print_clause(bi_clause *clause, FILE *fp);
1122*61046927SAndroid Build Coastguard Worker void bi_print_block(bi_block *block, FILE *fp);
1123*61046927SAndroid Build Coastguard Worker void bi_print_shader(bi_context *ctx, FILE *fp);
1124*61046927SAndroid Build Coastguard Worker 
1125*61046927SAndroid Build Coastguard Worker /* BIR passes */
1126*61046927SAndroid Build Coastguard Worker 
1127*61046927SAndroid Build Coastguard Worker bool bi_instr_uses_helpers(bi_instr *I);
1128*61046927SAndroid Build Coastguard Worker bool bi_block_terminates_helpers(bi_block *block);
1129*61046927SAndroid Build Coastguard Worker void bi_analyze_helper_terminate(bi_context *ctx);
1130*61046927SAndroid Build Coastguard Worker void bi_mark_clauses_td(bi_context *ctx);
1131*61046927SAndroid Build Coastguard Worker 
1132*61046927SAndroid Build Coastguard Worker void bi_analyze_helper_requirements(bi_context *ctx);
1133*61046927SAndroid Build Coastguard Worker void bi_opt_copy_prop(bi_context *ctx);
1134*61046927SAndroid Build Coastguard Worker void bi_opt_dce(bi_context *ctx, bool partial);
1135*61046927SAndroid Build Coastguard Worker void bi_opt_cse(bi_context *ctx);
1136*61046927SAndroid Build Coastguard Worker void bi_opt_mod_prop_forward(bi_context *ctx);
1137*61046927SAndroid Build Coastguard Worker void bi_opt_mod_prop_backward(bi_context *ctx);
1138*61046927SAndroid Build Coastguard Worker void bi_opt_fuse_dual_texture(bi_context *ctx);
1139*61046927SAndroid Build Coastguard Worker void bi_opt_dce_post_ra(bi_context *ctx);
1140*61046927SAndroid Build Coastguard Worker void bi_opt_message_preload(bi_context *ctx);
1141*61046927SAndroid Build Coastguard Worker void bi_opt_push_ubo(bi_context *ctx);
1142*61046927SAndroid Build Coastguard Worker void bi_opt_reorder_push(bi_context *ctx);
1143*61046927SAndroid Build Coastguard Worker void bi_lower_swizzle(bi_context *ctx);
1144*61046927SAndroid Build Coastguard Worker void bi_lower_fau(bi_context *ctx);
1145*61046927SAndroid Build Coastguard Worker void bi_assign_scoreboard(bi_context *ctx);
1146*61046927SAndroid Build Coastguard Worker void bi_register_allocate(bi_context *ctx);
1147*61046927SAndroid Build Coastguard Worker void va_optimize(bi_context *ctx);
1148*61046927SAndroid Build Coastguard Worker void va_lower_split_64bit(bi_context *ctx);
1149*61046927SAndroid Build Coastguard Worker 
1150*61046927SAndroid Build Coastguard Worker void bi_lower_opt_instructions(bi_context *ctx);
1151*61046927SAndroid Build Coastguard Worker 
1152*61046927SAndroid Build Coastguard Worker void bi_pressure_schedule(bi_context *ctx);
1153*61046927SAndroid Build Coastguard Worker void bi_schedule(bi_context *ctx);
1154*61046927SAndroid Build Coastguard Worker bool bi_can_fma(bi_instr *ins);
1155*61046927SAndroid Build Coastguard Worker bool bi_can_add(bi_instr *ins);
1156*61046927SAndroid Build Coastguard Worker bool bi_must_message(bi_instr *ins);
1157*61046927SAndroid Build Coastguard Worker bool bi_reads_zero(bi_instr *ins);
1158*61046927SAndroid Build Coastguard Worker bool bi_reads_temps(bi_instr *ins, unsigned src);
1159*61046927SAndroid Build Coastguard Worker bool bi_reads_t(bi_instr *ins, unsigned src);
1160*61046927SAndroid Build Coastguard Worker 
1161*61046927SAndroid Build Coastguard Worker #ifndef NDEBUG
1162*61046927SAndroid Build Coastguard Worker bool bi_validate_initialization(bi_context *ctx);
1163*61046927SAndroid Build Coastguard Worker void bi_validate(bi_context *ctx, const char *after_str);
1164*61046927SAndroid Build Coastguard Worker #else
1165*61046927SAndroid Build Coastguard Worker static inline bool
bi_validate_initialization(UNUSED bi_context * ctx)1166*61046927SAndroid Build Coastguard Worker bi_validate_initialization(UNUSED bi_context *ctx)
1167*61046927SAndroid Build Coastguard Worker {
1168*61046927SAndroid Build Coastguard Worker    return true;
1169*61046927SAndroid Build Coastguard Worker }
1170*61046927SAndroid Build Coastguard Worker static inline void
bi_validate(UNUSED bi_context * ctx,UNUSED const char * after_str)1171*61046927SAndroid Build Coastguard Worker bi_validate(UNUSED bi_context *ctx, UNUSED const char *after_str)
1172*61046927SAndroid Build Coastguard Worker {
1173*61046927SAndroid Build Coastguard Worker    return;
1174*61046927SAndroid Build Coastguard Worker }
1175*61046927SAndroid Build Coastguard Worker #endif
1176*61046927SAndroid Build Coastguard Worker 
1177*61046927SAndroid Build Coastguard Worker uint32_t bi_fold_constant(bi_instr *I, bool *unsupported);
1178*61046927SAndroid Build Coastguard Worker bool bi_opt_constant_fold(bi_context *ctx);
1179*61046927SAndroid Build Coastguard Worker 
1180*61046927SAndroid Build Coastguard Worker /* Liveness */
1181*61046927SAndroid Build Coastguard Worker 
1182*61046927SAndroid Build Coastguard Worker void bi_compute_liveness_ssa(bi_context *ctx);
1183*61046927SAndroid Build Coastguard Worker void bi_liveness_ins_update_ssa(BITSET_WORD *live, const bi_instr *ins);
1184*61046927SAndroid Build Coastguard Worker 
1185*61046927SAndroid Build Coastguard Worker void bi_postra_liveness(bi_context *ctx);
1186*61046927SAndroid Build Coastguard Worker uint64_t MUST_CHECK bi_postra_liveness_ins(uint64_t live, bi_instr *ins);
1187*61046927SAndroid Build Coastguard Worker 
1188*61046927SAndroid Build Coastguard Worker /* Layout */
1189*61046927SAndroid Build Coastguard Worker 
1190*61046927SAndroid Build Coastguard Worker signed bi_block_offset(bi_context *ctx, bi_clause *start, bi_block *target);
1191*61046927SAndroid Build Coastguard Worker bool bi_ec0_packed(unsigned tuple_count);
1192*61046927SAndroid Build Coastguard Worker 
1193*61046927SAndroid Build Coastguard Worker /* Check if there are no more instructions starting with a given block, this
1194*61046927SAndroid Build Coastguard Worker  * needs to recurse in case a shader ends with multiple empty blocks */
1195*61046927SAndroid Build Coastguard Worker 
1196*61046927SAndroid Build Coastguard Worker static inline bool
bi_is_terminal_block(bi_block * block)1197*61046927SAndroid Build Coastguard Worker bi_is_terminal_block(bi_block *block)
1198*61046927SAndroid Build Coastguard Worker {
1199*61046927SAndroid Build Coastguard Worker    return (block == NULL) || (list_is_empty(&block->instructions) &&
1200*61046927SAndroid Build Coastguard Worker                               bi_is_terminal_block(block->successors[0]) &&
1201*61046927SAndroid Build Coastguard Worker                               bi_is_terminal_block(block->successors[1]));
1202*61046927SAndroid Build Coastguard Worker }
1203*61046927SAndroid Build Coastguard Worker 
1204*61046927SAndroid Build Coastguard Worker /* Code emit */
1205*61046927SAndroid Build Coastguard Worker 
1206*61046927SAndroid Build Coastguard Worker /* Returns the size of the final clause */
1207*61046927SAndroid Build Coastguard Worker unsigned bi_pack(bi_context *ctx, struct util_dynarray *emission);
1208*61046927SAndroid Build Coastguard Worker void bi_pack_valhall(bi_context *ctx, struct util_dynarray *emission);
1209*61046927SAndroid Build Coastguard Worker 
1210*61046927SAndroid Build Coastguard Worker struct bi_packed_tuple {
1211*61046927SAndroid Build Coastguard Worker    uint64_t lo;
1212*61046927SAndroid Build Coastguard Worker    uint64_t hi;
1213*61046927SAndroid Build Coastguard Worker };
1214*61046927SAndroid Build Coastguard Worker 
1215*61046927SAndroid Build Coastguard Worker uint8_t bi_pack_literal(enum bi_clause_subword literal);
1216*61046927SAndroid Build Coastguard Worker 
1217*61046927SAndroid Build Coastguard Worker uint8_t bi_pack_upper(enum bi_clause_subword upper,
1218*61046927SAndroid Build Coastguard Worker                       struct bi_packed_tuple *tuples,
1219*61046927SAndroid Build Coastguard Worker                       ASSERTED unsigned tuple_count);
1220*61046927SAndroid Build Coastguard Worker uint64_t bi_pack_tuple_bits(enum bi_clause_subword idx,
1221*61046927SAndroid Build Coastguard Worker                             struct bi_packed_tuple *tuples,
1222*61046927SAndroid Build Coastguard Worker                             ASSERTED unsigned tuple_count, unsigned offset,
1223*61046927SAndroid Build Coastguard Worker                             unsigned nbits);
1224*61046927SAndroid Build Coastguard Worker 
1225*61046927SAndroid Build Coastguard Worker uint8_t bi_pack_sync(enum bi_clause_subword t1, enum bi_clause_subword t2,
1226*61046927SAndroid Build Coastguard Worker                      enum bi_clause_subword t3, struct bi_packed_tuple *tuples,
1227*61046927SAndroid Build Coastguard Worker                      ASSERTED unsigned tuple_count, bool z);
1228*61046927SAndroid Build Coastguard Worker 
1229*61046927SAndroid Build Coastguard Worker void bi_pack_format(struct util_dynarray *emission, unsigned index,
1230*61046927SAndroid Build Coastguard Worker                     struct bi_packed_tuple *tuples,
1231*61046927SAndroid Build Coastguard Worker                     ASSERTED unsigned tuple_count, uint64_t header,
1232*61046927SAndroid Build Coastguard Worker                     uint64_t ec0, unsigned m0, bool z);
1233*61046927SAndroid Build Coastguard Worker 
1234*61046927SAndroid Build Coastguard Worker unsigned bi_pack_fma(bi_instr *I, enum bifrost_packed_src src0,
1235*61046927SAndroid Build Coastguard Worker                      enum bifrost_packed_src src1, enum bifrost_packed_src src2,
1236*61046927SAndroid Build Coastguard Worker                      enum bifrost_packed_src src3);
1237*61046927SAndroid Build Coastguard Worker unsigned bi_pack_add(bi_instr *I, enum bifrost_packed_src src0,
1238*61046927SAndroid Build Coastguard Worker                      enum bifrost_packed_src src1, enum bifrost_packed_src src2,
1239*61046927SAndroid Build Coastguard Worker                      enum bifrost_packed_src src3);
1240*61046927SAndroid Build Coastguard Worker 
1241*61046927SAndroid Build Coastguard Worker /* Like in NIR, for use with the builder */
1242*61046927SAndroid Build Coastguard Worker 
1243*61046927SAndroid Build Coastguard Worker enum bi_cursor_option {
1244*61046927SAndroid Build Coastguard Worker    bi_cursor_after_block,
1245*61046927SAndroid Build Coastguard Worker    bi_cursor_before_instr,
1246*61046927SAndroid Build Coastguard Worker    bi_cursor_after_instr
1247*61046927SAndroid Build Coastguard Worker };
1248*61046927SAndroid Build Coastguard Worker 
1249*61046927SAndroid Build Coastguard Worker typedef struct {
1250*61046927SAndroid Build Coastguard Worker    enum bi_cursor_option option;
1251*61046927SAndroid Build Coastguard Worker 
1252*61046927SAndroid Build Coastguard Worker    union {
1253*61046927SAndroid Build Coastguard Worker       bi_block *block;
1254*61046927SAndroid Build Coastguard Worker       bi_instr *instr;
1255*61046927SAndroid Build Coastguard Worker    };
1256*61046927SAndroid Build Coastguard Worker } bi_cursor;
1257*61046927SAndroid Build Coastguard Worker 
1258*61046927SAndroid Build Coastguard Worker static inline bi_cursor
bi_after_block(bi_block * block)1259*61046927SAndroid Build Coastguard Worker bi_after_block(bi_block *block)
1260*61046927SAndroid Build Coastguard Worker {
1261*61046927SAndroid Build Coastguard Worker    return (bi_cursor){.option = bi_cursor_after_block, .block = block};
1262*61046927SAndroid Build Coastguard Worker }
1263*61046927SAndroid Build Coastguard Worker 
1264*61046927SAndroid Build Coastguard Worker static inline bi_cursor
bi_before_instr(bi_instr * instr)1265*61046927SAndroid Build Coastguard Worker bi_before_instr(bi_instr *instr)
1266*61046927SAndroid Build Coastguard Worker {
1267*61046927SAndroid Build Coastguard Worker    return (bi_cursor){.option = bi_cursor_before_instr, .instr = instr};
1268*61046927SAndroid Build Coastguard Worker }
1269*61046927SAndroid Build Coastguard Worker 
1270*61046927SAndroid Build Coastguard Worker static inline bi_cursor
bi_after_instr(bi_instr * instr)1271*61046927SAndroid Build Coastguard Worker bi_after_instr(bi_instr *instr)
1272*61046927SAndroid Build Coastguard Worker {
1273*61046927SAndroid Build Coastguard Worker    return (bi_cursor){.option = bi_cursor_after_instr, .instr = instr};
1274*61046927SAndroid Build Coastguard Worker }
1275*61046927SAndroid Build Coastguard Worker 
1276*61046927SAndroid Build Coastguard Worker static inline bi_cursor
bi_after_block_logical(bi_block * block)1277*61046927SAndroid Build Coastguard Worker bi_after_block_logical(bi_block *block)
1278*61046927SAndroid Build Coastguard Worker {
1279*61046927SAndroid Build Coastguard Worker    if (list_is_empty(&block->instructions))
1280*61046927SAndroid Build Coastguard Worker       return bi_after_block(block);
1281*61046927SAndroid Build Coastguard Worker 
1282*61046927SAndroid Build Coastguard Worker    bi_instr *last = list_last_entry(&block->instructions, bi_instr, link);
1283*61046927SAndroid Build Coastguard Worker    assert(last != NULL);
1284*61046927SAndroid Build Coastguard Worker 
1285*61046927SAndroid Build Coastguard Worker    if (last->branch_target)
1286*61046927SAndroid Build Coastguard Worker       return bi_before_instr(last);
1287*61046927SAndroid Build Coastguard Worker    else
1288*61046927SAndroid Build Coastguard Worker       return bi_after_block(block);
1289*61046927SAndroid Build Coastguard Worker }
1290*61046927SAndroid Build Coastguard Worker 
1291*61046927SAndroid Build Coastguard Worker static inline bi_cursor
bi_before_nonempty_block(bi_block * block)1292*61046927SAndroid Build Coastguard Worker bi_before_nonempty_block(bi_block *block)
1293*61046927SAndroid Build Coastguard Worker {
1294*61046927SAndroid Build Coastguard Worker    bi_instr *I = list_first_entry(&block->instructions, bi_instr, link);
1295*61046927SAndroid Build Coastguard Worker    assert(I != NULL);
1296*61046927SAndroid Build Coastguard Worker 
1297*61046927SAndroid Build Coastguard Worker    return bi_before_instr(I);
1298*61046927SAndroid Build Coastguard Worker }
1299*61046927SAndroid Build Coastguard Worker 
1300*61046927SAndroid Build Coastguard Worker static inline bi_cursor
bi_before_block(bi_block * block)1301*61046927SAndroid Build Coastguard Worker bi_before_block(bi_block *block)
1302*61046927SAndroid Build Coastguard Worker {
1303*61046927SAndroid Build Coastguard Worker    if (list_is_empty(&block->instructions))
1304*61046927SAndroid Build Coastguard Worker       return bi_after_block(block);
1305*61046927SAndroid Build Coastguard Worker    else
1306*61046927SAndroid Build Coastguard Worker       return bi_before_nonempty_block(block);
1307*61046927SAndroid Build Coastguard Worker }
1308*61046927SAndroid Build Coastguard Worker 
1309*61046927SAndroid Build Coastguard Worker /* Invariant: a tuple must be nonempty UNLESS it is the last tuple of a clause,
1310*61046927SAndroid Build Coastguard Worker  * in which case there must exist a nonempty penultimate tuple */
1311*61046927SAndroid Build Coastguard Worker 
1312*61046927SAndroid Build Coastguard Worker ATTRIBUTE_RETURNS_NONNULL static inline bi_instr *
bi_first_instr_in_tuple(bi_tuple * tuple)1313*61046927SAndroid Build Coastguard Worker bi_first_instr_in_tuple(bi_tuple *tuple)
1314*61046927SAndroid Build Coastguard Worker {
1315*61046927SAndroid Build Coastguard Worker    bi_instr *instr = tuple->fma ?: tuple->add;
1316*61046927SAndroid Build Coastguard Worker    assert(instr != NULL);
1317*61046927SAndroid Build Coastguard Worker    return instr;
1318*61046927SAndroid Build Coastguard Worker }
1319*61046927SAndroid Build Coastguard Worker 
1320*61046927SAndroid Build Coastguard Worker ATTRIBUTE_RETURNS_NONNULL static inline bi_instr *
bi_first_instr_in_clause(bi_clause * clause)1321*61046927SAndroid Build Coastguard Worker bi_first_instr_in_clause(bi_clause *clause)
1322*61046927SAndroid Build Coastguard Worker {
1323*61046927SAndroid Build Coastguard Worker    return bi_first_instr_in_tuple(&clause->tuples[0]);
1324*61046927SAndroid Build Coastguard Worker }
1325*61046927SAndroid Build Coastguard Worker 
1326*61046927SAndroid Build Coastguard Worker ATTRIBUTE_RETURNS_NONNULL static inline bi_instr *
bi_last_instr_in_clause(bi_clause * clause)1327*61046927SAndroid Build Coastguard Worker bi_last_instr_in_clause(bi_clause *clause)
1328*61046927SAndroid Build Coastguard Worker {
1329*61046927SAndroid Build Coastguard Worker    bi_tuple tuple = clause->tuples[clause->tuple_count - 1];
1330*61046927SAndroid Build Coastguard Worker    bi_instr *instr = tuple.add ?: tuple.fma;
1331*61046927SAndroid Build Coastguard Worker 
1332*61046927SAndroid Build Coastguard Worker    if (!instr) {
1333*61046927SAndroid Build Coastguard Worker       assert(clause->tuple_count >= 2);
1334*61046927SAndroid Build Coastguard Worker       tuple = clause->tuples[clause->tuple_count - 2];
1335*61046927SAndroid Build Coastguard Worker       instr = tuple.add ?: tuple.fma;
1336*61046927SAndroid Build Coastguard Worker    }
1337*61046927SAndroid Build Coastguard Worker 
1338*61046927SAndroid Build Coastguard Worker    assert(instr != NULL);
1339*61046927SAndroid Build Coastguard Worker    return instr;
1340*61046927SAndroid Build Coastguard Worker }
1341*61046927SAndroid Build Coastguard Worker 
1342*61046927SAndroid Build Coastguard Worker /* Implemented by expanding bi_foreach_instr_in_block_from(_rev) with the start
1343*61046927SAndroid Build Coastguard Worker  * (end) of the clause and adding a condition for the clause boundary */
1344*61046927SAndroid Build Coastguard Worker 
1345*61046927SAndroid Build Coastguard Worker #define bi_foreach_instr_in_clause(block, clause, pos)                         \
1346*61046927SAndroid Build Coastguard Worker    for (bi_instr *pos =                                                        \
1347*61046927SAndroid Build Coastguard Worker            list_entry(bi_first_instr_in_clause(clause), bi_instr, link);       \
1348*61046927SAndroid Build Coastguard Worker         (&pos->link != &(block)->instructions) &&                              \
1349*61046927SAndroid Build Coastguard Worker         (pos != bi_next_op(bi_last_instr_in_clause(clause)));                  \
1350*61046927SAndroid Build Coastguard Worker         pos = list_entry(pos->link.next, bi_instr, link))
1351*61046927SAndroid Build Coastguard Worker 
1352*61046927SAndroid Build Coastguard Worker #define bi_foreach_instr_in_clause_rev(block, clause, pos)                     \
1353*61046927SAndroid Build Coastguard Worker    for (bi_instr *pos =                                                        \
1354*61046927SAndroid Build Coastguard Worker            list_entry(bi_last_instr_in_clause(clause), bi_instr, link);        \
1355*61046927SAndroid Build Coastguard Worker         (&pos->link != &(block)->instructions) &&                              \
1356*61046927SAndroid Build Coastguard Worker         pos != bi_prev_op(bi_first_instr_in_clause(clause));                   \
1357*61046927SAndroid Build Coastguard Worker         pos = list_entry(pos->link.prev, bi_instr, link))
1358*61046927SAndroid Build Coastguard Worker 
1359*61046927SAndroid Build Coastguard Worker static inline bi_cursor
bi_before_clause(bi_clause * clause)1360*61046927SAndroid Build Coastguard Worker bi_before_clause(bi_clause *clause)
1361*61046927SAndroid Build Coastguard Worker {
1362*61046927SAndroid Build Coastguard Worker    return bi_before_instr(bi_first_instr_in_clause(clause));
1363*61046927SAndroid Build Coastguard Worker }
1364*61046927SAndroid Build Coastguard Worker 
1365*61046927SAndroid Build Coastguard Worker static inline bi_cursor
bi_before_tuple(bi_tuple * tuple)1366*61046927SAndroid Build Coastguard Worker bi_before_tuple(bi_tuple *tuple)
1367*61046927SAndroid Build Coastguard Worker {
1368*61046927SAndroid Build Coastguard Worker    return bi_before_instr(bi_first_instr_in_tuple(tuple));
1369*61046927SAndroid Build Coastguard Worker }
1370*61046927SAndroid Build Coastguard Worker 
1371*61046927SAndroid Build Coastguard Worker static inline bi_cursor
bi_after_clause(bi_clause * clause)1372*61046927SAndroid Build Coastguard Worker bi_after_clause(bi_clause *clause)
1373*61046927SAndroid Build Coastguard Worker {
1374*61046927SAndroid Build Coastguard Worker    return bi_after_instr(bi_last_instr_in_clause(clause));
1375*61046927SAndroid Build Coastguard Worker }
1376*61046927SAndroid Build Coastguard Worker 
1377*61046927SAndroid Build Coastguard Worker /* IR builder in terms of cursor infrastructure */
1378*61046927SAndroid Build Coastguard Worker 
1379*61046927SAndroid Build Coastguard Worker typedef struct {
1380*61046927SAndroid Build Coastguard Worker    bi_context *shader;
1381*61046927SAndroid Build Coastguard Worker    bi_cursor cursor;
1382*61046927SAndroid Build Coastguard Worker } bi_builder;
1383*61046927SAndroid Build Coastguard Worker 
1384*61046927SAndroid Build Coastguard Worker static inline bi_builder
bi_init_builder(bi_context * ctx,bi_cursor cursor)1385*61046927SAndroid Build Coastguard Worker bi_init_builder(bi_context *ctx, bi_cursor cursor)
1386*61046927SAndroid Build Coastguard Worker {
1387*61046927SAndroid Build Coastguard Worker    return (bi_builder){.shader = ctx, .cursor = cursor};
1388*61046927SAndroid Build Coastguard Worker }
1389*61046927SAndroid Build Coastguard Worker 
1390*61046927SAndroid Build Coastguard Worker /* Insert an instruction at the cursor and move the cursor */
1391*61046927SAndroid Build Coastguard Worker 
1392*61046927SAndroid Build Coastguard Worker static inline void
bi_builder_insert(bi_cursor * cursor,bi_instr * I)1393*61046927SAndroid Build Coastguard Worker bi_builder_insert(bi_cursor *cursor, bi_instr *I)
1394*61046927SAndroid Build Coastguard Worker {
1395*61046927SAndroid Build Coastguard Worker    switch (cursor->option) {
1396*61046927SAndroid Build Coastguard Worker    case bi_cursor_after_instr:
1397*61046927SAndroid Build Coastguard Worker       list_add(&I->link, &cursor->instr->link);
1398*61046927SAndroid Build Coastguard Worker       cursor->instr = I;
1399*61046927SAndroid Build Coastguard Worker       return;
1400*61046927SAndroid Build Coastguard Worker 
1401*61046927SAndroid Build Coastguard Worker    case bi_cursor_after_block:
1402*61046927SAndroid Build Coastguard Worker       list_addtail(&I->link, &cursor->block->instructions);
1403*61046927SAndroid Build Coastguard Worker       cursor->option = bi_cursor_after_instr;
1404*61046927SAndroid Build Coastguard Worker       cursor->instr = I;
1405*61046927SAndroid Build Coastguard Worker       return;
1406*61046927SAndroid Build Coastguard Worker 
1407*61046927SAndroid Build Coastguard Worker    case bi_cursor_before_instr:
1408*61046927SAndroid Build Coastguard Worker       list_addtail(&I->link, &cursor->instr->link);
1409*61046927SAndroid Build Coastguard Worker       cursor->option = bi_cursor_after_instr;
1410*61046927SAndroid Build Coastguard Worker       cursor->instr = I;
1411*61046927SAndroid Build Coastguard Worker       return;
1412*61046927SAndroid Build Coastguard Worker    }
1413*61046927SAndroid Build Coastguard Worker 
1414*61046927SAndroid Build Coastguard Worker    unreachable("Invalid cursor option");
1415*61046927SAndroid Build Coastguard Worker }
1416*61046927SAndroid Build Coastguard Worker 
1417*61046927SAndroid Build Coastguard Worker bi_instr *bi_csel_from_mux(bi_builder *b, const bi_instr *I, bool must_sign);
1418*61046927SAndroid Build Coastguard Worker 
1419*61046927SAndroid Build Coastguard Worker /* Read back power-efficent garbage, TODO maybe merge with null? */
1420*61046927SAndroid Build Coastguard Worker static inline bi_index
bi_dontcare(bi_builder * b)1421*61046927SAndroid Build Coastguard Worker bi_dontcare(bi_builder *b)
1422*61046927SAndroid Build Coastguard Worker {
1423*61046927SAndroid Build Coastguard Worker    if (b->shader->arch >= 9)
1424*61046927SAndroid Build Coastguard Worker       return bi_zero();
1425*61046927SAndroid Build Coastguard Worker    else
1426*61046927SAndroid Build Coastguard Worker       return bi_passthrough(BIFROST_SRC_FAU_HI);
1427*61046927SAndroid Build Coastguard Worker }
1428*61046927SAndroid Build Coastguard Worker 
1429*61046927SAndroid Build Coastguard Worker #define bi_worklist_init(ctx, w)        u_worklist_init(w, ctx->num_blocks, ctx)
1430*61046927SAndroid Build Coastguard Worker #define bi_worklist_push_head(w, block) u_worklist_push_head(w, block, index)
1431*61046927SAndroid Build Coastguard Worker #define bi_worklist_push_tail(w, block) u_worklist_push_tail(w, block, index)
1432*61046927SAndroid Build Coastguard Worker #define bi_worklist_peek_head(w)        u_worklist_peek_head(w, bi_block, index)
1433*61046927SAndroid Build Coastguard Worker #define bi_worklist_pop_head(w)         u_worklist_pop_head(w, bi_block, index)
1434*61046927SAndroid Build Coastguard Worker #define bi_worklist_peek_tail(w)        u_worklist_peek_tail(w, bi_block, index)
1435*61046927SAndroid Build Coastguard Worker #define bi_worklist_pop_tail(w)         u_worklist_pop_tail(w, bi_block, index)
1436*61046927SAndroid Build Coastguard Worker 
1437*61046927SAndroid Build Coastguard Worker /* NIR passes */
1438*61046927SAndroid Build Coastguard Worker 
1439*61046927SAndroid Build Coastguard Worker bool bi_lower_divergent_indirects(nir_shader *shader, unsigned lanes);
1440*61046927SAndroid Build Coastguard Worker 
1441*61046927SAndroid Build Coastguard Worker #ifdef __cplusplus
1442*61046927SAndroid Build Coastguard Worker } /* extern C */
1443*61046927SAndroid Build Coastguard Worker #endif
1444*61046927SAndroid Build Coastguard Worker 
1445*61046927SAndroid Build Coastguard Worker #endif
1446