mirror of
https://github.com/libretro/virtualjaguar-libretro.git
synced 2026-11-09 03:39:38 -10:00
Merge pull request #567 from libretro/perf/560-rpi-soc-tuning
perf(build): per-SoC -mcpu and -O3 for every Raspberry Pi target
This commit is contained in:
5 files changed
+342
-26
No files matched your search
@@ -96,6 +96,85 @@ jobs:
|
||||
cxx: 'g++ -m32'
|
||||
multilib: true
|
||||
|
||||
# Raspberry Pi -- per-SoC tuned (issue #560).
|
||||
#
|
||||
# Cross-compiled on x86_64: -mcpu names a core to generate code FOR,
|
||||
# it does not require running on one, so no Pi hardware is needed to
|
||||
# produce these. The per-SoC flags live in the Makefile's rpi*
|
||||
# platform blocks -- do not duplicate them here.
|
||||
#
|
||||
# rpi0 is deliberately absent: it is the same BCM2835/ARM1176 part
|
||||
# as rpi1 and resolves to identical flags, so the rpi1 artifact
|
||||
# serves both. Every other row is a genuinely distinct target.
|
||||
#
|
||||
# 32- and 64-bit rows for the same chip are BOTH needed: they are
|
||||
# different userlands (Raspberry Pi OS ships both), and the 32-bit
|
||||
# ones additionally carry -mfpu/-mfloat-abi, which aarch64 gcc
|
||||
# rejects outright.
|
||||
- platform: linux-rpi1-armv6
|
||||
artifact: virtualjaguar_libretro.so
|
||||
os: ubuntu-latest
|
||||
cc: arm-linux-gnueabihf-gcc
|
||||
cxx: arm-linux-gnueabihf-g++
|
||||
make_extra: platform=rpi1
|
||||
cross_arm: armhf
|
||||
|
||||
- platform: linux-rpi2-cortex-a7
|
||||
artifact: virtualjaguar_libretro.so
|
||||
os: ubuntu-latest
|
||||
cc: arm-linux-gnueabihf-gcc
|
||||
cxx: arm-linux-gnueabihf-g++
|
||||
make_extra: platform=rpi2
|
||||
cross_arm: armhf
|
||||
|
||||
- platform: linux-rpi3-cortex-a53
|
||||
artifact: virtualjaguar_libretro.so
|
||||
os: ubuntu-latest
|
||||
cc: arm-linux-gnueabihf-gcc
|
||||
cxx: arm-linux-gnueabihf-g++
|
||||
make_extra: platform=rpi3
|
||||
cross_arm: armhf
|
||||
|
||||
- platform: linux-rpi3_64-cortex-a53
|
||||
artifact: virtualjaguar_libretro.so
|
||||
os: ubuntu-latest
|
||||
cc: aarch64-linux-gnu-gcc
|
||||
cxx: aarch64-linux-gnu-g++
|
||||
make_extra: platform=rpi3_64
|
||||
cross_arm: arm64
|
||||
|
||||
- platform: linux-rpi4-cortex-a72
|
||||
artifact: virtualjaguar_libretro.so
|
||||
os: ubuntu-latest
|
||||
cc: arm-linux-gnueabihf-gcc
|
||||
cxx: arm-linux-gnueabihf-g++
|
||||
make_extra: platform=rpi4
|
||||
cross_arm: armhf
|
||||
|
||||
- platform: linux-rpi4_64-cortex-a72
|
||||
artifact: virtualjaguar_libretro.so
|
||||
os: ubuntu-latest
|
||||
cc: aarch64-linux-gnu-gcc
|
||||
cxx: aarch64-linux-gnu-g++
|
||||
make_extra: platform=rpi4_64
|
||||
cross_arm: arm64
|
||||
|
||||
- platform: linux-rpi5-cortex-a76
|
||||
artifact: virtualjaguar_libretro.so
|
||||
os: ubuntu-latest
|
||||
cc: arm-linux-gnueabihf-gcc
|
||||
cxx: arm-linux-gnueabihf-g++
|
||||
make_extra: platform=rpi5
|
||||
cross_arm: armhf
|
||||
|
||||
- platform: linux-rpi5_64-cortex-a76
|
||||
artifact: virtualjaguar_libretro.so
|
||||
os: ubuntu-latest
|
||||
cc: aarch64-linux-gnu-gcc
|
||||
cxx: aarch64-linux-gnu-g++
|
||||
make_extra: platform=rpi5_64
|
||||
cross_arm: arm64
|
||||
|
||||
# macOS
|
||||
- platform: macos-arm64
|
||||
artifact: virtualjaguar_libretro.dylib
|
||||
@@ -193,6 +272,21 @@ jobs:
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y gcc-multilib g++-multilib
|
||||
|
||||
# Cross toolchain for the Raspberry Pi rows. Also provides the matching
|
||||
# objcopy: the host x86_64 objcopy in the packaging step below cannot
|
||||
# read an ARM ELF (Ubuntu's binutils is single-target), so the strip /
|
||||
# split-debug step needs the prefixed one.
|
||||
- name: Install ARM cross toolchain
|
||||
if: matrix.config.cross_arm
|
||||
run: |
|
||||
set -e
|
||||
sudo apt-get update
|
||||
if [ "${{ matrix.config.cross_arm }}" = armhf ]; then
|
||||
sudo apt-get install -y gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
|
||||
else
|
||||
sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
|
||||
fi
|
||||
|
||||
- name: Set up MSYS2
|
||||
if: runner.os == 'Windows'
|
||||
uses: msys2/setup-msys2@v2
|
||||
@@ -259,9 +353,17 @@ jobs:
|
||||
OUT="virtualjaguar_libretro-${{ matrix.config.platform }}${EXT}"
|
||||
DBG="${OUT}.debug"
|
||||
cp "$SRC" "dist/${OUT}"
|
||||
objcopy --only-keep-debug "dist/${OUT}" "dist/${DBG}"
|
||||
objcopy --strip-debug --strip-unneeded "dist/${OUT}"
|
||||
( cd dist && objcopy --add-gnu-debuglink="${DBG}" "${OUT}" )
|
||||
# A cross-built ARM core needs the cross objcopy -- Ubuntu's
|
||||
# binutils is single-target, so the host one cannot read an ARM ELF
|
||||
# and the split-debug step would fail (or, worse, be skipped).
|
||||
case "${{ matrix.config.cross_arm }}" in
|
||||
armhf) OBJCOPY=arm-linux-gnueabihf-objcopy ;;
|
||||
arm64) OBJCOPY=aarch64-linux-gnu-objcopy ;;
|
||||
*) OBJCOPY=objcopy ;;
|
||||
esac
|
||||
"$OBJCOPY" --only-keep-debug "dist/${OUT}" "dist/${DBG}"
|
||||
"$OBJCOPY" --strip-debug --strip-unneeded "dist/${OUT}"
|
||||
( cd dist && "$OBJCOPY" --add-gnu-debuglink="${DBG}" "${OUT}" )
|
||||
tar -C dist -czf "dist/virtualjaguar_libretro-${{ matrix.config.platform }}-debug.tar.gz" "${DBG}"
|
||||
rm "dist/${DBG}"
|
||||
|
||||
|
||||
@@ -48,8 +48,27 @@ endif
|
||||
# compilers again, and the Vita has real memory limits, so neither result
|
||||
# above says anything about them. Measure before adding one.
|
||||
#
|
||||
# The rpi* targets are here by maintainer decision rather than by the
|
||||
# measurement protocol above: the Pi platform names identify the silicon
|
||||
# exactly, and every one of them is a small in-order or narrow out-of-order
|
||||
# core with no headroom to spare, which is the case -O3 helps most. The
|
||||
# closest evidence we have is the +5.5% measured on macOS arm64 (#515) --
|
||||
# same ISA family, different compiler. Re-measure on real hardware when a
|
||||
# Pi is available; test/tools/rpi_perf.sh exists for exactly that.
|
||||
#
|
||||
# -Ofast was considered and REJECTED for these. Its headline implication is
|
||||
# -ffast-math, which #517 measured at ~0% here (the hot loops are integer;
|
||||
# the only floating point is a SAVESTATED I2S resampler and event
|
||||
# scheduling) and then removed globally as a latent determinism hazard.
|
||||
# Determinism is load-bearing in this tree -- run-ahead (#400), netplay, and
|
||||
# savestate compatibility all depend on it -- so -Ofast would reintroduce
|
||||
# exactly what #517 took out, for a measured-zero gain, on a platform people
|
||||
# run netplay on. `make OPT_LEVEL=-Ofast platform=rpi4` still works if you
|
||||
# want to measure it.
|
||||
#
|
||||
# Override on the command line to test: `make OPT_LEVEL=-O2`.
|
||||
OPT_O3_PLATFORMS := unix osx win ios-arm64 ios9 tvos-arm64
|
||||
OPT_O3_PLATFORMS := unix osx win ios-arm64 ios9 tvos-arm64 \
|
||||
rpi0 rpi1 rpi2 rpi3 rpi3_64 rpi4 rpi4_64 rpi5 rpi5_64
|
||||
# classic_armv7_a7 asks for -Ofast in its own platform block and always has.
|
||||
# It never took effect: the shared release branch appended -O2 afterwards and
|
||||
# the last -O wins, so the target silently built at -O2 (issue #516). The
|
||||
@@ -329,22 +348,71 @@ else ifneq (,$(filter arm64 aarch64,$(platform)))
|
||||
# NEON-capable running a 32-bit OS, but rpi1 and rpi0 are ARMv6 (ARM1176) with
|
||||
# no NEON at all, so they are deliberately absent from the NEON list.
|
||||
#
|
||||
# No -mcpu/-mtune and no -O level here. Both are unmeasured on this hardware
|
||||
# and the standing rule from #515/#516/#517 is to measure first -- #516 is
|
||||
# precisely the case of an optimisation flag that looked applied and was not.
|
||||
# PER-SOC TUNING. Unlike a generic ARM target, a Raspberry Pi platform name
|
||||
# identifies the silicon exactly, so -mcpu is a statement of fact rather than
|
||||
# a guess -- which is why these get it and `unix`/`armv7-*` do not.
|
||||
#
|
||||
# rpi0 rpi1 BCM2835 ARM1176JZF-S ARMv6 + VFPv2, NO NEON
|
||||
# rpi2 BCM2836 Cortex-A7 ARMv7-A + NEON-VFPv4
|
||||
# rpi3 BCM2837 Cortex-A53 ARMv8-A, 32-bit userland
|
||||
# rpi4 BCM2711 Cortex-A72 ARMv8-A, 32-bit userland
|
||||
# rpi5 BCM2712 Cortex-A76 ARMv8.2-A, 32-bit userland
|
||||
# *_64 same parts, aarch64 userland
|
||||
#
|
||||
# -mcpu implies -mtune, so both are never passed. -mfpu/-mfloat-abi are
|
||||
# 32-bit-ARM-only options -- aarch64 gcc ERRORS on them -- so they are gated
|
||||
# on the same 64-bit split as ARCH below, not appended blindly.
|
||||
#
|
||||
# rpi2 is the ambiguous one: board revision 1.2 shipped a BCM2837 (A53), but
|
||||
# the libretro `rpi2` name conventionally means the original A7 part, and A7
|
||||
# code runs on an A53 while the reverse is not true. Kept at A7 on purpose.
|
||||
#
|
||||
# -O3 comes from OPT_O3_PLATFORMS at the top of this file, NOT from here --
|
||||
# see the #516 note there. Appending an -O to CFLAGS in a platform block is
|
||||
# exactly the bug that made classic_armv7_a7 silently build at -O2 for years.
|
||||
else ifneq (,$(filter rpi0 rpi1 rpi2 rpi3 rpi3_64 rpi4 rpi4_64 rpi5 rpi5_64,$(platform)))
|
||||
TARGET := $(TARGET_NAME)_libretro.so
|
||||
fpic := -fPIC
|
||||
SHARED := -shared -Wl,--no-undefined -Wl,--version-script=$(LINK_SCRIPT)
|
||||
GC_STYLE := gnu
|
||||
ifneq (,$(filter rpi0 rpi1,$(platform)))
|
||||
RPI_MCPU := arm1176jzf-s
|
||||
else ifeq ($(platform),rpi2)
|
||||
RPI_MCPU := cortex-a7
|
||||
else ifneq (,$(filter rpi3 rpi3_64,$(platform)))
|
||||
RPI_MCPU := cortex-a53
|
||||
else ifneq (,$(filter rpi4 rpi4_64,$(platform)))
|
||||
RPI_MCPU := cortex-a72
|
||||
else
|
||||
RPI_MCPU := cortex-a76
|
||||
endif
|
||||
CFLAGS += -mcpu=$(RPI_MCPU)
|
||||
ifneq (,$(filter rpi3_64 rpi4_64 rpi5_64,$(platform)))
|
||||
ARCH = aarch64
|
||||
else
|
||||
ARCH = arm
|
||||
ifneq (,$(filter rpi2 rpi3 rpi4 rpi5,$(platform)))
|
||||
# 32-bit only. ARMv6 parts get plain VFP; everything else NEON, in
|
||||
# the encoding its ISA level actually provides.
|
||||
ifneq (,$(filter rpi0 rpi1,$(platform)))
|
||||
# -marm is REQUIRED here, not a tuning choice. Debian's armhf
|
||||
# cross toolchain is --with-arch=armv7-a+fp and defaults to
|
||||
# Thumb; ARMv6 has only Thumb-1, and GCC cannot pair Thumb-1
|
||||
# with the hard-float VFP ABI:
|
||||
# sorry, unimplemented: Thumb-1 'hard-float' VFP ABI
|
||||
# A native Pi 1 compiler defaults to ARM mode and never shows
|
||||
# this, so it only bites cross-builds -- i.e. CI. Verified in
|
||||
# an arm-linux-gnueabihf container; A7/A53/A72/A76 build fine
|
||||
# either way and are left on the Thumb-2 default.
|
||||
CFLAGS += -marm -mfpu=vfp -mfloat-abi=hard
|
||||
else ifeq ($(platform),rpi2)
|
||||
CFLAGS += -mfpu=neon-vfpv4 -mfloat-abi=hard
|
||||
HAVE_NEON = 1
|
||||
else
|
||||
CFLAGS += -mfpu=neon-fp-armv8 -mfloat-abi=hard
|
||||
HAVE_NEON = 1
|
||||
endif
|
||||
endif
|
||||
CXXFLAGS += $(CFLAGS)
|
||||
|
||||
else ifneq (,$(findstring armv,$(platform)))
|
||||
TARGET := $(TARGET_NAME)_libretro.so
|
||||
|
||||
+13
-9
@@ -126,15 +126,19 @@ else
|
||||
# Derive ARCH from the toolchain triple when the platform block did not set
|
||||
# it. Issue #560.
|
||||
#
|
||||
# This is the case that reaches actual users. The rules below key on
|
||||
# $(ARCH); the native `uname -m` fallback further down is deliberately
|
||||
# skipped for cross-compilers (BLITTER_CROSS_CC); and no platform block
|
||||
# sets ARCH for a generic `platform=unix` cross-build. So the shipped
|
||||
# "Linux 64-bit (ARM)" buildbot binary -- .gitlab-ci.yml:44, built as
|
||||
# platform=unix with an aarch64- prefixed CC -- matched nothing and fell
|
||||
# through to the SCALAR blitter on hardware where NEON is architecturally
|
||||
# mandatory. The guard written to prevent false detection was, by itself,
|
||||
# forcing the slow path.
|
||||
# The rules below key on $(ARCH); the native `uname -m` fallback further
|
||||
# down is deliberately skipped for cross-compilers (BLITTER_CROSS_CC); and
|
||||
# no platform block sets ARCH for a generic `platform=unix` cross-build. So
|
||||
# a cross-compiled aarch64 build matched nothing and fell through to the
|
||||
# SCALAR blitter on hardware where NEON is architecturally mandatory. The
|
||||
# guard written to prevent false detection was, by itself, forcing the slow
|
||||
# path.
|
||||
#
|
||||
# NOT the official Linux ARM64 cores, to be clear: both the GitLab buildbot
|
||||
# (ci-templates linux-aarch64.yml, `tags: aarch64`) and the GitHub
|
||||
# release/nightly matrix row build NATIVELY with plain `gcc`, so `uname -m`
|
||||
# fired and they always had NEON. This hits cross-builds -- distro
|
||||
# packagers, container cross-compiles, anyone following a cross recipe.
|
||||
#
|
||||
# Only aarch64 is inferred. A 32-bit arm-*-gnueabihf triple says nothing
|
||||
# about NEON (the armhf baseline is VFP; ARMv6 parts such as the Pi 1 and
|
||||
|
||||
@@ -16,6 +16,47 @@ Output: `virtualjaguar_libretro.{dylib,so,dll}`. CI: `make -j4` on Ubuntu (GCC)
|
||||
or `platform=`; `Makefile.common` lists sources. Flags: `-D__LIBRETRO__`, `-DMSB_FIRST`
|
||||
(big-endian).
|
||||
|
||||
## ARM / Raspberry Pi targets
|
||||
|
||||
The `rpi*` platform names identify the silicon exactly, so they carry real per-SoC
|
||||
tuning (issue #560). Everything is resolved in the Makefile's `rpi*` platform block —
|
||||
**never re-specify these on the command line**, and never append an `-O` in a platform
|
||||
block (that is the #516 bug: the last `-O` wins and a later `-O2` silently beat
|
||||
`-Ofast` for years).
|
||||
|
||||
| platform | SoC | core | blitter | flags on top of `-O3` |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `rpi0` `rpi1` | BCM2835 | ARM1176JZF-S (ARMv6) | **scalar** | `-marm -mcpu=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard` |
|
||||
| `rpi2` | BCM2836 | Cortex-A7 | neon | `-mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard` |
|
||||
| `rpi3` / `rpi3_64` | BCM2837 | Cortex-A53 | neon | `-mcpu=cortex-a53` (+`-mfpu=neon-fp-armv8 -mfloat-abi=hard` on 32-bit) |
|
||||
| `rpi4` / `rpi4_64` | BCM2711 | Cortex-A72 | neon | `-mcpu=cortex-a72` (same 32-bit addition) |
|
||||
| `rpi5` / `rpi5_64` | BCM2712 | Cortex-A76 | neon | `-mcpu=cortex-a76` (same 32-bit addition) |
|
||||
|
||||
Three traps, all verified in an `arm-linux-gnueabihf` container:
|
||||
|
||||
- **`-mfpu` / `-mfloat-abi` are 32-bit-ARM only.** `aarch64-linux-gnu-gcc` hard-errors
|
||||
(`unrecognized command-line option '-mfpu=neon-fp-armv8'`), so a `*_64` row that
|
||||
acquires one does not build at all.
|
||||
- **`rpi0`/`rpi1` need `-marm`.** Debian's armhf cross toolchain is
|
||||
`--with-arch=armv7-a+fp` and defaults to Thumb; ARMv6 only has Thumb-1, and GCC
|
||||
cannot pair Thumb-1 with hard-float (`sorry, unimplemented: Thumb-1 'hard-float' VFP
|
||||
ABI`). A native Pi 1 compiler defaults to ARM mode, so this bites cross-builds only.
|
||||
- **`rpi1` is scalar on purpose.** ARM1176 has no NEON. Do not "fix" it.
|
||||
|
||||
`-Ofast` is deliberately **not** used: it implies `-ffast-math`, which #517 measured at
|
||||
~0% here and removed globally as a determinism hazard (run-ahead #400, netplay,
|
||||
savestate compat all depend on determinism). `make OPT_LEVEL=-Ofast platform=rpi4`
|
||||
still works if you want to measure it.
|
||||
|
||||
`test/tools/simd_matrix_check.sh` (in `make test`) asserts all of the above — blitter,
|
||||
the *last* `-O`, the expected `-mcpu`, and that 32-bit-only flags stay off 64-bit rows.
|
||||
Release/nightly build all eight via `release.yml`'s matrix, cross-compiled on x86_64
|
||||
(`-mcpu` names a core to generate code *for*; it does not require running on one).
|
||||
|
||||
> The libretro GitLab buildbot cannot do this: `libretro-infrastructure/ci-templates`
|
||||
> has no `rpi*` template (only `linux-aarch64.yml` for ARM Linux), so per-chipset Pi
|
||||
> cores would need a template added upstream.
|
||||
|
||||
**Host builds: prefix `DEVELOPER_DIR=/Library/Developer/CommandLineTools`.** `xcode-select`
|
||||
points at Xcode.app, so bare `make`/`cc` resolve inside an app bundle → macOS raises an App
|
||||
Management prompt on every invocation (dozens per multi-agent run). Same Apple clang, no
|
||||
|
||||
@@ -9,9 +9,11 @@
|
||||
# notice. This script is the thing that notices.
|
||||
#
|
||||
# What it caught when it was written:
|
||||
# * platform=unix with an aarch64- cross CC -- the shipped "Linux 64-bit
|
||||
# (ARM)" buildbot binary -- selected SCALAR on hardware where NEON is
|
||||
# architecturally mandatory.
|
||||
# * platform=unix with an aarch64- CROSS CC selected SCALAR on hardware
|
||||
# where NEON is architecturally mandatory. (Not the official ARM64
|
||||
# Linux cores -- both build natively with plain gcc, so `uname -m`
|
||||
# fired and they always had NEON. This hit cross-builds: distro
|
||||
# packagers, container cross-compiles.)
|
||||
# * armv7-neon-hardfloat, a platform named after NEON, selected SCALAR.
|
||||
# * every rpi* name fell through to the Windows branch and built a .dll.
|
||||
#
|
||||
@@ -47,7 +49,7 @@ trap 'rm -f "$PROBE"' EXIT
|
||||
# quotes keep make's $(...) out of the shell's hands.
|
||||
{
|
||||
printf 'vjsimd:\n'
|
||||
printf '\t@echo "SIMD=$(notdir $(BLITTER_SIMD_SRC)) TARGET=$(notdir $(TARGET))"\n'
|
||||
printf '\t@echo "SIMD=$(notdir $(BLITTER_SIMD_SRC)) TARGET=$(notdir $(TARGET)) CFLAGS=$(CFLAGS)"\n'
|
||||
} > "$PROBE"
|
||||
|
||||
fail=0
|
||||
@@ -63,8 +65,26 @@ dump() {
|
||||
# -n prints the *unexecuted* `echo "SIMD=... TARGET=..."` line, quotes and
|
||||
# all, so strip the quotes before matching or the first token anchors to a
|
||||
# `"` and silently never matches.
|
||||
make -n -f Makefile -f "$PROBE" vjsimd platform="$plat" "$@" 2>/dev/null \
|
||||
| tr -d '"' | tr ' ' '\n' | grep -E '^(SIMD|TARGET)=' | tr '\n' ' '
|
||||
# `env -u MAKEFLAGS` is load-bearing, not tidiness. GNU make passes
|
||||
# command-line variables to sub-makes through MAKEFLAGS, and this script
|
||||
# runs from inside `make test` -- so under `make coverage`, which invokes
|
||||
# `$(MAKE) COVERAGE=1 TEST_EXPORTS=1 test`, the probe below would inherit
|
||||
# COVERAGE=1 and see `FLAGS += --coverage -O0 -g` appended after the
|
||||
# resolved level. Every rpi row then reports "last -O is -O0", which is
|
||||
# the Makefile behaving CORRECTLY for a coverage build and this check
|
||||
# asking the wrong question.
|
||||
#
|
||||
# The question these assertions exist to answer is what a RELEASE build
|
||||
# resolves to, so the probe must be independent of whatever axes the
|
||||
# calling make happens to carry. The explicit empty assignments pin the
|
||||
# rest of BUILD_AXES for the same reason -- a future `make test` variant
|
||||
# that sets DEBUG=1 would otherwise silently move the answer again.
|
||||
env -u MAKEFLAGS -u MFLAGS -u MAKELEVEL \
|
||||
make -n -f Makefile -f "$PROBE" vjsimd platform="$plat" \
|
||||
COVERAGE= DEBUG= TEST_EXPORTS= BENCH_PROFILE= BLITTER_TRACE= \
|
||||
RELEASE_DEBUG_INFO= DEBUG_PRESENTATION= STATIC_LINKING= \
|
||||
"$@" 2>/dev/null \
|
||||
| tr -d '"' | sed -n 's/.*\(SIMD=.*\)/\1/p' | head -1
|
||||
}
|
||||
|
||||
# expect <expected-simd> <platform> [CC=...] -- '*' to skip the SIMD check
|
||||
@@ -110,11 +130,71 @@ expect() {
|
||||
return 0
|
||||
}
|
||||
|
||||
# expect_tune <platform> <expected-last-O> <expected-mcpu|-> <expect-32bit-fp:yes|no>
|
||||
#
|
||||
# Guards issue #516, which is a DIFFERENT failure from the SIMD one above and
|
||||
# needs its own assertion: classic_armv7_a7 asked for -Ofast in its platform
|
||||
# block for years and silently built at -O2, because the shared release branch
|
||||
# appended -O2 afterwards and the LAST -O wins. Nothing noticed, because a
|
||||
# wrong -O level -- exactly like a wrong blitter -- compiles, links and passes
|
||||
# every functional test.
|
||||
#
|
||||
# So this asserts the resolved level is the last -O in CFLAGS, not merely
|
||||
# present, and that exactly one -O appears at all.
|
||||
#
|
||||
# It also asserts -mfpu/-mfloat-abi appear ONLY on 32-bit ARM: aarch64 gcc
|
||||
# hard-errors on them ("unrecognized command-line option '-mfpu=neon-fp-armv8'"),
|
||||
# so leaking one onto a *_64 row breaks that build outright.
|
||||
expect_tune() {
|
||||
local plat="$1" want_o="$2" want_mcpu="$3" want_fp="$4"
|
||||
local got cflags last_o n_o mcpu has_fp
|
||||
|
||||
checked=$((checked + 1))
|
||||
got="$(dump "$plat")"
|
||||
cflags="$(printf '%s' "$got" | sed -n 's/.*CFLAGS=//p')"
|
||||
|
||||
if [ -z "$cflags" ]; then
|
||||
printf 'FAIL %-42s could not read CFLAGS\n' "$plat"; fail=$((fail + 1)); return
|
||||
fi
|
||||
|
||||
last_o="$(printf '%s' "$cflags" | tr ' ' '\n' | grep -E '^-O' | tail -1)"
|
||||
n_o="$( printf '%s' "$cflags" | tr ' ' '\n' | grep -cE '^-O')"
|
||||
mcpu="$( printf '%s' "$cflags" | tr ' ' '\n' | grep -E '^-mcpu=' | tail -1)"
|
||||
has_fp="$(printf '%s' "$cflags" | tr ' ' '\n' | grep -cE '^-(mfpu=|mfloat-abi=)')"
|
||||
|
||||
if [ "$last_o" != "$want_o" ]; then
|
||||
printf 'FAIL %-42s last -O is %s, expected %s (issue #516)\n' "$plat" "${last_o:-none}" "$want_o"
|
||||
fail=$((fail + 1)); return
|
||||
fi
|
||||
if [ "$n_o" -ne 1 ]; then
|
||||
printf 'FAIL %-42s %s -O flags in CFLAGS; expected exactly 1 (issue #516)\n' "$plat" "$n_o"
|
||||
fail=$((fail + 1)); return
|
||||
fi
|
||||
if [ "$want_mcpu" = "-" ]; then
|
||||
if [ -n "$mcpu" ]; then
|
||||
printf 'FAIL %-42s unexpected %s\n' "$plat" "$mcpu"; fail=$((fail + 1)); return
|
||||
fi
|
||||
elif [ "$mcpu" != "-mcpu=$want_mcpu" ]; then
|
||||
printf 'FAIL %-42s -mcpu is %s, expected -mcpu=%s\n' "$plat" "${mcpu:-none}" "$want_mcpu"
|
||||
fail=$((fail + 1)); return
|
||||
fi
|
||||
if [ "$want_fp" = yes ] && [ "$has_fp" -eq 0 ]; then
|
||||
printf 'FAIL %-42s 32-bit ARM row is missing -mfpu/-mfloat-abi\n' "$plat"; fail=$((fail + 1)); return
|
||||
fi
|
||||
if [ "$want_fp" = no ] && [ "$has_fp" -ne 0 ]; then
|
||||
printf 'FAIL %-42s 64-bit row carries -mfpu/-mfloat-abi; aarch64 gcc rejects those\n' "$plat"
|
||||
fail=$((fail + 1)); return
|
||||
fi
|
||||
|
||||
[ "$VERBOSE" = 1 ] && printf 'ok %-42s %s %s\n' "$plat" "$last_o" "${mcpu:-(no -mcpu)}"
|
||||
return 0
|
||||
}
|
||||
|
||||
echo "simd_matrix_check: blitter selection per platform (issue #560)"
|
||||
|
||||
# --- the regression that shipped: cross-compiled ARM64 Linux ---------------
|
||||
# platform=unix + an aarch64 cross CC is .gitlab-ci.yml:44, "Linux 64-bit
|
||||
# (ARM)" -- the binary an actual Raspberry Pi user installs.
|
||||
# --- cross-compiled ARM64 Linux --------------------------------------------
|
||||
# Not what the official runners do (they are native), but what a distro
|
||||
# packager or a container cross-build does.
|
||||
expect neon unix CC=aarch64-linux-gnu-gcc
|
||||
expect neon unix CC=aarch64-none-linux-gnu-gcc
|
||||
# 32-bit armhf says nothing about NEON (VFP baseline, and ARMv6 parts exist),
|
||||
@@ -161,6 +241,27 @@ case "$(uname -m 2>/dev/null)" in
|
||||
*) expect '*' unix ;;
|
||||
esac
|
||||
|
||||
# --- per-SoC tuning and optimisation level (issues #560, #516) --------------
|
||||
# The Pi platform names identify the silicon exactly, so -mcpu is a fact here
|
||||
# rather than a guess. rpi0/rpi1 are ARMv6 (ARM1176, no NEON); the rest are
|
||||
# A7/A53/A72/A76.
|
||||
echo
|
||||
echo "simd_matrix_check: -O level and per-SoC tuning (issues #516, #560)"
|
||||
expect_tune rpi0 -O3 arm1176jzf-s yes
|
||||
expect_tune rpi1 -O3 arm1176jzf-s yes
|
||||
expect_tune rpi2 -O3 cortex-a7 yes
|
||||
expect_tune rpi3 -O3 cortex-a53 yes
|
||||
expect_tune rpi3_64 -O3 cortex-a53 no
|
||||
expect_tune rpi4 -O3 cortex-a72 yes
|
||||
expect_tune rpi4_64 -O3 cortex-a72 no
|
||||
expect_tune rpi5 -O3 cortex-a76 yes
|
||||
expect_tune rpi5_64 -O3 cortex-a76 no
|
||||
# The target #516 was actually about: -Ofast must survive to the end.
|
||||
expect_tune classic_armv7_a7 -Ofast - yes
|
||||
# Non-Pi ARM must NOT acquire -mcpu -- we do not know their silicon.
|
||||
expect_tune tvos-arm64 -O3 - no
|
||||
expect_tune vita -O2 - no
|
||||
|
||||
echo
|
||||
if [ "$fail" -ne 0 ]; then
|
||||
echo "simd_matrix_check: FAILED ($fail of $checked rows)"
|
||||
|
||||
Reference in new issue
Block a user