/* Test vneg works correctly. */ /* { dg-do run } */ /* { dg-options "--save-temps" } */ #include #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; } /* { dg-final { cleanup-saved-temps } } */