<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Thanks for kicking off this discussion and for all the interesting responses.<div class=""><br class=""></div><div class="">Marking indirect parameters as noalias enables more aggressive memory optimization with respect to the indirect arguments on certain targets. On ARM64 this leads to 1%-2% in code size reductions in some cases.</div><div class=""><br class=""></div><div class="">While we work towards adjusting the C++ standard, I would like to provide a way for users to opt-in to the new behavior (e.g. for code-bases that exclusively use C or guarantee that no addresses can escape before the argument is passed): <a href="https://reviews.llvm.org/D85473" class="">https://reviews.llvm.org/D85473</a></div><div class=""><br class=""></div><div class="">What do you think?</div><div class=""><br class=""></div><div class="">Cheers,</div><div class="">Florian<br class=""><div class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Aug 4, 2020, at 04:28, Hal Finkel via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" class="">cfe-dev@lists.llvm.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class="">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" class="">
<div class=""><p class=""><br class="">
</p>
<div class="moz-cite-prefix">On 8/3/20 8:45 PM, John McCall wrote:<br class="">
</div>
<blockquote type="cite" cite="mid:833CCC19-6042-4889-B081-28EBD258FBB2@apple.com" class="">
<div style="font-family:sans-serif" class="">
<div style="white-space:normal" class=""><p dir="auto" class="">On 31 Jul 2020, at 19:50, Hal Finkel wrote:</p>
</div>
<div style="white-space:normal" class="">
<blockquote style="border-left:2px solid #777; color:#777;
margin:0 0 5px; padding-left:5px" class=""><p dir="auto" class="">On 7/31/20 5:59 PM, James Y Knight wrote:</p>
<blockquote style="border-left:2px solid #777; color:#999;
margin:0 0 5px; padding-left:5px; border-left-color:#999" class=""><p dir="auto" class="">This discussion reminds me of an example I
ran into a couple weeks ago, where the execution of the
program is dependent precisely upon whether the ABI
calls for the object to be passed indirectly, or in a
register<br class="">
<br class="">
In the case where NVRO is triggered, the class member
foo_ is fully-constructed on the first line of CreateFoo
(despite appearing as if that's only constructing a
local variable). In the case where the struct is small
enough to fit in a register, NVRO does not apply, and in
that case, foo_ isn't constructed until after CreateFoo
returns.<br class="">
<br class="">
Therefore, I believe it's implementation-defined whether
the following program has undefined behavior.<br class="">
<br class="">
<a href="https://godbolt.org/z/YT9zsz" style="color:#999" moz-do-not-send="true" class="">https://godbolt.org/z/YT9zsz</a>
<<a href="https://godbolt.org/z/YT9zsz" style="color:#999" moz-do-not-send="true" class="">https://godbolt.org/z/YT9zsz</a>><br class="">
<br class="">
#include <assert.h><br class="">
<br class="">
struct Foo {<br class="">
int x;<br class="">
* // assert fails if you comment out these unused
fields!<br class="">
* int dummy[4];<br class="">
};<br class="">
<br class="">
struct Bar {<br class="">
Bar() : foo_(CreateFoo()) {}<br class="">
<br class="">
Foo CreateFoo() {<br class="">
Foo f;<br class="">
f.x = 55;<br class="">
assert(foo_.x == 55);<br class="">
return f;<br class="">
}<br class="">
Foo foo_;<br class="">
};<br class="">
<br class="">
int main() {<br class="">
Bar b;<br class="">
}</p>
</blockquote><p dir="auto" class="">Looks that way to me too. The example in
11.10.5p2 sort of makes this point as well (by pointing
out that you can directly initialize a global this way).</p>
</blockquote>
</div>
<div style="white-space:normal" class=""><p dir="auto" class="">It does seem hard to argue that this is invalid
under the specification. To me it seems like it clearly <em class="">ought</em>
to be invalid, though. Note that Clang has always emitted
return address arguments as <code style="background-color:#F7F7F7; border-radius:3px;
margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">noalias</code>,
so this has immediate significance.</p><p dir="auto" class="">If I were writing the specification, I would
rewrite the restriction in <code style="background-color:#F7F7F7; border-radius:3px;
margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">[class.cdtor]p2</code>
to say that pointers derived by naming a
returned/constructed object do not formally point to the
object until the function actually returns, even if the copy
is elided. That would make James’s example undefined
behavior.</p><p dir="auto" class="">John.</p>
</div>
</div>
</blockquote><p class=""><br class="">
</p><p class="">I agree. It seems like we should be able to make a sanitizer
detect this kind of mistake as well (although the general case
will require some msan-like propagation scheme).<br class="">
</p><p class=""> -Hal<br class="">
</p><p class=""><br class="">
</p>
<blockquote type="cite" cite="mid:833CCC19-6042-4889-B081-28EBD258FBB2@apple.com" class="">
<div style="font-family:sans-serif" class="">
<div style="white-space:normal" class="">
</div>
<div style="white-space:normal" class="">
<blockquote style="border-left:2px solid #777; color:#777;
margin:0 0 5px; padding-left:5px" class=""><p dir="auto" class=""> -Hal<br class="">
<br class="">
</p>
<blockquote style="border-left:2px solid #777; color:#999;
margin:0 0 5px; padding-left:5px; border-left-color:#999" class=""><p dir="auto" class="">On Fri, Jul 31, 2020 at 2:27 PM Hal Finkel
via cfe-dev <<a class="moz-txt-link-abbreviated" href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a> <<a href="mailto:cfe-dev@lists.llvm.org" style="color:#999" moz-do-not-send="true" class="">mailto:cfe-dev@lists.llvm.org</a>>>
wrote:<br class="">
<br class="">
<br class="">
On 7/31/20 1:24 PM, Hal Finkel wrote:</p>
<blockquote style="border-left:2px solid #777; color:#BBB;
margin:0 0 5px; padding-left:5px;
border-left-color:#BBB" class=""><p dir="auto" class=""> On 7/31/20 12:43 PM, John McCall wrote:</p>
<blockquote style="border-left:2px solid #777;
color:#BBB; margin:0 0 5px; padding-left:5px;
border-left-color:#BBB" class=""><p dir="auto" class=""> n 31 Jul 2020, at 7:35, Hal Finkel
wrote:<br class="">
<br class="">
On 7/29/20 9:00 PM, John McCall via cfe-dev wrote:<br class="">
<br class="">
On 29 Jul 2020, at 17:42, Richard Smith wrote:<br class="">
<br class="">
On Wed, 29 Jul 2020 at 12:52, John McCall<br class="">
<a class="moz-txt-link-rfc2396E" href="mailto:rjmccall@apple.com"><rjmccall@apple.com></a> <<a href="mailto:rjmccall@apple.com" style="color:#BBB" moz-do-not-send="true" class="">mailto:rjmccall@apple.com</a>>
wrote:<br class="">
<br class="">
...<br class="">
<br class="">
I think concretely, the escape hatch doesn't stop
things<br class="">
from<br class="">
going wrong,<br class="">
because -- as you note -- even though we *could*
have<br class="">
made a copy,<br class="">
it's<br class="">
observable whether or not we *did* make a copy. For
example:<br class="">
<br class="">
I would say that it’s observable whether the
parameter<br class="">
variable has<br class="">
the same address as the argument. That doesn’t
/have/ to<br class="">
be the same<br class="">
question as whether a copy was performed: we could<br class="">
consider there to be<br class="">
a formal copy (or series of copies) that ultimately<br class="">
creates /an/ object<br class="">
at the same address, but it’s not the /same/ object
and<br class="">
so pointers<br class="">
to the old object no longer validly pointer to it.
But I<br class="">
guess that<br class="">
would probably violate the lifetime rules, because
it<br class="">
would make accesses<br class="">
through old pointers UB when in fact they should at<br class="">
worst access a valid<br class="">
object that’s just unrelated to the parameter
object.<br class="">
<br class="">
I think that it would be great to be able to do
this, but<br class="">
unfortunately, I think that the point that you raise
here is<br class="">
a key issue. Whether or not the copy is performed is
visible<br class="">
in the model, and so we can't simply act as though
there was<br class="">
a copy when optimizing. Someone could easily have
code that<br class="">
looks like:<br class="">
<br class="">
Foo DefaultX;<br class="">
<br class="">
...<br class="">
<br class="">
void something(Foo &A, Foo &B) {<br class="">
<br class="">
if (&A == &B) { ... }<br class="">
<br class="">
}<br class="">
<br class="">
void bar(Foo X) { something(X, DefaultX); }<br class="">
<br class="">
This example isn’t really on point; a call like
|bar(DefaultX)|<br class="">
obviously cannot just pass the address of |DefaultX|
as a<br class="">
by-value argument without first proving a lot of
stuff about how<br class="">
|foo| uses both its parameter and |DefaultX|. I
think |noalias|<br class="">
is actually a subset of what would have to be proven
there.<br class="">
</p>
</blockquote><p dir="auto" class=""> Yes, I apologize. You're right: my
pseudo-code missed the point.<br class="">
So the record is clear, let me rephrase:<br class="">
<br class="">
Foo *DefaultX = nullptr;<br class="">
...<br class="">
Foo::Foo() { if (!DefaultX) DefaultX = this; }<br class="">
...<br class="">
void bar(Foo X) { something(X, *DefaultX); }<br class="">
...<br class="">
bar(Foo{});<br class="">
<br class="">
I think that's closer to what we're talking about.<br class="">
<br class="">
</p>
<blockquote style="border-left:2px solid #777;
color:#BBB; margin:0 0 5px; padding-left:5px;
border-left-color:#BBB" class=""><p dir="auto" class=""> In general, the standard is clear that
you cannot rely on<br class="">
escaping a pointer to/into a trivially-copyable
pr-value<br class="">
argument prior to the call and then rely on that
pointer<br class="">
pointing into the corresponding parameter object.<br class="">
Implementations are /allowed/ to introduce copies.
But it does<br class="">
seem like the current wording would allow you to
rely on that<br class="">
pointer pointing into /some/ valid object, at least
until the<br class="">
end of the caller’s full-expression. That means
that, if we<br class="">
don’t guarantee to do an actual copy of the
argument, we cannot<br class="">
make it UB to access the parameter variable through
pointers to<br class="">
the argument temporary, which is what marking the
parameter as<br class="">
|noalias| would do.<br class="">
<br class="">
So I guess the remaining questions are:<br class="">
<br class="">
* Is this something we can reasonably change in the
standard?<br class="">
</p>
</blockquote><p dir="auto" class=""> This is the part that I'm unclear about.
What change would we make?<br class="">
<br class="">
</p>
</blockquote><p dir="auto" class=""> Also, maybe some extended use of the
no_unique_address attribute<br class="">
would help?<br class="">
<br class="">
-Hal<br class="">
<br class="">
</p>
<blockquote style="border-left:2px solid #777; color:#BBB;
margin:0 0 5px; padding-left:5px;
border-left-color:#BBB" class="">
<blockquote style="border-left:2px solid #777;
color:#BBB; margin:0 0 5px; padding-left:5px;
border-left-color:#BBB" class=""><p dir="auto" class=""> * Are we comfortable setting |noalias|
in C if the only place<br class="">
that would break is with a C++ caller?<br class="">
</p>
</blockquote><p dir="auto" class=""> Out of curiosity, if you take C in
combination with our<br class="">
statement-expression extension implementation<br class="">
(<a href="https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html" style="color:#BBB" moz-do-not-send="true" class="">https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html</a><br class="">
<<a href="https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html" style="color:#BBB" moz-do-not-send="true" class="">https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html</a>>),
and<br class="">
notwithstanding the statement in the GCC manual about
returns by<br class="">
value (i.e., the part just before where it says,
"Therefore the<br class="">
this pointer observed by Foo is not the address of
a."), is there<br class="">
any relationship to this topic?<br class="">
<br class="">
Thanks again,<br class="">
<br class="">
Hal<br class="">
<br class="">
</p>
<blockquote style="border-left:2px solid #777;
color:#BBB; margin:0 0 5px; padding-left:5px;
border-left-color:#BBB" class=""><p dir="auto" class=""> John.<br class="">
<br class="">
As Richard's example shows, the code doesn't need to<br class="">
explicitly compare the addresses to detect the copy
either.<br class="">
Any code that reads/writes to the objects can do it.
A<br class="">
perhaps-more-realistic example might be:<br class="">
<br class="">
int Cnt = A.RefCnt; ++A.RefCnt; ++B.RefCnt; if
(Cnt + 1 !=<br class="">
A.RefCnt) { /* same object case */ }<br class="">
<br class="">
The best suggestion that I have so far is that we
could add<br class="">
an attribute like 'can_copy' indicating that the
optimizer<br class="">
can make a formal copy of the argument in the callee
and use<br class="">
that instead of the original pointer if that seems
useful. I<br class="">
can certainly imagine a transformation such as LICM
making<br class="">
use of such a thing (although the cost modeling
would<br class="">
probably need to be fairly conservative).<br class="">
<br class="">
-Hal<br class="">
<br class="">
...<br class="">
<br class="">
John.<br class="">
<br class="">
<br class="">
_______________________________________________<br class="">
cfe-dev mailing list<br class="">
<a class="moz-txt-link-abbreviated" href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a> <<a href="mailto:cfe-dev@lists.llvm.org" style="color:#BBB" moz-do-not-send="true" class="">mailto:cfe-dev@lists.llvm.org</a>><br class="">
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" style="color:#BBB" moz-do-not-send="true" class="">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br class="">
<<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" style="color:#BBB" moz-do-not-send="true" class="">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a>><br class="">
<br class="">
-- <br class="">
Hal Finkel<br class="">
Lead, Compiler Technology and Programming Languages<br class="">
Leadership Computing Facility<br class="">
Argonne National Laboratory<br class="">
</p>
</blockquote><p dir="auto" class=""> -- <br class="">
Hal Finkel<br class="">
Lead, Compiler Technology and Programming Languages<br class="">
Leadership Computing Facility<br class="">
Argonne National Laboratory</p>
</blockquote><p dir="auto" class=""> -- <br class="">
Hal Finkel<br class="">
Lead, Compiler Technology and Programming Languages<br class="">
Leadership Computing Facility<br class="">
Argonne National Laboratory<br class="">
<br class="">
_______________________________________________<br class="">
cfe-dev mailing list<br class="">
<a class="moz-txt-link-abbreviated" href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a> <<a href="mailto:cfe-dev@lists.llvm.org" style="color:#999" moz-do-not-send="true" class="">mailto:cfe-dev@lists.llvm.org</a>><br class="">
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" style="color:#999" moz-do-not-send="true" class="">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br class="">
<<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" style="color:#999" moz-do-not-send="true" class="">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a>><br class="">
</p>
</blockquote><p dir="auto" class="">-- <br class="">
Hal Finkel<br class="">
Lead, Compiler Technology and Programming Languages<br class="">
Leadership Computing Facility<br class="">
Argonne National Laboratory</p>
</blockquote>
</div>
<div style="white-space:normal" class="">
</div>
</div>
</blockquote>
<pre class="moz-signature" cols="72">--
Hal Finkel
Lead, Compiler Technology and Programming Languages
Leadership Computing Facility
Argonne National Laboratory</pre>
</div>
_______________________________________________<br class="">cfe-dev mailing list<br class=""><a href="mailto:cfe-dev@lists.llvm.org" class="">cfe-dev@lists.llvm.org</a><br class="">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev<br class=""></div></blockquote></div><br class=""></div></div></body></html>