ir_nodehashmap_t adr_map; /**< Map addresses to */
block_t *forward; /**< Inverse post-order list of all blocks Start->End */
block_t *backward; /**< Inverse post-order list of all blocks End->Start */
- ir_node *start_bl; /**< start block of the current graph */
ir_node *end_bl; /**< end block of the current graph */
unsigned *curr_set; /**< current set of addresses */
memop_t **curr_id_2_memop; /**< current map of address ids to memops */
}
DB((dbg, LEVEL_2, "\n}\n\n"));
}
-} /* dump_block_list */
+}
/**
* Dumps the current set.
i = (i + 1) & 3;
}
DB((dbg, LEVEL_2, "\n}\n"));
-} /* dump_curr */
+}
#else
static void dump_block_list(ldst_env *env)
assert(is_Block(block));
return (block_t*)get_irn_link(block);
-} /* get_block_entry */
+}
/** Get the memop entry for a memory operation node */
static memop_t *get_irn_memop(const ir_node *irn)
{
assert(! is_Block(irn));
return (memop_t*)get_irn_link(irn);
-} /* get_irn_memop */
+}
/**
* Walk over the memory edges from definition to users.
}
if (post)
post(irn, ctx);
-} /* walk_memory */
+}
/**
* Walks over all memory nodes of a graph.
walk_memory(get_irg_initial_mem(irg), pre, post, ctx);
ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
-} /* walk_memory_irg */
+}
/**
* Register an address and allocate a (sparse, 0..n) ID for it.
{
address_entry *entry;
- /* skip Confirms and Casts */
+ /* skip Confirms */
restart:
if (is_Confirm(adr)) {
adr = get_Confirm_value(adr);
goto restart;
}
- if (is_Cast(adr)) {
- adr = get_Cast_op(adr);
- goto restart;
- }
entry = ir_nodehashmap_get(address_entry, &env.adr_map, adr);
#endif
}
return entry->id;
-} /* register_address */
+}
/**
if (is_Phi(address) && get_nodes_block(address) == block)
address = get_Phi_pred(address, pos);
return address;
-} /* phi_translate */
+}
/**
* Walker: allocate an block entry for every block
(void)register_address(irn);
}
}
-} /* prepare_blocks */
+}
/**
* Post-Walker, link in all Phi's
ir_node *block = get_nodes_block(irn);
add_Block_phi(block, irn);
}
-} /* link_phis */
+}
/**
* Block walker: creates the inverse post-order list for the CFG.
/* remember the first visited (last in list) entry, needed for later */
if (env.backward == NULL)
env.backward = entry;
-} /* inverse_post_order */
+}
/**
* Block walker: create backward links for the memops of a block.
last = op;
}
entry->memop_backward = last;
-} /* collect_backward */
+}
/**
* Allocate a memop.
if (irn != NULL)
set_irn_link(irn, m);
return m;
-} /* alloc_memop */
+}
/**
* Create a memop for a Phi-replacement.
set_irn_link(phi, m);
return m;
-} /* clone_memop_phi */
+}
/**
* Return the memory properties of a call node.
}
}
return prop & (mtp_property_const|mtp_property_pure);
-} /* get_Call_memory_properties */
+}
/**
* Returns an entity if the address ptr points to a constant one.
} else
return NULL;
}
-} /* find_constant_entity */
+}
/**
* Return the Selection index of a Sel node from dimension n
static long get_Sel_array_index_long(ir_node *n, int dim)
{
ir_node *index = get_Sel_index(n, dim);
- assert(is_Const(index));
return get_tarval_long(get_Const_tarval(index));
-} /* get_Sel_array_index_long */
+}
typedef struct path_entry {
ir_entity *ent;
goto ptr_arith;
}
return NULL;
-} /* rec_find_compound_ent_value */
+}
static ir_node *find_compound_ent_value(ir_node *ptr)
{
return rec_find_compound_ent_value(ptr, NULL);
-} /* find_compound_ent_value */
+}
/**
* Mark a Load memop to be replace by a definition
op->replace = def;
op->flags |= FLAG_KILLED_NODE;
env.changed = 1;
-} /* mark_replace_load */
+}
/**
* Mark a Store memop to be removed.
{
op->flags |= FLAG_KILLED_NODE;
env.changed = 1;
-} /* mark_remove_store */
+}
/**
* Update a memop for a Load.
/* no user, KILL it */
mark_replace_load(m, NULL);
}
-} /* update_Load_memop */
+}
/**
* Update a memop for a Store.
}
m->value.value = get_Store_value(store);
m->value.mode = get_irn_mode(m->value.value);
-} /* update_Store_memop */
+}
/**
* Update a memop for a Call.
break;
}
}
-} /* update_Call_memop */
+}
/**
* Update a memop for a Div/Mod.
{
/* the Phi is its own mem */
m->mem = m->node;
-} /* update_Phi_memop */
+}
/**
* Memory walker: collect all memory ops and build topological lists.
entry->memop_backward = op;
}
}
-} /* collect_memops */
+}
/**
* Find an address in the current set.
return res;
}
return NULL;
-} /* find_address */
+}
/**
* Find an address in the avail_out set.
return res;
}
return NULL;
-} /* find_address_avail */
+}
/**
* Kill all addresses from the current set.
/* set sentinel */
rbitset_set(env.curr_set, env.rbs_size - 1);
-} /* kill_all */
+}
/**
* Kill memops that are not alias free due to a Store value from the current set.
DB((dbg, LEVEL_2, "KILLING %+F because of possible alias address %+F\n", op->node, value->address));
}
}
-} /* kill_memops */
+}
/**
* Add the value of a memop to the current set.
{
rbitset_set(env.curr_set, op->value.id);
env.curr_id_2_memop[op->value.id] = op;
-} /* add_memop */
+}
/**
* Add the value of a memop to the avail_out set.
{
rbitset_set(bl->avail_out, op->value.id);
bl->id_2_memop_avail[op->value.id] = op;
-} /* add_memop_avail */
+}
/**
* Check, if we can convert a value of one mode to another mode
get_mode_size_bits(from) == get_mode_size_bits(to))
return 1;
return 0;
-} /* can_convert_to */
+}
/**
* Add a Conv to the requested mode if needed.
return NULL;
}
return irn;
-} /* conv_to */
+}
/**
* Update the address of an value if this address was a load result
value->address = op->replace;
}
}
-} /* update_address */
+}
/**
* Do forward dataflow analysis on the given block and calculate the
kill_all();
}
}
-} /* calc_gen_kill_avail */
-
-#define BYTE_SIZE(x) (((x) + 7) >> 3)
+}
/**
* Do forward dataflow analysis on a given block to calculate the avail_out set
calc_gen_kill_avail(bl);
dump_curr(bl, "Avail_out");
-} /* forward_avail */
+}
/**
* Do backward dataflow analysis on a given block to calculate the antic set
}
dump_curr(bl, "AnticL_in");
return 0;
-} /* backward_antic */
+}
/**
* Replace a Load memop by a already known value.
if (proj != NULL) {
exchange(proj, new_r_Jmp(get_nodes_block(load)));
}
-} /* replace_load */
+}
/**
* Remove a Store memop.
if (proj != NULL) {
exchange(proj, new_r_Jmp(get_nodes_block(store)));
}
-} /* remove_store */
+}
/**
}
}
}
-} /* do_replacements */
+}
/**
* Calculate the Avail_out sets for all basic blocks.
/* restore the current sets */
env.curr_id_2_memop = tmp_memop;
env.curr_set = tmp_set;
-} /* calcAvail */
+}
/**
* Calculate the Antic_in sets for all basic blocks.
++i;
} while (need_iter);
DB((dbg, LEVEL_2, "Get anticipated Load set after %d iterations\n", i));
-} /* calcAntic */
+}
/**
* Return the node representing the last memory in a block.
/* if there is NO memory in this block, go to the dominator */
bl = get_block_entry(get_Block_idom(bl->block));
}
-} /* find_last_memory */
+}
/**
* Reroute all memory users of old memory
/* all edges previously point to omem now point to nmem */
nmem->o.out = omem->o.out;
-} /* reroute_all_mem_users */
+}
/**
* Reroute memory users of old memory that are dominated by a given block
edges at the end either. */
/* first entry is used for the length */
nmem->o.out = new_out;
-} /* reroute_mem_through */
+}
/**
* insert Loads, making partly redundant Loads fully redundant
if (! rbitset_is_set(env.curr_set, pos))
env.curr_id_2_memop[pos] = NULL;
else {
- ir_node *pred = get_Block_cfgpred_block(bl->block, 0);
- block_t *pred_bl = get_block_entry(pred);
- int need_phi = 0;
- memop_t *first = NULL;
- ir_mode *mode = NULL;
+ int need_phi = 0;
+ memop_t *first = NULL;
+ ir_mode *mode = NULL;
for (i = 0; i < n; ++i) {
- memop_t *mop;
-
- pred = get_Block_cfgpred_block(bl->block, i);
- pred_bl = get_block_entry(pred);
+ ir_node *pred = get_Block_cfgpred_block(bl->block, i);
+ block_t *pred_bl = get_block_entry(pred);
- mop = pred_bl->id_2_memop_avail[pos];
+ memop_t *mop = pred_bl->id_2_memop_avail[pos];
if (first == NULL) {
first = mop;
ins[0] = first->value.value;
}
dump_curr(bl, "Avail_out");
return 0;
-} /* insert_Load */
+}
/**
* Insert Loads upwards.
} while (need_iter);
DB((dbg, LEVEL_2, "Finished Load inserting after %d iterations\n", i));
-} /* insert_Loads_upwards */
+}
void opt_ldst(ir_graph *irg)
{
env.n_mem_ops = 0;
env.max_cfg_preds = 0;
env.changed = 0;
- env.start_bl = get_irg_start_block(irg);
env.end_bl = get_irg_end_block(irg);
#ifdef DEBUG_libfirm
env.id_2_address = NEW_ARR_F(ir_node *, 0);
/* produce an inverse post-order list for the CFG: this links only reachable
blocks */
- irg_out_block_walk(get_irg_start_block(irg), NULL, inverse_post_order, NULL);
+ ir_node *const start_block = get_irg_start_block(irg);
+ irg_out_block_walk(start_block, NULL, inverse_post_order, NULL);
if (! get_Block_mark(env.end_bl)) {
/*
env.backward = bl;
/* check that we really start with the start / end block */
- assert(env.forward->block == env.start_bl);
+ assert(env.forward->block == start_block);
assert(env.backward->block == env.end_bl);
/* create address sets: for now, only the existing addresses are allowed plus one
/* create the current set */
env.curr_set = rbitset_obstack_alloc(&env.obst, env.rbs_size);
rbitset_set(env.curr_set, env.rbs_size - 1);
- env.curr_id_2_memop = NEW_ARR_D(memop_t *, &env.obst, env.rbs_size);
- memset(env.curr_id_2_memop, 0, env.rbs_size * sizeof(env.curr_id_2_memop[0]));
+ env.curr_id_2_memop = NEW_ARR_DZ(memop_t*, &env.obst, env.rbs_size);
for (bl = env.forward; bl != NULL; bl = bl->forward_next) {
/* set sentinel bits */
bl->avail_out = rbitset_obstack_alloc(&env.obst, env.rbs_size);
rbitset_set(bl->avail_out, env.rbs_size - 1);
- bl->id_2_memop_avail = NEW_ARR_D(memop_t *, &env.obst, env.rbs_size);
- memset(bl->id_2_memop_avail, 0, env.rbs_size * sizeof(bl->id_2_memop_avail[0]));
+ bl->id_2_memop_avail = NEW_ARR_DZ(memop_t*, &env.obst, env.rbs_size);
bl->anticL_in = rbitset_obstack_alloc(&env.obst, env.rbs_size);
rbitset_set(bl->anticL_in, env.rbs_size - 1);
- bl->id_2_memop_antic = NEW_ARR_D(memop_t *, &env.obst, env.rbs_size);
- memset(bl->id_2_memop_antic, 0, env.rbs_size * sizeof(bl->id_2_memop_antic[0]));
+ bl->id_2_memop_antic = NEW_ARR_DZ(memop_t*, &env.obst, env.rbs_size);
}
(void) dump_block_list;
#ifdef DEBUG_libfirm
DEL_ARR_F(env.id_2_address);
#endif
-} /* opt_ldst */
+}
ir_graph_pass_t *opt_ldst_pass(const char *name)
{
return def_graph_pass(name ? name : "ldst_df", opt_ldst);
-} /* opt_ldst_pass */
+}