C++ Logo

std-proposals

Advanced search

Re: [std-proposals] P2815 breaks all provenance-related optimizations

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Wed, 22 Feb 2023 07:57:06 -0500
On Tue, Feb 21, 2023 at 9:53 PM connor horman via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> I just learned of P2815, and I do not know of another place I can respond
> to it, so I'm going to answer here.
>

The presentation's title slide (and unfortunately nowhere else — I missed
it the first time too!) refers to P2188:
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2188r1.html
which, being a WG21 paper, contains contact info for the author. I've
cc'ed him here.

Anthony: In the mailing-list archive, this thread begins at
https://lists.isocpp.org/std-proposals/2023/02/5848.php .

In my opinion, the proposal in question eliminates all provenance based
> alias analysis, used to eliminate memory accesses when unanalyzed code is
> present.
>
> Consider the following example code:
>
> int foo(int* p){
> int i;
> opaque_operation(&i,p);
> i = 0;
> *p = 1;
> return i;
> }
>
> (Where the optimizer is unable to analyze `opaque_operation`
> In current compilers, this can be optimized to [...
>

int foo(int *p) {
    int i; opaque_operation(&i, p);
    *p = 1; return 0;
}

...]. Under the proposal, however, `opaque_operation` could observe that
> `&i` and `p` have the same *value representation*, which means that they
> must be equal (it may do so with defined behaviour in all executions, for
> example, by terminating if they are bytewise unequal). Thus the write to
> `p` may modify the value of `i`. This would make the transformation [...]
> invalid under the proposal.
>

I see your point. It would be like: You go to a magic show. The magician
gives one deck of cards to an audience member, who randomly selects a card
and signs its face. He gives a second deck of cards to a second audience
member, who randomly selects another card and signs its face. The magician
takes both cards behind a partition, then re-emerges and triumphantly shows
the audience that both audience members have somehow chosen the same card!
"I know how that trick is done," you whisper. "Whenever the two audience
members choose different cards, the magician goes behind the partition and
kills himself."

As in magic, C++ has some common-sense rules about what counts as a
reasonable explanation for a trick and what doesn't.
For example, all three major compilers will optimize
    int bar(int k) {
        while (k) { }
        return 42;
    }
to
    int bar(int k) {
        return 42;
    }
because C++ considers the explanation "Whenever k==0, the bottom of the
loop is never reached" to be unreasonable.
Now, personally, I actually disagree with C++'s criterion there — I think
"sometimes the loop is infinite" seems like a pretty reasonable
"explanation of the trick" as far as I'm concerned. But the example does
show that C++ *already has mechanisms* by which it can say "Such-and-such
an explanation of the trick is unreasonable; we don't have to entertain the
possibility that it could ever really happen that way."

So I don't think you're correct to worry that P2188 / P2815 would
completely destroy *all* provenance-based optimizations. It needs to
propose some wording before we can say anything concrete about it, of
course. And it might end up destroying some optimizations. But it needn't
destroy all of them. And at first glance it doesn't seem out-of-keeping
with the direction of C++.
(Likewise, the existence of `reinterpret_cast` doesn't destroy all
type-based alias analysis. And `const_cast` famously destroys some-
*but-not-all* const-based optimizations.)

–Arthur

Received on 2023-02-22 12:57:19