[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
Wed Sep 30 04:37:40 PDT 2026
https://github.com/schittir created https://github.com/llvm/llvm-project/pull/227665
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.
>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] [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) {}
More information about the cfe-commits
mailing list