- BugFix of the last fix ...
[libfirm] / ir / ir / irarch.c
index e6d3aba..ada45d6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
+ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
  *
  * This file is part of libFirm.
  *
@@ -70,47 +70,15 @@ static const ir_settings_arch_dep_t *params = NULL;
 /** The bit mask, which optimizations to apply. */
 static arch_dep_opts_t opts;
 
-/* we need this new pseudo op */
-static ir_op *op_Mulh = NULL;
-
-/**
- * construct a Mulh: Mulh(a,b) = (a * b) >> w, w is the with in bits of a, b
- */
-static ir_node *
-new_rd_Mulh (dbg_info *db, ir_graph *irg, ir_node *block,
-       ir_node *op1, ir_node *op2, ir_mode *mode) {
-       ir_node *in[2];
-       ir_node *res;
-
-       in[0] = op1;
-       in[1] = op2;
-       res = new_ir_node(db, irg, block, op_Mulh, mode, 2, in);
-       res = optimize_node(res);
-       IRN_VRFY_IRG(res, irg);
-       return res;
-}
-
-ir_op *get_op_Mulh(void)  { return op_Mulh; }
-
 void arch_dep_init(arch_dep_params_factory_t factory) {
        opts = arch_dep_none;
 
        if (factory != NULL)
                params = factory();
-
-       if (! op_Mulh) {
-               int mulh_opc = get_next_ir_opcode();
-
-               /* create the Mulh operation */
-               op_Mulh = new_ir_op(mulh_opc, "Mulh",  op_pin_state_floats, irop_flag_commutative, oparity_binary, 0, 0, NULL);
-       }
 }
 
 void arch_dep_set_opts(arch_dep_opts_t the_opts) {
        opts = the_opts;
-
-       if (opts & arch_dep_mul_to_shift)
-               set_opt_arch_dep_running(1);
 }
 
 /** check, whether a mode allows a Mulh instruction. */
