On 20/07/21 20:43 +0100, Jonathan Wakely wrote:
Clang provides __builtin_operator_new and __builtin_operator_delete,
which have the same semantics as ::operator new and ::operator delete
except that the compiler is allowed to elide calls to them. This changes
std::allocator to use those built-in functions so that memory allocated
by std::allocator can be optimized away when using Clang. This avoids an
abstraction penalty for using std::allocator to allocate storage rather
than a new-expression.

Signed-off-by: Jonathan Wakely <jwak...@redhat.com>

libstdc++-v3/ChangeLog:

        PR libstdc++/94295
        * include/ext/new_allocator.h (_GLIBCXX_OPERATOR_NEW)
        (_GLIBCXX_OPERATOR_DELETE, _GLIBCXX_SIZED_DEALLOC): Define.
        (allocator::allocate, allocator::deallocate): Use new macros.

Tested powerpc64le-linux.

The macros are ugly, but using #ifdef is unavoidable here. I think
this is less ugly than the laternative ways to do this.

Any objections to pushing this, or any better ideas for doing this?

Nobody said anything, so I've pushed it to trunk.


commit f8c86589f2eab42c0888390bea7bceb8dc31d92b
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Mon Jul 19 16:43:11 2021

   libstdc++: Use __builtin_operator_new when available [PR94295]

   Clang provides __builtin_operator_new and __builtin_operator_delete,
   which have the same semantics as ::operator new and ::operator delete
   except that the compiler is allowed to elide calls to them. This changes
   std::allocator to use those built-in functions so that memory allocated
   by std::allocator can be optimized away when using Clang. This avoids an
   abstraction penalty for using std::allocator to allocate storage rather
   than a new-expression.

   Signed-off-by: Jonathan Wakely <jwak...@redhat.com>

   libstdc++-v3/ChangeLog:

           PR libstdc++/94295
           * include/ext/new_allocator.h (_GLIBCXX_OPERATOR_NEW)
           (_GLIBCXX_OPERATOR_DELETE, _GLIBCXX_SIZED_DEALLOC): Define.
           (allocator::allocate, allocator::deallocate): Use new macros.

diff --git a/libstdc++-v3/include/ext/new_allocator.h 
b/libstdc++-v3/include/ext/new_allocator.h
index 3fb893be152..7c48c820c62 100644
--- a/libstdc++-v3/include/ext/new_allocator.h
+++ b/libstdc++-v3/include/ext/new_allocator.h
@@ -97,6 +97,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
      { return std::__addressof(__x); }
#endif

+#if __has_builtin(__builtin_operator_new) >= 201802L
+# define _GLIBCXX_OPERATOR_NEW __builtin_operator_new
+# define _GLIBCXX_OPERATOR_DELETE __builtin_operator_delete
+#else
+# define _GLIBCXX_OPERATOR_NEW ::operator new
+# define _GLIBCXX_OPERATOR_DELETE ::operator delete
+#endif
+
      // NB: __n is permitted to be 0.  The C++ standard says nothing
      // about what the return value is when __n == 0.
      _GLIBCXX_NODISCARD _Tp*
@@ -121,34 +129,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
          {
            std::align_val_t __al = std::align_val_t(alignof(_Tp));
-           return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp), __al));
+           return static_cast<_Tp*>(_GLIBCXX_OPERATOR_NEW(__n * sizeof(_Tp),
+                                                          __al));
          }
#endif
-       return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
+       return static_cast<_Tp*>(_GLIBCXX_OPERATOR_NEW(__n * sizeof(_Tp)));
      }

      // __p is not permitted to be a null pointer.
      void
-      deallocate(_Tp* __p, size_type __t __attribute__ ((__unused__)))
+      deallocate(_Tp* __p, size_type __n __attribute__ ((__unused__)))
      {
+#if __cpp_sized_deallocation
+# define _GLIBCXX_SIZED_DEALLOC(p, n) (p), (n) * sizeof(_Tp)
+#else
+# define _GLIBCXX_SIZED_DEALLOC(p, n) (p)
+#endif
+
#if __cpp_aligned_new
        if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
          {
-           ::operator delete(__p,
-# if __cpp_sized_deallocation
-                             __t * sizeof(_Tp),
-# endif
-                             std::align_val_t(alignof(_Tp)));
+           _GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(__p, __n),
+                                    std::align_val_t(alignof(_Tp)));
            return;
          }
#endif
-       ::operator delete(__p
-#if __cpp_sized_deallocation
-                         , __t * sizeof(_Tp)
-#endif
-                        );
+       _GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(__p, __n));
      }

+#undef _GLIBCXX_SIZED_DEALLOC
+#undef _GLIBCXX_OPERATOR_DELETE
+#undef _GLIBCXX_OPERATOR_NEW
+
#if __cplusplus <= 201703L
      size_type
      max_size() const _GLIBCXX_USE_NOEXCEPT

Reply via email to