runtime: RyuJit: Functions with stackalloc won't inline
Functions using stackalloc will fail to inline with reason unknown opcode
Discovered this as part of this PR https://github.com/davidfowl/Channels/pull/145 (should have probably raised it then)
Example function that will fail to inline even with aggressive inlinining
public unsafe bool TrySliceTo(byte b1, byte b2, out ReadableBuffer slice, out ReadCursor cursor)
{
byte* twoBytes = stackalloc byte[2];
twoBytes[0] = b1;
twoBytes[1] = b2;
return TrySliceTo(new Span<byte>(twoBytes, 2), out slice, out cursor);
}
Changed function that will inline successfully without aggressive inlinining
public unsafe bool TrySliceTo(byte b1, byte b2, out ReadableBuffer slice, out ReadCursor cursor)
{
// use address of ushort rather than stackalloc as the inliner won't inline functions with stackalloc
ushort twoBytes;
byte* byteArray = (byte*)&twoBytes;
byteArray[0] = b1;
byteArray[1] = b2;
return TrySliceTo(new Span<byte>(byteArray, 2), out slice, out cursor);
}
/cc @AndyAyersMS @JosephTremoulet category:cq theme:inlining skill-level:expert cost:medium
About this issue
- Original URL
- State: open
- Created 8 years ago
- Reactions: 1
- Comments: 22 (22 by maintainers)
Sure, dotnet/coreclr#8542.
Undoing stackalloc has always been something of a pipe dream – I don’t know of any native compilers that do it either.
Aside from getting the mechanical aspects right, the undo point creates a barrier to code motion that can be hard for the compiler to model and reason about (similar to what happens with pinning). And there is an EH aspect to consider too… we’d likely need to induce a try/finally to ensure that the undo always happened.
There are challenges inlining methods with
stackalloc, primarily because there is nounstackalloc. Inlining such methods can convert cases that do not overflow the stack into cases that do.C/C++compilers have similar limitations inlining methods with
alloca.We could consider supporting this for aggressive inline methods, perhaps.