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

via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 2 11:46:43 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/9] [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/9] 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/9] 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/9] 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/9] 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/9] 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/9] 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

>From 3f0eafc0e862f5a597e9f28424caf2871db13c76 Mon Sep 17 00:00:00 2001
From: Sindhu Chittireddy <sindhu.chittireddy at intel.com>
Date: Fri, 2 Oct 2026 08:36:34 -0700
Subject: [PATCH 8/9] Don't derive sse/sse2 from an ARM64EC host

The device gets its __SSE__/__SSE2__ predefines from the host, and AArch64
defines neither, so the x86 intrinsic headers are unusable with an ARM64EC
host whether or not the features are set. Limit the condition to x86-64 MSVC
hosts.
---
 clang/docs/ReleaseNotes.md                                | 4 ++--
 clang/lib/Basic/Targets/SPIR.cpp                          | 7 +++----
 clang/test/CodeGenSYCL/spirv-host-adaptation-features.cpp | 4 ++--
 3 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 511333c11fbbc..0d43d5a5ebd38 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -1092,8 +1092,8 @@ The `alpha.cplusplus.UseAfterLifetimeEnd` checker was renamed to `alpha.core.Use
 #### Improvements
 
 - SPIR and SPIR-V targets now enable `sse` and `sse2` by default when the host
-  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 is x86-64 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 79a12ce2b20d8..06467ee8ecfcd 100644
--- a/clang/lib/Basic/Targets/SPIR.cpp
+++ b/clang/lib/Basic/Targets/SPIR.cpp
@@ -113,12 +113,11 @@ void SPIRV64TargetInfo::getTargetDefines(const LangOptions &Opts,
 bool BaseSPIRTargetInfo::initFeatureMap(
     llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
     const std::vector<std::string> &FeaturesVec) const {
-  // On x86-64 and ARM64EC MSVC hosts, the STL headers use always_inline _mm_*
-  // intrinsics, which require sse/sse2 in the device feature set.
+  // On x86-64 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();
-    if (HT.isWindowsMSVCEnvironment() &&
-        (HT.getArch() == llvm::Triple::x86_64 || HT.isWindowsArm64EC())) {
+    if (HT.isWindowsMSVCEnvironment() && HT.getArch() == llvm::Triple::x86_64) {
       Features["sse"] = true;
       Features["sse2"] = true;
     }
diff --git a/clang/test/CodeGenSYCL/spirv-host-adaptation-features.cpp b/clang/test/CodeGenSYCL/spirv-host-adaptation-features.cpp
index 9decbbc736f5b..ffcc96d7a6ed2 100644
--- a/clang/test/CodeGenSYCL/spirv-host-adaptation-features.cpp
+++ b/clang/test/CodeGenSYCL/spirv-host-adaptation-features.cpp
@@ -4,8 +4,6 @@
 // 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 \
@@ -21,6 +19,8 @@
 /// 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
+// RUN: %clang_cc1 -triple spirv64-unknown-unknown -aux-triple arm64ec-pc-windows-msvc \
+// RUN:   -fsycl-is-device -emit-llvm -o - %s | FileCheck --check-prefix=NO-SSE2 %s
 // 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
 // RUN: %clang_cc1 -triple spirv64-unknown-unknown -aux-triple x86_64-unknown-linux-gnu \

>From 9d24075c58cbf012785d2de5acc1daa2f65d810b Mon Sep 17 00:00:00 2001
From: Sindhu Chittireddy <sindhu.chittireddy at intel.com>
Date: Fri, 2 Oct 2026 11:45:58 -0700
Subject: [PATCH 9/9] Undo switch case

---
 clang/lib/Basic/Targets/SPIR.h | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

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



More information about the cfe-commits mailing list