From f27040c5a50f4cc676192727edbceb4669f115f3 Mon Sep 17 00:00:00 2001 From: Gerard Gorman Date: Tue, 13 Oct 2026 17:10:15 +0000 Subject: [PATCH 1/3] arch: Detect all Apple-silicon chips as AppleArm `get_platform` only recognised Apple silicon through `'m1' in brand`, so an "Apple M2/M3/M4 ..." brand string fell through to ANYCPU. On such a machine `skipif('cpu64-arm')` does not fire and tests that force an x86 platform (e.g. `test_nested_nthreads` with `knl7210`) emit x86 intrinsics headers that clang rejects on arm64; which chip a macOS CI runner gets is a lottery, so the same PR can be green or red on different runs. Map any "apple m" brand to the registered AppleArm of that generation, falling back to the newest registered one for chips not yet listed (the actual `march` is derived at runtime by `AppleArm.march`). Add a test that fails for M2/M3/M4 brand strings without this change. --- devito/arch/archinfo.py | 8 ++++++-- tests/test_arch.py | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/devito/arch/archinfo.py b/devito/arch/archinfo.py index 53de39e8926..9e1d0406169 100644 --- a/devito/arch/archinfo.py +++ b/devito/arch/archinfo.py @@ -753,8 +753,12 @@ def get_platform(): return platform_registry['power8'] elif 'arm' in brand: return platform_registry['arm'] - elif 'm1' in brand: - return platform_registry['m1'] + elif 'apple m' in brand: + # Apple silicon: "Apple M1", "Apple M2 Pro", "Apple M4 Max", ... + # Chips newer than the registered ones are still AppleArm; the + # exact `march` is derived at runtime by `AppleArm.march` + key = brand.split('apple ')[1].split()[0] + return platform_registry.get(key, platform_registry['m3']) elif 'amd' in brand: return platform_registry['amd'] except: diff --git a/tests/test_arch.py b/tests/test_arch.py index 9565c6f08d2..a64923f551e 100644 --- a/tests/test_arch.py +++ b/tests/test_arch.py @@ -1,6 +1,7 @@ import pytest from devito import configuration, switchconfig +from devito.arch import archinfo from devito.arch.compiler import GNUCompiler, compiler_registry, sniff_compiler_version @@ -18,6 +19,26 @@ def test_gcc(cc): assert cc in compiler_registry +@pytest.mark.parametrize('brand,expected', [ + ('Apple M1', 'm1'), + ('Apple M2 Pro', 'm2'), + ('Apple M3 Max', 'm3'), + ('Apple M4 Max', 'm3'), # newer than the registry: still AppleArm +]) +def test_detect_apple_silicon(monkeypatch, brand, expected): + """ + Platform autodetection must classify every Apple-silicon brand string as + AppleArm, not just "Apple M1"; otherwise `skipif('cpu64-arm')` does not + fire and x86-only codepaths are exercised on arm64 macOS. + """ + monkeypatch.setattr(archinfo, 'get_cpu_info', + lambda: {'brand': brand, 'logical': 8, 'physical': 8}) + # Bypass the memoization cache + platform = archinfo.get_platform.func() + assert isinstance(platform, archinfo.AppleArm) + assert platform.name == expected + + def test_switcharch(): old_compiler = configuration['compiler'] with switchconfig(compiler='gcc-4.9'): From 0fadf14dcf2e899bd732f9299fac0501e1b1501b Mon Sep 17 00:00:00 2001 From: Gerard Gorman Date: Wed, 14 Oct 2026 16:05:07 +0000 Subject: [PATCH 2/3] arch: Trim Apple-silicon comments and test --- devito/arch/archinfo.py | 4 +--- tests/test_arch.py | 15 +++------------ 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/devito/arch/archinfo.py b/devito/arch/archinfo.py index 9e1d0406169..aeb7b43dc9d 100644 --- a/devito/arch/archinfo.py +++ b/devito/arch/archinfo.py @@ -754,9 +754,7 @@ def get_platform(): elif 'arm' in brand: return platform_registry['arm'] elif 'apple m' in brand: - # Apple silicon: "Apple M1", "Apple M2 Pro", "Apple M4 Max", ... - # Chips newer than the registered ones are still AppleArm; the - # exact `march` is derived at runtime by `AppleArm.march` + # Unregistered (newer) chips fall back to the latest AppleArm key = brand.split('apple ')[1].split()[0] return platform_registry.get(key, platform_registry['m3']) elif 'amd' in brand: diff --git a/tests/test_arch.py b/tests/test_arch.py index a64923f551e..33fa00418ba 100644 --- a/tests/test_arch.py +++ b/tests/test_arch.py @@ -23,20 +23,11 @@ def test_gcc(cc): ('Apple M1', 'm1'), ('Apple M2 Pro', 'm2'), ('Apple M3 Max', 'm3'), - ('Apple M4 Max', 'm3'), # newer than the registry: still AppleArm + ('Apple M4 Max', 'm3'), ]) def test_detect_apple_silicon(monkeypatch, brand, expected): - """ - Platform autodetection must classify every Apple-silicon brand string as - AppleArm, not just "Apple M1"; otherwise `skipif('cpu64-arm')` does not - fire and x86-only codepaths are exercised on arm64 macOS. - """ - monkeypatch.setattr(archinfo, 'get_cpu_info', - lambda: {'brand': brand, 'logical': 8, 'physical': 8}) - # Bypass the memoization cache - platform = archinfo.get_platform.func() - assert isinstance(platform, archinfo.AppleArm) - assert platform.name == expected + monkeypatch.setattr(archinfo, 'get_cpu_info', lambda: {'brand': brand}) + assert archinfo.get_platform.func() is archinfo.platform_registry[expected] def test_switcharch(): From bc74301f596dc1ec7c70d8405c44ef81af75d35f Mon Sep 17 00:00:00 2001 From: Gerard Gorman Date: Thu, 15 Oct 2026 01:58:25 +0000 Subject: [PATCH 3/3] tests: Drop the Apple-silicon detection test --- tests/test_arch.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/tests/test_arch.py b/tests/test_arch.py index 33fa00418ba..9565c6f08d2 100644 --- a/tests/test_arch.py +++ b/tests/test_arch.py @@ -1,7 +1,6 @@ import pytest from devito import configuration, switchconfig -from devito.arch import archinfo from devito.arch.compiler import GNUCompiler, compiler_registry, sniff_compiler_version @@ -19,17 +18,6 @@ def test_gcc(cc): assert cc in compiler_registry -@pytest.mark.parametrize('brand,expected', [ - ('Apple M1', 'm1'), - ('Apple M2 Pro', 'm2'), - ('Apple M3 Max', 'm3'), - ('Apple M4 Max', 'm3'), -]) -def test_detect_apple_silicon(monkeypatch, brand, expected): - monkeypatch.setattr(archinfo, 'get_cpu_info', lambda: {'brand': brand}) - assert archinfo.get_platform.func() is archinfo.platform_registry[expected] - - def test_switcharch(): old_compiler = configuration['compiler'] with switchconfig(compiler='gcc-4.9'):