[gcc(refs/vendors/ARM/heads/arm-struct-reorg-wip)] PR tree-optimization/93986 - ICE on mixed-precision wide_int arguments

Tamar Christina tnfchris@gcc.gnu.org
Fri Jul 17 13:26:17 GMT 2020


https://gcc.gnu.org/g:10bbbb591cfe6cac200e926a73f3b8065147ce84

commit 10bbbb591cfe6cac200e926a73f3b8065147ce84
Author: Martin Sebor <msebor@redhat.com>
Date:   Wed Mar 4 15:14:49 2020 -0700

    PR tree-optimization/93986 - ICE on mixed-precision wide_int arguments
    
    gcc/testsuite/ChangeLog:
    
            PR tree-optimization/93986
            * gcc.dg/pr93986.c: New test.
    
    gcc/ChangeLog:
    
            PR tree-optimization/93986
            * tree-ssa-strlen.c (maybe_warn_overflow): Convert all wide_int
            operands to the same precision widest_int to avoid ICEs.

Diff:
---
 gcc/ChangeLog                  |   6 +++
 gcc/testsuite/ChangeLog        |   5 ++
 gcc/testsuite/gcc.dg/pr93986.c |  16 ++++++
 gcc/tree-ssa-strlen.c          | 110 ++++++++++++++++++++++++++---------------
 4 files changed, 97 insertions(+), 40 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b7c9d86c90c..0df606a8211 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2020-03-04  Martin Sebor  <msebor@redhat.com>
+
+	PR tree-optimization/93986
+	* tree-ssa-strlen.c (maybe_warn_overflow): Convert all wide_int
+	operands to the same precision widest_int to avoid ICEs.
+
 2020-03-04  Bill Schmidt  <wschmidt@linux.ibm.com>
 
 	PR target/87560
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9fcec5abc9e..468f7673e29 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2020-03-04  Martin Sebor  <msebor@redhat.com>
+
+	PR tree-optimization/93986
+        * gcc.dg/pr93986.c: New test.
+
 2020-03-04  David Malcolm  <dmalcolm@redhat.com>
 
 	PR analyzer/94028
diff --git a/gcc/testsuite/gcc.dg/pr93986.c b/gcc/testsuite/gcc.dg/pr93986.c
new file mode 100644
index 00000000000..bdbc192a01d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr93986.c
@@ -0,0 +1,16 @@
+/* PR tree-optimization/93986 - ICE in decompose, at wide-int.h:984
+   { dg-do compile }
+   { dg-options "-O1 -foptimize-strlen -ftree-slp-vectorize" } */
+
+int dd (void);
+
+void ya (int cm)
+{
+  char s2[cm];
+
+  s2[cm-12] = s2[cm-11] = s2[cm-10] = s2[cm-9]
+    = s2[cm-8] = s2[cm-7] = s2[cm-6] = s2[cm-5] = ' ';
+
+  if (dd ())
+    __builtin_exit (0);
+}
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index b76b54efbd8..81be11de797 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -1924,11 +1924,21 @@ maybe_warn_overflow (gimple *stmt, tree len,
   if (TREE_NO_WARNING (dest))
     return;
 
+  /* Use maximum precision to avoid overflow in the addition below.
+     Make sure all operands have the same precision to keep wide_int
+     from ICE'ing.  */
+
+  /* Convenience constants.  */
+  const widest_int diff_min
+    = wi::to_widest (TYPE_MIN_VALUE (ptrdiff_type_node));
+  const widest_int diff_max
+    = wi::to_widest (TYPE_MAX_VALUE (ptrdiff_type_node));
+  const widest_int size_max
+    = wi::to_widest (TYPE_MAX_VALUE (size_type_node));
+
   /* The offset into the destination object computed below and not
      reflected in DESTSIZE.  */
-  wide_int offrng[2];
-  const int off_prec = TYPE_PRECISION (ptrdiff_type_node);
-  offrng[0] = offrng[1] = wi::zero (off_prec);
+  widest_int offrng[2] = { 0, 0 };
 
   if (!si)
     {
@@ -1941,15 +1951,17 @@ maybe_warn_overflow (gimple *stmt, tree len,
 	     ARRAY_REF (MEM_REF (vlaptr, 0), N].  */
 	  tree off = TREE_OPERAND (ref, 1);
 	  ref = TREE_OPERAND (ref, 0);
-	  if (get_range (off, offrng, rvals))
+	  wide_int rng[2];
+	  if (get_range (off, rng, rvals))
 	    {
-	      offrng[0] = offrng[0].from (offrng[0], off_prec, SIGNED);
-	      offrng[1] = offrng[1].from (offrng[1], off_prec, SIGNED);
+	      /* Convert offsets to the maximum precision.  */
+	      offrng[0] = widest_int::from (rng[0], SIGNED);
+	      offrng[1] = widest_int::from (rng[1], SIGNED);
 	    }
 	  else
 	    {
-	      offrng[0] = wi::to_wide (TYPE_MIN_VALUE (ptrdiff_type_node));
-	      offrng[1] = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node));
+	      offrng[0] = diff_min;
+	      offrng[1] = diff_max;
 	    }
 	}
 
