xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/lima/ir/pp/node.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/u_math.h"
26 #include "util/ralloc.h"
27 #include "util/bitscan.h"
28 
29 #include "ppir.h"
30 
31 const ppir_op_info ppir_op_infos[] = {
32    [ppir_op_unsupported] = {
33       .name = "unsupported",
34    },
35    [ppir_op_mov] = {
36       .name = "mov",
37       .slots = (int []) {
38          PPIR_INSTR_SLOT_ALU_SCL_ADD, PPIR_INSTR_SLOT_ALU_SCL_MUL,
39          PPIR_INSTR_SLOT_ALU_VEC_ADD, PPIR_INSTR_SLOT_ALU_VEC_MUL,
40          PPIR_INSTR_SLOT_END
41       },
42    },
43    [ppir_op_abs] = {
44       .name = "abs",
45    },
46    [ppir_op_neg] = {
47       .name = "neg",
48    },
49    [ppir_op_sat] = {
50       .name = "sat",
51    },
52    [ppir_op_clamp_pos] = {
53       .name = "clamp_pos",
54    },
55    [ppir_op_trunc] = {
56       .name = "trunc",
57    },
58    [ppir_op_mul] = {
59       .name = "mul",
60       .slots = (int []) {
61          PPIR_INSTR_SLOT_ALU_SCL_MUL, PPIR_INSTR_SLOT_ALU_VEC_MUL,
62          PPIR_INSTR_SLOT_END
63       },
64    },
65    [ppir_op_add] = {
66       .name = "add",
67       .slots = (int []) {
68          PPIR_INSTR_SLOT_ALU_SCL_ADD, PPIR_INSTR_SLOT_ALU_VEC_ADD,
69          PPIR_INSTR_SLOT_END
70       },
71    },
72    [ppir_op_sum3] = {
73       .name = "sum3",
74       .slots = (int []) {
75          PPIR_INSTR_SLOT_ALU_VEC_ADD, PPIR_INSTR_SLOT_END
76       },
77    },
78    [ppir_op_sum4] = {
79       .name = "sum4",
80       .slots = (int []) {
81          PPIR_INSTR_SLOT_ALU_VEC_ADD, PPIR_INSTR_SLOT_END
82       },
83    },
84    [ppir_op_rsqrt] = {
85       .name = "rsqrt",
86       .slots = (int []) {
87          PPIR_INSTR_SLOT_ALU_COMBINE, PPIR_INSTR_SLOT_END
88       },
89    },
90    [ppir_op_log2] = {
91       .name = "log2",
92       .slots = (int []) {
93          PPIR_INSTR_SLOT_ALU_COMBINE, PPIR_INSTR_SLOT_END
94       },
95    },
96    [ppir_op_exp2] = {
97       .name = "exp2",
98       .slots = (int []) {
99          PPIR_INSTR_SLOT_ALU_COMBINE, PPIR_INSTR_SLOT_END
100       },
101    },
102    [ppir_op_sqrt] = {
103       .name = "sqrt",
104       .slots = (int []) {
105          PPIR_INSTR_SLOT_ALU_COMBINE, PPIR_INSTR_SLOT_END
106       },
107    },
108    [ppir_op_sin] = {
109       .name = "sin",
110       .slots = (int []) {
111          PPIR_INSTR_SLOT_ALU_COMBINE, PPIR_INSTR_SLOT_END
112       },
113    },
114    [ppir_op_cos] = {
115       .name = "cos",
116       .slots = (int []) {
117          PPIR_INSTR_SLOT_ALU_COMBINE, PPIR_INSTR_SLOT_END
118       },
119    },
120    [ppir_op_max] = {
121       .name = "max",
122       .slots = (int []) {
123          PPIR_INSTR_SLOT_ALU_SCL_ADD, PPIR_INSTR_SLOT_ALU_SCL_MUL,
124          PPIR_INSTR_SLOT_ALU_VEC_ADD, PPIR_INSTR_SLOT_ALU_VEC_MUL,
125          PPIR_INSTR_SLOT_END
126       },
127    },
128    [ppir_op_min] = {
129       .name = "min",
130       .slots = (int []) {
131          PPIR_INSTR_SLOT_ALU_SCL_ADD, PPIR_INSTR_SLOT_ALU_SCL_MUL,
132          PPIR_INSTR_SLOT_ALU_VEC_ADD, PPIR_INSTR_SLOT_ALU_VEC_MUL,
133          PPIR_INSTR_SLOT_END
134       },
135    },
136    [ppir_op_floor] = {
137       .name = "floor",
138       .slots = (int []) {
139          PPIR_INSTR_SLOT_ALU_SCL_ADD, PPIR_INSTR_SLOT_ALU_VEC_ADD,
140          PPIR_INSTR_SLOT_END
141       },
142    },
143    [ppir_op_ceil] = {
144       .name = "ceil",
145       .slots = (int []) {
146          PPIR_INSTR_SLOT_ALU_SCL_ADD, PPIR_INSTR_SLOT_ALU_VEC_ADD,
147          PPIR_INSTR_SLOT_END
148       },
149    },
150    [ppir_op_fract] = {
151       .name = "fract",
152       .slots = (int []) {
153          PPIR_INSTR_SLOT_ALU_SCL_ADD, PPIR_INSTR_SLOT_ALU_VEC_ADD,
154          PPIR_INSTR_SLOT_END
155       },
156    },
157    [ppir_op_ddx] = {
158       .name = "ddx",
159       .slots = (int []) {
160          PPIR_INSTR_SLOT_ALU_SCL_ADD, PPIR_INSTR_SLOT_ALU_VEC_ADD,
161          PPIR_INSTR_SLOT_END
162       },
163    },
164    [ppir_op_ddy] = {
165       .name = "ddy",
166       .slots = (int []) {
167          PPIR_INSTR_SLOT_ALU_SCL_ADD, PPIR_INSTR_SLOT_ALU_VEC_ADD,
168          PPIR_INSTR_SLOT_END
169       },
170    },
171    [ppir_op_and] = {
172       .name = "and",
173       .slots = (int []) {
174          PPIR_INSTR_SLOT_ALU_SCL_MUL, PPIR_INSTR_SLOT_ALU_VEC_MUL,
175          PPIR_INSTR_SLOT_END
176       },
177    },
178    [ppir_op_or] = {
179       .name = "or",
180       .slots = (int []) {
181          PPIR_INSTR_SLOT_ALU_SCL_MUL, PPIR_INSTR_SLOT_ALU_VEC_MUL,
182          PPIR_INSTR_SLOT_END
183       },
184    },
185    [ppir_op_xor] = {
186       .name = "xor",
187       .slots = (int []) {
188          PPIR_INSTR_SLOT_ALU_SCL_MUL, PPIR_INSTR_SLOT_ALU_VEC_MUL,
189          PPIR_INSTR_SLOT_END
190       },
191    },
192    [ppir_op_not] = {
193       .name = "not",
194       .slots = (int []) {
195          PPIR_INSTR_SLOT_ALU_SCL_MUL, PPIR_INSTR_SLOT_ALU_VEC_MUL,
196          PPIR_INSTR_SLOT_END
197       },
198    },
199    [ppir_op_lt] = {
200       .name = "lt",
201    },
202    [ppir_op_le] = {
203       .name = "le",
204    },
205    [ppir_op_gt] = {
206       .name = "gt",
207       .slots = (int []) {
208          PPIR_INSTR_SLOT_ALU_SCL_MUL, PPIR_INSTR_SLOT_ALU_SCL_ADD,
209          PPIR_INSTR_SLOT_ALU_VEC_MUL, PPIR_INSTR_SLOT_ALU_VEC_ADD,
210          PPIR_INSTR_SLOT_END
211       },
212    },
213    [ppir_op_ge] = {
214       .name = "ge",
215       .slots = (int []) {
216          PPIR_INSTR_SLOT_ALU_SCL_MUL, PPIR_INSTR_SLOT_ALU_SCL_ADD,
217          PPIR_INSTR_SLOT_ALU_VEC_MUL, PPIR_INSTR_SLOT_ALU_VEC_ADD,
218          PPIR_INSTR_SLOT_END
219       },
220    },
221    [ppir_op_eq] = {
222       .name = "eq",
223       .slots = (int []) {
224          PPIR_INSTR_SLOT_ALU_SCL_MUL, PPIR_INSTR_SLOT_ALU_SCL_ADD,
225          PPIR_INSTR_SLOT_ALU_VEC_MUL, PPIR_INSTR_SLOT_ALU_VEC_ADD,
226          PPIR_INSTR_SLOT_END
227       },
228    },
229    [ppir_op_ne] = {
230       .name = "ne",
231       .slots = (int []) {
232          PPIR_INSTR_SLOT_ALU_SCL_MUL, PPIR_INSTR_SLOT_ALU_SCL_ADD,
233          PPIR_INSTR_SLOT_ALU_VEC_MUL, PPIR_INSTR_SLOT_ALU_VEC_ADD,
234          PPIR_INSTR_SLOT_END
235       },
236    },
237    [ppir_op_select] = {
238       .name = "select",
239       .slots = (int []) {
240          PPIR_INSTR_SLOT_ALU_SCL_ADD, PPIR_INSTR_SLOT_ALU_VEC_ADD,
241          PPIR_INSTR_SLOT_END
242       },
243    },
244    [ppir_op_rcp] = {
245       .name = "rcp",
246       .slots = (int []) {
247          PPIR_INSTR_SLOT_ALU_COMBINE, PPIR_INSTR_SLOT_END
248       },
249    },
250    [ppir_op_load_varying] = {
251       .name = "ld_var",
252       .type = ppir_node_type_load,
253       .slots = (int []) {
254          PPIR_INSTR_SLOT_VARYING, PPIR_INSTR_SLOT_END
255       },
256    },
257    [ppir_op_load_coords] = {
258       .name = "ld_coords",
259       .type = ppir_node_type_load,
260       .slots = (int []) {
261          PPIR_INSTR_SLOT_VARYING, PPIR_INSTR_SLOT_END
262       },
263    },
264    [ppir_op_load_coords_reg] = {
265       .name = "ld_coords_reg",
266       .type = ppir_node_type_load,
267       .slots = (int []) {
268          PPIR_INSTR_SLOT_VARYING, PPIR_INSTR_SLOT_END
269       },
270    },
271    [ppir_op_load_fragcoord] = {
272       .name = "ld_fragcoord",
273       .type = ppir_node_type_load,
274       .slots = (int []) {
275          PPIR_INSTR_SLOT_VARYING, PPIR_INSTR_SLOT_END
276       },
277    },
278    [ppir_op_load_pointcoord] = {
279       .name = "ld_pointcoord",
280       .type = ppir_node_type_load,
281       .slots = (int []) {
282          PPIR_INSTR_SLOT_VARYING, PPIR_INSTR_SLOT_END
283       },
284    },
285    [ppir_op_load_frontface] = {
286       .name = "ld_frontface",
287       .type = ppir_node_type_load,
288       .slots = (int []) {
289          PPIR_INSTR_SLOT_VARYING, PPIR_INSTR_SLOT_END
290       },
291    },
292    [ppir_op_load_uniform] = {
293       .name = "ld_uni",
294       .type = ppir_node_type_load,
295       .slots = (int []) {
296          PPIR_INSTR_SLOT_UNIFORM, PPIR_INSTR_SLOT_END
297       },
298    },
299    [ppir_op_load_texture] = {
300       .name = "ld_tex",
301       .type = ppir_node_type_load_texture,
302       .slots = (int []) {
303          PPIR_INSTR_SLOT_TEXLD, PPIR_INSTR_SLOT_END
304       },
305    },
306    [ppir_op_load_temp] = {
307       .name = "ld_temp",
308       .type = ppir_node_type_load,
309       .slots = (int []) {
310          PPIR_INSTR_SLOT_UNIFORM, PPIR_INSTR_SLOT_END
311       },
312    },
313    [ppir_op_const] = {
314       .name = "const",
315       .type = ppir_node_type_const,
316    },
317    [ppir_op_store_temp] = {
318       .name = "st_temp",
319       .type = ppir_node_type_store,
320       .slots = (int []) {
321          PPIR_INSTR_SLOT_STORE_TEMP, PPIR_INSTR_SLOT_END
322       },
323    },
324    [ppir_op_discard] = {
325       .name = "discard",
326       .type = ppir_node_type_discard,
327       .slots = (int []) {
328          PPIR_INSTR_SLOT_BRANCH, PPIR_INSTR_SLOT_END
329       },
330    },
331    [ppir_op_branch] = {
332       .name = "branch",
333       .type = ppir_node_type_branch,
334       .slots = (int []) {
335          PPIR_INSTR_SLOT_BRANCH, PPIR_INSTR_SLOT_END
336       },
337    },
338    [ppir_op_undef] = {
339       .name = "undef",
340       .type = ppir_node_type_alu,
341       .slots = (int []) {
342          PPIR_INSTR_SLOT_END
343       },
344    },
345    [ppir_op_dummy] = {
346       .name = "dummy",
347       .type = ppir_node_type_alu,
348       .slots = (int []) {
349          PPIR_INSTR_SLOT_END
350       },
351    },
352 };
353 
ppir_node_create(ppir_block * block,ppir_op op,int index,unsigned mask)354 void *ppir_node_create(ppir_block *block, ppir_op op, int index, unsigned mask)
355 {
356    ppir_compiler *comp = block->comp;
357    static const int node_size[] = {
358       [ppir_node_type_alu] = sizeof(ppir_alu_node),
359       [ppir_node_type_const] = sizeof(ppir_const_node),
360       [ppir_node_type_load] = sizeof(ppir_load_node),
361       [ppir_node_type_store] = sizeof(ppir_store_node),
362       [ppir_node_type_load_texture] = sizeof(ppir_load_texture_node),
363       [ppir_node_type_discard] = sizeof(ppir_discard_node),
364       [ppir_node_type_branch] = sizeof(ppir_branch_node),
365    };
366 
367    ppir_node_type type = ppir_op_infos[op].type;
368    int size = node_size[type];
369    ppir_node *node = rzalloc_size(block, size);
370    if (!node)
371       return NULL;
372 
373    list_inithead(&node->succ_list);
374    list_inithead(&node->pred_list);
375 
376    if (index >= 0) {
377       if (mask) {
378          /* reg has 4 slots for each component write node */
379          while (mask)
380             comp->var_nodes[(index << 2) + u_bit_scan(&mask)] = node;
381          snprintf(node->name, sizeof(node->name), "reg%d", index);
382       } else {
383          comp->var_nodes[index] = node;
384          snprintf(node->name, sizeof(node->name), "ssa%d", index);
385       }
386    }
387    else
388       snprintf(node->name, sizeof(node->name), "new");
389 
390    node->op = op;
391    node->type = type;
392    node->index = comp->cur_index++;
393    node->block = block;
394 
395    return node;
396 }
397 
ppir_node_add_dep(ppir_node * succ,ppir_node * pred,ppir_dep_type type)398 void ppir_node_add_dep(ppir_node *succ, ppir_node *pred,
399                        ppir_dep_type type)
400 {
401    /* don't add dep for two nodes from different block */
402    if (succ->block != pred->block) {
403       pred->succ_different_block = true;
404       return;
405    }
406 
407    /* don't add duplicated dep */
408    ppir_node_foreach_pred(succ, dep) {
409       if (dep->pred == pred)
410          return;
411    }
412 
413    ppir_dep *dep = ralloc(succ, ppir_dep);
414    dep->pred = pred;
415    dep->succ = succ;
416    dep->type = type;
417    list_addtail(&dep->pred_link, &succ->pred_list);
418    list_addtail(&dep->succ_link, &pred->succ_list);
419 }
420 
ppir_node_remove_dep(ppir_dep * dep)421 void ppir_node_remove_dep(ppir_dep *dep)
422 {
423    list_del(&dep->succ_link);
424    list_del(&dep->pred_link);
425    ralloc_free(dep);
426 }
427 
_ppir_node_replace_child(ppir_src * src,ppir_node * old_child,ppir_node * new_child)428 static void _ppir_node_replace_child(ppir_src *src, ppir_node *old_child, ppir_node *new_child)
429 {
430    ppir_dest *od = ppir_node_get_dest(old_child);
431    if (ppir_node_target_equal(src, od)) {
432       ppir_node_target_assign(src, new_child);
433    }
434 }
435 
ppir_node_replace_child(ppir_node * parent,ppir_node * old_child,ppir_node * new_child)436 void ppir_node_replace_child(ppir_node *parent, ppir_node *old_child, ppir_node *new_child)
437 {
438    switch (parent->type) {
439    case ppir_node_type_alu:
440    {
441       ppir_alu_node *alu = ppir_node_to_alu(parent);
442       for (int i = 0; i < alu->num_src; i++)
443          _ppir_node_replace_child(alu->src + i, old_child, new_child);
444       break;
445    }
446    case ppir_node_type_branch:
447    {
448       ppir_branch_node *branch = ppir_node_to_branch(parent);
449       for (int i = 0; i < 2; i++)
450          _ppir_node_replace_child(branch->src + i, old_child, new_child);
451       break;
452    }
453    case ppir_node_type_load:
454    {
455       ppir_load_node *load = ppir_node_to_load(parent);
456       _ppir_node_replace_child(&load->src, old_child, new_child);
457       break;
458    }
459    case ppir_node_type_load_texture:
460    {
461       ppir_load_texture_node *load_texture = ppir_node_to_load_texture(parent);
462       for (int i = 0; i < load_texture->num_src; i++)
463          _ppir_node_replace_child(ppir_node_get_src(parent, i), old_child, new_child);
464       break;
465    }
466    case ppir_node_type_store:
467    {
468       ppir_store_node *store = ppir_node_to_store(parent);
469       _ppir_node_replace_child(&store->src, old_child, new_child);
470       break;
471    }
472    default:
473       ppir_debug("unknown node type in %s\n", __func__);
474       break;
475    }
476 }
477 
ppir_node_replace_pred(ppir_dep * dep,ppir_node * new_pred)478 void ppir_node_replace_pred(ppir_dep *dep, ppir_node *new_pred)
479 {
480    list_del(&dep->succ_link);
481    dep->pred = new_pred;
482    list_addtail(&dep->succ_link, &new_pred->succ_list);
483 }
484 
ppir_dep_for_pred(ppir_node * node,ppir_node * pred)485 ppir_dep *ppir_dep_for_pred(ppir_node *node, ppir_node *pred)
486 {
487    if (!pred)
488       return NULL;
489 
490    if (node->block != pred->block)
491       return NULL;
492 
493    ppir_node_foreach_pred(node, dep) {
494       if (dep->pred == pred)
495          return dep;
496    }
497    return NULL;
498 }
499 
ppir_node_replace_all_succ(ppir_node * dst,ppir_node * src)500 void ppir_node_replace_all_succ(ppir_node *dst, ppir_node *src)
501 {
502    ppir_node_foreach_succ_safe(src, dep) {
503       ppir_node_replace_pred(dep, dst);
504       ppir_node_replace_child(dep->succ, src, dst);
505    }
506 }
507 
ppir_node_delete(ppir_node * node)508 void ppir_node_delete(ppir_node *node)
509 {
510    ppir_node_foreach_succ_safe(node, dep)
511       ppir_node_remove_dep(dep);
512 
513    ppir_node_foreach_pred_safe(node, dep)
514       ppir_node_remove_dep(dep);
515 
516    list_del(&node->list);
517    ralloc_free(node);
518 }
519 
ppir_node_print_dest(ppir_dest * dest)520 static void ppir_node_print_dest(ppir_dest *dest)
521 {
522    switch (dest->type) {
523    case ppir_target_ssa:
524       printf("ssa%d", dest->ssa.index);
525       break;
526    case ppir_target_pipeline:
527       printf("pipeline %d", dest->pipeline);
528       break;
529    case ppir_target_register:
530       printf("reg %d", dest->reg->index);
531       break;
532    }
533 }
534 
ppir_node_print_src(ppir_src * src)535 static void ppir_node_print_src(ppir_src *src)
536 {
537    switch (src->type) {
538    case ppir_target_ssa: {
539       if (src->node)
540          printf("ssa node %d", src->node->index);
541       else
542          printf("ssa idx %d", src->ssa ? src->ssa->index : -1);
543       break;
544    }
545    case ppir_target_pipeline:
546       if (src->node)
547          printf("pipeline %d node %d", src->pipeline, src->node->index);
548       else
549          printf("pipeline %d", src->pipeline);
550       break;
551    case ppir_target_register:
552       printf("reg %d", src->reg->index);
553       break;
554    }
555 }
556 
ppir_node_print_node(ppir_node * node,int space)557 static void ppir_node_print_node(ppir_node *node, int space)
558 {
559    for (int i = 0; i < space; i++)
560       printf(" ");
561 
562    printf("%s%d: %s %s: ", node->printed && !ppir_node_is_leaf(node) ? "+" : "",
563           node->index, ppir_op_infos[node->op].name, node->name);
564 
565    ppir_dest *dest = ppir_node_get_dest(node);
566    if (dest) {
567       printf("dest: ");
568       ppir_node_print_dest(dest);
569    }
570 
571    if (ppir_node_get_src_num(node) > 0) {
572       printf(" src: ");
573    }
574    for (int i = 0; i < ppir_node_get_src_num(node); i++) {
575       ppir_node_print_src(ppir_node_get_src(node, i));
576       if (i != (ppir_node_get_src_num(node) - 1))
577          printf(", ");
578    }
579    printf("\n");
580 
581    if (!node->printed) {
582       ppir_node_foreach_pred(node, dep) {
583          ppir_node *pred = dep->pred;
584          ppir_node_print_node(pred, space + 2);
585       }
586 
587       node->printed = true;
588    }
589 }
590 
ppir_node_print_prog(ppir_compiler * comp)591 void ppir_node_print_prog(ppir_compiler *comp)
592 {
593    if (!(lima_debug & LIMA_DEBUG_PP))
594       return;
595 
596    list_for_each_entry(ppir_block, block, &comp->block_list, list) {
597       list_for_each_entry(ppir_node, node, &block->node_list, list) {
598          node->printed = false;
599       }
600    }
601 
602    printf("========prog========\n");
603    list_for_each_entry(ppir_block, block, &comp->block_list, list) {
604       printf("-------block %3d-------\n", block->index);
605       list_for_each_entry(ppir_node, node, &block->node_list, list) {
606          if (ppir_node_is_root(node))
607             ppir_node_print_node(node, 0);
608       }
609    }
610    printf("====================\n");
611 }
612 
ppir_node_insert_mov_local(ppir_node * node)613 static ppir_node *ppir_node_insert_mov_local(ppir_node *node)
614 {
615    ppir_node *move = ppir_node_create(node->block, ppir_op_mov, -1, 0);
616    if (unlikely(!move))
617       return NULL;
618 
619    ppir_dest *dest = ppir_node_get_dest(node);
620    ppir_alu_node *alu = ppir_node_to_alu(move);
621    alu->dest = *dest;
622    alu->num_src = 1;
623    ppir_node_target_assign(alu->src, node);
624 
625    for (int s = 0; s < 4; s++)
626       alu->src->swizzle[s] = s;
627 
628    ppir_node_replace_all_succ(move, node);
629    ppir_node_add_dep(move, node, ppir_dep_src);
630    list_addtail(&move->list, &node->list);
631 
632    if (node->is_out) {
633       node->is_out = false;
634       move->is_out = true;
635    }
636 
637    return move;
638 }
639 
ppir_node_insert_mov(ppir_node * old)640 ppir_node *ppir_node_insert_mov(ppir_node *old)
641 {
642    ppir_node *move = ppir_node_insert_mov_local(old);
643    ppir_compiler *comp = old->block->comp;
644 
645    list_for_each_entry(ppir_block, block, &comp->block_list, list) {
646       if (old->block == block)
647          continue;
648       list_for_each_entry_safe(ppir_node, node, &block->node_list, list) {
649          for (int i = 0; i < ppir_node_get_src_num(node); i++){
650             ppir_src *src = ppir_node_get_src(node, i);
651             if (!src)
652                continue;
653             if (src->node == old)
654                ppir_node_target_assign(src, move);
655          }
656       }
657    }
658 
659    return move;
660 }
661 
ppir_node_has_single_src_succ(ppir_node * node)662 bool ppir_node_has_single_src_succ(ppir_node *node)
663 {
664    if (ppir_node_has_single_succ(node) &&
665        list_first_entry(&node->succ_list,
666                         ppir_dep, succ_link)->type == ppir_dep_src)
667       return true;
668 
669    int cnt = 0;
670    ppir_node_foreach_succ(node, dep) {
671       if (dep->type != ppir_dep_src)
672          continue;
673       cnt++;
674    }
675 
676    return cnt == 1;
677 }
678