[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