<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Oct 10, 2017, at 2:57 PM, John McCall 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=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class="">On Oct 10, 2017, at 12:12 PM, Hal Finkel via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" class="">cfe-dev@lists.llvm.org</a>> wrote:</div><div class=""><div bgcolor="#FFFFFF" text="#000000" class=""><p class="">[+Richard, Chandler]<br class=""></p><br class=""><div class="moz-cite-prefix">On 10/09/2017 07:00 PM, Hans Wennborg via cfe-dev wrote:<br class=""></div><blockquote cite="mid:CAB8jPhdEO9MZW=BapwP0QQ5wi9Dr5MiVgFi9yUAMJkWay5+-JA@mail.gmail.com" type="cite" class=""><pre wrap="" class="">I am not a language lawyer, but I'll atttempt to answer anyway.

On Mon, Oct 9, 2017 at 2:16 PM, Kreitzer, David L via cfe-dev
<a class="moz-txt-link-rfc2396E" href="mailto:cfe-dev@lists.llvm.org"><cfe-dev@lists.llvm.org></a> wrote:
</pre><blockquote type="cite" class=""><pre wrap="" class="">This llvm patch, <a class="moz-txt-link-freetext" href="https://reviews.llvm.org/D37289">https://reviews.llvm.org/D37289</a>, attempts to do an optimization
that involves speculating loads. The patch itself needs some work regardless,
but we are questioning the legality of the optimization, which is currently
performed by both gcc and icc. The desired transformation looks like this:

    typedef struct S {
      char padding[4088];
      struct S *p1;
      struct S *p2;
    } S;

    struct S* f1(struct S *s, int x)
    {
      S *r;
      if (x)
        r = s->p1;
      else
        r = s->p2;
      return r;
    }

TO

    struct S* f1(struct S *s, int x)
    {
      return (x) ? s->p1 : s->p2;
    }

The fundamental question seems to be whether loading one member of struct S
makes it valid to load other members of the same struct.
</pre></blockquote><pre wrap="" class="">Yes, I believe that's true. If we're dereferencing s on both paths, it
must point to a struct S object, and then loading from any member of
that object should be fine.</pre></blockquote><br class="">I also believe that this is correct.<br class=""><br class="">I think that Chandler summarized some things to be careful about in this regard here:<br class=""> <span class="Apple-converted-space"> </span><a class="moz-txt-link-freetext" href="http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20170807/477944.html">http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20170807/477944.html</a><br class=""><br class="">Of the three points highlighted here, the second clearly might apply:<br class=""><blockquote type="cite" class=""><pre class="" style="white-space: pre-wrap; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">2) Related to #1, there are applications that rely on this memory model,
for example structures where entire regions of the structure live in
protected pages and cannot be correctly accessed.</pre></blockquote><br class="">This, however, is clearly an extension to the standard memory model, and I see no reason to support this by default. Speculatively loading cache lines under contention from other cores might not be a good thing to do for performance reasons, but that's not a correctness issue.<br class=""></div></div></blockquote><div class=""><br class=""></div>I agree that this optimization is legal under the C and C++ specs.</div></div></blockquote><div><br class=""></div>Sorry, I'd meant to add a proviso to this.  It's legal under the C and C++</div><div>specs to the same extent that any load speculation is.</div><div><br class=""></div><div>In general, load speculation is theoretically problematic in C/C++ because</div><div>it is undefined behavior to have a race even if the race is spurious.  For example,</div><div>a program containing a load that races with a store has undefined behavior even</div><div>if the result of the load is never used.  Therefore, strictly speaking, speculating a</div><div>load can introduce a race that didn't otherwise exist, meaning that it can introduce</div><div>undefined behavior to a program, meaning that it's not a legal transformation.  Now,</div><div>AFAIK LLVM doesn't have any multi-threaded analyses that would actually</div><div>miscompile such a speculation, but it can still matter because e.g. TSan emits code</div><div>that dynamically enforces the memory model, and it will dutifully report the race here.</div><div><br class=""></div><div>(Or, to quote from C11 5.1.2.4p28:</div><div><br class=""></div><div>  Transformations that introduce a speculative read of a potentially shared memory</div><div>  location may not preserve the semantics of the program as defined in this standard,</div><div>  since they potentially introduce a data race. However, they are typically valid in the</div><div>  context of an optimizing compiler that targets a specific machine with well-defined</div><div>  semantics for data races. They would be invalid for a hypothetical machine that is</div><div>  not tolerant of races or provides hardware race detection.</div><div><br class=""></div><div>In this sense, TSan makes an arbitrary machine race-intolerant.)</div><div><br class="">One obvious-seeming idea that I haven't fully thought through is to simply give</div><div>speculated loads weaker semantics in LLVM, so that it's not undefined behavior</div><div>for a speculated load to be part of a race unless the result of the load is actually</div><div>used.  Of course, you'd have to define what "used" means.</div><div><br class=""></div><div>John.</div><div><br class=""></div><div><br class=""><blockquote type="cite" class=""><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">John.</div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br class=""><blockquote type="cite" class=""><div class=""><div bgcolor="#FFFFFF" text="#000000" class=""><br class=""> -Hal<br class=""><br class=""><blockquote cite="mid:CAB8jPhdEO9MZW=BapwP0QQ5wi9Dr5MiVgFi9yUAMJkWay5+-JA@mail.gmail.com" type="cite" class=""><pre wrap="" class=""></pre><blockquote type="cite" class=""><pre wrap="" class="">Both gcc & icc
seem to think so and make a distinction between this case and a similar case
where one field is accessed through an lvalue of a different type:

    typedef struct T {
      char padding[4088];
      struct S *p1;
    } T;

    struct S* f2(struct S *s, int x)
    {
      S *r;
      if (x)
        r = ((T*)s)->p1;
      else
        r = s->p2;
      return r;
    }

Neither compiler will transform this case.
</pre></blockquote><pre wrap="" class="">I suspect it would be within the compiler's rights, but my language
knowledge is too weak. Does the cast imply that s points to a valid
struct S object (or null, but then we couldn't dereference it)? I'm
curious to find out :-)

 - Hans
_______________________________________________
cfe-dev mailing list
<a class="moz-txt-link-abbreviated" href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a>
<a class="moz-txt-link-freetext" href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a>
</pre></blockquote><br class=""><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=""><a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br class=""></div></blockquote></div><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">_______________________________________________</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">cfe-dev mailing list</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="mailto:cfe-dev@lists.llvm.org" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">cfe-dev@lists.llvm.org</a><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a></div></blockquote></div><br class=""></body></html>