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