-
Notifications
You must be signed in to change notification settings - Fork 789
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Nop IL instructions in release code #6026
Comments
Hilarious workaround 😂 Any chance you could send 2 PRs? |
@forki I could, but I honestly not sure which way to fix it is better. Fix 1: Remove these 2 lines as a whole. C# seems not care too much about Fix 2: |
Does C# add |
@ForNeVeR C# indeed generates using System;
namespace ConsoleApp19
{
struct Foo { }
abstract class Bar
{
public abstract void bar(ref Foo foo);
}
class RealBar : Bar
{
public override void bar(ref Foo foo)
{
bar(ref foo);
}
}
class Program
{
static int Main(string[] args)
{
var a = new Foo();
var bar = new RealBar();
bar.bar(ref a);
return 0;
}
}
} |
AFAIK the reason for the nops is so that you can set a breakpoint on lines that otherwise dont map to an instruction (e.g. closing braces) |
question: is there any benefit from any |
no benefits. They are useful for placing breakpoints. And because they are wasting cycles they should be eliminated from optimized builds.
they should |
@forki, no, not in IL, but in native code opcodes it's common, and usually used to machine-word-align instructions or improve pipelining hints to the CPU. There maybe other cases, but in IL itself I doubt it's useful, let alone that it needs instruction alignment. |
Yeah, this is more of a bug that this happens. It should only be for debug. |
I'm in two minds about this.
However in practice there appear to be JIT optimizations which are sensitive to the presence of nop, so I guess we can remove them from release code on that basis. |
Based on the earlier comment on importer it seems that nops only imported in debug code (search CEE_NOP in the code): https://github.com/dotnet/runtime/blob/857b2db411741ee57bfe24da58f77e6e124aa110/src/coreclr/src/jit/importer.cpp#L16345 |
Closing this out as generating NOP for breakpoints etc. is not a problem |
FSC generates
nop
instructions after void calls because of thishttps://github.com/fsharp/fsharp/blob/6819e1c769269edefcea2263c98f993e90b623e2/src/fsharp/IlxGen.fs#L2702
But he also continues to do so even in release configuration!
Repro steps
dotnet run -c Release
Attached project
ConsoleApp18.zip
Expected behavior
There shouldn't be nop instructions in IL (this is Release config)
And as neat side effect it should be JIT-friendly to be optimized by JIT and run forever without Stack Overflow. (
callvirt
just beforeret
)bar.bar
should be like this:Actual behavior
Nop
instruction after every void callJIT can't optimize this pattern:
and everything fails with SO
bar.bar
looks like this:Known workarounds
Adding
<DebugType>ByDesign</DebugType>
fixes the issue.Why? Glad you asked.
Because
SetDebugSwitch
method fails horribly on this line withByDesign
switch (also withnone
butByDesign
is better)https://github.com/fsharp/fsharp/blob/6819e1c769269edefcea2263c98f993e90b623e2/src/fsharp/CompileOptions.fs#L480
and doesn't execute this line
tcConfigB.debuginfo <- s = OptionSwitch.On
This fixes everything (but breaks something else).
nop
instructions won't be emited.Related information
Provide any related information
The text was updated successfully, but these errors were encountered: