diff options
| author | Guillaume Chatelet <gchatelet@google.com> | 2019-10-14 09:04:15 +0000 |
|---|---|---|
| committer | Guillaume Chatelet <gchatelet@google.com> | 2019-10-14 09:04:15 +0000 |
| commit | 415df89e22abe3defa06cbc901a173e5a6791f8d (patch) | |
| tree | 54343abb421641828de2c16a49a7452563be0606 /llvm | |
| parent | 52bfa73af841bbbcee0ea59577c9d7b4bd9831d5 (diff) | |
| download | bcm5719-llvm-415df89e22abe3defa06cbc901a173e5a6791f8d.tar.gz bcm5719-llvm-415df89e22abe3defa06cbc901a173e5a6791f8d.zip | |
[Alignment][NFC] Support compile time constants
Summary:
This is patch is part of a series to introduce an Alignment type.
See this thread for context: http://lists.llvm.org/pipermail/llvm-dev/2019-July/133851.html
See this patch for the introduction of the type: https://reviews.llvm.org/D64790
Reviewers: courbet
Subscribers: llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D68936
llvm-svn: 374758
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/include/llvm/Support/Alignment.h | 29 | ||||
| -rw-r--r-- | llvm/include/llvm/Support/MathExtras.h | 10 | ||||
| -rw-r--r-- | llvm/unittests/Support/AlignmentTest.cpp | 22 | ||||
| -rw-r--r-- | llvm/unittests/Support/MathExtrasTest.cpp | 19 |
4 files changed, 78 insertions, 2 deletions
diff --git a/llvm/include/llvm/Support/Alignment.h b/llvm/include/llvm/Support/Alignment.h index 3d8a4235b0e..5e8e686150d 100644 --- a/llvm/include/llvm/Support/Alignment.h +++ b/llvm/include/llvm/Support/Alignment.h @@ -53,14 +53,25 @@ private: friend unsigned encode(struct MaybeAlign A); friend struct MaybeAlign decodeMaybeAlign(unsigned Value); + /// A trivial type to allow construction of constexpr Align. + /// This is currently needed to workaround a bug in GCC 5.3 which prevents + /// definition of constexpr assign operators. + /// https://stackoverflow.com/questions/46756288/explicitly-defaulted-function-cannot-be-declared-as-constexpr-because-the-implic + /// FIXME: Remove this, make all assign operators constexpr and introduce user + /// defined literals when we don't have to support GCC 5.3 anymore. + /// https://llvm.org/docs/GettingStarted.html#getting-a-modern-host-c-toolchain + struct LogValue { + uint8_t Log; + }; + public: /// Default is byte-aligned. constexpr Align() = default; /// Do not perform checks in case of copy/move construct/assign, because the /// checks have been performed when building `Other`. - Align(const Align &Other) = default; + constexpr Align(const Align &Other) = default; + constexpr Align(Align &&Other) = default; Align &operator=(const Align &Other) = default; - Align(Align &&Other) = default; Align &operator=(Align &&Other) = default; explicit Align(uint64_t Value) { @@ -80,6 +91,20 @@ public: /// would be better than /// `if (A > Align(1))` constexpr static const Align None() { return Align(); } + + /// Allow constructions of constexpr Align. + template <size_t kValue> constexpr static LogValue Constant() { + return LogValue{CTLog2<kValue>()}; + } + + /// Allow constructions of constexpr Align from types. + /// Compile time equivalent to Align(alignof(T)). + template <typename T> constexpr static LogValue Of() { + return Constant<std::alignment_of<T>::value>(); + } + + /// Constexpr constructor from LogValue type. + constexpr Align(LogValue CA) : ShiftValue(CA.Log) {} }; /// Treats the value 0 as a 1, so Align is always at least 1. diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h index 605539ea11e..be6152a19b8 100644 --- a/llvm/include/llvm/Support/MathExtras.h +++ b/llvm/include/llvm/Support/MathExtras.h @@ -560,6 +560,16 @@ inline unsigned countPopulation(T Value) { return detail::PopulationCounter<T, sizeof(T)>::count(Value); } +/// Compile time Log2. +/// Valid only for positive powers of two. +template <size_t kValue> constexpr inline size_t CTLog2() { + static_assert(kValue > 0 && llvm::isPowerOf2_64(kValue), + "Value is not a valid power of 2"); + return 1 + CTLog2<kValue / 2>(); +} + +template <> constexpr inline size_t CTLog2<1>() { return 0; } + /// Return the log base 2 of the specified value. inline double Log2(double Value) { #if defined(__ANDROID_API__) && __ANDROID_API__ < 18 diff --git a/llvm/unittests/Support/AlignmentTest.cpp b/llvm/unittests/Support/AlignmentTest.cpp index 0b1435912b9..a6c053385cb 100644 --- a/llvm/unittests/Support/AlignmentTest.cpp +++ b/llvm/unittests/Support/AlignmentTest.cpp @@ -21,6 +21,28 @@ using namespace llvm; namespace { +TEST(AlignmentTest, AlignOfConstant) { + EXPECT_EQ(Align::Of<uint8_t>(), Align(alignof(uint8_t))); + EXPECT_EQ(Align::Of<uint16_t>(), Align(alignof(uint16_t))); + EXPECT_EQ(Align::Of<uint32_t>(), Align(alignof(uint32_t))); + EXPECT_EQ(Align::Of<uint64_t>(), Align(alignof(uint64_t))); +} + +TEST(AlignmentTest, AlignConstant) { + EXPECT_EQ(Align::Constant<1>(), Align(1)); + EXPECT_EQ(Align::Constant<2>(), Align(2)); + EXPECT_EQ(Align::Constant<4>(), Align(4)); + EXPECT_EQ(Align::Constant<8>(), Align(8)); + EXPECT_EQ(Align::Constant<16>(), Align(16)); + EXPECT_EQ(Align::Constant<32>(), Align(32)); + EXPECT_EQ(Align::Constant<64>(), Align(64)); +} + +TEST(AlignmentTest, AlignConstexprConstant) { + constexpr Align kConstantAlign = Align::Of<uint64_t>(); + EXPECT_EQ(Align(8), kConstantAlign); +} + std::vector<uint64_t> getValidAlignments() { std::vector<uint64_t> Out; for (size_t Shift = 0; Shift < 64; ++Shift) diff --git a/llvm/unittests/Support/MathExtrasTest.cpp b/llvm/unittests/Support/MathExtrasTest.cpp index 01c83c9e14d..e910d83b626 100644 --- a/llvm/unittests/Support/MathExtrasTest.cpp +++ b/llvm/unittests/Support/MathExtrasTest.cpp @@ -203,6 +203,25 @@ TEST(MathExtras, PowerOf2Floor) { EXPECT_EQ(4U, PowerOf2Floor(7U)); } +TEST(MathExtras, CTLog2) { + EXPECT_EQ(CTLog2<1ULL << 0>(), 0U); + EXPECT_EQ(CTLog2<1ULL << 1>(), 1U); + EXPECT_EQ(CTLog2<1ULL << 2>(), 2U); + EXPECT_EQ(CTLog2<1ULL << 3>(), 3U); + EXPECT_EQ(CTLog2<1ULL << 4>(), 4U); + EXPECT_EQ(CTLog2<1ULL << 5>(), 5U); + EXPECT_EQ(CTLog2<1ULL << 6>(), 6U); + EXPECT_EQ(CTLog2<1ULL << 7>(), 7U); + EXPECT_EQ(CTLog2<1ULL << 8>(), 8U); + EXPECT_EQ(CTLog2<1ULL << 9>(), 9U); + EXPECT_EQ(CTLog2<1ULL << 10>(), 10U); + EXPECT_EQ(CTLog2<1ULL << 11>(), 11U); + EXPECT_EQ(CTLog2<1ULL << 12>(), 12U); + EXPECT_EQ(CTLog2<1ULL << 13>(), 13U); + EXPECT_EQ(CTLog2<1ULL << 14>(), 14U); + EXPECT_EQ(CTLog2<1ULL << 15>(), 15U); +} + TEST(MathExtras, ByteSwap_32) { EXPECT_EQ(0x44332211u, ByteSwap_32(0x11223344)); EXPECT_EQ(0xDDCCBBAAu, ByteSwap_32(0xAABBCCDD)); |

