[vm/compiler] Optimize 'double == int' in AOT

TEST=vm/cc/IRTest_DoubleEqualsSmi
Fixes https://github.com/dart-lang/sdk/issues/47031

Change-Id: I6395ae50806b238971872b375c495962cb868cb1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/212484
Reviewed-by: Slava Egorov <vegorov@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
diff --git a/runtime/vm/compiler/aot/aot_call_specializer.cc b/runtime/vm/compiler/aot/aot_call_specializer.cc
index 8a0978b..6fa1d01 100644
--- a/runtime/vm/compiler/aot/aot_call_specializer.cc
+++ b/runtime/vm/compiler/aot/aot_call_specializer.cc
@@ -602,7 +602,7 @@
       case Token::kNE: {
         // TODO(dartbug.com/32166): Support EQ, NE for nullable doubles.
         // (requires null-aware comparison instruction).
-        if (left_type->IsDouble() && right_type->IsDouble()) {
+        if (!left_type->is_nullable() && !right_type->is_nullable()) {
           left_value = PrepareStaticOpInput(left_value, kDoubleCid, instr);
           right_value = PrepareStaticOpInput(right_value, kDoubleCid, instr);
           replacement = new (Z) EqualityCompareInstr(
diff --git a/runtime/vm/compiler/backend/il_test.cc b/runtime/vm/compiler/backend/il_test.cc
index 260d17d..d373a1a 100644
--- a/runtime/vm/compiler/backend/il_test.cc
+++ b/runtime/vm/compiler/backend/il_test.cc
@@ -604,4 +604,33 @@
   RANGES_CONTAIN_EXPECTED_CIDS(abstract_range, expected_cids);
 }
 
+// This test verifies that double == Smi is recognized and
+// implemented using EqualityCompare.
+// Regression test for https://github.com/dart-lang/sdk/issues/47031.
+ISOLATE_UNIT_TEST_CASE(IRTest_DoubleEqualsSmi) {
+  const char* kScript = R"(
+    bool foo(double x) => (x + 0.5) == 0;
+    main() {
+      foo(-0.5);
+    }
+  )";
+
+  const auto& root_library = Library::Handle(LoadTestScript(kScript));
+  const auto& function = Function::Handle(GetFunction(root_library, "foo"));
+
+  TestPipeline pipeline(function, CompilerPass::kAOT);
+  FlowGraph* flow_graph = pipeline.RunPasses({});
+
+  auto entry = flow_graph->graph_entry()->normal_entry();
+  ILMatcher cursor(flow_graph, entry, /*trace=*/true,
+                   ParallelMovesHandling::kSkip);
+
+  RELEASE_ASSERT(cursor.TryMatch({
+      kMoveGlob,
+      kMatchAndMoveBinaryDoubleOp,
+      kMatchAndMoveEqualityCompare,
+      kMatchReturn,
+  }));
+}
+
 }  // namespace dart