"Fossies" - the Fresh Open Source Software Archive

Member "mesa-20.1.8/src/gallium/drivers/lima/ir/gp/codegen.c" (16 Sep 2020, 19546 Bytes) of package /linux/misc/mesa-20.1.8.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "codegen.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 20.1.5_vs_20.2.0-rc1.

    1 /*
    2  * Copyright (c) 2017 Lima Project
    3  *
    4  * Permission is hereby granted, free of charge, to any person obtaining a
    5  * copy of this software and associated documentation files (the "Software"),
    6  * to deal in the Software without restriction, including without limitation
    7  * the rights to use, copy, modify, merge, publish, distribute, sub license,
    8  * and/or sell copies of the Software, and to permit persons to whom the
    9  * Software is furnished to do so, subject to the following conditions:
   10  *
   11  * The above copyright notice and this permission notice (including the
   12  * next paragraph) shall be included in all copies or substantial portions
   13  * of the Software.
   14  *
   15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
   18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   21  * DEALINGS IN THE SOFTWARE.
   22  *
   23  */
   24 
   25 #include "util/ralloc.h"
   26 
   27 #include "gpir.h"
   28 #include "codegen.h"
   29 #include "lima_context.h"
   30 
   31 static gpir_codegen_src gpir_get_alu_input(gpir_node *parent, gpir_node *child)
   32 {
   33    static const int slot_to_src[GPIR_INSTR_SLOT_NUM][3] = {
   34       [GPIR_INSTR_SLOT_MUL0] = {
   35          gpir_codegen_src_unused, gpir_codegen_src_p1_mul_0, gpir_codegen_src_p2_mul_0 },
   36       [GPIR_INSTR_SLOT_MUL1] = {
   37          gpir_codegen_src_unused, gpir_codegen_src_p1_mul_1, gpir_codegen_src_p2_mul_1 },
   38 
   39       [GPIR_INSTR_SLOT_ADD0] = {
   40          gpir_codegen_src_unused, gpir_codegen_src_p1_acc_0, gpir_codegen_src_p2_acc_0 },
   41       [GPIR_INSTR_SLOT_ADD1] = {
   42          gpir_codegen_src_unused, gpir_codegen_src_p1_acc_1, gpir_codegen_src_p2_acc_1 },
   43 
   44       [GPIR_INSTR_SLOT_COMPLEX] = {
   45          gpir_codegen_src_unused, gpir_codegen_src_p1_complex, gpir_codegen_src_unused },
   46       [GPIR_INSTR_SLOT_PASS] = {
   47          gpir_codegen_src_unused, gpir_codegen_src_p1_pass, gpir_codegen_src_p2_pass },
   48 
   49       [GPIR_INSTR_SLOT_REG0_LOAD0] = {
   50          gpir_codegen_src_attrib_x, gpir_codegen_src_p1_attrib_x, gpir_codegen_src_unused },
   51       [GPIR_INSTR_SLOT_REG0_LOAD1] = {
   52          gpir_codegen_src_attrib_y, gpir_codegen_src_p1_attrib_y, gpir_codegen_src_unused },
   53       [GPIR_INSTR_SLOT_REG0_LOAD2] = {
   54          gpir_codegen_src_attrib_z, gpir_codegen_src_p1_attrib_z, gpir_codegen_src_unused },
   55       [GPIR_INSTR_SLOT_REG0_LOAD3] = {
   56          gpir_codegen_src_attrib_w, gpir_codegen_src_p1_attrib_w, gpir_codegen_src_unused },
   57 
   58       [GPIR_INSTR_SLOT_REG1_LOAD0] = {
   59          gpir_codegen_src_register_x, gpir_codegen_src_unused, gpir_codegen_src_unused},
   60       [GPIR_INSTR_SLOT_REG1_LOAD1] = {
   61          gpir_codegen_src_register_y, gpir_codegen_src_unused, gpir_codegen_src_unused},
   62       [GPIR_INSTR_SLOT_REG1_LOAD2] = {
   63          gpir_codegen_src_register_z, gpir_codegen_src_unused, gpir_codegen_src_unused},
   64       [GPIR_INSTR_SLOT_REG1_LOAD3] = {
   65          gpir_codegen_src_register_w, gpir_codegen_src_unused, gpir_codegen_src_unused},
   66 
   67       [GPIR_INSTR_SLOT_MEM_LOAD0] = {
   68          gpir_codegen_src_load_x, gpir_codegen_src_unused, gpir_codegen_src_unused },
   69       [GPIR_INSTR_SLOT_MEM_LOAD1] = {
   70          gpir_codegen_src_load_y, gpir_codegen_src_unused, gpir_codegen_src_unused },
   71       [GPIR_INSTR_SLOT_MEM_LOAD2] = {
   72          gpir_codegen_src_load_z, gpir_codegen_src_unused, gpir_codegen_src_unused },
   73       [GPIR_INSTR_SLOT_MEM_LOAD3] = {
   74          gpir_codegen_src_load_w, gpir_codegen_src_unused, gpir_codegen_src_unused },
   75    };
   76 
   77    int diff = child->sched.instr->index - parent->sched.instr->index;
   78    assert(diff < 3);
   79    assert(diff >= 0);
   80 
   81    int src = slot_to_src[child->sched.pos][diff];
   82    assert(src != gpir_codegen_src_unused);
   83    return src;
   84 }
   85 
   86 static void gpir_codegen_mul0_slot(gpir_codegen_instr *code, gpir_instr *instr)
   87 {
   88    gpir_node *node = instr->slots[GPIR_INSTR_SLOT_MUL0];
   89 
   90    if (!node) {
   91       code->mul0_src0 = gpir_codegen_src_unused;
   92       code->mul0_src1 = gpir_codegen_src_unused;
   93       return;
   94    }
   95 
   96    gpir_alu_node *alu = gpir_node_to_alu(node);
   97 
   98    switch (node->op) {
   99    case gpir_op_mul:
  100       code->mul0_src0 = gpir_get_alu_input(node, alu->children[0]);
  101       code->mul0_src1 = gpir_get_alu_input(node, alu->children[1]);
  102       if (code->mul0_src1 == gpir_codegen_src_p1_complex) {
  103          /* Will get confused with gpir_codegen_src_ident, so need to swap inputs */
  104          code->mul0_src1 = code->mul0_src0;
  105          code->mul0_src0 = gpir_codegen_src_p1_complex;
  106       }
  107 
  108       code->mul0_neg = alu->dest_negate;
  109       if (alu->children_negate[0])
  110          code->mul0_neg = !code->mul0_neg;
  111       if (alu->children_negate[1])
  112          code->mul0_neg = !code->mul0_neg;
  113       break;
  114 
  115    case gpir_op_neg:
  116       code->mul0_neg = true;
  117    case gpir_op_mov:
  118       code->mul0_src0 = gpir_get_alu_input(node, alu->children[0]);
  119       code->mul0_src1 = gpir_codegen_src_ident;
  120       break;
  121 
  122    case gpir_op_complex1:
  123       code->mul0_src0 = gpir_get_alu_input(node, alu->children[0]);
  124       code->mul0_src1 = gpir_get_alu_input(node, alu->children[1]);
  125       code->mul_op = gpir_codegen_mul_op_complex1;
  126       break;
  127 
  128    case gpir_op_complex2:
  129       code->mul0_src0 = gpir_get_alu_input(node, alu->children[0]);
  130       code->mul0_src1 = code->mul0_src0;
  131       code->mul_op = gpir_codegen_mul_op_complex2;
  132       break;
  133 
  134    case gpir_op_select:
  135       code->mul0_src0 = gpir_get_alu_input(node, alu->children[2]);
  136       code->mul0_src1 = gpir_get_alu_input(node, alu->children[0]);
  137       code->mul_op = gpir_codegen_mul_op_select;
  138       break;
  139 
  140    default:
  141       assert(0);
  142    }
  143 }
  144 
  145 static void gpir_codegen_mul1_slot(gpir_codegen_instr *code, gpir_instr *instr)
  146 {
  147    gpir_node *node = instr->slots[GPIR_INSTR_SLOT_MUL1];
  148 
  149    if (!node) {
  150       code->mul1_src0 = gpir_codegen_src_unused;
  151       code->mul1_src1 = gpir_codegen_src_unused;
  152       return;
  153    }
  154 
  155    gpir_alu_node *alu = gpir_node_to_alu(node);
  156 
  157    switch (node->op) {
  158    case gpir_op_mul:
  159       code->mul1_src0 = gpir_get_alu_input(node, alu->children[0]);
  160       code->mul1_src1 = gpir_get_alu_input(node, alu->children[1]);
  161       if (code->mul1_src1 == gpir_codegen_src_p1_complex) {
  162          /* Will get confused with gpir_codegen_src_ident, so need to swap inputs */
  163          code->mul1_src1 = code->mul1_src0;
  164          code->mul1_src0 = gpir_codegen_src_p1_complex;
  165       }
  166 
  167       code->mul1_neg = alu->dest_negate;
  168       if (alu->children_negate[0])
  169          code->mul1_neg = !code->mul1_neg;
  170       if (alu->children_negate[1])
  171          code->mul1_neg = !code->mul1_neg;
  172       break;
  173 
  174    case gpir_op_neg:
  175       code->mul1_neg = true;
  176    case gpir_op_mov:
  177       code->mul1_src0 = gpir_get_alu_input(node, alu->children[0]);
  178       code->mul1_src1 = gpir_codegen_src_ident;
  179       break;
  180 
  181    case gpir_op_complex1:
  182       code->mul1_src0 = gpir_get_alu_input(node, alu->children[0]);
  183       code->mul1_src1 = gpir_get_alu_input(node, alu->children[2]);
  184       break;
  185 
  186    case gpir_op_select:
  187       code->mul1_src0 = gpir_get_alu_input(node, alu->children[1]);
  188       code->mul1_src1 = gpir_codegen_src_unused;
  189       break;
  190 
  191    default:
  192       assert(0);
  193    }
  194 }
  195 
  196 static void gpir_codegen_add0_slot(gpir_codegen_instr *code, gpir_instr *instr)
  197 {
  198    gpir_node *node = instr->slots[GPIR_INSTR_SLOT_ADD0];
  199 
  200    if (!node) {
  201       code->acc0_src0 = gpir_codegen_src_unused;
  202       code->acc0_src1 = gpir_codegen_src_unused;
  203       return;
  204    }
  205 
  206    gpir_alu_node *alu = gpir_node_to_alu(node);
  207 
  208    switch (node->op) {
  209    case gpir_op_add:
  210    case gpir_op_min:
  211    case gpir_op_max:
  212    case gpir_op_lt:
  213    case gpir_op_ge:
  214       code->acc0_src0 = gpir_get_alu_input(node, alu->children[0]);
  215       code->acc0_src1 = gpir_get_alu_input(node, alu->children[1]);
  216 
  217       code->acc0_src0_neg = alu->children_negate[0];
  218       code->acc0_src1_neg = alu->children_negate[1];
  219 
  220       switch (node->op) {
  221       case gpir_op_add:
  222          code->acc_op = gpir_codegen_acc_op_add;
  223          if (code->acc0_src1 == gpir_codegen_src_p1_complex) {
  224             code->acc0_src1 = code->acc0_src0;
  225             code->acc0_src0 = gpir_codegen_src_p1_complex;
  226 
  227             bool tmp = code->acc0_src0_neg;
  228             code->acc0_src0_neg = code->acc0_src1_neg;
  229             code->acc0_src1_neg = tmp;
  230          }
  231          break;
  232       case gpir_op_min:
  233          code->acc_op = gpir_codegen_acc_op_min;
  234          break;
  235       case gpir_op_max:
  236          code->acc_op = gpir_codegen_acc_op_max;
  237          break;
  238       case gpir_op_lt:
  239          code->acc_op = gpir_codegen_acc_op_lt;
  240          break;
  241       case gpir_op_ge:
  242          code->acc_op = gpir_codegen_acc_op_ge;
  243          break;
  244       default:
  245          assert(0);
  246       }
  247 
  248       break;
  249 
  250    case gpir_op_floor:
  251    case gpir_op_sign:
  252       code->acc0_src0 = gpir_get_alu_input(node, alu->children[0]);
  253       code->acc0_src0_neg = alu->children_negate[0];
  254       switch (node->op) {
  255       case gpir_op_floor:
  256          code->acc_op = gpir_codegen_acc_op_floor;
  257          break;
  258       case gpir_op_sign:
  259          code->acc_op = gpir_codegen_acc_op_sign;
  260          break;
  261       default:
  262          assert(0);
  263       }
  264       break;
  265 
  266    case gpir_op_neg:
  267       code->acc0_src0_neg = true;
  268    case gpir_op_mov:
  269       code->acc_op = gpir_codegen_acc_op_add;
  270       code->acc0_src0 = gpir_get_alu_input(node, alu->children[0]);
  271       code->acc0_src1 = gpir_codegen_src_ident;
  272       code->acc0_src1_neg = true;
  273       break;
  274 
  275    default:
  276       assert(0);
  277    }
  278 }
  279 
  280 static void gpir_codegen_add1_slot(gpir_codegen_instr *code, gpir_instr *instr)
  281 {
  282    gpir_node *node = instr->slots[GPIR_INSTR_SLOT_ADD1];
  283 
  284    if (!node) {
  285       code->acc1_src0 = gpir_codegen_src_unused;
  286       code->acc1_src1 = gpir_codegen_src_unused;
  287       return;
  288    }
  289 
  290    gpir_alu_node *alu = gpir_node_to_alu(node);
  291 
  292    switch (node->op) {
  293    case gpir_op_add:
  294    case gpir_op_min:
  295    case gpir_op_max:
  296    case gpir_op_lt:
  297    case gpir_op_ge:
  298       code->acc1_src0 = gpir_get_alu_input(node, alu->children[0]);
  299       code->acc1_src1 = gpir_get_alu_input(node, alu->children[1]);
  300 
  301       code->acc1_src0_neg = alu->children_negate[0];
  302       code->acc1_src1_neg = alu->children_negate[1];
  303 
  304       switch (node->op) {
  305       case gpir_op_add:
  306          code->acc_op = gpir_codegen_acc_op_add;
  307          if (code->acc1_src1 == gpir_codegen_src_p1_complex) {
  308             code->acc1_src1 = code->acc1_src0;
  309             code->acc1_src0 = gpir_codegen_src_p1_complex;
  310 
  311             bool tmp = code->acc1_src0_neg;
  312             code->acc1_src0_neg = code->acc1_src1_neg;
  313             code->acc1_src1_neg = tmp;
  314          }
  315          break;
  316       case gpir_op_min:
  317          code->acc_op = gpir_codegen_acc_op_min;
  318          break;
  319       case gpir_op_max:
  320          code->acc_op = gpir_codegen_acc_op_max;
  321          break;
  322       case gpir_op_lt:
  323          code->acc_op = gpir_codegen_acc_op_lt;
  324          break;
  325       case gpir_op_ge:
  326          code->acc_op = gpir_codegen_acc_op_ge;
  327          break;
  328       default:
  329          assert(0);
  330       }
  331 
  332       break;
  333 
  334    case gpir_op_floor:
  335    case gpir_op_sign:
  336       code->acc1_src0 = gpir_get_alu_input(node, alu->children[0]);
  337       code->acc1_src0_neg = alu->children_negate[0];
  338       switch (node->op) {
  339       case gpir_op_floor:
  340          code->acc_op = gpir_codegen_acc_op_floor;
  341          break;
  342       case gpir_op_sign:
  343          code->acc_op = gpir_codegen_acc_op_sign;
  344          break;
  345       default:
  346          assert(0);
  347       }
  348       break;
  349 
  350    case gpir_op_neg:
  351       code->acc1_src0_neg = true;
  352    case gpir_op_mov:
  353       code->acc_op = gpir_codegen_acc_op_add;
  354       code->acc1_src0 = gpir_get_alu_input(node, alu->children[0]);
  355       code->acc1_src1 = gpir_codegen_src_ident;
  356       code->acc1_src1_neg = true;
  357       break;
  358 
  359    default:
  360       assert(0);
  361    }
  362 }
  363 
  364 static void gpir_codegen_complex_slot(gpir_codegen_instr *code, gpir_instr *instr)
  365 {
  366    gpir_node *node = instr->slots[GPIR_INSTR_SLOT_COMPLEX];
  367 
  368    if (!node) {
  369       code->complex_src = gpir_codegen_src_unused;
  370       return;
  371    }
  372 
  373    switch (node->op) {
  374    case gpir_op_mov:
  375    case gpir_op_rcp_impl:
  376    case gpir_op_rsqrt_impl:
  377    case gpir_op_exp2_impl:
  378    case gpir_op_log2_impl:
  379    {
  380       gpir_alu_node *alu = gpir_node_to_alu(node);
  381       code->complex_src = gpir_get_alu_input(node, alu->children[0]);
  382       break;
  383    }
  384    default:
  385       assert(0);
  386    }
  387 
  388    switch (node->op) {
  389    case gpir_op_mov:
  390       code->complex_op = gpir_codegen_complex_op_pass;
  391       break;
  392    case gpir_op_rcp_impl:
  393       code->complex_op = gpir_codegen_complex_op_rcp;
  394       break;
  395    case gpir_op_rsqrt_impl:
  396       code->complex_op = gpir_codegen_complex_op_rsqrt;
  397       break;
  398    case gpir_op_exp2_impl:
  399       code->complex_op = gpir_codegen_complex_op_exp2;
  400       break;
  401    case gpir_op_log2_impl:
  402       code->complex_op = gpir_codegen_complex_op_log2;
  403       break;
  404    default:
  405       assert(0);
  406    }
  407 }
  408 
  409 static void gpir_codegen_pass_slot(gpir_codegen_instr *code, gpir_instr *instr)
  410 {
  411    gpir_node *node = instr->slots[GPIR_INSTR_SLOT_PASS];
  412 
  413    if (!node) {
  414       code->pass_op = gpir_codegen_pass_op_pass;
  415       code->pass_src = gpir_codegen_src_unused;
  416       return;
  417    }
  418 
  419    if (node->op == gpir_op_branch_cond) {
  420       gpir_branch_node *branch = gpir_node_to_branch(node);
  421 
  422       code->pass_op = gpir_codegen_pass_op_pass;
  423       code->pass_src = gpir_get_alu_input(node, branch->cond);
  424 
  425       /* Fill out branch information */
  426       unsigned offset = branch->dest->instr_offset;
  427       assert(offset < 0x200);
  428       code->branch = true;
  429       code->branch_target = offset & 0xff;
  430       code->branch_target_lo = !(offset >> 8);
  431       code->unknown_1 = 13;
  432       return;
  433    }
  434 
  435    gpir_alu_node *alu = gpir_node_to_alu(node);
  436    code->pass_src = gpir_get_alu_input(node, alu->children[0]);
  437 
  438    switch (node->op) {
  439    case gpir_op_mov:
  440       code->pass_op = gpir_codegen_pass_op_pass;
  441       break;
  442    case gpir_op_preexp2:
  443       code->pass_op = gpir_codegen_pass_op_preexp2;
  444       break;
  445    case gpir_op_postlog2:
  446       code->pass_op = gpir_codegen_pass_op_postlog2;
  447       break;
  448    default:
  449       assert(0);
  450    }
  451 
  452 }
  453 
  454 static void gpir_codegen_reg0_slot(gpir_codegen_instr *code, gpir_instr *instr)
  455 {
  456    if (!instr->reg0_use_count)
  457       return;
  458 
  459    code->register0_attribute = instr->reg0_is_attr;
  460    code->register0_addr = instr->reg0_index;
  461 }
  462 
  463 static void gpir_codegen_reg1_slot(gpir_codegen_instr *code, gpir_instr *instr)
  464 {
  465    if (!instr->reg1_use_count)
  466       return;
  467 
  468    code->register1_addr = instr->reg1_index;
  469 }
  470 
  471 static void gpir_codegen_mem_slot(gpir_codegen_instr *code, gpir_instr *instr)
  472 {
  473    if (!instr->mem_use_count) {
  474       code->load_offset = gpir_codegen_load_off_none;
  475       return;
  476    }
  477 
  478    code->load_addr = instr->mem_index;
  479    code->load_offset = gpir_codegen_load_off_none;
  480 }
  481 
  482 static gpir_codegen_store_src gpir_get_store_input(gpir_node *node)
  483 {
  484    static int slot_to_src[GPIR_INSTR_SLOT_NUM] = {
  485       [GPIR_INSTR_SLOT_MUL0] = gpir_codegen_store_src_mul_0,
  486       [GPIR_INSTR_SLOT_MUL1] = gpir_codegen_store_src_mul_1,
  487       [GPIR_INSTR_SLOT_ADD0] = gpir_codegen_store_src_acc_0,
  488       [GPIR_INSTR_SLOT_ADD1] = gpir_codegen_store_src_acc_1,
  489       [GPIR_INSTR_SLOT_COMPLEX] = gpir_codegen_store_src_complex,
  490       [GPIR_INSTR_SLOT_PASS] = gpir_codegen_store_src_pass,
  491       [GPIR_INSTR_SLOT_REG0_LOAD0...GPIR_INSTR_SLOT_STORE3] = gpir_codegen_store_src_none,
  492    };
  493 
  494    gpir_store_node *store = gpir_node_to_store(node);
  495    return slot_to_src[store->child->sched.pos];
  496 }
  497 
  498 static void gpir_codegen_store_slot(gpir_codegen_instr *code, gpir_instr *instr)
  499 {
  500 
  501    gpir_node *node = instr->slots[GPIR_INSTR_SLOT_STORE0];
  502    if (node)
  503       code->store0_src_x = gpir_get_store_input(node);
  504    else
  505       code->store0_src_x = gpir_codegen_store_src_none;
  506 
  507    node = instr->slots[GPIR_INSTR_SLOT_STORE1];
  508    if (node)
  509       code->store0_src_y = gpir_get_store_input(node);
  510    else
  511       code->store0_src_y = gpir_codegen_store_src_none;
  512 
  513    node = instr->slots[GPIR_INSTR_SLOT_STORE2];
  514    if (node)
  515       code->store1_src_z = gpir_get_store_input(node);
  516    else
  517       code->store1_src_z = gpir_codegen_store_src_none;
  518 
  519    node = instr->slots[GPIR_INSTR_SLOT_STORE3];
  520    if (node)
  521       code->store1_src_w = gpir_get_store_input(node);
  522    else
  523       code->store1_src_w = gpir_codegen_store_src_none;
  524 
  525    if (instr->store_content[0] == GPIR_INSTR_STORE_TEMP) {
  526       code->store0_temporary = true;
  527       code->unknown_1 = 12;
  528    }
  529    else {
  530       code->store0_varying = instr->store_content[0] == GPIR_INSTR_STORE_VARYING;
  531       code->store0_addr = instr->store_index[0];
  532    }
  533 
  534    if (instr->store_content[1] == GPIR_INSTR_STORE_TEMP) {
  535       code->store1_temporary = true;
  536       code->unknown_1 = 12;
  537    }
  538    else {
  539       code->store1_varying = instr->store_content[1] == GPIR_INSTR_STORE_VARYING;
  540       code->store1_addr = instr->store_index[1];
  541    }
  542 }
  543 
  544 static void gpir_codegen(gpir_codegen_instr *code, gpir_instr *instr)
  545 {
  546    gpir_codegen_mul0_slot(code, instr);
  547    gpir_codegen_mul1_slot(code, instr);
  548 
  549    gpir_codegen_add0_slot(code, instr);
  550    gpir_codegen_add1_slot(code, instr);
  551 
  552    gpir_codegen_complex_slot(code, instr);
  553    gpir_codegen_pass_slot(code, instr);
  554 
  555    gpir_codegen_reg0_slot(code, instr);
  556    gpir_codegen_reg1_slot(code, instr);
  557    gpir_codegen_mem_slot(code, instr);
  558 
  559    gpir_codegen_store_slot(code, instr);
  560 }
  561 
  562 static void gpir_codegen_print_prog(gpir_compiler *comp)
  563 {
  564    uint32_t *data = comp->prog->shader;
  565    int num_dword_per_instr = sizeof(gpir_codegen_instr) / sizeof(uint32_t);
  566 
  567    for (int i = 0; i < comp->num_instr; i++) {
  568       printf("%03d: ", i);
  569       for (int j = 0; j < num_dword_per_instr; j++)
  570          printf("%08x ", data[i * num_dword_per_instr + j]);
  571       printf("\n");
  572    }
  573 }
  574 
  575 bool gpir_codegen_prog(gpir_compiler *comp)
  576 {
  577    int num_instr = 0;
  578    list_for_each_entry(gpir_block, block, &comp->block_list, list) {
  579       block->instr_offset = num_instr;
  580       num_instr += list_length(&block->instr_list);
  581    }
  582 
  583    assert(num_instr <= 512);
  584 
  585    gpir_codegen_instr *code = rzalloc_array(comp->prog, gpir_codegen_instr, num_instr);
  586    if (!code)
  587       return false;
  588 
  589    int instr_index = 0;
  590    list_for_each_entry(gpir_block, block, &comp->block_list, list) {
  591       list_for_each_entry(gpir_instr, instr, &block->instr_list, list) {
  592          gpir_codegen(code + instr_index, instr);
  593          instr_index++;
  594       }
  595    }
  596 
  597    for (int i = 0; i < num_instr; i++) {
  598       if (code[i].register0_attribute)
  599          comp->prog->prefetch = i;
  600    }
  601 
  602    comp->prog->shader = code;
  603    comp->prog->shader_size = num_instr * sizeof(gpir_codegen_instr);
  604 
  605    if (lima_debug & LIMA_DEBUG_GP) {
  606       gpir_codegen_print_prog(comp);
  607       gpir_disassemble_program(code, num_instr);
  608    }
  609 
  610    return true;
  611 }
  612 
  613 static gpir_codegen_acc_op gpir_codegen_get_acc_op(gpir_op op)
  614 {
  615    switch (op) {
  616    case gpir_op_add:
  617    case gpir_op_neg:
  618    case gpir_op_mov:
  619       return gpir_codegen_acc_op_add;
  620    case gpir_op_min:
  621       return gpir_codegen_acc_op_min;
  622    case gpir_op_max:
  623       return gpir_codegen_acc_op_max;
  624    case gpir_op_lt:
  625       return gpir_codegen_acc_op_lt;
  626    case gpir_op_ge:
  627       return gpir_codegen_acc_op_ge;
  628    case gpir_op_floor:
  629       return gpir_codegen_acc_op_floor;
  630    case gpir_op_sign:
  631       return gpir_codegen_acc_op_sign;
  632    default:
  633       assert(0);
  634    }
  635    return -1;
  636 }
  637 
  638 bool gpir_codegen_acc_same_op(gpir_op op1, gpir_op op2)
  639 {
  640    return gpir_codegen_get_acc_op(op1) == gpir_codegen_get_acc_op(op2);
  641 }