2011/4/27 Michael Hope <michael.h...@linaro.org>:
> On Tue, Apr 26, 2011 at 1:48 PM, Barry Song <21cn...@gmail.com> wrote:
>> 2011/4/26 Barry Song <21cn...@gmail.com>:
>>> Hi Michael,
>>>
>>> 2011/4/26 Michael Hope <michael.h...@linaro.org>:
>>>> Hi Barry.  I think the toolchain is operating correctly here.  The
>>>> current version recognises a divide followed by a modulo and optimises
>>>> this into a call to the standard EABI function __aeabi__uldivmod().
>>>> Note the code:
>>>>
>>>>        do_div(Kpart, source);
>>>>
>>>>        K = Kpart & 0xFFFFFFFF;
>>>>
>>>>        /* Check if we need to round */
>>>>        if ((K % 10) >= 5)
>>>>                K += 5;
>>>>
>>>> This function is provided by libgcc for normal applications. The
>>>> kernel provides it's own versions in arch/arm/lib/lib1funcs.s but is
>>>> missing __aeabi_uldivmod (note the 'l' for 64 bit).
>>> In fact the problem happen ealier:
>>>
>>>  if (Ndiv < 6) {
>>>               source /= 2;
>>>                pll_div->pre_div = 1;
>>>                Ndiv = target / source;
>>>        } else
>>>                pll_div->pre_div = 0;
>>>
>>>        if ((Ndiv < 6) || (Ndiv > 12))
>>>                printk(KERN_WARNING
>>>                        "WM8974 N value %u outwith recommended range!\n",
>>>                        Ndiv);
>>>
>>>        pll_div->n = Ndiv;
>>>        Nmod = target % source;
>>>        Kpart = FIXED_PLL_SIZE * (long long)Nmod;
>>>
>>>        do_div(Kpart, source);
>>>
>>> If commenting "source /= 2", the problem disappear.
>>>
>>>
>> Or if adding one line before do_div, all will be ok.
>>        asm("" : "+r"(source));
>>        do_div(Kpart, source);
>
> Hi Barry.  I can reproduce the problem in Linaro GCC 4.5-2011.04 and
> GCC 4.5.2.  It does not exist in GCC 4.6.0.  wm8974_set_dai_pll()
> inlines the call to pll_factors() and leaves a .globl reference to
> __aeabi_uldivmod in the code.  This function is never called.
>
> Marking pll_factors() as __attribute__((noinline)) also works around
> the problem.
>
> I've logged http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48783 upstream
> and recorded this as LP: #771551.

Thanks. I am totally thinking it is a gcc bug not an optimization
feature. in fact, __aeabi_uldivmod is never called as seen by objdump.
It only exists in symbol reference list.

>
> -- Michael
>

_______________________________________________
linaro-toolchain mailing list
linaro-toolchain@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-toolchain

Reply via email to