Skip to content

Commit 500fc82

Browse files
L-seriesmkannwischer
authored andcommitted
Make: add compiler and host platform feature detection
This commit extends the Makefiles to check both compiler and host CPU capabilities when setting architecture flags with AUTO=1. - Adds test/mk/compiler.mk for compile-time compiler feature detection (AVX2, BMI2, SSE2 for x86_64; SHA3 for AArch64) - test/mk/auto.mk detects host CPU features and only enables flags when both compiler AND host support them - Adds host_info target to display feature detection status - Adds workaround for valgrind SHA3 incompatibility by allowing MK_COMPILER_SUPPORTS_SHA3=0 override on command line - Updated .github/actions/ct-test/action.yml to disable SHA3 for valgrind constant-time tests Adapted from mlkem-native commit 9da1ccd668c5c956b9c367e048a3df611dd9473 Signed-off-by: Andreas Hatziiliou <[email protected]>
1 parent 50b2bb5 commit 500fc82

File tree

5 files changed

+216
-32
lines changed

5 files changed

+216
-32
lines changed

.github/actions/ct-test/action.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,5 @@ runs:
4646
# It may increase run-time of the valgrind tests.
4747
# TODO: Check with future versions of valgrind if this is still needed (both 3.24 and 3.25 fail without)
4848
# TODO: Check if this is still needed once the poly_chknorm intrinsics implementation is replaced by assembly
49-
tests func --exec-wrapper="valgrind --vex-guest-max-insns=55 --error-exitcode=1 ${{ inputs.valgrind_flags }}" --cflags="-DMLD_CONFIG_CT_TESTING_ENABLED -DNTESTS=5 ${{ inputs.cflags }}"
49+
# Disable the AArch64 SHA3 extension as it's not yet supported by valgrind
50+
MK_COMPILER_SUPPORTS_SHA3=0 tests func --exec-wrapper="valgrind --vex-guest-max-insns=55 --error-exitcode=1 ${{ inputs.valgrind_flags }}" --cflags="-DMLD_CONFIG_CT_TESTING_ENABLED -DNTESTS=5 ${{ inputs.cflags }}"

Makefile

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
build test all \
1818
clean quickcheck check-defined-CYCLES \
1919
size_44 size_65 size_87 size \
20-
run_size_44 run_size_65 run_size_87 run_size
20+
run_size_44 run_size_65 run_size_87 run_size \
21+
host_info
2122

