Hi!

extract_muldiv{,_1} is apparently only prepared to handle scalar integer
operations, the callers ensure it by only calling it if the divisor or
one of the multiplicands is INTEGER_CST and because neither multiplication
nor division nor modulo are really supported e.g. for pointer types, nullptr
type etc.  But the CASE_CONVERT handling doesn't really check if it isn't
a cast from some other type kind, so on the testcase we end up trying to
build MULT_EXPR in POINTER_TYPE which ICEs.  A few years ago Marek has
added ANY_INTEGRAL_TYPE_P checks to two spots, but the code uses
TYPE_PRECISION which means something completely different for vector types,
etc.
So IMNSHO we should just punt on conversions from non-integrals or
non-scalar integrals.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk?

2021-03-26  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/99777
        * fold-const.c (extract_muldiv_1): For conversions, punt on casts from
        types other than scalar integral types.

        * g++.dg/torture/pr99777.C: New test.

--- gcc/fold-const.c.jj 2021-03-25 13:41:55.000000000 +0100
+++ gcc/fold-const.c    2021-03-26 11:51:57.901091895 +0100
@@ -6713,6 +6713,8 @@ extract_muldiv_1 (tree t, tree c, enum t
       break;
 
     CASE_CONVERT: case NON_LVALUE_EXPR:
+      if (!INTEGRAL_TYPE_P (TREE_TYPE (op0)))
+       break;
       /* If op0 is an expression ...  */
       if ((COMPARISON_CLASS_P (op0)
           || UNARY_CLASS_P (op0)
@@ -6721,8 +6723,7 @@ extract_muldiv_1 (tree t, tree c, enum t
           || EXPRESSION_CLASS_P (op0))
          /* ... and has wrapping overflow, and its type is smaller
             than ctype, then we cannot pass through as widening.  */
-         && (((ANY_INTEGRAL_TYPE_P (TREE_TYPE (op0))
-               && TYPE_OVERFLOW_WRAPS (TREE_TYPE (op0)))
+         && ((TYPE_OVERFLOW_WRAPS (TREE_TYPE (op0))
               && (TYPE_PRECISION (ctype)
                   > TYPE_PRECISION (TREE_TYPE (op0))))
              /* ... or this is a truncation (t is narrower than op0),
@@ -6737,8 +6738,7 @@ extract_muldiv_1 (tree t, tree c, enum t
              /* ... or has undefined overflow while the converted to
                 type has not, we cannot do the operation in the inner type
                 as that would introduce undefined overflow.  */
-             || ((ANY_INTEGRAL_TYPE_P (TREE_TYPE (op0))
-                  && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0)))
+             || (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0))
                  && !TYPE_OVERFLOW_UNDEFINED (type))))
        break;
 
--- gcc/testsuite/g++.dg/torture/pr99777.C.jj   2021-03-26 12:22:49.833560450 
+0100
+++ gcc/testsuite/g++.dg/torture/pr99777.C      2021-03-26 12:22:37.927692142 
+0100
@@ -0,0 +1,44 @@
+// PR tree-optimization/99777
+
+template <typename T>
+inline const T &
+min (const T &a, const T &b)
+{
+  if (b < a)
+    return b;
+  return a;
+}
+
+template <typename T>
+inline const T &
+max (const T &a, const T &b)
+{
+  if (a < b)
+    return b;
+  return a;
+}
+
+extern int o, a, c;
+long h;
+unsigned long long e;
+signed char d;
+extern short p[][7][5][30];
+
+void
+test (long long b, short f[][17][25][22][20])
+{
+  for (char i = 0; i < 7; i += 3)
+    for (unsigned char l = e; l < 5; l += 2)
+      {
+       if (max (0LL, min (7LL, b)))
+         for (bool j = 0; j < 1; j = b)
+           {
+             for (unsigned k = d; k < 20; k++)
+               h = f[0][i][l][b][k];
+             for (int m = 0; m < 5; m++)
+               p[c][i][l][m] = 0;
+           }
+       for (int n = 0; n < 4; n += a)
+         o = n;
+      }
+}

        Jakub

Reply via email to