/*
- * 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 <malloc.h>
-#endif
-#ifdef HAVE_ALLOCA_H
-# include <alloca.h>
-#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#include <assert.h>
+#include "lowering.h"
#include "irnode_t.h"
#include "irgraph_t.h"
#include "irmode_t.h"
#include "firmstat.h"
#include "irgwalk.h"
#include "ircons.h"
-#include "lower_dw.h"
#include "irflag.h"
#include "irtools.h"
#include "debug.h"
#include "pmap.h"
#include "pdeq.h"
#include "irdump.h"
+#include "xmalloc.h"
/** A map from mode to a primitive type. */
static pmap *prim_types;
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;
/**
* 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 */
};
/**
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 */
/**
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)];
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;
* 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;
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;
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;
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;
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 */
* 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) {
* 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);
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);
} /* 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);
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.
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))) {
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;
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 */
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 */
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)
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);
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);
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);
} /* 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));