-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Incorrect IND(ADDR(LCL_VAR)) folding when types do not match #620
Comments
@dotnet/jit-contrib |
LHS version of the above: static unsafe void Test(short a, int b)
{
short c = (short)(a * 2);
*((ushort*)&c) = (ushort)(a * b);
Console.WriteLine(c);
} generates: 480FBFC9 movsx rcx, cx
0FAFCA imul ecx, edx
0FB7C9 movzx rcx, cx
E8ADFCFFFF call System.Console:WriteLine(int) and prints 65535. This is clearly incorrect as the value of a Despite the similarity with the RHS version of the bug, this might require a different fix. The pre-morph tree is:
Note that if the LHS was a Post-morph the tree becomes:
So the problem is the missing normalize on store cast, that would have to be somehow added if we want to continue folding the LHS. And the fun part is that in this case the signed/unsigned difference the comment talks about can't even be detected - the LHS indir has type |
And if Roslyn wouldn't generate that narrowing cast then you could make this print ever larger values because the narrowing effect of the
So |
Unrelated to this bug but since it's in the same area I'll included this here for completness: unsafe struct Arr
{
public int len;
public fixed byte a1[65536];
}
[MethodImpl(MethodImplOptions.NoInlining)]
static unsafe void Test(short a, int b)
{
Arr r = default;
Console.WriteLine(r.a1[65535]);
} The tree is:
Morph code checks if the runtime/src/coreclr/src/jit/morph.cpp Line 12944 in f621f44
but then fails to check if the sum of the ADD offset and LCL_FLD also fits in 16 bit:runtime/src/coreclr/src/jit/morph.cpp Line 13010 in f621f44
So why doesn't the assert in runtime/src/coreclr/src/jit/morph.cpp Lines 12989 to 12991 in f621f44
This tries to use the indir type to determine the size of the lclvar and thus wrongly concludes that the var size is 1 ( |
Another case: [MethodImpl(MethodImplOptions.NoInlining)]
static unsafe int Test(short a, int b)
{
short c = (short)(a * 2);
Unsafe.As<short, Bytes>(ref c).hi = (byte)b;
Console.WriteLine(c);
return c;
} Prints -65026 which again is out of The original tree is:
and it becomes:
The problem is that the variable is "normalize on store" but no normalization is done when such a partial update occurs. We'll probably need to mark the variable "address exposed" just to force it to be "normalize on load". Not ideal but then this is such a corner case that it's unlikely to matter. |
Fixed by #40535 |
I was looking at reimplementing this kind of folding in
LocalAddressVisitor
and ran into this morph code:runtime/src/coreclr/src/jit/morph.cpp
Lines 12859 to 12870 in f621f44
I don't think that "signed/unsigned differences won't matter":
generates
and prints [edit] -2. The result is obviously incorrect,
ushort / 1
can't ever be negative.category:correctness
theme:morph
skill-level:intermediate
cost:medium
The text was updated successfully, but these errors were encountered: