Amendment to r28345-r28346.
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Fri, 11 Feb 2011 13:19:11 +0000 (13:19 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Fri, 11 Feb 2011 13:19:11 +0000 (13:19 +0000)
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]

ir/ir/irarch.c
ir/ir/iropt.c
ir/ir/irverify.c

index 0df9fdb..27e70ff 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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);
 
index 2eb25b1..ccd1038 100644 (file)
@@ -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;
index 7280dcf..46a679b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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) &&