Bug 48783

Summary: ~0ULL % (a / (a & -a)) == 0 is not optimized to false on the tree level
Product: gcc Reporter: Michael Hope <michael.hope>
Component: tree-optimizationAssignee: Not yet assigned to anyone <unassigned>
Status: NEW ---    
Severity: normal CC: ams, ramana
Priority: P3 Keywords: missed-optimization, TREE
Version: 4.5.2   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2012-01-28 00:00:00
Attachments: Preprocessed source
Preprocessed source

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
        .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?
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));
    }
}

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.
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 )


cheers
Ramana
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.