1  /* Copyright (C) 2007  Free Software Foundation.
       2  
       3     Verify that built-in folding of frexp is correctly performed by the
       4     compiler.
       5  
       6     Origin: Kaveh R. Ghazi,  February 21, 2007.  */
       7  
       8  /* { dg-do link } */
       9  /* { dg-options "-fno-finite-math-only" { target sh*-*-* } } */
      10  /* In order to fold algebraic exprs below, targets with "composite"
      11     floating point formats need -funsafe-math-optimizations.  */
      12  /* { dg-require-effective-target inf } */
      13  /* { dg-options "-funsafe-math-optimizations" { target powerpc*-*-* } } */
      14  
      15  extern void link_error(int);
      16  
      17  /* Return TRUE if the sign of X != sign of Y.  This is important when
      18     comparing signed zeros.  */
      19  #define CKSGN_F(X,Y) \
      20    (__builtin_copysignf(1.0F,(X)) != __builtin_copysignf(1.0F,(Y)))
      21  #define CKSGN(X,Y) \
      22    (__builtin_copysign(1.0,(X)) != __builtin_copysign(1.0,(Y)))
      23  #define CKSGN_L(X,Y) \
      24    (__builtin_copysignl(1.0L,(X)) != __builtin_copysignl(1.0L,(Y)))
      25  
      26  /* We can only check the exponent when optimizing since we rely on
      27     other optimizations to propagate the value.  TRUE means an error
      28     occurred.  */
      29  #ifdef __OPTIMIZE__
      30  #define CKEXP(X,Y) X != Y
      31  #else
      32  #define CKEXP(X,Y) 0
      33  #endif
      34  
      35  /* Test that frexp(ARG,&i) == RES && i == EXP.  Check the sign in
      36     case we get -0.0.  */
      37  #define TESTIT_FREXP(ARG,RES,EXP) do { \
      38    int i = 12345; \
      39    if (__builtin_frexpf(ARG##f,&i) != RES##f \
      40        || CKEXP(i,EXP) \
      41        || CKSGN_F(__builtin_frexpf(ARG##f,&i),RES##f)) \
      42      link_error(__LINE__); \
      43    i = 12345; \
      44    if (__builtin_frexp(ARG,&i) != RES \
      45        || CKEXP(i,EXP) \
      46        || CKSGN(__builtin_frexp(ARG,&i),RES)) \
      47      link_error(__LINE__); \
      48    i = 12345; \
      49    if (__builtin_frexpl(ARG##l,&i) != RES##l \
      50        || CKEXP(i,EXP) \
      51        || CKSGN_L(__builtin_frexpl(ARG##l,&i),RES##l)) \
      52      link_error(__LINE__); \
      53    } while (0)
      54  
      55  /* Test that FUNCRES(frexp(NEG FUNCARG(ARGARG),&i)) is false.  Check
      56     the sign as well.  Ensure side-effects are evaluated in i.  */
      57  #define TESTIT_FREXP2(NEG,FUNCARG,ARGARG,FUNCRES) do { \
      58    int i=5; \
      59    if (!__builtin_##FUNCRES##f(__builtin_frexpf(NEG __builtin_##FUNCARG##f(ARGARG),&i)) \
      60        || CKSGN_F(__builtin_frexpf(NEG __builtin_##FUNCARG##f(ARGARG),(i++,&i)), NEG __builtin_##FUNCARG##f(ARGARG)) \
      61        || CKEXP(i,6)) \
      62      link_error(__LINE__); \
      63    if (!__builtin_##FUNCRES(__builtin_frexp(NEG __builtin_##FUNCARG(ARGARG),&i)) \
      64        || CKSGN(__builtin_frexp(NEG __builtin_##FUNCARG(ARGARG),(i++,&i)), NEG __builtin_##FUNCARG(ARGARG)) \
      65        || CKEXP(i,7)) \
      66      link_error(__LINE__); \
      67    if (!__builtin_##FUNCRES##l(__builtin_frexpl(NEG __builtin_##FUNCARG##l(ARGARG),&i)) \
      68        || CKSGN_L(__builtin_frexpl(NEG __builtin_##FUNCARG##l(ARGARG),(i++,&i)), NEG __builtin_##FUNCARG##l(ARGARG)) \
      69        || CKEXP(i,8)) \
      70      link_error(__LINE__); \
      71    } while (0)
      72  
      73  void __attribute__ ((__noinline__))
      74  foo(void)
      75  {
      76    /* Test that frexp(ARG1,&i) -> ARG2 && i == ARG3.  */
      77    TESTIT_FREXP (-0x1p40, -0.5, 41);
      78    TESTIT_FREXP (-0x1p30, -0.5, 31);
      79    TESTIT_FREXP (-0x1p20, -0.5, 21);
      80    TESTIT_FREXP (-0x1p10, -0.5, 11);
      81    TESTIT_FREXP (-0x1p5, -0.5, 6);
      82    TESTIT_FREXP (-100/3.0, -100/192.0, 6);
      83    TESTIT_FREXP (-1.5, -0.75, 1);
      84    TESTIT_FREXP (-1.0, -0.5, 1);
      85    TESTIT_FREXP (-1/3.0, -2/3.0, -1);
      86    TESTIT_FREXP (-1/9.0, -8/9.0, -3);
      87    TESTIT_FREXP (-0x1p-5, -0.5, -4);
      88    TESTIT_FREXP (-0x1p-10, -0.5, -9);
      89    TESTIT_FREXP (-0x1p-20, -0.5, -19);
      90    TESTIT_FREXP (-0x1p-30, -0.5, -29);
      91    TESTIT_FREXP (-0x1p-40, -0.5, -39);
      92    TESTIT_FREXP (-0.0, -0.0, 0);
      93    TESTIT_FREXP (0.0, 0.0, 0);
      94    TESTIT_FREXP (0x1p-40, 0.5, -39);
      95    TESTIT_FREXP (0x1p-30, 0.5, -29);
      96    TESTIT_FREXP (0x1p-20, 0.5, -19);
      97    TESTIT_FREXP (0x1p-10, 0.5, -9);
      98    TESTIT_FREXP (0x1p-5, 0.5, -4);
      99    TESTIT_FREXP (1/9.0, 8/9.0, -3);
     100    TESTIT_FREXP (1/3.0, 2/3.0, -1);
     101    TESTIT_FREXP (1.0, 0.5, 1);
     102    TESTIT_FREXP (1.5, 0.75, 1);
     103    TESTIT_FREXP (100/3.0, 100/192.0, 6);
     104    TESTIT_FREXP (0x1p5, 0.5, 6);
     105    TESTIT_FREXP (0x1p10, 0.5, 11);
     106    TESTIT_FREXP (0x1p20, 0.5, 21);
     107    TESTIT_FREXP (0x1p30, 0.5, 31);
     108    TESTIT_FREXP (0x1p40, 0.5, 41);
     109  
     110    /* Test for frexp(+-Inf,&i) -> +-Inf and frexp(+-NaN,&i) -> +-NaN.
     111       Exponent is left unspecified, but we test for side-effects.  */
     112    TESTIT_FREXP2 ( ,inf, , isinf);
     113    TESTIT_FREXP2 (- ,inf, , isinf);
     114    TESTIT_FREXP2 ( ,nan, "", isnan);
     115    TESTIT_FREXP2 (- ,nan, "", isnan);
     116  }
     117  
     118  int main()
     119  {
     120    foo ();
     121    
     122    return 0;
     123  }