[Mlir-commits] [mlir] [mlir][SPIRV] Lower ptr dialect to PBA addresses (PR #206159)
Eddy Shieh
llvmlistbot at llvm.org
Sun Jun 28 15:43:56 PDT 2026
https://github.com/edmundshieh updated https://github.com/llvm/llvm-project/pull/206159
>From 802af4c1b884b5a16e137c6d91f7e5823fb41e29 Mon Sep 17 00:00:00 2001
From: eshieh <eshieh at nvidia.com>
Date: Fri, 26 Jun 2026 14:25:17 -0400
Subject: [PATCH] [SPIRV] Lower ptr dialect to PBA addresses
Add a Ptr-to-SPIR-V conversion that represents ptr values as 64-bit
PhysicalStorageBuffer addresses. The conversion materializes typed
SPIR-V pointers at memory access sites so the ptr dialect can remain
pointee-type agnostic until loads and stores.
This covers the standalone conversion path. Vulkan runner ABI
integration is left for a follow-up because it depends on separate
runtime support for raw physical storage buffer arguments.
Tests:
- ninja -C build-pba mlir-opt
- llvm-lit -v mlir/test/Conversion/PtrToSPIRV/ptr-to-spirv.mlir
Assisted-by: OpenAI Codex
---
mlir/include/mlir/Conversion/Passes.h | 1 +
mlir/include/mlir/Conversion/Passes.td | 23 ++
.../mlir/Conversion/PtrToSPIRV/PtrToSPIRV.h | 37 +++
mlir/lib/Conversion/CMakeLists.txt | 1 +
mlir/lib/Conversion/PtrToSPIRV/CMakeLists.txt | 17 +
mlir/lib/Conversion/PtrToSPIRV/PtrToSPIRV.cpp | 297 ++++++++++++++++++
.../Conversion/PtrToSPIRV/ptr-to-spirv.mlir | 43 +++
7 files changed, 419 insertions(+)
create mode 100644 mlir/include/mlir/Conversion/PtrToSPIRV/PtrToSPIRV.h
create mode 100644 mlir/lib/Conversion/PtrToSPIRV/CMakeLists.txt
create mode 100644 mlir/lib/Conversion/PtrToSPIRV/PtrToSPIRV.cpp
create mode 100644 mlir/test/Conversion/PtrToSPIRV/ptr-to-spirv.mlir
diff --git a/mlir/include/mlir/Conversion/Passes.h b/mlir/include/mlir/Conversion/Passes.h
index 0ea248df3fee4..1394e03bc4f45 100644
--- a/mlir/include/mlir/Conversion/Passes.h
+++ b/mlir/include/mlir/Conversion/Passes.h
@@ -61,6 +61,7 @@
#include "mlir/Conversion/OpenACCToSCF/ConvertOpenACCToSCF.h"
#include "mlir/Conversion/OpenMPToLLVM/ConvertOpenMPToLLVM.h"
#include "mlir/Conversion/PDLToPDLInterp/PDLToPDLInterp.h"
+#include "mlir/Conversion/PtrToSPIRV/PtrToSPIRV.h"
#include "mlir/Conversion/RaiseWasm/RaiseWasmMLIR.h"
#include "mlir/Conversion/ReconcileUnrealizedCasts/ReconcileUnrealizedCasts.h"
#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h"
diff --git a/mlir/include/mlir/Conversion/Passes.td b/mlir/include/mlir/Conversion/Passes.td
index 340ff8fdf2a8a..9cc8765dce934 100644
--- a/mlir/include/mlir/Conversion/Passes.td
+++ b/mlir/include/mlir/Conversion/Passes.td
@@ -1134,6 +1134,29 @@ def ConvertPDLToPDLInterpPass : Pass<"convert-pdl-to-pdl-interp", "ModuleOp"> {
let dependentDialects = ["pdl_interp::PDLInterpDialect"];
}
+//===----------------------------------------------------------------------===//
+// PtrToSPIRV
+//===----------------------------------------------------------------------===//
+
+def ConvertPtrToSPIRVPass : Pass<"convert-ptr-to-spirv"> {
+ let summary = "Convert Ptr dialect operations to SPIR-V dialect operations";
+ let description = [{
+ This pass lowers supported Ptr dialect operations to SPIR-V operations.
+ Ptr dialect pointer types are converted to address integer types. Memory
+ operations materialize SPIR-V pointer types in the selected storage class.
+ The default storage class is PhysicalStorageBuffer, which enables physical
+ buffer address style pointer arithmetic.
+ }];
+
+ let dependentDialects = ["ptr::PtrDialect", "spirv::SPIRVDialect"];
+
+ let options = [
+ Option<"storageClass", "storage-class", "std::string",
+ /*default=*/"\"PhysicalStorageBuffer\"",
+ "SPIR-V storage class to use for materialized pointer accesses">
+ ];
+}
+
//===----------------------------------------------------------------------===//
// ReconcileUnrealizedCasts
//===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/Conversion/PtrToSPIRV/PtrToSPIRV.h b/mlir/include/mlir/Conversion/PtrToSPIRV/PtrToSPIRV.h
new file mode 100644
index 0000000000000..2e7463b6061d5
--- /dev/null
+++ b/mlir/include/mlir/Conversion/PtrToSPIRV/PtrToSPIRV.h
@@ -0,0 +1,37 @@
+//===- PtrToSPIRV.h - Convert Ptr to SPIR-V dialect ------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_CONVERSION_PTRTOSPIRV_PTRTOSPIRV_H
+#define MLIR_CONVERSION_PTRTOSPIRV_PTRTOSPIRV_H
+
+#include "mlir/Dialect/SPIRV/IR/SPIRVEnums.h"
+#include "mlir/Pass/Pass.h"
+#include <memory>
+
+namespace mlir {
+class RewritePatternSet;
+class SPIRVTypeConverter;
+
+#define GEN_PASS_DECL_CONVERTPTRTOSPIRVPASS
+#include "mlir/Conversion/Passes.h.inc"
+
+namespace ptr {
+/// Populates the type converter with conversions for ptr dialect types.
+void populatePtrToSPIRVTypeConversions(SPIRVTypeConverter &typeConverter);
+
+/// Appends patterns for lowering ptr dialect operations to SPIR-V operations.
+void populatePtrToSPIRVPatterns(const SPIRVTypeConverter &typeConverter,
+ RewritePatternSet &patterns,
+ spirv::StorageClass storageClass =
+ spirv::StorageClass::PhysicalStorageBuffer);
+
+std::unique_ptr<OperationPass<>> createConvertPtrToSPIRVPass();
+} // namespace ptr
+} // namespace mlir
+
+#endif // MLIR_CONVERSION_PTRTOSPIRV_PTRTOSPIRV_H
diff --git a/mlir/lib/Conversion/CMakeLists.txt b/mlir/lib/Conversion/CMakeLists.txt
index 4fa5b9d582a4e..30cef4eabd086 100644
--- a/mlir/lib/Conversion/CMakeLists.txt
+++ b/mlir/lib/Conversion/CMakeLists.txt
@@ -55,6 +55,7 @@ add_subdirectory(OpenACCToSCF)
add_subdirectory(OpenMPToLLVM)
add_subdirectory(PDLToPDLInterp)
add_subdirectory(PtrToLLVM)
+add_subdirectory(PtrToSPIRV)
add_subdirectory(RaiseWasm)
add_subdirectory(ReconcileUnrealizedCasts)
add_subdirectory(SCFToControlFlow)
diff --git a/mlir/lib/Conversion/PtrToSPIRV/CMakeLists.txt b/mlir/lib/Conversion/PtrToSPIRV/CMakeLists.txt
new file mode 100644
index 0000000000000..29c6045401d4b
--- /dev/null
+++ b/mlir/lib/Conversion/PtrToSPIRV/CMakeLists.txt
@@ -0,0 +1,17 @@
+add_mlir_conversion_library(MLIRPtrToSPIRV
+ PtrToSPIRV.cpp
+
+ ADDITIONAL_HEADER_DIRS
+ ${MLIR_MAIN_INCLUDE_DIR}/mlir/Conversion/PtrToSPIRV
+
+ DEPENDS
+ MLIRConversionPassIncGen
+
+ LINK_COMPONENTS
+ Core
+
+ LINK_LIBS PUBLIC
+ MLIRPtrDialect
+ MLIRSPIRVConversion
+ MLIRSPIRVDialect
+ )
diff --git a/mlir/lib/Conversion/PtrToSPIRV/PtrToSPIRV.cpp b/mlir/lib/Conversion/PtrToSPIRV/PtrToSPIRV.cpp
new file mode 100644
index 0000000000000..813bc6fb1a13e
--- /dev/null
+++ b/mlir/lib/Conversion/PtrToSPIRV/PtrToSPIRV.cpp
@@ -0,0 +1,297 @@
+//===- PtrToSPIRV.cpp - Ptr to SPIR-V dialect conversion -----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Conversion/PtrToSPIRV/PtrToSPIRV.h"
+
+#include "mlir/Dialect/Ptr/IR/PtrOps.h"
+#include "mlir/Dialect/Ptr/IR/PtrTypes.h"
+#include "mlir/Dialect/SPIRV/IR/SPIRVAttributes.h"
+#include "mlir/Dialect/SPIRV/IR/SPIRVDialect.h"
+#include "mlir/Dialect/SPIRV/IR/SPIRVOps.h"
+#include "mlir/Dialect/SPIRV/Transforms/SPIRVConversion.h"
+#include "mlir/Transforms/DialectConversion.h"
+#include "llvm/ADT/StringRef.h"
+#include <limits>
+
+namespace mlir {
+#define GEN_PASS_DEF_CONVERTPTRTOSPIRVPASS
+#include "mlir/Conversion/Passes.h.inc"
+} // namespace mlir
+
+using namespace mlir;
+
+namespace {
+
+static FailureOr<Type> getAddressType(spirv::TargetEnvAttr targetAttr,
+ MLIRContext *context) {
+ spirv::AddressingModel addressingModel =
+ spirv::getAddressingModel(targetAttr, /*use64bitAddress=*/true);
+ if (addressingModel == spirv::AddressingModel::PhysicalStorageBuffer64)
+ return IntegerType::get(context, 64);
+
+ return failure();
+}
+
+static LogicalResult getMemoryAccessAttrs(std::optional<int64_t> alignment,
+ Builder &builder,
+ spirv::MemoryAccessAttr &accessAttr,
+ IntegerAttr &alignmentAttr) {
+ if (!alignment)
+ return success();
+ if (*alignment > std::numeric_limits<uint32_t>::max())
+ return failure();
+
+ accessAttr = spirv::MemoryAccessAttr::get(builder.getContext(),
+ spirv::MemoryAccess::Aligned);
+ alignmentAttr = builder.getI32IntegerAttr(*alignment);
+ return success();
+}
+
+static LogicalResult checkSupportedPtrLoad(ptr::LoadOp op,
+ PatternRewriter &rewriter) {
+ if (op.getVolatile_() || op.getNontemporal() || op.getInvariant() ||
+ op.getInvariantGroup())
+ return rewriter.notifyMatchFailure(
+ op, "unsupported ptr.load memory operand for SPIR-V lowering");
+ if (op.getOrdering() != ptr::AtomicOrdering::not_atomic)
+ return rewriter.notifyMatchFailure(
+ op, "unsupported atomic ptr.load for SPIR-V lowering");
+ return success();
+}
+
+static LogicalResult checkSupportedPtrStore(ptr::StoreOp op,
+ PatternRewriter &rewriter) {
+ if (op.getVolatile_() || op.getNontemporal() || op.getInvariantGroup())
+ return rewriter.notifyMatchFailure(
+ op, "unsupported ptr.store memory operand for SPIR-V lowering");
+ if (op.getOrdering() != ptr::AtomicOrdering::not_atomic)
+ return rewriter.notifyMatchFailure(
+ op, "unsupported atomic ptr.store for SPIR-V lowering");
+ return success();
+}
+
+static FailureOr<Value>
+castAddressToPointeeType(Operation *op, Value address, Type pointeeType,
+ spirv::StorageClass storageClass, Location loc,
+ PatternRewriter &rewriter) {
+ if (!isa<IntegerType>(address.getType())) {
+ (void)rewriter.notifyMatchFailure(op, "expected integer address operand");
+ return failure();
+ }
+ if (storageClass != spirv::StorageClass::PhysicalStorageBuffer) {
+ (void)rewriter.notifyMatchFailure(
+ op, "only PhysicalStorageBuffer pointer materialization is supported");
+ return failure();
+ }
+
+ auto typedPtrType = spirv::PointerType::get(pointeeType, storageClass);
+ return spirv::ConvertUToPtrOp::create(rewriter, loc, typedPtrType, address)
+ .getResult();
+}
+
+struct PtrTypeOffsetOpConverter final
+ : public OpConversionPattern<ptr::TypeOffsetOp> {
+ using Base::Base;
+
+ LogicalResult
+ matchAndRewrite(ptr::TypeOffsetOp op, OpAdaptor adaptor,
+ ConversionPatternRewriter &rewriter) const override {
+ Type convertedType = getTypeConverter()->convertType(op.getType());
+ if (!convertedType)
+ return rewriter.notifyMatchFailure(op, "result type is not convertible");
+
+ llvm::TypeSize typeSize = op.getTypeSize();
+ if (typeSize.isScalable())
+ return rewriter.notifyMatchFailure(op, "scalable type size");
+
+ auto intType = dyn_cast<IntegerType>(convertedType);
+ if (!intType)
+ return rewriter.notifyMatchFailure(
+ op, "converted result type is not an integer");
+
+ auto attr = rewriter.getIntegerAttr(intType, typeSize.getFixedValue());
+ rewriter.replaceOpWithNewOp<spirv::ConstantOp>(op, intType, attr);
+ return success();
+ }
+};
+
+struct PtrAddOpConverter final : public OpConversionPattern<ptr::PtrAddOp> {
+ using Base::Base;
+
+ LogicalResult
+ matchAndRewrite(ptr::PtrAddOp op, OpAdaptor adaptor,
+ ConversionPatternRewriter &rewriter) const override {
+ Type convertedType = getTypeConverter()->convertType(op.getType());
+ if (!convertedType)
+ return rewriter.notifyMatchFailure(op, "result type is not convertible");
+
+ auto addressType = dyn_cast<IntegerType>(convertedType);
+ if (!addressType)
+ return rewriter.notifyMatchFailure(
+ op, "converted result type is not an integer address");
+ if (adaptor.getBase().getType() != addressType)
+ return rewriter.notifyMatchFailure(
+ op, "converted base pointer type does not match result type");
+
+ Location loc = op.getLoc();
+ Value offset = adaptor.getOffset();
+ if (!isa<IntegerType>(offset.getType()))
+ return rewriter.notifyMatchFailure(op, "offset is not an integer");
+ if (offset.getType() != addressType)
+ offset = spirv::UConvertOp::create(rewriter, loc, addressType, offset);
+
+ rewriter.replaceOpWithNewOp<spirv::IAddOp>(op, addressType,
+ adaptor.getBase(), offset);
+ return success();
+ }
+};
+
+struct PtrLoadOpConverter final : public OpConversionPattern<ptr::LoadOp> {
+ PtrLoadOpConverter(const SPIRVTypeConverter &typeConverter,
+ MLIRContext *context, spirv::StorageClass storageClass)
+ : OpConversionPattern<ptr::LoadOp>(typeConverter, context),
+ storageClass(storageClass) {}
+
+ LogicalResult
+ matchAndRewrite(ptr::LoadOp op, OpAdaptor adaptor,
+ ConversionPatternRewriter &rewriter) const override {
+ if (failed(checkSupportedPtrLoad(op, rewriter)))
+ return failure();
+
+ Type convertedType = getTypeConverter()->convertType(op.getType());
+ if (!convertedType)
+ return rewriter.notifyMatchFailure(op, "result type is not convertible");
+
+ FailureOr<Value> ptr =
+ castAddressToPointeeType(op, adaptor.getPtr(), convertedType,
+ storageClass, op.getLoc(), rewriter);
+ if (failed(ptr))
+ return failure();
+
+ spirv::MemoryAccessAttr accessAttr;
+ IntegerAttr alignmentAttr;
+ if (failed(getMemoryAccessAttrs(op.getAlignment(), rewriter, accessAttr,
+ alignmentAttr)))
+ return rewriter.notifyMatchFailure(op, "invalid alignment requirement");
+
+ rewriter.replaceOpWithNewOp<spirv::LoadOp>(op, convertedType, *ptr,
+ accessAttr, alignmentAttr);
+ return success();
+ }
+
+private:
+ spirv::StorageClass storageClass;
+};
+
+struct PtrStoreOpConverter final : public OpConversionPattern<ptr::StoreOp> {
+ PtrStoreOpConverter(const SPIRVTypeConverter &typeConverter,
+ MLIRContext *context, spirv::StorageClass storageClass)
+ : OpConversionPattern<ptr::StoreOp>(typeConverter, context),
+ storageClass(storageClass) {}
+
+ LogicalResult
+ matchAndRewrite(ptr::StoreOp op, OpAdaptor adaptor,
+ ConversionPatternRewriter &rewriter) const override {
+ if (failed(checkSupportedPtrStore(op, rewriter)))
+ return failure();
+
+ Type valueType = adaptor.getValue().getType();
+ FailureOr<Value> ptr = castAddressToPointeeType(
+ op, adaptor.getPtr(), valueType, storageClass, op.getLoc(), rewriter);
+ if (failed(ptr))
+ return failure();
+
+ spirv::MemoryAccessAttr accessAttr;
+ IntegerAttr alignmentAttr;
+ if (failed(getMemoryAccessAttrs(op.getAlignment(), rewriter, accessAttr,
+ alignmentAttr)))
+ return rewriter.notifyMatchFailure(op, "invalid alignment requirement");
+
+ rewriter.replaceOpWithNewOp<spirv::StoreOp>(op, *ptr, adaptor.getValue(),
+ accessAttr, alignmentAttr);
+ return success();
+ }
+
+private:
+ spirv::StorageClass storageClass;
+};
+
+static FailureOr<spirv::StorageClass> parseStorageClass(StringRef storageClass,
+ Operation *op) {
+ std::optional<spirv::StorageClass> parsed =
+ spirv::symbolizeStorageClass(storageClass);
+ if (!parsed)
+ return op->emitError() << "invalid SPIR-V storage class: " << storageClass;
+ return *parsed;
+}
+
+struct ConvertPtrToSPIRVPass final
+ : public impl::ConvertPtrToSPIRVPassBase<ConvertPtrToSPIRVPass> {
+ using Base::Base;
+
+ void runOnOperation() override {
+ Operation *op = getOperation();
+ spirv::TargetEnvAttr targetAttr = spirv::lookupTargetEnvOrDefault(op);
+ std::unique_ptr<SPIRVConversionTarget> target =
+ SPIRVConversionTarget::get(targetAttr);
+ SPIRVTypeConverter typeConverter(targetAttr);
+
+ FailureOr<spirv::StorageClass> storageClass =
+ parseStorageClass(this->storageClass, op);
+ if (failed(storageClass))
+ return signalPassFailure();
+ if (*storageClass != spirv::StorageClass::PhysicalStorageBuffer) {
+ op->emitError()
+ << "ptr-to-SPIR-V currently only supports PhysicalStorageBuffer";
+ return signalPassFailure();
+ }
+ if (failed(getAddressType(targetAttr, op->getContext()))) {
+ op->emitError()
+ << "ptr-to-SPIR-V requires PhysicalStorageBuffer64 addressing";
+ return signalPassFailure();
+ }
+
+ ptr::populatePtrToSPIRVTypeConversions(typeConverter);
+
+ target->addLegalOp<UnrealizedConversionCastOp>();
+ target->addIllegalDialect<ptr::PtrDialect>();
+
+ RewritePatternSet patterns(&getContext());
+ ptr::populatePtrToSPIRVPatterns(typeConverter, patterns, *storageClass);
+
+ if (failed(applyPartialConversion(op, *target, std::move(patterns))))
+ signalPassFailure();
+ }
+};
+
+} // namespace
+
+void mlir::ptr::populatePtrToSPIRVTypeConversions(
+ SPIRVTypeConverter &typeConverter) {
+ spirv::TargetEnvAttr targetAttr = typeConverter.getTargetEnv().getAttr();
+ typeConverter.addConversion([targetAttr](
+ ptr::PtrType type) -> std::optional<Type> {
+ FailureOr<Type> addressType = getAddressType(targetAttr, type.getContext());
+ if (failed(addressType))
+ return std::nullopt;
+ return *addressType;
+ });
+}
+
+void mlir::ptr::populatePtrToSPIRVPatterns(
+ const SPIRVTypeConverter &typeConverter, RewritePatternSet &patterns,
+ spirv::StorageClass storageClass) {
+ patterns.add<PtrAddOpConverter, PtrTypeOffsetOpConverter>(
+ typeConverter, patterns.getContext());
+ patterns.add<PtrLoadOpConverter, PtrStoreOpConverter>(
+ typeConverter, patterns.getContext(), storageClass);
+}
+
+std::unique_ptr<OperationPass<>> mlir::ptr::createConvertPtrToSPIRVPass() {
+ return std::make_unique<ConvertPtrToSPIRVPass>();
+}
diff --git a/mlir/test/Conversion/PtrToSPIRV/ptr-to-spirv.mlir b/mlir/test/Conversion/PtrToSPIRV/ptr-to-spirv.mlir
new file mode 100644
index 0000000000000..6863577ce7264
--- /dev/null
+++ b/mlir/test/Conversion/PtrToSPIRV/ptr-to-spirv.mlir
@@ -0,0 +1,43 @@
+// RUN: mlir-opt %s -split-input-file -convert-ptr-to-spirv | FileCheck %s
+
+!ptr = !ptr.ptr<#ptr.generic_space>
+
+module attributes {
+ spirv.target_env = #spirv.target_env<
+ #spirv.vce<v1.5, [Shader, Int64, PhysicalStorageBufferAddresses],
+ [SPV_KHR_physical_storage_buffer]>,
+ #spirv.resource_limits<>>
+} {
+
+// CHECK-LABEL: func.func @ptr_add_load_store
+// CHECK-SAME: %[[PTR:.*]]: !ptr.ptr<#ptr.generic_space>
+// CHECK-SAME: %[[OFFSET:.*]]: index
+// CHECK-SAME: %[[VALUE:.*]]: f32
+func.func @ptr_add_load_store(%ptr: !ptr, %offset: index, %value: f32) -> f32 {
+ // CHECK-DAG: %[[ADDR:.*]] = builtin.unrealized_conversion_cast %[[PTR]] : !ptr.ptr<#ptr.generic_space> to i64
+ // CHECK-DAG: %[[SPIRV_OFFSET:.*]] = builtin.unrealized_conversion_cast %[[OFFSET]] : index to i32
+ // CHECK: %[[OFFSET64:.*]] = spirv.UConvert %[[SPIRV_OFFSET]] : i32 to i64
+ // CHECK: %[[ELEM_ADDR:.*]] = spirv.IAdd %[[ADDR]], %[[OFFSET64]] : i64
+ %elem = ptr.ptr_add %ptr, %offset : !ptr, index
+
+ // CHECK: %[[LOAD_PTR:.*]] = spirv.ConvertUToPtr %[[ELEM_ADDR]] : i64 to !spirv.ptr<f32, PhysicalStorageBuffer>
+ // CHECK: %[[LOADED:.*]] = spirv.Load "PhysicalStorageBuffer" %[[LOAD_PTR]] ["Aligned", 4] : f32
+ %loaded = ptr.load %elem alignment = 4 : !ptr -> f32
+
+ // CHECK: %[[STORE_PTR:.*]] = spirv.ConvertUToPtr %[[ELEM_ADDR]] : i64 to !spirv.ptr<f32, PhysicalStorageBuffer>
+ // CHECK: spirv.Store "PhysicalStorageBuffer" %[[STORE_PTR]], %[[VALUE]] ["Aligned", 4] : f32
+ ptr.store %value, %elem alignment = 4 : f32, !ptr
+
+ // CHECK: return %[[LOADED]] : f32
+ return %loaded : f32
+}
+
+// CHECK-LABEL: func.func @type_offset
+func.func @type_offset() -> index {
+ // CHECK: %[[SIZE:.*]] = spirv.Constant 4 : i32
+ %size = ptr.type_offset f32 : index
+ // CHECK: builtin.unrealized_conversion_cast %[[SIZE]] : i32 to index
+ return %size : index
+}
+
+} // module
More information about the Mlir-commits
mailing list