Fabian Mora 8a820f133a
[mlir][LLVM|ptr] Add the #llvm.address_space attribute, and allow ptr translation (#156333)
This commit introduces the `#llvm.address_space` attribute. This
attribute implements the `ptr::MemorySpaceAttrInterface`, establishing
the semantics of the LLVM address space.
This allows making `!ptr.ptr` translatable to LLVM IR as long it uses
the `#llvm.address_space` attribute.
Concretely, `!ptr.ptr<#llvm.address_space<N>>` now translates to `ptr
addrspace(N)`.

Additionally, this patch makes `PtrLikeTypes` with no metadata, no
element type, and with `#llvm.address_space` memory space, compatible
with the LLVM dialect.

**Infrastructure Updates:**
- Refactor `ptr::MemorySpaceAttrInterface` to include DataLayout
parameter for better validation
- Add new utility functions `LLVM::isLoadableType()` and
`LLVM::isTypeCompatibleWithAtomicOp()`
- Update type compatibility checks to support ptr-like types with LLVM
address spaces
- Splice the `MemorySpaceAttrInterface` to its own library, so the
LLVMDialect won't depend on the PtrDialect yet

**Translation Support:**
- New `PtrToLLVMIRTranslation` module for converting ptr dialect to LLVM
IR
- Type translation support for ptr types with LLVM address spaces
- Proper address space preservation during IR lowering

Example:
```mlir
llvm.func @llvm_ops_with_ptr_values(%arg0: !llvm.ptr) {
  %1 = llvm.load %arg0 : !llvm.ptr -> !ptr.ptr<#llvm.address_space<1>>
  llvm.store %1, %arg0 : !ptr.ptr<#llvm.address_space<1>>, !llvm.ptr
  llvm.return
}
```
Translates to:
```llvmir
; ModuleID = 'LLVMDialectModule'
source_filename = "LLVMDialectModule"

define void @llvm_ops_with_ptr_values(ptr %0) {
  %2 = load ptr addrspace(1), ptr %0, align 8
  store ptr addrspace(1) %2, ptr %0, align 8
  ret void
}

!llvm.module.flags = !{!0}

!0 = !{i32 2, !"Debug Info Version", i32 3}
```
2025-09-02 12:02:14 +00:00

10 lines
439 B
MLIR

// RUN: mlir-opt %s --verify-roundtrip
// Check that LLVM ops accept ptr values.
llvm.func @llvm_ops_with_ptr_values(%arg0: !llvm.ptr, %arg1: !llvm.struct<(!ptr.ptr<#llvm.address_space<3>>)>) {
%1 = llvm.load %arg0 : !llvm.ptr -> !ptr.ptr<#llvm.address_space<1>>
llvm.store %1, %arg0 : !ptr.ptr<#llvm.address_space<1>>, !llvm.ptr
llvm.store %arg1, %arg0 : !llvm.struct<(!ptr.ptr<#llvm.address_space<3>>)>, !llvm.ptr
llvm.return
}