Added atomicExchange to core.atomic#2729
Conversation
|
Thanks for your pull request and interest in making D better, @TurkeyMan! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please see CONTRIBUTING.md for more information. If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment. Bugzilla references
Testing this PR locallyIf you don't have a local development environment setup, you can use Digger to test this PR: dub fetch digger
dub run digger -- build "master + druntime#2729" |
|
What is that CI error? |
|
Please add "Fix Issue 20104" to the commit title so that it gets picked up by the bot. Also pure inline asm is likely do cause problems for LDC/GDC optimisers. |
51c5b46 to
31d729f
Compare
|
I'm just following the rest of the code in core.atomic. |
|
OK. We should probably fix that at some point though. |
|
Assuming that LDC/GDC have their own druntime forks, they'll need to implement this function such that it pipes through to those compilers intrinsics properly. |
ed3ac46 to
757b671
Compare
|
There's #2596, not merged because people are unsure what to do when atomics aren't supported (currently, fake pure mutex). |
| } | ||
|
|
||
| shared(T) atomicExchange(MemoryOrder ms = MemoryOrder.seq,T,V)( shared(T)* here, V exchangeWith ) pure nothrow @nogc @safe | ||
| if ( !is(T == class) && !is(T U : U*) && __traits( compiles, { *here = exchangeWith; } ) ) |
There was a problem hiding this comment.
Just to make sure you've done your homework, are there any invalid memory orders for this operation? (I think I know the answer without checking anyway).
There was a problem hiding this comment.
There are no invalid orders.
Infact, the order does not affect codegen in any way; it should be routed through to the backend to inform code mobility.
757b671 to
b65bf53
Compare
Personally, I'd rather an error in a library called 'druntime'. |
|
wtf is an atomic float?! that's not a thing! |
That would be fine if the atomic module wasn't used by druntime in critical places. But this line of discussion is best to be done in the other pr. ... Atomic exchange SGTM. |
|
Of course it is, how else are you supposed to do race free parallel reductions? |
11e6b05 to
da02edf
Compare
|
This is grueling... how many hours have I been trying to pacify the CI now? >_< |
|
I don't understand what's wrong with the float test... it works for me locally :/ |
|
Different calling conv? |
da02edf to
d537b0a
Compare
Fix Issue 20104 - core.atomic has no exchange function
d537b0a to
16048f1
Compare
|
Doesn't explain why the apveyor test fails, since that's specifically what I'm testing... |
|
Also, this code shouldn't interact with the calling convention; that's handled outside the asm block. |
| assert( base !is val, T.stringof ); | ||
| assert( atom is base, T.stringof ); | ||
|
|
||
| assert( atomicExchange( &atom, val ) is base, T.stringof ); |
There was a problem hiding this comment.
maybe do
auto x = atomicExchange( &atom, val );
static if (is(T == float))
printf("%a, %a\n",x, base);
assert(x is base, T.stringof);
and see what it thinks?
83d2083 to
00ec4a1
Compare
src/core/atomic.d
Outdated
| { | ||
| mov exchangeWith, RAX; | ||
| } | ||
| return exchangeWith; |
There was a problem hiding this comment.
@WalterBright I think there might be a codegen issue with asm in functions... this here assigns RAX to a local, which emits correct code, but then the return doesn't actually return the argument correctly.
I reduced the snippet:
extern(C) float floop(float* r, float x)
{
asm
{
mov EAX, x;
mov RCX, r;
xchg [RCX], EAX;
mov x, EAX;
}
return x;
}And compile with DMD: dmd asmtest.d -c -m64 and emit's this:
0000000000000000 <floop>:
0: 55 push %rbp
1: 48 8b ec mov %rsp,%rbp
4: 48 83 ec 10 sub $0x10,%rsp
8: 48 89 7d f0 mov %rdi,-0x10(%rbp)
c: f3 0f 11 45 f8 movss %xmm0,-0x8(%rbp)
; the asm block
11: 8b 45 f8 mov -0x8(%rbp),%eax
14: 48 8b 4d f0 mov -0x10(%rbp),%rcx
18: 87 01 xchg %eax,(%rcx)
1a: 89 45 f8 mov %eax,-0x8(%rbp)
; return statement doesn't repopulate xmm0
; movss 0x8(%rbp),%xmm0 ; <- this is missing!
1d: c9 leaveq
1e: c3 retqThere's a line missing that should load the float back into xmm0 before returning... I suspect DMD is assuming that the asm block did not clobber x.
This is on linux... but when I build for windows, I don't see this issue.
There was a problem hiding this comment.
Well, the CI here suggests it fails on windows too; perhaps it's just that I can't repro this issue on my local machine...?
Is it possible there's a regression in a DMD more recent than the version I'm running locally? (2.087.0 Windows)
Has anything changed recently that might affect this?
There was a problem hiding this comment.
-m32 does work properly:
00000000 <floop>:
0: 55 push %ebp
1: 8b ec mov %esp,%ebp
3: 8b 45 0c mov 0xc(%ebp),%eax
6: 8b 4d 08 mov 0x8(%ebp),%ecx
9: 87 01 xchg %eax,(%ecx)
b: 89 45 0c mov %eax,0xc(%ebp)
e: d9 45 0c flds 0xc(%ebp) ; <- here it is
11: 5d pop %ebp
12: c3 retSo, it's just x64... and only on master DMD, my local compiler works correctly. (2.087.0 Windows)
00ec4a1 to
9032ee2
Compare
9032ee2 to
7e9c9db
Compare
|
Mmm, I think is codegen bug. |
No description provided.