Bug 48783 - ~0ULL % (a / (a & -a)) == 0 is not optimized to false on the tree level
Summary: ~0ULL % (a / (a & -a)) == 0 is not optimized to false on the tree level
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.5.2
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
Keywords: missed-optimization, TREE
Depends on:
Reported: 2011-04-26 23:45 UTC by Michael Hope
Modified: 2012-01-29 01:44 UTC (History)
2 users (show)

See Also:
Known to work:
Known to fail:
Last reconfirmed: 2012-01-28 00:00:00

Preprocessed source (135.27 KB, application/x-gzip)
2011-04-26 23:45 UTC, Michael Hope
Preprocessed source (135.26 KB, application/x-gzip)
2011-04-27 09:54 UTC, Michael Hope

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Hope 2011-04-26 23:45:08 UTC
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.
Comment 1 Andrew Stubbs 2011-04-27 09:15:08 UTC
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
        .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]
        bl      __aeabi_uidivmod
        movw    r5, #52429
        movt    r5, 52428
        mov     r0, #167772160
        umull   r0, r1, r1, r0

I can't find a bug here?
Comment 2 Michael Hope 2011-04-27 09:52:09 UTC
Sorry, the original attachment included the __attribute__((noinline)) workaround on pll_factors().  Attached is the original that shows the fault.
Comment 3 Michael Hope 2011-04-27 09:54:56 UTC
Created attachment 24111 [details]
Preprocessed source
Comment 4 Andrew Stubbs 2011-04-27 11:08:10 UTC
Somewhat reduced testcase:

static void
f (unsigned int a)
  unsigned long long __res;
  if (~0ULL % (a / (a & -a)) == 0)
      asm ("": "+&r" (__res));

g (unsigned int a)
  f (a);

This gives:

        .global __aeabi_uidiv
        .global __aeabi_uldivmod
        .align  2
        .global g
        .type   g, %function
        @ args = 0, pretend = 0, frame = 0
        @ frame_needed = 0, uses_anonymous_args = 0
        push    {lr}
        .save {lr}
        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.
Comment 5 Ramana Radhakrishnan 2011-05-31 22:28:11 UTC
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 )

Comment 6 Andrew Pinski 2012-01-29 01:44:28 UTC
~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.