Commit a0fe3cf1 authored by Michael Beck's avatar Michael Beck
Browse files

Amendment to r28345-r28346.

Check for mode int on several places where Div nodes are handled:
- fixed arch_dep_replace_div_by_const() (works for int only)
- fixed constant folding for Div nodes (different for float and int)
- fixed transform_node_Div() (some code pathes allowed only for int)
- fixed comment and one missing check in Div mode verifycation

[r28366]
parent 3bc87291
/*
* Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
* Copyright (C) 1995-2011 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
......@@ -925,6 +925,11 @@ ir_node *arch_dep_replace_div_by_const(ir_node *irn)
left = get_Div_left(irn);
mode = get_irn_mode(left);
/* can only handle integer Div's */
if (!mode_is_int(mode))
return irn;
block = get_irn_n(irn, -1);
dbg = get_irn_dbg_info(irn);
......
......@@ -544,10 +544,10 @@ static ir_tarval *computed_value_Proj_Cmp(const ir_node *n)
} /* computed_value_Proj_Cmp */
/**
* Calculate the value of an integer Div of two nodes.
* Calculate the value of an integer Div.
* Special case: 0 / b
*/
static ir_tarval *do_computed_value_Div(const ir_node *a, const ir_node *b)
static ir_tarval *do_computed_value_integer_Div(const ir_node *a, const ir_node *b)
{
ir_tarval *ta = value_of(a);
ir_tarval *tb;
......@@ -560,7 +560,21 @@ static ir_tarval *do_computed_value_Div(const ir_node *a, const ir_node *b)
if (ta != tarval_bad && tb != tarval_bad)
return tarval_div(ta, tb);
return tarval_bad;
} /* do_computed_value_Div */
} /* do_computed_value_integer_Div */
/**
* Return the value of a floating point Div.
*/
static ir_tarval *do_computed_value_float_Div(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_float_Div */
/**
* Calculate the value of an integer Mod of two nodes.
......@@ -587,8 +601,12 @@ static ir_tarval *computed_value_Proj_Div(const ir_node *n)
long proj_nr = get_Proj_proj(n);
if (proj_nr == pn_Div_res) {
const ir_node *a = get_Proj_pred(n);
return do_computed_value_Div(get_Div_left(a), get_Div_right(a));
const ir_node *div = get_Proj_pred(n);
const ir_mode *mode = get_irn_mode(get_Div_resmode(div));
if (mode_is_int(mode))
return do_computed_value_integer_Div(get_Div_left(div), get_Div_right(div));
else if (mode_is_float(mode))
return do_computed_value_float_Div(get_Div_left(div), get_Div_right(div));
}
return tarval_bad;
} /* computed_value_Proj_Div */
......@@ -601,8 +619,8 @@ static ir_tarval *computed_value_Proj_Mod(const ir_node *n)
long proj_nr = get_Proj_proj(n);
if (proj_nr == pn_Mod_res) {
const ir_node *a = get_Proj_pred(n);
return do_computed_value_Mod(get_Mod_left(a), get_Mod_right(a));
const ir_node *mod = get_Proj_pred(n);
return do_computed_value_Mod(get_Mod_left(mod), get_Mod_right(mod));
}
return tarval_bad;
} /* computed_value_Proj_Mod */
......@@ -2791,35 +2809,56 @@ static ir_node *transform_node_Div(ir_node *n)
ir_mode *mode = get_Div_resmode(n);
ir_node *a = get_Div_left(n);
ir_node *b = get_Div_right(n);
ir_node *value;
ir_node *value = n;
const ir_node *dummy;
if (is_Const(b) && is_const_Phi(a)) {
/* check for Div(Phi, Const) */
value = apply_binop_on_phi(a, get_Const_tarval(b), (eval_func) tarval_div, mode, 0);
if (value) {
DBG_OPT_ALGSIM0(n, value, FS_OPT_CONST_PHI);
goto make_tuple;
}
} 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;
if (mode_is_int(mode)) {
if (is_Const(b) && is_const_Phi(a)) {
/* check for Div(Phi, Const) */
value = apply_binop_on_phi(a, get_Const_tarval(b), (eval_func) tarval_div, mode, 0);
if (value) {
DBG_OPT_ALGSIM0(n, value, FS_OPT_CONST_PHI);
goto make_tuple;
}
} 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)) {
/* check for Div(Phi, Phi) */
value = apply_binop_on_2_phis(a, b, (eval_func) tarval_div, mode);
if (value) {
DBG_OPT_ALGSIM0(n, value, FS_OPT_CONST_PHI);
goto make_tuple;
}
}
} 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) {
DBG_OPT_ALGSIM0(n, value, FS_OPT_CONST_PHI);
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);
value = n;
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);
}
} else {
assert(mode_is_float(mode));
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);
......@@ -2851,33 +2890,8 @@ static ir_node *transform_node_Div(ir_node *n)
}
}
}
} else {
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;
}
}
/* Try architecture dependent optimization */
value = arch_dep_replace_div_by_const(n);
}
}
if (value != n) {
ir_node *mem, *blk;
ir_graph *irg;
......
/*
* Copyright (C) 1995-2010 University of Karlsruhe. All right reserved.
* Copyright (C) 1995-2011 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
......@@ -445,7 +445,7 @@ static int verify_node_Proj_Div(ir_node *n, ir_node *p)
(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 == get_Div_resmode(n))
(proj == pn_Div_res && mode_is_data(mode) && mode == get_Div_resmode(n))
),
"wrong Proj from Div", 0,
show_proj_failure(p);
......@@ -1254,7 +1254,7 @@ static int verify_node_Div(ir_node *n, ir_graph *irg)
(void) irg;
ASSERT_AND_RET(
/* Div: BB x M x int x int --> M x X x int */
/* Div: BB x M x data x data --> M x X x data */
op1mode == mode_M &&
op2mode == op3mode &&
mode_is_data(op2mode) &&
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment