-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Description
The following example:
[MethodImpl(MethodImplOptions.NoInlining)]
static int Test(sbyte x)
{
return x % 0;
}generates
G_M55886_IG02:
480FBEC1 movsx rax, cl
G_M55886_IG03:
C3 retOf course, this doesn't generate a DivideByZeroException exception as it should.
This is partially caused by a recent change I did that transforms x % c into x - (x / c) * c if c is not a power of 2. 0 is not a power of 2 but the transform should not be done when c is 0. ARM64 appears to do the same transform unconditionally so probably it is also affected by this. I think we should simply transform x % 0 into x / 0.
However, the actual bug is somewhere else. The following IL code triggers it as well:
.method private hidebysig static int32
Test(int8 arg) cil managed noinlining
{
.maxstack 8
ldarg.0
ldarg.0
ldc.i4.0
div
ldc.i4.0
mul
sub
ret
}
The C# compiler doesn't usually produce this kind of code, it drops x * 0. It's that multiplication that's probably mishandled by the JIT, it tries to drop it and sometimes it drops the division as well. When it works correctly the generated code looks like this:
G_M55886_IG02:
480FBEC9 movsx rcx, cl
4533C0 xor r8d, r8d
8BC1 mov eax, ecx
99 cdq
41F7F8 idiv edx:eax, r8d
8BC1 mov eax, ecxI'll look into this.
category:correctness
theme:cse
skill-level:intermediate
cost:medium