summaryrefslogtreecommitdiff
path: root/arch/arm/insert_string_acle.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/insert_string_acle.c')
-rw-r--r--arch/arm/insert_string_acle.c42
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