[clang] [C] Disable use of NRVO (PR #101038)
John McCall via cfe-commits
cfe-commits at lists.llvm.org
Mon Jul 29 11:00:08 PDT 2024
rjmccall wrote:
I agree that the standard does not appear to permit this in C. There are three ways to fix this:
1. Disable NRVO in the callee just in case the address being initialized is aliased.
2. Disable RVO in the caller when aliasing is possible.
3. Convince the committee that they should change the standard to permit these simple optimizations.
(1) also requires disabling copy elision in some cases. It is not possible to directly observe the address of the compound literal in `return (struct S) { E1, E2 };`, as the other example does, but E1 or E2 might assign to a field of the alias, and such modifications must be overwritten when the return occurs.
It is tractable to implement (2) with a simple local escape analysis of the variable's initializer. This would *not* be tractable if the initialized variable were a global variable, but, fortunately, C does not permit global variables to be initialized with non-constant expressions.
(3) would presumably take the form of either permitting objects to overlap in certain situations, the same way that C++ permits copy elision, or just generally weakening object overlap rules during initialization.
Richard, I'm sorry to contradict you, but Aaron is correct to guess that this is ABI-affecting: ABIs should and sometimes do specify whether an indirect return address is allowed to be aliased. For example, the x86_64 psABI is quite clear:
> If the type has class MEMORY, then the caller provides space for the return value and passes the address of this storage in %rdi as if it were the first argument to the function. In effect, this address becomes a “hidden” first argument. This storage must not overlap any data visible to the callee through other names than this argument.
So on x86_64, we are clearly required to at least do (2). I don't think we want different rules on different targets unless we're forced to.
If (2) is implemented correctly, I believe there's no way to observe NRVO, so we don't also need to implement (1).
https://github.com/llvm/llvm-project/pull/101038
More information about the cfe-commits
mailing list