Skip to content

[GlobalISel][LLT] Introduce FPInfo for LLT (Enable bfloat, ppc128float and others in GlobalISel)#155107

Merged
lialan merged 69 commits into
llvm:mainfrom
DenisGZM:llt-fpinfo
Mar 24, 2026
Merged

[GlobalISel][LLT] Introduce FPInfo for LLT (Enable bfloat, ppc128float and others in GlobalISel)#155107
lialan merged 69 commits into
llvm:mainfrom
DenisGZM:llt-fpinfo

Conversation

@DenisGZM

@DenisGZM DenisGZM commented Aug 23, 2025

Copy link
Copy Markdown
Contributor

Added extra information in LLT to support ambiguous fp types during GlobalISel. Original idea by @tgymnich

Main differences from #122503 are:

  • Do not deprecate LLT::scalar
  • Allow targets to enable/disable IR translation with extenden LLT via TargetOption::EnableGlobalISelExtendedLLT (disabled by default)
  • IRTranslator use TargetLoweringInfo for appropriate LLT generation.
  • For this reason added flag in GlobalISelMatchTable` to allow switch between legacy and new extended LLT names
  • Revert using stubs like LLT::float32 for float types as they are real now. Added TODO for such cases.

Also MIRParser now may parse new type indentifiers.

@llvmbot

llvmbot commented Aug 23, 2025

Copy link
Copy Markdown
Member

@llvm/pr-subscribers-llvm-selectiondag
@llvm/pr-subscribers-tablegen

@llvm/pr-subscribers-backend-amdgpu

Author: Denis.G (DenisGZM)

Changes

Added extra information in LLT to support ambiguous fp types during GlobalISel. Original idea by @tgymnich

Main differences from #122503 are:

  • Do not deprecate LLT::scalar
  • Allow targets to enable/disable IR translation with extenden LLT via TargetOption::EnableGlobalISelExtendedLLT (disabled by default)
  • IRTranslator use TargetLoweringInfo for appropriate LLT generation.
  • For this reason added flag in GlobalISelMatchTable` to allow switch between legacy and new extended LLT names
  • Revert using stubs like LLT::float32 for float types as they are real now. Added TODO for such cases.

Also MIRParser now may parse new type indetifiers.


Patch is 97.84 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/155107.diff

50 Files Affected:

  • (modified) llvm/include/llvm/CodeGen/Analysis.h (+2-1)
  • (modified) llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h (+2)
  • (modified) llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h (+1-1)
  • (modified) llvm/include/llvm/CodeGen/LowLevelTypeUtils.h (+3-3)
  • (modified) llvm/include/llvm/CodeGen/TargetLowering.h (+3)
  • (modified) llvm/include/llvm/CodeGenTypes/LowLevelType.h (+275-99)
  • (modified) llvm/include/llvm/Target/TargetMachine.h (+1)
  • (modified) llvm/include/llvm/Target/TargetOptions.h (+6-1)
  • (modified) llvm/lib/CodeGen/Analysis.cpp (+5-5)
  • (modified) llvm/lib/CodeGen/GlobalISel/CallLowering.cpp (+7-6)
  • (modified) llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp (+46-41)
  • (modified) llvm/lib/CodeGen/GlobalISel/LegalizeMutations.cpp (+2-4)
  • (modified) llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp (+1-1)
  • (modified) llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp (+2-1)
  • (modified) llvm/lib/CodeGen/LowLevelTypeUtils.cpp (+71-16)
  • (modified) llvm/lib/CodeGen/MIRParser/MIParser.cpp (+78-37)
  • (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (+2-2)
  • (modified) llvm/lib/CodeGen/TargetLoweringBase.cpp (+8)
  • (modified) llvm/lib/CodeGenTypes/LowLevelType.cpp (+65-14)
  • (modified) llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp (+2-2)
  • (modified) llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp (+1-1)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp (+3-2)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPUCombinerHelper.cpp (+5-3)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp (+9-8)
  • (modified) llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid0.mir (+2-2)
  • (modified) llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid1.mir (+2-2)
  • (modified) llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid2.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid3.mir (+3-3)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err0.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err1.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err10.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err11.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err12.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err13.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err14.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err15.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err2.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err3.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err4.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err5.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err6.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err7.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err8.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err9.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/WebAssembly/typed-immediate-operand-invalid0.mir (+2-2)
  • (modified) llvm/test/CodeGen/MIR/WebAssembly/typed-immediate-operand-invalid1.mir (+2-2)
  • (modified) llvm/unittests/CodeGen/GlobalISel/CMakeLists.txt (+1)
  • (added) llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp (+130)
  • (modified) llvm/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp (+8-6)
  • (modified) llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp (+70-9)
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/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/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/include/llvm/CodeGen/LowLevelTypeUtils.h b/llvm/include/llvm/CodeGen/LowLevelTypeUtils.h
index 51a298eb8b247..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,11 +36,11 @@ 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.
 LLVM_ABI const llvm::fltSemantics &getFltSemanticForLLT(LLT Ty);
-}
+} // namespace llvm
 
 #endif // LLVM_CODEGEN_LOWLEVELTYPEUTILS_H
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 d8e0848aff84d..0c217ba1fcf7e 100644
--- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h
+++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
@@ -39,68 +39,148 @@ 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
+  };
+
+  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,
+  };
+
+  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;
+
+    return Kind::VECTOR_ANY;
+  }
+
+  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;
+
+    return Kind::ANY_SCALAR;
+  }
+
   /// 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};
