[gcc r15-86] c++: Propagate hidden flag on decls from partitions
https://gcc.gnu.org/g:3032ebf0c9b769f02f494e97417a1b68ad59c884 commit r15-86-g3032ebf0c9b769f02f494e97417a1b68ad59c884 Author: Nathaniel Shead Date: Tue Apr 9 21:52:38 2024 +1000 c++: Propagate hidden flag on decls from partitions While working on some other fixes I noticed that the partition handling code used the wrong flag to propagate OVL_HIDDEN_P on exported bindings from partitions. This patch fixes that, and renames the flag to be clearer. gcc/cp/ChangeLog: * name-lookup.cc (walk_module_binding): Use the partition-specific hidden flag instead of the top-level decl_hidden. gcc/testsuite/ChangeLog: * g++.dg/modules/using-16_a.C: New test. * g++.dg/modules/using-16_b.C: New test. * g++.dg/modules/using-16_c.C: New test. Signed-off-by: Nathaniel Shead Diff: --- gcc/cp/name-lookup.cc | 10 +- gcc/testsuite/g++.dg/modules/using-16_a.C | 11 +++ gcc/testsuite/g++.dg/modules/using-16_b.C | 12 gcc/testsuite/g++.dg/modules/using-16_c.C | 11 +++ 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc index 5d2319db43d..78f08acffaa 100644 --- a/gcc/cp/name-lookup.cc +++ b/gcc/cp/name-lookup.cc @@ -4290,19 +4290,19 @@ walk_module_binding (tree binding, bitmap partitions, count += callback (btype, flags, data); } - bool hidden = STAT_DECL_HIDDEN_P (bind); + bool part_hidden = STAT_DECL_HIDDEN_P (bind); for (ovl_iterator iter (MAYBE_STAT_DECL (STAT_DECL (bind))); iter; ++iter) { if (iter.hidden_p ()) - hidden = true; + part_hidden = true; gcc_checking_assert - (!(hidden && DECL_IS_UNDECLARED_BUILTIN (*iter))); + (!(part_hidden && DECL_IS_UNDECLARED_BUILTIN (*iter))); WMB_Flags flags = WMB_None; if (maybe_dups) flags = WMB_Flags (flags | WMB_Dups); - if (decl_hidden) + if (part_hidden) flags = WMB_Flags (flags | WMB_Hidden); if (iter.using_p ()) { @@ -4311,7 +4311,7 @@ walk_module_binding (tree binding, bitmap partitions, flags = WMB_Flags (flags | WMB_Export); } count += callback (*iter, flags, data); - hidden = false; + part_hidden = false; } } } diff --git a/gcc/testsuite/g++.dg/modules/using-16_a.C b/gcc/testsuite/g++.dg/modules/using-16_a.C new file mode 100644 index 000..25d8bca5d1c --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/using-16_a.C @@ -0,0 +1,11 @@ +// { dg-additional-options "-fmodules-ts" } +// { dg-module-cmi M:S } + +export module M:S; + +namespace foo { + // propagate hidden from partitions + export struct S { +friend void f(S); + }; +}; diff --git a/gcc/testsuite/g++.dg/modules/using-16_b.C b/gcc/testsuite/g++.dg/modules/using-16_b.C new file mode 100644 index 000..3f704a913f4 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/using-16_b.C @@ -0,0 +1,12 @@ +// { dg-additional-options "-fmodules-ts -Wno-global-module" } +// { dg-module-cmi M } + +module; +namespace bar { + void f(int); +} +export module M; +export import :S; +namespace foo { + export using bar::f; +} diff --git a/gcc/testsuite/g++.dg/modules/using-16_c.C b/gcc/testsuite/g++.dg/modules/using-16_c.C new file mode 100644 index 000..5e46cd16013 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/using-16_c.C @@ -0,0 +1,11 @@ +// { dg-additional-options "-fmodules-ts" } +import M; + +int main() { + // this should be hidden and fail + foo::f(foo::S{}); // { dg-error "cannot convert" } + + // but these should be legal + foo::f(10); + f(foo::S{}); +}
[gcc r15-85] c++: Propagate using decls from partitions [PR114868]
https://gcc.gnu.org/g:0d0215b10dbbe39d655ceda4af283f288ec7680c commit r15-85-g0d0215b10dbbe39d655ceda4af283f288ec7680c Author: Nathaniel Shead Date: Tue Apr 9 21:49:58 2024 +1000 c++: Propagate using decls from partitions [PR114868] The modules code currently neglects to set OVL_USING_P on the dependency created for a using-decl, which causes it not to remember that the OVL_EXPORT_P flag had been set on it when emitted from the primary interface unit. This patch ensures that it occurs. PR c++/114868 gcc/cp/ChangeLog: * module.cc (depset::hash::add_binding_entity): Propagate OVL_USING_P for using-declarations. gcc/testsuite/ChangeLog: * g++.dg/modules/using-15_a.C: New test. * g++.dg/modules/using-15_b.C: New test. * g++.dg/modules/using-15_c.C: New test. Signed-off-by: Nathaniel Shead Diff: --- gcc/cp/module.cc | 6 ++ gcc/testsuite/g++.dg/modules/using-15_a.C | 14 ++ gcc/testsuite/g++.dg/modules/using-15_b.C | 6 ++ gcc/testsuite/g++.dg/modules/using-15_c.C | 8 4 files changed, 34 insertions(+) diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 5b8ff5bc483..fac0301d80e 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -13150,10 +13150,14 @@ depset::hash::add_binding_entity (tree decl, WMB_Flags flags, void *data_) /* Ignore NTTP objects. */ return false; + bool unscoped_enum_const_p = false; if (!(flags & WMB_Using) && CP_DECL_CONTEXT (decl) != data->ns) { /* A using that lost its wrapper or an unscoped enum constant. */ + /* FIXME: Ensure that unscoped enums are differentiated from +'using enum' declarations when PR c++/114683 is fixed. */ + unscoped_enum_const_p = (TREE_CODE (decl) == CONST_DECL); flags = WMB_Flags (flags | WMB_Using); if (DECL_MODULE_EXPORT_P (TREE_CODE (decl) == CONST_DECL ? TYPE_NAME (TREE_TYPE (decl)) @@ -13214,6 +13218,8 @@ depset::hash::add_binding_entity (tree decl, WMB_Flags flags, void *data_) if (flags & WMB_Using) { decl = ovl_make (decl, NULL_TREE); + if (!unscoped_enum_const_p) + OVL_USING_P (decl) = true; if (flags & WMB_Export) OVL_EXPORT_P (decl) = true; } diff --git a/gcc/testsuite/g++.dg/modules/using-15_a.C b/gcc/testsuite/g++.dg/modules/using-15_a.C new file mode 100644 index 000..3f4bb6c5914 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/using-15_a.C @@ -0,0 +1,14 @@ +// PR c++/114868 +// { dg-additional-options "-fmodules-ts -Wno-global-module" } +// { dg-module-cmi M:a } + +module; +namespace foo { + void a(); +} +export module M:a; + +namespace bar { + // propagate usings from partitions + export using foo::a; +} diff --git a/gcc/testsuite/g++.dg/modules/using-15_b.C b/gcc/testsuite/g++.dg/modules/using-15_b.C new file mode 100644 index 000..4b0cb745157 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/using-15_b.C @@ -0,0 +1,6 @@ +// PR c++/114868 +// { dg-additional-options "-fmodules-ts" } +// { dg-module-cmi M } + +export module M; +export import :a; diff --git a/gcc/testsuite/g++.dg/modules/using-15_c.C b/gcc/testsuite/g++.dg/modules/using-15_c.C new file mode 100644 index 000..74dd10a5413 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/using-15_c.C @@ -0,0 +1,8 @@ +// PR c++/114868 +// { dg-additional-options "-fmodules-ts" } +import M; + +int main() { + bar::a(); + foo::a(); // { dg-error "not been declared" } +}
[gcc r15-87] Cleanups to unsupported_range.
https://gcc.gnu.org/g:1b5732de7e3980aa5197b1ac818f48f1ce9f87ab commit r15-87-g1b5732de7e3980aa5197b1ac818f48f1ce9f87ab Author: Aldy Hernandez Date: Tue Apr 30 18:54:11 2024 +0200 Cleanups to unsupported_range. Here are some cleanups to unsupported_range so the assignment operator takes an unsupported_range and behaves like the other ranges. This makes subsequent cleanups easier. gcc/ChangeLog: * value-range.cc (unsupported_range::union_): Cast vrange to unsupported_range. (unsupported_range::intersect): Same. (unsupported_range::operator=): Make argument an unsupported_range. * value-range.h: New constructor. Diff: --- gcc/value-range.cc | 10 +++--- gcc/value-range.h | 7 ++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/gcc/value-range.cc b/gcc/value-range.cc index ca6d521c625..7250115261f 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -147,8 +147,10 @@ unsupported_range::set_varying (tree) } bool -unsupported_range::union_ (const vrange &r) +unsupported_range::union_ (const vrange &v) { + const unsupported_range &r = as_a (v); + if (r.undefined_p () || varying_p ()) return false; if (undefined_p () || r.varying_p ()) @@ -161,8 +163,10 @@ unsupported_range::union_ (const vrange &r) } bool -unsupported_range::intersect (const vrange &r) +unsupported_range::intersect (const vrange &v) { + const unsupported_range &r = as_a (v); + if (undefined_p () || r.varying_p ()) return false; if (r.undefined_p ()) @@ -216,7 +220,7 @@ unsupported_range::fits_p (const vrange &) const } unsupported_range & -unsupported_range::operator= (const vrange &r) +unsupported_range::operator= (const unsupported_range &r) { if (r.undefined_p ()) set_undefined (); diff --git a/gcc/value-range.h b/gcc/value-range.h index 11c73faca1b..471f362f388 100644 --- a/gcc/value-range.h +++ b/gcc/value-range.h @@ -389,6 +389,11 @@ public: { set_undefined (); } + unsupported_range (const unsupported_range &src) +: vrange (VR_UNKNOWN) + { +unsupported_range::operator= (src); + } void set (tree min, tree, value_range_kind = VR_RANGE) final override; tree type () const final override; bool supports_type_p (const_tree) const final override; @@ -405,7 +410,7 @@ public: void set_zero (tree type) final override; void set_nonnegative (tree type) final override; bool fits_p (const vrange &) const final override; - unsupported_range& operator= (const vrange &r); + unsupported_range& operator= (const unsupported_range &r); tree lbound () const final override; tree ubound () const final override; };
[gcc r15-88] Reduce startup costs for Value_Range.
https://gcc.gnu.org/g:c60b3e211c555706cdc2dc8bfcdd540152cff350 commit r15-88-gc60b3e211c555706cdc2dc8bfcdd540152cff350 Author: Aldy Hernandez Date: Tue Apr 30 19:39:00 2024 +0200 Reduce startup costs for Value_Range. Value_Range is our polymorphic temporary that can hold any range. It is used for type agnostic code where it isn't known ahead of time, what the type of the range will be (irange, france, etc). Currently, there is a temporary of each type in the object, which means we need to construct each range for every temporary. This isn't scaling well now that prange is about to add yet another range type. This patch removes each range, opting to use in-place new for a byte buffer sufficiently large to hold ranges of any type. It reduces the memory footprint by 14% for every Value_Range temporary (from 792 to 680 bytes), and we are guaranteed it will never again grow as we add more range types (strings, complex numbers, etc). Surprisingly, it improves VRP performance by 6.61% and overall compilation by 0.44%, which is a lot more than we bargained for when we started working on prange performance. There is a slight change in semantics for Value_Range. The default constructor does not initialize the object at all. It must be manually initialized with either Value_Range::set_type(), or by assigning a range to it. This means that IPA's m_known_value_ranges must be initialized at allocation, instead of depending on the empty constructor to initialize it to VR_UNDEFINED for unsupported_range. I have taken the time to properly document both the class, and each method. If anything isn't clear, please let me know so I can adjust it accordingly. gcc/ChangeLog: * ipa-fnsummary.cc (evaluate_properties_for_edge): Initialize Value_Range's. * value-range.h (class Value_Range): Add a buffer and remove m_irange and m_frange. (Value_Range::Value_Range): Call init. (Value_Range::set_type): Same. (Value_Range::init): Use in place new to initialize buffer. (Value_Range::operator=): Tidy. Diff: --- gcc/ipa-fnsummary.cc | 8 +++- gcc/value-range.h| 127 --- 2 files changed, 76 insertions(+), 59 deletions(-) diff --git a/gcc/ipa-fnsummary.cc b/gcc/ipa-fnsummary.cc index dff40cd8aa5..668a01ef175 100644 --- a/gcc/ipa-fnsummary.cc +++ b/gcc/ipa-fnsummary.cc @@ -681,8 +681,12 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p, if (!vr.undefined_p () && !vr.varying_p ()) { if (!avals->m_known_value_ranges.length ()) - avals->m_known_value_ranges.safe_grow_cleared (count, -true); + { + avals->m_known_value_ranges.safe_grow_cleared (count, + true); + for (int i = 0; i < count; ++i) + avals->m_known_value_ranges[i].set_type (void_type_node); + } avals->m_known_value_ranges[i] = vr; } } diff --git a/gcc/value-range.h b/gcc/value-range.h index 471f362f388..f1c638f8cd0 100644 --- a/gcc/value-range.h +++ b/gcc/value-range.h @@ -684,6 +684,16 @@ typedef int_range<2> value_range; // This is an "infinite" precision range object for use in temporary // calculations for any of the handled types. The object can be // transparently used as a vrange. +// +// Using any of the various constructors initializes the object +// appropriately, but the default constructor is uninitialized and +// must be initialized either with set_type() or by assigning into it. +// +// Assigning between incompatible types is allowed. For example if a +// temporary holds an irange, you can assign an frange into it, and +// all the right things will happen. However, before passing this +// object to a function accepting a vrange, the correct type must be +// set. If it isn't, you can do so with set_type(). class Value_Range { @@ -693,6 +703,7 @@ public: Value_Range (tree type); Value_Range (tree, tree, value_range_kind kind = VR_RANGE); Value_Range (const Value_Range &); + ~Value_Range (); void set_type (tree type); vrange& operator= (const vrange &); Value_Range& operator= (const Value_Range &); @@ -726,16 +737,29 @@ public: void accept (const vrange_visitor &v) const { m_vrange->accept (v); } private: void init (tree type); - unsupported_range m_unsupported; + void init (const vrange &); + vrange *m_vrange; - int_range_max m_irange; - frange m_frange; + // The buffer must be at least the size of the
[gcc r15-89] doc: Remove old details on libunwind for ia64-*-hpux*
https://gcc.gnu.org/g:81f7965e63028c1289ae3b1836750da74b01bc4a commit r15-89-g81f7965e63028c1289ae3b1836750da74b01bc4a Author: Gerald Pfeifer Date: Wed May 1 11:18:19 2024 +0200 doc: Remove old details on libunwind for ia64-*-hpux* gcc: PR target/69374 * doc/install.texi (Specific) : Remove details on libunwind for GCC 3.4 and earlier. Diff: --- gcc/doc/install.texi | 6 -- 1 file changed, 6 deletions(-) diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index b13c62ed2b7..4119304f66a 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -4316,12 +4316,6 @@ Building GCC on this target requires the GNU Assembler. The bundled HP assembler will not work. To prevent GCC from using the wrong assembler, the option @option{--with-gnu-as} may be necessary. -The GCC libunwind library has not been ported to HPUX@. This means that for -GCC versions 3.2.3 and earlier, @option{--enable-libunwind-exceptions} -is required to build GCC@. For GCC 3.3 and later, this is the default. -For gcc 3.4.3 and later, @option{--enable-libunwind-exceptions} is -removed and the system libunwind library will always be used. - @html
[gcc r15-90] doc: FreeBSD no longer has a GNU toolchain in base
https://gcc.gnu.org/g:0695aba3e987f4bb06c95f29ff90a8a3234e1507 commit r15-90-g0695aba3e987f4bb06c95f29ff90a8a3234e1507 Author: Gerald Pfeifer Date: Wed May 1 16:23:08 2024 +0200 doc: FreeBSD no longer has a GNU toolchain in base gcc: PR target/69374 PR target/112959 * doc/install.texi (Specific) <*-*-freebsd*>: No longer refer to GCC or binutils in base. Recommend bootstrap using binutils. Diff: --- gcc/doc/install.texi | 15 +-- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index 4119304f66a..b1d28dcb03b 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -4092,16 +4092,11 @@ This configuration is intended for embedded systems. We support FreeBSD using the ELF file format with DWARF 2 debugging for all CPU architectures. There are no known issues with mixing object files and libraries with different -debugging formats. Otherwise, this release of GCC should now match -more of the configuration used in the stock FreeBSD configuration of -GCC@. In particular, @option{--enable-threads} is now configured by -default. However, as a general user, do not attempt to replace the -system compiler with this release. - -The version of binutils installed in @file{/usr/bin} probably works -with this release of GCC@. Bootstrapping against the latest GNU -binutils and/or the version found in @file{/usr/ports/devel/binutils} has -been known to enable additional features and improve overall testsuite +debugging formats. + +We recommend bootstrapping against the latest GNU binutils or the +version found in the @file{devel/binutils} port. This also has been +known to enable additional features and improve overall testsuite results. @html
[gcc r15-91] c++: const void* memchr [PR113706]
https://gcc.gnu.org/g:c3bc2787b8beb7aae67fdf2a7f7271a9a4edca7c commit r15-91-gc3bc2787b8beb7aae67fdf2a7f7271a9a4edca7c Author: Jason Merrill Date: Mon Feb 12 18:24:00 2024 -0500 c++: const void* memchr [PR113706] The C++ standard specifies that the functions have const and non-const overloads, unlike C's single function with const argument and non-const return. Many systems don't actually implement this, but only add an overload with non-const argument, so both end up having non-const return. Solaris does what the standard says, but we were penalizing it by not recognizing the const overload as the built-in memchr. PR c++/113706 gcc/cp/ChangeLog: * decl.cc (decls_match): Handle memchr return type being const-qualified. gcc/testsuite/ChangeLog: * g++.dg/opt/const-builtin1.C: New test. * c-c++-common/pr103798-2.c: Remove xfail. Diff: --- gcc/cp/decl.cc| 10 ++ gcc/testsuite/c-c++-common/pr103798-2.c | 3 +-- gcc/testsuite/g++.dg/opt/const-builtin1.C | 33 +++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index d88e0698652..df855334133 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -1156,6 +1156,16 @@ decls_match (tree newdecl, tree olddecl, bool record_versions /* = true */) tree r2 = fndecl_declared_return_type (olddecl); tree r1 = fndecl_declared_return_type (newdecl); + /* For memchr et al, allow const void* return type (as specified by C++) +when we expect void* (as in C). */ + if (DECL_IS_UNDECLARED_BUILTIN (olddecl) + && DECL_EXTERN_C_P (olddecl) + && !same_type_p (r1, r2) + && TREE_CODE (r1) == POINTER_TYPE + && TREE_CODE (r2) == POINTER_TYPE + && comp_ptr_ttypes (TREE_TYPE (r1), TREE_TYPE (r2))) + r2 = r1; + tree p1 = TYPE_ARG_TYPES (f1); tree p2 = TYPE_ARG_TYPES (f2); diff --git a/gcc/testsuite/c-c++-common/pr103798-2.c b/gcc/testsuite/c-c++-common/pr103798-2.c index 83cdfaa1660..e7e99c3679e 100644 --- a/gcc/testsuite/c-c++-common/pr103798-2.c +++ b/gcc/testsuite/c-c++-common/pr103798-2.c @@ -27,5 +27,4 @@ main () return 0; } -/* See PR c++/113706 for the xfail. */ -/* { dg-final { scan-assembler-not "memchr" { xfail { c++ && { *-*-solaris2* *-*-vxworks* } } } } } */ +/* { dg-final { scan-assembler-not "memchr" } } */ diff --git a/gcc/testsuite/g++.dg/opt/const-builtin1.C b/gcc/testsuite/g++.dg/opt/const-builtin1.C new file mode 100644 index 000..8b9987271c0 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/const-builtin1.C @@ -0,0 +1,33 @@ +// PR c++/113706 +/* A variant of the pr103798-2.c test with const void * memchr return type, as + specified by the C++ standard. */ +/* { dg-do run } */ +/* { dg-options "-O2 -fdump-tree-optimized -save-temps" } */ + +extern "C" const void *memchr (const void *, int, __SIZE_TYPE__); // { dg-bogus "built-in" } + +__attribute__ ((weak)) +int +f (int a) +{ + return memchr ("aE", a, 2) != 0; +} + +__attribute__ ((weak)) +int +g (char a) +{ + return a == 'a' || a == 'E'; +} + +int +main () +{ + for (int i = 0; i < 255; i++) + if (f (i + 256) != g (i + 256)) + __builtin_abort (); + + return 0; +} + +/* { dg-final { scan-assembler-not "memchr" } } */
[gcc r15-92] libstdc++: Guard uses of is_pointer_interconvertible_v [PR114891]
https://gcc.gnu.org/g:1fbe1a50d86df11f434351cf62461a32747f9710 commit r15-92-g1fbe1a50d86df11f434351cf62461a32747f9710 Author: Jonathan Wakely Date: Tue Apr 30 09:48:00 2024 +0100 libstdc++: Guard uses of is_pointer_interconvertible_v [PR114891] This type trait isn't supported by Clang 18. It's only used in static assertions, so they can just be omitted if the trait isn't available. libstdc++-v3/ChangeLog: PR libstdc++/114891 * include/std/generator: Check feature test macro before using is_pointer_interconvertible_v. Diff: --- libstdc++-v3/include/std/generator | 8 1 file changed, 8 insertions(+) diff --git a/libstdc++-v3/include/std/generator b/libstdc++-v3/include/std/generator index 789016b5a88..1d5acc91420 100644 --- a/libstdc++-v3/include/std/generator +++ b/libstdc++-v3/include/std/generator @@ -322,8 +322,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template auto await_suspend(std::coroutine_handle<_Promise> __c) noexcept { +#ifdef __glibcxx_is_pointer_interconvertible static_assert(is_pointer_interconvertible_base_of_v< _Promise_erased, _Promise>); +#endif auto& __n = __c.promise()._M_nest; return __n._M_pop(); @@ -344,8 +346,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template void await_suspend(std::coroutine_handle<_Promise>) noexcept { +#ifdef __glibcxx_is_pointer_interconvertible static_assert(is_pointer_interconvertible_base_of_v< _Promise_erased, _Promise>); +#endif _M_bottom_value = ::std::addressof(_M_value); } @@ -375,8 +379,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION std::coroutine_handle<> await_suspend(std::coroutine_handle<_Promise> __p) noexcept { +#ifdef __glibcxx_is_pointer_interconvertible static_assert(is_pointer_interconvertible_base_of_v< _Promise_erased, _Promise>); +#endif auto __c = _Coro_handle::from_address(__p.address()); auto __t = _Coro_handle::from_address(this->_M_gen._M_coro.address()); @@ -685,8 +691,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return { coroutine_handle::from_promise(*this) }; } }; +#ifdef __glibcxx_is_pointer_interconvertible static_assert(is_pointer_interconvertible_base_of_v<_Erased_promise, promise_type>); +#endif generator(const generator&) = delete;
[gcc r15-93] [committed] [RISC-V] Fix detection of store pair fusion cases
https://gcc.gnu.org/g:fad93e7617ce1aafb006983a71b6edc9ae1eb2d1 commit r15-93-gfad93e7617ce1aafb006983a71b6edc9ae1eb2d1 Author: Jeff Law Date: Wed May 1 11:28:41 2024 -0600 [committed] [RISC-V] Fix detection of store pair fusion cases We've got the ability to count the number of store pair fusions happening in the front-end of the pipeline. When comparing some code from last year vs the current trunk we saw a fairly dramatic drop. The problem is the store pair fusion detection code was actively harmful due to a minor bug in checking offsets. So instead of pairing up 8 byte stores such as sp+0 with sp+8, it tried to pair up sp+8 and sp+16. Given uarch sensitivity I didn't try to pull together a testcase. But we could certainly see the undesirable behavior in benchmarks as simplistic as dhrystone up through spec2017. Anyway, bootstrapped a while back. Also verified through our performance counters that store pair fusion rates are back up. Regression tested with crosses a few minutes ago. gcc/ * config/riscv/riscv.cc (riscv_macro_fusion_pair_p): Break out tests for easier debugging in store pair fusion case. Fix offset check in same. Diff: --- gcc/config/riscv/riscv.cc | 57 ++- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 0f62b295b96..24d1ead3902 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -8874,26 +8874,43 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr) extract_base_offset_in_addr (SET_DEST (prev_set), &base_prev, &offset_prev); extract_base_offset_in_addr (SET_DEST (curr_set), &base_curr, &offset_curr); - /* The two stores must be contained within opposite halves of the same -16 byte aligned block of memory. We know that the stack pointer and -the frame pointer have suitable alignment. So we just need to check -the offsets of the two stores for suitable alignment. - -Originally the thought was to check MEM_ALIGN, but that was reporting -incorrect alignments, even for SP/FP accesses, so we gave up on that -approach. */ - if (base_prev != NULL_RTX - && base_curr != NULL_RTX - && REG_P (base_prev) - && REG_P (base_curr) - && REGNO (base_prev) == REGNO (base_curr) - && (REGNO (base_prev) == STACK_POINTER_REGNUM - || REGNO (base_prev) == HARD_FRAME_POINTER_REGNUM) - && ((INTVAL (offset_prev) == INTVAL (offset_curr) + 8 - && (INTVAL (offset_prev) % 16) == 0) - || ((INTVAL (offset_curr) == INTVAL (offset_prev) + 8) - && (INTVAL (offset_curr) % 16) == 0))) - return true; + /* Fail if we did not find both bases. */ + if (base_prev == NULL_RTX || base_curr == NULL_RTX) + return false; + + /* Fail if either base is not a register. */ + if (!REG_P (base_prev) || !REG_P (base_curr)) + return false; + + /* Fail if the bases are not the same register. */ + if (REGNO (base_prev) != REGNO (base_curr)) + return false; + + /* Originally the thought was to check MEM_ALIGN, but that was +reporting incorrect alignments, even for SP/FP accesses, so we +gave up on that approach. Instead just check for stack/hfp +which we know are aligned. */ + if (REGNO (base_prev) != STACK_POINTER_REGNUM + && REGNO (base_prev) != HARD_FRAME_POINTER_REGNUM) + return false; + + /* The two stores must be contained within opposite halves of the +same 16 byte aligned block of memory. We know that the stack +pointer and the frame pointer have suitable alignment. So we +just need to check the offsets of the two stores for suitable +alignment. */ + /* Get the smaller offset into OFFSET_PREV. */ + if (INTVAL (offset_prev) > INTVAL (offset_curr)) + std::swap (offset_prev, offset_curr); + + /* If the smaller offset (OFFSET_PREV) is not 16 byte aligned, +then fail. */ + if ((INTVAL (offset_prev) % 16) != 0) + return false; + + /* The higher offset must be 8 bytes more than the lower +offset. */ + return (INTVAL (offset_prev) + 8 == INTVAL (offset_curr)); } }
[gcc(refs/vendors/riscv/heads/gcc-14-with-riscv-opts)] [committed] [RISC-V] Fix detection of store pair fusion cases
https://gcc.gnu.org/g:b00f7226022a259211796781c9efb61645ad30a2 commit b00f7226022a259211796781c9efb61645ad30a2 Author: Jeff Law Date: Wed May 1 11:28:41 2024 -0600 [committed] [RISC-V] Fix detection of store pair fusion cases We've got the ability to count the number of store pair fusions happening in the front-end of the pipeline. When comparing some code from last year vs the current trunk we saw a fairly dramatic drop. The problem is the store pair fusion detection code was actively harmful due to a minor bug in checking offsets. So instead of pairing up 8 byte stores such as sp+0 with sp+8, it tried to pair up sp+8 and sp+16. Given uarch sensitivity I didn't try to pull together a testcase. But we could certainly see the undesirable behavior in benchmarks as simplistic as dhrystone up through spec2017. Anyway, bootstrapped a while back. Also verified through our performance counters that store pair fusion rates are back up. Regression tested with crosses a few minutes ago. gcc/ * config/riscv/riscv.cc (riscv_macro_fusion_pair_p): Break out tests for easier debugging in store pair fusion case. Fix offset check in same. (cherry picked from commit fad93e7617ce1aafb006983a71b6edc9ae1eb2d1) Diff: --- gcc/config/riscv/riscv.cc | 57 ++- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 0f62b295b96..24d1ead3902 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -8874,26 +8874,43 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr) extract_base_offset_in_addr (SET_DEST (prev_set), &base_prev, &offset_prev); extract_base_offset_in_addr (SET_DEST (curr_set), &base_curr, &offset_curr); - /* The two stores must be contained within opposite halves of the same -16 byte aligned block of memory. We know that the stack pointer and -the frame pointer have suitable alignment. So we just need to check -the offsets of the two stores for suitable alignment. - -Originally the thought was to check MEM_ALIGN, but that was reporting -incorrect alignments, even for SP/FP accesses, so we gave up on that -approach. */ - if (base_prev != NULL_RTX - && base_curr != NULL_RTX - && REG_P (base_prev) - && REG_P (base_curr) - && REGNO (base_prev) == REGNO (base_curr) - && (REGNO (base_prev) == STACK_POINTER_REGNUM - || REGNO (base_prev) == HARD_FRAME_POINTER_REGNUM) - && ((INTVAL (offset_prev) == INTVAL (offset_curr) + 8 - && (INTVAL (offset_prev) % 16) == 0) - || ((INTVAL (offset_curr) == INTVAL (offset_prev) + 8) - && (INTVAL (offset_curr) % 16) == 0))) - return true; + /* Fail if we did not find both bases. */ + if (base_prev == NULL_RTX || base_curr == NULL_RTX) + return false; + + /* Fail if either base is not a register. */ + if (!REG_P (base_prev) || !REG_P (base_curr)) + return false; + + /* Fail if the bases are not the same register. */ + if (REGNO (base_prev) != REGNO (base_curr)) + return false; + + /* Originally the thought was to check MEM_ALIGN, but that was +reporting incorrect alignments, even for SP/FP accesses, so we +gave up on that approach. Instead just check for stack/hfp +which we know are aligned. */ + if (REGNO (base_prev) != STACK_POINTER_REGNUM + && REGNO (base_prev) != HARD_FRAME_POINTER_REGNUM) + return false; + + /* The two stores must be contained within opposite halves of the +same 16 byte aligned block of memory. We know that the stack +pointer and the frame pointer have suitable alignment. So we +just need to check the offsets of the two stores for suitable +alignment. */ + /* Get the smaller offset into OFFSET_PREV. */ + if (INTVAL (offset_prev) > INTVAL (offset_curr)) + std::swap (offset_prev, offset_curr); + + /* If the smaller offset (OFFSET_PREV) is not 16 byte aligned, +then fail. */ + if ((INTVAL (offset_prev) % 16) != 0) + return false; + + /* The higher offset must be 8 bytes more than the lower +offset. */ + return (INTVAL (offset_prev) + 8 == INTVAL (offset_curr)); } }
[gcc r15-94] [committed] [RISC-V] Trivial pattern cleanup
https://gcc.gnu.org/g:76ca6e1f8b1524b82a871ce29cf58c79e5e77e2b commit r15-94-g76ca6e1f8b1524b82a871ce29cf58c79e5e77e2b Author: Jeff Law Date: Wed May 1 12:43:37 2024 -0600 [committed] [RISC-V] Trivial pattern cleanup As I was reviewing and cleaning up some internal work, I noticed a particular idiom being used elsewhere in the RISC-V backend. Specifically the use of explicit subregs when an adjustment to the match_operand would be sufficient. Let's take this example from the and-not splitter: > (define_split >[(set (match_operand:X 0 "register_operand") > (and:X (not:X (lshiftrt:X (match_operand:X 1 "register_operand") > (subreg:QI (match_operand:X 2 "register_operand") 0))) >(const_int 1)))] Note the explicit subreg. We can instead use a match_operand with QImode. This ever-so-slightly simplifies the machine description. It also means that if we have a QImode object lying around (say we loaded it from memory in QImode), we can use it directly rather than first extending it to X, then truncing to QI. So we end up with simpler RTL and in rare cases improve the code we generate. When used in a define_split or define_insn_and_split we need to make suitable adjustments to the split RTL. Bootstrapped a while back. Just re-tested with a cross. gcc/ * config/riscv/bitmanip.md (splitter to use w-form division): Remove explicit subregs. (zero extended bitfield extraction): Similarly. * config/riscv/thead.md (*th_memidx_operand): Similarly. Diff: --- gcc/config/riscv/bitmanip.md | 9 + gcc/config/riscv/thead.md| 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md index ccda25c01c1..ad3ad758959 100644 --- a/gcc/config/riscv/bitmanip.md +++ b/gcc/config/riscv/bitmanip.md @@ -50,11 +50,11 @@ (sign_extend:DI (div:SI (plus:SI (ashift:SI (subreg:SI (match_operand:DI 1 "register_operand") 0) (match_operand:QI 2 "imm123_operand")) (subreg:SI (match_operand:DI 3 "register_operand") 0)) - (subreg:SI (match_operand:DI 4 "register_operand") 0 + (match_operand:SI 4 "register_operand" (clobber (match_operand:DI 5 "register_operand"))] "TARGET_64BIT && TARGET_ZBA" [(set (match_dup 5) (plus:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3))) -(set (match_dup 0) (sign_extend:DI (div:SI (subreg:SI (match_dup 5) 0) (subreg:SI (match_dup 4) 0]) +(set (match_dup 0) (sign_extend:DI (div:SI (subreg:SI (match_dup 5) 0) (match_dup 4]) ; Zba does not provide W-forms of sh[123]add(.uw)?, which leads to an ; interesting irregularity: we can generate a signed 32-bit result @@ -722,13 +722,14 @@ (define_split [(set (match_operand:X 0 "register_operand") (and:X (not:X (lshiftrt:X (match_operand:X 1 "register_operand") - (subreg:QI (match_operand:X 2 "register_operand") 0))) + (match_operand:QI 2 "register_operand"))) (const_int 1)))] "TARGET_ZBS" [(set (match_dup 0) (zero_extract:X (match_dup 1) (const_int 1) (match_dup 2))) - (set (match_dup 0) (xor:X (match_dup 0) (const_int 1)))]) + (set (match_dup 0) (xor:X (match_dup 0) (const_int 1)))] + "operands[2] = gen_lowpart (mode, operands[2]);") ;; We can create a polarity-reversed mask (i.e. bit N -> { set = 0, clear = -1 }) ;; using a bext(i) followed by an addi instruction. diff --git a/gcc/config/riscv/thead.md b/gcc/config/riscv/thead.md index 5c7d4beb1b6..a47fe6f28b8 100644 --- a/gcc/config/riscv/thead.md +++ b/gcc/config/riscv/thead.md @@ -466,12 +466,12 @@ (define_insn_and_split "*th_memidx_operand" [(set (match_operand:DI 0 "register_operand" "=r") (ashift:DI - (zero_extend:DI (subreg:SI (match_operand:DI 1 "register_operand" "r") 0)) + (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) (match_operand 2 "const_int_operand" "n")))] "TARGET_64BIT && TARGET_XTHEADMEMIDX && lra_in_progress" "#" "" - [(set (match_dup 0) (zero_extend:DI (subreg:SI (match_dup 1) 0))) + [(set (match_dup 0) (zero_extend:DI (match_dup 1))) (set (match_dup 0) (ashift:DI (match_dup 0) (match_dup 2)))] "" [(set_attr "type" "bitmanip")])
[gcc(refs/vendors/riscv/heads/gcc-14-with-riscv-opts)] [committed] [RISC-V] Trivial pattern cleanup
https://gcc.gnu.org/g:990fa14f80e03260209b01823f3de859b9e72f66 commit 990fa14f80e03260209b01823f3de859b9e72f66 Author: Jeff Law Date: Wed May 1 12:43:37 2024 -0600 [committed] [RISC-V] Trivial pattern cleanup As I was reviewing and cleaning up some internal work, I noticed a particular idiom being used elsewhere in the RISC-V backend. Specifically the use of explicit subregs when an adjustment to the match_operand would be sufficient. Let's take this example from the and-not splitter: > (define_split >[(set (match_operand:X 0 "register_operand") > (and:X (not:X (lshiftrt:X (match_operand:X 1 "register_operand") > (subreg:QI (match_operand:X 2 "register_operand") 0))) >(const_int 1)))] Note the explicit subreg. We can instead use a match_operand with QImode. This ever-so-slightly simplifies the machine description. It also means that if we have a QImode object lying around (say we loaded it from memory in QImode), we can use it directly rather than first extending it to X, then truncing to QI. So we end up with simpler RTL and in rare cases improve the code we generate. When used in a define_split or define_insn_and_split we need to make suitable adjustments to the split RTL. Bootstrapped a while back. Just re-tested with a cross. gcc/ * config/riscv/bitmanip.md (splitter to use w-form division): Remove explicit subregs. (zero extended bitfield extraction): Similarly. * config/riscv/thead.md (*th_memidx_operand): Similarly. (cherry picked from commit 76ca6e1f8b1524b82a871ce29cf58c79e5e77e2b) Diff: --- gcc/config/riscv/bitmanip.md | 9 + gcc/config/riscv/thead.md| 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md index ccda25c01c1..ad3ad758959 100644 --- a/gcc/config/riscv/bitmanip.md +++ b/gcc/config/riscv/bitmanip.md @@ -50,11 +50,11 @@ (sign_extend:DI (div:SI (plus:SI (ashift:SI (subreg:SI (match_operand:DI 1 "register_operand") 0) (match_operand:QI 2 "imm123_operand")) (subreg:SI (match_operand:DI 3 "register_operand") 0)) - (subreg:SI (match_operand:DI 4 "register_operand") 0 + (match_operand:SI 4 "register_operand" (clobber (match_operand:DI 5 "register_operand"))] "TARGET_64BIT && TARGET_ZBA" [(set (match_dup 5) (plus:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3))) -(set (match_dup 0) (sign_extend:DI (div:SI (subreg:SI (match_dup 5) 0) (subreg:SI (match_dup 4) 0]) +(set (match_dup 0) (sign_extend:DI (div:SI (subreg:SI (match_dup 5) 0) (match_dup 4]) ; Zba does not provide W-forms of sh[123]add(.uw)?, which leads to an ; interesting irregularity: we can generate a signed 32-bit result @@ -722,13 +722,14 @@ (define_split [(set (match_operand:X 0 "register_operand") (and:X (not:X (lshiftrt:X (match_operand:X 1 "register_operand") - (subreg:QI (match_operand:X 2 "register_operand") 0))) + (match_operand:QI 2 "register_operand"))) (const_int 1)))] "TARGET_ZBS" [(set (match_dup 0) (zero_extract:X (match_dup 1) (const_int 1) (match_dup 2))) - (set (match_dup 0) (xor:X (match_dup 0) (const_int 1)))]) + (set (match_dup 0) (xor:X (match_dup 0) (const_int 1)))] + "operands[2] = gen_lowpart (mode, operands[2]);") ;; We can create a polarity-reversed mask (i.e. bit N -> { set = 0, clear = -1 }) ;; using a bext(i) followed by an addi instruction. diff --git a/gcc/config/riscv/thead.md b/gcc/config/riscv/thead.md index 5c7d4beb1b6..a47fe6f28b8 100644 --- a/gcc/config/riscv/thead.md +++ b/gcc/config/riscv/thead.md @@ -466,12 +466,12 @@ (define_insn_and_split "*th_memidx_operand" [(set (match_operand:DI 0 "register_operand" "=r") (ashift:DI - (zero_extend:DI (subreg:SI (match_operand:DI 1 "register_operand" "r") 0)) + (zero_extend:DI (match_operand:SI 1 "register_operand" "r")) (match_operand 2 "const_int_operand" "n")))] "TARGET_64BIT && TARGET_XTHEADMEMIDX && lra_in_progress" "#" "" - [(set (match_dup 0) (zero_extend:DI (subreg:SI (match_dup 1) 0))) + [(set (match_dup 0) (zero_extend:DI (match_dup 1))) (set (match_dup 0) (ashift:DI (match_dup 0) (match_dup 2)))] "" [(set_attr "type" "bitmanip")])
[gcc r15-95] c++: drop in-charge for dtors without vbases
https://gcc.gnu.org/g:a12cae973900f118436ef85c1197e91bf0428280 commit r15-95-ga12cae973900f118436ef85c1197e91bf0428280 Author: Jason Merrill Date: Tue Dec 12 18:07:28 2023 -0500 c++: drop in-charge for dtors without vbases Constructors and destructors use the in-charge parameter to decide whether they're responsible for recursing into virtual bases. Historically all destructors had this parameter in order to also distinguish the deleting destructor. But r151673 in GCC 4.5 changed the deleting destructor to just call the complete destructor and then operator delete, making the in-charge parameter no longer relevant for destructors in classes without virtual bases. Having it causes confusion in constexpr evaluation, which assumes that clones will have the same parameters as the cloned 'tor. gcc/cp/ChangeLog: * cp-tree.h (base_ctor_identifier): Adjust comment. * call.cc (in_charge_arg_for_name): Abort on deleting dtor. * decl2.cc (maybe_retrofit_in_chrg): Don't add it for destructors without vbases, either. * constexpr.cc (cxx_eval_call_expression): Remove workaround. gcc/testsuite/ChangeLog: * g++.dg/debug/dwarf2/array-3.C: No more 'int' for in-chrg parm. * g++.dg/debug/dwarf2/array-4.C: Likewise. Diff: --- gcc/cp/cp-tree.h| 3 +-- gcc/cp/call.cc | 4 +++- gcc/cp/constexpr.cc | 20 +++- gcc/cp/decl2.cc | 12 gcc/testsuite/g++.dg/debug/dwarf2/array-3.C | 6 +++--- gcc/testsuite/g++.dg/debug/dwarf2/array-4.C | 2 +- 6 files changed, 19 insertions(+), 28 deletions(-) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 1938ada0268..5d1bd6ba493 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -289,8 +289,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; /* The name of a constructor that does not construct virtual base classes. */ #define base_ctor_identifier cp_global_trees[CPTI_BASE_CTOR_IDENTIFIER] /* The name of a destructor that takes an in-charge parameter to - decide whether or not to destroy virtual base classes and whether - or not to delete the object. */ + decide whether or not to destroy virtual base classes. */ #define dtor_identifier cp_global_trees[CPTI_DTOR_IDENTIFIER] /* The name of a destructor that destroys virtual base classes. */ #define complete_dtor_identifier cp_global_trees[CPTI_COMPLETE_DTOR_IDENTIFIER] diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index dbdd7c29fe8..7c4ecf08c4b 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -11167,7 +11167,9 @@ in_charge_arg_for_name (tree name) if (name == complete_dtor_identifier) return integer_two_node; else if (name == deleting_dtor_identifier) - return integer_three_node; + /* The deleting dtor should now be handled by + build_delete_destructor_body. */ + gcc_unreachable (); gcc_checking_assert (name == base_dtor_identifier); } diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index 8078b31544d..50f799d7ff7 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -3243,19 +3243,13 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, ctx->global->put_value (remapped, arg); remapped = DECL_CHAIN (remapped); } - for (; remapped; remapped = TREE_CHAIN (remapped)) - if (DECL_NAME (remapped) == in_charge_identifier) - { - /* FIXME destructors unnecessarily have in-charge parameters - even in classes without vbases, map it to 0 for now. */ - gcc_assert (!CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fun))); - ctx->global->put_value (remapped, integer_zero_node); - } - else - { - gcc_assert (seen_error ()); - *non_constant_p = true; - } + if (remapped) + { + /* We shouldn't have any parms without args, but fail gracefully +in error recovery. */ + gcc_checking_assert (seen_error ()); + *non_constant_p = true; + } /* Add the RESULT_DECL to the values map, too. */ gcc_assert (!DECL_BY_REFERENCE (res)); ctx->global->put_value (res, NULL_TREE); diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc index 806a2a4bc69..b8dc55b51d9 100644 --- a/gcc/cp/decl2.cc +++ b/gcc/cp/decl2.cc @@ -275,11 +275,8 @@ build_artificial_parm (tree fn, tree name, tree type) return parm; } -/* Constructors for types with virtual baseclasses need an "in-charge" flag - saying whether this constructor is responsible for initialization of - virtual baseclasses or not. All destructors also need this "in-charge" - flag, which
[gcc r13-8667] c++: __is_constructible ref binding [PR100667]
https://gcc.gnu.org/g:19821ce86afa0f4ce0d2312b16864c809e605be9 commit r13-8667-g19821ce86afa0f4ce0d2312b16864c809e605be9 Author: Jason Merrill Date: Wed Mar 27 16:14:01 2024 -0400 c++: __is_constructible ref binding [PR100667] The requirement that a type argument be complete is excessive in the case of direct reference binding to the same type, which does not rely on any properties of the type. This is LWG 2939. PR c++/100667 gcc/cp/ChangeLog: * semantics.cc (same_type_ref_bind_p): New. (finish_trait_expr): Use it. gcc/testsuite/ChangeLog: * g++.dg/ext/is_constructible8.C: New test. (cherry picked from commit 8bb3ef3f6e335e8794590fb712a2661d11d21973) Diff: --- gcc/cp/semantics.cc | 50 ++-- gcc/testsuite/g++.dg/ext/is_constructible8.C | 31 + 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 3bf478fd68c..079ad5c93bf 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -12176,6 +12176,47 @@ check_trait_type (tree type, int kind = 1) return true; } +/* True iff the conversion (if any) would be a direct reference + binding, not requiring complete types. This is LWG2939. */ + +static bool +same_type_ref_bind_p (cp_trait_kind kind, tree type1, tree type2) +{ + tree from, to; + switch (kind) +{ + /* These put the target type first. */ +case CPTK_IS_CONSTRUCTIBLE: +case CPTK_IS_NOTHROW_CONSTRUCTIBLE: +case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE: +case CPTK_REF_CONSTRUCTS_FROM_TEMPORARY: +case CPTK_REF_CONVERTS_FROM_TEMPORARY: + to = type1; + from = type2; + break; + + /* These put it second. */ +case CPTK_IS_CONVERTIBLE: +case CPTK_IS_NOTHROW_CONVERTIBLE: + to = type2; + from = type1; + break; + +default: + gcc_unreachable (); +} + + if (TREE_CODE (to) != REFERENCE_TYPE || !from) +return false; + if (TREE_CODE (from) == TREE_VEC && TREE_VEC_LENGTH (from) == 1) +from = TREE_VEC_ELT (from, 0); + else if (TREE_CODE (from) == TREE_LIST && !TREE_CHAIN (from)) +from = TREE_VALUE (from); + return (TYPE_P (from) + && (same_type_ignoring_top_level_qualifiers_p + (non_reference (to), non_reference (from; +} + /* Process a trait expression. */ tree @@ -12241,14 +12282,19 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2) return error_mark_node; break; -case CPTK_IS_TRIVIALLY_ASSIGNABLE: case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE: -case CPTK_IS_NOTHROW_ASSIGNABLE: case CPTK_IS_NOTHROW_CONSTRUCTIBLE: case CPTK_IS_CONVERTIBLE: case CPTK_IS_NOTHROW_CONVERTIBLE: case CPTK_REF_CONSTRUCTS_FROM_TEMPORARY: case CPTK_REF_CONVERTS_FROM_TEMPORARY: + /* Don't check completeness for direct reference binding. */; + if (same_type_ref_bind_p (kind, type1, type2)) + break; + gcc_fallthrough (); + +case CPTK_IS_NOTHROW_ASSIGNABLE: +case CPTK_IS_TRIVIALLY_ASSIGNABLE: if (!check_trait_type (type1) || !check_trait_type (type2)) return error_mark_node; diff --git a/gcc/testsuite/g++.dg/ext/is_constructible8.C b/gcc/testsuite/g++.dg/ext/is_constructible8.C new file mode 100644 index 000..a27ec6eddd7 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_constructible8.C @@ -0,0 +1,31 @@ +// PR c++/100667 +// { dg-do compile { target c++11 } } + +struct T; + +#define SA(X) static_assert ((X), #X); + +SA (__is_constructible(T&&, T)); +SA (__is_constructible(const T&, T)); +SA (!__is_constructible(T&, T)); +SA (__is_nothrow_constructible(T&&, T)); +SA (__is_nothrow_constructible(const T&, T)); +SA (!__is_nothrow_constructible(T&, T)); +SA (__is_trivially_constructible(T&&, T)); +SA (__is_trivially_constructible(const T&, T)); +SA (!__is_trivially_constructible(T&, T)); + +SA (__is_convertible(T, T&&)); +SA (__is_convertible(T, const T&)); +SA (!__is_convertible(T, T&)); +SA (__is_nothrow_convertible(T, T&&)); +SA (__is_nothrow_convertible(T, const T&)); +SA (!__is_nothrow_convertible(T, T&)); + +// All false because either the conversion fails or it doesn't bind a temporary +SA (!__reference_constructs_from_temporary (T&&, T)); +SA (!__reference_constructs_from_temporary (const T&, T)); +SA (!__reference_constructs_from_temporary (T&, T)); +SA (!__reference_converts_from_temporary (T&&, T)); +SA (!__reference_converts_from_temporary (const T&, T)); +SA (!__reference_converts_from_temporary (T&, T));
[gcc r13-8668] c++: binding reference to comma expr [PR114561]
https://gcc.gnu.org/g:7bc362ea61e5bf552356aa862beb7845fe50a47c commit r13-8668-g7bc362ea61e5bf552356aa862beb7845fe50a47c Author: Jason Merrill Date: Tue Apr 2 10:52:28 2024 -0400 c++: binding reference to comma expr [PR114561] We represent a reference binding where the referent type is more qualified by a ck_ref_bind around a ck_qual. We performed the ck_qual and then tried to undo it with STRIP_NOPS, but that doesn't work if the conversion is buried in COMPOUND_EXPR. So instead let's avoid performing that fake conversion in the first place. PR c++/114561 PR c++/114562 gcc/cp/ChangeLog: * call.cc (convert_like_internal): Avoid adding qualification conversion in direct reference binding. gcc/testsuite/ChangeLog: * g++.dg/conversion/ref10.C: New test. * g++.dg/conversion/ref11.C: New test. (cherry picked from commit 5d7e9a35024f065b25f61747859c7cb7a770c92b) Diff: --- gcc/cp/call.cc | 23 +-- gcc/testsuite/g++.dg/conversion/ref10.C | 5 + gcc/testsuite/g++.dg/conversion/ref11.C | 33 + 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index d012680f185..b10bdc62d38 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -8632,7 +8632,15 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, break; }; - expr = convert_like (next_conversion (convs), expr, fn, argnum, + conversion *nc = next_conversion (convs); + if (convs->kind == ck_ref_bind && nc->kind == ck_qual + && !convs->need_temporary_p) +/* direct_reference_binding might have inserted a ck_qual under + this ck_ref_bind for the benefit of conversion sequence ranking. + Don't actually perform that conversion. */ +nc = next_conversion (nc); + + expr = convert_like (nc, expr, fn, argnum, convs->kind == ck_ref_bind ? issue_conversion_warnings : false, c_cast_p, /*nested_p=*/true, complain & ~tf_no_cleanup); @@ -8710,19 +8718,6 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, { tree ref_type = totype; - /* direct_reference_binding might have inserted a ck_qual under - this ck_ref_bind for the benefit of conversion sequence ranking. - Ignore the conversion; we'll create our own below. */ - if (next_conversion (convs)->kind == ck_qual - && !convs->need_temporary_p) - { - gcc_assert (same_type_p (TREE_TYPE (expr), -next_conversion (convs)->type)); - /* Strip the cast created by the ck_qual; cp_build_addr_expr - below expects an lvalue. */ - STRIP_NOPS (expr); - } - if (convs->bad_p && !next_conversion (convs)->bad_p) { tree extype = TREE_TYPE (expr); diff --git a/gcc/testsuite/g++.dg/conversion/ref10.C b/gcc/testsuite/g++.dg/conversion/ref10.C new file mode 100644 index 000..1913f733a6b --- /dev/null +++ b/gcc/testsuite/g++.dg/conversion/ref10.C @@ -0,0 +1,5 @@ +// PR c++/114561 + +void create(void* u) { + const void* const& r = ( (void)0, u ); +} diff --git a/gcc/testsuite/g++.dg/conversion/ref11.C b/gcc/testsuite/g++.dg/conversion/ref11.C new file mode 100644 index 000..bb9b835034c --- /dev/null +++ b/gcc/testsuite/g++.dg/conversion/ref11.C @@ -0,0 +1,33 @@ +// PR c++/114562 +// { dg-do compile { target c++11 } } + +template +struct Optional { + Optional(T&&); +}; + +struct MyClass { + MyClass(Optional); +}; + +// const void* NONE = nullptr; // Correct Error +void* NONE = nullptr; // Crash + +void beforeParam(); + +template +struct Create { + template static T create(U &&) noexcept; +}; + + +template +template +T Create::create(U && u) noexcept { + return T( ( (beforeParam()), (u) ) ); // { dg-error "cannot bind rvalue reference" } + // return T( (u) ); // Correct Error +} + +void test_func() { + Create::create(NONE); +}
[gcc r13-8669] c++: alias CTAD and template template parm [PR114377]
https://gcc.gnu.org/g:60e1e13f458f1fcfb05a30ace57fa682461e2732 commit r13-8669-g60e1e13f458f1fcfb05a30ace57fa682461e2732 Author: centurion Date: Wed Mar 27 18:36:37 2024 + c++: alias CTAD and template template parm [PR114377] To match all the other places that pull a _TEMPLATE_PARM out of a _DECL (get_template_parm_index, etc.). This change is too small to be legally significant for copyright. PR c++/114377 gcc/cp/ChangeLog: * pt.cc (find_template_parameter_info::found): Use TREE_TYPE for TEMPLATE_DECL instead of DECL_INITIAL. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/class-deduction-alias19.C: New test. Reviewed-by: Jason Merrill (cherry picked from commit 801e82acd6b4f0cf863529875947e394899ea7b9) Diff: --- gcc/cp/pt.cc | 3 ++- gcc/testsuite/g++.dg/cpp2a/class-deduction-alias19.C | 15 +++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index a768d11c82f..fa660fcf49e 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -10917,7 +10917,8 @@ find_template_parameter_info::found (tree parm) { if (TREE_CODE (parm) == TREE_LIST) parm = TREE_VALUE (parm); - if (TREE_CODE (parm) == TYPE_DECL) + if (TREE_CODE (parm) == TYPE_DECL + || TREE_CODE (parm) == TEMPLATE_DECL) parm = TREE_TYPE (parm); else parm = DECL_INITIAL (parm); diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias19.C b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias19.C new file mode 100644 index 000..1ea79bd7691 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias19.C @@ -0,0 +1,15 @@ +// PR c++/114377 +// { dg-do compile { target c++20 } } + +template typename Iterator> +struct K {}; + +template +class Foo {}; + +template typename TTP> +using Bar = Foo>; + +void s() { +Bar(1); // { dg-error "failed|no match" } +}
[gcc r13-8670] c++: problematic assert in reference_binding [PR113141]
https://gcc.gnu.org/g:c70abea054fe0021b7b2c2e07996afaadc17a07b commit r13-8670-gc70abea054fe0021b7b2c2e07996afaadc17a07b Author: Patrick Palka Date: Wed May 1 18:16:08 2024 -0400 c++: problematic assert in reference_binding [PR113141] r14-9946 / r14-9947 fixed this PR properly for GCC 14. For GCC 13, let's just remove the problematic assert. PR c++/113141 gcc/cp/ChangeLog: * call.cc (reference_binding): Remove badness criteria sanity check in the recursive case. gcc/testsuite/ChangeLog: * g++.dg/conversion/ref12.C: New test. * g++.dg/cpp0x/initlist-ref1.C: new test. Diff: --- gcc/cp/call.cc | 1 - gcc/testsuite/g++.dg/conversion/ref12.C| 13 + gcc/testsuite/g++.dg/cpp0x/initlist-ref1.C | 16 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index b10bdc62d38..70c7f6178b8 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -2017,7 +2017,6 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, if (!new_second) return NULL; conv = merge_conversion_sequences (t, new_second); - gcc_assert (maybe_valid_p || conv->bad_p); return conv; } } diff --git a/gcc/testsuite/g++.dg/conversion/ref12.C b/gcc/testsuite/g++.dg/conversion/ref12.C new file mode 100644 index 000..633b7e48e47 --- /dev/null +++ b/gcc/testsuite/g++.dg/conversion/ref12.C @@ -0,0 +1,13 @@ +// PR c++/113141 + +struct Matrix { }; + +struct TPoint3 { operator const Matrix(); }; + +void f(Matrix&); + +int main() { + TPoint3 X; + Matrix& m = (Matrix &)X; + f((Matrix &)X); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-ref1.C b/gcc/testsuite/g++.dg/cpp0x/initlist-ref1.C new file mode 100644 index 000..f893f12dafa --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-ref1.C @@ -0,0 +1,16 @@ +// PR c++/113141 +// { dg-do compile { target c++11 } } + +struct ConvToRef { + operator int&(); +}; + +struct A { int& r; }; + +void f(A); + +int main() { + ConvToRef c; + A a{{c}}; + f({{c}}); +}
[gcc r15-96] doc: Describe limitations re Ada, D, and Go on FreeBSD
https://gcc.gnu.org/g:ff98aab108a6a4e50a831e7cfc011c2131f8d19c commit r15-96-gff98aab108a6a4e50a831e7cfc011c2131f8d19c Author: Gerald Pfeifer Date: Thu May 2 00:45:52 2024 +0200 doc: Describe limitations re Ada, D, and Go on FreeBSD gcc: PR target/69374 PR target/112959 * doc/install.texi (Specific) <*-*-freebsd*>: The Ada and D run-time libraries are broken on i386 which also can affect 64-bit builds. Go is broken. Diff: --- gcc/doc/install.texi | 8 1 file changed, 8 insertions(+) diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index b1d28dcb03b..9f2e427be68 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -4099,6 +4099,14 @@ version found in the @file{devel/binutils} port. This also has been known to enable additional features and improve overall testsuite results. +@c Bugs 112958 and 112957 +Ada and D (or rather their respective libraries) are broken on +FreeBSD/i386. This also affects building 32-bit libraries on +FreeBSD/amd64, so configure with @option{--disable-multilib} +there in case you are building one of these front ends. + +Go (or rather libgo) is generally broken on FreeBSD. + @html @end html
[gcc r15-98] c++: Implement modules ABI for vtable emissions
https://gcc.gnu.org/g:ad30265ccfb211fca35789df2d1404cc12302219 commit r15-98-gad30265ccfb211fca35789df2d1404cc12302219 Author: Nathaniel Shead Date: Tue Apr 16 22:50:26 2024 +1000 c++: Implement modules ABI for vtable emissions This patch implements the changes described in https://github.com/itanium-cxx-abi/cxx-abi/pull/171. One restriction that is lifted in the ABI that hasn't been updated here is that the ABI no longer requires unique vtables to be emitted with vague linkage. I haven't changed this behaviour for this patch, but in the future we could look into changing the relevant target hook ('class_data_always_comdat') to default to 'false'. But the current behaviour is more forgiving to changes in key function identification. Since the ABI for vtables attached to named modules no longer depends on key methods, this also resolves the issue described in PR c++/105224. PR c++/105224 gcc/cp/ChangeLog: * class.cc (finish_struct_1): Also push classes attached to a module into the 'keyed_classes' list. * decl.cc (record_key_method_defined): Don't push classes attached to a named module into the 'keyed_classes' list. * module.cc (trees_in::read_class_def): Likewise. * decl2.cc (import_export_class): Uniquely emit vtables for non-template classes attached to a named module. (vtables_uniquely_emitted): New function. (import_export_decl): Update comments. Update with knowledge about new kinds of uniquely emitted vtables. gcc/testsuite/ChangeLog: * g++.dg/modules/virt-2_a.C: Update linkage requirements. * g++.dg/modules/virt-2_b.C: Likewise. * g++.dg/modules/virt-2_c.C: Likewise. * g++.dg/modules/virt-4_a.C: New test. * g++.dg/modules/virt-4_b.C: New test. Signed-off-by: Nathaniel Shead Reviewed-by: Jason Merrill Diff: --- gcc/cp/class.cc | 7 ++- gcc/cp/decl.cc | 8 ++- gcc/cp/decl2.cc | 102 +--- gcc/cp/module.cc| 12 ++-- gcc/testsuite/g++.dg/modules/virt-2_a.C | 3 - gcc/testsuite/g++.dg/modules/virt-2_b.C | 9 +-- gcc/testsuite/g++.dg/modules/virt-2_c.C | 10 ++-- gcc/testsuite/g++.dg/modules/virt-4_a.C | 31 ++ gcc/testsuite/g++.dg/modules/virt-4_b.C | 23 +++ 9 files changed, 151 insertions(+), 54 deletions(-) diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc index 5f258729940..5ef7c71af61 100644 --- a/gcc/cp/class.cc +++ b/gcc/cp/class.cc @@ -7820,8 +7820,11 @@ finish_struct_1 (tree t) /* If a polymorphic class has no key method, we may emit the vtable in every translation unit where the class definition appears. If we're devirtualizing, we can look into the vtable even if we -aren't emitting it. */ - if (!CLASSTYPE_KEY_METHOD (t)) +aren't emitting it. + +Additionally, if the class is attached to a named module, make sure +to always emit the vtable in this TU. */ + if (!CLASSTYPE_KEY_METHOD (t) || module_attach_p ()) vec_safe_push (keyed_classes, t); } diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index df855334133..de0c02a39ee 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -18481,7 +18481,13 @@ record_key_method_defined (tree fndecl) { tree fnclass = DECL_CONTEXT (fndecl); if (fndecl == CLASSTYPE_KEY_METHOD (fnclass)) - vec_safe_push (keyed_classes, fnclass); + { + tree classdecl = TYPE_NAME (fnclass); + /* Classes attached to a named module are already handled. */ + if (!DECL_LANG_SPECIFIC (classdecl) + || !DECL_MODULE_ATTACH_P (classdecl)) + vec_safe_push (keyed_classes, fnclass); + } } } diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc index b8dc55b51d9..1f84878b2b9 100644 --- a/gcc/cp/decl2.cc +++ b/gcc/cp/decl2.cc @@ -2422,17 +2422,26 @@ import_export_class (tree ctype) import_export = -1; else if (TYPE_POLYMORPHIC_P (ctype)) { - /* The ABI specifies that the virtual table and associated -information are emitted with the key method, if any. */ - tree method = CLASSTYPE_KEY_METHOD (ctype); - /* If weak symbol support is not available, then we must be -careful not to emit the vtable when the key function is -inline. An inline function can be defined in multiple -translation units. If we were to emit the vtable in each -translation unit containing a definition, we would get -multiple definition errors at link-time. */ - if (method && (flag_weak || ! DECL_DECLARED_INLINE_P (method))) - import_export = (DECL_REALLY_EXTERN (method) ? -1 : 1); + tree cdecl = TYPE_NAME (ctype); + if
[gcc r13-8672] rs6000: Replace OPTION_MASK_DIRECT_MOVE with OPTION_MASK_P8_VECTOR [PR101865]
https://gcc.gnu.org/g:d42105742841e73ca867b6da0c5ca6ad4d86fed6 commit r13-8672-gd42105742841e73ca867b6da0c5ca6ad4d86fed6 Author: Peter Bergner Date: Tue Apr 9 15:24:39 2024 -0500 rs6000: Replace OPTION_MASK_DIRECT_MOVE with OPTION_MASK_P8_VECTOR [PR101865] This is a cleanup patch in preparation to fixing the real bug in PR101865. TARGET_DIRECT_MOVE is redundant with TARGET_P8_VECTOR, so alias it to that. Also replace all usages of OPTION_MASK_DIRECT_MOVE with OPTION_MASK_P8_VECTOR and delete the now dead mask. 2024-04-09 Peter Bergner gcc/ PR target/101865 * config/rs6000/rs6000.h (TARGET_DIRECT_MOVE): Define. * config/rs6000/rs6000.cc (rs6000_option_override_internal): Replace OPTION_MASK_DIRECT_MOVE with OPTION_MASK_P8_VECTOR. Delete redundant OPTION_MASK_DIRECT_MOVE usage. Delete TARGET_DIRECT_MOVE dead code. (rs6000_opt_masks): Neuter the "direct-move" option. * config/rs6000/rs6000-c.cc (rs6000_target_modify_macros): Replace OPTION_MASK_DIRECT_MOVE with OPTION_MASK_P8_VECTOR. Delete useless comment. * config/rs6000/rs6000-cpus.def (ISA_2_7_MASKS_SERVER): Delete OPTION_MASK_DIRECT_MOVE. (OTHER_P8_VECTOR_MASKS): Likewise. (POWERPC_MASKS): Likewise. * config/rs6000/rs6000.opt (mdirect-move): Remove Mask and Var. (cherry picked from commit 7924e352523b37155ed9d76dc426701de9d11a22) Diff: --- gcc/config/rs6000/rs6000-c.cc | 14 +- gcc/config/rs6000/rs6000-cpus.def | 3 --- gcc/config/rs6000/rs6000.cc | 14 +++--- gcc/config/rs6000/rs6000.h| 2 ++ gcc/config/rs6000/rs6000.opt | 2 +- 5 files changed, 7 insertions(+), 28 deletions(-) diff --git a/gcc/config/rs6000/rs6000-c.cc b/gcc/config/rs6000/rs6000-c.cc index 8555174d36e..2bedc0fc938 100644 --- a/gcc/config/rs6000/rs6000-c.cc +++ b/gcc/config/rs6000/rs6000-c.cc @@ -429,19 +429,7 @@ rs6000_target_modify_macros (bool define_p, HOST_WIDE_INT flags) rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR6"); if ((flags & OPTION_MASK_POPCNTD) != 0) rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR7"); - /* Note that the OPTION_MASK_DIRECT_MOVE flag is automatically - turned on in the following condition: - 1. TARGET_P8_VECTOR is enabled and OPTION_MASK_DIRECT_MOVE is not -explicitly disabled. -Hereafter, the OPTION_MASK_DIRECT_MOVE flag is considered to -have been turned on explicitly. - Note that the OPTION_MASK_DIRECT_MOVE flag is automatically - turned off in any of the following conditions: - 1. TARGET_HARD_FLOAT, TARGET_ALTIVEC, or TARGET_VSX is explicitly - disabled and OPTION_MASK_DIRECT_MOVE was not explicitly - enabled. - 2. TARGET_VSX is off. */ - if ((flags & OPTION_MASK_DIRECT_MOVE) != 0) + if ((flags & OPTION_MASK_P8_VECTOR) != 0) rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR8"); if ((flags & OPTION_MASK_MODULO) != 0) rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR9"); diff --git a/gcc/config/rs6000/rs6000-cpus.def b/gcc/config/rs6000/rs6000-cpus.def index 4f350da378c..4f8d07b9a0d 100644 --- a/gcc/config/rs6000/rs6000-cpus.def +++ b/gcc/config/rs6000/rs6000-cpus.def @@ -49,7 +49,6 @@ #define ISA_2_7_MASKS_SERVER (ISA_2_6_MASKS_SERVER \ | OPTION_MASK_P8_VECTOR\ | OPTION_MASK_CRYPTO \ -| OPTION_MASK_DIRECT_MOVE \ | OPTION_MASK_EFFICIENT_UNALIGNED_VSX \ | OPTION_MASK_QUAD_MEMORY \ | OPTION_MASK_QUAD_MEMORY_ATOMIC) @@ -93,7 +92,6 @@ /* Flags that need to be turned off if -mno-power8-vector. */ #define OTHER_P8_VECTOR_MASKS (OTHER_P9_VECTOR_MASKS \ | OPTION_MASK_P9_VECTOR\ -| OPTION_MASK_DIRECT_MOVE \ | OPTION_MASK_CRYPTO) /* Flags that need to be turned off if -mno-vsx. */ @@ -124,7 +122,6 @@ | OPTION_MASK_CMPB \ | OPTION_MASK_CRYPTO \ | OPTION_MASK_DFP \ -| OPTION_MASK_DIRECT_MOVE \ | OPTION_MASK_DLMZB\ | OPTION_MASK_EFFICIENT_UNALIGNED_VSX \ | OPTION_MASK_FLOAT128_HW \ diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index e5ceff3a61b..4d8740202b7 100644 --- a/gcc/config/rs6000/rs6000.cc +++
[gcc r13-8673] rs6000: Add OPTION_MASK_POWER8 [PR101865]
https://gcc.gnu.org/g:0ae9252f7b52151209b36d8a1cefc49f1b23fa46 commit r13-8673-g0ae9252f7b52151209b36d8a1cefc49f1b23fa46 Author: Will Schmidt Date: Fri Apr 12 14:55:16 2024 -0500 rs6000: Add OPTION_MASK_POWER8 [PR101865] The bug in PR101865 is the _ARCH_PWR8 predefine macro is conditional upon TARGET_DIRECT_MOVE, which can be false for some -mcpu=power8 compiles if the -mno-altivec or -mno-vsx options are used. The solution here is to create a new OPTION_MASK_POWER8 mask that is true for -mcpu=power8, regardless of Altivec or VSX enablement. Unfortunately, the only way to create an OPTION_MASK_* mask is to create a new option, which we have done here, but marked it as WarnRemoved since we do not want users using it. For stage1, we will look into how we can create ISA mask flags for use in the compiler without the need for explicit options. 2024-04-12 Will Schmidt Peter Bergner gcc/ PR target/101865 * config/rs6000/rs6000-builtin.cc (rs6000_builtin_is_supported): Use TARGET_POWER8. * config/rs6000/rs6000-c.cc (rs6000_target_modify_macros): Use OPTION_MASK_POWER8. * config/rs6000/rs6000-cpus.def (POWERPC_MASKS): Add OPTION_MASK_POWER8. (ISA_2_7_MASKS_SERVER): Likewise. * config/rs6000/rs6000.cc (rs6000_option_override_internal): Update comment. Use OPTION_MASK_POWER8 and TARGET_POWER8. * config/rs6000/rs6000.h (TARGET_SYNC_HI_QI): Use TARGET_POWER8. * config/rs6000/rs6000.md (define_attr "isa"): Add p8. (define_attr "enabled"): Handle it. (define_insn "prefetch"): Use TARGET_POWER8. * config/rs6000/rs6000.opt (mpower8-internal): New. gcc/testsuite/ PR target/101865 * gcc.target/powerpc/predefine-p7-novsx.c: New test. * gcc.target/powerpc/predefine-p8-noaltivec-novsx.c: New test. * gcc.target/powerpc/predefine-p8-noaltivec.c: New test. * gcc.target/powerpc/predefine-p8-novsx.c: New test. * gcc.target/powerpc/predefine-p8-pragma-vsx.c: New test. * gcc.target/powerpc/predefine-p9-novsx.c: New test. (cherry picked from commit aa57af93ba22865be747f926e4e5f219e7f8758a) Diff: --- gcc/config/rs6000/rs6000-builtin.cc| 2 +- gcc/config/rs6000/rs6000-c.cc | 2 +- gcc/config/rs6000/rs6000-cpus.def | 2 + gcc/config/rs6000/rs6000.cc| 7 +- gcc/config/rs6000/rs6000.h | 2 +- gcc/config/rs6000/rs6000.md| 8 +- gcc/config/rs6000/rs6000.opt | 4 + .../gcc.target/powerpc/predefine-p7-novsx.c| 22 + .../powerpc/predefine-p8-noaltivec-novsx.c | 26 ++ .../gcc.target/powerpc/predefine-p8-noaltivec.c| 26 ++ .../gcc.target/powerpc/predefine-p8-novsx.c| 26 ++ .../gcc.target/powerpc/predefine-p8-pragma-vsx.c | 101 + .../gcc.target/powerpc/predefine-p9-novsx.c| 26 ++ 13 files changed, 245 insertions(+), 9 deletions(-) diff --git a/gcc/config/rs6000/rs6000-builtin.cc b/gcc/config/rs6000/rs6000-builtin.cc index 2b4412e0403..5b17132a101 100644 --- a/gcc/config/rs6000/rs6000-builtin.cc +++ b/gcc/config/rs6000/rs6000-builtin.cc @@ -165,7 +165,7 @@ rs6000_builtin_is_supported (enum rs6000_gen_builtins fncode) case ENB_P7_64: return TARGET_POPCNTD && TARGET_POWERPC64; case ENB_P8: - return TARGET_DIRECT_MOVE; + return TARGET_POWER8; case ENB_P8V: return TARGET_P8_VECTOR; case ENB_P9: diff --git a/gcc/config/rs6000/rs6000-c.cc b/gcc/config/rs6000/rs6000-c.cc index 2bedc0fc938..a931efd2409 100644 --- a/gcc/config/rs6000/rs6000-c.cc +++ b/gcc/config/rs6000/rs6000-c.cc @@ -429,7 +429,7 @@ rs6000_target_modify_macros (bool define_p, HOST_WIDE_INT flags) rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR6"); if ((flags & OPTION_MASK_POPCNTD) != 0) rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR7"); - if ((flags & OPTION_MASK_P8_VECTOR) != 0) + if ((flags & OPTION_MASK_POWER8) != 0) rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR8"); if ((flags & OPTION_MASK_MODULO) != 0) rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR9"); diff --git a/gcc/config/rs6000/rs6000-cpus.def b/gcc/config/rs6000/rs6000-cpus.def index 4f8d07b9a0d..641ad09a3ba 100644 --- a/gcc/config/rs6000/rs6000-cpus.def +++ b/gcc/config/rs6000/rs6000-cpus.def @@ -47,6 +47,7 @@ fusion here, instead set it in rs6000.cc if we are tuning for a power8 system. */ #define ISA_2_7_MASKS_SERVER (ISA_2_6_MASKS_SERVER \ +| OPTION_MASK_POWER8 \ | OPTION_MASK_P8_VECTOR
[gcc r15-99] middle-end/114579 - speed up add_scope_conflicts
https://gcc.gnu.org/g:bbe83599320288025a417c54d9afcb3885cb2766 commit r15-99-gbbe83599320288025a417c54d9afcb3885cb2766 Author: Richard Biener Date: Thu Apr 4 14:00:10 2024 +0200 middle-end/114579 - speed up add_scope_conflicts The following speeds up stack variable conflict detection by recognizing that the all-to-all conflict recording is only necessary for CFG merges as it's the unioning of the live variable sets that doesn't come with explicit mentions we record conflicts for. If we employ this optimization we have to make sure to perform the all-to-all conflict recording for all CFG merges even those into empty blocks where we might previously have skipped this. I have reworded the comment before the all-to-all conflict recording since it seemed to be confusing and missing the point - but maybe I am also missing something here. Nevertheless for the testcase in the PR the compile-time spend in add_scope_conflicts at -O1 drops from previously 67s (39%) to 10s (9%). PR middle-end/114579 * cfgexpand.cc (add_scope_conflicts_1): Record all-to-all conflicts only when there's a CFG merge but for all CFG merges. Diff: --- gcc/cfgexpand.cc | 46 +- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc index cfc5291aa0c..afee064aa15 100644 --- a/gcc/cfgexpand.cc +++ b/gcc/cfgexpand.cc @@ -640,21 +640,26 @@ add_scope_conflicts_1 (basic_block bb, bitmap work, bool for_conflict) { if (for_conflict && visit == visit_op) { - /* If this is the first real instruction in this BB we need -to add conflicts for everything live at this point now. -Unlike classical liveness for named objects we can't -rely on seeing a def/use of the names we're interested in. -There might merely be indirect loads/stores. We'd not add any -conflicts for such partitions. */ + /* When we are inheriting live variables from our predecessors +through a CFG merge we might not see an actual mention of +the variables to record the approprate conflict as defs/uses +might be through indirect stores/loads. For this reason +we have to make sure each live variable conflicts with +each other. When there's just a single predecessor the +set of conflicts is already up-to-date. +We perform this delayed at the first real instruction to +allow clobbers starting this block to remove variables from +the set of live variables. */ bitmap_iterator bi; unsigned i; - EXECUTE_IF_SET_IN_BITMAP (work, 0, i, bi) - { - class stack_var *a = &stack_vars[i]; - if (!a->conflicts) - a->conflicts = BITMAP_ALLOC (&stack_var_bitmap_obstack); - bitmap_ior_into (a->conflicts, work); - } + if (EDGE_COUNT (bb->preds) > 1) + EXECUTE_IF_SET_IN_BITMAP (work, 0, i, bi) + { + class stack_var *a = &stack_vars[i]; + if (!a->conflicts) + a->conflicts = BITMAP_ALLOC (&stack_var_bitmap_obstack); + bitmap_ior_into (a->conflicts, work); + } visit = visit_conflict; } walk_stmt_load_store_addr_ops (stmt, work, visit, visit, visit); @@ -662,6 +667,21 @@ add_scope_conflicts_1 (basic_block bb, bitmap work, bool for_conflict) add_scope_conflicts_2 (USE_FROM_PTR (use_p), work, visit); } } + + /* When there was no real instruction but there's a CFG merge we need + to add the conflicts now. */ + if (for_conflict && visit == visit_op && EDGE_COUNT (bb->preds) > 1) +{ + bitmap_iterator bi; + unsigned i; + EXECUTE_IF_SET_IN_BITMAP (work, 0, i, bi) + { + class stack_var *a = &stack_vars[i]; + if (!a->conflicts) + a->conflicts = BITMAP_ALLOC (&stack_var_bitmap_obstack); + bitmap_ior_into (a->conflicts, work); + } +} } /* Generate stack partition conflicts between all partitions that are
[gcc r15-100] s390: testsuite: Fix zero_bits_compound-1.c
https://gcc.gnu.org/g:6c4a745c6910659a75d1881cf3c4128f24b5666f commit r15-100-g6c4a745c6910659a75d1881cf3c4128f24b5666f Author: Stefan Schulze Frielinghaus Date: Thu May 2 08:39:32 2024 +0200 s390: testsuite: Fix zero_bits_compound-1.c Starting with r12-2731-g96146e61cd7aee we do not generate code like _5 = (unsigned int) c_2(D); i_6 = _5 << 8; _7 = _5 << 20; i_8 = i_6 | _7; anymore but instead _5 = (unsigned int) c_2(D); _3 = _5 * 1048832; which leads finally to slightly different assembly code where we previously ended up for z10 or newer with lr %r1,%r2 sll %r1,8 rosbg %r1,%r2,32,43,20 llgfr %r2,%r1 br %r14 and now lr %r1,%r2 sll %r1,12 ar %r2,%r1 risbg %r2,%r2,35,128+55,8 br %r14 The zero-extend materializes via risbg for which the pattern contains an "and" which is why the test fails. Thus, instead of scanning for RTL expressions rather scan for assembler instructions for s390. gcc/testsuite/ChangeLog: * gcc.dg/zero_bits_compound-1.c: Fix for s390. Diff: --- gcc/testsuite/gcc.dg/zero_bits_compound-1.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gcc/testsuite/gcc.dg/zero_bits_compound-1.c b/gcc/testsuite/gcc.dg/zero_bits_compound-1.c index e71594911b2..f1e267e0fb0 100644 --- a/gcc/testsuite/gcc.dg/zero_bits_compound-1.c +++ b/gcc/testsuite/gcc.dg/zero_bits_compound-1.c @@ -39,4 +39,5 @@ unsigned long bar (unsigned char c) } /* Check that no pattern containing an AND expression was used. */ -/* { dg-final { scan-assembler-not "\\(and:" } } */ +/* { dg-final { scan-assembler-not "\\(and:" { target { ! { s390*-*-* } } } } } */ +/* { dg-final { scan-assembler-not "\\tng?rk?\\t" { target { s390*-*-* } } } } */
[gcc r15-101] c++: Don't emit unused GMF partial specializations [PR114630]
https://gcc.gnu.org/g:02917ac4528e32d1b2d0da5f45ef5937c56942cd commit r15-101-g02917ac4528e32d1b2d0da5f45ef5937c56942cd Author: Nathaniel Shead Date: Thu Apr 11 19:15:35 2024 +1000 c++: Don't emit unused GMF partial specializations [PR114630] The change in r14-8408 to also emit partial specializations in the global module fragment caused the regression in the linked PR; this patch fixes this by restricting emitted GM partial specializations to those that are actually used. PR c++/114630 gcc/cp/ChangeLog: * module.cc (depset::hash::add_partial_entities): Mark GM specializations as unreached. (depset::hash::find_dependencies): Also reach entities in the DECL_TEMPLATE_SPECIALIZATIONS list. gcc/testsuite/ChangeLog: * g++.dg/modules/partial-3.C: New test. Signed-off-by: Nathaniel Shead Diff: --- gcc/cp/module.cc | 75 gcc/testsuite/g++.dg/modules/partial-3.C | 20 + 2 files changed, 66 insertions(+), 29 deletions(-) diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index f7725091f60..44dc81eed3e 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -13308,14 +13308,22 @@ depset::hash::add_partial_entities (vec *partial_classes) depset *dep = make_dependency (inner, depset::EK_DECL); if (dep->get_entity_kind () == depset::EK_REDIRECT) - /* We should have recorded the template as a partial - specialization. */ - gcc_checking_assert (dep->deps[0]->get_entity_kind () -== depset::EK_PARTIAL); + { + dep = dep->deps[0]; + /* We should have recorded the template as a partial +specialization. */ + gcc_checking_assert (dep->get_entity_kind () + == depset::EK_PARTIAL); + } else /* It was an explicit specialization, not a partial one. */ gcc_checking_assert (dep->get_entity_kind () == depset::EK_SPECIALIZATION); + + /* Only emit GM entities if reached. */ + if (!DECL_LANG_SPECIFIC (inner) + || !DECL_MODULE_PURVIEW_P (inner)) + dep->set_flag_bit (); } } @@ -13636,31 +13644,40 @@ depset::hash::find_dependencies (module_state *module) if (!walker.is_key_order () && TREE_CODE (decl) == TEMPLATE_DECL && !DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (decl)) - /* Mark all the explicit & partial specializations as - reachable. */ - for (tree cons = DECL_TEMPLATE_INSTANTIATIONS (decl); -cons; cons = TREE_CHAIN (cons)) - { - tree spec = TREE_VALUE (cons); - if (TYPE_P (spec)) - spec = TYPE_NAME (spec); - int use_tpl; - node_template_info (spec, use_tpl); - if (use_tpl & 2) - { - depset *spec_dep = find_dependency (spec); - if (spec_dep->get_entity_kind () == EK_REDIRECT) - spec_dep = spec_dep->deps[0]; - if (spec_dep->is_unreached ()) - { - reached_unreached = true; - spec_dep->clear_flag_bit (); - dump (dumper::DEPEND) - && dump ("Reaching unreached specialization" - " %C:%N", TREE_CODE (spec), spec); - } - } - } + { + /* Mark all the explicit & partial specializations as +reachable. We search both specialization lists as some +constrained partial specializations for class types are +only found in DECL_TEMPLATE_SPECIALIZATIONS. */ + auto mark_reached = [this](tree spec) + { + if (TYPE_P (spec)) + spec = TYPE_NAME (spec); + int use_tpl; + node_template_info (spec, use_tpl); + if (use_tpl & 2) + { + depset *spec_dep = find_dependency (spec); + if (spec_dep->get_entity_kind () == EK_REDIRECT) + spec_dep = spec_dep->deps[0]; + if (spec_dep->is_unreached ()) + { + reached_unreached = true; + spec_dep->clear_flag_bit (); + dump (dumper::DEPEND) + && dump ("Reaching unreached specialization" +" %C:%N", TREE_CODE (spec), spe
[gcc r15-102] s390: testsuite: Fix risbg-ll-2.c
https://gcc.gnu.org/g:66f49ccd409c7a3f6eb89dd78e275ab57c983c79 commit r15-102-g66f49ccd409c7a3f6eb89dd78e275ab57c983c79 Author: Stefan Schulze Frielinghaus Date: Thu May 2 08:43:50 2024 +0200 s390: testsuite: Fix risbg-ll-2.c Starting with r14-2047-gd0e891406b16dc we see through subregs which means for f10 in risbg-ll-2.c we do not end up with rosbg_si_noshift but rather rosbg_di_noshift which materializes in slightly different start index. This saves us an extend. gcc/testsuite/ChangeLog: * gcc.target/s390/risbg-ll-2.c: Fix start offset for rosbg of f10. Diff: --- gcc/testsuite/gcc.target/s390/risbg-ll-2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/testsuite/gcc.target/s390/risbg-ll-2.c b/gcc/testsuite/gcc.target/s390/risbg-ll-2.c index 8bf1a0ff88b..ca80602a83f 100644 --- a/gcc/testsuite/gcc.target/s390/risbg-ll-2.c +++ b/gcc/testsuite/gcc.target/s390/risbg-ll-2.c @@ -113,7 +113,7 @@ i32 f9 (i64 v_x, i32 v_y) // ands with incompatible masks. i32 f10 (i64 v_x, i32 v_y) { - /* { dg-final { scan-assembler "f10:\n\tsrlg\t%r2,%r2,48\n\trosbg\t%r2,%r3,32,39,0" { target { lp64 } } } } */ + /* { dg-final { scan-assembler "f10:\n\tsrlg\t%r2,%r2,48\n\trosbg\t%r2,%r3,0,39,0" { target { lp64 } } } } */ /* { dg-final { scan-assembler "f10:\n\tnilf\t%r4,4278190080\n\trosbg\t%r4,%r2,48,63,48" { target { ! lp64 } } } } */ i64 v_shr6 = ((ui64)v_x) >> 48; i32 v_conv = (ui32)v_shr6;