diff mbox

New option to turn off stack reuse for temporaries

Message ID CAAkRFZK_27tveOTLioz-YwfF_4w4qtTJkRFjno7r8risRVQsnQ@mail.gmail.com
State New
Headers show

Commit Message

Xinliang David Li June 20, 2012, 10:50 p.m. UTC
One of the most common runtime errors we have seen in gcc-4_7 is
caused by dangling references to temporaries whole life time have
ended

e.g,

 const A& a = foo();

or
foo (A());// where temp's address is saved and used after foo.

Of course this is user error according to the standard, triaging of
bugs like this is pretty time consuming to triage. This patch tries to
introduce an option to disable stack reuse for temporaries, which can
be used to debugging purpose.

Is this good for trunk?

thanks,

David

2012-06-20  Xinliang David Li  <davidxl@google.com>

        * common.opt: -ftemp-reuse-stack option.
        * gimplify.c (gimplify_target_expr): Check new flag.

Comments

Jason Merrill June 21, 2012, 12:29 a.m. UTC | #1
The documentation needs to explain more what the option controls, and 
why you might want it on or off.  Other than that it looks fine.

Jason
Xinliang David Li June 21, 2012, 5:28 a.m. UTC | #2
I modified the documentation and it now looks like this:

@item -ftemp-stack-reuse
@opindex ftemp_stack_reuse
This option enables stack space reuse for temporaries. The default is on.
The lifetime of a compiler generated temporary is well defined by the C++
standard. When a lifetime of a temporary ends, and if the temporary lives
in memory, an optimizing compiler has the freedom to reuse its stack
space with other temporaries or scoped local variables whose live range
does not overlap with it. However some of the legacy code relies on
the behavior of older compilers in which temporaries' stack space is
not reused, the aggressive stack reuse can lead to runtime errors. This
option is used to control the temporary stack reuse optimization.

Does it look ok?

thanks,

David

On Wed, Jun 20, 2012 at 5:29 PM, Jason Merrill <jason@redhat.com> wrote:
> The documentation needs to explain more what the option controls, and why
> you might want it on or off.  Other than that it looks fine.
>
> Jason
Jason Merrill June 21, 2012, 6:16 a.m. UTC | #3
OK.

Jason
Richard Biener June 21, 2012, 9:21 a.m. UTC | #4
On Thu, Jun 21, 2012 at 7:28 AM, Xinliang David Li <davidxl@google.com> wrote:
> I modified the documentation and it now looks like this:
>
> @item -ftemp-stack-reuse
> @opindex ftemp_stack_reuse
> This option enables stack space reuse for temporaries. The default is on.
> The lifetime of a compiler generated temporary is well defined by the C++
> standard. When a lifetime of a temporary ends, and if the temporary lives
> in memory, an optimizing compiler has the freedom to reuse its stack
> space with other temporaries or scoped local variables whose live range
> does not overlap with it. However some of the legacy code relies on
> the behavior of older compilers in which temporaries' stack space is
> not reused, the aggressive stack reuse can lead to runtime errors. This
> option is used to control the temporary stack reuse optimization.
>
> Does it look ok?

The flag is not restricted to the C++ compiler and applies to all automatic
variables.  The description is very much C++ specific though - I think
it should mention the concept of scopes.

Also even with this flag there is no guarantee we cannot figure out lifetime
in other ways, for example if the temporary gets promoted to a register.
Also with this patch you remove code motion barriers which might cause
other issues.

A more "proper" place to fix this is when we actually do the stack reuse,
in cfgexpand.

So no, I don't think the patch is ok as-is.

Thanks,
Richard.

> thanks,
>
> David
>
> On Wed, Jun 20, 2012 at 5:29 PM, Jason Merrill <jason@redhat.com> wrote:
>> The documentation needs to explain more what the option controls, and why
>> you might want it on or off.  Other than that it looks fine.
>>
>> Jason
Michael Matz June 21, 2012, 3:53 p.m. UTC | #5
Hi,

On Thu, 21 Jun 2012, Richard Guenther wrote:

> The flag is not restricted to the C++ compiler and applies to all 
> automatic variables.

The use of that flag in the gimplifier (->in_cleanup_expr) makes it 
actually c++ specific.

> Also even with this flag there is no guarantee we cannot figure out 
> lifetime in other ways, for example if the temporary gets promoted to a 
> register. Also with this patch you remove code motion barriers which 
> might cause other issues.
> 
> A more "proper" place to fix this is when we actually do the stack 
> reuse, in cfgexpand.

That is true, though.  It would then also enable debugging help for 
pointers to things that go out-of-scope.


Ciao,
Michael.
Jason Merrill June 21, 2012, 5:50 p.m. UTC | #6
On 06/21/2012 02:21 AM, Richard Guenther wrote:
> The flag is not restricted to the C++ compiler and applies to all automatic
> variables.

This only affects the clobbers for C++ temporary objects, not clobbers 
for automatic variables going out of scope.

> Also with this patch you remove code motion barriers which might cause
> other issues.

How so?

> A more "proper" place to fix this is when we actually do the stack reuse,
> in cfgexpand.

How would that distinguish between the clobbers for temporaries vs. 
automatics?

Jason
Xinliang David Li June 21, 2012, 6:27 p.m. UTC | #7
On Thu, Jun 21, 2012 at 2:21 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Thu, Jun 21, 2012 at 7:28 AM, Xinliang David Li <davidxl@google.com> wrote:
>> I modified the documentation and it now looks like this:
>>
>> @item -ftemp-stack-reuse
>> @opindex ftemp_stack_reuse
>> This option enables stack space reuse for temporaries. The default is on.
>> The lifetime of a compiler generated temporary is well defined by the C++
>> standard. When a lifetime of a temporary ends, and if the temporary lives
>> in memory, an optimizing compiler has the freedom to reuse its stack
>> space with other temporaries or scoped local variables whose live range
>> does not overlap with it. However some of the legacy code relies on
>> the behavior of older compilers in which temporaries' stack space is
>> not reused, the aggressive stack reuse can lead to runtime errors. This
>> option is used to control the temporary stack reuse optimization.
>>
>> Does it look ok?
>
> The flag is not restricted to the C++ compiler and applies to all automatic
> variables.  The description is very much C++ specific though - I think
> it should mention the concept of scopes.
>
> Also even with this flag there is no guarantee we cannot figure out lifetime
> in other ways, for example if the temporary gets promoted to a register.

That should not be an issue then -- if the compiler can figure out the
live range via data flow analysis (instead of relying on
assertions/markers), the stack reuse or register promotion based on
that should always be safe (assuming no bugs in the analysis).

> Also with this patch you remove code motion barriers which might cause
> other issues.

What other issues? It enables more potential code motion, but on the
other hand, causes more conservative stack reuse. As far I can tell,
the handling of temporaries is added independently after the clobber
for scoped variables are introduced. This option can be used to
restore the older behavior (in handling temps).

thanks,

David

>
> A more "proper" place to fix this is when we actually do the stack reuse,
> in cfgexpand.
>
> So no, I don't think the patch is ok as-is.
>
> Thanks,
> Richard.
>
>> thanks,
>>
>> David
>>
>> On Wed, Jun 20, 2012 at 5:29 PM, Jason Merrill <jason@redhat.com> wrote:
>>> The documentation needs to explain more what the option controls, and why
>>> you might want it on or off.  Other than that it looks fine.
>>>
>>> Jason
Richard Biener June 22, 2012, 8:28 a.m. UTC | #8
On Thu, Jun 21, 2012 at 5:53 PM, Michael Matz <matz@suse.de> wrote:
> Hi,
>
> On Thu, 21 Jun 2012, Richard Guenther wrote:
>
>> The flag is not restricted to the C++ compiler and applies to all
>> automatic variables.
>
> The use of that flag in the gimplifier (->in_cleanup_expr) makes it
> actually c++ specific.

We don't have any other users of WITH_CLEANUP_EXPR?  Indeed.

>> Also even with this flag there is no guarantee we cannot figure out
>> lifetime in other ways, for example if the temporary gets promoted to a
>> register. Also with this patch you remove code motion barriers which
>> might cause other issues.
>>
>> A more "proper" place to fix this is when we actually do the stack
>> reuse, in cfgexpand.
>
> That is true, though.  It would then also enable debugging help for
> pointers to things that go out-of-scope.

Yes.  So I think if the flag is supposed to be used for debugging (instead
of as fix or workaround for invalid programs) then we should go one step
further and have it disable stack slot sharing alltogether - without any
other side-effect on pre-RTL optimizations (which undoubtedly not having
the CLOBBERS have).

Richard.

>
> Ciao,
> Michael.
Richard Biener June 22, 2012, 8:30 a.m. UTC | #9
On Thu, Jun 21, 2012 at 8:27 PM, Xinliang David Li <davidxl@google.com> wrote:
> On Thu, Jun 21, 2012 at 2:21 AM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Thu, Jun 21, 2012 at 7:28 AM, Xinliang David Li <davidxl@google.com> wrote:
>>> I modified the documentation and it now looks like this:
>>>
>>> @item -ftemp-stack-reuse
>>> @opindex ftemp_stack_reuse
>>> This option enables stack space reuse for temporaries. The default is on.
>>> The lifetime of a compiler generated temporary is well defined by the C++
>>> standard. When a lifetime of a temporary ends, and if the temporary lives
>>> in memory, an optimizing compiler has the freedom to reuse its stack
>>> space with other temporaries or scoped local variables whose live range
>>> does not overlap with it. However some of the legacy code relies on
>>> the behavior of older compilers in which temporaries' stack space is
>>> not reused, the aggressive stack reuse can lead to runtime errors. This
>>> option is used to control the temporary stack reuse optimization.
>>>
>>> Does it look ok?
>>
>> The flag is not restricted to the C++ compiler and applies to all automatic
>> variables.  The description is very much C++ specific though - I think
>> it should mention the concept of scopes.
>>
>> Also even with this flag there is no guarantee we cannot figure out lifetime
>> in other ways, for example if the temporary gets promoted to a register.
>
> That should not be an issue then -- if the compiler can figure out the
> live range via data flow analysis (instead of relying on
> assertions/markers), the stack reuse or register promotion based on
> that should always be safe (assuming no bugs in the analysis).
>
>> Also with this patch you remove code motion barriers which might cause
>> other issues.
>
> What other issues? It enables more potential code motion, but on the
> other hand, causes more conservative stack reuse. As far I can tell,
> the handling of temporaries is added independently after the clobber
> for scoped variables are introduced. This option can be used to
> restore the older behavior (in handling temps).

Well, it does not really restore the old behavior (if you mean before adding
CLOBBERS, not before the single patch that might have used those for
gimplifying WITH_CLEANUP_EXPR).  You say it disables stack-slot sharing
for those decls but it also does other things via side-effects of no longer
emitting the CLOBBER.  I say it's better to disable the stack-slot sharing.

Richard.

> thanks,
>
> David
>
>>
>> A more "proper" place to fix this is when we actually do the stack reuse,
>> in cfgexpand.
>>
>> So no, I don't think the patch is ok as-is.
>>
>> Thanks,
>> Richard.
>>
>>> thanks,
>>>
>>> David
>>>
>>> On Wed, Jun 20, 2012 at 5:29 PM, Jason Merrill <jason@redhat.com> wrote:
>>>> The documentation needs to explain more what the option controls, and why
>>>> you might want it on or off.  Other than that it looks fine.
>>>>
>>>> Jason
Jason Merrill June 22, 2012, 9:29 a.m. UTC | #10
On 06/22/2012 01:30 AM, Richard Guenther wrote:
>> What other issues? It enables more potential code motion, but on the
>> other hand, causes more conservative stack reuse. As far I can tell,
>> the handling of temporaries is added independently after the clobber
>> for scoped variables are introduced. This option can be used to
>> restore the older behavior (in handling temps).
>
> Well, it does not really restore the old behavior (if you mean before adding
> CLOBBERS, not before the single patch that might have used those for
> gimplifying WITH_CLEANUP_EXPR).  You say it disables stack-slot sharing
> for those decls but it also does other things via side-effects of no longer
> emitting the CLOBBER.  I say it's better to disable the stack-slot sharing.

The patch exactly restores the behavior of temporaries from before my 
change to add CLOBBERs for temporaries.  The primary effect of that 
change was to provide stack-slot sharing, but if there are other effects 
they are probably desirable as well, since the broken code depended on 
the old behavior.

Jason
Richard Biener June 22, 2012, 9:39 a.m. UTC | #11
On Fri, Jun 22, 2012 at 11:29 AM, Jason Merrill <jason@redhat.com> wrote:
> On 06/22/2012 01:30 AM, Richard Guenther wrote:
>>>
>>> What other issues? It enables more potential code motion, but on the
>>> other hand, causes more conservative stack reuse. As far I can tell,
>>> the handling of temporaries is added independently after the clobber
>>> for scoped variables are introduced. This option can be used to
>>> restore the older behavior (in handling temps).
>>
>>
>> Well, it does not really restore the old behavior (if you mean before
>> adding
>> CLOBBERS, not before the single patch that might have used those for
>> gimplifying WITH_CLEANUP_EXPR).  You say it disables stack-slot sharing
>> for those decls but it also does other things via side-effects of no
>> longer
>> emitting the CLOBBER.  I say it's better to disable the stack-slot
>> sharing.
>
>
> The patch exactly restores the behavior of temporaries from before my change
> to add CLOBBERs for temporaries.  The primary effect of that change was to
> provide stack-slot sharing, but if there are other effects they are probably
> desirable as well, since the broken code depended on the old behavior.

So you see it as workaround option, like -fno-strict-aliasing, rather than
debugging aid?

Richard.

> Jason
Xinliang David Li June 22, 2012, 3:51 p.m. UTC | #12
On Fri, Jun 22, 2012 at 2:39 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Fri, Jun 22, 2012 at 11:29 AM, Jason Merrill <jason@redhat.com> wrote:
>> On 06/22/2012 01:30 AM, Richard Guenther wrote:
>>>>
>>>> What other issues? It enables more potential code motion, but on the
>>>> other hand, causes more conservative stack reuse. As far I can tell,
>>>> the handling of temporaries is added independently after the clobber
>>>> for scoped variables are introduced. This option can be used to
>>>> restore the older behavior (in handling temps).
>>>
>>>
>>> Well, it does not really restore the old behavior (if you mean before
>>> adding
>>> CLOBBERS, not before the single patch that might have used those for
>>> gimplifying WITH_CLEANUP_EXPR).  You say it disables stack-slot sharing
>>> for those decls but it also does other things via side-effects of no
>>> longer
>>> emitting the CLOBBER.  I say it's better to disable the stack-slot
>>> sharing.
>>
>>
>> The patch exactly restores the behavior of temporaries from before my change
>> to add CLOBBERs for temporaries.  The primary effect of that change was to
>> provide stack-slot sharing, but if there are other effects they are probably
>> desirable as well, since the broken code depended on the old behavior.
>
> So you see it as workaround option, like -fno-strict-aliasing, rather than
> debugging aid?

It can be used for both purposes -- if the violations are as pervasive
as strict-aliasing cases (which looks like so).

thanks,

David

>
> Richard.
>
>> Jason
Xinliang David Li June 25, 2012, 4:25 p.m. UTC | #13
Are there any more concerns about this patch? If not, I'd like to check it in.

thanks,

David

On Fri, Jun 22, 2012 at 8:51 AM, Xinliang David Li <davidxl@google.com> wrote:
> On Fri, Jun 22, 2012 at 2:39 AM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Fri, Jun 22, 2012 at 11:29 AM, Jason Merrill <jason@redhat.com> wrote:
>>> On 06/22/2012 01:30 AM, Richard Guenther wrote:
>>>>>
>>>>> What other issues? It enables more potential code motion, but on the
>>>>> other hand, causes more conservative stack reuse. As far I can tell,
>>>>> the handling of temporaries is added independently after the clobber
>>>>> for scoped variables are introduced. This option can be used to
>>>>> restore the older behavior (in handling temps).
>>>>
>>>>
>>>> Well, it does not really restore the old behavior (if you mean before
>>>> adding
>>>> CLOBBERS, not before the single patch that might have used those for
>>>> gimplifying WITH_CLEANUP_EXPR).  You say it disables stack-slot sharing
>>>> for those decls but it also does other things via side-effects of no
>>>> longer
>>>> emitting the CLOBBER.  I say it's better to disable the stack-slot
>>>> sharing.
>>>
>>>
>>> The patch exactly restores the behavior of temporaries from before my change
>>> to add CLOBBERs for temporaries.  The primary effect of that change was to
>>> provide stack-slot sharing, but if there are other effects they are probably
>>> desirable as well, since the broken code depended on the old behavior.
>>
>> So you see it as workaround option, like -fno-strict-aliasing, rather than
>> debugging aid?
>
> It can be used for both purposes -- if the violations are as pervasive
> as strict-aliasing cases (which looks like so).
>
> thanks,
>
> David
>
>>
>> Richard.
>>
>>> Jason
Richard Biener June 26, 2012, 8:28 a.m. UTC | #14
On Mon, Jun 25, 2012 at 6:25 PM, Xinliang David Li <davidxl@google.com> wrote:
> Are there any more concerns about this patch? If not, I'd like to check it in.

No - the fact that the flag is C++ specific but in common.opt is odd enough
and -ftemp-reuse-stack sounds very very generic - which in fact it is not,
it's a no-op in C.  Is there a more formal phrase for the temporary kind that
is affected?  For me "temp" is synonymous to "auto" so I'd have expected
the switch to turn off stack slot sharing for

 {
   int a[5];
 }
 {
   int a[5];
 }

but that is not what it does.  So - a little kludgy but probably more to what
I'd like it to be would be to move the option to c-family/c.opt enabled only
for C++ and Obj-C++ and export it to the middle-end via a new langhook
(the gimplifier code should be in Frontend code that lowers to GENERIC
really and the WITH_CLEANUP_EXPR code should be C++ frontend specific ...).

