Introduce StringSwitch instructions in D8

Change-Id: I1bfc0b3b1b97f84c767b1be9fc6c96f765545beb
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index bd261a3..9d6a8b6 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -35,6 +35,7 @@
 import com.android.tools.r8.ir.conversion.passes.FilledNewArrayRewriter;
 import com.android.tools.r8.ir.conversion.passes.MoveResultRewriter;
 import com.android.tools.r8.ir.conversion.passes.ParentConstructorHoistingCodeRewriter;
+import com.android.tools.r8.ir.conversion.passes.StringSwitchConverter;
 import com.android.tools.r8.ir.conversion.passes.StringSwitchRemover;
 import com.android.tools.r8.ir.conversion.passes.ThrowCatchOptimizer;
 import com.android.tools.r8.ir.conversion.passes.TrivialPhiSimplifier;
@@ -584,6 +585,13 @@
       return timing;
     }
 
+    // In R8, StringSwitch instructions are introduced when entering the LIR phase. In D8, we don't
+    // use LIR, so we explicitly introduce StringSwitch instructions here.
+    if (!options.getTestingOptions().isSupportedLirPhase()) {
+      new StringSwitchConverter(appView)
+          .run(code, methodProcessor, methodProcessingContext, timing);
+    }
+
     if (options.canHaveArtStringNewInitBug()) {
       timing.begin("Check for new-init issue");
       TrivialPhiSimplifier.ensureDirectStringNewToInit(appView, code);
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/switches/ConvertRemovedStringSwitchTest.java b/src/test/java/com/android/tools/r8/ir/optimize/switches/ConvertRemovedStringSwitchTest.java
index 1239133..fc490c64 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/switches/ConvertRemovedStringSwitchTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/switches/ConvertRemovedStringSwitchTest.java
@@ -13,8 +13,14 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.conversion.passes.StringSwitchConverter;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.Reporter;
+import com.android.tools.r8.utils.Timing;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
@@ -52,7 +58,7 @@
         .assertSuccessWithOutputLines("A", "B", "C", "D", "E!");
   }
 
-  private void inspect(CodeInspector inspector) {
+  private void inspect(CodeInspector inspector) throws Exception {
     ClassSubject classSubject = inspector.clazz(TestClass.class);
     assertThat(classSubject, isPresent());
 
@@ -69,7 +75,12 @@
     assertEquals(1, stringCounts.getInt("E!"));
 
     // Verify that we can rebuild the StringSwitch instruction.
-    IRCode code = mainMethodSubject.buildIR();
+    AppView<?> appView =
+        computeAppView(
+            AndroidApp.builder().build(),
+            new InternalOptions(inspector.getFactory(), new Reporter()));
+    IRCode code = mainMethodSubject.buildIR(appView);
+    new StringSwitchConverter(appView).run(code, Timing.empty());
     assertTrue(code.streamInstructions().anyMatch(Instruction::isStringSwitch));
   }
 
diff --git a/src/test/testbase/java/com/android/tools/r8/TestBase.java b/src/test/testbase/java/com/android/tools/r8/TestBase.java
index a0dbfa4..5512419 100644
--- a/src/test/testbase/java/com/android/tools/r8/TestBase.java
+++ b/src/test/testbase/java/com/android/tools/r8/TestBase.java
@@ -793,9 +793,14 @@
   }
 
   protected static AppView<AppInfo> computeAppView(AndroidApp app) throws Exception {
+    return computeAppView(app, new InternalOptions());
+  }
+
+  protected static AppView<AppInfo> computeAppView(AndroidApp app, InternalOptions options)
+      throws Exception {
     AppInfo appInfo =
         AppInfo.createInitialAppInfo(
-            readApplicationForDexOutput(app, new InternalOptions()),
+            readApplicationForDexOutput(app, options),
             GlobalSyntheticsStrategy.forNonSynthesizing());
     return AppView.createForD8(appInfo);
   }