[clang] [clang][SPIR-V] Add x86 calling conventions and sse/sse2 for MSVC hosts (PR #227665)

via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 1 20:46:54 PDT 2026


https://github.com/schittir updated https://github.com/llvm/llvm-project/pull/227665

>From f3dab416c11d0eb14e00ade6e58c60ef948060f8 Mon Sep 17 00:00:00 2001
From: Sindhu Chittireddy <sindhu.chittireddy at intel.com>
Date: Tue, 29 Sep 2026 18:23:58 -0700
Subject: [PATCH 1/7] [clang][SPIR-V] Add sse/sse2 for MSVC hosts and x86
 calling conventions

This patch adds sse and sse2 to initFeatureMap when the host predefines _M_X64,
as MSVC's STL headers declare always_inline _mm_* intrinsics requiring them.

It also permits CC_X86VectorCall and CC_X86RegCall calling conventions.
This affects only compilations with no x86 auxiliary target.
---
 clang/lib/Basic/Targets/SPIR.cpp              | 16 ++++++++
 clang/lib/Basic/Targets/SPIR.h                | 10 ++++-
 .../spirv-host-adaptation-features.cpp        | 37 +++++++++++++++++++
 .../spirv-host-adaptation-macros.cpp          | 14 +++++++
 clang/test/SemaSYCL/sycl-cconv.cpp            |  4 ++
 5 files changed, 80 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/CodeGenSYCL/spirv-host-adaptation-features.cpp

diff --git a/clang/lib/Basic/Targets/SPIR.cpp b/clang/lib/Basic/Targets/SPIR.cpp
index 3eb62c9051b58..b84cb88eac8b2 100644
--- a/clang/lib/Basic/Targets/SPIR.cpp
+++ b/clang/lib/Basic/Targets/SPIR.cpp
@@ -110,6 +110,22 @@ void SPIRV64TargetInfo::getTargetDefines(const LangOptions &Opts,
   DefineStd(Builder, "SPIRV64", Opts);
 }
 
+bool BaseSPIRTargetInfo::initFeatureMap(
+    llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
+    const std::vector<std::string> &FeaturesVec) const {
+  // When the host predefines _M_X64, MSVC STL headers use always_inline _mm_*
+  // intrinsics, which require sse/sse2 in the device feature set.
+  if (const TargetInfo *Host = getHostTarget()) {
+    const llvm::Triple &HT = Host->getTriple();
+    if (HT.isWindowsMSVCEnvironment() &&
+        (HT.getArch() == llvm::Triple::x86_64 || HT.isWindowsArm64EC())) {
+      Features["sse"] = true;
+      Features["sse2"] = true;
+    }
+  }
+  return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
+}
+
 static const AMDGPUTargetInfo
     AMDGPUTI(llvm::Triple(llvm::Triple::amdgpu, llvm::Triple::NoSubArch,
                           llvm::Triple::AMD, llvm::Triple::AMDHSA),
diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h
index c24a55ecfc970..566f4cf9abc9e 100644
--- a/clang/lib/Basic/Targets/SPIR.h
+++ b/clang/lib/Basic/Targets/SPIR.h
@@ -185,9 +185,17 @@ class LLVM_LIBRARY_VISIBILITY BaseSPIRTargetInfo : public TargetInfo {
   }
 
   CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
-    return (CC == CC_C || CC == CC_DeviceKernel) ? CCCR_OK : CCCR_Warning;
+    return (CC == CC_C || CC == CC_DeviceKernel || CC == CC_X86RegCall ||
+            CC == CC_X86VectorCall)
+               ? CCCR_OK
+               : CCCR_Warning;
   }
 
+  bool
+  initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
+                 StringRef CPU,
+                 const std::vector<std::string> &FeaturesVec) const override;
+
   void setAddressSpaceMap(bool DefaultIsGeneric) {
     AddrSpaceMap = DefaultIsGeneric ? &SPIRDefIsGenMap : &SPIRDefIsPrivMap;
   }
