diff mbox

wide-int, misc

Message ID 8F7BF292-65C2-46AD-B13C-5D739961DA0B@comcast.net
State New
Headers show

Commit Message

Mike Stump Nov. 23, 2013, 7:22 p.m. UTC
Richi has asked the we break the wide-int patch so that the individual port and front end maintainers can review their parts without have to go through the entire patch.    This patch covers the random pieces that didn't seem to fit nicely into other bins.

Ok?
* coretypes.h
	(struct hwivec_def): New.
	(hwivec): New.
	(const_hwivec): New.
	* dbxout.c
	(stabstr_U): Use wide-int interfaces.
	(dbxout_type): Update to use cst_fits_shwi_p.
	* defaults.h
	(TARGET_SUPPORTS_WIDE_INT): Add default.
	* double-int.h: Include wide-int.h.
	(struct wi::int_traits): New.
	* fixed-value.c: Include wide-int.h.
	(fixed_from_string): Use wide-int interfaces.
	(fixed_to_decimal): Likewise.
	(fixed_convert_from_real): Likewise.
	(real_convert_from_fixed): Likewise.
	* predict.c
	(predict_iv_comparison): Use wide-int interfaces.
	* pretty-print.h: Include wide-int-print.h.
	(pp_wide_int) New.
	* signop.h: New file.
	* system.h
	(STATIC_CONSTANT_P): New.
	(STATIC_ASSERT): New.
	* target.def
	(can_use_doloop_p): Take widest_ints rather than double_ints.
	* target.h: Include wide-int.h rather than double-int.h.

Comments

Richard Biener Dec. 2, 2013, 3:28 p.m. UTC | #1
On Sat, Nov 23, 2013 at 8:22 PM, Mike Stump <mikestump@comcast.net> wrote:
> Richi has asked the we break the wide-int patch so that the individual port and front end maintainers can review their parts without have to go through the entire patch.    This patch covers the random pieces that didn't seem to fit nicely into other bins.
>
> Ok?

Ok.

Thanks,
Richard.
diff mbox

Patch

diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 5d60240..439b0cb 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -58,6 +58,9 @@  typedef const struct rtx_def *const_rtx;
 struct rtvec_def;
 typedef struct rtvec_def *rtvec;
 typedef const struct rtvec_def *const_rtvec;
+struct hwivec_def;
+typedef struct hwivec_def *hwivec;
+typedef const struct hwivec_def *const_hwivec;
 union tree_node;
 typedef union tree_node *tree;
 typedef const union tree_node *const_tree;
