use tv_t.h instead of tv.h
[libfirm] / ir / ir / irarch.c
index ab66f36..74a4c83 100644 (file)
 #include "ircons_t.h"
 #include "irgmod.h"
 #include "irvrfy.h"
-#include "tv.h"
+#include "tv_t.h"
 #include "dbginfo_t.h"
 #include "iropt_dbg.h"
 #include "irflag_t.h"
-#include "firmstat.h"
+#include "irhooks.h"
 #include "ircons.h"
 #include "irarch.h"
-#include "firmstat.h"
 
 #undef DEB
 
@@ -88,6 +87,14 @@ void arch_dep_set_opts(arch_dep_opts_t the_opts) {
   opts = the_opts;
 }
 
+/* check, wheater a mode allows a Mulh instruction */
+static int allow_Mulh(ir_mode *mode)
+{
+  if (get_mode_size_bits(mode) > params->max_bits_for_mulh)
+    return 0;
+  return (mode_is_signed(mode) && params->allow_mulhs) || (!mode_is_signed(mode) && params->allow_mulhu);
+}
+
 ir_node *arch_dep_replace_mul_with_shifts(ir_node *irn)
 {
   ir_node *res = irn;
@@ -287,12 +294,10 @@ ir_node *arch_dep_replace_mul_with_shifts(ir_node *irn)
               int amount = abs(curr_shift) - 1;
               ir_node *aux = operand;
 
-
               assert(amount >= 0 && "What is a negative shift??");
 
               if(amount != 0) {
-                tarval *shift_amount = new_tarval_from_long(amount, mode_Iu);
-                ir_node *cnst = new_r_Const(current_ir_graph, block, mode_Iu, shift_amount);
+                ir_node *cnst = new_r_Const_long(current_ir_graph, block, mode_Iu, amount);
                 aux = new_r_Shl(current_ir_graph, block, operand, cnst, mode);
               }
 
@@ -330,7 +335,7 @@ ir_node *arch_dep_replace_mul_with_shifts(ir_node *irn)
   }
 
   if (res != irn)
-    stat_arch_dep_replace_mul_with_shifts(irn);
+    hook_arch_dep_replace_mul_with_shifts(irn);
 
   return res;
 }
@@ -396,13 +401,20 @@ static struct ms magic(tarval *d)
   int bits        = get_mode_size_bits(u_mode);
   int p;
   tarval *ad, *anc, *delta, *q1, *r1, *q2, *r2, *t;     /* unsigned */
-  pnc_number d_cmp, M_cmp;
+  pn_Cmp d_cmp, M_cmp;
+
+  tarval *bits_minus_1, *two_bits_1;
 
   struct ms mag;
 
+  tarval_int_overflow_mode_t rem = tarval_get_integer_overflow_mode();
+
+  /* we need overflow mode to work correctly */
+  tarval_set_integer_overflow_mode(TV_OVERFLOW_WRAP);
+
   /* 2^(bits-1) */
-  tarval *bits_minus_1 = new_tarval_from_long(bits - 1, u_mode);
-  tarval *two_bits_1   = SHL(get_mode_one(u_mode), bits_minus_1);
+  bits_minus_1 = new_tarval_from_long(bits - 1, u_mode);
+  two_bits_1   = SHL(get_mode_one(u_mode), bits_minus_1);
 
   ad  = CNV(ABS(d), u_mode);
   t   = ADD(two_bits_1, SHR(CNV(d, u_mode), bits_minus_1));
@@ -418,7 +430,7 @@ static struct ms magic(tarval *d)
     q1 = ADD(q1, q1);                           /* Update q1 = 2^p/|nc| */
     r1 = ADD(r1, r1);                           /* Update r1 = rem(2^p, |nc|) */
 
-    if (CMP(r1, anc) & Ge) {
+    if (CMP(r1, anc) & pn_Cmp_Ge) {
       q1 = ADD(q1, ONE(u_mode));
       r1 = SUB(r1, anc);
     }
@@ -426,17 +438,17 @@ static struct ms magic(tarval *d)
     q2 = ADD(q2, q2);                           /* Update q2 = 2^p/|d| */
     r2 = ADD(r2, r2);                           /* Update r2 = rem(2^p, |d|) */
 
-    if (CMP(r2, ad) & Ge) {
+    if (CMP(r2, ad) & pn_Cmp_Ge) {
       q2 = ADD(q2, ONE(u_mode));
       r2 = SUB(r2, ad);
     }
 
     delta = SUB(ad, r2);
-  } while (CMP(q1, delta) & Lt || (CMP(q1, delta) & Eq && CMP(r1, ZERO(u_mode)) & Eq));
+  } while (CMP(q1, delta) & pn_Cmp_Lt || (CMP(q1, delta) & pn_Cmp_Eq && CMP(r1, ZERO(u_mode)) & pn_Cmp_Eq));
 
   d_cmp = CMP(d, ZERO(mode));
 