diff --git a/clang/test/CodeGenSYCL/spirv-host-adaptation-features.cpp b/clang/test/CodeGenSYCL/spirv-host-adaptation-features.cpp
new file mode 100644
index 0000000000000..8b054e0e9291a
--- /dev/null
+++ b/clang/test/CodeGenSYCL/spirv-host-adaptation-features.cpp
@@ -0,0 +1,37 @@
+/// Check the sse/sse2 device features derived from the host target.
+
+// RUN: %clang_cc1 -triple spir64-unknown-unknown -aux-triple x86_64-pc-windows-msvc \
+// RUN:   -fsycl-is-device -emit-llvm -o - %s | FileCheck --check-prefix=SSE2 %s
+// RUN: %clang_cc1 -triple spirv64-unknown-unknown -aux-triple x86_64-pc-windows-msvc \
+// RUN:   -fsycl-is-device -emit-llvm -o - %s | FileCheck --check-prefix=SSE2 %s
+// RUN: %clang_cc1 -triple spirv64-unknown-unknown -aux-triple arm64ec-pc-windows-msvc \
+// RUN:   -fsycl-is-device -emit-llvm -o - %s | FileCheck --check-prefix=SSE2 %s
+// RUN: %clang_cc1 -triple spir-unknown-unknown -aux-triple x86_64-pc-windows-msvc \
+// RUN:   -fsycl-is-device -emit-llvm -o - %s | FileCheck --check-prefix=SSE2 %s
+// RUN: %clang_cc1 -triple spirv32-unknown-unknown -aux-triple x86_64-pc-windows-msvc \
+// RUN:   -fsycl-is-device -emit-llvm -o - %s | FileCheck --check-prefix=SSE2 %s
+/// Windows ARM64 without EC is not an x86 host and does not predefine _M_X64.
+// RUN: %clang_cc1 -triple spirv64-unknown-unknown -aux-triple aarch64-pc-windows-msvc \
+// RUN:   -fsycl-is-device -emit-llvm -o - %s | FileCheck --check-prefix=NO-SSE2 %s
+
+/// 32-bit Windows hosts predefine _M_IX86 rather than _M_X64.
+// RUN: %clang_cc1 -triple spirv32-unknown-unknown -aux-triple i386-pc-windows-msvc \
+// RUN:   -fsycl-is-device -emit-llvm -o - %s | FileCheck --check-prefix=NO-SSE2 %s
+
+/// Non-MSVC x86_64 hosts do not predefine _M_X64, whether or not they are
+/// Windows hosts.
+// RUN: %clang_cc1 -triple spirv64-unknown-unknown -aux-triple x86_64-unknown-linux-gnu \
+// RUN:   -fsycl-is-device -emit-llvm -o - %s | FileCheck --check-prefix=NO-SSE2 %s
+// RUN: %clang_cc1 -triple spirv64-unknown-unknown -aux-triple x86_64-pc-windows-gnu \
+// RUN:   -fsycl-is-device -emit-llvm -o - %s | FileCheck --check-prefix=NO-SSE2 %s
+// RUN: %clang_cc1 -triple spirv64-unknown-unknown -aux-triple x86_64-uefi \
+// RUN:   -fsycl-is-device -emit-llvm -o - %s | FileCheck --check-prefix=NO-SSE2 %s
+// RUN: %clang_cc1 -triple spirv64-unknown-unknown \
+// RUN:   -fsycl-is-device -emit-llvm -o - %s | FileCheck --check-prefix=NO-SSE2 %s
+
+[[clang::sycl_external]] void test() {}
+
+// SSE2: define {{.*}}spir_func void @_Z4testv() #[[ATTR:[0-9]+]]
+// SSE2: attributes #[[ATTR]] = {{{.*}}"target-features"="+sse,+sse2"
+
+// NO-SSE2-NOT: "target-features"
diff --git a/clang/test/Preprocessor/spirv-host-adaptation-macros.cpp b/clang/test/Preprocessor/spirv-host-adaptation-macros.cpp
index 786059fee4cf0..852ea9c3c1544 100644
--- a/clang/test/Preprocessor/spirv-host-adaptation-macros.cpp
+++ b/clang/test/Preprocessor/spirv-host-adaptation-macros.cpp
@@ -7,6 +7,8 @@
 // RUN:   -fsycl-is-device -E -dM %s | FileCheck --check-prefix=WIN64 %s
 // RUN: %clang_cc1 -triple spirv32-unknown-unknown -aux-triple i386-unknown-linux-gnu \
 // RUN:   -fsycl-is-device -E -dM %s | FileCheck --check-prefix=LINUX32 %s
