GDC optimizations bug ?

Maor via D.gnu d.gnu at puremagic.com
Sun Nov 9 06:20:56 PST 2014


On Sunday, 9 November 2014 at 11:50:24 UTC, Iain Buclaw via D.gnu 
wrote:
> On 9 November 2014 08:54, Iain Buclaw <ibuclaw at gdcproject.org> 
> wrote:
>>
>> On 9 Nov 2014 08:40, "Maor via D.gnu" <d.gnu at puremagic.com> 
>> wrote:
>>>
>>> Hi,
>>>
>>> I'm trying to compile a program using inline asm with 
>>> optimizations and I
>>> got my inline asm functions thrown out by the optimizer 
>>> although I declared
>>> them as having side effects (by stating a memory clobber).
>>> I wrote the following toy program to demonstrate the problem:
>>>
>>> ----------------------------------------------
>>>
>>> import std.stdio;
>>> import gcc.attribute;
>>>
>>> @attribute("forceinline") ulong exchangeAndAdd(shared ulong 
>>> *counter,
>>> ulong addition) {
>>>       ulong retVal = void; // we don't want it initialized 
>>> when dmd is
>>> used
>>>       asm {
>>>         "
>>>           mov  %2, %0             ;
>>>           lock                    ;
>>>           xadd %0, (%1)           ;
>>>         ":
>>>         "=&r"(retVal) :
>>>         "r"(counter), "r"(addition) :
>>
>> Maybe try:  "=m"(*counter)
>>
>> The bug is likely in your input/output clobbers, gcc will 
>> always optimise
>> against you unless you get the input/output/clobbers precisely 
>> correct.
>
> Yep, it looks like using (%1) -> "r"(counter) creates a 
> temporary in
> the register but never binds back.  The optimiser sees that 
> memory is
> clobbered, but non of the operands have memory side effects.
>
> Telling gcc that this is a memory operand fixes it - %1 ->
> "m"(counter).  But I think that having counter as an input 
> operand is
> wrong, as it *has* infact a new value written to it.  You can 
> also
> omit the 'mov' instruction by telling gcc the "0" register 
> should be
> loaded with the input "addition"
>
> Your fixed (and simplified) assembler statement now becomes:
>
>
> @attribute("forceinline") ulong exchangeAndAdd(shared ulong 
> *counter,
> ulong addition) {
>       ulong retVal = void; // we don't want it initialized when 
> dmd is used
>       asm {
>           "
>           lock                    ;
>           xadd %0, %1             ;
>           " :
>           "=r"(retVal), "=m"(*counter) :
>           "0"(addition) :
>           "memory";
>       }
>       return retVal;
> }

Hi,

Thanks for the tip!
Indeed, it solves the problem (which uncovered another one, but 
one which deserves a different subject :)

Cheers,
Maor


More information about the D.gnu mailing list