2223
SHELL := /bin/bash
2324
.DEFAULT_GOAL := build
@@ -38,6 +39,8 @@ $(error Neither 'shasum' nor 'sha256sum' found. Please install one of these tool
3839
endif
3940

4041
include test/mk/config.mk
42+
include test/mk/compiler.mk
43+
include test/mk/auto.mk
4144
include test/mk/components.mk
4245
include test/mk/rules.mk
4346

@@ -91,6 +94,15 @@ acvp_65: $(MLDSA65_DIR)/bin/acvp_mldsa65
9194
acvp_87: $(MLDSA87_DIR)/bin/acvp_mldsa87
9295
$(Q)echo " ACVP ML-DSA-87: $^"
9396
acvp: acvp_44 acvp_65 acvp_87
97+
98+
ifeq ($(HOST_PLATFORM),Linux-aarch64)
99+
# valgrind does not work with the AArch64 SHA3 extension
100+
# Use armv8-a as the target architecture, overwriting a
101+
# potential earlier addition of armv8.4-a+sha3.
102+
$(MLDSA44_DIR)/bin/test_stack44: CFLAGS += -march=armv8-a
103+
$(MLDSA65_DIR)/bin/test_stack65: CFLAGS += -march=armv8-a
104+
$(MLDSA87_DIR)/bin/test_stack87: CFLAGS += -march=armv8-a
105+
endif
94106

95107
stack_44: $(MLDSA44_DIR)/bin/test_stack44
96108
$(Q)echo " STACK ML-DSA-44: $^"
@@ -178,6 +190,29 @@ run_size: \
178190
run_size_65 \
179191
run_size_87
180192

193+
# Display host and compiler feature detection information
194+
# Shows which architectural features are supported by both the compiler and host CPU
195+
# Usage: make host_info [AUTO=0|1] [CROSS_PREFIX=...]
196+
host_info:
197+
@echo "=== Host and Compiler Feature Detection ==="
198+
@echo "Host Platform: $(HOST_PLATFORM)"
199+
@echo "Target Architecture: $(ARCH)"
200+
@echo "Compiler: $(CC)"
201+
@echo "Cross Prefix: $(if $(CROSS_PREFIX),$(CROSS_PREFIX),<none>)"
202+
@echo "AUTO: $(AUTO)"
203+
@echo ""
204+
ifeq ($(ARCH),x86_64)
205+
@echo "=== x86_64 Feature Support ==="
206+
@echo "AVX2: Host $(if $(filter 1,$(MK_HOST_SUPPORTS_AVX2)),✅,❌) Compiler $(if $(filter 1,$(MK_COMPILER_SUPPORTS_AVX2)),✅,❌)"
207+
@echo "SSE2: Host $(if $(filter 1,$(MK_HOST_SUPPORTS_SSE2)),✅,❌) Compiler $(if $(filter 1,$(MK_COMPILER_SUPPORTS_SSE2)),✅,❌)"
208+
@echo "BMI2: Host $(if $(filter 1,$(MK_HOST_SUPPORTS_BMI2)),✅,❌) Compiler $(if $(filter 1,$(MK_COMPILER_SUPPORTS_BMI2)),✅,❌)"
209+
else ifeq ($(ARCH),aarch64)
210+
@echo "=== AArch64 Feature Support ==="
211+
@echo "SHA3: Host $(if $(filter 1,$(MK_HOST_SUPPORTS_SHA3)),✅,❌) Compiler $(if $(filter 1,$(MK_COMPILER_SUPPORTS_SHA3)),✅,❌)"
212+
else
213+
@echo "=== Architecture Not Supported ==="
214+
@echo "No specific feature detection available for $(ARCH)"
215+
endif
181216

182217
clean:
183218
-$(RM) -rf *.gcno *.gcda *.lcov *.o *.so

test/mk/auto.mk

Lines changed: 103 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,115 @@
22
# Copyright (c) The mldsa-native project authors
33
# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
44

5-
# Automatically detect system architecture and set preprocessor etc accordingly
5+
# Automatically detect system architecture and set preprocessor flags accordingly
6+
# This file detects host CPU capabilities and combines them with compiler support
7+
# to enable optimal compilation flags.
8+
9+
ifndef _AUTO_MK
10+
_AUTO_MK :=
11+
12+
# Helper function to check if host CPU supports a feature
13+
# Usage: $(call check_host_feature,feature_pattern,source_command)
14+
define check_host_feature
15+
$(shell $(2) 2>/dev/null | grep -q "$(1)" && echo 1 || echo 0)
16+
endef
17+
18+
# x86_64 architecture detection
19+
ifeq ($(ARCH),x86_64)
20+
21+
# Host CPU feature detection for x86_64
622
ifeq ($(HOST_PLATFORM),Linux-x86_64)
7-
ifeq ($(CROSS_PREFIX),)
8-
CFLAGS += -mavx2 -mbmi2 -mpopcnt -maes
9-
CFLAGS += -DMLD_FORCE_X86_64
10-
else ifneq ($(findstring aarch64_be, $(CROSS_PREFIX)),)
11-
CFLAGS += -DMLD_FORCE_AARCH64_EB
12-
else ifneq ($(findstring aarch64, $(CROSS_PREFIX)),)
13-
CFLAGS += -DMLD_FORCE_AARCH64
23+
# Linux: Use /proc/cpuinfo
24+
MK_HOST_SUPPORTS_AVX2 := $(call check_host_feature,avx2,cat /proc/cpuinfo)
25+
MK_HOST_SUPPORTS_SSE2 := $(call check_host_feature,sse2,cat /proc/cpuinfo)
26+
MK_HOST_SUPPORTS_BMI2 := $(call check_host_feature,bmi2,cat /proc/cpuinfo)
27+
else ifeq ($(HOST_PLATFORM),Darwin-x86_64)
28+
# macOS: Use sysctl
29+
MK_HOST_SUPPORTS_AVX2 := $(call check_host_feature,AVX2,sysctl -n machdep.cpu.leaf7_features)
30+
MK_HOST_SUPPORTS_SSE2 := $(call check_host_feature,SSE2,sysctl -n machdep.cpu.features)
31+
MK_HOST_SUPPORTS_BMI2 := $(call check_host_feature,BMI2,sysctl -n machdep.cpu.leaf7_features)
32+
else ifneq ($(CROSS_PREFIX),)
33+
# Cross-compilation: assume all features are supported
34+
MK_HOST_SUPPORTS_AVX2 := 1
35+
MK_HOST_SUPPORTS_SSE2 := 1
36+
MK_HOST_SUPPORTS_BMI2 := 1
1437
else
38+
# Other platforms: assume no support
39+
MK_HOST_SUPPORTS_AVX2 := 0
40+
MK_HOST_SUPPORTS_SSE2 := 0
41+
MK_HOST_SUPPORTS_BMI2 := 0
42+
endif # HOST_PLATFORM x86_64
1543

16-
endif
44+
endif # x86_64
1745

18-
# linux aarch64
19-
else ifeq ($(HOST_PLATFORM),Linux-aarch64)
20-
ifeq ($(CROSS_PREFIX),)
21-
CFLAGS += -DMLD_FORCE_AARCH64
22-
else ifneq ($(findstring x86_64, $(CROSS_PREFIX)),)
23-
CFLAGS += -mavx2 -mbmi2 -mpopcnt -maes
24-
CFLAGS += -DMLD_FORCE_X86_64
25-
else
26-
endif
46+
# AArch64 architecture detection
47+
ifeq ($(ARCH),aarch64)
2748

28-
# darwin aarch64
49+
# Host CPU feature detection for AArch64
50+
ifeq ($(HOST_PLATFORM),Linux-aarch64)
51+
# Linux: Use /proc/cpuinfo (look for sha3 in Features line)
52+
MK_HOST_SUPPORTS_SHA3 := $(call check_host_feature,sha3,cat /proc/cpuinfo)
2953
else ifeq ($(HOST_PLATFORM),Darwin-arm64)
30-
ifeq ($(CROSS_PREFIX),)
31-
CFLAGS += -DMLD_FORCE_AARCH64
32-
else ifneq ($(findstring x86_64, $(CROSS_PREFIX)),)
33-
CFLAGS += -DMLD_FORCE_X86_64
34-
else ifneq ($(findstring aarch64, $(CROSS_PREFIX)),)
35-
CFLAGS += -DMLD_FORCE_AARCH64
54+
# macOS: Use sysctl to check for SHA3 support
55+
MK_HOST_SUPPORTS_SHA3 := $(call check_host_feature,1,sysctl -n hw.optional.armv8_2_sha3)
56+
else ifneq ($(CROSS_PREFIX),)
57+
# Cross-compilation: assume all features are supported
58+
MK_HOST_SUPPORTS_SHA3 := 1
3659
else
60+
# Other platforms: assume no support
61+
MK_HOST_SUPPORTS_SHA3 := 0
62+
endif # HOST_PLATFORM aarch64
63+
64+
endif # aarch64
65+
66+
# Only apply CFLAGS modifications if AUTO=1
67+
ifeq ($(AUTO),1)
68+
69+
# x86_64 CFLAGS configuration
70+
ifeq ($(ARCH),x86_64)
71+
CFLAGS += -DMLD_FORCE_X86_64
72+
73+
# Add flags only if both compiler and host support the feature
74+
ifeq ($(MK_COMPILER_SUPPORTS_AVX2)$(MK_HOST_SUPPORTS_AVX2),11)
75+
CFLAGS += -mavx2
3776
endif
77+
78+
ifeq ($(MK_COMPILER_SUPPORTS_BMI2)$(MK_HOST_SUPPORTS_BMI2),11)
79+
CFLAGS += -mbmi2
3880
endif
81+
endif # x86_64
82+
83+
# AArch64 CFLAGS configuration
84+
ifeq ($(ARCH),aarch64)
85+
CFLAGS += -DMLD_FORCE_AARCH64
86+
87+
# Add SHA3 flags only if both compiler and host support it
88+
ifeq ($(MK_COMPILER_SUPPORTS_SHA3)$(MK_HOST_SUPPORTS_SHA3),11)
89+
CFLAGS += -march=armv8.4-a+sha3
90+
endif
91+
endif # aarch64
92+
93+
# AArch64 Big Endian CFLAGS configuration
94+
ifeq ($(ARCH),aarch64_be)
95+
CFLAGS += -DMLD_FORCE_AARCH64_EB
96+
endif # aarch64_be
97+
98+
# RISC-V 64-bit CFLAGS configuration
99+
ifeq ($(ARCH),riscv64)
100+
CFLAGS += -DMLD_FORCE_RISCV64
101+
CFLAGS += -march=rv64gcv
102+
endif # riscv64
103+
104+
# RISC-V 32-bit CFLAGS configuration
105+
ifeq ($(ARCH),riscv32)
106+
CFLAGS += -DMLD_FORCE_RISCV32
107+
endif # riscv32
108+
109+
# PowerPC 64-bit Little Endian CFLAGS configuration
110+
ifeq ($(ARCH),powerpc64le)
111+
CFLAGS += -DMLD_FORCE_PPC64LE
112+
endif # powerpc64le
113+
114+
endif # AUTO=1
115+
116+
endif # _AUTO_MK

test/mk/compiler.mk

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# Copyright (c) The mlkem-native project authors
2+
# Copyright (c) The mldsa-native project authors
3+
# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
4+
#
5+
# Compiler feature detection for mldsa-native
6+
# This file detects whether the compiler supports various architectural features
7+
# used by mldsa-native through compile-time tests with C code containing inline assembly.
8+
#
9+
# Feature detection can be overridden by setting the corresponding variable on the command line:
10+
# make MK_COMPILER_SUPPORTS_SHA3=0 # Disable SHA3 detection
11+
# make MK_COMPILER_SUPPORTS_AVX2=0 # Disable AVX2 detection
12+
# make MK_COMPILER_SUPPORTS_BMI2=0 # Disable BMI2 detection
13+
# make MK_COMPILER_SUPPORTS_SSE2=0 # Disable SSE2 detection
14+
15+
ifndef _COMPILER_MK
16+
_COMPILER_MK :=
17+
18+
19+
# Override ARCH for cross-compilation based on CROSS_PREFIX
20+
ifeq ($(CROSS_PREFIX),)
21+
ARCH := $(shell uname -m)
22+
# Normalize architecture names
23+
ifeq ($(ARCH),arm64)
24+
ARCH := aarch64
25+
endif
26+
else # CROSS_PREFIX
27+
ifneq ($(findstring x86_64, $(CROSS_PREFIX)),)
28+
ARCH := x86_64
29+
else ifneq ($(findstring aarch64_be, $(CROSS_PREFIX)),)
30+
ARCH := aarch64_be
31+
else ifneq ($(findstring aarch64, $(CROSS_PREFIX)),)
32+
ARCH := aarch64
33+
else ifneq ($(findstring riscv64, $(CROSS_PREFIX)),)
34+
ARCH := riscv64
35+
else ifneq ($(findstring riscv32, $(CROSS_PREFIX)),)
36+
ARCH := riscv32
37+
else ifneq ($(findstring powerpc64le, $(CROSS_PREFIX)),)
38+
ARCH := powerpc64le
39+
else ifneq ($(findstring arm-none-eabi-, $(CROSS_PREFIX)),)
40+
ARCH := arm
41+
else
42+
ifeq ($(AUTO),1)
43+
$(warning Unknown cross-compilation prefix $(CROSS_PREFIX), no automatic detection of CFLAGS.)
44+
ARCH := unknown
45+
endif
46+
endif
47+
endif # CROSS_PREFIX
48+
49+
# x86_64 feature detection
50+
ifeq ($(ARCH),x86_64)
51+
52+
# Test AVX2 support using C with inline assembly
53+
# Can be overridden by setting MK_COMPILER_SUPPORTS_AVX2=0/1 on command line
54+
MK_COMPILER_SUPPORTS_AVX2 ?= $(shell echo 'int main() { __asm__("vpxor %%ymm0, %%ymm1, %%ymm2" ::: "ymm0", "ymm1", "ymm2"); return 0; }' | $(CC) -mavx2 -x c - -c -o /dev/null 2>/dev/null && echo 1 || echo 0)
55+
56+
# Test SSE2 support using C with inline assembly
57+
# Can be overridden by setting MK_COMPILER_SUPPORTS_SSE2=0/1 on command line
58+
MK_COMPILER_SUPPORTS_SSE2 ?= $(shell echo 'int main() { __asm__("pxor %%xmm0, %%xmm1" ::: "xmm0", "xmm1"); return 0; }' | $(CC) -msse2 -x c - -c -o /dev/null 2>/dev/null && echo 1 || echo 0)
59+
60+
# Test BMI2 support using C with inline assembly
61+
# Can be overridden by setting MK_COMPILER_SUPPORTS_BMI2=0/1 on command line
62+
MK_COMPILER_SUPPORTS_BMI2 ?= $(shell echo 'int main() { __asm__("pdep %%eax, %%ebx, %%ecx" ::: "eax", "ebx", "ecx"); return 0; }' | $(CC) -mbmi2 -x c - -c -o /dev/null 2>/dev/null && echo 1 || echo 0)
63+
64+
endif # x86_64
65+
66+
# AArch64 feature detection
67+
ifeq ($(ARCH),aarch64)
68+
69+
# Test SHA3 support (Armv8.4-a+SHA3) using C with inline assembly
70+
# Can be overridden by setting MK_COMPILER_SUPPORTS_SHA3=0/1 on command line
71+
MK_COMPILER_SUPPORTS_SHA3 ?= $(shell echo 'int main() { __asm__("eor3 v0.16b, v1.16b, v2.16b, v3.16b" ::: "v0", "v1", "v2", "v3"); return 0; }' | $(CC) -march=armv8.4-a+sha3 -x c - -c -o /dev/null 2>/dev/null && echo 1 || echo 0)
72+
73+
endif # aarch64
74+
75+
endif # _COMPILER_MK

test/mk/config.mk

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,9 @@ $(1)_FROM_ENV := $$($(1))
8989
endef
9090
$(foreach var,$(RETAINED_VARS),$(eval $(call CAPTURE_VAR,$(var))))
9191

92-
AUTO ?= 1
9392
CYCLES ?=
9493
OPT ?= 1
9594

96-
ifeq ($(AUTO),1)
97-
include test/mk/auto.mk
98-
endif
99-
10095
BUILD_DIR ?= test/build
10196

10297
MAKE_OBJS = $(2:%=$(1)/%.o)

0 commit comments

Comments
 (0)