r224329 - Renamed RefersToEnclosingLocal bitfield to RefersToCapturedVariable.
Bataev, Alexey
a.bataev at hotmail.com
Mon Jan 12 02:19:49 PST 2015
Hi Richard, John,
Done in r225624.
Best regards,
Alexey Bataev
=============
Software Engineer
Intel Compiler Team
06.01.2015 8:45, John McCall пишет:
>> On Jan 5, 2015, at 7:05 AM, Richard Smith <richard at metafoo.co.uk
>> <mailto:richard at metafoo.co.uk>> wrote:
>> On Sun, Jan 4, 2015 at 7:57 PM, John McCall <rjmccall at apple.com
>> <mailto:rjmccall at apple.com>> wrote:
>>
>>> On Jan 4, 2015, at 6:28 PM, Richard Smith <richard at metafoo.co.uk
>>> <mailto:richard at metafoo.co.uk>> wrote:
>>>
>>> On 5 Jan 2015 02:08, "John McCall" <rjmccall at apple.com
>>> <mailto:rjmccall at apple.com>> wrote:
>>> >>
>>> >> On Jan 4, 2015, at 1:11 AM, Richard Smith
>>> <richard at metafoo.co.uk <mailto:richard at metafoo.co.uk>> wrote:
>>> >> On Sat, Jan 3, 2015 at 1:46 PM, John McCall
>>> <rjmccall at apple.com <mailto:rjmccall at apple.com>> wrote:
>>> >>>>
>>> >>>> On Jan 2, 2015, at 7:10 AM, Richard Smith
>>> <richard at metafoo.co.uk <mailto:richard at metafoo.co.uk>> wrote:
>>> >>>> On Tue, Dec 16, 2014 at 12:01 AM, Alexey Bataev
>>> <a.bataev at hotmail.com <mailto:a.bataev at hotmail.com>> wrote:
>>> >>>>>
>>> >>>>> Author: abataev
>>> >>>>> Date: Tue Dec 16 02:01:48 2014
>>> >>>>> New Revision: 224329
>>> >>>>>
>>> >>>>> URL: http://llvm.org/viewvc/llvm-project?rev=224329&view=rev
>>> >>>>> Log:
>>> >>>>> Renamed RefersToEnclosingLocal bitfield to
>>> RefersToCapturedVariable.
>>> >>>>> 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.
>>> >>>>> No functional changes.
>>> >>>>
>>> >>>>
>>> >>>> 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).
>>> >>>
>>> >>>
>>> >>> 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.
>>> >>
>>> >>
>>> >> 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).
>>> >>
>>> >> 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.
>>> >
>>> >
>>> > 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?
>>> >
>>> > 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.
>>>
>>> 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.
>>>
>> 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.
>>
>>
>> Apologies for the terseness, was replying from a phone.
>>
>> Okay, I believe what you’re saying is:
>> 1. A reference to an entity (a variable/this) within a lambda
>> only causes a capture if it's an ODR use.
>> 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.
>> 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.)
>> 4. Since we sometimes share DRE nodes, we can’t retroactively
>> alter a node after doing the necessary semantic analysis.
>> 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.
>>
>> I think point #4 tells us that the desired information in #5
>> can’t actually be directly represented in the AST, though.
>>
>>
>> Yes, that's an excellent summary. For concreteness, here's an example
>> where this happens:
>> 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.)(); }
>> 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.
>>
>> 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.
>>
>>
>> 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.
>
> 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.
>
>> In all other cases, it's correct and often reasonable to evaluate the
>> expression at runtime.
>
> 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.
>
> 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.
>
>> 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.
>
> Sure.
>
>> 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.
>>
>>
>> That seems fine to me.
>
> Okay. Alexey, would you mind doing this after you get back from break?
>
> John.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150112/67345c76/attachment.html>
More information about the cfe-commits
mailing list