Revert "[vm/compiler] Optimize switch statements"

This reverts commit f5228127f8570be359c2645b8c315bfafe9b0ce3.

Reason for revert: causes a VM crash, see b/242964932 (the test is also publicly available at https://github.com/simolus3/drift/blob/93fb0da38a5f33c8db289bfde696b0ca3d401b7f/drift_dev/test/analyzer/sql_queries/query_analyzer_test.dart#L8)

Original change's description:
> [vm/compiler] Optimize switch statements
>
> Switch statements that either contain only integers or only enum values of the same type can be optimized.
>
> Depending on the number of switch expressions and the number of holes that the range of switch expressions contains, either a binary search or a jump table is used.
>
> TEST=runtime/test/vm/dart{,_2}/optimized_switch
> TEST=tests/language{,_2}/switch
>
> Fixes: https://github.com/dart-lang/sdk/issues/49585
>
> Co-authored-by: Gabriel Terwesten gabriel@terwesten.net
>
> Change-Id: I62dcdb7843107f03de7e468c60b4db52ec78f676
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/253787
> Reviewed-by: Alexander Markov <alexmarkov@google.com>
> Commit-Queue: Alexander Markov <alexmarkov@google.com>

TBR=vegorov@google.com,alexmarkov@google.com,gabriel@terwesten.net

Change-Id: I8c673ea70e7ed91dffb3674e7dcb4aaa0611e978
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/255258
Reviewed-by: Slava Egorov <vegorov@google.com>
Reviewed-by: Ilya Yanok <yanok@google.com>
Commit-Queue: Slava Egorov <vegorov@google.com>
diff --git a/runtime/tests/vm/dart/optimized_switch_test.dart b/runtime/tests/vm/dart/optimized_switch_test.dart
deleted file mode 100644
index 9c80033..0000000
--- a/runtime/tests/vm/dart/optimized_switch_test.dart
+++ /dev/null
@@ -1,577 +0,0 @@
-// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Test switches that use binary search or a jump table to dispatch cases.
-
-import 'package:expect/expect.dart';
-
-void main() {
-  Expect.isTrue(duplicateEnum(L._0) == 0);
-  Expect.isTrue(duplicateEnum(L._1) == 1);
-  Expect.isTrue(duplicateEnum(L._2) == 2);
-  Expect.isTrue(duplicateEnum(L._3) == null);
-
-  Expect.isTrue(duplicateInt(0) == 0);
-  Expect.isTrue(duplicateInt(1) == 1);
-  Expect.isTrue(duplicateInt(2) == 2);
-  Expect.isTrue(duplicateInt(3) == null);
-
-  Expect.isTrue(binarySearchEnumExhaustive(S._0) == 0);
-  Expect.isTrue(binarySearchEnumExhaustive(S._1) == 1);
-  Expect.isTrue(binarySearchEnumExhaustive(S._2) == 2);
-
-  Expect.isTrue(binarySearchEnumWithDefault(null) == null);
-  Expect.isTrue(binarySearchEnumWithDefault(S._0) == 0);
-  Expect.isTrue(binarySearchEnumWithDefault(S._1) == null);
-  Expect.isTrue(binarySearchEnumWithDefault(S._2) == 2);
-
-  Expect.isTrue(binarySearchEnumHole(S._0) == 0);
-  Expect.isTrue(binarySearchEnumHole(S._1) == null);
-  Expect.isTrue(binarySearchEnumHole(S._2) == 2);
-
-  Expect.isTrue(binarySearchEnumNoLowerBound(S._0) == null);
-  Expect.isTrue(binarySearchEnumNoLowerBound(S._1) == 1);
-  Expect.isTrue(binarySearchEnumNoLowerBound(S._2) == 2);
-
-  Expect.isTrue(binarySearchEnumNoUpperBound(S._0) == 0);
-  Expect.isTrue(binarySearchEnumNoUpperBound(S._1) == 1);
-  Expect.isTrue(binarySearchEnumNoUpperBound(S._2) == null);
-
-  Expect.isTrue(binarySearchInt(-2) == null);
-  Expect.isTrue(binarySearchInt(-1) == -1);
-  Expect.isTrue(binarySearchInt(0) == 0);
-  Expect.isTrue(binarySearchInt(1) == 1);
-  Expect.isTrue(binarySearchInt(2) == null);
-
-  Expect.isTrue(binarySearchIntWithDefault(null) == null);
-  Expect.isTrue(binarySearchIntWithDefault(-1) == null);
-  Expect.isTrue(binarySearchIntWithDefault(0) == 0);
-  Expect.isTrue(binarySearchIntWithDefault(1) == null);
-  Expect.isTrue(binarySearchIntWithDefault(2) == 2);
-  Expect.isTrue(binarySearchIntWithDefault(3) == null);
-
-  Expect.isTrue(jumpTableEnumExhaustive(L._0) == 0);
-  Expect.isTrue(jumpTableEnumExhaustive(L._1) == 1);
-  Expect.isTrue(jumpTableEnumExhaustive(L._2) == 2);
-  Expect.isTrue(jumpTableEnumExhaustive(L._3) == 3);
-  Expect.isTrue(jumpTableEnumExhaustive(L._4) == 4);
-  Expect.isTrue(jumpTableEnumExhaustive(L._5) == 5);
-  Expect.isTrue(jumpTableEnumExhaustive(L._6) == 6);
-  Expect.isTrue(jumpTableEnumExhaustive(L._7) == 7);
-  Expect.isTrue(jumpTableEnumExhaustive(L._8) == 8);
-  Expect.isTrue(jumpTableEnumExhaustive(L._9) == 9);
-  Expect.isTrue(jumpTableEnumExhaustive(L._10) == 10);
-  Expect.isTrue(jumpTableEnumExhaustive(L._11) == 11);
-  Expect.isTrue(jumpTableEnumExhaustive(L._12) == 12);
-  Expect.isTrue(jumpTableEnumExhaustive(L._13) == 13);
-  Expect.isTrue(jumpTableEnumExhaustive(L._14) == 14);
-  Expect.isTrue(jumpTableEnumExhaustive(L._15) == 15);
-  Expect.isTrue(jumpTableEnumExhaustive(L._16) == 16);
-
-  Expect.isTrue(jumpTableEnumWithDefault(null) == null);
-  Expect.isTrue(jumpTableEnumWithDefault(L._0) == 0);
-  Expect.isTrue(jumpTableEnumWithDefault(L._1) == 1);
-  Expect.isTrue(jumpTableEnumWithDefault(L._2) == 2);
-  Expect.isTrue(jumpTableEnumWithDefault(L._3) == 3);
-  Expect.isTrue(jumpTableEnumWithDefault(L._4) == 4);
-  Expect.isTrue(jumpTableEnumWithDefault(L._5) == 5);
-  Expect.isTrue(jumpTableEnumWithDefault(L._6) == 6);
-  Expect.isTrue(jumpTableEnumWithDefault(L._7) == 7);
-  Expect.isTrue(jumpTableEnumWithDefault(L._8) == null);
-  Expect.isTrue(jumpTableEnumWithDefault(L._9) == 9);
-  Expect.isTrue(jumpTableEnumWithDefault(L._10) == 10);
-  Expect.isTrue(jumpTableEnumWithDefault(L._11) == 11);
-  Expect.isTrue(jumpTableEnumWithDefault(L._12) == 12);
-  Expect.isTrue(jumpTableEnumWithDefault(L._13) == 13);
-  Expect.isTrue(jumpTableEnumWithDefault(L._14) == 14);
-  Expect.isTrue(jumpTableEnumWithDefault(L._15) == 15);
-  Expect.isTrue(jumpTableEnumWithDefault(L._16) == 16);
-
-  Expect.isTrue(jumpTableEnumHole(L._0) == 0);
-  Expect.isTrue(jumpTableEnumHole(L._1) == null);
-  Expect.isTrue(jumpTableEnumHole(L._2) == 2);
-  Expect.isTrue(jumpTableEnumHole(L._3) == 3);
-  Expect.isTrue(jumpTableEnumHole(L._4) == 4);
-  Expect.isTrue(jumpTableEnumHole(L._5) == 5);
-  Expect.isTrue(jumpTableEnumHole(L._6) == 6);
-  Expect.isTrue(jumpTableEnumHole(L._7) == 7);
-  Expect.isTrue(jumpTableEnumHole(L._8) == 8);
-  Expect.isTrue(jumpTableEnumHole(L._9) == 9);
-  Expect.isTrue(jumpTableEnumHole(L._10) == 10);
-  Expect.isTrue(jumpTableEnumHole(L._11) == 11);
-  Expect.isTrue(jumpTableEnumHole(L._12) == 12);
-  Expect.isTrue(jumpTableEnumHole(L._13) == 13);
-  Expect.isTrue(jumpTableEnumHole(L._14) == 14);
-  Expect.isTrue(jumpTableEnumHole(L._15) == 15);
-  Expect.isTrue(jumpTableEnumHole(L._16) == 16);
-
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._0) == null);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._1) == 1);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._2) == 2);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._3) == 3);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._4) == 4);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._5) == 5);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._6) == 6);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._7) == 7);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._8) == 8);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._9) == 9);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._10) == 10);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._11) == 11);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._12) == 12);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._13) == 13);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._14) == 14);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._15) == 15);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._16) == 16);
-
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._0) == 0);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._1) == 1);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._2) == 2);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._3) == 3);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._4) == 4);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._5) == 5);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._6) == 6);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._7) == 7);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._8) == 8);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._9) == 9);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._10) == 10);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._11) == 11);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._12) == 12);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._13) == 13);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._14) == 14);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._15) == 15);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._16) == null);
-
-  Expect.isTrue(jumpTableInt(-2) == null);
-  Expect.isTrue(jumpTableInt(-1) == -1);
-  Expect.isTrue(jumpTableInt(0) == 0);
-  Expect.isTrue(jumpTableInt(1) == 1);
-  Expect.isTrue(jumpTableInt(2) == 2);
-  Expect.isTrue(jumpTableInt(3) == 3);
-  Expect.isTrue(jumpTableInt(4) == 4);
-  Expect.isTrue(jumpTableInt(5) == 5);
-  Expect.isTrue(jumpTableInt(6) == 6);
-  Expect.isTrue(jumpTableInt(7) == 7);
-  Expect.isTrue(jumpTableInt(8) == 8);
-  Expect.isTrue(jumpTableInt(9) == 9);
-  Expect.isTrue(jumpTableInt(10) == 10);
-  Expect.isTrue(jumpTableInt(11) == 11);
-  Expect.isTrue(jumpTableInt(12) == 12);
-  Expect.isTrue(jumpTableInt(13) == 13);
-  Expect.isTrue(jumpTableInt(14) == 14);
-  Expect.isTrue(jumpTableInt(15) == null);
-
-  Expect.isTrue(jumpTableIntWithDefault(null) == null);
-  Expect.isTrue(jumpTableIntWithDefault(-1) == null);
-  Expect.isTrue(jumpTableIntWithDefault(0) == 0);
-  Expect.isTrue(jumpTableIntWithDefault(1) == 1);
-  Expect.isTrue(jumpTableIntWithDefault(2) == 2);
-  Expect.isTrue(jumpTableIntWithDefault(3) == 3);
-  Expect.isTrue(jumpTableIntWithDefault(4) == 4);
-  Expect.isTrue(jumpTableIntWithDefault(5) == 5);
-  Expect.isTrue(jumpTableIntWithDefault(6) == 6);
-  Expect.isTrue(jumpTableIntWithDefault(7) == 7);
-  Expect.isTrue(jumpTableIntWithDefault(8) == null);
-  Expect.isTrue(jumpTableIntWithDefault(9) == 9);
-  Expect.isTrue(jumpTableIntWithDefault(10) == 10);
-  Expect.isTrue(jumpTableIntWithDefault(11) == 11);
-  Expect.isTrue(jumpTableIntWithDefault(12) == 12);
-  Expect.isTrue(jumpTableIntWithDefault(13) == 13);
-  Expect.isTrue(jumpTableIntWithDefault(14) == 14);
-  Expect.isTrue(jumpTableIntWithDefault(15) == 15);
-  Expect.isTrue(jumpTableIntWithDefault(16) == 16);
-  Expect.isTrue(jumpTableIntWithDefault(17) == null);
-}
-
-/// Small enum that is used to test binary search switches.
-enum S {
-  _0,
-  _1,
-  _2,
-}
-
-/// Large enum that is used to test jump table switches.
-///
-/// Must have enough values to trigger a jump table (currently 16) + 1 so
-/// we can create a jump table switch that is not exhaustive.
-enum L {
-  _0,
-  _1,
-  _2,
-  _3,
-  _4,
-  _5,
-  _6,
-  _7,
-  _8,
-  _9,
-  _10,
-  _11,
-  _12,
-  _13,
-  _14,
-  _15,
-  _16,
-}
-
-int? duplicateEnum(L v) {
-  switch (v) {
-    case L._0:
-      return 0;
-    case L._1:
-      return 1;
-    case L._2:
-      return 2;
-    case L._1:
-      return 3;
-  }
-}
-
-int? duplicateInt(int v) {
-  switch (v) {
-    case 0:
-      return 0;
-    case 1:
-      return 1;
-    case 2:
-      return 2;
-    case 1:
-      return 3;
-  }
-}
-
-int binarySearchEnumExhaustive(S v) {
-  switch (v) {
-    case S._0:
-      return 0;
-    case S._1:
-      return 1;
-    case S._2:
-      return 2;
-  }
-}
-
-int? binarySearchEnumWithDefault(S? v) {
-  switch (v) {
-    case S._0:
-      return 0;
-    case S._2:
-      return 2;
-    default:
-      return null;
-  }
-}
-
-int? binarySearchEnumHole(S v) {
-  switch (v) {
-    case S._0:
-      return 0;
-    case S._2:
-      return 2;
-  }
-}
-
-int? binarySearchEnumNoLowerBound(S v) {
-  switch (v) {
-    case S._1:
-      return 1;
-    case S._2:
-      return 2;
-  }
-}
-
-int? binarySearchEnumNoUpperBound(S v) {
-  switch (v) {
-    case S._0:
-      return 0;
-    case S._1:
-      return 1;
-  }
-}
-
-int? binarySearchInt(int v) {
-  switch (v) {
-    case -1:
-      return -1;
-    case 0:
-      return 0;
-    case 1:
-      return 1;
-  }
-}
-
-int? binarySearchIntWithDefault(int? v) {
-  switch (v) {
-    case 0:
-      return 0;
-    case 2:
-      return 2;
-    default:
-      return null;
-  }
-}
-
-int jumpTableEnumExhaustive(L v) {
-  switch (v) {
-    case L._0:
-      return 0;
-    case L._1:
-      return 1;
-    case L._2:
-      return 2;
-    case L._3:
-      return 3;
-    case L._4:
-      return 4;
-    case L._5:
-      return 5;
-    case L._6:
-      return 6;
-    case L._7:
-      return 7;
-    case L._8:
-      return 8;
-    case L._9:
-      return 9;
-    case L._10:
-      return 10;
-    case L._11:
-      return 11;
-    case L._12:
-      return 12;
-    case L._13:
-      return 13;
-    case L._14:
-      return 14;
-    case L._15:
-      return 15;
-    case L._16:
-      return 16;
-  }
-}
-
-int? jumpTableEnumWithDefault(L? v) {
-  switch (v) {
-    case L._0:
-      return 0;
-    case L._1:
-      return 1;
-    case L._2:
-      return 2;
-    case L._3:
-      return 3;
-    case L._4:
-      return 4;
-    case L._5:
-      return 5;
-    case L._6:
-      return 6;
-    case L._7:
-      return 7;
-    case L._9:
-      return 9;
-    case L._10:
-      return 10;
-    case L._11:
-      return 11;
-    case L._12:
-      return 12;
-    case L._13:
-      return 13;
-    case L._14:
-      return 14;
-    case L._15:
-      return 15;
-    case L._16:
-      return 16;
-    default:
-      return null;
-  }
-}
-
-int? jumpTableEnumHole(L v) {
-  switch (v) {
-    case L._0:
-      return 0;
-    case L._2:
-      return 2;
-    case L._3:
-      return 3;
-    case L._4:
-      return 4;
-    case L._5:
-      return 5;
-    case L._6:
-      return 6;
-    case L._7:
-      return 7;
-    case L._8:
-      return 8;
-    case L._9:
-      return 9;
-    case L._10:
-      return 10;
-    case L._11:
-      return 11;
-    case L._12:
-      return 12;
-    case L._13:
-      return 13;
-    case L._14:
-      return 14;
-    case L._15:
-      return 15;
-    case L._16:
-      return 16;
-  }
-}
-
-int? jumpTableEnumNoLowerBound(L v) {
-  switch (v) {
-    case L._1:
-      return 1;
-    case L._2:
-      return 2;
-    case L._3:
-      return 3;
-    case L._4:
-      return 4;
-    case L._5:
-      return 5;
-    case L._6:
-      return 6;
-    case L._7:
-      return 7;
-    case L._8:
-      return 8;
-    case L._9:
-      return 9;
-    case L._10:
-      return 10;
-    case L._11:
-      return 11;
-    case L._12:
-      return 12;
-    case L._13:
-      return 13;
-    case L._14:
-      return 14;
-    case L._15:
-      return 15;
-    case L._16:
-      return 16;
-  }
-}
-
-int? jumpTableEnumNoUpperBound(L v) {
-  switch (v) {
-    case L._0:
-      return 0;
-    case L._1:
-      return 1;
-    case L._2:
-      return 2;
-    case L._3:
-      return 3;
-    case L._4:
-      return 4;
-    case L._5:
-      return 5;
-    case L._6:
-      return 6;
-    case L._7:
-      return 7;
-    case L._8:
-      return 8;
-    case L._9:
-      return 9;
-    case L._10:
-      return 10;
-    case L._11:
-      return 11;
-    case L._12:
-      return 12;
-    case L._13:
-      return 13;
-    case L._14:
-      return 14;
-    case L._15:
-      return 15;
-  }
-}
-
-int? jumpTableInt(int v) {
-  switch (v) {
-    case -1:
-      return -1;
-    case 0:
-      return 0;
-    case 1:
-      return 1;
-    case 2:
-      return 2;
-    case 3:
-      return 3;
-    case 4:
-      return 4;
-    case 5:
-      return 5;
-    case 6:
-      return 6;
-    case 7:
-      return 7;
-    case 8:
-      return 8;
-    case 9:
-      return 9;
-    case 10:
-      return 10;
-    case 11:
-      return 11;
-    case 12:
-      return 12;
-    case 13:
-      return 13;
-    case 14:
-      return 14;
-  }
-}
-
-int? jumpTableIntWithDefault(int? v) {
-  switch (v) {
-    case 0:
-      return 0;
-    case 1:
-      return 1;
-    case 2:
-      return 2;
-    case 3:
-      return 3;
-    case 4:
-      return 4;
-    case 5:
-      return 5;
-    case 6:
-      return 6;
-    case 7:
-      return 7;
-    case 9:
-      return 9;
-    case 10:
-      return 10;
-    case 11:
-      return 11;
-    case 12:
-      return 12;
-    case 13:
-      return 13;
-    case 14:
-      return 14;
-    case 15:
-      return 15;
-    case 16:
-      return 16;
-    default:
-      return null;
-  }
-}
diff --git a/runtime/tests/vm/dart_2/optimized_switch_test.dart b/runtime/tests/vm/dart_2/optimized_switch_test.dart
deleted file mode 100644
index ed63635..0000000
--- a/runtime/tests/vm/dart_2/optimized_switch_test.dart
+++ /dev/null
@@ -1,579 +0,0 @@
-// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart = 2.9
-
-// Test switches that use binary search or a jump table to dispatch cases.
-
-import 'package:expect/expect.dart';
-
-void main() {
-  Expect.isTrue(duplicateEnum(L._0) == 0);
-  Expect.isTrue(duplicateEnum(L._1) == 1);
-  Expect.isTrue(duplicateEnum(L._2) == 2);
-  Expect.isTrue(duplicateEnum(L._3) == null);
-
-  Expect.isTrue(duplicateInt(0) == 0);
-  Expect.isTrue(duplicateInt(1) == 1);
-  Expect.isTrue(duplicateInt(2) == 2);
-  Expect.isTrue(duplicateInt(3) == null);
-
-  Expect.isTrue(binarySearchEnumExhaustive(S._0) == 0);
-  Expect.isTrue(binarySearchEnumExhaustive(S._1) == 1);
-  Expect.isTrue(binarySearchEnumExhaustive(S._2) == 2);
-
-  Expect.isTrue(binarySearchEnumWithDefault(null) == null);
-  Expect.isTrue(binarySearchEnumWithDefault(S._0) == 0);
-  Expect.isTrue(binarySearchEnumWithDefault(S._1) == null);
-  Expect.isTrue(binarySearchEnumWithDefault(S._2) == 2);
-
-  Expect.isTrue(binarySearchEnumHole(S._0) == 0);
-  Expect.isTrue(binarySearchEnumHole(S._1) == null);
-  Expect.isTrue(binarySearchEnumHole(S._2) == 2);
-
-  Expect.isTrue(binarySearchEnumNoLowerBound(S._0) == null);
-  Expect.isTrue(binarySearchEnumNoLowerBound(S._1) == 1);
-  Expect.isTrue(binarySearchEnumNoLowerBound(S._2) == 2);
-
-  Expect.isTrue(binarySearchEnumNoUpperBound(S._0) == 0);
-  Expect.isTrue(binarySearchEnumNoUpperBound(S._1) == 1);
-  Expect.isTrue(binarySearchEnumNoUpperBound(S._2) == null);
-
-  Expect.isTrue(binarySearchInt(-2) == null);
-  Expect.isTrue(binarySearchInt(-1) == -1);
-  Expect.isTrue(binarySearchInt(0) == 0);
-  Expect.isTrue(binarySearchInt(1) == 1);
-  Expect.isTrue(binarySearchInt(2) == null);
-
-  Expect.isTrue(binarySearchIntWithDefault(null) == null);
-  Expect.isTrue(binarySearchIntWithDefault(-1) == null);
-  Expect.isTrue(binarySearchIntWithDefault(0) == 0);
-  Expect.isTrue(binarySearchIntWithDefault(1) == null);
-  Expect.isTrue(binarySearchIntWithDefault(2) == 2);
-  Expect.isTrue(binarySearchIntWithDefault(3) == null);
-
-  Expect.isTrue(jumpTableEnumExhaustive(L._0) == 0);
-  Expect.isTrue(jumpTableEnumExhaustive(L._1) == 1);
-  Expect.isTrue(jumpTableEnumExhaustive(L._2) == 2);
-  Expect.isTrue(jumpTableEnumExhaustive(L._3) == 3);
-  Expect.isTrue(jumpTableEnumExhaustive(L._4) == 4);
-  Expect.isTrue(jumpTableEnumExhaustive(L._5) == 5);
-  Expect.isTrue(jumpTableEnumExhaustive(L._6) == 6);
-  Expect.isTrue(jumpTableEnumExhaustive(L._7) == 7);
-  Expect.isTrue(jumpTableEnumExhaustive(L._8) == 8);
-  Expect.isTrue(jumpTableEnumExhaustive(L._9) == 9);
-  Expect.isTrue(jumpTableEnumExhaustive(L._10) == 10);
-  Expect.isTrue(jumpTableEnumExhaustive(L._11) == 11);
-  Expect.isTrue(jumpTableEnumExhaustive(L._12) == 12);
-  Expect.isTrue(jumpTableEnumExhaustive(L._13) == 13);
-  Expect.isTrue(jumpTableEnumExhaustive(L._14) == 14);
-  Expect.isTrue(jumpTableEnumExhaustive(L._15) == 15);
-  Expect.isTrue(jumpTableEnumExhaustive(L._16) == 16);
-
-  Expect.isTrue(jumpTableEnumWithDefault(null) == null);
-  Expect.isTrue(jumpTableEnumWithDefault(L._0) == 0);
-  Expect.isTrue(jumpTableEnumWithDefault(L._1) == 1);
-  Expect.isTrue(jumpTableEnumWithDefault(L._2) == 2);
-  Expect.isTrue(jumpTableEnumWithDefault(L._3) == 3);
-  Expect.isTrue(jumpTableEnumWithDefault(L._4) == 4);
-  Expect.isTrue(jumpTableEnumWithDefault(L._5) == 5);
-  Expect.isTrue(jumpTableEnumWithDefault(L._6) == 6);
-  Expect.isTrue(jumpTableEnumWithDefault(L._7) == 7);
-  Expect.isTrue(jumpTableEnumWithDefault(L._8) == null);
-  Expect.isTrue(jumpTableEnumWithDefault(L._9) == 9);
-  Expect.isTrue(jumpTableEnumWithDefault(L._10) == 10);
-  Expect.isTrue(jumpTableEnumWithDefault(L._11) == 11);
-  Expect.isTrue(jumpTableEnumWithDefault(L._12) == 12);
-  Expect.isTrue(jumpTableEnumWithDefault(L._13) == 13);
-  Expect.isTrue(jumpTableEnumWithDefault(L._14) == 14);
-  Expect.isTrue(jumpTableEnumWithDefault(L._15) == 15);
-  Expect.isTrue(jumpTableEnumWithDefault(L._16) == 16);
-
-  Expect.isTrue(jumpTableEnumHole(L._0) == 0);
-  Expect.isTrue(jumpTableEnumHole(L._1) == null);
-  Expect.isTrue(jumpTableEnumHole(L._2) == 2);
-  Expect.isTrue(jumpTableEnumHole(L._3) == 3);
-  Expect.isTrue(jumpTableEnumHole(L._4) == 4);
-  Expect.isTrue(jumpTableEnumHole(L._5) == 5);
-  Expect.isTrue(jumpTableEnumHole(L._6) == 6);
-  Expect.isTrue(jumpTableEnumHole(L._7) == 7);
-  Expect.isTrue(jumpTableEnumHole(L._8) == 8);
-  Expect.isTrue(jumpTableEnumHole(L._9) == 9);
-  Expect.isTrue(jumpTableEnumHole(L._10) == 10);
-  Expect.isTrue(jumpTableEnumHole(L._11) == 11);
-  Expect.isTrue(jumpTableEnumHole(L._12) == 12);
-  Expect.isTrue(jumpTableEnumHole(L._13) == 13);
-  Expect.isTrue(jumpTableEnumHole(L._14) == 14);
-  Expect.isTrue(jumpTableEnumHole(L._15) == 15);
-  Expect.isTrue(jumpTableEnumHole(L._16) == 16);
-
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._0) == null);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._1) == 1);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._2) == 2);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._3) == 3);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._4) == 4);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._5) == 5);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._6) == 6);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._7) == 7);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._8) == 8);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._9) == 9);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._10) == 10);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._11) == 11);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._12) == 12);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._13) == 13);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._14) == 14);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._15) == 15);
-  Expect.isTrue(jumpTableEnumNoLowerBound(L._16) == 16);
-
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._0) == 0);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._1) == 1);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._2) == 2);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._3) == 3);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._4) == 4);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._5) == 5);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._6) == 6);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._7) == 7);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._8) == 8);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._9) == 9);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._10) == 10);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._11) == 11);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._12) == 12);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._13) == 13);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._14) == 14);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._15) == 15);
-  Expect.isTrue(jumpTableEnumNoUpperBound(L._16) == null);
-
-  Expect.isTrue(jumpTableInt(-2) == null);
-  Expect.isTrue(jumpTableInt(-1) == -1);
-  Expect.isTrue(jumpTableInt(0) == 0);
-  Expect.isTrue(jumpTableInt(1) == 1);
-  Expect.isTrue(jumpTableInt(2) == 2);
-  Expect.isTrue(jumpTableInt(3) == 3);
-  Expect.isTrue(jumpTableInt(4) == 4);
-  Expect.isTrue(jumpTableInt(5) == 5);
-  Expect.isTrue(jumpTableInt(6) == 6);
-  Expect.isTrue(jumpTableInt(7) == 7);
-  Expect.isTrue(jumpTableInt(8) == 8);
-  Expect.isTrue(jumpTableInt(9) == 9);
-  Expect.isTrue(jumpTableInt(10) == 10);
-  Expect.isTrue(jumpTableInt(11) == 11);
-  Expect.isTrue(jumpTableInt(12) == 12);
-  Expect.isTrue(jumpTableInt(13) == 13);
-  Expect.isTrue(jumpTableInt(14) == 14);
-  Expect.isTrue(jumpTableInt(15) == null);
-
-  Expect.isTrue(jumpTableIntWithDefault(null) == null);
-  Expect.isTrue(jumpTableIntWithDefault(-1) == null);
-  Expect.isTrue(jumpTableIntWithDefault(0) == 0);
-  Expect.isTrue(jumpTableIntWithDefault(1) == 1);
-  Expect.isTrue(jumpTableIntWithDefault(2) == 2);
-  Expect.isTrue(jumpTableIntWithDefault(3) == 3);
-  Expect.isTrue(jumpTableIntWithDefault(4) == 4);
-  Expect.isTrue(jumpTableIntWithDefault(5) == 5);
-  Expect.isTrue(jumpTableIntWithDefault(6) == 6);
-  Expect.isTrue(jumpTableIntWithDefault(7) == 7);
-  Expect.isTrue(jumpTableIntWithDefault(8) == null);
-  Expect.isTrue(jumpTableIntWithDefault(9) == 9);
-  Expect.isTrue(jumpTableIntWithDefault(10) == 10);
-  Expect.isTrue(jumpTableIntWithDefault(11) == 11);
-  Expect.isTrue(jumpTableIntWithDefault(12) == 12);
-  Expect.isTrue(jumpTableIntWithDefault(13) == 13);
-  Expect.isTrue(jumpTableIntWithDefault(14) == 14);
-  Expect.isTrue(jumpTableIntWithDefault(15) == 15);
-  Expect.isTrue(jumpTableIntWithDefault(16) == 16);
-  Expect.isTrue(jumpTableIntWithDefault(17) == null);
-}
-
-/// Small enum that is used to test binary search switches.
-enum S {
-  _0,
-  _1,
-  _2,
-}
-
-/// Large enum that is used to test jump table switches.
-///
-/// Must have enough values to trigger a jump table (currently 16) + 1 so
-/// we can create a jump table switch that is not exhaustive.
-enum L {
-  _0,
-  _1,
-  _2,
-  _3,
-  _4,
-  _5,
-  _6,
-  _7,
-  _8,
-  _9,
-  _10,
-  _11,
-  _12,
-  _13,
-  _14,
-  _15,
-  _16,
-}
-
-int duplicateEnum(L v) {
-  switch (v) {
-    case L._0:
-      return 0;
-    case L._1:
-      return 1;
-    case L._2:
-      return 2;
-    case L._1:
-      return 3;
-  }
-}
-
-int duplicateInt(int v) {
-  switch (v) {
-    case 0:
-      return 0;
-    case 1:
-      return 1;
-    case 2:
-      return 2;
-    case 1:
-      return 3;
-  }
-}
-
-int binarySearchEnumExhaustive(S v) {
-  switch (v) {
-    case S._0:
-      return 0;
-    case S._1:
-      return 1;
-    case S._2:
-      return 2;
-  }
-}
-
-int binarySearchEnumWithDefault(S v) {
-  switch (v) {
-    case S._0:
-      return 0;
-    case S._2:
-      return 2;
-    default:
-      return null;
-  }
-}
-
-int binarySearchEnumHole(S v) {
-  switch (v) {
-    case S._0:
-      return 0;
-    case S._2:
-      return 2;
-  }
-}
-
-int binarySearchEnumNoLowerBound(S v) {
-  switch (v) {
-    case S._1:
-      return 1;
-    case S._2:
-      return 2;
-  }
-}
-
-int binarySearchEnumNoUpperBound(S v) {
-  switch (v) {
-    case S._0:
-      return 0;
-    case S._1:
-      return 1;
-  }
-}
-
-int binarySearchInt(int v) {
-  switch (v) {
-    case -1:
-      return -1;
-    case 0:
-      return 0;
-    case 1:
-      return 1;
-  }
-}
-
-int binarySearchIntWithDefault(int v) {
-  switch (v) {
-    case 0:
-      return 0;
-    case 2:
-      return 2;
-    default:
-      return null;
-  }
-}
-
-int jumpTableEnumExhaustive(L v) {
-  switch (v) {
-    case L._0:
-      return 0;
-    case L._1:
-      return 1;
-    case L._2:
-      return 2;
-    case L._3:
-      return 3;
-    case L._4:
-      return 4;
-    case L._5:
-      return 5;
-    case L._6:
-      return 6;
-    case L._7:
-      return 7;
-    case L._8:
-      return 8;
-    case L._9:
-      return 9;
-    case L._10:
-      return 10;
-    case L._11:
-      return 11;
-    case L._12:
-      return 12;
-    case L._13:
-      return 13;
-    case L._14:
-      return 14;
-    case L._15:
-      return 15;
-    case L._16:
-      return 16;
-  }
-}
-
-int jumpTableEnumWithDefault(L v) {
-  switch (v) {
-    case L._0:
-      return 0;
-    case L._1:
-      return 1;
-    case L._2:
-      return 2;
-    case L._3:
-      return 3;
-    case L._4:
-      return 4;
-    case L._5:
-      return 5;
-    case L._6:
-      return 6;
-    case L._7:
-      return 7;
-    case L._9:
-      return 9;
-    case L._10:
-      return 10;
-    case L._11:
-      return 11;
-    case L._12:
-      return 12;
-    case L._13:
-      return 13;
-    case L._14:
-      return 14;
-    case L._15:
-      return 15;
-    case L._16:
-      return 16;
-    default:
-      return null;
-  }
-}
-
-int jumpTableEnumHole(L v) {
-  switch (v) {
-    case L._0:
-      return 0;
-    case L._2:
-      return 2;
-    case L._3:
-      return 3;
-    case L._4:
-      return 4;
-    case L._5:
-      return 5;
-    case L._6:
-      return 6;
-    case L._7:
-      return 7;
-    case L._8:
-      return 8;
-    case L._9:
-      return 9;
-    case L._10:
-      return 10;
-    case L._11:
-      return 11;
-    case L._12:
-      return 12;
-    case L._13:
-      return 13;
-    case L._14:
-      return 14;
-    case L._15:
-      return 15;
-    case L._16:
-      return 16;
-  }
-}
-
-int jumpTableEnumNoLowerBound(L v) {
-  switch (v) {
-    case L._1:
-      return 1;
-    case L._2:
-      return 2;
-    case L._3:
-      return 3;
-    case L._4:
-      return 4;
-    case L._5:
-      return 5;
-    case L._6:
-      return 6;
-    case L._7:
-      return 7;
-    case L._8:
-      return 8;
-    case L._9:
-      return 9;
-    case L._10:
-      return 10;
-    case L._11:
-      return 11;
-    case L._12:
-      return 12;
-    case L._13:
-      return 13;
-    case L._14:
-      return 14;
-    case L._15:
-      return 15;
-    case L._16:
-      return 16;
-  }
-}
-
-int jumpTableEnumNoUpperBound(L v) {
-  switch (v) {
-    case L._0:
-      return 0;
-    case L._1:
-      return 1;
-    case L._2:
-      return 2;
-    case L._3:
-      return 3;
-    case L._4:
-      return 4;
-    case L._5:
-      return 5;
-    case L._6:
-      return 6;
-    case L._7:
-      return 7;
-    case L._8:
-      return 8;
-    case L._9:
-      return 9;
-    case L._10:
-      return 10;
-    case L._11:
-      return 11;
-    case L._12:
-      return 12;
-    case L._13:
-      return 13;
-    case L._14:
-      return 14;
-    case L._15:
-      return 15;
-  }
-}
-
-int jumpTableInt(int v) {
-  switch (v) {
-    case -1:
-      return -1;
-    case 0:
-      return 0;
-    case 1:
-      return 1;
-    case 2:
-      return 2;
-    case 3:
-      return 3;
-    case 4:
-      return 4;
-    case 5:
-      return 5;
-    case 6:
-      return 6;
-    case 7:
-      return 7;
-    case 8:
-      return 8;
-    case 9:
-      return 9;
-    case 10:
-      return 10;
-    case 11:
-      return 11;
-    case 12:
-      return 12;
-    case 13:
-      return 13;
-    case 14:
-      return 14;
-  }
-}
-
-int jumpTableIntWithDefault(int v) {
-  switch (v) {
-    case 0:
-      return 0;
-    case 1:
-      return 1;
-    case 2:
-      return 2;
-    case 3:
-      return 3;
-    case 4:
-      return 4;
-    case 5:
-      return 5;
-    case 6:
-      return 6;
-    case 7:
-      return 7;
-    case 9:
-      return 9;
-    case 10:
-      return 10;
-    case 11:
-      return 11;
-    case 12:
-      return 12;
-    case 13:
-      return 13;
-    case 14:
-      return 14;
-    case 15:
-      return 15;
-    case 16:
-      return 16;
-    default:
-      return null;
-  }
-}
diff --git a/runtime/vm/compiler/backend/branch_optimizer.cc b/runtime/vm/compiler/backend/branch_optimizer.cc
index 23511b4..3c58635 100644
--- a/runtime/vm/compiler/backend/branch_optimizer.cc
+++ b/runtime/vm/compiler/backend/branch_optimizer.cc
@@ -284,10 +284,8 @@
         BranchInstr* branch = pred->last_instruction()->AsBranch();
 
         if (branch == nullptr) {
-          // There is no "B_pred" block, or the block is the IndirectGoto
-          // of a switch that uses it as a jump table.
-          ASSERT(pred->last_instruction()->IsGraphEntry() ||
-                 pred->last_instruction()->IsIndirectGoto());
+          // There is no "B_pred" block.
+          ASSERT(pred->last_instruction()->IsGraphEntry());
           continue;
         }
 
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index b2c9ad3..b021b2e 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -232,10 +232,8 @@
 }
 
 void ConstantPropagator::VisitIndirectGoto(IndirectGotoInstr* instr) {
-  if (reachable_->Contains(instr->GetBlock()->preorder_number())) {
-    for (intptr_t i = 0; i < instr->SuccessorCount(); i++) {
-      SetReachable(instr->SuccessorAt(i));
-    }
+  for (intptr_t i = 0; i < instr->SuccessorCount(); i++) {
+    SetReachable(instr->SuccessorAt(i));
   }
 }
 
@@ -1504,11 +1502,7 @@
 }
 
 static bool IsEmptyBlock(BlockEntryInstr* block) {
-  // A block containing a goto to itself forms an infinite loop.
-  // We don't consider this an empty block to handle the edge-case where code
-  // reduces to an infinite loop.
-  return block->next()->IsGoto() &&
-         block->next()->AsGoto()->successor() != block && !HasPhis(block) &&
+  return block->next()->IsGoto() && !HasPhis(block) &&
          !block->IsIndirectEntry();
 }
 
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 6c5b044..921a465 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -1472,8 +1472,7 @@
   return flow_graph_builder_->LoadLocal(variable);
 }
 
