JIT: Remove double-{negation,not} in during morph phase (#32000)
authordamageboy <125730+damageboy@users.noreply.github.com>
Thu, 24 Sep 2020 23:20:09 +0000 (02:20 +0300)
committerGitHub <noreply@github.com>
Thu, 24 Sep 2020 23:20:09 +0000 (16:20 -0700)
- fixes #13647
- Deals with arithmetic negation as well as bitwise-not
- Co-authored with @EgorBo holding my hand :)

src/coreclr/src/jit/morph.cpp
src/tests/JIT/opt/perf/doublenegate/doublenegate.cs [new file with mode: 0644]
src/tests/JIT/opt/perf/doublenegate/doublenegate.csproj [new file with mode: 0644]

index 6b75dad..e855cc4 100644 (file)
@@ -13585,6 +13585,12 @@ DONE_MORPHING_CHILDREN:
 
         case GT_NOT:
         case GT_NEG:
+            // Remove double negation/not
+            if (op1->OperIs(oper) && opts.OptimizationEnabled())
+            {
+                GenTree* child = op1->AsOp()->gtGetOp1();
+                return child;
+            }
 
             /* Any constant cases should have been folded earlier */
             noway_assert(!op1->OperIsConst() || !opts.OptEnabled(CLFLG_CONSTANTFOLD) || optValnumCSE_phase);
diff --git a/src/tests/JIT/opt/perf/doublenegate/doublenegate.cs b/src/tests/JIT/opt/perf/doublenegate/doublenegate.cs
new file mode 100644 (file)
index 0000000..73deee1
--- /dev/null
@@ -0,0 +1,81 @@
+using System;
+using System.Runtime.CompilerServices;
+
+namespace coreclr_test_13647
+{
+    class doublenegate
+    {
+        static int _dummyValueInt = 6;
+        static double _dummyValueDouble = 6.0;
+
+        static int Main(string[] args)
+        {
+            if (Test1() && Test2() && Test3()) {
+                Console.WriteLine("PASSED");
+                return 100;
+            }
+            Console.WriteLine("FAILED");
+            return 1;
+        }
+
+        static bool Test1()
+        {
+            var x = DoubleNegationInt(6);
+            var y = 
+                DoubleNegationInt(
+                    DoubleNegationInt(
+                        DoubleNegationInt(x)));
+            var z = DoubleNegationInt(_dummyValueInt);
+
+           if (x == 6 && y == 6 && z == 6)
+                return true;
+            return false;
+        }       
+
+        [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
+        static int NegationInt(int value) => -value;
+
+        [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
+        static int DoubleNegationInt(int value) => NegationInt(NegationInt(value));
+
+        static bool Test2()
+        {
+            var x = DoubleNegationDouble(6.0);
+            var y = 
+                DoubleNegationDouble(
+                    DoubleNegationDouble(
+                        DoubleNegationDouble(x)));
+            var z = DoubleNegationDouble(_dummyValueDouble);
+
+            if (x == 6.0 && y == 6.0 && z == 6.0)
+                return true;
+            return false;
+        }       
+
+        [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
+        static double NegationDouble(double value) => -value;
+
+        [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
+        static double DoubleNegationDouble(double value) => NegationDouble(NegationDouble(value));
+
+        static bool Test3()
+        {
+            var x = DoubleNotInt(6);
+            var y = 
+                DoubleNotInt(
+                    DoubleNotInt(
+                        DoubleNotInt(x)));
+            var z = DoubleNotInt(_dummyValueInt);
+
+           if (x == 6 && y == 6 && z == 6)
+                return true;
+            return false;
+        }       
+
+        [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
+        static int NotInt(int value) => ~value;
+
+        [MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
+        static int DoubleNotInt(int value) => NotInt(NotInt(value));
+    }
+}
diff --git a/src/tests/JIT/opt/perf/doublenegate/doublenegate.csproj b/src/tests/JIT/opt/perf/doublenegate/doublenegate.csproj
new file mode 100644 (file)
index 0000000..dec2a36
--- /dev/null
@@ -0,0 +1,11 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <DebugType>None</DebugType>
+  </PropertyGroup>
+  <PropertyGroup>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="doublenegate.cs" />
+  </ItemGroup>
+</Project>