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 @@ -21,6 +21,7 @@ #ifndef LLVM_SUPPORT_ALIGNMENT_H_ #define LLVM_SUPPORT_ALIGNMENT_H_ +#include "llvm/ADT/APInt.h" #include "llvm/Support/MathExtras.h" #include #include @@ -146,6 +147,15 @@ return SizeInBytes % Lhs.value() == 0; } +/// Checks that SizeInBytes is a multiple of the alignment. +inline bool isAligned(Align Lhs, const APInt &SizeInBytes) { + if (SizeInBytes.isZero()) + return true; + const unsigned OffsetTrailingZeroes = SizeInBytes.countr_zero(); + const unsigned MinimumTrailingZeroes = Log2(Lhs); + return OffsetTrailingZeroes >= MinimumTrailingZeroes; +} + /// Checks that Addr is a multiple of the alignment. inline bool isAddrAligned(Align Lhs, const void *Addr) { return isAligned(Lhs, reinterpret_cast(Addr)); 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 @@ -153,8 +153,14 @@ if (A) { EXPECT_EQ(isAligned(*A, T.offset), T.isAligned); EXPECT_EQ(isAddrAligned(*A, T.forgedAddr()), T.isAligned); + EXPECT_EQ(isAligned(*A, APInt(32, T.offset)), T.isAligned); } } + // Additional tests for APInt that can't represent the alignment. + // Here APInt(4, I) can represent values from 0 to 15. + EXPECT_TRUE(isAligned(Align(32), APInt(4, 0))); // zero is always aligned. + for (int I = 1; I < 16; ++I) + EXPECT_FALSE(isAligned(Align(32), APInt(4, I))); } TEST(AlignmentTest, offsetToAlignment) {