<div dir="ltr"><div dir="ltr">On Thu, Jun 13, 2019 at 12:54 AM JF Bastien <<a href="mailto:jfbastien@apple.com" target="_blank">jfbastien@apple.com</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto"><div dir="ltr"><br></div><div dir="ltr"><br><blockquote type="cite">On Jun 12, 2019, at 9:38 PM, James Y Knight <<a href="mailto:jyknight@google.com" target="_blank">jyknight@google.com</a>> wrote:<br><br></blockquote></div><blockquote type="cite"><div dir="ltr"><div dir="ltr"><div dir="ltr">On Tue, Jun 11, 2019 at 12:08 PM JF Bastien via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div><div>I think we want option 2.: keep volatile memcpy, and implement it as touching each byte exactly once. That’s unlikely to be particularly useful for every direct-to-hardware uses, but it behaves intuitively enough that I think it’s desirable.<br></div><div></div></div></div></blockquote><div><br></div><div>As Eli pointed out, that precludes lowering a volatile memcpy into a call the memcpy library function. The usual "memcpy" library function may well use the same overlapping-memory trick, and there is no "volatile_memcpy" libc function which would provide a guarantee of not touching bytes multiple times. Perhaps it's okay to just always emit an inline loop instead of falling back to a memcpy call.</div></div></div></div></blockquote><div><br></div><div>In which circumstances does this matter?</div></div></blockquote><div><br></div><div>If it's problematic to touch a byte multiple times when emitting inlined instructions for a "volatile memcpy", surely it's also problematic to emit a library function call which does the same thing?</div><div><br></div><div>But -- I don't know of any realistic circumstance where either one would be important to actual users. Someone would need to have a situation where doing 2 overlapping 4-byte writes to implement a 7-byte memcpy is problematic, but where it doesn't matter to them what permutation of non-overlapping memory read/write sizes is used -- and furthermore, where the order doesn't matter. That seems extremely unlikely to ever be the case.</div><div><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 dir="auto"><div>Paul McKenney has a follow on paper (linked from R2 of mine) which addresses some of your questions I think. LLVM can do what it wants for now since there’s no standard, but there’s likely to be one eventually and we probably should match what it’s likely to be. </div></div></blockquote><div><br></div><div>I agree, Paul's paper describes the actually-required (vs C-standard-required) semantics for volatile loads and stores today -- that they must use non-tearing operations for sizes/alignments where the hardware provides such. (IMO, any usage of volatile where that cannot be done is extremely questionable). Of course, that doesn't say anything about memcpy, since volatile memcpy isn't part of C, just part of LLVM.</div><div><br></div></div><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Always a byte-by-byte copy?</blockquote></div></blockquote><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> </blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">It can. </blockquote><div> </div><div>So, why does llvm even provide a volatile memcpy intrinsic? One possible answer is that it was needed in order to implement volatile aggregate copies generated by the C frontend. So, given the real world requirement to use single instructions where possible...what about this code:</div><div><br></div><div>struct X {int n;}; <br>void foo(volatile struct X *n) {<br>    n[0] = n[1];<br>}<br></div><div><br></div><div>Clang implements it by creating a volatile llvm.memcpy call. Which currently is generally lowered as a 32-bit read/write. Maybe it should be _required_ to always emit a 32-bit read/write instruction, just as if you were directly operating on a 'volatile int *n'? (Assuming a 32-bit platform which has such instructions, of course)?</div><div><br></div><div>Or -- maybe memcpy is actually not a reasonable thing to use for copying a volatile struct at all. Perhaps a volatile struct copy should do volatile element-wise copies of each fundamentally-typed field? That might make some sense. (But...unions?).<br></div><div><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 dir="auto"><blockquote type="cite"><div dir="ltr">
</div></blockquote></div></blockquote></div></div>