1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright (C) 2019-2020 Collabora, Ltd.
3bf215546Sopenharmony_ci * Copyright (C) 2019 Alyssa Rosenzweig <alyssa@rosenzweig.io>
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
8bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
10bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci *
12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
14bf215546Sopenharmony_ci * Software.
15bf215546Sopenharmony_ci *
16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22bf215546Sopenharmony_ci * SOFTWARE.
23bf215546Sopenharmony_ci */
24bf215546Sopenharmony_ci
25bf215546Sopenharmony_ci#ifndef _MDG_COMPILER_H
26bf215546Sopenharmony_ci#define _MDG_COMPILER_H
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include "midgard.h"
29bf215546Sopenharmony_ci#include "helpers.h"
30bf215546Sopenharmony_ci#include "midgard_compile.h"
31bf215546Sopenharmony_ci#include "midgard_ops.h"
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ci#include "util/hash_table.h"
34bf215546Sopenharmony_ci#include "util/u_dynarray.h"
35bf215546Sopenharmony_ci#include "util/set.h"
36bf215546Sopenharmony_ci#include "util/list.h"
37bf215546Sopenharmony_ci#include "util/u_math.h"
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_ci#include "compiler/nir_types.h"
40bf215546Sopenharmony_ci#include "compiler/nir/nir.h"
41bf215546Sopenharmony_ci#include "panfrost/util/pan_ir.h"
42bf215546Sopenharmony_ci#include "panfrost/util/lcra.h"
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_ci/* Forward declare */
45bf215546Sopenharmony_cistruct midgard_block;
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_ci/* Target types. Defaults to TARGET_GOTO (the type corresponding directly to
48bf215546Sopenharmony_ci * the hardware), hence why that must be zero. TARGET_DISCARD signals this
49bf215546Sopenharmony_ci * instruction is actually a discard op. */
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci#define TARGET_GOTO 0
52bf215546Sopenharmony_ci#define TARGET_BREAK 1
53bf215546Sopenharmony_ci#define TARGET_CONTINUE 2
54bf215546Sopenharmony_ci#define TARGET_DISCARD 3
55bf215546Sopenharmony_ci#define TARGET_TILEBUF_WAIT 4
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_citypedef struct midgard_branch {
58bf215546Sopenharmony_ci        /* If conditional, the condition is specified in r31.w */
59bf215546Sopenharmony_ci        bool conditional;
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_ci        /* For conditionals, if this is true, we branch on FALSE. If false, we  branch on TRUE. */
62bf215546Sopenharmony_ci        bool invert_conditional;
63bf215546Sopenharmony_ci
64bf215546Sopenharmony_ci        /* Branch targets: the start of a block, the start of a loop (continue), the end of a loop (break). Value is one of TARGET_ */
65bf215546Sopenharmony_ci        unsigned target_type;
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci        /* The actual target */
68bf215546Sopenharmony_ci        union {
69bf215546Sopenharmony_ci                int target_block;
70bf215546Sopenharmony_ci                int target_break;
71bf215546Sopenharmony_ci                int target_continue;
72bf215546Sopenharmony_ci        };
73bf215546Sopenharmony_ci} midgard_branch;
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci/* Generic in-memory data type repesenting a single logical instruction, rather
76bf215546Sopenharmony_ci * than a single instruction group. This is the preferred form for code gen.
77bf215546Sopenharmony_ci * Multiple midgard_insturctions will later be combined during scheduling,
78bf215546Sopenharmony_ci * though this is not represented in this structure.  Its format bridges
79bf215546Sopenharmony_ci * the low-level binary representation with the higher level semantic meaning.
80bf215546Sopenharmony_ci *
81bf215546Sopenharmony_ci * Notably, it allows registers to be specified as block local SSA, for code
82bf215546Sopenharmony_ci * emitted before the register allocation pass.
83bf215546Sopenharmony_ci */
84bf215546Sopenharmony_ci
85bf215546Sopenharmony_ci#define MIR_SRC_COUNT 4
86bf215546Sopenharmony_ci#define MIR_VEC_COMPONENTS 16
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_citypedef struct midgard_instruction {
89bf215546Sopenharmony_ci        /* Must be first for casting */
90bf215546Sopenharmony_ci        struct list_head link;
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ci        unsigned type; /* ALU, load/store, texture */
93bf215546Sopenharmony_ci
94bf215546Sopenharmony_ci        /* Instruction arguments represented as block-local SSA
95bf215546Sopenharmony_ci         * indices, rather than registers. ~0 means unused. */
96bf215546Sopenharmony_ci        unsigned src[MIR_SRC_COUNT];
97bf215546Sopenharmony_ci        unsigned dest;
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_ci        /* vec16 swizzle, unpacked, per source */
100bf215546Sopenharmony_ci        unsigned swizzle[MIR_SRC_COUNT][MIR_VEC_COMPONENTS];
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci        /* Types! */
103bf215546Sopenharmony_ci        nir_alu_type src_types[MIR_SRC_COUNT];
104bf215546Sopenharmony_ci        nir_alu_type dest_type;
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci        /* Packing ops have non-32-bit dest types even though they functionally
107bf215546Sopenharmony_ci         * work at the 32-bit level, use this as a signal to disable copyprop.
108bf215546Sopenharmony_ci         * We maybe need synthetic pack ops instead. */
109bf215546Sopenharmony_ci        bool is_pack;
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_ci        /* Modifiers, depending on type */
112bf215546Sopenharmony_ci        union {
113bf215546Sopenharmony_ci                struct {
114bf215546Sopenharmony_ci                        bool src_abs[MIR_SRC_COUNT];
115bf215546Sopenharmony_ci                        bool src_neg[MIR_SRC_COUNT];
116bf215546Sopenharmony_ci                };
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_ci                struct {
119bf215546Sopenharmony_ci                        bool src_shift[MIR_SRC_COUNT];
120bf215546Sopenharmony_ci                };
121bf215546Sopenharmony_ci        };
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci        /* Out of the union for csel (could maybe be fixed..) */
124bf215546Sopenharmony_ci        bool src_invert[MIR_SRC_COUNT];
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_ci        /* If the op supports it */
127bf215546Sopenharmony_ci        enum midgard_roundmode roundmode;
128bf215546Sopenharmony_ci
129bf215546Sopenharmony_ci        /* For textures: should helpers execute this instruction (instead of
130bf215546Sopenharmony_ci         * just helping with derivatives)? Should helpers terminate after? */
131bf215546Sopenharmony_ci        bool helper_terminate;
132bf215546Sopenharmony_ci        bool helper_execute;
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci        /* I.e. (1 << alu_bit) */
135bf215546Sopenharmony_ci        int unit;
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci        bool has_constants;
138bf215546Sopenharmony_ci        midgard_constants constants;
139bf215546Sopenharmony_ci        uint16_t inline_constant;
140bf215546Sopenharmony_ci        bool has_inline_constant;
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci        bool compact_branch;
143bf215546Sopenharmony_ci        uint8_t writeout;
144bf215546Sopenharmony_ci        bool last_writeout;
145bf215546Sopenharmony_ci
146bf215546Sopenharmony_ci        /* Masks in a saneish format. One bit per channel, not packed fancy.
147bf215546Sopenharmony_ci         * Use this instead of the op specific ones, and switch over at emit
148bf215546Sopenharmony_ci         * time */
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci        uint16_t mask;
151bf215546Sopenharmony_ci
152bf215546Sopenharmony_ci        /* Hint for the register allocator not to spill the destination written
153bf215546Sopenharmony_ci         * from this instruction (because it is a spill/unspill node itself).
154bf215546Sopenharmony_ci         * Bitmask of spilled classes */
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ci        unsigned no_spill;
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_ci        /* Generic hint for intra-pass use */
159bf215546Sopenharmony_ci        bool hint;
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci        /* During scheduling, the backwards dependency graph
162bf215546Sopenharmony_ci         * (DAG). nr_dependencies is the number of unscheduled
163bf215546Sopenharmony_ci         * instructions that must still be scheduled after
164bf215546Sopenharmony_ci         * (before) this instruction. dependents are which
165bf215546Sopenharmony_ci         * instructions need to be scheduled before (after) this
166bf215546Sopenharmony_ci         * instruction. */
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci        unsigned nr_dependencies;
169bf215546Sopenharmony_ci        BITSET_WORD *dependents;
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci        /* Use this in conjunction with `type` */
172bf215546Sopenharmony_ci        unsigned op;
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_ci        /* This refers to midgard_outmod_float or midgard_outmod_int.
175bf215546Sopenharmony_ci         * In case of a ALU op, use midgard_is_integer_out_op() to know which
176bf215546Sopenharmony_ci         * one is used.
177bf215546Sopenharmony_ci         * If it's a texture op, it's always midgard_outmod_float. */
178bf215546Sopenharmony_ci        unsigned outmod;
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci        union {
181bf215546Sopenharmony_ci                midgard_load_store_word load_store;
182bf215546Sopenharmony_ci                midgard_texture_word texture;
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ci                midgard_branch branch;
185bf215546Sopenharmony_ci        };
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_ci        unsigned bundle_id;
188bf215546Sopenharmony_ci} midgard_instruction;
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_citypedef struct midgard_block {
191bf215546Sopenharmony_ci        pan_block base;
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci        bool scheduled;
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_ci        /* List of midgard_bundles emitted (after the scheduler has run) */
196bf215546Sopenharmony_ci        struct util_dynarray bundles;
197bf215546Sopenharmony_ci
198bf215546Sopenharmony_ci        /* Number of quadwords _actually_ emitted, as determined after scheduling */
199bf215546Sopenharmony_ci        unsigned quadword_count;
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci        /* Indicates this is a fixed-function fragment epilogue block */
202bf215546Sopenharmony_ci        bool epilogue;
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci        /* Are helper invocations required by this block? */
205bf215546Sopenharmony_ci        bool helpers_in;
206bf215546Sopenharmony_ci} midgard_block;
207bf215546Sopenharmony_ci
208bf215546Sopenharmony_citypedef struct midgard_bundle {
209bf215546Sopenharmony_ci        /* Tag for the overall bundle */
210bf215546Sopenharmony_ci        int tag;
211bf215546Sopenharmony_ci
212bf215546Sopenharmony_ci        /* Instructions contained by the bundle. instruction_count <= 6 (vmul,
213bf215546Sopenharmony_ci         * sadd, vadd, smul, vlut, branch) */
214bf215546Sopenharmony_ci        int instruction_count;
215bf215546Sopenharmony_ci        midgard_instruction *instructions[6];
216bf215546Sopenharmony_ci
217bf215546Sopenharmony_ci        /* Bundle-wide ALU configuration */
218bf215546Sopenharmony_ci        int padding;
219bf215546Sopenharmony_ci        int control;
220bf215546Sopenharmony_ci        bool has_embedded_constants;
221bf215546Sopenharmony_ci        midgard_constants constants;
222bf215546Sopenharmony_ci        bool last_writeout;
223bf215546Sopenharmony_ci} midgard_bundle;
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_cienum midgard_rt_id {
226bf215546Sopenharmony_ci        MIDGARD_COLOR_RT0 = 0,
227bf215546Sopenharmony_ci        MIDGARD_COLOR_RT1,
228bf215546Sopenharmony_ci        MIDGARD_COLOR_RT2,
229bf215546Sopenharmony_ci        MIDGARD_COLOR_RT3,
230bf215546Sopenharmony_ci        MIDGARD_COLOR_RT4,
231bf215546Sopenharmony_ci        MIDGARD_COLOR_RT5,
232bf215546Sopenharmony_ci        MIDGARD_COLOR_RT6,
233bf215546Sopenharmony_ci        MIDGARD_COLOR_RT7,
234bf215546Sopenharmony_ci        MIDGARD_ZS_RT,
235bf215546Sopenharmony_ci        MIDGARD_NUM_RTS,
236bf215546Sopenharmony_ci};
237bf215546Sopenharmony_ci
238bf215546Sopenharmony_ci#define MIDGARD_MAX_SAMPLE_ITER 16
239bf215546Sopenharmony_ci
240bf215546Sopenharmony_citypedef struct compiler_context {
241bf215546Sopenharmony_ci        const struct panfrost_compile_inputs *inputs;
242bf215546Sopenharmony_ci        nir_shader *nir;
243bf215546Sopenharmony_ci        struct pan_shader_info *info;
244bf215546Sopenharmony_ci        gl_shader_stage stage;
245bf215546Sopenharmony_ci
246bf215546Sopenharmony_ci        /* Number of samples for a keyed blend shader. Depends on is_blend */
247bf215546Sopenharmony_ci        unsigned blend_sample_iterations;
248bf215546Sopenharmony_ci
249bf215546Sopenharmony_ci        /* Index to precolour to r0 for an input blend colour */
250bf215546Sopenharmony_ci        unsigned blend_input;
251bf215546Sopenharmony_ci
252bf215546Sopenharmony_ci        /* Index to precolour to r2 for a dual-source blend colour */
253bf215546Sopenharmony_ci        unsigned blend_src1;
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci        /* Count of spills and fills for shaderdb */
256bf215546Sopenharmony_ci        unsigned spills;
257bf215546Sopenharmony_ci        unsigned fills;
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_ci        /* Current NIR function */
260bf215546Sopenharmony_ci        nir_function *func;
261bf215546Sopenharmony_ci
262bf215546Sopenharmony_ci        /* Allocated compiler temporary counter */
263bf215546Sopenharmony_ci        unsigned temp_alloc;
264bf215546Sopenharmony_ci
265bf215546Sopenharmony_ci        /* Unordered list of midgard_blocks */
266bf215546Sopenharmony_ci        int block_count;
267bf215546Sopenharmony_ci        struct list_head blocks;
268bf215546Sopenharmony_ci
269bf215546Sopenharmony_ci        /* TODO merge with block_count? */
270bf215546Sopenharmony_ci        unsigned block_source_count;
271bf215546Sopenharmony_ci
272bf215546Sopenharmony_ci        /* List of midgard_instructions emitted for the current block */
273bf215546Sopenharmony_ci        midgard_block *current_block;
274bf215546Sopenharmony_ci
275bf215546Sopenharmony_ci        /* If there is a preset after block, use this, otherwise emit_block will create one if NULL */
276bf215546Sopenharmony_ci        midgard_block *after_block;
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_ci        /* The current "depth" of the loop, for disambiguating breaks/continues
279bf215546Sopenharmony_ci         * when using nested loops */
280bf215546Sopenharmony_ci        int current_loop_depth;
281bf215546Sopenharmony_ci
282bf215546Sopenharmony_ci        /* Total number of loops for shader-db */
283bf215546Sopenharmony_ci        unsigned loop_count;
284bf215546Sopenharmony_ci
285bf215546Sopenharmony_ci        /* Constants which have been loaded, for later inlining */
286bf215546Sopenharmony_ci        struct hash_table_u64 *ssa_constants;
287bf215546Sopenharmony_ci
288bf215546Sopenharmony_ci        int temp_count;
289bf215546Sopenharmony_ci        int max_hash;
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_ci        /* Set of NIR indices that were already emitted as outmods */
292bf215546Sopenharmony_ci        BITSET_WORD *already_emitted;
293bf215546Sopenharmony_ci
294bf215546Sopenharmony_ci        /* Count of instructions emitted from NIR overall, across all blocks */
295bf215546Sopenharmony_ci        int instruction_count;
296bf215546Sopenharmony_ci
297bf215546Sopenharmony_ci        unsigned quadword_count;
298bf215546Sopenharmony_ci
299bf215546Sopenharmony_ci        /* Bitmask of valid metadata */
300bf215546Sopenharmony_ci        unsigned metadata;
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_ci        /* Model-specific quirk set */
303bf215546Sopenharmony_ci        uint32_t quirks;
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_ci        /* Writeout instructions for each render target */
306bf215546Sopenharmony_ci        midgard_instruction *writeout_branch[MIDGARD_NUM_RTS][MIDGARD_MAX_SAMPLE_ITER];
307bf215546Sopenharmony_ci
308bf215546Sopenharmony_ci        struct hash_table_u64 *sysval_to_id;
309bf215546Sopenharmony_ci
310bf215546Sopenharmony_ci        /* Mask of UBOs that need to be uploaded */
311bf215546Sopenharmony_ci        uint32_t ubo_mask;
312bf215546Sopenharmony_ci} compiler_context;
313bf215546Sopenharmony_ci
314bf215546Sopenharmony_ci/* Per-block live_in/live_out */
315bf215546Sopenharmony_ci#define MIDGARD_METADATA_LIVENESS (1 << 0)
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_ci/* Helpers for manipulating the above structures (forming the driver IR) */
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci/* Append instruction to end of current block */
320bf215546Sopenharmony_ci
321bf215546Sopenharmony_cistatic inline midgard_instruction *
322bf215546Sopenharmony_cimir_upload_ins(struct compiler_context *ctx, struct midgard_instruction ins)
323bf215546Sopenharmony_ci{
324bf215546Sopenharmony_ci        midgard_instruction *heap = ralloc(ctx, struct midgard_instruction);
325bf215546Sopenharmony_ci        memcpy(heap, &ins, sizeof(ins));
326bf215546Sopenharmony_ci        return heap;
327bf215546Sopenharmony_ci}
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_cistatic inline midgard_instruction *
330bf215546Sopenharmony_ciemit_mir_instruction(struct compiler_context *ctx, struct midgard_instruction ins)
331bf215546Sopenharmony_ci{
332bf215546Sopenharmony_ci        midgard_instruction *u = mir_upload_ins(ctx, ins);
333bf215546Sopenharmony_ci        list_addtail(&u->link, &ctx->current_block->base.instructions);
334bf215546Sopenharmony_ci        return u;
335bf215546Sopenharmony_ci}
336bf215546Sopenharmony_ci
337bf215546Sopenharmony_cistatic inline struct midgard_instruction *
338bf215546Sopenharmony_cimir_insert_instruction_before(struct compiler_context *ctx,
339bf215546Sopenharmony_ci                              struct midgard_instruction *tag,
340bf215546Sopenharmony_ci                              struct midgard_instruction ins)
341bf215546Sopenharmony_ci{
342bf215546Sopenharmony_ci        struct midgard_instruction *u = mir_upload_ins(ctx, ins);
343bf215546Sopenharmony_ci        list_addtail(&u->link, &tag->link);
344bf215546Sopenharmony_ci        return u;
345bf215546Sopenharmony_ci}
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_cistatic inline void
348bf215546Sopenharmony_cimir_remove_instruction(struct midgard_instruction *ins)
349bf215546Sopenharmony_ci{
350bf215546Sopenharmony_ci        list_del(&ins->link);
351bf215546Sopenharmony_ci}
352bf215546Sopenharmony_ci
353bf215546Sopenharmony_cistatic inline midgard_instruction*
354bf215546Sopenharmony_cimir_prev_op(struct midgard_instruction *ins)
355bf215546Sopenharmony_ci{
356bf215546Sopenharmony_ci        return list_last_entry(&(ins->link), midgard_instruction, link);
357bf215546Sopenharmony_ci}
358bf215546Sopenharmony_ci
359bf215546Sopenharmony_cistatic inline midgard_instruction*
360bf215546Sopenharmony_cimir_next_op(struct midgard_instruction *ins)
361bf215546Sopenharmony_ci{
362bf215546Sopenharmony_ci        return list_first_entry(&(ins->link), midgard_instruction, link);
363bf215546Sopenharmony_ci}
364bf215546Sopenharmony_ci
365bf215546Sopenharmony_ci#define mir_foreach_block(ctx, v) \
366bf215546Sopenharmony_ci        list_for_each_entry(pan_block, v, &ctx->blocks, link)
367bf215546Sopenharmony_ci
368bf215546Sopenharmony_ci#define mir_foreach_block_from(ctx, from, v) \
369bf215546Sopenharmony_ci        list_for_each_entry_from(pan_block, v, &from->base, &ctx->blocks, link)
370bf215546Sopenharmony_ci
371bf215546Sopenharmony_ci#define mir_foreach_instr_in_block(block, v) \
372bf215546Sopenharmony_ci        list_for_each_entry(struct midgard_instruction, v, &block->base.instructions, link)
373bf215546Sopenharmony_ci#define mir_foreach_instr_in_block_rev(block, v) \
374bf215546Sopenharmony_ci        list_for_each_entry_rev(struct midgard_instruction, v, &block->base.instructions, link)
375bf215546Sopenharmony_ci
376bf215546Sopenharmony_ci#define mir_foreach_instr_in_block_safe(block, v) \
377bf215546Sopenharmony_ci        list_for_each_entry_safe(struct midgard_instruction, v, &block->base.instructions, link)
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_ci#define mir_foreach_instr_in_block_safe_rev(block, v) \
380bf215546Sopenharmony_ci        list_for_each_entry_safe_rev(struct midgard_instruction, v, &block->base.instructions, link)
381bf215546Sopenharmony_ci
382bf215546Sopenharmony_ci#define mir_foreach_instr_in_block_from(block, v, from) \
383bf215546Sopenharmony_ci        list_for_each_entry_from(struct midgard_instruction, v, from, &block->base.instructions, link)
384bf215546Sopenharmony_ci
385bf215546Sopenharmony_ci#define mir_foreach_instr_in_block_from_rev(block, v, from) \
386bf215546Sopenharmony_ci        list_for_each_entry_from_rev(struct midgard_instruction, v, from, &block->base.instructions, link)
387bf215546Sopenharmony_ci
388bf215546Sopenharmony_ci#define mir_foreach_bundle_in_block(block, v) \
389bf215546Sopenharmony_ci        util_dynarray_foreach(&block->bundles, midgard_bundle, v)
390bf215546Sopenharmony_ci
391bf215546Sopenharmony_ci#define mir_foreach_bundle_in_block_rev(block, v) \
392bf215546Sopenharmony_ci        util_dynarray_foreach_reverse(&block->bundles, midgard_bundle, v)
393bf215546Sopenharmony_ci
394bf215546Sopenharmony_ci#define mir_foreach_instr_in_block_scheduled_rev(block, v) \
395bf215546Sopenharmony_ci        midgard_instruction* v; \
396bf215546Sopenharmony_ci        signed i = 0; \
397bf215546Sopenharmony_ci        mir_foreach_bundle_in_block_rev(block, _bundle) \
398bf215546Sopenharmony_ci                for (i = (_bundle->instruction_count - 1), v = _bundle->instructions[i]; \
399bf215546Sopenharmony_ci                                i >= 0; \
400bf215546Sopenharmony_ci                                --i, v = (i >= 0) ? _bundle->instructions[i] : NULL) \
401bf215546Sopenharmony_ci
402bf215546Sopenharmony_ci#define mir_foreach_instr_global(ctx, v) \
403bf215546Sopenharmony_ci        mir_foreach_block(ctx, v_block) \
404bf215546Sopenharmony_ci                mir_foreach_instr_in_block(((midgard_block *) v_block), v)
405bf215546Sopenharmony_ci
406bf215546Sopenharmony_ci#define mir_foreach_instr_global_safe(ctx, v) \
407bf215546Sopenharmony_ci        mir_foreach_block(ctx, v_block) \
408bf215546Sopenharmony_ci                mir_foreach_instr_in_block_safe(((midgard_block *) v_block), v)
409bf215546Sopenharmony_ci
410bf215546Sopenharmony_ci/* Based on set_foreach, expanded with automatic type casts */
411bf215546Sopenharmony_ci
412bf215546Sopenharmony_ci#define mir_foreach_predecessor(blk, v) \
413bf215546Sopenharmony_ci        struct set_entry *_entry_##v; \
414bf215546Sopenharmony_ci        struct midgard_block *v; \
415bf215546Sopenharmony_ci        for (_entry_##v = _mesa_set_next_entry(blk->base.predecessors, NULL), \
416bf215546Sopenharmony_ci                v = (struct midgard_block *) (_entry_##v ? _entry_##v->key : NULL);  \
417bf215546Sopenharmony_ci                _entry_##v != NULL; \
418bf215546Sopenharmony_ci                _entry_##v = _mesa_set_next_entry(blk->base.predecessors, _entry_##v), \
419bf215546Sopenharmony_ci                v = (struct midgard_block *) (_entry_##v ? _entry_##v->key : NULL))
420bf215546Sopenharmony_ci
421bf215546Sopenharmony_ci#define mir_foreach_src(ins, v) \
422bf215546Sopenharmony_ci        for (unsigned v = 0; v < ARRAY_SIZE(ins->src); ++v)
423bf215546Sopenharmony_ci
424bf215546Sopenharmony_cistatic inline midgard_instruction *
425bf215546Sopenharmony_cimir_last_in_block(struct midgard_block *block)
426bf215546Sopenharmony_ci{
427bf215546Sopenharmony_ci        return list_last_entry(&block->base.instructions, struct midgard_instruction, link);
428bf215546Sopenharmony_ci}
429bf215546Sopenharmony_ci
430bf215546Sopenharmony_cistatic inline midgard_block *
431bf215546Sopenharmony_cimir_get_block(compiler_context *ctx, int idx)
432bf215546Sopenharmony_ci{
433bf215546Sopenharmony_ci        struct list_head *lst = &ctx->blocks;
434bf215546Sopenharmony_ci
435bf215546Sopenharmony_ci        while ((idx--) + 1)
436bf215546Sopenharmony_ci                lst = lst->next;
437bf215546Sopenharmony_ci
438bf215546Sopenharmony_ci        return (struct midgard_block *) lst;
439bf215546Sopenharmony_ci}
440bf215546Sopenharmony_ci
441bf215546Sopenharmony_cistatic inline bool
442bf215546Sopenharmony_cimir_is_alu_bundle(midgard_bundle *bundle)
443bf215546Sopenharmony_ci{
444bf215546Sopenharmony_ci        return IS_ALU(bundle->tag);
445bf215546Sopenharmony_ci}
446bf215546Sopenharmony_ci
447bf215546Sopenharmony_cistatic inline unsigned
448bf215546Sopenharmony_cimake_compiler_temp(compiler_context *ctx)
449bf215546Sopenharmony_ci{
450bf215546Sopenharmony_ci        return (ctx->func->impl->ssa_alloc + ctx->temp_alloc++) << 1;
451bf215546Sopenharmony_ci}
452bf215546Sopenharmony_ci
453bf215546Sopenharmony_cistatic inline unsigned
454bf215546Sopenharmony_cimake_compiler_temp_reg(compiler_context *ctx)
455bf215546Sopenharmony_ci{
456bf215546Sopenharmony_ci        return ((ctx->func->impl->reg_alloc + ctx->temp_alloc++) << 1) | PAN_IS_REG;
457bf215546Sopenharmony_ci}
458bf215546Sopenharmony_ci
459bf215546Sopenharmony_cistatic inline unsigned
460bf215546Sopenharmony_cinir_ssa_index(nir_ssa_def *ssa)
461bf215546Sopenharmony_ci{
462bf215546Sopenharmony_ci        return (ssa->index << 1) | 0;
463bf215546Sopenharmony_ci}
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_cistatic inline unsigned
466bf215546Sopenharmony_cinir_src_index(compiler_context *ctx, nir_src *src)
467bf215546Sopenharmony_ci{
468bf215546Sopenharmony_ci        if (src->is_ssa)
469bf215546Sopenharmony_ci                return nir_ssa_index(src->ssa);
470bf215546Sopenharmony_ci        else {
471bf215546Sopenharmony_ci                assert(!src->reg.indirect);
472bf215546Sopenharmony_ci                return (src->reg.reg->index << 1) | PAN_IS_REG;
473bf215546Sopenharmony_ci        }
474bf215546Sopenharmony_ci}
475bf215546Sopenharmony_ci
476bf215546Sopenharmony_cistatic inline unsigned
477bf215546Sopenharmony_cinir_dest_index(nir_dest *dst)
478bf215546Sopenharmony_ci{
479bf215546Sopenharmony_ci        if (dst->is_ssa)
480bf215546Sopenharmony_ci                return (dst->ssa.index << 1) | 0;
481bf215546Sopenharmony_ci        else {
482bf215546Sopenharmony_ci                assert(!dst->reg.indirect);
483bf215546Sopenharmony_ci                return (dst->reg.reg->index << 1) | PAN_IS_REG;
484bf215546Sopenharmony_ci        }
485bf215546Sopenharmony_ci}
486bf215546Sopenharmony_ci
487bf215546Sopenharmony_ci
488bf215546Sopenharmony_ci
489bf215546Sopenharmony_ci/* MIR manipulation */
490bf215546Sopenharmony_ci
491bf215546Sopenharmony_civoid mir_rewrite_index(compiler_context *ctx, unsigned old, unsigned new);
492bf215546Sopenharmony_civoid mir_rewrite_index_src(compiler_context *ctx, unsigned old, unsigned new);
493bf215546Sopenharmony_civoid mir_rewrite_index_dst(compiler_context *ctx, unsigned old, unsigned new);
494bf215546Sopenharmony_civoid mir_rewrite_index_dst_single(midgard_instruction *ins, unsigned old, unsigned new);
495bf215546Sopenharmony_civoid mir_rewrite_index_src_single(midgard_instruction *ins, unsigned old, unsigned new);
496bf215546Sopenharmony_civoid mir_rewrite_index_src_swizzle(compiler_context *ctx, unsigned old, unsigned new, unsigned *swizzle);
497bf215546Sopenharmony_cibool mir_single_use(compiler_context *ctx, unsigned value);
498bf215546Sopenharmony_ciunsigned mir_use_count(compiler_context *ctx, unsigned value);
499bf215546Sopenharmony_ciuint16_t mir_bytemask_of_read_components(midgard_instruction *ins, unsigned node);
500bf215546Sopenharmony_ciuint16_t mir_bytemask_of_read_components_index(midgard_instruction *ins, unsigned i);
501bf215546Sopenharmony_ciuint16_t mir_from_bytemask(uint16_t bytemask, unsigned bits);
502bf215546Sopenharmony_ciuint16_t mir_bytemask(midgard_instruction *ins);
503bf215546Sopenharmony_ciuint16_t mir_round_bytemask_up(uint16_t mask, unsigned bits);
504bf215546Sopenharmony_civoid mir_set_bytemask(midgard_instruction *ins, uint16_t bytemask);
505bf215546Sopenharmony_cisigned mir_upper_override(midgard_instruction *ins, unsigned inst_size);
506bf215546Sopenharmony_ciunsigned mir_components_for_type(nir_alu_type T);
507bf215546Sopenharmony_ciunsigned max_bitsize_for_alu(midgard_instruction *ins);
508bf215546Sopenharmony_cimidgard_reg_mode reg_mode_for_bitsize(unsigned bitsize);
509bf215546Sopenharmony_ci
510bf215546Sopenharmony_ci/* MIR printing */
511bf215546Sopenharmony_ci
512bf215546Sopenharmony_civoid mir_print_instruction(midgard_instruction *ins);
513bf215546Sopenharmony_civoid mir_print_bundle(midgard_bundle *ctx);
514bf215546Sopenharmony_civoid mir_print_block(midgard_block *block);
515bf215546Sopenharmony_civoid mir_print_shader(compiler_context *ctx);
516bf215546Sopenharmony_cibool mir_nontrivial_mod(midgard_instruction *ins, unsigned i, bool check_swizzle);
517bf215546Sopenharmony_cibool mir_nontrivial_outmod(midgard_instruction *ins);
518bf215546Sopenharmony_ci
519bf215546Sopenharmony_cimidgard_instruction *mir_insert_instruction_before_scheduled(compiler_context *ctx, midgard_block *block, midgard_instruction *tag, midgard_instruction ins);
520bf215546Sopenharmony_cimidgard_instruction *mir_insert_instruction_after_scheduled(compiler_context *ctx, midgard_block *block, midgard_instruction *tag, midgard_instruction ins);
521bf215546Sopenharmony_civoid mir_flip(midgard_instruction *ins);
522bf215546Sopenharmony_civoid mir_compute_temp_count(compiler_context *ctx);
523bf215546Sopenharmony_ci
524bf215546Sopenharmony_ci#define LDST_GLOBAL (REGISTER_LDST_ZERO << 2)
525bf215546Sopenharmony_ci#define LDST_SHARED ((REGISTER_LDST_LOCAL_STORAGE_PTR << 2) | COMPONENT_Z)
526bf215546Sopenharmony_ci#define LDST_SCRATCH ((REGISTER_LDST_PC_SP << 2) | COMPONENT_Z)
527bf215546Sopenharmony_ci
528bf215546Sopenharmony_civoid mir_set_offset(compiler_context *ctx, midgard_instruction *ins, nir_src *offset, unsigned seg);
529bf215546Sopenharmony_civoid mir_set_ubo_offset(midgard_instruction *ins, nir_src *src, unsigned bias);
530bf215546Sopenharmony_ci
531bf215546Sopenharmony_ci/* 'Intrinsic' move for aliasing */
532bf215546Sopenharmony_ci
533bf215546Sopenharmony_cistatic inline midgard_instruction
534bf215546Sopenharmony_civ_mov(unsigned src, unsigned dest)
535bf215546Sopenharmony_ci{
536bf215546Sopenharmony_ci        midgard_instruction ins = {
537bf215546Sopenharmony_ci                .type = TAG_ALU_4,
538bf215546Sopenharmony_ci                .mask = 0xF,
539bf215546Sopenharmony_ci                .src = { ~0, src, ~0, ~0 },
540bf215546Sopenharmony_ci                .src_types = { 0, nir_type_uint32 },
541bf215546Sopenharmony_ci                .swizzle = SWIZZLE_IDENTITY,
542bf215546Sopenharmony_ci                .dest = dest,
543bf215546Sopenharmony_ci                .dest_type = nir_type_uint32,
544bf215546Sopenharmony_ci                .op = midgard_alu_op_imov,
545bf215546Sopenharmony_ci                .outmod = midgard_outmod_keeplo
546bf215546Sopenharmony_ci        };
547bf215546Sopenharmony_ci
548bf215546Sopenharmony_ci        return ins;
549bf215546Sopenharmony_ci}
550bf215546Sopenharmony_ci
551bf215546Sopenharmony_ci/* Broad types of register classes so we can handle special
552bf215546Sopenharmony_ci * registers */
553bf215546Sopenharmony_ci
554bf215546Sopenharmony_ci#define REG_CLASS_WORK          0
555bf215546Sopenharmony_ci#define REG_CLASS_LDST          1
556bf215546Sopenharmony_ci#define REG_CLASS_TEXR          3
557bf215546Sopenharmony_ci#define REG_CLASS_TEXW          4
558bf215546Sopenharmony_ci
559bf215546Sopenharmony_ci/* Like a move, but to thread local storage! */
560bf215546Sopenharmony_ci
561bf215546Sopenharmony_cistatic inline midgard_instruction
562bf215546Sopenharmony_civ_load_store_scratch(
563bf215546Sopenharmony_ci                unsigned srcdest,
564bf215546Sopenharmony_ci                unsigned index,
565bf215546Sopenharmony_ci                bool is_store,
566bf215546Sopenharmony_ci                unsigned mask)
567bf215546Sopenharmony_ci{
568bf215546Sopenharmony_ci        /* We index by 32-bit vec4s */
569bf215546Sopenharmony_ci        unsigned byte = (index * 4 * 4);
570bf215546Sopenharmony_ci
571bf215546Sopenharmony_ci        midgard_instruction ins = {
572bf215546Sopenharmony_ci                .type = TAG_LOAD_STORE_4,
573bf215546Sopenharmony_ci                .mask = mask,
574bf215546Sopenharmony_ci                .dest_type = nir_type_uint32,
575bf215546Sopenharmony_ci                .dest = ~0,
576bf215546Sopenharmony_ci                .src = { ~0, ~0, ~0, ~0 },
577bf215546Sopenharmony_ci                .swizzle = SWIZZLE_IDENTITY_4,
578bf215546Sopenharmony_ci                .op = is_store ? midgard_op_st_128 : midgard_op_ld_128,
579bf215546Sopenharmony_ci                .load_store = {
580bf215546Sopenharmony_ci                        /* For register spilling - to thread local storage */
581bf215546Sopenharmony_ci                        .arg_reg = REGISTER_LDST_LOCAL_STORAGE_PTR,
582bf215546Sopenharmony_ci                        .arg_comp = COMPONENT_X,
583bf215546Sopenharmony_ci                        .bitsize_toggle = true,
584bf215546Sopenharmony_ci                        .index_format = midgard_index_address_u32,
585bf215546Sopenharmony_ci                        .index_reg = REGISTER_LDST_ZERO,
586bf215546Sopenharmony_ci                },
587bf215546Sopenharmony_ci
588bf215546Sopenharmony_ci                /* If we spill an unspill, RA goes into an infinite loop */
589bf215546Sopenharmony_ci                .no_spill = (1 << REG_CLASS_WORK)
590bf215546Sopenharmony_ci        };
591bf215546Sopenharmony_ci
592bf215546Sopenharmony_ci        ins.constants.u32[0] = byte;
593bf215546Sopenharmony_ci
594bf215546Sopenharmony_ci        if (is_store) {
595bf215546Sopenharmony_ci                ins.src[0] = srcdest;
596bf215546Sopenharmony_ci                ins.src_types[0] = nir_type_uint32;
597bf215546Sopenharmony_ci
598bf215546Sopenharmony_ci                /* Ensure we are tightly swizzled so liveness analysis is
599bf215546Sopenharmony_ci                 * correct */
600bf215546Sopenharmony_ci
601bf215546Sopenharmony_ci                for (unsigned i = 0; i < 4; ++i) {
602bf215546Sopenharmony_ci                        if (!(mask & (1 << i)))
603bf215546Sopenharmony_ci                                ins.swizzle[0][i] = COMPONENT_X;
604bf215546Sopenharmony_ci                }
605bf215546Sopenharmony_ci        } else
606bf215546Sopenharmony_ci                ins.dest = srcdest;
607bf215546Sopenharmony_ci
608bf215546Sopenharmony_ci        return ins;
609bf215546Sopenharmony_ci}
610bf215546Sopenharmony_ci
611bf215546Sopenharmony_cistatic inline bool
612bf215546Sopenharmony_cimir_has_arg(midgard_instruction *ins, unsigned arg)
613bf215546Sopenharmony_ci{
614bf215546Sopenharmony_ci        if (!ins)
615bf215546Sopenharmony_ci                return false;
616bf215546Sopenharmony_ci
617bf215546Sopenharmony_ci        mir_foreach_src(ins, i) {
618bf215546Sopenharmony_ci                if (ins->src[i] == arg)
619bf215546Sopenharmony_ci                        return true;
620bf215546Sopenharmony_ci        }
621bf215546Sopenharmony_ci
622bf215546Sopenharmony_ci        return false;
623bf215546Sopenharmony_ci}
624bf215546Sopenharmony_ci
625bf215546Sopenharmony_ci/* Scheduling */
626bf215546Sopenharmony_ci
627bf215546Sopenharmony_civoid midgard_schedule_program(compiler_context *ctx);
628bf215546Sopenharmony_ci
629bf215546Sopenharmony_civoid mir_ra(compiler_context *ctx);
630bf215546Sopenharmony_civoid mir_squeeze_index(compiler_context *ctx);
631bf215546Sopenharmony_civoid mir_lower_special_reads(compiler_context *ctx);
632bf215546Sopenharmony_civoid mir_liveness_ins_update(uint16_t *live, midgard_instruction *ins, unsigned max);
633bf215546Sopenharmony_civoid mir_compute_liveness(compiler_context *ctx);
634bf215546Sopenharmony_civoid mir_invalidate_liveness(compiler_context *ctx);
635bf215546Sopenharmony_cibool mir_is_live_after(compiler_context *ctx, midgard_block *block, midgard_instruction *start, int src);
636bf215546Sopenharmony_ci
637bf215546Sopenharmony_civoid mir_create_pipeline_registers(compiler_context *ctx);
638bf215546Sopenharmony_civoid midgard_promote_uniforms(compiler_context *ctx);
639bf215546Sopenharmony_ci
640bf215546Sopenharmony_civoid
641bf215546Sopenharmony_cimidgard_emit_derivatives(compiler_context *ctx, nir_alu_instr *instr);
642bf215546Sopenharmony_ci
643bf215546Sopenharmony_civoid
644bf215546Sopenharmony_cimidgard_lower_derivatives(compiler_context *ctx, midgard_block *block);
645bf215546Sopenharmony_ci
646bf215546Sopenharmony_cibool mir_op_computes_derivatives(gl_shader_stage stage, unsigned op);
647bf215546Sopenharmony_ci
648bf215546Sopenharmony_civoid mir_analyze_helper_terminate(compiler_context *ctx);
649bf215546Sopenharmony_civoid mir_analyze_helper_requirements(compiler_context *ctx);
650bf215546Sopenharmony_ci
651bf215546Sopenharmony_ci/* Final emission */
652bf215546Sopenharmony_ci
653bf215546Sopenharmony_civoid emit_binary_bundle(
654bf215546Sopenharmony_ci        compiler_context *ctx,
655bf215546Sopenharmony_ci        midgard_block *block,
656bf215546Sopenharmony_ci        midgard_bundle *bundle,
657bf215546Sopenharmony_ci        struct util_dynarray *emission,
658bf215546Sopenharmony_ci        int next_tag);
659bf215546Sopenharmony_ci
660bf215546Sopenharmony_cibool nir_fuse_io_16(nir_shader *shader);
661bf215546Sopenharmony_ci
662bf215546Sopenharmony_cibool midgard_nir_lod_errata(nir_shader *shader);
663bf215546Sopenharmony_ci
664bf215546Sopenharmony_ciunsigned midgard_get_first_tag_from_block(compiler_context *ctx, unsigned block_idx);
665bf215546Sopenharmony_ci
666bf215546Sopenharmony_ci/* Optimizations */
667bf215546Sopenharmony_ci
668bf215546Sopenharmony_cibool midgard_opt_copy_prop(compiler_context *ctx, midgard_block *block);
669bf215546Sopenharmony_cibool midgard_opt_combine_projection(compiler_context *ctx, midgard_block *block);
670bf215546Sopenharmony_cibool midgard_opt_varying_projection(compiler_context *ctx, midgard_block *block);
671bf215546Sopenharmony_cibool midgard_opt_dead_code_eliminate(compiler_context *ctx);
672bf215546Sopenharmony_cibool midgard_opt_dead_move_eliminate(compiler_context *ctx, midgard_block *block);
673bf215546Sopenharmony_ci
674bf215546Sopenharmony_ci#endif
675