extern void pass_assign_vregs(void);
extern void pass_calculate_vreg_spillibility(void);
+extern void pass_collapse_adjacent_moves(void);
extern void pass_convert_copies_to_moves(void);
extern void pass_convert_inputs_to_phis(void);
extern void pass_convert_locals_to_ssa(void);
extern void pass_instruction_selector(void);
extern void pass_live_value_analysis(void);
extern void pass_add_prologue_epilogue(void);
+extern void pass_prune_stray_moves(void);
extern void pass_register_allocator(void);
extern void pass_remove_dead_blocks(void);
extern void pass_remove_dead_phis(void);
--- /dev/null
+#include "mcg.h"
+
+static struct vreg* find_source_of_vreg(struct hop* hop, struct vreg* vreg);
+
+static void merge(struct hop* master, struct hop* slave)
+{
+ int i, j;
+
+ for (i=0; i<slave->vregusage.count; i++)
+ {
+ struct vreg* sinput = slave->vregusage.item[i].left;
+ struct vreg* soutput = slave->vregusage.item[i].right;
+
+ if (sinput && soutput)
+ {
+ for (j=0; j<master->vregusage.count; j++)
+ {
+ struct vreg* minput = master->vregusage.item[j].left;
+ struct vreg* moutput = master->vregusage.item[j].right;
+
+ if (minput && moutput && (sinput == moutput))
+ {
+ /* The input of the slave was written by the master; so instead source
+ * the slave's copy from the source of the master. */
+ sinput = minput;
+ break;
+ }
+ }
+
+ hop_add_through_vreg(master, sinput, soutput);
+ }
+ }
+}
+
+void pass_collapse_adjacent_moves(void)
+{
+ int i, j;
+
+ for (i=0; i<cfg.preorder.count; i++)
+ {
+ struct basicblock* bb = cfg.preorder.item[i];
+
+ j = 0;
+ while (j < (bb->hops.count-1))
+ {
+ struct hop* firstmove = bb->hops.item[j];
+ struct hop* secondmove = bb->hops.item[j+1];
+ if (firstmove->is_move && secondmove->is_move)
+ {
+ merge(firstmove, secondmove);
+ array_remove(&bb->hops, secondmove);
+ }
+ else
+ j++;
+ }
+ }
+}
--- /dev/null
+#include "mcg.h"
+
+static struct vreg* find_source_of_vreg(struct hop* hop, struct vreg* vreg);
+
+static void prune(struct hop* master, struct hop* slave)
+{
+ int i, j;
+
+ for (i=0; i<master->vregusage.count; i++)
+ {
+ struct vreg* minput = master->vregusage.item[i].left;
+ struct vreg* moutput = master->vregusage.item[i].right;
+
+ if (moutput)
+ {
+ bool found = false;
+
+ for (j=0; j<slave->vregusage.count; j++)
+ {
+ struct vreg* sinput = slave->vregusage.item[j].left;
+ struct vreg* soutput = slave->vregusage.item[j].right;
+
+ if (sinput == moutput)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ pmap_remove_index(&master->vregusage, i);
+ i--;
+ }
+ }
+ }
+}
+
+void pass_prune_stray_moves(void)
+{
+ int i, j;
+
+ for (i=0; i<cfg.preorder.count; i++)
+ {
+ struct basicblock* bb = cfg.preorder.item[i];
+
+ for (j=0; j<(bb->hops.count-1); j++)
+ {
+ struct hop* firstmove = bb->hops.item[j];
+ struct hop* secondmove = bb->hops.item[j+1];
+ if (firstmove->is_move && !secondmove->is_move)
+ prune(firstmove, secondmove);
+ }
+ }
+}
+
struct vreg* invreg1 = actual(hop->vregusage.item[k].left);
struct vreg* outvreg1 = actual(hop->vregusage.item[k].right);
+ if (invreg1)
+ graph_add_vertex(&interference, invreg1);
+ if (outvreg1)
+ graph_add_vertex(&interference, outvreg1);
+
for (m=k; m<hop->vregusage.count; m++)
{
struct vreg* invreg2 = actual(hop->vregusage.item[m].left);
struct vreg* outvreg2 = actual(hop->vregusage.item[m].right);
- if (invreg1)
- graph_add_vertex(&interference, invreg1);
if (invreg2)
graph_add_vertex(&interference, invreg2);
- if (outvreg1)
- graph_add_vertex(&interference, outvreg1);
if (outvreg2)
graph_add_vertex(&interference, outvreg2);
}
}
+static void check_graph(void)
+{
+ struct edge_iterator eit = {};
+ while (graph_next_edge(&interference, &eit))
+ assert(!graph_contains_edge(&affinity, eit.left, eit.right));
+
+ while (graph_next_edge(&affinity, &eit))
+ assert(!graph_contains_edge(&interference, eit.left, eit.right));
+}
+
static void dump_vreg(struct vreg* vreg)
{
fprintf(regalloc_dot_file, "[%%%d]", vreg->id);
thisdegree++;
}
- if (thisdegree < degree)
+ if ((thisdegree < degree) && !graph_contains_edge(&interference, left, right))
{
vmaster = left;
vslave = right;
{
wire_together_bbs();
generate_graph();
+ check_graph();
dump_interference_graph();
simplified.count = 0;
current_proc = proc;
pass_group_irs();
- print_blocks('1');
+ print_blocks('a');
/* Passes from here on must preserve IR grouping */
pass_eliminate_trivial_blocks();
pass_remove_dead_blocks();
- print_blocks('2');
+ print_blocks('b');
update_graph_data();
+ print_blocks('c');
pass_split_critical_edges();
+ print_blocks('d');
update_graph_data();
if (cfg_dot_file)
/* Passes from here on can't alter the BB graph without also updating prevs
* and nexts (and then calling update_graph_data()). */
- print_blocks('3');
+ print_blocks('e');
pass_wire_up_return_values();
+ print_blocks('f');
pass_convert_stack_ops();
+ print_blocks('g');
pass_convert_locals_to_ssa();
- print_blocks('4');
+ print_blocks('h');
pass_convert_inputs_to_phis();
+ print_blocks('i');
pass_convert_nonlocal_phis();
+ print_blocks('j');
pass_remove_dead_phis();
- print_blocks('5');
+ print_blocks('k');
pass_infer_types();
- print_blocks('6');
+ print_blocks('l');
pass_instruction_selector();
- print_hops('7');
+ print_hops('m');
pass_live_value_analysis();
- print_hops('8');
+ print_hops('n');
pass_assign_vregs();
- pass_calculate_vreg_spillibility();
+ print_hops('o');
pass_convert_copies_to_moves();
- print_hops('9');
+ print_hops('p');
+ pass_collapse_adjacent_moves();
+ print_hops('q');
+ pass_prune_stray_moves();
+ print_hops('r');
+ pass_calculate_vreg_spillibility();
+ print_hops('s');
pass_register_allocator();
- print_hops('a');
+ print_hops('t');
#if 0
pass_add_prologue_epilogue();
print_hops('9');