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 <[email protected]> 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@+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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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@+1 {{SYCL device code does not support variadic functions}} sycl_entry_point<class kn>([]() { printf("world\n"); moo(); - //expected-error@+1 {{SYCL device code does not support variadic functions}} + //expected-error@+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 <[email protected]> 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@+1 {{'regcall' calling convention is not supported for this target}} void __attribute__((regcall)) rcall(int a, int b) {} +// no-x86-host-warning@+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@+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 <[email protected]> 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@+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@+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@+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 <[email protected]> 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 <[email protected]> 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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
