X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Flower%2Flower_dw.c;h=5d4a9670de30124275c6370e6fae97680ba72898;hb=be375dcbb1195db1ed6a7ea7e4787456fb1d7b4f;hp=abffdef2788f23fd489d90bba693e81936f44888;hpb=a8f70b24434c8c4b5ee3f689bfde7e86dd7d9e96;p=libfirm diff --git a/ir/lower/lower_dw.c b/ir/lower/lower_dw.c index abffdef27..5d4a9670d 100644 --- a/ir/lower/lower_dw.c +++ b/ir/lower/lower_dw.c @@ -3,7 +3,7 @@ * File name: ir/lower/lower_dw.c * Purpose: Lower Double word operations, ie Mode L -> I. * Author: Michael Beck - * Created: 8.10.2004 + * Created: 8.10.2004 * CVS-ID: $Id$ * Copyright: (c) 1998-2006 Universität Karlsruhe * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE. @@ -73,7 +73,7 @@ typedef struct _op_mode_entry { const ir_op *op; /**< the op */ const ir_mode *imode; /**< the input mode */ const ir_mode *omode; /**< the output mode */ - entity *ent; /**< the associated entity of this (op, imode, omode) triple */ + ir_entity *ent; /**< the associated entity of this (op, imode, omode) triple */ } op_mode_entry_t; /** @@ -90,13 +90,13 @@ typedef struct _conv_tp_entry { * we need some store to hold the replacement: */ typedef struct _node_entry_t { - ir_node *low_word; /**< the low word */ - ir_node *high_word; /**< the high word */ + ir_node *low_word; /**< the low word */ + ir_node *high_word; /**< the high word */ } node_entry_t; enum lower_flags { - MUST_BE_LOWERED = 1, /**< graph must be lowered */ - CF_CHANGED = 2, /**< control flow was changed */ + MUST_BE_LOWERED = 1, /**< graph must be lowered */ + CF_CHANGED = 2, /**< control flow was changed */ }; /** @@ -490,7 +490,7 @@ static ir_node *get_intrinsic_address(ir_type *method, ir_op *op, ir_mode *imode, ir_mode *omode, ir_node *block, lower_env_t *env) { symconst_symbol sym; - entity *ent; + ir_entity *ent; op_mode_entry_t key, *entry; key.op = op; @@ -679,7 +679,9 @@ static void lower_Mod(ir_node *node, ir_mode *mode, lower_env_t *env) { * Create two intrinsic Calls. */ static void lower_DivMod(ir_node *node, ir_mode *mode, lower_env_t *env) { - ir_node *block, *proj, *irn, *mem, *callDiv, *callMod, *resDiv, *resMod; + ir_node *block, *proj, *irn, *mem, *callDiv, *callMod; + ir_node *resDiv = NULL; + ir_node *resMod = NULL; ir_node *in[4]; ir_mode *opmode; dbg_info *dbg; @@ -1161,6 +1163,42 @@ static void lower_Not(ir_node *node, ir_mode *mode, lower_env_t *env) { env->entries[idx]->high_word = new_rd_Not(dbg, current_ir_graph, block, op_h, mode); } /* lower_Not */ +/** + * Translate a Minus. + * + * Create two Minus'. + */ +static void lower_Minus(ir_node *node, ir_mode *mode, lower_env_t *env) { + ir_node *block, *irn; + ir_node *op_l, *op_h; + dbg_info *dbg; + int idx; + ir_graph *irg; + node_entry_t *entry; + + irn = get_Minus_op(node); + entry = env->entries[get_irn_idx(irn)]; + assert(entry); + + if (! entry->low_word) { + /* not ready yet, wait */ + pdeq_putr(env->waitq, node); + return; + } /* if */ + + op_l = entry->low_word; + op_h = entry->high_word; + + dbg = get_irn_dbg_info(node); + block = get_nodes_block(node); + irg = current_ir_graph; + + idx = get_irn_idx(node); + assert(idx < env->n_entries); + env->entries[idx]->low_word = new_rd_Minus(dbg, current_ir_graph, block, op_l, mode); + env->entries[idx]->high_word = new_rd_Minus(dbg, current_ir_graph, block, op_h, mode); +} /* lower_Minus */ + /** * Translate a Cond. */ @@ -1292,7 +1330,7 @@ static void lower_Cond(ir_node *node, ir_mode *mode, lower_env_t *env) { mark_irn_visited(proj); exchange(projF, proj); } else { - /* a rel b <==> a_h rel b_h || (a_h == b_h && a_l rel b_l) */ + /* a rel b <==> a_h REL b_h || (a_h == b_h && a_l rel b_l) */ ir_node *dstT, *dstF, *newbl_eq, *newbl_l; pmap_entry *entry; @@ -1304,7 +1342,7 @@ static void lower_Cond(ir_node *node, ir_mode *mode, lower_env_t *env) { assert(entry); dstF = entry->value; - irn = new_r_Proj(irg, block, cmpH, mode_b, pnc); + irn = new_r_Proj(irg, block, cmpH, mode_b, pnc & ~pn_Cmp_Eq); dbg = get_irn_dbg_info(node); irn = new_rd_Cond(dbg, irg, block, irn); @@ -1560,7 +1598,7 @@ static void lower_Conv(ir_node *node, ir_mode *mode, lower_env_t *env) { if (mode == env->params->high_signed) { lower_Conv_from_Ls(node, env); - } else if (mode == env->params->high_unsigned) { + } else if (mode == env->params->high_unsigned) { lower_Conv_from_Lu(node, env); } /* if */ } /* if */ @@ -1663,12 +1701,12 @@ static ir_type *lower_mtp(ir_type *mtp, lower_env_t *env) { * Translate a Return. */ static void lower_Return(ir_node *node, ir_mode *mode, lower_env_t *env) { - ir_graph *irg = current_ir_graph; - entity *ent = get_irg_entity(irg); - ir_type *mtp = get_entity_type(ent); - ir_node **in; - int i, j, n, idx; - int need_conv = 0; + ir_graph *irg = current_ir_graph; + ir_entity *ent = get_irg_entity(irg); + ir_type *mtp = get_entity_type(ent); + ir_node **in; + int i, j, n, idx; + int need_conv = 0; /* check if this return must be lowered */ for (i = 0, n = get_Return_n_ress(node); i < n; ++i) { @@ -1720,13 +1758,13 @@ static void lower_Return(ir_node *node, ir_mode *mode, lower_env_t *env) { * Translate the parameters. */ static void lower_Start(ir_node *node, ir_mode *mode, lower_env_t *env) { - ir_graph *irg = current_ir_graph; - entity *ent = get_irg_entity(irg); - ir_type *tp = get_entity_type(ent); - ir_type *mtp; - long *new_projs; - int i, j, n_params, rem; - ir_node *proj, *args; + ir_graph *irg = current_ir_graph; + ir_entity *ent = get_irg_entity(irg); + ir_type *tp = get_entity_type(ent); + ir_type *mtp; + long *new_projs; + int i, j, n_params, rem; + ir_node *proj, *args; if (is_lowered_type(tp)) { mtp = get_associated_type(tp); @@ -2015,22 +2053,134 @@ static void lower_Phi(ir_node *phi, ir_mode *mode, lower_env_t *env) { } /* if */ } /* lower_Phi */ +/** + * Translate a Psi. + */ +static void lower_Psi(ir_node *psi, ir_mode *mode, lower_env_t *env) { + ir_graph *irg = current_ir_graph; + ir_node *block, *val; + ir_node **valsl, **valsh, **conds; + dbg_info *dbg; + int idx, i, n_conds = get_Psi_n_conds(psi); + + /* first create a new in array */ + NEW_ARR_A(ir_node *, valsl, n_conds + 1); + NEW_ARR_A(ir_node *, valsh, n_conds + 1); + + for (i = 0; i < n_conds; ++i) { + val = get_Psi_val(psi, i); + idx = get_irn_idx(val); + if (env->entries[idx]->low_word) { + /* Values already build */ + valsl[i] = env->entries[idx]->low_word; + valsh[i] = env->entries[idx]->high_word; + } else { + /* still not ready */ + pdeq_putr(env->waitq, psi); + return; + } /* if */ + } /* for */ + val = get_Psi_default(psi); + idx = get_irn_idx(val); + if (env->entries[idx]->low_word) { + /* Values already build */ + valsl[i] = env->entries[idx]->low_word; + valsh[i] = env->entries[idx]->high_word; + } else { + /* still not ready */ + pdeq_putr(env->waitq, psi); + return; + } /* if */ + + + NEW_ARR_A(ir_node *, conds, n_conds); + for (i = 0; i < n_conds; ++i) { + conds[i] = get_Psi_cond(psi, i); + } /* for */ + + dbg = get_irn_dbg_info(psi); + block = get_nodes_block(psi); + + idx = get_irn_idx(psi); + assert(idx < env->n_entries); + env->entries[idx]->low_word = new_rd_Psi(dbg, irg, block, n_conds, conds, valsl, mode); + env->entries[idx]->high_word = new_rd_Psi(dbg, irg, block, n_conds, conds, valsh, mode); +} /* lower_Psi */ + /** * check for opcodes that must always be lowered. */ static int always_lower(opcode code) { switch (code) { + case iro_Proj: case iro_Start: case iro_Call: case iro_Return: case iro_Cond: - case iro_Conv: + case iro_Conv: return 1; default: return 0; } /* switch */ } /* always_lower */ +/** + * lower boolean Proj(Cmp) + */ +static ir_node *lower_boolean_Proj_Cmp(ir_node *proj, ir_node *cmp, lower_env_t *env) { + int lidx, ridx; + ir_node *l, *r, *low, *high, *t, *res; + pn_Cmp pnc; + ir_node *blk; + ir_graph *irg = current_ir_graph; + dbg_info *db; + + l = get_Cmp_left(cmp); + lidx = get_irn_idx(l); + if (! env->entries[lidx]->low_word) { + /* still not ready */ + return NULL; + } /* if */ + + r = get_Cmp_right(cmp); + ridx = get_irn_idx(r); + if (! env->entries[ridx]->low_word) { + /* still not ready */ + return NULL; + } /* if */ + + pnc = get_Proj_proj(proj); + blk = get_nodes_block(cmp); + db = get_irn_dbg_info(cmp); + low = new_rd_Cmp(db, irg, blk, env->entries[lidx]->low_word, env->entries[ridx]->low_word); + high = new_rd_Cmp(db, irg, blk, env->entries[lidx]->high_word, env->entries[ridx]->high_word); + + if (pnc == pn_Cmp_Eq) { + /* simple case:a == b <==> a_h == b_h && a_l == b_l */ + res = new_rd_And(db, irg, blk, + new_r_Proj(irg, blk, low, mode_b, pnc), + new_r_Proj(irg, blk, high, mode_b, pnc), + mode_b); + } else if (pnc == pn_Cmp_Lg) { + /* simple case:a != b <==> a_h != b_h || a_l != b_l */ + res = new_rd_Or(db, irg, blk, + new_r_Proj(irg, blk, low, mode_b, pnc), + new_r_Proj(irg, blk, high, mode_b, pnc), + mode_b); + } else { + /* a rel b <==> a_h REL b_h || (a_h == b_h && a_l rel b_l) */ + t = new_rd_And(db, irg, blk, + new_r_Proj(irg, blk, low, mode_b, pnc), + new_r_Proj(irg, blk, high, mode_b, pn_Cmp_Eq), + mode_b); + res = new_rd_Or(db, irg, blk, + new_r_Proj(irg, blk, high, mode_b, pnc & ~pn_Cmp_Eq), + t, + mode_b); + } /* if */ + return res; +} /* lower_boolean_Proj_Cmp */ + /** * The type of a lower function. * @@ -2048,14 +2198,44 @@ static void lower_ops(ir_node *node, void *env) lower_env_t *lenv = env; node_entry_t *entry; int idx = get_irn_idx(node); + ir_mode *mode = get_irn_mode(node); + + if (mode == mode_b || get_irn_op(node) == op_Psi) { + int i; + + for (i = get_irn_arity(node) - 1; i >= 0; --i) { + ir_node *proj = get_irn_n(node, i); + + if (is_Proj(proj)) { + ir_node *cmp = get_Proj_pred(proj); - entry = lenv->entries[idx]; + if (is_Cmp(cmp)) { + ir_node *arg = get_Cmp_left(cmp); + + mode = get_irn_mode(arg); + if (mode == lenv->params->high_signed || + mode == lenv->params->high_unsigned) { + ir_node *res = lower_boolean_Proj_Cmp(proj, cmp, lenv); + + if (res == NULL) { + /* could not lower because predecessors not ready */ + waitq_put(lenv->waitq, node); + return; + } /* if */ + set_irn_n(node, i, res); + } /* if */ + } /* if */ + } /* if */ + } /* for */ + } /* if */ + + entry = idx < lenv->n_entries ? lenv->entries[idx] : NULL; if (entry || always_lower(get_irn_opcode(node))) { ir_op *op = get_irn_op(node); lower_func func = (lower_func)op->ops.generic; if (func) { - ir_mode *mode = get_irn_op_mode(node); + mode = get_irn_op_mode(node); if (mode == lenv->params->high_signed) mode = lenv->params->low_signed; @@ -2111,7 +2291,7 @@ void lower_dw_ops(const lwrdw_param_t *param) assert(2 * get_mode_size_bits(param->low_unsigned) == get_mode_size_bits(param->high_unsigned)); assert(get_mode_size_bits(param->low_signed) == get_mode_size_bits(param->low_unsigned)); - /* create the necessary maps */ + /* create the necessary maps */ if (! prim_types) prim_types = pmap_create(); if (! intrinsic_fkt) @@ -2121,13 +2301,13 @@ void lower_dw_ops(const lwrdw_param_t *param) if (! lowered_type) lowered_type = pmap_create(); - /* create a primitive unsigned and signed type */ + /* create a primitive unsigned and signed type */ if (! tp_u) tp_u = get_primitive_type(param->low_unsigned); if (! tp_s) tp_s = get_primitive_type(param->low_signed); - /* create method types for the created binop calls */ + /* create method types for the created binop calls */ if (! binop_tp_u) { binop_tp_u = new_type_method(IDENT("binop_u_intrinsic"), 4, 2); set_method_param_type(binop_tp_u, 0, tp_u); @@ -2191,7 +2371,7 @@ void lower_dw_ops(const lwrdw_param_t *param) #define LOWER_BIN(op) LOWER2(op, lower_Binop) #define LOWER_UN(op) LOWER2(op, lower_Unop) - /* the table of all operations that must be lowered follows */ + /* the table of all operations that must be lowered follows */ LOWER(Load); LOWER(Store); LOWER(Const); @@ -2204,6 +2384,7 @@ void lower_dw_ops(const lwrdw_param_t *param) LOWER(Call); LOWER(Unknown); LOWER(Phi); + LOWER(Psi); LOWER(Start); LOWER_BIN(Add); @@ -2213,7 +2394,7 @@ void lower_dw_ops(const lwrdw_param_t *param) LOWER(Shr); LOWER(Shrs); LOWER(Rot); - LOWER_UN(Minus); + LOWER(Minus); LOWER(DivMod); LOWER(Div); LOWER(Mod); @@ -2268,8 +2449,6 @@ void lower_dw_ops(const lwrdw_param_t *param) set_irg_extblk_inconsistent(irg); set_irg_loopinfo_inconsistent(irg); } /* if */ - - dump_ir_block_graph(irg, "-dw"); } /* if */ pmap_destroy(lenv.proj_2_block); free(lenv.entries); @@ -2280,13 +2459,13 @@ void lower_dw_ops(const lwrdw_param_t *param) } /* lower_dw_ops */ /* Default implementation. */ -entity *def_create_intrinsic_fkt(ir_type *method, const ir_op *op, - const ir_mode *imode, const ir_mode *omode, - void *context) +ir_entity *def_create_intrinsic_fkt(ir_type *method, const ir_op *op, + const ir_mode *imode, const ir_mode *omode, + void *context) { char buf[64]; ident *id; - entity *ent; + ir_entity *ent; if (imode == omode) { snprintf(buf, sizeof(buf), "__l%s%s", get_op_name(op), get_mode_name(imode));