[llvm] 842e718 - Add support for zero-sized Scalars as a LowLevelType

Paulo Matos via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 22 04:48:14 PDT 2021


Author: Paulo Matos
Date: 2021-07-22T13:47:19+02:00
New Revision: 842e718b666f028e8fd3ea72d999fb5848767a02

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

LOG: Add support for zero-sized Scalars as a LowLevelType

Opaque values (of zero size) can be stored in memory with the
implemention of reference types in the WebAssembly backend. Since
MachineMemOperand uses LLTs we need to be able to support
zero-sized scalars types in LLTs.

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

Added: 
    

Modified: 
    llvm/include/llvm/Support/LowLevelTypeImpl.h
    llvm/lib/Support/LowLevelType.cpp
    llvm/unittests/CodeGen/LowLevelTypeTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Support/LowLevelTypeImpl.h b/llvm/include/llvm/Support/LowLevelTypeImpl.h
index 3d631dc6d5307..2071a08d87117 100644
--- a/llvm/include/llvm/Support/LowLevelTypeImpl.h
+++ b/llvm/include/llvm/Support/LowLevelTypeImpl.h
@@ -41,8 +41,7 @@ class LLT {
 public:
   /// Get a low-level scalar or aggregate "bag of bits".
   static LLT scalar(unsigned SizeInBits) {
-    assert(SizeInBits > 0 && "invalid scalar size");
-    return LLT{/*isPointer=*/false, /*isVector=*/false,
+    return LLT{/*isPointer=*/false, /*isVector=*/false, /*isScalar=*/true,
                ElementCount::getFixed(0), SizeInBits,
                /*AddressSpace=*/0};
   }
@@ -50,23 +49,23 @@ class LLT {
   /// Get a low-level pointer in the given address space.
   static LLT pointer(unsigned AddressSpace, unsigned SizeInBits) {
     assert(SizeInBits > 0 && "invalid pointer size");
-    return LLT{/*isPointer=*/true, /*isVector=*/false,
+    return LLT{/*isPointer=*/true, /*isVector=*/false, /*isScalar=*/false,
                ElementCount::getFixed(0), SizeInBits, AddressSpace};
   }
 
   /// Get a low-level vector of some number of elements and element width.
   static LLT vector(ElementCount EC, unsigned ScalarSizeInBits) {
     assert(!EC.isScalar() && "invalid number of vector elements");
-    assert(ScalarSizeInBits > 0 && "invalid vector element size");
-    return LLT{/*isPointer=*/false, /*isVector=*/true, EC, ScalarSizeInBits,
-               /*AddressSpace=*/0};
+    return LLT{/*isPointer=*/false, /*isVector=*/true, /*isScalar=*/false,
+               EC, ScalarSizeInBits, /*AddressSpace=*/0};
   }
 
   /// Get a low-level vector of some number of elements and element type.
   static LLT vector(ElementCount EC, LLT ScalarTy) {
     assert(!EC.isScalar() && "invalid number of vector elements");
     assert(!ScalarTy.isVector() && "invalid vector element type");
-    return LLT{ScalarTy.isPointer(), /*isVector=*/true, EC,
+    return LLT{ScalarTy.isPointer(), /*isVector=*/true, /*isScalar=*/false,
+               EC,
                ScalarTy.getSizeInBits().getFixedSize(),
                ScalarTy.isPointer() ? ScalarTy.getAddressSpace() : 0};
   }
@@ -106,17 +105,18 @@ class LLT {
     return scalarOrVector(EC, LLT::scalar(static_cast<unsigned>(ScalarSize)));
   }
 
-  explicit LLT(bool isPointer, bool isVector, ElementCount EC,
+  explicit LLT(bool isPointer, bool isVector, bool isScalar, ElementCount EC,
                uint64_t SizeInBits, unsigned AddressSpace) {
-    init(isPointer, isVector, EC, SizeInBits, AddressSpace);
+    init(isPointer, isVector, isScalar, EC, SizeInBits, AddressSpace);
   }
-  explicit LLT() : IsPointer(false), IsVector(false), RawData(0) {}
+  explicit LLT()
+      : IsScalar(false), IsPointer(false), IsVector(false), RawData(0) {}
 
   explicit LLT(MVT VT);
 
-  bool isValid() const { return RawData != 0; }
+  bool isValid() const { return IsScalar || RawData != 0; }
 
-  bool isScalar() const { return isValid() && !IsPointer && !IsVector; }
+  bool isScalar() const { return IsScalar; }
 
   bool isPointer() const { return isValid() && IsPointer && !IsVector; }
 
@@ -196,6 +196,8 @@ class LLT {
   /// not attempt to handle cases that aren't evenly divisible.
   LLT divide(int Factor) const {
     assert(Factor != 1);
+    assert((!isScalar() || getScalarSizeInBits() != 0) &&
+           "cannot divide scalar of size zero");
     if (isVector()) {
       assert(getElementCount().isKnownMultipleOf(Factor));
       return scalarOrVector(getElementCount().divideCoefficientBy(Factor),
@@ -209,18 +211,17 @@ class LLT {
   bool isByteSized() const { return getSizeInBits().isKnownMultipleOf(8); }
 
   unsigned getScalarSizeInBits() const {
-    assert(RawData != 0 && "Invalid Type");
-    if (!IsVector) {
-      if (!IsPointer)
-        return getFieldValue(ScalarSizeFieldInfo);
-      else
-        return getFieldValue(PointerSizeFieldInfo);
-    } else {
+    if (IsScalar)
+      return getFieldValue(ScalarSizeFieldInfo);
+    if (IsVector) {
       if (!IsPointer)
         return getFieldValue(VectorSizeFieldInfo);
       else
         return getFieldValue(PointerVectorSizeFieldInfo);
-    }
+    } else if (IsPointer)
+      return getFieldValue(PointerSizeFieldInfo);
+    else
+      llvm_unreachable("unexpected LLT");
   }
 
   unsigned getAddressSpace() const {
@@ -252,7 +253,7 @@ class LLT {
 
   bool operator==(const LLT &RHS) const {
     return IsPointer == RHS.IsPointer && IsVector == RHS.IsVector &&
-           RHS.RawData == RawData;
+           IsScalar == RHS.IsScalar && RHS.RawData == RawData;
   }
 
   bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
@@ -262,9 +263,10 @@ class LLT {
 
 private:
   /// LLT is packed into 64 bits as follows:
+  /// isScalar : 1
   /// isPointer : 1
   /// isVector  : 1
-  /// with 62 bits remaining for Kind-specific data, packed in bitfields
+  /// with 61 bits remaining for Kind-specific data, packed in bitfields
   /// as described below. As there isn't a simple portable way to pack bits
   /// into bitfields, here the 
diff erent fields in the packed structure is
   /// described in static const *Field variables. Each of these variables
@@ -286,7 +288,7 @@ class LLT {
   static const constexpr BitFieldInfo PointerAddressSpaceFieldInfo{
       24, PointerSizeFieldInfo[0] + PointerSizeFieldInfo[1]};
   static_assert((PointerAddressSpaceFieldInfo[0] +
-                 PointerAddressSpaceFieldInfo[1]) <= 62,
+                 PointerAddressSpaceFieldInfo[1]) <= 61,
                 "Insufficient bits to encode all data");
   /// * Vector-of-non-pointer (isPointer == 0 && isVector == 1):
   ///   NumElements: 16;
@@ -297,7 +299,7 @@ class LLT {
       32, VectorElementsFieldInfo[0] + VectorElementsFieldInfo[1]};
   static const constexpr BitFieldInfo VectorScalableFieldInfo{
       1, VectorSizeFieldInfo[0] + VectorSizeFieldInfo[1]};
-  static_assert((VectorSizeFieldInfo[0] + VectorSizeFieldInfo[1]) <= 62,
+  static_assert((VectorSizeFieldInfo[0] + VectorSizeFieldInfo[1]) <= 61,
                 "Insufficient bits to encode all data");
   /// * Vector-of-pointer (isPointer == 1 && isVector == 1):
   ///   NumElements: 16;
@@ -314,12 +316,13 @@ class LLT {
       1, PointerVectorAddressSpaceFieldInfo[0] +
              PointerVectorAddressSpaceFieldInfo[1]};
   static_assert((PointerVectorAddressSpaceFieldInfo[0] +
-                 PointerVectorAddressSpaceFieldInfo[1]) <= 62,
+                 PointerVectorAddressSpaceFieldInfo[1]) <= 61,
                 "Insufficient bits to encode all data");
 
+  uint64_t IsScalar : 1;
   uint64_t IsPointer : 1;
   uint64_t IsVector : 1;
-  uint64_t RawData : 62;
+  uint64_t RawData : 61;
 
   static uint64_t getMask(const BitFieldInfo FieldInfo) {
     const int FieldSizeInBits = FieldInfo[0];
@@ -336,19 +339,16 @@ class LLT {
     return getMask(FieldInfo) & (RawData >> FieldInfo[1]);
   }
 
-  void init(bool IsPointer, bool IsVector, ElementCount EC, uint64_t SizeInBits,
-            unsigned AddressSpace) {
+  void init(bool IsPointer, bool IsVector, bool IsScalar, ElementCount EC,
+            uint64_t SizeInBits, unsigned AddressSpace) {
     assert(SizeInBits <= std::numeric_limits<unsigned>::max() &&
            "Not enough bits in LLT to represent size");
     this->IsPointer = IsPointer;
     this->IsVector = IsVector;
-    if (!IsVector) {
-      if (!IsPointer)
-        RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo);
-      else
-        RawData = maskAndShift(SizeInBits, PointerSizeFieldInfo) |
-                  maskAndShift(AddressSpace, PointerAddressSpaceFieldInfo);
-    } else {
+    this->IsScalar = IsScalar;
+    if (IsScalar)
+      RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo);
+    else if (IsVector) {
       assert(EC.isVector() && "invalid number of vector elements");
       if (!IsPointer)
         RawData =
@@ -363,13 +363,17 @@ class LLT {
             maskAndShift(AddressSpace, PointerVectorAddressSpaceFieldInfo) |
             maskAndShift(EC.isScalable() ? 1 : 0,
                          PointerVectorScalableFieldInfo);
-    }
+    } else if (IsPointer)
+      RawData = maskAndShift(SizeInBits, PointerSizeFieldInfo) |
+                maskAndShift(AddressSpace, PointerAddressSpaceFieldInfo);
+    else
+      llvm_unreachable("unexpected LLT configuration");
   }
 
 public:
   uint64_t getUniqueRAWLLTData() const {
-    return ((uint64_t)RawData) << 2 | ((uint64_t)IsPointer) << 1 |
-           ((uint64_t)IsVector);
+    return ((uint64_t)RawData) << 3 | ((uint64_t)IsScalar) << 2 |
+           ((uint64_t)IsPointer) << 1 | ((uint64_t)IsVector);
   }
 };
 

diff  --git a/llvm/lib/Support/LowLevelType.cpp b/llvm/lib/Support/LowLevelType.cpp
index 42b91e9a30116..ecf557997ad1a 100644
--- a/llvm/lib/Support/LowLevelType.cpp
+++ b/llvm/lib/Support/LowLevelType.cpp
@@ -17,16 +17,17 @@ using namespace llvm;
 
 LLT::LLT(MVT VT) {
   if (VT.isVector()) {
-    init(/*IsPointer=*/false, VT.getVectorNumElements() > 1,
+    bool asVector = VT.getVectorNumElements() > 1;
+    init(/*IsPointer=*/false, asVector, /*IsScalar=*/!asVector,
          VT.getVectorElementCount(), VT.getVectorElementType().getSizeInBits(),
          /*AddressSpace=*/0);
   } else if (VT.isValid()) {
     // Aggregates are no 
diff erent from real scalars as far as GlobalISel is
     // concerned.
-    assert(VT.getSizeInBits().isNonZero() && "invalid zero-sized type");
-    init(/*IsPointer=*/false, /*IsVector=*/false, ElementCount::getFixed(0),
-         VT.getSizeInBits(), /*AddressSpace=*/0);
+    init(/*IsPointer=*/false, /*IsVector=*/false, /*IsScalar=*/true,
+         ElementCount::getFixed(0), VT.getSizeInBits(), /*AddressSpace=*/0);
   } else {
+    IsScalar = false;
     IsPointer = false;
     IsVector = false;
     RawData = 0;

diff  --git a/llvm/unittests/CodeGen/LowLevelTypeTest.cpp b/llvm/unittests/CodeGen/LowLevelTypeTest.cpp
index 9ff75b8f183bb..bf629c5d5e35f 100644
--- a/llvm/unittests/CodeGen/LowLevelTypeTest.cpp
+++ b/llvm/unittests/CodeGen/LowLevelTypeTest.cpp
@@ -22,7 +22,7 @@ TEST(LowLevelTypeTest, Scalar) {
   LLVMContext C;
   DataLayout DL("");
 
-  for (unsigned S : {1U, 17U, 32U, 64U, 0xfffffU}) {
+  for (unsigned S : {0U, 1U, 17U, 32U, 64U, 0xfffffU}) {
     const LLT Ty = LLT::scalar(S);
 
     // Test kind.
@@ -41,8 +41,10 @@ TEST(LowLevelTypeTest, Scalar) {
     EXPECT_FALSE(Ty != Ty);
 
     // Test Type->LLT conversion.
-    Type *IRTy = IntegerType::get(C, S);
-    EXPECT_EQ(Ty, getLLTForType(*IRTy, DL));
+    if (S != 0) {
+      Type *IRTy = IntegerType::get(C, S);
+      EXPECT_EQ(Ty, getLLTForType(*IRTy, DL));
+    }
   }
 }
 
@@ -50,7 +52,7 @@ TEST(LowLevelTypeTest, Vector) {
   LLVMContext C;
   DataLayout DL("");
 
-  for (unsigned S : {1U, 17U, 32U, 64U, 0xfffU}) {
+  for (unsigned S : {0U, 1U, 17U, 32U, 64U, 0xfffU}) {
     for (auto EC :
          {ElementCount::getFixed(2), ElementCount::getFixed(3),
           ElementCount::getFixed(4), ElementCount::getFixed(32),
@@ -94,9 +96,11 @@ TEST(LowLevelTypeTest, Vector) {
       EXPECT_NE(VTy, STy);
 
       // Test Type->LLT conversion.
-      Type *IRSTy = IntegerType::get(C, S);
-      Type *IRTy = VectorType::get(IRSTy, EC);
-      EXPECT_EQ(VTy, getLLTForType(*IRTy, DL));
+      if (S != 0) {
+        Type *IRSTy = IntegerType::get(C, S);
+        Type *IRTy = VectorType::get(IRSTy, EC);
+        EXPECT_EQ(VTy, getLLTForType(*IRTy, DL));
+      }
     }
   }
 }


        


More information about the llvm-commits mailing list