aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2021-03-29 12:35:32 +0200
committerJakub Jelinek <jakub@redhat.com>2021-04-22 16:52:49 +0200
commit1ee66d06f25d5bf14e2f3b599fc391dc3d532722 (patch)
tree720806a78fd06a2fd784e47ced0475ab357d1a84
parent698b03a66e5115c5dd5cf84bbb499e210df3e709 (diff)
downloadgcc-1ee66d06f25d5bf14e2f3b599fc391dc3d532722.zip
gcc-1ee66d06f25d5bf14e2f3b599fc391dc3d532722.tar.gz
gcc-1ee66d06f25d5bf14e2f3b599fc391dc3d532722.tar.bz2
fold-const: Fix ICE in extract_muldiv_1 [PR99777]
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. 2021-03-29 Jakub Jelinek <jakub@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. (cherry picked from commit afe9a630eae114665e77402ea083201c9d406e99)
-rw-r--r--gcc/fold-const.c8
-rw-r--r--gcc/testsuite/g++.dg/torture/pr99777.C44
2 files changed, 48 insertions, 4 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 66d705f..30b1d8f 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -6235,6 +6235,8 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
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)
@@ -6243,8 +6245,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
|| 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),
@@ -6259,8 +6260,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
/* ... 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;
diff --git a/gcc/testsuite/g++.dg/torture/pr99777.C b/gcc/testsuite/g++.dg/torture/pr99777.C
new file mode 100644
index 0000000..3cddde5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr99777.C
@@ -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;
+ }
+}