aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2017-01-04 04:03:19 +0100
committerChristopher Li <sparse@chrisli.org>2017-02-13 09:34:45 +0800
commitc9d08bf0047b4a1ea9fa1f201c6495bb2d81b541 (patch)
treeccca108d0bb37526b6e018c294dba525b7e277ea
parent0ee83ccffa3437fa97058c7cdc28961f59476c9d (diff)
downloadsparse-dev-c9d08bf0047b4a1ea9fa1f201c6495bb2d81b541.tar.gz
fix superfluous phisrc
In some case more phisrc are created than expected. For example, on the following code: static int foo(int a, int b) { int i, x = 0; switch (a) { case 0: i = 0; break; case 1: i = 1; break; default: i = -1; break; } if (b) x = i; return x; } test-linearize returns something like: foo: .L0: <entry-point> phisrc.32 %phi2(x) <- $0 phisrc.32 %phi3(x) <- $0 phisrc.32 %phi4(x) <- $0 switch %arg1, 0 -> .L2, 1 -> .L3, default -> .L4 .L2: phisrc.32 %phi6(i) <- $0 br .L1 .L3: phisrc.32 %phi7(i) <- $1 br .L1 .L4: phisrc.32 %phi8(i) <- $0xffffffff br .L1 .L1: br %arg2, .L5, .L6 .L5: phi.32 %r3 <- %phi6(i), %phi7(i), %phi8(i) phisrc.32 %phi5(x) <- %r3 br .L6 .L6: phi.32 %r4 <- %phi2(x), %phi3(x), %phi4(x), %phi5(x) ret.32 %r4 where we can notice that %phi2, %phi3 and %phi4 in .L0 and .L6 are completly redundant, only one of them is needed. This also violates the usual semantic of phi-nodes: one phi for each parent bb. There is as much %phi such created as there is cases in the switch statement and the same problem also occurs with an if-else and 2 %phis. Whats' happening is the following: - find_dominating_parents() search dominators for .L6 - try first parent: .L1, find nothing, thus recurses - .L1 has 3 parents (the three cases): .L2, .L3, .L4 - each of them has .L0 as dominator, it's recorded as such but three times The problem is fixed by checking the dominators list and refusing to create more than one phisrc in the same basic block. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com> Signed-off-by: Christopher Li <sparse@chrisli.org>
-rw-r--r--flow.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/flow.c b/flow.c
index 7db9548f..d8e253b1 100644
--- a/flow.c
+++ b/flow.c
@@ -316,6 +316,17 @@ int dominates(pseudo_t pseudo, struct instruction *insn, struct instruction *dom
return 1;
}
+static int phisrc_in_bb(struct pseudo_list *list, struct basic_block *bb)
+{
+ pseudo_t p;
+ FOR_EACH_PTR(list, p) {
+ if (p->def->bb == bb)
+ return 1;
+ } END_FOR_EACH_PTR(p);
+
+ return 0;
+}
+
static int find_dominating_parents(pseudo_t pseudo, struct instruction *insn,
struct basic_block *bb, unsigned long generation, struct pseudo_list **dominators,
int local, int loads)
@@ -358,6 +369,8 @@ no_dominance:
continue;
found_dominator:
+ if (dominators && phisrc_in_bb(*dominators, parent))
+ continue;
br = delete_last_instruction(&parent->insns);
phi = alloc_phi(parent, one->target, one->size);
phi->ident = phi->ident ? : pseudo->ident;