Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 19 Oct 2014 14:47:16 +0200
From:      Adam Nowacki <nowakpl@platinum.linux.pl>
To:        freebsd-hackers@freebsd.org
Subject:   Re: panic in ivy_rng_store() when compiled with -O0
Message-ID:  <5443B2D4.3020407@platinum.linux.pl>
In-Reply-To: <7A5C3D84-1B1F-4BA3-818D-37231BF424FE@FreeBSD.org>
References:  <54384ABD.5080806@FreeBSD.org> <2533199.DHZybpy49d@ralph.baldwin.cx> <54415E13.4000203@delphij.net> <7A5C3D84-1B1F-4BA3-818D-37231BF424FE@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On 2014-10-17 20:33, Dimitry Andric wrote:
> On 17 Oct 2014, at 20:21, Xin Li <delphij@delphij.net> wrote:
>> On 10/17/14 08:53, John Baldwin wrote:
>>> On Friday, October 10, 2014 02:08:13 PM Navdeep Parhar wrote:
> ...
>> movq %rdi,(%rdi) is obviously wrong (%rdi holds the result from
>> rdrand), which I believed to be a compiler bug in register allocation.
>>
>> Navdeep have committed a change to mark 'tmp' input+output, which does
>> fix the output but I'm not 100% sure if that's right, as 'tmp' is not
>> considered an input of the inline assembler block, and this may break
>> compile on other compilers, but for now it's better than previous
>> situation.
>>
>> Speaking for the compiler issue, Dimitry have reported this upstream at:
>>
>> 	http://llvm.org/bugs/show_bug.cgi?id=21273
>>
>> There is a suggestion in the reply, that change 'tmp' to early clobber
>> would workaround the issue, like:
>>
>> Index: ivy.c
>> ===================================================================
>> - --- ivy.c	(revision 273195)
>> +++ ivy.c	(working copy)
>> @@ -79,7 +79,7 @@
>> 	    "2:\n\t"
>> 	    "mov	%2,%1\n\t" /* *buf = tmp */
>> 	    "3:"
>> - -	    : "+q" (retry), "=m" (*buf), "+q" (tmp) : : "cc");
>> +	    : "+q" (retry), "=m" (*buf), "=&q" (tmp) : : "cc");
> 
> Yes, this generates the correct code for all cases I tried, e.g. with
> gcc 4.2 from base, gcc 4.7 through 5.0 from ports, clang 3.4, clang 3.5
> and clang trunk, all at -O0 through -O3, and -Os.
> 
> So at the moment this fix is the best option, I think.

GCC documentation explains what happens:
"The same problem can occur if one output parameter (a) allows a
register constraint and another output parameter (b) allows a memory
constraint. The code generated by GCC to access the memory address in b
can contain registers which might be shared by a, and GCC considers
those registers to be inputs to the asm. As above, GCC assumes that such
input registers are consumed before any outputs are written. This
assumption may result in incorrect behavior if the asm writes to a
before using b. Combining the `&' constraint with the register
constraint ensures that modifying a will not affect what address is
referenced by b. Omitting the `&' constraint means that the location of
b will be undefined if a is modified before using b. "

Both tmp and retry need the '&' constraint.

    : "+&q" (retry), "=m" (*buf), "=&q" (tmp) : : "cc");




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?5443B2D4.3020407>