text: /* Test vneg works correctly.  */
  /* { dg-do run } */
  /* { dg-options "--save-temps" } */
  
  #include <arm_neon.h>
  
  #define FLT_EPSILON __FLT_EPSILON__
  #define DBL_EPSILON __DBL_EPSILON__
  #define FLT_MAX __FLT_MAX__
  #define FLT_MIN __FLT_MIN__
  #define DBL_MAX __DBL_MAX__
  #define DBL_MIN __DBL_MIN__
  
  #define TEST0 0
  /* 6 digits of pi.  */
  #define TEST1 3.14159
  /* 6 digits of -e.  */
  #define TEST2 -2.71828
  /* 2^25, float has 24 significand bits
     according to Single-precision floating-point format.  */
  #define TEST3_FLT 33554432
  /* 2^54, double has 53 significand bits
     according to Double-precision floating-point format.  */
  #define TEST3_DBL 18014398509481984
  
  extern void abort (void);
  
  #define FLT_INFINITY (__builtin_inff ())
  #define DBL_INFINITY (__builtin_inf ())
  
  #ifndef NAN
  #define NAN (0.0 / 0.0)
  #endif
  
  #define CONCAT(a, b) a##b
  #define CONCAT1(a, b) CONCAT (a, b)
  #define REG_INFEX64 _
  #define REG_INFEX128 q_
  #define REG_INFEX(reg_len) REG_INFEX##reg_len
  #define POSTFIX(reg_len, data_len) \
    CONCAT1 (REG_INFEX (reg_len), f##data_len)
  
  #define DATA_TYPE_32 float
  #define DATA_TYPE_64 double
  #define DATA_TYPE(data_len) DATA_TYPE_##data_len
  
  #define STORE_INST(reg_len, data_len) \
    CONCAT1 (vst1, POSTFIX (reg_len, data_len))
  #define LOAD_INST(reg_len, data_len) \
    CONCAT1 (vld1, POSTFIX (reg_len, data_len))
  #define NEG_INST(reg_len, data_len) \
    CONCAT1 (vneg, POSTFIX (reg_len, data_len))
  
  #define INHIB_OPTIMIZATION asm volatile ("" : : : "memory")
  #define RUN_TEST(test_set, reg_len, data_len, n, a, b, c) \
    {						       \
      int i;					       \
      (a) = LOAD_INST (reg_len, data_len) (test_set);    \
      (b) = NEG_INST (reg_len, data_len) (a);	       \
      STORE_INST (reg_len, data_len) (c, b);	       \
      for (i = 0; i < n; i++)			       \
        {						       \
  	DATA_TYPE (data_len) diff;		       \
  	INHIB_OPTIMIZATION;			       \
  	diff = test_set[i] + c[i];		       \
  	if (diff > EPSILON)			       \
  	    return 1;				       \
        }						       \
    }
  
  #define TEST3 TEST3_FLT
  #define EPSILON FLT_EPSILON
  #define VAR_MIN FLT_MIN
  #define VAR_MAX FLT_MAX
  #define INFINITY FLT_INFINITY
  
  int
  test_vneg_f32 ()
  {
    float32x2_t a;
    float32x2_t b;
    float32_t c[2];
  
    float32_t test_set0[2] = { TEST0, TEST1 };
    float32_t test_set1[2] = { TEST2, TEST3 };
    float32_t test_set2[2] = { VAR_MAX, VAR_MIN };
    float32_t test_set3[2] = { INFINITY, NAN };
  
    RUN_TEST (test_set0, 64, 32, 2, a, b, c);
    RUN_TEST (test_set1, 64, 32, 2, a, b, c);
    RUN_TEST (test_set2, 64, 32, 2, a, b, c);
    RUN_TEST (test_set3, 64, 32, 0, a, b, c);
  
    /* Since last test cannot be checked in a uniform way by adding
       negation result to original value, the number of lanes to be
       checked in RUN_TEST is 0 (last argument).  Instead, result
       will be checked manually.  */
  
    if (c[0] != -INFINITY)
      return 1;
  
    if (!__builtin_isnan (c[1]))
      return 1;
  
    return 0;
  }
  
  /* { dg-final { scan-assembler-times "fneg\\tv\[0-9\]+\.2s, v\[0-9\]+\.2s" 4 } } */
  
  #undef TEST3
  #undef EPSILON
  #undef VAR_MIN
  #undef VAR_MAX
  #undef INFINITY
  
  #define TEST3 TEST3_DBL
  #define EPSILON DBL_EPSILON
  #define VAR_MIN DBL_MIN
  #define VAR_MAX DBL_MAX
  #define INFINITY DBL_INFINITY
  
  int
  test_vneg_f64 ()
  {
    float64x1_t a;
    float64x1_t b;
    float64_t c[1];
  
    float64_t test_set0[1] = { TEST0 };
    float64_t test_set1[1] = { TEST1 };
    float64_t test_set2[1] = { TEST2 };
    float64_t test_set3[1] = { TEST3 };
    float64_t test_set4[1] = { VAR_MAX };
    float64_t test_set5[1] = { VAR_MIN };
    float64_t test_set6[1] = { INFINITY };
    float64_t test_set7[1] = { NAN };
  
    RUN_TEST (test_set0, 64, 64, 1, a, b, c);
    RUN_TEST (test_set1, 64, 64, 1, a, b, c);
    RUN_TEST (test_set2, 64, 64, 1, a, b, c);
    RUN_TEST (test_set3, 64, 64, 1, a, b, c);
    RUN_TEST (test_set4, 64, 64, 1, a, b, c);
    RUN_TEST (test_set5, 64, 64, 1, a, b, c);
    RUN_TEST (test_set6, 64, 64, 0, a, b, c);
  
    /* Since last test cannot be checked in a uniform way by adding
       negation result to original value, the number of lanes to be
       checked in RUN_TEST is 0 (last argument).  Instead, result
       will be checked manually.  */
  
    if (c[0] != -INFINITY)
      return 1;
  
    /* Same as above.  */
  
    RUN_TEST (test_set7, 64, 64, 0, a, b, c);
  
    if (!__builtin_isnan (c[0]))
      return 1;
  
    return 0;
  }
  
  /* { dg-final { scan-assembler-times "fneg\\td\[0-9\]+, d\[0-9\]+" 8 } } */
  
  #undef TEST3
  #undef EPSILON
  #undef VAR_MIN
  #undef VAR_MAX
  #undef INFINITY
  
  #define TEST3 TEST3_FLT
  #define EPSILON FLT_EPSILON
  #define VAR_MIN FLT_MIN
  #define VAR_MAX FLT_MAX
  #define INFINITY FLT_INFINITY
  
  int
  test_vnegq_f32 ()
  {
    float32x4_t a;
    float32x4_t b;
    float32_t c[4];
  
    float32_t test_set0[4] = { TEST0, TEST1, TEST2, TEST3 };
    float32_t test_set1[4] = { FLT_MAX, FLT_MIN, INFINITY, NAN };
  
    RUN_TEST (test_set0, 128, 32, 4, a, b, c);
    RUN_TEST (test_set1, 128, 32, 2, a, b, c);
  
    /* Since last test cannot be fully checked in a uniform way by
       adding negation result to original value, the number of lanes
       to be checked in RUN_TEST is 0 (last argument).  Instead, result
       will be checked manually.  */
  
    if (c[2] != -INFINITY)
      return 1;
  
    if (!__builtin_isnan (c[3]))
      return 1;
  
    return 0;
  }
  
  /* { dg-final { scan-assembler-times "fneg\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s" 2 } } */
  
  #undef TEST3
  #undef EPSILON
  #undef VAR_MIN
  #undef VAR_MAX
  #undef INFINITY
  
  #define TEST3 TEST3_DBL
  #define EPSILON DBL_EPSILON
  #define VAR_MIN DBL_MIN
  #define VAR_MAX DBL_MAX
  #define INFINITY DBL_INFINITY
  
  int
  test_vnegq_f64 ()
  {
    float64x2_t a;
    float64x2_t b;
    float64_t c[2];
  
    float64_t test_set0[2] = { TEST0, TEST1 };
    float64_t test_set1[2] = { TEST2, TEST3 };
    float64_t test_set2[2] = { FLT_MAX, FLT_MIN };
    float64_t test_set3[2] = { INFINITY, NAN };
  
    RUN_TEST (test_set0, 128, 64, 2, a, b, c);
    RUN_TEST (test_set1, 128, 64, 2, a, b, c);
    RUN_TEST (test_set2, 128, 64, 2, a, b, c);
    RUN_TEST (test_set3, 128, 64, 0, a, b, c);
  
    /* Since last test cannot be checked in a uniform way by adding
       negation result to original value, the number of lanes to be
       checked in RUN_TEST is 0 (last argument).  Instead, result
       will be checked manually.  */
  
    if (c[0] != -INFINITY)
      return 1;
  
    if (!__builtin_isnan (c[1]))
      return 1;
  
    return 0;
  }
  
  /* { dg-final { scan-assembler-times "fneg\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d" 4 } } */
  
  int
  main (int argc, char **argv)
  {
    if (test_vneg_f32 ())
      abort ();
  
    if (test_vneg_f64 ())
      abort ();
  
    if (test_vnegq_f32 ())
      abort ();
  
    if (test_vnegq_f64 ())
      abort ();
  
    return 0;
  }
  
  