+    return LLT{Kind::ANY_SCALAR, 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::ANY_SCALAR, 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) {
     assert(!EC.isScalar() && "invalid number of vector elements");
-    return LLT{/*isPointer=*/false, /*isVector=*/true, /*isScalar=*/false,
-               EC, ScalarSizeInBits, /*AddressSpace=*/0};
+    return LLT{Kind::VECTOR_ANY, 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::EXTENDED_FP80);
+  }
+
+  /// 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::PPC128_FLOAT);
   }
 
   /// 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);
+  static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits) {
+    return vector(ElementCount::getFixed(NumElements),
+                  LLT::scalar(ScalarSizeInBits));
   }
 
   /// Get a low-level fixed-width vector of some number of elements and element
@@ -111,9 +191,9 @@ 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);
+  static constexpr LLT scalable_vector(unsigned MinNumElements, unsigned ScalarSizeInBits) {
+    return vector(ElementCount::getScalable(MinNumElements),
+                  LLT::scalar(ScalarSizeInBits));
   }
 
   /// Get a low-level scalable vector of some number of elements and element
@@ -132,27 +212,79 @@ class LLT {
     return scalarOrVector(EC, LLT::scalar(static_cast<unsigned>(ScalarSize)));
   }
 
-  explicit constexpr LLT(bool isPointer, bool isVector, bool isScalar,
-                         ElementCount EC, uint64_t SizeInBits,
-                         unsigned AddressSpace)
+  explicit constexpr LLT(Kind Info, ElementCount EC, uint64_t SizeInBits,
+                         unsigned AddressSpace, FPVariant FP)
       : LLT() {
-    init(isPointer, isVector, isScalar, EC, SizeInBits, AddressSpace);
+    init(Info, EC, SizeInBits, AddressSpace, FP);
   }
-  explicit constexpr LLT()
-      : IsScalar(false), IsPointer(false), IsVector(false), RawData(0) {}
 
-  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 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::ANY_SCALAR || 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::EXTENDED_FP80);
+  }
+  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 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 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_ANY || 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
@@ -177,12 +309,18 @@ 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(); }
 
   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());
   }
@@ -207,6 +345,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 {
@@ -217,10 +364,14 @@ 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(), 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
@@ -229,6 +380,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.
@@ -243,6 +398,9 @@ class LLT {
     }
 
     assert(getScalarSizeInBits() % Factor == 0);
+    if (isInteger())
+      return integer(getScalarSizeInBits() / Factor);
+
     return scalar(getScalarSizeInBits() / Factor);
   }
 
