Fix incorrect cast in gtFoldExprConst
authorMike Danes <onemihaid@hotmail.com>
Sat, 4 Feb 2017 10:14:54 +0000 (12:14 +0200)
committerMike Danes <onemihaid@hotmail.com>
Fri, 24 Feb 2017 19:56:41 +0000 (21:56 +0200)
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

src/coreclr/src/jit/gentree.cpp

index 7af500f..539df23 100644 (file)
@@ -13410,15 +13410,10 @@ GenTreePtr Compiler::gtFoldExprConst(GenTreePtr tree)
 #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