On Sunday, 9 November 2014 at 11:50:24 UTC, Iain Buclaw via D.gnu
wrote:
On 9 November 2014 08:54, Iain Buclaw <ibuc...@gdcproject.org>
wrote:
On 9 Nov 2014 08:40, "Maor via D.gnu" <d.gnu@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