wide-int, v2: Fix estimation of buffer sizes for wide_int printing [PR111800]

Message ID ZSpkVdv/G5isFzXv@tucnak
State Unresolved
Headers
Series wide-int, v2: Fix estimation of buffer sizes for wide_int printing [PR111800] |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Jakub Jelinek Oct. 14, 2023, 9:50 a.m. UTC
  Hi!

On Sat, Oct 14, 2023 at 10:41:28AM +0200, Richard Biener wrote:
> Can we somehow abstract this common pattern?

So like this?  With room for the future tweaks like printing decimal
instead of hex numbers by print_dec*, where we'd only need to adjust
the inlines.  The XALLOCAVEC call is left for the callers, those would
make the inlines uninlinable and not doing what they should.

2023-10-14  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/111800
gcc/
	* wide-int-print.h (print_dec_buf_size, print_decs_buf_size,
	print_decu_buf_size, print_hex_buf_size): New inline functions.
	* wide-int.cc (assert_deceq): Use print_dec_buf_size.
	(assert_hexeq): Use print_hex_buf_size.
	* wide-int-print.cc (print_decs): Use print_decs_buf_size.
	(print_decu): Use print_decu_buf_size.
	(print_hex): Use print_hex_buf_size.
	(pp_wide_int_large): Use print_dec_buf_size.
	* value-range.cc (irange_bitmask::dump): Use print_hex_buf_size.
	* value-range-pretty-print.cc (vrange_printer::print_irange_bitmasks):
	Likewise.
	* tree-ssa-loop-niter.cc (do_warn_aggressive_loop_optimizations): Use
	print_dec_buf_size.  Use TYPE_SIGN macro in print_dec call argument.
gcc/c-family/
	* c-warn.cc (match_case_to_enum_1): Assert w.get_precision ()
	is smaller or equal to WIDE_INT_MAX_INL_PRECISION rather than
	w.get_len () is smaller or equal to WIDE_INT_MAX_INL_ELTS.



	Jakub
  

Comments

Richard Biener Oct. 14, 2023, 10:49 a.m. UTC | #1
> Am 14.10.2023 um 11:50 schrieb Jakub Jelinek <jakub@redhat.com>:
> 
> Hi!
> 
>> On Sat, Oct 14, 2023 at 10:41:28AM +0200, Richard Biener wrote:
>> Can we somehow abstract this common pattern?
> 
> So like this?  With room for the future tweaks like printing decimal
> instead of hex numbers by print_dec*, where we'd only need to adjust
> the inlines.  The XALLOCAVEC call is left for the callers, those would
> make the inlines uninlinable and not doing what they should.

LGTM.

Richard 

