public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Richard Sandiford <richard.sandiford@arm.com>
To: Michael Matz <matz@suse.de>
Cc: Qing Zhao <qing.zhao@oracle.com>,
	gcc-patches Qing Zhao via <gcc-patches@gcc.gnu.org>,
	kees cook <keescook@chromium.org>
Subject: Re: HELP!! How to inhibit optimizations applied to .DEFERRED_INIT argument?
Date: Thu, 01 Jul 2021 16:35:38 +0100	[thread overview]
Message-ID: <mpto8bmvygl.fsf@arm.com> (raw)
In-Reply-To: <alpine.LSU.2.20.2107011419030.25557@wotan.suse.de> (Michael Matz's message of "Thu, 1 Jul 2021 14:40:11 +0000 (UTC)")

Michael Matz <matz@suse.de> writes:
> Hello,
>
> I haven't followed this thread too closely, in particular I haven't seen 
> why the current form of the .DEFERRED_INIT call was chosen or suggested, 
> but it triggered my "well, that's obviously wrong" gut feeling; so sorry 
> for stating something which might be obvious to thread participants here.  

Well, it does feel like this is pressing the reset button on a thread
whose message count is already in the high double figures.  There's a
risk that restarting the discussion now is going to repeat a lot of the
same ground, probably at similar length.  (But I realise that the sheer
length of the thread is probably also the main reason for not having
followed it closely. :-))

To recap, the purpose of the option is to do two things simultaneously:

(1) make the object code behave “as if” automatic variables were
    initialised with a fill pattern, before any explicit initialisation

(2) continue to treat uses of uninitialised automatic variables as
    (semantically) undefined behaviour

When this was discussed on the clang list, (2) was a key requirement
and was instrumental in getting the feature accepted.  The option is
specificially *not* trying to change language semantics or create
a fork in the language.

The option is both a security and a debugging feature.  As a security
feature, it would be legitimate to optimise:

   int foo;
   if (flag)
     foo = 1;
   x = foo;

into:

   x = 1;

since the behaviour is at least deterministic.  But from a debugging QoI
perspective, this should not happen.  We should generate the same code
as for:

   int foo = <fill-pattern>;
   if (flag)
     foo = 1;
   x = foo;

However, because of (2), we should still generate a -Wmaybe-uninitialized
warning for the “x = foo” assignment.

This is not a combination we support at the moment, so something needs
to give.  The question of course is what.

