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";
+}