1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (c) 2017 Lima Project 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sub license, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 12bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 13bf215546Sopenharmony_ci * of the Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#include "util/ralloc.h" 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "ppir.h" 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_cippir_instr *ppir_instr_create(ppir_block *block) 30bf215546Sopenharmony_ci{ 31bf215546Sopenharmony_ci ppir_instr *instr = rzalloc(block, ppir_instr); 32bf215546Sopenharmony_ci if (!instr) 33bf215546Sopenharmony_ci return NULL; 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci list_inithead(&instr->succ_list); 36bf215546Sopenharmony_ci list_inithead(&instr->pred_list); 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci instr->index = block->comp->cur_instr_index++; 39bf215546Sopenharmony_ci instr->reg_pressure = -1; 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci list_addtail(&instr->list, &block->instr_list); 42bf215546Sopenharmony_ci return instr; 43bf215546Sopenharmony_ci} 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_civoid ppir_instr_add_dep(ppir_instr *succ, ppir_instr *pred) 46bf215546Sopenharmony_ci{ 47bf215546Sopenharmony_ci /* don't add duplicated instr */ 48bf215546Sopenharmony_ci ppir_instr_foreach_pred(succ, dep) { 49bf215546Sopenharmony_ci if (pred == dep->pred) 50bf215546Sopenharmony_ci return; 51bf215546Sopenharmony_ci } 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci ppir_dep *dep = ralloc(succ, ppir_dep); 54bf215546Sopenharmony_ci dep->pred = pred; 55bf215546Sopenharmony_ci dep->succ = succ; 56bf215546Sopenharmony_ci list_addtail(&dep->pred_link, &succ->pred_list); 57bf215546Sopenharmony_ci list_addtail(&dep->succ_link, &pred->succ_list); 58bf215546Sopenharmony_ci} 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_civoid ppir_instr_insert_mul_node(ppir_node *add, ppir_node *mul) 61bf215546Sopenharmony_ci{ 62bf215546Sopenharmony_ci ppir_instr *instr = add->instr; 63bf215546Sopenharmony_ci int pos = mul->instr_pos; 64bf215546Sopenharmony_ci int *slots = ppir_op_infos[mul->op].slots; 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci for (int i = 0; slots[i] != PPIR_INSTR_SLOT_END; i++) { 67bf215546Sopenharmony_ci /* possible to insert at required place */ 68bf215546Sopenharmony_ci if (slots[i] == pos) { 69bf215546Sopenharmony_ci if (!instr->slots[pos]) { 70bf215546Sopenharmony_ci ppir_alu_node *add_alu = ppir_node_to_alu(add); 71bf215546Sopenharmony_ci ppir_alu_node *mul_alu = ppir_node_to_alu(mul); 72bf215546Sopenharmony_ci ppir_dest *dest = &mul_alu->dest; 73bf215546Sopenharmony_ci int pipeline = pos == PPIR_INSTR_SLOT_ALU_VEC_MUL ? 74bf215546Sopenharmony_ci ppir_pipeline_reg_vmul : ppir_pipeline_reg_fmul; 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ci /* ^vmul/^fmul can't be used as last arg */ 77bf215546Sopenharmony_ci if (add_alu->num_src > 1) { 78bf215546Sopenharmony_ci ppir_src *last_src = add_alu->src + add_alu->num_src - 1; 79bf215546Sopenharmony_ci if (ppir_node_target_equal(last_src, dest)) 80bf215546Sopenharmony_ci return; 81bf215546Sopenharmony_ci } 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci /* update add node src to use pipeline reg */ 84bf215546Sopenharmony_ci ppir_src *src = add_alu->src; 85bf215546Sopenharmony_ci if (add_alu->num_src == 3) { 86bf215546Sopenharmony_ci if (ppir_node_target_equal(src, dest)) { 87bf215546Sopenharmony_ci src->type = ppir_target_pipeline; 88bf215546Sopenharmony_ci src->pipeline = pipeline; 89bf215546Sopenharmony_ci } 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci if (ppir_node_target_equal(++src, dest)) { 92bf215546Sopenharmony_ci src->type = ppir_target_pipeline; 93bf215546Sopenharmony_ci src->pipeline = pipeline; 94bf215546Sopenharmony_ci } 95bf215546Sopenharmony_ci } 96bf215546Sopenharmony_ci else { 97bf215546Sopenharmony_ci assert(ppir_node_target_equal(src, dest)); 98bf215546Sopenharmony_ci src->type = ppir_target_pipeline; 99bf215546Sopenharmony_ci src->pipeline = pipeline; 100bf215546Sopenharmony_ci } 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci /* update mul node dest to output to pipeline reg */ 103bf215546Sopenharmony_ci dest->type = ppir_target_pipeline; 104bf215546Sopenharmony_ci dest->pipeline = pipeline; 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ci instr->slots[pos] = mul; 107bf215546Sopenharmony_ci mul->instr = instr; 108bf215546Sopenharmony_ci } 109bf215546Sopenharmony_ci return; 110bf215546Sopenharmony_ci } 111bf215546Sopenharmony_ci } 112bf215546Sopenharmony_ci} 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci/* check whether a const slot fix into another const slot */ 115bf215546Sopenharmony_cistatic bool ppir_instr_insert_const(ppir_const *dst, const ppir_const *src, 116bf215546Sopenharmony_ci uint8_t *swizzle) 117bf215546Sopenharmony_ci{ 118bf215546Sopenharmony_ci int i, j; 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci for (i = 0; i < src->num; i++) { 121bf215546Sopenharmony_ci for (j = 0; j < dst->num; j++) { 122bf215546Sopenharmony_ci if (src->value[i].ui == dst->value[j].ui) 123bf215546Sopenharmony_ci break; 124bf215546Sopenharmony_ci } 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_ci if (j == dst->num) { 127bf215546Sopenharmony_ci if (dst->num == 4) 128bf215546Sopenharmony_ci return false; 129bf215546Sopenharmony_ci dst->value[dst->num++] = src->value[i]; 130bf215546Sopenharmony_ci } 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci swizzle[i] = j; 133bf215546Sopenharmony_ci } 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci return true; 136bf215546Sopenharmony_ci} 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_cistatic void ppir_update_src_pipeline(ppir_pipeline pipeline, ppir_src *src, 139bf215546Sopenharmony_ci ppir_dest *dest, uint8_t *swizzle) 140bf215546Sopenharmony_ci{ 141bf215546Sopenharmony_ci if (ppir_node_target_equal(src, dest)) { 142bf215546Sopenharmony_ci src->type = ppir_target_pipeline; 143bf215546Sopenharmony_ci src->pipeline = pipeline; 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci if (swizzle) { 146bf215546Sopenharmony_ci for (int k = 0; k < 4; k++) 147bf215546Sopenharmony_ci src->swizzle[k] = swizzle[src->swizzle[k]]; 148bf215546Sopenharmony_ci } 149bf215546Sopenharmony_ci } 150bf215546Sopenharmony_ci} 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci/* make alu node src reflact the pipeline reg */ 153bf215546Sopenharmony_cistatic void ppir_instr_update_src_pipeline(ppir_instr *instr, ppir_pipeline pipeline, 154bf215546Sopenharmony_ci ppir_dest *dest, uint8_t *swizzle) 155bf215546Sopenharmony_ci{ 156bf215546Sopenharmony_ci for (int i = PPIR_INSTR_SLOT_ALU_START; i <= PPIR_INSTR_SLOT_ALU_END; i++) { 157bf215546Sopenharmony_ci if (!instr->slots[i]) 158bf215546Sopenharmony_ci continue; 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci ppir_alu_node *alu = ppir_node_to_alu(instr->slots[i]); 161bf215546Sopenharmony_ci for (int j = 0; j < alu->num_src; j++) { 162bf215546Sopenharmony_ci ppir_src *src = alu->src + j; 163bf215546Sopenharmony_ci ppir_update_src_pipeline(pipeline, src, dest, swizzle); 164bf215546Sopenharmony_ci } 165bf215546Sopenharmony_ci } 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci ppir_node *branch_node = instr->slots[PPIR_INSTR_SLOT_BRANCH]; 168bf215546Sopenharmony_ci if (branch_node && (branch_node->type == ppir_node_type_branch)) { 169bf215546Sopenharmony_ci ppir_branch_node *branch = ppir_node_to_branch(branch_node); 170bf215546Sopenharmony_ci for (int j = 0; j < 2; j++) { 171bf215546Sopenharmony_ci ppir_src *src = branch->src + j; 172bf215546Sopenharmony_ci ppir_update_src_pipeline(pipeline, src, dest, swizzle); 173bf215546Sopenharmony_ci } 174bf215546Sopenharmony_ci } 175bf215546Sopenharmony_ci} 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_cibool ppir_instr_insert_node(ppir_instr *instr, ppir_node *node) 178bf215546Sopenharmony_ci{ 179bf215546Sopenharmony_ci if (node->op == ppir_op_const) { 180bf215546Sopenharmony_ci int i; 181bf215546Sopenharmony_ci ppir_const_node *c = ppir_node_to_const(node); 182bf215546Sopenharmony_ci const ppir_const *nc = &c->constant; 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_ci for (i = 0; i < 2; i++) { 185bf215546Sopenharmony_ci ppir_const ic = instr->constant[i]; 186bf215546Sopenharmony_ci uint8_t swizzle[4] = {0}; 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci if (ppir_instr_insert_const(&ic, nc, swizzle)) { 189bf215546Sopenharmony_ci instr->constant[i] = ic; 190bf215546Sopenharmony_ci ppir_node *succ = ppir_node_first_succ(node); 191bf215546Sopenharmony_ci for (int s = 0; s < ppir_node_get_src_num(succ); s++) { 192bf215546Sopenharmony_ci ppir_src *src = ppir_node_get_src(succ, s); 193bf215546Sopenharmony_ci assert(src); 194bf215546Sopenharmony_ci if (src->node != node) 195bf215546Sopenharmony_ci continue; 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci ppir_update_src_pipeline(ppir_pipeline_reg_const0 + i, src, 198bf215546Sopenharmony_ci &c->dest, swizzle); 199bf215546Sopenharmony_ci } 200bf215546Sopenharmony_ci break; 201bf215546Sopenharmony_ci } 202bf215546Sopenharmony_ci } 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci /* no const slot can insert */ 205bf215546Sopenharmony_ci if (i == 2) 206bf215546Sopenharmony_ci return false; 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci return true; 209bf215546Sopenharmony_ci } 210bf215546Sopenharmony_ci else { 211bf215546Sopenharmony_ci int *slots = ppir_op_infos[node->op].slots; 212bf215546Sopenharmony_ci for (int i = 0; slots[i] != PPIR_INSTR_SLOT_END; i++) { 213bf215546Sopenharmony_ci int pos = slots[i]; 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci if (instr->slots[pos]) { 216bf215546Sopenharmony_ci /* node already in this instr, i.e. load_uniform */ 217bf215546Sopenharmony_ci if (instr->slots[pos] == node) 218bf215546Sopenharmony_ci return true; 219bf215546Sopenharmony_ci else 220bf215546Sopenharmony_ci continue; 221bf215546Sopenharmony_ci } 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci /* ^fmul dests (e.g. condition for select) can only be 224bf215546Sopenharmony_ci * scheduled to ALU_SCL_MUL */ 225bf215546Sopenharmony_ci if (pos == PPIR_INSTR_SLOT_ALU_SCL_ADD) { 226bf215546Sopenharmony_ci ppir_dest *dest = ppir_node_get_dest(node); 227bf215546Sopenharmony_ci if (dest && dest->type == ppir_target_pipeline && 228bf215546Sopenharmony_ci dest->pipeline == ppir_pipeline_reg_fmul) 229bf215546Sopenharmony_ci continue; 230bf215546Sopenharmony_ci } 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci if (pos == PPIR_INSTR_SLOT_ALU_SCL_MUL || 233bf215546Sopenharmony_ci pos == PPIR_INSTR_SLOT_ALU_SCL_ADD) { 234bf215546Sopenharmony_ci ppir_dest *dest = ppir_node_get_dest(node); 235bf215546Sopenharmony_ci if (!ppir_target_is_scalar(dest)) 236bf215546Sopenharmony_ci continue; 237bf215546Sopenharmony_ci } 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_ci instr->slots[pos] = node; 240bf215546Sopenharmony_ci node->instr = instr; 241bf215546Sopenharmony_ci node->instr_pos = pos; 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci if ((node->op == ppir_op_load_uniform) || (node->op == ppir_op_load_temp)) { 244bf215546Sopenharmony_ci ppir_load_node *l = ppir_node_to_load(node); 245bf215546Sopenharmony_ci ppir_instr_update_src_pipeline( 246bf215546Sopenharmony_ci instr, ppir_pipeline_reg_uniform, &l->dest, NULL); 247bf215546Sopenharmony_ci } 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_ci return true; 250bf215546Sopenharmony_ci } 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_ci return false; 253bf215546Sopenharmony_ci } 254bf215546Sopenharmony_ci} 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_cistatic struct { 257bf215546Sopenharmony_ci int len; 258bf215546Sopenharmony_ci char *name; 259bf215546Sopenharmony_ci} ppir_instr_fields[] = { 260bf215546Sopenharmony_ci [PPIR_INSTR_SLOT_VARYING] = { 4, "vary" }, 261bf215546Sopenharmony_ci [PPIR_INSTR_SLOT_TEXLD] = { 4, "texl"}, 262bf215546Sopenharmony_ci [PPIR_INSTR_SLOT_UNIFORM] = { 4, "unif" }, 263bf215546Sopenharmony_ci [PPIR_INSTR_SLOT_ALU_VEC_MUL] = { 4, "vmul" }, 264bf215546Sopenharmony_ci [PPIR_INSTR_SLOT_ALU_SCL_MUL] = { 4, "smul" }, 265bf215546Sopenharmony_ci [PPIR_INSTR_SLOT_ALU_VEC_ADD] = { 4, "vadd" }, 266bf215546Sopenharmony_ci [PPIR_INSTR_SLOT_ALU_SCL_ADD] = { 4, "sadd" }, 267bf215546Sopenharmony_ci [PPIR_INSTR_SLOT_ALU_COMBINE] = { 4, "comb" }, 268bf215546Sopenharmony_ci [PPIR_INSTR_SLOT_STORE_TEMP] = { 4, "stor" }, 269bf215546Sopenharmony_ci [PPIR_INSTR_SLOT_BRANCH] = { 4, "brch" }, 270bf215546Sopenharmony_ci}; 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_civoid ppir_instr_print_list(ppir_compiler *comp) 273bf215546Sopenharmony_ci{ 274bf215546Sopenharmony_ci if (!(lima_debug & LIMA_DEBUG_PP)) 275bf215546Sopenharmony_ci return; 276bf215546Sopenharmony_ci 277bf215546Sopenharmony_ci printf("======ppir instr list======\n"); 278bf215546Sopenharmony_ci printf(" "); 279bf215546Sopenharmony_ci for (int i = 0; i < PPIR_INSTR_SLOT_NUM; i++) 280bf215546Sopenharmony_ci printf("%-*s ", ppir_instr_fields[i].len, ppir_instr_fields[i].name); 281bf215546Sopenharmony_ci printf("const0|1\n"); 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci list_for_each_entry(ppir_block, block, &comp->block_list, list) { 284bf215546Sopenharmony_ci printf("-------block %3d-------\n", block->index); 285bf215546Sopenharmony_ci list_for_each_entry(ppir_instr, instr, &block->instr_list, list) { 286bf215546Sopenharmony_ci printf("%c%03d: ", instr->stop ? '*' : ' ', instr->index); 287bf215546Sopenharmony_ci for (int i = 0; i < PPIR_INSTR_SLOT_NUM; i++) { 288bf215546Sopenharmony_ci ppir_node *node = instr->slots[i]; 289bf215546Sopenharmony_ci if (node) 290bf215546Sopenharmony_ci printf("%-*d ", ppir_instr_fields[i].len, node->index); 291bf215546Sopenharmony_ci else 292bf215546Sopenharmony_ci printf("%-*s ", ppir_instr_fields[i].len, "null"); 293bf215546Sopenharmony_ci } 294bf215546Sopenharmony_ci for (int i = 0; i < 2; i++) { 295bf215546Sopenharmony_ci if (i) 296bf215546Sopenharmony_ci printf("| "); 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci for (int j = 0; j < instr->constant[i].num; j++) 299bf215546Sopenharmony_ci printf("%f ", instr->constant[i].value[j].f); 300bf215546Sopenharmony_ci } 301bf215546Sopenharmony_ci printf("\n"); 302bf215546Sopenharmony_ci } 303bf215546Sopenharmony_ci } 304bf215546Sopenharmony_ci printf("===========================\n"); 305bf215546Sopenharmony_ci} 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_cistatic void ppir_instr_print_sub(ppir_instr *instr) 308bf215546Sopenharmony_ci{ 309bf215546Sopenharmony_ci printf("[%s%d", 310bf215546Sopenharmony_ci instr->printed && !ppir_instr_is_leaf(instr) ? "+" : "", 311bf215546Sopenharmony_ci instr->index); 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_ci if (!instr->printed) { 314bf215546Sopenharmony_ci ppir_instr_foreach_pred(instr, dep) { 315bf215546Sopenharmony_ci ppir_instr_print_sub(dep->pred); 316bf215546Sopenharmony_ci } 317bf215546Sopenharmony_ci 318bf215546Sopenharmony_ci instr->printed = true; 319bf215546Sopenharmony_ci } 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci printf("]"); 322bf215546Sopenharmony_ci} 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_civoid ppir_instr_print_dep(ppir_compiler *comp) 325bf215546Sopenharmony_ci{ 326bf215546Sopenharmony_ci if (!(lima_debug & LIMA_DEBUG_PP)) 327bf215546Sopenharmony_ci return; 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_ci list_for_each_entry(ppir_block, block, &comp->block_list, list) { 330bf215546Sopenharmony_ci list_for_each_entry(ppir_instr, instr, &block->instr_list, list) { 331bf215546Sopenharmony_ci instr->printed = false; 332bf215546Sopenharmony_ci } 333bf215546Sopenharmony_ci } 334bf215546Sopenharmony_ci 335bf215546Sopenharmony_ci printf("======ppir instr depend======\n"); 336bf215546Sopenharmony_ci list_for_each_entry(ppir_block, block, &comp->block_list, list) { 337bf215546Sopenharmony_ci printf("-------block %3d-------\n", block->index); 338bf215546Sopenharmony_ci list_for_each_entry(ppir_instr, instr, &block->instr_list, list) { 339bf215546Sopenharmony_ci if (ppir_instr_is_root(instr)) { 340bf215546Sopenharmony_ci ppir_instr_print_sub(instr); 341bf215546Sopenharmony_ci printf("\n"); 342bf215546Sopenharmony_ci } 343bf215546Sopenharmony_ci } 344bf215546Sopenharmony_ci } 345bf215546Sopenharmony_ci printf("=============================\n"); 346bf215546Sopenharmony_ci} 347