[Mlir-commits] [mlir] [MLIR][LLVM] Query target extension type data layouts (PR #236540)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Wed Oct 28 12:14:28 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir

Author: Akimasa Watanuki (Men-cotton)

<details>
<summary>Changes</summary>

Expose the layout representation of LLVM target extension types and delegate size and alignment queries to that representation. Follow LLVM target type layout rules for pointer representations, explicit SPIR-V layouts, padding, and scalable vectors so clients do not need target-name-specific alignment fallbacks.

Assisted-by: Codex / GPT-6

---
Full diff: https://github.com/llvm/llvm-project/pull/236540.diff


4 Files Affected:

- (modified) mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.td (+6-1) 
- (modified) mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp (+69) 
- (modified) mlir/unittests/Dialect/LLVMIR/CMakeLists.txt (+1) 
- (modified) mlir/unittests/Dialect/LLVMIR/LLVMTypeTest.cpp (+86) 


``````````diff
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.td
index e31323651ceda1..fb798789ab195e 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.td
@@ -330,7 +330,9 @@ def LLVMPointerType : LLVMType<"LLVMPointer", "ptr", [
 // LLVMTargetExtType
 //===----------------------------------------------------------------------===//
 
-def LLVMTargetExtType : LLVMType<"LLVMTargetExt", "target"> {
+def LLVMTargetExtType : LLVMType<"LLVMTargetExt", "target", [
+    DeclareTypeInterfaceMethods<DataLayoutTypeInterface,
+                                ["getPreferredAlignment"]>]> {
   let summary = "LLVM target-specific extension type";
   let description = [{
     LLVM dialect target extension type, which are generally unintrospectable
@@ -359,6 +361,9 @@ def LLVMTargetExtType : LLVMType<"LLVMTargetExt", "target"> {
 
     bool hasProperty(Property Prop) const;
     bool supportsMemOps() const;
+
+    /// Return the type used for layout, or void for an unsized extension type.
+    Type getLayoutType() const;
   }];
 }
 
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp
index 2d99c0e4a4931d..0d7a9c31d86502 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp
@@ -22,6 +22,7 @@
 
 #include "llvm/ADT/TypeSwitch.h"
 #include "llvm/Support/TypeSize.h"
+#include "llvm/TargetParser/RISCVTargetParser.h"
 #include <optional>
 
 using namespace mlir;
@@ -754,6 +755,74 @@ bool LLVM::LLVMTargetExtType::supportsMemOps() const {
   return false;
 }
 
+Type LLVM::LLVMTargetExtType::getLayoutType() const {
+  // Keep this mapping consistent with getTargetTypeInfo in
+  // llvm/lib/IR/Type.cpp.
+  MLIRContext *context = getContext();
+  StringRef name = getExtTypeName();
+  if (name == "spirv.Type") {
+    assert(getIntParams().size() == 3 &&
+           "wrong number of parameters for spirv.Type");
+    unsigned size = getIntParams()[1];
+    unsigned alignment = getIntParams()[2];
+    if (size && alignment)
+      return LLVMArrayType::get(IntegerType::get(context, alignment),
+                                size * 8 / alignment);
+    return IntegerType::get(context, 32);
+  }
+  if (name == "spirv.IntegralConstant" || name == "spirv.Literal" ||
+      name == "amdgpu.stridemark")
+    return LLVMVoidType::get(context);
+  if (name == "spirv.Padding" || name == "dx.Padding") {
+    assert(getIntParams().size() == 1 && "expected padding size");
+    return LLVMArrayType::get(IntegerType::get(context, 8), getIntParams()[0]);
+  }
+  if (name.starts_with(kSpirvPrefix) || name.starts_with("dx.") ||
+      name == "wasm.funcref" || name == "wasm.externref")
+    return LLVMPointerType::get(context);
+  if (name == kArmSVCount)
+    return VectorType::get({16}, IntegerType::get(context, 1), {true});
+  if (name == "riscv.vector.tuple") {
+    assert(getTypeParams().size() == 1 && getIntParams().size() == 1 &&
+           "expected tuple vector type and field count");
+    unsigned numElements =
+        std::max(getVectorNumElements(getTypeParams()[0]).getKnownMinValue(),
+                 llvm::RISCV::RVVBytesPerBlock) *
+        getIntParams()[0];
+    return VectorType::get({numElements}, IntegerType::get(context, 8), {true});
+  }
+  if (name == kAMDGCNNamedBarrier)
+    return IntegerType::get(context, 8);
+  if (name == "llvm.test.vectorelement")
+    return IntegerType::get(context, 32);
+  return LLVMVoidType::get(context);
+}
+
+llvm::TypeSize LLVM::LLVMTargetExtType::getTypeSizeInBits(
+    const DataLayout &dataLayout, DataLayoutEntryListRef params) const {
+  Type layoutType = getLayoutType();
+  // LLVM vector bit sizes do not round the element count up to a power of two,
+  // unlike the default data layout for builtin MLIR vectors.
+  if (auto vectorType = dyn_cast<VectorType>(layoutType))
+    return llvm::TypeSize::get(
+        vectorType.getNumElements() *
+            dataLayout.getTypeSizeInBits(vectorType.getElementType())
+                .getFixedValue(),
+        vectorType.isScalable());
+  return dataLayout.getTypeSizeInBits(layoutType);
+}
+
+uint64_t
+LLVM::LLVMTargetExtType::getABIAlignment(const DataLayout &dataLayout,
+                                         DataLayoutEntryListRef params) const {
+  return dataLayout.getTypeABIAlignment(getLayoutType());
+}
+
+uint64_t LLVM::LLVMTargetExtType::getPreferredAlignment(
+    const DataLayout &dataLayout, DataLayoutEntryListRef params) const {
+  return dataLayout.getTypePreferredAlignment(getLayoutType());
+}
+
 //===----------------------------------------------------------------------===//
 // LLVMPPCFP128Type
 //===----------------------------------------------------------------------===//
diff --git a/mlir/unittests/Dialect/LLVMIR/CMakeLists.txt b/mlir/unittests/Dialect/LLVMIR/CMakeLists.txt
index 0dffa51bdcf167..784a857872658c 100644
--- a/mlir/unittests/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/unittests/Dialect/LLVMIR/CMakeLists.txt
@@ -5,6 +5,7 @@ add_mlir_unittest(MLIRLLVMIRTests
 )
 mlir_target_link_libraries(MLIRLLVMIRTests
   PRIVATE
+  MLIRDLTIDialect
   MLIRFuncDialect
   MLIRLLVMDialect
   MLIRROCDLDialect
diff --git a/mlir/unittests/Dialect/LLVMIR/LLVMTypeTest.cpp b/mlir/unittests/Dialect/LLVMIR/LLVMTypeTest.cpp
index 72d8867d232aad..aa8176693f9a3e 100644
--- a/mlir/unittests/Dialect/LLVMIR/LLVMTypeTest.cpp
+++ b/mlir/unittests/Dialect/LLVMIR/LLVMTypeTest.cpp
@@ -7,7 +7,13 @@
 //===----------------------------------------------------------------------===//
 
 #include "LLVMTestBase.h"
+#include "mlir/Dialect/DLTI/DLTI.h"
 #include "mlir/Dialect/LLVMIR/LLVMTypes.h"
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/BuiltinOps.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/LLVMContext.h"
 
 using namespace mlir;
 using namespace mlir::LLVM;
@@ -60,3 +66,83 @@ TEST_F(LLVMIRTest, StructElementOffsets) {
   EXPECT_EQ(packedAlloc.getElementOffset(dataLayout, 1), 16u);
   EXPECT_EQ(dataLayout.getTypeSize(packedAlloc), 17u);
 }
+
+TEST_F(LLVMIRTest, TargetExtensionLayoutMatchesLLVM) {
+  DataLayout layout;
+  llvm::LLVMContext llvmContext;
+  llvm::DataLayout llvmLayout("");
+  auto check = [&](StringRef name, ArrayRef<Type> typeParams,
+                   ArrayRef<llvm::Type *> llvmTypeParams,
+                   ArrayRef<unsigned> intParams) {
+    SCOPED_TRACE(name.str());
+    auto type = LLVMTargetExtType::get(&context, name, typeParams, intParams);
+    auto *llvmType =
+        llvm::TargetExtType::get(llvmContext, name, llvmTypeParams, intParams);
+    llvm::TypeSize size = layout.getTypeSizeInBits(type);
+    llvm::TypeSize llvmSize = llvmLayout.getTypeSizeInBits(llvmType);
+    EXPECT_EQ(size.getKnownMinValue(), llvmSize.getKnownMinValue());
+    EXPECT_EQ(size.isScalable(), llvmSize.isScalable());
+    EXPECT_EQ(layout.getTypeABIAlignment(type),
+              llvmLayout.getABITypeAlign(llvmType).value());
+    EXPECT_EQ(layout.getTypePreferredAlignment(type),
+              llvmLayout.getPrefTypeAlign(llvmType).value());
+  };
+
+  check("spirv.Image", {Float32Type::get(&context)},
+        {llvm::Type::getFloatTy(llvmContext)}, {1, 0, 0, 0, 0, 0, 0});
+  check("spirv.SignedImage", {}, {}, {});
+  check("spirv.Sampler", {}, {}, {});
+  check("spirv.Pipe", {}, {}, {0});
+  check("spirv.Event", {}, {}, {});
+  check("dx.RawBuffer", {IntegerType::get(&context, 32)},
+        {llvm::Type::getInt32Ty(llvmContext)}, {0, 0});
+  check("wasm.funcref", {}, {}, {});
+  check("wasm.externref", {}, {}, {});
+  check("spirv.Type", {}, {}, {0, 8, 32});
+  check("spirv.Type", {}, {}, {0, 0, 0});
+  check("spirv.Padding", {}, {}, {3});
+  check("dx.Padding", {}, {}, {3});
+  check("amdgcn.named.barrier", {}, {}, {0});
+  check("llvm.test.vectorelement", {}, {}, {});
+  check("aarch64.svcount", {}, {}, {});
+  check("riscv.vector.tuple",
+        {VectorType::get({4}, IntegerType::get(&context, 64), {true})},
+        {llvm::ScalableVectorType::get(llvm::Type::getInt64Ty(llvmContext), 4)},
+        {3});
+}
+
+TEST_F(LLVMIRTest, UnsizedTargetExtensionLayout) {
+  for (StringRef name : {"spirv.IntegralConstant", "spirv.Literal",
+                         "amdgpu.stridemark", "unknown"}) {
+    SCOPED_TRACE(name.str());
+    auto type = LLVMTargetExtType::get(&context, name, {}, {});
+    EXPECT_TRUE(isa<LLVMVoidType>(type.getLayoutType()));
+  }
+}
+
+TEST_F(LLVMIRTest, TargetExtensionLayoutInAggregates) {
+  DataLayout layout;
+  auto sampler = LLVMTargetExtType::get(&context, "spirv.Sampler", {}, {});
+  auto array = LLVMArrayType::get(sampler, 3);
+  EXPECT_EQ(layout.getTypeSize(array).getFixedValue(), 24u);
+  EXPECT_EQ(layout.getTypeABIAlignment(array), 8u);
+  auto record = LLVMStructType::getLiteral(
+      &context, {IntegerType::get(&context, 8), sampler});
+  EXPECT_EQ(record.getElementOffset(layout, 1), 8u);
+  EXPECT_EQ(layout.getTypeSize(record).getFixedValue(), 16u);
+}
+
+TEST_F(LLVMIRTest, TargetExtensionCustomPointerLayout) {
+  context.getOrLoadDialect<DLTIDialect>();
+  Builder builder(&context);
+  OwningOpRef<ModuleOp> module = ModuleOp::create(builder.getUnknownLoc());
+  auto pointerEntry = DataLayoutEntryAttr::get(
+      LLVMPointerType::get(&context), builder.getI64VectorAttr({32, 32, 64}));
+  (*module)->setAttr(DLTIDialect::kDataLayoutAttrName,
+                     DataLayoutSpecAttr::get(&context, {pointerEntry}));
+  DataLayout layout(module.get());
+  auto sampler = LLVMTargetExtType::get(&context, "spirv.Sampler", {}, {});
+  EXPECT_EQ(layout.getTypeSizeInBits(sampler).getFixedValue(), 32u);
+  EXPECT_EQ(layout.getTypeABIAlignment(sampler), 4u);
+  EXPECT_EQ(layout.getTypePreferredAlignment(sampler), 8u);
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/236540


More information about the Mlir-commits mailing list