[llvm] [GlobalISel][LLT] Introduce FPInfo for LLT (Enable bfloat, ppc128float and others in GlobalISel) (PR #155107)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 3 07:39:04 PST 2026
https://github.com/DenisGZM updated https://github.com/llvm/llvm-project/pull/155107
>From 6baa709de27e3bcdf36e044b3f87b064857a83de Mon Sep 17 00:00:00 2001
From: Tim Gymnich <tim at gymni.ch>
Date: Fri, 4 Oct 2024 09:20:06 +0000
Subject: [PATCH 01/40] add isScalar and isFixedVector
---
llvm/include/llvm/CodeGenTypes/LowLevelType.h | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/llvm/include/llvm/CodeGenTypes/LowLevelType.h b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
index d8e0848aff84d..d466dccd9e8df 100644
--- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h
+++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
@@ -147,6 +147,9 @@ class LLT {
constexpr bool isScalar() const { return IsScalar; }
constexpr bool isToken() const { return IsScalar && RawData == 0; };
constexpr bool isVector() const { return isValid() && IsVector; }
+ constexpr bool isScalar(unsigned Size) const {
+ return isScalar() && getScalarSizeInBits() == Size;
+ }
constexpr bool isPointer() const {
return isValid() && IsPointer && !IsVector;
}
@@ -177,6 +180,12 @@ class LLT {
/// if the LLT is not a vector type.
constexpr bool isFixedVector() const { return isVector() && !isScalable(); }
+ constexpr bool isFixedVector(unsigned NumElements,
+ unsigned ScalarSize) const {
+ return isFixedVector() && getNumElements() == NumElements &&
+ getScalarSizeInBits() == ScalarSize;
+ }
+
/// Returns true if the LLT is a scalable vector. Returns false otherwise,
/// even if the LLT is not a vector type.
constexpr bool isScalableVector() const { return isVector() && isScalable(); }
>From cc16885507e4d578f2c7d849428066acc826e291 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 02/40] 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 fd72a3898562e..8412042a780e8 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
@@ -380,7 +380,7 @@ LLVM_ABI LegalizeMutation changeElementCountTo(unsigned TypeIdx,
/// Keep the same scalar or element type as \p TypeIdx, but take the number of
/// elements from \p Ty.
-LLVM_ABI LegalizeMutation changeElementCountTo(unsigned TypeIdx, LLT Ty);
+LLVM_ABI 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 f04aed6fb3b914a563074ebe27b6efd17d993317 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 03/40] FPInfo: LLT changes
---
llvm/include/llvm/CodeGen/LowLevelTypeUtils.h | 2 +-
llvm/include/llvm/CodeGenTypes/LowLevelType.h | 345 +++++++++++++-----
.../CodeGen/GlobalISel/MachineIRBuilder.cpp | 3 +-
llvm/lib/CodeGen/LowLevelTypeUtils.cpp | 75 +++-
llvm/lib/CodeGen/MIRParser/MIParser.cpp | 102 ++++--
llvm/lib/CodeGenTypes/LowLevelType.cpp | 60 ++-
.../GlobalISel/GlobalISelMatchTable.cpp | 101 +++--
7 files changed, 490 insertions(+), 198 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/LowLevelTypeUtils.h b/llvm/include/llvm/CodeGen/LowLevelTypeUtils.h
index 51a298eb8b247..f0c1758a4c9cc 100644
--- a/llvm/include/llvm/CodeGen/LowLevelTypeUtils.h
+++ b/llvm/include/llvm/CodeGen/LowLevelTypeUtils.h
@@ -41,6 +41,6 @@ LLVM_ABI LLT getLLTForMVT(MVT Ty);
/// Get the appropriate floating point arithmetic semantic based on the bit size
/// of the given scalar LLT.
LLVM_ABI 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 d466dccd9e8df..32572d6753c61 100644
--- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h
+++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
@@ -30,6 +30,7 @@
#include "llvm/CodeGenTypes/MachineValueType.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
#include <cassert>
namespace llvm {
@@ -39,68 +40,150 @@ 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 {
+ INVALID = 0b000,
+ INTEGER = 0b001,
+ FLOAT = 0b010,
+ POINTER = 0b011,
+ 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;
+
+ 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;
+
+ llvm_unreachable("Type is already a scalar type");
+ }
+
/// Get a low-level scalar or aggregate "bag of bits".
- static constexpr LLT scalar(unsigned SizeInBits) {
- return LLT{/*isPointer=*/false, /*isVector=*/false, /*isScalar=*/true,
- ElementCount::getFixed(0), SizeInBits,
- /*AddressSpace=*/0};
+ [[deprecated("Use LLT::integer(unsigned) instead.")]] static constexpr LLT
+ scalar(unsigned SizeInBits) {
+ 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),
+ return LLT{Kind::INTEGER, ElementCount::getFixed(0),
/*SizeInBits=*/0,
- /*AddressSpace=*/0};
+ /*AddressSpace=*/0, static_cast<FPVariant>(0)};
}
/// 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.
- static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits) {
+ [[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.
- static constexpr LLT fixed_vector(unsigned NumElements,
- unsigned ScalarSizeInBits) {
- return vector(ElementCount::getFixed(NumElements), ScalarSizeInBits);
+ [[deprecated(
+ "Use LLT::fixed_vector(unsigned, LLT) instead.")]] static constexpr LLT
+ fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits) {
+ return vector(ElementCount::getFixed(NumElements),
+ LLT::integer(ScalarSizeInBits));
}
/// Get a low-level fixed-width vector of some number of elements and element
@@ -111,9 +194,11 @@ class LLT {
/// Get a low-level scalable vector of some number of elements and element
/// width.
- static constexpr LLT scalable_vector(unsigned MinNumElements,
- unsigned ScalarSizeInBits) {
- return vector(ElementCount::getScalable(MinNumElements), ScalarSizeInBits);
+ [[deprecated(
+ "Use LLT::scalable_vector(unsigned, LLT) instead.")]] static constexpr LLT
+ scalable_vector(unsigned MinNumElements, unsigned ScalarSizeInBits) {
+ return vector(ElementCount::getScalable(MinNumElements),
+ LLT::integer(ScalarSizeInBits));
}
/// Get a low-level scalable vector of some number of elements and element
@@ -126,36 +211,81 @@ class LLT {
return EC.isScalar() ? ScalarTy : LLT::vector(EC, ScalarTy);
}
- static constexpr LLT scalarOrVector(ElementCount EC, uint64_t ScalarSize) {
+ [[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)));
+ return scalarOrVector(EC, LLT::integer(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) {}
LLVM_ABI 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 Info == Kind::INTEGER || Info == Kind::FLOAT; }
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);
+ }
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
@@ -191,7 +321,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());
}
@@ -216,6 +346,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 {
@@ -226,10 +365,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
@@ -238,6 +377,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.
@@ -252,7 +395,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
@@ -286,10 +429,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());
}
LLVM_ABI void print(raw_ostream &OS) const;
@@ -299,8 +455,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); }
@@ -310,37 +465,33 @@ 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.
///
- /// +--------+---------+--------+----------+----------------------+
- /// |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:
@@ -350,6 +501,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;
@@ -367,9 +519,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) {
@@ -390,21 +540,21 @@ 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) {
+ this->Info = Info;
+ if (Info == Kind::POINTER || Info == Kind::VECTOR_POINTER) {
RawData = maskAndShift(SizeInBits, PointerSizeFieldInfo) |
maskAndShift(AddressSpace, PointerAddressSpaceFieldInfo);
} else {
- RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo);
+ RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo) |
+ maskAndShift((uint64_t)FP, FPFieldInfo);
}
- if (IsVector) {
+
+ if (Info == Kind::VECTOR_INTEGER || Info == Kind::VECTOR_FLOAT ||
+ Info == Kind::VECTOR_POINTER) {
RawData |= maskAndShift(EC.getKnownMinValue(), VectorElementsFieldInfo) |
maskAndShift(EC.isScalable() ? 1 : 0, VectorScalableFieldInfo);
}
@@ -412,8 +562,7 @@ 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);
}
};
@@ -422,15 +571,15 @@ inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) {
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) {
@@ -442,6 +591,6 @@ template<> struct DenseMapInfo<LLT> {
}
};
-}
+} // namespace llvm
#endif // LLVM_CODEGEN_LOWLEVELTYPE_H
diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index 27df7e369436a..211809eacf4a7 100644
--- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -581,7 +581,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..cf34bf71a8c3a 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,20 @@ 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) {
- assert(Ty.isScalar() && "Expected a scalar type.");
+ assert(Ty.isFloat() && "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 6a464d9dd6886..b0cd260fadd7e 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -1929,26 +1929,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 prefix");
+ }
+
+ 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");
@@ -1957,6 +1964,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>, "
@@ -1991,25 +2015,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();
@@ -2025,14 +2063,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 character");
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 efaf05adc8f06..16a12cabce4c5 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
+++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
@@ -360,42 +360,95 @@ 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)";
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)";
+
+ OS << ")";
return;
}
+
if (Ty.isPointer() && Ty.getSizeInBits() > 0) {
OS << "LLT::pointer(" << Ty.getAddressSpace() << ", " << Ty.getSizeInBits()
<< ")";
return;
}
+
llvm_unreachable("Unhandled LLT");
}
@@ -403,36 +456,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 -------------------------------------------------===//
@@ -441,11 +465,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 79ba6eb82ba370025a4d90da8e3b4a050620e95b Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Fri, 22 Aug 2025 19:13:47 +0300
Subject: [PATCH 04/40] Return default logic for LLT::scalar. Allow target to
enable and disable extended types for llvm-ir lowering in TargetLoweringBase.
Added flag for GISel emitter to enable/disable extended types in matcher
tables
---
llvm/include/llvm/CodeGen/Analysis.h | 3 +-
llvm/include/llvm/CodeGen/LowLevelTypeUtils.h | 4 +-
llvm/include/llvm/CodeGen/TargetLowering.h | 3 +
llvm/include/llvm/CodeGenTypes/LowLevelType.h | 134 ++++++++++--------
llvm/include/llvm/Target/TargetMachine.h | 1 +
llvm/include/llvm/Target/TargetOptions.h | 7 +-
llvm/lib/CodeGen/Analysis.cpp | 10 +-
llvm/lib/CodeGen/GlobalISel/CallLowering.cpp | 13 +-
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 50 +++----
llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp | 2 +-
llvm/lib/CodeGen/LowLevelTypeUtils.cpp | 22 ++-
llvm/lib/CodeGen/MIRParser/MIParser.cpp | 23 +--
.../CodeGen/SelectionDAG/SelectionDAGISel.cpp | 4 +-
llvm/lib/CodeGen/TargetLoweringBase.cpp | 8 ++
llvm/lib/CodeGenTypes/LowLevelType.cpp | 35 +++--
llvm/lib/Support/TypeSize.cpp | 2 +-
.../AArch64/GISel/AArch64CallLowering.cpp | 4 +-
.../AArch64/GISel/AArch64RegisterBankInfo.cpp | 2 +-
llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp | 5 +-
.../Target/AMDGPU/AMDGPUCombinerHelper.cpp | 8 +-
.../lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp | 17 +--
.../GlobalISel/GlobalISelMatchTable.cpp | 46 +++++-
22 files changed, 255 insertions(+), 148 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/Analysis.h b/llvm/include/llvm/CodeGen/Analysis.h
index 98b52579d03b7..2aadc27930b7a 100644
--- a/llvm/include/llvm/CodeGen/Analysis.h
+++ b/llvm/include/llvm/CodeGen/Analysis.h
@@ -101,7 +101,8 @@ inline void ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL,
/// If Offsets is non-null, it points to a vector to be filled in
/// with the in-memory offsets of each of the individual values.
///
-void computeValueLLTs(const DataLayout &DL, Type &Ty,
+void computeValueLLTs(const TargetLowering &TLI,
+ const DataLayout &DL, Type &Ty,
SmallVectorImpl<LLT> &ValueTys,
SmallVectorImpl<uint64_t> *Offsets = nullptr,
uint64_t StartingOffset = 0);
diff --git a/llvm/include/llvm/CodeGen/LowLevelTypeUtils.h b/llvm/include/llvm/CodeGen/LowLevelTypeUtils.h
index f0c1758a4c9cc..1c8f34b1a8518 100644
--- a/llvm/include/llvm/CodeGen/LowLevelTypeUtils.h
+++ b/llvm/include/llvm/CodeGen/LowLevelTypeUtils.h
@@ -27,7 +27,7 @@ class Type;
struct fltSemantics;
/// Construct a low-level type based on an LLVM type.
-LLVM_ABI LLT getLLTForType(Type &Ty, const DataLayout &DL);
+LLVM_ABI LLT getLLTForType(Type &Ty, const DataLayout &DL, bool AllowExtendedLLT = false);
/// Get a rough equivalent of an MVT for a given LLT. MVT can't distinguish
/// pointers, so these will convert to a plain integer.
@@ -36,7 +36,7 @@ LLVM_ABI EVT getApproximateEVTForLLT(LLT Ty, LLVMContext &Ctx);
/// Get a rough equivalent of an LLT for a given MVT. LLT does not yet support
/// scalarable vector types, and will assert if used.
-LLVM_ABI LLT getLLTForMVT(MVT Ty);
+LLVM_ABI LLT getLLTForMVT(MVT Ty, bool AllowExtendedLLT = false);
/// Get the appropriate floating point arithmetic semantic based on the bit size
/// of the given scalar LLT.
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 4480ced637456..f4fdd8c69ea9e 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -416,6 +416,9 @@ class LLVM_ABI TargetLoweringBase {
/// amounts, returns MVT::i32.
EVT getShiftAmountTy(EVT LHSTy, const DataLayout &DL) const;
+ virtual LLT getLLTForType(Type &Ty, const DataLayout &DL) const;
+ virtual LLT getLLTForMVT(MVT Ty) const;
+
/// Return the preferred type to use for a shift opcode, given the shifted
/// amount type is \p ShiftValueTy.
LLVM_READONLY
diff --git a/llvm/include/llvm/CodeGenTypes/LowLevelType.h b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
index 32572d6753c61..daec87ab536c0 100644
--- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h
+++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
@@ -30,7 +30,6 @@
#include "llvm/CodeGenTypes/MachineValueType.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
#include <cassert>
namespace llvm {
@@ -52,13 +51,15 @@ class LLT {
};
enum class Kind : uint64_t {
- INVALID = 0b000,
- INTEGER = 0b001,
- FLOAT = 0b010,
- POINTER = 0b011,
- VECTOR_INTEGER = 0b101,
- VECTOR_FLOAT = 0b110,
- VECTOR_POINTER = 0b111,
+ INVALID = 0b0000,
+ ANY_SCALAR = 0b0001,
+ INTEGER = 0b0010,
+ FLOAT = 0b0011,
+ POINTER = 0b0100,
+ VECTOR_ANY = 0b0101,
+ VECTOR_INTEGER = 0b0110,
+ VECTOR_FLOAT = 0b0111,
+ VECTOR_POINTER = 0b1000,
};
constexpr static Kind toVector(Kind Ty) {
@@ -71,7 +72,7 @@ class LLT {
if (Ty == Kind::FLOAT)
return Kind::VECTOR_FLOAT;
- llvm_unreachable("Type is already a vector type");
+ return Kind::VECTOR_ANY;
}
constexpr static Kind toScalar(Kind Ty) {
@@ -84,13 +85,12 @@ class LLT {
if (Ty == Kind::VECTOR_FLOAT)
return Kind::FLOAT;
- llvm_unreachable("Type is already a scalar type");
+ return Kind::ANY_SCALAR;
}
/// Get a low-level scalar or aggregate "bag of bits".
- [[deprecated("Use LLT::integer(unsigned) instead.")]] static constexpr LLT
- scalar(unsigned SizeInBits) {
- return LLT{Kind::INTEGER, ElementCount::getFixed(0), SizeInBits,
+ static constexpr LLT scalar(unsigned SizeInBits) {
+ return LLT{Kind::ANY_SCALAR, ElementCount::getFixed(0), SizeInBits,
/*AddressSpace=*/0, static_cast<FPVariant>(0)};
}
@@ -106,7 +106,7 @@ class LLT {
/// Get a low-level token; just a scalar with zero bits (or no size).
static constexpr LLT token() {
- return LLT{Kind::INTEGER, ElementCount::getFixed(0),
+ return LLT{Kind::ANY_SCALAR, ElementCount::getFixed(0),
/*SizeInBits=*/0,
/*AddressSpace=*/0, static_cast<FPVariant>(0)};
}
@@ -119,10 +119,9 @@ class LLT {
}
/// Get a low-level vector of some number of elements and element width.
- [[deprecated("Use LLT::vector(EC, LLT) instead.")]] static constexpr LLT
- vector(ElementCount EC, unsigned ScalarSizeInBits) {
+ static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits) {
assert(!EC.isScalar() && "invalid number of vector elements");
- return LLT{Kind::VECTOR_INTEGER, EC, ScalarSizeInBits,
+ return LLT{Kind::VECTOR_ANY, EC, ScalarSizeInBits,
/*AddressSpace=*/0, static_cast<FPVariant>(0)};
}
@@ -179,11 +178,9 @@ class LLT {
/// Get a low-level fixed-width vector of some number of elements and element
/// width.
- [[deprecated(
- "Use LLT::fixed_vector(unsigned, LLT) instead.")]] static constexpr LLT
- fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits) {
+ static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits) {
return vector(ElementCount::getFixed(NumElements),
- LLT::integer(ScalarSizeInBits));
+ LLT::scalar(ScalarSizeInBits));
}
/// Get a low-level fixed-width vector of some number of elements and element
@@ -194,11 +191,9 @@ class LLT {
/// Get a low-level scalable vector of some number of elements and element
/// width.
- [[deprecated(
- "Use LLT::scalable_vector(unsigned, LLT) instead.")]] static constexpr LLT
- scalable_vector(unsigned MinNumElements, unsigned ScalarSizeInBits) {
+ static constexpr LLT scalable_vector(unsigned MinNumElements, unsigned ScalarSizeInBits) {
return vector(ElementCount::getScalable(MinNumElements),
- LLT::integer(ScalarSizeInBits));
+ LLT::scalar(ScalarSizeInBits));
}
/// Get a low-level scalable vector of some number of elements and element
@@ -211,12 +206,10 @@ class LLT {
return EC.isScalar() ? ScalarTy : LLT::vector(EC, ScalarTy);
}
- [[deprecated(
- "Use LLT::scalarOrVector(EC, LLT) instead.")]] static constexpr LLT
- scalarOrVector(ElementCount EC, uint64_t ScalarSize) {
+ 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::integer(static_cast<unsigned>(ScalarSize)));
+ return scalarOrVector(EC, LLT::scalar(static_cast<unsigned>(ScalarSize)));
}
explicit constexpr LLT(Kind Info, ElementCount EC, uint64_t SizeInBits,
@@ -225,11 +218,11 @@ class LLT {
init(Info, EC, SizeInBits, AddressSpace, FP);
}
- LLVM_ABI explicit LLT(MVT VT);
+ LLVM_ABI explicit LLT(MVT VT, bool AllowExtendedLLT = false);
explicit constexpr LLT() : Info(static_cast<Kind>(0)), RawData(0) {}
constexpr bool isValid() const { return isToken() || RawData != 0; }
- constexpr bool isScalar() const { return Info == Kind::INTEGER || Info == Kind::FLOAT; }
+ constexpr bool isScalar() const { return Info == Kind::ANY_SCALAR || Info == Kind::INTEGER || Info == Kind::FLOAT; }
constexpr bool isScalar(unsigned Size) const {
return isScalar() && getScalarSizeInBits() == Size;
}
@@ -262,7 +255,13 @@ class LLT {
return isVariantFloat(128, FPVariant::VARIANT_FLOAT_2);
}
constexpr bool isToken() const {
- return Info == Kind::INTEGER && RawData == 0;
+ return Info == Kind::ANY_SCALAR && RawData == 0;
+ }
+ constexpr bool isAnyScalar() const {
+ return isValid() && Info == Kind::ANY_SCALAR;
+ }
+ constexpr bool isVectorAny() const {
+ return isVector() && Info == Kind::VECTOR_ANY;
}
constexpr bool isInteger() const {
return isValid() && Info == Kind::INTEGER;
@@ -275,8 +274,8 @@ class LLT {
}
constexpr bool isVector() const {
return isValid() &&
- (Info == Kind::VECTOR_INTEGER || Info == Kind::VECTOR_FLOAT ||
- Info == Kind::VECTOR_POINTER);
+ (Info == Kind::VECTOR_ANY || Info == Kind::VECTOR_INTEGER||
+ Info == Kind::VECTOR_FLOAT || Info == Kind::VECTOR_POINTER);
}
constexpr bool isPointer() const {
return isValid() && Info == Kind::POINTER;
@@ -367,8 +366,12 @@ class LLT {
constexpr LLT changeElementSize(unsigned NewEltSize) const {
assert(!isPointerOrPointerVector() && !(isFloat() || isFloatVector()) &&
"invalid to directly change element size for pointers");
- return isVector() ? LLT::vector(getElementCount(), LLT::integer(NewEltSize))
- : LLT::integer(NewEltSize);
+ return isVector()
+ ? LLT::vector(getElementCount(), getElementType().isInteger()
+ ? LLT::integer(NewEltSize)
+ : LLT::scalar(NewEltSize))
+ : isInteger() ? LLT::integer(NewEltSize)
+ : LLT::scalar(NewEltSize);
}
/// Return a vector or scalar with the same element type and the new element
@@ -395,7 +398,10 @@ class LLT {
}
assert(getScalarSizeInBits() % Factor == 0);
- return integer(getScalarSizeInBits() / Factor);
+ if (isInteger())
+ return integer(getScalarSizeInBits() / Factor);
+
+ return scalar(getScalarSizeInBits() / Factor);
}
/// Produce a vector type that is \p Factor times bigger, preserving the
@@ -435,7 +441,10 @@ class LLT {
if (isFloatVector())
return floatingPoint(getScalarSizeInBits(), getFPVariant());
- return integer(getScalarSizeInBits());
+ if (isIntegerVector())
+ return integer(getScalarSizeInBits());
+
+ return scalar(getScalarSizeInBits());
}
constexpr LLT changeToInteger() const {
@@ -455,6 +464,13 @@ class LLT {
#endif
constexpr bool operator==(const LLT &RHS) const {
+ if (isAnyScalar() || RHS.isAnyScalar()) {
+ return isScalar() == RHS.isScalar() && RawData == RHS.RawData;
+ }
+ if (isVector() && RHS.isVector()) {
+ return getElementType() == RHS.getElementType() &&
+ getElementCount() == RHS.getElementCount();
+ }
return Info == RHS.Info && RawData == RHS.RawData;
}
@@ -465,8 +481,8 @@ class LLT {
private:
/// LLT is packed into 64 bits as follows:
- /// Info : 3
- /// RawData : 61
+ /// Info : 4
+ /// RawData : 60
/// 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
@@ -480,13 +496,13 @@ class LLT {
63 56 47 39 31 23 15 7 0
| | | | | | | | |
|xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|
- ................................... (1)
- ***************** (2)
- ~~~~~~~~~~~~~~~~~~~~~~~~~~ (3)
- ^^^^^^^^^^^^^^^^^ (4)
- @ (5)
+ ........ ........ ........ ........ (1)
+ ******** ******** (2)
+ ~~~~~~~~ ~~~~~~~~ ~~~~~~~~ (3)
+ ^^^^^^^^ ^^^^^^^^ (4)
+ @ (5)
### (6)
- %%% (7)
+ %%%% (7)
(1) ScalarSize (2) PointerSize (3) PointerAddressSpace
(4) VectorElements (5) VectorScalable (6) FPVariant (7) Kind
@@ -500,18 +516,20 @@ class LLT {
/// valid encodings, SizeInBits/SizeOfElement must be larger than 0.
/// * Non-pointer scalar (isPointer == 0 && isVector == 0):
/// SizeInBits: 32;
- static const constexpr BitFieldInfo ScalarSizeFieldInfo{32, 29};
- static const constexpr BitFieldInfo FPFieldInfo{3, 21};
+ /// FPInfoField: 3;
+ static const constexpr BitFieldInfo ScalarSizeFieldInfo{32, 28};
+ static const constexpr BitFieldInfo FPFieldInfo{3, 20};
/// * Pointer (isPointer == 1 && isVector == 0):
/// SizeInBits: 16;
/// AddressSpace: 24;
- static const constexpr BitFieldInfo PointerSizeFieldInfo{16, 45};
- static const constexpr BitFieldInfo PointerAddressSpaceFieldInfo{24, 21};
+ static const constexpr BitFieldInfo PointerSizeFieldInfo{16, 44};
+ static const constexpr BitFieldInfo PointerAddressSpaceFieldInfo{24, 20};
/// * Vector-of-non-pointer (isPointer == 0 && isVector == 1):
/// NumElements: 16;
/// SizeOfElement: 32;
+ /// FPInfoField: 3;
/// Scalable: 1;
- static const constexpr BitFieldInfo VectorElementsFieldInfo{16, 5};
+ static const constexpr BitFieldInfo VectorElementsFieldInfo{16, 4};
static const constexpr BitFieldInfo VectorScalableFieldInfo{1, 0};
/// * Vector-of-pointer (isPointer == 1 && isVector == 1):
/// NumElements: 16;
@@ -519,8 +537,8 @@ class LLT {
/// AddressSpace: 24;
/// Scalable: 1;
- Kind Info : 3;
- uint64_t RawData : 61;
+ Kind Info : 4;
+ uint64_t RawData : 60;
static constexpr uint64_t getMask(const BitFieldInfo FieldInfo) {
const int FieldSizeInBits = FieldInfo[0];
@@ -553,8 +571,8 @@ class LLT {
maskAndShift((uint64_t)FP, FPFieldInfo);
}
- if (Info == Kind::VECTOR_INTEGER || Info == Kind::VECTOR_FLOAT ||
- Info == Kind::VECTOR_POINTER) {
+ if (Info == Kind::VECTOR_ANY || Info == Kind::VECTOR_INTEGER ||
+ Info == Kind::VECTOR_FLOAT || Info == Kind::VECTOR_POINTER) {
RawData |= maskAndShift(EC.getKnownMinValue(), VectorElementsFieldInfo) |
maskAndShift(EC.isScalable() ? 1 : 0, VectorScalableFieldInfo);
}
@@ -562,7 +580,7 @@ class LLT {
public:
constexpr uint64_t getUniqueRAWLLTData() const {
- return ((uint64_t)RawData) << 3 | ((uint64_t)Info);
+ return ((uint64_t)RawData) << 4 | ((uint64_t)Info);
}
};
@@ -574,12 +592,12 @@ inline raw_ostream& operator<<(raw_ostream &OS, const LLT &Ty) {
template <> struct DenseMapInfo<LLT> {
static inline LLT getEmptyKey() {
LLT Invalid;
- Invalid.Info = static_cast<LLT::Kind>(2);
+ Invalid.Info = LLT::Kind::POINTER;
return Invalid;
}
static inline LLT getTombstoneKey() {
LLT Invalid;
- Invalid.Info = static_cast<LLT::Kind>(3);
+ Invalid.Info = LLT::Kind::VECTOR_ANY;
return Invalid;
}
static inline unsigned getHashValue(const LLT &Ty) {
diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h
index bf4e490554723..5671318a8586d 100644
--- a/llvm/include/llvm/Target/TargetMachine.h
+++ b/llvm/include/llvm/Target/TargetMachine.h
@@ -295,6 +295,7 @@ class LLVM_ABI TargetMachine {
bool getO0WantsFastISel() { return O0WantsFastISel; }
void setO0WantsFastISel(bool Enable) { O0WantsFastISel = Enable; }
void setGlobalISel(bool Enable) { Options.EnableGlobalISel = Enable; }
+ void setGlobalISelExtendedLLT(bool Enable) { Options.EnableGlobalISelExtendedLLT = Enable; }
void setGlobalISelAbort(GlobalISelAbortMode Mode) {
Options.GlobalISelAbort = Mode;
}
diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h
index db90f2e4cc7cc..839412cd151bf 100644
--- a/llvm/include/llvm/Target/TargetOptions.h
+++ b/llvm/include/llvm/Target/TargetOptions.h
@@ -123,7 +123,8 @@ class TargetOptions {
ApproxFuncFPMath(false), EnableAIXExtendedAltivecABI(false),
HonorSignDependentRoundingFPMathOption(false), NoZerosInBSS(false),
GuaranteedTailCallOpt(false), StackSymbolOrdering(true),
- EnableFastISel(false), EnableGlobalISel(false), UseInitArray(false),
+ EnableFastISel(false), EnableGlobalISel(false),
+ EnableGlobalISelExtendedLLT(false), UseInitArray(false),
DisableIntegratedAS(false), FunctionSections(false),
DataSections(false), IgnoreXCOFFVisibility(false),
XCOFFTracebackTable(true), UniqueSectionNames(true),
@@ -235,6 +236,10 @@ class TargetOptions {
/// EnableGlobalISel - This flag enables global instruction selection.
unsigned EnableGlobalISel : 1;
+ /// EnableGlobalISelExtendedLLT - This flag enables LLTs with extenden type info
+ /// so target may distinguish different formats of equal sized scalars.
+ unsigned EnableGlobalISelExtendedLLT : 1;
+
/// EnableGlobalISelAbort - Control abort behaviour when global instruction
/// selection fails to lower/select an instruction.
GlobalISelAbortMode GlobalISelAbort = GlobalISelAbortMode::Enable;
diff --git a/llvm/lib/CodeGen/Analysis.cpp b/llvm/lib/CodeGen/Analysis.cpp
index 2ef96cc4400f7..61d509db7f14a 100644
--- a/llvm/lib/CodeGen/Analysis.cpp
+++ b/llvm/lib/CodeGen/Analysis.cpp
@@ -146,8 +146,8 @@ void llvm::ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL,
}
}
-void llvm::computeValueLLTs(const DataLayout &DL, Type &Ty,
- SmallVectorImpl<LLT> &ValueTys,
+void llvm::computeValueLLTs(const TargetLowering &TLI, const DataLayout &DL,
+ Type &Ty, SmallVectorImpl<LLT> &ValueTys,
SmallVectorImpl<uint64_t> *Offsets,
uint64_t StartingOffset) {
// Given a struct type, recursively traverse the elements.
@@ -158,7 +158,7 @@ void llvm::computeValueLLTs(const DataLayout &DL, Type &Ty,
const StructLayout *SL = Offsets ? DL.getStructLayout(STy) : nullptr;
for (unsigned I = 0, E = STy->getNumElements(); I != E; ++I) {
uint64_t EltOffset = SL ? SL->getElementOffset(I) : 0;
- computeValueLLTs(DL, *STy->getElementType(I), ValueTys, Offsets,
+ computeValueLLTs(TLI, DL, *STy->getElementType(I), ValueTys, Offsets,
StartingOffset + EltOffset);
}
return;
@@ -168,7 +168,7 @@ void llvm::computeValueLLTs(const DataLayout &DL, Type &Ty,
Type *EltTy = ATy->getElementType();
uint64_t EltSize = DL.getTypeAllocSize(EltTy).getFixedValue();
for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i)
- computeValueLLTs(DL, *EltTy, ValueTys, Offsets,
+ computeValueLLTs(TLI, DL, *EltTy, ValueTys, Offsets,
StartingOffset + i * EltSize);
return;
}
@@ -176,7 +176,7 @@ void llvm::computeValueLLTs(const DataLayout &DL, Type &Ty,
if (Ty.isVoidTy())
return;
// Base case: we can get an LLT for this LLVM IR type.
- ValueTys.push_back(getLLTForType(Ty, DL));
+ ValueTys.push_back(TLI.getLLTForType(Ty, DL));
if (Offsets != nullptr)
Offsets->push_back(StartingOffset * 8);
}
diff --git a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
index 90a18b86c1b1f..41609dae1b156 100644
--- a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
@@ -159,7 +159,7 @@ bool CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, const CallBase &CB,
if (const Function *F = dyn_cast<Function>(CalleeV)) {
if (F->hasFnAttribute(Attribute::NonLazyBind)) {
- LLT Ty = getLLTForType(*F->getType(), DL);
+ LLT Ty = TLI->getLLTForType(*F->getType(), DL);
Register Reg = MIRBuilder.buildGlobalValue(Ty, F).getReg(0);
Info.Callee = MachineOperand::CreateReg(Reg, false);
} else {
@@ -781,11 +781,11 @@ bool CallLowering::handleAssignments(ValueHandler &Handler,
const MVT ValVT = VA.getValVT();
const MVT LocVT = VA.getLocVT();
- const LLT LocTy(LocVT);
- const LLT ValTy(ValVT);
+ const LLT LocTy = TLI->getLLTForMVT(LocVT);
+ const LLT ValTy = TLI->getLLTForMVT(ValVT);
const LLT NewLLT = Handler.isIncomingArgumentHandler() ? LocTy : ValTy;
const EVT OrigVT = EVT::getEVT(Args[i].Ty);
- const LLT OrigTy = getLLTForType(*Args[i].Ty, DL);
+ const LLT OrigTy = TLI->getLLTForType(*Args[i].Ty, DL);
const LLT PointerTy = LLT::pointer(
AllocaAddressSpace, DL.getPointerSizeInBits(AllocaAddressSpace));
@@ -1004,7 +1004,7 @@ void CallLowering::insertSRetLoads(MachineIRBuilder &MIRBuilder, Type *RetTy,
Align BaseAlign = DL.getPrefTypeAlign(RetTy);
Type *RetPtrTy =
PointerType::get(RetTy->getContext(), DL.getAllocaAddrSpace());
- LLT OffsetLLTy = getLLTForType(*DL.getIndexType(RetPtrTy), DL);
+ LLT OffsetLLTy = TLI->getLLTForType(*DL.getIndexType(RetPtrTy), DL);
MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(MF, FI);
@@ -1035,7 +1035,8 @@ void CallLowering::insertSRetStores(MachineIRBuilder &MIRBuilder, Type *RetTy,
unsigned NumValues = SplitVTs.size();
Align BaseAlign = DL.getPrefTypeAlign(RetTy);
unsigned AS = DL.getAllocaAddrSpace();
- LLT OffsetLLTy = getLLTForType(*DL.getIndexType(RetTy->getContext(), AS), DL);
+ LLT OffsetLLTy =
+ TLI->getLLTForType(*DL.getIndexType(RetTy->getContext(), AS), DL);
MachinePointerInfo PtrInfo(AS);
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 8424a8108d76e..4484a0769ad2a 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -193,7 +193,7 @@ IRTranslator::allocateVRegs(const Value &Val) {
auto *Regs = VMap.getVRegs(Val);
auto *Offsets = VMap.getOffsets(Val);
SmallVector<LLT, 4> SplitTys;
- computeValueLLTs(*DL, *Val.getType(), SplitTys,
+ computeValueLLTs(*TLI, *DL, *Val.getType(), SplitTys,
Offsets->empty() ? Offsets : nullptr);
for (unsigned i = 0; i < SplitTys.size(); ++i)
Regs->push_back(0);
@@ -217,7 +217,7 @@ ArrayRef<Register> IRTranslator::getOrCreateVRegs(const Value &Val) {
"Don't know how to create an empty vreg");
SmallVector<LLT, 4> SplitTys;
- computeValueLLTs(*DL, *Val.getType(), SplitTys,
+ computeValueLLTs(*TLI, *DL, *Val.getType(), SplitTys,
Offsets->empty() ? Offsets : nullptr);
if (!isa<Constant>(Val)) {
@@ -858,7 +858,7 @@ void IRTranslator::emitJumpTable(SwitchCG::JumpTable &JT,
MIB.setDebugLoc(CurBuilder->getDebugLoc());
Type *PtrIRTy = PointerType::getUnqual(MF->getFunction().getContext());
- const LLT PtrTy = getLLTForType(*PtrIRTy, *DL);
+ const LLT PtrTy = TLI->getLLTForType(*PtrIRTy, *DL);
auto Table = MIB.buildJumpTable(PtrTy, JT.JTI);
MIB.buildBrJT(Table.getReg(0), JT.JTI, JT.Reg);
@@ -873,7 +873,7 @@ bool IRTranslator::emitJumpTableHeader(SwitchCG::JumpTable &JT,
const Value &SValue = *JTH.SValue;
// Subtract the lowest switch case value from the value being switched on.
- const LLT SwitchTy = getLLTForType(*SValue.getType(), *DL);
+ const LLT SwitchTy = TLI->getLLTForType(*SValue.getType(), *DL);
Register SwitchOpReg = getOrCreateVReg(SValue);
auto FirstCst = MIB.buildConstant(SwitchTy, JTH.First);
auto Sub = MIB.buildSub({SwitchTy}, SwitchOpReg, FirstCst);
@@ -1106,7 +1106,7 @@ void IRTranslator::emitBitTestHeader(SwitchCG::BitTestBlock &B,
auto RangeSub = MIB.buildSub(SwitchOpTy, SwitchOpReg, MinValReg);
Type *PtrIRTy = PointerType::getUnqual(MF->getFunction().getContext());
- const LLT PtrTy = getLLTForType(*PtrIRTy, *DL);
+ const LLT PtrTy = TLI->getLLTForType(*PtrIRTy, *DL);
LLT MaskTy = SwitchOpTy;
if (MaskTy.getSizeInBits() > PtrTy.getSizeInBits() ||
@@ -1159,7 +1159,7 @@ void IRTranslator::emitBitTestCase(SwitchCG::BitTestBlock &BB,
MachineIRBuilder &MIB = *CurBuilder;
MIB.setMBB(*SwitchBB);
- LLT SwitchTy = getLLTForMVT(BB.RegVT);
+ LLT SwitchTy = TLI->getLLTForMVT(BB.RegVT);
Register Cmp;
unsigned PopCount = llvm::popcount(B.Mask);
if (PopCount == 1) {
@@ -1386,7 +1386,7 @@ bool IRTranslator::translateLoad(const User &U, MachineIRBuilder &MIRBuilder) {
const Value *Ptr = LI.getPointerOperand();
Type *OffsetIRTy = DL->getIndexType(Ptr->getType());
- LLT OffsetTy = getLLTForType(*OffsetIRTy, *DL);
+ LLT OffsetTy = TLI->getLLTForType(*OffsetIRTy, *DL);
if (CLI->supportSwiftError() && isSwiftError(Ptr)) {
assert(Regs.size() == 1 && "swifterror should be single pointer");
@@ -1433,7 +1433,7 @@ bool IRTranslator::translateStore(const User &U, MachineIRBuilder &MIRBuilder) {
Register Base = getOrCreateVReg(*SI.getPointerOperand());
Type *OffsetIRTy = DL->getIndexType(SI.getPointerOperandType());
- LLT OffsetTy = getLLTForType(*OffsetIRTy, *DL);
+ LLT OffsetTy = TLI->getLLTForType(*OffsetIRTy, *DL);
if (CLI->supportSwiftError() && isSwiftError(SI.getPointerOperand())) {
assert(Vals.size() == 1 && "swifterror should be single pointer");
@@ -1555,8 +1555,8 @@ bool IRTranslator::translateCopy(const User &U, const Value &V,
bool IRTranslator::translateBitCast(const User &U,
MachineIRBuilder &MIRBuilder) {
// If we're bitcasting to the source type, we can reuse the source vreg.
- if (getLLTForType(*U.getOperand(0)->getType(), *DL) ==
- getLLTForType(*U.getType(), *DL)) {
+ if (TLI->getLLTForType(*U.getOperand(0)->getType(), *DL) ==
+ TLI->getLLTForType(*U.getType(), *DL)) {
// If the source is a ConstantInt then it was probably created by
// ConstantHoisting and we should leave it alone.
if (isa<ConstantInt>(U.getOperand(0)))
@@ -1588,9 +1588,9 @@ bool IRTranslator::translateGetElementPtr(const User &U,
Value &Op0 = *U.getOperand(0);
Register BaseReg = getOrCreateVReg(Op0);
Type *PtrIRTy = Op0.getType();
- LLT PtrTy = getLLTForType(*PtrIRTy, *DL);
+ LLT PtrTy = TLI->getLLTForType(*PtrIRTy, *DL);
Type *OffsetIRTy = DL->getIndexType(PtrIRTy);
- LLT OffsetTy = getLLTForType(*OffsetIRTy, *DL);
+ LLT OffsetTy = TLI->getLLTForType(*OffsetIRTy, *DL);
uint32_t PtrAddFlags = 0;
// Each PtrAdd generated to implement the GEP inherits its nuw, nusw, inbounds
@@ -1627,9 +1627,9 @@ bool IRTranslator::translateGetElementPtr(const User &U,
BaseReg)
.getReg(0);
PtrIRTy = FixedVectorType::get(PtrIRTy, VectorWidth);
- PtrTy = getLLTForType(*PtrIRTy, *DL);
+ PtrTy = TLI->getLLTForType(*PtrIRTy, *DL);
OffsetIRTy = DL->getIndexType(PtrIRTy);
- OffsetTy = getLLTForType(*OffsetIRTy, *DL);
+ OffsetTy = TLI->getLLTForType(*OffsetIRTy, *DL);
}
int64_t Offset = 0;
@@ -1679,7 +1679,7 @@ bool IRTranslator::translateGetElementPtr(const User &U,
Register GepOffsetReg;
if (ElementSize != 1) {
auto ElementSizeMIB = MIRBuilder.buildConstant(
- getLLTForType(*OffsetIRTy, *DL), ElementSize);
+ TLI->getLLTForType(*OffsetIRTy, *DL), ElementSize);
// The multiplication is NUW if the GEP is NUW and NSW if the GEP is
// NUSW.
@@ -2336,7 +2336,7 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
MIRBuilder.buildFMA(Dst, Op0, Op1, Op2,
MachineInstr::copyFlagsFromInstruction(CI));
} else {
- LLT Ty = getLLTForType(*CI.getType(), *DL);
+ LLT Ty = TLI->getLLTForType(*CI.getType(), *DL);
auto FMul = MIRBuilder.buildFMul(
Ty, Op0, Op1, MachineInstr::copyFlagsFromInstruction(CI));
MIRBuilder.buildFAdd(Dst, FMul, Op2,
@@ -2403,7 +2403,7 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
getStackGuard(getOrCreateVReg(CI), MIRBuilder);
return true;
case Intrinsic::stackprotector: {
- LLT PtrTy = getLLTForType(*CI.getArgOperand(0)->getType(), *DL);
+ LLT PtrTy = TLI->getLLTForType(*CI.getArgOperand(0)->getType(), *DL);
Register GuardVal;
if (TLI->useLoadStackGuardNode(*CI.getModule())) {
GuardVal = MRI->createGenericVirtualRegister(PtrTy);
@@ -2650,7 +2650,7 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
case Intrinsic::vector_deinterleave2: {
// Both intrinsics have at least one operand.
Value *Op0 = CI.getOperand(0);
- LLT ResTy = getLLTForType(*Op0->getType(), MIRBuilder.getDataLayout());
+ LLT ResTy = TLI->getLLTForType(*Op0->getType(), MIRBuilder.getDataLayout());
if (!ResTy.isFixedVector())
return false;
@@ -2700,7 +2700,7 @@ bool IRTranslator::translateCallBase(const CallBase &CB,
for (const auto &Arg : CB.args()) {
if (CLI->supportSwiftError() && isSwiftError(Arg)) {
assert(SwiftInVReg == 0 && "Expected only one swift error argument");
- LLT Ty = getLLTForType(*Arg->getType(), *DL);
+ LLT Ty = TLI->getLLTForType(*Arg->getType(), *DL);
SwiftInVReg = MRI->createGenericVirtualRegister(Ty);
MIRBuilder.buildCopy(SwiftInVReg, SwiftError.getOrCreateVRegUseAt(
&CB, &MIRBuilder.getMBB(), Arg));
@@ -2852,7 +2852,7 @@ bool IRTranslator::translateCall(const User &U, MachineIRBuilder &MIRBuilder) {
Align Alignment = Info.align.value_or(
DL->getABITypeAlign(Info.memVT.getTypeForEVT(F->getContext())));
LLT MemTy = Info.memVT.isSimple()
- ? getLLTForMVT(Info.memVT.getSimpleVT())
+ ? TLI->getLLTForMVT(Info.memVT.getSimpleVT())
: LLT::scalar(Info.memVT.getStoreSizeInBits());
// TODO: We currently just fallback to address space 0 if getTgtMemIntrinsic
@@ -3060,13 +3060,13 @@ bool IRTranslator::translateLandingPad(const User &U,
if (auto *RegMask = TRI.getCustomEHPadPreservedMask(*MF))
MF->getRegInfo().addPhysRegsUsedFromRegMask(RegMask);
- LLT Ty = getLLTForType(*LP.getType(), *DL);
+ LLT Ty = TLI->getLLTForType(*LP.getType(), *DL);
Register Undef = MRI->createGenericVirtualRegister(Ty);
MIRBuilder.buildUndef(Undef);
SmallVector<LLT, 2> Tys;
for (Type *Ty : cast<StructType>(LP.getType())->elements())
- Tys.push_back(getLLTForType(*Ty, *DL));
+ Tys.push_back(TLI->getLLTForType(*Ty, *DL));
assert(Tys.size() == 2 && "Only two-valued landingpads are supported");
// Mark exception register as live in.
@@ -3111,7 +3111,7 @@ bool IRTranslator::translateAlloca(const User &U,
// Now we're in the harder dynamic case.
Register NumElts = getOrCreateVReg(*AI.getArraySize());
Type *IntPtrIRTy = DL->getIntPtrType(AI.getType());
- LLT IntPtrTy = getLLTForType(*IntPtrIRTy, *DL);
+ LLT IntPtrTy = TLI->getLLTForType(*IntPtrIRTy, *DL);
if (MRI->getType(NumElts) != IntPtrTy) {
Register ExtElts = MRI->createGenericVirtualRegister(IntPtrTy);
MIRBuilder.buildZExtOrTrunc(ExtElts, NumElts);
@@ -3854,8 +3854,8 @@ bool IRTranslator::emitSPDescriptorParent(StackProtectorDescriptor &SPD,
CurBuilder->setInsertPt(*ParentBB, ParentBB->end());
// First create the loads to the guard/stack slot for the comparison.
Type *PtrIRTy = PointerType::getUnqual(MF->getFunction().getContext());
- const LLT PtrTy = getLLTForType(*PtrIRTy, *DL);
- LLT PtrMemTy = getLLTForMVT(TLI->getPointerMemTy(*DL));
+ const LLT PtrTy = TLI->getLLTForType(*PtrIRTy, *DL);
+ LLT PtrMemTy = TLI->getLLTForMVT(TLI->getPointerMemTy(*DL));
MachineFrameInfo &MFI = ParentBB->getParent()->getFrameInfo();
int FI = MFI.getStackProtectorIndex();
diff --git a/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp b/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp
index b2f84351c9a95..b1e134ce5ef9e 100644
--- a/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp
@@ -952,7 +952,7 @@ void LoadStoreOpt::initializeStoreMergeTargetInfo(unsigned AddrSpace) {
const auto &LI = *MF->getSubtarget().getLegalizerInfo();
const auto &DL = MF->getFunction().getDataLayout();
Type *IRPtrTy = PointerType::get(MF->getFunction().getContext(), AddrSpace);
- LLT PtrTy = getLLTForType(*IRPtrTy, DL);
+ LLT PtrTy = TLI->getLLTForType(*IRPtrTy, DL);
// We assume that we're not going to be generating any stores wider than
// MaxStoreSizeToForm bits for now.
for (unsigned Size = 2; Size <= MaxStoreSizeToForm; Size *= 2) {
diff --git a/llvm/lib/CodeGen/LowLevelTypeUtils.cpp b/llvm/lib/CodeGen/LowLevelTypeUtils.cpp
index cf34bf71a8c3a..6a15b1748630d 100644
--- a/llvm/lib/CodeGen/LowLevelTypeUtils.cpp
+++ b/llvm/lib/CodeGen/LowLevelTypeUtils.cpp
@@ -17,16 +17,16 @@
#include "llvm/IR/DerivedTypes.h"
using namespace llvm;
-LLT llvm::getLLTForType(Type &Ty, const DataLayout &DL) {
- if (auto VTy = dyn_cast<VectorType>(&Ty)) {
+LLT llvm::getLLTForType(Type &Ty, const DataLayout &DL, bool AllowExtendedLLT) {
+ if (auto *VTy = dyn_cast<VectorType>(&Ty)) {
auto EC = VTy->getElementCount();
- LLT ScalarTy = getLLTForType(*VTy->getElementType(), DL);
+ LLT ScalarTy = getLLTForType(*VTy->getElementType(), DL, AllowExtendedLLT);
if (EC.isScalar())
return ScalarTy;
return LLT::vector(EC, ScalarTy);
}
- if (auto PTy = dyn_cast<PointerType>(&Ty)) {
+ if (auto *PTy = dyn_cast<PointerType>(&Ty)) {
unsigned AddrSpace = PTy->getAddressSpace();
return LLT::pointer(AddrSpace, DL.getPointerSizeInBits(AddrSpace));
}
@@ -37,6 +37,11 @@ LLT llvm::getLLTForType(Type &Ty, const DataLayout &DL) {
auto SizeInBits = DL.getTypeSizeInBits(&Ty);
assert(SizeInBits != 0 && "invalid zero-sized type");
+ // Return simple scalar
+ if (!AllowExtendedLLT)
+ return LLT::scalar(SizeInBits);
+
+ // Choose more precise LLT variant
if (Ty.isFloatingPointTy()) {
if (Ty.isHalfTy())
return LLT::float16();
@@ -66,7 +71,7 @@ LLT llvm::getLLTForType(Type &Ty, const DataLayout &DL) {
return LLT::integer(SizeInBits);
}
- return LLT::integer(SizeInBits);
+ return LLT::scalar(SizeInBits);
}
if (Ty.isTokenTy())
@@ -106,10 +111,13 @@ EVT llvm::getApproximateEVTForLLT(LLT Ty, LLVMContext &Ctx) {
return EVT::getIntegerVT(Ctx, Ty.getSizeInBits());
}
-LLT llvm::getLLTForMVT(MVT Ty) { return LLT(Ty); }
+LLT llvm::getLLTForMVT(MVT VT, bool AllowExtendedLLT) {
+ return LLT(VT, AllowExtendedLLT);
+}
const llvm::fltSemantics &llvm::getFltSemanticForLLT(LLT Ty) {
- assert(Ty.isFloat() && "Expected a scalar type.");
+ assert((Ty.isAnyScalar() || Ty.isFloat()) &&
+ "Expected a any scalar or float type.");
if (Ty.isBFloat(16))
return APFloat::BFloat();
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index b0cd260fadd7e..699f4d3529b6e 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -1934,10 +1934,11 @@ 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 prefix");
+ return error("expected integers after 's'/'i'/'f'/'bf'/'p' type identifier");
}
if (Token.range().starts_with("s") || Token.range().starts_with("i")) {
+ bool ScalarOrInt = Token.range().starts_with("s");
auto ScalarSize = APSInt(TypeDigits).getZExtValue();
if (!ScalarSize) {
Ty = LLT::token();
@@ -1948,7 +1949,7 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
if (!verifyScalarSize(ScalarSize))
return error("invalid size for scalar type");
- Ty = LLT::integer(ScalarSize);
+ Ty = ScalarOrInt ? LLT::scalar(ScalarSize) : LLT::integer(ScalarSize);
lex();
return false;
}
@@ -1983,8 +1984,9 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
// 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>, "
- "or <vscale x M x pA> for GlobalISel type");
+ return error(Loc, "expected tN, pA, <M x tN>, <M x pA>, <vscale x M x tN>, "
+ "or <vscale x M x pA> for GlobalISel type, "
+ "where t = {'s', 'i', 'f', 'bf'}");
lex();
bool HasVScale =
@@ -1992,15 +1994,15 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
if (HasVScale) {
lex();
if (Token.isNot(MIToken::Identifier) || Token.stringValue() != "x")
- return error("expected <vscale x M x sN> or <vscale x M x pA>");
+ return error("expected <vscale x M x tN>, where t = {'s', 'i', 'f', 'bf', 'p'}");
lex();
}
auto GetError = [this, &HasVScale, Loc]() {
if (HasVScale)
return error(
- Loc, "expected <vscale x M x sN> or <vscale M x pA> for vector type");
- return error(Loc, "expected <M x sN> or <M x pA> for vector type");
+ Loc, "expected <vscale x M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}");
+ return error(Loc, "expected <M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}");
};
if (Token.isNot(MIToken::IntegerLiteral))
@@ -2027,10 +2029,11 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
"expected integers after 's'/'i'/'f'/'bf'/'p' type identifier");
if (Token.range().starts_with("s") || Token.range().starts_with("i")) {
+ bool ScalarOrInt = Token.range().starts_with("s");
auto ScalarSize = APSInt(VectorTyDigits).getZExtValue();
if (!verifyScalarSize(ScalarSize))
return error("invalid size for scalar element in vector");
- Ty = LLT::integer(ScalarSize);
+ Ty = ScalarOrInt ? LLT::scalar(ScalarSize) : LLT::integer(ScalarSize);
} else if (Token.range().starts_with("p")) {
const DataLayout &DL = MF.getDataLayout();
uint64_t AS = APSInt(VectorTyDigits).getZExtValue();
@@ -2068,9 +2071,9 @@ bool MIParser::parseTypedImmediateOperand(MachineOperand &Dest) {
!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'");
+ "'s', 'f', 'bf', or 'p'");
if (TypeDigits.empty() || !llvm::all_of(TypeDigits, isdigit))
- return error("expected integers after 'i'/'s'/'f'/'bf'/'p' type character");
+ return error("expected integers after 'i'/'s'/'f'/'bf'/'p' type identifier");
auto Loc = Token.location();
lex();
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index ece50ed95fc49..ca75c42ee0a72 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -2457,7 +2457,7 @@ void SelectionDAGISel::Select_READ_REGISTER(SDNode *Op) {
const MDString *RegStr = cast<MDString>(MD->getMD()->getOperand(0));
EVT VT = Op->getValueType(0);
- LLT Ty = VT.isSimple() ? getLLTForMVT(VT.getSimpleVT()) : LLT();
+ LLT Ty = VT.isSimple() ? TLI->getLLTForMVT(VT.getSimpleVT()) : LLT();
const MachineFunction &MF = CurDAG->getMachineFunction();
Register Reg = TLI->getRegisterByName(RegStr->getString().data(), Ty, MF);
@@ -2488,7 +2488,7 @@ void SelectionDAGISel::Select_WRITE_REGISTER(SDNode *Op) {
const MDString *RegStr = cast<MDString>(MD->getMD()->getOperand(0));
EVT VT = Op->getOperand(2).getValueType();
- LLT Ty = VT.isSimple() ? getLLTForMVT(VT.getSimpleVT()) : LLT();
+ LLT Ty = VT.isSimple() ? TLI->getLLTForMVT(VT.getSimpleVT()) : LLT();
const MachineFunction &MF = CurDAG->getMachineFunction();
Register Reg = TLI->getRegisterByName(RegStr->getString().data(), Ty, MF);
diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp
index 350948a92a3ae..ee95f9ea05c02 100644
--- a/llvm/lib/CodeGen/TargetLoweringBase.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp
@@ -978,6 +978,14 @@ EVT TargetLoweringBase::getShiftAmountTy(EVT LHSTy,
return ShiftVT;
}
+LLT TargetLoweringBase::getLLTForType(Type &Ty, const DataLayout &DL) const {
+ return llvm::getLLTForType(Ty, DL, TM.Options.EnableGlobalISelExtendedLLT);
+}
+
+LLT TargetLoweringBase::getLLTForMVT(MVT Ty) const {
+ return llvm::getLLTForMVT(Ty, TM.Options.EnableGlobalISelExtendedLLT);
+}
+
bool TargetLoweringBase::canOpTrap(unsigned Op, EVT VT) const {
assert(isTypeLegal(VT));
switch (Op) {
diff --git a/llvm/lib/CodeGenTypes/LowLevelType.cpp b/llvm/lib/CodeGenTypes/LowLevelType.cpp
index 925b4efaf0edf..35329793bd508 100644
--- a/llvm/lib/CodeGenTypes/LowLevelType.cpp
+++ b/llvm/lib/CodeGenTypes/LowLevelType.cpp
@@ -32,30 +32,47 @@ static std::optional<LLT::FPVariant> deriveFPInfo(MVT VT) {
}
}
-LLT::LLT(MVT VT) {
+LLT::LLT(MVT VT, bool AllowExtendedLLT) {
+ if (!AllowExtendedLLT) {
+ if (VT.isVector()) {
+ bool AsVector = VT.getVectorMinNumElements() > 1 || VT.isScalableVector();
+ Kind Info = AsVector ? Kind::VECTOR_ANY : Kind::ANY_SCALAR;
+ init(Info, VT.getVectorElementCount(),
+ VT.getVectorElementType().getSizeInBits(), 0, FPVariant::IEEE_FLOAT);
+ } else if (VT.isValid() && !VT.isScalableTargetExtVT()) {
+ init(Kind::ANY_SCALAR, ElementCount::getFixed(0), VT.getSizeInBits(), 0,
+ FPVariant::IEEE_FLOAT);
+ } else {
+ this->Info = Kind::INVALID;
+ this->RawData = 0;
+ }
+ return;
+ }
+
auto FP = deriveFPInfo(VT);
bool AsVector = VT.isVector() &&
(VT.getVectorMinNumElements() > 1 || VT.isScalableVector());
- Kind Info;
+ LLT::Kind Info;
if (FP.has_value())
- Info = AsVector ? Kind::VECTOR_FLOAT : Kind::FLOAT;
+ Info = AsVector ? LLT::Kind::VECTOR_FLOAT : LLT::Kind::FLOAT;
else
- Info = AsVector ? Kind::VECTOR_INTEGER : Kind::INTEGER;
+ Info = AsVector ? LLT::Kind::VECTOR_INTEGER : LLT::Kind::INTEGER;
if (VT.isVector()) {
init(Info, VT.getVectorElementCount(),
- VT.getVectorElementType().getSizeInBits(),
- /*AddressSpace=*/0, FP.value_or(FPVariant::IEEE_FLOAT));
+ VT.getVectorElementType().getSizeInBits(), 0,
+ FP.value_or(LLT::FPVariant::IEEE_FLOAT));
} else if (VT.isValid() && !VT.isScalableTargetExtVT()) {
// Aggregates are no different from real scalars as far as GlobalISel is
// concerned.
- init(Info, ElementCount::getFixed(0), VT.getSizeInBits(),
- /*AddressSpace=*/0, FP.value_or(FPVariant::IEEE_FLOAT));
+ init(Info, ElementCount::getFixed(0), VT.getSizeInBits(), 0,
+ FP.value_or(LLT::FPVariant::IEEE_FLOAT));
} else {
- this->Info = static_cast<Kind>(0);
+ this->Info = Kind::INVALID;
this->RawData = 0;
}
+ return;
}
void LLT::print(raw_ostream &OS) const {
diff --git a/llvm/lib/Support/TypeSize.cpp b/llvm/lib/Support/TypeSize.cpp
index 43346b81cd676..a96fced8eff30 100644
--- a/llvm/lib/Support/TypeSize.cpp
+++ b/llvm/lib/Support/TypeSize.cpp
@@ -44,7 +44,7 @@ void llvm::reportInvalidSizeRequest(const char *Msg) {
return;
}
#endif
- report_fatal_error("Invalid size request on a scalable vector.");
+ report_fatal_error(Twine("Invalid size request on a scalable vector.") + Msg);
}
TypeSize::operator TypeSize::ScalarTy() const {
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
index 79bef76cf4c4f..c897a0f65084f 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
@@ -457,7 +457,7 @@ bool AArch64CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
ExtendOp = TargetOpcode::G_ZEXT;
LLT NewLLT(NewVT);
- LLT OldLLT = getLLTForType(*CurArgInfo.Ty, DL);
+ LLT OldLLT = TLI.getLLTForType(*CurArgInfo.Ty, DL);
CurArgInfo.Ty = EVT(NewVT).getTypeForEVT(Ctx);
// Instead of an extend, we might have a vector type which needs
// padding with more elements, e.g. <2 x half> -> <4 x half>.
@@ -1397,7 +1397,7 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
// is set.
if (Info.Callee.isSymbol() && F.getParent()->getRtLibUseGOT()) {
auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_GLOBAL_VALUE);
- DstOp(getLLTForType(*F.getType(), DL)).addDefToMIB(MRI, MIB);
+ DstOp(TLI.getLLTForType(*F.getType(), DL)).addDefToMIB(MRI, MIB);
MIB.addExternalSymbol(Info.Callee.getSymbolName(), AArch64II::MO_GOT);
Info.Callee = MachineOperand::CreateReg(MIB.getReg(0), false);
}
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
index 31954e7954c03..f4ab0190d223f 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
@@ -569,7 +569,7 @@ bool AArch64RegisterBankInfo::onlyUsesFP(const MachineInstr &MI,
case Intrinsic::aarch64_neon_fcvtpu:
// Force FPR register bank for half types, as those types otherwise
// don't get legalized correctly resulting in fp16 <-> gpr32 COPY's.
- return MRI.getType(MI.getOperand(2).getReg()) == LLT::float16();
+ return MRI.getType(MI.getOperand(2).getReg()) == LLT::scalar(16); // TODO: Expected LLT::float16()
default:
break;
}
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp
index d1a5b4e85da46..b5ef1a87a5abb 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp
@@ -332,7 +332,7 @@ bool AMDGPUCallLowering::lowerReturnVal(MachineIRBuilder &B,
extOpcodeToISDExtOpcode(ExtendOp));
if (ExtVT != VT) {
RetInfo.Ty = ExtVT.getTypeForEVT(Ctx);
- LLT ExtTy = getLLTForType(*RetInfo.Ty, DL);
+ LLT ExtTy = TLI.getLLTForType(*RetInfo.Ty, DL);
Reg = B.buildInstr(ExtendOp, {ExtTy}, {Reg}).getReg(0);
}
}
@@ -414,6 +414,7 @@ void AMDGPUCallLowering::lowerParameter(MachineIRBuilder &B, ArgInfo &OrigArg,
MachineFunction &MF = B.getMF();
const Function &F = MF.getFunction();
const DataLayout &DL = F.getDataLayout();
+ const SITargetLowering &TLI = *getTLI<SITargetLowering>();
MachinePointerInfo PtrInfo(AMDGPUAS::CONSTANT_ADDRESS);
LLT PtrTy = LLT::pointer(AMDGPUAS::CONSTANT_ADDRESS, 64);
@@ -427,7 +428,7 @@ void AMDGPUCallLowering::lowerParameter(MachineIRBuilder &B, ArgInfo &OrigArg,
Register PtrReg = B.getMRI()->createGenericVirtualRegister(PtrTy);
lowerParameterPtr(PtrReg, B, Offset + FieldOffsets[Idx]);
- LLT ArgTy = getLLTForType(*SplitArg.Ty, DL);
+ LLT ArgTy = TLI.getLLTForType(*SplitArg.Ty, DL);
if (SplitArg.Flags[0].isPointer()) {
// Compensate for losing pointeriness in splitValueTypes.
LLT PtrTy = LLT::pointer(SplitArg.Flags[0].getPointerAddrSpace(),
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCombinerHelper.cpp b/llvm/lib/Target/AMDGPU/AMDGPUCombinerHelper.cpp
index d23521c87e202..853f55278c667 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUCombinerHelper.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUCombinerHelper.cpp
@@ -464,8 +464,9 @@ bool AMDGPUCombinerHelper::matchCombineFmulWithSelectToFldexp(
LLT DestTy = MRI.getType(Dst);
LLT ScalarDestTy = DestTy.getScalarType();
- if ((ScalarDestTy != LLT::float64() && ScalarDestTy != LLT::float32() &&
- ScalarDestTy != LLT::float16()) ||
+ // TODO: Expected float type in ScalarDestTy
+ if ((ScalarDestTy != LLT::scalar(64) && ScalarDestTy != LLT::scalar(32) &&
+ ScalarDestTy != LLT::scalar(16)) ||
!MRI.hasOneNonDBGUse(Sel.getOperand(0).getReg()))
return false;
@@ -486,7 +487,8 @@ bool AMDGPUCombinerHelper::matchCombineFmulWithSelectToFldexp(
return false;
// For f32, only non-inline constants should be transformed.
- if (ScalarDestTy == LLT::float32() && TII.isInlineConstant(*SelectTrueVal) &&
+ // TODO: Expected float32
+ if (ScalarDestTy == LLT::scalar(32) && TII.isInlineConstant(*SelectTrueVal) &&
TII.isInlineConstant(*SelectFalseVal))
return false;
diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
index 600a13096f55d..ccc01ddfce777 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
@@ -295,9 +295,9 @@ constexpr LLT S1 = LLT::scalar(1);
constexpr LLT S8 = LLT::scalar(8);
constexpr LLT S16 = LLT::scalar(16);
constexpr LLT S32 = LLT::scalar(32);
-constexpr LLT F32 = LLT::float32();
+constexpr LLT F32 = LLT::scalar(32); // TODO: Expected float32
constexpr LLT S64 = LLT::scalar(64);
-constexpr LLT F64 = LLT::float64();
+constexpr LLT F64 = LLT::scalar(64); // TODO: Expected float64
constexpr LLT S96 = LLT::scalar(96);
constexpr LLT S128 = LLT::scalar(128);
constexpr LLT S160 = LLT::scalar(160);
@@ -317,7 +317,7 @@ constexpr LLT V10S16 = LLT::fixed_vector(10, 16);
constexpr LLT V12S16 = LLT::fixed_vector(12, 16);
constexpr LLT V16S16 = LLT::fixed_vector(16, 16);
-constexpr LLT V2F16 = LLT::fixed_vector(2, LLT::float16());
+constexpr LLT V2F16 = LLT::fixed_vector(2, LLT::scalar(16)); // TODO: Expected float16
constexpr LLT V2BF16 = V2F16; // FIXME
constexpr LLT V2S32 = LLT::fixed_vector(2, 32);
@@ -3344,11 +3344,12 @@ bool AMDGPULegalizerInfo::legalizeFMad(
const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
// TODO: Always legal with future ftz flag.
+ // TODO: Type is expected to be float32/float16
// FIXME: Do we need just output?
- if (Ty == LLT::float32() &&
+ if (Ty == LLT::scalar(32) &&
MFI->getMode().FP32Denormals == DenormalMode::getPreserveSign())
return true;
- if (Ty == LLT::float16() &&
+ if (Ty == LLT::scalar(16) &&
MFI->getMode().FP64FP16Denormals == DenormalMode::getPreserveSign())
return true;
@@ -3900,8 +3901,8 @@ bool AMDGPULegalizerInfo::legalizeFPow(MachineInstr &MI,
Register Src1 = MI.getOperand(2).getReg();
unsigned Flags = MI.getFlags();
LLT Ty = B.getMRI()->getType(Dst);
- const LLT F16 = LLT::float16();
- const LLT F32 = LLT::float32();
+ const LLT F16 = LLT::scalar(16); // TODO: Expected float16
+ const LLT F32 = LLT::scalar(32); // TODO: Expected float32
if (Ty == F32) {
auto Log = B.buildFLog2(F32, Src0, Flags);
@@ -3944,7 +3945,7 @@ bool AMDGPULegalizerInfo::legalizeFFloor(MachineInstr &MI,
MachineIRBuilder &B) const {
const LLT S1 = LLT::scalar(1);
- const LLT F64 = LLT::float64();
+ const LLT F64 = LLT::scalar(64); // TODO: Expected float64
Register Dst = MI.getOperand(0).getReg();
Register OrigSrc = MI.getOperand(1).getReg();
unsigned Flags = MI.getFlags();
diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
index 16a12cabce4c5..4af29cee0a3fe 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
+++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
@@ -10,6 +10,7 @@
#include "Common/CodeGenInstruction.h"
#include "Common/CodeGenRegisters.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/ScopedPrinter.h"
@@ -20,6 +21,11 @@
STATISTIC(NumPatternEmitted, "Number of patterns emitted");
+static llvm::cl::opt<bool> AllowExtendedLLT(
+ "gisel-extended-llt",
+ llvm::cl::desc("Generate an extended llt names in match tables"),
+ llvm::cl::init(false));
+
namespace llvm {
namespace gi {
@@ -417,6 +423,8 @@ void LLTCodeGen::emitCxxConstructorCall(raw_ostream &OS) const {
else if (Ty.isFloat())
OS << "LLT::floatingPoint(" << Ty.getScalarSizeInBits()
<< ", LLT::FPVariant::IEEE_FLOAT)";
+ else
+ OS << "LLT::scalar(" << Ty.getScalarSizeInBits() << ")";
return;
}
@@ -438,7 +446,8 @@ void LLTCodeGen::emitCxxConstructorCall(raw_ostream &OS) const {
else if (ElemTy.isFloat())
OS << "LLT::floatingPoint(" << ElemTy.getScalarSizeInBits()
<< ", LLT::FPVariant::IEEE_FLOAT)";
-
+ else
+ OS << "LLT::scalar(" << Ty.getScalarSizeInBits() << ")";
OS << ")";
return;
}
@@ -456,7 +465,36 @@ 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 {
- return Ty.getUniqueRAWLLTData() < Other.Ty.getUniqueRAWLLTData();
+ 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();
}
//===- LLTCodeGen Helpers -------------------------------------------------===//
@@ -465,10 +503,10 @@ std::optional<LLTCodeGen> MVTToLLT(MVT::SimpleValueType SVT) {
MVT VT(SVT);
if (VT.isVector() && !VT.getVectorElementCount().isScalar())
- return LLTCodeGen(LLT(VT));
+ return LLTCodeGen(LLT(VT, AllowExtendedLLT));
if (VT.isInteger() || VT.isFloatingPoint())
- return LLTCodeGen(LLT(VT));
+ return LLTCodeGen(LLT(VT, AllowExtendedLLT));
return std::nullopt;
}
>From bc4b0ec59137b7effc2acdecabcbd0b179d64b35 Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Fri, 22 Aug 2025 19:14:47 +0300
Subject: [PATCH 05/40] Fix MIR tests
---
.../CodeGen/MIR/AArch64/parse-low-level-type-invalid0.mir | 4 ++--
.../CodeGen/MIR/AArch64/parse-low-level-type-invalid1.mir | 4 ++--
.../CodeGen/MIR/AArch64/parse-low-level-type-invalid2.mir | 2 +-
.../CodeGen/MIR/AArch64/parse-low-level-type-invalid3.mir | 6 +++---
llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err0.mir | 2 +-
llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err1.mir | 2 +-
.../test/CodeGen/MIR/Generic/scalable-vector-type-err10.mir | 2 +-
.../test/CodeGen/MIR/Generic/scalable-vector-type-err11.mir | 2 +-
.../test/CodeGen/MIR/Generic/scalable-vector-type-err12.mir | 2 +-
.../test/CodeGen/MIR/Generic/scalable-vector-type-err13.mir | 2 +-
.../test/CodeGen/MIR/Generic/scalable-vector-type-err14.mir | 2 +-
.../test/CodeGen/MIR/Generic/scalable-vector-type-err15.mir | 2 +-
llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err2.mir | 2 +-
llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err3.mir | 2 +-
llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err4.mir | 2 +-
llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err5.mir | 2 +-
llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err6.mir | 2 +-
llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err7.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 | 4 ++--
.../MIR/WebAssembly/typed-immediate-operand-invalid1.mir | 4 ++--
22 files changed, 28 insertions(+), 28 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..95fd669a5d971 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
@@ -1,10 +1,10 @@
# RUN: not llc -mtriple=aarch64-- -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
-# When a low-level type is only a single 's'/'p' character
+# When a low-level type is only a single 's'/'i'/'f'/'bf'/'p' type identifier
---
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..dd0bb73a6cf42 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
@@ -5,6 +5,6 @@ name: test_low_level_type_does_not_start_with_s_p_lt
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
+ ; CHECK: [[@LINE+1]]:10: expected tN, pA, <M x tN>, <M x pA>, <vscale x M x tN>, or <vscale x M x pA> for GlobalISel type, where t = {'s', 'i', 'f', 'bf'}
+ %0:_(n64) = 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..ba652329c5337 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
@@ -1,10 +1,10 @@
# RUN: not llc -mtriple=aarch64-- -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
-# When a low-level type is a vector which element type does not start with 's' or 'p'
+# When a low-level type is a vector which element type does not start with right type identifier
---
name: test_low_level_type_does_not_start_with_s_p
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
+ ; CHECK: [[@LINE+1]]:10: expected <M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}
+ %0:_(<2 x n64>) = COPY $q0
...
diff --git a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err0.mir b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err0.mir
index 5553d97acd003..6fc6640ea422a 100644
--- a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err0.mir
+++ b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err0.mir
@@ -6,5 +6,5 @@ body: |
%0:_(<vscale) = IMPLICIT_DEF
...
-# CHECK: expected <vscale x M x sN> or <vscale x M x pA>
+# CHECK: expected <vscale x M x tN>, where t = {'s', 'i', 'f', 'bf', 'p'}
diff --git a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err1.mir b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err1.mir
index 12bfb82ebcd12..0017e01be3b04 100644
--- a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err1.mir
+++ b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err1.mir
@@ -6,4 +6,4 @@ body: |
%0:_(<vscale notanx) = IMPLICIT_DEF
...
-# CHECK: expected <vscale x M x sN> or <vscale x M x pA>
+# CHECK: expected <vscale x M x tN>, where t = {'s', 'i', 'f', 'bf', 'p'}
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-err11.mir b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err11.mir
index f8927c22ab45f..64296f624826e 100644
--- a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err11.mir
+++ b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err11.mir
@@ -7,4 +7,4 @@ body: |
%0:_(<vscale x 4 x s32) = IMPLICIT_DEF
...
-# CHECK: expected <vscale x M x sN> or <vscale M x pA> for vector type
+# CHECK: expected <vscale x M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}
diff --git a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err12.mir b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err12.mir
index 5ced1aea30c08..9c840d92ac967 100644
--- a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err12.mir
+++ b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err12.mir
@@ -7,4 +7,4 @@ body: |
%0:_(<vscale x 4 x p0) = IMPLICIT_DEF
...
-# CHECK: expected <vscale x M x sN> or <vscale M x pA> for vector type
+# CHECK: expected <vscale x M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}
diff --git a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err13.mir b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err13.mir
index 94b8230233fa6..982adfdf792c2 100644
--- a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err13.mir
+++ b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err13.mir
@@ -7,4 +7,4 @@ body: |
%0:_(<vscale x 4 x s32 X) = IMPLICIT_DEF
...
-# CHECK: expected <vscale x M x sN> or <vscale M x pA> for vector type
+# CHECK: expected <vscale x M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}
diff --git a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err14.mir b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err14.mir
index 323e2d975692f..8a3e86ecaaab9 100644
--- a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err14.mir
+++ b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err14.mir
@@ -7,4 +7,4 @@ body: |
%0:_(<vscale x 4 x p0 X) = IMPLICIT_DEF
...
-# CHECK: expected <vscale x M x sN> or <vscale M x pA> for vector type
+# CHECK: expected <vscale x M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}
diff --git a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err15.mir b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err15.mir
index d1613869bf671..228b367b06d40 100644
--- a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err15.mir
+++ b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err15.mir
@@ -7,4 +7,4 @@ body: |
%0:_(notatype) = IMPLICIT_DEF
...
-# CHECK: expected sN, pA, <M x sN>, <M x pA>, <vscale x M x sN>, or <vscale x M x pA> for GlobalISel type
+# CHECK: expected tN, pA, <M x tN>, <M x pA>, <vscale x M x tN>, or <vscale x M x pA> for GlobalISel type, where t = {'s', 'i', 'f', 'bf'}
diff --git a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err2.mir b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err2.mir
index c504a7d6be249..b187bff218a75 100644
--- a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err2.mir
+++ b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err2.mir
@@ -6,4 +6,4 @@ body: |
%0:_(<vscale x) = IMPLICIT_DEF
...
-# CHECK: expected <vscale x M x sN> or <vscale M x pA> for vector type
+# CHECK: expected <vscale x M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}
diff --git a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err3.mir b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err3.mir
index c504a7d6be249..b187bff218a75 100644
--- a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err3.mir
+++ b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err3.mir
@@ -6,4 +6,4 @@ body: |
%0:_(<vscale x) = IMPLICIT_DEF
...
-# CHECK: expected <vscale x M x sN> or <vscale M x pA> for vector type
+# CHECK: expected <vscale x M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}
diff --git a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err4.mir b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err4.mir
index 654f534f4d301..1969f28b18d28 100644
--- a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err4.mir
+++ b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err4.mir
@@ -6,5 +6,5 @@ body: |
%0:_(<vscale x notanint) = IMPLICIT_DEF
...
-# CHECK: expected <vscale x M x sN> or <vscale M x pA> for vector type
+# CHECK: expected <vscale x M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}
diff --git a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err5.mir b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err5.mir
index 26be2868c522e..49823f7432ba9 100644
--- a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err5.mir
+++ b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err5.mir
@@ -6,4 +6,4 @@ body: |
%0:_(<vscale x 4) = IMPLICIT_DEF
...
-# CHECK: expected <vscale x M x sN> or <vscale M x pA> for vector type
+# CHECK: expected <vscale x M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}
diff --git a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err6.mir b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err6.mir
index 07a30f57139dc..7f8e421e76ae3 100644
--- a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err6.mir
+++ b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err6.mir
@@ -7,5 +7,5 @@ body: |
%0:_(<vscale x 4 x) = IMPLICIT_DEF
...
-# CHECK: expected <vscale x M x sN> or <vscale M x pA> for vector type
+# CHECK: expected <vscale x M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}
diff --git a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err7.mir b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err7.mir
index dba902efe6331..ae3c472e2557c 100644
--- a/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err7.mir
+++ b/llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err7.mir
@@ -6,4 +6,4 @@ body: |
%0:_(<vscale x 4 x notansorp) = IMPLICIT_DEF
...
-# CHECK: expected <vscale x M x sN> or <vscale M x pA> for vector type
+# CHECK: expected <vscale x M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}
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..7a2e381372549 100644
--- a/llvm/test/CodeGen/MIR/WebAssembly/typed-immediate-operand-invalid0.mir
+++ b/llvm/test/CodeGen/MIR/WebAssembly/typed-immediate-operand-invalid0.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 is only a single 'i'/'s'/'p' character
+# When a typed immediate operand is only a single type character
---
name: test_typed_immediate_operand_invalid0
liveins:
@@ -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..7f59a9e5eca0f 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 right type identifier
---
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 655b85ada6d0c441ad6e36d4474ad31f5326dc5a Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Fri, 22 Aug 2025 19:32:47 +0300
Subject: [PATCH 06/40] enable bfloat in IRTranslator for targets that support
it
---
.../llvm/CodeGen/GlobalISel/IRTranslator.h | 2 +
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 37 +++++++++++--------
2 files changed, 23 insertions(+), 16 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
index 3d7ccd55ee042..5673fd5168477 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
@@ -642,6 +642,8 @@ class IRTranslator : public MachineFunctionPass {
StackProtectorDescriptor SPDescriptor;
+ bool mayTranslateUserTypes(const User &U) const;
+
/// Switch analysis and optimization.
class GISelSwitchLowering : public SwitchCG::SwitchLowering {
public:
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 4484a0769ad2a..0abaeea482f24 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -295,19 +295,10 @@ void IRTranslator::addMachineCFGPred(CFGEdge Edge, MachineBasicBlock *NewPred) {
MachinePreds[Edge].push_back(NewPred);
}
-static bool containsBF16Type(const User &U) {
- // BF16 cannot currently be represented by LLT, to avoid miscompiles we
- // prevent any instructions using them. FIXME: This can be removed once LLT
- // supports bfloat.
- return U.getType()->getScalarType()->isBFloatTy() ||
- any_of(U.operands(), [](Value *V) {
- return V->getType()->getScalarType()->isBFloatTy();
- });
-}
bool IRTranslator::translateBinaryOp(unsigned Opcode, const User &U,
MachineIRBuilder &MIRBuilder) {
- if (containsBF16Type(U))
+ if (!mayTranslateUserTypes(U))
return false;
// Get or create a virtual register for each value.
@@ -329,7 +320,7 @@ bool IRTranslator::translateBinaryOp(unsigned Opcode, const User &U,
bool IRTranslator::translateUnaryOp(unsigned Opcode, const User &U,
MachineIRBuilder &MIRBuilder) {
- if (containsBF16Type(U))
+ if (!mayTranslateUserTypes(U))
return false;
Register Op0 = getOrCreateVReg(*U.getOperand(0));
@@ -349,7 +340,7 @@ bool IRTranslator::translateFNeg(const User &U, MachineIRBuilder &MIRBuilder) {
bool IRTranslator::translateCompare(const User &U,
MachineIRBuilder &MIRBuilder) {
- if (containsBF16Type(U))
+ if (!mayTranslateUserTypes(U))
return false;
auto *CI = cast<CmpInst>(&U);
@@ -1570,7 +1561,7 @@ bool IRTranslator::translateBitCast(const User &U,
bool IRTranslator::translateCast(unsigned Opcode, const User &U,
MachineIRBuilder &MIRBuilder) {
- if (containsBF16Type(U))
+ if (!mayTranslateUserTypes(U))
return false;
uint32_t Flags = 0;
@@ -2675,7 +2666,7 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
bool IRTranslator::translateInlineAsm(const CallBase &CB,
MachineIRBuilder &MIRBuilder) {
- if (containsBF16Type(CB))
+ if (!mayTranslateUserTypes(CB))
return false;
const InlineAsmLowering *ALI = MF->getSubtarget().getInlineAsmLowering();
@@ -2766,7 +2757,7 @@ bool IRTranslator::translateCallBase(const CallBase &CB,
}
bool IRTranslator::translateCall(const User &U, MachineIRBuilder &MIRBuilder) {
- if (containsBF16Type(U))
+ if (!mayTranslateUserTypes(U))
return false;
const CallInst &CI = cast<CallInst>(U);
@@ -3392,7 +3383,7 @@ bool IRTranslator::translateAtomicCmpXchg(const User &U,
bool IRTranslator::translateAtomicRMW(const User &U,
MachineIRBuilder &MIRBuilder) {
- if (containsBF16Type(U))
+ if (!mayTranslateUserTypes(U))
return false;
const AtomicRMWInst &I = cast<AtomicRMWInst>(U);
@@ -3733,6 +3724,20 @@ bool IRTranslator::translate(const Constant &C, Register Reg) {
return true;
}
+bool IRTranslator::mayTranslateUserTypes(const User &U) const {
+ if (TLI->getTargetMachine().Options.EnableGlobalISelExtendedLLT) {
+ return true;
+ }
+
+ // BF16 cannot currently be represented by default LLT, to avoid miscompiles
+ // we prevent any instructions using them in targets with disabled
+ // TargetOptions::EnableGlobalISelExtendedLLT.
+ return !U.getType()->getScalarType()->isBFloatTy() &&
+ !any_of(U.operands(), [](Value *V) {
+ return V->getType()->getScalarType()->isBFloatTy();
+ });
+}
+
bool IRTranslator::finalizeBasicBlock(const BasicBlock &BB,
MachineBasicBlock &MBB) {
for (auto &BTB : SL->BitTestCases) {
>From b767e6ee5420427e5fa7769cdd30c40e66dce340 Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Sat, 23 Aug 2025 18:20:22 +0300
Subject: [PATCH 07/40] [unittest] Added simple IRTranslator test for bf16
---
.../CodeGen/GlobalISel/CMakeLists.txt | 1 +
.../GlobalISel/IRTranslatorBF16Test.cpp | 130 ++++++++++++++++++
2 files changed, 131 insertions(+)
create mode 100644 llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp
diff --git a/llvm/unittests/CodeGen/GlobalISel/CMakeLists.txt b/llvm/unittests/CodeGen/GlobalISel/CMakeLists.txt
index 4ef6aff943f73..e85a3aa72c961 100644
--- a/llvm/unittests/CodeGen/GlobalISel/CMakeLists.txt
+++ b/llvm/unittests/CodeGen/GlobalISel/CMakeLists.txt
@@ -14,6 +14,7 @@ set(LLVM_LINK_COMPONENTS
)
add_llvm_unittest(GlobalISelTests
+ IRTranslatorBF16Test.cpp
ConstantFoldingTest.cpp
CSETest.cpp
GIMatchTableExecutorTest.cpp
diff --git a/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp b/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp
new file mode 100644
index 0000000000000..31ec0e34a0661
--- /dev/null
+++ b/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp
@@ -0,0 +1,130 @@
+//===- IRTranslator.cpp - IRTranslator 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/CodeGen/GlobalISel/IRTranslator.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/TargetFrameLowering.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/CodeGen/TargetOpcodes.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/Module.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+#include "gtest/gtest.h"
+#include <memory>
+
+using namespace llvm;
+
+namespace {
+struct AArch64IRTranslatorTest : public ::testing::Test {
+ LLVMContext C;
+
+public:
+ AArch64IRTranslatorTest() {}
+ std::unique_ptr<TargetMachine> createTargetMachine() const {
+ Triple TargetTriple("aarch64--");
+ std::string Error;
+ const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error);
+ if (!T)
+ return nullptr;
+
+ TargetOptions Options;
+ return std::unique_ptr<TargetMachine>(
+ T->createTargetMachine(TargetTriple, "", "", Options, std::nullopt,
+ std::nullopt, CodeGenOptLevel::Aggressive));
+ }
+
+ std::unique_ptr<Module> parseIR(const char *IR) {
+ SMDiagnostic Err;
+ std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
+ if (!Mod)
+ Err.print("Test TargetIRTranslator", errs());
+ return Mod;
+ }
+};
+} // namespace
+
+TEST_F(AArch64IRTranslatorTest, IRTranslateBfloat16) {
+ InitializeAllTargets();
+ InitializeAllTargetMCs();
+ InitializeAllAsmPrinters();
+ InitializeAllAsmParsers();
+
+ PassRegistry *Registry = PassRegistry::getPassRegistry();
+ initializeCore(*Registry);
+ initializeCodeGen(*Registry);
+ initializeGlobalISel(*Registry);
+
+ std::unique_ptr<Module> M = parseIR(R"(
+ define void @foo(ptr %p0) {
+ %ptr1 = getelementptr bfloat, ptr %p0, i64 0
+ %ptr2 = getelementptr bfloat, ptr %p0, i64 1
+ %ptr3 = getelementptr bfloat, ptr %p0, i64 2
+ %a = load bfloat, ptr %ptr1, align 2
+ %b = load bfloat, ptr %ptr2, align 2
+ %c = load bfloat, ptr %ptr3, align 2
+ %mul = fmul bfloat %a, %b
+ %res = fadd bfloat %mul, %c
+ %ptr4 = getelementptr bfloat, ptr %p0, i64 3
+ store bfloat %res, ptr %ptr4, align 2
+ ret void
+ }
+ )");
+
+ auto TM = createTargetMachine();
+ M->setDataLayout(TM->createDataLayout());
+
+ TM->setGlobalISel(true);
+ TM->setGlobalISelExtendedLLT(true);
+ TM->setGlobalISelAbort(GlobalISelAbortMode::DisableWithDiag);
+
+ legacy::PassManager PM;
+ TargetPassConfig *TPC(TM->createPassConfig(PM));
+
+ MachineModuleInfoWrapperPass *MMIWP = new MachineModuleInfoWrapperPass(TM.get());
+ PM.add(TPC);
+ PM.add(MMIWP);
+ PM.add(new IRTranslator());
+ PM.run(*M);
+
+ auto *MMI = &MMIWP->getMMI();
+ Function *F = M->getFunction("foo");
+ auto *MF = MMI->getMachineFunction(*F);
+ MachineRegisterInfo &MRI = MF->getRegInfo();
+ ASSERT_FALSE(MF->getProperties().hasProperty(
+ llvm::MachineFunctionProperties::Property::FailedISel));
+ for (auto &MI : MF->front()) {
+ if (MI.getOpcode() == TargetOpcode::G_LOAD) {
+ ASSERT_EQ(MRI.getType(MI.getOperand(0).getReg()), LLT::bfloat16());
+ }
+
+ if (MI.getOpcode() == TargetOpcode::G_FADD ||
+ MI.getOpcode() == TargetOpcode::G_FMUL) {
+ for (auto &Op : MI.operands()) {
+ ASSERT_EQ(MRI.getType(Op.getReg()), LLT::bfloat16());
+ }
+ }
+ }
+ MMI->deleteMachineFunctionFor(*F);
+
+ // Run again without extended LLT
+ TM->setGlobalISelExtendedLLT(false);
+ PM.run(*M);
+ MF = MMI->getMachineFunction(*F);
+ ASSERT_TRUE(MF->getProperties().hasProperty(llvm::MachineFunctionProperties::Property::FailedISel));
+}
>From 82602b7ecdae957ef2349e36d16aecda91cfb2f0 Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Sat, 23 Aug 2025 18:45:53 +0300
Subject: [PATCH 08/40] fixed names
---
llvm/include/llvm/CodeGenTypes/LowLevelType.h | 14 +++++++-------
llvm/lib/CodeGenTypes/LowLevelType.cpp | 4 ++--
llvm/lib/Support/TypeSize.cpp | 2 +-
3 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/llvm/include/llvm/CodeGenTypes/LowLevelType.h b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
index daec87ab536c0..0c217ba1fcf7e 100644
--- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h
+++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
@@ -42,9 +42,9 @@ class LLT {
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
+ PPC128_FLOAT = 0x2, // PPC128_FLOAT
+ EXTENDED_FP80 = 0x3, // FP80
+ TENSOR_FLOAT32 = 0x4, // TENSOR_FLOAT32
VARIANT_FLOAT_5 = 0x5, // UNASSIGNED
VARIANT_FLOAT_6 = 0x6, // UNASSIGNED
VARIANT_FLOAT_7 = 0x7, // UNASSIGNED
@@ -163,7 +163,7 @@ class LLT {
/// Get a 80-bit X86 floating point value.
static constexpr LLT x86fp80() {
- return floatingPoint(80, FPVariant::VARIANT_FLOAT_3);
+ return floatingPoint(80, FPVariant::EXTENDED_FP80);
}
/// Get a 128-bit IEEE quad value.
@@ -173,7 +173,7 @@ class LLT {
/// Get a 128-bit PowerPC double double value.
static constexpr LLT ppcf128() {
- return floatingPoint(128, FPVariant::VARIANT_FLOAT_2);
+ return floatingPoint(128, FPVariant::PPC128_FLOAT);
}
/// Get a low-level fixed-width vector of some number of elements and element
@@ -249,10 +249,10 @@ class LLT {
return isVariantFloat(Size, FPVariant::BRAIN_FLOAT);
}
constexpr bool isX86FP80() const {
- return isVariantFloat(80, FPVariant::VARIANT_FLOAT_3);
+ return isVariantFloat(80, FPVariant::EXTENDED_FP80);
}
constexpr bool isPPCF128() const {
- return isVariantFloat(128, FPVariant::VARIANT_FLOAT_2);
+ return isVariantFloat(128, FPVariant::PPC128_FLOAT);
}
constexpr bool isToken() const {
return Info == Kind::ANY_SCALAR && RawData == 0;
diff --git a/llvm/lib/CodeGenTypes/LowLevelType.cpp b/llvm/lib/CodeGenTypes/LowLevelType.cpp
index 35329793bd508..6025f3fedafa1 100644
--- a/llvm/lib/CodeGenTypes/LowLevelType.cpp
+++ b/llvm/lib/CodeGenTypes/LowLevelType.cpp
@@ -24,9 +24,9 @@ static std::optional<LLT::FPVariant> deriveFPInfo(MVT VT) {
case MVT::bf16:
return LLT::FPVariant::BRAIN_FLOAT;
case MVT::f80:
- return LLT::FPVariant::VARIANT_FLOAT_3;
+ return LLT::FPVariant::EXTENDED_FP80;
case MVT::ppcf128:
- return LLT::FPVariant::VARIANT_FLOAT_2;
+ return LLT::FPVariant::PPC128_FLOAT;
default:
return LLT::FPVariant::IEEE_FLOAT;
}
diff --git a/llvm/lib/Support/TypeSize.cpp b/llvm/lib/Support/TypeSize.cpp
index a96fced8eff30..43346b81cd676 100644
--- a/llvm/lib/Support/TypeSize.cpp
+++ b/llvm/lib/Support/TypeSize.cpp
@@ -44,7 +44,7 @@ void llvm::reportInvalidSizeRequest(const char *Msg) {
return;
}
#endif
- report_fatal_error(Twine("Invalid size request on a scalable vector.") + Msg);
+ report_fatal_error("Invalid size request on a scalable vector.");
}
TypeSize::operator TypeSize::ScalarTy() const {
>From 6485b50cfdea9a41c11b294b70c30b35d22ee845 Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Sat, 23 Aug 2025 19:21:30 +0300
Subject: [PATCH 09/40] code style fixes
---
llvm/include/llvm/CodeGen/Analysis.h | 3 +--
.../llvm/CodeGen/GlobalISel/LegalizerInfo.h | 3 ++-
llvm/include/llvm/CodeGen/LowLevelTypeUtils.h | 3 ++-
llvm/include/llvm/CodeGenTypes/LowLevelType.h | 13 +++++++++----
llvm/include/llvm/Target/TargetMachine.h | 4 +++-
llvm/include/llvm/Target/TargetOptions.h | 4 ++--
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 1 -
llvm/lib/CodeGen/MIRParser/MIParser.cpp | 16 ++++++++++------
.../AArch64/GISel/AArch64RegisterBankInfo.cpp | 3 ++-
llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp | 5 +++--
.../CodeGen/GlobalISel/IRTranslatorBF16Test.cpp | 10 ++++++----
11 files changed, 40 insertions(+), 25 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/Analysis.h b/llvm/include/llvm/CodeGen/Analysis.h
index 2aadc27930b7a..5c36ecd26719e 100644
--- a/llvm/include/llvm/CodeGen/Analysis.h
+++ b/llvm/include/llvm/CodeGen/Analysis.h
@@ -101,8 +101,7 @@ inline void ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL,
/// If Offsets is non-null, it points to a vector to be filled in
/// with the in-memory offsets of each of the individual values.
///
-void computeValueLLTs(const TargetLowering &TLI,
- const DataLayout &DL, Type &Ty,
+void computeValueLLTs(const TargetLowering &TLI, const DataLayout &DL, Type &Ty,
SmallVectorImpl<LLT> &ValueTys,
SmallVectorImpl<uint64_t> *Offsets = nullptr,
uint64_t StartingOffset = 0);
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
index 8412042a780e8..7b6b5dbf0be05 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
@@ -380,7 +380,8 @@ LLVM_ABI LegalizeMutation changeElementCountTo(unsigned TypeIdx,
/// Keep the same scalar or element type as \p TypeIdx, but take the number of
/// elements from \p Ty.
-LLVM_ABI LegalizeMutation changeElementCountTo(unsigned TypeIdx, ElementCount EC);
+LLVM_ABI 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/include/llvm/CodeGen/LowLevelTypeUtils.h b/llvm/include/llvm/CodeGen/LowLevelTypeUtils.h
index 1c8f34b1a8518..4092509948ae6 100644
--- a/llvm/include/llvm/CodeGen/LowLevelTypeUtils.h
+++ b/llvm/include/llvm/CodeGen/LowLevelTypeUtils.h
@@ -27,7 +27,8 @@ class Type;
struct fltSemantics;
/// Construct a low-level type based on an LLVM type.
-LLVM_ABI LLT getLLTForType(Type &Ty, const DataLayout &DL, bool AllowExtendedLLT = false);
+LLVM_ABI LLT getLLTForType(Type &Ty, const DataLayout &DL,
+ bool AllowExtendedLLT = false);
/// Get a rough equivalent of an MVT for a given LLT. MVT can't distinguish
/// pointers, so these will convert to a plain integer.
diff --git a/llvm/include/llvm/CodeGenTypes/LowLevelType.h b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
index 0c217ba1fcf7e..3378baf680230 100644
--- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h
+++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
@@ -178,7 +178,8 @@ class LLT {
/// Get a low-level fixed-width vector of some number of elements and element
/// width.
- static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits) {
+ static constexpr LLT fixed_vector(unsigned NumElements,
+ unsigned ScalarSizeInBits) {
return vector(ElementCount::getFixed(NumElements),
LLT::scalar(ScalarSizeInBits));
}
@@ -191,7 +192,8 @@ class LLT {
/// Get a low-level scalable vector of some number of elements and element
/// width.
- static constexpr LLT scalable_vector(unsigned MinNumElements, unsigned ScalarSizeInBits) {
+ static constexpr LLT scalable_vector(unsigned MinNumElements,
+ unsigned ScalarSizeInBits) {
return vector(ElementCount::getScalable(MinNumElements),
LLT::scalar(ScalarSizeInBits));
}
@@ -222,7 +224,10 @@ class LLT {
explicit constexpr LLT() : Info(static_cast<Kind>(0)), RawData(0) {}
constexpr bool isValid() const { return isToken() || RawData != 0; }
- constexpr bool isScalar() const { return Info == Kind::ANY_SCALAR || Info == Kind::INTEGER || Info == Kind::FLOAT; }
+ constexpr bool isScalar() const {
+ return Info == Kind::ANY_SCALAR || Info == Kind::INTEGER ||
+ Info == Kind::FLOAT;
+ }
constexpr bool isScalar(unsigned Size) const {
return isScalar() && getScalarSizeInBits() == Size;
}
@@ -274,7 +279,7 @@ class LLT {
}
constexpr bool isVector() const {
return isValid() &&
- (Info == Kind::VECTOR_ANY || Info == Kind::VECTOR_INTEGER||
+ (Info == Kind::VECTOR_ANY || Info == Kind::VECTOR_INTEGER ||
Info == Kind::VECTOR_FLOAT || Info == Kind::VECTOR_POINTER);
}
constexpr bool isPointer() const {
diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h
index 5671318a8586d..a503199856c5a 100644
--- a/llvm/include/llvm/Target/TargetMachine.h
+++ b/llvm/include/llvm/Target/TargetMachine.h
@@ -295,7 +295,9 @@ class LLVM_ABI TargetMachine {
bool getO0WantsFastISel() { return O0WantsFastISel; }
void setO0WantsFastISel(bool Enable) { O0WantsFastISel = Enable; }
void setGlobalISel(bool Enable) { Options.EnableGlobalISel = Enable; }
- void setGlobalISelExtendedLLT(bool Enable) { Options.EnableGlobalISelExtendedLLT = Enable; }
+ void setGlobalISelExtendedLLT(bool Enable) {
+ Options.EnableGlobalISelExtendedLLT = Enable;
+ }
void setGlobalISelAbort(GlobalISelAbortMode Mode) {
Options.GlobalISelAbort = Mode;
}
diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h
index 839412cd151bf..b167d4e13a342 100644
--- a/llvm/include/llvm/Target/TargetOptions.h
+++ b/llvm/include/llvm/Target/TargetOptions.h
@@ -236,8 +236,8 @@ class TargetOptions {
/// EnableGlobalISel - This flag enables global instruction selection.
unsigned EnableGlobalISel : 1;
- /// EnableGlobalISelExtendedLLT - This flag enables LLTs with extenden type info
- /// so target may distinguish different formats of equal sized scalars.
+ /// EnableGlobalISelExtendedLLT - This flag enables LLTs with extenden type
+ /// info so target may distinguish different formats of equal sized scalars.
unsigned EnableGlobalISelExtendedLLT : 1;
/// EnableGlobalISelAbort - Control abort behaviour when global instruction
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 670e03e69a9c4..8dac12fc4597a 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -294,7 +294,6 @@ void IRTranslator::addMachineCFGPred(CFGEdge Edge, MachineBasicBlock *NewPred) {
MachinePreds[Edge].push_back(NewPred);
}
-
bool IRTranslator::translateBinaryOp(unsigned Opcode, const User &U,
MachineIRBuilder &MIRBuilder) {
if (!mayTranslateUserTypes(U))
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 699f4d3529b6e..94205698c5038 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -1934,7 +1934,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")) {
@@ -1994,15 +1995,17 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
if (HasVScale) {
lex();
if (Token.isNot(MIToken::Identifier) || Token.stringValue() != "x")
- return error("expected <vscale x M x tN>, where t = {'s', 'i', 'f', 'bf', 'p'}");
+ return error(
+ "expected <vscale x M x tN>, where t = {'s', 'i', 'f', 'bf', 'p'}");
lex();
}
auto GetError = [this, &HasVScale, Loc]() {
if (HasVScale)
- return error(
- Loc, "expected <vscale x M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}");
- return error(Loc, "expected <M x tN> for vector type, where t = {'s', 'i', 'f', 'bf', 'p'}");
+ return error(Loc, "expected <vscale x M x tN> for vector type, where t = "
+ "{'s', 'i', 'f', 'bf', 'p'}");
+ return error(Loc, "expected <M x tN> for vector type, where t = {'s', 'i', "
+ "'f', 'bf', 'p'}");
};
if (Token.isNot(MIToken::IntegerLiteral))
@@ -2073,7 +2076,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();
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
index aa598dec1c800..29d5cec49d579 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
@@ -570,7 +570,8 @@ bool AArch64RegisterBankInfo::onlyUsesFP(const MachineInstr &MI,
case Intrinsic::aarch64_neon_fcvtpu:
// Force FPR register bank for half types, as those types otherwise
// don't get legalized correctly resulting in fp16 <-> gpr32 COPY's.
- return MRI.getType(MI.getOperand(2).getReg()) == LLT::scalar(16); // TODO: Expected LLT::float16()
+ return MRI.getType(MI.getOperand(2).getReg()) ==
+ LLT::scalar(16); // TODO: Expected LLT::float16()
default:
break;
}
diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
index ccc01ddfce777..a4e2f321be91d 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
@@ -317,8 +317,9 @@ constexpr LLT V10S16 = LLT::fixed_vector(10, 16);
constexpr LLT V12S16 = LLT::fixed_vector(12, 16);
constexpr LLT V16S16 = LLT::fixed_vector(16, 16);
-constexpr LLT V2F16 = LLT::fixed_vector(2, LLT::scalar(16)); // TODO: Expected float16
-constexpr LLT V2BF16 = V2F16; // FIXME
+constexpr LLT V2F16 =
+ LLT::fixed_vector(2, LLT::scalar(16)); // TODO: Expected float16
+constexpr LLT V2BF16 = V2F16; // FIXME
constexpr LLT V2S32 = LLT::fixed_vector(2, 32);
constexpr LLT V3S32 = LLT::fixed_vector(3, 32);
diff --git a/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp b/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp
index 31ec0e34a0661..c532634c19817 100644
--- a/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp
+++ b/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/CodeGen/GlobalISel/IRTranslator.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/AsmParser/Parser.h"
+#include "llvm/CodeGen/GlobalISel/IRTranslator.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
@@ -46,7 +46,7 @@ struct AArch64IRTranslatorTest : public ::testing::Test {
TargetOptions Options;
return std::unique_ptr<TargetMachine>(
T->createTargetMachine(TargetTriple, "", "", Options, std::nullopt,
- std::nullopt, CodeGenOptLevel::Aggressive));
+ std::nullopt, CodeGenOptLevel::Aggressive));
}
std::unique_ptr<Module> parseIR(const char *IR) {
@@ -96,7 +96,8 @@ TEST_F(AArch64IRTranslatorTest, IRTranslateBfloat16) {
legacy::PassManager PM;
TargetPassConfig *TPC(TM->createPassConfig(PM));
- MachineModuleInfoWrapperPass *MMIWP = new MachineModuleInfoWrapperPass(TM.get());
+ MachineModuleInfoWrapperPass *MMIWP =
+ new MachineModuleInfoWrapperPass(TM.get());
PM.add(TPC);
PM.add(MMIWP);
PM.add(new IRTranslator());
@@ -126,5 +127,6 @@ TEST_F(AArch64IRTranslatorTest, IRTranslateBfloat16) {
TM->setGlobalISelExtendedLLT(false);
PM.run(*M);
MF = MMI->getMachineFunction(*F);
- ASSERT_TRUE(MF->getProperties().hasProperty(llvm::MachineFunctionProperties::Property::FailedISel));
+ ASSERT_TRUE(MF->getProperties().hasProperty(
+ llvm::MachineFunctionProperties::Property::FailedISel));
}
>From d8c9da0763fc54a65b6f433d90af1204ca3abddf Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Mon, 8 Sep 2025 14:46:59 +0300
Subject: [PATCH 10/40] style
---
.../TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
index 1a624957d5efc..3bee2568e69dc 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
+++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
@@ -24,10 +24,10 @@ STATISTIC(NumPatternEmitted, "Number of patterns emitted");
using namespace llvm;
using namespace gi;
-static llvm::cl::opt<bool> AllowExtendedLLT(
- "gisel-extended-llt",
- llvm::cl::desc("Generate an extended llt names in match tables"),
- llvm::cl::init(false));
+static cl::opt<bool>
+ AllowExtendedLLT("gisel-extended-llt",
+ cl::desc("Generate an extended llt names in match tables"),
+ cl::init(false));
// FIXME: Use createStringError instead.
static Error failUnsupported(const Twine &Reason) {
>From 7c5f7d226eb0631f1c3b79bc8881fe40a2a6f95b Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Sun, 14 Sep 2025 17:27:28 +0300
Subject: [PATCH 11/40] style
---
llvm/lib/CodeGen/MIRParser/MIParser.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 94205698c5038..56dcb64feb30d 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -1968,13 +1968,13 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
if (Token.range().starts_with("f") || Token.range().starts_with("bf")) {
LLT::FPVariant FPVariant;
- if (Token.range().starts_with("f")) {
+ if (Token.range().starts_with("f"))
FPVariant = LLT::FPVariant::IEEE_FLOAT;
- } else if (Token.range().starts_with("bf")) {
+ else if (Token.range().starts_with("bf"))
FPVariant = LLT::FPVariant::BRAIN_FLOAT;
- } else {
+ else
return error("unknown floating point type identifier");
- }
+
auto ScalarSize = APSInt(TypeDigits).getZExtValue();
if (!ScalarSize || !verifyScalarSize(ScalarSize))
return error("invalid size for scalar type");
>From e1f805c031ec41315018307c33459372cf191ce4 Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Sat, 20 Sep 2025 00:29:20 +0300
Subject: [PATCH 12/40] Review fixes
---
llvm/include/llvm/CodeGen/TargetLowering.h | 8 +-
llvm/include/llvm/CodeGenTypes/LowLevelType.h | 153 +++++++++---------
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 3 +-
llvm/lib/CodeGen/LowLevelTypeUtils.cpp | 6 +-
llvm/lib/CodeGen/MIRParser/MIParser.cpp | 4 +-
llvm/lib/CodeGenTypes/LowLevelType.cpp | 2 +-
6 files changed, 87 insertions(+), 89 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 9bfac318ff595..03db625ce840b 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -417,8 +417,12 @@ class LLVM_ABI TargetLoweringBase {
/// amounts, returns MVT::i32.
EVT getShiftAmountTy(EVT LHSTy, const DataLayout &DL) const;
- virtual LLT getLLTForType(Type &Ty, const DataLayout &DL) const;
- virtual LLT getLLTForMVT(MVT Ty) const;
+ /// Returns LLT for given Type, taking into account
+ /// TargetOptions::EnableGlobalISelExtendedLLT.
+ LLT getLLTForType(Type &Ty, const DataLayout &DL) const;
+ /// Returns LLT for given MVT, taking into account
+ /// TargetOptions::EnableGlobalISelExtendedLLT.
+ LLT getLLTForMVT(MVT Ty) const;
/// Return the preferred type to use for a shift opcode, given the shifted
/// amount type is \p ShiftValueTy.
diff --git a/llvm/include/llvm/CodeGenTypes/LowLevelType.h b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
index 0d074f3413c1c..31ac31d36e4a2 100644
--- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h
+++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
@@ -40,26 +40,26 @@ class raw_ostream;
class LLT {
public:
enum class FPVariant {
- IEEE_FLOAT = 0x0,
- BRAIN_FLOAT = 0x1, // BRAIN_FLOAT
- PPC128_FLOAT = 0x2, // PPC128_FLOAT
- EXTENDED_FP80 = 0x3, // FP80
- TENSOR_FLOAT32 = 0x4, // TENSOR_FLOAT32
- VARIANT_FLOAT_5 = 0x5, // UNASSIGNED
- VARIANT_FLOAT_6 = 0x6, // UNASSIGNED
- VARIANT_FLOAT_7 = 0x7, // UNASSIGNED
+ IEEE_FLOAT,
+ BF16, // BF16
+ TENSOR_FLOAT32, // TENSOR_FLOAT32
+ EXTENDED_FP80, // FP80
+ PPC128_FLOAT, // PPC128_FLOAT
+ VARIANT_FLOAT_5, // UNASSIGNED
+ VARIANT_FLOAT_6, // UNASSIGNED
+ VARIANT_FLOAT_7, // UNASSIGNED
};
- enum class Kind : uint64_t {
- INVALID = 0b0000,
- ANY_SCALAR = 0b0001,
- INTEGER = 0b0010,
- FLOAT = 0b0011,
- POINTER = 0b0100,
- VECTOR_ANY = 0b0101,
- VECTOR_INTEGER = 0b0110,
- VECTOR_FLOAT = 0b0111,
- VECTOR_POINTER = 0b1000,
+ enum class Kind : uint8_t {
+ INVALID,
+ ANY_SCALAR,
+ INTEGER,
+ FLOAT,
+ POINTER,
+ VECTOR_ANY,
+ VECTOR_INTEGER,
+ VECTOR_FLOAT,
+ VECTOR_POINTER,
};
constexpr static Kind toVector(Kind Ty) {
@@ -136,15 +136,9 @@ class LLT {
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 bfloat16 value.
+ static constexpr LLT bfloat16() { return floatingPoint(16, FPVariant::BF16); }
/// Get a 16-bit IEEE half value.
static constexpr LLT float16() {
@@ -231,7 +225,7 @@ class LLT {
constexpr bool isScalar(unsigned Size) const {
return isScalar() && getScalarSizeInBits() == Size;
}
- constexpr bool isFloat() const { return isValid() && Info == Kind::FLOAT; }
+ constexpr bool isFloat() const { return Info == Kind::FLOAT; }
constexpr bool isFloat(unsigned Size) const {
return isFloat() && getScalarSizeInBits() == Size;
}
@@ -244,14 +238,12 @@ class LLT {
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 isFloatVector() const { return 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);
+ return isVariantFloat(Size, FPVariant::BF16);
}
constexpr bool isX86FP80() const {
return isVariantFloat(80, FPVariant::EXTENDED_FP80);
@@ -262,31 +254,22 @@ class LLT {
constexpr bool isToken() const {
return Info == Kind::ANY_SCALAR && RawData == 0;
}
- constexpr bool isAnyScalar() const {
- return isValid() && Info == Kind::ANY_SCALAR;
- }
- constexpr bool isVectorAny() const {
- return isVector() && Info == Kind::VECTOR_ANY;
- }
- constexpr bool isInteger() const {
- return isValid() && Info == Kind::INTEGER;
- }
+ constexpr bool isAnyScalar() const { return Info == Kind::ANY_SCALAR; }
+ constexpr bool isVectorAny() const { return Info == Kind::VECTOR_ANY; }
+ constexpr bool isInteger() const { return Info == Kind::INTEGER; }
constexpr bool isInteger(unsigned Size) const {
return isInteger() && getScalarSizeInBits() == Size;
}
constexpr bool isIntegerVector() const {
- return isVector() && Info == Kind::VECTOR_INTEGER;
+ return Info == Kind::VECTOR_INTEGER;
}
constexpr bool isVector() const {
- return isValid() &&
- (Info == Kind::VECTOR_ANY || Info == Kind::VECTOR_INTEGER ||
- Info == Kind::VECTOR_FLOAT || Info == Kind::VECTOR_POINTER);
- }
- constexpr bool isPointer() const {
- return isValid() && Info == Kind::POINTER;
+ return Info == Kind::VECTOR_ANY || Info == Kind::VECTOR_INTEGER ||
+ Info == Kind::VECTOR_FLOAT || Info == Kind::VECTOR_POINTER;
}
+ constexpr bool isPointer() const { return Info == Kind::POINTER; }
constexpr bool isPointerVector() const {
- return isVector() && Info == Kind::VECTOR_POINTER;
+ return Info == Kind::VECTOR_POINTER;
}
constexpr bool isPointerOrPointerVector() const {
return isPointer() || isPointerVector();
@@ -469,13 +452,13 @@ class LLT {
#endif
constexpr bool operator==(const LLT &RHS) const {
- if (isAnyScalar() || RHS.isAnyScalar()) {
+ if (isAnyScalar() || RHS.isAnyScalar())
return isScalar() == RHS.isScalar() && RawData == RHS.RawData;
- }
- if (isVector() && RHS.isVector()) {
+
+ if (isVector() && RHS.isVector())
return getElementType() == RHS.getElementType() &&
getElementCount() == RHS.getElementCount();
- }
+
return Info == RHS.Info && RawData == RHS.RawData;
}
@@ -488,7 +471,7 @@ class LLT {
/// LLT is packed into 64 bits as follows:
/// Info : 4
/// RawData : 60
- /// with 61 bits of RawData remaining for Kind-specific data, packed in
+ /// with 60 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
@@ -509,38 +492,52 @@ class LLT {
### (6)
%%%% (7)
- (1) ScalarSize (2) PointerSize (3) PointerAddressSpace
- (4) VectorElements (5) VectorScalable (6) FPVariant (7) Kind
+ (1) ScalarSize: [63:32]
+ (2) PointerSize: [63:48]
+ (3) PointerAddressSpace: [47:24]
+ (4) VectorElements: [23:8]
+ (5) VectorScalable: [4:4]
+ (6) FPVariant: [26:24]
+ (7) Kind: [3:0]
*/
- typedef int BitFieldInfo[2];
- ///
- /// This is how the bitfields are packed per Kind:
+
+ /// This is how the LLT are packed per Kind:
/// * Invalid:
- /// gets encoded as RawData == 0, as that is an invalid encoding, since for
- /// valid encodings, SizeInBits/SizeOfElement must be larger than 0.
+ /// Info: [3:0] = 0
+ /// RawData: [63:4] = 0;
+ ///
/// * Non-pointer scalar (isPointer == 0 && isVector == 0):
- /// SizeInBits: 32;
- /// FPInfoField: 3;
- static const constexpr BitFieldInfo ScalarSizeFieldInfo{32, 28};
- static const constexpr BitFieldInfo FPFieldInfo{3, 20};
+ /// Info: [3:0];
+ /// FPVariant: [26:24];
+ /// SizeOfElement: [63:32];
+ ///
/// * Pointer (isPointer == 1 && isVector == 0):
- /// SizeInBits: 16;
- /// AddressSpace: 24;
- static const constexpr BitFieldInfo PointerSizeFieldInfo{16, 44};
- static const constexpr BitFieldInfo PointerAddressSpaceFieldInfo{24, 20};
+ /// Info: [3:0];
+ /// AddressSpace: [47:24];
+ /// SizeInBits: [63:48];
+ ///
/// * Vector-of-non-pointer (isPointer == 0 && isVector == 1):
- /// NumElements: 16;
- /// SizeOfElement: 32;
- /// FPInfoField: 3;
- /// Scalable: 1;
- static const constexpr BitFieldInfo VectorElementsFieldInfo{16, 4};
- static const constexpr BitFieldInfo VectorScalableFieldInfo{1, 0};
+ /// Info: [3:0]
+ /// Scalable: [4:4];
+ /// VectorElements: [23:8];
+ /// FPVariant: [26:24];
+ /// SizeOfElement: [63:32];
+ ///
/// * Vector-of-pointer (isPointer == 1 && isVector == 1):
- /// NumElements: 16;
- /// SizeOfElement: 16;
- /// AddressSpace: 24;
- /// Scalable: 1;
+ /// Scalable: [4:4];
+ /// VectorElements: [23:8];
+ /// AddressSpace: [47:24];
+ /// SizeInBits: [63:48];
+
+ /// BitFieldInfo: {Size, Offset}
+ typedef int BitFieldInfo[2];
+ static const constexpr BitFieldInfo VectorScalableFieldInfo{1, 0};
+ static const constexpr BitFieldInfo VectorElementsFieldInfo{16, 4};
+ static const constexpr BitFieldInfo FPFieldInfo{3, 20};
+ static const constexpr BitFieldInfo PointerAddressSpaceFieldInfo{24, 20};
+ static const constexpr BitFieldInfo ScalarSizeFieldInfo{32, 28};
+ static const constexpr BitFieldInfo PointerSizeFieldInfo{16, 44};
Kind Info : 4;
uint64_t RawData : 60;
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index ad1fb6331186e..7f48922ecfbef 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -3723,9 +3723,8 @@ bool IRTranslator::translate(const Constant &C, Register Reg) {
}
bool IRTranslator::mayTranslateUserTypes(const User &U) const {
- if (TLI->getTargetMachine().Options.EnableGlobalISelExtendedLLT) {
+ if (TLI->getTargetMachine().Options.EnableGlobalISelExtendedLLT)
return true;
- }
// BF16 cannot currently be represented by default LLT, to avoid miscompiles
// we prevent any instructions using them in targets with disabled
diff --git a/llvm/lib/CodeGen/LowLevelTypeUtils.cpp b/llvm/lib/CodeGen/LowLevelTypeUtils.cpp
index 6a15b1748630d..57265b048125d 100644
--- a/llvm/lib/CodeGen/LowLevelTypeUtils.cpp
+++ b/llvm/lib/CodeGen/LowLevelTypeUtils.cpp
@@ -67,9 +67,8 @@ LLT llvm::getLLTForType(Type &Ty, const DataLayout &DL, bool AllowExtendedLLT) {
llvm_unreachable("Unhandled LLVM IR floating point type");
}
- if (Ty.isIntegerTy()) {
+ if (Ty.isIntegerTy())
return LLT::integer(SizeInBits);
- }
return LLT::scalar(SizeInBits);
}
@@ -81,10 +80,9 @@ LLT llvm::getLLTForType(Type &Ty, const DataLayout &DL, bool AllowExtendedLLT) {
}
MVT llvm::getMVTForLLT(LLT Ty) {
- if (Ty.isVector()) {
+ if (Ty.isVector())
return MVT::getVectorVT(getMVTForLLT(Ty.getElementType()),
Ty.getElementCount());
- }
if (Ty.isFloat()) {
if (Ty == LLT::bfloat16())
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 56dcb64feb30d..2e69ec6691591 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -1971,7 +1971,7 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
if (Token.range().starts_with("f"))
FPVariant = LLT::FPVariant::IEEE_FLOAT;
else if (Token.range().starts_with("bf"))
- FPVariant = LLT::FPVariant::BRAIN_FLOAT;
+ FPVariant = LLT::FPVariant::BF16;
else
return error("unknown floating point type identifier");
@@ -2053,7 +2053,7 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
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);
+ Ty = LLT::floatingPoint(ScalarSize, LLT::FPVariant::BF16);
} else
return GetError();
lex();
diff --git a/llvm/lib/CodeGenTypes/LowLevelType.cpp b/llvm/lib/CodeGenTypes/LowLevelType.cpp
index 6025f3fedafa1..c5995c179fa72 100644
--- a/llvm/lib/CodeGenTypes/LowLevelType.cpp
+++ b/llvm/lib/CodeGenTypes/LowLevelType.cpp
@@ -22,7 +22,7 @@ static std::optional<LLT::FPVariant> deriveFPInfo(MVT VT) {
switch (VT.getScalarType().SimpleTy) {
case MVT::bf16:
- return LLT::FPVariant::BRAIN_FLOAT;
+ return LLT::FPVariant::BF16;
case MVT::f80:
return LLT::FPVariant::EXTENDED_FP80;
case MVT::ppcf128:
>From d37eeb8c826eb2c27e93c8b1aba9b88c8e1dea1f Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Mon, 22 Sep 2025 23:56:05 +0300
Subject: [PATCH 13/40] typo
---
llvm/include/llvm/Target/TargetOptions.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h
index 0b81ded79c0b1..fff27c9601810 100644
--- a/llvm/include/llvm/Target/TargetOptions.h
+++ b/llvm/include/llvm/Target/TargetOptions.h
@@ -230,7 +230,7 @@ class TargetOptions {
/// EnableGlobalISel - This flag enables global instruction selection.
unsigned EnableGlobalISel : 1;
- /// EnableGlobalISelExtendedLLT - This flag enables LLTs with extenden type
+ /// EnableGlobalISelExtendedLLT - This flag enables LLTs with extended type
/// info so target may distinguish different formats of equal sized scalars.
unsigned EnableGlobalISelExtendedLLT : 1;
>From aba146b8deaf34186468ff24912cb7b2d5d65a40 Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Tue, 23 Sep 2025 13:08:58 +0300
Subject: [PATCH 14/40] Small fix in test
---
llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp b/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp
index c532634c19817..079f8dea377e0 100644
--- a/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp
+++ b/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp
@@ -111,13 +111,13 @@ TEST_F(AArch64IRTranslatorTest, IRTranslateBfloat16) {
llvm::MachineFunctionProperties::Property::FailedISel));
for (auto &MI : MF->front()) {
if (MI.getOpcode() == TargetOpcode::G_LOAD) {
- ASSERT_EQ(MRI.getType(MI.getOperand(0).getReg()), LLT::bfloat16());
+ ASSERT_TRUE(MRI.getType(MI.getOperand(0).getReg()).isBFloat(16));
}
if (MI.getOpcode() == TargetOpcode::G_FADD ||
MI.getOpcode() == TargetOpcode::G_FMUL) {
for (auto &Op : MI.operands()) {
- ASSERT_EQ(MRI.getType(Op.getReg()), LLT::bfloat16());
+ ASSERT_TRUE(MRI.getType(Op.getReg()).isBFloat(16));
}
}
}
>From a72d2a3f5066e609e51d50a90f62a80c5174149b Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Thu, 16 Oct 2025 14:58:08 +0300
Subject: [PATCH 15/40] Fixed misprints
---
.../TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
index efd2a99f7104b..e689a2d3be283 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
+++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
@@ -26,7 +26,7 @@ using namespace gi;
static cl::opt<bool>
AllowExtendedLLT("gisel-extended-llt",
- cl::desc("Generate an extended llt names in match tables"),
+ cl::desc("Generate extended llt names in match tables"),
cl::init(false));
// FIXME: Use createStringError instead.
@@ -418,7 +418,7 @@ void LLTCodeGen::emitCxxConstructorCall(raw_ostream &OS) const {
if (Ty.isInteger())
OS << "LLT::integer(" << Ty.getScalarSizeInBits() << ")";
else if (Ty.isBFloat(16))
- OS << "LLT::bfloat()";
+ OS << "LLT::bfloat16()";
else if (Ty.isPPCF128())
OS << "LLT::ppcf128()";
else if (Ty.isX86FP80())
@@ -441,7 +441,7 @@ void LLTCodeGen::emitCxxConstructorCall(raw_ostream &OS) const {
if (ElemTy.isInteger())
OS << "LLT::integer(" << ElemTy.getScalarSizeInBits() << ")";
else if (ElemTy.isBFloat(16))
- OS << "LLT::bfloat()";
+ OS << "LLT::bfloat16()";
else if (ElemTy.isPPCF128())
OS << "LLT::ppcf128()";
else if (ElemTy.isX86FP80())
>From ce75915901e25a69bf6278f36ae525d112313e23 Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Fri, 17 Oct 2025 16:12:29 +0300
Subject: [PATCH 16/40] Restructure LLT packed data. LLTCodeGen compare now
uses `getUniqueRAWLLTData`. Added simple test for GlobalSelEmitter
---
llvm/include/llvm/CodeGenTypes/LowLevelType.h | 73 ++++++++++---------
.../GlobalISelEmitter/GlobalISelEmitter.td | 36 ++++++++-
.../TableGen/GlobalISelEmitter/HwModes.td | 10 +--
.../GlobalISel/GlobalISelMatchTable.cpp | 31 +-------
4 files changed, 76 insertions(+), 74 deletions(-)
diff --git a/llvm/include/llvm/CodeGenTypes/LowLevelType.h b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
index 31ac31d36e4a2..04e19d03c7c37 100644
--- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h
+++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
@@ -469,9 +469,9 @@ class LLT {
private:
/// LLT is packed into 64 bits as follows:
- /// Info : 4
/// RawData : 60
- /// with 60 bits of RawData remaining for Kind-specific data, packed in
+ /// Info : 4
+ /// 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
@@ -484,51 +484,52 @@ class 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: [63:32]
- (2) PointerSize: [63:48]
- (3) PointerAddressSpace: [47:24]
- (4) VectorElements: [23:8]
- (5) VectorScalable: [4:4]
- (6) FPVariant: [26:24]
- (7) Kind: [3:0]
+ %%%% (1)
+ .... ........ ........ ........ .... (2)
+ **** ******** **** (3)
+ ~~~~ ~~~~~~~~ ~~~~~~~~ ~~~~ (4)
+ ### (5)
+ ^^^^ ^^^^^^^^ ^^^^ (6)
+ @ (7)
+
+ (1) Kind: [63:60]
+ (2) ScalarSize: [59:28]
+ (3) PointerSize: [59:44]
+ (4) PointerAddressSpace: [43:20]
+ (5) FPVariant: [22:20]
+ (6) VectorElements: [19:4]
+ (7) VectorScalable: [0:0]
*/
/// This is how the LLT are packed per Kind:
/// * Invalid:
- /// Info: [3:0] = 0
- /// RawData: [63:4] = 0;
+ /// Info: [63:60] = 0
+ /// RawData: [59:0] = 0;
///
/// * Non-pointer scalar (isPointer == 0 && isVector == 0):
- /// Info: [3:0];
- /// FPVariant: [26:24];
- /// SizeOfElement: [63:32];
+ /// Info: [63:60];
+ /// SizeOfElement: [59:28];
+ /// FPVariant: [22:20];
///
/// * Pointer (isPointer == 1 && isVector == 0):
- /// Info: [3:0];
- /// AddressSpace: [47:24];
- /// SizeInBits: [63:48];
+ /// Info: [63:60];
+ /// SizeInBits: [59:44];
+ /// AddressSpace: [43:20];
///
/// * Vector-of-non-pointer (isPointer == 0 && isVector == 1):
- /// Info: [3:0]
- /// Scalable: [4:4];
- /// VectorElements: [23:8];
- /// FPVariant: [26:24];
- /// SizeOfElement: [63:32];
+ /// Info: [63:60]
+ /// SizeOfElement: [59:28];
+ /// FPVariant: [22:20];
+ /// VectorElements: [19:4];
+ /// Scalable: [0:0];
///
/// * Vector-of-pointer (isPointer == 1 && isVector == 1):
- /// Scalable: [4:4];
- /// VectorElements: [23:8];
- /// AddressSpace: [47:24];
- /// SizeInBits: [63:48];
+ /// Info: [63:60];
+ /// SizeInBits: [59:44];
+ /// AddressSpace: [43:20];
+ /// VectorElements: [19:4];
+ /// Scalable: [0:0];
/// BitFieldInfo: {Size, Offset}
typedef int BitFieldInfo[2];
@@ -539,8 +540,8 @@ class LLT {
static const constexpr BitFieldInfo ScalarSizeFieldInfo{32, 28};
static const constexpr BitFieldInfo PointerSizeFieldInfo{16, 44};
- Kind Info : 4;
uint64_t RawData : 60;
+ Kind Info : 4;
static constexpr uint64_t getMask(const BitFieldInfo FieldInfo) {
const int FieldSizeInBits = FieldInfo[0];
@@ -582,7 +583,7 @@ class LLT {
public:
constexpr uint64_t getUniqueRAWLLTData() const {
- return ((uint64_t)RawData) << 4 | ((uint64_t)Info);
+ return ((uint64_t)RawData) | ((uint64_t)Info) << 60;
}
};
diff --git a/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td b/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
index fdabc53a3ff3b..d889523950a91 100644
--- a/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
+++ b/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
@@ -1,6 +1,7 @@
// RUN: llvm-tblgen -gen-global-isel -I %p/../../../include -I %p/../Common -optimize-match-table=false %s -o %t.non-optimized.cpp
// RUN: llvm-tblgen -gen-global-isel -I %p/../../../include -I %p/../Common -optimize-match-table=true %s -o %t.optimized.cpp
// RUN: llvm-tblgen -gen-global-isel -I %p/../../../include -I %p/../Common %s -o %t.default.cpp
+// RUN: llvm-tblgen -gen-global-isel -I %p/../../../include -I %p/../Common -gisel-extended-llt %s -o %t.extended-llt.cpp
// RUN: FileCheck %s --check-prefixes=CHECK,R19C,R19N -input-file=%t.non-optimized.cpp
// RUN: FileCheck %s --check-prefixes=CHECK,R19C,R19O -input-file=%t.optimized.cpp
@@ -19,6 +20,7 @@
// RUN: FileCheck %s --check-prefixes=CHECK,R02C,R02N,NOOPT -input-file=%t.non-optimized.cpp
// RUN: FileCheck %s --check-prefixes=CHECK,R02C,R02O -input-file=%t.optimized.cpp
+// RUN: FileCheck %s --check-prefixes=EXTENDED -input-file=%t.extended-llt.cpp
// RUN: diff %t.default.cpp %t.optimized.cpp
@@ -94,15 +96,28 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
// CHECK-LABEL: // LLT Objects.
// CHECK-NEXT: enum {
-// CHECK-NEXT: GILLT_p0s32
// CHECK-NEXT: GILLT_s32,
-// CHECK-NEXT: }
+// CHECK-NEXT: GILLT_p0s32,
+// CHECK-NEXT: };
// CHECK-NEXT: const static size_t NumTypeObjects = 2;
// CHECK-NEXT: const static LLT TypeObjects[] = {
-// CHECK-NEXT: LLT::pointer(0, 32),
// CHECK-NEXT: LLT::scalar(32),
+// CHECK-NEXT: LLT::pointer(0, 32),
// CHECK-NEXT: };
+// EXTENDED-LABEL: // LLT Objects.
+// EXTENDED-NEXT: enum {
+// EXTENDED-NEXT: GILLT_i32,
+// EXTENDED-NEXT: GILLT_f32,
+// EXTENDED-NEXT: GILLT_p0s32,
+// EXTENDED-NEXT: };
+// EXTENDED-NEXT: const static size_t NumTypeObjects = 3;
+// EXTENDED-NEXT: const static LLT TypeObjects[] = {
+// EXTENDED-NEXT: LLT::integer(32),
+// EXTENDED-NEXT: LLT::floatingPoint(32, LLT::FPVariant::IEEE_FLOAT),
+// EXTENDED-NEXT: LLT::pointer(0, 32),
+// EXTENDED-NEXT: };
+
// CHECK-LABEL: enum SubtargetFeatureBits : uint8_t {
// CHECK-NEXT: Feature_HasABit = 0,
// CHECK-NEXT: Feature_HasBBit = 1,
@@ -251,6 +266,10 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
// CHECK-LABEL: MyTargetInstructionSelector::getMatchTable() const {
// CHECK-NEXT: MatchTable0[] = {
+// EXTENDED: const uint8_t *
+// EXTENDED-LABEL: MyTargetInstructionSelector::getMatchTable() const {
+// EXTENDED-NEXT: MatchTable0[] = {
+
//===- Test a pattern with multiple ComplexPatterns in multiple instrs ----===//
//
// R19O-NEXT: GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2({{[0-9]+}}), GIMT_Encode2({{[0-9]+}}), /*)*//*default:*//*Label [[DEFAULT_NUM:[0-9]+]]*/ GIMT_Encode4([[DEFAULT:[0-9]+]]),
@@ -328,6 +347,17 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
// R19O: // Label [[DEFAULT_NUM]]: @[[DEFAULT]]
// R19O-NEXT: GIM_Reject,
// R19O-NEXT: };
+//
+// EXTENDED-NEXT: GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2({{[0-9]+}}), GIMT_Encode2({{[0-9]+}}), /*)*//*default:*//*Label [[DEFAULT_NUM:[0-9]+]]*/ GIMT_Encode4([[DEFAULT:[0-9]+]]),
+// EXTENDED-NEXT: /*TargetOpcode::G_ADD*//*Label [[CASE_ADD_NUM:[0-9]+]]*/ GIMT_Encode4([[CASE_ADD:[0-9]+]]),
+// EXTENDED: /*TargetOpcode::G_SELECT*//*Label [[CASE_SELECT_NUM:[0-9]+]]*/ GIMT_Encode4([[CASE_SELECT:[0-9]+]]),
+// EXTENDED: // Label [[CASE_ADD_NUM]]: @[[CASE_ADD]]
+// EXTENDED: // Label [[CASE_SELECT_NUM]]: @[[CASE_SELECT]]
+// EXTENDED-NEXT: GIM_Try, /*On fail goto*//*Label [[GROUP_NUM:[0-9]+]]*/ GIMT_Encode4([[GROUP:[0-9]+]]),
+// EXTENDED-NEXT: GIM_RootCheckType, /*Op*/0, /*Type*/GILLT_i32,
+// EXTENDED-NEXT: GIM_RootCheckType, /*Op*/1, /*Type*/GILLT_i32,
+// EXTENDED-NEXT: GIM_RootCheckType, /*Op*/2, /*Type*/GILLT_i32,
+// EXTENDED-NEXT: GIM_RootCheckType, /*Op*/3, /*Type*/GILLT_i32,
def INSN3 : I<(outs GPR32:$dst),
(ins GPR32Op:$src1, GPR32:$src2a, GPR32:$src2b, GPR32:$scr), []>;
diff --git a/llvm/test/TableGen/GlobalISelEmitter/HwModes.td b/llvm/test/TableGen/GlobalISelEmitter/HwModes.td
index 56d62ca070889..00be337183b07 100644
--- a/llvm/test/TableGen/GlobalISelEmitter/HwModes.td
+++ b/llvm/test/TableGen/GlobalISelEmitter/HwModes.td
@@ -66,17 +66,17 @@ class I<dag OOps, dag IOps, list<dag> Pat>
// CHECK-LABEL: // LLT Objects.
// CHECK-NEXT: enum {
-// CHECK-NEXT: GILLT_p0s32,
-// CHECK-NEXT: GILLT_p0s64,
// CHECK-NEXT: GILLT_s32,
// CHECK-NEXT: GILLT_s64,
-// CHECK-NEXT: }
+// CHECK-NEXT: GILLT_p0s32,
+// CHECK-NEXT: GILLT_p0s64,
+// CHECK-NEXT: };
// CHECK-NEXT: const static size_t NumTypeObjects = 4;
// CHECK-NEXT: const static LLT TypeObjects[] = {
-// CHECK-NEXT: LLT::pointer(0, 32),
-// CHECK-NEXT: LLT::pointer(0, 64),
// CHECK-NEXT: LLT::scalar(32),
// CHECK-NEXT: LLT::scalar(64),
+// CHECK-NEXT: LLT::pointer(0, 32),
+// CHECK-NEXT: LLT::pointer(0, 64),
// CHECK-NEXT: };
// CHECK-LABEL: enum SubtargetFeatureBits : uint8_t {
diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
index e689a2d3be283..c5cdea5c1c753 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
+++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
@@ -468,36 +468,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 -------------------------------------------------===//
>From 74e1cf875244f6de889ce138ea667e0dbb4bb158 Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Fri, 17 Oct 2025 16:39:32 +0300
Subject: [PATCH 17/40] initialization fix
---
llvm/include/llvm/CodeGenTypes/LowLevelType.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/include/llvm/CodeGenTypes/LowLevelType.h b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
index 04e19d03c7c37..aac77737c411f 100644
--- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h
+++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
@@ -215,7 +215,7 @@ class LLT {
}
LLVM_ABI explicit LLT(MVT VT, bool AllowExtendedLLT = false);
- explicit constexpr LLT() : Info(static_cast<Kind>(0)), RawData(0) {}
+ explicit constexpr LLT() : RawData(0), Info(static_cast<Kind>(0)) {}
constexpr bool isValid() const { return isToken() || RawData != 0; }
constexpr bool isScalar() const {
>From 664b6445c7b5a146297cf2c61675d708616b0334 Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Thu, 30 Oct 2025 15:36:58 +0300
Subject: [PATCH 18/40] Link CodeGenTypes to TableGenCommon
---
llvm/utils/TableGen/Common/CMakeLists.txt | 3 +++
1 file changed, 3 insertions(+)
diff --git a/llvm/utils/TableGen/Common/CMakeLists.txt b/llvm/utils/TableGen/Common/CMakeLists.txt
index 66279a3ed3755..b49f36b937c42 100644
--- a/llvm/utils/TableGen/Common/CMakeLists.txt
+++ b/llvm/utils/TableGen/Common/CMakeLists.txt
@@ -43,6 +43,9 @@ add_llvm_library(LLVMTableGenCommon STATIC OBJECT EXCLUDE_FROM_ALL DISABLE_LLVM_
DEPENDS
vt_gen
intrinsics_gen
+
+ LINK_COMPONENTS
+ CodeGenTypes
)
# Users may include its headers as "Common/*.h"
>From cb0dc5fc83f4d7c6bd2eb91fe114c59f165d414d Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Mon, 10 Nov 2025 20:59:15 +0300
Subject: [PATCH 19/40] Fix misprint
---
llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
index 696bd64c22d13..525f222d4ae25 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
+++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
@@ -396,7 +396,7 @@ void LLTCodeGen::emitCxxEnumValue(raw_ostream &OS) const {
OS << "x86fp80";
else if (ElemTy.isFloat())
OS << "f" << ElemTy.getSizeInBits();
- else if (Ty.isInteger())
+ else if (ElemTy.isInteger())
OS << "i" << ElemTy.getSizeInBits();
else
OS << "s" << ElemTy.getSizeInBits();
>From e076732fe2304e8e4d1d6dbd8c1fc7e8aba9d36f Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Tue, 11 Nov 2025 15:04:57 +0300
Subject: [PATCH 20/40] format
---
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 097362cf86956..d7c5508aec27a 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -3820,9 +3820,9 @@ bool IRTranslator::mayTranslateUserTypes(const User &U) const {
// SPIRV target is exception.
return TM.getTargetTriple().isSPIRV() ||
(!U.getType()->getScalarType()->isBFloatTy() &&
- !any_of(U.operands(), [](Value *V) {
- return V->getType()->getScalarType()->isBFloatTy();
- }));
+ !any_of(U.operands(), [](Value *V) {
+ return V->getType()->getScalarType()->isBFloatTy();
+ }));
}
bool IRTranslator::finalizeBasicBlock(const BasicBlock &BB,
>From 24c0af1925527b0ec8ca6859bf7dafc0283fc6dc Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Sat, 15 Nov 2025 16:08:25 +0300
Subject: [PATCH 21/40] Replace FPVariant with APFloat::Semantics
---
llvm/include/llvm/CodeGenTypes/LowLevelType.h | 189 ++++++++++--------
llvm/lib/CodeGen/LowLevelTypeUtils.cpp | 34 ++--
llvm/lib/CodeGen/MIRParser/MIParser.cpp | 19 +-
llvm/lib/CodeGenTypes/LowLevelType.cpp | 47 +++--
.../lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp | 12 +-
.../GlobalISelEmitter/GlobalISelEmitter.td | 2 +-
.../GlobalISel/IRTranslatorBF16Test.cpp | 4 +-
.../GlobalISel/GlobalISelMatchTable.cpp | 14 +-
8 files changed, 166 insertions(+), 155 deletions(-)
diff --git a/llvm/include/llvm/CodeGenTypes/LowLevelType.h b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
index 80e4aae388c71..1456700ce0bb1 100644
--- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h
+++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
@@ -26,10 +26,13 @@
#ifndef LLVM_CODEGEN_LOWLEVELTYPE_H
#define LLVM_CODEGEN_LOWLEVELTYPE_H
+#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/bit.h"
#include "llvm/CodeGenTypes/MachineValueType.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
#include <cassert>
namespace llvm {
@@ -39,16 +42,7 @@ class raw_ostream;
class LLT {
public:
- enum class FPVariant {
- IEEE_FLOAT,
- BF16, // BF16
- TENSOR_FLOAT32, // TENSOR_FLOAT32
- EXTENDED_FP80, // FP80
- PPC128_FLOAT, // PPC128_FLOAT
- VARIANT_FLOAT_5, // UNASSIGNED
- VARIANT_FLOAT_6, // UNASSIGNED
- VARIANT_FLOAT_7, // UNASSIGNED
- };
+ using FpSemantics = APFloat::Semantics;
enum class Kind : uint8_t {
INVALID,
@@ -91,38 +85,39 @@ class LLT {
/// Get a low-level scalar or aggregate "bag of bits".
static constexpr LLT scalar(unsigned SizeInBits) {
return LLT{Kind::ANY_SCALAR, ElementCount::getFixed(0), SizeInBits,
- /*AddressSpace=*/0, static_cast<FPVariant>(0)};
+ /*AddressSpace=*/0, static_cast<FpSemantics>(0)};
}
static constexpr LLT integer(unsigned SizeInBits) {
return LLT{Kind::INTEGER, ElementCount::getFixed(0), SizeInBits,
- /*AddressSpace=*/0, static_cast<FPVariant>(0)};
+ /*AddressSpace=*/0, static_cast<FpSemantics>(0)};
}
- static constexpr LLT floatingPoint(unsigned SizeInBits, FPVariant FP) {
- return LLT{Kind::FLOAT, ElementCount::getFixed(0), SizeInBits,
- /*AddressSpace=*/0, FP};
+ static LLT floatingPoint(const FpSemantics &Sem) {
+ return LLT{Kind::FLOAT, ElementCount::getFixed(0),
+ APFloat::getSizeInBits(APFloatBase::EnumToSemantics(Sem)),
+ /*AddressSpace=*/0, Sem};
}
/// Get a low-level token; just a scalar with zero bits (or no size).
static constexpr LLT token() {
return LLT{Kind::ANY_SCALAR, ElementCount::getFixed(0),
/*SizeInBits=*/0,
- /*AddressSpace=*/0, static_cast<FPVariant>(0)};
+ /*AddressSpace=*/0, static_cast<FpSemantics>(0)};
}
/// 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{Kind::POINTER, ElementCount::getFixed(0), SizeInBits,
- AddressSpace, static_cast<FPVariant>(0)};
+ AddressSpace, static_cast<FpSemantics>(0)};
}
/// Get a low-level vector of some number of elements and element width.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits) {
assert(!EC.isScalar() && "invalid number of vector elements");
return LLT{Kind::VECTOR_ANY, EC, ScalarSizeInBits,
- /*AddressSpace=*/0, static_cast<FPVariant>(0)};
+ /*AddressSpace=*/0, static_cast<FpSemantics>(0)};
}
/// Get a low-level vector of some number of elements and element type.
@@ -133,41 +128,62 @@ class LLT {
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)};
+ ScalarTy.isFloat() ? ScalarTy.getFpSemantics()
+ : static_cast<FpSemantics>(0)};
+ }
+
+ static constexpr LLT floatIEEE(unsigned SizeInBits) {
+ switch (SizeInBits) {
+ default:
+ llvm_unreachable("Wrong SizeInBits for IEEE Floating point!");
+ case 16:
+ return float16();
+ case 32:
+ return float32();
+ case 64:
+ return float64();
+ case 128:
+ return float128();
+ }
}
// Get a bfloat16 value.
- static constexpr LLT bfloat16() { return floatingPoint(16, FPVariant::BF16); }
-
+ static constexpr LLT bfloat16() {
+ return LLT{Kind::FLOAT, ElementCount::getFixed(0), 16, 0,
+ FpSemantics::S_BFloat};
+ }
/// Get a 16-bit IEEE half value.
static constexpr LLT float16() {
- return floatingPoint(16, FPVariant::IEEE_FLOAT);
+ return LLT{Kind::FLOAT, ElementCount::getFixed(0), 16, 0,
+ FpSemantics::S_IEEEhalf};
}
-
/// Get a 32-bit IEEE float value.
static constexpr LLT float32() {
- return floatingPoint(32, FPVariant::IEEE_FLOAT);
+ return LLT{Kind::FLOAT, ElementCount::getFixed(0), 32, 0,
+ FpSemantics::S_IEEEsingle};
}
-
/// Get a 64-bit IEEE double value.
static constexpr LLT float64() {
- return floatingPoint(64, FPVariant::IEEE_FLOAT);
+ return LLT{Kind::FLOAT, ElementCount::getFixed(0), 64, 0,
+ FpSemantics::S_IEEEdouble};
}
/// Get a 80-bit X86 floating point value.
static constexpr LLT x86fp80() {
- return floatingPoint(80, FPVariant::EXTENDED_FP80);
+ return LLT{Kind::FLOAT, ElementCount::getFixed(0), 80, 0,
+ FpSemantics::S_x87DoubleExtended};
}
/// Get a 128-bit IEEE quad value.
static constexpr LLT float128() {
- return floatingPoint(128, FPVariant::IEEE_FLOAT);
+ return LLT{Kind::FLOAT, ElementCount::getFixed(0), 128, 0,
+ FpSemantics::S_IEEEquad};
}
/// Get a 128-bit PowerPC double double value.
static constexpr LLT ppcf128() {
- return floatingPoint(128, FPVariant::PPC128_FLOAT);
+ return LLT{Kind::FLOAT, ElementCount::getFixed(0), 128, 0,
+ FpSemantics::S_PPCDoubleDouble};
}
/// Get a low-level fixed-width vector of some number of elements and element
@@ -209,15 +225,34 @@ class LLT {
}
explicit constexpr LLT(Kind Info, ElementCount EC, uint64_t SizeInBits,
- unsigned AddressSpace, FPVariant FP)
+ unsigned AddressSpace, FpSemantics Sem)
: LLT() {
- init(Info, EC, SizeInBits, AddressSpace, FP);
+ init(Info, EC, SizeInBits, AddressSpace, Sem);
}
LLVM_ABI explicit LLT(MVT VT, bool AllowExtendedLLT = false);
explicit constexpr LLT() : RawData(0), Info(static_cast<Kind>(0)) {}
+ constexpr bool isToken() const {
+ return Info == Kind::ANY_SCALAR && RawData == 0;
+ }
constexpr bool isValid() const { return isToken() || RawData != 0; }
+ constexpr bool isAnyScalar() const { return Info == Kind::ANY_SCALAR; }
+ constexpr bool isInteger() const { return Info == Kind::INTEGER; }
+ constexpr bool isFloat() const { return Info == Kind::FLOAT; }
+ constexpr bool isPointer() const { return Info == Kind::POINTER; }
+ constexpr bool isVectorAny() const { return Info == Kind::VECTOR_ANY; }
+ constexpr bool isIntegerVector() const {
+ return Info == Kind::VECTOR_INTEGER;
+ }
+ constexpr bool isFloatVector() const { return Info == Kind::VECTOR_FLOAT; }
+ constexpr bool isPointerVector() const {
+ return Info == Kind::VECTOR_POINTER;
+ }
+ constexpr bool isPointerOrPointerVector() const {
+ return isPointer() || isPointerVector();
+ }
+
constexpr bool isScalar() const {
return Info == Kind::ANY_SCALAR || Info == Kind::INTEGER ||
Info == Kind::FLOAT;
@@ -225,54 +260,35 @@ class LLT {
constexpr bool isScalar(unsigned Size) const {
return isScalar() && getScalarSizeInBits() == Size;
}
- constexpr bool isFloat() const { return Info == Kind::FLOAT; }
- constexpr bool isFloat(unsigned Size) const {
- return isFloat() && getScalarSizeInBits() == Size;
+ constexpr bool isVector() const {
+ return Info == Kind::VECTOR_ANY || Info == Kind::VECTOR_INTEGER ||
+ Info == Kind::VECTOR_FLOAT || Info == Kind::VECTOR_POINTER;
}
- constexpr bool isVariantFloat() const {
- return isFloat() && getFPVariant() != FPVariant::IEEE_FLOAT;
+
+ constexpr bool isInteger(unsigned Size) const {
+ return isInteger() && getScalarSizeInBits() == Size;
}
- constexpr bool isVariantFloat(FPVariant Variant) const {
- return isFloat() && getFPVariant() == Variant;
+
+ constexpr bool isFloat(unsigned Size) const {
+ return isFloat() && getScalarSizeInBits() == Size;
}
- constexpr bool isVariantFloat(unsigned Size, FPVariant Variant) const {
- return isVariantFloat(Variant) && getScalarSizeInBits() == Size;
+ constexpr bool isFloatWithSem(FpSemantics Sem) const {
+ return isFloat() && getFpSemantics() == Sem;
}
- constexpr bool isFloatVector() const { return Info == Kind::VECTOR_FLOAT; }
- constexpr bool isIEEEFloat(unsigned Size) const {
- return isVariantFloat(Size, FPVariant::IEEE_FLOAT);
+ constexpr bool isFloatIEEE() const {
+ return isFloatWithSem(APFloatBase::S_IEEEhalf) ||
+ isFloatWithSem(APFloatBase::S_IEEEsingle) ||
+ isFloatWithSem(APFloatBase::S_IEEEdouble) ||
+ isFloatWithSem(APFloatBase::S_IEEEquad);
}
- constexpr bool isBFloat(unsigned Size) const {
- return isVariantFloat(Size, FPVariant::BF16);
+ constexpr bool isBFloat16() const {
+ return isFloatWithSem(FpSemantics::S_BFloat);
}
constexpr bool isX86FP80() const {
- return isVariantFloat(80, FPVariant::EXTENDED_FP80);
+ return isFloatWithSem(FpSemantics::S_x87DoubleExtended);
}
constexpr bool isPPCF128() const {
- return isVariantFloat(128, FPVariant::PPC128_FLOAT);
- }
- constexpr bool isToken() const {
- return Info == Kind::ANY_SCALAR && RawData == 0;
- }
- constexpr bool isAnyScalar() const { return Info == Kind::ANY_SCALAR; }
- constexpr bool isVectorAny() const { return Info == Kind::VECTOR_ANY; }
- constexpr bool isInteger() const { return Info == Kind::INTEGER; }
- constexpr bool isInteger(unsigned Size) const {
- return isInteger() && getScalarSizeInBits() == Size;
- }
- constexpr bool isIntegerVector() const {
- return Info == Kind::VECTOR_INTEGER;
- }
- constexpr bool isVector() const {
- return Info == Kind::VECTOR_ANY || Info == Kind::VECTOR_INTEGER ||
- Info == Kind::VECTOR_FLOAT || Info == Kind::VECTOR_POINTER;
- }
- constexpr bool isPointer() const { return Info == Kind::POINTER; }
- constexpr bool isPointerVector() const {
- return Info == Kind::VECTOR_POINTER;
- }
- constexpr bool isPointerOrPointerVector() const {
- return isPointer() || isPointerVector();
+ return isFloatWithSem(FpSemantics::S_PPCDoubleDouble);
}
/// Returns the number of elements in a vector LLT. Must only be called on
@@ -333,11 +349,10 @@ class LLT {
return isVector() ? getElementType() : *this;
}
- constexpr FPVariant getFPVariant() const {
+ constexpr FpSemantics getFpSemantics() const {
assert((isFloat() || isFloatVector()) &&
"cannot get FP info for non float type");
-
- return FPVariant(getFieldValue(FPFieldInfo));
+ return FpSemantics(getFieldValue(FpSemanticFieldInfo));
}
constexpr Kind getKind() const { return Info; }
@@ -427,7 +442,7 @@ class LLT {
return pointer(getAddressSpace(), getScalarSizeInBits());
if (isFloatVector())
- return floatingPoint(getScalarSizeInBits(), getFPVariant());
+ return floatingPoint(getFpSemantics());
if (isIntegerVector())
return integer(getScalarSizeInBits());
@@ -453,7 +468,8 @@ class LLT {
constexpr bool operator==(const LLT &RHS) const {
if (isAnyScalar() || RHS.isAnyScalar())
- return isScalar() == RHS.isScalar() && RawData == RHS.RawData;
+ return isScalar() == RHS.isScalar() &&
+ getScalarSizeInBits() == RHS.getScalarSizeInBits();
if (isVector() && RHS.isVector())
return getElementType() == RHS.getElementType() &&
@@ -488,7 +504,7 @@ class LLT {
.... ........ ........ ........ .... (2)
**** ******** **** (3)
~~~~ ~~~~~~~~ ~~~~~~~~ ~~~~ (4)
- ### (5)
+ #### #### (5)
^^^^ ^^^^^^^^ ^^^^ (6)
@ (7)
@@ -496,7 +512,7 @@ class LLT {
(2) ScalarSize: [59:28]
(3) PointerSize: [59:44]
(4) PointerAddressSpace: [43:20]
- (5) FPVariant: [22:20]
+ (5) FpSemantics: [27:20]
(6) VectorElements: [19:4]
(7) VectorScalable: [0:0]
@@ -510,7 +526,7 @@ class LLT {
/// * Non-pointer scalar (isPointer == 0 && isVector == 0):
/// Info: [63:60];
/// SizeOfElement: [59:28];
- /// FPVariant: [22:20];
+ /// FpSemantics: [27:20];
///
/// * Pointer (isPointer == 1 && isVector == 0):
/// Info: [63:60];
@@ -520,7 +536,7 @@ class LLT {
/// * Vector-of-non-pointer (isPointer == 0 && isVector == 1):
/// Info: [63:60]
/// SizeOfElement: [59:28];
- /// FPVariant: [22:20];
+ /// FpSemantics: [27:20];
/// VectorElements: [19:4];
/// Scalable: [0:0];
///
@@ -533,9 +549,10 @@ class LLT {
/// BitFieldInfo: {Size, Offset}
typedef int BitFieldInfo[2];
+ static_assert(bit_width_constexpr((uint32_t)APFloat::S_MaxSemantics) <= 8);
static constexpr BitFieldInfo VectorScalableFieldInfo{1, 0};
static constexpr BitFieldInfo VectorElementsFieldInfo{16, 4};
- static constexpr BitFieldInfo FPFieldInfo{3, 20};
+ static constexpr BitFieldInfo FpSemanticFieldInfo{8, 20};
static constexpr BitFieldInfo PointerAddressSpaceFieldInfo{24, 20};
static constexpr BitFieldInfo ScalarSizeFieldInfo{32, 28};
static constexpr BitFieldInfo PointerSizeFieldInfo{16, 44};
@@ -562,7 +579,7 @@ class LLT {
}
constexpr void init(Kind Info, ElementCount EC, uint64_t SizeInBits,
- unsigned AddressSpace, FPVariant FP) {
+ unsigned AddressSpace, FpSemantics Sem) {
assert(SizeInBits <= std::numeric_limits<unsigned>::max() &&
"Not enough bits in LLT to represent size");
this->Info = Info;
@@ -571,7 +588,7 @@ class LLT {
maskAndShift(AddressSpace, PointerAddressSpaceFieldInfo);
} else {
RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo) |
- maskAndShift((uint64_t)FP, FPFieldInfo);
+ maskAndShift((uint64_t)Sem, FpSemanticFieldInfo);
}
if (Info == Kind::VECTOR_ANY || Info == Kind::VECTOR_INTEGER ||
@@ -587,7 +604,7 @@ class LLT {
}
};
-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;
}
@@ -607,9 +624,7 @@ template <> struct DenseMapInfo<LLT> {
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
diff --git a/llvm/lib/CodeGen/LowLevelTypeUtils.cpp b/llvm/lib/CodeGen/LowLevelTypeUtils.cpp
index 57265b048125d..b3f397610c71c 100644
--- a/llvm/lib/CodeGen/LowLevelTypeUtils.cpp
+++ b/llvm/lib/CodeGen/LowLevelTypeUtils.cpp
@@ -117,24 +117,20 @@ const llvm::fltSemantics &llvm::getFltSemanticForLLT(LLT Ty) {
assert((Ty.isAnyScalar() || Ty.isFloat()) &&
"Expected a any scalar or float 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();
- case 32:
- return APFloat::IEEEsingle();
- case 64:
- return APFloat::IEEEdouble();
- case 128:
- return APFloat::IEEEquad();
+ if (Ty.isAnyScalar()) {
+ switch (Ty.getSizeInBits()) {
+ default:
+ llvm_unreachable("Invalid FP type size.");
+ case 16:
+ return APFloat::IEEEhalf();
+ case 32:
+ return APFloat::IEEEsingle();
+ case 64:
+ return APFloat::IEEEdouble();
+ case 128:
+ return APFloat::IEEEquad();
+ }
}
- llvm_unreachable("Invalid FP type size.");
+
+ return APFloat::EnumToSemantics(Ty.getFpSemantics());
}
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 8497ee7b17fef..8f431640da154 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -1969,18 +1969,15 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
}
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::BF16;
- 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);
+
+ if (Token.range().starts_with("bf") && ScalarSize != 16)
+ return error("invalid size for bfloat");
+
+ Ty = Token.range().starts_with("bf") ? LLT::bfloat16()
+ : LLT::floatIEEE(ScalarSize);
lex();
return false;
}
@@ -2050,12 +2047,12 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
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);
+ Ty = LLT::floatIEEE(ScalarSize);
} 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::BF16);
+ Ty = LLT::bfloat16();
} else
return GetError();
lex();
diff --git a/llvm/lib/CodeGenTypes/LowLevelType.cpp b/llvm/lib/CodeGenTypes/LowLevelType.cpp
index 96b7a33783fba..229c9d542fe9e 100644
--- a/llvm/lib/CodeGenTypes/LowLevelType.cpp
+++ b/llvm/lib/CodeGenTypes/LowLevelType.cpp
@@ -16,19 +16,25 @@
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
-static std::optional<LLT::FPVariant> deriveFPInfo(MVT VT) {
- if (!VT.isFloatingPoint())
- return std::nullopt;
-
+// Repeat logic of MVT::getFltSemantics to exclude CodeGen dependency
+static LLT::FpSemantics getFpSemanticsForMVT(MVT VT) {
switch (VT.getScalarType().SimpleTy) {
+ default:
+ llvm_unreachable("Unknown FP format");
+ case MVT::f16:
+ return LLT::FpSemantics::S_IEEEhalf;
case MVT::bf16:
- return LLT::FPVariant::BF16;
+ return LLT::FpSemantics::S_BFloat;
+ case MVT::f32:
+ return LLT::FpSemantics::S_IEEEsingle;
+ case MVT::f64:
+ return LLT::FpSemantics::S_IEEEdouble;
case MVT::f80:
- return LLT::FPVariant::EXTENDED_FP80;
+ return LLT::FpSemantics::S_x87DoubleExtended;
+ case MVT::f128:
+ return LLT::FpSemantics::S_IEEEquad;
case MVT::ppcf128:
- return LLT::FPVariant::PPC128_FLOAT;
- default:
- return LLT::FPVariant::IEEE_FLOAT;
+ return LLT::FpSemantics::S_PPCDoubleDouble;
}
}
@@ -38,10 +44,11 @@ LLT::LLT(MVT VT, bool AllowExtendedLLT) {
bool AsVector = VT.getVectorMinNumElements() > 1 || VT.isScalableVector();
Kind Info = AsVector ? Kind::VECTOR_ANY : Kind::ANY_SCALAR;
init(Info, VT.getVectorElementCount(),
- VT.getVectorElementType().getSizeInBits(), 0, FPVariant::IEEE_FLOAT);
+ VT.getVectorElementType().getSizeInBits(), 0,
+ static_cast<FpSemantics>(0));
} else if (VT.isValid() && !VT.isScalableTargetExtVT()) {
init(Kind::ANY_SCALAR, ElementCount::getFixed(0), VT.getSizeInBits(), 0,
- FPVariant::IEEE_FLOAT);
+ static_cast<FpSemantics>(0));
} else {
this->Info = Kind::INVALID;
this->RawData = 0;
@@ -49,25 +56,24 @@ LLT::LLT(MVT VT, bool AllowExtendedLLT) {
return;
}
- auto FP = deriveFPInfo(VT);
+ bool IsFloatingPoint = VT.isFloatingPoint();
+ FpSemantics FpSem =
+ IsFloatingPoint ? getFpSemanticsForMVT(VT) : static_cast<FpSemantics>(0);
bool AsVector = VT.isVector() &&
(VT.getVectorMinNumElements() > 1 || VT.isScalableVector());
-
LLT::Kind Info;
- if (FP.has_value())
+ if (IsFloatingPoint)
Info = AsVector ? LLT::Kind::VECTOR_FLOAT : LLT::Kind::FLOAT;
else
Info = AsVector ? LLT::Kind::VECTOR_INTEGER : LLT::Kind::INTEGER;
if (VT.isVector()) {
init(Info, VT.getVectorElementCount(),
- VT.getVectorElementType().getSizeInBits(), 0,
- FP.value_or(LLT::FPVariant::IEEE_FLOAT));
+ VT.getVectorElementType().getSizeInBits(), 0, FpSem);
} else if (VT.isValid() && !VT.isScalableTargetExtVT()) {
// Aggregates are no different from real scalars as far as GlobalISel is
// concerned.
- init(Info, ElementCount::getFixed(0), VT.getSizeInBits(), 0,
- FP.value_or(LLT::FPVariant::IEEE_FLOAT));
+ init(Info, ElementCount::getFixed(0), VT.getSizeInBits(), 0, FpSem);
} else {
this->Info = Kind::INVALID;
this->RawData = 0;
@@ -81,12 +87,11 @@ void LLT::print(raw_ostream &OS) const {
OS << getElementCount() << " x " << getElementType() << ">";
} else if (isPointer()) {
OS << "p" << getAddressSpace();
- } else if (isBFloat(16)) {
+ } else if (isBFloat16()) {
OS << "bf16";
} else if (isPPCF128()) {
OS << "ppcf128";
- } else if (isFloat()) {
- assert(!isVariantFloat() && "unknown float variant");
+ } else if (isFloatIEEE()) {
OS << "f" << getScalarSizeInBits();
} else if (isInteger()) {
OS << "i" << getScalarSizeInBits();
diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
index d4d1c7f18668e..4f4ef74688a54 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
@@ -317,9 +317,9 @@ constexpr LLT V10S16 = LLT::fixed_vector(10, 16);
constexpr LLT V12S16 = LLT::fixed_vector(12, 16);
constexpr LLT V16S16 = LLT::fixed_vector(16, 16);
-constexpr LLT V2F16 =
- LLT::fixed_vector(2, LLT::scalar(16)); // TODO: Expected float16
-constexpr LLT V2BF16 = V2F16; // FIXME
+// TODO: Expected LLT::fixed_vector(2, LLT::float16())
+constexpr LLT V2F16 = LLT::fixed_vector(2, LLT::scalar(16));
+constexpr LLT V2BF16 = V2F16; // FIXME
constexpr LLT V2S32 = LLT::fixed_vector(2, 32);
constexpr LLT V3S32 = LLT::fixed_vector(3, 32);
@@ -3344,7 +3344,7 @@ bool AMDGPULegalizerInfo::legalizeFMad(
const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
// TODO: Always legal with future ftz flag.
- // TODO: Type is expected to be float32/float16
+ // TODO: Type is expected to be LLT::float32()/LLT::float16()
// FIXME: Do we need just output?
if (Ty == LLT::scalar(32) &&
MFI->getMode().FP32Denormals == DenormalMode::getPreserveSign())
@@ -3895,8 +3895,8 @@ bool AMDGPULegalizerInfo::legalizeFPow(MachineInstr &MI,
Register Src1 = MI.getOperand(2).getReg();
unsigned Flags = MI.getFlags();
LLT Ty = B.getMRI()->getType(Dst);
- const LLT F16 = LLT::scalar(16); // TODO: Expected float16
- const LLT F32 = LLT::scalar(32); // TODO: Expected float32
+ const LLT F16 = LLT::scalar(16); // TODO: Expected LLT::float16()
+ const LLT F32 = LLT::scalar(32); // TODO: Expected LLT::float32()
if (Ty == F32) {
auto Log = B.buildFLog2(F32, Src0, Flags);
diff --git a/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td b/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
index d889523950a91..e85ec2e990e09 100644
--- a/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
+++ b/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
@@ -114,7 +114,7 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
// EXTENDED-NEXT: const static size_t NumTypeObjects = 3;
// EXTENDED-NEXT: const static LLT TypeObjects[] = {
// EXTENDED-NEXT: LLT::integer(32),
-// EXTENDED-NEXT: LLT::floatingPoint(32, LLT::FPVariant::IEEE_FLOAT),
+// EXTENDED-NEXT: LLT::floatIEEE(32),
// EXTENDED-NEXT: LLT::pointer(0, 32),
// EXTENDED-NEXT: };
diff --git a/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp b/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp
index 079f8dea377e0..ffac39e90bb6a 100644
--- a/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp
+++ b/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp
@@ -111,13 +111,13 @@ TEST_F(AArch64IRTranslatorTest, IRTranslateBfloat16) {
llvm::MachineFunctionProperties::Property::FailedISel));
for (auto &MI : MF->front()) {
if (MI.getOpcode() == TargetOpcode::G_LOAD) {
- ASSERT_TRUE(MRI.getType(MI.getOperand(0).getReg()).isBFloat(16));
+ ASSERT_TRUE(MRI.getType(MI.getOperand(0).getReg()).isBFloat16());
}
if (MI.getOpcode() == TargetOpcode::G_FADD ||
MI.getOpcode() == TargetOpcode::G_FMUL) {
for (auto &Op : MI.operands()) {
- ASSERT_TRUE(MRI.getType(Op.getReg()).isBFloat(16));
+ ASSERT_TRUE(MRI.getType(Op.getReg()).isBFloat16());
}
}
}
diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
index 525f222d4ae25..5ef4ac65cde84 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
+++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
@@ -369,7 +369,7 @@ std::string LLTCodeGen::getCxxEnumValue() const {
void LLTCodeGen::emitCxxEnumValue(raw_ostream &OS) const {
if (Ty.isScalar()) {
- if (Ty.isBFloat(16))
+ if (Ty.isBFloat16())
OS << "GILLT_bf16";
else if (Ty.isPPCF128())
OS << "GILLT_ppcf128";
@@ -388,7 +388,7 @@ void LLTCodeGen::emitCxxEnumValue(raw_ostream &OS) const {
<< Ty.getElementCount().getKnownMinValue();
LLT ElemTy = Ty.getElementType();
- if (ElemTy.isBFloat(16))
+ if (ElemTy.isBFloat16())
OS << "bf16";
else if (ElemTy.isPPCF128())
OS << "ppcf128";
@@ -417,15 +417,14 @@ void LLTCodeGen::emitCxxConstructorCall(raw_ostream &OS) const {
if (Ty.isScalar()) {
if (Ty.isInteger())
OS << "LLT::integer(" << Ty.getScalarSizeInBits() << ")";
- else if (Ty.isBFloat(16))
+ else if (Ty.isBFloat16())
OS << "LLT::bfloat16()";
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)";
+ OS << "LLT::floatIEEE(" << Ty.getScalarSizeInBits() << ")";
else
OS << "LLT::scalar(" << Ty.getScalarSizeInBits() << ")";
return;
@@ -440,15 +439,14 @@ void LLTCodeGen::emitCxxConstructorCall(raw_ostream &OS) const {
LLT ElemTy = Ty.getElementType();
if (ElemTy.isInteger())
OS << "LLT::integer(" << ElemTy.getScalarSizeInBits() << ")";
- else if (ElemTy.isBFloat(16))
+ else if (ElemTy.isBFloat16())
OS << "LLT::bfloat16()";
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)";
+ OS << "LLT::floatIEEE(" << ElemTy.getScalarSizeInBits() << ")";
else
OS << "LLT::scalar(" << Ty.getScalarSizeInBits() << ")";
OS << ")";
>From 282bfd7d28882a0717f251bcae98564c55a78aed Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Fri, 28 Nov 2025 00:21:08 +0300
Subject: [PATCH 22/40] Added assert and updated comment
---
llvm/include/llvm/CodeGenTypes/LowLevelType.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/include/llvm/CodeGenTypes/LowLevelType.h b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
index 1456700ce0bb1..64dc0249b88c3 100644
--- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h
+++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
@@ -365,10 +365,10 @@ class LLT {
/// If this type is a vector, return a vector with the same number of elements
/// but the new element size. Otherwise, return the new element type. Invalid
- /// for pointer types. For pointer types, use changeElementType.
+ /// for pointer and floating point types. For these, use changeElementType.
constexpr LLT changeElementSize(unsigned NewEltSize) const {
assert(!isPointerOrPointerVector() && !(isFloat() || isFloatVector()) &&
- "invalid to directly change element size for pointers");
+ "invalid to directly change element size for pointers and floats");
return isVector()
? LLT::vector(getElementCount(), getElementType().isInteger()
? LLT::integer(NewEltSize)
@@ -392,8 +392,8 @@ class LLT {
/// not attempt to handle cases that aren't evenly divisible.
constexpr LLT divide(int Factor) const {
assert(Factor != 1);
- assert((!isScalar() || getScalarSizeInBits() != 0) &&
- "cannot divide scalar of size zero");
+ assert((!isScalar() || getScalarSizeInBits() != 0) && !isFloat() &&
+ "cannot divide scalar of size zero and floats");
if (isVector()) {
assert(getElementCount().isKnownMultipleOf(Factor));
return scalarOrVector(getElementCount().divideCoefficientBy(Factor),
>From af98f6361af10f2231d079946f6b6d3e87bfd6b9 Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Sat, 6 Dec 2025 15:00:11 +0300
Subject: [PATCH 23/40] Added global state for LLT, allowing initialize
extended LLTs
---
llvm/include/llvm/CodeGen/LowLevelTypeUtils.h | 5 +-
llvm/include/llvm/CodeGen/TargetLowering.h | 7 ---
llvm/include/llvm/CodeGenTypes/LowLevelType.h | 8 ++-
llvm/lib/CodeGen/Analysis.cpp | 2 +-
llvm/lib/CodeGen/GlobalISel/CallLowering.cpp | 13 +++--
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 50 ++++++++++---------
llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp | 2 +-
llvm/lib/CodeGen/LowLevelTypeUtils.cpp | 10 ++--
.../CodeGen/SelectionDAG/SelectionDAGISel.cpp | 4 +-
llvm/lib/CodeGen/TargetLoweringBase.cpp | 8 ---
llvm/lib/CodeGenTypes/LowLevelType.cpp | 6 ++-
.../AArch64/GISel/AArch64CallLowering.cpp | 4 +-
llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp | 4 +-
.../GlobalISel/GlobalISelMatchTable.cpp | 9 +---
.../GlobalISelMatchTableExecutorEmitter.cpp | 10 ++++
.../GlobalISelMatchTableExecutorEmitter.h | 2 +-
16 files changed, 71 insertions(+), 73 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/LowLevelTypeUtils.h b/llvm/include/llvm/CodeGen/LowLevelTypeUtils.h
index 4092509948ae6..f0c1758a4c9cc 100644
--- a/llvm/include/llvm/CodeGen/LowLevelTypeUtils.h
+++ b/llvm/include/llvm/CodeGen/LowLevelTypeUtils.h
@@ -27,8 +27,7 @@ class Type;
struct fltSemantics;
/// Construct a low-level type based on an LLVM type.
-LLVM_ABI LLT getLLTForType(Type &Ty, const DataLayout &DL,
- bool AllowExtendedLLT = false);
+LLVM_ABI LLT getLLTForType(Type &Ty, const DataLayout &DL);
/// Get a rough equivalent of an MVT for a given LLT. MVT can't distinguish
/// pointers, so these will convert to a plain integer.
@@ -37,7 +36,7 @@ LLVM_ABI EVT getApproximateEVTForLLT(LLT Ty, LLVMContext &Ctx);
/// Get a rough equivalent of an LLT for a given MVT. LLT does not yet support
/// scalarable vector types, and will assert if used.
-LLVM_ABI LLT getLLTForMVT(MVT Ty, bool AllowExtendedLLT = false);
+LLVM_ABI LLT getLLTForMVT(MVT Ty);
/// Get the appropriate floating point arithmetic semantic based on the bit size
/// of the given scalar LLT.
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index a5f7bdb037165..b2697c81fd825 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -418,13 +418,6 @@ class LLVM_ABI TargetLoweringBase {
/// amounts, returns MVT::i32.
EVT getShiftAmountTy(EVT LHSTy, const DataLayout &DL) const;
- /// Returns LLT for given Type, taking into account
- /// TargetOptions::EnableGlobalISelExtendedLLT.
- LLT getLLTForType(Type &Ty, const DataLayout &DL) const;
- /// Returns LLT for given MVT, taking into account
- /// TargetOptions::EnableGlobalISelExtendedLLT.
- LLT getLLTForMVT(MVT Ty) const;
-
/// Return the preferred type to use for a shift opcode, given the shifted
/// amount type is \p ShiftValueTy.
LLVM_READONLY
diff --git a/llvm/include/llvm/CodeGenTypes/LowLevelType.h b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
index 64dc0249b88c3..fbbb4bd0d1de1 100644
--- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h
+++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
@@ -230,7 +230,7 @@ class LLT {
init(Info, EC, SizeInBits, AddressSpace, Sem);
}
- LLVM_ABI explicit LLT(MVT VT, bool AllowExtendedLLT = false);
+ LLVM_ABI explicit LLT(MVT VT);
explicit constexpr LLT() : RawData(0), Info(static_cast<Kind>(0)) {}
constexpr bool isToken() const {
@@ -602,6 +602,12 @@ class LLT {
constexpr uint64_t getUniqueRAWLLTData() const {
return ((uint64_t)RawData) | ((uint64_t)Info) << 60;
}
+
+ static bool getUseExtended() { return ExtendedLLT; }
+ static void setUseExtended(bool Enable) { ExtendedLLT = Enable; }
+
+private:
+ static bool ExtendedLLT;
};
inline raw_ostream &operator<<(raw_ostream &OS, const LLT &Ty) {
diff --git a/llvm/lib/CodeGen/Analysis.cpp b/llvm/lib/CodeGen/Analysis.cpp
index 6d6697167cefa..f16c35ce3f259 100644
--- a/llvm/lib/CodeGen/Analysis.cpp
+++ b/llvm/lib/CodeGen/Analysis.cpp
@@ -176,7 +176,7 @@ void llvm::computeValueLLTs(const TargetLowering &TLI, const DataLayout &DL,
if (Ty.isVoidTy())
return;
// Base case: we can get an LLT for this LLVM IR type.
- ValueTys.push_back(TLI.getLLTForType(Ty, DL));
+ ValueTys.push_back(getLLTForType(Ty, DL));
if (Offsets)
Offsets->push_back(StartingOffset);
}
diff --git a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
index b29695c66020d..c1501b2f428f7 100644
--- a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
@@ -159,7 +159,7 @@ bool CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, const CallBase &CB,
if (const Function *F = dyn_cast<Function>(CalleeV)) {
if (F->hasFnAttribute(Attribute::NonLazyBind)) {
- LLT Ty = TLI->getLLTForType(*F->getType(), DL);
+ LLT Ty = getLLTForType(*F->getType(), DL);
Register Reg = MIRBuilder.buildGlobalValue(Ty, F).getReg(0);
Info.Callee = MachineOperand::CreateReg(Reg, false);
} else {
@@ -786,11 +786,11 @@ bool CallLowering::handleAssignments(ValueHandler &Handler,
const MVT ValVT = VA.getValVT();
const MVT LocVT = VA.getLocVT();
- const LLT LocTy = TLI->getLLTForMVT(LocVT);
- const LLT ValTy = TLI->getLLTForMVT(ValVT);
+ const LLT LocTy = getLLTForMVT(LocVT);
+ const LLT ValTy = getLLTForMVT(ValVT);
const LLT NewLLT = Handler.isIncomingArgumentHandler() ? LocTy : ValTy;
const EVT OrigVT = EVT::getEVT(Args[i].Ty);
- const LLT OrigTy = TLI->getLLTForType(*Args[i].Ty, DL);
+ const LLT OrigTy = getLLTForType(*Args[i].Ty, DL);
const LLT PointerTy = LLT::pointer(
AllocaAddressSpace, DL.getPointerSizeInBits(AllocaAddressSpace));
@@ -1009,7 +1009,7 @@ void CallLowering::insertSRetLoads(MachineIRBuilder &MIRBuilder, Type *RetTy,
Align BaseAlign = DL.getPrefTypeAlign(RetTy);
Type *RetPtrTy =
PointerType::get(RetTy->getContext(), DL.getAllocaAddrSpace());
- LLT OffsetLLTy = TLI->getLLTForType(*DL.getIndexType(RetPtrTy), DL);
+ LLT OffsetLLTy = getLLTForType(*DL.getIndexType(RetPtrTy), DL);
MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(MF, FI);
@@ -1040,8 +1040,7 @@ void CallLowering::insertSRetStores(MachineIRBuilder &MIRBuilder, Type *RetTy,
unsigned NumValues = SplitVTs.size();
Align BaseAlign = DL.getPrefTypeAlign(RetTy);
unsigned AS = DL.getAllocaAddrSpace();
- LLT OffsetLLTy =
- TLI->getLLTForType(*DL.getIndexType(RetTy->getContext(), AS), DL);
+ LLT OffsetLLTy = getLLTForType(*DL.getIndexType(RetTy->getContext(), AS), DL);
MachinePointerInfo PtrInfo(AS);
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index b76ce276fd371..74bc88df79495 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -847,7 +847,7 @@ void IRTranslator::emitJumpTable(SwitchCG::JumpTable &JT,
MIB.setDebugLoc(CurBuilder->getDebugLoc());
Type *PtrIRTy = PointerType::getUnqual(MF->getFunction().getContext());
- const LLT PtrTy = TLI->getLLTForType(*PtrIRTy, *DL);
+ const LLT PtrTy = getLLTForType(*PtrIRTy, *DL);
auto Table = MIB.buildJumpTable(PtrTy, JT.JTI);
MIB.buildBrJT(Table.getReg(0), JT.JTI, JT.Reg);
@@ -862,7 +862,7 @@ bool IRTranslator::emitJumpTableHeader(SwitchCG::JumpTable &JT,
const Value &SValue = *JTH.SValue;
// Subtract the lowest switch case value from the value being switched on.
- const LLT SwitchTy = TLI->getLLTForType(*SValue.getType(), *DL);
+ const LLT SwitchTy = getLLTForType(*SValue.getType(), *DL);
Register SwitchOpReg = getOrCreateVReg(SValue);
auto FirstCst = MIB.buildConstant(SwitchTy, JTH.First);
auto Sub = MIB.buildSub({SwitchTy}, SwitchOpReg, FirstCst);
@@ -1095,7 +1095,7 @@ void IRTranslator::emitBitTestHeader(SwitchCG::BitTestBlock &B,
auto RangeSub = MIB.buildSub(SwitchOpTy, SwitchOpReg, MinValReg);
Type *PtrIRTy = PointerType::getUnqual(MF->getFunction().getContext());
- const LLT PtrTy = TLI->getLLTForType(*PtrIRTy, *DL);
+ const LLT PtrTy = getLLTForType(*PtrIRTy, *DL);
LLT MaskTy = SwitchOpTy;
if (MaskTy.getSizeInBits() > PtrTy.getSizeInBits() ||
@@ -1148,7 +1148,7 @@ void IRTranslator::emitBitTestCase(SwitchCG::BitTestBlock &BB,
MachineIRBuilder &MIB = *CurBuilder;
MIB.setMBB(*SwitchBB);
- LLT SwitchTy = TLI->getLLTForMVT(BB.RegVT);
+ LLT SwitchTy = getLLTForMVT(BB.RegVT);
Register Cmp;
unsigned PopCount = llvm::popcount(B.Mask);
if (PopCount == 1) {
@@ -1375,7 +1375,7 @@ bool IRTranslator::translateLoad(const User &U, MachineIRBuilder &MIRBuilder) {
const Value *Ptr = LI.getPointerOperand();
Type *OffsetIRTy = DL->getIndexType(Ptr->getType());
- LLT OffsetTy = TLI->getLLTForType(*OffsetIRTy, *DL);
+ LLT OffsetTy = getLLTForType(*OffsetIRTy, *DL);
if (CLI->supportSwiftError() && isSwiftError(Ptr)) {
assert(Regs.size() == 1 && "swifterror should be single pointer");
@@ -1422,7 +1422,7 @@ bool IRTranslator::translateStore(const User &U, MachineIRBuilder &MIRBuilder) {
Register Base = getOrCreateVReg(*SI.getPointerOperand());
Type *OffsetIRTy = DL->getIndexType(SI.getPointerOperandType());
- LLT OffsetTy = TLI->getLLTForType(*OffsetIRTy, *DL);
+ LLT OffsetTy = getLLTForType(*OffsetIRTy, *DL);
if (CLI->supportSwiftError() && isSwiftError(SI.getPointerOperand())) {
assert(Vals.size() == 1 && "swifterror should be single pointer");
@@ -1544,8 +1544,8 @@ bool IRTranslator::translateCopy(const User &U, const Value &V,
bool IRTranslator::translateBitCast(const User &U,
MachineIRBuilder &MIRBuilder) {
// If we're bitcasting to the source type, we can reuse the source vreg.
- if (TLI->getLLTForType(*U.getOperand(0)->getType(), *DL) ==
- TLI->getLLTForType(*U.getType(), *DL)) {
+ if (getLLTForType(*U.getOperand(0)->getType(), *DL) ==
+ getLLTForType(*U.getType(), *DL)) {
// If the source is a ConstantInt then it was probably created by
// ConstantHoisting and we should leave it alone.
if (isa<ConstantInt>(U.getOperand(0)))
@@ -1577,9 +1577,9 @@ bool IRTranslator::translateGetElementPtr(const User &U,
Value &Op0 = *U.getOperand(0);
Register BaseReg = getOrCreateVReg(Op0);
Type *PtrIRTy = Op0.getType();
- LLT PtrTy = TLI->getLLTForType(*PtrIRTy, *DL);
+ LLT PtrTy = getLLTForType(*PtrIRTy, *DL);
Type *OffsetIRTy = DL->getIndexType(PtrIRTy);
- LLT OffsetTy = TLI->getLLTForType(*OffsetIRTy, *DL);
+ LLT OffsetTy = getLLTForType(*OffsetIRTy, *DL);
uint32_t PtrAddFlags = 0;
// Each PtrAdd generated to implement the GEP inherits its nuw, nusw, inbounds
@@ -1616,9 +1616,9 @@ bool IRTranslator::translateGetElementPtr(const User &U,
BaseReg)
.getReg(0);
PtrIRTy = FixedVectorType::get(PtrIRTy, VectorWidth);
- PtrTy = TLI->getLLTForType(*PtrIRTy, *DL);
+ PtrTy = getLLTForType(*PtrIRTy, *DL);
OffsetIRTy = DL->getIndexType(PtrIRTy);
- OffsetTy = TLI->getLLTForType(*OffsetIRTy, *DL);
+ OffsetTy = getLLTForType(*OffsetIRTy, *DL);
}
int64_t Offset = 0;
@@ -1668,7 +1668,7 @@ bool IRTranslator::translateGetElementPtr(const User &U,
Register GepOffsetReg;
if (ElementSize != 1) {
auto ElementSizeMIB = MIRBuilder.buildConstant(
- TLI->getLLTForType(*OffsetIRTy, *DL), ElementSize);
+ getLLTForType(*OffsetIRTy, *DL), ElementSize);
// The multiplication is NUW if the GEP is NUW and NSW if the GEP is
// NUSW.
@@ -2329,7 +2329,7 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
MIRBuilder.buildFMA(Dst, Op0, Op1, Op2,
MachineInstr::copyFlagsFromInstruction(CI));
} else {
- LLT Ty = TLI->getLLTForType(*CI.getType(), *DL);
+ LLT Ty = getLLTForType(*CI.getType(), *DL);
auto FMul = MIRBuilder.buildFMul(
Ty, Op0, Op1, MachineInstr::copyFlagsFromInstruction(CI));
MIRBuilder.buildFAdd(Dst, FMul, Op2,
@@ -2403,7 +2403,7 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
getStackGuard(getOrCreateVReg(CI), MIRBuilder);
return true;
case Intrinsic::stackprotector: {
- LLT PtrTy = TLI->getLLTForType(*CI.getArgOperand(0)->getType(), *DL);
+ LLT PtrTy = getLLTForType(*CI.getArgOperand(0)->getType(), *DL);
Register GuardVal;
if (TLI->useLoadStackGuardNode(*CI.getModule())) {
GuardVal = MRI->createGenericVirtualRegister(PtrTy);
@@ -2653,7 +2653,7 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
case Intrinsic::vector_deinterleave2: {
// Both intrinsics have at least one operand.
Value *Op0 = CI.getOperand(0);
- LLT ResTy = TLI->getLLTForType(*Op0->getType(), MIRBuilder.getDataLayout());
+ LLT ResTy = getLLTForType(*Op0->getType(), MIRBuilder.getDataLayout());
if (!ResTy.isFixedVector())
return false;
@@ -2710,7 +2710,7 @@ bool IRTranslator::translateCallBase(const CallBase &CB,
for (const auto &Arg : CB.args()) {
if (CLI->supportSwiftError() && isSwiftError(Arg)) {
assert(SwiftInVReg == 0 && "Expected only one swift error argument");
- LLT Ty = TLI->getLLTForType(*Arg->getType(), *DL);
+ LLT Ty = getLLTForType(*Arg->getType(), *DL);
SwiftInVReg = MRI->createGenericVirtualRegister(Ty);
MIRBuilder.buildCopy(SwiftInVReg, SwiftError.getOrCreateVRegUseAt(
&CB, &MIRBuilder.getMBB(), Arg));
@@ -2877,7 +2877,7 @@ bool IRTranslator::translateIntrinsic(
TgtMemIntrinsicInfo->memVT.getTypeForEVT(F->getContext())));
LLT MemTy =
TgtMemIntrinsicInfo->memVT.isSimple()
- ? TLI->getLLTForMVT(TgtMemIntrinsicInfo->memVT.getSimpleVT())
+ ? getLLTForMVT(TgtMemIntrinsicInfo->memVT.getSimpleVT())
: LLT::scalar(TgtMemIntrinsicInfo->memVT.getStoreSizeInBits());
// TODO: We currently just fallback to address space 0 if getTgtMemIntrinsic
@@ -3091,13 +3091,13 @@ bool IRTranslator::translateLandingPad(const User &U,
if (auto *RegMask = TRI.getCustomEHPadPreservedMask(*MF))
MF->getRegInfo().addPhysRegsUsedFromRegMask(RegMask);
- LLT Ty = TLI->getLLTForType(*LP.getType(), *DL);
+ LLT Ty = getLLTForType(*LP.getType(), *DL);
Register Undef = MRI->createGenericVirtualRegister(Ty);
MIRBuilder.buildUndef(Undef);
SmallVector<LLT, 2> Tys;
for (Type *Ty : cast<StructType>(LP.getType())->elements())
- Tys.push_back(TLI->getLLTForType(*Ty, *DL));
+ Tys.push_back(getLLTForType(*Ty, *DL));
assert(Tys.size() == 2 && "Only two-valued landingpads are supported");
// Mark exception register as live in.
@@ -3142,7 +3142,7 @@ bool IRTranslator::translateAlloca(const User &U,
// Now we're in the harder dynamic case.
Register NumElts = getOrCreateVReg(*AI.getArraySize());
Type *IntPtrIRTy = DL->getIntPtrType(AI.getType());
- LLT IntPtrTy = TLI->getLLTForType(*IntPtrIRTy, *DL);
+ LLT IntPtrTy = getLLTForType(*IntPtrIRTy, *DL);
if (MRI->getType(NumElts) != IntPtrTy) {
Register ExtElts = MRI->createGenericVirtualRegister(IntPtrTy);
MIRBuilder.buildZExtOrTrunc(ExtElts, NumElts);
@@ -3949,8 +3949,8 @@ bool IRTranslator::emitSPDescriptorParent(StackProtectorDescriptor &SPD,
CurBuilder->setInsertPt(*ParentBB, ParentBB->end());
// First create the loads to the guard/stack slot for the comparison.
Type *PtrIRTy = PointerType::getUnqual(MF->getFunction().getContext());
- const LLT PtrTy = TLI->getLLTForType(*PtrIRTy, *DL);
- LLT PtrMemTy = TLI->getLLTForMVT(TLI->getPointerMemTy(*DL));
+ const LLT PtrTy = getLLTForType(*PtrIRTy, *DL);
+ LLT PtrMemTy = getLLTForMVT(TLI->getPointerMemTy(*DL));
MachineFrameInfo &MFI = ParentBB->getParent()->getFrameInfo();
int FI = MFI.getStackProtectorIndex();
@@ -4153,6 +4153,10 @@ bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) {
return false;
}
+ // Enable globally extended LLT types.
+ if (TM.Options.EnableGlobalISelExtendedLLT)
+ LLT::setUseExtended(true);
+
// Release the per-function state when we return, whether we succeeded or not.
auto FinalizeOnReturn = make_scope_exit([this]() { finalizeFunction(); });
diff --git a/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp b/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp
index cade075b702f4..cdc1f64dc439f 100644
--- a/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp
@@ -952,7 +952,7 @@ void LoadStoreOpt::initializeStoreMergeTargetInfo(unsigned AddrSpace) {
const auto &LI = *MF->getSubtarget().getLegalizerInfo();
const auto &DL = MF->getFunction().getDataLayout();
Type *IRPtrTy = PointerType::get(MF->getFunction().getContext(), AddrSpace);
- LLT PtrTy = TLI->getLLTForType(*IRPtrTy, DL);
+ LLT PtrTy = getLLTForType(*IRPtrTy, DL);
// We assume that we're not going to be generating any stores wider than
// MaxStoreSizeToForm bits for now.
for (unsigned Size = 2; Size <= MaxStoreSizeToForm; Size *= 2) {
diff --git a/llvm/lib/CodeGen/LowLevelTypeUtils.cpp b/llvm/lib/CodeGen/LowLevelTypeUtils.cpp
index b3f397610c71c..1ebf2e62f3242 100644
--- a/llvm/lib/CodeGen/LowLevelTypeUtils.cpp
+++ b/llvm/lib/CodeGen/LowLevelTypeUtils.cpp
@@ -17,10 +17,10 @@
#include "llvm/IR/DerivedTypes.h"
using namespace llvm;
-LLT llvm::getLLTForType(Type &Ty, const DataLayout &DL, bool AllowExtendedLLT) {
+LLT llvm::getLLTForType(Type &Ty, const DataLayout &DL) {
if (auto *VTy = dyn_cast<VectorType>(&Ty)) {
auto EC = VTy->getElementCount();
- LLT ScalarTy = getLLTForType(*VTy->getElementType(), DL, AllowExtendedLLT);
+ LLT ScalarTy = getLLTForType(*VTy->getElementType(), DL);
if (EC.isScalar())
return ScalarTy;
return LLT::vector(EC, ScalarTy);
@@ -38,7 +38,7 @@ LLT llvm::getLLTForType(Type &Ty, const DataLayout &DL, bool AllowExtendedLLT) {
assert(SizeInBits != 0 && "invalid zero-sized type");
// Return simple scalar
- if (!AllowExtendedLLT)
+ if (!LLT::getUseExtended())
return LLT::scalar(SizeInBits);
// Choose more precise LLT variant
@@ -109,9 +109,7 @@ EVT llvm::getApproximateEVTForLLT(LLT Ty, LLVMContext &Ctx) {
return EVT::getIntegerVT(Ctx, Ty.getSizeInBits());
}
-LLT llvm::getLLTForMVT(MVT VT, bool AllowExtendedLLT) {
- return LLT(VT, AllowExtendedLLT);
-}
+LLT llvm::getLLTForMVT(MVT VT) { return LLT(VT); }
const llvm::fltSemantics &llvm::getFltSemanticForLLT(LLT Ty) {
assert((Ty.isAnyScalar() || Ty.isFloat()) &&
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 2abed21acdab3..dd8f18d3b8a6a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -2482,7 +2482,7 @@ void SelectionDAGISel::Select_READ_REGISTER(SDNode *Op) {
const MDString *RegStr = cast<MDString>(MD->getMD()->getOperand(0));
EVT VT = Op->getValueType(0);
- LLT Ty = VT.isSimple() ? TLI->getLLTForMVT(VT.getSimpleVT()) : LLT();
+ LLT Ty = VT.isSimple() ? getLLTForMVT(VT.getSimpleVT()) : LLT();
const MachineFunction &MF = CurDAG->getMachineFunction();
Register Reg = TLI->getRegisterByName(RegStr->getString().data(), Ty, MF);
@@ -2513,7 +2513,7 @@ void SelectionDAGISel::Select_WRITE_REGISTER(SDNode *Op) {
const MDString *RegStr = cast<MDString>(MD->getMD()->getOperand(0));
EVT VT = Op->getOperand(2).getValueType();
- LLT Ty = VT.isSimple() ? TLI->getLLTForMVT(VT.getSimpleVT()) : LLT();
+ LLT Ty = VT.isSimple() ? getLLTForMVT(VT.getSimpleVT()) : LLT();
const MachineFunction &MF = CurDAG->getMachineFunction();
Register Reg = TLI->getRegisterByName(RegStr->getString().data(), Ty, MF);
diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp
index 968e8a88e9dfa..1d674b283db15 100644
--- a/llvm/lib/CodeGen/TargetLoweringBase.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp
@@ -1051,14 +1051,6 @@ EVT TargetLoweringBase::getShiftAmountTy(EVT LHSTy,
return ShiftVT;
}
-LLT TargetLoweringBase::getLLTForType(Type &Ty, const DataLayout &DL) const {
- return llvm::getLLTForType(Ty, DL, TM.Options.EnableGlobalISelExtendedLLT);
-}
-
-LLT TargetLoweringBase::getLLTForMVT(MVT Ty) const {
- return llvm::getLLTForMVT(Ty, TM.Options.EnableGlobalISelExtendedLLT);
-}
-
bool TargetLoweringBase::canOpTrap(unsigned Op, EVT VT) const {
assert(isTypeLegal(VT));
switch (Op) {
diff --git a/llvm/lib/CodeGenTypes/LowLevelType.cpp b/llvm/lib/CodeGenTypes/LowLevelType.cpp
index 229c9d542fe9e..9418d54058c4b 100644
--- a/llvm/lib/CodeGenTypes/LowLevelType.cpp
+++ b/llvm/lib/CodeGenTypes/LowLevelType.cpp
@@ -16,6 +16,8 @@
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
+bool LLT::ExtendedLLT = false;
+
// Repeat logic of MVT::getFltSemantics to exclude CodeGen dependency
static LLT::FpSemantics getFpSemanticsForMVT(MVT VT) {
switch (VT.getScalarType().SimpleTy) {
@@ -38,8 +40,8 @@ static LLT::FpSemantics getFpSemanticsForMVT(MVT VT) {
}
}
-LLT::LLT(MVT VT, bool AllowExtendedLLT) {
- if (!AllowExtendedLLT) {
+LLT::LLT(MVT VT) {
+ if (!ExtendedLLT) {
if (VT.isVector()) {
bool AsVector = VT.getVectorMinNumElements() > 1 || VT.isScalableVector();
Kind Info = AsVector ? Kind::VECTOR_ANY : Kind::ANY_SCALAR;
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
index 0d5379b61e954..7907a3c283624 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp
@@ -457,7 +457,7 @@ bool AArch64CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
ExtendOp = TargetOpcode::G_ZEXT;
LLT NewLLT(NewVT);
- LLT OldLLT = TLI.getLLTForType(*CurArgInfo.Ty, DL);
+ LLT OldLLT = getLLTForType(*CurArgInfo.Ty, DL);
CurArgInfo.Ty = EVT(NewVT).getTypeForEVT(Ctx);
// Instead of an extend, we might have a vector type which needs
// padding with more elements, e.g. <2 x half> -> <4 x half>.
@@ -1397,7 +1397,7 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
// is set.
if (Info.Callee.isSymbol() && F.getParent()->getRtLibUseGOT()) {
auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_GLOBAL_VALUE);
- DstOp(TLI.getLLTForType(*F.getType(), DL)).addDefToMIB(MRI, MIB);
+ DstOp(getLLTForType(*F.getType(), DL)).addDefToMIB(MRI, MIB);
MIB.addExternalSymbol(Info.Callee.getSymbolName(), AArch64II::MO_GOT);
Info.Callee = MachineOperand::CreateReg(MIB.getReg(0), false);
}
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp
index c39d7f7a55f34..78d6a21808ee9 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp
@@ -332,7 +332,7 @@ bool AMDGPUCallLowering::lowerReturnVal(MachineIRBuilder &B,
extOpcodeToISDExtOpcode(ExtendOp));
if (ExtVT != VT) {
RetInfo.Ty = ExtVT.getTypeForEVT(Ctx);
- LLT ExtTy = TLI.getLLTForType(*RetInfo.Ty, DL);
+ LLT ExtTy = getLLTForType(*RetInfo.Ty, DL);
Reg = B.buildInstr(ExtendOp, {ExtTy}, {Reg}).getReg(0);
}
}
@@ -428,7 +428,7 @@ void AMDGPUCallLowering::lowerParameter(MachineIRBuilder &B, ArgInfo &OrigArg,
Register PtrReg = B.getMRI()->createGenericVirtualRegister(PtrTy);
lowerParameterPtr(PtrReg, B, Offset + FieldOffsets[Idx]);
- LLT ArgTy = TLI.getLLTForType(*SplitArg.Ty, DL);
+ LLT ArgTy = getLLTForType(*SplitArg.Ty, DL);
if (SplitArg.Flags[0].isPointer()) {
// Compensate for losing pointeriness in splitValueTypes.
LLT PtrTy = LLT::pointer(SplitArg.Flags[0].getPointerAddrSpace(),
diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
index 308db1f2ca205..9f7069e04f85a 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
+++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
@@ -24,11 +24,6 @@ STATISTIC(NumPatternEmitted, "Number of patterns emitted");
using namespace llvm;
using namespace gi;
-static cl::opt<bool>
- AllowExtendedLLT("gisel-extended-llt",
- cl::desc("Generate extended llt names in match tables"),
- cl::init(false));
-
// FIXME: Use createStringError instead.
static Error failUnsupported(const Twine &Reason) {
return make_error<StringError>(Reason, inconvertibleErrorCode());
@@ -473,10 +468,10 @@ bool LLTCodeGen::operator<(const LLTCodeGen &Other) const {
std::optional<LLTCodeGen> llvm::gi::MVTToLLT(MVT VT) {
if (VT.isVector() && !VT.getVectorElementCount().isScalar())
- return LLTCodeGen(LLT(VT, AllowExtendedLLT));
+ return LLTCodeGen(LLT(VT));
if (VT.isInteger() || VT.isFloatingPoint())
- return LLTCodeGen(LLT(VT, AllowExtendedLLT));
+ return LLTCodeGen(LLT(VT));
return std::nullopt;
}
diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp
index 333d956a4ff3b..27dc02ccb1646 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp
+++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp
@@ -8,10 +8,20 @@
#include "GlobalISelMatchTableExecutorEmitter.h"
#include "GlobalISelMatchTable.h"
+#include "llvm/Support/CommandLine.h"
using namespace llvm;
using namespace llvm::gi;
+static cl::opt<bool>
+ AllowExtendedLLT("gisel-extended-llt",
+ cl::desc("Generate extended llt names in match tables"),
+ cl::init(false));
+
+GlobalISelMatchTableExecutorEmitter::GlobalISelMatchTableExecutorEmitter() {
+ LLT::setUseExtended(AllowExtendedLLT);
+}
+
void GlobalISelMatchTableExecutorEmitter::emitSubtargetFeatureBitsetImpl(
raw_ostream &OS, ArrayRef<RuleMatcher> Rules) {
SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures,
diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h
index 1f66d73f77576..c56e0549f1ec6 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h
+++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h
@@ -188,7 +188,7 @@ class GlobalISelMatchTableExecutorEmitter {
Comment);
}
- GlobalISelMatchTableExecutorEmitter() = default;
+ GlobalISelMatchTableExecutorEmitter();
public:
virtual ~GlobalISelMatchTableExecutorEmitter() = default;
>From 899e79e58c29d3227790f37d299f3b4987862b21 Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Sat, 6 Dec 2025 15:05:28 +0300
Subject: [PATCH 24/40] Remove TargetOption::EnableGlobalISelExtendedLLT.
Targets must use LLT::setUseExtended instead.
---
llvm/include/llvm/Target/TargetMachine.h | 3 ---
llvm/include/llvm/Target/TargetOptions.h | 7 +------
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 12 ++++--------
3 files changed, 5 insertions(+), 17 deletions(-)
diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h
index 9099683967398..d0fd483a8ddaa 100644
--- a/llvm/include/llvm/Target/TargetMachine.h
+++ b/llvm/include/llvm/Target/TargetMachine.h
@@ -295,9 +295,6 @@ class LLVM_ABI TargetMachine {
bool getO0WantsFastISel() { return O0WantsFastISel; }
void setO0WantsFastISel(bool Enable) { O0WantsFastISel = Enable; }
void setGlobalISel(bool Enable) { Options.EnableGlobalISel = Enable; }
- void setGlobalISelExtendedLLT(bool Enable) {
- Options.EnableGlobalISelExtendedLLT = Enable;
- }
void setGlobalISelAbort(GlobalISelAbortMode Mode) {
Options.GlobalISelAbort = Mode;
}
diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h
index 123bb94a53dc4..0312515d11798 100644
--- a/llvm/include/llvm/Target/TargetOptions.h
+++ b/llvm/include/llvm/Target/TargetOptions.h
@@ -123,8 +123,7 @@ class TargetOptions {
NoSignedZerosFPMath(false), EnableAIXExtendedAltivecABI(false),
HonorSignDependentRoundingFPMathOption(false), NoZerosInBSS(false),
GuaranteedTailCallOpt(false), StackSymbolOrdering(true),
- EnableFastISel(false), EnableGlobalISel(false),
- EnableGlobalISelExtendedLLT(false), UseInitArray(false),
+ EnableFastISel(false), EnableGlobalISel(false), UseInitArray(false),
DisableIntegratedAS(false), FunctionSections(false),
DataSections(false), IgnoreXCOFFVisibility(false),
XCOFFTracebackTable(true), UniqueSectionNames(true),
@@ -223,10 +222,6 @@ class TargetOptions {
/// EnableGlobalISel - This flag enables global instruction selection.
unsigned EnableGlobalISel : 1;
- /// EnableGlobalISelExtendedLLT - This flag enables LLTs with extended type
- /// info so target may distinguish different formats of equal sized scalars.
- unsigned EnableGlobalISelExtendedLLT : 1;
-
/// EnableGlobalISelAbort - Control abort behaviour when global instruction
/// selection fails to lower/select an instruction.
GlobalISelAbortMode GlobalISelAbort = GlobalISelAbortMode::Enable;
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 74bc88df79495..c7151dc2a3190 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -3814,12 +3814,12 @@ bool IRTranslator::translate(const Constant &C, Register Reg) {
bool IRTranslator::mayTranslateUserTypes(const User &U) const {
const TargetMachine &TM = TLI->getTargetMachine();
- if (TLI->getTargetMachine().Options.EnableGlobalISelExtendedLLT)
+ if (LLT::getUseExtended())
return true;
- // BF16 cannot currently be represented by default LLT, to avoid miscompiles
- // we prevent any instructions using them in targets with disabled
- // TargetOptions::EnableGlobalISelExtendedLLT.
+ // BF16 cannot currently be represented by default LLT. To avoid miscompiles
+ // we prevent any instructions using them by default in all targets that do
+ // not explicitly enable it via LLT::setUseExtended(true).
// SPIRV target is exception.
return TM.getTargetTriple().isSPIRV() ||
(!U.getType()->getScalarType()->isBFloatTy() &&
@@ -4153,10 +4153,6 @@ bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) {
return false;
}
- // Enable globally extended LLT types.
- if (TM.Options.EnableGlobalISelExtendedLLT)
- LLT::setUseExtended(true);
-
// Release the per-function state when we return, whether we succeeded or not.
auto FinalizeOnReturn = make_scope_exit([this]() { finalizeFunction(); });
>From 0fa794a1f5a090b7c32a651812d7088567730c03 Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Sat, 6 Dec 2025 16:17:11 +0300
Subject: [PATCH 25/40] Fix after merge
---
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 2 +-
llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp | 5 +++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index fc00ce3aee1a8..2dcff723be3a4 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -3057,7 +3057,7 @@ bool IRTranslator::translateInvoke(const User &U,
/// intrinsics such as amdgcn.kill.
bool IRTranslator::translateCallBr(const User &U,
MachineIRBuilder &MIRBuilder) {
- if (containsBF16Type(U))
+ if (!mayTranslateUserTypes(U))
return false; // see translateCall
const CallBrInst &I = cast<CallBrInst>(U);
diff --git a/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp b/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp
index ffac39e90bb6a..2f39416010235 100644
--- a/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp
+++ b/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp
@@ -90,8 +90,8 @@ TEST_F(AArch64IRTranslatorTest, IRTranslateBfloat16) {
M->setDataLayout(TM->createDataLayout());
TM->setGlobalISel(true);
- TM->setGlobalISelExtendedLLT(true);
TM->setGlobalISelAbort(GlobalISelAbortMode::DisableWithDiag);
+ LLT::setUseExtended(true);
legacy::PassManager PM;
TargetPassConfig *TPC(TM->createPassConfig(PM));
@@ -124,7 +124,8 @@ TEST_F(AArch64IRTranslatorTest, IRTranslateBfloat16) {
MMI->deleteMachineFunctionFor(*F);
// Run again without extended LLT
- TM->setGlobalISelExtendedLLT(false);
+ LLT::setUseExtended(false);
+
PM.run(*M);
MF = MMI->getMachineFunction(*F);
ASSERT_TRUE(MF->getProperties().hasProperty(
>From 97c78325010dd46f9dde1d8c9c9758dc174c38df Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Sun, 21 Dec 2025 21:42:57 +0300
Subject: [PATCH 26/40] review fixes
---
llvm/include/llvm/CodeGen/Analysis.h | 2 +-
llvm/include/llvm/CodeGenTypes/LowLevelType.h | 146 +++++++++++-------
llvm/lib/CodeGen/Analysis.cpp | 8 +-
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 4 +-
llvm/lib/CodeGen/MIRParser/MIParser.cpp | 12 +-
llvm/lib/CodeGenTypes/LowLevelType.cpp | 30 ++--
6 files changed, 120 insertions(+), 82 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/Analysis.h b/llvm/include/llvm/CodeGen/Analysis.h
index b60029d1d7398..2f1364d199710 100644
--- a/llvm/include/llvm/CodeGen/Analysis.h
+++ b/llvm/include/llvm/CodeGen/Analysis.h
@@ -87,7 +87,7 @@ void ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL, Type *Ty,
/// If Offsets is non-null, it points to a vector to be filled in
/// with the in-memory offsets of each of the individual values.
///
-void computeValueLLTs(const TargetLowering &TLI, const DataLayout &DL, Type &Ty,
+void computeValueLLTs(const DataLayout &DL, Type &Ty,
SmallVectorImpl<LLT> &ValueTys,
SmallVectorImpl<uint64_t> *Offsets = nullptr,
uint64_t StartingOffset = 0);
diff --git a/llvm/include/llvm/CodeGenTypes/LowLevelType.h b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
index fbbb4bd0d1de1..33cb4d0b5e771 100644
--- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h
+++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
@@ -9,17 +9,19 @@
/// Implement a low-level type suitable for MachineInstr level instruction
/// selection.
///
-/// For a type attached to a MachineInstr, we only care about 2 details: total
-/// size and the number of vector lanes (if any). Accordingly, there are 4
-/// possible valid type-kinds:
+/// For a type attached to a MachineInstr, we care about total
+/// size, the number of vector lanes (if any)
+/// and the kind of the type (anyscalar, integer, float and etc).
+/// Floating point are filled with APFloat::Semantics to make them
+/// distinguishable.
///
-/// * `sN` for scalars and aggregates
-/// * `<N x sM>` for vectors, which must have at least 2 elements.
-/// * `pN` for pointers
+/// Earlier other information required for correct selection was expected to be
+/// carried only by the opcode, or non-type flags. For example the distinction
+/// between G_ADD and G_FADD for int/float or fast-math flags.
///
-/// Other information required for correct selection is expected to be carried
-/// by the opcode, or non-type flags. For example the distinction between G_ADD
-/// and G_FADD for int/float or fast-math flags.
+/// Now we also able to rely on the kind of the type.
+/// This may be useful to distinguish different types of the same size used at
+/// the same opcode, for example, G_FADD with half vs G_FADD with bfloat16.
///
//===----------------------------------------------------------------------===//
@@ -84,40 +86,35 @@ class LLT {
/// Get a low-level scalar or aggregate "bag of bits".
static constexpr LLT scalar(unsigned SizeInBits) {
- return LLT{Kind::ANY_SCALAR, ElementCount::getFixed(0), SizeInBits,
- /*AddressSpace=*/0, static_cast<FpSemantics>(0)};
+ return LLT{Kind::ANY_SCALAR, ElementCount::getFixed(0), SizeInBits};
}
static constexpr LLT integer(unsigned SizeInBits) {
- return LLT{Kind::INTEGER, ElementCount::getFixed(0), SizeInBits,
- /*AddressSpace=*/0, static_cast<FpSemantics>(0)};
+ return LLT{Kind::INTEGER, ElementCount::getFixed(0), SizeInBits};
}
static LLT floatingPoint(const FpSemantics &Sem) {
return LLT{Kind::FLOAT, ElementCount::getFixed(0),
- APFloat::getSizeInBits(APFloatBase::EnumToSemantics(Sem)),
- /*AddressSpace=*/0, Sem};
+ APFloat::getSizeInBits(APFloatBase::EnumToSemantics(Sem)), Sem};
}
/// Get a low-level token; just a scalar with zero bits (or no size).
static constexpr LLT token() {
return LLT{Kind::ANY_SCALAR, ElementCount::getFixed(0),
- /*SizeInBits=*/0,
- /*AddressSpace=*/0, static_cast<FpSemantics>(0)};
+ /*SizeInBits=*/0};
}
/// 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{Kind::POINTER, ElementCount::getFixed(0), SizeInBits,
- AddressSpace, static_cast<FpSemantics>(0)};
+ AddressSpace};
}
/// Get a low-level vector of some number of elements and element width.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits) {
assert(!EC.isScalar() && "invalid number of vector elements");
- return LLT{Kind::VECTOR_ANY, EC, ScalarSizeInBits,
- /*AddressSpace=*/0, static_cast<FpSemantics>(0)};
+ return LLT{Kind::VECTOR_ANY, EC, ScalarSizeInBits};
}
/// Get a low-level vector of some number of elements and element type.
@@ -126,10 +123,14 @@ class LLT {
assert(!ScalarTy.isVector() && "invalid vector element type");
Kind Info = toVector(ScalarTy.Info);
- return LLT{Info, EC, ScalarTy.getSizeInBits().getFixedValue(),
- ScalarTy.isPointer() ? ScalarTy.getAddressSpace() : 0,
- ScalarTy.isFloat() ? ScalarTy.getFpSemantics()
- : static_cast<FpSemantics>(0)};
+ if (ScalarTy.isPointer())
+ return LLT{Info, EC, ScalarTy.getSizeInBits().getFixedValue(),
+ ScalarTy.getAddressSpace()};
+ if (ScalarTy.isFloat())
+ return LLT{Info, EC, ScalarTy.getSizeInBits().getFixedValue(),
+ ScalarTy.getFpSemantics()};
+
+ return LLT{Info, EC, ScalarTy.getSizeInBits().getFixedValue()};
}
static constexpr LLT floatIEEE(unsigned SizeInBits) {
@@ -149,40 +150,40 @@ class LLT {
// Get a bfloat16 value.
static constexpr LLT bfloat16() {
- return LLT{Kind::FLOAT, ElementCount::getFixed(0), 16, 0,
+ return LLT{Kind::FLOAT, ElementCount::getFixed(0), 16,
FpSemantics::S_BFloat};
}
/// Get a 16-bit IEEE half value.
static constexpr LLT float16() {
- return LLT{Kind::FLOAT, ElementCount::getFixed(0), 16, 0,
+ return LLT{Kind::FLOAT, ElementCount::getFixed(0), 16,
FpSemantics::S_IEEEhalf};
}
/// Get a 32-bit IEEE float value.
static constexpr LLT float32() {
- return LLT{Kind::FLOAT, ElementCount::getFixed(0), 32, 0,
+ return LLT{Kind::FLOAT, ElementCount::getFixed(0), 32,
FpSemantics::S_IEEEsingle};
}
/// Get a 64-bit IEEE double value.
static constexpr LLT float64() {
- return LLT{Kind::FLOAT, ElementCount::getFixed(0), 64, 0,
+ return LLT{Kind::FLOAT, ElementCount::getFixed(0), 64,
FpSemantics::S_IEEEdouble};
}
/// Get a 80-bit X86 floating point value.
static constexpr LLT x86fp80() {
- return LLT{Kind::FLOAT, ElementCount::getFixed(0), 80, 0,
+ return LLT{Kind::FLOAT, ElementCount::getFixed(0), 80,
FpSemantics::S_x87DoubleExtended};
}
/// Get a 128-bit IEEE quad value.
static constexpr LLT float128() {
- return LLT{Kind::FLOAT, ElementCount::getFixed(0), 128, 0,
+ return LLT{Kind::FLOAT, ElementCount::getFixed(0), 128,
FpSemantics::S_IEEEquad};
}
/// Get a 128-bit PowerPC double double value.
static constexpr LLT ppcf128() {
- return LLT{Kind::FLOAT, ElementCount::getFixed(0), 128, 0,
+ return LLT{Kind::FLOAT, ElementCount::getFixed(0), 128,
FpSemantics::S_PPCDoubleDouble};
}
@@ -224,10 +225,21 @@ class LLT {
return scalarOrVector(EC, LLT::scalar(static_cast<unsigned>(ScalarSize)));
}
+ explicit constexpr LLT(Kind Info, ElementCount EC, uint64_t SizeInBits)
+ : LLT() {
+ init(Info, EC, SizeInBits);
+ }
+
+ explicit constexpr LLT(Kind Info, ElementCount EC, uint64_t SizeInBits,
+ unsigned AddressSpace)
+ : LLT() {
+ init(Info, EC, SizeInBits, AddressSpace);
+ }
+
explicit constexpr LLT(Kind Info, ElementCount EC, uint64_t SizeInBits,
- unsigned AddressSpace, FpSemantics Sem)
+ FpSemantics Sem)
: LLT() {
- init(Info, EC, SizeInBits, AddressSpace, Sem);
+ init(Info, EC, SizeInBits, Sem);
}
LLVM_ABI explicit LLT(MVT VT);
@@ -241,7 +253,7 @@ class LLT {
constexpr bool isInteger() const { return Info == Kind::INTEGER; }
constexpr bool isFloat() const { return Info == Kind::FLOAT; }
constexpr bool isPointer() const { return Info == Kind::POINTER; }
- constexpr bool isVectorAny() const { return Info == Kind::VECTOR_ANY; }
+ constexpr bool isAnyVector() const { return Info == Kind::VECTOR_ANY; }
constexpr bool isIntegerVector() const {
return Info == Kind::VECTOR_INTEGER;
}
@@ -272,23 +284,21 @@ class LLT {
constexpr bool isFloat(unsigned Size) const {
return isFloat() && getScalarSizeInBits() == Size;
}
- constexpr bool isFloatWithSem(FpSemantics Sem) const {
+ constexpr bool isFloat(FpSemantics Sem) const {
return isFloat() && getFpSemantics() == Sem;
}
constexpr bool isFloatIEEE() const {
- return isFloatWithSem(APFloatBase::S_IEEEhalf) ||
- isFloatWithSem(APFloatBase::S_IEEEsingle) ||
- isFloatWithSem(APFloatBase::S_IEEEdouble) ||
- isFloatWithSem(APFloatBase::S_IEEEquad);
- }
- constexpr bool isBFloat16() const {
- return isFloatWithSem(FpSemantics::S_BFloat);
+ return isFloat(APFloatBase::S_IEEEhalf) ||
+ isFloat(APFloatBase::S_IEEEsingle) ||
+ isFloat(APFloatBase::S_IEEEdouble) ||
+ isFloat(APFloatBase::S_IEEEquad);
}
+ constexpr bool isBFloat16() const { return isFloat(FpSemantics::S_BFloat); }
constexpr bool isX86FP80() const {
- return isFloatWithSem(FpSemantics::S_x87DoubleExtended);
+ return isFloat(FpSemantics::S_x87DoubleExtended);
}
constexpr bool isPPCF128() const {
- return isFloatWithSem(FpSemantics::S_PPCDoubleDouble);
+ return isFloat(FpSemantics::S_PPCDoubleDouble);
}
/// Returns the number of elements in a vector LLT. Must only be called on
@@ -578,21 +588,51 @@ class LLT {
return getMask(FieldInfo) & (RawData >> FieldInfo[1]);
}
- constexpr void init(Kind Info, ElementCount EC, uint64_t SizeInBits,
- unsigned AddressSpace, FpSemantics Sem) {
+ // Init for scalar and integer single or vector types
+ constexpr void init(Kind Info, ElementCount EC, uint64_t SizeInBits) {
assert(SizeInBits <= std::numeric_limits<unsigned>::max() &&
"Not enough bits in LLT to represent size");
+ assert((Info == Kind::ANY_SCALAR || Info == Kind::INTEGER ||
+ Info == Kind::VECTOR_ANY || Info == Kind::VECTOR_INTEGER) &&
+ "Called initializer for wrong LLT Kind");
this->Info = Info;
- if (Info == Kind::POINTER || Info == Kind::VECTOR_POINTER) {
- RawData = maskAndShift(SizeInBits, PointerSizeFieldInfo) |
- maskAndShift(AddressSpace, PointerAddressSpaceFieldInfo);
- } else {
+ RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo);
+
+ if (Info == Kind::VECTOR_ANY || Info == Kind::VECTOR_INTEGER) {
RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo) |
- maskAndShift((uint64_t)Sem, FpSemanticFieldInfo);
+ maskAndShift(EC.getKnownMinValue(), VectorElementsFieldInfo) |
+ maskAndShift(EC.isScalable() ? 1 : 0, VectorScalableFieldInfo);
}
+ }
+
+ // Init pointer or pointer vector
+ constexpr void init(Kind Info, ElementCount EC, uint64_t SizeInBits,
+ unsigned AddressSpace) {
+ assert(SizeInBits <= std::numeric_limits<unsigned>::max() &&
+ "Not enough bits in LLT to represent size");
+ assert((Info == Kind::POINTER || Info == Kind::VECTOR_POINTER) &&
+ "Called initializer for wrong LLT Kind");
+ this->Info = Info;
+ RawData = maskAndShift(SizeInBits, PointerSizeFieldInfo) |
+ maskAndShift(AddressSpace, PointerAddressSpaceFieldInfo);
+
+ if (Info == Kind::VECTOR_POINTER) {
+ RawData |= maskAndShift(EC.getKnownMinValue(), VectorElementsFieldInfo) |
+ maskAndShift(EC.isScalable() ? 1 : 0, VectorScalableFieldInfo);
+ }
+ }
+
+ constexpr void init(Kind Info, ElementCount EC, uint64_t SizeInBits,
+ FpSemantics Sem) {
+ assert(SizeInBits <= std::numeric_limits<unsigned>::max() &&
+ "Not enough bits in LLT to represent size");
+ assert((Info == Kind::FLOAT || Info == Kind::VECTOR_FLOAT) &&
+ "Called initializer for wrong LLT Kind");
+ this->Info = Info;
+ RawData = maskAndShift(SizeInBits, ScalarSizeFieldInfo) |
+ maskAndShift((uint64_t)Sem, FpSemanticFieldInfo);
- if (Info == Kind::VECTOR_ANY || Info == Kind::VECTOR_INTEGER ||
- Info == Kind::VECTOR_FLOAT || Info == Kind::VECTOR_POINTER) {
+ if (Info == Kind::VECTOR_FLOAT) {
RawData |= maskAndShift(EC.getKnownMinValue(), VectorElementsFieldInfo) |
maskAndShift(EC.isScalable() ? 1 : 0, VectorScalableFieldInfo);
}
diff --git a/llvm/lib/CodeGen/Analysis.cpp b/llvm/lib/CodeGen/Analysis.cpp
index f16c35ce3f259..f5fbfb7e5e21d 100644
--- a/llvm/lib/CodeGen/Analysis.cpp
+++ b/llvm/lib/CodeGen/Analysis.cpp
@@ -146,8 +146,8 @@ void llvm::ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL,
}
}
-void llvm::computeValueLLTs(const TargetLowering &TLI, const DataLayout &DL,
- Type &Ty, SmallVectorImpl<LLT> &ValueTys,
+void llvm::computeValueLLTs(const DataLayout &DL, Type &Ty,
+ SmallVectorImpl<LLT> &ValueTys,
SmallVectorImpl<uint64_t> *Offsets,
uint64_t StartingOffset) {
// Given a struct type, recursively traverse the elements.
@@ -158,7 +158,7 @@ void llvm::computeValueLLTs(const TargetLowering &TLI, const DataLayout &DL,
const StructLayout *SL = Offsets ? DL.getStructLayout(STy) : nullptr;
for (unsigned I = 0, E = STy->getNumElements(); I != E; ++I) {
uint64_t EltOffset = SL ? SL->getElementOffset(I) : 0;
- computeValueLLTs(TLI, DL, *STy->getElementType(I), ValueTys, Offsets,
+ computeValueLLTs(DL, *STy->getElementType(I), ValueTys, Offsets,
StartingOffset + EltOffset);
}
return;
@@ -168,7 +168,7 @@ void llvm::computeValueLLTs(const TargetLowering &TLI, const DataLayout &DL,
Type *EltTy = ATy->getElementType();
uint64_t EltSize = DL.getTypeAllocSize(EltTy).getFixedValue();
for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i)
- computeValueLLTs(TLI, DL, *EltTy, ValueTys, Offsets,
+ computeValueLLTs(DL, *EltTy, ValueTys, Offsets,
StartingOffset + i * EltSize);
return;
}
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 2dcff723be3a4..23178610c16d1 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -193,7 +193,7 @@ IRTranslator::allocateVRegs(const Value &Val) {
auto *Regs = VMap.getVRegs(Val);
auto *Offsets = VMap.getOffsets(Val);
SmallVector<LLT, 4> SplitTys;
- computeValueLLTs(*TLI, *DL, *Val.getType(), SplitTys,
+ computeValueLLTs(*DL, *Val.getType(), SplitTys,
Offsets->empty() ? Offsets : nullptr);
for (unsigned i = 0; i < SplitTys.size(); ++i)
Regs->push_back(0);
@@ -217,7 +217,7 @@ ArrayRef<Register> IRTranslator::getOrCreateVRegs(const Value &Val) {
"Don't know how to create an empty vreg");
SmallVector<LLT, 4> SplitTys;
- computeValueLLTs(*TLI, *DL, *Val.getType(), SplitTys,
+ computeValueLLTs(*DL, *Val.getType(), SplitTys,
Offsets->empty() ? Offsets : nullptr);
if (!isa<Constant>(Val)) {
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 9c35ec552b62c..26de822b4c344 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -1952,8 +1952,8 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
"expected integers after 's'/'i'/'f'/'bf'/'p' type identifier");
}
- if (Token.range().starts_with("s") || Token.range().starts_with("i")) {
- bool ScalarOrInt = Token.range().starts_with("s");
+ bool Scalar = Token.range().starts_with("s");
+ if (Scalar || Token.range().starts_with("i")) {
auto ScalarSize = APSInt(TypeDigits).getZExtValue();
if (!ScalarSize) {
Ty = LLT::token();
@@ -1964,7 +1964,7 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
if (!verifyScalarSize(ScalarSize))
return error("invalid size for scalar type");
- Ty = ScalarOrInt ? LLT::scalar(ScalarSize) : LLT::integer(ScalarSize);
+ Ty = Scalar ? LLT::scalar(ScalarSize) : LLT::integer(ScalarSize);
lex();
return false;
}
@@ -2042,12 +2042,12 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) {
return error(
"expected integers after 's'/'i'/'f'/'bf'/'p' type identifier");
- if (Token.range().starts_with("s") || Token.range().starts_with("i")) {
- bool ScalarOrInt = Token.range().starts_with("s");
+ Scalar = Token.range().starts_with("s");
+ if (Scalar || Token.range().starts_with("i")) {
auto ScalarSize = APSInt(VectorTyDigits).getZExtValue();
if (!verifyScalarSize(ScalarSize))
return error("invalid size for scalar element in vector");
- Ty = ScalarOrInt ? LLT::scalar(ScalarSize) : LLT::integer(ScalarSize);
+ Ty = Scalar ? LLT::scalar(ScalarSize) : LLT::integer(ScalarSize);
} else if (Token.range().starts_with("p")) {
const DataLayout &DL = MF.getDataLayout();
uint64_t AS = APSInt(VectorTyDigits).getZExtValue();
diff --git a/llvm/lib/CodeGenTypes/LowLevelType.cpp b/llvm/lib/CodeGenTypes/LowLevelType.cpp
index 9418d54058c4b..484329e918903 100644
--- a/llvm/lib/CodeGenTypes/LowLevelType.cpp
+++ b/llvm/lib/CodeGenTypes/LowLevelType.cpp
@@ -18,7 +18,6 @@ using namespace llvm;
bool LLT::ExtendedLLT = false;
-// Repeat logic of MVT::getFltSemantics to exclude CodeGen dependency
static LLT::FpSemantics getFpSemanticsForMVT(MVT VT) {
switch (VT.getScalarType().SimpleTy) {
default:
@@ -46,11 +45,9 @@ LLT::LLT(MVT VT) {
bool AsVector = VT.getVectorMinNumElements() > 1 || VT.isScalableVector();
Kind Info = AsVector ? Kind::VECTOR_ANY : Kind::ANY_SCALAR;
init(Info, VT.getVectorElementCount(),
- VT.getVectorElementType().getSizeInBits(), 0,
- static_cast<FpSemantics>(0));
+ VT.getVectorElementType().getSizeInBits());
} else if (VT.isValid() && !VT.isScalableTargetExtVT()) {
- init(Kind::ANY_SCALAR, ElementCount::getFixed(0), VT.getSizeInBits(), 0,
- static_cast<FpSemantics>(0));
+ init(Kind::ANY_SCALAR, ElementCount::getFixed(0), VT.getSizeInBits());
} else {
this->Info = Kind::INVALID;
this->RawData = 0;
@@ -59,23 +56,24 @@ LLT::LLT(MVT VT) {
}
bool IsFloatingPoint = VT.isFloatingPoint();
- FpSemantics FpSem =
- IsFloatingPoint ? getFpSemanticsForMVT(VT) : static_cast<FpSemantics>(0);
bool AsVector = VT.isVector() &&
(VT.getVectorMinNumElements() > 1 || VT.isScalableVector());
- LLT::Kind Info;
- if (IsFloatingPoint)
- Info = AsVector ? LLT::Kind::VECTOR_FLOAT : LLT::Kind::FLOAT;
- else
- Info = AsVector ? LLT::Kind::VECTOR_INTEGER : LLT::Kind::INTEGER;
- if (VT.isVector()) {
- init(Info, VT.getVectorElementCount(),
- VT.getVectorElementType().getSizeInBits(), 0, FpSem);
+ if (AsVector) {
+ if (IsFloatingPoint)
+ init(LLT::Kind::VECTOR_FLOAT, VT.getVectorElementCount(),
+ VT.getVectorElementType().getSizeInBits(), getFpSemanticsForMVT(VT));
+ else
+ init(LLT::Kind::VECTOR_INTEGER, VT.getVectorElementCount(),
+ VT.getVectorElementType().getSizeInBits());
} else if (VT.isValid() && !VT.isScalableTargetExtVT()) {
// Aggregates are no different from real scalars as far as GlobalISel is
// concerned.
- init(Info, ElementCount::getFixed(0), VT.getSizeInBits(), 0, FpSem);
+ if (IsFloatingPoint)
+ init(LLT::Kind::FLOAT, ElementCount::getFixed(0), VT.getSizeInBits(),
+ getFpSemanticsForMVT(VT));
+ else
+ init(LLT::Kind::INTEGER, ElementCount::getFixed(0), VT.getSizeInBits());
} else {
this->Info = Kind::INVALID;
this->RawData = 0;
>From f8cf186806507a734f7c170818f5c45172842453 Mon Sep 17 00:00:00 2001
From: Ryan Cowan <ryan.cowan at arm.com>
Date: Fri, 2 Jan 2026 11:19:31 +0000
Subject: [PATCH 27/40] Add wrapper around type constructors to fallback to
scalars when extended types aren't enabled
---
llvm/include/llvm/CodeGenTypes/LowLevelType.h | 21 +++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/llvm/include/llvm/CodeGenTypes/LowLevelType.h b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
index 86f091297bc4a..b909e7e63fc0b 100644
--- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h
+++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
@@ -98,6 +98,27 @@ class LLT {
APFloat::getSizeInBits(APFloatBase::EnumToSemantics(Sem)), Sem};
}
+ static LLT buildInteger(unsigned SizeInBits) {
+ if (!getUseExtended())
+ return LLT::scalar(SizeInBits);
+
+ return integer(SizeInBits);
+ }
+
+ static LLT buildFloatingPoint(const FpSemantics &Sem) {
+ if (!getUseExtended())
+ return LLT::scalar(APFloat::getSizeInBits(APFloatBase::EnumToSemantics(Sem)));
+
+ return floatingPoint(Sem);
+ }
+
+ static LLT buildFloatingIEEE(unsigned SizeInBits) {
+ if (!getUseExtended())
+ return LLT::scalar(SizeInBits);
+
+ return floatIEEE(SizeInBits);
+ }
+
/// Get a low-level token; just a scalar with zero bits (or no size).
static constexpr LLT token() {
return LLT{Kind::ANY_SCALAR, ElementCount::getFixed(0),
>From 12b9b094b8eb33b6bc0a3fd26a0068dcfcc6a82f Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Mon, 12 Jan 2026 15:48:12 +0300
Subject: [PATCH 28/40] Modify mutations to change the size of types, not the
type itself
---
.../llvm/CodeGen/GlobalISel/LegalizerInfo.h | 26 +++++++++++--------
llvm/include/llvm/CodeGenTypes/LowLevelType.h | 22 +++++++++-------
.../CodeGen/GlobalISel/LegalizeMutations.cpp | 12 +++++++--
3 files changed, 38 insertions(+), 22 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
index 9324bab3fe656..bb5145fcab963 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
@@ -402,6 +402,11 @@ LLVM_ABI LegalizeMutation changeElementCountTo(unsigned TypeIdx,
LLVM_ABI LegalizeMutation changeElementSizeTo(unsigned TypeIdx,
unsigned FromTypeIdx);
+/// Change the scalar size or element size to have the same scalar size as the
+/// type \p NewTy. Unlike changeElementTo, this discards pointer types and only
+/// changes the size.
+LLVM_ABI LegalizeMutation changeElementSizeTo(unsigned TypeIdx, LLT NewTy);
+
/// Widen the scalar type or vector element type for the given type index to the
/// next power of 2.
LLVM_ABI LegalizeMutation widenScalarOrEltToNextPow2(unsigned TypeIdx,
@@ -1032,7 +1037,7 @@ class LegalizeRuleSet {
using namespace LegalizeMutations;
return actionIf(LegalizeAction::WidenScalar,
scalarOrEltNarrowerThan(TypeIdx, Ty.getScalarSizeInBits()),
- changeElementTo(typeIdx(TypeIdx), Ty));
+ changeElementSizeTo(typeIdx(TypeIdx), Ty));
}
/// Ensure the scalar or element is at least as wide as Ty.
@@ -1043,7 +1048,7 @@ class LegalizeRuleSet {
return actionIf(LegalizeAction::WidenScalar,
all(Predicate, scalarOrEltNarrowerThan(
TypeIdx, Ty.getScalarSizeInBits())),
- changeElementTo(typeIdx(TypeIdx), Ty));
+ changeElementSizeTo(typeIdx(TypeIdx), Ty));
}
/// Ensure the vector size is at least as wide as VectorSize by promoting the
@@ -1062,7 +1067,7 @@ class LegalizeRuleSet {
const LLT VecTy = Query.Types[TypeIdx];
unsigned NumElts = VecTy.getNumElements();
unsigned MinSize = VectorSize / NumElts;
- LLT NewTy = LLT::fixed_vector(NumElts, LLT::scalar(MinSize));
+ LLT NewTy = LLT::fixed_vector(NumElts, VecTy.getElementType().changeElementSize(MinSize));
return std::make_pair(TypeIdx, NewTy);
});
}
@@ -1073,7 +1078,7 @@ class LegalizeRuleSet {
using namespace LegalizeMutations;
return actionIf(LegalizeAction::WidenScalar,
scalarNarrowerThan(TypeIdx, Ty.getSizeInBits()),
- changeTo(typeIdx(TypeIdx), Ty));
+ changeElementSizeTo(typeIdx(TypeIdx), Ty));
}
LegalizeRuleSet &minScalar(bool Pred, unsigned TypeIdx, const LLT Ty) {
if (!Pred)
@@ -1094,7 +1099,7 @@ class LegalizeRuleSet {
QueryTy.getSizeInBits() < Ty.getSizeInBits() &&
Predicate(Query);
},
- changeTo(typeIdx(TypeIdx), Ty));
+ changeElementSizeTo(typeIdx(TypeIdx), Ty));
}
/// Ensure the scalar is at most as wide as Ty.
@@ -1103,7 +1108,7 @@ class LegalizeRuleSet {
using namespace LegalizeMutations;
return actionIf(LegalizeAction::NarrowScalar,
scalarOrEltWiderThan(TypeIdx, Ty.getScalarSizeInBits()),
- changeElementTo(typeIdx(TypeIdx), Ty));
+ changeElementSizeTo(typeIdx(TypeIdx), Ty));
}
/// Ensure the scalar is at most as wide as Ty.
@@ -1112,7 +1117,7 @@ class LegalizeRuleSet {
using namespace LegalizeMutations;
return actionIf(LegalizeAction::NarrowScalar,
scalarWiderThan(TypeIdx, Ty.getSizeInBits()),
- changeTo(typeIdx(TypeIdx), Ty));
+ changeElementSizeTo(typeIdx(TypeIdx), Ty));
}
/// Conditionally limit the maximum size of the scalar.
@@ -1130,7 +1135,7 @@ class LegalizeRuleSet {
QueryTy.getSizeInBits() > Ty.getSizeInBits() &&
Predicate(Query);
},
- changeElementTo(typeIdx(TypeIdx), Ty));
+ changeElementSizeTo(typeIdx(TypeIdx), Ty));
}
/// Limit the range of scalar sizes to MinTy and MaxTy.
@@ -1195,9 +1200,8 @@ class LegalizeRuleSet {
Predicate(Query);
},
[=](const LegalityQuery &Query) {
- LLT T = Query.Types[LargeTypeIdx];
- if (T.isPointerVector())
- T = T.changeElementType(LLT::scalar(T.getScalarSizeInBits()));
+ LLT T = Query.Types[TypeIdx].changeElementSize(
+ Query.Types[LargeTypeIdx].getScalarSizeInBits());
return std::make_pair(TypeIdx, T);
});
}
diff --git a/llvm/include/llvm/CodeGenTypes/LowLevelType.h b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
index b909e7e63fc0b..4d8164b9bb358 100644
--- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h
+++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
@@ -402,16 +402,20 @@ class LLT {
/// If this type is a vector, return a vector with the same number of elements
/// but the new element size. Otherwise, return the new element type. Invalid
- /// for pointer and floating point types. For these, use changeElementType.
+ /// for pointer types. For these, use changeElementType.
constexpr LLT changeElementSize(unsigned NewEltSize) const {
- assert(!isPointerOrPointerVector() && !(isFloat() || isFloatVector()) &&
- "invalid to directly change element size for pointers and floats");
- return isVector()
- ? LLT::vector(getElementCount(), getElementType().isInteger()
- ? LLT::integer(NewEltSize)
- : LLT::scalar(NewEltSize))
- : isInteger() ? LLT::integer(NewEltSize)
- : LLT::scalar(NewEltSize);
+ assert(!isPointerOrPointerVector() &&
+ "invalid to directly change element size for pointers");
+ if (isVector())
+ return LLT::vector(getElementCount(), getElementType().changeElementSize(NewEltSize));
+
+ if (isInteger())
+ return LLT::integer(NewEltSize);
+
+ if (isFloatIEEE())
+ return LLT::floatIEEE(NewEltSize);
+
+ return LLT::scalar(NewEltSize);
}
/// Return a vector with the same element type and the new element count. Must
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizeMutations.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizeMutations.cpp
index ded4df4edc14c..92a94401403f5 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizeMutations.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizeMutations.cpp
@@ -67,8 +67,16 @@ LegalizeMutation LegalizeMutations::changeElementSizeTo(unsigned TypeIdx,
return [=](const LegalityQuery &Query) {
const LLT OldTy = Query.Types[TypeIdx];
const LLT NewTy = Query.Types[FromTypeIdx];
- const LLT NewEltTy = LLT::scalar(NewTy.getScalarSizeInBits());
- return std::make_pair(TypeIdx, OldTy.changeElementType(NewEltTy));
+ return std::make_pair(TypeIdx, OldTy.changeElementSize(NewTy.getScalarSizeInBits()));
+ };
+}
+
+LegalizeMutation LegalizeMutations::changeElementSizeTo(unsigned TypeIdx,
+ LLT NewTy) {
+ return [=](const LegalityQuery &Query) {
+ const LLT OldTy = Query.Types[TypeIdx];
+ return std::make_pair(TypeIdx,
+ OldTy.changeElementSize(NewTy.getScalarSizeInBits()));
};
}
>From cfed5d4f186eb57a1c3f5191172ecae9375737e5 Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Mon, 12 Jan 2026 16:11:34 +0300
Subject: [PATCH 29/40] format
---
llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h | 3 ++-
llvm/include/llvm/CodeGenTypes/LowLevelType.h | 6 ++++--
llvm/lib/CodeGen/GlobalISel/LegalizeMutations.cpp | 3 ++-
3 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
index bb5145fcab963..ad8ef30d8659c 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
@@ -1067,7 +1067,8 @@ class LegalizeRuleSet {
const LLT VecTy = Query.Types[TypeIdx];
unsigned NumElts = VecTy.getNumElements();
unsigned MinSize = VectorSize / NumElts;
- LLT NewTy = LLT::fixed_vector(NumElts, VecTy.getElementType().changeElementSize(MinSize));
+ LLT NewTy = LLT::fixed_vector(
+ NumElts, VecTy.getElementType().changeElementSize(MinSize));
return std::make_pair(TypeIdx, NewTy);
});
}
diff --git a/llvm/include/llvm/CodeGenTypes/LowLevelType.h b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
index 4d8164b9bb358..d79f3a4a8e246 100644
--- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h
+++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
@@ -107,7 +107,8 @@ class LLT {
static LLT buildFloatingPoint(const FpSemantics &Sem) {
if (!getUseExtended())
- return LLT::scalar(APFloat::getSizeInBits(APFloatBase::EnumToSemantics(Sem)));
+ return LLT::scalar(
+ APFloat::getSizeInBits(APFloatBase::EnumToSemantics(Sem)));
return floatingPoint(Sem);
}
@@ -407,7 +408,8 @@ class LLT {
assert(!isPointerOrPointerVector() &&
"invalid to directly change element size for pointers");
if (isVector())
- return LLT::vector(getElementCount(), getElementType().changeElementSize(NewEltSize));
+ return LLT::vector(getElementCount(),
+ getElementType().changeElementSize(NewEltSize));
if (isInteger())
return LLT::integer(NewEltSize);
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizeMutations.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizeMutations.cpp
index 92a94401403f5..f7ead3b41ea49 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizeMutations.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizeMutations.cpp
@@ -67,7 +67,8 @@ LegalizeMutation LegalizeMutations::changeElementSizeTo(unsigned TypeIdx,
return [=](const LegalityQuery &Query) {
const LLT OldTy = Query.Types[TypeIdx];
const LLT NewTy = Query.Types[FromTypeIdx];
- return std::make_pair(TypeIdx, OldTy.changeElementSize(NewTy.getScalarSizeInBits()));
+ return std::make_pair(TypeIdx,
+ OldTy.changeElementSize(NewTy.getScalarSizeInBits()));
};
}
>From 28ada8686983ef7d661b8165abb638b0fee6c3f4 Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Sat, 31 Jan 2026 13:16:33 +0300
Subject: [PATCH 30/40] fixed bf16 test
---
llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp b/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp
index 2f39416010235..6826f3e7e5c21 100644
--- a/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp
+++ b/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp
@@ -46,7 +46,7 @@ struct AArch64IRTranslatorTest : public ::testing::Test {
TargetOptions Options;
return std::unique_ptr<TargetMachine>(
T->createTargetMachine(TargetTriple, "", "", Options, std::nullopt,
- std::nullopt, CodeGenOptLevel::Aggressive));
+ std::nullopt, CodeGenOptLevel::None));
}
std::unique_ptr<Module> parseIR(const char *IR) {
>From bc21f31de4fe4352844763bf6cd1f6f9b786121d Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Sat, 31 Jan 2026 14:03:08 +0300
Subject: [PATCH 31/40] review fixes
---
llvm/lib/CodeGen/LowLevelTypeUtils.cpp | 36 ++++++++++++--------------
1 file changed, 16 insertions(+), 20 deletions(-)
diff --git a/llvm/lib/CodeGen/LowLevelTypeUtils.cpp b/llvm/lib/CodeGen/LowLevelTypeUtils.cpp
index 1ebf2e62f3242..659510a660c07 100644
--- a/llvm/lib/CodeGen/LowLevelTypeUtils.cpp
+++ b/llvm/lib/CodeGen/LowLevelTypeUtils.cpp
@@ -42,30 +42,25 @@ LLT llvm::getLLTForType(Type &Ty, const DataLayout &DL) {
return LLT::scalar(SizeInBits);
// Choose more precise LLT variant
- if (Ty.isFloatingPointTy()) {
- if (Ty.isHalfTy())
+ if (Ty.isFloatingPointTy())
+ switch (Ty.getTypeID()) {
+ default:
+ llvm_unreachable("Unhandled LLVM IR floating point type");
+ case Type::HalfTyID:
return LLT::float16();
-
- if (Ty.isBFloatTy())
+ case Type::BFloatTyID:
return LLT::bfloat16();
-
- if (Ty.isFloatTy())
+ case Type::FloatTyID:
return LLT::float32();
-
- if (Ty.isDoubleTy())
+ case Type::DoubleTyID:
return LLT::float64();
-
- if (Ty.isX86_FP80Ty())
+ case Type::X86_FP80TyID:
return LLT::x86fp80();
-
- if (Ty.isFP128Ty())
+ case Type::FP128TyID:
return LLT::float128();
-
- if (Ty.isPPC_FP128Ty())
+ case Type::PPC_FP128TyID:
return LLT::ppcf128();
-
- llvm_unreachable("Unhandled LLVM IR floating point type");
- }
+ }
if (Ty.isIntegerTy())
return LLT::integer(SizeInBits);
@@ -85,13 +80,13 @@ MVT llvm::getMVTForLLT(LLT Ty) {
Ty.getElementCount());
if (Ty.isFloat()) {
- if (Ty == LLT::bfloat16())
+ if (Ty.isBFloat16())
return MVT::bf16;
- if (Ty == LLT::x86fp80())
+ if (Ty.isX86FP80())
return MVT::f80;
- if (Ty == LLT::ppcf128())
+ if (Ty.isPPCF128())
return MVT::ppcf128;
return MVT::getFloatingPointVT(Ty.getSizeInBits());
@@ -115,6 +110,7 @@ const llvm::fltSemantics &llvm::getFltSemanticForLLT(LLT Ty) {
assert((Ty.isAnyScalar() || Ty.isFloat()) &&
"Expected a any scalar or float type.");
+ // Any scalar type always matches IEEE format
if (Ty.isAnyScalar()) {
switch (Ty.getSizeInBits()) {
default:
>From 96b1725f773c36bce53e43c5a01f0a4e96752b6d Mon Sep 17 00:00:00 2001
From: Ryan Cowan <ryan.cowan at arm.com>
Date: Mon, 29 Dec 2025 14:41:12 +0000
Subject: [PATCH 32/40] Try to match multiple types in the match table. Start
with the given type, then try integers and finally fall back to scalars.
---
.../GlobalISel/GIMatchTableExecutorImpl.h | 48 ++++++++++++++-----
1 file changed, 35 insertions(+), 13 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
index 78b189d44e285..9982502c0f9a2 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
@@ -285,24 +285,46 @@ bool GIMatchTableExecutor::executeMatchTable(
break;
}
const LLT Ty = MRI.getType(MO.getReg());
- const auto TyI = ExecInfo.TypeIDMap.find(Ty);
- if (TyI == ExecInfo.TypeIDMap.end()) {
- CurrentIdx = Default;
- break;
- }
- const int64_t TypeID = TyI->second;
- if (TypeID < LowerBound || UpperBound <= TypeID) {
- CurrentIdx = Default;
+
+ SmallVector<LLT> TypesToTry;
+ TypesToTry.push_back(Ty);
+
+ // Always try the integer patterns as we now consider that to be generic
+ // (to an extent)
+ if (LLT::getUseExtended() && !Ty.getScalarType().isInteger())
+ TypesToTry.push_back(
+ Ty.changeElementType(LLT::integer(Ty.getScalarSizeInBits())));
+
+ if (LLT::getUseExtended() && Ty.isAnyScalar() &&
+ Ty.getScalarSizeInBits() > 8)
+ TypesToTry.push_back(
+ Ty.changeElementType(LLT::floatIEEE(Ty.getScalarSizeInBits())));
+
+ const auto JumpTableBase = CurrentIdx;
+ bool Matched = false;
+ for (LLT Type : TypesToTry) {
+ const auto TyI = ExecInfo.TypeIDMap.find(Type);
+ if (TyI == ExecInfo.TypeIDMap.end())
+ continue;
+ const int64_t TypeID = TyI->second;
+ if (TypeID < LowerBound || UpperBound <= TypeID)
+ continue;
+ const auto NumEntry = (TypeID - LowerBound);
+ // Each entry is 4 bytes
+ CurrentIdx =
+ readBytesAs<uint32_t>(MatchTable + JumpTableBase + (NumEntry * 4));
+ if (!CurrentIdx) {
+ CurrentIdx = Default;
+ continue;
+ }
+ Matched = true;
break;
}
- const auto NumEntry = (TypeID - LowerBound);
- // Each entry is 4 bytes
- CurrentIdx =
- readBytesAs<uint32_t>(MatchTable + CurrentIdx + (NumEntry * 4));
- if (!CurrentIdx) {
+ if (!Matched) {
CurrentIdx = Default;
break;
}
+
OnFailResumeAt.push_back(Default);
break;
}
>From 53f8fa3fc4501aec102541c0b7e08130baa9b692 Mon Sep 17 00:00:00 2001
From: Ryan Cowan <ryan.cowan at arm.com>
Date: Mon, 2 Feb 2026 11:19:50 +0000
Subject: [PATCH 33/40] Modify construction of types to reduce the instances of
scalar types in shared infra.
---
llvm/include/llvm/CodeGen/TargetLowering.h | 2 +-
llvm/lib/CodeGen/GlobalISel/CallLowering.cpp | 2 +-
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 29 ++--
.../CodeGen/GlobalISel/LegalizerHelper.cpp | 144 +++++++++++-------
.../CodeGen/GlobalISel/MachineIRBuilder.cpp | 2 +-
5 files changed, 104 insertions(+), 75 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 442225bdec01f..d68e85493b1bf 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -442,7 +442,7 @@ class LLVM_ABI TargetLoweringBase {
/// G_INSERT_VECTOR_ELT, G_EXTRACT_VECTOR_ELT,
/// G_INSERT_SUBVECTOR, and G_EXTRACT_SUBVECTOR
LLT getVectorIdxLLT(const DataLayout &DL) const {
- return LLT::scalar(getVectorIdxWidth(DL));
+ return LLT::integer(getVectorIdxWidth(DL));
}
/// Returns the type to be used for the EVL/AVL operand of VP nodes:
diff --git a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
index 0aa2620e63257..de0557783fd14 100644
--- a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
@@ -1310,7 +1310,7 @@ void CallLowering::ValueHandler::copyArgumentMemory(
MemSize, DstAlign);
const LLT PtrTy = MRI.getType(DstPtr);
- const LLT SizeTy = LLT::scalar(PtrTy.getSizeInBits());
+ const LLT SizeTy = LLT::integer(PtrTy.getSizeInBits());
auto SizeConst = MIRBuilder.buildConstant(SizeTy, MemSize);
MIRBuilder.buildMemCpy(DstPtr, SrcPtr, SizeConst, *DstMMO, *SrcMMO);
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 4236600f53749..e14b13d5a2014 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -889,7 +889,7 @@ bool IRTranslator::emitJumpTableHeader(SwitchCG::JumpTable &JT,
auto Cst = getOrCreateVReg(
*ConstantInt::get(SValue.getType(), JTH.Last - JTH.First));
Cst = MIB.buildZExtOrTrunc(PtrScalarTy, Cst).getReg(0);
- auto Cmp = MIB.buildICmp(CmpInst::ICMP_UGT, LLT::scalar(1), Sub, Cst);
+ auto Cmp = MIB.buildICmp(CmpInst::ICMP_UGT, LLT::integer(1), Sub, Cst);
auto BrCond = MIB.buildBrCond(Cmp.getReg(0), *JT.Default);
@@ -920,7 +920,7 @@ void IRTranslator::emitSwitchCase(SwitchCG::CaseBlock &CB,
return;
}
- const LLT i1Ty = LLT::scalar(1);
+ const LLT i1Ty = LLT::integer(1);
// Build the compare.
if (!CB.CmpMHS) {
const auto *CI = dyn_cast<ConstantInt>(CB.CmpRHS);
@@ -1132,7 +1132,7 @@ void IRTranslator::emitBitTestHeader(SwitchCG::BitTestBlock &B,
if (!B.FallthroughUnreachable) {
// Conditional branch to the default block.
auto RangeCst = MIB.buildConstant(SwitchOpTy, B.Range);
- auto RangeCmp = MIB.buildICmp(CmpInst::Predicate::ICMP_UGT, LLT::scalar(1),
+ auto RangeCmp = MIB.buildICmp(CmpInst::Predicate::ICMP_UGT, LLT::integer(1),
RangeSub, RangeCst);
MIB.buildBrCond(RangeCmp, *B.Default);
}
@@ -1158,15 +1158,16 @@ void IRTranslator::emitBitTestCase(SwitchCG::BitTestBlock &BB,
// would need to be to shift a 1 bit in that position.
auto MaskTrailingZeros =
MIB.buildConstant(SwitchTy, llvm::countr_zero(B.Mask));
- Cmp =
- MIB.buildICmp(ICmpInst::ICMP_EQ, LLT::scalar(1), Reg, MaskTrailingZeros)
- .getReg(0);
+ Cmp = MIB.buildICmp(ICmpInst::ICMP_EQ, LLT::integer(1), Reg,
+ MaskTrailingZeros)
+ .getReg(0);
} else if (PopCount == BB.Range) {
// There is only one zero bit in the range, test for it directly.
auto MaskTrailingOnes =
MIB.buildConstant(SwitchTy, llvm::countr_one(B.Mask));
- Cmp = MIB.buildICmp(CmpInst::ICMP_NE, LLT::scalar(1), Reg, MaskTrailingOnes)
- .getReg(0);
+ Cmp =
+ MIB.buildICmp(CmpInst::ICMP_NE, LLT::integer(1), Reg, MaskTrailingOnes)
+ .getReg(0);
} else {
// Make desired shift.
auto CstOne = MIB.buildConstant(SwitchTy, 1);
@@ -1176,7 +1177,7 @@ void IRTranslator::emitBitTestCase(SwitchCG::BitTestBlock &BB,
auto CstMask = MIB.buildConstant(SwitchTy, B.Mask);
auto AndOp = MIB.buildAnd(SwitchTy, SwitchVal, CstMask);
auto CstZero = MIB.buildConstant(SwitchTy, 0);
- Cmp = MIB.buildICmp(CmpInst::ICMP_NE, LLT::scalar(1), AndOp, CstZero)
+ Cmp = MIB.buildICmp(CmpInst::ICMP_NE, LLT::integer(1), AndOp, CstZero)
.getReg(0);
}
@@ -1723,7 +1724,7 @@ bool IRTranslator::translateMemFunc(const CallInst &CI,
SrcRegs.push_back(SrcReg);
}
- LLT SizeTy = LLT::scalar(MinPtrSize);
+ LLT SizeTy = LLT::integer(MinPtrSize);
// The size operand should be the minimum of the pointer sizes.
Register &SizeOpReg = SrcRegs[SrcRegs.size() - 1];
@@ -3255,7 +3256,8 @@ bool IRTranslator::translateInsertElement(const User &U,
if (!Idx)
Idx = getOrCreateVReg(*U.getOperand(2));
if (MRI->getType(Idx).getSizeInBits() != PreferredVecIdxWidth) {
- const LLT VecIdxTy = LLT::scalar(PreferredVecIdxWidth);
+ const LLT VecIdxTy =
+ MRI->getType(Idx).changeElementSize(PreferredVecIdxWidth);
Idx = MIRBuilder.buildZExtOrTrunc(VecIdxTy, Idx).getReg(0);
}
MIRBuilder.buildInsertVectorElement(Res, Val, Elt, Idx);
@@ -3336,7 +3338,8 @@ bool IRTranslator::translateExtractElement(const User &U,
if (!Idx)
Idx = getOrCreateVReg(*U.getOperand(1));
if (MRI->getType(Idx).getSizeInBits() != PreferredVecIdxWidth) {
- const LLT VecIdxTy = LLT::scalar(PreferredVecIdxWidth);
+ const LLT VecIdxTy =
+ MRI->getType(Idx).changeElementSize(PreferredVecIdxWidth);
Idx = MIRBuilder.buildZExtOrTrunc(VecIdxTy, Idx).getReg(0);
}
MIRBuilder.buildExtractVectorElement(Res, Val, Idx);
@@ -4061,7 +4064,7 @@ bool IRTranslator::emitSPDescriptorParent(StackProtectorDescriptor &SPD,
// Perform the comparison.
auto Cmp =
- CurBuilder->buildICmp(CmpInst::ICMP_NE, LLT::scalar(1), Guard, GuardVal);
+ CurBuilder->buildICmp(CmpInst::ICMP_NE, LLT::integer(1), Guard, GuardVal);
// If the guard/stackslot do not equal, branch to failure MBB.
CurBuilder->buildBrCond(Cmp, *SPD.getFailureMBB());
// Otherwise branch to success MBB.
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index ace08c2f77df8..a6f8ba487abe1 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -1182,7 +1182,7 @@ LegalizerHelper::createFCMPLibcall(MachineInstr &MI,
const CmpInst::Predicate ICmpPred,
const DstOp &Res) -> Register {
// FCMP libcall always returns an i32, and needs an ICMP with #0.
- constexpr LLT TempLLT = LLT::scalar(32);
+ constexpr LLT TempLLT = LLT::integer(32);
Register Temp = MRI.createGenericVirtualRegister(TempLLT);
// Generate libcall, holding result in Temp
const auto Status = createLibcall(
@@ -3295,10 +3295,8 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
LLT VecTy = MRI.getType(VecReg);
Observer.changingInstr(MI);
- widenScalarSrc(
- MI,
- VecTy.changeVectorElementType(LLT::scalar(WideTy.getSizeInBits())), 1,
- TargetOpcode::G_ANYEXT);
+ widenScalarSrc(MI, LLT::vector(VecTy.getElementCount(), WideTy), 1,
+ TargetOpcode::G_ANYEXT);
widenScalarDst(MI, WideTy, 0);
Observer.changedInstr(MI);
@@ -3952,7 +3950,7 @@ LegalizerHelper::bitcastConcatVector(MachineInstr &MI, unsigned TypeIdx,
// Check if bitcast is Legal
auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
- LLT SrcScalTy = LLT::scalar(SrcTy.getSizeInBits());
+ LLT SrcScalTy = CastTy.getScalarType();
// Check if the build vector is Legal
if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
@@ -4150,6 +4148,8 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerLoad(GAnyLoad &LoadMI) {
LLT MemTy = MMO.getMemoryType();
MachineFunction &MF = MIRBuilder.getMF();
+ LLT EltTy = MemTy.getScalarType();
+
unsigned MemSizeInBits = MemTy.getSizeInBits();
unsigned MemStoreSizeInBits = 8 * MemTy.getSizeInBytes();
@@ -4159,7 +4159,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerLoad(GAnyLoad &LoadMI) {
// Promote to a byte-sized load if not loading an integral number of
// bytes. For example, promote EXTLOAD:i20 -> EXTLOAD:i24.
- LLT WideMemTy = LLT::scalar(MemStoreSizeInBits);
+ LLT WideMemTy = EltTy.changeElementSize(MemStoreSizeInBits);
MachineMemOperand *NewMMO =
MF.getMachineMemOperand(&MMO, MMO.getPointerInfo(), WideMemTy);
@@ -4261,12 +4261,22 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerLoad(GAnyLoad &LoadMI) {
LLT PtrTy = MRI.getType(PtrReg);
unsigned AnyExtSize = PowerOf2Ceil(DstTy.getSizeInBits());
- LLT AnyExtTy = LLT::scalar(AnyExtSize);
+
+ LLT AnyExtTy;
+ LLT OffsetCstRes;
+ if (EltTy.isPointer()) {
+ AnyExtTy = LLT::scalar(AnyExtSize);
+ OffsetCstRes = LLT::scalar(PtrTy.getSizeInBits());
+ } else {
+ AnyExtTy = EltTy.changeElementSize(AnyExtSize);
+ OffsetCstRes = EltTy.changeElementSize(PtrTy.getSizeInBits());
+ }
+
auto LargeLoad = MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
PtrReg, *LargeMMO);
- auto OffsetCst = MIRBuilder.buildConstant(LLT::scalar(PtrTy.getSizeInBits()),
- LargeSplitSize / 8);
+ auto OffsetCst = MIRBuilder.buildConstant(
+ OffsetCstRes, LargeSplitSize / 8);
Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
auto SmallPtr = MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
auto SmallLoad = MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), AnyExtTy,
@@ -4403,7 +4413,7 @@ LegalizerHelper::scalarizeVectorBooleanStore(GStore &StoreMI) {
// We need to build an integer scalar of the vector bit pattern.
// It's not legal for us to add padding when storing a vector.
unsigned NumBits = MemTy.getSizeInBits();
- LLT IntTy = LLT::scalar(NumBits);
+ LLT IntTy = LLT::integer(NumBits);
auto CurrVal = MIRBuilder.buildConstant(IntTy, 0);
LLT IdxTy = TLI.getVectorIdxLLT(MF.getDataLayout());
@@ -5460,7 +5470,7 @@ LegalizerHelper::reduceLoadStoreWidth(GLoadStore &LdStMI, unsigned TypeIdx,
return UnableToLegalize;
LLT PtrTy = MRI.getType(AddrReg);
- const LLT OffsetTy = LLT::scalar(PtrTy.getSizeInBits());
+ const LLT OffsetTy = LLT::integer(PtrTy.getSizeInBits());
unsigned TotalSize = ValTy.getSizeInBits();
@@ -6151,7 +6161,7 @@ LegalizerHelper::narrowScalarShift(MachineInstr &MI, unsigned TypeIdx,
// input. If that isn't small enough, the resulting pieces will be further
// legalized.
const unsigned NewBitSize = DstEltSize / 2;
- const LLT HalfTy = LLT::scalar(NewBitSize);
+ const LLT HalfTy = DstTy.getScalarType().changeElementSize(NewBitSize);
const LLT CondTy = LLT::scalar(1);
if (auto VRegAndVal = getIConstantVRegValWithLookThrough(Amt, MRI)) {
@@ -8291,11 +8301,13 @@ LegalizerHelper::lowerU64ToF64BitFloatOps(MachineInstr &MI) {
static LegalizerHelper::LegalizeResult
loweri64tof16ITOFP(MachineInstr &MI, Register Dst, LLT DstTy, Register Src,
LLT SrcTy, MachineIRBuilder &MIRBuilder) {
+ auto DstFpTy =
+ SrcTy.changeElementType(LLT::floatIEEE(SrcTy.getScalarSizeInBits()));
auto M1 = MI.getOpcode() == TargetOpcode::G_UITOFP
- ? MIRBuilder.buildUITOFP(SrcTy, Src)
- : MIRBuilder.buildSITOFP(SrcTy, Src);
- LLT S32Ty = SrcTy.changeElementSize(32);
- auto M2 = MIRBuilder.buildFPTrunc(S32Ty, M1);
+ ? MIRBuilder.buildUITOFP(DstFpTy, Src)
+ : MIRBuilder.buildSITOFP(DstFpTy, Src);
+ LLT F32Ty = DstFpTy.changeElementSize(32);
+ auto M2 = MIRBuilder.buildFPTrunc(F32Ty, M1);
MIRBuilder.buildFPTrunc(Dst, M2);
MI.eraseFromParent();
return LegalizerHelper::Legalized;
@@ -8334,11 +8346,11 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerUITOFP(MachineInstr &MI) {
LegalizerHelper::LegalizeResult LegalizerHelper::lowerSITOFP(MachineInstr &MI) {
auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();
- const LLT S64 = LLT::scalar(64);
- const LLT S32 = LLT::scalar(32);
- const LLT S1 = LLT::scalar(1);
+ const LLT I64 = LLT::integer(64);
+ const LLT I32 = LLT::integer(32);
+ const LLT I1 = LLT::integer(1);
- if (SrcTy == S1) {
+ if (SrcTy == I1) {
auto True = MIRBuilder.buildFConstant(DstTy, -1.0);
auto False = MIRBuilder.buildFConstant(DstTy, 0.0);
MIRBuilder.buildSelect(Dst, Src, True, False);
@@ -8349,26 +8361,26 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerSITOFP(MachineInstr &MI) {
if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
return loweri64tof16ITOFP(MI, Dst, DstTy, Src, SrcTy, MIRBuilder);
- if (SrcTy != S64)
+ if (SrcTy != I64)
return UnableToLegalize;
- if (DstTy == S32) {
+ if (DstTy.getScalarSizeInBits() == 32) {
// signed cl2f(long l) {
// long s = l >> 63;
// float r = cul2f((l + s) ^ s);
// return s ? -r : r;
// }
Register L = Src;
- auto SignBit = MIRBuilder.buildConstant(S64, 63);
- auto S = MIRBuilder.buildAShr(S64, L, SignBit);
+ auto SignBit = MIRBuilder.buildConstant(I64, 63);
+ auto S = MIRBuilder.buildAShr(I64, L, SignBit);
- auto LPlusS = MIRBuilder.buildAdd(S64, L, S);
- auto Xor = MIRBuilder.buildXor(S64, LPlusS, S);
- auto R = MIRBuilder.buildUITOFP(S32, Xor);
+ auto LPlusS = MIRBuilder.buildAdd(I64, L, S);
+ auto Xor = MIRBuilder.buildXor(I64, LPlusS, S);
+ auto R = MIRBuilder.buildUITOFP(I32, Xor);
- auto RNeg = MIRBuilder.buildFNeg(S32, R);
- auto SignNotZero = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1, S,
- MIRBuilder.buildConstant(S64, 0));
+ auto RNeg = MIRBuilder.buildFNeg(I32, R);
+ auto SignNotZero = MIRBuilder.buildICmp(CmpInst::ICMP_NE, I1, S,
+ MIRBuilder.buildConstant(I64, 0));
MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
MI.eraseFromParent();
return Legalized;
@@ -8516,14 +8528,13 @@ LegalizerHelper::lowerFPTOINT_SAT(MachineInstr &MI) {
if (AreExactFloatBounds) {
// Clamp Src by MinFloat from below. If Src is NaN the result is MinFloat.
auto MaxC = MIRBuilder.buildFConstant(SrcTy, MinFloat);
- auto MaxP = MIRBuilder.buildFCmp(CmpInst::FCMP_OGT,
- SrcTy.changeElementSize(1), Src, MaxC);
+ auto MaxP =
+ MIRBuilder.buildFCmp(CmpInst::FCMP_OGT, LLT::integer(1), Src, MaxC);
auto Max = MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
// Clamp by MaxFloat from above. NaN cannot occur.
auto MinC = MIRBuilder.buildFConstant(SrcTy, MaxFloat);
- auto MinP =
- MIRBuilder.buildFCmp(CmpInst::FCMP_OLT, SrcTy.changeElementSize(1), Max,
- MinC, MachineInstr::FmNoNans);
+ auto MinP = MIRBuilder.buildFCmp(CmpInst::FCMP_OLT, LLT::integer(1), Max,
+ MinC, MachineInstr::FmNoNans);
auto Min =
MIRBuilder.buildSelect(SrcTy, MinP, Max, MinC, MachineInstr::FmNoNans);
// Convert clamped value to integer. In the unsigned case we're done,
@@ -8536,8 +8547,8 @@ LegalizerHelper::lowerFPTOINT_SAT(MachineInstr &MI) {
// Otherwise, select 0 if Src is NaN.
auto FpToInt = MIRBuilder.buildFPTOSI(DstTy, Min);
- auto IsZero = MIRBuilder.buildFCmp(CmpInst::FCMP_UNO,
- DstTy.changeElementSize(1), Src, Src);
+ auto IsZero =
+ MIRBuilder.buildFCmp(CmpInst::FCMP_UNO, LLT::integer(1), Src, Src);
MIRBuilder.buildSelect(Dst, IsZero, MIRBuilder.buildConstant(DstTy, 0),
FpToInt);
MI.eraseFromParent();
@@ -8552,15 +8563,13 @@ LegalizerHelper::lowerFPTOINT_SAT(MachineInstr &MI) {
// If Src ULT MinFloat, select MinInt. In particular, this also selects
// MinInt if Src is NaN.
- auto ULT =
- MIRBuilder.buildFCmp(CmpInst::FCMP_ULT, SrcTy.changeElementSize(1), Src,
- MIRBuilder.buildFConstant(SrcTy, MinFloat));
+ auto ULT = MIRBuilder.buildFCmp(CmpInst::FCMP_ULT, LLT::integer(1), Src,
+ MIRBuilder.buildFConstant(SrcTy, MinFloat));
auto Max = MIRBuilder.buildSelect(
DstTy, ULT, MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
// If Src OGT MaxFloat, select MaxInt.
- auto OGT =
- MIRBuilder.buildFCmp(CmpInst::FCMP_OGT, SrcTy.changeElementSize(1), Src,
- MIRBuilder.buildFConstant(SrcTy, MaxFloat));
+ auto OGT = MIRBuilder.buildFCmp(CmpInst::FCMP_OGT, LLT::integer(1), Src,
+ MIRBuilder.buildFConstant(SrcTy, MaxFloat));
// In the unsigned case we are done, because we mapped NaN to MinInt, which
// is already zero.
@@ -8574,8 +8583,8 @@ LegalizerHelper::lowerFPTOINT_SAT(MachineInstr &MI) {
// Otherwise, select 0 if Src is NaN.
auto Min = MIRBuilder.buildSelect(
DstTy, OGT, MIRBuilder.buildConstant(DstTy, MaxInt), Max);
- auto IsZero = MIRBuilder.buildFCmp(CmpInst::FCMP_UNO,
- DstTy.changeElementSize(1), Src, Src);
+ auto IsZero =
+ MIRBuilder.buildFCmp(CmpInst::FCMP_UNO, LLT::integer(1), Src, Src);
MIRBuilder.buildSelect(Dst, IsZero, MIRBuilder.buildConstant(DstTy, 0), Min);
MI.eraseFromParent();
return Legalized;
@@ -8738,7 +8747,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerMinMax(MachineInstr &MI) {
auto [Dst, Src0, Src1] = MI.getFirst3Regs();
const CmpInst::Predicate Pred = minMaxToCompare(MI.getOpcode());
- LLT CmpType = MRI.getType(Dst).changeElementType(LLT::scalar(1));
+ LLT CmpType = MRI.getType(Dst).changeElementType(LLT::integer(1));
auto Cmp = MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
@@ -8801,26 +8810,43 @@ LegalizerHelper::lowerFCopySign(MachineInstr &MI) {
const int Src0Size = Src0Ty.getScalarSizeInBits();
const int Src1Size = Src1Ty.getScalarSizeInBits();
- auto SignBitMask = MIRBuilder.buildConstant(
- Src0Ty, APInt::getSignMask(Src0Size));
+ LLT DstIntTy =
+ DstTy.changeElementType(LLT::integer(DstTy.getScalarSizeInBits()));
+ LLT Src0IntTy = Src0Ty.changeElementType(LLT::integer(Src0Size));
+ LLT Src1IntTy = Src1Ty.changeElementType(LLT::integer(Src1Size));
+
+ Register Src0Int = Src0;
+ Register Src1Int = Src1;
+
+ if (!(Src0Ty.getScalarType().isAnyScalar() ||
+ Src0Ty.getScalarType().isInteger()))
+ Src0Int = MIRBuilder.buildBitcast(Src0IntTy, Src0).getReg(0);
+
+ if (!(Src1Ty.getScalarType().isAnyScalar() ||
+ Src1Ty.getScalarType().isInteger()))
+ Src1Int = MIRBuilder.buildBitcast(Src1IntTy, Src1).getReg(0);
+
+ auto SignBitMask =
+ MIRBuilder.buildConstant(Src0IntTy, APInt::getSignMask(Src0Size));
auto NotSignBitMask = MIRBuilder.buildConstant(
- Src0Ty, APInt::getLowBitsSet(Src0Size, Src0Size - 1));
+ Src0IntTy, APInt::getLowBitsSet(Src0Size, Src0Size - 1));
- Register And0 = MIRBuilder.buildAnd(Src0Ty, Src0, NotSignBitMask).getReg(0);
+ Register And0 =
+ MIRBuilder.buildAnd(Src0IntTy, Src0Int, NotSignBitMask).getReg(0);
Register And1;
if (Src0Ty == Src1Ty) {
- And1 = MIRBuilder.buildAnd(Src1Ty, Src1, SignBitMask).getReg(0);
+ And1 = MIRBuilder.buildAnd(Src1IntTy, Src1Int, SignBitMask).getReg(0);
} else if (Src0Size > Src1Size) {
- auto ShiftAmt = MIRBuilder.buildConstant(Src0Ty, Src0Size - Src1Size);
- auto Zext = MIRBuilder.buildZExt(Src0Ty, Src1);
- auto Shift = MIRBuilder.buildShl(Src0Ty, Zext, ShiftAmt);
+ auto ShiftAmt = MIRBuilder.buildConstant(Src0IntTy, Src0Size - Src1Size);
+ auto Zext = MIRBuilder.buildZExt(Src0IntTy, Src1Int);
+ auto Shift = MIRBuilder.buildShl(Src0IntTy, Zext, ShiftAmt);
And1 = MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask).getReg(0);
} else {
- auto ShiftAmt = MIRBuilder.buildConstant(Src1Ty, Src1Size - Src0Size);
- auto Shift = MIRBuilder.buildLShr(Src1Ty, Src1, ShiftAmt);
- auto Trunc = MIRBuilder.buildTrunc(Src0Ty, Shift);
- And1 = MIRBuilder.buildAnd(Src0Ty, Trunc, SignBitMask).getReg(0);
+ auto ShiftAmt = MIRBuilder.buildConstant(Src1IntTy, Src1Size - Src0Size);
+ auto Shift = MIRBuilder.buildLShr(Src1IntTy, Src1Int, ShiftAmt);
+ auto Trunc = MIRBuilder.buildTrunc(Src0IntTy, Shift);
+ And1 = MIRBuilder.buildAnd(Src0IntTy, Trunc, SignBitMask).getReg(0);
}
// Be careful about setting nsz/nnan/ninf on every instruction, since the
diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index 0468c214e4bae..63c9ada9b059d 100644
--- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -787,7 +787,7 @@ MachineInstrBuilder MachineIRBuilder::buildShuffleSplat(const DstOp &Res,
assert(Src.getLLTTy(*getMRI()) == DstTy.getElementType() &&
"Expected Src to match Dst elt ty");
auto UndefVec = buildUndef(DstTy);
- auto Zero = buildConstant(LLT::scalar(64), 0);
+ auto Zero = buildConstant(LLT::integer(64), 0);
auto InsElt = buildInsertVectorElement(DstTy, UndefVec, Src, Zero);
SmallVector<int, 16> ZeroMask(DstTy.getNumElements());
return buildShuffleVector(DstTy, InsElt, UndefVec, ZeroMask);
>From 555f66b18e0c0919a8909acc8f74dee975c12fe8 Mon Sep 17 00:00:00 2001
From: Ryan Cowan <ryan.cowan at arm.com>
Date: Mon, 2 Feb 2026 13:23:54 +0000
Subject: [PATCH 34/40] Add bitcasts & copies to coerce types when necessary.
Allow select functions to 'see through' bitcasts to allow existing
optimisations to work.
---
llvm/lib/CodeGen/GlobalISel/CallLowering.cpp | 23 ++++-
.../lib/CodeGen/GlobalISel/CombinerHelper.cpp | 19 +++-
.../CodeGen/GlobalISel/LegalizerHelper.cpp | 94 ++++++++++++++++---
llvm/lib/CodeGen/GlobalISel/Utils.cpp | 24 ++++-
llvm/lib/CodeGen/MachineVerifier.cpp | 11 ++-
5 files changed, 147 insertions(+), 24 deletions(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
index de0557783fd14..bb6ff5f2e2485 100644
--- a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
@@ -340,13 +340,25 @@ mergeVectorRegsToResultRegs(MachineIRBuilder &B, ArrayRef<Register> DstRegs,
if (LCMTy == LLTy) {
// Common case where no padding is needed.
assert(DstRegs.size() == 1);
- return B.buildConcatVectors(DstRegs[0], SrcRegs);
+
+ SmallVector<Register, 8> ConcatRegs(SrcRegs.size());
+ llvm::copy(SrcRegs, ConcatRegs.begin());
+
+ if (LLTy.getScalarType() != PartLLT.getScalarType())
+ for (int I = 0; I != SrcRegs.size(); ++I)
+ ConcatRegs[I] =
+ B.buildBitcast(MRI.getType(SrcRegs[I])
+ .changeElementType(LLTy.getScalarType()),
+ SrcRegs[I])
+ .getReg(0);
+
+ return B.buildConcatVectors(DstRegs[0], ConcatRegs);
}
// We need to create an unmerge to the result registers, which may require
// widening the original value.
Register UnmergeSrcReg;
- if (LCMTy != PartLLT) {
+ if (LCMTy.getSizeInBits() != PartLLT.getSizeInBits()) {
assert(DstRegs.size() == 1);
return B.buildDeleteTrailingVectorElements(
DstRegs[0], B.buildMergeLikeInstr(LCMTy, SrcRegs));
@@ -366,6 +378,9 @@ mergeVectorRegsToResultRegs(MachineIRBuilder &B, ArrayRef<Register> DstRegs,
for (int I = DstRegs.size(); I != NumDst; ++I)
PadDstRegs[I] = MRI.createGenericVirtualRegister(LLTy);
+ if (PartLLT != LCMTy)
+ UnmergeSrcReg = B.buildBitcast(LCMTy, UnmergeSrcReg).getReg(0);
+
if (PadDstRegs.size() == 1)
return B.buildDeleteTrailingVectorElements(DstRegs[0], UnmergeSrcReg);
return B.buildUnmerge(PadDstRegs, UnmergeSrcReg);
@@ -456,7 +471,7 @@ static void buildCopyFromRegs(MachineIRBuilder &B, ArrayRef<Register> OrigRegs,
PartLLT = NewTy;
}
- if (LLTy.getScalarType() == PartLLT.getElementType()) {
+ if (LLTy.getScalarSizeInBits() == PartLLT.getScalarSizeInBits()) {
mergeVectorRegsToResultRegs(B, OrigRegs, CastRegs);
} else {
unsigned I = 0;
@@ -1411,7 +1426,7 @@ static bool isCopyCompatibleType(LLT SrcTy, LLT DstTy) {
void CallLowering::IncomingValueHandler::assignValueToReg(
Register ValVReg, Register PhysReg, const CCValAssign &VA) {
const MVT LocVT = VA.getLocVT();
- const LLT LocTy(LocVT);
+ const LLT LocTy = getLLTForMVT(LocVT);
const LLT RegTy = MRI.getType(ValVReg);
if (isCopyCompatibleType(RegTy, LocTy)) {
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index b9273d388ea70..13f16fa46dfe9 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -2351,9 +2351,22 @@ void CombinerHelper::applyCombineUnmergeConstant(
assert((MI.getNumOperands() - 1 == Csts.size()) &&
"Not enough operands to replace all defs");
unsigned NumElems = MI.getNumOperands() - 1;
- for (unsigned Idx = 0; Idx < NumElems; ++Idx) {
- Register DstReg = MI.getOperand(Idx).getReg();
- Builder.buildConstant(DstReg, Csts[Idx]);
+
+ Register SrcReg = MI.getOperand(NumElems).getReg();
+
+ if (MRI.getType(SrcReg).isFloat()) {
+ APFloat Val(getFltSemanticForLLT(MRI.getType(MI.getOperand(0).getReg())));
+
+ for (unsigned Idx = 0; Idx < NumElems; ++Idx) {
+ Register DstReg = MI.getOperand(Idx).getReg();
+ Val.convertFromAPInt(Csts[Idx], false, detail::rmTowardZero);
+ Builder.buildFConstant(DstReg, Val);
+ }
+ } else {
+ for (unsigned Idx = 0; Idx < NumElems; ++Idx) {
+ Register DstReg = MI.getOperand(Idx).getReg();
+ Builder.buildConstant(DstReg, Csts[Idx]);
+ }
}
MI.eraseFromParent();
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index a6f8ba487abe1..19f551fb882bf 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -4597,12 +4597,30 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
return Legalized;
}
case TargetOpcode::G_FNEG: {
- auto [Res, SubByReg] = MI.getFirst2Regs();
- LLT Ty = MRI.getType(Res);
+ auto [Res, ResTy, SubByReg, SubByRegTy] = MI.getFirst2RegLLTs();
+ LLT TyInt =
+ ResTy.changeElementType(LLT::integer(ResTy.getScalarSizeInBits()));
+ Register castedSubByReg = SubByReg;
+
+ if (!(SubByRegTy.getScalarType().isAnyScalar() ||
+ SubByRegTy.getScalarType().isInteger()))
+ castedSubByReg =
+ MIRBuilder
+ .buildBitcast(SubByRegTy.changeElementType(
+ LLT::integer(SubByRegTy.getScalarSizeInBits())),
+ SubByReg)
+ .getReg(0);
auto SignMask = MIRBuilder.buildConstant(
- Ty, APInt::getSignMask(Ty.getScalarSizeInBits()));
- MIRBuilder.buildXor(Res, SubByReg, SignMask);
+ TyInt, APInt::getSignMask(TyInt.getScalarSizeInBits()));
+
+ if (ResTy != TyInt) {
+ Register NewDst =
+ MIRBuilder.buildXor(TyInt, castedSubByReg, SignMask).getReg(0);
+ MIRBuilder.buildBitcast(Res, NewDst);
+ } else
+ MIRBuilder.buildXor(Res, castedSubByReg, SignMask).getReg(0);
+
MI.eraseFromParent();
return Legalized;
}
@@ -8857,7 +8875,12 @@ LegalizerHelper::lowerFCopySign(MachineInstr &MI) {
// We masked the sign bit and the not-sign bit, so these are disjoint.
Flags |= MachineInstr::Disjoint;
- MIRBuilder.buildOr(Dst, And0, And1, Flags);
+ if (DstTy == DstIntTy)
+ MIRBuilder.buildOr(Dst, And0, And1, Flags).getReg(0);
+ else {
+ Register NewDst = MIRBuilder.buildOr(DstIntTy, And0, And1, Flags).getReg(0);
+ MIRBuilder.buildBitcast(Dst, NewDst);
+ }
MI.eraseFromParent();
return Legalized;
@@ -10147,12 +10170,17 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerSelect(MachineInstr &MI) {
auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
MI.getFirst4RegLLTs();
+ LLT Op1TyInt =
+ Op1Ty.changeElementType(LLT::integer(Op1Ty.getScalarSizeInBits()));
+
bool IsEltPtr = DstTy.isPointerOrPointerVector();
if (IsEltPtr) {
LLT ScalarPtrTy = LLT::scalar(DstTy.getScalarSizeInBits());
LLT NewTy = DstTy.changeElementType(ScalarPtrTy);
Op1Reg = MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
+ Op1Ty = MRI.getType(Op1Reg);
Op2Reg = MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
+ Op2Ty = MRI.getType(Op2Reg);
DstTy = NewTy;
}
@@ -10187,6 +10215,18 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerSelect(MachineInstr &MI) {
return UnableToLegalize;
}
+ if (!(Op1Ty.getScalarType().isAnyScalar() ||
+ Op1Ty.getScalarType().isInteger()))
+ Op1Reg = MIRBuilder.buildBitcast(Op1TyInt, Op1Reg).getReg(0);
+
+ if (!(Op2Ty.getScalarType().isAnyScalar() ||
+ Op2Ty.getScalarType().isInteger()))
+ Op2Reg = MIRBuilder
+ .buildBitcast(Op2Ty.changeElementType(
+ LLT::integer(Op2Ty.getScalarSizeInBits())),
+ Op2Reg)
+ .getReg(0);
+
auto NotMask = MIRBuilder.buildNot(MaskTy, MaskReg);
auto NewOp1 = MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
auto NewOp2 = MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
@@ -10194,7 +10234,12 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerSelect(MachineInstr &MI) {
auto Or = MIRBuilder.buildOr(DstTy, NewOp1, NewOp2);
MIRBuilder.buildIntToPtr(DstReg, Or);
} else {
- MIRBuilder.buildOr(DstReg, NewOp1, NewOp2);
+ if (DstTy == Op1TyInt)
+ MIRBuilder.buildOr(DstReg, NewOp1, NewOp2);
+ else {
+ auto Or = MIRBuilder.buildOr(Op1TyInt, NewOp1, NewOp2);
+ MIRBuilder.buildBitcast(DstReg, Or.getReg(0));
+ }
}
MI.eraseFromParent();
return Legalized;
@@ -10310,16 +10355,37 @@ LegalizerHelper::lowerAbsDiffToMinMax(MachineInstr &MI) {
}
LegalizerHelper::LegalizeResult LegalizerHelper::lowerFAbs(MachineInstr &MI) {
- Register SrcReg = MI.getOperand(1).getReg();
- Register DstReg = MI.getOperand(0).getReg();
+ auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
+ LLT TyInt =
+ DstTy.changeElementType(LLT::integer(DstTy.getScalarSizeInBits()));
+ Register castedSrc = SrcReg;
+
+ if (!(SrcTy.getScalarType().isAnyScalar() ||
+ SrcTy.getScalarType().isInteger()))
+ castedSrc = MIRBuilder
+ .buildBitcast(SrcTy.changeElementType(LLT::integer(
+ SrcTy.getScalarSizeInBits())),
+ SrcReg)
+ .getReg(0);
- LLT Ty = MRI.getType(DstReg);
+ if (MRI.getType(DstReg) != TyInt) {
+ // Reset sign bit
+ Register NewDst =
+ MIRBuilder
+ .buildAnd(
+ TyInt, castedSrc,
+ MIRBuilder.buildConstant(
+ TyInt, APInt::getSignedMaxValue(DstTy.getScalarSizeInBits())))
+ .getReg(0);
- // Reset sign bit
- MIRBuilder.buildAnd(
- DstReg, SrcReg,
- MIRBuilder.buildConstant(
- Ty, APInt::getSignedMaxValue(Ty.getScalarSizeInBits())));
+ MIRBuilder.buildBitcast(DstReg, NewDst);
+ } else
+ MIRBuilder
+ .buildAnd(
+ DstReg, castedSrc,
+ MIRBuilder.buildConstant(
+ TyInt, APInt::getSignedMaxValue(DstTy.getScalarSizeInBits())))
+ .getReg(0);
MI.eraseFromParent();
return Legalized;
diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
index 658774ec3fcb9..b29a55f960232 100644
--- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
@@ -796,15 +796,35 @@ llvm::ConstantFoldFPBinOp(unsigned Opcode, const Register Op1,
return std::nullopt;
}
+static GBuildVector *getBuildVectorLikeDef(Register Reg,
+ const MachineRegisterInfo &MRI) {
+ if (auto *BV = getOpcodeDef<GBuildVector>(Reg, MRI))
+ return BV;
+
+ auto *Bitcast = getOpcodeDef(TargetOpcode::G_BITCAST, Reg, MRI);
+ if (!Bitcast)
+ return nullptr;
+
+ auto [Dst, DstTy, Src, SrcTy] = Bitcast->getFirst2RegLLTs();
+ if (!SrcTy.isVector() || !DstTy.isVector())
+ return nullptr;
+ if (SrcTy.getElementCount() != DstTy.getElementCount())
+ return nullptr;
+ if (SrcTy.getScalarSizeInBits() != DstTy.getScalarSizeInBits())
+ return nullptr;
+
+ return getOpcodeDef<GBuildVector>(Src, MRI);
+}
+
SmallVector<APInt>
llvm::ConstantFoldVectorBinop(unsigned Opcode, const Register Op1,
const Register Op2,
const MachineRegisterInfo &MRI) {
- auto *SrcVec2 = getOpcodeDef<GBuildVector>(Op2, MRI);
+ auto *SrcVec2 = getBuildVectorLikeDef(Op2, MRI);
if (!SrcVec2)
return SmallVector<APInt>();
- auto *SrcVec1 = getOpcodeDef<GBuildVector>(Op1, MRI);
+ auto *SrcVec1 = getBuildVectorLikeDef(Op1, MRI);
if (!SrcVec1)
return SmallVector<APInt>();
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index 919d451e25e54..c51cd9d48dee1 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -1336,7 +1336,16 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
if (SrcTy.getSizeInBits() != DstTy.getSizeInBits())
report("bitcast sizes must match", MI);
- if (SrcTy == DstTy)
+ bool SameType = SrcTy.getKind() == DstTy.getKind();
+ if (SameType && SrcTy.isPointerOrPointerVector())
+ SameType &= SrcTy.getAddressSpace() == DstTy.getAddressSpace();
+
+ SameType &= SrcTy.getScalarSizeInBits() == DstTy.getScalarSizeInBits();
+
+ if (SameType && SrcTy.isVector())
+ SameType &= SrcTy.getElementCount() == DstTy.getElementCount();
+
+ if (SameType)
report("bitcast must change the type", MI);
break;
>From 776b2793f9e3897469d44618b6842eedf0fc31ad Mon Sep 17 00:00:00 2001
From: Ryan Cowan <ryan.cowan at arm.com>
Date: Mon, 2 Feb 2026 11:24:07 +0000
Subject: [PATCH 35/40] Modify type constructors to use wrapper constructor to
allow scalar fallback in shared infra
---
llvm/include/llvm/CodeGen/TargetLowering.h | 2 +-
llvm/lib/CodeGen/GlobalISel/CallLowering.cpp | 2 +-
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 24 +++---
.../CodeGen/GlobalISel/LegalizerHelper.cpp | 79 +++++++++----------
.../CodeGen/GlobalISel/MachineIRBuilder.cpp | 2 +-
5 files changed, 54 insertions(+), 55 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index d68e85493b1bf..741e0769a94ac 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -442,7 +442,7 @@ class LLVM_ABI TargetLoweringBase {
/// G_INSERT_VECTOR_ELT, G_EXTRACT_VECTOR_ELT,
/// G_INSERT_SUBVECTOR, and G_EXTRACT_SUBVECTOR
LLT getVectorIdxLLT(const DataLayout &DL) const {
- return LLT::integer(getVectorIdxWidth(DL));
+ return LLT::buildInteger(getVectorIdxWidth(DL));
}
/// Returns the type to be used for the EVL/AVL operand of VP nodes:
diff --git a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
index bb6ff5f2e2485..2c903c49a0117 100644
--- a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
@@ -1325,7 +1325,7 @@ void CallLowering::ValueHandler::copyArgumentMemory(
MemSize, DstAlign);
const LLT PtrTy = MRI.getType(DstPtr);
- const LLT SizeTy = LLT::integer(PtrTy.getSizeInBits());
+ const LLT SizeTy = LLT::buildInteger(PtrTy.getSizeInBits());
auto SizeConst = MIRBuilder.buildConstant(SizeTy, MemSize);
MIRBuilder.buildMemCpy(DstPtr, SrcPtr, SizeConst, *DstMMO, *SrcMMO);
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index e14b13d5a2014..6d26e2f8c8fda 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -889,7 +889,7 @@ bool IRTranslator::emitJumpTableHeader(SwitchCG::JumpTable &JT,
auto Cst = getOrCreateVReg(
*ConstantInt::get(SValue.getType(), JTH.Last - JTH.First));
Cst = MIB.buildZExtOrTrunc(PtrScalarTy, Cst).getReg(0);
- auto Cmp = MIB.buildICmp(CmpInst::ICMP_UGT, LLT::integer(1), Sub, Cst);
+ auto Cmp = MIB.buildICmp(CmpInst::ICMP_UGT, LLT::buildInteger(1), Sub, Cst);
auto BrCond = MIB.buildBrCond(Cmp.getReg(0), *JT.Default);
@@ -920,7 +920,7 @@ void IRTranslator::emitSwitchCase(SwitchCG::CaseBlock &CB,
return;
}
- const LLT i1Ty = LLT::integer(1);
+ const LLT i1Ty = LLT::buildInteger(1);
// Build the compare.
if (!CB.CmpMHS) {
const auto *CI = dyn_cast<ConstantInt>(CB.CmpRHS);
@@ -1132,8 +1132,8 @@ void IRTranslator::emitBitTestHeader(SwitchCG::BitTestBlock &B,
if (!B.FallthroughUnreachable) {
// Conditional branch to the default block.
auto RangeCst = MIB.buildConstant(SwitchOpTy, B.Range);
- auto RangeCmp = MIB.buildICmp(CmpInst::Predicate::ICMP_UGT, LLT::integer(1),
- RangeSub, RangeCst);
+ auto RangeCmp = MIB.buildICmp(CmpInst::Predicate::ICMP_UGT,
+ LLT::buildInteger(1), RangeSub, RangeCst);
MIB.buildBrCond(RangeCmp, *B.Default);
}
@@ -1158,16 +1158,16 @@ void IRTranslator::emitBitTestCase(SwitchCG::BitTestBlock &BB,
// would need to be to shift a 1 bit in that position.
auto MaskTrailingZeros =
MIB.buildConstant(SwitchTy, llvm::countr_zero(B.Mask));
- Cmp = MIB.buildICmp(ICmpInst::ICMP_EQ, LLT::integer(1), Reg,
+ Cmp = MIB.buildICmp(ICmpInst::ICMP_EQ, LLT::buildInteger(1), Reg,
MaskTrailingZeros)
.getReg(0);
} else if (PopCount == BB.Range) {
// There is only one zero bit in the range, test for it directly.
auto MaskTrailingOnes =
MIB.buildConstant(SwitchTy, llvm::countr_one(B.Mask));
- Cmp =
- MIB.buildICmp(CmpInst::ICMP_NE, LLT::integer(1), Reg, MaskTrailingOnes)
- .getReg(0);
+ Cmp = MIB.buildICmp(CmpInst::ICMP_NE, LLT::buildInteger(1), Reg,
+ MaskTrailingOnes)
+ .getReg(0);
} else {
// Make desired shift.
auto CstOne = MIB.buildConstant(SwitchTy, 1);
@@ -1177,7 +1177,7 @@ void IRTranslator::emitBitTestCase(SwitchCG::BitTestBlock &BB,
auto CstMask = MIB.buildConstant(SwitchTy, B.Mask);
auto AndOp = MIB.buildAnd(SwitchTy, SwitchVal, CstMask);
auto CstZero = MIB.buildConstant(SwitchTy, 0);
- Cmp = MIB.buildICmp(CmpInst::ICMP_NE, LLT::integer(1), AndOp, CstZero)
+ Cmp = MIB.buildICmp(CmpInst::ICMP_NE, LLT::buildInteger(1), AndOp, CstZero)
.getReg(0);
}
@@ -1724,7 +1724,7 @@ bool IRTranslator::translateMemFunc(const CallInst &CI,
SrcRegs.push_back(SrcReg);
}
- LLT SizeTy = LLT::integer(MinPtrSize);
+ LLT SizeTy = LLT::buildInteger(MinPtrSize);
// The size operand should be the minimum of the pointer sizes.
Register &SizeOpReg = SrcRegs[SrcRegs.size() - 1];
@@ -4063,8 +4063,8 @@ bool IRTranslator::emitSPDescriptorParent(StackProtectorDescriptor &SPD,
}
// Perform the comparison.
- auto Cmp =
- CurBuilder->buildICmp(CmpInst::ICMP_NE, LLT::integer(1), Guard, GuardVal);
+ auto Cmp = CurBuilder->buildICmp(CmpInst::ICMP_NE, LLT::buildInteger(1),
+ Guard, GuardVal);
// If the guard/stackslot do not equal, branch to failure MBB.
CurBuilder->buildBrCond(Cmp, *SPD.getFailureMBB());
// Otherwise branch to success MBB.
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 19f551fb882bf..55944b008cb15 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -1182,7 +1182,7 @@ LegalizerHelper::createFCMPLibcall(MachineInstr &MI,
const CmpInst::Predicate ICmpPred,
const DstOp &Res) -> Register {
// FCMP libcall always returns an i32, and needs an ICMP with #0.
- constexpr LLT TempLLT = LLT::integer(32);
+ LLT TempLLT = LLT::buildInteger(32);
Register Temp = MRI.createGenericVirtualRegister(TempLLT);
// Generate libcall, holding result in Temp
const auto Status = createLibcall(
@@ -4275,8 +4275,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerLoad(GAnyLoad &LoadMI) {
auto LargeLoad = MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
PtrReg, *LargeMMO);
- auto OffsetCst = MIRBuilder.buildConstant(
- OffsetCstRes, LargeSplitSize / 8);
+ auto OffsetCst = MIRBuilder.buildConstant(OffsetCstRes, LargeSplitSize / 8);
Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
auto SmallPtr = MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
auto SmallLoad = MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), AnyExtTy,
@@ -4413,7 +4412,7 @@ LegalizerHelper::scalarizeVectorBooleanStore(GStore &StoreMI) {
// We need to build an integer scalar of the vector bit pattern.
// It's not legal for us to add padding when storing a vector.
unsigned NumBits = MemTy.getSizeInBits();
- LLT IntTy = LLT::integer(NumBits);
+ LLT IntTy = LLT::buildInteger(NumBits);
auto CurrVal = MIRBuilder.buildConstant(IntTy, 0);
LLT IdxTy = TLI.getVectorIdxLLT(MF.getDataLayout());
@@ -4599,15 +4598,15 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
case TargetOpcode::G_FNEG: {
auto [Res, ResTy, SubByReg, SubByRegTy] = MI.getFirst2RegLLTs();
LLT TyInt =
- ResTy.changeElementType(LLT::integer(ResTy.getScalarSizeInBits()));
+ ResTy.changeElementType(LLT::buildInteger(ResTy.getScalarSizeInBits()));
Register castedSubByReg = SubByReg;
if (!(SubByRegTy.getScalarType().isAnyScalar() ||
SubByRegTy.getScalarType().isInteger()))
castedSubByReg =
MIRBuilder
- .buildBitcast(SubByRegTy.changeElementType(
- LLT::integer(SubByRegTy.getScalarSizeInBits())),
+ .buildBitcast(SubByRegTy.changeElementType(LLT::buildInteger(
+ SubByRegTy.getScalarSizeInBits())),
SubByReg)
.getReg(0);
@@ -4616,7 +4615,7 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
if (ResTy != TyInt) {
Register NewDst =
- MIRBuilder.buildXor(TyInt, castedSubByReg, SignMask).getReg(0);
+ MIRBuilder.buildXor(TyInt, castedSubByReg, SignMask).getReg(0);
MIRBuilder.buildBitcast(Res, NewDst);
} else
MIRBuilder.buildXor(Res, castedSubByReg, SignMask).getReg(0);
@@ -5488,7 +5487,7 @@ LegalizerHelper::reduceLoadStoreWidth(GLoadStore &LdStMI, unsigned TypeIdx,
return UnableToLegalize;
LLT PtrTy = MRI.getType(AddrReg);
- const LLT OffsetTy = LLT::integer(PtrTy.getSizeInBits());
+ const LLT OffsetTy = LLT::buildInteger(PtrTy.getSizeInBits());
unsigned TotalSize = ValTy.getSizeInBits();
@@ -8319,8 +8318,8 @@ LegalizerHelper::lowerU64ToF64BitFloatOps(MachineInstr &MI) {
static LegalizerHelper::LegalizeResult
loweri64tof16ITOFP(MachineInstr &MI, Register Dst, LLT DstTy, Register Src,
LLT SrcTy, MachineIRBuilder &MIRBuilder) {
- auto DstFpTy =
- SrcTy.changeElementType(LLT::floatIEEE(SrcTy.getScalarSizeInBits()));
+ auto DstFpTy = SrcTy.changeElementType(
+ LLT::buildFloatingIEEE(SrcTy.getScalarSizeInBits()));
auto M1 = MI.getOpcode() == TargetOpcode::G_UITOFP
? MIRBuilder.buildUITOFP(DstFpTy, Src)
: MIRBuilder.buildSITOFP(DstFpTy, Src);
@@ -8364,9 +8363,9 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerUITOFP(MachineInstr &MI) {
LegalizerHelper::LegalizeResult LegalizerHelper::lowerSITOFP(MachineInstr &MI) {
auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();
- const LLT I64 = LLT::integer(64);
- const LLT I32 = LLT::integer(32);
- const LLT I1 = LLT::integer(1);
+ const LLT I64 = LLT::buildInteger(64);
+ const LLT I32 = LLT::buildInteger(32);
+ const LLT I1 = LLT::buildInteger(1);
if (SrcTy == I1) {
auto True = MIRBuilder.buildFConstant(DstTy, -1.0);
@@ -8546,13 +8545,13 @@ LegalizerHelper::lowerFPTOINT_SAT(MachineInstr &MI) {
if (AreExactFloatBounds) {
// Clamp Src by MinFloat from below. If Src is NaN the result is MinFloat.
auto MaxC = MIRBuilder.buildFConstant(SrcTy, MinFloat);
- auto MaxP =
- MIRBuilder.buildFCmp(CmpInst::FCMP_OGT, LLT::integer(1), Src, MaxC);
+ auto MaxP = MIRBuilder.buildFCmp(CmpInst::FCMP_OGT, LLT::buildInteger(1),
+ Src, MaxC);
auto Max = MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
// Clamp by MaxFloat from above. NaN cannot occur.
auto MinC = MIRBuilder.buildFConstant(SrcTy, MaxFloat);
- auto MinP = MIRBuilder.buildFCmp(CmpInst::FCMP_OLT, LLT::integer(1), Max,
- MinC, MachineInstr::FmNoNans);
+ auto MinP = MIRBuilder.buildFCmp(CmpInst::FCMP_OLT, LLT::buildInteger(1),
+ Max, MinC, MachineInstr::FmNoNans);
auto Min =
MIRBuilder.buildSelect(SrcTy, MinP, Max, MinC, MachineInstr::FmNoNans);
// Convert clamped value to integer. In the unsigned case we're done,
@@ -8566,7 +8565,7 @@ LegalizerHelper::lowerFPTOINT_SAT(MachineInstr &MI) {
// Otherwise, select 0 if Src is NaN.
auto FpToInt = MIRBuilder.buildFPTOSI(DstTy, Min);
auto IsZero =
- MIRBuilder.buildFCmp(CmpInst::FCMP_UNO, LLT::integer(1), Src, Src);
+ MIRBuilder.buildFCmp(CmpInst::FCMP_UNO, LLT::buildInteger(1), Src, Src);
MIRBuilder.buildSelect(Dst, IsZero, MIRBuilder.buildConstant(DstTy, 0),
FpToInt);
MI.eraseFromParent();
@@ -8581,12 +8580,12 @@ LegalizerHelper::lowerFPTOINT_SAT(MachineInstr &MI) {
// If Src ULT MinFloat, select MinInt. In particular, this also selects
// MinInt if Src is NaN.
- auto ULT = MIRBuilder.buildFCmp(CmpInst::FCMP_ULT, LLT::integer(1), Src,
+ auto ULT = MIRBuilder.buildFCmp(CmpInst::FCMP_ULT, LLT::buildInteger(1), Src,
MIRBuilder.buildFConstant(SrcTy, MinFloat));
auto Max = MIRBuilder.buildSelect(
DstTy, ULT, MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
// If Src OGT MaxFloat, select MaxInt.
- auto OGT = MIRBuilder.buildFCmp(CmpInst::FCMP_OGT, LLT::integer(1), Src,
+ auto OGT = MIRBuilder.buildFCmp(CmpInst::FCMP_OGT, LLT::buildInteger(1), Src,
MIRBuilder.buildFConstant(SrcTy, MaxFloat));
// In the unsigned case we are done, because we mapped NaN to MinInt, which
@@ -8602,7 +8601,7 @@ LegalizerHelper::lowerFPTOINT_SAT(MachineInstr &MI) {
auto Min = MIRBuilder.buildSelect(
DstTy, OGT, MIRBuilder.buildConstant(DstTy, MaxInt), Max);
auto IsZero =
- MIRBuilder.buildFCmp(CmpInst::FCMP_UNO, LLT::integer(1), Src, Src);
+ MIRBuilder.buildFCmp(CmpInst::FCMP_UNO, LLT::buildInteger(1), Src, Src);
MIRBuilder.buildSelect(Dst, IsZero, MIRBuilder.buildConstant(DstTy, 0), Min);
MI.eraseFromParent();
return Legalized;
@@ -8765,7 +8764,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerMinMax(MachineInstr &MI) {
auto [Dst, Src0, Src1] = MI.getFirst3Regs();
const CmpInst::Predicate Pred = minMaxToCompare(MI.getOpcode());
- LLT CmpType = MRI.getType(Dst).changeElementType(LLT::integer(1));
+ LLT CmpType = MRI.getType(Dst).changeElementType(LLT::buildInteger(1));
auto Cmp = MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
@@ -8829,9 +8828,9 @@ LegalizerHelper::lowerFCopySign(MachineInstr &MI) {
const int Src1Size = Src1Ty.getScalarSizeInBits();
LLT DstIntTy =
- DstTy.changeElementType(LLT::integer(DstTy.getScalarSizeInBits()));
- LLT Src0IntTy = Src0Ty.changeElementType(LLT::integer(Src0Size));
- LLT Src1IntTy = Src1Ty.changeElementType(LLT::integer(Src1Size));
+ DstTy.changeElementType(LLT::buildInteger(DstTy.getScalarSizeInBits()));
+ LLT Src0IntTy = Src0Ty.changeElementType(LLT::buildInteger(Src0Size));
+ LLT Src1IntTy = Src1Ty.changeElementType(LLT::buildInteger(Src1Size));
Register Src0Int = Src0;
Register Src1Int = Src1;
@@ -10171,7 +10170,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerSelect(MachineInstr &MI) {
MI.getFirst4RegLLTs();
LLT Op1TyInt =
- Op1Ty.changeElementType(LLT::integer(Op1Ty.getScalarSizeInBits()));
+ Op1Ty.changeElementType(LLT::buildInteger(Op1Ty.getScalarSizeInBits()));
bool IsEltPtr = DstTy.isPointerOrPointerVector();
if (IsEltPtr) {
@@ -10222,8 +10221,8 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerSelect(MachineInstr &MI) {
if (!(Op2Ty.getScalarType().isAnyScalar() ||
Op2Ty.getScalarType().isInteger()))
Op2Reg = MIRBuilder
- .buildBitcast(Op2Ty.changeElementType(
- LLT::integer(Op2Ty.getScalarSizeInBits())),
+ .buildBitcast(Op2Ty.changeElementType(LLT::buildInteger(
+ Op2Ty.getScalarSizeInBits())),
Op2Reg)
.getReg(0);
@@ -10357,13 +10356,13 @@ LegalizerHelper::lowerAbsDiffToMinMax(MachineInstr &MI) {
LegalizerHelper::LegalizeResult LegalizerHelper::lowerFAbs(MachineInstr &MI) {
auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
LLT TyInt =
- DstTy.changeElementType(LLT::integer(DstTy.getScalarSizeInBits()));
+ DstTy.changeElementType(LLT::buildInteger(DstTy.getScalarSizeInBits()));
Register castedSrc = SrcReg;
if (!(SrcTy.getScalarType().isAnyScalar() ||
SrcTy.getScalarType().isInteger()))
castedSrc = MIRBuilder
- .buildBitcast(SrcTy.changeElementType(LLT::integer(
+ .buildBitcast(SrcTy.changeElementType(LLT::buildInteger(
SrcTy.getScalarSizeInBits())),
SrcReg)
.getReg(0);
@@ -10372,20 +10371,20 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerFAbs(MachineInstr &MI) {
// Reset sign bit
Register NewDst =
MIRBuilder
- .buildAnd(
- TyInt, castedSrc,
- MIRBuilder.buildConstant(
- TyInt, APInt::getSignedMaxValue(DstTy.getScalarSizeInBits())))
+ .buildAnd(TyInt, castedSrc,
+ MIRBuilder.buildConstant(
+ TyInt, APInt::getSignedMaxValue(
+ DstTy.getScalarSizeInBits())))
.getReg(0);
MIRBuilder.buildBitcast(DstReg, NewDst);
} else
MIRBuilder
- .buildAnd(
- DstReg, castedSrc,
- MIRBuilder.buildConstant(
- TyInt, APInt::getSignedMaxValue(DstTy.getScalarSizeInBits())))
- .getReg(0);
+ .buildAnd(
+ DstReg, castedSrc,
+ MIRBuilder.buildConstant(
+ TyInt, APInt::getSignedMaxValue(DstTy.getScalarSizeInBits())))
+ .getReg(0);
MI.eraseFromParent();
return Legalized;
diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index 63c9ada9b059d..51f371d4a4108 100644
--- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -787,7 +787,7 @@ MachineInstrBuilder MachineIRBuilder::buildShuffleSplat(const DstOp &Res,
assert(Src.getLLTTy(*getMRI()) == DstTy.getElementType() &&
"Expected Src to match Dst elt ty");
auto UndefVec = buildUndef(DstTy);
- auto Zero = buildConstant(LLT::integer(64), 0);
+ auto Zero = buildConstant(LLT::buildInteger(64), 0);
auto InsElt = buildInsertVectorElement(DstTy, UndefVec, Src, Zero);
SmallVector<int, 16> ZeroMask(DstTy.getNumElements());
return buildShuffleVector(DstTy, InsElt, UndefVec, ZeroMask);
>From 0b51da8d3588f591001b32f55edd248ed2b8095b Mon Sep 17 00:00:00 2001
From: Ryan Cowan <ryan.cowan at arm.com>
Date: Mon, 2 Feb 2026 11:25:58 +0000
Subject: [PATCH 36/40] Improve formatting in places
---
llvm/lib/CodeGen/GlobalISel/CallLowering.cpp | 15 +++---
.../CodeGen/GlobalISel/LegalizerHelper.cpp | 46 +++++++++----------
2 files changed, 28 insertions(+), 33 deletions(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
index 2c903c49a0117..b88490c6901ed 100644
--- a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
@@ -345,12 +345,11 @@ mergeVectorRegsToResultRegs(MachineIRBuilder &B, ArrayRef<Register> DstRegs,
llvm::copy(SrcRegs, ConcatRegs.begin());
if (LLTy.getScalarType() != PartLLT.getScalarType())
- for (int I = 0; I != SrcRegs.size(); ++I)
- ConcatRegs[I] =
- B.buildBitcast(MRI.getType(SrcRegs[I])
- .changeElementType(LLTy.getScalarType()),
- SrcRegs[I])
- .getReg(0);
+ for (size_t I = 0, E = SrcRegs.size(); I != E; ++I) {
+ auto BitcastDst =
+ MRI.getType(SrcRegs[I]).changeElementType(LLTy.getScalarType());
+ ConcatRegs[I] = B.buildBitcast(BitcastDst, SrcRegs[I]).getReg(0);
+ }
return B.buildConcatVectors(DstRegs[0], ConcatRegs);
}
@@ -369,13 +368,13 @@ mergeVectorRegsToResultRegs(MachineIRBuilder &B, ArrayRef<Register> DstRegs,
UnmergeSrcReg = SrcRegs[0];
}
- int NumDst = LCMTy.getSizeInBits() / LLTy.getSizeInBits();
+ size_t NumDst = LCMTy.getSizeInBits() / LLTy.getSizeInBits();
SmallVector<Register, 8> PadDstRegs(NumDst);
llvm::copy(DstRegs, PadDstRegs.begin());
// Create the excess dead defs for the unmerge.
- for (int I = DstRegs.size(); I != NumDst; ++I)
+ for (size_t I = DstRegs.size(); I != NumDst; ++I)
PadDstRegs[I] = MRI.createGenericVirtualRegister(LLTy);
if (PartLLT != LCMTy)
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 55944b008cb15..5f44a5283384f 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -4599,26 +4599,24 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
auto [Res, ResTy, SubByReg, SubByRegTy] = MI.getFirst2RegLLTs();
LLT TyInt =
ResTy.changeElementType(LLT::buildInteger(ResTy.getScalarSizeInBits()));
- Register castedSubByReg = SubByReg;
+ Register CastedSubByReg = SubByReg;
if (!(SubByRegTy.getScalarType().isAnyScalar() ||
- SubByRegTy.getScalarType().isInteger()))
- castedSubByReg =
- MIRBuilder
- .buildBitcast(SubByRegTy.changeElementType(LLT::buildInteger(
- SubByRegTy.getScalarSizeInBits())),
- SubByReg)
- .getReg(0);
+ SubByRegTy.getScalarType().isInteger())) {
+ auto BitcastDst = SubByRegTy.changeElementType(
+ LLT::buildInteger(SubByRegTy.getScalarSizeInBits()));
+ CastedSubByReg = MIRBuilder.buildBitcast(BitcastDst, SubByReg).getReg(0);
+ }
auto SignMask = MIRBuilder.buildConstant(
TyInt, APInt::getSignMask(TyInt.getScalarSizeInBits()));
if (ResTy != TyInt) {
Register NewDst =
- MIRBuilder.buildXor(TyInt, castedSubByReg, SignMask).getReg(0);
+ MIRBuilder.buildXor(TyInt, CastedSubByReg, SignMask).getReg(0);
MIRBuilder.buildBitcast(Res, NewDst);
} else
- MIRBuilder.buildXor(Res, castedSubByReg, SignMask).getReg(0);
+ MIRBuilder.buildXor(Res, CastedSubByReg, SignMask).getReg(0);
MI.eraseFromParent();
return Legalized;
@@ -10219,12 +10217,11 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerSelect(MachineInstr &MI) {
Op1Reg = MIRBuilder.buildBitcast(Op1TyInt, Op1Reg).getReg(0);
if (!(Op2Ty.getScalarType().isAnyScalar() ||
- Op2Ty.getScalarType().isInteger()))
- Op2Reg = MIRBuilder
- .buildBitcast(Op2Ty.changeElementType(LLT::buildInteger(
- Op2Ty.getScalarSizeInBits())),
- Op2Reg)
- .getReg(0);
+ Op2Ty.getScalarType().isInteger())) {
+ auto Op2TyInt =
+ Op2Ty.changeElementType(LLT::buildInteger(Op2Ty.getScalarSizeInBits()));
+ Op2Reg = MIRBuilder.buildBitcast(Op2TyInt, Op2Reg).getReg(0);
+ }
auto NotMask = MIRBuilder.buildNot(MaskTy, MaskReg);
auto NewOp1 = MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
@@ -10357,21 +10354,20 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerFAbs(MachineInstr &MI) {
auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
LLT TyInt =
DstTy.changeElementType(LLT::buildInteger(DstTy.getScalarSizeInBits()));
- Register castedSrc = SrcReg;
+ Register CastedSrc = SrcReg;
if (!(SrcTy.getScalarType().isAnyScalar() ||
- SrcTy.getScalarType().isInteger()))
- castedSrc = MIRBuilder
- .buildBitcast(SrcTy.changeElementType(LLT::buildInteger(
- SrcTy.getScalarSizeInBits())),
- SrcReg)
- .getReg(0);
+ SrcTy.getScalarType().isInteger())) {
+ auto SrcTyInt =
+ SrcTy.changeElementType(LLT::buildInteger(SrcTy.getScalarSizeInBits()));
+ CastedSrc = MIRBuilder.buildBitcast(SrcTyInt, SrcReg).getReg(0);
+ }
if (MRI.getType(DstReg) != TyInt) {
// Reset sign bit
Register NewDst =
MIRBuilder
- .buildAnd(TyInt, castedSrc,
+ .buildAnd(TyInt, CastedSrc,
MIRBuilder.buildConstant(
TyInt, APInt::getSignedMaxValue(
DstTy.getScalarSizeInBits())))
@@ -10381,7 +10377,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerFAbs(MachineInstr &MI) {
} else
MIRBuilder
.buildAnd(
- DstReg, castedSrc,
+ DstReg, CastedSrc,
MIRBuilder.buildConstant(
TyInt, APInt::getSignedMaxValue(DstTy.getScalarSizeInBits())))
.getReg(0);
>From 555cc5733238a950f3a62f47479d3de551d8a2d5 Mon Sep 17 00:00:00 2001
From: Ryan Cowan <ryan.cowan at arm.com>
Date: Mon, 2 Feb 2026 13:48:49 +0000
Subject: [PATCH 37/40] Update tests
---
.../GlobalISel/irtranslator-subvector.ll | 8 +++-
.../CodeGen/AArch64/GlobalISel/pr168872.ll | 18 ++++----
.../AArch64/GlobalISel/translate-gep.ll | 4 +-
.../translate-sve-formal-argument-multiple.ll | 44 +++++++++++++++----
.../translate-sve-formal-argument.ll | 20 +++++++--
5 files changed, 70 insertions(+), 24 deletions(-)
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-subvector.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-subvector.ll
index 149bf72b053ef..862e0f6022395 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-subvector.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-subvector.ll
@@ -334,10 +334,14 @@ define i32 @extract_v4iptr_vector_insert_const_fixed_legal(<4 x ptr> %a, <4 x pt
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $q0
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $q1
- ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x p0>) = G_CONCAT_VECTORS [[COPY]](<2 x s64>), [[COPY1]](<2 x s64>)
+ ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY]](<2 x s64>)
+ ; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY1]](<2 x s64>)
+ ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x p0>) = G_CONCAT_VECTORS [[BITCAST]](<2 x p0>), [[BITCAST1]](<2 x p0>)
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(<2 x s64>) = COPY $q2
; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(<2 x s64>) = COPY $q3
- ; CHECK-NEXT: [[CONCAT_VECTORS1:%[0-9]+]]:_(<4 x p0>) = G_CONCAT_VECTORS [[COPY2]](<2 x s64>), [[COPY3]](<2 x s64>)
+ ; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY2]](<2 x s64>)
+ ; CHECK-NEXT: [[BITCAST3:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY3]](<2 x s64>)
+ ; CHECK-NEXT: [[CONCAT_VECTORS1:%[0-9]+]]:_(<4 x p0>) = G_CONCAT_VECTORS [[BITCAST2]](<2 x p0>), [[BITCAST3]](<2 x p0>)
; CHECK-NEXT: [[COPY4:%[0-9]+]]:_(p0) = COPY $x0
; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(p0) = COPY $x1
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/pr168872.ll b/llvm/test/CodeGen/AArch64/GlobalISel/pr168872.ll
index 4405c06ff0e23..c7ff34fd35935 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/pr168872.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/pr168872.ll
@@ -12,16 +12,14 @@ define <4 x ptr> @pr168872(<4 x ptr> %ptrs) {
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $q0
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $q1
- ; CHECK-NEXT: [[C:%[0-9]+]]:_(p0) = G_CONSTANT i64 0
- ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x p0>) = G_BUILD_VECTOR [[C]](p0), [[C]](p0)
; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY]](<2 x s64>)
; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY1]](<2 x s64>)
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(p0) = G_CONSTANT i64 0
+ ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x p0>) = G_BUILD_VECTOR [[C]](p0), [[C]](p0)
; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(<2 x s64>) = G_ICMP intpred(ugt), [[BITCAST]](<2 x p0>), [[BUILD_VECTOR]]
; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(<2 x s64>) = G_ICMP intpred(ugt), [[BITCAST1]](<2 x p0>), [[BUILD_VECTOR]]
- ; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY]](<2 x s64>)
- ; CHECK-NEXT: [[BITCAST3:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY1]](<2 x s64>)
- ; CHECK-NEXT: [[PTRTOINT:%[0-9]+]]:_(<2 x s64>) = G_PTRTOINT [[BITCAST2]](<2 x p0>)
- ; CHECK-NEXT: [[PTRTOINT1:%[0-9]+]]:_(<2 x s64>) = G_PTRTOINT [[BITCAST3]](<2 x p0>)
+ ; CHECK-NEXT: [[PTRTOINT:%[0-9]+]]:_(<2 x s64>) = G_PTRTOINT [[BITCAST]](<2 x p0>)
+ ; CHECK-NEXT: [[PTRTOINT1:%[0-9]+]]:_(<2 x s64>) = G_PTRTOINT [[BITCAST1]](<2 x p0>)
; CHECK-NEXT: [[PTRTOINT2:%[0-9]+]]:_(<2 x s64>) = G_PTRTOINT [[BUILD_VECTOR]](<2 x p0>)
; CHECK-NEXT: [[PTRTOINT3:%[0-9]+]]:_(<2 x s64>) = G_PTRTOINT [[BUILD_VECTOR]](<2 x p0>)
; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
@@ -36,10 +34,10 @@ define <4 x ptr> @pr168872(<4 x ptr> %ptrs) {
; CHECK-NEXT: [[OR1:%[0-9]+]]:_(<2 x s64>) = G_OR [[AND1]], [[AND3]]
; CHECK-NEXT: [[INTTOPTR:%[0-9]+]]:_(<2 x p0>) = G_INTTOPTR [[OR]](<2 x s64>)
; CHECK-NEXT: [[INTTOPTR1:%[0-9]+]]:_(<2 x p0>) = G_INTTOPTR [[OR1]](<2 x s64>)
- ; CHECK-NEXT: [[BITCAST4:%[0-9]+]]:_(<2 x s64>) = G_BITCAST [[INTTOPTR]](<2 x p0>)
- ; CHECK-NEXT: [[BITCAST5:%[0-9]+]]:_(<2 x s64>) = G_BITCAST [[INTTOPTR1]](<2 x p0>)
- ; CHECK-NEXT: $q0 = COPY [[BITCAST4]](<2 x s64>)
- ; CHECK-NEXT: $q1 = COPY [[BITCAST5]](<2 x s64>)
+ ; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<2 x s64>) = G_BITCAST [[INTTOPTR]](<2 x p0>)
+ ; CHECK-NEXT: [[BITCAST3:%[0-9]+]]:_(<2 x s64>) = G_BITCAST [[INTTOPTR1]](<2 x p0>)
+ ; CHECK-NEXT: $q0 = COPY [[BITCAST2]](<2 x s64>)
+ ; CHECK-NEXT: $q1 = COPY [[BITCAST3]](<2 x s64>)
; CHECK-NEXT: RET_ReallyLR implicit $q0, implicit $q1
entry:
%cmp = icmp ugt <4 x ptr> %ptrs, zeroinitializer
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/translate-gep.ll b/llvm/test/CodeGen/AArch64/GlobalISel/translate-gep.ll
index 5b2d6607f6297..dca947100b31e 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/translate-gep.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/translate-gep.ll
@@ -153,7 +153,9 @@ define <4 x ptr> @vector_gep_v4i32(<4 x ptr> %b, <4 x i32> %off) {
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $q0
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $q1
- ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x p0>) = G_CONCAT_VECTORS [[COPY]](<2 x s64>), [[COPY1]](<2 x s64>)
+ ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY]](<2 x s64>)
+ ; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[COPY1]](<2 x s64>)
+ ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x p0>) = G_CONCAT_VECTORS [[BITCAST]](<2 x p0>), [[BITCAST1]](<2 x p0>)
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(<4 x s32>) = COPY $q2
; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(<4 x s64>) = G_SEXT [[COPY2]](<4 x s32>)
; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(<4 x p0>) = G_PTR_ADD [[CONCAT_VECTORS]], [[SEXT]](<4 x s64>)
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/translate-sve-formal-argument-multiple.ll b/llvm/test/CodeGen/AArch64/GlobalISel/translate-sve-formal-argument-multiple.ll
index 28d53dab9d99f..06616510119e0 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/translate-sve-formal-argument-multiple.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/translate-sve-formal-argument-multiple.ll
@@ -20,7 +20,11 @@ define void @formal_argument_mix_sve(
; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z5
; CHECK-NEXT: [[COPY6:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z6
; CHECK-NEXT: [[COPY7:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z7
- ; CHECK-NEXT: [[CONCAT_VECTORS1:%[0-9]+]]:_(<vscale x 8 x p0>) = G_CONCAT_VECTORS [[COPY4]](<vscale x 2 x s64>), [[COPY5]](<vscale x 2 x s64>), [[COPY6]](<vscale x 2 x s64>), [[COPY7]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY4]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY5]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY6]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST3:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY7]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[CONCAT_VECTORS1:%[0-9]+]]:_(<vscale x 8 x p0>) = G_CONCAT_VECTORS [[BITCAST]](<vscale x 2 x p0>), [[BITCAST1]](<vscale x 2 x p0>), [[BITCAST2]](<vscale x 2 x p0>), [[BITCAST3]](<vscale x 2 x p0>)
; CHECK-NEXT: RET_ReallyLR
<vscale x 8 x i16> %0, <vscale x 8 x float> %1, <vscale x 16 x i8> %2, <vscale x 8 x ptr> %3
) {
@@ -190,16 +194,24 @@ define void @formal_argument_nxv4p0_4(<vscale x 4 x ptr> %0, <vscale x 4 x ptr>
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z0
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z1
- ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 4 x p0>) = G_CONCAT_VECTORS [[COPY]](<vscale x 2 x s64>), [[COPY1]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY1]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 4 x p0>) = G_CONCAT_VECTORS [[BITCAST]](<vscale x 2 x p0>), [[BITCAST1]](<vscale x 2 x p0>)
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z2
; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z3
- ; CHECK-NEXT: [[CONCAT_VECTORS1:%[0-9]+]]:_(<vscale x 4 x p0>) = G_CONCAT_VECTORS [[COPY2]](<vscale x 2 x s64>), [[COPY3]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY2]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST3:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY3]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[CONCAT_VECTORS1:%[0-9]+]]:_(<vscale x 4 x p0>) = G_CONCAT_VECTORS [[BITCAST2]](<vscale x 2 x p0>), [[BITCAST3]](<vscale x 2 x p0>)
; CHECK-NEXT: [[COPY4:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z4
; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z5
- ; CHECK-NEXT: [[CONCAT_VECTORS2:%[0-9]+]]:_(<vscale x 4 x p0>) = G_CONCAT_VECTORS [[COPY4]](<vscale x 2 x s64>), [[COPY5]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST4:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY4]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST5:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY5]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[CONCAT_VECTORS2:%[0-9]+]]:_(<vscale x 4 x p0>) = G_CONCAT_VECTORS [[BITCAST4]](<vscale x 2 x p0>), [[BITCAST5]](<vscale x 2 x p0>)
; CHECK-NEXT: [[COPY6:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z6
; CHECK-NEXT: [[COPY7:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z7
- ; CHECK-NEXT: [[CONCAT_VECTORS3:%[0-9]+]]:_(<vscale x 4 x p0>) = G_CONCAT_VECTORS [[COPY6]](<vscale x 2 x s64>), [[COPY7]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST6:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY6]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST7:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY7]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[CONCAT_VECTORS3:%[0-9]+]]:_(<vscale x 4 x p0>) = G_CONCAT_VECTORS [[BITCAST6]](<vscale x 2 x p0>), [[BITCAST7]](<vscale x 2 x p0>)
; CHECK-NEXT: RET_ReallyLR
ret void
}
@@ -314,12 +326,20 @@ define void @formal_argument_nxv8p0_2(<vscale x 8 x ptr> %0, <vscale x 8 x ptr>
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z1
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z2
; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z3
- ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 8 x p0>) = G_CONCAT_VECTORS [[COPY]](<vscale x 2 x s64>), [[COPY1]](<vscale x 2 x s64>), [[COPY2]](<vscale x 2 x s64>), [[COPY3]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY1]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY2]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST3:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY3]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 8 x p0>) = G_CONCAT_VECTORS [[BITCAST]](<vscale x 2 x p0>), [[BITCAST1]](<vscale x 2 x p0>), [[BITCAST2]](<vscale x 2 x p0>), [[BITCAST3]](<vscale x 2 x p0>)
; CHECK-NEXT: [[COPY4:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z4
; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z5
; CHECK-NEXT: [[COPY6:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z6
; CHECK-NEXT: [[COPY7:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z7
- ; CHECK-NEXT: [[CONCAT_VECTORS1:%[0-9]+]]:_(<vscale x 8 x p0>) = G_CONCAT_VECTORS [[COPY4]](<vscale x 2 x s64>), [[COPY5]](<vscale x 2 x s64>), [[COPY6]](<vscale x 2 x s64>), [[COPY7]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST4:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY4]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST5:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY5]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST6:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY6]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST7:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY7]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[CONCAT_VECTORS1:%[0-9]+]]:_(<vscale x 8 x p0>) = G_CONCAT_VECTORS [[BITCAST4]](<vscale x 2 x p0>), [[BITCAST5]](<vscale x 2 x p0>), [[BITCAST6]](<vscale x 2 x p0>), [[BITCAST7]](<vscale x 2 x p0>)
; CHECK-NEXT: RET_ReallyLR
ret void
}
@@ -436,7 +456,15 @@ define void @formal_argument_nxv16p0_1(<vscale x 16 x ptr> %0) {
; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z5
; CHECK-NEXT: [[COPY6:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z6
; CHECK-NEXT: [[COPY7:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z7
- ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 16 x p0>) = G_CONCAT_VECTORS [[COPY]](<vscale x 2 x s64>), [[COPY1]](<vscale x 2 x s64>), [[COPY2]](<vscale x 2 x s64>), [[COPY3]](<vscale x 2 x s64>), [[COPY4]](<vscale x 2 x s64>), [[COPY5]](<vscale x 2 x s64>), [[COPY6]](<vscale x 2 x s64>), [[COPY7]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY1]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY2]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST3:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY3]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST4:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY4]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST5:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY5]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST6:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY6]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST7:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY7]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 16 x p0>) = G_CONCAT_VECTORS [[BITCAST]](<vscale x 2 x p0>), [[BITCAST1]](<vscale x 2 x p0>), [[BITCAST2]](<vscale x 2 x p0>), [[BITCAST3]](<vscale x 2 x p0>), [[BITCAST4]](<vscale x 2 x p0>), [[BITCAST5]](<vscale x 2 x p0>), [[BITCAST6]](<vscale x 2 x p0>), [[BITCAST7]](<vscale x 2 x p0>)
; CHECK-NEXT: RET_ReallyLR
ret void
}
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/translate-sve-formal-argument.ll b/llvm/test/CodeGen/AArch64/GlobalISel/translate-sve-formal-argument.ll
index ec89da824779a..e6476ae726540 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/translate-sve-formal-argument.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/translate-sve-formal-argument.ll
@@ -155,7 +155,9 @@ define void @formal_argument_nxv4p0(<vscale x 4 x ptr> %0) {
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z0
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z1
- ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 4 x p0>) = G_CONCAT_VECTORS [[COPY]](<vscale x 2 x s64>), [[COPY1]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY1]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 4 x p0>) = G_CONCAT_VECTORS [[BITCAST]](<vscale x 2 x p0>), [[BITCAST1]](<vscale x 2 x p0>)
; CHECK-NEXT: RET_ReallyLR
ret void
}
@@ -255,7 +257,11 @@ define void @formal_argument_nxv8p0(<vscale x 8 x ptr> %0) {
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z1
; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z2
; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z3
- ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 8 x p0>) = G_CONCAT_VECTORS [[COPY]](<vscale x 2 x s64>), [[COPY1]](<vscale x 2 x s64>), [[COPY2]](<vscale x 2 x s64>), [[COPY3]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY1]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY2]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST3:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY3]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 8 x p0>) = G_CONCAT_VECTORS [[BITCAST]](<vscale x 2 x p0>), [[BITCAST1]](<vscale x 2 x p0>), [[BITCAST2]](<vscale x 2 x p0>), [[BITCAST3]](<vscale x 2 x p0>)
; CHECK-NEXT: RET_ReallyLR
ret void
}
@@ -383,7 +389,15 @@ define void @formal_argument_nxv16p0(<vscale x 16 x ptr> %0) {
; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z5
; CHECK-NEXT: [[COPY6:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z6
; CHECK-NEXT: [[COPY7:%[0-9]+]]:_(<vscale x 2 x s64>) = COPY $z7
- ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 16 x p0>) = G_CONCAT_VECTORS [[COPY]](<vscale x 2 x s64>), [[COPY1]](<vscale x 2 x s64>), [[COPY2]](<vscale x 2 x s64>), [[COPY3]](<vscale x 2 x s64>), [[COPY4]](<vscale x 2 x s64>), [[COPY5]](<vscale x 2 x s64>), [[COPY6]](<vscale x 2 x s64>), [[COPY7]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY1]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY2]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST3:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY3]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST4:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY4]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST5:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY5]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST6:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY6]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[BITCAST7:%[0-9]+]]:_(<vscale x 2 x p0>) = G_BITCAST [[COPY7]](<vscale x 2 x s64>)
+ ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<vscale x 16 x p0>) = G_CONCAT_VECTORS [[BITCAST]](<vscale x 2 x p0>), [[BITCAST1]](<vscale x 2 x p0>), [[BITCAST2]](<vscale x 2 x p0>), [[BITCAST3]](<vscale x 2 x p0>), [[BITCAST4]](<vscale x 2 x p0>), [[BITCAST5]](<vscale x 2 x p0>), [[BITCAST6]](<vscale x 2 x p0>), [[BITCAST7]](<vscale x 2 x p0>)
; CHECK-NEXT: RET_ReallyLR
ret void
}
>From 1799b1b527ebcfb322dfa5a22c343c3088f45fa0 Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Mon, 23 Feb 2026 15:28:36 +0300
Subject: [PATCH 38/40] Revert GIMatchTable patch
---
.../GlobalISel/GIMatchTableExecutorImpl.h | 48 +++++--------------
1 file changed, 13 insertions(+), 35 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
index de605d833a460..8f6586e79d78a 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
@@ -285,46 +285,24 @@ bool GIMatchTableExecutor::executeMatchTable(
break;
}
const LLT Ty = MRI.getType(MO.getReg());
-
- SmallVector<LLT> TypesToTry;
- TypesToTry.push_back(Ty);
-
- // Always try the integer patterns as we now consider that to be generic
- // (to an extent)
- if (LLT::getUseExtended() && !Ty.getScalarType().isInteger())
- TypesToTry.push_back(
- Ty.changeElementType(LLT::integer(Ty.getScalarSizeInBits())));
-
- if (LLT::getUseExtended() && Ty.isAnyScalar() &&
- Ty.getScalarSizeInBits() > 8)
- TypesToTry.push_back(
- Ty.changeElementType(LLT::floatIEEE(Ty.getScalarSizeInBits())));
-
- const auto JumpTableBase = CurrentIdx;
- bool Matched = false;
- for (LLT Type : TypesToTry) {
- const auto TyI = ExecInfo.TypeIDMap.find(Type);
- if (TyI == ExecInfo.TypeIDMap.end())
- continue;
- const int64_t TypeID = TyI->second;
- if (TypeID < LowerBound || UpperBound <= TypeID)
- continue;
- const auto NumEntry = (TypeID - LowerBound);
- // Each entry is 4 bytes
- CurrentIdx =
- readBytesAs<uint32_t>(MatchTable + JumpTableBase + (NumEntry * 4));
- if (!CurrentIdx) {
- CurrentIdx = Default;
- continue;
- }
- Matched = true;
+ const auto TyI = ExecInfo.TypeIDMap.find(Ty);
+ if (TyI == ExecInfo.TypeIDMap.end()) {
+ CurrentIdx = Default;
break;
}
- if (!Matched) {
+ const int64_t TypeID = TyI->second;
+ if (TypeID < LowerBound || UpperBound <= TypeID) {
+ CurrentIdx = Default;
+ break;
+ }
+ const auto NumEntry = (TypeID - LowerBound);
+ // Each entry is 4 bytes
+ CurrentIdx =
+ readBytesAs<uint32_t>(MatchTable + CurrentIdx + (NumEntry * 4));
+ if (!CurrentIdx) {
CurrentIdx = Default;
break;
}
-
OnFailResumeAt.push_back(Default);
break;
}
>From c721feef10c442fb39532417c9d771d649244aa7 Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Mon, 23 Feb 2026 16:07:31 +0300
Subject: [PATCH 39/40] review fixes
---
llvm/include/llvm/CodeGenTypes/LowLevelType.h | 2 ++
llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp | 4 ++--
llvm/lib/CodeGen/LowLevelTypeUtils.cpp | 1 +
.../unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp | 8 ++++----
4 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/llvm/include/llvm/CodeGenTypes/LowLevelType.h b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
index d79f3a4a8e246..fdd39602ee887 100644
--- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h
+++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
@@ -155,6 +155,7 @@ class LLT {
return LLT{Info, EC, ScalarTy.getSizeInBits().getFixedValue()};
}
+ // FIXME: Remove this builder
static constexpr LLT floatIEEE(unsigned SizeInBits) {
switch (SizeInBits) {
default:
@@ -309,6 +310,7 @@ class LLT {
constexpr bool isFloat(FpSemantics Sem) const {
return isFloat() && getFpSemantics() == Sem;
}
+ // FIXME: Remove or rework this predicate
constexpr bool isFloatIEEE() const {
return isFloat(APFloatBase::S_IEEEhalf) ||
isFloat(APFloatBase::S_IEEEsingle) ||
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 2afcba0a72f6f..5f3fc9fd80cb3 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -4602,8 +4602,8 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
ResTy.changeElementType(LLT::buildInteger(ResTy.getScalarSizeInBits()));
Register CastedSubByReg = SubByReg;
- if (!(SubByRegTy.getScalarType().isAnyScalar() ||
- SubByRegTy.getScalarType().isInteger())) {
+ if (!SubByRegTy.getScalarType().isAnyScalar() &&
+ !SubByRegTy.getScalarType().isInteger()) {
auto BitcastDst = SubByRegTy.changeElementType(
LLT::buildInteger(SubByRegTy.getScalarSizeInBits()));
CastedSubByReg = MIRBuilder.buildBitcast(BitcastDst, SubByReg).getReg(0);
diff --git a/llvm/lib/CodeGen/LowLevelTypeUtils.cpp b/llvm/lib/CodeGen/LowLevelTypeUtils.cpp
index 659510a660c07..a213c81eae98e 100644
--- a/llvm/lib/CodeGen/LowLevelTypeUtils.cpp
+++ b/llvm/lib/CodeGen/LowLevelTypeUtils.cpp
@@ -111,6 +111,7 @@ const llvm::fltSemantics &llvm::getFltSemanticForLLT(LLT Ty) {
"Expected a any scalar or float type.");
// Any scalar type always matches IEEE format
+ // FIXME: Remove this handling
if (Ty.isAnyScalar()) {
switch (Ty.getSizeInBits()) {
default:
diff --git a/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp b/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp
index 6826f3e7e5c21..89a304dfe1dca 100644
--- a/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp
+++ b/llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp
@@ -107,17 +107,17 @@ TEST_F(AArch64IRTranslatorTest, IRTranslateBfloat16) {
Function *F = M->getFunction("foo");
auto *MF = MMI->getMachineFunction(*F);
MachineRegisterInfo &MRI = MF->getRegInfo();
- ASSERT_FALSE(MF->getProperties().hasProperty(
+ EXPECT_FALSE(MF->getProperties().hasProperty(
llvm::MachineFunctionProperties::Property::FailedISel));
for (auto &MI : MF->front()) {
if (MI.getOpcode() == TargetOpcode::G_LOAD) {
- ASSERT_TRUE(MRI.getType(MI.getOperand(0).getReg()).isBFloat16());
+ EXPECT_TRUE(MRI.getType(MI.getOperand(0).getReg()).isBFloat16());
}
if (MI.getOpcode() == TargetOpcode::G_FADD ||
MI.getOpcode() == TargetOpcode::G_FMUL) {
for (auto &Op : MI.operands()) {
- ASSERT_TRUE(MRI.getType(Op.getReg()).isBFloat16());
+ EXPECT_TRUE(MRI.getType(Op.getReg()).isBFloat16());
}
}
}
@@ -128,6 +128,6 @@ TEST_F(AArch64IRTranslatorTest, IRTranslateBfloat16) {
PM.run(*M);
MF = MMI->getMachineFunction(*F);
- ASSERT_TRUE(MF->getProperties().hasProperty(
+ EXPECT_TRUE(MF->getProperties().hasProperty(
llvm::MachineFunctionProperties::Property::FailedISel));
}
>From aba480da90d74d1cb2c1e0209b2c773e1f073c00 Mon Sep 17 00:00:00 2001
From: Denis Gerasimov <dengzmm at gmail.com>
Date: Tue, 3 Mar 2026 18:09:22 +0300
Subject: [PATCH 40/40] Rm redundant builders
---
llvm/include/llvm/CodeGen/TargetLowering.h | 2 +-
llvm/include/llvm/CodeGenTypes/LowLevelType.h | 30 ++++-------
llvm/lib/CodeGen/GlobalISel/CallLowering.cpp | 2 +-
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 24 ++++-----
.../CodeGen/GlobalISel/LegalizerHelper.cpp | 52 +++++++++----------
.../CodeGen/GlobalISel/MachineIRBuilder.cpp | 2 +-
6 files changed, 50 insertions(+), 62 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 314978f18dd79..1a4eaaf214c4d 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -442,7 +442,7 @@ class LLVM_ABI TargetLoweringBase {
/// G_INSERT_VECTOR_ELT, G_EXTRACT_VECTOR_ELT,
/// G_INSERT_SUBVECTOR, and G_EXTRACT_SUBVECTOR
LLT getVectorIdxLLT(const DataLayout &DL) const {
- return LLT::buildInteger(getVectorIdxWidth(DL));
+ return LLT::integer(getVectorIdxWidth(DL));
}
/// Returns the type to be used for the EVL/AVL operand of VP nodes:
diff --git a/llvm/include/llvm/CodeGenTypes/LowLevelType.h b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
index fdd39602ee887..ea488538361c4 100644
--- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h
+++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
@@ -89,35 +89,20 @@ class LLT {
return LLT{Kind::ANY_SCALAR, ElementCount::getFixed(0), SizeInBits};
}
- static constexpr LLT integer(unsigned SizeInBits) {
- return LLT{Kind::INTEGER, ElementCount::getFixed(0), SizeInBits};
- }
-
- static LLT floatingPoint(const FpSemantics &Sem) {
- return LLT{Kind::FLOAT, ElementCount::getFixed(0),
- APFloat::getSizeInBits(APFloatBase::EnumToSemantics(Sem)), Sem};
- }
-
- static LLT buildInteger(unsigned SizeInBits) {
+ static LLT integer(unsigned SizeInBits) {
if (!getUseExtended())
return LLT::scalar(SizeInBits);
- return integer(SizeInBits);
+ return LLT{Kind::INTEGER, ElementCount::getFixed(0), SizeInBits};
}
- static LLT buildFloatingPoint(const FpSemantics &Sem) {
+ static LLT floatingPoint(const FpSemantics &Sem) {
if (!getUseExtended())
return LLT::scalar(
APFloat::getSizeInBits(APFloatBase::EnumToSemantics(Sem)));
- return floatingPoint(Sem);
- }
-
- static LLT buildFloatingIEEE(unsigned SizeInBits) {
- if (!getUseExtended())
- return LLT::scalar(SizeInBits);
-
- return floatIEEE(SizeInBits);
+ return LLT{Kind::FLOAT, ElementCount::getFixed(0),
+ APFloat::getSizeInBits(APFloatBase::EnumToSemantics(Sem)), Sem};
}
/// Get a low-level token; just a scalar with zero bits (or no size).
@@ -156,7 +141,10 @@ class LLT {
}
// FIXME: Remove this builder
- static constexpr LLT floatIEEE(unsigned SizeInBits) {
+ static LLT floatIEEE(unsigned SizeInBits) {
+ if (!getUseExtended())
+ return LLT::scalar(SizeInBits);
+
switch (SizeInBits) {
default:
llvm_unreachable("Wrong SizeInBits for IEEE Floating point!");
diff --git a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
index a918b3f8f4e20..4775dd6c8be31 100644
--- a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp
@@ -1313,7 +1313,7 @@ void CallLowering::ValueHandler::copyArgumentMemory(
MemSize, DstAlign);
const LLT PtrTy = MRI.getType(DstPtr);
- const LLT SizeTy = LLT::buildInteger(PtrTy.getSizeInBits());
+ const LLT SizeTy = LLT::integer(PtrTy.getSizeInBits());
auto SizeConst = MIRBuilder.buildConstant(SizeTy, MemSize);
MIRBuilder.buildMemCpy(DstPtr, SrcPtr, SizeConst, *DstMMO, *SrcMMO);
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 3715dcdc6ea7c..eaf27557d9127 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -899,7 +899,7 @@ bool IRTranslator::emitJumpTableHeader(SwitchCG::JumpTable &JT,
auto Cst = getOrCreateVReg(
*ConstantInt::get(SValue.getType(), JTH.Last - JTH.First));
Cst = MIB.buildZExtOrTrunc(PtrScalarTy, Cst).getReg(0);
- auto Cmp = MIB.buildICmp(CmpInst::ICMP_UGT, LLT::buildInteger(1), Sub, Cst);
+ auto Cmp = MIB.buildICmp(CmpInst::ICMP_UGT, LLT::integer(1), Sub, Cst);
auto BrCond = MIB.buildBrCond(Cmp.getReg(0), *JT.Default);
@@ -930,7 +930,7 @@ void IRTranslator::emitSwitchCase(SwitchCG::CaseBlock &CB,
return;
}
- const LLT i1Ty = LLT::buildInteger(1);
+ const LLT i1Ty = LLT::integer(1);
// Build the compare.
if (!CB.CmpMHS) {
const auto *CI = dyn_cast<ConstantInt>(CB.CmpRHS);
@@ -1142,8 +1142,8 @@ void IRTranslator::emitBitTestHeader(SwitchCG::BitTestBlock &B,
if (!B.FallthroughUnreachable) {
// Conditional branch to the default block.
auto RangeCst = MIB.buildConstant(SwitchOpTy, B.Range);
- auto RangeCmp = MIB.buildICmp(CmpInst::Predicate::ICMP_UGT,
- LLT::buildInteger(1), RangeSub, RangeCst);
+ auto RangeCmp = MIB.buildICmp(CmpInst::Predicate::ICMP_UGT, LLT::integer(1),
+ RangeSub, RangeCst);
MIB.buildBrCond(RangeCmp, *B.Default);
}
@@ -1168,16 +1168,16 @@ void IRTranslator::emitBitTestCase(SwitchCG::BitTestBlock &BB,
// would need to be to shift a 1 bit in that position.
auto MaskTrailingZeros =
MIB.buildConstant(SwitchTy, llvm::countr_zero(B.Mask));
- Cmp = MIB.buildICmp(ICmpInst::ICMP_EQ, LLT::buildInteger(1), Reg,
+ Cmp = MIB.buildICmp(ICmpInst::ICMP_EQ, LLT::integer(1), Reg,
MaskTrailingZeros)
.getReg(0);
} else if (PopCount == BB.Range) {
// There is only one zero bit in the range, test for it directly.
auto MaskTrailingOnes =
MIB.buildConstant(SwitchTy, llvm::countr_one(B.Mask));
- Cmp = MIB.buildICmp(CmpInst::ICMP_NE, LLT::buildInteger(1), Reg,
- MaskTrailingOnes)
- .getReg(0);
+ Cmp =
+ MIB.buildICmp(CmpInst::ICMP_NE, LLT::integer(1), Reg, MaskTrailingOnes)
+ .getReg(0);
} else {
// Make desired shift.
auto CstOne = MIB.buildConstant(SwitchTy, 1);
@@ -1187,7 +1187,7 @@ void IRTranslator::emitBitTestCase(SwitchCG::BitTestBlock &BB,
auto CstMask = MIB.buildConstant(SwitchTy, B.Mask);
auto AndOp = MIB.buildAnd(SwitchTy, SwitchVal, CstMask);
auto CstZero = MIB.buildConstant(SwitchTy, 0);
- Cmp = MIB.buildICmp(CmpInst::ICMP_NE, LLT::buildInteger(1), AndOp, CstZero)
+ Cmp = MIB.buildICmp(CmpInst::ICMP_NE, LLT::integer(1), AndOp, CstZero)
.getReg(0);
}
@@ -1734,7 +1734,7 @@ bool IRTranslator::translateMemFunc(const CallInst &CI,
SrcRegs.push_back(SrcReg);
}
- LLT SizeTy = LLT::buildInteger(MinPtrSize);
+ LLT SizeTy = LLT::integer(MinPtrSize);
// The size operand should be the minimum of the pointer sizes.
Register &SizeOpReg = SrcRegs[SrcRegs.size() - 1];
@@ -4073,8 +4073,8 @@ bool IRTranslator::emitSPDescriptorParent(StackProtectorDescriptor &SPD,
}
// Perform the comparison.
- auto Cmp = CurBuilder->buildICmp(CmpInst::ICMP_NE, LLT::buildInteger(1),
- Guard, GuardVal);
+ auto Cmp =
+ CurBuilder->buildICmp(CmpInst::ICMP_NE, LLT::integer(1), Guard, GuardVal);
// If the guard/stackslot do not equal, branch to failure MBB.
CurBuilder->buildBrCond(Cmp, *SPD.getFailureMBB());
// Otherwise branch to success MBB.
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 5f3fc9fd80cb3..9731a0cf0ba58 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -1182,7 +1182,7 @@ LegalizerHelper::createFCMPLibcall(MachineInstr &MI,
const CmpInst::Predicate ICmpPred,
const DstOp &Res) -> Register {
// FCMP libcall always returns an i32, and needs an ICMP with #0.
- LLT TempLLT = LLT::buildInteger(32);
+ LLT TempLLT = LLT::integer(32);
Register Temp = MRI.createGenericVirtualRegister(TempLLT);
// Generate libcall, holding result in Temp
const auto Status = createLibcall(
@@ -4413,7 +4413,7 @@ LegalizerHelper::scalarizeVectorBooleanStore(GStore &StoreMI) {
// We need to build an integer scalar of the vector bit pattern.
// It's not legal for us to add padding when storing a vector.
unsigned NumBits = MemTy.getSizeInBits();
- LLT IntTy = LLT::buildInteger(NumBits);
+ LLT IntTy = LLT::integer(NumBits);
auto CurrVal = MIRBuilder.buildConstant(IntTy, 0);
LLT IdxTy = TLI.getVectorIdxLLT(MF.getDataLayout());
@@ -4599,13 +4599,13 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
case TargetOpcode::G_FNEG: {
auto [Res, ResTy, SubByReg, SubByRegTy] = MI.getFirst2RegLLTs();
LLT TyInt =
- ResTy.changeElementType(LLT::buildInteger(ResTy.getScalarSizeInBits()));
+ ResTy.changeElementType(LLT::integer(ResTy.getScalarSizeInBits()));
Register CastedSubByReg = SubByReg;
if (!SubByRegTy.getScalarType().isAnyScalar() &&
!SubByRegTy.getScalarType().isInteger()) {
auto BitcastDst = SubByRegTy.changeElementType(
- LLT::buildInteger(SubByRegTy.getScalarSizeInBits()));
+ LLT::integer(SubByRegTy.getScalarSizeInBits()));
CastedSubByReg = MIRBuilder.buildBitcast(BitcastDst, SubByReg).getReg(0);
}
@@ -5488,7 +5488,7 @@ LegalizerHelper::reduceLoadStoreWidth(GLoadStore &LdStMI, unsigned TypeIdx,
return UnableToLegalize;
LLT PtrTy = MRI.getType(AddrReg);
- const LLT OffsetTy = LLT::buildInteger(PtrTy.getSizeInBits());
+ const LLT OffsetTy = LLT::integer(PtrTy.getSizeInBits());
unsigned TotalSize = ValTy.getSizeInBits();
@@ -8331,8 +8331,8 @@ LegalizerHelper::lowerU64ToF64BitFloatOps(MachineInstr &MI) {
static LegalizerHelper::LegalizeResult
loweri64tof16ITOFP(MachineInstr &MI, Register Dst, LLT DstTy, Register Src,
LLT SrcTy, MachineIRBuilder &MIRBuilder) {
- auto DstFpTy = SrcTy.changeElementType(
- LLT::buildFloatingIEEE(SrcTy.getScalarSizeInBits()));
+ auto DstFpTy =
+ SrcTy.changeElementType(LLT::floatIEEE(SrcTy.getScalarSizeInBits()));
auto M1 = MI.getOpcode() == TargetOpcode::G_UITOFP
? MIRBuilder.buildUITOFP(DstFpTy, Src)
: MIRBuilder.buildSITOFP(DstFpTy, Src);
@@ -8376,9 +8376,9 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerUITOFP(MachineInstr &MI) {
LegalizerHelper::LegalizeResult LegalizerHelper::lowerSITOFP(MachineInstr &MI) {
auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();
- const LLT I64 = LLT::buildInteger(64);
- const LLT I32 = LLT::buildInteger(32);
- const LLT I1 = LLT::buildInteger(1);
+ const LLT I64 = LLT::integer(64);
+ const LLT I32 = LLT::integer(32);
+ const LLT I1 = LLT::integer(1);
if (SrcTy == I1) {
auto True = MIRBuilder.buildFConstant(DstTy, -1.0);
@@ -8558,13 +8558,13 @@ LegalizerHelper::lowerFPTOINT_SAT(MachineInstr &MI) {
if (AreExactFloatBounds) {
// Clamp Src by MinFloat from below. If Src is NaN the result is MinFloat.
auto MaxC = MIRBuilder.buildFConstant(SrcTy, MinFloat);
- auto MaxP = MIRBuilder.buildFCmp(CmpInst::FCMP_OGT, LLT::buildInteger(1),
- Src, MaxC);
+ auto MaxP =
+ MIRBuilder.buildFCmp(CmpInst::FCMP_OGT, LLT::integer(1), Src, MaxC);
auto Max = MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
// Clamp by MaxFloat from above. NaN cannot occur.
auto MinC = MIRBuilder.buildFConstant(SrcTy, MaxFloat);
- auto MinP = MIRBuilder.buildFCmp(CmpInst::FCMP_OLT, LLT::buildInteger(1),
- Max, MinC, MachineInstr::FmNoNans);
+ auto MinP = MIRBuilder.buildFCmp(CmpInst::FCMP_OLT, LLT::integer(1), Max,
+ MinC, MachineInstr::FmNoNans);
auto Min =
MIRBuilder.buildSelect(SrcTy, MinP, Max, MinC, MachineInstr::FmNoNans);
// Convert clamped value to integer. In the unsigned case we're done,
@@ -8578,7 +8578,7 @@ LegalizerHelper::lowerFPTOINT_SAT(MachineInstr &MI) {
// Otherwise, select 0 if Src is NaN.
auto FpToInt = MIRBuilder.buildFPTOSI(DstTy, Min);
auto IsZero =
- MIRBuilder.buildFCmp(CmpInst::FCMP_UNO, LLT::buildInteger(1), Src, Src);
+ MIRBuilder.buildFCmp(CmpInst::FCMP_UNO, LLT::integer(1), Src, Src);
MIRBuilder.buildSelect(Dst, IsZero, MIRBuilder.buildConstant(DstTy, 0),
FpToInt);
MI.eraseFromParent();
@@ -8593,12 +8593,12 @@ LegalizerHelper::lowerFPTOINT_SAT(MachineInstr &MI) {
// If Src ULT MinFloat, select MinInt. In particular, this also selects
// MinInt if Src is NaN.
- auto ULT = MIRBuilder.buildFCmp(CmpInst::FCMP_ULT, LLT::buildInteger(1), Src,
+ auto ULT = MIRBuilder.buildFCmp(CmpInst::FCMP_ULT, LLT::integer(1), Src,
MIRBuilder.buildFConstant(SrcTy, MinFloat));
auto Max = MIRBuilder.buildSelect(
DstTy, ULT, MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
// If Src OGT MaxFloat, select MaxInt.
- auto OGT = MIRBuilder.buildFCmp(CmpInst::FCMP_OGT, LLT::buildInteger(1), Src,
+ auto OGT = MIRBuilder.buildFCmp(CmpInst::FCMP_OGT, LLT::integer(1), Src,
MIRBuilder.buildFConstant(SrcTy, MaxFloat));
// In the unsigned case we are done, because we mapped NaN to MinInt, which
@@ -8614,7 +8614,7 @@ LegalizerHelper::lowerFPTOINT_SAT(MachineInstr &MI) {
auto Min = MIRBuilder.buildSelect(
DstTy, OGT, MIRBuilder.buildConstant(DstTy, MaxInt), Max);
auto IsZero =
- MIRBuilder.buildFCmp(CmpInst::FCMP_UNO, LLT::buildInteger(1), Src, Src);
+ MIRBuilder.buildFCmp(CmpInst::FCMP_UNO, LLT::integer(1), Src, Src);
MIRBuilder.buildSelect(Dst, IsZero, MIRBuilder.buildConstant(DstTy, 0), Min);
MI.eraseFromParent();
return Legalized;
@@ -8806,7 +8806,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerMinMax(MachineInstr &MI) {
auto [Dst, Src0, Src1] = MI.getFirst3Regs();
const CmpInst::Predicate Pred = minMaxToCompare(MI.getOpcode());
- LLT CmpType = MRI.getType(Dst).changeElementType(LLT::buildInteger(1));
+ LLT CmpType = MRI.getType(Dst).changeElementType(LLT::integer(1));
auto Cmp = MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);
@@ -8870,9 +8870,9 @@ LegalizerHelper::lowerFCopySign(MachineInstr &MI) {
const int Src1Size = Src1Ty.getScalarSizeInBits();
LLT DstIntTy =
- DstTy.changeElementType(LLT::buildInteger(DstTy.getScalarSizeInBits()));
- LLT Src0IntTy = Src0Ty.changeElementType(LLT::buildInteger(Src0Size));
- LLT Src1IntTy = Src1Ty.changeElementType(LLT::buildInteger(Src1Size));
+ DstTy.changeElementType(LLT::integer(DstTy.getScalarSizeInBits()));
+ LLT Src0IntTy = Src0Ty.changeElementType(LLT::integer(Src0Size));
+ LLT Src1IntTy = Src1Ty.changeElementType(LLT::integer(Src1Size));
Register Src0Int = Src0;
Register Src1Int = Src1;
@@ -10212,7 +10212,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerSelect(MachineInstr &MI) {
MI.getFirst4RegLLTs();
LLT Op1TyInt =
- Op1Ty.changeElementType(LLT::buildInteger(Op1Ty.getScalarSizeInBits()));
+ Op1Ty.changeElementType(LLT::integer(Op1Ty.getScalarSizeInBits()));
bool IsEltPtr = DstTy.isPointerOrPointerVector();
if (IsEltPtr) {
@@ -10263,7 +10263,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerSelect(MachineInstr &MI) {
if (!(Op2Ty.getScalarType().isAnyScalar() ||
Op2Ty.getScalarType().isInteger())) {
auto Op2TyInt =
- Op2Ty.changeElementType(LLT::buildInteger(Op2Ty.getScalarSizeInBits()));
+ Op2Ty.changeElementType(LLT::integer(Op2Ty.getScalarSizeInBits()));
Op2Reg = MIRBuilder.buildBitcast(Op2TyInt, Op2Reg).getReg(0);
}
@@ -10397,13 +10397,13 @@ LegalizerHelper::lowerAbsDiffToMinMax(MachineInstr &MI) {
LegalizerHelper::LegalizeResult LegalizerHelper::lowerFAbs(MachineInstr &MI) {
auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
LLT TyInt =
- DstTy.changeElementType(LLT::buildInteger(DstTy.getScalarSizeInBits()));
+ DstTy.changeElementType(LLT::integer(DstTy.getScalarSizeInBits()));
Register CastedSrc = SrcReg;
if (!(SrcTy.getScalarType().isAnyScalar() ||
SrcTy.getScalarType().isInteger())) {
auto SrcTyInt =
- SrcTy.changeElementType(LLT::buildInteger(SrcTy.getScalarSizeInBits()));
+ SrcTy.changeElementType(LLT::integer(SrcTy.getScalarSizeInBits()));
CastedSrc = MIRBuilder.buildBitcast(SrcTyInt, SrcReg).getReg(0);
}
diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index 51f371d4a4108..63c9ada9b059d 100644
--- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -787,7 +787,7 @@ MachineInstrBuilder MachineIRBuilder::buildShuffleSplat(const DstOp &Res,
assert(Src.getLLTTy(*getMRI()) == DstTy.getElementType() &&
"Expected Src to match Dst elt ty");
auto UndefVec = buildUndef(DstTy);
- auto Zero = buildConstant(LLT::buildInteger(64), 0);
+ auto Zero = buildConstant(LLT::integer(64), 0);
auto InsElt = buildInsertVectorElement(DstTy, UndefVec, Src, Zero);
SmallVector<int, 16> ZeroMask(DstTy.getNumElements());
return buildShuffleVector(DstTy, InsElt, UndefVec, ZeroMask);
More information about the llvm-commits
mailing list