Skip to content

[CIR] Infrastructure and MemorySpaceAttrInterface for Address Spaces - #179073

Merged
RiverDave merged 9 commits into
mainfrom
users/riverdave/memspaceattr-for-asattr
Feb 28, 2026
Merged

RiverDave merged 9 commits into
mainfrom
users/riverdave/memspaceattr-for-asattr

Conversation

@RiverDave

@RiverDave RiverDave commented Jan 31, 2026

Copy link
Copy Markdown
Contributor

Related: #175871, #179278, #160386

  • Introducing the LangAddressSpace enum with offload address space kinds (offload_private, offload_local, offload_global, offload_constant, offload_generic) and the LangAddressSpaceAttr attribute.

  • Generalizes CIR AS attributes as MemorySpaceAttrInterface and Attaches it to PointerType. Includes test coverage for valid IR roundtrips and invalid address space parsing.

This starts a series of patches with the purpose of bringing complete address spaces support features for CIR. Most of the test coverage is provided in subsequent patches further down the stack. note that most of these patches are based on: llvm/clangir#1986

@RiverDave RiverDave changed the title [CIR] Implement MemorySpaceAttrInterface for lang and target specific AS attributes [CIR] Implement MemorySpaceAttrInterface for Lang and Target specific AS attributes Jan 31, 2026
@github-actions

github-actions Bot commented Jan 31, 2026

Copy link
Copy Markdown

✅ With the latest revision this PR passed the C/C++ code formatter.

@RiverDave
RiverDave requested a review from koparasy January 31, 2026 22:38
@RiverDave
RiverDave force-pushed the users/riverdave/memspaceattr-for-asattr branch from 9ddd795 to 5cba86c Compare January 31, 2026 22:48
@RiverDave RiverDave changed the title [CIR] Implement MemorySpaceAttrInterface for Lang and Target specific AS attributes [CIR] Attach MemorySpaceAttrInterface for Lang and Target specific AS attributes Feb 1, 2026
Comment thread clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp Outdated
@RiverDave
RiverDave marked this pull request as ready for review February 1, 2026 16:06
@llvmbot llvmbot added clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project labels Feb 1, 2026
@llvmbot

llvmbot commented Feb 1, 2026

Copy link
Copy Markdown
Member

@llvm/pr-subscribers-clangir

@llvm/pr-subscribers-clang

Author: David Rivera (RiverDave)

Changes

Makes both LangAddressSpaceAttr and TargetAddressSpaceAttr implement MLIR's MemorySpaceAttrInterface. Includes test coverage for valid IR roundtrips and invalid address space parsing.


Patch is 25.48 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/179073.diff

15 Files Affected:

  • (modified) clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h (+9-11)
  • (modified) clang/include/clang/CIR/Dialect/IR/CIRAttrs.td (+1-1)
  • (modified) clang/include/clang/CIR/Dialect/IR/CIRTypes.h (+11-4)
  • (modified) clang/include/clang/CIR/Dialect/IR/CIRTypes.td (+6-4)
  • (modified) clang/lib/CIR/CodeGen/Address.h (+2-1)
  • (modified) clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp (+1-1)
  • (modified) clang/lib/CIR/CodeGen/CIRGenExpr.cpp (+5-11)
  • (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+3-2)
  • (modified) clang/lib/CIR/CodeGen/CIRGenTypeCache.h (+3-2)
  • (modified) clang/lib/CIR/CodeGen/TargetInfo.cpp (+4-2)
  • (modified) clang/lib/CIR/CodeGen/TargetInfo.h (+6-5)
  • (modified) clang/lib/CIR/Dialect/IR/CIRTypes.cpp (+45-44)
  • (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+20-3)
  • (added) clang/test/CIR/IR/address-space.cir (+41)
  • (modified) clang/test/CIR/IR/invalid-addrspace.cir (+29-3)
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 2aaae86240cf2..345507d3402e9 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -153,29 +153,27 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
     return cir::PointerType::get(ty);
   }
 
