xref: /aosp_15_r20/external/mesa3d/src/freedreno/ir3/ir3.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2012 Rob Clark <[email protected]>
3*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker  */
5*61046927SAndroid Build Coastguard Worker 
6*61046927SAndroid Build Coastguard Worker #include "ir3.h"
7*61046927SAndroid Build Coastguard Worker 
8*61046927SAndroid Build Coastguard Worker #include <assert.h>
9*61046927SAndroid Build Coastguard Worker #include <errno.h>
10*61046927SAndroid Build Coastguard Worker #include <stdbool.h>
11*61046927SAndroid Build Coastguard Worker #include <stdio.h>
12*61046927SAndroid Build Coastguard Worker #include <stdlib.h>
13*61046927SAndroid Build Coastguard Worker #include <string.h>
14*61046927SAndroid Build Coastguard Worker 
15*61046927SAndroid Build Coastguard Worker #include "util/bitscan.h"
16*61046927SAndroid Build Coastguard Worker #include "util/half_float.h"
17*61046927SAndroid Build Coastguard Worker #include "util/ralloc.h"
18*61046927SAndroid Build Coastguard Worker #include "util/u_math.h"
19*61046927SAndroid Build Coastguard Worker 
20*61046927SAndroid Build Coastguard Worker #include "instr-a3xx.h"
21*61046927SAndroid Build Coastguard Worker #include "ir3_shader.h"
22*61046927SAndroid Build Coastguard Worker 
23*61046927SAndroid Build Coastguard Worker /* simple allocator to carve allocations out of an up-front allocated heap,
24*61046927SAndroid Build Coastguard Worker  * so that we can free everything easily in one shot.
25*61046927SAndroid Build Coastguard Worker  */
26*61046927SAndroid Build Coastguard Worker void *
ir3_alloc(struct ir3 * shader,int sz)27*61046927SAndroid Build Coastguard Worker ir3_alloc(struct ir3 *shader, int sz)
28*61046927SAndroid Build Coastguard Worker {
29*61046927SAndroid Build Coastguard Worker    return rzalloc_size(shader, sz); /* TODO: don't use rzalloc */
30*61046927SAndroid Build Coastguard Worker }
31*61046927SAndroid Build Coastguard Worker 
32*61046927SAndroid Build Coastguard Worker struct ir3 *
ir3_create(struct ir3_compiler * compiler,struct ir3_shader_variant * v)33*61046927SAndroid Build Coastguard Worker ir3_create(struct ir3_compiler *compiler, struct ir3_shader_variant *v)
34*61046927SAndroid Build Coastguard Worker {
35*61046927SAndroid Build Coastguard Worker    struct ir3 *shader = rzalloc(v, struct ir3);
36*61046927SAndroid Build Coastguard Worker 
37*61046927SAndroid Build Coastguard Worker    shader->compiler = compiler;
38*61046927SAndroid Build Coastguard Worker    shader->type = v->type;
39*61046927SAndroid Build Coastguard Worker 
40*61046927SAndroid Build Coastguard Worker    list_inithead(&shader->block_list);
41*61046927SAndroid Build Coastguard Worker    list_inithead(&shader->array_list);
42*61046927SAndroid Build Coastguard Worker 
43*61046927SAndroid Build Coastguard Worker    return shader;
44*61046927SAndroid Build Coastguard Worker }
45*61046927SAndroid Build Coastguard Worker 
46*61046927SAndroid Build Coastguard Worker void
ir3_destroy(struct ir3 * shader)47*61046927SAndroid Build Coastguard Worker ir3_destroy(struct ir3 *shader)
48*61046927SAndroid Build Coastguard Worker {
49*61046927SAndroid Build Coastguard Worker    ralloc_free(shader);
50*61046927SAndroid Build Coastguard Worker }
51*61046927SAndroid Build Coastguard Worker 
52*61046927SAndroid Build Coastguard Worker static bool
is_shared_consts(struct ir3_compiler * compiler,const struct ir3_const_state * const_state,struct ir3_register * reg)53*61046927SAndroid Build Coastguard Worker is_shared_consts(struct ir3_compiler *compiler,
54*61046927SAndroid Build Coastguard Worker                  const struct ir3_const_state *const_state,
55*61046927SAndroid Build Coastguard Worker                  struct ir3_register *reg)
56*61046927SAndroid Build Coastguard Worker {
57*61046927SAndroid Build Coastguard Worker    if (const_state->push_consts_type == IR3_PUSH_CONSTS_SHARED &&
58*61046927SAndroid Build Coastguard Worker        reg->flags & IR3_REG_CONST) {
59*61046927SAndroid Build Coastguard Worker       uint32_t min_const_reg = regid(compiler->shared_consts_base_offset, 0);
60*61046927SAndroid Build Coastguard Worker       uint32_t max_const_reg =
61*61046927SAndroid Build Coastguard Worker          regid(compiler->shared_consts_base_offset +
62*61046927SAndroid Build Coastguard Worker                compiler->shared_consts_size, 0);
63*61046927SAndroid Build Coastguard Worker       return reg->num >= min_const_reg && min_const_reg < max_const_reg;
64*61046927SAndroid Build Coastguard Worker    }
65*61046927SAndroid Build Coastguard Worker 
66*61046927SAndroid Build Coastguard Worker    return false;
67*61046927SAndroid Build Coastguard Worker }
68*61046927SAndroid Build Coastguard Worker 
69*61046927SAndroid Build Coastguard Worker static void
collect_reg_info(struct ir3_instruction * instr,struct ir3_register * reg,struct ir3_info * info)70*61046927SAndroid Build Coastguard Worker collect_reg_info(struct ir3_instruction *instr, struct ir3_register *reg,
71*61046927SAndroid Build Coastguard Worker                  struct ir3_info *info)
72*61046927SAndroid Build Coastguard Worker {
73*61046927SAndroid Build Coastguard Worker    struct ir3_shader_variant *v = info->data;
74*61046927SAndroid Build Coastguard Worker 
75*61046927SAndroid Build Coastguard Worker    if (reg->flags & IR3_REG_IMMED) {
76*61046927SAndroid Build Coastguard Worker       /* nothing to do */
77*61046927SAndroid Build Coastguard Worker       return;
78*61046927SAndroid Build Coastguard Worker    }
79*61046927SAndroid Build Coastguard Worker 
80*61046927SAndroid Build Coastguard Worker    /* Shared consts don't need to be included into constlen. */
81*61046927SAndroid Build Coastguard Worker    if (is_shared_consts(v->compiler, ir3_const_state(v), reg))
82*61046927SAndroid Build Coastguard Worker       return;
83*61046927SAndroid Build Coastguard Worker 
84*61046927SAndroid Build Coastguard Worker    unsigned components;
85*61046927SAndroid Build Coastguard Worker    int16_t max;
86*61046927SAndroid Build Coastguard Worker 
87*61046927SAndroid Build Coastguard Worker    if (reg->flags & IR3_REG_RELATIV) {
88*61046927SAndroid Build Coastguard Worker       components = reg->size;
89*61046927SAndroid Build Coastguard Worker       max = (reg->array.base + components - 1);
90*61046927SAndroid Build Coastguard Worker    } else {
91*61046927SAndroid Build Coastguard Worker       components = util_last_bit(reg->wrmask);
92*61046927SAndroid Build Coastguard Worker       max = (reg->num + components - 1);
93*61046927SAndroid Build Coastguard Worker    }
94*61046927SAndroid Build Coastguard Worker 
95*61046927SAndroid Build Coastguard Worker    if (reg->flags & IR3_REG_CONST) {
96*61046927SAndroid Build Coastguard Worker       info->max_const = MAX2(info->max_const, max >> 2);
97*61046927SAndroid Build Coastguard Worker    } else if (max < regid(48, 0)) {
98*61046927SAndroid Build Coastguard Worker       if (reg->flags & IR3_REG_HALF) {
99*61046927SAndroid Build Coastguard Worker          if (v->mergedregs) {
100*61046927SAndroid Build Coastguard Worker             /* starting w/ a6xx, half regs conflict with full regs: */
101*61046927SAndroid Build Coastguard Worker             info->max_reg = MAX2(info->max_reg, max >> 3);
102*61046927SAndroid Build Coastguard Worker          } else {
103*61046927SAndroid Build Coastguard Worker             info->max_half_reg = MAX2(info->max_half_reg, max >> 2);
104*61046927SAndroid Build Coastguard Worker          }
105*61046927SAndroid Build Coastguard Worker       } else {
106*61046927SAndroid Build Coastguard Worker          info->max_reg = MAX2(info->max_reg, max >> 2);
107*61046927SAndroid Build Coastguard Worker       }
108*61046927SAndroid Build Coastguard Worker    }
109*61046927SAndroid Build Coastguard Worker }
110*61046927SAndroid Build Coastguard Worker 
111*61046927SAndroid Build Coastguard Worker bool
ir3_should_double_threadsize(struct ir3_shader_variant * v,unsigned regs_count)112*61046927SAndroid Build Coastguard Worker ir3_should_double_threadsize(struct ir3_shader_variant *v, unsigned regs_count)
113*61046927SAndroid Build Coastguard Worker {
114*61046927SAndroid Build Coastguard Worker    const struct ir3_compiler *compiler = v->compiler;
115*61046927SAndroid Build Coastguard Worker 
116*61046927SAndroid Build Coastguard Worker    /* If the user forced a particular wavesize respect that. */
117*61046927SAndroid Build Coastguard Worker    if (v->shader_options.real_wavesize == IR3_SINGLE_ONLY)
118*61046927SAndroid Build Coastguard Worker       return false;
119*61046927SAndroid Build Coastguard Worker    if (v->shader_options.real_wavesize == IR3_DOUBLE_ONLY)
120*61046927SAndroid Build Coastguard Worker       return true;
121*61046927SAndroid Build Coastguard Worker 
122*61046927SAndroid Build Coastguard Worker    /* We can't support more than compiler->branchstack_size diverging threads
123*61046927SAndroid Build Coastguard Worker     * in a wave. Thus, doubling the threadsize is only possible if we don't
124*61046927SAndroid Build Coastguard Worker     * exceed the branchstack size limit.
125*61046927SAndroid Build Coastguard Worker     */
126*61046927SAndroid Build Coastguard Worker    if (MIN2(v->branchstack, compiler->threadsize_base * 2) >
127*61046927SAndroid Build Coastguard Worker        compiler->branchstack_size) {
128*61046927SAndroid Build Coastguard Worker       return false;
129*61046927SAndroid Build Coastguard Worker    }
130*61046927SAndroid Build Coastguard Worker 
131*61046927SAndroid Build Coastguard Worker    switch (v->type) {
132*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_KERNEL:
133*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_COMPUTE: {
134*61046927SAndroid Build Coastguard Worker       unsigned threads_per_wg =
135*61046927SAndroid Build Coastguard Worker          v->local_size[0] * v->local_size[1] * v->local_size[2];
136*61046927SAndroid Build Coastguard Worker 
137*61046927SAndroid Build Coastguard Worker       /* For a5xx, if the workgroup size is greater than the maximum number
138*61046927SAndroid Build Coastguard Worker        * of threads per core with 32 threads per wave (512) then we have to
139*61046927SAndroid Build Coastguard Worker        * use the doubled threadsize because otherwise the workgroup wouldn't
140*61046927SAndroid Build Coastguard Worker        * fit. For smaller workgroup sizes, we follow the blob and use the
141*61046927SAndroid Build Coastguard Worker        * smaller threadsize.
142*61046927SAndroid Build Coastguard Worker        */
143*61046927SAndroid Build Coastguard Worker       if (compiler->gen < 6) {
144*61046927SAndroid Build Coastguard Worker          return v->local_size_variable ||
145*61046927SAndroid Build Coastguard Worker                 threads_per_wg >
146*61046927SAndroid Build Coastguard Worker                    compiler->threadsize_base * compiler->max_waves;
147*61046927SAndroid Build Coastguard Worker       }
148*61046927SAndroid Build Coastguard Worker 
149*61046927SAndroid Build Coastguard Worker       /* On a6xx, we prefer the larger threadsize unless the workgroup is
150*61046927SAndroid Build Coastguard Worker        * small enough that it would be useless. Note that because
151*61046927SAndroid Build Coastguard Worker        * threadsize_base is bumped to 64, we don't have to worry about the
152*61046927SAndroid Build Coastguard Worker        * workgroup fitting, unlike the a5xx case.
153*61046927SAndroid Build Coastguard Worker        */
154*61046927SAndroid Build Coastguard Worker       if (!v->local_size_variable) {
155*61046927SAndroid Build Coastguard Worker          if (threads_per_wg <= compiler->threadsize_base)
156*61046927SAndroid Build Coastguard Worker             return false;
157*61046927SAndroid Build Coastguard Worker       }
158*61046927SAndroid Build Coastguard Worker    }
159*61046927SAndroid Build Coastguard Worker       FALLTHROUGH;
160*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_FRAGMENT: {
161*61046927SAndroid Build Coastguard Worker       /* Check that doubling the threadsize wouldn't exceed the regfile size */
162*61046927SAndroid Build Coastguard Worker       return regs_count * 2 <= compiler->reg_size_vec4;
163*61046927SAndroid Build Coastguard Worker    }
164*61046927SAndroid Build Coastguard Worker 
165*61046927SAndroid Build Coastguard Worker    default:
166*61046927SAndroid Build Coastguard Worker       /* On a6xx+, it's impossible to use a doubled wavesize in the geometry
167*61046927SAndroid Build Coastguard Worker        * stages - the bit doesn't exist. The blob never used it for the VS
168*61046927SAndroid Build Coastguard Worker        * on earlier gen's anyway.
169*61046927SAndroid Build Coastguard Worker        */
170*61046927SAndroid Build Coastguard Worker       return false;
171*61046927SAndroid Build Coastguard Worker    }
172*61046927SAndroid Build Coastguard Worker }
173*61046927SAndroid Build Coastguard Worker 
174*61046927SAndroid Build Coastguard Worker /* Get the maximum number of waves that could be used even if this shader
175*61046927SAndroid Build Coastguard Worker  * didn't use any registers.
176*61046927SAndroid Build Coastguard Worker  */
177*61046927SAndroid Build Coastguard Worker unsigned
ir3_get_reg_independent_max_waves(struct ir3_shader_variant * v,bool double_threadsize)178*61046927SAndroid Build Coastguard Worker ir3_get_reg_independent_max_waves(struct ir3_shader_variant *v,
179*61046927SAndroid Build Coastguard Worker                                   bool double_threadsize)
180*61046927SAndroid Build Coastguard Worker {
181*61046927SAndroid Build Coastguard Worker    const struct ir3_compiler *compiler = v->compiler;
182*61046927SAndroid Build Coastguard Worker    unsigned max_waves = compiler->max_waves;
183*61046927SAndroid Build Coastguard Worker 
184*61046927SAndroid Build Coastguard Worker    /* Compute the limit based on branchstack */
185*61046927SAndroid Build Coastguard Worker    if (v->branchstack > 0) {
186*61046927SAndroid Build Coastguard Worker       unsigned branchstack_max_waves = compiler->branchstack_size /
187*61046927SAndroid Build Coastguard Worker                                        v->branchstack *
188*61046927SAndroid Build Coastguard Worker                                        compiler->wave_granularity;
189*61046927SAndroid Build Coastguard Worker       max_waves = MIN2(max_waves, branchstack_max_waves);
190*61046927SAndroid Build Coastguard Worker    }
191*61046927SAndroid Build Coastguard Worker 
192*61046927SAndroid Build Coastguard Worker    /* If this is a compute shader, compute the limit based on shared size */
193*61046927SAndroid Build Coastguard Worker    if ((v->type == MESA_SHADER_COMPUTE) ||
194*61046927SAndroid Build Coastguard Worker        (v->type == MESA_SHADER_KERNEL)) {
195*61046927SAndroid Build Coastguard Worker       unsigned threads_per_wg =
196*61046927SAndroid Build Coastguard Worker          v->local_size[0] * v->local_size[1] * v->local_size[2];
197*61046927SAndroid Build Coastguard Worker       unsigned waves_per_wg =
198*61046927SAndroid Build Coastguard Worker          DIV_ROUND_UP(threads_per_wg, compiler->threadsize_base *
199*61046927SAndroid Build Coastguard Worker                                          (double_threadsize ? 2 : 1) *
200*61046927SAndroid Build Coastguard Worker                                          compiler->wave_granularity);
201*61046927SAndroid Build Coastguard Worker 
202*61046927SAndroid Build Coastguard Worker       /* Shared is allocated in chunks of 1k */
203*61046927SAndroid Build Coastguard Worker       unsigned shared_per_wg = ALIGN_POT(v->shared_size, 1024);
204*61046927SAndroid Build Coastguard Worker       if (shared_per_wg > 0 && !v->local_size_variable) {
205*61046927SAndroid Build Coastguard Worker          unsigned wgs_per_core = compiler->local_mem_size / shared_per_wg;
206*61046927SAndroid Build Coastguard Worker 
207*61046927SAndroid Build Coastguard Worker          max_waves = MIN2(max_waves, waves_per_wg * wgs_per_core *
208*61046927SAndroid Build Coastguard Worker                                         compiler->wave_granularity);
209*61046927SAndroid Build Coastguard Worker       }
210*61046927SAndroid Build Coastguard Worker 
211*61046927SAndroid Build Coastguard Worker       /* If we have a compute shader that has a big workgroup, a barrier, and
212*61046927SAndroid Build Coastguard Worker        * a branchstack which limits max_waves - this may result in a situation
213*61046927SAndroid Build Coastguard Worker        * when we cannot run concurrently all waves of the workgroup, which
214*61046927SAndroid Build Coastguard Worker        * would lead to a hang.
215*61046927SAndroid Build Coastguard Worker        *
216*61046927SAndroid Build Coastguard Worker        * TODO: Could we spill branchstack or is there other way around?
217*61046927SAndroid Build Coastguard Worker        * Blob just explodes in such case.
218*61046927SAndroid Build Coastguard Worker        */
219*61046927SAndroid Build Coastguard Worker       if (v->has_barrier && (max_waves < waves_per_wg)) {
220*61046927SAndroid Build Coastguard Worker          mesa_loge(
221*61046927SAndroid Build Coastguard Worker             "Compute shader (%s) which has workgroup barrier cannot be used "
222*61046927SAndroid Build Coastguard Worker             "because it's impossible to have enough concurrent waves.",
223*61046927SAndroid Build Coastguard Worker             v->name);
224*61046927SAndroid Build Coastguard Worker          exit(1);
225*61046927SAndroid Build Coastguard Worker       }
226*61046927SAndroid Build Coastguard Worker    }
227*61046927SAndroid Build Coastguard Worker 
228*61046927SAndroid Build Coastguard Worker    return max_waves;
229*61046927SAndroid Build Coastguard Worker }
230*61046927SAndroid Build Coastguard Worker 
231*61046927SAndroid Build Coastguard Worker /* Get the maximum number of waves that could be launched limited by reg size.
232*61046927SAndroid Build Coastguard Worker  */
233*61046927SAndroid Build Coastguard Worker unsigned
ir3_get_reg_dependent_max_waves(const struct ir3_compiler * compiler,unsigned reg_count,bool double_threadsize)234*61046927SAndroid Build Coastguard Worker ir3_get_reg_dependent_max_waves(const struct ir3_compiler *compiler,
235*61046927SAndroid Build Coastguard Worker                                 unsigned reg_count, bool double_threadsize)
236*61046927SAndroid Build Coastguard Worker {
237*61046927SAndroid Build Coastguard Worker    return reg_count ? (compiler->reg_size_vec4 /
238*61046927SAndroid Build Coastguard Worker                        (reg_count * (double_threadsize ? 2 : 1)) *
239*61046927SAndroid Build Coastguard Worker                        compiler->wave_granularity)
240*61046927SAndroid Build Coastguard Worker                     : compiler->max_waves;
241*61046927SAndroid Build Coastguard Worker }
242*61046927SAndroid Build Coastguard Worker 
243*61046927SAndroid Build Coastguard Worker void
ir3_collect_info(struct ir3_shader_variant * v)244*61046927SAndroid Build Coastguard Worker ir3_collect_info(struct ir3_shader_variant *v)
245*61046927SAndroid Build Coastguard Worker {
246*61046927SAndroid Build Coastguard Worker    struct ir3_info *info = &v->info;
247*61046927SAndroid Build Coastguard Worker    struct ir3 *shader = v->ir;
248*61046927SAndroid Build Coastguard Worker    const struct ir3_compiler *compiler = v->compiler;
249*61046927SAndroid Build Coastguard Worker 
250*61046927SAndroid Build Coastguard Worker    memset(info, 0, sizeof(*info));
251*61046927SAndroid Build Coastguard Worker    info->data = v;
252*61046927SAndroid Build Coastguard Worker    info->max_reg = -1;
253*61046927SAndroid Build Coastguard Worker    info->max_half_reg = -1;
254*61046927SAndroid Build Coastguard Worker    info->max_const = -1;
255*61046927SAndroid Build Coastguard Worker    info->multi_dword_ldp_stp = false;
256*61046927SAndroid Build Coastguard Worker 
257*61046927SAndroid Build Coastguard Worker    uint32_t instr_count = 0;
258*61046927SAndroid Build Coastguard Worker    foreach_block (block, &shader->block_list) {
259*61046927SAndroid Build Coastguard Worker       foreach_instr (instr, &block->instr_list) {
260*61046927SAndroid Build Coastguard Worker          instr_count++;
261*61046927SAndroid Build Coastguard Worker       }
262*61046927SAndroid Build Coastguard Worker    }
263*61046927SAndroid Build Coastguard Worker 
264*61046927SAndroid Build Coastguard Worker    v->instrlen = DIV_ROUND_UP(instr_count, compiler->instr_align);
265*61046927SAndroid Build Coastguard Worker 
266*61046927SAndroid Build Coastguard Worker    /* Pad out with NOPs to instrlen, including at least 4 so that cffdump
267*61046927SAndroid Build Coastguard Worker     * doesn't try to decode the following data as instructions (such as the
268*61046927SAndroid Build Coastguard Worker     * next stage's shader in turnip)
269*61046927SAndroid Build Coastguard Worker     */
270*61046927SAndroid Build Coastguard Worker    info->size = MAX2(v->instrlen * compiler->instr_align, instr_count + 4) * 8;
271*61046927SAndroid Build Coastguard Worker    info->sizedwords = info->size / 4;
272*61046927SAndroid Build Coastguard Worker 
273*61046927SAndroid Build Coastguard Worker    info->early_preamble = v->early_preamble;
274*61046927SAndroid Build Coastguard Worker 
275*61046927SAndroid Build Coastguard Worker    bool in_preamble = false;
276*61046927SAndroid Build Coastguard Worker    bool has_eq = false;
277*61046927SAndroid Build Coastguard Worker 
278*61046927SAndroid Build Coastguard Worker    foreach_block (block, &shader->block_list) {
279*61046927SAndroid Build Coastguard Worker       int sfu_delay = 0, mem_delay = 0;
280*61046927SAndroid Build Coastguard Worker 
281*61046927SAndroid Build Coastguard Worker       foreach_instr (instr, &block->instr_list) {
282*61046927SAndroid Build Coastguard Worker 
283*61046927SAndroid Build Coastguard Worker          foreach_src (reg, instr) {
284*61046927SAndroid Build Coastguard Worker             collect_reg_info(instr, reg, info);
285*61046927SAndroid Build Coastguard Worker          }
286*61046927SAndroid Build Coastguard Worker 
287*61046927SAndroid Build Coastguard Worker          foreach_dst (reg, instr) {
288*61046927SAndroid Build Coastguard Worker             if (is_dest_gpr(reg)) {
289*61046927SAndroid Build Coastguard Worker                collect_reg_info(instr, reg, info);
290*61046927SAndroid Build Coastguard Worker             }
291*61046927SAndroid Build Coastguard Worker          }
292*61046927SAndroid Build Coastguard Worker 
293*61046927SAndroid Build Coastguard Worker          if ((instr->opc == OPC_STP || instr->opc == OPC_LDP)) {
294*61046927SAndroid Build Coastguard Worker             unsigned components = instr->srcs[2]->uim_val;
295*61046927SAndroid Build Coastguard Worker 
296*61046927SAndroid Build Coastguard Worker             /* This covers any multi-component access that could straddle
297*61046927SAndroid Build Coastguard Worker              * across multiple double-words.
298*61046927SAndroid Build Coastguard Worker              */
299*61046927SAndroid Build Coastguard Worker             if (components > 1)
300*61046927SAndroid Build Coastguard Worker                info->multi_dword_ldp_stp = true;
301*61046927SAndroid Build Coastguard Worker 
302*61046927SAndroid Build Coastguard Worker             if (instr->opc == OPC_STP)
303*61046927SAndroid Build Coastguard Worker                info->stp_count += components;
304*61046927SAndroid Build Coastguard Worker             else
305*61046927SAndroid Build Coastguard Worker                info->ldp_count += components;
306*61046927SAndroid Build Coastguard Worker          }
307*61046927SAndroid Build Coastguard Worker 
308*61046927SAndroid Build Coastguard Worker          if ((instr->opc == OPC_BARY_F || instr->opc == OPC_FLAT_B) &&
309*61046927SAndroid Build Coastguard Worker              (instr->dsts[0]->flags & IR3_REG_EI))
310*61046927SAndroid Build Coastguard Worker             info->last_baryf = info->instrs_count;
311*61046927SAndroid Build Coastguard Worker 
312*61046927SAndroid Build Coastguard Worker          if ((instr->opc == OPC_NOP) && (instr->flags & IR3_INSTR_EQ)) {
313*61046927SAndroid Build Coastguard Worker             info->last_helper = info->instrs_count;
314*61046927SAndroid Build Coastguard Worker             has_eq = true;
315*61046927SAndroid Build Coastguard Worker          }
316*61046927SAndroid Build Coastguard Worker 
317*61046927SAndroid Build Coastguard Worker          if (v->type == MESA_SHADER_FRAGMENT && v->need_pixlod &&
318*61046927SAndroid Build Coastguard Worker              instr->opc == OPC_END && !v->prefetch_end_of_quad && !has_eq)
319*61046927SAndroid Build Coastguard Worker             info->last_helper = info->instrs_count;
320*61046927SAndroid Build Coastguard Worker 
321*61046927SAndroid Build Coastguard Worker          if (instr->opc == OPC_SHPS)
322*61046927SAndroid Build Coastguard Worker             in_preamble = true;
323*61046927SAndroid Build Coastguard Worker 
324*61046927SAndroid Build Coastguard Worker          /* Don't count instructions in the preamble for instruction-count type
325*61046927SAndroid Build Coastguard Worker           * stats, because their effect should be much smaller.
326*61046927SAndroid Build Coastguard Worker           * TODO: we should probably have separate stats for preamble
327*61046927SAndroid Build Coastguard Worker           * instructions, but that would blow up the amount of stats...
328*61046927SAndroid Build Coastguard Worker           */
329*61046927SAndroid Build Coastguard Worker          if (!in_preamble) {
330*61046927SAndroid Build Coastguard Worker             unsigned instrs_count = 1 + instr->repeat + instr->nop;
331*61046927SAndroid Build Coastguard Worker             unsigned nops_count = instr->nop;
332*61046927SAndroid Build Coastguard Worker 
333*61046927SAndroid Build Coastguard Worker             if (instr->opc == OPC_NOP) {
334*61046927SAndroid Build Coastguard Worker                nops_count = 1 + instr->repeat;
335*61046927SAndroid Build Coastguard Worker                info->instrs_per_cat[0] += nops_count;
336*61046927SAndroid Build Coastguard Worker             } else if (!is_meta(instr)) {
337*61046927SAndroid Build Coastguard Worker                info->instrs_per_cat[opc_cat(instr->opc)] += 1 + instr->repeat;
338*61046927SAndroid Build Coastguard Worker                info->instrs_per_cat[0] += nops_count;
339*61046927SAndroid Build Coastguard Worker             }
340*61046927SAndroid Build Coastguard Worker 
341*61046927SAndroid Build Coastguard Worker             if (instr->opc == OPC_MOV) {
342*61046927SAndroid Build Coastguard Worker                if (instr->cat1.src_type == instr->cat1.dst_type) {
343*61046927SAndroid Build Coastguard Worker                   info->mov_count += 1 + instr->repeat;
344*61046927SAndroid Build Coastguard Worker                } else {
345*61046927SAndroid Build Coastguard Worker                   info->cov_count += 1 + instr->repeat;
346*61046927SAndroid Build Coastguard Worker                }
347*61046927SAndroid Build Coastguard Worker             }
348*61046927SAndroid Build Coastguard Worker 
349*61046927SAndroid Build Coastguard Worker             info->instrs_count += instrs_count;
350*61046927SAndroid Build Coastguard Worker             info->nops_count += nops_count;
351*61046927SAndroid Build Coastguard Worker 
352*61046927SAndroid Build Coastguard Worker             if (instr->flags & IR3_INSTR_SS) {
353*61046927SAndroid Build Coastguard Worker                info->ss++;
354*61046927SAndroid Build Coastguard Worker                info->sstall += sfu_delay;
355*61046927SAndroid Build Coastguard Worker                sfu_delay = 0;
356*61046927SAndroid Build Coastguard Worker             }
357*61046927SAndroid Build Coastguard Worker 
358*61046927SAndroid Build Coastguard Worker             if (instr->flags & IR3_INSTR_SY) {
359*61046927SAndroid Build Coastguard Worker                info->sy++;
360*61046927SAndroid Build Coastguard Worker                info->systall += mem_delay;
361*61046927SAndroid Build Coastguard Worker                mem_delay = 0;
362*61046927SAndroid Build Coastguard Worker             }
363*61046927SAndroid Build Coastguard Worker 
364*61046927SAndroid Build Coastguard Worker             if (is_ss_producer(instr)) {
365*61046927SAndroid Build Coastguard Worker                sfu_delay = soft_ss_delay(instr);
366*61046927SAndroid Build Coastguard Worker             } else {
367*61046927SAndroid Build Coastguard Worker                int n = MIN2(sfu_delay, 1 + instr->repeat + instr->nop);
368*61046927SAndroid Build Coastguard Worker                sfu_delay -= n;
369*61046927SAndroid Build Coastguard Worker             }
370*61046927SAndroid Build Coastguard Worker 
371*61046927SAndroid Build Coastguard Worker             if (is_sy_producer(instr)) {
372*61046927SAndroid Build Coastguard Worker                mem_delay = soft_sy_delay(instr, shader);
373*61046927SAndroid Build Coastguard Worker             } else {
374*61046927SAndroid Build Coastguard Worker                int n = MIN2(mem_delay, 1 + instr->repeat + instr->nop);
375*61046927SAndroid Build Coastguard Worker                mem_delay -= n;
376*61046927SAndroid Build Coastguard Worker             }
377*61046927SAndroid Build Coastguard Worker          }
378*61046927SAndroid Build Coastguard Worker 
379*61046927SAndroid Build Coastguard Worker          if (instr->opc == OPC_SHPE)
380*61046927SAndroid Build Coastguard Worker             in_preamble = false;
381*61046927SAndroid Build Coastguard Worker       }
382*61046927SAndroid Build Coastguard Worker    }
383*61046927SAndroid Build Coastguard Worker 
384*61046927SAndroid Build Coastguard Worker    /* for vertex shader, the inputs are loaded into registers before the shader
385*61046927SAndroid Build Coastguard Worker     * is executed, so max_regs from the shader instructions might not properly
386*61046927SAndroid Build Coastguard Worker     * reflect the # of registers actually used, especially in case passthrough
387*61046927SAndroid Build Coastguard Worker     * varyings.
388*61046927SAndroid Build Coastguard Worker     *
389*61046927SAndroid Build Coastguard Worker     * Likewise, for fragment shader, we can have some regs which are passed
390*61046927SAndroid Build Coastguard Worker     * input values but never touched by the resulting shader (ie. as result
391*61046927SAndroid Build Coastguard Worker     * of dead code elimination or simply because we don't know how to turn
392*61046927SAndroid Build Coastguard Worker     * the reg off.
393*61046927SAndroid Build Coastguard Worker     */
394*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < v->inputs_count; i++) {
395*61046927SAndroid Build Coastguard Worker       /* skip frag inputs fetch via bary.f since their reg's are
396*61046927SAndroid Build Coastguard Worker        * not written by gpu before shader starts (and in fact the
397*61046927SAndroid Build Coastguard Worker        * regid's might not even be valid)
398*61046927SAndroid Build Coastguard Worker        */
399*61046927SAndroid Build Coastguard Worker       if (v->inputs[i].bary)
400*61046927SAndroid Build Coastguard Worker          continue;
401*61046927SAndroid Build Coastguard Worker 
402*61046927SAndroid Build Coastguard Worker       /* ignore high regs that are global to all threads in a warp
403*61046927SAndroid Build Coastguard Worker        * (they exist by default) (a5xx+)
404*61046927SAndroid Build Coastguard Worker        */
405*61046927SAndroid Build Coastguard Worker       if (v->inputs[i].regid >= regid(48, 0))
406*61046927SAndroid Build Coastguard Worker          continue;
407*61046927SAndroid Build Coastguard Worker 
408*61046927SAndroid Build Coastguard Worker       if (v->inputs[i].compmask) {
409*61046927SAndroid Build Coastguard Worker          unsigned n = util_last_bit(v->inputs[i].compmask) - 1;
410*61046927SAndroid Build Coastguard Worker          int32_t regid = v->inputs[i].regid + n;
411*61046927SAndroid Build Coastguard Worker          if (v->inputs[i].half) {
412*61046927SAndroid Build Coastguard Worker             if (!v->mergedregs) {
413*61046927SAndroid Build Coastguard Worker                v->info.max_half_reg = MAX2(v->info.max_half_reg, regid >> 2);
414*61046927SAndroid Build Coastguard Worker             } else {
415*61046927SAndroid Build Coastguard Worker                v->info.max_reg = MAX2(v->info.max_reg, regid >> 3);
416*61046927SAndroid Build Coastguard Worker             }
417*61046927SAndroid Build Coastguard Worker          } else {
418*61046927SAndroid Build Coastguard Worker             v->info.max_reg = MAX2(v->info.max_reg, regid >> 2);
419*61046927SAndroid Build Coastguard Worker          }
420*61046927SAndroid Build Coastguard Worker       }
421*61046927SAndroid Build Coastguard Worker    }
422*61046927SAndroid Build Coastguard Worker 
423*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < v->num_sampler_prefetch; i++) {
424*61046927SAndroid Build Coastguard Worker       unsigned n = util_last_bit(v->sampler_prefetch[i].wrmask) - 1;
425*61046927SAndroid Build Coastguard Worker       int32_t regid = v->sampler_prefetch[i].dst + n;
426*61046927SAndroid Build Coastguard Worker       if (v->sampler_prefetch[i].half_precision) {
427*61046927SAndroid Build Coastguard Worker          if (!v->mergedregs) {
428*61046927SAndroid Build Coastguard Worker             v->info.max_half_reg = MAX2(v->info.max_half_reg, regid >> 2);
429*61046927SAndroid Build Coastguard Worker          } else {
430*61046927SAndroid Build Coastguard Worker             v->info.max_reg = MAX2(v->info.max_reg, regid >> 3);
431*61046927SAndroid Build Coastguard Worker          }
432*61046927SAndroid Build Coastguard Worker       } else {
433*61046927SAndroid Build Coastguard Worker          v->info.max_reg = MAX2(v->info.max_reg, regid >> 2);
434*61046927SAndroid Build Coastguard Worker       }
435*61046927SAndroid Build Coastguard Worker    }
436*61046927SAndroid Build Coastguard Worker 
437*61046927SAndroid Build Coastguard Worker    /* TODO: for a5xx and below, is there a separate regfile for
438*61046927SAndroid Build Coastguard Worker     * half-registers?
439*61046927SAndroid Build Coastguard Worker     */
440*61046927SAndroid Build Coastguard Worker    unsigned regs_count =
441*61046927SAndroid Build Coastguard Worker       info->max_reg + 1 +
442*61046927SAndroid Build Coastguard Worker       (compiler->gen >= 6 ? ((info->max_half_reg + 2) / 2) : 0);
443*61046927SAndroid Build Coastguard Worker 
444*61046927SAndroid Build Coastguard Worker    info->double_threadsize = ir3_should_double_threadsize(v, regs_count);
445*61046927SAndroid Build Coastguard Worker 
446*61046927SAndroid Build Coastguard Worker    /* TODO this is different for earlier gens, but earlier gens don't use this */
447*61046927SAndroid Build Coastguard Worker    info->subgroup_size = v->info.double_threadsize ? 128 : 64;
448*61046927SAndroid Build Coastguard Worker 
449*61046927SAndroid Build Coastguard Worker    unsigned reg_independent_max_waves =
450*61046927SAndroid Build Coastguard Worker       ir3_get_reg_independent_max_waves(v, info->double_threadsize);
451*61046927SAndroid Build Coastguard Worker    unsigned reg_dependent_max_waves = ir3_get_reg_dependent_max_waves(
452*61046927SAndroid Build Coastguard Worker       compiler, regs_count, info->double_threadsize);
453*61046927SAndroid Build Coastguard Worker    info->max_waves = MIN2(reg_independent_max_waves, reg_dependent_max_waves);
454*61046927SAndroid Build Coastguard Worker    assert(info->max_waves <= v->compiler->max_waves);
455*61046927SAndroid Build Coastguard Worker }
456*61046927SAndroid Build Coastguard Worker 
457*61046927SAndroid Build Coastguard Worker static struct ir3_register *
reg_create(struct ir3 * shader,int num,int flags)458*61046927SAndroid Build Coastguard Worker reg_create(struct ir3 *shader, int num, int flags)
459*61046927SAndroid Build Coastguard Worker {
460*61046927SAndroid Build Coastguard Worker    struct ir3_register *reg = ir3_alloc(shader, sizeof(struct ir3_register));
461*61046927SAndroid Build Coastguard Worker    reg->wrmask = 1;
462*61046927SAndroid Build Coastguard Worker    reg->flags = flags;
463*61046927SAndroid Build Coastguard Worker    reg->num = num;
464*61046927SAndroid Build Coastguard Worker    return reg;
465*61046927SAndroid Build Coastguard Worker }
466*61046927SAndroid Build Coastguard Worker 
467*61046927SAndroid Build Coastguard Worker static void
insert_instr(struct ir3_cursor cursor,struct ir3_instruction * instr)468*61046927SAndroid Build Coastguard Worker insert_instr(struct ir3_cursor cursor, struct ir3_instruction *instr)
469*61046927SAndroid Build Coastguard Worker {
470*61046927SAndroid Build Coastguard Worker    struct ir3 *shader = instr->block->shader;
471*61046927SAndroid Build Coastguard Worker 
472*61046927SAndroid Build Coastguard Worker    instr->serialno = ++shader->instr_count;
473*61046927SAndroid Build Coastguard Worker 
474*61046927SAndroid Build Coastguard Worker    switch (cursor.option) {
475*61046927SAndroid Build Coastguard Worker    case IR3_CURSOR_BEFORE_BLOCK:
476*61046927SAndroid Build Coastguard Worker       list_add(&instr->node, &cursor.block->instr_list);
477*61046927SAndroid Build Coastguard Worker       break;
478*61046927SAndroid Build Coastguard Worker    case IR3_CURSOR_AFTER_BLOCK:
479*61046927SAndroid Build Coastguard Worker       list_addtail(&instr->node, &cursor.block->instr_list);
480*61046927SAndroid Build Coastguard Worker       break;
481*61046927SAndroid Build Coastguard Worker    case IR3_CURSOR_BEFORE_INSTR:
482*61046927SAndroid Build Coastguard Worker       list_addtail(&instr->node, &cursor.instr->node);
483*61046927SAndroid Build Coastguard Worker       break;
484*61046927SAndroid Build Coastguard Worker    case IR3_CURSOR_AFTER_INSTR:
485*61046927SAndroid Build Coastguard Worker       list_add(&instr->node, &cursor.instr->node);
486*61046927SAndroid Build Coastguard Worker       break;
487*61046927SAndroid Build Coastguard Worker    }
488*61046927SAndroid Build Coastguard Worker 
489*61046927SAndroid Build Coastguard Worker    if (is_input(instr))
490*61046927SAndroid Build Coastguard Worker       array_insert(shader, shader->baryfs, instr);
491*61046927SAndroid Build Coastguard Worker }
492*61046927SAndroid Build Coastguard Worker 
493*61046927SAndroid Build Coastguard Worker struct ir3_block *
ir3_block_create(struct ir3 * shader)494*61046927SAndroid Build Coastguard Worker ir3_block_create(struct ir3 *shader)
495*61046927SAndroid Build Coastguard Worker {
496*61046927SAndroid Build Coastguard Worker    struct ir3_block *block = ir3_alloc(shader, sizeof(*block));
497*61046927SAndroid Build Coastguard Worker #if MESA_DEBUG
498*61046927SAndroid Build Coastguard Worker    block->serialno = ++shader->block_count;
499*61046927SAndroid Build Coastguard Worker #endif
500*61046927SAndroid Build Coastguard Worker    block->shader = shader;
501*61046927SAndroid Build Coastguard Worker    list_inithead(&block->node);
502*61046927SAndroid Build Coastguard Worker    list_inithead(&block->instr_list);
503*61046927SAndroid Build Coastguard Worker    return block;
504*61046927SAndroid Build Coastguard Worker }
505*61046927SAndroid Build Coastguard Worker 
506*61046927SAndroid Build Coastguard Worker static struct ir3_instruction *
block_get_last_instruction(struct ir3_block * block)507*61046927SAndroid Build Coastguard Worker block_get_last_instruction(struct ir3_block *block)
508*61046927SAndroid Build Coastguard Worker {
509*61046927SAndroid Build Coastguard Worker    if (list_is_empty(&block->instr_list))
510*61046927SAndroid Build Coastguard Worker       return NULL;
511*61046927SAndroid Build Coastguard Worker    return list_last_entry(&block->instr_list, struct ir3_instruction, node);
512*61046927SAndroid Build Coastguard Worker }
513*61046927SAndroid Build Coastguard Worker 
514*61046927SAndroid Build Coastguard Worker struct ir3_instruction *
ir3_block_get_terminator(struct ir3_block * block)515*61046927SAndroid Build Coastguard Worker ir3_block_get_terminator(struct ir3_block *block)
516*61046927SAndroid Build Coastguard Worker {
517*61046927SAndroid Build Coastguard Worker    struct ir3_instruction *last = block_get_last_instruction(block);
518*61046927SAndroid Build Coastguard Worker 
519*61046927SAndroid Build Coastguard Worker    if (last && is_terminator(last))
520*61046927SAndroid Build Coastguard Worker       return last;
521*61046927SAndroid Build Coastguard Worker 
522*61046927SAndroid Build Coastguard Worker    return NULL;
523*61046927SAndroid Build Coastguard Worker }
524*61046927SAndroid Build Coastguard Worker 
525*61046927SAndroid Build Coastguard Worker struct ir3_instruction *
ir3_block_take_terminator(struct ir3_block * block)526*61046927SAndroid Build Coastguard Worker ir3_block_take_terminator(struct ir3_block *block)
527*61046927SAndroid Build Coastguard Worker {
528*61046927SAndroid Build Coastguard Worker    struct ir3_instruction *terminator = ir3_block_get_terminator(block);
529*61046927SAndroid Build Coastguard Worker 
530*61046927SAndroid Build Coastguard Worker    if (terminator)
531*61046927SAndroid Build Coastguard Worker       list_delinit(&terminator->node);
532*61046927SAndroid Build Coastguard Worker 
533*61046927SAndroid Build Coastguard Worker    return terminator;
534*61046927SAndroid Build Coastguard Worker }
535*61046927SAndroid Build Coastguard Worker 
536*61046927SAndroid Build Coastguard Worker struct ir3_instruction *
ir3_block_get_last_non_terminator(struct ir3_block * block)537*61046927SAndroid Build Coastguard Worker ir3_block_get_last_non_terminator(struct ir3_block *block)
538*61046927SAndroid Build Coastguard Worker {
539*61046927SAndroid Build Coastguard Worker    struct ir3_instruction *last = block_get_last_instruction(block);
540*61046927SAndroid Build Coastguard Worker 
541*61046927SAndroid Build Coastguard Worker    if (!last)
542*61046927SAndroid Build Coastguard Worker       return NULL;
543*61046927SAndroid Build Coastguard Worker 
544*61046927SAndroid Build Coastguard Worker    if (!is_terminator(last))
545*61046927SAndroid Build Coastguard Worker       return last;
546*61046927SAndroid Build Coastguard Worker 
547*61046927SAndroid Build Coastguard Worker    if (last->node.prev != &block->instr_list)
548*61046927SAndroid Build Coastguard Worker       return list_entry(last->node.prev, struct ir3_instruction, node);
549*61046927SAndroid Build Coastguard Worker 
550*61046927SAndroid Build Coastguard Worker    return NULL;
551*61046927SAndroid Build Coastguard Worker }
552*61046927SAndroid Build Coastguard Worker 
553*61046927SAndroid Build Coastguard Worker struct ir3_instruction *
ir3_block_get_last_phi(struct ir3_block * block)554*61046927SAndroid Build Coastguard Worker ir3_block_get_last_phi(struct ir3_block *block)
555*61046927SAndroid Build Coastguard Worker {
556*61046927SAndroid Build Coastguard Worker    struct ir3_instruction *last_phi = NULL;
557*61046927SAndroid Build Coastguard Worker 
558*61046927SAndroid Build Coastguard Worker    foreach_instr (instr, &block->instr_list) {
559*61046927SAndroid Build Coastguard Worker       if (instr->opc != OPC_META_PHI)
560*61046927SAndroid Build Coastguard Worker          break;
561*61046927SAndroid Build Coastguard Worker 
562*61046927SAndroid Build Coastguard Worker       last_phi = instr;
563*61046927SAndroid Build Coastguard Worker    }
564*61046927SAndroid Build Coastguard Worker 
565*61046927SAndroid Build Coastguard Worker    return last_phi;
566*61046927SAndroid Build Coastguard Worker }
567*61046927SAndroid Build Coastguard Worker 
568*61046927SAndroid Build Coastguard Worker void
ir3_block_add_predecessor(struct ir3_block * block,struct ir3_block * pred)569*61046927SAndroid Build Coastguard Worker ir3_block_add_predecessor(struct ir3_block *block, struct ir3_block *pred)
570*61046927SAndroid Build Coastguard Worker {
571*61046927SAndroid Build Coastguard Worker    array_insert(block, block->predecessors, pred);
572*61046927SAndroid Build Coastguard Worker }
573*61046927SAndroid Build Coastguard Worker 
574*61046927SAndroid Build Coastguard Worker void
ir3_block_link_physical(struct ir3_block * pred,struct ir3_block * succ)575*61046927SAndroid Build Coastguard Worker ir3_block_link_physical(struct ir3_block *pred,
576*61046927SAndroid Build Coastguard Worker                         struct ir3_block *succ)
577*61046927SAndroid Build Coastguard Worker {
578*61046927SAndroid Build Coastguard Worker    array_insert(pred, pred->physical_successors, succ);
579*61046927SAndroid Build Coastguard Worker    array_insert(succ, succ->physical_predecessors, pred);
580*61046927SAndroid Build Coastguard Worker }
581*61046927SAndroid Build Coastguard Worker 
582*61046927SAndroid Build Coastguard Worker void
ir3_block_remove_predecessor(struct ir3_block * block,struct ir3_block * pred)583*61046927SAndroid Build Coastguard Worker ir3_block_remove_predecessor(struct ir3_block *block, struct ir3_block *pred)
584*61046927SAndroid Build Coastguard Worker {
585*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < block->predecessors_count; i++) {
586*61046927SAndroid Build Coastguard Worker       if (block->predecessors[i] == pred) {
587*61046927SAndroid Build Coastguard Worker          if (i < block->predecessors_count - 1) {
588*61046927SAndroid Build Coastguard Worker             block->predecessors[i] =
589*61046927SAndroid Build Coastguard Worker                block->predecessors[block->predecessors_count - 1];
590*61046927SAndroid Build Coastguard Worker          }
591*61046927SAndroid Build Coastguard Worker 
592*61046927SAndroid Build Coastguard Worker          block->predecessors_count--;
593*61046927SAndroid Build Coastguard Worker          return;
594*61046927SAndroid Build Coastguard Worker       }
595*61046927SAndroid Build Coastguard Worker    }
596*61046927SAndroid Build Coastguard Worker }
597*61046927SAndroid Build Coastguard Worker 
598*61046927SAndroid Build Coastguard Worker unsigned
ir3_block_get_pred_index(struct ir3_block * block,struct ir3_block * pred)599*61046927SAndroid Build Coastguard Worker ir3_block_get_pred_index(struct ir3_block *block, struct ir3_block *pred)
600*61046927SAndroid Build Coastguard Worker {
601*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < block->predecessors_count; i++) {
602*61046927SAndroid Build Coastguard Worker       if (block->predecessors[i] == pred) {
603*61046927SAndroid Build Coastguard Worker          return i;
604*61046927SAndroid Build Coastguard Worker       }
605*61046927SAndroid Build Coastguard Worker    }
606*61046927SAndroid Build Coastguard Worker 
607*61046927SAndroid Build Coastguard Worker    unreachable("ir3_block_get_pred_index() invalid predecessor");
608*61046927SAndroid Build Coastguard Worker }
609*61046927SAndroid Build Coastguard Worker 
610*61046927SAndroid Build Coastguard Worker static struct ir3_instruction *
instr_create(struct ir3_block * block,opc_t opc,int ndst,int nsrc)611*61046927SAndroid Build Coastguard Worker instr_create(struct ir3_block *block, opc_t opc, int ndst, int nsrc)
612*61046927SAndroid Build Coastguard Worker {
613*61046927SAndroid Build Coastguard Worker    /* Add extra sources for array destinations and the address reg */
614*61046927SAndroid Build Coastguard Worker    if (1 <= opc_cat(opc))
615*61046927SAndroid Build Coastguard Worker       nsrc += 2;
616*61046927SAndroid Build Coastguard Worker    struct ir3_instruction *instr;
617*61046927SAndroid Build Coastguard Worker    unsigned sz = sizeof(*instr) + (ndst * sizeof(instr->dsts[0])) +
618*61046927SAndroid Build Coastguard Worker                  (nsrc * sizeof(instr->srcs[0]));
619*61046927SAndroid Build Coastguard Worker    char *ptr = ir3_alloc(block->shader, sz);
620*61046927SAndroid Build Coastguard Worker 
621*61046927SAndroid Build Coastguard Worker    instr = (struct ir3_instruction *)ptr;
622*61046927SAndroid Build Coastguard Worker    ptr += sizeof(*instr);
623*61046927SAndroid Build Coastguard Worker    instr->dsts = (struct ir3_register **)ptr;
624*61046927SAndroid Build Coastguard Worker    instr->srcs = instr->dsts + ndst;
625*61046927SAndroid Build Coastguard Worker 
626*61046927SAndroid Build Coastguard Worker #if MESA_DEBUG
627*61046927SAndroid Build Coastguard Worker    instr->dsts_max = ndst;
628*61046927SAndroid Build Coastguard Worker    instr->srcs_max = nsrc;
629*61046927SAndroid Build Coastguard Worker #endif
630*61046927SAndroid Build Coastguard Worker 
631*61046927SAndroid Build Coastguard Worker    list_inithead(&instr->rpt_node);
632*61046927SAndroid Build Coastguard Worker    return instr;
633*61046927SAndroid Build Coastguard Worker }
634*61046927SAndroid Build Coastguard Worker 
635*61046927SAndroid Build Coastguard Worker static void
add_to_address_users(struct ir3_instruction * instr)636*61046927SAndroid Build Coastguard Worker add_to_address_users(struct ir3_instruction *instr)
637*61046927SAndroid Build Coastguard Worker {
638*61046927SAndroid Build Coastguard Worker    assert(instr->address != NULL);
639*61046927SAndroid Build Coastguard Worker 
640*61046927SAndroid Build Coastguard Worker    struct ir3 *ir = instr->block->shader;
641*61046927SAndroid Build Coastguard Worker    struct ir3_register *addr_reg = instr->address->def;
642*61046927SAndroid Build Coastguard Worker    assert(reg_num(addr_reg) == REG_A0);
643*61046927SAndroid Build Coastguard Worker    unsigned comp = reg_comp(addr_reg);
644*61046927SAndroid Build Coastguard Worker    if (comp == 0) {
645*61046927SAndroid Build Coastguard Worker       array_insert(ir, ir->a0_users, instr);
646*61046927SAndroid Build Coastguard Worker    } else {
647*61046927SAndroid Build Coastguard Worker       assert(comp == 1);
648*61046927SAndroid Build Coastguard Worker       array_insert(ir, ir->a1_users, instr);
649*61046927SAndroid Build Coastguard Worker    }
650*61046927SAndroid Build Coastguard Worker }
651*61046927SAndroid Build Coastguard Worker 
652*61046927SAndroid Build Coastguard Worker static struct ir3_block *
get_block(struct ir3_cursor cursor)653*61046927SAndroid Build Coastguard Worker get_block(struct ir3_cursor cursor)
654*61046927SAndroid Build Coastguard Worker {
655*61046927SAndroid Build Coastguard Worker    switch (cursor.option) {
656*61046927SAndroid Build Coastguard Worker    case IR3_CURSOR_BEFORE_BLOCK:
657*61046927SAndroid Build Coastguard Worker    case IR3_CURSOR_AFTER_BLOCK:
658*61046927SAndroid Build Coastguard Worker       return cursor.block;
659*61046927SAndroid Build Coastguard Worker    case IR3_CURSOR_BEFORE_INSTR:
660*61046927SAndroid Build Coastguard Worker    case IR3_CURSOR_AFTER_INSTR:
661*61046927SAndroid Build Coastguard Worker       return cursor.instr->block;
662*61046927SAndroid Build Coastguard Worker    }
663*61046927SAndroid Build Coastguard Worker 
664*61046927SAndroid Build Coastguard Worker    unreachable("illegal cursor option");
665*61046927SAndroid Build Coastguard Worker }
666*61046927SAndroid Build Coastguard Worker 
667*61046927SAndroid Build Coastguard Worker struct ir3_instruction *
ir3_instr_create_at(struct ir3_cursor cursor,opc_t opc,int ndst,int nsrc)668*61046927SAndroid Build Coastguard Worker ir3_instr_create_at(struct ir3_cursor cursor, opc_t opc, int ndst, int nsrc)
669*61046927SAndroid Build Coastguard Worker {
670*61046927SAndroid Build Coastguard Worker    struct ir3_block *block = get_block(cursor);
671*61046927SAndroid Build Coastguard Worker    struct ir3_instruction *instr = instr_create(block, opc, ndst, nsrc);
672*61046927SAndroid Build Coastguard Worker    instr->block = block;
673*61046927SAndroid Build Coastguard Worker    instr->opc = opc;
674*61046927SAndroid Build Coastguard Worker    insert_instr(cursor, instr);
675*61046927SAndroid Build Coastguard Worker    return instr;
676*61046927SAndroid Build Coastguard Worker }
677*61046927SAndroid Build Coastguard Worker 
678*61046927SAndroid Build Coastguard Worker struct ir3_instruction *
ir3_build_instr(struct ir3_builder * builder,opc_t opc,int ndst,int nsrc)679*61046927SAndroid Build Coastguard Worker ir3_build_instr(struct ir3_builder *builder, opc_t opc, int ndst, int nsrc)
680*61046927SAndroid Build Coastguard Worker {
681*61046927SAndroid Build Coastguard Worker    struct ir3_instruction *instr =
682*61046927SAndroid Build Coastguard Worker       ir3_instr_create_at(builder->cursor, opc, ndst, nsrc);
683*61046927SAndroid Build Coastguard Worker    builder->cursor = ir3_after_instr(instr);
684*61046927SAndroid Build Coastguard Worker    return instr;
685*61046927SAndroid Build Coastguard Worker }
686*61046927SAndroid Build Coastguard Worker 
687*61046927SAndroid Build Coastguard Worker struct ir3_instruction *
ir3_instr_create(struct ir3_block * block,opc_t opc,int ndst,int nsrc)688*61046927SAndroid Build Coastguard Worker ir3_instr_create(struct ir3_block *block, opc_t opc, int ndst, int nsrc)
689*61046927SAndroid Build Coastguard Worker {
690*61046927SAndroid Build Coastguard Worker    return ir3_instr_create_at(ir3_before_terminator(block), opc, ndst, nsrc);
691*61046927SAndroid Build Coastguard Worker }
692*61046927SAndroid Build Coastguard Worker 
693*61046927SAndroid Build Coastguard Worker struct ir3_instruction *
ir3_instr_create_at_end(struct ir3_block * block,opc_t opc,int ndst,int nsrc)694*61046927SAndroid Build Coastguard Worker ir3_instr_create_at_end(struct ir3_block *block, opc_t opc, int ndst, int nsrc)
695*61046927SAndroid Build Coastguard Worker {
696*61046927SAndroid Build Coastguard Worker    return ir3_instr_create_at(ir3_after_block(block), opc, ndst, nsrc);
697*61046927SAndroid Build Coastguard Worker }
698*61046927SAndroid Build Coastguard Worker 
699*61046927SAndroid Build Coastguard Worker struct ir3_instruction *
ir3_instr_clone(struct ir3_instruction * instr)700*61046927SAndroid Build Coastguard Worker ir3_instr_clone(struct ir3_instruction *instr)
701*61046927SAndroid Build Coastguard Worker {
702*61046927SAndroid Build Coastguard Worker    struct ir3_instruction *new_instr = instr_create(
703*61046927SAndroid Build Coastguard Worker       instr->block, instr->opc, instr->dsts_count, instr->srcs_count);
704*61046927SAndroid Build Coastguard Worker    struct ir3_register **dsts, **srcs;
705*61046927SAndroid Build Coastguard Worker 
706*61046927SAndroid Build Coastguard Worker    dsts = new_instr->dsts;
707*61046927SAndroid Build Coastguard Worker    srcs = new_instr->srcs;
708*61046927SAndroid Build Coastguard Worker    *new_instr = *instr;
709*61046927SAndroid Build Coastguard Worker    new_instr->dsts = dsts;
710*61046927SAndroid Build Coastguard Worker    new_instr->srcs = srcs;
711*61046927SAndroid Build Coastguard Worker    list_inithead(&new_instr->rpt_node);
712*61046927SAndroid Build Coastguard Worker 
713*61046927SAndroid Build Coastguard Worker    insert_instr(ir3_before_terminator(instr->block), new_instr);
714*61046927SAndroid Build Coastguard Worker 
715*61046927SAndroid Build Coastguard Worker    /* clone registers: */
716*61046927SAndroid Build Coastguard Worker    new_instr->dsts_count = 0;
717*61046927SAndroid Build Coastguard Worker    new_instr->srcs_count = 0;
718*61046927SAndroid Build Coastguard Worker    foreach_dst (reg, instr) {
719*61046927SAndroid Build Coastguard Worker       struct ir3_register *new_reg =
720*61046927SAndroid Build Coastguard Worker          ir3_dst_create(new_instr, reg->num, reg->flags);
721*61046927SAndroid Build Coastguard Worker       *new_reg = *reg;
722*61046927SAndroid Build Coastguard Worker       if (new_reg->instr)
723*61046927SAndroid Build Coastguard Worker          new_reg->instr = new_instr;
724*61046927SAndroid Build Coastguard Worker    }
725*61046927SAndroid Build Coastguard Worker    foreach_src (reg, instr) {
726*61046927SAndroid Build Coastguard Worker       struct ir3_register *new_reg =
727*61046927SAndroid Build Coastguard Worker          ir3_src_create(new_instr, reg->num, reg->flags);
728*61046927SAndroid Build Coastguard Worker       *new_reg = *reg;
729*61046927SAndroid Build Coastguard Worker    }
730*61046927SAndroid Build Coastguard Worker 
731*61046927SAndroid Build Coastguard Worker    if (instr->address) {
732*61046927SAndroid Build Coastguard Worker       assert(instr->srcs_count > 0);
733*61046927SAndroid Build Coastguard Worker       new_instr->address = new_instr->srcs[instr->srcs_count - 1];
734*61046927SAndroid Build Coastguard Worker       add_to_address_users(new_instr);
735*61046927SAndroid Build Coastguard Worker    }
736*61046927SAndroid Build Coastguard Worker 
737*61046927SAndroid Build Coastguard Worker    return new_instr;
738*61046927SAndroid Build Coastguard Worker }
739*61046927SAndroid Build Coastguard Worker 
740*61046927SAndroid Build Coastguard Worker /* Add a false dependency to instruction, to ensure it is scheduled first: */
741*61046927SAndroid Build Coastguard Worker void
ir3_instr_add_dep(struct ir3_instruction * instr,struct ir3_instruction * dep)742*61046927SAndroid Build Coastguard Worker ir3_instr_add_dep(struct ir3_instruction *instr, struct ir3_instruction *dep)
743*61046927SAndroid Build Coastguard Worker {
744*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < instr->deps_count; i++) {
745*61046927SAndroid Build Coastguard Worker       if (instr->deps[i] == dep)
746*61046927SAndroid Build Coastguard Worker          return;
747*61046927SAndroid Build Coastguard Worker    }
748*61046927SAndroid Build Coastguard Worker 
749*61046927SAndroid Build Coastguard Worker    array_insert(instr, instr->deps, dep);
750*61046927SAndroid Build Coastguard Worker }
751*61046927SAndroid Build Coastguard Worker 
752*61046927SAndroid Build Coastguard Worker void
ir3_instr_remove(struct ir3_instruction * instr)753*61046927SAndroid Build Coastguard Worker ir3_instr_remove(struct ir3_instruction *instr)
754*61046927SAndroid Build Coastguard Worker {
755*61046927SAndroid Build Coastguard Worker    list_delinit(&instr->node);
756*61046927SAndroid Build Coastguard Worker    list_delinit(&instr->rpt_node);
757*61046927SAndroid Build Coastguard Worker }
758*61046927SAndroid Build Coastguard Worker 
759*61046927SAndroid Build Coastguard Worker void
ir3_instr_create_rpt(struct ir3_instruction ** instrs,unsigned n)760*61046927SAndroid Build Coastguard Worker ir3_instr_create_rpt(struct ir3_instruction **instrs, unsigned n)
761*61046927SAndroid Build Coastguard Worker {
762*61046927SAndroid Build Coastguard Worker    assert(n > 0 && !ir3_instr_is_rpt(instrs[0]));
763*61046927SAndroid Build Coastguard Worker 
764*61046927SAndroid Build Coastguard Worker    for (unsigned i = 1; i < n; ++i) {
765*61046927SAndroid Build Coastguard Worker       assert(!ir3_instr_is_rpt(instrs[i]));
766*61046927SAndroid Build Coastguard Worker       assert(instrs[i]->serialno > instrs[i - 1]->serialno);
767*61046927SAndroid Build Coastguard Worker 
768*61046927SAndroid Build Coastguard Worker       list_addtail(&instrs[i]->rpt_node, &instrs[0]->rpt_node);
769*61046927SAndroid Build Coastguard Worker    }
770*61046927SAndroid Build Coastguard Worker }
771*61046927SAndroid Build Coastguard Worker 
772*61046927SAndroid Build Coastguard Worker bool
ir3_instr_is_rpt(const struct ir3_instruction * instr)773*61046927SAndroid Build Coastguard Worker ir3_instr_is_rpt(const struct ir3_instruction *instr)
774*61046927SAndroid Build Coastguard Worker {
775*61046927SAndroid Build Coastguard Worker    return !list_is_empty(&instr->rpt_node);
776*61046927SAndroid Build Coastguard Worker }
777*61046927SAndroid Build Coastguard Worker 
778*61046927SAndroid Build Coastguard Worker bool
ir3_instr_is_first_rpt(const struct ir3_instruction * instr)779*61046927SAndroid Build Coastguard Worker ir3_instr_is_first_rpt(const struct ir3_instruction *instr)
780*61046927SAndroid Build Coastguard Worker {
781*61046927SAndroid Build Coastguard Worker    if (!ir3_instr_is_rpt(instr))
782*61046927SAndroid Build Coastguard Worker       return false;
783*61046927SAndroid Build Coastguard Worker 
784*61046927SAndroid Build Coastguard Worker    struct ir3_instruction *prev_rpt =
785*61046927SAndroid Build Coastguard Worker       list_entry(instr->rpt_node.prev, struct ir3_instruction, rpt_node);
786*61046927SAndroid Build Coastguard Worker    return prev_rpt->serialno > instr->serialno;
787*61046927SAndroid Build Coastguard Worker }
788*61046927SAndroid Build Coastguard Worker 
789*61046927SAndroid Build Coastguard Worker struct ir3_instruction *
ir3_instr_prev_rpt(const struct ir3_instruction * instr)790*61046927SAndroid Build Coastguard Worker ir3_instr_prev_rpt(const struct ir3_instruction *instr)
791*61046927SAndroid Build Coastguard Worker {
792*61046927SAndroid Build Coastguard Worker    assert(ir3_instr_is_rpt(instr));
793*61046927SAndroid Build Coastguard Worker 
794*61046927SAndroid Build Coastguard Worker    if (ir3_instr_is_first_rpt(instr))
795*61046927SAndroid Build Coastguard Worker       return NULL;
796*61046927SAndroid Build Coastguard Worker    return list_entry(instr->rpt_node.prev, struct ir3_instruction, rpt_node);
797*61046927SAndroid Build Coastguard Worker }
798*61046927SAndroid Build Coastguard Worker 
799*61046927SAndroid Build Coastguard Worker struct ir3_instruction *
ir3_instr_first_rpt(struct ir3_instruction * instr)800*61046927SAndroid Build Coastguard Worker ir3_instr_first_rpt(struct ir3_instruction *instr)
801*61046927SAndroid Build Coastguard Worker {
802*61046927SAndroid Build Coastguard Worker    assert(ir3_instr_is_rpt(instr));
803*61046927SAndroid Build Coastguard Worker 
804*61046927SAndroid Build Coastguard Worker    while (!ir3_instr_is_first_rpt(instr)) {
805*61046927SAndroid Build Coastguard Worker       instr = ir3_instr_prev_rpt(instr);
806*61046927SAndroid Build Coastguard Worker       assert(instr);
807*61046927SAndroid Build Coastguard Worker    }
808*61046927SAndroid Build Coastguard Worker 
809*61046927SAndroid Build Coastguard Worker    return instr;
810*61046927SAndroid Build Coastguard Worker }
811*61046927SAndroid Build Coastguard Worker 
812*61046927SAndroid Build Coastguard Worker unsigned
ir3_instr_rpt_length(const struct ir3_instruction * instr)813*61046927SAndroid Build Coastguard Worker ir3_instr_rpt_length(const struct ir3_instruction *instr)
814*61046927SAndroid Build Coastguard Worker {
815*61046927SAndroid Build Coastguard Worker    assert(ir3_instr_is_first_rpt(instr));
816*61046927SAndroid Build Coastguard Worker 
817*61046927SAndroid Build Coastguard Worker    return list_length(&instr->rpt_node) + 1;
818*61046927SAndroid Build Coastguard Worker }
819*61046927SAndroid Build Coastguard Worker 
820*61046927SAndroid Build Coastguard Worker struct ir3_register *
ir3_src_create(struct ir3_instruction * instr,int num,int flags)821*61046927SAndroid Build Coastguard Worker ir3_src_create(struct ir3_instruction *instr, int num, int flags)
822*61046927SAndroid Build Coastguard Worker {
823*61046927SAndroid Build Coastguard Worker    struct ir3 *shader = instr->block->shader;
824*61046927SAndroid Build Coastguard Worker #if MESA_DEBUG
825*61046927SAndroid Build Coastguard Worker    assert(instr->srcs_count < instr->srcs_max);
826*61046927SAndroid Build Coastguard Worker #endif
827*61046927SAndroid Build Coastguard Worker    struct ir3_register *reg = reg_create(shader, num, flags);
828*61046927SAndroid Build Coastguard Worker    instr->srcs[instr->srcs_count++] = reg;
829*61046927SAndroid Build Coastguard Worker    return reg;
830*61046927SAndroid Build Coastguard Worker }
831*61046927SAndroid Build Coastguard Worker 
832*61046927SAndroid Build Coastguard Worker struct ir3_register *
ir3_dst_create(struct ir3_instruction * instr,int num,int flags)833*61046927SAndroid Build Coastguard Worker ir3_dst_create(struct ir3_instruction *instr, int num, int flags)
834*61046927SAndroid Build Coastguard Worker {
835*61046927SAndroid Build Coastguard Worker    struct ir3 *shader = instr->block->shader;
836*61046927SAndroid Build Coastguard Worker #if MESA_DEBUG
837*61046927SAndroid Build Coastguard Worker    assert(instr->dsts_count < instr->dsts_max);
838*61046927SAndroid Build Coastguard Worker #endif
839*61046927SAndroid Build Coastguard Worker    struct ir3_register *reg = reg_create(shader, num, flags);
840*61046927SAndroid Build Coastguard Worker    instr->dsts[instr->dsts_count++] = reg;
841*61046927SAndroid Build Coastguard Worker    return reg;
842*61046927SAndroid Build Coastguard Worker }
843*61046927SAndroid Build Coastguard Worker 
844*61046927SAndroid Build Coastguard Worker struct ir3_register *
ir3_reg_clone(struct ir3 * shader,struct ir3_register * reg)845*61046927SAndroid Build Coastguard Worker ir3_reg_clone(struct ir3 *shader, struct ir3_register *reg)
846*61046927SAndroid Build Coastguard Worker {
847*61046927SAndroid Build Coastguard Worker    struct ir3_register *new_reg = reg_create(shader, 0, 0);
848*61046927SAndroid Build Coastguard Worker    *new_reg = *reg;
849*61046927SAndroid Build Coastguard Worker    return new_reg;
850*61046927SAndroid Build Coastguard Worker }
851*61046927SAndroid Build Coastguard Worker 
852*61046927SAndroid Build Coastguard Worker void
ir3_reg_set_last_array(struct ir3_instruction * instr,struct ir3_register * reg,struct ir3_register * last_write)853*61046927SAndroid Build Coastguard Worker ir3_reg_set_last_array(struct ir3_instruction *instr, struct ir3_register *reg,
854*61046927SAndroid Build Coastguard Worker                        struct ir3_register *last_write)
855*61046927SAndroid Build Coastguard Worker {
856*61046927SAndroid Build Coastguard Worker    assert(reg->flags & IR3_REG_ARRAY);
857*61046927SAndroid Build Coastguard Worker    struct ir3_register *new_reg = ir3_src_create(instr, 0, 0);
858*61046927SAndroid Build Coastguard Worker    *new_reg = *reg;
859*61046927SAndroid Build Coastguard Worker    new_reg->def = last_write;
860*61046927SAndroid Build Coastguard Worker    ir3_reg_tie(reg, new_reg);
861*61046927SAndroid Build Coastguard Worker }
862*61046927SAndroid Build Coastguard Worker 
863*61046927SAndroid Build Coastguard Worker void
ir3_instr_set_address(struct ir3_instruction * instr,struct ir3_instruction * addr)864*61046927SAndroid Build Coastguard Worker ir3_instr_set_address(struct ir3_instruction *instr,
865*61046927SAndroid Build Coastguard Worker                       struct ir3_instruction *addr)
866*61046927SAndroid Build Coastguard Worker {
867*61046927SAndroid Build Coastguard Worker    if (!instr->address) {
868*61046927SAndroid Build Coastguard Worker       assert(instr->block == addr->block);
869*61046927SAndroid Build Coastguard Worker 
870*61046927SAndroid Build Coastguard Worker       instr->address =
871*61046927SAndroid Build Coastguard Worker          ir3_src_create(instr, addr->dsts[0]->num, addr->dsts[0]->flags);
872*61046927SAndroid Build Coastguard Worker       instr->address->def = addr->dsts[0];
873*61046927SAndroid Build Coastguard Worker       add_to_address_users(instr);
874*61046927SAndroid Build Coastguard Worker    } else {
875*61046927SAndroid Build Coastguard Worker       assert(instr->address->def->instr == addr);
876*61046927SAndroid Build Coastguard Worker    }
877*61046927SAndroid Build Coastguard Worker }
878*61046927SAndroid Build Coastguard Worker 
879*61046927SAndroid Build Coastguard Worker /* Does this instruction use the scalar ALU?
880*61046927SAndroid Build Coastguard Worker  */
881*61046927SAndroid Build Coastguard Worker bool
is_scalar_alu(struct ir3_instruction * instr,const struct ir3_compiler * compiler)882*61046927SAndroid Build Coastguard Worker is_scalar_alu(struct ir3_instruction *instr,
883*61046927SAndroid Build Coastguard Worker               const struct ir3_compiler *compiler)
884*61046927SAndroid Build Coastguard Worker {
885*61046927SAndroid Build Coastguard Worker    /* MOVMSK seems to always need (ss) even with other scalar ALU instructions
886*61046927SAndroid Build Coastguard Worker     */
887*61046927SAndroid Build Coastguard Worker    return instr->opc != OPC_MOVMSK &&
888*61046927SAndroid Build Coastguard Worker       instr->opc != OPC_SCAN_CLUSTERS_MACRO &&
889*61046927SAndroid Build Coastguard Worker       instr->opc != OPC_SCAN_MACRO &&
890*61046927SAndroid Build Coastguard Worker       is_alu(instr) && (instr->dsts[0]->flags & IR3_REG_SHARED) &&
891*61046927SAndroid Build Coastguard Worker       /* scalar->scalar mov instructions (but NOT cov) were supported before the
892*61046927SAndroid Build Coastguard Worker        * scalar ALU was supported, but they still required (ss) whereas on GPUs
893*61046927SAndroid Build Coastguard Worker        * that have a scalar ALU they are executed on it and do not require (ss).
894*61046927SAndroid Build Coastguard Worker        * We have to be careful to return false for these if scalar ALU isn't
895*61046927SAndroid Build Coastguard Worker        * supported, so that we treat them like vector->scalar mov instructions
896*61046927SAndroid Build Coastguard Worker        * (such as requiring (ss)).
897*61046927SAndroid Build Coastguard Worker        */
898*61046927SAndroid Build Coastguard Worker       compiler->has_scalar_alu &&
899*61046927SAndroid Build Coastguard Worker       /* moves from normal to shared seem to use a separate ALU as before and
900*61046927SAndroid Build Coastguard Worker        * require a (ss) on dependent instructions.
901*61046927SAndroid Build Coastguard Worker        */
902*61046927SAndroid Build Coastguard Worker       ((instr->opc != OPC_MOV && !is_subgroup_cond_mov_macro(instr)) ||
903*61046927SAndroid Build Coastguard Worker        (instr->srcs[0]->flags & (IR3_REG_SHARED | IR3_REG_IMMED | IR3_REG_CONST)));
904*61046927SAndroid Build Coastguard Worker }
905*61046927SAndroid Build Coastguard Worker 
906*61046927SAndroid Build Coastguard Worker void
ir3_block_clear_mark(struct ir3_block * block)907*61046927SAndroid Build Coastguard Worker ir3_block_clear_mark(struct ir3_block *block)
908*61046927SAndroid Build Coastguard Worker {
909*61046927SAndroid Build Coastguard Worker    foreach_instr (instr, &block->instr_list)
910*61046927SAndroid Build Coastguard Worker       instr->flags &= ~IR3_INSTR_MARK;
911*61046927SAndroid Build Coastguard Worker }
912*61046927SAndroid Build Coastguard Worker 
913*61046927SAndroid Build Coastguard Worker void
ir3_clear_mark(struct ir3 * ir)914*61046927SAndroid Build Coastguard Worker ir3_clear_mark(struct ir3 *ir)
915*61046927SAndroid Build Coastguard Worker {
916*61046927SAndroid Build Coastguard Worker    foreach_block (block, &ir->block_list) {
917*61046927SAndroid Build Coastguard Worker       ir3_block_clear_mark(block);
918*61046927SAndroid Build Coastguard Worker    }
919*61046927SAndroid Build Coastguard Worker }
920*61046927SAndroid Build Coastguard Worker 
921*61046927SAndroid Build Coastguard Worker unsigned
ir3_count_instructions(struct ir3 * ir)922*61046927SAndroid Build Coastguard Worker ir3_count_instructions(struct ir3 *ir)
923*61046927SAndroid Build Coastguard Worker {
924*61046927SAndroid Build Coastguard Worker    unsigned cnt = 1;
925*61046927SAndroid Build Coastguard Worker    foreach_block (block, &ir->block_list) {
926*61046927SAndroid Build Coastguard Worker       block->start_ip = cnt;
927*61046927SAndroid Build Coastguard Worker       foreach_instr (instr, &block->instr_list) {
928*61046927SAndroid Build Coastguard Worker          instr->ip = cnt++;
929*61046927SAndroid Build Coastguard Worker       }
930*61046927SAndroid Build Coastguard Worker       block->end_ip = cnt;
931*61046927SAndroid Build Coastguard Worker    }
932*61046927SAndroid Build Coastguard Worker    return cnt;
933*61046927SAndroid Build Coastguard Worker }
934*61046927SAndroid Build Coastguard Worker 
935*61046927SAndroid Build Coastguard Worker unsigned
ir3_count_instructions_sched(struct ir3 * ir)936*61046927SAndroid Build Coastguard Worker ir3_count_instructions_sched(struct ir3 *ir)
937*61046927SAndroid Build Coastguard Worker {
938*61046927SAndroid Build Coastguard Worker    unsigned cnt = 1;
939*61046927SAndroid Build Coastguard Worker    foreach_block (block, &ir->block_list) {
940*61046927SAndroid Build Coastguard Worker       block->start_ip = cnt;
941*61046927SAndroid Build Coastguard Worker       foreach_instr (instr, &block->instr_list) {
942*61046927SAndroid Build Coastguard Worker          if (!is_terminator(instr))
943*61046927SAndroid Build Coastguard Worker             instr->ip = cnt++;
944*61046927SAndroid Build Coastguard Worker       }
945*61046927SAndroid Build Coastguard Worker       block->end_ip = cnt;
946*61046927SAndroid Build Coastguard Worker    }
947*61046927SAndroid Build Coastguard Worker    return cnt;
948*61046927SAndroid Build Coastguard Worker }
949*61046927SAndroid Build Coastguard Worker 
950*61046927SAndroid Build Coastguard Worker /* When counting instructions for RA, we insert extra fake instructions at the
951*61046927SAndroid Build Coastguard Worker  * beginning of each block, where values become live, and at the end where
952*61046927SAndroid Build Coastguard Worker  * values die. This prevents problems where values live-in at the beginning or
953*61046927SAndroid Build Coastguard Worker  * live-out at the end of a block from being treated as if they were
954*61046927SAndroid Build Coastguard Worker  * live-in/live-out at the first/last instruction, which would be incorrect.
955*61046927SAndroid Build Coastguard Worker  * In ir3_legalize these ip's are assumed to be actual ip's of the final
956*61046927SAndroid Build Coastguard Worker  * program, so it would be incorrect to use this everywhere.
957*61046927SAndroid Build Coastguard Worker  */
958*61046927SAndroid Build Coastguard Worker 
959*61046927SAndroid Build Coastguard Worker unsigned
ir3_count_instructions_ra(struct ir3 * ir)960*61046927SAndroid Build Coastguard Worker ir3_count_instructions_ra(struct ir3 *ir)
961*61046927SAndroid Build Coastguard Worker {
962*61046927SAndroid Build Coastguard Worker    unsigned cnt = 1;
963*61046927SAndroid Build Coastguard Worker    foreach_block (block, &ir->block_list) {
964*61046927SAndroid Build Coastguard Worker       block->start_ip = cnt++;
965*61046927SAndroid Build Coastguard Worker       foreach_instr (instr, &block->instr_list) {
966*61046927SAndroid Build Coastguard Worker          instr->ip = cnt++;
967*61046927SAndroid Build Coastguard Worker       }
968*61046927SAndroid Build Coastguard Worker       block->end_ip = cnt++;
969*61046927SAndroid Build Coastguard Worker    }
970*61046927SAndroid Build Coastguard Worker    return cnt;
971*61046927SAndroid Build Coastguard Worker }
972*61046927SAndroid Build Coastguard Worker 
973*61046927SAndroid Build Coastguard Worker struct ir3_array *
ir3_lookup_array(struct ir3 * ir,unsigned id)974*61046927SAndroid Build Coastguard Worker ir3_lookup_array(struct ir3 *ir, unsigned id)
975*61046927SAndroid Build Coastguard Worker {
976*61046927SAndroid Build Coastguard Worker    foreach_array (arr, &ir->array_list)
977*61046927SAndroid Build Coastguard Worker       if (arr->id == id)
978*61046927SAndroid Build Coastguard Worker          return arr;
979*61046927SAndroid Build Coastguard Worker    return NULL;
980*61046927SAndroid Build Coastguard Worker }
981*61046927SAndroid Build Coastguard Worker 
ir3_find_ssa_uses_for(struct ir3 * ir,void * mem_ctx,use_filter_cb filter)982*61046927SAndroid Build Coastguard Worker void ir3_find_ssa_uses_for(struct ir3 *ir, void *mem_ctx, use_filter_cb filter)
983*61046927SAndroid Build Coastguard Worker {
984*61046927SAndroid Build Coastguard Worker    /* We could do this in a single pass if we can assume instructions
985*61046927SAndroid Build Coastguard Worker     * are always sorted.  Which currently might not always be true.
986*61046927SAndroid Build Coastguard Worker     * (In particular after ir3_group pass, but maybe other places.)
987*61046927SAndroid Build Coastguard Worker     */
988*61046927SAndroid Build Coastguard Worker    foreach_block (block, &ir->block_list)
989*61046927SAndroid Build Coastguard Worker       foreach_instr (instr, &block->instr_list)
990*61046927SAndroid Build Coastguard Worker          instr->uses = NULL;
991*61046927SAndroid Build Coastguard Worker 
992*61046927SAndroid Build Coastguard Worker    foreach_block (block, &ir->block_list) {
993*61046927SAndroid Build Coastguard Worker       foreach_instr (instr, &block->instr_list) {
994*61046927SAndroid Build Coastguard Worker          foreach_ssa_src_n (src, n, instr) {
995*61046927SAndroid Build Coastguard Worker             if (!filter(instr, n))
996*61046927SAndroid Build Coastguard Worker                continue;
997*61046927SAndroid Build Coastguard Worker             if (!src->uses)
998*61046927SAndroid Build Coastguard Worker                src->uses = _mesa_pointer_set_create(mem_ctx);
999*61046927SAndroid Build Coastguard Worker             _mesa_set_add(src->uses, instr);
1000*61046927SAndroid Build Coastguard Worker          }
1001*61046927SAndroid Build Coastguard Worker       }
1002*61046927SAndroid Build Coastguard Worker    }
1003*61046927SAndroid Build Coastguard Worker }
1004*61046927SAndroid Build Coastguard Worker 
1005*61046927SAndroid Build Coastguard Worker static bool
no_false_deps(struct ir3_instruction * instr,unsigned src_n)1006*61046927SAndroid Build Coastguard Worker no_false_deps(struct ir3_instruction *instr, unsigned src_n)
1007*61046927SAndroid Build Coastguard Worker {
1008*61046927SAndroid Build Coastguard Worker    return !__is_false_dep(instr, src_n);
1009*61046927SAndroid Build Coastguard Worker }
1010*61046927SAndroid Build Coastguard Worker 
1011*61046927SAndroid Build Coastguard Worker static bool
any_src(struct ir3_instruction * instr,unsigned src_n)1012*61046927SAndroid Build Coastguard Worker any_src(struct ir3_instruction *instr, unsigned src_n)
1013*61046927SAndroid Build Coastguard Worker {
1014*61046927SAndroid Build Coastguard Worker    return true;
1015*61046927SAndroid Build Coastguard Worker }
1016*61046927SAndroid Build Coastguard Worker 
1017*61046927SAndroid Build Coastguard Worker void
ir3_find_ssa_uses(struct ir3 * ir,void * mem_ctx,bool falsedeps)1018*61046927SAndroid Build Coastguard Worker ir3_find_ssa_uses(struct ir3 *ir, void *mem_ctx, bool falsedeps)
1019*61046927SAndroid Build Coastguard Worker {
1020*61046927SAndroid Build Coastguard Worker    if (falsedeps)
1021*61046927SAndroid Build Coastguard Worker       return ir3_find_ssa_uses_for(ir, mem_ctx, any_src);
1022*61046927SAndroid Build Coastguard Worker    return ir3_find_ssa_uses_for(ir, mem_ctx, no_false_deps);
1023*61046927SAndroid Build Coastguard Worker }
1024*61046927SAndroid Build Coastguard Worker 
1025*61046927SAndroid Build Coastguard Worker /**
1026*61046927SAndroid Build Coastguard Worker  * Set the destination type of an instruction, for example if a
1027*61046927SAndroid Build Coastguard Worker  * conversion is folded in, handling the special cases where the
1028*61046927SAndroid Build Coastguard Worker  * instruction's dest type or opcode needs to be fixed up.
1029*61046927SAndroid Build Coastguard Worker  */
1030*61046927SAndroid Build Coastguard Worker void
ir3_set_dst_type(struct ir3_instruction * instr,bool half)1031*61046927SAndroid Build Coastguard Worker ir3_set_dst_type(struct ir3_instruction *instr, bool half)
1032*61046927SAndroid Build Coastguard Worker {
1033*61046927SAndroid Build Coastguard Worker    if (half) {
1034*61046927SAndroid Build Coastguard Worker       instr->dsts[0]->flags |= IR3_REG_HALF;
1035*61046927SAndroid Build Coastguard Worker    } else {
1036*61046927SAndroid Build Coastguard Worker       instr->dsts[0]->flags &= ~IR3_REG_HALF;
1037*61046927SAndroid Build Coastguard Worker    }
1038*61046927SAndroid Build Coastguard Worker 
1039*61046927SAndroid Build Coastguard Worker    switch (opc_cat(instr->opc)) {
1040*61046927SAndroid Build Coastguard Worker    case 1: /* move instructions */
1041*61046927SAndroid Build Coastguard Worker       if (half) {
1042*61046927SAndroid Build Coastguard Worker          instr->cat1.dst_type = half_type(instr->cat1.dst_type);
1043*61046927SAndroid Build Coastguard Worker       } else {
1044*61046927SAndroid Build Coastguard Worker          instr->cat1.dst_type = full_type(instr->cat1.dst_type);
1045*61046927SAndroid Build Coastguard Worker       }
1046*61046927SAndroid Build Coastguard Worker       break;
1047*61046927SAndroid Build Coastguard Worker    case 4:
1048*61046927SAndroid Build Coastguard Worker       if (half) {
1049*61046927SAndroid Build Coastguard Worker          instr->opc = cat4_half_opc(instr->opc);
1050*61046927SAndroid Build Coastguard Worker       } else {
1051*61046927SAndroid Build Coastguard Worker          instr->opc = cat4_full_opc(instr->opc);
1052*61046927SAndroid Build Coastguard Worker       }
1053*61046927SAndroid Build Coastguard Worker       break;
1054*61046927SAndroid Build Coastguard Worker    case 5:
1055*61046927SAndroid Build Coastguard Worker       if (half) {
1056*61046927SAndroid Build Coastguard Worker          instr->cat5.type = half_type(instr->cat5.type);
1057*61046927SAndroid Build Coastguard Worker       } else {
1058*61046927SAndroid Build Coastguard Worker          instr->cat5.type = full_type(instr->cat5.type);
1059*61046927SAndroid Build Coastguard Worker       }
1060*61046927SAndroid Build Coastguard Worker       break;
1061*61046927SAndroid Build Coastguard Worker    }
1062*61046927SAndroid Build Coastguard Worker }
1063*61046927SAndroid Build Coastguard Worker 
1064*61046927SAndroid Build Coastguard Worker /**
1065*61046927SAndroid Build Coastguard Worker  * One-time fixup for instruction src-types.  Other than cov's that
1066*61046927SAndroid Build Coastguard Worker  * are folded, an instruction's src type does not change.
1067*61046927SAndroid Build Coastguard Worker  */
1068*61046927SAndroid Build Coastguard Worker void
ir3_fixup_src_type(struct ir3_instruction * instr)1069*61046927SAndroid Build Coastguard Worker ir3_fixup_src_type(struct ir3_instruction *instr)
1070*61046927SAndroid Build Coastguard Worker {
1071*61046927SAndroid Build Coastguard Worker    if (instr->srcs_count == 0)
1072*61046927SAndroid Build Coastguard Worker       return;
1073*61046927SAndroid Build Coastguard Worker 
1074*61046927SAndroid Build Coastguard Worker    switch (opc_cat(instr->opc)) {
1075*61046927SAndroid Build Coastguard Worker    case 1: /* move instructions */
1076*61046927SAndroid Build Coastguard Worker       if (instr->srcs[0]->flags & IR3_REG_HALF) {
1077*61046927SAndroid Build Coastguard Worker          instr->cat1.src_type = half_type(instr->cat1.src_type);
1078*61046927SAndroid Build Coastguard Worker       } else {
1079*61046927SAndroid Build Coastguard Worker          instr->cat1.src_type = full_type(instr->cat1.src_type);
1080*61046927SAndroid Build Coastguard Worker       }
1081*61046927SAndroid Build Coastguard Worker       break;
1082*61046927SAndroid Build Coastguard Worker    case 3:
1083*61046927SAndroid Build Coastguard Worker       if (instr->srcs[0]->flags & IR3_REG_HALF) {
1084*61046927SAndroid Build Coastguard Worker          instr->opc = cat3_half_opc(instr->opc);
1085*61046927SAndroid Build Coastguard Worker       } else {
1086*61046927SAndroid Build Coastguard Worker          instr->opc = cat3_full_opc(instr->opc);
1087*61046927SAndroid Build Coastguard Worker       }
1088*61046927SAndroid Build Coastguard Worker       break;
1089*61046927SAndroid Build Coastguard Worker    }
1090*61046927SAndroid Build Coastguard Worker }
1091*61046927SAndroid Build Coastguard Worker 
1092*61046927SAndroid Build Coastguard Worker /**
1093*61046927SAndroid Build Coastguard Worker  * Map a floating point immed to FLUT (float lookup table) value,
1094*61046927SAndroid Build Coastguard Worker  * returns negative for immediates that cannot be mapped.
1095*61046927SAndroid Build Coastguard Worker  */
1096*61046927SAndroid Build Coastguard Worker int
ir3_flut(struct ir3_register * src_reg)1097*61046927SAndroid Build Coastguard Worker ir3_flut(struct ir3_register *src_reg)
1098*61046927SAndroid Build Coastguard Worker {
1099*61046927SAndroid Build Coastguard Worker    static const struct {
1100*61046927SAndroid Build Coastguard Worker       uint32_t f32;
1101*61046927SAndroid Build Coastguard Worker       uint16_t f16;
1102*61046927SAndroid Build Coastguard Worker    } flut[] = {
1103*61046927SAndroid Build Coastguard Worker          { .f32 = 0x00000000, .f16 = 0x0000 },    /* 0.0 */
1104*61046927SAndroid Build Coastguard Worker          { .f32 = 0x3f000000, .f16 = 0x3800 },    /* 0.5 */
1105*61046927SAndroid Build Coastguard Worker          { .f32 = 0x3f800000, .f16 = 0x3c00 },    /* 1.0 */
1106*61046927SAndroid Build Coastguard Worker          { .f32 = 0x40000000, .f16 = 0x4000 },    /* 2.0 */
1107*61046927SAndroid Build Coastguard Worker          { .f32 = 0x402df854, .f16 = 0x4170 },    /* e */
1108*61046927SAndroid Build Coastguard Worker          { .f32 = 0x40490fdb, .f16 = 0x4248 },    /* pi */
1109*61046927SAndroid Build Coastguard Worker          { .f32 = 0x3ea2f983, .f16 = 0x3518 },    /* 1/pi */
1110*61046927SAndroid Build Coastguard Worker          { .f32 = 0x3f317218, .f16 = 0x398c },    /* 1/log2(e) */
1111*61046927SAndroid Build Coastguard Worker          { .f32 = 0x3fb8aa3b, .f16 = 0x3dc5 },    /* log2(e) */
1112*61046927SAndroid Build Coastguard Worker          { .f32 = 0x3e9a209b, .f16 = 0x34d1 },    /* 1/log2(10) */
1113*61046927SAndroid Build Coastguard Worker          { .f32 = 0x40549a78, .f16 = 0x42a5 },    /* log2(10) */
1114*61046927SAndroid Build Coastguard Worker          { .f32 = 0x40800000, .f16 = 0x4400 },    /* 4.0 */
1115*61046927SAndroid Build Coastguard Worker    };
1116*61046927SAndroid Build Coastguard Worker 
1117*61046927SAndroid Build Coastguard Worker    if (src_reg->flags & IR3_REG_HALF) {
1118*61046927SAndroid Build Coastguard Worker       /* Note that half-float immeds are already lowered to 16b in nir: */
1119*61046927SAndroid Build Coastguard Worker       uint32_t imm = src_reg->uim_val;
1120*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < ARRAY_SIZE(flut); i++) {
1121*61046927SAndroid Build Coastguard Worker          if (flut[i].f16 == imm) {
1122*61046927SAndroid Build Coastguard Worker             return i;
1123*61046927SAndroid Build Coastguard Worker          }
1124*61046927SAndroid Build Coastguard Worker       }
1125*61046927SAndroid Build Coastguard Worker    } else {
1126*61046927SAndroid Build Coastguard Worker       uint32_t imm = src_reg->uim_val;
1127*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < ARRAY_SIZE(flut); i++) {
1128*61046927SAndroid Build Coastguard Worker          if (flut[i].f32 == imm) {
1129*61046927SAndroid Build Coastguard Worker             return i;
1130*61046927SAndroid Build Coastguard Worker          }
1131*61046927SAndroid Build Coastguard Worker       }
1132*61046927SAndroid Build Coastguard Worker    }
1133*61046927SAndroid Build Coastguard Worker 
1134*61046927SAndroid Build Coastguard Worker    return -1;
1135*61046927SAndroid Build Coastguard Worker }
1136*61046927SAndroid Build Coastguard Worker 
1137*61046927SAndroid Build Coastguard Worker static unsigned
cp_flags(unsigned flags)1138*61046927SAndroid Build Coastguard Worker cp_flags(unsigned flags)
1139*61046927SAndroid Build Coastguard Worker {
1140*61046927SAndroid Build Coastguard Worker    /* only considering these flags (at least for now): */
1141*61046927SAndroid Build Coastguard Worker    flags &= (IR3_REG_CONST | IR3_REG_IMMED | IR3_REG_FNEG | IR3_REG_FABS |
1142*61046927SAndroid Build Coastguard Worker              IR3_REG_SNEG | IR3_REG_SABS | IR3_REG_BNOT | IR3_REG_RELATIV |
1143*61046927SAndroid Build Coastguard Worker              IR3_REG_SHARED);
1144*61046927SAndroid Build Coastguard Worker    return flags;
1145*61046927SAndroid Build Coastguard Worker }
1146*61046927SAndroid Build Coastguard Worker 
1147*61046927SAndroid Build Coastguard Worker bool
ir3_valid_flags(struct ir3_instruction * instr,unsigned n,unsigned flags)1148*61046927SAndroid Build Coastguard Worker ir3_valid_flags(struct ir3_instruction *instr, unsigned n, unsigned flags)
1149*61046927SAndroid Build Coastguard Worker {
1150*61046927SAndroid Build Coastguard Worker    struct ir3_compiler *compiler = instr->block->shader->compiler;
1151*61046927SAndroid Build Coastguard Worker    unsigned valid_flags;
1152*61046927SAndroid Build Coastguard Worker 
1153*61046927SAndroid Build Coastguard Worker    flags = cp_flags(flags);
1154*61046927SAndroid Build Coastguard Worker 
1155*61046927SAndroid Build Coastguard Worker    /* If destination is indirect, then source cannot be.. at least
1156*61046927SAndroid Build Coastguard Worker     * I don't think so..
1157*61046927SAndroid Build Coastguard Worker     */
1158*61046927SAndroid Build Coastguard Worker    if (instr->dsts_count > 0 && (instr->dsts[0]->flags & IR3_REG_RELATIV) &&
1159*61046927SAndroid Build Coastguard Worker        (flags & IR3_REG_RELATIV))
1160*61046927SAndroid Build Coastguard Worker       return false;
1161*61046927SAndroid Build Coastguard Worker 
1162*61046927SAndroid Build Coastguard Worker    if (flags & IR3_REG_RELATIV) {
1163*61046927SAndroid Build Coastguard Worker       /* TODO need to test on earlier gens.. pretty sure the earlier
1164*61046927SAndroid Build Coastguard Worker        * problem was just that we didn't check that the src was from
1165*61046927SAndroid Build Coastguard Worker        * same block (since we can't propagate address register values
1166*61046927SAndroid Build Coastguard Worker        * across blocks currently)
1167*61046927SAndroid Build Coastguard Worker        */
1168*61046927SAndroid Build Coastguard Worker       if (compiler->gen < 6)
1169*61046927SAndroid Build Coastguard Worker          return false;
1170*61046927SAndroid Build Coastguard Worker 
1171*61046927SAndroid Build Coastguard Worker       /* NOTE in the special try_swap_mad_two_srcs() case we can be
1172*61046927SAndroid Build Coastguard Worker        * called on a src that has already had an indirect load folded
1173*61046927SAndroid Build Coastguard Worker        * in, in which case ssa() returns NULL
1174*61046927SAndroid Build Coastguard Worker        */
1175*61046927SAndroid Build Coastguard Worker       if (instr->srcs[n]->flags & IR3_REG_SSA) {
1176*61046927SAndroid Build Coastguard Worker          struct ir3_instruction *src = ssa(instr->srcs[n]);
1177*61046927SAndroid Build Coastguard Worker          if (src->address->def->instr->block != instr->block)
1178*61046927SAndroid Build Coastguard Worker             return false;
1179*61046927SAndroid Build Coastguard Worker       }
1180*61046927SAndroid Build Coastguard Worker    }
1181*61046927SAndroid Build Coastguard Worker 
1182*61046927SAndroid Build Coastguard Worker    if (is_meta(instr)) {
1183*61046927SAndroid Build Coastguard Worker       /* collect and phi nodes support const/immed sources, which will be
1184*61046927SAndroid Build Coastguard Worker        * turned into move instructions, but not anything else.
1185*61046927SAndroid Build Coastguard Worker        */
1186*61046927SAndroid Build Coastguard Worker       if (flags & ~(IR3_REG_IMMED | IR3_REG_CONST | IR3_REG_SHARED))
1187*61046927SAndroid Build Coastguard Worker          return false;
1188*61046927SAndroid Build Coastguard Worker 
1189*61046927SAndroid Build Coastguard Worker       /* Except for immed/const sources, source and dest shared-ness must match.
1190*61046927SAndroid Build Coastguard Worker        */
1191*61046927SAndroid Build Coastguard Worker       if (!(flags & (IR3_REG_IMMED | IR3_REG_CONST)) &&
1192*61046927SAndroid Build Coastguard Worker           (flags & IR3_REG_SHARED) != (instr->dsts[0]->flags & IR3_REG_SHARED))
1193*61046927SAndroid Build Coastguard Worker          return false;
1194*61046927SAndroid Build Coastguard Worker 
1195*61046927SAndroid Build Coastguard Worker       return true;
1196*61046927SAndroid Build Coastguard Worker    }
1197*61046927SAndroid Build Coastguard Worker 
1198*61046927SAndroid Build Coastguard Worker    switch (opc_cat(instr->opc)) {
1199*61046927SAndroid Build Coastguard Worker    case 0: /* end, chmask */
1200*61046927SAndroid Build Coastguard Worker       return flags == 0;
1201*61046927SAndroid Build Coastguard Worker    case 1:
1202*61046927SAndroid Build Coastguard Worker       switch (instr->opc) {
1203*61046927SAndroid Build Coastguard Worker       case OPC_MOVMSK:
1204*61046927SAndroid Build Coastguard Worker       case OPC_SWZ:
1205*61046927SAndroid Build Coastguard Worker       case OPC_SCT:
1206*61046927SAndroid Build Coastguard Worker       case OPC_GAT:
1207*61046927SAndroid Build Coastguard Worker          valid_flags = IR3_REG_SHARED;
1208*61046927SAndroid Build Coastguard Worker          break;
1209*61046927SAndroid Build Coastguard Worker       case OPC_SCAN_MACRO:
1210*61046927SAndroid Build Coastguard Worker          if (n == 0)
1211*61046927SAndroid Build Coastguard Worker             return flags == 0;
1212*61046927SAndroid Build Coastguard Worker          else
1213*61046927SAndroid Build Coastguard Worker             return flags == IR3_REG_SHARED;
1214*61046927SAndroid Build Coastguard Worker          break;
1215*61046927SAndroid Build Coastguard Worker       case OPC_SCAN_CLUSTERS_MACRO:
1216*61046927SAndroid Build Coastguard Worker          if (n == 0)
1217*61046927SAndroid Build Coastguard Worker             return flags == IR3_REG_SHARED;
1218*61046927SAndroid Build Coastguard Worker          else
1219*61046927SAndroid Build Coastguard Worker             return flags == 0;
1220*61046927SAndroid Build Coastguard Worker          break;
1221*61046927SAndroid Build Coastguard Worker       default: {
1222*61046927SAndroid Build Coastguard Worker          valid_flags =
1223*61046927SAndroid Build Coastguard Worker             IR3_REG_IMMED | IR3_REG_CONST | IR3_REG_RELATIV | IR3_REG_SHARED;
1224*61046927SAndroid Build Coastguard Worker 
1225*61046927SAndroid Build Coastguard Worker          /* floating-point conversions when moving from non-shared to shared
1226*61046927SAndroid Build Coastguard Worker           * seem not to work. We only use floating-point types in ir3 for
1227*61046927SAndroid Build Coastguard Worker           * conversions, so don't bother specially handling the case where the
1228*61046927SAndroid Build Coastguard Worker           * types are equal. Same goes for 8-bit sign extension.
1229*61046927SAndroid Build Coastguard Worker           */
1230*61046927SAndroid Build Coastguard Worker          if ((instr->dsts[0]->flags & IR3_REG_SHARED) &&
1231*61046927SAndroid Build Coastguard Worker              !(flags & (IR3_REG_SHARED | IR3_REG_IMMED | IR3_REG_CONST)) &&
1232*61046927SAndroid Build Coastguard Worker              ((full_type(instr->cat1.src_type) == TYPE_F32 ||
1233*61046927SAndroid Build Coastguard Worker                full_type(instr->cat1.dst_type) == TYPE_F32) ||
1234*61046927SAndroid Build Coastguard Worker               (instr->cat1.src_type == TYPE_U8 &&
1235*61046927SAndroid Build Coastguard Worker                full_type(instr->cat1.dst_type) == TYPE_S32)))
1236*61046927SAndroid Build Coastguard Worker             return false;
1237*61046927SAndroid Build Coastguard Worker 
1238*61046927SAndroid Build Coastguard Worker          /* Conversions seem not to work in shared->shared copies before scalar
1239*61046927SAndroid Build Coastguard Worker           * ALU is supported.
1240*61046927SAndroid Build Coastguard Worker           */
1241*61046927SAndroid Build Coastguard Worker          if (!compiler->has_scalar_alu &&
1242*61046927SAndroid Build Coastguard Worker              (flags & IR3_REG_SHARED) &&
1243*61046927SAndroid Build Coastguard Worker              (instr->dsts[0]->flags & IR3_REG_SHARED) &&
1244*61046927SAndroid Build Coastguard Worker              instr->cat1.src_type != instr->cat1.dst_type)
1245*61046927SAndroid Build Coastguard Worker             return false;
1246*61046927SAndroid Build Coastguard Worker       }
1247*61046927SAndroid Build Coastguard Worker       }
1248*61046927SAndroid Build Coastguard Worker       if (flags & ~valid_flags)
1249*61046927SAndroid Build Coastguard Worker          return false;
1250*61046927SAndroid Build Coastguard Worker       break;
1251*61046927SAndroid Build Coastguard Worker    case 2:
1252*61046927SAndroid Build Coastguard Worker       valid_flags = ir3_cat2_absneg(instr->opc) | IR3_REG_CONST |
1253*61046927SAndroid Build Coastguard Worker                     IR3_REG_RELATIV | IR3_REG_IMMED | IR3_REG_SHARED;
1254*61046927SAndroid Build Coastguard Worker 
1255*61046927SAndroid Build Coastguard Worker       if (flags & ~valid_flags)
1256*61046927SAndroid Build Coastguard Worker          return false;
1257*61046927SAndroid Build Coastguard Worker 
1258*61046927SAndroid Build Coastguard Worker       /* Allow an immediate src1 for flat.b, since it's ignored */
1259*61046927SAndroid Build Coastguard Worker       if (instr->opc == OPC_FLAT_B &&
1260*61046927SAndroid Build Coastguard Worker           n == 1 && flags == IR3_REG_IMMED)
1261*61046927SAndroid Build Coastguard Worker          return true;
1262*61046927SAndroid Build Coastguard Worker 
1263*61046927SAndroid Build Coastguard Worker       /* cat2/cat3 scalar ALU instructions must not have regular sources. */
1264*61046927SAndroid Build Coastguard Worker       if (instr->dsts[0]->flags & IR3_REG_SHARED) {
1265*61046927SAndroid Build Coastguard Worker          if (!(flags & (IR3_REG_SHARED | IR3_REG_IMMED | IR3_REG_CONST)))
1266*61046927SAndroid Build Coastguard Worker             return false;
1267*61046927SAndroid Build Coastguard Worker       }
1268*61046927SAndroid Build Coastguard Worker 
1269*61046927SAndroid Build Coastguard Worker       if (flags & (IR3_REG_CONST | IR3_REG_IMMED | IR3_REG_SHARED)) {
1270*61046927SAndroid Build Coastguard Worker          unsigned m = n ^ 1;
1271*61046927SAndroid Build Coastguard Worker          /* cannot deal w/ const or shared in both srcs:
1272*61046927SAndroid Build Coastguard Worker           * (note that some cat2 actually only have a single src)
1273*61046927SAndroid Build Coastguard Worker           */
1274*61046927SAndroid Build Coastguard Worker          if (m < instr->srcs_count) {
1275*61046927SAndroid Build Coastguard Worker             struct ir3_register *reg = instr->srcs[m];
1276*61046927SAndroid Build Coastguard Worker             if (instr->dsts[0]->flags & IR3_REG_SHARED) {
1277*61046927SAndroid Build Coastguard Worker                if ((flags & IR3_REG_CONST) && (reg->flags & IR3_REG_CONST))
1278*61046927SAndroid Build Coastguard Worker                   return false;
1279*61046927SAndroid Build Coastguard Worker             } else {
1280*61046927SAndroid Build Coastguard Worker                if ((flags & (IR3_REG_CONST | IR3_REG_SHARED)) &&
1281*61046927SAndroid Build Coastguard Worker                    (reg->flags & (IR3_REG_CONST | IR3_REG_SHARED)))
1282*61046927SAndroid Build Coastguard Worker                   return false;
1283*61046927SAndroid Build Coastguard Worker             }
1284*61046927SAndroid Build Coastguard Worker             if ((flags & IR3_REG_IMMED) && reg->flags & (IR3_REG_IMMED))
1285*61046927SAndroid Build Coastguard Worker                return false;
1286*61046927SAndroid Build Coastguard Worker          }
1287*61046927SAndroid Build Coastguard Worker       }
1288*61046927SAndroid Build Coastguard Worker       break;
1289*61046927SAndroid Build Coastguard Worker    case 3:
1290*61046927SAndroid Build Coastguard Worker       valid_flags =
1291*61046927SAndroid Build Coastguard Worker          ir3_cat3_absneg(instr->opc) | IR3_REG_RELATIV | IR3_REG_SHARED;
1292*61046927SAndroid Build Coastguard Worker 
1293*61046927SAndroid Build Coastguard Worker       switch (instr->opc) {
1294*61046927SAndroid Build Coastguard Worker       case OPC_SHRM:
1295*61046927SAndroid Build Coastguard Worker       case OPC_SHLM:
1296*61046927SAndroid Build Coastguard Worker       case OPC_SHRG:
1297*61046927SAndroid Build Coastguard Worker       case OPC_SHLG:
1298*61046927SAndroid Build Coastguard Worker       case OPC_ANDG: {
1299*61046927SAndroid Build Coastguard Worker          valid_flags |= IR3_REG_IMMED;
1300*61046927SAndroid Build Coastguard Worker          /* Can be RELATIV+CONST but not CONST: */
1301*61046927SAndroid Build Coastguard Worker          if (flags & IR3_REG_RELATIV)
1302*61046927SAndroid Build Coastguard Worker             valid_flags |= IR3_REG_CONST;
1303*61046927SAndroid Build Coastguard Worker          break;
1304*61046927SAndroid Build Coastguard Worker       }
1305*61046927SAndroid Build Coastguard Worker       case OPC_WMM:
1306*61046927SAndroid Build Coastguard Worker       case OPC_WMM_ACCU: {
1307*61046927SAndroid Build Coastguard Worker          valid_flags = IR3_REG_SHARED;
1308*61046927SAndroid Build Coastguard Worker          if (n == 2)
1309*61046927SAndroid Build Coastguard Worker             valid_flags = IR3_REG_CONST;
1310*61046927SAndroid Build Coastguard Worker          break;
1311*61046927SAndroid Build Coastguard Worker       }
1312*61046927SAndroid Build Coastguard Worker       case OPC_DP2ACC:
1313*61046927SAndroid Build Coastguard Worker       case OPC_DP4ACC:
1314*61046927SAndroid Build Coastguard Worker          break;
1315*61046927SAndroid Build Coastguard Worker       default:
1316*61046927SAndroid Build Coastguard Worker          valid_flags |= IR3_REG_CONST;
1317*61046927SAndroid Build Coastguard Worker       }
1318*61046927SAndroid Build Coastguard Worker 
1319*61046927SAndroid Build Coastguard Worker       if (flags & ~valid_flags)
1320*61046927SAndroid Build Coastguard Worker          return false;
1321*61046927SAndroid Build Coastguard Worker 
1322*61046927SAndroid Build Coastguard Worker       if (flags & (IR3_REG_CONST | IR3_REG_RELATIV) ||
1323*61046927SAndroid Build Coastguard Worker           (!(instr->dsts[0]->flags & IR3_REG_SHARED) &&
1324*61046927SAndroid Build Coastguard Worker            (flags & IR3_REG_SHARED))) {
1325*61046927SAndroid Build Coastguard Worker          /* cannot deal w/ const/shared/relativ in 2nd src: */
1326*61046927SAndroid Build Coastguard Worker          if (n == 1)
1327*61046927SAndroid Build Coastguard Worker             return false;
1328*61046927SAndroid Build Coastguard Worker       }
1329*61046927SAndroid Build Coastguard Worker 
1330*61046927SAndroid Build Coastguard Worker       if (instr->dsts[0]->flags & IR3_REG_SHARED) {
1331*61046927SAndroid Build Coastguard Worker          if (!(flags & (IR3_REG_SHARED | IR3_REG_IMMED | IR3_REG_CONST)))
1332*61046927SAndroid Build Coastguard Worker             return false;
1333*61046927SAndroid Build Coastguard Worker       }
1334*61046927SAndroid Build Coastguard Worker 
1335*61046927SAndroid Build Coastguard Worker       break;
1336*61046927SAndroid Build Coastguard Worker    case 4:
1337*61046927SAndroid Build Coastguard Worker       if ((instr->dsts[0]->flags & IR3_REG_SHARED) != (flags & IR3_REG_SHARED))
1338*61046927SAndroid Build Coastguard Worker          return false;
1339*61046927SAndroid Build Coastguard Worker       /* seems like blob compiler avoids const as src.. */
1340*61046927SAndroid Build Coastguard Worker       /* TODO double check if this is still the case on a4xx */
1341*61046927SAndroid Build Coastguard Worker       if (flags & (IR3_REG_CONST | IR3_REG_IMMED))
1342*61046927SAndroid Build Coastguard Worker          return false;
1343*61046927SAndroid Build Coastguard Worker       if (flags & (IR3_REG_SABS | IR3_REG_SNEG))
1344*61046927SAndroid Build Coastguard Worker          return false;
1345*61046927SAndroid Build Coastguard Worker       break;
1346*61046927SAndroid Build Coastguard Worker    case 5:
1347*61046927SAndroid Build Coastguard Worker       if (instr->opc == OPC_ISAM && (instr->flags & IR3_INSTR_V)) {
1348*61046927SAndroid Build Coastguard Worker          if (((instr->flags & IR3_INSTR_S2EN) && n == 2) ||
1349*61046927SAndroid Build Coastguard Worker              (!(instr->flags & IR3_INSTR_S2EN) && n == 1)) {
1350*61046927SAndroid Build Coastguard Worker             return flags == IR3_REG_IMMED;
1351*61046927SAndroid Build Coastguard Worker          }
1352*61046927SAndroid Build Coastguard Worker       }
1353*61046927SAndroid Build Coastguard Worker       /* no flags allowed */
1354*61046927SAndroid Build Coastguard Worker       if (flags)
1355*61046927SAndroid Build Coastguard Worker          return false;
1356*61046927SAndroid Build Coastguard Worker       break;
1357*61046927SAndroid Build Coastguard Worker    case 6:
1358*61046927SAndroid Build Coastguard Worker       valid_flags = IR3_REG_IMMED;
1359*61046927SAndroid Build Coastguard Worker 
1360*61046927SAndroid Build Coastguard Worker       if (instr->opc == OPC_STC && n == 1)
1361*61046927SAndroid Build Coastguard Worker          valid_flags |= IR3_REG_SHARED;
1362*61046927SAndroid Build Coastguard Worker 
1363*61046927SAndroid Build Coastguard Worker       if (flags & ~valid_flags)
1364*61046927SAndroid Build Coastguard Worker          return false;
1365*61046927SAndroid Build Coastguard Worker 
1366*61046927SAndroid Build Coastguard Worker       if (flags & IR3_REG_IMMED) {
1367*61046927SAndroid Build Coastguard Worker          /* doesn't seem like we can have immediate src for store
1368*61046927SAndroid Build Coastguard Worker           * instructions:
1369*61046927SAndroid Build Coastguard Worker           *
1370*61046927SAndroid Build Coastguard Worker           * TODO this restriction could also apply to load instructions,
1371*61046927SAndroid Build Coastguard Worker           * but for load instructions this arg is the address (and not
1372*61046927SAndroid Build Coastguard Worker           * really sure any good way to test a hard-coded immed addr src)
1373*61046927SAndroid Build Coastguard Worker           */
1374*61046927SAndroid Build Coastguard Worker          if (is_store(instr) && (instr->opc != OPC_STG) && (n == 1))
1375*61046927SAndroid Build Coastguard Worker             return false;
1376*61046927SAndroid Build Coastguard Worker 
1377*61046927SAndroid Build Coastguard Worker          if ((instr->opc == OPC_LDL) && (n == 0))
1378*61046927SAndroid Build Coastguard Worker             return false;
1379*61046927SAndroid Build Coastguard Worker 
1380*61046927SAndroid Build Coastguard Worker          if ((instr->opc == OPC_STL) && (n != 2))
1381*61046927SAndroid Build Coastguard Worker             return false;
1382*61046927SAndroid Build Coastguard Worker 
1383*61046927SAndroid Build Coastguard Worker          if ((instr->opc == OPC_LDP) && (n == 0))
1384*61046927SAndroid Build Coastguard Worker             return false;
1385*61046927SAndroid Build Coastguard Worker 
1386*61046927SAndroid Build Coastguard Worker          if ((instr->opc == OPC_STP) && (n != 2))
1387*61046927SAndroid Build Coastguard Worker             return false;
1388*61046927SAndroid Build Coastguard Worker 
1389*61046927SAndroid Build Coastguard Worker          if (instr->opc == OPC_STLW && n == 0)
1390*61046927SAndroid Build Coastguard Worker             return false;
1391*61046927SAndroid Build Coastguard Worker 
1392*61046927SAndroid Build Coastguard Worker          if (instr->opc == OPC_LDLW && n == 0)
1393*61046927SAndroid Build Coastguard Worker             return false;
1394*61046927SAndroid Build Coastguard Worker 
1395*61046927SAndroid Build Coastguard Worker          /* disallow immediates in anything but the SSBO slot argument for
1396*61046927SAndroid Build Coastguard Worker           * cat6 instructions:
1397*61046927SAndroid Build Coastguard Worker           */
1398*61046927SAndroid Build Coastguard Worker          if (is_global_a3xx_atomic(instr->opc) && (n != 0))
1399*61046927SAndroid Build Coastguard Worker             return false;
1400*61046927SAndroid Build Coastguard Worker 
1401*61046927SAndroid Build Coastguard Worker          if (is_local_atomic(instr->opc) || is_global_a6xx_atomic(instr->opc) ||
1402*61046927SAndroid Build Coastguard Worker              is_bindless_atomic(instr->opc))
1403*61046927SAndroid Build Coastguard Worker             return false;
1404*61046927SAndroid Build Coastguard Worker 
1405*61046927SAndroid Build Coastguard Worker          if (instr->opc == OPC_STG && (n == 2))
1406*61046927SAndroid Build Coastguard Worker             return false;
1407*61046927SAndroid Build Coastguard Worker 
1408*61046927SAndroid Build Coastguard Worker          if (instr->opc == OPC_STG_A && (n == 4))
1409*61046927SAndroid Build Coastguard Worker             return false;
1410*61046927SAndroid Build Coastguard Worker 
1411*61046927SAndroid Build Coastguard Worker          if (instr->opc == OPC_LDG && (n == 0))
1412*61046927SAndroid Build Coastguard Worker             return false;
1413*61046927SAndroid Build Coastguard Worker 
1414*61046927SAndroid Build Coastguard Worker          if (instr->opc == OPC_LDG_A && (n < 2))
1415*61046927SAndroid Build Coastguard Worker             return false;
1416*61046927SAndroid Build Coastguard Worker 
1417*61046927SAndroid Build Coastguard Worker          if (instr->opc == OPC_STC && n != 0)
1418*61046927SAndroid Build Coastguard Worker             return false;
1419*61046927SAndroid Build Coastguard Worker 
1420*61046927SAndroid Build Coastguard Worker          /* as with atomics, these cat6 instrs can only have an immediate
1421*61046927SAndroid Build Coastguard Worker           * for SSBO/IBO slot argument
1422*61046927SAndroid Build Coastguard Worker           */
1423*61046927SAndroid Build Coastguard Worker          switch (instr->opc) {
1424*61046927SAndroid Build Coastguard Worker          case OPC_LDIB:
1425*61046927SAndroid Build Coastguard Worker          case OPC_STIB:
1426*61046927SAndroid Build Coastguard Worker             if (n != 0 && n != 2)
1427*61046927SAndroid Build Coastguard Worker                return false;
1428*61046927SAndroid Build Coastguard Worker             break;
1429*61046927SAndroid Build Coastguard Worker          case OPC_RESINFO:
1430*61046927SAndroid Build Coastguard Worker             if (n != 0)
1431*61046927SAndroid Build Coastguard Worker                return false;
1432*61046927SAndroid Build Coastguard Worker             break;
1433*61046927SAndroid Build Coastguard Worker          default:
1434*61046927SAndroid Build Coastguard Worker             break;
1435*61046927SAndroid Build Coastguard Worker          }
1436*61046927SAndroid Build Coastguard Worker       }
1437*61046927SAndroid Build Coastguard Worker 
1438*61046927SAndroid Build Coastguard Worker       break;
1439*61046927SAndroid Build Coastguard Worker    }
1440*61046927SAndroid Build Coastguard Worker 
1441*61046927SAndroid Build Coastguard Worker    return true;
1442*61046927SAndroid Build Coastguard Worker }
1443*61046927SAndroid Build Coastguard Worker 
1444*61046927SAndroid Build Coastguard Worker bool
ir3_valid_immediate(struct ir3_instruction * instr,int32_t immed)1445*61046927SAndroid Build Coastguard Worker ir3_valid_immediate(struct ir3_instruction *instr, int32_t immed)
1446*61046927SAndroid Build Coastguard Worker {
1447*61046927SAndroid Build Coastguard Worker    if (instr->opc == OPC_MOV || is_meta(instr))
1448*61046927SAndroid Build Coastguard Worker       return true;
1449*61046927SAndroid Build Coastguard Worker 
1450*61046927SAndroid Build Coastguard Worker    if (is_mem(instr)) {
1451*61046927SAndroid Build Coastguard Worker       switch (instr->opc) {
1452*61046927SAndroid Build Coastguard Worker       /* Some load/store instructions have a 13-bit offset and size which must
1453*61046927SAndroid Build Coastguard Worker        * always be an immediate and the rest of the sources cannot be
1454*61046927SAndroid Build Coastguard Worker        * immediates, so the frontend is responsible for checking the size:
1455*61046927SAndroid Build Coastguard Worker        */
1456*61046927SAndroid Build Coastguard Worker       case OPC_LDL:
1457*61046927SAndroid Build Coastguard Worker       case OPC_STL:
1458*61046927SAndroid Build Coastguard Worker       case OPC_LDP:
1459*61046927SAndroid Build Coastguard Worker       case OPC_STP:
1460*61046927SAndroid Build Coastguard Worker       case OPC_LDG:
1461*61046927SAndroid Build Coastguard Worker       case OPC_STG:
1462*61046927SAndroid Build Coastguard Worker       case OPC_SPILL_MACRO:
1463*61046927SAndroid Build Coastguard Worker       case OPC_RELOAD_MACRO:
1464*61046927SAndroid Build Coastguard Worker       case OPC_LDG_A:
1465*61046927SAndroid Build Coastguard Worker       case OPC_STG_A:
1466*61046927SAndroid Build Coastguard Worker       case OPC_LDLW:
1467*61046927SAndroid Build Coastguard Worker       case OPC_STLW:
1468*61046927SAndroid Build Coastguard Worker       case OPC_LDLV:
1469*61046927SAndroid Build Coastguard Worker          return true;
1470*61046927SAndroid Build Coastguard Worker       default:
1471*61046927SAndroid Build Coastguard Worker          /* most cat6 src immediates can only encode 8 bits: */
1472*61046927SAndroid Build Coastguard Worker          return !(immed & ~0xff);
1473*61046927SAndroid Build Coastguard Worker       }
1474*61046927SAndroid Build Coastguard Worker    }
1475*61046927SAndroid Build Coastguard Worker 
1476*61046927SAndroid Build Coastguard Worker    /* Other than cat1 (mov) we can only encode up to 10 bits, sign-extended: */
1477*61046927SAndroid Build Coastguard Worker    return !(immed & ~0x1ff) || !(-immed & ~0x1ff);
1478*61046927SAndroid Build Coastguard Worker }
1479*61046927SAndroid Build Coastguard Worker 
1480*61046927SAndroid Build Coastguard Worker struct ir3_instruction *
ir3_get_cond_for_nonzero_compare(struct ir3_instruction * instr)1481*61046927SAndroid Build Coastguard Worker ir3_get_cond_for_nonzero_compare(struct ir3_instruction *instr)
1482*61046927SAndroid Build Coastguard Worker {
1483*61046927SAndroid Build Coastguard Worker    /* If instr is a negation (likely as a result of an nir_b2n), we can ignore
1484*61046927SAndroid Build Coastguard Worker     * that and use its source, since the nonzero-ness stays the same.
1485*61046927SAndroid Build Coastguard Worker     */
1486*61046927SAndroid Build Coastguard Worker    if (instr->opc == OPC_ABSNEG_S && instr->flags == 0 &&
1487*61046927SAndroid Build Coastguard Worker        (instr->srcs[0]->flags & (IR3_REG_SNEG | IR3_REG_SABS)) ==
1488*61046927SAndroid Build Coastguard Worker           IR3_REG_SNEG) {
1489*61046927SAndroid Build Coastguard Worker       return instr->srcs[0]->def->instr;
1490*61046927SAndroid Build Coastguard Worker    }
1491*61046927SAndroid Build Coastguard Worker 
1492*61046927SAndroid Build Coastguard Worker    return instr;
1493*61046927SAndroid Build Coastguard Worker }
1494*61046927SAndroid Build Coastguard Worker 
1495*61046927SAndroid Build Coastguard Worker bool
ir3_supports_rpt(struct ir3_compiler * compiler,unsigned opc)1496*61046927SAndroid Build Coastguard Worker ir3_supports_rpt(struct ir3_compiler *compiler, unsigned opc)
1497*61046927SAndroid Build Coastguard Worker {
1498*61046927SAndroid Build Coastguard Worker    switch (opc_cat(opc)) {
1499*61046927SAndroid Build Coastguard Worker    case 0:
1500*61046927SAndroid Build Coastguard Worker       return opc == OPC_NOP;
1501*61046927SAndroid Build Coastguard Worker    case 1:
1502*61046927SAndroid Build Coastguard Worker       return opc == OPC_MOV || opc == OPC_SWZ || opc == OPC_MOVMSK;
1503*61046927SAndroid Build Coastguard Worker    case 2:
1504*61046927SAndroid Build Coastguard Worker       if (opc == OPC_BARY_F && !compiler->has_rpt_bary_f)
1505*61046927SAndroid Build Coastguard Worker          return false;
1506*61046927SAndroid Build Coastguard Worker       return true;
1507*61046927SAndroid Build Coastguard Worker    case 3:
1508*61046927SAndroid Build Coastguard Worker       return opc != OPC_DP2ACC && opc != OPC_DP4ACC;
1509*61046927SAndroid Build Coastguard Worker    case 4:
1510*61046927SAndroid Build Coastguard Worker       return opc != OPC_RCP;
1511*61046927SAndroid Build Coastguard Worker    default:
1512*61046927SAndroid Build Coastguard Worker       return false;
1513*61046927SAndroid Build Coastguard Worker    }
1514*61046927SAndroid Build Coastguard Worker }
1515