Test NewArrayWithData length rewrite

Bug: 202365761
Change-Id: I9edee6852f119406f549a046d452fde9b81e4836
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 293635b..07ba0ce 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
@@ -189,7 +189,7 @@
     this.appView = appView;
     this.options = appView.options();
     this.printer = printer;
-    this.codeRewriter = new CodeRewriter(appView, this);
+    this.codeRewriter = new CodeRewriter(appView);
     this.constantCanonicalizer = new ConstantCanonicalizer(codeRewriter);
     this.classInitializerDefaultsOptimization =
         new ClassInitializerDefaultsOptimization(appView, this);
@@ -1141,7 +1141,7 @@
     String previous = printMethod(code, "Initial IR (SSA)", null);
 
     if (options.testing.irModifier != null) {
-      options.testing.irModifier.accept(code);
+      options.testing.irModifier.accept(code, appView);
     }
 
     if (options.canHaveArtStringNewInitBug()) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index 71a8249..cdc2c6e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -85,7 +85,6 @@
 import com.android.tools.r8.ir.code.Value;
 import com.android.tools.r8.ir.code.ValueType;
 import com.android.tools.r8.ir.code.Xor;
-import com.android.tools.r8.ir.conversion.IRConverter;
 import com.android.tools.r8.ir.conversion.MethodProcessor;
 import com.android.tools.r8.ir.optimize.UtilityMethodsForCodeOptimizations.UtilityMethodForCodeOptimizations;
 import com.android.tools.r8.ir.optimize.controlflow.SwitchCaseAnalyzer;
@@ -156,15 +155,12 @@
   private static final int STOP_SHARED_CONSTANT_THRESHOLD = 50;
   private static final int SELF_RECURSION_LIMIT = 4;
 
-  public final IRConverter converter;
-
   private final AppView<?> appView;
   private final DexItemFactory dexItemFactory;
   private final InternalOptions options;
 
-  public CodeRewriter(AppView<?> appView, IRConverter converter) {
+  public CodeRewriter(AppView<?> appView) {
     this.appView = appView;
-    this.converter = converter;
     this.options = appView.options();
     this.dexItemFactory = appView.dexItemFactory();
   }
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 1def57e..2605507 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -1647,7 +1647,7 @@
     public boolean noLocalsTableOnInput = false;
     public boolean forceNameReflectionOptimization = false;
     public boolean enableNarrowAndWideningingChecksInD8 = false;
-    public Consumer<IRCode> irModifier = null;
+    public BiConsumer<IRCode, AppView<?>> irModifier = null;
     public Consumer<IRCode> inlineeIrModifier = null;
     public int basicBlockMuncherIterationLimit = NO_LIMIT;
     public boolean dontReportFailingCheckDiscarded = false;
diff --git a/src/test/java/com/android/tools/r8/cf/TryRangeTestRunner.java b/src/test/java/com/android/tools/r8/cf/TryRangeTestRunner.java
index aec1329..8f5dc82 100644
--- a/src/test/java/com/android/tools/r8/cf/TryRangeTestRunner.java
+++ b/src/test/java/com/android/tools/r8/cf/TryRangeTestRunner.java
@@ -13,6 +13,7 @@
 import com.android.tools.r8.cf.code.CfLabel;
 import com.android.tools.r8.cf.code.CfLoad;
 import com.android.tools.r8.cf.code.CfStackInstruction;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.CfCode;
 import com.android.tools.r8.ir.code.BasicBlock;
 import com.android.tools.r8.ir.code.IRCode;
@@ -84,7 +85,7 @@
     assert instructions.get(index + 4) instanceof CfStackInstruction;
   }
 
-  private void processIR(IRCode code) {
+  private void processIR(IRCode code, AppView<?> appView) {
     if (!code.method().qualifiedName().equals(TryRangeTestLimitRange.class.getName() + ".main")) {
       return;
     }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerPhiDirectUserAfterInlineTest.java b/src/test/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerPhiDirectUserAfterInlineTest.java
index 6001549..5cea9fa 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerPhiDirectUserAfterInlineTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/classinliner/ClassInlinerPhiDirectUserAfterInlineTest.java
@@ -15,6 +15,7 @@
 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.Argument;
 import com.android.tools.r8.ir.code.BasicBlock;
 import com.android.tools.r8.ir.code.IRCode;
@@ -86,6 +87,10 @@
             });
   }
 