> Anyway:
>
> On Thu, 1 Jul 2021, Richard Sandiford via Gcc-patches wrote:
>
>> >> It's not a bug in SSA, it's at most a missed optimization there.
>> >
>> > I still think that SSA cannot handle block-scoped variable correctly 
>> > in this case, it should not move the variable out side of the block 
>> > scope. -:)
>> >
>> >>  But with -ftrivial-auto-var-init it becomes a correctness issue.
>> 
>> I might have lost track of what “it” is here.  Do you mean the 
>> progation, or the fact that we have a PHI in the first place?
>> 
>> For:
>> 
>> unsigned int
>> f (int n)
>> {
>>   unsigned int res = 0;
>>   for (int i = 0; i < n; i += 1)
>>     {
>>       unsigned int foo;
>>       foo += 1;
>
> Note that here foo is used uninitialized.  That is the thing from which 
> everything else follows.

Right, that was the point.

> Garbage in, garbage out.  It makes not too much sense to argue that
> the generated PHI node on this loop (generated because of the
> exposed-upward use of foo) is wrong, or right, or should better be
> something else.  The input program was broken, so anything makes sense.

Yeah, without the new option it's GIGO.  But I think it's still possible
to rank different forms of garbage output in terms of how self-consistent
they are.

IMO it makes no sense to say that “foo” is upwards-exposed to somewhere
where “foo” doesn't exist.  Using “foo_N(D)” doesn't have that problem,
so I think it's possible to say that it's “better” garbage output. :-)

And the point is that with the new option, this is no longer garbage
input as far as SSA is concerned: carrying the old value of “foo”
across iterations would not be implementing the option correctly.
How SSA handles this becomes a correctness issue.

> That is the same with Qings shorter testcase:
>
>   6   for (i = 0; i < a; i++) {
>   7     if (__extension__({int size2;
>   8         size2 = ART_INIT (size2, 2);
>
> Uninitialized use of size2 right there.  And it's the same for the use of 
> .DEFERRED_INIT as the patch does:
>
> {
>   int size2;
>   size2 = .DEFERRED_INIT (size2, 2);
>   size2 = 4;
>   _1 = size2 > 5;
>   D.2240 = (int) _1;
> }
>
> Argument of the pseudo-function-call to .DEFERRED_INIT uninitialized -> 
> boom.
>
> You can't solve any of this by fiddling with how SSA rewriting behaves at 
> a large scale.  You need to change this and only this specific 
> interpretation of a use.  Or preferrably not generate it to start with.
>
>> IMO the foo_3 PHI makes no sense.  foo doesn't live beyond its block,
>> so there should be no loop-carried dependency here.
>> 
>> So yeah, if “it” meant that the fact that variables live too long,
>> then I agree that becomes a correctness issue with this feature,
>> rather than just an odd quirk.  Could we solve it by inserting
>> a clobber at the end of the variable's scope, or something like that?
>
> It would possibly make GCC not generate a PHI on this broken input, yes.  
> But why would that be an improvement?

Hopefully the above answers this.

>> > Agreed, I have made such change yesterday, and this work around the 
>> > current issue.
>> >
>> > temp = .DEFERRED_INIT (temp/WITH_SIZE_EXPR(temp), init_type)
>> >
>> > To:
>> >
>> > temp = .DEFERRED_INIT (SIZE_of_temp, init_type)
>> 
>> I think we're going round in circles here though.  The point of having
>> the undefined input was so that we would continue to warn about undefined
>> inputs.  The above issue doesn't seem like a good justification for
>> dropping that.
>
> If you want to rely on the undefined use for error reporting then you must 
> only generate an undefined use when there was one before, you can't just 
> insert new undefined uses.  I don't see how it could be otherwise, as soon 
> as you introduce new undefined uses you can and will run into GCC making 
> use of the undefinedness, not just this particular issue with lifetime and 
> PHI nodes which might be "solved" by clobbers.
>
> I think it's a chicken egg problem: you can't add undefined uses, for 
> which you need to know if there was one, but the facility is supposed to 
> help detecting if there is one to start with.

The idea is that .DEFERRED_INIT would naturally get optimised away by
DCE/DSE if the variable is provably initialised before it's used.

Thanks,
Richard

  reply	other threads:[~2021-07-01 15:35 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-30  0:14 Qing Zhao
2021-06-30  7:46 ` Richard Biener
2021-06-30 14:04   ` Qing Zhao
2021-06-30 14:39     ` Richard Biener
2021-06-30 15:11       ` Qing Zhao
2021-06-30 15:43       ` Qing Zhao
2021-06-30 17:20         ` Andrew Pinski
2021-06-30 17:36           ` Richard Biener
2021-06-30 18:07             ` Qing Zhao
2021-06-30 18:59               ` Richard Biener
2021-06-30 19:10                 ` Qing Zhao
2021-06-30 19:14                 ` Qing Zhao
2021-06-30 19:20                   ` Andrew Pinski
2021-06-30 19:54                     ` Qing Zhao
2021-07-01  6:48                   ` Richard Biener
2021-07-01 13:45                     ` Qing Zhao
2021-07-01 14:04                       ` Richard Biener
2021-07-01 15:27                         ` Qing Zhao
2021-07-01 14:09                       ` Richard Sandiford
2021-07-01 14:40                         ` Michael Matz
2021-07-01 15:35                           ` Richard Sandiford [this message]
2021-07-01 16:06                             ` Michael Matz
2021-07-01 16:23                               ` Richard Sandiford
2021-07-01 16:35                                 ` Qing Zhao
2021-07-01 15:42                           ` Qing Zhao
2021-07-01 18:14                           ` Richard Biener
2021-07-01 15:32                         ` Qing Zhao
2021-06-30 19:04               ` Qing Zhao
2021-06-30 17:45           ` Qing Zhao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=mpto8bmvygl.fsf@arm.com \
    --to=richard.sandiford@arm.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=keescook@chromium.org \
    --cc=matz@suse.de \
    --cc=qing.zhao@oracle.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).