* 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.
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 */
};
/**
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;
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.
*/
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;
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);
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;
/* 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;
if (is_lowered_type(tp)) {
mtp = get_associated_type(tp);
} /* 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.
*
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;
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);
#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);
LOWER(Call);
LOWER(Unknown);
LOWER(Phi);
+ LOWER(Psi);
LOWER(Start);
LOWER_BIN(Add);
LOWER(Shr);
LOWER(Shrs);
LOWER(Rot);
- LOWER_UN(Minus);
+ LOWER(Minus);
LOWER(DivMod);
LOWER(Div);
LOWER(Mod);
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;
if (imode == omode) {
snprintf(buf, sizeof(buf), "__l%s%s", get_op_name(op), get_mode_name(imode));