+// RUN: %clang_cc1 -triple spirv32-unknown-unknown -aux-triple i386-pc-windows-msvc \
+// RUN:   -fsycl-is-device -E -dM %s | FileCheck --check-prefix=WIN32 %s
 // RUN: %clang_cc1 -triple spirv64-unknown-unknown \
 // RUN:   -fsycl-is-device -E -dM %s | FileCheck --check-prefix=NOHOST64 %s
 // RUN: %clang_cc1 -triple spirv32-unknown-unknown \
@@ -38,6 +40,14 @@
 // LINUX32-DAG: #define __SIZEOF_PTRDIFF_T__ 4
 // LINUX32-DAG: #define __SIZEOF_POINTER__ 4
 
+// Windows i386 host (ILP32)
+// WIN32-DAG: #define __SIZE_TYPE__ unsigned int
+// WIN32-DAG: #define __PTRDIFF_TYPE__ int
+// WIN32-DAG: #define __INTPTR_TYPE__ int
+// WIN32-DAG: #define __SIZEOF_SIZE_T__ 4
+// WIN32-DAG: #define __SIZEOF_PTRDIFF_T__ 4
+// WIN32-DAG: #define __SIZEOF_POINTER__ 4
+
 // No host (SPIRV64 defaults)
 // NOHOST64-DAG: #define __SIZE_TYPE__ long unsigned int
 // NOHOST64-DAG: #define __PTRDIFF_TYPE__ long int
@@ -59,6 +69,8 @@
 // WIN64-DAG: #define _WIN64 1
 // WIN64-DAG: #define _M_X64 100
 // WIN64-DAG: #define _M_AMD64 100
+// WIN32-DAG: #define _WIN32 1
+// WIN32-DAG: #define _M_IX86 600
 // LINUX64-DAG: #define __linux__ 1
 // LINUX64-DAG: #define __x86_64__ 1
 
@@ -67,6 +79,8 @@
 // LINUX64-DAG: #define __SPIRV64__ 1
 // WIN64-DAG: #define __SPIRV__ 1
 // WIN64-DAG: #define __SPIRV64__ 1
+// WIN32-DAG: #define __SPIRV__ 1
+// WIN32-DAG: #define __SPIRV32__ 1
 // NOHOST64-DAG: #define __SPIRV__ 1
 // NOHOST64-DAG: #define __SPIRV64__ 1
 // NOHOST32-DAG: #define __SPIRV__ 1
diff --git a/clang/test/SemaSYCL/sycl-cconv.cpp b/clang/test/SemaSYCL/sycl-cconv.cpp
index 1b250676cf478..8661aa3a372d5 100644
--- a/clang/test/SemaSYCL/sycl-cconv.cpp
+++ b/clang/test/SemaSYCL/sycl-cconv.cpp
@@ -15,6 +15,10 @@ void bar() {
   printf("hello\n");
 }
 
+// Accepted by the SPIR-V target itself, with no host to fall back on.
+void __attribute__((regcall)) rcall(int a, int b) {}
+void __attribute__((vectorcall)) vcall(float a, float b) {}
+
 // Check some weird calling convention that is not supported even by x86_64 aux.
 // no-aux-warning at +1 {{'__swiftasynccall__' calling convention is not supported for this target}}
 void __attribute__((__swiftasynccall__)) g(void) {}

>From 43a10425cca3151f55f9544b5ff1a78832699a7e Mon Sep 17 00:00:00 2001
From: Sindhu Chittireddy <sindhu.chittireddy at intel.com>
Date: Wed, 30 Sep 2026 07:45:38 -0700
Subject: [PATCH 2/7] Use a switch in checkCallingConvention

---
 clang/lib/Basic/Targets/SPIR.h | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h
index 566f4cf9abc9e..e2cd809cfd16f 100644
--- a/clang/lib/Basic/Targets/SPIR.h
+++ b/clang/lib/Basic/Targets/SPIR.h
@@ -185,10 +185,15 @@ class LLVM_LIBRARY_VISIBILITY BaseSPIRTargetInfo : public TargetInfo {
   }
 
   CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
-    return (CC == CC_C || CC == CC_DeviceKernel || CC == CC_X86RegCall ||
-            CC == CC_X86VectorCall)
-               ? CCCR_OK
-               : CCCR_Warning;
+    switch (CC) {
+    case CC_C:
+    case CC_DeviceKernel:
+    case CC_X86RegCall:
+    case CC_X86VectorCall:
+      return CCCR_OK;
+    default:
+      return CCCR_Warning;
+    }
   }
 
   bool

