[llvm] [SPIR-V] Support for C++ for OpenCL source language (PR #188791)
Arseniy Obolenskiy via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 27 06:21:26 PDT 2026
https://github.com/aobolensk updated https://github.com/llvm/llvm-project/pull/188791
>From 09a193be6eef136a1ee4761cd2cde6b032d8f13f Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Thu, 26 Mar 2026 17:25:52 +0100
Subject: [PATCH 1/3] [SPIR-V] Add support for C++ for OpenCL source language
via opencl.cxx.version metadata
- Add CPP_for_OpenCL source language operand
- Handle opencl.cxx.version metadata
Align handling with SPIR-V translator logic and tests presented there
---
llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 17 +++++++++++++++
.../lib/Target/SPIRV/SPIRVSymbolicOperands.td | 1 +
.../CodeGen/SPIRV/opencl-cxx-version-2021.ll | 21 +++++++++++++++++++
.../SPIRV/opencl-cxx-version-incompatible.ll | 20 ++++++++++++++++++
llvm/test/CodeGen/SPIRV/opencl-cxx-version.ll | 21 +++++++++++++++++++
5 files changed, 80 insertions(+)
create mode 100644 llvm/test/CodeGen/SPIRV/opencl-cxx-version-2021.ll
create mode 100644 llvm/test/CodeGen/SPIRV/opencl-cxx-version-incompatible.ll
create mode 100644 llvm/test/CodeGen/SPIRV/opencl-cxx-version.ll
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index 6bd2eb552a936..03195d50675d1 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -182,6 +182,23 @@ void SPIRVModuleAnalysis::setBaseInfo(const Module &M) {
// Prevent Major part of OpenCL version to be 0
MAI.SrcLangVersion =
(std::max(1U, MajorNum) * 100 + MinorNum) * 1000 + RevNum;
+ // When opencl.cxx.version is also present, validate compatibility
+ // and use C++ for OpenCL as source language with the C++ version.
+ if (auto *CxxVerNode = M.getNamedMetadata("opencl.cxx.version")) {
+ assert(CxxVerNode->getNumOperands() > 0 && "Invalid SPIR");
+ auto *CxxMD = CxxVerNode->getOperand(0);
+ unsigned CxxVer =
+ (getMetadataUInt(CxxMD, 0) * 100 + getMetadataUInt(CxxMD, 1)) * 1000 +
+ getMetadataUInt(CxxMD, 2);
+ if ((MAI.SrcLangVersion == 200000 && CxxVer == 100000) ||
+ (MAI.SrcLangVersion == 300000 && CxxVer == 202100000)) {
+ MAI.SrcLang = SPIRV::SourceLanguage::CPP_for_OpenCL;
+ MAI.SrcLangVersion = CxxVer;
+ } else {
+ report_fatal_error(
+ "opencl cxx version is not compatible with opencl c version!");
+ }
+ }
} else {
// If there is no information about OpenCL version we are forced to generate
// OpenCL 1.0 by default for the OpenCL environment to avoid puzzling
diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
index cf8ed17eaef5c..c4204c997641d 100644
--- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
+++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
@@ -662,6 +662,7 @@ defm GLSL : SourceLanguageOperand<2>;
defm OpenCL_C : SourceLanguageOperand<3>;
defm OpenCL_CPP : SourceLanguageOperand<4>;
defm HLSL : SourceLanguageOperand<5>;
+defm CPP_for_OpenCL : SourceLanguageOperand<6>;
//===----------------------------------------------------------------------===//
// Multiclass used to define AddressingModel enum values and at the same time
diff --git a/llvm/test/CodeGen/SPIRV/opencl-cxx-version-2021.ll b/llvm/test/CodeGen/SPIRV/opencl-cxx-version-2021.ll
new file mode 100644
index 0000000000000..566a22f7b2bcb
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/opencl-cxx-version-2021.ll
@@ -0,0 +1,21 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+
+; When both opencl.ocl.version (3.0) and opencl.cxx.version (2021) are present,
+; the source language should be OpenCL C++ with version 202100000.
+
+; CHECK: OpSource CPP_for_OpenCL 202100000
+
+target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
+target triple = "spir64-unknown-unknown"
+
+define spir_kernel void @foo() {
+entry:
+ ret void
+}
+
+!opencl.ocl.version = !{!0}
+!opencl.cxx.version = !{!1}
+!opencl.spir.version = !{!0}
+
+!0 = !{i32 3, i32 0}
+!1 = !{i32 2021, i32 0}
diff --git a/llvm/test/CodeGen/SPIRV/opencl-cxx-version-incompatible.ll b/llvm/test/CodeGen/SPIRV/opencl-cxx-version-incompatible.ll
new file mode 100644
index 0000000000000..79372aed21491
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/opencl-cxx-version-incompatible.ll
@@ -0,0 +1,20 @@
+; RUN: not --crash llc -O0 -mtriple=spirv64-unknown-unknown %s -o - 2>&1 | FileCheck %s
+
+; Incompatible OpenCL C and C++ versions should produce a fatal error.
+; OpenCL C 2.0 is not compatible with C++ for OpenCL 2021.
+
+; CHECK: LLVM ERROR: opencl cxx version is not compatible with opencl c version!
+
+target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
+target triple = "spir64-unknown-unknown"
+
+define spir_kernel void @foo() {
+entry:
+ ret void
+}
+
+!opencl.ocl.version = !{!0}
+!opencl.cxx.version = !{!1}
+
+!0 = !{i32 2, i32 0}
+!1 = !{i32 2021, i32 0}
diff --git a/llvm/test/CodeGen/SPIRV/opencl-cxx-version.ll b/llvm/test/CodeGen/SPIRV/opencl-cxx-version.ll
new file mode 100644
index 0000000000000..b5c13aac14b26
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/opencl-cxx-version.ll
@@ -0,0 +1,21 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+
+; When both opencl.ocl.version (2.0) and opencl.cxx.version (1.0) are present,
+; the source language should be OpenCL C++ with version 100000
+
+; CHECK: OpSource CPP_for_OpenCL 100000
+
+target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
+target triple = "spir64-unknown-unknown"
+
+define spir_kernel void @foo() {
+entry:
+ ret void
+}
+
+!opencl.ocl.version = !{!0}
+!opencl.cxx.version = !{!1}
+!opencl.spir.version = !{!0}
+
+!0 = !{i32 2, i32 0}
+!1 = !{i32 1, i32 0}
>From 438eb2d689baf166a1a2477b1ffd36c6ca611963 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Fri, 27 Mar 2026 12:10:34 +0100
Subject: [PATCH 2/3] Add RUN for spirv-val
---
llvm/test/CodeGen/SPIRV/opencl-cxx-version-2021.ll | 1 +
llvm/test/CodeGen/SPIRV/opencl-cxx-version.ll | 1 +
2 files changed, 2 insertions(+)
diff --git a/llvm/test/CodeGen/SPIRV/opencl-cxx-version-2021.ll b/llvm/test/CodeGen/SPIRV/opencl-cxx-version-2021.ll
index 566a22f7b2bcb..26ce5915cc157 100644
--- a/llvm/test/CodeGen/SPIRV/opencl-cxx-version-2021.ll
+++ b/llvm/test/CodeGen/SPIRV/opencl-cxx-version-2021.ll
@@ -1,4 +1,5 @@
; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
; When both opencl.ocl.version (3.0) and opencl.cxx.version (2021) are present,
; the source language should be OpenCL C++ with version 202100000.
diff --git a/llvm/test/CodeGen/SPIRV/opencl-cxx-version.ll b/llvm/test/CodeGen/SPIRV/opencl-cxx-version.ll
index b5c13aac14b26..600cbc899f750 100644
--- a/llvm/test/CodeGen/SPIRV/opencl-cxx-version.ll
+++ b/llvm/test/CodeGen/SPIRV/opencl-cxx-version.ll
@@ -1,4 +1,5 @@
; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
; When both opencl.ocl.version (2.0) and opencl.cxx.version (1.0) are present,
; the source language should be OpenCL C++ with version 100000
>From 3344e505c6db4ac65d3c9f0c404046ec86932659 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Fri, 27 Mar 2026 14:21:13 +0100
Subject: [PATCH 3/3] Remove target triple and target datalayout
---
llvm/test/CodeGen/SPIRV/opencl-cxx-version-2021.ll | 3 ---
llvm/test/CodeGen/SPIRV/opencl-cxx-version-incompatible.ll | 3 ---
llvm/test/CodeGen/SPIRV/opencl-cxx-version.ll | 3 ---
3 files changed, 9 deletions(-)
diff --git a/llvm/test/CodeGen/SPIRV/opencl-cxx-version-2021.ll b/llvm/test/CodeGen/SPIRV/opencl-cxx-version-2021.ll
index 26ce5915cc157..1fc8d47025cde 100644
--- a/llvm/test/CodeGen/SPIRV/opencl-cxx-version-2021.ll
+++ b/llvm/test/CodeGen/SPIRV/opencl-cxx-version-2021.ll
@@ -6,9 +6,6 @@
; CHECK: OpSource CPP_for_OpenCL 202100000
-target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
-target triple = "spir64-unknown-unknown"
-
define spir_kernel void @foo() {
entry:
ret void
diff --git a/llvm/test/CodeGen/SPIRV/opencl-cxx-version-incompatible.ll b/llvm/test/CodeGen/SPIRV/opencl-cxx-version-incompatible.ll
index 79372aed21491..cabeb62331a55 100644
--- a/llvm/test/CodeGen/SPIRV/opencl-cxx-version-incompatible.ll
+++ b/llvm/test/CodeGen/SPIRV/opencl-cxx-version-incompatible.ll
@@ -5,9 +5,6 @@
; CHECK: LLVM ERROR: opencl cxx version is not compatible with opencl c version!
-target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
-target triple = "spir64-unknown-unknown"
-
define spir_kernel void @foo() {
entry:
ret void
diff --git a/llvm/test/CodeGen/SPIRV/opencl-cxx-version.ll b/llvm/test/CodeGen/SPIRV/opencl-cxx-version.ll
index 600cbc899f750..caad2ffaf0dce 100644
--- a/llvm/test/CodeGen/SPIRV/opencl-cxx-version.ll
+++ b/llvm/test/CodeGen/SPIRV/opencl-cxx-version.ll
@@ -6,9 +6,6 @@
; CHECK: OpSource CPP_for_OpenCL 100000
-target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
-target triple = "spir64-unknown-unknown"
-
define spir_kernel void @foo() {
entry:
ret void
More information about the llvm-commits
mailing list