17ec681f3Smrg/* 27ec681f3Smrg * Copyright (C) 2020 Collabora, Ltd. 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 207ec681f3Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 217ec681f3Smrg * SOFTWARE. 227ec681f3Smrg */ 237ec681f3Smrg 247ec681f3Smrg#include "compiler.h" 257ec681f3Smrg 267ec681f3Smrg/* The scheduler packs multiple instructions into a clause (grouped as tuple), 277ec681f3Smrg * and the packing code takes in a clause and emits it to the wire. During 287ec681f3Smrg * scheduling, we need to lay out the instructions (tuples) and constants 297ec681f3Smrg * within the clause so constraints can be resolved during scheduling instead 307ec681f3Smrg * of failing packing. These routines will help building clauses from 317ec681f3Smrg * instructions so the scheduler can focus on the high-level algorithm, and 327ec681f3Smrg * manipulating clause layouts. 337ec681f3Smrg */ 347ec681f3Smrg 357ec681f3Smrg/* Is embedded constant 0 packed for free in a clause with this many tuples? */ 367ec681f3Smrg 377ec681f3Smrgbool 387ec681f3Smrgbi_ec0_packed(unsigned tuple_count) 397ec681f3Smrg{ 407ec681f3Smrg return (tuple_count == 3) || 417ec681f3Smrg (tuple_count == 5) || 427ec681f3Smrg (tuple_count == 6) || 437ec681f3Smrg (tuple_count == 8); 447ec681f3Smrg} 457ec681f3Smrg 467ec681f3Smrg/* Helper to calculate the number of quadwords in a clause. This is a function 477ec681f3Smrg * of the number of instructions and constants; it doesn't require actually 487ec681f3Smrg * packing, which is useful for branch offsets. 497ec681f3Smrg * 507ec681f3Smrg * Table of instruction count to instruction quadwords, per the packing 517ec681f3Smrg * algorithm, where * indicates a constant is packed for free: 527ec681f3Smrg * 537ec681f3Smrg * X | Y 547ec681f3Smrg * ---|--- 557ec681f3Smrg * 1 | 1 567ec681f3Smrg * 2 | 2 577ec681f3Smrg * 3 | 3* 587ec681f3Smrg * 4 | 3 597ec681f3Smrg * 5 | 4* 607ec681f3Smrg * 6 | 5* 617ec681f3Smrg * 7 | 5 627ec681f3Smrg * 8 | 6* 637ec681f3Smrg * 647ec681f3Smrg * Y = { X if X <= 3 657ec681f3Smrg * { X - 1 if 4 <= X <= 6 667ec681f3Smrg * { X - 2 if 7 <= X <= 8 677ec681f3Smrg * 687ec681f3Smrg * and there is a constant for free if X is in {3, 5, 6, 8}. The remaining 697ec681f3Smrg * constants are packed two-by-two as constant quadwords. 707ec681f3Smrg */ 717ec681f3Smrg 727ec681f3Smrgstatic unsigned 737ec681f3Smrgbi_clause_quadwords(bi_clause *clause) 747ec681f3Smrg{ 757ec681f3Smrg unsigned X = clause->tuple_count; 767ec681f3Smrg unsigned Y = X - ((X >= 7) ? 2 : (X >= 4) ? 1 : 0); 777ec681f3Smrg 787ec681f3Smrg unsigned constants = clause->constant_count; 797ec681f3Smrg 807ec681f3Smrg if ((X != 4) && (X != 7) && (X >= 3) && constants) 817ec681f3Smrg constants--; 827ec681f3Smrg 837ec681f3Smrg return Y + DIV_ROUND_UP(constants, 2); 847ec681f3Smrg} 857ec681f3Smrg 867ec681f3Smrg/* Measures the number of quadwords a branch jumps. Bifrost relative offsets 877ec681f3Smrg * are from the beginning of a clause so to jump forward we count the current 887ec681f3Smrg * clause length, but to jump backwards we do not. */ 897ec681f3Smrg 907ec681f3Smrgsigned 917ec681f3Smrgbi_block_offset(bi_context *ctx, bi_clause *start, bi_block *target) 927ec681f3Smrg{ 937ec681f3Smrg /* Signed since we might jump backwards */ 947ec681f3Smrg signed ret = 0; 957ec681f3Smrg 967ec681f3Smrg /* Determine if the block we're branching to is strictly greater in 977ec681f3Smrg * source order */ 987ec681f3Smrg bool forwards = target->name > start->block->name; 997ec681f3Smrg 1007ec681f3Smrg if (forwards) { 1017ec681f3Smrg /* We have to jump through this block from the start of this 1027ec681f3Smrg * clause to the end */ 1037ec681f3Smrg bi_foreach_clause_in_block_from(start->block, clause, start) { 1047ec681f3Smrg ret += bi_clause_quadwords(clause); 1057ec681f3Smrg } 1067ec681f3Smrg 1077ec681f3Smrg /* We then need to jump through every clause of every following 1087ec681f3Smrg * block until the target */ 1097ec681f3Smrg bi_foreach_block_from(ctx, start->block, blk) { 1107ec681f3Smrg /* Don't double-count the first block */ 1117ec681f3Smrg if (blk == start->block) 1127ec681f3Smrg continue; 1137ec681f3Smrg 1147ec681f3Smrg /* End just before the target */ 1157ec681f3Smrg if (blk == target) 1167ec681f3Smrg break; 1177ec681f3Smrg 1187ec681f3Smrg /* Count every clause in the block */ 1197ec681f3Smrg bi_foreach_clause_in_block(blk, clause) { 1207ec681f3Smrg ret += bi_clause_quadwords(clause); 1217ec681f3Smrg } 1227ec681f3Smrg } 1237ec681f3Smrg } else { 1247ec681f3Smrg /* We start at the beginning of the clause but have to jump 1257ec681f3Smrg * through the clauses before us in the block */ 1267ec681f3Smrg bi_foreach_clause_in_block_from_rev(start->block, clause, start) { 1277ec681f3Smrg if (clause == start) 1287ec681f3Smrg continue; 1297ec681f3Smrg 1307ec681f3Smrg ret -= bi_clause_quadwords(clause); 1317ec681f3Smrg } 1327ec681f3Smrg 1337ec681f3Smrg /* And jump back every clause of preceding blocks up through 1347ec681f3Smrg * and including the target to get to the beginning of the 1357ec681f3Smrg * target */ 1367ec681f3Smrg bi_foreach_block_from_rev(ctx, start->block, blk) { 1377ec681f3Smrg if (blk == start->block) 1387ec681f3Smrg continue; 1397ec681f3Smrg 1407ec681f3Smrg bi_foreach_clause_in_block(blk, clause) { 1417ec681f3Smrg ret -= bi_clause_quadwords(clause); 1427ec681f3Smrg } 1437ec681f3Smrg 1447ec681f3Smrg /* End just after the target */ 1457ec681f3Smrg if (blk == target) 1467ec681f3Smrg break; 1477ec681f3Smrg } 1487ec681f3Smrg } 1497ec681f3Smrg 1507ec681f3Smrg return ret; 1517ec681f3Smrg} 152