commit d6cf49eaf5ac237c57785dce42c89deac911affa Author: Andrew Pinski Date: Mon May 20 00:16:40 2024 -0700 match: Disable `(type)zero_one_valuep*CST` for 1bit signed types [PR115154] The problem here is the pattern added in r13-1162-g9991d84d2a8435 assumes that it is well defined to multiply zero_one_valuep by the truncated converted integer constant. It is well defined for all types except for signed 1bit types. Where `a * -1` is produced which is undefined/ So disable this pattern for 1bit signed types. Note the pattern added in r14-3432-gddd64a6ec3b38e is able to workaround the undefinedness except when `-fsanitize=undefined` is turned on, this is why I added a testcase for that. Bootstrapped and tested on x86_64-linux-gnu with no regressions. PR tree-optimization/115154 gcc/ChangeLog: * match.pd (convert (mult zero_one_valued_p@1 INTEGER_CST@2)): Disable for 1bit signed types. gcc/testsuite/ChangeLog: * c-c++-common/ubsan/signed1bitfield-1.c: New test. * gcc.c-torture/execute/signed1bitfield-1.c: New test. Signed-off-by: Andrew Pinski (cherry picked from commit 49c87d22535ac4f8aacf088b3f462861c26cacb4) diff --git a/gcc/match.pd b/gcc/match.pd index dc34e7ead9f..fda4a211efc 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -2023,12 +2023,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (mult (convert @0) @1))) /* Narrow integer multiplication by a zero_one_valued_p operand. - Multiplication by [0,1] is guaranteed not to overflow. */ + Multiplication by [0,1] is guaranteed not to overflow except for + 1bit signed types. */ (simplify (convert (mult@0 zero_one_valued_p@1 INTEGER_CST@2)) (if (INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (TREE_TYPE (@0)) - && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (@0))) + && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (@0)) + && (TYPE_UNSIGNED (type) || TYPE_PRECISION (type) > 1)) (mult (convert @1) (convert @2)))) /* (X << C) != 0 can be simplified to X, when C is zero_one_valued_p. diff --git a/gcc/testsuite/c-c++-common/ubsan/signed1bitfield-1.c b/gcc/testsuite/c-c++-common/ubsan/signed1bitfield-1.c new file mode 100644 index 00000000000..2ba8cf4dab0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/signed1bitfield-1.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -fsanitize=undefined" } */ + +/* PR tree-optimization/115154 */ +/* This was being miscompiled with -fsanitize=undefined due to + `(signed:1)(t*5)` being transformed into `-((signed:1)t)` which + is undefined. */ + +struct s { + signed b : 1; +} f; +int i = 55; +__attribute__((noinline)) +void check(int a) +{ + if (!a) + __builtin_abort(); +} +int main() { + int t = i != 5; + t = t*5; + f.b = t; + int tt = f.b; + check(f.b); +} diff --git a/gcc/testsuite/gcc.c-torture/execute/signed1bitfield-1.c b/gcc/testsuite/gcc.c-torture/execute/signed1bitfield-1.c new file mode 100644 index 00000000000..ab888ca3a04 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/signed1bitfield-1.c @@ -0,0 +1,23 @@ +/* PR tree-optimization/115154 */ +/* This was being miscompiled to `(signed:1)(t*5)` + being transformed into `-((signed:1)t)` which is undefined. + Note there is a pattern which removes the negative in some cases + which works around the issue. */ + +struct { + signed b : 1; +} f; +int i = 55; +__attribute__((noinline)) +void check(int a) +{ + if (!a) + __builtin_abort(); +} +int main() { + int t = i != 5; + t = t*5; + f.b = t; + int tt = f.b; + check(f.b); +} commit 3f6a42510a1bd4b004ed70ac44cdad2770b732a8 Author: Andrew Pinski Date: Sat May 18 11:55:58 2024 -0700 PHIOPT: Don't transform minmax if middle bb contains a phi [PR115143] The problem here is even if last_and_only_stmt returns a statement, the bb might still contain a phi node which defines a ssa name which is used in that statement so we need to add a check to make sure that the phi nodes are empty for the middle bbs in both the `CMP?MINMAX:MINMAX` case and the `CMP?MINMAX:B` cases. Bootstrapped and tested on x86_64_linux-gnu with no regressions. PR tree-optimization/115143 gcc/ChangeLog: * tree-ssa-phiopt.cc (minmax_replacement): Check for empty phi nodes for middle bbs for the case where middle bb is not empty. gcc/testsuite/ChangeLog: * gcc.c-torture/compile/pr115143-1.c: New test. * gcc.c-torture/compile/pr115143-2.c: New test. * gcc.c-torture/compile/pr115143-3.c: New test. Signed-off-by: Andrew Pinski (cherry picked from commit 9ff8f041331ef8b56007fb3c4d41d76f9850010d) diff --git a/gcc/testsuite/gcc.c-torture/compile/pr115143-1.c b/gcc/testsuite/gcc.c-torture/compile/pr115143-1.c new file mode 100644 index 00000000000..5cb119ea432 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr115143-1.c @@ -0,0 +1,21 @@ +/* PR tree-optimization/115143 */ +/* This used to ICE. + minmax part of phiopt would transform, + would transform `a!=0?min(a, b) : 0` into `min(a,b)` + which was correct except b was defined by a phi in the inner + bb which was not handled. */ +short a, d; +char b; +long c; +unsigned long e, f; +void g(unsigned long h) { + if (c ? e : b) + if (e) + if (d) { + a = f ? ({ + unsigned long i = d ? f : 0, j = e ? h : 0; + i < j ? i : j; + }) : 0; + } +} + diff --git a/gcc/testsuite/gcc.c-torture/compile/pr115143-2.c b/gcc/testsuite/gcc.c-torture/compile/pr115143-2.c new file mode 100644 index 00000000000..05c3bbe9738 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr115143-2.c @@ -0,0 +1,30 @@ +/* { dg-options "-fgimple" } */ +/* PR tree-optimization/115143 */ +/* This used to ICE. + minmax part of phiopt would transform, + would transform `a!=0?min(a, b) : 0` into `min(a,b)` + which was correct except b was defined by a phi in the inner + bb which was not handled. */ +unsigned __GIMPLE (ssa,startwith("phiopt")) +foo (unsigned a, unsigned b) +{ + unsigned j; + unsigned _23; + unsigned _12; + + __BB(2): + if (a_6(D) != 0u) + goto __BB3; + else + goto __BB4; + + __BB(3): + j_10 = __PHI (__BB2: b_11(D)); + _23 = __MIN (a_6(D), j_10); + goto __BB4; + + __BB(4): + _12 = __PHI (__BB3: _23, __BB2: 0u); + return _12; + +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr115143-3.c b/gcc/testsuite/gcc.c-torture/compile/pr115143-3.c new file mode 100644 index 00000000000..53c5fb5588e --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr115143-3.c @@ -0,0 +1,29 @@ +/* { dg-options "-fgimple" } */ +/* PR tree-optimization/115143 */ +/* This used to ICE. + minmax part of phiopt would transform, + would transform `a!=0?min(a, b) : 0` into `min(a,b)` + which was correct except b was defined by a phi in the inner + bb which was not handled. */ +unsigned __GIMPLE (ssa,startwith("phiopt")) +foo (unsigned a, unsigned b) +{ + unsigned j; + unsigned _23; + unsigned _12; + + __BB(2): + if (a_6(D) > 0u) + goto __BB3; + else + goto __BB4; + + __BB(3): + j_10 = __PHI (__BB2: b_7(D)); + _23 = __MIN (a_6(D), j_10); + goto __BB4; + + __BB(4): + _12 = __PHI (__BB3: _23, __BB2: 0u); + return _12; +} diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc index c3d78d1400b..d507530307a 100644 --- a/gcc/tree-ssa-phiopt.cc +++ b/gcc/tree-ssa-phiopt.cc @@ -2106,6 +2106,10 @@ minmax_replacement (basic_block cond_bb, basic_block middle_bb, basic_block alt_ || gimple_code (assign) != GIMPLE_ASSIGN) return false; + /* There cannot be any phi nodes in the middle bb. */ + if (!gimple_seq_empty_p (phi_nodes (middle_bb))) + return false; + lhs = gimple_assign_lhs (assign); ass_code = gimple_assign_rhs_code (assign); if (ass_code != MAX_EXPR && ass_code != MIN_EXPR) @@ -2119,6 +2123,10 @@ minmax_replacement (basic_block cond_bb, basic_block middle_bb, basic_block alt_ || gimple_code (assign) != GIMPLE_ASSIGN) return false; + /* There cannot be any phi nodes in the alt middle bb. */ + if (!gimple_seq_empty_p (phi_nodes (alt_middle_bb))) + return false; + alt_lhs = gimple_assign_lhs (assign); if (ass_code != gimple_assign_rhs_code (assign)) return false; @@ -2229,6 +2237,10 @@ minmax_replacement (basic_block cond_bb, basic_block middle_bb, basic_block alt_ || gimple_code (assign) != GIMPLE_ASSIGN) return false; + /* There cannot be any phi nodes in the middle bb. */ + if (!gimple_seq_empty_p (phi_nodes (middle_bb))) + return false; + lhs = gimple_assign_lhs (assign); ass_code = gimple_assign_rhs_code (assign); if (ass_code != MAX_EXPR && ass_code != MIN_EXPR) commit c827f46d8652d7a089e614302a4cffb6b192284d Author: Kewen Lin Date: Wed Apr 10 02:59:43 2024 -0500 testsuite: Adjust pr113359-2_*.c with unsigned long long [PR114662] pr113359-2_*.c define a struct having unsigned long type members ay and az which have 4 bytes size at -m32, while the related constants CL1 and CL2 used for equality check are always 8 bytes, it makes compiler consider the below 69 if (a.ay != CL1) 70 __builtin_abort (); always to abort and optimize away the following call to getb, which leads to the expected wpa dumping on "Semantic equality" missing. This patch is to modify the types with unsigned long long accordingly. PR testsuite/114662 gcc/testsuite/ChangeLog: * gcc.dg/lto/pr113359-2_0.c: Use unsigned long long instead of unsigned long. * gcc.dg/lto/pr113359-2_1.c: Likewise. (cherry picked from commit 4923ed49b93352bcf9e43cafac38345e4a54c3f8) diff --git a/gcc/testsuite/gcc.dg/lto/pr113359-2_0.c b/gcc/testsuite/gcc.dg/lto/pr113359-2_0.c index 8b2d5bdfab2..8495667599d 100644 --- a/gcc/testsuite/gcc.dg/lto/pr113359-2_0.c +++ b/gcc/testsuite/gcc.dg/lto/pr113359-2_0.c @@ -8,15 +8,15 @@ struct SA { unsigned int ax; - unsigned long ay; - unsigned long az; + unsigned long long ay; + unsigned long long az; }; struct SB { unsigned int bx; - unsigned long by; - unsigned long bz; + unsigned long long by; + unsigned long long bz; }; struct ZA diff --git a/gcc/testsuite/gcc.dg/lto/pr113359-2_1.c b/gcc/testsuite/gcc.dg/lto/pr113359-2_1.c index 61bc0547981..8320f347efe 100644 --- a/gcc/testsuite/gcc.dg/lto/pr113359-2_1.c +++ b/gcc/testsuite/gcc.dg/lto/pr113359-2_1.c @@ -5,15 +5,15 @@ struct SA { unsigned int ax; - unsigned long ay; - unsigned long az; + unsigned long long ay; + unsigned long long az; }; struct SB { unsigned int bx; - unsigned long by; - unsigned long bz; + unsigned long long by; + unsigned long long bz; }; struct ZA commit 5ed32d00a7b408baa48d85e841740e73c8504d7a Author: Harald Anlauf Date: Fri May 10 21:18:03 2024 +0200 Fortran: fix dependency checks for inquiry refs [PR115039] gcc/fortran/ChangeLog: PR fortran/115039 * expr.cc (gfc_traverse_expr): An inquiry ref does not constitute a dependency and cannot collide with a symbol. gcc/testsuite/ChangeLog: PR fortran/115039 * gfortran.dg/statement_function_5.f90: New test. (cherry picked from commit d4974fd22730014e337fd7ec2471945ba8afb00e) diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc index a6c4dccb125..4a9b29c7e9d 100644 --- a/gcc/fortran/expr.cc +++ b/gcc/fortran/expr.cc @@ -5483,7 +5483,7 @@ gfc_traverse_expr (gfc_expr *expr, gfc_symbol *sym, break; case REF_INQUIRY: - return true; + return false; default: gcc_unreachable (); diff --git a/gcc/testsuite/gfortran.dg/statement_function_5.f90 b/gcc/testsuite/gfortran.dg/statement_function_5.f90 new file mode 100644 index 00000000000..bc5a5dba7a0 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/statement_function_5.f90 @@ -0,0 +1,20 @@ +! { dg-do compile } +! PR fortran/115039 +! +! Check that inquiry refs work with statement functions +! +! { dg-additional-options "-std=legacy -fdump-tree-optimized" } +! { dg-prune-output " Obsolescent feature" } +! { dg-final { scan-tree-dump-not "_gfortran_stop_numeric" "optimized" } } + +program testit + implicit none + complex :: x + real :: im + integer :: slen + character(5) :: s + im(x) = x%im + x%re + x%kind + slen(s) = s%len + if (im((1.0,3.0) + (2.0,4.0)) /= 14.) stop 1 + if (slen('abcdef') /= 5) stop 2 +end program testit commit 0a9df2c711f40e067cd57707d8e623136ae4efbe Author: Jonathan Wakely Date: Tue May 21 13:16:33 2024 +0100 c++: Fix std dialect hint for std::to_address [PR107800] The correct dialect for std::to_address is cxx20 not cxx11. gcc/cp/ChangeLog: PR libstdc++/107800 * cxxapi-data.csv : Change dialect to cxx20. * std-name-hint.gperf: Regenerate. * std-name-hint.h: Regenerate. (cherry picked from commit 826a7d3d19d3ebf04e21d6f1c89eb341a36fb5d1) diff --git a/gcc/cp/cxxapi-data.csv b/gcc/cp/cxxapi-data.csv index eb6dbcd6057..aecad73a7e8 100644 --- a/gcc/cp/cxxapi-data.csv +++ b/gcc/cp/cxxapi-data.csv @@ -460,7 +460,7 @@ # unimplemented ,default_accessor,1,no # unimplemented ,mdspan,1,cxx23 ,pointer_traits,1,cxx11 -,to_address,1,cxx11 +,to_address,1,cxx20 ,align,1,cxx11 ,assume_aligned,1,cxx20 ,allocator_arg_t,1,cxx11 diff --git a/gcc/cp/std-name-hint.gperf b/gcc/cp/std-name-hint.gperf index 758e74f77d6..a46c7f3e68f 100644 --- a/gcc/cp/std-name-hint.gperf +++ b/gcc/cp/std-name-hint.gperf @@ -220,7 +220,7 @@ pointer_traits, "", cxx11 reinterpret_pointer_cast, "", cxx17 shared_ptr, "", cxx11 static_pointer_cast, "", cxx11 -to_address, "", cxx11 +to_address, "", cxx20 uninitialized_construct_using_allocator, "", cxx20 unique_ptr, "", cxx11 uses_allocator, "", cxx11 diff --git a/gcc/cp/std-name-hint.h b/gcc/cp/std-name-hint.h index 5848fca6f0e..8503d195145 100644 --- a/gcc/cp/std-name-hint.h +++ b/gcc/cp/std-name-hint.h @@ -291,7 +291,7 @@ std_name_hint_lookup::find (const char *str, size_t len) #line 472 "std-name-hint.gperf" {"variant_npos", "", cxx17}, #line 223 "std-name-hint.gperf" - {"to_address", "", cxx11}, + {"to_address", "", cxx20}, #line 460 "std-name-hint.gperf" {"pair", "", cxx98}, #line 269 "std-name-hint.gperf" commit bd5e672303f5f777e8927a746d3ee42db21d871b Author: Dimitrij Mijoski Date: Thu Sep 28 21:38:11 2023 +0200 libstdc++: Fix handling of surrogate CP in codecvt [PR108976] This patch fixes the handling of surrogate code points in all standard facets for transcoding Unicode that are based on std::codecvt. Surrogate code points should always be treated as error. On the other hand surrogate code units can only appear in UTF-16 and only when they come in a proper pair. Additionally, it fixes a bug in std::codecvt_utf16::in() when odd number of bytes were given in the range [from, from_end), error was returned always. The last byte in such range does not form a full UTF-16 code unit and we can not make any decisions for error, instead partial should be returned. The testsuite for testing these facets was updated in the following order: 1. All functions that test codecvts that work with UTF-8 were refactored and made more generic so they accept codecvt that works with the char type char8_t. 2. The same functions were updated with new test cases for transcoding errors and now additionally test for surrogates, overlong UTF-8 sequences, code points out of the Unicode range, and more tests for missing leading and trailing code units. 3. New tests were added to test codecvt_utf16 in both of its variants, UTF-16 <-> UTF-32/UCS-4 and UTF-16 <-> UCS-2. libstdc++-v3/ChangeLog: PR libstdc++/108976 * src/c++11/codecvt.cc (read_utf8_code_point): Fix handing of surrogates in UTF-8. (ucs4_out): Fix handling of surrogates in UCS-4 -> UTF-8. (ucs4_in): Fix handling of range with odd number of bytes. (ucs4_out): Fix handling of surrogates in UCS-4 -> UTF-16. (ucs2_out): Fix handling of surrogates in UCS-2 -> UTF-16. (ucs2_in): Fix handling of range with odd number of bytes. (__codecvt_utf16_base::do_in): Likewise. (__codecvt_utf16_base::do_in): Likewise. (__codecvt_utf16_base::do_in): Likewise. * testsuite/22_locale/codecvt/codecvt_unicode.cc: Renames, add tests for codecvt_utf16 and codecvt_utf16. * testsuite/22_locale/codecvt/codecvt_unicode.h: Refactor UTF-8 testing functions for char8_t, add more test cases for errors, add testing functions for codecvt_utf16. * testsuite/22_locale/codecvt/codecvt_unicode_wchar_t.cc: Renames, add tests for codecvt_utf16. * testsuite/22_locale/codecvt/codecvt_utf16/79980.cc (test06): Fix test. * testsuite/22_locale/codecvt/codecvt_unicode_char8_t.cc: New test. (cherry picked from commit a8b9c32da787ea0bfbfc9118ac816fa7be4b1bc8) diff --git a/libstdc++-v3/src/c++11/codecvt.cc b/libstdc++-v3/src/c++11/codecvt.cc index 02f05752de8..2cc812cfc34 100644 --- a/libstdc++-v3/src/c++11/codecvt.cc +++ b/libstdc++-v3/src/c++11/codecvt.cc @@ -284,6 +284,8 @@ namespace return invalid_mb_sequence; if (c1 == 0xE0 && c2 < 0xA0) [[unlikely]] // overlong return invalid_mb_sequence; + if (c1 == 0xED && c2 >= 0xA0) [[unlikely]] // surrogate + return invalid_mb_sequence; if (avail < 3) [[unlikely]] return incomplete_mb_character; char32_t c3 = (unsigned char) from[2]; @@ -484,6 +486,8 @@ namespace while (from.size()) { const char32_t c = from[0]; + if (0xD800 <= c && c <= 0xDFFF) [[unlikely]] + return codecvt_base::error; if (c > maxcode) [[unlikely]] return codecvt_base::error; if (!write_utf8_code_point(to, c)) [[unlikely]] @@ -508,7 +512,7 @@ namespace return codecvt_base::error; to = codepoint; } - return from.size() ? codecvt_base::partial : codecvt_base::ok; + return from.nbytes() ? codecvt_base::partial : codecvt_base::ok; } // ucs4 -> utf16 @@ -521,6 +525,8 @@ namespace while (from.size()) { const char32_t c = from[0]; + if (0xD800 <= c && c <= 0xDFFF) [[unlikely]] + return codecvt_base::error; if (c > maxcode) [[unlikely]] return codecvt_base::error; if (!write_utf16_code_point(to, c, mode)) [[unlikely]] @@ -653,7 +659,7 @@ namespace while (from.size() && to.size()) { char16_t c = from[0]; - if (is_high_surrogate(c)) + if (0xD800 <= c && c <= 0xDFFF) return codecvt_base::error; if (c > maxcode) return codecvt_base::error; @@ -680,7 +686,7 @@ namespace return codecvt_base::error; to = c; } - return from.size() == 0 ? codecvt_base::ok : codecvt_base::partial; + return from.nbytes() == 0 ? codecvt_base::ok : codecvt_base::partial; } const char16_t* @@ -1344,8 +1350,6 @@ do_in(state_type&, const extern_type* __from, const extern_type* __from_end, auto res = ucs2_in(from, to, _M_maxcode, _M_mode); __from_next = reinterpret_cast(from.next); __to_next = to.next; - if (res == codecvt_base::ok && __from_next != __from_end) - res = codecvt_base::error; return res; } @@ -1419,8 +1423,6 @@ do_in(state_type&, const extern_type* __from, const extern_type* __from_end, auto res = ucs4_in(from, to, _M_maxcode, _M_mode); __from_next = reinterpret_cast(from.next); __to_next = to.next; - if (res == codecvt_base::ok && __from_next != __from_end) - res = codecvt_base::error; return res; } @@ -1521,8 +1523,6 @@ do_in(state_type&, const extern_type* __from, const extern_type* __from_end, #endif __from_next = reinterpret_cast(from.next); __to_next = reinterpret_cast(to.next); - if (res == codecvt_base::ok && __from_next != __from_end) - res = codecvt_base::error; return res; } diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.cc b/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.cc index df1a2b4cc51..c563781ca72 100644 --- a/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.cc +++ b/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.cc @@ -27,38 +27,58 @@ void test_utf8_utf32_codecvts () { using codecvt_c32 = codecvt; - auto loc_c = locale::classic (); + auto &loc_c = locale::classic (); VERIFY (has_facet (loc_c)); auto &cvt = use_facet (loc_c); - test_utf8_utf32_codecvts (cvt); + test_utf8_utf32_cvt (cvt); codecvt_utf8 cvt2; - test_utf8_utf32_codecvts (cvt2); + test_utf8_utf32_cvt (cvt2); } void test_utf8_utf16_codecvts () { using codecvt_c16 = codecvt; - auto loc_c = locale::classic (); + auto &loc_c = locale::classic (); VERIFY (has_facet (loc_c)); auto &cvt = use_facet (loc_c); - test_utf8_utf16_cvts (cvt); + test_utf8_utf16_cvt (cvt); codecvt_utf8_utf16 cvt2; - test_utf8_utf16_cvts (cvt2); + test_utf8_utf16_cvt (cvt2); codecvt_utf8_utf16 cvt3; - test_utf8_utf16_cvts (cvt3); + test_utf8_utf16_cvt (cvt3); } void test_utf8_ucs2_codecvts () { codecvt_utf8 cvt; - test_utf8_ucs2_cvts (cvt); + test_utf8_ucs2_cvt (cvt); +} + +void +test_utf16_utf32_codecvts () +{ + codecvt_utf16 cvt; + test_utf16_utf32_cvt (cvt, utf16_big_endian); + + codecvt_utf16 cvt2; + test_utf16_utf32_cvt (cvt2, utf16_little_endian); +} + +void +test_utf16_ucs2_codecvts () +{ + codecvt_utf16 cvt; + test_utf16_ucs2_cvt (cvt, utf16_big_endian); + + codecvt_utf16 cvt2; + test_utf16_ucs2_cvt (cvt2, utf16_little_endian); } int @@ -67,4 +87,6 @@ main () test_utf8_utf32_codecvts (); test_utf8_utf16_codecvts (); test_utf8_ucs2_codecvts (); + test_utf16_utf32_codecvts (); + test_utf16_ucs2_codecvts (); } diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.h b/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.h index fbdc7a35b28..d3ae42fac13 100644 --- a/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.h +++ b/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.h @@ -42,33 +42,33 @@ auto constexpr array_size (const T (&)[N]) -> size_t return N; } -template +template void -utf8_to_utf32_in_ok (const std::codecvt &cvt) +utf8_to_utf32_in_ok (const std::codecvt &cvt) { using namespace std; // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP - const char in[] = "bш\uAAAA\U0010AAAA"; - const char32_t exp_literal[] = U"bш\uAAAA\U0010AAAA"; - CharT exp[array_size (exp_literal)] = {}; - std::copy (begin (exp_literal), end (exp_literal), begin (exp)); - - static_assert (array_size (in) == 11, ""); - static_assert (array_size (exp_literal) == 5, ""); - static_assert (array_size (exp) == 5, ""); - VERIFY (char_traits::length (in) == 10); - VERIFY (char_traits::length (exp_literal) == 4); - VERIFY (char_traits::length (exp) == 4); + const unsigned char input[] = "b\u0448\uAAAA\U0010AAAA"; + const char32_t expected[] = U"b\u0448\uAAAA\U0010AAAA"; + static_assert (array_size (input) == 11, ""); + static_assert (array_size (expected) == 5, ""); + + ExternT in[array_size (input)]; + InternT exp[array_size (expected)]; + copy (begin (input), end (input), begin (in)); + copy (begin (expected), end (expected), begin (exp)); + VERIFY (char_traits::length (in) == 10); + VERIFY (char_traits::length (exp) == 4); test_offsets_ok offsets[] = {{0, 0}, {1, 1}, {3, 2}, {6, 3}, {10, 4}}; for (auto t : offsets) { - CharT out[array_size (exp) - 1] = {}; + InternT out[array_size (exp) - 1] = {}; VERIFY (t.in_size <= array_size (in)); VERIFY (t.out_size <= array_size (out)); auto state = mbstate_t{}; - auto in_next = (const char *) nullptr; - auto out_next = (CharT *) nullptr; + auto in_next = (const ExternT *) nullptr; + auto out_next = (InternT *) nullptr; auto res = codecvt_base::result (); res = cvt.in (state, in, in + t.in_size, in_next, out, out + t.out_size, @@ -76,19 +76,19 @@ utf8_to_utf32_in_ok (const std::codecvt &cvt) VERIFY (res == cvt.ok); VERIFY (in_next == in + t.in_size); VERIFY (out_next == out + t.out_size); - VERIFY (char_traits::compare (out, exp, t.out_size) == 0); + VERIFY (char_traits::compare (out, exp, t.out_size) == 0); if (t.out_size < array_size (out)) VERIFY (out[t.out_size] == 0); } for (auto t : offsets) { - CharT out[array_size (exp)] = {}; + InternT out[array_size (exp)] = {}; VERIFY (t.in_size <= array_size (in)); VERIFY (t.out_size <= array_size (out)); auto state = mbstate_t{}; - auto in_next = (const char *) nullptr; - auto out_next = (CharT *) nullptr; + auto in_next = (const ExternT *) nullptr; + auto out_next = (InternT *) nullptr; auto res = codecvt_base::result (); res @@ -96,29 +96,29 @@ utf8_to_utf32_in_ok (const std::codecvt &cvt) VERIFY (res == cvt.ok); VERIFY (in_next == in + t.in_size); VERIFY (out_next == out + t.out_size); - VERIFY (char_traits::compare (out, exp, t.out_size) == 0); + VERIFY (char_traits::compare (out, exp, t.out_size) == 0); if (t.out_size < array_size (out)) VERIFY (out[t.out_size] == 0); } } -template +template void -utf8_to_utf32_in_partial (const std::codecvt &cvt) +utf8_to_utf32_in_partial (const std::codecvt &cvt) { using namespace std; // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP - const char in[] = "bш\uAAAA\U0010AAAA"; - const char32_t exp_literal[] = U"bш\uAAAA\U0010AAAA"; - CharT exp[array_size (exp_literal)] = {}; - std::copy (begin (exp_literal), end (exp_literal), begin (exp)); - - static_assert (array_size (in) == 11, ""); - static_assert (array_size (exp_literal) == 5, ""); - static_assert (array_size (exp) == 5, ""); - VERIFY (char_traits::length (in) == 10); - VERIFY (char_traits::length (exp_literal) == 4); - VERIFY (char_traits::length (exp) == 4); + const unsigned char input[] = "b\u0448\uAAAA\U0010AAAA"; + const char32_t expected[] = U"b\u0448\uAAAA\U0010AAAA"; + static_assert (array_size (input) == 11, ""); + static_assert (array_size (expected) == 5, ""); + + ExternT in[array_size (input)]; + InternT exp[array_size (expected)]; + copy (begin (input), end (input), begin (in)); + copy (begin (expected), end (expected), begin (exp)); + VERIFY (char_traits::length (in) == 10); + VERIFY (char_traits::length (exp) == 4); test_offsets_partial offsets[] = { {1, 0, 0, 0}, // no space for first CP @@ -144,14 +144,14 @@ utf8_to_utf32_in_partial (const std::codecvt &cvt) for (auto t : offsets) { - CharT out[array_size (exp) - 1] = {}; + InternT out[array_size (exp) - 1] = {}; VERIFY (t.in_size <= array_size (in)); VERIFY (t.out_size <= array_size (out)); VERIFY (t.expected_in_next <= t.in_size); VERIFY (t.expected_out_next <= t.out_size); auto state = mbstate_t{}; - auto in_next = (const char *) nullptr; - auto out_next = (CharT *) nullptr; + auto in_next = (const ExternT *) nullptr; + auto out_next = (InternT *) nullptr; auto res = codecvt_base::result (); res = cvt.in (state, in, in + t.in_size, in_next, out, out + t.out_size, @@ -159,37 +159,58 @@ utf8_to_utf32_in_partial (const std::codecvt &cvt) VERIFY (res == cvt.partial); VERIFY (in_next == in + t.expected_in_next); VERIFY (out_next == out + t.expected_out_next); - VERIFY (char_traits::compare (out, exp, t.expected_out_next) == 0); + VERIFY (char_traits::compare (out, exp, t.expected_out_next) + == 0); if (t.expected_out_next < array_size (out)) VERIFY (out[t.expected_out_next] == 0); } } -template +template void -utf8_to_utf32_in_error (const std::codecvt &cvt) +utf8_to_utf32_in_error (const std::codecvt &cvt) { using namespace std; - // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP - const char valid_in[] = "bш\uAAAA\U0010AAAA"; - const char32_t exp_literal[] = U"bш\uAAAA\U0010AAAA"; - CharT exp[array_size (exp_literal)] = {}; - std::copy (begin (exp_literal), end (exp_literal), begin (exp)); + // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP, 4-byte CP + const unsigned char input[] = "b\u0448\uD700\U0010AAAA"; + const char32_t expected[] = U"b\u0448\uD700\U0010AAAA"; + static_assert (array_size (input) == 11, ""); + static_assert (array_size (expected) == 5, ""); + + ExternT in[array_size (input)]; + InternT exp[array_size (expected)]; + copy (begin (input), end (input), begin (in)); + copy (begin (expected), end (expected), begin (exp)); + VERIFY (char_traits::length (in) == 10); + VERIFY (char_traits::length (exp) == 4); + + // There are 5 classes of errors in UTF-8 decoding + // 1. Missing leading byte + // 2. Missing trailing byte + // 3. Surrogate CP + // 4. Overlong sequence + // 5. CP out of Unicode range + test_offsets_error offsets[] = { + + // 1. Missing leading byte. We will replace the leading byte with + // non-leading byte, such as a byte that is always invalid or a trailing + // byte. - static_assert (array_size (valid_in) == 11, ""); - static_assert (array_size (exp_literal) == 5, ""); - static_assert (array_size (exp) == 5, ""); - VERIFY (char_traits::length (valid_in) == 10); - VERIFY (char_traits::length (exp_literal) == 4); - VERIFY (char_traits::length (exp) == 4); + // replace leading byte with invalid byte + {1, 4, 0, 0, 0xFF, 0}, + {3, 4, 1, 1, 0xFF, 1}, + {6, 4, 3, 2, 0xFF, 3}, + {10, 4, 6, 3, 0xFF, 6}, - test_offsets_error offsets[] = { + // replace leading byte with trailing byte + {1, 4, 0, 0, 0b10101010, 0}, + {3, 4, 1, 1, 0b10101010, 1}, + {6, 4, 3, 2, 0b10101010, 3}, + {10, 4, 6, 3, 0b10101010, 6}, - // replace leading byte with invalid byte - {1, 4, 0, 0, '\xFF', 0}, - {3, 4, 1, 1, '\xFF', 1}, - {6, 4, 3, 2, '\xFF', 3}, - {10, 4, 6, 3, '\xFF', 6}, + // 2. Missing trailing byte. We will replace the trailing byte with + // non-trailing byte, such as a byte that is always invalid or a leading + // byte (simple ASCII byte in our case). // replace first trailing byte with ASCII byte {3, 4, 1, 1, 'z', 2}, @@ -197,21 +218,27 @@ utf8_to_utf32_in_error (const std::codecvt &cvt) {10, 4, 6, 3, 'z', 7}, // replace first trailing byte with invalid byte - {3, 4, 1, 1, '\xFF', 2}, - {6, 4, 3, 2, '\xFF', 4}, - {10, 4, 6, 3, '\xFF', 7}, + {3, 4, 1, 1, 0xFF, 2}, + {6, 4, 3, 2, 0xFF, 4}, + {10, 4, 6, 3, 0xFF, 7}, // replace second trailing byte with ASCII byte {6, 4, 3, 2, 'z', 5}, {10, 4, 6, 3, 'z', 8}, // replace second trailing byte with invalid byte - {6, 4, 3, 2, '\xFF', 5}, - {10, 4, 6, 3, '\xFF', 8}, + {6, 4, 3, 2, 0xFF, 5}, + {10, 4, 6, 3, 0xFF, 8}, // replace third trailing byte {10, 4, 6, 3, 'z', 9}, - {10, 4, 6, 3, '\xFF', 9}, + {10, 4, 6, 3, 0xFF, 9}, + + // 2.1 The following test-cases raise doubt whether error or partial should + // be returned. For example, we have 4-byte sequence with valid leading + // byte. If we hide the last byte we need to return partial. But, if the + // second or third byte, which are visible to the call to codecvt, are + // malformed then error should be returned. // replace first trailing byte with ASCII byte, also incomplete at end {5, 4, 3, 2, 'z', 4}, @@ -219,30 +246,51 @@ utf8_to_utf32_in_error (const std::codecvt &cvt) {9, 4, 6, 3, 'z', 7}, // replace first trailing byte with invalid byte, also incomplete at end - {5, 4, 3, 2, '\xFF', 4}, - {8, 4, 6, 3, '\xFF', 7}, - {9, 4, 6, 3, '\xFF', 7}, + {5, 4, 3, 2, 0xFF, 4}, + {8, 4, 6, 3, 0xFF, 7}, + {9, 4, 6, 3, 0xFF, 7}, // replace second trailing byte with ASCII byte, also incomplete at end {9, 4, 6, 3, 'z', 8}, // replace second trailing byte with invalid byte, also incomplete at end - {9, 4, 6, 3, '\xFF', 8}, + {9, 4, 6, 3, 0xFF, 8}, + + // 3. Surrogate CP. We modify the second byte (first trailing) of the 3-byte + // CP U+D700 + {6, 4, 3, 2, 0b10100000, 4}, // turn U+D700 into U+D800 + {6, 4, 3, 2, 0b10101100, 4}, // turn U+D700 into U+DB00 + {6, 4, 3, 2, 0b10110000, 4}, // turn U+D700 into U+DC00 + {6, 4, 3, 2, 0b10111100, 4}, // turn U+D700 into U+DF00 + + // 4. Overlong sequence. The CPs in the input are chosen such as modifying + // just the leading byte is enough to make them overlong, i.e. for the + // 3-byte and 4-byte CP the second byte (first trailing) has enough leading + // zeroes. + {3, 4, 1, 1, 0b11000000, 1}, // make the 2-byte CP overlong + {3, 4, 1, 1, 0b11000001, 1}, // make the 2-byte CP overlong + {6, 4, 3, 2, 0b11100000, 3}, // make the 3-byte CP overlong + {10, 4, 6, 3, 0b11110000, 6}, // make the 4-byte CP overlong + + // 5. CP above range + // turn U+10AAAA into U+14AAAA by changing its leading byte + {10, 4, 6, 3, 0b11110101, 6}, + // turn U+10AAAA into U+11AAAA by changing its 2nd byte + {10, 4, 6, 3, 0b10011010, 7}, }; for (auto t : offsets) { - char in[array_size (valid_in)] = {}; - CharT out[array_size (exp) - 1] = {}; + InternT out[array_size (exp) - 1] = {}; VERIFY (t.in_size <= array_size (in)); VERIFY (t.out_size <= array_size (out)); VERIFY (t.expected_in_next <= t.in_size); VERIFY (t.expected_out_next <= t.out_size); - char_traits::copy (in, valid_in, array_size (valid_in)); + auto old_char = in[t.replace_pos]; in[t.replace_pos] = t.replace_char; auto state = mbstate_t{}; - auto in_next = (const char *) nullptr; - auto out_next = (CharT *) nullptr; + auto in_next = (const ExternT *) nullptr; + auto out_next = (InternT *) nullptr; auto res = codecvt_base::result (); res = cvt.in (state, in, in + t.in_size, in_next, out, out + t.out_size, @@ -250,48 +298,51 @@ utf8_to_utf32_in_error (const std::codecvt &cvt) VERIFY (res == cvt.error); VERIFY (in_next == in + t.expected_in_next); VERIFY (out_next == out + t.expected_out_next); - VERIFY (char_traits::compare (out, exp, t.expected_out_next) == 0); + VERIFY (char_traits::compare (out, exp, t.expected_out_next) + == 0); if (t.expected_out_next < array_size (out)) VERIFY (out[t.expected_out_next] == 0); + + in[t.replace_pos] = old_char; } } -template +template void -utf8_to_utf32_in (const std::codecvt &cvt) +utf8_to_utf32_in (const std::codecvt &cvt) { utf8_to_utf32_in_ok (cvt); utf8_to_utf32_in_partial (cvt); utf8_to_utf32_in_error (cvt); } -template +template void -utf32_to_utf8_out_ok (const std::codecvt &cvt) +utf32_to_utf8_out_ok (const std::codecvt &cvt) { using namespace std; // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP - const char32_t in_literal[] = U"bш\uAAAA\U0010AAAA"; - const char exp[] = "bш\uAAAA\U0010AAAA"; - CharT in[array_size (in_literal)] = {}; - copy (begin (in_literal), end (in_literal), begin (in)); - - static_assert (array_size (in_literal) == 5, ""); - static_assert (array_size (in) == 5, ""); - static_assert (array_size (exp) == 11, ""); - VERIFY (char_traits::length (in_literal) == 4); - VERIFY (char_traits::length (in) == 4); - VERIFY (char_traits::length (exp) == 10); + const char32_t input[] = U"b\u0448\uAAAA\U0010AAAA"; + const unsigned char expected[] = "b\u0448\uAAAA\U0010AAAA"; + static_assert (array_size (input) == 5, ""); + static_assert (array_size (expected) == 11, ""); + + InternT in[array_size (input)]; + ExternT exp[array_size (expected)]; + copy (begin (input), end (input), begin (in)); + copy (begin (expected), end (expected), begin (exp)); + VERIFY (char_traits::length (in) == 4); + VERIFY (char_traits::length (exp) == 10); const test_offsets_ok offsets[] = {{0, 0}, {1, 1}, {2, 3}, {3, 6}, {4, 10}}; for (auto t : offsets) { - char out[array_size (exp) - 1] = {}; + ExternT out[array_size (exp) - 1] = {}; VERIFY (t.in_size <= array_size (in)); VERIFY (t.out_size <= array_size (out)); auto state = mbstate_t{}; - auto in_next = (const CharT *) nullptr; - auto out_next = (char *) nullptr; + auto in_next = (const InternT *) nullptr; + auto out_next = (ExternT *) nullptr; auto res = codecvt_base::result (); res = cvt.out (state, in, in + t.in_size, in_next, out, out + t.out_size, @@ -299,29 +350,29 @@ utf32_to_utf8_out_ok (const std::codecvt &cvt) VERIFY (res == cvt.ok); VERIFY (in_next == in + t.in_size); VERIFY (out_next == out + t.out_size); - VERIFY (char_traits::compare (out, exp, t.out_size) == 0); + VERIFY (char_traits::compare (out, exp, t.out_size) == 0); if (t.out_size < array_size (out)) VERIFY (out[t.out_size] == 0); } } -template +template void -utf32_to_utf8_out_partial (const std::codecvt &cvt) +utf32_to_utf8_out_partial (const std::codecvt &cvt) { using namespace std; // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP - const char32_t in_literal[] = U"bш\uAAAA\U0010AAAA"; - const char exp[] = "bш\uAAAA\U0010AAAA"; - CharT in[array_size (in_literal)] = {}; - copy (begin (in_literal), end (in_literal), begin (in)); - - static_assert (array_size (in_literal) == 5, ""); - static_assert (array_size (in) == 5, ""); - static_assert (array_size (exp) == 11, ""); - VERIFY (char_traits::length (in_literal) == 4); - VERIFY (char_traits::length (in) == 4); - VERIFY (char_traits::length (exp) == 10); + const char32_t input[] = U"b\u0448\uAAAA\U0010AAAA"; + const unsigned char expected[] = "b\u0448\uAAAA\U0010AAAA"; + static_assert (array_size (input) == 5, ""); + static_assert (array_size (expected) == 11, ""); + + InternT in[array_size (input)]; + ExternT exp[array_size (expected)]; + copy (begin (input), end (input), begin (in)); + copy (begin (expected), end (expected), begin (exp)); + VERIFY (char_traits::length (in) == 4); + VERIFY (char_traits::length (exp) == 10); const test_offsets_partial offsets[] = { {1, 0, 0, 0}, // no space for first CP @@ -340,14 +391,14 @@ utf32_to_utf8_out_partial (const std::codecvt &cvt) }; for (auto t : offsets) { - char out[array_size (exp) - 1] = {}; + ExternT out[array_size (exp) - 1] = {}; VERIFY (t.in_size <= array_size (in)); VERIFY (t.out_size <= array_size (out)); VERIFY (t.expected_in_next <= t.in_size); VERIFY (t.expected_out_next <= t.out_size); auto state = mbstate_t{}; - auto in_next = (const CharT *) nullptr; - auto out_next = (char *) nullptr; + auto in_next = (const InternT *) nullptr; + auto out_next = (ExternT *) nullptr; auto res = codecvt_base::result (); res = cvt.out (state, in, in + t.in_size, in_next, out, out + t.out_size, @@ -355,44 +406,58 @@ utf32_to_utf8_out_partial (const std::codecvt &cvt) VERIFY (res == cvt.partial); VERIFY (in_next == in + t.expected_in_next); VERIFY (out_next == out + t.expected_out_next); - VERIFY (char_traits::compare (out, exp, t.expected_out_next) == 0); + VERIFY (char_traits::compare (out, exp, t.expected_out_next) + == 0); if (t.expected_out_next < array_size (out)) VERIFY (out[t.expected_out_next] == 0); } } -template +template void -utf32_to_utf8_out_error (const std::codecvt &cvt) +utf32_to_utf8_out_error (const std::codecvt &cvt) { using namespace std; - const char32_t valid_in[] = U"bш\uAAAA\U0010AAAA"; - const char exp[] = "bш\uAAAA\U0010AAAA"; - - static_assert (array_size (valid_in) == 5, ""); - static_assert (array_size (exp) == 11, ""); - VERIFY (char_traits::length (valid_in) == 4); - VERIFY (char_traits::length (exp) == 10); - - test_offsets_error offsets[] = {{4, 10, 0, 0, 0x00110000, 0}, - {4, 10, 1, 1, 0x00110000, 1}, - {4, 10, 2, 3, 0x00110000, 2}, - {4, 10, 3, 6, 0x00110000, 3}}; + // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP + const char32_t input[] = U"b\u0448\uAAAA\U0010AAAA"; + const unsigned char expected[] = "b\u0448\uAAAA\U0010AAAA"; + static_assert (array_size (input) == 5, ""); + static_assert (array_size (expected) == 11, ""); + + InternT in[array_size (input)]; + ExternT exp[array_size (expected)]; + copy (begin (input), end (input), begin (in)); + copy (begin (expected), end (expected), begin (exp)); + VERIFY (char_traits::length (in) == 4); + VERIFY (char_traits::length (exp) == 10); + + test_offsets_error offsets[] = { + + // Surrogate CP + {4, 10, 0, 0, 0xD800, 0}, + {4, 10, 1, 1, 0xDBFF, 1}, + {4, 10, 2, 3, 0xDC00, 2}, + {4, 10, 3, 6, 0xDFFF, 3}, + + // CP out of range + {4, 10, 0, 0, 0x00110000, 0}, + {4, 10, 1, 1, 0x00110000, 1}, + {4, 10, 2, 3, 0x00110000, 2}, + {4, 10, 3, 6, 0x00110000, 3}}; for (auto t : offsets) { - CharT in[array_size (valid_in)] = {}; - char out[array_size (exp) - 1] = {}; + ExternT out[array_size (exp) - 1] = {}; VERIFY (t.in_size <= array_size (in)); VERIFY (t.out_size <= array_size (out)); VERIFY (t.expected_in_next <= t.in_size); VERIFY (t.expected_out_next <= t.out_size); - copy (begin (valid_in), end (valid_in), begin (in)); + auto old_char = in[t.replace_pos]; in[t.replace_pos] = t.replace_char; auto state = mbstate_t{}; - auto in_next = (const CharT *) nullptr; - auto out_next = (char *) nullptr; + auto in_next = (const InternT *) nullptr; + auto out_next = (ExternT *) nullptr; auto res = codecvt_base::result (); res = cvt.out (state, in, in + t.in_size, in_next, out, out + t.out_size, @@ -400,56 +465,59 @@ utf32_to_utf8_out_error (const std::codecvt &cvt) VERIFY (res == cvt.error); VERIFY (in_next == in + t.expected_in_next); VERIFY (out_next == out + t.expected_out_next); - VERIFY (char_traits::compare (out, exp, t.expected_out_next) == 0); + VERIFY (char_traits::compare (out, exp, t.expected_out_next) + == 0); if (t.expected_out_next < array_size (out)) VERIFY (out[t.expected_out_next] == 0); + + in[t.replace_pos] = old_char; } } -template +template void -utf32_to_utf8_out (const std::codecvt &cvt) +utf32_to_utf8_out (const std::codecvt &cvt) { utf32_to_utf8_out_ok (cvt); utf32_to_utf8_out_partial (cvt); utf32_to_utf8_out_error (cvt); } -template +template void -test_utf8_utf32_codecvts (const std::codecvt &cvt) +test_utf8_utf32_cvt (const std::codecvt &cvt) { utf8_to_utf32_in (cvt); utf32_to_utf8_out (cvt); } -template +template void -utf8_to_utf16_in_ok (const std::codecvt &cvt) +utf8_to_utf16_in_ok (const std::codecvt &cvt) { using namespace std; // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP - const char in[] = "bш\uAAAA\U0010AAAA"; - const char16_t exp_literal[] = u"bш\uAAAA\U0010AAAA"; - CharT exp[array_size (exp_literal)] = {}; - copy (begin (exp_literal), end (exp_literal), begin (exp)); - - static_assert (array_size (in) == 11, ""); - static_assert (array_size (exp_literal) == 6, ""); - static_assert (array_size (exp) == 6, ""); - VERIFY (char_traits::length (in) == 10); - VERIFY (char_traits::length (exp_literal) == 5); - VERIFY (char_traits::length (exp) == 5); + const unsigned char input[] = "b\u0448\uAAAA\U0010AAAA"; + const char16_t expected[] = u"b\u0448\uAAAA\U0010AAAA"; + static_assert (array_size (input) == 11, ""); + static_assert (array_size (expected) == 6, ""); + + ExternT in[array_size (input)]; + InternT exp[array_size (expected)]; + copy (begin (input), end (input), begin (in)); + copy (begin (expected), end (expected), begin (exp)); + VERIFY (char_traits::length (in) == 10); + VERIFY (char_traits::length (exp) == 5); test_offsets_ok offsets[] = {{0, 0}, {1, 1}, {3, 2}, {6, 3}, {10, 5}}; for (auto t : offsets) { - CharT out[array_size (exp) - 1] = {}; + InternT out[array_size (exp) - 1] = {}; VERIFY (t.in_size <= array_size (in)); VERIFY (t.out_size <= array_size (out)); auto state = mbstate_t{}; - auto in_next = (const char *) nullptr; - auto out_next = (CharT *) nullptr; + auto in_next = (const ExternT *) nullptr; + auto out_next = (InternT *) nullptr; auto res = codecvt_base::result (); res = cvt.in (state, in, in + t.in_size, in_next, out, out + t.out_size, @@ -457,19 +525,19 @@ utf8_to_utf16_in_ok (const std::codecvt &cvt) VERIFY (res == cvt.ok); VERIFY (in_next == in + t.in_size); VERIFY (out_next == out + t.out_size); - VERIFY (char_traits::compare (out, exp, t.out_size) == 0); + VERIFY (char_traits::compare (out, exp, t.out_size) == 0); if (t.out_size < array_size (out)) VERIFY (out[t.out_size] == 0); } for (auto t : offsets) { - CharT out[array_size (exp)] = {}; + InternT out[array_size (exp)] = {}; VERIFY (t.in_size <= array_size (in)); VERIFY (t.out_size <= array_size (out)); auto state = mbstate_t{}; - auto in_next = (const char *) nullptr; - auto out_next = (CharT *) nullptr; + auto in_next = (const ExternT *) nullptr; + auto out_next = (InternT *) nullptr; auto res = codecvt_base::result (); res @@ -477,29 +545,29 @@ utf8_to_utf16_in_ok (const std::codecvt &cvt) VERIFY (res == cvt.ok); VERIFY (in_next == in + t.in_size); VERIFY (out_next == out + t.out_size); - VERIFY (char_traits::compare (out, exp, t.out_size) == 0); + VERIFY (char_traits::compare (out, exp, t.out_size) == 0); if (t.out_size < array_size (out)) VERIFY (out[t.out_size] == 0); } } -template +template void -utf8_to_utf16_in_partial (const std::codecvt &cvt) +utf8_to_utf16_in_partial (const std::codecvt &cvt) { using namespace std; // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP - const char in[] = "bш\uAAAA\U0010AAAA"; - const char16_t exp_literal[] = u"bш\uAAAA\U0010AAAA"; - CharT exp[array_size (exp_literal)] = {}; - copy (begin (exp_literal), end (exp_literal), begin (exp)); - - static_assert (array_size (in) == 11, ""); - static_assert (array_size (exp_literal) == 6, ""); - static_assert (array_size (exp) == 6, ""); - VERIFY (char_traits::length (in) == 10); - VERIFY (char_traits::length (exp_literal) == 5); - VERIFY (char_traits::length (exp) == 5); + const unsigned char input[] = "b\u0448\uAAAA\U0010AAAA"; + const char16_t expected[] = u"b\u0448\uAAAA\U0010AAAA"; + static_assert (array_size (input) == 11, ""); + static_assert (array_size (expected) == 6, ""); + + ExternT in[array_size (input)]; + InternT exp[array_size (expected)]; + copy (begin (input), end (input), begin (in)); + copy (begin (expected), end (expected), begin (exp)); + VERIFY (char_traits::length (in) == 10); + VERIFY (char_traits::length (exp) == 5); test_offsets_partial offsets[] = { {1, 0, 0, 0}, // no space for first CP @@ -530,14 +598,14 @@ utf8_to_utf16_in_partial (const std::codecvt &cvt) for (auto t : offsets) { - CharT out[array_size (exp) - 1] = {}; + InternT out[array_size (exp) - 1] = {}; VERIFY (t.in_size <= array_size (in)); VERIFY (t.out_size <= array_size (out)); VERIFY (t.expected_in_next <= t.in_size); VERIFY (t.expected_out_next <= t.out_size); auto state = mbstate_t{}; - auto in_next = (const char *) nullptr; - auto out_next = (CharT *) nullptr; + auto in_next = (const ExternT *) nullptr; + auto out_next = (InternT *) nullptr; auto res = codecvt_base::result (); res = cvt.in (state, in, in + t.in_size, in_next, out, out + t.out_size, @@ -545,36 +613,58 @@ utf8_to_utf16_in_partial (const std::codecvt &cvt) VERIFY (res == cvt.partial); VERIFY (in_next == in + t.expected_in_next); VERIFY (out_next == out + t.expected_out_next); - VERIFY (char_traits::compare (out, exp, t.expected_out_next) == 0); + VERIFY (char_traits::compare (out, exp, t.expected_out_next) + == 0); if (t.expected_out_next < array_size (out)) VERIFY (out[t.expected_out_next] == 0); } } -template +template void -utf8_to_utf16_in_error (const std::codecvt &cvt) +utf8_to_utf16_in_error (const std::codecvt &cvt) { using namespace std; - const char valid_in[] = "bш\uAAAA\U0010AAAA"; - const char16_t exp_literal[] = u"bш\uAAAA\U0010AAAA"; - CharT exp[array_size (exp_literal)] = {}; - copy (begin (exp_literal), end (exp_literal), begin (exp)); + // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP, 4-byte CP + const unsigned char input[] = "b\u0448\uD700\U0010AAAA"; + const char16_t expected[] = u"b\u0448\uD700\U0010AAAA"; + static_assert (array_size (input) == 11, ""); + static_assert (array_size (expected) == 6, ""); + + ExternT in[array_size (input)]; + InternT exp[array_size (expected)]; + copy (begin (input), end (input), begin (in)); + copy (begin (expected), end (expected), begin (exp)); + VERIFY (char_traits::length (in) == 10); + VERIFY (char_traits::length (exp) == 5); + + // There are 5 classes of errors in UTF-8 decoding + // 1. Missing leading byte + // 2. Missing trailing byte + // 3. Surrogate CP + // 4. Overlong sequence + // 5. CP out of Unicode range + test_offsets_error offsets[] = { + + // 1. Missing leading byte. We will replace the leading byte with + // non-leading byte, such as a byte that is always invalid or a trailing + // byte. - static_assert (array_size (valid_in) == 11, ""); - static_assert (array_size (exp_literal) == 6, ""); - static_assert (array_size (exp) == 6, ""); - VERIFY (char_traits::length (valid_in) == 10); - VERIFY (char_traits::length (exp_literal) == 5); - VERIFY (char_traits::length (exp) == 5); + // replace leading byte with invalid byte + {1, 5, 0, 0, 0xFF, 0}, + {3, 5, 1, 1, 0xFF, 1}, + {6, 5, 3, 2, 0xFF, 3}, + {10, 5, 6, 3, 0xFF, 6}, - test_offsets_error offsets[] = { + // replace leading byte with trailing byte + {1, 5, 0, 0, 0b10101010, 0}, + {3, 5, 1, 1, 0b10101010, 1}, + {6, 5, 3, 2, 0b10101010, 3}, + {10, 5, 6, 3, 0b10101010, 6}, - // replace leading byte with invalid byte - {1, 5, 0, 0, '\xFF', 0}, - {3, 5, 1, 1, '\xFF', 1}, - {6, 5, 3, 2, '\xFF', 3}, - {10, 5, 6, 3, '\xFF', 6}, + // 2. Missing trailing byte. We will replace the trailing byte with + // non-trailing byte, such as a byte that is always invalid or a leading + // byte (simple ASCII byte in our case). // replace first trailing byte with ASCII byte {3, 5, 1, 1, 'z', 2}, @@ -582,21 +672,27 @@ utf8_to_utf16_in_error (const std::codecvt &cvt) {10, 5, 6, 3, 'z', 7}, // replace first trailing byte with invalid byte - {3, 5, 1, 1, '\xFF', 2}, - {6, 5, 3, 2, '\xFF', 4}, - {10, 5, 6, 3, '\xFF', 7}, + {3, 5, 1, 1, 0xFF, 2}, + {6, 5, 3, 2, 0xFF, 4}, + {10, 5, 6, 3, 0xFF, 7}, // replace second trailing byte with ASCII byte {6, 5, 3, 2, 'z', 5}, {10, 5, 6, 3, 'z', 8}, // replace second trailing byte with invalid byte - {6, 5, 3, 2, '\xFF', 5}, - {10, 5, 6, 3, '\xFF', 8}, + {6, 5, 3, 2, 0xFF, 5}, + {10, 5, 6, 3, 0xFF, 8}, // replace third trailing byte {10, 5, 6, 3, 'z', 9}, - {10, 5, 6, 3, '\xFF', 9}, + {10, 5, 6, 3, 0xFF, 9}, + + // 2.1 The following test-cases raise doubt whether error or partial should + // be returned. For example, we have 4-byte sequence with valid leading + // byte. If we hide the last byte we need to return partial. But, if the + // second or third byte, which are visible to the call to codecvt, are + // malformed then error should be returned. // replace first trailing byte with ASCII byte, also incomplete at end {5, 5, 3, 2, 'z', 4}, @@ -604,30 +700,51 @@ utf8_to_utf16_in_error (const std::codecvt &cvt) {9, 5, 6, 3, 'z', 7}, // replace first trailing byte with invalid byte, also incomplete at end - {5, 5, 3, 2, '\xFF', 4}, - {8, 5, 6, 3, '\xFF', 7}, - {9, 5, 6, 3, '\xFF', 7}, + {5, 5, 3, 2, 0xFF, 4}, + {8, 5, 6, 3, 0xFF, 7}, + {9, 5, 6, 3, 0xFF, 7}, // replace second trailing byte with ASCII byte, also incomplete at end {9, 5, 6, 3, 'z', 8}, // replace second trailing byte with invalid byte, also incomplete at end - {9, 5, 6, 3, '\xFF', 8}, + {9, 5, 6, 3, 0xFF, 8}, + + // 3. Surrogate CP. We modify the second byte (first trailing) of the 3-byte + // CP U+D700 + {6, 5, 3, 2, 0b10100000, 4}, // turn U+D700 into U+D800 + {6, 5, 3, 2, 0b10101100, 4}, // turn U+D700 into U+DB00 + {6, 5, 3, 2, 0b10110000, 4}, // turn U+D700 into U+DC00 + {6, 5, 3, 2, 0b10111100, 4}, // turn U+D700 into U+DF00 + + // 4. Overlong sequence. The CPs in the input are chosen such as modifying + // just the leading byte is enough to make them overlong, i.e. for the + // 3-byte and 4-byte CP the second byte (first trailing) has enough leading + // zeroes. + {3, 5, 1, 1, 0b11000000, 1}, // make the 2-byte CP overlong + {3, 5, 1, 1, 0b11000001, 1}, // make the 2-byte CP overlong + {6, 5, 3, 2, 0b11100000, 3}, // make the 3-byte CP overlong + {10, 5, 6, 3, 0b11110000, 6}, // make the 4-byte CP overlong + + // 5. CP above range + // turn U+10AAAA into U+14AAAA by changing its leading byte + {10, 5, 6, 3, 0b11110101, 6}, + // turn U+10AAAA into U+11AAAA by changing its 2nd byte + {10, 5, 6, 3, 0b10011010, 7}, }; for (auto t : offsets) { - char in[array_size (valid_in)] = {}; - CharT out[array_size (exp) - 1] = {}; + InternT out[array_size (exp) - 1] = {}; VERIFY (t.in_size <= array_size (in)); VERIFY (t.out_size <= array_size (out)); VERIFY (t.expected_in_next <= t.in_size); VERIFY (t.expected_out_next <= t.out_size); - char_traits::copy (in, valid_in, array_size (valid_in)); + auto old_char = in[t.replace_pos]; in[t.replace_pos] = t.replace_char; auto state = mbstate_t{}; - auto in_next = (const char *) nullptr; - auto out_next = (CharT *) nullptr; + auto in_next = (const ExternT *) nullptr; + auto out_next = (InternT *) nullptr; auto res = codecvt_base::result (); res = cvt.in (state, in, in + t.in_size, in_next, out, out + t.out_size, @@ -635,48 +752,51 @@ utf8_to_utf16_in_error (const std::codecvt &cvt) VERIFY (res == cvt.error); VERIFY (in_next == in + t.expected_in_next); VERIFY (out_next == out + t.expected_out_next); - VERIFY (char_traits::compare (out, exp, t.expected_out_next) == 0); + VERIFY (char_traits::compare (out, exp, t.expected_out_next) + == 0); if (t.expected_out_next < array_size (out)) VERIFY (out[t.expected_out_next] == 0); + + in[t.replace_pos] = old_char; } } -template +template void -utf8_to_utf16_in (const std::codecvt &cvt) +utf8_to_utf16_in (const std::codecvt &cvt) { utf8_to_utf16_in_ok (cvt); utf8_to_utf16_in_partial (cvt); utf8_to_utf16_in_error (cvt); } -template +template void -utf16_to_utf8_out_ok (const std::codecvt &cvt) +utf16_to_utf8_out_ok (const std::codecvt &cvt) { using namespace std; // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP - const char16_t in_literal[] = u"bш\uAAAA\U0010AAAA"; - const char exp[] = "bш\uAAAA\U0010AAAA"; - CharT in[array_size (in_literal)]; - copy (begin (in_literal), end (in_literal), begin (in)); - - static_assert (array_size (in_literal) == 6, ""); - static_assert (array_size (exp) == 11, ""); - static_assert (array_size (in) == 6, ""); - VERIFY (char_traits::length (in_literal) == 5); - VERIFY (char_traits::length (exp) == 10); - VERIFY (char_traits::length (in) == 5); + const char16_t input[] = u"b\u0448\uAAAA\U0010AAAA"; + const unsigned char expected[] = "b\u0448\uAAAA\U0010AAAA"; + static_assert (array_size (input) == 6, ""); + static_assert (array_size (expected) == 11, ""); + + InternT in[array_size (input)]; + ExternT exp[array_size (expected)]; + copy (begin (input), end (input), begin (in)); + copy (begin (expected), end (expected), begin (exp)); + VERIFY (char_traits::length (in) == 5); + VERIFY (char_traits::length (exp) == 10); const test_offsets_ok offsets[] = {{0, 0}, {1, 1}, {2, 3}, {3, 6}, {5, 10}}; for (auto t : offsets) { - char out[array_size (exp) - 1] = {}; + ExternT out[array_size (exp) - 1] = {}; VERIFY (t.in_size <= array_size (in)); VERIFY (t.out_size <= array_size (out)); auto state = mbstate_t{}; - auto in_next = (const CharT *) nullptr; - auto out_next = (char *) nullptr; + auto in_next = (const InternT *) nullptr; + auto out_next = (ExternT *) nullptr; auto res = codecvt_base::result (); res = cvt.out (state, in, in + t.in_size, in_next, out, out + t.out_size, @@ -684,29 +804,29 @@ utf16_to_utf8_out_ok (const std::codecvt &cvt) VERIFY (res == cvt.ok); VERIFY (in_next == in + t.in_size); VERIFY (out_next == out + t.out_size); - VERIFY (char_traits::compare (out, exp, t.out_size) == 0); + VERIFY (char_traits::compare (out, exp, t.out_size) == 0); if (t.out_size < array_size (out)) VERIFY (out[t.out_size] == 0); } } -template +template void -utf16_to_utf8_out_partial (const std::codecvt &cvt) +utf16_to_utf8_out_partial (const std::codecvt &cvt) { using namespace std; // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP - const char16_t in_literal[] = u"bш\uAAAA\U0010AAAA"; - const char exp[] = "bш\uAAAA\U0010AAAA"; - CharT in[array_size (in_literal)]; - copy (begin (in_literal), end (in_literal), begin (in)); - - static_assert (array_size (in_literal) == 6, ""); - static_assert (array_size (exp) == 11, ""); - static_assert (array_size (in) == 6, ""); - VERIFY (char_traits::length (in_literal) == 5); - VERIFY (char_traits::length (exp) == 10); - VERIFY (char_traits::length (in) == 5); + const char16_t input[] = u"b\u0448\uAAAA\U0010AAAA"; + const unsigned char expected[] = "b\u0448\uAAAA\U0010AAAA"; + static_assert (array_size (input) == 6, ""); + static_assert (array_size (expected) == 11, ""); + + InternT in[array_size (input)]; + ExternT exp[array_size (expected)]; + copy (begin (input), end (input), begin (in)); + copy (begin (expected), end (expected), begin (exp)); + VERIFY (char_traits::length (in) == 5); + VERIFY (char_traits::length (exp) == 10); const test_offsets_partial offsets[] = { {1, 0, 0, 0}, // no space for first CP @@ -732,14 +852,14 @@ utf16_to_utf8_out_partial (const std::codecvt &cvt) }; for (auto t : offsets) { - char out[array_size (exp) - 1] = {}; + ExternT out[array_size (exp) - 1] = {}; VERIFY (t.in_size <= array_size (in)); VERIFY (t.out_size <= array_size (out)); VERIFY (t.expected_in_next <= t.in_size); VERIFY (t.expected_out_next <= t.out_size); auto state = mbstate_t{}; - auto in_next = (const CharT *) nullptr; - auto out_next = (char *) nullptr; + auto in_next = (const InternT *) nullptr; + auto out_next = (ExternT *) nullptr; auto res = codecvt_base::result (); res = cvt.out (state, in, in + t.in_size, in_next, out, out + t.out_size, @@ -747,26 +867,34 @@ utf16_to_utf8_out_partial (const std::codecvt &cvt) VERIFY (res == cvt.partial); VERIFY (in_next == in + t.expected_in_next); VERIFY (out_next == out + t.expected_out_next); - VERIFY (char_traits::compare (out, exp, t.expected_out_next) == 0); + VERIFY (char_traits::compare (out, exp, t.expected_out_next) + == 0); if (t.expected_out_next < array_size (out)) VERIFY (out[t.expected_out_next] == 0); } } -template +template void -utf16_to_utf8_out_error (const std::codecvt &cvt) +utf16_to_utf8_out_error (const std::codecvt &cvt) { using namespace std; - const char16_t valid_in[] = u"bш\uAAAA\U0010AAAA"; - const char exp[] = "bш\uAAAA\U0010AAAA"; - - static_assert (array_size (valid_in) == 6, ""); - static_assert (array_size (exp) == 11, ""); - VERIFY (char_traits::length (valid_in) == 5); - VERIFY (char_traits::length (exp) == 10); - - test_offsets_error offsets[] = { + // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP + const char16_t input[] = u"b\u0448\uAAAA\U0010AAAA"; + const unsigned char expected[] = "b\u0448\uAAAA\U0010AAAA"; + static_assert (array_size (input) == 6, ""); + static_assert (array_size (expected) == 11, ""); + + InternT in[array_size (input)]; + ExternT exp[array_size (expected)]; + copy (begin (input), end (input), begin (in)); + copy (begin (expected), end (expected), begin (exp)); + VERIFY (char_traits::length (in) == 5); + VERIFY (char_traits::length (exp) == 10); + + // The only possible error in UTF-16 is unpaired surrogate code units. + // So we replace valid code points (scalar values) with lone surrogate CU. + test_offsets_error offsets[] = { {5, 10, 0, 0, 0xD800, 0}, {5, 10, 0, 0, 0xDBFF, 0}, {5, 10, 0, 0, 0xDC00, 0}, @@ -796,18 +924,17 @@ utf16_to_utf8_out_error (const std::codecvt &cvt) for (auto t : offsets) { - CharT in[array_size (valid_in)] = {}; - char out[array_size (exp) - 1] = {}; + ExternT out[array_size (exp) - 1] = {}; VERIFY (t.in_size <= array_size (in)); VERIFY (t.out_size <= array_size (out)); VERIFY (t.expected_in_next <= t.in_size); VERIFY (t.expected_out_next <= t.out_size); - copy (begin (valid_in), end (valid_in), begin (in)); + auto old_char = in[t.replace_pos]; in[t.replace_pos] = t.replace_char; auto state = mbstate_t{}; - auto in_next = (const CharT *) nullptr; - auto out_next = (char *) nullptr; + auto in_next = (const InternT *) nullptr; + auto out_next = (ExternT *) nullptr; auto res = codecvt_base::result (); res = cvt.out (state, in, in + t.in_size, in_next, out, out + t.out_size, @@ -815,56 +942,59 @@ utf16_to_utf8_out_error (const std::codecvt &cvt) VERIFY (res == cvt.error); VERIFY (in_next == in + t.expected_in_next); VERIFY (out_next == out + t.expected_out_next); - VERIFY (char_traits::compare (out, exp, t.expected_out_next) == 0); + VERIFY (char_traits::compare (out, exp, t.expected_out_next) + == 0); if (t.expected_out_next < array_size (out)) VERIFY (out[t.expected_out_next] == 0); + + in[t.replace_pos] = old_char; } } -template +template void -utf16_to_utf8_out (const std::codecvt &cvt) +utf16_to_utf8_out (const std::codecvt &cvt) { utf16_to_utf8_out_ok (cvt); utf16_to_utf8_out_partial (cvt); utf16_to_utf8_out_error (cvt); } -template +template void -test_utf8_utf16_cvts (const std::codecvt &cvt) +test_utf8_utf16_cvt (const std::codecvt &cvt) { utf8_to_utf16_in (cvt); utf16_to_utf8_out (cvt); } -template +template void -utf8_to_ucs2_in_ok (const std::codecvt &cvt) +utf8_to_ucs2_in_ok (const std::codecvt &cvt) { using namespace std; // UTF-8 string of 1-byte CP, 2-byte CP and 3-byte CP - const char in[] = "bш\uAAAA"; - const char16_t exp_literal[] = u"bш\uAAAA"; - CharT exp[array_size (exp_literal)] = {}; - copy (begin (exp_literal), end (exp_literal), begin (exp)); - - static_assert (array_size (in) == 7, ""); - static_assert (array_size (exp_literal) == 4, ""); - static_assert (array_size (exp) == 4, ""); - VERIFY (char_traits::length (in) == 6); - VERIFY (char_traits::length (exp_literal) == 3); - VERIFY (char_traits::length (exp) == 3); + const unsigned char input[] = "b\u0448\uAAAA"; + const char16_t expected[] = u"b\u0448\uAAAA"; + static_assert (array_size (input) == 7, ""); + static_assert (array_size (expected) == 4, ""); + + ExternT in[array_size (input)]; + InternT exp[array_size (expected)]; + copy (begin (input), end (input), begin (in)); + copy (begin (expected), end (expected), begin (exp)); + VERIFY (char_traits::length (in) == 6); + VERIFY (char_traits::length (exp) == 3); test_offsets_ok offsets[] = {{0, 0}, {1, 1}, {3, 2}, {6, 3}}; for (auto t : offsets) { - CharT out[array_size (exp) - 1] = {}; + InternT out[array_size (exp) - 1] = {}; VERIFY (t.in_size <= array_size (in)); VERIFY (t.out_size <= array_size (out)); auto state = mbstate_t{}; - auto in_next = (const char *) nullptr; - auto out_next = (CharT *) nullptr; + auto in_next = (const ExternT *) nullptr; + auto out_next = (InternT *) nullptr; auto res = codecvt_base::result (); res = cvt.in (state, in, in + t.in_size, in_next, out, out + t.out_size, @@ -872,19 +1002,19 @@ utf8_to_ucs2_in_ok (const std::codecvt &cvt) VERIFY (res == cvt.ok); VERIFY (in_next == in + t.in_size); VERIFY (out_next == out + t.out_size); - VERIFY (char_traits::compare (out, exp, t.out_size) == 0); + VERIFY (char_traits::compare (out, exp, t.out_size) == 0); if (t.out_size < array_size (out)) VERIFY (out[t.out_size] == 0); } for (auto t : offsets) { - CharT out[array_size (exp)] = {}; + InternT out[array_size (exp)] = {}; VERIFY (t.in_size <= array_size (in)); VERIFY (t.out_size <= array_size (out)); auto state = mbstate_t{}; - auto in_next = (const char *) nullptr; - auto out_next = (CharT *) nullptr; + auto in_next = (const ExternT *) nullptr; + auto out_next = (InternT *) nullptr; auto res = codecvt_base::result (); res @@ -892,29 +1022,29 @@ utf8_to_ucs2_in_ok (const std::codecvt &cvt) VERIFY (res == cvt.ok); VERIFY (in_next == in + t.in_size); VERIFY (out_next == out + t.out_size); - VERIFY (char_traits::compare (out, exp, t.out_size) == 0); + VERIFY (char_traits::compare (out, exp, t.out_size) == 0); if (t.out_size < array_size (out)) VERIFY (out[t.out_size] == 0); } } -template +template void -utf8_to_ucs2_in_partial (const std::codecvt &cvt) +utf8_to_ucs2_in_partial (const std::codecvt &cvt) { using namespace std; // UTF-8 string of 1-byte CP, 2-byte CP and 3-byte CP - const char in[] = "bш\uAAAA"; - const char16_t exp_literal[] = u"bш\uAAAA"; - CharT exp[array_size (exp_literal)] = {}; - copy (begin (exp_literal), end (exp_literal), begin (exp)); - - static_assert (array_size (in) == 7, ""); - static_assert (array_size (exp_literal) == 4, ""); - static_assert (array_size (exp) == 4, ""); - VERIFY (char_traits::length (in) == 6); - VERIFY (char_traits::length (exp_literal) == 3); - VERIFY (char_traits::length (exp) == 3); + const unsigned char input[] = "b\u0448\uAAAA"; + const char16_t expected[] = u"b\u0448\uAAAA"; + static_assert (array_size (input) == 7, ""); + static_assert (array_size (expected) == 4, ""); + + ExternT in[array_size (input)]; + InternT exp[array_size (expected)]; + copy (begin (input), end (input), begin (in)); + copy (begin (expected), end (expected), begin (exp)); + VERIFY (char_traits::length (in) == 6); + VERIFY (char_traits::length (exp) == 3); test_offsets_partial offsets[] = { {1, 0, 0, 0}, // no space for first CP @@ -932,14 +1062,14 @@ utf8_to_ucs2_in_partial (const std::codecvt &cvt) for (auto t : offsets) { - CharT out[array_size (exp) - 1] = {}; + InternT out[array_size (exp) - 1] = {}; VERIFY (t.in_size <= array_size (in)); VERIFY (t.out_size <= array_size (out)); VERIFY (t.expected_in_next <= t.in_size); VERIFY (t.expected_out_next <= t.out_size); auto state = mbstate_t{}; - auto in_next = (const char *) nullptr; - auto out_next = (CharT *) nullptr; + auto in_next = (const ExternT *) nullptr; + auto out_next = (InternT *) nullptr; auto res = codecvt_base::result (); res = cvt.in (state, in, in + t.in_size, in_next, out, out + t.out_size, @@ -947,36 +1077,57 @@ utf8_to_ucs2_in_partial (const std::codecvt &cvt) VERIFY (res == cvt.partial); VERIFY (in_next == in + t.expected_in_next); VERIFY (out_next == out + t.expected_out_next); - VERIFY (char_traits::compare (out, exp, t.expected_out_next) == 0); + VERIFY (char_traits::compare (out, exp, t.expected_out_next) + == 0); if (t.expected_out_next < array_size (out)) VERIFY (out[t.expected_out_next] == 0); } } -template +template void -utf8_to_ucs2_in_error (const std::codecvt &cvt) +utf8_to_ucs2_in_error (const std::codecvt &cvt) { using namespace std; - const char valid_in[] = "bш\uAAAA\U0010AAAA"; - const char16_t exp_literal[] = u"bш\uAAAA\U0010AAAA"; - CharT exp[array_size (exp_literal)] = {}; - copy (begin (exp_literal), end (exp_literal), begin (exp)); + const unsigned char input[] = "b\u0448\uD700\U0010AAAA"; + const char16_t expected[] = u"b\u0448\uD700\U0010AAAA"; + static_assert (array_size (input) == 11, ""); + static_assert (array_size (expected) == 6, ""); + + ExternT in[array_size (input)]; + InternT exp[array_size (expected)]; + copy (begin (input), end (input), begin (in)); + copy (begin (expected), end (expected), begin (exp)); + VERIFY (char_traits::length (in) == 10); + VERIFY (char_traits::length (exp) == 5); + + // There are 5 classes of errors in UTF-8 decoding + // 1. Missing leading byte + // 2. Missing trailing byte + // 3. Surrogate CP + // 4. Overlong sequence + // 5. CP out of Unicode range + test_offsets_error offsets[] = { + + // 1. Missing leading byte. We will replace the leading byte with + // non-leading byte, such as a byte that is always invalid or a trailing + // byte. - static_assert (array_size (valid_in) == 11, ""); - static_assert (array_size (exp_literal) == 6, ""); - static_assert (array_size (exp) == 6, ""); - VERIFY (char_traits::length (valid_in) == 10); - VERIFY (char_traits::length (exp_literal) == 5); - VERIFY (char_traits::length (exp) == 5); + // replace leading byte with invalid byte + {1, 5, 0, 0, 0xFF, 0}, + {3, 5, 1, 1, 0xFF, 1}, + {6, 5, 3, 2, 0xFF, 3}, + {10, 5, 6, 3, 0xFF, 6}, - test_offsets_error offsets[] = { + // replace leading byte with trailing byte + {1, 5, 0, 0, 0b10101010, 0}, + {3, 5, 1, 1, 0b10101010, 1}, + {6, 5, 3, 2, 0b10101010, 3}, + {10, 5, 6, 3, 0b10101010, 6}, - // replace leading byte with invalid byte - {1, 5, 0, 0, '\xFF', 0}, - {3, 5, 1, 1, '\xFF', 1}, - {6, 5, 3, 2, '\xFF', 3}, - {10, 5, 6, 3, '\xFF', 6}, + // 2. Missing trailing byte. We will replace the trailing byte with + // non-trailing byte, such as a byte that is always invalid or a leading + // byte (simple ASCII byte in our case). // replace first trailing byte with ASCII byte {3, 5, 1, 1, 'z', 2}, @@ -984,72 +1135,90 @@ utf8_to_ucs2_in_error (const std::codecvt &cvt) {10, 5, 6, 3, 'z', 7}, // replace first trailing byte with invalid byte - {3, 5, 1, 1, '\xFF', 2}, - {6, 5, 3, 2, '\xFF', 4}, - {10, 5, 6, 3, '\xFF', 7}, + {3, 5, 1, 1, 0xFF, 2}, + {6, 5, 3, 2, 0xFF, 4}, + {10, 5, 6, 3, 0xFF, 7}, // replace second trailing byte with ASCII byte {6, 5, 3, 2, 'z', 5}, {10, 5, 6, 3, 'z', 8}, // replace second trailing byte with invalid byte - {6, 5, 3, 2, '\xFF', 5}, - {10, 5, 6, 3, '\xFF', 8}, + {6, 5, 3, 2, 0xFF, 5}, + {10, 5, 6, 3, 0xFF, 8}, // replace third trailing byte {10, 5, 6, 3, 'z', 9}, - {10, 5, 6, 3, '\xFF', 9}, - - // When we see a leading byte of 4-byte CP, we should return error, no - // matter if it is incomplete at the end or has errors in the trailing - // bytes. - - // Don't replace anything, show full 4-byte CP - {10, 4, 6, 3, 'b', 0}, - {10, 5, 6, 3, 'b', 0}, + {10, 5, 6, 3, 0xFF, 9}, - // Don't replace anything, show incomplete 4-byte CP at the end - {7, 4, 6, 3, 'b', 0}, // incomplete fourth CP - {8, 4, 6, 3, 'b', 0}, // incomplete fourth CP - {9, 4, 6, 3, 'b', 0}, // incomplete fourth CP - {7, 5, 6, 3, 'b', 0}, // incomplete fourth CP - {8, 5, 6, 3, 'b', 0}, // incomplete fourth CP - {9, 5, 6, 3, 'b', 0}, // incomplete fourth CP + // 2.1 The following test-cases raise doubt whether error or partial should + // be returned. For example, we have 4-byte sequence with valid leading + // byte. If we hide the last byte we need to return partial. But, if the + // second or third byte, which are visible to the call to codecvt, are + // malformed then error should be returned. // replace first trailing byte with ASCII byte, also incomplete at end {5, 5, 3, 2, 'z', 4}, - - // replace first trailing byte with invalid byte, also incomplete at end - {5, 5, 3, 2, '\xFF', 4}, - - // replace first trailing byte with ASCII byte, also incomplete at end {8, 5, 6, 3, 'z', 7}, {9, 5, 6, 3, 'z', 7}, // replace first trailing byte with invalid byte, also incomplete at end - {8, 5, 6, 3, '\xFF', 7}, - {9, 5, 6, 3, '\xFF', 7}, + {5, 5, 3, 2, 0xFF, 4}, + {8, 5, 6, 3, 0xFF, 7}, + {9, 5, 6, 3, 0xFF, 7}, // replace second trailing byte with ASCII byte, also incomplete at end {9, 5, 6, 3, 'z', 8}, // replace second trailing byte with invalid byte, also incomplete at end - {9, 5, 6, 3, '\xFF', 8}, + {9, 5, 6, 3, 0xFF, 8}, + + // 3. Surrogate CP. We modify the second byte (first trailing) of the 3-byte + // CP U+D700 + {6, 5, 3, 2, 0b10100000, 4}, // turn U+D700 into U+D800 + {6, 5, 3, 2, 0b10101100, 4}, // turn U+D700 into U+DB00 + {6, 5, 3, 2, 0b10110000, 4}, // turn U+D700 into U+DC00 + {6, 5, 3, 2, 0b10111100, 4}, // turn U+D700 into U+DF00 + + // 4. Overlong sequence. The CPs in the input are chosen such as modifying + // just the leading byte is enough to make them overlong, i.e. for the + // 3-byte and 4-byte CP the second byte (first trailing) has enough leading + // zeroes. + {3, 5, 1, 1, 0b11000000, 1}, // make the 2-byte CP overlong + {3, 5, 1, 1, 0b11000001, 1}, // make the 2-byte CP overlong + {6, 5, 3, 2, 0b11100000, 3}, // make the 3-byte CP overlong + {10, 5, 6, 3, 0b11110000, 6}, // make the 4-byte CP overlong + + // 5. CP above range + // turn U+10AAAA into U+14AAAA by changing its leading byte + {10, 5, 6, 3, 0b11110101, 6}, + // turn U+10AAAA into U+11AAAA by changing its 2nd byte + {10, 5, 6, 3, 0b10011010, 7}, + // Don't replace anything, show full 4-byte CP U+10AAAA + {10, 4, 6, 3, 'b', 0}, + {10, 5, 6, 3, 'b', 0}, + // Don't replace anything, show incomplete 4-byte CP at the end. It's still + // out of UCS2 range just by seeing the first byte. + {7, 4, 6, 3, 'b', 0}, // incomplete fourth CP + {8, 4, 6, 3, 'b', 0}, // incomplete fourth CP + {9, 4, 6, 3, 'b', 0}, // incomplete fourth CP + {7, 5, 6, 3, 'b', 0}, // incomplete fourth CP + {8, 5, 6, 3, 'b', 0}, // incomplete fourth CP + {9, 5, 6, 3, 'b', 0}, // incomplete fourth CP }; for (auto t : offsets) { - char in[array_size (valid_in)] = {}; - CharT out[array_size (exp) - 1] = {}; + InternT out[array_size (exp) - 1] = {}; VERIFY (t.in_size <= array_size (in)); VERIFY (t.out_size <= array_size (out)); VERIFY (t.expected_in_next <= t.in_size); VERIFY (t.expected_out_next <= t.out_size); - char_traits::copy (in, valid_in, array_size (valid_in)); + auto old_char = in[t.replace_pos]; in[t.replace_pos] = t.replace_char; auto state = mbstate_t{}; - auto in_next = (const char *) nullptr; - auto out_next = (CharT *) nullptr; + auto in_next = (const ExternT *) nullptr; + auto out_next = (InternT *) nullptr; auto res = codecvt_base::result (); res = cvt.in (state, in, in + t.in_size, in_next, out, out + t.out_size, @@ -1057,48 +1226,51 @@ utf8_to_ucs2_in_error (const std::codecvt &cvt) VERIFY (res == cvt.error); VERIFY (in_next == in + t.expected_in_next); VERIFY (out_next == out + t.expected_out_next); - VERIFY (char_traits::compare (out, exp, t.expected_out_next) == 0); + VERIFY (char_traits::compare (out, exp, t.expected_out_next) + == 0); if (t.expected_out_next < array_size (out)) VERIFY (out[t.expected_out_next] == 0); + + in[t.replace_pos] = old_char; } } -template +template void -utf8_to_ucs2_in (const std::codecvt &cvt) +utf8_to_ucs2_in (const std::codecvt &cvt) { utf8_to_ucs2_in_ok (cvt); utf8_to_ucs2_in_partial (cvt); utf8_to_ucs2_in_error (cvt); } -template +template void -ucs2_to_utf8_out_ok (const std::codecvt &cvt) +ucs2_to_utf8_out_ok (const std::codecvt &cvt) { using namespace std; // UTF-8 string of 1-byte CP, 2-byte CP and 3-byte CP - const char16_t in_literal[] = u"bш\uAAAA"; - const char exp[] = "bш\uAAAA"; - CharT in[array_size (in_literal)] = {}; - copy (begin (in_literal), end (in_literal), begin (in)); - - static_assert (array_size (in_literal) == 4, ""); - static_assert (array_size (exp) == 7, ""); - static_assert (array_size (in) == 4, ""); - VERIFY (char_traits::length (in_literal) == 3); - VERIFY (char_traits::length (exp) == 6); - VERIFY (char_traits::length (in) == 3); + const char16_t input[] = u"b\u0448\uAAAA"; + const unsigned char expected[] = "b\u0448\uAAAA"; + static_assert (array_size (input) == 4, ""); + static_assert (array_size (expected) == 7, ""); + + InternT in[array_size (input)]; + ExternT exp[array_size (expected)]; + copy (begin (input), end (input), begin (in)); + copy (begin (expected), end (expected), begin (exp)); + VERIFY (char_traits::length (in) == 3); + VERIFY (char_traits::length (exp) == 6); const test_offsets_ok offsets[] = {{0, 0}, {1, 1}, {2, 3}, {3, 6}}; for (auto t : offsets) { - char out[array_size (exp) - 1] = {}; + ExternT out[array_size (exp) - 1] = {}; VERIFY (t.in_size <= array_size (in)); VERIFY (t.out_size <= array_size (out)); auto state = mbstate_t{}; - auto in_next = (const CharT *) nullptr; - auto out_next = (char *) nullptr; + auto in_next = (const InternT *) nullptr; + auto out_next = (ExternT *) nullptr; auto res = codecvt_base::result (); res = cvt.out (state, in, in + t.in_size, in_next, out, out + t.out_size, @@ -1106,29 +1278,29 @@ ucs2_to_utf8_out_ok (const std::codecvt &cvt) VERIFY (res == cvt.ok); VERIFY (in_next == in + t.in_size); VERIFY (out_next == out + t.out_size); - VERIFY (char_traits::compare (out, exp, t.out_size) == 0); + VERIFY (char_traits::compare (out, exp, t.out_size) == 0); if (t.out_size < array_size (out)) VERIFY (out[t.out_size] == 0); } } -template +template void -ucs2_to_utf8_out_partial (const std::codecvt &cvt) +ucs2_to_utf8_out_partial (const std::codecvt &cvt) { using namespace std; // UTF-8 string of 1-byte CP, 2-byte CP and 3-byte CP - const char16_t in_literal[] = u"bш\uAAAA"; - const char exp[] = "bш\uAAAA"; - CharT in[array_size (in_literal)] = {}; - copy (begin (in_literal), end (in_literal), begin (in)); - - static_assert (array_size (in_literal) == 4, ""); - static_assert (array_size (exp) == 7, ""); - static_assert (array_size (in) == 4, ""); - VERIFY (char_traits::length (in_literal) == 3); - VERIFY (char_traits::length (exp) == 6); - VERIFY (char_traits::length (in) == 3); + const char16_t input[] = u"b\u0448\uAAAA"; + const unsigned char expected[] = "b\u0448\uAAAA"; + static_assert (array_size (input) == 4, ""); + static_assert (array_size (expected) == 7, ""); + + InternT in[array_size (input)]; + ExternT exp[array_size (expected)]; + copy (begin (input), end (input), begin (in)); + copy (begin (expected), end (expected), begin (exp)); + VERIFY (char_traits::length (in) == 3); + VERIFY (char_traits::length (exp) == 6); const test_offsets_partial offsets[] = { {1, 0, 0, 0}, // no space for first CP @@ -1142,14 +1314,14 @@ ucs2_to_utf8_out_partial (const std::codecvt &cvt) }; for (auto t : offsets) { - char out[array_size (exp) - 1] = {}; + ExternT out[array_size (exp) - 1] = {}; VERIFY (t.in_size <= array_size (in)); VERIFY (t.out_size <= array_size (out)); VERIFY (t.expected_in_next <= t.in_size); VERIFY (t.expected_out_next <= t.out_size); auto state = mbstate_t{}; - auto in_next = (const CharT *) nullptr; - auto out_next = (char *) nullptr; + auto in_next = (const InternT *) nullptr; + auto out_next = (ExternT *) nullptr; auto res = codecvt_base::result (); res = cvt.out (state, in, in + t.in_size, in_next, out, out + t.out_size, @@ -1157,43 +1329,45 @@ ucs2_to_utf8_out_partial (const std::codecvt &cvt) VERIFY (res == cvt.partial); VERIFY (in_next == in + t.expected_in_next); VERIFY (out_next == out + t.expected_out_next); - VERIFY (char_traits::compare (out, exp, t.expected_out_next) == 0); + VERIFY (char_traits::compare (out, exp, t.expected_out_next) + == 0); if (t.expected_out_next < array_size (out)) VERIFY (out[t.expected_out_next] == 0); } } -template +template void -ucs2_to_utf8_out_error (const std::codecvt &cvt) +ucs2_to_utf8_out_error (const std::codecvt &cvt) { using namespace std; - const char16_t valid_in[] = u"bш\uAAAA\U0010AAAA"; - const char exp[] = "bш\uAAAA\U0010AAAA"; - - static_assert (array_size (valid_in) == 6, ""); - static_assert (array_size (exp) == 11, ""); - VERIFY (char_traits::length (valid_in) == 5); - VERIFY (char_traits::length (exp) == 10); - - test_offsets_error offsets[] = { - {5, 10, 0, 0, 0xD800, 0}, - {5, 10, 0, 0, 0xDBFF, 0}, - {5, 10, 0, 0, 0xDC00, 0}, - {5, 10, 0, 0, 0xDFFF, 0}, - - {5, 10, 1, 1, 0xD800, 1}, - {5, 10, 1, 1, 0xDBFF, 1}, - {5, 10, 1, 1, 0xDC00, 1}, - {5, 10, 1, 1, 0xDFFF, 1}, - - {5, 10, 2, 3, 0xD800, 2}, - {5, 10, 2, 3, 0xDBFF, 2}, - {5, 10, 2, 3, 0xDC00, 2}, - {5, 10, 2, 3, 0xDFFF, 2}, - - // dont replace anything, just show the surrogate pair - {5, 10, 3, 6, u'b', 0}, + const char16_t input[] = u"b\u0448\uAAAA\U0010AAAA"; + const unsigned char expected[] = "b\u0448\uAAAA\U0010AAAA"; + static_assert (array_size (input) == 6, ""); + static_assert (array_size (expected) == 11, ""); + + InternT in[array_size (input)]; + ExternT exp[array_size (expected)]; + copy (begin (input), end (input), begin (in)); + copy (begin (expected), end (expected), begin (exp)); + VERIFY (char_traits::length (in) == 5); + VERIFY (char_traits::length (exp) == 10); + + test_offsets_error offsets[] = { + {3, 6, 0, 0, 0xD800, 0}, + {3, 6, 0, 0, 0xDBFF, 0}, + {3, 6, 0, 0, 0xDC00, 0}, + {3, 6, 0, 0, 0xDFFF, 0}, + + {3, 6, 1, 1, 0xD800, 1}, + {3, 6, 1, 1, 0xDBFF, 1}, + {3, 6, 1, 1, 0xDC00, 1}, + {3, 6, 1, 1, 0xDFFF, 1}, + + {3, 6, 2, 3, 0xD800, 2}, + {3, 6, 2, 3, 0xDBFF, 2}, + {3, 6, 2, 3, 0xDC00, 2}, + {3, 6, 2, 3, 0xDFFF, 2}, // make the leading surrogate a trailing one {5, 10, 3, 6, 0xDC00, 3}, @@ -1206,6 +1380,9 @@ ucs2_to_utf8_out_error (const std::codecvt &cvt) // make the trailing surrogate a BMP char {5, 10, 3, 6, u'z', 4}, + // don't replace anything in the test cases bellow, just show the surrogate + // pair (fourth CP) fully or partially + {5, 10, 3, 6, u'b', 0}, {5, 7, 3, 6, u'b', 0}, // no space for fourth CP {5, 8, 3, 6, u'b', 0}, // no space for fourth CP {5, 9, 3, 6, u'b', 0}, // no space for fourth CP @@ -1214,23 +1391,21 @@ ucs2_to_utf8_out_error (const std::codecvt &cvt) {4, 7, 3, 6, u'b', 0}, // incomplete fourth CP, and no space for it {4, 8, 3, 6, u'b', 0}, // incomplete fourth CP, and no space for it {4, 9, 3, 6, u'b', 0}, // incomplete fourth CP, and no space for it - }; for (auto t : offsets) { - CharT in[array_size (valid_in)] = {}; - char out[array_size (exp) - 1] = {}; + ExternT out[array_size (exp) - 1] = {}; VERIFY (t.in_size <= array_size (in)); VERIFY (t.out_size <= array_size (out)); VERIFY (t.expected_in_next <= t.in_size); VERIFY (t.expected_out_next <= t.out_size); - copy (begin (valid_in), end (valid_in), begin (in)); + auto old_char = in[t.replace_pos]; in[t.replace_pos] = t.replace_char; auto state = mbstate_t{}; - auto in_next = (const CharT *) nullptr; - auto out_next = (char *) nullptr; + auto in_next = (const InternT *) nullptr; + auto out_next = (ExternT *) nullptr; auto res = codecvt_base::result (); res = cvt.out (state, in, in + t.in_size, in_next, out, out + t.out_size, @@ -1238,25 +1413,793 @@ ucs2_to_utf8_out_error (const std::codecvt &cvt) VERIFY (res == cvt.error); VERIFY (in_next == in + t.expected_in_next); VERIFY (out_next == out + t.expected_out_next); - VERIFY (char_traits::compare (out, exp, t.expected_out_next) == 0); + VERIFY (char_traits::compare (out, exp, t.expected_out_next) + == 0); if (t.expected_out_next < array_size (out)) VERIFY (out[t.expected_out_next] == 0); + + in[t.replace_pos] = old_char; } } -template +template void -ucs2_to_utf8_out (const std::codecvt &cvt) +ucs2_to_utf8_out (const std::codecvt &cvt) { ucs2_to_utf8_out_ok (cvt); ucs2_to_utf8_out_partial (cvt); ucs2_to_utf8_out_error (cvt); } -template +template void -test_utf8_ucs2_cvts (const std::codecvt &cvt) +test_utf8_ucs2_cvt (const std::codecvt &cvt) { utf8_to_ucs2_in (cvt); ucs2_to_utf8_out (cvt); } + +enum utf16_endianess +{ + utf16_big_endian, + utf16_little_endian +}; + +template +Iter2 +utf16_to_bytes (Iter1 f, Iter1 l, Iter2 o, utf16_endianess e) +{ + if (e == utf16_big_endian) + for (; f != l; ++f) + { + *o++ = (*f >> 8) & 0xFF; + *o++ = *f & 0xFF; + } + else + for (; f != l; ++f) + { + *o++ = *f & 0xFF; + *o++ = (*f >> 8) & 0xFF; + } + return o; +} + +template +void +utf16_to_utf32_in_ok (const std::codecvt &cvt, + utf16_endianess endianess) +{ + using namespace std; + const char16_t input[] = u"b\u0448\uAAAA\U0010AAAA"; + const char32_t expected[] = U"b\u0448\uAAAA\U0010AAAA"; + static_assert (array_size (input) == 6, ""); + static_assert (array_size (expected) == 5, ""); + + char in[array_size (input) * 2]; + InternT exp[array_size (expected)]; + utf16_to_bytes (begin (input), end (input), begin (in), endianess); + copy (begin (expected), end (expected), begin (exp)); + + test_offsets_ok offsets[] = {{0, 0}, {2, 1}, {4, 2}, {6, 3}, {10, 4}}; + for (auto t : offsets) + { + InternT out[array_size (exp) - 1] = {}; + VERIFY (t.in_size <= array_size (in)); + VERIFY (t.out_size <= array_size (out)); + auto state = mbstate_t{}; + auto in_next = (const char *) nullptr; + auto out_next = (InternT *) nullptr; + auto res = codecvt_base::result (); + + res = cvt.in (state, in, in + t.in_size, in_next, out, out + t.out_size, + out_next); + VERIFY (res == cvt.ok); + VERIFY (in_next == in + t.in_size); + VERIFY (out_next == out + t.out_size); + VERIFY (char_traits::compare (out, exp, t.out_size) == 0); + if (t.out_size < array_size (out)) + VERIFY (out[t.out_size] == 0); + } + + for (auto t : offsets) + { + InternT out[array_size (exp)] = {}; + VERIFY (t.in_size <= array_size (in)); + VERIFY (t.out_size <= array_size (out)); + auto state = mbstate_t{}; + auto in_next = (const char *) nullptr; + auto out_next = (InternT *) nullptr; + auto res = codecvt_base::result (); + + res + = cvt.in (state, in, in + t.in_size, in_next, out, end (out), out_next); + VERIFY (res == cvt.ok); + VERIFY (in_next == in + t.in_size); + VERIFY (out_next == out + t.out_size); + VERIFY (char_traits::compare (out, exp, t.out_size) == 0); + if (t.out_size < array_size (out)) + VERIFY (out[t.out_size] == 0); + } +} + +template +void +utf16_to_utf32_in_partial (const std::codecvt &cvt, + utf16_endianess endianess) +{ + using namespace std; + const char16_t input[] = u"b\u0448\uAAAA\U0010AAAA"; + const char32_t expected[] = U"b\u0448\uAAAA\U0010AAAA"; + static_assert (array_size (input) == 6, ""); + static_assert (array_size (expected) == 5, ""); + + char in[array_size (input) * 2]; + InternT exp[array_size (expected)]; + auto in_iter = begin (in); + utf16_to_bytes (begin (input), end (input), begin (in), endianess); + copy (begin (expected), end (expected), begin (exp)); + + test_offsets_partial offsets[] = { + {2, 0, 0, 0}, // no space for first CP + {1, 1, 0, 0}, // incomplete first CP + {1, 0, 0, 0}, // incomplete first CP, and no space for it + + {4, 1, 2, 1}, // no space for second CP + {3, 2, 2, 1}, // incomplete second CP + {3, 1, 2, 1}, // incomplete second CP, and no space for it + + {6, 2, 4, 2}, // no space for third CP + {5, 3, 4, 2}, // incomplete third CP + {5, 2, 4, 2}, // incomplete third CP, and no space for it + + {10, 3, 6, 3}, // no space for fourth CP + {7, 4, 6, 3}, // incomplete fourth CP + {8, 4, 6, 3}, // incomplete fourth CP + {9, 4, 6, 3}, // incomplete fourth CP + {7, 3, 6, 3}, // incomplete fourth CP, and no space for it + {8, 3, 6, 3}, // incomplete fourth CP, and no space for it + {9, 3, 6, 3}, // incomplete fourth CP, and no space for it + }; + + for (auto t : offsets) + { + InternT out[array_size (exp) - 1] = {}; + VERIFY (t.in_size <= array_size (in)); + VERIFY (t.out_size <= array_size (out)); + VERIFY (t.expected_in_next <= t.in_size); + VERIFY (t.expected_out_next <= t.out_size); + auto state = mbstate_t{}; + auto in_next = (const char *) nullptr; + auto out_next = (InternT *) nullptr; + auto res = codecvt_base::result (); + + res = cvt.in (state, in, in + t.in_size, in_next, out, out + t.out_size, + out_next); + VERIFY (res == cvt.partial); + VERIFY (in_next == in + t.expected_in_next); + VERIFY (out_next == out + t.expected_out_next); + VERIFY (char_traits::compare (out, exp, t.expected_out_next) + == 0); + if (t.expected_out_next < array_size (out)) + VERIFY (out[t.expected_out_next] == 0); + } +} + +template +void +utf16_to_utf32_in_error (const std::codecvt &cvt, + utf16_endianess endianess) +{ + using namespace std; + char16_t input[] = u"b\u0448\uAAAA\U0010AAAA"; + const char32_t expected[] = U"b\u0448\uAAAA\U0010AAAA"; + static_assert (array_size (input) == 6, ""); + static_assert (array_size (expected) == 5, ""); + + InternT exp[array_size (expected)]; + copy (begin (expected), end (expected), begin (exp)); + + // The only possible error in UTF-16 is unpaired surrogate code units. + // So we replace valid code points (scalar values) with lone surrogate CU. + test_offsets_error offsets[] = { + {10, 4, 0, 0, 0xD800, 0}, + {10, 4, 0, 0, 0xDBFF, 0}, + {10, 4, 0, 0, 0xDC00, 0}, + {10, 4, 0, 0, 0xDFFF, 0}, + + {10, 4, 2, 1, 0xD800, 1}, + {10, 4, 2, 1, 0xDBFF, 1}, + {10, 4, 2, 1, 0xDC00, 1}, + {10, 4, 2, 1, 0xDFFF, 1}, + + {10, 4, 4, 2, 0xD800, 2}, + {10, 4, 4, 2, 0xDBFF, 2}, + {10, 4, 4, 2, 0xDC00, 2}, + {10, 4, 4, 2, 0xDFFF, 2}, + + // make the leading surrogate a trailing one + {10, 4, 6, 3, 0xDC00, 3}, + {10, 4, 6, 3, 0xDFFF, 3}, + + // make the trailing surrogate a leading one + {10, 4, 6, 3, 0xD800, 4}, + {10, 4, 6, 3, 0xDBFF, 4}, + + // make the trailing surrogate a BMP char + {10, 4, 6, 3, u'z', 4}, + }; + + for (auto t : offsets) + { + char in[array_size (input) * 2]; + InternT out[array_size (exp) - 1] = {}; + VERIFY (t.in_size <= array_size (in)); + VERIFY (t.out_size <= array_size (out)); + VERIFY (t.expected_in_next <= t.in_size); + VERIFY (t.expected_out_next <= t.out_size); + auto old_char = input[t.replace_pos]; + input[t.replace_pos] = t.replace_char; // replace in input, not in in + utf16_to_bytes (begin (input), end (input), begin (in), endianess); + + auto state = mbstate_t{}; + auto in_next = (const char *) nullptr; + auto out_next = (InternT *) nullptr; + auto res = codecvt_base::result (); + + res = cvt.in (state, in, in + t.in_size, in_next, out, out + t.out_size, + out_next); + VERIFY (res == cvt.error); + VERIFY (in_next == in + t.expected_in_next); + VERIFY (out_next == out + t.expected_out_next); + VERIFY (char_traits::compare (out, exp, t.expected_out_next) + == 0); + if (t.expected_out_next < array_size (out)) + VERIFY (out[t.expected_out_next] == 0); + + input[t.replace_pos] = old_char; + } +} + +template +void +utf32_to_utf16_out_ok (const std::codecvt &cvt, + utf16_endianess endianess) +{ + using namespace std; + const char32_t input[] = U"b\u0448\uAAAA\U0010AAAA"; + const char16_t expected[] = u"b\u0448\uAAAA\U0010AAAA"; + static_assert (array_size (input) == 5, ""); + static_assert (array_size (expected) == 6, ""); + + InternT in[array_size (input)]; + char exp[array_size (expected) * 2]; + copy (begin (input), end (input), begin (in)); + utf16_to_bytes (begin (expected), end (expected), begin (exp), endianess); + + const test_offsets_ok offsets[] = {{0, 0}, {1, 2}, {2, 4}, {3, 6}, {4, 10}}; + for (auto t : offsets) + { + char out[array_size (exp) - 2] = {}; + VERIFY (t.in_size <= array_size (in)); + VERIFY (t.out_size <= array_size (out)); + auto state = mbstate_t{}; + auto in_next = (const InternT *) nullptr; + auto out_next = (char *) nullptr; + auto res = codecvt_base::result (); + + res = cvt.out (state, in, in + t.in_size, in_next, out, out + t.out_size, + out_next); + VERIFY (res == cvt.ok); + VERIFY (in_next == in + t.in_size); + VERIFY (out_next == out + t.out_size); + VERIFY (char_traits::compare (out, exp, t.out_size) == 0); + if (t.out_size < array_size (out)) + VERIFY (out[t.out_size] == 0); + } +} + +template +void +utf32_to_utf16_out_partial (const std::codecvt &cvt, + utf16_endianess endianess) +{ + using namespace std; + const char32_t input[] = U"b\u0448\uAAAA\U0010AAAA"; + const char16_t expected[] = u"b\u0448\uAAAA\U0010AAAA"; + static_assert (array_size (input) == 5, ""); + static_assert (array_size (expected) == 6, ""); + + InternT in[array_size (input)]; + char exp[array_size (expected) * 2]; + copy (begin (input), end (input), begin (in)); + utf16_to_bytes (begin (expected), end (expected), begin (exp), endianess); + + const test_offsets_partial offsets[] = { + {1, 0, 0, 0}, // no space for first CP + {1, 1, 0, 0}, // no space for first CP + + {2, 2, 1, 2}, // no space for second CP + {2, 3, 1, 2}, // no space for second CP + + {3, 4, 2, 4}, // no space for third CP + {3, 5, 2, 4}, // no space for third CP + + {4, 6, 3, 6}, // no space for fourth CP + {4, 7, 3, 6}, // no space for fourth CP + {4, 8, 3, 6}, // no space for fourth CP + {4, 9, 3, 6}, // no space for fourth CP + }; + for (auto t : offsets) + { + char out[array_size (exp) - 2] = {}; + VERIFY (t.in_size <= array_size (in)); + VERIFY (t.out_size <= array_size (out)); + VERIFY (t.expected_in_next <= t.in_size); + VERIFY (t.expected_out_next <= t.out_size); + auto state = mbstate_t{}; + auto in_next = (const InternT *) nullptr; + auto out_next = (char *) nullptr; + auto res = codecvt_base::result (); + + res = cvt.out (state, in, in + t.in_size, in_next, out, out + t.out_size, + out_next); + VERIFY (res == cvt.partial); + VERIFY (in_next == in + t.expected_in_next); + VERIFY (out_next == out + t.expected_out_next); + VERIFY (char_traits::compare (out, exp, t.expected_out_next) == 0); + if (t.expected_out_next < array_size (out)) + VERIFY (out[t.expected_out_next] == 0); + } +} + +template +void +utf32_to_utf16_out_error (const std::codecvt &cvt, + utf16_endianess endianess) +{ + using namespace std; + const char32_t input[] = U"b\u0448\uAAAA\U0010AAAA"; + const char16_t expected[] = u"b\u0448\uAAAA\U0010AAAA"; + static_assert (array_size (input) == 5, ""); + static_assert (array_size (expected) == 6, ""); + + InternT in[array_size (input)]; + char exp[array_size (expected) * 2]; + copy (begin (input), end (input), begin (in)); + utf16_to_bytes (begin (expected), end (expected), begin (exp), endianess); + + test_offsets_error offsets[] = { + + // Surrogate CP + {4, 10, 0, 0, 0xD800, 0}, + {4, 10, 1, 2, 0xDBFF, 1}, + {4, 10, 2, 4, 0xDC00, 2}, + {4, 10, 3, 6, 0xDFFF, 3}, + + // CP out of range + {4, 10, 0, 0, 0x00110000, 0}, + {4, 10, 1, 2, 0x00110000, 1}, + {4, 10, 2, 4, 0x00110000, 2}, + {4, 10, 3, 6, 0x00110000, 3}}; + + for (auto t : offsets) + { + char out[array_size (exp) - 2] = {}; + VERIFY (t.in_size <= array_size (in)); + VERIFY (t.out_size <= array_size (out)); + VERIFY (t.expected_in_next <= t.in_size); + VERIFY (t.expected_out_next <= t.out_size); + auto old_char = in[t.replace_pos]; + in[t.replace_pos] = t.replace_char; + + auto state = mbstate_t{}; + auto in_next = (const InternT *) nullptr; + auto out_next = (char *) nullptr; + auto res = codecvt_base::result (); + + res = cvt.out (state, in, in + t.in_size, in_next, out, out + t.out_size, + out_next); + VERIFY (res == cvt.error); + VERIFY (in_next == in + t.expected_in_next); + VERIFY (out_next == out + t.expected_out_next); + VERIFY (char_traits::compare (out, exp, t.expected_out_next) == 0); + if (t.expected_out_next < array_size (out)) + VERIFY (out[t.expected_out_next] == 0); + + in[t.replace_pos] = old_char; + } +} + +template +void +test_utf16_utf32_cvt (const std::codecvt &cvt, + utf16_endianess endianess) +{ + utf16_to_utf32_in_ok (cvt, endianess); + utf16_to_utf32_in_partial (cvt, endianess); + utf16_to_utf32_in_error (cvt, endianess); + utf32_to_utf16_out_ok (cvt, endianess); + utf32_to_utf16_out_partial (cvt, endianess); + utf32_to_utf16_out_error (cvt, endianess); +} + +template +void +utf16_to_ucs2_in_ok (const std::codecvt &cvt, + utf16_endianess endianess) +{ + using namespace std; + const char16_t input[] = u"b\u0448\uAAAA"; + const char16_t expected[] = u"b\u0448\uAAAA"; + static_assert (array_size (input) == 4, ""); + static_assert (array_size (expected) == 4, ""); + + char in[array_size (input) * 2]; + InternT exp[array_size (expected)]; + utf16_to_bytes (begin (input), end (input), begin (in), endianess); + copy (begin (expected), end (expected), begin (exp)); + + test_offsets_ok offsets[] = {{0, 0}, {2, 1}, {4, 2}, {6, 3}}; + for (auto t : offsets) + { + InternT out[array_size (exp) - 1] = {}; + VERIFY (t.in_size <= array_size (in)); + VERIFY (t.out_size <= array_size (out)); + auto state = mbstate_t{}; + auto in_next = (const char *) nullptr; + auto out_next = (InternT *) nullptr; + auto res = codecvt_base::result (); + + res = cvt.in (state, in, in + t.in_size, in_next, out, out + t.out_size, + out_next); + VERIFY (res == cvt.ok); + VERIFY (in_next == in + t.in_size); + VERIFY (out_next == out + t.out_size); + VERIFY (char_traits::compare (out, exp, t.out_size) == 0); + if (t.out_size < array_size (out)) + VERIFY (out[t.out_size] == 0); + } + + for (auto t : offsets) + { + InternT out[array_size (exp)] = {}; + VERIFY (t.in_size <= array_size (in)); + VERIFY (t.out_size <= array_size (out)); + auto state = mbstate_t{}; + auto in_next = (const char *) nullptr; + auto out_next = (InternT *) nullptr; + auto res = codecvt_base::result (); + + res + = cvt.in (state, in, in + t.in_size, in_next, out, end (out), out_next); + VERIFY (res == cvt.ok); + VERIFY (in_next == in + t.in_size); + VERIFY (out_next == out + t.out_size); + VERIFY (char_traits::compare (out, exp, t.out_size) == 0); + if (t.out_size < array_size (out)) + VERIFY (out[t.out_size] == 0); + } +} + +template +void +utf16_to_ucs2_in_partial (const std::codecvt &cvt, + utf16_endianess endianess) +{ + using namespace std; + const char16_t input[] = u"b\u0448\uAAAA"; + const char16_t expected[] = u"b\u0448\uAAAA"; + static_assert (array_size (input) == 4, ""); + static_assert (array_size (expected) == 4, ""); + + char in[array_size (input) * 2]; + InternT exp[array_size (expected)]; + auto in_iter = begin (in); + utf16_to_bytes (begin (input), end (input), begin (in), endianess); + copy (begin (expected), end (expected), begin (exp)); + + test_offsets_partial offsets[] = { + {2, 0, 0, 0}, // no space for first CP + {1, 1, 0, 0}, // incomplete first CP + {1, 0, 0, 0}, // incomplete first CP, and no space for it + + {4, 1, 2, 1}, // no space for second CP + {3, 2, 2, 1}, // incomplete second CP + {3, 1, 2, 1}, // incomplete second CP, and no space for it + + {6, 2, 4, 2}, // no space for third CP + {5, 3, 4, 2}, // incomplete third CP + {5, 2, 4, 2}, // incomplete third CP, and no space for it + }; + + for (auto t : offsets) + { + InternT out[array_size (exp) - 1] = {}; + VERIFY (t.in_size <= array_size (in)); + VERIFY (t.out_size <= array_size (out)); + VERIFY (t.expected_in_next <= t.in_size); + VERIFY (t.expected_out_next <= t.out_size); + auto state = mbstate_t{}; + auto in_next = (const char *) nullptr; + auto out_next = (InternT *) nullptr; + auto res = codecvt_base::result (); + + res = cvt.in (state, in, in + t.in_size, in_next, out, out + t.out_size, + out_next); + VERIFY (res == cvt.partial); + VERIFY (in_next == in + t.expected_in_next); + VERIFY (out_next == out + t.expected_out_next); + VERIFY (char_traits::compare (out, exp, t.expected_out_next) + == 0); + if (t.expected_out_next < array_size (out)) + VERIFY (out[t.expected_out_next] == 0); + } +} + +template +void +utf16_to_ucs2_in_error (const std::codecvt &cvt, + utf16_endianess endianess) +{ + using namespace std; + char16_t input[] = u"b\u0448\uAAAA\U0010AAAA"; + const char16_t expected[] = u"b\u0448\uAAAA\U0010AAAA"; + static_assert (array_size (input) == 6, ""); + static_assert (array_size (expected) == 6, ""); + + InternT exp[array_size (expected)]; + copy (begin (expected), end (expected), begin (exp)); + + // The only possible error in UTF-16 is unpaired surrogate code units. + // Additionally, because the target encoding is UCS-2, a proper pair of + // surrogates is also error. Simply, any surrogate CU is error. + test_offsets_error offsets[] = { + {6, 3, 0, 0, 0xD800, 0}, + {6, 3, 0, 0, 0xDBFF, 0}, + {6, 3, 0, 0, 0xDC00, 0}, + {6, 3, 0, 0, 0xDFFF, 0}, + + {6, 3, 2, 1, 0xD800, 1}, + {6, 3, 2, 1, 0xDBFF, 1}, + {6, 3, 2, 1, 0xDC00, 1}, + {6, 3, 2, 1, 0xDFFF, 1}, + + {6, 3, 4, 2, 0xD800, 2}, + {6, 3, 4, 2, 0xDBFF, 2}, + {6, 3, 4, 2, 0xDC00, 2}, + {6, 3, 4, 2, 0xDFFF, 2}, + + // make the leading surrogate a trailing one + {10, 5, 6, 3, 0xDC00, 3}, + {10, 5, 6, 3, 0xDFFF, 3}, + + // make the trailing surrogate a leading one + {10, 5, 6, 3, 0xD800, 4}, + {10, 5, 6, 3, 0xDBFF, 4}, + + // make the trailing surrogate a BMP char + {10, 5, 6, 3, u'z', 4}, + + // don't replace anything in the test cases bellow, just show the surrogate + // pair (fourth CP) fully or partially (just the first surrogate) + {10, 5, 6, 3, u'b', 0}, + {8, 5, 6, 3, u'b', 0}, + {9, 5, 6, 3, u'b', 0}, + + {10, 4, 6, 3, u'b', 0}, + {8, 4, 6, 3, u'b', 0}, + {9, 4, 6, 3, u'b', 0}, + }; + + for (auto t : offsets) + { + char in[array_size (input) * 2]; + InternT out[array_size (exp) - 1] = {}; + VERIFY (t.in_size <= array_size (in)); + VERIFY (t.out_size <= array_size (out)); + VERIFY (t.expected_in_next <= t.in_size); + VERIFY (t.expected_out_next <= t.out_size); + auto old_char = input[t.replace_pos]; + input[t.replace_pos] = t.replace_char; // replace in input, not in in + utf16_to_bytes (begin (input), end (input), begin (in), endianess); + + auto state = mbstate_t{}; + auto in_next = (const char *) nullptr; + auto out_next = (InternT *) nullptr; + auto res = codecvt_base::result (); + + res = cvt.in (state, in, in + t.in_size, in_next, out, out + t.out_size, + out_next); + VERIFY (res == cvt.error); + VERIFY (in_next == in + t.expected_in_next); + VERIFY (out_next == out + t.expected_out_next); + VERIFY (char_traits::compare (out, exp, t.expected_out_next) + == 0); + if (t.expected_out_next < array_size (out)) + VERIFY (out[t.expected_out_next] == 0); + + input[t.replace_pos] = old_char; + } +} + +template +void +ucs2_to_utf16_out_ok (const std::codecvt &cvt, + utf16_endianess endianess) +{ + using namespace std; + const char16_t input[] = u"b\u0448\uAAAA"; + const char16_t expected[] = u"b\u0448\uAAAA"; + static_assert (array_size (input) == 4, ""); + static_assert (array_size (expected) == 4, ""); + + InternT in[array_size (input)]; + char exp[array_size (expected) * 2]; + copy (begin (input), end (input), begin (in)); + utf16_to_bytes (begin (expected), end (expected), begin (exp), endianess); + + const test_offsets_ok offsets[] = {{0, 0}, {1, 2}, {2, 4}, {3, 6}}; + for (auto t : offsets) + { + char out[array_size (exp) - 2] = {}; + VERIFY (t.in_size <= array_size (in)); + VERIFY (t.out_size <= array_size (out)); + auto state = mbstate_t{}; + auto in_next = (const InternT *) nullptr; + auto out_next = (char *) nullptr; + auto res = codecvt_base::result (); + + res = cvt.out (state, in, in + t.in_size, in_next, out, out + t.out_size, + out_next); + VERIFY (res == cvt.ok); + VERIFY (in_next == in + t.in_size); + VERIFY (out_next == out + t.out_size); + VERIFY (char_traits::compare (out, exp, t.out_size) == 0); + if (t.out_size < array_size (out)) + VERIFY (out[t.out_size] == 0); + } +} + +template +void +ucs2_to_utf16_out_partial (const std::codecvt &cvt, + utf16_endianess endianess) +{ + using namespace std; + const char16_t input[] = u"b\u0448\uAAAA"; + const char16_t expected[] = u"b\u0448\uAAAA"; + static_assert (array_size (input) == 4, ""); + static_assert (array_size (expected) == 4, ""); + + InternT in[array_size (input)]; + char exp[array_size (expected) * 2]; + copy (begin (input), end (input), begin (in)); + utf16_to_bytes (begin (expected), end (expected), begin (exp), endianess); + + const test_offsets_partial offsets[] = { + {1, 0, 0, 0}, // no space for first CP + {1, 1, 0, 0}, // no space for first CP + + {2, 2, 1, 2}, // no space for second CP + {2, 3, 1, 2}, // no space for second CP + + {3, 4, 2, 4}, // no space for third CP + {3, 5, 2, 4}, // no space for third CP + }; + for (auto t : offsets) + { + char out[array_size (exp) - 2] = {}; + VERIFY (t.in_size <= array_size (in)); + VERIFY (t.out_size <= array_size (out)); + VERIFY (t.expected_in_next <= t.in_size); + VERIFY (t.expected_out_next <= t.out_size); + auto state = mbstate_t{}; + auto in_next = (const InternT *) nullptr; + auto out_next = (char *) nullptr; + auto res = codecvt_base::result (); + + res = cvt.out (state, in, in + t.in_size, in_next, out, out + t.out_size, + out_next); + VERIFY (res == cvt.partial); + VERIFY (in_next == in + t.expected_in_next); + VERIFY (out_next == out + t.expected_out_next); + VERIFY (char_traits::compare (out, exp, t.expected_out_next) == 0); + if (t.expected_out_next < array_size (out)) + VERIFY (out[t.expected_out_next] == 0); + } +} + +template +void +ucs2_to_utf16_out_error (const std::codecvt &cvt, + utf16_endianess endianess) +{ + using namespace std; + const char16_t input[] = u"b\u0448\uAAAA\U0010AAAA"; + const char16_t expected[] = u"b\u0448\uAAAA\U0010AAAA"; + static_assert (array_size (input) == 6, ""); + static_assert (array_size (expected) == 6, ""); + + InternT in[array_size (input)]; + char exp[array_size (expected) * 2]; + copy (begin (input), end (input), begin (in)); + utf16_to_bytes (begin (expected), end (expected), begin (exp), endianess); + + test_offsets_error offsets[] = { + {3, 6, 0, 0, 0xD800, 0}, + {3, 6, 0, 0, 0xDBFF, 0}, + {3, 6, 0, 0, 0xDC00, 0}, + {3, 6, 0, 0, 0xDFFF, 0}, + + {3, 6, 1, 2, 0xD800, 1}, + {3, 6, 1, 2, 0xDBFF, 1}, + {3, 6, 1, 2, 0xDC00, 1}, + {3, 6, 1, 2, 0xDFFF, 1}, + + {3, 6, 2, 4, 0xD800, 2}, + {3, 6, 2, 4, 0xDBFF, 2}, + {3, 6, 2, 4, 0xDC00, 2}, + {3, 6, 2, 4, 0xDFFF, 2}, + + // make the leading surrogate a trailing one + {5, 10, 3, 6, 0xDC00, 3}, + {5, 10, 3, 6, 0xDFFF, 3}, + + // make the trailing surrogate a leading one + {5, 10, 3, 6, 0xD800, 4}, + {5, 10, 3, 6, 0xDBFF, 4}, + + // make the trailing surrogate a BMP char + {5, 10, 3, 6, u'z', 4}, + + // don't replace anything in the test cases bellow, just show the surrogate + // pair (fourth CP) fully or partially (just the first surrogate) + {5, 10, 3, 6, u'b', 0}, + {5, 8, 3, 6, u'b', 0}, + {5, 9, 3, 6, u'b', 0}, + + {4, 10, 3, 6, u'b', 0}, + {4, 8, 3, 6, u'b', 0}, + {4, 9, 3, 6, u'b', 0}, + }; + + for (auto t : offsets) + { + char out[array_size (exp) - 2] = {}; + VERIFY (t.in_size <= array_size (in)); + VERIFY (t.out_size <= array_size (out)); + VERIFY (t.expected_in_next <= t.in_size); + VERIFY (t.expected_out_next <= t.out_size); + auto old_char = in[t.replace_pos]; + in[t.replace_pos] = t.replace_char; + + auto state = mbstate_t{}; + auto in_next = (const InternT *) nullptr; + auto out_next = (char *) nullptr; + auto res = codecvt_base::result (); + + res = cvt.out (state, in, in + t.in_size, in_next, out, out + t.out_size, + out_next); + VERIFY (res == cvt.error); + VERIFY (in_next == in + t.expected_in_next); + VERIFY (out_next == out + t.expected_out_next); + VERIFY (char_traits::compare (out, exp, t.expected_out_next) == 0); + if (t.expected_out_next < array_size (out)) + VERIFY (out[t.expected_out_next] == 0); + + in[t.replace_pos] = old_char; + } +} + +template +void +test_utf16_ucs2_cvt (const std::codecvt &cvt, + utf16_endianess endianess) +{ + utf16_to_ucs2_in_ok (cvt, endianess); + utf16_to_ucs2_in_partial (cvt, endianess); + utf16_to_ucs2_in_error (cvt, endianess); + ucs2_to_utf16_out_ok (cvt, endianess); + ucs2_to_utf16_out_partial (cvt, endianess); + ucs2_to_utf16_out_error (cvt, endianess); +} diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode_char8_t.cc b/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode_char8_t.cc new file mode 100644 index 00000000000..8ab5ba79f42 --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode_char8_t.cc @@ -0,0 +1,53 @@ +// Copyright (C) 2020-2023 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-do run { target c++11 } } +// { dg-require-cstdint "" } +// { dg-options "-fchar8_t" } + +#include "codecvt_unicode.h" + +using namespace std; + +void +test_utf8_utf32_codecvts () +{ + using codecvt_c32_c8 = codecvt; + auto &loc_c = locale::classic (); + VERIFY (has_facet (loc_c)); + + auto &cvt = use_facet (loc_c); + test_utf8_utf32_cvt (cvt); +} + +void +test_utf8_utf16_codecvts () +{ + using codecvt_c16_c8 = codecvt; + auto &loc_c = locale::classic (); + VERIFY (has_facet (loc_c)); + + auto &cvt = use_facet (loc_c); + test_utf8_utf16_cvt (cvt); +} + +int +main () +{ + test_utf8_utf32_codecvts (); + test_utf8_utf16_codecvts (); +} diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode_wchar_t.cc b/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode_wchar_t.cc index 4fd1bfec63a..d6e5b20e89b 100644 --- a/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode_wchar_t.cc +++ b/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode_wchar_t.cc @@ -28,7 +28,7 @@ test_utf8_utf32_codecvts () { #if __SIZEOF_WCHAR_T__ == 4 codecvt_utf8 cvt; - test_utf8_utf32_codecvts (cvt); + test_utf8_utf32_cvt (cvt); #endif } @@ -37,7 +37,7 @@ test_utf8_utf16_codecvts () { #if __SIZEOF_WCHAR_T__ >= 2 codecvt_utf8_utf16 cvt; - test_utf8_utf16_cvts (cvt); + test_utf8_utf16_cvt (cvt); #endif } @@ -46,7 +46,31 @@ test_utf8_ucs2_codecvts () { #if __SIZEOF_WCHAR_T__ == 2 codecvt_utf8 cvt; - test_utf8_ucs2_cvts (cvt); + test_utf8_ucs2_cvt (cvt); +#endif +} + +void +test_utf16_utf32_codecvts () +{ +#if __SIZEOF_WCHAR_T__ == 4 + codecvt_utf16 cvt3; + test_utf16_utf32_cvt (cvt3, utf16_big_endian); + + codecvt_utf16 cvt4; + test_utf16_utf32_cvt (cvt4, utf16_little_endian); +#endif +} + +void +test_utf16_ucs2_codecvts () +{ +#if __SIZEOF_WCHAR_T__ == 2 + codecvt_utf16 cvt3; + test_utf16_ucs2_cvt (cvt3, utf16_big_endian); + + codecvt_utf16 cvt4; + test_utf16_ucs2_cvt (cvt4, utf16_little_endian); #endif } @@ -56,4 +80,6 @@ main () test_utf8_utf32_codecvts (); test_utf8_utf16_codecvts (); test_utf8_ucs2_codecvts (); + test_utf16_utf32_codecvts (); + test_utf16_ucs2_codecvts (); } diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_utf16/79980.cc b/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_utf16/79980.cc index 970d2bc1113..f3f802f7c98 100644 --- a/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_utf16/79980.cc +++ b/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_utf16/79980.cc @@ -83,7 +83,7 @@ test06() const char src[] = "\0\x61\xAB\xCD"; Conv conv("to_bytes failed", u"from_bytes failed"); std::u16string result = conv.from_bytes(src, src+3); // incomplete character - VERIFY( result == u"from_bytes failed" ); + VERIFY( result == u"\u0061" ); VERIFY( conv.converted() == 2 ); } commit 9433e308e0ca48822aa5e3a9875aac1f86cbac72 Author: Dimitrij Mijoski Date: Wed Oct 18 12:52:20 2023 +0200 libstdc++: testsuite: Enhance codecvt_unicode with tests for length() We can test codecvt::length() with the same data that we test codecvt::in(). For each call of in() we add another call to length(). Some additional small cosmentic changes are applied. libstdc++-v3/ChangeLog: * testsuite/22_locale/codecvt/codecvt_unicode.h: Test length() (cherry picked from commit 59a7d38997ec4d8a606c97b00e1a8b697edd1316) diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.h b/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.h index d3ae42fac13..42270c50f14 100644 --- a/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.h +++ b/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.h @@ -17,7 +17,6 @@ #include #include -#include #include struct test_offsets_ok @@ -79,6 +78,11 @@ utf8_to_utf32_in_ok (const std::codecvt &cvt) VERIFY (char_traits::compare (out, exp, t.out_size) == 0); if (t.out_size < array_size (out)) VERIFY (out[t.out_size] == 0); + + state = {}; + auto len = cvt.length (state, in, in + t.in_size, t.out_size); + VERIFY (len >= 0); + VERIFY (static_cast (len) == t.in_size); } for (auto t : offsets) @@ -99,6 +103,11 @@ utf8_to_utf32_in_ok (const std::codecvt &cvt) VERIFY (char_traits::compare (out, exp, t.out_size) == 0); if (t.out_size < array_size (out)) VERIFY (out[t.out_size] == 0); + + state = {}; + auto len = cvt.length (state, in, in + t.in_size, array_size (out)); + VERIFY (len >= 0); + VERIFY (static_cast (len) == t.in_size); } } @@ -163,6 +172,11 @@ utf8_to_utf32_in_partial (const std::codecvt &cvt) == 0); if (t.expected_out_next < array_size (out)) VERIFY (out[t.expected_out_next] == 0); + + state = {}; + auto len = cvt.length (state, in, in + t.in_size, t.out_size); + VERIFY (len >= 0); + VERIFY (static_cast (len) == t.expected_in_next); } } @@ -303,6 +317,11 @@ utf8_to_utf32_in_error (const std::codecvt &cvt) if (t.expected_out_next < array_size (out)) VERIFY (out[t.expected_out_next] == 0); + state = {}; + auto len = cvt.length (state, in, in + t.in_size, t.out_size); + VERIFY (len >= 0); + VERIFY (static_cast (len) == t.expected_in_next); + in[t.replace_pos] = old_char; } } @@ -334,7 +353,7 @@ utf32_to_utf8_out_ok (const std::codecvt &cvt) VERIFY (char_traits::length (in) == 4); VERIFY (char_traits::length (exp) == 10); - const test_offsets_ok offsets[] = {{0, 0}, {1, 1}, {2, 3}, {3, 6}, {4, 10}}; + test_offsets_ok offsets[] = {{0, 0}, {1, 1}, {2, 3}, {3, 6}, {4, 10}}; for (auto t : offsets) { ExternT out[array_size (exp) - 1] = {}; @@ -374,7 +393,7 @@ utf32_to_utf8_out_partial (const std::codecvt &cvt) VERIFY (char_traits::length (in) == 4); VERIFY (char_traits::length (exp) == 10); - const test_offsets_partial offsets[] = { + test_offsets_partial offsets[] = { {1, 0, 0, 0}, // no space for first CP {2, 1, 1, 1}, // no space for second CP @@ -528,6 +547,11 @@ utf8_to_utf16_in_ok (const std::codecvt &cvt) VERIFY (char_traits::compare (out, exp, t.out_size) == 0); if (t.out_size < array_size (out)) VERIFY (out[t.out_size] == 0); + + state = {}; + auto len = cvt.length (state, in, in + t.in_size, t.out_size); + VERIFY (len >= 0); + VERIFY (static_cast (len) == t.in_size); } for (auto t : offsets) @@ -548,6 +572,11 @@ utf8_to_utf16_in_ok (const std::codecvt &cvt) VERIFY (char_traits::compare (out, exp, t.out_size) == 0); if (t.out_size < array_size (out)) VERIFY (out[t.out_size] == 0); + + state = {}; + auto len = cvt.length (state, in, in + t.in_size, array_size (out)); + VERIFY (len >= 0); + VERIFY (static_cast (len) == t.in_size); } } @@ -617,6 +646,11 @@ utf8_to_utf16_in_partial (const std::codecvt &cvt) == 0); if (t.expected_out_next < array_size (out)) VERIFY (out[t.expected_out_next] == 0); + + state = {}; + auto len = cvt.length (state, in, in + t.in_size, t.out_size); + VERIFY (len >= 0); + VERIFY (static_cast (len) == t.expected_in_next); } } @@ -757,6 +791,11 @@ utf8_to_utf16_in_error (const std::codecvt &cvt) if (t.expected_out_next < array_size (out)) VERIFY (out[t.expected_out_next] == 0); + state = {}; + auto len = cvt.length (state, in, in + t.in_size, t.out_size); + VERIFY (len >= 0); + VERIFY (static_cast (len) == t.expected_in_next); + in[t.replace_pos] = old_char; } } @@ -788,7 +827,7 @@ utf16_to_utf8_out_ok (const std::codecvt &cvt) VERIFY (char_traits::length (in) == 5); VERIFY (char_traits::length (exp) == 10); - const test_offsets_ok offsets[] = {{0, 0}, {1, 1}, {2, 3}, {3, 6}, {5, 10}}; + test_offsets_ok offsets[] = {{0, 0}, {1, 1}, {2, 3}, {3, 6}, {5, 10}}; for (auto t : offsets) { ExternT out[array_size (exp) - 1] = {}; @@ -828,7 +867,7 @@ utf16_to_utf8_out_partial (const std::codecvt &cvt) VERIFY (char_traits::length (in) == 5); VERIFY (char_traits::length (exp) == 10); - const test_offsets_partial offsets[] = { + test_offsets_partial offsets[] = { {1, 0, 0, 0}, // no space for first CP {2, 1, 1, 1}, // no space for second CP @@ -1005,6 +1044,11 @@ utf8_to_ucs2_in_ok (const std::codecvt &cvt) VERIFY (char_traits::compare (out, exp, t.out_size) == 0); if (t.out_size < array_size (out)) VERIFY (out[t.out_size] == 0); + + state = {}; + auto len = cvt.length (state, in, in + t.in_size, t.out_size); + VERIFY (len >= 0); + VERIFY (static_cast (len) == t.in_size); } for (auto t : offsets) @@ -1025,6 +1069,11 @@ utf8_to_ucs2_in_ok (const std::codecvt &cvt) VERIFY (char_traits::compare (out, exp, t.out_size) == 0); if (t.out_size < array_size (out)) VERIFY (out[t.out_size] == 0); + + state = {}; + auto len = cvt.length (state, in, in + t.in_size, array_size (out)); + VERIFY (len >= 0); + VERIFY (static_cast (len) == t.in_size); } } @@ -1081,6 +1130,11 @@ utf8_to_ucs2_in_partial (const std::codecvt &cvt) == 0); if (t.expected_out_next < array_size (out)) VERIFY (out[t.expected_out_next] == 0); + + state = {}; + auto len = cvt.length (state, in, in + t.in_size, t.out_size); + VERIFY (len >= 0); + VERIFY (static_cast (len) == t.expected_in_next); } } @@ -1231,6 +1285,11 @@ utf8_to_ucs2_in_error (const std::codecvt &cvt) if (t.expected_out_next < array_size (out)) VERIFY (out[t.expected_out_next] == 0); + state = {}; + auto len = cvt.length (state, in, in + t.in_size, t.out_size); + VERIFY (len >= 0); + VERIFY (static_cast (len) == t.expected_in_next); + in[t.replace_pos] = old_char; } } @@ -1262,7 +1321,7 @@ ucs2_to_utf8_out_ok (const std::codecvt &cvt) VERIFY (char_traits::length (in) == 3); VERIFY (char_traits::length (exp) == 6); - const test_offsets_ok offsets[] = {{0, 0}, {1, 1}, {2, 3}, {3, 6}}; + test_offsets_ok offsets[] = {{0, 0}, {1, 1}, {2, 3}, {3, 6}}; for (auto t : offsets) { ExternT out[array_size (exp) - 1] = {}; @@ -1302,7 +1361,7 @@ ucs2_to_utf8_out_partial (const std::codecvt &cvt) VERIFY (char_traits::length (in) == 3); VERIFY (char_traits::length (exp) == 6); - const test_offsets_partial offsets[] = { + test_offsets_partial offsets[] = { {1, 0, 0, 0}, // no space for first CP {2, 1, 1, 1}, // no space for second CP @@ -1499,6 +1558,11 @@ utf16_to_utf32_in_ok (const std::codecvt &cvt, VERIFY (char_traits::compare (out, exp, t.out_size) == 0); if (t.out_size < array_size (out)) VERIFY (out[t.out_size] == 0); + + state = {}; + auto len = cvt.length (state, in, in + t.in_size, t.out_size); + VERIFY (len >= 0); + VERIFY (static_cast (len) == t.in_size); } for (auto t : offsets) @@ -1519,6 +1583,11 @@ utf16_to_utf32_in_ok (const std::codecvt &cvt, VERIFY (char_traits::compare (out, exp, t.out_size) == 0); if (t.out_size < array_size (out)) VERIFY (out[t.out_size] == 0); + + state = {}; + auto len = cvt.length (state, in, in + t.in_size, array_size (out)); + VERIFY (len >= 0); + VERIFY (static_cast (len) == t.in_size); } } @@ -1535,7 +1604,6 @@ utf16_to_utf32_in_partial (const std::codecvt &cvt, char in[array_size (input) * 2]; InternT exp[array_size (expected)]; - auto in_iter = begin (in); utf16_to_bytes (begin (input), end (input), begin (in), endianess); copy (begin (expected), end (expected), begin (exp)); @@ -1582,6 +1650,11 @@ utf16_to_utf32_in_partial (const std::codecvt &cvt, == 0); if (t.expected_out_next < array_size (out)) VERIFY (out[t.expected_out_next] == 0); + + state = {}; + auto len = cvt.length (state, in, in + t.in_size, t.out_size); + VERIFY (len >= 0); + VERIFY (static_cast (len) == t.expected_in_next); } } @@ -1656,6 +1729,11 @@ utf16_to_utf32_in_error (const std::codecvt &cvt, if (t.expected_out_next < array_size (out)) VERIFY (out[t.expected_out_next] == 0); + state = {}; + auto len = cvt.length (state, in, in + t.in_size, t.out_size); + VERIFY (len >= 0); + VERIFY (static_cast (len) == t.expected_in_next); + input[t.replace_pos] = old_char; } } @@ -1676,7 +1754,7 @@ utf32_to_utf16_out_ok (const std::codecvt &cvt, copy (begin (input), end (input), begin (in)); utf16_to_bytes (begin (expected), end (expected), begin (exp), endianess); - const test_offsets_ok offsets[] = {{0, 0}, {1, 2}, {2, 4}, {3, 6}, {4, 10}}; + test_offsets_ok offsets[] = {{0, 0}, {1, 2}, {2, 4}, {3, 6}, {4, 10}}; for (auto t : offsets) { char out[array_size (exp) - 2] = {}; @@ -1714,7 +1792,7 @@ utf32_to_utf16_out_partial (const std::codecvt &cvt, copy (begin (input), end (input), begin (in)); utf16_to_bytes (begin (expected), end (expected), begin (exp), endianess); - const test_offsets_partial offsets[] = { + test_offsets_partial offsets[] = { {1, 0, 0, 0}, // no space for first CP {1, 1, 0, 0}, // no space for first CP @@ -1858,6 +1936,11 @@ utf16_to_ucs2_in_ok (const std::codecvt &cvt, VERIFY (char_traits::compare (out, exp, t.out_size) == 0); if (t.out_size < array_size (out)) VERIFY (out[t.out_size] == 0); + + state = {}; + auto len = cvt.length (state, in, in + t.in_size, t.out_size); + VERIFY (len >= 0); + VERIFY (static_cast (len) == t.in_size); } for (auto t : offsets) @@ -1878,6 +1961,11 @@ utf16_to_ucs2_in_ok (const std::codecvt &cvt, VERIFY (char_traits::compare (out, exp, t.out_size) == 0); if (t.out_size < array_size (out)) VERIFY (out[t.out_size] == 0); + + state = {}; + auto len = cvt.length (state, in, in + t.in_size, array_size (out)); + VERIFY (len >= 0); + VERIFY (static_cast (len) == t.in_size); } } @@ -1894,7 +1982,6 @@ utf16_to_ucs2_in_partial (const std::codecvt &cvt, char in[array_size (input) * 2]; InternT exp[array_size (expected)]; - auto in_iter = begin (in); utf16_to_bytes (begin (input), end (input), begin (in), endianess); copy (begin (expected), end (expected), begin (exp)); @@ -1933,6 +2020,11 @@ utf16_to_ucs2_in_partial (const std::codecvt &cvt, == 0); if (t.expected_out_next < array_size (out)) VERIFY (out[t.expected_out_next] == 0); + + state = {}; + auto len = cvt.length (state, in, in + t.in_size, t.out_size); + VERIFY (len >= 0); + VERIFY (static_cast (len) == t.expected_in_next); } } @@ -2018,6 +2110,11 @@ utf16_to_ucs2_in_error (const std::codecvt &cvt, if (t.expected_out_next < array_size (out)) VERIFY (out[t.expected_out_next] == 0); + state = {}; + auto len = cvt.length (state, in, in + t.in_size, t.out_size); + VERIFY (len >= 0); + VERIFY (static_cast (len) == t.expected_in_next); + input[t.replace_pos] = old_char; } } @@ -2038,7 +2135,7 @@ ucs2_to_utf16_out_ok (const std::codecvt &cvt, copy (begin (input), end (input), begin (in)); utf16_to_bytes (begin (expected), end (expected), begin (exp), endianess); - const test_offsets_ok offsets[] = {{0, 0}, {1, 2}, {2, 4}, {3, 6}}; + test_offsets_ok offsets[] = {{0, 0}, {1, 2}, {2, 4}, {3, 6}}; for (auto t : offsets) { char out[array_size (exp) - 2] = {}; @@ -2076,7 +2173,7 @@ ucs2_to_utf16_out_partial (const std::codecvt &cvt, copy (begin (input), end (input), begin (in)); utf16_to_bytes (begin (expected), end (expected), begin (exp), endianess); - const test_offsets_partial offsets[] = { + test_offsets_partial offsets[] = { {1, 0, 0, 0}, // no space for first CP {1, 1, 0, 0}, // no space for first CP commit a841964721931b7da03760b0bc47b3ec1f212f48 Author: GCC Administrator Date: Wed May 22 00:20:55 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1b02f752a85..2172a4e4cbe 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2024-05-21 Andrew Pinski + + Backported from master: + 2024-05-20 Andrew Pinski + + PR tree-optimization/115143 + * tree-ssa-phiopt.cc (minmax_replacement): Check for empty + phi nodes for middle bbs for the case where middle bb is not empty. + +2024-05-21 Andrew Pinski + + Backported from master: + 2024-05-21 Andrew Pinski + + PR tree-optimization/115154 + * match.pd (convert (mult zero_one_valued_p@1 INTEGER_CST@2)): Disable + for 1bit signed types. + 2024-05-21 Release Manager * GCC 13.3.0 released. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 2affb73fdd4..c9b34d6ac0f 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240521 +20240522 diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c9fde9a6e39..a0bc3e00fc3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2024-05-21 Jonathan Wakely + + Backported from master: + 2024-05-21 Jonathan Wakely + + PR libstdc++/107800 + * cxxapi-data.csv : Change dialect to cxx20. + * std-name-hint.gperf: Regenerate. + * std-name-hint.h: Regenerate. + 2024-05-21 Release Manager * GCC 13.3.0 released. diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 09c40248583..8b9072f58a9 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,12 @@ +2024-05-21 Harald Anlauf + + Backported from master: + 2024-05-11 Harald Anlauf + + PR fortran/115039 + * expr.cc (gfc_traverse_expr): An inquiry ref does not constitute + a dependency and cannot collide with a symbol. + 2024-05-21 Release Manager * GCC 13.3.0 released. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9e44625bc18..ecd7bc59f02 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,40 @@ +2024-05-21 Harald Anlauf + + Backported from master: + 2024-05-11 Harald Anlauf + + PR fortran/115039 + * gfortran.dg/statement_function_5.f90: New test. + +2024-05-21 Kewen Lin + + Backported from master: + 2024-04-10 Kewen Lin + + PR testsuite/114662 + * gcc.dg/lto/pr113359-2_0.c: Use unsigned long long instead of + unsigned long. + * gcc.dg/lto/pr113359-2_1.c: Likewise. + +2024-05-21 Andrew Pinski + + Backported from master: + 2024-05-20 Andrew Pinski + + PR tree-optimization/115143 + * gcc.c-torture/compile/pr115143-1.c: New test. + * gcc.c-torture/compile/pr115143-2.c: New test. + * gcc.c-torture/compile/pr115143-3.c: New test. + +2024-05-21 Andrew Pinski + + Backported from master: + 2024-05-21 Andrew Pinski + + PR tree-optimization/115154 + * c-c++-common/ubsan/signed1bitfield-1.c: New test. + * gcc.c-torture/execute/signed1bitfield-1.c: New test. + 2024-05-21 Release Manager * GCC 13.3.0 released. diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 317b1e535e5..bb56ce8109f 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,38 @@ +2024-05-21 Dimitrij Mijoski + + Backported from master: + 2023-10-21 Dimitrij Mijoski + + * testsuite/22_locale/codecvt/codecvt_unicode.h: Test length() + +2024-05-21 Dimitrij Mijoski + + Backported from master: + 2023-09-29 Dimitrij Mijoski + + PR libstdc++/108976 + * src/c++11/codecvt.cc (read_utf8_code_point): Fix handing of + surrogates in UTF-8. + (ucs4_out): Fix handling of surrogates in UCS-4 -> UTF-8. + (ucs4_in): Fix handling of range with odd number of bytes. + (ucs4_out): Fix handling of surrogates in UCS-4 -> UTF-16. + (ucs2_out): Fix handling of surrogates in UCS-2 -> UTF-16. + (ucs2_in): Fix handling of range with odd number of bytes. + (__codecvt_utf16_base::do_in): Likewise. + (__codecvt_utf16_base::do_in): Likewise. + (__codecvt_utf16_base::do_in): Likewise. + * testsuite/22_locale/codecvt/codecvt_unicode.cc: Renames, add + tests for codecvt_utf16 and codecvt_utf16. + * testsuite/22_locale/codecvt/codecvt_unicode.h: Refactor UTF-8 + testing functions for char8_t, add more test cases for errors, + add testing functions for codecvt_utf16. + * testsuite/22_locale/codecvt/codecvt_unicode_wchar_t.cc: + Renames, add tests for codecvt_utf16. + * testsuite/22_locale/codecvt/codecvt_utf16/79980.cc (test06): + Fix test. + * testsuite/22_locale/codecvt/codecvt_unicode_char8_t.cc: New + test. + 2024-05-21 Release Manager * GCC 13.3.0 released. commit 35ac28b9c26debcc8ec8b247d75d4d271de72189 Author: Jakub Jelinek Date: Wed May 22 09:12:28 2024 +0200 ubsan: Use right address space for MEM_REF created for bool/enum sanitization [PR115172] The following testcase is miscompiled, because -fsanitize=bool,enum creates a MEM_REF without propagating there address space qualifiers, so what should be normally loaded using say %gs:/%fs: segment prefix isn't. Together with asan it then causes that load to be sanitized. 2024-05-22 Jakub Jelinek PR sanitizer/115172 * ubsan.cc (instrument_bool_enum_load): If rhs is not in generic address space, use qualified version of utype with the right address space. Formatting fix. * gcc.dg/asan/pr115172.c: New test. (cherry picked from commit d3c506eff54fcbac389a529c2e98da108a410b7f) diff --git a/gcc/testsuite/gcc.dg/asan/pr115172.c b/gcc/testsuite/gcc.dg/asan/pr115172.c new file mode 100644 index 00000000000..8707e615733 --- /dev/null +++ b/gcc/testsuite/gcc.dg/asan/pr115172.c @@ -0,0 +1,20 @@ +/* PR sanitizer/115172 */ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-O2 -fsanitize=address,bool -ffat-lto-objects -fdump-tree-asan1" } */ +/* { dg-final { scan-tree-dump-not "\.ASAN_CHECK " "asan1" } } */ + +#ifdef __x86_64__ +#define SEG __seg_gs +#else +#define SEG __seg_fs +#endif + +extern struct S { _Bool b; } s; +void bar (void); + +void +foo (void) +{ + if (*(volatile _Bool SEG *) (__UINTPTR_TYPE__) &s.b) + bar (); +} diff --git a/gcc/ubsan.cc b/gcc/ubsan.cc index 93475786c1e..22d3330ca41 100644 --- a/gcc/ubsan.cc +++ b/gcc/ubsan.cc @@ -1719,13 +1719,17 @@ instrument_bool_enum_load (gimple_stmt_iterator *gsi) || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME) return; + addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (rhs)); + if (as != TYPE_ADDR_SPACE (utype)) + utype = build_qualified_type (utype, TYPE_QUALS (utype) + | ENCODE_QUAL_ADDR_SPACE (as)); bool ends_bb = stmt_ends_bb_p (stmt); location_t loc = gimple_location (stmt); tree lhs = gimple_assign_lhs (stmt); tree ptype = build_pointer_type (TREE_TYPE (rhs)); tree atype = reference_alias_ptr_type (rhs); gimple *g = gimple_build_assign (make_ssa_name (ptype), - build_fold_addr_expr (rhs)); + build_fold_addr_expr (rhs)); gimple_set_location (g, loc); gsi_insert_before (gsi, g, GSI_SAME_STMT); tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g), commit 53bc98f5355ada17d1629a2d0e96aebd397780c6 Author: Jakub Jelinek Date: Wed May 22 09:13:50 2024 +0200 strlen: Fix up !si->full_string_p handling in count_nonzero_bytes_addr [PR115152] The following testcase is miscompiled because strlen_pass::count_nonzero_bytes_addr doesn't handle correctly the !si->full_string_p case. If si->full_string_p, it correctly computes minlen and maxlen as minimum and maximum length of the '\0' terminated stgring and clears *nulterm (ie. makes sure !full_string_p in the ultimate caller) if minlen is equal or larger than nbytes and so '\0' isn't guaranteed to be among those bytes. But in the !si->full_string_p case, all we know is that there are [minlen,maxlen] non-zero bytes followed by unknown bytes, so effectively the maxlen is infinite (but caller cares about only the first nbytes bytes) and furthermore, we never know if there is any '\0' char among those, so *nulterm needs to be always cleared. 2024-05-22 Jakub Jelinek PR tree-optimization/115152 * tree-ssa-strlen.cc (strlen_pass::count_nonzero_bytes_addr): If !si->full_string_p, clear *nulterm and set maxlen to nbytes. * gcc.dg/pr115152.c: New test. (cherry picked from commit dbc9b45a3c2468ad134b3a9bd4961f7ae6bc1e67) diff --git a/gcc/testsuite/gcc.dg/pr115152.c b/gcc/testsuite/gcc.dg/pr115152.c new file mode 100644 index 00000000000..a44654e2015 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr115152.c @@ -0,0 +1,17 @@ +/* PR tree-optimization/115152 */ +/* { dg-do run } */ +/* { dg-options "-O3 -fno-tree-fre -fno-tree-dominator-opts -fno-tree-loop-im" } */ + +int a, b, c, d; +signed char e[1] = { 1 }; + +int +main () +{ + for (a = 0; a < 3; a++) + for (b = 0; b < 2; b++) + c = e[0] = e[0] ^ d; + if (!c) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-ssa-strlen.cc b/gcc/tree-ssa-strlen.cc index 3b10c7b4cb2..b911067d009 100644 --- a/gcc/tree-ssa-strlen.cc +++ b/gcc/tree-ssa-strlen.cc @@ -4836,7 +4836,7 @@ strlen_pass::count_nonzero_bytes_addr (tree exp, tree vuse, gimple *stmt, if (maxlen + 1 < nbytes) return false; - if (nbytes <= minlen) + if (nbytes <= minlen || !si->full_string_p) *nulterm = false; if (nbytes < minlen) @@ -4846,6 +4846,9 @@ strlen_pass::count_nonzero_bytes_addr (tree exp, tree vuse, gimple *stmt, maxlen = nbytes; } + if (!si->full_string_p) + maxlen = nbytes; + if (minlen < lenrange[0]) lenrange[0] = minlen; if (lenrange[1] < maxlen) commit 2ebf3af1f84d54fbda172eff105a8842c685d11d Author: Andrew Jenner Date: Tue Nov 28 15:27:05 2023 +0000 Fortran: fix reallocation on assignment of polymorphic variables [PR110415] This patch fixes two bugs related to polymorphic class assignment in the Fortran front-end. One (described in PR110415) is an issue with the malloc and realloc calls using the size from the old vptr rather than the new one. The other is caused by the return value from the realloc call being ignored. Testcases are added for these issues. 2023-11-28 Andrew Jenner gcc/fortran/ PR fortran/110415 * trans-expr.cc (trans_class_vptr_len_assignment): Add from_vptrp parameter. Populate it. Don't check for DECL_P when deciding whether to create temporary. (trans_class_pointer_fcn, gfc_trans_pointer_assignment): Add NULL argument to trans_class_vptr_len_assignment calls. (trans_class_assignment): Get rhs_vptr from trans_class_vptr_len_assignment and use it for determining size for allocation/reallocation. Use return value from realloc. gcc/testsuite/ PR fortran/110415 * gfortran.dg/pr110415.f90: New test. * gfortran.dg/asan/pr110415-2.f90: New test. * gfortran.dg/asan/pr110415-3.f90: New test. Co-Authored-By: Tobias Burnus (cherry picked from commit b247e917ff13328298c1eecf8563b12edd7ade04) diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index cfe03252582..2b2dceb8d0f 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -9748,7 +9748,8 @@ trans_get_upoly_len (stmtblock_t *block, gfc_expr *expr) static tree trans_class_vptr_len_assignment (stmtblock_t *block, gfc_expr * le, gfc_expr * re, gfc_se *rse, - tree * to_lenp, tree * from_lenp) + tree * to_lenp, tree * from_lenp, + tree * from_vptrp) { gfc_se se; gfc_expr * vptr_expr; @@ -9756,10 +9757,11 @@ trans_class_vptr_len_assignment (stmtblock_t *block, gfc_expr * le, bool set_vptr = false, temp_rhs = false; stmtblock_t *pre = block; tree class_expr = NULL_TREE; + tree from_vptr = NULL_TREE; /* Create a temporary for complicated expressions. */ if (re->expr_type != EXPR_VARIABLE && re->expr_type != EXPR_NULL - && rse->expr != NULL_TREE && !DECL_P (rse->expr)) + && rse->expr != NULL_TREE) { if (re->ts.type == BT_CLASS && !GFC_CLASS_TYPE_P (TREE_TYPE (rse->expr))) class_expr = gfc_get_class_from_expr (rse->expr); @@ -9856,6 +9858,7 @@ trans_class_vptr_len_assignment (stmtblock_t *block, gfc_expr * le, tmp = rse->expr; se.expr = gfc_class_vptr_get (tmp); + from_vptr = se.expr; if (UNLIMITED_POLY (re)) from_len = gfc_class_len_get (tmp); @@ -9877,6 +9880,7 @@ trans_class_vptr_len_assignment (stmtblock_t *block, gfc_expr * le, gfc_free_expr (vptr_expr); gfc_add_block_to_block (block, &se.pre); gcc_assert (se.post.head == NULL_TREE); + from_vptr = se.expr; } gfc_add_modify (pre, lhs_vptr, fold_convert (TREE_TYPE (lhs_vptr), se.expr)); @@ -9905,11 +9909,13 @@ trans_class_vptr_len_assignment (stmtblock_t *block, gfc_expr * le, } } - /* Return the _len trees only, when requested. */ + /* Return the _len and _vptr trees only, when requested. */ if (to_lenp) *to_lenp = to_len; if (from_lenp) *from_lenp = from_len; + if (from_vptrp) + *from_vptrp = from_vptr; return lhs_vptr; } @@ -9978,7 +9984,7 @@ trans_class_pointer_fcn (stmtblock_t *block, gfc_se *lse, gfc_se *rse, { expr1_vptr = trans_class_vptr_len_assignment (block, expr1, expr2, rse, - NULL, NULL); + NULL, NULL, NULL); gfc_add_block_to_block (block, &rse->pre); tmp = gfc_create_var (TREE_TYPE (rse->expr), "ptrtemp"); gfc_add_modify (&lse->pre, tmp, rse->expr); @@ -10054,7 +10060,7 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2) if (non_proc_ptr_assign && expr1->ts.type == BT_CLASS) { trans_class_vptr_len_assignment (&block, expr1, expr2, &rse, NULL, - NULL); + NULL, NULL); lse.expr = gfc_class_data_get (lse.expr); } @@ -10183,7 +10189,8 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2) if (expr1->ts.type == BT_CLASS) expr1_vptr = trans_class_vptr_len_assignment (&block, expr1, expr2, &rse, - NULL, NULL); + NULL, NULL, + NULL); } } else if (expr2->expr_type == EXPR_VARIABLE) @@ -10200,7 +10207,7 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2) rse.expr = NULL_TREE; rse.string_length = strlen_rhs; trans_class_vptr_len_assignment (&block, expr1, expr2, &rse, - NULL, NULL); + NULL, NULL, NULL); } if (remap == NULL) @@ -10233,7 +10240,7 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2) { expr1_vptr = trans_class_vptr_len_assignment (&block, expr1, expr2, &rse, NULL, - NULL); + NULL, NULL); gfc_add_block_to_block (&block, &rse.pre); tmp = gfc_create_var (TREE_TYPE (rse.expr), "ptrtemp"); gfc_add_modify (&lse.pre, tmp, rse.expr); @@ -11621,7 +11628,7 @@ trans_class_assignment (stmtblock_t *block, gfc_expr *lhs, gfc_expr *rhs, gfc_se *lse, gfc_se *rse, bool use_vptr_copy, bool class_realloc) { - tree tmp, fcn, stdcopy, to_len, from_len, vptr, old_vptr; + tree tmp, fcn, stdcopy, to_len, from_len, vptr, old_vptr, rhs_vptr; vec *args = NULL; bool final_expr; @@ -11645,7 +11652,9 @@ trans_class_assignment (stmtblock_t *block, gfc_expr *lhs, gfc_expr *rhs, } vptr = trans_class_vptr_len_assignment (block, lhs, rhs, rse, &to_len, - &from_len); + &from_len, &rhs_vptr); + if (rhs_vptr == NULL_TREE) + rhs_vptr = vptr; /* Generate (re)allocation of the lhs. */ if (class_realloc) @@ -11658,7 +11667,7 @@ trans_class_assignment (stmtblock_t *block, gfc_expr *lhs, gfc_expr *rhs, else old_vptr = build_int_cst (TREE_TYPE (vptr), 0); - size = gfc_vptr_size_get (vptr); + size = gfc_vptr_size_get (rhs_vptr); tmp = lse->expr; class_han = GFC_CLASS_TYPE_P (TREE_TYPE (tmp)) ? gfc_class_data_get (tmp) : tmp; @@ -11672,12 +11681,14 @@ trans_class_assignment (stmtblock_t *block, gfc_expr *lhs, gfc_expr *rhs, /* Reallocate if dynamic types are different. */ gfc_init_block (&re_alloc); + tmp = fold_convert (pvoid_type_node, class_han); re = build_call_expr_loc (input_location, builtin_decl_explicit (BUILT_IN_REALLOC), 2, - fold_convert (pvoid_type_node, class_han), - size); + tmp, size); + re = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (tmp), tmp, + re); tmp = fold_build2_loc (input_location, NE_EXPR, - logical_type_node, vptr, old_vptr); + logical_type_node, rhs_vptr, old_vptr); re = fold_build3_loc (input_location, COND_EXPR, void_type_node, tmp, re, build_empty_stmt (input_location)); gfc_add_expr_to_block (&re_alloc, re); diff --git a/gcc/testsuite/gfortran.dg/asan/pr110415-2.f90 b/gcc/testsuite/gfortran.dg/asan/pr110415-2.f90 new file mode 100755 index 00000000000..f4ff1823e54 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/asan/pr110415-2.f90 @@ -0,0 +1,45 @@ +! { dg-do run } +! +! Contributed by Brad Richardson +! +implicit none + type, abstract :: p + integer :: a = 4 + end type p + + type, extends(p) :: c + integer :: b = 7 + character(len=:), allocatable :: str, str2(:) + end type c + + type, extends(p) :: d + integer :: ef = 7 + end type d + + class(p), allocatable :: a + + a = func() + + a = func2() + + a = func() + + deallocate(a) + +contains + function func2() result(a) + class(p), allocatable :: a + a = d() + end function func2 + + function func() result(a) + class(p), allocatable :: a + + a = c() + select type(a) + type is (c) + a%str = 'abcd' + a%str2 = ['abcd','efgh'] + end select + end function func +end program diff --git a/gcc/testsuite/gfortran.dg/asan/pr110415-3.f90 b/gcc/testsuite/gfortran.dg/asan/pr110415-3.f90 new file mode 100755 index 00000000000..65c018d805f --- /dev/null +++ b/gcc/testsuite/gfortran.dg/asan/pr110415-3.f90 @@ -0,0 +1,49 @@ +! { dg-do run } +! +! Contributed by Brad Richardson +! +implicit none + type, abstract :: p + integer :: a = 4 + end type p + + type, extends(p) :: c + integer :: b = 7 + character(len=:), allocatable :: str, str2(:) + end type c + + type, extends(p) :: d + integer :: ef = 7 + end type d + + class(p), allocatable :: a(:) + + a = func() + + a = func2() + + a = func() + + deallocate(a) + +contains + function func2() result(a) + class(p), allocatable :: a(:) + a = [d(),d()] + end function func2 + + function func() result(a) + class(p), allocatable :: a(:) + + a = [c(),c(),c()] + select type(a) + type is (c) + a(1)%str = 'abcd' + a(2)%str = 'abc' + a(3)%str = 'abcd4' + a(1)%str2 = ['abcd','efgh'] + a(2)%str2 = ['bcd','fgh'] + a(3)%str2 = ['abcd6','efgh7'] + end select + end function func +end program diff --git a/gcc/testsuite/gfortran.dg/pr110415.f90 b/gcc/testsuite/gfortran.dg/pr110415.f90 new file mode 100644 index 00000000000..f647cc4c52c --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr110415.f90 @@ -0,0 +1,20 @@ +! { dg-do run } +! +! Contributed by Brad Richardson +! + type, abstract :: p + end type p + + type, extends(p) :: c + end type c + + class(p), allocatable :: a + + a = func() +contains + function func() result(a) + class(p), allocatable :: a + + a = c() + end function func +end program commit f0b88ec4ae829798cb533618f781ca467bab6b9b Author: Harald Anlauf Date: Mon Apr 29 19:52:52 2024 +0200 Fortran: fix issues with class(*) assignment [PR114827] gcc/fortran/ChangeLog: PR fortran/114827 * trans-array.cc (gfc_alloc_allocatable_for_assignment): Take into account _len of unlimited polymorphic entities when calculating the effective element size for allocation size and array span. Set _len of lhs to _len of rhs. * trans-expr.cc (trans_class_assignment): Take into account _len of unlimited polymorphic entities for allocation size. gcc/testsuite/ChangeLog: PR fortran/114827 * gfortran.dg/asan/unlimited_polymorphic_34.f90: New test. (cherry picked from commit 21e7aa5f3ea44ca2fef8deb8788edffc04901b5c) diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index 5eef4b4ec87..f38e872f5d9 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -11008,6 +11008,19 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop, gfc_add_modify (&fblock, linfo->delta[dim], tmp); } + /* Take into account _len of unlimited polymorphic entities, so that span + for array descriptors and allocation sizes are computed correctly. */ + if (UNLIMITED_POLY (expr2)) + { + tree len = gfc_class_len_get (TREE_OPERAND (desc2, 0)); + len = fold_build2_loc (input_location, MAX_EXPR, size_type_node, + fold_convert (size_type_node, len), + size_one_node); + elemsize2 = fold_build2_loc (input_location, MULT_EXPR, + gfc_array_index_type, elemsize2, + fold_convert (gfc_array_index_type, len)); + } + if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))) gfc_conv_descriptor_span_set (&fblock, desc, elemsize2); @@ -11054,6 +11067,9 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop, gfc_add_modify (&fblock, tmp, fold_convert (TREE_TYPE (tmp), TYPE_SIZE_UNIT (type))); + else if (UNLIMITED_POLY (expr2)) + gfc_add_modify (&fblock, tmp, + gfc_class_len_get (TREE_OPERAND (desc2, 0))); else gfc_add_modify (&fblock, tmp, build_int_cst (TREE_TYPE (tmp), 0)); diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index 2b2dceb8d0f..5946aa81391 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -11668,6 +11668,19 @@ trans_class_assignment (stmtblock_t *block, gfc_expr *lhs, gfc_expr *rhs, old_vptr = build_int_cst (TREE_TYPE (vptr), 0); size = gfc_vptr_size_get (rhs_vptr); + + /* Take into account _len of unlimited polymorphic entities. + TODO: handle class(*) allocatable function results on rhs. */ + if (UNLIMITED_POLY (rhs) && rhs->expr_type == EXPR_VARIABLE) + { + tree len = trans_get_upoly_len (block, rhs); + len = fold_build2_loc (input_location, MAX_EXPR, size_type_node, + fold_convert (size_type_node, len), + size_one_node); + size = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (size), + size, fold_convert (TREE_TYPE (size), len)); + } + tmp = lse->expr; class_han = GFC_CLASS_TYPE_P (TREE_TYPE (tmp)) ? gfc_class_data_get (tmp) : tmp; diff --git a/gcc/testsuite/gfortran.dg/asan/unlimited_polymorphic_34.f90 b/gcc/testsuite/gfortran.dg/asan/unlimited_polymorphic_34.f90 new file mode 100644 index 00000000000..c69158a1b55 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/asan/unlimited_polymorphic_34.f90 @@ -0,0 +1,135 @@ +! { dg-do run } +! PR fortran/114827 - issues with class(*) assignment found by valgrind +! +! Contributed by Neil Carlson + +program main + implicit none + call run + call run1 + call run2 +contains + ! Scalar tests + subroutine run () + character(*), parameter :: c = 'fubarfubarfubarfubarfubarfu' + character(*,kind=4), parameter :: d = 4_"abcdef" + complex, parameter :: z = (1.,2.) + class(*), allocatable :: y + + call foo (c, y) + select type (y) + type is (character(*)) +! print *, y(5:6) ! ICE (-> pr114874) + if (y /= c) stop 1 + class default + stop 2 + end select + + call foo (z, y) + select type (y) + type is (complex) + if (y /= z) stop 3 + class default + stop 4 + end select + + call foo (d, y) + select type (y) + type is (character(*,kind=4)) +! print *, y ! NAG fails here + if (y /= d) stop 5 + class default + stop 6 + end select + end subroutine + ! + subroutine foo (a, b) + class(*), intent(in) :: a + class(*), allocatable :: b + b = a + end subroutine + + ! Rank-1 tests + subroutine run1 () + character(*), parameter :: c(*) = ['fubar','snafu'] + character(*,kind=4), parameter :: d(*) = [4_"abc",4_"def"] + real, parameter :: r(*) = [1.,2.,3.] + class(*), allocatable :: y(:) + + call foo1 (c, y) + select type (y) + type is (character(*)) +! print *, ">",y(2)(1:3),"< >", c(2)(1:3), "<" + if (any (y /= c)) stop 11 + if (y(2)(1:3) /= c(2)(1:3)) stop 12 + class default + stop 13 + end select + + call foo1 (r, y) + select type (y) + type is (real) + if (any (y /= r)) stop 14 + class default + stop 15 + end select + + call foo1 (d, y) + select type (y) + type is (character(*,kind=4)) +! print *, ">",y(2)(2:3),"< >", d(2)(2:3), "<" + if (any (y /= d)) stop 16 + class default + stop 17 + end select + end subroutine + ! + subroutine foo1 (a, b) + class(*), intent(in) :: a(:) + class(*), allocatable :: b(:) + b = a + end subroutine + + ! Rank-2 tests + subroutine run2 () + character(7) :: c(2,3) + complex :: z(3,3) + integer :: i, j + class(*), allocatable :: y(:,:) + + c = reshape (['fubar11','snafu21',& + 'fubar12','snafu22',& + 'fubar13','snafu23'],shape(c)) + call foo2 (c, y) + select type (y) + type is (character(*)) +! print *, y(2,1) + if (y(2,1) /= c(2,1)) stop 21 + if (any (y /= c)) stop 22 + class default + stop 23 + end select + + do j = 1, size (z,2) + do i = 1, size (z,1) + z(i,j) = cmplx (i,j) + end do + end do + call foo2 (z, y) + select type (y) + type is (complex) +! print *, y(2,1) + if (any (y%re /= z%re)) stop 24 + if (any (y%im /= z%im)) stop 25 + class default + stop 26 + end select + end subroutine + ! + subroutine foo2 (a, b) + class(*), intent(in) :: a(:,:) + class(*), allocatable :: b(:,:) + b = a + end subroutine + +end program commit 75d394c20b0ad85dfe8511324d61d13e453c9285 Author: Torbjörn SVENSSON Date: Sat Apr 27 15:57:27 2024 +0200 testsuite: Verify r0-r3 are extended with CMSE Add regression test to the existing zero/sign extend tests for CMSE to verify that r0, r1, r2 and r3 are properly extended, not just r0. boolCharShortEnumSecureFunc test is done using -O0 to ensure the instructions are in a predictable order. gcc/testsuite/ChangeLog: * gcc.target/arm/cmse/extend-param.c: Add regression test. Add -fshort-enums. * gcc.target/arm/cmse/extend-return.c: Add -fshort-enums option. Signed-off-by: Torbjörn SVENSSON (cherry picked from commit 9ddad76e98ac8f257f90b3814ed3c6ba78d0f3c7) diff --git a/gcc/testsuite/gcc.target/arm/cmse/extend-param.c b/gcc/testsuite/gcc.target/arm/cmse/extend-param.c index 01fac786238..d01ef87e0be 100644 --- a/gcc/testsuite/gcc.target/arm/cmse/extend-param.c +++ b/gcc/testsuite/gcc.target/arm/cmse/extend-param.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-mcmse" } */ +/* { dg-options "-mcmse -fshort-enums" } */ /* { dg-final { check-function-bodies "**" "" "" } } */ #include @@ -78,7 +78,6 @@ __attribute__((cmse_nonsecure_entry)) char enumSecureFunc (enum offset index) { if (index >= ARRAY_SIZE) return 0; return array[index]; - } /* @@ -88,9 +87,23 @@ __attribute__((cmse_nonsecure_entry)) char enumSecureFunc (enum offset index) { ** ... */ __attribute__((cmse_nonsecure_entry)) char boolSecureFunc (bool index) { - if (index >= ARRAY_SIZE) return 0; return array[index]; +} -} \ No newline at end of file +/* +**__acle_se_boolCharShortEnumSecureFunc: +** ... +** uxtb r0, r0 +** uxtb r1, r1 +** uxth r2, r2 +** uxtb r3, r3 +** ... +*/ +__attribute__((cmse_nonsecure_entry,optimize(0))) char boolCharShortEnumSecureFunc (bool a, unsigned char b, unsigned short c, enum offset d) { + size_t index = a + b + c + d; + if (index >= ARRAY_SIZE) + return 0; + return array[index]; +} diff --git a/gcc/testsuite/gcc.target/arm/cmse/extend-return.c b/gcc/testsuite/gcc.target/arm/cmse/extend-return.c index cf731ed33df..081de0d699f 100644 --- a/gcc/testsuite/gcc.target/arm/cmse/extend-return.c +++ b/gcc/testsuite/gcc.target/arm/cmse/extend-return.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-mcmse" } */ +/* { dg-options "-mcmse -fshort-enums" } */ /* { dg-final { check-function-bodies "**" "" "" } } */ #include @@ -89,4 +89,4 @@ unsigned char __attribute__((noipa)) enumNonsecure0 (ns_enum_foo_t * ns_foo_p) unsigned char boolNonsecure0 (ns_bool_foo_t * ns_foo_p) { return ns_foo_p (); -} \ No newline at end of file +} commit 6f8933ce3fa83482b62d1b6e50d2a8f36addf73e Author: GCC Administrator Date: Thu May 23 00:20:12 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2172a4e4cbe..d00ff4365e1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2024-05-22 Jakub Jelinek + + Backported from master: + 2024-05-22 Jakub Jelinek + + PR tree-optimization/115152 + * tree-ssa-strlen.cc (strlen_pass::count_nonzero_bytes_addr): If + !si->full_string_p, clear *nulterm and set maxlen to nbytes. + +2024-05-22 Jakub Jelinek + + Backported from master: + 2024-05-22 Jakub Jelinek + + PR sanitizer/115172 + * ubsan.cc (instrument_bool_enum_load): If rhs is not in generic + address space, use qualified version of utype with the right + address space. Formatting fix. + 2024-05-21 Andrew Pinski Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index c9b34d6ac0f..e67e2574c12 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240522 +20240523 diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 8b9072f58a9..55db84bde1b 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,32 @@ +2024-05-22 Harald Anlauf + + Backported from master: + 2024-05-05 Harald Anlauf + + PR fortran/114827 + * trans-array.cc (gfc_alloc_allocatable_for_assignment): Take into + account _len of unlimited polymorphic entities when calculating + the effective element size for allocation size and array span. + Set _len of lhs to _len of rhs. + * trans-expr.cc (trans_class_assignment): Take into account _len + of unlimited polymorphic entities for allocation size. + +2024-05-22 Andrew Jenner + + Backported from master: + 2023-11-28 Andrew Jenner + Tobias Burnus + + PR fortran/110415 + * trans-expr.cc (trans_class_vptr_len_assignment): Add + from_vptrp parameter. Populate it. Don't check for DECL_P + when deciding whether to create temporary. + (trans_class_pointer_fcn, gfc_trans_pointer_assignment): Add + NULL argument to trans_class_vptr_len_assignment calls. + (trans_class_assignment): Get rhs_vptr from + trans_class_vptr_len_assignment and use it for determining size + for allocation/reallocation. Use return value from realloc. + 2024-05-21 Harald Anlauf Backported from master: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ecd7bc59f02..a4c90dbbf6b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,47 @@ +2024-05-22 Torbjörn SVENSSON + + Backported from master: + 2024-05-22 Torbjörn SVENSSON + + * gcc.target/arm/cmse/extend-param.c: Add regression test. Add + -fshort-enums. + * gcc.target/arm/cmse/extend-return.c: Add -fshort-enums option. + +2024-05-22 Harald Anlauf + + Backported from master: + 2024-05-05 Harald Anlauf + + PR fortran/114827 + * gfortran.dg/asan/unlimited_polymorphic_34.f90: New test. + +2024-05-22 Andrew Jenner + + Backported from master: + 2023-11-28 Andrew Jenner + Tobias Burnus + + PR fortran/110415 + * gfortran.dg/pr110415.f90: New test. + * gfortran.dg/asan/pr110415-2.f90: New test. + * gfortran.dg/asan/pr110415-3.f90: New test. + +2024-05-22 Jakub Jelinek + + Backported from master: + 2024-05-22 Jakub Jelinek + + PR tree-optimization/115152 + * gcc.dg/pr115152.c: New test. + +2024-05-22 Jakub Jelinek + + Backported from master: + 2024-05-22 Jakub Jelinek + + PR sanitizer/115172 + * gcc.dg/asan/pr115172.c: New test. + 2024-05-21 Harald Anlauf Backported from master: commit cf76815d93f065a48c06963b396e2d543e75b7a3 Author: GCC Administrator Date: Fri May 24 00:20:55 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index e67e2574c12..660b1b67ace 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240523 +20240524 commit 5f1457841abc2fd8657a52d1371c983ac010f1cc Author: Jason Merrill Date: Thu Jan 25 12:02:07 2024 -0500 c++: array of PMF [PR113598] Here AGGREGATE_TYPE_P includes pointers to member functions, which is not what we want. Instead we should use class||array, as elsewhere in the function. PR c++/113598 gcc/cp/ChangeLog: * init.cc (build_vec_init): Don't use {} for PMF. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/initlist-pmf2.C: New test. (cherry picked from commit 136a828754ff65079a834555582b49d54bd5bc64) diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc index 78e992af171..4977ce34398 100644 --- a/gcc/cp/init.cc +++ b/gcc/cp/init.cc @@ -4859,7 +4859,9 @@ build_vec_init (tree base, tree maxindex, tree init, But for non-classes, that's the same as value-initialization. */ if (empty_list) { - if (cxx_dialect >= cxx11 && AGGREGATE_TYPE_P (type)) + if (cxx_dialect >= cxx11 + && (CLASS_TYPE_P (type) + || TREE_CODE (type) == ARRAY_TYPE)) { init = build_constructor (init_list_type_node, NULL); } diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-pmf2.C b/gcc/testsuite/g++.dg/cpp0x/initlist-pmf2.C new file mode 100644 index 00000000000..0fac8333c75 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-pmf2.C @@ -0,0 +1,12 @@ +// PR c++/113598 +// { dg-additional-options -Wno-c++11-extensions } + +struct Cpu +{ + int op_nop(); +}; +typedef int(Cpu::*OpCode)(); +void f() +{ + new OpCode[256]{&Cpu::op_nop}; +} commit 53cdaa755de57e57ba9e787f232adc3cfde88209 Author: Jason Merrill Date: Fri Sep 22 12:10:11 2023 +0100 c++: unroll pragma in templates [PR111529] We were failing to handle ANNOTATE_EXPR in tsubst_copy_and_build, leading to problems with substitution of any wrapped expressions. Let's also not tell users that lambda templates are available in C++14. PR c++/111529 gcc/cp/ChangeLog: * parser.cc (cp_parser_lambda_declarator_opt): Don't suggest -std=c++14 for lambda templates. * pt.cc (tsubst_expr): Move ANNOTATE_EXPR handling... (tsubst_copy_and_build): ...here. gcc/testsuite/ChangeLog: * g++.dg/ext/unroll-4.C: New test. (cherry picked from commit 9c62af101e11e1cce573c2b3d2e18b403412dbc8) diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 4e67da6ff3a..a9241bd7e7a 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -11558,11 +11558,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) an opening angle if present. */ if (cp_lexer_next_token_is (parser->lexer, CPP_LESS)) { - if (cxx_dialect < cxx14) - pedwarn (parser->lexer->next_token->location, OPT_Wc__14_extensions, - "lambda templates are only available with " - "%<-std=c++14%> or %<-std=gnu++14%>"); - else if (pedantic && cxx_dialect < cxx20) + if (cxx_dialect < cxx20 + && (pedantic || cxx_dialect < cxx14)) pedwarn (parser->lexer->next_token->location, OPT_Wc__20_extensions, "lambda templates are only available with " "%<-std=c++20%> or %<-std=gnu++20%>"); diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 3af705c647a..5a6bf80c3d4 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -19926,13 +19926,6 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) templated_operator_saved_lookups (t), complain)); - case ANNOTATE_EXPR: - tmp = RECUR (TREE_OPERAND (t, 0)); - RETURN (build3_loc (EXPR_LOCATION (t), ANNOTATE_EXPR, - TREE_TYPE (tmp), tmp, - RECUR (TREE_OPERAND (t, 1)), - RECUR (TREE_OPERAND (t, 2)))); - case PREDICT_EXPR: RETURN (add_stmt (copy_node (t))); @@ -21862,6 +21855,13 @@ tsubst_copy_and_build (tree t, RETURN (op); } + case ANNOTATE_EXPR: + op1 = RECUR (TREE_OPERAND (t, 0)); + RETURN (build3_loc (EXPR_LOCATION (t), ANNOTATE_EXPR, + TREE_TYPE (op1), op1, + RECUR (TREE_OPERAND (t, 1)), + RECUR (TREE_OPERAND (t, 2)))); + default: /* Handle Objective-C++ constructs, if appropriate. */ { diff --git a/gcc/testsuite/g++.dg/ext/unroll-4.C b/gcc/testsuite/g++.dg/ext/unroll-4.C new file mode 100644 index 00000000000..d488aca974e --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/unroll-4.C @@ -0,0 +1,16 @@ +// PR c++/111529 +// { dg-do compile { target c++11 } } +// { dg-additional-options -Wno-c++20-extensions } + +template +void f() { + []() { + #pragma GCC unroll 9 + for (int i = 1; i; --i) { + } + }; +} + +int main() { + f<0>(); +} commit 91c7ec546aa2636df89f678fe1edd553a18582f0 Author: GCC Administrator Date: Sat May 25 00:20:14 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 660b1b67ace..96135ecc67a 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240524 +20240525 diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a0bc3e00fc3..5152f6d8085 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,22 @@ +2024-05-24 Jason Merrill + + Backported from master: + 2023-09-22 Jason Merrill + + PR c++/111529 + * parser.cc (cp_parser_lambda_declarator_opt): Don't suggest + -std=c++14 for lambda templates. + * pt.cc (tsubst_expr): Move ANNOTATE_EXPR handling... + (tsubst_copy_and_build): ...here. + +2024-05-24 Jason Merrill + + Backported from master: + 2024-01-25 Jason Merrill + + PR c++/113598 + * init.cc (build_vec_init): Don't use {} for PMF. + 2024-05-21 Jonathan Wakely Backported from master: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a4c90dbbf6b..001d6f822ff 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,19 @@ +2024-05-24 Jason Merrill + + Backported from master: + 2023-09-22 Jason Merrill + + PR c++/111529 + * g++.dg/ext/unroll-4.C: New test. + +2024-05-24 Jason Merrill + + Backported from master: + 2024-01-25 Jason Merrill + + PR c++/113598 + * g++.dg/cpp0x/initlist-pmf2.C: New test. + 2024-05-22 Torbjörn SVENSSON Backported from master: commit 513d0503f55fa073f4688a8b4246f1c715f7b57b Author: GCC Administrator Date: Sun May 26 00:20:27 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 96135ecc67a..6bc0967a4f6 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240525 +20240526 commit b954f157824f26e944be55570bee8184189e2939 Author: GCC Administrator Date: Mon May 27 00:20:11 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 6bc0967a4f6..345a13ee31c 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240526 +20240527 commit d7f9f231a177696c678309d46e4bd3055ecabec1 Author: GCC Administrator Date: Tue May 28 00:19:54 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 345a13ee31c..cfeb7c20268 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240527 +20240528 commit 67434fec24bef0faeec0eb402f82ca7e43a4a112 Author: Jonathan Wakely Date: Wed May 22 10:32:43 2024 +0100 libstdc++: Guard use of sized deallocation [PR114940] Clang does not enable -fsized-deallocation by default, which means it can't compile our header. Make the __cpp_lib_generator macro depend on the compiler-defined __cpp_sized_deallocation macro, and change to use unsized deallocation when __cpp_sized_deallocation isn't defined. libstdc++-v3/ChangeLog: PR libstdc++/114940 * include/std/stacktrace (_GLIBCXX_SIZED_DELETE): New macro. (basic_stacktrace::_Impl::_M_deallocate): Use it. (cherry picked from commit b2fdd508d7e63158e9d2a6dd04f901d02900def3) diff --git a/libstdc++-v3/include/std/stacktrace b/libstdc++-v3/include/std/stacktrace index 8f09467d751..3d8a085a6a9 100644 --- a/libstdc++-v3/include/std/stacktrace +++ b/libstdc++-v3/include/std/stacktrace @@ -600,6 +600,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #else # define _GLIBCXX_OPERATOR_NEW ::operator new # define _GLIBCXX_OPERATOR_DELETE ::operator delete +#endif + +#if __cpp_sized_deallocation +# define _GLIBCXX_SIZED_DELETE(T, p, n) \ + _GLIBCXX_OPERATOR_DELETE((p), (n) * sizeof(T)) +#else +# define _GLIBCXX_SIZED_DELETE(T, p, n) _GLIBCXX_OPERATOR_DELETE(p) #endif // Precondition: _M_frames == nullptr && __n != 0 @@ -641,8 +648,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (_M_capacity) { if constexpr (is_same_v>) - _GLIBCXX_OPERATOR_DELETE (static_cast(_M_frames), - _M_capacity * sizeof(value_type)); + _GLIBCXX_SIZED_DELETE(value_type, + static_cast(_M_frames), + _M_capacity); else __alloc.deallocate(_M_frames, _M_capacity); _M_frames = nullptr; @@ -650,6 +658,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } } +#undef _GLIBCXX_SIZED_DELETE #undef _GLIBCXX_OPERATOR_DELETE #undef _GLIBCXX_OPERATOR_NEW commit 3185cfe495944e6e5d000ccd820bed2e6f10cd6c Author: Tobias Burnus Date: Mon May 20 08:34:48 2024 +0200 Fortran: Fix SHAPE for zero-size arrays PR fortran/115150 gcc/fortran/ChangeLog: * trans-intrinsic.cc (gfc_conv_intrinsic_bound): Fix SHAPE for zero-size arrays gcc/testsuite/ChangeLog: * gfortran.dg/shape_12.f90: New test. (cherry picked from commit b701306a9b38bd74cdc26c7ece5add22f2203b56) diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc index aa0dea50089..455b61aa564 100644 --- a/gcc/fortran/trans-intrinsic.cc +++ b/gcc/fortran/trans-intrinsic.cc @@ -3090,7 +3090,9 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, enum gfc_isym_id op) lbound, gfc_index_one_node); } else if (op == GFC_ISYM_SHAPE) - se->expr = size; + se->expr = fold_build2_loc (input_location, MAX_EXPR, + gfc_array_index_type, size, + gfc_index_zero_node); else gcc_unreachable (); diff --git a/gcc/testsuite/gfortran.dg/shape_12.f90 b/gcc/testsuite/gfortran.dg/shape_12.f90 new file mode 100644 index 00000000000..e672e1ff9f9 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/shape_12.f90 @@ -0,0 +1,51 @@ +! { dg-do run } +! +! PR fortran/115150 +! +! Check that SHAPE handles zero-sized arrays correctly +! +implicit none +call one +call two + +contains + +subroutine one + real,allocatable :: A(:),B(:,:) + allocate(a(3:0), b(5:1, 2:5)) + + if (any (shape(a) /= [0])) stop 1 + if (any (shape(b) /= [0, 4])) stop 2 + if (size(a) /= 0) stop 3 + if (size(b) /= 0) stop 4 + if (any (lbound(a) /= [1])) stop 5 + if (any (lbound(b) /= [1, 2])) stop 6 + if (any (ubound(a) /= [0])) stop 5 + if (any (ubound(b) /= [0,5])) stop 6 +end + +subroutine two +integer :: x1(10), x2(10,10) +call f(x1, x2, -3) +end + +subroutine f(y1, y2, n) + integer, value :: n + integer :: y1(1:n) + integer :: y2(1:n,4,2:*) + call g(y1, y2) +end + +subroutine g(z1, z2) + integer :: z1(..), z2(..) + + if (any (shape(z1) /= [0])) stop 1 + if (any (shape(z2) /= [0, 4, -1])) stop 2 + if (size(z1) /= 0) stop 3 + if (size(z2) /= 0) stop 4 + if (any (lbound(z1) /= [1])) stop 5 + if (any (lbound(z2) /= [1, 1, 1])) stop 6 + if (any (ubound(z1) /= [0])) stop 5 + if (any (ubound(z2) /= [0, 4, -1])) stop 6 +end +end commit fd91953c4dfba2a592ec15f2b4a2da28b1cf1947 Author: Jakub Jelinek Date: Tue May 28 16:30:48 2024 +0200 libstdc++: Fix up 19_diagnostics/stacktrace/hash.cc on 13 branch The r13-8207-g17acf9fbeb10d7adad commit changed some tests to use -lstdc++exp instead of -lstdc++_libbacktrace, but it didn't change the 19_diagnostics/stacktrace/hash.cc test, presumably because when it was added on the trunk, it already had -lstdc++exp and it was changed to -lstdc++_libbacktrace only in the r13-8067-g16635b89f36c07b9e0 cherry-pick. The test fails with /usr/bin/ld: cannot find -lstdc++_libbacktrace collect2: error: ld returned 1 exit status compiler exited with status 1 FAIL: 19_diagnostics/stacktrace/hash.cc (test for excess errors) without this (while the library is still built, it isn't added in -L options). 2024-05-27 Jakub Jelinek * testsuite/19_diagnostics/stacktrace/hash.cc: Adjust dg-options to use -lstdc++exp. diff --git a/libstdc++-v3/testsuite/19_diagnostics/stacktrace/hash.cc b/libstdc++-v3/testsuite/19_diagnostics/stacktrace/hash.cc index a2f61e49981..37e6d6dd7ec 100644 --- a/libstdc++-v3/testsuite/19_diagnostics/stacktrace/hash.cc +++ b/libstdc++-v3/testsuite/19_diagnostics/stacktrace/hash.cc @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++23 -lstdc++_libbacktrace" } +// { dg-options "-std=gnu++23 -lstdc++exp" } // { dg-do run { target c++23 } } // { dg-require-effective-target stacktrace } commit ebca6006f44408b8084868da6613f185b810db74 Author: GCC Administrator Date: Wed May 29 00:21:40 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index cfeb7c20268..4fb76261189 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240528 +20240529 diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 55db84bde1b..e6a9e145e17 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,12 @@ +2024-05-28 Tobias Burnus + + Backported from master: + 2024-05-20 Tobias Burnus + + PR fortran/115150 + * trans-intrinsic.cc (gfc_conv_intrinsic_bound): Fix SHAPE + for zero-size arrays + 2024-05-22 Harald Anlauf Backported from master: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 001d6f822ff..32277bced6e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2024-05-28 Tobias Burnus + + Backported from master: + 2024-05-20 Tobias Burnus + + PR fortran/115150 + * gfortran.dg/shape_12.f90: New test. + 2024-05-24 Jason Merrill Backported from master: diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index bb56ce8109f..f4e136d8c4f 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,17 @@ +2024-05-28 Jakub Jelinek + + * testsuite/19_diagnostics/stacktrace/hash.cc: Adjust + dg-options to use -lstdc++exp. + +2024-05-28 Jonathan Wakely + + Backported from master: + 2024-05-22 Jonathan Wakely + + PR libstdc++/114940 + * include/std/stacktrace (_GLIBCXX_SIZED_DELETE): New macro. + (basic_stacktrace::_Impl::_M_deallocate): Use it. + 2024-05-21 Dimitrij Mijoski Backported from master: commit 2618cdaa1cf4ab54a756ca43f8ffbad06d26d49e Author: GCC Administrator Date: Thu May 30 00:21:08 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 4fb76261189..4f23b7f073e 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240529 +20240530 commit 3be8fa7b19d218ca5812d71801e3e83ee2260ea0 Author: YunQiang Su Date: Wed May 29 02:28:25 2024 +0800 MIPS16: Mark $2/$3 as clobbered if GP is used PR Target/84790. The gp init sequence li $2,%hi(_gp_disp) addiu $3,$pc,%lo(_gp_disp) sll $2,16 addu $2,$3 is generated directly in `mips_output_function_prologue`, and does not appear in the RTL. So the IRA/IPA passes are not aware that $2/$3 have been clobbered, so they may be used for cross (local) function call. Let's mark $2/$3 clobber both: - Just after the UNSPEC_GP RTL of a function; - Just after a function call. Reported-by: Matthias Schiffer Origin-Patch-by: Felix Fietkau . gcc * config/mips/mips.cc(mips16_gp_pseudo_reg): Mark MIPS16_PIC_TEMP and MIPS_PROLOGUE_TEMP clobbered. (mips_emit_call_insn): Mark MIPS16_PIC_TEMP and MIPS_PROLOGUE_TEMP clobbered if MIPS16 and CALL_CLOBBERED_GP. (cherry picked from commit 915440eed21de367cb41857afb5273aff5bcb737) diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc index 8e3dc313cb3..9bc73b2e77d 100644 --- a/gcc/config/mips/mips.cc +++ b/gcc/config/mips/mips.cc @@ -3140,6 +3140,9 @@ mips_emit_call_insn (rtx pattern, rtx orig_addr, rtx addr, bool lazy_p) { rtx post_call_tmp_reg = gen_rtx_REG (word_mode, POST_CALL_TMP_REG); clobber_reg (&CALL_INSN_FUNCTION_USAGE (insn), post_call_tmp_reg); + clobber_reg (&CALL_INSN_FUNCTION_USAGE (insn), MIPS16_PIC_TEMP); + clobber_reg (&CALL_INSN_FUNCTION_USAGE (insn), + MIPS_PROLOGUE_TEMP (word_mode)); } return insn; @@ -3236,7 +3239,13 @@ mips16_gp_pseudo_reg (void) rtx set = gen_load_const_gp (cfun->machine->mips16_gp_pseudo_rtx); rtx_insn *insn = emit_insn_after (set, scan); INSN_LOCATION (insn) = 0; - + /* NewABI support hasn't been implement. NewABI should generate RTL + sequence instead of ASM sequence directly. */ + if (mips_current_loadgp_style () == LOADGP_OLDABI) + { + emit_clobber (MIPS16_PIC_TEMP); + emit_clobber (MIPS_PROLOGUE_TEMP (Pmode)); + } pop_topmost_sequence (); } commit d0fb9d292fd251f5815496ff9abf6d0636a0c767 Author: GCC Administrator Date: Fri May 31 00:21:57 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d00ff4365e1..d03695d4dba 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2024-05-30 YunQiang Su + + Backported from master: + 2024-05-29 YunQiang Su + + * config/mips/mips.cc(mips16_gp_pseudo_reg): Mark + MIPS16_PIC_TEMP and MIPS_PROLOGUE_TEMP clobbered. + (mips_emit_call_insn): Mark MIPS16_PIC_TEMP and + MIPS_PROLOGUE_TEMP clobbered if MIPS16 and CALL_CLOBBERED_GP. + 2024-05-22 Jakub Jelinek Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 4f23b7f073e..a7808a0e59e 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240530 +20240531 commit 173f8763a66622f2a70ad66f60573fcff7d6b49e Author: Hongyu Wang Date: Wed May 15 11:24:34 2024 +0800 i386: Fix ix86_option override after change [PR 113719] In ix86_override_options_after_change, calls to ix86_default_align and ix86_recompute_optlev_based_flags will cause mismatched target opt_set when doing cl_optimization_restore. Move them back to ix86_option_override_internal to solve the issue. gcc/ChangeLog: PR target/113719 * config/i386/i386-options.cc (ix86_override_options_after_change): Remove call to ix86_default_align and ix86_recompute_optlev_based_flags. (ix86_option_override_internal): Call ix86_default_align and ix86_recompute_optlev_based_flags. (cherry picked from commit 499d00127d39ba894b0f7216d73660b380bdc325) diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc index c1229475138..cdbe2dc6201 100644 --- a/gcc/config/i386/i386-options.cc +++ b/gcc/config/i386/i386-options.cc @@ -1875,11 +1875,6 @@ ix86_recompute_optlev_based_flags (struct gcc_options *opts, void ix86_override_options_after_change (void) { - /* Default align_* from the processor table. */ - ix86_default_align (&global_options); - - ix86_recompute_optlev_based_flags (&global_options, &global_options_set); - /* Disable unrolling small loops when there's explicit -f{,no}unroll-loop. */ if ((OPTION_SET_P (flag_unroll_loops)) @@ -2420,6 +2415,8 @@ ix86_option_override_internal (bool main_args_p, set_ix86_tune_features (opts, ix86_tune, opts->x_ix86_dump_tunes); + ix86_recompute_optlev_based_flags (opts, opts_set); + ix86_override_options_after_change (); ix86_tune_cost = processor_cost_table[ix86_tune]; @@ -2451,6 +2448,9 @@ ix86_option_override_internal (bool main_args_p, || TARGET_64BIT_P (opts->x_ix86_isa_flags)) opts->x_ix86_regparm = REGPARM_MAX; + /* Default align_* from the processor table. */ + ix86_default_align (&global_options); + /* Provide default for -mbranch-cost= value. */ SET_OPTION_IF_UNSET (opts, opts_set, ix86_branch_cost, ix86_tune_cost->branch_cost); commit 0836216693749f3b0b383d015bd36c004754f1da Author: Richard Sandiford Date: Fri May 31 15:56:04 2024 +0100 vect: Fix access size alignment assumption [PR115192] create_intersect_range_checks checks whether two access ranges a and b are alias-free using something equivalent to: end_a <= start_b || end_b <= start_a It has two ways of doing this: a "vanilla" way that calculates the exact exclusive end pointers, and another way that uses the last inclusive aligned pointers (and changes the comparisons accordingly). The comment for the latter is: /* Calculate the minimum alignment shared by all four pointers, then arrange for this alignment to be subtracted from the exclusive maximum values to get inclusive maximum values. This "- min_align" is cumulative with a "+ access_size" in the calculation of the maximum values. In the best (and common) case, the two cancel each other out, leaving us with an inclusive bound based only on seg_len. In the worst case we're simply adding a smaller number than before. The problem is that the associated code implicitly assumed that the access size was a multiple of the pointer alignment, and so the alignment could be carried over to the exclusive end pointer. The testcase started failing after g:9fa5b473b5b8e289b6542 because that commit improved the alignment information for the accesses. gcc/ PR tree-optimization/115192 * tree-data-ref.cc (create_intersect_range_checks): Take the alignment of the access sizes into account. gcc/testsuite/ PR tree-optimization/115192 * gcc.dg/vect/pr115192.c: New test. (cherry picked from commit a0fe4fb1c8d7804515845dd5d2a814b3c7a1ccba) diff --git a/gcc/testsuite/gcc.dg/vect/pr115192.c b/gcc/testsuite/gcc.dg/vect/pr115192.c new file mode 100644 index 00000000000..923d377c1bb --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr115192.c @@ -0,0 +1,28 @@ +#include "tree-vect.h" + +int data[4 * 16 * 16] __attribute__((aligned(16))); + +__attribute__((noipa)) void +foo (__SIZE_TYPE__ n) +{ + for (__SIZE_TYPE__ i = 1; i < n; ++i) + { + data[i * n * 4] = data[(i - 1) * n * 4] + 1; + data[i * n * 4 + 1] = data[(i - 1) * n * 4 + 1] + 2; + } +} + +int +main () +{ + check_vect (); + + data[0] = 10; + data[1] = 20; + + foo (3); + + if (data[24] != 12 || data[25] != 24) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-data-ref.cc b/gcc/tree-data-ref.cc index 6cd5f7aa3cf..96934addff1 100644 --- a/gcc/tree-data-ref.cc +++ b/gcc/tree-data-ref.cc @@ -73,6 +73,7 @@ along with GCC; see the file COPYING3. If not see */ +#define INCLUDE_ALGORITHM #include "config.h" #include "system.h" #include "coretypes.h" @@ -2629,7 +2630,9 @@ create_intersect_range_checks (class loop *loop, tree *cond_expr, Because the maximum values are inclusive, there is an alias if the maximum value of one segment is equal to the minimum value of the other. */ - min_align = MIN (dr_a.align, dr_b.align); + min_align = std::min (dr_a.align, dr_b.align); + min_align = std::min (min_align, known_alignment (dr_a.access_size)); + min_align = std::min (min_align, known_alignment (dr_b.access_size)); cmp_code = LT_EXPR; } commit 2602b71103d5ef2ef86000cac832b31dad3dfe2b Author: Richard Sandiford Date: Fri May 31 15:56:05 2024 +0100 vect: Tighten vect_determine_precisions_from_range [PR113281] This was another PR caused by the way that vect_determine_precisions_from_range handles shifts. We tried to narrow 32768 >> x to a 16-bit shift based on range information for the inputs and outputs, with vect_recog_over_widening_pattern (after PR110828) adjusting the shift amount. But this doesn't work for the case where x is in [16, 31], since then 32-bit 32768 >> x is a well-defined zero, whereas no well-defined 16-bit 32768 >> y will produce 0. We could perhaps generate x < 16 ? 32768 >> x : 0 instead, but since vect_determine_precisions_from_range was never really supposed to rely on fix-ups, it seems better to fix that instead. The patch also makes the code more selective about which codes can be narrowed based on input and output ranges. This showed that vect_truncatable_operation_p was missing cases for BIT_NOT_EXPR (equivalent to BIT_XOR_EXPR of -1) and NEGATE_EXPR (equivalent to BIT_NOT_EXPR followed by a PLUS_EXPR of 1). pr113281-1.c is the original testcase. pr113281-[23].c failed before the patch due to overly optimistic narrowing. pr113281-[45].c previously passed and are meant to protect against accidental optimisation regressions. gcc/ PR target/113281 * tree-vect-patterns.cc (vect_recog_over_widening_pattern): Remove workaround for right shifts. (vect_truncatable_operation_p): Handle NEGATE_EXPR and BIT_NOT_EXPR. (vect_determine_precisions_from_range): Be more selective about which codes can be narrowed based on their input and output ranges. For shifts, require at least one more bit of precision than the maximum shift amount. gcc/testsuite/ PR target/113281 * gcc.dg/vect/pr113281-1.c: New test. * gcc.dg/vect/pr113281-2.c: Likewise. * gcc.dg/vect/pr113281-3.c: Likewise. * gcc.dg/vect/pr113281-4.c: Likewise. * gcc.dg/vect/pr113281-5.c: Likewise. (cherry picked from commit 1a8261e047f7a2c2b0afb95716f7615cba718cd1) diff --git a/gcc/testsuite/gcc.dg/vect/pr113281-1.c b/gcc/testsuite/gcc.dg/vect/pr113281-1.c new file mode 100644 index 00000000000..6df4231cb5f --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr113281-1.c @@ -0,0 +1,17 @@ +#include "tree-vect.h" + +unsigned char a; + +int main() { + check_vect (); + + short b = a = 0; + for (; a != 19; a++) + if (a) + b = 32872 >> a; + + if (b == 0) + return 0; + else + return 1; +} diff --git a/gcc/testsuite/gcc.dg/vect/pr113281-2.c b/gcc/testsuite/gcc.dg/vect/pr113281-2.c new file mode 100644 index 00000000000..3a1170c28b6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr113281-2.c @@ -0,0 +1,50 @@ +/* { dg-do compile } */ + +#define N 128 + +short x[N]; +short y[N]; + +void +f1 (void) +{ + for (int i = 0; i < N; ++i) + x[i] >>= y[i]; +} + +void +f2 (void) +{ + for (int i = 0; i < N; ++i) + x[i] >>= (y[i] < 32 ? y[i] : 32); +} + +void +f3 (void) +{ + for (int i = 0; i < N; ++i) + x[i] >>= (y[i] < 31 ? y[i] : 31); +} + +void +f4 (void) +{ + for (int i = 0; i < N; ++i) + x[i] >>= (y[i] & 31); +} + +void +f5 (void) +{ + for (int i = 0; i < N; ++i) + x[i] >>= 0x8000 >> y[i]; +} + +void +f6 (void) +{ + for (int i = 0; i < N; ++i) + x[i] >>= 0x8000 >> (y[i] & 31); +} + +/* { dg-final { scan-tree-dump-not {can narrow[^\n]+>>} "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr113281-3.c b/gcc/testsuite/gcc.dg/vect/pr113281-3.c new file mode 100644 index 00000000000..5982dd2d16f --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr113281-3.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ + +#define N 128 + +short x[N]; +short y[N]; + +void +f1 (void) +{ + for (int i = 0; i < N; ++i) + x[i] >>= (y[i] < 30 ? y[i] : 30); +} + +void +f2 (void) +{ + for (int i = 0; i < N; ++i) + x[i] >>= ((y[i] & 15) + 2); +} + +void +f3 (void) +{ + for (int i = 0; i < N; ++i) + x[i] >>= (y[i] < 16 ? y[i] : 16); +} + +void +f4 (void) +{ + for (int i = 0; i < N; ++i) + x[i] = 32768 >> ((y[i] & 15) + 3); +} + +/* { dg-final { scan-tree-dump {can narrow to signed:31 without loss [^\n]+>>} "vect" } } */ +/* { dg-final { scan-tree-dump {can narrow to signed:18 without loss [^\n]+>>} "vect" } } */ +/* { dg-final { scan-tree-dump {can narrow to signed:17 without loss [^\n]+>>} "vect" } } */ +/* { dg-final { scan-tree-dump {can narrow to unsigned:19 without loss [^\n]+>>} "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr113281-4.c b/gcc/testsuite/gcc.dg/vect/pr113281-4.c new file mode 100644 index 00000000000..10fbc0e8405 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr113281-4.c @@ -0,0 +1,55 @@ +/* { dg-do compile } */ + +#define N 128 + +short x[N]; +short y[N]; + +void +f1 (void) +{ + for (int i = 0; i < N; ++i) + x[i] >>= (y[i] & 15); +} + +void +f2 (void) +{ + for (int i = 0; i < N; ++i) + x[i] >>= ((y[i] & 7) + 8); +} + +void +f3 (void) +{ + for (int i = 0; i < N; ++i) + x[i] >>= ((y[i] & 7) ^ 11); +} + +void +f4 (void) +{ + for (int i = 0; i < N; ++i) + x[i] >>= (y[i] < 15 ? y[i] : 15); +} + +void +f5 (void) +{ + for (int i = 0; i < N; ++i) + x[i] >>= (y[i] < 15 ? y[i] : 1); +} + +void +f6 (void) +{ + for (int i = 0; i < N; ++i) + x[i] = 32768 >> (y[i] & 15); +} + +/* { dg-final { scan-tree-dump {:11:[^\n]+can narrow to signed:16 without loss [^\n]+>>} "vect" } } */ +/* { dg-final { scan-tree-dump {:18:[^\n]+can narrow to signed:16 without loss [^\n]+>>} "vect" } } */ +/* { dg-final { scan-tree-dump {:25:[^\n]+can narrow to signed:16 without loss [^\n]+>>} "vect" } } */ +/* { dg-final { scan-tree-dump {:32:[^\n]+can narrow to signed:16 without loss [^\n]+>>} "vect" } } */ +/* { dg-final { scan-tree-dump {:39:[^\n]+can narrow to signed:16 without loss [^\n]+>>} "vect" } } */ +/* { dg-final { scan-tree-dump {can narrow to unsigned:16 without loss [^\n]+>>} "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr113281-5.c b/gcc/testsuite/gcc.dg/vect/pr113281-5.c new file mode 100644 index 00000000000..4a4571792e2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr113281-5.c @@ -0,0 +1,66 @@ +/* { dg-do compile } */ + +#define N 128 + +short x[N]; +short y[N]; + +void +f1 (void) +{ + for (int i = 0; i < N; ++i) + { + int a = y[i]; + int b = ~a; + x[i] = b; + } +} + +void +f2 (void) +{ + for (int i = 0; i < N; ++i) + { + int a = y[i]; + int b = -a; + x[i] = b; + } +} + +void +f3 (void) +{ + for (int i = 0; i < N; ++i) + { + int a = x[i]; + int b = a / y[i]; + x[i] = b; + } +} + +void +f4 (void) +{ + for (int i = 0; i < N; ++i) + { + int a = x[i]; + int b = a < y[i] ? a : y[i]; + x[i] = b; + } +} + +void +f5 (void) +{ + for (int i = 0; i < N; ++i) + { + int a = x[i]; + int b = a > y[i] ? a : y[i]; + x[i] = b; + } +} + +/* { dg-final { scan-tree-dump {can narrow to signed:17 without loss [^\n]+= -} "vect" } } */ +/* { dg-final { scan-tree-dump {can narrow to signed:16 without loss [^\n]+= ~} "vect" } } */ +/* { dg-final { scan-tree-dump {can narrow to signed:16 without loss [^\n]+ MIN_EXPR} "vect" } } */ +/* { dg-final { scan-tree-dump {can narrow to signed:16 without loss [^\n]+ MAX_EXPR} "vect" } } */ diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc index e07ec25de56..d416445dd86 100644 --- a/gcc/tree-vect-patterns.cc +++ b/gcc/tree-vect-patterns.cc @@ -5491,9 +5491,11 @@ vect_truncatable_operation_p (tree_code code) { switch (code) { + case NEGATE_EXPR: case PLUS_EXPR: case MINUS_EXPR: case MULT_EXPR: + case BIT_NOT_EXPR: case BIT_AND_EXPR: case BIT_IOR_EXPR: case BIT_XOR_EXPR: @@ -5652,38 +5654,85 @@ vect_determine_precisions_from_range (stmt_vec_info stmt_info, gassign *stmt) unsigned int nops = gimple_num_ops (stmt); if (!vect_truncatable_operation_p (code)) - /* Check that all relevant input operands are compatible, and update - [MIN_VALUE, MAX_VALUE] to include their ranges. */ - for (unsigned int i = 1; i < nops; ++i) - { - tree op = gimple_op (stmt, i); - if (TREE_CODE (op) == INTEGER_CST) - { - /* Don't require the integer to have RHS_TYPE (which it might - not for things like shift amounts, etc.), but do require it - to fit the type. */ - if (!int_fits_type_p (op, type)) - return; - - min_value = wi::min (min_value, wi::to_wide (op, precision), sign); - max_value = wi::max (max_value, wi::to_wide (op, precision), sign); - } - else if (TREE_CODE (op) == SSA_NAME) - { - /* Ignore codes that don't take uniform arguments. */ - if (!types_compatible_p (TREE_TYPE (op), type)) - return; + { + /* Handle operations that can be computed in type T if all inputs + and outputs can be represented in type T. Also handle left and + right shifts, where (in addition) the maximum shift amount must + be less than the number of bits in T. */ + bool is_shift; + switch (code) + { + case LSHIFT_EXPR: + case RSHIFT_EXPR: + is_shift = true; + break; - wide_int op_min_value, op_max_value; - if (!vect_get_range_info (op, &op_min_value, &op_max_value)) - return; + case ABS_EXPR: + case MIN_EXPR: + case MAX_EXPR: + case TRUNC_DIV_EXPR: + case CEIL_DIV_EXPR: + case FLOOR_DIV_EXPR: + case ROUND_DIV_EXPR: + case EXACT_DIV_EXPR: + /* Modulus is excluded because it is typically calculated by doing + a division, for which minimum signed / -1 isn't representable in + the original signed type. We could take the division range into + account instead, if handling modulus ever becomes important. */ + is_shift = false; + break; - min_value = wi::min (min_value, op_min_value, sign); - max_value = wi::max (max_value, op_max_value, sign); - } - else + default: return; - } + } + for (unsigned int i = 1; i < nops; ++i) + { + tree op = gimple_op (stmt, i); + wide_int op_min_value, op_max_value; + if (TREE_CODE (op) == INTEGER_CST) + { + unsigned int op_precision = TYPE_PRECISION (TREE_TYPE (op)); + op_min_value = op_max_value = wi::to_wide (op, op_precision); + } + else if (TREE_CODE (op) == SSA_NAME) + { + if (!vect_get_range_info (op, &op_min_value, &op_max_value)) + return; + } + else + return; + + if (is_shift && i == 2) + { + /* There needs to be one more bit than the maximum shift amount. + + If the maximum shift amount is already 1 less than PRECISION + then we can't narrow the shift further. Dealing with that + case first ensures that we can safely use an unsigned range + below. + + op_min_value isn't relevant, since shifts by negative amounts + are UB. */ + if (wi::geu_p (op_max_value, precision - 1)) + return; + unsigned int min_bits = op_max_value.to_uhwi () + 1; + + /* As explained below, we can convert a signed shift into an + unsigned shift if the sign bit is always clear. At this + point we've already processed the ranges of the output and + the first input. */ + auto op_sign = sign; + if (sign == SIGNED && !wi::neg_p (min_value)) + op_sign = UNSIGNED; + op_min_value = wide_int::from (wi::min_value (min_bits, op_sign), + precision, op_sign); + op_max_value = wide_int::from (wi::max_value (min_bits, op_sign), + precision, op_sign); + } + min_value = wi::min (min_value, op_min_value, sign); + max_value = wi::max (max_value, op_max_value, sign); + } + } /* Try to switch signed types for unsigned types if we can. This is better for two reasons. First, unsigned ops tend commit acdf0f732adc585bdbd52b5cb57d942125a98b8e Author: GCC Administrator Date: Sat Jun 1 00:21:10 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d03695d4dba..6958e620310 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,38 @@ +2024-05-31 Richard Sandiford + + Backported from master: + 2024-01-29 Richard Sandiford + + PR target/113281 + * tree-vect-patterns.cc (vect_recog_over_widening_pattern): Remove + workaround for right shifts. + (vect_truncatable_operation_p): Handle NEGATE_EXPR and BIT_NOT_EXPR. + (vect_determine_precisions_from_range): Be more selective about + which codes can be narrowed based on their input and output ranges. + For shifts, require at least one more bit of precision than the + maximum shift amount. + +2024-05-31 Richard Sandiford + + Backported from master: + 2024-05-24 Richard Sandiford + + PR tree-optimization/115192 + * tree-data-ref.cc (create_intersect_range_checks): Take the + alignment of the access sizes into account. + +2024-05-31 Hongyu Wang + + Backported from master: + 2024-05-29 Hongyu Wang + + PR target/113719 + * config/i386/i386-options.cc (ix86_override_options_after_change): + Remove call to ix86_default_align and + ix86_recompute_optlev_based_flags. + (ix86_option_override_internal): Call ix86_default_align and + ix86_recompute_optlev_based_flags. + 2024-05-30 YunQiang Su Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index a7808a0e59e..fe85bc7903e 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240531 +20240601 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 32277bced6e..82e3a65b53f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,23 @@ +2024-05-31 Richard Sandiford + + Backported from master: + 2024-01-29 Richard Sandiford + + PR target/113281 + * gcc.dg/vect/pr113281-1.c: New test. + * gcc.dg/vect/pr113281-2.c: Likewise. + * gcc.dg/vect/pr113281-3.c: Likewise. + * gcc.dg/vect/pr113281-4.c: Likewise. + * gcc.dg/vect/pr113281-5.c: Likewise. + +2024-05-31 Richard Sandiford + + Backported from master: + 2024-05-24 Richard Sandiford + + PR tree-optimization/115192 + * gcc.dg/vect/pr115192.c: New test. + 2024-05-28 Tobias Burnus Backported from master: commit 3687dcfabfaae566f4b42aa8a805869b809e6247 Author: Jonathan Wakely Date: Wed May 29 10:59:48 2024 +0100 libstdc++: Replace link to gcc-4.3.2 docs in manual [PR115269] Link to the docs for GCC trunk instead. For the release branches, the link should be to the docs for appropriate release branch. Also replace the incomplete/outdated list of explicit -std options with a single entry for the -std option. libstdc++-v3/ChangeLog: PR libstdc++/115269 * doc/xml/manual/using.xml: Replace link to gcc-4.3.2 docs. Replace list of -std=... options with a single entry for -std. * doc/html/manual/using.html: Regenerate. (cherry picked from commit b460ede64f9471589822831e04eecff4a3dbecf2) diff --git a/libstdc++-v3/doc/html/manual/using.html b/libstdc++-v3/doc/html/manual/using.html index e8e0c6c0e85..144ca80e030 100644 --- a/libstdc++-v3/doc/html/manual/using.html +++ b/libstdc++-v3/doc/html/manual/using.html @@ -4,7 +4,7 @@  Next

Chapter 3. Using

Command Options

The set of features available in the GNU C++ library is shaped by - several GCC + several GCC Command Options. Options that impact libstdc++ are enumerated and detailed in the table below.

@@ -14,9 +14,11 @@ g++ -std=gnu++17 since GCC 11, and g++ -std=gnu++14 in GCC 6, 7, 8, 9, and 10, and g++ -std=gnu++98 for older releases. -

Table 3.1. C++ Command Options

Option FlagsDescription
-std=c++98 or -std=c++03 - Use the 1998 ISO C++ standard plus amendments.
-std=gnu++98 or -std=gnu++03 - As directly above, with GNU extensions.
-std=c++11Use the 2011 ISO C++ standard.
-std=gnu++11As directly above, with GNU extensions.
-std=c++14Use the 2014 ISO C++ standard.
-std=gnu++14As directly above, with GNU extensions.
+

Table 3.1. C++ Command Options

- -std=c++98 or -std=c++03 + -std - Use the 1998 ISO C++ standard plus amendments. - - - - -std=gnu++98 or -std=gnu++03 + + Select the C++ standard, and whether to use the base standard + or GNU dialect. - As directly above, with GNU extensions. - - - - -std=c++11 - Use the 2011 ISO C++ standard. - - - - -std=gnu++11 - As directly above, with GNU extensions. - - - - -std=c++14 - Use the 2014 ISO C++ standard. - - - - -std=gnu++14 - As directly above, with GNU extensions. commit b45d7281c1b4eb2cf61280b9f7064229b7ca7581 Author: Georg-Johann Lay Date: Sat Jun 1 12:46:31 2024 +0200 AVR: target/115317 - Make isinf(-Inf) return -1. PR target/115317 libgcc/config/avr/libf7/ * libf7-asm.sx (__isinf): Map -Inf to -1. gcc/testsuite/ * gcc.target/avr/torture/pr115317-isinf.c: New test. (cherry picked from commit f12454278dc725fec3520a5d870e967d79292ee6) diff --git a/gcc/testsuite/gcc.target/avr/torture/pr115317-isinf.c b/gcc/testsuite/gcc.target/avr/torture/pr115317-isinf.c new file mode 100644 index 00000000000..10f7b553fb9 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/pr115317-isinf.c @@ -0,0 +1,55 @@ +/* { dg-do run { target { ! avr_tiny } } } */ + +extern int isinff (float); +extern int isinf (double); +extern int isinfl (long double); + +int tst_isinf (float x, int val) +{ + double y; + long double z; + + __asm ("" : "+r"(x)); + if (isinff (x) != val) + __builtin_exit (__LINE__); + + y = x; + __asm ("" : "+r"(y)); + if (isinf (y) != val) + __builtin_exit (__LINE__); + + z = x; + __asm ("" : "+r"(z)); + if (isinfl (z) != val) + __builtin_exit (__LINE__); +} + +static float make_f (__UINT32_TYPE__ i) +{ + float f; + __builtin_memcpy (&f, &i, 4); + return f; +} + +int main (void) +{ + tst_isinf (__builtin_huge_valf(), 1); + tst_isinf (-__builtin_huge_valf(), -1); + tst_isinf (__builtin_nanf(""), 0); + tst_isinf (0.0f, 0); + tst_isinf (-0.0f, 0); + tst_isinf (1.0f, 0); + tst_isinf (-1.0f, 0); + tst_isinf (make_f (0x7f800000), 1); + tst_isinf (make_f (0xff800000), -1); + tst_isinf (make_f (0x7f7fffff), 0); + tst_isinf (make_f (0xff7fffff), 0); + tst_isinf (make_f (0x7f800001), 0); + tst_isinf (make_f (0xff800001), 0); + tst_isinf (make_f (0x00800000), 0); + tst_isinf (make_f (0x80800000), 0); + tst_isinf (make_f (0x00400000), 0); + tst_isinf (make_f (0x80400000), 0); + + return 0; +} diff --git a/libgcc/config/avr/libf7/libf7-asm.sx b/libgcc/config/avr/libf7/libf7-asm.sx index df315d35c73..84790d2f52d 100644 --- a/libgcc/config/avr/libf7/libf7-asm.sx +++ b/libgcc/config/avr/libf7/libf7-asm.sx @@ -1639,19 +1639,24 @@ _ENDF __copysign #ifdef F7MOD_D_isinf_ +;;; +Inf -> +1 +;;; -Inf -> -1 _DEFUN __isinf DALIAS isinf LALIAS isinfl + ;; Save sign for later + push R25 F7call class_D + pop TMP + ldi R24, 0 + ldi R25, 0 ;; Inf: T = Z = 1. - brtc 0f + brtc 0f ; ordinary number + brne 0f ; Nan ldi R24, 1 - breq 1f -0: - clr R24 -1: - clr R25 - ret + sbrc TMP, 7 + sbiw R24, 2 +0: ret _ENDF __isinf #endif /* F7MOD_D_isinf_ */ commit c57d73f4cd5ca61327406fc2521a2235dd49d12e Author: Georg-Johann Lay Date: Sat Jun 1 10:38:00 2024 +0200 AVR: tree-optimization/115307 - Work around isinf bloat from early passes. PR tree-optimization/115307 gcc/ * config/avr/avr.md (SFDF): New mode iterator. (isinf2) [sf, df]: New expanders. gcc/testsuite/ * gcc.target/avr/torture/pr115307-isinf.c: New test. (cherry picked from commit fabb545026f714b7d1cbe586f4c5bbf6430bdde3) diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 866ce47d033..46f7812cea2 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -285,6 +285,8 @@ (define_mode_iterator SPLIT34 [SI SF PSI SQ USQ SA USA]) +(define_mode_iterator SFDF [SF DF]) + ;; Define code iterators ;; Define two incarnations so that we can build the cartesian product. (define_code_iterator any_extend [sign_extend zero_extend]) @@ -9780,6 +9782,20 @@ operands[4] = GEN_INT (bitno % 8); }) + +;; Work around PR115307: Early passes expand isinf/f/l to a bloat. +;; These passes do not consider costs, and there is no way to +;; hook in or otherwise disable the generated bloat. + +;; isinfsf2 isinfdf2 +(define_expand "isinf2" + [(parallel [(match_operand:HI 0) + (match_operand:SFDF 1)])] + "" + { + FAIL; + }) + ;; Fixed-point instructions (include "avr-fixed.md") diff --git a/gcc/testsuite/gcc.target/avr/torture/pr115307-isinf.c b/gcc/testsuite/gcc.target/avr/torture/pr115307-isinf.c new file mode 100644 index 00000000000..6368bd205c5 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/pr115307-isinf.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ + +int call_isinff (float f) +{ + int isinff (float); + return isinff (f); +} + +int call_isinf (double f) +{ + int isinf (double); + return isinf (f); +} + +int call_isinfl (long double f) +{ + int isinfl (long double); + return isinfl (f); +} + +/* { dg-final { scan-assembler-not "unord" } } */ commit 6634ff0f61bd79df779bc6e6e4c0313ff405b7ba Author: GCC Administrator Date: Sun Jun 2 00:21:14 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6958e620310..15789476a7f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2024-06-01 Georg-Johann Lay + + Backported from master: + 2024-06-01 Georg-Johann Lay + + PR tree-optimization/115307 + * config/avr/avr.md (SFDF): New mode iterator. + (isinf2) [sf, df]: New expanders. + 2024-05-31 Richard Sandiford Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index fe85bc7903e..a793b463258 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240601 +20240602 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 82e3a65b53f..0c1d8383b38 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,19 @@ +2024-06-01 Georg-Johann Lay + + Backported from master: + 2024-06-01 Georg-Johann Lay + + PR tree-optimization/115307 + * gcc.target/avr/torture/pr115307-isinf.c: New test. + +2024-06-01 Georg-Johann Lay + + Backported from master: + 2024-06-01 Georg-Johann Lay + + PR target/115317 + * gcc.target/avr/torture/pr115317-isinf.c: New test. + 2024-05-31 Richard Sandiford Backported from master: diff --git a/libgcc/config/avr/libf7/ChangeLog b/libgcc/config/avr/libf7/ChangeLog index 64f4c9cfdfa..e39ab8db385 100644 --- a/libgcc/config/avr/libf7/ChangeLog +++ b/libgcc/config/avr/libf7/ChangeLog @@ -1,3 +1,11 @@ +2024-06-01 Georg-Johann Lay + + Backported from master: + 2024-06-01 Georg-Johann Lay + + PR target/115317 + * libf7-asm.sx (__isinf): Map -Inf to -1. + 2024-05-21 Release Manager * GCC 13.3.0 released. diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index f4e136d8c4f..83badc78ee9 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,13 @@ +2024-06-01 Jonathan Wakely + + Backported from master: + 2024-06-01 Jonathan Wakely + + PR libstdc++/115269 + * doc/xml/manual/using.xml: Replace link to gcc-4.3.2 docs. + Replace list of -std=... options with a single entry for -std. + * doc/html/manual/using.html: Regenerate. + 2024-05-28 Jakub Jelinek * testsuite/19_diagnostics/stacktrace/hash.cc: Adjust commit 218246b50b902a552a30d500e363c6e61176a17c Author: GCC Administrator Date: Mon Jun 3 00:21:21 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index a793b463258..10c994db93f 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240602 +20240603 commit ed06ca80bae174f1179222ff8e6b93464006e86a Author: Uros Bizjak Date: Fri May 31 15:52:03 2024 +0200 alpha: Fix invalid RTX in divmodsi insn patterns [PR115297] any_divmod instructions are modelled with invalid RTX: [(set (match_operand:DI 0 "register_operand" "=c") (sign_extend:DI (match_operator:SI 3 "divmod_operator" [(match_operand:DI 1 "register_operand" "a") (match_operand:DI 2 "register_operand" "b")]))) (clobber (reg:DI 23)) (clobber (reg:DI 28))] where SImode divmod_operator (div,mod,udiv,umod) has DImode operands. Wrap input operand with truncate:SI to make machine modes consistent. PR target/115297 gcc/ChangeLog: * config/alpha/alpha.md (si3): Wrap DImode operands 3 and 4 with truncate:SI RTX. (*divmodsi_internal_er): Ditto for operands 1 and 2. (*divmodsi_internal_er_1): Ditto. (*divmodsi_internal): Ditto. * config/alpha/constraints.md ("b"): Correct register number in the description. gcc/testsuite/ChangeLog: * gcc.target/alpha/pr115297.c: New test. (cherry picked from commit 0ac802064c2a018cf166c37841697e867de65a95) diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md index d91742496d0..17dfc4a5868 100644 --- a/gcc/config/alpha/alpha.md +++ b/gcc/config/alpha/alpha.md @@ -756,7 +756,8 @@ (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand"))) (parallel [(set (match_dup 5) (sign_extend:DI - (any_divmod:SI (match_dup 3) (match_dup 4)))) + (any_divmod:SI (truncate:SI (match_dup 3)) + (truncate:SI (match_dup 4))))) (clobber (reg:DI 23)) (clobber (reg:DI 28))]) (set (match_operand:SI 0 "nonimmediate_operand") @@ -782,9 +783,10 @@ (define_insn_and_split "*divmodsi_internal_er" [(set (match_operand:DI 0 "register_operand" "=c") - (sign_extend:DI (match_operator:SI 3 "divmod_operator" - [(match_operand:DI 1 "register_operand" "a") - (match_operand:DI 2 "register_operand" "b")]))) + (sign_extend:DI + (match_operator:SI 3 "divmod_operator" + [(truncate:SI (match_operand:DI 1 "register_operand" "a")) + (truncate:SI (match_operand:DI 2 "register_operand" "b"))]))) (clobber (reg:DI 23)) (clobber (reg:DI 28))] "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF" @@ -826,8 +828,8 @@ (define_insn "*divmodsi_internal_er_1" [(set (match_operand:DI 0 "register_operand" "=c") (sign_extend:DI (match_operator:SI 3 "divmod_operator" - [(match_operand:DI 1 "register_operand" "a") - (match_operand:DI 2 "register_operand" "b")]))) + [(truncate:SI (match_operand:DI 1 "register_operand" "a")) + (truncate:SI (match_operand:DI 2 "register_operand" "b"))]))) (use (match_operand:DI 4 "register_operand" "c")) (use (match_operand 5 "const_int_operand")) (clobber (reg:DI 23)) @@ -839,9 +841,10 @@ (define_insn "*divmodsi_internal" [(set (match_operand:DI 0 "register_operand" "=c") - (sign_extend:DI (match_operator:SI 3 "divmod_operator" - [(match_operand:DI 1 "register_operand" "a") - (match_operand:DI 2 "register_operand" "b")]))) + (sign_extend:DI + (match_operator:SI 3 "divmod_operator" + [(truncate:SI (match_operand:DI 1 "register_operand" "a")) + (truncate:SI (match_operand:DI 2 "register_operand" "b"))]))) (clobber (reg:DI 23)) (clobber (reg:DI 28))] "TARGET_ABI_OSF" diff --git a/gcc/config/alpha/constraints.md b/gcc/config/alpha/constraints.md index ac3a5293732..2c0c276d491 100644 --- a/gcc/config/alpha/constraints.md +++ b/gcc/config/alpha/constraints.md @@ -27,7 +27,7 @@ "General register 24, input to division routine") (define_register_constraint "b" "R25_REG" - "General register 24, input to division routine") + "General register 25, input to division routine") (define_register_constraint "c" "R27_REG" "General register 27, function call address") diff --git a/gcc/testsuite/gcc.target/alpha/pr115297.c b/gcc/testsuite/gcc.target/alpha/pr115297.c new file mode 100644 index 00000000000..4d5890ec8d9 --- /dev/null +++ b/gcc/testsuite/gcc.target/alpha/pr115297.c @@ -0,0 +1,13 @@ +/* PR target/115297 */ +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +enum { BPF_F_USER_BUILD_ID } __bpf_get_stack_size; +long __bpf_get_stack_flags, bpf_get_stack___trans_tmp_2; + +void bpf_get_stack() { + unsigned elem_size; + int err = elem_size = __bpf_get_stack_flags ?: sizeof(long); + if (__builtin_expect(__bpf_get_stack_size % elem_size, 0)) + bpf_get_stack___trans_tmp_2 = err; +} commit 38360bab8ac3b913d7377902f8d376e2a033c09d Author: GCC Administrator Date: Tue Jun 4 00:21:57 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 15789476a7f..1be03a0922e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2024-06-03 Uros Bizjak + + Backported from master: + 2024-05-31 Uros Bizjak + + PR target/115297 + * config/alpha/alpha.md (si3): Wrap DImode + operands 3 and 4 with truncate:SI RTX. + (*divmodsi_internal_er): Ditto for operands 1 and 2. + (*divmodsi_internal_er_1): Ditto. + (*divmodsi_internal): Ditto. + * config/alpha/constraints.md ("b"): Correct register + number in the description. + 2024-06-01 Georg-Johann Lay Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 10c994db93f..f8e244336c6 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240603 +20240604 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0c1d8383b38..2f14fd0e1a2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2024-06-03 Uros Bizjak + + Backported from master: + 2024-05-31 Uros Bizjak + + PR target/115297 + * gcc.target/alpha/pr115297.c: New test. + 2024-06-01 Georg-Johann Lay Backported from master: commit 16fe81cee6a355c0d60051e505253714533e0375 Author: GCC Administrator Date: Wed Jun 5 00:21:33 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index f8e244336c6..3577d8c152d 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240604 +20240605 commit c0f229342dca5bbedd30944877f3ef9b22fcf5a1 Author: GCC Administrator Date: Thu Jun 6 00:21:27 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 3577d8c152d..ab2ff39bb42 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240605 +20240606 commit 3cf6c1f30a6217738333ed70175ba15c34977134 Author: GCC Administrator Date: Fri Jun 7 00:21:34 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index ab2ff39bb42..de43a34b913 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240606 +20240607 commit e4f85ea6271a10e13c6874709a05e04ab0508fbf Author: Jan Hubicka Date: Fri Dec 29 23:51:03 2023 +0100 Disable FMADD in chains for Zen4 and generic this patch disables use of FMA in matrix multiplication loop for generic (for x86-64-v3) and zen4. I tested this on zen4 and Xenon Gold Gold 6212U. For Intel this is neutral both on the matrix multiplication microbenchmark (attached) and spec2k17 where the difference was within noise for Core. On core the micro-benchmark runs as follows: With FMA: 578,500,241 cycles:u # 3.645 GHz ( +- 0.12% ) 753,318,477 instructions:u # 1.30 insn per cycle ( +- 0.00% ) 125,417,701 branches:u # 790.227 M/sec ( +- 0.00% ) 0.159146 +- 0.000363 seconds time elapsed ( +- 0.23% ) No FMA: 577,573,960 cycles:u # 3.514 GHz ( +- 0.15% ) 878,318,479 instructions:u # 1.52 insn per cycle ( +- 0.00% ) 125,417,702 branches:u # 763.035 M/sec ( +- 0.00% ) 0.164734 +- 0.000321 seconds time elapsed ( +- 0.19% ) So the cycle count is unchanged and discrete multiply+add takes same time as FMA. While on zen: With FMA: 484875179 cycles:u # 3.599 GHz ( +- 0.05% ) (82.11%) 752031517 instructions:u # 1.55 insn per cycle 125106525 branches:u # 928.712 M/sec ( +- 0.03% ) (85.09%) 128356 branch-misses:u # 0.10% of all branches ( +- 0.06% ) (83.58%) No FMA: 375875209 cycles:u # 3.592 GHz ( +- 0.08% ) (80.74%) 875725341 instructions:u # 2.33 insn per cycle 124903825 branches:u # 1.194 G/sec ( +- 0.04% ) (84.59%) 0.105203 +- 0.000188 seconds time elapsed ( +- 0.18% ) The diffrerence is that Cores understand the fact that fmadd does not need all three parameters to start computation, while Zen cores doesn't. Since this seems noticeable win on zen and not loss on Core it seems like good default for generic. float a[SIZE][SIZE]; float b[SIZE][SIZE]; float c[SIZE][SIZE]; void init(void) { int i, j, k; for(i=0; i Date: Sat Jun 8 00:22:16 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1be03a0922e..62237b108ea 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2024-06-07 Jan Hubicka + + Backported from master: + 2023-12-29 Jan Hubicka + + * config/i386/x86-tune.def (X86_TUNE_AVOID_128FMA_CHAINS, + X86_TUNE_AVOID_256FMA_CHAINS): Enable for znver4 and Core. + 2024-06-03 Uros Bizjak Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index de43a34b913..ee1c5e1ee91 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240607 +20240608 commit cd8dc162ba1dd1d77d34595a361d9103a0a06965 Author: GCC Administrator Date: Sun Jun 9 00:21:10 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index ee1c5e1ee91..d0a507843a3 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240608 +20240609 commit 7067b7e556cbdca70d11afc40ca2023ce3d19321 Author: GCC Administrator Date: Mon Jun 10 00:21:19 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index d0a507843a3..35b9b526690 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240609 +20240610 commit e54d90911858174a0c528d2c06198bc2061b3b22 Author: Javier Miranda Date: Thu Apr 18 09:54:22 2024 +0000 ada: Storage_Error in indirect call to function returning limited type At runtime the code generated by the compiler reports the exception Storage_Error in an indirect call through an access-to-subprogram variable that references a function returning a limited tagged type object. gcc/ada/ * sem_ch6.adb (Might_Need_BIP_Task_Actuals): Add support for access-to-subprogram parameter types. * exp_ch6.adb (Add_Task_Actuals_To_Build_In_Place_Call): Add dummy BIP parameters to access-to-subprogram types that may reference a function that has BIP parameters. diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index c367d0a7392..dae8b98dfde 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -640,15 +640,20 @@ package body Exp_Ch6 is Master_Formal : Node_Id; begin + pragma Assert (Ekind (Function_Id) in E_Function + | E_Subprogram_Type); + -- No such extra parameters are needed if there are no tasks if not Needs_BIP_Task_Actuals (Function_Id) then -- However we must add dummy extra actuals if the function is - -- a dispatching operation that inherited these extra formals. + -- a dispatching operation that inherited these extra formals + -- or an access-to-subprogram type that requires these extra + -- actuals. - if Is_Dispatching_Operation (Function_Id) - and then Has_BIP_Extra_Formal (Function_Id, BIP_Task_Master) + if Has_BIP_Extra_Formal (Function_Id, BIP_Task_Master, + Must_Be_Frozen => False) then Master_Formal := Build_In_Place_Formal (Function_Id, BIP_Task_Master); diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index 40a870186b4..20e9583d6cf 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -8588,9 +8588,12 @@ package body Sem_Ch6 is -- Determines if E has its extra formals function Might_Need_BIP_Task_Actuals (E : Entity_Id) return Boolean; - -- Determines if E is a dispatching primitive returning a limited tagged - -- type object since some descendant might return an object with tasks - -- (and therefore need the BIP task extra actuals). + -- Determines if E is a function or an access to a function returning a + -- limited tagged type object. On dispatching primitives this predicate + -- is used to determine if some descendant of the function might return + -- an object with tasks (and therefore need the BIP task extra actuals). + -- On access-to-subprogram types it is used to determine if the target + -- function might return an object with tasks. function Needs_Accessibility_Check_Extra (E : Entity_Id; @@ -8711,9 +8714,8 @@ package body Sem_Ch6 is Func_Typ := Root_Type (Underlying_Type (Etype (Subp_Id))); - return Ekind (Subp_Id) = E_Function + return Ekind (Subp_Id) in E_Function | E_Subprogram_Type and then not Has_Foreign_Convention (Func_Typ) - and then Is_Dispatching_Operation (Subp_Id) and then Is_Tagged_Type (Func_Typ) and then Is_Limited_Type (Func_Typ) and then not Has_Aspect (Func_Typ, Aspect_No_Task_Parts); commit 02025fb144fcf4fbb964cd59e480149ac448ea6c Author: Eric Botcazou Date: Mon Jun 10 11:44:24 2024 +0200 Add testcase for PR ada/114398 gcc/testsuite/ PR ada/114398 * gnat.dg/access11.adb: New test. diff --git a/gcc/testsuite/gnat.dg/access11.adb b/gcc/testsuite/gnat.dg/access11.adb new file mode 100644 index 00000000000..7c5a07cf6fd --- /dev/null +++ b/gcc/testsuite/gnat.dg/access11.adb @@ -0,0 +1,80 @@ +-- PR ada/114398 +-- Testcase by Dennis van Raaij + +-- { dg-do run } + +with Ada.Finalization; + +procedure Access11 is + + package Pkg is + + type Int is + new Ada.Finalization.Limited_Controlled + with record + Value : Integer; + end record; + + procedure Set (This : out Int; To : Integer); + procedure Set (This : out Int; To : Int); + + function "+" (Left, Right : Int) return Int; + + overriding procedure Initialize (This : in out Int); + overriding procedure Finalize (This : in out Int); + + end Pkg; + + package body Pkg is + + procedure Set (This : out Int; To : Integer) is + begin + This.Value := To; + end Set; + + procedure Set (This : out Int; To : Int) is + begin + This.Value := To.Value; + end Set; + + function "+" (Left, Right : Int) return Int is + begin + return Result : Int do + Result.Value := Left.Value + Right.Value; + end return; + end "+"; + + overriding procedure Initialize (This : in out Int) is + begin + This.Value := 42; + end Initialize; + + overriding procedure Finalize (This : in out Int) is + begin + This.Value := 0; + end Finalize; + + end Pkg; + + use Pkg; + + type Binary_Operator is access + function (Left, Right : Int) return Int; + + procedure Test + (Op : Binary_Operator; + Left, Right : Int) + is + Result : Int; + begin + Result.Set (Op (Left, Right)); + end Test; + + A, B : Int; + +begin + A.Set (7); + B.Set (9); + + Test ("+"'Access, A, B); +end; commit ef494b147f6d210cfa7e1647fb0979aa3666022a Author: Eric Botcazou Date: Mon Jun 10 12:12:21 2024 +0200 Fix crash on access-to-incomplete type This just adds the missing guard. gcc/ada/ PR ada/114708 * exp_util.adb (Finalize_Address): Add guard for incomplete types. gcc/testsuite/ * gnat.dg/incomplete8.adb: New test. diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index 5e76ca21132..5435375d92e 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -6013,6 +6013,12 @@ package body Exp_Util is Utyp := Underlying_Type (Base_Type (Utyp)); + -- Handle incomplete types + + if No (Utyp) then + return Empty; + end if; + -- Deal with untagged derivation of private views. If the parent is -- now known to be protected, the finalization routine is the one -- defined on the corresponding record of the ancestor (corresponding diff --git a/gcc/testsuite/gnat.dg/incomplete8.adb b/gcc/testsuite/gnat.dg/incomplete8.adb new file mode 100644 index 00000000000..63fef59e866 --- /dev/null +++ b/gcc/testsuite/gnat.dg/incomplete8.adb @@ -0,0 +1,22 @@ +-- PR ada/114708 +-- Reported by Jere + +-- { dg-do compile } + +procedure Incomplete8 is + + generic + type Element_Type(<>); + package Test_Incomplete_Formal is + type Element_Access is access Element_Type; + end Test_Incomplete_Formal; + + type Node; + + package P is new Test_Incomplete_Formal(Node); + + type Node is limited null record; + +begin + null; +end; commit f2ef3ac78c7832e1483085be5a5fe23b1e402e70 Author: GCC Administrator Date: Tue Jun 11 00:21:58 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 35b9b526690..9561fe84baa 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240610 +20240611 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 62c1cd478b3..99a45f5d60b 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,16 @@ +2024-06-10 Eric Botcazou + + PR ada/114708 + * exp_util.adb (Finalize_Address): Add guard for incomplete types. + +2024-06-10 Javier Miranda + + * sem_ch6.adb (Might_Need_BIP_Task_Actuals): Add support + for access-to-subprogram parameter types. + * exp_ch6.adb (Add_Task_Actuals_To_Build_In_Place_Call): + Add dummy BIP parameters to access-to-subprogram types + that may reference a function that has BIP parameters. + 2024-05-21 Release Manager * GCC 13.3.0 released. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2f14fd0e1a2..afe4612e598 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2024-06-10 Eric Botcazou + + * gnat.dg/incomplete8.adb: New test. + +2024-06-10 Eric Botcazou + + PR ada/114398 + * gnat.dg/access11.adb: New test. + 2024-06-03 Uros Bizjak Backported from master: commit 8deaab6f79768700e1bf05fe6af83b185f678b7f Author: Jakub Jelinek Date: Wed May 15 18:37:17 2024 +0200 combine: Fix up simplify_compare_const [PR115092] The following testcases are miscompiled (with tons of GIMPLE optimization disabled) because combine sees GE comparison of 1-bit sign_extract (i.e. something with [-1, 0] value range) with (const_int -1) (which is always true) and optimizes it into NE comparison of 1-bit zero_extract ([0, 1] value range) against (const_int 0). The reason is that simplify_compare_const first (correctly) simplifies the comparison to GE (ashift:SI something (const_int 31)) (const_int -2147483648) and then an optimization for when the second operand is power of 2 triggers. That optimization is fine for power of 2s which aren't the signed minimum of the mode, or if it is NE, EQ, GEU or LTU against the signed minimum of the mode, but for GE or LT optimizing it into NE (or EQ) against const0_rtx is wrong, those cases are always true or always false (but the function doesn't have a standardized way to tell callers the comparison is now unconditional). The following patch just disables the optimization in that case. 2024-05-15 Jakub Jelinek PR rtl-optimization/114902 PR rtl-optimization/115092 * combine.cc (simplify_compare_const): Don't optimize GE op0 SIGNED_MIN or LT op0 SIGNED_MIN into NE op0 const0_rtx or EQ op0 const0_rtx. * gcc.dg/pr114902.c: New test. * gcc.dg/pr115092.c: New test. (cherry picked from commit 0b93a0ae153ef70a82ff63e67926a01fdab9956b) diff --git a/gcc/combine.cc b/gcc/combine.cc index fbc84099f73..39d47f50f47 100644 --- a/gcc/combine.cc +++ b/gcc/combine.cc @@ -11801,8 +11801,10 @@ simplify_compare_const (enum rtx_code code, machine_mode mode, `and'ed with that bit), we can replace this with a comparison with zero. */ if (const_op - && (code == EQ || code == NE || code == GE || code == GEU - || code == LT || code == LTU) + && (code == EQ || code == NE || code == GEU || code == LTU + /* This optimization is incorrect for signed >= INT_MIN or + < INT_MIN, those are always true or always false. */ + || ((code == GE || code == LT) && const_op > 0)) && is_a (mode, &int_mode) && GET_MODE_PRECISION (int_mode) - 1 < HOST_BITS_PER_WIDE_INT && pow2p_hwi (const_op & GET_MODE_MASK (int_mode)) diff --git a/gcc/testsuite/gcc.dg/pr114902.c b/gcc/testsuite/gcc.dg/pr114902.c new file mode 100644 index 00000000000..60684faa25d --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr114902.c @@ -0,0 +1,23 @@ +/* PR rtl-optimization/114902 */ +/* { dg-do run } */ +/* { dg-options "-O1 -fno-tree-fre -fno-tree-forwprop -fno-tree-ccp -fno-tree-dominator-opts" } */ + +__attribute__((noipa)) +int foo (int x) +{ + int a = ~x; + int t = a & 1; + int e = -t; + int b = e >= -1; + if (b) + return 0; + __builtin_trap (); +} + +int +main () +{ + foo (-1); + foo (0); + foo (1); +} diff --git a/gcc/testsuite/gcc.dg/pr115092.c b/gcc/testsuite/gcc.dg/pr115092.c new file mode 100644 index 00000000000..c9047f4d321 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr115092.c @@ -0,0 +1,16 @@ +/* PR rtl-optimization/115092 */ +/* { dg-do run } */ +/* { dg-options "-O1 -fgcse -ftree-pre -fno-tree-dominator-opts -fno-tree-fre -fno-guess-branch-probability" } */ + +int a, b, c = 1, d, e; + +int +main () +{ + int f, g = a; + b = -2; + f = -(1 >> ((c && b) & ~a)); + if (f <= b) + d = g / e; + return 0; +} commit 50b5019fde97c20a377e004c9d73df62e4898773 Author: Jakub Jelinek Date: Mon Jun 3 23:11:06 2024 +0200 rs6000: Fix up PCH in --enable-host-pie builds [PR115324] PCH doesn't work properly in --enable-host-pie configurations on powerpc*-linux*. The problem is that the rs6000_builtin_info and rs6000_instance_info arrays mix pointers to .rodata/.data (bifname and attr_string point to string literals in .rodata section, and the next member is either NULL or &rs6000_instance_info[XXX]) and GC member (tree fntype). Now, for normal GC this works just fine, we emit { &rs6000_instance_info[0].fntype, 1 * (RS6000_INST_MAX), sizeof (rs6000_instance_info[0]), >_ggc_mx_tree_node, >_pch_nx_tree_node }, { &rs6000_builtin_info[0].fntype, 1 * (RS6000_BIF_MAX), sizeof (rs6000_builtin_info[0]), >_ggc_mx_tree_node, >_pch_nx_tree_node }, GC roots which are strided and thus cover only the fntype members of all the elements of the two arrays. For PCH though it actually results in saving those huge arrays (one is 130832 bytes, another 81568 bytes) into the .gch files and loading them back in full. While the bifname and attr_string and next pointers are marked as GTY((skip)), they are actually saved to point to the .rodata and .data sections of the process which writes the PCH, but because cc1/cc1plus etc. are position independent executables with --enable-host-pie, when it is loaded from the PCH file, it can point in a completely different addresses where nothing is mapped at all or some random different thing appears at. While gengtype supports the callback option, that one is meant for relocatable function pointers and doesn't work in the case of GTY arrays inside of .data section anyway. So, either we'd need to add some further GTY extensions, or the following patch instead reworks it such that the fntype members which were the only reason for PCH in those arrays are moved to separate arrays. Size-wise in .data sections it is (in bytes): vanilla patched rs6000_builtin_info 130832 110704 rs6000_instance_info 81568 40784 rs6000_overload_info 7392 7392 rs6000_builtin_info_fntype 0 10064 rs6000_instance_info_fntype 0 20392 sum 219792 189336 where previously we saved/restored for PCH those 130832+81568 bytes, now we save/restore just 10064+20392 bytes, so this change is beneficial for the data section size. Unfortunately, it grows the size of the rs6000_init_generated_builtins function, vanilla had 218328 bytes, patched has 228668. When I applied void rs6000_init_generated_builtins () { + bifdata *rs6000_builtin_info_p; + tree *rs6000_builtin_info_fntype_p; + ovlddata *rs6000_instance_info_p; + tree *rs6000_instance_info_fntype_p; + ovldrecord *rs6000_overload_info_p; + __asm ("" : "=r" (rs6000_builtin_info_p) : "0" (rs6000_builtin_info)); + __asm ("" : "=r" (rs6000_builtin_info_fntype_p) : "0" (rs6000_builtin_info_fntype)); + __asm ("" : "=r" (rs6000_instance_info_p) : "0" (rs6000_instance_info)); + __asm ("" : "=r" (rs6000_instance_info_fntype_p) : "0" (rs6000_instance_info_fntype)); + __asm ("" : "=r" (rs6000_overload_info_p) : "0" (rs6000_overload_info)); + #define rs6000_builtin_info rs6000_builtin_info_p + #define rs6000_builtin_info_fntype rs6000_builtin_info_fntype_p + #define rs6000_instance_info rs6000_instance_info_p + #define rs6000_instance_info_fntype rs6000_instance_info_fntype_p + #define rs6000_overload_info rs6000_overload_info_p + hack by hand, the size of the function is 209700 though, so if really wanted, we could add __attribute__((__noipa__)) to the function when building with recent enough GCC and pass pointers to the first elements of the 5 arrays to the function as arguments. If you want such a change, could that be done incrementally? 2024-06-03 Jakub Jelinek PR target/115324 * config/rs6000/rs6000-gen-builtins.cc (write_decls): Remove GTY markup from struct bifdata and struct ovlddata and remove their fntype members. Change next member in struct ovlddata and first_instance member of struct ovldrecord to have int type rather than struct ovlddata *. Remove GTY markup from rs6000_builtin_info and rs6000_instance_info arrays, declare new rs6000_builtin_info_fntype and rs6000_instance_info_fntype arrays, which have GTY markup. (write_bif_static_init): Adjust for the above changes. (write_ovld_static_init): Likewise. (write_init_bif_table): Likewise. (write_init_ovld_table): Likewise. * config/rs6000/rs6000-builtin.cc (rs6000_init_builtins): Likewise. * config/rs6000/rs6000-c.cc (find_instance): Likewise. Make static. (altivec_resolve_overloaded_builtin): Adjust for the above changes. (cherry picked from commit 4cf2de9b5268224816a3d53fdd2c3d799ebfd9c8) diff --git a/gcc/config/rs6000/rs6000-builtin.cc b/gcc/config/rs6000/rs6000-builtin.cc index 5b17132a101..0cb6e742c6b 100644 --- a/gcc/config/rs6000/rs6000-builtin.cc +++ b/gcc/config/rs6000/rs6000-builtin.cc @@ -845,7 +845,7 @@ rs6000_init_builtins (void) enum rs6000_gen_builtins fn_code = (enum rs6000_gen_builtins) i; if (!rs6000_builtin_is_supported (fn_code)) continue; - tree fntype = rs6000_builtin_info[i].fntype; + tree fntype = rs6000_builtin_info_fntype[i]; tree t = TREE_TYPE (fntype); fprintf (stderr, "%s %s (", rs6000_type_string (t), rs6000_builtin_info[i].bifname); diff --git a/gcc/config/rs6000/rs6000-c.cc b/gcc/config/rs6000/rs6000-c.cc index a931efd2409..611cfe292d0 100644 --- a/gcc/config/rs6000/rs6000-c.cc +++ b/gcc/config/rs6000/rs6000-c.cc @@ -1658,34 +1658,37 @@ resolve_vec_step (resolution *res, vec *arglist, unsigned nargs) UNSUPPORTED_BUILTIN to true. If we don't match, return error_mark_node and leave UNSUPPORTED_BUILTIN alone. */ -tree -find_instance (bool *unsupported_builtin, ovlddata **instance, +static tree +find_instance (bool *unsupported_builtin, int *instance, rs6000_gen_builtins instance_code, rs6000_gen_builtins fcode, tree *types, tree *args) { - while (*instance && (*instance)->bifid != instance_code) - *instance = (*instance)->next; + while (*instance != -1 + && rs6000_instance_info[*instance].bifid != instance_code) + *instance = rs6000_instance_info[*instance].next; - ovlddata *inst = *instance; - gcc_assert (inst != NULL); + int inst = *instance; + gcc_assert (inst != -1); /* It is possible for an instance to require a data type that isn't - defined on this target, in which case inst->fntype will be NULL. */ - if (!inst->fntype) + defined on this target, in which case rs6000_instance_info_fntype[inst] + will be NULL. */ + if (!rs6000_instance_info_fntype[inst]) return error_mark_node; - tree fntype = rs6000_builtin_info[inst->bifid].fntype; + rs6000_gen_builtins bifid = rs6000_instance_info[inst].bifid; + tree fntype = rs6000_builtin_info_fntype[bifid]; tree parmtype0 = TREE_VALUE (TYPE_ARG_TYPES (fntype)); tree parmtype1 = TREE_VALUE (TREE_CHAIN (TYPE_ARG_TYPES (fntype))); if (rs6000_builtin_type_compatible (types[0], parmtype0) && rs6000_builtin_type_compatible (types[1], parmtype1)) { - if (rs6000_builtin_decl (inst->bifid, false) != error_mark_node - && rs6000_builtin_is_supported (inst->bifid)) + if (rs6000_builtin_decl (bifid, false) != error_mark_node + && rs6000_builtin_is_supported (bifid)) { - tree ret_type = TREE_TYPE (inst->fntype); + tree ret_type = TREE_TYPE (rs6000_instance_info_fntype[inst]); return altivec_build_resolved_builtin (args, 2, fntype, ret_type, - inst->bifid, fcode); + bifid, fcode); } else *unsupported_builtin = true; @@ -1868,11 +1871,11 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, bool unsupported_builtin = false; rs6000_gen_builtins instance_code; bool supported = false; - ovlddata *instance = rs6000_overload_info[adj_fcode].first_instance; - gcc_assert (instance != NULL); + int instance = rs6000_overload_info[adj_fcode].first_instance; + gcc_assert (instance != -1); /* Functions with no arguments can have only one overloaded instance. */ - gcc_assert (nargs > 0 || !instance->next); + gcc_assert (nargs > 0 || rs6000_instance_info[instance].next == -1); /* Standard overload processing involves determining whether an instance exists that is type-compatible with the overloaded function call. In @@ -1946,16 +1949,18 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, /* Standard overload processing. Look for an instance with compatible parameter types. If it is supported in the current context, resolve the overloaded call to that instance. */ - for (; instance != NULL; instance = instance->next) + for (; instance != -1; instance = rs6000_instance_info[instance].next) { + tree fntype = rs6000_instance_info_fntype[instance]; + rs6000_gen_builtins bifid = rs6000_instance_info[instance].bifid; /* It is possible for an instance to require a data type that isn't - defined on this target, in which case instance->fntype will be + defined on this target, in which case fntype will be NULL. */ - if (!instance->fntype) + if (!fntype) continue; bool mismatch = false; - tree nextparm = TYPE_ARG_TYPES (instance->fntype); + tree nextparm = TYPE_ARG_TYPES (fntype); for (unsigned int arg_i = 0; arg_i < nargs && nextparm != NULL; @@ -1973,15 +1978,14 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, if (mismatch) continue; - supported = rs6000_builtin_is_supported (instance->bifid); - if (rs6000_builtin_decl (instance->bifid, false) != error_mark_node + supported = rs6000_builtin_is_supported (bifid); + if (rs6000_builtin_decl (bifid, false) != error_mark_node && supported) { - tree fntype = rs6000_builtin_info[instance->bifid].fntype; - tree ret_type = TREE_TYPE (instance->fntype); + tree ret_type = TREE_TYPE (fntype); + fntype = rs6000_builtin_info_fntype[bifid]; return altivec_build_resolved_builtin (args, nargs, fntype, - ret_type, instance->bifid, - fcode); + ret_type, bifid, fcode); } else { @@ -1998,12 +2002,12 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, { /* Indicate that the instantiation of the overloaded builtin name is not available with the target flags in effect. */ - rs6000_gen_builtins fcode = (rs6000_gen_builtins) instance->bifid; + rs6000_gen_builtins bifid = rs6000_instance_info[instance].bifid; + rs6000_gen_builtins fcode = (rs6000_gen_builtins) bifid; rs6000_invalid_builtin (fcode); /* Provide clarity of the relationship between the overload and the instantiation. */ - const char *internal_name - = rs6000_builtin_info[instance->bifid].bifname; + const char *internal_name = rs6000_builtin_info[bifid].bifname; rich_location richloc (line_table, input_location); inform (&richloc, "overloaded builtin %qs is implemented by builtin %qs", diff --git a/gcc/config/rs6000/rs6000-gen-builtins.cc b/gcc/config/rs6000/rs6000-gen-builtins.cc index a2f442ed90d..872188c1913 100644 --- a/gcc/config/rs6000/rs6000-gen-builtins.cc +++ b/gcc/config/rs6000/rs6000-gen-builtins.cc @@ -2261,20 +2261,19 @@ write_decls (void) fprintf (header_file, "};\n\n"); fprintf (header_file, "#define PPC_MAXRESTROPNDS 3\n"); - fprintf (header_file, "struct GTY(()) bifdata\n"); + fprintf (header_file, "struct bifdata\n"); fprintf (header_file, "{\n"); - fprintf (header_file, " const char *GTY((skip(\"\"))) bifname;\n"); - fprintf (header_file, " bif_enable GTY((skip(\"\"))) enable;\n"); - fprintf (header_file, " tree fntype;\n"); - fprintf (header_file, " insn_code GTY((skip(\"\"))) icode;\n"); - fprintf (header_file, " int nargs;\n"); - fprintf (header_file, " int bifattrs;\n"); - fprintf (header_file, " int restr_opnd[PPC_MAXRESTROPNDS];\n"); - fprintf (header_file, " restriction GTY((skip(\"\"))) restr[PPC_MAXRESTROPNDS];\n"); - fprintf (header_file, " int restr_val1[PPC_MAXRESTROPNDS];\n"); - fprintf (header_file, " int restr_val2[PPC_MAXRESTROPNDS];\n"); - fprintf (header_file, " const char *GTY((skip(\"\"))) attr_string;\n"); - fprintf (header_file, " rs6000_gen_builtins GTY((skip(\"\"))) assoc_bif;\n"); + fprintf (header_file, " const char *bifname;\n"); + fprintf (header_file, " bif_enable enable;\n"); + fprintf (header_file, " insn_code icode;\n"); + fprintf (header_file, " int nargs;\n"); + fprintf (header_file, " int bifattrs;\n"); + fprintf (header_file, " int restr_opnd[PPC_MAXRESTROPNDS];\n"); + fprintf (header_file, " restriction restr[PPC_MAXRESTROPNDS];\n"); + fprintf (header_file, " int restr_val1[PPC_MAXRESTROPNDS];\n"); + fprintf (header_file, " int restr_val2[PPC_MAXRESTROPNDS];\n"); + fprintf (header_file, " const char *attr_string;\n"); + fprintf (header_file, " rs6000_gen_builtins assoc_bif;\n"); fprintf (header_file, "};\n\n"); fprintf (header_file, "#define bif_init_bit\t\t(0x00000001)\n"); @@ -2353,24 +2352,28 @@ write_decls (void) fprintf (header_file, "\n"); fprintf (header_file, - "extern GTY(()) bifdata rs6000_builtin_info[RS6000_BIF_MAX];\n\n"); + "extern bifdata rs6000_builtin_info[RS6000_BIF_MAX];\n\n"); - fprintf (header_file, "struct GTY(()) ovlddata\n"); + fprintf (header_file, + "extern GTY(()) tree rs6000_builtin_info_fntype[RS6000_BIF_MAX];\n\n"); + + fprintf (header_file, "struct ovlddata\n"); fprintf (header_file, "{\n"); - fprintf (header_file, " const char *GTY((skip(\"\"))) bifname;\n"); - fprintf (header_file, " rs6000_gen_builtins GTY((skip(\"\"))) bifid;\n"); - fprintf (header_file, " tree fntype;\n"); - fprintf (header_file, " ovlddata *GTY((skip(\"\"))) next;\n"); + fprintf (header_file, " const char *bifname;\n"); + fprintf (header_file, " rs6000_gen_builtins bifid;\n"); + fprintf (header_file, " int next;\n"); fprintf (header_file, "};\n\n"); fprintf (header_file, "struct ovldrecord\n"); fprintf (header_file, "{\n"); fprintf (header_file, " const char *ovld_name;\n"); - fprintf (header_file, " ovlddata *first_instance;\n"); + fprintf (header_file, " int first_instance;\n"); fprintf (header_file, "};\n\n"); fprintf (header_file, - "extern GTY(()) ovlddata rs6000_instance_info[RS6000_INST_MAX];\n"); + "extern ovlddata rs6000_instance_info[RS6000_INST_MAX];\n"); + fprintf (header_file, "extern GTY(()) tree " + "rs6000_instance_info_fntype[RS6000_INST_MAX];\n"); fprintf (header_file, "extern ovldrecord rs6000_overload_info[];\n\n"); fprintf (header_file, "extern void rs6000_init_generated_builtins ();\n\n"); @@ -2481,7 +2484,7 @@ write_bif_static_init (void) fprintf (init_file, "bifdata rs6000_builtin_info[RS6000_BIF_MAX] =\n"); fprintf (init_file, " {\n"); fprintf (init_file, " { /* RS6000_BIF_NONE: */\n"); - fprintf (init_file, " \"\", ENB_ALWAYS, 0, CODE_FOR_nothing, 0,\n"); + fprintf (init_file, " \"\", ENB_ALWAYS, CODE_FOR_nothing, 0,\n"); fprintf (init_file, " 0, {0, 0, 0}, {RES_NONE, RES_NONE, RES_NONE},\n"); fprintf (init_file, " {0, 0, 0}, {0, 0, 0}, \"\", RS6000_BIF_NONE\n"); fprintf (init_file, " },\n"); @@ -2493,8 +2496,6 @@ write_bif_static_init (void) bifp->proto.bifname); fprintf (init_file, " /* enable*/\t%s,\n", enable_string[bifp->stanza]); - /* Type must be instantiated at run time. */ - fprintf (init_file, " /* fntype */\t0,\n"); fprintf (init_file, " /* icode */\tCODE_FOR_%s,\n", bifp->patname); fprintf (init_file, " /* nargs */\t%d,\n", @@ -2586,6 +2587,8 @@ write_bif_static_init (void) fprintf (init_file, " },\n"); } fprintf (init_file, " };\n\n"); + + fprintf (init_file, "tree rs6000_builtin_info_fntype[RS6000_BIF_MAX];\n\n"); } /* Write the decls and initializers for rs6000_overload_info[] and @@ -2598,7 +2601,7 @@ write_ovld_static_init (void) "- RS6000_OVLD_NONE] =\n"); fprintf (init_file, " {\n"); fprintf (init_file, " { /* RS6000_OVLD_NONE: */\n"); - fprintf (init_file, " \"\", NULL\n"); + fprintf (init_file, " \"\", -1\n"); fprintf (init_file, " },\n"); for (int i = 0; i <= curr_ovld_stanza; i++) { @@ -2607,7 +2610,7 @@ write_ovld_static_init (void) fprintf (init_file, " /* ovld_name */\t\"%s\",\n", ovld_stanzas[i].intern_name); /* First-instance must currently be instantiated at run time. */ - fprintf (init_file, " /* first_instance */\tNULL\n"); + fprintf (init_file, " /* first_instance */\t-1\n"); fprintf (init_file, " },\n"); } fprintf (init_file, " };\n\n"); @@ -2615,7 +2618,7 @@ write_ovld_static_init (void) fprintf (init_file, "ovlddata rs6000_instance_info[RS6000_INST_MAX] =\n"); fprintf (init_file, " {\n"); fprintf (init_file, " { /* RS6000_INST_NONE: */\n"); - fprintf (init_file, " \"\", RS6000_BIF_NONE, NULL_TREE, NULL\n"); + fprintf (init_file, " \"\", RS6000_BIF_NONE, -1\n"); fprintf (init_file, " },\n"); for (int i = 0; i <= curr_ovld; i++) { @@ -2625,19 +2628,20 @@ write_ovld_static_init (void) ovlds[i].proto.bifname); fprintf (init_file, " /* bifid */\tRS6000_BIF_%s,\n", ovlds[i].bif_id_name); - /* Type must be instantiated at run time. */ - fprintf (init_file, " /* fntype */\t0,\n"); fprintf (init_file, " /* next */\t"); if (i < curr_ovld && !strcmp (ovlds[i+1].proto.bifname, ovlds[i].proto.bifname)) fprintf (init_file, - "&rs6000_instance_info[RS6000_INST_%s]\n", + "RS6000_INST_%s\n", ovlds[i+1].ovld_id_name); else - fprintf (init_file, "NULL\n"); + fprintf (init_file, "-1\n"); fprintf (init_file, " },\n"); } fprintf (init_file, " };\n\n"); + + fprintf (init_file, + "tree rs6000_instance_info_fntype[RS6000_INST_MAX];\n\n"); } /* Write code to initialize the built-in function table. */ @@ -2647,7 +2651,7 @@ write_init_bif_table (void) for (int i = 0; i <= curr_bif; i++) { fprintf (init_file, - " rs6000_builtin_info[RS6000_BIF_%s].fntype" + " rs6000_builtin_info_fntype[RS6000_BIF_%s]" "\n = %s;\n", bifs[i].idname, bifs[i].fndecl); @@ -2736,7 +2740,7 @@ write_init_ovld_table (void) for (int i = 0; i <= curr_ovld; i++) { fprintf (init_file, - " rs6000_instance_info[RS6000_INST_%s].fntype" + " rs6000_instance_info_fntype[RS6000_INST_%s]" "\n = %s;\n", ovlds[i].ovld_id_name, ovlds[i].fndecl); @@ -2793,7 +2797,7 @@ write_init_ovld_table (void) ".first_instance\n", stanza->stanza_id); fprintf (init_file, - " = &rs6000_instance_info[RS6000_INST_%s];\n\n", + " = RS6000_INST_%s;\n\n", ovlds[i].ovld_id_name); } } commit 308ca60bc010f7745a34bdb4527ecced506f72c1 Author: Jakub Jelinek Date: Tue Jun 4 12:20:13 2024 +0200 invoke.texi: Clarify -march=lujiazui I was recently searching which exact CPUs are affected by the PR114576 wrong-code issue and went from the PTA_* bitmasks in GCC, so arrived at the goldmont, goldmont-plus, tremont and lujiazui CPUs (as -march= cases which do enable -maes and don't enable -mavx). But when double-checking that against the invoke.texi documentation, that was true for the first 3, but lujiazui said it supported AVX. I was really confused by that, until I found the https://gcc.gnu.org/pipermail/gcc-patches/2022-October/604407.html explanation. So, seems the CPUs do have AVX and F16C but -march=lujiazui doesn't enable those and even activelly attempts to filter those out from the announced CPUID features, in glibc as well as e.g. in libgcc. Thus, I think we should document what actually happens, otherwise users could assume that gcc -march=lujiazui predefines __AVX__ and __F16C__, which it doesn't. 2024-06-04 Jakub Jelinek * doc/invoke.texi (lujiazui): Clarify that while the CPUs do support AVX and F16C, -march=lujiazui actually doesn't enable those. (cherry picked from commit 09b4ab53155ea16e1fb12c2afcd9b6fe29a31c74) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 792ce283bb9..914c4bc8e6d 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -32743,8 +32743,10 @@ instruction set support. @item lujiazui ZHAOXIN lujiazui CPU with x86-64, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, -SSE4.2, AVX, POPCNT, AES, PCLMUL, RDRND, XSAVE, XSAVEOPT, FSGSBASE, CX16, -ABM, BMI, BMI2, F16C, FXSR, RDSEED instruction set support. +SSE4.2, POPCNT, AES, PCLMUL, RDRND, XSAVE, XSAVEOPT, FSGSBASE, CX16, +ABM, BMI, BMI2, FXSR, RDSEED instruction set support. While the CPUs +do support AVX and F16C, these aren't enabled by @code{-march=lujiazui} +for performance reasons. @item geode AMD Geode embedded processor with MMX and 3DNow!@: instruction set support. commit f9db8b0571348adfcc98204ea7be787058af85cd Author: Jakub Jelinek Date: Tue Jun 4 12:28:01 2024 +0200 builtins: Force SAVE_EXPR for __builtin_{add,sub,mul}_overflow [PR108789] The following testcase is miscompiled, because we use save_expr on the .{ADD,SUB,MUL}_OVERFLOW call we are creating, but if the first two operands are not INTEGER_CSTs (in that case we just fold it right away) but are TREE_READONLY/!TREE_SIDE_EFFECTS, save_expr doesn't actually create a SAVE_EXPR at all and so we lower it to *arg2 = REALPART_EXPR (.ADD_OVERFLOW (arg0, arg1)), \ IMAGPART_EXPR (.ADD_OVERFLOW (arg0, arg1)) which evaluates the ifn twice and just hope it will be CSEd back. As *arg2 aliases *arg0, that is not the case. The builtins are really never const/pure as they store into what the third arguments points to, so after handling the INTEGER_CST+INTEGER_CST case, I think we should just always use SAVE_EXPR. Just building SAVE_EXPR by hand and setting TREE_SIDE_EFFECTS on it doesn't work, because c_fully_fold optimizes it away again, so the following patch marks the ifn calls as TREE_SIDE_EFFECTS (but doesn't do it for the __builtin_{add,sub,mul}_overflow_p case which were designed for use especially in constant expressions and don't really evaluate the realpart side, so we don't really need a SAVE_EXPR in that case). 2024-06-04 Jakub Jelinek PR middle-end/108789 * builtins.cc (fold_builtin_arith_overflow): For ovf_only, don't call save_expr and don't build REALPART_EXPR, otherwise set TREE_SIDE_EFFECTS on call before calling save_expr. * gcc.c-torture/execute/pr108789.c: New test. (cherry picked from commit b8e28381cb5c0cddfe5201faf799d8b27f5d7d6c) diff --git a/gcc/builtins.cc b/gcc/builtins.cc index 1bfdc598eec..e5210bfde49 100644 --- a/gcc/builtins.cc +++ b/gcc/builtins.cc @@ -9539,7 +9539,21 @@ fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode, tree ctype = build_complex_type (type); tree call = build_call_expr_internal_loc (loc, ifn, ctype, 2, arg0, arg1); - tree tgt = save_expr (call); + tree tgt; + if (ovf_only) + { + tgt = call; + intres = NULL_TREE; + } + else + { + /* Force SAVE_EXPR even for calls which satisfy tree_invariant_p_1, + as while the call itself is const, the REALPART_EXPR store is + certainly not. And in any case, we want just one call, + not multiple and trying to CSE them later. */ + TREE_SIDE_EFFECTS (call) = 1; + tgt = save_expr (call); + } intres = build1_loc (loc, REALPART_EXPR, type, tgt); ovfres = build1_loc (loc, IMAGPART_EXPR, type, tgt); ovfres = fold_convert_loc (loc, boolean_type_node, ovfres); diff --git a/gcc/testsuite/gcc.c-torture/execute/pr108789.c b/gcc/testsuite/gcc.c-torture/execute/pr108789.c new file mode 100644 index 00000000000..32ee19be1c4 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr108789.c @@ -0,0 +1,39 @@ +/* PR middle-end/108789 */ + +int +add (unsigned *r, const unsigned *a, const unsigned *b) +{ + return __builtin_add_overflow (*a, *b, r); +} + +int +mul (unsigned *r, const unsigned *a, const unsigned *b) +{ + return __builtin_mul_overflow (*a, *b, r); +} + +int +main () +{ + unsigned x; + + /* 1073741824U + 1073741824U should not overflow. */ + x = (__INT_MAX__ + 1U) / 2; + if (add (&x, &x, &x)) + __builtin_abort (); + + /* 256U * 256U should not overflow */ + x = 1U << (sizeof (int) * __CHAR_BIT__ / 4); + if (mul (&x, &x, &x)) + __builtin_abort (); + + /* 2147483648U + 2147483648U should overflow */ + x = __INT_MAX__ + 1U; + if (!add (&x, &x, &x)) + __builtin_abort (); + + /* 65536U * 65536U should overflow */ + x = 1U << (sizeof (int) * __CHAR_BIT__ / 2); + if (!mul (&x, &x, &x)) + __builtin_abort (); +} commit 865d60ab4edbdb10d13000af81f9168fd3816a86 Author: Jakub Jelinek Date: Tue Jun 4 15:49:41 2024 +0200 fold-const: Fix up CLZ handling in tree_call_nonnegative_warnv_p [PR115337] The function currently incorrectly assumes all the __builtin_clz* and .CLZ calls have non-negative result. That is the case of the former which is UB on zero and has [0, prec-1] return value otherwise, and is the case of the single argument .CLZ as well (again, UB on zero), but for two argument .CLZ is the case only if the second argument is also nonnegative (or if we know the argument can't be zero, but let's do that just in the ranger IMHO). The following patch does that. 2024-06-04 Jakub Jelinek PR tree-optimization/115337 * fold-const.cc (tree_call_nonnegative_warnv_p) : If fn is CFN_CLZ, use CLZ_DEFINED_VALUE_AT. (cherry picked from commit b82a816000791e7a286c7836b3a473ec0e2a577b) diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index 25dd7c1094e..ef537e1c620 100644 --- a/gcc/fold-const.cc +++ b/gcc/fold-const.cc @@ -85,6 +85,7 @@ along with GCC; see the file COPYING3. If not see #include "vec-perm-indices.h" #include "asan.h" #include "gimple-range.h" +#include "internal-fn.h" /* Nonzero if we are folding constants inside an initializer or a C++ manifestly-constant-evaluated context; zero otherwise. @@ -14887,7 +14888,6 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1, CASE_CFN_FFS: CASE_CFN_PARITY: CASE_CFN_POPCOUNT: - CASE_CFN_CLZ: CASE_CFN_CLRSB: case CFN_BUILT_IN_BSWAP16: case CFN_BUILT_IN_BSWAP32: @@ -14896,6 +14896,22 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1, /* Always true. */ return true; + CASE_CFN_CLZ: + if (fn != CFN_CLZ) + return true; + else if (INTEGRAL_TYPE_P (TREE_TYPE (arg0))) + { + tree atype = TREE_TYPE (arg0); + int val = 0; + if (direct_internal_fn_supported_p (IFN_CLZ, atype, + OPTIMIZE_FOR_BOTH) + && CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (atype), + val) == 2 + && val >= 0) + return true; + } + break; + CASE_CFN_SQRT: CASE_CFN_SQRT_FN: /* sqrt(-0.0) is -0.0. */ commit 7813d94393f60ac641265cb3fc3a446f9f3aea7e Author: Jakub Jelinek Date: Thu Jun 6 22:12:11 2024 +0200 c: Fix up pointer types to may_alias structures [PR114493] The following testcase ICEs in ipa-free-lang, because the fld_incomplete_type_of gcc_assert (TYPE_CANONICAL (t2) != t2 && TYPE_CANONICAL (t2) == TYPE_CANONICAL (TREE_TYPE (t))); assertion doesn't hold. This is because t is a struct S * type which was created while struct S was still incomplete and without the may_alias attribute (and TYPE_CANONICAL of a pointer type is a type created with can_alias_all = false argument), while later on on the struct definition may_alias attribute was used. fld_incomplete_type_of then creates an incomplete distinct copy of the structure (but with the original attributes) but pointers created for it are because of the "may_alias" attribute TYPE_REF_CAN_ALIAS_ALL, including their TYPE_CANONICAL, because while that is created with !can_alias_all argument, we later set it because of the "may_alias" attribute on the to_type. This doesn't ICE with C++ since PR70512 fix because the C++ FE sets TYPE_REF_CAN_ALIAS_ALL on all pointer types to the class type (and its variants) when the may_alias is added. The following patch does that in the C FE as well. 2024-06-06 Jakub Jelinek PR c/114493 * c-decl.cc (c_fixup_may_alias): New function. (finish_struct): Call it if "may_alias" attribute is specified. * gcc.dg/pr114493-1.c: New test. * gcc.dg/pr114493-2.c: New test. (cherry picked from commit d5a3c6d43acb8b2211d9fb59d59482d74c010f01) diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 7dcb1141bf7..318e9c5b253 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -9115,6 +9115,17 @@ is_flexible_array_member_p (bool is_last_field, } +/* TYPE is a struct or union that we're applying may_alias to after the body is + parsed. Fixup any POINTER_TO types. */ + +static void +c_fixup_may_alias (tree type) +{ + for (tree t = TYPE_POINTER_TO (type); t; t = TYPE_NEXT_PTR_TO (t)) + for (tree v = TYPE_MAIN_VARIANT (t); v; v = TYPE_NEXT_VARIANT (v)) + TYPE_REF_CAN_ALIAS_ALL (v) = true; +} + /* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T. LOC is the location of the RECORD_TYPE or UNION_TYPE's definition. FIELDLIST is a chain of FIELD_DECL nodes for the fields. @@ -9409,6 +9420,10 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, warning_at (loc, 0, "union cannot be made transparent"); } + if (lookup_attribute ("may_alias", TYPE_ATTRIBUTES (t))) + for (x = TYPE_MAIN_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x)) + c_fixup_may_alias (x); + tree incomplete_vars = C_TYPE_INCOMPLETE_VARS (TYPE_MAIN_VARIANT (t)); for (x = TYPE_MAIN_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x)) { diff --git a/gcc/testsuite/gcc.dg/pr114493-1.c b/gcc/testsuite/gcc.dg/pr114493-1.c new file mode 100644 index 00000000000..446f33eac3b --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr114493-1.c @@ -0,0 +1,19 @@ +/* PR c/114493 */ +/* { dg-do compile { target lto } } */ +/* { dg-options "-O2 -flto" } */ + +void foo (void); +struct S; +struct S bar (struct S **); +struct S qux (const struct S **); + +struct __attribute__((__may_alias__)) S { + int s; +}; + +struct S +baz (void) +{ + foo (); + return (struct S) {}; +} diff --git a/gcc/testsuite/gcc.dg/pr114493-2.c b/gcc/testsuite/gcc.dg/pr114493-2.c new file mode 100644 index 00000000000..93e3d6e5bc4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr114493-2.c @@ -0,0 +1,26 @@ +/* PR c/114493 */ +/* { dg-do compile { target lto } } */ +/* { dg-options "-O2 -flto -std=c2x" } */ + +void foo (void); +struct S; +struct S bar (struct S **); +struct S qux (const struct S **); + +void +corge (void) +{ + struct S { int s; } s; + s.s = 0; +} + +struct __attribute__((__may_alias__)) S { + int s; +}; + +struct S +baz (void) +{ + foo (); + return (struct S) {}; +} commit 26113c278069e7e58f5e4149ef86a30c043b262f Author: Matthias Kretz Date: Mon May 6 12:13:55 2024 +0200 libstdc++: Use __builtin_shufflevector for simd split and concat Signed-off-by: Matthias Kretz libstdc++-v3/ChangeLog: PR libstdc++/114958 * include/experimental/bits/simd.h (__as_vector): Return scalar simd as one-element vector. Return vector from single-vector fixed_size simd. (__vec_shuffle): New. (__extract_part): Adjust return type signature. (split): Use __extract_part for any split into non-fixed_size simds. (concat): If the return type stores a single vector, use __vec_shuffle (which calls __builtin_shufflevector) to produce the return value. * include/experimental/bits/simd_builtin.h (__shift_elements_right): Removed. (__extract_part): Return single elements directly. Use __vec_shuffle (which calls __builtin_shufflevector) to for all non-trivial cases. * include/experimental/bits/simd_fixed_size.h (__extract_part): Return single elements directly. * testsuite/experimental/simd/pr114958.cc: New test. (cherry picked from commit fb1649f8b4ad5043dd0e65e4e3a643a0ced018a9) diff --git a/libstdc++-v3/include/experimental/bits/simd.h b/libstdc++-v3/include/experimental/bits/simd.h index 63cc7bef610..6d3209b1a0e 100644 --- a/libstdc++-v3/include/experimental/bits/simd.h +++ b/libstdc++-v3/include/experimental/bits/simd.h @@ -1616,7 +1616,24 @@ template if constexpr (__is_vector_type_v<_V>) return __x; else if constexpr (is_simd<_V>::value || is_simd_mask<_V>::value) - return __data(__x)._M_data; + { + if constexpr (__is_fixed_size_abi_v) + { + static_assert(is_simd<_V>::value); + static_assert(_V::abi_type::template __traits< + typename _V::value_type>::_SimdMember::_S_tuple_size == 1); + return __as_vector(__data(__x).first); + } + else if constexpr (_V::size() > 1) + return __data(__x)._M_data; + else + { + static_assert(is_simd<_V>::value); + using _Tp = typename _V::value_type; + using _RV [[__gnu__::__vector_size__(sizeof(_Tp))]] = _Tp; + return _RV{__data(__x)}; + } + } else if constexpr (__is_vectorizable_v<_V>) return __vector_type_t<_V, 2>{__x}; else @@ -2026,6 +2043,60 @@ template > return ~__a; } +// }}} +// __vec_shuffle{{{ +template + _GLIBCXX_SIMD_INTRINSIC constexpr auto + __vec_shuffle(_T0 __x, _T1 __y, index_sequence<_Is...> __seq, _Fun __idx_perm) + { + constexpr int _N0 = sizeof(__x) / sizeof(__x[0]); + constexpr int _N1 = sizeof(__y) / sizeof(__y[0]); +#if __has_builtin(__builtin_shufflevector) +#ifdef __clang__ + // Clang requires _T0 == _T1 + if constexpr (sizeof(__x) > sizeof(__y) and _N1 == 1) + return __vec_shuffle(__x, _T0{__y[0]}, __seq, __idx_perm); + else if constexpr (sizeof(__x) > sizeof(__y)) + return __vec_shuffle(__x, __intrin_bitcast<_T0>(__y), __seq, __idx_perm); + else if constexpr (sizeof(__x) < sizeof(__y) and _N0 == 1) + return __vec_shuffle(_T1{__x[0]}, __y, __seq, [=](int __i) { + __i = __idx_perm(__i); + return __i < _N0 ? __i : __i - _N0 + _N1; + }); + else if constexpr (sizeof(__x) < sizeof(__y)) + return __vec_shuffle(__intrin_bitcast<_T1>(__x), __y, __seq, [=](int __i) { + __i = __idx_perm(__i); + return __i < _N0 ? __i : __i - _N0 + _N1; + }); + else +#endif + return __builtin_shufflevector(__x, __y, [=] { + constexpr int __j = __idx_perm(_Is); + static_assert(__j < _N0 + _N1); + return __j; + }()...); +#else + using _Tp = __remove_cvref_t; + return __vector_type_t<_Tp, sizeof...(_Is)> { + [=]() -> _Tp { + constexpr int __j = __idx_perm(_Is); + static_assert(__j < _N0 + _N1); + if constexpr (__j < 0) + return 0; + else if constexpr (__j < _N0) + return __x[__j]; + else + return __y[__j - _N0]; + }()... + }; +#endif + } + +template + _GLIBCXX_SIMD_INTRINSIC constexpr auto + __vec_shuffle(_T0 __x, _Seq __seq, _Fun __idx_perm) + { return __vec_shuffle(__x, _T0(), __seq, __idx_perm); } + // }}} // __concat{{{ template , @@ -3886,7 +3957,7 @@ template _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_CONST constexpr - _SimdWrapper<_Tp, _Np / _Total * _Combine> + conditional_t<_Np == _Total and _Combine == 1, _Tp, _SimdWrapper<_Tp, _Np / _Total * _Combine>> __extract_part(const _SimdWrapper<_Tp, _Np> __x); template @@ -4150,48 +4221,21 @@ template __split_wrapper(_SL::template _S_pop_front<1>(), __data(__x).second)); } - else if constexpr ((!is_same_v> && ...) - && (!__is_fixed_size_abi_v< - simd_abi::deduce_t<_Tp, _Sizes>> && ...)) + else if constexpr ((!__is_fixed_size_abi_v> && ...)) { - if constexpr (((_Sizes * 2 == _Np) && ...)) - return {{__private_init, __extract_part<0, 2>(__data(__x))}, - {__private_init, __extract_part<1, 2>(__data(__x))}}; - else if constexpr (is_same_v<_SizeList<_Sizes...>, - _SizeList<_Np / 3, _Np / 3, _Np / 3>>) - return {{__private_init, __extract_part<0, 3>(__data(__x))}, - {__private_init, __extract_part<1, 3>(__data(__x))}, - {__private_init, __extract_part<2, 3>(__data(__x))}}; - else if constexpr (is_same_v<_SizeList<_Sizes...>, - _SizeList<2 * _Np / 3, _Np / 3>>) - return {{__private_init, __extract_part<0, 3, 2>(__data(__x))}, - {__private_init, __extract_part<2, 3>(__data(__x))}}; - else if constexpr (is_same_v<_SizeList<_Sizes...>, - _SizeList<_Np / 3, 2 * _Np / 3>>) - return {{__private_init, __extract_part<0, 3>(__data(__x))}, - {__private_init, __extract_part<1, 3, 2>(__data(__x))}}; - else if constexpr (is_same_v<_SizeList<_Sizes...>, - _SizeList<_Np / 2, _Np / 4, _Np / 4>>) - return {{__private_init, __extract_part<0, 2>(__data(__x))}, - {__private_init, __extract_part<2, 4>(__data(__x))}, - {__private_init, __extract_part<3, 4>(__data(__x))}}; - else if constexpr (is_same_v<_SizeList<_Sizes...>, - _SizeList<_Np / 4, _Np / 4, _Np / 2>>) - return {{__private_init, __extract_part<0, 4>(__data(__x))}, - {__private_init, __extract_part<1, 4>(__data(__x))}, - {__private_init, __extract_part<1, 2>(__data(__x))}}; - else if constexpr (is_same_v<_SizeList<_Sizes...>, - _SizeList<_Np / 4, _Np / 2, _Np / 4>>) - return {{__private_init, __extract_part<0, 4>(__data(__x))}, - {__private_init, __extract_center(__data(__x))}, - {__private_init, __extract_part<3, 4>(__data(__x))}}; - else if constexpr (((_Sizes * 4 == _Np) && ...)) - return {{__private_init, __extract_part<0, 4>(__data(__x))}, - {__private_init, __extract_part<1, 4>(__data(__x))}, - {__private_init, __extract_part<2, 4>(__data(__x))}, - {__private_init, __extract_part<3, 4>(__data(__x))}}; - // else fall through + constexpr array __size = {_Sizes...}; + return __generate_from_n_evaluations( + [&](auto __i) constexpr { + constexpr size_t __offset = [&]() { + size_t __r = 0; + for (unsigned __j = 0; __j < __i; ++__j) + __r += __size[__j]; + return __r; + }(); + return __deduced_simd<_Tp, __size[__i]>( + __private_init, + __extract_part<__offset, _Np, __size[__i]>(__data(__x))); + }); } #ifdef _GLIBCXX_SIMD_USE_ALIASING_LOADS const __may_alias<_Tp>* const __element_ptr @@ -4253,14 +4297,37 @@ template simd<_Tp, simd_abi::deduce_t<_Tp, (simd_size_v<_Tp, _As> + ...)>> concat(const simd<_Tp, _As>&... __xs) { - using _Rp = __deduced_simd<_Tp, (simd_size_v<_Tp, _As> + ...)>; + constexpr int _Np = (simd_size_v<_Tp, _As> + ...); + using _Abi = simd_abi::deduce_t<_Tp, _Np>; + using _Rp = simd<_Tp, _Abi>; + using _RW = typename _SimdTraits<_Tp, _Abi>::_SimdMember; if constexpr (sizeof...(__xs) == 1) return simd_cast<_Rp>(__xs...); else if ((... && __xs._M_is_constprop())) - return simd<_Tp, - simd_abi::deduce_t<_Tp, (simd_size_v<_Tp, _As> + ...)>>( - [&](auto __i) constexpr _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA + return _Rp([&](auto __i) constexpr _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA { return __subscript_in_pack<__i>(__xs...); }); + else if constexpr (__is_simd_wrapper_v<_RW> and sizeof...(__xs) == 2) + { + return {__private_init, + __vec_shuffle(__as_vector(__xs)..., std::make_index_sequence<_RW::_S_full_size>(), + [](int __i) { + constexpr int __sizes[2] = {int(simd_size_v<_Tp, _As>)...}; + constexpr int __padding0 + = sizeof(__vector_type_t<_Tp, __sizes[0]>) / sizeof(_Tp) + - __sizes[0]; + return __i >= _Np ? -1 : __i < __sizes[0] ? __i : __i + __padding0; + })}; + } + else if constexpr (__is_simd_wrapper_v<_RW> and sizeof...(__xs) == 3) + return [](const auto& __x0, const auto& __x1, const auto& __x2) + _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA { + return concat(concat(__x0, __x1), __x2); + }(__xs...); + else if constexpr (__is_simd_wrapper_v<_RW> and sizeof...(__xs) > 3) + return [](const auto& __x0, const auto& __x1, const auto&... __rest) + _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA { + return concat(concat(__x0, __x1), concat(__rest...)); + }(__xs...); else { _Rp __r{}; diff --git a/libstdc++-v3/include/experimental/bits/simd_builtin.h b/libstdc++-v3/include/experimental/bits/simd_builtin.h index 2fa1cf48750..0c2b587f72d 100644 --- a/libstdc++-v3/include/experimental/bits/simd_builtin.h +++ b/libstdc++-v3/include/experimental/bits/simd_builtin.h @@ -92,124 +92,16 @@ template >(__x._M_data); } -// }}} -// __shift_elements_right{{{ -// if (__shift % 2ⁿ == 0) => the low n Bytes are correct -template > - _GLIBCXX_SIMD_INTRINSIC _Tp - __shift_elements_right(_Tp __v) - { - [[maybe_unused]] const auto __iv = __to_intrin(__v); - static_assert(__shift <= sizeof(_Tp)); - if constexpr (__shift == 0) - return __v; - else if constexpr (__shift == sizeof(_Tp)) - return _Tp(); -#if _GLIBCXX_SIMD_X86INTRIN // {{{ - else if constexpr (__have_sse && __shift == 8 - && _TVT::template _S_is) - return _mm_movehl_ps(__iv, __iv); - else if constexpr (__have_sse2 && __shift == 8 - && _TVT::template _S_is) - return _mm_unpackhi_pd(__iv, __iv); - else if constexpr (__have_sse2 && sizeof(_Tp) == 16) - return reinterpret_cast( - _mm_srli_si128(reinterpret_cast<__m128i>(__iv), __shift)); - else if constexpr (__shift == 16 && sizeof(_Tp) == 32) - { - /*if constexpr (__have_avx && _TVT::template _S_is) - return _mm256_permute2f128_pd(__iv, __iv, 0x81); - else if constexpr (__have_avx && _TVT::template _S_is) - return _mm256_permute2f128_ps(__iv, __iv, 0x81); - else if constexpr (__have_avx) - return reinterpret_cast( - _mm256_permute2f128_si256(__iv, __iv, 0x81)); - else*/ - return __zero_extend(__hi128(__v)); - } - else if constexpr (__have_avx2 && sizeof(_Tp) == 32 && __shift < 16) - { - const auto __vll = __vector_bitcast<_LLong>(__v); - return reinterpret_cast( - _mm256_alignr_epi8(_mm256_permute2x128_si256(__vll, __vll, 0x81), - __vll, __shift)); - } - else if constexpr (__have_avx && sizeof(_Tp) == 32 && __shift < 16) - { - const auto __vll = __vector_bitcast<_LLong>(__v); - return reinterpret_cast( - __concat(_mm_alignr_epi8(__hi128(__vll), __lo128(__vll), __shift), - _mm_srli_si128(__hi128(__vll), __shift))); - } - else if constexpr (sizeof(_Tp) == 32 && __shift > 16) - return __zero_extend(__shift_elements_right<__shift - 16>(__hi128(__v))); - else if constexpr (sizeof(_Tp) == 64 && __shift == 32) - return __zero_extend(__hi256(__v)); - else if constexpr (__have_avx512f && sizeof(_Tp) == 64) - { - if constexpr (__shift >= 48) - return __zero_extend( - __shift_elements_right<__shift - 48>(__extract<3, 4>(__v))); - else if constexpr (__shift >= 32) - return __zero_extend( - __shift_elements_right<__shift - 32>(__hi256(__v))); - else if constexpr (__shift % 8 == 0) - return reinterpret_cast( - _mm512_alignr_epi64(__m512i(), __intrin_bitcast<__m512i>(__v), - __shift / 8)); - else if constexpr (__shift % 4 == 0) - return reinterpret_cast( - _mm512_alignr_epi32(__m512i(), __intrin_bitcast<__m512i>(__v), - __shift / 4)); - else if constexpr (__have_avx512bw && __shift < 16) - { - const auto __vll = __vector_bitcast<_LLong>(__v); - return reinterpret_cast( - _mm512_alignr_epi8(_mm512_shuffle_i32x4(__vll, __vll, 0xf9), - __vll, __shift)); - } - else if constexpr (__have_avx512bw && __shift < 32) - { - const auto __vll = __vector_bitcast<_LLong>(__v); - return reinterpret_cast( - _mm512_alignr_epi8(_mm512_shuffle_i32x4(__vll, __m512i(), 0xee), - _mm512_shuffle_i32x4(__vll, __vll, 0xf9), - __shift - 16)); - } - else - __assert_unreachable<_Tp>(); - } - /* - } else if constexpr (__shift % 16 == 0 && sizeof(_Tp) == 64) - return __auto_bitcast(__extract<__shift / 16, 4>(__v)); - */ -#endif // _GLIBCXX_SIMD_X86INTRIN }}} - else - { - constexpr int __chunksize = __shift % 8 == 0 ? 8 - : __shift % 4 == 0 ? 4 - : __shift % 2 == 0 ? 2 - : 1; - auto __w = __vector_bitcast<__int_with_sizeof_t<__chunksize>>(__v); - using _Up = decltype(__w); - return __intrin_bitcast<_Tp>( - __call_with_n_evaluations<(sizeof(_Tp) - __shift) / __chunksize>( - [](auto... __chunks) _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA { - return _Up{__chunks...}; - }, [&](auto __i) _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA { - return __w[__shift / __chunksize + __i]; - })); - } - } - // }}} // __extract_part(_SimdWrapper<_Tp, _Np>) {{{ template _GLIBCXX_SIMD_INTRINSIC _GLIBCXX_CONST constexpr - _SimdWrapper<_Tp, _Np / _Total * _Combine> + conditional_t<_Np == _Total and _Combine == 1, _Tp, _SimdWrapper<_Tp, _Np / _Total * _Combine>> __extract_part(const _SimdWrapper<_Tp, _Np> __x) { - if constexpr (_Index % 2 == 0 && _Total % 2 == 0 && _Combine % 2 == 0) + if constexpr (_Np == _Total and _Combine == 1) + return __x[_Index]; + else if constexpr (_Index % 2 == 0 && _Total % 2 == 0 && _Combine % 2 == 0) return __extract_part<_Index / 2, _Total / 2, _Combine / 2>(__x); else { @@ -235,39 +127,11 @@ template return __x; else if constexpr (_Index == 0) return __intrin_bitcast<_R>(__as_vector(__x)); -#if _GLIBCXX_SIMD_X86INTRIN // {{{ - else if constexpr (sizeof(__x) == 32 - && __return_size * sizeof(_Tp) <= 16) - { - constexpr size_t __bytes_to_skip = __values_to_skip * sizeof(_Tp); - if constexpr (__bytes_to_skip == 16) - return __vector_bitcast<_Tp, __return_size>( - __hi128(__as_vector(__x))); - else - return __vector_bitcast<_Tp, __return_size>( - _mm_alignr_epi8(__hi128(__vector_bitcast<_LLong>(__x)), - __lo128(__vector_bitcast<_LLong>(__x)), - __bytes_to_skip)); - } -#endif // _GLIBCXX_SIMD_X86INTRIN }}} - else if constexpr (_Index > 0 - && (__values_to_skip % __return_size != 0 - || sizeof(_R) >= 8) - && (__values_to_skip + __return_size) * sizeof(_Tp) - <= 64 - && sizeof(__x) >= 16) - return __intrin_bitcast<_R>( - __shift_elements_right<__values_to_skip * sizeof(_Tp)>( - __as_vector(__x))); else - { - _R __r = {}; - __builtin_memcpy(&__r, - reinterpret_cast(&__x) - + sizeof(_Tp) * __values_to_skip, - __return_size * sizeof(_Tp)); - return __r; - } + return __vec_shuffle(__as_vector(__x), make_index_sequence<__bit_ceil(__return_size)>(), + [](size_t __i) { + return __i + __values_to_skip; + }); } } diff --git a/libstdc++-v3/include/experimental/bits/simd_fixed_size.h b/libstdc++-v3/include/experimental/bits/simd_fixed_size.h index 131fbd254be..20f158aa84e 100644 --- a/libstdc++-v3/include/experimental/bits/simd_fixed_size.h +++ b/libstdc++-v3/include/experimental/bits/simd_fixed_size.h @@ -927,7 +927,9 @@ template ; // handle (optimize) the simple cases - if constexpr (_Index == 0 && _Tuple::_S_first_size == __return_size) + if constexpr (__return_size == 1) + return __x[integral_constant()]; + else if constexpr (_Index == 0 && _Tuple::_S_first_size == __return_size) return __x.first._M_data; else if constexpr (_Index == 0 && _Total == _Combine) return __x; diff --git a/libstdc++-v3/testsuite/experimental/simd/pr114958.cc b/libstdc++-v3/testsuite/experimental/simd/pr114958.cc new file mode 100644 index 00000000000..f7b09ad9ba7 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/simd/pr114958.cc @@ -0,0 +1,20 @@ +// { dg-options "-std=c++17" } +// { dg-do compile { target x86_64-*-* } } +// { dg-require-effective-target c++17 } +// { dg-additional-options "-march=x86-64-v3" { target x86_64-*-* } } +// { dg-require-cmath "" } +// { dg-final { scan-assembler-times "vperm(?:q|pd)\\s+\\\$144" 1 } } + +#include + +namespace stdx = std::experimental; + +using T = std::uint64_t; +using V = stdx::simd>; +using V1 = stdx::simd; + +V perm(V data) +{ + auto [carry, _] = stdx::split<3, 1>(data); + return concat(V1(), carry); +} commit 0efc27068e59cac6bd80ff962e92618a037bbfe8 Author: Matthias Kretz Date: Wed May 15 11:02:22 2024 +0200 libstdc++: Avoid MMX return types from __builtin_shufflevector This resolves a regression on i686 that was introduced with r15-429-gfb1649f8b4ad50. Signed-off-by: Matthias Kretz libstdc++-v3/ChangeLog: PR libstdc++/115247 * include/experimental/bits/simd.h (__as_vector): Don't use vector_size(8) on __i386__. (__vec_shuffle): Never return MMX vectors, widen to 16 bytes instead. (concat): Fix padding calculation to pick up widening logic from __as_vector. (cherry picked from commit 241a6cc88d866fb36bd35ddb3edb659453d6322e) diff --git a/libstdc++-v3/include/experimental/bits/simd.h b/libstdc++-v3/include/experimental/bits/simd.h index 6d3209b1a0e..ce7805e43e5 100644 --- a/libstdc++-v3/include/experimental/bits/simd.h +++ b/libstdc++-v3/include/experimental/bits/simd.h @@ -1630,7 +1630,12 @@ template { static_assert(is_simd<_V>::value); using _Tp = typename _V::value_type; +#ifdef __i386__ + constexpr auto __bytes = sizeof(_Tp) == 8 ? 16 : sizeof(_Tp); + using _RV [[__gnu__::__vector_size__(__bytes)]] = _Tp; +#else using _RV [[__gnu__::__vector_size__(sizeof(_Tp))]] = _Tp; +#endif return _RV{__data(__x)}; } } @@ -2046,11 +2051,14 @@ template > // }}} // __vec_shuffle{{{ template - _GLIBCXX_SIMD_INTRINSIC constexpr auto + _GLIBCXX_SIMD_INTRINSIC constexpr + __vector_type_t()[0])>, sizeof...(_Is)> __vec_shuffle(_T0 __x, _T1 __y, index_sequence<_Is...> __seq, _Fun __idx_perm) { constexpr int _N0 = sizeof(__x) / sizeof(__x[0]); constexpr int _N1 = sizeof(__y) / sizeof(__y[0]); + using _Tp = remove_reference_t()[0])>; + using _RV [[maybe_unused]] = __vector_type_t<_Tp, sizeof...(_Is)>; #if __has_builtin(__builtin_shufflevector) #ifdef __clang__ // Clang requires _T0 == _T1 @@ -2070,14 +2078,23 @@ template }); else #endif - return __builtin_shufflevector(__x, __y, [=] { - constexpr int __j = __idx_perm(_Is); - static_assert(__j < _N0 + _N1); - return __j; - }()...); + { + const auto __r = __builtin_shufflevector(__x, __y, [=] { + constexpr int __j = __idx_perm(_Is); + static_assert(__j < _N0 + _N1); + return __j; + }()...); +#ifdef __i386__ + if constexpr (sizeof(__r) == sizeof(_RV)) + return __r; + else + return _RV {__r[_Is]...}; +#else + return __r; +#endif + } #else - using _Tp = __remove_cvref_t; - return __vector_type_t<_Tp, sizeof...(_Is)> { + return _RV { [=]() -> _Tp { constexpr int __j = __idx_perm(_Is); static_assert(__j < _N0 + _N1); @@ -4312,9 +4329,9 @@ template __vec_shuffle(__as_vector(__xs)..., std::make_index_sequence<_RW::_S_full_size>(), [](int __i) { constexpr int __sizes[2] = {int(simd_size_v<_Tp, _As>)...}; - constexpr int __padding0 - = sizeof(__vector_type_t<_Tp, __sizes[0]>) / sizeof(_Tp) - - __sizes[0]; + constexpr int __vsizes[2] + = {int(sizeof(__as_vector(__xs)) / sizeof(_Tp))...}; + constexpr int __padding0 = __vsizes[0] - __sizes[0]; return __i >= _Np ? -1 : __i < __sizes[0] ? __i : __i + __padding0; })}; } commit ef2169090d0868e4718c2ebf25365aaa52c22139 Author: Matthias Kretz Date: Mon Jun 3 12:02:07 2024 +0200 libstdc++: Fix simd conversion for -fno-signed-char for Clang The special case for Clang in the trait producing a signed integer type lead to the trait returning 'char' where it should have been 'signed char'. This workaround was introduced because on Clang the return type of vector compares was not convertible to '_SimdWrapper< __int_for_sizeof_t<...' unless '__int_for_sizeof_t' was an alias for 'char'. In order to not rewrite the complete mask type code (there is code scattered around the implementation assuming signed integers), this needs to be 'signed char'; so the special case for Clang needs to be removed. The conversion issue is now solved in _SimdWrapper, which now additionally allows conversion from vector types with compatible integral type. Signed-off-by: Matthias Kretz libstdc++-v3/ChangeLog: PR libstdc++/115308 * include/experimental/bits/simd.h (__int_for_sizeof): Remove special cases for __clang__. (_SimdWrapper): Change constructor overload set to allow conversion from vector types with integral conversions via bit reinterpretation. (cherry picked from commit 8e36cf4c5c9140915d0019999db132a900b48037) diff --git a/libstdc++-v3/include/experimental/bits/simd.h b/libstdc++-v3/include/experimental/bits/simd.h index ce7805e43e5..e6c407d86fa 100644 --- a/libstdc++-v3/include/experimental/bits/simd.h +++ b/libstdc++-v3/include/experimental/bits/simd.h @@ -584,19 +584,12 @@ template static_assert(_Bytes > 0); if constexpr (_Bytes == sizeof(int)) return int(); - #ifdef __clang__ - else if constexpr (_Bytes == sizeof(char)) - return char(); - #else else if constexpr (_Bytes == sizeof(_SChar)) return _SChar(); - #endif else if constexpr (_Bytes == sizeof(short)) return short(); - #ifndef __clang__ else if constexpr (_Bytes == sizeof(long)) return long(); - #endif else if constexpr (_Bytes == sizeof(_LLong)) return _LLong(); #ifdef __SIZEOF_INT128__ @@ -2712,6 +2705,8 @@ template // }}} // _SimdWrapper{{{ +struct _DisabledSimdWrapper; + template struct _SimdWrapper< _Tp, _Width, @@ -2721,16 +2716,17 @@ template == sizeof(__vector_type_t<_Tp, _Width>), __vector_type_t<_Tp, _Width>> { - using _Base - = _SimdWrapperBase<__has_iec559_behavior<__signaling_NaN, _Tp>::value - && sizeof(_Tp) * _Width - == sizeof(__vector_type_t<_Tp, _Width>), - __vector_type_t<_Tp, _Width>>; + static constexpr bool _S_need_default_init + = __has_iec559_behavior<__signaling_NaN, _Tp>::value + and sizeof(_Tp) * _Width == sizeof(__vector_type_t<_Tp, _Width>); + + using _BuiltinType = __vector_type_t<_Tp, _Width>; + + using _Base = _SimdWrapperBase<_S_need_default_init, _BuiltinType>; static_assert(__is_vectorizable_v<_Tp>); static_assert(_Width >= 2); // 1 doesn't make sense, use _Tp directly then - using _BuiltinType = __vector_type_t<_Tp, _Width>; using value_type = _Tp; static inline constexpr size_t _S_full_size @@ -2766,13 +2762,26 @@ template _GLIBCXX_SIMD_INTRINSIC constexpr _SimdWrapper& operator=(_SimdWrapper&&) = default; - template >, - is_same<_V, __intrinsic_type_t<_Tp, _Width>>>>> + // Convert from exactly matching __vector_type_t + using _SimdWrapperBase<_S_need_default_init, _BuiltinType>::_SimdWrapperBase; + + // Convert from __intrinsic_type_t if __intrinsic_type_t and __vector_type_t differ, otherwise + // this ctor should not exist. Making the argument type unusable is our next best solution. + _GLIBCXX_SIMD_INTRINSIC constexpr + _SimdWrapper(conditional_t>, + _DisabledSimdWrapper, __intrinsic_type_t<_Tp, _Width>> __x) + : _Base(__vector_bitcast<_Tp, _Width>(__x)) {} + + // Convert from different __vector_type_t, but only if bit reinterpretation is a correct + // conversion of the value_type + template , + typename = enable_if_t + and is_integral_v>> _GLIBCXX_SIMD_INTRINSIC constexpr _SimdWrapper(_V __x) - // __vector_bitcast can convert e.g. __m128 to __vector(2) float - : _Base(__vector_bitcast<_Tp, _Width>(__x)) {} + : _Base(reinterpret_cast<_BuiltinType>(__x)) {} template && ...) commit 6eb0e931097a8fec01591051c9ef582d52fe7f0c Author: Andrew Pinski Date: Tue Jun 11 12:30:01 2024 -0700 Fix building JIT with musl libc [PR115442] Just like r13-6662-g0e6f87835ccabf but this time for jit/jit-recording.cc. Pushed as obvious after a quick build to make sure jit still builds. gcc/jit/ChangeLog: PR jit/115442 * jit-recording.cc: Define INCLUDE_SSTREAM before including system.h and don't directly incldue sstream. Signed-off-by: Andrew Pinski (cherry picked from commit e4244b88d75124f6957bfa080c8ad34017364e53) diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc index cf734cf7ef5..914082ae861 100644 --- a/gcc/jit/jit-recording.cc +++ b/gcc/jit/jit-recording.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "config.h" +#define INCLUDE_SSTREAM #include "system.h" #include "coretypes.h" #include "tm.h" commit 3f5d0ca6850297239e9ce98b33ee7751028716b3 Author: GCC Administrator Date: Wed Jun 12 00:22:42 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 62237b108ea..d1c13cae7cd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,63 @@ +2024-06-11 Jakub Jelinek + + Backported from master: + 2024-06-04 Jakub Jelinek + + PR tree-optimization/115337 + * fold-const.cc (tree_call_nonnegative_warnv_p) : + If fn is CFN_CLZ, use CLZ_DEFINED_VALUE_AT. + +2024-06-11 Jakub Jelinek + + Backported from master: + 2024-06-04 Jakub Jelinek + + PR middle-end/108789 + * builtins.cc (fold_builtin_arith_overflow): For ovf_only, + don't call save_expr and don't build REALPART_EXPR, otherwise + set TREE_SIDE_EFFECTS on call before calling save_expr. + +2024-06-11 Jakub Jelinek + + Backported from master: + 2024-06-04 Jakub Jelinek + + * doc/invoke.texi (lujiazui): Clarify that while the CPUs do support + AVX and F16C, -march=lujiazui actually doesn't enable those. + +2024-06-11 Jakub Jelinek + + Backported from master: + 2024-06-03 Jakub Jelinek + + PR target/115324 + * config/rs6000/rs6000-gen-builtins.cc (write_decls): Remove + GTY markup from struct bifdata and struct ovlddata and remove their + fntype members. Change next member in struct ovlddata and + first_instance member of struct ovldrecord to have int type rather + than struct ovlddata *. Remove GTY markup from rs6000_builtin_info + and rs6000_instance_info arrays, declare new + rs6000_builtin_info_fntype and rs6000_instance_info_fntype arrays, + which have GTY markup. + (write_bif_static_init): Adjust for the above changes. + (write_ovld_static_init): Likewise. + (write_init_bif_table): Likewise. + (write_init_ovld_table): Likewise. + * config/rs6000/rs6000-builtin.cc (rs6000_init_builtins): Likewise. + * config/rs6000/rs6000-c.cc (find_instance): Likewise. Make static. + (altivec_resolve_overloaded_builtin): Adjust for the above changes. + +2024-06-11 Jakub Jelinek + + Backported from master: + 2024-05-15 Jakub Jelinek + + PR rtl-optimization/114902 + PR rtl-optimization/115092 + * combine.cc (simplify_compare_const): Don't optimize + GE op0 SIGNED_MIN or LT op0 SIGNED_MIN into NE op0 const0_rtx or + EQ op0 const0_rtx. + 2024-06-07 Jan Hubicka Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 9561fe84baa..da7aa8ad65c 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240611 +20240612 diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index ef66688f68a..fc98e3e1fca 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,13 @@ +2024-06-11 Jakub Jelinek + + Backported from master: + 2024-06-06 Jakub Jelinek + + PR c/114493 + * c-decl.cc (c_fixup_may_alias): New function. + (finish_struct): Call it if "may_alias" attribute is + specified. + 2024-05-21 Release Manager * GCC 13.3.0 released. diff --git a/gcc/jit/ChangeLog b/gcc/jit/ChangeLog index 89b4a6a2157..dd792870a54 100644 --- a/gcc/jit/ChangeLog +++ b/gcc/jit/ChangeLog @@ -1,3 +1,12 @@ +2024-06-11 Andrew Pinski + + Backported from master: + 2024-06-11 Andrew Pinski + + PR jit/115442 + * jit-recording.cc: Define INCLUDE_SSTREAM before including + system.h and don't directly incldue sstream. + 2024-05-21 Release Manager * GCC 13.3.0 released. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index afe4612e598..76ae98870e0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,30 @@ +2024-06-11 Jakub Jelinek + + Backported from master: + 2024-06-06 Jakub Jelinek + + PR c/114493 + * gcc.dg/pr114493-1.c: New test. + * gcc.dg/pr114493-2.c: New test. + +2024-06-11 Jakub Jelinek + + Backported from master: + 2024-06-04 Jakub Jelinek + + PR middle-end/108789 + * gcc.c-torture/execute/pr108789.c: New test. + +2024-06-11 Jakub Jelinek + + Backported from master: + 2024-05-15 Jakub Jelinek + + PR rtl-optimization/114902 + PR rtl-optimization/115092 + * gcc.dg/pr114902.c: New test. + * gcc.dg/pr115092.c: New test. + 2024-06-10 Eric Botcazou * gnat.dg/incomplete8.adb: New test. diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 83badc78ee9..fad3d1c2b50 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,53 @@ +2024-06-11 Matthias Kretz + + Backported from master: + 2024-06-04 Matthias Kretz + + PR libstdc++/115308 + * include/experimental/bits/simd.h (__int_for_sizeof): Remove + special cases for __clang__. + (_SimdWrapper): Change constructor overload set to allow + conversion from vector types with integral conversions via bit + reinterpretation. + +2024-06-11 Matthias Kretz + + Backported from master: + 2024-05-29 Matthias Kretz + + PR libstdc++/115247 + * include/experimental/bits/simd.h (__as_vector): Don't use + vector_size(8) on __i386__. + (__vec_shuffle): Never return MMX vectors, widen to 16 bytes + instead. + (concat): Fix padding calculation to pick up widening logic from + __as_vector. + +2024-06-11 Matthias Kretz + + Backported from master: + 2024-05-13 Matthias Kretz + + PR libstdc++/114958 + * include/experimental/bits/simd.h (__as_vector): Return scalar + simd as one-element vector. Return vector from single-vector + fixed_size simd. + (__vec_shuffle): New. + (__extract_part): Adjust return type signature. + (split): Use __extract_part for any split into non-fixed_size + simds. + (concat): If the return type stores a single vector, use + __vec_shuffle (which calls __builtin_shufflevector) to produce + the return value. + * include/experimental/bits/simd_builtin.h + (__shift_elements_right): Removed. + (__extract_part): Return single elements directly. Use + __vec_shuffle (which calls __builtin_shufflevector) to for all + non-trivial cases. + * include/experimental/bits/simd_fixed_size.h (__extract_part): + Return single elements directly. + * testsuite/experimental/simd/pr114958.cc: New test. + 2024-06-01 Jonathan Wakely Backported from master: commit bf3ffb44355ca8aeea18c95a2b027023b3dab569 Author: Torbjörn SVENSSON Date: Thu Jun 6 17:12:11 2024 +0200 arm: Zero/Sign extends for CMSE security on Armv8-M.baseline [PR115253] Properly handle zero and sign extension for Armv8-M.baseline as Cortex-M23 can have the security extension active. Currently, there is an internal compiler error on Cortex-M23 for the epilog processing of sign extension. This patch addresses the following CVE-2024-0151 for Armv8-M.baseline. gcc/ChangeLog: PR target/115253 * config/arm/arm.cc (cmse_nonsecure_call_inline_register_clear): Sign extend for Thumb1. (thumb1_expand_prologue): Add zero/sign extend. Signed-off-by: Torbjörn SVENSSON Co-authored-by: Yvan ROUX (cherry picked from commit 65bd0655ece268895e5018e393bafb769e201c78) diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc index cd82728ae60..c00c6d7c1e6 100644 --- a/gcc/config/arm/arm.cc +++ b/gcc/config/arm/arm.cc @@ -19143,17 +19143,25 @@ cmse_nonsecure_call_inline_register_clear (void) || TREE_CODE (ret_type) == BOOLEAN_TYPE) && known_lt (GET_MODE_SIZE (TYPE_MODE (ret_type)), 4)) { - machine_mode ret_mode = TYPE_MODE (ret_type); + rtx ret_reg = gen_rtx_REG (TYPE_MODE (ret_type), R0_REGNUM); + rtx si_reg = gen_rtx_REG (SImode, R0_REGNUM); rtx extend; if (TYPE_UNSIGNED (ret_type)) - extend = gen_rtx_ZERO_EXTEND (SImode, - gen_rtx_REG (ret_mode, R0_REGNUM)); + extend = gen_rtx_SET (si_reg, gen_rtx_ZERO_EXTEND (SImode, + ret_reg)); else - extend = gen_rtx_SIGN_EXTEND (SImode, - gen_rtx_REG (ret_mode, R0_REGNUM)); - emit_insn_after (gen_rtx_SET (gen_rtx_REG (SImode, R0_REGNUM), - extend), insn); - + { + /* Signed-extension is a special case because of + thumb1_extendhisi2. */ + if (TARGET_THUMB1 + && known_eq (GET_MODE_SIZE (TYPE_MODE (ret_type)), 2)) + extend = gen_thumb1_extendhisi2 (si_reg, ret_reg); + else + extend = gen_rtx_SET (si_reg, + gen_rtx_SIGN_EXTEND (SImode, + ret_reg)); + } + emit_insn_after (extend, insn); } @@ -27172,6 +27180,58 @@ thumb1_expand_prologue (void) live_regs_mask = offsets->saved_regs_mask; lr_needs_saving = live_regs_mask & (1 << LR_REGNUM); + /* The AAPCS requires the callee to widen integral types narrower + than 32 bits to the full width of the register; but when handling + calls to non-secure space, we cannot trust the callee to have + correctly done so. So forcibly re-widen the result here. */ + if (IS_CMSE_ENTRY (func_type)) + { + function_args_iterator args_iter; + CUMULATIVE_ARGS args_so_far_v; + cumulative_args_t args_so_far; + bool first_param = true; + tree arg_type; + tree fndecl = current_function_decl; + tree fntype = TREE_TYPE (fndecl); + arm_init_cumulative_args (&args_so_far_v, fntype, NULL_RTX, fndecl); + args_so_far = pack_cumulative_args (&args_so_far_v); + FOREACH_FUNCTION_ARGS (fntype, arg_type, args_iter) + { + rtx arg_rtx; + + if (VOID_TYPE_P (arg_type)) + break; + + function_arg_info arg (arg_type, /*named=*/true); + if (!first_param) + /* We should advance after processing the argument and pass + the argument we're advancing past. */ + arm_function_arg_advance (args_so_far, arg); + first_param = false; + arg_rtx = arm_function_arg (args_so_far, arg); + gcc_assert (REG_P (arg_rtx)); + if ((TREE_CODE (arg_type) == INTEGER_TYPE + || TREE_CODE (arg_type) == ENUMERAL_TYPE + || TREE_CODE (arg_type) == BOOLEAN_TYPE) + && known_lt (GET_MODE_SIZE (GET_MODE (arg_rtx)), 4)) + { + rtx res_reg = gen_rtx_REG (SImode, REGNO (arg_rtx)); + if (TYPE_UNSIGNED (arg_type)) + emit_set_insn (res_reg, gen_rtx_ZERO_EXTEND (SImode, arg_rtx)); + else + { + /* Signed-extension is a special case because of + thumb1_extendhisi2. */ + if (known_eq (GET_MODE_SIZE (GET_MODE (arg_rtx)), 2)) + emit_insn (gen_thumb1_extendhisi2 (res_reg, arg_rtx)); + else + emit_set_insn (res_reg, + gen_rtx_SIGN_EXTEND (SImode, arg_rtx)); + } + } + } + } + /* Extract a mask of the ones we can give to the Thumb's push instruction. */ l_mask = live_regs_mask & 0x40ff; /* Then count how many other high registers will need to be pushed. */ commit dfab6851eb557a47a5e61d00ad4c519072a69f61 Author: Torbjörn SVENSSON Date: Fri Jun 7 10:42:22 2024 +0200 testsuite: Fix expand-return CMSE test for Armv8.1-M [PR115253] For Armv8.1-M, the clearing of the registers is handled differently than for Armv8-M, so update the test case accordingly. gcc/testsuite/ChangeLog: PR target/115253 * gcc.target/arm/cmse/extend-return.c: Update test case condition for Armv8.1-M. Signed-off-by: Torbjörn SVENSSON Co-authored-by: Yvan ROUX (cherry picked from commit cf5f9171bae1f5f3034dc9a055b77446962f1a8c) diff --git a/gcc/testsuite/gcc.target/arm/cmse/extend-return.c b/gcc/testsuite/gcc.target/arm/cmse/extend-return.c index 081de0d699f..2288d166bd3 100644 --- a/gcc/testsuite/gcc.target/arm/cmse/extend-return.c +++ b/gcc/testsuite/gcc.target/arm/cmse/extend-return.c @@ -1,5 +1,7 @@ /* { dg-do compile } */ /* { dg-options "-mcmse -fshort-enums" } */ +/* ARMv8-M expectation with target { ! arm_cmse_clear_ok }. */ +/* ARMv8.1-M expectation with target arm_cmse_clear_ok. */ /* { dg-final { check-function-bodies "**" "" "" } } */ #include @@ -20,7 +22,15 @@ typedef enum offset __attribute__ ((cmse_nonsecure_call)) ns_enum_foo_t (void); typedef bool __attribute__ ((cmse_nonsecure_call)) ns_bool_foo_t (void); /* -**unsignNonsecure0: +**unsignNonsecure0: { target arm_cmse_clear_ok } +** ... +** blxns r[0-3] +** ... +** uxtb r0, r0 +** ... +*/ +/* +**unsignNonsecure0: { target { ! arm_cmse_clear_ok } } ** ... ** bl __gnu_cmse_nonsecure_call ** uxtb r0, r0 @@ -32,7 +42,15 @@ unsigned char unsignNonsecure0 (ns_unsign_foo_t * ns_foo_p) } /* -**signNonsecure0: +**signNonsecure0: { target arm_cmse_clear_ok } +** ... +** blxns r[0-3] +** ... +** sxtb r0, r0 +** ... +*/ +/* +**signNonsecure0: { target { ! arm_cmse_clear_ok } } ** ... ** bl __gnu_cmse_nonsecure_call ** sxtb r0, r0 @@ -44,7 +62,15 @@ signed char signNonsecure0 (ns_sign_foo_t * ns_foo_p) } /* -**shortUnsignNonsecure0: +**shortUnsignNonsecure0: { target arm_cmse_clear_ok } +** ... +** blxns r[0-3] +** ... +** uxth r0, r0 +** ... +*/ +/* +**shortUnsignNonsecure0: { target { ! arm_cmse_clear_ok } } ** ... ** bl __gnu_cmse_nonsecure_call ** uxth r0, r0 @@ -56,7 +82,15 @@ unsigned short shortUnsignNonsecure0 (ns_short_unsign_foo_t * ns_foo_p) } /* -**shortSignNonsecure0: +**shortSignNonsecure0: { target arm_cmse_clear_ok } +** ... +** blxns r[0-3] +** ... +** sxth r0, r0 +** ... +*/ +/* +**shortSignNonsecure0: { target { ! arm_cmse_clear_ok } } ** ... ** bl __gnu_cmse_nonsecure_call ** sxth r0, r0 @@ -68,7 +102,15 @@ signed short shortSignNonsecure0 (ns_short_sign_foo_t * ns_foo_p) } /* -**enumNonsecure0: +**enumNonsecure0: { target arm_cmse_clear_ok } +** ... +** blxns r[0-3] +** ... +** uxtb r0, r0 +** ... +*/ +/* +**enumNonsecure0: { target { ! arm_cmse_clear_ok } } ** ... ** bl __gnu_cmse_nonsecure_call ** uxtb r0, r0 @@ -80,7 +122,15 @@ unsigned char __attribute__((noipa)) enumNonsecure0 (ns_enum_foo_t * ns_foo_p) } /* -**boolNonsecure0: +**boolNonsecure0: { target arm_cmse_clear_ok } +** ... +** blxns r[0-3] +** ... +** uxtb r0, r0 +** ... +*/ +/* +**boolNonsecure0: { target { ! arm_cmse_clear_ok } } ** ... ** bl __gnu_cmse_nonsecure_call ** uxtb r0, r0 commit 113a104edb5c31fbaa767ba8526f0da4dcf39ebe Author: Andre Vieira Date: Thu Jun 6 16:02:50 2024 +0100 arm: Add .type and .size to __gnu_cmse_nonsecure_call [PR115360] This patch adds missing assembly directives to the CMSE library wrapper to call functions with attribute cmse_nonsecure_call. Without the .type directive the linker will fail to produce the correct veneer if a call to this wrapper function is to far from the wrapper itself. The .size was added for completeness, though we don't necessarily have a usecase for it. libgcc/ChangeLog: PR target/115360 * config/arm/cmse_nonsecure_call.S: Add .type and .size directives. (cherry picked from commit c559353af49fe5743d226ac3112a285b27a50f6a) diff --git a/libgcc/config/arm/cmse_nonsecure_call.S b/libgcc/config/arm/cmse_nonsecure_call.S index c92eb62c473..8c3b8f466a1 100644 --- a/libgcc/config/arm/cmse_nonsecure_call.S +++ b/libgcc/config/arm/cmse_nonsecure_call.S @@ -33,6 +33,7 @@ #endif .thumb +.type __gnu_cmse_nonsecure_call, %function .global __gnu_cmse_nonsecure_call __gnu_cmse_nonsecure_call: #if defined(__ARM_ARCH_8M_MAIN__) @@ -142,3 +143,4 @@ pop {r5-r7, pc} #else #error "This should only be used for armv8-m base- and mainline." #endif +.size __gnu_cmse_nonsecure_call, .-__gnu_cmse_nonsecure_call commit 341342da85a3d9ce27a7669df788b555efdd09e3 Author: GCC Administrator Date: Thu Jun 13 00:21:14 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d1c13cae7cd..586ab9fa4cf 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2024-06-12 Torbjörn SVENSSON + + Backported from master: + 2024-06-12 Torbjörn SVENSSON + Yvan ROUX + + PR target/115253 + * config/arm/arm.cc (cmse_nonsecure_call_inline_register_clear): + Sign extend for Thumb1. + (thumb1_expand_prologue): Add zero/sign extend. + 2024-06-11 Jakub Jelinek Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index da7aa8ad65c..9da7c1a8c5f 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240612 +20240613 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 76ae98870e0..391efb96f57 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2024-06-12 Torbjörn SVENSSON + + Backported from master: + 2024-06-12 Torbjörn SVENSSON + Yvan ROUX + + PR target/115253 + * gcc.target/arm/cmse/extend-return.c: Update test case + condition for Armv8.1-M. + 2024-06-11 Jakub Jelinek Backported from master: diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 2b6f36359d1..cfcadeec45e 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,11 @@ +2024-06-12 Andre Vieira + + Backported from master: + 2024-06-06 Andre Vieira + + PR target/115360 + * config/arm/cmse_nonsecure_call.S: Add .type and .size directives. + 2024-05-21 Release Manager * GCC 13.3.0 released. commit 7da2f895bd3294cc3f6bd202c73bce78d71c73bf Author: GCC Administrator Date: Fri Jun 14 00:21:39 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 9da7c1a8c5f..5306f61500d 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240613 +20240614 commit 24dbdd20dcbd4c560f852cce51aa0754464476f5 Author: Jonathan Wakely Date: Fri Jun 14 12:10:48 2024 +0100 libstdc++: Fix declaration of posix_memalign for freestanding Thanks to Jérôme Duval for noticing this. libstdc++-v3/ChangeLog: * libsupc++/new_opa.cc [!_GLIBCXX_HOSTED]: Fix declaration of posix_memalign. (cherry picked from commit 161efd677458f20d13ee1018a4d5e3964febd508) diff --git a/libstdc++-v3/libsupc++/new_opa.cc b/libstdc++-v3/libsupc++/new_opa.cc index 29767c1cfaa..3c06b5c0bcf 100644 --- a/libstdc++-v3/libsupc++/new_opa.cc +++ b/libstdc++-v3/libsupc++/new_opa.cc @@ -47,7 +47,7 @@ using std::size_t; extern "C" { # if _GLIBCXX_HAVE_POSIX_MEMALIGN - void *posix_memalign(void **, size_t alignment, size_t size); + int posix_memalign(void **, size_t alignment, size_t size); # elif _GLIBCXX_HAVE_ALIGNED_ALLOC void *aligned_alloc(size_t alignment, size_t size); # elif _GLIBCXX_HAVE__ALIGNED_MALLOC commit 072e71f07730b90af07ac417d58702628cfdf210 Author: GCC Administrator Date: Sat Jun 15 00:20:25 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 5306f61500d..c882ae50504 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240614 +20240615 diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index fad3d1c2b50..93cf81e62b3 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,11 @@ +2024-06-14 Jonathan Wakely + + Backported from master: + 2024-06-14 Jonathan Wakely + + * libsupc++/new_opa.cc [!_GLIBCXX_HOSTED]: Fix declaration of + posix_memalign. + 2024-06-11 Matthias Kretz Backported from master: commit 663be6b995fdbd473222e51c7c96b9ebfd45dd6d Author: GCC Administrator Date: Sun Jun 16 00:20:14 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index c882ae50504..85b77d08b9d 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240615 +20240616 commit a62db395b1187a548a02f3c76b18ce60976e2f90 Author: GCC Administrator Date: Mon Jun 17 00:20:31 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 85b77d08b9d..bf0b926d2c4 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240616 +20240617 commit 6d0a0c547a6c8425d432129fc90869305fef7bc2 Author: Jakub Jelinek Date: Mon Jun 17 18:53:21 2024 +0200 c++: Fix up floating point conversion rank comparison for _Float32 and float if float/double are same size [PR115511] On AVR and SH with some options sizeof (float) == sizeof (double) and the 2 types have the same set of values. http://eel.is/c++draft/conv.rank#2.2 for this says that double still has bigger rank than float and http://eel.is/c++draft/conv.rank#2.2 says that extended type with the same set of values as more than one standard floating point type shall have the same rank as double. I've implemented the latter rule as if (cnt > 1 && mv2 == long_double_type_node) return -2; with the _Float64/double/long double case having same mode case (various targets with -mlong-double-64) in mind. But never thought there are actually targets where float and double are the same, that needs handling too, if cnt > 1 (that is the extended type mv1 has same set of values as 2 or 3 of float/double/long double) and mv2 is float, we need to return 2, because mv1 in that case should have same rank as double and double has bigger rank than float. 2024-06-17 Jakub Jelinek PR target/111343 PR c++/115511 * typeck.cc (cp_compare_floating_point_conversion_ranks): If an extended floating point type mv1 has same set of values as more than one standard floating point type and mv2 is float, return 2. * g++.dg/cpp23/ext-floating18.C: New test. (cherry picked from commit 8584c98f370cd91647c184ce58141508ca478a12) diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index 81bc9edd955..470bb2ee5f7 100644 --- a/gcc/cp/typeck.cc +++ b/gcc/cp/typeck.cc @@ -393,6 +393,9 @@ cp_compare_floating_point_conversion_ranks (tree t1, tree t2) has higher rank. */ if (cnt > 1 && mv2 == long_double_type_node) return -2; + /* And similarly if t2 is float, t2 has lower rank. */ + if (cnt > 1 && mv2 == float_type_node) + return 2; /* Otherwise, they have equal rank, but extended types (other than std::bfloat16_t) have higher subrank. std::bfloat16_t shouldn't have equal rank to any standard diff --git a/gcc/testsuite/g++.dg/cpp23/ext-floating18.C b/gcc/testsuite/g++.dg/cpp23/ext-floating18.C new file mode 100644 index 00000000000..ece25464bfd --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/ext-floating18.C @@ -0,0 +1,26 @@ +// P1467R9 - Extended floating-point types and standard names. +// { dg-do compile { target c++23 } } +// { dg-options "" } +// { dg-add-options float32 } + +constexpr int foo (float) { return 1; } +constexpr int foo (double) { return 2; } +constexpr int foo (long double) { return 3; } + +#ifdef __STDCPP_FLOAT32_T__ +#if __FLT_MAX_EXP__ == __FLT32_MAX_EXP__ \ + && __FLT_MAX_DIG__ == __FLT32_MAX_DIG__ +#if __FLT_MAX_EXP__ == __DBL_MAX_EXP__ \ + && __FLT_MAX_DIG__ == __DBL_MAX_DIG__ +static_assert (foo (1.0f32) == 2); +#else +static_assert (foo (1.0f32) == 1); +#endif +#endif +#endif +#ifdef __STDCPP_FLOAT64_T__ +#if __DBL_MAX_EXP__ == __FLT64_MAX_EXP__ \ + && __DBL_MAX_DIG__ == __FLT64_MAX_DIG__ +static_assert (foo (1.0f64) == 2); +#endif +#endif commit be14e6cf7f2dc23012dfced0a4aff0894fd6ff57 Author: Jakub Jelinek Date: Mon Jun 17 19:24:05 2024 +0200 c-family: Fix -Warray-compare warning ICE [PR115290] The warning code uses %D to print the ARRAY_REF first operands. That works in the most common case where those operands are decls, but as can be seen on the following testcase, they can be other expressions with array type. Just changing %D to %E isn't enough, because then the diagnostics can suggest something like note: use '&(x) != 0 ? (int (*)[32])&a : (int (*)[32])&b[0] == &(y) != 0 ? (int (*)[32])&a : (int (*)[32])&b[0]' to compare the addresses which is a bad suggestion, the %E printing doesn't know that the warning code will want to add & before it and [0] after it. So, the following patch adds ()s around the operand as well, but does that only for non-decls, for decls keeps it as &arr[0] like before. 2024-06-17 Jakub Jelinek PR c/115290 * c-warn.cc (do_warn_array_compare): Use %E rather than %D for printing op0 and op1; if those operands aren't decls, also print parens around them. * c-c++-common/Warray-compare-3.c: New test. (cherry picked from commit b63c7d92012f92e0517190cf263d29bbef8a06bf) diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc index 9ac43a1af6e..6ee96edfd23 100644 --- a/gcc/c-family/c-warn.cc +++ b/gcc/c-family/c-warn.cc @@ -3827,11 +3827,16 @@ do_warn_array_compare (location_t location, tree_code code, tree op0, tree op1) /* C doesn't allow +arr. */ if (c_dialect_cxx ()) inform (location, "use unary %<+%> which decays operands to pointers " - "or %<&%D[0] %s &%D[0]%> to compare the addresses", - op0, op_symbol_code (code), op1); + "or %<&%s%E%s[0] %s &%s%E%s[0]%> to compare the addresses", + DECL_P (op0) ? "" : "(", op0, DECL_P (op0) ? "" : ")", + op_symbol_code (code), + DECL_P (op1) ? "" : "(", op1, DECL_P (op1) ? "" : ")"); else - inform (location, "use %<&%D[0] %s &%D[0]%> to compare the addresses", - op0, op_symbol_code (code), op1); + inform (location, + "use %<&%s%E%s[0] %s &%s%E%s[0]%> to compare the addresses", + DECL_P (op0) ? "" : "(", op0, DECL_P (op0) ? "" : ")", + op_symbol_code (code), + DECL_P (op1) ? "" : "(", op1, DECL_P (op1) ? "" : ")"); } } diff --git a/gcc/testsuite/c-c++-common/Warray-compare-3.c b/gcc/testsuite/c-c++-common/Warray-compare-3.c new file mode 100644 index 00000000000..4725aa2b38b --- /dev/null +++ b/gcc/testsuite/c-c++-common/Warray-compare-3.c @@ -0,0 +1,13 @@ +/* PR c/115290 */ +/* { dg-do compile } */ +/* { dg-options "-Warray-compare" } */ + +int a[32][32], b[32][32]; + +int +foo (int x, int y) +{ + return (x ? a : b) == (y ? a : b); /* { dg-warning "comparison between two arrays" } */ +/* { dg-message "use '&\\\(\[^\n\r]*\\\)\\\[0\\\] == &\\\(\[^\n\r]*\\\)\\\[0\\\]' to compare the addresses" "" { target c } .-1 } */ +/* { dg-message "use unary '\\\+' which decays operands to pointers or '&\\\(\[^\n\r]*\\\)\\\[0\\\] == &\\\(\[^\n\r]*\\\)\\\[0\\\]' to compare the addresses" "" { target c++ } .-2 } */ +} commit 3ff23396e864175e011fa3578346d2dda0b1572e Author: GCC Administrator Date: Tue Jun 18 00:20:31 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index bf0b926d2c4..27d3477e4c4 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240617 +20240618 diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index ef9554fb426..80c93fc7ebc 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,13 @@ +2024-06-17 Jakub Jelinek + + Backported from master: + 2024-06-17 Jakub Jelinek + + PR c/115290 + * c-warn.cc (do_warn_array_compare): Use %E rather than %D for + printing op0 and op1; if those operands aren't decls, also print + parens around them. + 2024-05-21 Release Manager * GCC 13.3.0 released. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5152f6d8085..bcb359adbcd 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2024-06-17 Jakub Jelinek + + Backported from master: + 2024-06-17 Jakub Jelinek + + PR target/111343 + PR c++/115511 + * typeck.cc (cp_compare_floating_point_conversion_ranks): If an + extended floating point type mv1 has same set of values as more + than one standard floating point type and mv2 is float, return 2. + 2024-05-24 Jason Merrill Backported from master: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 391efb96f57..f30a0024409 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,20 @@ +2024-06-17 Jakub Jelinek + + Backported from master: + 2024-06-17 Jakub Jelinek + + PR c/115290 + * c-c++-common/Warray-compare-3.c: New test. + +2024-06-17 Jakub Jelinek + + Backported from master: + 2024-06-17 Jakub Jelinek + + PR target/111343 + PR c++/115511 + * g++.dg/cpp23/ext-floating18.C: New test. + 2024-06-12 Torbjörn SVENSSON Backported from master: commit 41ea2639564d702e3839a577e2ada8a8890520d6 Author: GCC Administrator Date: Wed Jun 19 00:21:22 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 27d3477e4c4..6fe37f7c386 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240618 +20240619 commit 0530884fbf49cc81119d66de7e4a48b47172ed4c Author: Harald Anlauf Date: Mon Jun 3 22:02:06 2024 +0200 Fortran: fix ALLOCATE with SOURCE=, zero-length character [PR83865] gcc/fortran/ChangeLog: PR fortran/83865 * trans-stmt.cc (gfc_trans_allocate): Restrict special case for source-expression with zero-length character to rank 0, so that the array shape is not discarded. gcc/testsuite/ChangeLog: PR fortran/83865 * gfortran.dg/allocate_with_source_32.f90: New test. (cherry picked from commit 7f21aee0d4ef95eee7d9f7f42e9a056715836648) diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc index 35eb1880539..caa7b59e912 100644 --- a/gcc/fortran/trans-stmt.cc +++ b/gcc/fortran/trans-stmt.cc @@ -6398,8 +6398,9 @@ gfc_trans_allocate (gfc_code * code) else gfc_add_block_to_block (&post, &se.post); - /* Special case when string in expr3 is zero. */ + /* Special case when string in expr3 is scalar and has length zero. */ if (code->expr3->ts.type == BT_CHARACTER + && code->expr3->rank == 0 && integer_zerop (se.string_length)) { gfc_init_se (&se, NULL); diff --git a/gcc/testsuite/gfortran.dg/allocate_with_source_32.f90 b/gcc/testsuite/gfortran.dg/allocate_with_source_32.f90 new file mode 100644 index 00000000000..4a9bd46da4d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/allocate_with_source_32.f90 @@ -0,0 +1,33 @@ +! { dg-do run } +! +! PR fortran/83865 +! +! Test ALLOCATE with SOURCE= of deferred length character, where +! the source-expression is an array of character with length 0. + +program p + implicit none + character(:), allocatable :: z(:) + character(1) :: cc(4) = "" + allocate (z, source=['']) + if (len (z) /= 0 .or. size (z) /= 1) stop 1 + deallocate (z) + allocate (z, source=['','']) + if (len (z) /= 0 .or. size (z) /= 2) stop 2 + deallocate (z) + allocate (z, source=[ character(0) :: 'a','b','c']) + if (len (z) /= 0 .or. size (z) /= 3) stop 3 + deallocate (z) + allocate (z, source=[ character(0) :: cc ]) + if (len (z) /= 0 .or. size (z) /= 4) stop 4 + deallocate (z) + associate (x => f()) + if (len (x) /= 0 .or. size (x) /= 1) stop 5 + if (x(1) /= '') stop 6 + end associate +contains + function f() result(z) + character(:), allocatable :: z(:) + allocate (z, source=['']) + end function f +end commit abde654af57649cd53a50a9fd174cac9c60fc4ae Author: GCC Administrator Date: Thu Jun 20 00:20:46 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 6fe37f7c386..9df1831b6e3 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240619 +20240620 diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index e6a9e145e17..21654771942 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,13 @@ +2024-06-19 Harald Anlauf + + Backported from master: + 2024-06-04 Harald Anlauf + + PR fortran/83865 + * trans-stmt.cc (gfc_trans_allocate): Restrict special case for + source-expression with zero-length character to rank 0, so that + the array shape is not discarded. + 2024-05-28 Tobias Burnus Backported from master: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f30a0024409..893e5453dcf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2024-06-19 Harald Anlauf + + Backported from master: + 2024-06-04 Harald Anlauf + + PR fortran/83865 + * gfortran.dg/allocate_with_source_32.f90: New test. + 2024-06-17 Jakub Jelinek Backported from master: commit e216eb16ef740c4e820a24c73e7d7e97a12d93c3 Author: Jakub Jelinek Date: Mon Jun 17 22:02:46 2024 +0200 diagnostics: Fix add_misspelling_candidates [PR115440] The option_map array for most entries contains just non-NULL opt0 { "-Wno-", NULL, "-W", false, true }, { "-fno-", NULL, "-f", false, true }, { "-gno-", NULL, "-g", false, true }, { "-mno-", NULL, "-m", false, true }, { "--debug=", NULL, "-g", false, false }, { "--machine-", NULL, "-m", true, false }, { "--machine-no-", NULL, "-m", false, true }, { "--machine=", NULL, "-m", false, false }, { "--machine=no-", NULL, "-m", false, true }, { "--machine", "", "-m", false, false }, { "--machine", "no-", "-m", false, true }, { "--optimize=", NULL, "-O", false, false }, { "--std=", NULL, "-std=", false, false }, { "--std", "", "-std=", false, false }, { "--warn-", NULL, "-W", true, false }, { "--warn-no-", NULL, "-W", false, true }, { "--", NULL, "-f", true, false }, { "--no-", NULL, "-f", false, true } and so add_misspelling_candidates works correctly for it, but 3 out of these, { "--machine", "", "-m", false, false }, { "--machine", "no-", "-m", false, true }, and { "--std", "", "-std=", false, false }, use non-NULL opt1. That says that --machine foo should map to -mfoo and --machine no-foo should map to -mno-foo and --std c++17 should map to -std=c++17 add_misspelling_canidates was not handling this, so it hapilly registered say --stdc++17 or --machineavx512 (twice) as spelling alternatives, when those options aren't recognized. Instead we support --std c++17 or --machine avx512 --machine no-avx512 The following patch fixes that. On this particular testcase, we no longer suggest anything, even when among the suggestion is say that --std c++17 or -std=c++17 etc. 2024-06-17 Jakub Jelinek PR driver/115440 * opts-common.cc (add_misspelling_candidates): If opt1 is non-NULL, add a space and opt1 to the alternative suggestion text. * g++.dg/cpp1z/pr115440.C: New test. (cherry picked from commit 96db57948b50f45235ae4af3b46db66cae7ea859) diff --git a/gcc/opts-common.cc b/gcc/opts-common.cc index 23ddcaa3b55..0684b235675 100644 --- a/gcc/opts-common.cc +++ b/gcc/opts-common.cc @@ -502,6 +502,7 @@ add_misspelling_candidates (auto_vec *candidates, for (unsigned i = 0; i < ARRAY_SIZE (option_map); i++) { const char *opt0 = option_map[i].opt0; + const char *opt1 = option_map[i].opt1; const char *new_prefix = option_map[i].new_prefix; size_t new_prefix_len = strlen (new_prefix); @@ -510,8 +511,9 @@ add_misspelling_candidates (auto_vec *candidates, if (strncmp (opt_text, new_prefix, new_prefix_len) == 0) { - char *alternative = concat (opt0 + 1, opt_text + new_prefix_len, - NULL); + char *alternative + = concat (opt0 + 1, opt1 ? " " : "", opt1 ? opt1 : "", + opt_text + new_prefix_len, NULL); candidates->safe_push (alternative); } } diff --git a/gcc/testsuite/g++.dg/cpp1z/pr115440.C b/gcc/testsuite/g++.dg/cpp1z/pr115440.C new file mode 100644 index 00000000000..788d4806fe2 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/pr115440.C @@ -0,0 +1,8 @@ +// PR driver/115440 +// { dg-do compile { target c++17_only } } +// { dg-options "--c++17" } + +int i; + +// { dg-bogus "unrecognized command-line option '--c\\\+\\\+17'; did you mean '--stdc\\\+\\\+17'" "" { target *-*-* } 0 } +// { dg-error "unrecognized command-line option '--c\\\+\\\+17'" "" { target *-*-* } 0 } commit 701de952ef41c90d7c5676d8322c418e3b668cd3 Author: GCC Administrator Date: Fri Jun 21 00:26:10 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 586ab9fa4cf..92d96996209 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2024-06-20 Jakub Jelinek + + Backported from master: + 2024-06-17 Jakub Jelinek + + PR driver/115440 + * opts-common.cc (add_misspelling_candidates): If opt1 is non-NULL, + add a space and opt1 to the alternative suggestion text. + 2024-06-12 Torbjörn SVENSSON Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 9df1831b6e3..e778c427d11 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240620 +20240621 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 893e5453dcf..93db02d4e92 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2024-06-20 Jakub Jelinek + + Backported from master: + 2024-06-17 Jakub Jelinek + + PR driver/115440 + * g++.dg/cpp1z/pr115440.C: New test. + 2024-06-19 Harald Anlauf Backported from master: commit fbd088a069b172cae4e268abe2d38e567ef97990 Author: Matthias Kretz Date: Fri Jun 14 15:11:25 2024 +0200 libstdc++: Fix find_last_set(simd_mask) to ignore padding bits With the change to the AVX512 find_last_set implementation, the change to AVX512 operator!= is unnecessary. However, the latter was not producing optimal code and unnecessarily set the padding bits. In theory, the compiler could determine that with the new != implementation, the bit operation for clearing the padding bits is a no-op and can be elided. Signed-off-by: Matthias Kretz libstdc++-v3/ChangeLog: PR libstdc++/115454 * include/experimental/bits/simd_x86.h (_S_not_equal_to): Use neq comparison instead of bitwise negation after eq. (_S_find_last_set): Clear unused high bits before computing bit_width. * testsuite/experimental/simd/pr115454_find_last_set.cc: New test. (cherry picked from commit 1340ddea0158de3f49aeb75b4013e5fc313ff6f4) diff --git a/libstdc++-v3/include/experimental/bits/simd_x86.h b/libstdc++-v3/include/experimental/bits/simd_x86.h index 79c246455ee..5f427ccd90f 100644 --- a/libstdc++-v3/include/experimental/bits/simd_x86.h +++ b/libstdc++-v3/include/experimental/bits/simd_x86.h @@ -2339,29 +2339,29 @@ template __assert_unreachable<_Tp>(); } else if constexpr (sizeof(__xi) == 64 && sizeof(_Tp) == 8) - return ~_mm512_mask_cmpeq_epi64_mask(__k1, __xi, __yi); + return _mm512_mask_cmpneq_epi64_mask(__k1, __xi, __yi); else if constexpr (sizeof(__xi) == 64 && sizeof(_Tp) == 4) - return ~_mm512_mask_cmpeq_epi32_mask(__k1, __xi, __yi); + return _mm512_mask_cmpneq_epi32_mask(__k1, __xi, __yi); else if constexpr (sizeof(__xi) == 64 && sizeof(_Tp) == 2) - return ~_mm512_mask_cmpeq_epi16_mask(__k1, __xi, __yi); + return _mm512_mask_cmpneq_epi16_mask(__k1, __xi, __yi); else if constexpr (sizeof(__xi) == 64 && sizeof(_Tp) == 1) - return ~_mm512_mask_cmpeq_epi8_mask(__k1, __xi, __yi); + return _mm512_mask_cmpneq_epi8_mask(__k1, __xi, __yi); else if constexpr (sizeof(__xi) == 32 && sizeof(_Tp) == 8) - return ~_mm256_mask_cmpeq_epi64_mask(__k1, __xi, __yi); + return _mm256_mask_cmpneq_epi64_mask(__k1, __xi, __yi); else if constexpr (sizeof(__xi) == 32 && sizeof(_Tp) == 4) - return ~_mm256_mask_cmpeq_epi32_mask(__k1, __xi, __yi); + return _mm256_mask_cmpneq_epi32_mask(__k1, __xi, __yi); else if constexpr (sizeof(__xi) == 32 && sizeof(_Tp) == 2) - return ~_mm256_mask_cmpeq_epi16_mask(__k1, __xi, __yi); + return _mm256_mask_cmpneq_epi16_mask(__k1, __xi, __yi); else if constexpr (sizeof(__xi) == 32 && sizeof(_Tp) == 1) - return ~_mm256_mask_cmpeq_epi8_mask(__k1, __xi, __yi); + return _mm256_mask_cmpneq_epi8_mask(__k1, __xi, __yi); else if constexpr (sizeof(__xi) == 16 && sizeof(_Tp) == 8) - return ~_mm_mask_cmpeq_epi64_mask(__k1, __xi, __yi); + return _mm_mask_cmpneq_epi64_mask(__k1, __xi, __yi); else if constexpr (sizeof(__xi) == 16 && sizeof(_Tp) == 4) - return ~_mm_mask_cmpeq_epi32_mask(__k1, __xi, __yi); + return _mm_mask_cmpneq_epi32_mask(__k1, __xi, __yi); else if constexpr (sizeof(__xi) == 16 && sizeof(_Tp) == 2) - return ~_mm_mask_cmpeq_epi16_mask(__k1, __xi, __yi); + return _mm_mask_cmpneq_epi16_mask(__k1, __xi, __yi); else if constexpr (sizeof(__xi) == 16 && sizeof(_Tp) == 1) - return ~_mm_mask_cmpeq_epi8_mask(__k1, __xi, __yi); + return _mm_mask_cmpneq_epi8_mask(__k1, __xi, __yi); else __assert_unreachable<_Tp>(); } // }}} @@ -5292,7 +5292,7 @@ template _S_find_last_set(simd_mask<_Tp, _Abi> __k) { if constexpr (__is_avx512_abi<_Abi>()) - return std::__bit_width(__k._M_data._M_data) - 1; + return std::__bit_width(_Abi::_S_masked(__k._M_data)._M_data) - 1; else return _Base::_S_find_last_set(__k); } diff --git a/libstdc++-v3/testsuite/experimental/simd/pr115454_find_last_set.cc b/libstdc++-v3/testsuite/experimental/simd/pr115454_find_last_set.cc new file mode 100644 index 00000000000..b47f19d3067 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/simd/pr115454_find_last_set.cc @@ -0,0 +1,49 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run { target *-*-* } } +// { dg-require-effective-target c++17 } +// { dg-additional-options "-march=x86-64-v4" { target avx512f } } +// { dg-require-cmath "" } + +#include + +namespace stdx = std::experimental; + +using T = std::uint64_t; + +template +using V = stdx::simd>; + +[[gnu::noinline, gnu::noipa]] +int reduce(V x) +{ + static_assert(stdx::find_last_set(V([](unsigned i) { return i; }) != V(0)) == 3); + return stdx::find_last_set(x != -1); +} + +[[gnu::noinline, gnu::noipa]] +int reduce2() +{ + using M8 = typename V::mask_type; + using M4 = typename V::mask_type; + if constexpr (sizeof(M8) == sizeof(M4)) + { + M4 k; + __builtin_memcpy(&__data(k), &__data(M8(true)), sizeof(M4)); + return stdx::find_last_set(k); + } + return 3; +} + + +int main() +{ + const V x {}; + + const int r = reduce(x); + if (r != 3) + __builtin_abort(); + + const int r2 = reduce2(); + if (r2 != 3) + __builtin_abort(); +} commit c335e34ff89ec9aec1ba874dc5cece9c2303c906 Author: Matthias Kretz Date: Fri Jun 21 16:22:22 2024 +0200 libstdc++: Fix test on x86_64 and non-simd targets * Running a test compiled with AVX512 instructions requires avx512f_runtime not just avx512f. * The 'reduce2' test violated an invariant of fixed_size_simd_mask and thus failed on all targets without 16-Byte vector builtins enabled (in bits/simd.h). Signed-off-by: Matthias Kretz libstdc++-v3/ChangeLog: PR libstdc++/115575 * testsuite/experimental/simd/pr115454_find_last_set.cc: Require avx512f_runtime. Don't memcpy fixed_size masks. (cherry picked from commit 77f321435b4ac37992c2ed6737ca0caa1dd50551) diff --git a/libstdc++-v3/testsuite/experimental/simd/pr115454_find_last_set.cc b/libstdc++-v3/testsuite/experimental/simd/pr115454_find_last_set.cc index b47f19d3067..25a713b4e94 100644 --- a/libstdc++-v3/testsuite/experimental/simd/pr115454_find_last_set.cc +++ b/libstdc++-v3/testsuite/experimental/simd/pr115454_find_last_set.cc @@ -1,7 +1,7 @@ // { dg-options "-std=gnu++17" } // { dg-do run { target *-*-* } } // { dg-require-effective-target c++17 } -// { dg-additional-options "-march=x86-64-v4" { target avx512f } } +// { dg-additional-options "-march=x86-64-v4" { target avx512f_runtime } } // { dg-require-cmath "" } #include @@ -25,7 +25,9 @@ int reduce2() { using M8 = typename V::mask_type; using M4 = typename V::mask_type; - if constexpr (sizeof(M8) == sizeof(M4)) + if constexpr (sizeof(M8) == sizeof(M4) + && !std::is_same_v>) + // fixed_size invariant: padding bits of masks are zero, the memcpy would violate that { M4 k; __builtin_memcpy(&__data(k), &__data(M8(true)), sizeof(M4)); commit df9c225093ce49586caabc0bedc82e865b3bfdc5 Author: GCC Administrator Date: Sat Jun 22 00:22:16 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index e778c427d11..d4f60539db5 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240621 +20240622 diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 93cf81e62b3..6b9f146c69d 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,25 @@ +2024-06-21 Matthias Kretz + + Backported from master: + 2024-06-21 Matthias Kretz + + PR libstdc++/115575 + * testsuite/experimental/simd/pr115454_find_last_set.cc: Require + avx512f_runtime. Don't memcpy fixed_size masks. + +2024-06-21 Matthias Kretz + + Backported from master: + 2024-06-20 Matthias Kretz + + PR libstdc++/115454 + * include/experimental/bits/simd_x86.h (_S_not_equal_to): Use + neq comparison instead of bitwise negation after eq. + (_S_find_last_set): Clear unused high bits before computing + bit_width. + * testsuite/experimental/simd/pr115454_find_last_set.cc: New + test. + 2024-06-14 Jonathan Wakely Backported from master: commit 464c4af21e2eaad78a47f8de198998cca2f3c017 Author: GCC Administrator Date: Sun Jun 23 00:20:54 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index d4f60539db5..7b41634677c 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240622 +20240623 commit db36cf4975fff05f3651ac15ca38919ed8bee2b4 Author: GCC Administrator Date: Mon Jun 24 00:21:57 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 7b41634677c..149499c5447 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240623 +20240624 commit dd54ed4ae417935300a3c4bb356d37c2ae7f731e Author: Kewen Lin Date: Tue May 28 21:13:40 2024 -0500 rs6000: Don't clobber return value when eh_return called [PR114846] As the associated test case in PR114846 shows, currently with eh_return involved some register restoring for EH RETURN DATA in epilogue can clobber the one which holding the return value. Referring to the existing handlings in some other targets, this patch makes eh_return expander call one new define_insn_and_split eh_return_internal which directly calls rs6000_emit_epilogue with epilogue_type EPILOGUE_TYPE_EH_RETURN instead of the previous treating normal return with crtl->calls_eh_return specially. PR target/114846 gcc/ChangeLog: * config/rs6000/rs6000-logue.cc (rs6000_emit_epilogue): As EPILOGUE_TYPE_EH_RETURN would be passed as epilogue_type directly now, adjust the relevant handlings on it. * config/rs6000/rs6000.md (eh_return expander): Append by calling gen_eh_return_internal and emit_barrier. (eh_return_internal): New define_insn_and_split, call function rs6000_emit_epilogue with epilogue type EPILOGUE_TYPE_EH_RETURN. gcc/testsuite/ChangeLog: * gcc.target/powerpc/pr114846.c: New test. (cherry picked from commit e5fc5d42d25c86ae48178db04ce64d340a834614) diff --git a/gcc/config/rs6000/rs6000-logue.cc b/gcc/config/rs6000/rs6000-logue.cc index d6c9c6e5b52..baadbbd692e 100644 --- a/gcc/config/rs6000/rs6000-logue.cc +++ b/gcc/config/rs6000/rs6000-logue.cc @@ -4311,9 +4311,6 @@ rs6000_emit_epilogue (enum epilogue_type epilogue_type) rs6000_stack_t *info = rs6000_stack_info (); - if (epilogue_type == EPILOGUE_TYPE_NORMAL && crtl->calls_eh_return) - epilogue_type = EPILOGUE_TYPE_EH_RETURN; - int strategy = info->savres_strategy; bool using_load_multiple = !!(strategy & REST_MULTIPLE); bool restoring_GPRs_inline = !!(strategy & REST_INLINE_GPRS); @@ -4791,7 +4788,9 @@ rs6000_emit_epilogue (enum epilogue_type epilogue_type) /* In the ELFv2 ABI we need to restore all call-saved CR fields from *separate* slots if the routine calls __builtin_eh_return, so - that they can be independently restored by the unwinder. */ + that they can be independently restored by the unwinder. Since + it is for CR fields restoring, it should be done for any epilogue + types (not EPILOGUE_TYPE_EH_RETURN specific). */ if (DEFAULT_ABI == ABI_ELFv2 && crtl->calls_eh_return) { int i, cr_off = info->ehcr_offset; diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 7e33fb4039a..8d8118197da 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -14147,6 +14147,8 @@ "" { emit_insn (gen_eh_set_lr (Pmode, operands[0])); + emit_jump_insn (gen_eh_return_internal ()); + emit_barrier (); DONE; }) @@ -14163,6 +14165,19 @@ DONE; }) +(define_insn_and_split "eh_return_internal" + [(eh_return)] + "" + "#" + "epilogue_completed" + [(const_int 0)] +{ + if (!TARGET_SCHED_PROLOG) + emit_insn (gen_blockage ()); + rs6000_emit_epilogue (EPILOGUE_TYPE_EH_RETURN); + DONE; +}) + (define_insn "prefetch" [(prefetch (match_operand 0 "indexed_or_indirect_address" "a") (match_operand:SI 1 "const_int_operand" "n") diff --git a/gcc/testsuite/gcc.target/powerpc/pr114846.c b/gcc/testsuite/gcc.target/powerpc/pr114846.c new file mode 100644 index 00000000000..efe2300b73a --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr114846.c @@ -0,0 +1,20 @@ +/* { dg-do run } */ +/* { dg-require-effective-target builtin_eh_return } */ + +/* Ensure it runs successfully. */ + +__attribute__ ((noipa)) +int f (int *a, long offset, void *handler) +{ + if (*a == 5) + return 5; + __builtin_eh_return (offset, handler); +} + +int main () +{ + int t = 5; + if (f (&t, 0, 0) != 5) + __builtin_abort (); + return 0; +} commit 2cb5a44f673fea281203979cfbbfb2fc7725e484 Author: GCC Administrator Date: Tue Jun 25 00:21:43 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 92d96996209..e136aa6f204 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2024-06-24 Kewen Lin + + Backported from master: + 2024-05-29 Kewen Lin + + PR target/114846 + * config/rs6000/rs6000-logue.cc (rs6000_emit_epilogue): As + EPILOGUE_TYPE_EH_RETURN would be passed as epilogue_type directly + now, adjust the relevant handlings on it. + * config/rs6000/rs6000.md (eh_return expander): Append by calling + gen_eh_return_internal and emit_barrier. + (eh_return_internal): New define_insn_and_split, call function + rs6000_emit_epilogue with epilogue type EPILOGUE_TYPE_EH_RETURN. + 2024-06-20 Jakub Jelinek Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 149499c5447..271b3eb540d 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240624 +20240625 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 93db02d4e92..c82f0655725 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2024-06-24 Kewen Lin + + Backported from master: + 2024-05-29 Kewen Lin + + PR target/114846 + * gcc.target/powerpc/pr114846.c: New test. + 2024-06-20 Jakub Jelinek Backported from master: commit bc6e4bd567867280dae832ec8edeec480c937e47 Author: Jonathan Wakely Date: Tue Jun 25 23:25:54 2024 +0100 libstdc++: Remove confusing text from status tables for release branch When I tried to make the release branch versions of these docs refer to the release branch instead of "mainline GCC", for some reason I left the text "not any particular release" there. That's just confusing, because the docs are for a particular release, the latest on that branch. Remove that confusing text in several places. libstdc++-v3/ChangeLog: * doc/xml/manual/status_cxx1998.xml: Remove confusing "not in any particular release" text. * doc/xml/manual/status_cxx2011.xml: Likewise. * doc/xml/manual/status_cxx2014.xml: Likewise. * doc/xml/manual/status_cxx2017.xml: Likewise. * doc/xml/manual/status_cxx2020.xml: Likewise. * doc/xml/manual/status_cxx2023.xml: Likewise. * doc/xml/manual/status_cxxtr1.xml: Likewise. * doc/xml/manual/status_cxxtr24733.xml: Likewise. * doc/html/manual/status.html: Regenerate. diff --git a/libstdc++-v3/doc/html/manual/status.html b/libstdc++-v3/doc/html/manual/status.html index 53957bd2e0d..a2c89002289 100644 --- a/libstdc++-v3/doc/html/manual/status.html +++ b/libstdc++-v3/doc/html/manual/status.html @@ -6,7 +6,7 @@ This status table is based on the table of contents of ISO/IEC 14882:2003.

This section describes the C++ support in -the GCC 13 release series, not in any particular release. +the GCC 13 release series.

Table 1.1. C++ 1998/2003 Implementation Status

Option FlagsDescription
-std + + Select the C++ standard, and whether to use the base standard + or GNU dialect. +
-fno-exceptions See exception-free dialect
-fno-rtti diff --git a/libstdc++-v3/doc/xml/manual/using.xml b/libstdc++-v3/doc/xml/manual/using.xml index 7276cad0feb..42890f3b180 100644 --- a/libstdc++-v3/doc/xml/manual/using.xml +++ b/libstdc++-v3/doc/xml/manual/using.xml @@ -7,7 +7,7 @@ The set of features available in the GNU C++ library is shaped by - several GCC + several GCC Command Options. Options that impact libstdc++ are enumerated and detailed in the table below. @@ -37,35 +37,12 @@
SectionDescriptionStatusComments
18 @@ -161,7 +161,7 @@ since that release. This status table is based on the table of contents of ISO/IEC 14882:2011.

This section describes the C++11 support in -the GCC 13 release series, not in any particular release. +the GCC 13 release series.

Table 1.2. C++ 2011 Implementation Status

SectionDescriptionStatusComments
18 @@ -434,7 +434,7 @@ Some subclauses are not shown in the table where the content is unchanged since C++11 and the implementation is complete.

This section describes the C++14 and library TS support in -the GCC 13 release series, not in any particular release. +the GCC 13 release series.

Table 1.3. C++ 2014 Implementation Status

SectionDescriptionStatusComments
18 @@ -579,7 +579,7 @@ so the API and ABI of features added in C++17 is only stable since that release.

This section describes the C++17 and library TS support in -the GCC 13 release series, not in any particular release. +the GCC 13 release series.

The following table lists new library features that are included in the C++17 standard. The "Proposal" column provides a link to the @@ -1255,7 +1255,7 @@ options. The pre-defined symbol presence of the required flag.

This section describes the C++20 and library TS support in -the GCC 13 release series, not in any particular release. +the GCC 13 release series.

The following table lists new library features that are included in the C++20 standard. The "Proposal" column provides a link to the @@ -1725,7 +1725,7 @@ options. The pre-defined symbol presence of the required flag.

This section describes the C++23 and library TS support in -the GCC 13 release series, not in any particular release. +the GCC 13 release series.

The following table lists new library features that have been accepted into the C++23 working draft. The "Proposal" column provides a link to the @@ -2123,7 +2123,7 @@ In this implementation the header names are prefixed by <tr1/memory>, and so on.

This page describes the TR1 support in -the GCC 13 release series, not in any particular release. +the GCC 13 release series.

Table 1.11. C++ TR1 Implementation Status

SectionDescriptionStatusComments
2General Utilities
2.1Reference wrappers  
2.1.1Additions to header <functional> synopsisY 
2.1.2Class template reference_wrapper  
2.1.2.1reference_wrapper construct/copy/destroyY 
2.1.2.2reference_wrapper assignmentY 
2.1.2.3reference_wrapper accessY 
2.1.2.4reference_wrapper invocationY 
2.1.2.5reference_wrapper helper functionsY 
2.2Smart pointers  
2.2.1Additions to header <memory> synopsisY 
2.2.2Class bad_weak_ptrY 
2.2.3Class template shared_ptr 

Uses code from @@ -2144,7 +2144,7 @@ ISO/IEC TR 24733:2011, decimal floating-point arithmetic".

This page describes the TR 24733 support in -the GCC 13 release series, not in any particular release. +the GCC 13 release series.

Table 1.12. C++ TR 24733 Implementation Status

SectionDescriptionStatusComments
0 diff --git a/libstdc++-v3/doc/xml/manual/status_cxx1998.xml b/libstdc++-v3/doc/xml/manual/status_cxx1998.xml index 8bc1bde54fb..5bf1cde220c 100644 --- a/libstdc++-v3/doc/xml/manual/status_cxx1998.xml +++ b/libstdc++-v3/doc/xml/manual/status_cxx1998.xml @@ -19,7 +19,7 @@ This status table is based on the table of contents of ISO/IEC 14882:2003. This section describes the C++ support in -the GCC 13 release series, not in any particular release. +the GCC 13 release series. diff --git a/libstdc++-v3/doc/xml/manual/status_cxx2011.xml b/libstdc++-v3/doc/xml/manual/status_cxx2011.xml index 14eb791a82b..334f8440743 100644 --- a/libstdc++-v3/doc/xml/manual/status_cxx2011.xml +++ b/libstdc++-v3/doc/xml/manual/status_cxx2011.xml @@ -35,7 +35,7 @@ This status table is based on the table of contents of ISO/IEC 14882:2011. This section describes the C++11 support in -the GCC 13 release series, not in any particular release. +the GCC 13 release series. diff --git a/libstdc++-v3/doc/xml/manual/status_cxx2014.xml b/libstdc++-v3/doc/xml/manual/status_cxx2014.xml index 608373d3c4c..37fb8f9ac32 100644 --- a/libstdc++-v3/doc/xml/manual/status_cxx2014.xml +++ b/libstdc++-v3/doc/xml/manual/status_cxx2014.xml @@ -30,7 +30,7 @@ since C++11 and the implementation is complete. This section describes the C++14 and library TS support in -the GCC 13 release series, not in any particular release. +the GCC 13 release series. diff --git a/libstdc++-v3/doc/xml/manual/status_cxx2017.xml b/libstdc++-v3/doc/xml/manual/status_cxx2017.xml index 4a71a07f36f..f8afadb84c8 100644 --- a/libstdc++-v3/doc/xml/manual/status_cxx2017.xml +++ b/libstdc++-v3/doc/xml/manual/status_cxx2017.xml @@ -24,7 +24,7 @@ since that release. This section describes the C++17 and library TS support in -the GCC 13 release series, not in any particular release. +the GCC 13 release series. diff --git a/libstdc++-v3/doc/xml/manual/status_cxx2020.xml b/libstdc++-v3/doc/xml/manual/status_cxx2020.xml index c67401457e3..a0df925dcfc 100644 --- a/libstdc++-v3/doc/xml/manual/status_cxx2020.xml +++ b/libstdc++-v3/doc/xml/manual/status_cxx2020.xml @@ -21,7 +21,7 @@ presence of the required flag. This section describes the C++20 and library TS support in -the GCC 13 release series, not in any particular release. +the GCC 13 release series. diff --git a/libstdc++-v3/doc/xml/manual/status_cxx2023.xml b/libstdc++-v3/doc/xml/manual/status_cxx2023.xml index f24de7771aa..ac1d3e0ec56 100644 --- a/libstdc++-v3/doc/xml/manual/status_cxx2023.xml +++ b/libstdc++-v3/doc/xml/manual/status_cxx2023.xml @@ -21,7 +21,7 @@ presence of the required flag. This section describes the C++23 and library TS support in -the GCC 13 release series, not in any particular release. +the GCC 13 release series. diff --git a/libstdc++-v3/doc/xml/manual/status_cxxtr1.xml b/libstdc++-v3/doc/xml/manual/status_cxxtr1.xml index c4ebaa068ab..c7a0f3fc66b 100644 --- a/libstdc++-v3/doc/xml/manual/status_cxxtr1.xml +++ b/libstdc++-v3/doc/xml/manual/status_cxxtr1.xml @@ -23,7 +23,7 @@ In this implementation the header names are prefixed by This page describes the TR1 support in -the GCC 13 release series, not in any particular release. +the GCC 13 release series. diff --git a/libstdc++-v3/doc/xml/manual/status_cxxtr24733.xml b/libstdc++-v3/doc/xml/manual/status_cxxtr24733.xml index e6b2aa3bf39..d297a56e276 100644 --- a/libstdc++-v3/doc/xml/manual/status_cxxtr24733.xml +++ b/libstdc++-v3/doc/xml/manual/status_cxxtr24733.xml @@ -18,7 +18,7 @@ decimal floating-point arithmetic". This page describes the TR 24733 support in -the GCC 13 release series, not in any particular release. +the GCC 13 release series. commit 563aa24222a447c777093762b6b3123234bd9876 Author: GCC Administrator Date: Wed Jun 26 00:21:26 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 271b3eb540d..c2b916de874 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240625 +20240626 diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 6b9f146c69d..cd9b4e6de80 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,16 @@ +2024-06-25 Jonathan Wakely + + * doc/xml/manual/status_cxx1998.xml: Remove confusing "not in + any particular release" text. + * doc/xml/manual/status_cxx2011.xml: Likewise. + * doc/xml/manual/status_cxx2014.xml: Likewise. + * doc/xml/manual/status_cxx2017.xml: Likewise. + * doc/xml/manual/status_cxx2020.xml: Likewise. + * doc/xml/manual/status_cxx2023.xml: Likewise. + * doc/xml/manual/status_cxxtr1.xml: Likewise. + * doc/xml/manual/status_cxxtr24733.xml: Likewise. + * doc/html/manual/status.html: Regenerate. + 2024-06-21 Matthias Kretz Backported from master: commit d0810073e66b7ebbda179ca7c647d4284823a28e Author: GCC Administrator Date: Thu Jun 27 00:22:16 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index c2b916de874..3402e552106 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240626 +20240627 commit 952ea3260e40992d3bf5e1f17b4845a4e5c908b5 Author: Kyrylo Tkachov Date: Wed Jun 19 14:56:02 2024 +0530 Add support for -mcpu=grace This adds support for the NVIDIA Grace CPU to aarch64. We reuse the tuning decisions for the Neoverse V2 core, but include a number of architecture features that are not enabled by default in -mcpu=neoverse-v2. This allows Grace users to more simply target the CPU with -mcpu=grace rather than remembering what extensions to tag on top of -mcpu=neoverse-v2. Bootstrapped and tested on aarch64-none-linux-gnu. gcc/ * config/aarch64/aarch64-cores.def (grace): New entry. * config/aarch64/aarch64-tune.md: Regenerate. * doc/invoke.texi (AArch64 Options): Document the above. Signed-off-by: Kyrylo Tkachov diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def index fdda0697b88..bec08ca1910 100644 --- a/gcc/config/aarch64/aarch64-cores.def +++ b/gcc/config/aarch64/aarch64-cores.def @@ -182,6 +182,8 @@ AARCH64_CORE("neoverse-n2", neoversen2, cortexa57, V9A, (I8MM, BF16, SVE2_BITPER AARCH64_CORE("cobalt-100", cobalt100, cortexa57, V9A, (I8MM, BF16, SVE2_BITPERM, RNG, MEMTAG, PROFILE), neoversen2, 0x6d, 0xd49, -1) AARCH64_CORE("neoverse-v2", neoversev2, cortexa57, V9A, (I8MM, BF16, SVE2_BITPERM, RNG, MEMTAG, PROFILE), neoversev2, 0x41, 0xd4f, -1) +AARCH64_CORE("grace", grace, cortexa57, V9A, (I8MM, BF16, CRYPTO, SVE2_BITPERM, SVE2_AES, SVE2_SHA3, SVE2_SM4, PROFILE), neoversev2, 0x41, 0xd4f, -1) + AARCH64_CORE("demeter", demeter, cortexa57, V9A, (I8MM, BF16, SVE2_BITPERM, RNG, MEMTAG, PROFILE), neoversev2, 0x41, 0xd4f, -1) #undef AARCH64_CORE diff --git a/gcc/config/aarch64/aarch64-tune.md b/gcc/config/aarch64/aarch64-tune.md index 9d46d38a292..6eae8522593 100644 --- a/gcc/config/aarch64/aarch64-tune.md +++ b/gcc/config/aarch64/aarch64-tune.md @@ -1,5 +1,5 @@ ;; -*- buffer-read-only: t -*- ;; Generated automatically by gentune.sh from aarch64-cores.def (define_attr "tune" - "cortexa34,cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,octeontx,octeontxt81,octeontxt83,thunderxt81,thunderxt83,ampere1,ampere1a,emag,xgene1,falkor,qdf24xx,exynosm1,phecda,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,cortexa76ae,cortexa77,cortexa78,cortexa78ae,cortexa78c,cortexa65,cortexa65ae,cortexx1,cortexx1c,neoversen1,ares,neoversee1,octeontx2,octeontx2t98,octeontx2t96,octeontx2t93,octeontx2f95,octeontx2f95n,octeontx2f95mm,a64fx,tsv110,thunderx3t110,neoversev1,zeus,neoverse512tvb,saphira,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82,cortexa510,cortexa710,cortexa715,cortexx2,cortexx3,neoversen2,cobalt100,neoversev2,demeter" + "cortexa34,cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,octeontx,octeontxt81,octeontxt83,thunderxt81,thunderxt83,ampere1,ampere1a,emag,xgene1,falkor,qdf24xx,exynosm1,phecda,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,cortexa76ae,cortexa77,cortexa78,cortexa78ae,cortexa78c,cortexa65,cortexa65ae,cortexx1,cortexx1c,neoversen1,ares,neoversee1,octeontx2,octeontx2t98,octeontx2t96,octeontx2t93,octeontx2f95,octeontx2f95n,octeontx2f95mm,a64fx,tsv110,thunderx3t110,neoversev1,zeus,neoverse512tvb,saphira,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82,cortexa510,cortexa710,cortexa715,cortexx2,cortexx3,neoversen2,cobalt100,neoversev2,grace,demeter" (const (symbol_ref "((enum attr_tune) aarch64_tune)"))) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 914c4bc8e6d..b17d0cf9341 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -20315,8 +20315,8 @@ performance of the code. Permissible values for this option are: @samp{cortex-a78}, @samp{cortex-a78ae}, @samp{cortex-a78c}, @samp{ares}, @samp{exynos-m1}, @samp{emag}, @samp{falkor}, @samp{neoverse-512tvb}, @samp{neoverse-e1}, @samp{neoverse-n1}, -@samp{neoverse-n2}, @samp{neoverse-v1}, @samp{neoverse-v2}, @samp{qdf24xx}, -@samp{saphira}, @samp{phecda}, @samp{xgene1}, @samp{vulcan}, +@samp{neoverse-n2}, @samp{neoverse-v1}, @samp{neoverse-v2}, @samp{grace}, +@samp{qdf24xx}, @samp{saphira}, @samp{phecda}, @samp{xgene1}, @samp{vulcan}, @samp{octeontx}, @samp{octeontx81}, @samp{octeontx83}, @samp{octeontx2}, @samp{octeontx2t98}, @samp{octeontx2t96} @samp{octeontx2t93}, @samp{octeontx2f95}, @samp{octeontx2f95n}, commit 3de1c4985bebd1882b6643789daba24f2d11bafe Author: Alexandre Oliva Date: Thu Jun 27 08:32:15 2024 -0300 [libstdc++] [testsuite] defer to check_vect_support* [PR115454] The newly-added testcase overrides the default dg-do action set by check_vect_support_and_set_flags (in libstdc++-dg/conformance.exp), so it attempts to run the test even if runtime vector support is not available. Remove the explicit dg-do directive, so that the default is honored, and the test is run if vector support is found, and only compiled otherwise. for libstdc++-v3/ChangeLog PR libstdc++/115454 * testsuite/experimental/simd/pr115454_find_last_set.cc: Defer to check_vect_support_and_set_flags's default dg-do action. (cherry picked from commit 95faa1bea7bdc7f92fcccb3543bfcbc8184c5e5b) diff --git a/libstdc++-v3/testsuite/experimental/simd/pr115454_find_last_set.cc b/libstdc++-v3/testsuite/experimental/simd/pr115454_find_last_set.cc index 25a713b4e94..4ade8601f27 100644 --- a/libstdc++-v3/testsuite/experimental/simd/pr115454_find_last_set.cc +++ b/libstdc++-v3/testsuite/experimental/simd/pr115454_find_last_set.cc @@ -1,5 +1,4 @@ // { dg-options "-std=gnu++17" } -// { dg-do run { target *-*-* } } // { dg-require-effective-target c++17 } // { dg-additional-options "-march=x86-64-v4" { target avx512f_runtime } } // { dg-require-cmath "" } commit c93a9bba743ac236f6045ba7aafbc12a83726c48 Author: Andrew Carlotti Date: Fri Nov 24 17:06:07 2023 +0000 aarch64: Fix +nocrypto handling Additionally, replace all checks for the AARCH64_FL_CRYPTO bit with checks for (AARCH64_FL_AES | AARCH64_FL_SHA2) instead. The value of the AARCH64_FL_CRYPTO bit within isa_flags is now ignored, but it is retained because removing it would make processing the data in option-extensions.def significantly more complex. This bug should have been picked up by an existing test, but a missing newline meant that the pattern incorrectly allowed "+crypto+nocrypto". gcc/ChangeLog: PR target/115618 * common/config/aarch64/aarch64-common.cc (aarch64_get_extension_string_for_isa_flags): Fix generation of the "+nocrypto" extension. * config/aarch64/aarch64.h (AARCH64_ISA_CRYPTO): Remove. (TARGET_CRYPTO): Remove. * config/aarch64/aarch64-c.cc (aarch64_update_cpp_builtins): Don't use TARGET_CRYPTO. gcc/testsuite/ChangeLog: PR target/115618 * gcc.target/aarch64/options_set_4.c: Add terminating newline. * gcc.target/aarch64/options_set_27.c: New test. (cherry picked from commit 8d30107455f2309854ced3d65fb07dc1f2c357c0) diff --git a/gcc/common/config/aarch64/aarch64-common.cc b/gcc/common/config/aarch64/aarch64-common.cc index 20bc4e1291b..673407ca9a8 100644 --- a/gcc/common/config/aarch64/aarch64-common.cc +++ b/gcc/common/config/aarch64/aarch64-common.cc @@ -310,6 +310,7 @@ aarch64_get_extension_string_for_isa_flags But in order to make the output more readable, it seems better to add the strings in definition order. */ aarch64_feature_flags added = 0; + auto flags_crypto = AARCH64_FL_AES | AARCH64_FL_SHA2; for (unsigned int i = ARRAY_SIZE (all_extensions); i-- > 0; ) { auto &opt = all_extensions[i]; @@ -319,7 +320,7 @@ aarch64_get_extension_string_for_isa_flags per-feature crypto flags. */ auto flags = opt.flag_canonical; if (flags == AARCH64_FL_CRYPTO) - flags = AARCH64_FL_AES | AARCH64_FL_SHA2; + flags = flags_crypto; if ((flags & isa_flags & (explicit_flags | ~current_flags)) == flags) { @@ -338,14 +339,32 @@ aarch64_get_extension_string_for_isa_flags not have an HWCAPs then it shouldn't be taken into account for feature detection because one way or another we can't tell if it's available or not. */ + for (auto &opt : all_extensions) - if (opt.native_detect_p - && (opt.flag_canonical & current_flags & ~isa_flags)) - { - current_flags &= ~opt.flags_off; - outstr += "+no"; - outstr += opt.name; - } + { + auto flags = opt.flag_canonical; + /* As a special case, don't emit "+noaes" or "+nosha2" when we could emit + "+nocrypto" instead, in order to support assemblers that predate the + separate per-feature crypto flags. Only allow "+nocrypto" when "sm4" + is not already enabled (to avoid dependending on whether "+nocrypto" + also disables "sm4"). */ + if (flags & flags_crypto + && (flags_crypto & current_flags & ~isa_flags) == flags_crypto + && !(current_flags & AARCH64_FL_SM4)) + continue; + + if (flags == AARCH64_FL_CRYPTO) + /* If either crypto flag needs removing here, then both do. */ + flags = flags_crypto; + + if (opt.native_detect_p + && (flags & current_flags & ~isa_flags)) + { + current_flags &= ~opt.flags_off; + outstr += "+no"; + outstr += opt.name; + } + } return outstr; } diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc index 578ec6f45b0..6c5331a7625 100644 --- a/gcc/config/aarch64/aarch64-c.cc +++ b/gcc/config/aarch64/aarch64-c.cc @@ -139,7 +139,7 @@ aarch64_update_cpp_builtins (cpp_reader *pfile) aarch64_def_or_undef (TARGET_ILP32, "_ILP32", pfile); aarch64_def_or_undef (TARGET_ILP32, "__ILP32__", pfile); - aarch64_def_or_undef (TARGET_CRYPTO, "__ARM_FEATURE_CRYPTO", pfile); + aarch64_def_or_undef (TARGET_AES && TARGET_SHA2, "__ARM_FEATURE_CRYPTO", pfile); aarch64_def_or_undef (TARGET_SIMD_RDMA, "__ARM_FEATURE_QRDMX", pfile); aarch64_def_or_undef (TARGET_SVE, "__ARM_FEATURE_SVE", pfile); cpp_undef (pfile, "__ARM_FEATURE_SVE_BITS"); diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index cfeaf4657ab..996a261334a 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -177,10 +177,13 @@ enum class aarch64_feature : unsigned char { #endif -/* Macros to test ISA flags. */ +/* Macros to test ISA flags. + + There is intentionally no macro for AARCH64_FL_CRYPTO, since this flag bit + is not always set when its constituent features are present. + Check (TARGET_AES && TARGET_SHA2) instead. */ #define AARCH64_ISA_CRC (aarch64_isa_flags & AARCH64_FL_CRC) -#define AARCH64_ISA_CRYPTO (aarch64_isa_flags & AARCH64_FL_CRYPTO) #define AARCH64_ISA_FP (aarch64_isa_flags & AARCH64_FL_FP) #define AARCH64_ISA_SIMD (aarch64_isa_flags & AARCH64_FL_SIMD) #define AARCH64_ISA_LSE (aarch64_isa_flags & AARCH64_FL_LSE) @@ -224,9 +227,6 @@ enum class aarch64_feature : unsigned char { #define AARCH64_ISA_CSSC (aarch64_isa_flags & AARCH64_FL_CSSC) #define AARCH64_ISA_RCPC (aarch64_isa_flags & AARCH64_FL_RCPC) -/* Crypto is an optional extension to AdvSIMD. */ -#define TARGET_CRYPTO (AARCH64_ISA_CRYPTO) - /* SHA2 is an optional extension to AdvSIMD. */ #define TARGET_SHA2 (AARCH64_ISA_SHA2) diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_27.c b/gcc/testsuite/gcc.target/aarch64/options_set_27.c new file mode 100644 index 00000000000..e3574464013 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/options_set_27.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=armv8.2-a+aes+sha3" } */ + +int main () +{ + return 0; +} + +/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc\+aes\+sha3\n} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_4.c b/gcc/testsuite/gcc.target/aarch64/options_set_4.c index 5370e02e153..7b00d09a47f 100644 --- a/gcc/testsuite/gcc.target/aarch64/options_set_4.c +++ b/gcc/testsuite/gcc.target/aarch64/options_set_4.c @@ -6,7 +6,7 @@ int main () return 0; } -/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc\+crypto} 1 } } */ +/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc\+crypto\n} 1 } } */ /* Check if individual bits that make up a grouping is specified that only the grouping is kept. */ commit 5aa9ed0f353f835005c3df8932c7bc6e26f53904 Author: Wilco Dijkstra Date: Wed Oct 25 16:28:04 2023 +0100 AArch64: Fix strict-align cpymem/setmem [PR103100] The cpymemdi/setmemdi implementation doesn't fully support strict alignment. Block the expansion if the alignment is less than 16 with STRICT_ALIGNMENT. Clean up the condition when to use MOPS. gcc/ChangeLog/ PR target/103100 * config/aarch64/aarch64.md (cpymemdi): Remove pattern condition. (setmemdi): Likewise. * config/aarch64/aarch64.cc (aarch64_expand_cpymem): Support strict-align. Cleanup condition for using MOPS. (aarch64_expand_setmem): Likewise. (cherry picked from commit 318f5232cfb3e0c9694889565e1f5424d0354463) diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index b8a4ab1b980..2f01580a797 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -24897,27 +24897,23 @@ aarch64_expand_cpymem (rtx *operands) int mode_bits; rtx dst = operands[0]; rtx src = operands[1]; + unsigned align = UINTVAL (operands[3]); rtx base; machine_mode cur_mode = BLKmode; + bool size_p = optimize_function_for_size_p (cfun); - /* Variable-sized memcpy can go through the MOPS expansion if available. */ - if (!CONST_INT_P (operands[2])) + /* Variable-sized or strict-align copies may use the MOPS expansion. */ + if (!CONST_INT_P (operands[2]) || (STRICT_ALIGNMENT && align < 16)) return aarch64_expand_cpymem_mops (operands); - unsigned HOST_WIDE_INT size = INTVAL (operands[2]); - - /* Try to inline up to 256 bytes or use the MOPS threshold if available. */ - unsigned HOST_WIDE_INT max_copy_size - = TARGET_MOPS ? aarch64_mops_memcpy_size_threshold : 256; + unsigned HOST_WIDE_INT size = UINTVAL (operands[2]); - bool size_p = optimize_function_for_size_p (cfun); + /* Try to inline up to 256 bytes. */ + unsigned max_copy_size = 256; + unsigned mops_threshold = aarch64_mops_memcpy_size_threshold; - /* Large constant-sized cpymem should go through MOPS when possible. - It should be a win even for size optimization in the general case. - For speed optimization the choice between MOPS and the SIMD sequence - depends on the size of the copy, rather than number of instructions, - alignment etc. */ - if (size > max_copy_size) + /* Large copies use MOPS when available or a library call. */ + if (size > max_copy_size || (TARGET_MOPS && size > mops_threshold)) return aarch64_expand_cpymem_mops (operands); int copy_bits = 256; @@ -25081,12 +25077,13 @@ aarch64_expand_setmem (rtx *operands) unsigned HOST_WIDE_INT len; rtx dst = operands[0]; rtx val = operands[2], src; + unsigned align = UINTVAL (operands[3]); rtx base; machine_mode cur_mode = BLKmode, next_mode; - /* If we don't have SIMD registers or the size is variable use the MOPS - inlined sequence if possible. */ - if (!CONST_INT_P (operands[1]) || !TARGET_SIMD) + /* Variable-sized or strict-align memset may use the MOPS expansion. */ + if (!CONST_INT_P (operands[1]) || !TARGET_SIMD + || (STRICT_ALIGNMENT && align < 16)) return aarch64_expand_setmem_mops (operands); bool size_p = optimize_function_for_size_p (cfun); @@ -25094,10 +25091,13 @@ aarch64_expand_setmem (rtx *operands) /* Default the maximum to 256-bytes when considering only libcall vs SIMD broadcast sequence. */ unsigned max_set_size = 256; + unsigned mops_threshold = aarch64_mops_memset_size_threshold; - len = INTVAL (operands[1]); - if (len > max_set_size && !TARGET_MOPS) - return false; + len = UINTVAL (operands[1]); + + /* Large memset uses MOPS when available or a library call. */ + if (len > max_set_size || (TARGET_MOPS && len > mops_threshold)) + return aarch64_expand_setmem_mops (operands); int cst_val = !!(CONST_INT_P (val) && (INTVAL (val) != 0)); /* The MOPS sequence takes: @@ -25110,12 +25110,6 @@ aarch64_expand_setmem (rtx *operands) the arguments + 1 for the call. */ unsigned libcall_cost = 4; - /* Upper bound check. For large constant-sized setmem use the MOPS sequence - when available. */ - if (TARGET_MOPS - && len >= (unsigned HOST_WIDE_INT) aarch64_mops_memset_size_threshold) - return aarch64_expand_setmem_mops (operands); - /* Attempt a sequence with a vector broadcast followed by stores. Count the number of operations involved to see if it's worth it against the alternatives. A simple counter simd_ops on the @@ -25157,10 +25151,8 @@ aarch64_expand_setmem (rtx *operands) simd_ops++; n -= mode_bits; - /* Do certain trailing copies as overlapping if it's going to be - cheaper. i.e. less instructions to do so. For instance doing a 15 - byte copy it's more efficient to do two overlapping 8 byte copies than - 8 + 4 + 2 + 1. Only do this when -mstrict-align is not supplied. */ + /* Emit trailing writes using overlapping unaligned accesses + (when !STRICT_ALIGNMENT) - this is smaller and faster. */ if (n > 0 && n < copy_limit / 2 && !STRICT_ALIGNMENT) { next_mode = smallest_mode_for_size (n, MODE_INT); diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 922cc987595..b585604cbe0 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -1659,7 +1659,7 @@ (match_operand:BLK 1 "memory_operand") (match_operand:DI 2 "general_operand") (match_operand:DI 3 "immediate_operand")] - "!STRICT_ALIGNMENT || TARGET_MOPS" + "" { if (aarch64_expand_cpymem (operands)) DONE; @@ -1756,7 +1756,7 @@ (match_operand:QI 2 "nonmemory_operand")) ;; Value (use (match_operand:DI 1 "general_operand")) ;; Length (match_operand 3 "immediate_operand")] ;; Align - "TARGET_SIMD || TARGET_MOPS" + "" { if (aarch64_expand_setmem (operands)) DONE; commit e65b1a1764a5cfb57d12e9aa6815093fec7eef2b Author: GCC Administrator Date: Fri Jun 28 00:22:31 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e136aa6f204..db259ce8b74 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,35 @@ +2024-06-27 Wilco Dijkstra + + Backported from master: + 2023-11-30 Wilco Dijkstra + + PR target/103100 + * config/aarch64/aarch64.md (cpymemdi): Remove pattern condition. + (setmemdi): Likewise. + * config/aarch64/aarch64.cc (aarch64_expand_cpymem): Support + strict-align. Cleanup condition for using MOPS. + (aarch64_expand_setmem): Likewise. + +2024-06-27 Andrew Carlotti + + Backported from master: + 2023-12-16 Andrew Carlotti + + PR target/115618 + * common/config/aarch64/aarch64-common.cc + (aarch64_get_extension_string_for_isa_flags): Fix generation of + the "+nocrypto" extension. + * config/aarch64/aarch64.h (AARCH64_ISA_CRYPTO): Remove. + (TARGET_CRYPTO): Remove. + * config/aarch64/aarch64-c.cc (aarch64_update_cpp_builtins): + Don't use TARGET_CRYPTO. + +2024-06-27 Kyrylo Tkachov + + * config/aarch64/aarch64-cores.def (grace): New entry. + * config/aarch64/aarch64-tune.md: Regenerate. + * doc/invoke.texi (AArch64 Options): Document the above. + 2024-06-24 Kewen Lin Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 3402e552106..b08c5cee3e2 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240627 +20240628 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c82f0655725..71a6a1de8c9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2024-06-27 Andrew Carlotti + + Backported from master: + 2023-12-16 Andrew Carlotti + + PR target/115618 + * gcc.target/aarch64/options_set_4.c: Add terminating newline. + * gcc.target/aarch64/options_set_27.c: New test. + 2024-06-24 Kewen Lin Backported from master: diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index cd9b4e6de80..1fdd7f39b59 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,12 @@ +2024-06-27 Alexandre Oliva + + Backported from master: + 2024-06-27 Alexandre Oliva + + PR libstdc++/115454 + * testsuite/experimental/simd/pr115454_find_last_set.cc: Defer + to check_vect_support_and_set_flags's default dg-do action. + 2024-06-25 Jonathan Wakely * doc/xml/manual/status_cxx1998.xml: Remove confusing "not in commit 361bfcec901ca882130e338aebaa2ebc6ea2dc3b Author: Kewen Lin Date: Thu Jun 20 20:23:56 2024 -0500 rs6000: Fix wrong RTL patterns for vector merge high/low word on LE Commit r12-4496 changes some define_expands and define_insns for vector merge high/low word, which are altivec_vmrg[hl]w, vsx_xxmrg[hl]w_. These defines are mainly for built-in function vec_merge{h,l}, __builtin_vsx_xxmrghw, __builtin_vsx_xxmrghw_4si and some internal gen function needs. These functions should consider endianness, taking vec_mergeh as example, as PVIPR defines, vec_mergeh "Merges the first halves (in element order) of two vectors", it does note it's in element order. So it's mapped into vmrghw on BE while vmrglw on LE respectively. Although the mapped insns are different, as the discussion in PR106069, the RTL pattern should be still the same, it is conformed before commit r12-4496, define_expand altivec_vmrghw got expanded into: (vec_select:VSX_W (vec_concat: (match_operand:VSX_W 1 "register_operand" "wa,v") (match_operand:VSX_W 2 "register_operand" "wa,v")) (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))] on both BE and LE then. But commit r12-4496 changed it to expand into: (vec_select:VSX_W (vec_concat: (match_operand:VSX_W 1 "register_operand" "wa,v") (match_operand:VSX_W 2 "register_operand" "wa,v")) (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))] on BE, and (vec_select:VSX_W (vec_concat: (match_operand:VSX_W 1 "register_operand" "wa,v") (match_operand:VSX_W 2 "register_operand" "wa,v")) (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))] on LE, although the mapped insn are still vmrghw on BE and vmrglw on LE, the associated RTL pattern is completely wrong and inconsistent with the mapped insn. If optimization passes leave this pattern alone, even if its pattern doesn't represent its mapped insn, it's still fine, that's why simple testing on bif doesn't expose this issue. But once some optimization pass such as combine does some changes basing on this wrong pattern, because the pattern doesn't match the semantics that the expanded insn is intended to represent, it would cause the unexpected result. So this patch is to fix the wrong RTL pattern, ensure the associated RTL patterns become the same as before which can have the same semantic as their mapped insns. With the proposed patch, the expanders like altivec_vmrghw expands into altivec_vmrghb_direct_be or altivec_vmrglb_direct_le depending on endianness, "direct" can easily show which insn would be generated, _be and _le are mainly for the different RTL patterns as endianness. Co-authored-by: Xionghu Luo PR target/106069 PR target/115355 gcc/ChangeLog: * config/rs6000/altivec.md (altivec_vmrghw_direct_): Rename to ... (altivec_vmrghw_direct__be): ... this. Add the condition BYTES_BIG_ENDIAN. (altivec_vmrghw_direct__le): New define_insn. (altivec_vmrglw_direct_): Rename to ... (altivec_vmrglw_direct__be): ... this. Add the condition BYTES_BIG_ENDIAN. (altivec_vmrglw_direct__le): New define_insn. (altivec_vmrghw): Adjust by calling gen_altivec_vmrghw_direct_v4si_be for BE and gen_altivec_vmrglw_direct_v4si_le for LE. (altivec_vmrglw): Adjust by calling gen_altivec_vmrglw_direct_v4si_be for BE and gen_altivec_vmrghw_direct_v4si_le for LE. (vec_widen_umult_hi_v8hi): Adjust the call to gen_altivec_vmrghw_direct_v4si by gen_altivec_vmrghw for BE and by gen_altivec_vmrglw for LE. (vec_widen_smult_hi_v8hi): Likewise. (vec_widen_umult_lo_v8hi): Adjust the call to gen_altivec_vmrglw_direct_v4si by gen_altivec_vmrglw for BE and by gen_altivec_vmrghw for LE (vec_widen_smult_lo_v8hi): Likewise. * config/rs6000/rs6000.cc (altivec_expand_vec_perm_const): Replace CODE_FOR_altivec_vmrghw_direct_v4si by CODE_FOR_altivec_vmrghw_direct_v4si_be for BE and CODE_FOR_altivec_vmrghw_direct_v4si_le for LE. And replace CODE_FOR_altivec_vmrglw_direct_v4si by CODE_FOR_altivec_vmrglw_direct_v4si_be for BE and CODE_FOR_altivec_vmrglw_direct_v4si_le for LE. * config/rs6000/vsx.md (vsx_xxmrghw_): Adjust by calling gen_altivec_vmrghw_direct_v4si_be for BE and gen_altivec_vmrglw_direct_v4si_le for LE. (vsx_xxmrglw_): Adjust by calling gen_altivec_vmrglw_direct_v4si_be for BE and gen_altivec_vmrghw_direct_v4si_le for LE. gcc/testsuite/ChangeLog: * g++.target/powerpc/pr106069.C: New test. * gcc.target/powerpc/pr115355.c: New test. (cherry picked from commit 52c112800d9f44457c4832309a48c00945811313) diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md index ad1224e0b57..92e2e4a4090 100644 --- a/gcc/config/rs6000/altivec.md +++ b/gcc/config/rs6000/altivec.md @@ -1212,16 +1212,18 @@ (use (match_operand:V4SI 2 "register_operand"))] "VECTOR_MEM_ALTIVEC_P (V4SImode)" { - rtx (*fun) (rtx, rtx, rtx); - fun = BYTES_BIG_ENDIAN ? gen_altivec_vmrghw_direct_v4si - : gen_altivec_vmrglw_direct_v4si; - if (!BYTES_BIG_ENDIAN) - std::swap (operands[1], operands[2]); - emit_insn (fun (operands[0], operands[1], operands[2])); + if (BYTES_BIG_ENDIAN) + emit_insn (gen_altivec_vmrghw_direct_v4si_be (operands[0], + operands[1], + operands[2])); + else + emit_insn (gen_altivec_vmrglw_direct_v4si_le (operands[0], + operands[2], + operands[1])); DONE; }) -(define_insn "altivec_vmrghw_direct_" +(define_insn "altivec_vmrghw_direct__be" [(set (match_operand:VSX_W 0 "register_operand" "=wa,v") (vec_select:VSX_W (vec_concat: @@ -1229,7 +1231,21 @@ (match_operand:VSX_W 2 "register_operand" "wa,v")) (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))] - "TARGET_ALTIVEC" + "TARGET_ALTIVEC && BYTES_BIG_ENDIAN" + "@ + xxmrghw %x0,%x1,%x2 + vmrghw %0,%1,%2" + [(set_attr "type" "vecperm")]) + +(define_insn "altivec_vmrghw_direct__le" + [(set (match_operand:VSX_W 0 "register_operand" "=wa,v") + (vec_select:VSX_W + (vec_concat: + (match_operand:VSX_W 2 "register_operand" "wa,v") + (match_operand:VSX_W 1 "register_operand" "wa,v")) + (parallel [(const_int 2) (const_int 6) + (const_int 3) (const_int 7)])))] + "TARGET_ALTIVEC && !BYTES_BIG_ENDIAN" "@ xxmrghw %x0,%x1,%x2 vmrghw %0,%1,%2" @@ -1318,16 +1334,18 @@ (use (match_operand:V4SI 2 "register_operand"))] "VECTOR_MEM_ALTIVEC_P (V4SImode)" { - rtx (*fun) (rtx, rtx, rtx); - fun = BYTES_BIG_ENDIAN ? gen_altivec_vmrglw_direct_v4si - : gen_altivec_vmrghw_direct_v4si; - if (!BYTES_BIG_ENDIAN) - std::swap (operands[1], operands[2]); - emit_insn (fun (operands[0], operands[1], operands[2])); + if (BYTES_BIG_ENDIAN) + emit_insn (gen_altivec_vmrglw_direct_v4si_be (operands[0], + operands[1], + operands[2])); + else + emit_insn (gen_altivec_vmrghw_direct_v4si_le (operands[0], + operands[2], + operands[1])); DONE; }) -(define_insn "altivec_vmrglw_direct_" +(define_insn "altivec_vmrglw_direct__be" [(set (match_operand:VSX_W 0 "register_operand" "=wa,v") (vec_select:VSX_W (vec_concat: @@ -1335,7 +1353,21 @@ (match_operand:VSX_W 2 "register_operand" "wa,v")) (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))] - "TARGET_ALTIVEC" + "TARGET_ALTIVEC && BYTES_BIG_ENDIAN" + "@ + xxmrglw %x0,%x1,%x2 + vmrglw %0,%1,%2" + [(set_attr "type" "vecperm")]) + +(define_insn "altivec_vmrglw_direct__le" + [(set (match_operand:VSX_W 0 "register_operand" "=wa,v") + (vec_select:VSX_W + (vec_concat: + (match_operand:VSX_W 2 "register_operand" "wa,v") + (match_operand:VSX_W 1 "register_operand" "wa,v")) + (parallel [(const_int 0) (const_int 4) + (const_int 1) (const_int 5)])))] + "TARGET_ALTIVEC && !BYTES_BIG_ENDIAN" "@ xxmrglw %x0,%x1,%x2 vmrglw %0,%1,%2" @@ -3807,13 +3839,13 @@ { emit_insn (gen_altivec_vmuleuh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmulouh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrghw_direct_v4si (operands[0], ve, vo)); + emit_insn (gen_altivec_vmrghw (operands[0], ve, vo)); } else { emit_insn (gen_altivec_vmulouh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmuleuh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrghw_direct_v4si (operands[0], vo, ve)); + emit_insn (gen_altivec_vmrglw (operands[0], ve, vo)); } DONE; }) @@ -3832,13 +3864,13 @@ { emit_insn (gen_altivec_vmuleuh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmulouh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrglw_direct_v4si (operands[0], ve, vo)); + emit_insn (gen_altivec_vmrglw (operands[0], ve, vo)); } else { emit_insn (gen_altivec_vmulouh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmuleuh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrglw_direct_v4si (operands[0], vo, ve)); + emit_insn (gen_altivec_vmrghw (operands[0], ve, vo)); } DONE; }) @@ -3857,13 +3889,13 @@ { emit_insn (gen_altivec_vmulesh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmulosh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrghw_direct_v4si (operands[0], ve, vo)); + emit_insn (gen_altivec_vmrghw (operands[0], ve, vo)); } else { emit_insn (gen_altivec_vmulosh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmulesh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrghw_direct_v4si (operands[0], vo, ve)); + emit_insn (gen_altivec_vmrglw (operands[0], ve, vo)); } DONE; }) @@ -3882,13 +3914,13 @@ { emit_insn (gen_altivec_vmulesh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmulosh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrglw_direct_v4si (operands[0], ve, vo)); + emit_insn (gen_altivec_vmrglw (operands[0], ve, vo)); } else { emit_insn (gen_altivec_vmulosh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmulesh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrglw_direct_v4si (operands[0], vo, ve)); + emit_insn (gen_altivec_vmrghw (operands[0], ve, vo)); } DONE; }) diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index 9cfde1a52ea..b3d648312f1 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -23174,8 +23174,8 @@ altivec_expand_vec_perm_const (rtx target, rtx op0, rtx op1, : CODE_FOR_altivec_vmrglh_direct, {0, 1, 16, 17, 2, 3, 18, 19, 4, 5, 20, 21, 6, 7, 22, 23}}, {OPTION_MASK_ALTIVEC, - BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghw_direct_v4si - : CODE_FOR_altivec_vmrglw_direct_v4si, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghw_direct_v4si_be + : CODE_FOR_altivec_vmrglw_direct_v4si_le, {0, 1, 2, 3, 16, 17, 18, 19, 4, 5, 6, 7, 20, 21, 22, 23}}, {OPTION_MASK_ALTIVEC, BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglb_direct @@ -23186,8 +23186,8 @@ altivec_expand_vec_perm_const (rtx target, rtx op0, rtx op1, : CODE_FOR_altivec_vmrghh_direct, {8, 9, 24, 25, 10, 11, 26, 27, 12, 13, 28, 29, 14, 15, 30, 31}}, {OPTION_MASK_ALTIVEC, - BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglw_direct_v4si - : CODE_FOR_altivec_vmrghw_direct_v4si, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglw_direct_v4si_be + : CODE_FOR_altivec_vmrghw_direct_v4si_le, {8, 9, 10, 11, 24, 25, 26, 27, 12, 13, 14, 15, 28, 29, 30, 31}}, {OPTION_MASK_P8_VECTOR, BYTES_BIG_ENDIAN ? CODE_FOR_p8_vmrgew_v4sf_direct diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md index f70d69ee4b9..b9a1bfb5c16 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -4683,12 +4683,14 @@ (const_int 1) (const_int 5)])))] "VECTOR_MEM_VSX_P (mode)" { - rtx (*fun) (rtx, rtx, rtx); - fun = BYTES_BIG_ENDIAN ? gen_altivec_vmrghw_direct_ - : gen_altivec_vmrglw_direct_; - if (!BYTES_BIG_ENDIAN) - std::swap (operands[1], operands[2]); - emit_insn (fun (operands[0], operands[1], operands[2])); + if (BYTES_BIG_ENDIAN) + emit_insn (gen_altivec_vmrghw_direct_v4si_be (operands[0], + operands[1], + operands[2])); + else + emit_insn (gen_altivec_vmrglw_direct_v4si_le (operands[0], + operands[2], + operands[1])); DONE; } [(set_attr "type" "vecperm")]) @@ -4703,12 +4705,14 @@ (const_int 3) (const_int 7)])))] "VECTOR_MEM_VSX_P (mode)" { - rtx (*fun) (rtx, rtx, rtx); - fun = BYTES_BIG_ENDIAN ? gen_altivec_vmrglw_direct_ - : gen_altivec_vmrghw_direct_; - if (!BYTES_BIG_ENDIAN) - std::swap (operands[1], operands[2]); - emit_insn (fun (operands[0], operands[1], operands[2])); + if (BYTES_BIG_ENDIAN) + emit_insn (gen_altivec_vmrglw_direct_v4si_be (operands[0], + operands[1], + operands[2])); + else + emit_insn (gen_altivec_vmrghw_direct_v4si_le (operands[0], + operands[2], + operands[1])); DONE; } [(set_attr "type" "vecperm")]) diff --git a/gcc/testsuite/g++.target/powerpc/pr106069.C b/gcc/testsuite/g++.target/powerpc/pr106069.C new file mode 100644 index 00000000000..537207d2fe8 --- /dev/null +++ b/gcc/testsuite/g++.target/powerpc/pr106069.C @@ -0,0 +1,119 @@ +/* { dg-options "-O -fno-tree-forwprop -maltivec" } */ +/* { dg-require-effective-target vmx_hw } */ +/* { dg-do run } */ + +typedef __attribute__ ((altivec (vector__))) unsigned native_simd_type; + +union +{ + native_simd_type V; + int R[4]; +} store_le_vec; + +struct S +{ + S () = default; + S (unsigned B0) + { + native_simd_type val{B0}; + m_simd = val; + } + void store_le (unsigned int out[]) + { + store_le_vec.V = m_simd; + unsigned int x0 = store_le_vec.R[0]; + __builtin_memcpy (out, &x0, 4); + } + S rotl (unsigned int r) + { + native_simd_type rot{r}; + return __builtin_vec_rl (m_simd, rot); + } + void operator+= (S other) + { + m_simd = __builtin_vec_add (m_simd, other.m_simd); + } + void operator^= (S other) + { + m_simd = __builtin_vec_xor (m_simd, other.m_simd); + } + static void transpose (S &B0, S B1, S B2, S B3) + { + native_simd_type T0 = __builtin_vec_mergeh (B0.m_simd, B2.m_simd); + native_simd_type T1 = __builtin_vec_mergeh (B1.m_simd, B3.m_simd); + native_simd_type T2 = __builtin_vec_mergel (B0.m_simd, B2.m_simd); + native_simd_type T3 = __builtin_vec_mergel (B1.m_simd, B3.m_simd); + B0 = __builtin_vec_mergeh (T0, T1); + B3 = __builtin_vec_mergel (T2, T3); + } + S (native_simd_type x) : m_simd (x) {} + native_simd_type m_simd; +}; + +void +foo (unsigned int output[], unsigned state[]) +{ + S R00 = state[0]; + S R01 = state[0]; + S R02 = state[2]; + S R03 = state[0]; + S R05 = state[5]; + S R06 = state[6]; + S R07 = state[7]; + S R08 = state[8]; + S R09 = state[9]; + S R10 = state[10]; + S R11 = state[11]; + S R12 = state[12]; + S R13 = state[13]; + S R14 = state[4]; + S R15 = state[15]; + for (int r = 0; r != 10; ++r) + { + R09 += R13; + R11 += R15; + R05 ^= R09; + R06 ^= R10; + R07 ^= R11; + R07 = R07.rotl (7); + R00 += R05; + R01 += R06; + R02 += R07; + R15 ^= R00; + R12 ^= R01; + R13 ^= R02; + R00 += R05; + R01 += R06; + R02 += R07; + R15 ^= R00; + R12 = R12.rotl (8); + R13 = R13.rotl (8); + R10 += R15; + R11 += R12; + R08 += R13; + R09 += R14; + R05 ^= R10; + R06 ^= R11; + R07 ^= R08; + R05 = R05.rotl (7); + R06 = R06.rotl (7); + R07 = R07.rotl (7); + } + R00 += state[0]; + S::transpose (R00, R01, R02, R03); + R00.store_le (output); +} + +unsigned int res[1]; +unsigned main_state[]{1634760805, 60878, 2036477234, 6, + 0, 825562964, 1471091955, 1346092787, + 506976774, 4197066702, 518848283, 118491664, + 0, 0, 0, 0}; +int +main () +{ + foo (res, main_state); + if (res[0] != 0x41fcef98) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/powerpc/pr115355.c b/gcc/testsuite/gcc.target/powerpc/pr115355.c new file mode 100644 index 00000000000..8955126b808 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr115355.c @@ -0,0 +1,37 @@ +/* { dg-do run } */ +/* { dg-require-effective-target p9vector_hw } */ +/* Force vectorization with -fno-vect-cost-model to have vector unpack + which exposes the issue in PR115355. */ +/* { dg-options "-O2 -mdejagnu-cpu=power9 -fno-vect-cost-model" } */ + +/* Verify it runs successfully. */ + +__attribute__((noipa)) +void setToIdentityGOOD(unsigned long long *mVec, unsigned int mLen) +{ + #pragma GCC novector + for (unsigned int i = 0; i < mLen; i++) + mVec[i] = i; +} + +__attribute__((noipa)) +void setToIdentityBAD(unsigned long long *mVec, unsigned int mLen) +{ + for (unsigned int i = 0; i < mLen; i++) + mVec[i] = i; +} + +unsigned long long vec1[100]; +unsigned long long vec2[100]; + +int main() +{ + unsigned int l = 29; + setToIdentityGOOD (vec1, 29); + setToIdentityBAD (vec2, 29); + + if (__builtin_memcmp (vec1, vec2, l * sizeof (vec1[0])) != 0) + __builtin_abort (); + + return 0; +} commit 4b64a1051a927a65a9acefbbb5714a8118c320bc Author: Jonathan Wakely Date: Wed Jun 26 20:22:54 2024 +0100 libstdc++: Fix std::format for chrono::duration with unsigned rep [PR115668] Using std::chrono::abs is only valid if numeric_limits::is_signed is true, so using it unconditionally made it ill-formed to format a duration with an unsigned rep. The duration formatter might as well negate the duration itself instead of using chrono::abs, because it already needs to check for a negative value. libstdc++-v3/ChangeLog: PR libstdc++/115668 * include/bits/chrono_io.h (formatter::format): Do not use chrono::abs. * testsuite/20_util/duration/io.cc: Check formatting a duration with unsigned rep. (cherry picked from commit dafa750c8a6f0a088677871bfaad054881737ab1) diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h index 1838ad1a8c6..d63f7c40d83 100644 --- a/libstdc++-v3/include/bits/chrono_io.h +++ b/libstdc++-v3/include/bits/chrono_io.h @@ -1608,7 +1608,10 @@ namespace __format format(const chrono::duration<_Rep, _Period>& __d, basic_format_context<_Out, _CharT>& __fc) const { - return _M_f._M_format(chrono::abs(__d), __fc, __d < __d.zero()); + if constexpr (numeric_limits<_Rep>::is_signed) + if (__d < __d.zero()) + return _M_f._M_format(-__d, __fc, true); + return _M_f._M_format(__d, __fc, false); } private: diff --git a/libstdc++-v3/testsuite/20_util/duration/io.cc b/libstdc++-v3/testsuite/20_util/duration/io.cc index 2043f0c4e9d..b7028a4e6c6 100644 --- a/libstdc++-v3/testsuite/20_util/duration/io.cc +++ b/libstdc++-v3/testsuite/20_util/duration/io.cc @@ -101,6 +101,12 @@ test_format() std::chrono::duration d{0.5}; s = std::format("{}", d); VERIFY( s == "0.5ms" ); + + std::chrono::duration u{500}; // PR libstdc++/115668 + s = std::format("{}", u); + VERIFY( s == "500ms" ); + s = std::format("{:%Q %q}", u); + VERIFY( s == "500 ms" ); } int main() commit 84cae12ed9055153bb5a4b72d50f0c36110b8027 Author: Jonathan Wakely Date: Tue Jun 25 13:35:17 2024 +0100 libstdc++: Replace viewcvs links in docs with cgit links For this backport to the release branch, the links to the git repo refer to the branch. libstdc++-v3/ChangeLog: * doc/xml/faq.xml: Replace viewcvs links with cgit links. * doc/xml/manual/allocator.xml: Likewise. * doc/xml/manual/mt_allocator.xml: Likewise. * doc/html/*: Regenerate. (cherry picked from commit 9d8021d1875677286c3dde90dfed2aca864edad0) diff --git a/libstdc++-v3/doc/html/faq.html b/libstdc++-v3/doc/html/faq.html index d08f03940c9..2e913920d05 100644 --- a/libstdc++-v3/doc/html/faq.html +++ b/libstdc++-v3/doc/html/faq.html @@ -148,7 +148,7 @@ The libstdc++ project is contributed to by several developers all over the world, in the same way as GCC or the Linux kernel. The current maintainers are listed in the - MAINTAINERS + MAINTAINERS file (look for "c++ runtime libs").

Development and discussion is held on the libstdc++ mailing diff --git a/libstdc++-v3/doc/html/manual/memory.html b/libstdc++-v3/doc/html/manual/memory.html index 08ad2fd4dd8..4bea1390014 100644 --- a/libstdc++-v3/doc/html/manual/memory.html +++ b/libstdc++-v3/doc/html/manual/memory.html @@ -120,8 +120,8 @@ Over multiple iterations, various STL container objects have elements inserted to some maximum amount. A variety of allocators are tested. - Test source for sequence - and associative + Test source for sequence + and associative containers.

  • Insertion and erasure in a multi-threaded environment. @@ -130,14 +130,14 @@ on a per-thread basis, as well as measuring thread contention for memory resources. Test source - here. + here.

  • A threaded producer/consumer model.

    Test source for - sequence + sequence and - associative + associative containers.

  • Since GCC 12 the default choice for diff --git a/libstdc++-v3/doc/html/manual/mt_allocator_impl.html b/libstdc++-v3/doc/html/manual/mt_allocator_impl.html index 2e5926add00..7b35919d7bb 100644 --- a/libstdc++-v3/doc/html/manual/mt_allocator_impl.html +++ b/libstdc++-v3/doc/html/manual/mt_allocator_impl.html @@ -155,7 +155,7 @@ that uses it is fully constructed. For most (but not all) STL containers, this works, as an instance of the allocator is constructed as part of a container's constructor. However, this assumption is implementation-specific, and subject to change. For an example of a -pool that frees memory, see the following - - example. +pool that frees memory, see the + ext/mt_allocator/deallocate_local-6.cc + example.

    \ No newline at end of file diff --git a/libstdc++-v3/doc/xml/faq.xml b/libstdc++-v3/doc/xml/faq.xml index da41199584e..0481c695fcd 100644 --- a/libstdc++-v3/doc/xml/faq.xml +++ b/libstdc++-v3/doc/xml/faq.xml @@ -91,7 +91,7 @@ The libstdc++ project is contributed to by several developers all over the world, in the same way as GCC or the Linux kernel. The current maintainers are listed in the - MAINTAINERS + MAINTAINERS file (look for "c++ runtime libs").
    diff --git a/libstdc++-v3/doc/xml/manual/allocator.xml b/libstdc++-v3/doc/xml/manual/allocator.xml index 2418539be8d..bf709356fce 100644 --- a/libstdc++-v3/doc/xml/manual/allocator.xml +++ b/libstdc++-v3/doc/xml/manual/allocator.xml @@ -184,8 +184,8 @@ Over multiple iterations, various STL container objects have elements inserted to some maximum amount. A variety of allocators are tested. - Test source for sequence - and associative + Test source for sequence + and associative containers. @@ -200,7 +200,7 @@ on a per-thread basis, as well as measuring thread contention for memory resources. Test source - here. + here.
    @@ -210,9 +210,9 @@
    Test source for - sequence + sequence and - associative + associative containers. diff --git a/libstdc++-v3/doc/xml/manual/mt_allocator.xml b/libstdc++-v3/doc/xml/manual/mt_allocator.xml index f1c09b3bd8f..58bb4ea299c 100644 --- a/libstdc++-v3/doc/xml/manual/mt_allocator.xml +++ b/libstdc++-v3/doc/xml/manual/mt_allocator.xml @@ -307,9 +307,9 @@ that uses it is fully constructed. For most (but not all) STL containers, this works, as an instance of the allocator is constructed as part of a container's constructor. However, this assumption is implementation-specific, and subject to change. For an example of a -pool that frees memory, see the following - - example. +pool that frees memory, see the + ext/mt_allocator/deallocate_local-6.cc + example. commit ae1f6eba16c9daa6e71425d79c0b35028063ca6d Author: GCC Administrator Date: Sat Jun 29 00:22:14 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index db259ce8b74..f4b9b507375 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,46 @@ +2024-06-28 Kewen Lin + + Backported from master: + 2024-06-21 Kewen Lin + Xionghu Luo + + PR target/106069 + PR target/115355 + * config/rs6000/altivec.md (altivec_vmrghw_direct_): Rename + to ... + (altivec_vmrghw_direct__be): ... this. Add the condition + BYTES_BIG_ENDIAN. + (altivec_vmrghw_direct__le): New define_insn. + (altivec_vmrglw_direct_): Rename to ... + (altivec_vmrglw_direct__be): ... this. Add the condition + BYTES_BIG_ENDIAN. + (altivec_vmrglw_direct__le): New define_insn. + (altivec_vmrghw): Adjust by calling gen_altivec_vmrghw_direct_v4si_be + for BE and gen_altivec_vmrglw_direct_v4si_le for LE. + (altivec_vmrglw): Adjust by calling gen_altivec_vmrglw_direct_v4si_be + for BE and gen_altivec_vmrghw_direct_v4si_le for LE. + (vec_widen_umult_hi_v8hi): Adjust the call to + gen_altivec_vmrghw_direct_v4si by gen_altivec_vmrghw for BE + and by gen_altivec_vmrglw for LE. + (vec_widen_smult_hi_v8hi): Likewise. + (vec_widen_umult_lo_v8hi): Adjust the call to + gen_altivec_vmrglw_direct_v4si by gen_altivec_vmrglw for BE + and by gen_altivec_vmrghw for LE + (vec_widen_smult_lo_v8hi): Likewise. + * config/rs6000/rs6000.cc (altivec_expand_vec_perm_const): Replace + CODE_FOR_altivec_vmrghw_direct_v4si by + CODE_FOR_altivec_vmrghw_direct_v4si_be for BE and + CODE_FOR_altivec_vmrghw_direct_v4si_le for LE. And replace + CODE_FOR_altivec_vmrglw_direct_v4si by + CODE_FOR_altivec_vmrglw_direct_v4si_be for BE and + CODE_FOR_altivec_vmrglw_direct_v4si_le for LE. + * config/rs6000/vsx.md (vsx_xxmrghw_): Adjust by calling + gen_altivec_vmrghw_direct_v4si_be for BE and + gen_altivec_vmrglw_direct_v4si_le for LE. + (vsx_xxmrglw_): Adjust by calling + gen_altivec_vmrglw_direct_v4si_be for BE and + gen_altivec_vmrghw_direct_v4si_le for LE. + 2024-06-27 Wilco Dijkstra Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index b08c5cee3e2..674b36c5c7c 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240628 +20240629 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 71a6a1de8c9..b7d55cf675a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2024-06-28 Kewen Lin + + Backported from master: + 2024-06-21 Kewen Lin + Xionghu Luo + + PR target/106069 + PR target/115355 + * g++.target/powerpc/pr106069.C: New test. + * gcc.target/powerpc/pr115355.c: New test. + 2024-06-27 Andrew Carlotti Backported from master: diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 1fdd7f39b59..959d59758ff 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,24 @@ +2024-06-28 Jonathan Wakely + + Backported from master: + 2024-06-25 Jonathan Wakely + + * doc/xml/faq.xml: Replace viewcvs links with cgit links. + * doc/xml/manual/allocator.xml: Likewise. + * doc/xml/manual/mt_allocator.xml: Likewise. + * doc/html/*: Regenerate. + +2024-06-28 Jonathan Wakely + + Backported from master: + 2024-06-27 Jonathan Wakely + + PR libstdc++/115668 + * include/bits/chrono_io.h (formatter::format): + Do not use chrono::abs. + * testsuite/20_util/duration/io.cc: Check formatting a duration + with unsigned rep. + 2024-06-27 Alexandre Oliva Backported from master: commit 5a4ea0b20c1555924b8e3ac3d695235ad2e72921 Author: GCC Administrator Date: Sun Jun 30 00:22:23 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 674b36c5c7c..e88fa6b412b 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240629 +20240630 commit 461c8462d6bab40ec9198a1ec2204ffaf555a610 Author: GCC Administrator Date: Mon Jul 1 00:23:19 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index e88fa6b412b..ff13db4fe3e 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240630 +20240701 commit 743575bfc6cfb3520047bddf969f880455d581b1 Author: Georg-Johann Lay Date: Mon Jul 1 12:31:01 2024 +0200 AVR: target/88236, target/115726 - Fix __memx code generation. PR target/88236 PR target/115726 gcc/ * config/avr/avr.md (mov) [avr_mem_memx_p]: Expand in such a way that the destination does not overlap with any hard register clobbered / used by xload8qi_A resp. xload_A. * config/avr/avr.cc (avr_out_xload): Avoid early-clobber situation for Z by executing just one load when the output register overlaps with Z. gcc/testsuite/ * gcc.target/avr/torture/pr88236-pr115726.c: New test. (cherry picked from commit 3d23abd3dd9c8c226ea302203b214b346f4fe8d7) diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc index a5c628134b4..36ad0f23162 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -4093,7 +4093,13 @@ avr_out_xload (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen) xop[2] = lpm_addr_reg_rtx; xop[3] = AVR_HAVE_LPMX ? op[0] : lpm_reg_rtx; - avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, -1); + if (plen) + *plen = 0; + + if (reg_overlap_mentioned_p (xop[3], lpm_addr_reg_rtx)) + avr_asm_len ("sbrs %1,7", xop, plen, 1); + + avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, 1); avr_asm_len ("sbrc %1,7" CR_TAB "ld %3,%a2", xop, plen, 2); diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 46f7812cea2..c8b5ccaf098 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -718,12 +718,26 @@ if (!REG_P (addr)) src = replace_equiv_address (src, copy_to_mode_reg (PSImode, addr)); + rtx dest2 = reg_overlap_mentioned_p (dest, lpm_addr_reg_rtx) + ? gen_reg_rtx (mode) + : dest; + if (!avr_xload_libgcc_p (mode)) /* ; No here because gen_xload8_A only iterates over ALL1. ; insn-emit does not depend on the mode, it's all about operands. */ - emit_insn (gen_xload8qi_A (dest, src)); + emit_insn (gen_xload8qi_A (dest2, src)); else - emit_insn (gen_xload_A (dest, src)); + { + rtx reg_22 = gen_rtx_REG (mode, 22); + if (reg_overlap_mentioned_p (dest2, reg_22) + || reg_overlap_mentioned_p (dest2, all_regs_rtx[21])) + dest2 = gen_reg_rtx (mode); + + emit_insn (gen_xload_A (dest2, src)); + } + + if (dest2 != dest) + emit_move_insn (dest, dest2); DONE; } diff --git a/gcc/testsuite/gcc.target/avr/torture/pr88236-pr115726.c b/gcc/testsuite/gcc.target/avr/torture/pr88236-pr115726.c new file mode 100644 index 00000000000..9fd5fd3b5f5 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/pr88236-pr115726.c @@ -0,0 +1,115 @@ +/* { dg-do run { target { ! avr_tiny } } } */ +/* { dg-additional-options "-std=gnu99" } */ + +const __flash char fvals8[] = { 1, 2, 3 }; +char rvals8[] = { 0, 2, 4 }; + +const __flash int fvals16[] = { 1, 2, 3 }; +int rvals16[] = { 0, 2, 4 }; + +__attribute__((noinline, noclone)) +char xload8_r30 (const __memx char *pc) +{ + register char c __asm ("r30"); + c = *pc; + __asm (";;" : "+r" (c)); + return c; +} + +__attribute__((noinline, noclone)) +int xload16_r30 (const __memx int *pc) +{ + register int c __asm ("r30"); + c = *pc; + __asm (";;" : "+r" (c)); + return c; +} + +__attribute__((noinline, noclone)) +char xload8_r22 (const __memx char *pc) +{ + register char c __asm ("r22"); + c = *pc; + __asm (";;" : "+r" (c)); + return c; +} + +__attribute__((noinline, noclone)) +int xload16_r22 (const __memx int *pc) +{ + register int c __asm ("r22"); + c = *pc; + __asm (";;" : "+r" (c)); + return c; +} + +__attribute__((noinline, noclone)) +int xload16_r20 (const __memx int *pc) +{ + register int c __asm ("r20"); + c = *pc; + __asm (";;" : "+r" (c)); + return c; +} + +void test8 (void) +{ + char c; + for (int i = 0; i < 3; ++i) + { + c = xload8_r30 (fvals8 + i); + if (c != 1 + i) + __builtin_exit (__LINE__); + + c = xload8_r22 (fvals8 + i); + if (c != 1 + i) + __builtin_exit (__LINE__); + + c = xload8_r30 (rvals8 + i); + if (c != 2 * i) + __builtin_exit (__LINE__); + + c = xload8_r22 (rvals8 + i); + if (c != 2 * i) + __builtin_exit (__LINE__); + } +} + +void test16 (void) +{ + int c; + for (int i = 0; i < 3; ++i) + { + c = xload16_r30 (fvals16 + i); + if (c != 1 + i) + __builtin_exit (__LINE__); + + c = xload16_r22 (fvals16 + i); + if (c != 1 + i) + __builtin_exit (__LINE__); + + c = xload16_r20 (fvals16 + i); + if (c != 1 + i) + __builtin_exit (__LINE__); + + c = xload16_r30 (rvals16 + i); + if (c != 2 * i) + __builtin_exit (__LINE__); + + c = xload16_r22 (rvals16 + i); + if (c != 2 * i) + __builtin_exit (__LINE__); + + c = xload16_r20 (rvals16 + i); + if (c != 2 * i) + __builtin_exit (__LINE__); + } +} + +int main (void) +{ + test8(); + test16(); + + return 0; +} commit b4abe8f7f5c3269d058b176fa00fe5c71de05c68 Author: GCC Administrator Date: Tue Jul 2 00:22:31 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f4b9b507375..b13742057d4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2024-07-01 Georg-Johann Lay + + Backported from master: + 2024-07-01 Georg-Johann Lay + + PR target/88236 + PR target/115726 + * config/avr/avr.md (mov) [avr_mem_memx_p]: Expand in such a + way that the destination does not overlap with any hard register + clobbered / used by xload8qi_A resp. xload_A. + * config/avr/avr.cc (avr_out_xload): Avoid early-clobber + situation for Z by executing just one load when the output register + overlaps with Z. + 2024-06-28 Kewen Lin Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index ff13db4fe3e..7f1fc5ab8cf 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240701 +20240702 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b7d55cf675a..35123ff00da 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2024-07-01 Georg-Johann Lay + + Backported from master: + 2024-07-01 Georg-Johann Lay + + PR target/88236 + PR target/115726 + * gcc.target/avr/torture/pr88236-pr115726.c: New test. + 2024-06-28 Kewen Lin Backported from master: commit 2dd393435b05530c0a6ef432c33ac0643c594475 Author: GCC Administrator Date: Wed Jul 3 00:23:44 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 7f1fc5ab8cf..f8fa5e4aa67 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240702 +20240703 commit ffdd377fc07cdc7b62669d354e23f30940eaaffe Author: Kewen Lin Date: Wed Jun 26 02:16:17 2024 -0500 rs6000: Fix wrong RTL patterns for vector merge high/low char on LE Commit r12-4496 changes some define_expands and define_insns for vector merge high/low char, which are altivec_vmrg[hl]b. These defines are mainly for built-in function vec_merge{h,l} and some internal gen function needs. These functions should consider endianness, taking vec_mergeh as example, as PVIPR defines, vec_mergeh "Merges the first halves (in element order) of two vectors", it does note it's in element order. So it's mapped into vmrghb on BE while vmrglb on LE respectively. Although the mapped insns are different, as the discussion in PR106069, the RTL pattern should be still the same, it is conformed before commit r12-4496, but gets changed into different patterns on BE and LE starting from commit r12-4496. Similar to 32-bit element case in commit log of r15-1504, this 8-bit element pattern on LE doesn't actually match what the underlying insn is intended to represent, once some optimization like combine does some changes basing on it, it would cause the unexpected consequence. The newly constructed test case pr106069-1.c is a typical example for this issue. So this patch is to fix the wrong RTL pattern, ensure the associated RTL patterns become the same as before which can have the same semantic as their mapped insns. With the proposed patch, the expanders like altivec_vmrghb expands into altivec_vmrghb_direct_be or altivec_vmrglb_direct_le depending on endianness, "direct" can easily show which insn would be generated, _be and _le are mainly for the different RTL patterns as endianness. Co-authored-by: Xionghu Luo PR target/106069 PR target/115355 gcc/ChangeLog: * config/rs6000/altivec.md (altivec_vmrghb_direct): Rename to ... (altivec_vmrghb_direct_be): ... this. Add condition BYTES_BIG_ENDIAN. (altivec_vmrghb_direct_le): New define_insn. (altivec_vmrglb_direct): Rename to ... (altivec_vmrglb_direct_be): ... this. Add condition BYTES_BIG_ENDIAN. (altivec_vmrglb_direct_le): New define_insn. (altivec_vmrghb): Adjust by calling gen_altivec_vmrghb_direct_be for BE and gen_altivec_vmrglb_direct_le for LE. (altivec_vmrglb): Adjust by calling gen_altivec_vmrglb_direct_be for BE and gen_altivec_vmrghb_direct_le for LE. * config/rs6000/rs6000.cc (altivec_expand_vec_perm_const): Replace CODE_FOR_altivec_vmrghb_direct by CODE_FOR_altivec_vmrghb_direct_be for BE and CODE_FOR_altivec_vmrghb_direct_le for LE. And replace CODE_FOR_altivec_vmrglb_direct by CODE_FOR_altivec_vmrglb_direct_be for BE and CODE_FOR_altivec_vmrglb_direct_le for LE. gcc/testsuite/ChangeLog: * gcc.target/powerpc/pr106069-1.c: New test. (cherry picked from commit 62520e4e9f7e2fe8a16ee57a4bd35da2e921ae22) diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md index 92e2e4a4090..47664204bc5 100644 --- a/gcc/config/rs6000/altivec.md +++ b/gcc/config/rs6000/altivec.md @@ -1152,15 +1152,16 @@ (use (match_operand:V16QI 2 "register_operand"))] "TARGET_ALTIVEC" { - rtx (*fun) (rtx, rtx, rtx) = BYTES_BIG_ENDIAN ? gen_altivec_vmrghb_direct - : gen_altivec_vmrglb_direct; - if (!BYTES_BIG_ENDIAN) - std::swap (operands[1], operands[2]); - emit_insn (fun (operands[0], operands[1], operands[2])); + if (BYTES_BIG_ENDIAN) + emit_insn ( + gen_altivec_vmrghb_direct_be (operands[0], operands[1], operands[2])); + else + emit_insn ( + gen_altivec_vmrglb_direct_le (operands[0], operands[2], operands[1])); DONE; }) -(define_insn "altivec_vmrghb_direct" +(define_insn "altivec_vmrghb_direct_be" [(set (match_operand:V16QI 0 "register_operand" "=v") (vec_select:V16QI (vec_concat:V32QI @@ -1174,7 +1175,25 @@ (const_int 5) (const_int 21) (const_int 6) (const_int 22) (const_int 7) (const_int 23)])))] - "TARGET_ALTIVEC" + "TARGET_ALTIVEC && BYTES_BIG_ENDIAN" + "vmrghb %0,%1,%2" + [(set_attr "type" "vecperm")]) + +(define_insn "altivec_vmrghb_direct_le" + [(set (match_operand:V16QI 0 "register_operand" "=v") + (vec_select:V16QI + (vec_concat:V32QI + (match_operand:V16QI 2 "register_operand" "v") + (match_operand:V16QI 1 "register_operand" "v")) + (parallel [(const_int 8) (const_int 24) + (const_int 9) (const_int 25) + (const_int 10) (const_int 26) + (const_int 11) (const_int 27) + (const_int 12) (const_int 28) + (const_int 13) (const_int 29) + (const_int 14) (const_int 30) + (const_int 15) (const_int 31)])))] + "TARGET_ALTIVEC && !BYTES_BIG_ENDIAN" "vmrghb %0,%1,%2" [(set_attr "type" "vecperm")]) @@ -1274,15 +1293,16 @@ (use (match_operand:V16QI 2 "register_operand"))] "TARGET_ALTIVEC" { - rtx (*fun) (rtx, rtx, rtx) = BYTES_BIG_ENDIAN ? gen_altivec_vmrglb_direct - : gen_altivec_vmrghb_direct; - if (!BYTES_BIG_ENDIAN) - std::swap (operands[1], operands[2]); - emit_insn (fun (operands[0], operands[1], operands[2])); + if (BYTES_BIG_ENDIAN) + emit_insn ( + gen_altivec_vmrglb_direct_be (operands[0], operands[1], operands[2])); + else + emit_insn ( + gen_altivec_vmrghb_direct_le (operands[0], operands[2], operands[1])); DONE; }) -(define_insn "altivec_vmrglb_direct" +(define_insn "altivec_vmrglb_direct_be" [(set (match_operand:V16QI 0 "register_operand" "=v") (vec_select:V16QI (vec_concat:V32QI @@ -1296,7 +1316,25 @@ (const_int 13) (const_int 29) (const_int 14) (const_int 30) (const_int 15) (const_int 31)])))] - "TARGET_ALTIVEC" + "TARGET_ALTIVEC && BYTES_BIG_ENDIAN" + "vmrglb %0,%1,%2" + [(set_attr "type" "vecperm")]) + +(define_insn "altivec_vmrglb_direct_le" + [(set (match_operand:V16QI 0 "register_operand" "=v") + (vec_select:V16QI + (vec_concat:V32QI + (match_operand:V16QI 2 "register_operand" "v") + (match_operand:V16QI 1 "register_operand" "v")) + (parallel [(const_int 0) (const_int 16) + (const_int 1) (const_int 17) + (const_int 2) (const_int 18) + (const_int 3) (const_int 19) + (const_int 4) (const_int 20) + (const_int 5) (const_int 21) + (const_int 6) (const_int 22) + (const_int 7) (const_int 23)])))] + "TARGET_ALTIVEC && !BYTES_BIG_ENDIAN" "vmrglb %0,%1,%2" [(set_attr "type" "vecperm")]) diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index b3d648312f1..10088033aa1 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -23166,8 +23166,8 @@ altivec_expand_vec_perm_const (rtx target, rtx op0, rtx op1, CODE_FOR_altivec_vpkuwum_direct, {2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31}}, {OPTION_MASK_ALTIVEC, - BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghb_direct - : CODE_FOR_altivec_vmrglb_direct, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghb_direct_be + : CODE_FOR_altivec_vmrglb_direct_le, {0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23}}, {OPTION_MASK_ALTIVEC, BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghh_direct @@ -23178,8 +23178,8 @@ altivec_expand_vec_perm_const (rtx target, rtx op0, rtx op1, : CODE_FOR_altivec_vmrglw_direct_v4si_le, {0, 1, 2, 3, 16, 17, 18, 19, 4, 5, 6, 7, 20, 21, 22, 23}}, {OPTION_MASK_ALTIVEC, - BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglb_direct - : CODE_FOR_altivec_vmrghb_direct, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglb_direct_be + : CODE_FOR_altivec_vmrghb_direct_le, {8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31}}, {OPTION_MASK_ALTIVEC, BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglh_direct diff --git a/gcc/testsuite/gcc.target/powerpc/pr106069-1.c b/gcc/testsuite/gcc.target/powerpc/pr106069-1.c new file mode 100644 index 00000000000..4945d8fedfb --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr106069-1.c @@ -0,0 +1,39 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target vmx_hw } */ + +/* Test vector merge for 8-bit element size, + it will abort if the RTL pattern isn't expected. */ + +#include "altivec.h" + +__attribute__((noipa)) +signed char elem_6 (vector signed char a, vector signed char b) +{ + vector signed char c = vec_mergeh (a,b); + return vec_extract (c, 6); +} + +__attribute__((noipa)) +unsigned char elem_15 (vector unsigned char a, vector unsigned char b) +{ + vector unsigned char c = vec_mergel (a,b); + return vec_extract (c, 15); +} + +int +main () +{ + vector unsigned char v1 + = {3, 33, 22, 12, 34, 14, 5, 25, 30, 11, 0, 21, 17, 27, 38, 8}; + vector unsigned char v2 + = {81, 82, 83, 84, 68, 67, 66, 65, 99, 100, 101, 102, 250, 125, 0, 6}; + signed char x1 = elem_6 ((vector signed char) v1, (vector signed char) v2); + unsigned char x2 = elem_15 (v1, v2); + + if (x1 != 12 || x2 != 6) + __builtin_abort (); + + return 0; +} + commit bab38d9271ce3f26cb64b8cb712351eb3fedd559 Author: Kewen Lin Date: Wed Jun 26 02:16:17 2024 -0500 rs6000: Fix wrong RTL patterns for vector merge high/low short on LE Commit r12-4496 changes some define_expands and define_insns for vector merge high/low short, which are altivec_vmrg[hl]h. These defines are mainly for built-in function vec_merge{h,l} and some internal gen function needs. These functions should consider endianness, taking vec_mergeh as example, as PVIPR defines, vec_mergeh "Merges the first halves (in element order) of two vectors", it does note it's in element order. So it's mapped into vmrghh on BE while vmrglh on LE respectively. Although the mapped insns are different, as the discussion in PR106069, the RTL pattern should be still the same, it is conformed before commit r12-4496, but gets changed into different patterns on BE and LE starting from commit r12-4496. Similar to 32-bit element case in commit log of r15-1504, this 16-bit element pattern on LE doesn't actually match what the underlying insn is intended to represent, once some optimization like combine does some changes basing on it, it would cause the unexpected consequence. The newly constructed test case pr106069-2.c is a typical example for this issue on element type short. So this patch is to fix the wrong RTL pattern, ensure the associated RTL patterns become the same as before which can have the same semantic as their mapped insns. With the proposed patch, the expanders like altivec_vmrghh expands into altivec_vmrghh_direct_be or altivec_vmrglh_direct_le depending on endianness, "direct" can easily show which insn would be generated, _be and _le are mainly for the different RTL patterns as endianness. Co-authored-by: Xionghu Luo PR target/106069 PR target/115355 gcc/ChangeLog: * config/rs6000/altivec.md (altivec_vmrghh_direct): Rename to ... (altivec_vmrghh_direct_be): ... this. Add condition BYTES_BIG_ENDIAN. (altivec_vmrghh_direct_le): New define_insn. (altivec_vmrglh_direct): Rename to ... (altivec_vmrglh_direct_be): ... this. Add condition BYTES_BIG_ENDIAN. (altivec_vmrglh_direct_le): New define_insn. (altivec_vmrghh): Adjust by calling gen_altivec_vmrghh_direct_be for BE and gen_altivec_vmrglh_direct_le for LE. (altivec_vmrglh): Adjust by calling gen_altivec_vmrglh_direct_be for BE and gen_altivec_vmrghh_direct_le for LE. (vec_widen_umult_hi_v16qi): Adjust the call to gen_altivec_vmrghh_direct by gen_altivec_vmrghh for BE and by gen_altivec_vmrglh for LE. (vec_widen_smult_hi_v16qi): Likewise. (vec_widen_umult_lo_v16qi): Adjust the call to gen_altivec_vmrglh_direct by gen_altivec_vmrglh for BE and by gen_altivec_vmrghh for LE. (vec_widen_smult_lo_v16qi): Likewise. * config/rs6000/rs6000.cc (altivec_expand_vec_perm_const): Replace CODE_FOR_altivec_vmrghh_direct by CODE_FOR_altivec_vmrghh_direct_be for BE and CODE_FOR_altivec_vmrghh_direct_le for LE. And replace CODE_FOR_altivec_vmrglh_direct by CODE_FOR_altivec_vmrglh_direct_be for BE and CODE_FOR_altivec_vmrglh_direct_le for LE. gcc/testsuite/ChangeLog: * gcc.target/powerpc/pr106069-2.c: New test. (cherry picked from commit 812c70bf4981958488331d4ea5af8709b5321da1) diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md index 47664204bc5..6557393a97c 100644 --- a/gcc/config/rs6000/altivec.md +++ b/gcc/config/rs6000/altivec.md @@ -1203,17 +1203,18 @@ (use (match_operand:V8HI 2 "register_operand"))] "TARGET_ALTIVEC" { - rtx (*fun) (rtx, rtx, rtx) = BYTES_BIG_ENDIAN ? gen_altivec_vmrghh_direct - : gen_altivec_vmrglh_direct; - if (!BYTES_BIG_ENDIAN) - std::swap (operands[1], operands[2]); - emit_insn (fun (operands[0], operands[1], operands[2])); + if (BYTES_BIG_ENDIAN) + emit_insn ( + gen_altivec_vmrghh_direct_be (operands[0], operands[1], operands[2])); + else + emit_insn ( + gen_altivec_vmrglh_direct_le (operands[0], operands[2], operands[1])); DONE; }) -(define_insn "altivec_vmrghh_direct" +(define_insn "altivec_vmrghh_direct_be" [(set (match_operand:V8HI 0 "register_operand" "=v") - (vec_select:V8HI + (vec_select:V8HI (vec_concat:V16HI (match_operand:V8HI 1 "register_operand" "v") (match_operand:V8HI 2 "register_operand" "v")) @@ -1221,7 +1222,21 @@ (const_int 1) (const_int 9) (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))] - "TARGET_ALTIVEC" + "TARGET_ALTIVEC && BYTES_BIG_ENDIAN" + "vmrghh %0,%1,%2" + [(set_attr "type" "vecperm")]) + +(define_insn "altivec_vmrghh_direct_le" + [(set (match_operand:V8HI 0 "register_operand" "=v") + (vec_select:V8HI + (vec_concat:V16HI + (match_operand:V8HI 2 "register_operand" "v") + (match_operand:V8HI 1 "register_operand" "v")) + (parallel [(const_int 4) (const_int 12) + (const_int 5) (const_int 13) + (const_int 6) (const_int 14) + (const_int 7) (const_int 15)])))] + "TARGET_ALTIVEC && !BYTES_BIG_ENDIAN" "vmrghh %0,%1,%2" [(set_attr "type" "vecperm")]) @@ -1344,15 +1359,16 @@ (use (match_operand:V8HI 2 "register_operand"))] "TARGET_ALTIVEC" { - rtx (*fun) (rtx, rtx, rtx) = BYTES_BIG_ENDIAN ? gen_altivec_vmrglh_direct - : gen_altivec_vmrghh_direct; - if (!BYTES_BIG_ENDIAN) - std::swap (operands[1], operands[2]); - emit_insn (fun (operands[0], operands[1], operands[2])); + if (BYTES_BIG_ENDIAN) + emit_insn ( + gen_altivec_vmrglh_direct_be (operands[0], operands[1], operands[2])); + else + emit_insn ( + gen_altivec_vmrghh_direct_le (operands[0], operands[2], operands[1])); DONE; }) -(define_insn "altivec_vmrglh_direct" +(define_insn "altivec_vmrglh_direct_be" [(set (match_operand:V8HI 0 "register_operand" "=v") (vec_select:V8HI (vec_concat:V16HI @@ -1362,7 +1378,21 @@ (const_int 5) (const_int 13) (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))] - "TARGET_ALTIVEC" + "TARGET_ALTIVEC && BYTES_BIG_ENDIAN" + "vmrglh %0,%1,%2" + [(set_attr "type" "vecperm")]) + +(define_insn "altivec_vmrglh_direct_le" + [(set (match_operand:V8HI 0 "register_operand" "=v") + (vec_select:V8HI + (vec_concat:V16HI + (match_operand:V8HI 2 "register_operand" "v") + (match_operand:V8HI 1 "register_operand" "v")) + (parallel [(const_int 0) (const_int 8) + (const_int 1) (const_int 9) + (const_int 2) (const_int 10) + (const_int 3) (const_int 11)])))] + "TARGET_ALTIVEC && !BYTES_BIG_ENDIAN" "vmrglh %0,%1,%2" [(set_attr "type" "vecperm")]) @@ -3777,13 +3807,13 @@ { emit_insn (gen_altivec_vmuleub (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmuloub (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrghh_direct (operands[0], ve, vo)); + emit_insn (gen_altivec_vmrghh (operands[0], ve, vo)); } else { emit_insn (gen_altivec_vmuloub (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmuleub (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrghh_direct (operands[0], vo, ve)); + emit_insn (gen_altivec_vmrglh (operands[0], ve, vo)); } DONE; }) @@ -3802,13 +3832,13 @@ { emit_insn (gen_altivec_vmuleub (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmuloub (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrglh_direct (operands[0], ve, vo)); + emit_insn (gen_altivec_vmrglh (operands[0], ve, vo)); } else { emit_insn (gen_altivec_vmuloub (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmuleub (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrglh_direct (operands[0], vo, ve)); + emit_insn (gen_altivec_vmrghh (operands[0], ve, vo)); } DONE; }) @@ -3827,13 +3857,13 @@ { emit_insn (gen_altivec_vmulesb (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmulosb (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrghh_direct (operands[0], ve, vo)); + emit_insn (gen_altivec_vmrghh (operands[0], ve, vo)); } else { emit_insn (gen_altivec_vmulosb (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmulesb (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrghh_direct (operands[0], vo, ve)); + emit_insn (gen_altivec_vmrglh (operands[0], ve, vo)); } DONE; }) @@ -3852,13 +3882,13 @@ { emit_insn (gen_altivec_vmulesb (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmulosb (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrglh_direct (operands[0], ve, vo)); + emit_insn (gen_altivec_vmrglh (operands[0], ve, vo)); } else { emit_insn (gen_altivec_vmulosb (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmulesb (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrglh_direct (operands[0], vo, ve)); + emit_insn (gen_altivec_vmrghh (operands[0], ve, vo)); } DONE; }) diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index 10088033aa1..76eb89ad529 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -23170,8 +23170,8 @@ altivec_expand_vec_perm_const (rtx target, rtx op0, rtx op1, : CODE_FOR_altivec_vmrglb_direct_le, {0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23}}, {OPTION_MASK_ALTIVEC, - BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghh_direct - : CODE_FOR_altivec_vmrglh_direct, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghh_direct_be + : CODE_FOR_altivec_vmrglh_direct_le, {0, 1, 16, 17, 2, 3, 18, 19, 4, 5, 20, 21, 6, 7, 22, 23}}, {OPTION_MASK_ALTIVEC, BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghw_direct_v4si_be @@ -23182,8 +23182,8 @@ altivec_expand_vec_perm_const (rtx target, rtx op0, rtx op1, : CODE_FOR_altivec_vmrghb_direct_le, {8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31}}, {OPTION_MASK_ALTIVEC, - BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglh_direct - : CODE_FOR_altivec_vmrghh_direct, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglh_direct_be + : CODE_FOR_altivec_vmrghh_direct_le, {8, 9, 24, 25, 10, 11, 26, 27, 12, 13, 28, 29, 14, 15, 30, 31}}, {OPTION_MASK_ALTIVEC, BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglw_direct_v4si_be diff --git a/gcc/testsuite/gcc.target/powerpc/pr106069-2.c b/gcc/testsuite/gcc.target/powerpc/pr106069-2.c new file mode 100644 index 00000000000..283e3290fb3 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr106069-2.c @@ -0,0 +1,37 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target vmx_hw } */ + +/* Test vector merge for 16-bit element size, + it will abort if the RTL pattern isn't expected. */ + +#include "altivec.h" + +__attribute__((noipa)) +signed short elem_2 (vector signed short a, vector signed short b) +{ + vector signed short c = vec_mergeh (a,b); + return vec_extract (c, 2); +} + +__attribute__((noipa)) +unsigned short elem_7 (vector unsigned short a, vector unsigned short b) +{ + vector unsigned short c = vec_mergel (a,b); + return vec_extract (c, 7); +} + +int +main () +{ + vector unsigned short v1 = {3, 22, 12, 34, 5, 25, 30, 11}; + vector unsigned short v2 = {84, 168, 267, 966, 65, 399, 999, 99}; + signed short x1 = elem_2 ((vector signed short) v1, (vector signed short) v2); + unsigned short x2 = elem_7 (v1, v2); + + if (x1 != 22 || x2 != 99) + __builtin_abort (); + + return 0; +} + commit ba9fef4bdea000032ca5c121a1baba02450faf2b Author: Georg-Johann Lay Date: Wed Jul 3 10:29:18 2024 +0200 AVR: target/98762 - Handle partial clobber in movqi output. PR target/98762 gcc/ * config/avr/avr.cc (avr_out_movqi_r_mr_reg_disp_tiny): Properly restore the base register when it is partially clobbered. gcc/testsuite/ * gcc.target/avr/torture/pr98762.c: New test. (cherry picked from commit e9fb6efa1cf542353fd44ddcbb5136344c463fd0) diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc index 36ad0f23162..676ab2405db 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -4245,13 +4245,30 @@ avr_out_movqi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen) rtx dest = op[0]; rtx src = op[1]; rtx x = XEXP (src, 0); + rtx base = XEXP (x, 0); - avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB - "ld %0,%b1" , op, plen, -3); + if (plen) + *plen = 0; - if (!reg_overlap_mentioned_p (dest, XEXP (x, 0)) - && !reg_unused_after (insn, XEXP (x, 0))) - avr_asm_len (TINY_SBIW (%I1, %J1, %o1), op, plen, 2); + if (!reg_overlap_mentioned_p (dest, base)) + { + avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB + "ld %0,%b1", op, plen, 3); + if (!reg_unused_after (insn, base)) + avr_asm_len (TINY_SBIW (%I1, %J1, %o1), op, plen, 2); + } + else + { + // PR98762: The base register overlaps dest and is only partly clobbered. + rtx base2 = all_regs_rtx[1 ^ REGNO (dest)]; + + if (!reg_unused_after (insn, base2)) + avr_asm_len ("mov __tmp_reg__,%0" , &base2, plen, 1); + avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB + "ld %0,%b1", op, plen, 3); + if (!reg_unused_after (insn, base2)) + avr_asm_len ("mov %0,__tmp_reg__" , &base2, plen, 1); + } return ""; } diff --git a/gcc/testsuite/gcc.target/avr/torture/pr98762.c b/gcc/testsuite/gcc.target/avr/torture/pr98762.c new file mode 100644 index 00000000000..c3ba7da69a8 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/pr98762.c @@ -0,0 +1,19 @@ +/* { dg-do run } */ +/* { dg-additional-options "-std=c99" } */ + +long long acc = 0x1122334455667788; + +__attribute__((noinline,noclone)) +void addhi (short a) +{ + acc += (long long) a << 32; +} + +int main (void) +{ + addhi (0x0304); + if (acc != 0x1122364855667788) + __builtin_abort(); + + return 0; +} commit ecd6ebe5fb0151f9649705a5798325032bbc811a Author: John David Anglin Date: Sun Jun 30 09:48:21 2024 -0400 hppa: Fix ICE caused by mismatched predicate and constraint in xmpyu patterns 2024-06-30 John David Anglin gcc/ChangeLog: PR target/115691 * config/pa/pa.md: Remove incorrect xmpyu patterns. diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md index 36d20576102..d832a29683c 100644 --- a/gcc/config/pa/pa.md +++ b/gcc/config/pa/pa.md @@ -5493,24 +5493,6 @@ [(set_attr "type" "fpmuldbl") (set_attr "length" "4")]) -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=f") - (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "f")) - (match_operand:DI 2 "uint32_operand" "f")))] - "TARGET_PA_11 && ! TARGET_SOFT_FLOAT && ! TARGET_SOFT_MULT && !TARGET_64BIT" - "xmpyu %1,%R2,%0" - [(set_attr "type" "fpmuldbl") - (set_attr "length" "4")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=f") - (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "f")) - (match_operand:DI 2 "uint32_operand" "f")))] - "TARGET_PA_11 && ! TARGET_SOFT_FLOAT && ! TARGET_SOFT_MULT && TARGET_64BIT" - "xmpyu %1,%2R,%0" - [(set_attr "type" "fpmuldbl") - (set_attr "length" "4")]) - (define_insn "" [(set (reg:SI 29) (mult:SI (reg:SI 26) (reg:SI 25))) (clobber (match_operand:SI 0 "register_operand" "=a")) commit a26c560d3f679d5237dd5191869e845740b94759 Author: GCC Administrator Date: Thu Jul 4 00:23:04 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b13742057d4..7226adb8c45 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,77 @@ +2024-07-03 John David Anglin + + PR target/115691 + * config/pa/pa.md: Remove incorrect xmpyu patterns. + +2024-07-03 Georg-Johann Lay + + Backported from master: + 2024-07-03 Georg-Johann Lay + + PR target/98762 + * config/avr/avr.cc (avr_out_movqi_r_mr_reg_disp_tiny): Properly + restore the base register when it is partially clobbered. + +2024-07-03 Kewen Lin + + Backported from master: + 2024-06-26 Kewen Lin + Xionghu Luo + + PR target/106069 + PR target/115355 + * config/rs6000/altivec.md (altivec_vmrghh_direct): Rename to ... + (altivec_vmrghh_direct_be): ... this. Add condition BYTES_BIG_ENDIAN. + (altivec_vmrghh_direct_le): New define_insn. + (altivec_vmrglh_direct): Rename to ... + (altivec_vmrglh_direct_be): ... this. Add condition BYTES_BIG_ENDIAN. + (altivec_vmrglh_direct_le): New define_insn. + (altivec_vmrghh): Adjust by calling gen_altivec_vmrghh_direct_be + for BE and gen_altivec_vmrglh_direct_le for LE. + (altivec_vmrglh): Adjust by calling gen_altivec_vmrglh_direct_be + for BE and gen_altivec_vmrghh_direct_le for LE. + (vec_widen_umult_hi_v16qi): Adjust the call to + gen_altivec_vmrghh_direct by gen_altivec_vmrghh for BE + and by gen_altivec_vmrglh for LE. + (vec_widen_smult_hi_v16qi): Likewise. + (vec_widen_umult_lo_v16qi): Adjust the call to + gen_altivec_vmrglh_direct by gen_altivec_vmrglh for BE + and by gen_altivec_vmrghh for LE. + (vec_widen_smult_lo_v16qi): Likewise. + * config/rs6000/rs6000.cc (altivec_expand_vec_perm_const): Replace + CODE_FOR_altivec_vmrghh_direct by + CODE_FOR_altivec_vmrghh_direct_be for BE and + CODE_FOR_altivec_vmrghh_direct_le for LE. And replace + CODE_FOR_altivec_vmrglh_direct by + CODE_FOR_altivec_vmrglh_direct_be for BE and + CODE_FOR_altivec_vmrglh_direct_le for LE. + +2024-07-03 Kewen Lin + + Backported from master: + 2024-06-26 Kewen Lin + Xionghu Luo + + PR target/106069 + PR target/115355 + * config/rs6000/altivec.md (altivec_vmrghb_direct): Rename to ... + (altivec_vmrghb_direct_be): ... this. Add condition BYTES_BIG_ENDIAN. + (altivec_vmrghb_direct_le): New define_insn. + (altivec_vmrglb_direct): Rename to ... + (altivec_vmrglb_direct_be): ... this. Add condition BYTES_BIG_ENDIAN. + (altivec_vmrglb_direct_le): New define_insn. + (altivec_vmrghb): Adjust by calling gen_altivec_vmrghb_direct_be + for BE and gen_altivec_vmrglb_direct_le for LE. + (altivec_vmrglb): Adjust by calling gen_altivec_vmrglb_direct_be + for BE and gen_altivec_vmrghb_direct_le for LE. + * config/rs6000/rs6000.cc (altivec_expand_vec_perm_const): Replace + CODE_FOR_altivec_vmrghb_direct by + CODE_FOR_altivec_vmrghb_direct_be for BE and + CODE_FOR_altivec_vmrghb_direct_le for LE. And replace + CODE_FOR_altivec_vmrglb_direct by + CODE_FOR_altivec_vmrglb_direct_be for BE and + CODE_FOR_altivec_vmrglb_direct_le for LE. + 2024-07-01 Georg-Johann Lay Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index f8fa5e4aa67..efaf824b8cd 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240703 +20240704 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 35123ff00da..165ee066569 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,31 @@ +2024-07-03 Georg-Johann Lay + + Backported from master: + 2024-07-03 Georg-Johann Lay + + PR target/98762 + * gcc.target/avr/torture/pr98762.c: New test. + +2024-07-03 Kewen Lin + + Backported from master: + 2024-06-26 Kewen Lin + Xionghu Luo + + PR target/106069 + PR target/115355 + * gcc.target/powerpc/pr106069-2.c: New test. + +2024-07-03 Kewen Lin + + Backported from master: + 2024-06-26 Kewen Lin + Xionghu Luo + + PR target/106069 + PR target/115355 + * gcc.target/powerpc/pr106069-1.c: New test. + 2024-07-01 Georg-Johann Lay Backported from master: commit 7785289f8d1f6350a3f48232ce578009b0e23534 Author: Kyrylo Tkachov Date: Thu Jun 27 16:10:41 2024 +0530 aarch64: PR target/115457 Implement missing __ARM_FEATURE_BF16 macro The ACLE asks the user to test for __ARM_FEATURE_BF16 before using the header but GCC doesn't set this up. LLVM does, so this is an inconsistency between the compilers. This patch enables that macro for TARGET_BF16_FP. Bootstrapped and tested on aarch64-none-linux-gnu. gcc/ PR target/115457 * config/aarch64/aarch64-c.cc (aarch64_update_cpp_builtins): Define __ARM_FEATURE_BF16 for TARGET_BF16_FP. gcc/testsuite/ PR target/115457 * gcc.target/aarch64/acle/bf16_feature.c: New test. Signed-off-by: Kyrylo Tkachov (cherry picked from commit c10942134fa759843ac1ed1424b86fcb8e6368ba) diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc index 6c5331a7625..51709d6044e 100644 --- a/gcc/config/aarch64/aarch64-c.cc +++ b/gcc/config/aarch64/aarch64-c.cc @@ -202,6 +202,8 @@ aarch64_update_cpp_builtins (cpp_reader *pfile) "__ARM_FEATURE_BF16_VECTOR_ARITHMETIC", pfile); aarch64_def_or_undef (TARGET_BF16_FP, "__ARM_FEATURE_BF16_SCALAR_ARITHMETIC", pfile); + aarch64_def_or_undef (TARGET_BF16_FP, + "__ARM_FEATURE_BF16", pfile); aarch64_def_or_undef (TARGET_LS64, "__ARM_FEATURE_LS64", pfile); aarch64_def_or_undef (AARCH64_ISA_RCPC, "__ARM_FEATURE_RCPC", pfile); diff --git a/gcc/testsuite/gcc.target/aarch64/acle/bf16_feature.c b/gcc/testsuite/gcc.target/aarch64/acle/bf16_feature.c new file mode 100644 index 00000000000..96584b4b988 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/bf16_feature.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ + +#pragma GCC target "+bf16" +#ifndef __ARM_FEATURE_BF16 +#error "__ARM_FEATURE_BF16 is not defined but should be!" +#endif + +void +foo (void) {} + commit 40d54856c1189ab6125d3eeb064df25082dd0e50 Author: Kyrylo Tkachov Date: Fri Jun 28 13:22:37 2024 +0530 aarch64: PR target/115475 Implement missing __ARM_FEATURE_SVE_BF16 macro The ACLE requires __ARM_FEATURE_SVE_BF16 to be enabled when SVE and BF16 and the associated intrinsics are available. GCC does support the required intrinsics for TARGET_SVE_BF16 so define this macro too. Bootstrapped and tested on aarch64-none-linux-gnu. gcc/ PR target/115475 * config/aarch64/aarch64-c.cc (aarch64_update_cpp_builtins): Define __ARM_FEATURE_SVE_BF16 for TARGET_SVE_BF16. gcc/testsuite/ PR target/115475 * gcc.target/aarch64/acle/bf16_sve_feature.c: New test. Signed-off-by: Kyrylo Tkachov (cherry picked from commit 6492c7130d6ae9992298fc3d072e2589d1131376) diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc index 51709d6044e..6ddfcc7ce3e 100644 --- a/gcc/config/aarch64/aarch64-c.cc +++ b/gcc/config/aarch64/aarch64-c.cc @@ -204,6 +204,9 @@ aarch64_update_cpp_builtins (cpp_reader *pfile) "__ARM_FEATURE_BF16_SCALAR_ARITHMETIC", pfile); aarch64_def_or_undef (TARGET_BF16_FP, "__ARM_FEATURE_BF16", pfile); + aarch64_def_or_undef (TARGET_SVE_BF16, + "__ARM_FEATURE_SVE_BF16", pfile); + aarch64_def_or_undef (TARGET_LS64, "__ARM_FEATURE_LS64", pfile); aarch64_def_or_undef (AARCH64_ISA_RCPC, "__ARM_FEATURE_RCPC", pfile); diff --git a/gcc/testsuite/gcc.target/aarch64/acle/bf16_sve_feature.c b/gcc/testsuite/gcc.target/aarch64/acle/bf16_sve_feature.c new file mode 100644 index 00000000000..cb3ddac71a3 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/bf16_sve_feature.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ + +#pragma GCC target "+sve+bf16" +#ifndef __ARM_FEATURE_SVE_BF16 +#error "__ARM_FEATURE_SVE_BF16 is not defined but should be!" +#endif + +void +foo (void) {} + commit ad2bf890b1edad25b0ccce706ddf73fb78d90bfc Author: GCC Administrator Date: Fri Jul 5 00:22:14 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7226adb8c45..b635235eab8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2024-07-04 Kyrylo Tkachov + + Backported from master: + 2024-07-03 Kyrylo Tkachov + + PR target/115475 + * config/aarch64/aarch64-c.cc (aarch64_update_cpp_builtins): + Define __ARM_FEATURE_SVE_BF16 for TARGET_SVE_BF16. + +2024-07-04 Kyrylo Tkachov + + Backported from master: + 2024-07-03 Kyrylo Tkachov + + PR target/115457 + * config/aarch64/aarch64-c.cc (aarch64_update_cpp_builtins): + Define __ARM_FEATURE_BF16 for TARGET_BF16_FP. + 2024-07-03 John David Anglin PR target/115691 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index efaf824b8cd..90cf77743f7 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240704 +20240705 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 165ee066569..89de3f12d5c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,19 @@ +2024-07-04 Kyrylo Tkachov + + Backported from master: + 2024-07-03 Kyrylo Tkachov + + PR target/115475 + * gcc.target/aarch64/acle/bf16_sve_feature.c: New test. + +2024-07-04 Kyrylo Tkachov + + Backported from master: + 2024-07-03 Kyrylo Tkachov + + PR target/115457 + * gcc.target/aarch64/acle/bf16_feature.c: New test. + 2024-07-03 Georg-Johann Lay Backported from master: commit 4a49d212b54ab152737e3209b7f80af3a80966b8 Author: Georg-Johann Lay Date: Fri Jul 5 13:22:12 2024 +0200 AVR: target/87376 - Use nop_general_operand for DImode inputs. The avr-dimode.md expanders have code like emit_move_insn(acc_a, operands[1]) where acc_a is a hard register and operands[1] might be a non-generic address-space memory reference. Such loads may clobber hard regs since some of them are implemented as libgcc calls /and/ 64-moves are expanded as eight byte-moves, so that acc_a or acc_b might be clobbered by such a load. This patch simply denies non-generic address-space references by using nop_general_operand for all avr-dimode.md input predicates. With the patch, all memory loads that require library calls are issued before the expander codes from avr-dimode.md are run. PR target/87376 gcc/ * config/avr/avr-dimode.md: Use "nop_general_operand" instead of "general_operand" as predicate for all input operands. gcc/testsuite/ * gcc.target/avr/torture/pr87376.c: New test. (cherry picked from commit 23a0935262d6817097406578b1c70563f424804b) diff --git a/gcc/config/avr/avr-dimode.md b/gcc/config/avr/avr-dimode.md index 91f0d395761..ba444be1b33 100644 --- a/gcc/config/avr/avr-dimode.md +++ b/gcc/config/avr/avr-dimode.md @@ -62,8 +62,8 @@ ;; "addta3" "adduta3" (define_expand "add3" [(parallel [(match_operand:ALL8 0 "general_operand" "") - (match_operand:ALL8 1 "general_operand" "") - (match_operand:ALL8 2 "general_operand" "")])] + (match_operand:ALL8 1 "nop_general_operand") + (match_operand:ALL8 2 "nop_general_operand")])] "avr_have_dimode" { rtx acc_a = gen_rtx_REG (mode, ACC_A); @@ -178,8 +178,8 @@ ;; "subta3" "subuta3" (define_expand "sub3" [(parallel [(match_operand:ALL8 0 "general_operand" "") - (match_operand:ALL8 1 "general_operand" "") - (match_operand:ALL8 2 "general_operand" "")])] + (match_operand:ALL8 1 "nop_general_operand") + (match_operand:ALL8 2 "nop_general_operand")])] "avr_have_dimode" { rtx acc_a = gen_rtx_REG (mode, ACC_A); @@ -259,8 +259,8 @@ (define_expand "3" [(set (match_operand:ALL8S 0 "general_operand" "") - (ss_addsub:ALL8S (match_operand:ALL8S 1 "general_operand" "") - (match_operand:ALL8S 2 "general_operand" "")))] + (ss_addsub:ALL8S (match_operand:ALL8S 1 "nop_general_operand") + (match_operand:ALL8S 2 "nop_general_operand")))] "avr_have_dimode" { rtx acc_a = gen_rtx_REG (mode, ACC_A); @@ -332,8 +332,8 @@ (define_expand "3" [(set (match_operand:ALL8U 0 "general_operand" "") - (us_addsub:ALL8U (match_operand:ALL8U 1 "general_operand" "") - (match_operand:ALL8U 2 "general_operand" "")))] + (us_addsub:ALL8U (match_operand:ALL8U 1 "nop_general_operand") + (match_operand:ALL8U 2 "nop_general_operand")))] "avr_have_dimode" { rtx acc_a = gen_rtx_REG (mode, ACC_A); @@ -405,7 +405,7 @@ (define_expand "negdi2" [(parallel [(match_operand:DI 0 "general_operand" "") - (match_operand:DI 1 "general_operand" "")])] + (match_operand:DI 1 "nop_general_operand")])] "avr_have_dimode" { rtx acc_a = gen_rtx_REG (DImode, ACC_A); @@ -602,8 +602,8 @@ ;; "ashluta3" "ashruta3" "lshruta3" "rotluta3" (define_expand "3" [(parallel [(match_operand:ALL8 0 "general_operand" "") - (di_shifts:ALL8 (match_operand:ALL8 1 "general_operand" "") - (match_operand:QI 2 "general_operand" ""))])] + (di_shifts:ALL8 (match_operand:ALL8 1 "nop_general_operand") + (match_operand:QI 2 "nop_general_operand"))])] "avr_have_dimode" { rtx acc_a = gen_rtx_REG (mode, ACC_A); @@ -648,8 +648,8 @@ ;; "mulsidi3" (define_expand "mulsidi3" [(parallel [(match_operand:DI 0 "register_operand" "") - (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" "") + (match_operand:SI 1 "nop_general_operand") + (match_operand:SI 2 "nop_general_operand") ;; Just to mention the iterator (clobber (any_extend:SI (match_dup 1)))])] "avr_have_dimode diff --git a/gcc/testsuite/gcc.target/avr/torture/pr87376.c b/gcc/testsuite/gcc.target/avr/torture/pr87376.c new file mode 100644 index 00000000000..c31a4a9dda5 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/pr87376.c @@ -0,0 +1,60 @@ +/* { dg-do run { target { ! avr_tiny } } } */ +/* { dg-additional-options "-std=gnu99" } */ + +typedef __UINT64_TYPE__ uint64_t; + +extern const __memx uint64_t aa __asm ("real_aa"); +extern const uint64_t bb __asm ("real_bb"); + +const __memx uint64_t real_aa = 0x1122334455667788; +const uint64_t real_bb = 0x0908070605040302; + +__attribute__((noinline,noclone)) +uint64_t add1 (void) +{ + return aa + bb; +} + +__attribute__((noinline,noclone)) +uint64_t add2 (void) +{ + return bb + aa; +} + +__attribute__((noinline,noclone)) +uint64_t sub1 (void) +{ + return aa - bb; +} + +__attribute__((noinline,noclone)) +uint64_t sub2 (void) +{ + return bb - aa; +} + +__attribute__((noinline,noclone)) +uint64_t neg1 (void) +{ + return -aa; +} + +int main (void) +{ + if (neg1() != -real_aa) + __builtin_exit (__LINE__); + + if (add1() != real_aa + real_bb) + __builtin_exit (__LINE__); + + if (add2() != real_bb + real_aa) + __builtin_exit (__LINE__); + + if (sub1() != real_aa - real_bb) + __builtin_exit (__LINE__); + + if (sub2() != real_bb - real_aa) + __builtin_exit (__LINE__); + + return 0; +} commit 1fd7caa0af4869c38698abdf73fe9f51d7dd823b Author: GCC Administrator Date: Sat Jul 6 00:22:18 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b635235eab8..a035c36e80e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2024-07-05 Georg-Johann Lay + + Backported from master: + 2024-07-05 Georg-Johann Lay + + PR target/87376 + * config/avr/avr-dimode.md: Use "nop_general_operand" instead + of "general_operand" as predicate for all input operands. + 2024-07-04 Kyrylo Tkachov Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 90cf77743f7..d97996cc287 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240705 +20240706 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 89de3f12d5c..b35264c40d8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2024-07-05 Georg-Johann Lay + + Backported from master: + 2024-07-05 Georg-Johann Lay + + PR target/87376 + * gcc.target/avr/torture/pr87376.c: New test. + 2024-07-04 Kyrylo Tkachov Backported from master: commit f1b4d48d6254956a4dd1c9939437074c59596064 Author: GCC Administrator Date: Sun Jul 7 00:21:43 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index d97996cc287..391dc0be055 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240706 +20240707 commit ed36bd1855298e46f827c484bcd0fe8783a34a3a Author: GCC Administrator Date: Mon Jul 8 00:21:41 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 391dc0be055..d50aabd12dd 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240707 +20240708 commit b1429ddd7f20a5c88b65d8de38d64c98c4820782 Author: Paul Thomas Date: Sun May 12 06:59:45 2024 +0100 Fortran: Unlimited polymorphic intrinsic function arguments [PR84006] 2024-05-12 Paul Thomas gcc/fortran PR fortran/84006 PR fortran/100027 PR fortran/98534 * iresolve.cc (gfc_resolve_transfer): Emit a TODO error for unlimited polymorphic mold. * trans-expr.cc (gfc_resize_class_size_with_len): Use the fold even if a block is not available in which to fix the result. (trans_class_assignment): Enable correct assignment of character expressions to unlimited polymorphic variables using lhs _len field and rse string_length. * trans-intrinsic.cc (gfc_conv_intrinsic_storage_size): Extract the class expression so that the unlimited polymorphic class expression can be used in gfc_resize_class_size_with_len to obtain the storage size for character payloads. Guard the use of GFC_DECL_SAVED_DESCRIPTOR by testing for DECL_LANG_SPECIFIC to prevent the ICE. Also, invert the order to use the class expression extracted from the argument. (gfc_conv_intrinsic_transfer): In same way as 'storage_size', use the _len field to obtaining the correct length for arg 1. Add a branch for the element size in bytes of class expressions with provision to make use of the unlimited polymorphic _len field. Again, the class references are explicitly identified. 'mold_expr' was already declared. Use it instead of 'arg'. Do not fix 'dest_word_len' for deferred character sources because reallocation on assign makes use of it before it is assigned. gcc/testsuite/ PR fortran/84006 PR fortran/100027 * gfortran.dg/storage_size_7.f90: New test. PR fortran/98534 * gfortran.dg/transfer_class_4.f90: New test. (cherry picked from commit b9294757f82aae8de6d98c122cd4e3b98f685217) diff --git a/gcc/fortran/iresolve.cc b/gcc/fortran/iresolve.cc index 8acad60a02b..108c9a35949 100644 --- a/gcc/fortran/iresolve.cc +++ b/gcc/fortran/iresolve.cc @@ -3017,6 +3017,10 @@ gfc_resolve_transfer (gfc_expr *f, gfc_expr *source ATTRIBUTE_UNUSED, } } + if (UNLIMITED_POLY (mold)) + gfc_error ("TODO: unlimited polymorphic MOLD in TRANSFER intrinsic at %L", + &mold->where); + f->ts = mold->ts; if (size == NULL && mold->rank == 0) diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index 5946aa81391..6b75c147a35 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -317,6 +317,8 @@ gfc_resize_class_size_with_len (stmtblock_t * block, tree class_expr, tree size) size = gfc_evaluate_now (size, block); tmp = gfc_evaluate_now (fold_convert (type , tmp), block); } + else + tmp = fold_convert (type , tmp); tmp2 = fold_build2_loc (input_location, MULT_EXPR, type, size, tmp); tmp = fold_build2_loc (input_location, GT_EXPR, @@ -11671,15 +11673,24 @@ trans_class_assignment (stmtblock_t *block, gfc_expr *lhs, gfc_expr *rhs, /* Take into account _len of unlimited polymorphic entities. TODO: handle class(*) allocatable function results on rhs. */ - if (UNLIMITED_POLY (rhs) && rhs->expr_type == EXPR_VARIABLE) + if (UNLIMITED_POLY (rhs)) { - tree len = trans_get_upoly_len (block, rhs); + tree len; + if (rhs->expr_type == EXPR_VARIABLE) + len = trans_get_upoly_len (block, rhs); + else + len = gfc_class_len_get (tmp); len = fold_build2_loc (input_location, MAX_EXPR, size_type_node, fold_convert (size_type_node, len), size_one_node); size = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (size), size, fold_convert (TREE_TYPE (size), len)); } + else if (rhs->ts.type == BT_CHARACTER && rse->string_length) + size = fold_build2_loc (input_location, MULT_EXPR, + gfc_charlen_type_node, size, + rse->string_length); + tmp = lse->expr; class_han = GFC_CLASS_TYPE_P (TREE_TYPE (tmp)) diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc index 455b61aa564..f40bfda903b 100644 --- a/gcc/fortran/trans-intrinsic.cc +++ b/gcc/fortran/trans-intrinsic.cc @@ -8254,7 +8254,9 @@ gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr) { gfc_expr *arg; gfc_se argse; - tree type, result_type, tmp; + tree type, result_type, tmp, class_decl = NULL; + gfc_symbol *sym; + bool unlimited = false; arg = expr->value.function.actual->expr; @@ -8265,10 +8267,12 @@ gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr) { if (arg->ts.type == BT_CLASS) { + unlimited = UNLIMITED_POLY (arg); gfc_add_vptr_component (arg); gfc_add_size_component (arg); gfc_conv_expr (&argse, arg); tmp = fold_convert (result_type, argse.expr); + class_decl = gfc_get_class_from_expr (argse.expr); goto done; } @@ -8280,14 +8284,20 @@ gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr) { argse.want_pointer = 0; gfc_conv_expr_descriptor (&argse, arg); + sym = arg->expr_type == EXPR_VARIABLE ? arg->symtree->n.sym : NULL; if (arg->ts.type == BT_CLASS) { - if (arg->rank > 0) + unlimited = UNLIMITED_POLY (arg); + if (TREE_CODE (argse.expr) == COMPONENT_REF) + tmp = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0)); + else if (arg->rank > 0 && sym + && DECL_LANG_SPECIFIC (sym->backend_decl)) tmp = gfc_class_vtab_size_get ( - GFC_DECL_SAVED_DESCRIPTOR (arg->symtree->n.sym->backend_decl)); + GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl)); else - tmp = gfc_class_vtab_size_get (TREE_OPERAND (argse.expr, 0)); + gcc_unreachable (); tmp = fold_convert (result_type, tmp); + class_decl = gfc_get_class_from_expr (argse.expr); goto done; } type = gfc_get_element_type (TREE_TYPE (argse.expr)); @@ -8301,6 +8311,9 @@ gfc_conv_intrinsic_storage_size (gfc_se *se, gfc_expr *expr) tmp = fold_convert (result_type, tmp); done: + if (unlimited && class_decl) + tmp = gfc_resize_class_size_with_len (NULL, class_decl, tmp); + se->expr = fold_build2_loc (input_location, MULT_EXPR, result_type, tmp, build_int_cst (result_type, BITS_PER_UNIT)); gfc_add_block_to_block (&se->pre, &argse.pre); @@ -8423,7 +8436,10 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr) { tmp = build_fold_indirect_ref_loc (input_location, argse.expr); if (GFC_CLASS_TYPE_P (TREE_TYPE (tmp))) - source = gfc_class_data_get (tmp); + { + source = gfc_class_data_get (tmp); + class_ref = tmp; + } else { /* Array elements are evaluated as a reference to the data. @@ -8450,9 +8466,17 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr) break; case BT_CLASS: if (class_ref != NULL_TREE) - tmp = gfc_class_vtab_size_get (class_ref); + { + tmp = gfc_class_vtab_size_get (class_ref); + if (UNLIMITED_POLY (source_expr)) + tmp = gfc_resize_class_size_with_len (NULL, class_ref, tmp); + } else - tmp = gfc_class_vtab_size_get (argse.expr); + { + tmp = gfc_class_vtab_size_get (argse.expr); + if (UNLIMITED_POLY (source_expr)) + tmp = gfc_resize_class_size_with_len (NULL, argse.expr, tmp); + } break; default: source_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location, @@ -8505,6 +8529,13 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr) if (arg->expr->ts.type == BT_CHARACTER) tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length); + else if (arg->expr->ts.type == BT_CLASS) + { + class_ref = TREE_OPERAND (argse.expr, 0); + tmp = gfc_class_vtab_size_get (class_ref); + if (UNLIMITED_POLY (arg->expr)) + tmp = gfc_resize_class_size_with_len (&argse.pre, class_ref, tmp); + } else tmp = fold_convert (gfc_array_index_type, size_in_bytes (source_type)); @@ -8545,15 +8576,14 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr) if (arg->expr->rank == 0) { - gfc_conv_expr_reference (&argse, arg->expr); + gfc_conv_expr_reference (&argse, mold_expr); mold_type = TREE_TYPE (build_fold_indirect_ref_loc (input_location, argse.expr)); } else { - gfc_init_se (&argse, NULL); argse.want_pointer = 0; - gfc_conv_expr_descriptor (&argse, arg->expr); + gfc_conv_expr_descriptor (&argse, mold_expr); mold_type = gfc_get_element_type (TREE_TYPE (argse.expr)); } @@ -8564,27 +8594,41 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr) { /* If this TRANSFER is nested in another TRANSFER, use a type that preserves all bits. */ - if (arg->expr->ts.type == BT_LOGICAL) - mold_type = gfc_get_int_type (arg->expr->ts.kind); + if (mold_expr->ts.type == BT_LOGICAL) + mold_type = gfc_get_int_type (mold_expr->ts.kind); } /* Obtain the destination word length. */ - switch (arg->expr->ts.type) + switch (mold_expr->ts.type) { case BT_CHARACTER: - tmp = size_of_string_in_bytes (arg->expr->ts.kind, argse.string_length); - mold_type = gfc_get_character_type_len (arg->expr->ts.kind, + tmp = size_of_string_in_bytes (mold_expr->ts.kind, argse.string_length); + mold_type = gfc_get_character_type_len (mold_expr->ts.kind, argse.string_length); break; case BT_CLASS: - tmp = gfc_class_vtab_size_get (argse.expr); + if (scalar_mold) + class_ref = argse.expr; + else + class_ref = TREE_OPERAND (argse.expr, 0); + tmp = gfc_class_vtab_size_get (class_ref); + if (UNLIMITED_POLY (arg->expr)) + tmp = gfc_resize_class_size_with_len (&argse.pre, class_ref, tmp); break; default: tmp = fold_convert (gfc_array_index_type, size_in_bytes (mold_type)); break; } - dest_word_len = gfc_create_var (gfc_array_index_type, NULL); - gfc_add_modify (&se->pre, dest_word_len, tmp); + + /* Do not fix dest_word_len if it is a variable, since the temporary can wind + up being used before the assignment. */ + if (mold_expr->ts.type == BT_CHARACTER && mold_expr->ts.deferred) + dest_word_len = tmp; + else + { + dest_word_len = gfc_create_var (gfc_array_index_type, NULL); + gfc_add_modify (&se->pre, dest_word_len, tmp); + } /* Finally convert SIZE, if it is present. */ arg = arg->next; diff --git a/gcc/testsuite/gfortran.dg/storage_size_7.f90 b/gcc/testsuite/gfortran.dg/storage_size_7.f90 new file mode 100644 index 00000000000..e32ca1b6a0e --- /dev/null +++ b/gcc/testsuite/gfortran.dg/storage_size_7.f90 @@ -0,0 +1,91 @@ +! { dg-do run } +! Fix STORAGE_SIZE intrinsic for polymorphic arguments PR84006 and PR100027. +! Contributed by Steve Kargl +! and José Rui Faustino de Sousa +program p + use, intrinsic :: ISO_FORTRAN_ENV, only: int64 + type t + integer i + end type + type s + class(t), allocatable :: c(:) + end type + integer :: rslt, class_rslt + integer(kind=int64), target :: tgt + class(t), allocatable, target :: t_alloc(:) + class(s), allocatable, target :: s_alloc(:) + character(:), allocatable, target :: chr(:) + class(*), pointer :: ptr_s, ptr_a(:) + + allocate (t_alloc(2), source=t(1)) + rslt = storage_size(t_alloc(1)) ! Scalar arg - the original testcase + if (rslt .ne. 32) stop 1 + + rslt = storage_size(t_alloc) ! Array arg + if (rslt .ne. 32) stop 2 + + call pr100027 + + allocate (s_alloc(2), source=s([t(1), t(2)])) +! This, of course, is processor dependent: gfortran gives 576, NAG 448 +! and Intel 1216. + class_rslt = storage_size(s_alloc) ! Type with a class component + ptr_s => s_alloc(2) +! However, the unlimited polymorphic result should be the same + if (storage_size (ptr_s) .ne. class_rslt) stop 3 + ptr_a => s_alloc + if (storage_size (ptr_a) .ne. class_rslt) stop 4 + + rslt = storage_size(s_alloc(1)%c(2)) ! Scalar component arg + if (rslt .ne. 32) stop 5 + + rslt = storage_size(s_alloc(1)%c) ! Scalar component of array arg + if (rslt .ne. 32) stop 6 + + ptr_s => tgt + rslt = storage_size (ptr_s) ! INTEGER(8) target + if (rslt .ne. 64) stop 7 + + allocate (chr(2), source = ["abcde", "fghij"]) + ptr_s => chr(2) + rslt = storage_size (ptr_s) ! CHARACTER(5) scalar + if (rslt .ne. 40) stop 8 + + ptr_a => chr + rslt = storage_size (ptr_a) ! CHARACTER(5) array + if (rslt .ne. 40) stop 9 + + deallocate (t_alloc, s_alloc, chr) ! For valgrind check + +contains + +! Original testcase from José Rui Faustino de Sousa + subroutine pr100027 + implicit none + + integer, parameter :: n = 11 + + type :: foo_t + end type foo_t + + type, extends(foo_t) :: bar_t + end type bar_t + + class(*), pointer :: apu(:) + class(foo_t), pointer :: apf(:) + class(bar_t), pointer :: apb(:) + type(bar_t), target :: atb(n) + + integer :: m + + apu => atb + m = storage_size(apu) + if (m .ne. 0) stop 10 + apf => atb + m = storage_size(apf) + if (m .ne. 0) stop 11 + apb => atb + m = storage_size(apb) + if (m .ne. 0) stop 12 + end +end program p diff --git a/gcc/testsuite/gfortran.dg/transfer_class_4.f90 b/gcc/testsuite/gfortran.dg/transfer_class_4.f90 new file mode 100644 index 00000000000..604874e1e28 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/transfer_class_4.f90 @@ -0,0 +1,87 @@ +! { dg-do run } +! +! Fix TRANSFER intrinsic for unlimited polymorphic SOURCEs - PR98534 +! Note that unlimited polymorphic MOLD is a TODO. +! +! Contributed by Paul Thomas +! + use, intrinsic :: ISO_FORTRAN_ENV, only: real32 + implicit none + character(*), parameter :: string = "abcdefgh" + character(len=:), allocatable :: string_a(:) + class(*), allocatable :: star + class(*), allocatable :: star_a(:) + character(len=:), allocatable :: chr + character(len=:), allocatable :: chr_a(:) + integer :: sz, sum1, sum2, i + real(real32) :: r = 1.0 + +! Part 1: worked correctly + star = r + sz = storage_size (star)/8 + allocate (character(len=sz) :: chr) + chr = transfer (star, chr) + sum1 = sum ([(ichar(chr(i:i)), i = 1, sz)]) + chr = transfer(1.0, chr) + sum2 = sum ([(ichar(chr(i:i)), i = 1, sz)]) + + if (sz /= storage_size (r)/8) stop 1 + if (sum1 /= sum2) stop 2 + + deallocate (star) ! The automatic reallocation causes invalid writes + ! and memory leaks. Even with this deallocation + ! The invalid writes still occur. + deallocate (chr) + +! Part 2: Got everything wrong because '_len' field of unlimited polymorphic +! expressions was not used. + star = string + sz = storage_size (star)/8 + if (sz /= len (string)) stop 3 ! storage_size failed + + sz = len (string) ! Ignore previous error in storage_size + allocate (character(len=sz) :: chr) + chr = transfer (star, chr) + sum1 = sum ([(ichar(chr(i:i)), i = 1, sz)]) + chr = transfer(string, chr) + sum2 = sum ([(ichar(chr(i:i)), i = 1, sz)]) + if (sum1 /= sum2) stop 4 ! transfer failed + +! Check that arrays are OK for transfer + star_a = ['abcde','fghij'] + allocate (character (len = 5) :: chr_a(2)) + chr_a = transfer (star_a, chr_a) + if (any (chr_a .ne. ['abcde','fghij'])) stop 5 + +! Check that string length and size are correctly handled + string_a = ["abcdefgh", "ijklmnop"] + star_a = string_a; + chr_a = transfer (star_a, chr_a) ! Old string length used for size + if (size(chr_a) .ne. 4) stop 6 + if (len(chr_a) .ne. 5) stop 7 + if (trim (chr_a(3)) .ne. "klmno") stop 8 + if (chr_a(4)(1:1) .ne. "p") stop 9 + + chr_a = transfer (star_a, string_a) ! Use correct string_length for payload + if (size(chr_a) .ne. 2) stop 10 + if (len(chr_a) .ne. 8) stop 11 + if (any (chr_a .ne. string_a)) stop 12 + +! Check that an unlimited polymorphic function result is transferred OK + deallocate (chr_a) + string_a = ['abc', 'def', 'hij'] + chr_a = transfer (foo (string_a), string_a) + if (any (chr_a .ne. string_a)) stop 13 + +! Finally, check that the SIZE gives correct results with unlimited sources. + chr_a = transfer (star_a, chr_a, 4) + if (chr_a (4) .ne. 'jkl') stop 14 + + deallocate (star, chr, star_a, chr_a, string_a) +contains + function foo (arg) result(res) + character(*), intent(in) :: arg(:) + class(*), allocatable :: res(:) + res = arg + end +end commit 58ef04d26d1ba9eaf54fabc84b656b6b965d83ac Author: GCC Administrator Date: Tue Jul 9 00:22:24 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index d50aabd12dd..b01fad6bd4f 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240708 +20240709 diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 21654771942..915e08ca130 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,34 @@ +2024-07-08 Paul Thomas + + Backported from master: + 2024-05-12 Paul Thomas + + PR fortran/84006 + PR fortran/100027 + PR fortran/98534 + * iresolve.cc (gfc_resolve_transfer): Emit a TODO error for + unlimited polymorphic mold. + * trans-expr.cc (gfc_resize_class_size_with_len): Use the fold + even if a block is not available in which to fix the result. + (trans_class_assignment): Enable correct assignment of + character expressions to unlimited polymorphic variables using + lhs _len field and rse string_length. + * trans-intrinsic.cc (gfc_conv_intrinsic_storage_size): Extract + the class expression so that the unlimited polymorphic class + expression can be used in gfc_resize_class_size_with_len to + obtain the storage size for character payloads. Guard the use + of GFC_DECL_SAVED_DESCRIPTOR by testing for DECL_LANG_SPECIFIC + to prevent the ICE. Also, invert the order to use the class + expression extracted from the argument. + (gfc_conv_intrinsic_transfer): In same way as 'storage_size', + use the _len field to obtaining the correct length for arg 1. + Add a branch for the element size in bytes of class expressions + with provision to make use of the unlimited polymorphic _len + field. Again, the class references are explicitly identified. + 'mold_expr' was already declared. Use it instead of 'arg'. Do + not fix 'dest_word_len' for deferred character sources because + reallocation on assign makes use of it before it is assigned. + 2024-06-19 Harald Anlauf Backported from master: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b35264c40d8..2c17953b2d7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2024-07-08 Paul Thomas + + Backported from master: + 2024-05-12 Paul Thomas + + PR fortran/84006 + PR fortran/100027 + PR fortran/98534 + * gfortran.dg/storage_size_7.f90: New test. + * gfortran.dg/transfer_class_4.f90: New test. + 2024-07-05 Georg-Johann Lay Backported from master: commit 3cd410fe4f48ffd841fcd5442d1f2d6350666330 Author: Jonathan Wakely Date: Fri Jun 28 15:14:15 2024 +0100 libstdc++: Define __glibcxx_assert_fail for non-verbose build [PR115585] When the library is configured with --disable-libstdcxx-verbose the assertions just abort instead of calling __glibcxx_assert_fail, and so I didn't export that function for the non-verbose build. However, that option is documented to not change the library ABI, so we still need to export the symbol from the library. It could be needed by programs compiled against the headers from a verbose build. The non-verbose definition can just call abort so that it doesn't pull in I/O symbols, which are unwanted in a non-verbose build. libstdc++-v3/ChangeLog: PR libstdc++/115585 * src/c++11/assert_fail.cc (__glibcxx_assert_fail): Add definition for non-verbose builds. (cherry picked from commit 52370c839edd04df86d3ff2b71fcdca0c7376a7f) diff --git a/libstdc++-v3/src/c++11/assert_fail.cc b/libstdc++-v3/src/c++11/assert_fail.cc index 540e953da2e..774ffa70118 100644 --- a/libstdc++-v3/src/c++11/assert_fail.cc +++ b/libstdc++-v3/src/c++11/assert_fail.cc @@ -22,10 +22,10 @@ // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . -#include // for std::fprintf, stderr #include // for std::abort #ifdef _GLIBCXX_VERBOSE_ASSERT +#include // for std::fprintf, stderr namespace std { [[__noreturn__]] @@ -41,4 +41,12 @@ namespace std abort(); } } +#else +namespace std +{ + [[__noreturn__]] + void + __glibcxx_assert_fail(const char*, int, const char*, const char*) noexcept + { abort(); } +} #endif commit c36ef56fc1df456a2174d7cb42967a0e871597c2 Author: Jonathan Wakely Date: Sun Jul 7 12:22:42 2024 +0100 libstdc++: Fix _Atomic(T) macro in [PR115807] The definition of the _Atomic(T) macro needs to refer to ::std::atomic, not some other std::atomic relative to the current namespace. libstdc++-v3/ChangeLog: PR libstdc++/115807 * include/c_compatibility/stdatomic.h (_Atomic): Ensure it refers to std::atomic in the global namespace. * testsuite/29_atomics/headers/stdatomic.h/115807.cc: New test. (cherry picked from commit 40d234dd6439e8c8cfbf3f375a61906aed35c80d) diff --git a/libstdc++-v3/include/c_compatibility/stdatomic.h b/libstdc++-v3/include/c_compatibility/stdatomic.h index b565a1c1ab1..2bb23decf8d 100644 --- a/libstdc++-v3/include/c_compatibility/stdatomic.h +++ b/libstdc++-v3/include/c_compatibility/stdatomic.h @@ -34,7 +34,7 @@ #define __cpp_lib_stdatomic_h 202011L -#define _Atomic(_Tp) std::atomic<_Tp> +#define _Atomic(_Tp) ::std::atomic<_Tp> using std::memory_order; using std::memory_order_relaxed; diff --git a/libstdc++-v3/testsuite/29_atomics/headers/stdatomic.h/115807.cc b/libstdc++-v3/testsuite/29_atomics/headers/stdatomic.h/115807.cc new file mode 100644 index 00000000000..14f320fe835 --- /dev/null +++ b/libstdc++-v3/testsuite/29_atomics/headers/stdatomic.h/115807.cc @@ -0,0 +1,14 @@ +// { dg-do compile { target c++23 } } +#include +namespace other { + namespace std { + int atomic = 0; + } + _Atomic(long) a{}; +} + +#include + +namespace non::std { + static_assert( ::std::is_same_v<_Atomic(int), ::std::atomic> ); +} commit cc0b3547620b5b0cd270c72b2e16aa12d91abe92 Author: GCC Administrator Date: Wed Jul 10 00:22:51 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index b01fad6bd4f..1f0d44748df 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240709 +20240710 diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 959d59758ff..833b36f9f95 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,22 @@ +2024-07-09 Jonathan Wakely + + Backported from master: + 2024-07-08 Jonathan Wakely + + PR libstdc++/115807 + * include/c_compatibility/stdatomic.h (_Atomic): Ensure it + refers to std::atomic in the global namespace. + * testsuite/29_atomics/headers/stdatomic.h/115807.cc: New test. + +2024-07-09 Jonathan Wakely + + Backported from master: + 2024-06-28 Jonathan Wakely + + PR libstdc++/115585 + * src/c++11/assert_fail.cc (__glibcxx_assert_fail): Add + definition for non-verbose builds. + 2024-06-28 Jonathan Wakely Backported from master: commit 4f6f63f2cfcc62d6d893f301ea6aa4f6365624ba Author: Torbjörn SVENSSON Date: Wed Jul 10 18:14:22 2024 +0200 testsuite: Align testcase with implementation [PR105090] Since r13-1006-g2005b9b888eeac, the test case copysign_softfloat_1.c no longer contains any lsr istruction, so drop the check as per comment 9 in PR105090. gcc/testsuite/ChangeLog: PR target/105090 * gcc.target/arm/copysign_softfloat_1.c: Drop check for lsr Signed-off-by: Torbjörn SVENSSON (cherry picked from commit 4865a92b35054fdfaa1318a4c1f56d95d44012a2) diff --git a/gcc/testsuite/gcc.target/arm/copysign_softfloat_1.c b/gcc/testsuite/gcc.target/arm/copysign_softfloat_1.c index a14922f1c12..50317b7abe5 100644 --- a/gcc/testsuite/gcc.target/arm/copysign_softfloat_1.c +++ b/gcc/testsuite/gcc.target/arm/copysign_softfloat_1.c @@ -42,7 +42,6 @@ main (int argc, char **argv) int index = 0; /* { dg-final { scan-assembler-times "bfi" 2 { target arm_softfloat } } } */ -/* { dg-final { scan-assembler-times "lsr" 1 { target arm_softfloat } } } */ for (index; index < N; index++) { if (__builtin_copysignf (a_f[index], b_f[index]) != c_f[index]) commit cc47ad09e571016f498710fbd8a19f302c9004de Author: Uros Bizjak Date: Wed Jul 10 09:27:27 2024 +0200 middle-end: Fix stalled swapped condition code value [PR115836] emit_store_flag_1 calculates scode (swapped condition code) at the beginning of the function from the value of code variable. However, code variable may change before scode usage site, resulting in invalid stalled scode value. Move calculation of scode value just before its only usage site to avoid stalled scode value. PR middle-end/115836 gcc/ChangeLog: * expmed.cc (emit_store_flag_1): Move calculation of scode just before its only usage site. (cherry picked from commit 44933fdeb338e00c972e42224b9a83d3f8f6a757) diff --git a/gcc/expmed.cc b/gcc/expmed.cc index 1553ea8e31e..e06cdd47e9e 100644 --- a/gcc/expmed.cc +++ b/gcc/expmed.cc @@ -5607,11 +5607,9 @@ emit_store_flag_1 (rtx target, enum rtx_code code, rtx op0, rtx op1, enum insn_code icode; machine_mode compare_mode; enum mode_class mclass; - enum rtx_code scode; if (unsignedp) code = unsigned_condition (code); - scode = swap_condition (code); /* If one operand is constant, make it the second one. Only do this if the other operand is not constant as well. */ @@ -5726,6 +5724,8 @@ emit_store_flag_1 (rtx target, enum rtx_code code, rtx op0, rtx op1, if (GET_MODE_CLASS (mode) == MODE_FLOAT) { + enum rtx_code scode = swap_condition (code); + tem = emit_cstore (target, icode, scode, mode, compare_mode, unsignedp, op1, op0, normalizep, target_mode); if (tem) commit aa053808404fbb38d60be4c21c6506d42f9c9a04 Author: GCC Administrator Date: Thu Jul 11 00:22:16 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a035c36e80e..8c472ed49d9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2024-07-10 Uros Bizjak + + Backported from master: + 2024-07-10 Uros Bizjak + + PR middle-end/115836 + * expmed.cc (emit_store_flag_1): Move calculation of + scode just before its only usage site. + 2024-07-05 Georg-Johann Lay Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 1f0d44748df..d8524ff6036 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240710 +20240711 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2c17953b2d7..06807da30a0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2024-07-10 Torbjörn SVENSSON + + Backported from master: + 2024-07-10 Torbjörn SVENSSON + + PR target/105090 + * gcc.target/arm/copysign_softfloat_1.c: Drop check for lsr + 2024-07-08 Paul Thomas Backported from master: commit dd7b273f8dc03f28b0cd07c1a489d5200abaf790 Author: Andre Vieira Date: Thu Jul 11 15:38:45 2024 +0100 mve: Fix vsetq_lane for 64-bit elements with lane 1 [PR 115611] This patch fixes the backend pattern that was printing the wrong input scalar register pair when inserting into lane 1. Added a new test to force float-abi=hard so we can use scan-assembler to check correct codegen. gcc/ChangeLog: PR target/115611 * config/arm/mve.md (mve_vec_setv2di_internal): Fix printing of input scalar register pair when lane = 1. gcc/testsuite/ChangeLog: * gcc.target/arm/mve/intrinsics/vsetq_lane_su64.c: New test. (cherry picked from commit 7c11fdd2cc11a7058e9643b6abf27831970ad2c9) diff --git a/gcc/config/arm/mve.md b/gcc/config/arm/mve.md index cf172f16c57..fd016c43461 100644 --- a/gcc/config/arm/mve.md +++ b/gcc/config/arm/mve.md @@ -10166,7 +10166,7 @@ if (elt == 0) return "vmov\t%e0, %Q1, %R1"; else - return "vmov\t%f0, %J1, %K1"; + return "vmov\t%f0, %Q1, %R1"; } [(set_attr "type" "mve_move")]) diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/vsetq_lane_su64.c b/gcc/testsuite/gcc.target/arm/mve/intrinsics/vsetq_lane_su64.c new file mode 100644 index 00000000000..5aa3bc9a76a --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/vsetq_lane_su64.c @@ -0,0 +1,63 @@ +/* { dg-require-effective-target arm_v8_1m_mve_ok } */ +/* { dg-add-options arm_v8_1m_mve } */ +/* { dg-require-effective-target arm_hard_ok } */ +/* { dg-additional-options "-mfloat-abi=hard -O2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include "arm_mve.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* +**fn1: +** vmov d0, r0, r1 +** bx lr +*/ +uint64x2_t +fn1 (uint64_t a, uint64x2_t b) +{ + return vsetq_lane_u64 (a, b, 0); +} + +/* +**fn2: +** vmov d1, r0, r1 +** bx lr +*/ +uint64x2_t +fn2 (uint64_t a, uint64x2_t b) +{ + return vsetq_lane_u64 (a, b, 1); +} + +/* +**fn3: +** vmov d0, r0, r1 +** bx lr +*/ +int64x2_t +fn3 (int64_t a, int64x2_t b) +{ + return vsetq_lane_s64 (a, b, 0); +} + +/* +**fn4: +** vmov d1, r0, r1 +** bx lr +*/ +int64x2_t +fn4 (int64_t a, int64x2_t b) +{ + return vsetq_lane_s64 (a, b, 1); +} + + +#ifdef __cplusplus +} +#endif + +/* { dg-final { scan-assembler-not "__ARM_undef" } } */ + commit abc038a8b4644e49ab2038e3c279e5b28d5cb895 Author: GCC Administrator Date: Fri Jul 12 00:23:51 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8c472ed49d9..bbd8a0e5120 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2024-07-11 Andre Vieira + + Backported from master: + 2024-07-11 Andre Vieira + + PR target/115611 + * config/arm/mve.md (mve_vec_setv2di_internal): Fix printing of input + scalar register pair when lane = 1. + 2024-07-10 Uros Bizjak Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index d8524ff6036..93ea1dc1b26 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240711 +20240712 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 06807da30a0..9ca7f3452d0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2024-07-11 Andre Vieira + + Backported from master: + 2024-07-11 Andre Vieira + + * gcc.target/arm/mve/intrinsics/vsetq_lane_su64.c: New test. + 2024-07-10 Torbjörn SVENSSON Backported from master: commit 1b22831d3c74a1b3e72dab840e2818e495ecd567 Author: Paul Thomas Date: Thu May 23 07:59:46 2024 +0100 Fortran: Fix ICEs due to comp calls in initialization exprs [PR103312] 2024-05-23 Paul Thomas gcc/fortran PR fortran/103312 * dependency.cc (gfc_dep_compare_expr): Handle component call expressions. Return -2 as default and return 0 if compared with a function expression that is from an interface body and has the same name. * expr.cc (gfc_reduce_init_expr): If the expression is a comp call do not attempt to reduce, defer to resolution and return false. * trans-types.cc (gfc_get_dtype_rank_type, gfc_get_nodesc_array_type): Fix whitespace. gcc/testsuite/ PR fortran/103312 * gfortran.dg/pr103312.f90: New test. (cherry picked from commit 2ce90517ed75c4af9fc0616f2670cf6dfcfa8a91) diff --git a/gcc/fortran/dependency.cc b/gcc/fortran/dependency.cc index 9117825ee6e..f928099e9e2 100644 --- a/gcc/fortran/dependency.cc +++ b/gcc/fortran/dependency.cc @@ -440,6 +440,38 @@ gfc_dep_compare_expr (gfc_expr *e1, gfc_expr *e2) return mpz_sgn (e2->value.op.op2->value.integer); } + + if (e1->expr_type == EXPR_COMPCALL) + { + /* This will have emerged from interface.cc(gfc_check_typebound_override) + via gfc_check_result_characteristics. It is possible that other + variants exist that are 'equal' but play it safe for now by setting + the relationship as 'indeterminate'. */ + if (e2->expr_type == EXPR_FUNCTION && e2->ref) + { + gfc_ref *ref = e2->ref; + gfc_symbol *s = NULL; + + if (e1->value.compcall.tbp->u.specific) + s = e1->value.compcall.tbp->u.specific->n.sym; + + /* Check if the proc ptr points to an interface declaration and the + names are the same; ie. the overriden proc. of an abstract type. + The checking of the arguments will already have been done. */ + for (; ref && s; ref = ref->next) + if (!ref->next && ref->type == REF_COMPONENT + && ref->u.c.component->attr.proc_pointer + && ref->u.c.component->ts.interface + && ref->u.c.component->ts.interface->attr.if_source + == IFSRC_IFBODY + && !strcmp (s->name, ref->u.c.component->name)) + return 0; + } + + /* Assume as default that TKR checking is sufficient. */ + return -2; + } + if (e1->expr_type != e2->expr_type) return -3; diff --git a/gcc/fortran/expr.cc b/gcc/fortran/expr.cc index 4a9b29c7e9d..90d2daa0864 100644 --- a/gcc/fortran/expr.cc +++ b/gcc/fortran/expr.cc @@ -3188,6 +3188,11 @@ gfc_reduce_init_expr (gfc_expr *expr) { bool t; + /* It is far too early to resolve a class compcall. Punt to resolution. */ + if (expr && expr->expr_type == EXPR_COMPCALL + && expr->symtree->n.sym->ts.type == BT_CLASS) + return false; + gfc_init_expr_flag = true; t = gfc_resolve_expr (expr); if (t) diff --git a/gcc/fortran/trans-types.cc b/gcc/fortran/trans-types.cc index b2a3000da1f..0c59ab3f5b5 100644 --- a/gcc/fortran/trans-types.cc +++ b/gcc/fortran/trans-types.cc @@ -1591,7 +1591,7 @@ gfc_get_dtype_rank_type (int rank, tree etype) size = size_in_bytes (etype); break; } - + gcc_assert (size); STRIP_NOPS (size); @@ -1736,7 +1736,7 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * as, gfc_packed packed, tmp = gfc_conv_mpz_to_tree (expr->value.integer, gfc_index_integer_kind); else - tmp = NULL_TREE; + tmp = NULL_TREE; GFC_TYPE_ARRAY_LBOUND (type, n) = tmp; expr = as->upper[n]; diff --git a/gcc/testsuite/gfortran.dg/pr103312.f90 b/gcc/testsuite/gfortran.dg/pr103312.f90 new file mode 100644 index 00000000000..deacc70bf5d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr103312.f90 @@ -0,0 +1,87 @@ +! { dg-do run } +! +! Test the fix for pr103312, in which the use of a component call in +! initialization expressions, eg. character(this%size()), caused ICEs. +! +! Contributed by Arseny Solokha +! +module example + + type, abstract :: foo + integer :: i + contains + procedure(foo_size), deferred :: size + procedure(foo_func), deferred :: func + end type + + interface + function foo_func (this) result (string) + import :: foo + class(foo) :: this + character(this%size()) :: string + end function + pure integer function foo_size (this) + import foo + class(foo), intent(in) :: this + end function + end interface + +end module + +module extension + use example + implicit none + type, extends(foo) :: bar + contains + procedure :: size + procedure :: func + end type + +contains + pure integer function size (this) + class(bar), intent(in) :: this + size = this%i + end function + function func (this) result (string) + class(bar) :: this + character(this%size()) :: string + string = repeat ("x", len (string)) + end function + +end module + +module unextended + implicit none + type :: foobar + integer :: i + contains + procedure :: size + procedure :: func + end type + +contains + pure integer function size (this) + class(foobar), intent(in) :: this + size = this%i + end function + function func (this) result (string) + class(foobar) :: this + character(this%size()) :: string + character(:), allocatable :: chr + string = repeat ("y", len (string)) + allocate (character(this%size()) :: chr) + if (len (string) .ne. len (chr)) stop 1 + end function + +end module + + use example + use extension + use unextended + type(bar) :: a + type(foobar) :: b + a%i = 5 + if (a%func() .ne. 'xxxxx') stop 2 + b%i = 7 + if (b%func() .ne. 'yyyyyyy') stop 3 +end commit 08463348c5cce84dc3c64ac4fbb20e2795ee104f Author: Jonathan Wakely Date: Tue Jun 18 13:27:02 2024 +0100 libstdc++: Fix std::to_array for trivial-ish types [PR115522] Due to PR c++/85723 the std::is_trivial trait is true for types with a deleted default constructor, so the use of std::is_trivial in std::to_array is not sufficient to ensure the type can be trivially default constructed then filled using memcpy. I also forgot that a type with a deleted assignment operator can still be trivial, so we also need to check that it's assignable because the is_constant_evaluated() path can't use memcpy. Replace the uses of std::is_trivial with std::is_trivially_copyable (needed for memcpy), std::is_trivially_default_constructible (needed so that the default construction is valid and does no work) and std::is_copy_assignable (needed for the constant evaluation case). libstdc++-v3/ChangeLog: PR libstdc++/115522 * include/std/array (to_array): Workaround the fact that std::is_trivial is not sufficient to check that a type is trivially default constructible and assignable. * testsuite/23_containers/array/creation/115522.cc: New test. (cherry picked from commit 510ce5eed69ee1bea9c2c696fe3b2301e16d1486) diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array index edcac892b52..dd9b4a0ab03 100644 --- a/libstdc++-v3/include/std/array +++ b/libstdc++-v3/include/std/array @@ -426,7 +426,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static_assert(is_constructible_v<_Tp, _Tp&>); if constexpr (is_constructible_v<_Tp, _Tp&>) { - if constexpr (is_trivial_v<_Tp>) + if constexpr (is_trivially_copyable_v<_Tp> + && is_trivially_default_constructible_v<_Tp> + && is_copy_assignable_v<_Tp>) { array, _Nm> __arr; if (!__is_constant_evaluated() && _Nm != 0) @@ -455,7 +457,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static_assert(is_move_constructible_v<_Tp>); if constexpr (is_move_constructible_v<_Tp>) { - if constexpr (is_trivial_v<_Tp>) + if constexpr (is_trivially_copyable_v<_Tp> + && is_trivially_default_constructible_v<_Tp> + && is_copy_assignable_v<_Tp>) { array, _Nm> __arr; if (!__is_constant_evaluated() && _Nm != 0) diff --git a/libstdc++-v3/testsuite/23_containers/array/creation/115522.cc b/libstdc++-v3/testsuite/23_containers/array/creation/115522.cc new file mode 100644 index 00000000000..37073e002bd --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/array/creation/115522.cc @@ -0,0 +1,33 @@ +// { dg-do compile { target c++20 } } + +// PR libstdc++/115522 std::to_array no longer works for struct which is +// trivial but not default constructible + +#include + +void +test_deleted_ctor() +{ + struct S + { + S() = delete; + S(int) { } + }; + + S arr[1] = {{1}}; + auto arr1 = std::to_array(arr); + auto arr2 = std::to_array(std::move(arr)); +} + +void +test_deleted_assignment() +{ + struct S + { + void operator=(const S&) = delete; + }; + + S arr[1] = {}; + auto a1 = std::to_array(arr); + auto a2 = std::to_array(std::move(arr)); +} commit 6f5b676416b517848f772cc3231aab92f6c709cb Author: GCC Administrator Date: Sat Jul 13 00:22:10 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 93ea1dc1b26..c6f47ba7ab6 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240712 +20240713 diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 915e08ca130..89ff48798e0 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,19 @@ +2024-07-12 Paul Thomas + + Backported from master: + 2024-05-23 Paul Thomas + + PR fortran/103312 + * dependency.cc (gfc_dep_compare_expr): Handle component call + expressions. Return -2 as default and return 0 if compared with + a function expression that is from an interface body and has + the same name. + * expr.cc (gfc_reduce_init_expr): If the expression is a comp + call do not attempt to reduce, defer to resolution and return + false. + * trans-types.cc (gfc_get_dtype_rank_type, + gfc_get_nodesc_array_type): Fix whitespace. + 2024-07-08 Paul Thomas Backported from master: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9ca7f3452d0..c8395ea571d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2024-07-12 Paul Thomas + + Backported from master: + 2024-05-23 Paul Thomas + + PR fortran/103312 + * gfortran.dg/pr103312.f90: New test. + 2024-07-11 Andre Vieira Backported from master: diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 833b36f9f95..6307b1c0e76 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,14 @@ +2024-07-12 Jonathan Wakely + + Backported from master: + 2024-06-21 Jonathan Wakely + + PR libstdc++/115522 + * include/std/array (to_array): Workaround the fact that + std::is_trivial is not sufficient to check that a type is + trivially default constructible and assignable. + * testsuite/23_containers/array/creation/115522.cc: New test. + 2024-07-09 Jonathan Wakely Backported from master: commit 616c3290785c204b3019e7aaff8a7d9bb425d336 Author: Lulu Cheng Date: Thu Jul 4 10:37:26 2024 +0800 LoongArch: TFmode is not allowed to be stored in the float register. PR target/115752 gcc/ChangeLog: * config/loongarch/loongarch.cc (loongarch_hard_regno_mode_ok_uncached): Replace UNITS_PER_FPVALUE with UNITS_PER_HWFPVALUE. * config/loongarch/loongarch.h (UNITS_PER_FPVALUE): Delete. gcc/testsuite/ChangeLog: * gcc.target/loongarch/pr115752.c: New test. (cherry picked from commit abeb6c8a62758faa0719e818e6e8a7db15a6793b) diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index 2238858cd6a..be26e156beb 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -5491,7 +5491,7 @@ loongarch_hard_regno_mode_ok_uncached (unsigned int regno, machine_mode mode) if (mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT || mclass == MODE_VECTOR_FLOAT) - return size <= UNITS_PER_FPVALUE; + return size <= UNITS_PER_HWFPVALUE; /* Allow integer modes that fit into a single register. We need to put integers into FPRs when using instructions like CVT diff --git a/gcc/config/loongarch/loongarch.h b/gcc/config/loongarch/loongarch.h index d072522e3cf..b1149a12aba 100644 --- a/gcc/config/loongarch/loongarch.h +++ b/gcc/config/loongarch/loongarch.h @@ -202,13 +202,6 @@ along with GCC; see the file COPYING3. If not see #define UNITS_PER_HWFPVALUE \ (TARGET_SOFT_FLOAT ? 0 : UNITS_PER_FPREG) -/* The largest size of value that can be held in floating-point - registers. */ -#define UNITS_PER_FPVALUE \ - (TARGET_SOFT_FLOAT ? 0 \ - : TARGET_SINGLE_FLOAT ? UNITS_PER_FPREG \ - : LONG_DOUBLE_TYPE_SIZE / BITS_PER_UNIT) - /* The number of bytes in a double. */ #define UNITS_PER_DOUBLE (TYPE_PRECISION (double_type_node) / BITS_PER_UNIT) diff --git a/gcc/testsuite/gcc.target/loongarch/pr115752.c b/gcc/testsuite/gcc.target/loongarch/pr115752.c new file mode 100644 index 00000000000..df4bae524f7 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/pr115752.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ + +long double +test (long double xx) +{ + __asm ("" :: "f"(xx)); /* { dg-error "inconsistent operand constraints in an 'asm'" } */ + return xx + 1; +} commit b5bb59ad508fa645ba325f9da513dc0aa52b58cf Author: GCC Administrator Date: Sun Jul 14 00:22:35 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bbd8a0e5120..40b7b00757a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2024-07-13 Lulu Cheng + + Backported from master: + 2024-07-12 Lulu Cheng + + PR target/115752 + * config/loongarch/loongarch.cc + (loongarch_hard_regno_mode_ok_uncached): Replace + UNITS_PER_FPVALUE with UNITS_PER_HWFPVALUE. + * config/loongarch/loongarch.h (UNITS_PER_FPVALUE): Delete. + 2024-07-11 Andre Vieira Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index c6f47ba7ab6..7a5180344d5 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240713 +20240714 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c8395ea571d..0dc32acfc0c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2024-07-13 Lulu Cheng + + Backported from master: + 2024-07-12 Lulu Cheng + + PR target/115752 + * gcc.target/loongarch/pr115752.c: New test. + 2024-07-12 Paul Thomas Backported from master: commit e3ac65f4e270171677d991ead9743b6b48f07bab Author: GCC Administrator Date: Mon Jul 15 00:21:57 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 7a5180344d5..5e0ee8afc37 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240714 +20240715 commit 9a1cdaa5e8441394d613f5f3401e7aab21efe8f0 Author: liuhongt Date: Fri Jul 12 09:39:23 2024 +0800 Fix SSA_NAME leak due to def_stmt is removed before use_stmt. - _5 = __atomic_fetch_or_8 (&set_work_pending_p, 1, 0); - # DEBUG old => (long int) _5 + _6 = .ATOMIC_BIT_TEST_AND_SET (&set_work_pending_p, 0, 1, 0, __atomic_fetch_or_8); + # DEBUG old => NULL # DEBUG BEGIN_STMT - # DEBUG D#2 => _5 & 1 + # DEBUG D#2 => NULL ... - _10 = ~_5; - _8 = (_Bool) _10; - # DEBUG ret => _8 + _8 = _6 == 0; + # DEBUG ret => (_Bool) _10 confirmed. convert_atomic_bit_not does this, it checks for single_use and removes the def, failing to release the name (which would fix this up IIRC). Note the function removes stmts in "wrong" order (before uses of LHS are removed), so it requires larger surgery. And it leaks SSA names. gcc/ChangeLog: PR target/115872 * tree-ssa-ccp.cc (convert_atomic_bit_not): Remove use_stmt after use_nop_stmt is removed. (optimize_atomic_bit_test_and): Ditto. gcc/testsuite/ChangeLog: * gcc.target/i386/pr115872.c: New test. (cherry picked from commit a8209237dc46dc4db7d9d8e3807e6c93734c64b5) diff --git a/gcc/testsuite/gcc.target/i386/pr115872.c b/gcc/testsuite/gcc.target/i386/pr115872.c new file mode 100644 index 00000000000..937004456d3 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr115872.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -g" } */ + +long set_work_pending_p; +_Bool set_work_pending() { + _Bool __trans_tmp_1; + long mask = 1, old = __atomic_fetch_or(&set_work_pending_p, mask, 0); + __trans_tmp_1 = old & mask; + return !__trans_tmp_1; +} +void __queue_work() { + _Bool ret = set_work_pending(); + if (ret) + __queue_work(); +} + diff --git a/gcc/tree-ssa-ccp.cc b/gcc/tree-ssa-ccp.cc index 2e552b330b7..6c9da603ef9 100644 --- a/gcc/tree-ssa-ccp.cc +++ b/gcc/tree-ssa-ccp.cc @@ -3321,9 +3321,10 @@ convert_atomic_bit_not (enum internal_fn fn, gimple *use_stmt, return nullptr; gimple_stmt_iterator gsi; - gsi = gsi_for_stmt (use_stmt); - gsi_remove (&gsi, true); tree var = make_ssa_name (TREE_TYPE (lhs)); + /* use_stmt need to be removed after use_nop_stmt, + so use_lhs can be released. */ + gimple *use_stmt_removal = use_stmt; use_stmt = gimple_build_assign (var, BIT_AND_EXPR, lhs, and_mask); gsi = gsi_for_stmt (use_not_stmt); gsi_insert_before (&gsi, use_stmt, GSI_NEW_STMT); @@ -3333,6 +3334,8 @@ convert_atomic_bit_not (enum internal_fn fn, gimple *use_stmt, gsi_insert_after (&gsi, g, GSI_NEW_STMT); gsi = gsi_for_stmt (use_not_stmt); gsi_remove (&gsi, true); + gsi = gsi_for_stmt (use_stmt_removal); + gsi_remove (&gsi, true); return use_stmt; } @@ -3635,8 +3638,7 @@ optimize_atomic_bit_test_and (gimple_stmt_iterator *gsip, */ } var = make_ssa_name (TREE_TYPE (use_rhs)); - gsi = gsi_for_stmt (use_stmt); - gsi_remove (&gsi, true); + gimple* use_stmt_removal = use_stmt; g = gimple_build_assign (var, BIT_AND_EXPR, use_rhs, and_mask); gsi = gsi_for_stmt (use_nop_stmt); @@ -3653,6 +3655,8 @@ optimize_atomic_bit_test_and (gimple_stmt_iterator *gsip, gsi_insert_after (&gsi, g, GSI_NEW_STMT); gsi = gsi_for_stmt (use_nop_stmt); gsi_remove (&gsi, true); + gsi = gsi_for_stmt (use_stmt_removal); + gsi_remove (&gsi, true); } } else commit c2e42ae5138210afc4b6d54da1f424597ee9dcbe Author: GCC Administrator Date: Tue Jul 16 00:24:20 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 40b7b00757a..a2c361f5e78 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2024-07-15 liuhongt + + Backported from master: + 2024-07-15 liuhongt + + PR target/115872 + * tree-ssa-ccp.cc (convert_atomic_bit_not): Remove use_stmt after use_nop_stmt is removed. + (optimize_atomic_bit_test_and): Ditto. + 2024-07-13 Lulu Cheng Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 5e0ee8afc37..e63e19096bc 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240715 +20240716 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0dc32acfc0c..04b7e511e29 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2024-07-15 liuhongt + + Backported from master: + 2024-07-15 liuhongt + + * gcc.target/i386/pr115872.c: New test. + 2024-07-13 Lulu Cheng Backported from master: commit 0b9d6829b503cfc72c4271ead2948d8100cce25c Author: Alexandre Oliva Date: Tue Jul 16 06:48:18 2024 -0300 [i386] restore recompute to override opts after change [PR113719] The first patch for PR113719 regressed gcc.dg/ipa/iinline-attr.c on toolchains configured to --enable-frame-pointer, because the optimization node created within handle_optimize_attribute had flag_omit_frame_pointer incorrectly set, whereas default_optimization_node didn't. With this difference, can_inline_edge_by_limits_p flagged an optimization mismatch and we refused to inline the function that had a redundant optimization flag into one that didn't, which is exactly what is tested for there. This patch restores the calls to ix86_default_align and ix86_recompute_optlev_based_flags that used to be, and ought to be, issued during TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE, but preserves the intent of the original change, of having those functions called at different spots within ix86_option_override_internal. To that end, the remaining bits were refactored into a separate function, that was in turn adjusted to operate on explicitly-passed opts and opts_set, rather than going for their global counterparts. for gcc/ChangeLog PR target/113719 * config/i386/i386-options.cc (ix86_override_options_after_change_1): Add opts and opts_set parms, operate on them, after factoring out of... (ix86_override_options_after_change): ... this. Restore calls of ix86_default_align and ix86_recompute_optlev_based_flags. (ix86_option_override_internal): Call the factored-out bits. (cherry picked from commit bf2fc0a27b35de039c3d45e6d7ea9ad0a8a305ba) diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc index cdbe2dc6201..4c27e4e0195 100644 --- a/gcc/config/i386/i386-options.cc +++ b/gcc/config/i386/i386-options.cc @@ -1870,37 +1870,58 @@ ix86_recompute_optlev_based_flags (struct gcc_options *opts, } } -/* Implement TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE hook. */ +/* Implement part of TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE hook. */ -void -ix86_override_options_after_change (void) +static void +ix86_override_options_after_change_1 (struct gcc_options *opts, + struct gcc_options *opts_set) { +#define OPTS_SET_P(OPTION) opts_set->x_ ## OPTION +#define OPTS(OPTION) opts->x_ ## OPTION + /* Disable unrolling small loops when there's explicit -f{,no}unroll-loop. */ - if ((OPTION_SET_P (flag_unroll_loops)) - || (OPTION_SET_P (flag_unroll_all_loops) - && flag_unroll_all_loops)) + if ((OPTS_SET_P (flag_unroll_loops)) + || (OPTS_SET_P (flag_unroll_all_loops) + && OPTS (flag_unroll_all_loops))) { - if (!OPTION_SET_P (ix86_unroll_only_small_loops)) - ix86_unroll_only_small_loops = 0; + if (!OPTS_SET_P (ix86_unroll_only_small_loops)) + OPTS (ix86_unroll_only_small_loops) = 0; /* Re-enable -frename-registers and -fweb if funroll-loops enabled. */ - if (!OPTION_SET_P (flag_web)) - flag_web = flag_unroll_loops; - if (!OPTION_SET_P (flag_rename_registers)) - flag_rename_registers = flag_unroll_loops; + if (!OPTS_SET_P (flag_web)) + OPTS (flag_web) = OPTS (flag_unroll_loops); + if (!OPTS_SET_P (flag_rename_registers)) + OPTS (flag_rename_registers) = OPTS (flag_unroll_loops); /* -fcunroll-grow-size default follws -f[no]-unroll-loops. */ - if (!OPTION_SET_P (flag_cunroll_grow_size)) - flag_cunroll_grow_size = flag_unroll_loops - || flag_peel_loops - || optimize >= 3; + if (!OPTS_SET_P (flag_cunroll_grow_size)) + OPTS (flag_cunroll_grow_size) + = (OPTS (flag_unroll_loops) + || OPTS (flag_peel_loops) + || OPTS (optimize) >= 3); } else { - if (!OPTION_SET_P (flag_cunroll_grow_size)) - flag_cunroll_grow_size = flag_peel_loops || optimize >= 3; + if (!OPTS_SET_P (flag_cunroll_grow_size)) + OPTS (flag_cunroll_grow_size) + = (OPTS (flag_peel_loops) + || OPTS (optimize) >= 3); } +#undef OPTS +#undef OPTS_SET_P +} + +/* Implement TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE hook. */ + +void +ix86_override_options_after_change (void) +{ + ix86_default_align (&global_options); + + ix86_recompute_optlev_based_flags (&global_options, &global_options_set); + + ix86_override_options_after_change_1 (&global_options, &global_options_set); } /* Clear stack slot assignments remembered from previous functions. @@ -2417,7 +2438,7 @@ ix86_option_override_internal (bool main_args_p, ix86_recompute_optlev_based_flags (opts, opts_set); - ix86_override_options_after_change (); + ix86_override_options_after_change_1 (opts, opts_set); ix86_tune_cost = processor_cost_table[ix86_tune]; /* TODO: ix86_cost should be chosen at instruction or function granuality commit 52959e34c8a7a0473784ca044487d05e791286c1 Author: Alexandre Oliva Date: Tue Jul 16 06:48:36 2024 -0300 [i386] adjust flag_omit_frame_pointer in a single function [PR113719] The first two patches for PR113719 have each regressed gcc.dg/ipa/iinline-attr.c on a different target. The reason for this instability is that there are competing flag_omit_frame_pointer overriders on x86: - ix86_recompute_optlev_based_flags computes and sets a -f[no-]omit-frame-pointer default depending on USE_IX86_FRAME_POINTER and, in 32-bit mode, optimize_size - ix86_option_override_internal enables flag_omit_frame_pointer for -momit-leaf-frame-pointer to take effect ix86_option_override[_internal] calls ix86_recompute_optlev_based_flags before setting flag_omit_frame_pointer. It is called during global process_options. But ix86_recompute_optlev_based_flags is also called by parse_optimize_options, during attribute processing, and at that point, ix86_option_override is not called, so the final overrider for global options is not applied to the optimize attributes. If they differ, the testcase fails. In order to fix this, we need to process all overriders of this option whenever we process any of them. Since this setting is affected by optimization options, it makes sense to compute it in parse_optimize_options, rather than in process_options. for gcc/ChangeLog PR target/113719 * config/i386/i386-options.cc (ix86_option_override_internal): Move flag_omit_frame_pointer final overrider... (ix86_recompute_optlev_based_flags): ... here. (cherry picked from commit bf8e80f9d164f8778d86a3dc50e501cf19a9eff1) diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc index 4c27e4e0195..a4cff4e615f 100644 --- a/gcc/config/i386/i386-options.cc +++ b/gcc/config/i386/i386-options.cc @@ -1868,6 +1868,12 @@ ix86_recompute_optlev_based_flags (struct gcc_options *opts, opts->x_flag_pcc_struct_return = DEFAULT_PCC_STRUCT_RETURN; } } + + /* Keep nonleaf frame pointers. */ + if (opts->x_flag_omit_frame_pointer) + opts->x_target_flags &= ~MASK_OMIT_LEAF_FRAME_POINTER; + else if (TARGET_OMIT_LEAF_FRAME_POINTER_P (opts->x_target_flags)) + opts->x_flag_omit_frame_pointer = 1; } /* Implement part of TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE hook. */ @@ -2509,12 +2515,6 @@ ix86_option_override_internal (bool main_args_p, opts->x_target_flags |= MASK_NO_RED_ZONE; } - /* Keep nonleaf frame pointers. */ - if (opts->x_flag_omit_frame_pointer) - opts->x_target_flags &= ~MASK_OMIT_LEAF_FRAME_POINTER; - else if (TARGET_OMIT_LEAF_FRAME_POINTER_P (opts->x_target_flags)) - opts->x_flag_omit_frame_pointer = 1; - /* If we're doing fast math, we don't care about comparison order wrt NaNs. This lets us use a shorter comparison sequence. */ if (opts->x_flag_finite_math_only) commit 544b65cddf296a63dfb91c6ffa4f474ae9d70052 Author: Stefan Schulze Frielinghaus Date: Tue Jul 16 13:59:06 2024 +0200 s390: Align *cjump_64 and *icjump_64 During machine reorg we optimize backward jumps and transform insns as e.g. (jump_insn 118 117 119 (set (pc) (if_then_else (ne (reg:CCRAW 33 %cc) (const_int 8 [0x8])) (label_ref 134) (pc))) "dec_math_1.f90":204:8 discrim 1 2161 {*cjump_64} (expr_list:REG_DEAD (reg:CCRAW 33 %cc) (int_list:REG_BR_PROB 719407028 (nil))) -> 134) into (jump_insn 118 117 432 (set (pc) (if_then_else (ne (reg:CCRAW 33 %cc) (const_int 8 [0x8])) (pc) (label_ref 433))) "dec_math_1.f90":204:8 discrim 1 -1 (expr_list:REG_DEAD (reg:CCRAW 33 %cc) (int_list:REG_BR_PROB 719407028 (nil))) -> 433) The latter is not recognized anymore since *icjump_64 only matches CC_REGNUM against zero. Fixed by aligning *cjump_64 and *icjump_64. gcc/ChangeLog: * config/s390/s390.md (*icjump_64): Allow raw CC comparisons, i.e., any constant integer between 0 and 15 for CC comparisons. (cherry picked from commit 56de68aba6cb9cf3022d9e303eec6c6cdb49ad4d) diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 00d39608e1d..50a828f2bbb 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -9480,7 +9480,8 @@ (define_insn "*icjump_64" [(set (pc) (if_then_else - (match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)]) + (match_operator 1 "s390_comparison" [(reg CC_REGNUM) + (match_operand 2 "const_int_operand" "")]) (pc) (label_ref (match_operand 0 "" ""))))] "" commit 1accf7036570cbb0fef9afa595634be03f8c14e8 Author: Stefan Schulze Frielinghaus Date: Tue Jul 16 13:59:38 2024 +0200 s390: Fix output template for movv1qi Although for instructions MVI and MVIY it does not make a difference whether the immediate is interpreted as signed or unsigned, GAS expects unsigned immediates for instruction format SI_URD. gcc/ChangeLog: * config/s390/vector.md (mov): Fix output template for movv1qi. (cherry picked from commit e6680d3f392f7f7cc2a1515276213e21e9eeab1c) diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md index 21bec729efa..1bae1056951 100644 --- a/gcc/config/s390/vector.md +++ b/gcc/config/s390/vector.md @@ -359,8 +359,8 @@ lr\t%0,%1 mvi\t%0,0 mviy\t%0,0 - mvi\t%0,-1 - mviy\t%0,-1 + mvi\t%0,255 + mviy\t%0,255 lhi\t%0,0 lhi\t%0,-1 llc\t%0,%1 commit a80b321b2f78878751037ea645a9c11bc171cc71 Author: GCC Administrator Date: Wed Jul 17 00:22:31 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a2c361f5e78..bea19202132 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,42 @@ +2024-07-16 Stefan Schulze Frielinghaus + + Backported from master: + 2024-07-12 Stefan Schulze Frielinghaus + + * config/s390/vector.md (mov): Fix output template for + movv1qi. + +2024-07-16 Stefan Schulze Frielinghaus + + Backported from master: + 2024-07-12 Stefan Schulze Frielinghaus + + * config/s390/s390.md (*icjump_64): Allow raw CC comparisons, + i.e., any constant integer between 0 and 15 for CC comparisons. + +2024-07-16 Alexandre Oliva + + Backported from master: + 2024-07-15 Alexandre Oliva + + PR target/113719 + * config/i386/i386-options.cc (ix86_option_override_internal): + Move flag_omit_frame_pointer final overrider... + (ix86_recompute_optlev_based_flags): ... here. + +2024-07-16 Alexandre Oliva + + Backported from master: + 2024-07-03 Alexandre Oliva + + PR target/113719 + * config/i386/i386-options.cc + (ix86_override_options_after_change_1): Add opts and opts_set + parms, operate on them, after factoring out of... + (ix86_override_options_after_change): ... this. Restore calls + of ix86_default_align and ix86_recompute_optlev_based_flags. + (ix86_option_override_internal): Call the factored-out bits. + 2024-07-15 liuhongt Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index e63e19096bc..5961a7c72a1 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240716 +20240717 commit 37bd7d5c4e17c97d2b7d50f630b1cf8b347a31f4 Author: Uros Bizjak Date: Wed Jul 17 18:11:26 2024 +0200 alpha: Fix duplicate !tlsgd!62 assemble error [PR115526] Add missing "cannot_copy" attribute to instructions that have to stay in 1-1 correspondence with another insn. PR target/115526 gcc/ChangeLog: * config/alpha/alpha.md (movdi_er_high_g): Add cannot_copy attribute. (movdi_er_tlsgd): Ditto. (movdi_er_tlsldm): Ditto. (call_value_osf_): Ditto. gcc/testsuite/ChangeLog: * gcc.target/alpha/pr115526.c: New test. (cherry picked from commit 0841fd4c42ab053be951b7418233f0478282d020) diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md index 17dfc4a5868..0752c5a001c 100644 --- a/gcc/config/alpha/alpha.md +++ b/gcc/config/alpha/alpha.md @@ -3933,7 +3933,8 @@ else return "ldq %0,%2(%1)\t\t!literal!%3"; } - [(set_attr "type" "ldsym")]) + [(set_attr "type" "ldsym") + (set_attr "cannot_copy" "true")]) (define_split [(set (match_operand:DI 0 "register_operand") @@ -3957,7 +3958,8 @@ return "lda %0,%2(%1)\t\t!tlsgd"; else return "lda %0,%2(%1)\t\t!tlsgd!%3"; -}) +} + [(set_attr "cannot_copy" "true")]) (define_insn "movdi_er_tlsldm" [(set (match_operand:DI 0 "register_operand" "=r") @@ -3970,7 +3972,8 @@ return "lda %0,%&(%1)\t\t!tlsldm"; else return "lda %0,%&(%1)\t\t!tlsldm!%2"; -}) +} + [(set_attr "cannot_copy" "true")]) (define_insn "*movdi_er_gotdtp" [(set (match_operand:DI 0 "register_operand" "=r") @@ -5939,6 +5942,7 @@ "HAVE_AS_TLS" "ldq $27,%1($29)\t\t!literal!%2\;jsr $26,($27),%1\t\t!lituse_!%2\;ldah $29,0($26)\t\t!gpdisp!%*\;lda $29,0($29)\t\t!gpdisp!%*" [(set_attr "type" "jsr") + (set_attr "cannot_copy" "true") (set_attr "length" "16")]) ;; We must use peep2 instead of a split because we need accurate life diff --git a/gcc/testsuite/gcc.target/alpha/pr115526.c b/gcc/testsuite/gcc.target/alpha/pr115526.c new file mode 100644 index 00000000000..2f57903fec3 --- /dev/null +++ b/gcc/testsuite/gcc.target/alpha/pr115526.c @@ -0,0 +1,46 @@ +/* PR target/115526 */ +/* { dg-do assemble } */ +/* { dg-options "-O2 -Wno-attributes -fvisibility=hidden -fPIC -mcpu=ev4" } */ + +struct _ts { + struct _dtoa_state *interp; +}; +struct Bigint { + int k; +} *_Py_dg_strtod_bs; +struct _dtoa_state { + struct Bigint p5s; + struct Bigint *freelist[]; +}; +extern _Thread_local struct _ts _Py_tss_tstate; +typedef struct Bigint Bigint; +int pow5mult_k; +long _Py_dg_strtod_ndigits; +void PyMem_Free(); +void Bfree(Bigint *v) { + if (v) + { + if (v->k) + PyMem_Free(); + else { + struct _dtoa_state *interp = _Py_tss_tstate.interp; + interp->freelist[v->k] = v; + } + } +} +static Bigint *pow5mult(Bigint *b) { + for (;;) { + if (pow5mult_k & 1) { + Bfree(b); + if (b == 0) + return 0; + } + if (!(pow5mult_k >>= 1)) + break; + } + return 0; +} +void _Py_dg_strtod() { + if (_Py_dg_strtod_ndigits) + pow5mult(_Py_dg_strtod_bs); +} commit 94f4117c56ed715cb299272953690e496f9567f4 Author: GCC Administrator Date: Thu Jul 18 00:22:27 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bea19202132..3351352d47f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2024-07-17 Uros Bizjak + + Backported from master: + 2024-07-17 Uros Bizjak + + PR target/115526 + * config/alpha/alpha.md (movdi_er_high_g): Add cannot_copy attribute. + (movdi_er_tlsgd): Ditto. + (movdi_er_tlsldm): Ditto. + (call_value_osf_): Ditto. + 2024-07-16 Stefan Schulze Frielinghaus Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 5961a7c72a1..1d16bb88567 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240717 +20240718 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 04b7e511e29..04f6261132c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2024-07-17 Uros Bizjak + + Backported from master: + 2024-07-17 Uros Bizjak + + PR target/115526 + * gcc.target/alpha/pr115526.c: New test. + 2024-07-15 liuhongt Backported from master: commit b17ac5e747f8df2d47855344375d1e86465b70bf Author: GCC Administrator Date: Fri Jul 19 00:23:22 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 1d16bb88567..92d0274c3c6 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240718 +20240719 commit 953bf37690d22de956d75c6aef7a9690ad55b9a7 Author: LIU Hao Date: Mon Jul 15 16:55:52 2024 +0800 Do not use caller-saved registers for COMDAT functions A reference to a COMDAT function may be resolved to another definition outside the current translation unit, so it's not eligible for `-fipa-ra`. In `decl_binds_to_current_def_p()` there is already a check for weak symbols. This commit checks for COMDAT functions that are not implemented as weak symbols, for example, on *-*-mingw32. gcc/ChangeLog: PR rtl-optimization/115049 * varasm.cc (decl_binds_to_current_def_p): Add a check for COMDAT declarations too, like weak ones. (cherry picked from commit 5080840d8fbf25a321dd27543a1462d393d338bc) diff --git a/gcc/varasm.cc b/gcc/varasm.cc index 9ad41c3dbdb..e95cef8a725 100644 --- a/gcc/varasm.cc +++ b/gcc/varasm.cc @@ -7632,6 +7632,8 @@ decl_binds_to_current_def_p (const_tree decl) for all other declaration types. */ if (DECL_WEAK (decl)) return false; + if (DECL_COMDAT_GROUP (decl)) + return false; if (DECL_COMMON (decl) && (DECL_INITIAL (decl) == NULL || (!in_lto_p && DECL_INITIAL (decl) == error_mark_node))) commit efbbc24b02e9c18dc2aaff1c7083544cc7db5b94 Author: GCC Administrator Date: Sat Jul 20 00:20:28 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3351352d47f..f253848df1a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2024-07-19 LIU Hao + + Backported from master: + 2024-07-18 LIU Hao + + PR rtl-optimization/115049 + * varasm.cc (decl_binds_to_current_def_p): Add a check for COMDAT + declarations too, like weak ones. + 2024-07-17 Uros Bizjak Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 92d0274c3c6..6c93b259fd6 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240719 +20240720 commit 44fe2c06a156a63f7ae359fd5dd3ce98afa3e92a Author: René Rebe Date: Fri Jul 12 21:17:08 2024 +0000 rs6000: Fix .machine cpu selection w/ altivec [PR97367] There are various non-IBM CPUs with altivec, so we cannot use that flag to determine which .machine cpu to use, so ignore it. Emit an additional ".machine altivec" if Altivec is enabled so that the assembler doesn't require an explicit -maltivec option to assemble any Altivec instructions for those targets where the ".machine cpu" is insufficient to enable Altivec. For example, -mcpu=G5 emits a ".machine power4". 2024-07-18 René Rebe Peter Bergner gcc/ PR target/97367 * config/rs6000/rs6000.cc (rs6000_machine_from_flags): Do not consider OPTION_MASK_ALTIVEC. (emit_asm_machine): For Altivec compiles, emit a ".machine altivec". gcc/testsuite/ PR target/97367 * gcc.target/powerpc/pr97367.c: New test. Signed-off-by: René Rebe (cherry picked from commit 6962835bca3e6bef0f6ceae84a7814138b08b8a5) diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index 76eb89ad529..29475ffcb7f 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -5894,7 +5894,8 @@ rs6000_machine_from_flags (void) HOST_WIDE_INT flags = rs6000_isa_flags; /* Disable the flags that should never influence the .machine selection. */ - flags &= ~(OPTION_MASK_PPC_GFXOPT | OPTION_MASK_PPC_GPOPT | OPTION_MASK_ISEL); + flags &= ~(OPTION_MASK_PPC_GFXOPT | OPTION_MASK_PPC_GPOPT | OPTION_MASK_ISEL + | OPTION_MASK_ALTIVEC); if ((flags & (ISA_3_1_MASKS_SERVER & ~ISA_3_0_MASKS_SERVER)) != 0) return "power10"; @@ -5919,6 +5920,8 @@ void emit_asm_machine (void) { fprintf (asm_out_file, "\t.machine %s\n", rs6000_machine); + if (TARGET_ALTIVEC) + fprintf (asm_out_file, "\t.machine altivec\n"); } #endif diff --git a/gcc/testsuite/gcc.target/powerpc/pr97367.c b/gcc/testsuite/gcc.target/powerpc/pr97367.c new file mode 100644 index 00000000000..ef269a5f913 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr97367.c @@ -0,0 +1,13 @@ +/* PR target/97367 */ +/* { dg-options "-mdejagnu-cpu=G5" } */ + +/* Verify we emit a ".machine power4" and ".machine altivec" rather + than a ".machine power7". */ + +int dummy (void) +{ + return 0; +} + +/* { dg-final { scan-assembler {\.machine power4\M} } } */ +/* { dg-final { scan-assembler {\.machine altivec\M} } } */ commit 7c81ff02a943cda82cc1a82b36ae8ab14470b00a Author: Paul Thomas Date: Mon May 13 07:27:20 2024 +0100 Fortran: Fix wrong code in unlimited polymorphic assignment [PR113363] 2024-05-13 Paul Thomas gcc/fortran PR fortran/113363 * trans-array.cc (gfc_array_init_size): Use the expr3 dtype so that the correct element size is used. * trans-expr.cc (gfc_conv_procedure_call): Remove restriction that ss and ss->loop be present for the finalization of class array function results. (trans_class_assignment): Use free and malloc, rather than realloc, for character expressions assigned to unlimited poly entities. * trans-stmt.cc (gfc_trans_allocate): Build a correct rhs for the assignment of an unlimited polymorphic 'source'. gcc/testsuite/ PR fortran/113363 * gfortran.dg/pr113363.f90: New test. (cherry picked from commit 2d0eeb529d400e61197a09c56011be976dd81ef0) diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index f38e872f5d9..9557cd14b5e 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -5795,6 +5795,11 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset, tmp = gfc_conv_descriptor_dtype (descriptor); gfc_add_modify (pblock, tmp, gfc_get_dtype_rank_type (rank, type)); } + else if (expr3_desc && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (expr3_desc))) + { + tmp = gfc_conv_descriptor_dtype (descriptor); + gfc_add_modify (pblock, tmp, gfc_conv_descriptor_dtype (expr3_desc)); + } else { tmp = gfc_conv_descriptor_dtype (descriptor); diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index 6b75c147a35..657f1cb649b 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -7984,8 +7984,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, call the finalization function of the temporary. Note that the nullification of allocatable components needed by the result is done in gfc_trans_assignment_1. */ - if (expr && ((gfc_is_class_array_function (expr) - && se->ss && se->ss->loop) + if (expr && (gfc_is_class_array_function (expr) || gfc_is_alloc_class_scalar_function (expr)) && se->expr && GFC_CLASS_TYPE_P (TREE_TYPE (se->expr)) && expr->must_finalize) @@ -11705,18 +11704,25 @@ trans_class_assignment (stmtblock_t *block, gfc_expr *lhs, gfc_expr *rhs, /* Reallocate if dynamic types are different. */ gfc_init_block (&re_alloc); - tmp = fold_convert (pvoid_type_node, class_han); - re = build_call_expr_loc (input_location, - builtin_decl_explicit (BUILT_IN_REALLOC), 2, - tmp, size); - re = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (tmp), tmp, - re); - tmp = fold_build2_loc (input_location, NE_EXPR, - logical_type_node, rhs_vptr, old_vptr); - re = fold_build3_loc (input_location, COND_EXPR, void_type_node, - tmp, re, build_empty_stmt (input_location)); - gfc_add_expr_to_block (&re_alloc, re); - + if (UNLIMITED_POLY (lhs) && rhs->ts.type == BT_CHARACTER) + { + gfc_add_expr_to_block (&re_alloc, gfc_call_free (class_han)); + gfc_allocate_using_malloc (&re_alloc, class_han, size, NULL_TREE); + } + else + { + tmp = fold_convert (pvoid_type_node, class_han); + re = build_call_expr_loc (input_location, + builtin_decl_explicit (BUILT_IN_REALLOC), + 2, tmp, size); + re = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (tmp), + tmp, re); + tmp = fold_build2_loc (input_location, NE_EXPR, + logical_type_node, rhs_vptr, old_vptr); + re = fold_build3_loc (input_location, COND_EXPR, void_type_node, + tmp, re, build_empty_stmt (input_location)); + gfc_add_expr_to_block (&re_alloc, re); + } tree realloc_expr = lhs->ts.type == BT_CLASS ? gfc_finish_block (&re_alloc) : build_empty_stmt (input_location); diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc index caa7b59e912..11a8a9c74ca 100644 --- a/gcc/fortran/trans-stmt.cc +++ b/gcc/fortran/trans-stmt.cc @@ -7059,6 +7059,46 @@ gfc_trans_allocate (gfc_code * code) gfc_expr *rhs = e3rhs ? e3rhs : gfc_copy_expr (code->expr3); flag_realloc_lhs = 0; + /* The handling of code->expr3 above produces a derived type of + type "STAR", whose size defaults to size(void*). In order to + have the right type information for the assignment, we must + reconstruct an unlimited polymorphic rhs. */ + if (UNLIMITED_POLY (code->expr3) + && e3rhs && e3rhs->ts.type == BT_DERIVED + && !strcmp (e3rhs->ts.u.derived->name, "STAR")) + { + gfc_ref *ref; + gcc_assert (TREE_CODE (expr3_vptr) == COMPONENT_REF); + tmp = gfc_create_var (gfc_typenode_for_spec (&code->expr3->ts), + "e3"); + gfc_add_modify (&block, tmp, + gfc_get_class_from_expr (expr3_vptr)); + rhs->symtree->n.sym->backend_decl = tmp; + rhs->ts = code->expr3->ts; + rhs->symtree->n.sym->ts = rhs->ts; + for (ref = init_expr->ref; ref; ref = ref->next) + { + /* Copy over the lhs _data component ref followed by the + full array reference for source expressions with rank. + Otherwise, just copy the _data component ref. */ + if (code->expr3->rank + && ref && ref->next && !ref->next->next) + { + rhs->ref = gfc_copy_ref (ref); + break; + } + else if ((init_expr->rank && !code->expr3->rank + && ref && ref->next && !ref->next->next) + || (ref && !ref->next)) + { + rhs->ref = gfc_copy_ref (ref); + gfc_free_ref_list (rhs->ref->next); + rhs->ref->next = NULL; + break; + } + } + } + /* Set the symbol to be artificial so that the result is not finalized. */ init_expr->symtree->n.sym->attr.artificial = 1; tmp = gfc_trans_assignment (init_expr, rhs, true, false, true, diff --git a/gcc/testsuite/gfortran.dg/pr113363.f90 b/gcc/testsuite/gfortran.dg/pr113363.f90 new file mode 100644 index 00000000000..99d4f2076d8 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr113363.f90 @@ -0,0 +1,86 @@ +! { dg-do run } +! Test the fix for comment 1 in PR113363, which failed as in comments below. +! Contributed by Harald Anlauf +program p + implicit none + class(*), allocatable :: x(:), y + character(*), parameter :: arr(2) = ["hello ","bye "], & + sca = "Have a nice day" + character(10) :: const + +! Bug was detected in polymorphic array function results + allocate(x, source = foo ()) + call check1 (x, arr) ! Wrong output "6 hello e" + deallocate (x) + x = foo () + call check1 (x, arr) ! Wrong output "0 " + associate (var => foo ()) ! OK after r14-9489-g3fd46d859cda10 + call check1 (var, arr) ! Now OK - outputs: "6 hello bye " + end associate + +! Check scalar function results ! All OK + allocate (y, source = bar()) + call check2 (y, sca) + deallocate (y) + y = bar () + call check2 (y, sca) + deallocate (y) + associate (var => bar ()) + call check2 (var, sca) + end associate + +! Finally variable expressions... + allocate (y, source = x(1)) ! Gave zero length here + call check2 (y, "hello") + y = x(2) ! Segfaulted here + call check2 (y, "bye ") + associate (var => x(2)) ! Gave zero length here + call check2 (var, "bye ") + end associate + +! ...and constant expressions ! All OK + deallocate(y) + allocate (y, source = "abcde") + call check2 (y, "abcde") + const = "hijklmnopq" + y = const + call check2 (y, "hijklmnopq") + associate (var => "mnopq") + call check2 (var, "mnopq") + end associate + deallocate (x, y) + +contains + + function foo() result(res) + class(*), allocatable :: res(:) + res = arr + end function foo + + function bar() result(res) + class(*), allocatable :: res + res = sca + end function bar + + subroutine check1 (x, carg) + class(*), intent(in) :: x(:) + character(*) :: carg(:) + select type (x) + type is (character(*)) + if (any (x .ne. carg)) stop 1 + class default + stop 2 + end select + end subroutine check1 + + subroutine check2 (x, carg) + class(*), intent(in) :: x + character(*) :: carg + select type (x) + type is (character(*)) + if (x .ne. carg) stop 3 + class default + stop 4 + end select + end subroutine check2 +end commit 130edabae09e18064e0bdcb12656e4f4f9a51ff3 Author: Stefan Schulze Frielinghaus Date: Sat Jul 20 16:05:41 2024 +0200 s390: Fix unresolved iterators bhfgq and xdee Code attribute bhfgq is missing a mapping for TF. This results in unresolved iterators in assembler templates for *bswaptf. With the TF mapping added the base mnemonics vlbr and vstbr are not "used" anymore but only the extended mnemonics (vlbr was interpreted as vlbr; likewise for vstbr). Therefore, remove the base mnemonics from the scheduling description, otherwise, genattrtab would error about unknown mnemonics. Likewise, for movtf_vr only the extended mnemonics for vrepi are used, now, which means the base mnemonic is "unused" and has to be removed from the scheduling description. Similarly, we end up with unresolved iterators in assembler templates for mulfprx23 since code attribute xdee is missing a mapping for FPRX2. Note, this is basically a cherry pick of commit r15-2060-ga4abda934aa426 with the addition that vrepi is removed from the scheduling description, too. gcc/ChangeLog: * config/s390/3931.md (vlbr, vstbr, vrepi): Remove. * config/s390/s390.md (xdee): Add FPRX2 mapping. * config/s390/vector.md (bhfgq): Add TF mapping. diff --git a/gcc/config/s390/3931.md b/gcc/config/s390/3931.md index bed1f6c21f1..9cb11b72bba 100644 --- a/gcc/config/s390/3931.md +++ b/gcc/config/s390/3931.md @@ -404,7 +404,6 @@ vlvgg, vlvgh, vlvgp, vst, -vstbr, vstbrf, vstbrg, vstbrh, @@ -627,7 +626,6 @@ tm, tmy, vl, vlbb, -vlbr, vlbrf, vlbrg, vlbrh, @@ -661,7 +659,6 @@ vlreph, vlrl, vlrlr, vst, -vstbr, vstbrf, vstbrg, vstbrh, @@ -1077,7 +1074,6 @@ vrepb, vrepf, vrepg, vreph, -vrepi, vrepib, vrepif, vrepig, @@ -1930,7 +1926,6 @@ vrepb, vrepf, vrepg, vreph, -vrepi, vrepib, vrepif, vrepig, @@ -2156,7 +2151,6 @@ vistrfs, vistrhs, vl, vlbb, -vlbr, vlbrf, vlbrg, vlbrh, @@ -2248,7 +2242,6 @@ tbegin, tbeginc, tend, vst, -vstbr, vstbrf, vstbrg, vstbrh, diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 50a828f2bbb..8edc1261c38 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -744,7 +744,7 @@ ;; In FP templates, a in "mr" will expand to "mxr" in ;; TF/TDmode, "mdr" in DF/DDmode, "meer" in SFmode and "mer in ;; SDmode. -(define_mode_attr xdee [(TF "x") (DF "d") (SF "ee") (TD "x") (DD "d") (SD "e")]) +(define_mode_attr xdee [(TF "x") (FPRX2 "x") (DF "d") (SF "ee") (TD "x") (DD "d") (SD "e")]) ;; The decimal floating point variants of add, sub, div and mul support 3 ;; fp register operands. The following attributes allow to merge the bfp and diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md index 1bae1056951..f88e8b655fa 100644 --- a/gcc/config/s390/vector.md +++ b/gcc/config/s390/vector.md @@ -134,7 +134,7 @@ (V1TI "q") (TI "q") (V1SF "f") (V2SF "f") (V4SF "f") (V1DF "g") (V2DF "g") - (V1TF "q")]) + (V1TF "q") (TF "q")]) ; This is for vmalhw. It gets an 'w' attached to avoid confusion with ; multiply and add logical high vmalh. commit a23deb15053134840ba77d19d96b0f0771f696bf Author: Siddhesh Poyarekar Date: Fri Jul 19 12:44:32 2024 -0400 Avoid undefined behaviour in build_option_suggestions The inner loop in build_option_suggestions uses OPTION to take the address of OPTB and use it across iterations, which is undefined behaviour since OPTB is defined within the loop. Pull it outside the loop to make this defined. gcc/ChangeLog: * opt-suggestions.cc (option_proposer::build_option_suggestions): Pull OPTB definition out of the innermost loop. (cherry picked from commit e0d997e913f811ecf4b3e10891e6a4aab5b38a31) diff --git a/gcc/opt-suggestions.cc b/gcc/opt-suggestions.cc index cc0adc28ac3..1f40db35b93 100644 --- a/gcc/opt-suggestions.cc +++ b/gcc/opt-suggestions.cc @@ -167,9 +167,9 @@ option_proposer::build_option_suggestions (const char *prefix) add_misspelling_candidates (m_option_suggestions, option, opt_text); + struct cl_option optb; for (int j = 0; sanitizer_opts[j].name != NULL; ++j) { - struct cl_option optb; /* -fsanitize=all is not valid, only -fno-sanitize=all. So don't register the positive misspelling candidates for it. */ commit 44e07e4a31679ee7ee6feb9954d90188a3ef4aee Author: GCC Administrator Date: Sun Jul 21 00:20:26 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f253848df1a..409aab86aa8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +2024-07-20 Siddhesh Poyarekar + + Backported from master: + 2024-07-20 Siddhesh Poyarekar + + * opt-suggestions.cc + (option_proposer::build_option_suggestions): Pull OPTB + definition out of the innermost loop. + +2024-07-20 Stefan Schulze Frielinghaus + + * config/s390/3931.md (vlbr, vstbr, vrepi): Remove. + * config/s390/s390.md (xdee): Add FPRX2 mapping. + * config/s390/vector.md (bhfgq): Add TF mapping. + +2024-07-20 René Rebe + + Backported from master: + 2024-07-18 René Rebe + Peter Bergner + + PR target/97367 + * config/rs6000/rs6000.cc (rs6000_machine_from_flags): Do not consider + OPTION_MASK_ALTIVEC. + (emit_asm_machine): For Altivec compiles, emit a ".machine altivec". + 2024-07-19 LIU Hao Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 6c93b259fd6..d1ac33f77fb 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240720 +20240721 diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 89ff48798e0..40353ce2fa5 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,20 @@ +2024-07-20 Paul Thomas + + Backported from master: + 2024-05-13 Paul Thomas + + PR fortran/113363 + * trans-array.cc (gfc_array_init_size): Use the expr3 dtype so + that the correct element size is used. + * trans-expr.cc (gfc_conv_procedure_call): Remove restriction + that ss and ss->loop be present for the finalization of class + array function results. + (trans_class_assignment): Use free and malloc, rather than + realloc, for character expressions assigned to unlimited poly + entities. + * trans-stmt.cc (gfc_trans_allocate): Build a correct rhs for + the assignment of an unlimited polymorphic 'source'. + 2024-07-12 Paul Thomas Backported from master: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 04f6261132c..611c142e8e8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,20 @@ +2024-07-20 Paul Thomas + + Backported from master: + 2024-05-13 Paul Thomas + + PR fortran/113363 + * gfortran.dg/pr113363.f90: New test. + +2024-07-20 René Rebe + + Backported from master: + 2024-07-18 René Rebe + Peter Bergner + + PR target/97367 + * gcc.target/powerpc/pr97367.c: New test. + 2024-07-17 Uros Bizjak Backported from master: commit ae6d5dc35735168c13f4599e7cf3f32fbb3c06c9 Author: Harald Anlauf Date: Thu Jul 18 21:15:48 2024 +0200 Fortran: character array constructor with >= 4 constant elements [PR103115] gcc/fortran/ChangeLog: PR fortran/103115 * trans-array.cc (gfc_trans_array_constructor_value): If the first element of an array constructor is deferred-length character and therefore does not have an element size known at compile time, do not try to collect subsequent constant elements into a constructor for optimization. gcc/testsuite/ChangeLog: PR fortran/103115 * gfortran.dg/string_array_constructor_4.f90: New test. (cherry picked from commit c93be1606ecf8e0f65b96b67aa023fb456ceb3a3) diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index 9557cd14b5e..4d42cf1131a 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -2119,7 +2119,9 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, p = gfc_constructor_next (p); n++; } - if (n < 4) + /* Constructor with few constant elements, or element size not + known at compile time (e.g. deferred-length character). */ + if (n < 4 || !INTEGER_CST_P (TYPE_SIZE_UNIT (type))) { /* Scalar values. */ gfc_init_se (&se, NULL); diff --git a/gcc/testsuite/gfortran.dg/string_array_constructor_4.f90 b/gcc/testsuite/gfortran.dg/string_array_constructor_4.f90 new file mode 100644 index 00000000000..b5b81f07395 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/string_array_constructor_4.f90 @@ -0,0 +1,59 @@ +! { dg-do run } +! PR fortran/103115 - character array constructor with >= 4 constant elements +! +! This used to ICE when the first element is deferred-length character +! or could lead to wrong results. + +program pr103115 + implicit none + integer :: i + character(*), parameter :: expect(*) = [ "1","2","3","4","5" ] + character(5) :: abc = "12345" + character(5), parameter :: def = "12345" + character(:), dimension(:), allocatable :: list + character(:), dimension(:), allocatable :: titles + titles = ["1"] + titles = [ titles& + ,"2"& + ,"3"& + ,"4"& + ,"5"& ! used to ICE + ] + if (len (titles) /= 1 .or. size (titles) /= 5) stop 1 + if (any (titles /= expect)) stop 2 + titles = ["1"] + titles = [ titles, (char(48+i),i=2,5) ] + if (len (titles) /= 1 .or. size (titles) /= 5) stop 3 + if (any (titles /= expect)) stop 4 + titles = ["1"] + titles = [ titles, ("2345"(i:i),i=1,4) ] + if (len (titles) /= 1 .or. size (titles) /= 5) stop 5 + if (any (titles /= expect)) stop 6 + titles = ["1"] + titles = [ titles, (def(i:i),i=2,5) ] + if (len (titles) /= 1 .or. size (titles) /= 5) stop 7 + if (any (titles /= expect)) stop 8 + list = [ (char(48+i),i=1,5) ] + titles = [ list(1), (char(48+i),i=2,5) ] + if (len (titles) /= 1 .or. size (titles) /= 5) stop 9 + if (any (titles /= expect)) stop 10 + titles = ["1"] + titles = [ titles, (abc(i:i),i=2,5) ] + if (len (titles) /= 1 .or. size (titles) /= 5) stop 11 + if (any (titles /= expect)) stop 12 + + ! with typespec: + list = [ (char(48+i),i=1,5) ] + titles = [ character(2) :: list(1), (char(48+i),i=2,5) ] + if (len (titles) /= 2 .or. size (titles) /= 5) stop 13 + if (any (titles /= expect)) stop 14 + titles = ["1"] + titles = [ character(2) :: titles, (char(48+i),i=2,5) ] + if (len (titles) /= 2 .or. size (titles) /= 5) stop 15 + if (any (titles /= expect)) stop 16 + titles = ["1"] + titles = [ character(2) :: titles, (def(i:i),i=2,5) ] + if (len (titles) /= 2 .or. size (titles) /= 5) stop 17 + if (any (titles /= expect)) stop 18 + deallocate (titles, list) +end commit 9778ad559f8288a2965fe865b93eb93a45dd43d7 Author: GCC Administrator Date: Mon Jul 22 00:20:35 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index d1ac33f77fb..01bbf6ed5e1 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240721 +20240722 diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 40353ce2fa5..4673ec16567 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,15 @@ +2024-07-21 Harald Anlauf + + Backported from master: + 2024-07-19 Harald Anlauf + + PR fortran/103115 + * trans-array.cc (gfc_trans_array_constructor_value): If the first + element of an array constructor is deferred-length character and + therefore does not have an element size known at compile time, do + not try to collect subsequent constant elements into a constructor + for optimization. + 2024-07-20 Paul Thomas Backported from master: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 611c142e8e8..c3051734ea4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2024-07-21 Harald Anlauf + + Backported from master: + 2024-07-19 Harald Anlauf + + PR fortran/103115 + * gfortran.dg/string_array_constructor_4.f90: New test. + 2024-07-20 Paul Thomas Backported from master: commit 4ce7c81212c7819dfe6dbbe2399220fb12da6d71 Author: Maciej W. Rozycki Date: Sat Jun 29 23:26:55 2024 +0100 [PR115565] cse: Don't use a valid regno for non-register in comparison_qty Use INT_MIN rather than -1 in `comparison_qty' where a comparison is not with a register, because the value of -1 is actually a valid reference to register 0 in the case where it has not been assigned a quantity. Using -1 makes `REG_QTY (REGNO (folded_arg1)) == ent->comparison_qty' comparison in `fold_rtx' to incorrectly trigger in rare circumstances and return true for a memory reference, making CSE consider a comparison operation to evaluate to a constant expression and consequently make the resulting code incorrectly execute or fail to execute conditional blocks. This has caused a miscompilation of rwlock.c from LinuxThreads for the `alpha-linux-gnu' target, where `rwlock->__rw_writer != thread_self ()' expression (where `thread_self' returns the thread pointer via a PALcode call) has been decided to be always true (with `ent->comparison_qty' using -1 for a reference to to `rwlock->__rw_writer', while register 0 holding the thread pointer retrieved by `thread_self') and code for the false case has been optimized away where it mustn't have, causing program lockups. The issue has been observed as a regression from commit 08a692679fb8 ("Undefined cse.c behaviour causes 3.4 regression on HPUX"), , and up to commit 932ad4d9b550 ("Make CSE path following use the CFG"), , where CSE has been restructured sufficiently for the issue not to trigger with the original reproducer anymore. However the original bug remains and can trigger, because `comparison_qty' will still be assigned -1 for a memory reference and the `reg_qty' member of a `cse_reg_info_table' entry will still be assigned -1 for register 0 where the entry has not been assigned a quantity, e.g. at initialization. Use INT_MIN then as noted above, so that the value remains negative, for consistency with the REGNO_QTY_VALID_P macro (even though not used on `comparison_qty'), and then so that it should not ever match a valid negated register number, fixing the regression with commit 08a692679fb8. gcc/ PR rtl-optimization/115565 * cse.cc (record_jump_cond): Use INT_MIN rather than -1 for `comparison_qty' if !REG_P. (cherry picked from commit 69bc5fb97dc3fada81869e00fa65d39f7def6acf) diff --git a/gcc/cse.cc b/gcc/cse.cc index 8fbda4ecc86..9a399e312f1 100644 --- a/gcc/cse.cc +++ b/gcc/cse.cc @@ -239,7 +239,7 @@ static int next_qty; the constant being compared against, or zero if the comparison is not against a constant. `comparison_qty' holds the quantity being compared against when the result is known. If the comparison - is not with a register, `comparison_qty' is -1. */ + is not with a register, `comparison_qty' is INT_MIN. */ struct qty_table_elem { @@ -4068,7 +4068,7 @@ record_jump_cond (enum rtx_code code, machine_mode mode, rtx op0, else { ent->comparison_const = op1; - ent->comparison_qty = -1; + ent->comparison_qty = INT_MIN; } return; commit 8a470d7c424f67fa2e9e61197aea7d99efca6a9c Author: GCC Administrator Date: Tue Jul 23 00:20:58 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 409aab86aa8..a25e3b605d7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2024-07-22 Maciej W. Rozycki + + Backported from master: + 2024-06-29 Maciej W. Rozycki + + PR rtl-optimization/115565 + * cse.cc (record_jump_cond): Use INT_MIN rather than -1 for + `comparison_qty' if !REG_P. + 2024-07-20 Siddhesh Poyarekar Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 01bbf6ed5e1..833d506febb 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240722 +20240723 commit e504184f9175204bc66bf5a95a400bc4685f8ffc Author: Alexandre Oliva Date: Tue Jul 23 01:28:00 2024 -0300 [powerpc] [testsuite] reorder dg directives [PR106069] The dg-do directive appears after dg-require-effective-target in g++.target/powerpc/pr106069.C. That doesn't work the way that was presumably intended. Both of these directives set dg-do-what, but dg-do does so fully and unconditionally, overriding any decisions recorded there by earlier directives. Reorder the directives more canonically, so that both take effect. for gcc/testsuite/ChangeLog PR target/106069 * g++.target/powerpc/pr106069.C: Reorder dg directives. (cherry picked from commit ad65caa332bc7600caff6b9b5b29175b40d91e67) diff --git a/gcc/testsuite/g++.target/powerpc/pr106069.C b/gcc/testsuite/g++.target/powerpc/pr106069.C index 537207d2fe8..826379a4479 100644 --- a/gcc/testsuite/g++.target/powerpc/pr106069.C +++ b/gcc/testsuite/g++.target/powerpc/pr106069.C @@ -1,6 +1,6 @@ +/* { dg-do run } */ /* { dg-options "-O -fno-tree-forwprop -maltivec" } */ /* { dg-require-effective-target vmx_hw } */ -/* { dg-do run } */ typedef __attribute__ ((altivec (vector__))) unsigned native_simd_type; commit dec571e95cf47e21a1a60ed337e68e3474f57f7d Author: Haochen Jiang Date: Mon Jul 22 14:06:18 2024 +0800 i386: Change prefetchi output template For prefetchi instructions, RIP-relative address is explicitly mentioned for operand and assembler obeys that rule strictly. This makes instruction like: prefetchit0 bar got illegal for assembler, which should be a broad usage for prefetchi. Change to %a to explicitly add (%rip) after function label to make it legal in assembler so that it could pass to linker to get the real address. gcc/ChangeLog: * config/i386/i386.md (prefetchi): Change to %a. gcc/testsuite/ChangeLog: * gcc.target/i386/prefetchi-1.c: Check (%rip). diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index b4b39865d67..a224c9f940e 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -24291,7 +24291,7 @@ "TARGET_PREFETCHI && TARGET_64BIT" { static const char * const patterns[2] = { - "prefetchit1\t%0", "prefetchit0\t%0" + "prefetchit1\t%a0", "prefetchit0\t%a0" }; int locality = INTVAL (operands[1]); diff --git a/gcc/testsuite/gcc.target/i386/prefetchi-1.c b/gcc/testsuite/gcc.target/i386/prefetchi-1.c index 80f25e70e8e..03dfdc55e86 100644 --- a/gcc/testsuite/gcc.target/i386/prefetchi-1.c +++ b/gcc/testsuite/gcc.target/i386/prefetchi-1.c @@ -1,7 +1,7 @@ /* { dg-do compile { target { ! ia32 } } } */ /* { dg-options "-mprefetchi -O2" } */ -/* { dg-final { scan-assembler-times "\[ \\t\]+prefetchit0\[ \\t\]+" 2 } } */ -/* { dg-final { scan-assembler-times "\[ \\t\]+prefetchit1\[ \\t\]+" 2 } } */ +/* { dg-final { scan-assembler-times "\[ \\t\]+prefetchit0\[ \\t\]+bar\\(%rip\\)" 2 } } */ +/* { dg-final { scan-assembler-times "\[ \\t\]+prefetchit1\[ \\t\]+bar\\(%rip\\)" 2 } } */ #include commit b35276655e6767a6e037e58edfa4738317498337 Author: Richard Biener Date: Mon Jul 15 13:01:24 2024 +0200 Fixup unaligned load/store cost for znver4 Currently unaligned YMM and ZMM load and store costs are cheaper than aligned which causes the vectorizer to purposely mis-align accesses by adding an alignment prologue. It looks like the unaligned costs were simply left untouched from znver3 where they equate the aligned costs when tweaking aligned costs for znver4. The following makes the unaligned costs equal to the aligned costs. This avoids the miscompile seen in PR115843 but it's of course not a real fix for the issue uncovered there. But it makes it qualify as a regression fix. PR tree-optimization/115843 * config/i386/x86-tune-costs.h (znver4_cost): Update unaligned load and store cost from the aligned costs. (cherry picked from commit 1e3aa9c9278db69d4bdb661a750a7268789188d6) diff --git a/gcc/config/i386/x86-tune-costs.h b/gcc/config/i386/x86-tune-costs.h index 4f7a67ca5c5..14c5507a601 100644 --- a/gcc/config/i386/x86-tune-costs.h +++ b/gcc/config/i386/x86-tune-costs.h @@ -1924,8 +1924,8 @@ struct processor_costs znver4_cost = { in 32bit, 64bit, 128bit, 256bit and 512bit */ {8, 8, 8, 12, 12}, /* cost of storing SSE register in 32bit, 64bit, 128bit, 256bit and 512bit */ - {6, 6, 6, 6, 6}, /* cost of unaligned loads. */ - {8, 8, 8, 8, 8}, /* cost of unaligned stores. */ + {6, 6, 10, 10, 12}, /* cost of unaligned loads. */ + {8, 8, 8, 12, 12}, /* cost of unaligned stores. */ 2, 2, 2, /* cost of moving XMM,YMM,ZMM register. */ 6, /* cost of moving SSE register to integer. */ commit 0575d3b81532858cd475b17b23a28f1cf0097802 Author: GCC Administrator Date: Wed Jul 24 00:21:39 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a25e3b605d7..b22225d04b5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2024-07-23 Richard Biener + + Backported from master: + 2024-07-16 Richard Biener + + PR tree-optimization/115843 + * config/i386/x86-tune-costs.h (znver4_cost): Update unaligned + load and store cost from the aligned costs. + +2024-07-23 Haochen Jiang + + * config/i386/i386.md (prefetchi): Change to %a. + 2024-07-22 Maciej W. Rozycki Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 833d506febb..d050dd67721 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240723 +20240724 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c3051734ea4..8372c75a9e6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,15 @@ +2024-07-23 Haochen Jiang + + * gcc.target/i386/prefetchi-1.c: Check (%rip). + +2024-07-23 Alexandre Oliva + + Backported from master: + 2024-07-23 Alexandre Oliva + + PR target/106069 + * g++.target/powerpc/pr106069.C: Reorder dg directives. + 2024-07-21 Harald Anlauf Backported from master: commit 9bbdec4d94f9120b75d03a610e0338bb05ee40f7 Author: Peter Bergner Date: Fri Jun 7 16:03:08 2024 -0500 rs6000: Update ELFv2 stack frame comment showing the correct ROP save location The ELFv2 stack frame layout comment in rs6000-logue.cc shows the ROP hash save slot in the wrong location. Update the comment to show the correct ROP hash save location in the frame. 2024-06-07 Peter Bergner gcc/ * config/rs6000/rs6000-logue.cc (rs6000_stack_info): Update comment. (cherry picked from commit e91cf26a954a5c1bf431e36f3a1e69f94e9fa4fe) diff --git a/gcc/config/rs6000/rs6000-logue.cc b/gcc/config/rs6000/rs6000-logue.cc index baadbbd692e..ddd46ae459a 100644 --- a/gcc/config/rs6000/rs6000-logue.cc +++ b/gcc/config/rs6000/rs6000-logue.cc @@ -591,21 +591,21 @@ rs6000_savres_strategy (rs6000_stack_t *info, +---------------------------------------+ | Parameter save area (+padding*) (P) | 32 +---------------------------------------+ - | Optional ROP hash slot (R) | 32+P + | Alloca space (A) | 32+P +---------------------------------------+ - | Alloca space (A) | 32+P+R + | Local variable space (L) | 32+P+A +---------------------------------------+ - | Local variable space (L) | 32+P+R+A + | Optional ROP hash slot (R) | 32+P+A+L +---------------------------------------+ - | Save area for AltiVec registers (W) | 32+P+R+A+L + | Save area for AltiVec registers (W) | 32+P+A+L+R +---------------------------------------+ - | AltiVec alignment padding (Y) | 32+P+R+A+L+W + | AltiVec alignment padding (Y) | 32+P+A+L+R+W +---------------------------------------+ - | Save area for GP registers (G) | 32+P+R+A+L+W+Y + | Save area for GP registers (G) | 32+P+A+L+R+W+Y +---------------------------------------+ - | Save area for FP registers (F) | 32+P+R+A+L+W+Y+G + | Save area for FP registers (F) | 32+P+A+L+R+W+Y+G +---------------------------------------+ - old SP->| back chain to caller's caller | 32+P+R+A+L+W+Y+G+F + old SP->| back chain to caller's caller | 32+P+A+L+R+W+Y+G+F +---------------------------------------+ * If the alloca area is present, the parameter save area is commit bc51e5abcd9cf9a4f74384f2df7c0c8c5ae07c1c Author: Peter Bergner Date: Fri Jun 14 14:36:20 2024 -0500 rs6000: Compute rop_hash_save_offset for non-Altivec compiles [PR115389] We currently only compute the offset for the ROP hash save location in the stack frame for Altivec compiles. For non-Altivec compiles when we emit ROP mitigation instructions, we use a default offset of zero which corresponds to the backchain save location which will get clobbered on any call. The fix is to compute the ROP hash save location for all compiles. 2024-06-14 Peter Bergner gcc/ PR target/115389 * config/rs6000/rs6000-logue.cc (rs6000_stack_info): Compute rop_hash_save_offset for non-Altivec compiles. gcc/testsuite PR target/115389 * gcc.target/powerpc/pr115389.c: New test. (cherry picked from commit c70eea0dba5f223d49c80cfb3e80e87b74330aac) diff --git a/gcc/config/rs6000/rs6000-logue.cc b/gcc/config/rs6000/rs6000-logue.cc index ddd46ae459a..d38b90b6107 100644 --- a/gcc/config/rs6000/rs6000-logue.cc +++ b/gcc/config/rs6000/rs6000-logue.cc @@ -817,17 +817,16 @@ rs6000_stack_info (void) gcc_assert (info->altivec_size == 0 || info->altivec_save_offset % 16 == 0); - /* Adjust for AltiVec case. */ - info->ehrd_offset = info->altivec_save_offset - ehrd_size; - /* Adjust for ROP protection. */ info->rop_hash_save_offset = info->altivec_save_offset - info->rop_hash_size; - info->ehrd_offset -= info->rop_hash_size; } else - info->ehrd_offset = info->gp_save_offset - ehrd_size; + /* Adjust for ROP protection. */ + info->rop_hash_save_offset + = info->gp_save_offset - info->rop_hash_size; + info->ehrd_offset = info->rop_hash_save_offset - ehrd_size; info->ehcr_offset = info->ehrd_offset - ehcr_size; info->cr_save_offset = reg_size; /* first word when 64-bit. */ info->lr_save_offset = 2*reg_size; diff --git a/gcc/testsuite/gcc.target/powerpc/pr115389.c b/gcc/testsuite/gcc.target/powerpc/pr115389.c new file mode 100644 index 00000000000..a091ee8a1be --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr115389.c @@ -0,0 +1,17 @@ +/* PR target/115389 */ +/* { dg-do assemble } */ +/* { dg-options "-O2 -mdejagnu-cpu=power10 -mrop-protect -mno-vsx -mno-altivec -mabi=no-altivec -save-temps" } */ +/* { dg-require-effective-target rop_ok } */ + +/* Verify we do not emit invalid offsets for our ROP insns. */ + +extern void foo (void); +long +bar (void) +{ + foo (); + return 0; +} + +/* { dg-final { scan-assembler-times {\mhashst\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mhashchk\M} 1 } } */ commit 77fd352a47137d79e6b7a480503ce4368f13c3e5 Author: Peter Bergner Date: Wed Jun 19 16:07:29 2024 -0500 rs6000: ROP - Emit hashst and hashchk insns on Power8 and later [PR114759] We currently only emit the ROP-protect hash* insns for Power10, where the insns were added to the architecture. We want to emit them for earlier cpus (where they operate as NOPs), so that if those older binaries are ever executed on a Power10, then they'll be protected from ROP attacks. Binutils accepts hashst and hashchk back to Power8, so change GCC to emit them for Power8 and later. This matches clang's behavior. 2024-06-19 Peter Bergner gcc/ PR target/114759 * config/rs6000/rs6000-logue.cc (rs6000_stack_info): Use TARGET_POWER8. (rs6000_emit_prologue): Likewise. * config/rs6000/rs6000.md (hashchk): Likewise. (hashst): Likewise. Fix whitespace. gcc/testsuite/ PR target/114759 * gcc.target/powerpc/pr114759-2.c: New test. * lib/target-supports.exp (rop_ok): Use check_effective_target_has_arch_pwr8. (cherry picked from commit a05c3d23d1e1c8d2971b123804fc7a61a3561adb) diff --git a/gcc/config/rs6000/rs6000-logue.cc b/gcc/config/rs6000/rs6000-logue.cc index d38b90b6107..9e6b4ca5533 100644 --- a/gcc/config/rs6000/rs6000-logue.cc +++ b/gcc/config/rs6000/rs6000-logue.cc @@ -716,7 +716,7 @@ rs6000_stack_info (void) info->calls_p = (!crtl->is_leaf || cfun->machine->ra_needs_full_frame); info->rop_hash_size = 0; - if (TARGET_POWER10 + if (TARGET_POWER8 && info->calls_p && DEFAULT_ABI == ABI_ELFv2 && rs6000_rop_protect) @@ -3275,7 +3275,7 @@ rs6000_emit_prologue (void) /* NOTE: The hashst isn't needed if we're going to do a sibcall, but there's no way to know that here. Harmless except for performance, of course. */ - if (TARGET_POWER10 && rs6000_rop_protect && info->rop_hash_size != 0) + if (TARGET_POWER8 && rs6000_rop_protect && info->rop_hash_size != 0) { gcc_assert (DEFAULT_ABI == ABI_ELFv2); rtx stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM); @@ -5054,7 +5054,7 @@ rs6000_emit_epilogue (enum epilogue_type epilogue_type) /* The ROP hash check must occur after the stack pointer is restored (since the hash involves r1), and is not performed for a sibcall. */ - if (TARGET_POWER10 + if (TARGET_POWER8 && rs6000_rop_protect && info->rop_hash_size != 0 && epilogue_type != EPILOGUE_TYPE_SIBCALL) diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 8d8118197da..79aaf490837 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -15665,9 +15665,9 @@ (define_insn "hashst" [(set (match_operand:DI 0 "simple_offsettable_mem_operand" "=m") - (unspec_volatile:DI [(match_operand:DI 1 "int_reg_operand" "r")] + (unspec_volatile:DI [(match_operand:DI 1 "int_reg_operand" "r")] UNSPEC_HASHST))] - "TARGET_POWER10 && rs6000_rop_protect" + "TARGET_POWER8 && rs6000_rop_protect" { static char templ[32]; const char *p = rs6000_privileged ? "p" : ""; @@ -15680,7 +15680,7 @@ [(unspec_volatile [(match_operand:DI 0 "int_reg_operand" "r") (match_operand:DI 1 "simple_offsettable_mem_operand" "m")] UNSPEC_HASHCHK)] - "TARGET_POWER10 && rs6000_rop_protect" + "TARGET_POWER8 && rs6000_rop_protect" { static char templ[32]; const char *p = rs6000_privileged ? "p" : ""; diff --git a/gcc/testsuite/gcc.target/powerpc/pr114759-2.c b/gcc/testsuite/gcc.target/powerpc/pr114759-2.c new file mode 100644 index 00000000000..3881ebd416e --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr114759-2.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mdejagnu-cpu=power8 -mrop-protect" } */ +/* { dg-require-effective-target rop_ok } Only enable on supported ABIs. */ + +/* Verify we generate ROP-protect hash insns when compiling for Power8. */ + +extern void foo (void); + +int +bar (void) +{ + foo (); + return 5; +} + +/* { dg-final { scan-assembler-times {\mhashst\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mhashchk\M} 1 } } */ diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index be8ddc8e0f8..c81313ea717 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -6919,7 +6919,7 @@ proc check_effective_target_powerpc_elfv2 { } { # Return 1 if this is a PowerPC target supporting -mrop-protect proc check_effective_target_rop_ok { } { - return [check_effective_target_power10_ok] && [check_effective_target_powerpc_elfv2] + return [check_effective_target_has_arch_pwr8] && [check_effective_target_powerpc_elfv2] } # The VxWorks SPARC simulator accepts only EM_SPARC executables and commit 63b1b3e23c3c589c2859d481705dc706cbff35a1 Author: Peter Bergner Date: Mon Jul 15 16:57:32 2024 -0500 rs6000: Error on CPUs and ABIs that don't support the ROP protection insns [PR114759] We currently silently ignore the -mrop-protect option for old CPUs we don't support with the ROP hash insns, but we throw an error for unsupported ABIs. This patch treats unsupported CPUs and ABIs similarly by throwing an error both both. This matches clang behavior and allows us to simplify our tests in the code that generates our prologue and epilogue code. 2024-06-26 Peter Bergner gcc/ PR target/114759 * config/rs6000/rs6000.cc (rs6000_option_override_internal): Disallow CPUs and ABIs that do no support the ROP protection insns. * config/rs6000/rs6000-logue.cc (rs6000_stack_info): Remove now unneeded tests. (rs6000_emit_prologue): Likewise. Remove unneeded gcc_assert. (rs6000_emit_epilogue): Likewise. * config/rs6000/rs6000.md: Likewise. gcc/testsuite/ PR target/114759 * gcc.target/powerpc/pr114759-3.c: New test. (cherry picked from commit 6f2bab9b5d1ce1914c748b7dcd8638dafaa98df7) diff --git a/gcc/config/rs6000/rs6000-logue.cc b/gcc/config/rs6000/rs6000-logue.cc index 9e6b4ca5533..208404e6864 100644 --- a/gcc/config/rs6000/rs6000-logue.cc +++ b/gcc/config/rs6000/rs6000-logue.cc @@ -716,17 +716,11 @@ rs6000_stack_info (void) info->calls_p = (!crtl->is_leaf || cfun->machine->ra_needs_full_frame); info->rop_hash_size = 0; - if (TARGET_POWER8 - && info->calls_p - && DEFAULT_ABI == ABI_ELFv2 - && rs6000_rop_protect) + /* If we want ROP protection and this function makes a call, indicate + we need to create a stack slot to save the hashed return address in. */ + if (rs6000_rop_protect + && info->calls_p) info->rop_hash_size = 8; - else if (rs6000_rop_protect && DEFAULT_ABI != ABI_ELFv2) - { - /* We can't check this in rs6000_option_override_internal since - DEFAULT_ABI isn't established yet. */ - error ("%qs requires the ELFv2 ABI", "-mrop-protect"); - } /* Determine if we need to save the condition code registers. */ if (save_reg_p (CR2_REGNO) @@ -3275,9 +3269,8 @@ rs6000_emit_prologue (void) /* NOTE: The hashst isn't needed if we're going to do a sibcall, but there's no way to know that here. Harmless except for performance, of course. */ - if (TARGET_POWER8 && rs6000_rop_protect && info->rop_hash_size != 0) + if (info->rop_hash_size) { - gcc_assert (DEFAULT_ABI == ABI_ELFv2); rtx stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM); rtx addr = gen_rtx_PLUS (Pmode, stack_ptr, GEN_INT (info->rop_hash_save_offset)); @@ -5054,12 +5047,9 @@ rs6000_emit_epilogue (enum epilogue_type epilogue_type) /* The ROP hash check must occur after the stack pointer is restored (since the hash involves r1), and is not performed for a sibcall. */ - if (TARGET_POWER8 - && rs6000_rop_protect - && info->rop_hash_size != 0 + if (info->rop_hash_size && epilogue_type != EPILOGUE_TYPE_SIBCALL) { - gcc_assert (DEFAULT_ABI == ABI_ELFv2); rtx stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM); rtx addr = gen_rtx_PLUS (Pmode, stack_ptr, GEN_INT (info->rop_hash_save_offset)); diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index 29475ffcb7f..2b876c90e6f 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -4850,6 +4850,18 @@ rs6000_option_override_internal (bool global_init_p) } } + /* We only support ROP protection on certain targets. */ + if (rs6000_rop_protect) + { + /* Disallow CPU targets we don't support. */ + if (!TARGET_POWER8) + error ("%<-mrop-protect%> requires %<-mcpu=power8%> or later"); + + /* Disallow ABI targets we don't support. */ + if (DEFAULT_ABI != ABI_ELFv2) + error ("%<-mrop-protect%> requires the ELFv2 ABI"); + } + /* Initialize all of the registers. */ rs6000_init_hard_regno_mode_ok (global_init_p); diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 79aaf490837..7e6fcc45a20 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -15667,7 +15667,7 @@ [(set (match_operand:DI 0 "simple_offsettable_mem_operand" "=m") (unspec_volatile:DI [(match_operand:DI 1 "int_reg_operand" "r")] UNSPEC_HASHST))] - "TARGET_POWER8 && rs6000_rop_protect" + "rs6000_rop_protect" { static char templ[32]; const char *p = rs6000_privileged ? "p" : ""; @@ -15680,7 +15680,7 @@ [(unspec_volatile [(match_operand:DI 0 "int_reg_operand" "r") (match_operand:DI 1 "simple_offsettable_mem_operand" "m")] UNSPEC_HASHCHK)] - "TARGET_POWER8 && rs6000_rop_protect" + "rs6000_rop_protect" { static char templ[32]; const char *p = rs6000_privileged ? "p" : ""; diff --git a/gcc/testsuite/gcc.target/powerpc/pr114759-3.c b/gcc/testsuite/gcc.target/powerpc/pr114759-3.c new file mode 100644 index 00000000000..6770a9aec3b --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr114759-3.c @@ -0,0 +1,19 @@ +/* PR target/114759 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -mdejagnu-cpu=power7 -mrop-protect" } */ + +/* Verify we emit an error if we use -mrop-protect with an unsupported cpu. */ + +extern void foo (void); + +int +bar (void) +{ + foo (); + return 5; +} + +/* The correct line number is in the preamble to the error message, not + in the final line (which is all that dg-error inspects). Hence, we have + to tell dg-error to ignore the line number. */ +/* { dg-error "'-mrop-protect' requires '-mcpu=power8'" "PR114759" { target *-*-* } 0 } */ commit 9a4603d323d890dfab6d27ede17dc904abdccd9b Author: Peter Bergner Date: Thu Jul 18 18:01:46 2024 -0500 rs6000: Catch unsupported ABI errors when using -mrop-protect [PR114759,PR115988] 2024-07-18 Peter Bergner gcc/testsuite/ PR target/114759 PR target/115988 * gcc.target/powerpc/pr114759-3.c: Catch unsupported ABI errors. (cherry picked from commit b2f47a5c1d5204131660ea0372a08e692df8844e) diff --git a/gcc/testsuite/gcc.target/powerpc/pr114759-3.c b/gcc/testsuite/gcc.target/powerpc/pr114759-3.c index 6770a9aec3b..e2f1d42e111 100644 --- a/gcc/testsuite/gcc.target/powerpc/pr114759-3.c +++ b/gcc/testsuite/gcc.target/powerpc/pr114759-3.c @@ -2,7 +2,8 @@ /* { dg-do compile } */ /* { dg-options "-O2 -mdejagnu-cpu=power7 -mrop-protect" } */ -/* Verify we emit an error if we use -mrop-protect with an unsupported cpu. */ +/* Verify we emit an error if we use -mrop-protect with an unsupported cpu + or ABI. */ extern void foo (void); @@ -17,3 +18,4 @@ bar (void) in the final line (which is all that dg-error inspects). Hence, we have to tell dg-error to ignore the line number. */ /* { dg-error "'-mrop-protect' requires '-mcpu=power8'" "PR114759" { target *-*-* } 0 } */ +/* { dg-error "'-mrop-protect' requires the ELFv2 ABI" "PR114759" { target { ! rop_ok } } 0 } */ commit 46d68bc90688745fc9f25795c371ecaf21e18b56 Author: Jonathan Wakely Date: Wed Jul 24 11:32:22 2024 +0100 libstdc++: Fix std::vector for -std=gnu++14 -fconcepts [PR116070] This questionable combination of flags causes a number of errors. This one in std::vector needs to be fixed in the gcc-13 branch so I'm committing it separately to simplify backporting. libstdc++-v3/ChangeLog: PR libstdc++/116070 * include/bits/stl_bvector.h: Check feature test macro before using is_default_constructible_v. (cherry picked from commit 5fc9c40fea2481e56bf7bcc994cb40c71e28abb8) diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h index e18de7c62aa..63e416053e0 100644 --- a/libstdc++-v3/include/bits/stl_bvector.h +++ b/libstdc++-v3/include/bits/stl_bvector.h @@ -593,7 +593,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _GLIBCXX20_CONSTEXPR _Bvector_impl() _GLIBCXX_NOEXCEPT_IF( is_nothrow_default_constructible<_Bit_alloc_type>::value) -#if __cpp_concepts +#if __cpp_concepts && __cpp_lib_type_trait_variable_templates requires is_default_constructible_v<_Bit_alloc_type> #endif : _Bit_alloc_type() commit 58b3e55cef20a489a83a50151d74f12dd57e9a59 Author: GCC Administrator Date: Thu Jul 25 00:22:12 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b22225d04b5..654f63926e2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,46 @@ +2024-07-24 Peter Bergner + + Backported from master: + 2024-07-17 Peter Bergner + + PR target/114759 + * config/rs6000/rs6000.cc (rs6000_option_override_internal): Disallow + CPUs and ABIs that do no support the ROP protection insns. + * config/rs6000/rs6000-logue.cc (rs6000_stack_info): Remove now + unneeded tests. + (rs6000_emit_prologue): Likewise. + Remove unneeded gcc_assert. + (rs6000_emit_epilogue): Likewise. + * config/rs6000/rs6000.md: Likewise. + +2024-07-24 Peter Bergner + + Backported from master: + 2024-07-17 Peter Bergner + + PR target/114759 + * config/rs6000/rs6000-logue.cc (rs6000_stack_info): Use TARGET_POWER8. + (rs6000_emit_prologue): Likewise. + * config/rs6000/rs6000.md (hashchk): Likewise. + (hashst): Likewise. + Fix whitespace. + +2024-07-24 Peter Bergner + + Backported from master: + 2024-06-17 Peter Bergner + + PR target/115389 + * config/rs6000/rs6000-logue.cc (rs6000_stack_info): Compute + rop_hash_save_offset for non-Altivec compiles. + +2024-07-24 Peter Bergner + + Backported from master: + 2024-06-08 Peter Bergner + + * config/rs6000/rs6000-logue.cc (rs6000_stack_info): Update comment. + 2024-07-23 Richard Biener Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index d050dd67721..503038db09c 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240724 +20240725 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8372c75a9e6..a950a5a4b28 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,38 @@ +2024-07-24 Peter Bergner + + Backported from master: + 2024-07-19 Peter Bergner + + PR target/114759 + PR target/115988 + * gcc.target/powerpc/pr114759-3.c: Catch unsupported ABI errors. + +2024-07-24 Peter Bergner + + Backported from master: + 2024-07-17 Peter Bergner + + PR target/114759 + * gcc.target/powerpc/pr114759-3.c: New test. + +2024-07-24 Peter Bergner + + Backported from master: + 2024-07-17 Peter Bergner + + PR target/114759 + * gcc.target/powerpc/pr114759-2.c: New test. + * lib/target-supports.exp (rop_ok): Use + check_effective_target_has_arch_pwr8. + +2024-07-24 Peter Bergner + + Backported from master: + 2024-06-17 Peter Bergner + + PR target/115389 + * gcc.target/powerpc/pr115389.c: New test. + 2024-07-23 Haochen Jiang * gcc.target/i386/prefetchi-1.c: Check (%rip). diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 6307b1c0e76..c6296e97404 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,12 @@ +2024-07-24 Jonathan Wakely + + Backported from master: + 2024-07-24 Jonathan Wakely + + PR libstdc++/116070 + * include/bits/stl_bvector.h: Check feature test macro before + using is_default_constructible_v. + 2024-07-12 Jonathan Wakely Backported from master: commit f280772c08f5101fee39bf4ec65c19015edacb43 Author: GCC Administrator Date: Fri Jul 26 00:20:23 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 503038db09c..c8f8a5f000a 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240725 +20240726 commit 4e03c89072daa53d25014a306b2878867952d475 Author: GCC Administrator Date: Sat Jul 27 00:20:29 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index c8f8a5f000a..3eff065eb0c 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240726 +20240727 commit 920adcb55228a5dbe0fe8183e8cc46c8cf7af93c Author: GCC Administrator Date: Sun Jul 28 00:20:58 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 3eff065eb0c..65b8ef17038 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240727 +20240728 commit 69272e4eef7e6820c2bdf990154d7ad83f0ebf4c Author: GCC Administrator Date: Mon Jul 29 00:20:57 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 65b8ef17038..d1b40fa5c77 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240728 +20240729 commit bb15c4cf21dbe76df5a225342d1fbe8ecd3c7971 Author: Haochen Jiang Date: Thu Jul 25 16:12:20 2024 +0800 i386: Fix AVX512 intrin macro typo There are several typo in AVX512 intrins macro define. Correct them to solve errors when compiled with -O0. gcc/ChangeLog: * config/i386/avx512dqintrin.h (_mm_mask_fpclass_ss_mask): Correct operand order. (_mm_mask_fpclass_sd_mask): Ditto. (_mm256_maskz_reduce_round_ss): Use __builtin_ia32_reducess_mask_round instead of __builtin_ia32_reducesd_mask_round. (_mm_reduce_round_sd): Use -1 as mask since it is non-mask. (_mm_reduce_round_ss): Ditto. * config/i386/avx512vlbwintrin.h (_mm256_mask_alignr_epi8): Correct operand usage. (_mm_mask_alignr_epi8): Ditto. * config/i386/avx512vlintrin.h (_mm_mask_alignr_epi64): Ditto. gcc/testsuite/ChangeLog: * gcc.target/i386/avx512bw-vpalignr-1b.c: New test. * gcc.target/i386/avx512dq-vfpclasssd-1b.c: Ditto. * gcc.target/i386/avx512dq-vfpclassss-1b.c: Ditto. * gcc.target/i386/avx512dq-vreducesd-1b.c: Ditto. * gcc.target/i386/avx512dq-vreducess-1b.c: Ditto. * gcc.target/i386/avx512vl-valignq-1b.c: Ditto. diff --git a/gcc/config/i386/avx512dqintrin.h b/gcc/config/i386/avx512dqintrin.h index 93900a0b5c7..4383ff14670 100644 --- a/gcc/config/i386/avx512dqintrin.h +++ b/gcc/config/i386/avx512dqintrin.h @@ -2800,11 +2800,11 @@ _mm512_fpclass_ps_mask (__m512 __A, const int __imm) ((__mmask8) __builtin_ia32_fpclasssd_mask ((__v2df) (__m128d) (X), \ (int) (C), (__mmask8) (-1))) \ -#define _mm_mask_fpclass_ss_mask(X, C, U) \ +#define _mm_mask_fpclass_ss_mask(U, X, C) \ ((__mmask8) __builtin_ia32_fpclassss_mask ((__v4sf) (__m128) (X), \ (int) (C), (__mmask8) (U))) -#define _mm_mask_fpclass_sd_mask(X, C, U) \ +#define _mm_mask_fpclass_sd_mask(U, X, C) \ ((__mmask8) __builtin_ia32_fpclasssd_mask ((__v2df) (__m128d) (X), \ (int) (C), (__mmask8) (U))) @@ -2839,8 +2839,9 @@ _mm512_fpclass_ps_mask (__m512 __A, const int __imm) (__mmask8)(U))) #define _mm_reduce_round_sd(A, B, C, R) \ - ((__m128d) __builtin_ia32_reducesd_round ((__v2df)(__m128d)(A), \ - (__v2df)(__m128d)(B), (int)(C), (__mmask8)(U), (int)(R))) + ((__m128d) __builtin_ia32_reducesd_mask_round ((__v2df)(__m128d)(A), \ + (__v2df)(__m128d)(B), (int)(C), (__v2df) _mm_avx512_setzero_pd (), \ + (__mmask8)(-1), (int)(R))) #define _mm_mask_reduce_round_sd(W, U, A, B, C, R) \ ((__m128d) __builtin_ia32_reducesd_mask_round ((__v2df)(__m128d)(A), \ @@ -2867,8 +2868,9 @@ _mm512_fpclass_ps_mask (__m512 __A, const int __imm) (__mmask8)(U))) #define _mm_reduce_round_ss(A, B, C, R) \ - ((__m128) __builtin_ia32_reducess_round ((__v4sf)(__m128)(A), \ - (__v4sf)(__m128)(B), (int)(C), (__mmask8)(U), (int)(R))) + ((__m128) __builtin_ia32_reducess_mask_round ((__v4sf)(__m128)(A), \ + (__v4sf)(__m128)(B), (int)(C), (__v4sf) _mm_avx512_setzero_ps (), \ + (__mmask8)(-1), (int)(R))) #define _mm_mask_reduce_round_ss(W, U, A, B, C, R) \ ((__m128) __builtin_ia32_reducess_mask_round ((__v4sf)(__m128)(A), \ @@ -2876,7 +2878,7 @@ _mm512_fpclass_ps_mask (__m512 __A, const int __imm) (__mmask8)(U), (int)(R))) #define _mm_maskz_reduce_round_ss(U, A, B, C, R) \ - ((__m128) __builtin_ia32_reducesd_mask_round ((__v4sf)(__m128)(A), \ + ((__m128) __builtin_ia32_reducess_mask_round ((__v4sf)(__m128)(A), \ (__v4sf)(__m128)(B), (int)(C), (__v4sf) _mm_setzero_ps (), \ (__mmask8)(U), (int)(R))) diff --git a/gcc/config/i386/avx512vlbwintrin.h b/gcc/config/i386/avx512vlbwintrin.h index 0232783a362..43486527652 100644 --- a/gcc/config/i386/avx512vlbwintrin.h +++ b/gcc/config/i386/avx512vlbwintrin.h @@ -1839,7 +1839,7 @@ _mm_maskz_slli_epi16 (__mmask8 __U, __m128i __A, int __B) #define _mm256_mask_alignr_epi8(W, U, X, Y, N) \ ((__m256i) __builtin_ia32_palignr256_mask ((__v4di)(__m256i)(X), \ (__v4di)(__m256i)(Y), (int)((N) * 8), \ - (__v4di)(__m256i)(X), (__mmask32)(U))) + (__v4di)(__m256i)(W), (__mmask32)(U))) #define _mm256_mask_srli_epi16(W, U, A, B) \ ((__m256i) __builtin_ia32_psrlwi256_mask ((__v16hi)(__m256i)(A), \ @@ -1922,7 +1922,7 @@ _mm_maskz_slli_epi16 (__mmask8 __U, __m128i __A, int __B) #define _mm_mask_alignr_epi8(W, U, X, Y, N) \ ((__m128i) __builtin_ia32_palignr128_mask ((__v2di)(__m128i)(X), \ (__v2di)(__m128i)(Y), (int)((N) * 8), \ - (__v2di)(__m128i)(X), (__mmask16)(U))) + (__v2di)(__m128i)(W), (__mmask16)(U))) #define _mm_maskz_alignr_epi8(U, X, Y, N) \ ((__m128i) __builtin_ia32_palignr128_mask ((__v2di)(__m128i)(X), \ diff --git a/gcc/config/i386/avx512vlintrin.h b/gcc/config/i386/avx512vlintrin.h index 758b71a9dbd..1243335b3da 100644 --- a/gcc/config/i386/avx512vlintrin.h +++ b/gcc/config/i386/avx512vlintrin.h @@ -13609,7 +13609,7 @@ _mm256_permutex_pd (__m256d __X, const int __M) #define _mm_mask_alignr_epi64(W, U, X, Y, C) \ ((__m128i)__builtin_ia32_alignq128_mask ((__v2di)(__m128i)(X), \ - (__v2di)(__m128i)(Y), (int)(C), (__v2di)(__m128i)(X), (__mmask8)-1)) + (__v2di)(__m128i)(Y), (int)(C), (__v2di)(__m128i)(W), (__mmask8)(U))) #define _mm_maskz_alignr_epi64(U, X, Y, C) \ ((__m128i)__builtin_ia32_alignq128_mask ((__v2di)(__m128i)(X), \ diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-vpalignr-1b.c b/gcc/testsuite/gcc.target/i386/avx512bw-vpalignr-1b.c new file mode 100644 index 00000000000..2b42aa90b91 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512bw-vpalignr-1b.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O0 -mavx512bw -mavx512vl" } */ +/* { dg-final { scan-assembler-times "vpalignr\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "vpalignr\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */ + +#include + +volatile __m256i y; +volatile __m128i x; +volatile __mmask32 m2; +volatile __mmask16 m3; + +void extern +avx512bw_test (void) +{ + y = _mm256_mask_alignr_epi8 (y, m2, y, y, 10); + x = _mm_mask_alignr_epi8 (x, m3, x, x, 10); +} diff --git a/gcc/testsuite/gcc.target/i386/avx512dq-vfpclasssd-1b.c b/gcc/testsuite/gcc.target/i386/avx512dq-vfpclasssd-1b.c new file mode 100644 index 00000000000..8c7f96fb7a7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512dq-vfpclasssd-1b.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-mavx512dq -O0" } */ +/* { dg-final { scan-assembler-times "vfpclasssd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[0-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */ + +#include + +volatile __m128d x128; +volatile __mmask8 m8; + +void extern +avx512dq_test (void) +{ + m8 = _mm_mask_fpclass_sd_mask (m8, x128, 13); +} diff --git a/gcc/testsuite/gcc.target/i386/avx512dq-vfpclassss-1b.c b/gcc/testsuite/gcc.target/i386/avx512dq-vfpclassss-1b.c new file mode 100644 index 00000000000..3196fd60d64 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512dq-vfpclassss-1b.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-mavx512dq -O0" } */ +/* { dg-final { scan-assembler-times "vfpclassss\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[0-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */ + +#include + +volatile __m128 x128; +volatile __mmask8 m8; + +void extern +avx512dq_test (void) +{ + m8 = _mm_mask_fpclass_ss_mask (m8, x128, 13); +} diff --git a/gcc/testsuite/gcc.target/i386/avx512dq-vreducesd-1b.c b/gcc/testsuite/gcc.target/i386/avx512dq-vreducesd-1b.c new file mode 100644 index 00000000000..9ae8259d373 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512dq-vreducesd-1b.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-mavx512dq -O0" } */ +/* { dg-final { scan-assembler-times "vreducesd\[ \\t\]+\[^\{\n\]*\{sae\}\[^\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */ + +#include + +#define IMM 123 + +volatile __m128d x1, x2, xx1, xx2; +volatile __mmask8 m; + +void extern +avx512dq_test (void) +{ + xx1 = _mm_reduce_round_sd (xx1, xx2, IMM, _MM_FROUND_NO_EXC); +} diff --git a/gcc/testsuite/gcc.target/i386/avx512dq-vreducess-1b.c b/gcc/testsuite/gcc.target/i386/avx512dq-vreducess-1b.c new file mode 100644 index 00000000000..47bf48fb617 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512dq-vreducess-1b.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-mavx512dq -O0" } */ +/* { dg-final { scan-assembler-times "vreducess\[ \\t\]+\[^\{\n\]*\{sae\}\[^\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */ + +#include + +#define IMM 123 + +volatile __m128 x1, x2, xx1, xx2; +volatile __mmask8 m; + +void extern +avx512dq_test (void) +{ + xx1 = _mm_reduce_round_ss (xx1, xx2, IMM, _MM_FROUND_NO_EXC); +} diff --git a/gcc/testsuite/gcc.target/i386/avx512vl-valignq-1b.c b/gcc/testsuite/gcc.target/i386/avx512vl-valignq-1b.c new file mode 100644 index 00000000000..0ab16b27733 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512vl-valignq-1b.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O0 -mavx512vl" } */ +/* { dg-final { scan-assembler-times "valignq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */ + +#include + +volatile __m256i y; +volatile __m128i x; +volatile __mmask8 m; + +void extern +avx512vl_test (void) +{ + x = _mm_mask_alignr_epi64 (x, m, x, x, 1); +} commit b2ab34b2bb292948bfe103f56b13e9911d143d74 Author: Haochen Jiang Date: Mon Jul 29 14:10:49 2024 +0800 i386: Use _mm_setzero_ps/d instead of _mm_avx512_setzero_ps/d for GCC13/12 In GCC13/12, there is no _mm_avx512_setzero_ps/d since it is introduced in GCC14. gcc/ChangeLog: * config/i386/avx512dqintrin.h (_mm_reduce_round_sd): Use _mm_setzero_pd instead of _mm_avx512_setzero_pd. (_mm_reduce_round_ss): Use _mm_setzero_ps instead of _mm_avx512_setzero_ps. diff --git a/gcc/config/i386/avx512dqintrin.h b/gcc/config/i386/avx512dqintrin.h index 4383ff14670..82f4acc7d2e 100644 --- a/gcc/config/i386/avx512dqintrin.h +++ b/gcc/config/i386/avx512dqintrin.h @@ -2840,7 +2840,7 @@ _mm512_fpclass_ps_mask (__m512 __A, const int __imm) #define _mm_reduce_round_sd(A, B, C, R) \ ((__m128d) __builtin_ia32_reducesd_mask_round ((__v2df)(__m128d)(A), \ - (__v2df)(__m128d)(B), (int)(C), (__v2df) _mm_avx512_setzero_pd (), \ + (__v2df)(__m128d)(B), (int)(C), (__v2df) _mm_setzero_pd (), \ (__mmask8)(-1), (int)(R))) #define _mm_mask_reduce_round_sd(W, U, A, B, C, R) \ @@ -2869,7 +2869,7 @@ _mm512_fpclass_ps_mask (__m512 __A, const int __imm) #define _mm_reduce_round_ss(A, B, C, R) \ ((__m128) __builtin_ia32_reducess_mask_round ((__v4sf)(__m128)(A), \ - (__v4sf)(__m128)(B), (int)(C), (__v4sf) _mm_avx512_setzero_ps (), \ + (__v4sf)(__m128)(B), (int)(C), (__v4sf) _mm_setzero_ps (), \ (__mmask8)(-1), (int)(R))) #define _mm_mask_reduce_round_ss(W, U, A, B, C, R) \ commit 320a9c55258136cdbdbf47b58ed0e807c1f2600f Author: GCC Administrator Date: Tue Jul 30 00:20:42 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 654f63926e2..6a70f2003e3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2024-07-29 Haochen Jiang + + * config/i386/avx512dqintrin.h (_mm_reduce_round_sd): Use + _mm_setzero_pd instead of _mm_avx512_setzero_pd. + (_mm_reduce_round_ss): Use _mm_setzero_ps instead of + _mm_avx512_setzero_ps. + +2024-07-29 Haochen Jiang + + * config/i386/avx512dqintrin.h + (_mm_mask_fpclass_ss_mask): Correct operand order. + (_mm_mask_fpclass_sd_mask): Ditto. + (_mm256_maskz_reduce_round_ss): Use __builtin_ia32_reducess_mask_round + instead of __builtin_ia32_reducesd_mask_round. + (_mm_reduce_round_sd): Use -1 as mask since it is non-mask. + (_mm_reduce_round_ss): Ditto. + * config/i386/avx512vlbwintrin.h + (_mm256_mask_alignr_epi8): Correct operand usage. + (_mm_mask_alignr_epi8): Ditto. + * config/i386/avx512vlintrin.h (_mm_mask_alignr_epi64): Ditto. + 2024-07-24 Peter Bergner Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index d1b40fa5c77..d42ae94bcd3 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240729 +20240730 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a950a5a4b28..439b130b3d7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2024-07-29 Haochen Jiang + + * gcc.target/i386/avx512bw-vpalignr-1b.c: New test. + * gcc.target/i386/avx512dq-vfpclasssd-1b.c: Ditto. + * gcc.target/i386/avx512dq-vfpclassss-1b.c: Ditto. + * gcc.target/i386/avx512dq-vreducesd-1b.c: Ditto. + * gcc.target/i386/avx512dq-vreducess-1b.c: Ditto. + * gcc.target/i386/avx512vl-valignq-1b.c: Ditto. + 2024-07-24 Peter Bergner Backported from master: commit d80abba35edda7b508e29b723daebc0e475ddd87 Author: Haochen Jiang Date: Thu Jul 25 16:16:05 2024 +0800 i386: Add non-optimize prefetchi intrins Under -O0, with the "newly" introduced intrins, the variable will be transformed as mem instead of the origin symbol_ref. The compiler will then treat the operand as invalid and turn the operation into nop, which is not expected. Use macro for non-optimize to keep the variable as symbol_ref just as how prefetch intrin does. gcc/ChangeLog: * config/i386/prfchiintrin.h (_m_prefetchit0): Add macro for non-optimized option. (_m_prefetchit1): Ditto. gcc/testsuite/ChangeLog: * gcc.target/i386/prefetchi-1b.c: New test. diff --git a/gcc/config/i386/prfchiintrin.h b/gcc/config/i386/prfchiintrin.h index 382fc079551..84cf27fe49c 100644 --- a/gcc/config/i386/prfchiintrin.h +++ b/gcc/config/i386/prfchiintrin.h @@ -37,6 +37,7 @@ #define __DISABLE_PREFETCHI__ #endif /* __PREFETCHI__ */ +#ifdef __OPTIMIZE__ extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _m_prefetchit0 (void* __P) @@ -50,6 +51,14 @@ _m_prefetchit1 (void* __P) { __builtin_ia32_prefetchi (__P, 2); } +#else +#define _m_prefetchit0(P) \ + __builtin_ia32_prefetchi(P, 3); + +#define _m_prefetchit1(P) \ + __builtin_ia32_prefetchi(P, 2); + +#endif #ifdef __DISABLE_PREFETCHI__ #undef __DISABLE_PREFETCHI__ diff --git a/gcc/testsuite/gcc.target/i386/prefetchi-1b.c b/gcc/testsuite/gcc.target/i386/prefetchi-1b.c new file mode 100644 index 00000000000..93139554d3c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/prefetchi-1b.c @@ -0,0 +1,26 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-mprefetchi -O0" } */ +/* { dg-final { scan-assembler-times "\[ \\t\]+prefetchit0\[ \\t\]+bar\\(%rip\\)" 1 } } */ +/* { dg-final { scan-assembler-times "\[ \\t\]+prefetchit1\[ \\t\]+bar\\(%rip\\)" 1 } } */ + +#include + +int +bar (int a) +{ + return a + 1; +} + +int +foo1 (int b) +{ + _m_prefetchit0 (bar); + return bar (b) + 1; +} + +int +foo2 (int b) +{ + _m_prefetchit1 (bar); + return bar (b) + 1; +} commit fa6c24e535f2456fe4f37707b51e12872bd0b329 Author: GCC Administrator Date: Wed Jul 31 00:21:24 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6a70f2003e3..7bc86f69939 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2024-07-30 Haochen Jiang + + * config/i386/prfchiintrin.h + (_m_prefetchit0): Add macro for non-optimized option. + (_m_prefetchit1): Ditto. + 2024-07-29 Haochen Jiang * config/i386/avx512dqintrin.h (_mm_reduce_round_sd): Use diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index d42ae94bcd3..e2dab5541a0 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240730 +20240731 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 439b130b3d7..91bcc5bdb92 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2024-07-30 Haochen Jiang + + * gcc.target/i386/prefetchi-1b.c: New test. + 2024-07-29 Haochen Jiang * gcc.target/i386/avx512bw-vpalignr-1b.c: New test. commit 7928ec56429d7564ca7ac68ce8389d3460d2b5b6 Author: GCC Administrator Date: Thu Aug 1 00:22:00 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index e2dab5541a0..5b64322fc60 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240731 +20240801 commit 65b8906a5fea8b3b8eda728459f234cd6c1fd3e7 Author: GCC Administrator Date: Fri Aug 2 00:21:57 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 5b64322fc60..ba6415cbd75 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240801 +20240802 commit 4e0846dd6d005f1f657278ea4dfa193cbc4bb710 Author: GCC Administrator Date: Sat Aug 3 00:21:15 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index ba6415cbd75..613753ee8b5 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240802 +20240803 commit 991acbdff051b134a5974147f46029794eb23820 Author: GCC Administrator Date: Sun Aug 4 00:20:12 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 613753ee8b5..444c7cbae43 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240803 +20240804 commit dcc9a85ff03525eb15a5ce8e86c0772afb719b4a Author: GCC Administrator Date: Mon Aug 5 00:20:13 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 444c7cbae43..25c46364131 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240804 +20240805 commit 7195144e39e404ec712ca5401f2328c14d5020eb Author: Paul Thomas Date: Thu Jul 18 08:51:35 2024 +0100 Fortran: Suppress bogus used uninitialized warnings [PR108889]. 2024-07-18 Paul Thomas gcc/fortran PR fortran/108889 * gfortran.h: Add bit field 'allocated_in_scope' to gfc_symbol. * trans-array.cc (gfc_array_allocate): Set 'allocated_in_scope' after allocation if not a component reference. (gfc_alloc_allocatable_for_assignment): If 'allocated_in_scope' not set, not a component ref and not allocated, set the array bounds and offset to give zero length in all dimensions. Then set allocated_in_scope. gcc/testsuite/ PR fortran/108889 * gfortran.dg/pr108889.f90: New test. (cherry picked from commit c3aa339ea50f050caf7ed2e497f5499ec2d7b9cc) diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index c1430f7dfec..c710945f101 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -1927,6 +1927,10 @@ typedef struct gfc_symbol /* Set if this should be passed by value, but is not a VALUE argument according to the Fortran standard. */ unsigned pass_as_value:1; + /* Set if an allocatable array variable has been allocated in the current + scope. Used in the suppression of uninitialized warnings in reallocation + on assignment. */ + unsigned allocated_in_scope:1; int refs; struct gfc_namespace *ns; /* namespace containing this symbol */ diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index 4d42cf1131a..eecb342f32a 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -6341,6 +6341,8 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg, else gfc_add_expr_to_block (&se->pre, set_descriptor); + expr->symtree->n.sym->allocated_in_scope = 1; + return true; } @@ -10645,6 +10647,8 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop, stmtblock_t realloc_block; stmtblock_t alloc_block; stmtblock_t fblock; + stmtblock_t loop_pre_block; + gfc_ref *ref; gfc_ss *rss; gfc_ss *lss; gfc_array_info *linfo; @@ -10845,6 +10849,45 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop, array1, build_int_cst (TREE_TYPE (array1), 0)); cond_null= gfc_evaluate_now (cond_null, &fblock); + /* If the data is null, set the descriptor bounds and offset. This suppresses + the maybe used uninitialized warning and forces the use of malloc because + the size is zero in all dimensions. Note that this block is only executed + if the lhs is unallocated and is only applied once in any namespace. + Component references are not subject to the warnings. */ + for (ref = expr1->ref; ref; ref = ref->next) + if (ref->type == REF_COMPONENT) + break; + + if (!expr1->symtree->n.sym->allocated_in_scope && !ref) + { + gfc_start_block (&loop_pre_block); + for (n = 0; n < expr1->rank; n++) + { + gfc_conv_descriptor_lbound_set (&loop_pre_block, desc, + gfc_rank_cst[n], + gfc_index_one_node); + gfc_conv_descriptor_ubound_set (&loop_pre_block, desc, + gfc_rank_cst[n], + gfc_index_zero_node); + gfc_conv_descriptor_stride_set (&loop_pre_block, desc, + gfc_rank_cst[n], + gfc_index_zero_node); + } + + tmp = gfc_conv_descriptor_offset (desc); + gfc_add_modify (&loop_pre_block, tmp, gfc_index_zero_node); + + tmp = fold_build2_loc (input_location, EQ_EXPR, + logical_type_node, array1, + build_int_cst (TREE_TYPE (array1), 0)); + tmp = build3_v (COND_EXPR, tmp, + gfc_finish_block (&loop_pre_block), + build_empty_stmt (input_location)); + gfc_prepend_expr_to_block (&loop->pre, tmp); + + expr1->symtree->n.sym->allocated_in_scope = 1; + } + tmp = build3_v (COND_EXPR, cond_null, build1_v (GOTO_EXPR, jump_label1), build_empty_stmt (input_location)); diff --git a/gcc/testsuite/gfortran.dg/pr108889.f90 b/gcc/testsuite/gfortran.dg/pr108889.f90 new file mode 100644 index 00000000000..7fd4e3882a4 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr108889.f90 @@ -0,0 +1,43 @@ +! { dg-do compile } +! { dg-options "-Wall -fdump-tree-original" } +! +! Contributed by Tobias Burnus +! +program main + implicit none + + type :: struct + real, allocatable :: var(:) + end type struct + + type(struct) :: single + real, allocatable :: ref1(:), ref2(:), ref3(:), ref4(:) + + ref2 = [1,2,3,4,5] ! Warnings here + + single%var = ref2 ! No warnings for components + ref1 = single%var ! Warnings here + ref1 = [1,2,3,4,5] ! Should not add to tree dump count + + allocate (ref3(5)) + ref3 = single%var ! No warnings following allocation + + call set_ref4 + + call test (ref1) + call test (ref2) + call test (ref3) + call test (ref4) + +contains + subroutine test (arg) + real, allocatable :: arg(:) + if (size(arg) /= size(single%var)) stop 1 + if (lbound(arg, 1) /= 1) stop 2 + if (any (arg /= single%var)) stop 3 + end + subroutine set_ref4 + ref4 = single%var ! Warnings in contained scope + end +end +! { df-final { scan-tree-dump-times "ubound = 0" 3 "original" } } \ No newline at end of file commit bf0673ef66a6dd8a000c6fb882a206c1cef639c7 Author: Paul Thomas Date: Fri Jul 19 16:58:33 2024 +0100 libgomp: Remove bogus warnings from privatized-ref-2.f90. 2024-07-19 Paul Thomas libgomp/ChangeLog * testsuite/libgomp.oacc-fortran/privatized-ref-2.f90: Cut dg-note about 'a' and remove bogus warnings about its array descriptor components being used uninitialized. (cherry picked from commit 8d6994f33a98a168151a57a3d21395b19196cd9d) diff --git a/libgomp/testsuite/libgomp.oacc-fortran/privatized-ref-2.f90 b/libgomp/testsuite/libgomp.oacc-fortran/privatized-ref-2.f90 index 498ef70b63a..8cf79a10e8d 100644 --- a/libgomp/testsuite/libgomp.oacc-fortran/privatized-ref-2.f90 +++ b/libgomp/testsuite/libgomp.oacc-fortran/privatized-ref-2.f90 @@ -29,16 +29,10 @@ program main implicit none (type, external) integer :: j integer, allocatable :: A(:) - ! { dg-note {'a' declared here} {} { target *-*-* } .-1 } character(len=:), allocatable :: my_str character(len=15), allocatable :: my_str15 A = [(3*j, j=1, 10)] - ! { dg-bogus {'a\.offset' is used uninitialized} {PR77504 etc.} { xfail *-*-* } .-1 } - ! { dg-bogus {'a\.dim\[0\]\.lbound' is used uninitialized} {PR77504 etc.} { xfail *-*-* } .-2 } - ! { dg-bogus {'a\.dim\[0\]\.ubound' is used uninitialized} {PR77504 etc.} { xfail *-*-* } .-3 } - ! { dg-bogus {'a\.dim\[0\]\.lbound' may be used uninitialized} {PR77504 etc.} { xfail { ! __OPTIMIZE__ } } .-4 } - ! { dg-bogus {'a\.dim\[0\]\.ubound' may be used uninitialized} {PR77504 etc.} { xfail { ! __OPTIMIZE__ } } .-5 } call foo (A, size(A)) call bar (A) my_str = "1234567890" commit 87cb0112b4f301e8bc92f34283273cd4a916b58f Author: GCC Administrator Date: Tue Aug 6 00:21:45 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 25c46364131..f2c439e6ce5 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240805 +20240806 diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 4673ec16567..3109e9b359c 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,17 @@ +2024-08-05 Paul Thomas + + Backported from master: + 2024-07-18 Paul Thomas + + PR fortran/108889 + * gfortran.h: Add bit field 'allocated_in_scope' to gfc_symbol. + * trans-array.cc (gfc_array_allocate): Set 'allocated_in_scope' + after allocation if not a component reference. + (gfc_alloc_allocatable_for_assignment): If 'allocated_in_scope' + not set, not a component ref and not allocated, set the array + bounds and offset to give zero length in all dimensions. Then + set allocated_in_scope. + 2024-07-21 Harald Anlauf Backported from master: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 91bcc5bdb92..ebf3dbe6075 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2024-08-05 Paul Thomas + + Backported from master: + 2024-07-18 Paul Thomas + + PR fortran/108889 + * gfortran.dg/pr108889.f90: New test. + 2024-07-30 Haochen Jiang * gcc.target/i386/prefetchi-1b.c: New test. diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index eaa8f243f1a..5a2b0caac8f 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,12 @@ +2024-08-05 Paul Thomas + + Backported from master: + 2024-07-19 Paul Thomas + + * testsuite/libgomp.oacc-fortran/privatized-ref-2.f90: Cut + dg-note about 'a' and remove bogus warnings about its array + descriptor components being used uninitialized. + 2024-05-21 Release Manager * GCC 13.3.0 released. commit 73064a28689fe3799f4fb5f1bab7634df889a43e Author: Andrew Pinski Date: Sat Aug 3 09:30:57 2024 -0700 sh: Don't call make_insn_raw in sh_recog_treg_set_expr [PR116189] This was an interesting compare debug failure to debug. The first symptom was in gcse which would produce different order of creating psedu-registers. This was caused by a different order of a hashtable walk, due to the hash table having different number of entries. Which in turn was due to the number of max insn being different between the 2 runs. The place max insn uid comes from was in sh_recog_treg_set_expr which is called via rtx_costs and fwprop would cause rtx_costs in some cases for debug insn related stuff. Build and tested for sh4-linux-gnu. PR target/116189 gcc/ChangeLog: * config/sh/sh.cc (sh_recog_treg_set_expr): Don't call make_insn_raw, make the insn with a fake uid. gcc/testsuite/ChangeLog: * c-c++-common/torture/pr116189-1.c: New test. Signed-off-by: Andrew Pinski (cherry picked from commit 0355c943b9e954e8f59068971d934f1b91ecb729) diff --git a/gcc/config/sh/sh.cc b/gcc/config/sh/sh.cc index 8ac20dfaa38..717123af655 100644 --- a/gcc/config/sh/sh.cc +++ b/gcc/config/sh/sh.cc @@ -12279,7 +12279,17 @@ sh_recog_treg_set_expr (rtx op, machine_mode mode) have to capture its current state and restore it afterwards. */ recog_data_d prev_recog_data = recog_data; - rtx_insn* i = make_insn_raw (gen_rtx_SET (get_t_reg_rtx (), op)); + /* Note we can't use insn_raw here since that increases the uid + and could cause debug compare differences; this insn never leaves + this function so create a dummy one. */ + rtx_insn* i = as_a (rtx_alloc (INSN)); + + INSN_UID (i) = 1; + PATTERN (i) = gen_rtx_SET (get_t_reg_rtx (), op); + INSN_CODE (i) = -1; + REG_NOTES (i) = NULL; + INSN_LOCATION (i) = curr_insn_location (); + BLOCK_FOR_INSN (i) = NULL; SET_PREV_INSN (i) = NULL; SET_NEXT_INSN (i) = NULL; diff --git a/gcc/testsuite/c-c++-common/torture/pr116189-1.c b/gcc/testsuite/c-c++-common/torture/pr116189-1.c new file mode 100644 index 00000000000..055c563f43e --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/pr116189-1.c @@ -0,0 +1,30 @@ +/* { dg-additional-options "-fcompare-debug" } */ + +/* PR target/116189 */ + +/* In the sh backend, we used to create insn in the path of rtx_costs. + This means sometimes the max uid for insns would be different between + debugging and non debugging which then would cause gcse's hashtable + to have different number of slots which would cause a different walk + for that hash table. */ + +extern void ff(void); +extern short nn[8][4]; +typedef unsigned short move_table[4]; +extern signed long long ira_overall_cost; +extern signed long long ira_load_cost; +extern move_table *x_ira_register_move_cost[1]; +struct move { struct move *next; }; +unsigned short t; +void emit_move_list(struct move * list, int freq, unsigned char mode, int regno) { + int cost; + for (; list != 0; list = list->next) + { + ff(); + unsigned short aclass = t; + cost = (nn)[mode][aclass] ; + ira_load_cost = cost; + cost = x_ira_register_move_cost[mode][aclass][aclass] * freq ; + ira_overall_cost = cost; + } +} commit f6624adc535a165ab667646c57b73e213d868cca Author: John David Anglin Date: Tue Aug 6 13:40:26 2024 -0400 hppa: Fix (plus (plus (mult (a) (mem_shadd_constant)) (b)) (c)) optimization The constant C must be an integral multiple of the shift value in the above optimization. Non integral values can occur evaluating IMAGPART_EXPR when the shadd constant is 8 and we have SFmode. 2024-08-06 John David Anglin gcc/ChangeLog: PR target/113384 * config/pa/pa.cc (hppa_legitimize_address): Add check to ensure constant is an integral multiple of shift the value. diff --git a/gcc/config/pa/pa.cc b/gcc/config/pa/pa.cc index 3e2ae9fa677..8ed376a9f49 100644 --- a/gcc/config/pa/pa.cc +++ b/gcc/config/pa/pa.cc @@ -1263,6 +1263,7 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, /* If the index adds a large constant, try to scale the constant so that it can be loaded with only one insn. */ if (GET_CODE (XEXP (idx, 1)) == CONST_INT + && INTVAL (XEXP (idx, 1)) % (1 << shift_val) == 0 && VAL_14_BITS_P (INTVAL (XEXP (idx, 1)) / INTVAL (XEXP (XEXP (idx, 0), 1))) && INTVAL (XEXP (idx, 1)) % INTVAL (XEXP (XEXP (idx, 0), 1)) == 0) commit 9d368828bd4d04ce507e02a581be850fca849fae Author: GCC Administrator Date: Wed Aug 7 00:20:44 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7bc86f69939..5e4d67476ae 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2024-08-06 John David Anglin + + PR target/113384 + * config/pa/pa.cc (hppa_legitimize_address): Add check to + ensure constant is an integral multiple of shift the value. + +2024-08-06 Andrew Pinski + + Backported from master: + 2024-08-06 Andrew Pinski + + PR target/116189 + * config/sh/sh.cc (sh_recog_treg_set_expr): Don't call make_insn_raw, + make the insn with a fake uid. + 2024-07-30 Haochen Jiang * config/i386/prfchiintrin.h diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index f2c439e6ce5..0795b809c24 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240806 +20240807 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ebf3dbe6075..c44e87f280c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2024-08-06 Andrew Pinski + + Backported from master: + 2024-08-06 Andrew Pinski + + PR target/116189 + * c-c++-common/torture/pr116189-1.c: New test. + 2024-08-05 Paul Thomas Backported from master: commit 617bbaef953497b3b2025421885f0fbbf2c77d82 Author: GCC Administrator Date: Thu Aug 8 00:20:57 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 0795b809c24..e2d907af701 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240807 +20240808 commit 7830d924496bd9bd410086391dc53ce7ca67d779 Author: GCC Administrator Date: Fri Aug 9 00:21:13 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index e2d907af701..17534e79088 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240808 +20240809 commit 12ba140ee93adc56a3426f0c6c05f4d6c6a3d08e Author: Patrick Palka Date: Fri Aug 9 09:03:14 2024 -0400 c++: local class memfn synth from uneval context [PR113063] This is essentially a narrow backport of r14-6724-gfced59166f95e9 that instead uses cp_evaluated instead of maybe_push_to_top_level to clear cp_unevaluated_operand within synthesize_method, which turns out is sufficient to also fix the 13.3 regression PR116289 (whose immediate trigger is a change backport r13-7739-gd919309679334a). PR c++/113063 PR c++/116289 gcc/cp/ChangeLog: * method.cc (synthesize_method): Use cp_evaluated. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/spaceship-synth16.C: New test. * g++.dg/cpp2a/spaceship-synth16a.C: New test. Reviewed-by: Jason Merrill diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc index 9fd5567e97f..09ea6d732df 100644 --- a/gcc/cp/method.cc +++ b/gcc/cp/method.cc @@ -1797,6 +1797,7 @@ synthesize_method (tree fndecl) it now. */ push_deferring_access_checks (dk_no_deferred); + cp_evaluated ev; if (! context) push_to_top_level (); else if (nested) diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16.C new file mode 100644 index 00000000000..37a183de0f5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16.C @@ -0,0 +1,13 @@ +// PR c++/113063 +// { dg-do link { target c++20 } } + +#include + +int main() { + struct X { + auto operator<=>(const X&) const = default; + }; + X x; + static_assert(noexcept(x <=> x)); + x <=> x; +} diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16a.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16a.C new file mode 100644 index 00000000000..68388a680b2 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth16a.C @@ -0,0 +1,16 @@ +// PR c++/116289 +// PR c++/113063 +// { dg-do link { target c++20 } } +// A version of spaceship-synth16.C where the local class isn't empty. + +#include + +int main() { + struct X { + int m = 0; + auto operator<=>(const X&) const = default; + }; + X x; + static_assert(noexcept(x <=> x)); + x <=> x; +} commit 419c5337e354e48bdd87aff640fdb05e32983404 Author: GCC Administrator Date: Sat Aug 10 00:21:07 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 17534e79088..5d474ddc6cc 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240809 +20240810 diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index bcb359adbcd..ffa34d2acda 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2024-08-09 Patrick Palka + + PR c++/113063 + PR c++/116289 + * method.cc (synthesize_method): Use cp_evaluated. + 2024-06-17 Jakub Jelinek Backported from master: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c44e87f280c..0f6eeaaa2ca 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2024-08-09 Patrick Palka + + PR c++/113063 + PR c++/116289 + * g++.dg/cpp2a/spaceship-synth16.C: New test. + * g++.dg/cpp2a/spaceship-synth16a.C: New test. + 2024-08-06 Andrew Pinski Backported from master: commit 30088070b4698798d240156b49c789d5ad59e88f Author: GCC Administrator Date: Sun Aug 11 00:20:23 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 5d474ddc6cc..c3de54be1f1 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240810 +20240811 commit 368956531679ee094c5e200117f6cdfba783dd0c Author: GCC Administrator Date: Mon Aug 12 00:20:35 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index c3de54be1f1..2454f4b3e28 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240811 +20240812 commit 617562e4e422c7bd282960b14abfffd994445009 Author: liuhongt Date: Wed Jul 24 11:29:23 2024 +0800 Refine constraint "Bk" to define_special_memory_constraint. For below pattern, RA may still allocate r162 as v/k register, try to reload for address with leaq __libc_tsd_CTYPE_B@gottpoff(%rip), %rsi which result a linker error. (set (reg:DI 162) (mem/u/c:DI (const:DI (unspec:DI [(symbol_ref:DI ("a") [flags 0x60] )] UNSPEC_GOTNTPOFF)) Quote from H.J for why linker issue an error. >What do these do: > > leaq __libc_tsd_CTYPE_B@gottpoff(%rip), %rax > vmovq (%rax), %xmm0 > >From x86-64 TLS psABI: > >The assembler generates for the x@gottpoff(%rip) expressions a R X86 >64 GOTTPOFF relocation for the symbol x which requests the linker to >generate a GOT entry with a R X86 64 TPOFF64 relocation. The offset of >the GOT entry relative to the end of the instruction is then used in >the instruction. The R X86 64 TPOFF64 relocation is pro- cessed at >program startup time by the dynamic linker by looking up the symbol x >in the modules loaded at that point. The offset is written in the GOT >entry and later loaded by the addq instruction. > >The above code sequence looks wrong to me. gcc/ChangeLog: PR target/116043 * config/i386/constraints.md (Bk): Refine to define_special_memory_constraint. gcc/testsuite/ChangeLog: * gcc.target/i386/pr116043.c: New test. (cherry picked from commit bc1fda00d5f20e2f3e77a50b2822562b6e0040b2) diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md index aeda1078471..71265ddc7f4 100644 --- a/gcc/config/i386/constraints.md +++ b/gcc/config/i386/constraints.md @@ -190,7 +190,7 @@ (and (match_operand 0 "memory_operand") (match_test "constant_address_p (XEXP (op, 0))"))) -(define_memory_constraint "Bk" +(define_special_memory_constraint "Bk" "@internal TLS address that allows insn using non-integer registers." (and (match_operand 0 "memory_operand") (not (match_test "ix86_gpr_tls_address_pattern_p (op)")))) diff --git a/gcc/testsuite/gcc.target/i386/pr116043.c b/gcc/testsuite/gcc.target/i386/pr116043.c new file mode 100644 index 00000000000..76553496c10 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr116043.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-mavx512bf16 -O3" } */ +/* { dg-final { scan-assembler-not {(?n)lea.*@gottpoff} } } */ + +extern __thread int a, c, i, j, k, l; +int *b; +struct d { + int e; +} f, g; +char *h; + +void m(struct d *n) { + b = &k; + for (; n->e; b++, n--) { + i = b && a; + if (i) + j = c; + } +} + +char *o(struct d *n) { + for (; n->e;) + return h; +} + +int q() { + if (l) + return 1; + int p = *o(&g); + m(&f); + m(&g); + l = p; +} commit 7b0e478ad54ee93e63b7d0bb0caf7a5f6638c16c Author: GCC Administrator Date: Tue Aug 13 00:20:42 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5e4d67476ae..b4b5513466a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2024-08-12 liuhongt + + Backported from master: + 2024-07-30 liuhongt + + PR target/116043 + * config/i386/constraints.md (Bk): Refine to + define_special_memory_constraint. + 2024-08-06 John David Anglin PR target/113384 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 2454f4b3e28..e2b84f6ebd8 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240812 +20240813 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0f6eeaaa2ca..88c640f466b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2024-08-12 liuhongt + + Backported from master: + 2024-07-30 liuhongt + + * gcc.target/i386/pr116043.c: New test. + 2024-08-09 Patrick Palka PR c++/113063 commit a79d7cc1c35b014762590fedaec9597bb07a911c Author: GCC Administrator Date: Wed Aug 14 00:20:35 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index e2b84f6ebd8..94834f4f423 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240813 +20240814 commit 8796e33108c7ac557a2799300aea679c9e84e336 Author: GCC Administrator Date: Thu Aug 15 00:23:11 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 94834f4f423..2ea444e25fe 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240814 +20240815 commit 73d22beaab8b797ebc5e6db0cf9158d2b471ca81 Author: GCC Administrator Date: Fri Aug 16 00:21:43 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 2ea444e25fe..c11f769cc2c 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240815 +20240816 commit 22c6a11686d3f20f8682c2fbe9e33867a7e8af0e Author: Richard Sandiford Date: Fri Aug 16 07:58:24 2024 +0100 aarch64: Fix expansion of svsudot [PR114607] Not sure how this happend, but: svsudot is supposed to be expanded as USDOT with the operands swapped. However, a thinko in the expansion of svsudot meant that the arguments weren't in fact swapped; the attempted swap was just a no-op. And the testcases blithely accepted that. gcc/ PR target/114607 * config/aarch64/aarch64-sve-builtins-base.cc (svusdot_impl::expand): Fix botched attempt to swap the operands for svsudot. gcc/testsuite/ PR target/114607 * gcc.target/aarch64/sve/acle/asm/sudot_s32.c: New test. (cherry picked from commit 2c1c2485a4b1aca746ac693041e51ea6da5c64ca) diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.cc b/gcc/config/aarch64/aarch64-sve-builtins-base.cc index cd9cace3c9b..34f2d8c6e4e 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins-base.cc +++ b/gcc/config/aarch64/aarch64-sve-builtins-base.cc @@ -2403,7 +2403,7 @@ public: version) is through the USDOT instruction but with the second and third inputs swapped. */ if (m_su) - e.rotate_inputs_left (1, 2); + e.rotate_inputs_left (1, 3); /* The ACLE function has the same order requirements as for svdot. While there's no requirement for the RTL pattern to have the same sort of order as that for dot_prod, it's easier to read. diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sudot_s32.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sudot_s32.c index 4b452619eee..e06b69affab 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sudot_s32.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/sudot_s32.c @@ -6,7 +6,7 @@ /* ** sudot_s32_tied1: -** usdot z0\.s, z2\.b, z4\.b +** usdot z0\.s, z4\.b, z2\.b ** ret */ TEST_TRIPLE_Z (sudot_s32_tied1, svint32_t, svint8_t, svuint8_t, @@ -17,7 +17,7 @@ TEST_TRIPLE_Z (sudot_s32_tied1, svint32_t, svint8_t, svuint8_t, ** sudot_s32_tied2: ** mov (z[0-9]+)\.d, z0\.d ** movprfx z0, z4 -** usdot z0\.s, z2\.b, \1\.b +** usdot z0\.s, \1\.b, z2\.b ** ret */ TEST_TRIPLE_Z_REV (sudot_s32_tied2, svint32_t, svint8_t, svuint8_t, @@ -27,7 +27,7 @@ TEST_TRIPLE_Z_REV (sudot_s32_tied2, svint32_t, svint8_t, svuint8_t, /* ** sudot_w0_s32_tied: ** mov (z[0-9]+\.b), w0 -** usdot z0\.s, z2\.b, \1 +** usdot z0\.s, \1, z2\.b ** ret */ TEST_TRIPLE_ZX (sudot_w0_s32_tied, svint32_t, svint8_t, uint8_t, @@ -37,7 +37,7 @@ TEST_TRIPLE_ZX (sudot_w0_s32_tied, svint32_t, svint8_t, uint8_t, /* ** sudot_9_s32_tied: ** mov (z[0-9]+\.b), #9 -** usdot z0\.s, z2\.b, \1 +** usdot z0\.s, \1, z2\.b ** ret */ TEST_TRIPLE_Z (sudot_9_s32_tied, svint32_t, svint8_t, uint8_t, commit 959d6529df206c1983be14383da081f374416e47 Author: Richard Sandiford Date: Fri Aug 16 07:58:25 2024 +0100 aarch64: Fix bogus cnot optimisation [PR114603] aarch64-sve.md had a pattern that combined: cmpeq pb.T, pa/z, zc.T, #0 mov zd.T, pb/z, #1 into: cnot zd.T, pa/m, zc.T But this is only valid if pa.T is a ptrue. In other cases, the original would set inactive elements of zd.T to 0, whereas the combined form would copy elements from zc.T. gcc/ PR target/114603 * config/aarch64/aarch64-sve.md (@aarch64_pred_cnot): Replace with... (@aarch64_ptrue_cnot): ...this, requiring operand 1 to be a ptrue. (*cnot): Require operand 1 to be a ptrue. * config/aarch64/aarch64-sve-builtins-base.cc (svcnot_impl::expand): Use aarch64_ptrue_cnot for _x operations that are predicated with a ptrue. Represent other _x operations as fully-defined _m operations. gcc/testsuite/ PR target/114603 * gcc.target/aarch64/sve/acle/general/cnot_1.c: New test. (cherry picked from commit 67cbb1c638d6ab3a9cb77e674541e2b291fb67df) diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.cc b/gcc/config/aarch64/aarch64-sve-builtins-base.cc index 34f2d8c6e4e..852f569461a 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins-base.cc +++ b/gcc/config/aarch64/aarch64-sve-builtins-base.cc @@ -496,15 +496,22 @@ public: expand (function_expander &e) const override { machine_mode mode = e.vector_mode (0); - if (e.pred == PRED_x) - { - /* The pattern for CNOT includes an UNSPEC_PRED_Z, so needs - a ptrue hint. */ - e.add_ptrue_hint (0, e.gp_mode (0)); - return e.use_pred_x_insn (code_for_aarch64_pred_cnot (mode)); - } - - return e.use_cond_insn (code_for_cond_cnot (mode), 0); + machine_mode pred_mode = e.gp_mode (0); + /* The underlying _x pattern is effectively: + + dst = src == 0 ? 1 : 0 + + rather than an UNSPEC_PRED_X. Using this form allows autovec + constructs to be matched by combine, but it means that the + predicate on the src == 0 comparison must be all-true. + + For simplicity, represent other _x operations as fully-defined _m + operations rather than using a separate bespoke pattern. */ + if (e.pred == PRED_x + && gen_lowpart (pred_mode, e.args[0]) == CONSTM1_RTX (pred_mode)) + return e.use_pred_x_insn (code_for_aarch64_ptrue_cnot (mode)); + return e.use_cond_insn (code_for_cond_cnot (mode), + e.pred == PRED_x ? 1 : 0); } }; diff --git a/gcc/config/aarch64/aarch64-sve.md b/gcc/config/aarch64/aarch64-sve.md index 7533b956686..0a05aecd1a3 100644 --- a/gcc/config/aarch64/aarch64-sve.md +++ b/gcc/config/aarch64/aarch64-sve.md @@ -3225,24 +3225,24 @@ ;; - CNOT ;; ------------------------------------------------------------------------- -;; Predicated logical inverse. -(define_expand "@aarch64_pred_cnot" +;; Logical inverse, predicated with a ptrue. +(define_expand "@aarch64_ptrue_cnot" [(set (match_operand:SVE_FULL_I 0 "register_operand") (unspec:SVE_FULL_I [(unspec: [(match_operand: 1 "register_operand") - (match_operand:SI 2 "aarch64_sve_ptrue_flag") + (const_int SVE_KNOWN_PTRUE) (eq: - (match_operand:SVE_FULL_I 3 "register_operand") - (match_dup 4))] + (match_operand:SVE_FULL_I 2 "register_operand") + (match_dup 3))] UNSPEC_PRED_Z) - (match_dup 5) - (match_dup 4)] + (match_dup 4) + (match_dup 3)] UNSPEC_SEL))] "TARGET_SVE" { - operands[4] = CONST0_RTX (mode); - operands[5] = CONST1_RTX (mode); + operands[3] = CONST0_RTX (mode); + operands[4] = CONST1_RTX (mode); } ) @@ -3251,7 +3251,7 @@ (unspec:SVE_I [(unspec: [(match_operand: 1 "register_operand" "Upl, Upl") - (match_operand:SI 5 "aarch64_sve_ptrue_flag") + (const_int SVE_KNOWN_PTRUE) (eq: (match_operand:SVE_I 2 "register_operand" "0, w") (match_operand:SVE_I 3 "aarch64_simd_imm_zero"))] diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cnot_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cnot_1.c new file mode 100644 index 00000000000..b1a489f0cf0 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cnot_1.c @@ -0,0 +1,23 @@ +/* { dg-options "-O2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** foo: +** cmpeq (p[0-7])\.s, p0/z, z0\.s, #0 +** mov z0\.s, \1/z, #1 +** ret +*/ +svint32_t foo(svbool_t pg, svint32_t y) +{ + return svsel(svcmpeq(pg, y, 0), svdup_s32(1), svdup_s32(0)); +} + +#ifdef __cplusplus +} +#endif commit 2466e1078a149518880b4d3cfcd36abdb07336ef Author: GCC Administrator Date: Sat Aug 17 00:20:56 2024 +0000 Daily bump. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b4b5513466a..7d2121df1ec 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +2024-08-16 Richard Sandiford + + Backported from master: + 2024-04-05 Richard Sandiford + + PR target/114603 + * config/aarch64/aarch64-sve.md (@aarch64_pred_cnot): Replace + with... + (@aarch64_ptrue_cnot): ...this, requiring operand 1 to be + a ptrue. + (*cnot): Require operand 1 to be a ptrue. + * config/aarch64/aarch64-sve-builtins-base.cc (svcnot_impl::expand): + Use aarch64_ptrue_cnot for _x operations that are predicated + with a ptrue. Represent other _x operations as fully-defined _m + operations. + +2024-08-16 Richard Sandiford + + Backported from master: + 2024-04-08 Richard Sandiford + + PR target/114607 + * config/aarch64/aarch64-sve-builtins-base.cc + (svusdot_impl::expand): Fix botched attempt to swap the operands + for svsudot. + 2024-08-12 liuhongt Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index c11f769cc2c..720f32939ba 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240816 +20240817 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 88c640f466b..2e20c448ecc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,19 @@ +2024-08-16 Richard Sandiford + + Backported from master: + 2024-04-05 Richard Sandiford + + PR target/114603 + * gcc.target/aarch64/sve/acle/general/cnot_1.c: New test. + +2024-08-16 Richard Sandiford + + Backported from master: + 2024-04-08 Richard Sandiford + + PR target/114607 + * gcc.target/aarch64/sve/acle/asm/sudot_s32.c: New test. + 2024-08-12 liuhongt Backported from master: commit b8fe699e2c39b2bc9159131a8f46bcc169f9f2b5 Author: GCC Administrator Date: Sun Aug 18 00:20:47 2024 +0000 Daily bump. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 720f32939ba..5e34934c797 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20240817 +20240818