@@ -37,7 +37,175 @@ LIBVER_PATCH := $(shell echo $(LIBVER_PATCH_SCRIPT))
3737LIBVER := $(LIBVER_MAJOR ) .$(LIBVER_MINOR ) .$(LIBVER_PATCH )
3838
3939MAKEFLAGS += --no-print-directory
40- CFLAGS ?= -O3
40+
41+ # ------------------------------------------------------------------
42+ # Performance tuning for the default build:
43+ #
44+ # For the fully-default invocation only (plain 'make': no CC and no
45+ # CFLAGS supplied on the command line or in the environment, and no
46+ # runtime-dispatch build requested), this Makefile:
47+ # 1. prefers clang over the built-in 'cc' default (clang generates a
48+ # measurably faster XXH3/XXH128 AVX-512 kernel than GCC on this
49+ # class of CPU), and
50+ # 2. adds -march=native to the *default* CFLAGS (the AVX-512 XXH3
51+ # kernel is ~60% faster than the portable SSE2 + runtime-dispatch
52+ # configuration).
53+ # Hash values are unaffected (bit-identical on every architecture).
54+ #
55+ # As soon as the user chooses anything (CC=... or CFLAGS=... on the
56+ # command line or in the environment), behavior is exactly upstream:
57+ # no compiler substitution, no -march=native, and the usual runtime
58+ # vector-dispatch default on x86/x64 (DISPATCH=1).
59+ #
60+ # Knobs:
61+ # NATIVE=0 never add -march=native. Use this (or supply explicit
62+ # CFLAGS=...) before 'make install' when the produced
63+ # binaries/libraries will be copied to other (possibly
64+ # older) machines - native binaries can raise SIGILL on
65+ # CPUs lacking the build host's ISA.
66+ # NATIVE=1 request -march=native even together with an explicit
67+ # CC=... . The flag is still skipped automatically when
68+ # the build cannot or must not use it: cross-compilation
69+ # (a --target/-target/-arch/-m32 style option anywhere in
70+ # CC/CFLAGS/CPPFLAGS/MOREFLAGS, or '$(CC) -dumpmachine'
71+ # reporting a machine different from 'uname -m'), a
72+ # compiler that rejects -march=native, a multi-word or
73+ # shell-unsafe CC value, or any runtime-dispatch build.
74+ # DISPATCH=1 runtime x86 vector-dispatch build. The Makefile then
75+ # never adds -march=native itself, so the baseline code
76+ # paths stay portable (the AVX2/AVX512 kernels are still
77+ # compiled with their own target attributes and selected
78+ # at runtime); explicit user CFLAGS/MOREFLAGS are, as
79+ # always, left untouched. The same no-native rule applies
80+ # to the 'dispatch' target and to LIBXXH_DISPATCH=1.
81+ # When native tuning is off, DISPATCH defaults to 1 on
82+ # x86/x64 exactly like upstream; when native tuning is
83+ # active it defaults to 0 (native codegen already covers
84+ # the host ISA, and this is the configuration the
85+ # documented performance numbers, ~59 GB/s XXH3_64b, were
86+ # measured with).
87+ # CFLAGS=... explicit CFLAGS keep working exactly as before and are
88+ # never modified; supplying them also restores the
89+ # upstream DISPATCH default.
90+ # MOREFLAGS=... appended after CFLAGS as before; unaffected.
91+
92+ # Remember whether the user chose a compiler, before any substitution.
93+ CC_USER_CHOSEN := $(if $(filter default,$(origin CC ) ) ,,1)
94+ ifeq ($(CC_USER_CHOSEN ) ,)
95+ # 'command -v' only ever performs a PATH lookup (no user input is
96+ # re-evaluated by the shell), and the resolved absolute path is a
97+ # single safe token. The assignment is exported so that recursive
98+ # makes (tests/, tests/bench, tests/collisions, ...) build with the
99+ # same compiler as the top-level artifacts.
100+ CLANG_BIN := $(shell command -v clang 2> /dev/null || command -v clang-18 2> /dev/null)
101+ ifneq ($(CLANG_BIN),)
102+ export CC := $(CLANG_BIN )
103+ endif
104+ endif
105+
106+ # CC_SAFE=1 iff CC is a single word containing none of the characters a
107+ # POSIX shell treats specially (; | & $ ` ( ) < > ' " \ or whitespace)
108+ # and no pathname-expansion metacharacter (* ? [ ]). Computed with pure
109+ # make string functions: dangerous characters are removed one by one and
110+ # the result compared to the original - any difference means a
111+ # metacharacter was present. No shell is involved. The awkward
112+ # definitions below exist because some characters cannot appear
113+ # literally in a make function call argument.
114+ EMPTY :=
115+ SPACE := $(EMPTY ) $(EMPTY )
116+ DOLLAR := $$
117+ LPAREN := (
118+ RPAREN := )
119+ CC_STRIPPED := $(CC )
120+ CC_STRIPPED := $(subst ;,,$(CC_STRIPPED ) )
121+ CC_STRIPPED := $(subst |,,$(CC_STRIPPED ) )
122+ CC_STRIPPED := $(subst &,,$(CC_STRIPPED ) )
123+ CC_STRIPPED := $(subst `,,$(CC_STRIPPED ) )
124+ CC_STRIPPED := $(subst ',,$(CC_STRIPPED ) )
125+ CC_STRIPPED := $(subst ",,$(CC_STRIPPED ) )
126+ CC_STRIPPED := $(subst \,,$(CC_STRIPPED ) )
127+ CC_STRIPPED := $(subst <,,$(CC_STRIPPED ) )
128+ CC_STRIPPED := $(subst >,,$(CC_STRIPPED ) )
129+ CC_STRIPPED := $(subst * ,,$(CC_STRIPPED ) )
130+ CC_STRIPPED := $(subst ?,,$(CC_STRIPPED ) )
131+ CC_STRIPPED := $(subst [,,$(CC_STRIPPED ) )
132+ CC_STRIPPED := $(subst ],,$(CC_STRIPPED ) )
133+ CC_STRIPPED := $(subst $(DOLLAR ) ,,$(CC_STRIPPED ) )
134+ CC_STRIPPED := $(subst $(SPACE ) ,,$(CC_STRIPPED ) )
135+ CC_STRIPPED := $(subst $(LPAREN ) ,,$(CC_STRIPPED ) )
136+ CC_STRIPPED := $(subst $(RPAREN ) ,,$(CC_STRIPPED ) )
137+ CC_SAFE := $(and $(filter 1,$(words $(CC ) ) ) ,$(if $(filter x$(CC ) ,x$(CC_STRIPPED ) ) ,1) )
138+
139+ # NATIVE: 1 = add -march=native to the default CFLAGS (when usable),
140+ # 0 = never. Default 'auto' resolves to 1 only for the fully-default
141+ # invocation (CC not chosen by the user, CFLAGS not supplied).
142+ # NATIVE_ON is the internal result: non-empty iff -march=native will be
143+ # added. It is a separate variable because a command-line 'NATIVE=1'
144+ # would override any later file-level reassignment of NATIVE itself.
145+ NATIVE ?= auto
146+ NATIVE_ON :=
147+ ifeq ($(NATIVE ) ,1)
148+ NATIVE_ON := 1
149+ else ifeq ($(NATIVE),auto)
150+ ifeq ($(CC_USER_CHOSEN)$(origin CFLAGS),undefined)
151+ NATIVE_ON := 1
152+ endif
153+ endif
154+ # A runtime-dispatch build must stay portable: never add the native flag
155+ # (this intentionally overrides even an explicit NATIVE=1).
156+ ifneq (,$(filter dispatch,$(MAKECMDGOALS ) )$(filter 1,$(DISPATCH ) $(LIBXXH_DISPATCH ) ) )
157+ NATIVE_ON :=
158+ endif
159+ # Cross-compilation guard #1: a target-selection option anywhere in the
160+ # compile line disables native tuning (covers --target=/-target, Apple
161+ # -arch, and -m32/-mx32/-m16 sub-architecture builds).
162+ ifneq (,$(findstring -target,$(CC ) $(CFLAGS ) $(CPPFLAGS ) $(MOREFLAGS ) )$(filter -arch -m32 -mx32 -m16,$(CC ) $(CFLAGS ) $(CPPFLAGS ) $(MOREFLAGS ) ) )
163+ NATIVE_ON :=
164+ endif
165+ # Remaining guards need to run the compiler; $(CC) is only ever executed
166+ # here when CC_SAFE=1, i.e. a plain single word free of shell
167+ # metacharacters, so the probes cannot execute anything but the named
168+ # compiler. Probe output is filtered by 'tr' so only [A-Za-z0-9._-]
169+ # survive before make compares it.
170+ ifeq ($(NATIVE_ON ) ,1)
171+ ifneq ($(CC_SAFE),1)
172+ NATIVE_ON := # non-plain CC -> stay portable, skip probes
173+ else ifeq ($(findstring $(shell uname -m) ,$(shell $(CC ) -dumpmachine 2> /dev/null | tr -cd 'A-Za-z0-9._-') ) ,)
174+ NATIVE_ON := # cross toolchain, or target undeterminable
175+ else ifneq ($(shell $(CC ) -march=native -E -x c /dev/null > /dev/null 2>&1 && echo 1) ,1)
176+ NATIVE_ON := # compiler does not accept -march=native
177+ endif
178+ endif
179+
180+ # Runtime vector dispatch: upstream defaults DISPATCH to 1 on x86/x64
181+ # targets. That default is preserved in every configuration except the
182+ # fully-default native-tuned build, where it becomes 0 (the whole binary
183+ # is compiled for the host ISA anyway).
184+ detect_x86_arch = $(shell $(CC ) -dumpmachine | grep -E 'i[3-6]86|x86_64')
185+ ifneq ($(strip $(call detect_x86_arch) ) ,)
186+ # note: can be overridden at compile time, by setting DISPATCH=0/1
187+ ifeq ($(NATIVE_ON),1)
188+ DISPATCH ?= 0
189+ else
190+ DISPATCH ?= 1
191+ endif
192+ else
193+ ifeq ($(DISPATCH),1)
194+ $(info "Note : DISPATCH=1 is only supported on x86/x64 targets")
195+ endif
196+ override DISPATCH := 0
197+ endif
198+
199+ # Default CFLAGS. Explicit CFLAGS=... on the command line or in the
200+ # environment is never modified (the '?=' below only fills in a
201+ # make-default CFLAGS; when the user supplied CFLAGS, NATIVE_ON is off).
202+ ifeq ($(NATIVE_ON ) ,1)
203+ CFLAGS ?= -O3 -march=native
204+ else
205+ CFLAGS ?= -O3
206+ endif
207+ # ------------------------------------------------------------------
208+
41209DEBUGFLAGS+ =-Wall -Wextra -Wconversion -Wcast-qual -Wcast-align -Wshadow \
42210 -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \
43211 -Wstrict-prototypes -Wundef -Wpointer-arith -Wformat-security \
54222EXT =
55223endif
56224
57- # automatically enable runtime vector dispatch on x86/64 targets
58- detect_x86_arch = $(shell $(CC ) -dumpmachine | grep -E 'i[3-6]86|x86_64')
59- ifneq ($(strip $(call detect_x86_arch) ) ,)
60- # note: can be overridden at compile time, by setting DISPATCH=0
61- DISPATCH ?= 1
62- else
63- ifeq ($(DISPATCH),1)
64- $(info "Note : DISPATCH=1 is only supported on x86/x64 targets")
65- endif
66- override DISPATCH := 0
67- endif
68-
69225ifeq ($(NODE_JS ) ,1)
70226 # Link in unrestricted filesystem support
71227 LDFLAGS += -sNODERAWFS
@@ -372,7 +528,7 @@ clangtest:
372528.PHONY : gcc-og-test
373529gcc-og-test :
374530 @echo ---- test gcc -Og compilation ----
375- CFLAGS=" -Og -Wall -Wextra -Wundef -Wshadow -Wcast-align -Werror -fPIC" CPPFLAGS=" -DXXH_NO_INLINE_HINTS" MOREFLAGS=" -Werror" $(MAKE ) all
531+ CFLAGS=" -Og -Wall -Wextra -Wundef -Wshadow -Wcast-align -Werror -fPIC" CPPFLAGS=" -DXXH_NO_INLINE_HINTS" MOREFLAGS=" -Werror" $(MAKE ) all CC=gcc
376532
377533.PHONY : cxxtest
378534cxxtest :
0 commit comments