aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/flow.c
diff options
authorLinus Torvalds <torvalds@ppc970.osdl.org>2004-11-24 11:41:31 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 21:04:43 -0700
commite4fb90fb0c66b034ba45671a32616c208ccd478a (patch)
tree8db644a14d6a6061b2d1bbf2f04cb53ef48c11ff /flow.c
parentffd3283cdce661b220c0393020a8197ac1a9d310 (diff)
downloadsparse-dev-e4fb90fb0c66b034ba45671a32616c208ccd478a.tar.gz
Teach basic block packing about deleted phi-nodes and no-ops.
If a basic block is a source of phi-nodes, but they have all been cleared, we can just ignore them. Similarly, if a basic block is only a series of no-ops followed by a branch, we can still do the branch rewrite.
Diffstat (limited to 'flow.c')
-rw-r--r--flow.c31
1 files changed, 24 insertions, 7 deletions
diff --git a/flow.c b/flow.c
index a7fb052d..8b27c290 100644
--- a/flow.c
+++ b/flow.c
@@ -621,6 +621,8 @@ static int rewrite_parent_branch(struct basic_block *bb, struct basic_block *old
case OP_BR:
rewrite_branch(bb, &insn->bb_true, old, new);
rewrite_branch(bb, &insn->bb_false, old, new);
+ if (insn->bb_true == insn->bb_false)
+ insn->bb_false = NULL;
return 1;
case OP_SWITCH: {
struct multijmp *jmp;
@@ -726,20 +728,35 @@ void pack_basic_blocks(struct entrypoint *ep)
/*
* If this block has a phi-node associated with it,
*/
- if (bb->phinodes)
- continue;
+ if (bb->phinodes) {
+ struct phi *phi;
+ FOR_EACH_PTR(bb->phinodes, phi) {
+ if (phi->source)
+ goto no_merge;
+ } END_FOR_EACH_PTR(phi);
+ }
/*
* Just a branch?
*/
- first = first_instruction(bb->insns);
- if (first && first->opcode == OP_BR) {
- if (rewrite_branch_bb(bb, first)) {
- kill_bb(bb);
+ FOR_EACH_PTR(bb->insns, first) {
+ if (!first->bb)
continue;
+ switch (first->opcode) {
+ case OP_NOP: case OP_LNOP: case OP_SNOP:
+ continue;
+ case OP_BR:
+ if (rewrite_branch_bb(bb, first)) {
+ kill_bb(bb);
+ goto no_merge;
+ }
+ /* fallthrough */
+ default:
+ goto out;
}
- }
+ } END_FOR_EACH_PTR(first);
+out:
if (ep->entry == bb)
continue;