1  /* Check that calls to the vectorized math functions are actually emitted.  */
       2  
       3  /* { dg-do compile } */
       4  /* { dg-options "-O2 -ftree-vectorize -fno-math-errno -mstack-size=3000000 -fdump-tree-vect" } */
       5  
       6  
       7  #undef PRINT_RESULT
       8  #define VERBOSE 0
       9  #define EARLY_EXIT 1
      10  
      11  #include <math.h>
      12  #include <stdlib.h>
      13  
      14  #ifdef PRINT_RESULT
      15    #include <stdio.h>
      16    #define PRINTF printf
      17  #else
      18    static void null_printf (const char *f, ...) { }
      19  
      20    #define PRINTF null_printf
      21  #endif
      22  
      23  #define N 512
      24  #define EPSILON_float 1e-5
      25  #define EPSILON_double 1e-10
      26  
      27  static int failed = 0;
      28  
      29  int deviation_float (float x, float y)
      30  {
      31    union {
      32      float f;
      33      unsigned u;
      34    } u, v;
      35  
      36    u.f = x;
      37    v.f = y;
      38  
      39    unsigned mask = 0x80000000U; 
      40    int i;
      41  
      42    for (i = 32; i > 0; i--)
      43      if ((u.u ^ v.u) & mask)
      44        break;
      45      else
      46        mask >>= 1;
      47  
      48    return i;
      49  }
      50  
      51  int deviation_double (double x, double y)
      52  {
      53    union {
      54      double d;
      55      unsigned long long u;
      56    } u, v;
      57  
      58    u.d = x;
      59    v.d = y;
      60  
      61    unsigned long long mask = 0x8000000000000000ULL;
      62    int i;
      63  
      64    for (i = 64; i > 0; i--)
      65      if ((u.u ^ v.u) & mask)
      66        break;
      67      else
      68        mask >>= 1;
      69  
      70    return i;
      71  }
      72  
      73  #define TEST_FUN(TFLOAT, LOW, HIGH, FUN) \
      74  __attribute__((optimize("no-tree-vectorize"))) \
      75  __attribute__((optimize("no-unsafe-math-optimizations"))) \
      76  void check_##FUN (TFLOAT res[N], TFLOAT a[N]) \
      77  { \
      78    int failed = 0; \
      79    for (int i = 0; i < N; i++) { \
      80      TFLOAT expected = FUN (a[i]); \
      81      TFLOAT diff = __builtin_fabs (expected - res[i]); \
      82      int deviation = deviation_##TFLOAT (expected, res[i]); \
      83      int fail = isnan (res[i]) != isnan (expected) \
      84                 || isinf (res[i]) != isinf (expected) \
      85                 || (diff > EPSILON_##TFLOAT && deviation > 10); \
      86      failed |= fail; \
      87      if (VERBOSE || fail) \
      88        PRINTF (#FUN "(%f) = %f, expected = %f, diff = %f, deviation = %d %s\n", \
      89                a[i], res[i], expected, diff, deviation, fail ? "(!)" : ""); \
      90      if (EARLY_EXIT && fail) \
      91        exit (1); \
      92    } \
      93  } \
      94  void test_##FUN (void) \
      95  { \
      96    TFLOAT res[N], a[N]; \
      97    for (int i = 0; i < N; i++) \
      98      a[i] = LOW + ((HIGH - LOW) / N) * i; \
      99    for (int i = 0; i < N; i++) \
     100      res[i] = FUN (a[i]); \
     101    check_##FUN (res, a); \
     102  }\
     103  test_##FUN ();
     104  
     105  #define TEST_FUN2(TFLOAT, LOW1, HIGH1, LOW2, HIGH2, FUN) \
     106  __attribute__((optimize("no-tree-vectorize"))) \
     107  __attribute__((optimize("no-unsafe-math-optimizations"))) \
     108  void check_##FUN (TFLOAT res[N], TFLOAT a[N], TFLOAT b[N]) \
     109  { \
     110    int failed = 0; \
     111    for (int i = 0; i < N; i++) { \
     112      TFLOAT expected = FUN (a[i], b[i]); \
     113      TFLOAT diff = __builtin_fabs (expected - res[i]); \
     114      int deviation = deviation_##TFLOAT (expected, res[i]); \
     115      int fail = isnan (res[i]) != isnan (expected) \
     116                 || isinf (res[i]) != isinf (expected) \
     117                 || (diff > EPSILON_##TFLOAT && deviation > 10); \
     118      failed |= fail; \
     119      if (VERBOSE || fail) \
     120        PRINTF (#FUN "(%f,%f) = %f, expected = %f, diff = %f, deviation = %d %s\n", \
     121                a[i], b[i], res[i], expected, diff, deviation, fail ? "(!)" : ""); \
     122      if (EARLY_EXIT && fail) \
     123        exit (1); \
     124    } \
     125  } \
     126  void test_##FUN (void) \
     127  { \
     128    TFLOAT res[N], a[N], b[N]; \
     129    for (int i = 0; i < N; i++) { \
     130      a[i] = LOW1 + ((HIGH1 - LOW1) / N) * i; \
     131      b[i] = LOW2 + ((HIGH2 - LOW2) / N) * i; \
     132    } \
     133    for (int i = 0; i < N; i++) \
     134      res[i] = FUN (a[i], b[i]); \
     135    check_##FUN (res, a, b); \
     136  }\
     137  test_##FUN ();
     138  
     139  int main (void)
     140  {
     141    TEST_FUN (float, -1.1, 1.1, acosf); /* { dg-final { scan-tree-dump "v64sf_acosf" "vect" } }*/
     142    TEST_FUN (float, -10, 10, acoshf); /* { dg-final { scan-tree-dump "v64sf_acoshf" "vect" } }*/
     143    TEST_FUN (float, -1.1, 1.1, asinf); /* { dg-final { scan-tree-dump "v64sf_asinf" "vect" } }*/
     144    TEST_FUN (float, -10, 10, asinhf); /* { dg-final { scan-tree-dump "v64sf_asinhf" "vect" } }*/
     145    TEST_FUN (float, -1.1, 1.1, atanf); /* { dg-final { scan-tree-dump "v64sf_atanf" "vect" } }*/
     146    TEST_FUN2 (float, -2.0, 2.0, 2.0, -2.0, atan2f); /* { dg-final { scan-tree-dump "v64sf_atan2f" "vect" } }*/
     147    TEST_FUN (float, -2.0, 2.0, atanhf); /* { dg-final { scan-tree-dump "v64sf_atanhf" "vect" } }*/
     148    TEST_FUN2 (float, -10.0, 10.0, 5.0, -15.0, copysignf); /* { dg-final { scan-tree-dump "v64sf_copysignf" "vect" } }*/
     149    TEST_FUN (float, -3.14159265359, 3.14159265359, cosf); /* { dg-final { scan-tree-dump "v64sf_cosf" "vect" } }*/
     150    TEST_FUN (float, -3.14159265359, 3.14159265359, coshf); /* { dg-final { scan-tree-dump "v64sf_coshf" "vect" } }*/
     151    TEST_FUN (float, -10.0, 10.0, erff);  /* { dg-final { scan-tree-dump "v64sf_erff" "vect" } }*/
     152    TEST_FUN (float, -10.0, 10.0, expf); /* { dg-final { scan-tree-dump "v64sf_expf" "vect" } }*/
     153    TEST_FUN (float, -10.0, 10.0, exp2f); /* { dg-final { scan-tree-dump "v64sf_exp2f" "vect" } }*/
     154    TEST_FUN2 (float, -10.0, 10.0, 100.0, -25.0, fmodf); /* { dg-final { scan-tree-dump "v64sf_fmodf" "vect" } }*/
     155    TEST_FUN (float, -10.0, 10.0, gammaf); /* { dg-final { scan-tree-dump "v64sf_gammaf" "vect" { xfail *-*-*} } }*/
     156    TEST_FUN2 (float, -10.0, 10.0, 15.0, -5.0,hypotf); /* { dg-final { scan-tree-dump "v64sf_hypotf" "vect" } }*/
     157    TEST_FUN (float, -10.0, 10.0, lgammaf); /* { dg-final { scan-tree-dump "v64sf_lgammaf" "vect" { xfail *-*-*} } }*/
     158    TEST_FUN (float, -1.0, 50.0, logf); /* { dg-final { scan-tree-dump "v64sf_logf" "vect" } }*/
     159    TEST_FUN (float, -1.0, 500.0, log10f); /* { dg-final { scan-tree-dump "v64sf_log10f" "vect" } }*/
     160    TEST_FUN (float, -1.0, 64.0, log2f); /* { dg-final { scan-tree-dump "v64sf_log2f" "vect" } }*/
     161    TEST_FUN2 (float, -100.0, 100.0, 100.0, -100.0, powf); /* { dg-final { scan-tree-dump "v64sf_powf" "vect" } }*/
     162    TEST_FUN2 (float, -50.0, 100.0, -2.0, 40.0, remainderf); /* { dg-final { scan-tree-dump "v64sf_remainderf" "vect" } }*/
     163    TEST_FUN (float, -50.0, 50.0, rintf);  /* { dg-final { scan-tree-dump "v64sf_rintf" "vect" } }*/
     164    TEST_FUN2 (float, -50.0, 50.0, -10.0, 32.0, __builtin_scalbf); /* { dg-final { scan-tree-dump "v64sf_scalbf" "vect" } }*/
     165    TEST_FUN (float, -10.0, 10.0, __builtin_significandf); /* { dg-final { scan-tree-dump "v64sf_significandf" "vect" } }*/
     166    TEST_FUN (float, -3.14159265359, 3.14159265359, sinf); /* { dg-final { scan-tree-dump "v64sf_sinf" "vect" } }*/
     167    TEST_FUN (float, -3.14159265359, 3.14159265359, sinhf); /* { dg-final { scan-tree-dump "v64sf_sinhf" "vect" } }*/
     168    TEST_FUN (float, -0.1, 10000.0, sqrtf); /* { dg-final { scan-tree-dump "v64sf_sqrtf" "vect" } }*/
     169    TEST_FUN (float, -5.0, 5.0, tanf); /* { dg-final { scan-tree-dump "v64sf_tanf" "vect" } }*/
     170    TEST_FUN (float, -3.14159265359, 3.14159265359, tanhf); /* { dg-final { scan-tree-dump "v64sf_tanhf" "vect" } }*/
     171    TEST_FUN (float, -10.0, 10.0, tgammaf); /* { dg-final { scan-tree-dump "v64sf_tgammaf" "vect" } }*/
     172  
     173    TEST_FUN (double, -1.1, 1.1, acos); /* { dg-final { scan-tree-dump "v64df_acos" "vect" } }*/
     174    TEST_FUN (double, -10, 10, acosh); /* { dg-final { scan-tree-dump "v64df_acosh" "vect" } }*/
     175    TEST_FUN (double, -1.1, 1.1, asin); /* { dg-final { scan-tree-dump "v64df_asin" "vect" } }*/
     176    TEST_FUN (double, -10, 10, asinh); /* { dg-final { scan-tree-dump "v64df_asinh" "vect" } }*/
     177    TEST_FUN (double, -1.1, 1.1, atan); /* { dg-final { scan-tree-dump "v64df_atan" "vect" } }*/
     178    TEST_FUN2 (double, -2.0, 2.0, 2.0, -2.0, atan2); /* { dg-final { scan-tree-dump "v64df_atan2" "vect" } }*/
     179    TEST_FUN (double, -2.0, 2.0, atanh); /* { dg-final { scan-tree-dump "v64df_atanh" "vect" } }*/
     180    TEST_FUN2 (double, -10.0, 10.0, 5.0, -15.0, copysign); /* { dg-final { scan-tree-dump "v64df_copysign" "vect" } }*/
     181    TEST_FUN (double, -3.14159265359, 3.14159265359, cos); /* { dg-final { scan-tree-dump "v64df_cos" "vect" } }*/
     182    TEST_FUN (double, -3.14159265359, 3.14159265359, cosh); /* { dg-final { scan-tree-dump "v64df_cosh" "vect" } }*/
     183    TEST_FUN (double, -10.0, 10.0, erf); /* { dg-final { scan-tree-dump "v64df_erf" "vect" } }*/
     184    TEST_FUN (double, -10.0, 10.0, exp); /* { dg-final { scan-tree-dump "v64df_exp" "vect" } }*/
     185    TEST_FUN (double, -10.0, 10.0, exp2); /* { dg-final { scan-tree-dump "v64df_exp2" "vect" } }*/
     186    TEST_FUN2 (double, -10.0, 10.0, 100.0, -25.0, fmod); /* { dg-final { scan-tree-dump "v64df_fmod" "vect" } }*/
     187    TEST_FUN (double, -10.0, 10.0, gamma); /* { dg-final { scan-tree-dump "v64df_gamma" "vect" { xfail *-*-*} } }*/
     188    TEST_FUN2 (double, -10.0, 10.0, 15.0, -5.0, hypot); /* { dg-final { scan-tree-dump "v64df_hypot" "vect" } }*/
     189    TEST_FUN (double, -10.0, 10.0, lgamma); /* { dg-final { scan-tree-dump "v64df_lgamma" "vect" { xfail *-*-*} } }*/
     190    TEST_FUN (double, -1.0, 50.0, log); /* { dg-final { scan-tree-dump "v64df_log" "vect" } }*/
     191    TEST_FUN (double, -1.0, 500.0, log10); /* { dg-final { scan-tree-dump "v64df_log10" "vect" } }*/
     192    TEST_FUN (double, -1.0, 64.0, log2); /* { dg-final { scan-tree-dump "v64df_log2" "vect" { xfail *-*-*} } }*/
     193    TEST_FUN2 (double, -100.0, 100.0, 100.0, -100.0, pow); /* { dg-final { scan-tree-dump "v64df_pow" "vect" } }*/
     194    TEST_FUN2 (double, -50.0, 100.0, -2.0, 40.0, remainder); /* { dg-final { scan-tree-dump "v64df_remainder" "vect" } }*/
     195    TEST_FUN (double, -50.0, 50.0, rint); /* { dg-final { scan-tree-dump "v64df_rint" "vect" } }*/
     196    TEST_FUN2 (double, -50.0, 50.0, -10.0, 32.0, __builtin_scalb); /* { dg-final { scan-tree-dump "v64df_scalb" "vect" } }*/
     197    TEST_FUN (double, -10.0, 10.0, __builtin_significand); /* { dg-final { scan-tree-dump "v64df_significand" "vect" } }*/
     198    TEST_FUN (double, -3.14159265359, 3.14159265359, sin); /* { dg-final { scan-tree-dump "v64df_sin" "vect" } }*/
     199    TEST_FUN (double, -3.14159265359, 3.14159265359, sinh); /* { dg-final { scan-tree-dump "v64df_sinh" "vect" } }*/
     200    TEST_FUN (double, -0.1, 10000.0, sqrt); /* { dg-final { scan-tree-dump "v64df_sqrt" "vect" } }*/
     201    TEST_FUN (double, -5.0, 5.0, tan); /* { dg-final { scan-tree-dump "v64df_tan" "vect" } }*/
     202    TEST_FUN (double, -3.14159265359, 3.14159265359, tanh); /* { dg-final { scan-tree-dump "v64df_tanh" "vect" } }*/
     203    TEST_FUN (double, -10.0, 10.0, tgamma); /* { dg-final { scan-tree-dump "v64df_tgamma" "vect" } }*/
     204  
     205    return failed;
     206  }