__aeabi_uldivmod in float64_rem() after LLVM commit 3bc09c7da50a7bb2df51b1829f837f017da5ee34
nathanchance opened this issue · 10 comments
After llvm/llvm-project@3bc09c7, I see the following error while building ARCH=arm allmodconfig
:
ld.lld: error: undefined symbol: __aeabi_uldivmod
>>> referenced by softfloat.c
>>> nwfpe/softfloat.o:(float64_rem) in archive arch/arm/built-in.a
>>> did you mean: __aeabi_uidivmod
>>> defined in: arch/arm/lib/lib.a(lib1funcs.o)
arch/arm/nwfpe/softfloat.c
is kind of dense, I reduced out the following using cvise
:
$ cat softfloat.i
long float64_rem_b;
long long float64_rem_aSig;
void float64_rem() {
unsigned bSig = float64_rem_b | 10000000000000;
do
float64_rem_aSig -= bSig;
while (0 <= float64_rem_aSig);
}
$ clang --target=arm-linux-gnueabi -O2 -c -o softfloat.{o,i}
$ llvm-nm softfloat.o
U __aeabi_uldivmod
00000000 T float64_rem
00000008 B float64_rem_aSig
00000000 B float64_rem_b
cc @preames
AFAICT, there is no division by constant here; so https://reviews.llvm.org/D130862 won't/doesn't help.
Android is hitting this now with https://android-review.googlesource.com/c/kernel/common/+/2237552.
So it looks like https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/nwfpe/softfloat.c is based on this library: http://www.jhauser.us/arithmetic/SoftFloat.html. Specifically, it seems like what's in tree is an old version of the version 2 release. Looks like the latest release is version 3 which looks like a rewrite, but for version 2 there's a version 2c that has an updated implementation of float64_rem
. Maybe the updated version doesn't have this issue? If so, then maybe we can update just that function?
EDIT: Oh, maybe /tmp/SoftFloat-2c/softfloat/bits64/softfloat.c is the version the kernel is using? Now called f64_rem
in /tmp/SoftFloat-3e/source/f64_rem.c?
diff --git a/arch/arm/nwfpe/softfloat.c b/arch/arm/nwfpe/softfloat.c
index ffa6b438786b..a0a7bae0b8b9 100644
--- a/arch/arm/nwfpe/softfloat.c
+++ b/arch/arm/nwfpe/softfloat.c
@@ -2309,7 +2309,7 @@ float64 float64_rem( struct roundingData *roundData, float64 a, float64 b )
do {
alternateASig = aSig;
++q;
- aSig -= bSig;
+ /*aSig -= bSig;*/
} while ( 0 <= (sbits64) aSig );
sigMean = aSig + alternateASig;
if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) {
makes the __aeabi_uldivmod
emission go away. Obviously not correct, but potentially a clue. This is visible in the reproducer script from @nathanchance.
submitted to RMK's queue: https://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=9256/1
The workaround appears to be accepted: https://git.kernel.org/next/linux-next/c/3220022038b9a3845eea762af85f1c5694b9f861
The workaround has been merged into mainline: https://git.kernel.org/linus/3220022038b9a3845eea762af85f1c5694b9f861
Ah, sounds like this shouldn't have been picked up by stable for 4.14.y in the current form. CrOS folks are reporting there's no CC_IS_CLANG there.