Thanks,
Richard.

> thanks,
>
> David
>
> On Fri, Jun 22, 2012 at 8:51 AM, Xinliang David Li <davidxl@google.com> wrote:
>> On Fri, Jun 22, 2012 at 2:39 AM, Richard Guenther
>> <richard.guenther@gmail.com> wrote:
>>> On Fri, Jun 22, 2012 at 11:29 AM, Jason Merrill <jason@redhat.com> wrote:
>>>> On 06/22/2012 01:30 AM, Richard Guenther wrote:
>>>>>>
>>>>>> What other issues? It enables more potential code motion, but on the
>>>>>> other hand, causes more conservative stack reuse. As far I can tell,
>>>>>> the handling of temporaries is added independently after the clobber
>>>>>> for scoped variables are introduced. This option can be used to
>>>>>> restore the older behavior (in handling temps).
>>>>>
>>>>>
>>>>> Well, it does not really restore the old behavior (if you mean before
>>>>> adding
>>>>> CLOBBERS, not before the single patch that might have used those for
>>>>> gimplifying WITH_CLEANUP_EXPR).  You say it disables stack-slot sharing
>>>>> for those decls but it also does other things via side-effects of no
>>>>> longer
>>>>> emitting the CLOBBER.  I say it's better to disable the stack-slot
>>>>> sharing.
>>>>
>>>>
>>>> The patch exactly restores the behavior of temporaries from before my change
>>>> to add CLOBBERs for temporaries.  The primary effect of that change was to
>>>> provide stack-slot sharing, but if there are other effects they are probably
>>>> desirable as well, since the broken code depended on the old behavior.
>>>
>>> So you see it as workaround option, like -fno-strict-aliasing, rather than
>>> debugging aid?
>>
>> It can be used for both purposes -- if the violations are as pervasive
>> as strict-aliasing cases (which looks like so).
>>
>> thanks,
>>
>> David
>>
>>>
>>> Richard.
>>>
>>>> Jason
Jason Merrill June 26, 2012, 3:16 p.m. UTC | #15
On 06/26/2012 04:28 AM, Richard Guenther wrote:
> No - the fact that the flag is C++ specific but in common.opt is odd enough
> and -ftemp-reuse-stack sounds very very generic - which in fact it is not,
> it's a no-op in C.  Is there a more formal phrase for the temporary kind that
> is affected?

Not that I'm aware of.  This is a temporary introduced by TARGET_EXPR, 
which lives until the end of the enclosing CLEANUP_POINT_EXPR.

> So - a little kludgy but probably more to what
> I'd like it to be would be to move the option to c-family/c.opt enabled only
> for C++ and Obj-C++ and export it to the middle-end via a new langhook

Hmm, that does seem rather kludgy for something that affects the 
behavior of middle-end code working on GENERIC.

> (the gimplifier code should be in Frontend code that lowers to GENERIC
> really and the WITH_CLEANUP_EXPR code should be C++ frontend specific ...).

TARGET_EXPR has been a back-end code since the dawn of GCC version 
control; if it's still only used by the C++ front end I guess it could 
move to cp-tree.def, but we can't really lower it until gimplification 
time because we need to strip away enclosing COMPOUND_EXPRs and such so 
we can see that it's on the RHS of an initialization and optimize away 
the temporary in that case.  And now that GIMPLE isn't a subset of 
GENERIC, we can't just use the gimplifier at genericization time.  And 
I'd rather not duplicate the entire gimplifier in the front end.

Jason
Michael Matz June 26, 2012, 4:07 p.m. UTC | #16
Hi,

On Tue, 26 Jun 2012, Jason Merrill wrote:

> > (the gimplifier code should be in Frontend code that lowers to GENERIC 
> > really and the WITH_CLEANUP_EXPR code should be C++ frontend specific 
> > ...).
> 
> TARGET_EXPR has been a back-end code since the dawn of GCC version 
> control; if it's still only used by the C++ front end I guess it could 
> move to cp-tree.def, but we can't really lower it until gimplification 
> time because we need to strip away enclosing COMPOUND_EXPRs and such so 
> we can see that it's on the RHS of an initialization and optimize away 
> the temporary in that case. And now that GIMPLE isn't a subset of 
> GENERIC, we can't just use the gimplifier at genericization time.  And 
> I'd rather not duplicate the entire gimplifier in the front end.

I agree with Jason.  TARGET_EXPR and CLEANUP_POINT_EXPR might currently be 
used only for C++, but I think they are sensible general constructs to be 
supported by the gimplifier.

But I also think that the option to disable stack slot sharing should be 
moved to cfgexpand to trigger non-sharing of everything, not just these 
cleanup temporaries.  After all using the (c++)temporary after expression 
end is a source bug that the option is supposed to work around, just like 
this is:

  char *p; { char str[50]; p = str; } use(p);

So, IMO the option should also work around this source bug.  We had at 
least one example of that in our own code base.


Ciao,
Michael.
Jakub Jelinek June 26, 2012, 4:16 p.m. UTC | #17
On Tue, Jun 26, 2012 at 06:07:09PM +0200, Michael Matz wrote:
> I agree with Jason.  TARGET_EXPR and CLEANUP_POINT_EXPR might currently be 
> used only for C++, but I think they are sensible general constructs to be 
> supported by the gimplifier.
> 
> But I also think that the option to disable stack slot sharing should be 
> moved to cfgexpand to trigger non-sharing of everything, not just these 
> cleanup temporaries.  After all using the (c++)temporary after expression 
> end is a source bug that the option is supposed to work around, just like 
> this is:

If you move it solely to cfgexpand time, broken code will still often not
work the way it happened to work with 4.6 and earlier.  You'd need to both
disable the sharing and disable additions of gimple clobbers.
Because otherwise DCE/DSE and other passes happily optimize (broken) code
away.  So, if we want a -fno-strict-aliasing like option to work around
broken code, we should IMHO do both of those.
> 
>   char *p; { char str[50]; p = str; } use(p);
> 
> So, IMO the option should also work around this source bug.  We had at 
> least one example of that in our own code base.

