{
for (;;) {
if (is_SymConst(ptr) && get_SymConst_kind(ptr) == symconst_addr_ent) {
- ir_entity *ent = get_SymConst_entity(ptr);
- if (variability_constant == get_entity_variability(ent))
- return ent;
- return NULL;
+ return get_SymConst_entity(ptr);
} else if (is_Sel(ptr)) {
ir_entity *ent = get_Sel_entity(ptr);
ir_type *tp = get_entity_owner(ent);
if (is_SymConst(ptr)) {
/* a SymConst. If the depth is 0, this is an access to a global
* entity and we don't need a component path, else we know
- * at least it's length.
+ * at least its length.
*/
assert(get_SymConst_kind(ptr) == symconst_addr_ent);
root = get_SymConst_entity(ptr);
set_compound_graph_path_array_index(res, pos, get_Sel_array_index_long(ptr, 0));
}
} else if (is_Add(ptr)) {
- ir_node *l = get_Add_left(ptr);
- ir_node *r = get_Add_right(ptr);
- ir_mode *mode;
+ ir_node *l = get_Add_left(ptr);
+ ir_node *r = get_Add_right(ptr);
+ ir_mode *mode = get_irn_mode(ptr);
+ tarval *tmp;
- if (is_Const(r)) {
+ if (is_Const(r) && get_irn_mode(l) == mode) {
ptr = l;
tv = get_Const_tarval(r);
} else {
}
ptr_arith:
mode = get_tarval_mode(tv);
+ tmp = tv;
/* ptr must be a Sel or a SymConst, this was checked in find_constant_entity() */
if (is_Sel(ptr)) {
size = get_type_size_bytes(get_entity_type(ent));
sz = new_tarval_from_long(size, mode);
- tv_index = tarval_div(tv, sz);
- tv = tarval_mod(tv, sz);
+ tv_index = tarval_div(tmp, sz);
+ tmp = tarval_mod(tmp, sz);
- if (tv_index == tarval_bad || tv == tarval_bad)
+ if (tv_index == tarval_bad || tmp == tarval_bad)
return NULL;
assert(get_array_n_dimensions(tp) == 1 && "multiarrays not implemented");
/* ok, bounds check finished */
++idx;
}
- if (! tarval_is_null(tv)) {
+ if (! tarval_is_null(tmp)) {
/* access to some struct/union member */
return NULL;
}
* valid, if the graph is in phase_high and _no_ address computation is used.
*/
static compound_graph_path *get_accessed_path(ir_node *ptr) {
- return rec_get_accessed_path(ptr, 0);
+ compound_graph_path *gr = rec_get_accessed_path(ptr, 0);
+ return gr;
} /* get_accessed_path */
typedef struct path_entry {
static void reduce_adr_usage(ir_node *ptr);
/**
- * Update a Load that may lost it's usage.
+ * Update a Load that may have lost its users.
*/
static void handle_load_update(ir_node *load) {
ldst_info_t *info = get_irn_link(load);
ir_node *ptr = get_Load_ptr(load);
ir_node *mem = get_Load_mem(load);
- /* a Load which value is neither used nor exception checked, remove it */
+ /* a Load whose value is neither used nor exception checked, remove it */
exchange(info->projs[pn_Load_M], mem);
if (info->projs[pn_Load_X_regular])
exchange(info->projs[pn_Load_X_regular], new_r_Jmp(current_ir_graph, get_nodes_block(load)));
} /* handle_load_update */
/**
- * A Use of an address node is vanished. Check if this was a Proj
+ * A use of an address node has vanished. Check if this was a Proj
* node and update the counters.
*/
static void reduce_adr_usage(ir_node *ptr) {
ldst_info_t *info = get_irn_link(pred);
info->projs[get_Proj_proj(ptr)] = NULL;
- /* this node lost it's result proj, handle that */
+ /* this node lost its result proj, handle that */
handle_load_update(pred);
}
}
}
/* The mem of the Load. Must still be returned after optimization. */
- mem = get_Load_mem(load);
+ mem = get_Load_mem(load);
if (! info->projs[pn_Load_res] && ! info->projs[pn_Load_X_except]) {
/* a Load which value is neither used nor exception checked, remove it */
value = NULL;
/* check if we can determine the entity that will be loaded */
ent = find_constant_entity(ptr);
- if (ent != NULL) {
- if ((allocation_static == get_entity_allocation(ent)) &&
- (visibility_external_allocated != get_entity_visibility(ent))) {
- /* a static allocation that is not external: there should be NO exception
- * when loading even if we cannot replace the load itself. */
-
- /* no exception, clear the info field as it might be checked later again */
- if (info->projs[pn_Load_X_except]) {
- exchange(info->projs[pn_Load_X_except], new_Bad());
- info->projs[pn_Load_X_except] = NULL;
- res |= CF_CHANGED;
- }
- if (info->projs[pn_Load_X_regular]) {
- exchange(info->projs[pn_Load_X_regular], new_r_Jmp(current_ir_graph, get_nodes_block(load)));
- info->projs[pn_Load_X_regular] = NULL;
- res |= CF_CHANGED;
- }
+ if (ent != NULL &&
+ allocation_static == get_entity_allocation(ent) &&
+ visibility_external_allocated != get_entity_visibility(ent)) {
+ /* a static allocation that is not external: there should be NO exception
+ * when loading even if we cannot replace the load itself. */
+
+ /* no exception, clear the info field as it might be checked later again */
+ if (info->projs[pn_Load_X_except]) {
+ exchange(info->projs[pn_Load_X_except], new_Bad());
+ info->projs[pn_Load_X_except] = NULL;
+ res |= CF_CHANGED;
+ }
+ if (info->projs[pn_Load_X_regular]) {
+ exchange(info->projs[pn_Load_X_regular], new_r_Jmp(current_ir_graph, get_nodes_block(load)));
+ info->projs[pn_Load_X_regular] = NULL;
+ res |= CF_CHANGED;
+ }
- if (variability_constant == get_entity_variability(ent)) {
- if (is_atomic_entity(ent)) {
- /* Might not be atomic after
- lowering of Sels. In this
- case we could also load, but
- it's more complicated. */
- /* more simpler case: we load the content of a constant value:
- * replace it by the constant itself
- */
- value = get_atomic_ent_value(ent);
- } else {
- if (ent->has_initializer) {
- /* new style initializer */
- value = find_compound_ent_value(ptr);
- } else {
- /* old style initializer */
- compound_graph_path *path = get_accessed_path(ptr);
-
- if (path != NULL) {
- assert(is_proper_compound_graph_path(path, get_compound_graph_path_length(path)-1));
-
- value = get_compound_ent_value_by_path(ent, path);
- free_compound_graph_path(path);
- }
- }
+ if (variability_constant == get_entity_variability(ent)) {
+ if (is_atomic_entity(ent)) {
+ /* Might not be atomic after lowering of Sels. In this case we
+ * could also load, but it's more complicated. */
+ /* more simpler case: we load the content of a constant value:
+ * replace it by the constant itself */
+ value = get_atomic_ent_value(ent);
+ } else if (ent->has_initializer) {
+ /* new style initializer */
+ value = find_compound_ent_value(ptr);
+ } else {
+ /* old style initializer */
+ compound_graph_path *path = get_accessed_path(ptr);
+
+ if (path != NULL) {
+ assert(is_proper_compound_graph_path(path, get_compound_graph_path_length(path)-1));
+
+ value = get_compound_ent_value_by_path(ent, path);
+ DB((dbg, LEVEL_1, " Constant access at %F%F resulted in %+F\n", ent, path, value));
+ free_compound_graph_path(path);
}
- if (value != NULL)
- value = can_replace_load_by_const(load, value);
}
+ if (value != NULL)
+ value = can_replace_load_by_const(load, value);
}
}
}
return res;
} /* follow_Mem_chain_for_Store */
+/** find entity used as base for an address calculation */
+static ir_entity *find_entity(ir_node *ptr)
+{
+ switch(get_irn_opcode(ptr)) {
+ case iro_SymConst:
+ return get_SymConst_entity(ptr);
+ case iro_Sel: {
+ ir_node *pred = get_Sel_ptr(ptr);
+ if (get_irg_frame(get_irn_irg(ptr)) == pred)
+ return get_Sel_entity(ptr);
+
+ return find_entity(pred);
+ }
+ case iro_Sub:
+ case iro_Add: {
+ ir_node *left = get_binop_left(ptr);
+ ir_node *right;
+ if (mode_is_reference(get_irn_mode(left)))
+ return find_entity(left);
+ right = get_binop_right(ptr);
+ if (mode_is_reference(get_irn_mode(right)))
+ return find_entity(right);
+ return NULL;
+ }
+ default:
+ return NULL;
+ }
+}
+
/**
* optimize a Store
*
* @param store the Store node
*/
static unsigned optimize_store(ir_node *store) {
- ir_node *ptr, *mem;
+ ir_node *ptr;
+ ir_node *mem;
+ ir_entity *entity;
if (get_Store_volatility(store) == volatility_is_volatile)
return 0;
- ptr = get_Store_ptr(store);
+ ptr = get_Store_ptr(store);
+ entity = find_entity(ptr);
+
+ /* a store to an entity which is never read is unnecessary */
+ if (entity != NULL && !(get_entity_usage(entity) & ir_usage_read)) {
+ ldst_info_t *info = get_irn_link(store);
+ if (info->projs[pn_Store_X_except] == NULL) {
+ exchange(info->projs[pn_Store_M], get_Store_mem(store));
+ kill_node(store);
+ reduce_adr_usage(ptr);
+ return DF_CHANGED;
+ }
+ }
/* Check, if the address of this Store is used more than once.
* If not, this Store cannot be removed in any case. */
/* Handle graph state */
if (env.changes) {
set_irg_outs_inconsistent(irg);
+ set_irg_entity_usage_state(irg, ir_entity_usage_not_computed);
}
if (env.changes & CF_CHANGED) {