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