[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 &registry) {
                   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 &registry) {
   registerNVVMDialectTranslation(registry);
   registerOpenACCDialectTranslation(registry);
   registerOpenMPDialectTranslation(registry);
+  registerPtrDialectTranslation(registry);
   registerROCDLDialectTranslation(registry);
   registerX86VectorDialectTranslation(registry);
 
@@ -60,6 +62,7 @@ registerAllGPUToLLVMIRTranslations(DialectRegistry &registry) {
   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 &registry);
+
+/// 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 &registry) {
+  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