<div dir="ltr">I've not had time to really dig into all of this thread, but I wanted to point out:<br><br><div class="gmail_quote"><div dir="ltr">On Mon, Feb 22, 2016 at 10:27 PM Sanjoy Das via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Assuming everyone is on the same page, here's a rough high level agenda:<br>
<br>
<br>
# step A: Introduce an `interposable` function attribute<br>
<br>
We can bike shed on the name and the exact specification, but the<br>
general idea is that you cannot do IPA / IPO over callsites calling<br>
`interposable` functions without inlining them.  This attribute will<br>
(usually) have to be used on function bodies that can deoptimize (e.g. has a<br>
side exit / guard it in); but also has more general use cases.<br></blockquote><div><br></div><div>Note that we already have this *exact* concept in the IR via linkage for better or worse. I think it is really confusing as you are currently describing it because it seems deeply overlapping with linkage, which is where the whole interposition thing comes from, and yet you never mention how it interacts with linkage at all. What does it mean to have a common linkage function that lacks the interposable attribute? Or a LinkOnceODR function that does have that attribute?</div><div><br></div><div>If the goal is to factor replaceability out of linkage, we should actually factor it out rather than adding yet one more way to talk about this.</div><div><br></div><div>And generally, we need to be *really* careful adding function attributes. Look at the challenges we had figuring out norecurse. Adding attributes needs to be viewed as nearly as high cost as adding instructions, substantially higher cost than intrinsics.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
<br>
# step B: Introduce a `side_exit` intrinsic<br>
<br>
Specify an `@llvm.experimental.side_exit` intrinsic, polymorphic on the<br>
return type:<br>
<br>
 - Consumes a "deopt" continuation, and replaces the current physical<br>
   stack frame with one or more interpreter frames (implementation<br>
   provided by the runtime).<br></blockquote><div><br></div><div>I think it would be really helpful to work to describe these things in terms of semantic contracts on the IR rather than in terms of implementation strategies. For example, not all IR interacts with an interpreter, and so I don't think we should use the term "interpreter" to specify the semantic model exposed by the IR.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
 - Calls to this intrinsic must be `musttail` (verifier will check this)<br>
 - We'll have some minor logic in the inliner such that when inlining @f into @g<br>
   in<br>
<br>
     define i32 @f() {<br>
       if (X) return side_exit() [ "deopt"(X) ];<br>
       return i32 20;<br>
     }<br>
<br>
     define i64 @g() {<br>
       if (Y) {<br>
         r = f() [ "deopt"(Y) ];<br>
         print(r);<br>
     }<br>
<br>
   We get<br>
<br>
     define i64 @g() {<br>
       if (Y) {<br>
         if (X) return side_exit() [ "deopt"(Y, X) ];<br>
         print(20);<br>
       }<br>
     }<br>
<br>
   and not<br>
<br>
     define i64 @g() {<br>
       if (Y) {<br>
         r = X ? (side_exit() [ "deopt"(Y, X) ]) : 20;<br>
         print(r);<br>
     }<br>
<br>
<br>
# step C: Introduce a `guard_on` intrinsic<br>
<br>
Will be based around what was discussed / is going to be discussed on<br>
this thread.<br>
<br>
<br>
(I think Philip was right in suggesting to split out a "step B" that<br>
only introduces a `side_exit` intrinsic.  We *will* have to specify<br>
them, since we'd like to optimize some after we've lowered guards into<br>
explicit control flow, and for that we need a specification of side<br>
exits.)<br>
<br>
<br>
# aside: non-managed languages and guards<br>
<br>
Chandler raised some points on IRC around making `guard_on` (and<br>
possibly `side_exit`?) more generally applicable to unmanaged<br>
languages; so we'd want to be careful to specify these in a way that<br>
allows for implementations in an unmanaged environments (by function<br>
cloning, for instance).<br>
<br>
-- Sanjoy<br>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div></div>