<html>
  <head>
    <meta content="text/html; charset=windows-1252"
      http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <br>
    <div class="moz-cite-prefix">On 11/04/2014 03:59 AM, Arnaud A. de
      Grandmaison wrote:<br>
    </div>
    <blockquote cite="mid:000001cff826$c9b98ca0$5d2ca5e0$@arm.com"
      type="cite">
      <meta http-equiv="Content-Type" content="text/html;
        charset=windows-1252">
      <meta name="Generator" content="Microsoft Word 14 (filtered
        medium)">
      <style><!--
/* Font Definitions */
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri","sans-serif";
        mso-fareast-language:EN-US;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
span.EmailStyle17
        {mso-style-type:personal-compose;
        font-family:"Calibri","sans-serif";
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri","sans-serif";
        mso-fareast-language:EN-US;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
      <div class="WordSection1">
        <p class="MsoNormal">The LRM
          (<a class="moz-txt-link-freetext" href="http://llvm.org/docs/LangRef.html#llvm-lifetime-start-intrinsic">http://llvm.org/docs/LangRef.html#llvm-lifetime-start-intrinsic</a>)
          essentially  states that:<o:p></o:p></p>
        <p class="MsoNormal"> - ptr is dead before a call to
          “lifetime.start size, ptr”<o:p></o:p></p>
        <p class="MsoNormal"> - ptr is dead after a call to
          “lifetime.end size, ptr”<o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">This is all good and fine, and the expected
          use case is that all “lifetime.end size, ptr” markers are
          matched with a preceding “lifetime.start size, ptr” in the
          CFG.<o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">What is supposed to happen when a
          “lifetime.end size, ptr” is not matched with a “lifetime.start
          size, ptr” ? I think there are a few possible answers:<o:p></o:p></p>
        <p class="MsoNormal"> - the memory area pointed to by ptr is
          assumed to be alive since function entry<o:p></o:p></p>
        <p class="MsoNormal"> - the memory area pointed to by ptr is
          assumed to be dead since function entry, as it has not been
          marked alive<o:p></o:p></p>
        <p class="MsoNormal"> - this is an unexpected situation</p>
      </div>
    </blockquote>
    My reading of the current spec is that your first option is the only
    valid interpretation.<br>
    <br>
    My interpretation of the spec wording would be that each path in the
    program may contain either a lifetime.start, a lifetime.end, or
    both.  If the path contains no marker, the location is assumed live
    (unless proven otherwise).  The lifetime markers segment the path
    into live, and dead regions, but only on that specific path.  To
    reason about global properties, the optimizer must form
    "for-all-paths" facts.  (Dominance being the easiest form of this
    generally.)<br>
    <br>
    Just to note, this is rather different than the "invariant.*"
    family.  In particular, the invariant family requires the "start" as
    an argument to the "end" intrinsic.<br>
    <br>
    <blockquote cite="mid:000001cff826$c9b98ca0$5d2ca5e0$@arm.com"
      type="cite">
      <div class="WordSection1">
        <p class="MsoNormal"><o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">I think this ambiguity should be cleared in
          the LRM, because today’s implicit assumption may be broken at
          any time.</p>
      </div>
    </blockquote>
    I believe the existing implementation matches the semantics I
    specified above.  If you find a case where it doesn't, that's a
    bug.  <br>
    <blockquote cite="mid:000001cff826$c9b98ca0$5d2ca5e0$@arm.com"
      type="cite">
      <div class="WordSection1">
        <p class="MsoNormal"><o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">This is not a theoretical question: clang
          can generate such cases. For example, the following testcase:<o:p></o:p></p>
        <p class="MsoNormal">struct X {<o:p></o:p></p>
        <p class="MsoNormal">  void doSomething();<o:p></o:p></p>
        <p class="MsoNormal">  char b[33];<o:p></o:p></p>
        <p class="MsoNormal">};<o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">void bar(X &);<o:p></o:p></p>
        <p class="MsoNormal">void baz();<o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">void test(int i) {<o:p></o:p></p>
        <p class="MsoNormal">  if (i==9) {<o:p></o:p></p>
        <p class="MsoNormal">    X x;<o:p></o:p></p>
        <p class="MsoNormal">    x.doSomething();<o:p></o:p></p>
        <p class="MsoNormal">label:<o:p></o:p></p>
        <p class="MsoNormal">    bar(x);<o:p></o:p></p>
        <p class="MsoNormal">  } else {<o:p></o:p></p>
        <p class="MsoNormal">    baz();<o:p></o:p></p>
        <p class="MsoNormal">    if (i==0)<o:p></o:p></p>
        <p class="MsoNormal">      goto label;<o:p></o:p></p>
        <p class="MsoNormal">  }<o:p></o:p></p>
        <p class="MsoNormal">}<o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">Produces:<o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">%struct.X = type { [33 x i8] }<o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">define void @_Z4testi(i32 %i) {<o:p></o:p></p>
        <p class="MsoNormal">entry:<o:p></o:p></p>
        <p class="MsoNormal">  %x = alloca %struct.X, align 1<o:p></o:p></p>
        <p class="MsoNormal">  %cmp = icmp eq i32 %i, 9<o:p></o:p></p>
        <p class="MsoNormal">  br i1 %cmp, label %if.then, label
          %if.else<o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">if.then:                                         
          ; preds = %entry<o:p></o:p></p>
        <p class="MsoNormal">  %0 = getelementptr inbounds %struct.X*
          %x, i64 0, i32 0, i64 0<o:p></o:p></p>
        <p class="MsoNormal">  call void @llvm.lifetime.start(i64 33,
          i8* %0)<o:p></o:p></p>
        <p class="MsoNormal">  call void
          @_ZN1X11doSomethingEv(%struct.X* %x)<o:p></o:p></p>
        <p class="MsoNormal">  br label %label<o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">label:                                           
          ; preds = %if.else.label_crit_edge, %if.then<o:p></o:p></p>
        <p class="MsoNormal">  %.pre-phi = phi i8* [ %.pre,
          %if.else.label_crit_edge ], [ %0, %if.then ]<o:p></o:p></p>
        <p class="MsoNormal">  call void @_Z3barR1X(%struct.X*
          dereferenceable(33) %x)<o:p></o:p></p>
        <p class="MsoNormal">  call void @llvm.lifetime.end(i64 33, i8*
          %.pre-phi)<o:p></o:p></p>
        <p class="MsoNormal">  br label %if.end3<o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">if.else:                                   
                ; preds = %entry<o:p></o:p></p>
        <p class="MsoNormal">  tail call void @_Z3bazv()<o:p></o:p></p>
        <p class="MsoNormal">  %cmp1 = icmp eq i32 %i, 0<o:p></o:p></p>
        <p class="MsoNormal">  br i1 %cmp1, label
          %if.else.label_crit_edge, label %if.end3<o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">if.else.label_crit_edge:                         
          ; preds = %if.else<o:p></o:p></p>
        <p class="MsoNormal">  %.pre = getelementptr inbounds %struct.X*
          %x, i64 0, i32 0, i64 0<o:p></o:p></p>
        <p class="MsoNormal">  br label %label<o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">if.end3:                                         
          ; preds = %if.else, %label<o:p></o:p></p>
        <p class="MsoNormal">  ret void<o:p></o:p></p>
        <p class="MsoNormal">}<o:p></o:p></p>
        <p class="MsoNormal"><o:p> </o:p></p>
        <p class="MsoNormal">Note that the path thru
          if.else.label_crit_edge has no lifetime start.</p>
      </div>
    </blockquote>
    This seems fine to me.  The optimizer can (soundly) conclude that %p
    is dead after the "lifetime.end" (for the two instructions), and
    dead before the "lifetime.start" (for the *single* instruction in
    that basic block, *not* for the previous BB).  This seems like the
    proper result for this example, am I missing something?<br>
    <br>
    Philip<br>
  </body>
</html>