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 struct basic_block
*tmp
;
38 FOR_EACH_PTR(new->parents
, tmp
) {
40 *THIS_ADDRESS(tmp
) = bb
;
41 } END_FOR_EACH_PTR(tmp
);
43 FOR_EACH_PTR(bb
->children
, tmp
) {
45 *THIS_ADDRESS(tmp
) = new;
46 } END_FOR_EACH_PTR(tmp
);
50 * Return the known truth value of a pseudo, or -1 if
53 static int pseudo_truth_value(pseudo_t pseudo
)
55 switch (pseudo
->type
) {
57 return !!pseudo
->value
;
60 struct instruction
*insn
= pseudo
->def
;
61 if (insn
->opcode
== OP_SETVAL
&& insn
->target
== pseudo
) {
62 struct expression
*expr
= insn
->val
;
64 /* A symbol address is always considered true.. */
67 if (expr
->type
== EXPR_VALUE
)
78 static void try_to_simplify_bb(struct entrypoint
*ep
, struct basic_block
*bb
,
79 struct instruction
*first
, struct instruction
*second
)
83 FOR_EACH_PTR(first
->phi_list
, phi
) {
84 struct instruction
*def
= phi
->def
;
85 struct basic_block
*source
= def
->bb
, *target
;
86 pseudo_t pseudo
= def
->src1
;
87 struct instruction
*br
;
90 if (!pseudo
|| !source
)
92 br
= last_instruction(source
->insns
);
95 if (br
->opcode
!= OP_BR
)
98 true = pseudo_truth_value(pseudo
);
101 target
= true ? second
->bb_true
: second
->bb_false
;
102 rewrite_branch(source
, &br
->bb_true
, bb
, target
);
103 rewrite_branch(source
, &br
->bb_false
, bb
, target
);
104 } END_FOR_EACH_PTR(phi
);
107 static inline int linearize_insn_list(struct instruction_list
*list
, struct instruction
**arr
, int nr
)
109 return linearize_ptr_list((struct ptr_list
*)list
, (void **)arr
, nr
);
112 static void simplify_phi_nodes(struct entrypoint
*ep
)
114 struct basic_block
*bb
;
116 FOR_EACH_PTR(ep
->bbs
, bb
) {
117 struct instruction
*insns
[2], *first
, *second
;
119 if (linearize_insn_list(bb
->insns
, insns
, 2) < 2)
125 if (first
->opcode
!= OP_PHI
)
127 if (second
->opcode
!= OP_BR
)
129 if (first
->target
!= second
->cond
)
131 try_to_simplify_bb(ep
, bb
, first
, second
);
132 } END_FOR_EACH_PTR(bb
);
135 static inline void concat_user_list(struct pseudo_ptr_list
*src
, struct pseudo_ptr_list
**dst
)
137 concat_ptr_list((struct ptr_list
*)src
, (struct ptr_list
**)dst
);
140 void convert_instruction_target(struct instruction
*insn
, pseudo_t src
)
142 pseudo_t target
, *usep
;
145 * Go through the "insn->users" list and replace them all..
147 target
= insn
->target
;
150 FOR_EACH_PTR(target
->users
, usep
) {
152 assert(*usep
== target
);
155 } END_FOR_EACH_PTR(usep
);
156 concat_user_list(target
->users
, &src
->users
);
157 target
->users
= NULL
;
160 static void convert_load_insn(struct instruction
*insn
, pseudo_t src
)
162 convert_instruction_target(insn
, src
);
163 /* Turn the load into a no-op */
164 insn
->opcode
= OP_LNOP
;
167 static int overlapping_memop(struct instruction
*a
, struct instruction
*b
)
169 unsigned int a_start
= (a
->offset
<< 3) + a
->type
->bit_offset
;
170 unsigned int b_start
= (b
->offset
<< 3) + b
->type
->bit_offset
;
171 unsigned int a_size
= a
->type
->bit_size
;
172 unsigned int b_size
= b
->type
->bit_size
;
174 if (a_size
+ a_start
<= b_start
)
176 if (b_size
+ b_start
<= a_start
)
181 static inline int same_memop(struct instruction
*a
, struct instruction
*b
)
183 return a
->offset
== b
->offset
&&
184 a
->type
->bit_size
== b
->type
->bit_size
&&
185 a
->type
->bit_offset
== b
->type
->bit_offset
;
189 * Return 1 if "one" dominates the access to 'pseudo'
192 * Return 0 if it doesn't, and -1 if you don't know.
194 static int dominates(pseudo_t pseudo
, struct instruction
*insn
,
195 struct instruction
*one
, int local
)
197 int opcode
= one
->opcode
;
199 if (opcode
== OP_CALL
)
200 return local
? 0 : -1;
201 if (opcode
!= OP_LOAD
&& opcode
!= OP_STORE
)
203 if (one
->src
!= pseudo
) {
206 /* We don't think two explicitly different symbols ever alias */
207 if (one
->src
->type
== PSEUDO_SYM
)
209 /* We could try to do some alias analysis here */
212 if (!same_memop(insn
, one
)) {
213 if (one
->opcode
== OP_LOAD
)
215 if (!overlapping_memop(insn
, one
))
222 static int find_dominating_parents(pseudo_t pseudo
, struct instruction
*insn
,
223 struct basic_block
*bb
, unsigned long generation
, struct pseudo_list
**dominators
,
224 int local
, int loads
)
226 struct basic_block
*parent
;
228 if (bb_list_size(bb
->parents
) > 1)
230 FOR_EACH_PTR(bb
->parents
, parent
) {
231 struct instruction
*one
;
232 struct instruction
*br
;
235 FOR_EACH_PTR_REVERSE(parent
->insns
, one
) {
239 dominance
= dominates(pseudo
, insn
, one
, local
);
241 if (one
->opcode
== OP_LOAD
)
247 if (one
->opcode
== OP_LOAD
&& !loads
)
249 goto found_dominator
;
250 } END_FOR_EACH_PTR_REVERSE(one
);
252 if (parent
->generation
== generation
)
254 parent
->generation
= generation
;
256 if (!find_dominating_parents(pseudo
, insn
, parent
, generation
, dominators
, local
, loads
))
261 br
= delete_last_instruction(&parent
->insns
);
262 phi
= alloc_phi(parent
, one
->target
);
263 add_instruction(&parent
->insns
, br
);
264 use_pseudo(phi
, add_pseudo(dominators
, phi
));
265 } END_FOR_EACH_PTR(parent
);
270 * We should probably sort the phi list just to make it easier to compare
271 * later for equality.
273 static void rewrite_load_instruction(struct instruction
*insn
, struct pseudo_list
*dominators
)
278 * Check for somewhat common case of duplicate
281 new = first_pseudo(dominators
)->def
->src1
;
282 FOR_EACH_PTR(dominators
, phi
) {
283 if (new != phi
->def
->src1
)
285 } END_FOR_EACH_PTR(phi
);
288 * All the same pseudo - mark the phi-nodes unused
289 * and convert the load into a LNOP and replace the
292 FOR_EACH_PTR(dominators
, phi
) {
294 } END_FOR_EACH_PTR(phi
);
295 convert_load_insn(insn
, new);
299 new = alloc_pseudo(insn
);
300 convert_load_insn(insn
, new);
303 * FIXME! This is dubious. We should probably allocate a new
304 * instruction instead of re-using the OP_LOAD instruction.
305 * Re-use of the instruction makes the usage list suspect.
307 * It should be ok, because the only usage of the OP_LOAD
308 * is the symbol pseudo, and we should never follow that
309 * list _except_ for exactly the dominant instruction list
310 * generation (and then we always check the opcode).
312 insn
->opcode
= OP_PHI
;
314 insn
->phi_list
= dominators
;
318 static int find_dominating_stores(pseudo_t pseudo
, struct instruction
*insn
,
319 unsigned long generation
, int local
)
321 struct basic_block
*bb
= insn
->bb
;
322 struct instruction
*one
, *dom
= NULL
;
323 struct pseudo_list
*dominators
;
326 /* Unreachable load? Undo it */
328 insn
->opcode
= OP_LNOP
;
333 FOR_EACH_PTR(bb
->insns
, one
) {
337 dominance
= dominates(pseudo
, insn
, one
, local
);
339 /* Ignore partial load dominators */
340 if (one
->opcode
== OP_LOAD
)
350 } END_FOR_EACH_PTR(one
);
352 warning(pseudo
->sym
->pos
, "unable to find symbol read");
359 convert_load_insn(insn
, dom
->target
);
363 /* Ok, go find the parents */
364 bb
->generation
= generation
;
367 if (!find_dominating_parents(pseudo
, insn
, bb
, generation
, &dominators
, local
, 1))
370 /* This happens with initial assignments to structures etc.. */
374 convert_load_insn(insn
, value_pseudo(0));
379 * If we find just one dominating instruction, we
380 * can turn it into a direct thing. Otherwise we'll
381 * have to turn the load into a phi-node of the
384 rewrite_load_instruction(insn
, dominators
);
388 /* Kill a pseudo that is dead on exit from the bb */
389 static void kill_dead_stores(pseudo_t pseudo
, unsigned long generation
, struct basic_block
*bb
, int local
)
391 struct instruction
*insn
;
392 struct basic_block
*parent
;
394 if (bb
->generation
== generation
)
396 bb
->generation
= generation
;
397 FOR_EACH_PTR_REVERSE(bb
->insns
, insn
) {
398 int opcode
= insn
->opcode
;
400 if (opcode
!= OP_LOAD
&& opcode
!= OP_STORE
) {
403 if (opcode
== OP_CALL
)
407 if (insn
->src
== pseudo
) {
408 if (opcode
== OP_LOAD
)
410 insn
->opcode
= OP_SNOP
;
415 if (insn
->src
->type
!= PSEUDO_SYM
)
417 } END_FOR_EACH_PTR_REVERSE(insn
);
419 FOR_EACH_PTR(bb
->parents
, parent
) {
420 struct basic_block
*child
;
421 FOR_EACH_PTR(parent
->children
, child
) {
422 if (child
&& child
!= bb
)
424 } END_FOR_EACH_PTR(child
);
425 kill_dead_stores(pseudo
, generation
, parent
, local
);
426 } END_FOR_EACH_PTR(parent
);
430 * This should see if the "insn" trivially dominates some previous store, and kill the
431 * store if unnecessary.
433 static void kill_dominated_stores(pseudo_t pseudo
, struct instruction
*insn
,
434 unsigned long generation
, struct basic_block
*bb
, int local
, int found
)
436 struct instruction
*one
;
437 struct basic_block
*parent
;
439 /* Unreachable store? Undo it */
441 insn
->opcode
= OP_SNOP
;
444 if (bb
->generation
== generation
)
446 bb
->generation
= generation
;
447 FOR_EACH_PTR_REVERSE(bb
->insns
, one
) {
455 dominance
= dominates(pseudo
, insn
, one
, local
);
460 if (one
->opcode
== OP_LOAD
)
462 one
->opcode
= OP_SNOP
;
463 } END_FOR_EACH_PTR_REVERSE(one
);
466 warning(bb
->pos
, "Unable to find instruction");
470 FOR_EACH_PTR(bb
->parents
, parent
) {
471 struct basic_block
*child
;
472 FOR_EACH_PTR(parent
->children
, child
) {
473 if (child
&& child
!= bb
)
475 } END_FOR_EACH_PTR(child
);
476 kill_dominated_stores(pseudo
, insn
, generation
, parent
, local
, found
);
477 } END_FOR_EACH_PTR(parent
);
480 static void simplify_one_symbol(struct entrypoint
*ep
, struct symbol
*sym
)
482 pseudo_t pseudo
, src
, *pp
;
483 struct instruction
*def
;
485 int all
, stores
, complex;
487 /* Never used as a symbol? */
488 pseudo
= sym
->pseudo
;
492 /* We don't do coverage analysis of volatiles.. */
493 if (sym
->ctype
.modifiers
& MOD_VOLATILE
)
496 /* ..and symbols with external visibility need more care */
497 mod
= sym
->ctype
.modifiers
& (MOD_EXTERN
| MOD_STATIC
| MOD_ADDRESSABLE
);
499 goto external_visibility
;
504 FOR_EACH_PTR(pseudo
->users
, pp
) {
505 /* We know that the symbol-pseudo use is the "src" in the instruction */
506 struct instruction
*insn
= container(pp
, struct instruction
, src
);
508 switch (insn
->opcode
) {
518 mod
|= MOD_ADDRESSABLE
;
519 goto external_visibility
;
521 warning(sym
->pos
, "symbol '%s' pseudo used in unexpected way", show_ident(sym
->ident
));
523 complex |= insn
->offset
;
524 } END_FOR_EACH_PTR(pp
);
532 * Goodie, we have a single store (if even that) in the whole
533 * thing. Replace all loads with moves from the pseudo,
534 * replace the store with a def.
540 /* Turn the store into a no-op */
541 def
->opcode
= OP_SNOP
;
543 FOR_EACH_PTR(pseudo
->users
, pp
) {
544 struct instruction
*insn
= container(pp
, struct instruction
, src
);
545 if (insn
->opcode
== OP_LOAD
)
546 convert_load_insn(insn
, src
);
547 } END_FOR_EACH_PTR(pp
);
554 FOR_EACH_PTR_REVERSE(pseudo
->users
, pp
) {
555 struct instruction
*insn
= container(pp
, struct instruction
, src
);
556 if (insn
->opcode
== OP_LOAD
)
557 all
&= find_dominating_stores(pseudo
, insn
, ++bb_generation
, !mod
);
558 } END_FOR_EACH_PTR_REVERSE(pp
);
560 /* If we converted all the loads, remove the stores. They are dead */
562 FOR_EACH_PTR(pseudo
->users
, pp
) {
563 struct instruction
*insn
= container(pp
, struct instruction
, src
);
564 if (insn
->opcode
== OP_STORE
)
565 insn
->opcode
= OP_SNOP
;
566 } END_FOR_EACH_PTR(pp
);
569 * If we couldn't take the shortcut, see if we can at least kill some
572 FOR_EACH_PTR(pseudo
->users
, pp
) {
573 struct instruction
*insn
= container(pp
, struct instruction
, src
);
574 if (insn
->opcode
== OP_STORE
)
575 kill_dominated_stores(pseudo
, insn
, ++bb_generation
, insn
->bb
, !mod
, 0);
576 } END_FOR_EACH_PTR(pp
);
578 if (!(mod
& (MOD_EXTERN
| MOD_STATIC
))) {
579 struct basic_block
*bb
;
580 FOR_EACH_PTR(ep
->bbs
, bb
) {
582 kill_dead_stores(pseudo
, ++bb_generation
, bb
, !mod
);
583 } END_FOR_EACH_PTR(bb
);
590 void simplify_symbol_usage(struct entrypoint
*ep
)
594 FOR_EACH_PTR(ep
->accesses
, sym
) {
595 simplify_one_symbol(ep
, sym
);
597 } END_FOR_EACH_PTR(sym
);
600 static void mark_bb_reachable(struct basic_block
*bb
, unsigned long generation
)
602 struct basic_block
*child
;
604 if (bb
->generation
== generation
)
606 bb
->generation
= generation
;
607 FOR_EACH_PTR(bb
->children
, child
) {
608 mark_bb_reachable(child
, generation
);
609 } END_FOR_EACH_PTR(child
);
612 static void kill_defs(struct instruction
*insn
)
614 pseudo_t target
= insn
->target
;
616 if (!target
|| target
->def
!= insn
)
619 switch (target
->type
) {
622 convert_instruction_target(insn
, VOID
);
626 void kill_bb(struct basic_block
*bb
)
628 struct instruction
*insn
;
629 struct basic_block
*child
, *parent
;
631 FOR_EACH_PTR(bb
->insns
, insn
) {
632 kill_instruction(insn
);
635 * We kill unreachable instructions even if they
636 * otherwise aren't "killable". Eg volatile loads
640 } END_FOR_EACH_PTR(insn
);
643 FOR_EACH_PTR(bb
->children
, child
) {
644 remove_bb_from_list(&child
->parents
, bb
);
645 } END_FOR_EACH_PTR(child
);
648 FOR_EACH_PTR(bb
->parents
, parent
) {
649 remove_bb_from_list(&parent
->children
, bb
);
650 } END_FOR_EACH_PTR(parent
);
654 static void kill_unreachable_bbs(struct entrypoint
*ep
)
656 struct basic_block
*bb
;
657 unsigned long generation
= ++bb_generation
;
659 mark_bb_reachable(ep
->entry
, generation
);
660 FOR_EACH_PTR(ep
->bbs
, bb
) {
661 if (bb
->generation
== generation
)
663 /* Mark it as being dead */
665 } END_FOR_EACH_PTR(bb
);
668 static int rewrite_parent_branch(struct basic_block
*bb
, struct basic_block
*old
, struct basic_block
*new)
670 struct instruction
*insn
= last_instruction(bb
->insns
);
674 switch (insn
->opcode
) {
676 rewrite_branch(bb
, &insn
->bb_true
, old
, new);
677 rewrite_branch(bb
, &insn
->bb_false
, old
, new);
678 if (insn
->bb_true
== insn
->bb_false
)
679 insn
->bb_false
= NULL
;
682 struct multijmp
*jmp
;
683 FOR_EACH_PTR(insn
->multijmp_list
, jmp
) {
684 rewrite_branch(bb
, &jmp
->target
, old
, new);
685 } END_FOR_EACH_PTR(jmp
);
693 static struct basic_block
* rewrite_branch_bb(struct basic_block
*bb
, struct instruction
*br
)
695 struct basic_block
*success
;
696 struct basic_block
*parent
;
697 struct basic_block
*target
= br
->bb_true
;
698 struct basic_block
*false = br
->bb_false
;
700 if (target
&& false) {
701 pseudo_t cond
= br
->cond
;
702 if (cond
->type
!= PSEUDO_VAL
)
704 target
= cond
->value
? target
: false;
707 target
= target
? : false;
709 FOR_EACH_PTR(bb
->parents
, parent
) {
710 if (!rewrite_parent_branch(parent
, bb
, target
))
712 } END_FOR_EACH_PTR(parent
);
716 static void simplify_one_switch(struct basic_block
*bb
,
718 struct instruction
*insn
)
720 struct multijmp
*jmp
;
722 FOR_EACH_PTR(insn
->multijmp_list
, jmp
) {
724 if (jmp
->begin
> jmp
->end
)
726 if (val
>= jmp
->begin
&& val
<= jmp
->end
)
728 } END_FOR_EACH_PTR(jmp
);
729 warning(bb
->pos
, "Impossible case statement");
733 insert_branch(bb
, insn
, jmp
->target
);
736 static void simplify_switch(struct entrypoint
*ep
)
738 struct basic_block
*bb
;
740 FOR_EACH_PTR(ep
->bbs
, bb
) {
742 struct instruction
*insn
= last_instruction(bb
->insns
);
744 if (!insn
|| insn
->opcode
!= OP_SWITCH
)
746 pseudo
= insn
->target
;
747 if (pseudo
->type
== PSEUDO_VAL
)
748 simplify_one_switch(bb
, pseudo
->value
, insn
);
749 } END_FOR_EACH_PTR(bb
);
752 void simplify_flow(struct entrypoint
*ep
)
754 simplify_phi_nodes(ep
);
756 kill_unreachable_bbs(ep
);
759 void pack_basic_blocks(struct entrypoint
*ep
)
761 struct basic_block
*bb
;
763 /* See if we can merge a bb into another one.. */
764 FOR_EACH_PTR(ep
->bbs
, bb
) {
765 struct instruction
*first
;
766 struct basic_block
*parent
, *child
, *last
;
768 if (!bb_reachable(bb
))
774 FOR_EACH_PTR(bb
->insns
, first
) {
777 switch (first
->opcode
) {
778 case OP_NOP
: case OP_LNOP
: case OP_SNOP
:
781 struct basic_block
*replace
;
782 replace
= rewrite_branch_bb(bb
, first
);
794 } END_FOR_EACH_PTR(first
);
801 * See if we only have one parent..
804 FOR_EACH_PTR(bb
->parents
, parent
) {
811 } END_FOR_EACH_PTR(parent
);
814 if (!parent
|| parent
== bb
)
818 * Goodie. See if the parent can merge..
820 FOR_EACH_PTR(parent
->children
, child
) {
823 } END_FOR_EACH_PTR(child
);
825 parent
->children
= bb
->children
;
826 FOR_EACH_PTR(bb
->children
, child
) {
827 struct basic_block
*p
;
828 FOR_EACH_PTR(child
->parents
, p
) {
831 *THIS_ADDRESS(p
) = parent
;
832 } END_FOR_EACH_PTR(p
);
833 } END_FOR_EACH_PTR(child
);
835 delete_last_instruction(&parent
->insns
);
836 concat_instruction_list(bb
->insns
, &parent
->insns
);
842 } END_FOR_EACH_PTR(bb
);