2 * Flow - walk the linearized flowgraph, simplifying it as we
5 * Copyright (C) 2004 Linus Torvalds
16 #include "expression.h"
17 #include "linearize.h"
20 unsigned long bb_generation
;
23 * Dammit, if we have a phi-node followed by a conditional
24 * branch on that phi-node, we should damn well be able to
25 * do something about the source. Maybe.
27 static void rewrite_branch(struct basic_block
*bb
,
28 struct basic_block
**ptr
,
29 struct basic_block
*old
,
30 struct basic_block
*new)
32 if (*ptr
!= old
|| new == old
)
35 /* We might find new if-conversions or non-dominating CSEs */
36 repeat_phase
|= REPEAT_CSE
;
38 replace_bb_in_list(&bb
->children
, old
, new, 1);
39 remove_bb_from_list(&old
->parents
, bb
, 1);
40 add_bb(&new->parents
, bb
);
44 * Return the known truth value of a pseudo, or -1 if
47 static int pseudo_truth_value(pseudo_t pseudo
)
49 switch (pseudo
->type
) {
51 return !!pseudo
->value
;
54 struct instruction
*insn
= pseudo
->def
;
55 if (insn
->opcode
== OP_SETVAL
&& insn
->target
== pseudo
) {
56 struct expression
*expr
= insn
->val
;
58 /* A symbol address is always considered true.. */
61 if (expr
->type
== EXPR_VALUE
)
72 static void try_to_simplify_bb(struct entrypoint
*ep
, struct basic_block
*bb
,
73 struct instruction
*first
, struct instruction
*second
)
77 FOR_EACH_PTR(first
->phi_list
, phi
) {
78 struct instruction
*def
= phi
->def
;
79 struct basic_block
*source
= def
->bb
, *target
;
80 pseudo_t pseudo
= def
->src1
;
81 struct instruction
*br
;
84 if (!pseudo
|| !source
)
86 br
= last_instruction(source
->insns
);
89 if (br
->opcode
!= OP_BR
)
92 true = pseudo_truth_value(pseudo
);
95 target
= true ? second
->bb_true
: second
->bb_false
;
96 rewrite_branch(source
, &br
->bb_true
, bb
, target
);
97 rewrite_branch(source
, &br
->bb_false
, bb
, target
);
98 } END_FOR_EACH_PTR(phi
);
101 static inline int linearize_insn_list(struct instruction_list
*list
, struct instruction
**arr
, int nr
)
103 return linearize_ptr_list((struct ptr_list
*)list
, (void **)arr
, nr
);
106 static void simplify_phi_nodes(struct entrypoint
*ep
)
108 struct basic_block
*bb
;
110 FOR_EACH_PTR(ep
->bbs
, bb
) {
111 struct instruction
*insns
[2], *first
, *second
;
113 if (linearize_insn_list(bb
->insns
, insns
, 2) < 2)
119 if (first
->opcode
!= OP_PHI
)
121 if (second
->opcode
!= OP_BR
)
123 if (first
->target
!= second
->cond
)
125 try_to_simplify_bb(ep
, bb
, first
, second
);
126 } END_FOR_EACH_PTR(bb
);
129 static inline void concat_user_list(struct pseudo_ptr_list
*src
, struct pseudo_ptr_list
**dst
)
131 concat_ptr_list((struct ptr_list
*)src
, (struct ptr_list
**)dst
);
134 void convert_instruction_target(struct instruction
*insn
, pseudo_t src
)
136 pseudo_t target
, *usep
;
139 * Go through the "insn->users" list and replace them all..
141 target
= insn
->target
;
144 FOR_EACH_PTR(target
->users
, usep
) {
146 assert(*usep
== target
);
149 } END_FOR_EACH_PTR(usep
);
150 concat_user_list(target
->users
, &src
->users
);
151 target
->users
= NULL
;
154 void convert_load_instruction(struct instruction
*insn
, pseudo_t src
)
156 convert_instruction_target(insn
, src
);
157 /* Turn the load into a no-op */
158 insn
->opcode
= OP_LNOP
;
162 static int overlapping_memop(struct instruction
*a
, struct instruction
*b
)
164 unsigned int a_start
= a
->offset
<< 3;
165 unsigned int b_start
= b
->offset
<< 3;
166 unsigned int a_size
= a
->size
;
167 unsigned int b_size
= b
->size
;
169 if (a_size
+ a_start
<= b_start
)
171 if (b_size
+ b_start
<= a_start
)
176 static inline int same_memop(struct instruction
*a
, struct instruction
*b
)
178 return a
->offset
== b
->offset
&& a
->size
== b
->size
;
182 * Return 1 if "one" dominates the access to 'pseudo'
185 * Return 0 if it doesn't, and -1 if you don't know.
187 int dominates(pseudo_t pseudo
, struct instruction
*insn
, struct instruction
*dom
, int local
)
189 int opcode
= dom
->opcode
;
191 if (opcode
== OP_CALL
)
192 return local
? 0 : -1;
193 if (opcode
!= OP_LOAD
&& opcode
!= OP_STORE
)
195 if (dom
->src
!= pseudo
) {
198 /* We don't think two explicitly different symbols ever alias */
199 if (dom
->src
->type
== PSEUDO_SYM
)
201 /* We could try to do some alias analysis here */
204 if (!same_memop(insn
, dom
)) {
205 if (dom
->opcode
== OP_LOAD
)
207 if (!overlapping_memop(insn
, dom
))
214 static int find_dominating_parents(pseudo_t pseudo
, struct instruction
*insn
,
215 struct basic_block
*bb
, unsigned long generation
, struct pseudo_list
**dominators
,
216 int local
, int loads
)
218 struct basic_block
*parent
;
223 if (bb_list_size(bb
->parents
) > 1)
225 FOR_EACH_PTR(bb
->parents
, parent
) {
226 struct instruction
*one
;
227 struct instruction
*br
;
230 FOR_EACH_PTR_REVERSE(parent
->insns
, one
) {
234 dominance
= dominates(pseudo
, insn
, one
, local
);
236 if (one
->opcode
== OP_LOAD
)
242 if (one
->opcode
== OP_LOAD
&& !loads
)
244 goto found_dominator
;
245 } END_FOR_EACH_PTR_REVERSE(one
);
247 if (parent
->generation
== generation
)
249 parent
->generation
= generation
;
251 if (!find_dominating_parents(pseudo
, insn
, parent
, generation
, dominators
, local
, loads
))
256 br
= delete_last_instruction(&parent
->insns
);
257 phi
= alloc_phi(parent
, one
->target
, one
->size
);
258 add_instruction(&parent
->insns
, br
);
259 use_pseudo(phi
, add_pseudo(dominators
, phi
));
260 } END_FOR_EACH_PTR(parent
);
265 * We should probably sort the phi list just to make it easier to compare
266 * later for equality.
268 void rewrite_load_instruction(struct instruction
*insn
, struct pseudo_list
*dominators
)
273 * Check for somewhat common case of duplicate
276 new = first_pseudo(dominators
)->def
->src1
;
277 FOR_EACH_PTR(dominators
, phi
) {
278 if (new != phi
->def
->src1
)
280 } END_FOR_EACH_PTR(phi
);
283 * All the same pseudo - mark the phi-nodes unused
284 * and convert the load into a LNOP and replace the
287 FOR_EACH_PTR(dominators
, phi
) {
289 } END_FOR_EACH_PTR(phi
);
290 convert_load_instruction(insn
, new);
294 /* We leave symbol pseudos with a bogus usage list here */
295 if (insn
->src
->type
!= PSEUDO_SYM
)
296 kill_use(&insn
->src
);
297 insn
->opcode
= OP_PHI
;
298 insn
->phi_list
= dominators
;
301 static int find_dominating_stores(pseudo_t pseudo
, struct instruction
*insn
,
302 unsigned long generation
, int local
)
304 struct basic_block
*bb
= insn
->bb
;
305 struct instruction
*one
, *dom
= NULL
;
306 struct pseudo_list
*dominators
;
309 /* Unreachable load? Undo it */
311 insn
->opcode
= OP_LNOP
;
316 FOR_EACH_PTR(bb
->insns
, one
) {
320 dominance
= dominates(pseudo
, insn
, one
, local
);
322 /* Ignore partial load dominators */
323 if (one
->opcode
== OP_LOAD
)
333 } END_FOR_EACH_PTR(one
);
335 warning(pseudo
->sym
->pos
, "unable to find symbol read");
342 convert_load_instruction(insn
, dom
->target
);
346 /* Ok, go find the parents */
347 bb
->generation
= generation
;
350 if (!find_dominating_parents(pseudo
, insn
, bb
, generation
, &dominators
, local
, 1))
353 /* This happens with initial assignments to structures etc.. */
357 convert_load_instruction(insn
, value_pseudo(0));
362 * If we find just one dominating instruction, we
363 * can turn it into a direct thing. Otherwise we'll
364 * have to turn the load into a phi-node of the
367 rewrite_load_instruction(insn
, dominators
);
371 static void kill_store(struct instruction
*insn
)
375 insn
->opcode
= OP_SNOP
;
376 kill_use(&insn
->target
);
380 /* Kill a pseudo that is dead on exit from the bb */
381 static void kill_dead_stores(pseudo_t pseudo
, unsigned long generation
, struct basic_block
*bb
, int local
)
383 struct instruction
*insn
;
384 struct basic_block
*parent
;
386 if (bb
->generation
== generation
)
388 bb
->generation
= generation
;
389 FOR_EACH_PTR_REVERSE(bb
->insns
, insn
) {
390 int opcode
= insn
->opcode
;
392 if (opcode
!= OP_LOAD
&& opcode
!= OP_STORE
) {
395 if (opcode
== OP_CALL
)
399 if (insn
->src
== pseudo
) {
400 if (opcode
== OP_LOAD
)
407 if (insn
->src
->type
!= PSEUDO_SYM
)
409 } END_FOR_EACH_PTR_REVERSE(insn
);
411 FOR_EACH_PTR(bb
->parents
, parent
) {
412 struct basic_block
*child
;
413 FOR_EACH_PTR(parent
->children
, child
) {
414 if (child
&& child
!= bb
)
416 } END_FOR_EACH_PTR(child
);
417 kill_dead_stores(pseudo
, generation
, parent
, local
);
418 } END_FOR_EACH_PTR(parent
);
422 * This should see if the "insn" trivially dominates some previous store, and kill the
423 * store if unnecessary.
425 static void kill_dominated_stores(pseudo_t pseudo
, struct instruction
*insn
,
426 unsigned long generation
, struct basic_block
*bb
, int local
, int found
)
428 struct instruction
*one
;
429 struct basic_block
*parent
;
431 /* Unreachable store? Undo it */
436 if (bb
->generation
== generation
)
438 bb
->generation
= generation
;
439 FOR_EACH_PTR_REVERSE(bb
->insns
, one
) {
447 dominance
= dominates(pseudo
, insn
, one
, local
);
452 if (one
->opcode
== OP_LOAD
)
455 } END_FOR_EACH_PTR_REVERSE(one
);
458 warning(bb
->pos
, "Unable to find instruction");
462 FOR_EACH_PTR(bb
->parents
, parent
) {
463 struct basic_block
*child
;
464 FOR_EACH_PTR(parent
->children
, child
) {
465 if (child
&& child
!= bb
)
467 } END_FOR_EACH_PTR(child
);
468 kill_dominated_stores(pseudo
, insn
, generation
, parent
, local
, found
);
469 } END_FOR_EACH_PTR(parent
);
472 static void simplify_one_symbol(struct entrypoint
*ep
, struct symbol
*sym
)
474 pseudo_t pseudo
, src
, *pp
;
475 struct instruction
*def
;
477 int all
, stores
, complex;
479 /* Never used as a symbol? */
480 pseudo
= sym
->pseudo
;
484 /* We don't do coverage analysis of volatiles.. */
485 if (sym
->ctype
.modifiers
& MOD_VOLATILE
)
488 /* ..and symbols with external visibility need more care */
489 mod
= sym
->ctype
.modifiers
& (MOD_NONLOCAL
| MOD_STATIC
| MOD_ADDRESSABLE
);
491 goto external_visibility
;
496 FOR_EACH_PTR(pseudo
->users
, pp
) {
497 /* We know that the symbol-pseudo use is the "src" in the instruction */
498 struct instruction
*insn
= container(pp
, struct instruction
, src
);
500 switch (insn
->opcode
) {
510 mod
|= MOD_ADDRESSABLE
;
511 goto external_visibility
;
518 warning(sym
->pos
, "symbol '%s' pseudo used in unexpected way", show_ident(sym
->ident
));
520 complex |= insn
->offset
;
521 } END_FOR_EACH_PTR(pp
);
529 * Goodie, we have a single store (if even that) in the whole
530 * thing. Replace all loads with moves from the pseudo,
531 * replace the store with a def.
537 FOR_EACH_PTR(pseudo
->users
, pp
) {
538 struct instruction
*insn
= container(pp
, struct instruction
, src
);
539 if (insn
->opcode
== OP_LOAD
)
540 convert_load_instruction(insn
, src
);
541 } END_FOR_EACH_PTR(pp
);
543 /* Turn the store into a no-op */
551 FOR_EACH_PTR_REVERSE(pseudo
->users
, pp
) {
552 struct instruction
*insn
= container(pp
, struct instruction
, src
);
553 if (insn
->opcode
== OP_LOAD
)
554 all
&= find_dominating_stores(pseudo
, insn
, ++bb_generation
, !mod
);
555 } END_FOR_EACH_PTR_REVERSE(pp
);
557 /* If we converted all the loads, remove the stores. They are dead */
559 FOR_EACH_PTR(pseudo
->users
, pp
) {
560 struct instruction
*insn
= container(pp
, struct instruction
, src
);
561 if (insn
->opcode
== OP_STORE
)
563 } END_FOR_EACH_PTR(pp
);
566 * If we couldn't take the shortcut, see if we can at least kill some
569 FOR_EACH_PTR(pseudo
->users
, pp
) {
570 struct instruction
*insn
= container(pp
, struct instruction
, src
);
571 if (insn
->opcode
== OP_STORE
)
572 kill_dominated_stores(pseudo
, insn
, ++bb_generation
, insn
->bb
, !mod
, 0);
573 } END_FOR_EACH_PTR(pp
);
575 if (!(mod
& (MOD_NONLOCAL
| MOD_STATIC
))) {
576 struct basic_block
*bb
;
577 FOR_EACH_PTR(ep
->bbs
, bb
) {
579 kill_dead_stores(pseudo
, ++bb_generation
, bb
, !mod
);
580 } END_FOR_EACH_PTR(bb
);
587 void simplify_symbol_usage(struct entrypoint
*ep
)
591 FOR_EACH_PTR(ep
->accesses
, sym
) {
592 simplify_one_symbol(ep
, sym
);
593 } END_FOR_EACH_PTR(sym
);
596 static void mark_bb_reachable(struct basic_block
*bb
, unsigned long generation
)
598 struct basic_block
*child
;
600 if (bb
->generation
== generation
)
602 bb
->generation
= generation
;
603 FOR_EACH_PTR(bb
->children
, child
) {
604 mark_bb_reachable(child
, generation
);
605 } END_FOR_EACH_PTR(child
);
608 static void kill_defs(struct instruction
*insn
)
610 pseudo_t target
= insn
->target
;
612 if (!has_use_list(target
))
614 if (target
->def
!= insn
)
617 convert_instruction_target(insn
, VOID
);
620 void kill_bb(struct basic_block
*bb
)
622 struct instruction
*insn
;
623 struct basic_block
*child
, *parent
;
625 FOR_EACH_PTR(bb
->insns
, insn
) {
626 kill_instruction(insn
);
629 * We kill unreachable instructions even if they
630 * otherwise aren't "killable". Eg volatile loads
634 } END_FOR_EACH_PTR(insn
);
637 FOR_EACH_PTR(bb
->children
, child
) {
638 remove_bb_from_list(&child
->parents
, bb
, 0);
639 } END_FOR_EACH_PTR(child
);
642 FOR_EACH_PTR(bb
->parents
, parent
) {
643 remove_bb_from_list(&parent
->children
, bb
, 0);
644 } END_FOR_EACH_PTR(parent
);
648 static void kill_unreachable_bbs(struct entrypoint
*ep
)
650 struct basic_block
*bb
;
651 unsigned long generation
= ++bb_generation
;
653 mark_bb_reachable(ep
->entry
, generation
);
654 FOR_EACH_PTR(ep
->bbs
, bb
) {
655 if (bb
->generation
== generation
)
657 /* Mark it as being dead */
659 } END_FOR_EACH_PTR(bb
);
662 static int rewrite_parent_branch(struct basic_block
*bb
, struct basic_block
*old
, struct basic_block
*new)
664 struct instruction
*insn
= last_instruction(bb
->insns
);
669 /* Infinite loops: let's not "optimize" them.. */
673 switch (insn
->opcode
) {
675 rewrite_branch(bb
, &insn
->bb_true
, old
, new);
676 rewrite_branch(bb
, &insn
->bb_false
, old
, new);
678 /* Conditional branch to same target? */
679 if (insn
->bb_true
== insn
->bb_false
) {
680 remove_bb_from_list(&new->parents
, bb
, 1);
681 remove_bb_from_list(&bb
->children
, new, 1);
682 insn
->bb_false
= NULL
;
683 kill_use(&insn
->cond
);
687 struct multijmp
*jmp
;
688 FOR_EACH_PTR(insn
->multijmp_list
, jmp
) {
689 rewrite_branch(bb
, &jmp
->target
, old
, new);
690 } END_FOR_EACH_PTR(jmp
);
698 static struct basic_block
* rewrite_branch_bb(struct basic_block
*bb
, struct instruction
*br
)
700 struct basic_block
*parent
;
701 struct basic_block
*target
= br
->bb_true
;
702 struct basic_block
*false = br
->bb_false
;
704 if (target
&& false) {
705 pseudo_t cond
= br
->cond
;
706 if (cond
->type
!= PSEUDO_VAL
)
708 target
= cond
->value
? target
: false;
712 * We can't do FOR_EACH_PTR() here, because the parent list
713 * may change when we rewrite the parent.
715 while ((parent
= first_basic_block(bb
->parents
)) != NULL
) {
716 if (!rewrite_parent_branch(parent
, bb
, target
))
722 static void simplify_one_switch(struct basic_block
*bb
,
724 struct instruction
*insn
)
726 struct multijmp
*jmp
;
728 FOR_EACH_PTR(insn
->multijmp_list
, jmp
) {
730 if (jmp
->begin
> jmp
->end
)
732 if (val
>= jmp
->begin
&& val
<= jmp
->end
)
734 } END_FOR_EACH_PTR(jmp
);
735 warning(bb
->pos
, "Impossible case statement");
739 insert_branch(bb
, insn
, jmp
->target
);
742 static void simplify_switch(struct entrypoint
*ep
)
744 struct basic_block
*bb
;
746 FOR_EACH_PTR(ep
->bbs
, bb
) {
748 struct instruction
*insn
= last_instruction(bb
->insns
);
750 if (!insn
|| insn
->opcode
!= OP_SWITCH
)
752 pseudo
= insn
->target
;
753 if (pseudo
->type
== PSEUDO_VAL
)
754 simplify_one_switch(bb
, pseudo
->value
, insn
);
755 } END_FOR_EACH_PTR(bb
);
758 static void vrfy_bb_in_list(struct basic_block
*bb
, struct basic_block_list
*list
)
761 struct basic_block
*tmp
;
762 int no_bb_in_list
= 0;
764 FOR_EACH_PTR(list
, tmp
) {
767 } END_FOR_EACH_PTR(tmp
);
768 assert(no_bb_in_list
);
772 static void vrfy_parents(struct basic_block
*bb
)
774 struct basic_block
*tmp
;
775 FOR_EACH_PTR(bb
->parents
, tmp
) {
776 vrfy_bb_in_list(bb
, tmp
->children
);
777 } END_FOR_EACH_PTR(tmp
);
780 static void vrfy_children(struct basic_block
*bb
)
782 struct basic_block
*tmp
;
783 struct instruction
*br
= last_instruction(bb
->insns
);
786 assert(!bb
->children
);
789 switch (br
->opcode
) {
790 struct multijmp
*jmp
;
792 vrfy_bb_in_list(br
->bb_true
, bb
->children
);
793 vrfy_bb_in_list(br
->bb_false
, bb
->children
);
796 case OP_COMPUTEDGOTO
:
797 FOR_EACH_PTR(br
->multijmp_list
, jmp
) {
798 vrfy_bb_in_list(jmp
->target
, bb
->children
);
799 } END_FOR_EACH_PTR(jmp
);
805 FOR_EACH_PTR(bb
->children
, tmp
) {
806 vrfy_bb_in_list(bb
, tmp
->parents
);
807 } END_FOR_EACH_PTR(tmp
);
810 static void vrfy_bb_flow(struct basic_block
*bb
)
816 void vrfy_flow(struct entrypoint
*ep
)
818 struct basic_block
*bb
;
819 struct basic_block
*entry
= ep
->entry
;
821 FOR_EACH_PTR(ep
->bbs
, bb
) {
825 } END_FOR_EACH_PTR(bb
);
829 void simplify_flow(struct entrypoint
*ep
)
831 simplify_phi_nodes(ep
);
833 kill_unreachable_bbs(ep
);
836 void pack_basic_blocks(struct entrypoint
*ep
)
838 struct basic_block
*bb
;
840 /* See if we can merge a bb into another one.. */
841 FOR_EACH_PTR(ep
->bbs
, bb
) {
842 struct instruction
*first
, *insn
;
843 struct basic_block
*parent
, *child
, *last
;
845 if (!bb_reachable(bb
))
851 FOR_EACH_PTR(bb
->insns
, first
) {
854 switch (first
->opcode
) {
855 case OP_NOP
: case OP_LNOP
: case OP_SNOP
:
858 struct basic_block
*replace
;
859 replace
= rewrite_branch_bb(bb
, first
);
871 } END_FOR_EACH_PTR(first
);
878 * See if we only have one parent..
881 FOR_EACH_PTR(bb
->parents
, parent
) {
888 } END_FOR_EACH_PTR(parent
);
891 if (!parent
|| parent
== bb
)
895 * Goodie. See if the parent can merge..
897 FOR_EACH_PTR(parent
->children
, child
) {
900 } END_FOR_EACH_PTR(child
);
905 repeat_phase
|= REPEAT_CSE
;
908 * But don't allow phi-source merges after this.
909 * FIXME, FIXME! I really need to think about this.
910 * Is it true? I think it's ok to merge phi-sources,
911 * as long as we keep their relative position in
912 * the stream. It's the re-ordering we can't have.
915 merge_phi_sources
= 0;
917 parent
->children
= bb
->children
;
921 FOR_EACH_PTR(parent
->children
, child
) {
922 replace_bb_in_list(&child
->parents
, bb
, parent
, 0);
923 } END_FOR_EACH_PTR(child
);
925 delete_last_instruction(&parent
->insns
);
926 FOR_EACH_PTR(bb
->insns
, insn
) {
928 assert(insn
->bb
== bb
);
931 add_instruction(&parent
->insns
, insn
);
932 } END_FOR_EACH_PTR(insn
);
937 } END_FOR_EACH_PTR(bb
);