Yeah, gengtype I think.

	Jakub
Mike Stump June 26, 2012, 8:09 p.m. UTC | #18
On Jun 26, 2012, at 9:07 AM, Michael Matz wrote:
> I agree with Jason.  TARGET_EXPR and CLEANUP_POINT_EXPR might currently be 
> used only for C++, but I think they are sensible general constructs to be 
> supported by the gimplifier.

As do I.  The intent was for Ada and every other language with things like temporaries and cleanups to reuse the backend constructs, so that instead of writing optimizers, one for each language, to instead share the optimizer across languages.  To me, the middle end and the backend are the best places for these.
Eric Botcazou June 26, 2012, 10:37 p.m. UTC | #19
> As do I.  The intent was for Ada and every other language with things like
> temporaries and cleanups to reuse the backend constructs, so that instead
> of writing optimizers, one for each language, to instead share the
> optimizer across languages.  To me, the middle end and the backend are the
> best places for these.

Both are very high-level constructs though.  By the time the AST is converted 
to GENERIC in the Ada compiler, it is already too lowered to make use of them.
Xinliang David Li June 29, 2012, 5:43 a.m. UTC | #20
(re-post in plain text)

Moving this to cfgexpand time is simple and it can also be extended to
handle scoped variables. However Jakub raised a good point about this
being too late as stack space overlay is not the only way to cause
trouble when the lifetime of a stack object is extended beyond the
clobber stmt.

thanks,

David

On Tue, Jun 26, 2012 at 1:28 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Mon, Jun 25, 2012 at 6:25 PM, Xinliang David Li <davidxl@google.com> wrote:
>> Are there any more concerns about this patch? If not, I'd like to check it in.
>
> No - the fact that the flag is C++ specific but in common.opt is odd enough
> and -ftemp-reuse-stack sounds very very generic - which in fact it is not,
> it's a no-op in C.  Is there a more formal phrase for the temporary kind that
> is affected?  For me "temp" is synonymous to "auto" so I'd have expected
> the switch to turn off stack slot sharing for
>
>  {
>   int a[5];
>  }
>  {
>   int a[5];
>  }
>
> but that is not what it does.  So - a little kludgy but probably more to what
> I'd like it to be would be to move the option to c-family/c.opt enabled only
> for C++ and Obj-C++ and export it to the middle-end via a new langhook
> (the gimplifier code should be in Frontend code that lowers to GENERIC
> really and the WITH_CLEANUP_EXPR code should be C++ frontend specific ...).
>
> Thanks,
> Richard.
>
>> thanks,
>>
>> David
>>
>> On Fri, Jun 22, 2012 at 8:51 AM, Xinliang David Li <davidxl@google.com> wrote:
>>> On Fri, Jun 22, 2012 at 2:39 AM, Richard Guenther
>>> <richard.guenther@gmail.com> wrote:
>>>> On Fri, Jun 22, 2012 at 11:29 AM, Jason Merrill <jason@redhat.com> wrote:
>>>>> On 06/22/2012 01:30 AM, Richard Guenther wrote:
>>>>>>>
>>>>>>> What other issues? It enables more potential code motion, but on the
>>>>>>> other hand, causes more conservative stack reuse. As far I can tell,
>>>>>>> the handling of temporaries is added independently after the clobber
>>>>>>> for scoped variables are introduced. This option can be used to
>>>>>>> restore the older behavior (in handling temps).
>>>>>>
>>>>>>
>>>>>> Well, it does not really restore the old behavior (if you mean before
>>>>>> adding
>>>>>> CLOBBERS, not before the single patch that might have used those for
>>>>>> gimplifying WITH_CLEANUP_EXPR).  You say it disables stack-slot sharing
>>>>>> for those decls but it also does other things via side-effects of no
>>>>>> longer
>>>>>> emitting the CLOBBER.  I say it's better to disable the stack-slot
>>>>>> sharing.
>>>>>
>>>>>
>>>>> The patch exactly restores the behavior of temporaries from before my change
>>>>> to add CLOBBERs for temporaries.  The primary effect of that change was to
>>>>> provide stack-slot sharing, but if there are other effects they are probably
>>>>> desirable as well, since the broken code depended on the old behavior.
>>>>
>>>> So you see it as workaround option, like -fno-strict-aliasing, rather than
>>>> debugging aid?
>>>
>>> It can be used for both purposes -- if the violations are as pervasive
>>> as strict-aliasing cases (which looks like so).
>>>
>>> thanks,
>>>
>>> David
>>>
>>>>
>>>> Richard.
>>>>
>>>>> Jason
Xinliang David Li July 2, 2012, 11:30 p.m. UTC | #21
I extended the patch a little so that the option can be used to set
multiple stack reuse levels: -fstack-reuse=[all|name_vars|none]

all: enable stack reuse for all local vars (named vars and compiler
generated temporaries) which live in memory;
name_vars: enable stack reuse only for user declared local vars with names;
none: disable stack reuse completely.

Note the patch still chooses to suppress clobber statement generation
instead of just ignoring them in stack layout. This has the additional
advantage of allowing more aggressive code motion when stack use is
disabled.

The documentation will be updated when the patch is agreed upon.

thanks,

David