>From 58193c3132462d4632c23feadadfc4a3e715d3be Mon Sep 17 00:00:00 2001
From: Sindhu Chittireddy <sindhu.chittireddy at intel.com>
Date: Wed, 30 Sep 2026 08:29:36 -0700
Subject: [PATCH 3/7] Add test coverage for explicitly disabled sse/sse2

---
 .../CodeGenSYCL/spirv-host-adaptation-features.cpp    | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/clang/test/CodeGenSYCL/spirv-host-adaptation-features.cpp b/clang/test/CodeGenSYCL/spirv-host-adaptation-features.cpp
index 8b054e0e9291a..18ff40b648306 100644
--- a/clang/test/CodeGenSYCL/spirv-host-adaptation-features.cpp
+++ b/clang/test/CodeGenSYCL/spirv-host-adaptation-features.cpp
@@ -10,6 +10,14 @@
 // RUN:   -fsycl-is-device -emit-llvm -o - %s | FileCheck --check-prefix=SSE2 %s
 // RUN: %clang_cc1 -triple spirv32-unknown-unknown -aux-triple x86_64-pc-windows-msvc \
 // RUN:   -fsycl-is-device -emit-llvm -o - %s | FileCheck --check-prefix=SSE2 %s
+/// An explicit -target-feature overrides the derived default.
+// RUN: %clang_cc1 -triple spirv64-unknown-unknown -aux-triple x86_64-pc-windows-msvc \
+// RUN:   -target-feature -sse2 -fsycl-is-device -emit-llvm -o - %s \
+// RUN:   | FileCheck --check-prefix=NO-SSE2-FLAG %s
+// RUN: %clang_cc1 -triple spirv64-unknown-unknown -aux-triple x86_64-pc-windows-msvc \
+// RUN:   -target-feature -sse -fsycl-is-device -emit-llvm -o - %s \
+// RUN:   | FileCheck --check-prefix=NO-SSE-FLAG %s
+
 /// Windows ARM64 without EC is not an x86 host and does not predefine _M_X64.
 // RUN: %clang_cc1 -triple spirv64-unknown-unknown -aux-triple aarch64-pc-windows-msvc \
 // RUN:   -fsycl-is-device -emit-llvm -o - %s | FileCheck --check-prefix=NO-SSE2 %s
@@ -35,3 +43,6 @@
 // SSE2: attributes #[[ATTR]] = {{{.*}}"target-features"="+sse,+sse2"
 
 // NO-SSE2-NOT: "target-features"
+
+// NO-SSE2-FLAG: attributes #{{[0-9]+}} = {{{.*}}"target-features"="+sse,-sse2"
+// NO-SSE-FLAG: attributes #{{[0-9]+}} = {{{.*}}"target-features"="+sse2,-sse"

>From 1da8d7dfe2e64e46a03ffc68ddaeb3d52ab8094f Mon Sep 17 00:00:00 2001
From: Sindhu Chittireddy <sindhu.chittireddy at intel.com>
Date: Wed, 30 Sep 2026 10:18:15 -0700
Subject: [PATCH 4/7] Add release notes for the sse/sse2 and calling convention
 changes

