<div dir="ltr"><div class="gmail_quote"><div dir="ltr">On Tue, Feb 23, 2016 at 9:33 AM Sanjoy Das <<a href="mailto:sanjoy@playingwithpointers.com">sanjoy@playingwithpointers.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Mon, Feb 22, 2016 at 11:18 PM, Chandler Carruth <<a href="mailto:chandlerc@gmail.com" target="_blank">chandlerc@gmail.com</a>> wrote:<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<br>
>> a<br>
>> side exit / guard it in); but also has more general use cases.<br>
><br>
><br>
> Note that we already have this *exact* concept in the IR via linkage for<br>
> better or worse. I think it is really confusing as you are currently<br>
<br>
I was going to have a more detailed discussion on this in the (yet to<br>
be started) review thread for `interposable`: we'd like to be able to<br>
inline `interposable` functions.  The "interposition" can only happen<br>
in physical function boundaries, so opt is allowed to do as much<br>
IPA/IPO it wants once it makes the physical function boundary go away<br>
via inlining.  None of linkage types seem to have this property.<br>
<br>
Part of the challenge here is to specify the attribute in a way that<br>
allows inlining, but not IPA without inlining.  In fact, maybe it is<br>
best to not call it "interposable" at all?<br></blockquote><div><br></div><div>Yea, this is something *very* different from interposable. GCC and other compilers that work to support symbol interposition make specific efforts to not inline them in specific ways (that frankly I don't fully understand, as it doesn't seem to be always which is what the definition of interposable indicates to me...).</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Actually, I think one of the problems we're trying to solve with<br>
`interposable` is applicable to the available_externally linkage as<br>
well.  Say we have<br>
<br>
```<br>
void foo() available_externally {<br>
  %t0 = load atomic %ptr<br>
  %t1 = load atomic %ptr<br>
  if (%t0 != %t1) print("X");<br>
}<br>
void main() {<br>
  foo();<br>
  print("Y");<br>
}<br>
```<br>
<br>
Now the possible behaviors of the above program are {print("X"),<br>
print("Y")} or {print("Y")}.  But if we run opt then we have<br>
<br>
```<br>
void foo() available_externally readnone nounwind {<br>
  ;; After CSE'ing the two loads and folding the condition<br>
}<br>
void main() {<br>
  foo();<br>
  print("Y");<br>
}<br>
```<br>
<br>
and some generic reordering<br>
<br>
```<br>
void foo() available_externally readnone nounwind {<br>
  ;; After CSE'ing the two loads and folding the condition<br>
}<br>
void main() {<br>
  print("Y");<br>
  foo();  // legal since we're moving a readnone nounwind function that<br>
          // was guaranteed to execute (hence can't have UB)<br>
}<br>
```<br>
<br>
Now if we do not inline @foo(), and instead re-link the call site in<br>
@main to some non-optimized copy (or differently optimized copy) of<br>
foo, then it is possible for the program to have the behavior<br>
{print("Y"); print ("X")}, which was disallowed in the earlier<br>
program.<br>
<br>
In other words, opt refined the semantics of @foo() (i.e. reduced the<br>
set of behaviors it may have) in ways that would make later<br>
optimizations invalid if we de-refine the implementation of @foo().<br>
<br>
Given this, I'd say we don't need a new attribute / linkage type, and<br>
can add our restriction to the available_externally linkage.<br></blockquote><div><br></div><div>Interesting example, I agree it seems quite broken. Even more interesting, I can't see anything we do in LLVM that prevents this from breaking essentially everywhere. =[[[[[[</div><div><br></div><div>link_once and link_once_odr at least seem equally broken because we don't put the caller and callee into a single comdat or anything to ensure that the optimized one is selected at link time.</div><div><br></div><div>But there are also multiple different kinds of overriding we should think about:</div><div><br></div><div>1) Can the definition get replaced at link time (or at runtime via an interpreter) with a differently *optimized* variant stemming from the same definition (thus it has the same behavior but not the same refinement). This is the "ODR" guarantee in some linkages (and vaguely implied for available_externally)</div><div><br></div><div>2) Can the definition get replaced at link time (or at runtime via an interpreter) with a function that has fundamentally different behavior</div><div><br></div><div>3) To support replacing the definition, the call edge must be preserved.</div><div><br></div><div>To support interposition you need #3, the most restrictive model. LLVM (i think) actually does a decent job of modeling this as we say that the function is totally opaque. We don't do IPA or inlining. But I don't think that's what you're looking for.</div><div><br></div><div>I'm curious whether your use case is actually in the #1 bucket or #2 bucket. That is, I'm wondering if there is any way in which the "different implementation" would actually break in the face of optimizations on things like *non-deduced* function attributes, etc.</div><div><br></div><div>If your use case looks more like #1, then I actually think this is what we want for link_once_odr and available_externally. You probably want the former rather than the latter as you don't want it to be discardable.</div><div><br></div><div>If your use case looks more like #2, then I think its essentially "link_once" or "link_any", and it isn't clear that LLVM does a great job of modeling this today.</div><div><br></div><div>I'd be mildly interested in factoring the discarding semantics from the "what do other definitions look like" semantics. The former are what I think fit cleanly into linkages, and the latter I think we wedged into them because they seemed to correspond in some cases and because attributes used to be very limited in number.</div></div></div>