On Thu, Jun 28, 2012 at 10:43 PM, Xinliang David Li <davidxl@google.com> wrote:
> (re-post in plain text)
>
> Moving this to cfgexpand time is simple and it can also be extended to
> handle scoped variables. However Jakub raised a good point about this
> being too late as stack space overlay is not the only way to cause
> trouble when the lifetime of a stack object is extended beyond the
> clobber stmt.
>
> thanks,
>
> David
>
> On Tue, Jun 26, 2012 at 1:28 AM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Mon, Jun 25, 2012 at 6:25 PM, Xinliang David Li <davidxl@google.com> wrote:
>>> Are there any more concerns about this patch? If not, I'd like to check it in.
>>
>> No - the fact that the flag is C++ specific but in common.opt is odd enough
>> and -ftemp-reuse-stack sounds very very generic - which in fact it is not,
>> it's a no-op in C.  Is there a more formal phrase for the temporary kind that
>> is affected?  For me "temp" is synonymous to "auto" so I'd have expected
>> the switch to turn off stack slot sharing for
>>
>>  {
>>   int a[5];
>>  }
>>  {
>>   int a[5];
>>  }
>>
>> but that is not what it does.  So - a little kludgy but probably more to what
>> I'd like it to be would be to move the option to c-family/c.opt enabled only
>> for C++ and Obj-C++ and export it to the middle-end via a new langhook
>> (the gimplifier code should be in Frontend code that lowers to GENERIC
>> really and the WITH_CLEANUP_EXPR code should be C++ frontend specific ...).
>>
>> Thanks,
>> Richard.
>>
>>> thanks,
>>>
>>> David
>>>
>>> On Fri, Jun 22, 2012 at 8:51 AM, Xinliang David Li <davidxl@google.com> wrote:
>>>> On Fri, Jun 22, 2012 at 2:39 AM, Richard Guenther
>>>> <richard.guenther@gmail.com> wrote:
>>>>> On Fri, Jun 22, 2012 at 11:29 AM, Jason Merrill <jason@redhat.com> wrote:
>>>>>> On 06/22/2012 01:30 AM, Richard Guenther wrote:
>>>>>>>>
>>>>>>>> What other issues? It enables more potential code motion, but on the
>>>>>>>> other hand, causes more conservative stack reuse. As far I can tell,
>>>>>>>> the handling of temporaries is added independently after the clobber
>>>>>>>> for scoped variables are introduced. This option can be used to
>>>>>>>> restore the older behavior (in handling temps).
>>>>>>>
>>>>>>>
>>>>>>> Well, it does not really restore the old behavior (if you mean before
>>>>>>> adding
>>>>>>> CLOBBERS, not before the single patch that might have used those for
>>>>>>> gimplifying WITH_CLEANUP_EXPR).  You say it disables stack-slot sharing
>>>>>>> for those decls but it also does other things via side-effects of no
>>>>>>> longer
>>>>>>> emitting the CLOBBER.  I say it's better to disable the stack-slot
>>>>>>> sharing.
>>>>>>
>>>>>>
>>>>>> The patch exactly restores the behavior of temporaries from before my change
>>>>>> to add CLOBBERs for temporaries.  The primary effect of that change was to
>>>>>> provide stack-slot sharing, but if there are other effects they are probably
>>>>>> desirable as well, since the broken code depended on the old behavior.
>>>>>
>>>>> So you see it as workaround option, like -fno-strict-aliasing, rather than
>>>>> debugging aid?
>>>>
>>>> It can be used for both purposes -- if the violations are as pervasive
>>>> as strict-aliasing cases (which looks like so).
>>>>
>>>> thanks,
>>>>
>>>> David
>>>>
>>>>>
>>>>> Richard.
>>>>>
>>>>>> Jason
Xinliang David Li July 4, 2012, 3:01 p.m. UTC | #22
Comment?

David

On Mon, Jul 2, 2012 at 4:30 PM, Xinliang David Li <davidxl@google.com> wrote:
> I extended the patch a little so that the option can be used to set
> multiple stack reuse levels: -fstack-reuse=[all|name_vars|none]
>
> all: enable stack reuse for all local vars (named vars and compiler
> generated temporaries) which live in memory;
> name_vars: enable stack reuse only for user declared local vars with names;
> none: disable stack reuse completely.
>
> Note the patch still chooses to suppress clobber statement generation
> instead of just ignoring them in stack layout. This has the additional
> advantage of allowing more aggressive code motion when stack use is
> disabled.
>
> The documentation will be updated when the patch is agreed upon.
>
> thanks,
>
> David
>
>
> On Thu, Jun 28, 2012 at 10:43 PM, Xinliang David Li <davidxl@google.com> wrote:
>> (re-post in plain text)
>>
>> Moving this to cfgexpand time is simple and it can also be extended to
>> handle scoped variables. However Jakub raised a good point about this
>> being too late as stack space overlay is not the only way to cause
>> trouble when the lifetime of a stack object is extended beyond the
>> clobber stmt.
>>
>> thanks,
>>
>> David
>>
>> On Tue, Jun 26, 2012 at 1:28 AM, Richard Guenther
>> <richard.guenther@gmail.com> wrote:
>>> On Mon, Jun 25, 2012 at 6:25 PM, Xinliang David Li <davidxl@google.com> wrote:
>>>> Are there any more concerns about this patch? If not, I'd like to check it in.
>>>
>>> No - the fact that the flag is C++ specific but in common.opt is odd enough
>>> and -ftemp-reuse-stack sounds very very generic - which in fact it is not,
>>> it's a no-op in C.  Is there a more formal phrase for the temporary kind that
>>> is affected?  For me "temp" is synonymous to "auto" so I'd have expected
>>> the switch to turn off stack slot sharing for
>>>
>>>  {
>>>   int a[5];
>>>  }
>>>  {
>>>   int a[5];
>>>  }
>>>
>>> but that is not what it does.  So - a little kludgy but probably more to what
>>> I'd like it to be would be to move the option to c-family/c.opt enabled only
>>> for C++ and Obj-C++ and export it to the middle-end via a new langhook
>>> (the gimplifier code should be in Frontend code that lowers to GENERIC
>>> really and the WITH_CLEANUP_EXPR code should be C++ frontend specific ...).
>>>
>>> Thanks,
>>> Richard.
>>>
>>>> thanks,
>>>>
>>>> David
>>>>
>>>> On Fri, Jun 22, 2012 at 8:51 AM, Xinliang David Li <davidxl@google.com> wrote:
>>>>> On Fri, Jun 22, 2012 at 2:39 AM, Richard Guenther
>>>>> <richard.guenther@gmail.com> wrote:
>>>>>> On Fri, Jun 22, 2012 at 11:29 AM, Jason Merrill <jason@redhat.com> wrote:
>>>>>>> On 06/22/2012 01:30 AM, Richard Guenther wrote:
>>>>>>>>>
>>>>>>>>> What other issues? It enables more potential code motion, but on the
>>>>>>>>> other hand, causes more conservative stack reuse. As far I can tell,
>>>>>>>>> the handling of temporaries is added independently after the clobber
>>>>>>>>> for scoped variables are introduced. This option can be used to
>>>>>>>>> restore the older behavior (in handling temps).
>>>>>>>>
>>>>>>>>
>>>>>>>> Well, it does not really restore the old behavior (if you mean before
>>>>>>>> adding
>>>>>>>> CLOBBERS, not before the single patch that might have used those for
>>>>>>>> gimplifying WITH_CLEANUP_EXPR).  You say it disables stack-slot sharing
>>>>>>>> for those decls but it also does other things via side-effects of no
>>>>>>>> longer
>>>>>>>> emitting the CLOBBER.  I say it's better to disable the stack-slot
>>>>>>>> sharing.
>>>>>>>
>>>>>>>
>>>>>>> The patch exactly restores the behavior of temporaries from before my change
>>>>>>> to add CLOBBERs for temporaries.  The primary effect of that change was to
>>>>>>> provide stack-slot sharing, but if there are other effects they are probably
>>>>>>> desirable as well, since the broken code depended on the old behavior.
>>>>>>
>>>>>> So you see it as workaround option, like -fno-strict-aliasing, rather than
>>>>>> debugging aid?
>>>>>
>>>>> It can be used for both purposes -- if the violations are as pervasive
>>>>> as strict-aliasing cases (which looks like so).
>>>>>
>>>>> thanks,
>>>>>
>>>>> David
>>>>>
>>>>>>
>>>>>> Richard.
>>>>>>
>>>>>>> Jason
Xinliang David Li July 9, 2012, 4:30 p.m. UTC | #23
Ping ..