@@ -261,8 +229,8 @@ static unsigned char *value_to_condensed(mul_env *env, tarval *tv, int *pr) {
  * Calculate the gain when using the generalized complementary technique
  */
 static int calculate_gain(unsigned char *R, int r) {
-       int max_gain = -1;
-       int idx, i;
+       int max_gain = 0;
+       int idx = -1, i;
        int gain;
 
        /* the gain for r == 1 */
@@ -276,9 +244,7 @@ static int calculate_gain(unsigned char *R, int r) {
                        idx = i;
                }
        }
-       if (max_gain > 0)
-               return idx;
-       return -1;
+       return idx;
 }
 
 /**
@@ -358,11 +324,16 @@ static instruction *decompose_simple_cases(mul_env *env, unsigned char *R, int r
                assert(r == 2);
 
                ins = env->root;
+               if (R[1] <= env->max_S) {
+                       ins = emit_LEA(env, ins, ins, R[1]);
+                       if (R[0] != 0) {
+                               ins = emit_SHIFT(env, ins, R[0]);
+                       }
+                       return ins;
+               }
                if (R[0] != 0) {
                        ins = emit_SHIFT(env, ins, R[0]);
                }
-               if (R[1] <= env->max_S)
-                       return emit_LEA(env, ins, ins, R[1]);
 
                ins2 = emit_SHIFT(env, env->root, R[0] + R[1]);
                return emit_LEA(env, ins, ins2, 0);
@@ -599,30 +570,34 @@ ir_node *arch_dep_replace_mul_with_shifts(ir_node *irn) {
        if (params == NULL || (opts & arch_dep_mul_to_shift) == 0)
                return irn;
 
-       if (is_Mul(irn) && mode_is_int(mode)) {
-               ir_node *left    = get_binop_left(irn);
-               ir_node *right   = get_binop_right(irn);
-               tarval *tv       = NULL;
-               ir_node *operand = NULL;
-
-               /* Look, if one operand is a constant. */
-               if (is_Const(left)) {
-                       tv = get_Const_tarval(left);
-                       operand = right;
-               } else if (is_Const(right)) {
-                       tv = get_Const_tarval(right);
-                       operand = left;
-               }
+       set_arch_dep_running(1);
+       {
+               if (is_Mul(irn) && mode_is_int(mode)) {
+                       ir_node *left    = get_binop_left(irn);
+                       ir_node *right   = get_binop_right(irn);
+                       tarval *tv       = NULL;
+                       ir_node *operand = NULL;
+
+                       /* Look, if one operand is a constant. */
+                       if (is_Const(left)) {
+                               tv = get_Const_tarval(left);
+                               operand = right;
+                       } else if (is_Const(right)) {
+                               tv = get_Const_tarval(right);
+                               operand = left;
+                       }
 
-               if (tv != NULL) {
-                       res = do_decomposition(irn, operand, tv);
+                       if (tv != NULL) {
+                               res = do_decomposition(irn, operand, tv);
 
-                       if (res != irn) {
-                               hook_arch_dep_replace_mul_with_shifts(irn);
-                               exchange(irn, res);
+                               if (res != irn) {
+                                       hook_arch_dep_replace_mul_with_shifts(irn);
+                                       exchange(irn, res);
+                               }
                        }
                }
        }
+       //set_arch_dep_running(0);
 
        return res;
 }
@@ -926,7 +901,7 @@ ir_node *arch_dep_replace_div_by_const(ir_node *irn) {
                tv = get_Const_tarval(c);
 
                /* check for division by zero */
-               if (classify_tarval(tv) == TV_CLASSIFY_NULL)
+               if (tarval_is_null(tv))
                        return irn;
 
                left  = get_Div_left(irn);
@@ -955,15 +930,20 @@ ir_node *arch_dep_replace_div_by_const(ir_node *irn) {
                                ir_node *k_node;
                                ir_node *curr = left;
 
-                               if (k != 1) {
-                                       k_node = new_r_Const_long(current_ir_graph, block, mode_Iu, k - 1);
-                                       curr   = new_rd_Shrs(dbg, current_ir_graph, block, left, k_node, mode);
-                               }
+                               /* create the correction code for signed values only if there might be a remainder */
+                               if (! is_Div_remainderless(irn)) {
+                                       if (k != 1) {
+                                               k_node = new_r_Const_long(current_ir_graph, block, mode_Iu, k - 1);
+                                               curr   = new_rd_Shrs(dbg, current_ir_graph, block, left, k_node, mode);
+                                       }
 
-                               k_node = new_r_Const_long(current_ir_graph, block, mode_Iu, bits - k);
-                               curr   = new_rd_Shr(dbg, current_ir_graph, block, curr, k_node, mode);
+                                       k_node = new_r_Const_long(current_ir_graph, block, mode_Iu, bits - k);
+                                       curr   = new_rd_Shr(dbg, current_ir_graph, block, curr, k_node, mode);
 
-                               curr   = new_rd_Add(dbg, current_ir_graph, block, left, curr, mode);
+                                       curr   = new_rd_Add(dbg, current_ir_graph, block, left, curr, mode);
+                               } else {
+                                       k_node = left;
+                               }
 
                                k_node = new_r_Const_long(current_ir_graph, block, mode_Iu, k);
                                res    = new_rd_Shrs(dbg, current_ir_graph, block, curr, k_node, mode);
@@ -1017,7 +997,7 @@ ir_node *arch_dep_replace_mod_by_const(ir_node *irn) {
                tv = get_Const_tarval(c);
 
                /* check for division by zero */
-               if (classify_tarval(tv) == TV_CLASSIFY_NULL)
+               if (tarval_is_null(tv))
                        return irn;
 
                left  = get_Mod_left(irn);
@@ -1111,7 +1091,7 @@ void arch_dep_replace_divmod_by_const(ir_node **div, ir_node **mod, ir_node *irn
                tv = get_Const_tarval(c);
 
                /* check for division by zero */
-               if (classify_tarval(tv) == TV_CLASSIFY_NULL)
+               if (tarval_is_null(tv))
                        return;
 
                left  = get_DivMod_left(irn);