Skip to content

Commit 7e440d9

Browse files
committed
[probably not for upstream] CodeGen, libcxx: Introduce __has_non_relocatable_fields.
In order to properly benchmark PFP we need to be able to do an A/B comparison and make A and B as equal as possible. This includes not disabling libc++'s non-standard trivially relocatable optimizations wherever possible. In the upstream code we just made trivially_relocatable equivalent to trivially_copyable but in the benchmarking version of the code (also more aligned to what will be possible in C++26) restore trivially_relocatable logic but also check whether any of the fields are non-relocatable using a temporarily introduced builtin.
1 parent 0d8ee11 commit 7e440d9

File tree

4 files changed

+25
-18
lines changed

4 files changed

+25
-18
lines changed

clang/include/clang/Basic/TokenKinds.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,7 @@ TYPE_TRAIT_2(__is_pointer_interconvertible_base_of, IsPointerInterconvertibleBas
544544
#include "clang/Basic/TransformTypeTraits.def"
545545

546546
// Clang-only C++ Type Traits
547+
TYPE_TRAIT_1(__has_non_relocatable_fields, HasNonRelocatableFields, KEYCXX)
547548
TYPE_TRAIT_1(__is_trivially_equality_comparable, IsTriviallyEqualityComparable, KEYCXX)
548549
TYPE_TRAIT_1(__is_bounded_array, IsBoundedArray, KEYCXX)
549550
TYPE_TRAIT_1(__is_unbounded_array, IsUnboundedArray, KEYCXX)

clang/lib/Sema/SemaTypeTraits.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
547547
case UTT_IsTriviallyEqualityComparable:
548548
case UTT_IsCppTriviallyRelocatable:
549549
case UTT_IsReplaceable:
550+
case UTT_HasNonRelocatableFields:
550551
case UTT_CanPassInRegs:
551552
// Per the GCC type traits documentation, T shall be a complete type, cv void,
552553
// or an array of unknown bound. But GCC actually imposes the same constraints
@@ -1149,6 +1150,10 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
11491150
return C.hasUniqueObjectRepresentations(T);
11501151
case UTT_IsTriviallyRelocatable:
11511152
return IsTriviallyRelocatableType(Self, T);
1153+
case UTT_HasNonRelocatableFields:
1154+
return T->getAsCXXRecordDecl() &&
1155+
!C.arePFPFieldsTriviallyRelocatable(T->getAsCXXRecordDecl()) &&
1156+
C.hasPFPFields(T);
11521157
case UTT_IsBitwiseCloneable:
11531158
return T.isBitwiseCloneableType(C);
11541159
case UTT_IsCppTriviallyRelocatable:

libcxx/include/__type_traits/is_trivially_relocatable.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,14 @@ template <class _Tp, class = void>
3434
struct __libcpp_is_trivially_relocatable : is_trivially_copyable<_Tp> {};
3535
#endif
3636

37-
// __trivially_relocatable on libc++'s builtin types does not currently return the right answer with PFP.
38-
#if !__has_feature(pointer_field_protection)
3937
template <class _Tp>
4038
struct __libcpp_is_trivially_relocatable<_Tp,
41-
__enable_if_t<is_same<_Tp, typename _Tp::__trivially_relocatable>::value> >
42-
: true_type {};
39+
__enable_if_t<is_same<_Tp, typename _Tp::__trivially_relocatable>::value
40+
#if __has_builtin(__has_non_relocatable_fields)
41+
&& !__has_non_relocatable_fields(_Tp)
4342
#endif
43+
> > : true_type {
44+
};
4445

4546
_LIBCPP_END_NAMESPACE_STD
4647

libcxx/test/libcxx/type_traits/is_trivially_relocatable.compile.pass.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ static_assert(!std::__libcpp_is_trivially_relocatable<NonTrivialDestructor>::val
7676
// ----------------------
7777

7878
// __split_buffer
79-
static_assert(std::__libcpp_is_trivially_relocatable<std::__split_buffer<int> >::value == pfp_disabled, "");
80-
static_assert(std::__libcpp_is_trivially_relocatable<std::__split_buffer<NotTriviallyCopyable> >::value == pfp_disabled, "");
79+
static_assert(std::__libcpp_is_trivially_relocatable<std::__split_buffer<int> >::value, "");
80+
static_assert(std::__libcpp_is_trivially_relocatable<std::__split_buffer<NotTriviallyCopyable> >::value, "");
8181
static_assert(!std::__libcpp_is_trivially_relocatable<std::__split_buffer<int, test_allocator<int> > >::value, "");
8282

8383
// standard library types
@@ -105,17 +105,17 @@ struct NotTriviallyRelocatableCharTraits : constexpr_char_traits<T> {
105105
};
106106

107107
static_assert(std::__libcpp_is_trivially_relocatable<
108-
std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::value == pfp_disabled,
108+
std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::value,
109109
"");
110110
static_assert(std::__libcpp_is_trivially_relocatable<
111-
std::basic_string<char, NotTriviallyRelocatableCharTraits<char>, std::allocator<char> > >::value == pfp_disabled,
111+
std::basic_string<char, NotTriviallyRelocatableCharTraits<char>, std::allocator<char> > >::value,
112112
"");
113113
static_assert(std::__libcpp_is_trivially_relocatable<
114-
std::basic_string<MyChar, constexpr_char_traits<MyChar>, std::allocator<MyChar> > >::value == pfp_disabled,
114+
std::basic_string<MyChar, constexpr_char_traits<MyChar>, std::allocator<MyChar> > >::value,
115115
"");
116116
static_assert(
117117
std::__libcpp_is_trivially_relocatable<
118-
std::basic_string<MyChar, NotTriviallyRelocatableCharTraits<MyChar>, std::allocator<MyChar> > >::value == pfp_disabled,
118+
std::basic_string<MyChar, NotTriviallyRelocatableCharTraits<MyChar>, std::allocator<MyChar> > >::value,
119119
"");
120120
static_assert(!std::__libcpp_is_trivially_relocatable<
121121
std::basic_string<char, std::char_traits<char>, test_allocator<char> > >::value,
@@ -127,18 +127,18 @@ static_assert(
127127
#endif
128128

129129
// deque
130-
static_assert(std::__libcpp_is_trivially_relocatable<std::deque<int> >::value == pfp_disabled, "");
131-
static_assert(std::__libcpp_is_trivially_relocatable<std::deque<NotTriviallyCopyable> >::value == pfp_disabled, "");
130+
static_assert(std::__libcpp_is_trivially_relocatable<std::deque<int> >::value, "");
131+
static_assert(std::__libcpp_is_trivially_relocatable<std::deque<NotTriviallyCopyable> >::value, "");
132132
static_assert(!std::__libcpp_is_trivially_relocatable<std::deque<int, test_allocator<int> > >::value, "");
133133

134134
// exception_ptr
135135
#ifndef _LIBCPP_ABI_MICROSOFT // FIXME: Is this also the case on windows?
136-
static_assert(std::__libcpp_is_trivially_relocatable<std::exception_ptr>::value == pfp_disabled, "");
136+
static_assert(std::__libcpp_is_trivially_relocatable<std::exception_ptr>::value, "");
137137
#endif
138138

139139
// expected
140140
#if TEST_STD_VER >= 23
141-
static_assert(std::__libcpp_is_trivially_relocatable<std::expected<int, int> >::value == pfp_disabled);
141+
static_assert(std::__libcpp_is_trivially_relocatable<std::expected<int, int> >::value);
142142
static_assert(std::__libcpp_is_trivially_relocatable<std::expected<std::unique_ptr<int>, int>>::value == pfp_disabled);
143143
static_assert(std::__libcpp_is_trivially_relocatable<std::expected<int, std::unique_ptr<int>>>::value == pfp_disabled);
144144
static_assert(std::__libcpp_is_trivially_relocatable<std::expected<std::unique_ptr<int>, std::unique_ptr<int>>>::value == pfp_disabled);
@@ -151,7 +151,7 @@ static_assert(
151151

152152
// locale
153153
#ifndef TEST_HAS_NO_LOCALIZATION
154-
static_assert(std::__libcpp_is_trivially_relocatable<std::locale>::value == pfp_disabled, "");
154+
static_assert(std::__libcpp_is_trivially_relocatable<std::locale>::value, "");
155155
#endif
156156

157157
// optional
@@ -162,7 +162,7 @@ static_assert(std::__libcpp_is_trivially_relocatable<std::optional<std::unique_p
162162
#endif // TEST_STD_VER >= 17
163163

164164
// pair
165-
static_assert(std::__libcpp_is_trivially_relocatable<std::pair<int, int> >::value == pfp_disabled, "");
165+
static_assert(std::__libcpp_is_trivially_relocatable<std::pair<int, int> >::value, "");
166166
static_assert(!std::__libcpp_is_trivially_relocatable<std::pair<NotTriviallyCopyable, int> >::value, "");
167167
static_assert(!std::__libcpp_is_trivially_relocatable<std::pair<int, NotTriviallyCopyable> >::value, "");
168168
static_assert(!std::__libcpp_is_trivially_relocatable<std::pair<NotTriviallyCopyable, NotTriviallyCopyable> >::value,
@@ -177,11 +177,11 @@ static_assert(std::__libcpp_is_trivially_relocatable<std::shared_ptr<NotTriviall
177177
#if TEST_STD_VER >= 11
178178
static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<> >::value, "");
179179

180-
static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<int> >::value == pfp_disabled, "");
180+
static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<int> >::value, "");
181181
static_assert(!std::__libcpp_is_trivially_relocatable<std::tuple<NotTriviallyCopyable> >::value, "");
182182
static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<std::unique_ptr<int> > >::value == pfp_disabled, "");
183183

184-
static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<int, int> >::value == pfp_disabled, "");
184+
static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<int, int> >::value, "");
185185
static_assert(!std::__libcpp_is_trivially_relocatable<std::tuple<NotTriviallyCopyable, int> >::value, "");
186186
static_assert(!std::__libcpp_is_trivially_relocatable<std::tuple<int, NotTriviallyCopyable> >::value, "");
187187
static_assert(!std::__libcpp_is_trivially_relocatable<std::tuple<NotTriviallyCopyable, NotTriviallyCopyable> >::value,

0 commit comments

Comments
 (0)