On Wed, Jul 4, 2012 at 8:01 AM, Xinliang David Li <davidxl@google.com> wrote:
> Comment?
>
> David
>
> On Mon, Jul 2, 2012 at 4:30 PM, Xinliang David Li <davidxl@google.com> wrote:
>> I extended the patch a little so that the option can be used to set
>> multiple stack reuse levels: -fstack-reuse=[all|name_vars|none]
>>
>> all: enable stack reuse for all local vars (named vars and compiler
>> generated temporaries) which live in memory;
>> name_vars: enable stack reuse only for user declared local vars with names;
>> none: disable stack reuse completely.
>>
>> Note the patch still chooses to suppress clobber statement generation
>> instead of just ignoring them in stack layout. This has the additional
>> advantage of allowing more aggressive code motion when stack use is
>> disabled.
>>
>> The documentation will be updated when the patch is agreed upon.
>>
>> thanks,
>>
>> David
>>
>>
>> On Thu, Jun 28, 2012 at 10:43 PM, Xinliang David Li <davidxl@google.com> wrote:
>>> (re-post in plain text)
>>>
>>> Moving this to cfgexpand time is simple and it can also be extended to
>>> handle scoped variables. However Jakub raised a good point about this
>>> being too late as stack space overlay is not the only way to cause
>>> trouble when the lifetime of a stack object is extended beyond the
>>> clobber stmt.
>>>
>>> thanks,
>>>
>>> David
>>>
>>> On Tue, Jun 26, 2012 at 1:28 AM, Richard Guenther
>>> <richard.guenther@gmail.com> wrote:
>>>> On Mon, Jun 25, 2012 at 6:25 PM, Xinliang David Li <davidxl@google.com> wrote:
>>>>> Are there any more concerns about this patch? If not, I'd like to check it in.
>>>>
>>>> No - the fact that the flag is C++ specific but in common.opt is odd enough
>>>> and -ftemp-reuse-stack sounds very very generic - which in fact it is not,
>>>> it's a no-op in C.  Is there a more formal phrase for the temporary kind that
>>>> is affected?  For me "temp" is synonymous to "auto" so I'd have expected
>>>> the switch to turn off stack slot sharing for
>>>>
>>>>  {
>>>>   int a[5];
>>>>  }
>>>>  {
>>>>   int a[5];
>>>>  }
>>>>
>>>> but that is not what it does.  So - a little kludgy but probably more to what
>>>> I'd like it to be would be to move the option to c-family/c.opt enabled only
>>>> for C++ and Obj-C++ and export it to the middle-end via a new langhook
>>>> (the gimplifier code should be in Frontend code that lowers to GENERIC
>>>> really and the WITH_CLEANUP_EXPR code should be C++ frontend specific ...).
>>>>
>>>> Thanks,
>>>> Richard.
>>>>
>>>>> thanks,
>>>>>
>>>>> David
>>>>>
>>>>> On Fri, Jun 22, 2012 at 8:51 AM, Xinliang David Li <davidxl@google.com> wrote:
>>>>>> On Fri, Jun 22, 2012 at 2:39 AM, Richard Guenther
>>>>>> <richard.guenther@gmail.com> wrote:
>>>>>>> On Fri, Jun 22, 2012 at 11:29 AM, Jason Merrill <jason@redhat.com> wrote:
>>>>>>>> On 06/22/2012 01:30 AM, Richard Guenther wrote:
>>>>>>>>>>
>>>>>>>>>> What other issues? It enables more potential code motion, but on the
>>>>>>>>>> other hand, causes more conservative stack reuse. As far I can tell,
>>>>>>>>>> the handling of temporaries is added independently after the clobber
>>>>>>>>>> for scoped variables are introduced. This option can be used to
>>>>>>>>>> restore the older behavior (in handling temps).
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Well, it does not really restore the old behavior (if you mean before
>>>>>>>>> adding
>>>>>>>>> CLOBBERS, not before the single patch that might have used those for
>>>>>>>>> gimplifying WITH_CLEANUP_EXPR).  You say it disables stack-slot sharing
>>>>>>>>> for those decls but it also does other things via side-effects of no
>>>>>>>>> longer
>>>>>>>>> emitting the CLOBBER.  I say it's better to disable the stack-slot
>>>>>>>>> sharing.
>>>>>>>>
>>>>>>>>
>>>>>>>> The patch exactly restores the behavior of temporaries from before my change
>>>>>>>> to add CLOBBERs for temporaries.  The primary effect of that change was to
>>>>>>>> provide stack-slot sharing, but if there are other effects they are probably
>>>>>>>> desirable as well, since the broken code depended on the old behavior.
>>>>>>>
>>>>>>> So you see it as workaround option, like -fno-strict-aliasing, rather than
>>>>>>> debugging aid?
>>>>>>
>>>>>> It can be used for both purposes -- if the violations are as pervasive
>>>>>> as strict-aliasing cases (which looks like so).
>>>>>>
>>>>>> thanks,
>>>>>>
>>>>>> David
>>>>>>
>>>>>>>
>>>>>>> Richard.
>>>>>>>
>>>>>>>> Jason
Jason Merrill July 9, 2012, 10:53 p.m. UTC | #24
This looks fine to me, if nobody has any more objections.

