diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 8f5713774890e7..432db3b0426d2b 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -12661,8 +12661,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) // Skip optimization if non-NEG operand is constant. // Both op1 and op2 are not constant because it was already checked above. - if (opts.OptimizationEnabled() && fgGlobalMorph && - (((op1->gtFlags & GTF_EXCEPT) == 0) || ((op2->gtFlags & GTF_EXCEPT) == 0))) + if (opts.OptimizationEnabled() && fgGlobalMorph) { // a - -b = > a + b // SUB(a, (NEG(b)) => ADD(a, b) @@ -12687,7 +12686,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) // -a - -b = > b - a // SUB(NEG(a), (NEG(b)) => SUB(b, a) - if (op1->OperIs(GT_NEG) && op2->OperIs(GT_NEG)) + if (op1->OperIs(GT_NEG) && op2->OperIs(GT_NEG) && gtCanSwapOrder(op1, op2)) { // tree: SUB // op1: NEG @@ -12886,15 +12885,14 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) } } - if (opts.OptimizationEnabled() && fgGlobalMorph && - (((op1->gtFlags & GTF_EXCEPT) == 0) || ((op2->gtFlags & GTF_EXCEPT) == 0))) + if (opts.OptimizationEnabled() && fgGlobalMorph) { // - a + b = > b - a // ADD((NEG(a), b) => SUB(b, a) // Skip optimization if non-NEG operand is constant. - if (op1->OperIs(GT_NEG) && !op2->OperIs(GT_NEG) && - !(op2->IsCnsIntOrI() && varTypeIsIntegralOrI(typ))) + if (op1->OperIs(GT_NEG) && !op2->OperIs(GT_NEG) && !op2->IsIntegralConst() && + gtCanSwapOrder(op1, op2)) { // tree: ADD // op1: NEG diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_55140/Runtime_55140.cs b/src/tests/JIT/Regression/JitBlue/Runtime_55140/Runtime_55140.cs new file mode 100644 index 00000000000000..220d40aa87750a --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_55140/Runtime_55140.cs @@ -0,0 +1,43 @@ +using System; +using System.Runtime.CompilerServices; + +public class Runtime_55140 +{ + private static int _value; + + public static int Main() + { + _value = 100; + if (TestSubNegNeg() is not 1 and var subNegNeg) + { + Console.WriteLine($"TestSubNegNeg returned: {subNegNeg}. Expected: 1"); + return 101; + } + + _value = 100; + if (TestAddNeg() is not 1 and var addNeg) + { + Console.WriteLine($"TestAddNeg returned: {addNeg}. Expected: 1"); + return 102; + } + + return 100; + } + + // Test that the ADD(NEG(a), b) => SUB(b, a) transform does not reorder persistent side effects. + [MethodImpl(MethodImplOptions.NoInlining)] + private static int TestAddNeg() + { + return -Increment() + _value; + } + + // Test that the SUB(NEG(a), NEG(b)) => SUB(b, a) transform does not reorder persistent side effects. + [MethodImpl(MethodImplOptions.NoInlining)] + private static int TestSubNegNeg() + { + return -Increment() - -_value; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static int Increment() => _value++; +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_55140/Runtime_55140.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_55140/Runtime_55140.csproj new file mode 100644 index 00000000000000..f3e1cbd44b4041 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_55140/Runtime_55140.csproj @@ -0,0 +1,12 @@ + + + Exe + + + None + True + + + + +