[clang] [CIR][CUDA] Support built-in CUDA surface type (PR #196079)
Orphic Dreamer via cfe-commits
cfe-commits at lists.llvm.org
Sun Jun 14 11:31:20 PDT 2026
https://github.com/Siya-05 updated https://github.com/llvm/llvm-project/pull/196079
>From a881019f9c4942ca96f0ea643bbc32586c8eb28a Mon Sep 17 00:00:00 2001
From: Sivapriya Venkateswarar <sivapriyaofficial2005 at gmail.com>
Date: Wed, 6 May 2026 17:36:31 +0400
Subject: [PATCH 1/7] [CIR][CUDA] Support built-in CUDA surface type
---
clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 8 ++++++++
clang/lib/CIR/CodeGen/TargetInfo.cpp | 6 ++++++
clang/lib/CIR/CodeGen/TargetInfo.h | 4 ++++
clang/test/CIR/CodeGenCUDA/surface.cu | 21 +++++++++++++++++++++
4 files changed, 39 insertions(+)
create mode 100644 clang/test/CIR/CodeGenCUDA/surface.cu
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index 85b7e854abb7f..308e1b44a6352 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -295,6 +295,14 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
type = astContext.getCanonicalType(type);
const Type *ty = type.getTypePtr();
+ if (astContext.getLangOpts().CUDAIsDevice) {
+ if (type->isCUDADeviceBuiltinSurfaceType()) {
+ if (mlir::Type ty =
+ cgm.getTargetCIRGenInfo().getCUDADeviceBuiltinSurfaceDeviceType())
+ return ty;
+ }
+ }
+
// Process record types before the type cache lookup.
if (const auto *recordType = dyn_cast<RecordType>(type))
return convertRecordDeclType(recordType->getDecl()->getDefinitionOrSelf());
diff --git a/clang/lib/CIR/CodeGen/TargetInfo.cpp b/clang/lib/CIR/CodeGen/TargetInfo.cpp
index fc939cd9605ab..a88f662e5a132 100644
--- a/clang/lib/CIR/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CIR/CodeGen/TargetInfo.cpp
@@ -132,6 +132,12 @@ class NVPTXTargetCIRGenInfo : public TargetCIRGenInfo {
public:
NVPTXTargetCIRGenInfo(CIRGenTypes &cgt)
: TargetCIRGenInfo(std::make_unique<NVPTXABIInfo>(cgt)) {}
+
+ mlir::Type getCUDADeviceBuiltinSurfaceDeviceType() const override {
+ // CUDA surface is represented as a 64-bit handle on device
+ return cir::IntType::get(&getABIInfo().cgt.getMLIRContext(), 64,
+ /*isSigned=*/true);
+ }
};
} // namespace
diff --git a/clang/lib/CIR/CodeGen/TargetInfo.h b/clang/lib/CIR/CodeGen/TargetInfo.h
index ecdfb7cb42c0e..8c00ec186ef94 100644
--- a/clang/lib/CIR/CodeGen/TargetInfo.h
+++ b/clang/lib/CIR/CodeGen/TargetInfo.h
@@ -66,6 +66,10 @@ class TargetCIRGenInfo {
cir::LangAddressSpace::Default);
}
+ virtual mlir::Type getCUDADeviceBuiltinSurfaceDeviceType() const {
+ return nullptr;
+ }
+
/// Determine whether a call to an unprototyped functions under
/// the given calling convention should use the variadic
/// convention or the non-variadic convention.
diff --git a/clang/test/CIR/CodeGenCUDA/surface.cu b/clang/test/CIR/CodeGenCUDA/surface.cu
new file mode 100644
index 0000000000000..d28f876080180
--- /dev/null
+++ b/clang/test/CIR/CodeGenCUDA/surface.cu
@@ -0,0 +1,21 @@
+// REQUIRES: x86-registered-target
+// REQUIRES: nvptx-registered-target
+// RUN: %clang_cc1 -fclangir -std=c++11 -fcuda-is-device -triple nvptx64-nvidia-cuda -emit-cir -o - %s | FileCheck --check-prefix=DEVICE-CIR %s
+// RUN: %clang_cc1 -fclangir -std=c++11 -fcuda-is-device -triple nvptx64-nvidia-cuda -emit-llvm -o - %s | FileCheck --check-prefix=DEVICE-LLVM %s
+
+struct surfaceReference {
+ int desc;
+};
+
+template <typename T, int dim = 1>
+struct __attribute__((device_builtin_surface_type)) surface
+ : public surfaceReference {};
+
+template <int dim>
+struct __attribute__((device_builtin_surface_type)) surface<void, dim>
+ : public surfaceReference {};
+
+surface<void, 2> surf;
+
+// DEVICE-CIR: cir.global external target_address_space(1) @surf = #cir.poison : !s64i
+// DEVICE-LLVM: @surf ={{.*}} addrspace(1) externally_initialized global i64 poison
\ No newline at end of file
>From 4921dc6b7761c246230591c01a7cb42560d6922f Mon Sep 17 00:00:00 2001
From: Sivapriya Venkateswarar <sivapriyaofficial2005 at gmail.com>
Date: Fri, 8 May 2026 14:12:08 +0400
Subject: [PATCH 2/7] [CIR][CUDA] Add trailing newline to surface test
---
clang/test/CIR/CodeGenCUDA/surface.cu | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/test/CIR/CodeGenCUDA/surface.cu b/clang/test/CIR/CodeGenCUDA/surface.cu
index d28f876080180..6044d63f85dd3 100644
--- a/clang/test/CIR/CodeGenCUDA/surface.cu
+++ b/clang/test/CIR/CodeGenCUDA/surface.cu
@@ -18,4 +18,4 @@ struct __attribute__((device_builtin_surface_type)) surface<void, dim>
surface<void, 2> surf;
// DEVICE-CIR: cir.global external target_address_space(1) @surf = #cir.poison : !s64i
-// DEVICE-LLVM: @surf ={{.*}} addrspace(1) externally_initialized global i64 poison
\ No newline at end of file
+// DEVICE-LLVM: @surf ={{.*}} addrspace(1) externally_initialized global i64 poison
>From b64a002698c6dddb1fe0a34f56b2bdd5d1fa20fa Mon Sep 17 00:00:00 2001
From: Sivapriya Venkateswarar <sivapriyaofficial2005 at gmail.com>
Date: Mon, 18 May 2026 07:55:35 +0400
Subject: [PATCH 3/7] [CIR][CUDA] Mark texture type as missing
---
clang/include/clang/CIR/MissingFeatures.h | 1 +
clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 3 +++
2 files changed, 4 insertions(+)
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 74902047274d1..7f800ad5ac3d0 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -238,6 +238,7 @@ struct MissingFeatures {
static bool ctorConstLvalueToRvalueConversion() { return false; }
static bool ctorMemcpyizer() { return false; }
static bool cudaSupport() { return false; }
+ static bool cudaTextureType() { return false; }
static bool hipModuleCtor() { return false; }
static bool globalRegistration() { return false; }
static bool dataLayoutTypeIsSized() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index 308e1b44a6352..d0cd751cd5d47 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -10,6 +10,7 @@
#include "clang/AST/Type.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
+#include "clang/CIR/MissingFeatures.h"
#include <cassert>
@@ -300,6 +301,8 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
if (mlir::Type ty =
cgm.getTargetCIRGenInfo().getCUDADeviceBuiltinSurfaceDeviceType())
return ty;
+ } else if (type->isCUDADeviceBuiltinTextureType()) {
+ assert(!cir::MissingFeatures::cudaTextureType());
}
}
>From e38198c55dfa2537df14bf8c26750864f164e5af Mon Sep 17 00:00:00 2001
From: Sivapriya Venkateswarar <sivapriyaofficial2005 at gmail.com>
Date: Thu, 21 May 2026 20:09:01 +0400
Subject: [PATCH 4/7] [CIR][CUDA] Add OG CodeGen comparison for surface test
---
clang/test/CIR/CodeGenCUDA/surface.cu | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/clang/test/CIR/CodeGenCUDA/surface.cu b/clang/test/CIR/CodeGenCUDA/surface.cu
index 6044d63f85dd3..a03962ed5f263 100644
--- a/clang/test/CIR/CodeGenCUDA/surface.cu
+++ b/clang/test/CIR/CodeGenCUDA/surface.cu
@@ -1,7 +1,8 @@
// REQUIRES: x86-registered-target
// REQUIRES: nvptx-registered-target
// RUN: %clang_cc1 -fclangir -std=c++11 -fcuda-is-device -triple nvptx64-nvidia-cuda -emit-cir -o - %s | FileCheck --check-prefix=DEVICE-CIR %s
-// RUN: %clang_cc1 -fclangir -std=c++11 -fcuda-is-device -triple nvptx64-nvidia-cuda -emit-llvm -o - %s | FileCheck --check-prefix=DEVICE-LLVM %s
+// RUN: %clang_cc1 -fclangir -std=c++11 -fcuda-is-device -triple nvptx64-nvidia-cuda -emit-llvm -o - %s | FileCheck --check-prefix=DEVICE-CIR-LLVM %s
+// RUN: %clang_cc1 -std=c++11 -fcuda-is-device -triple nvptx64-nvidia-cuda -emit-llvm -o - %s | FileCheck --check-prefix=DEVICE-OGCG %s
struct surfaceReference {
int desc;
@@ -18,4 +19,7 @@ struct __attribute__((device_builtin_surface_type)) surface<void, dim>
surface<void, 2> surf;
// DEVICE-CIR: cir.global external target_address_space(1) @surf = #cir.poison : !s64i
-// DEVICE-LLVM: @surf ={{.*}} addrspace(1) externally_initialized global i64 poison
+
+// CIR lowers poison to LLVM poison, while OG CodeGen emits undef.
+// DEVICE-CIR-LLVM: @surf ={{.*}} addrspace(1) externally_initialized global i64 poison
+// DEVICE-OGCG: @surf ={{.*}} addrspace(1) externally_initialized global i64 undef
\ No newline at end of file
>From decb75eeb1622a70c24d300dc9c3dbdbb7684bec Mon Sep 17 00:00:00 2001
From: Sivapriya Venkateswarar <sivapriyaofficial2005 at gmail.com>
Date: Sat, 23 May 2026 12:06:00 +0400
Subject: [PATCH 5/7] [CIR][NVPTX] Move target info to Targets directory
---
clang/lib/CIR/CodeGen/CMakeLists.txt | 1 +
clang/lib/CIR/CodeGen/TargetInfo.cpp | 25 --------------
clang/lib/CIR/CodeGen/Targets/NVPTX.cpp | 46 +++++++++++++++++++++++++
3 files changed, 47 insertions(+), 25 deletions(-)
create mode 100644 clang/lib/CIR/CodeGen/Targets/NVPTX.cpp
diff --git a/clang/lib/CIR/CodeGen/CMakeLists.txt b/clang/lib/CIR/CodeGen/CMakeLists.txt
index 7320afe626bdc..f8d7c91894a71 100644
--- a/clang/lib/CIR/CodeGen/CMakeLists.txt
+++ b/clang/lib/CIR/CodeGen/CMakeLists.txt
@@ -55,6 +55,7 @@ add_clang_library(clangCIR
CIRGenVTables.cpp
TargetInfo.cpp
Targets/AMDGPU.cpp
+ Targets/NVPTX.cpp
DEPENDS
MLIRCIR
diff --git a/clang/lib/CIR/CodeGen/TargetInfo.cpp b/clang/lib/CIR/CodeGen/TargetInfo.cpp
index a88f662e5a132..84f6d5dd2039e 100644
--- a/clang/lib/CIR/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CIR/CodeGen/TargetInfo.cpp
@@ -121,36 +121,11 @@ class X8664TargetCIRGenInfo : public TargetCIRGenInfo {
};
} // namespace
-namespace {
-
-class NVPTXABIInfo : public ABIInfo {
-public:
- NVPTXABIInfo(CIRGenTypes &cgt) : ABIInfo(cgt) {}
-};
-
-class NVPTXTargetCIRGenInfo : public TargetCIRGenInfo {
-public:
- NVPTXTargetCIRGenInfo(CIRGenTypes &cgt)
- : TargetCIRGenInfo(std::make_unique<NVPTXABIInfo>(cgt)) {}
-
- mlir::Type getCUDADeviceBuiltinSurfaceDeviceType() const override {
- // CUDA surface is represented as a 64-bit handle on device
- return cir::IntType::get(&getABIInfo().cgt.getMLIRContext(), 64,
- /*isSigned=*/true);
- }
-};
-} // namespace
-
std::unique_ptr<TargetCIRGenInfo>
clang::CIRGen::createAMDGPUTargetCIRGenInfo(CIRGenTypes &cgt) {
return std::make_unique<AMDGPUTargetCIRGenInfo>(cgt);
}
-std::unique_ptr<TargetCIRGenInfo>
-clang::CIRGen::createNVPTXTargetCIRGenInfo(CIRGenTypes &cgt) {
- return std::make_unique<NVPTXTargetCIRGenInfo>(cgt);
-}
-
std::unique_ptr<TargetCIRGenInfo>
clang::CIRGen::createX8664TargetCIRGenInfo(CIRGenTypes &cgt) {
return std::make_unique<X8664TargetCIRGenInfo>(cgt);
diff --git a/clang/lib/CIR/CodeGen/Targets/NVPTX.cpp b/clang/lib/CIR/CodeGen/Targets/NVPTX.cpp
new file mode 100644
index 0000000000000..a50f397da8e73
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/Targets/NVPTX.cpp
@@ -0,0 +1,46 @@
+//===---- NVPTX.cpp - NVPTX-specific CIR CodeGen --------------------------===//
+//
+// 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 NVPTX-specific CIR CodeGen logic.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../ABIInfo.h"
+#include "../TargetInfo.h"
+
+#include "clang/CIR/Dialect/IR/CIRTypes.h"
+
+using namespace clang;
+using namespace clang::CIRGen;
+
+namespace {
+
+class NVPTXABIInfo : public ABIInfo {
+public:
+ NVPTXABIInfo(CIRGenTypes &cgt) : ABIInfo(cgt) {}
+};
+
+class NVPTXTargetCIRGenInfo : public TargetCIRGenInfo {
+public:
+ NVPTXTargetCIRGenInfo(CIRGenTypes &cgt)
+ : TargetCIRGenInfo(std::make_unique<NVPTXABIInfo>(cgt)) {}
+
+ mlir::Type getCUDADeviceBuiltinSurfaceDeviceType() const override {
+ // On the device side, surface reference is represented as an object handle
+ // in 64-bit integer.
+ return cir::IntType::get(&getABIInfo().cgt.getMLIRContext(), 64,
+ /*isSigned=*/true);
+ }
+};
+
+} // namespace
+
+std::unique_ptr<TargetCIRGenInfo>
+clang::CIRGen::createNVPTXTargetCIRGenInfo(CIRGenTypes &cgt) {
+ return std::make_unique<NVPTXTargetCIRGenInfo>(cgt);
+}
>From bbaf731929872e19dde9da79c75d11fbff6e58b1 Mon Sep 17 00:00:00 2001
From: Sivapriya Venkateswarar <sivapriyaofficial2005 at gmail.com>
Date: Sun, 7 Jun 2026 20:19:42 +0400
Subject: [PATCH 6/7] CIR: fix test nits (RUN order, trailing newline)
---
clang/test/CIR/CodeGenCUDA/surface.cu | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/clang/test/CIR/CodeGenCUDA/surface.cu b/clang/test/CIR/CodeGenCUDA/surface.cu
index a03962ed5f263..5da6ea0079fdc 100644
--- a/clang/test/CIR/CodeGenCUDA/surface.cu
+++ b/clang/test/CIR/CodeGenCUDA/surface.cu
@@ -1,8 +1,8 @@
// REQUIRES: x86-registered-target
// REQUIRES: nvptx-registered-target
-// RUN: %clang_cc1 -fclangir -std=c++11 -fcuda-is-device -triple nvptx64-nvidia-cuda -emit-cir -o - %s | FileCheck --check-prefix=DEVICE-CIR %s
-// RUN: %clang_cc1 -fclangir -std=c++11 -fcuda-is-device -triple nvptx64-nvidia-cuda -emit-llvm -o - %s | FileCheck --check-prefix=DEVICE-CIR-LLVM %s
-// RUN: %clang_cc1 -std=c++11 -fcuda-is-device -triple nvptx64-nvidia-cuda -emit-llvm -o - %s | FileCheck --check-prefix=DEVICE-OGCG %s
+// RUN: %clang_cc1 -fclangir -std=c++11 -fcuda-is-device -triple nvptx64-nvidia-cuda -emit-cir -o - %s | FileCheck --check-prefix=CIR-DEVICE %s
+// RUN: %clang_cc1 -fclangir -std=c++11 -fcuda-is-device -triple nvptx64-nvidia-cuda -emit-llvm -o - %s | FileCheck --check-prefix=LLVM-DEVICE %s
+// RUN: %clang_cc1 -std=c++11 -fcuda-is-device -triple nvptx64-nvidia-cuda -emit-llvm -o - %s | FileCheck --check-prefix=OGCG-DEVICE %s
struct surfaceReference {
int desc;
@@ -18,8 +18,8 @@ struct __attribute__((device_builtin_surface_type)) surface<void, dim>
surface<void, 2> surf;
-// DEVICE-CIR: cir.global external target_address_space(1) @surf = #cir.poison : !s64i
+// CIR-DEVICE: cir.global external target_address_space(1) @surf = #cir.poison : !s64i
// CIR lowers poison to LLVM poison, while OG CodeGen emits undef.
-// DEVICE-CIR-LLVM: @surf ={{.*}} addrspace(1) externally_initialized global i64 poison
-// DEVICE-OGCG: @surf ={{.*}} addrspace(1) externally_initialized global i64 undef
\ No newline at end of file
+// LLVM-DEVICE: @surf ={{.*}} addrspace(1) externally_initialized global i64 poison
+// OGCG-DEVICE: @surf ={{.*}} addrspace(1) externally_initialized global i64 undef
>From 27be0d238e2d445b8e9f0f842026146447689d65 Mon Sep 17 00:00:00 2001
From: Sivapriya Venkateswarar <sivapriyaofficial2005 at gmail.com>
Date: Sun, 14 Jun 2026 15:57:47 +0400
Subject: [PATCH 7/7] WIP: investigate NVPTX target info migration
---
clang/lib/CIR/CodeGen/TargetInfo.cpp | 3 +-
clang/lib/CIR/CodeGen/Targets/NVPTX.cpp | 40 +++++++++++++++++++++++++
2 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/clang/lib/CIR/CodeGen/TargetInfo.cpp b/clang/lib/CIR/CodeGen/TargetInfo.cpp
index 84f6d5dd2039e..a493502660a31 100644
--- a/clang/lib/CIR/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CIR/CodeGen/TargetInfo.cpp
@@ -6,6 +6,7 @@
#include "clang/Basic/AddressSpaces.h"
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/MissingFeatures.h"
using namespace clang;
using namespace clang::CIRGen;
@@ -149,4 +150,4 @@ TargetCIRGenInfo::getGlobalVarAddressSpace(CIRGenModule &cgm,
!(cgm.getLangOpts().CUDA && cgm.getLangOpts().CUDAIsDevice) &&
"Address space agnostic languages only");
return d ? d->getType().getAddressSpace() : LangAS::Default;
-}
+}
\ No newline at end of file
diff --git a/clang/lib/CIR/CodeGen/Targets/NVPTX.cpp b/clang/lib/CIR/CodeGen/Targets/NVPTX.cpp
index a50f397da8e73..34ff4f13834e3 100644
--- a/clang/lib/CIR/CodeGen/Targets/NVPTX.cpp
+++ b/clang/lib/CIR/CodeGen/Targets/NVPTX.cpp
@@ -29,6 +29,46 @@ class NVPTXTargetCIRGenInfo : public TargetCIRGenInfo {
public:
NVPTXTargetCIRGenInfo(CIRGenTypes &cgt)
: TargetCIRGenInfo(std::make_unique<NVPTXABIInfo>(cgt)) {}
+
+ void setTargetAttributes(const clang::Decl *decl, mlir::Operation *global,
+ CIRGenModule &cgm) const override {
+ auto globalValue = mlir::dyn_cast<cir::CIRGlobalValueInterface>(global);
+ if (globalValue && globalValue.isDeclaration())
+ return;
+
+ const auto *vd = dyn_cast_or_null<VarDecl>(decl);
+ if (vd) {
+ if (cgm.getLangOpts().CUDA) {
+ if (vd->getType()->isCUDADeviceBuiltinSurfaceType() ||
+ vd->getType()->isCUDADeviceBuiltinTextureType())
+ assert(!cir::MissingFeatures::emitNVVMMetadata());
+ return;
+ }
+ }
+
+ const auto *fd = dyn_cast_or_null<FunctionDecl>(decl);
+ if (!fd)
+ return;
+
+ auto func = mlir::cast<cir::FuncOp>(global);
+
+ // Perform special handling in OpenCL/CUDA mode.
+ if (cgm.getLangOpts().OpenCL || cgm.getLangOpts().CUDA) {
+ // Use function attributes to check for kernel functions. By default, all
+ // functions are device functions.
+ if (fd->hasAttr<DeviceKernelAttr>() || fd->hasAttr<CUDAGlobalAttr>()) {
+ // OpenCL/CUDA kernel functions get kernel metadata. Kernel functions
+ // are also not subject to inlining.
+ func.setInlineKind(cir::InlineKind::NoInline);
+ if (fd->hasAttr<CUDAGlobalAttr>()) {
+ func.setCallingConv(cir::CallingConv::PTXKernel);
+ assert(!cir::MissingFeatures::opFuncParameterAttributes());
+ }
+ if (fd->hasAttr<CUDALaunchBoundsAttr>())
+ assert(!cir::MissingFeatures::handleCUDALaunchBoundsAttr());
+ }
+ }
+ }
mlir::Type getCUDADeviceBuiltinSurfaceDeviceType() const override {
// On the device side, surface reference is represented as an object handle
More information about the cfe-commits
mailing list