Path: blob/21.2-virgl/src/gallium/drivers/lima/ir/pp/instr.c
4574 views
/*1* Copyright (c) 2017 Lima Project2*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, sub license,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 the11* next paragraph) shall be included in all copies or substantial portions12* of the 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 NON-INFRINGEMENT. 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, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER20* DEALINGS IN THE SOFTWARE.21*22*/2324#include "util/ralloc.h"2526#include "ppir.h"2728ppir_instr *ppir_instr_create(ppir_block *block)29{30ppir_instr *instr = rzalloc(block, ppir_instr);31if (!instr)32return NULL;3334list_inithead(&instr->succ_list);35list_inithead(&instr->pred_list);3637instr->index = block->comp->cur_instr_index++;38instr->reg_pressure = -1;3940list_addtail(&instr->list, &block->instr_list);41return instr;42}4344void ppir_instr_add_dep(ppir_instr *succ, ppir_instr *pred)45{46/* don't add duplicated instr */47ppir_instr_foreach_pred(succ, dep) {48if (pred == dep->pred)49return;50}5152ppir_dep *dep = ralloc(succ, ppir_dep);53dep->pred = pred;54dep->succ = succ;55list_addtail(&dep->pred_link, &succ->pred_list);56list_addtail(&dep->succ_link, &pred->succ_list);57}5859void ppir_instr_insert_mul_node(ppir_node *add, ppir_node *mul)60{61ppir_instr *instr = add->instr;62int pos = mul->instr_pos;63int *slots = ppir_op_infos[mul->op].slots;6465for (int i = 0; slots[i] != PPIR_INSTR_SLOT_END; i++) {66/* possible to insert at required place */67if (slots[i] == pos) {68if (!instr->slots[pos]) {69ppir_alu_node *add_alu = ppir_node_to_alu(add);70ppir_alu_node *mul_alu = ppir_node_to_alu(mul);71ppir_dest *dest = &mul_alu->dest;72int pipeline = pos == PPIR_INSTR_SLOT_ALU_VEC_MUL ?73ppir_pipeline_reg_vmul : ppir_pipeline_reg_fmul;7475/* ^vmul/^fmul can't be used as last arg */76if (add_alu->num_src > 1) {77ppir_src *last_src = add_alu->src + add_alu->num_src - 1;78if (ppir_node_target_equal(last_src, dest))79return;80}8182/* update add node src to use pipeline reg */83ppir_src *src = add_alu->src;84if (add_alu->num_src == 3) {85if (ppir_node_target_equal(src, dest)) {86src->type = ppir_target_pipeline;87src->pipeline = pipeline;88}8990if (ppir_node_target_equal(++src, dest)) {91src->type = ppir_target_pipeline;92src->pipeline = pipeline;93}94}95else {96assert(ppir_node_target_equal(src, dest));97src->type = ppir_target_pipeline;98src->pipeline = pipeline;99}100101/* update mul node dest to output to pipeline reg */102dest->type = ppir_target_pipeline;103dest->pipeline = pipeline;104105instr->slots[pos] = mul;106mul->instr = instr;107}108return;109}110}111}112113/* check whether a const slot fix into another const slot */114static bool ppir_instr_insert_const(ppir_const *dst, const ppir_const *src,115uint8_t *swizzle)116{117int i, j;118119for (i = 0; i < src->num; i++) {120for (j = 0; j < dst->num; j++) {121if (src->value[i].ui == dst->value[j].ui)122break;123}124125if (j == dst->num) {126if (dst->num == 4)127return false;128dst->value[dst->num++] = src->value[i];129}130131swizzle[i] = j;132}133134return true;135}136137static void ppir_update_src_pipeline(ppir_pipeline pipeline, ppir_src *src,138ppir_dest *dest, uint8_t *swizzle)139{140if (ppir_node_target_equal(src, dest)) {141src->type = ppir_target_pipeline;142src->pipeline = pipeline;143144if (swizzle) {145for (int k = 0; k < 4; k++)146src->swizzle[k] = swizzle[src->swizzle[k]];147}148}149}150151/* make alu node src reflact the pipeline reg */152static void ppir_instr_update_src_pipeline(ppir_instr *instr, ppir_pipeline pipeline,153ppir_dest *dest, uint8_t *swizzle)154{155for (int i = PPIR_INSTR_SLOT_ALU_START; i <= PPIR_INSTR_SLOT_ALU_END; i++) {156if (!instr->slots[i])157continue;158159ppir_alu_node *alu = ppir_node_to_alu(instr->slots[i]);160for (int j = 0; j < alu->num_src; j++) {161ppir_src *src = alu->src + j;162ppir_update_src_pipeline(pipeline, src, dest, swizzle);163}164}165166ppir_node *branch_node = instr->slots[PPIR_INSTR_SLOT_BRANCH];167if (branch_node && (branch_node->type == ppir_node_type_branch)) {168ppir_branch_node *branch = ppir_node_to_branch(branch_node);169for (int j = 0; j < 2; j++) {170ppir_src *src = branch->src + j;171ppir_update_src_pipeline(pipeline, src, dest, swizzle);172}173}174}175176bool ppir_instr_insert_node(ppir_instr *instr, ppir_node *node)177{178if (node->op == ppir_op_const) {179int i;180ppir_const_node *c = ppir_node_to_const(node);181const ppir_const *nc = &c->constant;182183for (i = 0; i < 2; i++) {184ppir_const ic = instr->constant[i];185uint8_t swizzle[4] = {0};186187if (ppir_instr_insert_const(&ic, nc, swizzle)) {188ppir_node *succ = ppir_node_first_succ(node);189ppir_src *src = NULL;190for (int s = 0; s < ppir_node_get_src_num(succ); s++) {191src = ppir_node_get_src(succ, s);192if (src->node == node)193break;194}195assert(src->node == node);196197instr->constant[i] = ic;198ppir_update_src_pipeline(ppir_pipeline_reg_const0 + i, src,199&c->dest, swizzle);200break;201}202}203204/* no const slot can insert */205if (i == 2)206return false;207208return true;209}210else {211int *slots = ppir_op_infos[node->op].slots;212for (int i = 0; slots[i] != PPIR_INSTR_SLOT_END; i++) {213int pos = slots[i];214215if (instr->slots[pos]) {216/* node already in this instr, i.e. load_uniform */217if (instr->slots[pos] == node)218return true;219else220continue;221}222223/* ^fmul dests (e.g. condition for select) can only be224* scheduled to ALU_SCL_MUL */225if (pos == PPIR_INSTR_SLOT_ALU_SCL_ADD) {226ppir_dest *dest = ppir_node_get_dest(node);227if (dest && dest->type == ppir_target_pipeline &&228dest->pipeline == ppir_pipeline_reg_fmul)229continue;230}231232if (pos == PPIR_INSTR_SLOT_ALU_SCL_MUL ||233pos == PPIR_INSTR_SLOT_ALU_SCL_ADD) {234ppir_dest *dest = ppir_node_get_dest(node);235if (!ppir_target_is_scalar(dest))236continue;237}238239instr->slots[pos] = node;240node->instr = instr;241node->instr_pos = pos;242243if ((node->op == ppir_op_load_uniform) || (node->op == ppir_op_load_temp)) {244ppir_load_node *l = ppir_node_to_load(node);245ppir_instr_update_src_pipeline(246instr, ppir_pipeline_reg_uniform, &l->dest, NULL);247}248249return true;250}251252return false;253}254}255256static struct {257int len;258char *name;259} ppir_instr_fields[] = {260[PPIR_INSTR_SLOT_VARYING] = { 4, "vary" },261[PPIR_INSTR_SLOT_TEXLD] = { 4, "texl"},262[PPIR_INSTR_SLOT_UNIFORM] = { 4, "unif" },263[PPIR_INSTR_SLOT_ALU_VEC_MUL] = { 4, "vmul" },264[PPIR_INSTR_SLOT_ALU_SCL_MUL] = { 4, "smul" },265[PPIR_INSTR_SLOT_ALU_VEC_ADD] = { 4, "vadd" },266[PPIR_INSTR_SLOT_ALU_SCL_ADD] = { 4, "sadd" },267[PPIR_INSTR_SLOT_ALU_COMBINE] = { 4, "comb" },268[PPIR_INSTR_SLOT_STORE_TEMP] = { 4, "stor" },269[PPIR_INSTR_SLOT_BRANCH] = { 4, "brch" },270};271272void ppir_instr_print_list(ppir_compiler *comp)273{274if (!(lima_debug & LIMA_DEBUG_PP))275return;276277printf("======ppir instr list======\n");278printf(" ");279for (int i = 0; i < PPIR_INSTR_SLOT_NUM; i++)280printf("%-*s ", ppir_instr_fields[i].len, ppir_instr_fields[i].name);281printf("const0|1\n");282283list_for_each_entry(ppir_block, block, &comp->block_list, list) {284printf("-------block %3d-------\n", block->index);285list_for_each_entry(ppir_instr, instr, &block->instr_list, list) {286printf("%c%03d: ", instr->is_end ? '*' : ' ', instr->index);287for (int i = 0; i < PPIR_INSTR_SLOT_NUM; i++) {288ppir_node *node = instr->slots[i];289if (node)290printf("%-*d ", ppir_instr_fields[i].len, node->index);291else292printf("%-*s ", ppir_instr_fields[i].len, "null");293}294for (int i = 0; i < 2; i++) {295if (i)296printf("| ");297298for (int j = 0; j < instr->constant[i].num; j++)299printf("%f ", instr->constant[i].value[j].f);300}301printf("\n");302}303}304printf("===========================\n");305}306307static void ppir_instr_print_sub(ppir_instr *instr)308{309printf("[%s%d",310instr->printed && !ppir_instr_is_leaf(instr) ? "+" : "",311instr->index);312313if (!instr->printed) {314ppir_instr_foreach_pred(instr, dep) {315ppir_instr_print_sub(dep->pred);316}317318instr->printed = true;319}320321printf("]");322}323324void ppir_instr_print_dep(ppir_compiler *comp)325{326if (!(lima_debug & LIMA_DEBUG_PP))327return;328329list_for_each_entry(ppir_block, block, &comp->block_list, list) {330list_for_each_entry(ppir_instr, instr, &block->instr_list, list) {331instr->printed = false;332}333}334335printf("======ppir instr depend======\n");336list_for_each_entry(ppir_block, block, &comp->block_list, list) {337printf("-------block %3d-------\n", block->index);338list_for_each_entry(ppir_instr, instr, &block->instr_list, list) {339if (ppir_instr_is_root(instr)) {340ppir_instr_print_sub(instr);341printf("\n");342}343}344}345printf("=============================\n");346}347348349