@@ -277,10 +435,26 @@ 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());
+
+    if (isIntegerVector())
+      return integer(getScalarSizeInBits());
+
+    return scalar(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;
@@ -290,8 +464,14 @@ class LLT {
 #endif
 
   constexpr bool operator==(const LLT &RHS) const {
-    return IsPointer == RHS.IsPointer && IsVector == RHS.IsVector &&
-           IsScalar == RHS.IsScalar && RHS.RawData == RawData;
+    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;
   }
 
   constexpr bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
@@ -301,37 +481,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 : 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
   /// described in static const *Field variables. Each of these variables
   /// is a 2-element array, with the first ele...
[truncated]

@llvmbot

llvmbot commented Aug 23, 2025

Copy link
Copy Markdown
Member

@llvm/pr-subscribers-llvm-globalisel

Author: Denis.G (DenisGZM)

Changes

Added extra information in LLT to support ambiguous fp types during GlobalISel. Original idea by @tgymnich

Main differences from #122503 are:

  • Do not deprecate LLT::scalar
  • Allow targets to enable/disable IR translation with extenden LLT via TargetOption::EnableGlobalISelExtendedLLT (disabled by default)
  • IRTranslator use TargetLoweringInfo for appropriate LLT generation.
  • For this reason added flag in GlobalISelMatchTable` to allow switch between legacy and new extended LLT names
  • Revert using stubs like LLT::float32 for float types as they are real now. Added TODO for such cases.

Also MIRParser now may parse new type indetifiers.


Patch is 97.84 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/155107.diff

50 Files Affected:

  • (modified) llvm/include/llvm/CodeGen/Analysis.h (+2-1)
  • (modified) llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h (+2)
  • (modified) llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h (+1-1)
  • (modified) llvm/include/llvm/CodeGen/LowLevelTypeUtils.h (+3-3)
  • (modified) llvm/include/llvm/CodeGen/TargetLowering.h (+3)
  • (modified) llvm/include/llvm/CodeGenTypes/LowLevelType.h (+275-99)
  • (modified) llvm/include/llvm/Target/TargetMachine.h (+1)
  • (modified) llvm/include/llvm/Target/TargetOptions.h (+6-1)
  • (modified) llvm/lib/CodeGen/Analysis.cpp (+5-5)
  • (modified) llvm/lib/CodeGen/GlobalISel/CallLowering.cpp (+7-6)
  • (modified) llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp (+46-41)
  • (modified) llvm/lib/CodeGen/GlobalISel/LegalizeMutations.cpp (+2-4)
  • (modified) llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp (+1-1)
  • (modified) llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp (+2-1)
  • (modified) llvm/lib/CodeGen/LowLevelTypeUtils.cpp (+71-16)
  • (modified) llvm/lib/CodeGen/MIRParser/MIParser.cpp (+78-37)
  • (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (+2-2)
  • (modified) llvm/lib/CodeGen/TargetLoweringBase.cpp (+8)
  • (modified) llvm/lib/CodeGenTypes/LowLevelType.cpp (+65-14)
  • (modified) llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp (+2-2)
  • (modified) llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp (+1-1)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp (+3-2)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPUCombinerHelper.cpp (+5-3)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp (+9-8)
  • (modified) llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid0.mir (+2-2)
  • (modified) llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid1.mir (+2-2)
  • (modified) llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid2.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid3.mir (+3-3)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err0.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err1.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err10.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err11.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err12.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err13.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err14.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err15.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err2.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err3.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err4.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err5.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err6.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err7.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err8.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err9.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/WebAssembly/typed-immediate-operand-invalid0.mir (+2-2)
  • (modified) llvm/test/CodeGen/MIR/WebAssembly/typed-immediate-operand-invalid1.mir (+2-2)
  • (modified) llvm/unittests/CodeGen/GlobalISel/CMakeLists.txt (+1)
  • (added) llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp (+130)
  • (modified) llvm/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp (+8-6)
  • (modified) llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp (+70-9)
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/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/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/include/llvm/CodeGen/LowLevelTypeUtils.h b/llvm/include/llvm/CodeGen/LowLevelTypeUtils.h
index 51a298eb8b247..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,11 +36,11 @@ 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.
 LLVM_ABI const llvm::fltSemantics &getFltSemanticForLLT(LLT Ty);
-}
+} // namespace llvm
 
 #endif // LLVM_CODEGEN_LOWLEVELTYPEUTILS_H
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 d8e0848aff84d..0c217ba1fcf7e 100644
--- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h
+++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
@@ -39,68 +39,148 @@ 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
+  };
+
+  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,
+  };
+
+  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;
+
+    return Kind::VECTOR_ANY;
+  }
+
+  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;
+
+    return Kind::ANY_SCALAR;
+  }
+
   /// 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};
+    return LLT{Kind::ANY_SCALAR, 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::ANY_SCALAR, 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) {
     assert(!EC.isScalar() && "invalid number of vector elements");
-    return LLT{/*isPointer=*/false, /*isVector=*/true, /*isScalar=*/false,
-               EC, ScalarSizeInBits, /*AddressSpace=*/0};
+    return LLT{Kind::VECTOR_ANY, 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::EXTENDED_FP80);
+  }
+
+  /// 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::PPC128_FLOAT);
   }
 
   /// 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);
+  static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits) {
+    return vector(ElementCount::getFixed(NumElements),
+                  LLT::scalar(ScalarSizeInBits));
   }
 
   /// Get a low-level fixed-width vector of some number of elements and element
@@ -111,9 +191,9 @@ 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);
+  static constexpr LLT scalable_vector(unsigned MinNumElements, unsigned ScalarSizeInBits) {
+    return vector(ElementCount::getScalable(MinNumElements),
+                  LLT::scalar(ScalarSizeInBits));
   }
 
   /// Get a low-level scalable vector of some number of elements and element
@@ -132,27 +212,79 @@ class LLT {
     return scalarOrVector(EC, LLT::scalar(static_cast<unsigned>(ScalarSize)));
   }
 
-  explicit constexpr LLT(bool isPointer, bool isVector, bool isScalar,
-                         ElementCount EC, uint64_t SizeInBits,
-                         unsigned AddressSpace)
+  explicit constexpr LLT(Kind Info, ElementCount EC, uint64_t SizeInBits,
+                         unsigned AddressSpace, FPVariant FP)
       : LLT() {
-    init(isPointer, isVector, isScalar, EC, SizeInBits, AddressSpace);
+    init(Info, EC, SizeInBits, AddressSpace, FP);
   }
-  explicit constexpr LLT()
-      : IsScalar(false), IsPointer(false), IsVector(false), RawData(0) {}
 
-  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 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::ANY_SCALAR || 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::EXTENDED_FP80);
+  }
+  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 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 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_ANY || 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
@@ -177,12 +309,18 @@ 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(); }
 
   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());
   }
@@ -207,6 +345,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 {
@@ -217,10 +364,14 @@ 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(), 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
@@ -229,6 +380,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.
@@ -243,6 +398,9 @@ class LLT {
     }
 
     assert(getScalarSizeInBits() % Factor == 0);
+    if (isInteger())
+      return integer(getScalarSizeInBits() / Factor);
+
     return scalar(getScalarSizeInBits() / Factor);
   }
 
@@ -277,10 +435,26 @@ 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());
+
+    if (isIntegerVector())
+      return integer(getScalarSizeInBits());
+
+    return scalar(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;
@@ -290,8 +464,14 @@ class LLT {
 #endif
 
   constexpr bool operator==(const LLT &RHS) const {
-    return IsPointer == RHS.IsPointer && IsVector == RHS.IsVector &&
-           IsScalar == RHS.IsScalar && RHS.RawData == RawData;
+    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;
   }
 
   constexpr bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
@@ -301,37 +481,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 : 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
   /// described in static const *Field variables. Each of these variables
   /// is a 2-element array, with the first ele...
[truncated]

@llvmbot

llvmbot commented Aug 23, 2025

Copy link
Copy Markdown
Member

@llvm/pr-subscribers-backend-aarch64

Author: Denis.G (DenisGZM)

Changes

Added extra information in LLT to support ambiguous fp types during GlobalISel. Original idea by @tgymnich

Main differences from #122503 are:

  • Do not deprecate LLT::scalar
  • Allow targets to enable/disable IR translation with extenden LLT via TargetOption::EnableGlobalISelExtendedLLT (disabled by default)
  • IRTranslator use TargetLoweringInfo for appropriate LLT generation.
  • For this reason added flag in GlobalISelMatchTable` to allow switch between legacy and new extended LLT names
  • Revert using stubs like LLT::float32 for float types as they are real now. Added TODO for such cases.

Also MIRParser now may parse new type indetifiers.


Patch is 97.84 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/155107.diff

50 Files Affected:

  • (modified) llvm/include/llvm/CodeGen/Analysis.h (+2-1)
  • (modified) llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h (+2)
  • (modified) llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h (+1-1)
  • (modified) llvm/include/llvm/CodeGen/LowLevelTypeUtils.h (+3-3)
  • (modified) llvm/include/llvm/CodeGen/TargetLowering.h (+3)
  • (modified) llvm/include/llvm/CodeGenTypes/LowLevelType.h (+275-99)
  • (modified) llvm/include/llvm/Target/TargetMachine.h (+1)
  • (modified) llvm/include/llvm/Target/TargetOptions.h (+6-1)
  • (modified) llvm/lib/CodeGen/Analysis.cpp (+5-5)
  • (modified) llvm/lib/CodeGen/GlobalISel/CallLowering.cpp (+7-6)
  • (modified) llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp (+46-41)
  • (modified) llvm/lib/CodeGen/GlobalISel/LegalizeMutations.cpp (+2-4)
  • (modified) llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp (+1-1)
  • (modified) llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp (+2-1)
  • (modified) llvm/lib/CodeGen/LowLevelTypeUtils.cpp (+71-16)
  • (modified) llvm/lib/CodeGen/MIRParser/MIParser.cpp (+78-37)
  • (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (+2-2)
  • (modified) llvm/lib/CodeGen/TargetLoweringBase.cpp (+8)
  • (modified) llvm/lib/CodeGenTypes/LowLevelType.cpp (+65-14)
  • (modified) llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp (+2-2)
  • (modified) llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp (+1-1)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp (+3-2)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPUCombinerHelper.cpp (+5-3)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp (+9-8)
  • (modified) llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid0.mir (+2-2)
  • (modified) llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid1.mir (+2-2)
  • (modified) llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid2.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid3.mir (+3-3)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err0.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err1.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err10.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err11.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err12.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err13.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err14.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err15.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err2.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err3.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err4.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err5.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err6.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err7.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err8.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/Generic/scalable-vector-type-err9.mir (+1-1)
  • (modified) llvm/test/CodeGen/MIR/WebAssembly/typed-immediate-operand-invalid0.mir (+2-2)
  • (modified) llvm/test/CodeGen/MIR/WebAssembly/typed-immediate-operand-invalid1.mir (+2-2)
  • (modified) llvm/unittests/CodeGen/GlobalISel/CMakeLists.txt (+1)
  • (added) llvm/unittests/CodeGen/GlobalISel/IRTranslatorBF16Test.cpp (+130)
  • (modified) llvm/unittests/CodeGen/GlobalISel/LegalizerInfoTest.cpp (+8-6)
  • (modified) llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp (+70-9)
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/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/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/include/llvm/CodeGen/LowLevelTypeUtils.h b/llvm/include/llvm/CodeGen/LowLevelTypeUtils.h
index 51a298eb8b247..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,11 +36,11 @@ 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.
 LLVM_ABI const llvm::fltSemantics &getFltSemanticForLLT(LLT Ty);
-}
+} // namespace llvm
 
 #endif // LLVM_CODEGEN_LOWLEVELTYPEUTILS_H
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 d8e0848aff84d..0c217ba1fcf7e 100644
--- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h
+++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h
@@ -39,68 +39,148 @@ 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
+  };
+
+  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,
+  };
+
+  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;
+
+    return Kind::VECTOR_ANY;
+  }
+
+  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;
+
+    return Kind::ANY_SCALAR;
+  }
+
   /// 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};
