1  /* Copyright (C) 2004  Free Software Foundation.
       2  
       3     Verify that built-in math function conversion to smaller FP types
       4     is correctly performed by the compiler.
       5  
       6     Written by Kaveh Ghazi, 2004-03-17.  */
       7  
       8  /* { dg-do link } */
       9  /* { dg-options "-ffast-math" } */
      10  /* { dg-require-effective-target c99_runtime } */
      11  
      12  #include "../builtins-config.h"
      13  
      14  /* This check is necessary when converting to a C99 function.  */
      15  #ifdef HAVE_C99_RUNTIME
      16  #define C99CODE(CODE) (CODE)
      17  #define MAYBEC99(CODE, C99) (CODE)
      18  #else
      19  #define C99CODE(CODE) 0
      20  #define MAYBEC99(CODE, C99) (!(C99) && (CODE))
      21  #endif
      22  
      23  void test(double d1, float f1, long double ld1)
      24  {
      25    /* Test converting math builtins to narrower FP types based on a
      26       narrowing cast on the outside of the call.  MATHFN is the
      27       function to test, and C99 is 0/1 depending on whether the
      28       `double' version of MATHFN is a C99 function.  The optimization
      29       is only performed if the replacement function is actually
      30       narrower in width, so check that first.  */
      31  #define OUTER_CAST1(MATHFN, C99) \
      32   extern void link_failure_outer_##MATHFN##l_##MATHFN##_1(void); \
      33   extern void link_failure_outer_##MATHFN##l_##MATHFN##_2(void); \
      34   extern void link_failure_outer_##MATHFN##l_##MATHFN##f_1(void); \
      35   extern void link_failure_outer_##MATHFN##l_##MATHFN##f_2(void); \
      36   extern void link_failure_outer_##MATHFN##_##MATHFN##f_1(void); \
      37   extern void link_failure_outer_##MATHFN##_##MATHFN##f_2(void); \
      38   if (sizeof (long double) > sizeof (double) \
      39       && MAYBEC99 ((double) __builtin_##MATHFN##l((double)ld1) != __builtin_##MATHFN(ld1), C99)) \
      40      link_failure_outer_##MATHFN##l_##MATHFN##_1(); \
      41   if (sizeof (long double) > sizeof (double) \
      42       && MAYBEC99 ((double) __builtin_##MATHFN##l(d1) != __builtin_##MATHFN(d1), C99)) \
      43      link_failure_outer_##MATHFN##l_##MATHFN##_1(); \
      44   if (sizeof (long double) > sizeof (double) \
      45       && MAYBEC99 ((double) __builtin_##MATHFN##l(f1) != __builtin_##MATHFN(f1), C99)) \
      46      link_failure_outer_##MATHFN##l_##MATHFN##_2(); \
      47   if (sizeof (long double) > sizeof (float) \
      48       && C99CODE ((float) __builtin_##MATHFN##l((float) ld1) != __builtin_##MATHFN##f(ld1))) \
      49      link_failure_outer_##MATHFN##l_##MATHFN##f_1(); \
      50   if (sizeof (long double) > sizeof (float) \
      51       && C99CODE ((float) __builtin_##MATHFN##l((float) d1) != __builtin_##MATHFN##f(d1))) \
      52      link_failure_outer_##MATHFN##l_##MATHFN##f_1(); \
      53   if (sizeof (long double) > sizeof (float) \
      54       && C99CODE ((float) __builtin_##MATHFN##l(f1) != __builtin_##MATHFN##f(f1))) \
      55      link_failure_outer_##MATHFN##l_##MATHFN##f_2(); \
      56   if (sizeof (double) > sizeof (float) \
      57       && C99CODE ((float) __builtin_##MATHFN((float) ld1) != __builtin_##MATHFN##f(ld1))) \
      58      link_failure_outer_##MATHFN##_##MATHFN##f_1(); \
      59   if (sizeof (double) > sizeof (float) \
      60       && C99CODE ((float) __builtin_##MATHFN((float) d1) != __builtin_##MATHFN##f(d1))) \
      61      link_failure_outer_##MATHFN##_##MATHFN##f_1(); \
      62   if (sizeof (double) > sizeof (float) \
      63       && C99CODE ((float) __builtin_##MATHFN(f1) != __builtin_##MATHFN##f(f1))) \
      64      link_failure_outer_##MATHFN##_##MATHFN##f_2()
      65  
      66    /* Test converting math builtins to narrower FP types based on if
      67       the argument is a narrower type (perhaps implicitly) cast to a
      68       wider one.  */
      69  #define INNER_CAST1(MATHFN, C99) \
      70   extern void link_failure_inner_##MATHFN##l_##MATHFN(void); \
      71   extern void link_failure_inner_##MATHFN##l_##MATHFN##f(void); \
      72   extern void link_failure_inner_##MATHFN##_##MATHFN##f(void); \
      73   if (sizeof (long double) > sizeof (double) \
      74       && MAYBEC99 (__builtin_##MATHFN##l(d1) != (long double) __builtin_##MATHFN(d1), C99)) \
      75      link_failure_inner_##MATHFN##l_##MATHFN(); \
      76   if (sizeof (long double) > sizeof (float) \
      77       && C99CODE (__builtin_##MATHFN##l(f1) != (long double) __builtin_##MATHFN##f(f1))) \
      78      link_failure_inner_##MATHFN##l_##MATHFN##f(); \
      79   if (sizeof (long double) > sizeof (float) \
      80       && C99CODE (__builtin_##MATHFN##l((double)f1) != (long double) __builtin_##MATHFN##f(f1))) \
      81      link_failure_inner_##MATHFN##l_##MATHFN##f(); \
      82   if (sizeof (double) > sizeof (float) \
      83       && C99CODE (__builtin_##MATHFN(f1) != (double) __builtin_##MATHFN##f(f1))) \
      84      link_failure_inner_##MATHFN##_##MATHFN##f()
      85  
      86  
      87  #ifdef __OPTIMIZE__
      88    OUTER_CAST1 (acos, /*C99=*/ 0);
      89    OUTER_CAST1 (acosh, /*C99=*/ 1);
      90    OUTER_CAST1 (asin, /*C99=*/ 1);
      91    OUTER_CAST1 (asinh, /*C99=*/ 1);
      92    OUTER_CAST1 (atan, /*C99=*/ 0);
      93    OUTER_CAST1 (atanh, /*C99=*/ 1);
      94    OUTER_CAST1 (cbrt, /*C99=*/ 1);
      95    OUTER_CAST1 (cos, /*C99=*/ 0);
      96    OUTER_CAST1 (cosh, /*C99=*/ 0);
      97    OUTER_CAST1 (erf, /*C99=*/ 1);
      98    OUTER_CAST1 (erfc, /*C99=*/ 1);
      99    OUTER_CAST1 (exp, /*C99=*/ 0);
     100    OUTER_CAST1 (exp2, /*C99=*/ 1);
     101    OUTER_CAST1 (expm1, /*C99=*/ 1);
     102    OUTER_CAST1 (fabs, /*C99=*/ 0);
     103    OUTER_CAST1 (log, /*C99=*/ 0);
     104    OUTER_CAST1 (log10, /*C99=*/ 0);
     105    OUTER_CAST1 (log1p, /*C99=*/ 1);
     106    OUTER_CAST1 (log2, /*C99=*/ 1);
     107    OUTER_CAST1 (logb, /*C99=*/ 1);
     108    OUTER_CAST1 (sin, /*C99=*/ 0);
     109    OUTER_CAST1 (sinh, /*C99=*/ 0);
     110    OUTER_CAST1 (sqrt, /*C99=*/ 0);
     111    OUTER_CAST1 (tan, /*C99=*/ 0);
     112    OUTER_CAST1 (tanh, /*C99=*/ 0);
     113    OUTER_CAST1 (tgamma, /*C99=*/ 1);
     114  
     115    INNER_CAST1 (ceil, /*C99=*/ 0);
     116    OUTER_CAST1 (ceil, /*C99=*/ 0);
     117    INNER_CAST1 (floor, /*C99=*/ 0);
     118    OUTER_CAST1 (floor, /*C99=*/ 0);
     119    INNER_CAST1 (lceil, /*C99=*/ 1);
     120    OUTER_CAST1 (lceil, /*C99=*/ 1);
     121    INNER_CAST1 (lfloor, /*C99=*/ 1);
     122    OUTER_CAST1 (lfloor, /*C99=*/ 1);
     123    INNER_CAST1 (lrint, /*C99=*/ 1);
     124    OUTER_CAST1 (lrint, /*C99=*/ 1);
     125    INNER_CAST1 (lround, /*C99=*/ 1);
     126    OUTER_CAST1 (lround, /*C99=*/ 1);
     127    INNER_CAST1 (llceil, /*C99=*/ 1);
     128    OUTER_CAST1 (llceil, /*C99=*/ 1);
     129    INNER_CAST1 (llfloor, /*C99=*/ 1);
     130    OUTER_CAST1 (llfloor, /*C99=*/ 1);
     131    INNER_CAST1 (llrint, /*C99=*/ 1);
     132    OUTER_CAST1 (llrint, /*C99=*/ 1);
     133    INNER_CAST1 (llround, /*C99=*/ 1);
     134    OUTER_CAST1 (llround, /*C99=*/ 1);
     135    INNER_CAST1 (nearbyint, /*C99=*/ 1);
     136    OUTER_CAST1 (nearbyint, /*C99=*/ 1);
     137    INNER_CAST1 (rint, /*C99=*/ 1);
     138    OUTER_CAST1 (rint, /*C99=*/ 1);
     139    INNER_CAST1 (round, /*C99=*/ 1);
     140    OUTER_CAST1 (round, /*C99=*/ 1);
     141    INNER_CAST1 (trunc, /*C99=*/ 1);
     142    OUTER_CAST1 (trunc, /*C99=*/ 1);
     143  #endif /* __OPTIMIZE__ */
     144  }
     145  
     146  int main (void)
     147  {
     148    return 0;
     149  }