dotnet / runtime

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

JIT: Hoist invariant interface method lookups out of loops #6558

Open JosephTremoulet opened 8 years ago

JosephTremoulet commented 8 years ago

When all of the arguments of an interface call are invariant w.r.t. a containing loop, the jit could rewrite the interface call as a call to CORINFO_HELP_VIRTUAL_FUNC_PTR to fetch the function pointer followed by an indirect call on that pointer; the helper call could then be hoisted from the loop. This would remove a couple levels of indirection (i.e. dereferencing the cell, jumping to the thunk, verifying in the thunk that the callsite is monomorphic, and dereferencing the cached function pointer) per loop iteration. I presume that this would have to be weighed against the cost of redoing the lookup on each invocation of the method being compiled, which (if I understand our thunk calls correctly) would otherwise have its result cached across invocations.

[I'm migrating an optimization suggestion from Connect to GitHub]

category:cq theme:loop-opt skill-level:expert cost:medium

JosephTremoulet commented 8 years ago

Correction: the arguments to the interface call don't all need to be invariant, just the instance pointer (or more precisely its exact run-time type).

mikedn commented 7 years ago

When I originally posted this issue to Connect I was thinking that it could help with enumerators and small loops, where the relative cost of calling MoveNext/Current through an interface is significant. See dotnet/coreclr#8481 for an example that doesn't involve enumerators and has more complex code. The issue is about sort calling a delegate via an interface method but then it turned out that doing exactly the opposite is good either way because interface calls are slower than delegate calls.