"Fossies" - the Fresh Open Source Software Archive

Member "mesa-20.1.8/src/gallium/drivers/lima/ir/pp/lower.c" (16 Sep 2020, 11059 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 "lower.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/bitscan.h"
   26 #include "util/ralloc.h"
   27 
   28 #include "ppir.h"
   29 
   30 static bool ppir_lower_const(ppir_block *block, ppir_node *node)
   31 {
   32    if (ppir_node_is_root(node)) {
   33       ppir_node_delete(node);
   34       return true;
   35    }
   36 
   37    assert(ppir_node_has_single_succ(node));
   38 
   39    ppir_node *succ = ppir_node_first_succ(node);
   40    ppir_src *src = ppir_node_get_src_for_pred(succ, node);
   41    ppir_dest *dest = ppir_node_get_dest(node);
   42    assert(src != NULL);
   43 
   44    switch (succ->type) {
   45    case ppir_node_type_alu:
   46    case ppir_node_type_branch:
   47       /* ALU and branch can consume consts directly */
   48       dest->type = src->type = ppir_target_pipeline;
   49       /* Reg will be updated in node_to_instr later */
   50       dest->pipeline = src->pipeline = ppir_pipeline_reg_const0;
   51       return true;
   52    default:
   53       /* Create a move for everyone else */
   54       break;
   55    }
   56 
   57    ppir_node *move = ppir_node_insert_mov(node);
   58    if (unlikely(!move))
   59       return false;
   60 
   61    ppir_debug("lower const create move %d for %d\n",
   62               move->index, node->index);
   63 
   64    /* Need to be careful with changing src/dst type here:
   65     * it has to be done *after* successors have their children
   66     * replaced, otherwise ppir_node_replace_child() won't find
   67     * matching src/dst and as result won't work
   68     */
   69    ppir_src *mov_src = ppir_node_get_src(move, 0);
   70    mov_src->type = dest->type = ppir_target_pipeline;
   71    mov_src->pipeline = dest->pipeline = ppir_pipeline_reg_const0;
   72 
   73    return true;
   74 }
   75 
   76 static bool ppir_lower_swap_args(ppir_block *block, ppir_node *node)
   77 {
   78    /* swapped op must be the next op */
   79    node->op++;
   80 
   81    assert(node->type == ppir_node_type_alu);
   82    ppir_alu_node *alu = ppir_node_to_alu(node);
   83    assert(alu->num_src == 2);
   84 
   85    ppir_src tmp = alu->src[0];
   86    alu->src[0] = alu->src[1];
   87    alu->src[1] = tmp;
   88    return true;
   89 }
   90 
   91 static bool ppir_lower_load(ppir_block *block, ppir_node *node)
   92 {
   93    ppir_dest *dest = ppir_node_get_dest(node);
   94    if (ppir_node_is_root(node) && dest->type == ppir_target_ssa) {
   95       ppir_node_delete(node);
   96       return true;
   97    }
   98 
   99    /* load can have multiple successors in case if we duplicated load node
  100     * that has load node in source
  101     */
  102    if ((ppir_node_has_single_src_succ(node) || ppir_node_is_root(node)) &&
  103       dest->type != ppir_target_register) {
  104       ppir_node *succ = ppir_node_first_succ(node);
  105       switch (succ->type) {
  106       case ppir_node_type_alu:
  107       case ppir_node_type_branch: {
  108          ppir_src *src = ppir_node_get_src_for_pred(succ, node);
  109          /* Can consume uniforms directly */
  110          src->type = dest->type = ppir_target_pipeline;
  111          src->pipeline = dest->pipeline = ppir_pipeline_reg_uniform;
  112          return true;
  113       }
  114       default:
  115          /* Create mov for everyone else */
  116          break;
  117       }
  118    }
  119 
  120    ppir_node *move = ppir_node_insert_mov(node);
  121    if (unlikely(!move))
  122       return false;
  123 
  124    ppir_src *mov_src = ppir_node_get_src(move, 0);
  125    mov_src->type = dest->type = ppir_target_pipeline;
  126    mov_src->pipeline = dest->pipeline = ppir_pipeline_reg_uniform;
  127 
  128    return true;
  129 }
  130 
  131 static bool ppir_lower_ddxy(ppir_block *block, ppir_node *node)
  132 {
  133    assert(node->type == ppir_node_type_alu);
  134    ppir_alu_node *alu = ppir_node_to_alu(node);
  135 
  136    alu->src[1] = alu->src[0];
  137    if (node->op == ppir_op_ddx)
  138       alu->src[1].negate = !alu->src[1].negate;
  139    else if (node->op == ppir_op_ddy)
  140       alu->src[0].negate = !alu->src[0].negate;
  141    else
  142       assert(0);
  143 
  144    alu->num_src = 2;
  145 
  146    return true;
  147 }
  148 
  149 static bool ppir_lower_texture(ppir_block *block, ppir_node *node)
  150 {
  151    ppir_load_texture_node *load_tex = ppir_node_to_load_texture(node);
  152    ppir_dest *dest = ppir_node_get_dest(node);
  153    ppir_node *src_coords = ppir_node_get_src(node, 0)->node;
  154    ppir_load_node *load = NULL;
  155 
  156    if (src_coords && ppir_node_has_single_src_succ(src_coords) &&
  157        (src_coords->op == ppir_op_load_coords))
  158       load = ppir_node_to_load(src_coords);
  159    else {
  160       /* Create load_coords node */
  161       load = ppir_node_create(block, ppir_op_load_coords_reg, -1, 0);
  162       if (!load)
  163          return false;
  164       list_addtail(&load->node.list, &node->list);
  165 
  166       load->src = load_tex->src[0];
  167       load->num_src = 1;
  168       if (load_tex->sampler_dim == GLSL_SAMPLER_DIM_CUBE)
  169          load->num_components = 3;
  170       else
  171          load->num_components = 2;
  172 
  173       ppir_debug("%s create load_coords node %d for %d\n",
  174                  __FUNCTION__, load->node.index, node->index);
  175 
  176       ppir_node_foreach_pred_safe(node, dep) {
  177          ppir_node *pred = dep->pred;
  178          ppir_node_remove_dep(dep);
  179          ppir_node_add_dep(&load->node, pred, ppir_dep_src);
  180       }
  181       ppir_node_add_dep(node, &load->node, ppir_dep_src);
  182    }
  183 
  184    assert(load);
  185    load_tex->src[0].type = load->dest.type = ppir_target_pipeline;
  186    load_tex->src[0].pipeline = load->dest.pipeline = ppir_pipeline_reg_discard;
  187 
  188    /* Always create move node since there can be successors in other blocks */
  189    ppir_node *move = ppir_node_insert_mov_all_blocks(node);
  190    if (unlikely(!move))
  191       return false;
  192 
  193    ppir_debug("lower texture create move %d for %d\n",
  194               move->index, node->index);
  195 
  196    ppir_src *mov_src=  ppir_node_get_src(move, 0);
  197    mov_src->type = dest->type = ppir_target_pipeline;
  198    mov_src->pipeline = dest->pipeline = ppir_pipeline_reg_sampler;
  199 
  200    return true;
  201 }
  202 
  203 /* insert a move as the select condition to make sure it can
  204  * be inserted to select instr float mul slot
  205  */
  206 static bool ppir_lower_select(ppir_block *block, ppir_node *node)
  207 {
  208    ppir_alu_node *alu = ppir_node_to_alu(node);
  209 
  210    ppir_node *move = ppir_node_create(block, ppir_op_sel_cond, -1, 0);
  211    if (!move)
  212       return false;
  213    list_addtail(&move->list, &node->list);
  214 
  215    ppir_alu_node *move_alu = ppir_node_to_alu(move);
  216    ppir_src *move_src = move_alu->src, *src = alu->src;
  217    move_src->type = src->type;
  218    move_src->ssa = src->ssa;
  219    move_src->swizzle[0] = src->swizzle[0];
  220    move_alu->num_src = 1;
  221 
  222    ppir_dest *move_dest = &move_alu->dest;
  223    move_dest->type = ppir_target_pipeline;
  224    move_dest->pipeline = ppir_pipeline_reg_fmul;
  225    move_dest->write_mask = 1;
  226 
  227    ppir_node *pred = alu->src[0].node;
  228    ppir_dep *dep = ppir_dep_for_pred(node, pred);
  229    if (dep)
  230       ppir_node_replace_pred(dep, move);
  231    else
  232       ppir_node_add_dep(node, move, ppir_dep_src);
  233 
  234    /* pred can be a register */
  235    if (pred)
  236       ppir_node_add_dep(move, pred, ppir_dep_src);
  237 
  238    src->swizzle[0] = 0;
  239    ppir_node_target_assign(alu->src, move);
  240 
  241    return true;
  242 }
  243 
  244 static bool ppir_lower_trunc(ppir_block *block, ppir_node *node)
  245 {
  246    /* Turn it into a mov with a round to integer output modifier */
  247    ppir_alu_node *alu = ppir_node_to_alu(node);
  248    ppir_dest *move_dest = &alu->dest;
  249    move_dest->modifier = ppir_outmod_round;
  250    node->op = ppir_op_mov;
  251 
  252    return true;
  253 }
  254 
  255 static bool ppir_lower_abs(ppir_block *block, ppir_node *node)
  256 {
  257    /* Turn it into a mov and set the absolute modifier */
  258    ppir_alu_node *alu = ppir_node_to_alu(node);
  259 
  260    assert(alu->num_src == 1);
  261 
  262    alu->src[0].absolute = true;
  263    alu->src[0].negate = false;
  264    node->op = ppir_op_mov;
  265 
  266    return true;
  267 }
  268 
  269 static bool ppir_lower_neg(ppir_block *block, ppir_node *node)
  270 {
  271    /* Turn it into a mov and set the negate modifier */
  272    ppir_alu_node *alu = ppir_node_to_alu(node);
  273 
  274    assert(alu->num_src == 1);
  275 
  276    alu->src[0].negate = !alu->src[0].negate;
  277    node->op = ppir_op_mov;
  278 
  279    return true;
  280 }
  281 
  282 static bool ppir_lower_sat(ppir_block *block, ppir_node *node)
  283 {
  284    /* Turn it into a mov with the saturate output modifier */
  285    ppir_alu_node *alu = ppir_node_to_alu(node);
  286 
  287    assert(alu->num_src == 1);
  288 
  289    ppir_dest *move_dest = &alu->dest;
  290    move_dest->modifier = ppir_outmod_clamp_fraction;
  291    node->op = ppir_op_mov;
  292 
  293    return true;
  294 }
  295 
  296 static bool ppir_lower_branch(ppir_block *block, ppir_node *node)
  297 {
  298    ppir_branch_node *branch = ppir_node_to_branch(node);
  299 
  300    /* Unconditional branch */
  301    if (branch->num_src == 0)
  302       return true;
  303 
  304    ppir_const_node *zero = ppir_node_create(block, ppir_op_const, -1, 0);
  305 
  306    if (!zero)
  307       return false;
  308 
  309    zero->constant.value[0].f = 0;
  310    zero->constant.num = 1;
  311    zero->dest.type = ppir_target_pipeline;
  312    zero->dest.pipeline = ppir_pipeline_reg_const0;
  313    zero->dest.ssa.num_components = 1;
  314    zero->dest.write_mask = 0x01;
  315 
  316    /* For now we're just comparing branch condition with 0,
  317     * in future we should look whether it's possible to move
  318     * comparision node into branch itself and use current
  319     * way as a fallback for complex conditions.
  320     */
  321    ppir_node_target_assign(&branch->src[1], &zero->node);
  322 
  323    if (branch->negate)
  324       branch->cond_eq = true;
  325    else {
  326       branch->cond_gt = true;
  327       branch->cond_lt = true;
  328    }
  329 
  330    branch->num_src = 2;
  331 
  332    ppir_node_add_dep(&branch->node, &zero->node, ppir_dep_src);
  333    list_addtail(&zero->node.list, &node->list);
  334 
  335    return true;
  336 }
  337 
  338 static bool (*ppir_lower_funcs[ppir_op_num])(ppir_block *, ppir_node *) = {
  339    [ppir_op_abs] = ppir_lower_abs,
  340    [ppir_op_neg] = ppir_lower_neg,
  341    [ppir_op_const] = ppir_lower_const,
  342    [ppir_op_ddx] = ppir_lower_ddxy,
  343    [ppir_op_ddy] = ppir_lower_ddxy,
  344    [ppir_op_lt] = ppir_lower_swap_args,
  345    [ppir_op_le] = ppir_lower_swap_args,
  346    [ppir_op_load_texture] = ppir_lower_texture,
  347    [ppir_op_select] = ppir_lower_select,
  348    [ppir_op_trunc] = ppir_lower_trunc,
  349    [ppir_op_sat] = ppir_lower_sat,
  350    [ppir_op_branch] = ppir_lower_branch,
  351    [ppir_op_load_uniform] = ppir_lower_load,
  352    [ppir_op_load_temp] = ppir_lower_load,
  353 };
  354 
  355 bool ppir_lower_prog(ppir_compiler *comp)
  356 {
  357    list_for_each_entry(ppir_block, block, &comp->block_list, list) {
  358       list_for_each_entry_safe(ppir_node, node, &block->node_list, list) {
  359          if (ppir_lower_funcs[node->op] &&
  360              !ppir_lower_funcs[node->op](block, node))
  361             return false;
  362       }
  363    }
  364 
  365    return true;
  366 }