<div dir="ltr"><div>I deliberately don't bring up call direction because I don't think it's important and I want to keep things simple:</div><div>- If the code is user code, it should not be inlined.</div><div>- If the code is system code (including non-standard 3rd-party dependencies), it should be inlined.</div><div><br></div><div>Take a hypothetical call stack from <a href="https://wandbox.org/permlink/oI43EGHIERSNpy52">this example program</a>:</div><div><br></div><div>?: std::strncmp(....) <- C standard library function, possibly an intrinsic, inline</div><div>?: std::string::operator==(char const*)  <- standard library function, inline</div><div>8: [](std::string const&) {....} <- lambda, don't inline</div><div>?: std::find_if(....) <- standard library taking lambda, inline</div><div>4: contains_sg15 <- user function containing lambda, don't inline</div><div>13: main <- user's main function, don't inline</div><div><br></div><div>I think whether to inline the lambda is mildly contentious but I think we both agree it should not be inlined. The real question is whether to inline `std::find_if`. I guess you're suggesting we don't inline it. I think -- on balance -- we probably should.</div><div><br></div><div>Let's step through this program and let's assume that I only use the "step into" functionality of the debugger, because that's an easy way to 'visit' an entire program. Let's assume `find_if` is a single function.</div><div><br></div><div>When I step into the call to `std::find_if`, I think it should skip through `std::find_if` and take me directly to line 9 in the lambda function in `contains_sg15`. Then, when I "step into" in the lambda, it'll step over the `std::string` call and take me directly to line 10. (That's what it does in GDB at least.) Then when I "step into" again, it <i>should</i> take me back to line 9 in the second lambda invocation.</div><div><br></div><div>Now, if that last action doesn't work, I think that's where you have the concern. I'm not entirely sure what'll happen once `std::find_if` is inlined. I know that without inlining, "step into" eventually does take me back to line 9 of the lambda body. If it doesn't, it's going to kick me back out into the body of `contains_sg15` which is a problem.</div><div><br></div><div>In that case, yes, maybe saying that functions which call non-`-isystem` functions should not be inlined is a rule to consider. But that instantly makes things more complicated: we now have a new reason why the same function might be both inlined and not inlined in the same TU. I don't know if that's a problem. We now send the user into the guts of a standard library call. That <i>is</i> a problem. That code looks frightening and obfuscated to the average developer.</div><div><br></div><div>A workaround to the problem would be to put a breakpoint in the lambda function. I personally would be perfectly happy with that compromise. We're looking at a problem which game developers (among others) experience then in-header functions are defined in the user's TU. In C code and non-modern C++, the offending code is defined in a separate .cpp file.</div><div><br></div><div>Imagine if `std::find_if` could be compiled in a separate TU. And imagine that TU was compiled with `-O2`. What would happen then? You might experience the same debugging difficulty. The same workaround, using a breakpoint, would work there also. We'd at least have parity with non-modern C++. That's the main aim here: not to improve the state of the art for C and C++, merely to help C++ catch up with C.</div><div><br></div><div>HTH,</div><div>John</div><div><br></div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, 20 Aug 2019 at 19:34, Ben Craig <<a href="mailto:ben.craig@ni.com">ben.craig@ni.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">





<div lang="EN-US">
<div class="gmail-m_5128484133000174400WordSection1">
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif">I think a question was glossed over.  Exactly which directions should be inlined…<u></u><u></u></span></p>
<ol style="margin-top:0in" start="1" type="1">
<li class="gmail-m_5128484133000174400MsoListParagraph" style="margin-left:0in"><span style="font-size:11pt;font-family:Calibri,sans-serif">User callee into user caller (definitely not)<u></u><u></u></span></li><li class="gmail-m_5128484133000174400MsoListParagraph" style="margin-left:0in"><span style="font-size:11pt;font-family:Calibri,sans-serif">System callee into system caller (yes)<u></u><u></u></span></li><li class="gmail-m_5128484133000174400MsoListParagraph" style="margin-left:0in"><span style="font-size:11pt;font-family:Calibri,sans-serif">User callee into system caller (maybe?)<u></u><u></u></span></li><li class="gmail-m_5128484133000174400MsoListParagraph" style="margin-left:0in"><span style="font-size:11pt;font-family:Calibri,sans-serif">System callee into user caller (maybe?)<u></u><u></u></span></li></ol>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif">Perhaps number 3 should be prohibited because then a breakpoint on “my” function would either not get hit, or turn into multiple breakpoints.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif">Perhaps number 4 should be prohibited because it makes stepping across loop iterations in things like std::transform more difficult.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif"><u></u> <u></u></span></p>
<div style="border-top:none;border-right:none;border-bottom:none;border-left:1.5pt solid blue;padding:0in 0in 0in 4pt">
<div>
<div style="border-right:none;border-bottom:none;border-left:none;border-top:1pt solid rgb(225,225,225);padding:3pt 0in 0in">
<p class="MsoNormal"><b><span style="font-size:11pt;font-family:Calibri,sans-serif">From:</span></b><span style="font-size:11pt;font-family:Calibri,sans-serif"> cfe-dev <<a href="mailto:cfe-dev-bounces@lists.llvm.org" target="_blank">cfe-dev-bounces@lists.llvm.org</a>>
<b>On Behalf Of </b>via cfe-dev<br>
<b>Sent:</b> Tuesday, August 20, 2019 12:59 PM<br>
<b>To:</b> <a href="mailto:arthur.j.odwyer@gmail.com" target="_blank">arthur.j.odwyer@gmail.com</a><br>
<b>Cc:</b> <a href="mailto:jonathanchesterfield@gmail.com" target="_blank">jonathanchesterfield@gmail.com</a>; <a href="mailto:john@mcfarlane.name" target="_blank">john@mcfarlane.name</a>; <a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
<b>Subject:</b> [EXTERNAL] Re: [cfe-dev] Varying per function optimisation based on include path?<u></u><u></u></span></p>
</div>
</div>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">Ah, I'd forgotten that Og prefers not to inline.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">Distinguishing optimization levels within one translation unit is tricky given the current way we build optimization pipelines. They are *not* designed to handle
 function-level differences in optimization levels.  Trying to (essentially) mix O1 and O2 in the same translation unit is a radical departure from how LLVM thinks about optimization.  ('optnone' is a special case where passes effectively disable themselves
 when presented with an 'optnone' function. Generalizing that to more optimization levels is a seriously invasive proposition.)<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">Re the "symbols" confusion, broadly speaking you can separate debug info into that which describes the source (types, variables, etc), and that which describes
 the generated code (to a first approximation, the instruction<->source mapping).  So the suggestion in this thread is to retain the former but not the latter.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">In this exercise, if we genuinely want to *prevent* debugging of defined-in-system-header functions (which seems like a highly questionable feature) it could
 be done with judicious application of the 'nodebug' attribute.  Not hard, really.<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">--paulr<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"><u></u> <u></u></span></p>
<div style="border-top:none;border-right:none;border-bottom:none;border-left:1.5pt solid blue;padding:0in 0in 0in 4pt">
<div>
<div style="border-right:none;border-bottom:none;border-left:none;border-top:1pt solid rgb(181,196,223);padding:3pt 0in 0in">
<p class="MsoNormal"><b><span style="font-size:10pt;font-family:Tahoma,sans-serif">From:</span></b><span style="font-size:10pt;font-family:Tahoma,sans-serif"> Arthur O'Dwyer [<a href="mailto:arthur.j.odwyer@gmail.com" target="_blank">mailto:arthur.j.odwyer@gmail.com</a>]
<br>
<b>Sent:</b> Tuesday, August 20, 2019 12:20 PM<br>
<b>To:</b> Robinson, Paul<br>
<b>Cc:</b> Jon Chesterfield; Clang Dev; John McFarlane<br>
<b>Subject:</b> Re: [cfe-dev] Varying per function optimisation based on include path?<u></u><u></u></span></p>
</div>
</div>
<p class="MsoNormal"><u></u> <u></u></p>
<div>
<div>
<div>
<div>
<div>
<div>
<div>
<p class="MsoNormal">On Tue, Aug 20, 2019 at 9:42 AM via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>> wrote:<u></u><u></u></p>
</div>
<div>
<blockquote style="border-top:none;border-right:none;border-bottom:none;border-left:1pt solid rgb(204,204,204);padding:0in 0in 0in 6pt;margin:5pt 0in 5pt 4.8pt">
<div>
<div>
<p class="MsoNormal">> In -Og mode, it seems that it would equally make sense to take "a very big<br>
> slice around system headers specifically to avoid" debug symbols for code<br>
> that users can't debug.<u></u><u></u></p>
<p class="MsoNormal"><a name="m_5128484133000174400_m_3359278419428531052__MailEndCompose"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)"> </span></a><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">Our users seem to like to be able to dump their STL containers, which definitely requires debug symbols
 for "code they can't debug."</span><u></u><u></u></p>
