<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Jan 13, 2016 at 10:32 AM, John Brawn <span dir="ltr"><<a href="mailto:John.Brawn@arm.com" target="_blank">John.Brawn@arm.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">





<div lang="EN-GB" link="blue" vlink="purple">
<div><span class="">
<p class="MsoNormal" style="margin-left:36pt"><b>What about non-x86 architectures?</b><u></u><u></u></p>
<p class="MsoNormal" style="margin-left:36pt"><u></u> <u></u></p>
<p class="MsoNormal" style="margin-left:36pt">Architectures such as ARMv8 support non-temporal instructions and require barriers such as <span style="font-family:'Courier New'">DMB nshld</span> to order loads and
<span style="font-family:'Courier New'">DMB nshst</span> to order stores.<u></u><u></u></p>
<p class="MsoNormal" style="margin-left:36pt"><u></u> <u></u></p>
<p class="MsoNormal" style="margin-left:36pt">Even ARM's address-dependency rule (a.k.a. the ill-fated <span style="font-family:'Courier New'">std::memory_order_consume</span>) fails to hold with non-temporals:<u></u><u></u></p>
<p class="MsoNormal" style="margin-left:36pt"><span style="font-family:'Courier New'">LDR X0, [X3]</span><u></u><u></u></p>
<p class="MsoNormal" style="margin-left:36pt"><span style="font-family:'Courier New'">LDNP X2, X1, [X0] // X0 may not be loaded when the instruction executes!</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"><u></u> <u></u></span></p>
</span><p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">What exactly do you mean by ‘X0 may not be loaded’ in your example here? If you mean that the LDNP<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">could start executing with the value of X0 from before the LDR,  e.g. initially X0=0x100, the LDR loads<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">X0=0x200 but the LDNP uses the old value of X0=0x100, then I don’t think that’s true. According to<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">section C3.2.4 of the ARMv8 ARMARM
<i>other</i> observers may observe the LDR and the LDNP in the wrong<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">order, but the CPU executing the instructions will observe them in program order.</span></p></div></div></blockquote><div><br></div><div>I haven't touched ARMv8 in a few years so I'm rusty on the non-temporal details for that ISA. I lifted this example from here:</div></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div class="gmail_extra"><div class="gmail_quote"><div><a href="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0024a/CJACGJJF.html">http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0024a/CJACGJJF.html</a></div></div></div></blockquote><div class="gmail_extra"><div class="gmail_quote"><div><br></div><div>Which is correct?</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div lang="EN-GB" link="blue" vlink="purple"><div><p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"><u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"><u></u> </span><span style="color:rgb(31,73,125);font-family:Calibri,sans-serif;font-size:11pt">I have no idea if that affects anything in this RFC though.</span></p></div></div></blockquote><div><br></div><div>Agreed, but I don't want to be misleading! The current example serves as a good justification for non-temporal read barriers, it would be a shame to justify myself on incorrect data :-)</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div lang="EN-GB" link="blue" vlink="purple"><div>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"><u></u> </span><span style="color:rgb(31,73,125);font-family:Calibri,sans-serif;font-size:11pt">John</span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"><u></u> <u></u></span></p>
<p class="MsoNormal"><b><span lang="EN-US" style="font-size:10pt;font-family:Tahoma,sans-serif">From:</span></b><span lang="EN-US" style="font-size:10pt;font-family:Tahoma,sans-serif"> llvm-dev [mailto:<a href="mailto:llvm-dev-bounces@lists.llvm.org" target="_blank">llvm-dev-bounces@lists.llvm.org</a>]
<b>On Behalf Of </b>JF Bastien via llvm-dev<br>
<b>Sent:</b> 13 January 2016 07:16<br>
<b>To:</b> llvm-dev<br>
<b>Cc:</b> Hans Boehm<br>
<b>Subject:</b> [llvm-dev] RFC: non-temporal fencing in LLVM IR<u></u><u></u></span></p><div><div class="h5">
<p class="MsoNormal"><u></u> <u></u></p>
<div>
<div>
<p class="MsoNormal">Hello, fencing enthusiasts!<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<p class="MsoNormal"><b>TL;DR:</b> We'd like to propose an addition to the LLVM memory model requiring non-temporal accesses be surrounded by non-temporal load barriers and non-temporal store barriers, and we'd like to add such orderings to the
<span style="font-family:'Courier New'">fence</span> IR opcode.<u></u><u></u></p>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">We are open to different approaches, hence this email instead of a patch.<u></u><u></u></p>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal"><b>Who's "we"?</b><u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Philip Reames brought this to my attention, and we've had numerous discussions with Hans Boehm on the topic. Any mistakes below are my own, all the clever bits are theirs.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal"><b>Why?</b><u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Ignore non-temporals for a moment, on most x86 targets LLVM generates an
<span style="font-family:'Courier New'">mfence</span> for <span style="font-family:'Courier New'">
seq_cst</span> atomic fencing. One could instead use a locked idempotent atomic accesses to top-of-stack such as <span style="font-family:'Courier New'">lock or4i [RSP-8] 0</span>. Philip has measured this as equivalent on micro-benchmarks, but as ~25% faster
 in macro-benchmarks (other codebases confirm this). There's one problem with this approach: non-temporal accesses on x86 are only ordered by fence instructions! This means that code using non-temporal accesses can't rely on LLVM's
