Path: blob/21.2-virgl/src/panfrost/bifrost/bir.c
4564 views
/*1* Copyright (C) 2020 Collabora Ltd.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,19* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE20* SOFTWARE.21*22* Authors (Collabora):23* Alyssa Rosenzweig <[email protected]>24*/2526#include "compiler.h"2728bool29bi_has_arg(bi_instr *ins, bi_index arg)30{31if (!ins)32return false;3334bi_foreach_src(ins, s) {35if (bi_is_equiv(ins->src[s], arg))36return true;37}3839return false;40}4142/* Precondition: valid 16-bit or 32-bit register format. Returns whether it is43* 32-bit. Note auto reads to 32-bit registers even if the memory format is44* 16-bit, so is considered as such here */4546bool47bi_is_regfmt_16(enum bi_register_format fmt)48{49switch (fmt) {50case BI_REGISTER_FORMAT_F16:51case BI_REGISTER_FORMAT_S16:52case BI_REGISTER_FORMAT_U16:53return true;54case BI_REGISTER_FORMAT_F32:55case BI_REGISTER_FORMAT_S32:56case BI_REGISTER_FORMAT_U32:57case BI_REGISTER_FORMAT_AUTO:58return false;59default:60unreachable("Invalid register format");61}62}6364static unsigned65bi_count_staging_registers(bi_instr *ins)66{67enum bi_sr_count count = bi_opcode_props[ins->op].sr_count;68unsigned vecsize = ins->vecsize + 1; /* XXX: off-by-one */6970switch (count) {71case BI_SR_COUNT_0 ... BI_SR_COUNT_4:72return count;73case BI_SR_COUNT_FORMAT:74return bi_is_regfmt_16(ins->register_format) ?75DIV_ROUND_UP(vecsize, 2) : vecsize;76case BI_SR_COUNT_VECSIZE:77return vecsize;78case BI_SR_COUNT_SR_COUNT:79return ins->sr_count;80}8182unreachable("Invalid sr_count");83}8485unsigned86bi_count_read_registers(bi_instr *ins, unsigned s)87{88if (s == 0 && bi_opcode_props[ins->op].sr_read)89return bi_count_staging_registers(ins);90else91return 1;92}9394unsigned95bi_count_write_registers(bi_instr *ins, unsigned d)96{97if (d == 0 && bi_opcode_props[ins->op].sr_write) {98/* TODO: this special case is even more special, TEXC has a99* generic write mask stuffed in the desc... */100if (ins->op == BI_OPCODE_TEXC)101return 4;102else103return bi_count_staging_registers(ins);104}105106return 1;107}108109unsigned110bi_writemask(bi_instr *ins, unsigned d)111{112unsigned mask = BITFIELD_MASK(bi_count_write_registers(ins, d));113unsigned shift = ins->dest[d].offset;114return (mask << shift);115}116117bi_clause *118bi_next_clause(bi_context *ctx, pan_block *block, bi_clause *clause)119{120if (!block && !clause)121return NULL;122123/* Try the first clause in this block if we're starting from scratch */124if (!clause && !list_is_empty(&((bi_block *) block)->clauses))125return list_first_entry(&((bi_block *) block)->clauses, bi_clause, link);126127/* Try the next clause in this block */128if (clause && clause->link.next != &((bi_block *) block)->clauses)129return list_first_entry(&(clause->link), bi_clause, link);130131/* Try the next block, or the one after that if it's empty, etc .*/132pan_block *next_block = pan_next_block(block);133134bi_foreach_block_from(ctx, next_block, block) {135bi_block *blk = (bi_block *) block;136137if (!list_is_empty(&blk->clauses))138return list_first_entry(&(blk->clauses), bi_clause, link);139}140141return NULL;142}143144/* Does an instruction have a side effect not captured by its register145* destination? Applies to certain message-passing instructions, +DISCARD, and146* branching only, used in dead code elimation. Branches are characterized by147* `last` which applies to them and some atomics, +BARRIER, +BLEND which148* implies no loss of generality */149150bool151bi_side_effects(enum bi_opcode op)152{153if (bi_opcode_props[op].last || op == BI_OPCODE_DISCARD_F32)154return true;155156switch (bi_opcode_props[op].message) {157case BIFROST_MESSAGE_NONE:158case BIFROST_MESSAGE_VARYING:159case BIFROST_MESSAGE_ATTRIBUTE:160case BIFROST_MESSAGE_TEX:161case BIFROST_MESSAGE_VARTEX:162case BIFROST_MESSAGE_LOAD:163case BIFROST_MESSAGE_64BIT:164return false;165166case BIFROST_MESSAGE_STORE:167case BIFROST_MESSAGE_ATOMIC:168case BIFROST_MESSAGE_BARRIER:169case BIFROST_MESSAGE_BLEND:170case BIFROST_MESSAGE_Z_STENCIL:171case BIFROST_MESSAGE_ATEST:172case BIFROST_MESSAGE_JOB:173return true;174175case BIFROST_MESSAGE_TILE:176return (op != BI_OPCODE_LD_TILE);177}178179unreachable("Invalid message type");180}181182183