[llvm] ca0f4e1 - Support: Make TypeSize constructors constexpr

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 19 06:48:15 PST 2022


Author: Matt Arsenault
Date: 2022-12-19T09:48:10-05:00
New Revision: ca0f4e193b05813717b5ff6d0c194936009e0874

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

LOG: Support: Make TypeSize constructors constexpr

This is to enable LLT to be constexpr

Added: 
    llvm/unittests/Support/TypeSizeTest.cpp

Modified: 
    llvm/include/llvm/Support/TypeSize.h
    llvm/unittests/Support/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Support/TypeSize.h b/llvm/include/llvm/Support/TypeSize.h
index 9cf2e873d718..ae871cf47873 100644
--- a/llvm/include/llvm/Support/TypeSize.h
+++ b/llvm/include/llvm/Support/TypeSize.h
@@ -54,7 +54,7 @@ class LinearPolyBase {
   std::array<ScalarTy, Dimensions> Coefficients;
 
 protected:
-  LinearPolyBase(ArrayRef<ScalarTy> Values) {
+  constexpr LinearPolyBase(ArrayRef<ScalarTy> Values) {
     std::copy(Values.begin(), Values.end(), Coefficients.begin());
   }
 
@@ -99,22 +99,22 @@ class LinearPolyBase {
     return Copy *= -1;
   }
 
-  bool operator==(const LinearPolyBase &RHS) const {
+  constexpr bool operator==(const LinearPolyBase &RHS) const {
     return std::equal(Coefficients.begin(), Coefficients.end(),
                       RHS.Coefficients.begin());
   }
 
-  bool operator!=(const LinearPolyBase &RHS) const {
+  constexpr bool operator!=(const LinearPolyBase &RHS) const {
     return !(*this == RHS);
   }
 
-  bool isZero() const {
+  constexpr bool isZero() const {
     return all_of(Coefficients, [](const ScalarTy &C) { return C == 0; });
   }
-  bool isNonZero() const { return !isZero(); }
-  explicit operator bool() const { return isNonZero(); }
+  constexpr bool isNonZero() const { return !isZero(); }
+  constexpr explicit operator bool() const { return isNonZero(); }
 
-  ScalarTy getValue(unsigned Dim) const { return Coefficients[Dim]; }
+  constexpr ScalarTy getValue(unsigned Dim) const { return Coefficients[Dim]; }
 };
 
 //===----------------------------------------------------------------------===//
@@ -173,7 +173,7 @@ class UnivariateLinearPolyBase {
   ScalarTy Value;         // The value at the univeriate dimension.
   unsigned UnivariateDim; // The univeriate dimension.
 
-  UnivariateLinearPolyBase(ScalarTy Val, unsigned UnivariateDim)
+  constexpr UnivariateLinearPolyBase(ScalarTy Val, unsigned UnivariateDim)
       : Value(Val), UnivariateDim(UnivariateDim) {
     assert(UnivariateDim < Dimensions && "Dimension out of range");
   }
@@ -190,7 +190,7 @@ class UnivariateLinearPolyBase {
     return LHS;
   }
 
-  friend LeafTy &operator*=(LeafTy &LHS, ScalarTy RHS) {
+  friend constexpr LeafTy &operator*=(LeafTy &LHS, ScalarTy RHS) {
     LHS.Value *= RHS;
     return LHS;
   }
@@ -205,7 +205,7 @@ class UnivariateLinearPolyBase {
     return Copy -= RHS;
   }
 
-  friend LeafTy operator*(const LeafTy &LHS, ScalarTy RHS) {
+  friend constexpr LeafTy operator*(const LeafTy &LHS, ScalarTy RHS) {
     LeafTy Copy = LHS;
     return Copy *= RHS;
   }
@@ -218,29 +218,29 @@ class UnivariateLinearPolyBase {
   }
 
 public:
-  bool operator==(const UnivariateLinearPolyBase &RHS) const {
+  constexpr bool operator==(const UnivariateLinearPolyBase &RHS) const {
     return Value == RHS.Value && UnivariateDim == RHS.UnivariateDim;
   }
 
-  bool operator!=(const UnivariateLinearPolyBase &RHS) const {
+  constexpr bool operator!=(const UnivariateLinearPolyBase &RHS) const {
     return !(*this == RHS);
   }
 
-  bool isZero() const { return !Value; }
-  bool isNonZero() const { return !isZero(); }
-  explicit operator bool() const { return isNonZero(); }
-  ScalarTy getValue(unsigned Dim) const {
+  constexpr bool isZero() const { return !Value; }
+  constexpr bool isNonZero() const { return !isZero(); }
+  explicit constexpr operator bool() const { return isNonZero(); }
+  constexpr ScalarTy getValue(unsigned Dim) const {
     return Dim == UnivariateDim ? Value : 0;
   }
 
   /// Add \p RHS to the value at the univariate dimension.
-  LeafTy getWithIncrement(ScalarTy RHS) const {
+  constexpr LeafTy getWithIncrement(ScalarTy RHS) const {
     return static_cast<LeafTy>(
         UnivariateLinearPolyBase(Value + RHS, UnivariateDim));
   }
 
   /// Subtract \p RHS from the value at the univariate dimension.
-  LeafTy getWithDecrement(ScalarTy RHS) const {
+  constexpr LeafTy getWithDecrement(ScalarTy RHS) const {
     return static_cast<LeafTy>(
         UnivariateLinearPolyBase(Value - RHS, UnivariateDim));
   }
@@ -272,44 +272,45 @@ class LinearPolySize : public UnivariateLinearPolyBase<LeafTy> {
   enum Dims : unsigned { FixedDim = 0, ScalableDim = 1 };
 
 protected:
-  LinearPolySize(ScalarTy MinVal, Dims D)
+  constexpr LinearPolySize(ScalarTy MinVal, Dims D)
       : UnivariateLinearPolyBase<LeafTy>(MinVal, D) {}
 
-  LinearPolySize(const UnivariateLinearPolyBase<LeafTy> &V)
+  constexpr LinearPolySize(const UnivariateLinearPolyBase<LeafTy> &V)
       : UnivariateLinearPolyBase<LeafTy>(V) {}
 
 public:
-
-  static LeafTy getFixed(ScalarTy MinVal) {
+  static constexpr LeafTy getFixed(ScalarTy MinVal) {
     return static_cast<LeafTy>(LinearPolySize(MinVal, FixedDim));
   }
-  static LeafTy getScalable(ScalarTy MinVal) {
+  static constexpr LeafTy getScalable(ScalarTy MinVal) {
     return static_cast<LeafTy>(LinearPolySize(MinVal, ScalableDim));
   }
-  static LeafTy get(ScalarTy MinVal, bool Scalable) {
+  static constexpr LeafTy get(ScalarTy MinVal, bool Scalable) {
     return static_cast<LeafTy>(
         LinearPolySize(MinVal, Scalable ? ScalableDim : FixedDim));
   }
-  static LeafTy getNull() { return get(0, false); }
+  static constexpr LeafTy getNull() { return get(0, false); }
 
   /// Returns the minimum value this size can represent.
-  ScalarTy getKnownMinValue() const { return this->Value; }
+  constexpr ScalarTy getKnownMinValue() const { return this->Value; }
   /// Returns whether the size is scaled by a runtime quantity (vscale).
-  bool isScalable() const { return this->UnivariateDim == ScalableDim; }
+  constexpr bool isScalable() const {
+    return this->UnivariateDim == ScalableDim;
+  }
   /// A return value of true indicates we know at compile time that the number
   /// of elements (vscale * Min) is definitely even. However, returning false
   /// does not guarantee that the total number of elements is odd.
-  bool isKnownEven() const { return (getKnownMinValue() & 0x1) == 0; }
+  constexpr bool isKnownEven() const { return (getKnownMinValue() & 0x1) == 0; }
   /// This function tells the caller whether the element count is known at
   /// compile time to be a multiple of the scalar value RHS.
-  bool isKnownMultipleOf(ScalarTy RHS) const {
+  constexpr bool isKnownMultipleOf(ScalarTy RHS) const {
     return getKnownMinValue() % RHS == 0;
   }
 
   // Return the minimum value with the assumption that the count is exact.
   // Use in places where a scalable count doesn't make sense (e.g. non-vector
   // types, or vectors in backends which don't support scalable vectors).
-  ScalarTy getFixedValue() const {
+  constexpr ScalarTy getFixedValue() const {
     assert(!isScalable() &&
            "Request for a fixed element count on a scalable object");
     return getKnownMinValue();
@@ -325,25 +326,29 @@ class LinearPolySize : public UnivariateLinearPolyBase<LeafTy> {
   // All the functions below make use of the fact vscale is always >= 1, which
   // means that <vscale x 4 x i32> is guaranteed to be >= <4 x i32>, etc.
 
-  static bool isKnownLT(const LinearPolySize &LHS, const LinearPolySize &RHS) {
+  static constexpr bool isKnownLT(const LinearPolySize &LHS,
+                                  const LinearPolySize &RHS) {
     if (!LHS.isScalable() || RHS.isScalable())
       return LHS.getKnownMinValue() < RHS.getKnownMinValue();
     return false;
   }
 
-  static bool isKnownGT(const LinearPolySize &LHS, const LinearPolySize &RHS) {
+  static constexpr bool isKnownGT(const LinearPolySize &LHS,
+                                  const LinearPolySize &RHS) {
     if (LHS.isScalable() || !RHS.isScalable())
       return LHS.getKnownMinValue() > RHS.getKnownMinValue();
     return false;
   }
 
-  static bool isKnownLE(const LinearPolySize &LHS, const LinearPolySize &RHS) {
+  static constexpr bool isKnownLE(const LinearPolySize &LHS,
+                                  const LinearPolySize &RHS) {
     if (!LHS.isScalable() || RHS.isScalable())
       return LHS.getKnownMinValue() <= RHS.getKnownMinValue();
     return false;
   }
 
-  static bool isKnownGE(const LinearPolySize &LHS, const LinearPolySize &RHS) {
+  static constexpr bool isKnownGE(const LinearPolySize &LHS,
+                                  const LinearPolySize &RHS) {
     if (LHS.isScalable() || !RHS.isScalable())
       return LHS.getKnownMinValue() >= RHS.getKnownMinValue();
     return false;
@@ -357,17 +362,17 @@ class LinearPolySize : public UnivariateLinearPolyBase<LeafTy> {
   /// The caller is recommended to use this function in combination with
   /// isKnownMultipleOf(RHS), which lets the caller know if it's possible to
   /// perform a lossless divide by RHS.
-  LeafTy divideCoefficientBy(ScalarTy RHS) const {
+  constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const {
     return static_cast<LeafTy>(
         LinearPolySize::get(getKnownMinValue() / RHS, isScalable()));
   }
 
-  LeafTy multiplyCoefficientBy(ScalarTy RHS) const {
+  constexpr LeafTy multiplyCoefficientBy(ScalarTy RHS) const {
     return static_cast<LeafTy>(
         LinearPolySize::get(getKnownMinValue() * RHS, isScalable()));
   }
 
-  LeafTy coefficientNextPowerOf2() const {
+  constexpr LeafTy coefficientNextPowerOf2() const {
     return static_cast<LeafTy>(LinearPolySize::get(
         static_cast<ScalarTy>(llvm::NextPowerOf2(getKnownMinValue())),
         isScalable()));
@@ -375,14 +380,14 @@ class LinearPolySize : public UnivariateLinearPolyBase<LeafTy> {
 
   /// Returns true if there exists a value X where RHS.multiplyCoefficientBy(X)
   /// will result in a value whose size matches our own.
-  bool hasKnownScalarFactor(const LinearPolySize &RHS) const {
+  constexpr bool hasKnownScalarFactor(const LinearPolySize &RHS) const {
     return isScalable() == RHS.isScalable() &&
            getKnownMinValue() % RHS.getKnownMinValue() == 0;
   }
 
   /// Returns a value X where RHS.multiplyCoefficientBy(X) will result in a
   /// value whose size matches our own.
-  ScalarTy getKnownScalarFactor(const LinearPolySize &RHS) const {
+  constexpr ScalarTy getKnownScalarFactor(const LinearPolySize &RHS) const {
     assert(hasKnownScalarFactor(RHS) && "Expected RHS to be a known factor!");
     return getKnownMinValue() / RHS.getKnownMinValue();
   }
@@ -403,17 +408,20 @@ template <> struct LinearPolyBaseTypeTraits<ElementCount> {
 
 class ElementCount : public LinearPolySize<ElementCount> {
 public:
-  ElementCount() : LinearPolySize(LinearPolySize::getNull()) {}
+  constexpr ElementCount() : LinearPolySize(LinearPolySize::getNull()) {}
 
-  ElementCount(const LinearPolySize<ElementCount> &V) : LinearPolySize(V) {}
+  constexpr ElementCount(const LinearPolySize<ElementCount> &V)
+      : LinearPolySize(V) {}
 
   /// Counting predicates.
   ///
   ///@{ Number of elements..
   /// Exactly one element.
-  bool isScalar() const { return !isScalable() && getKnownMinValue() == 1; }
+  constexpr bool isScalar() const {
+    return !isScalable() && getKnownMinValue() == 1;
+  }
   /// One or more elements.
-  bool isVector() const {
+  constexpr bool isVector() const {
     return (isScalable() && getKnownMinValue() != 0) || getKnownMinValue() > 1;
   }
   ///@}
@@ -434,15 +442,19 @@ template <> struct LinearPolyBaseTypeTraits<TypeSize> {
 // it will represent the known minimum size.
 class TypeSize : public LinearPolySize<TypeSize> {
 public:
-  TypeSize(const LinearPolySize<TypeSize> &V) : LinearPolySize(V) {}
-  TypeSize(ScalarTy MinVal, bool IsScalable)
+  constexpr TypeSize(const LinearPolySize<TypeSize> &V) : LinearPolySize(V) {}
+  constexpr TypeSize(ScalarTy MinVal, bool IsScalable)
       : LinearPolySize(LinearPolySize::get(MinVal, IsScalable)) {}
 
-  static TypeSize Fixed(ScalarTy MinVal) { return TypeSize(MinVal, false); }
-  static TypeSize Scalable(ScalarTy MinVal) { return TypeSize(MinVal, true); }
+  static constexpr TypeSize Fixed(ScalarTy MinVal) {
+    return TypeSize(MinVal, false);
+  }
+  static constexpr TypeSize Scalable(ScalarTy MinVal) {
+    return TypeSize(MinVal, true);
+  }
 
-  ScalarTy getFixedSize() const { return getFixedValue(); }
-  ScalarTy getKnownMinSize() const { return getKnownMinValue(); }
+  constexpr ScalarTy getFixedSize() const { return getFixedValue(); }
+  constexpr ScalarTy getKnownMinSize() const { return getKnownMinValue(); }
 
   // All code for this class below this point is needed because of the
   // temporary implicit conversion to uint64_t. The operator overloads are
@@ -472,25 +484,25 @@ class TypeSize : public LinearPolySize<TypeSize> {
 
   // Additional operators needed to avoid ambiguous parses
   // because of the implicit conversion hack.
-  friend TypeSize operator*(const TypeSize &LHS, const int RHS) {
+  friend constexpr TypeSize operator*(const TypeSize &LHS, const int RHS) {
     return LHS * (ScalarTy)RHS;
   }
-  friend TypeSize operator*(const TypeSize &LHS, const unsigned RHS) {
+  friend constexpr TypeSize operator*(const TypeSize &LHS, const unsigned RHS) {
     return LHS * (ScalarTy)RHS;
   }
-  friend TypeSize operator*(const TypeSize &LHS, const int64_t RHS) {
+  friend constexpr TypeSize operator*(const TypeSize &LHS, const int64_t RHS) {
     return LHS * (ScalarTy)RHS;
   }
-  friend TypeSize operator*(const int LHS, const TypeSize &RHS) {
+  friend constexpr TypeSize operator*(const int LHS, const TypeSize &RHS) {
     return RHS * LHS;
   }
-  friend TypeSize operator*(const unsigned LHS, const TypeSize &RHS) {
+  friend constexpr TypeSize operator*(const unsigned LHS, const TypeSize &RHS) {
     return RHS * LHS;
   }
-  friend TypeSize operator*(const int64_t LHS, const TypeSize &RHS) {
+  friend constexpr TypeSize operator*(const int64_t LHS, const TypeSize &RHS) {
     return RHS * LHS;
   }
-  friend TypeSize operator*(const uint64_t LHS, const TypeSize &RHS) {
+  friend constexpr TypeSize operator*(const uint64_t LHS, const TypeSize &RHS) {
     return RHS * LHS;
   }
 };
@@ -504,7 +516,7 @@ class TypeSize : public LinearPolySize<TypeSize> {
 /// of \p Align. \p Align must be non-zero.
 ///
 /// Similar to the alignTo functions in MathExtras.h
-inline TypeSize alignTo(TypeSize Size, uint64_t Align) {
+inline constexpr TypeSize alignTo(TypeSize Size, uint64_t Align) {
   assert(Align != 0u && "Align must be non-zero");
   return {(Size.getKnownMinValue() + Align - 1) / Align * Align,
           Size.isScalable()};

diff  --git a/llvm/unittests/Support/CMakeLists.txt b/llvm/unittests/Support/CMakeLists.txt
index 7ac6940f7ac4..335627224660 100644
--- a/llvm/unittests/Support/CMakeLists.txt
+++ b/llvm/unittests/Support/CMakeLists.txt
@@ -89,6 +89,7 @@ add_llvm_unittest(SupportTests
   TimeProfilerTest.cpp
   ToolOutputFileTest.cpp
   TypeNameTest.cpp
+  TypeSizeTest.cpp
   TypeTraitsTest.cpp
   TrailingObjectsTest.cpp
   TrigramIndexTest.cpp

diff  --git a/llvm/unittests/Support/TypeSizeTest.cpp b/llvm/unittests/Support/TypeSizeTest.cpp
new file mode 100644
index 000000000000..3552c7949a9a
--- /dev/null
+++ b/llvm/unittests/Support/TypeSizeTest.cpp
@@ -0,0 +1,84 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "llvm/Support/TypeSize.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+constexpr ElementCount CEElementCount = ElementCount();
+
+static_assert(!CEElementCount.isScalar());
+static_assert(!CEElementCount.isVector());
+
+constexpr ElementCount CEElementCountFixed1 = ElementCount::getFixed(1);
+static_assert(CEElementCountFixed1.isScalar());
+static_assert(!CEElementCountFixed1.isVector());
+static_assert(!CEElementCountFixed1.isScalable());
+
+constexpr ElementCount CEElementCountFixed3 = ElementCount::getFixed(3);
+constexpr ElementCount CEElementCountFixed4 = ElementCount::getFixed(4);
+
+static_assert(!CEElementCountFixed4.isScalar());
+static_assert(CEElementCountFixed4.isVector());
+static_assert(CEElementCountFixed4.isKnownEven());
+static_assert(!CEElementCountFixed3.isKnownEven());
+static_assert(!CEElementCountFixed4.isScalable());
+static_assert(!CEElementCountFixed3.isScalable());
+
+constexpr ElementCount CEElementCountScalable4 = ElementCount::getScalable(4);
+
+static_assert(CEElementCountScalable4.isScalable());
+static_assert(!ElementCount::getNull().isScalable());
+static_assert(
+    CEElementCountScalable4.hasKnownScalarFactor(ElementCount::getScalable(2)));
+static_assert(ElementCount::getScalable(8).getKnownScalarFactor(
+                  ElementCount::getScalable(2)) == 4);
+
+static_assert(CEElementCountScalable4 == ElementCount::get(4, true));
+static_assert(CEElementCountFixed4 == ElementCount::get(4, false));
+static_assert(ElementCount::isKnownLT(CEElementCountFixed3,
+                                      CEElementCountFixed4));
+static_assert(ElementCount::isKnownLE(CEElementCountFixed3,
+                                      CEElementCountFixed4));
+static_assert(ElementCount::isKnownGT(CEElementCountFixed4,
+                                      CEElementCountFixed3));
+static_assert(ElementCount::isKnownGE(CEElementCountFixed4,
+                                      CEElementCountFixed3));
+static_assert(CEElementCountFixed3.coefficientNextPowerOf2() ==
+              CEElementCountFixed4);
+static_assert(ElementCount::getFixed(8).divideCoefficientBy(2) ==
+              ElementCount::getFixed(4));
+static_assert(ElementCount::getFixed(8).multiplyCoefficientBy(3) ==
+              ElementCount::getFixed(24));
+static_assert(ElementCount::getFixed(8).isKnownMultipleOf(2));
+
+constexpr TypeSize TSFixed0 = TypeSize::Fixed(0);
+constexpr TypeSize TSFixed1 = TypeSize::Fixed(1);
+constexpr TypeSize TSFixed32 = TypeSize::Fixed(32);
+
+static_assert(TSFixed0.getFixedSize() == 0);
+static_assert(TSFixed1.getFixedSize() == 1);
+static_assert(TSFixed32.getFixedSize() == 32);
+static_assert(TSFixed32.getKnownMinSize() == 32);
+
+static_assert(TypeSize::Scalable(32).getKnownMinSize() == 32);
+
+static_assert(TSFixed32 * 2 == TypeSize::Fixed(64));
+static_assert(TSFixed32 * 2u == TypeSize::Fixed(64));
+static_assert(TSFixed32 * INT64_C(2) == TypeSize::Fixed(64));
+static_assert(TSFixed32 * UINT64_C(2) == TypeSize::Fixed(64));
+
+static_assert(2 * TSFixed32 == TypeSize::Fixed(64));
+static_assert(2u * TSFixed32 == TypeSize::Fixed(64));
+static_assert(INT64_C(2) * TSFixed32 == TypeSize::Fixed(64));
+static_assert(UINT64_C(2) * TSFixed32 == TypeSize::Fixed(64));
+static_assert(alignTo(TypeSize::Fixed(7), 8) == TypeSize::Fixed(8));
+
+} // namespace


        


More information about the llvm-commits mailing list