[llvm] [GlobalISel][AMDGPU] LLT changes for FPInfo (PR #130651)
Tim Gymnich via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 10 11:21:29 PDT 2025
https://github.com/tgymnich created https://github.com/llvm/llvm-project/pull/130651
- adds new floating point and integer LLT kinds for both scalars and vectors.
## TODO:
- [] fix new tests
>From c478d04d39a2b5d13152dac575e1327673f8e4c4 Mon Sep 17 00:00:00 2001
From: Tim Gymnich <tim at gymni.ch>
Date: Thu, 6 Feb 2025 13:16:43 +0100
Subject: [PATCH 1/5] use ElementCount instead of LLT for changeElementCount
---
.../llvm/CodeGen/GlobalISel/LegalizerInfo.h | 2 +-
llvm/lib/CodeGen/GlobalISel/LegalizeMutations.cpp | 6 ++----
.../CodeGen/GlobalISel/LegalizerInfoTest.cpp | 14 ++++++++------
3 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
index 9472aa196f9b4..f8819d9efd833 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
@@ -374,7 +374,7 @@ LegalizeMutation changeElementCountTo(unsigned TypeIdx, unsigned FromTypeIdx);
/// Keep the same scalar or element type as \p TypeIdx, but take the number of
/// elements from \p Ty.
-LegalizeMutation changeElementCountTo(unsigned TypeIdx, LLT Ty);
+LegalizeMutation changeElementCountTo(unsigned TypeIdx, ElementCount EC);
/// Change the scalar size or element size to have the same scalar size as type
/// index \p FromIndex. Unlike changeElementTo, this discards pointer types and
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizeMutations.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizeMutations.cpp
index 25c1db91b05d8..ded4df4edc14c 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizeMutations.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizeMutations.cpp
@@ -55,12 +55,10 @@ LegalizeMutation LegalizeMutations::changeElementCountTo(unsigned TypeIdx,
}
LegalizeMutation LegalizeMutations::changeElementCountTo(unsigned TypeIdx,
- LLT NewEltTy) {
+ ElementCount EC) {
return [=](const LegalityQuery &Query) {
const LLT OldTy = Query.Types[TypeIdx];
- ElementCount NewEltCount = NewEltTy.isVector() ? NewEltTy.getElementCount()
- : ElementCount::getFixed(1);
- return std::make_pair(TypeIdx, OldTy.changeElementCount(NewEltCount));
+ return std::make_pair(TypeIdx, OldTy.changeElementCount(EC));
};
}
diff --git a/llvm/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp b/llvm/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp
index 988e307909232..836c81b524672 100644
--- a/llvm/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp
+++ b/llvm/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp
@@ -420,12 +420,14 @@ TEST(LegalizerInfoTest, RuleSets) {
// Raw type form
LI.getActionDefinitionsBuilder(G_ADD)
- .fewerElementsIf(typeIs(0, v4s32), changeElementCountTo(0, v2s32))
- .fewerElementsIf(typeIs(0, v8s32), changeElementCountTo(0, s32))
- .fewerElementsIf(typeIs(0, LLT::scalable_vector(4, 16)),
- changeElementCountTo(0, LLT::scalable_vector(2, 16)))
- .fewerElementsIf(typeIs(0, LLT::scalable_vector(8, 16)),
- changeElementCountTo(0, s16));
+ .fewerElementsIf(typeIs(0, v4s32),
+ changeElementCountTo(0, ElementCount::getFixed(2)))
+ .fewerElementsIf(typeIs(0, v8s32),
+ changeElementCountTo(0, ElementCount::getFixed(1)))
+ .fewerElementsIf(typeIs(0, LLT::scalable_vector(4, s16)),
+ changeElementCountTo(0, ElementCount::getScalable(2)))
+ .fewerElementsIf(typeIs(0, LLT::scalable_vector(8, s16)),
+ changeElementCountTo(0, ElementCount::getFixed(1)));
LegacyInfo.computeTables();
>From b85545b06a4147cc6de1f2f81817a55fa16966fa Mon Sep 17 00:00:00 2001
From: Tim Gymnich <tim at gymni.ch>
Date: Wed, 12 Feb 2025 13:27:53 +0100
Subject: [PATCH 2/5] FPInfo: LLT changes
# Conflicts:
# llvm/include/llvm/CodeGenTypes/LowLevelType.h
---
llvm/include/llvm/CodeGen/LowLevelTypeUtils.h | 2 +-
llvm/include/llvm/CodeGenTypes/LowLevelType.h | 363 +++++++++++++-----
.../CodeGen/GlobalISel/MachineIRBuilder.cpp | 3 +-
llvm/lib/CodeGen/LowLevelTypeUtils.cpp | 74 +++-
llvm/lib/CodeGen/MIRParser/MIParser.cpp | 102 +++--
llvm/lib/CodeGenTypes/LowLevelType.cpp | 60 ++-
.../GlobalISel/GlobalISelMatchTable.cpp | 105 +++--
7 files changed, 516 insertions(+), 193 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/LowLevelTypeUtils.h b/llvm/include/llvm/CodeGen/LowLevelTypeUtils.h
index 142e5cd4e7ad1..e9288ce8fdf51 100644
--- a/llvm/include/llvm/CodeGen/LowLevelTypeUtils.h
+++ b/llvm/include/llvm/CodeGen/LowLevelTypeUtils.h
@@ -40,6 +40,6 @@ LLT getLLTForMVT(MVT Ty);
/// Get the appropriate floating point arithmetic semantic based on the bit size
/// of the given scalar LLT.
const llvm::fltSemantics &getFltSemanticForLLT(LLT Ty);
-}
+} // namespace llvm
#endif // LLVM_CODEGEN_LOWLEVELTYPEUTILS_H
diff --git a/llvm/include/llvm/CodeGenTypes/LowLevelType.h b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
index 06879e1f8d15b..91ebcc89c82ff 100644
--- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h
+++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
@@ -29,6 +29,7 @@
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/CodeGenTypes/MachineValueType.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
#include <cassert>
namespace llvm {
@@ -38,68 +39,159 @@ class raw_ostream;
class LLT {
public:
+ enum class FPVariant {
+ IEEE_FLOAT = 0x0,
+ BRAIN_FLOAT = 0x1, // BRAIN_FLOAT
+ VARIANT_FLOAT_2 = 0x2, // PPC_FLOAT
+ VARIANT_FLOAT_3 = 0x3, // FP80
+ VARIANT_FLOAT_4 = 0x4, // TENSOR_FLOAT
+ VARIANT_FLOAT_5 = 0x5, // UNASSIGNED
+ VARIANT_FLOAT_6 = 0x6, // UNASSIGNED
+ VARIANT_FLOAT_7 = 0x7, // UNASSIGNED
+ };
+
+ enum class Kind : uint64_t {
+ SCALAR = 0b000,
+ INTEGER = 0b001,
+ FLOAT = 0b010,
+ POINTER = 0b011,
+ VECTOR_SCALAR = 0b100,
+ VECTOR_INTEGER = 0b101,
+ VECTOR_FLOAT = 0b110,
+ VECTOR_POINTER = 0b111,
+ };
+
+ constexpr static Kind toVector(Kind Ty) {
+ if (Ty == Kind::POINTER)
+ return Kind::VECTOR_POINTER;
+
+ if (Ty == Kind::INTEGER)
+ return Kind::VECTOR_INTEGER;
+
+ if (Ty == Kind::FLOAT)
+ return Kind::VECTOR_FLOAT;
+
+ if (Ty == Kind::SCALAR)
+ return Kind::VECTOR_SCALAR;
+
+ llvm_unreachable("Type is already a vector type");
+ }
+
+ constexpr static Kind toScalar(Kind Ty) {
+ if (Ty == Kind::VECTOR_POINTER)
+ return Kind::POINTER;
+
+ if (Ty == Kind::VECTOR_INTEGER)
+ return Kind::INTEGER;
+
+ if (Ty == Kind::VECTOR_FLOAT)
+ return Kind::FLOAT;
+
+ if (Ty == Kind::VECTOR_SCALAR)
+ return Kind::SCALAR;
+
+ llvm_unreachable("Type is already a scalar type");
+ }
+
/// Get a low-level scalar or aggregate "bag of bits".
+ // TODO: deperecate this: [[deprecated("Use LLT::integer(unsigned)
+ // instead.")]]
static constexpr LLT scalar(unsigned SizeInBits) {
- return LLT{/*isPointer=*/false, /*isVector=*/false, /*isScalar=*/true,
- ElementCount::getFixed(0), SizeInBits,
- /*AddressSpace=*/0};
+ return LLT{Kind::INTEGER, ElementCount::getFixed(0), SizeInBits,
+ /*AddressSpace=*/0, static_cast<FPVariant>(0)};
+ }
+
+ static constexpr LLT integer(unsigned SizeInBits) {
+ return LLT{Kind::INTEGER, ElementCount::getFixed(0), SizeInBits,
+ /*AddressSpace=*/0, static_cast<FPVariant>(0)};
+ }
+
+ static constexpr LLT floatingPoint(unsigned SizeInBits, FPVariant FP) {
+ return LLT{Kind::FLOAT, ElementCount::getFixed(0), SizeInBits,
+ /*AddressSpace=*/0, FP};
}
/// Get a low-level token; just a scalar with zero bits (or no size).
static constexpr LLT token() {
- return LLT{/*isPointer=*/false, /*isVector=*/false,
- /*isScalar=*/true, ElementCount::getFixed(0),
- /*SizeInBits=*/0,
- /*AddressSpace=*/0};
+ LLT Token;
+ Token.Info = Kind::INTEGER;
+ return Token;
}
/// Get a low-level pointer in the given address space.
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits) {
assert(SizeInBits > 0 && "invalid pointer size");
- return LLT{/*isPointer=*/true, /*isVector=*/false, /*isScalar=*/false,
- ElementCount::getFixed(0), SizeInBits, AddressSpace};
+ return LLT{Kind::POINTER, ElementCount::getFixed(0), SizeInBits,
+ AddressSpace, static_cast<FPVariant>(0)};
}
/// Get a low-level vector of some number of elements and element width.
+ // TODO: deprecate this: [[deprecated("Use LLT::vector(EC, LLT) instead.")]]
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits) {
assert(!EC.isScalar() && "invalid number of vector elements");
- return LLT{/*isPointer=*/false, /*isVector=*/true, /*isScalar=*/false,
- EC, ScalarSizeInBits, /*AddressSpace=*/0};
+ return LLT{Kind::VECTOR_INTEGER, EC, ScalarSizeInBits,
+ /*AddressSpace=*/0, static_cast<FPVariant>(0)};
}
/// Get a low-level vector of some number of elements and element type.
static constexpr 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,
- /*isScalar=*/false,
- EC,
- ScalarTy.getSizeInBits().getFixedValue(),
- ScalarTy.isPointer() ? ScalarTy.getAddressSpace() : 0};
+
+ Kind Info = toVector(ScalarTy.Info);
+ return LLT{Info, EC, ScalarTy.getSizeInBits().getFixedValue(),
+ ScalarTy.isPointer() ? ScalarTy.getAddressSpace() : 0,
+ ScalarTy.isFloat() ? ScalarTy.getFPVariant()
+ : static_cast<FPVariant>(0)};
+ }
+ // Get a 8-bit brain float value.
+ static constexpr LLT bfloat8() {
+ return floatingPoint(8, FPVariant::BRAIN_FLOAT);
+ }
+
+ // Get a 16-bit brain float value.
+ static constexpr LLT bfloat16() {
+ return floatingPoint(16, FPVariant::BRAIN_FLOAT);
}
/// Get a 16-bit IEEE half value.
- /// TODO: Add IEEE semantics to type - This currently returns a simple `scalar(16)`.
static constexpr LLT float16() {
- return scalar(16);
+ return floatingPoint(16, FPVariant::IEEE_FLOAT);
}
/// Get a 32-bit IEEE float value.
static constexpr LLT float32() {
- return scalar(32);
+ return floatingPoint(32, FPVariant::IEEE_FLOAT);
}
/// Get a 64-bit IEEE double value.
static constexpr LLT float64() {
- return scalar(64);
+ return floatingPoint(64, FPVariant::IEEE_FLOAT);
+ }
+
+ /// Get a 80-bit X86 floating point value.
+ static constexpr LLT x86fp80() {
+ return floatingPoint(80, FPVariant::VARIANT_FLOAT_3);
+ }
+
+ /// Get a 128-bit IEEE quad value.
+ static constexpr LLT float128() {
+ return floatingPoint(128, FPVariant::IEEE_FLOAT);
+ }
+
+ /// Get a 128-bit PowerPC double double value.
+ static constexpr LLT ppcf128() {
+ return floatingPoint(128, FPVariant::VARIANT_FLOAT_2);
}
/// Get a low-level fixed-width vector of some number of elements and element
/// width.
+ // TODO: deprecate this: [[deprecated("Use LLT::fixed_vector(unsigned, LLT)
+ // instead.")]]
static constexpr LLT fixed_vector(unsigned NumElements,
unsigned ScalarSizeInBits) {
- return vector(ElementCount::getFixed(NumElements), ScalarSizeInBits);
+ return vector(ElementCount::getFixed(NumElements),
+ LLT::integer(ScalarSizeInBits));
}
/// Get a low-level fixed-width vector of some number of elements and element
@@ -110,9 +202,12 @@ class LLT {
/// Get a low-level scalable vector of some number of elements and element
/// width.
+ // TODO: deprecate this: [[deprecated("Use LLT::scalable_vector(unsigned, LLT)
+ // instead.")]]
static constexpr LLT scalable_vector(unsigned MinNumElements,
unsigned ScalarSizeInBits) {
- return vector(ElementCount::getScalable(MinNumElements), ScalarSizeInBits);
+ return vector(ElementCount::getScalable(MinNumElements),
+ LLT::integer(ScalarSizeInBits));
}
/// Get a low-level scalable vector of some number of elements and element
@@ -125,33 +220,83 @@ class LLT {
return EC.isScalar() ? ScalarTy : LLT::vector(EC, ScalarTy);
}
+ // TODO: deprecate this: [[deprecated("Use LLT::scalarOrVector(EC, LLT)
+ // instead.")]]
static constexpr LLT scalarOrVector(ElementCount EC, uint64_t ScalarSize) {
assert(ScalarSize <= std::numeric_limits<unsigned>::max() &&
"Not enough bits in LLT to represent size");
return scalarOrVector(EC, LLT::scalar(static_cast<unsigned>(ScalarSize)));
}
- explicit constexpr LLT(bool isPointer, bool isVector, bool isScalar,
- ElementCount EC, uint64_t SizeInBits,
- unsigned AddressSpace)
+ explicit constexpr LLT(Kind Info, ElementCount EC, uint64_t SizeInBits,
+ unsigned AddressSpace, FPVariant FP)
: LLT() {
- init(isPointer, isVector, isScalar, EC, SizeInBits, AddressSpace);
+ init(Info, EC, SizeInBits, AddressSpace, FP);
}
- explicit constexpr LLT()
- : IsScalar(false), IsPointer(false), IsVector(false), RawData(0) {}
explicit LLT(MVT VT);
+ explicit constexpr LLT() : Info(static_cast<Kind>(0)), RawData(0) {}
- constexpr bool isValid() const { return IsScalar || RawData != 0; }
- constexpr bool isScalar() const { return IsScalar; }
- constexpr bool isToken() const { return IsScalar && RawData == 0; };
- constexpr bool isVector() const { return isValid() && IsVector; }
+ constexpr bool isValid() const { return isToken() || RawData != 0; }
+ constexpr bool isScalar() const {
+ return isValid() && (Info == Kind::INTEGER || Info == Kind::FLOAT || Info == Kind::SCALAR);
+ }
+ constexpr bool isScalar(unsigned Size) const {
+ return isScalar() && getScalarSizeInBits() == Size;
+ }
+ constexpr bool isFloat() const { return isValid() && Info == Kind::FLOAT; }
+ constexpr bool isFloat(unsigned Size) const {
+ return isFloat() && getScalarSizeInBits() == Size;
+ }
+ constexpr bool isVariantFloat() const {
+ return isFloat() && getFPVariant() != FPVariant::IEEE_FLOAT;
+ }
+ constexpr bool isVariantFloat(FPVariant Variant) const {
+ return isFloat() && getFPVariant() == Variant;
+ }
+ constexpr bool isVariantFloat(unsigned Size, FPVariant Variant) const {
+ return isVariantFloat(Variant) && getScalarSizeInBits() == Size;
+ }
+ constexpr bool isFloatVector() const {
+ return isVector() && Info == Kind::VECTOR_FLOAT;
+ }
+ constexpr bool isIEEEFloat(unsigned Size) const {
+ return isVariantFloat(Size, FPVariant::IEEE_FLOAT);
+ }
+ constexpr bool isBFloat(unsigned Size) const {
+ return isVariantFloat(Size, FPVariant::BRAIN_FLOAT);
+ }
+ constexpr bool isX86FP80() const {
+ return isVariantFloat(80, FPVariant::VARIANT_FLOAT_3);
+ }
+ constexpr bool isPPCF128() const {
+ return isVariantFloat(128, FPVariant::VARIANT_FLOAT_2);
+ }
+ constexpr bool isToken() const {
+ return Info == Kind::INTEGER && RawData == 0;
+ }
+ constexpr bool isInteger() const {
+ return isValid() && Info == Kind::INTEGER;
+ }
+ constexpr bool isInteger(unsigned Size) const {
+ return isInteger() && getScalarSizeInBits() == Size;
+ }
+ constexpr bool isIntegerVector() const {
+ return isVector() && Info == Kind::VECTOR_INTEGER;
+ }
+ constexpr bool isVector() const {
+ return isValid() &&
+ (Info == Kind::VECTOR_INTEGER || Info == Kind::VECTOR_FLOAT ||
+ Info == Kind::VECTOR_POINTER || Info == Kind::VECTOR_SCALAR);
+ }
constexpr bool isPointer() const {
- return isValid() && IsPointer && !IsVector;
+ return isValid() && Info == Kind::POINTER;
+ }
+ constexpr bool isPointerVector() const {
+ return isVector() && Info == Kind::VECTOR_POINTER;
}
- constexpr bool isPointerVector() const { return IsPointer && isVector(); }
constexpr bool isPointerOrPointerVector() const {
- return IsPointer && isValid();
+ return isPointer() || isPointerVector();
}
/// Returns the number of elements in a vector LLT. Must only be called on
@@ -181,7 +326,7 @@ class LLT {
constexpr bool isScalableVector() const { return isVector() && isScalable(); }
constexpr ElementCount getElementCount() const {
- assert(IsVector && "cannot get number of elements on scalar/aggregate");
+ assert(isVector() && "cannot get number of elements on scalar/aggregate");
return ElementCount::get(getFieldValue(VectorElementsFieldInfo),
isScalable());
}
@@ -206,6 +351,15 @@ class LLT {
return isVector() ? getElementType() : *this;
}
+ constexpr FPVariant getFPVariant() const {
+ assert((isFloat() || isFloatVector()) &&
+ "cannot get FP info for non float type");
+
+ return FPVariant(getFieldValue(FPFieldInfo));
+ }
+
+ constexpr Kind getKind() const { return Info; }
+
/// If this type is a vector, return a vector with the same number of elements
/// but the new element type. Otherwise, return the new element type.
constexpr LLT changeElementType(LLT NewEltTy) const {
@@ -216,10 +370,10 @@ class LLT {
/// but the new element size. Otherwise, return the new element type. Invalid
/// for pointer types. For pointer types, use changeElementType.
constexpr LLT changeElementSize(unsigned NewEltSize) const {
- assert(!isPointerOrPointerVector() &&
+ assert(!isPointerOrPointerVector() && !(isFloat() || isFloatVector()) &&
"invalid to directly change element size for pointers");
- return isVector() ? LLT::vector(getElementCount(), NewEltSize)
- : LLT::scalar(NewEltSize);
+ return isVector() ? LLT::vector(getElementCount(), LLT::integer(NewEltSize))
+ : LLT::integer(NewEltSize);
}
/// Return a vector or scalar with the same element type and the new element
@@ -228,6 +382,10 @@ class LLT {
return LLT::scalarOrVector(EC, getScalarType());
}
+ constexpr LLT changeElementCount(unsigned NumElements) const {
+ return changeElementCount(ElementCount::getFixed(NumElements));
+ }
+
/// Return a type that is \p Factor times smaller. Reduces the number of
/// elements if this is a vector, or the bitwidth for scalar/pointers. Does
/// not attempt to handle cases that aren't evenly divisible.
@@ -242,7 +400,7 @@ class LLT {
}
assert(getScalarSizeInBits() % Factor == 0);
- return scalar(getScalarSizeInBits() / Factor);
+ return integer(getScalarSizeInBits() / Factor);
}
/// Produce a vector type that is \p Factor times bigger, preserving the
@@ -276,10 +434,23 @@ class LLT {
/// Returns the vector's element type. Only valid for vector types.
constexpr LLT getElementType() const {
assert(isVector() && "cannot get element type of scalar/aggregate");
- if (IsPointer)
+ if (isPointerVector())
return pointer(getAddressSpace(), getScalarSizeInBits());
- else
- return scalar(getScalarSizeInBits());
+
+ if (isFloatVector())
+ return floatingPoint(getScalarSizeInBits(), getFPVariant());
+
+ return integer(getScalarSizeInBits());
+ }
+
+ constexpr LLT changeToInteger() const {
+ if (isPointer() || isPointerVector())
+ return *this;
+
+ if (isVector())
+ return vector(getElementCount(), LLT::integer(getScalarSizeInBits()));
+
+ return integer(getSizeInBits());
}
void print(raw_ostream &OS) const;
@@ -289,8 +460,7 @@ class LLT {
#endif
constexpr bool operator==(const LLT &RHS) const {
- return IsPointer == RHS.IsPointer && IsVector == RHS.IsVector &&
- IsScalar == RHS.IsScalar && RHS.RawData == RawData;
+ return Info == RHS.Info && RawData == RHS.RawData;
}
constexpr bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
@@ -300,37 +470,38 @@ class LLT {
private:
/// LLT is packed into 64 bits as follows:
- /// isScalar : 1
- /// isPointer : 1
- /// isVector : 1
- /// 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 different fields in the packed structure is
+ /// Info : 3
+ /// RawData : 61
+ /// with 61 bits of RawData 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 different fields in the packed structure is
/// described in static const *Field variables. Each of these variables
/// is a 2-element array, with the first element describing the bitfield size
/// and the second element describing the bitfield offset.
+ /// There are 3 special LLT instances:
+ /// - invalid: Info == SCALAR, RawData == 0
+ /// - token: Info == INTEGER, RawData == 0
+ /// - empty: Info == FLOAT, RawData == 0
+ /// - tombstone: Info == POINTER, RawData == 0
///
- /// +--------+---------+--------+----------+----------------------+
- /// |isScalar|isPointer|isVector| RawData |Notes |
- /// +--------+---------+--------+----------+----------------------+
- /// | 0 | 0 | 0 | 0 |Invalid |
- /// +--------+---------+--------+----------+----------------------+
- /// | 0 | 0 | 1 | 0 |Tombstone Key |
- /// +--------+---------+--------+----------+----------------------+
- /// | 0 | 1 | 0 | 0 |Empty Key |
- /// +--------+---------+--------+----------+----------------------+
- /// | 1 | 0 | 0 | 0 |Token |
- /// +--------+---------+--------+----------+----------------------+
- /// | 1 | 0 | 0 | non-zero |Scalar |
- /// +--------+---------+--------+----------+----------------------+
- /// | 0 | 1 | 0 | non-zero |Pointer |
- /// +--------+---------+--------+----------+----------------------+
- /// | 0 | 0 | 1 | non-zero |Vector of non-pointer |
- /// +--------+---------+--------+----------+----------------------+
- /// | 0 | 1 | 1 | non-zero |Vector of pointer |
- /// +--------+---------+--------+----------+----------------------+
- ///
- /// Everything else is reserved.
+ /*
+ --- LLT ---
+
+ 63 56 47 39 31 23 15 7 0
+ | | | | | | | | |
+ |xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|
+ ................................... (1)
+ ***************** (2)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~ (3)
+ ^^^^^^^^^^^^^^^^^ (4)
+ @ (5)
+ ### (6)
+ %%% (7)
+
+ (1) ScalarSize (2) PointerSize (3) PointerAddressSpace
+ (4) VectorElements (5) VectorScalable (6) FPVariant (7) Kind
+
+ */
typedef int BitFieldInfo[2];
///
/// This is how the bitfields are packed per Kind:
@@ -340,6 +511,7 @@ class LLT {
/// * Non-pointer scalar (isPointer == 0 && isVector == 0):
/// SizeInBits: 32;
static const constexpr BitFieldInfo ScalarSizeFieldInfo{32, 29};
+ static const constexpr BitFieldInfo FPFieldInfo{3, 21};
/// * Pointer (isPointer == 1 && isVector == 0):
/// SizeInBits: 16;
/// AddressSpace: 24;
@@ -357,9 +529,7 @@ class LLT {
/// AddressSpace: 24;
/// Scalable: 1;
- uint64_t IsScalar : 1;
- uint64_t IsPointer : 1;
- uint64_t IsVector : 1;
+ Kind Info : 3;
uint64_t RawData : 61;
static constexpr uint64_t getMask(const BitFieldInfo FieldInfo) {
@@ -380,21 +550,29 @@ class LLT {
return getMask(FieldInfo) & (RawData >> FieldInfo[1]);
}
- constexpr void init(bool IsPointer, bool IsVector, bool IsScalar,
- ElementCount EC, uint64_t SizeInBits,
- unsigned AddressSpace) {
+ constexpr void init(Kind Info, ElementCount EC, uint64_t SizeInBits,
+ unsigned AddressSpace, FPVariant FP) {
assert(SizeInBits <= std::numeric_limits<unsigned>::max() &&
"Not enough bits in LLT to represent size");
- this->IsPointer = IsPointer;
- this->IsVector = IsVector;
- this->IsScalar = IsScalar;
- if (IsPointer) {
+ // TODO: remove this eventually once LLT transition to FP types is complete
+ if (Info == Kind::INTEGER || Info == Kind::FLOAT) {
+ this->Info = Kind::SCALAR;
+ } else if (Info == Kind::VECTOR_INTEGER || Info == Kind::VECTOR_FLOAT) {
+ this->Info = Kind::VECTOR_SCALAR;
+ } else {
+ this->Info = Info;
+ }
+
+ if (Info == Kind::POINTER || Info == Kind::VECTOR_POINTER) {
RawData = maskAndShift(SizeInBits, PointerSizeFieldInfo) |
maskAndShift(AddressSpace, PointerAddressSpaceFieldInfo);
} else {
RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo);
+ // TODO: Add FPInfo: | maskAndShift((uint64_t)FP, FPFieldInfo);
}
- if (IsVector) {
+
+ if (Info == Kind::VECTOR_INTEGER || Info == Kind::VECTOR_FLOAT ||
+ Info == Kind::VECTOR_POINTER || Info == Kind::VECTOR_SCALAR) {
RawData |= maskAndShift(EC.getKnownMinValue(), VectorElementsFieldInfo) |
maskAndShift(EC.isScalable() ? 1 : 0, VectorScalableFieldInfo);
}
@@ -402,36 +580,33 @@ class LLT {
public:
constexpr uint64_t getUniqueRAWLLTData() const {
- return ((uint64_t)RawData) << 3 | ((uint64_t)IsScalar) << 2 |
- ((uint64_t)IsPointer) << 1 | ((uint64_t)IsVector);
+ return ((uint64_t)RawData) << 3 | ((uint64_t)Info);
}
};
-inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) {
+inline raw_ostream &operator<<(raw_ostream &OS, const LLT &Ty) {
Ty.print(OS);
return OS;
}
-template<> struct DenseMapInfo<LLT> {
+template <> struct DenseMapInfo<LLT> {
static inline LLT getEmptyKey() {
LLT Invalid;
- Invalid.IsPointer = true;
+ Invalid.Info = static_cast<LLT::Kind>(2);
return Invalid;
}
static inline LLT getTombstoneKey() {
LLT Invalid;
- Invalid.IsVector = true;
+ Invalid.Info = static_cast<LLT::Kind>(3);
return Invalid;
}
static inline unsigned getHashValue(const LLT &Ty) {
uint64_t Val = Ty.getUniqueRAWLLTData();
return DenseMapInfo<uint64_t>::getHashValue(Val);
}
- static bool isEqual(const LLT &LHS, const LLT &RHS) {
- return LHS == RHS;
- }
+ static bool isEqual(const LLT &LHS, const LLT &RHS) { return LHS == RHS; }
};
-}
+} // namespace llvm
#endif // LLVM_CODEGEN_LOWLEVELTYPE_H
diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index 77a1a70d976d6..cb6b342b3fe6a 100644
--- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -563,7 +563,8 @@ MachineInstrBuilder MachineIRBuilder::buildExtOrTrunc(unsigned ExtOpc,
Op.getLLTTy(*getMRI()).getSizeInBits())
Opcode = TargetOpcode::G_TRUNC;
else
- assert(Res.getLLTTy(*getMRI()) == Op.getLLTTy(*getMRI()));
+ assert(Res.getLLTTy(*getMRI()).getSizeInBits() ==
+ Op.getLLTTy(*getMRI()).getSizeInBits());
return buildInstr(Opcode, Res, Op);
}
diff --git a/llvm/lib/CodeGen/LowLevelTypeUtils.cpp b/llvm/lib/CodeGen/LowLevelTypeUtils.cpp
index 936c9fbb2fff0..51a20cbd481ed 100644
--- a/llvm/lib/CodeGen/LowLevelTypeUtils.cpp
+++ b/llvm/lib/CodeGen/LowLevelTypeUtils.cpp
@@ -36,7 +36,37 @@ LLT llvm::getLLTForType(Type &Ty, const DataLayout &DL) {
// concerned.
auto SizeInBits = DL.getTypeSizeInBits(&Ty);
assert(SizeInBits != 0 && "invalid zero-sized type");
- return LLT::scalar(SizeInBits);
+
+ if (Ty.isFloatingPointTy()) {
+ if (Ty.isHalfTy())
+ return LLT::float16();
+
+ if (Ty.isBFloatTy())
+ return LLT::bfloat16();
+
+ if (Ty.isFloatTy())
+ return LLT::float32();
+
+ if (Ty.isDoubleTy())
+ return LLT::float64();
+
+ if (Ty.isX86_FP80Ty())
+ return LLT::x86fp80();
+
+ if (Ty.isFP128Ty())
+ return LLT::float128();
+
+ if (Ty.isPPC_FP128Ty())
+ return LLT::ppcf128();
+
+ llvm_unreachable("Unhandled LLVM IR floating point type");
+ }
+
+ if (Ty.isIntegerTy()) {
+ return LLT::integer(SizeInBits);
+ }
+
+ return LLT::integer(SizeInBits);
}
if (Ty.isTokenTy())
@@ -46,12 +76,25 @@ LLT llvm::getLLTForType(Type &Ty, const DataLayout &DL) {
}
MVT llvm::getMVTForLLT(LLT Ty) {
- if (!Ty.isVector())
- return MVT::getIntegerVT(Ty.getSizeInBits());
+ if (Ty.isVector()) {
+ return MVT::getVectorVT(getMVTForLLT(Ty.getElementType()),
+ Ty.getElementCount());
+ }
+
+ if (Ty.isFloat()) {
+ if (Ty == LLT::bfloat16())
+ return MVT::bf16;
+
+ if (Ty == LLT::x86fp80())
+ return MVT::f80;
+
+ if (Ty == LLT::ppcf128())
+ return MVT::ppcf128;
+
+ return MVT::getFloatingPointVT(Ty.getSizeInBits());
+ }
- return MVT::getVectorVT(
- MVT::getIntegerVT(Ty.getElementType().getSizeInBits()),
- Ty.getElementCount());
+ return MVT::getIntegerVT(Ty.getSizeInBits());
}
EVT llvm::getApproximateEVTForLLT(LLT Ty, LLVMContext &Ctx) {
@@ -63,16 +106,21 @@ EVT llvm::getApproximateEVTForLLT(LLT Ty, LLVMContext &Ctx) {
return EVT::getIntegerVT(Ctx, Ty.getSizeInBits());
}
-LLT llvm::getLLTForMVT(MVT Ty) {
- if (!Ty.isVector())
- return LLT::scalar(Ty.getSizeInBits());
-
- return LLT::scalarOrVector(Ty.getVectorElementCount(),
- Ty.getVectorElementType().getSizeInBits());
-}
+LLT llvm::getLLTForMVT(MVT Ty) { return LLT(Ty); }
const llvm::fltSemantics &llvm::getFltSemanticForLLT(LLT Ty) {
+ // TODO: strengthen assertion by asserting isFloat().
assert(Ty.isScalar() && "Expected a scalar type.");
+
+ if (Ty.isBFloat(16))
+ return APFloat::BFloat();
+ if (Ty.isX86FP80())
+ return APFloat::x87DoubleExtended();
+ if (Ty.isPPCF128())
+ return APFloat::PPCDoubleDouble();
+
+ assert(!Ty.isVariantFloat() && "Unhandled variant float type");
+
switch (Ty.getSizeInBits()) {
case 16:
return APFloat::IEEEhalf();
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 5c8e32d11cfb0..73a1cf2ed0d55 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -1923,26 +1923,33 @@ static bool verifyAddrSpace(uint64_t AddrSpace) {
}
bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
- if (Token.range().front() == 's' || Token.range().front() == 'p') {
- StringRef SizeStr = Token.range().drop_front();
- if (SizeStr.size() == 0 || !llvm::all_of(SizeStr, isdigit))
- return error("expected integers after 's'/'p' type character");
- }
-
- if (Token.range().front() == 's') {
- auto ScalarSize = APSInt(Token.range().drop_front()).getZExtValue();
- if (ScalarSize) {
- if (!verifyScalarSize(ScalarSize))
- return error("invalid size for scalar type");
- Ty = LLT::scalar(ScalarSize);
- } else {
+ StringRef TypeDigits = Token.range();
+ if (TypeDigits.consume_front("s") || TypeDigits.consume_front("i") ||
+ TypeDigits.consume_front("f") || TypeDigits.consume_front("p") ||
+ TypeDigits.consume_front("bf")) {
+ if (TypeDigits.empty() || !llvm::all_of(TypeDigits, isdigit))
+ return error("expected integers after 's'/'i'/'f'/'bf'/'p' type identifier");
+ }
+
+ if (Token.range().starts_with("s") || Token.range().starts_with("i")) {
+ auto ScalarSize = APSInt(TypeDigits).getZExtValue();
+ if (!ScalarSize) {
Ty = LLT::token();
+ lex();
+ return false;
}
+
+ if (!verifyScalarSize(ScalarSize))
+ return error("invalid size for scalar type");
+
+ Ty = LLT::integer(ScalarSize);
lex();
return false;
- } else if (Token.range().front() == 'p') {
+ }
+
+ if (Token.range().starts_with("p")) {
const DataLayout &DL = MF.getDataLayout();
- uint64_t AS = APSInt(Token.range().drop_front()).getZExtValue();
+ uint64_t AS = APSInt(TypeDigits).getZExtValue();
if (!verifyAddrSpace(AS))
return error("invalid address space number");
@@ -1951,6 +1958,23 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
return false;
}
+ if (Token.range().starts_with("f") || Token.range().starts_with("bf")) {
+ LLT::FPVariant FPVariant;
+ if (Token.range().starts_with("f")) {
+ FPVariant = LLT::FPVariant::IEEE_FLOAT;
+ } else if (Token.range().starts_with("bf")) {
+ FPVariant = LLT::FPVariant::BRAIN_FLOAT;
+ } else {
+ return error("unknown floating point type identifier");
+ }
+ auto ScalarSize = APSInt(TypeDigits).getZExtValue();
+ if (!ScalarSize || !verifyScalarSize(ScalarSize))
+ return error("invalid size for scalar type");
+ Ty = LLT::floatingPoint(ScalarSize, FPVariant);
+ lex();
+ return false;
+ }
+
// Now we're looking for a vector.
if (Token.isNot(MIToken::less))
return error(Loc, "expected sN, pA, <M x sN>, <M x pA>, <vscale x M x sN>, "
@@ -1985,25 +2009,39 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
return GetError();
lex();
- if (Token.range().front() != 's' && Token.range().front() != 'p')
+ StringRef VectorTyDigits = Token.range();
+ if (!VectorTyDigits.consume_front("s") &&
+ !VectorTyDigits.consume_front("i") &&
+ !VectorTyDigits.consume_front("f") &&
+ !VectorTyDigits.consume_front("p") && !VectorTyDigits.consume_front("bf"))
return GetError();
- StringRef SizeStr = Token.range().drop_front();
- if (SizeStr.size() == 0 || !llvm::all_of(SizeStr, isdigit))
- return error("expected integers after 's'/'p' type character");
+ if (VectorTyDigits.empty() || !llvm::all_of(VectorTyDigits, isdigit))
+ return error(
+ "expected integers after 's'/'i'/'f'/'bf'/'p' type identifier");
- if (Token.range().front() == 's') {
- auto ScalarSize = APSInt(Token.range().drop_front()).getZExtValue();
+ if (Token.range().starts_with("s") || Token.range().starts_with("i")) {
+ auto ScalarSize = APSInt(VectorTyDigits).getZExtValue();
if (!verifyScalarSize(ScalarSize))
return error("invalid size for scalar element in vector");
- Ty = LLT::scalar(ScalarSize);
- } else if (Token.range().front() == 'p') {
+ Ty = LLT::integer(ScalarSize);
+ } else if (Token.range().starts_with("p")) {
const DataLayout &DL = MF.getDataLayout();
- uint64_t AS = APSInt(Token.range().drop_front()).getZExtValue();
+ uint64_t AS = APSInt(VectorTyDigits).getZExtValue();
if (!verifyAddrSpace(AS))
return error("invalid address space number");
Ty = LLT::pointer(AS, DL.getPointerSizeInBits(AS));
+ } else if (Token.range().starts_with("f")) {
+ auto ScalarSize = APSInt(VectorTyDigits).getZExtValue();
+ if (!verifyScalarSize(ScalarSize))
+ return error("invalid size for float element in vector");
+ Ty = LLT::floatingPoint(ScalarSize, LLT::FPVariant::IEEE_FLOAT);
+ } else if (Token.range().starts_with("bf")) {
+ auto ScalarSize = APSInt(VectorTyDigits).getZExtValue();
+ if (!verifyScalarSize(ScalarSize))
+ return error("invalid size for bfloat element in vector");
+ Ty = LLT::floatingPoint(ScalarSize, LLT::FPVariant::BRAIN_FLOAT);
} else
return GetError();
lex();
@@ -2019,14 +2057,14 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
bool MIParser::parseTypedImmediateOperand(MachineOperand &Dest) {
assert(Token.is(MIToken::Identifier));
- StringRef TypeStr = Token.range();
- if (TypeStr.front() != 'i' && TypeStr.front() != 's' &&
- TypeStr.front() != 'p')
- return error(
- "a typed immediate operand should start with one of 'i', 's', or 'p'");
- StringRef SizeStr = Token.range().drop_front();
- if (SizeStr.size() == 0 || !llvm::all_of(SizeStr, isdigit))
- return error("expected integers after 'i'/'s'/'p' type character");
+ StringRef TypeDigits = Token.range();
+ if (!TypeDigits.consume_front("i") && !TypeDigits.consume_front("s") &&
+ !TypeDigits.consume_front("p") && !TypeDigits.consume_front("f") &&
+ !TypeDigits.consume_front("bf"))
+ return error("a typed immediate operand should start with one of 'i', "
+ "'s','f','bf', or 'p'");
+ if (TypeDigits.empty() || !llvm::all_of(TypeDigits, isdigit))
+ return error("expected integers after 'i'/'s'/'f'/'bf'/'p' type identifier");
auto Loc = Token.location();
lex();
diff --git a/llvm/lib/CodeGenTypes/LowLevelType.cpp b/llvm/lib/CodeGenTypes/LowLevelType.cpp
index 4785f2652b00e..925b4efaf0edf 100644
--- a/llvm/lib/CodeGenTypes/LowLevelType.cpp
+++ b/llvm/lib/CodeGenTypes/LowLevelType.cpp
@@ -16,22 +16,45 @@
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
+static std::optional<LLT::FPVariant> deriveFPInfo(MVT VT) {
+ if (!VT.isFloatingPoint())
+ return std::nullopt;
+
+ switch (VT.getScalarType().SimpleTy) {
+ case MVT::bf16:
+ return LLT::FPVariant::BRAIN_FLOAT;
+ case MVT::f80:
+ return LLT::FPVariant::VARIANT_FLOAT_3;
+ case MVT::ppcf128:
+ return LLT::FPVariant::VARIANT_FLOAT_2;
+ default:
+ return LLT::FPVariant::IEEE_FLOAT;
+ }
+}
+
LLT::LLT(MVT VT) {
+ auto FP = deriveFPInfo(VT);
+ bool AsVector = VT.isVector() &&
+ (VT.getVectorMinNumElements() > 1 || VT.isScalableVector());
+
+ Kind Info;
+ if (FP.has_value())
+ Info = AsVector ? Kind::VECTOR_FLOAT : Kind::FLOAT;
+ else
+ Info = AsVector ? Kind::VECTOR_INTEGER : Kind::INTEGER;
+
if (VT.isVector()) {
- bool asVector = VT.getVectorMinNumElements() > 1 || VT.isScalableVector();
- init(/*IsPointer=*/false, asVector, /*IsScalar=*/!asVector,
- VT.getVectorElementCount(), VT.getVectorElementType().getSizeInBits(),
- /*AddressSpace=*/0);
+ init(Info, VT.getVectorElementCount(),
+ VT.getVectorElementType().getSizeInBits(),
+ /*AddressSpace=*/0, FP.value_or(FPVariant::IEEE_FLOAT));
} else if (VT.isValid() && !VT.isScalableTargetExtVT()) {
// Aggregates are no different from real scalars as far as GlobalISel is
// concerned.
- init(/*IsPointer=*/false, /*IsVector=*/false, /*IsScalar=*/true,
- ElementCount::getFixed(0), VT.getSizeInBits(), /*AddressSpace=*/0);
+ init(Info, ElementCount::getFixed(0), VT.getSizeInBits(),
+ /*AddressSpace=*/0, FP.value_or(FPVariant::IEEE_FLOAT));
} else {
- IsScalar = false;
- IsPointer = false;
- IsVector = false;
- RawData = 0;
+ this->Info = static_cast<Kind>(0);
+ this->RawData = 0;
}
}
@@ -39,13 +62,23 @@ void LLT::print(raw_ostream &OS) const {
if (isVector()) {
OS << "<";
OS << getElementCount() << " x " << getElementType() << ">";
- } else if (isPointer())
+ } else if (isPointer()) {
OS << "p" << getAddressSpace();
- else if (isValid()) {
+ } else if (isBFloat(16)) {
+ OS << "bf16";
+ } else if (isPPCF128()) {
+ OS << "ppcf128";
+ } else if (isFloat()) {
+ assert(!isVariantFloat() && "unknown float variant");
+ OS << "f" << getScalarSizeInBits();
+ } else if (isInteger()) {
+ OS << "i" << getScalarSizeInBits();
+ } else if (isValid()) {
assert(isScalar() && "unexpected type");
OS << "s" << getScalarSizeInBits();
- } else
+ } else {
OS << "LLT_invalid";
+ }
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
@@ -56,6 +89,7 @@ LLVM_DUMP_METHOD void LLT::dump() const {
#endif
const constexpr LLT::BitFieldInfo LLT::ScalarSizeFieldInfo;
+const constexpr LLT::BitFieldInfo LLT::FPFieldInfo;
const constexpr LLT::BitFieldInfo LLT::PointerSizeFieldInfo;
const constexpr LLT::BitFieldInfo LLT::PointerAddressSpaceFieldInfo;
const constexpr LLT::BitFieldInfo LLT::VectorElementsFieldInfo;
diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
index 4c809b4016cbd..27d16b412acdf 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
+++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
@@ -355,42 +355,99 @@ std::string LLTCodeGen::getCxxEnumValue() const {
void LLTCodeGen::emitCxxEnumValue(raw_ostream &OS) const {
if (Ty.isScalar()) {
- OS << "GILLT_s" << Ty.getSizeInBits();
+ if (Ty.isBFloat(16))
+ OS << "GILLT_bf16";
+ else if (Ty.isPPCF128())
+ OS << "GILLT_ppcf128";
+ else if (Ty.isX86FP80())
+ OS << "GILLT_x86fp80";
+ else if (Ty.isFloat())
+ OS << "GILLT_f" << Ty.getSizeInBits();
+ else if (Ty.isInteger())
+ OS << "GILLT_i" << Ty.getSizeInBits();
+ else
+ OS << "GILLT_s" << Ty.getSizeInBits();
return;
}
if (Ty.isVector()) {
OS << (Ty.isScalable() ? "GILLT_nxv" : "GILLT_v")
- << Ty.getElementCount().getKnownMinValue() << "s"
- << Ty.getScalarSizeInBits();
+ << Ty.getElementCount().getKnownMinValue();
+
+ LLT ElemTy = Ty.getElementType();
+ if (ElemTy.isBFloat(16))
+ OS << "bf16";
+ else if (ElemTy.isPPCF128())
+ OS << "ppcf128";
+ else if (ElemTy.isX86FP80())
+ OS << "x86fp80";
+ else if (ElemTy.isFloat())
+ OS << "f" << ElemTy.getSizeInBits();
+ else if (Ty.isInteger())
+ OS << "i" << ElemTy.getSizeInBits();
+ else
+ OS << "s" << ElemTy.getSizeInBits();
return;
}
+
if (Ty.isPointer()) {
OS << "GILLT_p" << Ty.getAddressSpace();
if (Ty.getSizeInBits() > 0)
OS << "s" << Ty.getSizeInBits();
return;
}
+
llvm_unreachable("Unhandled LLT");
}
void LLTCodeGen::emitCxxConstructorCall(raw_ostream &OS) const {
if (Ty.isScalar()) {
- OS << "LLT::scalar(" << Ty.getSizeInBits() << ")";
+ if (Ty.isInteger())
+ OS << "LLT::integer(" << Ty.getScalarSizeInBits() << ")";
+ else if (Ty.isBFloat(16))
+ OS << "LLT::bfloat()";
+ else if (Ty.isPPCF128())
+ OS << "LLT::ppcf128()";
+ else if (Ty.isX86FP80())
+ OS << "LLT::x86fp80()";
+ else if (Ty.isFloat())
+ OS << "LLT::floatingPoint(" << Ty.getScalarSizeInBits()
+ << ", LLT::FPVariant::IEEE_FLOAT)";
+ else
+ OS << "LLT::scalar(" << Ty.getScalarSizeInBits() << ")";
return;
}
+
if (Ty.isVector()) {
OS << "LLT::vector("
<< (Ty.isScalable() ? "ElementCount::getScalable("
: "ElementCount::getFixed(")
- << Ty.getElementCount().getKnownMinValue() << "), "
- << Ty.getScalarSizeInBits() << ")";
+ << Ty.getElementCount().getKnownMinValue() << "), ";
+
+ LLT ElemTy = Ty.getElementType();
+ if (ElemTy.isInteger())
+ OS << "LLT::integer(" << ElemTy.getScalarSizeInBits() << ")";
+ else if (ElemTy.isBFloat(16))
+ OS << "LLT::bfloat()";
+ else if (ElemTy.isPPCF128())
+ OS << "LLT::ppcf128()";
+ else if (ElemTy.isX86FP80())
+ OS << "LLT::x86fp80()";
+ else if (ElemTy.isFloat())
+ OS << "LLT::floatingPoint(" << ElemTy.getScalarSizeInBits()
+ << ", LLT::FPVariant::IEEE_FLOAT)";
+ else
+ OS << "LLT::scalar(" << ElemTy.getScalarSizeInBits() << ")";
+ OS << ")";
+
return;
}
+
if (Ty.isPointer() && Ty.getSizeInBits() > 0) {
OS << "LLT::pointer(" << Ty.getAddressSpace() << ", " << Ty.getSizeInBits()
<< ")";
return;
}
+
llvm_unreachable("Unhandled LLT");
}
@@ -398,36 +455,7 @@ void LLTCodeGen::emitCxxConstructorCall(raw_ostream &OS) const {
/// particular logic behind the order but either A < B or B < A must be
/// true if A != B.
bool LLTCodeGen::operator<(const LLTCodeGen &Other) const {
- if (Ty.isValid() != Other.Ty.isValid())
- return Ty.isValid() < Other.Ty.isValid();
- if (!Ty.isValid())
- return false;
-
- if (Ty.isVector() != Other.Ty.isVector())
- return Ty.isVector() < Other.Ty.isVector();
- if (Ty.isScalar() != Other.Ty.isScalar())
- return Ty.isScalar() < Other.Ty.isScalar();
- if (Ty.isPointer() != Other.Ty.isPointer())
- return Ty.isPointer() < Other.Ty.isPointer();
-
- if (Ty.isPointer() && Ty.getAddressSpace() != Other.Ty.getAddressSpace())
- return Ty.getAddressSpace() < Other.Ty.getAddressSpace();
-
- if (Ty.isVector() && Ty.getElementCount() != Other.Ty.getElementCount())
- return std::tuple(Ty.isScalable(),
- Ty.getElementCount().getKnownMinValue()) <
- std::tuple(Other.Ty.isScalable(),
- Other.Ty.getElementCount().getKnownMinValue());
-
- assert((!Ty.isVector() || Ty.isScalable() == Other.Ty.isScalable()) &&
- "Unexpected mismatch of scalable property");
- return Ty.isVector()
- ? std::tuple(Ty.isScalable(),
- Ty.getSizeInBits().getKnownMinValue()) <
- std::tuple(Other.Ty.isScalable(),
- Other.Ty.getSizeInBits().getKnownMinValue())
- : Ty.getSizeInBits().getFixedValue() <
- Other.Ty.getSizeInBits().getFixedValue();
+ return Ty.getUniqueRAWLLTData() < Other.Ty.getUniqueRAWLLTData();
}
//===- LLTCodeGen Helpers -------------------------------------------------===//
@@ -436,11 +464,10 @@ std::optional<LLTCodeGen> MVTToLLT(MVT::SimpleValueType SVT) {
MVT VT(SVT);
if (VT.isVector() && !VT.getVectorElementCount().isScalar())
- return LLTCodeGen(
- LLT::vector(VT.getVectorElementCount(), VT.getScalarSizeInBits()));
+ return LLTCodeGen(LLT(VT));
if (VT.isInteger() || VT.isFloatingPoint())
- return LLTCodeGen(LLT::scalar(VT.getSizeInBits()));
+ return LLTCodeGen(LLT(VT));
return std::nullopt;
}
>From 2013042c274fcc6ccbee3cb64ae27ebb11ba1079 Mon Sep 17 00:00:00 2001
From: Tim Gymnich <tim at gymni.ch>
Date: Mon, 10 Mar 2025 17:46:28 +0000
Subject: [PATCH 3/5] update tests
---
.../CodeGen/MIR/AArch64/parse-low-level-type-invalid0.mir | 2 +-
.../CodeGen/MIR/AArch64/parse-low-level-type-invalid1.mir | 2 +-
.../CodeGen/MIR/AArch64/parse-low-level-type-invalid2.mir | 2 +-
.../CodeGen/MIR/AArch64/parse-low-level-type-invalid3.mir | 2 +-
llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err10.mir | 2 +-
llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err8.mir | 2 +-
llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err9.mir | 2 +-
.../MIR/WebAssembly/typed-immediate-operand-invalid0.mir | 2 +-
.../MIR/WebAssembly/typed-immediate-operand-invalid1.mir | 4 ++--
9 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid0.mir b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid0.mir
index cece3601dc1b2..3df418f323490 100644
--- a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid0.mir
+++ b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid0.mir
@@ -5,6 +5,6 @@ name: test_low_level_type_is_single_s_p
body: |
bb.0:
liveins: $x0
- ; CHECK: [[@LINE+1]]:10: expected integers after 's'/'p' type character
+ ; CHECK: [[@LINE+1]]:10: expected integers after 's'/'i'/'f'/'bf'/'p' type identifier
%0:_(s) = COPY $x0
...
diff --git a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid1.mir b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid1.mir
index 4a7b68dab623a..69fee251be61e 100644
--- a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid1.mir
+++ b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid1.mir
@@ -6,5 +6,5 @@ body: |
bb.0:
liveins: $x0
; CHECK: [[@LINE+1]]:10: expected sN, pA, <M x sN>, <M x pA>, <vscale x M x sN>, or <vscale x M x pA> for GlobalISel type
- %0:_(i64) = COPY $x0
+ %0:_(x64) = COPY $x0
...
diff --git a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid2.mir b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid2.mir
index 1bff7a5ec9ced..6277d24aacab3 100644
--- a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid2.mir
+++ b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid2.mir
@@ -5,6 +5,6 @@ name: test_low_level_type_is_single_s_p
body: |
bb.0:
liveins: $q0
- ; CHECK: [[@LINE+1]]:15: expected integers after 's'/'p' type character
+ ; CHECK: [[@LINE+1]]:15: expected integers after 's'/'i'/'f'/'bf'/'p' type identifier
%0:_(<2 x p>) = COPY $q0
...
diff --git a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid3.mir b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid3.mir
index ebb3d37f9dfa1..0669769a36b00 100644
--- a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid3.mir
+++ b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid3.mir
@@ -6,5 +6,5 @@ body: |
bb.0:
liveins: $q0
; CHECK: [[@LINE+1]]:10: expected <M x sN> or <M x pA> for vector type
- %0:_(<2 x i64>) = COPY $q0
+ %0:_(<2 x x64>) = COPY $q0
...
diff --git a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err10.mir b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err10.mir
index 7d7d7e49f23fe..37a9a0d2c159b 100644
--- a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err10.mir
+++ b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err10.mir
@@ -7,4 +7,4 @@ body: |
%0:_(<vscale x 4 x p) = IMPLICIT_DEF
...
-# CHECK: expected integers after 's'/'p' type character
+# CHECK: expected integers after 's'/'i'/'f'/'bf'/'p' type identifier
diff --git a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err8.mir b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err8.mir
index 8bedeabaa7906..9044f77f84dc5 100644
--- a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err8.mir
+++ b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err8.mir
@@ -7,4 +7,4 @@ body: |
%0:_(<vscale x 4 x s) = IMPLICIT_DEF
...
-# CHECK: expected integers after 's'/'p' type character
+# CHECK: expected integers after 's'/'i'/'f'/'bf'/'p' type identifier
diff --git a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err9.mir b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err9.mir
index fd0b9a4a054ab..9220715320d99 100644
--- a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err9.mir
+++ b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err9.mir
@@ -6,6 +6,6 @@ body: |
%0:_(<vscale x 4 x pX) = IMPLICIT_DEF
...
-# CHECK: expected integers after 's'/'p' type character
+# CHECK: expected integers after 's'/'i'/'f'/'bf'/'p' type identifier
diff --git a/llvm/test/CodeGen/MIR/WebAssembly/typed-immediate-operand-invalid0.mir b/llvm/test/CodeGen/MIR/WebAssembly/typed-immediate-operand-invalid0.mir
index 72908711e9ee5..5b812e5ff9d73 100644
--- a/llvm/test/CodeGen/MIR/WebAssembly/typed-immediate-operand-invalid0.mir
+++ b/llvm/test/CodeGen/MIR/WebAssembly/typed-immediate-operand-invalid0.mir
@@ -7,7 +7,7 @@ liveins:
body: |
bb.0:
liveins: $arguments
- ; CHECK: [[@LINE+1]]:24: expected integers after 'i'/'s'/'p' type character
+ ; CHECK: [[@LINE+1]]:24: expected integers after 'i'/'s'/'f'/'bf'/'p' type identifier
%0:i32 = CONST_I32 i 0, implicit-def dead $arguments
RETURN implicit-def dead $arguments
...
diff --git a/llvm/test/CodeGen/MIR/WebAssembly/typed-immediate-operand-invalid1.mir b/llvm/test/CodeGen/MIR/WebAssembly/typed-immediate-operand-invalid1.mir
index f5c16b52553bf..e9708697f2dee 100644
--- a/llvm/test/CodeGen/MIR/WebAssembly/typed-immediate-operand-invalid1.mir
+++ b/llvm/test/CodeGen/MIR/WebAssembly/typed-immediate-operand-invalid1.mir
@@ -1,5 +1,5 @@
# RUN: not llc -mtriple=wasm32-unknown-unknown -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
-# When a typed immediate operand does not start with 'i', 's', or 'p'
+# When a typed immediate operand does not start with 'i', 's','f','bf', or 'p'
---
name: test_typed_immediate_operand_invalid1
liveins:
@@ -7,7 +7,7 @@ liveins:
body: |
bb.0:
liveins: $arguments
- ; CHECK: [[@LINE+1]]:24: a typed immediate operand should start with one of 'i', 's', or 'p'
+ ; CHECK: [[@LINE+1]]:24: a typed immediate operand should start with one of 'i', 's','f','bf', or 'p'
%0:i32 = CONST_I32 abc 0, implicit-def dead $arguments
RETURN implicit-def dead $arguments
...
>From 27f8aad6fc0a46fb75e4aa07efedc95a53520989 Mon Sep 17 00:00:00 2001
From: Tim Gymnich <tim at gymni.ch>
Date: Mon, 10 Mar 2025 17:54:10 +0000
Subject: [PATCH 4/5] clang format
---
llvm/include/llvm/CodeGenTypes/LowLevelType.h | 3 ++-
llvm/lib/CodeGen/MIRParser/MIParser.cpp | 6 ++++--
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/llvm/include/llvm/CodeGenTypes/LowLevelType.h b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
index 91ebcc89c82ff..27692b2c9f1b3 100644
--- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h
+++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
@@ -239,7 +239,8 @@ class LLT {
constexpr bool isValid() const { return isToken() || RawData != 0; }
constexpr bool isScalar() const {
- return isValid() && (Info == Kind::INTEGER || Info == Kind::FLOAT || Info == Kind::SCALAR);
+ return isValid() && (Info == Kind::INTEGER || Info == Kind::FLOAT ||
+ Info == Kind::SCALAR);
}
constexpr bool isScalar(unsigned Size) const {
return isScalar() && getScalarSizeInBits() == Size;
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 73a1cf2ed0d55..204388ee6232d 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -1928,7 +1928,8 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
TypeDigits.consume_front("f") || TypeDigits.consume_front("p") ||
TypeDigits.consume_front("bf")) {
if (TypeDigits.empty() || !llvm::all_of(TypeDigits, isdigit))
- return error("expected integers after 's'/'i'/'f'/'bf'/'p' type identifier");
+ return error(
+ "expected integers after 's'/'i'/'f'/'bf'/'p' type identifier");
}
if (Token.range().starts_with("s") || Token.range().starts_with("i")) {
@@ -2064,7 +2065,8 @@ bool MIParser::parseTypedImmediateOperand(MachineOperand &Dest) {
return error("a typed immediate operand should start with one of 'i', "
"'s','f','bf', or 'p'");
if (TypeDigits.empty() || !llvm::all_of(TypeDigits, isdigit))
- return error("expected integers after 'i'/'s'/'f'/'bf'/'p' type identifier");
+ return error(
+ "expected integers after 'i'/'s'/'f'/'bf'/'p' type identifier");
auto Loc = Token.location();
lex();
>From 7822a5d2c1844ea9dde1152d20b35671c774668a Mon Sep 17 00:00:00 2001
From: Tim Gymnich <tim at gymni.ch>
Date: Mon, 10 Mar 2025 18:19:45 +0000
Subject: [PATCH 5/5] add tests
---
.../AArch64/parse-low-level-type-invalid0.mir | 27 ++++++++++++++
.../AArch64/parse-low-level-type-invalid2.mir | 36 +++++++++++++++++++
.../AArch64/parse-low-level-type-invalid5.mir | 29 ++++++++++++++-
.../AArch64/parse-low-level-type-invalid6.mir | 29 ++++++++++++++-
.../AArch64/parse-low-level-type-invalid7.mir | 29 ++++++++++++++-
.../AArch64/parse-low-level-type-invalid8.mir | 29 ++++++++++++++-
6 files changed, 175 insertions(+), 4 deletions(-)
diff --git a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid0.mir b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid0.mir
index 3df418f323490..6f37e718c56df 100644
--- a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid0.mir
+++ b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid0.mir
@@ -8,3 +8,30 @@ body: |
; CHECK: [[@LINE+1]]:10: expected integers after 's'/'i'/'f'/'bf'/'p' type identifier
%0:_(s) = COPY $x0
...
+
+---
+name: test_low_level_type_is_single_i_p
+body: |
+ bb.0:
+ liveins: $x0
+ ; CHECK: [[@LINE+1]]:10: expected integers after 's'/'i'/'f'/'bf'/'p' type identifier
+ %0:_(i) = COPY $x0
+...
+
+---
+name: test_low_level_type_is_single_f_p
+body: |
+ bb.0:
+ liveins: $x0
+ ; CHECK: [[@LINE+1]]:10: expected integers after 's'/'i'/'f'/'bf'/'p' type identifier
+ %0:_(f) = COPY $x0
+...
+
+---
+name: test_low_level_type_is_single_bf_p
+body: |
+ bb.0:
+ liveins: $x0
+ ; CHECK: [[@LINE+1]]:10: expected integers after 's'/'i'/'f'/'bf'/'p' type identifier
+ %0:_(bf) = COPY $x0
+...
diff --git a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid2.mir b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid2.mir
index 6277d24aacab3..94ecb0d40ca7c 100644
--- a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid2.mir
+++ b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid2.mir
@@ -8,3 +8,39 @@ body: |
; CHECK: [[@LINE+1]]:15: expected integers after 's'/'i'/'f'/'bf'/'p' type identifier
%0:_(<2 x p>) = COPY $q0
...
+
+---
+name: test_low_level_type_is_single_s_s
+body: |
+ bb.0:
+ liveins: $q0
+ ; CHECK: [[@LINE+1]]:15: expected integers after 's'/'i'/'f'/'bf'/'p' type identifier
+ %0:_(<2 x s>) = COPY $q0
+...
+
+---
+name: test_low_level_type_is_single_s_i
+body: |
+ bb.0:
+ liveins: $q0
+ ; CHECK: [[@LINE+1]]:15: expected integers after 's'/'i'/'f'/'bf'/'p' type identifier
+ %0:_(<2 x i>) = COPY $q0
+...
+
+---
+name: test_low_level_type_is_single_s_f
+body: |
+ bb.0:
+ liveins: $q0
+ ; CHECK: [[@LINE+1]]:15: expected integers after 's'/'i'/'f'/'bf'/'p' type identifier
+ %0:_(<2 x f>) = COPY $q0
+...
+
+---
+name: test_low_level_type_is_single_s_bf
+body: |
+ bb.0:
+ liveins: $q0
+ ; CHECK: [[@LINE+1]]:15: expected integers after 's'/'i'/'f'/'bf'/'p' type identifier
+ %0:_(<2 x bf>) = COPY $q0
+...
\ No newline at end of file
diff --git a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid5.mir b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid5.mir
index 79f0d554c1251..eeae2b332f687 100644
--- a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid5.mir
+++ b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid5.mir
@@ -1,10 +1,37 @@
# RUN: not llc -mtriple=aarch64-- -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
# When a low-level type is larger than supported
---
-name: test_scalar_size_65536
+name: test_scalar_size_65536_s
body: |
bb.0:
liveins: $x0
; CHECK: [[@LINE+1]]:10: invalid size for scalar type
%0:_(s65536) = G_IMPLICIT_DEF
...
+
+---
+name: test_scalar_size_65536_i
+body: |
+ bb.0:
+ liveins: $x0
+ ; CHECK: [[@LINE+1]]:10: invalid size for scalar type
+ %0:_(s65536) = G_IMPLICIT_DEF
+...
+
+---
+name: test_scalar_size_65536_f
+body: |
+ bb.0:
+ liveins: $x0
+ ; CHECK: [[@LINE+1]]:10: invalid size for scalar type
+ %0:_(f65536) = G_IMPLICIT_DEF
+...
+
+---
+name: test_scalar_size_65536_bf
+body: |
+ bb.0:
+ liveins: $x0
+ ; CHECK: [[@LINE+1]]:10: invalid size for scalar type
+ %0:_(bf65536) = G_IMPLICIT_DEF
+...
diff --git a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid6.mir b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid6.mir
index 632e5fa81db11..0e4aade1ceb9a 100644
--- a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid6.mir
+++ b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid6.mir
@@ -1,10 +1,37 @@
# RUN: not llc -mtriple=aarch64-- -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
# When a low-level type vector has a 0-bit element
---
-name: test_vector_element_size_0
+name: test_vector_element_size_0_s
body: |
bb.0:
liveins: $x0
; CHECK: [[@LINE+1]]:15: invalid size for scalar element in vector
%0:_(<2 x s0>) = G_IMPLICIT_DEF
...
+
+---
+name: test_vector_element_size_0_s
+body: |
+ bb.0:
+ liveins: $x0
+ ; CHECK: [[@LINE+1]]:15: invalid size for scalar element in vector
+ %0:_(<2 x s0>) = G_IMPLICIT_DEF
+...
+
+---
+name: test_vector_element_size_0_f
+body: |
+ bb.0:
+ liveins: $x0
+ ; CHECK: [[@LINE+1]]:15: invalid size for scalar element in vector
+ %0:_(<2 x f0>) = G_IMPLICIT_DEF
+...
+
+---
+name: test_vector_element_size_bf
+body: |
+ bb.0:
+ liveins: $x0
+ ; CHECK: [[@LINE+1]]:15: invalid size for scalar element in vector
+ %0:_(<2 x bf0>) = G_IMPLICIT_DEF
+...
diff --git a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid7.mir b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid7.mir
index 9d074648b7ea0..aa46fe6eaab22 100644
--- a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid7.mir
+++ b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid7.mir
@@ -1,10 +1,37 @@
# RUN: not llc -mtriple=aarch64-- -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
# When a low-level type vector has 0 elements
---
-name: test_vector_0_elements
+name: test_vector_0_elements_s
body: |
bb.0:
liveins: $x0
; CHECK: [[@LINE+1]]:11: invalid number of vector elements
%0:_(<0 x s1>) = G_IMPLICIT_DEF
...
+
+---
+name: test_vector_0_elements_i
+body: |
+ bb.0:
+ liveins: $x0
+ ; CHECK: [[@LINE+1]]:11: invalid number of vector elements
+ %0:_(<0 x i1>) = G_IMPLICIT_DEF
+...
+
+---
+name: test_vector_0_elements_f
+body: |
+ bb.0:
+ liveins: $x0
+ ; CHECK: [[@LINE+1]]:11: invalid number of vector elements
+ %0:_(<0 x f32>) = G_IMPLICIT_DEF
+...
+
+---
+name: test_vector_0_elements_bf
+body: |
+ bb.0:
+ liveins: $x0
+ ; CHECK: [[@LINE+1]]:11: invalid number of vector elements
+ %0:_(<0 x bf16>) = G_IMPLICIT_DEF
+...
diff --git a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid8.mir b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid8.mir
index 1b93834404003..1a7096888b472 100644
--- a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid8.mir
+++ b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid8.mir
@@ -1,10 +1,37 @@
# RUN: not llc -mtriple=aarch64-- -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
# When a low-level type vector has more elements than supported
---
-name: test_vector_too_many_elements
+name: test_vector_too_many_elements_s
body: |
bb.0:
liveins: $x0
; CHECK: [[@LINE+1]]:11: invalid number of vector elements
%0:_(<65536 x s1>) = G_IMPLICIT_DEF
...
+
+---
+name: test_vector_too_many_elements_i
+body: |
+ bb.0:
+ liveins: $x0
+ ; CHECK: [[@LINE+1]]:11: invalid number of vector elements
+ %0:_(<65536 x i1>) = G_IMPLICIT_DEF
+...
+
+---
+name: test_vector_too_many_elements_f
+body: |
+ bb.0:
+ liveins: $x0
+ ; CHECK: [[@LINE+1]]:11: invalid number of vector elements
+ %0:_(<65536 x f32>) = G_IMPLICIT_DEF
+...
+
+---
+name: test_vector_too_many_elements_bf
+body: |
+ bb.0:
+ liveins: $x0
+ ; CHECK: [[@LINE+1]]:11: invalid number of vector elements
+ %0:_(<65536 x b16>) = G_IMPLICIT_DEF
+...
More information about the llvm-commits
mailing list