---
 clang/docs/ReleaseNotes.md | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index c778703e8cc6f..b7fef479a2b55 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -1056,6 +1056,15 @@ The `alpha.cplusplus.UseAfterLifetimeEnd` checker was renamed to `alpha.core.Use
 
 #### Improvements
 
+- The `__regcall` and `__vectorcall` calling conventions are now accepted on
+  SPIR and SPIR-V targets. Previously they were diagnosed as unsupported when
+  compiling without an x86 auxiliary target.
+
+- SPIR and SPIR-V targets now enable `sse` and `sse2` by default when the host
+  target predefines `_M_X64`, as the MSVC STL headers declare `always_inline`
+  `_mm_*` intrinsics that require them. An explicit `-target-feature` still
+  overrides the default.
+
 ## Additional Information
 
 A wide variety of additional information is available on the [Clang web

>From 6d807b4182b83db700cec56ac02c692f41ebcd0a Mon Sep 17 00:00:00 2001
From: Sindhu Chittireddy <sindhu.chittireddy at intel.com>
Date: Wed, 30 Sep 2026 12:06:42 -0700
Subject: [PATCH 5/7] Reword the host target comments and fix test indentation

---
 clang/test/CodeGenSYCL/spirv-host-adaptation-features.cpp | 7 +------
 clang/test/SemaSYCL/sycl-cconv.cpp                        | 2 +-
 2 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/clang/test/CodeGenSYCL/spirv-host-adaptation-features.cpp b/clang/test/CodeGenSYCL/spirv-host-adaptation-features.cpp
index 18ff40b648306..9decbbc736f5b 100644
--- a/clang/test/CodeGenSYCL/spirv-host-adaptation-features.cpp
+++ b/clang/test/CodeGenSYCL/spirv-host-adaptation-features.cpp
@@ -18,16 +18,11 @@
 // RUN:   -target-feature -sse -fsycl-is-device -emit-llvm -o - %s \
 // RUN:   | FileCheck --check-prefix=NO-SSE-FLAG %s
 
-/// Windows ARM64 without EC is not an x86 host and does not predefine _M_X64.
+/// No sse/sse2 unless the host is 64-bit x86 MSVC
 // RUN: %clang_cc1 -triple spirv64-unknown-unknown -aux-triple aarch64-pc-windows-msvc \
 // RUN:   -fsycl-is-device -emit-llvm -o - %s | FileCheck --check-prefix=NO-SSE2 %s
-
-/// 32-bit Windows hosts predefine _M_IX86 rather than _M_X64.
 // RUN: %clang_cc1 -triple spirv32-unknown-unknown -aux-triple i386-pc-windows-msvc \
 // RUN:   -fsycl-is-device -emit-llvm -o - %s | FileCheck --check-prefix=NO-SSE2 %s
-
-/// Non-MSVC x86_64 hosts do not predefine _M_X64, whether or not they are
-/// Windows hosts.
 // RUN: %clang_cc1 -triple spirv64-unknown-unknown -aux-triple x86_64-unknown-linux-gnu \
 // RUN:   -fsycl-is-device -emit-llvm -o - %s | FileCheck --check-prefix=NO-SSE2 %s
 // RUN: %clang_cc1 -triple spirv64-unknown-unknown -aux-triple x86_64-pc-windows-gnu \
diff --git a/clang/test/SemaSYCL/sycl-cconv.cpp b/clang/test/SemaSYCL/sycl-cconv.cpp
index 8661aa3a372d5..5af1e31ef9c92 100644
--- a/clang/test/SemaSYCL/sycl-cconv.cpp
+++ b/clang/test/SemaSYCL/sycl-cconv.cpp
@@ -36,7 +36,7 @@ int main() {
   //expected-error at +1 {{SYCL device code does not support variadic functions}}
   sycl_entry_point<class kn>([]() { printf("world\n");
      moo();
-  //expected-error at +1 {{SYCL device code does not support variadic functions}}
+     //expected-error at +1 {{SYCL device code does not support variadic functions}}
      foo(1,2); });
   bar();
   return 0;

>From a9efd05fc0be54cf6afc059678fce249cd3f3995 Mon Sep 17 00:00:00 2001
From: Sindhu Chittireddy <sindhu.chittireddy at intel.com>
Date: Thu, 1 Oct 2026 12:43:32 -0700
Subject: [PATCH 6/7] Don't accept regcall and vectorcall on SPIR-V targets

Test hosts that lack these calling conventions and state the host
condition accurately in the comments and release note.
---
 clang/docs/ReleaseNotes.md         | 10 +++-------
 clang/lib/Basic/Targets/SPIR.cpp   |  2 +-
 clang/lib/Basic/Targets/SPIR.h     |  2 --
 clang/test/SemaSYCL/sycl-cconv.cpp | 16 +++++++++++++---
 4 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index b7fef479a2b55..6e0c175bf4196 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -1056,14 +1056,10 @@ The `alpha.cplusplus.UseAfterLifetimeEnd` checker was renamed to `alpha.core.Use
 
 #### Improvements
 
-- The `__regcall` and `__vectorcall` calling conventions are now accepted on
-  SPIR and SPIR-V targets. Previously they were diagnosed as unsupported when
-  compiling without an x86 auxiliary target.
-
 - SPIR and SPIR-V targets now enable `sse` and `sse2` by default when the host
