aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/builtins.c26
-rw-r--r--gcc/fold-const.c262
-rw-r--r--gcc/fold-const.h7
-rw-r--r--gcc/match.pd20
-rw-r--r--gcc/testsuite/gcc.dg/fold-isfinite-1.c21
-rw-r--r--gcc/testsuite/gcc.dg/fold-isfinite-2.c21
-rw-r--r--gcc/testsuite/gcc.dg/fold-isinf-1.c21
-rw-r--r--gcc/testsuite/gcc.dg/fold-isinf-2.c21
-rw-r--r--gcc/testsuite/gcc.dg/fold-isnan-1.c21
-rw-r--r--gcc/testsuite/gcc.dg/fold-isnan-2.c21
-rw-r--r--gcc/testsuite/gcc.dg/pr85811.c15
11 files changed, 443 insertions, 13 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 42c52a1..a75b24c 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -10691,9 +10691,10 @@ fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
switch (builtin_index)
{
case BUILT_IN_ISINF:
- if (!HONOR_INFINITIES (arg))
+ if (tree_expr_infinite_p (arg))
+ return omit_one_operand_loc (loc, type, integer_one_node, arg);
+ if (!tree_expr_maybe_infinite_p (arg))
return omit_one_operand_loc (loc, type, integer_zero_node, arg);
-
return NULL_TREE;
case BUILT_IN_ISINF_SIGN:
@@ -10729,14 +10730,16 @@ fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
}
case BUILT_IN_ISFINITE:
- if (!HONOR_NANS (arg)
- && !HONOR_INFINITIES (arg))
+ if (tree_expr_finite_p (arg))
return omit_one_operand_loc (loc, type, integer_one_node, arg);
-
+ if (tree_expr_nan_p (arg) || tree_expr_infinite_p (arg))
+ return omit_one_operand_loc (loc, type, integer_zero_node, arg);
return NULL_TREE;
case BUILT_IN_ISNAN:
- if (!HONOR_NANS (arg))
+ if (tree_expr_nan_p (arg))
+ return omit_one_operand_loc (loc, type, integer_one_node, arg);
+ if (!tree_expr_maybe_nan_p (arg))
return omit_one_operand_loc (loc, type, integer_zero_node, arg);
{
@@ -10810,7 +10813,7 @@ fold_builtin_fpclassify (location_t loc, tree *args, int nargs)
arg, build_real (type, r));
res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, fp_normal, res);
- if (HONOR_INFINITIES (mode))
+ if (tree_expr_maybe_infinite_p (arg))
{
real_inf (&r);
tmp = fold_build2_loc (loc, EQ_EXPR, integer_type_node, arg,
@@ -10819,7 +10822,7 @@ fold_builtin_fpclassify (location_t loc, tree *args, int nargs)
fp_infinite, res);
}
- if (HONOR_NANS (mode))
+ if (tree_expr_maybe_nan_p (arg))
{
tmp = fold_build2_loc (loc, ORDERED_EXPR, integer_type_node, arg, arg);
res = fold_build3_loc (loc, COND_EXPR, integer_type_node, tmp, res, fp_nan);
@@ -10867,12 +10870,15 @@ fold_builtin_unordered_cmp (location_t loc, tree fndecl, tree arg0, tree arg1,
if (unordered_code == UNORDERED_EXPR)
{
- if (!HONOR_NANS (arg0))
+ if (tree_expr_nan_p (arg0) || tree_expr_nan_p (arg1))
+ return omit_two_operands_loc (loc, type, integer_one_node, arg0, arg1);
+ if (!tree_expr_maybe_nan_p (arg0) && !tree_expr_maybe_nan_p (arg1))
return omit_two_operands_loc (loc, type, integer_zero_node, arg0, arg1);
return fold_build2_loc (loc, UNORDERED_EXPR, type, arg0, arg1);
}
- code = HONOR_NANS (arg0) ? unordered_code : ordered_code;
+ code = (tree_expr_maybe_nan_p (arg0) || tree_expr_maybe_nan_p (arg1))
+ ? unordered_code : ordered_code;
return fold_build1_loc (loc, TRUTH_NOT_EXPR, type,
fold_build2_loc (loc, code, type, arg0, arg1));
}
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index ddf18f2..31c48da 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -13701,6 +13701,248 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
}
}
+/* Return true if expression X cannot be (or contain) a NaN or infinity.
+ This function returns true for integer expressions, and returns
+ false if uncertain. */
+
+bool
+tree_expr_finite_p (const_tree x)
+{
+ machine_mode mode = element_mode (x);
+ if (!HONOR_NANS (mode) && !HONOR_INFINITIES (mode))
+ return true;
+ switch (TREE_CODE (x))
+ {
+ case REAL_CST:
+ return real_isfinite (TREE_REAL_CST_PTR (x));
+ case COMPLEX_CST:
+ return tree_expr_finite_p (TREE_REALPART (x))
+ && tree_expr_finite_p (TREE_IMAGPART (x));
+ case FLOAT_EXPR:
+ return true;
+ case ABS_EXPR:
+ case CONVERT_EXPR:
+ case NON_LVALUE_EXPR:
+ case NEGATE_EXPR:
+ case SAVE_EXPR:
+ return tree_expr_finite_p (TREE_OPERAND (x, 0));
+ case MIN_EXPR:
+ case MAX_EXPR:
+ return tree_expr_finite_p (TREE_OPERAND (x, 0))
+ && tree_expr_finite_p (TREE_OPERAND (x, 1));
+ case COND_EXPR:
+ return tree_expr_finite_p (TREE_OPERAND (x, 1))
+ && tree_expr_finite_p (TREE_OPERAND (x, 2));
+ case CALL_EXPR:
+ switch (get_call_combined_fn (x))
+ {
+ CASE_CFN_FABS:
+ return tree_expr_finite_p (CALL_EXPR_ARG (x, 0));
+ CASE_CFN_FMAX:
+ CASE_CFN_FMIN:
+ return tree_expr_finite_p (CALL_EXPR_ARG (x, 0))
+ && tree_expr_finite_p (CALL_EXPR_ARG (x, 1));
+ default:
+ return false;
+ }
+
+ default:
+ return false;
+ }
+}
+
+/* Return true if expression X evaluates to an infinity.
+ This function returns false for integer expressions. */
+
+bool
+tree_expr_infinite_p (const_tree x)
+{
+ if (!HONOR_INFINITIES (x))
+ return false;
+ switch (TREE_CODE (x))
+ {
+ case REAL_CST:
+ return real_isinf (TREE_REAL_CST_PTR (x));
+ case ABS_EXPR:
+ case NEGATE_EXPR:
+ case NON_LVALUE_EXPR:
+ case SAVE_EXPR:
+ return tree_expr_infinite_p (TREE_OPERAND (x, 0));
+ case COND_EXPR:
+ return tree_expr_infinite_p (TREE_OPERAND (x, 1))
+ && tree_expr_infinite_p (TREE_OPERAND (x, 2));
+ default:
+ return false;
+ }
+}
+
+/* Return true if expression X could evaluate to an infinity.
+ This function returns false for integer expressions, and returns
+ true if uncertain. */
+
+bool
+tree_expr_maybe_infinite_p (const_tree x)
+{
+ if (!HONOR_INFINITIES (x))
+ return false;
+ switch (TREE_CODE (x))
+ {
+ case REAL_CST:
+ return real_isinf (TREE_REAL_CST_PTR (x));
+ case FLOAT_EXPR:
+ return false;
+ case ABS_EXPR:
+ case NEGATE_EXPR:
+ return tree_expr_maybe_infinite_p (TREE_OPERAND (x, 0));
+ case COND_EXPR:
+ return tree_expr_maybe_infinite_p (TREE_OPERAND (x, 1))
+ || tree_expr_maybe_infinite_p (TREE_OPERAND (x, 2));
+ default:
+ return true;
+ }
+}
+
+/* Return true if expression X evaluates to a signaling NaN.
+ This function returns false for integer expressions. */
+
+bool
+tree_expr_signaling_nan_p (const_tree x)
+{
+ if (!HONOR_SNANS (x))
+ return false;
+ switch (TREE_CODE (x))
+ {
+ case REAL_CST:
+ return real_issignaling_nan (TREE_REAL_CST_PTR (x));
+ case NON_LVALUE_EXPR:
+ case SAVE_EXPR:
+ return tree_expr_signaling_nan_p (TREE_OPERAND (x, 0));
+ case COND_EXPR:
+ return tree_expr_signaling_nan_p (TREE_OPERAND (x, 1))
+ && tree_expr_signaling_nan_p (TREE_OPERAND (x, 2));
+ default:
+ return false;
+ }
+}
+
+/* Return true if expression X could evaluate to a signaling NaN.
+ This function returns false for integer expressions, and returns
+ true if uncertain. */
+
+bool
+tree_expr_maybe_signaling_nan_p (const_tree x)
+{
+ if (!HONOR_SNANS (x))
+ return false;
+ switch (TREE_CODE (x))
+ {
+ case REAL_CST:
+ return real_issignaling_nan (TREE_REAL_CST_PTR (x));
+ case FLOAT_EXPR:
+ return false;
+ case ABS_EXPR:
+ case CONVERT_EXPR:
+ case NEGATE_EXPR:
+ case NON_LVALUE_EXPR:
+ case SAVE_EXPR:
+ return tree_expr_maybe_signaling_nan_p (TREE_OPERAND (x, 0));
+ case MIN_EXPR:
+ case MAX_EXPR:
+ return tree_expr_maybe_signaling_nan_p (TREE_OPERAND (x, 0))
+ || tree_expr_maybe_signaling_nan_p (TREE_OPERAND (x, 1));
+ case COND_EXPR:
+ return tree_expr_maybe_signaling_nan_p (TREE_OPERAND (x, 1))
+ || tree_expr_maybe_signaling_nan_p (TREE_OPERAND (x, 2));
+ case CALL_EXPR:
+ switch (get_call_combined_fn (x))
+ {
+ CASE_CFN_FABS:
+ return tree_expr_maybe_signaling_nan_p (CALL_EXPR_ARG (x, 0));
+ CASE_CFN_FMAX:
+ CASE_CFN_FMIN:
+ return tree_expr_maybe_signaling_nan_p (CALL_EXPR_ARG (x, 0))
+ || tree_expr_maybe_signaling_nan_p (CALL_EXPR_ARG (x, 1));
+ default:
+ return true;
+ }
+ default:
+ return true;
+ }
+}
+
+/* Return true if expression X evaluates to a NaN.
+ This function returns false for integer expressions. */
+
+bool
+tree_expr_nan_p (const_tree x)
+{
+ if (!HONOR_NANS (x))
+ return false;
+ switch (TREE_CODE (x))
+ {
+ case REAL_CST:
+ return real_isnan (TREE_REAL_CST_PTR (x));
+ case NON_LVALUE_EXPR:
+ case SAVE_EXPR:
+ return tree_expr_nan_p (TREE_OPERAND (x, 0));
+ case COND_EXPR:
+ return tree_expr_nan_p (TREE_OPERAND (x, 1))
+ && tree_expr_nan_p (TREE_OPERAND (x, 2));
+ default:
+ return false;
+ }
+}
+
+/* Return true if expression X could evaluate to a NaN.
+ This function returns false for integer expressions, and returns
+ true if uncertain. */
+
+bool
+tree_expr_maybe_nan_p (const_tree x)
+{
+ if (!HONOR_NANS (x))
+ return false;
+ switch (TREE_CODE (x))
+ {
+ case REAL_CST:
+ return real_isnan (TREE_REAL_CST_PTR (x));
+ case FLOAT_EXPR:
+ return false;
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case MULT_EXPR:
+ return !tree_expr_finite_p (TREE_OPERAND (x, 0))
+ || !tree_expr_finite_p (TREE_OPERAND (x, 1));
+ case ABS_EXPR:
+ case CONVERT_EXPR:
+ case NEGATE_EXPR:
+ case NON_LVALUE_EXPR:
+ case SAVE_EXPR:
+ return tree_expr_maybe_nan_p (TREE_OPERAND (x, 0));
+ case MIN_EXPR:
+ case MAX_EXPR:
+ return tree_expr_maybe_nan_p (TREE_OPERAND (x, 0))
+ || tree_expr_maybe_nan_p (TREE_OPERAND (x, 1));
+ case COND_EXPR:
+ return tree_expr_maybe_nan_p (TREE_OPERAND (x, 1))
+ || tree_expr_maybe_nan_p (TREE_OPERAND (x, 2));
+ case CALL_EXPR:
+ switch (get_call_combined_fn (x))
+ {
+ CASE_CFN_FABS:
+ return tree_expr_maybe_nan_p (CALL_EXPR_ARG (x, 0));
+ CASE_CFN_FMAX:
+ CASE_CFN_FMIN:
+ return tree_expr_maybe_nan_p (CALL_EXPR_ARG (x, 0))
+ || tree_expr_maybe_nan_p (CALL_EXPR_ARG (x, 1));
+ default:
+ return true;
+ }
+ default:
+ return true;
+ }
+}
+
#define tree_expr_nonnegative_warnv_p(X, Y) \
_Pragma ("GCC error \"Use RECURSE for recursive calls\"") 0
@@ -13878,7 +14120,13 @@ tree_binary_nonnegative_warnv_p (enum tree_code code, tree type, tree op0,
return false;
case BIT_AND_EXPR:
+ return RECURSE (op0) || RECURSE (op1);
+
case MAX_EXPR:
+ /* Usually RECURSE (op0) || RECURSE (op1) but NaNs complicate
+ things. */
+ if (tree_expr_maybe_nan_p (op0) || tree_expr_maybe_nan_p (op1))
+ return RECURSE (op0) && RECURSE (op1);
return RECURSE (op0) || RECURSE (op1);
case BIT_IOR_EXPR:
@@ -14038,8 +14286,18 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1,
CASE_CFN_FMAX:
CASE_CFN_FMAX_FN:
- /* True if the 1st OR 2nd arguments are nonnegative. */
- return RECURSE (arg0) || RECURSE (arg1);
+ /* Usually RECURSE (arg0) || RECURSE (arg1) but NaNs complicate
+ things. In the presence of sNaNs, we're only guaranteed to be
+ non-negative if both operands are non-negative. In the presence
+ of qNaNs, we're non-negative if either operand is non-negative
+ and can't be a qNaN, or if both operands are non-negative. */
+ if (tree_expr_maybe_signaling_nan_p (arg0) ||
+ tree_expr_maybe_signaling_nan_p (arg1))
+ return RECURSE (arg0) && RECURSE (arg1);
+ return RECURSE (arg0) ? (!tree_expr_maybe_nan_p (arg0)
+ || RECURSE (arg1))
+ : (RECURSE (arg1)
+ && !tree_expr_maybe_nan_p (arg1));
CASE_CFN_FMIN:
CASE_CFN_FMIN_FN:
diff --git a/gcc/fold-const.h b/gcc/fold-const.h
index 0c0f5fd..e833019 100644
--- a/gcc/fold-const.h
+++ b/gcc/fold-const.h
@@ -186,6 +186,13 @@ extern tree non_lvalue_loc (location_t, tree);
extern bool tree_expr_nonzero_p (tree);
extern bool tree_expr_nonnegative_p (tree);
extern bool tree_expr_nonnegative_warnv_p (tree, bool *, int = 0);
+extern bool tree_expr_finite_p (const_tree);
+extern bool tree_expr_infinite_p (const_tree);
+extern bool tree_expr_maybe_infinite_p (const_tree);
+extern bool tree_expr_signaling_nan_p (const_tree);
+extern bool tree_expr_maybe_signaling_nan_p (const_tree);
+extern bool tree_expr_nan_p (const_tree);
+extern bool tree_expr_maybe_nan_p (const_tree);
extern tree make_range (tree, int *, tree *, tree *, bool *);
extern tree make_range_step (location_t, enum tree_code, tree, tree, tree,
tree *, tree *, int *, bool *);
diff --git a/gcc/match.pd b/gcc/match.pd
index 1dd05c4..cbb4bf0 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -4932,6 +4932,24 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
{ constant_boolean_node (cmp == ORDERED_EXPR || cmp == LTGT_EXPR
? false : true, type); })))
+/* Fold UNORDERED if either operand must be NaN, or neither can be. */
+(simplify
+ (unordered @0 @1)
+ (switch
+ (if (tree_expr_nan_p (@0) || tree_expr_nan_p (@1))
+ { constant_boolean_node (true, type); })
+ (if (!tree_expr_maybe_nan_p (@0) && !tree_expr_maybe_nan_p (@1))
+ { constant_boolean_node (false, type); })))
+
+/* Fold ORDERED if either operand must be NaN, or neither can be. */
+(simplify
+ (ordered @0 @1)
+ (switch
+ (if (tree_expr_nan_p (@0) || tree_expr_nan_p (@1))
+ { constant_boolean_node (false, type); })
+ (if (!tree_expr_maybe_nan_p (@0) && !tree_expr_maybe_nan_p (@1))
+ { constant_boolean_node (true, type); })))
+
/* bool_var != 0 becomes bool_var. */
(simplify
(ne @0 integer_zerop)
@@ -5063,7 +5081,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
/* Simplify sqrt(x) * sqrt(x) -> x. */
(simplify
(mult (SQRT_ALL@1 @0) @1)
- (if (!HONOR_SNANS (type))
+ (if (!tree_expr_maybe_signaling_nan_p (@0))
@0))
(for op (plus minus)
diff --git a/gcc/testsuite/gcc.dg/fold-isfinite-1.c b/gcc/testsuite/gcc.dg/fold-isfinite-1.c
new file mode 100644
index 0000000..2ea0192
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-isfinite-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target inf } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int foo(int x)
+{
+ return __builtin_finite((double)x);
+}
+
+int foof(int x)
+{
+ return __builtin_finitef((float)x);
+}
+
+int fool(int x)
+{
+ return __builtin_finitel((long double)x);
+}
+
+/* { dg-final { scan-tree-dump-times "_finite" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " u> " 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/fold-isfinite-2.c b/gcc/testsuite/gcc.dg/fold-isfinite-2.c
new file mode 100644
index 0000000..ff70d8d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-isfinite-2.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target inf } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int foo(unsigned int x)
+{
+ return __builtin_finite((double)x);
+}
+
+int foof(unsigned int x)
+{
+ return __builtin_finitef((float)x);
+}
+
+int fool(unsigned int x)
+{
+ return __builtin_finitel((long double)x);
+}
+
+/* { dg-final { scan-tree-dump-times "_finite" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " u> " 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/fold-isinf-1.c b/gcc/testsuite/gcc.dg/fold-isinf-1.c
new file mode 100644
index 0000000..485816e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-isinf-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target inf } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int foo(int x)
+{
+ return __builtin_isinf((double)x);
+}
+
+int foof(int x)
+{
+ return __builtin_isinff((float)x);
+}
+
+int fool(int x)
+{
+ return __builtin_isinfl((long double)x);
+}
+
+/* { dg-final { scan-tree-dump-times "_isinf" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " u<= " 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/fold-isinf-2.c b/gcc/testsuite/gcc.dg/fold-isinf-2.c
new file mode 100644
index 0000000..a236ca1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-isinf-2.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target inf } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int foo(unsigned int x)
+{
+ return __builtin_isinf((double)x);
+}
+
+int foof(unsigned int x)
+{
+ return __builtin_isinff((float)x);
+}
+
+int fool(unsigned int x)
+{
+ return __builtin_isinfl((long double)x);
+}
+
+/* { dg-final { scan-tree-dump-times "_isinf" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " u<= " 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/fold-isnan-1.c b/gcc/testsuite/gcc.dg/fold-isnan-1.c
new file mode 100644
index 0000000..05ee930
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-isnan-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target inf } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int foo(int x)
+{
+ return __builtin_isnan((double)x);
+}
+
+int foof(int x)
+{
+ return __builtin_isnanf((float)x);
+}
+
+int fool(int x)
+{
+ return __builtin_isnanl((long double)x);
+}
+
+/* { dg-final { scan-tree-dump-times "_isnan" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " unord " 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/fold-isnan-2.c b/gcc/testsuite/gcc.dg/fold-isnan-2.c
new file mode 100644
index 0000000..32b8833
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-isnan-2.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target inf } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int foo(unsigned int x)
+{
+ return __builtin_isnan((double)x);
+}
+
+int foof(unsigned int x)
+{
+ return __builtin_isnanf((float)x);
+}
+
+int fool(unsigned int x)
+{
+ return __builtin_isnanl((long double)x);
+}
+
+/* { dg-final { scan-tree-dump-times "_isnan" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " unord " 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/pr85811.c b/gcc/testsuite/gcc.dg/pr85811.c
new file mode 100644
index 0000000..868f66c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr85811.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+#include <stdio.h>
+
+int main() {
+ const double negval = -1.0;
+ const double nanval = 0.0 / 0.0;
+ const double val = __builtin_fmax(negval, nanval);
+ const double absval = __builtin_fabs(val);
+ printf("fabs(%.16e) = %.16e\n", val, absval);
+ return absval >= 0 ? 0 : 1;
+}
+
+/* We hope not to see: printf ("fabs(%.16e) = %.16e\n", val_4, val_4); */
+/* { dg-final { scan-tree-dump-not "val_\[0-9\]*, val_\[0-9\]*" "optimized" } } */