flow: don't parse inline functions which aren't interesting
[smatch.git] / flow.c
blobfa5d31c8b2d047c8e93ef0270d55a5059501bf8e
1 /*
2 * Flow - walk the linearized flowgraph, simplifying it as we
3 * go along.
5 * Copyright (C) 2004 Linus Torvalds
6 */
8 #include <string.h>
9 #include <stdarg.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <stddef.h>
13 #include <assert.h>
15 #include "parse.h"
16 #include "expression.h"
17 #include "linearize.h"
18 #include "flow.h"
19 #include "target.h"
21 unsigned long bb_generation;
24 * Dammit, if we have a phi-node followed by a conditional
25 * branch on that phi-node, we should damn well be able to
26 * do something about the source. Maybe.
28 static int rewrite_branch(struct basic_block *bb,
29 struct basic_block **ptr,
30 struct basic_block *old,
31 struct basic_block *new)
33 if (*ptr != old || new == old || !bb->ep)
34 return 0;
36 /* We might find new if-conversions or non-dominating CSEs */
37 /* we may also create new dead cycles */
38 repeat_phase |= REPEAT_CSE | REPEAT_CFG_CLEANUP;
39 *ptr = new;
40 replace_bb_in_list(&bb->children, old, new, 1);
41 remove_bb_from_list(&old->parents, bb, 1);
42 add_bb(&new->parents, bb);
43 return 1;
47 * Return the known truth value of a pseudo, or -1 if
48 * it's not known.
50 static int pseudo_truth_value(pseudo_t pseudo)
52 switch (pseudo->type) {
53 case PSEUDO_VAL:
54 return !!pseudo->value;
56 case PSEUDO_REG: {
57 struct instruction *insn = pseudo->def;
59 /* A symbol address is always considered true.. */
60 if (insn->opcode == OP_SYMADDR && insn->target == pseudo)
61 return 1;
63 /* Fall through */
64 default:
65 return -1;
70 * Does a basic block depend on the pseudos that "src" defines?
72 static int bb_depends_on(struct basic_block *target, struct basic_block *src)
74 pseudo_t pseudo;
76 FOR_EACH_PTR(src->defines, pseudo) {
77 if (pseudo_in_list(target->needs, pseudo))
78 return 1;
79 } END_FOR_EACH_PTR(pseudo);
80 return 0;
84 * This really should be handled by bb_depends_on()
85 * which efficiently check the dependence using the
86 * defines - needs liveness info. Problem is that
87 * there is no liveness done on OP_PHI & OP_PHISRC.
89 * This function add the missing dependency checks.
91 static int bb_depends_on_phi(struct basic_block *target, struct basic_block *src)
93 struct instruction *insn;
94 FOR_EACH_PTR(src->insns, insn) {
95 if (!insn->bb)
96 continue;
97 if (insn->opcode != OP_PHI)
98 continue;
99 if (pseudo_in_list(target->needs, insn->target))
100 return 1;
101 } END_FOR_EACH_PTR(insn);
102 return 0;
106 * When we reach here, we have:
107 * - a basic block that ends in a conditional branch and
108 * that has no side effects apart from the pseudos it
109 * may change.
110 * - the phi-node that the conditional branch depends on
111 * - full pseudo liveness information
113 * We need to check if any of the _sources_ of the phi-node
114 * may be constant, and not actually need this block at all.
116 static int try_to_simplify_bb(struct basic_block *bb, struct instruction *first, struct instruction *second)
118 int changed = 0;
119 pseudo_t phi;
120 int bogus;
123 * This a due to improper dominance tracking during
124 * simplify_symbol_usage()/conversion to SSA form.
125 * No sane simplification can be done when we have this.
127 bogus = bb_list_size(bb->parents) != pseudo_list_size(first->phi_list);
129 FOR_EACH_PTR(first->phi_list, phi) {
130 struct instruction *def = phi->def;
131 struct basic_block *source, *target;
132 pseudo_t pseudo;
133 struct instruction *br;
134 int true;
136 if (!def)
137 continue;
138 source = def->bb;
139 pseudo = def->src1;
140 if (!pseudo || !source)
141 continue;
142 br = last_instruction(source->insns);
143 if (!br)
144 continue;
145 if (br->opcode != OP_CBR && br->opcode != OP_BR)
146 continue;
147 true = pseudo_truth_value(pseudo);
148 if (true < 0)
149 continue;
150 target = true ? second->bb_true : second->bb_false;
151 if (bb_depends_on(target, bb))
152 continue;
153 if (bb_depends_on_phi(target, bb))
154 continue;
155 changed |= rewrite_branch(source, &br->bb_true, bb, target);
156 changed |= rewrite_branch(source, &br->bb_false, bb, target);
157 if (changed && !bogus)
158 kill_use(THIS_ADDRESS(phi));
159 } END_FOR_EACH_PTR(phi);
160 return changed;
163 static int bb_has_side_effects(struct basic_block *bb)
165 struct instruction *insn;
166 FOR_EACH_PTR(bb->insns, insn) {
167 switch (insn->opcode) {
168 case OP_CALL:
169 /* FIXME! This should take "const" etc into account */
170 return 1;
172 case OP_STORE:
173 case OP_CONTEXT:
174 return 1;
176 case OP_ASM:
177 /* FIXME! This should take "volatile" etc into account */
178 return 1;
180 default:
181 continue;
183 } END_FOR_EACH_PTR(insn);
184 return 0;
187 static int simplify_phi_branch(struct basic_block *bb, struct instruction *br)
189 pseudo_t cond = br->cond;
190 struct instruction *def;
192 if (cond->type != PSEUDO_REG)
193 return 0;
194 def = cond->def;
195 if (def->bb != bb || def->opcode != OP_PHI)
196 return 0;
197 if (bb_has_side_effects(bb))
198 return 0;
199 return try_to_simplify_bb(bb, def, br);
202 static int simplify_branch_branch(struct basic_block *bb, struct instruction *br,
203 struct basic_block **target_p, int true)
205 struct basic_block *target = *target_p, *final;
206 struct instruction *insn;
207 int retval;
209 if (target == bb)
210 return 0;
211 insn = last_instruction(target->insns);
212 if (!insn || insn->opcode != OP_CBR || insn->cond != br->cond)
213 return 0;
215 * Ahhah! We've found a branch to a branch on the same conditional!
216 * Now we just need to see if we can rewrite the branch..
218 retval = 0;
219 final = true ? insn->bb_true : insn->bb_false;
220 if (bb_has_side_effects(target))
221 goto try_to_rewrite_target;
222 if (bb_depends_on(final, target))
223 goto try_to_rewrite_target;
224 if (bb_depends_on_phi(final, target))
225 return 0;
226 return rewrite_branch(bb, target_p, target, final);
228 try_to_rewrite_target:
230 * If we're the only parent, at least we can rewrite the
231 * now-known second branch.
233 if (bb_list_size(target->parents) != 1)
234 return retval;
235 insert_branch(target, insn, final);
236 return 1;
239 static int simplify_one_branch(struct basic_block *bb, struct instruction *br)
241 if (simplify_phi_branch(bb, br))
242 return 1;
243 return simplify_branch_branch(bb, br, &br->bb_true, 1) |
244 simplify_branch_branch(bb, br, &br->bb_false, 0);
247 static int simplify_branch_nodes(struct entrypoint *ep)
249 int changed = 0;
250 struct basic_block *bb;
252 FOR_EACH_PTR(ep->bbs, bb) {
253 struct instruction *br = last_instruction(bb->insns);
255 if (!br || br->opcode != OP_CBR)
256 continue;
257 changed |= simplify_one_branch(bb, br);
258 } END_FOR_EACH_PTR(bb);
259 return changed;
263 * This is called late - when we have intra-bb liveness information..
265 int simplify_flow(struct entrypoint *ep)
267 return simplify_branch_nodes(ep);
270 static inline void concat_user_list(struct pseudo_user_list *src, struct pseudo_user_list **dst)
272 concat_ptr_list((struct ptr_list *)src, (struct ptr_list **)dst);
275 void convert_instruction_target(struct instruction *insn, pseudo_t src)
277 pseudo_t target;
278 struct pseudo_user *pu;
280 * Go through the "insn->users" list and replace them all..
282 target = insn->target;
283 if (target == src)
284 return;
285 FOR_EACH_PTR(target->users, pu) {
286 if (*pu->userp != VOID) {
287 assert(*pu->userp == target);
288 *pu->userp = src;
290 } END_FOR_EACH_PTR(pu);
291 if (has_use_list(src))
292 concat_user_list(target->users, &src->users);
293 target->users = NULL;
296 void convert_load_instruction(struct instruction *insn, pseudo_t src)
298 convert_instruction_target(insn, src);
299 /* Turn the load into a no-op */
300 insn->opcode = OP_LNOP;
301 insn->bb = NULL;
304 static int overlapping_memop(struct instruction *a, struct instruction *b)
306 unsigned int a_start = bytes_to_bits(a->offset);
307 unsigned int b_start = bytes_to_bits(b->offset);
308 unsigned int a_size = a->size;
309 unsigned int b_size = b->size;
311 if (a_size + a_start <= b_start)
312 return 0;
313 if (b_size + b_start <= a_start)
314 return 0;
315 return 1;
318 static inline int same_memop(struct instruction *a, struct instruction *b)
320 return a->offset == b->offset && a->size == b->size;
323 static inline int distinct_symbols(pseudo_t a, pseudo_t b)
325 if (a->type != PSEUDO_SYM)
326 return 0;
327 if (b->type != PSEUDO_SYM)
328 return 0;
329 return a->sym != b->sym;
333 * Return 1 if "dom" dominates the access to "pseudo"
334 * in "insn".
336 * Return 0 if it doesn't, and -1 if you don't know.
338 int dominates(pseudo_t pseudo, struct instruction *insn, struct instruction *dom, int local)
340 int opcode = dom->opcode;
342 if (opcode == OP_CALL || opcode == OP_ENTRY)
343 return local ? 0 : -1;
344 if (opcode != OP_LOAD && opcode != OP_STORE)
345 return 0;
346 if (dom->src != pseudo) {
347 if (local)
348 return 0;
349 /* We don't think two explicitly different symbols ever alias */
350 if (distinct_symbols(insn->src, dom->src))
351 return 0;
352 /* We could try to do some alias analysis here */
353 return -1;
355 if (!same_memop(insn, dom)) {
356 if (dom->opcode == OP_LOAD)
357 return 0;
358 if (!overlapping_memop(insn, dom))
359 return 0;
360 return -1;
362 return 1;
365 static int phisrc_in_bb(struct pseudo_list *list, struct basic_block *bb)
367 pseudo_t p;
368 FOR_EACH_PTR(list, p) {
369 if (p->def->bb == bb)
370 return 1;
371 } END_FOR_EACH_PTR(p);
373 return 0;
376 static int find_dominating_parents(pseudo_t pseudo, struct instruction *insn,
377 struct basic_block *bb, unsigned long generation, struct pseudo_list **dominators,
378 int local)
380 struct basic_block *parent;
382 if (!bb->parents)
383 return !!local;
385 FOR_EACH_PTR(bb->parents, parent) {
386 struct instruction *one;
387 struct instruction *br;
388 pseudo_t phi;
390 FOR_EACH_PTR_REVERSE(parent->insns, one) {
391 int dominance;
392 if (one == insn)
393 goto no_dominance;
394 dominance = dominates(pseudo, insn, one, local);
395 if (dominance < 0) {
396 if (one->opcode == OP_LOAD)
397 continue;
398 return 0;
400 if (!dominance)
401 continue;
402 goto found_dominator;
403 } END_FOR_EACH_PTR_REVERSE(one);
404 no_dominance:
405 if (parent->generation == generation)
406 continue;
407 parent->generation = generation;
409 if (!find_dominating_parents(pseudo, insn, parent, generation, dominators, local))
410 return 0;
411 continue;
413 found_dominator:
414 if (dominators && phisrc_in_bb(*dominators, parent))
415 continue;
416 br = delete_last_instruction(&parent->insns);
417 phi = alloc_phi(parent, one->target, one->size);
418 phi->ident = phi->ident ? : pseudo->ident;
419 add_instruction(&parent->insns, br);
420 use_pseudo(insn, phi, add_pseudo(dominators, phi));
421 } END_FOR_EACH_PTR(parent);
422 return 1;
426 * We should probably sort the phi list just to make it easier to compare
427 * later for equality.
429 void rewrite_load_instruction(struct instruction *insn, struct pseudo_list *dominators)
431 pseudo_t new, phi;
434 * Check for somewhat common case of duplicate
435 * phi nodes.
437 new = first_pseudo(dominators)->def->src1;
438 FOR_EACH_PTR(dominators, phi) {
439 if (new != phi->def->src1)
440 goto complex_phi;
441 new->ident = new->ident ? : phi->ident;
442 } END_FOR_EACH_PTR(phi);
445 * All the same pseudo - mark the phi-nodes unused
446 * and convert the load into a LNOP and replace the
447 * pseudo.
449 FOR_EACH_PTR(dominators, phi) {
450 kill_instruction(phi->def);
451 } END_FOR_EACH_PTR(phi);
452 convert_load_instruction(insn, new);
453 return;
455 complex_phi:
456 /* We leave symbol pseudos with a bogus usage list here */
457 if (insn->src->type != PSEUDO_SYM)
458 kill_use(&insn->src);
459 insn->opcode = OP_PHI;
460 insn->phi_list = dominators;
463 static int find_dominating_stores(pseudo_t pseudo, struct instruction *insn,
464 unsigned long generation, int local)
466 struct basic_block *bb = insn->bb;
467 struct instruction *one, *dom = NULL;
468 struct pseudo_list *dominators;
469 int partial;
471 /* Unreachable load? Undo it */
472 if (!bb) {
473 insn->opcode = OP_LNOP;
474 return 1;
477 partial = 0;
478 FOR_EACH_PTR(bb->insns, one) {
479 int dominance;
480 if (one == insn)
481 goto found;
482 dominance = dominates(pseudo, insn, one, local);
483 if (dominance < 0) {
484 /* Ignore partial load dominators */
485 if (one->opcode == OP_LOAD)
486 continue;
487 dom = NULL;
488 partial = 1;
489 continue;
491 if (!dominance)
492 continue;
493 dom = one;
494 partial = 0;
495 } END_FOR_EACH_PTR(one);
496 /* Whaa? */
497 warning(pseudo->sym->pos, "unable to find symbol read");
498 return 0;
499 found:
500 if (partial)
501 return 0;
503 if (dom) {
504 convert_load_instruction(insn, dom->target);
505 return 1;
508 /* OK, go find the parents */
509 bb->generation = generation;
511 dominators = NULL;
512 if (!find_dominating_parents(pseudo, insn, bb, generation, &dominators, local))
513 return 0;
515 /* This happens with initial assignments to structures etc.. */
516 if (!dominators) {
517 if (!local)
518 return 0;
519 check_access(insn);
520 convert_load_instruction(insn, value_pseudo(insn->type, 0));
521 return 1;
525 * If we find just one dominating instruction, we
526 * can turn it into a direct thing. Otherwise we'll
527 * have to turn the load into a phi-node of the
528 * dominators.
530 rewrite_load_instruction(insn, dominators);
531 return 1;
534 static void kill_store(struct instruction *insn)
536 if (insn) {
537 insn->bb = NULL;
538 insn->opcode = OP_SNOP;
539 kill_use(&insn->target);
543 /* Kill a pseudo that is dead on exit from the bb */
544 static void kill_dead_stores(pseudo_t pseudo, unsigned long generation, struct basic_block *bb, int local)
546 struct instruction *insn;
547 struct basic_block *parent;
549 if (bb->generation == generation)
550 return;
551 bb->generation = generation;
552 FOR_EACH_PTR_REVERSE(bb->insns, insn) {
553 int opcode = insn->opcode;
555 if (opcode != OP_LOAD && opcode != OP_STORE) {
556 if (local)
557 continue;
558 if (opcode == OP_CALL)
559 return;
560 continue;
562 if (insn->src == pseudo) {
563 if (opcode == OP_LOAD)
564 return;
565 kill_store(insn);
566 continue;
568 if (local)
569 continue;
570 if (insn->src->type != PSEUDO_SYM)
571 return;
572 } END_FOR_EACH_PTR_REVERSE(insn);
574 FOR_EACH_PTR(bb->parents, parent) {
575 struct basic_block *child;
576 FOR_EACH_PTR(parent->children, child) {
577 if (child && child != bb)
578 return;
579 } END_FOR_EACH_PTR(child);
580 kill_dead_stores(pseudo, generation, parent, local);
581 } END_FOR_EACH_PTR(parent);
585 * This should see if the "insn" trivially dominates some previous store, and kill the
586 * store if unnecessary.
588 static void kill_dominated_stores(pseudo_t pseudo, struct instruction *insn,
589 unsigned long generation, struct basic_block *bb, int local, int found)
591 struct instruction *one;
592 struct basic_block *parent;
594 /* Unreachable store? Undo it */
595 if (!bb) {
596 kill_store(insn);
597 return;
599 if (bb->generation == generation)
600 return;
601 bb->generation = generation;
602 FOR_EACH_PTR_REVERSE(bb->insns, one) {
603 int dominance;
604 if (!found) {
605 if (one != insn)
606 continue;
607 found = 1;
608 continue;
610 dominance = dominates(pseudo, insn, one, local);
611 if (!dominance)
612 continue;
613 if (dominance < 0)
614 return;
615 if (one->opcode == OP_LOAD)
616 return;
617 kill_store(one);
618 } END_FOR_EACH_PTR_REVERSE(one);
620 if (!found) {
621 warning(bb->pos, "Unable to find instruction");
622 return;
625 FOR_EACH_PTR(bb->parents, parent) {
626 struct basic_block *child;
627 FOR_EACH_PTR(parent->children, child) {
628 if (child && child != bb)
629 return;
630 } END_FOR_EACH_PTR(child);
631 kill_dominated_stores(pseudo, insn, generation, parent, local, found);
632 } END_FOR_EACH_PTR(parent);
635 void check_access(struct instruction *insn)
637 pseudo_t pseudo = insn->src;
639 if (insn->bb && pseudo->type == PSEUDO_SYM) {
640 int offset = insn->offset, bit = bytes_to_bits(offset) + insn->size;
641 struct symbol *sym = pseudo->sym;
643 if (sym->bit_size > 0 && (offset < 0 || bit > sym->bit_size))
644 warning(insn->pos, "invalid access %s '%s' (%d %d)",
645 offset < 0 ? "below" : "past the end of",
646 show_ident(sym->ident), offset,
647 bits_to_bytes(sym->bit_size));
651 static void simplify_one_symbol(struct entrypoint *ep, struct symbol *sym)
653 pseudo_t pseudo;
654 struct pseudo_user *pu;
655 unsigned long mod;
656 int all;
658 /* Never used as a symbol? */
659 pseudo = sym->pseudo;
660 if (!pseudo)
661 return;
663 /* We don't do coverage analysis of volatiles.. */
664 if (sym->ctype.modifiers & MOD_VOLATILE)
665 return;
667 /* ..and symbols with external visibility need more care */
668 mod = sym->ctype.modifiers & (MOD_NONLOCAL | MOD_STATIC | MOD_ADDRESSABLE);
669 if (mod)
670 goto external_visibility;
672 FOR_EACH_PTR(pseudo->users, pu) {
673 /* We know that the symbol-pseudo use is the "src" in the instruction */
674 struct instruction *insn = pu->insn;
676 switch (insn->opcode) {
677 case OP_STORE:
678 break;
679 case OP_LOAD:
680 break;
681 case OP_SYMADDR:
682 if (!insn->bb)
683 continue;
684 mod |= MOD_ADDRESSABLE;
685 goto external_visibility;
686 case OP_NOP:
687 case OP_SNOP:
688 case OP_LNOP:
689 case OP_PHI:
690 continue;
691 default:
692 warning(sym->pos, "symbol '%s' pseudo used in unexpected way", show_ident(sym->ident));
694 } END_FOR_EACH_PTR(pu);
696 external_visibility:
697 all = 1;
698 FOR_EACH_PTR_REVERSE(pseudo->users, pu) {
699 struct instruction *insn = pu->insn;
700 if (insn->opcode == OP_LOAD)
701 all &= find_dominating_stores(pseudo, insn, ++bb_generation, !mod);
702 } END_FOR_EACH_PTR_REVERSE(pu);
704 /* If we converted all the loads, remove the stores. They are dead */
705 if (all && !mod) {
706 FOR_EACH_PTR(pseudo->users, pu) {
707 struct instruction *insn = pu->insn;
708 if (insn->opcode == OP_STORE)
709 kill_store(insn);
710 } END_FOR_EACH_PTR(pu);
711 } else {
713 * If we couldn't take the shortcut, see if we can at least kill some
714 * of them..
716 FOR_EACH_PTR(pseudo->users, pu) {
717 struct instruction *insn = pu->insn;
718 if (insn->opcode == OP_STORE)
719 kill_dominated_stores(pseudo, insn, ++bb_generation, insn->bb, !mod, 0);
720 } END_FOR_EACH_PTR(pu);
722 if (!(mod & (MOD_NONLOCAL | MOD_STATIC))) {
723 struct basic_block *bb;
724 FOR_EACH_PTR(ep->bbs, bb) {
725 if (!bb->children)
726 kill_dead_stores(pseudo, ++bb_generation, bb, !mod);
727 } END_FOR_EACH_PTR(bb);
731 return;
734 void simplify_symbol_usage(struct entrypoint *ep)
736 pseudo_t pseudo;
738 FOR_EACH_PTR(ep->accesses, pseudo) {
739 simplify_one_symbol(ep, pseudo->sym);
740 } END_FOR_EACH_PTR(pseudo);
743 static void mark_bb_reachable(struct basic_block *bb, unsigned long generation)
745 struct basic_block *child;
747 if (bb->generation == generation)
748 return;
749 bb->generation = generation;
750 FOR_EACH_PTR(bb->children, child) {
751 mark_bb_reachable(child, generation);
752 } END_FOR_EACH_PTR(child);
755 static void kill_defs(struct instruction *insn)
757 pseudo_t target = insn->target;
759 if (!has_use_list(target))
760 return;
761 if (target->def != insn)
762 return;
764 convert_instruction_target(insn, VOID);
767 void kill_bb(struct basic_block *bb)
769 struct instruction *insn;
770 struct basic_block *child, *parent;
772 FOR_EACH_PTR(bb->insns, insn) {
773 kill_instruction_force(insn);
774 kill_defs(insn);
776 * We kill unreachable instructions even if they
777 * otherwise aren't "killable" (e.g. volatile loads)
779 } END_FOR_EACH_PTR(insn);
780 bb->insns = NULL;
782 FOR_EACH_PTR(bb->children, child) {
783 remove_bb_from_list(&child->parents, bb, 0);
784 } END_FOR_EACH_PTR(child);
785 bb->children = NULL;
787 FOR_EACH_PTR(bb->parents, parent) {
788 remove_bb_from_list(&parent->children, bb, 0);
789 } END_FOR_EACH_PTR(parent);
790 bb->parents = NULL;
793 void kill_unreachable_bbs(struct entrypoint *ep)
795 struct basic_block *bb;
796 unsigned long generation = ++bb_generation;
798 mark_bb_reachable(ep->entry->bb, generation);
799 FOR_EACH_PTR(ep->bbs, bb) {
800 if (bb->generation == generation)
801 continue;
802 /* Mark it as being dead */
803 kill_bb(bb);
804 bb->ep = NULL;
805 DELETE_CURRENT_PTR(bb);
806 } END_FOR_EACH_PTR(bb);
807 PACK_PTR_LIST(&ep->bbs);
810 static int rewrite_parent_branch(struct basic_block *bb, struct basic_block *old, struct basic_block *new)
812 int changed = 0;
813 struct instruction *insn = last_instruction(bb->insns);
815 if (!insn)
816 return 0;
818 /* Infinite loops: let's not "optimize" them.. */
819 if (old == new)
820 return 0;
822 switch (insn->opcode) {
823 case OP_CBR:
824 changed |= rewrite_branch(bb, &insn->bb_false, old, new);
825 /* fall through */
826 case OP_BR:
827 changed |= rewrite_branch(bb, &insn->bb_true, old, new);
828 assert(changed);
829 return changed;
830 case OP_SWITCH: {
831 struct multijmp *jmp;
832 FOR_EACH_PTR(insn->multijmp_list, jmp) {
833 changed |= rewrite_branch(bb, &jmp->target, old, new);
834 } END_FOR_EACH_PTR(jmp);
835 assert(changed);
836 return changed;
838 default:
839 return 0;
843 static struct basic_block * rewrite_branch_bb(struct basic_block *bb, struct instruction *br)
845 struct basic_block *parent;
846 struct basic_block *target = br->bb_true;
847 struct basic_block *false = br->bb_false;
849 if (br->opcode == OP_CBR) {
850 pseudo_t cond = br->cond;
851 if (cond->type != PSEUDO_VAL)
852 return NULL;
853 target = cond->value ? target : false;
857 * We can't do FOR_EACH_PTR() here, because the parent list
858 * may change when we rewrite the parent.
860 while ((parent = first_basic_block(bb->parents)) != NULL) {
861 if (!rewrite_parent_branch(parent, bb, target))
862 return NULL;
864 return target;
867 static void vrfy_bb_in_list(struct basic_block *bb, struct basic_block_list *list)
869 if (bb) {
870 struct basic_block *tmp;
871 int no_bb_in_list = 0;
873 FOR_EACH_PTR(list, tmp) {
874 if (bb == tmp)
875 return;
876 } END_FOR_EACH_PTR(tmp);
877 assert(no_bb_in_list);
881 static void vrfy_parents(struct basic_block *bb)
883 struct basic_block *tmp;
884 FOR_EACH_PTR(bb->parents, tmp) {
885 vrfy_bb_in_list(bb, tmp->children);
886 } END_FOR_EACH_PTR(tmp);
889 static void vrfy_children(struct basic_block *bb)
891 struct basic_block *tmp;
892 struct instruction *br = last_instruction(bb->insns);
894 if (!br) {
895 assert(!bb->children);
896 return;
898 switch (br->opcode) {
899 struct multijmp *jmp;
900 case OP_CBR:
901 vrfy_bb_in_list(br->bb_false, bb->children);
902 /* fall through */
903 case OP_BR:
904 vrfy_bb_in_list(br->bb_true, bb->children);
905 break;
906 case OP_SWITCH:
907 case OP_COMPUTEDGOTO:
908 FOR_EACH_PTR(br->multijmp_list, jmp) {
909 vrfy_bb_in_list(jmp->target, bb->children);
910 } END_FOR_EACH_PTR(jmp);
911 break;
912 default:
913 break;
916 FOR_EACH_PTR(bb->children, tmp) {
917 vrfy_bb_in_list(bb, tmp->parents);
918 } END_FOR_EACH_PTR(tmp);
921 static void vrfy_bb_flow(struct basic_block *bb)
923 vrfy_children(bb);
924 vrfy_parents(bb);
927 void vrfy_flow(struct entrypoint *ep)
929 struct basic_block *bb;
930 struct basic_block *entry = ep->entry->bb;
932 FOR_EACH_PTR(ep->bbs, bb) {
933 if (bb == entry)
934 entry = NULL;
935 vrfy_bb_flow(bb);
936 } END_FOR_EACH_PTR(bb);
937 assert(!entry);
940 void pack_basic_blocks(struct entrypoint *ep)
942 struct basic_block *bb;
944 /* See if we can merge a bb into another one.. */
945 FOR_EACH_PTR(ep->bbs, bb) {
946 struct instruction *first, *insn;
947 struct basic_block *parent, *child, *last;
949 if (!bb_reachable(bb))
950 continue;
953 * Just a branch?
955 FOR_EACH_PTR(bb->insns, first) {
956 if (!first->bb)
957 continue;
958 switch (first->opcode) {
959 case OP_NOP: case OP_LNOP: case OP_SNOP:
960 continue;
961 case OP_CBR:
962 case OP_BR: {
963 struct basic_block *replace;
964 replace = rewrite_branch_bb(bb, first);
965 if (replace) {
966 kill_bb(bb);
967 goto no_merge;
970 /* fallthrough */
971 default:
972 goto out;
974 } END_FOR_EACH_PTR(first);
976 out:
978 * See if we only have one parent..
980 last = NULL;
981 FOR_EACH_PTR(bb->parents, parent) {
982 if (last) {
983 if (last != parent)
984 goto no_merge;
985 continue;
987 last = parent;
988 } END_FOR_EACH_PTR(parent);
990 parent = last;
991 if (!parent || parent == bb)
992 continue;
995 * Goodie. See if the parent can merge..
997 FOR_EACH_PTR(parent->children, child) {
998 if (child != bb)
999 goto no_merge;
1000 } END_FOR_EACH_PTR(child);
1003 * Merge the two.
1005 repeat_phase |= REPEAT_CSE;
1007 parent->children = bb->children;
1008 bb->children = NULL;
1009 bb->parents = NULL;
1011 FOR_EACH_PTR(parent->children, child) {
1012 replace_bb_in_list(&child->parents, bb, parent, 0);
1013 } END_FOR_EACH_PTR(child);
1015 kill_instruction(delete_last_instruction(&parent->insns));
1016 FOR_EACH_PTR(bb->insns, insn) {
1017 if (insn->bb) {
1018 assert(insn->bb == bb);
1019 insn->bb = parent;
1021 add_instruction(&parent->insns, insn);
1022 } END_FOR_EACH_PTR(insn);
1023 bb->insns = NULL;
1025 no_merge:
1026 /* nothing to do */;
1027 } END_FOR_EACH_PTR(bb);