[gcc r14-9440] tree-optimization/114121 - chrec_fold_{plus, multiply} and recursion

Richard Biener rguenth@gcc.gnu.org
Tue Mar 12 14:16:34 GMT 2024


https://gcc.gnu.org/g:73dac51b32575f980289c073969c6d825963d076

commit r14-9440-g73dac51b32575f980289c073969c6d825963d076
Author: Richard Biener <rguenther@suse.de>
Date:   Tue Mar 12 14:00:05 2024 +0100

    tree-optimization/114121 - chrec_fold_{plus,multiply} and recursion
    
    The following addresses endless recursion in the
    chrec_fold_{plus,multiply} functions when handling sign-conversions.
    We only need to apply tricks when we'd fail (there's a chrec in the
    converted operand) and we need to make sure to not turn the other
    operand into something worse (for the chrec-vs-chrec case).
    
            PR tree-optimization/114121
            * tree-chrec.cc (chrec_fold_plus_1): Guard recursion with
            converted operand properly.
            (chrec_fold_multiply): Likewise.  Handle missed recursion.
    
            * gcc.dg/torture/pr114312.c: New testcase.

Diff:
---
 gcc/testsuite/gcc.dg/torture/pr114312.c |  15 +++
 gcc/tree-chrec.cc                       | 176 +++++++++++++++++---------------
 2 files changed, 107 insertions(+), 84 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/torture/pr114312.c b/gcc/testsuite/gcc.dg/torture/pr114312.c
