X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fopt%2Fscalar_replace.c;h=d0739ad8c1f2087d5fdf843945c59bf8a081137f;hb=e9924cc1137b5920e75f4b9f2e99195dce708433;hp=55e66d01ba98408a336221573ca4ed95e2173a69;hpb=c2df29899c20179098894a159bb242e10a5cbb7c;p=libfirm diff --git a/ir/opt/scalar_replace.c b/ir/opt/scalar_replace.c index 55e66d01b..d0739ad8c 100644 --- a/ir/opt/scalar_replace.c +++ b/ir/opt/scalar_replace.c @@ -1,30 +1,35 @@ /* - * Project: libFIRM - * File name: ir/opt/scalar_replace.c - * Purpose: scalar replacement of arrays and compounds - * Author: Beyhan Veliev - * Modified by: Michael Beck - * Created: - * CVS-ID: $Id$ - * Copyright: (c) 1998-2005 Universität Karlsruhe - * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE. + * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved. + * + * This file is part of libFirm. + * + * This file may be distributed and/or modified under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation and appearing in the file LICENSE.GPL included in the + * packaging of this file. + * + * Licensees holding valid libFirm Professional Edition licenses may use + * this file in accordance with the libFirm Commercial License. + * Agreement provided with the Software. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE. + */ + +/** + * @file + * @brief Scalar replacement of compounds. + * @author Beyhan Veliev, Michael Beck + * @version $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif -#ifdef HAVE_ALLOCA_H -#include -#endif - -#ifdef HAVE_MALLOC_H -#include -#endif - -#ifdef HAVE_STRING_H #include -#endif +#include "iroptimize.h" #include "scalar_replace.h" #include "irflag_t.h" #include "irouts.h" @@ -38,6 +43,7 @@ #include "irgmod.h" #include "irnode_t.h" #include "irtools.h" +#include "xmalloc.h" #define SET_VNUM(node, vnum) set_irn_link(node, INT_TO_PTR(vnum)) #define GET_VNUM(node) (unsigned)PTR_TO_INT(get_irn_link(node)) @@ -48,7 +54,7 @@ * accesses like a.b.c[8].d */ typedef union { - entity *ent; + ir_entity *ent; tarval *tv; } path_elem_t; @@ -66,7 +72,7 @@ typedef struct _path_t { #define PATH_SIZE(p) (sizeof(*(p)) + sizeof((p)->path[0]) * ((p)->path_len - 1)) typedef struct _scalars_t { - entity *ent; /**< A entity for scalar replacement. */ + ir_entity *ent; /**< A entity for scalar replacement. */ ir_type *ent_owner; /**< The owner of this entity. */ } scalars_t; @@ -80,6 +86,7 @@ static int path_cmp(const void *elt, const void *key, size_t size) { const path_t *p1 = elt; const path_t *p2 = key; + (void) size; /* we can use memcmp here, because identical tarvals should have identical addresses */ return memcmp(p1->path, p2->path, p1->path_len * sizeof(p1->path[0])); @@ -94,6 +101,7 @@ static int ent_cmp(const void *elt, const void *key, size_t size) { const scalars_t *c1 = elt; const scalars_t *c2 = key; + (void) size; return c1->ent != c2->ent; } @@ -129,13 +137,45 @@ static int is_const_sel(ir_node *sel) { return 1; } +/** + * Check the mode of a Load/Store with the mode of the entity + * that is accessed. + * If the mode of the entity and the Load/Store mode do not match, we + * have the bad reinterpret case: + * + * int i; + * char b = *(char *)&i; + * + * We do NOT count this as one value and return address_taken + * in that case. + * However, we support an often used case. If the mode is two-complement + * we allow casts between signed/unsigned. + * + * @param mode the mode of the Load/Store + * @param ent_mode the mode of the accessed entity + */ +static int check_load_store_mode(ir_mode *mode, ir_mode *ent_mode) { + if (ent_mode != mode) { + if (ent_mode == NULL || + get_mode_size_bits(ent_mode) != get_mode_size_bits(mode) || + get_mode_sort(ent_mode) != get_mode_sort(mode) || + get_mode_arithmetic(ent_mode) != irma_twos_complement || + get_mode_arithmetic(mode) != irma_twos_complement) + return 0; + } + return 1; +} + /* * Returns non-zero, if the address of an entity * represented by a Sel node (or it's successor Sels) is taken. */ int is_address_taken(ir_node *sel) { - int i; + int i; + ir_mode *emode, *mode; + ir_node *value; + ir_entity *ent; if (! is_const_sel(sel)) return 1; @@ -145,12 +185,24 @@ int is_address_taken(ir_node *sel) switch (get_irn_opcode(succ)) { case iro_Load: - /* ok, we just load from that entity */ + /* check if this load is not a hidden conversion */ + mode = get_Load_mode(succ); + ent = get_Sel_entity(sel); + emode = get_type_mode(get_entity_type(ent)); + if (! check_load_store_mode(mode, emode)) + return 1; break; case iro_Store: /* check that Sel is not the Store's value */ - if (get_Store_value(succ) == sel) + value = get_Store_value(succ); + if (value == sel) + return 1; + /* check if this Store is not a hidden conversion */ + mode = get_irn_mode(value); + ent = get_Sel_entity(sel); + emode = get_type_mode(get_entity_type(ent)); + if (! check_load_store_mode(mode, emode)) return 1; break; @@ -184,7 +236,7 @@ int is_address_taken(ir_node *sel) * @param ent the entity that will be scalar replaced * @param sel a Sel node that selects some fields of this entity */ -static void link_all_leave_sels(entity *ent, ir_node *sel) +static void link_all_leave_sels(ir_entity *ent, ir_node *sel) { int i, n, flag = 1; @@ -256,7 +308,7 @@ static int find_possible_replacements(ir_graph *irg) ir_node *succ = get_irn_out(irg_frame, i); if (is_Sel(succ)) { - entity *ent = get_Sel_entity(succ); + ir_entity *ent = get_Sel_entity(succ); set_entity_link(ent, NULL); } } @@ -270,7 +322,7 @@ static int find_possible_replacements(ir_graph *irg) ir_node *succ = get_irn_out(irg_frame, i); if (is_Sel(succ)) { - entity *ent = get_Sel_entity(succ); + ir_entity *ent = get_Sel_entity(succ); ir_type *ent_type; if (get_entity_link(ent) == ADDRESS_TAKEN) @@ -358,7 +410,7 @@ static path_t *find_path(ir_node *sel, unsigned len) * * @return the next free value number */ -static unsigned allocate_value_numbers(pset *sels, entity *ent, unsigned vnum, ir_mode ***modes) +static unsigned allocate_value_numbers(pset *sels, ir_entity *ent, unsigned vnum, ir_mode ***modes) { ir_node *sel, *next; path_t *key, *path; @@ -377,14 +429,12 @@ static unsigned allocate_value_numbers(pset *sels, entity *ent, unsigned vnum, i if (path) SET_VNUM(sel, path->vnum); else { - unsigned i; - key->vnum = vnum++; set_insert(pathes, key, PATH_SIZE(key), path_hash(key)); SET_VNUM(sel, key->vnum); - ARR_EXTO(ir_mode *, *modes, (key->vnum + 15) & ~15); + ARR_EXTO(ir_mode *, *modes, (int)((key->vnum + 15) & ~15)); (*modes)[key->vnum] = get_type_mode(get_entity_type(get_Sel_entity(sel))); @@ -393,6 +443,7 @@ static unsigned allocate_value_numbers(pset *sels, entity *ent, unsigned vnum, i #ifdef DEBUG_libfirm /* Debug output */ if (get_opt_scalar_replacement_verbose() && get_firm_verbosity() > 1) { + unsigned i; printf(" %s", get_entity_name(key->path[0].ent)); for (i = 1; i < key->path_len; ++i) { if (is_entity(key->path[i].ent)) @@ -467,7 +518,7 @@ static void topologic_walker(ir_node *node, void *ctx) if (value_arr[vnum]) { mem = get_Load_mem(node); - /* Beware: A load can contain a hidden conversion in Firm. + /* Beware: A Load can contain a hidden conversion in Firm. This happens for instance in the following code: int i; @@ -480,9 +531,10 @@ static void topologic_walker(ir_node *node, void *ctx) val = new_d_Conv(get_irn_dbg_info(node), val, mode); turn_into_tuple(node, pn_Load_max); - set_Tuple_pred(node, pn_Load_M, mem); - set_Tuple_pred(node, pn_Load_res, val); - set_Tuple_pred(node, pn_Load_X_except, new_Bad()); + set_Tuple_pred(node, pn_Load_M, mem); + set_Tuple_pred(node, pn_Load_res, val); + set_Tuple_pred(node, pn_Load_X_regular, new_r_Jmp(current_ir_graph, block)); + set_Tuple_pred(node, pn_Load_X_except, new_Bad()); } else { l = obstack_alloc(&env->obst, sizeof(*l)); l->node = node; @@ -508,13 +560,19 @@ static void topologic_walker(ir_node *node, void *ctx) block = get_nodes_block(node); value_arr = get_irn_link(block); - value_arr[vnum] = get_Store_value(node); + /* Beware: A Store can contain a hidden conversion in Firm. */ + val = get_Store_value(node); + if (get_irn_mode(val) != env->modes[vnum]) + val = new_d_Conv(get_irn_dbg_info(node), val, env->modes[vnum]); + value_arr[vnum] = val; mem = get_Store_mem(node); + block = get_nodes_block(node); turn_into_tuple(node, pn_Store_max); - set_Tuple_pred(node, pn_Store_M, mem); - set_Tuple_pred(node, pn_Store_X_except, new_Bad()); + set_Tuple_pred(node, pn_Store_M, mem); + set_Tuple_pred(node, pn_Store_X_regular, new_r_Jmp(current_ir_graph, block)); + set_Tuple_pred(node, pn_Store_X_except, new_Bad()); } else if (op == op_Phi && get_irn_mode(node) == mode_M) { /* * found a memory Phi: Here, we must create new Phi nodes @@ -641,17 +699,19 @@ static void fix_loads(env_t *env) val = new_Unknown(env->modes[l->vnum]); } - mem = get_Load_mem(load); - /* Beware: A load can contain a hidden conversion in Firm. + /* Beware: A Load can contain a hidden conversion in Firm. Handle this here. */ mode = get_Load_mode(load); if (mode != get_irn_mode(val)) val = new_d_Conv(get_irn_dbg_info(load), val, mode); + mem = get_Load_mem(load); + turn_into_tuple(load, pn_Load_max); - set_Tuple_pred(load, pn_Load_M, mem); - set_Tuple_pred(load, pn_Load_res, val); - set_Tuple_pred(load, pn_Load_X_except, new_Bad()); + set_Tuple_pred(load, pn_Load_M, mem); + set_Tuple_pred(load, pn_Load_res, val); + set_Tuple_pred(load, pn_Load_X_regular, new_r_Jmp(current_ir_graph, block)); + set_Tuple_pred(load, pn_Load_X_except, new_Bad()); } } @@ -733,7 +793,7 @@ void scalar_replacement_opt(ir_graph *irg) ir_node *succ = get_irn_out(irg_frame, i); if (is_Sel(succ)) { - entity *ent = get_Sel_entity(succ); + ir_entity *ent = get_Sel_entity(succ); if (get_entity_link(ent) == NULL || get_entity_link(ent) == ADDRESS_TAKEN) continue;