diff --git a/gcc/dbxout.c b/gcc/dbxout.c
index bc6a3af..bbd8be0 100644
--- a/gcc/dbxout.c
+++ b/gcc/dbxout.c
@@ -692,88 +692,39 @@  stabstr_U (unsigned HOST_WIDE_INT num)
 static void
 stabstr_O (tree cst)
 {
-  unsigned HOST_WIDE_INT high = TREE_INT_CST_HIGH (cst);
-  unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (cst);
-
-  char buf[128];
-  char *p = buf + sizeof buf;
-
-  /* GDB wants constants with no extra leading "1" bits, so
-     we need to remove any sign-extension that might be
-     present.  */
-  {
-    const unsigned int width = TYPE_PRECISION (TREE_TYPE (cst));
-    if (width == HOST_BITS_PER_DOUBLE_INT)
-      ;
-    else if (width > HOST_BITS_PER_WIDE_INT)
-      high &= (((HOST_WIDE_INT) 1 << (width - HOST_BITS_PER_WIDE_INT)) - 1);
-    else if (width == HOST_BITS_PER_WIDE_INT)
-      high = 0;
-    else
-      high = 0, low &= (((HOST_WIDE_INT) 1 << width) - 1);
-  }
+  int prec = TYPE_PRECISION (TREE_TYPE (cst));
+  int res_pres = prec % 3;
+  int i;
+  unsigned int digit;
 
   /* Leading zero for base indicator.  */
   stabstr_C ('0');
 
   /* If the value is zero, the base indicator will serve as the value
      all by itself.  */
-  if (high == 0 && low == 0)
+  if (wi::eq_p (cst, 0))
     return;
 
-  /* If the high half is zero, we need only print the low half normally.  */
-  if (high == 0)
-    NUMBER_FMT_LOOP (p, low, 8);
-  else
+  /* GDB wants constants with no extra leading "1" bits, so
+     we need to remove any sign-extension that might be
+     present.  */
+  if (res_pres == 1)
     {
-      /* When high != 0, we need to print enough zeroes from low to
-	 give the digits from high their proper place-values.  Hence
-	 NUMBER_FMT_LOOP cannot be used.  */
-      const int n_digits = HOST_BITS_PER_WIDE_INT / 3;
-      int i;
-
-      for (i = 1; i <= n_digits; i++)
-	{
-	  unsigned int digit = low % 8;
-	  low /= 8;
-	  *--p = '0' + digit;
-	}
-
-      /* Octal digits carry exactly three bits of information.  The
-	 width of a HOST_WIDE_INT is not normally a multiple of three.
-	 Therefore, the next digit printed probably needs to carry
-	 information from both low and high.  */
-      if (HOST_BITS_PER_WIDE_INT % 3 != 0)
-	{
-	  const int n_leftover_bits = HOST_BITS_PER_WIDE_INT % 3;
-	  const int n_bits_from_high = 3 - n_leftover_bits;
-
-	  const unsigned HOST_WIDE_INT
-	    low_mask = (((unsigned HOST_WIDE_INT)1) << n_leftover_bits) - 1;
-	  const unsigned HOST_WIDE_INT
-	    high_mask = (((unsigned HOST_WIDE_INT)1) << n_bits_from_high) - 1;
-
-	  unsigned int digit;
-
-	  /* At this point, only the bottom n_leftover_bits bits of low
-	     should be set.  */
-	  gcc_assert (!(low & ~low_mask));
-
-	  digit = (low | ((high & high_mask) << n_leftover_bits));
-	  high >>= n_bits_from_high;
-
-	  *--p = '0' + digit;
-	}
-
-      /* Now we can format high in the normal manner.  However, if
-	 the only bits of high that were set were handled by the
-	 digit split between low and high, high will now be zero, and
-	 we don't want to print extra digits in that case.  */
-      if (high)
-	NUMBER_FMT_LOOP (p, high, 8);
+      digit = wi::extract_uhwi (cst, prec - 1, 1);
+      stabstr_C ('0' + digit);
+    }
+  else if (res_pres == 2)
+    {
+      digit = wi::extract_uhwi (cst, prec - 2, 2);
+      stabstr_C ('0' + digit);
     }
 
-  obstack_grow (&stabstr_ob, p, (buf + sizeof buf) - p);
+  prec -= res_pres;
+  for (i = prec - 3; i <= 0; i = i - 3)
+    {
+      digit = wi::extract_uhwi (cst, i, 3);
+      stabstr_C ('0' + digit);
+    }
 }
 
 /* Called whenever it is safe to break a stabs string into multiple
@@ -2301,10 +2252,7 @@  dbxout_type (tree type, int full)
           if (TREE_CODE (value) == CONST_DECL)
             value = DECL_INITIAL (value);
 
-	  if (TREE_INT_CST_HIGH (value) == 0)
-	    stabstr_D (TREE_INT_CST_LOW (value));
-	  else if (TREE_INT_CST_HIGH (value) == -1
-		   && (HOST_WIDE_INT) TREE_INT_CST_LOW (value) < 0)
+	  if (cst_and_fits_in_hwi (value))
 	    stabstr_D (TREE_INT_CST_LOW (value));
 	  else
 	    stabstr_O (value);
diff --git a/gcc/defaults.h b/gcc/defaults.h
index 37e8a08..0c69918 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -1392,6 +1392,14 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define SWITCHABLE_TARGET 0
 #endif
 
+/* If the target supports integers that are wider than two
+   HOST_WIDE_INTs on the host compiler, then the target should define
+   TARGET_SUPPORTS_WIDE_INT and make the appropriate fixups.
+   Otherwise the compiler really is not robust.  */
+#ifndef TARGET_SUPPORTS_WIDE_INT
+#define TARGET_SUPPORTS_WIDE_INT 0
+#endif
+
 #endif /* GCC_INSN_FLAGS_H  */
 
 #endif  /* ! GCC_DEFAULTS_H */