-IndirectGotoInstr* StreamingFlowGraphBuilder::IndirectGoto(
-    intptr_t target_count) {
+Fragment StreamingFlowGraphBuilder::IndirectGoto(intptr_t target_count) {
   return flow_graph_builder_->IndirectGoto(target_count);
 }
 
@@ -3348,8 +3347,8 @@
     instructions += BuildArguments(
         &argument_names, &argument_count,
         /* positional_argument_count = */ nullptr);  // read arguments.
-    ++argument_count;                                // include receiver
-    SkipInterfaceMemberNameReference();              // interfaceTargetReference
+    ++argument_count;                             // include receiver
+    SkipInterfaceMemberNameReference();           // interfaceTargetReference
     return instructions +
            StaticCall(position, Function::ZoneHandle(Z, function.ptr()),
                       argument_count, argument_names, ICData::kSuper,
@@ -4277,7 +4276,7 @@
   const TokenPosition pos = ReadPosition();  // read file offset.
   if (position != nullptr) *position = pos;
 
-  ReadPosition();  // read file end offset.
+  ReadPosition();                           // read file end offset.
 
   intptr_t list_length = ReadListLength();  // read number of statements.
   for (intptr_t i = 0; i < list_length; ++i) {
@@ -4415,7 +4414,7 @@
   const TokenPosition pos = ReadPosition();  // read position.
   if (position != nullptr) *position = pos;
 
-  intptr_t target_index = ReadUInt();  // read target index.
+  intptr_t target_index = ReadUInt();       // read target index.
 
   TryFinallyBlock* outer_finally = nullptr;
   intptr_t target_context_depth = -1;
@@ -4442,7 +4441,7 @@
   const TokenPosition pos = ReadPosition();  // read position.
   if (position != nullptr) *position = pos;
 
-  TestFragment condition = TranslateConditionForControl();   // read condition.
+  TestFragment condition = TranslateConditionForControl();  // read condition.
   const Fragment body = BuildStatementWithBranchCoverage();  // read body
 
   Fragment body_entry(condition.CreateTrueSuccessor(flow_graph_builder_));
@@ -4583,7 +4582,7 @@
   const TokenPosition pos = ReadPosition();  // read position.
   if (position != nullptr) *position = pos;
 
-  TokenPosition body_position = ReadPosition();  // read body position.
+  TokenPosition body_position = ReadPosition();   // read body position.
   intptr_t variable_kernel_position = ReaderOffset() + data_program_offset_;
   SkipVariableDeclaration();  // read variable.
 
@@ -4641,186 +4640,150 @@
     TokenPosition* position) {
   const TokenPosition pos = ReadPosition();  // read position.
   if (position != nullptr) *position = pos;
-  const bool is_exhaustive = ReadBool();  // read exhaustive flag.
+  ReadBool();  // read exhaustive flag.
 
   // We need the number of cases. So start by getting that, then go back.
-  const intptr_t offset = ReaderOffset();
-  SkipExpression();                        // temporarily skip condition
-  intptr_t case_count = ReadListLength();  // read number of cases.
+  intptr_t offset = ReaderOffset();
+  SkipExpression();                   // temporarily skip condition
+  int case_count = ReadListLength();  // read number of cases.
   SetOffset(offset);
 
   SwitchBlock block(flow_graph_builder_, case_count);
 
-  Fragment instructions = BuildExpression();  // read condition.
-  instructions +=
+  // Instead of using a variable we should reuse the expression on the stack,
+  // since it won't be assigned again, we don't need phi nodes.
+  Fragment head_instructions = BuildExpression();  // read condition.
+  head_instructions +=
       StoreLocal(TokenPosition::kNoSource, scopes()->switch_variable);
-  instructions += Drop();
+  head_instructions += Drop();
 
   case_count = ReadListLength();  // read number of cases.
 
-  SwitchHelper helper(Z, pos, is_exhaustive, &block, case_count);
-
-  // Build the case bodies and collect the expressions into the helper
-  // for the next step.
-  for (intptr_t i = 0; i < case_count; ++i) {
-    helper.AddCaseBody(BuildSwitchCase(&helper, i));
-  }
-
-  // Build the code to dispatch to the case bodies.
-  switch (helper.SelectDispatchStrategy()) {
-    case kSwitchDispatchAuto:
-      UNREACHABLE();
-    case kSwitchDispatchLinearScan:
-      instructions += BuildLinearScanSwitch(&helper);
-      break;
-    case kSwitchDispatchBinarySearch:
-      instructions += BuildBinarySearchSwitch(&helper);
-      break;
-    case kSwitchDispatchJumpTable:
-      instructions += BuildJumpTableSwitch(&helper);
-      break;
-  }
-
-  return instructions;
-}
-
-Fragment StreamingFlowGraphBuilder::BuildSwitchCase(SwitchHelper* helper,
-                                                    intptr_t case_index) {
-  // Generate case body and try to find out whether the body will be target
+  // Phase 1: Generate bodies and try to find out whether a body will be target
   // of a jump due to:
   //   * `continue case_label`
   //   * `case e1: case e2: body`
-  //
-  // Also collect switch expressions into helper.
-
-  const int expression_count = ReadListLength();  // read number of expressions.
-  for (intptr_t j = 0; j < expression_count; ++j) {
-    const TokenPosition pos = ReadPosition();  // read jth position.
-    // read jth expression.
-    const Instance& value =
-        Instance::ZoneHandle(Z, constant_reader_.ReadConstantExpression());
-    helper->AddExpression(case_index, pos, value);
-  }
-
-  const bool is_default = ReadBool();  // read is_default.
-  if (is_default) helper->set_default_case(case_index);
-  Fragment body_fragment = BuildStatementWithBranchCoverage();  // read body.
-
-  if (body_fragment.entry == nullptr) {
-    // Make a NOP in order to ensure linking works properly.
-    body_fragment = NullConstant();
-    body_fragment += Drop();
-  }
-
-  // The Dart language specification mandates fall-throughs in [SwitchCase]es
-  // to be runtime errors.
-  if (!is_default && body_fragment.is_open() &&
-      (case_index < (helper->case_count() - 1))) {
-    const Class& klass = Class::ZoneHandle(
-        Z, Library::LookupCoreClass(Symbols::FallThroughError()));
-    ASSERT(!klass.IsNull());
-    const auto& error = klass.EnsureIsFinalized(thread());
-    ASSERT(error == Error::null());
-
-    GrowableHandlePtrArray<const String> pieces(Z, 3);
-    pieces.Add(Symbols::FallThroughError());
-    pieces.Add(Symbols::Dot());
-    pieces.Add(H.DartSymbolObfuscate("_create"));
-
-    const Function& constructor = Function::ZoneHandle(
-        Z, klass.LookupConstructorAllowPrivate(String::ZoneHandle(
-               Z, Symbols::FromConcatAll(H.thread(), pieces))));
-    ASSERT(!constructor.IsNull());
-    const String& url = H.DartSymbolPlain(
-        parsed_function()->function().ToLibNamePrefixedQualifiedCString());
-
-    // Create instance of _FallThroughError
-    body_fragment += AllocateObject(TokenPosition::kNoSource, klass, 0);
-    LocalVariable* instance = MakeTemporary();
-
-    // Call _FallThroughError._create constructor.
-    body_fragment += LoadLocal(instance);  // this
-    body_fragment += Constant(url);        // url
-    body_fragment += NullConstant();       // line
-
-    body_fragment +=
-        StaticCall(TokenPosition::kNoSource, constructor, 3, ICData::kStatic);
-    body_fragment += Drop();
-
-    // Throw the exception
-    body_fragment += ThrowException(TokenPosition::kNoSource);
-    body_fragment += Drop();
-  }
-
-  // If there is an implicit fall-through we have one [SwitchCase] and
-  // multiple expressions, e.g.
-  //
-  //    switch(expr) {
-  //      case a:
-  //      case b:
-  //        <stmt-body>
-  //    }
-  //
-  // This means that the <stmt-body> will have more than 1 incoming edge (one
-  // from `a == expr` and one from `a != expr && b == expr`). The
-  // `block.Destination()` records the additional jump.
-  if (expression_count > 1) {
-    helper->switch_block()->DestinationDirect(case_index);
-  }
-
-  return body_fragment;
-}
-
-Fragment StreamingFlowGraphBuilder::BuildLinearScanSwitch(
-    SwitchHelper* helper) {
-  // Build a switch using a sequence of equality tests.
-  //
-  // From a test:
-  // * jump directly to a body, if there is no jumper.
-  // * jump to a wrapper block which jumps to the body, if there is a jumper.
-
-  SwitchBlock* block = helper->switch_block();
-  const intptr_t case_count = helper->case_count();
-  const intptr_t default_case = helper->default_case();
-  const GrowableArray<Fragment>& case_bodies = helper->case_bodies();
-  Fragment current_instructions;
-  intptr_t expression_index = 0;
+  Fragment* body_fragments = Z->Alloc<Fragment>(case_count);
+  intptr_t* case_expression_offsets = Z->Alloc<intptr_t>(case_count);
+  int default_case = -1;
 
   for (intptr_t i = 0; i < case_count; ++i) {
+    case_expression_offsets[i] = ReaderOffset();
+    int expression_count = ReadListLength();  // read number of expressions.
+    for (intptr_t j = 0; j < expression_count; ++j) {
+      ReadPosition();    // read jth position.
+      SkipExpression();  // read jth expression.
+    }
+    bool is_default = ReadBool();  // read is_default.
+    if (is_default) default_case = i;
+    Fragment& body_fragment = body_fragments[i] =
+        BuildStatementWithBranchCoverage();  // read body.
+
+    if (body_fragment.entry == nullptr) {
+      // Make a NOP in order to ensure linking works properly.
+      body_fragment = NullConstant();
+      body_fragment += Drop();
+    }
+
+    // The Dart language specification mandates fall-throughs in [SwitchCase]es
+    // to be runtime errors.
+    if (!is_default && body_fragment.is_open() && (i < (case_count - 1))) {
+      const Class& klass = Class::ZoneHandle(
+          Z, Library::LookupCoreClass(Symbols::FallThroughError()));
+      ASSERT(!klass.IsNull());
+      const auto& error = klass.EnsureIsFinalized(thread());
+      ASSERT(error == Error::null());
+
+      GrowableHandlePtrArray<const String> pieces(Z, 3);
+      pieces.Add(Symbols::FallThroughError());
+      pieces.Add(Symbols::Dot());
+      pieces.Add(H.DartSymbolObfuscate("_create"));
+
+      const Function& constructor = Function::ZoneHandle(
+          Z, klass.LookupConstructorAllowPrivate(String::ZoneHandle(
+                 Z, Symbols::FromConcatAll(H.thread(), pieces))));
+      ASSERT(!constructor.IsNull());
+      const String& url = H.DartSymbolPlain(
+          parsed_function()->function().ToLibNamePrefixedQualifiedCString());
+
+      // Create instance of _FallThroughError
+      body_fragment += AllocateObject(TokenPosition::kNoSource, klass, 0);
+      LocalVariable* instance = MakeTemporary();
+
+      // Call _FallThroughError._create constructor.
+      body_fragment += LoadLocal(instance);  // this
+      body_fragment += Constant(url);        // url
+      body_fragment += NullConstant();       // line
+
+      body_fragment +=
+          StaticCall(TokenPosition::kNoSource, constructor, 3, ICData::kStatic);
+      body_fragment += Drop();
+
+      // Throw the exception
+      body_fragment += ThrowException(TokenPosition::kNoSource);
+      body_fragment += Drop();
+    }
+
+    // If there is an implicit fall-through we have one [SwitchCase] and
+    // multiple expressions, e.g.
+    //
+    //    switch(expr) {
+    //      case a:
+    //      case b:
+    //        <stmt-body>
+    //    }
+    //
+    // This means that the <stmt-body> will have more than 1 incoming edge (one
+    // from `a == expr` and one from `a != expr && b == expr`). The
+    // `block.Destination()` records the additional jump.
+    if (expression_count > 1) {
+      block.DestinationDirect(i);
+    }
+  }
+
+  intptr_t end_offset = ReaderOffset();
+
+  // Phase 2: Generate everything except the real bodies:
+  //   * jump directly to a body (if there is no jumper)
+  //   * jump to a wrapper block which jumps to the body (if there is a jumper)
+  Fragment current_instructions = head_instructions;
+  for (intptr_t i = 0; i < case_count; ++i) {
+    SetOffset(case_expression_offsets[i]);
+    int expression_count = ReadListLength();  // read length of expressions.
+
     if (i == default_case) {
       ASSERT(i == (case_count - 1));
 
-      if (block->HadJumper(i)) {
+      if (block.HadJumper(i)) {
         // There are several branches to the body, so we will make a goto to
         // the join block (and prepend a join instruction to the real body).
-        JoinEntryInstr* join = block->DestinationDirect(i);
+        JoinEntryInstr* join = block.DestinationDirect(i);
         current_instructions += Goto(join);
 
         current_instructions = Fragment(current_instructions.entry, join);
-        current_instructions += case_bodies[i];
+        current_instructions += body_fragments[i];
       } else {
-        current_instructions += case_bodies[i];
+        current_instructions += body_fragments[i];
       }
     } else {
       JoinEntryInstr* body_join = nullptr;
-      if (block->HadJumper(i)) {
-        body_join = block->DestinationDirect(i);
-        case_bodies[i] = Fragment(body_join) + case_bodies[i];
+      if (block.HadJumper(i)) {
+        body_join = block.DestinationDirect(i);
+        body_fragments[i] = Fragment(body_join) + body_fragments[i];
       }
 
-      const intptr_t expression_count = helper->case_expression_counts().At(i);
       for (intptr_t j = 0; j < expression_count; ++j) {
         TargetEntryInstr* then;
         TargetEntryInstr* otherwise;
 
-        const SwitchExpression& expression =
-            helper->expressions().At(expression_index++);
-        current_instructions += Constant(expression.value());
+        const TokenPosition pos = ReadPosition();  // read jth position.
+        current_instructions += Constant(
+            Instance::ZoneHandle(Z, constant_reader_.ReadConstantExpression()));
         current_instructions += LoadLocal(scopes()->switch_variable);
-        current_instructions += InstanceCall(
-            expression.position(), Symbols::EqualOperator(), Token::kEQ,
-            /*argument_count=*/2,
-            /*checked_argument_count=*/2);
+        current_instructions +=
+            InstanceCall(pos, Symbols::EqualOperator(), Token::kEQ,
+                         /*argument_count=*/2,
+                         /*checked_argument_count=*/2);
         current_instructions += BranchIfTrue(&then, &otherwise, false);
 
         Fragment then_fragment(then);
@@ -4831,23 +4794,23 @@
           // join instruction).
           then_fragment += Goto(body_join);
         } else {
-          // There is only a single branch to the body, so we will just append
+          // There is only a signle branch to the body, so we will just append
           // the body fragment.
-          then_fragment += case_bodies[i];
+          then_fragment += body_fragments[i];
         }
 
-        current_instructions = Fragment(current_instructions.entry, otherwise);
+        current_instructions = Fragment(otherwise);
       }
     }
   }
 
-  if (case_count > 0 && !helper->has_default()) {
+  if (case_count > 0 && default_case < 0) {
     // There is no default, which means we have an open [current_instructions]
     // (which is a [TargetEntryInstruction] for the last "otherwise" branch).
     //
     // Furthermore the last [SwitchCase] can be open as well.  If so, we need
     // to join these two.
-    Fragment& last_body = case_bodies[case_count - 1];
+    Fragment& last_body = body_fragments[case_count - 1];
     if (last_body.is_open()) {
       ASSERT(current_instructions.is_open());
       ASSERT(current_instructions.current->IsTargetEntry());
@@ -4857,7 +4820,7 @@
       current_instructions += Goto(join);
       last_body += Goto(join);
 
-      current_instructions = Fragment(current_instructions.entry, join);
+      current_instructions = Fragment(join);
     }
   } else {
     // All non-default cases will be closed (i.e. break/continue/throw/return)
@@ -4865,354 +4828,8 @@
     // default case.
   }
 
-  return current_instructions;
-}
-
-Fragment StreamingFlowGraphBuilder::BuildOptimizedSwitchPrelude(
-    SwitchHelper* helper,
-    JoinEntryInstr* join) {
-  const TokenPosition pos = helper->position();
-
-  // We need to check that the switch variable is of the correct type.
-  // If it is not, we go to [join] which is either the default case or
-  // the exit of the switch statement.
-
-  TargetEntryInstr* then_entry;
-  TargetEntryInstr* otherwise_entry;
-
-  const AbstractType& expression_type =
-      AbstractType::ZoneHandle(Z, helper->expression_class().RareType());
-  ASSERT(dart::SimpleInstanceOfType(expression_type));
-
-  Fragment instructions;
-  instructions += LoadLocal(scopes()->switch_variable);
-  instructions += Constant(expression_type);
-  instructions += InstanceCall(
-      pos, Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()),
-      Token::kIS, /*argument_count=*/2,
-      /*checked_argument_count=*/2);
-  instructions += BranchIfTrue(&then_entry, &otherwise_entry, /*negate=*/false);
-
-  Fragment otherwise_instructions(otherwise_entry);
-  otherwise_instructions += Goto(join);
-
-  instructions = Fragment(instructions.entry, then_entry);
-
-  if (helper->is_enum_switch()) {
-    // For an enum switch, we need to load the enum index from the switch
-    // variable.
-
-    instructions += LoadLocal(scopes()->switch_variable);
-    const Field& enum_index_field =
-        Field::ZoneHandle(Z, IG->object_store()->enum_index_field());
-    instructions += B->LoadField(enum_index_field, /*calls_initializer=*/false);
-    instructions += StoreLocal(pos, scopes()->switch_variable);
-    instructions += Drop();
-  }
-
-  return instructions;
-}
-
-Fragment StreamingFlowGraphBuilder::BuildBinarySearchSwitch(
-    SwitchHelper* helper) {
-  // * We build a binary tree of conditional branches where each branch bisects
-  //   the remaining cases.
-  //   * At holes in the switch expression range we need to add additional
-  //     bound checks.
-  // * At each leaf we add the body of the case or a goto, if the case has
-  //   jumpers.
-  //   * Leafs at the bounds of the switch expression range might need to
-  //     do a bound check.
-
-  SwitchBlock* block = helper->switch_block();
-  const intptr_t case_count = helper->case_count();
-  const intptr_t default_case = helper->default_case();
-  const GrowableArray<Fragment>& case_bodies = helper->case_bodies();
-  const intptr_t expression_count = helper->expressions().length();
-  const GrowableArray<SwitchExpression*>& sorted_expressions =
-      helper->sorted_expressions();
-  TargetEntryInstr* then_entry;
-  TargetEntryInstr* otherwise_entry;
-
-  // Entry to the default case or the exit of the switch, if there is no
-  // default case.
-  JoinEntryInstr* join;
-  if (helper->has_default()) {
-    join = block->DestinationDirect(default_case);
-  } else {
-    join = BuildJoinEntry();
-  }
-
-  Fragment join_instructions(join);
-  if (helper->has_default()) {
-    join_instructions += case_bodies.At(default_case);
-  }
-
-  Fragment current_instructions = BuildOptimizedSwitchPrelude(helper, join);
-
-  GrowableArray<SwitchRange> stack;
-  stack.Add(SwitchRange::Branch(0, expression_count - 1, current_instructions));
-
-  while (!stack.is_empty()) {
-    const SwitchRange range = stack.RemoveLast();
-    Fragment branch_instructions = range.branch_instructions();
-
-    if (range.is_leaf()) {
-      const intptr_t expression_index = range.min();
-      const SwitchExpression& expression =
-          *sorted_expressions.At(expression_index);
-
-      if (!range.is_bounds_checked() &&
-          ((helper->RequiresLowerBoundCheck() && expression_index == 0) ||
-           (helper->RequiresUpperBoundCheck() &&
-            expression_index == expression_count - 1))) {
-        // This leaf needs a bound check.
-
-        branch_instructions += LoadLocal(scopes()->switch_variable);
-        branch_instructions += Constant(expression.integer());
-        branch_instructions +=
-            StrictCompare(expression.position(), Token::kEQ_STRICT,
-                          /*number_check=*/true);
-        branch_instructions +=
-            BranchIfTrue(&then_entry, &otherwise_entry, /*negate=*/false);
-
-        Fragment otherwise_instructions(otherwise_entry);
-        otherwise_instructions += Goto(join);
-
-        stack.Add(SwitchRange::Leaf(expression_index, Fragment(then_entry),
-                                    /*is_bounds_checked=*/true));
-      } else {
-        // We are at a leaf where we can add the body of the case or a goto to
-        // [join].
-
-        const intptr_t case_index = expression.case_index();
-
-        if (case_index == default_case) {
-          branch_instructions += Goto(join);
-        } else {
-          if (block->HadJumper(case_index)) {
-            JoinEntryInstr* join = block->DestinationDirect(case_index);
-            branch_instructions += Goto(join);
-
-            if (join->next() == nullptr) {
-              // The first time we reach an expression that jumps to a case
-              // body we emit the body.
-              branch_instructions = Fragment(join);
-              branch_instructions += case_bodies.At(case_index);
-            }
-          } else {
-            branch_instructions += case_bodies.At(case_index);
-          }
-
-          if (!helper->has_default() && case_index == case_count - 1) {
-            if (branch_instructions.is_open()) {
-              branch_instructions += Goto(join);
-            }
-          }
-        }
-
-        ASSERT(branch_instructions.is_closed());
-      }
-    } else {
-      // Add a conditional to bisect the range.
-
-      const intptr_t middle = range.min() + (range.max() - range.min()) / 2;
-      const intptr_t next = middle + 1;
-      const SwitchExpression& middle_expression =
-          *sorted_expressions.At(middle);
-      const SwitchExpression& next_expression = *sorted_expressions.At(next);
-
-      branch_instructions += LoadLocal(scopes()->switch_variable);
-      branch_instructions += Constant(middle_expression.integer());
-      branch_instructions +=
-          InstanceCall(middle_expression.position(),
-                       Symbols::LessEqualOperator(), Token::kLTE,
-                       /*argument_count=*/2,
-                       /*checked_argument_count=*/2);
-      branch_instructions +=
-          BranchIfTrue(&then_entry, &otherwise_entry, /*negate=*/false);
-
-      Fragment lower_branch_instructions(then_entry);
-      Fragment upper_branch_instructions(otherwise_entry);
-
-      if (next_expression.integer().AsInt64Value() >
-          middle_expression.integer().AsInt64Value() + 1) {
-        // The upper branch is not contiguous with the lower branch.
-        // Before continuing in the upper branch we add a bound check.
-
-        upper_branch_instructions += LoadLocal(scopes()->switch_variable);
-        upper_branch_instructions += Constant(next_expression.integer());
-        upper_branch_instructions +=
-            InstanceCall(next_expression.position(),
-                         Symbols::GreaterEqualOperator(), Token::kGTE,
-                         /*argument_count=*/2,
-                         /*checked_argument_count=*/2);
-        upper_branch_instructions +=
-            BranchIfTrue(&then_entry, &otherwise_entry, /*negate=*/false);
-
-        Fragment otherwise_instructions(otherwise_entry);
-        otherwise_instructions += Goto(join);
-
-        upper_branch_instructions = Fragment(then_entry);
-      }
-
-      stack.Add(
-          SwitchRange::Branch(next, range.max(), upper_branch_instructions));
-      stack.Add(
-          SwitchRange::Branch(range.min(), middle, lower_branch_instructions));
-    }
-  }
-
-  return Fragment(current_instructions.entry, join_instructions.current);
-}
-
-Fragment StreamingFlowGraphBuilder::BuildJumpTableSwitch(SwitchHelper* helper) {
-  // * If input value is not integer or enum value, goto default case or
-  //   switch exit.
-  // * If value is enum value, load its index.
-  // * If input integer is outside of jump table range, goto default case
-  //   or switch exit.
-  // * Jump to case with jump table.
-  //     * For each expression, add entry to jump to case.
-  //     * For each hole in the integer range, add entry to jump to default
-  //       cause or switch exit.
-
-  SwitchBlock* block = helper->switch_block();
-  const TokenPosition pos = helper->position();
-  const intptr_t case_count = helper->case_count();
-  const intptr_t default_case = helper->default_case();
-  const GrowableArray<Fragment>& case_bodies = helper->case_bodies();
-  const Integer& expression_min = helper->expression_min();
-  const Integer& expression_max = helper->expression_max();
-  TargetEntryInstr* then_entry;
-  TargetEntryInstr* otherwise_entry;
-
-  // Entry to the default case or the exit of the switch, if there is no
-  // default case.
-  JoinEntryInstr* join;
-  if (helper->has_default()) {
-    join = block->DestinationDirect(default_case);
-  } else {
-    join = BuildJoinEntry();
-  }
-
-  Fragment join_instructions(join);
-
-  Fragment current_instructions = BuildOptimizedSwitchPrelude(helper, join);
-
-  if (helper->RequiresLowerBoundCheck()) {
-    current_instructions += LoadLocal(scopes()->switch_variable);
-    current_instructions += Constant(expression_min);
-    current_instructions += InstanceCall(pos, Symbols::GreaterEqualOperator(),
-                                         Token::kGTE, /*argument_count=*/2,
-                                         /*checked_argument_count=*/2);
-    current_instructions += BranchIfTrue(&then_entry, &otherwise_entry,
-                                         /*negate=*/false);
-    Fragment otherwise_instructions(otherwise_entry);
-    otherwise_instructions += Goto(join);
-
-    current_instructions = Fragment(current_instructions.entry, then_entry);
-  }
-
-  if (helper->RequiresUpperBoundCheck()) {
-    current_instructions += LoadLocal(scopes()->switch_variable);
-    current_instructions += Constant(expression_max);
-    current_instructions += InstanceCall(pos, Symbols::LessEqualOperator(),
-                                         Token::kLTE, /*argument_count=*/2,
-                                         /*checked_argument_count=*/2);
-    current_instructions += BranchIfTrue(&then_entry, &otherwise_entry,
-                                         /*negate=*/false);
-    Fragment otherwise_instructions(otherwise_entry);
-    otherwise_instructions += Goto(join);
-
-    current_instructions = Fragment(current_instructions.entry, then_entry);
-  }
-
-  current_instructions += LoadLocal(scopes()->switch_variable);
-
-  if (!expression_min.IsZero()) {
-    // Adjust for the range of the jump table, which starts at 0.
-    current_instructions += Constant(expression_min);
-    current_instructions +=
-        InstanceCall(pos, Symbols::Minus(), Token::kSUB, /*argument_count=*/2,
-                     /*checked_argument_count=*/2);
-  }
-
-  const intptr_t table_size = helper->ExpressionRange();
-  IndirectGotoInstr* indirect_goto = IndirectGoto(table_size);
-  current_instructions <<= indirect_goto;
-  current_instructions = current_instructions.closed();
-
-  GrowableArray<TargetEntryInstr*> table_entries(table_size);
-  table_entries.FillWith(nullptr, 0, table_size);
-
-  // Generate the jump table entries for the switch cases.
-  intptr_t expression_index = 0;
-  for (intptr_t i = 0; i < case_count; ++i) {
-    const int expression_count = helper->case_expression_counts().At(i);
-
-    // Generate jump table entries for each case expression.
-    if (i != default_case) {
-      for (intptr_t j = 0; j < expression_count; ++j) {
-        const SwitchExpression& expression =
-            helper->expressions().At(expression_index++);
-        const intptr_t table_offset =
-            expression.integer().AsInt64Value() - expression_min.AsInt64Value();
-
-        IndirectEntryInstr* indirect_entry =
-            B->BuildIndirectEntry(table_offset, CurrentTryIndex());
-        Fragment indirect_entry_instructions(indirect_entry);
-        indirect_entry_instructions += Goto(block->DestinationDirect(i));
-
-        TargetEntryInstr* entry = B->BuildTargetEntry();
-        Fragment entry_instructions(entry);
-        entry_instructions += Goto(indirect_entry);
-
-        table_entries[table_offset] = entry;
-      }
-    }
-
-    // Connect the case body to its join entry.
-    if (i == default_case) {
-      join_instructions += case_bodies.At(i);
-    } else {
-      Fragment case_instructions(block->DestinationDirect(i));
-      case_instructions += case_bodies.At(i);
-
-      if (i == case_count - 1) {
-        // If the last case is not the default case and it is still open
-        // close it by going to the exit of the switch.
-        if (case_instructions.is_open()) {
-          case_instructions += Goto(join);
-        }
-      }
-
-      ASSERT(case_instructions.is_closed());
-    }
-  }
-
-  // Generate the jump table entries for holes in the integer range.
-  for (intptr_t i = 0; i < table_size; i++) {
-    if (table_entries.At(i) == nullptr) {
-      IndirectEntryInstr* indirect_entry =
-          B->BuildIndirectEntry(i, CurrentTryIndex());
-      Fragment indirect_entry_instructions(indirect_entry);
-      indirect_entry_instructions += Goto(join);
-
-      TargetEntryInstr* entry = flow_graph_builder_->BuildTargetEntry();
-      Fragment entry_instructions(entry);
-      entry_instructions += Goto(indirect_entry);
-
-      table_entries[i] = entry;
-    }
-  }
-
-  // Add the jump table entries to the jump table.
-  for (intptr_t i = 0; i < table_size; i++) {
-    indirect_goto->AddSuccessor(table_entries.At(i));
-  }
-
-  return Fragment(current_instructions.entry, join_instructions.current);
+  SetOffset(end_offset);
+  return Fragment(head_instructions.entry, current_instructions.current);
 }
 
 Fragment StreamingFlowGraphBuilder::BuildContinueSwitchStatement(
@@ -5220,7 +4837,7 @@
   const TokenPosition pos = ReadPosition();  // read position.
   if (position != nullptr) *position = pos;
 
-  intptr_t target_index = ReadUInt();  // read target index.
+  intptr_t target_index = ReadUInt();       // read target index.
 
   TryFinallyBlock* outer_finally = nullptr;
   intptr_t target_context_depth = -1;
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 22da387..6daf672 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -152,7 +152,7 @@
   void InlineBailout(const char* reason);
   Fragment DebugStepCheck(TokenPosition position);
   Fragment LoadLocal(LocalVariable* variable);
-  IndirectGotoInstr* IndirectGoto(intptr_t target_count);
+  Fragment IndirectGoto(intptr_t target_count);
   Fragment Return(
       TokenPosition position,
       intptr_t yield_index = UntaggedPcDescriptors::kInvalidYieldIndex);
@@ -349,12 +349,6 @@
   Fragment BuildForStatement(TokenPosition* position);
   Fragment BuildForInStatement(bool async, TokenPosition* position);
   Fragment BuildSwitchStatement(TokenPosition* position);
-  Fragment BuildSwitchCase(SwitchHelper* helper, intptr_t case_index);
-  Fragment BuildLinearScanSwitch(SwitchHelper* helper);
-  Fragment BuildOptimizedSwitchPrelude(SwitchHelper* helper,
-                                       JoinEntryInstr* join);
-  Fragment BuildBinarySearchSwitch(SwitchHelper* helper);
-  Fragment BuildJumpTableSwitch(SwitchHelper* helper);
   Fragment BuildContinueSwitchStatement(TokenPosition* position);
   Fragment BuildIfStatement(TokenPosition* position);
   Fragment BuildReturnStatement(TokenPosition* position);
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 2a553e6..eba8dba 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -45,12 +45,6 @@
             false,
             "Print huge methods (less optimized)");
 
-DEFINE_FLAG(int,
-            force_switch_dispatch_type,
-            -1,
-            "Force switch statements to use a particular dispatch type: "
-            "-1=auto, 0=linear scan, 1=binary search, 2=jump table");
-
 namespace kernel {
 
 #define Z (zone_)
@@ -482,9 +476,9 @@
   }
 }
 
-IndirectGotoInstr* FlowGraphBuilder::IndirectGoto(intptr_t target_count) {
+Fragment FlowGraphBuilder::IndirectGoto(intptr_t target_count) {
   Value* index = Pop();
-  return new (Z) IndirectGotoInstr(target_count, index);
+  return Fragment(new (Z) IndirectGotoInstr(target_count, index));
 }
 
 Fragment FlowGraphBuilder::ThrowLateInitializationError(
@@ -4960,206 +4954,6 @@
   return prepend_type_arguments_;
 }
 
-int64_t SwitchHelper::ExpressionRange() const {
-  const int64_t min = expression_min().AsInt64Value();
-  const int64_t max = expression_max().AsInt64Value();
-  ASSERT(min <= max);
-  const uint64_t diff = static_cast<uint64_t>(max) - static_cast<uint64_t>(min);
-  // Saturate to avoid overflow.
-  if (diff > static_cast<uint64_t>(kMaxInt64 - 1)) {
-    return kMaxInt64;
-  }
-  return static_cast<int64_t>(diff + 1);
-}
-
-bool SwitchHelper::RequiresLowerBoundCheck() const {
-  if (is_enum_switch()) {
-    if (expression_min().IsZero()) {
-      // Enum indexes are always positive.
-      return false;
-    }
-  }
-  return true;
-}
-
-bool SwitchHelper::RequiresUpperBoundCheck() const {
-  if (is_enum_switch()) {
-    return has_default() || !is_exhaustive();
-  }
-  return true;
-}
-
-SwitchDispatch SwitchHelper::SelectDispatchStrategy() {
-  // For small to medium-sized switches, binary search is faster than a
-  // jump table.
-  // Please update runtime/tests/vm/dart/optimized_switch_test.dart
-  // when changing this constant.
-  const intptr_t kJumpTableMinExpressions = 16;
-  // This limit comes from IndirectGotoInstr.
-  // Realistically, the current limit should never be hit by any code.
-  const intptr_t kJumpTableMaxSize = kMaxInt32;
-  // Sometimes the switch expressions don't cover a contiguous range.
-  // If the ratio of holes to expressions is too great we fall back to a
-  // binary search to avoid code size explosion.
-  const double kJumpTableMaxHolesRatio = 1.0;
-
-  if (!is_optimizable()) {
-    // The switch is not optimizable, so we can only use linear scan.
-    return kSwitchDispatchLinearScan;
-  }
-
-  if (FLAG_force_switch_dispatch_type == kSwitchDispatchLinearScan) {
-    return kSwitchDispatchLinearScan;
-  }
-
-  PrepareForOptimizedSwitch();
-
-  if (!is_optimizable()) {
-    // While preparing for an optimized switch we might have discovered that
-    // the switch is not optimizable after all.
-    return kSwitchDispatchLinearScan;
-  }
-
-  if (FLAG_force_switch_dispatch_type == kSwitchDispatchBinarySearch) {
-    return kSwitchDispatchBinarySearch;
-  }
-
-  const int64_t range = ExpressionRange();
-  if (range > kJumpTableMaxSize) {
-    return kSwitchDispatchBinarySearch;
-  }
-
-  const intptr_t num_expressions = expressions().length();
-  ASSERT(num_expressions <= range);
-
-  const intptr_t max_holes = num_expressions * kJumpTableMaxHolesRatio;
-  const int64_t holes = range - num_expressions;
-
-  if (FLAG_force_switch_dispatch_type != kSwitchDispatchJumpTable) {
-    if (num_expressions < kJumpTableMinExpressions) {
-      return kSwitchDispatchBinarySearch;
-    }
-
-    if (holes > max_holes) {
-      return kSwitchDispatchBinarySearch;
-    }
-  }
-
-  // After this point we will use a jump table.
-
-  // In the general case, bounds checks are required before a jump table
-  // to handle all possible integer values.
-  // For enums, the set of possible index values is known and much smaller
-  // than the set of all possible integer values. A jump table that covers
-  // either or both bounds of the range of index values requires only one or
-  // no bounds checks.
-  // If the expressions of an enum switch don't cover the full range of
-  // values we can try to extend the jump table to cover the full range, but
-  // not beyond kJumpTableMaxHolesRatio.
-  // The count of enum values is not available when the flow graph is
-  // constructed. The lower bound is always 0 so eliminating the lower
-  // bound check is still possible by extending expression_min to 0.
-  //
-  // In the case of an integer switch we try to extend expression_min to 0
-  // for a different reason.
-  // If the range starts at zero it directly maps to the jump table
-  // and we don't need to adjust the switch variable before the
-  // jump table.
-  if (expression_min().AsInt64Value() > 0) {
-    const intptr_t holes_budget = Utils::Minimum(
-        // Holes still available.
-        max_holes - holes,
-        // Entries left in the jump table.
-        kJumpTableMaxSize - range);
-
-    const int64_t required_holes = expression_min().AsInt64Value();
-    if (required_holes <= holes_budget) {
-      expression_min_ = &Object::smi_zero();
-    }
-  }
-
-  return kSwitchDispatchJumpTable;
-}
-
-void SwitchHelper::PrepareForOptimizedSwitch() {
-  // Find the min and max of integer representations of expressions.
-  // We also populate SwitchExpressions.integer for later use.
-  const Field* enum_index_field = nullptr;
-  for (intptr_t i = 0; i < expressions_.length(); ++i) {
-    SwitchExpression& expression = expressions_[i];
-    sorted_expressions_.Add(&expression);
-
-    const Instance& value = expression.value();
-    const Integer* integer = nullptr;
-    if (is_enum_switch()) {
-      if (enum_index_field == nullptr) {
-        enum_index_field = &Field::Handle(
-            zone_, IsolateGroup::Current()->object_store()->enum_index_field());
-      }
-      integer = &Integer::ZoneHandle(
-          zone_, Integer::RawCast(value.GetField(*enum_index_field)));
-    } else {
-      integer = &Integer::Cast(value);
-    }
-    expression.set_integer(*integer);
-    if (i == 0) {
-      expression_min_ = integer;
-      expression_max_ = integer;
-    } else {
-      if (expression_min_->CompareWith(*integer) > 0) {
-        expression_min_ = integer;
-      }
-      if (expression_max_->CompareWith(*integer) < 0) {
-        expression_max_ = integer;
-      }
-    }
-  }
-
-  // Sort expressions by their integer value.
-  sorted_expressions_.Sort(
-      [](SwitchExpression* const* a, SwitchExpression* const* b) {
-        return (*a)->integer().CompareWith((*b)->integer());
-      });
-
-  // Check that there are no duplicate case expressions.
-  // Duplicate expressions are allowed in switch statements, but
-  // optimized switches don't implemented them.
-  for (intptr_t i = 0; i < sorted_expressions_.length() - 1; ++i) {
-    const SwitchExpression& a = *sorted_expressions_.At(i);
-    const SwitchExpression& b = *sorted_expressions_.At(i + 1);
-    if (a.integer().Equals(b.integer())) {
-      is_optimizable_ = false;
-      break;
-    }
-  }
-}
-
-void SwitchHelper::AddExpression(intptr_t case_index,
-                                 TokenPosition position,
-                                 const Instance& value) {
-  case_expression_counts_[case_index]++;
-
-  expressions_.Add(SwitchExpression(case_index, position, value));
-
-  if (is_optimizable_ || expression_class_ == nullptr) {
-    // Check the type of the expression for use in an optimized switch.
-    const Class& value_class = Class::ZoneHandle(zone_, value.clazz());
-    if (expression_class_ == nullptr) {
-      if (value.IsInteger() || value_class.is_enum_class()) {
-        expression_class_ = &value_class;
-        is_optimizable_ = true;
-      } else {
-        // At least one expression (the first) is not suitable for an
-        // optimized switch.
-        is_optimizable_ = false;
-      }
-    } else if (value_class.ptr() != expression_class_->ptr()) {
-      // At least one expression has a different type than the others.
-      is_optimizable_ = false;
-    }
-  }
-}
-
 }  // namespace kernel
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index 69471ce..045750e 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -19,7 +19,6 @@
 #include "vm/compiler/frontend/base_flow_graph_builder.h"
 #include "vm/compiler/frontend/kernel_translation_helper.h"
 #include "vm/compiler/frontend/scope_builder.h"
-#include "vm/object_store.h"
 
 namespace dart {
 
@@ -194,7 +193,7 @@
 
   Fragment RethrowException(TokenPosition position, int catch_try_index);
   Fragment LoadLocal(LocalVariable* variable);
-  IndirectGotoInstr* IndirectGoto(intptr_t target_count);
+  Fragment IndirectGoto(intptr_t target_count);
   Fragment StoreLateField(const Field& field,
                           LocalVariable* instance,
                           LocalVariable* setter_value);
@@ -936,190 +935,6 @@
   DISALLOW_COPY_AND_ASSIGN(CatchBlock);
 };
 
-enum SwitchDispatch {
-  kSwitchDispatchAuto = -1,
-  kSwitchDispatchLinearScan,
-  kSwitchDispatchBinarySearch,
-  kSwitchDispatchJumpTable,
-};
-
-// Collected information for a switch expression.
-class SwitchExpression {
- public:
-  SwitchExpression(intptr_t case_index,
-                   TokenPosition position,
-                   const Instance& value)
-      : case_index_(case_index), position_(position), value_(&value) {}
-
-  intptr_t case_index() const { return case_index_; }
-  const TokenPosition& position() const { return position_; }
-  // Constant value of the expression.
-  const Instance& value() const { return *value_; }
-
-  // Integer representation of the expression.
-  // For Integers it is the value itself and for Enums it is the index.
-  const Integer& integer() const {
-    ASSERT(integer_ != nullptr);
-    return *integer_;
-  }
-
-  void set_integer(const Integer& integer) {
-    ASSERT(integer_ == nullptr);
-    integer_ = &integer;
-  }
-
- private:
-  intptr_t case_index_;
-  TokenPosition position_;
-  const Instance* value_;
-  const Integer* integer_ = nullptr;
-};
-
-// A range that is covered by a branch in a binary search switch.
-// Leafs are represented by a range where min == max.
-class SwitchRange {
- public:
-  static SwitchRange Leaf(intptr_t index,
-                          Fragment branch_instructions,
-                          bool is_bounds_checked = false) {
-    return SwitchRange(index, index, branch_instructions, is_bounds_checked);
-  }
-
-  static SwitchRange Branch(intptr_t min,
-                            intptr_t max,
-                            Fragment branch_instructions) {
-    return SwitchRange(min, max, branch_instructions,
-                       /*is_bounds_checked=*/false);
-  }
-
-  // min and max are indexes into a sorted array of case expressions.
-  intptr_t min() const { return min_; }
-  intptr_t max() const { return max_; }
-  // The fragment to continue building code for the branch.
-  Fragment branch_instructions() const { return branch_instructions_; }
-  // For leafs, whether the branch is known to be in the bounds of the
-  // overall switch.
-  bool is_bounds_checked() const { return is_bounds_checked_; }
-  bool is_leaf() const { return min_ == max_; }
-
- private:
-  SwitchRange(intptr_t min,
-              intptr_t max,
-              Fragment branch_instructions,
-              bool is_bounds_checked)
-      : min_(min),
-        max_(max),
-        branch_instructions_(branch_instructions),
-        is_bounds_checked_(is_bounds_checked) {}
-
-  intptr_t min_;
-  intptr_t max_;
-  Fragment branch_instructions_;
-  bool is_bounds_checked_;
-};
-
-// Helper for building flow graph for a switch statement.
-class SwitchHelper {
- public:
-  SwitchHelper(Zone* zone,
-               TokenPosition position,
-               bool is_exhaustive,
-               SwitchBlock* switch_block,
-               intptr_t case_count)
-      : zone_(zone),
-        position_(position),
-        is_exhaustive_(is_exhaustive),
-        switch_block_(switch_block),
-        case_count_(case_count),
-        case_bodies_(case_count),
-        case_expression_counts_(case_count),
-        expressions_(case_count),
-        sorted_expressions_(case_count) {
-    case_expression_counts_.FillWith(0, 0, case_count);
-  }
-
-  // A switch statement is optimizable if all expression are of the same type
-  // and have integer representations.
-  bool is_optimizable() const { return is_optimizable_; }
-  const TokenPosition& position() const { return position_; }
-  bool is_exhaustive() const { return is_exhaustive_; }
-  SwitchBlock* switch_block() { return switch_block_; }
-  intptr_t case_count() const { return case_count_; }
-
-  // Index of default case.
-  intptr_t default_case() const { return default_case_; }
-  void set_default_case(intptr_t index) {
-    ASSERT(default_case_ == -1);
-    default_case_ = index;
-  }
-
-  const GrowableArray<Fragment>& case_bodies() const { return case_bodies_; }
-
-  // Array of the expression counts for all cases.
-  const GrowableArray<intptr_t>& case_expression_counts() const {
-    return case_expression_counts_;
-  }
-
-  const GrowableArray<SwitchExpression>& expressions() const {
-    return expressions_;
-  }
-
-  const GrowableArray<SwitchExpression*>& sorted_expressions() const {
-    return sorted_expressions_;
-  }
-
-  // The common class of all expressions. The statement must be optimizable.
-  const Class& expression_class() const {
-    ASSERT(expression_class_ != nullptr);
-    return *expression_class_;
-  }
-
-  const Integer& expression_min() const {
-    ASSERT(expression_min_ != nullptr);
-    return *expression_min_;
-  }
-  const Integer& expression_max() const {
-    ASSERT(expression_max_ != nullptr);
-    return *expression_max_;
-  }
-
-  bool has_default() const { return default_case_ >= 0; }
-
-  bool is_enum_switch() const { return expression_class().is_enum_class(); }
-
-  // Returns size of [min..max] range, or kMaxInt64 on overflow.
-  int64_t ExpressionRange() const;
-
-  bool RequiresLowerBoundCheck() const;
-  bool RequiresUpperBoundCheck() const;
-
-  SwitchDispatch SelectDispatchStrategy();
-
-  void AddCaseBody(Fragment body) { case_bodies_.Add(body); }
-
-  void AddExpression(intptr_t case_index,
-                     TokenPosition position,
-                     const Instance& value);
-
- private:
-  void PrepareForOptimizedSwitch();
-
-  Zone* zone_;
-  bool is_optimizable_ = false;
-  const TokenPosition position_;
-  const bool is_exhaustive_;
-  SwitchBlock* const switch_block_;
-  const intptr_t case_count_;
-  intptr_t default_case_ = -1;
-  GrowableArray<Fragment> case_bodies_;
-  GrowableArray<intptr_t> case_expression_counts_;
-  GrowableArray<SwitchExpression> expressions_;
-  GrowableArray<SwitchExpression*> sorted_expressions_;
-  const Class* expression_class_ = nullptr;
-  const Integer* expression_min_ = nullptr;
-  const Integer* expression_max_ = nullptr;
-};
-
 }  // namespace kernel
 }  // namespace dart
 
