[CodeGen] Stop storing alignment information into pointers in Address
authorAkira Hatanaka <ahatanaka@apple.com>
Fri, 24 Feb 2023 18:32:42 +0000 (10:32 -0800)
committerAkira Hatanaka <ahatanaka@apple.com>
Fri, 24 Feb 2023 18:33:10 +0000 (10:33 -0800)
This reverts b1613f05ae0ce4efc6b6475ea4459957ebcb0150. The change was
made in an attempt to reduce memory consumption by storing the alignment
information into pointers, but it turns out it doesn't make much
difference.

https://llvm-compile-time-tracker.com/compare.php?from=998ad085e865f2e5acc589d6bee0e3379042da2e&to=5de4a1989c474f37ac03f20ccb0aef50f6e3b854&stat=max-rss

This fixes a bug introduced in https://reviews.llvm.org/D142584. The
patch reduced the number of bits used for alignment from 6 bits to 5
bits, which made it impossible to encode the maximum allowed alignment
in llvm (1 << 32).

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

clang/lib/CodeGen/Address.h

index 9f7cd17..a45df7f 100644 (file)
@@ -25,80 +25,20 @@ namespace CodeGen {
 // Indicates whether a pointer is known not to be null.
 enum KnownNonNull_t { NotKnownNonNull, KnownNonNull };
 
-// We try to save some space by using 6 bits over two PointerIntPairs to store
-// the alignment. However, some arches don't support 3 bits in a PointerIntPair
-// so we fallback to storing the alignment separately.
-template <typename T, bool = alignof(llvm::Value *) >= 8> class AddressImpl {};
-
-template <typename T> class AddressImpl<T, false> {
+/// An aligned address.
+class Address {
   llvm::PointerIntPair<llvm::Value *, 1, bool> PointerAndKnownNonNull;
   llvm::Type *ElementType;
   CharUnits Alignment;
 
-public:
-  AddressImpl(llvm::Value *Pointer, llvm::Type *ElementType,
-              CharUnits Alignment, KnownNonNull_t IsKnownNonNull)
-      : PointerAndKnownNonNull(Pointer, IsKnownNonNull),
-        ElementType(ElementType), Alignment(Alignment) {}
-  llvm::Value *getPointer() const {
-    return PointerAndKnownNonNull.getPointer();
-  }
-  llvm::Type *getElementType() const { return ElementType; }
-  CharUnits getAlignment() const { return Alignment; }
-  KnownNonNull_t isKnownNonNull() const {
-    return (KnownNonNull_t)PointerAndKnownNonNull.getInt();
-  }
-  void setKnownNonNull() { PointerAndKnownNonNull.setInt(true); }
-};
-
-template <typename T> class AddressImpl<T, true> {
-  // Int portion stores the non-null bit and the upper 2 bits of the log of the
-  // alignment.
-  llvm::PointerIntPair<llvm::Value *, 3, unsigned> Pointer;
-  // Int portion stores lower 3 bits of the log of the alignment.
-  llvm::PointerIntPair<llvm::Type *, 3, unsigned> ElementType;
-
-public:
-  AddressImpl(llvm::Value *Pointer, llvm::Type *ElementType,
-              CharUnits Alignment, KnownNonNull_t IsKnownNonNull)
-      : Pointer(Pointer), ElementType(ElementType) {
-    if (Alignment.isZero()) {
-      this->Pointer.setInt(IsKnownNonNull << 2);
-      return;
-    }
-    // Currently the max supported alignment is exactly 1 << 32 and is
-    // guaranteed to be a power of 2, so we can store the log of the alignment
-    // into 5 bits.
-    assert(Alignment.isPowerOfTwo() && "Alignment cannot be zero");
-    auto AlignLog = llvm::Log2_64(Alignment.getQuantity());
-    assert(AlignLog < (1 << 5) && "cannot fit alignment into 5 bits");
-    this->Pointer.setInt(IsKnownNonNull << 2 | AlignLog >> 3);
-    this->ElementType.setInt(AlignLog & 7);
-  }
-  llvm::Value *getPointer() const { return Pointer.getPointer(); }
-  llvm::Type *getElementType() const { return ElementType.getPointer(); }
-  CharUnits getAlignment() const {
-    unsigned AlignLog = ((Pointer.getInt() & 0x3) << 3) | ElementType.getInt();
-    return CharUnits::fromQuantity(CharUnits::QuantityType(1) << AlignLog);
-  }
-  KnownNonNull_t isKnownNonNull() const {
-    return (KnownNonNull_t)(!!(Pointer.getInt() & 0x4));
-  }
-  void setKnownNonNull() { Pointer.setInt(Pointer.getInt() | 0x4); }
-};
-
-/// An aligned address.
-class Address {
-  AddressImpl<void> A;
-
 protected:
-  Address(std::nullptr_t)
-      : A(nullptr, nullptr, CharUnits::Zero(), NotKnownNonNull) {}
+  Address(std::nullptr_t) : ElementType(nullptr) {}
 
 public:
   Address(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment,
           KnownNonNull_t IsKnownNonNull = NotKnownNonNull)
-      : A(Pointer, ElementType, Alignment, IsKnownNonNull) {
+      : PointerAndKnownNonNull(Pointer, IsKnownNonNull),
+        ElementType(ElementType), Alignment(Alignment) {
     assert(Pointer != nullptr && "Pointer cannot be null");
     assert(ElementType != nullptr && "Element type cannot be null");
     assert(llvm::cast<llvm::PointerType>(Pointer->getType())
@@ -107,11 +47,13 @@ public:
   }
 
   static Address invalid() { return Address(nullptr); }
-  bool isValid() const { return A.getPointer() != nullptr; }
+  bool isValid() const {
+    return PointerAndKnownNonNull.getPointer() != nullptr;
+  }
 
   llvm::Value *getPointer() const {
     assert(isValid());
-    return A.getPointer();
+    return PointerAndKnownNonNull.getPointer();
   }
 
   /// Return the type of the pointer value.
@@ -122,7 +64,7 @@ public:
   /// Return the type of the values stored in this address.
   llvm::Type *getElementType() const {
     assert(isValid());
-    return A.getElementType();
+    return ElementType;
   }
 
   /// Return the address space that this address resides in.
@@ -138,7 +80,7 @@ public:
   /// Return the alignment of this pointer.
   CharUnits getAlignment() const {
     assert(isValid());
-    return A.getAlignment();
+    return Alignment;
   }
 
   /// Return address with different pointer, but same element type and
@@ -159,13 +101,13 @@ public:
   /// Whether the pointer is known not to be null.
   KnownNonNull_t isKnownNonNull() const {
     assert(isValid());
-    return A.isKnownNonNull();
+    return (KnownNonNull_t)PointerAndKnownNonNull.getInt();
   }
 
   /// Set the non-null bit.
   Address setKnownNonNull() {
     assert(isValid());
-    A.setKnownNonNull();
+    PointerAndKnownNonNull.setInt(true);
     return *this;
   }
 };