-
Notifications
You must be signed in to change notification settings - Fork 470
Description
Originally, I was going to make a suggestion for an attribute that tries to force inlining on functions. However, the RFC doc for inlining brought up several very good points of how such an approach can result in terrible consequences for misusing inlining.
I propose adding an attribute that 'encourages' the inlining cost-model to choose to inline a function; to bias the cost-model towards inlining a function (in cases where it otherwise wouldn't have), rather than to always force the function to be inlined if possible.
As said in that doc, inlining gives devs 'the opportunity to fine-tune performance-critical optimizations'. The implementation of this would also, ideally, prevent reckless spamming of the attribute where doing so causes harm.
I will naively suggest that the effect of this attribute be proportional to the actual size of the function it's used on, by having it less likely to be inlined with larger functions.
I don't have much experience with the cost model though and am unsure if such an approach feasible, or if a better option exists, which is why I don't have a more extensive idea of how this should be implemented.
Here is an example of how this feature could be used with an ideal implementation:
-- With the attribute, this will now be inlined when it couldn't be beforehand.
@preferinlining
function add(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)
return a + b + c + ... + p
end
-- Although this function has `@preferinlining`, it is obviously not inlined as it is recursive.
@preferinlining
function recurse(a: number)
if a > 500 then
return a
end
return recurse(a + 1)
end
-- This is a more realistic example of something that may actually be used in
-- a hot loop, where this would probably have not be inlined if not for the attribute.
@preferinlining
function indexOrDefault(t, k, default)
return t and t[k] or default
end
-- This is will not be inlined even with the attribute, as it is a variadic function.
@preferinlining
function a(...: number)
local x = 0
for i = 1, select("#", ...) do
x += select(i, ...)
end
return x
end