Skip to content

Commit 69d0f0c

Browse files
authored
[JIT] X64/ARM64 - Fold 'x & 255' and 'x & 65535' to a cast (#79630)
* Fold 'x & 256' and 'x & 65535' * Remove comments * Handle more cases * Minor change * Put header back * Some refactoring * Minor change * Minor change * Feedback
1 parent db28821 commit 69d0f0c

File tree

2 files changed

+105
-0
lines changed

2 files changed

+105
-0
lines changed

src/coreclr/jit/gentree.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13485,6 +13485,30 @@ GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
1348513485
return icon;
1348613486
};
1348713487

13488+
auto NewZeroExtendNode = [&](var_types type, GenTree* op1, var_types castToType) -> GenTree* {
13489+
assert(varTypeIsIntegral(type));
13490+
assert(!varTypeIsSmall(type));
13491+
assert(!varTypeIsUnsigned(type));
13492+
assert(varTypeIsUnsigned(castToType));
13493+
13494+
GenTreeCast* cast = gtNewCastNode(TYP_INT, op1, false, castToType);
13495+
if (fgGlobalMorph)
13496+
{
13497+
fgMorphTreeDone(cast);
13498+
}
13499+
13500+
if (type == TYP_LONG)
13501+
{
13502+
cast = gtNewCastNode(TYP_LONG, cast, true, TYP_LONG);
13503+
if (fgGlobalMorph)
13504+
{
13505+
fgMorphTreeDone(cast);
13506+
}
13507+
}
13508+
13509+
return cast;
13510+
};
13511+
1348813512
// Here `op` is the non-constant operand, `cons` is the constant operand
1348913513
// and `val` is the constant value.
1349013514

@@ -13641,6 +13665,21 @@ GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
1364113665
goto DONE_FOLD;
1364213666
}
1364313667
}
13668+
else if (val == 0xFF)
13669+
{
13670+
op = NewZeroExtendNode(tree->TypeGet(), op, TYP_UBYTE);
13671+
goto DONE_FOLD;
13672+
}
13673+
else if (val == 0xFFFF)
13674+
{
13675+
op = NewZeroExtendNode(tree->TypeGet(), op, TYP_USHORT);
13676+
goto DONE_FOLD;
13677+
}
13678+
else if ((val == 0xFFFFFFFF) && varTypeIsLong(tree))
13679+
{
13680+
op = NewZeroExtendNode(tree->TypeGet(), op, TYP_UINT);
13681+
goto DONE_FOLD;
13682+
}
1364413683
else
1364513684
{
1364613685
/* The GTF_BOOLEAN flag is set for nodes that are part

src/tests/JIT/opt/Remainder/IntRemainder.cs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace CodeGenTests
99
static class IntRemainder
1010
{
1111
static int _fieldValue = 123;
12+
static uint _fieldValueUnsigned = 123;
1213

1314
[MethodImpl(MethodImplOptions.NoInlining)]
1415
static int Int32_RemainderByOne()
@@ -32,6 +33,56 @@ static int Int32_RemainderByOneWithValue(int value)
3233
return value % 1;
3334
}
3435

36+
[MethodImpl(MethodImplOptions.NoInlining)]
37+
static byte Byte_RemainderByMaxValuePlusOne(uint value)
38+
{
39+
// X64-NOT: and {{[a-z]+}}
40+
41+
// X64: movzx {{[a-z]+}}, {{[a-z]+}}
42+
43+
return (byte)(value % (Byte.MaxValue + 1));
44+
}
45+
46+
[MethodImpl(MethodImplOptions.NoInlining)]
47+
static ushort UInt16_RemainderByMaxValuePlusOne(uint value)
48+
{
49+
// X64-NOT: and {{[a-z]+}}
50+
51+
// X64: movzx {{[a-z]+}}, {{[a-z]+}}
52+
53+
return (ushort)(value % (UInt16.MaxValue + 1));
54+
}
55+
56+
[MethodImpl(MethodImplOptions.NoInlining)]
57+
static uint Byte_RemainderByMaxValuePlusOne_Return_UInt32(uint value)
58+
{
59+
// X64-NOT: and {{[a-z]+}}
60+
61+
// X64: movzx {{[a-z]+}}, {{[a-z]+}}
62+
63+
return (value % (Byte.MaxValue + 1));
64+
}
65+
66+
[MethodImpl(MethodImplOptions.NoInlining)]
67+
static uint UInt16_RemainderByMaxValuePlusOne_Return_UInt32(uint value)
68+
{
69+
// X64-NOT: and {{[a-z]+}}
70+
71+
// X64: movzx {{[a-z]+}}, {{[a-z]+}}
72+
73+
return (value % (UInt16.MaxValue + 1));
74+
}
75+
76+
[MethodImpl(MethodImplOptions.NoInlining)]
77+
static byte Byte_RemainderByMaxValuePlusOne_WithField()
78+
{
79+
// X64-NOT: and {{[a-z]+}}
80+
81+
// X64: movzx {{[a-z]+}}, {{[a-z]+}}
82+
83+
return (byte)(_fieldValueUnsigned % (Byte.MaxValue + 1));
84+
}
85+
3586
static int Main()
3687
{
3788
if (Int32_RemainderByOne() != 0)
@@ -40,6 +91,21 @@ static int Main()
4091
if (Int32_RemainderByOneWithValue(-123) != 0)
4192
return 0;
4293

94+
if (Byte_RemainderByMaxValuePlusOne(68000) != 160)
95+
return 0;
96+
97+
if (UInt16_RemainderByMaxValuePlusOne(68000) != 2464)
98+
return 0;
99+
100+
if (Byte_RemainderByMaxValuePlusOne_Return_UInt32(68000) != 160)
101+
return 0;
102+
103+
if (UInt16_RemainderByMaxValuePlusOne_Return_UInt32(68000) != 2464)
104+
return 0;
105+
106+
if (Byte_RemainderByMaxValuePlusOne_WithField() != 123)
107+
return 0;
108+
43109
return 100;
44110
}
45111
}

0 commit comments

Comments
 (0)