From 5cbaf84c191b9a3e3cb26545c808d208bdbf2ab5 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 13 Oct 2022 14:24:05 +0200 Subject: tree-optimization/107160 - avoid reusing multiple accumulators Epilogue vectorization is not set up to re-use a vectorized accumulator consisting of more than one vector. For non-SLP we always reduce to a single but for SLP that isn't happening. In such case we currenlty miscompile the epilog so avoid this. PR tree-optimization/107160 * tree-vect-loop.cc (vect_create_epilog_for_reduction): Do not register accumulator if we failed to reduce it to a single vector. * gcc.dg/vect/pr107160.c: New testcase. --- gcc/testsuite/gcc.dg/vect/pr107160.c | 41 ++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/vect/pr107160.c (limited to 'gcc/testsuite') diff --git a/gcc/testsuite/gcc.dg/vect/pr107160.c b/gcc/testsuite/gcc.dg/vect/pr107160.c new file mode 100644 index 0000000..4f9f853c --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr107160.c @@ -0,0 +1,41 @@ +/* { dg-do run } */ + +#include + +#define N 128 +float fl[N]; + +__attribute__ ((noipa)) void +init () +{ + for (int i = 0; i < N; i++) + fl[i] = i; +} + +__attribute__ ((noipa)) float +foo (int n1) +{ + float sum0, sum1, sum2, sum3; + sum0 = sum1 = sum2 = sum3 = 0.0f; + + int n = (n1 / 4) * 4; + for (int i = 0; i < n; i += 4) + { + sum0 += fabs (fl[i]); + sum1 += fabs (fl[i + 1]); + sum2 += fabs (fl[i + 2]); + sum3 += fabs (fl[i + 3]); + } + + return sum0 + sum1 + sum2 + sum3; +} + +int +main () +{ + init (); + float res = foo (80); + if (res != 3160) + __builtin_abort (); + return 0; +} -- cgit v1.1 From 1cccf644ff92ac1145abdbf255d1862dd787875b Mon Sep 17 00:00:00 2001 From: Wilco Dijkstra Date: Thu, 13 Oct 2022 14:41:55 +0100 Subject: [AArch64] Improve bit tests [PR105773] Since AArch64 sets all flags on logical operations, comparisons with zero can be combined into an AND even if the condition is LE or GT. Add a new CC_NZV mode used by ANDS/BICS/TST instructions. gcc/ PR target/105773 * config/aarch64/aarch64.cc (aarch64_select_cc_mode): Allow GT/LE for merging compare with zero into AND. (aarch64_get_condition_code_1): Add CC_NZVmode support. * config/aarch64/aarch64-modes.def: Add CC_NZV. * config/aarch64/aarch64.md: Use CC_NZV in cmp+and patterns. gcc/testsuite/ PR target/105773 * gcc.target/aarch64/ands_2.c: Test for ANDS. * gcc.target/aarch64/bics_2.c: Test for BICS. * gcc.target/aarch64/tst_2.c: Test for TST. * gcc.target/aarch64/tst_imm_split_1.c: Fix test. --- gcc/testsuite/gcc.target/aarch64/ands_2.c | 30 +++++++++------------- gcc/testsuite/gcc.target/aarch64/bics_2.c | 24 ++++++++--------- gcc/testsuite/gcc.target/aarch64/tst_2.c | 30 +++++++++------------- gcc/testsuite/gcc.target/aarch64/tst_imm_split_1.c | 3 +-- 4 files changed, 35 insertions(+), 52 deletions(-) (limited to 'gcc/testsuite') diff --git a/gcc/testsuite/gcc.target/aarch64/ands_2.c b/gcc/testsuite/gcc.target/aarch64/ands_2.c index b061b1d..c8763f2 100644 --- a/gcc/testsuite/gcc.target/aarch64/ands_2.c +++ b/gcc/testsuite/gcc.target/aarch64/ands_2.c @@ -8,8 +8,7 @@ ands_si_test1 (int a, int b, int c) { int d = a & b; - /* { dg-final { scan-assembler-not "ands\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" } } */ - /* { dg-final { scan-assembler-times "and\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" 2 } } */ + /* { dg-final { scan-assembler "ands\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" } } */ if (d <= 0) return a + c; else @@ -21,12 +20,11 @@ ands_si_test2 (int a, int b, int c) { int d = a & 0x99999999; - /* { dg-final { scan-assembler-not "ands\tw\[0-9\]+, w\[0-9\]+, -1717986919" } } */ - /* { dg-final { scan-assembler "and\tw\[0-9\]+, w\[0-9\]+, -1717986919" } } */ - if (d <= 0) - return a + c; - else + /* { dg-final { scan-assembler "ands\tw\[0-9\]+, w\[0-9\]+, -1717986919" } } */ + if (d > 0) return b + d + c; + else + return a + c; } int @@ -34,8 +32,7 @@ ands_si_test3 (int a, int b, int c) { int d = a & (b << 3); - /* { dg-final { scan-assembler-not "ands\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, lsl 3" } } */ - /* { dg-final { scan-assembler "and\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, lsl 3" } } */ + /* { dg-final { scan-assembler "ands\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, lsl 3" } } */ if (d <= 0) return a + c; else @@ -49,8 +46,7 @@ ands_di_test1 (s64 a, s64 b, s64 c) { s64 d = a & b; - /* { dg-final { scan-assembler-not "ands\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+" } } */ - /* { dg-final { scan-assembler-times "and\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+" 2 } } */ + /* { dg-final { scan-assembler "ands\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+" } } */ if (d <= 0) return a + c; else @@ -62,12 +58,11 @@ ands_di_test2 (s64 a, s64 b, s64 c) { s64 d = a & 0xaaaaaaaaaaaaaaaall; - /* { dg-final { scan-assembler-not "ands\tx\[0-9\]+, x\[0-9\]+, -6148914691236517206" } } */ - /* { dg-final { scan-assembler "and\tx\[0-9\]+, x\[0-9\]+, -6148914691236517206" } } */ - if (d <= 0) - return a + c; - else + /* { dg-final { scan-assembler "ands\tx\[0-9\]+, x\[0-9\]+, -6148914691236517206" } } */ + if (d > 0) return b + d + c; + else + return a + c; } s64 @@ -75,8 +70,7 @@ ands_di_test3 (s64 a, s64 b, s64 c) { s64 d = a & (b << 3); - /* { dg-final { scan-assembler-not "ands\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, lsl 3" } } */ - /* { dg-final { scan-assembler "and\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, lsl 3" } } */ + /* { dg-final { scan-assembler "ands\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, lsl 3" } } */ if (d <= 0) return a + c; else diff --git a/gcc/testsuite/gcc.target/aarch64/bics_2.c b/gcc/testsuite/gcc.target/aarch64/bics_2.c index 9ccae36..c1f7e87 100644 --- a/gcc/testsuite/gcc.target/aarch64/bics_2.c +++ b/gcc/testsuite/gcc.target/aarch64/bics_2.c @@ -8,8 +8,7 @@ bics_si_test1 (int a, int b, int c) { int d = a & ~b; - /* { dg-final { scan-assembler-not "bics\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" } } */ - /* { dg-final { scan-assembler-times "bic\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" 2 } } */ + /* { dg-final { scan-assembler "bics\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" } } */ if (d <= 0) return a + c; else @@ -21,12 +20,11 @@ bics_si_test2 (int a, int b, int c) { int d = a & ~(b << 3); - /* { dg-final { scan-assembler-not "bics\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, lsl 3" } } */ - /* { dg-final { scan-assembler "bic\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, lsl 3" } } */ - if (d <= 0) - return a + c; - else + /* { dg-final { scan-assembler "bics\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, lsl 3" } } */ + if (d > 0) return b + d + c; + else + return a + c; } typedef long long s64; @@ -36,8 +34,7 @@ bics_di_test1 (s64 a, s64 b, s64 c) { s64 d = a & ~b; - /* { dg-final { scan-assembler-not "bics\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+" } } */ - /* { dg-final { scan-assembler-times "bic\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+" 2 } } */ + /* { dg-final { scan-assembler "bics\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+" } } */ if (d <= 0) return a + c; else @@ -49,12 +46,11 @@ bics_di_test2 (s64 a, s64 b, s64 c) { s64 d = a & ~(b << 3); - /* { dg-final { scan-assembler-not "bics\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, lsl 3" } } */ - /* { dg-final { scan-assembler "bic\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, lsl 3" } } */ - if (d <= 0) - return a + c; - else + /* { dg-final { scan-assembler "bics\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, lsl 3" } } */ + if (d > 0) return b + d + c; + else + return a + c; } int diff --git a/gcc/testsuite/gcc.target/aarch64/tst_2.c b/gcc/testsuite/gcc.target/aarch64/tst_2.c index c8b28fc..3c9bdfd 100644 --- a/gcc/testsuite/gcc.target/aarch64/tst_2.c +++ b/gcc/testsuite/gcc.target/aarch64/tst_2.c @@ -8,8 +8,7 @@ tst_si_test1 (int a, int b, int c) { int d = a & b; - /* { dg-final { scan-assembler-not "tst\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" } } */ - /* { dg-final { scan-assembler-times "and\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+" 2 } } */ + /* { dg-final { scan-assembler "tst\tw\[0-9\]+, w\[0-9\]+" } } */ if (d <= 0) return 12; else @@ -21,12 +20,11 @@ tst_si_test2 (int a, int b, int c) { int d = a & 0x99999999; - /* { dg-final { scan-assembler-not "tst\tw\[0-9\]+, w\[0-9\]+, -1717986919" } } */ - /* { dg-final { scan-assembler "and\tw\[0-9\]+, w\[0-9\]+, -1717986919" } } */ - if (d <= 0) - return 12; - else + /* { dg-final { scan-assembler "tst\tw\[0-9\]+, -1717986919" } } */ + if (d > 0) return 18; + else + return 12; } int @@ -34,8 +32,7 @@ tst_si_test3 (int a, int b, int c) { int d = a & (b << 3); - /* { dg-final { scan-assembler-not "tst\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, lsl 3" } } */ - /* { dg-final { scan-assembler "and\tw\[0-9\]+, w\[0-9\]+, w\[0-9\]+, lsl 3" } } */ + /* { dg-final { scan-assembler "tst\tw\[0-9\]+, w\[0-9\]+, lsl 3" } } */ if (d <= 0) return 12; else @@ -49,8 +46,7 @@ tst_di_test1 (s64 a, s64 b, s64 c) { s64 d = a & b; - /* { dg-final { scan-assembler-not "tst\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+" } } */ - /* { dg-final { scan-assembler-times "and\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+" 2 } } */ + /* { dg-final { scan-assembler "tst\tx\[0-9\]+, x\[0-9\]+" } } */ if (d <= 0) return 12; else @@ -62,8 +58,7 @@ tst_di_test2 (s64 a, s64 b, s64 c) { s64 d = a & 0xaaaaaaaaaaaaaaaall; - /* { dg-final { scan-assembler-not "tst\tx\[0-9\]+, x\[0-9\]+, -6148914691236517206" } } */ - /* { dg-final { scan-assembler "and\tx\[0-9\]+, x\[0-9\]+, -6148914691236517206" } } */ + /* { dg-final { scan-assembler "tst\tx\[0-9\]+, -6148914691236517206" } } */ if (d <= 0) return 12; else @@ -75,12 +70,11 @@ tst_di_test3 (s64 a, s64 b, s64 c) { s64 d = a & (b << 3); - /* { dg-final { scan-assembler-not "tst\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, lsl 3" } } */ - /* { dg-final { scan-assembler "and\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+, lsl 3" } } */ - if (d <= 0) - return 12; - else + /* { dg-final { scan-assembler "tst\tx\[0-9\]+, x\[0-9\]+, lsl 3" } } */ + if (d > 0) return 18; + else + return 12; } int diff --git a/gcc/testsuite/gcc.target/aarch64/tst_imm_split_1.c b/gcc/testsuite/gcc.target/aarch64/tst_imm_split_1.c index 33a2c0f..e456e82 100644 --- a/gcc/testsuite/gcc.target/aarch64/tst_imm_split_1.c +++ b/gcc/testsuite/gcc.target/aarch64/tst_imm_split_1.c @@ -14,5 +14,4 @@ g (unsigned char *p) } /* { dg-final { scan-assembler-not "and\\t\[xw\]\[0-9\]+, \[xw\]\[0-9\]+.*" } } */ -/* { dg-final { scan-assembler "tst\\t\[xw\]\[0-9\]+, \[xw\]\[0-9\]+" } } */ -/* { dg-final { scan-assembler "tst\\t\[xw\]\[0-9\]+, \[xw\]\[0-9\]+, lsr 4" } } */ +/* { dg-final { scan-assembler-times "tst\\t\[xw\]\[0-9\]+, \[xw\]\[0-9\]+" 2 } } */ -- cgit v1.1 From 3130e70dab1e64a7b014391fe941090d5f3b6b7d Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Tue, 11 Oct 2022 14:16:54 -0400 Subject: c++: ICE with VEC_INIT_EXPR and defarg [PR106925] Since r12-8066, in cxx_eval_vec_init we perform expand_vec_init_expr while processing the default argument in this test. At this point start_preparsed_function hasn't yet set current_function_decl. expand_vec_init_expr then leads to maybe_splice_retval_cleanup which checks DECL_CONSTRUCTOR_P (current_function_decl) without checking that c_f_d is non-null first. It seems correct that c_f_d is null here, so it seems to me that maybe_splice_retval_cleanup should check c_f_d as in the following patch. PR c++/106925 gcc/cp/ChangeLog: * except.cc (maybe_splice_retval_cleanup): Check current_function_decl. Make the bool const. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/initlist-defarg3.C: New test. --- gcc/testsuite/g++.dg/cpp0x/initlist-defarg3.C | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp0x/initlist-defarg3.C (limited to 'gcc/testsuite') diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-defarg3.C b/gcc/testsuite/g++.dg/cpp0x/initlist-defarg3.C new file mode 100644 index 0000000..5c3e886 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-defarg3.C @@ -0,0 +1,13 @@ +// PR c++/106925 +// { dg-do compile { target c++11 } } + +struct Foo; +template struct __array_traits { typedef Foo _Type[_Nm]; }; +template struct array { + typename __array_traits<_Nm>::_Type _M_elems; +}; +template struct MyVector { array data{}; }; +struct Foo { + float a{0}; +}; +void foo(MyVector<1> = MyVector<1>()); -- cgit v1.1 From 6cc3394507a2303a18891d34222c53f679256c37 Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Wed, 5 Oct 2022 10:42:07 -0400 Subject: propagate partial equivs in the cache. Adjust on-entry cache propagation to look for and propagate both full and partial equivalences. gcc/ PR tree-optimization/102540 PR tree-optimization/102872 * gimple-range-cache.cc (ranger_cache::fill_block_cache): Handle partial equivs. (ranger_cache::range_from_dom): Cleanup dump output. gcc/testsuite/ * gcc.dg/pr102540.c: New. * gcc.dg/pr102872.c: New. --- gcc/testsuite/gcc.dg/pr102540.c | 19 +++++++++++++++++++ gcc/testsuite/gcc.dg/pr102872.c | 16 ++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/pr102540.c create mode 100644 gcc/testsuite/gcc.dg/pr102872.c (limited to 'gcc/testsuite') diff --git a/gcc/testsuite/gcc.dg/pr102540.c b/gcc/testsuite/gcc.dg/pr102540.c new file mode 100644 index 0000000..c12f8fc --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr102540.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fdump-tree-evrp" } */ + + +void kill(); + +static long a; +static unsigned b; +int test1 () { + long c, e; + c = b = a; + e = c ? 2 / (c + 1) : 0; + if (e && !b) + kill (); + a = 0; +} + +/* { dg-final { scan-tree-dump-not "kill" "evrp" } } */ + diff --git a/gcc/testsuite/gcc.dg/pr102872.c b/gcc/testsuite/gcc.dg/pr102872.c new file mode 100644 index 0000000..971bb03 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr102872.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-evrp" } */ + +void foo(void); + +static int a, b; +int main() { + for (; a; ++a) { + unsigned short d = a; + if (!(b | d) && d) + foo(); + } +} + +/* { dg-final { scan-tree-dump-not "foo" "evrp" } } */ + -- cgit v1.1 From 99da523359e9333555585484eb3b8f854a98f1b4 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 13 Oct 2022 16:05:35 -0400 Subject: analyzer: fix ICE introduced in r13-3168 [PR107210] gcc/analyzer/ChangeLog: PR analyzer/107210 * svalue.cc (constant_svalue::maybe_fold_bits_within): Only attempt to extract individual bits when tree_fits_uhwi_p. gcc/testsuite/ChangeLog: PR analyzer/107210 * gfortran.dg/analyzer/pr107210.f90: New test. Signed-off-by: David Malcolm --- gcc/testsuite/gfortran.dg/analyzer/pr107210.f90 | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 gcc/testsuite/gfortran.dg/analyzer/pr107210.f90 (limited to 'gcc/testsuite') diff --git a/gcc/testsuite/gfortran.dg/analyzer/pr107210.f90 b/gcc/testsuite/gfortran.dg/analyzer/pr107210.f90 new file mode 100644 index 0000000..6132db4 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/analyzer/pr107210.f90 @@ -0,0 +1,16 @@ +! { dg-additional-options "-O1" } + +subroutine check_int (j) + INTEGER(4) :: i, ia(5), ib(5,4), ip, ipa(:) + target :: ib + POINTER :: ip, ipa + logical :: l(5) + + ipa=>ib(2:3,1) + + l = (/ sizeof(i) == 4, sizeof(ia) == 20, sizeof(ib) == 80, & + sizeof(ip) == 4, sizeof(ipa) == 8 /) + + if (any(.not.l)) STOP 4 + +end subroutine check_int -- cgit v1.1 From c26d335fffc689051ee5826455c9d54d1fcf1816 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Fri, 14 Oct 2022 00:55:40 +0200 Subject: Fix bogus -Wstringop-overflow warning If you compile the testcase with -O2 -fno-inline -Wall, you get: In function 'process_array3': cc1: warning: 'process_array4' accessing 4 bytes in a region of size 3 [- Wstringop-overflow=] cc1: note: referencing argument 1 of type 'char[4]' t.c:6:6: note: in a call to function 'process_array4' 6 | void process_array4 (char a[4], int n) | ^~~~~~~~~~~~~~ cc1: warning: 'process_array4' accessing 4 bytes in a region of size 3 [- Wstringop-overflow=] cc1: note: referencing argument 1 of type 'char[4]' t.c:6:6: note: in a call to function 'process_array4' That's because the ICF IPA pass has identified the two functions and turned process_array3 into a wrapper of process_array4. gcc/ * gimple-ssa-warn-access.cc (pass_waccess::check_call): Return early for calls made from thunks. gcc/testsuite/ * gcc.dg/Wstringop-overflow-89.c: New test. --- gcc/testsuite/gcc.dg/Wstringop-overflow-89.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/Wstringop-overflow-89.c (limited to 'gcc/testsuite') diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-89.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-89.c new file mode 100644 index 0000000..ba25a93 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-89.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-inline -Wall" } */ + +extern void process (char); + +void process_array4 (char a[4], int n) +{ + for (int i = 0; i < n; i++) + process (a[i]); +} + +void process_array3 (char a[3], int n) +{ + for (int i = 0; i < n; i++) + process (a[i]); +} -- cgit v1.1 From 621a911d336279d21e1e857cfead09af1c61df39 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Fri, 14 Oct 2022 00:16:35 +0000 Subject: Daily bump. --- gcc/testsuite/ChangeLog | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'gcc/testsuite') diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 737ee21..a985478 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,45 @@ +2022-10-13 Eric Botcazou + + * gcc.dg/Wstringop-overflow-89.c: New test. + +2022-10-13 David Malcolm + + PR analyzer/107210 + * gfortran.dg/analyzer/pr107210.f90: New test. + +2022-10-13 Andrew MacLeod + + * gcc.dg/pr102540.c: New. + * gcc.dg/pr102872.c: New. + +2022-10-13 Marek Polacek + + PR c++/106925 + * g++.dg/cpp0x/initlist-defarg3.C: New test. + +2022-10-13 Wilco Dijkstra + + PR target/105773 + * gcc.target/aarch64/ands_2.c: Test for ANDS. + * gcc.target/aarch64/bics_2.c: Test for BICS. + * gcc.target/aarch64/tst_2.c: Test for TST. + * gcc.target/aarch64/tst_imm_split_1.c: Fix test. + +2022-10-13 Richard Biener + + PR tree-optimization/107160 + * gcc.dg/vect/pr107160.c: New testcase. + +2022-10-13 Andre Vieira + + * gcc.dg/vect/pr107229-1.c: New test. + * gcc.dg/vect/pr107229-2.c: New test. + * gcc.dg/vect/pr107229-3.c: New test. + +2022-10-13 Joseph Myers + + * gcc.dg/c2x-float-10.c: Do not expect value 2 for *_IS_IEC_60559. + 2022-10-12 Lewis Hyatt PR preprocessor/60014 -- cgit v1.1 From 18981635127c6701733dc052aa054e569271b733 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Fri, 14 Oct 2022 02:18:45 +0000 Subject: c: C2x storage class specifiers in compound literals Implement the C2x feature of storage class specifiers in compound literals. Such storage class specifiers (static, register or thread_local; also constexpr, but we don't yet have C2x constexpr support implemented) can be used before the type name (not mixed with type specifiers, unlike in declarations) and have the same semantics and constraints as for declarations of named objects. Also allow GNU __thread to be used, given that thread_local can be. Bootstrapped with no regressions for x86_64-pc-linux-gnu. gcc/c/ * c-decl.cc (build_compound_literal): Add parameter scspecs. Handle storage class specifiers. * c-parser.cc (c_token_starts_compound_literal) (c_parser_compound_literal_scspecs): New. (c_parser_postfix_expression_after_paren_type): Add parameter scspecs. Call pedwarn_c11 for use of storage class specifiers. Update call to build_compound_literal. (c_parser_cast_expression, c_parser_sizeof_expression) (c_parser_alignof_expression): Handle storage class specifiers for compound literals. Update calls to c_parser_postfix_expression_after_paren_type. (c_parser_postfix_expression): Update syntax comment. * c-tree.h (build_compound_literal): Update prototype. * c-typeck.cc (c_mark_addressable): Diagnose taking address of register compound literal. gcc/testsuite/ * gcc.dg/c11-complit-1.c, gcc.dg/c11-complit-2.c, gcc.dg/c11-complit-3.c, gcc.dg/c2x-complit-2.c, gcc.dg/c2x-complit-3.c, gcc.dg/c2x-complit-4.c, gcc.dg/c2x-complit-5.c, gcc.dg/c2x-complit-6.c, gcc.dg/c2x-complit-7.c, gcc.dg/c90-complit-2.c, gcc.dg/gnu2x-complit-1.c, gcc.dg/gnu2x-complit-2.c: New tests. --- gcc/testsuite/gcc.dg/c11-complit-1.c | 7 ++++ gcc/testsuite/gcc.dg/c11-complit-2.c | 7 ++++ gcc/testsuite/gcc.dg/c11-complit-3.c | 7 ++++ gcc/testsuite/gcc.dg/c2x-complit-2.c | 48 +++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/c2x-complit-3.c | 24 ++++++++++++++ gcc/testsuite/gcc.dg/c2x-complit-4.c | 60 ++++++++++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/c2x-complit-5.c | 52 +++++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/c2x-complit-6.c | 7 ++++ gcc/testsuite/gcc.dg/c2x-complit-7.c | 7 ++++ gcc/testsuite/gcc.dg/c90-complit-2.c | 8 +++++ gcc/testsuite/gcc.dg/gnu2x-complit-1.c | 7 ++++ gcc/testsuite/gcc.dg/gnu2x-complit-2.c | 18 ++++++++++ 12 files changed, 252 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/c11-complit-1.c create mode 100644 gcc/testsuite/gcc.dg/c11-complit-2.c create mode 100644 gcc/testsuite/gcc.dg/c11-complit-3.c create mode 100644 gcc/testsuite/gcc.dg/c2x-complit-2.c create mode 100644 gcc/testsuite/gcc.dg/c2x-complit-3.c create mode 100644 gcc/testsuite/gcc.dg/c2x-complit-4.c create mode 100644 gcc/testsuite/gcc.dg/c2x-complit-5.c create mode 100644 gcc/testsuite/gcc.dg/c2x-complit-6.c create mode 100644 gcc/testsuite/gcc.dg/c2x-complit-7.c create mode 100644 gcc/testsuite/gcc.dg/c90-complit-2.c create mode 100644 gcc/testsuite/gcc.dg/gnu2x-complit-1.c create mode 100644 gcc/testsuite/gcc.dg/gnu2x-complit-2.c (limited to 'gcc/testsuite') diff --git a/gcc/testsuite/gcc.dg/c11-complit-1.c b/gcc/testsuite/gcc.dg/c11-complit-1.c new file mode 100644 index 0000000..e191ceb --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-complit-1.c @@ -0,0 +1,7 @@ +/* Test C2x storage class specifiers in compound literals not permitted for + C11. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ + +int *ps = &(static int) { 1 }; /* { dg-error "forbids storage class specifiers in compound literals" } */ +int ss = sizeof (static int) { 1 }; /* { dg-error "forbids storage class specifiers in compound literals" } */ diff --git a/gcc/testsuite/gcc.dg/c11-complit-2.c b/gcc/testsuite/gcc.dg/c11-complit-2.c new file mode 100644 index 0000000..d4d1f16 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-complit-2.c @@ -0,0 +1,7 @@ +/* Test C2x storage class specifiers in compound literals not permitted for + C11. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -pedantic" } */ + +int *ps = &(static int) { 1 }; /* { dg-warning "forbids storage class specifiers in compound literals" } */ +int ss = sizeof (static int) { 1 }; /* { dg-warning "forbids storage class specifiers in compound literals" } */ diff --git a/gcc/testsuite/gcc.dg/c11-complit-3.c b/gcc/testsuite/gcc.dg/c11-complit-3.c new file mode 100644 index 0000000..a73a8ef --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-complit-3.c @@ -0,0 +1,7 @@ +/* Test C2x storage class specifiers in compound literals not permitted for + C11, but -Wno-c11-c2x-compat disables the -pedantic diagnostic for that. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -pedantic-errors -Wno-c11-c2x-compat" } */ + +int *ps = &(static int) { 1 }; +int ss = sizeof (static int) { 1 }; diff --git a/gcc/testsuite/gcc.dg/c2x-complit-2.c b/gcc/testsuite/gcc.dg/c2x-complit-2.c new file mode 100644 index 0000000..dcca5e8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-complit-2.c @@ -0,0 +1,48 @@ +/* Test C2x storage class specifiers in compound literals. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +#include + +extern void abort (void); +extern void exit (int); + +/* static is OK (although redundant) at file scope. */ +int *ps = &(static int) { 1 }; +size_t ss = sizeof (static int) { 1 }; +int *psa = (static int [3]) { 1, 2, 3 }; + +int +main () +{ + if (ps[0] != 1) + abort (); + if (ss != sizeof (int)) + abort (); + if (psa[0] != 1 || psa[1] != 2 || psa[2] != 3) + abort (); + if ((register int) { 3 } != 3) + abort (); + /* A static compound literal, like a static variable, is initialized once, + but an automatic compound literal is initialized every time it is reached + in the order of execution. */ + int i = 0; + lab: + int *p = &(static int) { 0 }; + if (*p != i) + abort (); + i++; + *p = i; + if (i < 5) + goto lab; + i = 0; + lab2: + int *p2 = &(int) { 0 }; + if (*p2 != 0) + abort (); + i++; + *p2 = i; + if (i < 5) + goto lab2; + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/c2x-complit-3.c b/gcc/testsuite/gcc.dg/c2x-complit-3.c new file mode 100644 index 0000000..c672525 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-complit-3.c @@ -0,0 +1,24 @@ +/* Test C2x storage class specifiers in compound literals. Thread-local + cases, compilation tests. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ +/* { dg-require-effective-target tls } */ + +#include + +/* thread_local is OK at file scope, although of limited use since the + thread-local object and its address are not constant expressions. */ +size_t st = sizeof (thread_local int) { 1 }; +size_t sst = sizeof (static thread_local int) { 1 }; + +int * +f () +{ + return &(static thread_local int) { 2 }; +} + +int * +g () +{ + return &(thread_local static int) { 3 }; +} diff --git a/gcc/testsuite/gcc.dg/c2x-complit-4.c b/gcc/testsuite/gcc.dg/c2x-complit-4.c new file mode 100644 index 0000000..31d7413 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-complit-4.c @@ -0,0 +1,60 @@ +/* Test C2x storage class specifiers in compound literals. Thread-local + cases, execution tests. */ +/* { dg-do run } */ +/* { dg-options "-pthread -std=gnu2x -pedantic-errors" } */ +/* { dg-require-effective-target pthread_h } */ +/* { dg-require-effective-target pthread } */ +/* { dg-require-effective-target tls_runtime } */ +/* { dg-add-options tls } */ + +#include + +extern void abort (void); +extern void exit (int); + +int * +thread_addr () +{ + return (static thread_local int []) { 1, 2 }; +} + +int *volatile p, *volatile q, r; + +void * +thread_fn (void *) +{ + q = thread_addr (); + if (q[0] != 1 || q[1] != 2) + return NULL; + q[0] = 5; + q[1] = 6; + return &r; +} + +int +main () +{ + int i; + pthread_t tid; + void *ret; + p = thread_addr (); + if (p[0] != 1 || p[1] != 2) + abort (); + p[0] = 3; + p[1] = 4; + if (p != thread_addr ()) + abort (); + i = pthread_create (&tid, NULL, thread_fn, NULL); + if (p != thread_addr ()) + abort (); + i = pthread_join (tid, &ret); + if (i != 0) + abort (); + if (ret != &r) + abort (); + if (p != thread_addr ()) + abort (); + if (p[0] != 3 || p[1] != 4) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/c2x-complit-5.c b/gcc/testsuite/gcc.dg/c2x-complit-5.c new file mode 100644 index 0000000..1eb0f8d --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-complit-5.c @@ -0,0 +1,52 @@ +/* Test C2x storage class specifiers in compound literals: invalid code. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +int *p = &(register int) { 0 }; /* { dg-error "file-scope compound literal specifies" } */ + +int v; + +void +f () +{ + int *q = &(thread_local int) { 0 }; /* { dg-error "compound literal implicitly auto and declared" } */ + int *pc = &(static int) { v }; /* { dg-error "not constant" } */ + int *pt = &(static thread_local int) { v }; /* { dg-error "not constant" } */ + &(register int) { 0 }; /* { dg-error "address of register compound literal requested" } */ + struct s { int a, b; }; + &((register struct s) { 1, 2 }.b); /* { dg-error "address of register compound literal requested" } */ +} + +int *s = &(static static int) { 0 }; /* { dg-error "duplicate" } */ + +void +g () +{ + (void) (register register int) { 0 }; /* { dg-error "duplicate" } */ + (void) (static static int) { 0 }; /* { dg-error "duplicate" } */ + (void) (static thread_local thread_local int) { 0 }; /* { dg-error "duplicate" } */ + (void) (static register int) { 0 }; /* { dg-error "multiple storage classes in declaration specifiers" } */ + (void) (register static int) { 0 }; /* { dg-error "multiple storage classes in declaration specifiers" } */ + (void) (register thread_local int) { 0 }; /* { dg-error "used with" } */ + (void) (thread_local register int) { 0 }; /* { dg-error "used with" } */ +} + +void +h () +{ + /* The following cases are not part of the C2x syntax, but are detected + specially by the parser. */ + (static int) 0; /* { dg-error "storage class specifier in cast" } */ + sizeof (static int); /* { dg-error "storage class specifier in" } */ + alignof (static int); /* { dg-error "storage class specifier in" } */ +} + +void +bad_scspec () +{ + /* Storage class specifiers not permitted in compound literals result in a + syntax error. */ + (typedef int) { 0 }; /* { dg-error "expected" } */ + (auto int) { 0 }; /* { dg-error "expected" } */ + (extern int) { 0 }; /* { dg-error "expected" } */ +} diff --git a/gcc/testsuite/gcc.dg/c2x-complit-6.c b/gcc/testsuite/gcc.dg/c2x-complit-6.c new file mode 100644 index 0000000..23a0bb6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-complit-6.c @@ -0,0 +1,7 @@ +/* Test C2x storage class specifiers in compound literals diagnosed with + -Wc11-c2x-compat. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -Wc11-c2x-compat" } */ + +int *ps = &(static int) { 1 }; /* { dg-warning "forbids storage class specifiers in compound literals" } */ +int ss = sizeof (static int) { 1 }; /* { dg-warning "forbids storage class specifiers in compound literals" } */ diff --git a/gcc/testsuite/gcc.dg/c2x-complit-7.c b/gcc/testsuite/gcc.dg/c2x-complit-7.c new file mode 100644 index 0000000..0cd0b86 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-complit-7.c @@ -0,0 +1,7 @@ +/* Test C2x storage class specifiers in compound literals diagnosed with + -Wc11-c2x-compat, but not errors with -pedantic-errors. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -Wc11-c2x-compat -pedantic-errors" } */ + +int *ps = &(static int) { 1 }; /* { dg-warning "forbids storage class specifiers in compound literals" } */ +int ss = sizeof (static int) { 1 }; /* { dg-warning "forbids storage class specifiers in compound literals" } */ diff --git a/gcc/testsuite/gcc.dg/c90-complit-2.c b/gcc/testsuite/gcc.dg/c90-complit-2.c new file mode 100644 index 0000000..6fcf2a5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c90-complit-2.c @@ -0,0 +1,8 @@ +/* Test C2x storage class specifiers in compound literals not permitted for + C90, but without a duplicate diagnostic, just the diagnostic for compound + literals not being permitted in C90 at all. */ +/* { dg-do compile } */ +/* { dg-options "-std=c90 -pedantic-errors" } */ + +int *ps = &(static int) { 1 }; /* { dg-error "ISO C90 forbids compound literals" } */ +int ss = sizeof (static int) { 1 }; /* { dg-error "ISO C90 forbids compound literals" } */ diff --git a/gcc/testsuite/gcc.dg/gnu2x-complit-1.c b/gcc/testsuite/gcc.dg/gnu2x-complit-1.c new file mode 100644 index 0000000..e9da5ad --- /dev/null +++ b/gcc/testsuite/gcc.dg/gnu2x-complit-1.c @@ -0,0 +1,7 @@ +/* Test C2x storage class specifiers in compound literals: GNU use of alignof + on objects (tested separately since alignof parsing handles the type name of + compound literals). */ +/* { dg-do compile } */ +/* { dg-options "-std=gnu2x" } */ + +int a = alignof (static int) { 0 }; diff --git a/gcc/testsuite/gcc.dg/gnu2x-complit-2.c b/gcc/testsuite/gcc.dg/gnu2x-complit-2.c new file mode 100644 index 0000000..20cb38f --- /dev/null +++ b/gcc/testsuite/gcc.dg/gnu2x-complit-2.c @@ -0,0 +1,18 @@ +/* Test C2x storage class specifiers in compound literals. Thread-local + cases, compilation tests, GNU __thread used. */ +/* { dg-do compile } */ +/* { dg-options "-std=gnu2x" } */ +/* { dg-require-effective-target tls } */ + +#include + +/* __thread is OK at file scope, although of limited use since the + thread-local object and its address are not constant expressions. */ +size_t st = sizeof (__thread int) { 1 }; +size_t sst = sizeof (static __thread int) { 1 }; + +int * +f () +{ + return &(static __thread int) { 2 }; +} -- cgit v1.1 From 98e341130f87984af07c884fea773c0bb3cc8821 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 14 Oct 2022 09:28:57 +0200 Subject: c++: Implement excess precision support for C++ [PR107097, PR323] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The following patch implements excess precision support for C++. Like for C, it uses EXCESS_PRECISION_EXPR tree to say that its operand is evaluated in excess precision and what the semantic type of the expression is. In most places I've followed what the C FE does in similar spots, so e.g. for binary ops if one or both operands are already EXCESS_PRECISION_EXPR, strip those away or for operations that might need excess precision (+, -, *, /) check if the operands should use excess precision and convert to that type and at the end wrap into EXCESS_PRECISION_EXPR with the common semantic type. This patch follows the C99 handling where it differs from C11 handling. There are some cases which needed to be handled differently, the C FE can just strip EXCESS_PRECISION_EXPR (replace it with its operand) when handling explicit cast, but that IMHO isn't right for C++ - the discovery what exact conversion should be used (e.g. if user conversion or standard or their sequence) should be decided based on the semantic type (i.e. type of EXCESS_PRECISION_EXPR), and that decision continues in convert_like* where we pick the right user conversion, again, if say some class has ctor from double and long double and we are on ia32 with standard excess precision promoting float/double to long double, then we should pick the ctor from double. Or when some other class has ctor from just double, and EXCESS_PRECISION_EXPR semantic type is float, we should choose the user ctor from double, but actually just convert the long double excess precision to double and not to float first. We need to make sure even identity conversion converts from excess precision to the semantic one though, but if identity is chained with other conversions, we don't want the identity next_conversion to drop to semantic precision only to widen afterwards. The existing testcases tweaks were for cases on i686-linux where excess precision breaks those tests, e.g. if we have double d = 4.2; if (d == 4.2) then it does the expected thing only with -fexcess-precision=fast, because with -fexcess-precision=standard it is actually double d = 4.2; if ((long double) d == 4.2L) where 4.2L is different from 4.2. I've added -fexcess-precision=fast to some tests and changed other tests to use constants that are exactly representable and don't suffer from these excess precision issues. There is one exception, pr68180.C looks like a bug in the patch which is also present in the C FE (so I'd like to get it resolved incrementally in both). Reduced testcase: typedef float __attribute__((vector_size (16))) float32x4_t; float32x4_t foo(float32x4_t x, float y) { return x + y; } with -m32 -std=c11 -Wno-psabi or -m32 -std=c++17 -Wno-psabi it is rejected with: pr68180.c:2:52: error: conversion of scalar ‘long double’ to vector ‘float32x4_t’ {aka ‘__vector(4) float’} involves truncation but without excess precision (say just -std=c11 -Wno-psabi or -std=c++17 -Wno-psabi) it is accepted. Perhaps we should pass down the semantic type to scalar_to_vector and use the semantic type rather than excess precision type in the diagnostics. 2022-10-14 Jakub Jelinek PR middle-end/323 PR c++/107097 gcc/ * doc/invoke.texi (-fexcess-precision=standard): Mention that the option now also works in C++. gcc/c-family/ * c-common.def (EXCESS_PRECISION_EXPR): Remove comment part about the tree being specific to C/ObjC. * c-opts.cc (c_common_post_options): Handle flag_excess_precision in C++ the same as in C. * c-lex.cc (interpret_float): Set const_type to excess_precision () even for C++. gcc/cp/ * parser.cc (cp_parser_primary_expression): Handle EXCESS_PRECISION_EXPR with REAL_CST operand the same as REAL_CST. * cvt.cc (cp_ep_convert_and_check): New function. * call.cc (build_conditional_expr): Add excess precision support. When type_after_usual_arithmetic_conversions returns error_mark_node, use gcc_checking_assert that it is because of uncomparable floating point ranks instead of checking all those conditions and make it work also with complex types. (convert_like_internal): Likewise. Add NESTED_P argument, pass true to recursive calls to convert_like. (convert_like): Add NESTED_P argument, pass it through to convert_like_internal. For other overload pass false to it. (convert_like_with_context): Pass false to NESTED_P. (convert_arg_to_ellipsis): Add excess precision support. (magic_varargs_p): For __builtin_is{finite,inf,inf_sign,nan,normal} and __builtin_fpclassify return 2 instead of 1, document what it means. (build_over_call): Don't handle former magic 2 which is no longer used, instead for magic 1 remove EXCESS_PRECISION_EXPR. (perform_direct_initialization_if_possible): Pass false to NESTED_P convert_like argument. * constexpr.cc (cxx_eval_constant_expression): Handle EXCESS_PRECISION_EXPR. (potential_constant_expression_1): Likewise. * pt.cc (tsubst_copy, tsubst_copy_and_build): Likewise. * cp-tree.h (cp_ep_convert_and_check): Declare. * cp-gimplify.cc (cp_fold): Handle EXCESS_PRECISION_EXPR. * typeck.cc (cp_common_type): For COMPLEX_TYPEs, return error_mark_node if recursive call returned it. (convert_arguments): For magic 1 remove EXCESS_PRECISION_EXPR. (cp_build_binary_op): Add excess precision support. When cp_common_type returns error_mark_node, use gcc_checking_assert that it is because of uncomparable floating point ranks instead of checking all those conditions and make it work also with complex types. (cp_build_unary_op): Likewise. (cp_build_compound_expr): Likewise. (build_static_cast_1): Remove EXCESS_PRECISION_EXPR. gcc/testsuite/ * gcc.target/i386/excess-precision-1.c: For C++ wrap abort and exit declarations into extern "C" block. * gcc.target/i386/excess-precision-2.c: Likewise. * gcc.target/i386/excess-precision-3.c: Likewise. Remove check_float_nonproto and check_double_nonproto tests for C++. * gcc.target/i386/excess-precision-7.c: For C++ wrap abort and exit declarations into extern "C" block. * gcc.target/i386/excess-precision-9.c: Likewise. * g++.target/i386/excess-precision-1.C: New test. * g++.target/i386/excess-precision-2.C: New test. * g++.target/i386/excess-precision-3.C: New test. * g++.target/i386/excess-precision-4.C: New test. * g++.target/i386/excess-precision-5.C: New test. * g++.target/i386/excess-precision-6.C: New test. * g++.target/i386/excess-precision-7.C: New test. * g++.target/i386/excess-precision-9.C: New test. * g++.target/i386/excess-precision-11.C: New test. * c-c++-common/dfp/convert-bfp-10.c: Add -fexcess-precision=fast as dg-additional-options. * c-c++-common/dfp/compare-eq-const.c: Likewise. * g++.dg/cpp1z/constexpr-96862.C: Likewise. * g++.dg/cpp1z/decomp12.C (main): Use 2.25 instead of 2.3 to avoid excess precision differences. * g++.dg/other/thunk1.C: Add -fexcess-precision=fast as dg-additional-options. * g++.dg/vect/pr64410.cc: Likewise. * g++.dg/cpp1y/pr68180.C: Likewise. * g++.dg/vect/pr89653.cc: Likewise. * g++.dg/cpp0x/variadic-tuple.C: Likewise. * g++.dg/cpp0x/nsdmi-union1.C: Use 4.25 instead of 4.2 to avoid excess precision differences. * g++.old-deja/g++.brendan/copy9.C: Add -fexcess-precision=fast as dg-additional-options. * g++.old-deja/g++.brendan/overload7.C: Likewise. --- gcc/testsuite/c-c++-common/dfp/compare-eq-const.c | 1 + gcc/testsuite/c-c++-common/dfp/convert-bfp-10.c | 1 + gcc/testsuite/g++.dg/cpp0x/nsdmi-union1.C | 4 +- gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C | 1 + gcc/testsuite/g++.dg/cpp1y/pr68180.C | 2 +- gcc/testsuite/g++.dg/cpp1z/constexpr-96862.C | 2 +- gcc/testsuite/g++.dg/cpp1z/decomp12.C | 4 +- gcc/testsuite/g++.dg/other/thunk1.C | 1 + gcc/testsuite/g++.dg/vect/pr64410.cc | 1 + gcc/testsuite/g++.dg/vect/pr89653.cc | 1 + gcc/testsuite/g++.old-deja/g++.brendan/copy9.C | 1 + gcc/testsuite/g++.old-deja/g++.brendan/overload7.C | 1 + gcc/testsuite/g++.target/i386/excess-precision-1.C | 6 ++ .../g++.target/i386/excess-precision-11.C | 105 +++++++++++++++++++++ gcc/testsuite/g++.target/i386/excess-precision-2.C | 5 + gcc/testsuite/g++.target/i386/excess-precision-3.C | 6 ++ gcc/testsuite/g++.target/i386/excess-precision-4.C | 7 ++ gcc/testsuite/g++.target/i386/excess-precision-5.C | 32 +++++++ gcc/testsuite/g++.target/i386/excess-precision-6.C | 19 ++++ gcc/testsuite/g++.target/i386/excess-precision-7.C | 7 ++ gcc/testsuite/g++.target/i386/excess-precision-9.C | 6 ++ gcc/testsuite/gcc.target/i386/excess-precision-1.c | 6 ++ gcc/testsuite/gcc.target/i386/excess-precision-2.c | 6 ++ gcc/testsuite/gcc.target/i386/excess-precision-3.c | 10 ++ gcc/testsuite/gcc.target/i386/excess-precision-7.c | 6 ++ gcc/testsuite/gcc.target/i386/excess-precision-9.c | 6 ++ 26 files changed, 241 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.target/i386/excess-precision-1.C create mode 100644 gcc/testsuite/g++.target/i386/excess-precision-11.C create mode 100644 gcc/testsuite/g++.target/i386/excess-precision-2.C create mode 100644 gcc/testsuite/g++.target/i386/excess-precision-3.C create mode 100644 gcc/testsuite/g++.target/i386/excess-precision-4.C create mode 100644 gcc/testsuite/g++.target/i386/excess-precision-5.C create mode 100644 gcc/testsuite/g++.target/i386/excess-precision-6.C create mode 100644 gcc/testsuite/g++.target/i386/excess-precision-7.C create mode 100644 gcc/testsuite/g++.target/i386/excess-precision-9.C (limited to 'gcc/testsuite') diff --git a/gcc/testsuite/c-c++-common/dfp/compare-eq-const.c b/gcc/testsuite/c-c++-common/dfp/compare-eq-const.c index 0c9ff20..4bc2189 100644 --- a/gcc/testsuite/c-c++-common/dfp/compare-eq-const.c +++ b/gcc/testsuite/c-c++-common/dfp/compare-eq-const.c @@ -1,5 +1,6 @@ /* C99 6.5.9 Equality operators. Compare decimal float constants against each other. */ +/* { dg-additional-options "-fexcess-precision=fast" } */ #include "dfp-dbg.h" diff --git a/gcc/testsuite/c-c++-common/dfp/convert-bfp-10.c b/gcc/testsuite/c-c++-common/dfp/convert-bfp-10.c index 3fef98a..2cce3e6 100644 --- a/gcc/testsuite/c-c++-common/dfp/convert-bfp-10.c +++ b/gcc/testsuite/c-c++-common/dfp/convert-bfp-10.c @@ -1,4 +1,5 @@ /* This test assumes IEEE float and double. */ +/* { dg-additional-options "-fexcess-precision=fast" } */ #include "convert.h" diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-union1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-union1.C index 11bdd88..c5acc4a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-union1.C +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-union1.C @@ -18,8 +18,8 @@ int main() { Test t; B b; - B b2(4.2); + B b2(4.25); - if (t.a != 4 || b.i != 42 || b2.d != 4.2) + if (t.a != 4 || b.i != 42 || b2.d != 4.25) __builtin_abort(); } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C b/gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C index e2699d9..5164598 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C @@ -1,4 +1,5 @@ // { dg-do run { target c++11 } } +// { dg-additional-options "-fexcess-precision=fast" } // An implementation of TR1's using variadic teplates // Contributed by Douglas Gregor diff --git a/gcc/testsuite/g++.dg/cpp1y/pr68180.C b/gcc/testsuite/g++.dg/cpp1y/pr68180.C index 9e6e5e9..64d613e 100644 --- a/gcc/testsuite/g++.dg/cpp1y/pr68180.C +++ b/gcc/testsuite/g++.dg/cpp1y/pr68180.C @@ -1,6 +1,6 @@ // PR c++/68180 // { dg-do compile { target c++14 } } -// { dg-additional-options "-Wno-psabi" } +// { dg-additional-options "-Wno-psabi -fexcess-precision=fast" } typedef float __attribute__( ( vector_size( 16 ) ) ) float32x4_t; constexpr float32x4_t fill(float x) { diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-96862.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-96862.C index 0b5c2e81..daefca9 100644 --- a/gcc/testsuite/g++.dg/cpp1z/constexpr-96862.C +++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-96862.C @@ -1,6 +1,6 @@ // PR c++/96862 // { dg-do compile { target c++17 } } -// { dg-additional-options "-frounding-math" } +// { dg-additional-options "-frounding-math -fexcess-precision=fast" } constexpr double a = 0x1.0p+100 + 0x1.0p-100; const double b = 0x1.0p+100 + 0x1.0p-100; diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp12.C b/gcc/testsuite/g++.dg/cpp1z/decomp12.C index 56fd498..a65aaf9 100644 --- a/gcc/testsuite/g++.dg/cpp1z/decomp12.C +++ b/gcc/testsuite/g++.dg/cpp1z/decomp12.C @@ -7,13 +7,13 @@ template struct same_type; template struct same_type {}; int main() { - std::tuple tuple = { 1, 'a', 2.3, true }; + std::tuple tuple = { 1, 'a', 2.25, true }; auto[i, c, d, b] = tuple; same_type::type, decltype(i)>{}; same_type{}; same_type{}; same_type{}; same_type{}; - if (i != 1 || c != 'a' || d != 2.3 || b != true) + if (i != 1 || c != 'a' || d != 2.25 || b != true) __builtin_abort (); } diff --git a/gcc/testsuite/g++.dg/other/thunk1.C b/gcc/testsuite/g++.dg/other/thunk1.C index 9016562..7758111 100644 --- a/gcc/testsuite/g++.dg/other/thunk1.C +++ b/gcc/testsuite/g++.dg/other/thunk1.C @@ -1,5 +1,6 @@ // PR c++/12007 Multiple inheritance float pass by value fails // { dg-do run } +// { dg-additional-options "-fexcess-precision=fast" } extern "C" void abort (void); diff --git a/gcc/testsuite/g++.dg/vect/pr64410.cc b/gcc/testsuite/g++.dg/vect/pr64410.cc index cbc2acc..ad4b085 100644 --- a/gcc/testsuite/g++.dg/vect/pr64410.cc +++ b/gcc/testsuite/g++.dg/vect/pr64410.cc @@ -1,5 +1,6 @@ // { dg-do compile } // { dg-require-effective-target vect_double } +// { dg-additional-options "-fexcess-precision=fast" } #include #include diff --git a/gcc/testsuite/g++.dg/vect/pr89653.cc b/gcc/testsuite/g++.dg/vect/pr89653.cc index d38b49a..f5a071f 100644 --- a/gcc/testsuite/g++.dg/vect/pr89653.cc +++ b/gcc/testsuite/g++.dg/vect/pr89653.cc @@ -1,5 +1,6 @@ // { dg-do compile } // { dg-require-effective-target vect_double } +// { dg-additional-options "-fexcess-precision=fast" } #include diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/copy9.C b/gcc/testsuite/g++.old-deja/g++.brendan/copy9.C index f05b194..79339c1 100644 --- a/gcc/testsuite/g++.old-deja/g++.brendan/copy9.C +++ b/gcc/testsuite/g++.old-deja/g++.brendan/copy9.C @@ -1,4 +1,5 @@ // { dg-do run } +// { dg-additional-options "-fexcess-precision=fast" } // GROUPS passed copy-ctors #include diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/overload7.C b/gcc/testsuite/g++.old-deja/g++.brendan/overload7.C index 29a9060..08f220c 100644 --- a/gcc/testsuite/g++.old-deja/g++.brendan/overload7.C +++ b/gcc/testsuite/g++.old-deja/g++.brendan/overload7.C @@ -1,4 +1,5 @@ // { dg-do run } +// { dg-additional-options "-fexcess-precision=fast" } // GROUPS passed overloading extern "C" int printf (const char *, ...); diff --git a/gcc/testsuite/g++.target/i386/excess-precision-1.C b/gcc/testsuite/g++.target/i386/excess-precision-1.C new file mode 100644 index 0000000..0519d63 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/excess-precision-1.C @@ -0,0 +1,6 @@ +// Excess precision tests. Test that excess precision is carried +// through various operations. +// { dg-do run } +// { dg-options "-O2 -mfpmath=387 -fexcess-precision=standard" } + +#include "../../gcc.target/i386/excess-precision-1.c" diff --git a/gcc/testsuite/g++.target/i386/excess-precision-11.C b/gcc/testsuite/g++.target/i386/excess-precision-11.C new file mode 100644 index 0000000..119b666 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/excess-precision-11.C @@ -0,0 +1,105 @@ +// Excess precision tests. Test excess precision is removed when +// necessary. +// { dg-do run } +// { dg-options "-O2 -mfpmath=387 -fexcess-precision=standard" } + +#include +#include + +extern "C" void abort (); + +volatile float f1 = 1.0f; +volatile float f2 = 0x1.0p-30f; +volatile float f3 = 0x1.0p-60f; +volatile double d1 = 1.0; +volatile double d2 = 0x1.0p-30; +volatile double d3 = 0x1.0p-60; +volatile double d3d = 0x1.0p-52; +volatile float fadd1 = 1.0f + 0x1.0p-30f; +volatile double dadd2 = 1.0 + 0x1.0p-30 + 0x1.0p-60; +volatile double dh = 0x1.0p-24; +volatile float fha = 1.0f + 0x1.0p-23f; + +static inline void +check_float (float f) +{ + if (f != fadd1) + abort (); +} + +static inline void +check_float (double) +{ + abort (); +} + +static inline void +check_float (long double) +{ + abort (); +} + +static inline void +check_double (double d) +{ + if (d != dadd2) + abort (); +} + +static inline void +check_double (long double) +{ + abort (); +} + +static inline void +check_float2 (float f) +{ + if (f != fha) + abort (); +} + +struct S { + S () {} + S (float f) { if (f != fadd1) abort (); } +}; + +struct T { + T () {} + T (double d) { if (d != dadd2) abort (); } +}; + +static inline void +check_float3 (S) +{ +} + +static inline void +check_double2 (T) +{ +} + +void +test_call () +{ + check_float (f1 + f2); + check_double (f1 + f2); + check_double (d1 + d2 + d3); + /* Verify rounding direct to float without double rounding. */ + if (sizeof (long double) > sizeof (double)) + check_float2 (d1 + dh + d3); + else + check_float2 (d1 + dh + d3d); + check_float3 (f1 + f2); + check_double2 (f1 + f2); + check_double2 (d1 + d2 + d3); + S s1 = static_cast (f1 + f2); + T t2 = static_cast (f1 + f2); + T t3 = static_cast (d1 + d2 + d3); +} + +int +main () +{ + test_call (); +} diff --git a/gcc/testsuite/g++.target/i386/excess-precision-2.C b/gcc/testsuite/g++.target/i386/excess-precision-2.C new file mode 100644 index 0000000..afb2197 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/excess-precision-2.C @@ -0,0 +1,5 @@ +// Excess precision tests. Test excess precision of constants. +// { dg-do run } +// { dg-options "-O2 -mfpmath=387 -fexcess-precision=standard" } + +#include "../../gcc.target/i386/excess-precision-2.c" diff --git a/gcc/testsuite/g++.target/i386/excess-precision-3.C b/gcc/testsuite/g++.target/i386/excess-precision-3.C new file mode 100644 index 0000000..be8cc42 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/excess-precision-3.C @@ -0,0 +1,6 @@ +// Excess precision tests. Test excess precision is removed when +// necessary. +// { dg-do run } +// { dg-options "-O2 -mfpmath=387 -fexcess-precision=standard" } + +#include "../../gcc.target/i386/excess-precision-3.c" diff --git a/gcc/testsuite/g++.target/i386/excess-precision-4.C b/gcc/testsuite/g++.target/i386/excess-precision-4.C new file mode 100644 index 0000000..30606b1 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/excess-precision-4.C @@ -0,0 +1,7 @@ +// Excess precision tests. Test diagnostics for excess precision of +// constants. +// { dg-do compile } +// { dg-options "-mfpmath=387 -fexcess-precision=standard" } + +float f = 0.0f * 1e50f; // { dg-warning "floating constant exceeds range of 'float'" } +double d = 0.0 * 1e400; // { dg-warning "floating constant exceeds range of 'double'" } diff --git a/gcc/testsuite/g++.target/i386/excess-precision-5.C b/gcc/testsuite/g++.target/i386/excess-precision-5.C new file mode 100644 index 0000000..fa15753 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/excess-precision-5.C @@ -0,0 +1,32 @@ +// Excess precision tests. Verify excess precision doesn't affect +// actual types. +// { dg-do compile { target c++11 } } +// { dg-options "-mfpmath=387 -fexcess-precision=standard" } + +namespace std { + template struct integral_constant { + static constexpr T value = v; + }; + typedef integral_constant false_type; + typedef integral_constant true_type; + template + struct is_same : std::false_type {}; + template + struct is_same : std::true_type {}; +} + +float f; +double d; + +void +test_types (void) +{ +#define CHECK_FLOAT(E) static_assert (std::is_same ::value, "") +#define CHECK_DOUBLE(E) static_assert (std::is_same ::value, "") + CHECK_FLOAT (f + f); + CHECK_DOUBLE (d + d); + CHECK_FLOAT (f * f / f); + CHECK_DOUBLE (d * d / d); + CHECK_FLOAT (f ? f - f : f); + CHECK_DOUBLE (d ? d - d : d); +} diff --git a/gcc/testsuite/g++.target/i386/excess-precision-6.C b/gcc/testsuite/g++.target/i386/excess-precision-6.C new file mode 100644 index 0000000..06e9a93 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/excess-precision-6.C @@ -0,0 +1,19 @@ +// Excess precision tests. Make sure sqrt is not inlined for float or +// double. +// { dg-do compile } +// { dg-options "-mfpmath=387 -O2 -fno-math-errno -fexcess-precision=standard" } + +float f; +double d; + +float fr; +double dr; + +void +test_builtins (void) +{ + fr = __builtin_sqrtf (f); + dr = __builtin_sqrt (d); +} + +// { dg-final { scan-assembler-not "fsqrt" } } diff --git a/gcc/testsuite/g++.target/i386/excess-precision-7.C b/gcc/testsuite/g++.target/i386/excess-precision-7.C new file mode 100644 index 0000000..5df0d9d --- /dev/null +++ b/gcc/testsuite/g++.target/i386/excess-precision-7.C @@ -0,0 +1,7 @@ +// Excess precision tests. Test C99 semantics for conversions from +// integers to floating point: no excess precision for either explicit +// or implicit conversions. +// { dg-do run } +// { dg-options "-mfpmath=387 -fexcess-precision=standard" } + +#include "../../gcc.target/i386/excess-precision-7.c" diff --git a/gcc/testsuite/g++.target/i386/excess-precision-9.C b/gcc/testsuite/g++.target/i386/excess-precision-9.C new file mode 100644 index 0000000..1fcadb9 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/excess-precision-9.C @@ -0,0 +1,6 @@ +// Excess precision tests. Test implicit conversions in comparisons: +// no excess precision in C++. +// { dg-do run } +// { dg-options "-mfpmath=387 -fexcess-precision=standard" } + +#include "../../gcc.target/i386/excess-precision-9.c" diff --git a/gcc/testsuite/gcc.target/i386/excess-precision-1.c b/gcc/testsuite/gcc.target/i386/excess-precision-1.c index 1bd3b88..388cee7 100644 --- a/gcc/testsuite/gcc.target/i386/excess-precision-1.c +++ b/gcc/testsuite/gcc.target/i386/excess-precision-1.c @@ -5,8 +5,14 @@ #include +#ifdef __cplusplus +extern "C" { +#endif extern void abort (void); extern void exit (int); +#ifdef __cplusplus +} +#endif volatile float f1 = 1.0f; volatile float f2 = 0x1.0p-30f; diff --git a/gcc/testsuite/gcc.target/i386/excess-precision-2.c b/gcc/testsuite/gcc.target/i386/excess-precision-2.c index b5035e5..c14784e 100644 --- a/gcc/testsuite/gcc.target/i386/excess-precision-2.c +++ b/gcc/testsuite/gcc.target/i386/excess-precision-2.c @@ -4,8 +4,14 @@ #include +#ifdef __cplusplus +extern "C" { +#endif extern void abort (void); extern void exit (int); +#ifdef __cplusplus +} +#endif volatile long double ldadd1 = 1.0l + 0x1.0p-30l; volatile long double ld11f = 1.1f; diff --git a/gcc/testsuite/gcc.target/i386/excess-precision-3.c b/gcc/testsuite/gcc.target/i386/excess-precision-3.c index 1fd038a..e8e9abc 100644 --- a/gcc/testsuite/gcc.target/i386/excess-precision-3.c +++ b/gcc/testsuite/gcc.target/i386/excess-precision-3.c @@ -6,8 +6,14 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif extern void abort (void); extern void exit (int); +#ifdef __cplusplus +} +#endif volatile float f1 = 1.0f; volatile float f2 = 0x1.0p-30f; @@ -100,6 +106,7 @@ check_double (double d) abort (); } +#ifndef __cplusplus static inline void check_float_nonproto (f) float f; @@ -115,6 +122,7 @@ check_double_nonproto (d) if (d != dadd2) abort (); } +#endif static void check_double_va (int i, ...) @@ -132,9 +140,11 @@ test_call (void) check_float (f1 + f2); check_double (d1 + d2 + d3); check_double (f1 + f2 + f3); +#ifndef __cplusplus check_float_nonproto (f1 + f2); check_double_nonproto (d1 + d2 + d3); check_double_nonproto (f1 + f2 + f3); +#endif check_double_va (0, d1 + d2 + d3); check_double_va (0, f1 + f2 + f3); } diff --git a/gcc/testsuite/gcc.target/i386/excess-precision-7.c b/gcc/testsuite/gcc.target/i386/excess-precision-7.c index 0cdd932..4c3b950 100644 --- a/gcc/testsuite/gcc.target/i386/excess-precision-7.c +++ b/gcc/testsuite/gcc.target/i386/excess-precision-7.c @@ -4,8 +4,14 @@ /* { dg-do run } */ /* { dg-options "-std=c99 -mfpmath=387 -fexcess-precision=standard" } */ +#ifdef __cplusplus +extern "C" { +#endif extern void abort (void); extern void exit (int); +#ifdef __cplusplus +} +#endif int main (void) diff --git a/gcc/testsuite/gcc.target/i386/excess-precision-9.c b/gcc/testsuite/gcc.target/i386/excess-precision-9.c index 61e5fc1..5008164 100644 --- a/gcc/testsuite/gcc.target/i386/excess-precision-9.c +++ b/gcc/testsuite/gcc.target/i386/excess-precision-9.c @@ -3,8 +3,14 @@ /* { dg-do run } */ /* { dg-options "-std=c99 -mfpmath=387 -fexcess-precision=standard" } */ +#ifdef __cplusplus +extern "C" { +#endif extern void abort (void); extern void exit (int); +#ifdef __cplusplus +} +#endif int main (void) -- cgit v1.1 From 16ec267063c8ce60769888d4097bcd158410adc8 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 14 Oct 2022 09:33:23 +0200 Subject: c++: Excess precision for ? int : float or int == float [PR107097, PR82071, PR87390] The following incremental patch implements the C11 behavior (for all C++ versions) for cond ? int : float cond ? float : int int cmp float float cmp int where int is any integral type, float any floating point type with excess precision and cmp ==, !=, >, <, >=, <= and <=>. 2022-10-14 Jakub Jelinek PR c/82071 PR c/87390 PR c++/107097 gcc/cp/ * cp-tree.h (cp_ep_convert_and_check): Remove. * cvt.cc (cp_ep_convert_and_check): Remove. * call.cc (build_conditional_expr): Use excess precision for ?: with one arm floating and another integral. Don't convert first to semantic result type from integral types. (convert_like_internal): Don't call cp_ep_convert_and_check, instead just strip EXCESS_PRECISION_EXPR before calling cp_convert_and_check or cp_convert. * typeck.cc (cp_build_binary_op): Set may_need_excess_precision for comparisons or SPACESHIP_EXPR with at least one operand integral. Don't compute semantic_result_type if build_type is non-NULL. Call cp_convert_and_check instead of cp_ep_convert_and_check. gcc/testsuite/ * gcc.target/i386/excess-precision-8.c: For C++ wrap abort and exit declarations into extern "C" block. * gcc.target/i386/excess-precision-10.c: Likewise. * g++.target/i386/excess-precision-7.C: Remove. * g++.target/i386/excess-precision-8.C: New test. * g++.target/i386/excess-precision-9.C: Remove. * g++.target/i386/excess-precision-10.C: New test. * g++.target/i386/excess-precision-12.C: New test. --- gcc/testsuite/g++.target/i386/excess-precision-10.C | 6 ++++++ gcc/testsuite/g++.target/i386/excess-precision-12.C | 20 ++++++++++++++++++++ gcc/testsuite/g++.target/i386/excess-precision-7.C | 7 ------- gcc/testsuite/g++.target/i386/excess-precision-8.C | 7 +++++++ gcc/testsuite/g++.target/i386/excess-precision-9.C | 6 ------ gcc/testsuite/gcc.target/i386/excess-precision-10.c | 6 ++++++ gcc/testsuite/gcc.target/i386/excess-precision-8.c | 6 ++++++ 7 files changed, 45 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/g++.target/i386/excess-precision-10.C create mode 100644 gcc/testsuite/g++.target/i386/excess-precision-12.C delete mode 100644 gcc/testsuite/g++.target/i386/excess-precision-7.C create mode 100644 gcc/testsuite/g++.target/i386/excess-precision-8.C delete mode 100644 gcc/testsuite/g++.target/i386/excess-precision-9.C (limited to 'gcc/testsuite') diff --git a/gcc/testsuite/g++.target/i386/excess-precision-10.C b/gcc/testsuite/g++.target/i386/excess-precision-10.C new file mode 100644 index 0000000..9dbe25e --- /dev/null +++ b/gcc/testsuite/g++.target/i386/excess-precision-10.C @@ -0,0 +1,6 @@ +// Excess precision tests. Test implicit conversions in comparisons: +// excess precision in C++. +// { dg-do run } +// { dg-options "-mfpmath=387 -fexcess-precision=standard" } + +#include "../../gcc.target/i386/excess-precision-10.c" diff --git a/gcc/testsuite/g++.target/i386/excess-precision-12.C b/gcc/testsuite/g++.target/i386/excess-precision-12.C new file mode 100644 index 0000000..dff48c0 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/excess-precision-12.C @@ -0,0 +1,20 @@ +// Excess precision tests. Test implicit conversions in 3-way comparisons: +// excess precision in C++. +// { dg-do run { target c++20 } } +// { dg-options "-mfpmath=387 -fexcess-precision=standard" } + +#include +#include + +int +main (void) +{ + float f = 0x1p63f; + unsigned long long int u = (1ULL << 63) + 1; + + if ((f <=> u) >= 0) + abort (); + + if ((u <=> f) <= 0) + abort (); +} diff --git a/gcc/testsuite/g++.target/i386/excess-precision-7.C b/gcc/testsuite/g++.target/i386/excess-precision-7.C deleted file mode 100644 index 5df0d9d..0000000 --- a/gcc/testsuite/g++.target/i386/excess-precision-7.C +++ /dev/null @@ -1,7 +0,0 @@ -// Excess precision tests. Test C99 semantics for conversions from -// integers to floating point: no excess precision for either explicit -// or implicit conversions. -// { dg-do run } -// { dg-options "-mfpmath=387 -fexcess-precision=standard" } - -#include "../../gcc.target/i386/excess-precision-7.c" diff --git a/gcc/testsuite/g++.target/i386/excess-precision-8.C b/gcc/testsuite/g++.target/i386/excess-precision-8.C new file mode 100644 index 0000000..c170c00 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/excess-precision-8.C @@ -0,0 +1,7 @@ +// Excess precision tests. Test C++ semantics for conversions from +// integers to floating point: no excess precision for either explicit +// or implicit conversions. +// { dg-do run } +// { dg-options "-mfpmath=387 -fexcess-precision=standard" } + +#include "../../gcc.target/i386/excess-precision-8.c" diff --git a/gcc/testsuite/g++.target/i386/excess-precision-9.C b/gcc/testsuite/g++.target/i386/excess-precision-9.C deleted file mode 100644 index 1fcadb9..0000000 --- a/gcc/testsuite/g++.target/i386/excess-precision-9.C +++ /dev/null @@ -1,6 +0,0 @@ -// Excess precision tests. Test implicit conversions in comparisons: -// no excess precision in C++. -// { dg-do run } -// { dg-options "-mfpmath=387 -fexcess-precision=standard" } - -#include "../../gcc.target/i386/excess-precision-9.c" diff --git a/gcc/testsuite/gcc.target/i386/excess-precision-10.c b/gcc/testsuite/gcc.target/i386/excess-precision-10.c index f1b9b7e..1dd3e7a 100644 --- a/gcc/testsuite/gcc.target/i386/excess-precision-10.c +++ b/gcc/testsuite/gcc.target/i386/excess-precision-10.c @@ -3,8 +3,14 @@ /* { dg-do run } */ /* { dg-options "-std=c11 -mfpmath=387 -fexcess-precision=standard" } */ +#ifdef __cplusplus +extern "C" { +#endif extern void abort (void); extern void exit (int); +#ifdef __cplusplus +} +#endif int main (void) diff --git a/gcc/testsuite/gcc.target/i386/excess-precision-8.c b/gcc/testsuite/gcc.target/i386/excess-precision-8.c index c0a31ed..8dd0458 100644 --- a/gcc/testsuite/gcc.target/i386/excess-precision-8.c +++ b/gcc/testsuite/gcc.target/i386/excess-precision-8.c @@ -4,8 +4,14 @@ /* { dg-do run } */ /* { dg-options "-std=c11 -mfpmath=387 -fexcess-precision=standard" } */ +#ifdef __cplusplus +extern "C" { +#endif extern void abort (void); extern void exit (int); +#ifdef __cplusplus +} +#endif int main (void) -- cgit v1.1 From c2565a31c1622ab0926aeef4a6579413e121b9f9 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 14 Oct 2022 09:37:01 +0200 Subject: middle-end, c++, i386, libgcc: std::bfloat16_t and __bf16 arithmetic support Here is a complete patch to add std::bfloat16_t support on x86 (AArch64 and ARM left for later). Almost no BFmode optabs are added by the patch, so for binops/unops it extends to SFmode first and then truncates back to BFmode. For {HF,SF,DF,XF,TF}mode -> BFmode conversions libgcc has implementations of all those conversions so that we avoid double rounding, for BFmode -> {DF,XF,TF}mode conversions to avoid growing libgcc too much it emits BFmode -> SFmode conversion first and then converts to the even wider mode, neither step should be imprecise. For BFmode -> HFmode, it first emits a precise BFmode -> SFmode conversion and then SFmode -> HFmode, because neither format is subset or superset of the other, while SFmode is superset of both. expr.cc then contains a -ffast-math optimization of the BF -> SF and SF -> BF conversions if we don't optimize for space (and for the latter if -frounding-math isn't enabled either). For x86, perhaps truncsfbf2 optab could be defined for TARGET_AVX512BF16 but IMNSHO should FAIL if !flag_finite_math || flag_rounding_math || !flag_unsafe_math_optimizations, because I think the insn doesn't raise on sNaNs, hardcodes round to nearest and flushes denormals to zero. By default (unless x86 -fexcess-precision=16) we use float excess precision for BFmode, so truncate only on explicit casts and assignments. The patch introduces a single __bf16 builtin - __builtin_nansf16b, because (__bf16) __builtin_nansf ("") will drop the sNaN into qNaN, and uses f16b suffix instead of bf16 because there would be ambiguity on log vs. logb - __builtin_logbf16 could be either log with bf16 suffix or logb with f16 suffix. In other cases libstdc++ should mostly use __builtin_*f for std::bfloat16_t overloads (we have a problem with std::nextafter though but that one we have also for std::float16_t). 2022-10-14 Jakub Jelinek gcc/ * tree-core.h (enum tree_index): Add TI_BFLOAT16_TYPE. * tree.h (bfloat16_type_node): Define. * tree.cc (excess_precision_type): Promote bfloat16_type_mode like float16_type_mode. (build_common_tree_nodes): Initialize bfloat16_type_node if BFmode is supported. * expmed.h (maybe_expand_shift): Declare. * expmed.cc (maybe_expand_shift): No longer static. * expr.cc (convert_mode_scalar): Don't ICE on BF -> HF or HF -> BF conversions. If there is no optab, handle BF -> {DF,XF,TF,HF} conversions as separate BF -> SF -> {DF,XF,TF,HF} conversions, add -ffast-math generic implementation for BF -> SF and SF -> BF conversions. * builtin-types.def (BT_BFLOAT16, BT_FN_BFLOAT16_CONST_STRING): New. * builtins.def (BUILT_IN_NANSF16B): New builtin. * fold-const-call.cc (fold_const_call): Handle CFN_BUILT_IN_NANSF16B. * config/i386/i386.cc (classify_argument): Handle E_BCmode. (ix86_libgcc_floating_mode_supported_p): Also return true for BFmode for -msse2. (ix86_mangle_type): Mangle BFmode as DF16b. (ix86_invalid_conversion, ix86_invalid_unary_op, ix86_invalid_binary_op): Remove. (TARGET_INVALID_CONVERSION, TARGET_INVALID_UNARY_OP, TARGET_INVALID_BINARY_OP): Don't redefine. * config/i386/i386-builtins.cc (ix86_bf16_type_node): Remove. (ix86_register_bf16_builtin_type): Use bfloat16_type_node rather than ix86_bf16_type_node, only create it if still NULL. * config/i386/i386-builtin-types.def (BFLOAT16): Likewise. * config/i386/i386.md (cbranchbf4, cstorebf4): New expanders. gcc/c-family/ * c-cppbuiltin.cc (c_cpp_builtins): If bfloat16_type_node, predefine __BFLT16_*__ macros and for C++23 also __STDCPP_BFLOAT16_T__. Predefine bfloat16_type_node related macros for -fbuilding-libgcc. * c-lex.cc (interpret_float): Handle CPP_N_BFLOAT16. gcc/c/ * c-typeck.cc (convert_arguments): Don't promote __bf16 to double. gcc/cp/ * cp-tree.h (extended_float_type_p): Return true for bfloat16_type_node. * typeck.cc (cp_compare_floating_point_conversion_ranks): Set extended{1,2} if mv{1,2} is bfloat16_type_node. Adjust comment. gcc/testsuite/ * lib/target-supports.exp (check_effective_target_bfloat16, check_effective_target_bfloat16_runtime, add_options_for_bfloat16): New. * gcc.dg/torture/bfloat16-basic.c: New test. * gcc.dg/torture/bfloat16-builtin.c: New test. * gcc.dg/torture/bfloat16-builtin-issignaling-1.c: New test. * gcc.dg/torture/bfloat16-complex.c: New test. * gcc.dg/torture/builtin-issignaling-1.c: Allow to be includable from bfloat16-builtin-issignaling-1.c. * gcc.dg/torture/floatn-basic.h: Allow to be includable from bfloat16-basic.c. * gcc.target/i386/vect-bfloat16-typecheck_2.c: Adjust expected diagnostics. * gcc.target/i386/sse2-bfloat16-scalar-typecheck.c: Likewise. * gcc.target/i386/vect-bfloat16-typecheck_1.c: Likewise. * g++.target/i386/bfloat_cpp_typecheck.C: Likewise. libcpp/ * include/cpplib.h (CPP_N_BFLOAT16): Define. * expr.cc (interpret_float_suffix): Handle bf16 and BF16 suffixes for C++. libgcc/ * config/i386/t-softfp (softfp_extensions): Add bfsf. (softfp_truncations): Add tfbf xfbf dfbf sfbf hfbf. (CFLAGS-extendbfsf2.c, CFLAGS-truncsfbf2.c, CFLAGS-truncdfbf2.c, CFLAGS-truncxfbf2.c, CFLAGS-trunctfbf2.c, CFLAGS-trunchfbf2.c): Add -msse2. * config/i386/libgcc-glibc.ver (GCC_13.0.0): Export __extendbfsf2 and __trunc{s,d,x,t,h}fbf2. * config/i386/sfp-machine.h (_FP_NANSIGN_B): Define. * config/i386/64/sfp-machine.h (_FP_NANFRAC_B): Define. * config/i386/32/sfp-machine.h (_FP_NANFRAC_B): Define. * soft-fp/brain.h: New file. * soft-fp/truncsfbf2.c: New file. * soft-fp/truncdfbf2.c: New file. * soft-fp/truncxfbf2.c: New file. * soft-fp/trunctfbf2.c: New file. * soft-fp/trunchfbf2.c: New file. * soft-fp/truncbfhf2.c: New file. * soft-fp/extendbfsf2.c: New file. libiberty/ * cp-demangle.h (D_BUILTIN_TYPE_COUNT): Increment. * cp-demangle.c (cplus_demangle_builtin_types): Add std::bfloat16_t entry. (cplus_demangle_type): Demangle DF16b. * testsuite/demangle-expected (_Z3xxxDF16b): New test. --- .../g++.target/i386/bfloat_cpp_typecheck.C | 4 +- gcc/testsuite/gcc.dg/torture/bfloat16-basic.c | 11 ++ .../torture/bfloat16-builtin-issignaling-1.c | 21 +++ gcc/testsuite/gcc.dg/torture/bfloat16-builtin.c | 47 +++++ gcc/testsuite/gcc.dg/torture/bfloat16-complex.c | 61 +++++++ .../gcc.dg/torture/builtin-issignaling-1.c | 47 +++-- gcc/testsuite/gcc.dg/torture/floatn-basic.h | 18 +- .../i386/sse2-bfloat16-scalar-typecheck.c | 196 ++++++++++----------- .../gcc.target/i386/vect-bfloat16-typecheck_1.c | 100 +++++------ .../gcc.target/i386/vect-bfloat16-typecheck_2.c | 98 +++++------ gcc/testsuite/lib/target-supports.exp | 16 ++ 11 files changed, 394 insertions(+), 225 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/bfloat16-basic.c create mode 100644 gcc/testsuite/gcc.dg/torture/bfloat16-builtin-issignaling-1.c create mode 100644 gcc/testsuite/gcc.dg/torture/bfloat16-builtin.c create mode 100644 gcc/testsuite/gcc.dg/torture/bfloat16-complex.c (limited to 'gcc/testsuite') diff --git a/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C b/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C index b800a6d..2567129 100644 --- a/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C +++ b/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C @@ -5,6 +5,6 @@ void foo (void) { __bf16 (); /* { dg-bogus {invalid conversion to type '__bf16'} } */ __bf16 a = __bf16(); /* { dg-bogus {invalid conversion to type '__bf16'} } */ - __bf16 (0x1234); /* { dg-error {invalid conversion to type '__bf16'} } */ - __bf16 (0.1); /* { dg-error {invalid conversion to type '__bf16'} } */ + __bf16 (0x1234); /* { dg-bogus {invalid conversion to type '__bf16'} } */ + __bf16 (0.1); /* { dg-bogus {invalid conversion to type '__bf16'} } */ } diff --git a/gcc/testsuite/gcc.dg/torture/bfloat16-basic.c b/gcc/testsuite/gcc.dg/torture/bfloat16-basic.c new file mode 100644 index 0000000..09e54d4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/bfloat16-basic.c @@ -0,0 +1,11 @@ +/* Test __bf16. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options bfloat16 } */ +/* { dg-require-effective-target bfloat16_runtime } */ + +#define TYPE __bf16 +#define CST(C) CONCAT (C, bf16) +#define CSTU(C) CONCAT (C, BF16) + +#include "floatn-basic.h" diff --git a/gcc/testsuite/gcc.dg/torture/bfloat16-builtin-issignaling-1.c b/gcc/testsuite/gcc.dg/torture/bfloat16-builtin-issignaling-1.c new file mode 100644 index 0000000..0e428db --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/bfloat16-builtin-issignaling-1.c @@ -0,0 +1,21 @@ +/* Test __bf16 __builtin_issignaling. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options bfloat16 } */ +/* { dg-add-options ieee } */ +/* { dg-require-effective-target bfloat16_runtime } */ +/* { dg-additional-options "-fsignaling-nans" } */ +/* Workaround for PR57484 on ia32: */ +/* { dg-additional-options "-msse2 -mfpmath=sse" { target { ia32 && sse2_runtime } } } */ + +#define CONCATX(X, Y) X ## Y +#define CONCAT(X, Y) CONCATX (X, Y) + +#define TYPE __bf16 +#define CST(C) CONCAT (C, bf16) +#define FN(F) CONCAT (F, f16b) +#define NAN(x) ((__bf16) __builtin_nanf (x)) +#define INF ((__bf16) __builtin_inff ()) +#define EXT 0 + +#include "builtin-issignaling-1.c" diff --git a/gcc/testsuite/gcc.dg/torture/bfloat16-builtin.c b/gcc/testsuite/gcc.dg/torture/bfloat16-builtin.c new file mode 100644 index 0000000..ce02f6f --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/bfloat16-builtin.c @@ -0,0 +1,47 @@ +/* Test __bf16 built-in functions. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options bfloat16 } */ +/* { dg-add-options ieee } */ +/* { dg-require-effective-target bfloat16_runtime } */ + +extern void exit (int); +extern void abort (void); + +extern __bf16 test_type; +extern __typeof (__builtin_nansf16b ("")) test_type; + +volatile __bf16 inf_cst = (__bf16) __builtin_inff (); +volatile __bf16 huge_val_cst = (__bf16) __builtin_huge_valf (); +volatile __bf16 nan_cst = (__bf16) __builtin_nanf (""); +volatile __bf16 nans_cst = __builtin_nansf16b (""); +volatile __bf16 neg0 = -0.0bf16, neg1 = -1.0bf16, one = 1.0; + +int +main (void) +{ + volatile __bf16 r; + if (!__builtin_isinf (inf_cst)) + abort (); + if (!__builtin_isinf (huge_val_cst)) + abort (); + if (inf_cst != huge_val_cst) + abort (); + if (!__builtin_isnan (nan_cst)) + abort (); + if (!__builtin_isnan (nans_cst)) + abort (); + r = __builtin_fabsf (neg1); + if (r != 1.0bf16) + abort (); + r = __builtin_copysignf (one, neg0); + if (r != neg1) + abort (); + r = __builtin_copysignf (inf_cst, neg1); + if (r != -huge_val_cst) + abort (); + r = __builtin_copysignf (-inf_cst, one); + if (r != huge_val_cst) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/bfloat16-complex.c b/gcc/testsuite/gcc.dg/torture/bfloat16-complex.c new file mode 100644 index 0000000..fa27a77 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/bfloat16-complex.c @@ -0,0 +1,61 @@ +/* Test __bf16 complex arithmetic. */ +/* { dg-do run } */ +/* { dg-options "" } */ +/* { dg-add-options bfloat16 } */ +/* { dg-require-effective-target bfloat16_runtime } */ + +extern void exit (int); +extern void abort (void); + +volatile __bf16 a = 1.0bf16; +typedef _Complex float __cbf16 __attribute__((__mode__(__BC__))); +volatile __cbf16 b = __builtin_complex (2.0bf16, 3.0bf16); +volatile __cbf16 c = __builtin_complex (2.0bf16, 3.0bf16); +volatile __cbf16 d = __builtin_complex (2.0bf16, 3.0bf16); + +__cbf16 +fn (__cbf16 arg) +{ + return arg / 4; +} + +int +main (void) +{ + volatile __cbf16 r; + if (b != c) + abort (); + if (b != d) + abort (); + r = a + b; + if (__real__ r != 3.0bf16 || __imag__ r != 3.0bf16) + abort (); + r += d; + if (__real__ r != 5.0bf16 || __imag__ r != 6.0bf16) + abort (); + r -= a; + if (__real__ r != 4.0bf16 || __imag__ r != 6.0bf16) + abort (); + r /= (a + a); + if (__real__ r != 2.0bf16 || __imag__ r != 3.0bf16) + abort (); + r *= (a + a); + if (__real__ r != 4.0bf16 || __imag__ r != 6.0bf16) + abort (); + r -= b; + if (__real__ r != 2.0bf16 || __imag__ r != 3.0bf16) + abort (); + r *= r; + if (__real__ r != -5.0bf16 || __imag__ r != 12.0bf16) + abort (); + /* Division may not be exact, so round result before comparing. */ + r /= b; + r += __builtin_complex (100.0bf16, 100.0bf16); + r -= __builtin_complex (100.0bf16, 100.0bf16); + if (r != b) + abort (); + r = fn (r); + if (__real__ r != 0.5bf16 || __imag__ r != 0.75bf16) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/builtin-issignaling-1.c b/gcc/testsuite/gcc.dg/torture/builtin-issignaling-1.c index fddca6c..60125b2 100644 --- a/gcc/testsuite/gcc.dg/torture/builtin-issignaling-1.c +++ b/gcc/testsuite/gcc.dg/torture/builtin-issignaling-1.c @@ -4,7 +4,7 @@ /* Workaround for PR57484 on ia32: */ /* { dg-additional-options "-msse2 -mfpmath=sse" { target { ia32 && sse2_runtime } } } */ -#ifndef EXT +#if !defined(EXT) && !defined(TYPE) int f1 (void) { @@ -41,31 +41,42 @@ f6 (long double x) return __builtin_issignaling (x); } #else -#define CONCATX(X, Y) X ## Y -#define CONCAT(X, Y) CONCATX (X, Y) -#define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z) -#define CONCAT4(W, X, Y, Z) CONCAT (CONCAT (CONCAT (W, X), Y), Z) +#ifndef TYPE +# define CONCATX(X, Y) X ## Y +# define CONCAT(X, Y) CONCATX (X, Y) +# define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z) +# define CONCAT4(W, X, Y, Z) CONCAT (CONCAT (CONCAT (W, X), Y), Z) -#if EXT -# define TYPE CONCAT3 (_Float, WIDTH, x) -# define CST(C) CONCAT4 (C, f, WIDTH, x) -# define FN(F) CONCAT4 (F, f, WIDTH, x) -#else -# define TYPE CONCAT (_Float, WIDTH) -# define CST(C) CONCAT3 (C, f, WIDTH) -# define FN(F) CONCAT3 (F, f, WIDTH) +# if EXT +# define TYPE CONCAT3 (_Float, WIDTH, x) +# define CST(C) CONCAT4 (C, f, WIDTH, x) +# define FN(F) CONCAT4 (F, f, WIDTH, x) +# else +# define TYPE CONCAT (_Float, WIDTH) +# define CST(C) CONCAT3 (C, f, WIDTH) +# define FN(F) CONCAT3 (F, f, WIDTH) +# endif +#endif +#ifndef NANS +# define NANS(x) FN (__builtin_nans) (x) +#endif +#ifndef NAN +# define NAN(x) FN (__builtin_nan) (x) +#endif +#ifndef INF +# define INF FN (__builtin_inf) () #endif int f1 (void) { - return __builtin_issignaling (FN (__builtin_nans) ("")); + return __builtin_issignaling (NANS ("")); } int f2 (void) { - return __builtin_issignaling (FN (__builtin_nan) ("")); + return __builtin_issignaling (NAN ("")); } int @@ -118,10 +129,10 @@ main () if (!f6 (z)) __builtin_abort (); #else - if (f4 (w) || !f4 (FN (__builtin_nans) ("0x123")) || f4 (CST (42.0)) || f4 (FN (__builtin_nan) ("0x234")) - || f4 (FN (__builtin_inf) ()) || f4 (-FN (__builtin_inf) ()) || f4 (CST (-42.0)) || f4 (CST (-0.0)) || f4 (CST (0.0))) + if (f4 (w) || !f4 (NANS ("0x123")) || f4 (CST (42.0)) || f4 (NAN ("0x234")) + || f4 (INF) || f4 (-INF) || f4 (CST (-42.0)) || f4 (CST (-0.0)) || f4 (CST (0.0))) __builtin_abort (); - w = FN (__builtin_nans) (""); + w = NANS (""); asm volatile ("" : : : "memory"); if (!f4 (w)) __builtin_abort (); diff --git a/gcc/testsuite/gcc.dg/torture/floatn-basic.h b/gcc/testsuite/gcc.dg/torture/floatn-basic.h index 9131f46..6540b53 100644 --- a/gcc/testsuite/gcc.dg/torture/floatn-basic.h +++ b/gcc/testsuite/gcc.dg/torture/floatn-basic.h @@ -9,14 +9,16 @@ #define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z) #define CONCAT4(W, X, Y, Z) CONCAT (CONCAT (CONCAT (W, X), Y), Z) -#if EXT -# define TYPE CONCAT3 (_Float, WIDTH, x) -# define CST(C) CONCAT4 (C, f, WIDTH, x) -# define CSTU(C) CONCAT4 (C, F, WIDTH, x) -#else -# define TYPE CONCAT (_Float, WIDTH) -# define CST(C) CONCAT3 (C, f, WIDTH) -# define CSTU(C) CONCAT3 (C, F, WIDTH) +#ifndef TYPE +# if EXT +# define TYPE CONCAT3 (_Float, WIDTH, x) +# define CST(C) CONCAT4 (C, f, WIDTH, x) +# define CSTU(C) CONCAT4 (C, F, WIDTH, x) +# else +# define TYPE CONCAT (_Float, WIDTH) +# define CST(C) CONCAT3 (C, f, WIDTH) +# define CSTU(C) CONCAT3 (C, F, WIDTH) +# endif #endif extern void exit (int); diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c index 52b53b9..d1a76db 100644 --- a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c +++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c @@ -12,8 +12,8 @@ double is_a_double; float *float_ptr; -__bf16 foo1 (void) { return (__bf16) 0x1234; } /* { dg-error {invalid conversion to type '__bf16'} } */ -__bf16 foo2 (void) { return (__bf16) (short) 0x1234; } /* { dg-error {invalid conversion to type '__bf16'} } */ +__bf16 foo1 (void) { return (__bf16) 0x1234; } +__bf16 foo2 (void) { return (__bf16) (short) 0x1234; } __bf16 footest (__bf16 scalar0) { @@ -22,87 +22,87 @@ __bf16 footest (__bf16 scalar0) __bf16 scalar1_1; __bf16 scalar1_2 = glob_bfloat; - __bf16 scalar1_3 = 0; /* { dg-error {invalid conversion to type '__bf16'} } */ - __bf16 scalar1_4 = 0.1; /* { dg-error {invalid conversion to type '__bf16'} } */ - __bf16 scalar1_5 = is_a_float; /* { dg-error {invalid conversion to type '__bf16'} } */ - __bf16 scalar1_6 = is_an_int; /* { dg-error {invalid conversion to type '__bf16'} } */ - __bf16 scalar1_7 = is_a_float16; /* { dg-error {invalid conversion to type '__bf16'} } */ - __bf16 scalar1_8 = is_a_double; /* { dg-error {invalid conversion to type '__bf16'} } */ - __bf16 scalar1_9 = is_a_short_int; /* { dg-error {invalid conversion to type '__bf16'} } */ - - int initi_1_1 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ - float initi_1_2 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ - _Float16 initi_1_3 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ - short initi_1_4 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ - double initi_1_5 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ + __bf16 scalar1_3 = 0; + __bf16 scalar1_4 = 0.1; + __bf16 scalar1_5 = is_a_float; + __bf16 scalar1_6 = is_an_int; + __bf16 scalar1_7 = is_a_float16; + __bf16 scalar1_8 = is_a_double; + __bf16 scalar1_9 = is_a_short_int; + + int initi_1_1 = glob_bfloat; + float initi_1_2 = glob_bfloat; + _Float16 initi_1_3 = glob_bfloat; + short initi_1_4 = glob_bfloat; + double initi_1_5 = glob_bfloat; __bf16 scalar2_1 = {}; __bf16 scalar2_2 = { glob_bfloat }; - __bf16 scalar2_3 = { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } */ - __bf16 scalar2_4 = { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} } */ - __bf16 scalar2_5 = { is_a_float }; /* { dg-error {invalid conversion to type '__bf16'} } */ - __bf16 scalar2_6 = { is_an_int }; /* { dg-error {invalid conversion to type '__bf16'} } */ - __bf16 scalar2_7 = { is_a_float16 }; /* { dg-error {invalid conversion to type '__bf16'} } */ - __bf16 scalar2_8 = { is_a_double }; /* { dg-error {invalid conversion to type '__bf16'} } */ - __bf16 scalar2_9 = { is_a_short_int }; /* { dg-error {invalid conversion to type '__bf16'} } */ - - int initi_2_1 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ - float initi_2_2 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ - _Float16 initi_2_3 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ - short initi_2_4 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ - double initi_2_5 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ + __bf16 scalar2_3 = { 0 }; + __bf16 scalar2_4 = { 0.1 }; + __bf16 scalar2_5 = { is_a_float }; + __bf16 scalar2_6 = { is_an_int }; + __bf16 scalar2_7 = { is_a_float16 }; + __bf16 scalar2_8 = { is_a_double }; + __bf16 scalar2_9 = { is_a_short_int }; + + int initi_2_1 = { glob_bfloat }; + float initi_2_2 = { glob_bfloat }; + _Float16 initi_2_3 = { glob_bfloat }; + short initi_2_4 = { glob_bfloat }; + double initi_2_5 = { glob_bfloat }; /* Assignments. */ glob_bfloat = glob_bfloat; - glob_bfloat = 0; /* { dg-error {invalid conversion to type '__bf16'} } */ - glob_bfloat = 0.1; /* { dg-error {invalid conversion to type '__bf16'} } */ - glob_bfloat = is_a_float; /* { dg-error {invalid conversion to type '__bf16'} } */ - glob_bfloat = is_an_int; /* { dg-error {invalid conversion to type '__bf16'} } */ - glob_bfloat = is_a_float16; /* { dg-error {invalid conversion to type '__bf16'} } */ - glob_bfloat = is_a_double; /* { dg-error {invalid conversion to type '__bf16'} } */ - glob_bfloat = is_a_short_int; /* { dg-error {invalid conversion to type '__bf16'} } */ - - is_an_int = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ - is_a_float = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ - is_a_float16 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ - is_a_double = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ - is_a_short_int = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ + glob_bfloat = 0; + glob_bfloat = 0.1; + glob_bfloat = is_a_float; + glob_bfloat = is_an_int; + glob_bfloat = is_a_float16; + glob_bfloat = is_a_double; + glob_bfloat = is_a_short_int; + + is_an_int = glob_bfloat; + is_a_float = glob_bfloat; + is_a_float16 = glob_bfloat; + is_a_double = glob_bfloat; + is_a_short_int = glob_bfloat; /* Casting. */ (void) glob_bfloat; (__bf16) glob_bfloat; - (int) glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ - (float) glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ - (_Float16) glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ - (double) glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ - (short) glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ + (int) glob_bfloat; + (float) glob_bfloat; + (_Float16) glob_bfloat; + (double) glob_bfloat; + (short) glob_bfloat; - (__bf16) is_an_int; /* { dg-error {invalid conversion to type '__bf16'} } */ - (__bf16) is_a_float; /* { dg-error {invalid conversion to type '__bf16'} } */ - (__bf16) is_a_float16; /* { dg-error {invalid conversion to type '__bf16'} } */ - (__bf16) is_a_double; /* { dg-error {invalid conversion to type '__bf16'} } */ - (__bf16) is_a_short_int; /* { dg-error {invalid conversion to type '__bf16'} } */ + (__bf16) is_an_int; + (__bf16) is_a_float; + (__bf16) is_a_float16; + (__bf16) is_a_double; + (__bf16) is_a_short_int; /* Compound literals. */ (__bf16) {}; (__bf16) { glob_bfloat }; - (__bf16) { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } */ - (__bf16) { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} } */ - (__bf16) { is_a_float }; /* { dg-error {invalid conversion to type '__bf16'} } */ - (__bf16) { is_an_int }; /* { dg-error {invalid conversion to type '__bf16'} } */ - (__bf16) { is_a_float16 }; /* { dg-error {invalid conversion to type '__bf16'} } */ - (__bf16) { is_a_double }; /* { dg-error {invalid conversion to type '__bf16'} } */ - (__bf16) { is_a_short_int }; /* { dg-error {invalid conversion to type '__bf16'} } */ - - (int) { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ - (float) { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ - (_Float16) { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ - (double) { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ - (short) { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ + (__bf16) { 0 }; + (__bf16) { 0.1 }; + (__bf16) { is_a_float }; + (__bf16) { is_an_int }; + (__bf16) { is_a_float16 }; + (__bf16) { is_a_double }; + (__bf16) { is_a_short_int }; + + (int) { glob_bfloat }; + (float) { glob_bfloat }; + (_Float16) { glob_bfloat }; + (double) { glob_bfloat }; + (short) { glob_bfloat }; /* Arrays and Structs. */ @@ -145,16 +145,16 @@ __bf16 footest (__bf16 scalar0) bfloat_ptr = &bfloat_ptr3[1]; /* Simple comparison. */ - scalar0 > glob_bfloat; /* { dg-error {operation not permitted on type '__bf16'} } */ - glob_bfloat == scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ - scalar0 > is_a_float; /* { dg-error {operation not permitted on type '__bf16'} } */ - is_a_float == scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ - scalar0 > 0; /* { dg-error {operation not permitted on type '__bf16'} } */ - 0 == scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ - scalar0 > 0.1; /* { dg-error {operation not permitted on type '__bf16'} } */ - 0.1 == scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ - scalar0 > is_an_int; /* { dg-error {operation not permitted on type '__bf16'} } */ - is_an_int == scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ + scalar0 > glob_bfloat; + glob_bfloat == scalar0; + scalar0 > is_a_float; + is_a_float == scalar0; + scalar0 > 0; + 0 == scalar0; + scalar0 > 0.1; + 0.1 == scalar0; + scalar0 > is_an_int; + is_an_int == scalar0; /* Pointer comparison. */ @@ -174,41 +174,41 @@ __bf16 footest (__bf16 scalar0) /* Conditional expressions. */ 0 ? scalar0 : scalar0; - 0 ? scalar0 : is_a_float; /* { dg-error {invalid conversion from type '__bf16'} } */ - 0 ? is_a_float : scalar0; /* { dg-error {invalid conversion from type '__bf16'} } */ - 0 ? scalar0 : 0; /* { dg-error {invalid conversion to type '__bf16'} } */ - 0 ? 0 : scalar0; /* { dg-error {invalid conversion to type '__bf16'} } */ - 0 ? 0.1 : scalar0; /* { dg-error {invalid conversion from type '__bf16'} } */ - 0 ? scalar0 : 0.1; /* { dg-error {invalid conversion from type '__bf16'} } */ + 0 ? scalar0 : is_a_float; + 0 ? is_a_float : scalar0; + 0 ? scalar0 : 0; + 0 ? 0 : scalar0; + 0 ? 0.1 : scalar0; + 0 ? scalar0 : 0.1; 0 ? bfloat_ptr : bfloat_ptr2; 0 ? bfloat_ptr : float_ptr; /* { dg-warning {pointer type mismatch in conditional expression} } */ 0 ? float_ptr : bfloat_ptr; /* { dg-warning {pointer type mismatch in conditional expression} } */ - scalar0 ? scalar0 : scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ - scalar0 ? is_a_float : scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ - scalar0 ? scalar0 : is_a_float; /* { dg-error {operation not permitted on type '__bf16'} } */ - scalar0 ? is_a_float : is_a_float; /* { dg-error {operation not permitted on type '__bf16'} } */ + scalar0 ? scalar0 : scalar0; + scalar0 ? is_a_float : scalar0; + scalar0 ? scalar0 : is_a_float; + scalar0 ? is_a_float : is_a_float; /* Unary operators. */ - +scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ - -scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ - ~scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ - !scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ + +scalar0; + -scalar0; + ~scalar0; /* { dg-error {wrong type argument to bit-complement} } */ + !scalar0; *scalar0; /* { dg-error {invalid type argument of unary '\*'} } */ - __real scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ - __imag scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ - ++scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ - --scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ - scalar0++; /* { dg-error {operation not permitted on type '__bf16'} } */ - scalar0--; /* { dg-error {operation not permitted on type '__bf16'} } */ + __real scalar0; + __imag scalar0; + ++scalar0; + --scalar0; + scalar0++; + scalar0--; /* Binary arithmetic operations. */ - scalar0 = glob_bfloat + *bfloat_ptr; /* { dg-error {operation not permitted on type '__bf16'} } */ - scalar0 = glob_bfloat + 0.1; /* { dg-error {operation not permitted on type '__bf16'} } */ - scalar0 = glob_bfloat + 0; /* { dg-error {operation not permitted on type '__bf16'} } */ - scalar0 = glob_bfloat + is_a_float; /* { dg-error {operation not permitted on type '__bf16'} } */ + scalar0 = glob_bfloat + *bfloat_ptr; + scalar0 = glob_bfloat + 0.1; + scalar0 = glob_bfloat + 0; + scalar0 = glob_bfloat + is_a_float; return scalar0; } diff --git a/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_1.c b/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_1.c index 3804bac..8bc3f4a 100644 --- a/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_1.c +++ b/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_1.c @@ -48,20 +48,20 @@ __m128bf16 footest (__m128bf16 vector0) __m128bf16 vector2_1 = {}; __m128bf16 vector2_2 = { glob_bfloat }; __m128bf16 vector2_3 = { glob_bfloat, glob_bfloat, glob_bfloat, glob_bfloat }; - __m128bf16 vector2_4 = { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } */ - __m128bf16 vector2_5 = { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} } */ - __m128bf16 vector2_6 = { is_a_float16 }; /* { dg-error {invalid conversion to type '__bf16'} } */ - __m128bf16 vector2_7 = { is_a_float }; /* { dg-error {invalid conversion to type '__bf16'} } */ - __m128bf16 vector2_8 = { is_an_int }; /* { dg-error {invalid conversion to type '__bf16'} } */ - __m128bf16 vector2_9 = { is_a_short_int }; /* { dg-error {invalid conversion to type '__bf16'} } */ - __m128bf16 vector2_10 = { 0.0, 0, is_a_short_int, is_a_float }; /* { dg-error {invalid conversion to type '__bf16'} } */ - - __v8si initi_2_1 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ - __m256 initi_2_2 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ - __m128h initi_2_3 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ - __m128 initi_2_4 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ - __v4si initi_2_5 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ - __v4hi initi_2_6 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ + __m128bf16 vector2_4 = { 0 }; + __m128bf16 vector2_5 = { 0.1 }; + __m128bf16 vector2_6 = { is_a_float16 }; + __m128bf16 vector2_7 = { is_a_float }; + __m128bf16 vector2_8 = { is_an_int }; + __m128bf16 vector2_9 = { is_a_short_int }; + __m128bf16 vector2_10 = { 0.0, 0, is_a_short_int, is_a_float }; + + __v8si initi_2_1 = { glob_bfloat }; + __m256 initi_2_2 = { glob_bfloat }; + __m128h initi_2_3 = { glob_bfloat }; + __m128 initi_2_4 = { glob_bfloat }; + __v4si initi_2_5 = { glob_bfloat }; + __v4hi initi_2_6 = { glob_bfloat }; /* Assignments to/from vectors. */ @@ -85,25 +85,25 @@ __m128bf16 footest (__m128bf16 vector0) /* Assignments to/from elements. */ vector2_3[0] = glob_bfloat; - vector2_3[0] = is_an_int; /* { dg-error {invalid conversion to type '__bf16'} } */ - vector2_3[0] = is_a_short_int; /* { dg-error {invalid conversion to type '__bf16'} } */ - vector2_3[0] = is_a_float; /* { dg-error {invalid conversion to type '__bf16'} } */ - vector2_3[0] = is_a_float16; /* { dg-error {invalid conversion to type '__bf16'} } */ - vector2_3[0] = 0; /* { dg-error {invalid conversion to type '__bf16'} } */ - vector2_3[0] = 0.1; /* { dg-error {invalid conversion to type '__bf16'} } */ + vector2_3[0] = is_an_int; + vector2_3[0] = is_a_short_int; + vector2_3[0] = is_a_float; + vector2_3[0] = is_a_float16; + vector2_3[0] = 0; + vector2_3[0] = 0.1; glob_bfloat = vector2_3[0]; - is_an_int = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */ - is_a_short_int = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */ - is_a_float = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */ - is_a_float16 = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */ + is_an_int = vector2_3[0]; + is_a_short_int = vector2_3[0]; + is_a_float = vector2_3[0]; + is_a_float16 = vector2_3[0]; /* Compound literals. */ (__m128bf16) {}; - (__m128bf16) { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } */ - (__m128bf16) { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} } */ + (__m128bf16) { 0 }; + (__m128bf16) { 0.1 }; (__m128bf16) { is_a_float_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type '__m256'} } */ (__m128bf16) { is_an_int_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type '__v8si'} } */ (__m128bf16) { is_a_float_pair }; /* { dg-error {incompatible types when initializing type '__bf16' using type '__m128'} } */ @@ -186,16 +186,16 @@ __m128bf16 footest (__m128bf16 vector0) bfloat_ptr = &bfloat_ptr3[1]; /* Simple comparison. */ - vector0 > glob_bfloat_vec; /* { dg-error {operation not permitted on type '__bf16'} } */ - glob_bfloat_vec == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ - vector0 > is_a_float_vec; /* { dg-error {operation not permitted on type '__bf16'} } */ - is_a_float_vec == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ - vector0 > 0; /* { dg-error {operation not permitted on type '__bf16'} } */ - 0 == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ - vector0 > 0.1; /* { dg-error {operation not permitted on type '__bf16'} } */ - 0.1 == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ - vector0 > is_an_int_vec; /* { dg-error {operation not permitted on type '__bf16'} } */ - is_an_int_vec == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ + vector0 > glob_bfloat_vec; + glob_bfloat_vec == vector0; + vector0 > is_a_float_vec; /* { dg-error {comparing vectors with different element types} } */ + is_a_float_vec == vector0; /* { dg-error {comparing vectors with different element types} } */ + vector0 > 0; + 0 == vector0; + vector0 > 0.1; /* { dg-error {conversion of scalar 'double' to vector '__m128bf16'} } */ + 0.1 == vector0; /* { dg-error {conversion of scalar 'double' to vector '__m128bf16'} } */ + vector0 > is_an_int_vec; /* { dg-error {comparing vectors with different element types} } */ + is_an_int_vec == vector0; /* { dg-error {comparing vectors with different element types} } */ /* Pointer comparison. */ @@ -234,24 +234,24 @@ __m128bf16 footest (__m128bf16 vector0) /* Unary operators. */ - +vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ - -vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ - ~vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ - !vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ + +vector0; + -vector0; + ~vector0; /* { dg-error {wrong type argument to bit-complement} } */ + !vector0; /* { dg-error {wrong type argument to unary exclamation mark} } */ *vector0; /* { dg-error {invalid type argument of unary '\*'} } */ - __real vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ - __imag vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ - ++vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ - --vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ - vector0++; /* { dg-error {operation not permitted on type '__bf16'} } */ - vector0--; /* { dg-error {operation not permitted on type '__bf16'} } */ + __real vector0; /* { dg-error {wrong type argument to __real} } */ + __imag vector0; /* { dg-error {wrong type argument to __imag} } */ + ++vector0; + --vector0; + vector0++; + vector0--; /* Binary arithmetic operations. */ - vector0 = glob_bfloat_vec + *bfloat_ptr; /* { dg-error {operation not permitted on type '__bf16'} } */ - vector0 = glob_bfloat_vec + 0.1; /* { dg-error {operation not permitted on type '__bf16'} } */ - vector0 = glob_bfloat_vec + 0; /* { dg-error {operation not permitted on type '__bf16'} } */ - vector0 = glob_bfloat_vec + is_a_float_vec; /* { dg-error {operation not permitted on type '__bf16'} } */ + vector0 = glob_bfloat_vec + *bfloat_ptr; + vector0 = glob_bfloat_vec + 0.1; /* { dg-error {conversion of scalar 'double' to vector '__m128bf16'} } */ + vector0 = glob_bfloat_vec + 0; + vector0 = glob_bfloat_vec + is_a_float_vec; /* { dg-error {invalid operands to binary \+} } */ return vector0; } diff --git a/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_2.c b/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_2.c index f63b41d8..2a8a535 100644 --- a/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_2.c +++ b/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_2.c @@ -45,19 +45,19 @@ __m256bf16 footest (__m256bf16 vector0) __m256bf16 vector2_1 = {}; __m256bf16 vector2_2 = { glob_bfloat }; __m256bf16 vector2_3 = { glob_bfloat, glob_bfloat, glob_bfloat, glob_bfloat }; - __m256bf16 vector2_4 = { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } */ - __m256bf16 vector2_5 = { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} } */ - __m256bf16 vector2_6 = { is_a_float16 }; /* { dg-error {invalid conversion to type '__bf16'} } */ - __m256bf16 vector2_7 = { is_a_float }; /* { dg-error {invalid conversion to type '__bf16'} } */ - __m256bf16 vector2_8 = { is_an_int }; /* { dg-error {invalid conversion to type '__bf16'} } */ - __m256bf16 vector2_9 = { is_a_short_int }; /* { dg-error {invalid conversion to type '__bf16'} } */ - __m256bf16 vector2_10 = { 0.0, 0, is_a_short_int, is_a_float }; /* { dg-error "invalid conversion to type '__bf16'" } */ - - __v8si initi_2_1 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ - __m256 initi_2_2 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ - __m256h initi_2_3 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ - __m256i initi_2_5 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ - __v16hi initi_2_6 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ + __m256bf16 vector2_4 = { 0 }; + __m256bf16 vector2_5 = { 0.1 }; + __m256bf16 vector2_6 = { is_a_float16 }; + __m256bf16 vector2_7 = { is_a_float }; + __m256bf16 vector2_8 = { is_an_int }; + __m256bf16 vector2_9 = { is_a_short_int }; + __m256bf16 vector2_10 = { 0.0, 0, is_a_short_int, is_a_float }; + + __v8si initi_2_1 = { glob_bfloat }; + __m256 initi_2_2 = { glob_bfloat }; + __m256h initi_2_3 = { glob_bfloat }; + __m256i initi_2_5 = { glob_bfloat }; + __v16hi initi_2_6 = { glob_bfloat }; /* Assignments to/from vectors. */ @@ -79,25 +79,25 @@ __m256bf16 footest (__m256bf16 vector0) /* Assignments to/from elements. */ vector2_3[0] = glob_bfloat; - vector2_3[0] = is_an_int; /* { dg-error {invalid conversion to type '__bf16'} } */ - vector2_3[0] = is_a_short_int; /* { dg-error {invalid conversion to type '__bf16'} } */ - vector2_3[0] = is_a_float; /* { dg-error {invalid conversion to type '__bf16'} } */ - vector2_3[0] = is_a_float16; /* { dg-error {invalid conversion to type '__bf16'} } */ - vector2_3[0] = 0; /* { dg-error {invalid conversion to type '__bf16'} } */ - vector2_3[0] = 0.1; /* { dg-error {invalid conversion to type '__bf16'} } */ + vector2_3[0] = is_an_int; + vector2_3[0] = is_a_short_int; + vector2_3[0] = is_a_float; + vector2_3[0] = is_a_float16; + vector2_3[0] = 0; + vector2_3[0] = 0.1; glob_bfloat = vector2_3[0]; - is_an_int = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */ - is_a_short_int = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */ - is_a_float = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */ - is_a_float16 = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */ + is_an_int = vector2_3[0]; + is_a_short_int = vector2_3[0]; + is_a_float = vector2_3[0]; + is_a_float16 = vector2_3[0]; /* Compound literals. */ (__m256bf16) {}; - (__m256bf16) { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } */ - (__m256bf16) { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} } */ + (__m256bf16) { 0 }; + (__m256bf16) { 0.1 }; (__m256bf16) { is_a_float_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type '__m256'} } */ (__m256bf16) { is_an_int_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type '__v8si'} } */ (__m256bf16) { is_a_long_int_pair }; /* { dg-error {incompatible types when initializing type '__bf16' using type '__m256i'} } */ @@ -176,16 +176,16 @@ __m256bf16 footest (__m256bf16 vector0) bfloat_ptr = &bfloat_ptr3[1]; /* Simple comparison. */ - vector0 > glob_bfloat_vec; /* { dg-error {operation not permitted on type '__bf16'} } */ - glob_bfloat_vec == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ - vector0 > is_a_float_vec; /* { dg-error {operation not permitted on type '__bf16'} } */ - is_a_float_vec == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ - vector0 > 0; /* { dg-error {operation not permitted on type '__bf16'} } */ - 0 == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ - vector0 > 0.1; /* { dg-error {operation not permitted on type '__bf16'} } */ - 0.1 == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ - vector0 > is_an_int_vec; /* { dg-error {operation not permitted on type '__bf16'} } */ - is_an_int_vec == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ + vector0 > glob_bfloat_vec; + glob_bfloat_vec == vector0; + vector0 > is_a_float_vec; /* { dg-error {comparing vectors with different element types} } */ + is_a_float_vec == vector0; /* { dg-error {comparing vectors with different element types} } */ + vector0 > 0; + 0 == vector0; + vector0 > 0.1; /* { dg-error {conversion of scalar 'double' to vector '__m256bf16'} } */ + 0.1 == vector0; /* { dg-error {conversion of scalar 'double' to vector '__m256bf16'} } */ + vector0 > is_an_int_vec; /* { dg-error {comparing vectors with different element types} } */ + is_an_int_vec == vector0; /* { dg-error {comparing vectors with different element types} } */ /* Pointer comparison. */ @@ -224,24 +224,24 @@ __m256bf16 footest (__m256bf16 vector0) /* Unary operators. */ - +vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ - -vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ - ~vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ - !vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ + +vector0; + -vector0; + ~vector0; /* { dg-error {wrong type argument to bit-complement} } */ + !vector0; /* { dg-error {wrong type argument to unary exclamation mark} } */ *vector0; /* { dg-error {invalid type argument of unary '\*'} } */ - __real vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ - __imag vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ - ++vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ - --vector0; /* { dg-error {operation not permitted on type '__bf16'} } */ - vector0++; /* { dg-error {operation not permitted on type '__bf16'} } */ - vector0--; /* { dg-error {operation not permitted on type '__bf16'} } */ + __real vector0; /* { dg-error {wrong type argument to __real} } */ + __imag vector0; /* { dg-error {wrong type argument to __imag} } */ + ++vector0; + --vector0; + vector0++; + vector0--; /* Binary arithmetic operations. */ - vector0 = glob_bfloat_vec + *bfloat_ptr; /* { dg-error {operation not permitted on type '__bf16'} } */ - vector0 = glob_bfloat_vec + 0.1; /* { dg-error {operation not permitted on type '__bf16'} } */ - vector0 = glob_bfloat_vec + 0; /* { dg-error {operation not permitted on type '__bf16'} } */ - vector0 = glob_bfloat_vec + is_a_float_vec; /* { dg-error {operation not permitted on type '__bf16'} } */ + vector0 = glob_bfloat_vec + *bfloat_ptr; + vector0 = glob_bfloat_vec + 0.1; /* { dg-error {conversion of scalar 'double' to vector '__m256bf16'} } */ + vector0 = glob_bfloat_vec + 0; + vector0 = glob_bfloat_vec + is_a_float_vec; /* { dg-error {invalid operands to binary \+} } */ return vector0; } diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index fdd88e6..8d45bc2 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -3416,6 +3416,22 @@ proc check_effective_target_base_quadfloat_support { } { return 1 } +# Return 1 if the target supports the __bf16 type, 0 otherwise. + +proc check_effective_target_bfloat16 {} { + return [check_no_compiler_messages_nocache bfloat16 object { + __bf16 foo (__bf16 x) { return x + x; } + } [add_options_for_bfloat16 ""]] +} + +proc check_effective_target_bfloat16_runtime {} { + return [check_effective_target_bfloat16] +} + +proc add_options_for_bfloat16 { flags } { + return "$flags" +} + # Return 1 if the target supports all four forms of fused multiply-add # (fma, fms, fnma, and fnms) for both float and double. -- cgit v1.1 From 4b04292b76e89b332ae70208aabf8f0e12f3a63f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Kvalsvik?= Date: Tue, 4 Oct 2022 15:45:59 +0200 Subject: gcov: test switch/break line counts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The coverage support will under some conditions decide to split edges to accurately report coverage. By running the test suite with/without this edge splitting a small diff shows up, addressed by this patch, which should catch future regressions. Removing the edge splitting: $ diff --git a/gcc/profile.cc b/gcc/profile.cc --- a/gcc/profile.cc +++ b/gcc/profile.cc @@ -1244,19 +1244,7 @@ branch_prob (bool thunk) Don't do that when the locuses match, so if (blah) goto something; is not computed twice. */ - if (last - && gimple_has_location (last) - && !RESERVED_LOCATION_P (e->goto_locus) - && !single_succ_p (bb) - && (LOCATION_FILE (e->goto_locus) - != LOCATION_FILE (gimple_location (last)) - || (LOCATION_LINE (e->goto_locus) - != LOCATION_LINE (gimple_location (last))))) - { - basic_block new_bb = split_edge (e); - edge ne = single_succ_edge (new_bb); - ne->goto_locus = e->goto_locus; - } + if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL)) && e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun)) need_exit_edge = 1; Assuming the .gcov files from make chec-gcc RUNTESTFLAGS=gcov.exp are kept: $ diff -r no-split-edge with-split-edge | grep -C 2 -E "^[<>]\s\s" diff -r sans-split-edge/gcc/gcov-4.c.gcov with-split-edge/gcc/gcov-4.c.gcov 228c228 < -: 224: break; --- > 1: 224: break; 231c231 < -: 227: break; --- > #####: 227: break; 237c237 < -: 233: break; --- > 2: 233: break; gcc/testsuite/ChangeLog: * g++.dg/gcov/gcov-1.C: Add line count check. * gcc.misc-tests/gcov-4.c: Likewise. --- gcc/testsuite/g++.dg/gcov/gcov-1.C | 8 ++++---- gcc/testsuite/gcc.misc-tests/gcov-4.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'gcc/testsuite') diff --git a/gcc/testsuite/g++.dg/gcov/gcov-1.C b/gcc/testsuite/g++.dg/gcov/gcov-1.C index 9018b9a..ee383b4 100644 --- a/gcc/testsuite/g++.dg/gcov/gcov-1.C +++ b/gcc/testsuite/g++.dg/gcov/gcov-1.C @@ -257,20 +257,20 @@ test_switch (int i, int j) switch (i) /* count(5) */ /* branch(end) */ { - case 1: + case 1: /* count(1) */ result = do_something (2); /* count(1) */ - break; + break; /* count(1) */ case 2: result = do_something (1024); break; - case 3: + case 3: /* count(3) */ case 4: /* branch(67) */ if (j == 2) /* count(3) */ /* branch(end) */ return do_something (4); /* count(1) */ result = do_something (8); /* count(2) */ - break; + break; /* count(2) */ default: result = do_something (32); /* count(1) */ switch_m++; /* count(1) */ diff --git a/gcc/testsuite/gcc.misc-tests/gcov-4.c b/gcc/testsuite/gcc.misc-tests/gcov-4.c index 9d8ab1c..498d299 100644 --- a/gcc/testsuite/gcc.misc-tests/gcov-4.c +++ b/gcc/testsuite/gcc.misc-tests/gcov-4.c @@ -221,7 +221,7 @@ test_switch (int i, int j) { case 1: result = do_something (2); /* count(1) */ - break; + break; /* count(1) */ case 2: result = do_something (1024); break; @@ -230,7 +230,7 @@ test_switch (int i, int j) if (j == 2) /* count(3) */ return do_something (4); /* count(1) */ result = do_something (8); /* count(2) */ - break; + break; /* count(2) */ default: result = do_something (32); /* count(1) */ switch_m++; /* count(1) */ -- cgit v1.1 From 98fef35ad1d017bb86f50afe69e25c128a1a1be2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Kvalsvik?= Date: Fri, 7 Oct 2022 13:29:20 +0200 Subject: gcov: test line count for label in then/else block Add a test to catch regression in line counts for labels on top of then/else blocks. Only the 'goto