17ec681f3Smrg/* 27ec681f3Smrg * Copyright (C) 2019-2020 Collabora, Ltd. 37ec681f3Smrg * Copyright (C) 2019 Alyssa Rosenzweig <alyssa@rosenzweig.io> 47ec681f3Smrg * 57ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 67ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 77ec681f3Smrg * to deal in the Software without restriction, including without limitation 87ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 97ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 107ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 117ec681f3Smrg * 127ec681f3Smrg * The above copyright notice and this permission notice (including the next 137ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 147ec681f3Smrg * Software. 157ec681f3Smrg * 167ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 177ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 187ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 197ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 207ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 217ec681f3Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 227ec681f3Smrg * SOFTWARE. 237ec681f3Smrg */ 247ec681f3Smrg 257ec681f3Smrg#ifndef _MDG_COMPILER_H 267ec681f3Smrg#define _MDG_COMPILER_H 277ec681f3Smrg 287ec681f3Smrg#include "midgard.h" 297ec681f3Smrg#include "helpers.h" 307ec681f3Smrg#include "midgard_compile.h" 317ec681f3Smrg#include "midgard_ops.h" 327ec681f3Smrg 337ec681f3Smrg#include "util/hash_table.h" 347ec681f3Smrg#include "util/u_dynarray.h" 357ec681f3Smrg#include "util/set.h" 367ec681f3Smrg#include "util/list.h" 377ec681f3Smrg 387ec681f3Smrg#include "main/mtypes.h" 397ec681f3Smrg#include "compiler/nir_types.h" 407ec681f3Smrg#include "compiler/nir/nir.h" 417ec681f3Smrg#include "panfrost/util/pan_ir.h" 427ec681f3Smrg#include "panfrost/util/lcra.h" 437ec681f3Smrg 447ec681f3Smrg/* Forward declare */ 457ec681f3Smrgstruct midgard_block; 467ec681f3Smrg 477ec681f3Smrg/* Target types. Defaults to TARGET_GOTO (the type corresponding directly to 487ec681f3Smrg * the hardware), hence why that must be zero. TARGET_DISCARD signals this 497ec681f3Smrg * instruction is actually a discard op. */ 507ec681f3Smrg 517ec681f3Smrg#define TARGET_GOTO 0 527ec681f3Smrg#define TARGET_BREAK 1 537ec681f3Smrg#define TARGET_CONTINUE 2 547ec681f3Smrg#define TARGET_DISCARD 3 557ec681f3Smrg#define TARGET_TILEBUF_WAIT 4 567ec681f3Smrg 577ec681f3Smrgtypedef struct midgard_branch { 587ec681f3Smrg /* If conditional, the condition is specified in r31.w */ 597ec681f3Smrg bool conditional; 607ec681f3Smrg 617ec681f3Smrg /* For conditionals, if this is true, we branch on FALSE. If false, we branch on TRUE. */ 627ec681f3Smrg bool invert_conditional; 637ec681f3Smrg 647ec681f3Smrg /* Branch targets: the start of a block, the start of a loop (continue), the end of a loop (break). Value is one of TARGET_ */ 657ec681f3Smrg unsigned target_type; 667ec681f3Smrg 677ec681f3Smrg /* The actual target */ 687ec681f3Smrg union { 697ec681f3Smrg int target_block; 707ec681f3Smrg int target_break; 717ec681f3Smrg int target_continue; 727ec681f3Smrg }; 737ec681f3Smrg} midgard_branch; 747ec681f3Smrg 757ec681f3Smrg/* Generic in-memory data type repesenting a single logical instruction, rather 767ec681f3Smrg * than a single instruction group. This is the preferred form for code gen. 777ec681f3Smrg * Multiple midgard_insturctions will later be combined during scheduling, 787ec681f3Smrg * though this is not represented in this structure. Its format bridges 797ec681f3Smrg * the low-level binary representation with the higher level semantic meaning. 807ec681f3Smrg * 817ec681f3Smrg * Notably, it allows registers to be specified as block local SSA, for code 827ec681f3Smrg * emitted before the register allocation pass. 837ec681f3Smrg */ 847ec681f3Smrg 857ec681f3Smrg#define MIR_SRC_COUNT 4 867ec681f3Smrg#define MIR_VEC_COMPONENTS 16 877ec681f3Smrg 887ec681f3Smrgtypedef struct midgard_instruction { 897ec681f3Smrg /* Must be first for casting */ 907ec681f3Smrg struct list_head link; 917ec681f3Smrg 927ec681f3Smrg unsigned type; /* ALU, load/store, texture */ 937ec681f3Smrg 947ec681f3Smrg /* Instruction arguments represented as block-local SSA 957ec681f3Smrg * indices, rather than registers. ~0 means unused. */ 967ec681f3Smrg unsigned src[MIR_SRC_COUNT]; 977ec681f3Smrg unsigned dest; 987ec681f3Smrg 997ec681f3Smrg /* vec16 swizzle, unpacked, per source */ 1007ec681f3Smrg unsigned swizzle[MIR_SRC_COUNT][MIR_VEC_COMPONENTS]; 1017ec681f3Smrg 1027ec681f3Smrg /* Types! */ 1037ec681f3Smrg nir_alu_type src_types[MIR_SRC_COUNT]; 1047ec681f3Smrg nir_alu_type dest_type; 1057ec681f3Smrg 1067ec681f3Smrg /* Packing ops have non-32-bit dest types even though they functionally 1077ec681f3Smrg * work at the 32-bit level, use this as a signal to disable copyprop. 1087ec681f3Smrg * We maybe need synthetic pack ops instead. */ 1097ec681f3Smrg bool is_pack; 1107ec681f3Smrg 1117ec681f3Smrg /* Modifiers, depending on type */ 1127ec681f3Smrg union { 1137ec681f3Smrg struct { 1147ec681f3Smrg bool src_abs[MIR_SRC_COUNT]; 1157ec681f3Smrg bool src_neg[MIR_SRC_COUNT]; 1167ec681f3Smrg }; 1177ec681f3Smrg 1187ec681f3Smrg struct { 1197ec681f3Smrg bool src_shift[MIR_SRC_COUNT]; 1207ec681f3Smrg }; 1217ec681f3Smrg }; 1227ec681f3Smrg 1237ec681f3Smrg /* Out of the union for csel (could maybe be fixed..) */ 1247ec681f3Smrg bool src_invert[MIR_SRC_COUNT]; 1257ec681f3Smrg 1267ec681f3Smrg /* If the op supports it */ 1277ec681f3Smrg enum midgard_roundmode roundmode; 1287ec681f3Smrg 1297ec681f3Smrg /* For textures: should helpers execute this instruction (instead of 1307ec681f3Smrg * just helping with derivatives)? Should helpers terminate after? */ 1317ec681f3Smrg bool helper_terminate; 1327ec681f3Smrg bool helper_execute; 1337ec681f3Smrg 1347ec681f3Smrg /* I.e. (1 << alu_bit) */ 1357ec681f3Smrg int unit; 1367ec681f3Smrg 1377ec681f3Smrg bool has_constants; 1387ec681f3Smrg midgard_constants constants; 1397ec681f3Smrg uint16_t inline_constant; 1407ec681f3Smrg bool has_inline_constant; 1417ec681f3Smrg 1427ec681f3Smrg bool compact_branch; 1437ec681f3Smrg uint8_t writeout; 1447ec681f3Smrg bool last_writeout; 1457ec681f3Smrg 1467ec681f3Smrg /* Masks in a saneish format. One bit per channel, not packed fancy. 1477ec681f3Smrg * Use this instead of the op specific ones, and switch over at emit 1487ec681f3Smrg * time */ 1497ec681f3Smrg 1507ec681f3Smrg uint16_t mask; 1517ec681f3Smrg 1527ec681f3Smrg /* Hint for the register allocator not to spill the destination written 1537ec681f3Smrg * from this instruction (because it is a spill/unspill node itself). 1547ec681f3Smrg * Bitmask of spilled classes */ 1557ec681f3Smrg 1567ec681f3Smrg unsigned no_spill; 1577ec681f3Smrg 1587ec681f3Smrg /* Generic hint for intra-pass use */ 1597ec681f3Smrg bool hint; 1607ec681f3Smrg 1617ec681f3Smrg /* During scheduling, the backwards dependency graph 1627ec681f3Smrg * (DAG). nr_dependencies is the number of unscheduled 1637ec681f3Smrg * instructions that must still be scheduled after 1647ec681f3Smrg * (before) this instruction. dependents are which 1657ec681f3Smrg * instructions need to be scheduled before (after) this 1667ec681f3Smrg * instruction. */ 1677ec681f3Smrg 1687ec681f3Smrg unsigned nr_dependencies; 1697ec681f3Smrg BITSET_WORD *dependents; 1707ec681f3Smrg 1717ec681f3Smrg /* Use this in conjunction with `type` */ 1727ec681f3Smrg unsigned op; 1737ec681f3Smrg 1747ec681f3Smrg /* This refers to midgard_outmod_float or midgard_outmod_int. 1757ec681f3Smrg * In case of a ALU op, use midgard_is_integer_out_op() to know which 1767ec681f3Smrg * one is used. 1777ec681f3Smrg * If it's a texture op, it's always midgard_outmod_float. */ 1787ec681f3Smrg unsigned outmod; 1797ec681f3Smrg 1807ec681f3Smrg union { 1817ec681f3Smrg midgard_load_store_word load_store; 1827ec681f3Smrg midgard_texture_word texture; 1837ec681f3Smrg 1847ec681f3Smrg midgard_branch branch; 1857ec681f3Smrg }; 1867ec681f3Smrg 1877ec681f3Smrg unsigned bundle_id; 1887ec681f3Smrg} midgard_instruction; 1897ec681f3Smrg 1907ec681f3Smrgtypedef struct midgard_block { 1917ec681f3Smrg pan_block base; 1927ec681f3Smrg 1937ec681f3Smrg bool scheduled; 1947ec681f3Smrg 1957ec681f3Smrg /* List of midgard_bundles emitted (after the scheduler has run) */ 1967ec681f3Smrg struct util_dynarray bundles; 1977ec681f3Smrg 1987ec681f3Smrg /* Number of quadwords _actually_ emitted, as determined after scheduling */ 1997ec681f3Smrg unsigned quadword_count; 2007ec681f3Smrg 2017ec681f3Smrg /* Indicates this is a fixed-function fragment epilogue block */ 2027ec681f3Smrg bool epilogue; 2037ec681f3Smrg 2047ec681f3Smrg /* Are helper invocations required by this block? */ 2057ec681f3Smrg bool helpers_in; 2067ec681f3Smrg} midgard_block; 2077ec681f3Smrg 2087ec681f3Smrgtypedef struct midgard_bundle { 2097ec681f3Smrg /* Tag for the overall bundle */ 2107ec681f3Smrg int tag; 2117ec681f3Smrg 2127ec681f3Smrg /* Instructions contained by the bundle. instruction_count <= 6 (vmul, 2137ec681f3Smrg * sadd, vadd, smul, vlut, branch) */ 2147ec681f3Smrg int instruction_count; 2157ec681f3Smrg midgard_instruction *instructions[6]; 2167ec681f3Smrg 2177ec681f3Smrg /* Bundle-wide ALU configuration */ 2187ec681f3Smrg int padding; 2197ec681f3Smrg int control; 2207ec681f3Smrg bool has_embedded_constants; 2217ec681f3Smrg midgard_constants constants; 2227ec681f3Smrg bool last_writeout; 2237ec681f3Smrg} midgard_bundle; 2247ec681f3Smrg 2257ec681f3Smrgenum midgard_rt_id { 2267ec681f3Smrg MIDGARD_COLOR_RT0 = 0, 2277ec681f3Smrg MIDGARD_COLOR_RT1, 2287ec681f3Smrg MIDGARD_COLOR_RT2, 2297ec681f3Smrg MIDGARD_COLOR_RT3, 2307ec681f3Smrg MIDGARD_COLOR_RT4, 2317ec681f3Smrg MIDGARD_COLOR_RT5, 2327ec681f3Smrg MIDGARD_COLOR_RT6, 2337ec681f3Smrg MIDGARD_COLOR_RT7, 2347ec681f3Smrg MIDGARD_ZS_RT, 2357ec681f3Smrg MIDGARD_NUM_RTS, 2367ec681f3Smrg}; 2377ec681f3Smrg 2387ec681f3Smrg#define MIDGARD_MAX_SAMPLE_ITER 16 2397ec681f3Smrg 2407ec681f3Smrgtypedef struct compiler_context { 2417ec681f3Smrg const struct panfrost_compile_inputs *inputs; 2427ec681f3Smrg nir_shader *nir; 2437ec681f3Smrg struct pan_shader_info *info; 2447ec681f3Smrg gl_shader_stage stage; 2457ec681f3Smrg 2467ec681f3Smrg /* Number of samples for a keyed blend shader. Depends on is_blend */ 2477ec681f3Smrg unsigned blend_sample_iterations; 2487ec681f3Smrg 2497ec681f3Smrg /* Index to precolour to r0 for an input blend colour */ 2507ec681f3Smrg unsigned blend_input; 2517ec681f3Smrg 2527ec681f3Smrg /* Index to precolour to r2 for a dual-source blend colour */ 2537ec681f3Smrg unsigned blend_src1; 2547ec681f3Smrg 2557ec681f3Smrg /* Count of spills and fills for shaderdb */ 2567ec681f3Smrg unsigned spills; 2577ec681f3Smrg unsigned fills; 2587ec681f3Smrg 2597ec681f3Smrg /* Current NIR function */ 2607ec681f3Smrg nir_function *func; 2617ec681f3Smrg 2627ec681f3Smrg /* Allocated compiler temporary counter */ 2637ec681f3Smrg unsigned temp_alloc; 2647ec681f3Smrg 2657ec681f3Smrg /* Unordered list of midgard_blocks */ 2667ec681f3Smrg int block_count; 2677ec681f3Smrg struct list_head blocks; 2687ec681f3Smrg 2697ec681f3Smrg /* TODO merge with block_count? */ 2707ec681f3Smrg unsigned block_source_count; 2717ec681f3Smrg 2727ec681f3Smrg /* List of midgard_instructions emitted for the current block */ 2737ec681f3Smrg midgard_block *current_block; 2747ec681f3Smrg 2757ec681f3Smrg /* If there is a preset after block, use this, otherwise emit_block will create one if NULL */ 2767ec681f3Smrg midgard_block *after_block; 2777ec681f3Smrg 2787ec681f3Smrg /* The current "depth" of the loop, for disambiguating breaks/continues 2797ec681f3Smrg * when using nested loops */ 2807ec681f3Smrg int current_loop_depth; 2817ec681f3Smrg 2827ec681f3Smrg /* Total number of loops for shader-db */ 2837ec681f3Smrg unsigned loop_count; 2847ec681f3Smrg 2857ec681f3Smrg /* Constants which have been loaded, for later inlining */ 2867ec681f3Smrg struct hash_table_u64 *ssa_constants; 2877ec681f3Smrg 2887ec681f3Smrg int temp_count; 2897ec681f3Smrg int max_hash; 2907ec681f3Smrg 2917ec681f3Smrg /* Set of NIR indices that were already emitted as outmods */ 2927ec681f3Smrg BITSET_WORD *already_emitted; 2937ec681f3Smrg 2947ec681f3Smrg /* Count of instructions emitted from NIR overall, across all blocks */ 2957ec681f3Smrg int instruction_count; 2967ec681f3Smrg 2977ec681f3Smrg unsigned quadword_count; 2987ec681f3Smrg 2997ec681f3Smrg /* Bitmask of valid metadata */ 3007ec681f3Smrg unsigned metadata; 3017ec681f3Smrg 3027ec681f3Smrg /* Model-specific quirk set */ 3037ec681f3Smrg uint32_t quirks; 3047ec681f3Smrg 3057ec681f3Smrg /* Writeout instructions for each render target */ 3067ec681f3Smrg midgard_instruction *writeout_branch[MIDGARD_NUM_RTS][MIDGARD_MAX_SAMPLE_ITER]; 3077ec681f3Smrg 3087ec681f3Smrg struct hash_table_u64 *sysval_to_id; 3097ec681f3Smrg 3107ec681f3Smrg /* Mask of UBOs that need to be uploaded */ 3117ec681f3Smrg uint32_t ubo_mask; 3127ec681f3Smrg} compiler_context; 3137ec681f3Smrg 3147ec681f3Smrg/* Per-block live_in/live_out */ 3157ec681f3Smrg#define MIDGARD_METADATA_LIVENESS (1 << 0) 3167ec681f3Smrg 3177ec681f3Smrg/* Helpers for manipulating the above structures (forming the driver IR) */ 3187ec681f3Smrg 3197ec681f3Smrg/* Append instruction to end of current block */ 3207ec681f3Smrg 3217ec681f3Smrgstatic inline midgard_instruction * 3227ec681f3Smrgmir_upload_ins(struct compiler_context *ctx, struct midgard_instruction ins) 3237ec681f3Smrg{ 3247ec681f3Smrg midgard_instruction *heap = ralloc(ctx, struct midgard_instruction); 3257ec681f3Smrg memcpy(heap, &ins, sizeof(ins)); 3267ec681f3Smrg return heap; 3277ec681f3Smrg} 3287ec681f3Smrg 3297ec681f3Smrgstatic inline midgard_instruction * 3307ec681f3Smrgemit_mir_instruction(struct compiler_context *ctx, struct midgard_instruction ins) 3317ec681f3Smrg{ 3327ec681f3Smrg midgard_instruction *u = mir_upload_ins(ctx, ins); 3337ec681f3Smrg list_addtail(&u->link, &ctx->current_block->base.instructions); 3347ec681f3Smrg return u; 3357ec681f3Smrg} 3367ec681f3Smrg 3377ec681f3Smrgstatic inline struct midgard_instruction * 3387ec681f3Smrgmir_insert_instruction_before(struct compiler_context *ctx, 3397ec681f3Smrg struct midgard_instruction *tag, 3407ec681f3Smrg struct midgard_instruction ins) 3417ec681f3Smrg{ 3427ec681f3Smrg struct midgard_instruction *u = mir_upload_ins(ctx, ins); 3437ec681f3Smrg list_addtail(&u->link, &tag->link); 3447ec681f3Smrg return u; 3457ec681f3Smrg} 3467ec681f3Smrg 3477ec681f3Smrgstatic inline void 3487ec681f3Smrgmir_remove_instruction(struct midgard_instruction *ins) 3497ec681f3Smrg{ 3507ec681f3Smrg list_del(&ins->link); 3517ec681f3Smrg} 3527ec681f3Smrg 3537ec681f3Smrgstatic inline midgard_instruction* 3547ec681f3Smrgmir_prev_op(struct midgard_instruction *ins) 3557ec681f3Smrg{ 3567ec681f3Smrg return list_last_entry(&(ins->link), midgard_instruction, link); 3577ec681f3Smrg} 3587ec681f3Smrg 3597ec681f3Smrgstatic inline midgard_instruction* 3607ec681f3Smrgmir_next_op(struct midgard_instruction *ins) 3617ec681f3Smrg{ 3627ec681f3Smrg return list_first_entry(&(ins->link), midgard_instruction, link); 3637ec681f3Smrg} 3647ec681f3Smrg 3657ec681f3Smrg#define mir_foreach_block(ctx, v) \ 3667ec681f3Smrg list_for_each_entry(pan_block, v, &ctx->blocks, link) 3677ec681f3Smrg 3687ec681f3Smrg#define mir_foreach_block_from(ctx, from, v) \ 3697ec681f3Smrg list_for_each_entry_from(pan_block, v, &from->base, &ctx->blocks, link) 3707ec681f3Smrg 3717ec681f3Smrg#define mir_foreach_instr_in_block(block, v) \ 3727ec681f3Smrg list_for_each_entry(struct midgard_instruction, v, &block->base.instructions, link) 3737ec681f3Smrg#define mir_foreach_instr_in_block_rev(block, v) \ 3747ec681f3Smrg list_for_each_entry_rev(struct midgard_instruction, v, &block->base.instructions, link) 3757ec681f3Smrg 3767ec681f3Smrg#define mir_foreach_instr_in_block_safe(block, v) \ 3777ec681f3Smrg list_for_each_entry_safe(struct midgard_instruction, v, &block->base.instructions, link) 3787ec681f3Smrg 3797ec681f3Smrg#define mir_foreach_instr_in_block_safe_rev(block, v) \ 3807ec681f3Smrg list_for_each_entry_safe_rev(struct midgard_instruction, v, &block->base.instructions, link) 3817ec681f3Smrg 3827ec681f3Smrg#define mir_foreach_instr_in_block_from(block, v, from) \ 3837ec681f3Smrg list_for_each_entry_from(struct midgard_instruction, v, from, &block->base.instructions, link) 3847ec681f3Smrg 3857ec681f3Smrg#define mir_foreach_instr_in_block_from_rev(block, v, from) \ 3867ec681f3Smrg list_for_each_entry_from_rev(struct midgard_instruction, v, from, &block->base.instructions, link) 3877ec681f3Smrg 3887ec681f3Smrg#define mir_foreach_bundle_in_block(block, v) \ 3897ec681f3Smrg util_dynarray_foreach(&block->bundles, midgard_bundle, v) 3907ec681f3Smrg 3917ec681f3Smrg#define mir_foreach_bundle_in_block_rev(block, v) \ 3927ec681f3Smrg util_dynarray_foreach_reverse(&block->bundles, midgard_bundle, v) 3937ec681f3Smrg 3947ec681f3Smrg#define mir_foreach_instr_in_block_scheduled_rev(block, v) \ 3957ec681f3Smrg midgard_instruction* v; \ 3967ec681f3Smrg signed i = 0; \ 3977ec681f3Smrg mir_foreach_bundle_in_block_rev(block, _bundle) \ 3987ec681f3Smrg for (i = (_bundle->instruction_count - 1), v = _bundle->instructions[i]; \ 3997ec681f3Smrg i >= 0; \ 4007ec681f3Smrg --i, v = (i >= 0) ? _bundle->instructions[i] : NULL) \ 4017ec681f3Smrg 4027ec681f3Smrg#define mir_foreach_instr_global(ctx, v) \ 4037ec681f3Smrg mir_foreach_block(ctx, v_block) \ 4047ec681f3Smrg mir_foreach_instr_in_block(((midgard_block *) v_block), v) 4057ec681f3Smrg 4067ec681f3Smrg#define mir_foreach_instr_global_safe(ctx, v) \ 4077ec681f3Smrg mir_foreach_block(ctx, v_block) \ 4087ec681f3Smrg mir_foreach_instr_in_block_safe(((midgard_block *) v_block), v) 4097ec681f3Smrg 4107ec681f3Smrg/* Based on set_foreach, expanded with automatic type casts */ 4117ec681f3Smrg 4127ec681f3Smrg#define mir_foreach_predecessor(blk, v) \ 4137ec681f3Smrg struct set_entry *_entry_##v; \ 4147ec681f3Smrg struct midgard_block *v; \ 4157ec681f3Smrg for (_entry_##v = _mesa_set_next_entry(blk->base.predecessors, NULL), \ 4167ec681f3Smrg v = (struct midgard_block *) (_entry_##v ? _entry_##v->key : NULL); \ 4177ec681f3Smrg _entry_##v != NULL; \ 4187ec681f3Smrg _entry_##v = _mesa_set_next_entry(blk->base.predecessors, _entry_##v), \ 4197ec681f3Smrg v = (struct midgard_block *) (_entry_##v ? _entry_##v->key : NULL)) 4207ec681f3Smrg 4217ec681f3Smrg#define mir_foreach_src(ins, v) \ 4227ec681f3Smrg for (unsigned v = 0; v < ARRAY_SIZE(ins->src); ++v) 4237ec681f3Smrg 4247ec681f3Smrgstatic inline midgard_instruction * 4257ec681f3Smrgmir_last_in_block(struct midgard_block *block) 4267ec681f3Smrg{ 4277ec681f3Smrg return list_last_entry(&block->base.instructions, struct midgard_instruction, link); 4287ec681f3Smrg} 4297ec681f3Smrg 4307ec681f3Smrgstatic inline midgard_block * 4317ec681f3Smrgmir_get_block(compiler_context *ctx, int idx) 4327ec681f3Smrg{ 4337ec681f3Smrg struct list_head *lst = &ctx->blocks; 4347ec681f3Smrg 4357ec681f3Smrg while ((idx--) + 1) 4367ec681f3Smrg lst = lst->next; 4377ec681f3Smrg 4387ec681f3Smrg return (struct midgard_block *) lst; 4397ec681f3Smrg} 4407ec681f3Smrg 4417ec681f3Smrgstatic inline bool 4427ec681f3Smrgmir_is_alu_bundle(midgard_bundle *bundle) 4437ec681f3Smrg{ 4447ec681f3Smrg return IS_ALU(bundle->tag); 4457ec681f3Smrg} 4467ec681f3Smrg 4477ec681f3Smrgstatic inline unsigned 4487ec681f3Smrgmake_compiler_temp(compiler_context *ctx) 4497ec681f3Smrg{ 4507ec681f3Smrg return (ctx->func->impl->ssa_alloc + ctx->temp_alloc++) << 1; 4517ec681f3Smrg} 4527ec681f3Smrg 4537ec681f3Smrgstatic inline unsigned 4547ec681f3Smrgmake_compiler_temp_reg(compiler_context *ctx) 4557ec681f3Smrg{ 4567ec681f3Smrg return ((ctx->func->impl->reg_alloc + ctx->temp_alloc++) << 1) | PAN_IS_REG; 4577ec681f3Smrg} 4587ec681f3Smrg 4597ec681f3Smrgstatic inline unsigned 4607ec681f3Smrgnir_ssa_index(nir_ssa_def *ssa) 4617ec681f3Smrg{ 4627ec681f3Smrg return (ssa->index << 1) | 0; 4637ec681f3Smrg} 4647ec681f3Smrg 4657ec681f3Smrgstatic inline unsigned 4667ec681f3Smrgnir_src_index(compiler_context *ctx, nir_src *src) 4677ec681f3Smrg{ 4687ec681f3Smrg if (src->is_ssa) 4697ec681f3Smrg return nir_ssa_index(src->ssa); 4707ec681f3Smrg else { 4717ec681f3Smrg assert(!src->reg.indirect); 4727ec681f3Smrg return (src->reg.reg->index << 1) | PAN_IS_REG; 4737ec681f3Smrg } 4747ec681f3Smrg} 4757ec681f3Smrg 4767ec681f3Smrgstatic inline unsigned 4777ec681f3Smrgnir_dest_index(nir_dest *dst) 4787ec681f3Smrg{ 4797ec681f3Smrg if (dst->is_ssa) 4807ec681f3Smrg return (dst->ssa.index << 1) | 0; 4817ec681f3Smrg else { 4827ec681f3Smrg assert(!dst->reg.indirect); 4837ec681f3Smrg return (dst->reg.reg->index << 1) | PAN_IS_REG; 4847ec681f3Smrg } 4857ec681f3Smrg} 4867ec681f3Smrg 4877ec681f3Smrg 4887ec681f3Smrg 4897ec681f3Smrg/* MIR manipulation */ 4907ec681f3Smrg 4917ec681f3Smrgvoid mir_rewrite_index(compiler_context *ctx, unsigned old, unsigned new); 4927ec681f3Smrgvoid mir_rewrite_index_src(compiler_context *ctx, unsigned old, unsigned new); 4937ec681f3Smrgvoid mir_rewrite_index_dst(compiler_context *ctx, unsigned old, unsigned new); 4947ec681f3Smrgvoid mir_rewrite_index_dst_single(midgard_instruction *ins, unsigned old, unsigned new); 4957ec681f3Smrgvoid mir_rewrite_index_src_single(midgard_instruction *ins, unsigned old, unsigned new); 4967ec681f3Smrgvoid mir_rewrite_index_src_swizzle(compiler_context *ctx, unsigned old, unsigned new, unsigned *swizzle); 4977ec681f3Smrgbool mir_single_use(compiler_context *ctx, unsigned value); 4987ec681f3Smrgunsigned mir_use_count(compiler_context *ctx, unsigned value); 4997ec681f3Smrguint16_t mir_bytemask_of_read_components(midgard_instruction *ins, unsigned node); 5007ec681f3Smrguint16_t mir_bytemask_of_read_components_index(midgard_instruction *ins, unsigned i); 5017ec681f3Smrguint16_t mir_from_bytemask(uint16_t bytemask, unsigned bits); 5027ec681f3Smrguint16_t mir_bytemask(midgard_instruction *ins); 5037ec681f3Smrguint16_t mir_round_bytemask_up(uint16_t mask, unsigned bits); 5047ec681f3Smrgvoid mir_set_bytemask(midgard_instruction *ins, uint16_t bytemask); 5057ec681f3Smrgsigned mir_upper_override(midgard_instruction *ins, unsigned inst_size); 5067ec681f3Smrgunsigned mir_components_for_type(nir_alu_type T); 5077ec681f3Smrgunsigned max_bitsize_for_alu(midgard_instruction *ins); 5087ec681f3Smrgmidgard_reg_mode reg_mode_for_bitsize(unsigned bitsize); 5097ec681f3Smrg 5107ec681f3Smrg/* MIR printing */ 5117ec681f3Smrg 5127ec681f3Smrgvoid mir_print_instruction(midgard_instruction *ins); 5137ec681f3Smrgvoid mir_print_bundle(midgard_bundle *ctx); 5147ec681f3Smrgvoid mir_print_block(midgard_block *block); 5157ec681f3Smrgvoid mir_print_shader(compiler_context *ctx); 5167ec681f3Smrgbool mir_nontrivial_mod(midgard_instruction *ins, unsigned i, bool check_swizzle); 5177ec681f3Smrgbool mir_nontrivial_outmod(midgard_instruction *ins); 5187ec681f3Smrg 5197ec681f3Smrgvoid mir_insert_instruction_before_scheduled(compiler_context *ctx, midgard_block *block, midgard_instruction *tag, midgard_instruction ins); 5207ec681f3Smrgvoid mir_insert_instruction_after_scheduled(compiler_context *ctx, midgard_block *block, midgard_instruction *tag, midgard_instruction ins); 5217ec681f3Smrgvoid mir_flip(midgard_instruction *ins); 5227ec681f3Smrgvoid mir_compute_temp_count(compiler_context *ctx); 5237ec681f3Smrg 5247ec681f3Smrg#define LDST_GLOBAL (REGISTER_LDST_ZERO << 2) 5257ec681f3Smrg#define LDST_SHARED ((REGISTER_LDST_LOCAL_STORAGE_PTR << 2) | COMPONENT_Z) 5267ec681f3Smrg#define LDST_SCRATCH ((REGISTER_LDST_PC_SP << 2) | COMPONENT_Z) 5277ec681f3Smrg 5287ec681f3Smrgvoid mir_set_offset(compiler_context *ctx, midgard_instruction *ins, nir_src *offset, unsigned seg); 5297ec681f3Smrgvoid mir_set_ubo_offset(midgard_instruction *ins, nir_src *src, unsigned bias); 5307ec681f3Smrg 5317ec681f3Smrg/* 'Intrinsic' move for aliasing */ 5327ec681f3Smrg 5337ec681f3Smrgstatic inline midgard_instruction 5347ec681f3Smrgv_mov(unsigned src, unsigned dest) 5357ec681f3Smrg{ 5367ec681f3Smrg midgard_instruction ins = { 5377ec681f3Smrg .type = TAG_ALU_4, 5387ec681f3Smrg .mask = 0xF, 5397ec681f3Smrg .src = { ~0, src, ~0, ~0 }, 5407ec681f3Smrg .src_types = { 0, nir_type_uint32 }, 5417ec681f3Smrg .swizzle = SWIZZLE_IDENTITY, 5427ec681f3Smrg .dest = dest, 5437ec681f3Smrg .dest_type = nir_type_uint32, 5447ec681f3Smrg .op = midgard_alu_op_imov, 5457ec681f3Smrg .outmod = midgard_outmod_keeplo 5467ec681f3Smrg }; 5477ec681f3Smrg 5487ec681f3Smrg return ins; 5497ec681f3Smrg} 5507ec681f3Smrg 5517ec681f3Smrg/* Broad types of register classes so we can handle special 5527ec681f3Smrg * registers */ 5537ec681f3Smrg 5547ec681f3Smrg#define REG_CLASS_WORK 0 5557ec681f3Smrg#define REG_CLASS_LDST 1 5567ec681f3Smrg#define REG_CLASS_TEXR 3 5577ec681f3Smrg#define REG_CLASS_TEXW 4 5587ec681f3Smrg 5597ec681f3Smrg/* Like a move, but to thread local storage! */ 5607ec681f3Smrg 5617ec681f3Smrgstatic inline midgard_instruction 5627ec681f3Smrgv_load_store_scratch( 5637ec681f3Smrg unsigned srcdest, 5647ec681f3Smrg unsigned index, 5657ec681f3Smrg bool is_store, 5667ec681f3Smrg unsigned mask) 5677ec681f3Smrg{ 5687ec681f3Smrg /* We index by 32-bit vec4s */ 5697ec681f3Smrg unsigned byte = (index * 4 * 4); 5707ec681f3Smrg 5717ec681f3Smrg midgard_instruction ins = { 5727ec681f3Smrg .type = TAG_LOAD_STORE_4, 5737ec681f3Smrg .mask = mask, 5747ec681f3Smrg .dest_type = nir_type_uint32, 5757ec681f3Smrg .dest = ~0, 5767ec681f3Smrg .src = { ~0, ~0, ~0, ~0 }, 5777ec681f3Smrg .swizzle = SWIZZLE_IDENTITY_4, 5787ec681f3Smrg .op = is_store ? midgard_op_st_128 : midgard_op_ld_128, 5797ec681f3Smrg .load_store = { 5807ec681f3Smrg /* For register spilling - to thread local storage */ 5817ec681f3Smrg .arg_reg = REGISTER_LDST_LOCAL_STORAGE_PTR, 5827ec681f3Smrg .arg_comp = COMPONENT_X, 5837ec681f3Smrg .bitsize_toggle = true, 5847ec681f3Smrg .index_format = midgard_index_address_u32, 5857ec681f3Smrg .index_reg = REGISTER_LDST_ZERO, 5867ec681f3Smrg }, 5877ec681f3Smrg 5887ec681f3Smrg /* If we spill an unspill, RA goes into an infinite loop */ 5897ec681f3Smrg .no_spill = (1 << REG_CLASS_WORK) 5907ec681f3Smrg }; 5917ec681f3Smrg 5927ec681f3Smrg ins.constants.u32[0] = byte; 5937ec681f3Smrg 5947ec681f3Smrg if (is_store) { 5957ec681f3Smrg ins.src[0] = srcdest; 5967ec681f3Smrg ins.src_types[0] = nir_type_uint32; 5977ec681f3Smrg 5987ec681f3Smrg /* Ensure we are tightly swizzled so liveness analysis is 5997ec681f3Smrg * correct */ 6007ec681f3Smrg 6017ec681f3Smrg for (unsigned i = 0; i < 4; ++i) { 6027ec681f3Smrg if (!(mask & (1 << i))) 6037ec681f3Smrg ins.swizzle[0][i] = COMPONENT_X; 6047ec681f3Smrg } 6057ec681f3Smrg } else 6067ec681f3Smrg ins.dest = srcdest; 6077ec681f3Smrg 6087ec681f3Smrg return ins; 6097ec681f3Smrg} 6107ec681f3Smrg 6117ec681f3Smrgstatic inline bool 6127ec681f3Smrgmir_has_arg(midgard_instruction *ins, unsigned arg) 6137ec681f3Smrg{ 6147ec681f3Smrg if (!ins) 6157ec681f3Smrg return false; 6167ec681f3Smrg 6177ec681f3Smrg mir_foreach_src(ins, i) { 6187ec681f3Smrg if (ins->src[i] == arg) 6197ec681f3Smrg return true; 6207ec681f3Smrg } 6217ec681f3Smrg 6227ec681f3Smrg return false; 6237ec681f3Smrg} 6247ec681f3Smrg 6257ec681f3Smrg/* Scheduling */ 6267ec681f3Smrg 6277ec681f3Smrgvoid midgard_schedule_program(compiler_context *ctx); 6287ec681f3Smrg 6297ec681f3Smrgvoid mir_ra(compiler_context *ctx); 6307ec681f3Smrgvoid mir_squeeze_index(compiler_context *ctx); 6317ec681f3Smrgvoid mir_lower_special_reads(compiler_context *ctx); 6327ec681f3Smrgvoid mir_liveness_ins_update(uint16_t *live, midgard_instruction *ins, unsigned max); 6337ec681f3Smrgvoid mir_compute_liveness(compiler_context *ctx); 6347ec681f3Smrgvoid mir_invalidate_liveness(compiler_context *ctx); 6357ec681f3Smrgbool mir_is_live_after(compiler_context *ctx, midgard_block *block, midgard_instruction *start, int src); 6367ec681f3Smrg 6377ec681f3Smrgvoid mir_create_pipeline_registers(compiler_context *ctx); 6387ec681f3Smrgvoid midgard_promote_uniforms(compiler_context *ctx); 6397ec681f3Smrg 6407ec681f3Smrgvoid 6417ec681f3Smrgmidgard_emit_derivatives(compiler_context *ctx, nir_alu_instr *instr); 6427ec681f3Smrg 6437ec681f3Smrgvoid 6447ec681f3Smrgmidgard_lower_derivatives(compiler_context *ctx, midgard_block *block); 6457ec681f3Smrg 6467ec681f3Smrgbool mir_op_computes_derivatives(gl_shader_stage stage, unsigned op); 6477ec681f3Smrg 6487ec681f3Smrgvoid mir_analyze_helper_terminate(compiler_context *ctx); 6497ec681f3Smrgvoid mir_analyze_helper_requirements(compiler_context *ctx); 6507ec681f3Smrg 6517ec681f3Smrg/* Final emission */ 6527ec681f3Smrg 6537ec681f3Smrgvoid emit_binary_bundle( 6547ec681f3Smrg compiler_context *ctx, 6557ec681f3Smrg midgard_block *block, 6567ec681f3Smrg midgard_bundle *bundle, 6577ec681f3Smrg struct util_dynarray *emission, 6587ec681f3Smrg int next_tag); 6597ec681f3Smrg 6607ec681f3Smrgbool nir_fuse_io_16(nir_shader *shader); 6617ec681f3Smrg 6627ec681f3Smrgbool midgard_nir_lod_errata(nir_shader *shader); 6637ec681f3Smrg 6647ec681f3Smrgunsigned midgard_get_first_tag_from_block(compiler_context *ctx, unsigned block_idx); 6657ec681f3Smrg 6667ec681f3Smrg/* Optimizations */ 6677ec681f3Smrg 6687ec681f3Smrgbool midgard_opt_copy_prop(compiler_context *ctx, midgard_block *block); 6697ec681f3Smrgbool midgard_opt_combine_projection(compiler_context *ctx, midgard_block *block); 6707ec681f3Smrgbool midgard_opt_varying_projection(compiler_context *ctx, midgard_block *block); 6717ec681f3Smrgbool midgard_opt_dead_code_eliminate(compiler_context *ctx); 6727ec681f3Smrgbool midgard_opt_dead_move_eliminate(compiler_context *ctx, midgard_block *block); 6737ec681f3Smrg 6747ec681f3Smrg#endif 675