* ir_node *new_Minus (ir_node *op, ir_mode *mode);
* 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_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);
*
* Returns the high order bits of a n*n=2n multiplication.
*
- * ir_node *new_Quot (ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state)
- * -------------------------------------------------------------------------------------------------
- *
- * Quot performs exact division of floating point numbers. It's mode
- * is Tuple, the mode of the result must match the Proj mode
- * that extracts the result of the arithmetic operations.
- *
- * Inputs:
- * The store needed to model exceptions and the two operands.
- * Output:
- * A tuple containing a memory and a execution for modeling exceptions
- * and the result of the arithmetic operation.
- *
* ir_node *new_Div (ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state)
* ------------------------------------------------------------------------------------------------
*
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, Div, Mod, And, Or, Eor, Shl,
+ binops are: Add, Sub, Mul, 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, Div, Mod, Load, Store, Alloc,
+ of an exception: Call, 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_tarval *tarval_mul(ir_tarval *a, ir_tarval *b);
-/**
- * Division of two floating point tarvals.
- *
- * @param a the first tarval
- * @param b the second tarval
- *
- * @return a / b or tarval_bad
- */
-FIRM_API ir_tarval *tarval_quo(ir_tarval *a, ir_tarval *b);
-
/**
* Integer division of two tarvals.
*
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)
- is_Pin(node) is_Proj(node) is_Quot(node)
+ is_Pin(node) is_Proj(node)
is_Raise(node) is_Return(node) is_Sel(node) is_Start(node) is_Store(node)
is_SymConst(node) is_Sync(node) is_Tuple(node)
*/
return transform_binop(node, new_bd_TEMPLATE_Xor);
}
-static ir_node *gen_Quot(ir_node *node)
+static ir_node *gen_Div(ir_node *node)
{
+ ir_mode *mode = get_Div_resmode(node);
+ assert(mode_is_float(mode));
return transform_binop(node, new_bd_TEMPLATE_fDiv);
}
be_set_transform_function(op_Add, gen_Add);
be_set_transform_function(op_And, gen_And);
be_set_transform_function(op_Const, gen_Const);
+ be_set_transform_function(op_Div, gen_Div);
be_set_transform_function(op_Eor, gen_Eor);
be_set_transform_function(op_Jmp, gen_Jmp);
be_set_transform_function(op_Load, gen_Load);
be_set_transform_function(op_Not, gen_Not);
be_set_transform_function(op_Or, gen_Or);
be_set_transform_function(op_Phi, gen_Phi);
- be_set_transform_function(op_Quot, gen_Quot);
be_set_transform_function(op_Shl, gen_Shl);
be_set_transform_function(op_Shr, gen_Shr);
be_set_transform_function(op_Store, gen_Store);
return new_bd_arm_Mul(dbg, block, new_op1, new_op2);
}
-static ir_node *gen_Quot(ir_node *node)
+static ir_node *gen_Div(ir_node *node)
{
ir_node *block = be_transform_node(get_nodes_block(node));
- ir_node *op1 = get_Quot_left(node);
+ ir_node *op1 = get_Div_left(node);
ir_node *new_op1 = be_transform_node(op1);
- ir_node *op2 = get_Quot_right(node);
+ ir_node *op2 = get_Div_right(node);
ir_node *new_op2 = be_transform_node(op2);
- ir_mode *mode = get_irn_mode(node);
+ ir_mode *mode = get_Div_resmode(node);
dbg_info *dbg = get_irn_dbg_info(node);
assert(mode != mode_E && "IEEE Extended FP not supported");
+ /* integer division should be replaced by builtin call */
+ assert(mode_is_float(mode));
if (USE_FPA(isa)) {
return new_bd_arm_Dvf(dbg, block, new_op1, new_op2, mode);
panic("Unsupported Proj from CopyB");
}
-static ir_node *gen_Proj_Quot(ir_node *node)
+static ir_node *gen_Proj_Div(ir_node *node)
{
ir_node *pred = get_Proj_pred(node);
ir_node *new_pred = be_transform_node(pred);
long proj = get_Proj_proj(node);
switch (proj) {
- case pn_Quot_M:
- if (is_arm_Dvf(new_pred)) {
- return new_rd_Proj(dbgi, new_pred, mode_M, pn_arm_Dvf_M);
- }
- break;
- case pn_Quot_res:
- if (is_arm_Dvf(new_pred)) {
- return new_rd_Proj(dbgi, new_pred, mode, pn_arm_Dvf_res);
- }
- break;
+ case pn_Div_M:
+ return new_rd_Proj(dbgi, new_pred, mode_M, pn_arm_Dvf_M);
+ case pn_Div_res:
+ return new_rd_Proj(dbgi, new_pred, mode, pn_arm_Dvf_res);
default:
break;
}
- panic("Unsupported Proj from Quot");
+ panic("Unsupported Proj from Div");
}
/**
return gen_Proj_Call(node);
case iro_CopyB:
return gen_Proj_CopyB(node);
- case iro_Quot:
- return gen_Proj_Quot(node);
+ case iro_Div:
+ return gen_Proj_Div(node);
case iro_Cmp:
return gen_Proj_Cmp(node);
case iro_Start:
be_set_transform_function(op_Const, gen_Const);
be_set_transform_function(op_Conv, gen_Conv);
be_set_transform_function(op_CopyB, gen_CopyB);
+ be_set_transform_function(op_Div, gen_Div);
be_set_transform_function(op_Eor, gen_Eor);
be_set_transform_function(op_Jmp, gen_Jmp);
be_set_transform_function(op_Load, gen_Load);
be_set_transform_function(op_Or, gen_Or);
be_set_transform_function(op_Phi, gen_Phi);
be_set_transform_function(op_Proj, gen_Proj);
- be_set_transform_function(op_Quot, gen_Quot);
be_set_transform_function(op_Return, gen_Return);
be_set_transform_function(op_Rotl, gen_Rotl);
be_set_transform_function(op_Sel, gen_Sel);
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");
}
*/
static ir_node *gen_Div(ir_node *node)
{
- return create_Div(node);
-}
-
-
-/**
- * Creates an ia32 floating Div.
- *
- * @return The created ia32 xDiv node
- */
-static ir_node *gen_Quot(ir_node *node)
-{
- ir_node *op1 = get_Quot_left(node);
- ir_node *op2 = get_Quot_right(node);
+ ir_mode *mode = get_Div_resmode(node);
+ if (mode_is_float(mode)) {
+ ir_node *op1 = get_Div_left(node);
+ ir_node *op2 = get_Div_right(node);
- if (ia32_cg_config.use_sse2) {
- return gen_binop(node, op1, op2, new_bd_ia32_xDiv, match_am);
- } else {
- return gen_binop_x87_float(node, op1, op2, new_bd_ia32_vfdiv);
+ if (ia32_cg_config.use_sse2) {
+ return gen_binop(node, op1, op2, new_bd_ia32_xDiv, match_am);
+ } else {
+ return gen_binop_x87_float(node, op1, op2, new_bd_ia32_vfdiv);
+ }
}
-}
+ return create_Div(node);
+}
/**
* Creates an ia32 Shl.
/**
* Transform and renumber the Projs from a Div or Mod instruction.
*/
-static ir_node *gen_Proj_Div_Mod(ir_node *node)
+static ir_node *gen_Proj_Div(ir_node *node)
{
ir_node *block = be_transform_node(get_nodes_block(node));
ir_node *pred = get_Proj_pred(node);
dbg_info *dbgi = get_irn_dbg_info(node);
long proj = get_Proj_proj(node);
- assert(is_ia32_Div(new_pred) || is_ia32_IDiv(new_pred));
+ assert(pn_ia32_Div_M == pn_ia32_IDiv_M);
+ assert(pn_ia32_Div_div_res == pn_ia32_IDiv_div_res);
- switch (get_irn_opcode(pred)) {
- case iro_Div:
- switch (proj) {
- case pn_Div_M:
+ switch (proj) {
+ case pn_Div_M:
+ if (is_ia32_Div(new_pred) || is_ia32_IDiv(new_pred)) {
return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_Div_M);
- case pn_Div_res:
- return new_rd_Proj(dbgi, new_pred, mode_Iu, pn_ia32_Div_div_res);
- case pn_Div_X_regular:
- return new_rd_Jmp(dbgi, block);
- case pn_Div_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;
+ } else if (is_ia32_xDiv(new_pred)) {
+ return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_xDiv_M);
+ } else if (is_ia32_vfdiv(new_pred)) {
+ return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_vfdiv_M);
+ } else {
+ panic("Div transformed to unexpected thing %+F", new_pred);
}
- break;
- case iro_Mod:
- switch (proj) {
- case pn_Mod_M:
- return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_Div_M);
- case pn_Mod_res:
- return new_rd_Proj(dbgi, new_pred, mode_Iu, pn_ia32_Div_mod_res);
- case pn_Mod_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;
+ case pn_Div_res:
+ if (is_ia32_Div(new_pred) || is_ia32_IDiv(new_pred)) {
+ return new_rd_Proj(dbgi, new_pred, mode_Iu, pn_ia32_Div_div_res);
+ } else if (is_ia32_xDiv(new_pred)) {
+ return new_rd_Proj(dbgi, new_pred, mode_xmm, pn_ia32_xDiv_res);
+ } else if (is_ia32_vfdiv(new_pred)) {
+ return new_rd_Proj(dbgi, new_pred, mode_vfp, pn_ia32_vfdiv_res);
+ } else {
+ panic("Div transformed to unexpected thing %+F", new_pred);
}
- break;
+ case pn_Div_X_regular:
+ return new_rd_Jmp(dbgi, block);
+ case pn_Div_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;
}
- panic("No idea how to transform proj->Div/Mod");
+ panic("No idea how to transform proj->Div");
}
/**
- * Transform and renumber the Projs from a CopyB.
+ * Transform and renumber the Projs from a Div or Mod instruction.
*/
-static ir_node *gen_Proj_CopyB(ir_node *node)
+static ir_node *gen_Proj_Mod(ir_node *node)
{
ir_node *pred = get_Proj_pred(node);
ir_node *new_pred = be_transform_node(pred);
dbg_info *dbgi = get_irn_dbg_info(node);
long proj = get_Proj_proj(node);
+ assert(is_ia32_Div(new_pred) || is_ia32_IDiv(new_pred));
+ assert(pn_ia32_Div_M == pn_ia32_IDiv_M);
+ assert(pn_ia32_Div_mod_res == pn_ia32_IDiv_mod_res);
+
switch (proj) {
- case pn_CopyB_M:
- if (is_ia32_CopyB_i(new_pred)) {
- return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_CopyB_i_M);
- } else if (is_ia32_CopyB(new_pred)) {
- return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_CopyB_M);
- }
- break;
+ case pn_Mod_M:
+ return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_Div_M);
+ case pn_Mod_res:
+ return new_rd_Proj(dbgi, new_pred, mode_Iu, pn_ia32_Div_mod_res);
+ case pn_Mod_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;
}
-
- panic("No idea how to transform proj->CopyB");
+ panic("No idea how to transform proj->Mod");
}
/**
- * Transform and renumber the Projs from a Quot.
+ * Transform and renumber the Projs from a CopyB.
*/
-static ir_node *gen_Proj_Quot(ir_node *node)
+static ir_node *gen_Proj_CopyB(ir_node *node)
{
ir_node *pred = get_Proj_pred(node);
ir_node *new_pred = be_transform_node(pred);
long proj = get_Proj_proj(node);
switch (proj) {
- case pn_Quot_M:
- if (is_ia32_xDiv(new_pred)) {
- return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_xDiv_M);
- } else if (is_ia32_vfdiv(new_pred)) {
- return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_vfdiv_M);
- }
- break;
- case pn_Quot_res:
- if (is_ia32_xDiv(new_pred)) {
- return new_rd_Proj(dbgi, new_pred, mode_xmm, pn_ia32_xDiv_res);
- } else if (is_ia32_vfdiv(new_pred)) {
- return new_rd_Proj(dbgi, new_pred, mode_vfp, pn_ia32_vfdiv_res);
+ case pn_CopyB_M:
+ if (is_ia32_CopyB_i(new_pred)) {
+ return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_CopyB_i_M);
+ } else if (is_ia32_CopyB(new_pred)) {
+ return new_rd_Proj(dbgi, new_pred, mode_M, pn_ia32_CopyB_M);
}
break;
- case pn_Quot_X_regular:
- case pn_Quot_X_except:
default:
break;
}
- panic("No idea how to transform proj->Quot");
+ panic("No idea how to transform proj->CopyB");
}
static ir_node *gen_be_Call(ir_node *node)
case iro_Builtin:
return gen_Proj_Builtin(node);
case iro_Div:
+ return gen_Proj_Div(node);
case iro_Mod:
- return gen_Proj_Div_Mod(node);
+ return gen_Proj_Mod(node);
case iro_CopyB:
return gen_Proj_CopyB(node);
- case iro_Quot:
- return gen_Proj_Quot(node);
case beo_SubSP:
return gen_Proj_be_SubSP(node);
case beo_AddSP:
be_set_transform_function(op_Or, gen_Or);
be_set_transform_function(op_Phi, gen_Phi);
be_set_transform_function(op_Proj, gen_Proj);
- be_set_transform_function(op_Quot, gen_Quot);
be_set_transform_function(op_Rotl, gen_Rotl);
be_set_transform_function(op_Shl, gen_Shl);
be_set_transform_function(op_Shr, gen_Shr);
ir_node *right = get_Div_right(node);
ir_node *res;
- assert(!mode_is_float(mode));
+ if (mode_is_float(mode)) {
+ return gen_helper_binfpop(node, mode, new_bd_sparc_fdiv_s,
+ new_bd_sparc_fdiv_d, new_bd_sparc_fdiv_q);
+ }
+
if (mode_is_signed(mode)) {
ir_node *left_high = gen_sign_extension_value(left);
return res;
}
-static ir_node *gen_Quot(ir_node *node)
-{
- ir_mode *mode = get_Quot_resmode(node);
- assert(mode_is_float(mode));
- return gen_helper_binfpop(node, mode, new_bd_sparc_fdiv_s,
- new_bd_sparc_fdiv_d, new_bd_sparc_fdiv_q);
-}
-
#if 0
static ir_node *gen_Abs(ir_node *node)
{
assert(is_sparc_SDiv(new_pred) || is_sparc_UDiv(new_pred));
assert((int)pn_sparc_SDiv_res == (int)pn_sparc_UDiv_res);
assert((int)pn_sparc_SDiv_M == (int)pn_sparc_UDiv_M);
+ assert((int)pn_sparc_SDiv_res == (int)pn_sparc_fdiv_res);
+ assert((int)pn_sparc_SDiv_M == (int)pn_sparc_fdiv_M);
switch (pn) {
case pn_Div_res:
return new_r_Proj(new_pred, mode_gp, pn_sparc_SDiv_res);
panic("Unsupported Proj from Div");
}
-static ir_node *gen_Proj_Quot(ir_node *node)
-{
- ir_node *pred = get_Proj_pred(node);
- ir_node *new_pred = be_transform_node(pred);
- long pn = get_Proj_proj(node);
-
- assert(is_sparc_fdiv(new_pred));
- switch (pn) {
- case pn_Quot_res:
- return new_r_Proj(new_pred, mode_gp, pn_sparc_fdiv_res);
- case pn_Quot_M:
- return new_r_Proj(new_pred, mode_gp, pn_sparc_fdiv_M);
- default:
- break;
- }
- panic("Unsupported Proj from Quot");
-}
-
static ir_node *get_frame_base(void)
{
const arch_register_t *reg = cconv->omit_fp ? sp_reg : fp_reg;
return be_duplicate_node(node);
case iro_Div:
return gen_Proj_Div(node);
- case iro_Quot:
- return gen_Proj_Quot(node);
case iro_Start:
return gen_Proj_Start(node);
case iro_Proj: {
be_set_transform_function(op_Or, gen_Or);
be_set_transform_function(op_Phi, gen_Phi);
be_set_transform_function(op_Proj, gen_Proj);
- be_set_transform_function(op_Quot, gen_Quot);
be_set_transform_function(op_Return, gen_Return);
be_set_transform_function(op_Sel, gen_Sel);
be_set_transform_function(op_Shl, gen_Shl);
#undef X
};
-/** the lookup table for Proj(Quot) names */
-static const pns_lookup_t quot_lut[] = {
-#define X(a) { pn_Quot_##a, #a }
- X(M),
- X(X_regular),
- X(X_except),
- X(res)
-#undef X
-};
-
/** the lookup table for Proj(Div) names */
static const pns_lookup_t div_lut[] = {
#define X(a) { pn_Div_##a, #a }
{ iro_Start, E(start_lut) },
{ iro_Cond, E(cond_lut) },
{ iro_Call, E(call_lut) },
- { iro_Quot, E(quot_lut) },
{ iro_Div, E(div_lut) },
{ iro_Mod, E(mod_lut) },
{ iro_Load, E(load_lut) },
switch (get_irn_opcode(node)) {
case iro_Call :
- case iro_Quot :
case iro_Div :
case iro_Mod :
case iro_Load :
return computed_value_Cmp_Confirm(cmp, left, right, pn_cmp);
} /* computed_value_Proj_Cmp */
-/**
- * Return the value of a floating point Quot.
- */
-static ir_tarval *do_computed_value_Quot(const ir_node *a, const ir_node *b)
-{
- ir_tarval *ta = value_of(a);
- ir_tarval *tb = value_of(b);
-
- /* cannot optimize 0 / b = 0 because of NaN */
- if (ta != tarval_bad && tb != tarval_bad)
- return tarval_quo(ta, tb);
- return tarval_bad;
-} /* do_computed_value_Quot */
-
/**
* Calculate the value of an integer Div of two nodes.
* Special case: 0 / b
return tarval_bad;
} /* computed_value_Proj_Mod */
-/**
- * Return the value of a Proj(Quot).
- */
-static ir_tarval *computed_value_Proj_Quot(const ir_node *n)
-{
- long proj_nr = get_Proj_proj(n);
-
- if (proj_nr == pn_Quot_res) {
- const ir_node *a = get_Proj_pred(n);
- return do_computed_value_Quot(get_Quot_left(a), get_Quot_right(a));
- }
- return tarval_bad;
-} /* computed_value_Proj_Quot */
-
/**
* Return the value of a Proj.
*/
CASE_PROJ(Cmp);
CASE_PROJ(Div);
CASE_PROJ(Mod);
- CASE_PROJ(Quot);
CASE(Proj);
default:
/* leave NULL */
return proj;
} /* equivalent_node_Proj_Div */
-/**
- * Optimize a / 1.0 = a.
- */
-static ir_node *equivalent_node_Proj_Quot(ir_node *proj)
-{
- ir_node *oldn = proj;
- ir_node *quot = get_Proj_pred(proj);
- ir_node *b = get_Quot_right(quot);
- ir_tarval *tb = value_of(b);
-
- /* Div is not commutative. */
- if (tarval_is_one(tb)) { /* Quot(x, 1) == x */
- switch (get_Proj_proj(proj)) {
- case pn_Quot_M:
- proj = get_Quot_mem(quot);
- DBG_OPT_ALGSIM0(oldn, proj, FS_OPT_NEUTRAL_1);
- return proj;
-
- case pn_Quot_res:
- proj = get_Quot_left(quot);
- 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_Quot() */
- return proj;
- }
- }
- return proj;
-} /* equivalent_node_Proj_Quot */
-
/**
* Optimize CopyB(mem, x, x) into a Nop.
*/
CASE(Sync);
CASE_PROJ(Tuple);
CASE_PROJ(Div);
- CASE_PROJ(Quot);
CASE_PROJ(CopyB);
CASE_PROJ(Bound);
CASE_PROJ(Load);
DBG_OPT_ALGSIM0(n, value, FS_OPT_CONST_PHI);
goto make_tuple;
}
- }
- else if (is_Const(a) && is_const_Phi(b)) {
+ } else if (is_Const(a) && is_const_Phi(b)) {
/* check for Div(Const, Phi) */
value = apply_binop_on_phi(b, get_Const_tarval(a), (eval_func) tarval_div, mode, 1);
if (value) {
DBG_OPT_ALGSIM0(n, value, FS_OPT_CONST_PHI);
goto make_tuple;
}
- }
- else if (is_const_Phi(a) && is_const_Phi(b)) {
+ } else if (is_const_Phi(a) && is_const_Phi(b)) {
/* check for Div(Phi, Phi) */
value = apply_binop_on_2_phis(a, b, (eval_func) tarval_div, mode);
if (value) {
value = n;
- if (a == b && value_not_zero(a, &dummy)) {
- ir_graph *irg = get_irn_irg(n);
- /* BEWARE: we can optimize a/a to 1 only if this cannot cause a exception */
- value = new_r_Const(irg, get_mode_one(mode));
- DBG_OPT_CSTEVAL(n, value);
- goto make_tuple;
+ if (mode_is_float(mode)) {
+ /* Optimize x/c to x*(1/c) */
+ if (get_mode_arithmetic(mode) == irma_ieee754) {
+ ir_tarval *tv = value_of(b);
+
+ if (tv != tarval_bad) {
+ int rem = tarval_fp_ops_enabled();
+
+ /*
+ * Floating point constant folding might be disabled here to
+ * prevent rounding.
+ * However, as we check for exact result, doing it is safe.
+ * Switch it on.
+ */
+ tarval_enable_fp_ops(1);
+ tv = tarval_div(get_mode_one(mode), tv);
+ tarval_enable_fp_ops(rem);
+
+ /* Do the transformation if the result is either exact or we are
+ not using strict rules. */
+ if (tv != tarval_bad &&
+ (tarval_ieee754_get_exact() || (get_irg_fp_model(get_irn_irg(n)) & fp_strict_algebraic) == 0)) {
+ ir_node *block = get_nodes_block(n);
+ ir_graph *irg = get_irn_irg(block);
+ ir_node *c = new_r_Const(irg, tv);
+ dbg_info *dbgi = get_irn_dbg_info(n);
+ value = new_rd_Mul(dbgi, block, a, c, mode);
+
+ goto make_tuple;
+ }
+ }
+ }
+
} else {
- if (mode_is_signed(mode) && is_Const(b)) {
- ir_tarval *tv = get_Const_tarval(b);
+ assert(mode_is_int(mode));
+
+ if (a == b && value_not_zero(a, &dummy)) {
+ ir_graph *irg = get_irn_irg(n);
+ /* BEWARE: we can optimize a/a to 1 only if this cannot cause a exception */
+ value = new_r_Const(irg, get_mode_one(mode));
+ DBG_OPT_CSTEVAL(n, value);
+ goto make_tuple;
+ } else {
+ if (mode_is_signed(mode) && is_Const(b)) {
+ ir_tarval *tv = get_Const_tarval(b);
- if (tv == get_mode_minus_one(mode)) {
- /* a / -1 */
- value = new_rd_Minus(get_irn_dbg_info(n), get_nodes_block(n), a, mode);
- DBG_OPT_CSTEVAL(n, value);
- goto make_tuple;
+ if (tv == get_mode_minus_one(mode)) {
+ /* a / -1 */
+ value = new_rd_Minus(get_irn_dbg_info(n), get_nodes_block(n), a, mode);
+ DBG_OPT_CSTEVAL(n, value);
+ goto make_tuple;
+ }
}
+ /* Try architecture dependent optimization */
+ value = arch_dep_replace_div_by_const(n);
}
- /* Try architecture dependent optimization */
- value = arch_dep_replace_div_by_const(n);
}
+
if (value != n) {
ir_node *mem, *blk;
ir_graph *irg;
return n;
} /* transform_node_Mod */
-/**
- * Optimize x / c to x * (1/c)
- */
-static ir_node *transform_node_Quot(ir_node *n)
-{
- ir_mode *mode = get_Quot_resmode(n);
- ir_node *oldn = n;
-
- if (get_mode_arithmetic(mode) == irma_ieee754) {
- ir_node *b = get_Quot_right(n);
- ir_tarval *tv = value_of(b);
-
- if (tv != tarval_bad) {
- int rem = tarval_fp_ops_enabled();
-
- /*
- * Floating point constant folding might be disabled here to
- * prevent rounding.
- * However, as we check for exact result, doing it is safe.
- * Switch it on.
- */
- tarval_enable_fp_ops(1);
- tv = tarval_quo(get_mode_one(mode), tv);
- tarval_enable_fp_ops(rem);
-
- /* Do the transformation if the result is either exact or we are not
- using strict rules. */
- if (tv != tarval_bad &&
- (tarval_ieee754_get_exact() || (get_irg_fp_model(get_irn_irg(n)) & fp_strict_algebraic) == 0)) {
- ir_node *blk = get_nodes_block(n);
- ir_graph *irg = get_irn_irg(blk);
- ir_node *c = new_r_Const(irg, tv);
- ir_node *a = get_Quot_left(n);
- ir_node *m = new_rd_Mul(get_irn_dbg_info(n), blk, a, c, mode);
- ir_node *mem = get_Quot_mem(n);
-
- /* skip a potential Pin */
- mem = skip_Pin(mem);
- turn_into_tuple(n, pn_Quot_max);
- set_Tuple_pred(n, pn_Quot_M, mem);
- set_Tuple_pred(n, pn_Quot_X_regular, new_r_Jmp(blk));
- set_Tuple_pred(n, pn_Quot_X_except, get_irg_bad(irg));
- set_Tuple_pred(n, pn_Quot_res, m);
- DBG_OPT_ALGSIM1(oldn, a, b, m, FS_OPT_FP_INV_MUL);
- }
- }
- }
- return n;
-} /* transform_node_Quot */
-
/**
* Optimize -a CMP -b into b CMP a.
* This works only for for modes where unary Minus
CASE(Mul);
CASE_PROJ_EX(Div);
CASE_PROJ_EX(Mod);
- CASE(Quot);
CASE_PROJ_EX(Cmp);
CASE_PROJ_EX(Cond);
CASE(And);
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_Div_Mod(a, b);
-} /* node_cmp_attr_Quot */
-
/** Compares the attributes of two Confirm nodes. */
static int node_cmp_attr_Confirm(ir_node *a, ir_node *b)
{
CASE(ASM);
CASE(Div);
CASE(Mod);
- CASE(Quot);
CASE(Bound);
CASE(Builtin);
CASE(Dummy);
char strict; /**< If set, this is a strict Conv that cannot be removed. */
} conv_attr;
-/** Div/Mod/Quot attribute. */
+/** Div/Mod attribute. */
typedef struct divmod_attr {
except_attr exc; /**< The exception attribute. MUST be the first one. */
ir_mode *resmode; /**< Result mode for the division. */
return 1;
}
-/**
- * verify a Proj(Quot) node
- */
-static int verify_node_Proj_Quot(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_Quot_M && mode == mode_M) ||
- (proj == pn_Quot_X_regular && mode == mode_X) ||
- (proj == pn_Quot_X_except && mode == mode_X) ||
- (proj == pn_Quot_res && mode_is_float(mode) && mode == get_Quot_resmode(n))
- ),
- "wrong Proj from Quot", 0,
- show_proj_failure(p);
- );
- if (proj == pn_Quot_X_regular)
- ASSERT_AND_RET(
- get_irn_pinned(n) == op_pin_state_pinned,
- "Regular Proj from unpinned Quot", 0);
- else if (proj == pn_Quot_X_except)
- ASSERT_AND_RET(
- get_irn_pinned(n) == op_pin_state_pinned,
- "Exception Proj from unpinned Quot", 0);
- else if (proj == pn_Quot_M)
- ASSERT_AND_RET(
- get_irn_pinned(n) == op_pin_state_pinned,
- "Memory Proj from unpinned Quot", 0);
- return 1;
-}
-
/**
* verify a Proj(Div) node
*/
(proj == pn_Div_M && mode == mode_M) ||
(proj == pn_Div_X_regular && mode == mode_X) ||
(proj == pn_Div_X_except && mode == mode_X) ||
- (proj == pn_Div_res && mode_is_int(mode) && mode == get_Div_resmode(n))
+ (proj == pn_Div_res && mode == get_Div_resmode(n))
),
"wrong Proj from Div", 0,
show_proj_failure(p);
(proj == pn_Mod_M && mode == mode_M) ||
(proj == pn_Mod_X_regular && mode == mode_X) ||
(proj == pn_Mod_X_except && mode == mode_X) ||
- (proj == pn_Mod_res && mode_is_int(mode) && mode == get_Mod_resmode(n))
+ (proj == pn_Mod_res && mode == get_Mod_resmode(n))
),
"wrong Proj from Mod", 0,
show_proj_failure(p);
return 1;
}
-/**
- * verify a Quot node
- */
-static int verify_node_Quot(ir_node *n, ir_graph *irg)
-{
- ir_mode *mymode = get_irn_mode(n);
- ir_mode *op1mode = get_irn_mode(get_Quot_mem(n));
- ir_mode *op2mode = get_irn_mode(get_Quot_left(n));
- ir_mode *op3mode = get_irn_mode(get_Quot_right(n));
- (void) irg;
-
- ASSERT_AND_RET_DBG(
- /* Quot: BB x M x float x float --> M x X x float */
- op1mode == mode_M && op2mode == op3mode &&
- get_mode_sort(op2mode) == irms_float_number &&
- mymode == mode_T,
- "Quot node",0,
- show_binop_failure(n, "/* Quot: BB x M x float x float --> M x X x float */");
- );
- return 1;
-}
-
/**
* verify a Div node
*/
/* Div: BB x M x int x int --> M x X x int */
op1mode == mode_M &&
op2mode == op3mode &&
- mode_is_int(op2mode) &&
+ mode_is_data(op2mode) &&
mymode == mode_T,
"Div node", 0
);
CASE(Minus);
CASE(Mul);
CASE(Mulh);
- CASE(Quot);
CASE(Div);
CASE(Mod);
CASE(And);
CASE(Raise);
CASE(InstOf);
CASE(Call);
- CASE(Quot);
CASE(Div);
CASE(Mod);
CASE(Cmp);
if (irn == NULL) {
ir_mode *mode = get_irn_mode(left);
- ir_node *quot;
+ ir_node *div;
irn = new_r_Const(irg, get_mode_one(mode));
- quot = new_rd_Quot(dbg, block, mem, irn, left, mode, op_pin_state_pinned);
- mem = new_r_Proj(quot, mode_M, pn_Quot_M);
- irn = new_r_Proj(quot, mode, pn_Quot_res);
- reg_jmp = new_r_Proj(quot, mode_X, pn_Quot_X_regular);
- exc_jmp = new_r_Proj(quot, mode_X, pn_Quot_X_except);
+ div = new_rd_Div(dbg, block, mem, irn, left, mode, op_pin_state_pinned);
+ mem = new_r_Proj(div, mode_M, pn_Div_M);
+ irn = new_r_Proj(div, mode, pn_Div_res);
+ reg_jmp = new_r_Proj(div, mode_X, pn_Div_X_regular);
+ exc_jmp = new_r_Proj(div, mode_X, pn_Div_X_except);
}
DBG_OPT_ALGSIM0(call, irn, FS_OPT_RTS_POW);
replace_call(irn, call, mem, reg_jmp, exc_jmp);
{
switch (get_irn_opcode(node)) {
case iro_Load: return get_Load_mode(node);
- case iro_Quot: return get_Quot_resmode(node);
case iro_Div: return get_Div_resmode(node);
case iro_Mod: return get_Mod_resmode(node);
default: return NULL;
} /* update_Call_memop */
/**
- * Update a memop for a Div/Mod/Quot.
+ * Update a memop for a Div/Mod.
*
* @param m the memop
*/
/* we can those to find the memory edge */
break;
case iro_Div:
- case iro_Quot:
case iro_Mod:
update_DivOp_memop(op);
break;
/** The Div by Const node. */
static ir_op _op_ModC;
-/** The Quot by Const node. */
-static ir_op _op_QuotC;
-
/** The memory Proj node. */
static ir_op _op_ProjM;
op = status->op_ModC ? status->op_ModC : 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 */
- op = status->op_QuotC ? status->op_QuotC : op;
- } /* if */
- break;
case iro_Sel:
if (is_Sel(get_Sel_ptr(node))) {
/* special case, a Sel of a Sel, count on extra counter */
_op_ModC.code = --num;
_op_ModC.name = new_id_from_chars(X("ModC"));
- _op_QuotC.code = --num;
- _op_QuotC.name = new_id_from_chars(X("QuotC"));
-
status->op_Phi0 = &_op_Phi0;
status->op_PhiM = &_op_PhiM;
status->op_ProjM = &_op_ProjM;
status->op_MulC = &_op_MulC;
status->op_DivC = &_op_DivC;
status->op_ModC = &_op_ModC;
- status->op_QuotC = &_op_QuotC;
} else {
status->op_Phi0 = NULL;
status->op_PhiM = NULL;
status->op_MulC = NULL;
status->op_DivC = NULL;
status->op_ModC = NULL;
- status->op_QuotC = NULL;
} /* if */
/* for Florian: count the Sel depth */
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_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)) */
dumper_t *dumper; /**< list of dumper */
}
/*
- * floating point division
- */
-ir_tarval *tarval_quo(ir_tarval *a, ir_tarval *b)
-{
- assert((a->mode == b->mode) && mode_is_float(a->mode));
-
- carry_flag = -1;
-
- if (no_float)
- return tarval_bad;
-
- if (get_mode_n_vector_elems(a->mode) > 1) {
- /* vector arithmetic not implemented yet */
- return tarval_bad;
- }
-
- fc_div((const fp_value*) a->value, (const fp_value*) b->value, NULL);
- return get_tarval_overflow(fc_get_buffer(), fc_get_buffer_length(), a->mode);
-}
-
-/*
- * integer division
+ * division
* overflow is impossible, but look out for division by zero
*/
ir_tarval *tarval_div(ir_tarval *a, ir_tarval *b)
{
- assert((a->mode == b->mode) && mode_is_int(a->mode));
+ ir_mode *mode = a->mode;
+ assert(mode == b->mode);
carry_flag = -1;
- if (get_mode_n_vector_elems(a->mode) > 1) {
+ if (get_mode_n_vector_elems(mode) > 1) {
/* vector arithmetic not implemented yet */
return tarval_bad;
}
- /* x/0 error */
- if (b == get_mode_null(b->mode)) return tarval_bad;
- /* modes of a,b are equal */
- sc_div(a->value, b->value, NULL);
- return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
+ if (mode_is_int(mode)) {
+ /* x/0 error */
+ if (b == get_mode_null(mode))
+ return tarval_bad;
+
+ /* modes of a,b are equal */
+ sc_div(a->value, b->value, NULL);
+ return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
+ } else {
+ assert(mode_is_float(mode));
+ fc_div((const fp_value*) a->value, (const fp_value*) b->value, NULL);
+ return get_tarval_overflow(fc_get_buffer(), fc_get_buffer_length(), mode);
+ }
}
/*
pinned_init = "op_pin_state_pinned"
class Div(Op):
- """returns the quotient of its 2 operands, integer version"""
+ """returns the quotient of its 2 operands"""
ins = [
("mem", "memory dependency"),
("left", "first operand"),
]
attr_struct = "proj_attr"
-class Quot(Op):
- """returns the quotient of its 2 operands, floatingpoint version"""
- 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", "result of computation", "pn_Generic_other"),
- ]
- 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 Raise(Op):
"""Raises an exception. Unconditional change of control flow. Writes an
explicit Except variable to memory to pass it to the exception handler.