Created attachment 24107 [details] Preprocessed source 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. To reproduce: * 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. I get: .global __aeabi_uidiv .global __aeabi_uidivmod .align 2 .thumb .thumb_func .type pll_factors, %function pll_factors: .fnstart [.....] .L54: ldrb r3, [r6, #0] @ zero_extendqisi2 mov r0, r7 mov r1, r4 bfi r3, r5, #1, #4 strb r3, [r6, #0] bl __aeabi_uidivmod 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] Preprocessed source
Somewhat reduced testcase: static void f (unsigned int a) { unsigned long long __res; if (~0ULL % (a / (a & -a)) == 0) { asm ("": "+&r" (__res)); } } int g (unsigned int a) { f (a); } This gives: .global __aeabi_uidiv .global __aeabi_uldivmod .text .align 2 .global g .thumb .thumb_func .type g, %function g: .fnstart .LFB1: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 push {lr} .save {lr} ldr pc, [sp], #4 .fnend 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 ) cheers Ramana
~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.
Note the reduced testcase in comment #4 has been fixed since GCC 5 but I think the original issue is still there ...
See also thread starting at https://inbox.sourceware.org/gcc-patches/20221208105944.660323-1-jose.marchesi@oracle.com/ .
Note https://gcc.gnu.org/pipermail/gcc-patches/2023-August/627864.html