<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">Hi Richard, John,<br>
Done in r225624.<br>
<pre class="moz-signature" cols="72">Best regards,
Alexey Bataev
=============
Software Engineer
Intel Compiler Team</pre>
06.01.2015 8:45, John McCall пишет:<br>
</div>
<blockquote
cite="mid:FB476822-9917-4451-BB80-0634B1E6935A@apple.com"
type="cite">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<div>
<blockquote type="cite" class="">
<div class="">On Jan 5, 2015, at 7:05 AM, Richard Smith <<a
moz-do-not-send="true" href="mailto:richard@metafoo.co.uk"
class="">richard@metafoo.co.uk</a>> wrote:</div>
<div class="">
<div dir="ltr" class="">
<div class="gmail_extra">
<div class="gmail_quote">On Sun, Jan 4, 2015 at 7:57 PM,
John McCall <span dir="ltr" class=""><<a
moz-do-not-send="true"
href="mailto:rjmccall@apple.com" target="_blank"
class="">rjmccall@apple.com</a>></span> wrote:<br
class="">
<blockquote class="gmail_quote" style="margin:0px 0px
0px
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div style="word-wrap:break-word" class="">
<div class=""><span class="">
<blockquote type="cite" class="">
<div class="">On Jan 4, 2015, at 6:28 PM,
Richard Smith <<a
moz-do-not-send="true"
href="mailto:richard@metafoo.co.uk"
target="_blank" class="">richard@metafoo.co.uk</a>>
wrote:</div>
<div class="">
<p dir="ltr" class="">On 5 Jan 2015 02:08,
"John McCall" <<a
moz-do-not-send="true"
href="mailto:rjmccall@apple.com"
target="_blank" class="">rjmccall@apple.com</a>>
wrote:<br class="">
>><br class="">
>> On Jan 4, 2015, at 1:11 AM,
Richard Smith <<a
moz-do-not-send="true"
href="mailto:richard@metafoo.co.uk"
target="_blank" class="">richard@metafoo.co.uk</a>>
wrote:<br class="">
>> On Sat, Jan 3, 2015 at 1:46 PM,
John McCall <<a
moz-do-not-send="true"
href="mailto:rjmccall@apple.com"
target="_blank" class="">rjmccall@apple.com</a>>
wrote:<br class="">
>>>><br class="">
>>>> On Jan 2, 2015, at 7:10
AM, Richard Smith <<a
moz-do-not-send="true"
href="mailto:richard@metafoo.co.uk"
target="_blank" class="">richard@metafoo.co.uk</a>>
wrote:<br class="">
>>>> On Tue, Dec 16, 2014 at
12:01 AM, Alexey Bataev <<a
moz-do-not-send="true"
href="mailto:a.bataev@hotmail.com"
target="_blank" class="">a.bataev@hotmail.com</a>>
wrote:<br class="">
>>>>><br class="">
>>>>> Author: abataev<br
class="">
>>>>> Date: Tue Dec 16
02:01:48 2014<br class="">
>>>>> New Revision:
224329<br class="">
>>>>><br class="">
>>>>> URL: <a
moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project?rev=224329&view=rev"
target="_blank" class="">http://llvm.org/viewvc/llvm-project?rev=224329&view=rev</a><br
class="">
>>>>> Log:<br class="">
>>>>> Renamed
RefersToEnclosingLocal bitfield to
RefersToCapturedVariable.<br class="">
>>>>> Bitfield
RefersToEnclosingLocal of
Stmt::DeclRefExprBitfields renamed to
RefersToCapturedVariable to reflect
latest changes introduced in commit
224323. Also renamed method
Expr::refersToEnclosingLocal() to
Expr::refersToCapturedVariable() and
comments for constant arguments.<br
class="">
>>>>> No functional
changes.<br class="">
>>>><br class="">
>>>><br class="">
>>>> This seems like a bad
idea for me. It's incorrect: for a
lambda, the flag means that the
DeclRefExpr refers to an enclosing
local, and does *not* imply that the
variable is necessarily captured. This
confusion has already led to a bug
(fixed in r225060).<br class="">
>>><br class="">
>>><br class="">
>>> If that’s actually a useful
property to track, I have no complaint
about tracking the two things
separately. I don’t think DRE is short
of bits.<br class="">
>><br class="">
>><br class="">
>> The problem is that we can't
reasonably track whether a DRE refers to
a captured variable, because that is not
a local property of the DRE; it depends
on non-trivial properties of the context
in which the DRE is used (and more
generally it depends on how else that
same variable is used elsewhere in the
lambda, but we can largely ignore that).<br
class="">
>><br class="">
>> I'd be fine having separate
flags for 'refers to enclosing local'
and 'refers to captured global' (if the
latter is the point of this change), but
we should not claim a DRE refers to a
capture when it does not.<br class="">
><br class="">
><br class="">
> Richard, I understand that not all
DREs are potentially evaluated and thus
may not actually induce capturing, and I
concede your point that the flag's name
shouldn’t use the word “capture” if it’s
set on unevaluated DREs. The question
is this: what information do we actually
need to track on DREs?<br class="">
><br class="">
> It is very useful for IR-gen to be
able to immediately know whether a DRE
refers to a captured local or global
variable, no matter why that capture was
performed. As far as I’m aware, IR-gen
does not care about whether the flag is
set on unevaluated references to
enclosing variables, because IR-gen
should never see an unevaluated use in
normal expression emission.</p>
<p dir="ltr" class="">This is not about
unevaluated references, it's about
evaluated references that aren't odr
uses, which depends on the context in
which the DRE appears. IRGen does need
to deal with these cases.</p>
</div>
</blockquote>
</span>Ugh, fine, I will go haul out the
standard to figure out what you’re talking
about, since you are apparently in a vague mood
tonight.</div>
</div>
</blockquote>
<div class=""><br class="">
</div>
<div class="">Apologies for the terseness, was
replying from a phone.</div>
<div class=""> </div>
<blockquote class="gmail_quote" style="margin:0px 0px
0px
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div style="word-wrap:break-word" class="">
<div class="">Okay, I believe what you’re saying
is:</div>
<div class="">1. A reference to an entity (a
variable/this) within a lambda only causes a
capture if it's an ODR use.</div>
<div class="">2. All ODR uses are PE references,
but a PE reference isn't an ODR use if the
variable can be used in a constant expression
and it's a potential result of an expression
that’s either ignored or loaded.</div>
<div class="">3. Whether an expression is ignored
or loaded cannot be decided immediately from
context; you have to semantically process the
entire expression, and it may be different in
different template instantiations. (This
dependence is also true of PPE-ness, I think.)</div>
<div class="">4. Since we sometimes share DRE
nodes, we can’t retroactively alter a node after
doing the necessary semantic analysis.</div>
<div class="">5. AST clients are likely to want to
know whether a DRE is not an ODR-use and can
only be constant-evaluated. For example, it’s
important that IR-gen not actually emit a
reference to a static member variable of a class
template if that member variable hasn’t been
ODR-used. Clients should similarly not be
confused by an evaluated reference to an
uncaptured enclosing local.</div>
<div class=""><br class="">
</div>
<div class="">I think point #4 tells us that the
desired information in #5 can’t actually be
directly represented in the AST, though.</div>
</div>
</blockquote>
<div class=""><br class="">
</div>
<div class="">Yes, that's an excellent summary. For
concreteness, here's an example where this happens:</div>
<div class="">
<pre style="" class="">void f(int, int);
void f(const int&, double);
auto f() {
const int n = 0;
return [=](auto t) { return [=]() { f(n, t); } };
}
void g() { f()(0)(); f()(0.)(); }</pre>
</div>
<div class="">Here, the lambda returned by f()(0) does
not capture 'n', but the lambda returned by f()(0.)
does, and they share a DeclRefExpr for n.<br
class="">
</div>
<div class=""><br class="">
</div>
<blockquote class="gmail_quote" style="margin:0px 0px
0px
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div style="word-wrap:break-word" class="">
<div class="">But as the first example shows,
client interests in #5 are much broader than
just references to enclosing locals. IR-gen
would benefit from knowing whether an arbitrary
expression was constant-evaluable; currently it
has hacky code to try to constant-evaluate
specific nodes, and it lets all the other nodes
fall out from LLVM’s own constant-folding and
optimization, but it would clearly be better to,
say, know that a particular call is a call to a
constexpr function with constant arguments and
so we can just directly try to fold it instead
of emitting a whole bunch of unnecessary code
that will get cleaned up later. Using “this is
an enclosing local” as an incomplete
approximation of that isn’t actually useful.</div>
</div>
</blockquote>
<div class=""><br class="">
</div>
<div class="">The only cases where we need to emit
different code based on whether an expression is a
constant expression (outside unevaluated contexts)
are when initializing a variable of
static/thread_local storage duration, and when an
expression refers to an enclosing local variable
that it doesn't capture.</div>
</div>
</div>
</div>
</div>
</blockquote>
<div><br class="">
</div>
<div>You’re forgetting references to static data members, which
don’t have to be defined if they have a constant initializer
in the class definition and are never ODR-used. (Of course,
in practice people learn to avoid writing code that relies on
this because it’s too easy to accidentally ODR-use a variable;
but it’s in the spec.) This is something that can’t as easily
be hacked around in IRGen.</div>
<br class="">
<blockquote type="cite" class="">
<div class="">
<div dir="ltr" class="">
<div class="gmail_extra">
<div class="gmail_quote">
<div class=""> In all other cases, it's correct and
often reasonable to evaluate the expression at
runtime.</div>
</div>
</div>
</div>
</div>
</blockquote>
<div><br class="">
</div>
<div>It’s correct, but it’s easy to imagine code where this
causes a great deal of unnecessary code to be emitted,
optimized, and finally thrown away.</div>
<div><br class="">
</div>
<div>Also we probably have bugs involving some of the recursive
cases of potential results where IRGen will introduce illegal
symbol references. I’m particularly concerned about loads
from members.</div>
<br class="">
<blockquote type="cite" class="">
<div class="">
<div dir="ltr" class="">
<div class="gmail_extra">
<div class="gmail_quote">
<div class="">In the case where a lambda expression
refers to an enclosing local but doesn't capture it,
we should emit a copy of that local's value as a
constant global.</div>
</div>
</div>
</div>
</div>
</blockquote>
<div><br class="">
</div>
Sure.<br class="">
<div><br class="">
</div>
<blockquote type="cite" class="">
<div class="">
<div dir="ltr" class="">
<div class="gmail_extra">
<div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0px 0px
0px
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div style="word-wrap:break-word" class="">
<div class="">So it seems to me that we just need
one bit, called
refersToEnclosingVariableOrCapture(), with the
meaning that it’s set if the DRE refers to an
enclosing local (captured or not) or captured
global variable, regardless of whether this
reference is an ODR use.</div>
</div>
</blockquote>
<div class=""><br class="">
</div>
<div class="">That seems fine to me.</div>
</div>
</div>
</div>
</div>
</blockquote>
</div>
<br class="">
<div class="">Okay. Alexey, would you mind doing this after you
get back from break?</div>
<div class=""><br class="">
</div>
<div class="">John.</div>
</blockquote>
<br>
</body>
</html>