Commit 833fdb14 authored by Michael Beck's avatar Michael Beck
Browse files

added optimization that moves Store behind Phi (but seems buggy yet)

[r4002]
parent ae298d4a
...@@ -45,6 +45,21 @@ typedef struct _ldst_info_t { ...@@ -45,6 +45,21 @@ typedef struct _ldst_info_t {
int exc_idx; /**< predecessor index in the exception block */ int exc_idx; /**< predecessor index in the exception block */
} ldst_info_t; } ldst_info_t;
/**
* flags for control flow
*/
enum block_flags_t {
BLOCK_HAS_COND = 1, /**< Block has conditional control flow */
BLOCK_HAS_EXC = 2 /**< Block has exceptionl control flow */
};
/**
* a Block info
*/
typedef struct _block_info_t {
unsigned flags; /**< flags for the block */
} block_info_t;
/** /**
* walker, clears all links first * walker, clears all links first
*/ */
...@@ -56,7 +71,7 @@ static void init_links(ir_node *n, void *env) ...@@ -56,7 +71,7 @@ static void init_links(ir_node *n, void *env)
/** /**
* get the Load/Store info of a node * get the Load/Store info of a node
*/ */
static ldst_info_t *get_info(ir_node *node, walk_env_t *env) static ldst_info_t *get_ldst_info(ir_node *node, walk_env_t *env)
{ {
ldst_info_t *info = get_irn_link(node); ldst_info_t *info = get_irn_link(node);
...@@ -70,6 +85,23 @@ static ldst_info_t *get_info(ir_node *node, walk_env_t *env) ...@@ -70,6 +85,23 @@ static ldst_info_t *get_info(ir_node *node, walk_env_t *env)
return info; return info;
} }
/**
* get the Block info of a node
*/
static block_info_t *get_block_info(ir_node *node, walk_env_t *env)
{
block_info_t *info = get_irn_link(node);
if (! info) {
info = obstack_alloc(&env->obst, sizeof(*info));
memset(info, 0, sizeof(*info));
set_irn_link(node, info);
}
return info;
}
/** /**
* update the projection info for a Load/Store * update the projection info for a Load/Store
*/ */
...@@ -104,32 +136,49 @@ static int update_exc(ldst_info_t *info, ir_node *block, int pos) ...@@ -104,32 +136,49 @@ static int update_exc(ldst_info_t *info, ir_node *block, int pos)
/** /**
* walker, collects all Load/Store/Proj nodes * walker, collects all Load/Store/Proj nodes
*
* walks form Start -> End
*/ */
static void collect_nodes(ir_node *node, void *env) static void collect_nodes(ir_node *node, void *env)
{ {
ir_node *pred; ir_node *pred;
ldst_info_t *info; ldst_info_t *ldst_info;
walk_env_t *wenv = env; walk_env_t *wenv = env;
if (get_irn_op(node) == op_Proj) { if (get_irn_op(node) == op_Proj) {
pred = get_Proj_pred(node); pred = get_Proj_pred(node);
if (get_irn_op(pred) == op_Load || get_irn_op(pred) == op_Store) { if (get_irn_op(pred) == op_Load || get_irn_op(pred) == op_Store) {
info = get_info(pred, wenv); ldst_info = get_ldst_info(pred, wenv);
wenv->changes |= update_projs(info, node); wenv->changes |= update_projs(ldst_info, node);
} }
} }
else if (get_irn_op(node) == op_Block) { /* check, if it's an exception block */ else if (get_irn_op(node) == op_Block) { /* check, if it's an exception block */
int i, n; int i, n;
for (i = 0, n = get_Block_n_cfgpreds(node); i < n; ++i) { for (i = 0, n = get_Block_n_cfgpreds(node); i < n; ++i) {
ir_node *pred_block;
block_info_t *bl_info;
pred = skip_Proj(get_Block_cfgpred(node, i)); pred = skip_Proj(get_Block_cfgpred(node, i));
/* ignore Bad predecessors, they will be removed later */
if (is_Bad(pred))
continue;
pred_block = get_nodes_block(pred);
bl_info = get_block_info(pred_block, wenv);
if (is_fragile_op(pred))
bl_info->flags |= BLOCK_HAS_EXC;
else if (is_forking_op(pred))
bl_info->flags |= BLOCK_HAS_COND;
if (get_irn_op(pred) == op_Load || get_irn_op(pred) == op_Store) { if (get_irn_op(pred) == op_Load || get_irn_op(pred) == op_Store) {
info = get_info(pred, wenv); ldst_info = get_ldst_info(pred, wenv);
wenv->changes |= update_exc(info, node, i); wenv->changes |= update_exc(ldst_info, node, i);
} }
} }
} }
...@@ -291,10 +340,10 @@ static int optimize_store(ir_node *store) ...@@ -291,10 +340,10 @@ static int optimize_store(ir_node *store)
* \ | / Str * \ | / Str
* Phi * Phi
* *
* This removes teh number of stores and allows for predicated execution. * This removes the number of stores and allows for predicated execution.
* Moves Stores back to the end of a function which may be bad * Moves Stores back to the end of a function which may be bad
* *
* Note: that even works, if one of the Stores is already in our current block * Is only allowed if the predecessor blocks have only one successor.
*/ */
static int optimize_phi(ir_node *phi) static int optimize_phi(ir_node *phi)
{ {
...@@ -305,6 +354,7 @@ static int optimize_phi(ir_node *phi) ...@@ -305,6 +354,7 @@ static int optimize_phi(ir_node *phi)
int *idx; int *idx;
dbg_info *db = NULL; dbg_info *db = NULL;
ldst_info_t *info; ldst_info_t *info;
block_info_t *bl_info;
/* Must be a memory Phi */ /* Must be a memory Phi */
if (get_irn_mode(phi) != mode_M) if (get_irn_mode(phi) != mode_M)
...@@ -318,6 +368,15 @@ static int optimize_phi(ir_node *phi) ...@@ -318,6 +368,15 @@ static int optimize_phi(ir_node *phi)
if (get_irn_op(store) != op_Store) if (get_irn_op(store) != op_Store)
return 0; return 0;
/* abort on bad blocks */
if (is_Bad(get_nodes_block(store)))
return 0;
/* check if the block has only one output */
bl_info = get_irn_link(get_nodes_block(store));
if (bl_info->flags)
return 0;
/* this is the address of the store */ /* this is the address of the store */
ptr = get_Store_ptr(store); ptr = get_Store_ptr(store);
mode = get_irn_mode(get_Store_value(store)); mode = get_irn_mode(get_Store_value(store));
...@@ -338,6 +397,15 @@ static int optimize_phi(ir_node *phi) ...@@ -338,6 +397,15 @@ static int optimize_phi(ir_node *phi)
/* check, if all stores have the same exception flow */ /* check, if all stores have the same exception flow */
if (exc != info->exc_block) if (exc != info->exc_block)
return 0; return 0;
/* abort on bad blocks */
if (is_Bad(get_nodes_block(store)))
return 0;
/* check if the block has only one output */
bl_info = get_irn_link(get_nodes_block(store));
if (bl_info->flags)
return 0;
} }
/* /*
...@@ -354,7 +422,7 @@ static int optimize_phi(ir_node *phi) ...@@ -354,7 +422,7 @@ static int optimize_phi(ir_node *phi)
* \ | / Str * \ | / Str
* Phi * Phi
* *
* Note: that even works, if one of the Stores is already in our current block * Is only allowed if the predecessor blocks have only one successor.
*/ */
/* first step: collect all inputs */ /* first step: collect all inputs */
...@@ -417,8 +485,8 @@ static void do_load_store_optimize(ir_node *n, void *env) ...@@ -417,8 +485,8 @@ static void do_load_store_optimize(ir_node *n, void *env)
wenv->changes |= optimize_store(n); wenv->changes |= optimize_store(n);
break; break;
case iro_Phi: // case iro_Phi:
wenv->changes |= optimize_phi(n); // wenv->changes |= optimize_phi(n);
default: default:
; ;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment