mirror of
https://git.tukaani.org/xz.git
synced 2025-12-17 10:58:45 +00:00
tuklib_integer: Autodetect when -mstrict-align is used with GCC on ARM64
On ARM64, support for fast unaligned memory access was autodetected by
checking if __ARM_FEATURE_UNALIGNED is defined. However, at least GCC
versions up to 15.2.0 define the macro even when -mstrict-align has
been specified. Thus, autodetection with GCC doesn't work correctly,
and binaries built using -mstrict-align can be much slower than they
need to be, unless the user also passes --disable-unaligned-access
to configure or -DTUKLIB_FAST_UNALIGNED_ACCESS=OFF to cmake.
See the GCC bug:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111555
Workaround the issue by using heuristics with GCC on ARM64.
With Clang, the detection using __ARM_FEATURE_UNALIGNED works.
It also works with GCC on 32-bit ARM.
Fixes: e5f13a66567b ("tuklib_integer: Autodetect support for unaligned access on ARM.")
This commit is contained in:
parent
d9b318f5b8
commit
c690101ddd
@ -159,24 +159,16 @@ function(tuklib_integer TARGET_OR_ALL)
|
|||||||
set(FAST_UNALIGNED_GUESS ON)
|
set(FAST_UNALIGNED_GUESS ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
elseif(PROCESSOR MATCHES "^arm|^aarch64|^riscv")
|
elseif(PROCESSOR MATCHES "^arm|^riscv" AND NOT PROCESSOR MATCHES "^arm64")
|
||||||
# On 32-bit and 64-bit ARM, GCC and Clang
|
# On 32-bit ARM, GCC and Clang # #define __ARM_FEATURE_UNALIGNED
|
||||||
# #define __ARM_FEATURE_UNALIGNED if
|
# if and only if unaligned access is supported.
|
||||||
# unaligned access is supported.
|
|
||||||
#
|
|
||||||
# Exception: GCC at least up to 13.2.0
|
|
||||||
# defines it even when using -mstrict-align
|
|
||||||
# so in that case this autodetection goes wrong.
|
|
||||||
# Most of the time -mstrict-align isn't used so it
|
|
||||||
# shouldn't be a common problem in practice. See:
|
|
||||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111555
|
|
||||||
#
|
#
|
||||||
# RISC-V C API Specification says that if
|
# RISC-V C API Specification says that if
|
||||||
# __riscv_misaligned_fast is defined then
|
# __riscv_misaligned_fast is defined then
|
||||||
# unaligned access is known to be fast.
|
# unaligned access is known to be fast.
|
||||||
#
|
#
|
||||||
# MSVC is handled as a special case: We assume that
|
# MSVC is handled as a special case: We assume that
|
||||||
# 32/64-bit ARM supports fast unaligned access.
|
# 32-bit ARM supports fast unaligned access.
|
||||||
# If MSVC gets RISC-V support then this will assume
|
# If MSVC gets RISC-V support then this will assume
|
||||||
# fast unaligned access on RISC-V too.
|
# fast unaligned access on RISC-V too.
|
||||||
check_c_source_compiles("
|
check_c_source_compiles("
|
||||||
@ -192,6 +184,53 @@ function(tuklib_integer TARGET_OR_ALL)
|
|||||||
set(FAST_UNALIGNED_GUESS ON)
|
set(FAST_UNALIGNED_GUESS ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
elseif(PROCESSOR MATCHES "^aarch64|^arm64")
|
||||||
|
# On ARM64, Clang defines __ARM_FEATURE_UNALIGNED if and only if
|
||||||
|
# unaligned access is supported. However, GCC (at least up to 15.2.0)
|
||||||
|
# defines it even when using -mstrict-align, so autodetection with
|
||||||
|
# this macro doesn't work with GCC on ARM64. (It does work on
|
||||||
|
# 32-bit ARM.) See:
|
||||||
|
#
|
||||||
|
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111555
|
||||||
|
#
|
||||||
|
# We need three checks:
|
||||||
|
#
|
||||||
|
# 1. If __ARM_FEATURE_UNALIGNED is defined and the
|
||||||
|
# compiler isn't GCC, unaligned access is enabled.
|
||||||
|
# If the compiler is MSVC, unaligned access is
|
||||||
|
# enabled even without __ARM_FEATURE_UNALIGNED.
|
||||||
|
check_c_source_compiles("
|
||||||
|
#if defined(__ARM_FEATURE_UNALIGNED) \
|
||||||
|
&& (!defined(__GNUC__) || defined(__clang__))
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
#else
|
||||||
|
compile error
|
||||||
|
#endif
|
||||||
|
int main(void) { return 0; }
|
||||||
|
"
|
||||||
|
TUKLIB_FAST_UNALIGNED_DEFINED_BY_PREPROCESSOR)
|
||||||
|
if(TUKLIB_FAST_UNALIGNED_DEFINED_BY_PREPROCESSOR)
|
||||||
|
set(FAST_UNALIGNED_GUESS ON)
|
||||||
|
else()
|
||||||
|
# 2. If __ARM_FEATURE_UNALIGNED is not defined,
|
||||||
|
# unaligned access is disabled.
|
||||||
|
check_c_source_compiles("
|
||||||
|
#ifdef __ARM_FEATURE_UNALIGNED
|
||||||
|
compile error
|
||||||
|
#endif
|
||||||
|
int main(void) { return 0; }
|
||||||
|
"
|
||||||
|
TUKLIB_FAST_UNALIGNED_NOT_DEFINED_BY_PREPROCESSOR)
|
||||||
|
if(NOT TUKLIB_FAST_UNALIGNED_NOT_DEFINED_BY_PREPROCESSOR)
|
||||||
|
# 3. Use heuristics to detect if -mstrict-align is
|
||||||
|
# in effect when building with GCC.
|
||||||
|
tuklib_integer_internal_strict_align("[ \t]ldrb[ \t]")
|
||||||
|
if(NOT TUKLIB_INTEGER_STRICT_ALIGN)
|
||||||
|
set(FAST_UNALIGNED_GUESS ON)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
elseif(PROCESSOR MATCHES "^loongarch")
|
elseif(PROCESSOR MATCHES "^loongarch")
|
||||||
tuklib_integer_internal_strict_align("[ \t]ld\\.bu[ \t]")
|
tuklib_integer_internal_strict_align("[ \t]ld\\.bu[ \t]")
|
||||||
if(NOT TUKLIB_INTEGER_STRICT_ALIGN)
|
if(NOT TUKLIB_INTEGER_STRICT_ALIGN)
|
||||||
|
|||||||
@ -130,34 +130,74 @@ if test "x$enable_unaligned_access" = xauto ; then
|
|||||||
i?86|x86_64|powerpc|powerpc64|powerpc64le)
|
i?86|x86_64|powerpc|powerpc64|powerpc64le)
|
||||||
enable_unaligned_access=yes
|
enable_unaligned_access=yes
|
||||||
;;
|
;;
|
||||||
arm*|aarch64*|riscv*)
|
arm*|riscv*)
|
||||||
# On 32-bit and 64-bit ARM, GCC and Clang
|
# On 32-bit ARM, GCC and Clang
|
||||||
# #define __ARM_FEATURE_UNALIGNED if
|
# #define __ARM_FEATURE_UNALIGNED
|
||||||
# unaligned access is supported.
|
# if and only if unaligned access is supported.
|
||||||
#
|
|
||||||
# Exception: GCC at least up to 13.2.0
|
|
||||||
# defines it even when using -mstrict-align
|
|
||||||
# so in that case this autodetection goes wrong.
|
|
||||||
# Most of the time -mstrict-align isn't used so it
|
|
||||||
# shouldn't be a common problem in practice. See:
|
|
||||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111555
|
|
||||||
#
|
#
|
||||||
# RISC-V C API Specification says that if
|
# RISC-V C API Specification says that if
|
||||||
# __riscv_misaligned_fast is defined then
|
# __riscv_misaligned_fast is defined then
|
||||||
# unaligned access is known to be fast.
|
# unaligned access is known to be fast.
|
||||||
#
|
#
|
||||||
# MSVC is handled as a special case: We assume that
|
# MSVC is handled as a special case: We assume that
|
||||||
# 32/64-bit ARM supports fast unaligned access.
|
# 32-bit ARM supports fast unaligned access.
|
||||||
# If MSVC gets RISC-V support then this will assume
|
# If MSVC gets RISC-V support then this will assume
|
||||||
# fast unaligned access on RISC-V too.
|
# fast unaligned access on RISC-V too.
|
||||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
|
||||||
#if !defined(__ARM_FEATURE_UNALIGNED) \
|
#if !defined(__ARM_FEATURE_UNALIGNED) \
|
||||||
&& !defined(__riscv_misaligned_fast) \
|
&& !defined(__riscv_misaligned_fast) \
|
||||||
&& !defined(_MSC_VER)
|
&& !defined(_MSC_VER)
|
||||||
compile error
|
compile error
|
||||||
#endif
|
#endif
|
||||||
int main(void) { return 0; }
|
int main(void) { return 0; }
|
||||||
])], [enable_unaligned_access=yes], [enable_unaligned_access=no])
|
])],
|
||||||
|
[enable_unaligned_access=yes],
|
||||||
|
[enable_unaligned_access=no])
|
||||||
|
;;
|
||||||
|
aarch64*)
|
||||||
|
# On ARM64, Clang defines __ARM_FEATURE_UNALIGNED
|
||||||
|
# if and only if unaligned access is supported.
|
||||||
|
# However, GCC (at least up to 15.2.0) defines it
|
||||||
|
# even when using -mstrict-align, so autodetection
|
||||||
|
# with this macro doesn't work with GCC on ARM64.
|
||||||
|
# (It does work on 32-bit ARM.) See:
|
||||||
|
#
|
||||||
|
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111555
|
||||||
|
#
|
||||||
|
# We need three checks:
|
||||||
|
#
|
||||||
|
# 1. If __ARM_FEATURE_UNALIGNED is defined and the
|
||||||
|
# compiler isn't GCC, unaligned access is enabled.
|
||||||
|
# If the compiler is MSVC, unaligned access is
|
||||||
|
# enabled even without __ARM_FEATURE_UNALIGNED.
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
|
||||||
|
#if defined(__ARM_FEATURE_UNALIGNED) \
|
||||||
|
&& (!defined(__GNUC__) \
|
||||||
|
|| defined(__clang__))
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
#else
|
||||||
|
compile error
|
||||||
|
#endif
|
||||||
|
int main(void) { return 0; }
|
||||||
|
])], [enable_unaligned_access=yes])
|
||||||
|
|
||||||
|
# 2. If __ARM_FEATURE_UNALIGNED is not defined,
|
||||||
|
# unaligned access is disabled.
|
||||||
|
if test "x$enable_unaligned_access" = xauto ; then
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
|
||||||
|
#ifdef __ARM_FEATURE_UNALIGNED
|
||||||
|
compile error
|
||||||
|
#endif
|
||||||
|
int main(void) { return 0; }
|
||||||
|
])], [enable_unaligned_access=no])
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 3. Use heuristics to detect if -mstrict-align is
|
||||||
|
# in effect when building with GCC.
|
||||||
|
if test "x$enable_unaligned_access" = xauto ; then
|
||||||
|
[tuklib_integer_strict_align \
|
||||||
|
'[[:blank:]]ldrb[[:blank:]]']
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
loongarch*)
|
loongarch*)
|
||||||
# See sections 7.4, 8.1, and 8.2:
|
# See sections 7.4, 8.1, and 8.2:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user