return tarval_bad;
}
-/**
- * Return the value of a Carry.
- * Special : a op 0, 0 op b
- */
-static ir_tarval *computed_value_Carry(const ir_node *n)
-{
- ir_node *a = get_binop_left(n);
- ir_node *b = get_binop_right(n);
- ir_mode *m = get_irn_mode(n);
- ir_tarval *ta = value_of(a);
- ir_tarval *tb = value_of(b);
-
- if ((ta != tarval_bad) && (tb != tarval_bad)) {
- tarval_add(ta, tb);
- return tarval_carry() ? get_mode_one(m) : get_mode_null(m);
- } else {
- if (tarval_is_null(ta) || tarval_is_null(tb))
- return get_mode_null(m);
- }
- return tarval_bad;
-}
-
-/**
- * Return the value of a Borrow.
- * Special : a op 0
- */
-static ir_tarval *computed_value_Borrow(const ir_node *n)
-{
- ir_node *a = get_binop_left(n);
- ir_node *b = get_binop_right(n);
- ir_mode *m = get_irn_mode(n);
- ir_tarval *ta = value_of(a);
- ir_tarval *tb = value_of(b);
-
- if ((ta != tarval_bad) && (tb != tarval_bad)) {
- return tarval_cmp(ta, tb) == ir_relation_less ? get_mode_one(m) : get_mode_null(m);
- } else if (tarval_is_null(ta)) {
- return get_mode_null(m);
- }
- return tarval_bad;
-}
-
/**
* Return the value of an unary Minus.
*/
return proj;
}
-/**
- * Optimize Bounds(idx, idx, upper) into idx.
- */
-static ir_node *equivalent_node_Proj_Bound(ir_node *proj)
-{
- ir_node *oldn = proj;
- ir_node *bound = get_Proj_pred(proj);
- ir_node *idx = get_Bound_index(bound);
- ir_node *pred = skip_Proj(idx);
- int ret_tuple = 0;
-
- if (idx == get_Bound_lower(bound))
- ret_tuple = 1;
- else if (is_Bound(pred)) {
- /*
- * idx was Bounds checked previously, it is still valid if
- * lower <= pred_lower && pred_upper <= upper.
- */
- ir_node *lower = get_Bound_lower(bound);
- ir_node *upper = get_Bound_upper(bound);
- if (get_Bound_lower(pred) == lower &&
- get_Bound_upper(pred) == upper) {
- /*
- * One could expect that we simply return the previous
- * Bound here. However, this would be wrong, as we could
- * add an exception Proj to a new location then.
- * So, we must turn in into a tuple.
- */
- ret_tuple = 1;
- }
- }
- if (ret_tuple) {
- /* Turn Bound into a tuple (mem, jmp, bad, idx) */
- switch (get_Proj_proj(proj)) {
- case pn_Bound_M:
- DBG_OPT_EXC_REM(proj);
- proj = get_Bound_mem(bound);
- break;
- case pn_Bound_res:
- proj = idx;
- DBG_OPT_ALGSIM0(oldn, proj, FS_OPT_NOP);
- break;
- default:
- /* cannot optimize pn_Bound_X_regular, handled in transform ... */
- break;
- }
- }
- return proj;
-}
-
/**
* Does all optimizations on nodes that must be done on its Projs
* because of creating new nodes.
return n;
}
- irg = get_irn_irg(n);
block = get_nodes_block(n);
dbg_bitop = get_irn_dbg_info(n);
dbg_shift = get_irn_dbg_info(left);
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. */
/* skip a potential Pin */
mem = skip_Pin(mem);
- turn_into_tuple(n, pn_Div_max+1);
- set_Tuple_pred(n, pn_Div_M, mem);
- set_Tuple_pred(n, pn_Div_X_regular, new_r_Jmp(blk));
- set_Tuple_pred(n, pn_Div_X_except, new_r_Bad(irg, mode_X));
- set_Tuple_pred(n, pn_Div_res, value);
+ ir_node *const in[] = {
+ [pn_Div_M] = mem,
+ [pn_Div_res] = value,
+ [pn_Div_X_regular] = new_r_Jmp(blk),
+ [pn_Div_X_except] = new_r_Bad(irg, mode_X),
+ };
+ turn_into_tuple(n, ARRAY_SIZE(in), in);
}
return n;
}
/* skip a potential Pin */
mem = skip_Pin(mem);
- turn_into_tuple(n, pn_Mod_max+1);
- set_Tuple_pred(n, pn_Mod_M, mem);
- set_Tuple_pred(n, pn_Mod_X_regular, new_r_Jmp(blk));
- set_Tuple_pred(n, pn_Mod_X_except, new_r_Bad(irg, mode_X));
- set_Tuple_pred(n, pn_Mod_res, value);
+ ir_node *const in[] = {
+ [pn_Mod_M] = mem,
+ [pn_Mod_res] = value,
+ [pn_Mod_X_regular] = new_r_Jmp(blk),
+ [pn_Mod_X_except] = new_r_Bad(irg, mode_X),
+ };
+ turn_into_tuple(n, ARRAY_SIZE(in), in);
}
return n;
}
ir_node *a = get_Cond_selector(n);
ir_graph *irg = get_irn_irg(n);
ir_tarval *ta;
- ir_node *jmp;
/* we need block info which is not available in floating irgs */
if (get_irg_pinned(irg) == op_pin_state_floats)
if (ta != tarval_bad) {
/* It's branching on a boolean constant.
Replace it by a tuple (Bad, Jmp) or (Jmp, Bad) */
- ir_node *blk = get_nodes_block(n);
- jmp = new_r_Jmp(blk);
- turn_into_tuple(n, pn_Cond_max+1);
- if (ta == tarval_b_true) {
- set_Tuple_pred(n, pn_Cond_false, new_r_Bad(irg, mode_X));
- set_Tuple_pred(n, pn_Cond_true, jmp);
- } else {
- set_Tuple_pred(n, pn_Cond_false, jmp);
- set_Tuple_pred(n, pn_Cond_true, new_r_Bad(irg, mode_X));
- }
+ ir_node *const blk = get_nodes_block(n);
+ ir_node *const jmp = new_r_Jmp(blk);
+ ir_node *const bad = new_r_Bad(irg, mode_X);
+ bool const cond = ta == tarval_b_true;
+ ir_node *const in[] = {
+ [pn_Cond_false] = cond ? bad : jmp,
+ [pn_Cond_true] = cond ? jmp : bad,
+ };
+ turn_into_tuple(n, ARRAY_SIZE(in), in);
clear_irg_properties(irg, IR_GRAPH_PROPERTY_NO_UNREACHABLE_CODE);
}
return n;
return proj;
}
-/**
- * Optimize Bounds(idx, idx, upper) into idx.
- */
-static ir_node *transform_node_Proj_Bound(ir_node *proj)
-{
- ir_node *oldn = proj;
- ir_node *bound = get_Proj_pred(proj);
- ir_node *idx = get_Bound_index(bound);
- ir_node *pred = skip_Proj(idx);
- int ret_tuple = 0;
-
- if (idx == get_Bound_lower(bound))
- ret_tuple = 1;
- else if (is_Bound(pred)) {
- /*
- * idx was Bounds checked previously, it is still valid if
- * lower <= pred_lower && pred_upper <= upper.
- */
- ir_node *lower = get_Bound_lower(bound);
- ir_node *upper = get_Bound_upper(bound);
- if (get_Bound_lower(pred) == lower &&
- get_Bound_upper(pred) == upper) {
- /*
- * One could expect that we simply return the previous
- * Bound here. However, this would be wrong, as we could
- * add an exception Proj to a new location then.
- * So, we must turn in into a tuple.
- */
- ret_tuple = 1;
- }
- }
- if (ret_tuple) {
- /* Turn Bound into a tuple (mem, jmp, bad, idx) */
- switch (get_Proj_proj(proj)) {
- case pn_Bound_M:
- DBG_OPT_EXC_REM(proj);
- proj = get_Bound_mem(bound);
- break;
- case pn_Bound_X_except:
- DBG_OPT_EXC_REM(proj);
- proj = new_r_Bad(get_irn_irg(proj), mode_X);
- break;
- case pn_Bound_res:
- proj = idx;
- DBG_OPT_ALGSIM0(oldn, proj, FS_OPT_NOP);
- break;
- case pn_Bound_X_regular:
- DBG_OPT_EXC_REM(proj);
- proj = new_r_Jmp(get_nodes_block(bound));
- break;
- default:
- break;
- }
- }
- return proj;
-}
-
/**
* Does all optimizations on nodes that must be done on its Projs
* because of creating new nodes.
{
register_computed_value_func(op_Add, computed_value_Add);
register_computed_value_func(op_And, computed_value_And);
- register_computed_value_func(op_Borrow, computed_value_Borrow);
- register_computed_value_func(op_Carry, computed_value_Carry);
register_computed_value_func(op_Cmp, computed_value_Cmp);
register_computed_value_func(op_Confirm, computed_value_Confirm);
register_computed_value_func(op_Const, computed_value_Const);
register_equivalent_node_func(op_Shr, equivalent_node_left_zero);
register_equivalent_node_func(op_Shrs, equivalent_node_left_zero);
register_equivalent_node_func(op_Sub, equivalent_node_Sub);
- register_equivalent_node_func_proj(op_Bound, equivalent_node_Proj_Bound);
register_equivalent_node_func_proj(op_CopyB, equivalent_node_Proj_CopyB);
register_equivalent_node_func_proj(op_Div, equivalent_node_Proj_Div);
register_equivalent_node_func_proj(op_Tuple, equivalent_node_Proj_Tuple);
register_transform_node_func(op_Sub, transform_node_Sub);
register_transform_node_func(op_Switch, transform_node_Switch);
register_transform_node_func(op_Sync, transform_node_Sync);
- register_transform_node_func_proj(op_Bound, transform_node_Proj_Bound);
register_transform_node_func_proj(op_CopyB, transform_node_Proj_CopyB);
register_transform_node_func_proj(op_Div, transform_node_Proj_Div);
register_transform_node_func_proj(op_Load, transform_node_Proj_Load);