enum firmstat_options_t {
FIRMSTAT_ENABLED = 0x00000001, /**< enable statistics */
FIRMSTAT_PATTERN_ENABLED = 0x00000002, /**< enable pattern calculation */
- FIRMSTAT_COUNT_STRONG_OP = 0x00000004, /**< if set, count Mul/Div/Mod/DivMod by constant */
+ FIRMSTAT_COUNT_STRONG_OP = 0x00000004, /**< if set, count Mul/Div/Mod by constant */
FIRMSTAT_COUNT_DAG = 0x00000008, /**< if set, count DAG statistics */
FIRMSTAT_COUNT_DELETED = 0x00000010, /**< if set, count deleted graphs */
FIRMSTAT_COUNT_SELS = 0x00000020, /**< if set, count Sel(Sel(..)) differently */
*/
FIRM_API ir_node *arch_dep_replace_mod_by_const(ir_node *irn);
-/**
- * Replace DivMods with Shifts and Add/Subs and Mulh.
- * This function is driven by the 3 parameters:
- * - allow_mulhu
- * - allow_mulhs
- * - max_bits_for_mulh
- *
- * If irn is a DivMod with a Const, the constant is inspected if it meets the
- * requirements of the variables stated above. If a Shl/Add/Sub/Mulh
- * sequence can be generated that meets these requirements, this expression
- * is returned. In each other case irn is returned unmodified.
- *
- * @param div After call contains the Firm node div result or NULL.
- * @param mod After call contains the Firm node mod result or NULL.
- * @param irn The Firm node to inspect.
- */
-FIRM_API void arch_dep_replace_divmod_by_const(ir_node **div, ir_node **mod,
- ir_node *irn);
-
#include "end.h"
#endif
* ir_node *new_Mul (ir_node *op1, ir_node *op2, ir_mode *mode);
* ir_node *new_Mulh (ir_node *op1, ir_node *op2, ir_mode *mode);
* ir_node *new_Quot (ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state);
- * ir_node *new_DivMod (ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state);
* ir_node *new_Div (ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state);
* ir_node *new_Mod (ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state;
* ir_node *new_And (ir_node *op1, ir_node *op2, ir_mode *mode);
* A tuple containing a memory and a execution for modeling exceptions
* and the result of the arithmetic operation.
*
- * ir_node *new_DivMod (ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state)
- * ---------------------------------------------------------------------------------------------------
- *
- * Performs Div and Mod on integer values.
- *
- * Output:
- * A tuple containing a memory and a execution for modeling exceptions
- * and the two result of the arithmetic operations.
- *
* ir_node *new_Div (ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state)
* ------------------------------------------------------------------------------------------------
*
/** This hook is called after a Mul was replaced by a series of Shift and Add/Sub operations. */
void (*_hook_arch_dep_replace_mul_with_shifts)(void *context, ir_node *irn);
- /** This hook is called after a Div/Mod/DivMod by a constant value was replaced. */
+ /** This hook is called after a Div/Mod by a constant value was replaced. */
void (*_hook_arch_dep_replace_division_by_const)(void *context, ir_node *irn);
/** This hook is called after a new mode was registered. */
operands can be factored out. Left is the first, right the
second arithmetic value as listed in tech report 1999-44.
unops are: Minus, Abs, Not, Conv, Cast
- binops are: Add, Sub, Mul, Quot, DivMod, Div, Mod, And, Or, Eor, Shl,
+ binops are: Add, Sub, Mul, Quot, Div, Mod, And, Or, Eor, Shl,
Shr, Shrs, Rotl, Cmp */
FIRM_API int is_unop(const ir_node *node);
FIRM_API ir_node *get_unop_op(const ir_node *node);
FIRM_API int is_cfop(const ir_node *node);
/** Returns true if the operation can change the control flow because
- of an exception: Call, Quot, DivMod, Div, Mod, Load, Store, Alloc,
+ of an exception: Call, Quot, Div, Mod, Load, Store, Alloc,
Bad. Raise is not fragile, but a unconditional jump. */
FIRM_API int is_fragile_op(const ir_node *node);
/** Returns the memory operand of fragile operations. */
FIRM_API ir_node *get_fragile_op_mem(ir_node *node);
-/** Returns the result mode of a Div operation. */
-FIRM_API ir_mode *get_divop_resmod(const ir_node *node);
/** Returns true if the operation is a forking control flow
* operation: Cond. */
is_Abs(node) is_Alloc(node) is_Anchor(node) is_Borrow(node) is_Bound(node)
is_Break(node) is_Builtin(node) is_Call(node)
is_Carry(node) is_Cast(node) is_Cmp(node) is_Cond(node)
- is_CopyB(node) is_Div(node) is_DivMod(node) is_Dummy(node)
+ is_CopyB(node) is_Div(node) is_Dummy(node)
is_End(node) is_Free(node)
is_IJmp(node) is_InstOf(node) is_Jmp(node) is_Load(node) is_Minus(node)
is_Mod(node) is_Mul(node) is_Mulh(node) is_Mux(node) is_NoMem(node)
match_flags_t flags = match_commutative;
/* happens for div nodes... */
- if (mode == mode_T)
- mode = get_divop_resmod(node);
+ if (mode == mode_T) {
+ if (is_Div(node))
+ mode = get_Div_resmode(node);
+ else if (is_Mod(node))
+ mode = get_Mod_resmode(node);
+ else
+ panic("can't determine mode");
+ }
/* cannot use address mode with long double on x87 */
if (get_mode_size_bits(mode) <= 64)
}
/**
- * Generates an ia32 DivMod with additional infrastructure for the
+ * Generates an ia32 Div with additional infrastructure for the
* register allocator if needed.
*/
static ir_node *create_Div(ir_node *node)
mem = get_Mod_mem(node);
mode = get_Mod_resmode(node);
break;
- case iro_DivMod:
- op1 = get_DivMod_left(node);
- op2 = get_DivMod_right(node);
- mem = get_DivMod_mem(node);
- mode = get_DivMod_resmode(node);
- break;
default:
panic("invalid divmod node %+F", node);
}
return create_Div(node);
}
-/**
- * Generates an ia32 DivMod.
- */
-static ir_node *gen_DivMod(ir_node *node)
-{
- return create_Div(node);
-}
-
-
/**
* Creates an ia32 floating Div.
}
/**
- * Transform and renumber the Projs from a DivMod like instruction.
+ * Transform and renumber the Projs from a Div or Mod instruction.
*/
-static ir_node *gen_Proj_DivMod(ir_node *node)
+static ir_node *gen_Proj_Div_Mod(ir_node *node)
{
ir_node *block = be_transform_node(get_nodes_block(node));
ir_node *pred = get_Proj_pred(node);
break;
}
break;
- case iro_DivMod:
- switch (proj) {
- case pn_DivMod_M:
- return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_Div_M);
- case pn_DivMod_res_div:
- return new_rd_Proj(dbgi, new_pred, mode_Iu, pn_ia32_Div_div_res);
- case pn_DivMod_res_mod:
- return new_rd_Proj(dbgi, new_pred, mode_Iu, pn_ia32_Div_mod_res);
- case pn_DivMod_X_regular:
- return new_rd_Jmp(dbgi, block);
- case pn_DivMod_X_except:
- set_ia32_exc_label(new_pred, 1);
- return new_rd_Proj(dbgi, new_pred, mode_X, pn_ia32_Div_X_exc);
- default:
- break;
- }
- break;
default:
break;
}
- panic("No idea how to transform proj->DivMod");
+ panic("No idea how to transform proj->Div/Mod");
}
/**
return gen_Proj_Builtin(node);
case iro_Div:
case iro_Mod:
- case iro_DivMod:
- return gen_Proj_DivMod(node);
+ return gen_Proj_Div_Mod(node);
case iro_CopyB:
return gen_Proj_CopyB(node);
case iro_Quot:
be_set_transform_function(op_Conv, gen_Conv);
be_set_transform_function(op_CopyB, ia32_gen_CopyB);
be_set_transform_function(op_Div, gen_Div);
- be_set_transform_function(op_DivMod, gen_DivMod);
be_set_transform_function(op_Eor, gen_Eor);
be_set_transform_function(op_ia32_l_Adc, gen_ia32_l_Adc);
be_set_transform_function(op_ia32_l_Add, gen_ia32_l_Add);
/**
* Build the Mulh replacement code for n / tv.
*
- * Note that 'div' might be a mod or DivMod operation as well
+ * Note that 'div' might be a Mod operation as well
*/
static ir_node *replace_div_by_mulh(ir_node *div, ir_tarval *tv)
{
return res;
}
-
-/* Replace DivMods with Shifts and Add/Subs and Mulh. */
-void arch_dep_replace_divmod_by_const(ir_node **div, ir_node **mod, ir_node *irn)
-{
- const ir_settings_arch_dep_t *params = be_get_backend_param()->dep_param;
- *div = *mod = NULL;
-
- /* If the architecture dependent optimizations were not initialized
- or this optimization was not enabled. */
- if (params == NULL ||
- ((opts & (arch_dep_div_by_const|arch_dep_mod_by_const)) != (arch_dep_div_by_const|arch_dep_mod_by_const)))
- return;
-
- if (is_DivMod(irn)) {
- ir_node *c = get_DivMod_right(irn);
- ir_node *block, *left;
- ir_mode *mode;
- ir_tarval *tv, *ntv;
- dbg_info *dbg;
- int n, bits;
- int k;
- int n_flag = 0;
-
- if (! is_Const(c))
- return;
-
- tv = get_Const_tarval(c);
-
- /* check for division by zero */
- if (tarval_is_null(tv))
- return;
-
- left = get_DivMod_left(irn);
- mode = get_irn_mode(left);
- block = get_irn_n(irn, -1);
- dbg = get_irn_dbg_info(irn);
-
- bits = get_mode_size_bits(mode);
- n = (bits + 7) / 8;
-
- k = -1;
- if (mode_is_signed(mode)) {
- /* for signed divisions, the algorithm works for a / -2^k by negating the result */
- ntv = tarval_neg(tv);
- n_flag = 1;
- k = tv_ld2(ntv, n);
- }
-
- if (k < 0) {
- n_flag = 0;
- k = tv_ld2(tv, n);
- }
-
- if (k >= 0) { /* division by 2^k or -2^k */
- ir_graph *irg = get_irn_irg(irn);
- if (mode_is_signed(mode)) {
- ir_node *k_node, *c_k;
- ir_node *curr = left;
-
- if (k != 1) {
- k_node = new_r_Const_long(irg, mode_Iu, k - 1);
- curr = new_rd_Shrs(dbg, block, left, k_node, mode);
- }
-
- k_node = new_r_Const_long(irg, mode_Iu, bits - k);
- curr = new_rd_Shr(dbg, block, curr, k_node, mode);
-
- curr = new_rd_Add(dbg, block, left, curr, mode);
-
- c_k = new_r_Const_long(irg, mode_Iu, k);
-
- *div = new_rd_Shrs(dbg, block, curr, c_k, mode);
-
- if (n_flag) { /* negate the div result */
- ir_node *k_node = new_r_Const(irg, get_mode_null(mode));
- *div = new_rd_Sub(dbg, block, k_node, *div, mode);
- }
-
- k_node = new_r_Const_long(irg, mode, (-1) << k);
- curr = new_rd_And(dbg, block, curr, k_node, mode);
-
- *mod = new_rd_Sub(dbg, block, left, curr, mode);
- } else { /* unsigned case */
- ir_node *k_node = new_r_Const_long(irg, mode_Iu, k);
- *div = new_rd_Shr(dbg, block, left, k_node, mode);
-
- k_node = new_r_Const_long(irg, mode, (1 << k) - 1);
- *mod = new_rd_And(dbg, block, left, k_node, mode);
- }
- } else {
- /* other constant */
- if (allow_Mulh(params, mode)) {
- ir_node *t;
-
- *div = replace_div_by_mulh(irn, tv);
-
- t = new_rd_Mul(dbg, block, *div, c, mode);
-
- /* t = arch_dep_mul_to_shift(t); */
-
- *mod = new_rd_Sub(dbg, block, left, t, mode);
- }
- }
- }
-
- if (*div)
- hook_arch_dep_replace_division_by_const(irn);
-}
case iro_Mod:
fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Mod_resmode(n), NULL));
break;
- case iro_DivMod:
- fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_DivMod_resmode(n), NULL));
- break;
case iro_Builtin:
fprintf(F, "%s[%s]", get_irn_opname(n), get_builtin_kind_name(get_Builtin_kind(n)));
break;
#undef X
};
-/** the lookup table for Proj(DivMod) names */
-static const pns_lookup_t divmod_lut[] = {
-#define X(a) { pn_DivMod_##a, #a }
- X(M),
- X(X_regular),
- X(X_except),
- X(res_div),
- X(res_mod)
-#undef X
-};
-
/** the lookup table for Proj(Div) names */
static const pns_lookup_t div_lut[] = {
#define X(a) { pn_Div_##a, #a }
{ iro_Cond, E(cond_lut) },
{ iro_Call, E(call_lut) },
{ iro_Quot, E(quot_lut) },
- { iro_DivMod, E(divmod_lut) },
{ iro_Div, E(div_lut) },
{ iro_Mod, E(mod_lut) },
{ iro_Load, E(load_lut) },
set_irn_n(node, pos + SEL_INDEX_OFFSET, index);
}
-
-/* For unary and binary arithmetic operations the access to the
- operands can be factored out. Left is the first, right the
- second arithmetic value as listed in tech report 0999-33.
- unops are: Minus, Abs, Not, Conv, Cast
- binops are: Add, Sub, Mul, Quot, DivMod, Div, Mod, And, Or, Eor, Shl,
- Shr, Shrs, Rotate, Cmp */
-
-
ir_node **get_Call_param_arr(ir_node *node)
{
assert(is_Call(node));
switch (get_irn_opcode(node)) {
case iro_Call :
case iro_Quot :
- case iro_DivMod:
case iro_Div :
case iro_Mod :
case iro_Load :
}
}
-/* Returns the result mode of a Div operation. */
-ir_mode *get_divop_resmod(const ir_node *node)
-{
- switch (get_irn_opcode(node)) {
- case iro_Quot : return get_Quot_resmode(node);
- case iro_DivMod: return get_DivMod_resmode(node);
- case iro_Div : return get_Div_resmode(node);
- case iro_Mod : return get_Mod_resmode(node);
- default:
- panic("should not be reached");
- }
-}
-
/* Returns true if the operation is a forking control flow operation. */
int (is_irn_forking)(const ir_node *node)
{
return tarval_bad;
} /* do_computed_value_Mod */
-/**
- * Return the value of a Proj(DivMod).
- */
-static ir_tarval *computed_value_Proj_DivMod(const ir_node *n)
-{
- long proj_nr = get_Proj_proj(n);
-
- /* compute either the Div or the Mod part */
- if (proj_nr == pn_DivMod_res_div) {
- const ir_node *a = get_Proj_pred(n);
- return do_computed_value_Div(get_DivMod_left(a), get_DivMod_right(a));
- } else if (proj_nr == pn_DivMod_res_mod) {
- const ir_node *a = get_Proj_pred(n);
- return do_computed_value_Mod(get_DivMod_left(a), get_DivMod_right(a));
- }
- return tarval_bad;
-} /* computed_value_Proj_DivMod */
-
/**
* Return the value of a Proj(Div).
*/
CASE(Mux);
CASE(Confirm);
CASE_PROJ(Cmp);
- CASE_PROJ(DivMod);
CASE_PROJ(Div);
CASE_PROJ(Mod);
CASE_PROJ(Quot);
return proj;
} /* equivalent_node_Proj_Quot */
-/**
- * Optimize a / 1 = a.
- */
-static ir_node *equivalent_node_Proj_DivMod(ir_node *proj)
-{
- ir_node *oldn = proj;
- ir_node *divmod = get_Proj_pred(proj);
- ir_node *b = get_DivMod_right(divmod);
- ir_tarval *tb = value_of(b);
-
- /* Div is not commutative. */
- if (tarval_is_one(tb)) { /* div(x, 1) == x */
- switch (get_Proj_proj(proj)) {
- case pn_DivMod_M:
- proj = get_DivMod_mem(divmod);
- DBG_OPT_ALGSIM0(oldn, proj, FS_OPT_NEUTRAL_1);
- return proj;
-
- case pn_DivMod_res_div:
- proj = get_DivMod_left(divmod);
- DBG_OPT_ALGSIM0(oldn, proj, FS_OPT_NEUTRAL_1);
- return proj;
-
- default:
- /* we cannot replace the exception Proj's here, this is done in
- transform_node_Proj_DivMod().
- Note further that the pn_DivMod_res_div case is handled in
- computed_value_Proj(). */
- return proj;
- }
- }
- return proj;
-} /* equivalent_node_Proj_DivMod */
-
/**
* Optimize CopyB(mem, x, x) into a Nop.
*/
CASE_PROJ(Tuple);
CASE_PROJ(Div);
CASE_PROJ(Quot);
- CASE_PROJ(DivMod);
CASE_PROJ(CopyB);
CASE_PROJ(Bound);
CASE_PROJ(Load);
return n;
} /* transform_node_Mod */
-/**
- * Transform a DivMod node.
- */
-static ir_node *transform_node_DivMod(ir_node *n)
-{
- const ir_node *dummy;
- ir_node *a = get_DivMod_left(n);
- ir_node *b = get_DivMod_right(n);
- ir_mode *mode = get_DivMod_resmode(n);
- ir_node *va, *vb;
- ir_graph *irg = get_irn_irg(n);
- ir_tarval *ta, *tb;
- int evaluated = 0;
-
- if (is_Const(b) && is_const_Phi(a)) {
- /* check for Div(Phi, Const) */
- va = apply_binop_on_phi(a, get_Const_tarval(b), (eval_func) tarval_div, mode, 0);
- vb = apply_binop_on_phi(a, get_Const_tarval(b), (eval_func) tarval_mod, mode, 0);
- if (va && vb) {
- DBG_OPT_ALGSIM0(n, va, FS_OPT_CONST_PHI);
- DBG_OPT_ALGSIM0(n, vb, FS_OPT_CONST_PHI);
- goto make_tuple;
- }
- }
- else if (is_Const(a) && is_const_Phi(b)) {
- /* check for Div(Const, Phi) */
- va = apply_binop_on_phi(b, get_Const_tarval(a), (eval_func) tarval_div, mode, 1);
- vb = apply_binop_on_phi(b, get_Const_tarval(a), (eval_func) tarval_mod, mode, 1);
- if (va && vb) {
- DBG_OPT_ALGSIM0(n, va, FS_OPT_CONST_PHI);
- DBG_OPT_ALGSIM0(n, vb, FS_OPT_CONST_PHI);
- goto make_tuple;
- }
- }
- else if (is_const_Phi(a) && is_const_Phi(b)) {
- /* check for Div(Phi, Phi) */
- va = apply_binop_on_2_phis(a, b, (eval_func) tarval_div, mode);
- vb = apply_binop_on_2_phis(a, b, (eval_func) tarval_mod, mode);
- if (va && vb) {
- DBG_OPT_ALGSIM0(n, va, FS_OPT_CONST_PHI);
- DBG_OPT_ALGSIM0(n, vb, FS_OPT_CONST_PHI);
- goto make_tuple;
- }
- }
-
- ta = value_of(a);
- tb = value_of(b);
- if (tb != tarval_bad) {
- if (tb == get_mode_one(get_tarval_mode(tb))) {
- va = a;
- vb = new_r_Const(irg, get_mode_null(mode));
- DBG_OPT_CSTEVAL(n, vb);
- goto make_tuple;
- } else if (ta != tarval_bad) {
- ir_tarval *resa, *resb;
- resa = tarval_div(ta, tb);
- if (resa == tarval_bad) return n; /* Causes exception!!! Model by replacing through
- Jmp for X result!? */
- resb = tarval_mod(ta, tb);
- if (resb == tarval_bad) return n; /* Causes exception! */
- va = new_r_Const(irg, resa);
- vb = new_r_Const(irg, resb);
- DBG_OPT_CSTEVAL(n, va);
- DBG_OPT_CSTEVAL(n, vb);
- goto make_tuple;
- } else if (mode_is_signed(mode) && tb == get_mode_minus_one(mode)) {
- va = new_rd_Minus(get_irn_dbg_info(n), get_nodes_block(n), a, mode);
- vb = new_r_Const(irg, get_mode_null(mode));
- DBG_OPT_CSTEVAL(n, va);
- DBG_OPT_CSTEVAL(n, vb);
- goto make_tuple;
- } else { /* Try architecture dependent optimization */
- va = a;
- vb = b;
- arch_dep_replace_divmod_by_const(&va, &vb, n);
- evaluated = va != NULL;
- }
- } else if (a == b) {
- if (value_not_zero(a, &dummy)) {
- /* a/a && a != 0 */
- va = new_r_Const(irg, get_mode_one(mode));
- vb = new_r_Const(irg, get_mode_null(mode));
- DBG_OPT_CSTEVAL(n, va);
- DBG_OPT_CSTEVAL(n, vb);
- goto make_tuple;
- } else {
- /* BEWARE: it is NOT possible to optimize a/a to 1, as this may cause a exception */
- return n;
- }
- } else if (ta == get_mode_null(mode) && value_not_zero(b, &dummy)) {
- /* 0 / non-Const = 0 */
- vb = va = a;
- goto make_tuple;
- }
-
- if (evaluated) { /* replace by tuple */
- ir_node *mem, *blk;
-
-make_tuple:
- mem = get_DivMod_mem(n);
- /* skip a potential Pin */
- mem = skip_Pin(mem);
-
- blk = get_nodes_block(n);
- turn_into_tuple(n, pn_DivMod_max);
- set_Tuple_pred(n, pn_DivMod_M, mem);
- set_Tuple_pred(n, pn_DivMod_X_regular, new_r_Jmp(blk));
- set_Tuple_pred(n, pn_DivMod_X_except, get_irg_bad(irg)); /*no exception*/
- set_Tuple_pred(n, pn_DivMod_res_div, va);
- set_Tuple_pred(n, pn_DivMod_res_mod, vb);
- }
-
- return n;
-} /* transform_node_DivMod */
-
/**
* Optimize x / c to x * (1/c)
*/
return proj;
} /* transform_node_Proj_Mod */
-/**
- * Transform a Proj(DivMod) with a non-zero value.
- * Removes the exceptions and routes the memory to the NoMem node.
- */
-static ir_node *transform_node_Proj_DivMod(ir_node *proj)
-{
- ir_node *divmod = get_Proj_pred(proj);
- ir_node *b = get_DivMod_right(divmod);
- ir_node *res, *new_mem;
- const ir_node *confirm;
- long proj_nr;
-
- if (value_not_zero(b, &confirm)) {
- /* DivMod(x, y) && y != 0 */
- proj_nr = get_Proj_proj(proj);
-
- if (confirm == NULL) {
- /* we are sure we have a Const != 0 */
- new_mem = get_DivMod_mem(divmod);
- new_mem = skip_Pin(new_mem);
- set_DivMod_mem(divmod, new_mem);
- set_irn_pinned(divmod, op_pin_state_floats);
- }
-
- switch (proj_nr) {
-
- case pn_DivMod_X_regular:
- return new_r_Jmp(get_nodes_block(divmod));
-
- case pn_DivMod_X_except: {
- /* we found an exception handler, remove it */
- ir_graph *irg = get_irn_irg(proj);
- DBG_OPT_EXC_REM(proj);
- return get_irg_bad(irg);
- }
-
- case pn_DivMod_M: {
- ir_graph *irg = get_irn_irg(proj);
- res = get_DivMod_mem(divmod);
- new_mem = get_irg_no_mem(irg);
-
- if (confirm) {
- /* This node can only float up to the Confirm block */
- new_mem = new_r_Pin(get_nodes_block(confirm), new_mem);
- }
- /* this is a DivMod without exception, we can remove the memory edge */
- set_DivMod_mem(divmod, new_mem);
- return res;
- }
-
- case pn_DivMod_res_mod:
- if (get_DivMod_left(divmod) == b) {
- /* a % a = 0 if a != 0 */
- ir_graph *irg = get_irn_irg(proj);
- ir_mode *mode = get_irn_mode(proj);
- ir_node *res = new_r_Const(irg, get_mode_null(mode));
-
- DBG_OPT_CSTEVAL(divmod, res);
- return res;
- }
- }
- }
- return proj;
-} /* transform_node_Proj_DivMod */
-
/**
* Optimizes jump tables (CondIs or CondIu) by removing all impossible cases.
*/
if ((proj_nr == pn_Cmp_Eq || proj_nr == pn_Cmp_Lg) && is_Const(right) && is_Const_null(right) && is_Proj(left)) {
ir_node *op = get_Proj_pred(left);
- if ((is_Mod(op) && get_Proj_proj(left) == pn_Mod_res) ||
- (is_DivMod(op) && get_Proj_proj(left) == pn_DivMod_res_mod)) {
+ if (is_Mod(op) && get_Proj_proj(left) == pn_Mod_res) {
ir_node *c = get_binop_right(op);
if (is_Const(c)) {
CASE(Mul);
CASE_PROJ_EX(Div);
CASE_PROJ_EX(Mod);
- CASE_PROJ_EX(DivMod);
CASE(Quot);
CASE_PROJ_EX(Cmp);
CASE_PROJ_EX(Cond);
ma->no_remainder != mb->no_remainder;
} /* node_cmp_attr_Div */
-/** Compares the attributes of two DivMod nodes. */
-static int node_cmp_attr_DivMod(ir_node *a, ir_node *b)
+/** Compares the attributes of two Div or Mod nodes. */
+static int node_cmp_attr_Div_Mod(ir_node *a, ir_node *b)
{
const divmod_attr *ma = &a->attr.divmod;
const divmod_attr *mb = &b->attr.divmod;
return ma->exc.pin_state != mb->exc.pin_state ||
ma->resmode != mb->resmode;
-} /* node_cmp_attr_DivMod */
+} /* node_cmp_attr_Div_Mod */
/** Compares the attributes of two Mod nodes. */
static int node_cmp_attr_Mod(ir_node *a, ir_node *b)
{
- return node_cmp_attr_DivMod(a, b);
+ return node_cmp_attr_Div_Mod(a, b);
} /* node_cmp_attr_Mod */
/** Compares the attributes of two Quot nodes. */
static int node_cmp_attr_Quot(ir_node *a, ir_node *b)
{
- return node_cmp_attr_DivMod(a, b);
+ return node_cmp_attr_Div_Mod(a, b);
} /* node_cmp_attr_Quot */
/** Compares the attributes of two Confirm nodes. */
CASE(Confirm);
CASE(ASM);
CASE(Div);
- CASE(DivMod);
CASE(Mod);
CASE(Quot);
CASE(Bound);
char strict; /**< If set, this is a strict Conv that cannot be removed. */
} conv_attr;
-/** Div/Mod/DivMod/Quot attribute. */
+/** Div/Mod/Quot attribute. */
typedef struct divmod_attr {
except_attr exc; /**< The exception attribute. MUST be the first one. */
ir_mode *resmode; /**< Result mode for the division. */
copyb_attr copyb; /**< For CopyB operation */
bound_attr bound; /**< For Bound operation */
conv_attr conv; /**< For Conv operation */
- divmod_attr divmod; /**< For Div/Mod/DivMod operation */
+ divmod_attr divmod; /**< For Div/Mod operation */
asm_attr assem; /**< For ASM operation. */
} ir_attr;
return 1;
}
-/**
- * verify a Proj(DivMod) node
- */
-static int verify_node_Proj_DivMod(ir_node *n, ir_node *p)
-{
- ir_mode *mode = get_irn_mode(p);
- long proj = get_Proj_proj(p);
-
- ASSERT_AND_RET_DBG(
- (
- (proj == pn_DivMod_M && mode == mode_M) ||
- (proj == pn_DivMod_X_regular && mode == mode_X) ||
- (proj == pn_DivMod_X_except && mode == mode_X) ||
- (proj == pn_DivMod_res_div && mode_is_int(mode) && mode == get_DivMod_resmode(n)) ||
- (proj == pn_DivMod_res_mod && mode_is_int(mode) && mode == get_DivMod_resmode(n))
- ),
- "wrong Proj from DivMod", 0,
- show_proj_failure(p);
- );
- if (proj == pn_DivMod_X_regular)
- ASSERT_AND_RET(
- get_irn_pinned(n) == op_pin_state_pinned,
- "Regular Proj from unpinned DivMod", 0);
- else if (proj == pn_DivMod_X_except)
- ASSERT_AND_RET(
- get_irn_pinned(n) == op_pin_state_pinned,
- "Exception Proj from unpinned DivMod", 0);
- else if (proj == pn_DivMod_M)
- ASSERT_AND_RET(
- get_irn_pinned(n) == op_pin_state_pinned,
- "Memory Proj from unpinned DivMod", 0);
- return 1;
-}
-
/**
* verify a Proj(Div) node
*/
return 1;
}
-/**
- * verify a DivMod node
- */
-static int verify_node_DivMod(ir_node *n, ir_graph *irg)
-{
- ir_mode *mymode = get_irn_mode(n);
- ir_mode *op1mode = get_irn_mode(get_DivMod_mem(n));
- ir_mode *op2mode = get_irn_mode(get_DivMod_left(n));
- ir_mode *op3mode = get_irn_mode(get_DivMod_right(n));
- (void) irg;
-
- ASSERT_AND_RET(
- /* DivMod: BB x M x int x int --> M x X x int x int */
- op1mode == mode_M &&
- mode_is_int(op2mode) &&
- op3mode == op2mode &&
- mymode == mode_T,
- "DivMod node", 0
- );
- return 1;
-}
-
/**
* verify a Div node
*/
CASE(Mul);
CASE(Mulh);
CASE(Quot);
- CASE(DivMod);
CASE(Div);
CASE(Mod);
CASE(And);
CASE(InstOf);
CASE(Call);
CASE(Quot);
- CASE(DivMod);
CASE(Div);
CASE(Mod);
CASE(Cmp);
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:
}
}
-static void lower_DivMod(ir_node *node, ir_mode *mode, lower_env_t *env)
-{
- (void) node;
- (void) mode;
- (void) env;
- panic("DivMod is deprecated, no doubleword lowering");
-}
-
/**
* Translate a binop.
*
enter_lower_func(op_Const, lower_Const);
enter_lower_func(op_Conv, lower_Conv);
enter_lower_func(op_Div, lower_Div);
- enter_lower_func(op_DivMod, lower_DivMod);
enter_lower_func(op_Eor, lower_Eor);
enter_lower_func(op_Load, lower_Load);
enter_lower_func(op_Minus, lower_Unop);
case iro_Quot: return get_Quot_resmode(node);
case iro_Div: return get_Div_resmode(node);
case iro_Mod: return get_Mod_resmode(node);
- case iro_DivMod: return get_DivMod_resmode(node);
default: return NULL;
}
} /* get_irn_res_mode */
return 0;
mode = get_irn_mode(n);
if (!mode_is_data(mode)) {
- if (! is_Div(n) && ! is_Mod(n) && ! is_DivMod(n))
+ if (! is_Div(n) && ! is_Mod(n))
return 0;
if (! is_NoMem(get_fragile_op_mem(n)))
return 0;
ir_mode *mode;
ir_node *block1, *count_block, *duff_block;
- ir_node *ems, *ems_divmod, *ems_mod_proj, *cmp_null,
+ ir_node *ems, *ems_mod, *ems_div, *ems_mod_proj, *cmp_null,
*cmp_proj, *ems_mode_cond, *x_true, *x_false, *const_null;
ir_node *true_val, *false_val;
ir_node *ins[2];
ems = new_Sub(loop_info.end_val, loop_info.start_val,
get_irn_mode(loop_info.end_val));
- DB((dbg, LEVEL_4, "divmod ins %N %N\n", ems, loop_info.step));
- ems_divmod = new_r_DivMod(block1,
+ DB((dbg, LEVEL_4, "mod ins %N %N\n", ems, loop_info.step));
+ ems_mod = new_r_Mod(block1,
+ new_NoMem(),
+ ems,
+ loop_info.step,
+ mode,
+ op_pin_state_pinned);
+ ems_div = new_r_Div(block1,
new_NoMem(),
ems,
loop_info.step,
mode,
op_pin_state_pinned);
- DB((dbg, LEVEL_4, "New module node %N\n", ems_divmod));
+ DB((dbg, LEVEL_4, "New module node %N\n", ems_mod));
- ems_mod_proj = new_r_Proj(ems_divmod, mode_Iu, pn_DivMod_res_mod);
+ ems_mod_proj = new_r_Proj(ems_mod, mode_Iu, pn_Mod_res);
cmp_null = new_r_Cmp(block1, ems_mod_proj, const_null);
cmp_proj = new_r_Proj(cmp_null, mode_b, pn_Cmp_Eq);
ems_mode_cond = new_r_Cond(block1, cmp_proj);
correction = new_r_Phi(count_block, 2, ins, mode);
- count = new_r_Proj(ems_divmod, mode, pn_DivMod_res_div);
+ count = new_r_Proj(ems_div, mode, pn_Div_res);
/* (end - start) / step + correction */
count = new_Add(count, correction, mode);
} /* update_Call_memop */
/**
- * Update a memop for a Div/Mod/Quot/DivMod.
+ * Update a memop for a Div/Mod/Quot.
*
* @param m the memop
*/
/* we can those to find the memory edge */
break;
case iro_Div:
- case iro_DivMod:
case iro_Quot:
case iro_Mod:
update_DivOp_memop(op);
/** The Div by Const node. */
static ir_op _op_ModC;
-/** The Div by Const node. */
-static ir_op _op_DivModC;
-
/** The Quot by Const node. */
static ir_op _op_QuotC;
op = status->op_ModC ? status->op_ModC : op;
} /* if */
break;
- case iro_DivMod:
- if (is_Const(get_DivMod_right(node))) {
- /* special case, a division/modulo by a const, count on extra counter */
- op = status->op_DivModC ? status->op_DivModC : op;
- } /* if */
- break;
case iro_Quot:
if (is_Const(get_Quot_right(node))) {
/* special case, a floating point division by a const, count on extra counter */
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:
_op_ModC.code = --num;
_op_ModC.name = new_id_from_chars(X("ModC"));
- _op_DivModC.code = --num;
- _op_DivModC.name = new_id_from_chars(X("DivModC"));
-
_op_QuotC.code = --num;
_op_QuotC.name = new_id_from_chars(X("QuotC"));
status->op_MulC = &_op_MulC;
status->op_DivC = &_op_DivC;
status->op_ModC = &_op_ModC;
- status->op_DivModC = &_op_DivModC;
status->op_QuotC = &_op_QuotC;
} else {
status->op_Phi0 = NULL;
status->op_MulC = NULL;
status->op_DivC = NULL;
status->op_ModC = NULL;
- status->op_DivModC = NULL;
status->op_QuotC = NULL;
} /* if */
ir_op *op_MulC; /**< pseudo op for multiplication by const */
ir_op *op_DivC; /**< pseudo op for division by const */
ir_op *op_ModC; /**< pseudo op for modulo by const */
- ir_op *op_DivModC; /**< pseudo op for DivMod by const */
ir_op *op_QuotC; /**< pseudo op for floating point division by const */
ir_op *op_SelSel; /**< pseudo op for Sel(Sel) */
ir_op *op_SelSelSel; /**< pseudo op for Sel(Sel(Sel)) */
op_index = 1
arity_override = "oparity_binary"
-class DivMod(Op):
- """divides its 2 operands and computes the remainder of the division"""
- ins = [
- ("mem", "memory dependency"),
- ("left", "first operand"),
- ("right", "second operand"),
- ]
- outs = [
- ("M", "memory result", "pn_Generic_M"),
- ("X_regular", "control flow when no exception occurs", "pn_Generic_X_regular"),
- ("X_except", "control flow when exception occured", "pn_Generic_X_except"),
- ("res_div", "result of computation a/b", "pn_Generic_other"),
- ("res_mod", "result of computation a%b"),
- ]
- flags = [ "fragile", "uses_memory" ]
- attrs_name = "divmod"
- attrs = [
- dict(
- type = "ir_mode*",
- name = "resmode",
- comment = "mode of the result value",
- ),
- ]
- attr_struct = "divmod_attr"
- pinned = "exception"
- op_index = 1
- arity_override = "oparity_binary"
-
class Dummy(Op):
"""A placeholder value. This is used when constructing cyclic graphs where
you have cases where not all predecessors of a phi-node are known. Dummy