mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-09 22:51:29 +08:00
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
This commit is contained in:
parent
6af46feb6b
commit
b64d949c61
gcc
@ -1,5 +1,9 @@
|
||||
2006-11-18 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
|
||||
|
||||
* builtins.c (integer_valued_real_p): Handle fmin/fmax.
|
||||
(fold_builtin_fmin_fmax): New.
|
||||
(fold_builtin_1): Use it.
|
||||
|
||||
* fold-const.c (fold_strip_sign_ops): Handle copysign.
|
||||
|
||||
2006-11-18 Richard Guenther <rguenther@suse.de>
|
||||
|
@ -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);
|
||||
|
@ -1,5 +1,8 @@
|
||||
2006-11-18 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
|
||||
|
||||
* gcc.dg/builtins-20.c: Add fmin/fmax cases.
|
||||
* gcc.dg/torture/builtin-minmax-1.c: New.
|
||||
|
||||
* gcc.dg/builtins-20.c: Add cases for copysign.
|
||||
|
||||
2006-11-18 Francois-Xavier Coudert <coudert@clipper.ens.fr>
|
||||
|
@ -17,6 +17,8 @@ extern double sin (double);
|
||||
extern double tan (double);
|
||||
extern double fabs (double);
|
||||
extern double copysign (double, double);
|
||||
extern double fmin (double, double);
|
||||
extern double fmax (double, double);
|
||||
extern double hypot (double, double);
|
||||
extern double pure (double) __attribute__ ((__pure__));
|
||||
extern float cosf (float);
|
||||
@ -24,6 +26,8 @@ extern float sinf (float);
|
||||
extern float tanf (float);
|
||||
extern float fabsf (float);
|
||||
extern float copysignf (float, float);
|
||||
extern float fminf (float, float);
|
||||
extern float fmaxf (float, float);
|
||||
extern float hypotf (float, float);
|
||||
extern float puref (float) __attribute__ ((__pure__));
|
||||
extern long double cosl (long double);
|
||||
@ -31,6 +35,8 @@ extern long double sinl (long double);
|
||||
extern long double tanl (long double);
|
||||
extern long double fabsl (long double);
|
||||
extern long double copysignl (long double, long double);
|
||||
extern long double fminl (long double, long double);
|
||||
extern long double fmaxl (long double, long double);
|
||||
extern long double hypotl (long double, long double);
|
||||
extern long double purel (long double) __attribute__ ((__pure__));
|
||||
|
||||
@ -155,6 +161,30 @@ void test2(double x, double y)
|
||||
|
||||
if (hypot (tan(-x), tan(-fabs(y))) != hypot (tan(x), tan(y)))
|
||||
link_error ();
|
||||
|
||||
if (fmin (fmax(x,y),y) != y)
|
||||
link_error ();
|
||||
|
||||
if (fmin (fmax(y,x),y) != y)
|
||||
link_error ();
|
||||
|
||||
if (fmin (x,fmax(x,y)) != x)
|
||||
link_error ();
|
||||
|
||||
if (fmin (x,fmax(y,x)) != x)
|
||||
link_error ();
|
||||
|
||||
if (fmax (fmin(x,y),y) != y)
|
||||
link_error ();
|
||||
|
||||
if (fmax (fmin(y,x),y) != y)
|
||||
link_error ();
|
||||
|
||||
if (fmax (x,fmin(x,y)) != x)
|
||||
link_error ();
|
||||
|
||||
if (fmax (x,fmin(y,x)) != x)
|
||||
link_error ();
|
||||
}
|
||||
|
||||
void test1f(float x)
|
||||
@ -278,6 +308,30 @@ void test2f(float x, float y)
|
||||
|
||||
if (hypotf (tanf(-x), tanf(-fabsf(y))) != hypotf (tanf(x), tanf(y)))
|
||||
link_error ();
|
||||
|
||||
if (fminf (fmaxf(x,y),y) != y)
|
||||
link_error ();
|
||||
|
||||
if (fminf (fmaxf(y,x),y) != y)
|
||||
link_error ();
|
||||
|
||||
if (fminf (x,fmaxf(x,y)) != x)
|
||||
link_error ();
|
||||
|
||||
if (fminf (x,fmaxf(y,x)) != x)
|
||||
link_error ();
|
||||
|
||||
if (fmaxf (fminf(x,y),y) != y)
|
||||
link_error ();
|
||||
|
||||
if (fmaxf (fminf(y,x),y) != y)
|
||||
link_error ();
|
||||
|
||||
if (fmaxf (x,fminf(x,y)) != x)
|
||||
link_error ();
|
||||
|
||||
if (fmaxf (x,fminf(y,x)) != x)
|
||||
link_error ();
|
||||
}
|
||||
|
||||
|
||||
@ -402,6 +456,30 @@ void test2l(long double x, long double y)
|
||||
|
||||
if (hypotl (tanl(-x), tanl(-fabsl(y))) != hypotl (tanl(x), tanl(y)))
|
||||
link_error ();
|
||||
|
||||
if (fminl (fmaxl(x,y),y) != y)
|
||||
link_error ();
|
||||
|
||||
if (fminl (fmaxl(y,x),y) != y)
|
||||
link_error ();
|
||||
|
||||
if (fminl (x,fmaxl(x,y)) != x)
|
||||
link_error ();
|
||||
|
||||
if (fminl (x,fmaxl(y,x)) != x)
|
||||
link_error ();
|
||||
|
||||
if (fmaxl (fminl(x,y),y) != y)
|
||||
link_error ();
|
||||
|
||||
if (fmaxl (fminl(y,x),y) != y)
|
||||
link_error ();
|
||||
|
||||
if (fmaxl (x,fminl(x,y)) != x)
|
||||
link_error ();
|
||||
|
||||
if (fmaxl (x,fminl(y,x)) != x)
|
||||
link_error ();
|
||||
}
|
||||
|
||||
int main()
|
||||
|
100
gcc/testsuite/gcc.dg/torture/builtin-minmax-1.c
Normal file
100
gcc/testsuite/gcc.dg/torture/builtin-minmax-1.c
Normal file
@ -0,0 +1,100 @@
|
||||
/* Copyright (C) 2006 Free Software Foundation.
|
||||
|
||||
Verify that built-in math function folding of fmin/fmax is
|
||||
correctly performed by the compiler.
|
||||
|
||||
Origin: Kaveh R. Ghazi, November 13, 2006. */
|
||||
|
||||
/* { dg-do link } */
|
||||
/* { dg-options "-fno-math-errno" } */
|
||||
|
||||
/* All references to link_error should go away at compile-time. */
|
||||
extern void link_error(int);
|
||||
|
||||
#define DECLARE(FUNC) \
|
||||
extern float FUNC##f (float); \
|
||||
extern double FUNC (double); \
|
||||
extern long double FUNC##l (long double)
|
||||
#define DECLARE_L(FUNC) \
|
||||
extern long FUNC##f (float); \
|
||||
extern long FUNC (double); \
|
||||
extern long FUNC##l (long double)
|
||||
#define DECLARE2(FUNC) \
|
||||
extern float FUNC##f (float, float); \
|
||||
extern double FUNC (double, double); \
|
||||
extern long double FUNC##l (long double, long double)
|
||||
|
||||
DECLARE2(fmin);
|
||||
DECLARE2(fmax);
|
||||
DECLARE_L(lround);
|
||||
DECLARE_L(lrint);
|
||||
DECLARE(sqrt);
|
||||
DECLARE(fabs);
|
||||
extern int pure(int) __attribute__ ((__pure__));
|
||||
|
||||
/* Test that FUNC(x,x) == x. We cast to (long) so "!=" folds. */
|
||||
#define TEST_EQ(FUNC) do { \
|
||||
if ((long)FUNC##f(xf,xf) != (long)xf) \
|
||||
link_error(__LINE__); \
|
||||
if ((long)FUNC(x,x) != (long)x) \
|
||||
link_error(__LINE__); \
|
||||
if ((long)FUNC##l(xl,xl) != (long)xl) \
|
||||
link_error(__LINE__); \
|
||||
} while (0)
|
||||
|
||||
/* Test that FUNC(purefn,purefn) == purefn. We cast to (long) so "!=" folds. */
|
||||
#define TEST_EQ_PURE(FUNC) do { \
|
||||
if ((long)FUNC##f(pure(i),pure(i)) != (long)FUNC##f(pure(i),pure(i))) \
|
||||
link_error(__LINE__); \
|
||||
if ((long)FUNC(pure(i),pure(i)) != (long)FUNC(pure(i),pure(i))) \
|
||||
link_error(__LINE__); \
|
||||
if ((long)FUNC##l(pure(i),pure(i)) != (long)FUNC##l(pure(i),pure(i))) \
|
||||
link_error(__LINE__); \
|
||||
} while (0)
|
||||
|
||||
/* Test that lround(FUNC(int,int)) == lrint(FUNC(int,int)), i.e. both
|
||||
lround() and lrint() should be folded away. */
|
||||
#define TEST_NONNEG(FUNC) do { \
|
||||
if (lroundf(FUNC##f(i,j)) != lrintf(FUNC##f(i,j))) \
|
||||
link_error(__LINE__); \
|
||||
if (lround(FUNC(i,j)) != lrint(FUNC(i,j))) \
|
||||
link_error(__LINE__); \
|
||||
if (lroundl(FUNC##l(i,j)) != lrintl(FUNC##l(i,j))) \
|
||||
link_error(__LINE__); \
|
||||
} while (0)
|
||||
|
||||
/* Test that (long)fabs(FUNC(fabs(x),fabs(y))) ==
|
||||
(long)FUNC(fabs(x),fabs(y)). We cast to (long) so "!=" folds. */
|
||||
#define TEST_INT(FUNC) do { \
|
||||
if ((long)fabsf(FUNC##f(fabsf(xf),fabsf(yf))) != (long)FUNC##f(fabsf(xf),fabsf(yf))) \
|
||||
link_error(__LINE__); \
|
||||
if ((long)fabs(FUNC(fabs(x),fabs(y))) != (long)FUNC(fabs(x),fabs(y))) \
|
||||
link_error(__LINE__); \
|
||||
if ((long)fabsl(FUNC##l(fabsl(xl),fabsl(yl))) != (long)FUNC##l(fabsl(xl),fabsl(yl))) \
|
||||
link_error(__LINE__); \
|
||||
} while (0)
|
||||
|
||||
void foo (float xf, double x, long double xl,
|
||||
float yf, double y, long double yl,
|
||||
int i, int j)
|
||||
{
|
||||
TEST_EQ(fmin);
|
||||
TEST_EQ(fmax);
|
||||
|
||||
#ifdef __OPTIMIZE__
|
||||
TEST_EQ_PURE(fmin);
|
||||
TEST_EQ_PURE(fmax);
|
||||
#endif
|
||||
|
||||
TEST_INT(fmin);
|
||||
TEST_INT(fmax);
|
||||
|
||||
TEST_NONNEG(fmin);
|
||||
TEST_NONNEG(fmax);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
foo (1,1,1,1,1,1,1,1);
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user