-  if (d_cmp & Ge)
+  if (d_cmp & pn_Cmp_Ge)
     mag.M = ADD(CNV(q2, mode), ONE(mode));
   else
     mag.M = SUB(ZERO(mode), ADD(CNV(q2, mode), ONE(mode)));
@@ -446,10 +458,12 @@ static struct ms magic(tarval *d)
   mag.s = p - bits;
 
   /* need an add if d > 0 && M < 0 */
-  mag.need_add = d_cmp & Gt && M_cmp & Lt;
+  mag.need_add = d_cmp & pn_Cmp_Gt && M_cmp & pn_Cmp_Lt;
 
   /* need a sub if d < 0 && M > 0 */
-  mag.need_sub = d_cmp & Lt && M_cmp & Gt;
+  mag.need_sub = d_cmp & pn_Cmp_Lt && M_cmp & pn_Cmp_Gt;
+
+  tarval_set_integer_overflow_mode(rem);
 
   return mag;
 }
@@ -471,12 +485,18 @@ static struct mu magicu(tarval *d)
   int bits        = get_mode_size_bits(mode);
   int p;
   tarval *nc, *delta, *q1, *r1, *q2, *r2;
+  tarval *bits_minus_1, *two_bits_1, *seven_ff;
 
   struct mu magu;
 
-  tarval *bits_minus_1 = new_tarval_from_long(bits - 1, mode);
-  tarval *two_bits_1   = SHL(get_mode_one(mode), bits_minus_1);
-  tarval *seven_ff     = SUB(two_bits_1, ONE(mode));
+  tarval_int_overflow_mode_t rem = tarval_get_integer_overflow_mode();
+
+  /* we need overflow mode to work correctly */
+  tarval_set_integer_overflow_mode(TV_OVERFLOW_WRAP);
+
+  bits_minus_1 = new_tarval_from_long(bits - 1, mode);
+  two_bits_1   = SHL(get_mode_one(mode), bits_minus_1);
+  seven_ff     = SUB(two_bits_1, ONE(mode));
 
   magu.need_add = 0;                            /* initialize the add indicator */
   nc = SUB(NEG(ONE(mode)), MOD(NEG(d), d));
@@ -488,7 +508,7 @@ static struct mu magicu(tarval *d)
 
   do {
     ++p;
-    if (CMP(r1, SUB(nc, r1)) & Ge) {
+    if (CMP(r1, SUB(nc, r1)) & pn_Cmp_Ge) {
       q1 = ADD(ADD(q1, q1), ONE(mode));
       r1 = SUB(ADD(r1, r1), nc);
     }
@@ -497,15 +517,15 @@ static struct mu magicu(tarval *d)
       r1 = ADD(r1, r1);
     }
 
-    if (CMP(ADD(r2, ONE(mode)), SUB(d, r2)) & Ge) {
-      if (CMP(q2, seven_ff) & Ge)
+    if (CMP(ADD(r2, ONE(mode)), SUB(d, r2)) & pn_Cmp_Ge) {
+      if (CMP(q2, seven_ff) & pn_Cmp_Ge)
         magu.need_add = 1;
 
       q2 = ADD(ADD(q2, q2), ONE(mode));
       r2 = SUB(ADD(ADD(r2, r2), ONE(mode)), d);
     }
     else {
-      if (CMP(q2, two_bits_1) & Ge)
+      if (CMP(q2, two_bits_1) & pn_Cmp_Ge)
         magu.need_add = 1;
 
       q2 = ADD(q2, q2);
@@ -513,11 +533,13 @@ static struct mu magicu(tarval *d)
     }
     delta = SUB(SUB(d, ONE(mode)), r2);
   } while (p < 2*bits &&
-          (CMP(q1, delta) & Lt || (CMP(q1, delta) & Eq && CMP(r1, ZERO(mode)) & Eq)));
+          (CMP(q1, delta) & pn_Cmp_Lt || (CMP(q1, delta) & pn_Cmp_Eq && CMP(r1, ZERO(mode)) & pn_Cmp_Eq)));
 
   magu.M = ADD(q2, ONE(mode));                       /* Magic number */
   magu.s = p - bits;                                 /* and shift amount */
 
+  tarval_set_integer_overflow_mode(rem);
+
   return magu;
 }
 
@@ -535,6 +557,10 @@ static ir_node *replace_div_by_mulh(ir_node *div, tarval *tv)
   int bits       = get_mode_size_bits(mode);
   ir_node *q, *t, *c;
 