<span style="font-family:'Courier New'">fence</span> opcode to do the right thing, they instead have to rely on architecture-specific <span style="font-family:'Courier New'">_mm*fence</span> intrinsics.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal"><b>But wait! Who said developers need to issue any type of fence when using non-temporals?</b><u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Well, the LLVM memory model sure didn't. The x86 memory model does (volume 3 section 8.2.2 Memory Ordering) but LLVM targets more than x86 and the backends are free to ignore the
<span style="font-family:'Courier New'">!nontemporal</span> metadata, and AFAICT the x86 backend doesn't add those fences.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Therefore even without the above optimization the LLVM language reference is incorrect: non-temporals should be bracketed by barriers. This applies even without threading! Non-temporal accesses aren't guaranteed to interact well with regular
 accesses, which means that regular loads cannot move "down" a non-temporal barrier, and regular stores cannot move "up" a non-temporal barrier.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal"><b>Why not just have the compiler add the fences?</b><u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">LLVM could do this, either as a per-backend thing or a hookable pass such as
<span style="font-family:'Courier New'">AtomicExpandPass</span>. It seems more natural to ask the programmer to express intent, just as is done with atomics. In fact, a backend is current free to ignore <span style="font-family:'Courier New'">!nontemporal</span> on
 load and store and could therefore generate only half of what's requested, leading to incorrect code. That would of course be silly, backends should either honor all <span style="font-family:'Courier New'">!nontemporal</span> or none of them but who knows
 what the middle-end does.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Put another way: some optimized C library use non-temporal accesses (when string instructions aren't du jour) and they terminate their copying with an
<span style="font-family:'Courier New'">sfence</span>. It's a de-facto convention, the ABI doesn't say anything, but let's avoid divergence.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Aside: one day we may live in <a href="http://lists.llvm.org/pipermail/llvm-dev/2014-September/076701.html" target="_blank">the fence elimination promised land</a> where fences are exactly where they need to be, no more, no less.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal"><b>Isn't x86's </b><b><span style="font-family:'Courier New'">lfence</span> just a no-op?</b><u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Yes, but we're proposing the addition of a target-independent non-temporal load barrier. It'll be up to the x86 backend to make it an
<span style="font-family:'Courier New'">X86ISD::MEMBARRIER</span> and other backends to get it right (hint: it's not always a no-op).<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal"><b>Won't this optimization cause coherency misses? C++ access the thread stack concurrently all the time!</b><u></u><u></u></p>
</div>
<div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Maybe, but then it isn't much of an optimization if it's slowing code down. LLVM doesn't just target C++, and it's really up to the backend to decide whether one fence type is better than another (on x86, whether a locked top-of-stack idempotent
 operation is better than <span style="font-family:'Courier New'">mfence</span>). Other languages have private stacks where this isn't an issue, and where the stack top can reasonably be assumed to be in cache.<u></u><u></u></p>
</div>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal"><b>How will this affect non-user-mode code (i.e. kernel code)?</b><u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Kernel code still has to ask for _mm_<span style="font-family:'Courier New'">mfence</span> if it wants
<span style="font-family:'Courier New'">mfence</span>: C11 and C++11 barriers aren't specified as a specific instruction.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal"><b>Is it safe to access top-of-stack?</b><u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">AFAIK yes, and the ABI-specified red zone has our back (or front if the stack grows up ☻).<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal"><b>What about non-x86 architectures?</b><u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Architectures such as ARMv8 support non-temporal instructions and require barriers such as <span style="font-family:'Courier New'">DMB nshld</span> to order loads and
<span style="font-family:'Courier New'">DMB nshst</span> to order stores.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
</div>
<p class="MsoNormal">Even ARM's address-dependency rule (a.k.a. the ill-fated <span style="font-family:'Courier New'">std::memory_order_consume</span>) fails to hold with non-temporals:<u></u><u></u></p>
<div>
<div>
<div>
<p class="MsoNormal"><span style="font-family:'Courier New'">LDR X0, [X3]</span><u></u><u></u></p>
</div>
</div>
</div>
<div>
<div>
<div>
<p class="MsoNormal"><span style="font-family:'Courier New'">LDNP X2, X1, [X0] // X0 may not be loaded when the instruction executes!</span><u></u><u></u></p>
</div>
</div>
</div>
<div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal"><b>Who uses non-temporals anyways?</b><u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">That's an awfully personal question!<u></u><u></u></p>
</div>
</div>
</div>
</div></div></div>
</div>

</blockquote></div><br></div></div>