[Mlir-commits] [mlir] [mlir] Ptr dialect (PR #73057)
Fabian Mora
llvmlistbot at llvm.org
Tue Nov 21 16:38:49 PST 2023
https://github.com/fabianmcg created https://github.com/llvm/llvm-project/pull/73057
This patch introduces the Ptr dialect, a dialect to model pointer operations motivated by the goal of modularizing the LLVM dialect.
More specifically, this patch introduces:
- The pointer dialect and type.
- The `MemorySpaceAttrInterface` interface, an interface to conceptualize memory models, giving proper semantical meaning to the Ptr dialect ops.
- The `ptr::LoadOp` operation, an operation to load data from memory, with the semantics defined by `MemorySpaceAttrInterface` and translatable to LLVM IR.
- The `SharedDialectTypeInterface` interface, an interface to delegate printing and parsing to a different dialect.
- The introduction of `LLVM::AddressSpaceAttr`, an attribute to model LLVM memory semantics.
- The replacement of `LLVMPointerType` with `ptr::PtrType`.
>From 553c32785cd9175714469b6c098784c4ccba0394 Mon Sep 17 00:00:00 2001
From: Fabian Mora <fmora.dev at gmail.com>
Date: Wed, 22 Nov 2023 00:27:44 +0000
Subject: [PATCH] [mlir] Ptr dialect
This patch introduces the Ptr dialect, a dialect to model pointer operations
motivated by the goal of modularizing the LLVM dialect.
More specifically, this patch introduces:
- The pointer dialect and type.
- The `MemorySpaceAttrInterface` interface, an interface to conceptualize memory models, giving proper semantical meaning to the Ptr dialect ops.
- The `ptr::LoadOp` operation, an operation to load data from memory, with the semantics defined by `MemorySpaceAttrInterface` and translatable to LLVM IR.
- The `SharedDialectTypeInterface` interface, an interface to delegate printing and parsing to a different dialect.
- The introduction of `LLVM::AddressSpaceAttr`, an attribute to model LLVM memory semantics.
- The replacement of `LLVMPointerType` with `ptr::PtrType`.
---
mlir/include/mlir/Dialect/CMakeLists.txt | 1 +
.../mlir/Dialect/LLVMIR/LLVMAttrDefs.td | 15 +
mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h | 1 +
.../mlir/Dialect/LLVMIR/LLVMDialect.td | 3 +
mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.h | 31 ++
mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.td | 33 --
mlir/include/mlir/Dialect/Ptr/CMakeLists.txt | 1 +
.../mlir/Dialect/Ptr/IR/CMakeLists.txt | 17 +
.../Dialect/Ptr/IR/MemorySpaceInterfaces.h | 20 ++
.../Dialect/Ptr/IR/MemorySpaceInterfaces.td | 63 ++++
mlir/include/mlir/Dialect/Ptr/IR/PtrDialect.h | 20 ++
.../include/mlir/Dialect/Ptr/IR/PtrDialect.td | 84 +++++
mlir/include/mlir/Dialect/Ptr/IR/PtrEnums.td | 62 ++++
mlir/include/mlir/Dialect/Ptr/IR/PtrOps.h | 32 ++
mlir/include/mlir/Dialect/Ptr/IR/PtrOps.td | 68 ++++
mlir/include/mlir/Dialect/Ptr/IR/PtrTypes.h | 37 +++
mlir/include/mlir/IR/BuiltinTypeInterfaces.td | 25 ++
mlir/include/mlir/InitAllDialects.h | 2 +
mlir/include/mlir/Target/LLVMIR/Dialect/All.h | 3 +
.../Dialect/Ptr/PtrToLLVMIRTranslation.h | 31 ++
mlir/lib/Dialect/CMakeLists.txt | 1 +
mlir/lib/Dialect/LLVMIR/CMakeLists.txt | 2 +
mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp | 14 +
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp | 1 +
mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp | 146 ++-------
mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp | 5 +-
mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp | 5 +-
mlir/lib/Dialect/Ptr/CMakeLists.txt | 1 +
mlir/lib/Dialect/Ptr/IR/CMakeLists.txt | 15 +
mlir/lib/Dialect/Ptr/IR/PtrDialect.cpp | 294 ++++++++++++++++++
mlir/lib/IR/AsmPrinter.cpp | 5 +-
mlir/lib/Target/LLVMIR/CMakeLists.txt | 1 +
mlir/lib/Target/LLVMIR/Dialect/CMakeLists.txt | 1 +
.../Target/LLVMIR/Dialect/Ptr/CMakeLists.txt | 12 +
.../Dialect/Ptr/PtrToLLVMIRTranslation.cpp | 84 +++++
mlir/lib/Target/LLVMIR/TypeToLLVM.cpp | 8 +-
36 files changed, 985 insertions(+), 159 deletions(-)
create mode 100644 mlir/include/mlir/Dialect/Ptr/CMakeLists.txt
create mode 100644 mlir/include/mlir/Dialect/Ptr/IR/CMakeLists.txt
create mode 100644 mlir/include/mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h
create mode 100644 mlir/include/mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td
create mode 100644 mlir/include/mlir/Dialect/Ptr/IR/PtrDialect.h
create mode 100644 mlir/include/mlir/Dialect/Ptr/IR/PtrDialect.td
create mode 100644 mlir/include/mlir/Dialect/Ptr/IR/PtrEnums.td
create mode 100644 mlir/include/mlir/Dialect/Ptr/IR/PtrOps.h
create mode 100644 mlir/include/mlir/Dialect/Ptr/IR/PtrOps.td
create mode 100644 mlir/include/mlir/Dialect/Ptr/IR/PtrTypes.h
create mode 100644 mlir/include/mlir/Target/LLVMIR/Dialect/Ptr/PtrToLLVMIRTranslation.h
create mode 100644 mlir/lib/Dialect/Ptr/CMakeLists.txt
create mode 100644 mlir/lib/Dialect/Ptr/IR/CMakeLists.txt
create mode 100644 mlir/lib/Dialect/Ptr/IR/PtrDialect.cpp
create mode 100644 mlir/lib/Target/LLVMIR/Dialect/Ptr/CMakeLists.txt
create mode 100644 mlir/lib/Target/LLVMIR/Dialect/Ptr/PtrToLLVMIRTranslation.cpp
diff --git a/mlir/include/mlir/Dialect/CMakeLists.txt b/mlir/include/mlir/Dialect/CMakeLists.txt
index 1c4569ecfa58485..e01fc806d039d79 100644
--- a/mlir/include/mlir/Dialect/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/CMakeLists.txt
@@ -27,6 +27,7 @@ add_subdirectory(OpenACCMPCommon)
add_subdirectory(OpenMP)
add_subdirectory(PDL)
add_subdirectory(PDLInterp)
+add_subdirectory(Ptr)
add_subdirectory(Quant)
add_subdirectory(SCF)
add_subdirectory(Shape)
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index 9e35bf1ba977725..d0eb8474492da33 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -11,6 +11,7 @@
include "mlir/Dialect/LLVMIR/LLVMDialect.td"
include "mlir/IR/AttrTypeBase.td"
+include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td"
// All of the attributes will extend this class.
class LLVM_Attr<string name, string attrMnemonic,
@@ -47,6 +48,20 @@ def LinkageAttr : LLVM_Attr<"Linkage", "linkage"> {
let assemblyFormat = "`<` $linkage `>`";
}
+//===----------------------------------------------------------------------===//
+// AddressSpaceAttr
+//===----------------------------------------------------------------------===//
+
+def AddressSpaceAttr : LLVM_Attr<"AddressSpace", "address_space", [
+ DeclareAttrInterfaceMethods<MemorySpaceAttrInterface, [
+ "getModelOwner",
+ "getDefaultMemorySpace",
+ "isValidLoad"]>
+ ]> {
+ let parameters = (ins DefaultValuedParameter<"unsigned", "0">:$addressSpace);
+ let assemblyFormat = "(`<` $addressSpace^ `>`)?";
+}
+
//===----------------------------------------------------------------------===//
// Loop Attributes
//===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
index c370bfa2b733d65..bbc5898266c4980 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
@@ -15,6 +15,7 @@
#define MLIR_DIALECT_LLVMIR_LLVMATTRS_H_
#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
#include "mlir/IR/OpImplementation.h"
#include <optional>
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
index c4c011f30b3bcd9..a706f5f115bceab 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
@@ -96,6 +96,9 @@ def LLVM_Dialect : Dialect {
/// Register the attributes of this dialect.
void registerAttributes();
}];
+ let dependentDialects = [
+ "ptr::PtrDialect"
+ ];
}
#endif // LLVMIR_DIALECT
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.h
index ba2f14f173aa0c3..37892d6225c5ff2 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.h
@@ -14,6 +14,7 @@
#ifndef MLIR_DIALECT_LLVMIR_LLVMTYPES_H_
#define MLIR_DIALECT_LLVMIR_LLVMTYPES_H_
+#include "mlir/Dialect/Ptr/IR/PtrTypes.h"
#include "mlir/IR/Types.h"
#include "mlir/Interfaces/DataLayoutInterfaces.h"
#include "mlir/Interfaces/MemorySlotInterfaces.h"
@@ -291,7 +292,37 @@ enum class PtrDLEntryPos { Size = 0, Abi = 1, Preferred = 2, Index = 3 };
std::optional<unsigned> extractPointerSpecValue(Attribute attr,
PtrDLEntryPos pos);
+/// Returns whether a pointer type has an LLVM address space.
+bool isLLVMPointerType(Type type);
+
+/// Utility class for creating pointer types of the form
+/// `ptr.ptr<#llvm.address_space<#int_attr>>`
+class LLVMPointerType : public ptr::PtrType {
+public:
+ LLVMPointerType() : ptr::PtrType() {}
+ LLVMPointerType(const ptr::PtrType &ty) : ptr::PtrType(ty) {}
+ template <typename T>
+ static bool classof(T val) {
+ static_assert(std::is_convertible<Type, T>::value,
+ "casting from a non-convertible type");
+ return isLLVMPointerType(val);
+ }
+ static PtrType get(::mlir::MLIRContext *context, unsigned addressSpace = 0);
+ static ::mlir::Type parse(::mlir::AsmParser &odsParser);
+ void print(::mlir::AsmPrinter &odsPrinter) const;
+};
+
} // namespace LLVM
} // namespace mlir
+namespace mlir {
+namespace detail {
+template <>
+class TypeIDResolver<LLVM::LLVMPointerType> {
+public:
+ static TypeID resolveTypeID() { return TypeID::get<ptr::PtrType>(); }
+};
+} /* namespace detail */
+} // namespace mlir
+
#endif // MLIR_DIALECT_LLVMIR_LLVMTYPES_H_
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.td
index 0bd068c1be7c90a..f492ee93b0a30fb 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.td
@@ -117,39 +117,6 @@ def LLVMFunctionType : LLVMType<"LLVMFunction", "func"> {
}];
}
-//===----------------------------------------------------------------------===//
-// LLVMPointerType
-//===----------------------------------------------------------------------===//
-
-def LLVMPointerType : LLVMType<"LLVMPointer", "ptr", [
- DeclareTypeInterfaceMethods<DataLayoutTypeInterface, [
- "areCompatible", "verifyEntries"]>]> {
- let summary = "LLVM pointer type";
- let description = [{
- The `!llvm.ptr` type is an LLVM pointer type. This type typically represents
- a reference to an object in memory. Pointers are optionally parameterized
- by the address space.
-
- Example:
-
- ```mlir
- !llvm.ptr
- ```
- }];
-
- let parameters = (ins DefaultValuedParameter<"unsigned", "0">:$addressSpace);
- let assemblyFormat = [{
- (`<` $addressSpace^ `>`)?
- }];
-
- let skipDefaultBuilders = 1;
- let builders = [
- TypeBuilder<(ins CArg<"unsigned", "0">:$addressSpace), [{
- return $_get($_ctxt, addressSpace);
- }]>
- ];
-}
-
//===----------------------------------------------------------------------===//
// LLVMFixedVectorType
//===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/Dialect/Ptr/CMakeLists.txt b/mlir/include/mlir/Dialect/Ptr/CMakeLists.txt
new file mode 100644
index 000000000000000..f33061b2d87cffc
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Ptr/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(IR)
diff --git a/mlir/include/mlir/Dialect/Ptr/IR/CMakeLists.txt b/mlir/include/mlir/Dialect/Ptr/IR/CMakeLists.txt
new file mode 100644
index 000000000000000..9d7796deb0f1f7b
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Ptr/IR/CMakeLists.txt
@@ -0,0 +1,17 @@
+add_mlir_dialect(PtrOps ptr)
+add_mlir_doc(PtrOps PtrOps Dialects/ -gen-op-doc)
+
+set(LLVM_TARGET_DEFINITIONS MemorySpaceInterfaces.td)
+mlir_tablegen(MemorySpaceInterfaces.h.inc -gen-attr-interface-decls)
+mlir_tablegen(MemorySpaceInterfaces.cpp.inc -gen-attr-interface-defs)
+add_public_tablegen_target(MLIRPtrMemorySpaceInterfacesIncGen)
+
+set(LLVM_TARGET_DEFINITIONS PtrOps.td)
+mlir_tablegen(PtrOpsEnums.h.inc -gen-enum-decls)
+mlir_tablegen(PtrOpsEnums.cpp.inc -gen-enum-defs)
+add_public_tablegen_target(MLIRPtrOpsEnumsGen)
+
+set(LLVM_TARGET_DEFINITIONS PtrOps.td)
+mlir_tablegen(PtrOpsAttributes.h.inc -gen-attrdef-decls -attrdefs-dialect=ptr)
+mlir_tablegen(PtrOpsAttributes.cpp.inc -gen-attrdef-defs -attrdefs-dialect=ptr)
+add_public_tablegen_target(MLIRPtrOpsAttributesIncGen)
diff --git a/mlir/include/mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h b/mlir/include/mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h
new file mode 100644
index 000000000000000..c60dcdae0b18901
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h
@@ -0,0 +1,20 @@
+//===-- MemorySpaceInterfaces.h - GPU compilation interfaces ---*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines memory space interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_PTR_IR_MEMORYSPACEINTERFACES_H
+#define MLIR_DIALECT_PTR_IR_MEMORYSPACEINTERFACES_H
+
+#include "mlir/IR/Attributes.h"
+
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h.inc"
+
+#endif // MLIR_DIALECT_PTR_IR_MEMORYSPACEINTERFACES_H
diff --git a/mlir/include/mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td b/mlir/include/mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td
new file mode 100644
index 000000000000000..04f62f8bcafb924
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td
@@ -0,0 +1,63 @@
+//===-- MemorySpaceInterfaces.td - Memory space interfaces ----------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines memory space attribute interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PTR_MEMORYSPACEINTERFACES
+#define PTR_MEMORYSPACEINTERFACES
+
+include "mlir/IR/AttrTypeBase.td"
+include "mlir/IR/OpBase.td"
+
+//===----------------------------------------------------------------------===//
+// Memory space attribute interface.
+//===----------------------------------------------------------------------===//
+
+def MemorySpaceAttrInterface : AttrInterface<"MemorySpaceAttrInterface"> {
+ let description = [{
+ This interface defines a common API for interacting with the memory model of
+ a memory space and the operations in the pointer dialect, giving proper
+ semantical meaning to the ops.
+
+ Furthermore, this interface allows concepts such as read-only memory to be
+ adequately modeled and enforced.
+ }];
+ let cppNamespace = "::mlir::ptr";
+ let methods = [
+ InterfaceMethod<[{
+ Returns which dialect owns the memory model.
+ }],
+ "Dialect*", "getModelOwner", (ins),
+ [{}],
+ [{ return nullptr; }]
+ >,
+ InterfaceMethod<[{
+ Returns the address space as an unsigned int.
+ }],
+ "unsigned", "getAddressSpace", (ins),
+ [{}],
+ [{ return 0; }]
+ >,
+ InterfaceMethod<[{
+ Returns the address space as an unsigned int.
+ }],
+ "Attribute", "getDefaultMemorySpace", (ins)
+ >,
+ InterfaceMethod<[{
+ Returns whether a type can be loaded from memory.
+ }],
+ "bool", "isValidLoad", (ins "Type":$type),
+ [{}],
+ [{ return true; }]
+ >,
+ ];
+}
+
+#endif // PTR_MEMORYSPACEINTERFACES
diff --git a/mlir/include/mlir/Dialect/Ptr/IR/PtrDialect.h b/mlir/include/mlir/Dialect/Ptr/IR/PtrDialect.h
new file mode 100644
index 000000000000000..1e91ce60821d4b8
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Ptr/IR/PtrDialect.h
@@ -0,0 +1,20 @@
+//===- PointerDialect.h - Pointer dialect -----------------------*- C++ -*-===//
+//
+// This file is licensed 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Ptr dialect.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_PTR_IR_PTRDIALECT_H
+#define MLIR_DIALECT_PTR_IR_PTRDIALECT_H
+
+#include "mlir/IR/Dialect.h"
+
+#include "mlir/Dialect/Ptr/IR/PtrOpsDialect.h.inc"
+
+#endif // MLIR_DIALECT_PTR_IR_PTRDIALECT_H
diff --git a/mlir/include/mlir/Dialect/Ptr/IR/PtrDialect.td b/mlir/include/mlir/Dialect/Ptr/IR/PtrDialect.td
new file mode 100644
index 000000000000000..820e57b582627fa
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Ptr/IR/PtrDialect.td
@@ -0,0 +1,84 @@
+//===- PointerDialect.td - Pointer dialect -----------------*- tablegen -*-===//
+//
+// This file is licensed 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 PTR_DIALECT
+#define PTR_DIALECT
+
+include "mlir/Interfaces/DataLayoutInterfaces.td"
+include "mlir/IR/AttrTypeBase.td"
+include "mlir/IR/BuiltinTypeInterfaces.td"
+include "mlir/IR/OpBase.td"
+
+//===----------------------------------------------------------------------===//
+// Pointer dialect definition.
+//===----------------------------------------------------------------------===//
+
+def Ptr_Dialect : Dialect {
+ let name = "ptr";
+ let summary = "Pointer dialect";
+ let cppNamespace = "::mlir::ptr";
+ let useDefaultTypePrinterParser = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// Pointer type definitions
+//===----------------------------------------------------------------------===//
+
+class Pointer_Type<string name, string typeMnemonic, list<Trait> traits = []>
+ : TypeDef<Ptr_Dialect, name, traits> {
+ let mnemonic = typeMnemonic;
+}
+
+def PtrType : Pointer_Type<"Ptr", "ptr", [
+ MemRefElementTypeInterface,
+ DeclareTypeInterfaceMethods<DataLayoutTypeInterface, [
+ "areCompatible", "verifyEntries"]>,
+ DeclareTypeInterfaceMethods<SharedDialectTypeInterface, [
+ "getSharedDialect"]>
+ ]> {
+ let summary = "Pointer type";
+ let description = [{
+ The `ptr` type is an opaque pointer type. This type typically represents
+ a reference to an object in memory. Pointers are optionally parameterized
+ by a memory space.
+ Syntax:
+
+ ```mlir
+ pointer ::= `ptr` (`<` memory-space `>`)?
+ memory-space ::= attribute-value
+ ```
+ }];
+ let parameters = (ins OptionalParameter<"Attribute">:$memorySpace);
+ let assemblyFormat = "(`<` $memorySpace^ `>`)?";
+ let skipDefaultBuilders = 1;
+ let builders = [
+ TypeBuilder<(ins CArg<"Attribute", "nullptr">:$addressSpace), [{
+ return $_get($_ctxt, addressSpace);
+ }]>,
+ TypeBuilder<(ins CArg<"unsigned">:$addressSpace), [{
+ return $_get($_ctxt, IntegerAttr::get(IntegerType::get($_ctxt, 32),
+ addressSpace));
+ }]>
+ ];
+ let extraClassDeclaration = [{
+ /// Returns the default memory space.
+ Attribute getDefaultMemorySpace() const;
+
+ /// Returns the memory space as an unsigned number.
+ int64_t getAddressSpace() const;
+ }];
+}
+
+//===----------------------------------------------------------------------===//
+// Base address operation definition.
+//===----------------------------------------------------------------------===//
+
+class Pointer_Op<string mnemonic, list<Trait> traits = []> :
+ Op<Ptr_Dialect, mnemonic, traits>;
+
+#endif // PTR_DIALECT
diff --git a/mlir/include/mlir/Dialect/Ptr/IR/PtrEnums.td b/mlir/include/mlir/Dialect/Ptr/IR/PtrEnums.td
new file mode 100644
index 000000000000000..2ad6427975d146b
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Ptr/IR/PtrEnums.td
@@ -0,0 +1,62 @@
+//===-- PtrEnums.td - Ptr dialect enum file ----------------*- tablegen -*-===//
+//
+// 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 PTR_ENUMS
+#define PTR_ENUMS
+
+include "mlir/Dialect/Ptr/IR/PtrDialect.td"
+include "mlir/IR/EnumAttr.td"
+
+//===----------------------------------------------------------------------===//
+// Base classes for Ptr enum attributes.
+//===----------------------------------------------------------------------===//
+
+class Ptr_EnumAttrCase<string cppSym, string irSym, string llvmSym, int val> :
+ I64EnumAttrCase<cppSym, val, irSym> {
+ // The name of the equivalent enumerant in LLVM.
+ string llvmEnumerant = llvmSym;
+}
+
+class Ptr_EnumAttr<string name, string llvmName, string description,
+ list<Ptr_EnumAttrCase> cases,
+ list<Ptr_EnumAttrCase> unsupportedCases = []> :
+ I64EnumAttr<name, description, cases> {
+ // List of unsupported cases that have no conversion to an MLIR value.
+ list<Ptr_EnumAttrCase> unsupported = unsupportedCases;
+
+ // The equivalent enum class name in LLVM.
+ string llvmClassName = llvmName;
+}
+
+def AtomicOrderingNotAtomic : Ptr_EnumAttrCase<"not_atomic",
+ "not_atomic", "NotAtomic", 0>;
+def AtomicOrderingUnordered : Ptr_EnumAttrCase<"unordered",
+ "unordered", "Unordered", 1>;
+def AtomicOrderingMonotonic : Ptr_EnumAttrCase<"monotonic",
+ "monotonic", "Monotonic", 2>;
+def AtomicOrderingAcquire : Ptr_EnumAttrCase<"acquire",
+ "acquire", "Acquire", 4>;
+def AtomicOrderingRelease : Ptr_EnumAttrCase<"release",
+ "release", "Release", 5>;
+def AtomicOrderingAcquireRelease :
+ Ptr_EnumAttrCase<"acq_rel", "acq_rel", "AcquireRelease", 6>;
+def AtomicOrderingSequentiallyConsistent :
+ Ptr_EnumAttrCase<"seq_cst", "seq_cst", "SequentiallyConsistent", 7>;
+
+def AtomicOrdering : Ptr_EnumAttr<
+ "AtomicOrdering",
+ "::llvm::AtomicOrdering",
+ "Atomic ordering for LLVM's memory model",
+ [AtomicOrderingNotAtomic, AtomicOrderingUnordered, AtomicOrderingMonotonic,
+ AtomicOrderingAcquire, AtomicOrderingRelease, AtomicOrderingAcquireRelease,
+ AtomicOrderingSequentiallyConsistent
+ ]> {
+ let cppNamespace = "::mlir::ptr";
+}
+
+#endif // PTR_ENUMS
diff --git a/mlir/include/mlir/Dialect/Ptr/IR/PtrOps.h b/mlir/include/mlir/Dialect/Ptr/IR/PtrOps.h
new file mode 100644
index 000000000000000..47d7e355b5f54b8
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Ptr/IR/PtrOps.h
@@ -0,0 +1,32 @@
+//===- PointerDialect.h - Pointer dialect -----------------------*- C++ -*-===//
+//
+// This file is licensed 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Pointer dialect.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_PTR_IR_PTROPS_H
+#define MLIR_DIALECT_PTR_IR_PTROPS_H
+
+#include "mlir/Bytecode/BytecodeOpInterface.h"
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
+#include "mlir/Dialect/Ptr/IR/PtrDialect.h"
+#include "mlir/Dialect/Ptr/IR/PtrTypes.h"
+#include "mlir/IR/OpDefinition.h"
+#include "mlir/Interfaces/MemorySlotInterfaces.h"
+#include "mlir/Interfaces/SideEffectInterfaces.h"
+
+#include "mlir/Dialect/Ptr/IR/PtrOpsEnums.h.inc"
+
+#define GET_ATTRDEF_CLASSES
+#include "mlir/Dialect/Ptr/IR/PtrOpsAttributes.h.inc"
+
+#define GET_OP_CLASSES
+#include "mlir/Dialect/Ptr/IR/PtrOps.h.inc"
+
+#endif // MLIR_DIALECT_PTR_IR_PTROPS_H
diff --git a/mlir/include/mlir/Dialect/Ptr/IR/PtrOps.td b/mlir/include/mlir/Dialect/Ptr/IR/PtrOps.td
new file mode 100644
index 000000000000000..e9c348605a1edb2
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Ptr/IR/PtrOps.td
@@ -0,0 +1,68 @@
+//===- PointerOps.td - Pointer dialect ops -----------------*- tablegen -*-===//
+//
+// This file is licensed 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 PTR_OPS
+#define PTR_OPS
+
+include "mlir/Dialect/Ptr/IR/PtrDialect.td"
+include "mlir/Dialect/Ptr/IR/PtrEnums.td"
+include "mlir/Interfaces/MemorySlotInterfaces.td"
+include "mlir/Interfaces/SideEffectInterfaces.td"
+include "mlir/IR/EnumAttr.td"
+
+
+def Ptr_LoadOp : Pointer_Op<"load",
+ [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>,
+ DeclareOpInterfaceMethods<PromotableMemOpInterface>,
+ DeclareOpInterfaceMethods<SafeMemorySlotAccessOpInterface>]> {
+ let arguments = (ins PtrType:$addr,
+ OptionalAttr<I64Attr>:$alignment,
+ UnitAttr:$volatile_,
+ UnitAttr:$nontemporal,
+ DefaultValuedAttr<
+ AtomicOrdering, "AtomicOrdering::not_atomic">:$ordering,
+ OptionalAttr<StrAttr>:$syncscope);
+ let results = (outs AnyType:$res);
+ string llvmInstName = "Load";
+ let description = [{
+ The `load` operation is used to read from memory. A load may be marked as
+ atomic, volatile, and/or nontemporal, and takes a number of optional
+ attributes that specify aliasing information.
+
+ An atomic load only supports a limited set of pointer, integer, and
+ floating point types, and requires an explicit alignment.
+
+ Examples:
+ ```mlir
+ // A volatile load of a float variable.
+ %0 = ptr.load volatile %ptr : !ptr.ptr -> f32
+
+ // A nontemporal load of a float variable.
+ %0 = ptr.load %ptr {nontemporal} : !ptr.ptr -> f32
+
+ // An atomic load of an integer variable.
+ %0 = ptr.load %ptr atomic monotonic {alignment = 8 : i64}
+ : !ptr.ptr -> i64
+ ```
+ }];
+ let assemblyFormat = [{
+ (`volatile` $volatile_^)? $addr
+ (`atomic` (`syncscope` `(` $syncscope^ `)`)? $ordering^)?
+ attr-dict `:` qualified(type($addr)) `->` type($res)
+ }];
+ let builders = [
+ OpBuilder<(ins "Type":$type, "Value":$addr,
+ CArg<"unsigned", "0">:$alignment, CArg<"bool", "false">:$isVolatile,
+ CArg<"bool", "false">:$isNonTemporal,
+ CArg<"AtomicOrdering", "AtomicOrdering::not_atomic">:$ordering,
+ CArg<"StringRef", "StringRef()">:$syncscope)>
+ ];
+ let hasVerifier = 1;
+}
+
+#endif // PTR_OPS
diff --git a/mlir/include/mlir/Dialect/Ptr/IR/PtrTypes.h b/mlir/include/mlir/Dialect/Ptr/IR/PtrTypes.h
new file mode 100644
index 000000000000000..9351f3c073dec4a
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Ptr/IR/PtrTypes.h
@@ -0,0 +1,37 @@
+//===- PointerTypes.h - Pointer types ---------------------------*- C++ -*-===//
+//
+// This file is licensed 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Pointer dialect types.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_PTR_IR_PTRTYPES_H
+#define MLIR_DIALECT_PTR_IR_PTRTYPES_H
+
+#include "mlir/IR/Types.h"
+#include "mlir/Interfaces/DataLayoutInterfaces.h"
+
+namespace mlir {
+namespace ptr {
+/// The positions of different values in the data layout entry for pointers.
+enum class PtrDLEntryPos { Size = 0, Abi = 1, Preferred = 2, Index = 3 };
+
+/// Returns the value that corresponds to named position `pos` from the
+/// data layout entry `attr` assuming it's a dense integer elements attribute.
+/// Returns `std::nullopt` if `pos` is not present in the entry.
+/// Currently only `PtrDLEntryPos::Index` is optional, and all other positions
+/// may be assumed to be present.
+std::optional<unsigned> extractPointerSpecValue(Attribute attr,
+ PtrDLEntryPos pos);
+} // namespace ptr
+} // namespace mlir
+
+#define GET_TYPEDEF_CLASSES
+#include "mlir/Dialect/Ptr/IR/PtrOpsTypes.h.inc"
+
+#endif // MLIR_DIALECT_PTR_IR_PTRTYPES_H
diff --git a/mlir/include/mlir/IR/BuiltinTypeInterfaces.td b/mlir/include/mlir/IR/BuiltinTypeInterfaces.td
index db38e2e1bce22aa..d62ce5b4e6f71dd 100644
--- a/mlir/include/mlir/IR/BuiltinTypeInterfaces.td
+++ b/mlir/include/mlir/IR/BuiltinTypeInterfaces.td
@@ -188,4 +188,29 @@ def ShapedTypeInterface : TypeInterface<"ShapedType"> {
}];
}
+//===----------------------------------------------------------------------===//
+// SharedDialectTypeInterface
+//===----------------------------------------------------------------------===//
+
+def SharedDialectTypeInterface : TypeInterface<"SharedDialectTypeInterface"> {
+ let cppNamespace = "::mlir";
+ let description = [{
+ This interface allows sharing a type between dialects, allowing custom
+ parsing and printing of a type by a foreign dialect.
+ If a dialect has a type with this interface, then it must implement the
+ dialect methods `parseType` and `printType`.
+ }];
+ let methods = [
+ InterfaceMethod<[{
+ Returns the dialect responsible for printing and parsing the type
+ instance.
+ }],
+ "Dialect&", "getSharedDialect", (ins),
+ [{}],
+ [{ return $_type.getDialect(); }]
+ >
+ ];
+}
+
+
#endif // MLIR_IR_BUILTINTYPEINTERFACES_TD_
diff --git a/mlir/include/mlir/InitAllDialects.h b/mlir/include/mlir/InitAllDialects.h
index 19a62cadaa2e04f..83443cd82f8e592 100644
--- a/mlir/include/mlir/InitAllDialects.h
+++ b/mlir/include/mlir/InitAllDialects.h
@@ -60,6 +60,7 @@
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
#include "mlir/Dialect/PDL/IR/PDL.h"
#include "mlir/Dialect/PDLInterp/IR/PDLInterp.h"
+#include "mlir/Dialect/Ptr/IR/PtrDialect.h"
#include "mlir/Dialect/Quant/QuantOps.h"
#include "mlir/Dialect/SCF/IR/SCF.h"
#include "mlir/Dialect/SCF/IR/ValueBoundsOpInterfaceImpl.h"
@@ -127,6 +128,7 @@ inline void registerAllDialects(DialectRegistry ®istry) {
omp::OpenMPDialect,
pdl::PDLDialect,
pdl_interp::PDLInterpDialect,
+ ptr::PtrDialect,
quant::QuantizationDialect,
ROCDL::ROCDLDialect,
scf::SCFDialect,
diff --git a/mlir/include/mlir/Target/LLVMIR/Dialect/All.h b/mlir/include/mlir/Target/LLVMIR/Dialect/All.h
index 0563b9bf3d475a4..2b3d8c18c85e5d5 100644
--- a/mlir/include/mlir/Target/LLVMIR/Dialect/All.h
+++ b/mlir/include/mlir/Target/LLVMIR/Dialect/All.h
@@ -25,6 +25,7 @@
#include "mlir/Target/LLVMIR/Dialect/NVVM/NVVMToLLVMIRTranslation.h"
#include "mlir/Target/LLVMIR/Dialect/OpenACC/OpenACCToLLVMIRTranslation.h"
#include "mlir/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.h"
+#include "mlir/Target/LLVMIR/Dialect/Ptr/PtrToLLVMIRTranslation.h"
#include "mlir/Target/LLVMIR/Dialect/ROCDL/ROCDLToLLVMIRTranslation.h"
#include "mlir/Target/LLVMIR/Dialect/X86Vector/X86VectorToLLVMIRTranslation.h"
@@ -44,6 +45,7 @@ static inline void registerAllToLLVMIRTranslations(DialectRegistry ®istry) {
registerNVVMDialectTranslation(registry);
registerOpenACCDialectTranslation(registry);
registerOpenMPDialectTranslation(registry);
+ registerPtrDialectTranslation(registry);
registerROCDLDialectTranslation(registry);
registerX86VectorDialectTranslation(registry);
@@ -60,6 +62,7 @@ registerAllGPUToLLVMIRTranslations(DialectRegistry ®istry) {
registerGPUDialectTranslation(registry);
registerLLVMDialectTranslation(registry);
registerNVVMDialectTranslation(registry);
+ registerPtrDialectTranslation(registry);
registerROCDLDialectTranslation(registry);
// Extension required for translating GPU offloading Ops.
diff --git a/mlir/include/mlir/Target/LLVMIR/Dialect/Ptr/PtrToLLVMIRTranslation.h b/mlir/include/mlir/Target/LLVMIR/Dialect/Ptr/PtrToLLVMIRTranslation.h
new file mode 100644
index 000000000000000..5dc1b0e45995ca4
--- /dev/null
+++ b/mlir/include/mlir/Target/LLVMIR/Dialect/Ptr/PtrToLLVMIRTranslation.h
@@ -0,0 +1,31 @@
+//===- PtrToLLVMIRTranslation.h - Ptr Dialect to LLVM IR --------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides registration calls for Ptr dialect to LLVM IR translation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_TARGET_LLVMIR_DIALECT_PTR_PTRTOLLVMIRTRANSLATION_H
+#define MLIR_TARGET_LLVMIR_DIALECT_PTR_PTRTOLLVMIRTRANSLATION_H
+
+namespace mlir {
+
+class DialectRegistry;
+class MLIRContext;
+
+/// Register the Ptr dialect and the translation from it to the LLVM IR in
+/// the given registry;
+void registerPtrDialectTranslation(DialectRegistry ®istry);
+
+/// Register the Ptr dialect and the translation from it in the registry
+/// associated with the given context.
+void registerPtrDialectTranslation(MLIRContext &context);
+
+} // namespace mlir
+
+#endif // MLIR_TARGET_LLVMIR_DIALECT_PTR_PTRTOLLVMIRTRANSLATION_H
diff --git a/mlir/lib/Dialect/CMakeLists.txt b/mlir/lib/Dialect/CMakeLists.txt
index 68776a695cac4d4..281e85df3971c52 100644
--- a/mlir/lib/Dialect/CMakeLists.txt
+++ b/mlir/lib/Dialect/CMakeLists.txt
@@ -27,6 +27,7 @@ add_subdirectory(OpenACCMPCommon)
add_subdirectory(OpenMP)
add_subdirectory(PDL)
add_subdirectory(PDLInterp)
+add_subdirectory(Ptr)
add_subdirectory(Quant)
add_subdirectory(SCF)
add_subdirectory(Shape)
diff --git a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
index b00259677697a50..8e19782dfb4927f 100644
--- a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
@@ -19,6 +19,7 @@ add_mlir_dialect_library(MLIRLLVMDialect
MLIRLLVMIntrinsicOpsIncGen
MLIRLLVMInterfacesIncGen
MLIROpenMPOpsIncGen
+ MLIRPtrOpsIncGen
intrinsics_gen
LINK_COMPONENTS
@@ -37,6 +38,7 @@ add_mlir_dialect_library(MLIRLLVMDialect
MLIRIR
MLIRMemorySlotInterfaces
MLIRSideEffectInterfaces
+ MLIRPtrDialect
MLIRSupport
)
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
index 3d45ab8fac4d705..7b10e004d158c2c 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
@@ -109,3 +109,17 @@ bool MemoryEffectsAttr::isReadWrite() {
return false;
return true;
}
+
+//===----------------------------------------------------------------------===//
+// AddressSpaceAttr
+//===----------------------------------------------------------------------===//
+
+Dialect *AddressSpaceAttr::getModelOwner() const { return &getDialect(); }
+
+bool AddressSpaceAttr::isValidLoad(Type type) const {
+ return isCompatibleType(type);
+}
+
+Attribute AddressSpaceAttr::getDefaultMemorySpace() const {
+ return AddressSpaceAttr::get(getContext(), 0);
+}
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index f6c8f388732c3da..fe205d3947697c2 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -17,6 +17,7 @@
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
#include "mlir/Dialect/LLVMIR/LLVMInterfaces.h"
#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
+#include "mlir/Dialect/Ptr/IR/PtrDialect.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/BuiltinTypes.h"
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp
index 8841aa8362569a0..7b580319676e083 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp
@@ -15,6 +15,7 @@
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
+#include "mlir/Dialect/Ptr/IR/PtrTypes.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/DialectImplementation.h"
#include "mlir/IR/TypeSupport.h"
@@ -254,9 +255,6 @@ LLVMFunctionType::verify(function_ref<InFlightDiagnostic()> emitError,
//===----------------------------------------------------------------------===//
// DataLayoutTypeInterface
-constexpr const static unsigned kDefaultPointerSizeBits = 64;
-constexpr const static unsigned kDefaultPointerAlignment = 8;
-
std::optional<unsigned> mlir::LLVM::extractPointerSpecValue(Attribute attr,
PtrDLEntryPos pos) {
auto spec = llvm::cast<DenseIntElementsAttr>(attr);
@@ -266,127 +264,38 @@ std::optional<unsigned> mlir::LLVM::extractPointerSpecValue(Attribute attr,
return spec.getValues<unsigned>()[idx];
}
-/// Returns the part of the data layout entry that corresponds to `pos` for the
-/// given `type` by interpreting the list of entries `params`. For the pointer
-/// type in the default address space, returns the default value if the entries
-/// do not provide a custom one, for other address spaces returns std::nullopt.
-static std::optional<unsigned>
-getPointerDataLayoutEntry(DataLayoutEntryListRef params, LLVMPointerType type,
- PtrDLEntryPos pos) {
- // First, look for the entry for the pointer in the current address space.
- Attribute currentEntry;
- for (DataLayoutEntryInterface entry : params) {
- if (!entry.isTypeEntry())
- continue;
- if (llvm::cast<LLVMPointerType>(entry.getKey().get<Type>())
- .getAddressSpace() == type.getAddressSpace()) {
- currentEntry = entry.getValue();
- break;
- }
- }
- if (currentEntry) {
- return *extractPointerSpecValue(currentEntry, pos) /
- (pos == PtrDLEntryPos::Size ? 1 : kBitsInByte);
- }
-
- // If not found, and this is the pointer to the default memory space, assume
- // 64-bit pointers.
- if (type.getAddressSpace() == 0) {
- return pos == PtrDLEntryPos::Size ? kDefaultPointerSizeBits
- : kDefaultPointerAlignment;
- }
-
- return std::nullopt;
+ptr::PtrType LLVMPointerType::get(MLIRContext *context, unsigned addressSpace) {
+ return ptr::PtrType::get(context,
+ AddressSpaceAttr::get(context, addressSpace));
}
-unsigned
-LLVMPointerType::getTypeSizeInBits(const DataLayout &dataLayout,
- DataLayoutEntryListRef params) const {
- if (std::optional<unsigned> size =
- getPointerDataLayoutEntry(params, *this, PtrDLEntryPos::Size))
- return *size;
-
- // For other memory spaces, use the size of the pointer to the default memory
- // space.
- return dataLayout.getTypeSizeInBits(get(getContext()));
-}
-
-unsigned LLVMPointerType::getABIAlignment(const DataLayout &dataLayout,
- DataLayoutEntryListRef params) const {
- if (std::optional<unsigned> alignment =
- getPointerDataLayoutEntry(params, *this, PtrDLEntryPos::Abi))
- return *alignment;
-
- return dataLayout.getTypeABIAlignment(get(getContext()));
-}
-
-unsigned
-LLVMPointerType::getPreferredAlignment(const DataLayout &dataLayout,
- DataLayoutEntryListRef params) const {
- if (std::optional<unsigned> alignment =
- getPointerDataLayoutEntry(params, *this, PtrDLEntryPos::Preferred))
- return *alignment;
-
- return dataLayout.getTypePreferredAlignment(get(getContext()));
-}
-
-bool LLVMPointerType::areCompatible(DataLayoutEntryListRef oldLayout,
- DataLayoutEntryListRef newLayout) const {
- for (DataLayoutEntryInterface newEntry : newLayout) {
- if (!newEntry.isTypeEntry())
- continue;
- unsigned size = kDefaultPointerSizeBits;
- unsigned abi = kDefaultPointerAlignment;
- auto newType = llvm::cast<LLVMPointerType>(newEntry.getKey().get<Type>());
- const auto *it =
- llvm::find_if(oldLayout, [&](DataLayoutEntryInterface entry) {
- if (auto type = llvm::dyn_cast_if_present<Type>(entry.getKey())) {
- return llvm::cast<LLVMPointerType>(type).getAddressSpace() ==
- newType.getAddressSpace();
- }
- return false;
- });
- if (it == oldLayout.end()) {
- llvm::find_if(oldLayout, [&](DataLayoutEntryInterface entry) {
- if (auto type = llvm::dyn_cast_if_present<Type>(entry.getKey())) {
- return llvm::cast<LLVMPointerType>(type).getAddressSpace() == 0;
- }
- return false;
- });
- }
- if (it != oldLayout.end()) {
- size = *extractPointerSpecValue(*it, PtrDLEntryPos::Size);
- abi = *extractPointerSpecValue(*it, PtrDLEntryPos::Abi);
+Type LLVMPointerType::parse(AsmParser &odsParser) {
+ FailureOr<unsigned> addressSpace;
+ // Parse literal '<'
+ if (!odsParser.parseOptionalLess()) {
+ if (failed(addressSpace = FieldParser<unsigned>::parse(odsParser))) {
+ odsParser.emitError(odsParser.getCurrentLocation(),
+ "failed to parse LLVMPtrType parameter 'memorySpace' "
+ "which is to be a `unsigned`");
+ return {};
}
-
- Attribute newSpec = llvm::cast<DenseIntElementsAttr>(newEntry.getValue());
- unsigned newSize = *extractPointerSpecValue(newSpec, PtrDLEntryPos::Size);
- unsigned newAbi = *extractPointerSpecValue(newSpec, PtrDLEntryPos::Abi);
- if (size != newSize || abi < newAbi || abi % newAbi != 0)
- return false;
+ // Parse literal '>'
+ if (odsParser.parseGreater())
+ return {};
}
- return true;
+ return LLVMPointerType::get(odsParser.getContext(), addressSpace.value_or(0));
}
-LogicalResult LLVMPointerType::verifyEntries(DataLayoutEntryListRef entries,
- Location loc) const {
- for (DataLayoutEntryInterface entry : entries) {
- if (!entry.isTypeEntry())
- continue;
- auto values = llvm::dyn_cast<DenseIntElementsAttr>(entry.getValue());
- if (!values || (values.size() != 3 && values.size() != 4)) {
- return emitError(loc)
- << "expected layout attribute for " << entry.getKey().get<Type>()
- << " to be a dense integer elements attribute with 3 or 4 "
- "elements";
- }
- if (extractPointerSpecValue(values, PtrDLEntryPos::Abi) >
- extractPointerSpecValue(values, PtrDLEntryPos::Preferred)) {
- return emitError(loc) << "preferred alignment is expected to be at least "
- "as large as ABI alignment";
- }
- }
- return success();
+void LLVMPointerType::print(AsmPrinter &odsPrinter) const {
+ if (unsigned as = getAddressSpace(); as != 0)
+ odsPrinter << "<" << as << ">";
+}
+
+bool mlir::LLVM::isLLVMPointerType(Type type) {
+ if (auto ptrTy = mlir::dyn_cast<ptr::PtrType>(type))
+ return ptrTy.getMemorySpace() &&
+ mlir::isa<AddressSpaceAttr>(ptrTy.getMemorySpace());
+ return false;
}
//===----------------------------------------------------------------------===//
@@ -798,6 +707,7 @@ static bool isCompatibleImpl(Type type, DenseSet<Type> &compatibleTypes) {
isCompatible(vecType.getElementType());
})
.Case<LLVMPointerType>([&](auto pointerType) { return true; })
+ .Case<ptr::PtrType>([&](auto pointerType) { return true; })
.Case<LLVMTargetExtType>([&](auto extType) {
return llvm::all_of(extType.getTypeParams(), isCompatible);
})
diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
index 08e83cad482207d..6046f3071f3a99f 100644
--- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
+++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
@@ -37,7 +37,7 @@ struct MemRefPointerLikeModel
struct LLVMPointerPointerLikeModel
: public PointerLikeType::ExternalModel<LLVMPointerPointerLikeModel,
- LLVM::LLVMPointerType> {
+ ptr::PtrType> {
Type getElementType(Type pointer) const { return Type(); }
};
} // namespace
@@ -64,8 +64,7 @@ void OpenACCDialect::initialize() {
// the other dialects. This is probably better than having dialects like LLVM
// and memref be dependent on OpenACC.
MemRefType::attachInterface<MemRefPointerLikeModel>(*getContext());
- LLVM::LLVMPointerType::attachInterface<LLVMPointerPointerLikeModel>(
- *getContext());
+ ptr::PtrType::attachInterface<LLVMPointerPointerLikeModel>(*getContext());
}
//===----------------------------------------------------------------------===//
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index 480af0e1307c158..6042cc11fce0755 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -49,7 +49,7 @@ struct MemRefPointerLikeModel
struct LLVMPointerPointerLikeModel
: public PointerLikeType::ExternalModel<LLVMPointerPointerLikeModel,
- LLVM::LLVMPointerType> {
+ ptr::PtrType> {
Type getElementType(Type pointer) const { return Type(); }
};
@@ -79,8 +79,7 @@ void OpenMPDialect::initialize() {
addInterface<OpenMPDialectFoldInterface>();
MemRefType::attachInterface<MemRefPointerLikeModel>(*getContext());
- LLVM::LLVMPointerType::attachInterface<LLVMPointerPointerLikeModel>(
- *getContext());
+ ptr::PtrType::attachInterface<LLVMPointerPointerLikeModel>(*getContext());
// Attach default offload module interface to module op to access
// offload functionality through
diff --git a/mlir/lib/Dialect/Ptr/CMakeLists.txt b/mlir/lib/Dialect/Ptr/CMakeLists.txt
new file mode 100644
index 000000000000000..f33061b2d87cffc
--- /dev/null
+++ b/mlir/lib/Dialect/Ptr/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(IR)
diff --git a/mlir/lib/Dialect/Ptr/IR/CMakeLists.txt b/mlir/lib/Dialect/Ptr/IR/CMakeLists.txt
new file mode 100644
index 000000000000000..747275cdc5a32b0
--- /dev/null
+++ b/mlir/lib/Dialect/Ptr/IR/CMakeLists.txt
@@ -0,0 +1,15 @@
+add_mlir_dialect_library(
+ MLIRPtrDialect
+ PtrDialect.cpp
+ ADDITIONAL_HEADER_DIRS
+ ${PROJECT_SOURCE_DIR}/mlir/Dialect/Pointer
+ DEPENDS
+ MLIRPtrOpsIncGen
+ MLIRPtrMemorySpaceInterfacesIncGen
+ MLIRPtrOpsEnumsGen
+ MLIRPtrOpsAttributesIncGen
+ LINK_LIBS
+ PUBLIC
+ MLIRIR
+ MLIRDataLayoutInterfaces
+)
diff --git a/mlir/lib/Dialect/Ptr/IR/PtrDialect.cpp b/mlir/lib/Dialect/Ptr/IR/PtrDialect.cpp
new file mode 100644
index 000000000000000..a31946c36089852
--- /dev/null
+++ b/mlir/lib/Dialect/Ptr/IR/PtrDialect.cpp
@@ -0,0 +1,294 @@
+//===- PtrDialect.cpp - Pointer dialect ---------------------*- C++ -*-===//
+//
+// This file is licensed 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Pointer dialect.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/Ptr/IR/PtrOps.h"
+#include "mlir/IR/DialectImplementation.h"
+#include "mlir/IR/PatternMatch.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/TypeSwitch.h"
+
+using namespace mlir;
+using namespace mlir::ptr;
+
+//===----------------------------------------------------------------------===//
+// Pointer dialect
+//===----------------------------------------------------------------------===//
+
+void PtrDialect::initialize() {
+ addOperations<
+#define GET_OP_LIST
+#include "mlir/Dialect/Ptr/IR/PtrOps.cpp.inc"
+ >();
+ addTypes<
+#define GET_TYPEDEF_LIST
+#include "mlir/Dialect/Ptr/IR/PtrOpsTypes.cpp.inc"
+ >();
+}
+
+//===----------------------------------------------------------------------===//
+// Pointer type
+//===----------------------------------------------------------------------===//
+
+constexpr const static unsigned kDefaultPointerSizeBits = 64;
+constexpr const static unsigned kBitsInByte = 8;
+constexpr const static unsigned kDefaultPointerAlignment = 8;
+
+int64_t PtrType::getAddressSpace() const {
+ if (auto intAttr = llvm::dyn_cast_or_null<IntegerAttr>(getMemorySpace()))
+ return intAttr.getInt();
+ else if (auto ms = llvm::dyn_cast_or_null<MemorySpaceAttrInterface>(
+ getMemorySpace()))
+ return ms.getAddressSpace();
+ return 0;
+}
+
+Dialect &PtrType::getSharedDialect() const {
+ if (auto memSpace =
+ llvm::dyn_cast_or_null<MemorySpaceAttrInterface>(getMemorySpace());
+ memSpace && memSpace.getModelOwner())
+ return *memSpace.getModelOwner();
+ return getDialect();
+}
+
+Attribute PtrType::getDefaultMemorySpace() const {
+ if (auto ms =
+ llvm::dyn_cast_or_null<MemorySpaceAttrInterface>(getMemorySpace()))
+ return ms.getDefaultMemorySpace();
+ return nullptr;
+}
+
+std::optional<unsigned> mlir::ptr::extractPointerSpecValue(Attribute attr,
+ PtrDLEntryPos pos) {
+ auto spec = llvm::cast<DenseIntElementsAttr>(attr);
+ auto idx = static_cast<unsigned>(pos);
+ if (idx >= spec.size())
+ return std::nullopt;
+ return spec.getValues<unsigned>()[idx];
+}
+
+/// Returns the part of the data layout entry that corresponds to `pos` for the
+/// given `type` by interpreting the list of entries `params`. For the pointer
+/// type in the default address space, returns the default value if the entries
+/// do not provide a custom one, for other address spaces returns std::nullopt.
+static std::optional<unsigned>
+getPointerDataLayoutEntry(DataLayoutEntryListRef params, PtrType type,
+ PtrDLEntryPos pos) {
+ // First, look for the entry for the pointer in the current address space.
+ Attribute currentEntry;
+ for (DataLayoutEntryInterface entry : params) {
+ if (!entry.isTypeEntry())
+ continue;
+ if (llvm::cast<PtrType>(entry.getKey().get<Type>()).getMemorySpace() ==
+ type.getMemorySpace()) {
+ currentEntry = entry.getValue();
+ break;
+ }
+ }
+ if (currentEntry) {
+ return *extractPointerSpecValue(currentEntry, pos) /
+ (pos == PtrDLEntryPos::Size ? 1 : kBitsInByte);
+ }
+
+ // If not found, and this is the pointer to the default memory space, assume
+ // 64-bit pointers.
+ if (type.getAddressSpace() == 0) {
+ return pos == PtrDLEntryPos::Size ? kDefaultPointerSizeBits
+ : kDefaultPointerAlignment;
+ }
+
+ return std::nullopt;
+}
+
+unsigned PtrType::getTypeSizeInBits(const DataLayout &dataLayout,
+ DataLayoutEntryListRef params) const {
+ if (std::optional<unsigned> size =
+ getPointerDataLayoutEntry(params, *this, PtrDLEntryPos::Size))
+ return *size;
+
+ // For other memory spaces, use the size of the pointer to the default memory
+ // space.
+ return dataLayout.getTypeSizeInBits(
+ get(getContext(), getDefaultMemorySpace()));
+}
+
+unsigned PtrType::getABIAlignment(const DataLayout &dataLayout,
+ DataLayoutEntryListRef params) const {
+ if (std::optional<unsigned> alignment =
+ getPointerDataLayoutEntry(params, *this, PtrDLEntryPos::Abi))
+ return *alignment;
+
+ return dataLayout.getTypeABIAlignment(
+ get(getContext(), getDefaultMemorySpace()));
+}
+
+unsigned PtrType::getPreferredAlignment(const DataLayout &dataLayout,
+ DataLayoutEntryListRef params) const {
+ if (std::optional<unsigned> alignment =
+ getPointerDataLayoutEntry(params, *this, PtrDLEntryPos::Preferred))
+ return *alignment;
+
+ return dataLayout.getTypePreferredAlignment(
+ get(getContext(), getDefaultMemorySpace()));
+}
+
+bool PtrType::areCompatible(DataLayoutEntryListRef oldLayout,
+ DataLayoutEntryListRef newLayout) const {
+ for (DataLayoutEntryInterface newEntry : newLayout) {
+ if (!newEntry.isTypeEntry())
+ continue;
+ unsigned size = kDefaultPointerSizeBits;
+ unsigned abi = kDefaultPointerAlignment;
+ auto newType = llvm::cast<PtrType>(newEntry.getKey().get<Type>());
+ const auto *it =
+ llvm::find_if(oldLayout, [&](DataLayoutEntryInterface entry) {
+ if (auto type = llvm::dyn_cast_if_present<Type>(entry.getKey())) {
+ return llvm::cast<PtrType>(type).getMemorySpace() ==
+ newType.getMemorySpace();
+ }
+ return false;
+ });
+ if (it == oldLayout.end()) {
+ llvm::find_if(oldLayout, [&](DataLayoutEntryInterface entry) {
+ if (auto type = llvm::dyn_cast_if_present<Type>(entry.getKey())) {
+ return llvm::cast<PtrType>(type).getAddressSpace() == 0;
+ }
+ return false;
+ });
+ }
+ if (it != oldLayout.end()) {
+ size = *extractPointerSpecValue(*it, PtrDLEntryPos::Size);
+ abi = *extractPointerSpecValue(*it, PtrDLEntryPos::Abi);
+ }
+
+ Attribute newSpec = llvm::cast<DenseIntElementsAttr>(newEntry.getValue());
+ unsigned newSize = *extractPointerSpecValue(newSpec, PtrDLEntryPos::Size);
+ unsigned newAbi = *extractPointerSpecValue(newSpec, PtrDLEntryPos::Abi);
+ if (size != newSize || abi < newAbi || abi % newAbi != 0)
+ return false;
+ }
+ return true;
+}
+
+LogicalResult PtrType::verifyEntries(DataLayoutEntryListRef entries,
+ Location loc) const {
+ for (DataLayoutEntryInterface entry : entries) {
+ if (!entry.isTypeEntry())
+ continue;
+ auto values = llvm::dyn_cast<DenseIntElementsAttr>(entry.getValue());
+ if (!values || (values.size() != 3 && values.size() != 4)) {
+ return emitError(loc)
+ << "expected layout attribute for " << entry.getKey().get<Type>()
+ << " to be a dense integer elements attribute with 3 or 4 "
+ "elements";
+ }
+ if (extractPointerSpecValue(values, PtrDLEntryPos::Abi) >
+ extractPointerSpecValue(values, PtrDLEntryPos::Preferred)) {
+ return emitError(loc) << "preferred alignment is expected to be at least "
+ "as large as ABI alignment";
+ }
+ }
+ return success();
+}
+
+//===----------------------------------------------------------------------===//
+// LoadOp type
+//===----------------------------------------------------------------------===//
+
+bool ptr::LoadOp::loadsFrom(const MemorySlot &slot) {
+ return getAddr() == slot.ptr;
+}
+
+bool ptr::LoadOp::storesTo(const MemorySlot &slot) { return false; }
+
+Value ptr::LoadOp::getStored(const MemorySlot &slot, RewriterBase &rewriter) {
+ llvm_unreachable("getStored should not be called on LoadOp");
+}
+
+bool LoadOp::canUsesBeRemoved(const MemorySlot &slot,
+ const SmallPtrSetImpl<OpOperand *> &blockingUses,
+ SmallVectorImpl<OpOperand *> &newBlockingUses) {
+ if (blockingUses.size() != 1)
+ return false;
+ Value blockingUse = (*blockingUses.begin())->get();
+ // If the blocking use is the slot ptr itself, there will be enough
+ // context to reconstruct the result of the load at removal time, so it can
+ // be removed (provided it loads the exact stored value and is not
+ // volatile).
+ return blockingUse == slot.ptr && getAddr() == slot.ptr &&
+ getResult().getType() == slot.elemType && !getVolatile_();
+}
+
+DeletionKind
+LoadOp::removeBlockingUses(const MemorySlot &slot,
+ const SmallPtrSetImpl<OpOperand *> &blockingUses,
+ RewriterBase &rewriter, Value reachingDefinition) {
+ // `canUsesBeRemoved` checked this blocking use must be the loaded slot
+ // pointer.
+ rewriter.replaceAllUsesWith(getResult(), reachingDefinition);
+ return DeletionKind::Delete;
+}
+
+LogicalResult
+LoadOp::ensureOnlySafeAccesses(const MemorySlot &slot,
+ SmallVectorImpl<MemorySlot> &mustBeSafelyUsed) {
+ return success(getAddr() != slot.ptr || getType() == slot.elemType);
+}
+
+void LoadOp::getEffects(
+ SmallVectorImpl<SideEffects::EffectInstance<MemoryEffects::Effect>>
+ &effects) {
+ effects.emplace_back(MemoryEffects::Read::get(), getAddr());
+ // Volatile operations can have target-specific read-write effects on
+ // memory besides the one referred to by the pointer operand.
+ // Similarly, atomic operations that are monotonic or stricter cause
+ // synchronization that from a language point-of-view, are arbitrary
+ // read-writes into memory.
+ if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
+ getOrdering() != AtomicOrdering::unordered)) {
+ effects.emplace_back(MemoryEffects::Write::get());
+ effects.emplace_back(MemoryEffects::Read::get());
+ }
+}
+
+LogicalResult LoadOp::verify() {
+ Type valueType = getResult().getType();
+ if (auto ms = dyn_cast_or_null<MemorySpaceAttrInterface>(
+ getAddr().getType().getMemorySpace());
+ ms && !ms.isValidLoad(valueType))
+ return emitError("incompatible load type");
+ return success();
+}
+
+void LoadOp::build(OpBuilder &builder, OperationState &state, Type type,
+ Value addr, unsigned alignment, bool isVolatile,
+ bool isNonTemporal, AtomicOrdering ordering,
+ StringRef syncscope) {
+ build(builder, state, type, addr,
+ alignment ? builder.getI64IntegerAttr(alignment) : nullptr, isVolatile,
+ isNonTemporal, ordering,
+ syncscope.empty() ? nullptr : builder.getStringAttr(syncscope));
+}
+
+#include "mlir/Dialect/Ptr/IR/PtrOpsDialect.cpp.inc"
+
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.cpp.inc"
+
+#include "mlir/Dialect/Ptr/IR/PtrOpsEnums.cpp.inc"
+
+#define GET_ATTRDEF_CLASSES
+#include "mlir/Dialect/Ptr/IR/PtrOpsAttributes.cpp.inc"
+
+#define GET_TYPEDEF_CLASSES
+#include "mlir/Dialect/Ptr/IR/PtrOpsTypes.cpp.inc"
+
+#define GET_OP_CLASSES
+#include "mlir/Dialect/Ptr/IR/PtrOps.cpp.inc"
diff --git a/mlir/lib/IR/AsmPrinter.cpp b/mlir/lib/IR/AsmPrinter.cpp
index 6a67fc707b4976b..c26f0f1d4acbb9c 100644
--- a/mlir/lib/IR/AsmPrinter.cpp
+++ b/mlir/lib/IR/AsmPrinter.cpp
@@ -2703,7 +2703,10 @@ void AsmPrinter::Impl::printDialectAttribute(Attribute attr) {
}
void AsmPrinter::Impl::printDialectType(Type type) {
- auto &dialect = type.getDialect();
+ Dialect *dialectPtr = &type.getDialect();
+ if (auto ifce = dyn_cast<SharedDialectTypeInterface>(type))
+ dialectPtr = &ifce.getSharedDialect();
+ auto &dialect = *dialectPtr;
// Ask the dialect to serialize the type to a string.
std::string typeName;
diff --git a/mlir/lib/Target/LLVMIR/CMakeLists.txt b/mlir/lib/Target/LLVMIR/CMakeLists.txt
index 5db0885d70d6e7a..d402b8413865d86 100644
--- a/mlir/lib/Target/LLVMIR/CMakeLists.txt
+++ b/mlir/lib/Target/LLVMIR/CMakeLists.txt
@@ -57,6 +57,7 @@ add_mlir_translation_library(MLIRToLLVMIRTranslationRegistration
MLIRNVVMToLLVMIRTranslation
MLIROpenACCToLLVMIRTranslation
MLIROpenMPToLLVMIRTranslation
+ MLIRPtrToLLVMIRTranslation
MLIRROCDLToLLVMIRTranslation
)
diff --git a/mlir/lib/Target/LLVMIR/Dialect/CMakeLists.txt b/mlir/lib/Target/LLVMIR/Dialect/CMakeLists.txt
index fb0e5cd0649f636..3bdaa7145270057 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/CMakeLists.txt
+++ b/mlir/lib/Target/LLVMIR/Dialect/CMakeLists.txt
@@ -8,5 +8,6 @@ add_subdirectory(LLVMIR)
add_subdirectory(NVVM)
add_subdirectory(OpenACC)
add_subdirectory(OpenMP)
+add_subdirectory(Ptr)
add_subdirectory(ROCDL)
add_subdirectory(X86Vector)
diff --git a/mlir/lib/Target/LLVMIR/Dialect/Ptr/CMakeLists.txt b/mlir/lib/Target/LLVMIR/Dialect/Ptr/CMakeLists.txt
new file mode 100644
index 000000000000000..c40b47bbdff3390
--- /dev/null
+++ b/mlir/lib/Target/LLVMIR/Dialect/Ptr/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_mlir_translation_library(MLIRPtrToLLVMIRTranslation
+ PtrToLLVMIRTranslation.cpp
+
+ LINK_COMPONENTS
+ Core
+
+ LINK_LIBS PUBLIC
+ MLIRIR
+ MLIRPtrDialect
+ MLIRSupport
+ MLIRTargetLLVMIRExport
+ )
\ No newline at end of file
diff --git a/mlir/lib/Target/LLVMIR/Dialect/Ptr/PtrToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/Ptr/PtrToLLVMIRTranslation.cpp
new file mode 100644
index 000000000000000..4fc5aa3d372f86f
--- /dev/null
+++ b/mlir/lib/Target/LLVMIR/Dialect/Ptr/PtrToLLVMIRTranslation.cpp
@@ -0,0 +1,84 @@
+//===- PtrToLLVMIRTranslation.cpp - Translate Ptr dialect to LLVM IR ------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a translation between the MLIR Ptr dialect and LLVM IR.
+//
+//===----------------------------------------------------------------------===//
+#include "mlir/Target/LLVMIR/Dialect/Ptr/PtrToLLVMIRTranslation.h"
+#include "mlir/Dialect/Ptr/IR/PtrOps.h"
+#include "mlir/Target/LLVMIR/LLVMTranslationInterface.h"
+#include "mlir/Target/LLVMIR/ModuleTranslation.h"
+#include "llvm/ADT/TypeSwitch.h"
+
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/MDBuilder.h"
+
+using namespace mlir;
+using namespace mlir::ptr;
+
+namespace {
+LogicalResult convertLoadOp(LoadOp op, llvm::IRBuilderBase &builder,
+ LLVM::ModuleTranslation &moduleTranslation) {
+
+ auto *inst = builder.CreateLoad(
+ moduleTranslation.convertType(op.getResult().getType()),
+ moduleTranslation.lookupValue(op.getAddr()), op.getVolatile_());
+ moduleTranslation.mapValue(op.getRes()) = inst;
+
+ if (op.getSyncscope().has_value()) {
+ llvm::LLVMContext &llvmContext = builder.getContext();
+ inst->setSyncScopeID(
+ llvmContext.getOrInsertSyncScopeID(*op.getSyncscope()));
+ }
+
+ if (op.getAlignment().has_value()) {
+ auto align = *op.getAlignment();
+ if (align != 0)
+ inst->setAlignment(llvm::Align(align));
+ }
+
+ if (op.getNontemporal()) {
+ llvm::MDNode *metadata = llvm::MDNode::get(
+ inst->getContext(), llvm::ConstantAsMetadata::get(builder.getInt32(1)));
+ inst->setMetadata(llvm::LLVMContext::MD_nontemporal, metadata);
+ }
+ return success();
+}
+
+class PtrDialectLLVMIRTranslationInterface
+ : public LLVMTranslationDialectInterface {
+public:
+ using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface;
+
+ LogicalResult
+ convertOperation(Operation *operation, llvm::IRBuilderBase &builder,
+ LLVM::ModuleTranslation &moduleTranslation) const override {
+ return llvm::TypeSwitch<Operation *, LogicalResult>(operation)
+ .Case([&](ptr::LoadOp op) {
+ return convertLoadOp(op, builder, moduleTranslation);
+ })
+ .Default([&](Operation *op) {
+ return op->emitError("unsupported Ptr operation: ") << op->getName();
+ });
+ }
+};
+
+} // namespace
+
+void mlir::registerPtrDialectTranslation(DialectRegistry ®istry) {
+ registry.insert<ptr::PtrDialect>();
+ registry.addExtension(+[](MLIRContext *ctx, ptr::PtrDialect *dialect) {
+ dialect->addInterfaces<PtrDialectLLVMIRTranslationInterface>();
+ });
+}
+
+void mlir::registerPtrDialectTranslation(MLIRContext &context) {
+ DialectRegistry registry;
+ registerPtrDialectTranslation(registry);
+ context.appendDialectRegistry(registry);
+}
diff --git a/mlir/lib/Target/LLVMIR/TypeToLLVM.cpp b/mlir/lib/Target/LLVMIR/TypeToLLVM.cpp
index 6d8b415ff09dceb..c040ff2f0369a20 100644
--- a/mlir/lib/Target/LLVMIR/TypeToLLVM.cpp
+++ b/mlir/lib/Target/LLVMIR/TypeToLLVM.cpp
@@ -8,6 +8,7 @@
#include "mlir/Target/LLVMIR/TypeToLLVM.h"
#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
+#include "mlir/Dialect/Ptr/IR/PtrTypes.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/MLIRContext.h"
@@ -71,7 +72,7 @@ class TypeToLLVMIRTranslatorImpl {
return llvm::Type::getMetadataTy(context);
})
.Case<LLVM::LLVMArrayType, IntegerType, LLVM::LLVMFunctionType,
- LLVM::LLVMPointerType, LLVM::LLVMStructType,
+ LLVM::LLVMPointerType, ptr::PtrType, LLVM::LLVMStructType,
LLVM::LLVMFixedVectorType, LLVM::LLVMScalableVectorType,
VectorType, LLVM::LLVMTargetExtType>(
[this](auto type) { return this->translate(type); })
@@ -109,6 +110,11 @@ class TypeToLLVMIRTranslatorImpl {
return llvm::PointerType::get(context, type.getAddressSpace());
}
+ /// Translates the given pointer type.
+ llvm::Type *translate(ptr::PtrType type) {
+ return llvm::PointerType::get(context, type.getAddressSpace());
+ }
+
/// Translates the given structure type, supports both identified and literal
/// structs. This will _create_ a new identified structure every time, use
/// `convertType` if a structure with the same name must be looked up instead.
More information about the Mlir-commits
mailing list