+  /* Beware: do not transform bad code */
+  if (is_Bad(n) || is_Bad(block))
+    return div;
+
   if (mode_is_signed(mode)) {
     struct ms mag = magic(tv);
 
@@ -550,12 +576,12 @@ static ir_node *replace_div_by_mulh(ir_node *div, tarval *tv)
 
     /* Do we need the shift */
     if (mag.s > 0) {
-      c = new_r_Const(current_ir_graph, block, mode_Iu, new_tarval_from_long(mag.s, mode_Iu));
+      c = new_r_Const_long(current_ir_graph, block, mode_Iu, mag.s);
       q    = new_rd_Shrs(dbg, current_ir_graph, block, q, c, mode);
     }
 
     /* final */
-    c = new_r_Const(current_ir_graph, block, mode_Iu, new_tarval_from_long(bits-1, mode_Iu));
+    c = new_r_Const_long(current_ir_graph, block, mode_Iu, bits-1);
     t = new_rd_Shr(dbg, current_ir_graph, block, q, c, mode);
 
     q = new_rd_Add(dbg, current_ir_graph, block, q, t, mode);
@@ -578,7 +604,7 @@ static ir_node *replace_div_by_mulh(ir_node *div, tarval *tv)
 
         t = new_rd_Add(dbg, current_ir_graph, block, t, q, mode);
 
-        c = new_r_Const(current_ir_graph, block, mode_Iu, new_tarval_from_long(mag.s-1, mode_Iu));
+        c = new_r_Const_long(current_ir_graph, block, mode_Iu, mag.s-1);
         q = new_rd_Shr(dbg, current_ir_graph, block, t, c, mode);
       }
       else {
@@ -587,7 +613,7 @@ static ir_node *replace_div_by_mulh(ir_node *div, tarval *tv)
       }
     }
     else if (mag.s > 0) { /* default scheme, shift needed */
-      c = new_r_Const(current_ir_graph, block, mode_Iu, new_tarval_from_long(mag.s, mode_Iu));
+      c = new_r_Const_long(current_ir_graph, block, mode_Iu, mag.s);
       q = new_rd_Shr(dbg, current_ir_graph, block, q, c, mode);
     }
   }
@@ -643,16 +669,16 @@ ir_node *arch_dep_replace_div_by_const(ir_node *irn)
         ir_node *curr = left;
 
         if (k != 1) {
-          k_node = new_r_Const(current_ir_graph, block, mode_Iu, new_tarval_from_long(k - 1, mode_Iu));
+          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(current_ir_graph, block, mode_Iu, new_tarval_from_long(bits - k, mode_Iu));
+        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);
 
-        k_node = new_r_Const(current_ir_graph, block, mode_Iu, new_tarval_from_long(k, mode_Iu));
+        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);
 
         if (n_flag) { /* negate the result */
@@ -665,20 +691,19 @@ ir_node *arch_dep_replace_div_by_const(ir_node *irn)
       else {      /* unsigned case */
         ir_node *k_node;
 
-        k_node = new_r_Const(current_ir_graph, block, mode_Iu, new_tarval_from_long(k, mode_Iu));
+        k_node = new_r_Const_long(current_ir_graph, block, mode_Iu, k);
         res    = new_rd_Shr(dbg, current_ir_graph, block, left, k_node, mode);
       }
     }
     else {
       /* other constant */
-      if ((mode_is_signed(mode) && params->allow_mulhs) ||
-          (!mode_is_signed(mode) && params->allow_mulhu))
+      if (allow_Mulh(mode))
         res = replace_div_by_mulh(irn, tv);
     }
   }
 
   if (res != irn)
-    stat_arch_dep_replace_div_by_const(irn);
+    hook_arch_dep_replace_div_by_const(irn);
 
   return res;
 }
@@ -733,16 +758,16 @@ ir_node *arch_dep_replace_mod_by_const(ir_node *irn)
         ir_node *curr = left;
 
         if (k != 1) {
-          k_node = new_r_Const(current_ir_graph, block, mode_Iu, new_tarval_from_long(k - 1, mode_Iu));
+          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(current_ir_graph, block, mode_Iu, new_tarval_from_long(bits - k, mode_Iu));
+        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);
 
-        k_node = new_r_Const(current_ir_graph, block, mode, new_tarval_from_long((-1) << k, mode));
+        k_node = new_r_Const_long(current_ir_graph, block, mode, (-1) << k);
         curr   = new_rd_And(dbg, current_ir_graph, block, curr, k_node, mode);
 
         res    = new_rd_Sub(dbg, current_ir_graph, block, left, curr, mode);
