wide-int branch now up for public comment and review

Richard Sandiford rdsandiford@googlemail.com
Sat Aug 24 13:10:00 GMT 2013


Richard Sandiford <rdsandiford@googlemail.com> writes:
> I wonder how easy it would be to restrict this use of "zero precision"
> (i.e. flexible precision) to those where primitive types like "int" are
> used as template arguments to operators, and require a precision when
> constructing a wide_int.  I wouldn't have expected "real" precision 0
> (from zero-width bitfields or whatever) to need any special handling
> compared to precision 1 or 2.

I tried the last bit -- requiring a precision when constructing a
wide_int -- and it seemed surprising easy.  What do you think of
the attached?  Most of the forced knock-on changes seem like improvements,
but the java part is a bit ugly.  I also went with "wide_int (0, prec).cmp"
for now, although I'd like to add static cmp, cmps and cmpu alongside
leu_p, etc., if that's OK.  It would then be possible to write
"wide_int::cmp (0, ...)" and avoid the wide_int construction altogether.

I wondered whether you might also want to get rid of the build_int_cst*
functions, but that still looks a long way off, so I hope using them in
these two places doesn't seem too bad.

This is just an incremental step.  I've also only run it through a
subset of the testsuite so far, but full tests are in progress...

Thanks,
Richard


Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	2013-08-24 12:11:08.085684013 +0100
+++ gcc/fold-const.c	2013-08-24 01:00:00.000000000 +0100
@@ -8865,15 +8865,16 @@ pointer_may_wrap_p (tree base, tree offs
   if (bitpos < 0)
     return true;
 
+  int precision = TYPE_PRECISION (TREE_TYPE (base));
   if (offset == NULL_TREE)
-    wi_offset = wide_int::zero (TYPE_PRECISION (TREE_TYPE (base)));
+    wi_offset = wide_int::zero (precision);
   else if (TREE_CODE (offset) != INTEGER_CST || TREE_OVERFLOW (offset))
     return true;
   else
     wi_offset = offset;
 
   bool overflow;
-  wide_int units = wide_int::from_shwi (bitpos / BITS_PER_UNIT);
+  wide_int units = wide_int::from_shwi (bitpos / BITS_PER_UNIT, precision);
   total = wi_offset.add (units, UNSIGNED, &overflow);
   if (overflow)
     return true;
Index: gcc/gimple-ssa-strength-reduction.c
===================================================================
--- gcc/gimple-ssa-strength-reduction.c	2013-08-24 12:11:08.085684013 +0100
+++ gcc/gimple-ssa-strength-reduction.c	2013-08-24 01:00:00.000000000 +0100
@@ -777,7 +777,6 @@ restructure_reference (tree *pbase, tree
 {
   tree base = *pbase, offset = *poffset;
   max_wide_int index = *pindex;
-  wide_int bpu = BITS_PER_UNIT;
   tree mult_op0, t1, t2, type;
   max_wide_int c1, c2, c3, c4;
 
@@ -786,7 +785,7 @@ restructure_reference (tree *pbase, tree
       || TREE_CODE (base) != MEM_REF
       || TREE_CODE (offset) != MULT_EXPR
       || TREE_CODE (TREE_OPERAND (offset, 1)) != INTEGER_CST
-      || !index.umod_floor (bpu).zero_p ())
+      || !index.umod_floor (BITS_PER_UNIT).zero_p ())
     return false;
 
   t1 = TREE_OPERAND (base, 0);
@@ -822,7 +821,7 @@ restructure_reference (tree *pbase, tree
       c2 = 0;
     }
 
-  c4 = index.udiv_floor (bpu);
+  c4 = index.udiv_floor (BITS_PER_UNIT);
 
   *pbase = t1;
   *poffset = fold_build2 (MULT_EXPR, sizetype, t2,
Index: gcc/java/jcf-parse.c
===================================================================
--- gcc/java/jcf-parse.c	2013-08-24 12:11:08.085684013 +0100
+++ gcc/java/jcf-parse.c	2013-08-24 01:00:00.000000000 +0100
@@ -1043,9 +1043,10 @@ get_constant (JCF *jcf, int index)
 	wide_int val;
 
 	num = JPOOL_UINT (jcf, index);
-	val = wide_int (num).sforce_to_size (32).lshift_widen (32, 64);
+	val = wide_int::from_hwi (num, long_type_node)
+	  .sforce_to_size (32).lshift_widen (32, 64);
 	num = JPOOL_UINT (jcf, index + 1);
-	val |= wide_int (num);
+	val |= wide_int::from_hwi (num, long_type_node);
 
 	value = wide_int_to_tree (long_type_node, val);
 	break;
Index: gcc/loop-unroll.c
===================================================================
--- gcc/loop-unroll.c	2013-08-24 12:11:08.085684013 +0100
+++ gcc/loop-unroll.c	2013-08-24 01:00:00.000000000 +0100
@@ -816,8 +816,7 @@ unroll_loop_constant_iterations (struct
 	  desc->niter -= exit_mod;
 	  loop->nb_iterations_upper_bound -= exit_mod;
 	  if (loop->any_estimate
-	      && wide_int (exit_mod).leu_p
-	           (loop->nb_iterations_estimate))
+	      && wide_int::leu_p (exit_mod, loop->nb_iterations_estimate))
 	    loop->nb_iterations_estimate -= exit_mod;
 	  else
 	    loop->any_estimate = false;
@@ -860,8 +859,7 @@ unroll_loop_constant_iterations (struct
 	  desc->niter -= exit_mod + 1;
 	  loop->nb_iterations_upper_bound -= exit_mod + 1;
 	  if (loop->any_estimate
-	      && wide_int (exit_mod + 1).leu_p
-	           (loop->nb_iterations_estimate))
+	      && wide_int::leu_p (exit_mod + 1, loop->nb_iterations_estimate))
 	    loop->nb_iterations_estimate -= exit_mod + 1;
 	  else
 	    loop->any_estimate = false;
@@ -1381,7 +1379,7 @@ decide_peel_simple (struct loop *loop, i
   if (estimated_loop_iterations (loop, &iterations))
     {
       /* TODO: unsigned/signed confusion */
-      if (wide_int::from_shwi (npeel).leu_p (iterations))
+      if (wide_int::leu_p (npeel, iterations))
 	{
 	  if (dump_file)
 	    {
Index: gcc/real.c
===================================================================
--- gcc/real.c	2013-08-24 12:11:08.085684013 +0100
+++ gcc/real.c	2013-08-24 01:00:00.000000000 +0100
@@ -2401,7 +2401,7 @@ real_digit (int n)
   gcc_assert (n <= 9);
 
   if (n > 0 && num[n].cl == rvc_zero)
-    real_from_integer (&num[n], VOIDmode, wide_int (n), UNSIGNED);
+    real_from_integer (&num[n], VOIDmode, n, UNSIGNED);
 
   return &num[n];
 }
Index: gcc/tree-predcom.c
===================================================================
--- gcc/tree-predcom.c	2013-08-24 12:11:08.085684013 +0100
+++ gcc/tree-predcom.c	2013-08-24 01:00:00.000000000 +0100
@@ -923,7 +923,7 @@ add_ref_to_chain (chain_p chain, dref re
 
   gcc_assert (root->offset.les_p (ref->offset));
   dist = ref->offset - root->offset;
-  if (max_wide_int::from_uhwi (MAX_DISTANCE).leu_p (dist))
+  if (wide_int::leu_p (MAX_DISTANCE, dist))
     {
       free (ref);
       return;
Index: gcc/tree-pretty-print.c
===================================================================
--- gcc/tree-pretty-print.c	2013-08-24 12:48:00.091379339 +0100
+++ gcc/tree-pretty-print.c	2013-08-24 01:00:00.000000000 +0100
@@ -1295,7 +1295,7 @@ dump_generic_node (pretty_printer *buffe
 	tree field, val;
 	bool is_struct_init = false;
 	bool is_array_init = false;
-	wide_int curidx = 0;
+	wide_int curidx;
 	pp_left_brace (buffer);
 	if (TREE_CLOBBER_P (node))
 	  pp_string (buffer, "CLOBBER");
Index: gcc/tree-ssa-ccp.c
===================================================================
--- gcc/tree-ssa-ccp.c	2013-08-24 12:11:08.085684013 +0100
+++ gcc/tree-ssa-ccp.c	2013-08-24 01:00:00.000000000 +0100
@@ -526,7 +526,7 @@ get_value_from_alignment (tree expr)
 	      : -1).and_not (align / BITS_PER_UNIT - 1);
   val.lattice_val = val.mask.minus_one_p () ? VARYING : CONSTANT;
   if (val.lattice_val == CONSTANT)
-    val.value = wide_int_to_tree (type, bitpos / BITS_PER_UNIT);
+    val.value = build_int_cstu (type, bitpos / BITS_PER_UNIT);
   else
     val.value = NULL_TREE;
 
Index: gcc/tree-vrp.c
===================================================================
--- gcc/tree-vrp.c	2013-08-24 12:48:00.093379358 +0100
+++ gcc/tree-vrp.c	2013-08-24 01:00:00.000000000 +0100
@@ -2420,9 +2420,9 @@ extract_range_from_binary_expr_1 (value_
 	      wmin = min0 - max1;
 	      wmax = max0 - min1;
 
-	      if (wide_int (0).cmp (max1, sgn) != wmin.cmp (min0, sgn))
+	      if (wide_int (0, prec).cmp (max1, sgn) != wmin.cmp (min0, sgn))
 		min_ovf = min0.cmp (max1, sgn);
-	      if (wide_int (0).cmp (min1, sgn) != wmax.cmp (max0, sgn))
+	      if (wide_int (0, prec).cmp (min1, sgn) != wmax.cmp (max0, sgn))
 		max_ovf = max0.cmp (min1, sgn);
 	    }
 
@@ -4911,8 +4911,8 @@ register_edge_assert_for_2 (tree name, e
       gimple def_stmt = SSA_NAME_DEF_STMT (name);
       tree name2 = NULL_TREE, names[2], cst2 = NULL_TREE;
       tree val2 = NULL_TREE;
-      wide_int mask = 0;
       unsigned int prec = TYPE_PRECISION (TREE_TYPE (val));
+      wide_int mask (0, prec);
       unsigned int nprec = prec;
       enum tree_code rhs_code = ERROR_MARK;
 
@@ -5101,7 +5101,7 @@ register_edge_assert_for_2 (tree name, e
 	}
       if (names[0] || names[1])
 	{
-	  wide_int minv, maxv = 0, valv, cst2v;
+	  wide_int minv, maxv, valv, cst2v;
 	  wide_int tem, sgnbit;
 	  bool valid_p = false, valn = false, cst2n = false;
 	  enum tree_code ccode = comp_code;
@@ -5170,7 +5170,7 @@ register_edge_assert_for_2 (tree name, e
 		      goto lt_expr;
 		    }
 		  if (!cst2n)
-		    sgnbit = 0;
+		    sgnbit = wide_int::zero (nprec);
 		}
 	      break;
 
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	2013-08-24 12:11:08.085684013 +0100
+++ gcc/tree.c	2013-08-24 01:00:00.000000000 +0100
@@ -1048,13 +1048,13 @@ build_int_cst (tree type, HOST_WIDE_INT
   if (!type)
     type = integer_type_node;
 
-  return wide_int_to_tree (type, low);
+  return wide_int_to_tree (type, wide_int::from_hwi (low, type));
 }
 
 /* static inline */ tree
 build_int_cstu (tree type, unsigned HOST_WIDE_INT cst)
 {
-  return wide_int_to_tree (type, cst);
+  return wide_int_to_tree (type, wide_int::from_hwi (cst, type));
 }
 
 /* Create an INT_CST node with a LOW value sign extended to TYPE.  */
@@ -1064,7 +1064,7 @@ build_int_cst_type (tree type, HOST_WIDE
 {
   gcc_assert (type);
 
-  return wide_int_to_tree (type, low);
+  return wide_int_to_tree (type, wide_int::from_hwi (low, type));
 }
 
 /* Constructs tree in type TYPE from with value given by CST.  Signedness
@@ -10688,7 +10688,7 @@ lower_bound_in_type (tree outer, tree in
 	 contains all values of INNER type.  In particular, both INNER
 	 and OUTER types have zero in common.  */
       || (oprec > iprec && TYPE_UNSIGNED (inner)))
-    return wide_int_to_tree (outer, 0);
+    return build_int_cst (outer, 0);
   else
     {
       /* If we are widening a signed type to another signed type, we
Index: gcc/wide-int.cc
===================================================================
--- gcc/wide-int.cc	2013-08-24 12:48:00.096379386 +0100
+++ gcc/wide-int.cc	2013-08-24 01:00:00.000000000 +0100
@@ -32,6 +32,8 @@ along with GCC; see the file COPYING3.
 const int MAX_SIZE = 4 * (MAX_BITSIZE_MODE_ANY_INT / 4
 		     + MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_WIDE_INT + 32);
 
+static const HOST_WIDE_INT zeros[WIDE_INT_MAX_ELTS] = {};
+
 /*
  * Internal utilities.
  */
@@ -2517,7 +2519,7 @@ wide_int_ro::divmod_internal (bool compu
     {
       if (top_bit_of (dividend, dividend_len, dividend_prec))
 	{
-	  u0 = sub_large (wide_int (0).val, 1,
+	  u0 = sub_large (zeros, 1,
 			  dividend_prec, dividend, dividend_len, UNSIGNED);
 	  dividend = u0.val;
 	  dividend_len = u0.len;
@@ -2525,7 +2527,7 @@ wide_int_ro::divmod_internal (bool compu
 	}
       if (top_bit_of (divisor, divisor_len, divisor_prec))
 	{
-	  u1 = sub_large (wide_int (0).val, 1,
+	  u1 = sub_large (zeros, 1,
 			  divisor_prec, divisor, divisor_len, UNSIGNED);
 	  divisor = u1.val;
 	  divisor_len = u1.len;
Index: gcc/wide-int.h
===================================================================
--- gcc/wide-int.h	2013-08-24 12:14:20.979479335 +0100
+++ gcc/wide-int.h	2013-08-24 01:00:00.000000000 +0100
@@ -230,6 +230,11 @@ #define WIDE_INT_H
 #define DEBUG_WIDE_INT
 #endif
 
+/* Used for overloaded functions in which the only other acceptable
+   scalar type is const_tree.  It stops a plain 0 from being treated
+   as a null tree.  */
+struct never_used {};
+
 /* The MAX_BITSIZE_MODE_ANY_INT is automatically generated by a very
    early examination of the target's mode file.  Thus it is safe that
    some small multiple of this number is easily larger than any number
@@ -324,15 +329,16 @@ class GTY(()) wide_int_ro
 public:
   wide_int_ro ();
   wide_int_ro (const_tree);
-  wide_int_ro (HOST_WIDE_INT);
-  wide_int_ro (int);
-  wide_int_ro (unsigned HOST_WIDE_INT);
-  wide_int_ro (unsigned int);
+  wide_int_ro (never_used *);
+  wide_int_ro (HOST_WIDE_INT, unsigned int);
+  wide_int_ro (int, unsigned int);
+  wide_int_ro (unsigned HOST_WIDE_INT, unsigned int);
+  wide_int_ro (unsigned int, unsigned int);
   wide_int_ro (const rtx_mode_t &);
 
   /* Conversions.  */
-  static wide_int_ro from_shwi (HOST_WIDE_INT, unsigned int = 0);
-  static wide_int_ro from_uhwi (unsigned HOST_WIDE_INT, unsigned int = 0);
+  static wide_int_ro from_shwi (HOST_WIDE_INT, unsigned int);
+  static wide_int_ro from_uhwi (unsigned HOST_WIDE_INT, unsigned int);
   static wide_int_ro from_hwi (HOST_WIDE_INT, const_tree);
   static wide_int_ro from_shwi (HOST_WIDE_INT, enum machine_mode);
   static wide_int_ro from_uhwi (unsigned HOST_WIDE_INT, enum machine_mode);
@@ -349,9 +355,11 @@ class GTY(()) wide_int_ro
 
   static wide_int_ro max_value (unsigned int, signop, unsigned int = 0);
   static wide_int_ro max_value (const_tree);
+  static wide_int_ro max_value (never_used *);
   static wide_int_ro max_value (enum machine_mode, signop);
   static wide_int_ro min_value (unsigned int, signop, unsigned int = 0);
   static wide_int_ro min_value (const_tree);
+  static wide_int_ro min_value (never_used *);
   static wide_int_ro min_value (enum machine_mode, signop);
 
   /* Small constants.  These are generally only needed in the places
@@ -842,18 +850,16 @@ class GTY(()) wide_int : public wide_int
   wide_int ();
   wide_int (const wide_int_ro &);
   wide_int (const_tree);
-  wide_int (HOST_WIDE_INT);
-  wide_int (int);
-  wide_int (unsigned HOST_WIDE_INT);
-  wide_int (unsigned int);
+  wide_int (never_used *);
+  wide_int (HOST_WIDE_INT, unsigned int);
+  wide_int (int, unsigned int);
+  wide_int (unsigned HOST_WIDE_INT, unsigned int);
+  wide_int (unsigned int, unsigned int);
   wide_int (const rtx_mode_t &);
 
   wide_int &operator = (const wide_int_ro &);
   wide_int &operator = (const_tree);
-  wide_int &operator = (HOST_WIDE_INT);
-  wide_int &operator = (int);
-  wide_int &operator = (unsigned HOST_WIDE_INT);
-  wide_int &operator = (unsigned int);
+  wide_int &operator = (never_used *);
   wide_int &operator = (const rtx_mode_t &);
 
   wide_int &operator ++ ();
@@ -904,28 +910,28 @@ inline wide_int_ro::wide_int_ro (const_t
 		      TYPE_PRECISION (TREE_TYPE (tcst)), false);
 }
 
-inline wide_int_ro::wide_int_ro (HOST_WIDE_INT op0)
+inline wide_int_ro::wide_int_ro (HOST_WIDE_INT op0, unsigned int prec)
 {
-  precision = 0;
+  precision = prec;
   val[0] = op0;
   len = 1;
 }
 
-inline wide_int_ro::wide_int_ro (int op0)
+inline wide_int_ro::wide_int_ro (int op0, unsigned int prec)
 {
-  precision = 0;
+  precision = prec;
   val[0] = op0;
   len = 1;
 }
 
-inline wide_int_ro::wide_int_ro (unsigned HOST_WIDE_INT op0)
+inline wide_int_ro::wide_int_ro (unsigned HOST_WIDE_INT op0, unsigned int prec)
 {
-  *this = from_uhwi (op0);
+  *this = from_uhwi (op0, prec);
 }
 
-inline wide_int_ro::wide_int_ro (unsigned int op0)
+inline wide_int_ro::wide_int_ro (unsigned int op0, unsigned int prec)
 {
-  *this = from_uhwi (op0);
+  *this = from_uhwi (op0, prec);
 }
 
 inline wide_int_ro::wide_int_ro (const rtx_mode_t &op0)
@@ -2264,7 +2270,7 @@ wide_int_ro::mul_high (const T &c, signo
 wide_int_ro::operator - () const
 {
   wide_int_ro r;
-  r = wide_int_ro (0) - *this;
+  r = zero (precision) - *this;
   return r;
 }
 
@@ -2277,7 +2283,7 @@ wide_int_ro::neg (bool *overflow) const
 
   *overflow = only_sign_bit_p ();
 
-  return wide_int_ro (0) - *this;
+  return zero (precision) - *this;
 }
 
 /* Return THIS - C.  */
@@ -3147,28 +3153,28 @@ inline wide_int::wide_int (const_tree tc
 		      TYPE_PRECISION (TREE_TYPE (tcst)), false);
 }
 
-inline wide_int::wide_int (HOST_WIDE_INT op0)
+inline wide_int::wide_int (HOST_WIDE_INT op0, unsigned int prec)
 {
-  precision = 0;
+  precision = prec;
   val[0] = op0;
   len = 1;
 }
 
-inline wide_int::wide_int (int op0)
+inline wide_int::wide_int (int op0, unsigned int prec)
 {
-  precision = 0;
+  precision = prec;
   val[0] = op0;
   len = 1;
 }
 
-inline wide_int::wide_int (unsigned HOST_WIDE_INT op0)
+inline wide_int::wide_int (unsigned HOST_WIDE_INT op0, unsigned int prec)
 {
-  *this = wide_int_ro::from_uhwi (op0);
+  *this = wide_int_ro::from_uhwi (op0, prec);
 }
 
-inline wide_int::wide_int (unsigned int op0)
+inline wide_int::wide_int (unsigned int op0, unsigned int prec)
 {
-  *this = wide_int_ro::from_uhwi (op0);
+  *this = wide_int_ro::from_uhwi (op0, prec);
 }
 
 inline wide_int::wide_int (const rtx_mode_t &op0)
@@ -3567,31 +3573,28 @@ inline fixed_wide_int <bitsize>::fixed_w
 
 template <int bitsize>
 inline fixed_wide_int <bitsize>::fixed_wide_int (HOST_WIDE_INT op0)
-  : wide_int_ro (op0)
+  : wide_int_ro (op0, bitsize)
 {
-  precision = bitsize;
 }
 
 template <int bitsize>
-inline fixed_wide_int <bitsize>::fixed_wide_int (int op0) : wide_int_ro (op0)
+inline fixed_wide_int <bitsize>::fixed_wide_int (int op0)
+  : wide_int_ro (op0, bitsize)
 {
-  precision = bitsize;
 }
 
 template <int bitsize>
 inline fixed_wide_int <bitsize>::fixed_wide_int (unsigned HOST_WIDE_INT op0)
-  : wide_int_ro (op0)
+  : wide_int_ro (op0, bitsize)
 {
-  precision = bitsize;
   if (neg_p (SIGNED))
     static_cast <wide_int_ro &> (*this) = zext (HOST_BITS_PER_WIDE_INT);
 }
 
 template <int bitsize>
 inline fixed_wide_int <bitsize>::fixed_wide_int (unsigned int op0)
-  : wide_int_ro (op0)
+  : wide_int_ro (op0, bitsize)
 {
-  precision = bitsize;
   if (sizeof (int) == sizeof (HOST_WIDE_INT)
       && neg_p (SIGNED))
     *this = zext (HOST_BITS_PER_WIDE_INT);
@@ -3661,9 +3664,7 @@ fixed_wide_int <bitsize>::operator = (co
 inline fixed_wide_int <bitsize> &
 fixed_wide_int <bitsize>::operator = (HOST_WIDE_INT op0)
 {
-  static_cast <wide_int_ro &> (*this) = op0;
-  precision = bitsize;
-
+  static_cast <wide_int_ro &> (*this) = wide_int_ro (op0, bitsize);
   return *this;
 }
 
@@ -3671,9 +3672,7 @@ fixed_wide_int <bitsize>::operator = (HO
 inline fixed_wide_int <bitsize> &
 fixed_wide_int <bitsize>::operator = (int op0)
 {
-  static_cast <wide_int_ro &> (*this) = op0;
-  precision = bitsize;
-
+  static_cast <wide_int_ro &> (*this) = wide_int_ro (op0, bitsize);
   return *this;
 }
 
@@ -3681,8 +3680,7 @@ fixed_wide_int <bitsize>::operator = (in
 inline fixed_wide_int <bitsize> &
 fixed_wide_int <bitsize>::operator = (unsigned HOST_WIDE_INT op0)
 {
-  static_cast <wide_int_ro &> (*this) = op0;
-  precision = bitsize;
+  static_cast <wide_int_ro &> (*this) = wide_int_ro (op0, bitsize);
 
   /* This is logically top_bit_set_p.  */
   if (neg_p (SIGNED))
@@ -3695,8 +3693,7 @@ fixed_wide_int <bitsize>::operator = (un
 inline fixed_wide_int <bitsize> &
 fixed_wide_int <bitsize>::operator = (unsigned int op0)
 {
-  static_cast <wide_int_ro &> (*this) = op0;
-  precision = bitsize;
+  static_cast <wide_int_ro &> (*this) = wide_int_ro (op0, bitsize);
 
   if (sizeof (int) == sizeof (HOST_WIDE_INT)
       && neg_p (SIGNED))



More information about the Gcc-patches mailing list