@@ -1957,25 +1969,25 @@ maybe_warn_overflow (gimple *stmt, tree len,
 	{
 	  tree mem_off = TREE_OPERAND (ref, 1);
 	  ref = TREE_OPERAND (ref, 0);
-	  wide_int memoffrng[2];
-	  if (get_range (mem_off, memoffrng, rvals))
+	  wide_int rng[2];
+	  if (get_range (mem_off, rng, rvals))
 	    {
-	      offrng[0] += memoffrng[0];
-	      offrng[1] += memoffrng[1];
+	      offrng[0] += widest_int::from (rng[0], SIGNED);
+	      offrng[1] += widest_int::from (rng[1], SIGNED);
 	    }
 	  else
 	    {
-	      offrng[0] = wi::to_wide (TYPE_MIN_VALUE (ptrdiff_type_node));
-	      offrng[1] = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node));
+	      offrng[0] = diff_min;
+	      offrng[1] = diff_max;
 	    }
 	}
 
-      wide_int stroffrng[2];
-      if (int idx = get_stridx (ref, stroffrng, rvals))
+      wide_int rng[2];
+      if (int idx = get_stridx (ref, rng, rvals))
 	{
 	  si = get_strinfo (idx);
-	  offrng[0] += stroffrng[0];
-	  offrng[1] += stroffrng[1];
+	  offrng[0] += widest_int::from (rng[0], SIGNED);
+	  offrng[1] += widest_int::from (rng[1], SIGNED);
 	}
     }
 
