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 {
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);
}
}
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) {