X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Flower%2Flower_dw.c;h=5d4a9670de30124275c6370e6fae97680ba72898;hb=be375dcbb1195db1ed6a7ea7e4787456fb1d7b4f;hp=d9fdcd89a2b57194a5799658fa301be725aa8791;hpb=fe4f77964d4e6ba956330c59a5addfe5d45b1702;p=libfirm diff --git a/ir/lower/lower_dw.c b/ir/lower/lower_dw.c index d9fdcd89a..5d4a9670d 100644 --- a/ir/lower/lower_dw.c +++ b/ir/lower/lower_dw.c @@ -1,10 +1,12 @@ -/** - * @file irlwrdw.c - * @date 8.10.2004 - * @author Michael Beck - * @brief Lower Double word operations, ie Mode L -> I. - * - * $Id$ +/* + * 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. */ #ifdef HAVE_CONFIG_H # include "config.h" @@ -71,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; /** @@ -88,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 */ }; /** @@ -128,7 +130,7 @@ static ir_type *get_primitive_type(ir_mode *mode) { pmap_insert(prim_types, mode, tp); return tp; -} +} /* get_primitive_type */ /** * Create a method type for a Conv emulation from imode to omode. @@ -160,36 +162,31 @@ static ir_type *get_conv_type(ir_mode *imode, ir_mode *omode, lower_env_t *env) if (imode == env->params->high_signed) { set_method_param_type(mtd, n_param++, tp_s); set_method_param_type(mtd, n_param++, tp_s); - } - else if (imode == env->params->high_unsigned) { + } else if (imode == env->params->high_unsigned) { set_method_param_type(mtd, n_param++, tp_u); set_method_param_type(mtd, n_param++, tp_u); - } - else { + } else { ir_type *tp = get_primitive_type(imode); set_method_param_type(mtd, n_param++, tp); - } + } /* if */ n_res = 0; if (omode == env->params->high_signed) { set_method_res_type(mtd, n_res++, tp_s); set_method_res_type(mtd, n_res++, tp_s); - } - else if (omode == env->params->high_unsigned) { + } else if (omode == env->params->high_unsigned) { set_method_res_type(mtd, n_res++, tp_u); set_method_res_type(mtd, n_res++, tp_u); - } - else { + } else { ir_type *tp = get_primitive_type(omode); set_method_res_type(mtd, n_res++, tp); - } - + } /* if */ entry->mtd = mtd; - } - else + } else { mtd = entry->mtd; + } /* if */ return mtd; -} +} /* get_conv_type */ /** * Add an additional control flow input to a block. @@ -215,8 +212,8 @@ static void add_block_cf_input_nr(ir_node *block, int nr, ir_node *cf) in[i] = get_irn_n(phi, i); in[i] = in[nr]; set_irn_in(phi, i + 1, in); - } -} + } /* for */ +} /* add_block_cf_input_nr */ /** * Add an additional control flow input to a block. @@ -232,11 +229,11 @@ static void add_block_cf_input(ir_node *block, ir_node *tmpl, ir_node *cf) if (get_irn_n(block, i) == tmpl) { nr = i; break; - } - } + } /* if */ + } /* for */ assert(i < arity); add_block_cf_input_nr(block, nr, cf); -} +} /* add_block_cf_input */ /** * Return the "operational" mode of a Firm node. @@ -246,29 +243,23 @@ static ir_mode *get_irn_op_mode(ir_node *node) switch (get_irn_opcode(node)) { case iro_Load: return get_Load_mode(node); - case iro_Store: return get_irn_mode(get_Store_value(node)); - case iro_DivMod: return get_irn_mode(get_DivMod_left(node)); - case iro_Div: return get_irn_mode(get_Div_left(node)); - case iro_Mod: return get_irn_mode(get_Mod_left(node)); - case iro_Cmp: return get_irn_mode(get_Cmp_left(node)); - default: return get_irn_mode(node); - } -} + } /* switch */ +} /* get_irn_op_mode */ /** - * walker, prepare the node links + * Walker, prepare the node links. */ static void prepare_links(ir_node *node, void *env) { @@ -286,24 +277,18 @@ static void prepare_links(ir_node *node, void *env) lenv->entries[get_irn_idx(node)] = link; lenv->flags |= MUST_BE_LOWERED; - } - else if (get_irn_op(node) == op_Conv) { + } else if (get_irn_op(node) == op_Conv) { /* Conv nodes have two modes */ ir_node *pred = get_Conv_op(node); mode = get_irn_mode(pred); if (mode == lenv->params->high_signed || mode == lenv->params->high_unsigned) { - /* must lower this node either */ - link = obstack_alloc(&lenv->obst, sizeof(*link)); - - memset(link, 0, sizeof(*link)); - - lenv->entries[get_irn_idx(node)] = link; + /* must lower this node either but don't need a link */ lenv->flags |= MUST_BE_LOWERED; - } + } /* if */ return; - } + } /* if */ if (is_Proj(node)) { /* link all Proj nodes to its predecessor: @@ -312,24 +297,22 @@ static void prepare_links(ir_node *node, void *env) set_irn_link(node, get_irn_link(pred)); set_irn_link(pred, node); - } - else if (is_Phi(node)) { + } else if (is_Phi(node)) { /* link all Phi nodes to its block */ ir_node *block = get_nodes_block(node); set_irn_link(node, get_irn_link(block)); set_irn_link(block, node); - } - else if (is_Block(node)) { + } else if (is_Block(node)) { /* fill the Proj -> Block map */ for (i = get_Block_n_cfgpreds(node) - 1; i >= 0; --i) { ir_node *pred = get_Block_cfgpred(node, i); if (is_Proj(pred)) pmap_insert(lenv->proj_2_block, pred, node); - } - } -} + } /* for */ + } /* if */ +} /* prepare_links */ /** * Translate a Constant: create two. @@ -340,20 +323,21 @@ static void lower_Const(ir_node *node, ir_mode *mode, lower_env_t *env) { dbg_info *dbg = get_irn_dbg_info(node); ir_node *block = get_nodes_block(node); int idx; + ir_graph *irg = current_ir_graph; tv = get_Const_tarval(node); tv_l = tarval_convert_to(tv, mode); - low = new_rd_Const(dbg, current_ir_graph, block, mode, tv_l); + low = new_rd_Const(dbg, irg, block, mode, tv_l); tv_h = tarval_convert_to(tarval_shrs(tv, env->tv_mode_bits), mode); - high = new_rd_Const(dbg, current_ir_graph, block, mode, tv_h); + high = new_rd_Const(dbg, irg, block, mode, tv_h); idx = get_irn_idx(node); assert(idx < env->n_entries); env->entries[idx]->low_word = low; env->entries[idx]->high_word = high; -} +} /* lower_Const */ /** * Translate a Load: create two. @@ -372,13 +356,12 @@ static void lower_Load(ir_node *node, ir_mode *mode, lower_env_t *env) { high = new_r_Add(irg, block, adr, new_r_Const(irg, block, get_tarval_mode(env->tv_mode_bytes), env->tv_mode_bytes), get_irn_mode(adr)); - } - else { + } else { low = new_r_Add(irg, block, adr, new_r_Const(irg, block, get_tarval_mode(env->tv_mode_bytes), env->tv_mode_bytes), get_irn_mode(adr)); high = adr; - } + } /* if */ /* create two loads */ dbg = get_irn_dbg_info(node); @@ -413,12 +396,12 @@ static void lower_Load(ir_node *node, ir_mode *mode, lower_env_t *env) { break; default: assert(0 && "unexpected Proj number"); - } + } /* switch */ /* mark this proj: we have handled it already, otherwise we might fall into * out new nodes. */ mark_irn_visited(proj); - } -} + } /* for */ +} /* lower_Load */ /** * Translate a Store: create two. @@ -439,7 +422,7 @@ static void lower_Store(ir_node *node, ir_mode *mode, lower_env_t *env) { /* not ready yet, wait */ pdeq_putr(env->waitq, node); return; - } + } /* if */ irg = current_ir_graph; adr = get_Store_ptr(node); @@ -451,13 +434,12 @@ static void lower_Store(ir_node *node, ir_mode *mode, lower_env_t *env) { high = new_r_Add(irg, block, adr, new_r_Const(irg, block, get_tarval_mode(env->tv_mode_bytes), env->tv_mode_bytes), get_irn_mode(adr)); - } - else { + } else { low = new_r_Add(irg, block, adr, new_r_Const(irg, block, get_tarval_mode(env->tv_mode_bytes), env->tv_mode_bytes), get_irn_mode(adr)); high = adr; - } + } /* if */ /* create two Stores */ dbg = get_irn_dbg_info(node); @@ -487,12 +469,12 @@ static void lower_Store(ir_node *node, ir_mode *mode, lower_env_t *env) { break; default: assert(0 && "unexpected Proj number"); - } + } /* switch */ /* mark this proj: we have handled it already, otherwise we might fall into * out new nodes. */ mark_irn_visited(proj); - } -} + } /* for */ +} /* lower_Store */ /** * Return a node containing the address of the intrinsic emulation function. @@ -508,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; @@ -524,13 +506,12 @@ static ir_node *get_intrinsic_address(ir_type *method, ir_op *op, assert(ent && "Intrinsic creator must return an entity"); entry->ent = ent; - } - else + } else { ent = entry->ent; - + } /* if */ sym.entity_p = ent; return new_r_SymConst(current_ir_graph, block, sym, symconst_addr_ent); -} +} /* get_intrinsic_address */ /** * Translate a Div. @@ -544,6 +525,7 @@ static void lower_Div(ir_node *node, ir_mode *mode, lower_env_t *env) { dbg_info *dbg; ir_type *mtp; int idx; + ir_graph *irg; node_entry_t *entry; irn = get_Div_left(node); @@ -554,7 +536,7 @@ static void lower_Div(ir_node *node, ir_mode *mode, lower_env_t *env) { /* not ready yet, wait */ pdeq_putr(env->waitq, node); return; - } + } /* if */ in[0] = entry->low_word; in[1] = entry->high_word; @@ -567,21 +549,22 @@ static void lower_Div(ir_node *node, ir_mode *mode, lower_env_t *env) { /* not ready yet, wait */ pdeq_putr(env->waitq, node); return; - } + } /* if */ in[2] = entry->low_word; in[3] = entry->high_word; - dbg = get_irn_dbg_info(node); + dbg = get_irn_dbg_info(node); block = get_nodes_block(node); + irg = current_ir_graph; mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u; opmode = get_irn_op_mode(node); irn = get_intrinsic_address(mtp, get_irn_op(node), opmode, opmode, block, env); - call = new_rd_Call(dbg, current_ir_graph, block, get_Div_mem(node), + call = new_rd_Call(dbg, irg, block, get_Div_mem(node), irn, 4, in, mtp); set_irn_pinned(call, get_irn_pinned(node)); - irn = new_r_Proj(current_ir_graph, block, call, mode_T, pn_Call_T_result); + irn = new_r_Proj(irg, block, call, mode_T, pn_Call_T_result); for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) { switch (get_Proj_proj(proj)) { @@ -603,12 +586,12 @@ static void lower_Div(ir_node *node, ir_mode *mode, lower_env_t *env) { break; default: assert(0 && "unexpected Proj number"); - } + } /* switch */ /* mark this proj: we have handled it already, otherwise we might fall into * out new nodes. */ mark_irn_visited(proj); - } -} + } /* for */ +} /* lower_Div */ /** * Translate a Mod. @@ -622,6 +605,7 @@ static void lower_Mod(ir_node *node, ir_mode *mode, lower_env_t *env) { dbg_info *dbg; ir_type *mtp; int idx; + ir_graph *irg; node_entry_t *entry; irn = get_Mod_left(node); @@ -632,7 +616,7 @@ static void lower_Mod(ir_node *node, ir_mode *mode, lower_env_t *env) { /* not ready yet, wait */ pdeq_putr(env->waitq, node); return; - } + } /* if */ in[0] = entry->low_word; in[1] = entry->high_word; @@ -645,21 +629,22 @@ static void lower_Mod(ir_node *node, ir_mode *mode, lower_env_t *env) { /* not ready yet, wait */ pdeq_putr(env->waitq, node); return; - } + } /* if */ in[2] = entry->low_word; in[3] = entry->high_word; - dbg = get_irn_dbg_info(node); + dbg = get_irn_dbg_info(node); block = get_nodes_block(node); + irg = current_ir_graph; mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u; opmode = get_irn_op_mode(node); irn = get_intrinsic_address(mtp, get_irn_op(node), opmode, opmode, block, env); - call = new_rd_Call(dbg, current_ir_graph, block, get_Mod_mem(node), + call = new_rd_Call(dbg, irg, block, get_Mod_mem(node), irn, 4, in, mtp); set_irn_pinned(call, get_irn_pinned(node)); - irn = new_r_Proj(current_ir_graph, block, call, mode_T, pn_Call_T_result); + irn = new_r_Proj(irg, block, call, mode_T, pn_Call_T_result); for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) { switch (get_Proj_proj(proj)) { @@ -676,17 +661,17 @@ static void lower_Mod(ir_node *node, ir_mode *mode, lower_env_t *env) { case pn_Mod_res: /* Result of computation. */ idx = get_irn_idx(proj); assert(idx < env->n_entries); - env->entries[idx]->low_word = new_r_Proj(current_ir_graph, block, irn, mode, 0); - env->entries[idx]->high_word = new_r_Proj(current_ir_graph, block, irn, mode, 1); + env->entries[idx]->low_word = new_r_Proj(irg, block, irn, mode, 0); + env->entries[idx]->high_word = new_r_Proj(irg, block, irn, mode, 1); break; default: assert(0 && "unexpected Proj number"); - } + } /* switch */ /* mark this proj: we have handled it already, otherwise we might fall into * out new nodes. */ mark_irn_visited(proj); - } -} + } /* for */ +} /* lower_Mod */ /** * Translate a DivMod. @@ -694,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; @@ -702,6 +689,7 @@ static void lower_DivMod(ir_node *node, ir_mode *mode, lower_env_t *env) { int idx; node_entry_t *entry; unsigned flags = 0; + ir_graph *irg; /* check if both results are needed */ for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) { @@ -709,8 +697,8 @@ static void lower_DivMod(ir_node *node, ir_mode *mode, lower_env_t *env) { case pn_DivMod_res_div: flags |= 1; break; case pn_DivMod_res_mod: flags |= 2; break; default: break; - } - } + } /* switch */ + } /* for */ irn = get_DivMod_left(node); entry = env->entries[get_irn_idx(irn)]; @@ -720,7 +708,7 @@ static void lower_DivMod(ir_node *node, ir_mode *mode, lower_env_t *env) { /* not ready yet, wait */ pdeq_putr(env->waitq, node); return; - } + } /* if */ in[0] = entry->low_word; in[1] = entry->high_word; @@ -733,13 +721,14 @@ static void lower_DivMod(ir_node *node, ir_mode *mode, lower_env_t *env) { /* not ready yet, wait */ pdeq_putr(env->waitq, node); return; - } + } /* if */ in[2] = entry->low_word; in[3] = entry->high_word; - dbg = get_irn_dbg_info(node); + dbg = get_irn_dbg_info(node); block = get_nodes_block(node); + irg = current_ir_graph; mem = get_DivMod_mem(node); @@ -748,21 +737,21 @@ static void lower_DivMod(ir_node *node, ir_mode *mode, lower_env_t *env) { if (flags & 1) { opmode = get_irn_op_mode(node); irn = get_intrinsic_address(mtp, op_Div, opmode, opmode, block, env); - callDiv = new_rd_Call(dbg, current_ir_graph, block, mem, + callDiv = new_rd_Call(dbg, irg, block, mem, irn, 4, in, mtp); set_irn_pinned(callDiv, get_irn_pinned(node)); - resDiv = new_r_Proj(current_ir_graph, block, callDiv, mode_T, pn_Call_T_result); - } + resDiv = new_r_Proj(irg, block, callDiv, mode_T, pn_Call_T_result); + } /* if */ if (flags & 2) { if (flags & 1) - mem = new_r_Proj(current_ir_graph, block, callDiv, mode_M, pn_Call_M); + mem = new_r_Proj(irg, block, callDiv, mode_M, pn_Call_M); opmode = get_irn_op_mode(node); irn = get_intrinsic_address(mtp, op_Mod, opmode, opmode, block, env); - callMod = new_rd_Call(dbg, current_ir_graph, block, mem, + callMod = new_rd_Call(dbg, irg, block, mem, irn, 4, in, mtp); set_irn_pinned(callMod, get_irn_pinned(node)); - resMod = new_r_Proj(current_ir_graph, block, callMod, mode_T, pn_Call_T_result); - } + resMod = new_r_Proj(irg, block, callMod, mode_T, pn_Call_T_result); + } /* if */ for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) { switch (get_Proj_proj(proj)) { @@ -779,22 +768,22 @@ static void lower_DivMod(ir_node *node, ir_mode *mode, lower_env_t *env) { case pn_DivMod_res_div: /* Result of Div. */ idx = get_irn_idx(proj); assert(idx < env->n_entries); - env->entries[idx]->low_word = new_r_Proj(current_ir_graph, block, resDiv, mode, 0); - env->entries[idx]->high_word = new_r_Proj(current_ir_graph, block, resDiv, mode, 1); + env->entries[idx]->low_word = new_r_Proj(irg, block, resDiv, mode, 0); + env->entries[idx]->high_word = new_r_Proj(irg, block, resDiv, mode, 1); break; case pn_DivMod_res_mod: /* Result of Mod. */ idx = get_irn_idx(proj); - env->entries[idx]->low_word = new_r_Proj(current_ir_graph, block, resMod, mode, 0); - env->entries[idx]->high_word = new_r_Proj(current_ir_graph, block, resMod, mode, 1); + env->entries[idx]->low_word = new_r_Proj(irg, block, resMod, mode, 0); + env->entries[idx]->high_word = new_r_Proj(irg, block, resMod, mode, 1); break; default: assert(0 && "unexpected Proj number"); - } + } /* switch */ /* mark this proj: we have handled it already, otherwise we might fall into * out new nodes. */ mark_irn_visited(proj); - } -} + } /* for */ +} /* lower_DivMod */ /** * Translate a Binop. @@ -807,6 +796,7 @@ static void lower_Binop(ir_node *node, ir_mode *mode, lower_env_t *env) { dbg_info *dbg; ir_type *mtp; int idx; + ir_graph *irg; node_entry_t *entry; irn = get_binop_left(node); @@ -817,7 +807,7 @@ static void lower_Binop(ir_node *node, ir_mode *mode, lower_env_t *env) { /* not ready yet, wait */ pdeq_putr(env->waitq, node); return; - } + } /* if */ in[0] = entry->low_word; in[1] = entry->high_word; @@ -830,26 +820,27 @@ static void lower_Binop(ir_node *node, ir_mode *mode, lower_env_t *env) { /* not ready yet, wait */ pdeq_putr(env->waitq, node); return; - } + } /* if */ in[2] = entry->low_word; in[3] = entry->high_word; - dbg = get_irn_dbg_info(node); + dbg = get_irn_dbg_info(node); block = get_nodes_block(node); + irg = current_ir_graph; mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u; irn = get_intrinsic_address(mtp, get_irn_op(node), mode, mode, block, env); - irn = new_rd_Call(dbg, current_ir_graph, block, get_irg_no_mem(current_ir_graph), + irn = new_rd_Call(dbg, irg, block, get_irg_no_mem(current_ir_graph), irn, 4, in, mtp); set_irn_pinned(irn, get_irn_pinned(node)); - irn = new_r_Proj(current_ir_graph, block, irn, mode_T, pn_Call_T_result); + irn = new_r_Proj(irg, block, irn, mode_T, pn_Call_T_result); idx = get_irn_idx(node); assert(idx < env->n_entries); - env->entries[idx]->low_word = new_r_Proj(current_ir_graph, block, irn, mode, 0); - env->entries[idx]->high_word = new_r_Proj(current_ir_graph, block, irn, mode, 1); -} + env->entries[idx]->low_word = new_r_Proj(irg, block, irn, mode, 0); + env->entries[idx]->high_word = new_r_Proj(irg, block, irn, mode, 1); +} /* lower_Binop */ /** * Translate a Shiftop. @@ -862,6 +853,7 @@ static void lower_Shiftop(ir_node *node, ir_mode *mode, lower_env_t *env) { dbg_info *dbg; ir_type *mtp; int idx; + ir_graph *irg; node_entry_t *entry; irn = get_binop_left(node); @@ -872,7 +864,7 @@ static void lower_Shiftop(ir_node *node, ir_mode *mode, lower_env_t *env) { /* not ready yet, wait */ pdeq_putr(env->waitq, node); return; - } + } /* if */ in[0] = entry->low_word; in[1] = entry->high_word; @@ -882,115 +874,138 @@ static void lower_Shiftop(ir_node *node, ir_mode *mode, lower_env_t *env) { dbg = get_irn_dbg_info(node); block = get_nodes_block(node); + irg = current_ir_graph; mtp = mode_is_signed(mode) ? shiftop_tp_s : shiftop_tp_u; irn = get_intrinsic_address(mtp, get_irn_op(node), mode, mode, block, env); - irn = new_rd_Call(dbg, current_ir_graph, block, get_irg_no_mem(current_ir_graph), + irn = new_rd_Call(dbg, irg, block, get_irg_no_mem(current_ir_graph), irn, 3, in, mtp); set_irn_pinned(irn, get_irn_pinned(node)); - irn = new_r_Proj(current_ir_graph, block, irn, mode_T, pn_Call_T_result); + irn = new_r_Proj(irg, block, irn, mode_T, pn_Call_T_result); idx = get_irn_idx(node); assert(idx < env->n_entries); - env->entries[idx]->low_word = new_r_Proj(current_ir_graph, block, irn, mode, 0); - env->entries[idx]->high_word = new_r_Proj(current_ir_graph, block, irn, mode, 1); -} + env->entries[idx]->low_word = new_r_Proj(irg, block, irn, mode, 0); + env->entries[idx]->high_word = new_r_Proj(irg, block, irn, mode, 1); +} /* lower_Shiftop */ /** * Translate a Shr and handle special cases. */ static void lower_Shr(ir_node *node, ir_mode *mode, lower_env_t *env) { - ir_node *right = get_Shr_right(node); + ir_node *right = get_Shr_right(node); + ir_graph *irg = current_ir_graph; if (get_mode_arithmetic(mode) == irma_twos_complement && is_Const(right)) { tarval *tv = get_Const_tarval(right); if (tarval_is_long(tv) && - get_tarval_long(tv) == get_mode_size_bits(env->params->low_signed)) { + get_tarval_long(tv) >= get_mode_size_bits(mode)) { ir_node *block = get_nodes_block(node); ir_node *left = get_Shr_left(node); + ir_node *c; + long shf_cnt = get_tarval_long(tv) - get_mode_size_bits(mode); int idx = get_irn_idx(left); left = env->entries[idx]->high_word; idx = get_irn_idx(node); - env->entries[idx]->low_word = left; - env->entries[idx]->high_word = new_r_Const(current_ir_graph, block, mode, get_mode_null(mode)); + if (shf_cnt > 0) { + c = new_r_Const_long(irg, block, mode_Iu, shf_cnt); + env->entries[idx]->low_word = new_r_Shr(irg, block, left, c, mode); + } else { + env->entries[idx]->low_word = left; + } /* if */ + env->entries[idx]->high_word = new_r_Const(irg, block, mode, get_mode_null(mode)); return; - } - } + } /* if */ + } /* if */ lower_Shiftop(node, mode, env); -} +} /* lower_Shr */ /** * Translate a Shl and handle special cases. */ static void lower_Shl(ir_node *node, ir_mode *mode, lower_env_t *env) { - ir_node *right = get_Shl_right(node); + ir_node *right = get_Shl_right(node); + ir_graph *irg = current_ir_graph; if (get_mode_arithmetic(mode) == irma_twos_complement && is_Const(right)) { tarval *tv = get_Const_tarval(right); if (tarval_is_long(tv) && - get_tarval_long(tv) == get_mode_size_bits(env->params->low_signed)) { + get_tarval_long(tv) >= get_mode_size_bits(mode)) { ir_node *block = get_nodes_block(node); ir_node *left = get_Shl_left(node); + ir_node *c; + long shf_cnt = get_tarval_long(tv) - get_mode_size_bits(mode); int idx = get_irn_idx(left); left = env->entries[idx]->low_word; idx = get_irn_idx(node); - env->entries[idx]->low_word = new_r_Const(current_ir_graph, block, mode, get_mode_null(mode)); - env->entries[idx]->high_word = left; + if (shf_cnt > 0) { + c = new_r_Const_long(irg, block, mode_Iu, shf_cnt); + env->entries[idx]->high_word = new_r_Shl(irg, block, left, c, mode); + } else { + env->entries[idx]->high_word = left; + } /* if */ + env->entries[idx]->low_word = new_r_Const(irg, block, mode, get_mode_null(mode)); return; - } - } + } /* if */ + } /* if */ lower_Shiftop(node, mode, env); -} +} /* lower_Shl */ /** * Translate a Shrs and handle special cases. */ static void lower_Shrs(ir_node *node, ir_mode *mode, lower_env_t *env) { - ir_node *right = get_Shrs_right(node); + ir_node *right = get_Shrs_right(node); + ir_graph *irg = current_ir_graph; if (get_mode_arithmetic(mode) == irma_twos_complement && is_Const(right)) { tarval *tv = get_Const_tarval(right); if (tarval_is_long(tv) && - get_tarval_long(tv) == get_mode_size_bits(env->params->low_signed)) { + get_tarval_long(tv) >= get_mode_size_bits(mode)) { ir_node *block = get_nodes_block(node); ir_node *left = get_Shrs_left(node); + long shf_cnt = get_tarval_long(tv) - get_mode_size_bits(mode); ir_node *c; int idx = get_irn_idx(left); left = env->entries[idx]->high_word; idx = get_irn_idx(node); - c = new_r_Const_long(current_ir_graph, block, mode_Iu, get_mode_size_bits(mode) - 1); - env->entries[idx]->low_word = left; - env->entries[idx]->high_word = new_r_Shrs(current_ir_graph, block, left, c, mode); + if (shf_cnt > 0) { + c = new_r_Const_long(irg, block, mode_Iu, shf_cnt); + env->entries[idx]->low_word = new_r_Shrs(irg, block, left, c, mode); + } else { + env->entries[idx]->low_word = left; + } /* if */ + c = new_r_Const_long(irg, block, mode_Iu, get_mode_size_bits(mode) - 1); + env->entries[idx]->high_word = new_r_Shrs(irg, block, left, c, mode); return; - } - } + } /* if */ + } /* if */ lower_Shiftop(node, mode, env); -} +} /* lower_Shrs */ /** * Translate a Rot and handle special cases. */ static void lower_Rot(ir_node *node, ir_mode *mode, lower_env_t *env) { - ir_node *right = get_Rot_right(node); + ir_node *right = get_Rot_right(node); if (get_mode_arithmetic(mode) == irma_twos_complement && is_Const(right)) { tarval *tv = get_Const_tarval(right); if (tarval_is_long(tv) && - get_tarval_long(tv) == get_mode_size_bits(env->params->low_signed)) { - ir_node *block = get_nodes_block(node); + get_tarval_long(tv) == get_mode_size_bits(mode)) { ir_node *left = get_Rot_left(node); ir_node *h, *l; int idx = get_irn_idx(left); @@ -1003,10 +1018,11 @@ static void lower_Rot(ir_node *node, ir_mode *mode, lower_env_t *env) { env->entries[idx]->high_word = l; return; - } - } + } /* if */ + } /* if */ lower_Shiftop(node, mode, env); -} +} /* lower_Rot */ + /** * Translate an Unop. * @@ -1018,6 +1034,7 @@ static void lower_Unop(ir_node *node, ir_mode *mode, lower_env_t *env) { dbg_info *dbg; ir_type *mtp; int idx; + ir_graph *irg; node_entry_t *entry; irn = get_unop_op(node); @@ -1028,26 +1045,27 @@ static void lower_Unop(ir_node *node, ir_mode *mode, lower_env_t *env) { /* not ready yet, wait */ pdeq_putr(env->waitq, node); return; - } + } /* if */ in[0] = entry->low_word; in[1] = entry->high_word; - dbg = get_irn_dbg_info(node); + dbg = get_irn_dbg_info(node); block = get_nodes_block(node); + irg = current_ir_graph; mtp = mode_is_signed(mode) ? unop_tp_s : unop_tp_u; irn = get_intrinsic_address(mtp, get_irn_op(node), mode, mode, block, env); - irn = new_rd_Call(dbg, current_ir_graph, block, get_irg_no_mem(current_ir_graph), + irn = new_rd_Call(dbg, irg, block, get_irg_no_mem(current_ir_graph), irn, 2, in, mtp); set_irn_pinned(irn, get_irn_pinned(node)); - irn = new_r_Proj(current_ir_graph, block, irn, mode_T, pn_Call_T_result); + irn = new_r_Proj(irg, block, irn, mode_T, pn_Call_T_result); idx = get_irn_idx(node); assert(idx < env->n_entries); - env->entries[idx]->low_word = new_r_Proj(current_ir_graph, block, irn, mode, 0); - env->entries[idx]->high_word = new_r_Proj(current_ir_graph, block, irn, mode, 1); -} + env->entries[idx]->low_word = new_r_Proj(irg, block, irn, mode, 0); + env->entries[idx]->high_word = new_r_Proj(irg, block, irn, mode, 1); +} /* lower_Unop */ /** * Translate a logical Binop. @@ -1060,6 +1078,7 @@ static void lower_Binop_logical(ir_node *node, ir_mode *mode, lower_env_t *env, ir_node *lop_l, *lop_h, *rop_l, *rop_h; dbg_info *dbg; int idx; + ir_graph *irg; node_entry_t *entry; irn = get_binop_left(node); @@ -1070,7 +1089,7 @@ static void lower_Binop_logical(ir_node *node, ir_mode *mode, lower_env_t *env, /* not ready yet, wait */ pdeq_putr(env->waitq, node); return; - } + } /* if */ lop_l = entry->low_word; lop_h = entry->high_word; @@ -1083,7 +1102,7 @@ static void lower_Binop_logical(ir_node *node, ir_mode *mode, lower_env_t *env, /* not ready yet, wait */ pdeq_putr(env->waitq, node); return; - } + } /* if */ rop_l = entry->low_word; rop_h = entry->high_word; @@ -1093,9 +1112,10 @@ static void lower_Binop_logical(ir_node *node, ir_mode *mode, lower_env_t *env, idx = get_irn_idx(node); assert(idx < env->n_entries); - env->entries[idx]->low_word = constr_rd(dbg, current_ir_graph, block, lop_l, rop_l, mode); - env->entries[idx]->high_word = constr_rd(dbg, current_ir_graph, block, lop_h, rop_h, mode); -} + irg = current_ir_graph; + env->entries[idx]->low_word = constr_rd(dbg, irg, block, lop_l, rop_l, mode); + env->entries[idx]->high_word = constr_rd(dbg, irg, block, lop_h, rop_h, mode); +} /* lower_Binop_logical */ /** create a logical operation tranformation */ #define lower_logical(op) \ @@ -1117,6 +1137,7 @@ static void lower_Not(ir_node *node, ir_mode *mode, lower_env_t *env) { ir_node *op_l, *op_h; dbg_info *dbg; int idx; + ir_graph *irg; node_entry_t *entry; irn = get_Not_op(node); @@ -1127,19 +1148,56 @@ static void lower_Not(ir_node *node, ir_mode *mode, lower_env_t *env) { /* 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); + 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_Not(dbg, current_ir_graph, block, op_l, mode); 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. @@ -1165,9 +1223,10 @@ static void lower_Cond(ir_node *node, ir_mode *mode, lower_env_t *env) { idx = get_irn_idx(left); lentry = env->entries[idx]; - if (! lentry) + if (! lentry) { /* a normal Cmp */ return; + } /* if */ right = get_Cmp_right(cmp); idx = get_irn_idx(right); @@ -1178,7 +1237,7 @@ static void lower_Cond(ir_node *node, ir_mode *mode, lower_env_t *env) { /* not yet ready */ pdeq_putr(env->waitq, node); return; - } + } /* if */ /* all right, build the code */ for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) { @@ -1187,14 +1246,13 @@ static void lower_Cond(ir_node *node, ir_mode *mode, lower_env_t *env) { if (proj_nr == pn_Cond_true) { assert(projT == NULL && "more than one Proj(true)"); projT = proj; - } - else { + } else { assert(proj_nr == pn_Cond_false); assert(projF == NULL && "more than one Proj(false)"); projF = proj; - } + } /* if */ mark_irn_visited(proj); - } + } /* for */ assert(projT && projF); /* create a new high compare */ @@ -1238,8 +1296,7 @@ static void lower_Cond(ir_node *node, ir_mode *mode, lower_env_t *env) { proj = new_r_Proj(irg, new_bl, irn, mode_X, pn_Cond_true); mark_irn_visited(proj); exchange(projT, proj); - } - else if (pnc == pn_Cmp_Lg) { + } else if (pnc == pn_Cmp_Lg) { /* simple case:a != b <==> a_h != b_h || a_l != b_l */ pmap_entry *entry = pmap_find(env->proj_2_block, projT); @@ -1272,9 +1329,8 @@ static void lower_Cond(ir_node *node, ir_mode *mode, lower_env_t *env) { proj = new_r_Proj(irg, new_bl, irn, mode_X, pn_Cond_false); 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) */ + } else { + /* 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; @@ -1286,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); @@ -1326,12 +1382,11 @@ static void lower_Cond(ir_node *node, ir_mode *mode, lower_env_t *env) { proj = new_r_Proj(irg, newbl_l, irn, mode_X, pn_Cond_false); mark_irn_visited(proj); add_block_cf_input(dstF, projF, proj); - } + } /* if */ /* we have changed the control flow */ env->flags |= CF_CHANGED; - } - else { + } else { idx = get_irn_idx(sel); if (env->entries[idx]) { @@ -1346,11 +1401,11 @@ static void lower_Cond(ir_node *node, ir_mode *mode, lower_env_t *env) { /* not ready yet, wait */ pdeq_putr(env->waitq, node); return; - } + } /* if */ set_Cond_selector(node, env->entries[idx]->low_word); - } - } -} + } /* if */ + } /* if */ +} /* lower_Cond */ /** * Translate a Conv to higher_signed @@ -1367,15 +1422,27 @@ static void lower_Conv_to_Ls(ir_node *node, lower_env_t *env) { assert(idx < env->n_entries); if (mode_is_int(imode) || mode_is_reference(imode)) { - /* simple case: create a high word */ - if (imode != dst_mode) - op = new_rd_Conv(dbg, irg, block, op, dst_mode); + if (imode == env->params->high_unsigned) { + /* a Conv from Lu to Ls */ + int op_idx = get_irn_idx(op); - env->entries[idx]->low_word = op; - env->entries[idx]->high_word = new_rd_Shrs(dbg, irg, block, op, - new_Const_long(mode_Iu, get_mode_size_bits(dst_mode) - 1), dst_mode); - } - else { + if (! env->entries[op_idx]->low_word) { + /* not ready yet, wait */ + pdeq_putr(env->waitq, node); + return; + } /* if */ + env->entries[idx]->low_word = new_rd_Conv(dbg, irg, block, env->entries[op_idx]->low_word, dst_mode); + env->entries[idx]->high_word = new_rd_Conv(dbg, irg, block, env->entries[op_idx]->high_word, dst_mode); + } else { + /* simple case: create a high word */ + if (imode != dst_mode) + op = new_rd_Conv(dbg, irg, block, op, dst_mode); + + env->entries[idx]->low_word = op; + env->entries[idx]->high_word = new_rd_Shrs(dbg, irg, block, op, + new_Const_long(mode_Iu, get_mode_size_bits(dst_mode) - 1), dst_mode); + } /* if */ + } else { ir_node *irn, *call; ir_mode *omode = env->params->high_signed; ir_type *mtp = get_conv_type(imode, omode, env); @@ -1387,15 +1454,15 @@ static void lower_Conv_to_Ls(ir_node *node, lower_env_t *env) { env->entries[idx]->low_word = new_r_Proj(irg, block, irn, dst_mode, 0); env->entries[idx]->high_word = new_r_Proj(irg, block, irn, dst_mode, 1); - } -} + } /* if */ +} /* lower_Conv_to_Ls */ /** * Translate a Conv to higher_unsigned */ static void lower_Conv_to_Lu(ir_node *node, lower_env_t *env) { ir_node *op = get_Conv_op(node); - ir_mode *imode = get_irn_mode(op); + ir_mode *imode = get_irn_mode(op); ir_mode *dst_mode = env->params->low_unsigned; int idx = get_irn_idx(node); ir_graph *irg = current_ir_graph; @@ -1405,18 +1472,31 @@ static void lower_Conv_to_Lu(ir_node *node, lower_env_t *env) { assert(idx < env->n_entries); if (mode_is_int(imode) || mode_is_reference(imode)) { - /* simple case: create a high word */ - if (imode != dst_mode) - op = new_rd_Conv(dbg, irg, block, op, dst_mode); + if (imode == env->params->high_signed) { + /* a Conv from Ls to Lu */ + int op_idx = get_irn_idx(op); - env->entries[idx]->low_word = op; - env->entries[idx]->high_word = new_Const(dst_mode, get_mode_null(dst_mode)); - } - else { + if (! env->entries[op_idx]->low_word) { + /* not ready yet, wait */ + pdeq_putr(env->waitq, node); + return; + } /* if */ + env->entries[idx]->low_word = new_rd_Conv(dbg, irg, block, env->entries[op_idx]->low_word, dst_mode); + env->entries[idx]->high_word = new_rd_Conv(dbg, irg, block, env->entries[op_idx]->high_word, dst_mode); + } else { + /* simple case: create a high word */ + if (imode != dst_mode) + op = new_rd_Conv(dbg, irg, block, op, dst_mode); + + env->entries[idx]->low_word = op; + env->entries[idx]->high_word = new_Const(dst_mode, get_mode_null(dst_mode)); + } /* if */ + } else { ir_node *irn, *call; ir_mode *omode = env->params->high_unsigned; ir_type *mtp = get_conv_type(imode, omode, env); + /* do an intrinsic call */ irn = get_intrinsic_address(mtp, get_irn_op(node), imode, omode, block, env); call = new_rd_Call(dbg, irg, block, get_irg_no_mem(irg), irn, 1, &op, mtp); set_irn_pinned(call, get_irn_pinned(node)); @@ -1424,8 +1504,8 @@ static void lower_Conv_to_Lu(ir_node *node, lower_env_t *env) { env->entries[idx]->low_word = new_r_Proj(irg, block, irn, dst_mode, 0); env->entries[idx]->high_word = new_r_Proj(irg, block, irn, dst_mode, 1); - } -} + } /* if */ +} /* lower_Conv_to_Lu */ /** * Translate a Conv from higher_signed @@ -1448,8 +1528,7 @@ static void lower_Conv_from_Ls(ir_node *node, lower_env_t *env) { op = new_rd_Conv(dbg, irg, block, op, omode); set_Conv_op(node, op); - } - else { + } else { ir_node *irn, *call, *in[2]; ir_mode *imode = env->params->high_signed; ir_type *mtp = get_conv_type(imode, omode, env); @@ -1463,8 +1542,8 @@ static void lower_Conv_from_Ls(ir_node *node, lower_env_t *env) { irn = new_r_Proj(irg, block, call, mode_T, pn_Call_T_result); exchange(node, new_r_Proj(irg, block, irn, omode, 0)); - } -} + } /* if */ +} /* lower_Conv_from_Ls */ /** * Translate a Conv from higher_unsigned @@ -1487,8 +1566,7 @@ static void lower_Conv_from_Lu(ir_node *node, lower_env_t *env) { op = new_rd_Conv(dbg, irg, block, op, omode); set_Conv_op(node, op); - } - else { + } else { ir_node *irn, *call, *in[2]; ir_mode *imode = env->params->high_unsigned; ir_type *mtp = get_conv_type(imode, omode, env); @@ -1502,8 +1580,8 @@ static void lower_Conv_from_Lu(ir_node *node, lower_env_t *env) { irn = new_r_Proj(irg, block, call, mode_T, pn_Call_T_result); exchange(node, new_r_Proj(irg, block, irn, omode, 0)); - } -} + } /* if */ +} /* lower_Conv_from_Lu */ /** * Translate a Conv. @@ -1511,21 +1589,20 @@ static void lower_Conv_from_Lu(ir_node *node, lower_env_t *env) { static void lower_Conv(ir_node *node, ir_mode *mode, lower_env_t *env) { mode = get_irn_mode(node); - if (mode == env->params->high_signed) + if (mode == env->params->high_signed) { lower_Conv_to_Ls(node, env); - else if (mode == env->params->high_unsigned) + } else if (mode == env->params->high_unsigned) { lower_Conv_to_Lu(node, env); - else { + } else { ir_mode *mode = get_irn_mode(get_Conv_op(node)); - if (mode == env->params->high_signed) + if (mode == env->params->high_signed) { lower_Conv_from_Ls(node, env); - else { - assert(mode == env->params->high_unsigned); + } else if (mode == env->params->high_unsigned) { lower_Conv_from_Lu(node, env); - } - } -} + } /* if */ + } /* if */ +} /* lower_Conv */ /** * Lower the method type. @@ -1553,8 +1630,8 @@ static ir_type *lower_mtp(ir_type *mtp, lower_env_t *env) { if (mode == env->params->high_signed || mode == env->params->high_unsigned) ++n_param; - } - } + } /* if */ + } /* for */ /* count new number of results */ n_res = r = get_method_n_ress(mtp); @@ -1567,8 +1644,8 @@ static ir_type *lower_mtp(ir_type *mtp, lower_env_t *env) { if (mode == env->params->high_signed || mode == env->params->high_unsigned) ++n_res; - } - } + } /* if */ + } /* for */ id = mangle_u(new_id_from_chars("L", 1), get_type_ident(mtp)); res = new_type_method(id, n_param, n_res); @@ -1583,17 +1660,16 @@ static ir_type *lower_mtp(ir_type *mtp, lower_env_t *env) { if (mode == env->params->high_signed) { set_method_param_type(res, n_param++, tp_s); set_method_param_type(res, n_param++, tp_s); - } - else if (mode == env->params->high_unsigned) { + } else if (mode == env->params->high_unsigned) { set_method_param_type(res, n_param++, tp_u); set_method_param_type(res, n_param++, tp_u); - } - else + } else { set_method_param_type(res, n_param++, tp); - } - else + } /* if */ + } else { set_method_param_type(res, n_param++, tp); - } + } /* if */ + } /* for */ for (i = n_res = 0; i < r; ++i) { ir_type *tp = get_method_res_type(mtp, i); @@ -1603,35 +1679,34 @@ static ir_type *lower_mtp(ir_type *mtp, lower_env_t *env) { if (mode == env->params->high_signed) { set_method_res_type(res, n_res++, tp_s); set_method_res_type(res, n_res++, tp_s); - } - else if (mode == env->params->high_unsigned) { + } else if (mode == env->params->high_unsigned) { set_method_res_type(res, n_res++, tp_u); set_method_res_type(res, n_res++, tp_u); - } - else + } else { set_method_res_type(res, n_res++, tp); - } - else + } /* if */ + } else { set_method_res_type(res, n_res++, tp); - } + } /* if */ + } /* for */ set_lowered_type(mtp, res); pmap_insert(lowered_type, mtp, res); - } - else + } else { res = entry->value; + } /* if */ return res; -} +} /* lower_mtp */ /** * 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) { @@ -1645,10 +1720,10 @@ static void lower_Return(ir_node *node, ir_mode *mode, lower_env_t *env) { /* not ready yet, wait */ pdeq_putr(env->waitq, node); return; - } + } /* if */ need_conv = 1; - } - } + } /* if */ + } /* for */ if (! need_conv) return; @@ -1671,31 +1746,31 @@ static void lower_Return(ir_node *node, ir_mode *mode, lower_env_t *env) { if (env->entries[idx]) { in[++j] = env->entries[idx]->low_word; in[++j] = env->entries[idx]->high_word; - } - else + } else { in[++j] = pred; - } + } /* if */ + } /* for */ set_irn_in(node, j+1, in); -} +} /* lower_Return */ /** * 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; - - if (is_lowered_type(tp)) + 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); - else + } else { mtp = tp; - + } /* if */ assert(! is_lowered_type(mtp)); n_params = get_method_n_params(mtp); @@ -1715,8 +1790,8 @@ static void lower_Start(ir_node *node, ir_mode *mode, lower_env_t *env) { if (mode == env->params->high_signed || mode == env->params->high_unsigned) ++j; - } - } + } /* if */ + } /* for */ if (i == j) return; @@ -1750,20 +1825,21 @@ static void lower_Start(ir_node *node, ir_mode *mode, lower_env_t *env) { if (env->entries[idx]) { mode = get_irn_mode(proj); - if (mode == env->params->high_signed) + if (mode == env->params->high_signed) { mode = env->params->low_signed; - else + } else { mode = env->params->low_unsigned; + } /* if */ dbg = get_irn_dbg_info(proj); env->entries[idx]->low_word = new_rd_Proj(dbg, irg, get_nodes_block(proj), args, mode, new_projs[proj_nr]); env->entries[idx]->high_word = new_rd_Proj(dbg, irg, get_nodes_block(proj), args, mode, new_projs[proj_nr] + 1); - } - } + } /* if */ + } /* for */ set_optimize(rem); -} +} /* lower_Start */ /** * Translate a Call. @@ -1777,10 +1853,11 @@ static void lower_Call(ir_node *node, ir_mode *mode, lower_env_t *env) { int i, j; long *res_numbers = NULL; - if (is_lowered_type(tp)) + if (is_lowered_type(tp)) { call_tp = get_associated_type(tp); - else + } else { call_tp = tp; + } /* if */ assert(! is_lowered_type(call_tp)); @@ -1795,9 +1872,9 @@ static void lower_Call(ir_node *node, ir_mode *mode, lower_env_t *env) { mode == env->params->high_unsigned) { need_lower = 1; break; - } - } - } + } /* if */ + } /* if */ + } /* for */ n_res = get_method_n_ress(call_tp); if (n_res > 0) { NEW_ARR_A(long, res_numbers, n_res); @@ -1813,10 +1890,10 @@ static void lower_Call(ir_node *node, ir_mode *mode, lower_env_t *env) { mode == env->params->high_unsigned) { need_lower = 1; ++j; - } - } - } - } + } /* if */ + } /* if */ + } /* for */ + } /* if */ if (! need_lower) return; @@ -1842,10 +1919,10 @@ static void lower_Call(ir_node *node, ir_mode *mode, lower_env_t *env) { } in[j++] = env->entries[idx]->low_word; in[j++] = env->entries[idx]->high_word; - } - else + } else { in[j++] = pred; - } + } /* if */ + } /* for */ set_irn_in(node, j, in); @@ -1858,8 +1935,8 @@ static void lower_Call(ir_node *node, ir_mode *mode, lower_env_t *env) { /* found the result proj */ results = proj; break; - } - } + } /* if */ + } /* for */ if (results) { /* there are results */ int rem = get_optimize(); @@ -1879,33 +1956,35 @@ static void lower_Call(ir_node *node, ir_mode *mode, lower_env_t *env) { ir_mode *mode = get_irn_mode(proj); dbg_info *dbg; - if (mode == env->params->high_signed) + if (mode == env->params->high_signed) { mode = env->params->low_signed; - else + } else { mode = env->params->low_unsigned; + } /* if */ dbg = get_irn_dbg_info(proj); env->entries[idx]->low_word = new_rd_Proj(dbg, irg, get_nodes_block(proj), results, mode, res_numbers[proj_nr]); env->entries[idx]->high_word = new_rd_Proj(dbg, irg, get_nodes_block(proj), results, mode, res_numbers[proj_nr] + 1); - } + } /* if */ mark_irn_visited(proj); - } - } + } /* if */ + } /* for */ set_optimize(rem); } -} +} /* lower_Call */ /** * Translate an Unknown into two. */ static void lower_Unknown(ir_node *node, ir_mode *mode, lower_env_t *env) { int idx = get_irn_idx(node); + ir_graph *irg = current_ir_graph; env->entries[idx]->low_word = - env->entries[idx]->high_word = new_r_Unknown(current_ir_graph, mode); -} + env->entries[idx]->high_word = new_r_Unknown(irg, mode); +} /* lower_Unknown */ /** * Translate a Phi. @@ -1913,6 +1992,7 @@ static void lower_Unknown(ir_node *node, ir_mode *mode, lower_env_t *env) { * First step: just create two templates */ static void lower_Phi(ir_node *phi, ir_mode *mode, lower_env_t *env) { + ir_graph *irg = current_ir_graph; ir_node *block, *unk; ir_node **inl, **inh; dbg_info *dbg; @@ -1931,20 +2011,19 @@ static void lower_Phi(ir_node *phi, ir_mode *mode, lower_env_t *env) { if (env->entries[idx]->low_word) { set_Phi_pred(phil, i, env->entries[idx]->low_word); - set_Phi_pred(phil, i, env->entries[idx]->high_word); - } - else { + set_Phi_pred(phih, i, env->entries[idx]->high_word); + } else { /* still not ready */ pdeq_putr(env->waitq, phi); return; - } - } - } + } /* if */ + } /* for */ + } /* if */ /* first create a new in array */ NEW_ARR_A(ir_node *, inl, arity); NEW_ARR_A(ir_node *, inh, arity); - unk = new_r_Unknown(current_ir_graph, mode); + unk = new_r_Unknown(irg, mode); for (i = 0; i < arity; ++i) { ir_node *pred = get_Phi_pred(phi, i); @@ -1953,62 +2032,210 @@ static void lower_Phi(ir_node *phi, ir_mode *mode, lower_env_t *env) { if (env->entries[idx]->low_word) { inl[i] = env->entries[idx]->low_word; inh[i] = env->entries[idx]->high_word; - } - else { + } else { inl[i] = unk; inh[i] = unk; enq = 1; - } - } + } /* if */ + } /* for */ - dbg = get_irn_dbg_info(phi); + dbg = get_irn_dbg_info(phi); block = get_nodes_block(phi); idx = get_irn_idx(phi); assert(idx < env->n_entries); - env->entries[idx]->low_word = new_rd_Phi(dbg, current_ir_graph, block, arity, inl, mode); - env->entries[idx]->high_word = new_rd_Phi(dbg, current_ir_graph, block, arity, inh, mode); + env->entries[idx]->low_word = new_rd_Phi(dbg, irg, block, arity, inl, mode); + env->entries[idx]->high_word = new_rd_Phi(dbg, irg, block, arity, inh, mode); if (enq) { /* not yet finished */ pdeq_putr(env->waitq, phi); - } -} + } /* 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: return 1; default: return 0; - } -} + } /* switch */ +} /* always_lower */ -/** The type of a lower function. */ +/** + * 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. + * + * @param node the node to be lowered + * @param mode the low mode for the destination node + * @param env the lower environment + */ typedef void (*lower_func)(ir_node *node, ir_mode *mode, lower_env_t *env); /** - * lower a node. + * Lower a node. */ static void lower_ops(ir_node *node, void *env) { lower_env_t *lenv = env; node_entry_t *entry; int idx = get_irn_idx(node); - - entry = lenv->entries[idx]; + 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))) { 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; @@ -2017,9 +2244,9 @@ static void lower_ops(ir_node *node, void *env) DB((dbg, LEVEL_1, " %+F\n", node)); func(node, mode, lenv); - } - } -} + } /* if */ + } /* if */ +} /* lower_ops */ #define IDENT(s) new_id_from_chars(s, sizeof(s)-1) @@ -2031,7 +2258,7 @@ static int cmp_op_mode(const void *elt, const void *key, size_t size) { const op_mode_entry_t *e2 = key; return (e1->op - e2->op) | (e1->imode - e2->imode) | (e1->omode - e2->omode); -} +} /* cmp_op_mode */ /** * Compare two conv_tp_entry_t's. @@ -2041,7 +2268,7 @@ static int cmp_conv_tp(const void *elt, const void *key, size_t size) { const conv_tp_entry_t *e2 = key; return (e1->imode - e2->imode) | (e1->omode - e2->omode); -} +} /* static int cmp_conv_tp */ /* * Do the lowering. @@ -2050,6 +2277,7 @@ void lower_dw_ops(const lwrdw_param_t *param) { lower_env_t lenv; int i; + ir_graph *rem; if (! param) return; @@ -2063,6 +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 */ if (! prim_types) prim_types = pmap_create(); if (! intrinsic_fkt) @@ -2072,12 +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 */ 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 */ 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); @@ -2086,7 +2316,7 @@ void lower_dw_ops(const lwrdw_param_t *param) set_method_param_type(binop_tp_u, 3, tp_u); set_method_res_type(binop_tp_u, 0, tp_u); set_method_res_type(binop_tp_u, 1, tp_u); - } + } /* if */ if (! binop_tp_s) { binop_tp_s = new_type_method(IDENT("binop_s_intrinsic"), 4, 2); set_method_param_type(binop_tp_s, 0, tp_s); @@ -2095,7 +2325,7 @@ void lower_dw_ops(const lwrdw_param_t *param) set_method_param_type(binop_tp_s, 3, tp_s); set_method_res_type(binop_tp_s, 0, tp_s); set_method_res_type(binop_tp_s, 1, tp_s); - } + } /* if */ if (! shiftop_tp_u) { shiftop_tp_u = new_type_method(IDENT("shiftop_u_intrinsic"), 3, 2); set_method_param_type(shiftop_tp_u, 0, tp_u); @@ -2103,7 +2333,7 @@ void lower_dw_ops(const lwrdw_param_t *param) set_method_param_type(shiftop_tp_u, 2, tp_u); set_method_res_type(shiftop_tp_u, 0, tp_u); set_method_res_type(shiftop_tp_u, 1, tp_u); - } + } /* if */ if (! shiftop_tp_s) { shiftop_tp_s = new_type_method(IDENT("shiftop_s_intrinsic"), 3, 2); set_method_param_type(shiftop_tp_s, 0, tp_s); @@ -2112,21 +2342,21 @@ void lower_dw_ops(const lwrdw_param_t *param) set_method_param_type(shiftop_tp_s, 2, tp_u); set_method_res_type(shiftop_tp_s, 0, tp_s); set_method_res_type(shiftop_tp_s, 1, tp_s); - } + } /* if */ if (! unop_tp_u) { unop_tp_u = new_type_method(IDENT("unop_u_intrinsic"), 2, 2); set_method_param_type(unop_tp_u, 0, tp_u); set_method_param_type(unop_tp_u, 1, tp_u); set_method_res_type(unop_tp_u, 0, tp_u); set_method_res_type(unop_tp_u, 1, tp_u); - } + } /* if */ if (! unop_tp_s) { unop_tp_s = new_type_method(IDENT("unop_s_intrinsic"), 2, 2); set_method_param_type(unop_tp_s, 0, tp_s); set_method_param_type(unop_tp_s, 1, tp_s); set_method_res_type(unop_tp_s, 0, tp_s); set_method_res_type(unop_tp_s, 1, tp_s); - } + } /* if */ lenv.tv_mode_bytes = new_tarval_from_long(get_mode_size_bytes(param->low_unsigned), mode_Iu); lenv.tv_mode_bits = new_tarval_from_long(get_mode_size_bits(param->low_unsigned), mode_Iu); @@ -2141,6 +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 */ LOWER(Load); LOWER(Store); LOWER(Const); @@ -2153,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); @@ -2162,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); @@ -2176,6 +2408,7 @@ void lower_dw_ops(const lwrdw_param_t *param) #undef LOWER2 /* transform all graphs */ + rem = current_ir_graph; for (i = get_irp_n_irgs() - 1; i >= 0; --i) { ir_graph *irg = get_irp_irg(i); int n_idx; @@ -2200,11 +2433,12 @@ void lower_dw_ops(const lwrdw_param_t *param) /* last step: all waiting nodes */ DB((dbg, LEVEL_1, "finishing waiting nodes:\n")); + current_ir_graph = irg; while (! pdeq_empty(lenv.waitq)) { ir_node *node = pdeq_getl(lenv.waitq); lower_ops(node, &lenv); - } + } /* while */ /* outs are invalid, we changed the graph */ set_irg_outs_inconsistent(irg); @@ -2214,35 +2448,35 @@ void lower_dw_ops(const lwrdw_param_t *param) set_irg_doms_inconsistent(irg); set_irg_extblk_inconsistent(irg); set_irg_loopinfo_inconsistent(irg); - } - - dump_ir_block_graph(irg, "-dw"); - } + } /* if */ + } /* if */ pmap_destroy(lenv.proj_2_block); free(lenv.entries); obstack_free(&lenv.obst, NULL); - } + } /* for */ del_pdeq(lenv.waitq); -} + current_ir_graph = rem; +} /* 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) + if (imode == omode) { snprintf(buf, sizeof(buf), "__l%s%s", get_op_name(op), get_mode_name(imode)); - else + } else { snprintf(buf, sizeof(buf), "__l%s%s%s", get_op_name(op), get_mode_name(imode), get_mode_name(omode)); + } /* if */ id = new_id_from_str(buf); ent = new_entity(get_glob_type(), id, method); set_entity_ld_ident(ent, get_entity_ident(ent)); set_entity_visibility(ent, visibility_external_allocated); return ent; -} +} /* def_create_intrinsic_fkt */