@@ -1995,15 +2007,20 @@ maybe_warn_overflow (gimple *stmt, tree len,
   /* Compute the range of sizes of the destination object.  The range
      is constant for declared objects but may be a range for allocated
      objects.  */
-  const int siz_prec = TYPE_PRECISION (size_type_node);
-  wide_int sizrng[2];
+  widest_int sizrng[2] = { 0, 0 };
   if (si)
     {
-      destsize = gimple_call_alloc_size (si->alloc, sizrng, rvals);
+      wide_int rng[2];
+      destsize = gimple_call_alloc_size (si->alloc, rng, rvals);
+      if (destsize)
+	{
+	  sizrng[0] = widest_int::from (rng[0], UNSIGNED);
+	  sizrng[1] = widest_int::from (rng[1], UNSIGNED);
+	}
       alloc_call = si->alloc;
     }
   else
-    offrng[0] = offrng[1] = wi::zero (off_prec);
+    offrng[0] = offrng[1] = 0;
 
   if (!destsize)
     {
@@ -2014,7 +2031,7 @@ maybe_warn_overflow (gimple *stmt, tree len,
 	{
 	  /* Remember OFF but clear OFFRNG that may have been set above.  */
 	  destoff = off;
-	  offrng[0] = offrng[1] = wi::zero (off_prec);
+	  offrng[0] = offrng[1] = 0;
 
 	  if (destdecl && TREE_CODE (destdecl) == SSA_NAME)
 	    {
@@ -2024,27 +2041,30 @@ maybe_warn_overflow (gimple *stmt, tree len,
 	      destdecl = NULL_TREE;
 	    }
 
-	  if (!get_range (destsize, sizrng, rvals))
+	  wide_int rng[2];
+	  if (get_range (destsize, rng, rvals))
+	    {
+	      sizrng[0] = widest_int::from (rng[0], UNSIGNED);
+	      sizrng[1] = widest_int::from (rng[1], UNSIGNED);
+	    }
+	  else
 	    {
 	      /* On failure, rather than failing, set the maximum range
 		 so that overflow in allocated objects whose size depends
 		 on the strlen of the source can still be diagnosed
 		 below.  */
-	      sizrng[0] = wi::zero (siz_prec);
-	      sizrng[1] = wi::to_wide (TYPE_MAX_VALUE (sizetype));
+	      sizrng[0] = 0;
+	      sizrng[1] = size_max;
 	    }
 	}
     }
 
   if (!destsize)
     {
-      sizrng[0] = wi::zero (siz_prec);
-      sizrng[1] = wi::to_wide (TYPE_MAX_VALUE (sizetype));
+      sizrng[0] = 0;
+      sizrng[1] = size_max;
     };
 
-  sizrng[0] = sizrng[0].from (sizrng[0], siz_prec, UNSIGNED);
-  sizrng[1] = sizrng[1].from (sizrng[1], siz_prec, UNSIGNED);
-
   /* Return early if the DESTSIZE size expression is the same as LEN
      and the offset into the destination is zero.  This might happen
      in the case of a pair of malloc and memset calls to allocate
@@ -2052,10 +2072,13 @@ maybe_warn_overflow (gimple *stmt, tree len,
   if (destsize == len && !plus_one && offrng[0] == 0 && offrng[0] == offrng[1])
     return;
 
-  wide_int lenrng[2];
-  if (!get_range (len, lenrng, rvals))
+  wide_int rng[2];
+  if (!get_range (len, rng, rvals))
     return;
 
+  widest_int lenrng[2] =
+    { widest_int::from (rng[0], SIGNED), widest_int::from (rng[1], SIGNED) };
+
   if (plus_one)
     {
       lenrng[0] += 1;
@@ -2064,7 +2087,7 @@ maybe_warn_overflow (gimple *stmt, tree len,
 
   /* The size of the remaining space in the destination computed
      as the size of the latter minus the offset into it.  */
-  wide_int spcrng[2] = { sizrng[0], sizrng[1] };
+  widest_int spcrng[2] = { sizrng[0], sizrng[1] };
   if (wi::neg_p (offrng[0]) && wi::neg_p (offrng[1]))
     {
       /* When the offset is negative and the size of the destination
@@ -2075,7 +2098,7 @@ maybe_warn_overflow (gimple *stmt, tree len,
 	return;
 
       /* The remaining space is necessarily zero.  */
-      spcrng[0] = spcrng[1] = wi::zero (spcrng->get_precision ());
+      spcrng[0] = spcrng[1] = 0;
     }
   else if (wi::neg_p (offrng[0]))
     {
@@ -2203,7 +2226,16 @@ maybe_warn_overflow (gimple *stmt, tree len,
 
   /* If DESTOFF is not null, use it to format the offset value/range.  */
   if (destoff)
-    get_range (destoff, offrng);
+    {
+      wide_int rng[2];
+      if (get_range (destoff, rng))
+	{
+	  offrng[0] = widest_int::from (rng[0], SIGNED);
+	  offrng[1] = widest_int::from (rng[1], SIGNED);
+	}
+      else
+	offrng[0] = offrng[1] = 0;
+    }
 
   /* Format the offset to keep the number of inform calls from growing
      out of control.  */
@@ -2259,8 +2291,7 @@ maybe_warn_overflow (gimple *stmt, tree len,
       else if (sizrng[0] == 0)
 	{
 	  /* Avoid printing impossible sizes.  */
-	  if (wi::ltu_p (sizrng[1],
-			 wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node)) - 2))
+	  if (wi::ltu_p (sizrng[1], diff_max - 2))
 	    inform (gimple_location (alloc_call),
 		    "at offset %s to an object with size at most %wu "
 		    "declared here",
@@ -2284,8 +2315,7 @@ maybe_warn_overflow (gimple *stmt, tree len,
   else if (sizrng[0] == 0)
     {
       /* Avoid printing impossible sizes.  */
-      if (wi::ltu_p (sizrng[1],
-		     wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node)) - 2))
+      if (wi::ltu_p (sizrng[1], diff_max - 2))
 	inform (gimple_location (alloc_call),
 		"at offset %s to an object with size at most %wu allocated "
 		"by %qD here",


More information about the Gcc-cvs mailing list