xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/lima/ir/pp/lower.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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 
ppir_lower_const(ppir_block * block,ppir_node * node)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_dest *dest = ppir_node_get_dest(node);
41 
42    switch (succ->type) {
43    case ppir_node_type_alu:
44    case ppir_node_type_branch:
45       /* ALU and branch can consume consts directly */
46       dest->type = ppir_target_pipeline;
47       /* Reg will be updated in node_to_instr later */
48       dest->pipeline = ppir_pipeline_reg_const0;
49 
50       /* single succ can still have multiple references to this node */
51       for (int i = 0; i < ppir_node_get_src_num(succ); i++) {
52          ppir_src *src = ppir_node_get_src(succ, i);
53          if (src && src->node == node) {
54             src->type = ppir_target_pipeline;
55             src->pipeline = ppir_pipeline_reg_const0;
56          }
57       }
58       return true;
59    default:
60       /* Create a move for everyone else */
61       break;
62    }
63 
64    ppir_node *move = ppir_node_insert_mov(node);
65    if (unlikely(!move))
66       return false;
67 
68    ppir_debug("lower const create move %d for %d\n",
69               move->index, node->index);
70 
71    /* Need to be careful with changing src/dst type here:
72     * it has to be done *after* successors have their children
73     * replaced, otherwise ppir_node_replace_child() won't find
74     * matching src/dst and as result won't work
75     */
76    ppir_src *mov_src = ppir_node_get_src(move, 0);
77    mov_src->type = dest->type = ppir_target_pipeline;
78    mov_src->pipeline = dest->pipeline = ppir_pipeline_reg_const0;
79 
80    return true;
81 }
82 
ppir_lower_swap_args(ppir_block * block,ppir_node * node)83 static bool ppir_lower_swap_args(ppir_block *block, ppir_node *node)
84 {
85    /* swapped op must be the next op */
86    node->op++;
87 
88    assert(node->type == ppir_node_type_alu);
89    ppir_alu_node *alu = ppir_node_to_alu(node);
90    assert(alu->num_src == 2);
91 
92    ppir_src tmp = alu->src[0];
93    alu->src[0] = alu->src[1];
94    alu->src[1] = tmp;
95    return true;
96 }
97 
ppir_lower_load(ppir_block * block,ppir_node * node)98 static bool ppir_lower_load(ppir_block *block, ppir_node *node)
99 {
100    ppir_dest *dest = ppir_node_get_dest(node);
101    if (ppir_node_is_root(node) && !node->succ_different_block &&
102        dest->type == ppir_target_ssa) {
103       ppir_node_delete(node);
104       return true;
105    }
106 
107    /* load can have multiple successors in case if we duplicated load node
108     * that has load node in source
109     */
110    if ((ppir_node_has_single_src_succ(node) || ppir_node_is_root(node)) &&
111        !node->succ_different_block &&
112        dest->type != ppir_target_register) {
113       ppir_node *succ = ppir_node_first_succ(node);
114       switch (succ->type) {
115       case ppir_node_type_alu:
116       case ppir_node_type_branch: {
117          /* single succ can still have multiple references to this node */
118          for (int i = 0; i < ppir_node_get_src_num(succ); i++) {
119             ppir_src *src = ppir_node_get_src(succ, i);
120             if (src && src->node == node) {
121                /* Can consume uniforms directly */
122                src->type = dest->type = ppir_target_pipeline;
123                src->pipeline = dest->pipeline = ppir_pipeline_reg_uniform;
124             }
125          }
126          return true;
127       }
128       default:
129          /* Create mov for everyone else */
130          break;
131       }
132    }
133 
134    ppir_node *move = ppir_node_insert_mov(node);
135    if (unlikely(!move))
136       return false;
137 
138    ppir_src *mov_src = ppir_node_get_src(move, 0);
139    mov_src->type = dest->type = ppir_target_pipeline;
140    mov_src->pipeline = dest->pipeline = ppir_pipeline_reg_uniform;
141 
142    return true;
143 }
144 
ppir_lower_ddxy(ppir_block * block,ppir_node * node)145 static bool ppir_lower_ddxy(ppir_block *block, ppir_node *node)
146 {
147    assert(node->type == ppir_node_type_alu);
148    ppir_alu_node *alu = ppir_node_to_alu(node);
149 
150    alu->src[1] = alu->src[0];
151    if (node->op == ppir_op_ddx)
152       alu->src[1].negate = !alu->src[1].negate;
153    else if (node->op == ppir_op_ddy)
154       alu->src[0].negate = !alu->src[0].negate;
155    else
156       assert(0);
157 
158    alu->num_src = 2;
159 
160    return true;
161 }
162 
ppir_lower_texture(ppir_block * block,ppir_node * node)163 static bool ppir_lower_texture(ppir_block *block, ppir_node *node)
164 {
165    ppir_dest *dest = ppir_node_get_dest(node);
166 
167    if (ppir_node_has_single_succ(node) && dest->type == ppir_target_ssa) {
168       ppir_node *succ = ppir_node_first_succ(node);
169       dest->type = ppir_target_pipeline;
170       dest->pipeline = ppir_pipeline_reg_sampler;
171 
172       for (int i = 0; i < ppir_node_get_src_num(succ); i++) {
173          ppir_src *src = ppir_node_get_src(succ, i);
174          if (src && src->node == node) {
175             src->type = ppir_target_pipeline;
176             src->pipeline = ppir_pipeline_reg_sampler;
177          }
178       }
179       return true;
180    }
181 
182    /* Create move node as fallback */
183    ppir_node *move = ppir_node_insert_mov(node);
184    if (unlikely(!move))
185       return false;
186 
187    ppir_debug("lower texture create move %d for %d\n",
188               move->index, node->index);
189 
190    ppir_src *mov_src = ppir_node_get_src(move, 0);
191    mov_src->type = dest->type = ppir_target_pipeline;
192    mov_src->pipeline = dest->pipeline = ppir_pipeline_reg_sampler;
193 
194    return true;
195 }
196 
197 /* Check if the select condition and ensure it can be inserted to
198  * the scalar mul slot */
ppir_lower_select(ppir_block * block,ppir_node * node)199 static bool ppir_lower_select(ppir_block *block, ppir_node *node)
200 {
201    ppir_alu_node *alu = ppir_node_to_alu(node);
202    ppir_src *src0 = &alu->src[0];
203    ppir_src *src1 = &alu->src[1];
204    ppir_src *src2 = &alu->src[2];
205 
206    /* If the condition is already an alu scalar whose only successor
207     * is the select node, just turn it into pipeline output. */
208    /* The (src2->node == cond) case is a tricky exception.
209     * The reason is that we must force cond to output to ^fmul -- but
210     * then it no longer writes to a register and it is impossible to
211     * reference ^fmul in src2. So in that exceptional case, also fall
212     * back to the mov. */
213    ppir_node *cond = src0->node;
214    if (cond &&
215        cond->type == ppir_node_type_alu &&
216        ppir_node_has_single_succ(cond) &&
217        ppir_target_is_scalar(ppir_node_get_dest(cond)) &&
218        ppir_node_schedulable_slot(cond, PPIR_INSTR_SLOT_ALU_SCL_MUL) &&
219        src2->node != cond) {
220 
221       ppir_dest *cond_dest = ppir_node_get_dest(cond);
222       cond_dest->type = ppir_target_pipeline;
223       cond_dest->pipeline = ppir_pipeline_reg_fmul;
224 
225       ppir_node_target_assign(src0, cond);
226 
227       /* src1 could also be a reference from the same node as
228        * the condition, so update it in that case. */
229       if (src1->node && src1->node == cond)
230          ppir_node_target_assign(src1, cond);
231 
232       return true;
233    }
234 
235    /* If the condition can't be used for any reason, insert a mov
236     * so that the condition can end up in ^fmul */
237    ppir_node *move = ppir_node_create(block, ppir_op_mov, -1, 0);
238    if (!move)
239       return false;
240    list_addtail(&move->list, &node->list);
241 
242    ppir_alu_node *move_alu = ppir_node_to_alu(move);
243    ppir_src *move_src = move_alu->src;
244    move_src->type = src0->type;
245    move_src->ssa = src0->ssa;
246    move_src->swizzle[0] = src0->swizzle[0];
247    move_alu->num_src = 1;
248 
249    ppir_dest *move_dest = &move_alu->dest;
250    move_dest->type = ppir_target_pipeline;
251    move_dest->pipeline = ppir_pipeline_reg_fmul;
252    move_dest->write_mask = 1;
253 
254    ppir_node *pred = src0->node;
255    ppir_dep *dep = ppir_dep_for_pred(node, pred);
256    if (dep)
257       ppir_node_replace_pred(dep, move);
258    else
259       ppir_node_add_dep(node, move, ppir_dep_src);
260 
261    /* pred can be a register */
262    if (pred)
263       ppir_node_add_dep(move, pred, ppir_dep_src);
264 
265    ppir_node_target_assign(src0, move);
266 
267    /* src1 could also be a reference from the same node as
268     * the condition, so update it in that case. */
269    if (src1->node && src1->node == pred)
270       ppir_node_target_assign(src1, move);
271 
272    return true;
273 }
274 
ppir_lower_fold_src_mod(ppir_block * block,ppir_node * node)275 static bool ppir_lower_fold_src_mod(ppir_block *block, ppir_node *node)
276 {
277    assert(node->op == ppir_op_neg || node->op == ppir_op_abs);
278 
279    if (ppir_node_is_root(node))
280       return false;
281 
282    if (node->succ_different_block)
283       return false;
284 
285    ppir_dest *dest = ppir_node_get_dest(node);
286    if (dest->type != ppir_target_ssa)
287       return false;
288 
289    ppir_src *mod_src = ppir_node_get_src(node, 0);
290 
291    if (mod_src->type == ppir_target_pipeline &&
292        !ppir_node_has_single_succ(node))
293       return false;
294 
295    ppir_node_foreach_succ_safe(node, dep) {
296       ppir_node *succ = dep->succ;
297       assert(succ);
298 
299       if (succ->type != ppir_node_type_alu)
300          return false;
301    }
302 
303    ppir_node_foreach_succ_safe(node, dep) {
304       ppir_node *succ = dep->succ;
305       assert(succ && succ->type == ppir_node_type_alu);
306 
307       for (int i = 0; i < ppir_node_get_src_num(succ); i++) {
308          ppir_src *src = ppir_node_get_src(succ, i);
309          assert(src);
310 
311          if (src->node != node)
312             continue;
313 
314          uint8_t swizzle[4];
315          for (int j = 0; j < 4; j++)
316             swizzle[j] = mod_src->swizzle[src->swizzle[j]];
317 
318          /* Both src or mod_src may already carry folded modifiers.
319           * Account for those by saving src modifiers and applying
320           * them again afterwards. */
321          bool neg = src->negate;
322          bool abs = src->absolute;
323 
324          *src = *mod_src;
325          if (node->op == ppir_op_neg)
326             src->negate = !src->negate;
327          else /* ppir_op_abs */
328             src->absolute = true;
329 
330          if (neg)
331             src->negate = !src->negate;
332          if (abs)
333             src->absolute = true;
334 
335          memcpy(src->swizzle, swizzle, sizeof(swizzle));
336       }
337 
338       /* insert the succ alu node as successor of the mod src node */
339       ppir_node_foreach_pred_safe(node, dep) {
340          ppir_node *pred = dep->pred;
341          ppir_node_add_dep(succ, pred, ppir_dep_src);
342       }
343    }
344 
345    ppir_node_delete(node);
346    return true;
347 }
348 
ppir_lower_abs(ppir_block * block,ppir_node * node)349 static bool ppir_lower_abs(ppir_block *block, ppir_node *node)
350 {
351    /* Check if we can fold it as a src modifier */
352    if (ppir_lower_fold_src_mod(block, node))
353       return true;
354 
355    /* Fall back to a mov and set the absolute modifier */
356    ppir_alu_node *alu = ppir_node_to_alu(node);
357 
358    assert(alu->num_src == 1);
359 
360    alu->src[0].absolute = true;
361    alu->src[0].negate = false;
362    node->op = ppir_op_mov;
363 
364    return true;
365 }
366 
ppir_lower_neg(ppir_block * block,ppir_node * node)367 static bool ppir_lower_neg(ppir_block *block, ppir_node *node)
368 {
369    /* Check if we can fold it as a src modifier */
370    if (ppir_lower_fold_src_mod(block, node))
371       return true;
372 
373    /* Fall back to a mov and set the negate modifier */
374    ppir_alu_node *alu = ppir_node_to_alu(node);
375 
376    assert(alu->num_src == 1);
377 
378    alu->src[0].negate = !alu->src[0].negate;
379    node->op = ppir_op_mov;
380 
381    return true;
382 }
383 
ppir_lower_fold_dest_mod(ppir_block * block,ppir_node * node,ppir_outmod mod)384 static bool ppir_lower_fold_dest_mod(ppir_block *block, ppir_node *node, ppir_outmod mod)
385 {
386    ppir_dest *dest = ppir_node_get_dest(node);
387    if (dest->type != ppir_target_ssa)
388       return false;
389 
390    ppir_src *src = ppir_node_get_src(node, 0);
391    assert(src);
392    for (int i = 0; i < dest->ssa.num_components; i++) {
393       if (src->swizzle[i] != i)
394          return false;
395    }
396 
397    if (!ppir_node_has_single_pred(node))
398       return false;
399 
400    /* Can't track these successors with deps here so skip */
401    if (node->succ_different_block)
402       return false;
403 
404    ppir_node *pred = ppir_node_first_pred(node);
405    assert(pred);
406 
407    if (pred->type != ppir_node_type_alu)
408       return false;
409 
410    ppir_dest *pred_dest = ppir_node_get_dest(pred);
411    if (!ppir_node_has_single_succ(pred) || pred_dest->type != ppir_target_ssa)
412       return false;
413 
414    /* may happen for sum3 */
415    if (pred_dest->ssa.num_components != dest->ssa.num_components)
416       return false;
417 
418    if (pred_dest->modifier != ppir_outmod_none)
419       return false;
420 
421    pred_dest->modifier = mod;
422 
423    if (node->is_out)
424       pred->is_out = true;
425    pred_dest->ssa.out_type = pred_dest->ssa.out_type;
426 
427    ppir_node_replace_all_succ(pred, node);
428 
429    /* for all nodes after the mod node */
430    ppir_node_foreach_succ_safe(node, dep) {
431       /* replace the mod node with the pred alu */
432       ppir_node *p = dep->succ;
433       ppir_node_remove_dep(dep);
434       ppir_node_add_dep(p, pred, ppir_dep_src);
435    }
436 
437    ppir_node_delete(node);
438    return true;
439 }
440 
ppir_lower_with_dest_mod(ppir_block * block,ppir_node * node,ppir_outmod mod)441 static bool ppir_lower_with_dest_mod(ppir_block *block, ppir_node *node, ppir_outmod mod)
442 {
443    /* Check if we can fold it as a dest modifier */
444    if (ppir_lower_fold_dest_mod(block, node, mod))
445       return true;
446 
447    /* Fall back to a mov with the dest modifier */
448    ppir_alu_node *alu = ppir_node_to_alu(node);
449 
450    assert(alu->num_src == 1);
451 
452    ppir_dest *move_dest = &alu->dest;
453    move_dest->modifier = mod;
454    node->op = ppir_op_mov;
455 
456    return true;
457 }
458 
ppir_lower_trunc(ppir_block * block,ppir_node * node)459 static bool ppir_lower_trunc(ppir_block *block, ppir_node *node)
460 {
461    return ppir_lower_with_dest_mod(block, node, ppir_outmod_round);
462 }
463 
ppir_lower_clamp_pos(ppir_block * block,ppir_node * node)464 static bool ppir_lower_clamp_pos(ppir_block *block, ppir_node *node)
465 {
466    return ppir_lower_with_dest_mod(block, node, ppir_outmod_clamp_positive);
467 }
468 
ppir_lower_sat(ppir_block * block,ppir_node * node)469 static bool ppir_lower_sat(ppir_block *block, ppir_node *node)
470 {
471    return ppir_lower_with_dest_mod(block, node, ppir_outmod_clamp_fraction);
472 }
473 
ppir_lower_branch_merge_condition(ppir_block * block,ppir_node * node)474 static bool ppir_lower_branch_merge_condition(ppir_block *block, ppir_node *node)
475 {
476    /* Check if we can merge a condition with a branch instruction,
477     * removing the need for a select instruction */
478    assert(node->type == ppir_node_type_branch);
479 
480    if (!ppir_node_has_single_pred(node))
481       return false;
482 
483    ppir_node *pred = ppir_node_first_pred(node);
484    assert(pred);
485 
486    if (pred->type != ppir_node_type_alu)
487       return false;
488 
489    switch (pred->op)
490    {
491       case ppir_op_lt:
492       case ppir_op_gt:
493       case ppir_op_le:
494       case ppir_op_ge:
495       case ppir_op_eq:
496       case ppir_op_ne:
497          break;
498       default:
499          return false;
500    }
501 
502    ppir_dest *dest = ppir_node_get_dest(pred);
503    if (!ppir_node_has_single_succ(pred) || dest->type != ppir_target_ssa)
504       return false;
505 
506    ppir_alu_node *cond = ppir_node_to_alu(pred);
507    /* branch can't reference pipeline registers */
508    if (cond->src[0].type == ppir_target_pipeline ||
509        cond->src[1].type == ppir_target_pipeline)
510       return false;
511 
512    /* branch can't use flags */
513    if (cond->src[0].negate || cond->src[0].absolute ||
514        cond->src[1].negate || cond->src[1].absolute)
515       return false;
516 
517    /* at this point, it can be successfully be replaced. */
518    ppir_branch_node *branch = ppir_node_to_branch(node);
519    switch (pred->op)
520    {
521       case ppir_op_le:
522          branch->cond_gt = true;
523          break;
524       case ppir_op_lt:
525          branch->cond_eq = true;
526          branch->cond_gt = true;
527          break;
528       case ppir_op_ge:
529          branch->cond_lt = true;
530          break;
531       case ppir_op_gt:
532          branch->cond_eq = true;
533          branch->cond_lt = true;
534          break;
535       case ppir_op_eq:
536          branch->cond_lt = true;
537          branch->cond_gt = true;
538          break;
539       case ppir_op_ne:
540          branch->cond_eq = true;
541          break;
542       default:
543          assert(0);
544          break;
545    }
546 
547    assert(cond->num_src == 2);
548 
549    branch->num_src = 2;
550    branch->src[0] = cond->src[0];
551    branch->src[1] = cond->src[1];
552 
553    /* for all nodes before the condition */
554    ppir_node_foreach_pred_safe(pred, dep) {
555       /* insert the branch node as successor */
556       ppir_node *p = dep->pred;
557       ppir_node_remove_dep(dep);
558       ppir_node_add_dep(node, p, ppir_dep_src);
559    }
560 
561    ppir_node_delete(pred);
562 
563    return true;
564 }
565 
ppir_lower_branch(ppir_block * block,ppir_node * node)566 static bool ppir_lower_branch(ppir_block *block, ppir_node *node)
567 {
568    ppir_branch_node *branch = ppir_node_to_branch(node);
569 
570    /* Unconditional branch */
571    if (branch->num_src == 0)
572       return true;
573 
574    /* Check if we can merge a condition with the branch */
575    if (ppir_lower_branch_merge_condition(block, node))
576       return true;
577 
578    /* If the condition cannot be merged, fall back to a
579     * comparison against zero */
580    ppir_const_node *zero = ppir_node_create(block, ppir_op_const, -1, 0);
581 
582    if (!zero)
583       return false;
584 
585    zero->constant.value[0].f = 0;
586    zero->constant.num = 1;
587    zero->dest.type = ppir_target_pipeline;
588    zero->dest.pipeline = ppir_pipeline_reg_const0;
589    zero->dest.ssa.num_components = 1;
590    zero->dest.write_mask = 0x01;
591 
592    ppir_node_target_assign(&branch->src[1], &zero->node);
593 
594    if (branch->negate)
595       branch->cond_eq = true;
596    else {
597       branch->cond_gt = true;
598       branch->cond_lt = true;
599    }
600 
601    branch->num_src = 2;
602 
603    ppir_node_add_dep(&branch->node, &zero->node, ppir_dep_src);
604    list_addtail(&zero->node.list, &node->list);
605 
606    return true;
607 }
608 
ppir_lower_accum(ppir_block * block,ppir_node * node)609 static bool ppir_lower_accum(ppir_block *block, ppir_node *node)
610 {
611     /* If the last argument of a node placed in PPIR_INSTR_SLOT_ALU_SCL_ADD
612     * (or PPIR_INSTR_SLOT_ALU_VEC_ADD) is placed in
613     * PPIR_INSTR_SLOT_ALU_SCL_MUL (or PPIR_INSTR_SLOT_ALU_VEC_MUL) we cannot
614     * save a register (and an instruction) by using a pipeline register.
615     * Therefore it is interesting to make sure arguments of that type are
616     * the first argument by swapping arguments (if possible) */
617    ppir_alu_node *alu = ppir_node_to_alu(node);
618 
619    assert(alu->num_src >= 2);
620 
621    if (alu->src[0].type == ppir_target_pipeline)
622       return true;
623 
624    if (alu->src[0].type == ppir_target_ssa) {
625       int *src_0_slots = ppir_op_infos[alu->src[0].node->op].slots;
626       if (src_0_slots) {
627          for (int i = 0; src_0_slots[i] != PPIR_INSTR_SLOT_END; i++) {
628             if ((src_0_slots[i] == PPIR_INSTR_SLOT_ALU_SCL_MUL) ||
629                (src_0_slots[i] == PPIR_INSTR_SLOT_ALU_VEC_MUL)) {
630                return true;
631             }
632          }
633       }
634    }
635 
636    int src_to_swap = -1;
637    for (int j = 1; j < alu->num_src; j++) {
638       if (alu->src[j].type != ppir_target_ssa)
639          continue;
640       int *src_slots = ppir_op_infos[alu->src[j].node->op].slots;
641       if (!src_slots)
642          continue;
643       for (int i = 0; src_slots[i] != PPIR_INSTR_SLOT_END; i++) {
644          if ((src_slots[i] == PPIR_INSTR_SLOT_ALU_SCL_MUL) ||
645              (src_slots[i] == PPIR_INSTR_SLOT_ALU_VEC_MUL)) {
646             src_to_swap = j;
647             break;
648          }
649       }
650       if (src_to_swap > 0)
651          break;
652    }
653 
654    if (src_to_swap < 0)
655       return true;
656 
657    /* Swap arguments so that we can use a pipeline register later on */
658    ppir_src tmp = alu->src[0];
659    alu->src[0] = alu->src[src_to_swap];
660    alu->src[src_to_swap] = tmp;
661 
662    return true;
663 }
664 
665 static bool (*ppir_lower_funcs[ppir_op_num])(ppir_block *, ppir_node *) = {
666    [ppir_op_abs] = ppir_lower_abs,
667    [ppir_op_neg] = ppir_lower_neg,
668    [ppir_op_const] = ppir_lower_const,
669    [ppir_op_ddx] = ppir_lower_ddxy,
670    [ppir_op_ddy] = ppir_lower_ddxy,
671    [ppir_op_lt] = ppir_lower_swap_args,
672    [ppir_op_le] = ppir_lower_swap_args,
673    [ppir_op_load_texture] = ppir_lower_texture,
674    [ppir_op_select] = ppir_lower_select,
675    [ppir_op_trunc] = ppir_lower_trunc,
676    [ppir_op_sat] = ppir_lower_sat,
677    [ppir_op_clamp_pos] = ppir_lower_clamp_pos,
678    [ppir_op_branch] = ppir_lower_branch,
679    [ppir_op_load_uniform] = ppir_lower_load,
680    [ppir_op_load_temp] = ppir_lower_load,
681    [ppir_op_add] = ppir_lower_accum,
682    [ppir_op_max] = ppir_lower_accum,
683    [ppir_op_min] = ppir_lower_accum,
684    [ppir_op_eq] = ppir_lower_accum,
685    [ppir_op_ne] = ppir_lower_accum,
686 };
687 
ppir_lower_prog(ppir_compiler * comp)688 bool ppir_lower_prog(ppir_compiler *comp)
689 {
690    list_for_each_entry(ppir_block, block, &comp->block_list, list) {
691       list_for_each_entry_safe(ppir_node, node, &block->node_list, list) {
692          if (ppir_lower_funcs[node->op] &&
693              !ppir_lower_funcs[node->op](block, node))
694             return false;
695       }
696    }
697 
698    return true;
699 }
700