<html><head></head><body bgcolor="#FFFFFF"><div><span class="Apple-style-span" style="-webkit-tap-highlight-color: rgba(26, 26, 26, 0.296875); -webkit-composition-fill-color: rgba(175, 192, 227, 0.230469); -webkit-composition-frame-color: rgba(77, 128, 180, 0.230469); ">On Dec 16, 2011, at 3:29 PM, John Criswell <<a href="mailto:criswell@illinois.edu">criswell@illinois.edu</a>> wrote:</span></div><div></div><blockquote type="cite"><div>
  
    <meta content="text/html; charset=ISO-8859-1" http-equiv="Content-Type">
  
  
    On 12/16/11 4:45 PM, Chris Lattner wrote:
    <blockquote cite="mid:ECA41BF4-D1D5-446A-BD6D-87ED2CEC5D73@apple.com" type="cite">
      <meta http-equiv="Content-Type" content="text/html;
        charset=ISO-8859-1">
      <br>
      <div>
        <div>On Dec 16, 2011, at 2:41 PM, John Criswell wrote:</div>
        <br class="Apple-interchange-newline">
        <blockquote type="cite">
          <div bgcolor="#FFFFFF" text="#000000"> On 12/16/11 4:14 PM,
            Chris Lattner wrote:
            <blockquote cite="mid:19D8F13C-C5A8-44D3-861A-2CFF72BC2D94@apple.com" type="cite">
              <div>
                <div>On Dec 16, 2011, at 12:39 PM, Kostya Serebryany
                  wrote:</div>
                <blockquote type="cite">
                  <div class="gmail_quote">
                    <blockquote class="gmail_quote" style="margin-top:
                      0px; margin-right: 0px; margin-bottom: 0px;
                      margin-left: 0.8ex; border-left-width: 1px;
                      border-left-color: rgb(204, 204, 204);
                      border-left-style: solid; padding-left: 1ex;
                      position: static; z-index: auto; ">
                      <div class="HOEnZb">
                        <div class="h5">> Do we consider the above
                          transformation legal?<br>
                        </div>
                      </div>
                    </blockquote>
                  </div>
                </blockquote>
                <div><br>
                </div>
                <div>Yes, the transformation is perfectly legal for the
                  normal compiler.</div>
              </div>
            </blockquote>
            <br>
            So how do you guarantee that the behavior is predictable
            regardless of hardware platform if you don't define what the
            behavior should be?<br>
          </div>
        </blockquote>
        <div><br>
        </div>
        <div>I'm not sure what you mean.  What isn't defined?</div>
      </div>
    </blockquote>
    <br>
    The alloca in question allocates 22 bytes.  The 64-bit load in
    Kostya's original email is accessing two additional bytes past the
    end of the alloca (i.e., it is accessing array "elements" a[22] and
    a[23]).  Accessing that memory with a read or write is undefined
    behavior.  The program could fault, read zeros, read arbitrary bit
    patterns, etc.<br></div></blockquote><div><br></div><div>John, I think that you are missing that these operations are fully defined by LLVM IR.  I'm not sure what languages rules you are drawing these rules from, but they are not the rules of IR.</div><div><br></div><div>Doing this inside a compiler (the way we do) also is not invalid according to the C notions of undefined behavior, as it has the "as if" rule.  I agree that doing this at the source level would be invalid.</div><div><br></div><div>Again, I'm not opposed to having a way to disable these transformations, we just need a clean way to express it.</div><div><br></div><div>-Chris</div><br><blockquote type="cite"><div>
    In other words, the compiler is transforming this:<br>
    <br>
    return a[16] + a[21];<br>
    <br>
    into something like this:<br>
    <br>
    unsigned long * p = &(a[16]);<br>
    unsigned long v = *p; // This accesses memory locations a[22] and
    a[23]; doing so is undefined behavior<br>
    (do some bit fiddling to extra a[16] and a[17] from v)<br>
    <br>
    The original code is memory safe and exhibits defined behavior.  You
    can do whatever crazy, semantics-preserving optimization you want,
    run it on any crazy architecture you want, and it'll always exhibit
    the same behavior.<br>
    <br>
    The optimized code exhibits undefined behavior. On most systems, it
    just reads garbage data that is ignored by the compiler, but that's
    really just a side-effect of how most OS's and architectures do
    things.  If you do some crazy transforms or run on some obscure
    architecture, the optimized code may break.<br>
    <br>
    <blockquote cite="mid:ECA41BF4-D1D5-446A-BD6D-87ED2CEC5D73@apple.com" type="cite">
      <div><br>
        [snip]<br>
        <blockquote type="cite">
          <div bgcolor="#FFFFFF" text="#000000">What if you have a funky
            architecture that someone is porting LLVM to, or someone is
            using x86-32 segments in an interesting way?<br>
          </div>
        </blockquote>
        <div><br>
        </div>
        <div>We'll burn that bridge when we get to it ;-)</div>
      </div>
    </blockquote>
    <br>
    ASAN got burnt; SAFECode probably got burnt, too.  If we work around
    it, some poor researcher or developer may get burnt by it, too, and
    spend some time figuring out why his correct-looking program is not
    acting properly.  In other words, you're burning someone else's
    bridge.<br>
    <br>
    Granted, perhaps the benefits of an incorrect optimization may
    outweigh the loss of using LLVM on novel systems, but are you sure
    that making the optimization work properly is going to be so
    detrimental?<br>
    <br>
    <blockquote cite="mid:ECA41BF4-D1D5-446A-BD6D-87ED2CEC5D73@apple.com" type="cite">
      <div><br>
        <blockquote type="cite">
          <div bgcolor="#FFFFFF" text="#000000">Moreover, I don't really
            understand the rationale for allowing a transform to
            introduce undefined behavior into programs that exhibit no
            undefined behavior.</div>
        </blockquote>
        <div><br>
        </div>
        <div>There is no undefined behavior here.  This is exactly
          analogous to the code you get for bitfield accesses.  If you
          have an uninitialized struct and start storing into its fields
          (to initialize it)  you get a series of "load + mask + or +
          store" operations.  These are loading and touching "undefined"
          bits in a completely defined way.</div>
      </div>
    </blockquote>
    <br>
    I'll agree that they're both undefined behavior, but I don't think
    they fall within the same category.  The bit-mask initializing issue
    is a compromise you made because there either isn't an alternative
    way to do it that has defined behavior, or such an alternative is
    too expensive and difficult to implement and/or use.<br>
    <br>
    This appears to be a different case.  Fixing the optimization looks
    simple enough to me (am I missing something?), and I'm not convinced
    that fixing it would hurt performance (although since I haven't run
    an experiment, that is conjecture).<br>
    <br>
    So, perhaps I should ask this: if someone took the time to fix the
    transform so that it checks both the alignment *and* the allocation
    size and measures the resulting performance change, how much would
    performance need to suffer before the cure was deemed worse than the
    disease?<br>
    <br>
    -- John T.<br>
    <br>
    <br>
    <br>
      <br>
    <blockquote cite="mid:ECA41BF4-D1D5-446A-BD6D-87ED2CEC5D73@apple.com" type="cite">
      <div>
        <div><br>
        </div>
        <div>-Chris</div>
      </div>
      <br>
    </blockquote>
    <br>
  

</div></blockquote></body></html>