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>