</div>
</div>
</blockquote>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Hmm, I may have muddled things up by mentioning "debug symbols" without fully understanding what people mean by that phrase precisely. I meant "line-by-line debugging information enabling single-step through a bunch of templates that the
 user doesn't care about and would prefer to see inlined away." Forget debug symbols and focus on inlining, if that'll help avoid my confusion. :)<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<blockquote style="border-top:none;border-right:none;border-bottom:none;border-left:1pt solid rgb(204,204,204);padding:0in 0in 0in 6pt;margin:5pt 0in 5pt 4.8pt">
<div>
<div>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">OTOH being able to more aggressively optimize system-header code even in –Og mode seems reasonable.</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11pt;font-family:Calibri,sans-serif;color:rgb(31,73,125)">OTOOH most of the system-header code is templates or otherwise inlineable early, and after inlining
 the distinction between app and sys code really goes away.</span><u></u><u></u></p>
</div>
</div>
</blockquote>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">I believe we'd like to get "inlining early," but the problem is that `-Og` disables inlining. So there is no "after inlining" at the moment.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">Here's a very concrete example: <a href="https://urldefense.com/v3/__https:/godbolt.org/z/5tTgO4__;!fqWJcnlTkjM!7ZGRlXoS3ERcBoHUI0twkSwgjy1q68aYJaN5WYHvdmN5-ryxMXzEwmUQRCfC$" target="_blank">https://godbolt.org/z/5tTgO4</a><u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">int foo(std::tuple<int, int> t) {<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">    return std::get<0>(t);<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">}<u></u><u></u></span></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">At `-Og` this produces the assembly code<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">_Z3fooSt5tupleIJiiEE:<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">  pushq %rax<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">  callq _ZSt3getILm0EJiiEERNSt13tuple_elementIXT_ESt5tupleIJDpT0_EEE4typeERS4_<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">  movl (%rax), %eax<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">  popq %rcx<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">  retq<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">_ZSt3getILm0EJiiEERNSt13tuple_elementIXT_ESt5tupleIJDpT0_EEE4typeERS4_:<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">  jmp _ZSt12__get_helperILm0EiJiEERT0_RSt11_Tuple_implIXT_EJS0_DpT1_EE<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">_ZSt12__get_helperILm0EiJiEERT0_RSt11_Tuple_implIXT_EJS0_DpT1_EE:<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">  jmp _ZNSt11_Tuple_implILm0EJiiEE7_M_headERS0_<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">_ZNSt11_Tuple_implILm0EJiiEE7_M_headERS0_:<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">  addq $4, %rdi<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">  jmp _ZNSt10_Head_baseILm0EiLb0EE7_M_headERS0_<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">_ZNSt10_Head_baseILm0EiLb0EE7_M_headERS0_:<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">  movq %rdi, %rax<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">  retq<u></u><u></u></span></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">I believe that if John McFarlane's proposal were adopted by Clang, so that inlining-into-system-functions were allowed at `-Og`, then the resulting assembly code would look like this instead, for a much better experience in both debugging
 and runtime performance:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<div>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">_Z3fooSt5tupleIJiiEE:<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">  pushq %rax<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">  callq _ZSt3getILm0EJiiEERNSt13tuple_elementIXT_ESt5tupleIJDpT0_EEE4typeERS4_<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">  movl (%rax), %eax<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">  popq %rcx<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">  retq<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">_ZSt3getILm0EJiiEERNSt13tuple_elementIXT_ESt5tupleIJDpT0_EEE4typeERS4_:<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">  leaq 4(%rdi), %rax<u></u><u></u></span></p>
<p style="margin:0in 0in 0.0001pt;font-stretch:normal"><span style="font-size:10pt;font-family:Menlo,serif;color:black">  retq<u></u><u></u></span></p>
</div>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Notice that we still aren't inlining `std::get` into `foo`, because `foo` (as a user function) gets no inlining optimizations at `-Og`. But we do inline and collapse the whole chain of function-template helpers into `std::get` (because
 `std::get` is a function <b><i>defined</i></b> in a system header). This inlining creates new optimization opportunities, such as combining the `add` and `mov` into a single `lea`.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">HTH,<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">–Arthur<u></u><u></u></p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

</blockquote></div></div>