xref: /aosp_15_r20/external/mesa3d/src/freedreno/ir3/ir3_spill.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2021 Valve Corporation
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 "util/rb_tree.h"
7*61046927SAndroid Build Coastguard Worker #include "ir3_ra.h"
8*61046927SAndroid Build Coastguard Worker #include "ir3_shader.h"
9*61046927SAndroid Build Coastguard Worker 
10*61046927SAndroid Build Coastguard Worker /*
11*61046927SAndroid Build Coastguard Worker  * This pass does two things:
12*61046927SAndroid Build Coastguard Worker  *
13*61046927SAndroid Build Coastguard Worker  * 1. Calculates the maximum register pressure. To do this, we need to use the
14*61046927SAndroid Build Coastguard Worker  *    exact same technique that RA uses for combining meta_split instructions
15*61046927SAndroid Build Coastguard Worker  *    with their sources, so that our calculation agrees with RA.
16*61046927SAndroid Build Coastguard Worker  * 2. Spills when the register pressure is exceeded a limit calculated by RA.
17*61046927SAndroid Build Coastguard Worker  *    The implementation is based on "Register Spilling and Live-Range Splitting
18*61046927SAndroid Build Coastguard Worker  *    for SSA-Form Programs" by Braun and Hack, although again care has to be
19*61046927SAndroid Build Coastguard Worker  *    taken to handle combining split/collect instructions.
20*61046927SAndroid Build Coastguard Worker  */
21*61046927SAndroid Build Coastguard Worker 
22*61046927SAndroid Build Coastguard Worker struct reg_or_immed {
23*61046927SAndroid Build Coastguard Worker    unsigned flags;
24*61046927SAndroid Build Coastguard Worker    union {
25*61046927SAndroid Build Coastguard Worker       struct ir3_register *def;
26*61046927SAndroid Build Coastguard Worker       uint32_t uimm;
27*61046927SAndroid Build Coastguard Worker       unsigned const_num;
28*61046927SAndroid Build Coastguard Worker    };
29*61046927SAndroid Build Coastguard Worker };
30*61046927SAndroid Build Coastguard Worker 
31*61046927SAndroid Build Coastguard Worker struct ra_spill_interval {
32*61046927SAndroid Build Coastguard Worker    struct ir3_reg_interval interval;
33*61046927SAndroid Build Coastguard Worker 
34*61046927SAndroid Build Coastguard Worker    struct rb_node node;
35*61046927SAndroid Build Coastguard Worker    struct rb_node half_node;
36*61046927SAndroid Build Coastguard Worker 
37*61046927SAndroid Build Coastguard Worker    /* The current SSA value/const/immed this source is mapped to. */
38*61046927SAndroid Build Coastguard Worker    struct reg_or_immed dst;
39*61046927SAndroid Build Coastguard Worker 
40*61046927SAndroid Build Coastguard Worker    /* When computing use distances we use the distance relative to the start
41*61046927SAndroid Build Coastguard Worker     * of the block. So, for example, a value that's defined in cycle 5 of the
42*61046927SAndroid Build Coastguard Worker     * block and used 6 cycles later will always have a next_use_distance of 11
43*61046927SAndroid Build Coastguard Worker     * until we reach that use.
44*61046927SAndroid Build Coastguard Worker     */
45*61046927SAndroid Build Coastguard Worker    unsigned next_use_distance;
46*61046927SAndroid Build Coastguard Worker 
47*61046927SAndroid Build Coastguard Worker    /* Whether this value was reloaded and therefore doesn't need to be
48*61046927SAndroid Build Coastguard Worker     * spilled again. Corresponds to the S set in the paper.
49*61046927SAndroid Build Coastguard Worker     */
50*61046927SAndroid Build Coastguard Worker    bool already_spilled;
51*61046927SAndroid Build Coastguard Worker 
52*61046927SAndroid Build Coastguard Worker    /* We need to add sources early for accounting purposes, but we have to
53*61046927SAndroid Build Coastguard Worker     * insert the reload code for them last. Keep track of whether this interval
54*61046927SAndroid Build Coastguard Worker     * needs to be reloaded later.
55*61046927SAndroid Build Coastguard Worker     */
56*61046927SAndroid Build Coastguard Worker    bool needs_reload;
57*61046927SAndroid Build Coastguard Worker 
58*61046927SAndroid Build Coastguard Worker    /* Keep track of whether this interval currently can't be spilled because:
59*61046927SAndroid Build Coastguard Worker     * - It or one of its children is a source and we're making space for
60*61046927SAndroid Build Coastguard Worker     *   sources.
61*61046927SAndroid Build Coastguard Worker     * - It is a destination and we're making space for destinations.
62*61046927SAndroid Build Coastguard Worker     */
63*61046927SAndroid Build Coastguard Worker    bool cant_spill;
64*61046927SAndroid Build Coastguard Worker 
65*61046927SAndroid Build Coastguard Worker    /* Whether this interval can be rematerialized. */
66*61046927SAndroid Build Coastguard Worker    bool can_rematerialize;
67*61046927SAndroid Build Coastguard Worker };
68*61046927SAndroid Build Coastguard Worker 
69*61046927SAndroid Build Coastguard Worker struct ra_spill_block_state {
70*61046927SAndroid Build Coastguard Worker    unsigned *next_use_end;
71*61046927SAndroid Build Coastguard Worker    unsigned *next_use_start;
72*61046927SAndroid Build Coastguard Worker 
73*61046927SAndroid Build Coastguard Worker    unsigned cycles;
74*61046927SAndroid Build Coastguard Worker 
75*61046927SAndroid Build Coastguard Worker    /* Map from SSA def to reg_or_immed it is mapped to at the end of the block.
76*61046927SAndroid Build Coastguard Worker     * This map only contains values which we didn't spill, so it also serves as
77*61046927SAndroid Build Coastguard Worker     * a record of the new live-out set for this block.
78*61046927SAndroid Build Coastguard Worker     */
79*61046927SAndroid Build Coastguard Worker    struct hash_table *remap;
80*61046927SAndroid Build Coastguard Worker 
81*61046927SAndroid Build Coastguard Worker    /* For blocks whose successors are visited first (i.e. loop backedges), which
82*61046927SAndroid Build Coastguard Worker     * values should be live at the end.
83*61046927SAndroid Build Coastguard Worker     */
84*61046927SAndroid Build Coastguard Worker    BITSET_WORD *live_out;
85*61046927SAndroid Build Coastguard Worker 
86*61046927SAndroid Build Coastguard Worker    bool visited;
87*61046927SAndroid Build Coastguard Worker };
88*61046927SAndroid Build Coastguard Worker 
89*61046927SAndroid Build Coastguard Worker struct ra_spill_ctx {
90*61046927SAndroid Build Coastguard Worker    struct ir3_reg_ctx reg_ctx;
91*61046927SAndroid Build Coastguard Worker 
92*61046927SAndroid Build Coastguard Worker    struct ra_spill_interval **intervals;
93*61046927SAndroid Build Coastguard Worker    unsigned intervals_count;
94*61046927SAndroid Build Coastguard Worker 
95*61046927SAndroid Build Coastguard Worker    /* rb tree of live intervals that we can spill, ordered by next-use distance.
96*61046927SAndroid Build Coastguard Worker     * full_live_intervals contains the full+shared intervals in the merged_regs
97*61046927SAndroid Build Coastguard Worker     * case. We use this list to determine what to spill.
98*61046927SAndroid Build Coastguard Worker     */
99*61046927SAndroid Build Coastguard Worker    struct rb_tree full_live_intervals;
100*61046927SAndroid Build Coastguard Worker    struct rb_tree half_live_intervals;
101*61046927SAndroid Build Coastguard Worker 
102*61046927SAndroid Build Coastguard Worker    struct ir3_pressure cur_pressure, max_pressure;
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker    struct ir3_pressure limit_pressure;
105*61046927SAndroid Build Coastguard Worker 
106*61046927SAndroid Build Coastguard Worker    /* When spilling, we need to reserve a register to serve as the zero'd
107*61046927SAndroid Build Coastguard Worker     * "base". For simplicity we reserve a register at the beginning so that it's
108*61046927SAndroid Build Coastguard Worker     * always available.
109*61046927SAndroid Build Coastguard Worker     */
110*61046927SAndroid Build Coastguard Worker    struct ir3_register *base_reg;
111*61046927SAndroid Build Coastguard Worker 
112*61046927SAndroid Build Coastguard Worker    /* Current pvtmem offset in bytes. */
113*61046927SAndroid Build Coastguard Worker    unsigned spill_slot;
114*61046927SAndroid Build Coastguard Worker 
115*61046927SAndroid Build Coastguard Worker    struct ir3_liveness *live;
116*61046927SAndroid Build Coastguard Worker 
117*61046927SAndroid Build Coastguard Worker    const struct ir3_compiler *compiler;
118*61046927SAndroid Build Coastguard Worker 
119*61046927SAndroid Build Coastguard Worker    struct ra_spill_block_state *blocks;
120*61046927SAndroid Build Coastguard Worker 
121*61046927SAndroid Build Coastguard Worker    bool spilling;
122*61046927SAndroid Build Coastguard Worker 
123*61046927SAndroid Build Coastguard Worker    bool merged_regs;
124*61046927SAndroid Build Coastguard Worker };
125*61046927SAndroid Build Coastguard Worker 
126*61046927SAndroid Build Coastguard Worker static void
add_base_reg(struct ra_spill_ctx * ctx,struct ir3 * ir)127*61046927SAndroid Build Coastguard Worker add_base_reg(struct ra_spill_ctx *ctx, struct ir3 *ir)
128*61046927SAndroid Build Coastguard Worker {
129*61046927SAndroid Build Coastguard Worker    struct ir3_block *start = ir3_start_block(ir);
130*61046927SAndroid Build Coastguard Worker 
131*61046927SAndroid Build Coastguard Worker    /* We need to stick it after any meta instructions which need to be first. */
132*61046927SAndroid Build Coastguard Worker    struct ir3_instruction *after = NULL;
133*61046927SAndroid Build Coastguard Worker    foreach_instr (instr, &start->instr_list) {
134*61046927SAndroid Build Coastguard Worker       if (instr->opc != OPC_META_INPUT &&
135*61046927SAndroid Build Coastguard Worker           instr->opc != OPC_META_TEX_PREFETCH) {
136*61046927SAndroid Build Coastguard Worker          after = instr;
137*61046927SAndroid Build Coastguard Worker          break;
138*61046927SAndroid Build Coastguard Worker       }
139*61046927SAndroid Build Coastguard Worker    }
140*61046927SAndroid Build Coastguard Worker 
141*61046927SAndroid Build Coastguard Worker    struct ir3_instruction *mov = create_immed(start, 0);
142*61046927SAndroid Build Coastguard Worker 
143*61046927SAndroid Build Coastguard Worker    if (after)
144*61046927SAndroid Build Coastguard Worker       ir3_instr_move_before(mov, after);
145*61046927SAndroid Build Coastguard Worker 
146*61046927SAndroid Build Coastguard Worker    ctx->base_reg = mov->dsts[0];
147*61046927SAndroid Build Coastguard Worker 
148*61046927SAndroid Build Coastguard Worker    /* We don't create an interval, etc. for the base reg, so just lower the
149*61046927SAndroid Build Coastguard Worker     * register pressure limit to account for it. We assume it's always
150*61046927SAndroid Build Coastguard Worker     * available for simplicity.
151*61046927SAndroid Build Coastguard Worker     */
152*61046927SAndroid Build Coastguard Worker    ctx->limit_pressure.full -= reg_size(ctx->base_reg);
153*61046927SAndroid Build Coastguard Worker }
154*61046927SAndroid Build Coastguard Worker 
155*61046927SAndroid Build Coastguard Worker 
156*61046927SAndroid Build Coastguard Worker /* Compute the number of cycles per instruction used for next-use-distance
157*61046927SAndroid Build Coastguard Worker  * analysis. This is just approximate, obviously.
158*61046927SAndroid Build Coastguard Worker  */
159*61046927SAndroid Build Coastguard Worker static unsigned
instr_cycles(struct ir3_instruction * instr)160*61046927SAndroid Build Coastguard Worker instr_cycles(struct ir3_instruction *instr)
161*61046927SAndroid Build Coastguard Worker {
162*61046927SAndroid Build Coastguard Worker    if (instr->opc == OPC_META_PARALLEL_COPY) {
163*61046927SAndroid Build Coastguard Worker       unsigned cycles = 0;
164*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < instr->dsts_count; i++) {
165*61046927SAndroid Build Coastguard Worker          if (!instr->srcs[i]->def ||
166*61046927SAndroid Build Coastguard Worker              instr->srcs[i]->def->merge_set != instr->dsts[i]->merge_set) {
167*61046927SAndroid Build Coastguard Worker             cycles += reg_elems(instr->srcs[i]);
168*61046927SAndroid Build Coastguard Worker          }
169*61046927SAndroid Build Coastguard Worker       }
170*61046927SAndroid Build Coastguard Worker 
171*61046927SAndroid Build Coastguard Worker       return cycles;
172*61046927SAndroid Build Coastguard Worker    }
173*61046927SAndroid Build Coastguard Worker 
174*61046927SAndroid Build Coastguard Worker    if (instr->opc == OPC_META_COLLECT) {
175*61046927SAndroid Build Coastguard Worker       unsigned cycles = 0;
176*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < instr->srcs_count; i++) {
177*61046927SAndroid Build Coastguard Worker          if (!instr->srcs[i]->def ||
178*61046927SAndroid Build Coastguard Worker              instr->srcs[i]->def->merge_set != instr->dsts[0]->merge_set) {
179*61046927SAndroid Build Coastguard Worker             cycles++;
180*61046927SAndroid Build Coastguard Worker          }
181*61046927SAndroid Build Coastguard Worker       }
182*61046927SAndroid Build Coastguard Worker 
183*61046927SAndroid Build Coastguard Worker       return cycles;
184*61046927SAndroid Build Coastguard Worker    }
185*61046927SAndroid Build Coastguard Worker 
186*61046927SAndroid Build Coastguard Worker    if (is_meta(instr))
187*61046927SAndroid Build Coastguard Worker       return 0;
188*61046927SAndroid Build Coastguard Worker 
189*61046927SAndroid Build Coastguard Worker    return 1 + instr->repeat;
190*61046927SAndroid Build Coastguard Worker }
191*61046927SAndroid Build Coastguard Worker 
192*61046927SAndroid Build Coastguard Worker static bool
compute_block_next_distance(struct ra_spill_ctx * ctx,struct ir3_block * block,unsigned * tmp_next_use)193*61046927SAndroid Build Coastguard Worker compute_block_next_distance(struct ra_spill_ctx *ctx, struct ir3_block *block,
194*61046927SAndroid Build Coastguard Worker                             unsigned *tmp_next_use)
195*61046927SAndroid Build Coastguard Worker {
196*61046927SAndroid Build Coastguard Worker    struct ra_spill_block_state *state = &ctx->blocks[block->index];
197*61046927SAndroid Build Coastguard Worker    memcpy(tmp_next_use, state->next_use_end,
198*61046927SAndroid Build Coastguard Worker           ctx->live->definitions_count * sizeof(*tmp_next_use));
199*61046927SAndroid Build Coastguard Worker 
200*61046927SAndroid Build Coastguard Worker    unsigned cycle = state->cycles;
201*61046927SAndroid Build Coastguard Worker    foreach_instr_rev (instr, &block->instr_list) {
202*61046927SAndroid Build Coastguard Worker       ra_foreach_dst (dst, instr) {
203*61046927SAndroid Build Coastguard Worker          dst->next_use = tmp_next_use[dst->name];
204*61046927SAndroid Build Coastguard Worker       }
205*61046927SAndroid Build Coastguard Worker 
206*61046927SAndroid Build Coastguard Worker       ra_foreach_src (src, instr) {
207*61046927SAndroid Build Coastguard Worker          src->next_use = tmp_next_use[src->def->name];
208*61046927SAndroid Build Coastguard Worker       }
209*61046927SAndroid Build Coastguard Worker 
210*61046927SAndroid Build Coastguard Worker       cycle -= instr_cycles(instr);
211*61046927SAndroid Build Coastguard Worker 
212*61046927SAndroid Build Coastguard Worker       if (instr->opc == OPC_META_PARALLEL_COPY) {
213*61046927SAndroid Build Coastguard Worker          ra_foreach_src_n (src, i, instr) {
214*61046927SAndroid Build Coastguard Worker             if (src->def->merge_set == instr->dsts[i]->merge_set &&
215*61046927SAndroid Build Coastguard Worker                 src->def->merge_set_offset == instr->dsts[i]->merge_set_offset) {
216*61046927SAndroid Build Coastguard Worker                tmp_next_use[src->def->name] =
217*61046927SAndroid Build Coastguard Worker                   tmp_next_use[instr->dsts[i]->name];
218*61046927SAndroid Build Coastguard Worker             } else {
219*61046927SAndroid Build Coastguard Worker                tmp_next_use[src->def->name] = cycle;
220*61046927SAndroid Build Coastguard Worker             }
221*61046927SAndroid Build Coastguard Worker          }
222*61046927SAndroid Build Coastguard Worker       } else if (instr->opc != OPC_META_PHI) {
223*61046927SAndroid Build Coastguard Worker          ra_foreach_src (src, instr) {
224*61046927SAndroid Build Coastguard Worker             tmp_next_use[src->def->name] = cycle;
225*61046927SAndroid Build Coastguard Worker          }
226*61046927SAndroid Build Coastguard Worker       }
227*61046927SAndroid Build Coastguard Worker 
228*61046927SAndroid Build Coastguard Worker       ra_foreach_dst (dst, instr) {
229*61046927SAndroid Build Coastguard Worker          tmp_next_use[dst->name] = UINT_MAX;
230*61046927SAndroid Build Coastguard Worker       }
231*61046927SAndroid Build Coastguard Worker    }
232*61046927SAndroid Build Coastguard Worker 
233*61046927SAndroid Build Coastguard Worker    memcpy(state->next_use_start, tmp_next_use,
234*61046927SAndroid Build Coastguard Worker           ctx->live->definitions_count * sizeof(*tmp_next_use));
235*61046927SAndroid Build Coastguard Worker 
236*61046927SAndroid Build Coastguard Worker    bool progress = false;
237*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < block->predecessors_count; i++) {
238*61046927SAndroid Build Coastguard Worker       const struct ir3_block *pred = block->predecessors[i];
239*61046927SAndroid Build Coastguard Worker       struct ra_spill_block_state *pred_state = &ctx->blocks[pred->index];
240*61046927SAndroid Build Coastguard Worker 
241*61046927SAndroid Build Coastguard Worker       /* Add a large-enough distance in front of edges exiting the loop so that
242*61046927SAndroid Build Coastguard Worker        * variables that are live-through the loop but not used inside it are
243*61046927SAndroid Build Coastguard Worker        * prioritized for spilling, as per the paper. This just needs to be
244*61046927SAndroid Build Coastguard Worker        * larger than the longest path through the loop.
245*61046927SAndroid Build Coastguard Worker        */
246*61046927SAndroid Build Coastguard Worker       bool loop_exit = pred->loop_depth < block->loop_depth;
247*61046927SAndroid Build Coastguard Worker       unsigned block_distance = pred_state->cycles + (loop_exit ? 100000 : 0);
248*61046927SAndroid Build Coastguard Worker 
249*61046927SAndroid Build Coastguard Worker       for (unsigned j = 0; j < ctx->live->definitions_count; j++) {
250*61046927SAndroid Build Coastguard Worker          if (state->next_use_start[j] < UINT_MAX &&
251*61046927SAndroid Build Coastguard Worker              state->next_use_start[j] + block_distance <
252*61046927SAndroid Build Coastguard Worker              pred_state->next_use_end[j]) {
253*61046927SAndroid Build Coastguard Worker             pred_state->next_use_end[j] = state->next_use_start[j] +
254*61046927SAndroid Build Coastguard Worker                block_distance;
255*61046927SAndroid Build Coastguard Worker             progress = true;
256*61046927SAndroid Build Coastguard Worker          }
257*61046927SAndroid Build Coastguard Worker       }
258*61046927SAndroid Build Coastguard Worker 
259*61046927SAndroid Build Coastguard Worker       foreach_instr (phi, &block->instr_list) {
260*61046927SAndroid Build Coastguard Worker          if (phi->opc != OPC_META_PHI)
261*61046927SAndroid Build Coastguard Worker             break;
262*61046927SAndroid Build Coastguard Worker          if (!phi->srcs[i]->def)
263*61046927SAndroid Build Coastguard Worker             continue;
264*61046927SAndroid Build Coastguard Worker          unsigned src = phi->srcs[i]->def->name;
265*61046927SAndroid Build Coastguard Worker          if (phi->dsts[0]->next_use < UINT_MAX &&
266*61046927SAndroid Build Coastguard Worker              phi->dsts[0]->next_use + block_distance <
267*61046927SAndroid Build Coastguard Worker              pred_state->next_use_end[src]) {
268*61046927SAndroid Build Coastguard Worker             pred_state->next_use_end[src] = phi->dsts[0]->next_use +
269*61046927SAndroid Build Coastguard Worker                block_distance;
270*61046927SAndroid Build Coastguard Worker             progress = true;
271*61046927SAndroid Build Coastguard Worker          }
272*61046927SAndroid Build Coastguard Worker       }
273*61046927SAndroid Build Coastguard Worker    }
274*61046927SAndroid Build Coastguard Worker 
275*61046927SAndroid Build Coastguard Worker    return progress;
276*61046927SAndroid Build Coastguard Worker }
277*61046927SAndroid Build Coastguard Worker 
278*61046927SAndroid Build Coastguard Worker static void
compute_next_distance(struct ra_spill_ctx * ctx,struct ir3 * ir)279*61046927SAndroid Build Coastguard Worker compute_next_distance(struct ra_spill_ctx *ctx, struct ir3 *ir)
280*61046927SAndroid Build Coastguard Worker {
281*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < ctx->live->block_count; i++) {
282*61046927SAndroid Build Coastguard Worker       ctx->blocks[i].next_use_start =
283*61046927SAndroid Build Coastguard Worker          ralloc_array(ctx, unsigned, ctx->live->definitions_count);
284*61046927SAndroid Build Coastguard Worker       ctx->blocks[i].next_use_end =
285*61046927SAndroid Build Coastguard Worker          ralloc_array(ctx, unsigned, ctx->live->definitions_count);
286*61046927SAndroid Build Coastguard Worker 
287*61046927SAndroid Build Coastguard Worker       for (unsigned j = 0; j < ctx->live->definitions_count; j++) {
288*61046927SAndroid Build Coastguard Worker          ctx->blocks[i].next_use_start[j] = UINT_MAX;
289*61046927SAndroid Build Coastguard Worker          ctx->blocks[i].next_use_end[j] = UINT_MAX;
290*61046927SAndroid Build Coastguard Worker       }
291*61046927SAndroid Build Coastguard Worker    }
292*61046927SAndroid Build Coastguard Worker 
293*61046927SAndroid Build Coastguard Worker    foreach_block (block, &ir->block_list) {
294*61046927SAndroid Build Coastguard Worker       struct ra_spill_block_state *state = &ctx->blocks[block->index];
295*61046927SAndroid Build Coastguard Worker       state->cycles = 0;
296*61046927SAndroid Build Coastguard Worker       foreach_instr (instr, &block->instr_list) {
297*61046927SAndroid Build Coastguard Worker          state->cycles += instr_cycles(instr);
298*61046927SAndroid Build Coastguard Worker          foreach_dst (dst, instr) {
299*61046927SAndroid Build Coastguard Worker             dst->spill_slot = ~0;
300*61046927SAndroid Build Coastguard Worker          }
301*61046927SAndroid Build Coastguard Worker       }
302*61046927SAndroid Build Coastguard Worker    }
303*61046927SAndroid Build Coastguard Worker 
304*61046927SAndroid Build Coastguard Worker    unsigned *tmp_next_use =
305*61046927SAndroid Build Coastguard Worker       ralloc_array(ctx, unsigned, ctx->live->definitions_count);
306*61046927SAndroid Build Coastguard Worker 
307*61046927SAndroid Build Coastguard Worker    bool progress = true;
308*61046927SAndroid Build Coastguard Worker    while (progress) {
309*61046927SAndroid Build Coastguard Worker       progress = false;
310*61046927SAndroid Build Coastguard Worker       foreach_block_rev (block, &ir->block_list) {
311*61046927SAndroid Build Coastguard Worker          progress |= compute_block_next_distance(ctx, block, tmp_next_use);
312*61046927SAndroid Build Coastguard Worker       }
313*61046927SAndroid Build Coastguard Worker    }
314*61046927SAndroid Build Coastguard Worker }
315*61046927SAndroid Build Coastguard Worker 
316*61046927SAndroid Build Coastguard Worker static bool
can_rematerialize(struct ir3_register * reg)317*61046927SAndroid Build Coastguard Worker can_rematerialize(struct ir3_register *reg)
318*61046927SAndroid Build Coastguard Worker {
319*61046927SAndroid Build Coastguard Worker    if (reg->flags & IR3_REG_ARRAY)
320*61046927SAndroid Build Coastguard Worker       return false;
321*61046927SAndroid Build Coastguard Worker    if (reg->instr->opc != OPC_MOV)
322*61046927SAndroid Build Coastguard Worker       return false;
323*61046927SAndroid Build Coastguard Worker    if (!(reg->instr->srcs[0]->flags & (IR3_REG_IMMED | IR3_REG_CONST)))
324*61046927SAndroid Build Coastguard Worker       return false;
325*61046927SAndroid Build Coastguard Worker    if (reg->instr->srcs[0]->flags & IR3_REG_RELATIV)
326*61046927SAndroid Build Coastguard Worker       return false;
327*61046927SAndroid Build Coastguard Worker    return true;
328*61046927SAndroid Build Coastguard Worker }
329*61046927SAndroid Build Coastguard Worker 
330*61046927SAndroid Build Coastguard Worker static struct ir3_register *
rematerialize(struct ir3_register * reg,struct ir3_cursor cursor)331*61046927SAndroid Build Coastguard Worker rematerialize(struct ir3_register *reg, struct ir3_cursor cursor)
332*61046927SAndroid Build Coastguard Worker {
333*61046927SAndroid Build Coastguard Worker    d("rematerializing ssa_%u:%u", reg->instr->serialno, reg->name);
334*61046927SAndroid Build Coastguard Worker 
335*61046927SAndroid Build Coastguard Worker    struct ir3_instruction *remat =
336*61046927SAndroid Build Coastguard Worker       ir3_instr_create_at(cursor, reg->instr->opc, 1, reg->instr->srcs_count);
337*61046927SAndroid Build Coastguard Worker    struct ir3_register *dst = __ssa_dst(remat);
338*61046927SAndroid Build Coastguard Worker    dst->flags |= reg->flags & (IR3_REG_HALF | IR3_REG_ARRAY);
339*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < reg->instr->srcs_count; i++) {
340*61046927SAndroid Build Coastguard Worker       struct ir3_register *src =
341*61046927SAndroid Build Coastguard Worker          ir3_src_create(remat, INVALID_REG, reg->instr->srcs[i]->flags);
342*61046927SAndroid Build Coastguard Worker       *src = *reg->instr->srcs[i];
343*61046927SAndroid Build Coastguard Worker    }
344*61046927SAndroid Build Coastguard Worker 
345*61046927SAndroid Build Coastguard Worker    remat->cat1 = reg->instr->cat1;
346*61046927SAndroid Build Coastguard Worker 
347*61046927SAndroid Build Coastguard Worker    dst->merge_set = reg->merge_set;
348*61046927SAndroid Build Coastguard Worker    dst->merge_set_offset = reg->merge_set_offset;
349*61046927SAndroid Build Coastguard Worker    dst->interval_start = reg->interval_start;
350*61046927SAndroid Build Coastguard Worker    dst->interval_end = reg->interval_end;
351*61046927SAndroid Build Coastguard Worker    return dst;
352*61046927SAndroid Build Coastguard Worker }
353*61046927SAndroid Build Coastguard Worker 
354*61046927SAndroid Build Coastguard Worker static void
ra_spill_interval_init(struct ra_spill_interval * interval,struct ir3_register * reg)355*61046927SAndroid Build Coastguard Worker ra_spill_interval_init(struct ra_spill_interval *interval,
356*61046927SAndroid Build Coastguard Worker                        struct ir3_register *reg)
357*61046927SAndroid Build Coastguard Worker {
358*61046927SAndroid Build Coastguard Worker    ir3_reg_interval_init(&interval->interval, reg);
359*61046927SAndroid Build Coastguard Worker    interval->dst.flags = reg->flags;
360*61046927SAndroid Build Coastguard Worker    interval->dst.def = reg;
361*61046927SAndroid Build Coastguard Worker    interval->already_spilled = false;
362*61046927SAndroid Build Coastguard Worker    interval->needs_reload = false;
363*61046927SAndroid Build Coastguard Worker    interval->cant_spill = false;
364*61046927SAndroid Build Coastguard Worker    interval->can_rematerialize = can_rematerialize(reg);
365*61046927SAndroid Build Coastguard Worker }
366*61046927SAndroid Build Coastguard Worker 
367*61046927SAndroid Build Coastguard Worker static struct ra_spill_interval *
ir3_reg_interval_to_interval(struct ir3_reg_interval * interval)368*61046927SAndroid Build Coastguard Worker ir3_reg_interval_to_interval(struct ir3_reg_interval *interval)
369*61046927SAndroid Build Coastguard Worker {
370*61046927SAndroid Build Coastguard Worker    return rb_node_data(struct ra_spill_interval, interval, interval);
371*61046927SAndroid Build Coastguard Worker }
372*61046927SAndroid Build Coastguard Worker 
373*61046927SAndroid Build Coastguard Worker static struct ra_spill_interval *
ra_spill_interval_root(struct ra_spill_interval * interval)374*61046927SAndroid Build Coastguard Worker ra_spill_interval_root(struct ra_spill_interval *interval)
375*61046927SAndroid Build Coastguard Worker {
376*61046927SAndroid Build Coastguard Worker    struct ir3_reg_interval *ir3_interval = &interval->interval;
377*61046927SAndroid Build Coastguard Worker    while (ir3_interval->parent)
378*61046927SAndroid Build Coastguard Worker       ir3_interval = ir3_interval->parent;
379*61046927SAndroid Build Coastguard Worker    return ir3_reg_interval_to_interval(ir3_interval);
380*61046927SAndroid Build Coastguard Worker }
381*61046927SAndroid Build Coastguard Worker 
382*61046927SAndroid Build Coastguard Worker static struct ra_spill_ctx *
ir3_reg_ctx_to_ctx(struct ir3_reg_ctx * ctx)383*61046927SAndroid Build Coastguard Worker ir3_reg_ctx_to_ctx(struct ir3_reg_ctx *ctx)
384*61046927SAndroid Build Coastguard Worker {
385*61046927SAndroid Build Coastguard Worker    return rb_node_data(struct ra_spill_ctx, ctx, reg_ctx);
386*61046927SAndroid Build Coastguard Worker }
387*61046927SAndroid Build Coastguard Worker 
388*61046927SAndroid Build Coastguard Worker static int
spill_interval_cmp(const struct ra_spill_interval * a,const struct ra_spill_interval * b)389*61046927SAndroid Build Coastguard Worker spill_interval_cmp(const struct ra_spill_interval *a,
390*61046927SAndroid Build Coastguard Worker                    const struct ra_spill_interval *b)
391*61046927SAndroid Build Coastguard Worker {
392*61046927SAndroid Build Coastguard Worker    /* Prioritize intervals that we can rematerialize. */
393*61046927SAndroid Build Coastguard Worker    if (a->can_rematerialize && !b->can_rematerialize)
394*61046927SAndroid Build Coastguard Worker       return 1;
395*61046927SAndroid Build Coastguard Worker    if (!a->can_rematerialize && b->can_rematerialize)
396*61046927SAndroid Build Coastguard Worker       return -1;
397*61046927SAndroid Build Coastguard Worker 
398*61046927SAndroid Build Coastguard Worker    return a->next_use_distance - b->next_use_distance;
399*61046927SAndroid Build Coastguard Worker }
400*61046927SAndroid Build Coastguard Worker 
401*61046927SAndroid Build Coastguard Worker static int
ra_spill_interval_cmp(const struct rb_node * _a,const struct rb_node * _b)402*61046927SAndroid Build Coastguard Worker ra_spill_interval_cmp(const struct rb_node *_a, const struct rb_node *_b)
403*61046927SAndroid Build Coastguard Worker {
404*61046927SAndroid Build Coastguard Worker    const struct ra_spill_interval *a =
405*61046927SAndroid Build Coastguard Worker       rb_node_data(const struct ra_spill_interval, _a, node);
406*61046927SAndroid Build Coastguard Worker    const struct ra_spill_interval *b =
407*61046927SAndroid Build Coastguard Worker       rb_node_data(const struct ra_spill_interval, _b, node);
408*61046927SAndroid Build Coastguard Worker    return spill_interval_cmp(a, b);
409*61046927SAndroid Build Coastguard Worker }
410*61046927SAndroid Build Coastguard Worker 
411*61046927SAndroid Build Coastguard Worker static int
ra_spill_interval_half_cmp(const struct rb_node * _a,const struct rb_node * _b)412*61046927SAndroid Build Coastguard Worker ra_spill_interval_half_cmp(const struct rb_node *_a, const struct rb_node *_b)
413*61046927SAndroid Build Coastguard Worker {
414*61046927SAndroid Build Coastguard Worker    const struct ra_spill_interval *a =
415*61046927SAndroid Build Coastguard Worker       rb_node_data(const struct ra_spill_interval, _a, half_node);
416*61046927SAndroid Build Coastguard Worker    const struct ra_spill_interval *b =
417*61046927SAndroid Build Coastguard Worker       rb_node_data(const struct ra_spill_interval, _b, half_node);
418*61046927SAndroid Build Coastguard Worker    return spill_interval_cmp(a, b);
419*61046927SAndroid Build Coastguard Worker }
420*61046927SAndroid Build Coastguard Worker 
421*61046927SAndroid Build Coastguard Worker static void
interval_add(struct ir3_reg_ctx * _ctx,struct ir3_reg_interval * _interval)422*61046927SAndroid Build Coastguard Worker interval_add(struct ir3_reg_ctx *_ctx, struct ir3_reg_interval *_interval)
423*61046927SAndroid Build Coastguard Worker {
424*61046927SAndroid Build Coastguard Worker    struct ra_spill_interval *interval = ir3_reg_interval_to_interval(_interval);
425*61046927SAndroid Build Coastguard Worker    struct ra_spill_ctx *ctx = ir3_reg_ctx_to_ctx(_ctx);
426*61046927SAndroid Build Coastguard Worker 
427*61046927SAndroid Build Coastguard Worker    unsigned size = reg_size(interval->interval.reg);
428*61046927SAndroid Build Coastguard Worker    if (interval->interval.reg->flags & IR3_REG_SHARED) {
429*61046927SAndroid Build Coastguard Worker       ctx->cur_pressure.shared += size;
430*61046927SAndroid Build Coastguard Worker       if (interval->interval.reg->flags & IR3_REG_HALF)
431*61046927SAndroid Build Coastguard Worker          ctx->cur_pressure.shared_half += size;
432*61046927SAndroid Build Coastguard Worker    } else {
433*61046927SAndroid Build Coastguard Worker       if (interval->interval.reg->flags & IR3_REG_HALF) {
434*61046927SAndroid Build Coastguard Worker          ctx->cur_pressure.half += size;
435*61046927SAndroid Build Coastguard Worker          if (ctx->spilling) {
436*61046927SAndroid Build Coastguard Worker             rb_tree_insert(&ctx->half_live_intervals, &interval->half_node,
437*61046927SAndroid Build Coastguard Worker                            ra_spill_interval_half_cmp);
438*61046927SAndroid Build Coastguard Worker          }
439*61046927SAndroid Build Coastguard Worker       }
440*61046927SAndroid Build Coastguard Worker       if (ctx->merged_regs || !(interval->interval.reg->flags & IR3_REG_HALF)) {
441*61046927SAndroid Build Coastguard Worker          ctx->cur_pressure.full += size;
442*61046927SAndroid Build Coastguard Worker          if (ctx->spilling) {
443*61046927SAndroid Build Coastguard Worker             rb_tree_insert(&ctx->full_live_intervals, &interval->node,
444*61046927SAndroid Build Coastguard Worker                            ra_spill_interval_cmp);
445*61046927SAndroid Build Coastguard Worker          }
446*61046927SAndroid Build Coastguard Worker       }
447*61046927SAndroid Build Coastguard Worker    }
448*61046927SAndroid Build Coastguard Worker }
449*61046927SAndroid Build Coastguard Worker 
450*61046927SAndroid Build Coastguard Worker static void
interval_delete(struct ir3_reg_ctx * _ctx,struct ir3_reg_interval * _interval)451*61046927SAndroid Build Coastguard Worker interval_delete(struct ir3_reg_ctx *_ctx, struct ir3_reg_interval *_interval)
452*61046927SAndroid Build Coastguard Worker {
453*61046927SAndroid Build Coastguard Worker    struct ra_spill_interval *interval = ir3_reg_interval_to_interval(_interval);
454*61046927SAndroid Build Coastguard Worker    struct ra_spill_ctx *ctx = ir3_reg_ctx_to_ctx(_ctx);
455*61046927SAndroid Build Coastguard Worker 
456*61046927SAndroid Build Coastguard Worker    unsigned size = reg_size(interval->interval.reg);
457*61046927SAndroid Build Coastguard Worker    if (interval->interval.reg->flags & IR3_REG_SHARED) {
458*61046927SAndroid Build Coastguard Worker       ctx->cur_pressure.shared -= size;
459*61046927SAndroid Build Coastguard Worker       if (interval->interval.reg->flags & IR3_REG_HALF)
460*61046927SAndroid Build Coastguard Worker          ctx->cur_pressure.shared_half -= size;
461*61046927SAndroid Build Coastguard Worker    } else {
462*61046927SAndroid Build Coastguard Worker       if (interval->interval.reg->flags & IR3_REG_HALF) {
463*61046927SAndroid Build Coastguard Worker          ctx->cur_pressure.half -= size;
464*61046927SAndroid Build Coastguard Worker          if (ctx->spilling) {
465*61046927SAndroid Build Coastguard Worker             rb_tree_remove(&ctx->half_live_intervals, &interval->half_node);
466*61046927SAndroid Build Coastguard Worker          }
467*61046927SAndroid Build Coastguard Worker       }
468*61046927SAndroid Build Coastguard Worker       if (ctx->merged_regs || !(interval->interval.reg->flags & IR3_REG_HALF)) {
469*61046927SAndroid Build Coastguard Worker          ctx->cur_pressure.full -= size;
470*61046927SAndroid Build Coastguard Worker          if (ctx->spilling) {
471*61046927SAndroid Build Coastguard Worker             rb_tree_remove(&ctx->full_live_intervals, &interval->node);
472*61046927SAndroid Build Coastguard Worker          }
473*61046927SAndroid Build Coastguard Worker       }
474*61046927SAndroid Build Coastguard Worker    }
475*61046927SAndroid Build Coastguard Worker }
476*61046927SAndroid Build Coastguard Worker 
477*61046927SAndroid Build Coastguard Worker static void
interval_readd(struct ir3_reg_ctx * _ctx,struct ir3_reg_interval * _parent,struct ir3_reg_interval * _child)478*61046927SAndroid Build Coastguard Worker interval_readd(struct ir3_reg_ctx *_ctx, struct ir3_reg_interval *_parent,
479*61046927SAndroid Build Coastguard Worker                struct ir3_reg_interval *_child)
480*61046927SAndroid Build Coastguard Worker {
481*61046927SAndroid Build Coastguard Worker    interval_add(_ctx, _child);
482*61046927SAndroid Build Coastguard Worker }
483*61046927SAndroid Build Coastguard Worker 
484*61046927SAndroid Build Coastguard Worker static void
spill_ctx_init(struct ra_spill_ctx * ctx,struct ir3_shader_variant * v,struct ir3_liveness * live)485*61046927SAndroid Build Coastguard Worker spill_ctx_init(struct ra_spill_ctx *ctx, struct ir3_shader_variant *v,
486*61046927SAndroid Build Coastguard Worker                struct ir3_liveness *live)
487*61046927SAndroid Build Coastguard Worker {
488*61046927SAndroid Build Coastguard Worker    ctx->live = live;
489*61046927SAndroid Build Coastguard Worker    ctx->intervals = ralloc_array(ctx, struct ra_spill_interval *,
490*61046927SAndroid Build Coastguard Worker                                  ctx->live->definitions_count);
491*61046927SAndroid Build Coastguard Worker    struct ra_spill_interval *intervals =
492*61046927SAndroid Build Coastguard Worker       rzalloc_array(ctx, struct ra_spill_interval,
493*61046927SAndroid Build Coastguard Worker                     ctx->live->definitions_count);
494*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < ctx->live->definitions_count; i++)
495*61046927SAndroid Build Coastguard Worker       ctx->intervals[i] = &intervals[i];
496*61046927SAndroid Build Coastguard Worker 
497*61046927SAndroid Build Coastguard Worker    ctx->intervals_count = ctx->live->definitions_count;
498*61046927SAndroid Build Coastguard Worker    ctx->compiler = v->compiler;
499*61046927SAndroid Build Coastguard Worker    ctx->merged_regs = v->mergedregs;
500*61046927SAndroid Build Coastguard Worker 
501*61046927SAndroid Build Coastguard Worker    rb_tree_init(&ctx->reg_ctx.intervals);
502*61046927SAndroid Build Coastguard Worker    ctx->reg_ctx.interval_add = interval_add;
503*61046927SAndroid Build Coastguard Worker    ctx->reg_ctx.interval_delete = interval_delete;
504*61046927SAndroid Build Coastguard Worker    ctx->reg_ctx.interval_readd = interval_readd;
505*61046927SAndroid Build Coastguard Worker }
506*61046927SAndroid Build Coastguard Worker 
507*61046927SAndroid Build Coastguard Worker static void
ra_spill_ctx_insert(struct ra_spill_ctx * ctx,struct ra_spill_interval * interval)508*61046927SAndroid Build Coastguard Worker ra_spill_ctx_insert(struct ra_spill_ctx *ctx,
509*61046927SAndroid Build Coastguard Worker                     struct ra_spill_interval *interval)
510*61046927SAndroid Build Coastguard Worker {
511*61046927SAndroid Build Coastguard Worker    ir3_reg_interval_insert(&ctx->reg_ctx, &interval->interval);
512*61046927SAndroid Build Coastguard Worker }
513*61046927SAndroid Build Coastguard Worker 
514*61046927SAndroid Build Coastguard Worker static void
ra_spill_ctx_remove(struct ra_spill_ctx * ctx,struct ra_spill_interval * interval)515*61046927SAndroid Build Coastguard Worker ra_spill_ctx_remove(struct ra_spill_ctx *ctx,
516*61046927SAndroid Build Coastguard Worker                     struct ra_spill_interval *interval)
517*61046927SAndroid Build Coastguard Worker {
518*61046927SAndroid Build Coastguard Worker    ir3_reg_interval_remove(&ctx->reg_ctx, &interval->interval);
519*61046927SAndroid Build Coastguard Worker }
520*61046927SAndroid Build Coastguard Worker 
521*61046927SAndroid Build Coastguard Worker static void
init_dst(struct ra_spill_ctx * ctx,struct ir3_register * dst)522*61046927SAndroid Build Coastguard Worker init_dst(struct ra_spill_ctx *ctx, struct ir3_register *dst)
523*61046927SAndroid Build Coastguard Worker {
524*61046927SAndroid Build Coastguard Worker    struct ra_spill_interval *interval = ctx->intervals[dst->name];
525*61046927SAndroid Build Coastguard Worker    ra_spill_interval_init(interval, dst);
526*61046927SAndroid Build Coastguard Worker    if (ctx->spilling) {
527*61046927SAndroid Build Coastguard Worker       interval->next_use_distance = dst->next_use;
528*61046927SAndroid Build Coastguard Worker 
529*61046927SAndroid Build Coastguard Worker       /* We only need to keep track of used-ness if this value may be
530*61046927SAndroid Build Coastguard Worker        * rematerialized. This also keeps us from nuking things that may be
531*61046927SAndroid Build Coastguard Worker        * in the keeps list (e.g. atomics, input splits).
532*61046927SAndroid Build Coastguard Worker        */
533*61046927SAndroid Build Coastguard Worker       if (interval->can_rematerialize)
534*61046927SAndroid Build Coastguard Worker          dst->instr->flags |= IR3_INSTR_UNUSED;
535*61046927SAndroid Build Coastguard Worker    }
536*61046927SAndroid Build Coastguard Worker }
537*61046927SAndroid Build Coastguard Worker 
538*61046927SAndroid Build Coastguard Worker static void
insert_dst(struct ra_spill_ctx * ctx,struct ir3_register * dst)539*61046927SAndroid Build Coastguard Worker insert_dst(struct ra_spill_ctx *ctx, struct ir3_register *dst)
540*61046927SAndroid Build Coastguard Worker {
541*61046927SAndroid Build Coastguard Worker    struct ra_spill_interval *interval = ctx->intervals[dst->name];
542*61046927SAndroid Build Coastguard Worker    if (interval->interval.inserted)
543*61046927SAndroid Build Coastguard Worker       return;
544*61046927SAndroid Build Coastguard Worker 
545*61046927SAndroid Build Coastguard Worker    ra_spill_ctx_insert(ctx, interval);
546*61046927SAndroid Build Coastguard Worker    interval->cant_spill = true;
547*61046927SAndroid Build Coastguard Worker 
548*61046927SAndroid Build Coastguard Worker    /* For precolored inputs, make sure we leave enough registers to allow for
549*61046927SAndroid Build Coastguard Worker     * holes in the inputs. It can happen that the binning shader has a lower
550*61046927SAndroid Build Coastguard Worker     * register pressure than the main shader, but the main shader decided to
551*61046927SAndroid Build Coastguard Worker     * add holes between the inputs which means that the binning shader has a
552*61046927SAndroid Build Coastguard Worker     * higher register demand.
553*61046927SAndroid Build Coastguard Worker     */
554*61046927SAndroid Build Coastguard Worker    if (dst->instr->opc == OPC_META_INPUT && dst->num != INVALID_REG) {
555*61046927SAndroid Build Coastguard Worker       physreg_t physreg = ra_reg_get_physreg(dst);
556*61046927SAndroid Build Coastguard Worker       physreg_t max = physreg + reg_size(dst);
557*61046927SAndroid Build Coastguard Worker 
558*61046927SAndroid Build Coastguard Worker       if (interval->interval.reg->flags & IR3_REG_SHARED) {
559*61046927SAndroid Build Coastguard Worker          ctx->max_pressure.shared = MAX2(ctx->max_pressure.shared, max);
560*61046927SAndroid Build Coastguard Worker          if (interval->interval.reg->flags & IR3_REG_HALF) {
561*61046927SAndroid Build Coastguard Worker             ctx->max_pressure.shared_half = MAX2(ctx->max_pressure.shared_half,
562*61046927SAndroid Build Coastguard Worker                                                  max);
563*61046927SAndroid Build Coastguard Worker          }
564*61046927SAndroid Build Coastguard Worker       } else if (interval->interval.reg->flags & IR3_REG_HALF) {
565*61046927SAndroid Build Coastguard Worker          ctx->max_pressure.half = MAX2(ctx->max_pressure.half, max);
566*61046927SAndroid Build Coastguard Worker       } else {
567*61046927SAndroid Build Coastguard Worker          ctx->max_pressure.full = MAX2(ctx->max_pressure.full, max);
568*61046927SAndroid Build Coastguard Worker       }
569*61046927SAndroid Build Coastguard Worker    }
570*61046927SAndroid Build Coastguard Worker }
571*61046927SAndroid Build Coastguard Worker 
572*61046927SAndroid Build Coastguard Worker static void
insert_src(struct ra_spill_ctx * ctx,struct ir3_register * src)573*61046927SAndroid Build Coastguard Worker insert_src(struct ra_spill_ctx *ctx, struct ir3_register *src)
574*61046927SAndroid Build Coastguard Worker {
575*61046927SAndroid Build Coastguard Worker    struct ra_spill_interval *interval = ctx->intervals[src->def->name];
576*61046927SAndroid Build Coastguard Worker 
577*61046927SAndroid Build Coastguard Worker    if (!interval->interval.inserted) {
578*61046927SAndroid Build Coastguard Worker       ra_spill_ctx_insert(ctx, interval);
579*61046927SAndroid Build Coastguard Worker       interval->needs_reload = true;
580*61046927SAndroid Build Coastguard Worker       interval->already_spilled = true;
581*61046927SAndroid Build Coastguard Worker    }
582*61046927SAndroid Build Coastguard Worker 
583*61046927SAndroid Build Coastguard Worker    ra_spill_interval_root(interval)->cant_spill = true;
584*61046927SAndroid Build Coastguard Worker 
585*61046927SAndroid Build Coastguard Worker }
586*61046927SAndroid Build Coastguard Worker 
587*61046927SAndroid Build Coastguard Worker static void
remove_src_early(struct ra_spill_ctx * ctx,struct ir3_instruction * instr,struct ir3_register * src)588*61046927SAndroid Build Coastguard Worker remove_src_early(struct ra_spill_ctx *ctx, struct ir3_instruction *instr,
589*61046927SAndroid Build Coastguard Worker                  struct ir3_register *src)
590*61046927SAndroid Build Coastguard Worker {
591*61046927SAndroid Build Coastguard Worker    struct ra_spill_interval *interval = ctx->intervals[src->def->name];
592*61046927SAndroid Build Coastguard Worker 
593*61046927SAndroid Build Coastguard Worker    if (ctx->spilling) {
594*61046927SAndroid Build Coastguard Worker       /* It might happen that a collect that cannot be coalesced with one of its
595*61046927SAndroid Build Coastguard Worker        * sources while spilling can be coalesced with it afterwards. In this
596*61046927SAndroid Build Coastguard Worker        * case, we might be able to remove it here during spilling but not
597*61046927SAndroid Build Coastguard Worker        * afterwards (because it may have a child interval). If this happens, we
598*61046927SAndroid Build Coastguard Worker        * could end up with a register pressure that is higher after spilling
599*61046927SAndroid Build Coastguard Worker        * than before. Prevent this by never removing collects early while
600*61046927SAndroid Build Coastguard Worker        * spilling.
601*61046927SAndroid Build Coastguard Worker        */
602*61046927SAndroid Build Coastguard Worker       if (src->def->instr->opc == OPC_META_COLLECT)
603*61046927SAndroid Build Coastguard Worker          return;
604*61046927SAndroid Build Coastguard Worker    }
605*61046927SAndroid Build Coastguard Worker 
606*61046927SAndroid Build Coastguard Worker    if (!interval->interval.inserted || interval->interval.parent ||
607*61046927SAndroid Build Coastguard Worker        !rb_tree_is_empty(&interval->interval.children))
608*61046927SAndroid Build Coastguard Worker       return;
609*61046927SAndroid Build Coastguard Worker 
610*61046927SAndroid Build Coastguard Worker    ra_spill_ctx_remove(ctx, interval);
611*61046927SAndroid Build Coastguard Worker }
612*61046927SAndroid Build Coastguard Worker 
613*61046927SAndroid Build Coastguard Worker static void
remove_src(struct ra_spill_ctx * ctx,struct ir3_instruction * instr,struct ir3_register * src)614*61046927SAndroid Build Coastguard Worker remove_src(struct ra_spill_ctx *ctx, struct ir3_instruction *instr,
615*61046927SAndroid Build Coastguard Worker            struct ir3_register *src)
616*61046927SAndroid Build Coastguard Worker {
617*61046927SAndroid Build Coastguard Worker    struct ra_spill_interval *interval = ctx->intervals[src->def->name];
618*61046927SAndroid Build Coastguard Worker 
619*61046927SAndroid Build Coastguard Worker    if (!interval->interval.inserted)
620*61046927SAndroid Build Coastguard Worker       return;
621*61046927SAndroid Build Coastguard Worker 
622*61046927SAndroid Build Coastguard Worker    ra_spill_ctx_remove(ctx, interval);
623*61046927SAndroid Build Coastguard Worker }
624*61046927SAndroid Build Coastguard Worker 
625*61046927SAndroid Build Coastguard Worker static void
finish_dst(struct ra_spill_ctx * ctx,struct ir3_register * dst)626*61046927SAndroid Build Coastguard Worker finish_dst(struct ra_spill_ctx *ctx, struct ir3_register *dst)
627*61046927SAndroid Build Coastguard Worker {
628*61046927SAndroid Build Coastguard Worker    struct ra_spill_interval *interval = ctx->intervals[dst->name];
629*61046927SAndroid Build Coastguard Worker    interval->cant_spill = false;
630*61046927SAndroid Build Coastguard Worker }
631*61046927SAndroid Build Coastguard Worker 
632*61046927SAndroid Build Coastguard Worker static void
remove_dst(struct ra_spill_ctx * ctx,struct ir3_register * dst)633*61046927SAndroid Build Coastguard Worker remove_dst(struct ra_spill_ctx *ctx, struct ir3_register *dst)
634*61046927SAndroid Build Coastguard Worker {
635*61046927SAndroid Build Coastguard Worker    struct ra_spill_interval *interval = ctx->intervals[dst->name];
636*61046927SAndroid Build Coastguard Worker 
637*61046927SAndroid Build Coastguard Worker    if (!interval->interval.inserted)
638*61046927SAndroid Build Coastguard Worker       return;
639*61046927SAndroid Build Coastguard Worker 
640*61046927SAndroid Build Coastguard Worker    ra_spill_ctx_remove(ctx, interval);
641*61046927SAndroid Build Coastguard Worker }
642*61046927SAndroid Build Coastguard Worker 
643*61046927SAndroid Build Coastguard Worker static void
update_src_next_use(struct ra_spill_ctx * ctx,struct ir3_register * src)644*61046927SAndroid Build Coastguard Worker update_src_next_use(struct ra_spill_ctx *ctx, struct ir3_register *src)
645*61046927SAndroid Build Coastguard Worker {
646*61046927SAndroid Build Coastguard Worker    struct ra_spill_interval *interval = ctx->intervals[src->def->name];
647*61046927SAndroid Build Coastguard Worker 
648*61046927SAndroid Build Coastguard Worker    assert(interval->interval.inserted);
649*61046927SAndroid Build Coastguard Worker 
650*61046927SAndroid Build Coastguard Worker    interval->next_use_distance = src->next_use;
651*61046927SAndroid Build Coastguard Worker 
652*61046927SAndroid Build Coastguard Worker    /* If this node is inserted in one of the trees, then it needs to be resorted
653*61046927SAndroid Build Coastguard Worker     * as its key has changed.
654*61046927SAndroid Build Coastguard Worker     */
655*61046927SAndroid Build Coastguard Worker    if (!interval->interval.parent && !(src->flags & IR3_REG_SHARED)) {
656*61046927SAndroid Build Coastguard Worker       if (src->flags & IR3_REG_HALF) {
657*61046927SAndroid Build Coastguard Worker          rb_tree_remove(&ctx->half_live_intervals, &interval->half_node);
658*61046927SAndroid Build Coastguard Worker          rb_tree_insert(&ctx->half_live_intervals, &interval->half_node,
659*61046927SAndroid Build Coastguard Worker                         ra_spill_interval_half_cmp);
660*61046927SAndroid Build Coastguard Worker       }
661*61046927SAndroid Build Coastguard Worker       if (ctx->merged_regs || !(src->flags & IR3_REG_HALF)) {
662*61046927SAndroid Build Coastguard Worker          rb_tree_remove(&ctx->full_live_intervals, &interval->node);
663*61046927SAndroid Build Coastguard Worker          rb_tree_insert(&ctx->full_live_intervals, &interval->node,
664*61046927SAndroid Build Coastguard Worker                         ra_spill_interval_cmp);
665*61046927SAndroid Build Coastguard Worker       }
666*61046927SAndroid Build Coastguard Worker    }
667*61046927SAndroid Build Coastguard Worker }
668*61046927SAndroid Build Coastguard Worker 
669*61046927SAndroid Build Coastguard Worker static unsigned
get_spill_slot(struct ra_spill_ctx * ctx,struct ir3_register * reg)670*61046927SAndroid Build Coastguard Worker get_spill_slot(struct ra_spill_ctx *ctx, struct ir3_register *reg)
671*61046927SAndroid Build Coastguard Worker {
672*61046927SAndroid Build Coastguard Worker    if (reg->merge_set) {
673*61046927SAndroid Build Coastguard Worker       if (reg->merge_set->spill_slot == ~0) {
674*61046927SAndroid Build Coastguard Worker          reg->merge_set->spill_slot = ALIGN_POT(ctx->spill_slot,
675*61046927SAndroid Build Coastguard Worker                                                 reg->merge_set->alignment * 2);
676*61046927SAndroid Build Coastguard Worker          ctx->spill_slot = reg->merge_set->spill_slot + reg->merge_set->size * 2;
677*61046927SAndroid Build Coastguard Worker       }
678*61046927SAndroid Build Coastguard Worker       return reg->merge_set->spill_slot + reg->merge_set_offset * 2;
679*61046927SAndroid Build Coastguard Worker    } else {
680*61046927SAndroid Build Coastguard Worker       if (reg->spill_slot == ~0) {
681*61046927SAndroid Build Coastguard Worker          reg->spill_slot = ALIGN_POT(ctx->spill_slot, reg_elem_size(reg) * 2);
682*61046927SAndroid Build Coastguard Worker          ctx->spill_slot = reg->spill_slot + reg_size(reg) * 2;
683*61046927SAndroid Build Coastguard Worker       }
684*61046927SAndroid Build Coastguard Worker       return reg->spill_slot;
685*61046927SAndroid Build Coastguard Worker    }
686*61046927SAndroid Build Coastguard Worker }
687*61046927SAndroid Build Coastguard Worker 
688*61046927SAndroid Build Coastguard Worker static void
set_src_val(struct ir3_register * src,const struct reg_or_immed * val)689*61046927SAndroid Build Coastguard Worker set_src_val(struct ir3_register *src, const struct reg_or_immed *val)
690*61046927SAndroid Build Coastguard Worker {
691*61046927SAndroid Build Coastguard Worker    if (val->flags & IR3_REG_IMMED) {
692*61046927SAndroid Build Coastguard Worker       src->flags = IR3_REG_IMMED | (val->flags & IR3_REG_HALF);
693*61046927SAndroid Build Coastguard Worker       src->uim_val = val->uimm;
694*61046927SAndroid Build Coastguard Worker       src->def = NULL;
695*61046927SAndroid Build Coastguard Worker    } else if (val->flags & IR3_REG_CONST) {
696*61046927SAndroid Build Coastguard Worker       src->flags = IR3_REG_CONST | (val->flags & IR3_REG_HALF);
697*61046927SAndroid Build Coastguard Worker       src->num = val->const_num;
698*61046927SAndroid Build Coastguard Worker       src->def = NULL;
699*61046927SAndroid Build Coastguard Worker    } else {
700*61046927SAndroid Build Coastguard Worker       src->def = val->def;
701*61046927SAndroid Build Coastguard Worker       val->def->instr->flags &= ~IR3_INSTR_UNUSED;
702*61046927SAndroid Build Coastguard Worker    }
703*61046927SAndroid Build Coastguard Worker }
704*61046927SAndroid Build Coastguard Worker 
705*61046927SAndroid Build Coastguard Worker static struct ir3_register *
materialize_pcopy_src(const struct reg_or_immed * src,struct ir3_builder * builder)706*61046927SAndroid Build Coastguard Worker materialize_pcopy_src(const struct reg_or_immed *src,
707*61046927SAndroid Build Coastguard Worker                       struct ir3_builder *builder)
708*61046927SAndroid Build Coastguard Worker {
709*61046927SAndroid Build Coastguard Worker    struct ir3_instruction *mov = ir3_build_instr(builder, OPC_MOV, 1, 1);
710*61046927SAndroid Build Coastguard Worker    struct ir3_register *dst = __ssa_dst(mov);
711*61046927SAndroid Build Coastguard Worker    dst->flags |= src->flags & IR3_REG_HALF;
712*61046927SAndroid Build Coastguard Worker    struct ir3_register *mov_src = ir3_src_create(mov, INVALID_REG, src->flags);
713*61046927SAndroid Build Coastguard Worker    set_src_val(mov_src, src);
714*61046927SAndroid Build Coastguard Worker    mov->cat1.src_type = mov->cat1.dst_type =
715*61046927SAndroid Build Coastguard Worker       (src->flags & IR3_REG_HALF) ? TYPE_U16 : TYPE_U32;
716*61046927SAndroid Build Coastguard Worker    return dst;
717*61046927SAndroid Build Coastguard Worker }
718*61046927SAndroid Build Coastguard Worker 
719*61046927SAndroid Build Coastguard Worker static void
spill(struct ra_spill_ctx * ctx,const struct reg_or_immed * val,unsigned spill_slot,struct ir3_cursor cursor)720*61046927SAndroid Build Coastguard Worker spill(struct ra_spill_ctx *ctx, const struct reg_or_immed *val,
721*61046927SAndroid Build Coastguard Worker       unsigned spill_slot, struct ir3_cursor cursor)
722*61046927SAndroid Build Coastguard Worker {
723*61046927SAndroid Build Coastguard Worker    struct ir3_register *reg;
724*61046927SAndroid Build Coastguard Worker    struct ir3_builder builder = ir3_builder_at(cursor);
725*61046927SAndroid Build Coastguard Worker 
726*61046927SAndroid Build Coastguard Worker    /* If spilling an immed/const pcopy src, we need to actually materialize it
727*61046927SAndroid Build Coastguard Worker     * first with a mov.
728*61046927SAndroid Build Coastguard Worker     */
729*61046927SAndroid Build Coastguard Worker    if (val->flags & (IR3_REG_CONST | IR3_REG_IMMED)) {
730*61046927SAndroid Build Coastguard Worker       reg = materialize_pcopy_src(val, &builder);
731*61046927SAndroid Build Coastguard Worker    } else {
732*61046927SAndroid Build Coastguard Worker       reg = val->def;
733*61046927SAndroid Build Coastguard Worker       reg->instr->flags &= ~IR3_INSTR_UNUSED;
734*61046927SAndroid Build Coastguard Worker    }
735*61046927SAndroid Build Coastguard Worker 
736*61046927SAndroid Build Coastguard Worker    d("spilling ssa_%u:%u to %u", reg->instr->serialno, reg->name,
737*61046927SAndroid Build Coastguard Worker      spill_slot);
738*61046927SAndroid Build Coastguard Worker 
739*61046927SAndroid Build Coastguard Worker    unsigned elems = reg_elems(reg);
740*61046927SAndroid Build Coastguard Worker    struct ir3_instruction *spill =
741*61046927SAndroid Build Coastguard Worker       ir3_build_instr(&builder, OPC_SPILL_MACRO, 0, 3);
742*61046927SAndroid Build Coastguard Worker    ir3_src_create(spill, INVALID_REG, ctx->base_reg->flags)->def = ctx->base_reg;
743*61046927SAndroid Build Coastguard Worker    unsigned src_flags = reg->flags & (IR3_REG_HALF | IR3_REG_IMMED |
744*61046927SAndroid Build Coastguard Worker                                       IR3_REG_CONST | IR3_REG_SSA |
745*61046927SAndroid Build Coastguard Worker                                       IR3_REG_ARRAY);
746*61046927SAndroid Build Coastguard Worker    struct ir3_register *src = ir3_src_create(spill, INVALID_REG, src_flags);
747*61046927SAndroid Build Coastguard Worker    ir3_src_create(spill, INVALID_REG, IR3_REG_IMMED)->uim_val = elems;
748*61046927SAndroid Build Coastguard Worker    spill->cat6.dst_offset = spill_slot;
749*61046927SAndroid Build Coastguard Worker    spill->cat6.type = (reg->flags & IR3_REG_HALF) ? TYPE_U16 : TYPE_U32;
750*61046927SAndroid Build Coastguard Worker 
751*61046927SAndroid Build Coastguard Worker    src->def = reg;
752*61046927SAndroid Build Coastguard Worker    if (reg->flags & IR3_REG_ARRAY) {
753*61046927SAndroid Build Coastguard Worker       src->size = reg->size;
754*61046927SAndroid Build Coastguard Worker       src->array.id = reg->array.id;
755*61046927SAndroid Build Coastguard Worker       src->array.offset = 0;
756*61046927SAndroid Build Coastguard Worker    } else {
757*61046927SAndroid Build Coastguard Worker       src->wrmask = reg->wrmask;
758*61046927SAndroid Build Coastguard Worker    }
759*61046927SAndroid Build Coastguard Worker }
760*61046927SAndroid Build Coastguard Worker 
761*61046927SAndroid Build Coastguard Worker static void
spill_interval(struct ra_spill_ctx * ctx,struct ra_spill_interval * interval,struct ir3_cursor cursor)762*61046927SAndroid Build Coastguard Worker spill_interval(struct ra_spill_ctx *ctx, struct ra_spill_interval *interval,
763*61046927SAndroid Build Coastguard Worker                struct ir3_cursor cursor)
764*61046927SAndroid Build Coastguard Worker {
765*61046927SAndroid Build Coastguard Worker    if (interval->can_rematerialize && !interval->interval.reg->merge_set)
766*61046927SAndroid Build Coastguard Worker       return;
767*61046927SAndroid Build Coastguard Worker 
768*61046927SAndroid Build Coastguard Worker    spill(ctx, &interval->dst, get_spill_slot(ctx, interval->interval.reg),
769*61046927SAndroid Build Coastguard Worker          cursor);
770*61046927SAndroid Build Coastguard Worker }
771*61046927SAndroid Build Coastguard Worker 
772*61046927SAndroid Build Coastguard Worker /* This is similar to "limit" in the paper. */
773*61046927SAndroid Build Coastguard Worker static void
limit(struct ra_spill_ctx * ctx,struct ir3_cursor cursor)774*61046927SAndroid Build Coastguard Worker limit(struct ra_spill_ctx *ctx, struct ir3_cursor cursor)
775*61046927SAndroid Build Coastguard Worker {
776*61046927SAndroid Build Coastguard Worker    if (ctx->cur_pressure.half > ctx->limit_pressure.half) {
777*61046927SAndroid Build Coastguard Worker       d("cur half pressure %u exceeds %u", ctx->cur_pressure.half,
778*61046927SAndroid Build Coastguard Worker         ctx->limit_pressure.half);
779*61046927SAndroid Build Coastguard Worker       rb_tree_foreach_safe (struct ra_spill_interval, interval,
780*61046927SAndroid Build Coastguard Worker                             &ctx->half_live_intervals, half_node) {
781*61046927SAndroid Build Coastguard Worker          d("trying ssa_%u:%u", interval->interval.reg->instr->serialno,
782*61046927SAndroid Build Coastguard Worker            interval->interval.reg->name);
783*61046927SAndroid Build Coastguard Worker          if (!interval->cant_spill) {
784*61046927SAndroid Build Coastguard Worker             if (!interval->already_spilled)
785*61046927SAndroid Build Coastguard Worker                spill_interval(ctx, interval, cursor);
786*61046927SAndroid Build Coastguard Worker             ir3_reg_interval_remove_all(&ctx->reg_ctx, &interval->interval);
787*61046927SAndroid Build Coastguard Worker             if (ctx->cur_pressure.half <= ctx->limit_pressure.half)
788*61046927SAndroid Build Coastguard Worker                break;
789*61046927SAndroid Build Coastguard Worker          }
790*61046927SAndroid Build Coastguard Worker       }
791*61046927SAndroid Build Coastguard Worker 
792*61046927SAndroid Build Coastguard Worker       assert(ctx->cur_pressure.half <= ctx->limit_pressure.half);
793*61046927SAndroid Build Coastguard Worker    }
794*61046927SAndroid Build Coastguard Worker 
795*61046927SAndroid Build Coastguard Worker    if (ctx->cur_pressure.full > ctx->limit_pressure.full) {
796*61046927SAndroid Build Coastguard Worker       d("cur full pressure %u exceeds %u", ctx->cur_pressure.full,
797*61046927SAndroid Build Coastguard Worker         ctx->limit_pressure.full);
798*61046927SAndroid Build Coastguard Worker       rb_tree_foreach_safe (struct ra_spill_interval, interval,
799*61046927SAndroid Build Coastguard Worker                             &ctx->full_live_intervals, node) {
800*61046927SAndroid Build Coastguard Worker          d("trying ssa_%u:%u", interval->interval.reg->instr->serialno,
801*61046927SAndroid Build Coastguard Worker            interval->interval.reg->name);
802*61046927SAndroid Build Coastguard Worker          if (!interval->cant_spill) {
803*61046927SAndroid Build Coastguard Worker             if (!interval->already_spilled)
804*61046927SAndroid Build Coastguard Worker                spill_interval(ctx, interval, cursor);
805*61046927SAndroid Build Coastguard Worker             ir3_reg_interval_remove_all(&ctx->reg_ctx, &interval->interval);
806*61046927SAndroid Build Coastguard Worker             if (ctx->cur_pressure.full <= ctx->limit_pressure.full)
807*61046927SAndroid Build Coastguard Worker                break;
808*61046927SAndroid Build Coastguard Worker          } else {
809*61046927SAndroid Build Coastguard Worker             d("can't spill");
810*61046927SAndroid Build Coastguard Worker          }
811*61046927SAndroid Build Coastguard Worker       }
812*61046927SAndroid Build Coastguard Worker 
813*61046927SAndroid Build Coastguard Worker       assert(ctx->cur_pressure.full <= ctx->limit_pressure.full);
814*61046927SAndroid Build Coastguard Worker    }
815*61046927SAndroid Build Coastguard Worker }
816*61046927SAndroid Build Coastguard Worker 
817*61046927SAndroid Build Coastguard Worker /* There's a corner case where we reload a value which has overlapping live
818*61046927SAndroid Build Coastguard Worker  * values already reloaded, either because it's the child of some other interval
819*61046927SAndroid Build Coastguard Worker  * that was already reloaded or some of its children have already been
820*61046927SAndroid Build Coastguard Worker  * reloaded. Because RA only expects overlapping source/dest intervals for meta
821*61046927SAndroid Build Coastguard Worker  * instructions (split/collect), and we don't want to add register pressure by
822*61046927SAndroid Build Coastguard Worker  * creating an entirely separate value, we need to add splits and collects to
823*61046927SAndroid Build Coastguard Worker  * deal with this case. These splits/collects have to also have correct merge
824*61046927SAndroid Build Coastguard Worker  * set information, so that it doesn't result in any actual code or register
825*61046927SAndroid Build Coastguard Worker  * pressure in practice.
826*61046927SAndroid Build Coastguard Worker  */
827*61046927SAndroid Build Coastguard Worker 
828*61046927SAndroid Build Coastguard Worker static void
add_to_merge_set(struct ir3_merge_set * set,struct ir3_register * def,unsigned offset)829*61046927SAndroid Build Coastguard Worker add_to_merge_set(struct ir3_merge_set *set, struct ir3_register *def,
830*61046927SAndroid Build Coastguard Worker                  unsigned offset)
831*61046927SAndroid Build Coastguard Worker {
832*61046927SAndroid Build Coastguard Worker    def->merge_set = set;
833*61046927SAndroid Build Coastguard Worker    def->merge_set_offset = offset;
834*61046927SAndroid Build Coastguard Worker    def->interval_start = set->interval_start + offset;
835*61046927SAndroid Build Coastguard Worker    def->interval_end = set->interval_start + offset + reg_size(def);
836*61046927SAndroid Build Coastguard Worker }
837*61046927SAndroid Build Coastguard Worker 
838*61046927SAndroid Build Coastguard Worker static struct ir3_register *
split(struct ir3_register * def,unsigned offset,struct ir3_builder * builder)839*61046927SAndroid Build Coastguard Worker split(struct ir3_register *def, unsigned offset, struct ir3_builder *builder)
840*61046927SAndroid Build Coastguard Worker {
841*61046927SAndroid Build Coastguard Worker    if (reg_elems(def) == 1) {
842*61046927SAndroid Build Coastguard Worker       assert(offset == 0);
843*61046927SAndroid Build Coastguard Worker       return def;
844*61046927SAndroid Build Coastguard Worker    }
845*61046927SAndroid Build Coastguard Worker 
846*61046927SAndroid Build Coastguard Worker    assert(!(def->flags & IR3_REG_ARRAY));
847*61046927SAndroid Build Coastguard Worker    assert(def->merge_set);
848*61046927SAndroid Build Coastguard Worker    struct ir3_instruction *split =
849*61046927SAndroid Build Coastguard Worker       ir3_build_instr(builder, OPC_META_SPLIT, 1, 1);
850*61046927SAndroid Build Coastguard Worker    split->split.off = offset;
851*61046927SAndroid Build Coastguard Worker    struct ir3_register *dst = __ssa_dst(split);
852*61046927SAndroid Build Coastguard Worker    dst->flags |= def->flags & IR3_REG_HALF;
853*61046927SAndroid Build Coastguard Worker    struct ir3_register *src = ir3_src_create(split, INVALID_REG, def->flags);
854*61046927SAndroid Build Coastguard Worker    src->wrmask = def->wrmask;
855*61046927SAndroid Build Coastguard Worker    src->def = def;
856*61046927SAndroid Build Coastguard Worker    add_to_merge_set(def->merge_set, dst,
857*61046927SAndroid Build Coastguard Worker                     def->merge_set_offset + offset * reg_elem_size(def));
858*61046927SAndroid Build Coastguard Worker    return dst;
859*61046927SAndroid Build Coastguard Worker }
860*61046927SAndroid Build Coastguard Worker 
861*61046927SAndroid Build Coastguard Worker static struct ir3_register *
extract(struct ir3_register * parent_def,unsigned offset,unsigned elems,struct ir3_cursor cursor)862*61046927SAndroid Build Coastguard Worker extract(struct ir3_register *parent_def, unsigned offset, unsigned elems,
863*61046927SAndroid Build Coastguard Worker         struct ir3_cursor cursor)
864*61046927SAndroid Build Coastguard Worker {
865*61046927SAndroid Build Coastguard Worker    if (offset == 0 && elems == reg_elems(parent_def))
866*61046927SAndroid Build Coastguard Worker       return parent_def;
867*61046927SAndroid Build Coastguard Worker 
868*61046927SAndroid Build Coastguard Worker    struct ir3_builder builder = ir3_builder_at(cursor);
869*61046927SAndroid Build Coastguard Worker    struct ir3_register *srcs[elems];
870*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < elems; i++) {
871*61046927SAndroid Build Coastguard Worker       srcs[i] = split(parent_def, offset + i, &builder);
872*61046927SAndroid Build Coastguard Worker    }
873*61046927SAndroid Build Coastguard Worker 
874*61046927SAndroid Build Coastguard Worker    struct ir3_instruction *collect =
875*61046927SAndroid Build Coastguard Worker       ir3_build_instr(&builder, OPC_META_COLLECT, 1, elems);
876*61046927SAndroid Build Coastguard Worker    struct ir3_register *dst = __ssa_dst(collect);
877*61046927SAndroid Build Coastguard Worker    dst->flags |= parent_def->flags & IR3_REG_HALF;
878*61046927SAndroid Build Coastguard Worker    dst->wrmask = MASK(elems);
879*61046927SAndroid Build Coastguard Worker    add_to_merge_set(parent_def->merge_set, dst, parent_def->merge_set_offset);
880*61046927SAndroid Build Coastguard Worker 
881*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < elems; i++) {
882*61046927SAndroid Build Coastguard Worker       ir3_src_create(collect, INVALID_REG, parent_def->flags)->def = srcs[i];
883*61046927SAndroid Build Coastguard Worker    }
884*61046927SAndroid Build Coastguard Worker 
885*61046927SAndroid Build Coastguard Worker    return dst;
886*61046927SAndroid Build Coastguard Worker }
887*61046927SAndroid Build Coastguard Worker 
888*61046927SAndroid Build Coastguard Worker static struct ir3_register *
reload(struct ra_spill_ctx * ctx,struct ir3_register * reg,struct ir3_cursor cursor)889*61046927SAndroid Build Coastguard Worker reload(struct ra_spill_ctx *ctx, struct ir3_register *reg,
890*61046927SAndroid Build Coastguard Worker        struct ir3_cursor cursor)
891*61046927SAndroid Build Coastguard Worker {
892*61046927SAndroid Build Coastguard Worker    unsigned spill_slot = get_spill_slot(ctx, reg);
893*61046927SAndroid Build Coastguard Worker 
894*61046927SAndroid Build Coastguard Worker    d("reloading ssa_%u:%u from %u", reg->instr->serialno, reg->name,
895*61046927SAndroid Build Coastguard Worker      spill_slot);
896*61046927SAndroid Build Coastguard Worker 
897*61046927SAndroid Build Coastguard Worker    unsigned elems = reg_elems(reg);
898*61046927SAndroid Build Coastguard Worker    struct ir3_instruction *reload =
899*61046927SAndroid Build Coastguard Worker       ir3_instr_create_at(cursor, OPC_RELOAD_MACRO, 1, 3);
900*61046927SAndroid Build Coastguard Worker    struct ir3_register *dst = __ssa_dst(reload);
901*61046927SAndroid Build Coastguard Worker    dst->flags |= reg->flags & (IR3_REG_HALF | IR3_REG_ARRAY);
902*61046927SAndroid Build Coastguard Worker    /* The reload may be split into multiple pieces, and if the destination
903*61046927SAndroid Build Coastguard Worker     * overlaps with the base register then it could get clobbered before the
904*61046927SAndroid Build Coastguard Worker     * last ldp in the sequence. Note that we always reserve space for the base
905*61046927SAndroid Build Coastguard Worker     * register throughout the whole program, so effectively extending its live
906*61046927SAndroid Build Coastguard Worker     * range past the end of the instruction isn't a problem for our pressure
907*61046927SAndroid Build Coastguard Worker     * accounting.
908*61046927SAndroid Build Coastguard Worker     */
909*61046927SAndroid Build Coastguard Worker    dst->flags |= IR3_REG_EARLY_CLOBBER;
910*61046927SAndroid Build Coastguard Worker    ir3_src_create(reload, INVALID_REG, ctx->base_reg->flags)->def = ctx->base_reg;
911*61046927SAndroid Build Coastguard Worker    struct ir3_register *offset_reg =
912*61046927SAndroid Build Coastguard Worker       ir3_src_create(reload, INVALID_REG, IR3_REG_IMMED);
913*61046927SAndroid Build Coastguard Worker    offset_reg->uim_val = spill_slot;
914*61046927SAndroid Build Coastguard Worker    ir3_src_create(reload, INVALID_REG, IR3_REG_IMMED)->uim_val = elems;
915*61046927SAndroid Build Coastguard Worker    reload->cat6.type = (reg->flags & IR3_REG_HALF) ? TYPE_U16 : TYPE_U32;
916*61046927SAndroid Build Coastguard Worker 
917*61046927SAndroid Build Coastguard Worker    if (reg->flags & IR3_REG_ARRAY) {
918*61046927SAndroid Build Coastguard Worker       dst->array.offset = 0;
919*61046927SAndroid Build Coastguard Worker       dst->array.id = reg->array.id;
920*61046927SAndroid Build Coastguard Worker       dst->size = reg->size;
921*61046927SAndroid Build Coastguard Worker    } else {
922*61046927SAndroid Build Coastguard Worker       dst->wrmask = reg->wrmask;
923*61046927SAndroid Build Coastguard Worker    }
924*61046927SAndroid Build Coastguard Worker 
925*61046927SAndroid Build Coastguard Worker    dst->merge_set = reg->merge_set;
926*61046927SAndroid Build Coastguard Worker    dst->merge_set_offset = reg->merge_set_offset;
927*61046927SAndroid Build Coastguard Worker    dst->interval_start = reg->interval_start;
928*61046927SAndroid Build Coastguard Worker    dst->interval_end = reg->interval_end;
929*61046927SAndroid Build Coastguard Worker    return dst;
930*61046927SAndroid Build Coastguard Worker }
931*61046927SAndroid Build Coastguard Worker 
932*61046927SAndroid Build Coastguard Worker static void
rewrite_src_interval(struct ra_spill_ctx * ctx,struct ra_spill_interval * interval,struct ir3_register * def,struct ir3_cursor cursor)933*61046927SAndroid Build Coastguard Worker rewrite_src_interval(struct ra_spill_ctx *ctx,
934*61046927SAndroid Build Coastguard Worker                     struct ra_spill_interval *interval,
935*61046927SAndroid Build Coastguard Worker                     struct ir3_register *def,
936*61046927SAndroid Build Coastguard Worker                     struct ir3_cursor cursor)
937*61046927SAndroid Build Coastguard Worker {
938*61046927SAndroid Build Coastguard Worker    interval->dst.flags = def->flags;
939*61046927SAndroid Build Coastguard Worker    interval->dst.def = def;
940*61046927SAndroid Build Coastguard Worker    interval->needs_reload = false;
941*61046927SAndroid Build Coastguard Worker 
942*61046927SAndroid Build Coastguard Worker    rb_tree_foreach (struct ra_spill_interval, child,
943*61046927SAndroid Build Coastguard Worker                     &interval->interval.children, interval.node) {
944*61046927SAndroid Build Coastguard Worker       struct ir3_register *child_reg = child->interval.reg;
945*61046927SAndroid Build Coastguard Worker       struct ir3_register *child_def =
946*61046927SAndroid Build Coastguard Worker          extract(def, (child_reg->interval_start -
947*61046927SAndroid Build Coastguard Worker                        interval->interval.reg->interval_start) / reg_elem_size(def),
948*61046927SAndroid Build Coastguard Worker                  reg_elems(child_reg), cursor);
949*61046927SAndroid Build Coastguard Worker       rewrite_src_interval(ctx, child, child_def, cursor);
950*61046927SAndroid Build Coastguard Worker    }
951*61046927SAndroid Build Coastguard Worker }
952*61046927SAndroid Build Coastguard Worker 
953*61046927SAndroid Build Coastguard Worker static void
reload_def(struct ra_spill_ctx * ctx,struct ir3_register * def,struct ir3_cursor cursor)954*61046927SAndroid Build Coastguard Worker reload_def(struct ra_spill_ctx *ctx, struct ir3_register *def,
955*61046927SAndroid Build Coastguard Worker            struct ir3_cursor cursor)
956*61046927SAndroid Build Coastguard Worker {
957*61046927SAndroid Build Coastguard Worker    unsigned elems = reg_elems(def);
958*61046927SAndroid Build Coastguard Worker    struct ra_spill_interval *interval = ctx->intervals[def->name];
959*61046927SAndroid Build Coastguard Worker 
960*61046927SAndroid Build Coastguard Worker    struct ir3_reg_interval *ir3_parent = interval->interval.parent;
961*61046927SAndroid Build Coastguard Worker 
962*61046927SAndroid Build Coastguard Worker    if (ir3_parent) {
963*61046927SAndroid Build Coastguard Worker       struct ra_spill_interval *parent =
964*61046927SAndroid Build Coastguard Worker          ir3_reg_interval_to_interval(ir3_parent);
965*61046927SAndroid Build Coastguard Worker       if (!parent->needs_reload) {
966*61046927SAndroid Build Coastguard Worker          interval->dst.flags = def->flags;
967*61046927SAndroid Build Coastguard Worker          interval->dst.def = extract(
968*61046927SAndroid Build Coastguard Worker             parent->dst.def, (def->interval_start - parent->dst.def->interval_start) /
969*61046927SAndroid Build Coastguard Worker             reg_elem_size(def), elems, cursor);
970*61046927SAndroid Build Coastguard Worker          return;
971*61046927SAndroid Build Coastguard Worker       }
972*61046927SAndroid Build Coastguard Worker    }
973*61046927SAndroid Build Coastguard Worker 
974*61046927SAndroid Build Coastguard Worker    struct ir3_register *dst;
975*61046927SAndroid Build Coastguard Worker    if (interval->can_rematerialize)
976*61046927SAndroid Build Coastguard Worker       dst = rematerialize(def, cursor);
977*61046927SAndroid Build Coastguard Worker    else
978*61046927SAndroid Build Coastguard Worker       dst = reload(ctx, def, cursor);
979*61046927SAndroid Build Coastguard Worker 
980*61046927SAndroid Build Coastguard Worker    rewrite_src_interval(ctx, interval, dst, cursor);
981*61046927SAndroid Build Coastguard Worker }
982*61046927SAndroid Build Coastguard Worker 
983*61046927SAndroid Build Coastguard Worker static void
reload_src(struct ra_spill_ctx * ctx,struct ir3_cursor cursor,struct ir3_register * src)984*61046927SAndroid Build Coastguard Worker reload_src(struct ra_spill_ctx *ctx, struct ir3_cursor cursor,
985*61046927SAndroid Build Coastguard Worker             struct ir3_register *src)
986*61046927SAndroid Build Coastguard Worker {
987*61046927SAndroid Build Coastguard Worker    struct ra_spill_interval *interval = ctx->intervals[src->def->name];
988*61046927SAndroid Build Coastguard Worker 
989*61046927SAndroid Build Coastguard Worker    if (interval->needs_reload) {
990*61046927SAndroid Build Coastguard Worker       reload_def(ctx, src->def, cursor);
991*61046927SAndroid Build Coastguard Worker    }
992*61046927SAndroid Build Coastguard Worker 
993*61046927SAndroid Build Coastguard Worker    ra_spill_interval_root(interval)->cant_spill = false;
994*61046927SAndroid Build Coastguard Worker }
995*61046927SAndroid Build Coastguard Worker 
996*61046927SAndroid Build Coastguard Worker static void
rewrite_src(struct ra_spill_ctx * ctx,struct ir3_instruction * instr,struct ir3_register * src)997*61046927SAndroid Build Coastguard Worker rewrite_src(struct ra_spill_ctx *ctx, struct ir3_instruction *instr,
998*61046927SAndroid Build Coastguard Worker             struct ir3_register *src)
999*61046927SAndroid Build Coastguard Worker {
1000*61046927SAndroid Build Coastguard Worker    struct ra_spill_interval *interval = ctx->intervals[src->def->name];
1001*61046927SAndroid Build Coastguard Worker 
1002*61046927SAndroid Build Coastguard Worker    set_src_val(src, &interval->dst);
1003*61046927SAndroid Build Coastguard Worker }
1004*61046927SAndroid Build Coastguard Worker 
1005*61046927SAndroid Build Coastguard Worker static void
update_max_pressure(struct ra_spill_ctx * ctx)1006*61046927SAndroid Build Coastguard Worker update_max_pressure(struct ra_spill_ctx *ctx)
1007*61046927SAndroid Build Coastguard Worker {
1008*61046927SAndroid Build Coastguard Worker    d("pressure:");
1009*61046927SAndroid Build Coastguard Worker    d("\tfull: %u", ctx->cur_pressure.full);
1010*61046927SAndroid Build Coastguard Worker    d("\thalf: %u", ctx->cur_pressure.half);
1011*61046927SAndroid Build Coastguard Worker    d("\tshared: %u", ctx->cur_pressure.shared);
1012*61046927SAndroid Build Coastguard Worker    d("\tshared half: %u", ctx->cur_pressure.shared_half);
1013*61046927SAndroid Build Coastguard Worker 
1014*61046927SAndroid Build Coastguard Worker    ctx->max_pressure.full =
1015*61046927SAndroid Build Coastguard Worker       MAX2(ctx->max_pressure.full, ctx->cur_pressure.full);
1016*61046927SAndroid Build Coastguard Worker    ctx->max_pressure.half =
1017*61046927SAndroid Build Coastguard Worker       MAX2(ctx->max_pressure.half, ctx->cur_pressure.half);
1018*61046927SAndroid Build Coastguard Worker    ctx->max_pressure.shared =
1019*61046927SAndroid Build Coastguard Worker       MAX2(ctx->max_pressure.shared, ctx->cur_pressure.shared);
1020*61046927SAndroid Build Coastguard Worker    ctx->max_pressure.shared_half =
1021*61046927SAndroid Build Coastguard Worker       MAX2(ctx->max_pressure.shared_half, ctx->cur_pressure.shared_half);
1022*61046927SAndroid Build Coastguard Worker }
1023*61046927SAndroid Build Coastguard Worker 
1024*61046927SAndroid Build Coastguard Worker static void
handle_instr(struct ra_spill_ctx * ctx,struct ir3_instruction * instr)1025*61046927SAndroid Build Coastguard Worker handle_instr(struct ra_spill_ctx *ctx, struct ir3_instruction *instr)
1026*61046927SAndroid Build Coastguard Worker {
1027*61046927SAndroid Build Coastguard Worker    ra_foreach_dst (dst, instr) {
1028*61046927SAndroid Build Coastguard Worker       /* No need to handle instructions inserted while spilling. Most are
1029*61046927SAndroid Build Coastguard Worker        * ignored automatically by virtue of being inserted before the current
1030*61046927SAndroid Build Coastguard Worker        * instruction. However, for live-ins, we may insert extracts after the
1031*61046927SAndroid Build Coastguard Worker        * phis. Trying to handle them ends badly as they don't have intervals
1032*61046927SAndroid Build Coastguard Worker        * allocated.
1033*61046927SAndroid Build Coastguard Worker        * Note: since liveness is calculated before spilling, original
1034*61046927SAndroid Build Coastguard Worker        * instruction have a name while new ones don't.
1035*61046927SAndroid Build Coastguard Worker        */
1036*61046927SAndroid Build Coastguard Worker       if (!dst->name)
1037*61046927SAndroid Build Coastguard Worker          return;
1038*61046927SAndroid Build Coastguard Worker 
1039*61046927SAndroid Build Coastguard Worker       init_dst(ctx, dst);
1040*61046927SAndroid Build Coastguard Worker    }
1041*61046927SAndroid Build Coastguard Worker 
1042*61046927SAndroid Build Coastguard Worker    if (ctx->spilling) {
1043*61046927SAndroid Build Coastguard Worker       ra_foreach_src (src, instr)
1044*61046927SAndroid Build Coastguard Worker          insert_src(ctx, src);
1045*61046927SAndroid Build Coastguard Worker    }
1046*61046927SAndroid Build Coastguard Worker 
1047*61046927SAndroid Build Coastguard Worker    /* Handle tied and early-kill destinations. If a destination is tied to a
1048*61046927SAndroid Build Coastguard Worker     * source and that source is live-through, then we need to allocate a new
1049*61046927SAndroid Build Coastguard Worker     * register for the destination which is live-through itself and cannot
1050*61046927SAndroid Build Coastguard Worker     * overlap the sources. Similarly early-kill destinations cannot overlap
1051*61046927SAndroid Build Coastguard Worker     * sources.
1052*61046927SAndroid Build Coastguard Worker     */
1053*61046927SAndroid Build Coastguard Worker 
1054*61046927SAndroid Build Coastguard Worker    ra_foreach_dst (dst, instr) {
1055*61046927SAndroid Build Coastguard Worker       struct ir3_register *tied_src = dst->tied;
1056*61046927SAndroid Build Coastguard Worker       if ((tied_src && !(tied_src->flags & IR3_REG_FIRST_KILL)) ||
1057*61046927SAndroid Build Coastguard Worker           (dst->flags & IR3_REG_EARLY_CLOBBER))
1058*61046927SAndroid Build Coastguard Worker          insert_dst(ctx, dst);
1059*61046927SAndroid Build Coastguard Worker    }
1060*61046927SAndroid Build Coastguard Worker 
1061*61046927SAndroid Build Coastguard Worker    if (ctx->spilling)
1062*61046927SAndroid Build Coastguard Worker       limit(ctx, ir3_before_instr(instr));
1063*61046927SAndroid Build Coastguard Worker    else
1064*61046927SAndroid Build Coastguard Worker       update_max_pressure(ctx);
1065*61046927SAndroid Build Coastguard Worker 
1066*61046927SAndroid Build Coastguard Worker    if (ctx->spilling) {
1067*61046927SAndroid Build Coastguard Worker       ra_foreach_src (src, instr) {
1068*61046927SAndroid Build Coastguard Worker          reload_src(ctx, ir3_before_instr(instr), src);
1069*61046927SAndroid Build Coastguard Worker          update_src_next_use(ctx, src);
1070*61046927SAndroid Build Coastguard Worker       }
1071*61046927SAndroid Build Coastguard Worker    }
1072*61046927SAndroid Build Coastguard Worker 
1073*61046927SAndroid Build Coastguard Worker    ra_foreach_src (src, instr) {
1074*61046927SAndroid Build Coastguard Worker       if (src->flags & IR3_REG_FIRST_KILL)
1075*61046927SAndroid Build Coastguard Worker          remove_src_early(ctx, instr, src);
1076*61046927SAndroid Build Coastguard Worker    }
1077*61046927SAndroid Build Coastguard Worker 
1078*61046927SAndroid Build Coastguard Worker    ra_foreach_dst (dst, instr) {
1079*61046927SAndroid Build Coastguard Worker       insert_dst(ctx, dst);
1080*61046927SAndroid Build Coastguard Worker    }
1081*61046927SAndroid Build Coastguard Worker 
1082*61046927SAndroid Build Coastguard Worker    if (ctx->spilling)
1083*61046927SAndroid Build Coastguard Worker       limit(ctx, ir3_before_instr(instr));
1084*61046927SAndroid Build Coastguard Worker    else
1085*61046927SAndroid Build Coastguard Worker       update_max_pressure(ctx);
1086*61046927SAndroid Build Coastguard Worker 
1087*61046927SAndroid Build Coastguard Worker    /* We have to remove sources before rewriting them so that we can lookup the
1088*61046927SAndroid Build Coastguard Worker     * interval to remove before the source itself is changed.
1089*61046927SAndroid Build Coastguard Worker     */
1090*61046927SAndroid Build Coastguard Worker    ra_foreach_src (src, instr) {
1091*61046927SAndroid Build Coastguard Worker       if (src->flags & IR3_REG_FIRST_KILL)
1092*61046927SAndroid Build Coastguard Worker          remove_src(ctx, instr, src);
1093*61046927SAndroid Build Coastguard Worker    }
1094*61046927SAndroid Build Coastguard Worker 
1095*61046927SAndroid Build Coastguard Worker    if (ctx->spilling) {
1096*61046927SAndroid Build Coastguard Worker       ra_foreach_src (src, instr) {
1097*61046927SAndroid Build Coastguard Worker          rewrite_src(ctx, instr, src);
1098*61046927SAndroid Build Coastguard Worker       }
1099*61046927SAndroid Build Coastguard Worker    }
1100*61046927SAndroid Build Coastguard Worker 
1101*61046927SAndroid Build Coastguard Worker    ra_foreach_dst (dst, instr) {
1102*61046927SAndroid Build Coastguard Worker       finish_dst(ctx, dst);
1103*61046927SAndroid Build Coastguard Worker    }
1104*61046927SAndroid Build Coastguard Worker 
1105*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < instr->dsts_count; i++) {
1106*61046927SAndroid Build Coastguard Worker       if (ra_reg_is_dst(instr->dsts[i]) &&
1107*61046927SAndroid Build Coastguard Worker           (instr->dsts[i]->flags & IR3_REG_UNUSED))
1108*61046927SAndroid Build Coastguard Worker          remove_dst(ctx, instr->dsts[i]);
1109*61046927SAndroid Build Coastguard Worker    }
1110*61046927SAndroid Build Coastguard Worker }
1111*61046927SAndroid Build Coastguard Worker 
1112*61046927SAndroid Build Coastguard Worker static struct ra_spill_interval *
create_temp_interval(struct ra_spill_ctx * ctx,struct ir3_register * def)1113*61046927SAndroid Build Coastguard Worker create_temp_interval(struct ra_spill_ctx *ctx, struct ir3_register *def)
1114*61046927SAndroid Build Coastguard Worker {
1115*61046927SAndroid Build Coastguard Worker    unsigned name = ctx->intervals_count++;
1116*61046927SAndroid Build Coastguard Worker    unsigned offset = ctx->live->interval_offset;
1117*61046927SAndroid Build Coastguard Worker 
1118*61046927SAndroid Build Coastguard Worker    /* This is kinda hacky, but we need to create a fake SSA def here that is
1119*61046927SAndroid Build Coastguard Worker     * only used as part of the pcopy accounting. See below.
1120*61046927SAndroid Build Coastguard Worker     */
1121*61046927SAndroid Build Coastguard Worker    struct ir3_register *reg = rzalloc(ctx, struct ir3_register);
1122*61046927SAndroid Build Coastguard Worker    *reg = *def;
1123*61046927SAndroid Build Coastguard Worker    reg->name = name;
1124*61046927SAndroid Build Coastguard Worker    reg->interval_start = offset;
1125*61046927SAndroid Build Coastguard Worker    reg->interval_end = offset + reg_size(def);
1126*61046927SAndroid Build Coastguard Worker    reg->merge_set = NULL;
1127*61046927SAndroid Build Coastguard Worker 
1128*61046927SAndroid Build Coastguard Worker    ctx->intervals = reralloc(ctx, ctx->intervals, struct ra_spill_interval *,
1129*61046927SAndroid Build Coastguard Worker                              ctx->intervals_count);
1130*61046927SAndroid Build Coastguard Worker    struct ra_spill_interval *interval = rzalloc(ctx, struct ra_spill_interval);
1131*61046927SAndroid Build Coastguard Worker    ra_spill_interval_init(interval, reg);
1132*61046927SAndroid Build Coastguard Worker    ctx->intervals[name] = interval;
1133*61046927SAndroid Build Coastguard Worker    ctx->live->interval_offset += reg_size(def);
1134*61046927SAndroid Build Coastguard Worker    return interval;
1135*61046927SAndroid Build Coastguard Worker }
1136*61046927SAndroid Build Coastguard Worker 
1137*61046927SAndroid Build Coastguard Worker /* In the sequence of copies generated (see below), would this source be killed?
1138*61046927SAndroid Build Coastguard Worker  */
1139*61046927SAndroid Build Coastguard Worker static bool
is_last_pcopy_src(struct ir3_instruction * pcopy,unsigned src_n)1140*61046927SAndroid Build Coastguard Worker is_last_pcopy_src(struct ir3_instruction *pcopy, unsigned src_n)
1141*61046927SAndroid Build Coastguard Worker {
1142*61046927SAndroid Build Coastguard Worker    struct ir3_register *src = pcopy->srcs[src_n];
1143*61046927SAndroid Build Coastguard Worker    if (!(src->flags & IR3_REG_KILL))
1144*61046927SAndroid Build Coastguard Worker       return false;
1145*61046927SAndroid Build Coastguard Worker    for (unsigned j = src_n + 1; j < pcopy->srcs_count; j++) {
1146*61046927SAndroid Build Coastguard Worker       if (pcopy->srcs[j]->def == src->def)
1147*61046927SAndroid Build Coastguard Worker          return false;
1148*61046927SAndroid Build Coastguard Worker    }
1149*61046927SAndroid Build Coastguard Worker    return true;
1150*61046927SAndroid Build Coastguard Worker }
1151*61046927SAndroid Build Coastguard Worker 
1152*61046927SAndroid Build Coastguard Worker /* Parallel copies are different from normal instructions. The sources together
1153*61046927SAndroid Build Coastguard Worker  * may be larger than the entire register file, so we cannot just reload every
1154*61046927SAndroid Build Coastguard Worker  * source like normal, and indeed that probably wouldn't be a great idea.
1155*61046927SAndroid Build Coastguard Worker  * Instead we essentially need to lower the parallel copy to "copies," just like
1156*61046927SAndroid Build Coastguard Worker  * in the normal CSSA construction, although we implement the copies by
1157*61046927SAndroid Build Coastguard Worker  * reloading and then possibly spilling values. We essentially just shuffle
1158*61046927SAndroid Build Coastguard Worker  * around the sources until each source either (a) is live or (b) has the same
1159*61046927SAndroid Build Coastguard Worker  * spill slot as its corresponding destination. We do this by decomposing the
1160*61046927SAndroid Build Coastguard Worker  * copy into a series of copies, so:
1161*61046927SAndroid Build Coastguard Worker  *
1162*61046927SAndroid Build Coastguard Worker  * a, b, c = d, e, f
1163*61046927SAndroid Build Coastguard Worker  *
1164*61046927SAndroid Build Coastguard Worker  * becomes:
1165*61046927SAndroid Build Coastguard Worker  *
1166*61046927SAndroid Build Coastguard Worker  * d' = d
1167*61046927SAndroid Build Coastguard Worker  * e' = e
1168*61046927SAndroid Build Coastguard Worker  * f' = f
1169*61046927SAndroid Build Coastguard Worker  * a = d'
1170*61046927SAndroid Build Coastguard Worker  * b = e'
1171*61046927SAndroid Build Coastguard Worker  * c = f'
1172*61046927SAndroid Build Coastguard Worker  *
1173*61046927SAndroid Build Coastguard Worker  * the temporary SSA values d', e', and f' never actually show up in the result.
1174*61046927SAndroid Build Coastguard Worker  * They are only used for our internal accounting. They may, however, have their
1175*61046927SAndroid Build Coastguard Worker  * own spill slot created for them. Similarly, we don't actually emit any copy
1176*61046927SAndroid Build Coastguard Worker  * instructions, although we emit the spills/reloads that *would've* been
1177*61046927SAndroid Build Coastguard Worker  * required if those copies were there.
1178*61046927SAndroid Build Coastguard Worker  *
1179*61046927SAndroid Build Coastguard Worker  * TODO: in order to reduce the number of temporaries and therefore spill slots,
1180*61046927SAndroid Build Coastguard Worker  * we could instead do a more complicated analysis that considers the location
1181*61046927SAndroid Build Coastguard Worker  * transfer graph.
1182*61046927SAndroid Build Coastguard Worker  *
1183*61046927SAndroid Build Coastguard Worker  * In addition, we actually remove the parallel copy and rewrite all its uses
1184*61046927SAndroid Build Coastguard Worker  * (in the phi nodes) rather than rewrite its sources at the end. Recreating it
1185*61046927SAndroid Build Coastguard Worker  * later turns out to be easier than keeping it up-to-date throughout this pass,
1186*61046927SAndroid Build Coastguard Worker  * since we may have to remove entries for phi sources that are spilled and add
1187*61046927SAndroid Build Coastguard Worker  * entries for live-outs that are spilled and reloaded, which can happen here
1188*61046927SAndroid Build Coastguard Worker  * and then possibly be undone or done again when processing live-ins of the
1189*61046927SAndroid Build Coastguard Worker  * successor block.
1190*61046927SAndroid Build Coastguard Worker  */
1191*61046927SAndroid Build Coastguard Worker 
1192*61046927SAndroid Build Coastguard Worker static void
handle_pcopy(struct ra_spill_ctx * ctx,struct ir3_instruction * pcopy)1193*61046927SAndroid Build Coastguard Worker handle_pcopy(struct ra_spill_ctx *ctx, struct ir3_instruction *pcopy)
1194*61046927SAndroid Build Coastguard Worker {
1195*61046927SAndroid Build Coastguard Worker    ra_foreach_dst (dst, pcopy) {
1196*61046927SAndroid Build Coastguard Worker       struct ra_spill_interval *dst_interval = ctx->intervals[dst->name];
1197*61046927SAndroid Build Coastguard Worker       ra_spill_interval_init(dst_interval, dst);
1198*61046927SAndroid Build Coastguard Worker    }
1199*61046927SAndroid Build Coastguard Worker 
1200*61046927SAndroid Build Coastguard Worker    foreach_src_n (src, i, pcopy) {
1201*61046927SAndroid Build Coastguard Worker       struct ir3_register *dst = pcopy->dsts[i];
1202*61046927SAndroid Build Coastguard Worker       if (!(dst->flags & IR3_REG_SSA))
1203*61046927SAndroid Build Coastguard Worker          continue;
1204*61046927SAndroid Build Coastguard Worker 
1205*61046927SAndroid Build Coastguard Worker       d("processing src %u", i);
1206*61046927SAndroid Build Coastguard Worker 
1207*61046927SAndroid Build Coastguard Worker       /* Skip the intermediate copy for cases where the source is merged with
1208*61046927SAndroid Build Coastguard Worker        * the destination. Crucially this means that we also don't reload/spill
1209*61046927SAndroid Build Coastguard Worker        * it if it's been spilled, because it shares the same spill slot.
1210*61046927SAndroid Build Coastguard Worker        */
1211*61046927SAndroid Build Coastguard Worker       if ((src->flags & IR3_REG_SSA) && src->def->merge_set &&
1212*61046927SAndroid Build Coastguard Worker           src->def->merge_set == dst->merge_set &&
1213*61046927SAndroid Build Coastguard Worker           src->def->merge_set_offset == dst->merge_set_offset) {
1214*61046927SAndroid Build Coastguard Worker          struct ra_spill_interval *src_interval = ctx->intervals[src->def->name];
1215*61046927SAndroid Build Coastguard Worker          struct ra_spill_interval *dst_interval = ctx->intervals[dst->name];
1216*61046927SAndroid Build Coastguard Worker          if (src_interval->interval.inserted) {
1217*61046927SAndroid Build Coastguard Worker             update_src_next_use(ctx, src);
1218*61046927SAndroid Build Coastguard Worker             if (is_last_pcopy_src(pcopy, i))
1219*61046927SAndroid Build Coastguard Worker                ra_spill_ctx_remove(ctx, src_interval);
1220*61046927SAndroid Build Coastguard Worker             dst_interval->cant_spill = true;
1221*61046927SAndroid Build Coastguard Worker             ra_spill_ctx_insert(ctx, dst_interval);
1222*61046927SAndroid Build Coastguard Worker             limit(ctx, ir3_before_instr(pcopy));
1223*61046927SAndroid Build Coastguard Worker             dst_interval->cant_spill = false;
1224*61046927SAndroid Build Coastguard Worker             dst_interval->dst = src_interval->dst;
1225*61046927SAndroid Build Coastguard Worker          }
1226*61046927SAndroid Build Coastguard Worker       } else if (src->flags & IR3_REG_SSA) {
1227*61046927SAndroid Build Coastguard Worker          struct ra_spill_interval *temp_interval =
1228*61046927SAndroid Build Coastguard Worker             create_temp_interval(ctx, dst);
1229*61046927SAndroid Build Coastguard Worker          struct ir3_register *temp = temp_interval->interval.reg;
1230*61046927SAndroid Build Coastguard Worker          temp_interval->next_use_distance = src->next_use;
1231*61046927SAndroid Build Coastguard Worker 
1232*61046927SAndroid Build Coastguard Worker          insert_src(ctx, src);
1233*61046927SAndroid Build Coastguard Worker          limit(ctx, ir3_before_instr(pcopy));
1234*61046927SAndroid Build Coastguard Worker          reload_src(ctx, ir3_before_instr(pcopy), src);
1235*61046927SAndroid Build Coastguard Worker          update_src_next_use(ctx, src);
1236*61046927SAndroid Build Coastguard Worker          if (is_last_pcopy_src(pcopy, i))
1237*61046927SAndroid Build Coastguard Worker             remove_src(ctx, pcopy, src);
1238*61046927SAndroid Build Coastguard Worker          struct ra_spill_interval *src_interval =
1239*61046927SAndroid Build Coastguard Worker             ctx->intervals[src->def->name];
1240*61046927SAndroid Build Coastguard Worker          temp_interval->dst = src_interval->dst;
1241*61046927SAndroid Build Coastguard Worker 
1242*61046927SAndroid Build Coastguard Worker          temp_interval->cant_spill = true;
1243*61046927SAndroid Build Coastguard Worker          ra_spill_ctx_insert(ctx, temp_interval);
1244*61046927SAndroid Build Coastguard Worker          limit(ctx, ir3_before_instr(pcopy));
1245*61046927SAndroid Build Coastguard Worker          temp_interval->cant_spill = false;
1246*61046927SAndroid Build Coastguard Worker 
1247*61046927SAndroid Build Coastguard Worker          src->flags = temp->flags;
1248*61046927SAndroid Build Coastguard Worker          src->def = temp;
1249*61046927SAndroid Build Coastguard Worker       }
1250*61046927SAndroid Build Coastguard Worker    }
1251*61046927SAndroid Build Coastguard Worker 
1252*61046927SAndroid Build Coastguard Worker    d("done with pcopy srcs");
1253*61046927SAndroid Build Coastguard Worker 
1254*61046927SAndroid Build Coastguard Worker    foreach_src_n (src, i, pcopy) {
1255*61046927SAndroid Build Coastguard Worker       struct ir3_register *dst = pcopy->dsts[i];
1256*61046927SAndroid Build Coastguard Worker       if (!(dst->flags & IR3_REG_SSA))
1257*61046927SAndroid Build Coastguard Worker          continue;
1258*61046927SAndroid Build Coastguard Worker 
1259*61046927SAndroid Build Coastguard Worker       if ((src->flags & IR3_REG_SSA) && src->def->merge_set &&
1260*61046927SAndroid Build Coastguard Worker           src->def->merge_set == dst->merge_set &&
1261*61046927SAndroid Build Coastguard Worker           src->def->merge_set_offset == dst->merge_set_offset)
1262*61046927SAndroid Build Coastguard Worker          continue;
1263*61046927SAndroid Build Coastguard Worker 
1264*61046927SAndroid Build Coastguard Worker       struct ra_spill_interval *dst_interval = ctx->intervals[dst->name];
1265*61046927SAndroid Build Coastguard Worker 
1266*61046927SAndroid Build Coastguard Worker       if (!(src->flags & IR3_REG_SSA)) {
1267*61046927SAndroid Build Coastguard Worker          dst_interval->cant_spill = true;
1268*61046927SAndroid Build Coastguard Worker          ra_spill_ctx_insert(ctx, dst_interval);
1269*61046927SAndroid Build Coastguard Worker          limit(ctx, ir3_before_instr(pcopy));
1270*61046927SAndroid Build Coastguard Worker          dst_interval->cant_spill = false;
1271*61046927SAndroid Build Coastguard Worker 
1272*61046927SAndroid Build Coastguard Worker          assert(src->flags & (IR3_REG_CONST | IR3_REG_IMMED));
1273*61046927SAndroid Build Coastguard Worker          if (src->flags & IR3_REG_CONST) {
1274*61046927SAndroid Build Coastguard Worker             dst_interval->dst.flags = src->flags;
1275*61046927SAndroid Build Coastguard Worker             dst_interval->dst.const_num = src->num;
1276*61046927SAndroid Build Coastguard Worker          } else {
1277*61046927SAndroid Build Coastguard Worker             dst_interval->dst.flags = src->flags;
1278*61046927SAndroid Build Coastguard Worker             dst_interval->dst.uimm = src->uim_val;
1279*61046927SAndroid Build Coastguard Worker          }
1280*61046927SAndroid Build Coastguard Worker       } else {
1281*61046927SAndroid Build Coastguard Worker          struct ra_spill_interval *temp_interval = ctx->intervals[src->def->name];
1282*61046927SAndroid Build Coastguard Worker 
1283*61046927SAndroid Build Coastguard Worker          insert_src(ctx, src);
1284*61046927SAndroid Build Coastguard Worker          limit(ctx, ir3_before_instr(pcopy));
1285*61046927SAndroid Build Coastguard Worker          reload_src(ctx, ir3_before_instr(pcopy), src);
1286*61046927SAndroid Build Coastguard Worker          remove_src(ctx, pcopy, src);
1287*61046927SAndroid Build Coastguard Worker 
1288*61046927SAndroid Build Coastguard Worker          dst_interval->dst = temp_interval->dst;
1289*61046927SAndroid Build Coastguard Worker          ra_spill_ctx_insert(ctx, dst_interval);
1290*61046927SAndroid Build Coastguard Worker       }
1291*61046927SAndroid Build Coastguard Worker    }
1292*61046927SAndroid Build Coastguard Worker 
1293*61046927SAndroid Build Coastguard Worker    pcopy->flags |= IR3_INSTR_UNUSED;
1294*61046927SAndroid Build Coastguard Worker }
1295*61046927SAndroid Build Coastguard Worker 
1296*61046927SAndroid Build Coastguard Worker static void
handle_input_phi(struct ra_spill_ctx * ctx,struct ir3_instruction * instr)1297*61046927SAndroid Build Coastguard Worker handle_input_phi(struct ra_spill_ctx *ctx, struct ir3_instruction *instr)
1298*61046927SAndroid Build Coastguard Worker {
1299*61046927SAndroid Build Coastguard Worker    if (!(instr->dsts[0]->flags & IR3_REG_SSA))
1300*61046927SAndroid Build Coastguard Worker       return;
1301*61046927SAndroid Build Coastguard Worker 
1302*61046927SAndroid Build Coastguard Worker    init_dst(ctx, instr->dsts[0]);
1303*61046927SAndroid Build Coastguard Worker    insert_dst(ctx, instr->dsts[0]);
1304*61046927SAndroid Build Coastguard Worker    finish_dst(ctx, instr->dsts[0]);
1305*61046927SAndroid Build Coastguard Worker }
1306*61046927SAndroid Build Coastguard Worker 
1307*61046927SAndroid Build Coastguard Worker static void
remove_input_phi(struct ra_spill_ctx * ctx,struct ir3_instruction * instr)1308*61046927SAndroid Build Coastguard Worker remove_input_phi(struct ra_spill_ctx *ctx, struct ir3_instruction *instr)
1309*61046927SAndroid Build Coastguard Worker {
1310*61046927SAndroid Build Coastguard Worker    if (!(instr->dsts[0]->flags & IR3_REG_SSA))
1311*61046927SAndroid Build Coastguard Worker       return;
1312*61046927SAndroid Build Coastguard Worker 
1313*61046927SAndroid Build Coastguard Worker    if (instr->opc == OPC_META_TEX_PREFETCH) {
1314*61046927SAndroid Build Coastguard Worker       ra_foreach_src (src, instr) {
1315*61046927SAndroid Build Coastguard Worker          if (src->flags & IR3_REG_FIRST_KILL)
1316*61046927SAndroid Build Coastguard Worker             remove_src(ctx, instr, src);
1317*61046927SAndroid Build Coastguard Worker       }
1318*61046927SAndroid Build Coastguard Worker    }
1319*61046927SAndroid Build Coastguard Worker    if (instr->dsts[0]->flags & IR3_REG_UNUSED)
1320*61046927SAndroid Build Coastguard Worker       remove_dst(ctx, instr->dsts[0]);
1321*61046927SAndroid Build Coastguard Worker }
1322*61046927SAndroid Build Coastguard Worker 
1323*61046927SAndroid Build Coastguard Worker static void
handle_live_in(struct ra_spill_ctx * ctx,struct ir3_block * block,struct ir3_register * def)1324*61046927SAndroid Build Coastguard Worker handle_live_in(struct ra_spill_ctx *ctx, struct ir3_block *block,
1325*61046927SAndroid Build Coastguard Worker                struct ir3_register *def)
1326*61046927SAndroid Build Coastguard Worker {
1327*61046927SAndroid Build Coastguard Worker    struct ra_spill_interval *interval = ctx->intervals[def->name];
1328*61046927SAndroid Build Coastguard Worker    ra_spill_interval_init(interval, def);
1329*61046927SAndroid Build Coastguard Worker    if (ctx->spilling) {
1330*61046927SAndroid Build Coastguard Worker       interval->next_use_distance =
1331*61046927SAndroid Build Coastguard Worker          ctx->blocks[block->index].next_use_start[def->name];
1332*61046927SAndroid Build Coastguard Worker    }
1333*61046927SAndroid Build Coastguard Worker 
1334*61046927SAndroid Build Coastguard Worker    ra_spill_ctx_insert(ctx, interval);
1335*61046927SAndroid Build Coastguard Worker }
1336*61046927SAndroid Build Coastguard Worker 
1337*61046927SAndroid Build Coastguard Worker static bool
is_live_in_phi(struct ir3_register * def,struct ir3_block * block)1338*61046927SAndroid Build Coastguard Worker is_live_in_phi(struct ir3_register *def, struct ir3_block *block)
1339*61046927SAndroid Build Coastguard Worker {
1340*61046927SAndroid Build Coastguard Worker    return def->instr->opc == OPC_META_PHI && def->instr->block == block;
1341*61046927SAndroid Build Coastguard Worker }
1342*61046927SAndroid Build Coastguard Worker 
1343*61046927SAndroid Build Coastguard Worker static bool
is_live_in_pred(struct ra_spill_ctx * ctx,struct ir3_register * def,struct ir3_block * block,unsigned pred_idx)1344*61046927SAndroid Build Coastguard Worker is_live_in_pred(struct ra_spill_ctx *ctx, struct ir3_register *def,
1345*61046927SAndroid Build Coastguard Worker                 struct ir3_block *block, unsigned pred_idx)
1346*61046927SAndroid Build Coastguard Worker {
1347*61046927SAndroid Build Coastguard Worker    struct ir3_block *pred = block->predecessors[pred_idx];
1348*61046927SAndroid Build Coastguard Worker    struct ra_spill_block_state *state = &ctx->blocks[pred->index];
1349*61046927SAndroid Build Coastguard Worker    if (is_live_in_phi(def, block)) {
1350*61046927SAndroid Build Coastguard Worker       def = def->instr->srcs[pred_idx]->def;
1351*61046927SAndroid Build Coastguard Worker       if (!def)
1352*61046927SAndroid Build Coastguard Worker          return false;
1353*61046927SAndroid Build Coastguard Worker    }
1354*61046927SAndroid Build Coastguard Worker 
1355*61046927SAndroid Build Coastguard Worker    return _mesa_hash_table_search(state->remap, def);
1356*61046927SAndroid Build Coastguard Worker }
1357*61046927SAndroid Build Coastguard Worker 
1358*61046927SAndroid Build Coastguard Worker static bool
is_live_in_undef(struct ir3_register * def,struct ir3_block * block,unsigned pred_idx)1359*61046927SAndroid Build Coastguard Worker is_live_in_undef(struct ir3_register *def,
1360*61046927SAndroid Build Coastguard Worker                  struct ir3_block *block, unsigned pred_idx)
1361*61046927SAndroid Build Coastguard Worker {
1362*61046927SAndroid Build Coastguard Worker    if (!is_live_in_phi(def, block))
1363*61046927SAndroid Build Coastguard Worker       return false;
1364*61046927SAndroid Build Coastguard Worker 
1365*61046927SAndroid Build Coastguard Worker    return !def->instr->srcs[pred_idx]->def;
1366*61046927SAndroid Build Coastguard Worker }
1367*61046927SAndroid Build Coastguard Worker 
1368*61046927SAndroid Build Coastguard Worker static struct reg_or_immed *
read_live_in(struct ra_spill_ctx * ctx,struct ir3_register * def,struct ir3_block * block,unsigned pred_idx)1369*61046927SAndroid Build Coastguard Worker read_live_in(struct ra_spill_ctx *ctx, struct ir3_register *def,
1370*61046927SAndroid Build Coastguard Worker              struct ir3_block *block, unsigned pred_idx)
1371*61046927SAndroid Build Coastguard Worker {
1372*61046927SAndroid Build Coastguard Worker    struct ir3_block *pred = block->predecessors[pred_idx];
1373*61046927SAndroid Build Coastguard Worker    struct ra_spill_block_state *state = &ctx->blocks[pred->index];
1374*61046927SAndroid Build Coastguard Worker 
1375*61046927SAndroid Build Coastguard Worker    if (is_live_in_phi(def, block)) {
1376*61046927SAndroid Build Coastguard Worker       def = def->instr->srcs[pred_idx]->def;
1377*61046927SAndroid Build Coastguard Worker       if (!def)
1378*61046927SAndroid Build Coastguard Worker          return NULL;
1379*61046927SAndroid Build Coastguard Worker    }
1380*61046927SAndroid Build Coastguard Worker 
1381*61046927SAndroid Build Coastguard Worker    struct hash_entry *entry = _mesa_hash_table_search(state->remap, def);
1382*61046927SAndroid Build Coastguard Worker    if (entry)
1383*61046927SAndroid Build Coastguard Worker       return entry->data;
1384*61046927SAndroid Build Coastguard Worker    else
1385*61046927SAndroid Build Coastguard Worker       return NULL;
1386*61046927SAndroid Build Coastguard Worker }
1387*61046927SAndroid Build Coastguard Worker 
1388*61046927SAndroid Build Coastguard Worker static bool
is_live_in_all_preds(struct ra_spill_ctx * ctx,struct ir3_register * def,struct ir3_block * block)1389*61046927SAndroid Build Coastguard Worker is_live_in_all_preds(struct ra_spill_ctx *ctx, struct ir3_register *def,
1390*61046927SAndroid Build Coastguard Worker                      struct ir3_block *block)
1391*61046927SAndroid Build Coastguard Worker {
1392*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < block->predecessors_count; i++) {
1393*61046927SAndroid Build Coastguard Worker       if (!is_live_in_pred(ctx, def, block, i))
1394*61046927SAndroid Build Coastguard Worker          return false;
1395*61046927SAndroid Build Coastguard Worker    }
1396*61046927SAndroid Build Coastguard Worker 
1397*61046927SAndroid Build Coastguard Worker    return true;
1398*61046927SAndroid Build Coastguard Worker }
1399*61046927SAndroid Build Coastguard Worker 
1400*61046927SAndroid Build Coastguard Worker static void
spill_live_in(struct ra_spill_ctx * ctx,struct ir3_register * def,struct ir3_block * block)1401*61046927SAndroid Build Coastguard Worker spill_live_in(struct ra_spill_ctx *ctx, struct ir3_register *def,
1402*61046927SAndroid Build Coastguard Worker               struct ir3_block *block)
1403*61046927SAndroid Build Coastguard Worker {
1404*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < block->predecessors_count; i++) {
1405*61046927SAndroid Build Coastguard Worker       struct ir3_block *pred = block->predecessors[i];
1406*61046927SAndroid Build Coastguard Worker       struct ra_spill_block_state *state = &ctx->blocks[pred->index];
1407*61046927SAndroid Build Coastguard Worker 
1408*61046927SAndroid Build Coastguard Worker       if (!state->visited)
1409*61046927SAndroid Build Coastguard Worker          continue;
1410*61046927SAndroid Build Coastguard Worker 
1411*61046927SAndroid Build Coastguard Worker       struct reg_or_immed *pred_def = read_live_in(ctx, def, block, i);
1412*61046927SAndroid Build Coastguard Worker       if (pred_def) {
1413*61046927SAndroid Build Coastguard Worker          spill(ctx, pred_def, get_spill_slot(ctx, def),
1414*61046927SAndroid Build Coastguard Worker                ir3_before_terminator(pred));
1415*61046927SAndroid Build Coastguard Worker       }
1416*61046927SAndroid Build Coastguard Worker    }
1417*61046927SAndroid Build Coastguard Worker }
1418*61046927SAndroid Build Coastguard Worker 
1419*61046927SAndroid Build Coastguard Worker static void
spill_live_ins(struct ra_spill_ctx * ctx,struct ir3_block * block)1420*61046927SAndroid Build Coastguard Worker spill_live_ins(struct ra_spill_ctx *ctx, struct ir3_block *block)
1421*61046927SAndroid Build Coastguard Worker {
1422*61046927SAndroid Build Coastguard Worker    bool all_preds_visited = true;
1423*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < block->predecessors_count; i++) {
1424*61046927SAndroid Build Coastguard Worker       struct ir3_block *pred = block->predecessors[i];
1425*61046927SAndroid Build Coastguard Worker       struct ra_spill_block_state *state = &ctx->blocks[pred->index];
1426*61046927SAndroid Build Coastguard Worker       if (!state->visited) {
1427*61046927SAndroid Build Coastguard Worker          all_preds_visited = false;
1428*61046927SAndroid Build Coastguard Worker          break;
1429*61046927SAndroid Build Coastguard Worker       }
1430*61046927SAndroid Build Coastguard Worker    }
1431*61046927SAndroid Build Coastguard Worker 
1432*61046927SAndroid Build Coastguard Worker    /* Note: in the paper they explicitly spill live-through values first, but we
1433*61046927SAndroid Build Coastguard Worker     * should be doing that automatically by virtue of picking the largest
1434*61046927SAndroid Build Coastguard Worker     * distance due to the extra distance added to edges out of loops.
1435*61046927SAndroid Build Coastguard Worker     *
1436*61046927SAndroid Build Coastguard Worker     * TODO: Keep track of pressure in each block and preemptively spill
1437*61046927SAndroid Build Coastguard Worker     * live-through values as described in the paper to avoid spilling them
1438*61046927SAndroid Build Coastguard Worker     * inside the loop.
1439*61046927SAndroid Build Coastguard Worker     */
1440*61046927SAndroid Build Coastguard Worker 
1441*61046927SAndroid Build Coastguard Worker    if (ctx->cur_pressure.half > ctx->limit_pressure.half) {
1442*61046927SAndroid Build Coastguard Worker       rb_tree_foreach_safe (struct ra_spill_interval, interval,
1443*61046927SAndroid Build Coastguard Worker                             &ctx->half_live_intervals, half_node) {
1444*61046927SAndroid Build Coastguard Worker          if (all_preds_visited &&
1445*61046927SAndroid Build Coastguard Worker              is_live_in_all_preds(ctx, interval->interval.reg, block))
1446*61046927SAndroid Build Coastguard Worker             continue;
1447*61046927SAndroid Build Coastguard Worker          if (interval->interval.reg->merge_set ||
1448*61046927SAndroid Build Coastguard Worker              !interval->can_rematerialize)
1449*61046927SAndroid Build Coastguard Worker             spill_live_in(ctx, interval->interval.reg, block);
1450*61046927SAndroid Build Coastguard Worker          ir3_reg_interval_remove_all(&ctx->reg_ctx, &interval->interval);
1451*61046927SAndroid Build Coastguard Worker          if (ctx->cur_pressure.half <= ctx->limit_pressure.half)
1452*61046927SAndroid Build Coastguard Worker             break;
1453*61046927SAndroid Build Coastguard Worker       }
1454*61046927SAndroid Build Coastguard Worker    }
1455*61046927SAndroid Build Coastguard Worker 
1456*61046927SAndroid Build Coastguard Worker    if (ctx->cur_pressure.full > ctx->limit_pressure.full) {
1457*61046927SAndroid Build Coastguard Worker       rb_tree_foreach_safe (struct ra_spill_interval, interval,
1458*61046927SAndroid Build Coastguard Worker                             &ctx->full_live_intervals, node) {
1459*61046927SAndroid Build Coastguard Worker          if (all_preds_visited &&
1460*61046927SAndroid Build Coastguard Worker              is_live_in_all_preds(ctx, interval->interval.reg, block))
1461*61046927SAndroid Build Coastguard Worker             continue;
1462*61046927SAndroid Build Coastguard Worker          spill_live_in(ctx, interval->interval.reg, block);
1463*61046927SAndroid Build Coastguard Worker          ir3_reg_interval_remove_all(&ctx->reg_ctx, &interval->interval);
1464*61046927SAndroid Build Coastguard Worker          if (ctx->cur_pressure.full <= ctx->limit_pressure.full)
1465*61046927SAndroid Build Coastguard Worker             break;
1466*61046927SAndroid Build Coastguard Worker       }
1467*61046927SAndroid Build Coastguard Worker    }
1468*61046927SAndroid Build Coastguard Worker }
1469*61046927SAndroid Build Coastguard Worker 
1470*61046927SAndroid Build Coastguard Worker static void
live_in_rewrite(struct ra_spill_ctx * ctx,struct ra_spill_interval * interval,struct reg_or_immed * new_val,struct ir3_block * block,unsigned pred_idx)1471*61046927SAndroid Build Coastguard Worker live_in_rewrite(struct ra_spill_ctx *ctx,
1472*61046927SAndroid Build Coastguard Worker                 struct ra_spill_interval *interval,
1473*61046927SAndroid Build Coastguard Worker                 struct reg_or_immed *new_val,
1474*61046927SAndroid Build Coastguard Worker                 struct ir3_block *block, unsigned pred_idx)
1475*61046927SAndroid Build Coastguard Worker {
1476*61046927SAndroid Build Coastguard Worker    struct ir3_block *pred = block->predecessors[pred_idx];
1477*61046927SAndroid Build Coastguard Worker    struct ra_spill_block_state *state = &ctx->blocks[pred->index];
1478*61046927SAndroid Build Coastguard Worker    struct ir3_register *def = interval->interval.reg;
1479*61046927SAndroid Build Coastguard Worker    if (is_live_in_phi(def, block)) {
1480*61046927SAndroid Build Coastguard Worker       def = def->instr->srcs[pred_idx]->def;
1481*61046927SAndroid Build Coastguard Worker    }
1482*61046927SAndroid Build Coastguard Worker 
1483*61046927SAndroid Build Coastguard Worker    if (def)
1484*61046927SAndroid Build Coastguard Worker       _mesa_hash_table_insert(state->remap, def, new_val);
1485*61046927SAndroid Build Coastguard Worker }
1486*61046927SAndroid Build Coastguard Worker 
1487*61046927SAndroid Build Coastguard Worker static void
reload_live_in(struct ra_spill_ctx * ctx,struct ir3_register * def,struct ir3_block * block)1488*61046927SAndroid Build Coastguard Worker reload_live_in(struct ra_spill_ctx *ctx, struct ir3_register *def,
1489*61046927SAndroid Build Coastguard Worker                struct ir3_block *block)
1490*61046927SAndroid Build Coastguard Worker {
1491*61046927SAndroid Build Coastguard Worker    struct ra_spill_interval *interval = ctx->intervals[def->name];
1492*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < block->predecessors_count; i++) {
1493*61046927SAndroid Build Coastguard Worker       struct ir3_block *pred = block->predecessors[i];
1494*61046927SAndroid Build Coastguard Worker       struct ra_spill_block_state *state = &ctx->blocks[pred->index];
1495*61046927SAndroid Build Coastguard Worker       if (!state->visited)
1496*61046927SAndroid Build Coastguard Worker          continue;
1497*61046927SAndroid Build Coastguard Worker 
1498*61046927SAndroid Build Coastguard Worker       if (is_live_in_undef(def, block, i))
1499*61046927SAndroid Build Coastguard Worker          continue;
1500*61046927SAndroid Build Coastguard Worker 
1501*61046927SAndroid Build Coastguard Worker       struct reg_or_immed *new_val = read_live_in(ctx, def, block, i);
1502*61046927SAndroid Build Coastguard Worker 
1503*61046927SAndroid Build Coastguard Worker       if (!new_val) {
1504*61046927SAndroid Build Coastguard Worker          new_val = ralloc(ctx, struct reg_or_immed);
1505*61046927SAndroid Build Coastguard Worker          if (interval->can_rematerialize)
1506*61046927SAndroid Build Coastguard Worker             new_val->def = rematerialize(def, ir3_before_terminator(pred));
1507*61046927SAndroid Build Coastguard Worker          else
1508*61046927SAndroid Build Coastguard Worker             new_val->def = reload(ctx, def, ir3_before_terminator(pred));
1509*61046927SAndroid Build Coastguard Worker          new_val->flags = new_val->def->flags;
1510*61046927SAndroid Build Coastguard Worker       }
1511*61046927SAndroid Build Coastguard Worker       live_in_rewrite(ctx, interval, new_val, block, i);
1512*61046927SAndroid Build Coastguard Worker    }
1513*61046927SAndroid Build Coastguard Worker }
1514*61046927SAndroid Build Coastguard Worker 
1515*61046927SAndroid Build Coastguard Worker static void
reload_live_ins(struct ra_spill_ctx * ctx,struct ir3_block * block)1516*61046927SAndroid Build Coastguard Worker reload_live_ins(struct ra_spill_ctx *ctx, struct ir3_block *block)
1517*61046927SAndroid Build Coastguard Worker {
1518*61046927SAndroid Build Coastguard Worker    rb_tree_foreach (struct ra_spill_interval, interval, &ctx->reg_ctx.intervals,
1519*61046927SAndroid Build Coastguard Worker                     interval.node) {
1520*61046927SAndroid Build Coastguard Worker       reload_live_in(ctx, interval->interval.reg, block);
1521*61046927SAndroid Build Coastguard Worker    }
1522*61046927SAndroid Build Coastguard Worker }
1523*61046927SAndroid Build Coastguard Worker 
1524*61046927SAndroid Build Coastguard Worker static void
add_live_in_phi(struct ra_spill_ctx * ctx,struct ir3_register * def,struct ir3_register * parent_def,struct ir3_block * block)1525*61046927SAndroid Build Coastguard Worker add_live_in_phi(struct ra_spill_ctx *ctx, struct ir3_register *def,
1526*61046927SAndroid Build Coastguard Worker                 struct ir3_register *parent_def, struct ir3_block *block)
1527*61046927SAndroid Build Coastguard Worker {
1528*61046927SAndroid Build Coastguard Worker    struct ra_spill_interval *interval = ctx->intervals[def->name];
1529*61046927SAndroid Build Coastguard Worker    if (!interval->interval.inserted)
1530*61046927SAndroid Build Coastguard Worker       return;
1531*61046927SAndroid Build Coastguard Worker 
1532*61046927SAndroid Build Coastguard Worker    bool needs_phi = false;
1533*61046927SAndroid Build Coastguard Worker    struct ir3_register *cur_def = NULL;
1534*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < block->predecessors_count; i++) {
1535*61046927SAndroid Build Coastguard Worker       struct ir3_block *pred = block->predecessors[i];
1536*61046927SAndroid Build Coastguard Worker       struct ra_spill_block_state *state = &ctx->blocks[pred->index];
1537*61046927SAndroid Build Coastguard Worker 
1538*61046927SAndroid Build Coastguard Worker       if (!state->visited) {
1539*61046927SAndroid Build Coastguard Worker          needs_phi = true;
1540*61046927SAndroid Build Coastguard Worker          break;
1541*61046927SAndroid Build Coastguard Worker       }
1542*61046927SAndroid Build Coastguard Worker 
1543*61046927SAndroid Build Coastguard Worker       struct hash_entry *entry =
1544*61046927SAndroid Build Coastguard Worker          _mesa_hash_table_search(state->remap, def);
1545*61046927SAndroid Build Coastguard Worker       assert(entry);
1546*61046927SAndroid Build Coastguard Worker       struct reg_or_immed *pred_val = entry->data;
1547*61046927SAndroid Build Coastguard Worker       if ((pred_val->flags & (IR3_REG_IMMED | IR3_REG_CONST)) ||
1548*61046927SAndroid Build Coastguard Worker           !pred_val->def ||
1549*61046927SAndroid Build Coastguard Worker           (cur_def && cur_def != pred_val->def)) {
1550*61046927SAndroid Build Coastguard Worker          needs_phi = true;
1551*61046927SAndroid Build Coastguard Worker          break;
1552*61046927SAndroid Build Coastguard Worker       }
1553*61046927SAndroid Build Coastguard Worker       cur_def = pred_val->def;
1554*61046927SAndroid Build Coastguard Worker    }
1555*61046927SAndroid Build Coastguard Worker 
1556*61046927SAndroid Build Coastguard Worker    if (!needs_phi) {
1557*61046927SAndroid Build Coastguard Worker       interval->dst.def = cur_def;
1558*61046927SAndroid Build Coastguard Worker       interval->dst.flags = cur_def->flags;
1559*61046927SAndroid Build Coastguard Worker 
1560*61046927SAndroid Build Coastguard Worker       rb_tree_foreach (struct ra_spill_interval, child,
1561*61046927SAndroid Build Coastguard Worker                        &interval->interval.children, interval.node) {
1562*61046927SAndroid Build Coastguard Worker          add_live_in_phi(ctx, child->interval.reg, cur_def, block);
1563*61046927SAndroid Build Coastguard Worker       }
1564*61046927SAndroid Build Coastguard Worker 
1565*61046927SAndroid Build Coastguard Worker       return;
1566*61046927SAndroid Build Coastguard Worker    }
1567*61046927SAndroid Build Coastguard Worker 
1568*61046927SAndroid Build Coastguard Worker    if (parent_def) {
1569*61046927SAndroid Build Coastguard Worker       /* We have a child interval that needs a phi but whose parent does not
1570*61046927SAndroid Build Coastguard Worker        * need one (otherwise parent_def would be NULL). Just extract the child
1571*61046927SAndroid Build Coastguard Worker        * from the parent without creating a phi for the child.
1572*61046927SAndroid Build Coastguard Worker        */
1573*61046927SAndroid Build Coastguard Worker       unsigned offset = (def->interval_start - parent_def->interval_start) /
1574*61046927SAndroid Build Coastguard Worker                         reg_elem_size(def);
1575*61046927SAndroid Build Coastguard Worker       struct ir3_register *extracted =
1576*61046927SAndroid Build Coastguard Worker          extract(parent_def, offset, reg_elems(def), ir3_after_phis(block));
1577*61046927SAndroid Build Coastguard Worker       rewrite_src_interval(ctx, interval, extracted,
1578*61046927SAndroid Build Coastguard Worker                            ir3_after_instr(extracted->instr));
1579*61046927SAndroid Build Coastguard Worker       return;
1580*61046927SAndroid Build Coastguard Worker    }
1581*61046927SAndroid Build Coastguard Worker 
1582*61046927SAndroid Build Coastguard Worker    struct ir3_instruction *phi = ir3_instr_create_at(
1583*61046927SAndroid Build Coastguard Worker       ir3_before_block(block), OPC_META_PHI, 1, block->predecessors_count);
1584*61046927SAndroid Build Coastguard Worker    struct ir3_register *dst = __ssa_dst(phi);
1585*61046927SAndroid Build Coastguard Worker    dst->flags |= def->flags & (IR3_REG_HALF | IR3_REG_ARRAY);
1586*61046927SAndroid Build Coastguard Worker    dst->size = def->size;
1587*61046927SAndroid Build Coastguard Worker    dst->wrmask = def->wrmask;
1588*61046927SAndroid Build Coastguard Worker 
1589*61046927SAndroid Build Coastguard Worker    dst->interval_start = def->interval_start;
1590*61046927SAndroid Build Coastguard Worker    dst->interval_end = def->interval_end;
1591*61046927SAndroid Build Coastguard Worker    dst->merge_set = def->merge_set;
1592*61046927SAndroid Build Coastguard Worker    dst->merge_set_offset = def->merge_set_offset;
1593*61046927SAndroid Build Coastguard Worker 
1594*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < block->predecessors_count; i++) {
1595*61046927SAndroid Build Coastguard Worker       struct ir3_block *pred = block->predecessors[i];
1596*61046927SAndroid Build Coastguard Worker       struct ra_spill_block_state *state = &ctx->blocks[pred->index];
1597*61046927SAndroid Build Coastguard Worker       struct ir3_register *src = ir3_src_create(phi, INVALID_REG, dst->flags);
1598*61046927SAndroid Build Coastguard Worker       src->size = def->size;
1599*61046927SAndroid Build Coastguard Worker       src->wrmask = def->wrmask;
1600*61046927SAndroid Build Coastguard Worker 
1601*61046927SAndroid Build Coastguard Worker       if (state->visited) {
1602*61046927SAndroid Build Coastguard Worker          struct hash_entry *entry =
1603*61046927SAndroid Build Coastguard Worker             _mesa_hash_table_search(state->remap, def);
1604*61046927SAndroid Build Coastguard Worker          assert(entry);
1605*61046927SAndroid Build Coastguard Worker          struct reg_or_immed *new_val = entry->data;
1606*61046927SAndroid Build Coastguard Worker          set_src_val(src, new_val);
1607*61046927SAndroid Build Coastguard Worker       } else {
1608*61046927SAndroid Build Coastguard Worker          src->def = def;
1609*61046927SAndroid Build Coastguard Worker       }
1610*61046927SAndroid Build Coastguard Worker    }
1611*61046927SAndroid Build Coastguard Worker 
1612*61046927SAndroid Build Coastguard Worker    interval->dst.def = dst;
1613*61046927SAndroid Build Coastguard Worker    interval->dst.flags = dst->flags;
1614*61046927SAndroid Build Coastguard Worker    rewrite_src_interval(ctx, interval, dst, ir3_after_phis(block));
1615*61046927SAndroid Build Coastguard Worker }
1616*61046927SAndroid Build Coastguard Worker 
1617*61046927SAndroid Build Coastguard Worker static void
add_live_in_phis(struct ra_spill_ctx * ctx,struct ir3_block * block)1618*61046927SAndroid Build Coastguard Worker add_live_in_phis(struct ra_spill_ctx *ctx, struct ir3_block *block)
1619*61046927SAndroid Build Coastguard Worker {
1620*61046927SAndroid Build Coastguard Worker    rb_tree_foreach (struct ra_spill_interval, interval, &ctx->reg_ctx.intervals,
1621*61046927SAndroid Build Coastguard Worker                     interval.node) {
1622*61046927SAndroid Build Coastguard Worker       if (BITSET_TEST(ctx->live->live_in[block->index],
1623*61046927SAndroid Build Coastguard Worker                       interval->interval.reg->name)) {
1624*61046927SAndroid Build Coastguard Worker          add_live_in_phi(ctx, interval->interval.reg, NULL, block);
1625*61046927SAndroid Build Coastguard Worker       }
1626*61046927SAndroid Build Coastguard Worker    }
1627*61046927SAndroid Build Coastguard Worker }
1628*61046927SAndroid Build Coastguard Worker 
1629*61046927SAndroid Build Coastguard Worker /* When spilling a block with a single predecessors, the pred may have other
1630*61046927SAndroid Build Coastguard Worker  * successors so we can't choose what's live in and we can't spill/restore
1631*61046927SAndroid Build Coastguard Worker  * anything. Just make the inserted intervals exactly match the predecessor. If
1632*61046927SAndroid Build Coastguard Worker  * it wasn't live in the predecessor then it must've already been spilled. Also,
1633*61046927SAndroid Build Coastguard Worker  * there are no phi nodes and no live-ins.
1634*61046927SAndroid Build Coastguard Worker  */
1635*61046927SAndroid Build Coastguard Worker static void
spill_single_pred_live_in(struct ra_spill_ctx * ctx,struct ir3_block * block)1636*61046927SAndroid Build Coastguard Worker spill_single_pred_live_in(struct ra_spill_ctx *ctx,
1637*61046927SAndroid Build Coastguard Worker                           struct ir3_block *block)
1638*61046927SAndroid Build Coastguard Worker {
1639*61046927SAndroid Build Coastguard Worker    unsigned name;
1640*61046927SAndroid Build Coastguard Worker    BITSET_FOREACH_SET (name, ctx->live->live_in[block->index],
1641*61046927SAndroid Build Coastguard Worker                        ctx->live->definitions_count) {
1642*61046927SAndroid Build Coastguard Worker       struct ir3_register *reg = ctx->live->definitions[name];
1643*61046927SAndroid Build Coastguard Worker       struct ra_spill_interval *interval = ctx->intervals[reg->name];
1644*61046927SAndroid Build Coastguard Worker       struct reg_or_immed *val = read_live_in(ctx, reg, block, 0);
1645*61046927SAndroid Build Coastguard Worker       if (val)
1646*61046927SAndroid Build Coastguard Worker          interval->dst = *val;
1647*61046927SAndroid Build Coastguard Worker       else
1648*61046927SAndroid Build Coastguard Worker          ra_spill_ctx_remove(ctx, interval);
1649*61046927SAndroid Build Coastguard Worker    }
1650*61046927SAndroid Build Coastguard Worker }
1651*61046927SAndroid Build Coastguard Worker 
1652*61046927SAndroid Build Coastguard Worker static void
rewrite_phi(struct ra_spill_ctx * ctx,struct ir3_instruction * phi,struct ir3_block * block)1653*61046927SAndroid Build Coastguard Worker rewrite_phi(struct ra_spill_ctx *ctx, struct ir3_instruction *phi,
1654*61046927SAndroid Build Coastguard Worker             struct ir3_block *block)
1655*61046927SAndroid Build Coastguard Worker {
1656*61046927SAndroid Build Coastguard Worker    if (!(phi->dsts[0]->flags & IR3_REG_SSA))
1657*61046927SAndroid Build Coastguard Worker       return;
1658*61046927SAndroid Build Coastguard Worker 
1659*61046927SAndroid Build Coastguard Worker    if (!ctx->intervals[phi->dsts[0]->name]->interval.inserted) {
1660*61046927SAndroid Build Coastguard Worker       phi->flags |= IR3_INSTR_UNUSED;
1661*61046927SAndroid Build Coastguard Worker       return;
1662*61046927SAndroid Build Coastguard Worker    }
1663*61046927SAndroid Build Coastguard Worker 
1664*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < block->predecessors_count; i++) {
1665*61046927SAndroid Build Coastguard Worker       struct ir3_block *pred = block->predecessors[i];
1666*61046927SAndroid Build Coastguard Worker       struct ra_spill_block_state *state = &ctx->blocks[pred->index];
1667*61046927SAndroid Build Coastguard Worker 
1668*61046927SAndroid Build Coastguard Worker       if (!state->visited)
1669*61046927SAndroid Build Coastguard Worker          continue;
1670*61046927SAndroid Build Coastguard Worker 
1671*61046927SAndroid Build Coastguard Worker       struct ir3_register *src = phi->srcs[i];
1672*61046927SAndroid Build Coastguard Worker       if (!src->def)
1673*61046927SAndroid Build Coastguard Worker          continue;
1674*61046927SAndroid Build Coastguard Worker 
1675*61046927SAndroid Build Coastguard Worker       struct hash_entry *entry =
1676*61046927SAndroid Build Coastguard Worker          _mesa_hash_table_search(state->remap, src->def);
1677*61046927SAndroid Build Coastguard Worker       assert(entry);
1678*61046927SAndroid Build Coastguard Worker       struct reg_or_immed *new_val = entry->data;
1679*61046927SAndroid Build Coastguard Worker       set_src_val(src, new_val);
1680*61046927SAndroid Build Coastguard Worker    }
1681*61046927SAndroid Build Coastguard Worker }
1682*61046927SAndroid Build Coastguard Worker 
1683*61046927SAndroid Build Coastguard Worker static void
spill_live_out(struct ra_spill_ctx * ctx,struct ra_spill_interval * interval,struct ir3_block * block)1684*61046927SAndroid Build Coastguard Worker spill_live_out(struct ra_spill_ctx *ctx, struct ra_spill_interval *interval,
1685*61046927SAndroid Build Coastguard Worker                struct ir3_block *block)
1686*61046927SAndroid Build Coastguard Worker {
1687*61046927SAndroid Build Coastguard Worker    struct ir3_register *def = interval->interval.reg;
1688*61046927SAndroid Build Coastguard Worker 
1689*61046927SAndroid Build Coastguard Worker    if (interval->interval.reg->merge_set ||
1690*61046927SAndroid Build Coastguard Worker        !interval->can_rematerialize) {
1691*61046927SAndroid Build Coastguard Worker       spill(ctx, &interval->dst, get_spill_slot(ctx, def),
1692*61046927SAndroid Build Coastguard Worker             ir3_before_terminator(block));
1693*61046927SAndroid Build Coastguard Worker    }
1694*61046927SAndroid Build Coastguard Worker    ir3_reg_interval_remove_all(&ctx->reg_ctx, &interval->interval);
1695*61046927SAndroid Build Coastguard Worker }
1696*61046927SAndroid Build Coastguard Worker 
1697*61046927SAndroid Build Coastguard Worker static void
spill_live_outs(struct ra_spill_ctx * ctx,struct ir3_block * block)1698*61046927SAndroid Build Coastguard Worker spill_live_outs(struct ra_spill_ctx *ctx, struct ir3_block *block)
1699*61046927SAndroid Build Coastguard Worker {
1700*61046927SAndroid Build Coastguard Worker    struct ra_spill_block_state *state = &ctx->blocks[block->index];
1701*61046927SAndroid Build Coastguard Worker    rb_tree_foreach_safe (struct ra_spill_interval, interval,
1702*61046927SAndroid Build Coastguard Worker                          &ctx->reg_ctx.intervals, interval.node) {
1703*61046927SAndroid Build Coastguard Worker       if (!BITSET_TEST(state->live_out, interval->interval.reg->name)) {
1704*61046927SAndroid Build Coastguard Worker          spill_live_out(ctx, interval, block);
1705*61046927SAndroid Build Coastguard Worker       }
1706*61046927SAndroid Build Coastguard Worker    }
1707*61046927SAndroid Build Coastguard Worker }
1708*61046927SAndroid Build Coastguard Worker 
1709*61046927SAndroid Build Coastguard Worker static void
reload_live_out(struct ra_spill_ctx * ctx,struct ir3_register * def,struct ir3_block * block)1710*61046927SAndroid Build Coastguard Worker reload_live_out(struct ra_spill_ctx *ctx, struct ir3_register *def,
1711*61046927SAndroid Build Coastguard Worker                 struct ir3_block *block)
1712*61046927SAndroid Build Coastguard Worker {
1713*61046927SAndroid Build Coastguard Worker    struct ra_spill_interval *interval = ctx->intervals[def->name];
1714*61046927SAndroid Build Coastguard Worker    ir3_reg_interval_insert(&ctx->reg_ctx, &interval->interval);
1715*61046927SAndroid Build Coastguard Worker 
1716*61046927SAndroid Build Coastguard Worker    reload_def(ctx, def, ir3_before_terminator(block));
1717*61046927SAndroid Build Coastguard Worker }
1718*61046927SAndroid Build Coastguard Worker 
1719*61046927SAndroid Build Coastguard Worker static void
reload_live_outs(struct ra_spill_ctx * ctx,struct ir3_block * block)1720*61046927SAndroid Build Coastguard Worker reload_live_outs(struct ra_spill_ctx *ctx, struct ir3_block *block)
1721*61046927SAndroid Build Coastguard Worker {
1722*61046927SAndroid Build Coastguard Worker    struct ra_spill_block_state *state = &ctx->blocks[block->index];
1723*61046927SAndroid Build Coastguard Worker    unsigned name;
1724*61046927SAndroid Build Coastguard Worker    BITSET_FOREACH_SET (name, state->live_out, ctx->live->definitions_count) {
1725*61046927SAndroid Build Coastguard Worker       struct ir3_register *reg = ctx->live->definitions[name];
1726*61046927SAndroid Build Coastguard Worker       struct ra_spill_interval *interval = ctx->intervals[name];
1727*61046927SAndroid Build Coastguard Worker       if (!interval->interval.inserted)
1728*61046927SAndroid Build Coastguard Worker          reload_live_out(ctx, reg, block);
1729*61046927SAndroid Build Coastguard Worker    }
1730*61046927SAndroid Build Coastguard Worker }
1731*61046927SAndroid Build Coastguard Worker 
1732*61046927SAndroid Build Coastguard Worker static void
update_live_out_phis(struct ra_spill_ctx * ctx,struct ir3_block * block)1733*61046927SAndroid Build Coastguard Worker update_live_out_phis(struct ra_spill_ctx *ctx, struct ir3_block *block)
1734*61046927SAndroid Build Coastguard Worker {
1735*61046927SAndroid Build Coastguard Worker    assert(!block->successors[1]);
1736*61046927SAndroid Build Coastguard Worker    struct ir3_block *succ = block->successors[0];
1737*61046927SAndroid Build Coastguard Worker    unsigned pred_idx = ir3_block_get_pred_index(succ, block);
1738*61046927SAndroid Build Coastguard Worker 
1739*61046927SAndroid Build Coastguard Worker    foreach_instr (instr, &succ->instr_list) {
1740*61046927SAndroid Build Coastguard Worker       if (instr->opc != OPC_META_PHI)
1741*61046927SAndroid Build Coastguard Worker          break;
1742*61046927SAndroid Build Coastguard Worker 
1743*61046927SAndroid Build Coastguard Worker       struct ir3_register *def = instr->srcs[pred_idx]->def;
1744*61046927SAndroid Build Coastguard Worker       if (!def)
1745*61046927SAndroid Build Coastguard Worker          continue;
1746*61046927SAndroid Build Coastguard Worker 
1747*61046927SAndroid Build Coastguard Worker       struct ra_spill_interval *interval = ctx->intervals[def->name];
1748*61046927SAndroid Build Coastguard Worker       if (!interval->interval.inserted)
1749*61046927SAndroid Build Coastguard Worker          continue;
1750*61046927SAndroid Build Coastguard Worker       set_src_val(instr->srcs[pred_idx], &interval->dst);
1751*61046927SAndroid Build Coastguard Worker    }
1752*61046927SAndroid Build Coastguard Worker }
1753*61046927SAndroid Build Coastguard Worker 
1754*61046927SAndroid Build Coastguard Worker static void
record_pred_live_out(struct ra_spill_ctx * ctx,struct ra_spill_interval * interval,struct ir3_block * block,unsigned pred_idx)1755*61046927SAndroid Build Coastguard Worker record_pred_live_out(struct ra_spill_ctx *ctx,
1756*61046927SAndroid Build Coastguard Worker                      struct ra_spill_interval *interval,
1757*61046927SAndroid Build Coastguard Worker                      struct ir3_block *block, unsigned pred_idx)
1758*61046927SAndroid Build Coastguard Worker {
1759*61046927SAndroid Build Coastguard Worker    struct ir3_block *pred = block->predecessors[pred_idx];
1760*61046927SAndroid Build Coastguard Worker    struct ra_spill_block_state *state = &ctx->blocks[pred->index];
1761*61046927SAndroid Build Coastguard Worker 
1762*61046927SAndroid Build Coastguard Worker    struct ir3_register *def = interval->interval.reg;
1763*61046927SAndroid Build Coastguard Worker    if (is_live_in_phi(def, block)) {
1764*61046927SAndroid Build Coastguard Worker       def = def->instr->srcs[pred_idx]->def;
1765*61046927SAndroid Build Coastguard Worker    }
1766*61046927SAndroid Build Coastguard Worker    BITSET_SET(state->live_out, def->name);
1767*61046927SAndroid Build Coastguard Worker 
1768*61046927SAndroid Build Coastguard Worker    rb_tree_foreach (struct ra_spill_interval, child,
1769*61046927SAndroid Build Coastguard Worker                     &interval->interval.children, interval.node) {
1770*61046927SAndroid Build Coastguard Worker       record_pred_live_out(ctx, child, block, pred_idx);
1771*61046927SAndroid Build Coastguard Worker    }
1772*61046927SAndroid Build Coastguard Worker }
1773*61046927SAndroid Build Coastguard Worker 
1774*61046927SAndroid Build Coastguard Worker static void
record_pred_live_outs(struct ra_spill_ctx * ctx,struct ir3_block * block)1775*61046927SAndroid Build Coastguard Worker record_pred_live_outs(struct ra_spill_ctx *ctx, struct ir3_block *block)
1776*61046927SAndroid Build Coastguard Worker {
1777*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < block->predecessors_count; i++) {
1778*61046927SAndroid Build Coastguard Worker       struct ir3_block *pred = block->predecessors[i];
1779*61046927SAndroid Build Coastguard Worker       struct ra_spill_block_state *state = &ctx->blocks[pred->index];
1780*61046927SAndroid Build Coastguard Worker       if (state->visited)
1781*61046927SAndroid Build Coastguard Worker          continue;
1782*61046927SAndroid Build Coastguard Worker 
1783*61046927SAndroid Build Coastguard Worker       state->live_out = rzalloc_array(ctx, BITSET_WORD,
1784*61046927SAndroid Build Coastguard Worker                                       BITSET_WORDS(ctx->live->definitions_count));
1785*61046927SAndroid Build Coastguard Worker 
1786*61046927SAndroid Build Coastguard Worker 
1787*61046927SAndroid Build Coastguard Worker       rb_tree_foreach (struct ra_spill_interval, interval,
1788*61046927SAndroid Build Coastguard Worker                        &ctx->reg_ctx.intervals, interval.node) {
1789*61046927SAndroid Build Coastguard Worker          record_pred_live_out(ctx, interval, block, i);
1790*61046927SAndroid Build Coastguard Worker       }
1791*61046927SAndroid Build Coastguard Worker    }
1792*61046927SAndroid Build Coastguard Worker }
1793*61046927SAndroid Build Coastguard Worker 
1794*61046927SAndroid Build Coastguard Worker static void
record_live_out(struct ra_spill_ctx * ctx,struct ra_spill_block_state * state,struct ra_spill_interval * interval)1795*61046927SAndroid Build Coastguard Worker record_live_out(struct ra_spill_ctx *ctx,
1796*61046927SAndroid Build Coastguard Worker                 struct ra_spill_block_state *state,
1797*61046927SAndroid Build Coastguard Worker                 struct ra_spill_interval *interval)
1798*61046927SAndroid Build Coastguard Worker {
1799*61046927SAndroid Build Coastguard Worker    if (!(interval->dst.flags & IR3_REG_SSA) ||
1800*61046927SAndroid Build Coastguard Worker        interval->dst.def) {
1801*61046927SAndroid Build Coastguard Worker       struct reg_or_immed *val = ralloc(ctx, struct reg_or_immed);
1802*61046927SAndroid Build Coastguard Worker       *val = interval->dst;
1803*61046927SAndroid Build Coastguard Worker       _mesa_hash_table_insert(state->remap, interval->interval.reg, val);
1804*61046927SAndroid Build Coastguard Worker    }
1805*61046927SAndroid Build Coastguard Worker    rb_tree_foreach (struct ra_spill_interval, child,
1806*61046927SAndroid Build Coastguard Worker                     &interval->interval.children, interval.node) {
1807*61046927SAndroid Build Coastguard Worker       record_live_out(ctx, state, child);
1808*61046927SAndroid Build Coastguard Worker    }
1809*61046927SAndroid Build Coastguard Worker }
1810*61046927SAndroid Build Coastguard Worker 
1811*61046927SAndroid Build Coastguard Worker static void
record_live_outs(struct ra_spill_ctx * ctx,struct ir3_block * block)1812*61046927SAndroid Build Coastguard Worker record_live_outs(struct ra_spill_ctx *ctx, struct ir3_block *block)
1813*61046927SAndroid Build Coastguard Worker {
1814*61046927SAndroid Build Coastguard Worker    struct ra_spill_block_state *state = &ctx->blocks[block->index];
1815*61046927SAndroid Build Coastguard Worker    state->remap = _mesa_pointer_hash_table_create(ctx);
1816*61046927SAndroid Build Coastguard Worker 
1817*61046927SAndroid Build Coastguard Worker    rb_tree_foreach (struct ra_spill_interval, interval, &ctx->reg_ctx.intervals,
1818*61046927SAndroid Build Coastguard Worker                     interval.node) {
1819*61046927SAndroid Build Coastguard Worker       record_live_out(ctx, state, interval);
1820*61046927SAndroid Build Coastguard Worker    }
1821*61046927SAndroid Build Coastguard Worker }
1822*61046927SAndroid Build Coastguard Worker 
1823*61046927SAndroid Build Coastguard Worker static void
handle_block(struct ra_spill_ctx * ctx,struct ir3_block * block)1824*61046927SAndroid Build Coastguard Worker handle_block(struct ra_spill_ctx *ctx, struct ir3_block *block)
1825*61046927SAndroid Build Coastguard Worker {
1826*61046927SAndroid Build Coastguard Worker    memset(&ctx->cur_pressure, 0, sizeof(ctx->cur_pressure));
1827*61046927SAndroid Build Coastguard Worker    rb_tree_init(&ctx->reg_ctx.intervals);
1828*61046927SAndroid Build Coastguard Worker    rb_tree_init(&ctx->full_live_intervals);
1829*61046927SAndroid Build Coastguard Worker    rb_tree_init(&ctx->half_live_intervals);
1830*61046927SAndroid Build Coastguard Worker 
1831*61046927SAndroid Build Coastguard Worker    unsigned name;
1832*61046927SAndroid Build Coastguard Worker    BITSET_FOREACH_SET (name, ctx->live->live_in[block->index],
1833*61046927SAndroid Build Coastguard Worker                        ctx->live->definitions_count) {
1834*61046927SAndroid Build Coastguard Worker       struct ir3_register *reg = ctx->live->definitions[name];
1835*61046927SAndroid Build Coastguard Worker       handle_live_in(ctx, block, reg);
1836*61046927SAndroid Build Coastguard Worker    }
1837*61046927SAndroid Build Coastguard Worker 
1838*61046927SAndroid Build Coastguard Worker    foreach_instr (instr, &block->instr_list) {
1839*61046927SAndroid Build Coastguard Worker       if (instr->opc != OPC_META_PHI && instr->opc != OPC_META_INPUT &&
1840*61046927SAndroid Build Coastguard Worker           instr->opc != OPC_META_TEX_PREFETCH)
1841*61046927SAndroid Build Coastguard Worker          break;
1842*61046927SAndroid Build Coastguard Worker       handle_input_phi(ctx, instr);
1843*61046927SAndroid Build Coastguard Worker    }
1844*61046927SAndroid Build Coastguard Worker 
1845*61046927SAndroid Build Coastguard Worker    if (ctx->spilling) {
1846*61046927SAndroid Build Coastguard Worker       if (block->predecessors_count == 1 &&
1847*61046927SAndroid Build Coastguard Worker           block->predecessors[0]->successors[1]) {
1848*61046927SAndroid Build Coastguard Worker          spill_single_pred_live_in(ctx, block);
1849*61046927SAndroid Build Coastguard Worker       } else {
1850*61046927SAndroid Build Coastguard Worker          spill_live_ins(ctx, block);
1851*61046927SAndroid Build Coastguard Worker          reload_live_ins(ctx, block);
1852*61046927SAndroid Build Coastguard Worker          record_pred_live_outs(ctx, block);
1853*61046927SAndroid Build Coastguard Worker          foreach_instr (instr, &block->instr_list) {
1854*61046927SAndroid Build Coastguard Worker             if (instr->opc != OPC_META_PHI)
1855*61046927SAndroid Build Coastguard Worker                break;
1856*61046927SAndroid Build Coastguard Worker             rewrite_phi(ctx, instr, block);
1857*61046927SAndroid Build Coastguard Worker          }
1858*61046927SAndroid Build Coastguard Worker          add_live_in_phis(ctx, block);
1859*61046927SAndroid Build Coastguard Worker       }
1860*61046927SAndroid Build Coastguard Worker    } else {
1861*61046927SAndroid Build Coastguard Worker       update_max_pressure(ctx);
1862*61046927SAndroid Build Coastguard Worker    }
1863*61046927SAndroid Build Coastguard Worker 
1864*61046927SAndroid Build Coastguard Worker    foreach_instr (instr, &block->instr_list) {
1865*61046927SAndroid Build Coastguard Worker       di(instr, "processing");
1866*61046927SAndroid Build Coastguard Worker 
1867*61046927SAndroid Build Coastguard Worker       if (instr->opc == OPC_META_PHI || instr->opc == OPC_META_INPUT ||
1868*61046927SAndroid Build Coastguard Worker           instr->opc == OPC_META_TEX_PREFETCH)
1869*61046927SAndroid Build Coastguard Worker          remove_input_phi(ctx, instr);
1870*61046927SAndroid Build Coastguard Worker       else if (ctx->spilling && instr->opc == OPC_META_PARALLEL_COPY)
1871*61046927SAndroid Build Coastguard Worker          handle_pcopy(ctx, instr);
1872*61046927SAndroid Build Coastguard Worker       else if (ctx->spilling && instr->opc == OPC_MOV &&
1873*61046927SAndroid Build Coastguard Worker                instr->dsts[0] == ctx->base_reg)
1874*61046927SAndroid Build Coastguard Worker          /* skip */;
1875*61046927SAndroid Build Coastguard Worker       else
1876*61046927SAndroid Build Coastguard Worker          handle_instr(ctx, instr);
1877*61046927SAndroid Build Coastguard Worker    }
1878*61046927SAndroid Build Coastguard Worker 
1879*61046927SAndroid Build Coastguard Worker    if (ctx->spilling && block->successors[0]) {
1880*61046927SAndroid Build Coastguard Worker       struct ra_spill_block_state *state =
1881*61046927SAndroid Build Coastguard Worker          &ctx->blocks[block->successors[0]->index];
1882*61046927SAndroid Build Coastguard Worker       if (state->visited) {
1883*61046927SAndroid Build Coastguard Worker          assert(!block->successors[1]);
1884*61046927SAndroid Build Coastguard Worker 
1885*61046927SAndroid Build Coastguard Worker          spill_live_outs(ctx, block);
1886*61046927SAndroid Build Coastguard Worker          reload_live_outs(ctx, block);
1887*61046927SAndroid Build Coastguard Worker          update_live_out_phis(ctx, block);
1888*61046927SAndroid Build Coastguard Worker       }
1889*61046927SAndroid Build Coastguard Worker    }
1890*61046927SAndroid Build Coastguard Worker 
1891*61046927SAndroid Build Coastguard Worker    if (ctx->spilling) {
1892*61046927SAndroid Build Coastguard Worker       record_live_outs(ctx, block);
1893*61046927SAndroid Build Coastguard Worker       ctx->blocks[block->index].visited = true;
1894*61046927SAndroid Build Coastguard Worker    }
1895*61046927SAndroid Build Coastguard Worker }
1896*61046927SAndroid Build Coastguard Worker 
1897*61046927SAndroid Build Coastguard Worker static bool
simplify_phi_node(struct ir3_instruction * phi)1898*61046927SAndroid Build Coastguard Worker simplify_phi_node(struct ir3_instruction *phi)
1899*61046927SAndroid Build Coastguard Worker {
1900*61046927SAndroid Build Coastguard Worker    struct ir3_register *def = NULL;
1901*61046927SAndroid Build Coastguard Worker    foreach_src (src, phi) {
1902*61046927SAndroid Build Coastguard Worker       /* Ignore phi sources which point to the phi itself. */
1903*61046927SAndroid Build Coastguard Worker       if (src->def == phi->dsts[0])
1904*61046927SAndroid Build Coastguard Worker          continue;
1905*61046927SAndroid Build Coastguard Worker       /* If it's undef or it doesn't match the previous sources, bail */
1906*61046927SAndroid Build Coastguard Worker       if (!src->def || (def && def != src->def))
1907*61046927SAndroid Build Coastguard Worker          return false;
1908*61046927SAndroid Build Coastguard Worker       def = src->def;
1909*61046927SAndroid Build Coastguard Worker    }
1910*61046927SAndroid Build Coastguard Worker 
1911*61046927SAndroid Build Coastguard Worker    phi->data = def;
1912*61046927SAndroid Build Coastguard Worker    phi->flags |= IR3_INSTR_UNUSED;
1913*61046927SAndroid Build Coastguard Worker    return true;
1914*61046927SAndroid Build Coastguard Worker }
1915*61046927SAndroid Build Coastguard Worker 
1916*61046927SAndroid Build Coastguard Worker static struct ir3_register *
simplify_phi_def(struct ir3_register * def)1917*61046927SAndroid Build Coastguard Worker simplify_phi_def(struct ir3_register *def)
1918*61046927SAndroid Build Coastguard Worker {
1919*61046927SAndroid Build Coastguard Worker    if (def->instr->opc == OPC_META_PHI) {
1920*61046927SAndroid Build Coastguard Worker       struct ir3_instruction *phi = def->instr;
1921*61046927SAndroid Build Coastguard Worker 
1922*61046927SAndroid Build Coastguard Worker       /* Note: this function is always called at least once after visiting the
1923*61046927SAndroid Build Coastguard Worker        * phi, so either there has been a simplified phi in the meantime, in
1924*61046927SAndroid Build Coastguard Worker        * which case we will set progress=true and visit the definition again, or
1925*61046927SAndroid Build Coastguard Worker        * phi->data already has the most up-to-date value. Therefore we don't
1926*61046927SAndroid Build Coastguard Worker        * have to recursively check phi->data.
1927*61046927SAndroid Build Coastguard Worker        */
1928*61046927SAndroid Build Coastguard Worker       if (phi->data)
1929*61046927SAndroid Build Coastguard Worker          return phi->data;
1930*61046927SAndroid Build Coastguard Worker    }
1931*61046927SAndroid Build Coastguard Worker 
1932*61046927SAndroid Build Coastguard Worker    return def;
1933*61046927SAndroid Build Coastguard Worker }
1934*61046927SAndroid Build Coastguard Worker 
1935*61046927SAndroid Build Coastguard Worker static void
simplify_phi_srcs(struct ir3_instruction * instr)1936*61046927SAndroid Build Coastguard Worker simplify_phi_srcs(struct ir3_instruction *instr)
1937*61046927SAndroid Build Coastguard Worker {
1938*61046927SAndroid Build Coastguard Worker    foreach_src (src, instr) {
1939*61046927SAndroid Build Coastguard Worker       if (src->def)
1940*61046927SAndroid Build Coastguard Worker          src->def = simplify_phi_def(src->def);
1941*61046927SAndroid Build Coastguard Worker    }
1942*61046927SAndroid Build Coastguard Worker }
1943*61046927SAndroid Build Coastguard Worker 
1944*61046927SAndroid Build Coastguard Worker /* We insert phi nodes for all live-ins of loops in case we need to split the
1945*61046927SAndroid Build Coastguard Worker  * live range. This pass cleans that up for the case where the live range didn't
1946*61046927SAndroid Build Coastguard Worker  * actually need to be split.
1947*61046927SAndroid Build Coastguard Worker  */
1948*61046927SAndroid Build Coastguard Worker static void
simplify_phi_nodes(struct ir3 * ir)1949*61046927SAndroid Build Coastguard Worker simplify_phi_nodes(struct ir3 *ir)
1950*61046927SAndroid Build Coastguard Worker {
1951*61046927SAndroid Build Coastguard Worker    foreach_block (block, &ir->block_list) {
1952*61046927SAndroid Build Coastguard Worker       foreach_instr (instr, &block->instr_list) {
1953*61046927SAndroid Build Coastguard Worker          if (instr->opc != OPC_META_PHI)
1954*61046927SAndroid Build Coastguard Worker             break;
1955*61046927SAndroid Build Coastguard Worker          instr->data = NULL;
1956*61046927SAndroid Build Coastguard Worker       }
1957*61046927SAndroid Build Coastguard Worker    }
1958*61046927SAndroid Build Coastguard Worker 
1959*61046927SAndroid Build Coastguard Worker    bool progress;
1960*61046927SAndroid Build Coastguard Worker    do {
1961*61046927SAndroid Build Coastguard Worker       progress = false;
1962*61046927SAndroid Build Coastguard Worker       foreach_block (block, &ir->block_list) {
1963*61046927SAndroid Build Coastguard Worker          foreach_instr (instr, &block->instr_list) {
1964*61046927SAndroid Build Coastguard Worker             if (instr->opc == OPC_META_PHI || (instr->flags & IR3_INSTR_UNUSED))
1965*61046927SAndroid Build Coastguard Worker                continue;
1966*61046927SAndroid Build Coastguard Worker 
1967*61046927SAndroid Build Coastguard Worker             simplify_phi_srcs(instr);
1968*61046927SAndroid Build Coastguard Worker          }
1969*61046927SAndroid Build Coastguard Worker 
1970*61046927SAndroid Build Coastguard Worker          /* Visit phi nodes in the successors to make sure that phi sources are
1971*61046927SAndroid Build Coastguard Worker           * always visited at least once after visiting the definition they
1972*61046927SAndroid Build Coastguard Worker           * point to. See note in simplify_phi_def() for why this is necessary.
1973*61046927SAndroid Build Coastguard Worker           */
1974*61046927SAndroid Build Coastguard Worker          for (unsigned i = 0; i < 2; i++) {
1975*61046927SAndroid Build Coastguard Worker             struct ir3_block *succ = block->successors[i];
1976*61046927SAndroid Build Coastguard Worker             if (!succ)
1977*61046927SAndroid Build Coastguard Worker                continue;
1978*61046927SAndroid Build Coastguard Worker             foreach_instr (instr, &succ->instr_list) {
1979*61046927SAndroid Build Coastguard Worker                if (instr->opc != OPC_META_PHI)
1980*61046927SAndroid Build Coastguard Worker                   break;
1981*61046927SAndroid Build Coastguard Worker                if (instr->flags & IR3_INSTR_UNUSED) {
1982*61046927SAndroid Build Coastguard Worker                   if (instr->data)
1983*61046927SAndroid Build Coastguard Worker                      instr->data = simplify_phi_def(instr->data);
1984*61046927SAndroid Build Coastguard Worker                } else {
1985*61046927SAndroid Build Coastguard Worker                   simplify_phi_srcs(instr);
1986*61046927SAndroid Build Coastguard Worker                   progress |= simplify_phi_node(instr);
1987*61046927SAndroid Build Coastguard Worker                }
1988*61046927SAndroid Build Coastguard Worker             }
1989*61046927SAndroid Build Coastguard Worker          }
1990*61046927SAndroid Build Coastguard Worker       }
1991*61046927SAndroid Build Coastguard Worker    } while (progress);
1992*61046927SAndroid Build Coastguard Worker }
1993*61046927SAndroid Build Coastguard Worker 
1994*61046927SAndroid Build Coastguard Worker static void
unmark_dead(struct ir3 * ir)1995*61046927SAndroid Build Coastguard Worker unmark_dead(struct ir3 *ir)
1996*61046927SAndroid Build Coastguard Worker {
1997*61046927SAndroid Build Coastguard Worker    foreach_block (block, &ir->block_list) {
1998*61046927SAndroid Build Coastguard Worker       foreach_instr (instr, &block->instr_list) {
1999*61046927SAndroid Build Coastguard Worker          instr->flags &= ~IR3_INSTR_UNUSED;
2000*61046927SAndroid Build Coastguard Worker       }
2001*61046927SAndroid Build Coastguard Worker    }
2002*61046927SAndroid Build Coastguard Worker }
2003*61046927SAndroid Build Coastguard Worker 
2004*61046927SAndroid Build Coastguard Worker /* Simple pass to remove now-dead phi nodes and pcopy instructions. We mark
2005*61046927SAndroid Build Coastguard Worker  * which ones are dead along the way, so there's nothing to compute here.
2006*61046927SAndroid Build Coastguard Worker  */
2007*61046927SAndroid Build Coastguard Worker static void
cleanup_dead(struct ir3 * ir)2008*61046927SAndroid Build Coastguard Worker cleanup_dead(struct ir3 *ir)
2009*61046927SAndroid Build Coastguard Worker {
2010*61046927SAndroid Build Coastguard Worker    foreach_block (block, &ir->block_list) {
2011*61046927SAndroid Build Coastguard Worker       foreach_instr_safe (instr, &block->instr_list) {
2012*61046927SAndroid Build Coastguard Worker          if (instr->flags & IR3_INSTR_UNUSED) {
2013*61046927SAndroid Build Coastguard Worker             if (instr->opc == OPC_META_PARALLEL_COPY) {
2014*61046927SAndroid Build Coastguard Worker                /* There may be non-SSA shared copies, we need to preserve these.
2015*61046927SAndroid Build Coastguard Worker                 */
2016*61046927SAndroid Build Coastguard Worker                for (unsigned i = 0; i < instr->dsts_count;) {
2017*61046927SAndroid Build Coastguard Worker                   if (instr->dsts[i]->flags & IR3_REG_SSA) {
2018*61046927SAndroid Build Coastguard Worker                      instr->dsts[i] = instr->dsts[--instr->dsts_count];
2019*61046927SAndroid Build Coastguard Worker                      instr->srcs[i] = instr->srcs[--instr->srcs_count];
2020*61046927SAndroid Build Coastguard Worker                   } else {
2021*61046927SAndroid Build Coastguard Worker                      i++;
2022*61046927SAndroid Build Coastguard Worker                   }
2023*61046927SAndroid Build Coastguard Worker                }
2024*61046927SAndroid Build Coastguard Worker 
2025*61046927SAndroid Build Coastguard Worker                if (instr->dsts_count == 0)
2026*61046927SAndroid Build Coastguard Worker                   list_delinit(&instr->node);
2027*61046927SAndroid Build Coastguard Worker             } else {
2028*61046927SAndroid Build Coastguard Worker                list_delinit(&instr->node);
2029*61046927SAndroid Build Coastguard Worker             }
2030*61046927SAndroid Build Coastguard Worker          }
2031*61046927SAndroid Build Coastguard Worker       }
2032*61046927SAndroid Build Coastguard Worker    }
2033*61046927SAndroid Build Coastguard Worker }
2034*61046927SAndroid Build Coastguard Worker 
2035*61046927SAndroid Build Coastguard Worker /* Deal with merge sets after spilling. Spilling generally leaves the merge sets
2036*61046927SAndroid Build Coastguard Worker  * in a mess, and even if we properly cleaned up after ourselves, we would want
2037*61046927SAndroid Build Coastguard Worker  * to recompute the merge sets afterward anway. That's because
2038*61046927SAndroid Build Coastguard Worker  * spilling/reloading can "break up" phi webs and split/collect webs so that
2039*61046927SAndroid Build Coastguard Worker  * allocating them to the same register no longer gives any benefit. For
2040*61046927SAndroid Build Coastguard Worker  * example, imagine we have this:
2041*61046927SAndroid Build Coastguard Worker  *
2042*61046927SAndroid Build Coastguard Worker  * if (...) {
2043*61046927SAndroid Build Coastguard Worker  *    foo = ...
2044*61046927SAndroid Build Coastguard Worker  * } else {
2045*61046927SAndroid Build Coastguard Worker  *    bar = ...
2046*61046927SAndroid Build Coastguard Worker  * }
2047*61046927SAndroid Build Coastguard Worker  * baz = phi(foo, bar)
2048*61046927SAndroid Build Coastguard Worker  *
2049*61046927SAndroid Build Coastguard Worker  * and we spill "baz":
2050*61046927SAndroid Build Coastguard Worker  *
2051*61046927SAndroid Build Coastguard Worker  * if (...) {
2052*61046927SAndroid Build Coastguard Worker  *    foo = ...
2053*61046927SAndroid Build Coastguard Worker  *    spill(foo)
2054*61046927SAndroid Build Coastguard Worker  * } else {
2055*61046927SAndroid Build Coastguard Worker  *    bar = ...
2056*61046927SAndroid Build Coastguard Worker  *    spill(bar)
2057*61046927SAndroid Build Coastguard Worker  * }
2058*61046927SAndroid Build Coastguard Worker  * baz = reload()
2059*61046927SAndroid Build Coastguard Worker  *
2060*61046927SAndroid Build Coastguard Worker  * now foo, bar, and baz don't have to be allocated to the same register. How
2061*61046927SAndroid Build Coastguard Worker  * exactly the merge sets change can be complicated, so it's easier just to
2062*61046927SAndroid Build Coastguard Worker  * recompute them.
2063*61046927SAndroid Build Coastguard Worker  *
2064*61046927SAndroid Build Coastguard Worker  * However, there's a wrinkle in this: those same merge sets determine the
2065*61046927SAndroid Build Coastguard Worker  * register pressure, due to multiple values inhabiting the same register! And
2066*61046927SAndroid Build Coastguard Worker  * we assume that this sharing happens when spilling. Therefore we need a
2067*61046927SAndroid Build Coastguard Worker  * three-step procedure:
2068*61046927SAndroid Build Coastguard Worker  *
2069*61046927SAndroid Build Coastguard Worker  * 1. Drop the original merge sets.
2070*61046927SAndroid Build Coastguard Worker  * 2. Calculate which values *must* be merged, being careful to only use the
2071*61046927SAndroid Build Coastguard Worker  *    interval information which isn't trashed by spilling, and forcibly merge
2072*61046927SAndroid Build Coastguard Worker  *    them.
2073*61046927SAndroid Build Coastguard Worker  * 3. Let ir3_merge_regs() finish the job, including recalculating the
2074*61046927SAndroid Build Coastguard Worker  *    intervals.
2075*61046927SAndroid Build Coastguard Worker  */
2076*61046927SAndroid Build Coastguard Worker 
2077*61046927SAndroid Build Coastguard Worker static void
fixup_merge_sets(struct ir3_liveness * live,struct ir3 * ir)2078*61046927SAndroid Build Coastguard Worker fixup_merge_sets(struct ir3_liveness *live, struct ir3 *ir)
2079*61046927SAndroid Build Coastguard Worker {
2080*61046927SAndroid Build Coastguard Worker    foreach_block (block, &ir->block_list) {
2081*61046927SAndroid Build Coastguard Worker       foreach_instr (instr, &block->instr_list) {
2082*61046927SAndroid Build Coastguard Worker          foreach_dst (dst, instr) {
2083*61046927SAndroid Build Coastguard Worker             dst->merge_set = NULL;
2084*61046927SAndroid Build Coastguard Worker             dst->merge_set_offset = 0;
2085*61046927SAndroid Build Coastguard Worker          }
2086*61046927SAndroid Build Coastguard Worker       }
2087*61046927SAndroid Build Coastguard Worker    }
2088*61046927SAndroid Build Coastguard Worker 
2089*61046927SAndroid Build Coastguard Worker    ir3_index_instrs_for_merge_sets(ir);
2090*61046927SAndroid Build Coastguard Worker 
2091*61046927SAndroid Build Coastguard Worker    foreach_block (block, &ir->block_list) {
2092*61046927SAndroid Build Coastguard Worker       foreach_instr (instr, &block->instr_list) {
2093*61046927SAndroid Build Coastguard Worker          if (instr->opc != OPC_META_SPLIT &&
2094*61046927SAndroid Build Coastguard Worker              instr->opc != OPC_META_COLLECT)
2095*61046927SAndroid Build Coastguard Worker             continue;
2096*61046927SAndroid Build Coastguard Worker 
2097*61046927SAndroid Build Coastguard Worker          struct ir3_register *dst = instr->dsts[0];
2098*61046927SAndroid Build Coastguard Worker          ra_foreach_src (src, instr) {
2099*61046927SAndroid Build Coastguard Worker             if (!(src->flags & IR3_REG_KILL) &&
2100*61046927SAndroid Build Coastguard Worker                 src->def->interval_start < dst->interval_end &&
2101*61046927SAndroid Build Coastguard Worker                 dst->interval_start < src->def->interval_end) {
2102*61046927SAndroid Build Coastguard Worker                ir3_force_merge(dst, src->def,
2103*61046927SAndroid Build Coastguard Worker                                src->def->interval_start - dst->interval_start);
2104*61046927SAndroid Build Coastguard Worker             }
2105*61046927SAndroid Build Coastguard Worker          }
2106*61046927SAndroid Build Coastguard Worker       }
2107*61046927SAndroid Build Coastguard Worker    }
2108*61046927SAndroid Build Coastguard Worker 
2109*61046927SAndroid Build Coastguard Worker    ir3_merge_regs(live, ir);
2110*61046927SAndroid Build Coastguard Worker }
2111*61046927SAndroid Build Coastguard Worker 
2112*61046927SAndroid Build Coastguard Worker void
ir3_calc_pressure(struct ir3_shader_variant * v,struct ir3_liveness * live,struct ir3_pressure * max_pressure)2113*61046927SAndroid Build Coastguard Worker ir3_calc_pressure(struct ir3_shader_variant *v, struct ir3_liveness *live,
2114*61046927SAndroid Build Coastguard Worker                   struct ir3_pressure *max_pressure)
2115*61046927SAndroid Build Coastguard Worker {
2116*61046927SAndroid Build Coastguard Worker    struct ra_spill_ctx *ctx = rzalloc(NULL, struct ra_spill_ctx);
2117*61046927SAndroid Build Coastguard Worker    spill_ctx_init(ctx, v, live);
2118*61046927SAndroid Build Coastguard Worker 
2119*61046927SAndroid Build Coastguard Worker    foreach_block (block, &v->ir->block_list) {
2120*61046927SAndroid Build Coastguard Worker       handle_block(ctx, block);
2121*61046927SAndroid Build Coastguard Worker    }
2122*61046927SAndroid Build Coastguard Worker 
2123*61046927SAndroid Build Coastguard Worker    assert(ctx->cur_pressure.full == 0);
2124*61046927SAndroid Build Coastguard Worker    assert(ctx->cur_pressure.half == 0);
2125*61046927SAndroid Build Coastguard Worker    assert(ctx->cur_pressure.shared == 0);
2126*61046927SAndroid Build Coastguard Worker    assert(ctx->cur_pressure.shared_half == 0);
2127*61046927SAndroid Build Coastguard Worker 
2128*61046927SAndroid Build Coastguard Worker    *max_pressure = ctx->max_pressure;
2129*61046927SAndroid Build Coastguard Worker    ralloc_free(ctx);
2130*61046927SAndroid Build Coastguard Worker }
2131*61046927SAndroid Build Coastguard Worker 
2132*61046927SAndroid Build Coastguard Worker bool
ir3_spill(struct ir3 * ir,struct ir3_shader_variant * v,struct ir3_liveness ** live,const struct ir3_pressure * limit_pressure)2133*61046927SAndroid Build Coastguard Worker ir3_spill(struct ir3 *ir, struct ir3_shader_variant *v,
2134*61046927SAndroid Build Coastguard Worker           struct ir3_liveness **live,
2135*61046927SAndroid Build Coastguard Worker           const struct ir3_pressure *limit_pressure)
2136*61046927SAndroid Build Coastguard Worker {
2137*61046927SAndroid Build Coastguard Worker    void *mem_ctx = ralloc_parent(*live);
2138*61046927SAndroid Build Coastguard Worker    struct ra_spill_ctx *ctx = rzalloc(mem_ctx, struct ra_spill_ctx);
2139*61046927SAndroid Build Coastguard Worker    spill_ctx_init(ctx, v, *live);
2140*61046927SAndroid Build Coastguard Worker 
2141*61046927SAndroid Build Coastguard Worker    ctx->spilling = true;
2142*61046927SAndroid Build Coastguard Worker 
2143*61046927SAndroid Build Coastguard Worker    ctx->blocks = rzalloc_array(ctx, struct ra_spill_block_state,
2144*61046927SAndroid Build Coastguard Worker                                ctx->live->block_count);
2145*61046927SAndroid Build Coastguard Worker    rb_tree_init(&ctx->full_live_intervals);
2146*61046927SAndroid Build Coastguard Worker    rb_tree_init(&ctx->half_live_intervals);
2147*61046927SAndroid Build Coastguard Worker 
2148*61046927SAndroid Build Coastguard Worker    ctx->limit_pressure = *limit_pressure;
2149*61046927SAndroid Build Coastguard Worker    ctx->spill_slot = v->pvtmem_size;
2150*61046927SAndroid Build Coastguard Worker 
2151*61046927SAndroid Build Coastguard Worker    add_base_reg(ctx, ir);
2152*61046927SAndroid Build Coastguard Worker    compute_next_distance(ctx, ir);
2153*61046927SAndroid Build Coastguard Worker 
2154*61046927SAndroid Build Coastguard Worker    unmark_dead(ir);
2155*61046927SAndroid Build Coastguard Worker 
2156*61046927SAndroid Build Coastguard Worker    foreach_block (block, &ir->block_list) {
2157*61046927SAndroid Build Coastguard Worker       handle_block(ctx, block);
2158*61046927SAndroid Build Coastguard Worker    }
2159*61046927SAndroid Build Coastguard Worker 
2160*61046927SAndroid Build Coastguard Worker    simplify_phi_nodes(ir);
2161*61046927SAndroid Build Coastguard Worker 
2162*61046927SAndroid Build Coastguard Worker    cleanup_dead(ir);
2163*61046927SAndroid Build Coastguard Worker 
2164*61046927SAndroid Build Coastguard Worker    ir3_create_parallel_copies(ir);
2165*61046927SAndroid Build Coastguard Worker 
2166*61046927SAndroid Build Coastguard Worker    /* After this point, we're done mutating the IR. Liveness has been trashed,
2167*61046927SAndroid Build Coastguard Worker     * so recalculate it. We'll need it for recalculating the merge sets.
2168*61046927SAndroid Build Coastguard Worker     */
2169*61046927SAndroid Build Coastguard Worker    ralloc_free(ctx->live);
2170*61046927SAndroid Build Coastguard Worker    *live = ir3_calc_liveness(mem_ctx, ir);
2171*61046927SAndroid Build Coastguard Worker 
2172*61046927SAndroid Build Coastguard Worker    fixup_merge_sets(*live, ir);
2173*61046927SAndroid Build Coastguard Worker 
2174*61046927SAndroid Build Coastguard Worker    v->pvtmem_size = ctx->spill_slot;
2175*61046927SAndroid Build Coastguard Worker    ralloc_free(ctx);
2176*61046927SAndroid Build Coastguard Worker 
2177*61046927SAndroid Build Coastguard Worker    return true;
2178*61046927SAndroid Build Coastguard Worker }
2179