1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright 2024 Igalia S.L.
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_nir.h"
7*61046927SAndroid Build Coastguard Worker
8*61046927SAndroid Build Coastguard Worker bool
ir3_supports_vectorized_nir_op(nir_op op)9*61046927SAndroid Build Coastguard Worker ir3_supports_vectorized_nir_op(nir_op op)
10*61046927SAndroid Build Coastguard Worker {
11*61046927SAndroid Build Coastguard Worker switch (op) {
12*61046927SAndroid Build Coastguard Worker /* TODO: emitted as absneg which can often be folded away (e.g., into
13*61046927SAndroid Build Coastguard Worker * (neg)). This seems to often fail when repeated.
14*61046927SAndroid Build Coastguard Worker */
15*61046927SAndroid Build Coastguard Worker case nir_op_b2b1:
16*61046927SAndroid Build Coastguard Worker
17*61046927SAndroid Build Coastguard Worker /* dsx/dsy don't seem to support repeat. */
18*61046927SAndroid Build Coastguard Worker case nir_op_fddx:
19*61046927SAndroid Build Coastguard Worker case nir_op_fddx_coarse:
20*61046927SAndroid Build Coastguard Worker case nir_op_fddx_fine:
21*61046927SAndroid Build Coastguard Worker case nir_op_fddy:
22*61046927SAndroid Build Coastguard Worker case nir_op_fddy_coarse:
23*61046927SAndroid Build Coastguard Worker case nir_op_fddy_fine:
24*61046927SAndroid Build Coastguard Worker
25*61046927SAndroid Build Coastguard Worker /* dp2acc/dp4acc don't seem to support repeat. */
26*61046927SAndroid Build Coastguard Worker case nir_op_udot_4x8_uadd:
27*61046927SAndroid Build Coastguard Worker case nir_op_udot_4x8_uadd_sat:
28*61046927SAndroid Build Coastguard Worker case nir_op_sudot_4x8_iadd:
29*61046927SAndroid Build Coastguard Worker case nir_op_sudot_4x8_iadd_sat:
30*61046927SAndroid Build Coastguard Worker
31*61046927SAndroid Build Coastguard Worker /* Among SFU instructions, only rcp doesn't seem to support repeat. */
32*61046927SAndroid Build Coastguard Worker case nir_op_frcp:
33*61046927SAndroid Build Coastguard Worker return false;
34*61046927SAndroid Build Coastguard Worker
35*61046927SAndroid Build Coastguard Worker default:
36*61046927SAndroid Build Coastguard Worker return true;
37*61046927SAndroid Build Coastguard Worker }
38*61046927SAndroid Build Coastguard Worker }
39*61046927SAndroid Build Coastguard Worker
40*61046927SAndroid Build Coastguard Worker uint8_t
ir3_nir_vectorize_filter(const nir_instr * instr,const void * data)41*61046927SAndroid Build Coastguard Worker ir3_nir_vectorize_filter(const nir_instr *instr, const void *data)
42*61046927SAndroid Build Coastguard Worker {
43*61046927SAndroid Build Coastguard Worker if (instr->type == nir_instr_type_phi)
44*61046927SAndroid Build Coastguard Worker return 4;
45*61046927SAndroid Build Coastguard Worker if (instr->type != nir_instr_type_alu)
46*61046927SAndroid Build Coastguard Worker return 0;
47*61046927SAndroid Build Coastguard Worker
48*61046927SAndroid Build Coastguard Worker struct nir_alu_instr *alu = nir_instr_as_alu(instr);
49*61046927SAndroid Build Coastguard Worker
50*61046927SAndroid Build Coastguard Worker if (!ir3_supports_vectorized_nir_op(alu->op))
51*61046927SAndroid Build Coastguard Worker return 0;
52*61046927SAndroid Build Coastguard Worker
53*61046927SAndroid Build Coastguard Worker return 4;
54*61046927SAndroid Build Coastguard Worker }
55*61046927SAndroid Build Coastguard Worker
56*61046927SAndroid Build Coastguard Worker static void
rpt_list_split(struct list_head * list,struct list_head * at)57*61046927SAndroid Build Coastguard Worker rpt_list_split(struct list_head *list, struct list_head *at)
58*61046927SAndroid Build Coastguard Worker {
59*61046927SAndroid Build Coastguard Worker struct list_head *new_last = at->prev;
60*61046927SAndroid Build Coastguard Worker new_last->next = list;
61*61046927SAndroid Build Coastguard Worker at->prev = list->prev;
62*61046927SAndroid Build Coastguard Worker list->prev->next = at;
63*61046927SAndroid Build Coastguard Worker list->prev = new_last;
64*61046927SAndroid Build Coastguard Worker }
65*61046927SAndroid Build Coastguard Worker
66*61046927SAndroid Build Coastguard Worker static enum ir3_register_flags
rpt_compatible_src_flags(struct ir3_register * src)67*61046927SAndroid Build Coastguard Worker rpt_compatible_src_flags(struct ir3_register *src)
68*61046927SAndroid Build Coastguard Worker {
69*61046927SAndroid Build Coastguard Worker return src->flags &
70*61046927SAndroid Build Coastguard Worker (IR3_REG_SABS | IR3_REG_SNEG | IR3_REG_FABS | IR3_REG_FNEG |
71*61046927SAndroid Build Coastguard Worker IR3_REG_BNOT | IR3_REG_CONST | IR3_REG_IMMED | IR3_REG_SSA |
72*61046927SAndroid Build Coastguard Worker IR3_REG_HALF | IR3_REG_SHARED);
73*61046927SAndroid Build Coastguard Worker }
74*61046927SAndroid Build Coastguard Worker
75*61046927SAndroid Build Coastguard Worker static enum ir3_register_flags
rpt_compatible_dst_flags(struct ir3_instruction * instr)76*61046927SAndroid Build Coastguard Worker rpt_compatible_dst_flags(struct ir3_instruction *instr)
77*61046927SAndroid Build Coastguard Worker {
78*61046927SAndroid Build Coastguard Worker return instr->dsts[0]->flags & (IR3_REG_SSA | IR3_REG_HALF | IR3_REG_SHARED);
79*61046927SAndroid Build Coastguard Worker }
80*61046927SAndroid Build Coastguard Worker
81*61046927SAndroid Build Coastguard Worker static enum ir3_register_flags
rpt_illegal_src_flags(struct ir3_register * src)82*61046927SAndroid Build Coastguard Worker rpt_illegal_src_flags(struct ir3_register *src)
83*61046927SAndroid Build Coastguard Worker {
84*61046927SAndroid Build Coastguard Worker return src->flags & (IR3_REG_ARRAY | IR3_REG_RELATIV);
85*61046927SAndroid Build Coastguard Worker }
86*61046927SAndroid Build Coastguard Worker
87*61046927SAndroid Build Coastguard Worker static enum ir3_instruction_flags
rpt_compatible_instr_flags(struct ir3_instruction * instr)88*61046927SAndroid Build Coastguard Worker rpt_compatible_instr_flags(struct ir3_instruction *instr)
89*61046927SAndroid Build Coastguard Worker {
90*61046927SAndroid Build Coastguard Worker return instr->flags & IR3_INSTR_SAT;
91*61046927SAndroid Build Coastguard Worker }
92*61046927SAndroid Build Coastguard Worker
93*61046927SAndroid Build Coastguard Worker static bool
supports_imm_r(unsigned opc)94*61046927SAndroid Build Coastguard Worker supports_imm_r(unsigned opc)
95*61046927SAndroid Build Coastguard Worker {
96*61046927SAndroid Build Coastguard Worker return opc == OPC_BARY_F || opc == OPC_FLAT_B;
97*61046927SAndroid Build Coastguard Worker }
98*61046927SAndroid Build Coastguard Worker
99*61046927SAndroid Build Coastguard Worker static bool
srcs_can_rpt(struct ir3_instruction * instr,struct ir3_register * src,struct ir3_register * rpt_src,unsigned rpt_n)100*61046927SAndroid Build Coastguard Worker srcs_can_rpt(struct ir3_instruction *instr, struct ir3_register *src,
101*61046927SAndroid Build Coastguard Worker struct ir3_register *rpt_src, unsigned rpt_n)
102*61046927SAndroid Build Coastguard Worker {
103*61046927SAndroid Build Coastguard Worker if (rpt_illegal_src_flags(src) != 0 || rpt_illegal_src_flags(rpt_src) != 0)
104*61046927SAndroid Build Coastguard Worker return false;
105*61046927SAndroid Build Coastguard Worker if (rpt_compatible_src_flags(src) != rpt_compatible_src_flags(rpt_src))
106*61046927SAndroid Build Coastguard Worker return false;
107*61046927SAndroid Build Coastguard Worker if (src->flags & IR3_REG_IMMED) {
108*61046927SAndroid Build Coastguard Worker uint32_t val = src->uim_val;
109*61046927SAndroid Build Coastguard Worker uint32_t rpt_val = rpt_src->uim_val;
110*61046927SAndroid Build Coastguard Worker
111*61046927SAndroid Build Coastguard Worker if (rpt_val == val)
112*61046927SAndroid Build Coastguard Worker return true;
113*61046927SAndroid Build Coastguard Worker if (supports_imm_r(instr->opc))
114*61046927SAndroid Build Coastguard Worker return rpt_val == val + rpt_n;
115*61046927SAndroid Build Coastguard Worker return false;
116*61046927SAndroid Build Coastguard Worker }
117*61046927SAndroid Build Coastguard Worker
118*61046927SAndroid Build Coastguard Worker return true;
119*61046927SAndroid Build Coastguard Worker }
120*61046927SAndroid Build Coastguard Worker
121*61046927SAndroid Build Coastguard Worker static bool
can_rpt(struct ir3_instruction * instr,struct ir3_instruction * rpt,unsigned rpt_n)122*61046927SAndroid Build Coastguard Worker can_rpt(struct ir3_instruction *instr, struct ir3_instruction *rpt,
123*61046927SAndroid Build Coastguard Worker unsigned rpt_n)
124*61046927SAndroid Build Coastguard Worker {
125*61046927SAndroid Build Coastguard Worker if (rpt_n >= 4)
126*61046927SAndroid Build Coastguard Worker return false;
127*61046927SAndroid Build Coastguard Worker if (rpt->ip != instr->ip + rpt_n)
128*61046927SAndroid Build Coastguard Worker return false;
129*61046927SAndroid Build Coastguard Worker if (rpt->opc != instr->opc)
130*61046927SAndroid Build Coastguard Worker return false;
131*61046927SAndroid Build Coastguard Worker if (!ir3_supports_rpt(instr->block->shader->compiler, instr->opc))
132*61046927SAndroid Build Coastguard Worker return false;
133*61046927SAndroid Build Coastguard Worker if (rpt_compatible_instr_flags(rpt) != rpt_compatible_instr_flags(instr))
134*61046927SAndroid Build Coastguard Worker return false;
135*61046927SAndroid Build Coastguard Worker if (rpt_compatible_dst_flags(rpt) != rpt_compatible_dst_flags(instr))
136*61046927SAndroid Build Coastguard Worker return false;
137*61046927SAndroid Build Coastguard Worker if (instr->srcs_count != rpt->srcs_count)
138*61046927SAndroid Build Coastguard Worker return false;
139*61046927SAndroid Build Coastguard Worker
140*61046927SAndroid Build Coastguard Worker foreach_src_n (src, src_n, instr) {
141*61046927SAndroid Build Coastguard Worker if (!srcs_can_rpt(instr, src, rpt->srcs[src_n], rpt_n))
142*61046927SAndroid Build Coastguard Worker return false;
143*61046927SAndroid Build Coastguard Worker }
144*61046927SAndroid Build Coastguard Worker
145*61046927SAndroid Build Coastguard Worker return true;
146*61046927SAndroid Build Coastguard Worker }
147*61046927SAndroid Build Coastguard Worker
148*61046927SAndroid Build Coastguard Worker static bool
cleanup_rpt_instr(struct ir3_instruction * instr)149*61046927SAndroid Build Coastguard Worker cleanup_rpt_instr(struct ir3_instruction *instr)
150*61046927SAndroid Build Coastguard Worker {
151*61046927SAndroid Build Coastguard Worker if (!ir3_instr_is_first_rpt(instr))
152*61046927SAndroid Build Coastguard Worker return false;
153*61046927SAndroid Build Coastguard Worker
154*61046927SAndroid Build Coastguard Worker unsigned rpt_n = 1;
155*61046927SAndroid Build Coastguard Worker foreach_instr_rpt_excl (rpt, instr) {
156*61046927SAndroid Build Coastguard Worker if (!can_rpt(instr, rpt, rpt_n++)) {
157*61046927SAndroid Build Coastguard Worker rpt_list_split(&instr->rpt_node, &rpt->rpt_node);
158*61046927SAndroid Build Coastguard Worker
159*61046927SAndroid Build Coastguard Worker /* We have to do this recursively since later repetitions might come
160*61046927SAndroid Build Coastguard Worker * before the first in the instruction list.
161*61046927SAndroid Build Coastguard Worker */
162*61046927SAndroid Build Coastguard Worker cleanup_rpt_instr(rpt);
163*61046927SAndroid Build Coastguard Worker return true;
164*61046927SAndroid Build Coastguard Worker }
165*61046927SAndroid Build Coastguard Worker }
166*61046927SAndroid Build Coastguard Worker
167*61046927SAndroid Build Coastguard Worker return false;
168*61046927SAndroid Build Coastguard Worker }
169*61046927SAndroid Build Coastguard Worker
170*61046927SAndroid Build Coastguard Worker /* Pre-RA pass to clean up repetition groups that can never be merged into a rpt
171*61046927SAndroid Build Coastguard Worker * instruction. This ensures we don't needlessly allocate merge sets for them.
172*61046927SAndroid Build Coastguard Worker */
173*61046927SAndroid Build Coastguard Worker bool
ir3_cleanup_rpt(struct ir3 * ir,struct ir3_shader_variant * v)174*61046927SAndroid Build Coastguard Worker ir3_cleanup_rpt(struct ir3 *ir, struct ir3_shader_variant *v)
175*61046927SAndroid Build Coastguard Worker {
176*61046927SAndroid Build Coastguard Worker ir3_count_instructions(ir);
177*61046927SAndroid Build Coastguard Worker bool progress = false;
178*61046927SAndroid Build Coastguard Worker
179*61046927SAndroid Build Coastguard Worker foreach_block (block, &ir->block_list) {
180*61046927SAndroid Build Coastguard Worker foreach_instr (instr, &block->instr_list)
181*61046927SAndroid Build Coastguard Worker progress |= cleanup_rpt_instr(instr);
182*61046927SAndroid Build Coastguard Worker }
183*61046927SAndroid Build Coastguard Worker
184*61046927SAndroid Build Coastguard Worker return progress;
185*61046927SAndroid Build Coastguard Worker }
186*61046927SAndroid Build Coastguard Worker
187*61046927SAndroid Build Coastguard Worker enum rpt_src_type {
188*61046927SAndroid Build Coastguard Worker RPT_INCOMPATIBLE, /* Incompatible sources. */
189*61046927SAndroid Build Coastguard Worker RPT_SET, /* Compatible sources that need (r) set. */
190*61046927SAndroid Build Coastguard Worker RPT_DONT_SET, /* Compatible sources that don't need (r) set. */
191*61046927SAndroid Build Coastguard Worker };
192*61046927SAndroid Build Coastguard Worker
193*61046927SAndroid Build Coastguard Worker static enum rpt_src_type
srcs_rpt_compatible(struct ir3_instruction * instr,struct ir3_register * src,struct ir3_register * rpt_src)194*61046927SAndroid Build Coastguard Worker srcs_rpt_compatible(struct ir3_instruction *instr, struct ir3_register *src,
195*61046927SAndroid Build Coastguard Worker struct ir3_register *rpt_src)
196*61046927SAndroid Build Coastguard Worker {
197*61046927SAndroid Build Coastguard Worker /* Shared RA may have demoted some sources from shared to non-shared. When
198*61046927SAndroid Build Coastguard Worker * this happened for some but not all instructions in a repeat group, the
199*61046927SAndroid Build Coastguard Worker * assert below would trigger. Detect this here.
200*61046927SAndroid Build Coastguard Worker */
201*61046927SAndroid Build Coastguard Worker if ((src->flags & IR3_REG_SHARED) != (rpt_src->flags & IR3_REG_SHARED))
202*61046927SAndroid Build Coastguard Worker return RPT_INCOMPATIBLE;
203*61046927SAndroid Build Coastguard Worker
204*61046927SAndroid Build Coastguard Worker assert(srcs_can_rpt(instr, src, rpt_src, instr->repeat + 1));
205*61046927SAndroid Build Coastguard Worker
206*61046927SAndroid Build Coastguard Worker if (src->flags & IR3_REG_IMMED) {
207*61046927SAndroid Build Coastguard Worker if (supports_imm_r(instr->opc) &&
208*61046927SAndroid Build Coastguard Worker rpt_src->uim_val == src->uim_val + instr->repeat + 1) {
209*61046927SAndroid Build Coastguard Worker return RPT_SET;
210*61046927SAndroid Build Coastguard Worker }
211*61046927SAndroid Build Coastguard Worker
212*61046927SAndroid Build Coastguard Worker assert(rpt_src->uim_val == src->uim_val);
213*61046927SAndroid Build Coastguard Worker return RPT_DONT_SET;
214*61046927SAndroid Build Coastguard Worker }
215*61046927SAndroid Build Coastguard Worker
216*61046927SAndroid Build Coastguard Worker if (rpt_src->num == src->num + instr->repeat + 1) {
217*61046927SAndroid Build Coastguard Worker if ((src->flags & IR3_REG_R) || instr->repeat == 0)
218*61046927SAndroid Build Coastguard Worker return RPT_SET;
219*61046927SAndroid Build Coastguard Worker return RPT_INCOMPATIBLE;
220*61046927SAndroid Build Coastguard Worker }
221*61046927SAndroid Build Coastguard Worker
222*61046927SAndroid Build Coastguard Worker if (rpt_src->num == src->num && !(src->flags & IR3_REG_R))
223*61046927SAndroid Build Coastguard Worker return RPT_DONT_SET;
224*61046927SAndroid Build Coastguard Worker return RPT_INCOMPATIBLE;
225*61046927SAndroid Build Coastguard Worker }
226*61046927SAndroid Build Coastguard Worker
227*61046927SAndroid Build Coastguard Worker static unsigned
inc_wrmask(unsigned wrmask)228*61046927SAndroid Build Coastguard Worker inc_wrmask(unsigned wrmask)
229*61046927SAndroid Build Coastguard Worker {
230*61046927SAndroid Build Coastguard Worker return (wrmask << 1) | 0x1;
231*61046927SAndroid Build Coastguard Worker }
232*61046927SAndroid Build Coastguard Worker
233*61046927SAndroid Build Coastguard Worker static bool
try_merge(struct ir3_instruction * instr,struct ir3_instruction * rpt,unsigned rpt_n)234*61046927SAndroid Build Coastguard Worker try_merge(struct ir3_instruction *instr, struct ir3_instruction *rpt,
235*61046927SAndroid Build Coastguard Worker unsigned rpt_n)
236*61046927SAndroid Build Coastguard Worker {
237*61046927SAndroid Build Coastguard Worker assert(rpt_n > 0 && rpt_n < 4);
238*61046927SAndroid Build Coastguard Worker assert(instr->opc == rpt->opc);
239*61046927SAndroid Build Coastguard Worker assert(instr->dsts_count == 1 && rpt->dsts_count == 1);
240*61046927SAndroid Build Coastguard Worker assert(instr->srcs_count == rpt->srcs_count);
241*61046927SAndroid Build Coastguard Worker assert(rpt_compatible_instr_flags(instr) == rpt_compatible_instr_flags(rpt));
242*61046927SAndroid Build Coastguard Worker
243*61046927SAndroid Build Coastguard Worker struct ir3_register *dst = instr->dsts[0];
244*61046927SAndroid Build Coastguard Worker struct ir3_register *rpt_dst = rpt->dsts[0];
245*61046927SAndroid Build Coastguard Worker
246*61046927SAndroid Build Coastguard Worker if (rpt->ip != instr->ip + rpt_n)
247*61046927SAndroid Build Coastguard Worker return false;
248*61046927SAndroid Build Coastguard Worker if (rpt_dst->num != dst->num + rpt_n)
249*61046927SAndroid Build Coastguard Worker return false;
250*61046927SAndroid Build Coastguard Worker
251*61046927SAndroid Build Coastguard Worker enum rpt_src_type srcs_rpt[instr->srcs_count];
252*61046927SAndroid Build Coastguard Worker
253*61046927SAndroid Build Coastguard Worker foreach_src_n (src, src_n, instr) {
254*61046927SAndroid Build Coastguard Worker srcs_rpt[src_n] = srcs_rpt_compatible(instr, src, rpt->srcs[src_n]);
255*61046927SAndroid Build Coastguard Worker
256*61046927SAndroid Build Coastguard Worker if (srcs_rpt[src_n] == RPT_INCOMPATIBLE)
257*61046927SAndroid Build Coastguard Worker return false;
258*61046927SAndroid Build Coastguard Worker }
259*61046927SAndroid Build Coastguard Worker
260*61046927SAndroid Build Coastguard Worker foreach_src_n (src, src_n, instr) {
261*61046927SAndroid Build Coastguard Worker assert((src->flags & ~(IR3_REG_R | IR3_REG_KILL | IR3_REG_FIRST_KILL)) ==
262*61046927SAndroid Build Coastguard Worker (rpt->srcs[src_n]->flags & ~(IR3_REG_KILL | IR3_REG_FIRST_KILL)));
263*61046927SAndroid Build Coastguard Worker
264*61046927SAndroid Build Coastguard Worker if (srcs_rpt[src_n] == RPT_SET) {
265*61046927SAndroid Build Coastguard Worker src->flags |= IR3_REG_R;
266*61046927SAndroid Build Coastguard Worker src->wrmask = inc_wrmask(src->wrmask);
267*61046927SAndroid Build Coastguard Worker }
268*61046927SAndroid Build Coastguard Worker }
269*61046927SAndroid Build Coastguard Worker
270*61046927SAndroid Build Coastguard Worker dst->wrmask = inc_wrmask(dst->wrmask);
271*61046927SAndroid Build Coastguard Worker return true;
272*61046927SAndroid Build Coastguard Worker }
273*61046927SAndroid Build Coastguard Worker
274*61046927SAndroid Build Coastguard Worker static bool
merge_instr(struct ir3_instruction * instr)275*61046927SAndroid Build Coastguard Worker merge_instr(struct ir3_instruction *instr)
276*61046927SAndroid Build Coastguard Worker {
277*61046927SAndroid Build Coastguard Worker if (!ir3_instr_is_first_rpt(instr))
278*61046927SAndroid Build Coastguard Worker return false;
279*61046927SAndroid Build Coastguard Worker
280*61046927SAndroid Build Coastguard Worker bool progress = false;
281*61046927SAndroid Build Coastguard Worker
282*61046927SAndroid Build Coastguard Worker unsigned rpt_n = 1;
283*61046927SAndroid Build Coastguard Worker
284*61046927SAndroid Build Coastguard Worker foreach_instr_rpt_excl_safe (rpt, instr) {
285*61046927SAndroid Build Coastguard Worker /* When rpt cannot be merged, stop immediately. We will try to merge rpt
286*61046927SAndroid Build Coastguard Worker * with the following instructions (if any) once we encounter it in
287*61046927SAndroid Build Coastguard Worker * ir3_combine_rpt.
288*61046927SAndroid Build Coastguard Worker */
289*61046927SAndroid Build Coastguard Worker if (!try_merge(instr, rpt, rpt_n))
290*61046927SAndroid Build Coastguard Worker break;
291*61046927SAndroid Build Coastguard Worker
292*61046927SAndroid Build Coastguard Worker instr->repeat++;
293*61046927SAndroid Build Coastguard Worker
294*61046927SAndroid Build Coastguard Worker /* We cannot remove the rpt immediately since when it is the instruction
295*61046927SAndroid Build Coastguard Worker * after instr, foreach_instr_safe will fail. So mark it instead and
296*61046927SAndroid Build Coastguard Worker * remove it in ir3_combine_rpt when we encounter it.
297*61046927SAndroid Build Coastguard Worker */
298*61046927SAndroid Build Coastguard Worker rpt->flags |= IR3_INSTR_MARK;
299*61046927SAndroid Build Coastguard Worker list_delinit(&rpt->rpt_node);
300*61046927SAndroid Build Coastguard Worker ++rpt_n;
301*61046927SAndroid Build Coastguard Worker progress = true;
302*61046927SAndroid Build Coastguard Worker }
303*61046927SAndroid Build Coastguard Worker
304*61046927SAndroid Build Coastguard Worker list_delinit(&instr->rpt_node);
305*61046927SAndroid Build Coastguard Worker return progress;
306*61046927SAndroid Build Coastguard Worker }
307*61046927SAndroid Build Coastguard Worker
308*61046927SAndroid Build Coastguard Worker /* Merge compatible instructions in a repetition group into one or more rpt
309*61046927SAndroid Build Coastguard Worker * instructions.
310*61046927SAndroid Build Coastguard Worker */
311*61046927SAndroid Build Coastguard Worker bool
ir3_merge_rpt(struct ir3 * ir,struct ir3_shader_variant * v)312*61046927SAndroid Build Coastguard Worker ir3_merge_rpt(struct ir3 *ir, struct ir3_shader_variant *v)
313*61046927SAndroid Build Coastguard Worker {
314*61046927SAndroid Build Coastguard Worker ir3_clear_mark(ir);
315*61046927SAndroid Build Coastguard Worker ir3_count_instructions(ir);
316*61046927SAndroid Build Coastguard Worker bool progress = false;
317*61046927SAndroid Build Coastguard Worker
318*61046927SAndroid Build Coastguard Worker foreach_block (block, &ir->block_list) {
319*61046927SAndroid Build Coastguard Worker foreach_instr_safe (instr, &block->instr_list) {
320*61046927SAndroid Build Coastguard Worker if (instr->flags & IR3_INSTR_MARK) {
321*61046927SAndroid Build Coastguard Worker list_delinit(&instr->node);
322*61046927SAndroid Build Coastguard Worker continue;
323*61046927SAndroid Build Coastguard Worker }
324*61046927SAndroid Build Coastguard Worker
325*61046927SAndroid Build Coastguard Worker progress |= merge_instr(instr);
326*61046927SAndroid Build Coastguard Worker }
327*61046927SAndroid Build Coastguard Worker }
328*61046927SAndroid Build Coastguard Worker
329*61046927SAndroid Build Coastguard Worker return progress;
330*61046927SAndroid Build Coastguard Worker }
331