<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, Apr 18, 2021 at 8:29 PM Johannes Doerfert 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:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">I'm very much in favor of `noipa`. It comes up every few months<br>
and it would be widely useful. I'd expose it via Clang and -O0 could<br>
set it as well (for the LTO case).<br>
<br>
When it comes to inexact definitions, optnone functions, and existing <br>
attributes,<br>
I'd be in favor of 1) always allowing the use of existing attributes,<br>
and 2) not deriving new ones for an inexact or optnone definition.<br></blockquote><div><br></div><div>+1 from me on this FWIW! </div><div><br></div><div>-- </div><div>Mehdi</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
<br>
This is how the Attributor determines if it a function level attribute could<br>
be derived or if we should only stick with the existing information:<br>
<br>
/// Determine whether the function \p F is IPO amendable<br>
///<br>
/// If a function is exactly defined or it has alwaysinline attribute<br>
/// and is viable to be inlined, we say it is IPO amendable<br>
bool isFunctionIPOAmendable(const Function &F) {<br>
return F.hasExactDefinition() || <br>
InfoCache.InlineableFunctions.count(&F);<br>
}<br>
<br>
So, if the above check doesn't hold we will not add new attributes but <br>
we will<br>
still use existing ones. This seems to me the right way to allow <br>
users/frontends<br>
to provide information selectively.<br>
<br>
That said, right now the Attributor will not propagate any information <br>
from an<br>
optnone function or derive new information. Nevertheless, I'd be in <br>
favor to allow<br>
existing information to be used for IPO.<br>
<br>
~ Johannes<br>
<br>
<br>
On 4/18/21 8:40 PM, David Blaikie via llvm-dev wrote:<br>
> Prototyping the idea of "isDefinitionExact" returning false for optnone<br>
> (whether or not we split it out into noipo or not) I've tripped over<br>
> something it seems I created 5 years ago:<br>
><br>
> I added some IPC support for optnone to GlobalsModRef:<br>
> <a href="https://github.com/llvm/llvm-project/commit/c662b501508200076e581beb9345a7631173a1d8#diff-55664e96a7ce3533b46f12c6906acecb2bd9a599e2b79c97506af4b1b4873fa1" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/c662b501508200076e581beb9345a7631173a1d8#diff-55664e96a7ce3533b46f12c6906acecb2bd9a599e2b79c97506af4b1b4873fa1</a><br>
> - so it wouldn't conclude properties of an optnone function.<br>
><br>
> But I then made a follow-up commit (without a lot of context as to why,<br>
> unfortunately :/ ) that allowed GlobasModRef to use existing attributes on<br>
> an optnone function:<br>
> <a href="https://github.com/llvm/llvm-project/commit/7a9b788830da0a426fb0ff0a4cec6d592bb026e9#diff-55664e96a7ce3533b46f12c6906acecb2bd9a599e2b79c97506af4b1b4873fa1" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/7a9b788830da0a426fb0ff0a4cec6d592bb026e9#diff-55664e96a7ce3533b46f12c6906acecb2bd9a599e2b79c97506af4b1b4873fa1</a><br>
><br>
> But it seems making the function definition inexact, breaks the unit<br>
> testing added in the latter commit. I suppose then it's an open question<br>
> whether existing attributes on an inexact definition should be used at all?<br>
> (I don't know what motivated me to support them for optnone)<br>
><br>
> Oh, and here's a change from Chandler around the same time similarly<br>
> blocking some ipo for optnone:<br>
> <a href="https://github.com/llvm/llvm-project/commit/0fb998110abcf3d67495d12f854a1576b182d811#diff-cc618a9485181a9246c4e0367dc9f1a19d3cb6811d1e488713f53a753d3da60c" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/0fb998110abcf3d67495d12f854a1576b182d811#diff-cc618a9485181a9246c4e0367dc9f1a19d3cb6811d1e488713f53a753d3da60c</a><br>
> - in this case preventing FunctionAttrs from deriving the attributes for an<br>
> optnone function. That functionality looks like it can be subsumed by the<br>
> inexact approach - applying inexact to optnone and removing the change in<br>
> Chandler's patch still passes the tests. (hmm, tested - not quite, but more<br>
> work to do there)<br>
><br>
> On Sun, Apr 18, 2021 at 10:06 AM David Blaikie <<a href="mailto:dblaikie@gmail.com" target="_blank">dblaikie@gmail.com</a>> wrote:<br>
><br>
>> On Sun, Apr 18, 2021 at 9:43 AM Roman Lebedev <<a href="mailto:lebedev.ri@gmail.com" target="_blank">lebedev.ri@gmail.com</a>><br>
>> wrote:<br>
>><br>
>>> There's 'noipa' attribute in GCC, currently it is not supported by clang.<br>
>>> Theoretically, how would one implement it?<br>
>>><br>
>> If we wanted to do this really robustly, I guess we might have to<br>
>> introduce some sort of "here's the usual way to check if this is a<br>
>> definition/get the body of the function" (which for noipa it says "there is<br>
>> no body/don't look here") and "no, really, I need the definition" (for<br>
>> actual code generation).<br>
>><br>
>> Though I'm not advocating for that - I'm OK with a more ad-hoc/best-effort<br>
>> implementation targeting the -O0/debugging assistant<br>
>> __attribute__((optnone)) kind of use case - happy to fix cases as they come<br>
>> up to improve the user experience for these situations.<br>
>><br>
>> Maybe we could get away with generalizing this by having an optnone (or<br>
>> noipa) function appear "interposable" even though it doesn't have a real<br>
>> interposable linkage? That should hinder/disable any IPA.<br>
>><br>
>> Hmm, looks like GlobalValue::isDefinitionExact would be best to return<br>
>> false in this case (whatever we end up naming it) /maybe/<br>
>> mayBeDerefined should return false too.<br>
>><br>
>> Yeah, I guess if we can implement such a robust generalization, then it'd<br>
>> probably be OK/easy enough to implement both noipa and optnone implies<br>
>> noipa the same as it implies noinline (well, I guess noipa would subsume<br>
>> the noinline implication - if the function isn't exact, the inliner won't<br>
>> inline it so there wouldn't be any need for the explicit noinline)<br>
>><br>
>><br>
>>> With your proposal, clang `noipa` attribute could be lowered<br>
>>> to `optnone` on the whole function, To me that seems like<br>
>>> too much of a hammer, should that be the path forward.<br>
>>><br>
>> I agree that lowering noipa to optnone would be a very aggressive form of<br>
>> noipa - likely if we want to support noipa it would be to support it<br>
>> separately and maybe either lower -O0 (& maybe __attribute__((optnone))) to<br>
>> both optnone+noipa+noinline (since optnone already implies noinline) or<br>
>> make optnone imply ipa/be a superset of it implicitly (if we do have noipa<br>
>> it's probably best to have "optnone requires noipa" the same way "optnone<br>
>> requires noinline" rather than an implicit superset sort of thing).<br>
>><br>
>> I think that'd certainly be appropriate for -O0, and I'd argue it'd be<br>
>> appropriate for __attribute__((optnone)) because I think it'd be what<br>
>> people expect/is consistent with the motivation for the attribute (for<br>
>> debuggability - so you wouldn't want a caller to not fill in<br>
>> parameters/pass in garbage because it knows the implementation doesn't<br>
>> matter, or not use the result because it knows what the result should be).<br>
>><br>
>><br>
>>> Would it not be best to not conflate the two,<br>
>>> and just introduce the `noipa` attribute?<br>
>>><br>
>> I think we'd still want to conflate them for user-facing functionality,<br>
>> even if they were separable at the IR level.<br>
>><br>
>> - Dave<br>
>><br>
>><br>
>>> Roman<br>
>>><br>
>>> On Sun, Apr 18, 2021 at 7:37 PM David Blaikie <<a href="mailto:dblaikie@gmail.com" target="_blank">dblaikie@gmail.com</a>> wrote:<br>
>>>> While trying to reproduce some debug info thing (I don't have the exact<br>
>>> example at the moment - but I think it was more aggressive than the example<br>
>>> I have now, but something like this:<br>
>>>> __attribute__((optnone)) int f1() {<br>
>>>> return 3;<br>
>>>> }<br>
>>>> int main() {<br>
>>>> return f1();<br>
>>>> }<br>
>>>><br>
>>>><br>
>>>> (actually I think in my case I had a variable to hold the return value<br>
>>> from f1, with the intent that this variable's location couldn't use a<br>
>>> constant - a load from a volatile variable would probably have provided<br>
>>> similar functionality in this case)<br>
>>>> LLVM (& specifically Sparse Conditional Constant Propagation,<br>
>>> llvm/lib/Transforms/Scalar/SCCP.cpp) optimizes this code noting that f1<br>
>>> always returns 3, so rather than using the return value from the call to<br>
>>> f1, it ends up hardcoding the return value:<br>
>>>> define dso_local i32 @main() local_unnamed_addr #1 {<br>
>>>><br>
>>>> entry:<br>
>>>><br>
>>>> %call = tail call i32 @_Z2f1v()<br>
>>>><br>
>>>> ret i32 3<br>
>>>><br>
>>>> }<br>
>>>><br>
>>>><br>
>>>> I consider this a bug - in that optnone is used to implement -O0 for<br>
>>> LTO, so it seemed to me that the correct behavior is for an optnone<br>
>>> function to behave as though it were compiled in another object file<br>
>>> outside the purview of optimizations - interprocedural or intraprocedural.<br>
>>>> So I sent <a href="https://reviews.llvm.org/D100353" rel="noreferrer" target="_blank">https://reviews.llvm.org/D100353</a> to fix that.<br>
>>>><br>
>>>> Florian pointed out that this wasn't quite specified in the LangRef,<br>
>>> which says this about optnone:<br>
>>>> This function attribute indicates that most optimization passes will<br>
>>> skip this function, with the exception of interprocedural optimization<br>
>>> passes. Code generation defaults to the “fast” instruction selector. This<br>
>>> attribute cannot be used together with the alwaysinline attribute; this<br>
>>> attribute is also incompatible with the minsize attribute and the optsize<br>
>>> attribute.<br>
>>>> This attribute requires the noinline attribute to be specified on the<br>
>>> function as well, so the function is never inlined into any caller. Only<br>
>>> functions with the alwaysinline attribute are valid candidates for inlining<br>
>>> into the body of this function.<br>
>>>><br>
>>>> So the spec of optnone is unclear (or arguably explicitly disallows)<br>
>>> whether interprocedural optimizations should treat optnone functions in any<br>
>>> particular way.<br>
>>>> So I was going to update the wording to rephrase this to say<br>
>>> "Interprocedural optimizations should treat this function as though it were<br>
>>> defined in an isolated module/object." (perhaps "interprocedural<br>
>>> optimizations should treat optnone functions as opaque" or "as though they<br>
>>> were only declarations")<br>
>>>> The choice of this direction was based on my (possibly incorrect or<br>
>>> debatable) understanding of optnone, that it was equivalent to the function<br>
>>> being in a separate/non-lto object. (this seems consistent with the way<br>
>>> optnone is used to implement -O0 under lto - you could imagine a user<br>
>>> debugging a binary, using -O0 for the code they're interested in debugging,<br>
>>> and potentially using an interactive debugger to change some state in the<br>
>>> function causing it to return a different value - which would get quite<br>
>>> confusing if the return value was effectively hardcoded into the caller)<br>
>>>> What're folks thoughts on this?<br>
>>>><br>
>>>> - Dave<br>
><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="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><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="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div></div>