X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Flower%2Flower_dw.c;h=fd4dca60cee9dc2f612e4a6bab901b07f16b1319;hb=8f97b69a6eb98c92e51190b7e2323ec8e0a1fa00;hp=88da4d410b0e0f9a55fcdd51123b07d2e10f1ce6;hpb=869f4ab61410553cccd7f01c82efda00fc226dbc;p=libfirm diff --git a/ir/lower/lower_dw.c b/ir/lower/lower_dw.c index 88da4d410..fd4dca60c 100644 --- a/ir/lower/lower_dw.c +++ b/ir/lower/lower_dw.c @@ -1,23 +1,33 @@ /* - * Project: libFIRM - * File name: ir/lower/lower_dw.c - * Purpose: Lower Double word operations, ie Mode L -> I. - * Author: Michael Beck - * Created: 8.10.2004 - * CVS-ID: $Id$ - * Copyright: (c) 1998-2006 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 Lower Double word operations, ie 64bit -> 32bit, 32bit -> 16bit etc. + * @date 8.10.2004 + * @author Michael Beck + * @version $Id$ */ #ifdef HAVE_CONFIG_H # include "config.h" #endif -#ifdef HAVE_MALLOC_H -# include -#endif -#ifdef HAVE_ALLOCA_H -# include -#endif #ifdef HAVE_STRING_H # include #endif @@ -27,6 +37,7 @@ #include +#include "lowering.h" #include "irnode_t.h" #include "irgraph_t.h" #include "irmode_t.h" @@ -39,7 +50,6 @@ #include "firmstat.h" #include "irgwalk.h" #include "ircons.h" -#include "lower_dw.h" #include "irflag.h" #include "irtools.h" #include "debug.h" @@ -47,6 +57,7 @@ #include "pmap.h" #include "pdeq.h" #include "irdump.h" +#include "xmalloc.h" /** A map from mode to a primitive type. */ static pmap *prim_types; @@ -73,7 +84,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 +101,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 */ }; /** @@ -312,42 +323,6 @@ static void prepare_links(ir_node *node, void *env) pmap_insert(lenv->proj_2_block, pred, node); } /* for */ } /* if */ - - /* handle support for Psi nodes */ - if (mode == mode_b || get_irn_op(node) == op_Psi) { - 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); - - if (is_Cmp(cmp)) { - ir_node *l = get_Cmp_left(cmp); - mode = get_irn_mode(l); - - if (mode == lenv->params->high_signed || - mode == lenv->params->high_unsigned) { - /* ok, found a node that will be lowered */ - ir_node *nproj; - int rem = get_optimize(); - - set_optimize(0); - nproj = new_rd_Proj( - get_irn_dbg_info(proj), - current_ir_graph, - get_nodes_block(proj), - cmp, - get_irn_mode(proj), - get_Proj_proj(proj)); - set_optimize(rem); - - set_irn_n(node, i, nproj); - lenv->flags |= MUST_BE_LOWERED; - } /* if */ - } /* if */ - } /* if */ - } /* for */ - } /* if */ } /* prepare_links */ /** @@ -449,6 +424,8 @@ static void lower_Store(ir_node *node, ir_mode *mode, lower_env_t *env) { dbg_info *dbg; int idx; node_entry_t *entry; + (void) node; + (void) mode; irn = get_Store_value(node); entry = env->entries[get_irn_idx(irn)]; @@ -526,7 +503,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; @@ -715,7 +692,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; @@ -1241,6 +1220,7 @@ static void lower_Cond(ir_node *node, ir_mode *mode, lower_env_t *env) { ir_node *sel = get_Cond_selector(node); ir_mode *m = get_irn_mode(sel); int idx; + (void) mode; if (m == mode_b) { node_entry_t *lentry, *rentry; @@ -1554,6 +1534,12 @@ static void lower_Conv_from_Ls(ir_node *node, lower_env_t *env) { assert(idx < env->n_entries); + if (! env->entries[idx]->low_word) { + /* not ready yet, wait */ + pdeq_putr(env->waitq, node); + return; + } /* if */ + if (mode_is_int(omode) || mode_is_reference(omode)) { op = env->entries[idx]->low_word; @@ -1592,6 +1578,12 @@ static void lower_Conv_from_Lu(ir_node *node, lower_env_t *env) { assert(idx < env->n_entries); + if (! env->entries[idx]->low_word) { + /* not ready yet, wait */ + pdeq_putr(env->waitq, node); + return; + } /* if */ + if (mode_is_int(omode) || mode_is_reference(omode)) { op = env->entries[idx]->low_word; @@ -1632,7 +1624,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 */ @@ -1735,12 +1727,13 @@ 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; + (void) mode; /* check if this return must be lowered */ for (i = 0, n = get_Return_n_ress(node); i < n; ++i) { @@ -1792,13 +1785,14 @@ 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; + (void) mode; if (is_lowered_type(tp)) { mtp = get_associated_type(tp); @@ -1886,6 +1880,7 @@ static void lower_Call(ir_node *node, ir_mode *mode, lower_env_t *env) { int n_params, n_res, need_lower = 0; int i, j; long *res_numbers = NULL; + (void) mode; if (is_lowered_type(tp)) { call_tp = get_associated_type(tp); @@ -2142,38 +2137,48 @@ static void lower_Psi(ir_node *psi, ir_mode *mode, lower_env_t *env) { } /* lower_Psi */ /** - * lower all marked Proj(Cmp) + * check for opcodes that must always be lowered. + */ +static int always_lower(ir_opcode code) { + switch (code) { + case iro_Proj: + case iro_Start: + case iro_Call: + case iro_Return: + case iro_Cond: + case iro_Conv: + return 1; + default: + return 0; + } /* switch */ +} /* always_lower */ + +/** + * lower boolean Proj(Cmp) */ -static void lower_Proj(ir_node *node, ir_mode *mode, lower_env_t *env) { - int idx, lidx, ridx; - ir_node *cmp, *l, *r, *low, *high, *t, *res; +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; - idx = get_irn_idx(node); - if (env->entries[idx] == NULL) - return; - - cmp = get_Proj_pred(node); - l = get_Cmp_left(cmp); + l = get_Cmp_left(cmp); lidx = get_irn_idx(l); if (! env->entries[lidx]->low_word) { /* still not ready */ - pdeq_putr(env->waitq, node); - return; + return NULL; } /* if */ - r = get_Cmp_right(cmp); + r = get_Cmp_right(cmp); ridx = get_irn_idx(r); if (! env->entries[ridx]->low_word) { /* still not ready */ - pdeq_putr(env->waitq, node); - return; + return NULL; } /* if */ - pnc = get_Proj_proj(node); + 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); @@ -2202,25 +2207,8 @@ static void lower_Proj(ir_node *node, ir_mode *mode, lower_env_t *env) { t, mode_b); } /* if */ - exchange(node, res); -} /* lower_Proj */ - -/** - * 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: - return 1; - default: - return 0; - } /* switch */ -} /* always_lower */ + return res; +} /* lower_boolean_Proj_Cmp */ /** * The type of a lower function. @@ -2239,6 +2227,36 @@ 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); + + 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))) { @@ -2246,7 +2264,7 @@ static void lower_ops(ir_node *node, void *env) 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; @@ -2267,6 +2285,7 @@ static void lower_ops(ir_node *node, void *env) static int cmp_op_mode(const void *elt, const void *key, size_t size) { const op_mode_entry_t *e1 = elt; const op_mode_entry_t *e2 = key; + (void) size; return (e1->op - e2->op) | (e1->imode - e2->imode) | (e1->omode - e2->omode); } /* cmp_op_mode */ @@ -2277,6 +2296,7 @@ static int cmp_op_mode(const void *elt, const void *key, size_t size) { static int cmp_conv_tp(const void *elt, const void *key, size_t size) { const conv_tp_entry_t *e1 = elt; const conv_tp_entry_t *e2 = key; + (void) size; return (e1->imode - e2->imode) | (e1->omode - e2->omode); } /* static int cmp_conv_tp */ @@ -2302,7 +2322,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) @@ -2312,13 +2332,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); @@ -2405,12 +2425,11 @@ void lower_dw_ops(const lwrdw_param_t *param) LOWER(Shr); LOWER(Shrs); LOWER(Rot); - LOWER2(Minus, lower_Minus); + LOWER(Minus); LOWER(DivMod); LOWER(Div); LOWER(Mod); LOWER_UN(Abs); - LOWER2(Proj, lower_Proj); LOWER(Conv); @@ -2461,8 +2480,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); @@ -2473,13 +2490,14 @@ 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; + (void) context; if (imode == omode) { snprintf(buf, sizeof(buf), "__l%s%s", get_op_name(op), get_mode_name(imode));