-  target predefines `_M_X64`, as the MSVC STL headers declare `always_inline`
-  `_mm_*` intrinsics that require them. An explicit `-target-feature` still
-  overrides the default.
+  target is x86-64 or ARM64EC in an MSVC environment, as the MSVC STL headers
+  declare `always_inline` `_mm_*` intrinsics that require them. An explicit
+  `-target-feature` still overrides the default.
 
 ## Additional Information
 
diff --git a/clang/lib/Basic/Targets/SPIR.cpp b/clang/lib/Basic/Targets/SPIR.cpp
index b84cb88eac8b2..79a12ce2b20d8 100644
--- a/clang/lib/Basic/Targets/SPIR.cpp
+++ b/clang/lib/Basic/Targets/SPIR.cpp
@@ -113,7 +113,7 @@ void SPIRV64TargetInfo::getTargetDefines(const LangOptions &Opts,
 bool BaseSPIRTargetInfo::initFeatureMap(
     llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
     const std::vector<std::string> &FeaturesVec) const {
-  // When the host predefines _M_X64, MSVC STL headers use always_inline _mm_*
+  // On x86-64 and ARM64EC MSVC hosts, the STL headers use always_inline _mm_*
   // intrinsics, which require sse/sse2 in the device feature set.
   if (const TargetInfo *Host = getHostTarget()) {
     const llvm::Triple &HT = Host->getTriple();
diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h
index e2cd809cfd16f..579e6549d20eb 100644
--- a/clang/lib/Basic/Targets/SPIR.h
+++ b/clang/lib/Basic/Targets/SPIR.h
@@ -188,8 +188,6 @@ class LLVM_LIBRARY_VISIBILITY BaseSPIRTargetInfo : public TargetInfo {
     switch (CC) {
     case CC_C:
     case CC_DeviceKernel:
-    case CC_X86RegCall:
-    case CC_X86VectorCall:
       return CCCR_OK;
     default:
       return CCCR_Warning;
diff --git a/clang/test/SemaSYCL/sycl-cconv.cpp b/clang/test/SemaSYCL/sycl-cconv.cpp
index 5af1e31ef9c92..257329b1a4181 100644
--- a/clang/test/SemaSYCL/sycl-cconv.cpp
+++ b/clang/test/SemaSYCL/sycl-cconv.cpp
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -isystem %S/Inputs/ -fsycl-is-device -triple spirv64 -aux-triple x86_64-pc-windows-msvc -fsyntax-only -verify %s
-// RUN: %clang_cc1 -isystem %S/Inputs/ -fsycl-is-device -triple spirv64 -fsyntax-only -verify=expected,no-aux %s
+// RUN: %clang_cc1 -isystem %S/Inputs/ -fsycl-is-device -triple spirv64 -aux-triple x86_64-unknown-linux-gnu -fsyntax-only -verify %s
+// RUN: %clang_cc1 -isystem %S/Inputs/ -fsycl-is-device -triple spirv64 -aux-triple aarch64-unknown-linux-gnu -fsyntax-only -verify=expected,no-x86-host %s
+// RUN: %clang_cc1 -isystem %S/Inputs/ -fsycl-is-device -triple spirv64 -fsyntax-only -verify=expected,no-aux,no-x86-host %s
 
 // Check that there is no error/warning emitted for cdecl functions compiled for
 // SYCL device. Make sure variadic calls from within device code are diagnosed.
@@ -15,8 +17,11 @@ void bar() {
   printf("hello\n");
 }
 
-// Accepted by the SPIR-V target itself, with no host to fall back on.
+// Accepted when the auxiliary host target supports the calling convention and
+// diagnosed when neither the device nor the host does.
+// no-x86-host-warning at +1 {{'regcall' calling convention is not supported for this target}}
 void __attribute__((regcall)) rcall(int a, int b) {}
+// no-x86-host-warning at +1 {{'vectorcall' calling convention is not supported for this target}}
 void __attribute__((vectorcall)) vcall(float a, float b) {}
 
 // Check some weird calling convention that is not supported even by x86_64 aux.
@@ -37,7 +42,12 @@ int main() {
   sycl_entry_point<class kn>([]() { printf("world\n");
      moo();
      //expected-error at +1 {{SYCL device code does not support variadic functions}}
-     foo(1,2); });
+     foo(1,2);
+     // Calls are not diagnosed; an unsupported calling convention is diagnosed
+     // on the declaration instead.
+     rcall(1, 2);
+     vcall(1.0f, 2.0f);
+     g(); });
   bar();
   return 0;
 }

>From 57abe19a25d4de1f485c5cbb32c2d5a41c11df3b Mon Sep 17 00:00:00 2001
From: Sindhu Chittireddy <sindhu.chittireddy at intel.com>
Date: Thu, 1 Oct 2026 15:36:46 -0700
Subject: [PATCH 7/7] Add immintrin.h coverage for the host-derived sse/sse2
 features

Check that the x86 intrinsic headers parse and compile for a SPIR-V device
with an x86-64 MSVC host, that dropping sse/sse2 reinstates the always_inline
target feature errors, and that intrinsics lowering to x86 builtins stay
unavailable to device code.
---
 .../spirv-host-adaptation-immintrin.cpp       | 48 +++++++++++++++++++
 1 file changed, 48 insertions(+)
 create mode 100644 clang/test/CodeGenSYCL/spirv-host-adaptation-immintrin.cpp

diff --git a/clang/test/CodeGenSYCL/spirv-host-adaptation-immintrin.cpp b/clang/test/CodeGenSYCL/spirv-host-adaptation-immintrin.cpp
new file mode 100644
index 0000000000000..7871f1b704170
--- /dev/null
+++ b/clang/test/CodeGenSYCL/spirv-host-adaptation-immintrin.cpp
@@ -0,0 +1,48 @@
+/// Check that the x86 intrinsic headers parse and compile for a SPIR-V device
+/// when the auxiliary host target is x86-64 MSVC, which is what the sse/sse2
+/// device features derived from that host are for.
+
+// RUN: %clang_cc1 -triple spirv64-unknown-unknown -aux-triple x86_64-pc-windows-msvc \
+// RUN:   -fsycl-is-device -ffreestanding -emit-llvm -o - %s | FileCheck %s
+
+/// With sse/sse2 disabled, the always_inline intrinsics cannot be inlined into
+/// device code; this is the failure the derived features prevent.
+/// Codegen stops at the first failing function, so only add() is diagnosed.
+// RUN: %clang_cc1 -triple spirv64-unknown-unknown -aux-triple x86_64-pc-windows-msvc \
+// RUN:   -fsycl-is-device -ffreestanding -target-feature -sse -target-feature -sse2 \
+// RUN:   -emit-llvm -verify=no-sse -o - %s
+
+/// Intrinsics that lower to x86 builtins are rejected for the device.
+// RUN: %clang_cc1 -triple spirv64-unknown-unknown -aux-triple x86_64-pc-windows-msvc \
+// RUN:   -fsycl-is-device -ffreestanding -DX86_BUILTIN -emit-llvm -verify=x86-builtin \
+// RUN:   -o - %s
+
+#include <immintrin.h>
+
+// CHECK-LABEL: define {{.*}}spir_func noundef float @_Z3addff
+[[clang::sycl_external]] float add(float x, float y) {
+  // no-sse-error at +1 {{always_inline function '_mm_set1_ps' requires target feature 'sse', but would be inlined into function 'add' that is compiled without support for 'sse'}}
+  __m128 a = _mm_set1_ps(x);
+  // no-sse-error at +1 {{always_inline function '_mm_set1_ps' requires target feature 'sse', but would be inlined into function 'add' that is compiled without support for 'sse'}}
+  __m128 b = _mm_set1_ps(y);
+  // CHECK: fadd <4 x float>
+  // no-sse-error at +1 {{always_inline function '_mm_add_ps' requires target feature 'sse', but would be inlined into function 'add' that is compiled without support for 'sse'}}
+  __m128 c = _mm_add_ps(a, b);
+  return c[0];
+}
+
+// CHECK-LABEL: define {{.*}}spir_func void @_Z4sqrtPd
+[[clang::sycl_external]] void sqrt(double *p) {
+  __m128d a = _mm_set1_pd(*p);
+  // CHECK: call {{.*}}<2 x double> @llvm.sqrt.v2f64
+  __m128d b = _mm_sqrt_pd(a);
+  _mm_storeu_pd(p, b);
+}
+
+#ifdef X86_BUILTIN
+// The diagnostic is reported in the intrinsic header, not here.
+// x86-builtin-error@*:* {{cannot compile this builtin function yet}}
+[[clang::sycl_external]] __m128i madd(__m128i a, __m128i b) {
+  return _mm_madd_epi16(a, b);
+}
+#endif



More information about the cfe-commits mailing list