[llvm] b745c12 - [Align] Add isAligned taking an APInt

Guillaume Chatelet via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 27 02:27:58 PDT 2023


Author: Guillaume Chatelet
Date: 2023-06-27T09:27:47Z
New Revision: b745c123857e0153d75f8793df79497c41f39bf5

URL: https://github.com/llvm/llvm-project/commit/b745c123857e0153d75f8793df79497c41f39bf5
DIFF: https://github.com/llvm/llvm-project/commit/b745c123857e0153d75f8793df79497c41f39bf5.diff

LOG: [Align] Add isAligned taking an APInt

This showed up in https://reviews.llvm.org/D153308

Reviewed By: courbet, nikic

Differential Revision: https://reviews.llvm.org/D153356

Added: 
    

Modified: 
    llvm/include/llvm/ADT/APInt.h
    llvm/lib/Support/APInt.cpp
    llvm/unittests/ADT/APIntTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h
index a23e304cce444..6f2f25548cc84 100644
--- a/llvm/include/llvm/ADT/APInt.h
+++ b/llvm/include/llvm/ADT/APInt.h
@@ -28,6 +28,7 @@ class FoldingSetNodeID;
 class StringRef;
 class hash_code;
 class raw_ostream;
+struct Align;
 
 template <typename T> class SmallVectorImpl;
 template <typename T> class ArrayRef;
@@ -433,6 +434,10 @@ class [[nodiscard]] APInt {
     return (LO + TZ) == BitWidth;
   }
 
+  /// Checks if this APInt -interpreted as an address- is aligned to the
+  /// provided value.
+  bool isAligned(Align A) const;
+
   /// Check if the APInt's value is returned by getSignMask.
   ///
   /// \returns true if this is the value returned by getSignMask.
@@ -1570,8 +1575,8 @@ class [[nodiscard]] APInt {
 
   /// Count the number of trailing zero bits.
   ///
-  /// This function is an APInt version of std::countr_zero. It counts the number
-  /// of zeros from the least significant bit to the first set bit.
+  /// This function is an APInt version of std::countr_zero. It counts the
+  /// number of zeros from the least significant bit to the first set bit.
   ///
   /// \returns BitWidth if the value is zero, otherwise returns the number of
   /// zeros from the least significant bit to the first one bit.

diff  --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp
index bd8358c787259..05b1526da95ff 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -19,6 +19,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/bit.h"
 #include "llvm/Config/llvm-config.h"
+#include "llvm/Support/Alignment.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/MathExtras.h"
@@ -164,6 +165,14 @@ void APInt::Profile(FoldingSetNodeID& ID) const {
     ID.AddInteger(U.pVal[i]);
 }
 
+bool APInt::isAligned(Align A) const {
+  if (isZero())
+    return true;
+  const unsigned TrailingZeroes = countr_zero();
+  const unsigned MinimumTrailingZeroes = Log2(A);
+  return TrailingZeroes >= MinimumTrailingZeroes;
+}
+
 /// Prefix increment operator. Increments the APInt by one.
 APInt& APInt::operator++() {
   if (isSingleWord())

diff  --git a/llvm/unittests/ADT/APIntTest.cpp b/llvm/unittests/ADT/APIntTest.cpp
index a9993acec307d..3b909f8f7d14e 100644
--- a/llvm/unittests/ADT/APIntTest.cpp
+++ b/llvm/unittests/ADT/APIntTest.cpp
@@ -11,6 +11,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/Twine.h"
+#include "llvm/Support/Alignment.h"
 #include "gtest/gtest.h"
 #include <array>
 #include <optional>
@@ -1852,6 +1853,25 @@ TEST(APIntTest, isNegatedPowerOf2) {
   }
 }
 
+TEST(APIntTest, isAligned) {
+  struct {
+    uint64_t alignment;
+    uint64_t offset;
+    bool isAligned;
+  } Tests[] = {
+      {1, 0, true},  {1, 1, true},  {1, 5, true},  {2, 0, true},
+      {2, 1, false}, {2, 2, true},  {2, 7, false}, {2, 16, true},
+      {4, 0, true},  {4, 1, false}, {4, 4, true},  {4, 6, false},
+  };
+  for (const auto &T : Tests)
+    EXPECT_EQ(APInt(32, T.offset).isAligned(Align(T.alignment)), T.isAligned);
+  // Tests for APInt that can't represent the alignment.
+  // Here APInt(4, I) can represent values from 0 to 15.
+  EXPECT_TRUE(APInt(4, 0).isAligned(Align(32))); // zero is always aligned.
+  for (int I = 1; I < 16; ++I)
+    EXPECT_FALSE(APInt(4, I).isAligned(Align(32)));
+}
+
 // Test that self-move works with EXPENSIVE_CHECKS. It calls std::shuffle which
 // does self-move on some platforms.
 #ifdef EXPENSIVE_CHECKS


        


More information about the llvm-commits mailing list