[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