From 1e0c1ba3505f800c62a44b3cfb07d0fe0965337a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 2 Nov 2025 03:03:01 -0800 Subject: [PATCH 01/12] Runtime test coverage for ARM64EC. --- azure-pipelines.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index a01ce02bd8c..da6907ab482 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -135,12 +135,12 @@ stages: dependsOn: Build_And_Test_x64 displayName: 'Build and Test ARM64EC' pool: - name: ${{ variables.poolName }} + name: ${{ variables.arm64PoolName }} demands: ${{ variables.poolDemands }} jobs: - template: azure-devops/build-and-test.yml parameters: - hostArch: x64 + hostArch: arm64 targetArch: arm64 targetPlatform: arm64ec - testsBuildOnly: true + numShards: 10 From 0ddb8e3f8d71f61241eb5737d324f3e7fc55bdcc Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 5 Nov 2025 08:02:22 -0800 Subject: [PATCH 02/12] Verified: Compile with '-fuse-ld=link', link with '/machine:arm64ec'. --- tests/utils/stl/test/tests.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/utils/stl/test/tests.py b/tests/utils/stl/test/tests.py index 56206b65490..44d89d5ed97 100644 --- a/tests/utils/stl/test/tests.py +++ b/tests/utils/stl/test/tests.py @@ -245,6 +245,10 @@ def _handleEnvlst(self, litConfig): self.compileFlags.append('--target=arm64-pc-windows-msvc') elif (targetArch == 'arm64ec'.casefold()): self.compileFlags.append('--target=arm64ec-pc-windows-msvc') + # TRANSITION, GH-5825: As of Clang 20, compiling with `-fuse-ld=link` (avoiding lld-link) + # appears to be critically necessary for unknown reasons. + self.compileFlags.append('-fuse-ld=link') + self.linkFlags.append('/machine:arm64ec') elif ('nvcc'.casefold() in os.path.basename(cxx).casefold()): self._addCustomFeature('nvcc') From 1c57757c56e7afcff94b8d014e87e50da16b4cd0 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 5 Nov 2025 07:01:59 -0800 Subject: [PATCH 03/12] Verified: Add ARM64EC workarounds to P0811R3_midpoint_lerp. --- tests/std/tests/P0811R3_midpoint_lerp/test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/std/tests/P0811R3_midpoint_lerp/test.cpp b/tests/std/tests/P0811R3_midpoint_lerp/test.cpp index 1b97d1b40d9..ce17affe75d 100644 --- a/tests/std/tests/P0811R3_midpoint_lerp/test.cpp +++ b/tests/std/tests/P0811R3_midpoint_lerp/test.cpp @@ -1049,7 +1049,7 @@ void test_gh_1917() { ExceptGuard except; assert(bit_cast(lerp(2e+38f, 1e+38f, 4.0f)) == bit_cast(-2e+38f)); -#ifndef _M_ARM64 // TRANSITION, GH-5685 +#if !defined(_M_ARM64) && !defined(_M_ARM64EC) // TRANSITION, GH-5685 assert(check_feexcept(0)); #endif // ^^^ no workaround ^^^ } @@ -1066,7 +1066,7 @@ void test_gh_1917() { RoundGuard round{FE_UPWARD}; assert(bit_cast(lerp(2e+38f, 1e+38f, 4.0f)) == bit_cast(-2e+38f)); -#ifndef _M_ARM64 // TRANSITION, GH-5685 +#if !defined(_M_ARM64) && !defined(_M_ARM64EC) // TRANSITION, GH-5685 assert(check_feexcept(0)); #endif // ^^^ no workaround ^^^ } @@ -1082,7 +1082,7 @@ void test_gh_1917() { RoundGuard round{FE_DOWNWARD}; assert(bit_cast(lerp(2e+38f, 1e+38f, 4.0f)) == bit_cast(-2e+38f)); -#ifndef _M_ARM64 // TRANSITION, GH-5685 +#if !defined(_M_ARM64) && !defined(_M_ARM64EC) // TRANSITION, GH-5685 assert(check_feexcept(0)); #endif // ^^^ no workaround ^^^ } @@ -1098,7 +1098,7 @@ void test_gh_1917() { RoundGuard round{FE_TOWARDZERO}; assert(bit_cast(lerp(2e+38f, 1e+38f, 4.0f)) == bit_cast(-2e+38f)); -#ifndef _M_ARM64 // TRANSITION, GH-5685 +#if !defined(_M_ARM64) && !defined(_M_ARM64EC) // TRANSITION, GH-5685 assert(check_feexcept(0)); #endif // ^^^ no workaround ^^^ } From 8afce63ecb47c883fa5a7bbd51481050c1131646 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 5 Nov 2025 07:17:39 -0800 Subject: [PATCH 04/12] Verified: Fix Dev09_158457_tr1_mem_fn_calling_conventions for ARM64EC. The product code and the test code correctly avoided emitting `__vectorcall` for ARM64EC, but the expected output didn't consider ARM64EC. --- .../test.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/std/tests/Dev09_158457_tr1_mem_fn_calling_conventions/test.cpp b/tests/std/tests/Dev09_158457_tr1_mem_fn_calling_conventions/test.cpp index 3598b041f87..900eade1983 100644 --- a/tests/std/tests/Dev09_158457_tr1_mem_fn_calling_conventions/test.cpp +++ b/tests/std/tests/Dev09_158457_tr1_mem_fn_calling_conventions/test.cpp @@ -136,7 +136,7 @@ const int free_correct = 444343; // x86 ijw const int member_correct = 2111121; // x86 pure const int free_correct = 433343; // x86 pure #endif -#elif defined(_M_X64) +#elif defined(_M_X64) && !defined(_M_ARM64EC) #if !defined(_M_CEE) const int member_correct = 2211112; // x64 native const int free_correct = 433334; // x64 native @@ -149,14 +149,14 @@ const int free_correct = 433343; // x64 pure #endif #else #if !defined(_M_CEE) -const int member_correct = 2211111; // arm64 native -const int free_correct = 433333; // arm64 native +const int member_correct = 2211111; // arm64/arm64ec native +const int free_correct = 433333; // arm64/arm64ec native #elif !defined(_M_CEE_PURE) -const int member_correct = 2211121; // arm64 ijw -const int free_correct = 433343; // arm64 ijw +const int member_correct = 2211121; // arm64/arm64ec ijw +const int free_correct = 433343; // arm64/arm64ec ijw #else -const int member_correct = 2111121; // arm64 pure -const int free_correct = 433343; // arm64 pure +const int member_correct = 2111121; // arm64/arm64ec pure +const int free_correct = 433343; // arm64/arm64ec pure #endif #endif From 40c8bb18dc39a86cf77fd2a2260bc5e9e91467cb Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 5 Nov 2025 13:55:56 -0800 Subject: [PATCH 05/12] Verified: Work around stacktrace bug (GH 5830). --- tests/std/include/test_header_units_and_modules.hpp | 2 ++ tests/std/tests/P0881R7_stacktrace/test.cpp | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/std/include/test_header_units_and_modules.hpp b/tests/std/include/test_header_units_and_modules.hpp index bf79ffccab7..df85f9439e5 100644 --- a/tests/std/include/test_header_units_and_modules.hpp +++ b/tests/std/include/test_header_units_and_modules.hpp @@ -858,7 +858,9 @@ __declspec(dllexport) void test_stacktrace() { // export test_stacktrace to have desc.resize(pos); } +#ifndef _M_ARM64EC // TRANSITION, GH-5830 assert(desc == "test_stacktrace"); +#endif // ^^^ no workaround ^^^ } #endif // TEST_STANDARD >= 23 diff --git a/tests/std/tests/P0881R7_stacktrace/test.cpp b/tests/std/tests/P0881R7_stacktrace/test.cpp index effe7cfe838..547324d31fb 100644 --- a/tests/std/tests/P0881R7_stacktrace/test.cpp +++ b/tests/std/tests/P0881R7_stacktrace/test.cpp @@ -309,8 +309,8 @@ void test_impl() { } int main() { -#if !(defined(__clang__) && defined(_M_ARM64)) // TRANSITION, LLVM-74530 +#if !((defined(__clang__) && defined(_M_ARM64)) || defined(_M_ARM64EC)) // TRANSITION, LLVM-74530, GH-5830 jthread t{test_impl}; test_impl(); -#endif +#endif // ^^^ no workaround ^^^ } From 3b957017487e78557b0574c04779a526e65bfee7 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 5 Nov 2025 14:00:09 -0800 Subject: [PATCH 06/12] Verified: Improve P0881R7_stacktrace and comment about the threads. --- tests/std/tests/P0881R7_stacktrace/test.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/std/tests/P0881R7_stacktrace/test.cpp b/tests/std/tests/P0881R7_stacktrace/test.cpp index 547324d31fb..1819ad2b485 100644 --- a/tests/std/tests/P0881R7_stacktrace/test.cpp +++ b/tests/std/tests/P0881R7_stacktrace/test.cpp @@ -310,6 +310,10 @@ void test_impl() { int main() { #if !((defined(__clang__) && defined(_M_ARM64)) || defined(_M_ARM64EC)) // TRANSITION, LLVM-74530, GH-5830 + // First, run the test on a single thread, so that if anything fails, the output isn't interleaved. + test_impl(); + + // Then, run the test on multiple threads, as takes internal locks that should be exercised. jthread t{test_impl}; test_impl(); #endif // ^^^ no workaround ^^^ From f7e6a43998580c8fbe488ac66667bb05e447e1f6 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 6 Nov 2025 06:16:48 -0800 Subject: [PATCH 07/12] Verified: Add /OPT:REF,NOICF to universal_prefix.lst, fixing P0896R4_P1614R2_comparisons. --- tests/universal_prefix.lst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/universal_prefix.lst b/tests/universal_prefix.lst index b98fb54f8f5..c31e85f005a 100644 --- a/tests/universal_prefix.lst +++ b/tests/universal_prefix.lst @@ -1,4 +1,4 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -* PM_CL="/nologo /Od /W4 /w14061 /w14242 /w14265 /w14582 /w14583 /w14587 /w14588 /w14749 /w14841 /w14842 /w15038 /w15214 /w15215 /w15216 /w15217 /w15262 /sdl /WX /D_ENABLE_STL_INTERNAL_CHECK /bigobj" PM_LINK="/MANIFEST:EMBED" +* PM_CL="/nologo /Od /W4 /w14061 /w14242 /w14265 /w14582 /w14583 /w14587 /w14588 /w14749 /w14841 /w14842 /w15038 /w15214 /w15215 /w15216 /w15217 /w15262 /sdl /WX /D_ENABLE_STL_INTERNAL_CHECK /bigobj" PM_LINK="/MANIFEST:EMBED /OPT:REF,NOICF" From edd5bedf90dedee88d7683f799bea938b8c86b67 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 6 Nov 2025 07:04:12 -0800 Subject: [PATCH 08/12] Simplify names to 'Build ARCH' and 'Test ARCH'. --- azure-pipelines.yml | 46 ++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index da6907ab482..8db78f97a2e 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -18,9 +18,9 @@ stages: jobs: - template: azure-devops/format-validation.yml - - stage: Early_Build_x64 + - stage: Build_x64 dependsOn: [] - displayName: 'Early Build x64' + displayName: 'Build x64' pool: name: ${{ variables.poolName }} demands: ${{ variables.poolDemands }} @@ -35,9 +35,9 @@ stages: numShards: 1 skipTesting: true - - stage: Early_Build_x86 + - stage: Build_x86 dependsOn: [] - displayName: 'Early Build x86' + displayName: 'Build x86' pool: name: ${{ variables.poolName }} demands: ${{ variables.poolDemands }} @@ -52,9 +52,9 @@ stages: numShards: 1 skipTesting: true - - stage: Early_Build_ARM64 + - stage: Build_ARM64 dependsOn: [] - displayName: 'Early Build ARM64' + displayName: 'Build ARM64' pool: name: ${{ variables.poolName }} demands: ${{ variables.poolDemands }} @@ -69,9 +69,9 @@ stages: numShards: 1 skipTesting: true - - stage: Early_Build_ARM64EC + - stage: Build_ARM64EC dependsOn: [] - displayName: 'Early Build ARM64EC' + displayName: 'Build ARM64EC' pool: name: ${{ variables.poolName }} demands: ${{ variables.poolDemands }} @@ -86,14 +86,14 @@ stages: numShards: 1 skipTesting: true - - stage: Build_And_Test_x64 + - stage: Test_x64 dependsOn: - Code_Format - - Early_Build_x64 - - Early_Build_x86 - - Early_Build_ARM64 - - Early_Build_ARM64EC - displayName: 'Build and Test x64' + - Build_x64 + - Build_x86 + - Build_ARM64 + - Build_ARM64EC + displayName: 'Test x64' pool: name: ${{ variables.poolName }} demands: ${{ variables.poolDemands }} @@ -104,9 +104,9 @@ stages: targetArch: x64 targetPlatform: x64 - - stage: Build_And_Test_x86 - dependsOn: Build_And_Test_x64 - displayName: 'Build and Test x86' + - stage: Test_x86 + dependsOn: Test_x64 + displayName: 'Test x86' pool: name: ${{ variables.poolName }} demands: ${{ variables.poolDemands }} @@ -117,9 +117,9 @@ stages: targetArch: x86 targetPlatform: x86 - - stage: Build_And_Test_ARM64 - dependsOn: Build_And_Test_x64 - displayName: 'Build and Test ARM64' + - stage: Test_ARM64 + dependsOn: Test_x64 + displayName: 'Test ARM64' pool: name: ${{ variables.arm64PoolName }} demands: ${{ variables.poolDemands }} @@ -131,9 +131,9 @@ stages: targetPlatform: arm64 numShards: 10 - - stage: Build_And_Test_ARM64EC - dependsOn: Build_And_Test_x64 - displayName: 'Build and Test ARM64EC' + - stage: Test_ARM64EC + dependsOn: Test_x64 + displayName: 'Test ARM64EC' pool: name: ${{ variables.arm64PoolName }} demands: ${{ variables.poolDemands }} From f4d4b99584527ffe63a62fa7a0de1b39e2c4cc8c Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 6 Nov 2025 07:09:48 -0800 Subject: [PATCH 09/12] Distinguish the Cross builds. --- azure-pipelines.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 8db78f97a2e..4ff46d631f3 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -52,9 +52,9 @@ stages: numShards: 1 skipTesting: true - - stage: Build_ARM64 + - stage: Build_ARM64_Cross dependsOn: [] - displayName: 'Build ARM64' + displayName: 'Build ARM64 (Cross)' pool: name: ${{ variables.poolName }} demands: ${{ variables.poolDemands }} @@ -69,9 +69,9 @@ stages: numShards: 1 skipTesting: true - - stage: Build_ARM64EC + - stage: Build_ARM64EC_Cross dependsOn: [] - displayName: 'Build ARM64EC' + displayName: 'Build ARM64EC (Cross)' pool: name: ${{ variables.poolName }} demands: ${{ variables.poolDemands }} @@ -91,8 +91,8 @@ stages: - Code_Format - Build_x64 - Build_x86 - - Build_ARM64 - - Build_ARM64EC + - Build_ARM64_Cross + - Build_ARM64EC_Cross displayName: 'Test x64' pool: name: ${{ variables.poolName }} From 6673fea958f7a120bac6bbbb85c91c939623d4a9 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 6 Nov 2025 07:32:27 -0800 Subject: [PATCH 10/12] Add an early ARM64-native build. --- azure-pipelines.yml | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 4ff46d631f3..0cda1aa34ab 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -86,6 +86,25 @@ stages: numShards: 1 skipTesting: true + # This ARM64-native build will detect problems with the ARM64 pool as early as possible. + # The stage dependencies are structured to optimize the critical path. + - stage: Build_ARM64_Native + dependsOn: [] + displayName: 'Build ARM64 (Native)' + pool: + name: ${{ variables.arm64PoolName }} + demands: ${{ variables.poolDemands }} + jobs: + - template: azure-devops/build-and-test.yml + parameters: + hostArch: arm64 + targetArch: arm64 + targetPlatform: arm64 + analyzeBuild: true + buildBenchmarks: true + numShards: 1 + skipTesting: true + - stage: Test_x64 dependsOn: - Code_Format @@ -118,7 +137,9 @@ stages: targetPlatform: x86 - stage: Test_ARM64 - dependsOn: Test_x64 + dependsOn: + - Build_ARM64_Native + - Test_x64 displayName: 'Test ARM64' pool: name: ${{ variables.arm64PoolName }} @@ -132,7 +153,9 @@ stages: numShards: 10 - stage: Test_ARM64EC - dependsOn: Test_x64 + dependsOn: + - Build_ARM64_Native + - Test_x64 displayName: 'Test ARM64EC' pool: name: ${{ variables.arm64PoolName }} From 1e859ca7544b92d8b8b730aac886debf7b0bb58a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 6 Nov 2025 07:32:54 -0800 Subject: [PATCH 11/12] Style: Explicitly mark Code Format as having no dependencies, even though it's first. --- azure-pipelines.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 0cda1aa34ab..98f36d52a6b 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -11,6 +11,7 @@ pr: stages: - stage: Code_Format + dependsOn: [] displayName: 'Code Format' pool: name: ${{ variables.poolName }} From 8cd4e15507193ce9c6947c64732fe868623c6f1d Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 7 Nov 2025 06:29:54 -0800 Subject: [PATCH 12/12] Simplify P0881R7_stacktrace to a single thread. --- tests/std/tests/P0881R7_stacktrace/test.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/std/tests/P0881R7_stacktrace/test.cpp b/tests/std/tests/P0881R7_stacktrace/test.cpp index 1819ad2b485..3a2f86217e9 100644 --- a/tests/std/tests/P0881R7_stacktrace/test.cpp +++ b/tests/std/tests/P0881R7_stacktrace/test.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #ifdef HAS_EXPORT #define MAYBE_EXPORT __declspec(dllexport) @@ -310,11 +309,6 @@ void test_impl() { int main() { #if !((defined(__clang__) && defined(_M_ARM64)) || defined(_M_ARM64EC)) // TRANSITION, LLVM-74530, GH-5830 - // First, run the test on a single thread, so that if anything fails, the output isn't interleaved. - test_impl(); - - // Then, run the test on multiple threads, as takes internal locks that should be exercised. - jthread t{test_impl}; test_impl(); #endif // ^^^ no workaround ^^^ }