diff --git a/tests/language/switch/backward_jump_test.dart b/tests/language/switch/backward_jump_test.dart
index dbcde00..d4bc491 100644
--- a/tests/language/switch/backward_jump_test.dart
+++ b/tests/language/switch/backward_jump_test.dart
@@ -2,11 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=
-// VMOptions=--force-switch-dispatch-type=0
-// VMOptions=--force-switch-dispatch-type=1
-// VMOptions=--force-switch-dispatch-type=2
-
 import 'package:expect/expect.dart';
 
 main() {
diff --git a/tests/language/switch/empty_block_case_test.dart b/tests/language/switch/empty_block_case_test.dart
index 4fbc593..6edaff4 100644
--- a/tests/language/switch/empty_block_case_test.dart
+++ b/tests/language/switch/empty_block_case_test.dart
@@ -6,11 +6,6 @@
 
 // Test that a case with an empty block does not fall through.
 
-// VMOptions=
-// VMOptions=--force-switch-dispatch-type=0
-// VMOptions=--force-switch-dispatch-type=1
-// VMOptions=--force-switch-dispatch-type=2
-
 class EmptyBlockCaseTest {
   static testMain() {
     var exception = null;
diff --git a/tests/language/switch/fallthru_runtime_test.dart b/tests/language/switch/fallthru_runtime_test.dart
index 373c93f..b1dd57d 100644
--- a/tests/language/switch/fallthru_runtime_test.dart
+++ b/tests/language/switch/fallthru_runtime_test.dart
@@ -4,14 +4,8 @@
 // Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-
 // Check that FallThroughError is thrown if switch clause does not terminate.
 
-// VMOptions=
-// VMOptions=--force-switch-dispatch-type=0
-// VMOptions=--force-switch-dispatch-type=1
-// VMOptions=--force-switch-dispatch-type=2
-
 import "package:expect/expect.dart";
 
 String test(int n) {
diff --git a/tests/language/switch/infinite_switch_label_test.dart b/tests/language/switch/infinite_switch_label_test.dart
index 816a52c..7f484cc 100644
--- a/tests/language/switch/infinite_switch_label_test.dart
+++ b/tests/language/switch/infinite_switch_label_test.dart
@@ -4,11 +4,6 @@
 
 // Test nested switch statement using labels.
 
-// VMOptions=
-// VMOptions=--force-switch-dispatch-type=0
-// VMOptions=--force-switch-dispatch-type=1
-// VMOptions=--force-switch-dispatch-type=2
-
 library nested_switch_label;
 
 import "package:expect/expect.dart";
diff --git a/tests/language/switch/label2_test.dart b/tests/language/switch/label2_test.dart
index e03084d..612e6a9 100644
--- a/tests/language/switch/label2_test.dart
+++ b/tests/language/switch/label2_test.dart
@@ -4,11 +4,6 @@
 
 // Test switch statement using labels.
 
-// VMOptions=
-// VMOptions=--force-switch-dispatch-type=0
-// VMOptions=--force-switch-dispatch-type=1
-// VMOptions=--force-switch-dispatch-type=2
-
 import 'package:expect/expect.dart';
 
 void main() {
diff --git a/tests/language/switch/label_test.dart b/tests/language/switch/label_test.dart
index 3a36837..290c84f 100644
--- a/tests/language/switch/label_test.dart
+++ b/tests/language/switch/label_test.dart
@@ -1,14 +1,8 @@
 // Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-
 // Test switch statement using labels.
 
-// VMOptions=
-// VMOptions=--force-switch-dispatch-type=0
-// VMOptions=--force-switch-dispatch-type=1
-// VMOptions=--force-switch-dispatch-type=2
-
 import "package:expect/expect.dart";
 
 class Switcher {
diff --git a/tests/language/switch/nested_switch_label_test.dart b/tests/language/switch/nested_switch_label_test.dart
index efc27a2..49c2754 100644
--- a/tests/language/switch/nested_switch_label_test.dart
+++ b/tests/language/switch/nested_switch_label_test.dart
@@ -4,11 +4,6 @@
 
 // Test nested switch statement using labels.
 
-// VMOptions=
-// VMOptions=--force-switch-dispatch-type=0
-// VMOptions=--force-switch-dispatch-type=1
-// VMOptions=--force-switch-dispatch-type=2
-
 library nested_switch_label;
 
 import "package:expect/expect.dart";
diff --git a/tests/language/switch/scope_test.dart b/tests/language/switch/scope_test.dart
index 4ca4c3b..938a393 100644
--- a/tests/language/switch/scope_test.dart
+++ b/tests/language/switch/scope_test.dart
@@ -1,14 +1,8 @@
 // Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-
 // Test that a new scope is introduced for each switch case.
 
-// VMOptions=
-// VMOptions=--force-switch-dispatch-type=0
-// VMOptions=--force-switch-dispatch-type=1
-// VMOptions=--force-switch-dispatch-type=2
-
 import "package:expect/expect.dart";
 
 class SwitchScopeTest {
diff --git a/tests/language/switch/switch6_test.dart b/tests/language/switch/switch6_test.dart
index 32edea5..43e09dc 100644
--- a/tests/language/switch/switch6_test.dart
+++ b/tests/language/switch/switch6_test.dart
@@ -1,14 +1,8 @@
 // Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-
 // The break is in the right scope, http://b/3428700 was agreed upon.
 
-// VMOptions=
-// VMOptions=--force-switch-dispatch-type=0
-// VMOptions=--force-switch-dispatch-type=1
-// VMOptions=--force-switch-dispatch-type=2
-
 import "package:expect/expect.dart";
 
 class Switch6Test {
diff --git a/tests/language/switch/switch_test.dart b/tests/language/switch/switch_test.dart
index 3198957..032c2b7 100644
--- a/tests/language/switch/switch_test.dart
+++ b/tests/language/switch/switch_test.dart
@@ -1,14 +1,8 @@
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-
 // Test switch statement.
 
-// VMOptions=
-// VMOptions=--force-switch-dispatch-type=0
-// VMOptions=--force-switch-dispatch-type=1
-// VMOptions=--force-switch-dispatch-type=2
-
 import "package:expect/expect.dart";
 
 class Switcher {
diff --git a/tests/language/switch/try_catch_test.dart b/tests/language/switch/try_catch_test.dart
index 56632e7..beee717 100644
--- a/tests/language/switch/try_catch_test.dart
+++ b/tests/language/switch/try_catch_test.dart
@@ -5,11 +5,6 @@
 // Regression test for issue 18869: Check that try-catch is working correctly
 // inside switch-case clauses.
 
-// VMOptions=
-// VMOptions=--force-switch-dispatch-type=0
-// VMOptions=--force-switch-dispatch-type=1
-// VMOptions=--force-switch-dispatch-type=2
-
 import "package:expect/expect.dart";
 
 test_switch() {
diff --git a/tests/language_2/switch/backward_jump_test.dart b/tests/language_2/switch/backward_jump_test.dart
index dbcde00..d4bc491 100644
--- a/tests/language_2/switch/backward_jump_test.dart
+++ b/tests/language_2/switch/backward_jump_test.dart
@@ -2,11 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// VMOptions=
-// VMOptions=--force-switch-dispatch-type=0
-// VMOptions=--force-switch-dispatch-type=1
-// VMOptions=--force-switch-dispatch-type=2
-
 import 'package:expect/expect.dart';
 
 main() {
diff --git a/tests/language_2/switch/empty_block_case_test.dart b/tests/language_2/switch/empty_block_case_test.dart
index 9b28adc..5e9cfed 100644
--- a/tests/language_2/switch/empty_block_case_test.dart
+++ b/tests/language_2/switch/empty_block_case_test.dart
@@ -8,11 +8,6 @@
 
 // Test that a case with an empty block does not fall through.
 
-// VMOptions=
-// VMOptions=--force-switch-dispatch-type=0
-// VMOptions=--force-switch-dispatch-type=1
-// VMOptions=--force-switch-dispatch-type=2
-
 class EmptyBlockCaseTest {
   static testMain() {
     var exception = null;
diff --git a/tests/language_2/switch/fallthru_runtime_test.dart b/tests/language_2/switch/fallthru_runtime_test.dart
index ca1057f..3bcdf44c 100644
--- a/tests/language_2/switch/fallthru_runtime_test.dart
+++ b/tests/language_2/switch/fallthru_runtime_test.dart
@@ -8,11 +8,6 @@
 // BSD-style license that can be found in the LICENSE file.
 // Check that FallThroughError is thrown if switch clause does not terminate.
 
-// VMOptions=
-// VMOptions=--force-switch-dispatch-type=0
-// VMOptions=--force-switch-dispatch-type=1
-// VMOptions=--force-switch-dispatch-type=2
-
 import "package:expect/expect.dart";
 
 String test(int n) {
diff --git a/tests/language_2/switch/infinite_switch_label_test.dart b/tests/language_2/switch/infinite_switch_label_test.dart
index 2ddfad6..82de828 100644
--- a/tests/language_2/switch/infinite_switch_label_test.dart
+++ b/tests/language_2/switch/infinite_switch_label_test.dart
@@ -6,11 +6,6 @@
 
 // Test nested switch statement using labels.
 
-// VMOptions=
-// VMOptions=--force-switch-dispatch-type=0
-// VMOptions=--force-switch-dispatch-type=1
-// VMOptions=--force-switch-dispatch-type=2
-
 library nested_switch_label;
 
 import "package:expect/expect.dart";
diff --git a/tests/language_2/switch/label2_test.dart b/tests/language_2/switch/label2_test.dart
index 4c2dbb6..d018623 100644
--- a/tests/language_2/switch/label2_test.dart
+++ b/tests/language_2/switch/label2_test.dart
@@ -6,11 +6,6 @@
 
 // Test switch statement using labels.
 
-// VMOptions=
-// VMOptions=--force-switch-dispatch-type=0
-// VMOptions=--force-switch-dispatch-type=1
-// VMOptions=--force-switch-dispatch-type=2
-
 import 'package:expect/expect.dart';
 
 void main() {
diff --git a/tests/language_2/switch/label_test.dart b/tests/language_2/switch/label_test.dart
index d67bd32..601330f 100644
--- a/tests/language_2/switch/label_test.dart
+++ b/tests/language_2/switch/label_test.dart
@@ -1,16 +1,10 @@
 // Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-
 // Test switch statement using labels.
 
 // @dart = 2.9
 
-// VMOptions=
-// VMOptions=--force-switch-dispatch-type=0
-// VMOptions=--force-switch-dispatch-type=1
-// VMOptions=--force-switch-dispatch-type=2
-
 import "package:expect/expect.dart";
 
 class Switcher {
diff --git a/tests/language_2/switch/nested_switch_label_test.dart b/tests/language_2/switch/nested_switch_label_test.dart
index 1d1b2b5..55b66b08 100644
--- a/tests/language_2/switch/nested_switch_label_test.dart
+++ b/tests/language_2/switch/nested_switch_label_test.dart
@@ -6,11 +6,6 @@
 
 // Test nested switch statement using labels.
 
-// VMOptions=
-// VMOptions=--force-switch-dispatch-type=0
-// VMOptions=--force-switch-dispatch-type=1
-// VMOptions=--force-switch-dispatch-type=2
-
 library nested_switch_label;
 
 import "package:expect/expect.dart";
diff --git a/tests/language_2/switch/scope_test.dart b/tests/language_2/switch/scope_test.dart
index c36ec4a..c1b6536 100644
--- a/tests/language_2/switch/scope_test.dart
+++ b/tests/language_2/switch/scope_test.dart
@@ -1,16 +1,10 @@
 // Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-
 // Test that a new scope is introduced for each switch case.
 
 // @dart = 2.9
 
-// VMOptions=
-// VMOptions=--force-switch-dispatch-type=0
-// VMOptions=--force-switch-dispatch-type=1
-// VMOptions=--force-switch-dispatch-type=2
-
 import "package:expect/expect.dart";
 
 class SwitchScopeTest {
diff --git a/tests/language_2/switch/switch6_test.dart b/tests/language_2/switch/switch6_test.dart
index 9dad116..61e9196 100644
--- a/tests/language_2/switch/switch6_test.dart
+++ b/tests/language_2/switch/switch6_test.dart
@@ -1,14 +1,8 @@
 // Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-
 // The break is in the right scope, http://b/3428700 was agreed upon.
 
-// VMOptions=
-// VMOptions=--force-switch-dispatch-type=0
-// VMOptions=--force-switch-dispatch-type=1
-// VMOptions=--force-switch-dispatch-type=2
-
 // @dart = 2.9
 
 import "package:expect/expect.dart";
diff --git a/tests/language_2/switch/switch_test.dart b/tests/language_2/switch/switch_test.dart
index f190806..52c131c 100644
--- a/tests/language_2/switch/switch_test.dart
+++ b/tests/language_2/switch/switch_test.dart
@@ -1,14 +1,8 @@
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
-
 // Test switch statement.
 
-// VMOptions=
-// VMOptions=--force-switch-dispatch-type=0
-// VMOptions=--force-switch-dispatch-type=1
-// VMOptions=--force-switch-dispatch-type=2
-
 // @dart = 2.9
 
 import "package:expect/expect.dart";
diff --git a/tests/language_2/switch/try_catch_test.dart b/tests/language_2/switch/try_catch_test.dart
index d95e476..a37c890 100644
--- a/tests/language_2/switch/try_catch_test.dart
+++ b/tests/language_2/switch/try_catch_test.dart
@@ -7,11 +7,6 @@
 // Regression test for issue 18869: Check that try-catch is working correctly
 // inside switch-case clauses.
 
-// VMOptions=
-// VMOptions=--force-switch-dispatch-type=0
-// VMOptions=--force-switch-dispatch-type=1
-// VMOptions=--force-switch-dispatch-type=2
-
 import "package:expect/expect.dart";
 
 test_switch() {