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