<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Thanks for kicking off this discussion and for all the interesting responses.<div class=""><br class=""></div><div class="">Marking indirect parameters as noalias enables more aggressive memory optimization with respect to the indirect arguments on certain targets. On ARM64 this leads to 1%-2% in code size reductions in some cases.</div><div class=""><br class=""></div><div class="">While we work towards adjusting the C++ standard, I would like to provide a way for users to opt-in to the new behavior (e.g. for code-bases that exclusively use C or guarantee that no addresses can escape before the argument is passed): <a href="https://reviews.llvm.org/D85473" class="">https://reviews.llvm.org/D85473</a></div><div class=""><br class=""></div><div class="">What do you think?</div><div class=""><br class=""></div><div class="">Cheers,</div><div class="">Florian<br class=""><div class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Aug 4, 2020, at 04:28, Hal Finkel via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" class="">cfe-dev@lists.llvm.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class="">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" class="">
  
  <div class=""><p class=""><br class="">
    </p>
    <div class="moz-cite-prefix">On 8/3/20 8:45 PM, John McCall wrote:<br class="">
    </div>
    <blockquote type="cite" cite="mid:833CCC19-6042-4889-B081-28EBD258FBB2@apple.com" class="">
      
      <div style="font-family:sans-serif" class="">
        <div style="white-space:normal" class=""><p dir="auto" class="">On 31 Jul 2020, at 19:50, Hal Finkel wrote:</p>
        </div>
        <div style="white-space:normal" class="">
          <blockquote style="border-left:2px solid #777; color:#777;
            margin:0 0 5px; padding-left:5px" class=""><p dir="auto" class="">On 7/31/20 5:59 PM, James Y Knight wrote:</p>
            <blockquote style="border-left:2px solid #777; color:#999;
              margin:0 0 5px; padding-left:5px; border-left-color:#999" class=""><p dir="auto" class="">This discussion reminds me of an example I
                ran into a couple weeks ago, where the execution of the
                program is dependent precisely upon whether the ABI
                calls for the object to be passed indirectly, or in a
                register<br class="">
                <br class="">
                In the case where NVRO is triggered, the class member
                foo_ is fully-constructed on the first line of CreateFoo
                (despite appearing as if that's only constructing a
                local variable). In the case where the struct is small
                enough to fit in a register, NVRO does not apply, and in
                that case, foo_ isn't constructed until after CreateFoo
                returns.<br class="">
                <br class="">
                Therefore, I believe it's implementation-defined whether
                the following program has undefined behavior.<br class="">
                <br class="">
                <a href="https://godbolt.org/z/YT9zsz" style="color:#999" moz-do-not-send="true" class="">https://godbolt.org/z/YT9zsz</a>
                <<a href="https://godbolt.org/z/YT9zsz" style="color:#999" moz-do-not-send="true" class="">https://godbolt.org/z/YT9zsz</a>><br class="">
                <br class="">
                #include <assert.h><br class="">
                <br class="">
                struct Foo {<br class="">
                    int x;<br class="">
                *    // assert fails if you comment out these unused
                fields!<br class="">
                *    int dummy[4];<br class="">
                };<br class="">
                <br class="">
                struct Bar {<br class="">
                    Bar() : foo_(CreateFoo()) {}<br class="">
                <br class="">
                    Foo CreateFoo() {<br class="">
                        Foo f;<br class="">
                        f.x = 55;<br class="">
                        assert(foo_.x == 55);<br class="">
                        return f;<br class="">
                    }<br class="">
                    Foo foo_;<br class="">
                };<br class="">
                <br class="">
                int main() {<br class="">
                    Bar b;<br class="">
                }</p>
            </blockquote><p dir="auto" class="">Looks that way to me too. The example in
              11.10.5p2 sort of makes this point as well (by pointing
              out that you can directly initialize a global this way).</p>
          </blockquote>
        </div>
        <div style="white-space:normal" class=""><p dir="auto" class="">It does seem hard to argue that this is invalid
            under the specification. To me it seems like it clearly <em class="">ought</em>
            to be invalid, though. Note that Clang has always emitted
            return address arguments as <code style="background-color:#F7F7F7; border-radius:3px;
              margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">noalias</code>,
            so this has immediate significance.</p><p dir="auto" class="">If I were writing the specification, I would
            rewrite the restriction in <code style="background-color:#F7F7F7; border-radius:3px;
              margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">[class.cdtor]p2</code>
            to say that pointers derived by naming a
            returned/constructed object do not formally point to the
            object until the function actually returns, even if the copy
            is elided. That would make James’s example undefined
            behavior.</p><p dir="auto" class="">John.</p>
        </div>
      </div>
    </blockquote><p class=""><br class="">
    </p><p class="">I agree. It seems like we should be able to make a sanitizer
      detect this kind of mistake as well (although the general case
      will require some msan-like propagation scheme).<br class="">
    </p><p class=""> -Hal<br class="">
    </p><p class=""><br class="">
    </p>
    <blockquote type="cite" cite="mid:833CCC19-6042-4889-B081-28EBD258FBB2@apple.com" class="">
      <div style="font-family:sans-serif" class="">
        <div style="white-space:normal" class="">
        </div>
        <div style="white-space:normal" class="">
          <blockquote style="border-left:2px solid #777; color:#777;
            margin:0 0 5px; padding-left:5px" class=""><p dir="auto" class=""> -Hal<br class="">
              <br class="">
            </p>
            <blockquote style="border-left:2px solid #777; color:#999;
              margin:0 0 5px; padding-left:5px; border-left-color:#999" class=""><p dir="auto" class="">On Fri, Jul 31, 2020 at 2:27 PM Hal Finkel
                via cfe-dev <<a class="moz-txt-link-abbreviated" href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a> <<a href="mailto:cfe-dev@lists.llvm.org" style="color:#999" moz-do-not-send="true" class="">mailto:cfe-dev@lists.llvm.org</a>>>
                wrote:<br class="">
                <br class="">
                <br class="">
                On 7/31/20 1:24 PM, Hal Finkel wrote:</p>
              <blockquote style="border-left:2px solid #777; color:#BBB;
                margin:0 0 5px; padding-left:5px;
                border-left-color:#BBB" class=""><p dir="auto" class=""> On 7/31/20 12:43 PM, John McCall wrote:</p>
                <blockquote style="border-left:2px solid #777;
                  color:#BBB; margin:0 0 5px; padding-left:5px;
                  border-left-color:#BBB" class=""><p dir="auto" class=""> n 31 Jul 2020, at 7:35, Hal Finkel
                    wrote:<br class="">
                    <br class="">
                    On 7/29/20 9:00 PM, John McCall via cfe-dev wrote:<br class="">
                    <br class="">
                    On 29 Jul 2020, at 17:42, Richard Smith wrote:<br class="">
                    <br class="">
                    On Wed, 29 Jul 2020 at 12:52, John McCall<br class="">
                    <a class="moz-txt-link-rfc2396E" href="mailto:rjmccall@apple.com"><rjmccall@apple.com></a> <<a href="mailto:rjmccall@apple.com" style="color:#BBB" moz-do-not-send="true" class="">mailto:rjmccall@apple.com</a>>
                    wrote:<br class="">
                    <br class="">
                    ...<br class="">
                    <br class="">
                    I think concretely, the escape hatch doesn't stop
                    things<br class="">
                    from<br class="">
                    going wrong,<br class="">
                    because -- as you note -- even though we *could*
                    have<br class="">
                    made a copy,<br class="">
                    it's<br class="">
                    observable whether or not we *did* make a copy. For
                    example:<br class="">
                    <br class="">
                    I would say that it’s observable whether the
                    parameter<br class="">
                    variable has<br class="">
                    the same address as the argument. That doesn’t
                    /have/ to<br class="">
                    be the same<br class="">
                    question as whether a copy was performed: we could<br class="">
                    consider there to be<br class="">
                    a formal copy (or series of copies) that ultimately<br class="">
                    creates /an/ object<br class="">
                    at the same address, but it’s not the /same/ object
                    and<br class="">
                    so pointers<br class="">
                    to the old object no longer validly pointer to it.
                    But I<br class="">
                    guess that<br class="">
                    would probably violate the lifetime rules, because
                    it<br class="">
                    would make accesses<br class="">
                    through old pointers UB when in fact they should at<br class="">
                    worst access a valid<br class="">
                    object that’s just unrelated to the parameter
                    object.<br class="">
                    <br class="">
                    I think that it would be great to be able to do
                    this, but<br class="">
                    unfortunately, I think that the point that you raise
                    here is<br class="">
                    a key issue. Whether or not the copy is performed is
                    visible<br class="">
                    in the model, and so we can't simply act as though
                    there was<br class="">
                    a copy when optimizing. Someone could easily have
                    code that<br class="">
                    looks like:<br class="">
                    <br class="">
                    Foo DefaultX;<br class="">
                    <br class="">
                    ...<br class="">
                    <br class="">
                    void something(Foo &A, Foo &B) {<br class="">
                    <br class="">
                      if (&A == &B) { ... }<br class="">
                    <br class="">
                    }<br class="">
                    <br class="">
                    void bar(Foo X) { something(X, DefaultX); }<br class="">
                    <br class="">
                    This example isn’t really on point; a call like
                    |bar(DefaultX)|<br class="">
                    obviously cannot just pass the address of |DefaultX|
                    as a<br class="">
                    by-value argument without first proving a lot of
                    stuff about how<br class="">
                    |foo| uses both its parameter and |DefaultX|. I
                    think |noalias|<br class="">
                    is actually a subset of what would have to be proven
                    there.<br class="">
                  </p>
                </blockquote><p dir="auto" class=""> Yes, I apologize. You're right: my
                  pseudo-code missed the point.<br class="">
                  So the record is clear, let me rephrase:<br class="">
                  <br class="">
                  Foo *DefaultX = nullptr;<br class="">
                  ...<br class="">
                  Foo::Foo() { if (!DefaultX) DefaultX = this; }<br class="">
                  ...<br class="">
                  void bar(Foo X) { something(X, *DefaultX); }<br class="">
                  ...<br class="">
                  bar(Foo{});<br class="">
                  <br class="">
                  I think that's closer to what we're talking about.<br class="">
                  <br class="">
                </p>
                <blockquote style="border-left:2px solid #777;
                  color:#BBB; margin:0 0 5px; padding-left:5px;
                  border-left-color:#BBB" class=""><p dir="auto" class=""> In general, the standard is clear that
                    you cannot rely on<br class="">
                    escaping a pointer to/into a trivially-copyable
                    pr-value<br class="">
                    argument prior to the call and then rely on that
                    pointer<br class="">
                    pointing into the corresponding parameter object.<br class="">
                    Implementations are /allowed/ to introduce copies.
                    But it does<br class="">
                    seem like the current wording would allow you to
                    rely on that<br class="">
                    pointer pointing into /some/ valid object, at least
                    until the<br class="">
                    end of the caller’s full-expression. That means
                    that, if we<br class="">
                    don’t guarantee to do an actual copy of the
                    argument, we cannot<br class="">
                    make it UB to access the parameter variable through
                    pointers to<br class="">
                    the argument temporary, which is what marking the
                    parameter as<br class="">
                    |noalias| would do.<br class="">
                    <br class="">
                    So I guess the remaining questions are:<br class="">
                    <br class="">
                    * Is this something we can reasonably change in the
                    standard?<br class="">
                  </p>
                </blockquote><p dir="auto" class=""> This is the part that I'm unclear about.
                  What change would we make?<br class="">
                  <br class="">
                </p>
              </blockquote><p dir="auto" class=""> Also, maybe some extended use of the
                no_unique_address attribute<br class="">
                would help?<br class="">
                <br class="">
                 -Hal<br class="">
                <br class="">
              </p>
              <blockquote style="border-left:2px solid #777; color:#BBB;
                margin:0 0 5px; padding-left:5px;
                border-left-color:#BBB" class="">
                <blockquote style="border-left:2px solid #777;
                  color:#BBB; margin:0 0 5px; padding-left:5px;
                  border-left-color:#BBB" class=""><p dir="auto" class=""> * Are we comfortable setting |noalias|
                    in C if the only place<br class="">
                    that would break is with a C++ caller?<br class="">
                  </p>
                </blockquote><p dir="auto" class=""> Out of curiosity, if you take C in
                  combination with our<br class="">
                  statement-expression extension implementation<br class="">
                  (<a href="https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html" style="color:#BBB" moz-do-not-send="true" class="">https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html</a><br class="">
                  <<a href="https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html" style="color:#BBB" moz-do-not-send="true" class="">https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html</a>>),
                  and<br class="">
                  notwithstanding the statement in the GCC manual about
                  returns by<br class="">
                  value (i.e., the part just before where it says,
                  "Therefore the<br class="">
                  this pointer observed by Foo is not the address of
                  a."), is there<br class="">
                  any relationship to this topic?<br class="">
                  <br class="">
                  Thanks again,<br class="">
                  <br class="">
                  Hal<br class="">
                  <br class="">
                </p>
                <blockquote style="border-left:2px solid #777;
                  color:#BBB; margin:0 0 5px; padding-left:5px;
                  border-left-color:#BBB" class=""><p dir="auto" class=""> John.<br class="">
                    <br class="">
                    As Richard's example shows, the code doesn't need to<br class="">
                    explicitly compare the addresses to detect the copy
                    either.<br class="">
                    Any code that reads/writes to the objects can do it.
                    A<br class="">
                    perhaps-more-realistic example might be:<br class="">
                    <br class="">
                      int Cnt = A.RefCnt; ++A.RefCnt; ++B.RefCnt; if
                    (Cnt + 1 !=<br class="">
                    A.RefCnt) { /* same object case */ }<br class="">
                    <br class="">
                    The best suggestion that I have so far is that we
                    could add<br class="">
                    an attribute like 'can_copy' indicating that the
                    optimizer<br class="">
                    can make a formal copy of the argument in the callee
                    and use<br class="">
                    that instead of the original pointer if that seems
                    useful. I<br class="">
                    can certainly imagine a transformation such as LICM
                    making<br class="">
                    use of such a thing (although the cost modeling
                    would<br class="">
                    probably need to be fairly conservative).<br class="">
                    <br class="">
                     -Hal<br class="">
                    <br class="">
                    ...<br class="">
                    <br class="">
                    John.<br class="">
                    <br class="">
                    <br class="">
                    _______________________________________________<br class="">
                    cfe-dev mailing list<br class="">
                    <a class="moz-txt-link-abbreviated" href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a> <<a href="mailto:cfe-dev@lists.llvm.org" style="color:#BBB" moz-do-not-send="true" class="">mailto:cfe-dev@lists.llvm.org</a>><br class="">
                    <a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" style="color:#BBB" moz-do-not-send="true" class="">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br class="">
                    <<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" style="color:#BBB" moz-do-not-send="true" class="">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a>><br class="">
                    <br class="">
                    -- <br class="">
                    Hal Finkel<br class="">
                    Lead, Compiler Technology and Programming Languages<br class="">
                    Leadership Computing Facility<br class="">
                    Argonne National Laboratory<br class="">
                  </p>
                </blockquote><p dir="auto" class=""> -- <br class="">
                  Hal Finkel<br class="">
                  Lead, Compiler Technology and Programming Languages<br class="">
                  Leadership Computing Facility<br class="">
                  Argonne National Laboratory</p>
              </blockquote><p dir="auto" class=""> -- <br class="">
                Hal Finkel<br class="">
                Lead, Compiler Technology and Programming Languages<br class="">
                Leadership Computing Facility<br class="">
                Argonne National Laboratory<br class="">
                <br class="">
                _______________________________________________<br class="">
                cfe-dev mailing list<br class="">
                <a class="moz-txt-link-abbreviated" href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a> <<a href="mailto:cfe-dev@lists.llvm.org" style="color:#999" moz-do-not-send="true" class="">mailto:cfe-dev@lists.llvm.org</a>><br class="">
                <a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" style="color:#999" moz-do-not-send="true" class="">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br class="">
                <<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" style="color:#999" moz-do-not-send="true" class="">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a>><br class="">
              </p>
            </blockquote><p dir="auto" class="">-- <br class="">
              Hal Finkel<br class="">
              Lead, Compiler Technology and Programming Languages<br class="">
              Leadership Computing Facility<br class="">
              Argonne National Laboratory</p>
          </blockquote>
        </div>
        <div style="white-space:normal" class="">
        </div>
      </div>
    </blockquote>
    <pre class="moz-signature" cols="72">-- 
Hal Finkel
Lead, Compiler Technology and Programming Languages
Leadership Computing Facility
Argonne National Laboratory</pre>
  </div>

_______________________________________________<br class="">cfe-dev mailing list<br class=""><a href="mailto:cfe-dev@lists.llvm.org" class="">cfe-dev@lists.llvm.org</a><br class="">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev<br class=""></div></blockquote></div><br class=""></div></div></body></html>