It's not a call to the library, it's statically linked with the "real time function" __udivdi3. I'm not sure what real time functions are, but it sounds like they're sort of like inline functions for normal C operations.
From what I can tell, the compiler can't translate: min_free /= 2; to a single operation on 32 bit, so it's replaced with the __udivdi3 call. In userspace, since it's a division by two, you get two bit shifts. In other cases, it would be two divl operations. The kernel can do a double divide by using do_div.
By not including __udiv in the 32-bit libraries, Linus is essentially forcing the programmer to:
A) realize that integer division is costly
B) Manually decide whether to bitshift, or do two divisions with do_div.
64-bit division on 32-bit arch - where's the compiler error?
Posted Aug 30, 2011 2:34 UTC (Tue) by giraffedata (subscriber, #1954)
[Link]
It's not a call to the library, it's statically linked with the "real time function" __udivdi3.
It's a statically linked call to the library. I think you mean "run time function" -- that's what the GCC manual page you point to calls it." It means a function in the GCC runtime library, i.e. libgcc.
__udivdi3() is for use when compiling for a CPU that doesn't have a divide instruction (that used to be pretty common -- divide is a pretty complex instruction; I don't know if it is common now. x86 has always had divide). But if the compiler is smart enough to recognize a divide by two and know you can do that by shifting, I would expect it not to use __udivdi3() on any CPU.
But the error message makes it clear that the compiler in this case generated a call to __udivdi3() when it created btrfs.ko. I assume, then, that this is not x86 because as we've seen, the compiler generates shift instructions instead on x86 (and even if it didn't, it would just generate a divide instruction). I also have to believe the divide-by-shifting cleverness is in a platform-dependent part of GCC and is absent for whatever platform this is.
One other thing to note: we've been saying this is problem with 64 bit numbers on a 32 bit CPU. But __udivdi3() is the divide function for "unsigned long" operands, i.e. on a 32 bit machine it is a 32 bit divide.
The compiler would use __udivti3() instead if it wanted to divide 64 bit numbers.
64-bit division on 32-bit arch - where's the compiler error?
Posted Aug 30, 2011 3:34 UTC (Tue) by nybble41 (subscriber, #55106)
[Link]
> ... we've been saying this is problem with 64 bit numbers on a 32 bit CPU. But __udivdi3() is the divide function for "unsigned long" operands, i.e. on a 32 bit machine it is a 32 bit divide. The compiler would use __udivti3() instead if it wanted to divide 64 bit numbers.
That's not quite correct. The preface to the runtime library section[1] of the GCC Internals manual states that the C types are "for illustrative purposes", and that "these routines take arguments and return values of a specific machine mode, not a specific C type." The Machine Modes section[2] defines SImode, DImode, and TImode as a four-byte integer, an eight-byte integer, and a 16-byte integer, respectively. In other words, in the hypothetical architecture invented to illustrate these library routines, the "int" in __udivsi3() is 32-bit, the "long" in __udivdi3() is 64-bit, and the "long long" in __udivti3() is 128-bit.
A simple test program confirms that 64-bit division generates a call to __udivdi3() in 32-bit mode. Similarly, division of unsigned __int128 values in 64-bit mode generates a call to __udivti3().