diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index 5c1c26150eae19..c4a839fbb4044d 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -998,6 +998,17 @@ void CodeGen::genCodeForBinary(GenTreeOp* treeNode) src = op2; } + // We can skip emitting 'and reg0, -1` if we know that the upper 32bits of 'reg0' are zero'ed. + if (compiler->opts.OptimizationEnabled()) + { + if ((oper == GT_AND) && (targetType == TYP_INT) && !treeNode->gtSetFlags() && op2->IsIntegralConst(-1) && + emit->AreUpper32BitsZero(targetReg)) + { + genProduceReg(treeNode); + return; + } + } + // try to use an inc or dec if (oper == GT_ADD && !varTypeIsFloating(treeNode) && src->isContainedIntOrIImmed() && !treeNode->gtOverflowEx()) { diff --git a/src/tests/JIT/opt/And/IntAnd.cs b/src/tests/JIT/opt/And/IntAnd.cs new file mode 100644 index 00000000000000..80fb37b4e32b19 --- /dev/null +++ b/src/tests/JIT/opt/And/IntAnd.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; + +namespace CodeGenTests +{ + class IntAnd + { + [MethodImpl(MethodImplOptions.NoInlining)] + static uint Test_And_UInt32_MaxValue(uint i) + { + // X64: mov + + // X64-NOT: and + return i & UInt32.MaxValue; + } + + static int Main() + { + if (Test_And_UInt32_MaxValue(1234) != 1234) + return 0; + + return 100; + } + } +} diff --git a/src/tests/JIT/opt/And/IntAnd.csproj b/src/tests/JIT/opt/And/IntAnd.csproj new file mode 100644 index 00000000000000..42a89c8384d74e --- /dev/null +++ b/src/tests/JIT/opt/And/IntAnd.csproj @@ -0,0 +1,17 @@ + + + Exe + + + None + True + + + + true + + + + + +