mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[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
This commit is contained in:
parent
ba34d0d84b
commit
1f108d3854
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
|
Loading…
x
Reference in New Issue
Block a user