Jason
Olivier Ballereau Dec. 2, 2012, 12:31 p.m. UTC | #25
Hello David,

Sorry to come so late into the discussion, but...

On 21/06/12 00:50, Xinliang David Li wrote:
> One of the most common runtime errors we have seen in gcc-4_7 is
> caused by dangling references to temporaries whole life time have
> ended
> 
> e.g,
> 
>  const A& a = foo();
> 
> or
> foo (A());// where temp's address is saved and used after foo.
> 
> Of course this is user error according to the standard,
> [...]

... is the first of your 2 examples really a user error? If so, it
breaks GotW #88: A Candidate For the “Most Important const” [1]. Can you
please clarify?

Thanks in advance!
Olivier

[1]
http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/
Xinliang David Li Dec. 3, 2012, 1:02 a.m. UTC | #26
My first example is not correct --- according to the standard, the
lifetime of the temporary should be extended. The second example is an
user error.

 C++ standard says this in 12.2.5:

"
The second context is when a reference is bound to a temporary. The
temporary to which the reference is
bound or the temporary that is the complete object of a subobject to
which the reference is bound persists
for the lifetime of the reference except:
— A temporary bound to a reference member in a constructor’s
ctor-initializer (12.6.2) persists until the
constructor exits.
— A temporary bound to a reference parameter in a function call
(5.2.2) persists until the completion of
the full-expression containing the call.
— The lifetime of a temporary bound to the returned value in a
function return statement (6.6.3) is not
extended; the temporary is destroyed at the end of the full-expression
in the return statement.
— A temporary bound to a reference in a new-initializer (5.3.4)
persists until the completion of the
full-expression containing the new-initializer. [Example:
struct S { int mi; const std::pair<int,int>& mp; };
S a { 1, {2,3} };
S* p = new S{ 1, {2,3} }; // Creates dangling reference
— end example ] [ Note: This may introduce a dangling reference, and
implementations are encouraged
to issue a warning in such a case. — end note ]
"

David




On Sun, Dec 2, 2012 at 4:31 AM, Olivier Ballereau
<Olivier.Ballereau@gmx.net> wrote:
> Hello David,
>
> Sorry to come so late into the discussion, but...
>
> On 21/06/12 00:50, Xinliang David Li wrote:
>> One of the most common runtime errors we have seen in gcc-4_7 is
>> caused by dangling references to temporaries whole life time have
>> ended
>>
>> e.g,
>>
>>  const A& a = foo();
>>
>> or
>> foo (A());// where temp's address is saved and used after foo.
>>
>> Of course this is user error according to the standard,
>> [...]
>
> ... is the first of your 2 examples really a user error? If so, it
> breaks GotW #88: A Candidate For the “Most Important const” [1]. Can you
> please clarify?
>
> Thanks in advance!
> Olivier
>
> [1]
> http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/
>
diff mbox

Patch

Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi     (revision 188362)
+++ doc/invoke.texi     (working copy)
@@ -1003,6 +1003,7 @@  See S/390 and zSeries Options.
 -fstack-limit-register=@var{reg}  -fstack-limit-symbol=@var{sym} @gol
 -fno-stack-limit -fsplit-stack @gol
 -fleading-underscore  -ftls-model=@var{model} @gol
+-ftemp-stack-reuse @gol
 -ftrapv  -fwrapv  -fbounds-check @gol
 -fvisibility -fstrict-volatile-bitfields}
 @end table
@@ -19500,6 +19501,10 @@  indices used to access arrays are within
 currently only supported by the Java and Fortran front ends, where
 this option defaults to true and false respectively.

+@item -ftemp-stack-reuse
+@opindex ftemp_stack_reuse
+This option enables stack space reuse for temporaries. The default is on.
+
 @item -ftrapv
 @opindex ftrapv
 This option generates traps for signed overflow on addition, subtraction,
Index: gimplify.c
===================================================================
--- gimplify.c  (revision 188362)
+++ gimplify.c  (working copy)
@@ -5487,7 +5487,8 @@  gimplify_target_expr (tree *expr_p, gimp
       /* Add a clobber for the temporary going out of scope, like
         gimplify_bind_expr.  */
       if (gimplify_ctxp->in_cleanup_point_expr
-         && needs_to_live_in_memory (temp))
+         && needs_to_live_in_memory (temp)
+         && flag_temp_stack_reuse)
        {
          tree clobber = build_constructor (TREE_TYPE (temp), NULL);
          TREE_THIS_VOLATILE (clobber) = true;
Index: common.opt
===================================================================
--- common.opt  (revision 188362)
+++ common.opt  (working copy)
@@ -1322,6 +1322,10 @@  fif-conversion2
 Common Report Var(flag_if_conversion2) Optimization
 Perform conversion of conditional jumps to conditional execution

+ftemp-stack-reuse
+Common Report Var(flag_temp_stack_reuse) Init(1)
+Enable stack reuse for compiler generated temps
+
 ftree-loop-if-convert
 Common Report Var(flag_tree_loop_if_convert) Init(-1) Optimization
 Convert conditional jumps in innermost loops to branchless equivalents