X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Flower%2Flower_copyb.c;h=18f9fcd0b83e5b008acb396dbad2c45dcb652714;hb=07c77ebb4b165865ecdfc45a048ac55dea14d84e;hp=f35702071a8a9e8dfed2ed680b408d43e3072a07;hpb=bb3144f01520732c3e22858e820ed9f7ca8c912f;p=libfirm diff --git a/ir/lower/lower_copyb.c b/ir/lower/lower_copyb.c index f35702071..18f9fcd0b 100644 --- a/ir/lower/lower_copyb.c +++ b/ir/lower/lower_copyb.c @@ -21,7 +21,6 @@ * @file * @brief Lower small CopyB nodes into a series of Load/Store nodes * @author Michael Beck, Matthias Braun, Manuel Mohr - * @version $Id$ */ #include "config.h" @@ -35,6 +34,7 @@ #include "irtools.h" #include "irgmod.h" #include "error.h" +#include "be.h" typedef struct entry entry_t; struct entry { @@ -84,6 +84,9 @@ static unsigned max_small_size; /**< The maximum size of a CopyB node so that it is regarded as 'small'. */ static unsigned min_large_size; /**< The minimum size of a CopyB node so that it is regarded as 'large'. */ +static unsigned native_mode_bytes; /**< The size of the native mode in bytes. */ +static int allow_misalignments; /**< Whether backend can handle misaligned + loads and stores. */ typedef struct walk_env { struct obstack obst; /**< the obstack where data is allocated @@ -91,9 +94,9 @@ typedef struct walk_env { struct list_head list; /**< the list of copyb nodes. */ } walk_env_t; -static ir_mode *get_ir_mode(unsigned bytes) +static ir_mode *get_ir_mode(unsigned mode_bytes) { - switch (bytes) { + switch (mode_bytes) { case 1: return mode_Bu; case 2: return mode_Hu; case 4: return mode_Iu; @@ -107,29 +110,20 @@ static ir_mode *get_ir_mode(unsigned bytes) /** * Turn a small CopyB node into a series of Load/Store nodes. */ -static void lower_small_copyb_node(ir_node *irn, unsigned mode_bytes) +static void lower_small_copyb_node(ir_node *irn) { - ir_graph *irg = get_irn_irg(irn); - unsigned size; - unsigned offset; + ir_graph *irg = get_irn_irg(irn); + ir_node *block = get_nodes_block(irn); + ir_type *tp = get_CopyB_type(irn); + ir_node *addr_src = get_CopyB_src(irn); + ir_node *addr_dst = get_CopyB_dst(irn); + ir_node *mem = get_CopyB_mem(irn); + ir_mode *addr_mode = get_irn_mode(addr_src); + unsigned mode_bytes = allow_misalignments ? native_mode_bytes : tp->align; + unsigned size = get_type_size_bytes(tp); + unsigned offset = 0; ir_mode *mode; - ir_mode *addr_mode; - ir_node *mem; - ir_node *addr_src; - ir_node *addr_dst; - ir_node *block; - ir_type *tp; - - addr_src = get_CopyB_src(irn); - addr_dst = get_CopyB_dst(irn); - mem = get_CopyB_mem(irn); - addr_mode = get_irn_mode(addr_src); - block = get_nodes_block(irn); - - tp = get_CopyB_type(irn); - size = get_type_size_bytes(tp); - - offset = 0; + while (offset < size) { mode = get_ir_mode(mode_bytes); for (; offset + mode_bytes <= size; offset += mode_bytes) { @@ -167,13 +161,14 @@ static void lower_small_copyb_node(ir_node *irn, unsigned mode_bytes) set_Tuple_pred(irn, pn_CopyB_X_except, new_r_Bad(irg, mode_X)); } -static ir_type *get_memcpy_methodtype() +static ir_type *get_memcpy_methodtype(void) { - ir_type *tp = new_type_method(3, 1); + ir_type *tp = new_type_method(3, 1); + ir_mode *size_t_mode = get_ir_mode(native_mode_bytes); set_method_param_type(tp, 0, get_type_for_mode(mode_P)); set_method_param_type(tp, 1, get_type_for_mode(mode_P)); - set_method_param_type(tp, 2, get_type_for_mode(mode_Lu)); + set_method_param_type(tp, 2, get_type_for_mode(size_t_mode)); set_method_res_type (tp, 0, get_type_for_mode(mode_P)); return tp; @@ -183,12 +178,10 @@ static ir_node *get_memcpy_symconst(ir_graph *irg) { ident *id = new_id_from_str("memcpy"); ir_type *mt = get_memcpy_methodtype(); - ir_entity *ent = new_entity(get_glob_type(), id, mt); + ir_entity *ent = create_compilerlib_entity(id, mt); symconst_symbol sym; - set_entity_ld_ident(ent, get_entity_ident(ent)); sym.entity_p = ent; - return new_r_SymConst(irg, mode_P_code, sym, symconst_addr_ent); } @@ -206,15 +199,16 @@ static void lower_large_copyb_node(ir_node *irn) ir_type *copyb_tp = get_CopyB_type(irn); unsigned size = get_type_size_bytes(copyb_tp); - ir_node *symconst = get_memcpy_symconst(irg); - ir_type *call_tp = get_memcpy_methodtype(); + ir_node *symconst = get_memcpy_symconst(irg); + ir_type *call_tp = get_memcpy_methodtype(); + ir_mode *mode_size_t = get_ir_mode(native_mode_bytes); ir_node *in[3]; ir_node *call; ir_node *call_mem; in[0] = addr_dst; in[1] = addr_src; - in[2] = new_r_Const_long(irg, mode_Lu, size); + in[2] = new_r_Const_long(irg, mode_size_t, size); call = new_rd_Call(dbgi, block, mem, symconst, 3, in, call_tp); call_mem = new_r_Proj(call, mode_M, pn_Call_M); @@ -222,13 +216,13 @@ static void lower_large_copyb_node(ir_node *irn) set_irn_n(irn, pn_CopyB_M, call_mem); } -static void lower_copyb_node(ir_node *irn, unsigned native_mode_bytes) +static void lower_copyb_node(ir_node *irn) { ir_type *tp = get_CopyB_type(irn); unsigned size = get_type_size_bytes(tp); if (size <= max_small_size) - lower_small_copyb_node(irn, native_mode_bytes); + lower_small_copyb_node(irn); else if (size >= min_large_size) lower_large_copyb_node(irn); else @@ -277,21 +271,26 @@ static void find_copyb_nodes(ir_node *irn, void *ctx) list_add_tail(&entry->list, &env->list); } -void lower_CopyB(ir_graph *irg, unsigned max_small_sz, - unsigned min_large_sz, unsigned native_mode_bytes) +void lower_CopyB(ir_graph *irg, unsigned max_small_sz, unsigned min_large_sz, + int allow_misaligns) { - walk_env_t env; - entry_t *entry; + const backend_params *bparams = be_get_backend_param(); + walk_env_t env; + entry_t *entry; + assert(max_small_sz < min_large_sz && "CopyB size ranges must not overlap"); + max_small_size = max_small_sz; + min_large_size = min_large_sz; + native_mode_bytes = bparams->machine_size / 8; + allow_misalignments = allow_misaligns; + obstack_init(&env.obst); - max_small_size = max_small_sz; - min_large_size = min_large_sz; INIT_LIST_HEAD(&env.list); irg_walk_graph(irg, NULL, find_copyb_nodes, &env); list_for_each_entry(entry_t, entry, &env.list, list) { - lower_copyb_node(entry->copyb, native_mode_bytes); + lower_copyb_node(entry->copyb); } obstack_free(&env.obst, NULL);