diff --git a/gcc/double-int.h b/gcc/double-int.h
index 650520b..50ca182 100644
--- a/gcc/double-int.h
+++ b/gcc/double-int.h
@@ -20,6 +20,8 @@  along with GCC; see the file COPYING3.  If not see
 #ifndef DOUBLE_INT_H
 #define DOUBLE_INT_H
 
+#include "wide-int.h"
+
 /* A large integer is currently represented as a pair of HOST_WIDE_INTs.
    It therefore represents a number with precision of
    2 * HOST_BITS_PER_WIDE_INT bits (it is however possible that the
@@ -435,4 +437,36 @@  void mpz_set_double_int (mpz_t, double_int, bool);
 double_int mpz_get_double_int (const_tree, mpz_t, bool);
 #endif
 
+namespace wi
+{
+  template <>
+  struct int_traits <double_int>
+  {
+    static const enum precision_type precision_type = CONST_PRECISION;
+    static const bool host_dependent_precision = true;
+    static const unsigned int precision = HOST_BITS_PER_DOUBLE_INT;
+    static unsigned int get_precision (const double_int &);
+    static wi::storage_ref decompose (HOST_WIDE_INT *, unsigned int,
+				      const double_int &);
+  };
+}
+
+inline unsigned int
+wi::int_traits <double_int>::get_precision (const double_int &)
+{
+  return precision;
+}
+
+inline wi::storage_ref
+wi::int_traits <double_int>::decompose (HOST_WIDE_INT *scratch, unsigned int p,
+					const double_int &x)
+{
+  gcc_checking_assert (precision == p);
+  scratch[0] = x.low;
+  if ((x.high == 0 && scratch[0] >= 0) || (x.high == -1 && scratch[0] < 0))
+    return wi::storage_ref (scratch, 1, precision);
+  scratch[1] = x.high;
+  return wi::storage_ref (scratch, 2, precision);
+}
+
 #endif /* DOUBLE_INT_H */
diff --git a/gcc/fixed-value.c b/gcc/fixed-value.c
index 91ec588..03fd599 100644
--- a/gcc/fixed-value.c
+++ b/gcc/fixed-value.c
@@ -23,6 +23,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "tm.h"
 #include "tree.h"
 #include "diagnostic-core.h"
+#include "wide-int.h"
 
 /* Compare two fixed objects for bitwise identity.  */
 
@@ -113,6 +114,7 @@  fixed_from_string (FIXED_VALUE_TYPE *f, const char *str, enum machine_mode mode)
   REAL_VALUE_TYPE real_value, fixed_value, base_value;
   unsigned int fbit;
   enum fixed_value_range_code temp;
+  bool fail;
 
   f->mode = mode;
   fbit = GET_MODE_FBIT (mode);
@@ -127,8 +129,10 @@  fixed_from_string (FIXED_VALUE_TYPE *f, const char *str, enum machine_mode mode)
 	     "large fixed-point constant implicitly truncated to fixed-point type");
   real_2expN (&base_value, fbit, mode);
   real_arithmetic (&fixed_value, MULT_EXPR, &real_value, &base_value);