+    return LLT{Kind::ANY_SCALAR, 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::ANY_SCALAR, 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) {
     assert(!EC.isScalar() && "invalid number of vector elements");
-    return LLT{/*isPointer=*/false, /*isVector=*/true, /*isScalar=*/false,
-               EC, ScalarSizeInBits, /*AddressSpace=*/0};
+    return LLT{Kind::VECTOR_ANY, 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::EXTENDED_FP80);
+  }
+
+  /// 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::PPC128_FLOAT);
   }
 
   /// 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);
+  static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits) {
+    return vector(ElementCount::getFixed(NumElements),
+                  LLT::scalar(ScalarSizeInBits));
   }
 
   /// Get a low-level fixed-width vector of some number of elements and element
@@ -111,9 +191,9 @@ 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);
+  static constexpr LLT scalable_vector(unsigned MinNumElements, unsigned ScalarSizeInBits) {
+    return vector(ElementCount::getScalable(MinNumElements),
+                  LLT::scalar(ScalarSizeInBits));
   }
 
   /// Get a low-level scalable vector of some number of elements and element
@@ -132,27 +212,79 @@ class LLT {
     return scalarOrVector(EC, LLT::scalar(static_cast<unsigned>(ScalarSize)));
   }
 
-  explicit constexpr LLT(bool isPointer, bool isVector, bool isScalar,
-                         ElementCount EC, uint64_t SizeInBits,
-                         unsigned AddressSpace)
+  explicit constexpr LLT(Kind Info, ElementCount EC, uint64_t SizeInBits,
+                         unsigned AddressSpace, FPVariant FP)
       : LLT() {
-    init(isPointer, isVector, isScalar, EC, SizeInBits, AddressSpace);
+    init(Info, EC, SizeInBits, AddressSpace, FP);
   }
-  explicit constexpr LLT()
-      : IsScalar(false), IsPointer(false), IsVector(false), RawData(0) {}
 
-  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 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::ANY_SCALAR || 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::EXTENDED_FP80);
+  }
+  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 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 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_ANY || 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
@@ -177,12 +309,18 @@ 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(); }
 
   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());
   }
