diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index de5f6d0bdd298..668e7227871c4 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -14397,8 +14397,12 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) case GT_NOT: case GT_NEG: - // Remove double negation/not - if (op1->OperIs(oper) && opts.OptimizationEnabled()) + // Remove double negation/not. + // Note: this is not a safe tranformation if "tree" is a CSE candidate. + // Consider for example the following expression: NEG(NEG(OP)), where the top-level + // NEG is a CSE candidate. Were we to morph this to just OP, CSE would fail to find + // the original NEG in the statement. + if (op1->OperIs(oper) && opts.OptimizationEnabled() && !gtIsActiveCSE_Candidate(tree)) { GenTree* child = op1->AsOp()->gtGetOp1(); return child; diff --git a/src/tests/JIT/opt/CSE/CSEWithDoubleNegation.cs b/src/tests/JIT/opt/CSE/CSEWithDoubleNegation.cs new file mode 100644 index 0000000000000..d157d14a282cc --- /dev/null +++ b/src/tests/JIT/opt/CSE/CSEWithDoubleNegation.cs @@ -0,0 +1,34 @@ +// 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 CSEWithDoubleNegation +{ + class DoNotMorphAwayCSEThatRepresentsDoubleNegation + { + private static int _static = 0; + + static int Main(string[] args) + { + if (DoubleNeg() != 22) + { + Console.WriteLine("DoubleNeg() failed to return the expected value of 22"); + return -1; + } + + return 100; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static int DoubleNeg() + { + var a = 21; + _static = 42; + + return 43 - (0 - (a - _static)); + } + } +} + diff --git a/src/tests/JIT/opt/CSE/CSEWithDoubleNegation.csproj b/src/tests/JIT/opt/CSE/CSEWithDoubleNegation.csproj new file mode 100644 index 0000000000000..075001135d548 --- /dev/null +++ b/src/tests/JIT/opt/CSE/CSEWithDoubleNegation.csproj @@ -0,0 +1,12 @@ + + + Exe + + + None + True + + + + +