llvm.org GIT mirror llvm / cb39a85
Replace llvm::isPodLike<...> by llvm::is_trivially_copyable<...> As noted in https://bugs.llvm.org/show_bug.cgi?id=36651, the specialization for isPodLike<std::pair<...>> did not match the expectation of std::is_trivially_copyable which makes the memcpy optimization invalid. This patch renames the llvm::isPodLike trait into llvm::is_trivially_copyable. Unfortunately std::is_trivially_copyable is not portable across compiler / STL versions. So a portable version is provided too. Note that the following specialization were invalid: std::pair<T0, T1> llvm::Optional<T> Tests have been added to assert that former specialization are respected by the standard usage of llvm::is_trivially_copyable, and that when a decent version of std::is_trivially_copyable is available, llvm::is_trivially_copyable is compared to std::is_trivially_copyable. As of this patch, llvm::Optional is no longer considered trivially copyable, even if T is. This is to be fixed in a later patch, as it has impact on a long-running bug (see r347004) Note that GCC warns about this UB, but this got silented by https://reviews.llvm.org/D50296. Differential Revision: https://reviews.llvm.org/D54472 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351701 91177308-0d34-0410-b5e6-96231b3b80d8 Serge Guelton 1 year, 5 months ago
34 changed file(s) with 116 addition(s) and 129 deletion(s). Raw diff Collapse all Expand all
14551455 #. std::vector is exception-safe, and some implementations have pessimizations
14561456 that copy elements when SmallVector would move them.
14571457
1458 #. SmallVector understands ``isPodLike`` and uses realloc aggressively.
1458 #. SmallVector understands ``llvm::is_trivially_copyable`` and uses realloc aggressively.
14591459
14601460 #. Many LLVM APIs take a SmallVectorImpl as an out parameter (see the note
14611461 below).
524524
525525 /// @}
526526
527 // ArrayRefs can be treated like a POD type.
528 template struct isPodLike;
529 template struct isPodLike> {
530 static const bool value = true;
531 };
532
533527 template hash_code hash_value(ArrayRef S) {
534528 return hash_combine_range(S.begin(), S.end());
535529 }
144144 }
145145
146146 const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
147 if (isPodLike::value && isPodLike::value) {
147 if (is_trivially_copyable::value &&
148 is_trivially_copyable::value) {
148149 // Use a simpler loop when these are trivial types.
149150 for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P)
150151 P->getFirst() = EmptyKey;
420421 setNumEntries(other.getNumEntries());
421422 setNumTombstones(other.getNumTombstones());
422423
423 if (isPodLike::value && isPodLike::value)
424 if (is_trivially_copyable::value &&
425 is_trivially_copyable::value)
424426 memcpy(reinterpret_cast(getBuckets()), other.getBuckets(),
425427 getNumBuckets() * sizeof(BucketT));
426428 else
240240 }
241241 };
242242
243 template struct isPodLike;
244 template
245 struct isPodLike> { static const bool value = true; };
246
247243 } // end namespace llvm
248244
249245 #endif // LLVM_ADT_IMMUTABLELIST_H
2929
3030 namespace optional_detail {
3131 /// Storage for any type.
32 template PodLike::value> struct OptionalStorage {
32 template _trivially_copyable::value> struct OptionalStorage {
3333 AlignedCharArrayUnion storage;
3434 bool hasVal = false;
3535
184184 #endif
185185 };
186186
187 template struct isPodLike> {
188 // An Optional is pod-like if T is.
189 static const bool value = isPodLike::value;
190 };
191
192187 template
193188 bool operator==(const Optional &X, const Optional &Y) {
194189 if (X && Y)
174174 }
175175 };
176176
177 template struct isPodLike;
178 template
179 struct isPodLike> {
180 static const bool value = true;
181 };
182
183177 // Provide specialization of DenseMapInfo for PointerIntPair.
184178 template
185179 struct DenseMapInfo> {
178178 }
179179 };
180180
181 /// SmallVectorTemplateBase<isPodLike = false> - This is where we put method
181 /// SmallVectorTemplateBase<TriviallyCopyable = false> - This is where we put method
182182 /// implementations that are designed to work with non-POD-like T's.
183 template PodLike::value>
183 template _trivially_copyable::value>
184184 class SmallVectorTemplateBase : public SmallVectorTemplateCommon {
185185 protected:
186186 SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {}
234234 };
235235
236236 // Define this out-of-line to dissuade the C++ compiler from inlining it.
237 template
238 void SmallVectorTemplateBase::grow(size_t MinSize) {
237 template
238 void SmallVectorTemplateBase::grow(size_t MinSize) {
239239 if (MinSize > UINT32_MAX)
240240 report_bad_alloc_error("SmallVector capacity overflow during allocation");
241241
258258 this->Capacity = NewCapacity;
259259 }
260260
261
262 /// SmallVectorTemplateBase - This is where we put method
263 /// implementations that are designed to work with POD-like T's.
261 /// SmallVectorTemplateBase - This is where we put
262 /// method implementations that are designed to work with POD-like T's.
264263 template
265264 class SmallVectorTemplateBase : public SmallVectorTemplateCommon {
266265 protected:
329328 protected:
330329 // Default ctor - Initialize to empty.
331330 explicit SmallVectorImpl(unsigned N)
332 : SmallVectorTemplateBase, isPodLike::value>(N) {}
331 : SmallVectorTemplateBase>(N) {}
333332
334333 public:
335334 SmallVectorImpl(const SmallVectorImpl &) = delete;
926926 LLVM_NODISCARD
927927 hash_code hash_value(StringRef S);
928928
929 // StringRefs can be treated like a POD type.
930 template struct isPodLike;
931 template <> struct isPodLike { static const bool value = true; };
932
933929 } // end namespace llvm
934930
935931 #endif // LLVM_ADT_STRINGREF_H
3939 , typename = typename std::enable_if<__is_trivially_copyable(To)>::type
4040 , typename = typename std::enable_if<__is_trivially_copyable(From)>::type
4141 #else
42 // This case is GCC 4.x. clang with libc++ or libstdc++ never get here. Unlike
43 // llvm/Support/type_traits.h's isPodLike we don't want to provide a
44 // good-enough answer here: developers in that configuration will hit
45 // compilation failures on the bots instead of locally. That's acceptable
46 // because it's very few developers, and only until we move past C++11.
42 // This case is GCC 4.x. clang with libc++ or libstdc++ never get here. Unlike
43 // llvm/Support/type_traits.h's is_trivially_copyable we don't want to
44 // provide a good-enough answer here: developers in that configuration will hit
45 // compilation failures on the bots instead of locally. That's acceptable
46 // because it's very few developers, and only until we move past C++11.
4747 #endif
4848 >
4949 inline To bit_cast(const From &from) noexcept {
158158
159159 } // end namespace bfi_detail
160160
161 template <> struct isPodLike {
162 static const bool value = true;
163 };
164
165161 /// Base class for BlockFrequencyInfoImpl
166162 ///
167163 /// BlockFrequencyInfoImplBase has supporting data structures and some
185181 struct BlockNode {
186182 using IndexType = uint32_t;
187183
188 IndexType Index = std::numeric_limits::max();
189
190 BlockNode() = default;
184 IndexType Index;
185
186 BlockNode() : Index(std::numeric_limits::max()) {}
191187 BlockNode(IndexType Index) : Index(Index) {}
192188
193189 bool operator==(const BlockNode &X) const { return Index == X.Index; }
158158
159159 };
160160
161 template <> struct isPodLike { static const bool value=true; };
162
163161 /// BitCodeAbbrev - This class represents an abbreviation record. An
164162 /// abbreviation allows a complex record that has redundancy to be stored in a
165163 /// specialized format instead of the fully-general, fully-vbr, format.
798798 const uint16_t Version; /// The Dwarf version number for this unit.
799799 const uint8_t AddrSize; /// The size in bytes of an address for this unit.
800800 protected:
801 ~DIEUnit() = default;
801 virtual ~DIEUnit() = default;
802802
803803 public:
804804 DIEUnit(uint16_t Version, uint8_t AddrSize, dwarf::Tag UnitTag);
130130 }
131131 };
132132
133 template <> struct isPodLike {
134 static const bool value = true;
135 };
136
137133 /// List of PressureChanges in order of increasing, unique PSetID.
138134 ///
139135 /// Use a small fixed number, because we can fit more PressureChanges in an
236236
237237 void dump(const TargetRegisterInfo *TRI = nullptr) const;
238238 };
239
240 template <>
241 struct isPodLike { static const bool value = true; };
242239
243240 /// Scheduling unit. This is a node in the scheduling DAG.
244241 class SUnit {
230230 return LHS == RHS;
231231 }
232232 };
233 template <> struct isPodLike { static const bool value = true; };
234233
235234 /// Allow casting operators to work directly on
236235 /// SDValues as if they were SDNode*'s.
299299 return SlotIndex(&*--listEntry()->getIterator(), getSlot());
300300 }
301301 };
302
303 template <> struct isPodLike { static const bool value = true; };
304302
305303 inline raw_ostream& operator<<(raw_ostream &os, SlotIndex li) {
306304 li.print(os);
7373 }
7474 };
7575
76 template <> struct isPodLike {
77 static const bool value = true;
78 };
7976
8077 /// Target-Independent Code Generator Pass Configuration Options.
8178 ///
236236 }
237237 };
238238
239 template struct isPodLike> {
240 static const bool value = isPodLike::value;
241 };
242
243239 using succ_iterator = SuccIterator;
244240 using succ_const_iterator = SuccIterator;
245241 using succ_range = iterator_range;
307307 }
308308 };
309309
310 template
311 struct isPodLike> {
312 #ifdef NDEBUG
313 static const bool value = true;
314 #else
315 static const bool value = false;
316 #endif
317 };
318
319310 /// Value handle that tracks a Value across RAUW.
320311 ///
321312 /// TrackingVH is designed for situations where a client needs to hold a handle
547538 }
548539 };
549540
550 template struct isPodLike> {
551 #ifdef NDEBUG
552 static const bool value = true;
553 #else
554 static const bool value = false;
555 #endif
556 };
557
558541 } // end namespace llvm
559542
560543 #endif // LLVM_IR_VALUEHANDLE_H
152152 bool evaluateAsConstantImm(int64_t &Imm) const;
153153 };
154154
155 template <> struct isPodLike { static const bool value = true; };
156
157155 /// Instances of this class represent a single low-level machine
158156 /// instruction.
159157 class MCInst {
885885 Digits >>= Shift;
886886 }
887887
888 template struct isPodLike;
889 template struct isPodLike> {
890 static const bool value = true;
891 };
892888
893889 } // end namespace llvm
894890
2323
2424 namespace llvm {
2525
26 /// isPodLike - This is a type trait that is used to determine whether a given
27 /// type can be copied around with memcpy instead of running ctors etc.
28 template
29 struct isPodLike {
30 // std::is_trivially_copyable is available in libc++ with clang, libstdc++
31 // that comes with GCC 5. MSVC 2015 and newer also have
32 // std::is_trivially_copyable.
33 #if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) || \
34 (defined(__GNUC__) && __GNUC__ >= 5) || defined(_MSC_VER)
35 // If the compiler supports the is_trivially_copyable trait use it, as it
36 // matches the definition of isPodLike closely.
37 static const bool value = std::is_trivially_copyable::value;
38 #elif __has_feature(is_trivially_copyable)
39 // Use the internal name if the compiler supports is_trivially_copyable but we
40 // don't know if the standard library does. This is the case for clang in
41 // conjunction with libstdc++ from GCC 4.x.
42 static const bool value = __is_trivially_copyable(T);
43 #else
44 // If we don't know anything else, we can (at least) assume that all non-class
45 // types are PODs.
46 static const bool value = !std::is_class::value;
47 #endif
48 };
49
50 // std::pair's are pod-like if their elements are.
51 template
52 struct isPodLike> {
53 static const bool value = isPodLike::value && isPodLike::value;
54 };
5526
5627 /// Metafunction that determines whether the given type is either an
5728 /// integral type or an enumeration type, including enum classes.
11889 move_construction_triviality_helper(move_construction_triviality_helper&&) = default;
11990 ~move_construction_triviality_helper() = default;
12091 };
92
93 template
94 union trivial_helper {
95 T t;
96 };
12197 } // end namespace detail
12298
12399 /// An implementation of `std::is_trivially_copy_constructible` since we have
142118 template
143119 struct is_trivially_move_constructible : std::true_type {};
144120
121 // An implementation of `std::is_trivially_copyable` since STL version
122 // is not equally supported by all compilers, especially GCC 4.9.
123 // Uniform implementation of this trait is important for ABI compatibility
124 // as it has an impact on SmallVector's ABI (among others).
125 template
126 class is_trivially_copyable {
127
128 // copy constructors
129 static constexpr bool has_trivial_copy_constructor =
130 std::is_copy_constructible>::value;
131 static constexpr bool has_deleted_copy_constructor =
132 !std::is_copy_constructible::value;
133
134 // move constructors
135 static constexpr bool has_trivial_move_constructor =
136 std::is_move_constructible>::value;
137 static constexpr bool has_deleted_move_constructor =
138 !std::is_move_constructible::value;
139
140 // copy assign
141 static constexpr bool has_trivial_copy_assign =
142 std::is_copy_assignable>::value;
143 static constexpr bool has_deleted_copy_assign =
144 !std::is_copy_assignable::value;
145
146 // move assign
147 static constexpr bool has_trivial_move_assign =
148 std::is_move_assignable>::value;
149 static constexpr bool has_deleted_move_assign =
150 !std::is_move_assignable::value;
151
152 // destructor
153 static constexpr bool has_trivial_destructor =
154 std::is_destructible>::value;
155
156 public:
157
158 static constexpr bool value =
159 has_trivial_destructor &&
160 (has_deleted_move_assign || has_trivial_move_assign) &&
161 (has_deleted_move_constructor || has_trivial_move_constructor) &&
162 (has_deleted_copy_assign || has_trivial_copy_assign) &&
163 (has_deleted_copy_constructor || has_trivial_copy_constructor);
164
165 #if (__has_feature(is_trivially_copyable) || (defined(__GNUC__) && __GNUC__ >= 5))
166 static_assert(value == std::is_trivially_copyable::value, "inconsistent behavior between llvm:: and std:: implementation of is_trivially_copyable");
167 #endif
168 };
169
170
145171 } // end namespace llvm
146172
147173 // If the compiler supports detecting whether a class is final, define
220220
221221 } // end anonymous namespace
222222
223 namespace llvm {
224
225 template struct isPodLike;
226 template <> struct isPodLike { static const bool value = true; };
227
228 } // end namespace llvm
229
230223 /// Representation of the alloca slices.
231224 ///
232225 /// This class represents the slices of an alloca which are formed by its
6666 unsigned NewSize = Storage.size() - 1;
6767 if (NewSize) {
6868 // Move the slot at the end to the beginning.
69 if (isPodLike::value)
69 if (is_trivially_copyable::value)
7070 Storage[0] = Storage[NewSize];
7171 else
7272 std::swap(Storage[0], Storage[NewSize]);
247247 EXPECT_TRUE(AR2.equals(AR2Ref));
248248 }
249249
250 static_assert(is_trivially_copyable>::value,
251 "trivially copyable");
252
250253 } // end anonymous namespace
266266 ASSERT_EQ(6, i);
267267 }
268268
269 static_assert(is_trivially_copyable>>::value,
270 "trivially copyable");
271
269272 } // namespace
6060 Pair2.setPointerAndInt(&s, E::Case3);
6161 EXPECT_EQ(&s, Pair2.getPointer());
6262 EXPECT_EQ(E::Case3, Pair2.getInt());
63
64 static_assert(is_trivially_copyable>::value,
65 "trivially copyable");
6366 }
6467
6568 TEST(PointerIntPairTest, DefaultInitialize) {
9598
9699 EXPECT_EQ(FixnumPointerTraits::NumLowBitsAvailable - 1,
97100 PointerLikeTypeTraits::NumLowBitsAvailable);
101
102 static_assert(
103 is_trivially_copyable<
104 PointerIntPair>::value,
105 "trivially copyable");
98106 }
99107
100108 } // end anonymous namespace
10601060 EXPECT_EQ(StringRef("Bar"), Strings[1]);
10611061 }
10621062
1063 static_assert(is_trivially_copyable::value, "trivially copyable");
1064
10631065 } // end anonymous namespace
66 //===----------------------------------------------------------------------===//
77
88 #include "llvm/Analysis/BlockFrequencyInfo.h"
9 #include "llvm/Analysis/BlockFrequencyInfoImpl.h"
910 #include "llvm/Analysis/BranchProbabilityInfo.h"
1011 #include "llvm/Analysis/LoopInfo.h"
1112 #include "llvm/AsmParser/Parser.h"
8990 EXPECT_EQ(BFI.getBlockFreq(BB3).getFrequency(), BB3Freq);
9091 }
9192
93 static_assert(is_trivially_copyable::value,
94 "trivially copyable");
95
9296 } // end anonymous namespace
9397 } // end namespace llvm
146146 }
147147 }
148148
149 static_assert(is_trivially_copyable::value,
150 "trivially copyable");
151
149152 } // end anonymous namespace
1818 MachineInstrTest.cpp
1919 MachineOperandTest.cpp
2020 ScalableVectorMVTsTest.cpp
21 TypeTraitsTest.cpp
2122 )
2223
2324 add_subdirectory(GlobalISel)
271271 StringRef(OS.str()).endswith("filename:1:5"));
272272 }
273273
274 static_assert(is_trivially_copyable::value, "trivially copyable");
275
274276 } // end namespace
77
88 #include "CFGBuilder.h"
99
10 #include "llvm/IR/CFG.h"
1011 #include "llvm/IR/IRBuilder.h"
1112 #include "llvm/IR/LLVMContext.h"
1213 #include "llvm/Support/Debug.h"
264265 EXPECT_TRUE(isa(B.getOrAddBlock("c")->getTerminator()));
265266 EXPECT_TRUE(isa(B.getOrAddBlock("d")->getTerminator()));
266267 }
268
269 static_assert(is_trivially_copyable::value,
270 "trivially copyable");
271 static_assert(is_trivially_copyable::value,
272 "trivially copyable");
273 static_assert(is_trivially_copyable::value, "trivially copyable");
274 static_assert(is_trivially_copyable::value,
275 "trivially copyable");
561561 EXPECT_EQ(1u, (n * n).toInt());
562562 }
563563
564 static_assert(is_trivially_copyable>::value,
565 "trivially copyable");
566
564567 } // end namespace