diff options
Diffstat (limited to 'arch/arm/insert_string_acle.c')
-rw-r--r-- | arch/arm/insert_string_acle.c | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/arch/arm/insert_string_acle.c b/arch/arm/insert_string_acle.c index 2daf9ba..4fd5fa7 100644 --- a/arch/arm/insert_string_acle.c +++ b/arch/arm/insert_string_acle.c @@ -12,11 +12,49 @@ #include "../../zbuild.h" #include "../../deflate.h" +#if defined(__clang__) +/* CRC32 intrinsics are #ifdef'ed out of arm_acle.h unless we build with an + * armv8 target, which is incompatible with ThinLTO optimizations on Android. + * (Namely, mixing and matching different module-level targets makes ThinLTO + * warn, and Android defaults to armv7-a. This restriction does not apply to + * function-level `target`s, however.) + * + * Since we only need four crc intrinsics, and since clang's implementation of + * those are just wrappers around compiler builtins, it's simplest to #define + * those builtins directly. If this #define list grows too much (or we depend on + * an intrinsic that isn't a trivial wrapper), we may have to find a better way + * to go about this. + * + * NOTE: clang currently complains that "'+soft-float-abi' is not a recognized + * feature for this target (ignoring feature)." This appears to be a harmless + * bug in clang. + */ +#define __crc32b __builtin_arm_crc32b +#define __crc32d __builtin_arm_crc32d +#define __crc32w __builtin_arm_crc32w +#define __crc32cw __builtin_arm_crc32cw + +#if defined(__aarch64__) +#define TARGET_ARMV8_WITH_CRC __attribute__((target("crc"))) +#else // !defined(__aarch64__) +#define TARGET_ARMV8_WITH_CRC __attribute__((target("armv8-a,crc"))) +#endif // defined(__aarch64__) + +#elif defined(__GNUC__) +/* For GCC, we are setting CRC extensions at module level, so ThinLTO is not + * allowed. We can just include arm_acle.h. + */ +#include <arm_acle.h> +#define TARGET_ARMV8_WITH_CRC +#else // !defined(__GNUC__) && !defined(_aarch64__) +#error ARM CRC32 SIMD extensions only supported for Clang and GCC +#endif + #define UPDATE_HASH(s, h, val) \ h = __crc32w(0, val) -#define INSERT_STRING insert_string_acle -#define QUICK_INSERT_STRING quick_insert_string_acle +#define INSERT_STRING TARGET_ARMV8_WITH_CRC insert_string_acle +#define QUICK_INSERT_STRING TARGET_ARMV8_WITH_CRC quick_insert_string_acle #include "../../insert_string_tpl.h" #endif |