> 2023-10-14  Jakub Jelinek  <jakub@redhat.com>
> 
>    PR tree-optimization/111800
> gcc/
>    * wide-int-print.h (print_dec_buf_size, print_decs_buf_size,
>    print_decu_buf_size, print_hex_buf_size): New inline functions.
>    * wide-int.cc (assert_deceq): Use print_dec_buf_size.
>    (assert_hexeq): Use print_hex_buf_size.
>    * wide-int-print.cc (print_decs): Use print_decs_buf_size.
>    (print_decu): Use print_decu_buf_size.
>    (print_hex): Use print_hex_buf_size.
>    (pp_wide_int_large): Use print_dec_buf_size.
>    * value-range.cc (irange_bitmask::dump): Use print_hex_buf_size.
>    * value-range-pretty-print.cc (vrange_printer::print_irange_bitmasks):
>    Likewise.
>    * tree-ssa-loop-niter.cc (do_warn_aggressive_loop_optimizations): Use
>    print_dec_buf_size.  Use TYPE_SIGN macro in print_dec call argument.
> gcc/c-family/
>    * c-warn.cc (match_case_to_enum_1): Assert w.get_precision ()
>    is smaller or equal to WIDE_INT_MAX_INL_PRECISION rather than
>    w.get_len () is smaller or equal to WIDE_INT_MAX_INL_ELTS.
> 
> --- gcc/wide-int-print.h.jj    2023-10-13 19:34:44.283830089 +0200
> +++ gcc/wide-int-print.h    2023-10-14 11:21:44.190603091 +0200
> @@ -36,4 +36,40 @@ extern void print_hex (const wide_int_re
> extern void print_hex (const wide_int_ref &wi, FILE *file);
> extern void pp_wide_int_large (pretty_printer *, const wide_int_ref &, signop);
> 
> +inline bool
> +print_dec_buf_size (const wide_int_ref &wi, signop sgn, unsigned int *len)
> +{
> +  unsigned int l = wi.get_len ();
> +  if ((l != 1 || sgn == UNSIGNED) && wi::neg_p (wi))
> +    l = WIDE_INT_MAX_HWIS (wi.get_precision ());
> +  l = l * HOST_BITS_PER_WIDE_INT / 4 + 4;
> +  *len = l;
> +  return UNLIKELY (l > WIDE_INT_PRINT_BUFFER_SIZE);
> +}
> +
> +inline bool
> +print_decs_buf_size (const wide_int_ref &wi, unsigned int *len)
> +{
> +  return print_dec_buf_size (wi, SIGNED, len);
> +}
> +
> +inline bool
> +print_decu_buf_size (const wide_int_ref &wi, unsigned int *len)
> +{
> +  return print_dec_buf_size (wi, UNSIGNED, len);
> +}
> +
> +inline bool
> +print_hex_buf_size (const wide_int_ref &wi, unsigned int *len)
> +{
> +  unsigned int l;
> +  if (wi::neg_p (wi))
> +    l = WIDE_INT_MAX_HWIS (wi.get_precision ());
> +  else
> +    l = wi.get_len ();
> +  l = l * HOST_BITS_PER_WIDE_INT / 4 + 4;
> +  *len = l;
> +  return UNLIKELY (l > WIDE_INT_PRINT_BUFFER_SIZE);
> +}
> +
> #endif /* WIDE_INT_PRINT_H */
> --- gcc/wide-int.cc.jj    2023-10-14 11:07:52.738850767 +0200
> +++ gcc/wide-int.cc    2023-10-14 11:22:03.100347386 +0200
> @@ -2450,9 +2450,9 @@ static void
> assert_deceq (const char *expected, const wide_int_ref &wi, signop sgn)
> {
>   char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
> -  unsigned len = wi.get_len ();
> -  if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
> -    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
> +  unsigned len;
> +  if (print_dec_buf_size (wi, sgn, &len))
> +    p = XALLOCAVEC (char, len);
>   print_dec (wi, p, sgn);
>   ASSERT_STREQ (expected, p);
> }
> @@ -2463,9 +2463,9 @@ static void
> assert_hexeq (const char *expected, const wide_int_ref &wi)
> {
>   char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
> -  unsigned len = wi.get_len ();
> -  if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
> -    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
> +  unsigned len;
> +  if (print_hex_buf_size (wi, &len))
> +    p = XALLOCAVEC (char, len);
>   print_hex (wi, p);
>   ASSERT_STREQ (expected, p);
> }
> --- gcc/wide-int-print.cc.jj    2023-10-14 11:07:52.737850781 +0200
> +++ gcc/wide-int-print.cc    2023-10-14 11:37:43.994623668 +0200
> @@ -75,9 +75,9 @@ void
> print_decs (const wide_int_ref &wi, FILE *file)
> {
>   char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
> -  unsigned len = wi.get_len ();
> -  if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
> -    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
> +  unsigned len;
> +  if (print_decs_buf_size (wi, &len))
> +    p = XALLOCAVEC (char, len);
>   print_decs (wi, p);
>   fputs (p, file);
> }
> @@ -102,9 +102,9 @@ void
> print_decu (const wide_int_ref &wi, FILE *file)
> {
>   char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
> -  unsigned len = wi.get_len ();
> -  if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
> -    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
> +  unsigned len;
> +  if (print_decu_buf_size (wi, &len))
> +    p = XALLOCAVEC (char, len);
>   print_decu (wi, p);
>   fputs (p, file);
> }
> @@ -141,9 +141,9 @@ void
> print_hex (const wide_int_ref &wi, FILE *file)
> {
>   char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
> -  unsigned len = wi.get_len ();
> -  if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
> -    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
> +  unsigned len;
> +  if (print_hex_buf_size (wi, &len))
> +    p = XALLOCAVEC (char, len);
>   print_hex (wi, p);
>   fputs (p, file);
> }
> @@ -154,8 +154,10 @@ print_hex (const wide_int_ref &wi, FILE
> void
> pp_wide_int_large (pretty_printer *pp, const wide_int_ref &w, signop sgn)
> {
> -  unsigned int prec = w.get_precision ();
> -  char *buf = XALLOCAVEC (char, (prec + 3) / 4 + 3);
> +  unsigned int len;
> +  if (!print_dec_buf_size (w, sgn, &len))
> +    len = WIDE_INT_PRINT_BUFFER_SIZE;
> +  char *buf = XALLOCAVEC (char, len);
>   print_dec (w, buf, sgn);
>   pp_string (pp, buf);
> }
> --- gcc/value-range.cc.jj    2023-10-14 11:07:52.737850781 +0200
> +++ gcc/value-range.cc    2023-10-14 11:26:02.656108017 +0200
> @@ -251,11 +251,10 @@ irange_bitmask::dump (FILE *file) const
>   pp_needs_newline (&buffer) = true;
>   buffer.buffer->stream = file;
>   pp_string (&buffer, "MASK ");
> -  unsigned len_mask = m_mask.get_len ();
> -  unsigned len_val = m_value.get_len ();
> -  unsigned len = MAX (len_mask, len_val);
> -  if (len > WIDE_INT_MAX_INL_ELTS)
> -    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
> +  unsigned len_mask, len_val;
> +  if (print_hex_buf_size (m_mask, &len_mask)
> +      || print_hex_buf_size (m_value, &len_val))
> +    p = XALLOCAVEC (char, MAX (len_mask, len_val));
>   else
>     p = buf;
>   print_hex (m_mask, p);
> --- gcc/value-range-pretty-print.cc.jj    2023-10-14 11:07:52.735850808 +0200
> +++ gcc/value-range-pretty-print.cc    2023-10-14 11:26:46.084520752 +0200
> @@ -100,11 +100,10 @@ vrange_printer::print_irange_bitmasks (c
> 
>   pp_string (pp, " MASK ");
>   char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p;
> -  unsigned len_mask = bm.mask ().get_len ();
> -  unsigned len_val = bm.value ().get_len ();
> -  unsigned len = MAX (len_mask, len_val);
> -  if (len > WIDE_INT_MAX_INL_ELTS)
> -    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
> +  unsigned len_mask, len_val;
> +  if (print_hex_buf_size (bm.mask (), &len_mask)
> +      || print_hex_buf_size (bm.value (), &len_val))
> +    p = XALLOCAVEC (char, MAX (len_mask, len_val));
>   else
>     p = buf;
>   print_hex (bm.mask (), p);
> --- gcc/tree-ssa-loop-niter.cc.jj    2023-10-14 11:07:52.732850849 +0200
> +++ gcc/tree-ssa-loop-niter.cc    2023-10-14 11:27:58.299544234 +0200
> @@ -3874,13 +3874,13 @@ do_warn_aggressive_loop_optimizations (c
> 
>   gimple *estmt = last_nondebug_stmt (e->src);
>   char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p;
> -  unsigned len = i_bound.get_len ();
> -  if (len > WIDE_INT_MAX_INL_ELTS)
> -    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
> +  unsigned len;
> +  if (print_dec_buf_size (i_bound, TYPE_SIGN (TREE_TYPE (loop->nb_iterations)),
> +              &len))
> +    p = XALLOCAVEC (char, len);
>   else
>     p = buf;
> -  print_dec (i_bound, p, TYPE_UNSIGNED (TREE_TYPE (loop->nb_iterations))
> -         ? UNSIGNED : SIGNED);
> +  print_dec (i_bound, p, TYPE_SIGN (TREE_TYPE (loop->nb_iterations)));
>   auto_diagnostic_group d;
>   if (warning_at (gimple_location (stmt), OPT_Waggressive_loop_optimizations,
>          "iteration %s invokes undefined behavior", p))
> --- gcc/c-family/c-warn.cc.jj    2023-10-14 11:07:52.720851011 +0200
> +++ gcc/c-family/c-warn.cc    2023-10-14 11:08:38.493231623 +0200
> @@ -1519,7 +1519,7 @@ match_case_to_enum_1 (tree key, tree typ
>   char buf[WIDE_INT_PRINT_BUFFER_SIZE];
>   wide_int w = wi::to_wide (key);
> 
> -  gcc_assert (w.get_len () <= WIDE_INT_MAX_INL_ELTS);
> +  gcc_assert (w.get_precision () <= WIDE_INT_MAX_INL_PRECISION);
>   if (tree_fits_uhwi_p (key))
>     print_dec (w, buf, UNSIGNED);
>   else if (tree_fits_shwi_p (key))
> 
> 
>    Jakub
>
  

Patch

--- gcc/wide-int-print.h.jj	2023-10-13 19:34:44.283830089 +0200
+++ gcc/wide-int-print.h	2023-10-14 11:21:44.190603091 +0200
@@ -36,4 +36,40 @@  extern void print_hex (const wide_int_re
 extern void print_hex (const wide_int_ref &wi, FILE *file);
 extern void pp_wide_int_large (pretty_printer *, const wide_int_ref &, signop);
 
+inline bool
+print_dec_buf_size (const wide_int_ref &wi, signop sgn, unsigned int *len)
+{
+  unsigned int l = wi.get_len ();
+  if ((l != 1 || sgn == UNSIGNED) && wi::neg_p (wi))
+    l = WIDE_INT_MAX_HWIS (wi.get_precision ());
+  l = l * HOST_BITS_PER_WIDE_INT / 4 + 4;
+  *len = l;
+  return UNLIKELY (l > WIDE_INT_PRINT_BUFFER_SIZE);
+}
+
+inline bool
+print_decs_buf_size (const wide_int_ref &wi, unsigned int *len)
+{
+  return print_dec_buf_size (wi, SIGNED, len);
+}
+
+inline bool
+print_decu_buf_size (const wide_int_ref &wi, unsigned int *len)
+{
+  return print_dec_buf_size (wi, UNSIGNED, len);
+}
+
+inline bool
+print_hex_buf_size (const wide_int_ref &wi, unsigned int *len)
+{
+  unsigned int l;
+  if (wi::neg_p (wi))
+    l = WIDE_INT_MAX_HWIS (wi.get_precision ());
+  else
+    l = wi.get_len ();
+  l = l * HOST_BITS_PER_WIDE_INT / 4 + 4;
+  *len = l;
+  return UNLIKELY (l > WIDE_INT_PRINT_BUFFER_SIZE);
+}
+
 #endif /* WIDE_INT_PRINT_H */
--- gcc/wide-int.cc.jj	2023-10-14 11:07:52.738850767 +0200
+++ gcc/wide-int.cc	2023-10-14 11:22:03.100347386 +0200
@@ -2450,9 +2450,9 @@  static void
 assert_deceq (const char *expected, const wide_int_ref &wi, signop sgn)
 {
   char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
-  unsigned len = wi.get_len ();
-  if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
-    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+  unsigned len;
+  if (print_dec_buf_size (wi, sgn, &len))
+    p = XALLOCAVEC (char, len);
   print_dec (wi, p, sgn);
   ASSERT_STREQ (expected, p);
 }
@@ -2463,9 +2463,9 @@  static void
 assert_hexeq (const char *expected, const wide_int_ref &wi)
 {
   char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
-  unsigned len = wi.get_len ();
-  if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
-    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+  unsigned len;
+  if (print_hex_buf_size (wi, &len))
+    p = XALLOCAVEC (char, len);
   print_hex (wi, p);
   ASSERT_STREQ (expected, p);
 }
--- gcc/wide-int-print.cc.jj	2023-10-14 11:07:52.737850781 +0200
+++ gcc/wide-int-print.cc	2023-10-14 11:37:43.994623668 +0200
@@ -75,9 +75,9 @@  void
 print_decs (const wide_int_ref &wi, FILE *file)
 {
   char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
-  unsigned len = wi.get_len ();
-  if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
-    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+  unsigned len;
+  if (print_decs_buf_size (wi, &len))
+    p = XALLOCAVEC (char, len);
   print_decs (wi, p);
   fputs (p, file);
 }
@@ -102,9 +102,9 @@  void
 print_decu (const wide_int_ref &wi, FILE *file)
 {
   char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
-  unsigned len = wi.get_len ();
-  if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
-    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+  unsigned len;
+  if (print_decu_buf_size (wi, &len))
+    p = XALLOCAVEC (char, len);
   print_decu (wi, p);
   fputs (p, file);
 }
@@ -141,9 +141,9 @@  void
 print_hex (const wide_int_ref &wi, FILE *file)
 {
   char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
-  unsigned len = wi.get_len ();
-  if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
-    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+  unsigned len;
+  if (print_hex_buf_size (wi, &len))
+    p = XALLOCAVEC (char, len);
   print_hex (wi, p);
   fputs (p, file);
 }
@@ -154,8 +154,10 @@  print_hex (const wide_int_ref &wi, FILE
 void
 pp_wide_int_large (pretty_printer *pp, const wide_int_ref &w, signop sgn)
 {
-  unsigned int prec = w.get_precision ();
-  char *buf = XALLOCAVEC (char, (prec + 3) / 4 + 3);
+  unsigned int len;
+  if (!print_dec_buf_size (w, sgn, &len))
+    len = WIDE_INT_PRINT_BUFFER_SIZE;
+  char *buf = XALLOCAVEC (char, len);
   print_dec (w, buf, sgn);
   pp_string (pp, buf);
 }
--- gcc/value-range.cc.jj	2023-10-14 11:07:52.737850781 +0200
+++ gcc/value-range.cc	2023-10-14 11:26:02.656108017 +0200
@@ -251,11 +251,10 @@  irange_bitmask::dump (FILE *file) const
   pp_needs_newline (&buffer) = true;
   buffer.buffer->stream = file;
   pp_string (&buffer, "MASK ");
-  unsigned len_mask = m_mask.get_len ();
-  unsigned len_val = m_value.get_len ();
-  unsigned len = MAX (len_mask, len_val);
-  if (len > WIDE_INT_MAX_INL_ELTS)
-    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+  unsigned len_mask, len_val;
+  if (print_hex_buf_size (m_mask, &len_mask)
+      || print_hex_buf_size (m_value, &len_val))
+    p = XALLOCAVEC (char, MAX (len_mask, len_val));
   else
     p = buf;
   print_hex (m_mask, p);
--- gcc/value-range-pretty-print.cc.jj	2023-10-14 11:07:52.735850808 +0200
+++ gcc/value-range-pretty-print.cc	2023-10-14 11:26:46.084520752 +0200
@@ -100,11 +100,10 @@  vrange_printer::print_irange_bitmasks (c
 
   pp_string (pp, " MASK ");
   char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p;
-  unsigned len_mask = bm.mask ().get_len ();
-  unsigned len_val = bm.value ().get_len ();
-  unsigned len = MAX (len_mask, len_val);
-  if (len > WIDE_INT_MAX_INL_ELTS)
-    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+  unsigned len_mask, len_val;
+  if (print_hex_buf_size (bm.mask (), &len_mask)
+      || print_hex_buf_size (bm.value (), &len_val))
+    p = XALLOCAVEC (char, MAX (len_mask, len_val));
   else
     p = buf;
   print_hex (bm.mask (), p);
--- gcc/tree-ssa-loop-niter.cc.jj	2023-10-14 11:07:52.732850849 +0200
+++ gcc/tree-ssa-loop-niter.cc	2023-10-14 11:27:58.299544234 +0200
@@ -3874,13 +3874,13 @@  do_warn_aggressive_loop_optimizations (c
 
   gimple *estmt = last_nondebug_stmt (e->src);
   char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p;
-  unsigned len = i_bound.get_len ();
-  if (len > WIDE_INT_MAX_INL_ELTS)
-    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+  unsigned len;
+  if (print_dec_buf_size (i_bound, TYPE_SIGN (TREE_TYPE (loop->nb_iterations)),
+			  &len))
+    p = XALLOCAVEC (char, len);
   else
     p = buf;
-  print_dec (i_bound, p, TYPE_UNSIGNED (TREE_TYPE (loop->nb_iterations))
-	     ? UNSIGNED : SIGNED);
+  print_dec (i_bound, p, TYPE_SIGN (TREE_TYPE (loop->nb_iterations)));
   auto_diagnostic_group d;
   if (warning_at (gimple_location (stmt), OPT_Waggressive_loop_optimizations,
 		  "iteration %s invokes undefined behavior", p))
--- gcc/c-family/c-warn.cc.jj	2023-10-14 11:07:52.720851011 +0200
+++ gcc/c-family/c-warn.cc	2023-10-14 11:08:38.493231623 +0200
@@ -1519,7 +1519,7 @@  match_case_to_enum_1 (tree key, tree typ
   char buf[WIDE_INT_PRINT_BUFFER_SIZE];
   wide_int w = wi::to_wide (key);
 
-  gcc_assert (w.get_len () <= WIDE_INT_MAX_INL_ELTS);
+  gcc_assert (w.get_precision () <= WIDE_INT_MAX_INL_PRECISION);
   if (tree_fits_uhwi_p (key))
     print_dec (w, buf, UNSIGNED);
   else if (tree_fits_shwi_p (key))