aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cse.c6
-rw-r--r--flow.c18
-rw-r--r--lib.h2
-rw-r--r--linearize.c11
4 files changed, 29 insertions, 8 deletions
diff --git a/cse.c b/cse.c
index 4c91e56..a35177e 100644
--- a/cse.c
+++ b/cse.c
@@ -22,7 +22,7 @@ static struct instruction_list *insn_hash_table[INSN_HASH_SIZE];
#define hashval(x) ((unsigned long)(x))
-int repeat_phase;
+int repeat_phase, merge_phi_sources;
static int phi_compare(pseudo_t phi1, pseudo_t phi2)
{
@@ -209,6 +209,10 @@ static int insn_compare(const void *_i1, const void *_i2)
return i1->src1 < i2->src1 ? -1 : 1;
if (i1->bb != i2->bb)
return i1->bb < i2->bb ? -1 : 1;
+ if (!merge_phi_sources) {
+ if (i1 != i2)
+ return i1 < i2 ? -1 : 1;
+ }
break;
default:
diff --git a/flow.c b/flow.c
index 564391f..ac6ea27 100644
--- a/flow.c
+++ b/flow.c
@@ -32,6 +32,8 @@ static void rewrite_branch(struct basic_block *bb,
if (*ptr != old)
return;
+ /* We might find new if-conversions or non-dominating CSEs */
+ repeat_phase |= REPEAT_CSE;
*ptr = new;
replace_bb_in_list(&bb->children, old, new, 1);
remove_bb_from_list(&old->parents, bb, 1);
@@ -814,6 +816,21 @@ out:
goto no_merge;
} END_FOR_EACH_PTR(child);
+ /*
+ * Merge the two.
+ */
+ repeat_phase |= REPEAT_CSE;
+
+ /*
+ * But don't allow phi-source merges after this.
+ * FIXME, FIXME! I really need to think about this.
+ * Is it true? I think it's ok to merge phi-sources,
+ * as long as we keep their relative position in
+ * the stream. It's the re-ordering we can't have.
+ * I think.
+ */
+ merge_phi_sources = 0;
+
parent->children = bb->children;
FOR_EACH_PTR(bb->children, child) {
struct basic_block *p;
@@ -823,6 +840,7 @@ out:
*THIS_ADDRESS(p) = parent;
} END_FOR_EACH_PTR(p);
} END_FOR_EACH_PTR(child);
+ bb->children = NULL;
delete_last_instruction(&parent->insns);
FOR_EACH_PTR(bb->insns, insn) {
diff --git a/lib.h b/lib.h
index eb74ac1..2abafa0 100644
--- a/lib.h
+++ b/lib.h
@@ -17,7 +17,7 @@
#include "compat.h"
extern int verbose, optimize, preprocessing;
-extern int repeat_phase;
+extern int repeat_phase, merge_phi_sources;
#define container(ptr, type, member) \
(type *)((void *)(ptr) - offsetof(type, member))
diff --git a/linearize.c b/linearize.c
index 97207a3..46f6ced 100644
--- a/linearize.c
+++ b/linearize.c
@@ -1741,12 +1741,11 @@ static struct entrypoint *linearize_fn(struct symbol *sym, struct symbol *base_t
* Remove trivial instructions, and try to CSE
* the rest.
*/
- cleanup_and_cse(ep);
-
- /*
- * Remove or merge basic blocks.
- */
- pack_basic_blocks(ep);
+ merge_phi_sources = 1;
+ do {
+ cleanup_and_cse(ep);
+ pack_basic_blocks(ep);
+ } while (repeat_phase & REPEAT_CSE);
/* Cleanup */
clear_symbol_pseudos(ep);