new file mode 100644
index 00000000000..c508c64ed19
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr114312.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target bitint } */
+
+#if __BITINT_MAXWIDTH__ >= 129
+typedef _BitInt(129) B;
+B b;
+
+B
+foo(void)
+{
+  _BitInt(64) a = 1;
+  a &= b * b;
+  return b << a;
+}
+#endif
diff --git a/gcc/tree-chrec.cc b/gcc/tree-chrec.cc
index 7cd0ebc1010..1b2ed753551 100644
--- a/gcc/tree-chrec.cc
+++ b/gcc/tree-chrec.cc
@@ -251,23 +251,27 @@ chrec_fold_plus_1 (enum tree_code code, tree type,
 	  return chrec_fold_plus_poly_poly (code, type, op0, op1);
 
 	CASE_CONVERT:
-	  {
-	    /* We can strip sign-conversions to signed by performing the
-	       operation in unsigned.  */
-	    tree optype = TREE_TYPE (TREE_OPERAND (op1, 0));
-	    if (INTEGRAL_TYPE_P (type)
-		&& INTEGRAL_TYPE_P (optype)
-		&& tree_nop_conversion_p (type, optype)
-		&& TYPE_UNSIGNED (optype))
-	      return chrec_convert (type,
-				    chrec_fold_plus_1 (code, optype,
-						       chrec_convert (optype,
-								      op0, NULL),
-						       TREE_OPERAND (op1, 0)),
-				    NULL);
-	    if (tree_contains_chrecs (op1, NULL))
+	  if (tree_contains_chrecs (op1, NULL))
+	    {
+	      /* We can strip sign-conversions to signed by performing the
+		 operation in unsigned.  */
+	      tree optype = TREE_TYPE (TREE_OPERAND (op1, 0));
+	      if (INTEGRAL_TYPE_P (type)
+		  && INTEGRAL_TYPE_P (optype)
+		  && tree_nop_conversion_p (type, optype)
+		  && TYPE_UNSIGNED (optype))
+		{
+		  tree tem = chrec_convert (optype, op0, NULL);
+		  if (TREE_CODE (tem) == POLYNOMIAL_CHREC)
+		    return chrec_convert (type,
+					  chrec_fold_plus_1 (code, optype,
+							     tem,
+							     TREE_OPERAND
+							       (op1, 0)),
+					  NULL);
+		}
 	      return chrec_dont_know;
-	  }
+	    }
 	  /* FALLTHRU */
 
 	default:
@@ -284,26 +288,27 @@ chrec_fold_plus_1 (enum tree_code code, tree type,
 	}
 
     CASE_CONVERT:
-      {
-	/* We can strip sign-conversions to signed by performing the
-	   operation in unsigned.  */
-	tree optype = TREE_TYPE (TREE_OPERAND (op0, 0));
-	if (INTEGRAL_TYPE_P (type)
-	    && INTEGRAL_TYPE_P (optype)
-	    && tree_nop_conversion_p (type, optype)
-	    && TYPE_UNSIGNED (optype))
-	  return chrec_convert (type,
-				chrec_fold_plus_1 (code, optype,
-						   TREE_OPERAND (op0, 0),
-						   chrec_convert (optype,
-								  op1, NULL)),
-				NULL);
-	if (tree_contains_chrecs (op0, NULL))
+      if (tree_contains_chrecs (op0, NULL))
+	{
+	  /* We can strip sign-conversions to signed by performing the
+	     operation in unsigned.  */
+	  tree optype = TREE_TYPE (TREE_OPERAND (op0, 0));
+	  if (INTEGRAL_TYPE_P (type)
+	      && INTEGRAL_TYPE_P (optype)
+	      && tree_nop_conversion_p (type, optype)
+	      && TYPE_UNSIGNED (optype))
+	    return chrec_convert (type,
+				  chrec_fold_plus_1 (code, optype,
+						     TREE_OPERAND (op0, 0),
+						     chrec_convert (optype,
+								    op1, NULL)),
+				  NULL);
 	  return chrec_dont_know;
-      }
+	}
       /* FALLTHRU */
 
     default:
+      gcc_checking_assert (!tree_contains_chrecs (op0, NULL));
       switch (TREE_CODE (op1))
 	{
 	case POLYNOMIAL_CHREC:
@@ -325,24 +330,24 @@ chrec_fold_plus_1 (enum tree_code code, tree type,
 				    : build_int_cst_type (type, -1)));
 
 	CASE_CONVERT:
-	  {
-	    /* We can strip sign-conversions to signed by performing the
-	       operation in unsigned.  */
-	    tree optype = TREE_TYPE (TREE_OPERAND (op1, 0));
-	    if (INTEGRAL_TYPE_P (type)
-		&& INTEGRAL_TYPE_P (optype)
-		&& tree_nop_conversion_p (type, optype)
-		&& TYPE_UNSIGNED (optype))
-	      return chrec_convert (type,
-				    chrec_fold_plus_1 (code, optype,
-						       chrec_convert (optype,
-								      op0, NULL),
-						       TREE_OPERAND (op1, 0)),
-				    NULL);
-	  }
-
 	  if (tree_contains_chrecs (op1, NULL))
-	    return chrec_dont_know;
+	    {
+	      /* We can strip sign-conversions to signed by performing the
+		 operation in unsigned.  */
+	      tree optype = TREE_TYPE (TREE_OPERAND (op1, 0));
+	      if (INTEGRAL_TYPE_P (type)
+		  && INTEGRAL_TYPE_P (optype)
+		  && tree_nop_conversion_p (type, optype)
+		  && TYPE_UNSIGNED (optype))
+		return chrec_convert (type,
+				      chrec_fold_plus_1 (code, optype,
+							 chrec_convert (optype,
+									op0,
+									NULL),
+							 TREE_OPERAND (op1, 0)),
+				      NULL);
+	      return chrec_dont_know;
+	    }
 	  /* FALLTHRU */
 
 	default:
@@ -440,24 +445,26 @@ chrec_fold_multiply (tree type,
 	  return chrec_fold_multiply_poly_poly (type, op0, op1);
 
 	CASE_CONVERT:
-	  {
-	    /* We can strip sign-conversions to signed by performing the
-	       operation in unsigned.  */
-	    tree optype = TREE_TYPE (TREE_OPERAND (op1, 0));
-	    if (INTEGRAL_TYPE_P (type)
-		&& INTEGRAL_TYPE_P (optype)
-		&& tree_nop_conversion_p (type, optype)
-		&& TYPE_UNSIGNED (optype))
-	      return chrec_convert (type,
-				    chrec_fold_multiply (optype,
-							 chrec_convert (optype,
-									op0, NULL),
-							 TREE_OPERAND (op1, 0)),
-				    NULL);
-	  }
-
 	  if (tree_contains_chrecs (op1, NULL))
-	    return chrec_dont_know;
+	    {
+	      /* We can strip sign-conversions to signed by performing the
+		 operation in unsigned.  */
+	      tree optype = TREE_TYPE (TREE_OPERAND (op1, 0));
+	      if (INTEGRAL_TYPE_P (type)
+		  && INTEGRAL_TYPE_P (optype)
+		  && tree_nop_conversion_p (type, optype)
+		  && TYPE_UNSIGNED (optype))
+		{
+		  tree tem = chrec_convert (optype, op0, NULL);
+		  if (TREE_CODE (tem) == POLYNOMIAL_CHREC)
+		    return chrec_convert (type,
+					  chrec_fold_multiply (optype, tem,
+							       TREE_OPERAND
+								 (op1, 0)),
+					  NULL);
+		}
+	      return chrec_dont_know;
+	    }
 	  /* FALLTHRU */
 
 	default:
@@ -506,27 +513,28 @@ chrec_fold_multiply (tree type,
 	}
 
     CASE_CONVERT:
-      {
-	/* We can strip sign-conversions to signed by performing the
-	   operation in unsigned.  */
-	tree optype = TREE_TYPE (TREE_OPERAND (op0, 0));
-	if (INTEGRAL_TYPE_P (type)
-	    && INTEGRAL_TYPE_P (optype)
-	    && tree_nop_conversion_p (type, optype)
-	    && TYPE_UNSIGNED (optype))
-	  return chrec_convert (type,
-				chrec_fold_multiply (optype,
-						     TREE_OPERAND (op0, 0),
-						     chrec_convert (optype,
-								    op1, NULL)),
-				NULL);
-      }
-
       if (tree_contains_chrecs (op0, NULL))
-	return chrec_dont_know;
+	{
+	  /* We can strip sign-conversions to signed by performing the
+	     operation in unsigned.  */
+	  tree optype = TREE_TYPE (TREE_OPERAND (op0, 0));
+	  if (INTEGRAL_TYPE_P (type)
+	      && INTEGRAL_TYPE_P (optype)
+	      && tree_nop_conversion_p (type, optype)
+	      && TYPE_UNSIGNED (optype))
+	    return chrec_convert (type,
+				  chrec_fold_multiply (optype,
+						       TREE_OPERAND (op0, 0),
+						       chrec_convert (optype,
+								      op1,
+								      NULL)),
+				  NULL);
+	  return chrec_dont_know;
+	}
       /* FALLTHRU */
 
     default:
+      gcc_checking_assert (!tree_contains_chrecs (op0, NULL));
       if (integer_onep (op0))
 	return op1;
 
@@ -540,7 +548,7 @@ chrec_fold_multiply (tree type,
 
 	CASE_CONVERT:
 	  if (tree_contains_chrecs (op1, NULL))
-	    return chrec_dont_know;
+	    return chrec_fold_multiply (type, op1, op0);
 	  /* FALLTHRU */
 
 	default:


More information about the Gcc-cvs mailing list