Merge "The HBoundsCheck should be the index input of String.charAt."
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index 439e3b6..dbafb0b 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -1843,11 +1843,11 @@
// so create the HArrayLength, HBoundsCheck and HArrayGet.
HArrayLength* length = new (arena) HArrayLength(str, dex_pc, /* is_string_length */ true);
invoke->GetBlock()->InsertInstructionBefore(length, invoke);
- HBoundsCheck* bounds_check =
- new (arena) HBoundsCheck(index, length, dex_pc, invoke->GetDexMethodIndex());
+ HBoundsCheck* bounds_check = new (arena) HBoundsCheck(
+ index, length, dex_pc, invoke->GetDexMethodIndex());
invoke->GetBlock()->InsertInstructionBefore(bounds_check, invoke);
- HArrayGet* array_get =
- new (arena) HArrayGet(str, index, Primitive::kPrimChar, dex_pc, /* is_string_char_at */ true);
+ HArrayGet* array_get = new (arena) HArrayGet(
+ str, bounds_check, Primitive::kPrimChar, dex_pc, /* is_string_char_at */ true);
invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, array_get);
bounds_check->CopyEnvironmentFrom(invoke->GetEnvironment());
GetGraph()->SetHasBoundsChecks(true);
diff --git a/test/536-checker-intrinsic-optimization/src/Main.java b/test/536-checker-intrinsic-optimization/src/Main.java
index 26475ae..ed7524c 100644
--- a/test/536-checker-intrinsic-optimization/src/Main.java
+++ b/test/536-checker-intrinsic-optimization/src/Main.java
@@ -153,8 +153,8 @@
/// CHECK-DAG: <<Pos:i\d+>> ParameterValue
/// CHECK-DAG: <<NullCk:l\d+>> NullCheck [<<String>>]
/// CHECK-DAG: <<Length:i\d+>> ArrayLength [<<NullCk>>] is_string_length:true
- /// CHECK-DAG: BoundsCheck [<<Pos>>,<<Length>>] is_string_char_at:true
- /// CHECK-DAG: <<Char:c\d+>> ArrayGet [<<NullCk>>,<<Pos>>] is_string_char_at:true
+ /// CHECK-DAG: <<Bounds:i\d+>> BoundsCheck [<<Pos>>,<<Length>>] is_string_char_at:true
+ /// CHECK-DAG: <<Char:c\d+>> ArrayGet [<<NullCk>>,<<Bounds>>] is_string_char_at:true
/// CHECK-DAG: Return [<<Char>>]
/// CHECK-START: char Main.$opt$noinline$stringCharAt(java.lang.String, int) instruction_simplifier (after)
@@ -174,8 +174,8 @@
/// CHECK-DAG: <<Pos:i\d+>> ParameterValue
/// CHECK-DAG: <<NullCk:l\d+>> NullCheck [<<String>>]
/// CHECK-DAG: <<Length:i\d+>> ArrayLength [<<NullCk>>] is_string_length:true
- /// CHECK-DAG: BoundsCheck [<<Pos>>,<<Length>>] is_string_char_at:true
- /// CHECK-DAG: <<Char:c\d+>> ArrayGet [<<NullCk>>,<<Pos>>] is_string_char_at:true
+ /// CHECK-DAG: <<Bounds:i\d+>> BoundsCheck [<<Pos>>,<<Length>>] is_string_char_at:true
+ /// CHECK-DAG: <<Char:c\d+>> ArrayGet [<<NullCk>>,<<Bounds>>] is_string_char_at:true
/// CHECK-DAG: Return [<<Char>>]
/// CHECK-START: char Main.$opt$noinline$stringCharAtCatch(java.lang.String, int) instruction_simplifier (after)
diff --git a/test/632-checker-char-at-bounds/expected.txt b/test/632-checker-char-at-bounds/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/632-checker-char-at-bounds/expected.txt
diff --git a/test/632-checker-char-at-bounds/info.txt b/test/632-checker-char-at-bounds/info.txt
new file mode 100644
index 0000000..10b9a44
--- /dev/null
+++ b/test/632-checker-char-at-bounds/info.txt
@@ -0,0 +1,2 @@
+Regression test for the optimization of String.charAt, which
+had its SSA dependency incorrect with its corresponding bound check.
diff --git a/test/632-checker-char-at-bounds/src/Main.java b/test/632-checker-char-at-bounds/src/Main.java
new file mode 100644
index 0000000..65022d0
--- /dev/null
+++ b/test/632-checker-char-at-bounds/src/Main.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+
+ /// CHECK-START: void Main.main(java.lang.String[]) licm (after)
+ /// CHECK-DAG: <<NullCheck:l\d+>> NullCheck
+ /// CHECK-DAG: <<BoundsCheck:i\d+>> BoundsCheck
+ /// CHECK-DAG: ArrayGet [<<NullCheck>>,<<BoundsCheck>>]
+ public static void main(String[] args) {
+ try {
+ String foo = myString;
+ foo.getClass(); // Make sure the null check is not in the loop.
+ char c = 0;
+ for (int i = 0; i < 10; i++) {
+ // The charAt may be licm'ed, but it has to be licm'ed with its
+ // bounds check.
+ c = foo.charAt(10000000);
+ }
+ System.out.println(c);
+ } catch (StringIndexOutOfBoundsException e) {
+ // Expected
+ }
+ }
+
+ static String myString = "foo";
+}