[JIT] X64/ARM64 - Fold 'x & 255' and 'x & 65535' to a cast (#79630)
authorWill Smith <lol.tihan@gmail.com>
Thu, 5 Jan 2023 23:23:39 +0000 (15:23 -0800)
committerGitHub <noreply@github.com>
Thu, 5 Jan 2023 23:23:39 +0000 (15:23 -0800)
* Fold 'x & 256' and 'x & 65535'

* Remove comments

* Handle more cases

* Minor change

* Put header back

* Some refactoring

* Minor change

* Minor change

* Feedback

src/coreclr/jit/gentree.cpp
src/tests/JIT/opt/Remainder/IntRemainder.cs

index 117575fbd198f0a42cf457cbba0ebdf3cf51bd21..9cdb7b3406ec554fb4773224919779866da9f97f 100644 (file)
@@ -13485,6 +13485,30 @@ GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
         return icon;
     };
 
+    auto NewZeroExtendNode = [&](var_types type, GenTree* op1, var_types castToType) -> GenTree* {
+        assert(varTypeIsIntegral(type));
+        assert(!varTypeIsSmall(type));
+        assert(!varTypeIsUnsigned(type));
+        assert(varTypeIsUnsigned(castToType));
+
+        GenTreeCast* cast = gtNewCastNode(TYP_INT, op1, false, castToType);
+        if (fgGlobalMorph)
+        {
+            fgMorphTreeDone(cast);
+        }
+
+        if (type == TYP_LONG)
+        {
+            cast = gtNewCastNode(TYP_LONG, cast, true, TYP_LONG);
+            if (fgGlobalMorph)
+            {
+                fgMorphTreeDone(cast);
+            }
+        }
+
+        return cast;
+    };
+
     // Here `op` is the non-constant operand, `cons` is the constant operand
     // and `val` is the constant value.
 
@@ -13641,6 +13665,21 @@ GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
                     goto DONE_FOLD;
                 }
             }
+            else if (val == 0xFF)
+            {
+                op = NewZeroExtendNode(tree->TypeGet(), op, TYP_UBYTE);
+                goto DONE_FOLD;
+            }
+            else if (val == 0xFFFF)
+            {
+                op = NewZeroExtendNode(tree->TypeGet(), op, TYP_USHORT);
+                goto DONE_FOLD;
+            }
+            else if ((val == 0xFFFFFFFF) && varTypeIsLong(tree))
+            {
+                op = NewZeroExtendNode(tree->TypeGet(), op, TYP_UINT);
+                goto DONE_FOLD;
+            }
             else
             {
                 /* The GTF_BOOLEAN flag is set for nodes that are part
index 0783fae3067f816cffd74840f5af99aa627f455a..9112decb62a5c75ad8ef6dbd2e8d46297f184145 100644 (file)
@@ -9,6 +9,7 @@ namespace CodeGenTests
     static class IntRemainder
     {
         static int _fieldValue = 123;
+        static uint _fieldValueUnsigned = 123;
 
         [MethodImpl(MethodImplOptions.NoInlining)]
         static int Int32_RemainderByOne()
@@ -32,6 +33,56 @@ namespace CodeGenTests
             return value % 1;
         }
 
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        static byte Byte_RemainderByMaxValuePlusOne(uint value)
+        {
+            // X64-NOT: and {{[a-z]+}}
+
+            // X64: movzx {{[a-z]+}}, {{[a-z]+}}
+
+            return (byte)(value % (Byte.MaxValue + 1));
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        static ushort UInt16_RemainderByMaxValuePlusOne(uint value)
+        {
+            // X64-NOT: and {{[a-z]+}}
+
+            // X64: movzx {{[a-z]+}}, {{[a-z]+}}
+
+            return (ushort)(value % (UInt16.MaxValue + 1));
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        static uint Byte_RemainderByMaxValuePlusOne_Return_UInt32(uint value)
+        {
+            // X64-NOT: and {{[a-z]+}}
+
+            // X64: movzx {{[a-z]+}}, {{[a-z]+}}
+
+            return (value % (Byte.MaxValue + 1));
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        static uint UInt16_RemainderByMaxValuePlusOne_Return_UInt32(uint value)
+        {
+            // X64-NOT: and {{[a-z]+}}
+
+            // X64: movzx {{[a-z]+}}, {{[a-z]+}}
+
+            return (value % (UInt16.MaxValue + 1));
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        static byte Byte_RemainderByMaxValuePlusOne_WithField()
+        {
+            // X64-NOT: and {{[a-z]+}}
+
+            // X64: movzx {{[a-z]+}}, {{[a-z]+}}
+
+            return (byte)(_fieldValueUnsigned % (Byte.MaxValue + 1));
+        }
+
         static int Main()
         {
             if (Int32_RemainderByOne() != 0)
@@ -40,6 +91,21 @@ namespace CodeGenTests
             if (Int32_RemainderByOneWithValue(-123) != 0)
                 return 0;
 
+            if (Byte_RemainderByMaxValuePlusOne(68000) != 160)
+                return 0;
+
+            if (UInt16_RemainderByMaxValuePlusOne(68000) != 2464)
+                return 0;
+
+            if (Byte_RemainderByMaxValuePlusOne_Return_UInt32(68000) != 160)
+                return 0;
+
+            if (UInt16_RemainderByMaxValuePlusOne_Return_UInt32(68000) != 2464)
+                return 0;
+
+            if (Byte_RemainderByMaxValuePlusOne_WithField() != 123)
+                return 0;
+
             return 100;
         }
     }