<div dir="ltr">IMO, it's quite fine to call this "volatile", and it's actually the desirable semantics -- even for talking to devices.<div><br></div><div>E.g. you may want to memcpy data out of a device's buffer, and then do a volatile write to tell the device you're done with the buffer. Here, you want the memcpy to be volatile so it cannot be reordered across the "done" write. But, other than ensuring the correct ordering w.r.t. the subsequent volatile write, it's quite irrelevant exactly how the data is read from the buffer -- doing it in the most efficient way is desirable.<div><br></div><div>All I want is that this specification of what exactly is (and perhaps more importantly) isn't guaranteed is actually be written down, both in Clang docs for the builtins, and LLVM langref for the IR intrinsics. Other than that, this seems like a fine and useful addition.</div></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, May 8, 2020 at 1:07 PM JF Bastien <<a href="mailto:jfbastien@apple.com">jfbastien@apple.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="overflow-wrap: break-word;">I indeed think that this is fine for the purpose I’ve stated.<div><br></div><div>Fundamentally, if you’re interacting with device memory you want to know that accesses are performed in a certain order, at a certain size granularity. Today’s C and C++ implementations volatile on scalars effectively provide this knowledge, even if the Standard doesn’t say so. Volatile on anything “large” (more than one or two registers) doesn’t, and ought not to be used for device memory with specific semantics.</div><div><br></div><div>However, the volatile usage for ToCToU doesn’t care if what you describe happens! An adversary can race all they want, as long as any validity check occurs after the copy has completed then we’re fine.</div><div><br></div><div>Maybe this argues for calling the builtin something else than volatile, but still mapping it to volatile memcpy IR for now?</div><div><br><div><br><blockquote type="cite"><div>On May 7, 2020, at 3:07 PM, James Y Knight via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>> wrote:</div><br><div><div dir="ltr"><div></div><div>Volatile memcpy/memset/etc are indeed rather underspecified. As LangRef states, "If the isvolatile parameter is true, the llvm.memcpy call is a volatile operation. The detailed access behavior is not very cleanly specified and it is unwise to depend on it."</div><div><div><br></div><div>I think the intent at the moment is that the mem-operation as a whole should be treated as volatile -- so the memory copy, as a whole, will happen only once -- but that there's no guarantee as to what loads/stores are used to implement that, including potentially reading/writing some bytes multiple times, with different access sizes. I think those semantics make sense, but really ought to be fully nailed down.</div></div><div><br></div><div><br></div><div><br></div><div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, May 7, 2020 at 5:13 PM Joerg Sonnenberger via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Wed, May 06, 2020 at 03:40:43PM -0700, JF Bastien via cfe-dev wrote:<br>
> I’d like to add volatile overloads to mem* builtins, and authored a patch: <a href="https://reviews.llvm.org/D79279" rel="noreferrer" target="_blank">https://reviews.llvm.org/D79279</a> <<a href="https://reviews.llvm.org/D79279" rel="noreferrer" target="_blank">https://reviews.llvm.org/D79279</a>><br>
<br>
The major issue I have here is that it seems to seriously underspecify<br>
what it is actually happening with the memory. Consider an<br>
implementation of memset for example. It is entirely legal and<br>
potentially even useful to check for length being >= two registers and<br>
in that case implement it as<br>
    write to [start, start+reglen)<br>
    write to [start+len-reglen,start+len)<br>
    write to (start+reglen)&(reglen-1) in reglen blocks until reaching<br>
    the end<br>
<br>
or variations to try to hide the unaligned head and tail case in the<br>
main loop. This would violate the normal assumptions around volatile,<br>
e.g. when using device memory.<br>
<br>
Joerg<br>
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
</blockquote></div>
_______________________________________________<br>cfe-dev mailing list<br><a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br><a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br></div></blockquote></div><br></div></div></blockquote></div>