-  cir::PointerType getPointerTo(mlir::Type ty, cir::TargetAddressSpaceAttr as) {
+  cir::PointerType getPointerTo(mlir::Type ty,
+                                mlir::ptr::MemorySpaceAttrInterface as) {
+    if (!as)
+      return cir::PointerType::get(ty);
     return cir::PointerType::get(ty, as);
   }
 
   cir::PointerType getPointerTo(mlir::Type ty, clang::LangAS langAS) {
-    if (langAS == clang::LangAS::Default) // Default address space.
+    if (langAS == clang::LangAS::Default)
       return getPointerTo(ty);
 
-    if (clang::isTargetAddressSpace(langAS)) {
-      unsigned addrSpace = clang::toTargetAddressSpace(langAS);
-      auto asAttr = cir::TargetAddressSpaceAttr::get(
-          getContext(), getUI32IntegerAttr(addrSpace));
-      return getPointerTo(ty, asAttr);
-    }
-
-    llvm_unreachable("language-specific address spaces NYI");
+    mlir::ptr::MemorySpaceAttrInterface addrSpaceAttr =
+        cir::toCIRAddressSpaceAttr(getContext(), langAS);
+    return getPointerTo(ty, addrSpaceAttr);
   }
 
   cir::PointerType getVoidPtrTy(clang::LangAS langAS = clang::LangAS::Default) {
     return getPointerTo(cir::VoidType::get(getContext()), langAS);
   }
 
-  cir::PointerType getVoidPtrTy(cir::TargetAddressSpaceAttr as) {
+  cir::PointerType getVoidPtrTy(mlir::ptr::MemorySpaceAttrInterface as) {
     return getPointerTo(cir::VoidType::get(getContext()), as);
   }
 
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 4fbab2e83663d..0ab45f776f822 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -838,7 +838,7 @@ def CIR_TargetAddressSpaceAttr : CIR_Attr< "TargetAddressSpace",
     ```
   }];
 
-  let parameters = (ins "mlir::IntegerAttr":$value);
+  let parameters = (ins "unsigned":$value);
   let assemblyFormat = "`<` `target` `<` $value `>` `>`";
 }
 
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h
index 16c48ba4fb4e9..eee4140ba2801 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h
@@ -47,12 +47,19 @@ bool isSized(mlir::Type ty);
 
 cir::LangAddressSpace toCIRLangAddressSpace(clang::LangAS langAS);
 
-cir::TargetAddressSpaceAttr toCIRTargetAddressSpace(mlir::MLIRContext &context,
-                                                    clang::LangAS langAS);
-
-bool isMatchingAddressSpace(cir::TargetAddressSpaceAttr cirAS,
+// Compare a CIR memory space attribute with a Clang LangAS.
+bool isMatchingAddressSpace(mlir::MLIRContext &ctx,
+                            mlir::ptr::MemorySpaceAttrInterface cirAS,
                             clang::LangAS as);
 
+/// Convert an AST LangAS to the appropriate CIR address space attribute
+/// interface.
+mlir::ptr::MemorySpaceAttrInterface
+toCIRAddressSpaceAttr(mlir::MLIRContext *ctx, clang::LangAS langAS);
+
+bool isSupportedCIRMemorySpaceAttr(
+    mlir::ptr::MemorySpaceAttrInterface memorySpace);
+
 } // namespace cir
 
 //===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index 5ba7726e9b1a6..a940047f38acf 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -252,19 +252,19 @@ def CIR_PointerType : CIR_Type<"Pointer", "ptr", [
   let parameters = (ins
     "mlir::Type":$pointee,
     OptionalParameter<
-        "cir::TargetAddressSpaceAttr">:$addrSpace
+        "mlir::ptr::MemorySpaceAttrInterface">:$addrSpace
   );
 
   let skipDefaultBuilders = 1;
   let builders = [
     TypeBuilderWithInferredContext<(ins
       "mlir::Type":$pointee,
-       CArg<"cir::TargetAddressSpaceAttr", "nullptr">:$addrSpace), [{
+       CArg<"mlir::ptr::MemorySpaceAttrInterface", "{}">:$addrSpace), [{
         return $_get(pointee.getContext(), pointee, addrSpace);
     }]>,
     TypeBuilder<(ins
       "mlir::Type":$pointee,
-      CArg<"cir::TargetAddressSpaceAttr", "nullptr">:$addrSpace), [{
+      CArg<"mlir::ptr::MemorySpaceAttrInterface", "{}">:$addrSpace), [{
         return $_get($_ctxt, pointee, addrSpace);
     }]>
   ];
@@ -272,7 +272,7 @@ def CIR_PointerType : CIR_Type<"Pointer", "ptr", [
   let assemblyFormat = [{
     `<`
       $pointee
-      ( `,` ` ` custom<TargetAddressSpace>($addrSpace)^ )?
+      ( `,` ` ` custom<AddressSpaceValue>($addrSpace)^ )?
     `>`
   }];
 
@@ -303,6 +303,8 @@ def CIR_PointerType : CIR_Type<"Pointer", "ptr", [
       return false;
     }
   }];
+
+  let genVerifyDecl = 1;
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/Address.h b/clang/lib/CIR/CodeGen/Address.h
index f32cde957cd5c..b459ec948c2c4 100644
--- a/clang/lib/CIR/CodeGen/Address.h
+++ b/clang/lib/CIR/CodeGen/Address.h
@@ -14,6 +14,7 @@
 #ifndef CLANG_LIB_CIR_ADDRESS_H
 #define CLANG_LIB_CIR_ADDRESS_H
 
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
 #include "mlir/IR/Value.h"
 #include "clang/AST/CharUnits.h"
 #include "clang/CIR/Dialect/IR/CIRAttrs.h"
@@ -127,7 +128,7 @@ class Address {
     return elementType;
   }
 
-  cir::TargetAddressSpaceAttr getAddressSpace() const {
+  mlir::ptr::MemorySpaceAttrInterface getAddressSpace() const {
     auto ptrTy = mlir::dyn_cast<cir::PointerType>(getType());
     return ptrTy.getAddrSpace();
   }
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 0e5a5b531df78..474d2c0d00c8f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -338,7 +338,7 @@ static RValue emitBuiltinAlloca(CIRGenFunction &cgf, const CallExpr *e,
   // builtin / dynamic alloca we have to handle it here.
 
   if (!cir::isMatchingAddressSpace(
-          cgf.getCIRAllocaAddressSpace(),
+          cgf.getMLIRContext(), cgf.getCIRAllocaAddressSpace(),
           e->getType()->getPointeeType().getAddressSpace())) {
     cgf.cgm.errorNYI(e->getSourceRange(),
                      "Non-default address space for alloca");
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 504f18e1a9f31..ce0e62164029a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -15,6 +15,7 @@
 #include "CIRGenFunction.h"
 #include "CIRGenModule.h"
 #include "CIRGenValue.h"
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
 #include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/IR/Value.h"
 #include "clang/AST/Attr.h"
@@ -1437,9 +1438,9 @@ LValue CIRGenFunction::emitCastLValue(const CastExpr *e) {
     QualType destTy = getContext().getPointerType(e->getType());
 
     clang::LangAS srcLangAS = e->getSubExpr()->getType().getAddressSpace();
-    cir::TargetAddressSpaceAttr srcAS;
+    mlir::ptr::MemorySpaceAttrInterface srcAS;
     if (clang::isTargetAddressSpace(srcLangAS))
-      srcAS = cir::toCIRTargetAddressSpace(getMLIRContext(), srcLangAS);
+      srcAS = cir::toCIRAddressSpaceAttr(&getMLIRContext(), srcLangAS);
     else
       cgm.errorNYI(
           e->getSourceRange(),
@@ -2486,15 +2487,8 @@ Address CIRGenFunction::createTempAlloca(mlir::Type ty, CharUnits align,
   // in C++ the auto variables are in the default address space. Therefore
   // cast alloca to the default address space when necessary.
 
-  LangAS allocaAS = alloca.getAddressSpace()
-                        ? clang::getLangASFromTargetAS(
-                              alloca.getAddressSpace().getValue().getUInt())
-                        : clang::LangAS::Default;
-  LangAS dstTyAS = clang::LangAS::Default;
-  if (getCIRAllocaAddressSpace()) {
-    dstTyAS = clang::getLangASFromTargetAS(
-        getCIRAllocaAddressSpace().getValue().getUInt());
-  }
+  mlir::ptr::MemorySpaceAttrInterface allocaAS = alloca.getAddressSpace();
+  mlir::ptr::MemorySpaceAttrInterface dstTyAS = getCIRAllocaAddressSpace();
 
   if (dstTyAS != allocaAS) {
     getTargetHooks().performAddrSpaceCast(*this, v, getCIRAllocaAddressSpace(),
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 2af210bed98ff..62d9117562e8b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -19,6 +19,7 @@
 #include "clang/CIR/Dialect/IR/CIRTypes.h"
 #include "clang/CIR/MissingFeatures.h"
 
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
 #include "mlir/IR/Location.h"
 #include "mlir/IR/Value.h"
 
@@ -2143,9 +2144,9 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
       srcTy = srcTy->getPointeeType();
 
     clang::LangAS srcLangAS = srcTy.getAddressSpace();
-    cir::TargetAddressSpaceAttr subExprAS;
+    mlir::ptr::MemorySpaceAttrInterface subExprAS;
     if (clang::isTargetAddressSpace(srcLangAS))
-      subExprAS = cir::toCIRTargetAddressSpace(cgf.getMLIRContext(), srcLangAS);
+      subExprAS = cir::toCIRAddressSpaceAttr(&cgf.getMLIRContext(), srcLangAS);
     else
       cgf.cgm.errorNYI(subExpr->getSourceRange(),
                        "non-target address space conversion");
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypeCache.h b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h
index 0f63e91f45564..4f3c319816e3a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypeCache.h
+++ b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h
@@ -13,6 +13,7 @@
 #ifndef LLVM_CLANG_LIB_CIR_CIRGENTYPECACHE_H
 #define LLVM_CLANG_LIB_CIR_CIRGENTYPECACHE_H
 
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
 #include "clang/AST/CharUnits.h"
 #include "clang/Basic/AddressSpaces.h"
 #include "clang/CIR/Dialect/IR/CIRTypes.h"
@@ -80,7 +81,7 @@ struct CIRGenTypeCache {
     unsigned char SizeAlignInBytes;
   };
 
-  cir::TargetAddressSpaceAttr cirAllocaAddressSpace;
+  mlir::ptr::MemorySpaceAttrInterface cirAllocaAddressSpace;
 
   clang::CharUnits getSizeSize() const {
     return clang::CharUnits::fromQuantity(SizeSizeInBytes);
@@ -93,7 +94,7 @@ struct CIRGenTypeCache {
     return clang::CharUnits::fromQuantity(PointerAlignInBytes);
   }
 
-  cir::TargetAddressSpaceAttr getCIRAllocaAddressSpace() const {
+  mlir::ptr::MemorySpaceAttrInterface getCIRAllocaAddressSpace() const {
     return cirAllocaAddressSpace;
   }
 };
diff --git a/clang/lib/CIR/CodeGen/TargetInfo.cpp b/clang/lib/CIR/CodeGen/TargetInfo.cpp
index 377c532e492d9..b009478695f1b 100644
--- a/clang/lib/CIR/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CIR/CodeGen/TargetInfo.cpp
@@ -1,6 +1,7 @@
 #include "TargetInfo.h"
 #include "ABIInfo.h"
 #include "CIRGenFunction.h"
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
 #include "clang/CIR/Dialect/IR/CIRAttrs.h"
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
 
@@ -73,8 +74,9 @@ bool TargetCIRGenInfo::isNoProtoCallVariadic(
 }
 
 mlir::Value TargetCIRGenInfo::performAddrSpaceCast(
-    CIRGenFunction &cgf, mlir::Value v, cir::TargetAddressSpaceAttr srcAddr,
-    mlir::Type destTy, bool isNonNull) const {
+    CIRGenFunction &cgf, mlir::Value v,
+    mlir::ptr::MemorySpaceAttrInterface srcAS, mlir::Type destTy,
+    bool isNonNull) const {
   // Since target may map different address spaces in AST to the same address
   // space, an address space conversion may end up as a bitcast.
   if (cir::GlobalOp globalOp = v.getDefiningOp<cir::GlobalOp>())
diff --git a/clang/lib/CIR/CodeGen/TargetInfo.h b/clang/lib/CIR/CodeGen/TargetInfo.h
index 9535ba94fb08b..25bde654810ad 100644
--- a/clang/lib/CIR/CodeGen/TargetInfo.h
+++ b/clang/lib/CIR/CodeGen/TargetInfo.h
@@ -16,6 +16,7 @@
 
 #include "ABIInfo.h"
 #include "CIRGenTypes.h"
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
 #include "clang/Basic/AddressSpaces.h"
 #include "clang/CIR/Dialect/IR/CIRAttrs.h"
 
@@ -48,7 +49,7 @@ class TargetCIRGenInfo {
   const ABIInfo &getABIInfo() const { return *info; }
 
   /// Get the address space for alloca.
-  virtual cir::TargetAddressSpaceAttr getCIRAllocaAddressSpace() const {
+  virtual mlir::ptr::MemorySpaceAttrInterface getCIRAllocaAddressSpace() const {
     return {};
   }
   /// Perform address space cast of an expression of pointer type.
@@ -56,10 +57,10 @@ class TargetCIRGenInfo {
   /// \param DestTy is the destination pointer type.
   /// \param srcAS is theaddress space of \p V.
   /// \param IsNonNull is the flag indicating \p V is known to be non null.
-  virtual mlir::Value performAddrSpaceCast(CIRGenFunction &cgf, mlir::Value v,
-                                           cir::TargetAddressSpaceAttr srcAddr,
-                                           mlir::Type destTy,
-                                           bool isNonNull = false) const;
+  virtual mlir::Value
+  performAddrSpaceCast(CIRGenFunction &cgf, mlir::Value v,
+                       mlir::ptr::MemorySpaceAttrInterface srcAS,
+                       mlir::Type destTy, bool isNonNull = false) const;
 
   /// Determine whether a call to an unprototyped functions under
   /// the given calling convention should use the variadic
diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
index 8d97a8d5c88cd..42445a07864d8 100644
--- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
@@ -12,12 +12,15 @@
 
 #include "clang/CIR/Dialect/IR/CIRTypes.h"
 
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
 #include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/IR/DialectImplementation.h"
 #include "mlir/IR/MLIRContext.h"
+#include "mlir/Support/LLVM.h"
 #include "clang/Basic/AddressSpaces.h"
 #include "clang/CIR/Dialect/IR/CIRAttrs.h"
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
 #include "clang/CIR/Dialect/IR/CIRTypesDetails.h"
 #include "clang/CIR/MissingFeatures.h"
 #include "llvm/ADT/APInt.h"
@@ -941,6 +944,12 @@ void cir::VectorType::print(mlir::AsmPrinter &odsPrinter) const {
 // AddressSpace definitions
 //===----------------------------------------------------------------------===//
 
+bool cir::isSupportedCIRMemorySpaceAttr(
+    mlir::ptr::MemorySpaceAttrInterface memorySpace) {
+  return mlir::isa<cir::LangAddressSpaceAttr, cir::TargetAddressSpaceAttr>(
+      memorySpace);
+}
+
 cir::LangAddressSpace cir::toCIRLangAddressSpace(clang::LangAS langAS) {
   using clang::LangAS;
   switch (langAS) {
@@ -999,8 +1008,7 @@ parseAddressSpaceValue(mlir::AsmParser &p,
     if (p.parseRParen())
       return p.emitError(loc, "expected ')'");
 
-    attr = cir::TargetAddressSpaceAttr::get(
-        p.getContext(), p.getBuilder().getUI32IntegerAttr(val));
+    attr = cir::TargetAddressSpaceAttr::get(p.getContext(), val);
     return mlir::success();
   }
 
@@ -1012,7 +1020,7 @@ parseAddressSpaceValue(mlir::AsmParser &p,
     mlir::FailureOr<cir::LangAddressSpace> result =
         mlir::FieldParser<cir::LangAddressSpace>::parse(p);
     if (mlir::failed(result))
-      return p.emitError(loc, "expected language address space keyword");
+      return mlir::failure();
 
     if (p.parseRParen())
       return p.emitError(loc, "expected ')'");
@@ -1021,6 +1029,12 @@ parseAddressSpaceValue(mlir::AsmParser &p,
     return mlir::success();
   }
 
+  llvm::StringRef keyword;
+  if (p.parseOptionalKeyword(&keyword).succeeded())
+    return p.emitError(loc, "unknown address space specifier '")
+           << keyword << "'; expected 'target_address_space' or "
+           << "'lang_address_space'";
+
   return mlir::success();
 }
 
@@ -1043,55 +1057,42 @@ void printAddressSpaceValue(mlir::AsmPrinter &p,
   llvm_unreachable("unexpected address-space attribute kind");
 }
 
-cir::TargetAddressSpaceAttr
-cir::toCIRTargetAddressSpace(mlir::MLIRContext &context, clang::LangAS langAS) {
-  return cir::TargetAddressSpaceAttr::get(
-      &context,
-      IntegerAttr::get(&context,
-                       llvm::APSInt(clang::toTargetAddressSpace(langAS))));
-}
+mlir::ptr::MemorySpaceAttrInterface
+cir::toCIRAddressSpaceAttr(mlir::MLIRContext *ctx, clang::LangAS langAS) {
+  using clang::LangAS;
 
-bool cir::isMatchingAddressSpace(cir::TargetAddressSpaceAttr cirAS,
-                                 clang::LangAS as) {
-  // If there is no CIR target attr, consider it "default" and only match
-  // when the AST address space is LangAS::Default.
-  if (!cirAS)
-    return as == clang::LangAS::Default;
+  if (langAS == LangAS::Default)
+    return {}; // Default address space is represented as an empty attribute.
 
-  if (!isTargetAddressSpace(as))
-    return false;
+  if (clang::isTargetAddressSpace(langAS)) {
+    unsigned targetAS = clang::toTargetAddressSpace(langAS);
+    return cir::TargetAddressSpaceAttr::get(ctx, targetAS);
+  }
 
-  return cirAS.getValue().getUInt() == toTargetAddressSpace(as);
+  return cir::LangAddressSpaceAttr::get(ctx, toCIRLangAddressSpace(langAS));
 }
 
-mlir::ParseResult parseTargetAddressSpace(mlir::AsmParser &p,
-                                          cir::TargetAddressSpaceAttr &attr) {
-  if (failed(p.parseKeyword("target_address_space")))
-    return mlir::failure();
-
-  if (failed(p.parseLParen()))
-    return mlir::failure();
-
-  int32_t targetValue;
-  if (failed(p.parseInteger(targetValue)))
-    return p.emitError(p.getCurrentLocation(),
-                       "expected integer address space value");
+bool cir::isMatchingAddressSpace(mlir::MLIRContext &ctx,
+                                 mlir::ptr::MemorySpaceAttrInterface cirAS,
+                                 clang::LangAS as) {
+  return cir::toCIRAddressSpaceAttr(&ctx, as) == cirAS;
+}
 
-  if (failed(p.parseRParen()))
-    return p.emitError(p.getCurrentLocation(),
-                       "expected ')' after address space value");
+//===----------------------------------------------------------------------===//
+// PointerType Definitions
+//===----------------------------------------------------------------------===//
 
-  mlir::MLIRContext *context = p.getBuilder().getContext();
-  attr = cir::TargetAddressSpaceAttr::get(
-      context, p.getBuilder().getUI32IntegerAttr(targetValue));
-  return mlir::success();
-}
+mlir::LogicalResult cir::PointerType::verify(
+    llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
+    mlir::Type pointee, mlir::ptr::MemorySpaceAttrInterface addrSpace) {
+  if (addrSpace) {
+    if (!isSupportedCIRMemorySpaceAttr(addrSpace)) {
+      return emitError() << "unsupported address space attribute; expected "
+                            "'target_address_space' or 'lang_address_space'";
+    }
+  }
 
-// The custom printer for the `addrspace` parameter in `!cir.ptr`.
-// in the format of `target_address_space(N)`.
-void printTargetAddressSpace(mlir::AsmPrinter &p,
-                             cir::TargetAddressSpaceAttr attr) {
-  p << "target_address_space(" << attr.getValue().getUInt() << ")";
+  return success();
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index a774b0dcc6ba8..584d163e15073 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -21,12 +21,14 @@
 #include "mlir/Dialect/Func/IR/FuncOps.h"
 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
 #include "mlir/Dialect/LLVMIR/LLVMTypes.h"
+#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
 #include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/IR/BuiltinDialect.h"
 #include "mlir/IR/BuiltinOps.h"
 #include "mlir/IR/Types.h"
 #include "mlir/Pass/Pass.h"
 #include "mlir/Pass/PassManager.h"
+#include "mlir/Support/LLVM.h"
 #include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
 #include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
 #include "mlir/Target/LLVMIR/Export.h"
@@ -40,6 +42,7 @@
 #include "clang/CIR/Passes.h"
 #include "llvm/ADT/TypeSwitch.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Suppor...
[truncated]

@RiverDave RiverDave changed the title [CIR] Attach MemorySpaceAttrInterface for Lang and Target specific AS attributes [CIR] Spread MemorySpaceAttrInterface for Lang and Target specific AS attributes Feb 1, 2026
@RiverDave RiverDave changed the title [CIR] Spread MemorySpaceAttrInterface for Lang and Target specific AS attributes [CIR] Propagate MemorySpaceAttrInterface for Lang and Target specific AS attributes Feb 1, 2026

@koparasy koparasy left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall it looks good to me, but I am not extremely familiar with the current address space implementation of clang OG.

Comment thread clang/include/clang/CIR/Dialect/IR/CIRTypes.h Outdated
Comment thread clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp Outdated
Comment thread clang/lib/CIR/Dialect/IR/CIRTypes.cpp Outdated
Comment on lines +1064 to +1065
if (langAS == LangAS::Default)
return {}; // Default address space is represented as an empty attribute.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opinion: I would prefer not having "default = empty", but follow some fixed value. I don't know how that would translate to the rest of the implementation.

@RiverDave RiverDave Feb 4, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that I think of, we already have an existing LanguageAddress::Default (Similar to clang::LangAs::Default). I think empty attributes made sense back when we only had support for target AS. It will affect the implementation in some places, however it shouldn't be too hard to do. Any thoughts @andykaylor ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cir::LangAddressSpace::Default sounds perfect.

Comment thread clang/lib/CIR/Dialect/IR/CIRTypes.cpp

@andykaylor andykaylor left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me after other comments are discussed/addressed.

Comment thread clang/lib/CIR/CodeGen/TargetInfo.cpp Outdated
Comment thread clang/lib/CIR/Dialect/IR/CIRTypes.cpp Outdated
@RiverDave
RiverDave changed the base branch from users/riverdave/cir-langas-infra to main February 4, 2026 20:09
@RiverDave
RiverDave force-pushed the users/riverdave/memspaceattr-for-asattr branch 2 times, most recently from 415807a to 8fee86d Compare February 4, 2026 20:25
@RiverDave RiverDave changed the title [CIR] Propagate MemorySpaceAttrInterface for Lang and Target specific AS attributes [CIR] Infrastructure and MemorySpaceAttrInterface for Address Spaces Feb 4, 2026
@RiverDave

Copy link
Copy Markdown
Contributor Author

Just squashed this with #179054 so tests for the infrastructure implemented are self-contained. Apologies to the reviewers for the messy diff!

@github-actions

github-actions Bot commented Feb 4, 2026

Copy link
Copy Markdown

🐧 Linux x64 Test Results

  • 115465 tests passed
  • 4055 tests skipped

✅ The build succeeded and all tests passed.

@andykaylor andykaylor left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry it has taken me a while to get back to this. I've been kind of buried in the exception handling stuff.

This looks good, but the performAddrSpaceCast cast stuff will need to be refactored now that #179330 has been merged.

Comment thread clang/lib/CIR/Dialect/IR/CIRTypes.cpp Outdated
Comment on lines +1064 to +1065
if (langAS == LangAS::Default)
return {}; // Default address space is represented as an empty attribute.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cir::LangAddressSpace::Default sounds perfect.

@RiverDave

RiverDave commented Feb 11, 2026

Copy link
Copy Markdown
Contributor Author

Sorry it has taken me a while to get back to this. I've been kind of buried in the exception handling stuff.

This looks good, but the performAddrSpaceCast cast stuff will need to be refactored now that #179330 has been merged.

No worries at all. I still need to fix some merge conflicts, I'll ping you once it's ready for review :)

@RiverDave
RiverDave force-pushed the users/riverdave/memspaceattr-for-asattr branch from f043eb6 to f7be6a8 Compare February 26, 2026 04:19
@RiverDave

RiverDave commented Feb 26, 2026

Copy link
Copy Markdown
Contributor Author

Okay, I've updated this once again according to the feedback - it should (Hopefully) be good to go. {} is now represented as cir::AddrSpace::Default - although this is implicitly null in the attribute builder given I implemented: skipDefaultAddressSpace. This was mainly inspired by the memref dialect handling of default AS. For reference:

https://github.com/llvm/llvm-project/blob/d12870ea96befd5b5ec69c753c82a3e4af13e472/mlir/lib/IR/TypeDetail.h#L145C11-L145C33

// Drop default memory space value and replace it with empty attribute.

@andykaylor andykaylor left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, with one minor suggestion.


/// Normalize LangAddressSpace::Default to null (empty attribute).
mlir::ptr::MemorySpaceAttrInterface
skipDefaultAddressSpace(mlir::ptr::MemorySpaceAttrInterface addrSpace);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
skipDefaultAddressSpace(mlir::ptr::MemorySpaceAttrInterface addrSpace);
normalizeAddressSpace(mlir::ptr::MemorySpaceAttrInterface addrSpace);

@RiverDave
RiverDave merged commit 0b88ee1 into main Feb 28, 2026
10 checks passed
@RiverDave
RiverDave deleted the users/riverdave/memspaceattr-for-asattr branch February 28, 2026 04:08
sahas3 pushed a commit to sahas3/llvm-project that referenced this pull request Mar 4, 2026
…lvm#179073)

Related: llvm#175871,
https://github.com/issues/assigned?issue=llvm%7Cllvm-project%7C179278,
https://github.com/issues/assigned?issue=llvm%7Cllvm-project%7C160386

- Introducing the LangAddressSpace enum with offload address space kinds
(offload_private, offload_local, offload_global, offload_constant,
offload_generic) and the LangAddressSpaceAttr attribute.


- Generalizes CIR AS attributes as MemorySpaceAttrInterface and Attaches
it to `PointerType`. Includes test coverage for valid IR roundtrips and
invalid address space parsing.

This starts a series of patches with the purpose of bringing complete
address spaces support features for CIR. Most of the test coverage is
provided in subsequent patches further down the stack. note that most of
these patches are based on: llvm/clangir#1986
sujianIBM pushed a commit to sujianIBM/llvm-project that referenced this pull request Mar 5, 2026
…lvm#179073)

Related: llvm#175871,
https://github.com/issues/assigned?issue=llvm%7Cllvm-project%7C179278,
https://github.com/issues/assigned?issue=llvm%7Cllvm-project%7C160386

- Introducing the LangAddressSpace enum with offload address space kinds
(offload_private, offload_local, offload_global, offload_constant,
offload_generic) and the LangAddressSpaceAttr attribute.


- Generalizes CIR AS attributes as MemorySpaceAttrInterface and Attaches
it to `PointerType`. Includes test coverage for valid IR roundtrips and
invalid address space parsing.

This starts a series of patches with the purpose of bringing complete
address spaces support features for CIR. Most of the test coverage is
provided in subsequent patches further down the stack. note that most of
these patches are based on: llvm/clangir#1986
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants