dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.04k stars 4.68k forks source link

Inline for lambda #13679

Open blowin opened 4 years ago

blowin commented 4 years ago

Now:

public int Calculate(Func<int, int, int> c)
{
 return c(10, 20);   
}

public int CallCalculate() 
{
 return Calculate((x1, x2) => x1 + x2);   
}

Compile to:

private sealed class <>c
{
    public static readonly <>c <>9 = new <>c();

    public static Func<int, int, int> <>9__1_0;

    internal int <CallCalculate>b__1_0(int x1, int x2)
    {
        return x1 + x2;
    }
}

public int Calculate(Func<int, int, int> c)
{
    return c(10, 20);
}

public int CallCalculate()
{
    return Calculate(<>c.<>9__1_0 ?? (<>c.<>9__1_0 = new Func<int, int, int>(<>c.<>9.<CallCalculate>b__1_0)));
}

Is inline lambda possible? Like this:

public int Calculate()
{
 return 10 + 20;   
}

public int CallCalculate() 
{
 return Calculate();   
}

category:cq theme:inlining skill-level:expert cost:large

am11 commented 1 year ago

44610 is planned for 8.0. @EgorBo, does #44610 cover these kind of (simple callback) calls for inlining?

current codegen: https://godbolt.org/z/Wc56zrcoq

EgorBo commented 1 year ago

44610 is planned for 8.0. @EgorBo, does #44610 cover these kind of (simple callback) calls for inlining?

current codegen: https://godbolt.org/z/Wc56zrcoq

I think the current plan is to rely on guarded devirtualization for delegates for such things. Pure inlining is complicated because of that cache machinery Roslyn emits - hard to track types.

am11 commented 1 year ago

Ah, I see. Perhaps in some future milestone, linker (or some other pre-processing step) can turn Func and Action into regular methods; at least for simple / non-capturing cases? Couple of attributes in IL are emitted to identify the compiler-generated machinery (more can be added if needed to disambiguate the patterns).

For reference, C++ lambdas: https://godbolt.org/z/b4GThT8z6 and Swift closures: https://godbolt.org/z/8jf1jxq38 get CallCalculate optimized to return 30.