ClangBuiltLinux/linux

__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

AFAICT, there is no division by constant here; so https://reviews.llvm.org/D130862 won't/doesn't help.

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.

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.