@@ -207,6 +345,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 {
@@ -217,10 +364,14 @@ 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(), 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
@@ -229,6 +380,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.
@@ -243,6 +398,9 @@ class LLT {
     }
 
     assert(getScalarSizeInBits() % Factor == 0);
+    if (isInteger())
+      return integer(getScalarSizeInBits() / Factor);
+
     return scalar(getScalarSizeInBits() / Factor);
   }
 
@@ -277,10 +435,26 @@ 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());
+
+    if (isIntegerVector())
+      return integer(getScalarSizeInBits());
+
+    return scalar(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;
@@ -290,8 +464,14 @@ class LLT {
 #endif
 
   constexpr bool operator==(const LLT &RHS) const {
-    return IsPointer == RHS.IsPointer && IsVector == RHS.IsVector &&
-           IsScalar == RHS.IsScalar && RHS.RawData == RawData;
+    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;
   }
 
   constexpr bool operator!=(const LLT &RHS) const { return !(*this == RHS); }
@@ -301,37 +481,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 : 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
   /// described in static const *Field variables. Each of these variables
   /// is a 2-element array, with the first ele...
[truncated]

@github-actions

github-actions Bot commented Aug 23, 2025

Copy link
Copy Markdown

✅ With the latest revision this PR passed the C/C++ code formatter.

@DenisGZM

Copy link
Copy Markdown
Contributor Author

@aemerson @arsenm could you please take a look at this patch. Saw you discussed on llvm discourse about changes in LLT, so would be nice to hear your thoughts on this

@DenisGZM DenisGZM changed the title [GlobalISel][LLT] Introduce FPInfo for LLT [GlobalISel][LLT] Introduce FPInfo for LLT (Enable bfloat, ppc128float and others in GlobalISel) Sep 1, 2025
@llvm-ci

llvm-ci commented Mar 24, 2026

Copy link
Copy Markdown

LLVM Buildbot has detected a new failure on builder clang-armv8-quick running on linaro-clang-armv8-quick while building llvm at step 5 "ninja check 1".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/154/builds/29467

Here is the relevant piece of the build log for the reference
Step 5 (ninja check 1) failure: stage 1 checked (failure)
******************** TEST 'LLVM-Unit :: CodeGen/GlobalISel/./GlobalISelTests/1/311' FAILED ********************
Script(shard):
--
GTEST_OUTPUT=json:/home/tcwg-buildbot/worker/clang-armv8-quick/stage1/unittests/CodeGen/GlobalISel/./GlobalISelTests-LLVM-Unit-3451860-1-311.json GTEST_SHUFFLE=0 GTEST_TOTAL_SHARDS=311 GTEST_SHARD_INDEX=1 /home/tcwg-buildbot/worker/clang-armv8-quick/stage1/unittests/CodeGen/GlobalISel/./GlobalISelTests
--

Note: This is test shard 2 of 311.
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from AArch64IRTranslatorTest
[ RUN      ] AArch64IRTranslatorTest.IRTranslateBfloat16

--
exit: -11
--
shard JSON output does not exist: /home/tcwg-buildbot/worker/clang-armv8-quick/stage1/unittests/CodeGen/GlobalISel/./GlobalISelTests-LLVM-Unit-3451860-1-311.json
********************


@llvm-ci

llvm-ci commented Mar 24, 2026

Copy link
Copy Markdown

LLVM Buildbot has detected a new failure on builder llvm-clang-x86_64-darwin running on doug-worker-3 while building llvm at step 6 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/23/builds/18809

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'LLVM-Unit :: CodeGen/GlobalISel/./GlobalISelTests/1/10' FAILED ********************
Script(shard):
--
GTEST_OUTPUT=json:/Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/unittests/CodeGen/GlobalISel/./GlobalISelTests-LLVM-Unit-19206-1-10.json GTEST_SHUFFLE=0 GTEST_TOTAL_SHARDS=10 GTEST_SHARD_INDEX=1 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/unittests/CodeGen/GlobalISel/./GlobalISelTests
--

Note: This is test shard 2 of 10.
[==========] Running 31 tests from 4 test suites.
[----------] Global test environment set-up.
[----------] 1 test from AArch64IRTranslatorTest
[ RUN      ] AArch64IRTranslatorTest.IRTranslateBfloat16

--
exit: -11
--
shard JSON output does not exist: /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/unittests/CodeGen/GlobalISel/./GlobalISelTests-LLVM-Unit-19206-1-10.json
********************


@llvm-ci

llvm-ci commented Mar 24, 2026

Copy link
Copy Markdown

LLVM Buildbot has detected a new failure on builder clang-solaris11-sparcv9 running on solaris11-sparcv9 while building llvm at step 5 "ninja check 1".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/13/builds/12352

Here is the relevant piece of the build log for the reference
Step 5 (ninja check 1) failure: stage 1 checked (failure)
******************** TEST 'LLVM-Unit :: CodeGen/GlobalISel/./GlobalISelTests/1/39' FAILED ********************
Script(shard):
--
GTEST_OUTPUT=json:/opt/llvm-buildbot/home/solaris11-sparcv9/clang-solaris11-sparcv9/stage1/unittests/CodeGen/GlobalISel/./GlobalISelTests-LLVM-Unit-4429-1-39.json GTEST_SHUFFLE=0 GTEST_TOTAL_SHARDS=39 GTEST_SHARD_INDEX=1 /opt/llvm-buildbot/home/solaris11-sparcv9/clang-solaris11-sparcv9/stage1/unittests/CodeGen/GlobalISel/./GlobalISelTests
--

Note: This is test shard 2 of 39.
[==========] Running 8 tests from 2 test suites.
[----------] Global test environment set-up.
[----------] 1 test from AArch64IRTranslatorTest
[ RUN      ] AArch64IRTranslatorTest.IRTranslateBfloat16

--
exit: -11
--
shard JSON output does not exist: /opt/llvm-buildbot/home/solaris11-sparcv9/clang-solaris11-sparcv9/stage1/unittests/CodeGen/GlobalISel/./GlobalISelTests-LLVM-Unit-4429-1-39.json
********************


@jplehr

jplehr commented Mar 24, 2026

Copy link
Copy Markdown
Contributor

Hi, anybody looking at fixing this issue or should we revert?

@llvm-ci

llvm-ci commented Mar 24, 2026

Copy link
Copy Markdown

LLVM Buildbot has detected a new failure on builder llvm-clang-win-x-armv7l running on as-builder-1 while building llvm at step 9 "test-check-llvm".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/38/builds/8344

Here is the relevant piece of the build log for the reference
Step 9 (test-check-llvm) failure: Test just built components: check-llvm completed (failure)
******************** TEST 'LLVM-Unit :: CodeGen/GlobalISel/./GlobalISelTests.exe/1/156' FAILED ********************
Script(shard):
--
GTEST_OUTPUT=json:C:\buildbot\as-builder-1\x-armv7l\build\unittests\CodeGen\GlobalISel\.\GlobalISelTests.exe-LLVM-Unit-2604-1-156.json GTEST_SHUFFLE=0 GTEST_TOTAL_SHARDS=156 GTEST_SHARD_INDEX=1 C:\buildbot\as-builder-1\x-armv7l\build\unittests\CodeGen\GlobalISel\.\GlobalISelTests.exe
--

Script:
--
C:\buildbot\as-builder-1\x-armv7l\build\unittests\CodeGen\GlobalISel\.\GlobalISelTests.exe --gtest_filter=AArch64IRTranslatorTest.IRTranslateBfloat16
--
unknown file: error: SEH exception with code 0x3221225477 thrown in the test body.
Stack trace:



unknown file
SEH exception with code 0x3221225477 thrown in the test body.
Stack trace:




********************


@arsenm

arsenm commented Mar 24, 2026

Copy link
Copy Markdown
Contributor

Hi, anybody looking at fixing this issue or should we revert?

Probably is #188273

@lialan

lialan commented Mar 24, 2026

Copy link
Copy Markdown
Member

Hi, anybody looking at fixing this issue or should we revert?

Probably is #188273

@jplehr merged. should be clear now.

@aengelke

Copy link
Copy Markdown
Contributor

@joker-eph

Copy link
Copy Markdown
Contributor

There are compile-time failure here:

/vol/worker/mlir-nvidia/mlir-nvidia-gcc7/llvm.src/llvm/include/llvm/CodeGenTypes/LowLevelType.h:501:35: error: call to non-constexpr function ‘static llvm::LLT llvm::LLT::integer(unsigned int)’
     return integer(getSizeInBits());
                                   ^

joker-eph added a commit to joker-eph/llvm-project that referenced this pull request Mar 24, 2026
…c128float and others in GlobalISel) (llvm#155107)"

This reverts commit b1aa6a4 and commit ce44d63.

This fails the build with some older gcc:

llvm/include/llvm/CodeGenTypes/LowLevelType.h:501:35: error: call to non-constexpr function ‘static llvm::LLT llvm::LLT::integer(unsigned int)’
     return integer(getSizeInBits());
                                   ^
@joker-eph

Copy link
Copy Markdown
Contributor

Reverting in #188344

joker-eph added a commit that referenced this pull request Mar 24, 2026
…c128float and others in GlobalISel) (#155107)" (#188344)

This reverts commit b1aa6a4 and commit
ce44d63.

This fails the build with some older gcc:

llvm/include/llvm/CodeGenTypes/LowLevelType.h:501:35: error: call to
non-constexpr function ‘static llvm::LLT llvm::LLT::integer(unsigned
int)’
     return integer(getSizeInBits());
                                   ^
ronlieb pushed a commit to ROCm/llvm-project that referenced this pull request Mar 24, 2026
…c128float and others in GlobalISel) (llvm#155107)" (llvm#188344)

This reverts commit b1aa6a4 and commit
ce44d63.

This fails the build with some older gcc:

llvm/include/llvm/CodeGenTypes/LowLevelType.h:501:35: error: call to
non-constexpr function ‘static llvm::LLT llvm::LLT::integer(unsigned
int)’
     return integer(getSizeInBits());
                                   ^
@lialan

lialan commented Mar 25, 2026

Copy link
Copy Markdown
Member

There are compile-time failure here:

/vol/worker/mlir-nvidia/mlir-nvidia-gcc7/llvm.src/llvm/include/llvm/CodeGenTypes/LowLevelType.h:501:35: error: call to non-constexpr function ‘static llvm::LLT llvm::LLT::integer(unsigned int)’
     return integer(getSizeInBits());
                                   ^

Duh, this is something that can easily get missed. GCC 7 and 8 would fail the compilation, GCC 9+ works.

lialan added a commit to lialan/llvm-project that referenced this pull request Mar 25, 2026
…calling non-constexpr integer()/floatingPoint()

PR llvm#155107 introduced LLT::integer() and LLT::floatingPoint() which are
non-constexpr (they call getUseExtended() which reads a mutable static).
Several constexpr member functions now transitively call these, which
GCC 7/8 eagerly rejects even if the non-constexpr path is never taken
at compile time. GCC 9+ defers this check and accepts the code.

Remove constexpr from: getScalarType, changeElementSize,
changeVectorElementCount, changeElementCount, divide, multiplyElements,
getElementType, changeToInteger, operator==, operator!=.

Convert affected static_asserts in LowLevelTypeTest.cpp to runtime
EXPECT_EQ checks.
Aadarsh-Keshri pushed a commit to Aadarsh-Keshri/llvm-project that referenced this pull request Mar 28, 2026
…t and others in GlobalISel) (llvm#155107)

Added extra information in LLT to support ambiguous fp types during
GlobalISel. Original idea by @tgymnich

Main differences from llvm#122503
are:
* Do not deprecate LLT::scalar
* Allow targets to enable/disable IR translation with extenden LLT via
`TargetOption::EnableGlobalISelExtendedLLT` (disabled by default)
* `IRTranslator` use `TargetLoweringInfo` for appropriate `LLT`
generation.
* For this reason added flag in GlobalISelMatchTable` to allow switch
between legacy and new extended LLT names
* Revert using stubs like `LLT::float32` for float types as they are
real now. Added `TODO` for such cases.

Also MIRParser now may parse new type indentifiers.

---------

Co-authored-by: Tim Gymnich <tim@gymni.ch>
Co-authored-by: Ryan Cowan <ryan.cowan@arm.com>
Aadarsh-Keshri pushed a commit to Aadarsh-Keshri/llvm-project that referenced this pull request Mar 28, 2026
…c128float and others in GlobalISel) (llvm#155107)" (llvm#188344)

This reverts commit b1aa6a4 and commit
ce44d63.

This fails the build with some older gcc:

llvm/include/llvm/CodeGenTypes/LowLevelType.h:501:35: error: call to
non-constexpr function ‘static llvm::LLT llvm::LLT::integer(unsigned
int)’
     return integer(getSizeInBits());
                                   ^
@llvm-ci

llvm-ci commented Mar 29, 2026

Copy link
Copy Markdown

LLVM Buildbot has detected a new failure on builder clang-sparc64-linux running on debian-stadler-sparc64 while building llvm at step 7 "ninja check 1".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/114/builds/239

Here is the relevant piece of the build log for the reference
Step 7 (ninja check 1) failure: stage 1 checked (failure)
...
/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/llvm/llvm/unittests/ADT/CountCopyAndMove.h:34:58: warning: ‘<unnamed>.._anon_211::__Counter.llvm::CountCopyAndMove::val’ is used uninitialized [-Wuninitialized]
   34 |   CountCopyAndMove(CountCopyAndMove &&other) : val(other.val) {
      |                                                    ~~~~~~^~~
/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/llvm/llvm/unittests/ADT/FunctionExtrasTest.cpp: In member function ‘virtual void {anonymous}::UniqueFunctionTest_MovedFromStateIsDestroyedCorrectly_Test::TestBody()’:
/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/llvm/llvm/unittests/ADT/FunctionExtrasTest.cpp:338:9: note: ‘<anonymous>’ declared here
  338 |         [Counter = CountCopyAndMove{}] {}};
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[357/1092] Building CXX object unittests/ADT/CMakeFiles/ADTTests.dir/EquivalenceClassesTest.cpp.o
[358/1092] Building CXX object unittests/ADT/CMakeFiles/ADTTests.dir/IListNodeBaseTest.cpp.o
[359/1092] Building CXX object unittests/ADT/CMakeFiles/ADTTests.dir/ImmutableMapTest.cpp.o
FAILED: [code=1] unittests/ADT/CMakeFiles/ADTTests.dir/ImmutableMapTest.cpp.o 
/usr/bin/c++ -DLLVM_BUILD_STATIC -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GLIBCXX_USE_CXX11_ABI=1 -D_GNU_SOURCE -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/stage1/unittests/ADT -I/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/llvm/llvm/unittests/ADT -I/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/stage1/include -I/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/llvm/llvm/include -I/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/llvm/third-party/unittest/googletest/include -I/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/llvm/third-party/unittest/googlemock/include -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wimplicit-fallthrough -Wno-maybe-uninitialized -Wno-nonnull -Wno-class-memaccess -Wno-dangling-reference -Wno-redundant-move -Wno-pessimizing-move -Wno-array-bounds -Wno-stringop-overread -Wno-dangling-pointer -Wno-noexcept-type -Wdelete-non-virtual-dtor -Wsuggest-override -Wno-comment -Wno-misleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -O3 -DNDEBUG -std=c++17 -UNDEBUG -Wno-dangling-else -Wno-variadic-macros -fno-exceptions -funwind-tables -fno-rtti -Wno-suggest-override -MD -MT unittests/ADT/CMakeFiles/ADTTests.dir/ImmutableMapTest.cpp.o -MF unittests/ADT/CMakeFiles/ADTTests.dir/ImmutableMapTest.cpp.o.d -o unittests/ADT/CMakeFiles/ADTTests.dir/ImmutableMapTest.cpp.o -c /var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/llvm/llvm/unittests/ADT/ImmutableMapTest.cpp
In member function ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator=(std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&&)’:
cc1plus: error: expected primary-expression before ‘=’ token [-Wtemplate-body]
cc1plus: error: expected primary-expression before ‘=’ token [-Wtemplate-body]
cc1plus: error: expected primary-expression before ‘;’ token [-Wtemplate-body]
cc1plus: error: duplicate ‘static’ specifier [-Wtemplate-body]
In file included from /usr/include/c++/15/string:56,
                 from /usr/include/c++/15/bits/locale_classes.h:42,
                 from /usr/include/c++/15/bits/ios_base.h:43,
                 from /usr/include/c++/15/streambuf:45,
                 from /usr/include/c++/15/bits/streambuf_iterator.h:37,
                 from /usr/include/c++/15/iterator:68,
                 from /var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/llvm/llvm/include/llvm/ADT/ADL.h:13,
                 from /var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/llvm/llvm/include/llvm/ADT/Hashing.h:47,
                 from /var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/llvm/llvm/include/llvm/ADT/FoldingSet.h:19,
                 from /var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/llvm/llvm/include/llvm/ADT/ImmutableMap.h:17,
                 from /var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/llvm/llvm/unittests/ADT/ImmutableMapTest.cpp:9:
/usr/include/c++/15/bits/basic_string.h:970:43: error: declaration does not declare anything [-Wtemplate-body]
  970 |                 _M_set_length(__str.size());
      |                                           ^
[360/1092] Building CXX object unittests/ADT/CMakeFiles/ADTTests.dir/CoalescingBitVectorTest.cpp.o
[361/1092] Building CXX object unittests/ADT/CMakeFiles/ADTTests.dir/Interleave.cpp.o
[362/1092] Building CXX object unittests/ADT/CMakeFiles/ADTTests.dir/IListBaseTest.cpp.o
[363/1092] Building CXX object unittests/ADT/CMakeFiles/ADTTests.dir/IListTest.cpp.o
[364/1092] Building CXX object unittests/ADT/CMakeFiles/ADTTests.dir/IntEqClassesTest.cpp.o
[365/1092] Building CXX object unittests/ADT/CMakeFiles/ADTTests.dir/HashingTest.cpp.o
[366/1092] Building CXX object unittests/ADT/CMakeFiles/ADTTests.dir/IntrusiveRefCntPtrTest.cpp.o
[367/1092] Building CXX object unittests/ADT/CMakeFiles/ADTTests.dir/ImmutableListTest.cpp.o
[368/1092] Building CXX object unittests/ADT/CMakeFiles/ADTTests.dir/LazyAtomicPointerTest.cpp.o
[369/1092] Building CXX object tools/clang/unittests/Sema/CMakeFiles/SemaTests.dir/HeuristicResolverTest.cpp.o
/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/llvm/clang/unittests/Sema/HeuristicResolverTest.cpp: In instantiation of ‘void clang::{anonymous}::expectResolution(llvm::StringRef, ResolveFnT<ParamT>, const InputMatcher&, const OutputMatchers& ...) [with InputNode = clang::CXXDependentScopeMemberExpr; ParamT = const clang::CXXDependentScopeMemberExpr*; InputMatcher = clang::ast_matchers::internal::Matcher<clang::Stmt>; OutputMatchers = {}; ResolveFnT<ParamT> = std::function<std::vector<const clang::NamedDecl*>(const clang::HeuristicResolver*, const clang::CXXDependentScopeMemberExpr*)>]’:
/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/llvm/clang/unittests/Sema/HeuristicResolverTest.cpp:92:30:   required from ‘void clang::{anonymous}::expectResolution(llvm::StringRef, std::vector<const clang::NamedDecl*> (clang::HeuristicResolver::*)(const InputNode*) const, const InputMatcher&, const OutputMatchers& ...) [with InputNode = clang::CXXDependentScopeMemberExpr; InputMatcher = clang::ast_matchers::internal::Matcher<clang::Stmt>; OutputMatchers = {}]’
   92 |   expectResolution<InputNode>(
      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~^
   93 |       Code, ResolveFnT<const InputNode *>(std::mem_fn(ResolveFn)), IM, OMS...);
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/var/lib/buildbot/workers/debian-stadler-sparc64/clang-sparc64-linux/llvm/clang/unittests/Sema/HeuristicResolverTest.cpp:522:19:   required from here
  522 |   expectResolution(

lialan added a commit that referenced this pull request Apr 4, 2026
…c128float and others in GlobalISel) (#155107)" (#188502)

This is a reland of #155107
along with a fix for old gcc builds.

This patch is reverted in
#188344 due to compilation
failures described in
#155107 (comment)

The fix to old gcc builds is to remove `constexpr` modifiers in the
original patch in 0721d8e
llvm-sync Bot pushed a commit to arm/arm-toolchain that referenced this pull request Apr 4, 2026
… bfloat, ppc128float and others in GlobalISel) (#155107)" (#188502)

This is a reland of llvm/llvm-project#155107
along with a fix for old gcc builds.

This patch is reverted in
llvm/llvm-project#188344 due to compilation
failures described in
llvm/llvm-project#155107 (comment)

The fix to old gcc builds is to remove `constexpr` modifiers in the
original patch in 0721d8e7768c011b8cf2d4d223ca6eca3392b1f9
@QuantumSegfault

Copy link
Copy Markdown
Contributor

Been experimenting with this (after reland), and it's pretty sweet. Really helps clean up RegBankSelect (at least for Wasm).

Am I correct in my understanding that while this introduces extended LLT, it doesn't actually migrate much (or any of) of the core GISel infastructure to use LLT::integer or LLT:floatIEEE instead of LLT::scalar?

I noticed that for instance, IRTranslator for switch still uses LLT::scalar for the range check, which is not ideal. Is anybody investigating this or should I sift through existing uses of LLT::scalar and open a PR trying to specialize them?

@QuantumSegfault

Copy link
Copy Markdown
Contributor

I've found an issue while trying this out (related to match table). Details at #190873

cpullvm-upstream-sync Bot pushed a commit to navaneethshan/cpullvm-toolchain-1 that referenced this pull request Apr 13, 2026
… bfloat, ppc128float and others in GlobalISel) (#155107)" (#188502)

This is a reland of llvm/llvm-project#155107
along with a fix for old gcc builds.

This patch is reverted in
llvm/llvm-project#188344 due to compilation
failures described in
llvm/llvm-project#155107 (comment)

The fix to old gcc builds is to remove `constexpr` modifiers in the
original patch in 0721d8e7768c011b8cf2d4d223ca6eca3392b1f9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.