<p dir="auto">A.<br>
All <code class="notranslate">@assert</code>s should be exceptional, and since it's a macro already, it should outline (<code class="notranslate">@noinline</code>) automatically, as was manually done here (to avoid 3x speed regression):</p>
<p dir="auto"><a href="https://github.com/JuliaLang/julia/pull/34237/files">https://github.com/JuliaLang/julia/pull/34237/files</a></p>
<p dir="auto">B.<br>
I was looking into optimizing factorial myself, and think in general throws should be outlined too, i.e. all preconditions. For now A. is a low hanging-fruit I think. I'm not sure, possibly after A. is done, throws can be implemented with asserts, getting B for free?</p>
<p dir="auto">C.<br>
Maybe there are complications when there are two or more asserts and/or throws, still I doubt solving A. and/or B. would be slower then. However possibly in that case something even better could be done?</p>
<p dir="auto">We're increasingly seeing this kind of manual optimization in Base code:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function f(...)
    check_cond() || throw(SomeError(...))
end"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-en">f</span>(<span class="pl-k">...</span>)
    <span class="pl-c1">check_cond</span>() <span class="pl-k">||</span> <span class="pl-c1">throw</span>(<span class="pl-c1">SomeError</span>(<span class="pl-k">...</span>))
<span class="pl-k">end</span></pre></div>
<p dir="auto">rewritten as</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@noinline throw_some_error(...) = throw(SomeError(...))

function f(...)
    check_cond() || throw_some_error(...)
end"><pre class="notranslate"><span class="pl-c1">@noinline</span> <span class="pl-en">throw_some_error</span>(<span class="pl-k">...</span>) <span class="pl-k">=</span> <span class="pl-c1">throw</span>(<span class="pl-c1">SomeError</span>(<span class="pl-k">...</span>))

<span class="pl-k">function</span> <span class="pl-en">f</span>(<span class="pl-k">...</span>)
    <span class="pl-c1">check_cond</span>() <span class="pl-k">||</span> <span class="pl-c1">throw_some_error</span>(<span class="pl-k">...</span>)
<span class="pl-k">end</span></pre></div>
<p dir="auto">It would be great if the compiler could figure this out and do the transformation automatically. I don't think it needs to be terribly complicated either: <code class="notranslate">throw</code> should never be a common code path in Julia and throwing each kind of error could be its own outlined function, which would avoid an explosion of these automatically outlined throw functions.</p>