#include "irmode_t.h"
#include "irdom_t.h"
#include "iredges_t.h"
+#include "irgopt.h"
#include "be_t.h"
#include "bearch.h"
* Allocate an array for all blocks where the copies and the original
* value were defined.
*/
- int n_orig_blocks = pset_count(copy_blocks) + 1;
+ int n_orig_blocks = pset_count(copy_blocks);
ir_node **orig_blocks = malloc(n_orig_blocks * sizeof(orig_blocks[0]));
- /*
- * Fill the array of definition blocks.
- */
- orig_blocks[0] = get_nodes_block(orig);
-
/*
* Fill the worklist queue and the rest of the orig blocks array.
*/
- for(it = pset_first(copies), i = 1; it; it = pset_next(copies)) {
+ for(it = pset_first(copies), i = 0; it; it = pset_next(copies)) {
ir_node *copy_block = get_nodes_block(it);
if(!block_dominates(orig_block, copy_block)) {
&& "The block of the copy must be dominated by the block of the value");
}
- pdeq_putr(worklist, it);
+ pdeq_putr(worklist, copy_block);
orig_blocks[i++] = copy_block;
}
while(!pdeq_empty(worklist)) {
- ir_node *irn = pdeq_getl(worklist);
- ir_node *bl = get_nodes_block(irn);
+ ir_node *bl = pdeq_getl(worklist);
ir_node *y;
- int n_preds = get_irn_arity(bl);
pset *df = be_get_dominance_frontier(df_info, bl);
for(y = pset_first(df); y; y = pset_next(df)) {
+ int n_preds = get_irn_arity(y);
if(!pset_find_ptr(phi_blocks, y)) {
ir_node *phi;
*/
ins = realloc(ins, n_preds * sizeof(ins[0]));
for(i = 0; i < n_preds; ++i)
- ins[0] = new_Unknown(mode);
+ ins[i] = orig;
/* Insert phi node */
- phi = new_r_Phi(irg, bl, n_preds, ins, mode);
- DBG((dbg, LEVEL_2, " inserting phi in block %+F\n", bl));
+ phi = new_r_Phi(irg, y, n_preds, ins, mode);
+ DBG((dbg, LEVEL_2, " inserting phi %+F with %d args in block %+F\n",
+ phi, n_preds, bl));
/*
* The phi node itself is also a copy of the original
* If the usage is in a phi node, search the copy in the
* predecessor denoted by pos.
*/
- if(is_Phi(usage))
+ if(is_Phi(usage)) {
curr_bl = get_nodes_block(get_irn_n(curr_bl, pos));
+ start_irn = sched_last(curr_bl);
+ }
+
+ else {
+ start_irn = sched_prev(usage);
+ }
/*
* Traverse the dominance tree upwards from the
* predecessor block of the usage.
*/
- start_irn = usage;
while(curr_bl != NULL) {
/*
foreach_out_edge(orig, edge) {
outs[i].irn = get_edge_src_irn(edge);
outs[i].pos = get_edge_src_pos(edge);
- DBG((dbg, LEVEL_2, " %+F(%d)\n", outs[i].irn, outs[i].pos));
i += 1;
}
int pos = outs[i].pos;
def = search_def(irn, pos, copies, copy_blocks);
+ DBG((dbg, LEVEL_2, " %+F(%d) -> %+F\n", irn, pos, def));
+
if(def != NULL)
set_irn_n(irn, pos, def);
}
pset *copies = pset_new_ptr(2 * n);
pset *copy_blocks = pset_new_ptr(2 * n);
int save_optimize = get_optimize();
- int i;
+ int save_normalize = get_opt_normalize();
firm_dbg_module_t *dbg = DBG_MODULE;
+ int i;
firm_dbg_set_mask(dbg, -1);
DBG((dbg, LEVEL_1, "Introducing following copies of %+F\n", orig));
+
/* Fill the sets. */
+ pset_insert_ptr(copies, orig);
+ pset_insert_ptr(copy_blocks, get_nodes_block(orig));
+
for(i = 0; i < n; ++i) {
DBG((dbg, LEVEL_1,
" %+F in block %+F\n", copy_nodes[i], get_nodes_block(copy_nodes[i])));
* disappear.
*/
set_optimize(0);
+ set_opt_normalize(0);
/*
* Place the phi functions and reroute the usages.
/* reset the optimizations */
set_optimize(save_optimize);
+ set_opt_normalize(save_normalize);
del_pset(copies);
del_pset(copy_blocks);
#include "irnode.h"
#include "iredges_t.h"
#include "irdump.h"
+#include "irprintf.h"
+
#include "be_t.h"
#include "beutil.h"
#include "bechordal_t.h"
* Maps blocks to perm nodes inserted during phi destruction.
*/
typedef struct _block2perm_t {
- ir_node *block, *perm;
+ ir_node *block, *perm;
} block2perm_t;
static int set_cmp_b2p(const void *x, const void *y, size_t size) {
- const block2perm_t *b1 = x;
- const block2perm_t *b2 = y;
- return b1->block != b2->block;
+ const block2perm_t *b1 = x;
+ const block2perm_t *b2 = y;
+ return b1->block != b2->block;
}
#define is_Branch(irn) (arch_irn_classify(arch_env, irn) == arch_irn_class_branch)
#define is_curr_reg_class(irn) (get_reg_cls(p) == chordal_env->cls)
static ir_node *get_perm(be_main_session_env_t *session, be_chordal_env_t *chordal_env, ir_node *block) {
- block2perm_t find, *found;
- ir_node *p;
- set *b2p = chordal_env->data;
- const arch_env_t *arch_env = chordal_env->arch_env;
-
- /* iff needed insert perm node */
-
- /* .if the perm is in the pset return it */
- find.block = block;
- find.perm = NULL;
- found = set_insert(b2p, &find, sizeof(find), HASH_PTR(find.block));
- if (found->perm)
- return found->perm;
-
- /* .else look for a perm of right register class in the schedule */
- p = sched_last(find.block);
- while (!is_Block(p) && (is_Branch(p) || (is_Perm(p) && !is_curr_reg_class(p))))
- p = sched_prev(p);
-
- /* if we haven't found a perm of the right register class create a new one */
- if (! (is_Perm(p) && is_curr_reg_class(p)))
+ block2perm_t find, *found;
+ ir_node *p;
+ set *b2p = chordal_env->data;
+ const arch_env_t *arch_env = chordal_env->arch_env;
+
+ /* iff needed insert perm node */
+
+ /* .if the perm is in the pset return it */
+ find.block = block;
+ find.perm = NULL;
+ found = set_insert(b2p, &find, sizeof(find), HASH_PTR(find.block));
+ if (found->perm)
+ return found->perm;
+
+ /* .else look for a perm of right register class in the schedule */
+ p = sched_last(find.block);
+ while (!is_Block(p) && (is_Branch(p) || (is_Perm(p) && !is_curr_reg_class(p))))
+ p = sched_prev(p);
+
+ /* if we haven't found a perm of the right register class create a new one */
+ if (! (is_Perm(p) && is_curr_reg_class(p)))
p = insert_Perm_after(session, chordal_env->cls, p);
/* insert perm into pset */
*/
static void adjust_arguments(be_main_session_env_t *session, be_chordal_env_t *chordal_env, const ir_node *phi) {
int i, max;
- ir_node *arg, *perm, *proj;
+ ir_node *arg;
const arch_register_t *phi_reg, *arg_reg, *proj_reg;
const ir_edge_t *edge;
ir_node *phi_block = get_nodes_block(phi);
arg_reg = get_reg(arg);
/* if registers don't match ...*/
if (phi_reg != arg_reg) {
+ ir_node *perm;
+
perm = get_perm(session, chordal_env, get_nodes_block(get_irn_n(phi_block, i)));
- /* adjust assigned registers for the projs */
+
+ /*
+ * Look at the projs of the perm.
+ * Find the one which corresponds to the phi argument
+ * This is done via the proj number: If
+ * the i-th argument of the perm is the old Phi
+ * argument, then the Proj with number i is the
+ * one we want.
+ */
foreach_out_edge(perm, edge) {
- proj = get_edge_src_irn(edge);
- proj_reg = get_reg(proj);
- if (proj_reg == arg_reg)
- set_reg(proj, phi_reg);
- else if (proj_reg == phi_reg)
- set_reg(proj, arg_reg);
+ ir_node *proj = get_edge_src_irn(edge);
+ int proj_nr = get_Proj_proj(proj);
+
+ if(get_irn_n(perm, proj_nr) == arg) {
+ assert(get_reg(proj) == NULL);
+ set_reg(proj, phi_reg);
+ }
}
}
}
}
static void checker(be_chordal_env_t *chordal_env) {
- pmap_entry *pme;
- int i, max;
-
- /* iterate over all blocks */
- pmap_foreach(chordal_env->border_heads, pme) {
- border_t *curr;
- struct list_head *head = pme->value;
-
- /* iterate over the first ops in the block */
- list_for_each_entry_reverse(border_t, curr, head, list)
- if (curr->is_def && curr->is_real && is_Phi(curr->irn)) {
- const arch_register_t *phi_reg, *arg_reg;
- if (!is_Phi(curr->irn))
- break;
-
- phi_reg = get_reg(curr->irn);
- /* iterate over all args of phi */
- for(i=0, max=get_irn_arity(curr->irn); i<max; ++i) {
- arg_reg = get_reg(get_irn_n(curr->irn, i));
- assert(phi_reg == arg_reg && "WTF? You can do it better!?");
- }
- }
- }
+ pmap_entry *pme;
+ int i, max;
+
+ /* iterate over all blocks */
+ pmap_foreach(chordal_env->border_heads, pme) {
+ border_t *curr;
+ struct list_head *head = pme->value;
+
+ /* iterate over the first ops in the block */
+ list_for_each_entry_reverse(border_t, curr, head, list)
+ if (curr->is_def && curr->is_real && is_Phi(curr->irn)) {
+ const arch_register_t *phi_reg, *arg_reg;
+ if (!is_Phi(curr->irn))
+ break;
+
+ phi_reg = get_reg(curr->irn);
+ /* iterate over all args of phi */
+ for(i=0, max=get_irn_arity(curr->irn); i<max; ++i) {
+ arg_reg = get_reg(get_irn_n(curr->irn, i));
+ if(phi_reg != arg_reg)
+ ir_printf("register differ: %s %s\n", phi_reg->name, arg_reg->name);
+ }
+ }
+ }
}
void be_ssa_destruction(be_main_session_env_t *session, be_chordal_env_t *chordal_env) {