GCC Bugzilla – Bug 48783
~0ULL % (a / (a & -a)) == 0 is not optimized to false on the tree level
Last modified: 2012-01-29 01:44:28 UTC
Created attachment 24107 [details]
When compiled, the attached code refers to the 64 bit unsigned divmod helper function '__aeabi_uldivmod' even though the function is never called. This causes a link error when cross-compiling an ARM Linux 2.6.38 kernel.
* Make a arm-linux-gnueabi cross compiler configured with --with-mode=thumb --with-arch=armv7-a --with-tune=cortex-a9 --with-float=softfp --with-fpu=neon
* Compile the attached code with 'arm-linux-gnueabi-gcc -O2 -S wm8974.i'
* See a '.global __aeabi_uldivmod' in the header of wm8974_set_dai_pll
Marking pll_factors() as noinline or putting asm("" : "+r"(source)); before the call to do_div() works around the problem.
I don't see any call to __aeabi_uldivmod???
I *do* see __aeabi_uidivmod, and that does seem to be called properly.
.type pll_factors, %function
ldrb r3, [r6, #0] @ zero_extendqisi2
mov r0, r7
mov r1, r4
bfi r3, r5, #1, #4
strb r3, [r6, #0]
movw r5, #52429
movt r5, 52428
mov r0, #167772160
umull r0, r1, r1, r0
I can't find a bug here?
Sorry, the original attachment included the __attribute__((noinline)) workaround on pll_factors(). Attached is the original that shows the fault.
Created attachment 24111 [details]
Somewhat reduced testcase:
f (unsigned int a)
unsigned long long __res;
if (~0ULL % (a / (a & -a)) == 0)
asm ("": "+&r" (__res));
g (unsigned int a)
.type g, %function
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
ldr pc, [sp], #4
So, both __aeabi_uidiv and __aeabi_uldivmod are declared global, but neither is actually used as the code is optimized away.
IIUC the problem is because we externalize the label before the functions have been deleted.
Based on a quick look at the sources, I *think* this comes from the fact that the default definition of ASM_OUTPUT_EXTERNAL_LIBCALL ends up generating a .globl symname and somehow don't think this is a port specific problem ( which I *think* comes from config/elfos.h )
~0ULL % (a / (a & -a)) == 0
Is not optimized to false on the tree level.
Basically we should figure that out and we would then remove the reference to the uldivmod libcall.