Path: blob/21.2-virgl/src/panfrost/bifrost/bi_layout.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*/2223#include "compiler.h"2425/* The scheduler packs multiple instructions into a clause (grouped as tuple),26* and the packing code takes in a clause and emits it to the wire. During27* scheduling, we need to lay out the instructions (tuples) and constants28* within the clause so constraints can be resolved during scheduling instead29* of failing packing. These routines will help building clauses from30* instructions so the scheduler can focus on the high-level algorithm, and31* manipulating clause layouts.32*/3334/* Helper to see if a tuple can be inserted. We must satisfy the invariant:35*36* constant_count + tuple_count <= 1337*38* ...which is equivalent to the clause ending up with 8 or fewer quardwords.39* Inserting a tuple increases tuple_count by one, and if it reads a unique40* constant, it increases constant_count by one.41*/4243bool44bi_can_insert_tuple(bi_clause *clause, bool constant)45{46unsigned constant_count = clause->constant_count + (constant ? 1 : 0);47unsigned tuple_count = clause->tuple_count + 1;4849return (constant_count + tuple_count) <= 13;50}5152/* Is embedded constant 0 packed for free in a clause with this many tuples? */5354bool55bi_ec0_packed(unsigned tuple_count)56{57return (tuple_count == 3) ||58(tuple_count == 5) ||59(tuple_count == 6) ||60(tuple_count == 8);61}6263/* Helper to calculate the number of quadwords in a clause. This is a function64* of the number of instructions and constants; it doesn't require actually65* packing, which is useful for branch offsets.66*67* Table of instruction count to instruction quadwords, per the packing68* algorithm, where * indicates a constant is packed for free:69*70* X | Y71* ---|---72* 1 | 173* 2 | 274* 3 | 3*75* 4 | 376* 5 | 4*77* 6 | 5*78* 7 | 579* 8 | 6*80*81* Y = { X if X <= 382* { X - 1 if 4 <= X <= 683* { X - 2 if 7 <= X <= 884*85* and there is a constant for free if X is in {3, 5, 6, 8}. The remaining86* constants are packed two-by-two as constant quadwords.87*/8889unsigned90bi_clause_quadwords(bi_clause *clause)91{92unsigned X = clause->tuple_count;93unsigned Y = X - ((X >= 7) ? 2 : (X >= 4) ? 1 : 0);9495unsigned constants = clause->constant_count;9697if ((X != 4) && (X != 7) && (X >= 3) && constants)98constants--;99100return Y + DIV_ROUND_UP(constants, 2);101}102103/* Measures the number of quadwords a branch jumps. Bifrost relative offsets104* are from the beginning of a clause so to jump forward we count the current105* clause length, but to jump backwards we do not. */106107signed108bi_block_offset(bi_context *ctx, bi_clause *start, bi_block *target)109{110/* Signed since we might jump backwards */111signed ret = 0;112113/* Determine if the block we're branching to is strictly greater in114* source order */115bool forwards = target->base.name > start->block->base.name;116117if (forwards) {118/* We have to jump through this block from the start of this119* clause to the end */120bi_foreach_clause_in_block_from(start->block, clause, start) {121ret += bi_clause_quadwords(clause);122}123124/* We then need to jump through every clause of every following125* block until the target */126bi_foreach_block_from(ctx, start->block, _blk) {127bi_block *blk = (bi_block *) _blk;128129/* Don't double-count the first block */130if (blk == start->block)131continue;132133/* End just before the target */134if (blk == target)135break;136137/* Count every clause in the block */138bi_foreach_clause_in_block(blk, clause) {139ret += bi_clause_quadwords(clause);140}141}142} else {143/* We start at the beginning of the clause but have to jump144* through the clauses before us in the block */145bi_foreach_clause_in_block_from_rev(start->block, clause, start) {146if (clause == start)147continue;148149ret -= bi_clause_quadwords(clause);150}151152/* And jump back every clause of preceding blocks up through153* and including the target to get to the beginning of the154* target */155bi_foreach_block_from_rev(ctx, start->block, _blk) {156bi_block *blk = (bi_block *) _blk;157158if (blk == start->block)159continue;160161bi_foreach_clause_in_block(blk, clause) {162ret -= bi_clause_quadwords(clause);163}164165/* End just after the target */166if (blk == target)167break;168}169}170171return ret;172}173174175