aboutsummaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
authorKaveh R. Ghazi <ghazi@caip.rutgers.edu>2006-11-18 20:38:40 +0000
committerKaveh Ghazi <ghazi@gcc.gnu.org>2006-11-18 20:38:40 +0000
commitb64d949c6145fb4936987d07fce6c9e9b043eb9a (patch)
tree4271dac3a15920b86d9161661dc7f03100747e65 /gcc/builtins.c
parent6af46feb6b6cf1ff61860db3bc4af7d0ed03e148 (diff)
downloadgcc-b64d949c6145fb4936987d07fce6c9e9b043eb9a.zip
gcc-b64d949c6145fb4936987d07fce6c9e9b043eb9a.tar.gz
gcc-b64d949c6145fb4936987d07fce6c9e9b043eb9a.tar.bz2
builtins.c (integer_valued_real_p): Handle fmin/fmax.
* builtins.c (integer_valued_real_p): Handle fmin/fmax. (fold_builtin_fmin_fmax): New. (fold_builtin_1): Use it. testsuite: * gcc.dg/builtins-20.c: Add fmin/fmax cases. * gcc.dg/torture/builtin-minmax-1.c: New. From-SVN: r118976
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r--gcc/builtins.c49
1 files changed, 39 insertions, 10 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index b9005b4..4e4ea96 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -6708,6 +6708,11 @@ integer_valued_real_p (tree t)
CASE_FLT_FN (BUILT_IN_TRUNC):
return true;
+ CASE_FLT_FN (BUILT_IN_FMIN):
+ CASE_FLT_FN (BUILT_IN_FMAX):
+ return integer_valued_real_p (TREE_VALUE (TREE_OPERAND (t, 1)))
+ && integer_valued_real_p (TREE_VALUE (TREE_CHAIN (TREE_OPERAND (t, 1))));
+
default:
break;
}
@@ -8722,6 +8727,38 @@ fold_builtin_abs (tree arglist, tree type)
return fold_build1 (ABS_EXPR, type, arg);
}
+/* Fold a call to builtin fmin or fmax. */
+
+static tree
+fold_builtin_fmin_fmax (tree arglist, tree type, bool max)
+{
+ if (validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
+ {
+ tree arg0 = TREE_VALUE (arglist);
+ tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ /* Calculate the result when the argument is a constant. */
+ tree res = do_mpfr_arg2 (arg0, arg1, type, (max ? mpfr_max : mpfr_min));
+
+ if (res)
+ return res;
+
+ /* Transform fmin/fmax(x,x) -> x. */
+ if (operand_equal_p (arg0, arg1, OEP_PURE_SAME))
+ return omit_one_operand (type, arg0, arg1);
+
+ /* Convert fmin/fmax to MIN_EXPR/MAX_EXPR. C99 requires these
+ functions to return the numeric arg if the other one is NaN.
+ These tree codes don't honor that, so only transform if
+ -ffinite-math-only is set. C99 doesn't require -0.0 to be
+ handled, so we don't have to worry about it either. */
+ if (flag_finite_math_only)
+ return fold_build2 ((max ? MAX_EXPR : MIN_EXPR), type,
+ fold_convert (type, arg0),
+ fold_convert (type, arg1));
+ }
+ return NULL_TREE;
+}
+
/* Fold a call to __builtin_isnan(), __builtin_isinf, __builtin_finite.
EXP is the CALL_EXPR for the call. */
@@ -9143,18 +9180,10 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore)
break;
CASE_FLT_FN (BUILT_IN_FMIN):
- if (validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
- return do_mpfr_arg2 (TREE_VALUE (arglist),
- TREE_VALUE (TREE_CHAIN (arglist)),
- type, mpfr_min);
- break;
+ return fold_builtin_fmin_fmax (arglist, type, /*max=*/false);
CASE_FLT_FN (BUILT_IN_FMAX):
- if (validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
- return do_mpfr_arg2 (TREE_VALUE (arglist),
- TREE_VALUE (TREE_CHAIN (arglist)),
- type, mpfr_max);
- break;
+ return fold_builtin_fmin_fmax (arglist, type, /*max=*/true);
CASE_FLT_FN (BUILT_IN_HYPOT):
return fold_builtin_hypot (fndecl, arglist, type);