aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linearize.c
diff options
authorChristopher Li <sparse@chrisli.org>2004-04-16 12:45:25 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 21:01:34 -0700
commit36e42c3abe2e28974cc421fa1498511e7c6f8ee9 (patch)
tree49841b66afecf7edb9a27e41da4f61a18f1aace3 /linearize.c
parent6af6fb881bcc8bad6bd2b348eab84632604f5200 (diff)
downloadsparse-dev-36e42c3abe2e28974cc421fa1498511e7c6f8ee9.tar.gz
[PATCH] pack basic blocks
I figured out that I can unify the two case that need to merge the basic block. By doing that we avoid the need to modify the phi instructions. I also changed some macros in lib.h into inline functions for better type checking.
Diffstat (limited to 'linearize.c')
-rw-r--r--linearize.c71
1 files changed, 33 insertions, 38 deletions
diff --git a/linearize.c b/linearize.c
index 4ce14c04..f53f821c 100644
--- a/linearize.c
+++ b/linearize.c
@@ -903,52 +903,47 @@ void remove_unreachable_bbs(struct basic_block_list **bblist)
void pack_basic_blocks(struct basic_block_list **bblist)
{
- struct basic_block *child, *bb, *parent;
+ struct basic_block *bb;
struct list_iterator iterator;
- struct terminator_iterator term;
- struct instruction *jmp;
remove_unreachable_bbs(bblist);
init_bb_iterator(bblist, &iterator, 0);
while((bb=next_basic_block(&iterator))) {
- if (is_branch_goto(jmp=first_instruction(bb->insns))) {
- /*
- * This is an empty goto block. Transfer the parents' terminator
- * to target directly.
- */
- struct list_iterator it_parents;
- struct basic_block *target;
-
- target = jmp->bb_true ? jmp->bb_true : jmp->bb_false;
- replace_basic_block_list(&target->parents, bb, NULL);
- init_bb_iterator(&bb->parents, &it_parents, 0);
- while((parent=next_basic_block(&it_parents))) {
- init_terminator_iterator(last_instruction(parent->insns), &term);
- while ((child=next_terminator_bb(&term))) {
- if (child == bb) {
- replace_terminator_bb(&term, target);
- add_bb(&target->parents, parent);
- }
+ struct list_iterator it_parents;
+ struct terminator_iterator term;
+ struct instruction *jmp;
+ struct basic_block *target, *sibling, *parent;
+
+ if (!is_branch_goto(jmp=last_instruction(bb->insns)))
+ continue;
+
+ target = jmp->bb_true ? jmp->bb_true : jmp->bb_false;
+ if (target == bb)
+ continue;
+ if (bb_list_size(target->parents) != 1 && jmp != first_instruction(bb->insns))
+ continue;
+
+ /* Transfer the parents' terminator to target directly. */
+ replace_basic_block_list(&target->parents, bb, NULL);
+ init_bb_iterator(&bb->parents, &it_parents, 0);
+ while((parent=next_basic_block(&it_parents))) {
+ init_terminator_iterator(last_instruction(parent->insns), &term);
+ while ((sibling=next_terminator_bb(&term))) {
+ if (sibling == bb) {
+ replace_terminator_bb(&term, target);
+ add_bb(&target->parents, parent);
}
}
- delete_iterator(&iterator);
- continue;
- }
-
- if (bb_list_size(bb->parents)!=1)
- continue;
- parent = first_basic_block(bb->parents);
- if (parent!=bb && is_branch_goto(last_instruction(parent->insns))) {
- /*
- * Combine this block with the parent.
- */
- delete_last_instruction(&parent->insns);
- concat_instruction_list(bb->insns, &parent->insns);
- init_terminator_iterator(last_instruction(bb->insns), &term);
- while ((child=next_terminator_bb(&term)))
- replace_basic_block_list(&child->parents, bb, parent);
- delete_iterator(&iterator);
}
+
+ /* Move the instructions to the target block. */
+ delete_last_instruction(&bb->insns);
+ if (bb->insns) {
+ concat_instruction_list(target->insns, &bb->insns);
+ free_instruction_list(&target->insns);
+ target->insns = bb->insns;
+ }
+ delete_iterator(&iterator);
}
}