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

commit r14-9440-g73dac51b32575f980289c073969c6d825963d076
Author: Richard Biener <rguent...@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:

Reply via email to