<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>