<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/05/2014 10:54 AM, Arnaud A. de
      Grandmaison wrote:<br>
    </div>
    <blockquote cite="mid:000501cff929$f9823870$ec86a950$@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;}
@font-face
        {font-family:Tahoma;
        panose-1:2 11 6 4 3 5 4 4 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri","sans-serif";
        color:black;
        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;
        font-family:"Calibri","sans-serif";
        color:windowtext;}
span.EmailStyle18
        {mso-style-type:personal-reply;
        font-family:"Calibri","sans-serif";
        color:#1F497D;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}
@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"><span
            style="color:#1F497D;mso-fareast-language:EN-GB"><o:p> </o:p>*trimmed
            for length*<o:p></o:p></span></p>
        <p class="MsoNormal" style="margin-left:36.0pt"> <o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">This is not a
          theoretical question: clang can generate such cases. For
          example, the following testcase:<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">struct X {<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">  void
          doSomething();<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">  char b[33];<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">};<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt"> <o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">void bar(X
          &);<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">void baz();<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt"> <o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">void test(int i)
          {<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">  if (i==9) {<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">    X x;<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">   
          x.doSomething();<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">label:<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">    bar(x);<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">  } else {<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">    baz();<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">    if (i==0)<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">      goto
          label;<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">  }<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">}<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt"> <o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">Produces:<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt"> <o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">%struct.X = type
          { [33 x i8] }<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt"> <o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">define void
          @_Z4testi(i32 %i) {<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">entry:<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">  %x = alloca
          %struct.X, align 1<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">  %cmp = icmp eq
          i32 %i, 9<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">  br i1 %cmp,
          label %if.then, label %if.else<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt"> <o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">if.then:                                         
          ; preds = %entry<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">  %0 =
          getelementptr inbounds %struct.X* %x, i64 0, i32 0, i64 0<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">  call void
          @llvm.lifetime.start(i64 33, i8* %0)<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">  call void
          @_ZN1X11doSomethingEv(%struct.X* %x)<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">  br label
          %label<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt"> <o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">label:                                           
          ; preds = %if.else.label_crit_edge, %if.then<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">  %.pre-phi =
          phi i8* [ %.pre, %if.else.label_crit_edge ], [ %0, %if.then ]<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">  call void
          @_Z3barR1X(%struct.X* dereferenceable(33) %x)<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">  call void
          @llvm.lifetime.end(i64 33, i8* %.pre-phi)<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">  br label
          %if.end3<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt"> <o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">if.else:                                   
                ; preds = %entry<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">  tail call void
          @_Z3bazv()<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">  %cmp1 = icmp
          eq i32 %i, 0<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">  br i1 %cmp1,
          label %if.else.label_crit_edge, label %if.end3<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt"> <o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">if.else.label_crit_edge:                         
          ; preds = %if.else<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">  %.pre =
          getelementptr inbounds %struct.X* %x, i64 0, i32 0, i64 0<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">  br label
          %label<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt"> <o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">if.end3:                                         
          ; preds = %if.else, %label<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">  ret void<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">}<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt"> <o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt">Note that the
          path thru if.else.label_crit_edge has no lifetime start.<o:p></o:p></p>
        <p class="MsoNormal" style="margin-left:36.0pt"><span
            style="font-size:12.0pt;font-family:"Times New
            Roman","serif";mso-fareast-language:EN-GB">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>
          </span><span style="font-size:12.0pt;font-family:"Times
            New
            Roman","serif";color:#1F497D;mso-fareast-language:EN-GB"><o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="color:#1F497D;mso-fareast-language:EN-GB">With the
            clarification you made on the semantics, the above IR is
            correct, but could be improved when clang generates it: the
            label_crit_edge block should contain a lifetime.start for
            the alloca.</span></p>
      </div>
    </blockquote>
    Another approach would be have LLVM prove that %x is uninitialized
    along the path through if.else.label_crit_edge and then combine that
    with the lifetime.start along the other path.  This would require
    reasoning about pointer escapes, but that's fairly tractable.  It
    actually doesn't seem unreasonable that GVN would get this case.  Do
    you have a counter example where an optimization is missed only when
    the lifetime.start is not present?  <br>
    <br>
    More generally, are there specific optimizations which aren't
    kicking in with the current placement strategy that you'd like to
    see?<br>
    <br>
    Philip<br>
    <br>
    <br>
  </body>
</html>