Eli Friedman via llvm-dev
2019-Jun-06 18:24 UTC
[llvm-dev] @llvm.memcpy not honoring volatile?
The primary reason I don’t want to provide any guarantees for what instructions are used to implement volatile memcpy is that it would forbid lowering a volatile memcpy to a library call. clang uses a volatile memcpy for struct assignment in C. For example, “void f(volatile struct S*p) { p[0] = p[1]; }”. It’s not really that useful, but it’s been done that way since before clang was written. -Eli From: Guillaume Chatelet <gchatelet at google.com> Sent: Thursday, June 6, 2019 2:40 AM To: Tim Northover <t.p.northover at gmail.com> Cc: Eli Friedman <efriedma at quicinc.com>; llvm-dev <llvm-dev at lists.llvm.org> Subject: [EXT] Re: [llvm-dev] @llvm.memcpy not honoring volatile? Thx for the explanation Eli and Tim. My understanding of volatile was that you may have a different value every time you read and as such overlapping reads may be a bug. Now, since the behaviour of volatile memcpy is not guaranteed and since clang does not allow to use it anyways<https://godbolt.org/z/CnCOLc> I would like to challenge its existence. Is there a know reason for keeping the volatile argument in @llvm.memcpy? On Wed, Jun 5, 2019 at 11:28 PM Tim Northover <t.p.northover at gmail.com<mailto:t.p.northover at gmail.com>> wrote: On Wed, 5 Jun 2019 at 13:49, Eli Friedman via llvm-dev <llvm-dev at lists.llvm.org<mailto:llvm-dev at lists.llvm.org>> wrote:> I don’t see any particular reason to guarantee that a volatile memcpy will access each byte exactly once. How is that useful?I agree it's probably not that useful, but I think the non-duplicating property of volatile is ingrained strongly enough that viewing a memcpy as a single load and store to each unit (in an unspecified order) should be legitimate; so I think this actually is a bug. As the documentation says though, it's unwise to depend on the behaviour of a volatile memcpy. Cheers. Tim. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190606/c9a4fba4/attachment.html>
Guillaume Chatelet via llvm-dev
2019-Jun-07 08:38 UTC
[llvm-dev] @llvm.memcpy not honoring volatile?
On Thu, Jun 6, 2019 at 8:24 PM Eli Friedman <efriedma at quicinc.com> wrote:> clang uses a volatile memcpy for struct assignment in C. For example, > “void f(volatile struct S*p) { p[0] = p[1]; }”. It’s not really that > useful, but it’s been done that way since before clang was written. >Thx. I guess my next question is, from the code gen perspective is there a difference between the volatile and non volatile versions> void f(volatile struct S*p) { p[0] = p[1]; }and> void f(struct S*p) { p[0] = p[1]; }Clang could lower the volatile copy to a regular copy. And since memcpy has side effects it would still maintain "that volatile operations are emitted in source order relative to other volatile operations." I tried x86_64 gcc, x86_64 clang, ARM gcc, they all generate the exact same code.>-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190607/8e54f2d0/attachment.html>
Guillaume Chatelet via llvm-dev
2019-Jun-07 09:27 UTC
[llvm-dev] @llvm.memcpy not honoring volatile?
One data point. I ran check-llvm with a tweaked *SelectionDAG::getMemcpy* that always sets *isVol* to false. Only one test fails llvm/test/CodeGen/X86/stack-align.ll <https://github.com/llvm-project/llvm-project/blob/ea0411ed880b5b5ae9eea03d64dc0ddb4440259b/llvm/test/CodeGen/X86/stack-align.ll#L69> and I think it's a false positive. ---- Before _test5: ## @test5 ## %bb.0: pushl %ebp movl %esp, %ebp andl $-16, %esp * subl $32, %esp* * movsd 8(%ebp), %xmm0 ## xmm0 = mem[0],zero* * movsd 16(%ebp), %xmm1 ## xmm1 = mem[0],zero* * movsd %xmm1, 16(%esp)* * movsd %xmm0, 8(%esp)* movl %ebp, %esp popl %ebp retl $16 ## -- End function After _test5: ## @test5 ## %bb.0: pushl %ebp movl %esp, %ebp andl $-16, %esp movl %ebp, %esp popl %ebp retl $16 ## -- End function To me the copy should occur regardless of the volatile value, it's linked to the change of calling convention that breaks the stack alignment assumptions. On Fri, Jun 7, 2019 at 10:38 AM Guillaume Chatelet <gchatelet at google.com> wrote:> On Thu, Jun 6, 2019 at 8:24 PM Eli Friedman <efriedma at quicinc.com> wrote: > >> clang uses a volatile memcpy for struct assignment in C. For example, >> “void f(volatile struct S*p) { p[0] = p[1]; }”. It’s not really that >> useful, but it’s been done that way since before clang was written. >> > > Thx. I guess my next question is, from the code gen perspective is there a > difference between the volatile and non volatile versions > > void f(volatile struct S*p) { p[0] = p[1]; } > and > > void f(struct S*p) { p[0] = p[1]; } > > Clang could lower the volatile copy to a regular copy. And since memcpy > has side effects it would still maintain "that volatile operations are > emitted in source order relative to other volatile operations." > I tried x86_64 gcc, x86_64 clang, ARM gcc, they all generate the exact > same code. > >>-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190607/0029351c/attachment.html>