@@ -750,14 +775,13 @@ ir_node *arch_dep_replace_mod_by_const(ir_node *irn)
       else {      /* unsigned case */
         ir_node *k_node;
 
-        k_node = new_r_Const(current_ir_graph, block, mode, new_tarval_from_long((1 << k) - 1, mode));
+        k_node = new_r_Const_long(current_ir_graph, block, mode, (1 << k) - 1);
         res    = new_rd_And(dbg, current_ir_graph, block, left, k_node, mode);
       }
     }
     else {
       /* other constant */
-      if ((mode_is_signed(mode) && params->allow_mulhs) ||
-          (!mode_is_signed(mode) && params->allow_mulhu)) {
+      if (allow_Mulh(mode)) {
         res = replace_div_by_mulh(irn, tv);
 
         res = new_rd_Mul(dbg, current_ir_graph, block, res, c, mode);
@@ -770,7 +794,7 @@ ir_node *arch_dep_replace_mod_by_const(ir_node *irn)
   }
 
   if (res != irn)
-    stat_arch_dep_replace_mod_by_const(irn);
+    hook_arch_dep_replace_mod_by_const(irn);
 
   return res;
 }
@@ -825,16 +849,16 @@ void arch_dep_replace_divmod_by_const(ir_node **div, ir_node **mod, ir_node *irn
         ir_node *curr = left;
 
         if (k != 1) {
-          k_node = new_r_Const(current_ir_graph, block, mode_Iu, new_tarval_from_long(k - 1, mode_Iu));
+          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(current_ir_graph, block, mode_Iu, new_tarval_from_long(bits - k, mode_Iu));
+        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);
 
-        c_k    = new_r_Const(current_ir_graph, block, mode_Iu, new_tarval_from_long(k, mode_Iu));
+        c_k    = new_r_Const_long(current_ir_graph, block, mode_Iu, k);
 
         *div   = new_rd_Shrs(dbg, current_ir_graph, block, curr, c_k, mode);
 
@@ -845,7 +869,7 @@ void arch_dep_replace_divmod_by_const(ir_node **div, ir_node **mod, ir_node *irn
           *div = new_rd_Sub(dbg, current_ir_graph, block, k_node, *div, mode);
         }
 
-        k_node = new_r_Const(current_ir_graph, block, mode, new_tarval_from_long((-1) << k, mode));
+        k_node = new_r_Const_long(current_ir_graph, block, mode, (-1) << k);
         curr   = new_rd_And(dbg, current_ir_graph, block, curr, k_node, mode);
 
         *mod   = new_rd_Sub(dbg, current_ir_graph, block, left, curr, mode);
@@ -853,17 +877,16 @@ void arch_dep_replace_divmod_by_const(ir_node **div, ir_node **mod, ir_node *irn
       else {      /* unsigned case */
         ir_node *k_node;
 
-        k_node = new_r_Const(current_ir_graph, block, mode_Iu, new_tarval_from_long(k, mode_Iu));
+        k_node = new_r_Const_long(current_ir_graph, block, mode_Iu, k);
         *div   = new_rd_Shr(dbg, current_ir_graph, block, left, k_node, mode);
 
-        k_node = new_r_Const(current_ir_graph, block, mode, new_tarval_from_long((1 << k) - 1, mode));
+        k_node = new_r_Const_long(current_ir_graph, block, mode, (1 << k) - 1);
         *mod   = new_rd_And(dbg, current_ir_graph, block, left, k_node, mode);
       }
     }
     else {
       /* other constant */
-      if ((mode_is_signed(mode) && params->allow_mulhs) ||
-          (!mode_is_signed(mode) && params->allow_mulhu)) {
+      if (allow_Mulh(mode)) {
         ir_node *t;
 
         *div = replace_div_by_mulh(irn, tv);
@@ -878,16 +901,18 @@ void arch_dep_replace_divmod_by_const(ir_node **div, ir_node **mod, ir_node *irn
   }
 
   if (*div)
-    stat_arch_dep_replace_DivMod_by_const(irn);
+    hook_arch_dep_replace_DivMod_by_const(irn);
 }
 
 
 static const arch_dep_params_t default_params = {
-  1, /* also use subs */
-  0, /* allow Mulhs */
-  0, /* allow Mulus */
-  4, /* maximum shifts */
-  31 /* maximum shift amount */
+  1,  /* also use subs */
+  4,  /* maximum shifts */
+  31, /* maximum shift amount */
+
+  0,  /* allow Mulhs */
+  0,  /* allow Mulus */
+  32  /* Mulh allowed up to 32 bit */
 };
 
 const arch_dep_params_t *arch_dep_default_factory(void) {