[vm] Don't emit graph body when intrinsification is complete.

Flutter Gallery:
Instructions(CodeSize): -1.36%
Total(CodeSize): -0.87%

Change-Id: I40b8e0a5a73373993961e357b4cab9a78936332a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99162
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
Commit-Queue: Samir Jindel <sjindel@google.com>
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index b59a7fc..9e5377b 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -560,6 +560,14 @@
     StatsEnd(entry);
     pending_deoptimization_env_ = NULL;
     EndCodeSourceRange(entry->token_pos());
+
+    // The function was fully intrinsified, so there's no need to generate any
+    // more code.
+    if (fully_intrinsified_) {
+      ASSERT(entry == flow_graph().graph_entry()->normal_entry());
+      break;
+    }
+
     // Compile all successors until an exit, branch, or a block entry.
     for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
       Instruction* instr = it.Current();
@@ -1163,6 +1171,14 @@
 
 // Returns 'true' if regular code generation should be skipped.
 bool FlowGraphCompiler::TryIntrinsify() {
+  if (TryIntrinsifyHelper()) {
+    fully_intrinsified_ = true;
+    return true;
+  }
+  return false;
+}
+
+bool FlowGraphCompiler::TryIntrinsifyHelper() {
   Label exit;
   set_intrinsic_slow_path_label(&exit);
 
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index 435de9a..56046747 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -817,6 +817,7 @@
 
   void EmitFrameEntry();
 
+  bool TryIntrinsifyHelper();
   void AddPcRelativeCallTarget(const Function& function,
                                Code::EntryKind entry_kind);
   void AddPcRelativeCallStubTarget(const Code& stub_code);
@@ -1030,6 +1031,7 @@
   // True while emitting intrinsic code.
   bool intrinsic_mode_;
   Label* intrinsic_slow_path_label_ = nullptr;
+  bool fully_intrinsified_ = false;
   CodeStatistics* stats_;
 
   const Class& double_class_;
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index 684ca5a..04a4a85 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -943,8 +943,11 @@
   VisitBlocks();
 
   __ bkpt(0);
-  ASSERT(assembler()->constant_pool_allowed());
-  GenerateDeferredCode();
+
+  if (!fully_intrinsified_) {
+    ASSERT(assembler()->constant_pool_allowed());
+    GenerateDeferredCode();
+  }
 }
 
 void FlowGraphCompiler::GenerateCall(TokenPosition token_pos,
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index 20c7f57..192a903 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -932,8 +932,11 @@
   VisitBlocks();
 
   __ int3();
-  ASSERT(assembler()->constant_pool_allowed());
-  GenerateDeferredCode();
+
+  if (!fully_intrinsified_) {
+    ASSERT(assembler()->constant_pool_allowed());
+    GenerateDeferredCode();
+  }
 }
 
 void FlowGraphCompiler::GenerateCall(TokenPosition token_pos,
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index c65e75e..4af0220 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -3766,14 +3766,11 @@
       compiler->SpecialStatsEnd(CombinedCodeStatistics::kTagCheckedEntry);
     }
   }
-  // NOTE: Because in JIT X64/ARM mode the graph can have multiple
-  // entrypoints, so we generate several times the same intrinsification &
-  // frame setup.  That's why we cannot rely on the constant pool being
-  // `false` when we come in here.
+  // NOTE: Because in X64/ARM mode the graph can have multiple entrypoints, we
+  // generate several times the same intrinsification & frame setup. That's why
+  // we cannot rely on the constant pool being `false` when we come in here.
   __ set_constant_pool_allowed(false);
-  // TODO(#34162): Don't emit more code if 'TryIntrinsify' returns 'true'
-  // (meaning the function was fully intrinsified).
-  compiler->TryIntrinsify();
+  if (compiler->TryIntrinsify()) return;
   compiler->EmitPrologue();
   ASSERT(__ constant_pool_allowed());
 #endif