From: Matthias Braun Date: Fri, 7 Mar 2008 16:32:19 +0000 (+0000) Subject: a better version of a copyb lowerer X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=83811ec18bcb88ff5a45c8b10303636d34bf67ee;p=libfirm a better version of a copyb lowerer [r18000] --- diff --git a/include/libfirm/lowering.h b/include/libfirm/lowering.h index d6aadcb6c..0ddb1c1e9 100644 --- a/include/libfirm/lowering.h +++ b/include/libfirm/lowering.h @@ -144,6 +144,12 @@ typedef struct { */ void lower_calls_with_compounds(const lower_params_t *params); +/** + * * Lower CopyB nodes of size smaller that max_size into Loads/Stores + */ +void lower_CopyB(ir_graph *irg, unsigned max_size, unsigned native_mode_bytes); + + /** * A callback type for creating an intrinsic entity for a given opcode. * diff --git a/ir/lower/lower_copyb.c b/ir/lower/lower_copyb.c index edfd9a7a5..aa17a52b8 100644 --- a/ir/lower/lower_copyb.c +++ b/ir/lower/lower_copyb.c @@ -20,7 +20,7 @@ /** * @file * @brief Lower small CopyB nodes into a series of Load/store - * @author Michael Beck + * @author Matthias Braun, Michael Beck * @version $Id$ */ #ifdef HAVE_CONFIG_H @@ -30,59 +30,48 @@ #include "ircons.h" #include "lowering.h" #include "irprog_t.h" +#include "irgwalk.h" #include "irnode_t.h" #include "type_t.h" #include "irtools.h" - -typedef struct copyb_env { - ir_node *next; /**< link to the next one */ -} copyb_env; - - -typedef struct walker_env { - struct obstack obst; /**< temporary space */ - int max_size; - ir_node *list; /**< list of CopyB nodes. */ -} walker_env; - -/** - * Build a graph that copies an entity of type tp from src to tgt - */ -static ir_node *build_copy_graph(dbg_info *dbg, ir_node *blk, ir_node *mem, ir_node *src, ir_node *tgt, ir_type *tp) { - int i, n; - - if (is_Array_type(tp)) { - assert(0); - } else { - for (i = 0, n = get_compound_n_members(tp); i < n; ++i) { - ir_entity *ent = get_compound_member(tp, i); - ir_node *s = new_d_simpleSel(dbg, mem, src, ent); - ir_node *d = new_d_simpleSel(dbg, mem, tgt, ent); - ir_type *ent_tp = get_entity_type(ent); - - if (is_atomic_type(ent_tp)) { - ir_mode *mode = get_type_mode(ent_tp); - ir_node *irn = new_rd_Load(dbg, current_ir_graph, blk, mem, s, mode); - ir_node *res = new_r_Proj(current_ir_graph, blk, irn, mode, pn_Load_res); - - mem = new_r_Proj(current_ir_graph, blk, irn, mode_M, pn_Load_M); - irn = new_rd_Store(dbg, current_ir_graph, blk, mem, d, res); - mem = new_r_Proj(current_ir_graph, blk, irn, mode_M, pn_Store_M); - } else { - mem = build_copy_graph(dbg, blk, mem, s, d, ent_tp); - } - } +#include "iredges_t.h" +#include "irgmod.h" +#include "error.h" + +static unsigned max_size; +static unsigned native_mode_bytes; + +static ir_mode *get_ir_mode(unsigned bytes) +{ + switch(bytes) { + case 1: return mode_Bu; + case 2: return mode_Hu; + case 4: return mode_Iu; + case 8: return mode_Lu; + case 16: return mode_LLu; + default: + panic("unexpected mode size requested in copyb lowering"); } - return mem; } /** * Walker: lower small CopyB nodes. */ static void lower_copyb_nodes(ir_node *irn, void *ctx) { - ir_type *tp; - int size; - walker_env *env = ctx; + ir_graph *irg = current_ir_graph; + ir_type *tp; + unsigned size; + unsigned mode_bytes; + unsigned offset; + ir_mode *mode; + ir_mode *addr_mode; + ir_node *mem; + ir_node *addr_src; + ir_node *addr_dst; + ir_node *block; + ir_node *proj_M = NULL; + const ir_edge_t *edge; + (void) ctx; if (! is_CopyB(irn)) return; @@ -92,26 +81,74 @@ static void lower_copyb_nodes(ir_node *irn, void *ctx) { return; size = get_type_size_bytes(tp); - if (size > env->max_size) + if (size > max_size) return; - /* for now, we can only handle Struct's */ - if (is_Struct_type(tp)) { - irn = build_copy_graph(get_irn_dbg_info(irn), get_nodes_block(irn), get_CopyB_mem(irn), get_CopyB_src(irn), get_CopyB_dst(irn), tp); + foreach_out_edge(irn, edge) { + ir_node *node = get_edge_src_irn(edge); + long pn = get_Proj_proj(node); + + /* we don't lower copybs with exception edges (yet) */ + if(pn == pn_CopyB_X_except) + return; + if(pn == pn_CopyB_M_regular) { + assert(proj_M == NULL); + proj_M = node; + } + } + if(proj_M == NULL) { + panic("no projM on copyb"); } -} -/** - * Lower CopyB nodes of size smaller that max_size into Loads/Stores - */ -void lower_CopyB(int max_size) { - walker_env env; - int i; - - obstack_init(&env.obst); - env.max_size = max_size; - env.list = NULL; - for (i = get_irp_n_irgs() - 1; i >= 0; --i) { - irg_walk_graph(get_irp_irg(i), firm_clear_link, lower_copyb_nodes, NULL); + 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); + + offset = 0; + mode_bytes = native_mode_bytes; + while(offset < size) { + mode = get_ir_mode(mode_bytes); + for( ; offset + mode_bytes <= size; offset += mode_bytes) { + /* construct offset */ + ir_node *addr_const; + ir_node *add; + ir_node *load; + ir_node *load_res; + ir_node *load_mem; + ir_node *store; + ir_node *store_mem; + + addr_const = new_r_Const_long(irg, block, mode_Iu, offset); + add = new_r_Add(irg, block, addr_src, addr_const, addr_mode); + + load = new_r_Load(irg, block, mem, add, mode); + load_res = new_r_Proj(irg, block, load, mode, pn_Load_res); + load_mem = new_r_Proj(irg, block, load, mode_M, pn_Load_M); + + addr_const = new_r_Const_long(irg, block, mode_Iu, offset); + add = new_r_Add(irg, block, addr_dst, addr_const, addr_mode); + + store = new_r_Store(irg, block, mem, add, load_res); + store_mem = new_r_Proj(irg, block, store, mode_M, pn_Store_M); + + mem = store_mem; + } + + mode_bytes /= 2; } + + exchange(proj_M, mem); +} + +void lower_CopyB(ir_graph *irg, unsigned new_max_size, + unsigned new_native_mode_bytes) +{ + max_size = new_max_size; + native_mode_bytes = new_native_mode_bytes; + + edges_assure(irg); + + irg_walk_graph(irg, NULL, lower_copyb_nodes, NULL); } diff --git a/ir/lower/lower_hl.c b/ir/lower/lower_hl.c index 4d5c336a9..70730bd8e 100644 --- a/ir/lower/lower_hl.c +++ b/ir/lower/lower_hl.c @@ -223,8 +223,10 @@ static void lower_sel(ir_node *sel) { newn = get_Sel_ptr(sel); offset = get_entity_offset(ent); if (offset != 0) { - tv = new_tarval_from_long(offset, mode_Int); - cnst = new_r_Const(irg, get_irg_start_block(irg), mode_Int, tv); + ir_mode *mode_UInt = get_reference_mode_unsigned_eq(mode); + + tv = new_tarval_from_long(offset, mode_UInt); + cnst = new_r_Const(irg, get_irg_start_block(irg), mode_UInt, tv); newn = new_rd_Add(dbg, irg, bl, newn, cnst, mode); } } else {