#include "irflag_t.h"
#include "array.h"
#include "irhooks.h"
+#include "iredges.h"
#include "irtools.h"
#include "opt_polymorphy.h"
}
/** Return the number of uses of an address node */
-#define get_irn_n_uses(adr) (unsigned)PTR_TO_INT(get_irn_link(adr))
-/** Sets the number of uses of an address node */
-#define set_irn_n_uses(adr, n) set_irn_link(adr, INT_TO_PTR(n))
+#define get_irn_n_uses(adr) get_irn_n_edges(adr)
/**
* walker, collects all Load/Store/Proj nodes
if ((ldst_info->flags & LDST_VISITED) == 0) {
adr = get_Load_ptr(pred);
- set_irn_n_uses(adr, get_irn_n_uses(adr) + 1);
-
ldst_info->flags |= LDST_VISITED;
}
if ((ldst_info->flags & LDST_VISITED) == 0) {
adr = get_Store_ptr(pred);
- set_irn_n_uses(adr, get_irn_n_uses(adr) + 1);
-
ldst_info->flags |= LDST_VISITED;
}
}
}
}
- else if (op == op_Block) { /* check, if it's an exception block */
+ else if (op == op_Block) {
int i;
for (i = get_Block_n_cfgpreds(node) - 1; i >= 0; --i) {
bl_info = get_block_info(pred_block, wenv);
if (is_fragile_op(pred))
- bl_info->flags |= BLOCK_HAS_EXC;
+ bl_info->flags |= BLOCK_HAS_EXC;
else if (is_irn_forking(pred))
bl_info->flags |= BLOCK_HAS_COND;
/**
* Returns an entity if the address ptr points to a constant one.
*/
-static entity *find_constant_entity(ir_node *ptr)
+static ir_entity *find_constant_entity(ir_node *ptr)
{
for (;;) {
ir_op *op = get_irn_op(ptr);
return get_SymConst_entity(ptr);
}
else if (op == op_Sel) {
- entity *ent = get_Sel_entity(ptr);
- ir_type *tp = get_entity_owner(ent);
+ ir_entity *ent = get_Sel_entity(ptr);
+ ir_type *tp = get_entity_owner(ent);
/* Do not fiddle with polymorphism. */
if (is_Class_type(get_entity_owner(ent)) &&
*/
static compound_graph_path *rec_get_accessed_path(ir_node *ptr, int depth) {
compound_graph_path *res = NULL;
- entity *root, *field;
+ ir_entity *root, *field;
int path_len, pos;
if (get_irn_op(ptr) == op_SymConst) {
/* a Load which value is neither used nor exception checked, remove it */
exchange(info->projs[pn_Load_M], mem);
+ exchange(load, new_Bad());
reduce_adr_usage(ptr);
}
}
* node and update the counters.
*/
static void reduce_adr_usage(ir_node *ptr) {
- int use_count = get_irn_n_uses(ptr);
- --use_count;
- assert(use_count >= 0);
- set_irn_n_uses(ptr, use_count);
-
if (is_Proj(ptr)) {
- if (use_count <= 0) {
- /* this Proj is now dead, update the Load/Store info */
+ if (get_irn_n_edges(ptr) <= 0) {
+ /* this Proj is dead now */
ir_node *pred = get_Proj_pred(ptr);
opcode code = get_irn_opcode(pred);
if (info->projs[pn_Load_res])
exchange(info->projs[pn_Load_res], value);
+ exchange(load, new_Bad());
reduce_adr_usage(ptr);
return res | DF_CHANGED;
}
res |= CF_CHANGED;
}
+ exchange(load, new_Bad());
reduce_adr_usage(ptr);
return res |= DF_CHANGED;
}
static unsigned optimize_load(ir_node *load)
{
ldst_info_t *info = get_irn_link(load);
- ir_mode *load_mode = get_Load_mode(load);
ir_node *mem, *ptr, *new_node;
- entity *ent;
+ ir_entity *ent;
unsigned res = 0;
/* do NOT touch volatile loads for now */
if (get_irn_op(skip_Proj(mem)) == op_Alloc) {
/* ok, check the types */
- entity *ent = get_Sel_entity(ptr);
- ir_type *s_type = get_entity_type(ent);
- ir_type *a_type = get_Alloc_type(mem);
+ ir_entity *ent = get_Sel_entity(ptr);
+ ir_type *s_type = get_entity_type(ent);
+ ir_type *a_type = get_Alloc_type(mem);
if (is_SubClass_of(s_type, a_type)) {
/* ok, condition met: there can't be an exception because
/* a Load which value is neither used nor exception checked, remove it */
exchange(info->projs[pn_Load_M], mem);
+ exchange(load, new_Bad());
reduce_adr_usage(ptr);
return res | DF_CHANGED;
}
if (info->projs[pn_Load_res])
exchange(info->projs[pn_Load_res], new_node);
+ exchange(load, new_Bad());
reduce_adr_usage(ptr);
return res | DF_CHANGED;
}
res |= DF_CHANGED;
}
}
+ exchange(load, new_Bad());
reduce_adr_usage(ptr);
return res;
}
{
int j;
for (j = 0; j < get_compound_graph_path_length(path); ++j) {
- entity *node = get_compound_graph_path_node(path, j);
+ ir_entity *node = get_compound_graph_path_node(path, j);
fprintf(stdout, ".%s", get_entity_name(node));
if (is_Array_type(get_entity_owner(node)))
fprintf(stdout, "[%d]", get_compound_graph_path_array_index(path, j));
exchange(info->projs[pn_Load_res], copy_const_value(get_irn_dbg_info(load), c));
res |= DF_CHANGED;
}
+ exchange(load, new_Bad());
reduce_adr_usage(ptr);
return res;
}
if (get_Store_volatility(pred) != volatility_is_volatile && !pred_info->projs[pn_Store_X_except]) {
DBG_OPT_WAW(pred, store);
exchange( pred_info->projs[pn_Store_M], get_Store_mem(pred) );
+ exchange(pred, new_Bad());
reduce_adr_usage(ptr);
return DF_CHANGED;
}
if (! info->projs[pn_Store_X_except]) {
DBG_OPT_WAR(store, pred);
exchange( info->projs[pn_Store_M], mem );
+ exchange(store, new_Bad());
reduce_adr_usage(ptr);
return DF_CHANGED;
}
*/
static unsigned optimize_store(ir_node *store)
{
- ldst_info_t *info = get_irn_link(store);
ir_node *ptr, *mem;
if (get_Store_volatility(store) == volatility_is_volatile)
*
* val1 val2 val3 val1 val2 val3
* | | | \ | /
- * Str Str Str \ | /
+ * Store Store Store \ | /
* \ | / PhiData
* \ | / |
- * \ | / Str
+ * \ | / Store
* PhiM
*
* @endverbatim
static unsigned optimize_phi(ir_node *phi, walk_env_t *wenv)
{
int i, n;
- ir_node *store, *old_store, *ptr, *block, *phiM, *phiD, *exc, *projM;
+ ir_node *store, *old_store, *ptr, *block, *phi_block, *phiM, *phiD, *exc, *projM;
ir_mode *mode;
- ir_node **inM, **inD;
+ ir_node **inM, **inD, **stores;
int *idx;
dbg_info *db = NULL;
ldst_info_t *info;
if (get_irn_op(store) != op_Store)
return 0;
+ block = get_nodes_block(store);
+
/* abort on dead blocks */
- if (is_Block_dead(get_nodes_block(store)))
+ if (is_Block_dead(block))
return 0;
- /* check if the block has only one successor */
- bl_info = get_irn_link(get_nodes_block(store));
- if (bl_info->flags)
+ /* check if the block is post dominated by Phi-block
+ and has no exception exit */
+ bl_info = get_irn_link(block);
+ if (bl_info->flags & BLOCK_HAS_EXC)
+ return 0;
+
+ phi_block = get_nodes_block(phi);
+ if (! block_postdominates(phi_block, block))
return 0;
/* this is the address of the store */
return 0;
/* abort on dead blocks */
- if (is_Block_dead(get_nodes_block(store)))
+ block = get_nodes_block(pred);
+ if (is_Block_dead(block))
return 0;
- /* check if the block has only one successor */
- bl_info = get_irn_link(get_nodes_block(store));
- if (bl_info->flags)
+ /* check if the block is post dominated by Phi-block
+ and has no exception exit. Note that block must be different from
+ Phi-block, else we would move a Store from end End of a block to its
+ Start... */
+ bl_info = get_irn_link(block);
+ if (bl_info->flags & BLOCK_HAS_EXC)
+ return 0;
+ if (block == phi_block || ! block_postdominates(phi_block, block))
return 0;
}
* Is only allowed if the predecessor blocks have only one successor.
*/
- /* first step: collect all inputs */
+ NEW_ARR_A(ir_node *, stores, n);
NEW_ARR_A(ir_node *, inM, n);
NEW_ARR_A(ir_node *, inD, n);
NEW_ARR_A(int, idx, n);
+ /* Prepare: Collect all Store nodes. We must do this
+ first because we otherwise may loose a store when exchanging its
+ memory Proj.
+ */
+ for (i = 0; i < n; ++i)
+ stores[i] = skip_Proj(get_Phi_pred(phi, i));
+
+ /* Prepare: Skip the memory Proj: we need this in the case some stores
+ are cascaded.
+ Beware: One Store might be included more than once in the stores[]
+ list, so we must prevent to do the exchange more than once.
+ */
for (i = 0; i < n; ++i) {
- ir_node *pred = skip_Proj(get_Phi_pred(phi, i));
- info = get_irn_link(pred);
+ ir_node *store = stores[i];
+ ir_node *proj_m;
- inM[i] = get_Store_mem(pred);
- inD[i] = get_Store_value(pred);
- idx[i] = info->exc_idx;
+ info = get_irn_link(store);
+ proj_m = info->projs[pn_Store_M];
- /* Should we here replace the Proj after the Store by
- * the Store's memory? Would be save but should not be needed,
- * because we checked that all pred blocks have only one
- * control flow successor.
- */
+ if (is_Proj(proj_m) && get_Proj_pred(proj_m) == store)
+ exchange(proj_m, get_Store_mem(store));
+ }
+
+ /* first step: collect all inputs */
+ for (i = 0; i < n; ++i) {
+ ir_node *store = stores[i];
+ info = get_irn_link(store);
+
+ inM[i] = get_Store_mem(store);
+ inD[i] = get_Store_value(store);
+ idx[i] = info->exc_idx;
}
block = get_nodes_block(phi);
#ifdef DO_CACHEOPT
co_set_irn_name(store, co_get_irn_ident(old_store));
#endif
- /* we replaced n uses by 1 */
- set_irn_n_uses(ptr, get_irn_n_uses(ptr) - n + 1);
projM = new_rd_Proj(NULL, current_ir_graph, block, store, mode_M, pn_Store_M);
if (! get_opt_redundant_loadstore())
return;
+ edges_assure(irg);
+
+ /* for Phi optimization post-dominators are needed ... */
+ assure_postdoms(irg);
+
obstack_init(&env.obst);
env.changes = 0;