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