diff --git a/llvm/include/llvm/Support/Alignment.h b/llvm/include/llvm/Support/Alignment.h --- a/llvm/include/llvm/Support/Alignment.h +++ b/llvm/include/llvm/Support/Alignment.h @@ -174,7 +174,24 @@ // Most compilers can generate this code but the pattern may be missed when // multiple functions gets inlined. - return (Size + value - 1) & ~(value - 1); + return (Size + value - 1) & ~(value - 1U); +} + +/// If non-zero \p Skew is specified, the return value will be a minimal integer +/// that is greater than or equal to \p Size and equal to \p A * N + \p Skew for +/// some integer N. If \p Skew is larger than \p A, its value is adjusted to '\p +/// Skew mod \p A'. +/// +/// Examples: +/// \code +/// alignTo(5, Align(8), 7) = 7 +/// alignTo(17, Align(8), 1) = 17 +/// alignTo(~0LL, Align(8), 3) = 3 +/// \endcode +inline uint64_t alignTo(uint64_t Size, Align A, uint64_t Skew) { + const uint64_t value = A.value(); + Skew %= value; + return ((Size + value - 1 - Skew) & ~(value - 1U)) + Skew; } /// Returns a multiple of A needed to store `Size` bytes. diff --git a/llvm/unittests/Support/AlignmentTest.cpp b/llvm/unittests/Support/AlignmentTest.cpp --- a/llvm/unittests/Support/AlignmentTest.cpp +++ b/llvm/unittests/Support/AlignmentTest.cpp @@ -125,6 +125,12 @@ } } +TEST(AlignmentTest, AlignToWithSkew) { + EXPECT_EQ(alignTo(5, Align(8), 7), 7U); + EXPECT_EQ(alignTo(17, Align(8), 1), 17U); + EXPECT_EQ(alignTo(~0LL, Align(8), 3), 3U); +} + TEST(AlignmentTest, Log2) { for (uint64_t Value : getValidAlignments()) { EXPECT_EQ(Log2(Align(Value)), Log2_64(Value));