+  private void modifyIr(IRCode irCode, AppView<?> appView) {
+    modifyIr(irCode);
+  }
+
   private void modifyIr(IRCode irCode) {
     if (irCode.context().getReference().qualifiedName().equals(A.class.getTypeName() + ".foo")) {
       assertEquals(7, irCode.blocks.size());
diff --git a/src/test/java/com/android/tools/r8/rewrite/arrays/ArrayLengthRewriteTest.java b/src/test/java/com/android/tools/r8/rewrite/arrays/ArrayLengthRewriteTest.java
index 87ae7f4..40d6dbf 100644
--- a/src/test/java/com/android/tools/r8/rewrite/arrays/ArrayLengthRewriteTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/arrays/ArrayLengthRewriteTest.java
@@ -3,6 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.rewrite.arrays;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
 import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
@@ -17,10 +21,6 @@
 import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeTrue;
-
 @RunWith(Parameterized.class)
 public class ArrayLengthRewriteTest extends TestBase {
   @Parameters(name = "{0}, debug = {1}")
@@ -62,7 +62,7 @@
     assumeTrue(parameters.isDexRuntime());
 
     testForD8()
-        .setMinApi(parameters.getRuntime())
+        .setMinApi(parameters.getApiLevel())
         .setMode(debugMode ? CompilationMode.DEBUG : CompilationMode.RELEASE)
         .addProgramClasses(Main.class)
         .run(parameters.getRuntime(), Main.class)
@@ -72,7 +72,7 @@
 
   @Test public void r8() throws Exception {
     testForR8(parameters.getBackend())
-        .setMinApi(parameters.getRuntime())
+        .setMinApi(parameters.getApiLevel())
         .setMode(debugMode ? CompilationMode.DEBUG : CompilationMode.RELEASE)
         .addProgramClasses(Main.class)
         .addKeepMainRule(Main.class)
diff --git a/src/test/java/com/android/tools/r8/rewrite/arrays/ArrayWithDataLengthRewriteTest.java b/src/test/java/com/android/tools/r8/rewrite/arrays/ArrayWithDataLengthRewriteTest.java
new file mode 100644
index 0000000..4a76a6a
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/rewrite/arrays/ArrayWithDataLengthRewriteTest.java
@@ -0,0 +1,85 @@
+// Copyright (c) 2021, the R8 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.
+package com.android.tools.r8.rewrite.arrays;
+
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+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.optimize.CodeRewriter;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class ArrayWithDataLengthRewriteTest extends TestBase {
+  @Parameters(name = "{0}")
+  public static Iterable<?> data() {
+    return buildParameters(getTestParameters().withDexRuntimes().withAllApiLevels().build());
+  }
+
+  private final TestParameters parameters;
+
+  public ArrayWithDataLengthRewriteTest(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  private static final String[] expectedOutput = {"3"};
+
+  @Test
+  public void d8() throws Exception {
+    testForD8()
+        .setMinApi(parameters.getApiLevel())
+        .setMode(CompilationMode.RELEASE)
+        .addProgramClasses(Main.class)
+        .addOptionsModification(opt -> opt.testing.irModifier = this::transformArray)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(expectedOutput)
+        .inspect(this::assertNoArrayLength);
+  }
+
+  @Test
+  public void r8() throws Exception {
+    testForR8(parameters.getBackend())
+        .setMinApi(parameters.getRuntime())
+        .addProgramClasses(Main.class)
+        .addOptionsModification(opt -> opt.testing.irModifier = this::transformArray)
+        .addKeepMainRule(Main.class)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines(expectedOutput)
+        .inspect(this::assertNoArrayLength);
+  }
+
+  private void transformArray(IRCode irCode, AppView<?> appView) {
+    if (irCode.context().getReference().getName().toString().contains("main")) {
+      new CodeRewriter(appView).simplifyArrayConstruction(irCode);
+      assertTrue(irCode.streamInstructions().anyMatch(Instruction::isNewArrayFilledData));
+    }
+  }
+
+  private void assertNoArrayLength(CodeInspector inspector) {
+    ClassSubject mainClass = inspector.clazz(Main.class);
+    assertTrue(mainClass.isPresent());
+    assertTrue(
+        mainClass.mainMethod().streamInstructions().noneMatch(InstructionSubject::isArrayLength));
+  }
+
+  public static final class Main {
+    public static void main(String[] args) {
+      int[] ints = new int[3];
+      ints[0] = 5;
+      ints[1] = 6;
+      ints[2] = 1;
+      System.out.println(ints.length);
+    }
+  }
+}