[llvm] 16c1c9f - Revert D140263 "[NFC] Vastly simplifies TypeSize"
Guillaume Chatelet via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 6 07:33:11 PST 2023
Author: Guillaume Chatelet
Date: 2023-01-06T15:33:00Z
New Revision: 16c1c9fdcc481b036df8921750433e714eafd805
URL: https://github.com/llvm/llvm-project/commit/16c1c9fdcc481b036df8921750433e714eafd805
DIFF: https://github.com/llvm/llvm-project/commit/16c1c9fdcc481b036df8921750433e714eafd805.diff
LOG: Revert D140263 "[NFC] Vastly simplifies TypeSize"
This broke some build bots : https://lab.llvm.org/buildbot/#/builders/16/builds/41419/steps/5/logs/stdio
This reverts commit 4670d5ece57d9b030597da679072f78bb3f4d419.
Added:
llvm/unittests/Support/LinearPolyBaseTest.cpp
Modified:
llvm/include/llvm/Support/TypeSize.h
llvm/unittests/Support/CMakeLists.txt
llvm/unittests/Support/TypeSizeTest.cpp
llvm/utils/TableGen/CodeGenDAGPatterns.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Support/TypeSize.h b/llvm/include/llvm/Support/TypeSize.h
index 53c888e0a2e9b..ae871cf478733 100644
--- a/llvm/include/llvm/Support/TypeSize.h
+++ b/llvm/include/llvm/Support/TypeSize.h
@@ -31,97 +31,176 @@ namespace llvm {
/// done on a scalable vector. This function may not return.
void reportInvalidSizeRequest(const char *Msg);
-/// StackOffset holds a fixed and a scalable offset in bytes.
-class StackOffset {
- int64_t Fixed = 0;
- int64_t Scalable = 0;
+template <typename LeafTy> struct LinearPolyBaseTypeTraits {};
- StackOffset(int64_t Fixed, int64_t Scalable)
- : Fixed(Fixed), Scalable(Scalable) {}
+//===----------------------------------------------------------------------===//
+// LinearPolyBase - a base class for linear polynomials with multiple
+// dimensions. This can e.g. be used to describe offsets that are have both a
+// fixed and scalable component.
+//===----------------------------------------------------------------------===//
+/// LinearPolyBase describes a linear polynomial:
+/// c0 * scale0 + c1 * scale1 + ... + cK * scaleK
+/// where the scale is implicit, so only the coefficients are encoded.
+template <typename LeafTy>
+class LinearPolyBase {
public:
- StackOffset() = default;
- static StackOffset getFixed(int64_t Fixed) { return {Fixed, 0}; }
- static StackOffset getScalable(int64_t Scalable) { return {0, Scalable}; }
- static StackOffset get(int64_t Fixed, int64_t Scalable) {
- return {Fixed, Scalable};
+ using ScalarTy = typename LinearPolyBaseTypeTraits<LeafTy>::ScalarTy;
+ static constexpr auto Dimensions = LinearPolyBaseTypeTraits<LeafTy>::Dimensions;
+ static_assert(Dimensions != std::numeric_limits<unsigned>::max(),
+ "Dimensions out of range");
+
+private:
+ std::array<ScalarTy, Dimensions> Coefficients;
+
+protected:
+ constexpr LinearPolyBase(ArrayRef<ScalarTy> Values) {
+ std::copy(Values.begin(), Values.end(), Coefficients.begin());
+ }
+
+public:
+ friend LeafTy &operator+=(LeafTy &LHS, const LeafTy &RHS) {
+ for (unsigned I=0; I<Dimensions; ++I)
+ LHS.Coefficients[I] += RHS.Coefficients[I];
+ return LHS;
}
- /// Returns the fixed component of the stack.
- int64_t getFixed() const { return Fixed; }
+ friend LeafTy &operator-=(LeafTy &LHS, const LeafTy &RHS) {
+ for (unsigned I=0; I<Dimensions; ++I)
+ LHS.Coefficients[I] -= RHS.Coefficients[I];
+ return LHS;
+ }
+
+ friend LeafTy &operator*=(LeafTy &LHS, ScalarTy RHS) {
+ for (auto &C : LHS.Coefficients)
+ C *= RHS;
+ return LHS;
+ }
- /// Returns the scalable component of the stack.
- int64_t getScalable() const { return Scalable; }
+ friend LeafTy operator+(const LeafTy &LHS, const LeafTy &RHS) {
+ LeafTy Copy = LHS;
+ return Copy += RHS;
+ }
- // Arithmetic operations.
- StackOffset operator+(const StackOffset &RHS) const {
- return {Fixed + RHS.Fixed, Scalable + RHS.Scalable};
+ friend LeafTy operator-(const LeafTy &LHS, const LeafTy &RHS) {
+ LeafTy Copy = LHS;
+ return Copy -= RHS;
}
- StackOffset operator-(const StackOffset &RHS) const {
- return {Fixed - RHS.Fixed, Scalable - RHS.Scalable};
+
+ friend LeafTy operator*(const LeafTy &LHS, ScalarTy RHS) {
+ LeafTy Copy = LHS;
+ return Copy *= RHS;
}
- StackOffset &operator+=(const StackOffset &RHS) {
- Fixed += RHS.Fixed;
- Scalable += RHS.Scalable;
- return *this;
+
+ template <typename U = ScalarTy>
+ friend std::enable_if_t<std::is_signed<U>::value, LeafTy>
+ operator-(const LeafTy &LHS) {
+ LeafTy Copy = LHS;
+ return Copy *= -1;
}
- StackOffset &operator-=(const StackOffset &RHS) {
- Fixed -= RHS.Fixed;
- Scalable -= RHS.Scalable;
- return *this;
+
+ constexpr bool operator==(const LinearPolyBase &RHS) const {
+ return std::equal(Coefficients.begin(), Coefficients.end(),
+ RHS.Coefficients.begin());
}
- StackOffset operator-() const { return {-Fixed, -Scalable}; }
- // Equality comparisons.
- bool operator==(const StackOffset &RHS) const {
- return Fixed == RHS.Fixed && Scalable == RHS.Scalable;
+ constexpr bool operator!=(const LinearPolyBase &RHS) const {
+ return !(*this == RHS);
}
- bool operator!=(const StackOffset &RHS) const {
- return Fixed != RHS.Fixed || Scalable != RHS.Scalable;
+
+ constexpr bool isZero() const {
+ return all_of(Coefficients, [](const ScalarTy &C) { return C == 0; });
}
+ constexpr bool isNonZero() const { return !isZero(); }
+ constexpr explicit operator bool() const { return isNonZero(); }
- // The bool operator returns true iff any of the components is non zero.
- explicit operator bool() const { return Fixed != 0 || Scalable != 0; }
+ constexpr ScalarTy getValue(unsigned Dim) const { return Coefficients[Dim]; }
};
-namespace details {
+//===----------------------------------------------------------------------===//
+// StackOffset - Represent an offset with named fixed and scalable components.
+//===----------------------------------------------------------------------===//
+
+class StackOffset;
+template <> struct LinearPolyBaseTypeTraits<StackOffset> {
+ using ScalarTy = int64_t;
+ static constexpr unsigned Dimensions = 2;
+};
+
+/// StackOffset is a class to represent an offset with 2 dimensions,
+/// named fixed and scalable, respectively. This class allows a value for both
+/// dimensions to depict e.g. "8 bytes and 16 scalable bytes", which is needed
+/// to represent stack offsets.
+class StackOffset : public LinearPolyBase<StackOffset> {
+protected:
+ StackOffset(ScalarTy Fixed, ScalarTy Scalable)
+ : LinearPolyBase<StackOffset>({Fixed, Scalable}) {}
-// Base class for ElementCount and TypeSize below.
-template <typename LeafTy, typename ValueTy> class FixedOrScalableQuantity {
public:
- using ScalarTy = ValueTy;
+ StackOffset() : StackOffset({0, 0}) {}
+ StackOffset(const LinearPolyBase<StackOffset> &Other)
+ : LinearPolyBase<StackOffset>(Other) {}
+ static StackOffset getFixed(ScalarTy Fixed) { return {Fixed, 0}; }
+ static StackOffset getScalable(ScalarTy Scalable) { return {0, Scalable}; }
+ static StackOffset get(ScalarTy Fixed, ScalarTy Scalable) {
+ return {Fixed, Scalable};
+ }
+
+ ScalarTy getFixed() const { return this->getValue(0); }
+ ScalarTy getScalable() const { return this->getValue(1); }
+};
+
+//===----------------------------------------------------------------------===//
+// UnivariateLinearPolyBase - a base class for linear polynomials with multiple
+// dimensions, but where only one dimension can be set at any time.
+// This can e.g. be used to describe sizes that are either fixed or scalable.
+//===----------------------------------------------------------------------===//
+
+/// UnivariateLinearPolyBase is a base class for ElementCount and TypeSize.
+/// Like LinearPolyBase it tries to represent a linear polynomial
+/// where only one dimension can be set at any time, e.g.
+/// 0 * scale0 + 0 * scale1 + ... + cJ * scaleJ + ... + 0 * scaleK
+/// The dimension that is set is the univariate dimension.
+template <typename LeafTy>
+class UnivariateLinearPolyBase {
+public:
+ using ScalarTy = typename LinearPolyBaseTypeTraits<LeafTy>::ScalarTy;
+ static constexpr auto Dimensions = LinearPolyBaseTypeTraits<LeafTy>::Dimensions;
+ static_assert(Dimensions != std::numeric_limits<unsigned>::max(),
+ "Dimensions out of range");
protected:
- ScalarTy Quantity = 0;
- bool Scalable = false;
+ ScalarTy Value; // The value at the univeriate dimension.
+ unsigned UnivariateDim; // The univeriate dimension.
- constexpr FixedOrScalableQuantity() = default;
- constexpr FixedOrScalableQuantity(ScalarTy Quantity, bool Scalable)
- : Quantity(Quantity), Scalable(Scalable) {}
+ constexpr UnivariateLinearPolyBase(ScalarTy Val, unsigned UnivariateDim)
+ : Value(Val), UnivariateDim(UnivariateDim) {
+ assert(UnivariateDim < Dimensions && "Dimension out of range");
+ }
- friend constexpr LeafTy &operator+=(LeafTy &LHS, const LeafTy &RHS) {
- assert(LHS.Scalable == RHS.Scalable && "Incompatible types");
- LHS.Quantity += RHS.Quantity;
+ friend LeafTy &operator+=(LeafTy &LHS, const LeafTy &RHS) {
+ assert(LHS.UnivariateDim == RHS.UnivariateDim && "Invalid dimensions");
+ LHS.Value += RHS.Value;
return LHS;
}
- friend constexpr LeafTy &operator-=(LeafTy &LHS, const LeafTy &RHS) {
- assert(LHS.Scalable == RHS.Scalable && "Incompatible types");
- LHS.Quantity -= RHS.Quantity;
+ friend LeafTy &operator-=(LeafTy &LHS, const LeafTy &RHS) {
+ assert(LHS.UnivariateDim == RHS.UnivariateDim && "Invalid dimensions");
+ LHS.Value -= RHS.Value;
return LHS;
}
friend constexpr LeafTy &operator*=(LeafTy &LHS, ScalarTy RHS) {
- LHS.Quantity *= RHS;
+ LHS.Value *= RHS;
return LHS;
}
- friend constexpr LeafTy operator+(const LeafTy &LHS, const LeafTy &RHS) {
+ friend LeafTy operator+(const LeafTy &LHS, const LeafTy &RHS) {
LeafTy Copy = LHS;
return Copy += RHS;
}
- friend constexpr LeafTy operator-(const LeafTy &LHS, const LeafTy &RHS) {
+ friend LeafTy operator-(const LeafTy &LHS, const LeafTy &RHS) {
LeafTy Copy = LHS;
return Copy -= RHS;
}
@@ -132,43 +211,96 @@ template <typename LeafTy, typename ValueTy> class FixedOrScalableQuantity {
}
template <typename U = ScalarTy>
- friend constexpr std::enable_if_t<std::is_signed<U>::value, LeafTy>
+ friend std::enable_if_t<std::is_signed<U>::value, LeafTy>
operator-(const LeafTy &LHS) {
LeafTy Copy = LHS;
return Copy *= -1;
}
public:
- constexpr bool operator==(const FixedOrScalableQuantity &RHS) const {
- return Quantity == RHS.Quantity && Scalable == RHS.Scalable;
+ constexpr bool operator==(const UnivariateLinearPolyBase &RHS) const {
+ return Value == RHS.Value && UnivariateDim == RHS.UnivariateDim;
}
- constexpr bool operator!=(const FixedOrScalableQuantity &RHS) const {
- return Quantity != RHS.Quantity || Scalable != RHS.Scalable;
+ constexpr bool operator!=(const UnivariateLinearPolyBase &RHS) const {
+ return !(*this == RHS);
}
- constexpr bool isZero() const { return Quantity == 0; }
-
- constexpr bool isNonZero() const { return Quantity != 0; }
-
- explicit operator bool() const { return isNonZero(); }
+ 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 underlying quantity.
+ /// Add \p RHS to the value at the univariate dimension.
constexpr LeafTy getWithIncrement(ScalarTy RHS) const {
- return LeafTy::get(Quantity + RHS, Scalable);
+ return static_cast<LeafTy>(
+ UnivariateLinearPolyBase(Value + RHS, UnivariateDim));
+ }
+
+ /// Subtract \p RHS from the value at the univariate dimension.
+ constexpr LeafTy getWithDecrement(ScalarTy RHS) const {
+ return static_cast<LeafTy>(
+ UnivariateLinearPolyBase(Value - RHS, UnivariateDim));
}
+};
+
+
+//===----------------------------------------------------------------------===//
+// LinearPolySize - base class for fixed- or scalable sizes.
+// ^ ^
+// | |
+// | +----- ElementCount - Leaf class to represent an element count
+// | (vscale x unsigned)
+// |
+// +-------- TypeSize - Leaf class to represent a type size
+// (vscale x uint64_t)
+//===----------------------------------------------------------------------===//
+
+/// LinearPolySize is a base class to represent sizes. It is either
+/// fixed-sized or it is scalable-sized, but it cannot be both.
+template <typename LeafTy>
+class LinearPolySize : public UnivariateLinearPolyBase<LeafTy> {
+ // Make the parent class a friend, so that it can access the protected
+ // conversion/copy-constructor for UnivariatePolyBase<LeafTy> ->
+ // LinearPolySize<LeafTy>.
+ friend class UnivariateLinearPolyBase<LeafTy>;
- /// Returns the minimum value this quantity can represent.
- constexpr ScalarTy getKnownMinValue() const { return Quantity; }
+public:
+ using ScalarTy = typename UnivariateLinearPolyBase<LeafTy>::ScalarTy;
+ enum Dims : unsigned { FixedDim = 0, ScalableDim = 1 };
+
+protected:
+ constexpr LinearPolySize(ScalarTy MinVal, Dims D)
+ : UnivariateLinearPolyBase<LeafTy>(MinVal, D) {}
- /// Returns whether the quantity is scaled by a runtime quantity (vscale).
- constexpr bool isScalable() const { return Scalable; }
+ constexpr LinearPolySize(const UnivariateLinearPolyBase<LeafTy> &V)
+ : UnivariateLinearPolyBase<LeafTy>(V) {}
+public:
+ static constexpr LeafTy getFixed(ScalarTy MinVal) {
+ return static_cast<LeafTy>(LinearPolySize(MinVal, FixedDim));
+ }
+ static constexpr LeafTy getScalable(ScalarTy MinVal) {
+ return static_cast<LeafTy>(LinearPolySize(MinVal, ScalableDim));
+ }
+ static constexpr LeafTy get(ScalarTy MinVal, bool Scalable) {
+ return static_cast<LeafTy>(
+ LinearPolySize(MinVal, Scalable ? ScalableDim : FixedDim));
+ }
+ static constexpr LeafTy getNull() { return get(0, false); }
+
+ /// Returns the minimum value this size can represent.
+ constexpr ScalarTy getKnownMinValue() const { return this->Value; }
+ /// Returns whether the size is scaled by a runtime quantity (vscale).
+ 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.
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.
constexpr bool isKnownMultipleOf(ScalarTy RHS) const {
@@ -184,8 +316,8 @@ template <typename LeafTy, typename ValueTy> class FixedOrScalableQuantity {
return getKnownMinValue();
}
- // For some cases, quantity ordering between scalable and fixed quantity types
- // cannot be determined at compile time, so such comparisons aren't allowed.
+ // For some cases, size ordering between scalable and fixed size types cannot
+ // be determined at compile time, so such comparisons aren't allowed.
//
// e.g. <vscale x 2 x i16> could be bigger than <4 x i32> with a runtime
// vscale >= 5, equal sized with a vscale of 4, and smaller with
@@ -194,29 +326,29 @@ template <typename LeafTy, typename ValueTy> class FixedOrScalableQuantity {
// 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 constexpr bool isKnownLT(const FixedOrScalableQuantity &LHS,
- const FixedOrScalableQuantity &RHS) {
+ static constexpr bool isKnownLT(const LinearPolySize &LHS,
+ const LinearPolySize &RHS) {
if (!LHS.isScalable() || RHS.isScalable())
return LHS.getKnownMinValue() < RHS.getKnownMinValue();
return false;
}
- static constexpr bool isKnownGT(const FixedOrScalableQuantity &LHS,
- const FixedOrScalableQuantity &RHS) {
+ static constexpr bool isKnownGT(const LinearPolySize &LHS,
+ const LinearPolySize &RHS) {
if (LHS.isScalable() || !RHS.isScalable())
return LHS.getKnownMinValue() > RHS.getKnownMinValue();
return false;
}
- static constexpr bool isKnownLE(const FixedOrScalableQuantity &LHS,
- const FixedOrScalableQuantity &RHS) {
+ static constexpr bool isKnownLE(const LinearPolySize &LHS,
+ const LinearPolySize &RHS) {
if (!LHS.isScalable() || RHS.isScalable())
return LHS.getKnownMinValue() <= RHS.getKnownMinValue();
return false;
}
- static constexpr bool isKnownGE(const FixedOrScalableQuantity &LHS,
- const FixedOrScalableQuantity &RHS) {
+ static constexpr bool isKnownGE(const LinearPolySize &LHS,
+ const LinearPolySize &RHS) {
if (LHS.isScalable() || !RHS.isScalable())
return LHS.getKnownMinValue() >= RHS.getKnownMinValue();
return false;
@@ -231,31 +363,31 @@ template <typename LeafTy, typename ValueTy> class FixedOrScalableQuantity {
/// isKnownMultipleOf(RHS), which lets the caller know if it's possible to
/// perform a lossless divide by RHS.
constexpr LeafTy divideCoefficientBy(ScalarTy RHS) const {
- return LeafTy::get(getKnownMinValue() / RHS, isScalable());
+ return static_cast<LeafTy>(
+ LinearPolySize::get(getKnownMinValue() / RHS, isScalable()));
}
constexpr LeafTy multiplyCoefficientBy(ScalarTy RHS) const {
- return LeafTy::get(getKnownMinValue() * RHS, isScalable());
+ return static_cast<LeafTy>(
+ LinearPolySize::get(getKnownMinValue() * RHS, isScalable()));
}
constexpr LeafTy coefficientNextPowerOf2() const {
- return LeafTy::get(
+ return static_cast<LeafTy>(LinearPolySize::get(
static_cast<ScalarTy>(llvm::NextPowerOf2(getKnownMinValue())),
- isScalable());
+ isScalable()));
}
/// Returns true if there exists a value X where RHS.multiplyCoefficientBy(X)
- /// will result in a value whose quantity matches our own.
- constexpr bool
- hasKnownScalarFactor(const FixedOrScalableQuantity &RHS) const {
+ /// will result in a value whose size matches our own.
+ 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 quantity matches our own.
- constexpr ScalarTy
- getKnownScalarFactor(const FixedOrScalableQuantity &RHS) const {
+ /// value whose size matches our own.
+ constexpr ScalarTy getKnownScalarFactor(const LinearPolySize &RHS) const {
assert(hasKnownScalarFactor(RHS) && "Expected RHS to be a known factor!");
return getKnownMinValue() / RHS.getKnownMinValue();
}
@@ -268,35 +400,22 @@ template <typename LeafTy, typename ValueTy> class FixedOrScalableQuantity {
}
};
-} // namespace details
-
-// Stores the number of elements for a type and whether this type is fixed
-// (N-Elements) or scalable (e.g., SVE).
-// - ElementCount::getFixed(1) : A scalar value.
-// - ElementCount::getFixed(2) : A vector type holding 2 values.
-// - ElementCount::getScalable(4) : A scalable vector type holding 4 values.
-class ElementCount
- : public details::FixedOrScalableQuantity<ElementCount, unsigned> {
- constexpr ElementCount(ScalarTy MinVal, bool Scalable)
- : FixedOrScalableQuantity(MinVal, Scalable) {}
-
- constexpr ElementCount(
- const FixedOrScalableQuantity<ElementCount, unsigned> &V)
- : FixedOrScalableQuantity(V) {}
+class ElementCount;
+template <> struct LinearPolyBaseTypeTraits<ElementCount> {
+ using ScalarTy = unsigned;
+ static constexpr unsigned Dimensions = 2;
+};
+class ElementCount : public LinearPolySize<ElementCount> {
public:
- constexpr ElementCount() : FixedOrScalableQuantity() {}
+ constexpr ElementCount() : LinearPolySize(LinearPolySize::getNull()) {}
- static constexpr ElementCount getFixed(ScalarTy MinVal) {
- return ElementCount(MinVal, false);
- }
- static constexpr ElementCount getScalable(ScalarTy MinVal) {
- return ElementCount(MinVal, true);
- }
- static constexpr ElementCount get(ScalarTy MinVal, bool Scalable) {
- return ElementCount(MinVal, Scalable);
- }
+ constexpr ElementCount(const LinearPolySize<ElementCount> &V)
+ : LinearPolySize(V) {}
+ /// Counting predicates.
+ ///
+ ///@{ Number of elements..
/// Exactly one element.
constexpr bool isScalar() const {
return !isScalable() && getKnownMinValue() == 1;
@@ -305,33 +424,33 @@ class ElementCount
constexpr bool isVector() const {
return (isScalable() && getKnownMinValue() != 0) || getKnownMinValue() > 1;
}
+ ///@}
};
-// Stores the size of a type. If the type is of fixed size, it will represent
-// the exact size. If the type is a scalable vector, it will represent the known
-// minimum size.
-class TypeSize : public details::FixedOrScalableQuantity<TypeSize, uint64_t> {
- TypeSize(const FixedOrScalableQuantity<TypeSize, uint64_t> &V)
- : FixedOrScalableQuantity(V) {}
+// This class is used to represent the size of types. If the type is of fixed
+class TypeSize;
+template <> struct LinearPolyBaseTypeTraits<TypeSize> {
+ using ScalarTy = uint64_t;
+ static constexpr unsigned Dimensions = 2;
+};
+// TODO: Most functionality in this class will gradually be phased out
+// so it will resemble LinearPolySize as much as possible.
+//
+// TypeSize is used to represent the size of types. If the type is of fixed
+// size, it will represent the exact size. If the type is a scalable vector,
+// it will represent the known minimum size.
+class TypeSize : public LinearPolySize<TypeSize> {
public:
- constexpr TypeSize(ScalarTy Quantity, bool Scalable)
- : FixedOrScalableQuantity(Quantity, Scalable) {}
+ constexpr TypeSize(const LinearPolySize<TypeSize> &V) : LinearPolySize(V) {}
+ constexpr TypeSize(ScalarTy MinVal, bool IsScalable)
+ : LinearPolySize(LinearPolySize::get(MinVal, IsScalable)) {}
- static constexpr TypeSize getFixed(ScalarTy ExactSize) {
- return TypeSize(ExactSize, false);
+ static constexpr TypeSize Fixed(ScalarTy MinVal) {
+ return TypeSize(MinVal, false);
}
- static constexpr TypeSize getScalable(ScalarTy MinimunSize) {
- return TypeSize(MinimunSize, true);
- }
- static constexpr TypeSize get(ScalarTy Quantity, bool Scalable) {
- return TypeSize(Quantity, Scalable);
- }
- static constexpr TypeSize Fixed(ScalarTy ExactSize) {
- return TypeSize(ExactSize, false);
- }
- static constexpr TypeSize Scalable(ScalarTy MinimumSize) {
- return TypeSize(MinimumSize, true);
+ static constexpr TypeSize Scalable(ScalarTy MinVal) {
+ return TypeSize(MinVal, true);
}
constexpr ScalarTy getFixedSize() const { return getFixedValue(); }
@@ -393,7 +512,7 @@ class TypeSize : public details::FixedOrScalableQuantity<TypeSize, uint64_t> {
//===----------------------------------------------------------------------===//
/// Returns a TypeSize with a known minimum size that is the next integer
-/// (mod 2**64) that is greater than or equal to \p Quantity and is a multiple
+/// (mod 2**64) that is greater than or equal to \p Value and is a multiple
/// of \p Align. \p Align must be non-zero.
///
/// Similar to the alignTo functions in MathExtras.h
@@ -403,11 +522,10 @@ inline constexpr TypeSize alignTo(TypeSize Size, uint64_t Align) {
Size.isScalable()};
}
-/// Stream operator function for `FixedOrScalableQuantity`.
-template <typename LeafTy, typename ScalarTy>
-inline raw_ostream &
-operator<<(raw_ostream &OS,
- const details::FixedOrScalableQuantity<LeafTy, ScalarTy> &PS) {
+/// Stream operator function for `LinearPolySize`.
+template <typename LeafTy>
+inline raw_ostream &operator<<(raw_ostream &OS,
+ const LinearPolySize<LeafTy> &PS) {
PS.print(OS);
return OS;
}
@@ -426,6 +544,7 @@ template <> struct DenseMapInfo<ElementCount, void> {
return HashVal;
}
+
static bool isEqual(const ElementCount &LHS, const ElementCount &RHS) {
return LHS == RHS;
}
diff --git a/llvm/unittests/Support/CMakeLists.txt b/llvm/unittests/Support/CMakeLists.txt
index ccffb42e267eb..91c6c98748706 100644
--- a/llvm/unittests/Support/CMakeLists.txt
+++ b/llvm/unittests/Support/CMakeLists.txt
@@ -51,6 +51,7 @@ add_llvm_unittest(SupportTests
JSONTest.cpp
KnownBitsTest.cpp
LEB128Test.cpp
+ LinearPolyBaseTest.cpp
LineIteratorTest.cpp
LockFileManagerTest.cpp
MatchersTest.cpp
diff --git a/llvm/unittests/Support/LinearPolyBaseTest.cpp b/llvm/unittests/Support/LinearPolyBaseTest.cpp
new file mode 100644
index 0000000000000..15b366210bca4
--- /dev/null
+++ b/llvm/unittests/Support/LinearPolyBaseTest.cpp
@@ -0,0 +1,176 @@
+//===- TestPoly3D.cpp - Poly3D unit tests------------------------===//
+//
+// 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;
+
+class Poly3D;
+
+namespace llvm {
+template <> struct LinearPolyBaseTypeTraits<Poly3D> {
+ using ScalarTy = int64_t;
+ static const unsigned Dimensions = 3;
+};
+}
+
+using Poly3DBase = LinearPolyBase<Poly3D>;
+class Poly3D : public Poly3DBase {
+public:
+ using ScalarTy = Poly3DBase::ScalarTy;
+ Poly3D(ScalarTy x, ScalarTy y, ScalarTy z) : Poly3DBase({x, y, z}) {}
+ Poly3D(const Poly3DBase &Convert) : Poly3DBase(Convert) {}
+};
+
+TEST(LinearPolyBase, Poly3D_isZero) {
+ EXPECT_TRUE(Poly3D(0, 0, 0).isZero());
+ EXPECT_TRUE(Poly3D(0, 0, 1).isNonZero());
+ EXPECT_TRUE(Poly3D(0, 0, 1));
+}
+
+TEST(LinearPolyBase, Poly3D_Equality) {
+ EXPECT_EQ(Poly3D(1, 2, 3), Poly3D(1, 2, 3));
+ EXPECT_NE(Poly3D(1, 2, 3), Poly3D(1, 2, 4));
+}
+
+TEST(LinearPolyBase, Poly3D_GetValue) {
+ EXPECT_EQ(Poly3D(1, 2, 3).getValue(0), 1);
+ EXPECT_EQ(Poly3D(1, 2, 3).getValue(1), 2);
+ EXPECT_EQ(Poly3D(1, 2, 3).getValue(2), 3);
+}
+
+TEST(LinearPolyBase, Poly3D_Add) {
+ // Test operator+
+ EXPECT_EQ(Poly3D(42, 0, 0) + Poly3D(0, 42, 0) + Poly3D(0, 0, 42),
+ Poly3D(42, 42, 42));
+
+ // Test operator+=
+ Poly3D X(42, 0, 0);
+ X += Poly3D(0, 42, 0);
+ X += Poly3D(0, 0, 42);
+ EXPECT_EQ(X, Poly3D(42, 42, 42));
+}
+
+TEST(LinearPolyBase, Poly3D_Sub) {
+ // Test operator-
+ EXPECT_EQ(Poly3D(42, 42, 42) - Poly3D(42, 0, 0) - Poly3D(0, 42, 0) -
+ Poly3D(0, 0, 42),
+ Poly3D(0, 0, 0));
+
+ // Test operator-=
+ Poly3D X(42, 42, 42);
+ X -= Poly3D(42, 0, 0);
+ X -= Poly3D(0, 42, 0);
+ X -= Poly3D(0, 0, 42);
+ EXPECT_EQ(X, Poly3D(0, 0, 0));
+}
+
+TEST(LinearPolyBase, Poly3D_Scale) {
+ // Test operator*
+ EXPECT_EQ(Poly3D(1, 2, 4) * 2, Poly3D(2, 4, 8));
+ EXPECT_EQ(Poly3D(1, 2, 4) * -2, Poly3D(-2, -4, -8));
+}
+
+TEST(LinearPolyBase, Poly3D_Invert) {
+ // Test operator-
+ EXPECT_EQ(-Poly3D(2, 4, 8), Poly3D(-2, -4, -8));
+}
+
+class Univariate3D;
+namespace llvm {
+template <> struct LinearPolyBaseTypeTraits<Univariate3D> {
+ using ScalarTy = int64_t;
+ static const unsigned Dimensions = 3;
+};
+}
+
+using Univariate3DBase = UnivariateLinearPolyBase<Univariate3D>;
+class Univariate3D : public Univariate3DBase {
+public:
+ using ScalarTy = Univariate3DBase::ScalarTy;
+ constexpr Univariate3D(ScalarTy x, unsigned Dim) : Univariate3DBase(x, Dim) {}
+ Univariate3D(const Univariate3DBase &Convert) : Univariate3DBase(Convert) {}
+};
+
+TEST(UnivariateLinearPolyBase, Univariate3D_isZero) {
+ EXPECT_TRUE(Univariate3D(0, 0).isZero());
+ EXPECT_TRUE(Univariate3D(0, 1).isZero());
+ EXPECT_TRUE(Univariate3D(0, 2).isZero());
+ EXPECT_TRUE(Univariate3D(1, 0).isNonZero());
+ EXPECT_TRUE(Univariate3D(1, 1).isNonZero());
+ EXPECT_TRUE(Univariate3D(1, 2).isNonZero());
+ EXPECT_TRUE(Univariate3D(1, 0));
+}
+
+TEST(UnivariateLinearPolyBase, Univariate3D_Equality) {
+ EXPECT_EQ(Univariate3D(1, 0), Univariate3D(1, 0));
+ EXPECT_NE(Univariate3D(1, 0), Univariate3D(1, 2));
+ EXPECT_NE(Univariate3D(1, 0), Univariate3D(1, 1));
+ EXPECT_NE(Univariate3D(1, 0), Univariate3D(2, 0));
+ EXPECT_NE(Univariate3D(1, 0), Univariate3D(0, 0));
+}
+
+TEST(UnivariateLinearPolyBase, Univariate3D_GetValue) {
+ EXPECT_EQ(Univariate3D(42, 0).getValue(0), 42);
+ EXPECT_EQ(Univariate3D(42, 0).getValue(1), 0);
+ EXPECT_EQ(Univariate3D(42, 0).getValue(2), 0);
+
+ EXPECT_EQ(Univariate3D(42, 1).getValue(0), 0);
+ EXPECT_EQ(Univariate3D(42, 1).getValue(1), 42);
+ EXPECT_EQ(Univariate3D(42, 1).getValue(2), 0);
+}
+
+TEST(UnivariateLinearPolyBase, Univariate3D_Add) {
+ // Test operator+
+ EXPECT_EQ(Univariate3D(42, 0) + Univariate3D(42, 0), Univariate3D(84, 0));
+ EXPECT_EQ(Univariate3D(42, 1) + Univariate3D(42, 1), Univariate3D(84, 1));
+ EXPECT_DEBUG_DEATH(Univariate3D(42, 0) + Univariate3D(42, 1),
+ "Invalid dimensions");
+
+ // Test operator+=
+ Univariate3D X(42, 0);
+ X += Univariate3D(42, 0);
+ EXPECT_EQ(X, Univariate3D(84, 0));
+
+ // Test 'getWithIncrement' method
+ EXPECT_EQ(Univariate3D(42, 0).getWithIncrement(1), Univariate3D(43, 0));
+ EXPECT_EQ(Univariate3D(42, 1).getWithIncrement(2), Univariate3D(44, 1));
+ EXPECT_EQ(Univariate3D(42, 2).getWithIncrement(3), Univariate3D(45, 2));
+}
+
+TEST(UnivariateLinearPolyBase, Univariate3D_Sub) {
+ // Test operator+
+ EXPECT_EQ(Univariate3D(84, 0) - Univariate3D(42, 0), Univariate3D(42, 0));
+ EXPECT_EQ(Univariate3D(84, 1) - Univariate3D(42, 1), Univariate3D(42, 1));
+ EXPECT_DEBUG_DEATH(Univariate3D(84, 0) - Univariate3D(42, 1),
+ "Invalid dimensions");
+
+ // Test operator+=
+ Univariate3D X(84, 0);
+ X -= Univariate3D(42, 0);
+ EXPECT_EQ(X, Univariate3D(42, 0));
+
+ // Test 'getWithDecrement' method
+ EXPECT_EQ(Univariate3D(43, 0).getWithDecrement(1), Univariate3D(42, 0));
+ EXPECT_EQ(Univariate3D(44, 1).getWithDecrement(2), Univariate3D(42, 1));
+ EXPECT_EQ(Univariate3D(45, 2).getWithDecrement(3), Univariate3D(42, 2));
+}
+
+TEST(UnivariateLinearPolyBase, Univariate3D_Scale) {
+ // Test operator*
+ EXPECT_EQ(Univariate3D(4, 0) * 2, Univariate3D(8, 0));
+ EXPECT_EQ(Univariate3D(4, 1) * -2, Univariate3D(-8, 1));
+}
+
+TEST(UnivariateLinearPolyBase, Univariate3D_Invert) {
+ // Test operator-
+ EXPECT_EQ(-Univariate3D(4, 0), Univariate3D(-4, 0));
+ EXPECT_EQ(-Univariate3D(4, 1), Univariate3D(-4, 1));
+}
+
diff --git a/llvm/unittests/Support/TypeSizeTest.cpp b/llvm/unittests/Support/TypeSizeTest.cpp
index 6e566be375817..3552c7949a9a0 100644
--- a/llvm/unittests/Support/TypeSizeTest.cpp
+++ b/llvm/unittests/Support/TypeSizeTest.cpp
@@ -35,7 +35,7 @@ static_assert(!CEElementCountFixed3.isScalable());
constexpr ElementCount CEElementCountScalable4 = ElementCount::getScalable(4);
static_assert(CEElementCountScalable4.isScalable());
-static_assert(!ElementCount().isScalable());
+static_assert(!ElementCount::getNull().isScalable());
static_assert(
CEElementCountScalable4.hasKnownScalarFactor(ElementCount::getScalable(2)));
static_assert(ElementCount::getScalable(8).getKnownScalarFactor(
diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
index bbe04fc769f3d..8c1b0997d8698 100644
--- a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -740,7 +740,7 @@ bool TypeInfer::EnforceSameNumElts(TypeSetByHwMode &V, TypeSetByHwMode &W) {
auto NoLength = [](const SmallDenseSet<ElementCount> &Lengths,
MVT T) -> bool {
return !Lengths.count(T.isVector() ? T.getVectorElementCount()
- : ElementCount());
+ : ElementCount::getNull());
};
SmallVector<unsigned, 4> Modes;
@@ -751,9 +751,11 @@ bool TypeInfer::EnforceSameNumElts(TypeSetByHwMode &V, TypeSetByHwMode &W) {
SmallDenseSet<ElementCount> VN, WN;
for (MVT T : VS)
- VN.insert(T.isVector() ? T.getVectorElementCount() : ElementCount());
+ VN.insert(T.isVector() ? T.getVectorElementCount()
+ : ElementCount::getNull());
for (MVT T : WS)
- WN.insert(T.isVector() ? T.getVectorElementCount() : ElementCount());
+ WN.insert(T.isVector() ? T.getVectorElementCount()
+ : ElementCount::getNull());
Changed |= berase_if(VS, std::bind(NoLength, WN, std::placeholders::_1));
Changed |= berase_if(WS, std::bind(NoLength, VN, std::placeholders::_1));
More information about the llvm-commits
mailing list