Fix floor()/floorl() on armv7 arm32 devices.
armv8 arm32 has a single instruction for the floor() family, but armv7
arm32 doesn't. Play stupid preprocessor and namespace tricks to get
the best of both worlds (using __ARM_ARCH in code is less awkward than
trying to do similar with armv7_a and armv7_a_neon in the build system).
Bug: http://b/268267713
Test: llvm-objdump -d
Change-Id: I2a4bef6e6caa49092810f53eb7bf6ea46237743f
diff --git a/libm/builtins.cpp b/libm/builtins.cpp
index 779a2d1..96c006d 100644
--- a/libm/builtins.cpp
+++ b/libm/builtins.cpp
@@ -34,7 +34,19 @@
float copysignf(float x, float y) { return __builtin_copysignf(x, y); }
long double copysignl(long double x, long double y) { return __builtin_copysignl(x, y); }
-#if defined(__arm__) || defined(__aarch64__) || defined(__i386__) || defined(__x86_64__)
+#if defined(__arm__) && (__ARM_ARCH < 8)
+// armv8 arm32 has a single-instruction implementation for these, but
+// armv7 arm32 doesn't, so __builtin_ doesn't work for arm32.
+#include "math_private.h"
+namespace s_floor {
+#include "upstream-freebsd/lib/msun/src/s_floor.c"
+}
+namespace s_floorf {
+#include "upstream-freebsd/lib/msun/src/s_floorf.c"
+}
+float floorf(float x) { return s_floorf::floorf(x); }
+double floor(double x) { return s_floor::floor(x); }
+#elif defined(__arm__) || defined(__aarch64__) || defined(__i386__) || defined(__x86_64__)
float floorf(float x) { return __builtin_floorf(x); }
double floor(double x) { return __builtin_floor(x); }
#if defined(__ILP32__)