builtins.c (fold_fixed_mathfn): New function.

* builtins.c (fold_fixed_mathfn): New function.
	(fold_builtin_lround, fold_builtin): Use it.

testsuite:
	* gcc.dg/torture/builtin-integral-1.c: Reorg and add more cases.
	* gcc.dg/torture/builtin-convert-3.c: New test.

From-SVN: r81403
This commit is contained in:
Kaveh R. Ghazi 2004-05-02 02:53:05 +00:00 committed by Kaveh Ghazi
parent 3c2d679772
commit ca3df64369
5 changed files with 153 additions and 15 deletions

View file

@ -1,3 +1,8 @@
2004-05-01 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* builtins.c (fold_fixed_mathfn): New function.
(fold_builtin_lround, fold_builtin): Use it.
2004-05-01 Jakub Jelinek <jakub@redhat.com>
* config/sparc/linux64.h (TARGET_DEFAULT): Make 64-bit by default

View file

@ -6075,6 +6075,45 @@ fold_trunc_transparent_mathfn (tree exp)
return 0;
}
/* EXP is assumed to be builtin call which can narrow the FP type of
the argument, for instance lround((double)f) -> lroundf (f). */
static tree
fold_fixed_mathfn (tree exp)
{
tree fndecl = get_callee_fndecl (exp);
tree arglist = TREE_OPERAND (exp, 1);
enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
tree arg;
if (! validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
return 0;
arg = TREE_VALUE (arglist);
/* If argument is already integer valued, and we don't need to worry
about setting errno, there's no need to perform rounding. */
if (! flag_errno_math && integer_valued_real_p (arg))
return fold (build1 (FIX_TRUNC_EXPR, TREE_TYPE (exp), arg));
if (optimize)
{
tree ftype = TREE_TYPE (arg);
tree arg0 = strip_float_extensions (arg);
tree newtype = TREE_TYPE (arg0);
tree decl;
if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
&& (decl = mathfn_built_in (newtype, fcode)))
{
arglist =
build_tree_list (NULL_TREE, fold_convert (newtype, arg0));
return build_function_call_expr (decl, arglist);
}
}
return 0;
}
/* Fold function call to builtin cabs, cabsf or cabsl. ARGLIST
is the argument list and TYPE is the return type. Return
NULL_TREE if no if no simplification can be made. */
@ -6307,7 +6346,7 @@ fold_builtin_lround (tree exp)
}
}
return 0;
return fold_fixed_mathfn (exp);
}
/* Fold function call to builtin ffs, clz, ctz, popcount and parity
@ -7420,6 +7459,14 @@ fold_builtin (tree exp)
case BUILT_IN_LLROUNDL:
return fold_builtin_lround (exp);
case BUILT_IN_LRINT:
case BUILT_IN_LRINTF:
case BUILT_IN_LRINTL:
case BUILT_IN_LLRINT:
case BUILT_IN_LLRINTF:
case BUILT_IN_LLRINTL:
return fold_fixed_mathfn (exp);
case BUILT_IN_FFS:
case BUILT_IN_FFSL:
case BUILT_IN_FFSLL:

View file

@ -1,3 +1,8 @@
2004-05-01 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* gcc.dg/torture/builtin-integral-1.c: Reorg and add more cases.
* gcc.dg/torture/builtin-convert-3.c: New test.
2004-05-01 Ulrich Weigand <uweigand@de.ibm.com>
PR middle-end/15054

View file

@ -0,0 +1,56 @@
/* Copyright (C) 2004 Free Software Foundation.
Verify that builtin math functions (with fixed point return types)
are converted to smaller FP types correctly by the compiler.
Written by Kaveh Ghazi, 2004-05-01. */
/* { dg-do link } */
/* { dg-options "-ffast-math" } */
#include "../builtins-config.h"
#define PROTOTYPE1_RET(FN, RET) \
extern RET FN(double); \
extern RET FN##f(float); \
extern RET FN##l(long double);
/* Test converting math builtins to narrower FP types based on if the
argument is a narrower type (perhaps implicitly) cast to a wider
one. */
#define INNER_CAST1(MATHFN, RET) \
PROTOTYPE1_RET (MATHFN, RET); \
extern void link_failure_inner_##MATHFN##l_##MATHFN(void); \
extern void link_failure_inner_##MATHFN##l_##MATHFN##f(void); \
extern void link_failure_inner_##MATHFN##_##MATHFN##f(void); \
if (sizeof (long double) > sizeof (double) \
&& MATHFN##l(d1) != MATHFN(d1)) \
link_failure_inner_##MATHFN##l_##MATHFN(); \
if (sizeof (long double) > sizeof (float) \
&& MATHFN##l(f1) != MATHFN##f(f1)) \
link_failure_inner_##MATHFN##l_##MATHFN##f(); \
if (sizeof (long double) > sizeof (float) \
&& MATHFN##l((double)f1) != MATHFN##f(f1)) \
link_failure_inner_##MATHFN##l_##MATHFN##f(); \
if (sizeof (double) > sizeof (float) \
&& MATHFN(f1) != MATHFN##f(f1)) \
link_failure_inner_##MATHFN##_##MATHFN##f()
void __attribute__ ((__noinline__)) test (double d1, float f1)
{
#ifdef __OPTIMIZE__
#ifdef HAVE_C99_RUNTIME
/* We're converting to implicitly generated C99 functions. */
INNER_CAST1 (lround, long);
INNER_CAST1 (llround, long long);
INNER_CAST1 (lrint, long);
INNER_CAST1 (llrint, long long);
#endif /* HAVE_C99_RUNTIME */
#endif /* __OPTIMIZE__ */
}
int main (void)
{
test (1, 2);
return 0;
}

View file

@ -9,33 +9,57 @@
#define PROTOTYPE1(FN) extern double FN(double); extern float FN##f(float); \
extern long double FN##l(long double);
#define PROTOTYPE1_RET(FN, RET) extern RET FN(double); extern RET FN##f(float); \
extern RET FN##l(long double);
#define PROTOTYPE_LINK_FAILURE(FN) extern void link_failure_##FN(void); \
extern void link_failure_##FN##f(void); \
extern void link_failure_##FN##l(void); \
PROTOTYPE1(fabs)
PROTOTYPE1(ceil)
PROTOTYPE1(floor)
PROTOTYPE1(nearbyint)
PROTOTYPE1(rint)
PROTOTYPE1(round)
PROTOTYPE1(trunc)
PROTOTYPE1_RET(lround, long)
PROTOTYPE1_RET(llround, long long)
PROTOTYPE1_RET(lrint, long)
PROTOTYPE1_RET(llrint, long long)
void test(int i1, int i2)
{
/* Test that the various FP truncation builtins detect integral
arguments. */
/* Test that the various FP truncation builtins detect integral
arguments. */
#define CHECK_FN(MATHFN) \
PROTOTYPE1 (MATHFN) \
extern void link_failure_##MATHFN(void); \
extern void link_failure_##MATHFN##f(void); \
extern void link_failure_##MATHFN##l(void); \
PROTOTYPE_LINK_FAILURE(MATHFN); \
if (MATHFN(i1) != i1) link_failure_##MATHFN(); \
if (MATHFN##f(i1) != i1) link_failure_##MATHFN##f(); \
if (MATHFN##l(i1) != i1) link_failure_##MATHFN##l(); \
if (MATHFN##l(i1) != i1) link_failure_##MATHFN##l();
#define CHECK_FN_RET(MATHFN, RET) \
PROTOTYPE_LINK_FAILURE(MATHFN); \
if (MATHFN(i1) != (RET)(double)i1) link_failure_##MATHFN(); \
if (MATHFN##f(i1) != (RET)(float)i1) link_failure_##MATHFN##f(); \
if (MATHFN##l(i1) != (RET)(long double)i1) link_failure_##MATHFN##l();
/* Check that various other integral expressions are detected. */
#define CHECK_EXPR(EXPR,NAME) \
extern void link_failure_FP_##NAME(void); \
extern void link_failure_fixed_##NAME(void); \
if (ceill(EXPR) != (EXPR)) link_failure_FP_##NAME(); \
if (lroundl(EXPR) != (long)(long double)(EXPR)) link_failure_fixed_##NAME();
void __attribute__ ((__noinline__)) test (int i1, int i2)
{
CHECK_FN(ceil);
CHECK_FN(floor);
CHECK_FN(nearbyint);
CHECK_FN(rint);
CHECK_FN(round);
CHECK_FN(trunc);
/* Check that various other integral expressions are detected. */
#define CHECK_EXPR(EXPR,NAME) \
extern void link_failure_##NAME(void); \
if (ceill(EXPR) != (EXPR)) link_failure_##NAME(); \
CHECK_FN_RET(lround, long);
CHECK_FN_RET(llround, long long);
CHECK_FN_RET(lrint, long);
CHECK_FN_RET(llrint, long long);
CHECK_EXPR (5.0, REAL_CST);
CHECK_EXPR (5.0F, REAL_CSTf);
@ -54,5 +78,6 @@ void test(int i1, int i2)
int main (void)
{
test (1, 2);
return 0;
}