The fact that an operation is unsigned affects the operation itself but that doesn't mean that the result of the operation is also unsigned. Constants are stored as ssize_t and the node type is TYP_INT so the result has to be sign extended, not zero extended.
Otherwise code that uses the return of IconValue() without first narrowing it to int will behave incorrectly. Such code does exists, even gtFoldExprConst does this when folding shift operations:
uint a = uint.MaxValue;
uint b = 0;
int r = (int)checked(a + b);
Console.WriteLine((r >> 2).ToString("X"));
The above code prints
3FFFFFFF instead of the expected
FFFFFFFF.
This also makes gtFoldExprConst consistent with ValueNumStore::EvalFuncForConstantArgs which evaluates TYP_INT nodes as int and then casts to ssize_t.
Commit migrated from https://github.com/dotnet/coreclr/commit/
176e2c7964846bf5dea22557f0828475deac05e1
#endif
#ifdef _TARGET_64BIT_
- // we need to properly re-sign-extend or truncate as needed.
- if (tree->gtFlags & GTF_UNSIGNED)
- {
- i1 = UINT32(i1);
- }
- else
- {
- i1 = INT32(i1);
- }
+ // Some operations are performed as 64 bit instead of 32 bit so the upper 32 bits
+ // need to be discarded. Since constant values are stored as ssize_t and the node
+ // has TYP_INT the result needs to be sign extended rather than zero extended.
+ i1 = INT32(i1);
#endif // _TARGET_64BIT_
/* Also all conditional folding jumps here since the node hanging from