-  real_to_integer2 ((HOST_WIDE_INT *)&f->data.low, &f->data.high,
-		    &fixed_value);
+  wide_int w = real_to_integer (&fixed_value, &fail,
+				GET_MODE_PRECISION (mode));
+  f->data.low = w.elt (0);
+  f->data.high = w.elt (1);
 
   if (temp == FIXED_MAX_EPS && ALL_FRACT_MODE_P (f->mode))
     {
@@ -153,9 +157,12 @@  fixed_to_decimal (char *str, const FIXED_VALUE_TYPE *f_orig,
 {
   REAL_VALUE_TYPE real_value, base_value, fixed_value;
 
+  signop sgn = UNSIGNED_FIXED_POINT_MODE_P (f_orig->mode) ? UNSIGNED : SIGNED;
   real_2expN (&base_value, GET_MODE_FBIT (f_orig->mode), f_orig->mode);
-  real_from_integer (&real_value, VOIDmode, f_orig->data.low, f_orig->data.high,
-		     UNSIGNED_FIXED_POINT_MODE_P (f_orig->mode));
+  real_from_integer (&real_value, VOIDmode,
+		     wide_int::from (f_orig->data,
+				     GET_MODE_PRECISION (f_orig->mode), sgn),
+		     sgn);
   real_arithmetic (&fixed_value, RDIV_EXPR, &real_value, &base_value);
   real_to_decimal (str, &fixed_value, buf_size, 0, 1);
 }
@@ -1041,12 +1048,17 @@  fixed_convert_from_real (FIXED_VALUE_TYPE *f, enum machine_mode mode,
   int i_f_bits = GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode);
   unsigned int fbit = GET_MODE_FBIT (mode);
   enum fixed_value_range_code temp;
+  bool fail;
 
   real_value = *a;
   f->mode = mode;
   real_2expN (&base_value, fbit, mode);
   real_arithmetic (&fixed_value, MULT_EXPR, &real_value, &base_value);
-  real_to_integer2 ((HOST_WIDE_INT *)&f->data.low, &f->data.high, &fixed_value);
+
+  wide_int w = real_to_integer (&fixed_value, &fail,
+				GET_MODE_PRECISION (mode));
+  f->data.low = w.elt (0);
+  f->data.high = w.elt (1);
   temp = check_real_for_fixed_mode (&real_value, mode);
   if (temp == FIXED_UNDERFLOW) /* Minimum.  */
     {
@@ -1091,9 +1103,11 @@  real_convert_from_fixed (REAL_VALUE_TYPE *r, enum machine_mode mode,
 {
   REAL_VALUE_TYPE base_value, fixed_value, real_value;
 
+  signop sgn = UNSIGNED_FIXED_POINT_MODE_P (f->mode) ? UNSIGNED : SIGNED;
   real_2expN (&base_value, GET_MODE_FBIT (f->mode), f->mode);
-  real_from_integer (&fixed_value, VOIDmode, f->data.low, f->data.high,
-		     UNSIGNED_FIXED_POINT_MODE_P (f->mode));
+  real_from_integer (&fixed_value, VOIDmode,
+		     wide_int::from (f->data, GET_MODE_PRECISION (f->mode),
+				     sgn), sgn);
   real_arithmetic (&real_value, RDIV_EXPR, &fixed_value, &base_value);
   real_convert (r, mode, &real_value);
 }
diff --git a/gcc/predict.c b/gcc/predict.c
index 919dbe9..afe78c6 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -1310,76 +1310,58 @@  predict_iv_comparison (struct loop *loop, basic_block bb,
       && tree_fits_shwi_p (compare_base))
     {
       int probability;
-      bool of, overflow = false;
-      double_int mod, compare_count, tem, loop_count;
+      bool overflow, overall_overflow = false;
+      widest_int compare_count, tem;
 
-      double_int loop_bound = tree_to_double_int (loop_bound_var);
-      double_int compare_bound = tree_to_double_int (compare_var);
-      double_int base = tree_to_double_int (compare_base);
-      double_int compare_step = tree_to_double_int (compare_step_var);
+      widest_int loop_bound = wi::to_widest (loop_bound_var);
+      widest_int compare_bound = wi::to_widest (compare_var);
+      widest_int base = wi::to_widest (compare_base);
+      widest_int compare_step = wi::to_widest (compare_step_var);
 
       /* (loop_bound - base) / compare_step */
-      tem = loop_bound.sub_with_overflow (base, &of);
-      overflow |= of;
-      loop_count = tem.divmod_with_overflow (compare_step,
-					      0, TRUNC_DIV_EXPR,
-					      &mod, &of);
-      overflow |= of;
-
-      if ((!compare_step.is_negative ())
+      tem = wi::sub (loop_bound, base, SIGNED, &overflow);
+      overall_overflow |= overflow;
+      widest_int loop_count = wi::div_trunc (tem, compare_step, SIGNED,
+					     &overflow);
+      overall_overflow |= overflow;
+
+      if (!wi::neg_p (compare_step)
           ^ (compare_code == LT_EXPR || compare_code == LE_EXPR))
 	{
 	  /* (loop_bound - compare_bound) / compare_step */
-	  tem = loop_bound.sub_with_overflow (compare_bound, &of);
-	  overflow |= of;
-	  compare_count = tem.divmod_with_overflow (compare_step,
-						     0, TRUNC_DIV_EXPR,
-						     &mod, &of);
-	  overflow |= of;
+	  tem = wi::sub (loop_bound, compare_bound, SIGNED, &overflow);
+	  overall_overflow |= overflow;
+	  compare_count = wi::div_trunc (tem, compare_step, SIGNED, &overflow);
+	  overall_overflow |= overflow;
 	}
       else
         {
 	  /* (compare_bound - base) / compare_step */
-	  tem = compare_bound.sub_with_overflow (base, &of);
-	  overflow |= of;
-          compare_count = tem.divmod_with_overflow (compare_step,
-						     0, TRUNC_DIV_EXPR,
-						     &mod, &of);
-	  overflow |= of;
+	  tem = wi::sub (compare_bound, base, SIGNED, &overflow);
+	  overall_overflow |= overflow;
+          compare_count = wi::div_trunc (tem, compare_step, SIGNED, &overflow);
+	  overall_overflow |= overflow;
 	}
       if (compare_code == LE_EXPR || compare_code == GE_EXPR)
 	++compare_count;
       if (loop_bound_code == LE_EXPR || loop_bound_code == GE_EXPR)
 	++loop_count;
-      if (compare_count.is_negative ())
-        compare_count = double_int_zero;
-      if (loop_count.is_negative ())
-        loop_count = double_int_zero;
-      if (loop_count.is_zero ())
+      if (wi::neg_p (compare_count))
+        compare_count = 0;
+      if (wi::neg_p (loop_count))
+        loop_count = 0;
+      if (loop_count == 0)
 	probability = 0;
-      else if (compare_count.scmp (loop_count) == 1)
+      else if (wi::cmps (compare_count, loop_count) == 1)
 	probability = REG_BR_PROB_BASE;
       else
         {
-	  /* If loop_count is too big, such that REG_BR_PROB_BASE * loop_count
-	     could overflow, shift both loop_count and compare_count right
-	     a bit so that it doesn't overflow.  Note both counts are known not
-	     to be negative at this point.  */
-	  int clz_bits = clz_hwi (loop_count.high);
-	  gcc_assert (REG_BR_PROB_BASE < 32768);
-	  if (clz_bits < 16)
-	    {
-	      loop_count.arshift (16 - clz_bits, HOST_BITS_PER_DOUBLE_INT);
-	      compare_count.arshift (16 - clz_bits, HOST_BITS_PER_DOUBLE_INT);
-	    }
-	  tem = compare_count.mul_with_sign (double_int::from_shwi
-					    (REG_BR_PROB_BASE), true, &of);
-	  gcc_assert (!of);
-	  tem = tem.divmod (loop_count, true, TRUNC_DIV_EXPR, &mod);
+	  tem = compare_count * REG_BR_PROB_BASE;
+	  tem = wi::udiv_trunc (tem, loop_count);
 	  probability = tem.to_uhwi ();
 	}
 
-      if (!overflow)
+      if (!overall_overflow)
         predict_edge (then_edge, PRED_LOOP_IV_COMPARE, probability);
 
       return;
diff --git a/gcc/pretty-print.h b/gcc/pretty-print.h
index a60be32..0003f28 100644
--- a/gcc/pretty-print.h
+++ b/gcc/pretty-print.h
@@ -23,6 +23,7 @@  along with GCC; see the file COPYING3.  If not see
 
 #include "obstack.h"
 #include "input.h"
+#include "wide-int-print.h"
 
 /* Maximum number of format string arguments.  */
 #define PP_NL_ARGMAX   30
@@ -261,6 +262,13 @@  pp_get_prefix (const pretty_printer *pp) { return pp->prefix; }
 #define pp_decimal_int(PP, I)  pp_scalar (PP, "%d", I)
 #define pp_unsigned_wide_integer(PP, I) \
    pp_scalar (PP, HOST_WIDE_INT_PRINT_UNSIGNED, (unsigned HOST_WIDE_INT) I)
+#define pp_wide_int(PP, W, SGN)					\
+  do								\
+    {								\
+      print_dec (W, pp_buffer (PP)->digit_buffer, SGN);		\
+      pp_string (PP, pp_buffer (PP)->digit_buffer);		\
+    }								\
+  while (0)
 #define pp_wide_integer(PP, I) \
    pp_scalar (PP, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) I)
 #define pp_widest_integer(PP, I) \
diff --git a/gcc/signop.h b/gcc/signop.h
new file mode 100644
index 0000000..05dac90
--- /dev/null
+++ b/gcc/signop.h
@@ -0,0 +1,35 @@ 
+/* Operations with SIGNED and UNSIGNED.  -*- C++ -*-
+   Copyright (C) 2012-2013 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef SIGNOP_H
+#define SIGNOP_H
+
+/* This type is used for the large number of functions that produce
+   different results depending on if the operands are signed types or
+   unsigned types.  The signedness of a tree type can be found by
+   using the TYPE_SIGN macro.  */
+
+enum signop_e {
+  SIGNED,
+  UNSIGNED
+};
+
+typedef enum signop_e signop;
+
+#endif
diff --git a/gcc/system.h b/gcc/system.h
index 87ebe3c..adc9703 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -711,6 +711,16 @@  extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
 #define gcc_unreachable() (fancy_abort (__FILE__, __LINE__, __FUNCTION__))
 #endif
 
+#if GCC_VERSION >= 3001
+#define STATIC_CONSTANT_P(X) (__builtin_constant_p (X) && (X))
+#else
+#define STATIC_CONSTANT_P(X) (false && (X))
+#endif
+
+/* Until we can use STATIC_ASSERT.  */
+#define STATIC_ASSERT(X) \
+  typedef int assertion1[(X) ? 1 : -1] ATTRIBUTE_UNUSED
+
 /* Provide a fake boolean type.  We make no attempt to use the
    C99 _Bool, as it may not be available in the bootstrap compiler,
    and even if it is, it is liable to be buggy.
diff --git a/gcc/target.def b/gcc/target.def
index f6e42a1..de75e8d 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -3610,9 +3610,9 @@  loop is only entered from the top.\n\
 This hook is only used if @code{doloop_end} is available.  The default\n\
 implementation returns true.  You can use @code{can_use_doloop_if_innermost}\n\
 if the loop must be the innermost, and if there are no other restrictions.",
- bool, (double_int iterations, double_int iterations_max,
+ bool, (const widest_int &iterations, const widest_int &iterations_max,
 	unsigned int loop_depth, bool entered_at_top),
- hook_bool_dint_dint_uint_bool_true)
+ hook_bool_wint_wint_uint_bool_true)
 
 /* Returns NULL if target supports the insn within a doloop block,
    otherwise it returns an error message.  */
diff --git a/gcc/target.h b/gcc/target.h
index 12249ec..19522e2 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -50,7 +50,7 @@ 
 
 #include "insn-modes.h"
 #include "insn-codes.h"
-#include "double-int.h"
+#include "wide-int.h"
 
 #ifdef ENABLE_CHECKING