Merge "Support InlineInfo in StackMap."
diff --git a/Android.mk b/Android.mk
index e7623c6..3467f1d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -55,16 +55,16 @@
 clean-oat-target:
 	adb root
 	adb wait-for-device remount
-	adb shell sh -c "rm -rf $(ART_TARGET_NATIVETEST_DIR)"
-	adb shell sh -c "rm -rf $(ART_TARGET_TEST_DIR)"
-	adb shell sh -c "rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*/*"
-	adb shell sh -c "rm -rf $(DEXPREOPT_BOOT_JAR_DIR)/$(DEX2OAT_TARGET_ARCH)"
-	adb shell sh -c "rm -rf system/app/$(DEX2OAT_TARGET_ARCH)"
+	adb shell rm -rf $(ART_TARGET_NATIVETEST_DIR)
+	adb shell rm -rf $(ART_TARGET_TEST_DIR)
+	adb shell rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*/*
+	adb shell rm -rf $(DEXPREOPT_BOOT_JAR_DIR)/$(DEX2OAT_TARGET_ARCH)
+	adb shell rm -rf system/app/$(DEX2OAT_TARGET_ARCH)
 ifdef TARGET_2ND_ARCH
-	adb shell sh -c "rm -rf $(DEXPREOPT_BOOT_JAR_DIR)/$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH)"
-	adb shell sh -c "rm -rf system/app/$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH)"
+	adb shell rm -rf $(DEXPREOPT_BOOT_JAR_DIR)/$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH)
+	adb shell rm -rf system/app/$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH)
 endif
-	adb shell sh -c "rm -rf data/run-test/test-*/dalvik-cache/*"
+	adb shell rm -rf data/run-test/test-*/dalvik-cache/*
 
 ifneq ($(art_dont_bother),true)
 
@@ -404,9 +404,9 @@
 use-art-full:
 	adb root
 	adb wait-for-device shell stop
-	adb shell sh -c "rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*"
-	adb shell setprop dalvik.vm.dex2oat-filter ""
-	adb shell setprop dalvik.vm.image-dex2oat-filter ""
+	adb shell rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*
+	adb shell setprop dalvik.vm.dex2oat-filter \"\"
+	adb shell setprop dalvik.vm.image-dex2oat-filter \"\"
 	adb shell setprop persist.sys.dalvik.vm.lib.2 libart.so
 	adb shell start
 
@@ -414,9 +414,9 @@
 use-artd-full:
 	adb root
 	adb wait-for-device shell stop
-	adb shell sh -c "rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*"
-	adb shell setprop dalvik.vm.dex2oat-filter ""
-	adb shell setprop dalvik.vm.image-dex2oat-filter ""
+	adb shell rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*
+	adb shell setprop dalvik.vm.dex2oat-filter \"\"
+	adb shell setprop dalvik.vm.image-dex2oat-filter \"\"
 	adb shell setprop persist.sys.dalvik.vm.lib.2 libartd.so
 	adb shell start
 
@@ -424,7 +424,7 @@
 use-art-verify-at-runtime:
 	adb root
 	adb wait-for-device shell stop
-	adb shell sh -c "rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*"
+	adb shell rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*
 	adb shell setprop dalvik.vm.dex2oat-filter "verify-at-runtime"
 	adb shell setprop dalvik.vm.image-dex2oat-filter "verify-at-runtime"
 	adb shell setprop persist.sys.dalvik.vm.lib.2 libart.so
@@ -434,7 +434,7 @@
 use-art-interpret-only:
 	adb root
 	adb wait-for-device shell stop
-	adb shell sh -c "rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*"
+	adb shell rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*
 	adb shell setprop dalvik.vm.dex2oat-filter "interpret-only"
 	adb shell setprop dalvik.vm.image-dex2oat-filter "interpret-only"
 	adb shell setprop persist.sys.dalvik.vm.lib.2 libart.so
@@ -444,7 +444,7 @@
 use-artd-interpret-only:
 	adb root
 	adb wait-for-device shell stop
-	adb shell sh -c "rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*"
+	adb shell rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*
 	adb shell setprop dalvik.vm.dex2oat-filter "interpret-only"
 	adb shell setprop dalvik.vm.image-dex2oat-filter "interpret-only"
 	adb shell setprop persist.sys.dalvik.vm.lib.2 libartd.so
@@ -454,7 +454,7 @@
 use-art-verify-none:
 	adb root
 	adb wait-for-device shell stop
-	adb shell sh -c "rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*"
+	adb shell rm -rf $(ART_TARGET_DALVIK_CACHE_DIR)/*
 	adb shell setprop dalvik.vm.dex2oat-filter "verify-none"
 	adb shell setprop dalvik.vm.image-dex2oat-filter "verify-none"
 	adb shell setprop persist.sys.dalvik.vm.lib.2 libart.so
diff --git a/build/Android.common_build.mk b/build/Android.common_build.mk
index d1724cc..3e427a3 100644
--- a/build/Android.common_build.mk
+++ b/build/Android.common_build.mk
@@ -110,10 +110,6 @@
 ART_TARGET_CLANG_CFLAGS_arm64  += \
   -DNVALGRIND
 
-# FIXME: upstream LLVM has a vectorizer bug that needs to be fixed
-ART_TARGET_CLANG_CFLAGS_arm64 += \
-  -fno-vectorize
-
 # Warn about thread safety violations with clang.
 art_clang_cflags := -Wthread-safety
 
diff --git a/build/Android.common_path.mk b/build/Android.common_path.mk
index e0c0b0c..2d6b6a3 100644
--- a/build/Android.common_path.mk
+++ b/build/Android.common_path.mk
@@ -80,7 +80,7 @@
 TARGET_CORE_IMG_LOCATION := $(ART_TARGET_TEST_OUT)/core.art
 
 # Jar files for core.art.
-TARGET_CORE_JARS := core-libart conscrypt okhttp core-junit bouncycastle
+TARGET_CORE_JARS := core-libart conscrypt okhttp bouncycastle
 HOST_CORE_JARS := $(addsuffix -hostdex,$(TARGET_CORE_JARS))
 
 HOST_CORE_DEX_LOCATIONS   := $(foreach jar,$(HOST_CORE_JARS),  $(HOST_OUT_JAVA_LIBRARIES)/$(jar).jar)
diff --git a/compiler/dex/gvn_dead_code_elimination.cc b/compiler/dex/gvn_dead_code_elimination.cc
index a4319c3..6d8a7da 100644
--- a/compiler/dex/gvn_dead_code_elimination.cc
+++ b/compiler/dex/gvn_dead_code_elimination.cc
@@ -20,6 +20,7 @@
 
 #include "base/bit_vector-inl.h"
 #include "base/macros.h"
+#include "base/allocator.h"
 #include "compiler_enums.h"
 #include "dataflow_iterator-inl.h"
 #include "dex_instruction.h"
@@ -57,14 +58,12 @@
       low_def_over_high_word = prev_data->low_def_over_high_word;
     } else {
       prev_value = prev_data->prev_value_high;
-      low_def_over_high_word =
-          prev_data->prev_value_high.value != kNPos && !prev_data->high_def_over_low_word;
+      low_def_over_high_word = !prev_data->high_def_over_low_word;
     }
   } else {
     if (prev_data->vreg_def == v_reg) {
       prev_value_high = prev_data->prev_value;
-      high_def_over_low_word =
-          prev_data->prev_value.value != kNPos && !prev_data->low_def_over_high_word;
+      high_def_over_low_word = !prev_data->low_def_over_high_word;
     } else {
       prev_value_high = prev_data->prev_value_high;
       high_def_over_low_word = prev_data->high_def_over_low_word;
@@ -75,6 +74,9 @@
 GvnDeadCodeElimination::VRegChains::VRegChains(uint32_t num_vregs, ScopedArenaAllocator* alloc)
     : num_vregs_(num_vregs),
       vreg_data_(alloc->AllocArray<VRegValue>(num_vregs, kArenaAllocMisc)),
+      vreg_high_words_(num_vregs, false, Allocator::GetNoopAllocator(),
+                       BitVector::BitsToWords(num_vregs),
+                       alloc->AllocArray<uint32_t>(BitVector::BitsToWords(num_vregs))),
       mir_data_(alloc->Adapter()) {
   mir_data_.reserve(100);
 }
@@ -82,6 +84,7 @@
 inline void GvnDeadCodeElimination::VRegChains::Reset() {
   DCHECK(mir_data_.empty());
   std::fill_n(vreg_data_, num_vregs_, VRegValue());
+  vreg_high_words_.ClearAllBits();
 }
 
 void GvnDeadCodeElimination::VRegChains::AddMIRWithDef(MIR* mir, int v_reg, bool wide,
@@ -93,24 +96,26 @@
   data->wide_def = wide;
   data->vreg_def = v_reg;
 
-  if (vreg_data_[v_reg].change != kNPos &&
-      mir_data_[vreg_data_[v_reg].change].vreg_def + 1 == v_reg) {
-    data->low_def_over_high_word = true;
-  }
-  data->prev_value = vreg_data_[v_reg];
   DCHECK_LT(static_cast<size_t>(v_reg), num_vregs_);
+  data->prev_value = vreg_data_[v_reg];
+  data->low_def_over_high_word =
+      (vreg_data_[v_reg].change != kNPos)
+      ? GetMIRData(vreg_data_[v_reg].change)->vreg_def + 1 == v_reg
+      : vreg_high_words_.IsBitSet(v_reg);
   vreg_data_[v_reg].value = new_value;
   vreg_data_[v_reg].change = pos;
+  vreg_high_words_.ClearBit(v_reg);
 
   if (wide) {
-    if (vreg_data_[v_reg + 1].change != kNPos &&
-        mir_data_[vreg_data_[v_reg + 1].change].vreg_def == v_reg + 1) {
-      data->high_def_over_low_word = true;
-    }
-    data->prev_value_high = vreg_data_[v_reg + 1];
     DCHECK_LT(static_cast<size_t>(v_reg + 1), num_vregs_);
+    data->prev_value_high = vreg_data_[v_reg + 1];
+    data->high_def_over_low_word =
+        (vreg_data_[v_reg + 1].change != kNPos)
+        ? GetMIRData(vreg_data_[v_reg + 1].change)->vreg_def == v_reg + 1
+        : !vreg_high_words_.IsBitSet(v_reg + 1);
     vreg_data_[v_reg + 1].value = new_value;
     vreg_data_[v_reg + 1].change = pos;
+    vreg_high_words_.SetBit(v_reg + 1);
   }
 }
 
@@ -123,9 +128,17 @@
   if (data->has_def) {
     DCHECK_EQ(vreg_data_[data->vreg_def].change, NumMIRs() - 1u);
     vreg_data_[data->vreg_def] = data->prev_value;
+    DCHECK(!vreg_high_words_.IsBitSet(data->vreg_def));
+    if (data->low_def_over_high_word) {
+      vreg_high_words_.SetBit(data->vreg_def);
+    }
     if (data->wide_def) {
       DCHECK_EQ(vreg_data_[data->vreg_def + 1].change, NumMIRs() - 1u);
       vreg_data_[data->vreg_def + 1] = data->prev_value_high;
+      DCHECK(vreg_high_words_.IsBitSet(data->vreg_def + 1));
+      if (data->high_def_over_low_word) {
+        vreg_high_words_.ClearBit(data->vreg_def + 1);
+      }
     }
   }
   mir_data_.pop_back();
@@ -169,6 +182,7 @@
   uint16_t change = vreg_data_[v_reg].change;
   if (change == kNPos) {
     vreg_data_[v_reg].value = value;
+    vreg_high_words_.SetBit(v_reg);
   } else {
     while (true) {
       MIRData* data = &mir_data_[change];
@@ -208,6 +222,7 @@
         }
       }
       vreg_data_[v_reg].value = old_value;
+      DCHECK(!vreg_high_words_.IsBitSet(v_reg));  // Keep marked as low word.
     }
   } else {
     DCHECK_LT(static_cast<size_t>(v_reg + 1), num_vregs_);
@@ -223,6 +238,7 @@
         old_value = lvn->GetStartingVregValueNumber(v_reg);
       }
       vreg_data_[v_reg].value = old_value;
+      DCHECK(!vreg_high_words_.IsBitSet(v_reg));  // Keep marked as low word.
     }
     if (check_high && vreg_data_[v_reg + 1].value == kNoValue) {
       uint16_t old_value = lvn->GetStartingVregValueNumber(v_reg + 1);
@@ -234,6 +250,7 @@
         }
       }
       vreg_data_[v_reg + 1].value = old_value;
+      DCHECK(!vreg_high_words_.IsBitSet(v_reg + 1));  // Keep marked as low word.
     }
   }
 }
@@ -300,6 +317,8 @@
     if (next_change == kNPos) {
       DCHECK_EQ(vreg_data_[v_reg].change, old_change);
       vreg_data_[v_reg].change = new_change;
+      DCHECK_EQ(vreg_high_words_.IsBitSet(v_reg), v_reg == old_data->vreg_def + 1);
+      // No change in vreg_high_words_.
     } else {
       DCHECK_EQ(mir_data_[next_change].PrevChange(v_reg), old_change);
       mir_data_[next_change].SetPrevChange(v_reg, new_change);
@@ -316,6 +335,12 @@
     if (next_change == kNPos) {
       DCHECK_EQ(vreg_data_[v_reg].change, change);
       vreg_data_[v_reg] = (data->vreg_def == v_reg) ? data->prev_value : data->prev_value_high;
+      DCHECK_EQ(vreg_high_words_.IsBitSet(v_reg), v_reg == data->vreg_def + 1);
+      if (data->vreg_def == v_reg && data->low_def_over_high_word) {
+        vreg_high_words_.SetBit(v_reg);
+      } else if (data->vreg_def != v_reg && data->high_def_over_low_word) {
+        vreg_high_words_.ClearBit(v_reg);
+      }
     } else {
       DCHECK_EQ(mir_data_[next_change].PrevChange(v_reg), change);
       mir_data_[next_change].RemovePrevChange(v_reg, data);
diff --git a/compiler/dex/gvn_dead_code_elimination.h b/compiler/dex/gvn_dead_code_elimination.h
index bc75a01..06022db 100644
--- a/compiler/dex/gvn_dead_code_elimination.h
+++ b/compiler/dex/gvn_dead_code_elimination.h
@@ -121,6 +121,7 @@
    private:
     const uint32_t num_vregs_;
     VRegValue* const vreg_data_;
+    BitVector vreg_high_words_;
     ScopedArenaVector<MIRData> mir_data_;
   };
 
diff --git a/compiler/dex/gvn_dead_code_elimination_test.cc b/compiler/dex/gvn_dead_code_elimination_test.cc
index efb32bb..de591d0 100644
--- a/compiler/dex/gvn_dead_code_elimination_test.cc
+++ b/compiler/dex/gvn_dead_code_elimination_test.cc
@@ -1896,4 +1896,91 @@
   EXPECT_EQ(2u, phi->dalvikInsn.vA);
 }
 
+TEST_F(GvnDeadCodeEliminationTestDiamond, LongOverlaps1) {
+  static const MIRDef mirs[] = {
+      DEF_CONST_WIDE(3, Instruction::CONST_WIDE, 0u, 1000u),
+      DEF_CONST_WIDE(3, Instruction::CONST_WIDE, 2u, 1000u),
+      DEF_MOVE_WIDE(4, Instruction::MOVE_WIDE, 4u, 0u),
+      DEF_MOVE_WIDE(4, Instruction::MOVE_WIDE, 6u, 2u),
+      DEF_MOVE_WIDE(4, Instruction::MOVE_WIDE, 8u, 4u),
+      DEF_MOVE_WIDE(4, Instruction::MOVE_WIDE, 10u, 6u),
+  };
+
+  // The last insn should overlap the first and second.
+  static const int32_t sreg_to_vreg_map[] = { 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3 };
+  PrepareSRegToVRegMap(sreg_to_vreg_map);
+
+  PrepareMIRs(mirs);
+  static const int32_t wide_sregs[] = { 0, 2, 4, 6, 8, 10 };
+  MarkAsWideSRegs(wide_sregs);
+  PerformGVN_DCE();
+
+  ASSERT_EQ(arraysize(mirs), value_names_.size());
+  EXPECT_EQ(value_names_[0], value_names_[1]);
+  EXPECT_EQ(value_names_[0], value_names_[2]);
+  EXPECT_EQ(value_names_[0], value_names_[3]);
+  EXPECT_EQ(value_names_[0], value_names_[4]);
+
+  static const bool eliminated[] = {
+      false, false, false, false, false, false,
+  };
+  static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
+  for (size_t i = 0; i != arraysize(eliminated); ++i) {
+    bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
+    EXPECT_EQ(eliminated[i], actually_eliminated) << i;
+  }
+}
+
+TEST_F(GvnDeadCodeEliminationTestSimple, MixedOverlaps1) {
+  static const MIRDef mirs[] = {
+      DEF_CONST(3, Instruction::CONST, 0u, 1000u),
+      DEF_MOVE(3, Instruction::MOVE, 1u, 0u),
+      DEF_CONST(3, Instruction::CONST, 2u, 2000u),
+      { 3, Instruction::INT_TO_LONG, 0, 0u, 1, { 2u }, 2, { 3u, 4u} },
+      DEF_MOVE_WIDE(3, Instruction::MOVE_WIDE, 5u, 3u),
+      DEF_CONST(3, Instruction::CONST, 7u, 3000u),
+      DEF_CONST(3, Instruction::CONST, 8u, 4000u),
+  };
+
+  static const int32_t sreg_to_vreg_map[] = { 1, 2, 0, 0, 1, 3, 4, 0, 1 };
+  PrepareSRegToVRegMap(sreg_to_vreg_map);
+
+  PrepareMIRs(mirs);
+  static const int32_t wide_sregs[] = { 3, 5 };
+  MarkAsWideSRegs(wide_sregs);
+  PerformGVN_DCE();
+
+  ASSERT_EQ(arraysize(mirs), value_names_.size());
+  static const size_t diff_indexes[] = { 0, 2, 3, 5, 6 };
+  ExpectValueNamesNE(diff_indexes);
+  EXPECT_EQ(value_names_[0], value_names_[1]);
+  EXPECT_EQ(value_names_[3], value_names_[4]);
+
+  static const bool eliminated[] = {
+      false, true, false, false, true, false, false,
+  };
+  static_assert(arraysize(eliminated) == arraysize(mirs), "array size mismatch");
+  for (size_t i = 0; i != arraysize(eliminated); ++i) {
+    bool actually_eliminated = (static_cast<int>(mirs_[i].dalvikInsn.opcode) == kMirOpNop);
+    EXPECT_EQ(eliminated[i], actually_eliminated) << i;
+  }
+  // Check renamed registers in CONST.
+  MIR* cst = &mirs_[0];
+  ASSERT_EQ(Instruction::CONST, cst->dalvikInsn.opcode);
+  ASSERT_EQ(0, cst->ssa_rep->num_uses);
+  ASSERT_EQ(1, cst->ssa_rep->num_defs);
+  EXPECT_EQ(1, cst->ssa_rep->defs[0]);
+  EXPECT_EQ(2u, cst->dalvikInsn.vA);
+  // Check renamed registers in INT_TO_LONG.
+  MIR* int_to_long = &mirs_[3];
+  ASSERT_EQ(Instruction::INT_TO_LONG, int_to_long->dalvikInsn.opcode);
+  ASSERT_EQ(1, int_to_long->ssa_rep->num_uses);
+  EXPECT_EQ(2, int_to_long->ssa_rep->uses[0]);
+  ASSERT_EQ(2, int_to_long->ssa_rep->num_defs);
+  EXPECT_EQ(5, int_to_long->ssa_rep->defs[0]);
+  EXPECT_EQ(6, int_to_long->ssa_rep->defs[1]);
+  EXPECT_EQ(3u, int_to_long->dalvikInsn.vA);
+  EXPECT_EQ(0u, int_to_long->dalvikInsn.vB);
+}
+
 }  // namespace art
diff --git a/compiler/elf_writer.cc b/compiler/elf_writer.cc
index 47402f3..f75638d 100644
--- a/compiler/elf_writer.cc
+++ b/compiler/elf_writer.cc
@@ -39,16 +39,17 @@
 }
 
 void ElfWriter::GetOatElfInformation(File* file,
-                                     size_t& oat_loaded_size,
-                                     size_t& oat_data_offset) {
+                                     size_t* oat_loaded_size,
+                                     size_t* oat_data_offset) {
   std::string error_msg;
   std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, false, false, &error_msg));
   CHECK(elf_file.get() != nullptr) << error_msg;
 
-  oat_loaded_size = elf_file->GetLoadedSize();
-  CHECK_NE(0U, oat_loaded_size);
-  oat_data_offset = GetOatDataAddress(elf_file.get());
-  CHECK_NE(0U, oat_data_offset);
+  bool success = elf_file->GetLoadedSize(oat_loaded_size, &error_msg);
+  CHECK(success) << error_msg;
+  CHECK_NE(0U, *oat_loaded_size);
+  *oat_data_offset = GetOatDataAddress(elf_file.get());
+  CHECK_NE(0U, *oat_data_offset);
 }
 
 bool ElfWriter::Fixup(File* file, uintptr_t oat_data_begin) {
diff --git a/compiler/elf_writer.h b/compiler/elf_writer.h
index 033c1f8..8e13b51 100644
--- a/compiler/elf_writer.h
+++ b/compiler/elf_writer.h
@@ -38,8 +38,8 @@
   // Looks up information about location of oat file in elf file container.
   // Used for ImageWriter to perform memory layout.
   static void GetOatElfInformation(File* file,
-                                   size_t& oat_loaded_size,
-                                   size_t& oat_data_offset);
+                                   size_t* oat_loaded_size,
+                                   size_t* oat_data_offset);
 
   // Returns runtime oat_data runtime address for an opened ElfFile.
   static uintptr_t GetOatDataAddress(ElfFile* elf_file);
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 4dc7509..195949b 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -166,7 +166,7 @@
 
   size_t oat_loaded_size = 0;
   size_t oat_data_offset = 0;
-  ElfWriter::GetOatElfInformation(oat_file.get(), oat_loaded_size, oat_data_offset);
+  ElfWriter::GetOatElfInformation(oat_file.get(), &oat_loaded_size, &oat_data_offset);
 
   Thread::Current()->TransitionFromSuspendedToRunnable();
   CreateHeader(oat_loaded_size, oat_data_offset);
diff --git a/compiler/jni/quick/jni_compiler.cc b/compiler/jni/quick/jni_compiler.cc
index 6f2cb25..a06303d 100644
--- a/compiler/jni/quick/jni_compiler.cc
+++ b/compiler/jni/quick/jni_compiler.cc
@@ -138,7 +138,8 @@
     FrameOffset handle_scope_offset = main_jni_conv->CurrentParamHandleScopeEntryOffset();
     // Check handle scope offset is within frame
     CHECK_LT(handle_scope_offset.Uint32Value(), frame_size);
-    // TODO: Insert the read barrier for this load.
+    // Note this LoadRef() already includes the heap poisoning negation.
+    // Note this LoadRef() does not include read barrier. It will be handled below.
     __ LoadRef(main_jni_conv->InterproceduralScratchRegister(),
                mr_conv->MethodRegister(), mirror::ArtMethod::DeclaringClassOffset());
     __ VerifyObject(main_jni_conv->InterproceduralScratchRegister(), false);
@@ -189,6 +190,49 @@
   size_t current_out_arg_size = main_out_arg_size;
   __ IncreaseFrameSize(main_out_arg_size);
 
+  // Call the read barrier for the declaring class loaded from the method for a static call.
+  // Note that we always have outgoing param space available for at least two params.
+  if (kUseReadBarrier && is_static) {
+    ThreadOffset<4> read_barrier32 = QUICK_ENTRYPOINT_OFFSET(4, pReadBarrierJni);
+    ThreadOffset<8> read_barrier64 = QUICK_ENTRYPOINT_OFFSET(8, pReadBarrierJni);
+    main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size));
+    main_jni_conv->Next();  // Skip JNIEnv.
+    FrameOffset class_handle_scope_offset = main_jni_conv->CurrentParamHandleScopeEntryOffset();
+    main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size));
+    // Pass the handle for the class as the first argument.
+    if (main_jni_conv->IsCurrentParamOnStack()) {
+      FrameOffset out_off = main_jni_conv->CurrentParamStackOffset();
+      __ CreateHandleScopeEntry(out_off, class_handle_scope_offset,
+                         mr_conv->InterproceduralScratchRegister(),
+                         false);
+    } else {
+      ManagedRegister out_reg = main_jni_conv->CurrentParamRegister();
+      __ CreateHandleScopeEntry(out_reg, class_handle_scope_offset,
+                         ManagedRegister::NoRegister(), false);
+    }
+    main_jni_conv->Next();
+    // Pass the current thread as the second argument and call.
+    if (main_jni_conv->IsCurrentParamInRegister()) {
+      __ GetCurrentThread(main_jni_conv->CurrentParamRegister());
+      if (is_64_bit_target) {
+        __ Call(main_jni_conv->CurrentParamRegister(), Offset(read_barrier64),
+                main_jni_conv->InterproceduralScratchRegister());
+      } else {
+        __ Call(main_jni_conv->CurrentParamRegister(), Offset(read_barrier32),
+                main_jni_conv->InterproceduralScratchRegister());
+      }
+    } else {
+      __ GetCurrentThread(main_jni_conv->CurrentParamStackOffset(),
+                          main_jni_conv->InterproceduralScratchRegister());
+      if (is_64_bit_target) {
+        __ CallFromThread64(read_barrier64, main_jni_conv->InterproceduralScratchRegister());
+      } else {
+        __ CallFromThread32(read_barrier32, main_jni_conv->InterproceduralScratchRegister());
+      }
+    }
+    main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size));  // Reset.
+  }
+
   // 6. Call into appropriate JniMethodStart passing Thread* so that transition out of Runnable
   //    can occur. The result is the saved JNI local state that is restored by the exit call. We
   //    abuse the JNI calling convention here, that is guaranteed to support passing 2 pointer
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index dbdcc96..a871a82 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -176,7 +176,7 @@
   EXPECT_EQ(72U, sizeof(OatHeader));
   EXPECT_EQ(4U, sizeof(OatMethodOffsets));
   EXPECT_EQ(28U, sizeof(OatQuickMethodHeader));
-  EXPECT_EQ(111 * GetInstructionSetPointerSize(kRuntimeISA), sizeof(QuickEntryPoints));
+  EXPECT_EQ(112 * GetInstructionSetPointerSize(kRuntimeISA), sizeof(QuickEntryPoints));
 }
 
 TEST_F(OatTest, OatHeaderIsValid) {
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index a902760..502ef2f 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -34,10 +34,15 @@
 // Binary encoding of 2^31 for type double.
 static int64_t constexpr k2Pow31EncodingForDouble = INT64_C(0x41E0000000000000);
 
+// Minimum value for a primitive integer.
+static int32_t constexpr kPrimIntMin = 0x80000000;
+// Minimum value for a primitive long.
+static int64_t constexpr kPrimLongMin = INT64_C(0x8000000000000000);
+
 // Maximum value for a primitive integer.
 static int32_t constexpr kPrimIntMax = 0x7fffffff;
 // Maximum value for a primitive long.
-static int64_t constexpr kPrimLongMax = 0x7fffffffffffffff;
+static int64_t constexpr kPrimLongMax = INT64_C(0x7fffffffffffffff);
 
 class Assembler;
 class CodeGenerator;
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index f56e446..672e55e 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -17,6 +17,7 @@
 #include "code_generator_arm.h"
 
 #include "arch/arm/instruction_set_features_arm.h"
+#include "code_generator_utils.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "gc/accounting/card_table.h"
 #include "intrinsics.h"
@@ -347,11 +348,11 @@
 }
 
 void CodeGeneratorARM::DumpCoreRegister(std::ostream& stream, int reg) const {
-  stream << ArmManagedRegister::FromCoreRegister(Register(reg));
+  stream << Register(reg);
 }
 
 void CodeGeneratorARM::DumpFloatingPointRegister(std::ostream& stream, int reg) const {
-  stream << ArmManagedRegister::FromSRegister(SRegister(reg));
+  stream << SRegister(reg);
 }
 
 size_t CodeGeneratorARM::SaveCoreRegister(size_t stack_index, uint32_t reg_id) {
@@ -2185,11 +2186,134 @@
   }
 }
 
+void InstructionCodeGeneratorARM::DivRemOneOrMinusOne(HBinaryOperation* instruction) {
+  DCHECK(instruction->IsDiv() || instruction->IsRem());
+  DCHECK(instruction->GetResultType() == Primitive::kPrimInt);
+
+  LocationSummary* locations = instruction->GetLocations();
+  Location second = locations->InAt(1);
+  DCHECK(second.IsConstant());
+
+  Register out = locations->Out().AsRegister<Register>();
+  Register dividend = locations->InAt(0).AsRegister<Register>();
+  int32_t imm = second.GetConstant()->AsIntConstant()->GetValue();
+  DCHECK(imm == 1 || imm == -1);
+
+  if (instruction->IsRem()) {
+    __ LoadImmediate(out, 0);
+  } else {
+    if (imm == 1) {
+      __ Mov(out, dividend);
+    } else {
+      __ rsb(out, dividend, ShifterOperand(0));
+    }
+  }
+}
+
+void InstructionCodeGeneratorARM::DivRemByPowerOfTwo(HBinaryOperation* instruction) {
+  DCHECK(instruction->IsDiv() || instruction->IsRem());
+  DCHECK(instruction->GetResultType() == Primitive::kPrimInt);
+
+  LocationSummary* locations = instruction->GetLocations();
+  Location second = locations->InAt(1);
+  DCHECK(second.IsConstant());
+
+  Register out = locations->Out().AsRegister<Register>();
+  Register dividend = locations->InAt(0).AsRegister<Register>();
+  Register temp = locations->GetTemp(0).AsRegister<Register>();
+  int32_t imm = second.GetConstant()->AsIntConstant()->GetValue();
+  int32_t abs_imm = std::abs(imm);
+  DCHECK(IsPowerOfTwo(abs_imm));
+  int ctz_imm = CTZ(abs_imm);
+
+  if (ctz_imm == 1) {
+    __ Lsr(temp, dividend, 32 - ctz_imm);
+  } else {
+    __ Asr(temp, dividend, 31);
+    __ Lsr(temp, temp, 32 - ctz_imm);
+  }
+  __ add(out, temp, ShifterOperand(dividend));
+
+  if (instruction->IsDiv()) {
+    __ Asr(out, out, ctz_imm);
+    if (imm < 0) {
+      __ rsb(out, out, ShifterOperand(0));
+    }
+  } else {
+    __ ubfx(out, out, 0, ctz_imm);
+    __ sub(out, out, ShifterOperand(temp));
+  }
+}
+
+void InstructionCodeGeneratorARM::GenerateDivRemWithAnyConstant(HBinaryOperation* instruction) {
+  DCHECK(instruction->IsDiv() || instruction->IsRem());
+  DCHECK(instruction->GetResultType() == Primitive::kPrimInt);
+
+  LocationSummary* locations = instruction->GetLocations();
+  Location second = locations->InAt(1);
+  DCHECK(second.IsConstant());
+
+  Register out = locations->Out().AsRegister<Register>();
+  Register dividend = locations->InAt(0).AsRegister<Register>();
+  Register temp1 = locations->GetTemp(0).AsRegister<Register>();
+  Register temp2 = locations->GetTemp(1).AsRegister<Register>();
+  int64_t imm = second.GetConstant()->AsIntConstant()->GetValue();
+
+  int64_t magic;
+  int shift;
+  CalculateMagicAndShiftForDivRem(imm, false /* is_long */, &magic, &shift);
+
+  __ LoadImmediate(temp1, magic);
+  __ smull(temp2, temp1, dividend, temp1);
+
+  if (imm > 0 && magic < 0) {
+    __ add(temp1, temp1, ShifterOperand(dividend));
+  } else if (imm < 0 && magic > 0) {
+    __ sub(temp1, temp1, ShifterOperand(dividend));
+  }
+
+  if (shift != 0) {
+    __ Asr(temp1, temp1, shift);
+  }
+
+  if (instruction->IsDiv()) {
+    __ sub(out, temp1, ShifterOperand(temp1, ASR, 31));
+  } else {
+    __ sub(temp1, temp1, ShifterOperand(temp1, ASR, 31));
+    // TODO: Strength reduction for mls.
+    __ LoadImmediate(temp2, imm);
+    __ mls(out, temp1, temp2, dividend);
+  }
+}
+
+void InstructionCodeGeneratorARM::GenerateDivRemConstantIntegral(HBinaryOperation* instruction) {
+  DCHECK(instruction->IsDiv() || instruction->IsRem());
+  DCHECK(instruction->GetResultType() == Primitive::kPrimInt);
+
+  LocationSummary* locations = instruction->GetLocations();
+  Location second = locations->InAt(1);
+  DCHECK(second.IsConstant());
+
+  int32_t imm = second.GetConstant()->AsIntConstant()->GetValue();
+  if (imm == 0) {
+    // Do not generate anything. DivZeroCheck would prevent any code to be executed.
+  } else if (imm == 1 || imm == -1) {
+    DivRemOneOrMinusOne(instruction);
+  } else if (IsPowerOfTwo(std::abs(imm))) {
+    DivRemByPowerOfTwo(instruction);
+  } else {
+    DCHECK(imm <= -2 || imm >= 2);
+    GenerateDivRemWithAnyConstant(instruction);
+  }
+}
+
 void LocationsBuilderARM::VisitDiv(HDiv* div) {
   LocationSummary::CallKind call_kind = LocationSummary::kNoCall;
   if (div->GetResultType() == Primitive::kPrimLong) {
     // pLdiv runtime call.
     call_kind = LocationSummary::kCall;
+  } else if (div->GetResultType() == Primitive::kPrimInt && div->InputAt(1)->IsConstant()) {
+    // sdiv will be replaced by other instruction sequence.
   } else if (div->GetResultType() == Primitive::kPrimInt &&
              !codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
     // pIdivmod runtime call.
@@ -2200,7 +2324,20 @@
 
   switch (div->GetResultType()) {
     case Primitive::kPrimInt: {
-      if (codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
+      if (div->InputAt(1)->IsConstant()) {
+        locations->SetInAt(0, Location::RequiresRegister());
+        locations->SetInAt(1, Location::RegisterOrConstant(div->InputAt(1)));
+        locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
+        int32_t abs_imm = std::abs(div->InputAt(1)->AsIntConstant()->GetValue());
+        if (abs_imm <= 1) {
+          // No temp register required.
+        } else {
+          locations->AddTemp(Location::RequiresRegister());
+          if (!IsPowerOfTwo(abs_imm)) {
+            locations->AddTemp(Location::RequiresRegister());
+          }
+        }
+      } else if (codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
         locations->SetInAt(0, Location::RequiresRegister());
         locations->SetInAt(1, Location::RequiresRegister());
         locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
@@ -2244,7 +2381,9 @@
 
   switch (div->GetResultType()) {
     case Primitive::kPrimInt: {
-      if (codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
+      if (second.IsConstant()) {
+        GenerateDivRemConstantIntegral(div);
+      } else if (codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
         __ sdiv(out.AsRegister<Register>(),
                 first.AsRegister<Register>(),
                 second.AsRegister<Register>());
@@ -2296,8 +2435,11 @@
 
   // Most remainders are implemented in the runtime.
   LocationSummary::CallKind call_kind = LocationSummary::kCall;
-  if (rem->GetResultType() == Primitive::kPrimInt &&
-      codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
+  if (rem->GetResultType() == Primitive::kPrimInt && rem->InputAt(1)->IsConstant()) {
+    // sdiv will be replaced by other instruction sequence.
+    call_kind = LocationSummary::kNoCall;
+  } else if ((rem->GetResultType() == Primitive::kPrimInt)
+             && codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
     // Have hardware divide instruction for int, do it with three instructions.
     call_kind = LocationSummary::kNoCall;
   }
@@ -2306,7 +2448,20 @@
 
   switch (type) {
     case Primitive::kPrimInt: {
-      if (codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
+      if (rem->InputAt(1)->IsConstant()) {
+        locations->SetInAt(0, Location::RequiresRegister());
+        locations->SetInAt(1, Location::RegisterOrConstant(rem->InputAt(1)));
+        locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
+        int32_t abs_imm = std::abs(rem->InputAt(1)->AsIntConstant()->GetValue());
+        if (abs_imm <= 1) {
+          // No temp register required.
+        } else {
+          locations->AddTemp(Location::RequiresRegister());
+          if (!IsPowerOfTwo(abs_imm)) {
+            locations->AddTemp(Location::RequiresRegister());
+          }
+        }
+      } else if (codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
         locations->SetInAt(0, Location::RequiresRegister());
         locations->SetInAt(1, Location::RequiresRegister());
         locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
@@ -2363,7 +2518,9 @@
   Primitive::Type type = rem->GetResultType();
   switch (type) {
     case Primitive::kPrimInt: {
-      if (codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
+        if (second.IsConstant()) {
+          GenerateDivRemConstantIntegral(rem);
+        } else if (codegen_->GetInstructionSetFeatures().HasDivideInstruction()) {
         Register reg1 = first.AsRegister<Register>();
         Register reg2 = second.AsRegister<Register>();
         Register temp = locations->GetTemp(0).AsRegister<Register>();
diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h
index 1a498e1..2edbcf8 100644
--- a/compiler/optimizing/code_generator_arm.h
+++ b/compiler/optimizing/code_generator_arm.h
@@ -189,6 +189,10 @@
                              Label* true_target,
                              Label* false_target,
                              Label* always_true_target);
+  void DivRemOneOrMinusOne(HBinaryOperation* instruction);
+  void DivRemByPowerOfTwo(HBinaryOperation* instruction);
+  void GenerateDivRemWithAnyConstant(HBinaryOperation* instruction);
+  void GenerateDivRemConstantIntegral(HBinaryOperation* instruction);
 
   ArmAssembler* const assembler_;
   CodeGeneratorARM* const codegen_;
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 0222f93..f51ea41 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -17,6 +17,7 @@
 #include "code_generator_arm64.h"
 
 #include "arch/arm64/instruction_set_features_arm64.h"
+#include "code_generator_utils.h"
 #include "common_arm64.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "entrypoints/quick/quick_entrypoints_enum.h"
@@ -691,11 +692,11 @@
 }
 
 void CodeGeneratorARM64::DumpCoreRegister(std::ostream& stream, int reg) const {
-  stream << Arm64ManagedRegister::FromXRegister(XRegister(reg));
+  stream << XRegister(reg);
 }
 
 void CodeGeneratorARM64::DumpFloatingPointRegister(std::ostream& stream, int reg) const {
-  stream << Arm64ManagedRegister::FromDRegister(DRegister(reg));
+  stream << DRegister(reg);
 }
 
 void CodeGeneratorARM64::MoveConstant(CPURegister destination, HConstant* constant) {
@@ -979,14 +980,12 @@
   BlockPoolsScope block_pools(GetVIXLAssembler());
   __ Ldr(lr, MemOperand(tr, entry_point_offset));
   __ Blr(lr);
-  if (instruction != nullptr) {
-    RecordPcInfo(instruction, dex_pc, slow_path);
-    DCHECK(instruction->IsSuspendCheck()
-        || instruction->IsBoundsCheck()
-        || instruction->IsNullCheck()
-        || instruction->IsDivZeroCheck()
-        || !IsLeafMethod());
-    }
+  RecordPcInfo(instruction, dex_pc, slow_path);
+  DCHECK(instruction->IsSuspendCheck()
+         || instruction->IsBoundsCheck()
+         || instruction->IsNullCheck()
+         || instruction->IsDivZeroCheck()
+         || !IsLeafMethod());
 }
 
 void InstructionCodeGeneratorARM64::GenerateClassInitializationCheck(SlowPathCodeARM64* slow_path,
@@ -1605,6 +1604,152 @@
 #undef DEFINE_CONDITION_VISITORS
 #undef FOR_EACH_CONDITION_INSTRUCTION
 
+void InstructionCodeGeneratorARM64::DivRemOneOrMinusOne(HBinaryOperation* instruction) {
+  DCHECK(instruction->IsDiv() || instruction->IsRem());
+
+  LocationSummary* locations = instruction->GetLocations();
+  Location second = locations->InAt(1);
+  DCHECK(second.IsConstant());
+
+  Register out = OutputRegister(instruction);
+  Register dividend = InputRegisterAt(instruction, 0);
+  int64_t imm = Int64FromConstant(second.GetConstant());
+  DCHECK(imm == 1 || imm == -1);
+
+  if (instruction->IsRem()) {
+    __ Mov(out, 0);
+  } else {
+    if (imm == 1) {
+      __ Mov(out, dividend);
+    } else {
+      __ Neg(out, dividend);
+    }
+  }
+}
+
+void InstructionCodeGeneratorARM64::DivRemByPowerOfTwo(HBinaryOperation* instruction) {
+  DCHECK(instruction->IsDiv() || instruction->IsRem());
+
+  LocationSummary* locations = instruction->GetLocations();
+  Location second = locations->InAt(1);
+  DCHECK(second.IsConstant());
+
+  Register out = OutputRegister(instruction);
+  Register dividend = InputRegisterAt(instruction, 0);
+  int64_t imm = Int64FromConstant(second.GetConstant());
+  int64_t abs_imm = std::abs(imm);
+  DCHECK(IsPowerOfTwo(abs_imm));
+  int ctz_imm = CTZ(abs_imm);
+
+  UseScratchRegisterScope temps(GetVIXLAssembler());
+  Register temp = temps.AcquireSameSizeAs(out);
+
+  if (instruction->IsDiv()) {
+    __ Add(temp, dividend, abs_imm - 1);
+    __ Cmp(dividend, 0);
+    __ Csel(out, temp, dividend, lt);
+    if (imm > 0) {
+      __ Asr(out, out, ctz_imm);
+    } else {
+      __ Neg(out, Operand(out, ASR, ctz_imm));
+    }
+  } else {
+    int bits = instruction->GetResultType() == Primitive::kPrimInt ? 32 : 64;
+    __ Asr(temp, dividend, bits - 1);
+    __ Lsr(temp, temp, bits - ctz_imm);
+    __ Add(out, dividend, temp);
+    __ And(out, out, abs_imm - 1);
+    __ Sub(out, out, temp);
+  }
+}
+
+void InstructionCodeGeneratorARM64::GenerateDivRemWithAnyConstant(HBinaryOperation* instruction) {
+  DCHECK(instruction->IsDiv() || instruction->IsRem());
+
+  LocationSummary* locations = instruction->GetLocations();
+  Location second = locations->InAt(1);
+  DCHECK(second.IsConstant());
+
+  Register out = OutputRegister(instruction);
+  Register dividend = InputRegisterAt(instruction, 0);
+  int64_t imm = Int64FromConstant(second.GetConstant());
+
+  Primitive::Type type = instruction->GetResultType();
+  DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong);
+
+  int64_t magic;
+  int shift;
+  CalculateMagicAndShiftForDivRem(imm, type == Primitive::kPrimLong /* is_long */, &magic, &shift);
+
+  UseScratchRegisterScope temps(GetVIXLAssembler());
+  Register temp = temps.AcquireSameSizeAs(out);
+
+  // temp = get_high(dividend * magic)
+  __ Mov(temp, magic);
+  if (type == Primitive::kPrimLong) {
+    __ Smulh(temp, dividend, temp);
+  } else {
+    __ Smull(temp.X(), dividend, temp);
+    __ Lsr(temp.X(), temp.X(), 32);
+  }
+
+  if (imm > 0 && magic < 0) {
+    __ Add(temp, temp, dividend);
+  } else if (imm < 0 && magic > 0) {
+    __ Sub(temp, temp, dividend);
+  }
+
+  if (shift != 0) {
+    __ Asr(temp, temp, shift);
+  }
+
+  if (instruction->IsDiv()) {
+    __ Sub(out, temp, Operand(temp, ASR, type == Primitive::kPrimLong ? 63 : 31));
+  } else {
+    __ Sub(temp, temp, Operand(temp, ASR, type == Primitive::kPrimLong ? 63 : 31));
+    // TODO: Strength reduction for msub.
+    Register temp_imm = temps.AcquireSameSizeAs(out);
+    __ Mov(temp_imm, imm);
+    __ Msub(out, temp, temp_imm, dividend);
+  }
+}
+
+void InstructionCodeGeneratorARM64::GenerateDivRemIntegral(HBinaryOperation* instruction) {
+  DCHECK(instruction->IsDiv() || instruction->IsRem());
+  Primitive::Type type = instruction->GetResultType();
+  DCHECK(type == Primitive::kPrimInt || Primitive::kPrimLong);
+
+  LocationSummary* locations = instruction->GetLocations();
+  Register out = OutputRegister(instruction);
+  Location second = locations->InAt(1);
+
+  if (second.IsConstant()) {
+    int64_t imm = Int64FromConstant(second.GetConstant());
+
+    if (imm == 0) {
+      // Do not generate anything. DivZeroCheck would prevent any code to be executed.
+    } else if (imm == 1 || imm == -1) {
+      DivRemOneOrMinusOne(instruction);
+    } else if (IsPowerOfTwo(std::abs(imm))) {
+      DivRemByPowerOfTwo(instruction);
+    } else {
+      DCHECK(imm <= -2 || imm >= 2);
+      GenerateDivRemWithAnyConstant(instruction);
+    }
+  } else {
+    Register dividend = InputRegisterAt(instruction, 0);
+    Register divisor = InputRegisterAt(instruction, 1);
+    if (instruction->IsDiv()) {
+      __ Sdiv(out, dividend, divisor);
+    } else {
+      UseScratchRegisterScope temps(GetVIXLAssembler());
+      Register temp = temps.AcquireSameSizeAs(out);
+      __ Sdiv(temp, dividend, divisor);
+      __ Msub(out, temp, divisor, dividend);
+    }
+  }
+}
+
 void LocationsBuilderARM64::VisitDiv(HDiv* div) {
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(div, LocationSummary::kNoCall);
@@ -1612,7 +1757,7 @@
     case Primitive::kPrimInt:
     case Primitive::kPrimLong:
       locations->SetInAt(0, Location::RequiresRegister());
-      locations->SetInAt(1, Location::RequiresRegister());
+      locations->SetInAt(1, Location::RegisterOrConstant(div->InputAt(1)));
       locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
       break;
 
@@ -1633,7 +1778,7 @@
   switch (type) {
     case Primitive::kPrimInt:
     case Primitive::kPrimLong:
-      __ Sdiv(OutputRegister(div), InputRegisterAt(div, 0), InputRegisterAt(div, 1));
+      GenerateDivRemIntegral(div);
       break;
 
     case Primitive::kPrimFloat:
@@ -2456,7 +2601,7 @@
     case Primitive::kPrimInt:
     case Primitive::kPrimLong:
       locations->SetInAt(0, Location::RequiresRegister());
-      locations->SetInAt(1, Location::RequiresRegister());
+      locations->SetInAt(1, Location::RegisterOrConstant(rem->InputAt(1)));
       locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
       break;
 
@@ -2481,14 +2626,7 @@
   switch (type) {
     case Primitive::kPrimInt:
     case Primitive::kPrimLong: {
-      UseScratchRegisterScope temps(GetVIXLAssembler());
-      Register dividend = InputRegisterAt(rem, 0);
-      Register divisor = InputRegisterAt(rem, 1);
-      Register output = OutputRegister(rem);
-      Register temp = temps.AcquireSameSizeAs(output);
-
-      __ Sdiv(temp, dividend, divisor);
-      __ Msub(output, temp, divisor, dividend);
+      GenerateDivRemIntegral(rem);
       break;
     }
 
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index 8aeea54..0dc0918 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -163,6 +163,11 @@
                              vixl::Label* true_target,
                              vixl::Label* false_target,
                              vixl::Label* always_true_target);
+  void DivRemOneOrMinusOne(HBinaryOperation* instruction);
+  void DivRemByPowerOfTwo(HBinaryOperation* instruction);
+  void GenerateDivRemWithAnyConstant(HBinaryOperation* instruction);
+  void GenerateDivRemIntegral(HBinaryOperation* instruction);
+
 
   Arm64Assembler* const assembler_;
   CodeGeneratorARM64* const codegen_;
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 2848a48..0212da1 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -340,11 +340,11 @@
 }
 
 void CodeGeneratorX86::DumpCoreRegister(std::ostream& stream, int reg) const {
-  stream << X86ManagedRegister::FromCpuRegister(Register(reg));
+  stream << Register(reg);
 }
 
 void CodeGeneratorX86::DumpFloatingPointRegister(std::ostream& stream, int reg) const {
-  stream << X86ManagedRegister::FromXmmRegister(XmmRegister(reg));
+  stream << XmmRegister(reg);
 }
 
 size_t CodeGeneratorX86::SaveCoreRegister(size_t stack_index, uint32_t reg_id) {
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index e633970..63d6846 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -396,11 +396,11 @@
 }
 
 void CodeGeneratorX86_64::DumpCoreRegister(std::ostream& stream, int reg) const {
-  stream << X86_64ManagedRegister::FromCpuRegister(Register(reg));
+  stream << Register(reg);
 }
 
 void CodeGeneratorX86_64::DumpFloatingPointRegister(std::ostream& stream, int reg) const {
-  stream << X86_64ManagedRegister::FromXmmRegister(FloatRegister(reg));
+  stream << FloatRegister(reg);
 }
 
 size_t CodeGeneratorX86_64::SaveCoreRegister(size_t stack_index, uint32_t reg_id) {
diff --git a/compiler/optimizing/constant_folding.cc b/compiler/optimizing/constant_folding.cc
index b7a92b5..20ce110 100644
--- a/compiler/optimizing/constant_folding.cc
+++ b/compiler/optimizing/constant_folding.cc
@@ -28,6 +28,7 @@
   void VisitShift(HBinaryOperation* shift);
 
   void VisitAnd(HAnd* instruction) OVERRIDE;
+  void VisitCompare(HCompare* instruction) OVERRIDE;
   void VisitMul(HMul* instruction) OVERRIDE;
   void VisitOr(HOr* instruction) OVERRIDE;
   void VisitRem(HRem* instruction) OVERRIDE;
@@ -70,6 +71,14 @@
           inst->ReplaceWith(constant);
           inst->GetBlock()->RemoveInstruction(inst);
         }
+      } else if (inst->IsTypeConversion()) {
+        // Constant folding: replace `TypeConversion(a)' with a constant at
+        // compile time if `a' is a constant.
+        HConstant* constant = inst->AsTypeConversion()->TryStaticEvaluation();
+        if (constant != nullptr) {
+          inst->ReplaceWith(constant);
+          inst->GetBlock()->RemoveInstruction(inst);
+        }
       } else if (inst->IsDivZeroCheck()) {
         // We can safely remove the check if the input is a non-null constant.
         HDivZeroCheck* check = inst->AsDivZeroCheck();
@@ -108,6 +117,26 @@
   }
 }
 
+void InstructionWithAbsorbingInputSimplifier::VisitCompare(HCompare* instruction) {
+  HConstant* input_cst = instruction->GetConstantRight();
+  if (input_cst != nullptr) {
+    HInstruction* input_value = instruction->GetLeastConstantLeft();
+    if (Primitive::IsFloatingPointType(input_value->GetType()) &&
+        ((input_cst->IsFloatConstant() && input_cst->AsFloatConstant()->IsNaN()) ||
+         (input_cst->IsDoubleConstant() && input_cst->AsDoubleConstant()->IsNaN()))) {
+      // Replace code looking like
+      //    CMP{G,L} dst, src, NaN
+      // with
+      //    CONSTANT +1 (gt bias)
+      // or
+      //    CONSTANT -1 (lt bias)
+      instruction->ReplaceWith(GetGraph()->GetConstant(Primitive::kPrimInt,
+                                                       (instruction->IsGtBias() ? 1 : -1)));
+      instruction->GetBlock()->RemoveInstruction(instruction);
+    }
+  }
+}
+
 void InstructionWithAbsorbingInputSimplifier::VisitMul(HMul* instruction) {
   HConstant* input_cst = instruction->GetConstantRight();
   Primitive::Type type = instruction->GetType();
diff --git a/compiler/optimizing/dead_code_elimination.cc b/compiler/optimizing/dead_code_elimination.cc
index cd427c5..b31de98 100644
--- a/compiler/optimizing/dead_code_elimination.cc
+++ b/compiler/optimizing/dead_code_elimination.cc
@@ -17,6 +17,7 @@
 #include "dead_code_elimination.h"
 
 #include "base/bit_vector-inl.h"
+#include "ssa_phi_elimination.h"
 
 namespace art {
 
@@ -47,6 +48,12 @@
   }
 }
 
+static void MarkLoopHeadersContaining(const HBasicBlock& block, ArenaBitVector* set) {
+  for (HLoopInformationOutwardIterator it(block); !it.Done(); it.Advance()) {
+    set->SetBit(it.Current()->GetHeader()->GetBlockId());
+  }
+}
+
 void HDeadCodeElimination::MaybeRecordDeadBlock(HBasicBlock* block) {
   if (stats_ != nullptr) {
     stats_->RecordStat(MethodCompilationStat::kRemovedDeadInstruction,
@@ -58,18 +65,24 @@
   // Classify blocks as reachable/unreachable.
   ArenaAllocator* allocator = graph_->GetArena();
   ArenaBitVector live_blocks(allocator, graph_->GetBlocks().Size(), false);
+  ArenaBitVector affected_loops(allocator, graph_->GetBlocks().Size(), false);
+
   MarkReachableBlocks(graph_->GetEntryBlock(), &live_blocks);
 
-  // Remove all dead blocks. Process blocks in post-order, because removal needs
-  // the block's chain of dominators.
+  // Remove all dead blocks. Iterate in post order because removal needs the
+  // block's chain of dominators and nested loops need to be updated from the
+  // inside out.
   for (HPostOrderIterator it(*graph_); !it.Done(); it.Advance()) {
     HBasicBlock* block  = it.Current();
-    if (live_blocks.IsBitSet(block->GetBlockId())) {
-      // If this block is part of a loop that is being dismantled, we need to
-      // update its loop information.
-      block->UpdateLoopInformation();
+    int id = block->GetBlockId();
+    if (live_blocks.IsBitSet(id)) {
+      if (affected_loops.IsBitSet(id)) {
+        DCHECK(block->IsLoopHeader());
+        block->GetLoopInformation()->Update();
+      }
     } else {
       MaybeRecordDeadBlock(block);
+      MarkLoopHeadersContaining(*block, &affected_loops);
       block->DisconnectAndDelete();
     }
   }
@@ -120,6 +133,7 @@
 
 void HDeadCodeElimination::Run() {
   RemoveDeadBlocks();
+  SsaRedundantPhiElimination(graph_).Run();
   RemoveDeadInstructions();
 }
 
diff --git a/compiler/optimizing/dead_code_elimination.h b/compiler/optimizing/dead_code_elimination.h
index 0bea0fc..59a57c4 100644
--- a/compiler/optimizing/dead_code_elimination.h
+++ b/compiler/optimizing/dead_code_elimination.h
@@ -31,13 +31,13 @@
  public:
   HDeadCodeElimination(HGraph* graph,
                        OptimizingCompilerStats* stats = nullptr,
-                       const char* name = kDeadCodeEliminationPassName)
+                       const char* name = kInitialDeadCodeEliminationPassName)
       : HOptimization(graph, true, name, stats) {}
 
   void Run() OVERRIDE;
 
-  static constexpr const char* kDeadCodeEliminationPassName =
-    "dead_code_elimination";
+  static constexpr const char* kInitialDeadCodeEliminationPassName = "dead_code_elimination";
+  static constexpr const char* kFinalDeadCodeEliminationPassName = "dead_code_elimination_final";
 
  private:
   void MaybeRecordDeadBlock(HBasicBlock* block);
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index 7130127..7ea1240 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -17,14 +17,63 @@
 #include "graph_visualizer.h"
 
 #include "code_generator.h"
+#include "dead_code_elimination.h"
 #include "licm.h"
 #include "nodes.h"
 #include "optimization.h"
 #include "register_allocator.h"
 #include "ssa_liveness_analysis.h"
 
+#include <cctype>
+#include <sstream>
+
 namespace art {
 
+static bool HasWhitespace(const char* str) {
+  DCHECK(str != nullptr);
+  while (str[0] != 0) {
+    if (isspace(str[0])) {
+      return true;
+    }
+    str++;
+  }
+  return false;
+}
+
+class StringList {
+ public:
+  // Create an empty list
+  StringList() : is_empty_(true) {}
+
+  // Construct StringList from a linked list. List element class T
+  // must provide methods `GetNext` and `Dump`.
+  template<class T>
+  explicit StringList(T* first_entry) : StringList() {
+    for (T* current = first_entry; current != nullptr; current = current->GetNext()) {
+      current->Dump(NewEntryStream());
+    }
+  }
+
+  std::ostream& NewEntryStream() {
+    if (is_empty_) {
+      is_empty_ = false;
+    } else {
+      sstream_ << ",";
+    }
+    return sstream_;
+  }
+
+ private:
+  bool is_empty_;
+  std::ostringstream sstream_;
+
+  friend std::ostream& operator<<(std::ostream& os, const StringList& list);
+};
+
+std::ostream& operator<<(std::ostream& os, const StringList& list) {
+  return os << "[" << list.sstream_.str() << "]";
+}
+
 /**
  * HGraph visitor to generate a file suitable for the c1visualizer tool and IRHydra.
  */
@@ -124,76 +173,84 @@
     output_<< std::endl;
   }
 
-  void DumpLocation(Location location) {
+  void DumpLocation(std::ostream& stream, const Location& location) {
     if (location.IsRegister()) {
-      codegen_.DumpCoreRegister(output_, location.reg());
+      codegen_.DumpCoreRegister(stream, location.reg());
     } else if (location.IsFpuRegister()) {
-      codegen_.DumpFloatingPointRegister(output_, location.reg());
+      codegen_.DumpFloatingPointRegister(stream, location.reg());
     } else if (location.IsConstant()) {
-      output_ << "constant";
+      stream << "#";
       HConstant* constant = location.GetConstant();
       if (constant->IsIntConstant()) {
-        output_ << " " << constant->AsIntConstant()->GetValue();
+        stream << constant->AsIntConstant()->GetValue();
       } else if (constant->IsLongConstant()) {
-        output_ << " " << constant->AsLongConstant()->GetValue();
+        stream << constant->AsLongConstant()->GetValue();
       }
     } else if (location.IsInvalid()) {
-      output_ << "invalid";
+      stream << "invalid";
     } else if (location.IsStackSlot()) {
-      output_ << location.GetStackIndex() << "(sp)";
+      stream << location.GetStackIndex() << "(sp)";
     } else if (location.IsFpuRegisterPair()) {
-      codegen_.DumpFloatingPointRegister(output_, location.low());
-      output_ << " and ";
-      codegen_.DumpFloatingPointRegister(output_, location.high());
+      codegen_.DumpFloatingPointRegister(stream, location.low());
+      stream << "|";
+      codegen_.DumpFloatingPointRegister(stream, location.high());
     } else if (location.IsRegisterPair()) {
-      codegen_.DumpCoreRegister(output_, location.low());
-      output_ << " and ";
-      codegen_.DumpCoreRegister(output_, location.high());
+      codegen_.DumpCoreRegister(stream, location.low());
+      stream << "|";
+      codegen_.DumpCoreRegister(stream, location.high());
     } else if (location.IsUnallocated()) {
-      output_ << "<U>";
+      stream << "unallocated";
     } else {
       DCHECK(location.IsDoubleStackSlot());
-      output_ << "2x" << location.GetStackIndex() << "(sp)";
+      stream << "2x" << location.GetStackIndex() << "(sp)";
     }
   }
 
+  std::ostream& StartAttributeStream(const char* name = nullptr) {
+    if (name == nullptr) {
+      output_ << " ";
+    } else {
+      DCHECK(!HasWhitespace(name)) << "Checker does not allow spaces in attributes";
+      output_ << " " << name << ":";
+    }
+    return output_;
+  }
+
   void VisitParallelMove(HParallelMove* instruction) OVERRIDE {
-    output_ << " (";
+    StartAttributeStream("liveness") << instruction->GetLifetimePosition();
+    StringList moves;
     for (size_t i = 0, e = instruction->NumMoves(); i < e; ++i) {
       MoveOperands* move = instruction->MoveOperandsAt(i);
-      DumpLocation(move->GetSource());
-      output_ << " -> ";
-      DumpLocation(move->GetDestination());
-      if (i + 1 != e) {
-        output_ << ", ";
-      }
+      std::ostream& str = moves.NewEntryStream();
+      DumpLocation(str, move->GetSource());
+      str << "->";
+      DumpLocation(str, move->GetDestination());
     }
-    output_ << ")";
-    output_ << " (liveness: " << instruction->GetLifetimePosition() << ")";
+    StartAttributeStream("moves") <<  moves;
   }
 
   void VisitIntConstant(HIntConstant* instruction) OVERRIDE {
-    output_ << " " << instruction->GetValue();
+    StartAttributeStream() << instruction->GetValue();
   }
 
   void VisitLongConstant(HLongConstant* instruction) OVERRIDE {
-    output_ << " " << instruction->GetValue();
+    StartAttributeStream() << instruction->GetValue();
   }
 
   void VisitFloatConstant(HFloatConstant* instruction) OVERRIDE {
-    output_ << " " << instruction->GetValue();
+    StartAttributeStream() << instruction->GetValue();
   }
 
   void VisitDoubleConstant(HDoubleConstant* instruction) OVERRIDE {
-    output_ << " " << instruction->GetValue();
+    StartAttributeStream() << instruction->GetValue();
   }
 
   void VisitPhi(HPhi* phi) OVERRIDE {
-    output_ << " " << phi->GetRegNumber();
+    StartAttributeStream("reg") << phi->GetRegNumber();
   }
 
   void VisitMemoryBarrier(HMemoryBarrier* barrier) OVERRIDE {
-    output_ << " " << barrier->GetBarrierKind();
+    StartAttributeStream("kind") << barrier->GetBarrierKind();
   }
 
   bool IsPass(const char* name) {
@@ -202,64 +259,65 @@
 
   void PrintInstruction(HInstruction* instruction) {
     output_ << instruction->DebugName();
-    instruction->Accept(this);
     if (instruction->InputCount() > 0) {
-      output_ << " [ ";
-      for (HInputIterator inputs(instruction); !inputs.Done(); inputs.Advance()) {
-        output_ << GetTypeId(inputs.Current()->GetType()) << inputs.Current()->GetId() << " ";
+      StringList inputs;
+      for (HInputIterator it(instruction); !it.Done(); it.Advance()) {
+        inputs.NewEntryStream() << GetTypeId(it.Current()->GetType()) << it.Current()->GetId();
       }
-      output_ << "]";
+      StartAttributeStream() << inputs;
     }
+    instruction->Accept(this);
     if (instruction->HasEnvironment()) {
-      output_ << " (env:";
+      StringList envs;
       for (HEnvironment* environment = instruction->GetEnvironment();
            environment != nullptr;
            environment = environment->GetParent()) {
-        output_ << " [ ";
+        StringList vregs;
         for (size_t i = 0, e = environment->Size(); i < e; ++i) {
           HInstruction* insn = environment->GetInstructionAt(i);
           if (insn != nullptr) {
-            output_ << GetTypeId(insn->GetType()) << insn->GetId() << " ";
+            vregs.NewEntryStream() << GetTypeId(insn->GetType()) << insn->GetId();
           } else {
-            output_ << " _ ";
+            vregs.NewEntryStream() << "_";
           }
         }
-        output_ << "]";
+        envs.NewEntryStream() << vregs;
       }
-      output_ << ")";
+      StartAttributeStream("env") << envs;
     }
     if (IsPass(SsaLivenessAnalysis::kLivenessPassName)
         && is_after_pass_
         && instruction->GetLifetimePosition() != kNoLifetime) {
-      output_ << " (liveness: " << instruction->GetLifetimePosition();
+      StartAttributeStream("liveness") << instruction->GetLifetimePosition();
       if (instruction->HasLiveInterval()) {
-        output_ << " ";
-        const LiveInterval& interval = *instruction->GetLiveInterval();
-        interval.Dump(output_);
+        LiveInterval* interval = instruction->GetLiveInterval();
+        StartAttributeStream("ranges") << StringList(interval->GetFirstRange());
+        StartAttributeStream("uses") << StringList(interval->GetFirstUse());
+        StartAttributeStream("env_uses") << StringList(interval->GetFirstEnvironmentUse());
+        StartAttributeStream("is_fixed") << interval->IsFixed();
+        StartAttributeStream("is_split") << interval->IsSplit();
+        StartAttributeStream("is_low") << interval->IsLowInterval();
+        StartAttributeStream("is_high") << interval->IsHighInterval();
       }
-      output_ << ")";
     } else if (IsPass(RegisterAllocator::kRegisterAllocatorPassName) && is_after_pass_) {
+      StartAttributeStream("liveness") << instruction->GetLifetimePosition();
       LocationSummary* locations = instruction->GetLocations();
       if (locations != nullptr) {
-        output_ << " ( ";
+        StringList inputs;
         for (size_t i = 0; i < instruction->InputCount(); ++i) {
-          DumpLocation(locations->InAt(i));
-          output_ << " ";
+          DumpLocation(inputs.NewEntryStream(), locations->InAt(i));
         }
-        output_ << ")";
-        if (locations->Out().IsValid()) {
-          output_ << " -> ";
-          DumpLocation(locations->Out());
-        }
+        std::ostream& attr = StartAttributeStream("locations");
+        attr << inputs << "->";
+        DumpLocation(attr, locations->Out());
       }
-      output_ << " (liveness: " << instruction->GetLifetimePosition() << ")";
-    } else if (IsPass(LICM::kLoopInvariantCodeMotionPassName)) {
-      output_ << " ( loop_header:";
+    } else if (IsPass(LICM::kLoopInvariantCodeMotionPassName)
+               || IsPass(HDeadCodeElimination::kFinalDeadCodeEliminationPassName)) {
       HLoopInformation* info = instruction->GetBlock()->GetLoopInformation();
       if (info == nullptr) {
-        output_ << "null )";
+        StartAttributeStream("loop") << "none";
       } else {
-        output_ << "B" << info->GetHeader()->GetBlockId() << " )";
+        StartAttributeStream("loop") << "B" << info->GetHeader()->GetBlockId();
       }
     }
   }
@@ -279,7 +337,7 @@
       output_ << bci << " " << num_uses << " "
               << GetTypeId(instruction->GetType()) << instruction->GetId() << " ";
       PrintInstruction(instruction);
-      output_ << kEndInstructionMarker << std::endl;
+      output_ << " " << kEndInstructionMarker << std::endl;
     }
   }
 
diff --git a/compiler/optimizing/intrinsics_arm.cc b/compiler/optimizing/intrinsics_arm.cc
index 7f7b450..dccfe9a 100644
--- a/compiler/optimizing/intrinsics_arm.cc
+++ b/compiler/optimizing/intrinsics_arm.cc
@@ -850,6 +850,94 @@
   __ Bind(slow_path->GetExitLabel());
 }
 
+static void GenerateVisitStringIndexOf(HInvoke* invoke,
+                                       ArmAssembler* assembler,
+                                       CodeGeneratorARM* codegen,
+                                       ArenaAllocator* allocator,
+                                       bool start_at_zero) {
+  LocationSummary* locations = invoke->GetLocations();
+  Register tmp_reg = locations->GetTemp(0).AsRegister<Register>();
+
+  // Note that the null check must have been done earlier.
+  DCHECK(!invoke->CanDoImplicitNullCheckOn(invoke->InputAt(0)));
+
+  // Check for code points > 0xFFFF. Either a slow-path check when we don't know statically,
+  // or directly dispatch if we have a constant.
+  SlowPathCodeARM* slow_path = nullptr;
+  if (invoke->InputAt(1)->IsIntConstant()) {
+    if (static_cast<uint32_t>(invoke->InputAt(1)->AsIntConstant()->GetValue()) >
+        std::numeric_limits<uint16_t>::max()) {
+      // Always needs the slow-path. We could directly dispatch to it, but this case should be
+      // rare, so for simplicity just put the full slow-path down and branch unconditionally.
+      slow_path = new (allocator) IntrinsicSlowPathARM(invoke);
+      codegen->AddSlowPath(slow_path);
+      __ b(slow_path->GetEntryLabel());
+      __ Bind(slow_path->GetExitLabel());
+      return;
+    }
+  } else {
+    Register char_reg = locations->InAt(1).AsRegister<Register>();
+    __ LoadImmediate(tmp_reg, std::numeric_limits<uint16_t>::max());
+    __ cmp(char_reg, ShifterOperand(tmp_reg));
+    slow_path = new (allocator) IntrinsicSlowPathARM(invoke);
+    codegen->AddSlowPath(slow_path);
+    __ b(slow_path->GetEntryLabel(), HI);
+  }
+
+  if (start_at_zero) {
+    DCHECK_EQ(tmp_reg, R2);
+    // Start-index = 0.
+    __ LoadImmediate(tmp_reg, 0);
+  }
+
+  __ LoadFromOffset(kLoadWord, LR, TR,
+                    QUICK_ENTRYPOINT_OFFSET(kArmWordSize, pIndexOf).Int32Value());
+  __ blx(LR);
+
+  if (slow_path != nullptr) {
+    __ Bind(slow_path->GetExitLabel());
+  }
+}
+
+void IntrinsicLocationsBuilderARM::VisitStringIndexOf(HInvoke* invoke) {
+  LocationSummary* locations = new (arena_) LocationSummary(invoke,
+                                                            LocationSummary::kCall,
+                                                            kIntrinsified);
+  // We have a hand-crafted assembly stub that follows the runtime calling convention. So it's
+  // best to align the inputs accordingly.
+  InvokeRuntimeCallingConvention calling_convention;
+  locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
+  locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
+  locations->SetOut(Location::RegisterLocation(R0));
+
+  // Need a temp for slow-path codepoint compare, and need to send start-index=0.
+  locations->AddTemp(Location::RegisterLocation(calling_convention.GetRegisterAt(2)));
+}
+
+void IntrinsicCodeGeneratorARM::VisitStringIndexOf(HInvoke* invoke) {
+  GenerateVisitStringIndexOf(invoke, GetAssembler(), codegen_, GetAllocator(), true);
+}
+
+void IntrinsicLocationsBuilderARM::VisitStringIndexOfAfter(HInvoke* invoke) {
+  LocationSummary* locations = new (arena_) LocationSummary(invoke,
+                                                            LocationSummary::kCall,
+                                                            kIntrinsified);
+  // We have a hand-crafted assembly stub that follows the runtime calling convention. So it's
+  // best to align the inputs accordingly.
+  InvokeRuntimeCallingConvention calling_convention;
+  locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
+  locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
+  locations->SetInAt(2, Location::RegisterLocation(calling_convention.GetRegisterAt(2)));
+  locations->SetOut(Location::RegisterLocation(R0));
+
+  // Need a temp for slow-path codepoint compare.
+  locations->AddTemp(Location::RequiresRegister());
+}
+
+void IntrinsicCodeGeneratorARM::VisitStringIndexOfAfter(HInvoke* invoke) {
+  GenerateVisitStringIndexOf(invoke, GetAssembler(), codegen_, GetAllocator(), false);
+}
+
 void IntrinsicLocationsBuilderARM::VisitStringNewStringFromBytes(HInvoke* invoke) {
   LocationSummary* locations = new (arena_) LocationSummary(invoke,
                                                             LocationSummary::kCall,
@@ -951,8 +1039,6 @@
 UNIMPLEMENTED_INTRINSIC(MathRoundFloat)    // Could be done by changing rounding mode, maybe?
 UNIMPLEMENTED_INTRINSIC(UnsafeCASLong)     // High register pressure.
 UNIMPLEMENTED_INTRINSIC(SystemArrayCopyChar)
-UNIMPLEMENTED_INTRINSIC(StringIndexOf)
-UNIMPLEMENTED_INTRINSIC(StringIndexOfAfter)
 UNIMPLEMENTED_INTRINSIC(ReferenceGetReferent)
 UNIMPLEMENTED_INTRINSIC(StringGetCharsNoCheck)
 
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index ca3de99..2c4fab0 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -993,6 +993,91 @@
   __ Bind(slow_path->GetExitLabel());
 }
 
+static void GenerateVisitStringIndexOf(HInvoke* invoke,
+                                       vixl::MacroAssembler* masm,
+                                       CodeGeneratorARM64* codegen,
+                                       ArenaAllocator* allocator,
+                                       bool start_at_zero) {
+  LocationSummary* locations = invoke->GetLocations();
+  Register tmp_reg = WRegisterFrom(locations->GetTemp(0));
+
+  // Note that the null check must have been done earlier.
+  DCHECK(!invoke->CanDoImplicitNullCheckOn(invoke->InputAt(0)));
+
+  // Check for code points > 0xFFFF. Either a slow-path check when we don't know statically,
+  // or directly dispatch if we have a constant.
+  SlowPathCodeARM64* slow_path = nullptr;
+  if (invoke->InputAt(1)->IsIntConstant()) {
+    if (static_cast<uint32_t>(invoke->InputAt(1)->AsIntConstant()->GetValue()) > 0xFFFFU) {
+      // Always needs the slow-path. We could directly dispatch to it, but this case should be
+      // rare, so for simplicity just put the full slow-path down and branch unconditionally.
+      slow_path = new (allocator) IntrinsicSlowPathARM64(invoke);
+      codegen->AddSlowPath(slow_path);
+      __ B(slow_path->GetEntryLabel());
+      __ Bind(slow_path->GetExitLabel());
+      return;
+    }
+  } else {
+    Register char_reg = WRegisterFrom(locations->InAt(1));
+    __ Mov(tmp_reg, 0xFFFF);
+    __ Cmp(char_reg, Operand(tmp_reg));
+    slow_path = new (allocator) IntrinsicSlowPathARM64(invoke);
+    codegen->AddSlowPath(slow_path);
+    __ B(hi, slow_path->GetEntryLabel());
+  }
+
+  if (start_at_zero) {
+    // Start-index = 0.
+    __ Mov(tmp_reg, 0);
+  }
+
+  __ Ldr(lr, MemOperand(tr, QUICK_ENTRYPOINT_OFFSET(kArm64WordSize, pIndexOf).Int32Value()));
+  __ Blr(lr);
+
+  if (slow_path != nullptr) {
+    __ Bind(slow_path->GetExitLabel());
+  }
+}
+
+void IntrinsicLocationsBuilderARM64::VisitStringIndexOf(HInvoke* invoke) {
+  LocationSummary* locations = new (arena_) LocationSummary(invoke,
+                                                            LocationSummary::kCall,
+                                                            kIntrinsified);
+  // We have a hand-crafted assembly stub that follows the runtime calling convention. So it's
+  // best to align the inputs accordingly.
+  InvokeRuntimeCallingConvention calling_convention;
+  locations->SetInAt(0, LocationFrom(calling_convention.GetRegisterAt(0)));
+  locations->SetInAt(1, LocationFrom(calling_convention.GetRegisterAt(1)));
+  locations->SetOut(calling_convention.GetReturnLocation(Primitive::kPrimInt));
+
+  // Need a temp for slow-path codepoint compare, and need to send start_index=0.
+  locations->AddTemp(LocationFrom(calling_convention.GetRegisterAt(2)));
+}
+
+void IntrinsicCodeGeneratorARM64::VisitStringIndexOf(HInvoke* invoke) {
+  GenerateVisitStringIndexOf(invoke, GetVIXLAssembler(), codegen_, GetAllocator(), true);
+}
+
+void IntrinsicLocationsBuilderARM64::VisitStringIndexOfAfter(HInvoke* invoke) {
+  LocationSummary* locations = new (arena_) LocationSummary(invoke,
+                                                            LocationSummary::kCall,
+                                                            kIntrinsified);
+  // We have a hand-crafted assembly stub that follows the runtime calling convention. So it's
+  // best to align the inputs accordingly.
+  InvokeRuntimeCallingConvention calling_convention;
+  locations->SetInAt(0, LocationFrom(calling_convention.GetRegisterAt(0)));
+  locations->SetInAt(1, LocationFrom(calling_convention.GetRegisterAt(1)));
+  locations->SetInAt(2, LocationFrom(calling_convention.GetRegisterAt(2)));
+  locations->SetOut(calling_convention.GetReturnLocation(Primitive::kPrimInt));
+
+  // Need a temp for slow-path codepoint compare.
+  locations->AddTemp(Location::RequiresRegister());
+}
+
+void IntrinsicCodeGeneratorARM64::VisitStringIndexOfAfter(HInvoke* invoke) {
+  GenerateVisitStringIndexOf(invoke, GetVIXLAssembler(), codegen_, GetAllocator(), false);
+}
+
 void IntrinsicLocationsBuilderARM64::VisitStringNewStringFromBytes(HInvoke* invoke) {
   LocationSummary* locations = new (arena_) LocationSummary(invoke,
                                                             LocationSummary::kCall,
@@ -1080,8 +1165,6 @@
 }
 
 UNIMPLEMENTED_INTRINSIC(SystemArrayCopyChar)
-UNIMPLEMENTED_INTRINSIC(StringIndexOf)
-UNIMPLEMENTED_INTRINSIC(StringIndexOfAfter)
 UNIMPLEMENTED_INTRINSIC(ReferenceGetReferent)
 UNIMPLEMENTED_INTRINSIC(StringGetCharsNoCheck)
 
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index 1eef1ef..28b7a07 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -16,6 +16,8 @@
 
 #include "intrinsics_x86.h"
 
+#include <limits>
+
 #include "arch/x86/instruction_set_features_x86.h"
 #include "code_generator_x86.h"
 #include "entrypoints/quick/quick_entrypoints.h"
@@ -124,11 +126,8 @@
 //       restored!
 class IntrinsicSlowPathX86 : public SlowPathCodeX86 {
  public:
-  explicit IntrinsicSlowPathX86(HInvoke* invoke, Register temp)
-    : invoke_(invoke) {
-      // The temporary register has to be EAX for x86 invokes.
-      DCHECK_EQ(temp, EAX);
-    }
+  explicit IntrinsicSlowPathX86(HInvoke* invoke)
+    : invoke_(invoke) { }
 
   void EmitNativeCode(CodeGenerator* codegen_in) OVERRIDE {
     CodeGeneratorX86* codegen = down_cast<CodeGeneratorX86*>(codegen_in);
@@ -880,8 +879,6 @@
   locations->SetInAt(0, Location::RequiresRegister());
   locations->SetInAt(1, Location::RequiresRegister());
   locations->SetOut(Location::SameAsFirstInput());
-  // Needs to be EAX for the invoke.
-  locations->AddTemp(Location::RegisterLocation(EAX));
 }
 
 void IntrinsicCodeGeneratorX86::VisitStringCharAt(HInvoke* invoke) {
@@ -901,8 +898,7 @@
   // TODO: For simplicity, the index parameter is requested in a register, so different from Quick
   //       we will not optimize the code for constants (which would save a register).
 
-  SlowPathCodeX86* slow_path = new (GetAllocator()) IntrinsicSlowPathX86(
-      invoke, locations->GetTemp(0).AsRegister<Register>());
+  SlowPathCodeX86* slow_path = new (GetAllocator()) IntrinsicSlowPathX86(invoke);
   codegen_->AddSlowPath(slow_path);
 
   X86Assembler* assembler = GetAssembler();
@@ -926,8 +922,6 @@
   locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
   locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
   locations->SetOut(Location::RegisterLocation(EAX));
-  // Needs to be EAX for the invoke.
-  locations->AddTemp(Location::RegisterLocation(EAX));
 }
 
 void IntrinsicCodeGeneratorX86::VisitStringCompareTo(HInvoke* invoke) {
@@ -939,8 +933,7 @@
 
   Register argument = locations->InAt(1).AsRegister<Register>();
   __ testl(argument, argument);
-  SlowPathCodeX86* slow_path = new (GetAllocator()) IntrinsicSlowPathX86(
-      invoke, locations->GetTemp(0).AsRegister<Register>());
+  SlowPathCodeX86* slow_path = new (GetAllocator()) IntrinsicSlowPathX86(invoke);
   codegen_->AddSlowPath(slow_path);
   __ j(kEqual, slow_path->GetEntryLabel());
 
@@ -948,6 +941,158 @@
   __ Bind(slow_path->GetExitLabel());
 }
 
+static void CreateStringIndexOfLocations(HInvoke* invoke,
+                                         ArenaAllocator* allocator,
+                                         bool start_at_zero) {
+  LocationSummary* locations = new (allocator) LocationSummary(invoke,
+                                                               LocationSummary::kCallOnSlowPath,
+                                                               kIntrinsified);
+  // The data needs to be in EDI for scasw. So request that the string is there, anyways.
+  locations->SetInAt(0, Location::RegisterLocation(EDI));
+  // If we look for a constant char, we'll still have to copy it into EAX. So just request the
+  // allocator to do that, anyways. We can still do the constant check by checking the parameter
+  // of the instruction explicitly.
+  // Note: This works as we don't clobber EAX anywhere.
+  locations->SetInAt(1, Location::RegisterLocation(EAX));
+  if (!start_at_zero) {
+    locations->SetInAt(2, Location::RequiresRegister());          // The starting index.
+  }
+  // As we clobber EDI during execution anyways, also use it as the output.
+  locations->SetOut(Location::SameAsFirstInput());
+
+  // repne scasw uses ECX as the counter.
+  locations->AddTemp(Location::RegisterLocation(ECX));
+  // Need another temporary to be able to compute the result.
+  locations->AddTemp(Location::RequiresRegister());
+}
+
+static void GenerateStringIndexOf(HInvoke* invoke,
+                                  X86Assembler* assembler,
+                                  CodeGeneratorX86* codegen,
+                                  ArenaAllocator* allocator,
+                                  bool start_at_zero) {
+  LocationSummary* locations = invoke->GetLocations();
+
+  // Note that the null check must have been done earlier.
+  DCHECK(!invoke->CanDoImplicitNullCheckOn(invoke->InputAt(0)));
+
+  Register string_obj = locations->InAt(0).AsRegister<Register>();
+  Register search_value = locations->InAt(1).AsRegister<Register>();
+  Register counter = locations->GetTemp(0).AsRegister<Register>();
+  Register string_length = locations->GetTemp(1).AsRegister<Register>();
+  Register out = locations->Out().AsRegister<Register>();
+
+  // Check our assumptions for registers.
+  DCHECK_EQ(string_obj, EDI);
+  DCHECK_EQ(search_value, EAX);
+  DCHECK_EQ(counter, ECX);
+  DCHECK_EQ(out, EDI);
+
+  // Check for code points > 0xFFFF. Either a slow-path check when we don't know statically,
+  // or directly dispatch if we have a constant.
+  SlowPathCodeX86* slow_path = nullptr;
+  if (invoke->InputAt(1)->IsIntConstant()) {
+    if (static_cast<uint32_t>(invoke->InputAt(1)->AsIntConstant()->GetValue()) >
+    std::numeric_limits<uint16_t>::max()) {
+      // Always needs the slow-path. We could directly dispatch to it, but this case should be
+      // rare, so for simplicity just put the full slow-path down and branch unconditionally.
+      slow_path = new (allocator) IntrinsicSlowPathX86(invoke);
+      codegen->AddSlowPath(slow_path);
+      __ jmp(slow_path->GetEntryLabel());
+      __ Bind(slow_path->GetExitLabel());
+      return;
+    }
+  } else {
+    __ cmpl(search_value, Immediate(std::numeric_limits<uint16_t>::max()));
+    slow_path = new (allocator) IntrinsicSlowPathX86(invoke);
+    codegen->AddSlowPath(slow_path);
+    __ j(kAbove, slow_path->GetEntryLabel());
+  }
+
+  // From here down, we know that we are looking for a char that fits in 16 bits.
+  // Location of reference to data array within the String object.
+  int32_t value_offset = mirror::String::ValueOffset().Int32Value();
+  // Location of count within the String object.
+  int32_t count_offset = mirror::String::CountOffset().Int32Value();
+
+  // Load string length, i.e., the count field of the string.
+  __ movl(string_length, Address(string_obj, count_offset));
+
+  // Do a zero-length check.
+  // TODO: Support jecxz.
+  Label not_found_label;
+  __ testl(string_length, string_length);
+  __ j(kEqual, &not_found_label);
+
+  if (start_at_zero) {
+    // Number of chars to scan is the same as the string length.
+    __ movl(counter, string_length);
+
+    // Move to the start of the string.
+    __ addl(string_obj, Immediate(value_offset));
+  } else {
+    Register start_index = locations->InAt(2).AsRegister<Register>();
+
+    // Do a start_index check.
+    __ cmpl(start_index, string_length);
+    __ j(kGreaterEqual, &not_found_label);
+
+    // Ensure we have a start index >= 0;
+    __ xorl(counter, counter);
+    __ cmpl(start_index, Immediate(0));
+    __ cmovl(kGreater, counter, start_index);
+
+    // Move to the start of the string: string_obj + value_offset + 2 * start_index.
+    __ leal(string_obj, Address(string_obj, counter, ScaleFactor::TIMES_2, value_offset));
+
+    // Now update ecx (the repne scasw work counter). We have string.length - start_index left to
+    // compare.
+    __ negl(counter);
+    __ leal(counter, Address(string_length, counter, ScaleFactor::TIMES_1, 0));
+  }
+
+  // Everything is set up for repne scasw:
+  //   * Comparison address in EDI.
+  //   * Counter in ECX.
+  __ repne_scasw();
+
+  // Did we find a match?
+  __ j(kNotEqual, &not_found_label);
+
+  // Yes, we matched.  Compute the index of the result.
+  __ subl(string_length, counter);
+  __ leal(out, Address(string_length, -1));
+
+  Label done;
+  __ jmp(&done);
+
+  // Failed to match; return -1.
+  __ Bind(&not_found_label);
+  __ movl(out, Immediate(-1));
+
+  // And join up at the end.
+  __ Bind(&done);
+  if (slow_path != nullptr) {
+    __ Bind(slow_path->GetExitLabel());
+  }
+}
+
+void IntrinsicLocationsBuilderX86::VisitStringIndexOf(HInvoke* invoke) {
+  CreateStringIndexOfLocations(invoke, arena_, true);
+}
+
+void IntrinsicCodeGeneratorX86::VisitStringIndexOf(HInvoke* invoke) {
+  GenerateStringIndexOf(invoke, GetAssembler(), codegen_, GetAllocator(), true);
+}
+
+void IntrinsicLocationsBuilderX86::VisitStringIndexOfAfter(HInvoke* invoke) {
+  CreateStringIndexOfLocations(invoke, arena_, false);
+}
+
+void IntrinsicCodeGeneratorX86::VisitStringIndexOfAfter(HInvoke* invoke) {
+  GenerateStringIndexOf(invoke, GetAssembler(), codegen_, GetAllocator(), false);
+}
+
 void IntrinsicLocationsBuilderX86::VisitStringNewStringFromBytes(HInvoke* invoke) {
   LocationSummary* locations = new (arena_) LocationSummary(invoke,
                                                             LocationSummary::kCall,
@@ -958,8 +1103,6 @@
   locations->SetInAt(2, Location::RegisterLocation(calling_convention.GetRegisterAt(2)));
   locations->SetInAt(3, Location::RegisterLocation(calling_convention.GetRegisterAt(3)));
   locations->SetOut(Location::RegisterLocation(EAX));
-  // Needs to be EAX for the invoke.
-  locations->AddTemp(Location::RegisterLocation(EAX));
 }
 
 void IntrinsicCodeGeneratorX86::VisitStringNewStringFromBytes(HInvoke* invoke) {
@@ -968,8 +1111,7 @@
 
   Register byte_array = locations->InAt(0).AsRegister<Register>();
   __ testl(byte_array, byte_array);
-  SlowPathCodeX86* slow_path = new (GetAllocator()) IntrinsicSlowPathX86(
-      invoke, locations->GetTemp(0).AsRegister<Register>());
+  SlowPathCodeX86* slow_path = new (GetAllocator()) IntrinsicSlowPathX86(invoke);
   codegen_->AddSlowPath(slow_path);
   __ j(kEqual, slow_path->GetEntryLabel());
 
@@ -1003,8 +1145,6 @@
   InvokeRuntimeCallingConvention calling_convention;
   locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
   locations->SetOut(Location::RegisterLocation(EAX));
-  // Needs to be EAX for the invoke.
-  locations->AddTemp(Location::RegisterLocation(EAX));
 }
 
 void IntrinsicCodeGeneratorX86::VisitStringNewStringFromString(HInvoke* invoke) {
@@ -1013,8 +1153,7 @@
 
   Register string_to_copy = locations->InAt(0).AsRegister<Register>();
   __ testl(string_to_copy, string_to_copy);
-  SlowPathCodeX86* slow_path = new (GetAllocator()) IntrinsicSlowPathX86(
-      invoke, locations->GetTemp(0).AsRegister<Register>());
+  SlowPathCodeX86* slow_path = new (GetAllocator()) IntrinsicSlowPathX86(invoke);
   codegen_->AddSlowPath(slow_path);
   __ j(kEqual, slow_path->GetEntryLabel());
 
@@ -1584,8 +1723,6 @@
 
 UNIMPLEMENTED_INTRINSIC(MathRoundDouble)
 UNIMPLEMENTED_INTRINSIC(StringGetCharsNoCheck)
-UNIMPLEMENTED_INTRINSIC(StringIndexOf)
-UNIMPLEMENTED_INTRINSIC(StringIndexOfAfter)
 UNIMPLEMENTED_INTRINSIC(SystemArrayCopyChar)
 UNIMPLEMENTED_INTRINSIC(ReferenceGetReferent)
 
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index 3dbcd4c..0efa714 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -16,6 +16,8 @@
 
 #include "intrinsics_x86_64.h"
 
+#include <limits>
+
 #include "arch/x86_64/instruction_set_features_x86_64.h"
 #include "code_generator_x86_64.h"
 #include "entrypoints/quick/quick_entrypoints.h"
@@ -858,6 +860,157 @@
   __ Bind(slow_path->GetExitLabel());
 }
 
+static void CreateStringIndexOfLocations(HInvoke* invoke,
+                                         ArenaAllocator* allocator,
+                                         bool start_at_zero) {
+  LocationSummary* locations = new (allocator) LocationSummary(invoke,
+                                                               LocationSummary::kCallOnSlowPath,
+                                                               kIntrinsified);
+  // The data needs to be in RDI for scasw. So request that the string is there, anyways.
+  locations->SetInAt(0, Location::RegisterLocation(RDI));
+  // If we look for a constant char, we'll still have to copy it into RAX. So just request the
+  // allocator to do that, anyways. We can still do the constant check by checking the parameter
+  // of the instruction explicitly.
+  // Note: This works as we don't clobber RAX anywhere.
+  locations->SetInAt(1, Location::RegisterLocation(RAX));
+  if (!start_at_zero) {
+    locations->SetInAt(2, Location::RequiresRegister());          // The starting index.
+  }
+  // As we clobber RDI during execution anyways, also use it as the output.
+  locations->SetOut(Location::SameAsFirstInput());
+
+  // repne scasw uses RCX as the counter.
+  locations->AddTemp(Location::RegisterLocation(RCX));
+  // Need another temporary to be able to compute the result.
+  locations->AddTemp(Location::RequiresRegister());
+}
+
+static void GenerateStringIndexOf(HInvoke* invoke,
+                                  X86_64Assembler* assembler,
+                                  CodeGeneratorX86_64* codegen,
+                                  ArenaAllocator* allocator,
+                                  bool start_at_zero) {
+  LocationSummary* locations = invoke->GetLocations();
+
+  // Note that the null check must have been done earlier.
+  DCHECK(!invoke->CanDoImplicitNullCheckOn(invoke->InputAt(0)));
+
+  CpuRegister string_obj = locations->InAt(0).AsRegister<CpuRegister>();
+  CpuRegister search_value = locations->InAt(1).AsRegister<CpuRegister>();
+  CpuRegister counter = locations->GetTemp(0).AsRegister<CpuRegister>();
+  CpuRegister string_length = locations->GetTemp(1).AsRegister<CpuRegister>();
+  CpuRegister out = locations->Out().AsRegister<CpuRegister>();
+
+  // Check our assumptions for registers.
+  DCHECK_EQ(string_obj.AsRegister(), RDI);
+  DCHECK_EQ(search_value.AsRegister(), RAX);
+  DCHECK_EQ(counter.AsRegister(), RCX);
+  DCHECK_EQ(out.AsRegister(), RDI);
+
+  // Check for code points > 0xFFFF. Either a slow-path check when we don't know statically,
+  // or directly dispatch if we have a constant.
+  SlowPathCodeX86_64* slow_path = nullptr;
+  if (invoke->InputAt(1)->IsIntConstant()) {
+    if (static_cast<uint32_t>(invoke->InputAt(1)->AsIntConstant()->GetValue()) >
+    std::numeric_limits<uint16_t>::max()) {
+      // Always needs the slow-path. We could directly dispatch to it, but this case should be
+      // rare, so for simplicity just put the full slow-path down and branch unconditionally.
+      slow_path = new (allocator) IntrinsicSlowPathX86_64(invoke);
+      codegen->AddSlowPath(slow_path);
+      __ jmp(slow_path->GetEntryLabel());
+      __ Bind(slow_path->GetExitLabel());
+      return;
+    }
+  } else {
+    __ cmpl(search_value, Immediate(std::numeric_limits<uint16_t>::max()));
+    slow_path = new (allocator) IntrinsicSlowPathX86_64(invoke);
+    codegen->AddSlowPath(slow_path);
+    __ j(kAbove, slow_path->GetEntryLabel());
+  }
+
+  // From here down, we know that we are looking for a char that fits in 16 bits.
+  // Location of reference to data array within the String object.
+  int32_t value_offset = mirror::String::ValueOffset().Int32Value();
+  // Location of count within the String object.
+  int32_t count_offset = mirror::String::CountOffset().Int32Value();
+
+  // Load string length, i.e., the count field of the string.
+  __ movl(string_length, Address(string_obj, count_offset));
+
+  // Do a length check.
+  // TODO: Support jecxz.
+  Label not_found_label;
+  __ testl(string_length, string_length);
+  __ j(kEqual, &not_found_label);
+
+  if (start_at_zero) {
+    // Number of chars to scan is the same as the string length.
+    __ movl(counter, string_length);
+
+    // Move to the start of the string.
+    __ addq(string_obj, Immediate(value_offset));
+  } else {
+    CpuRegister start_index = locations->InAt(2).AsRegister<CpuRegister>();
+
+    // Do a start_index check.
+    __ cmpl(start_index, string_length);
+    __ j(kGreaterEqual, &not_found_label);
+
+    // Ensure we have a start index >= 0;
+    __ xorl(counter, counter);
+    __ cmpl(start_index, Immediate(0));
+    __ cmov(kGreater, counter, start_index, false);  // 32-bit copy is enough.
+
+    // Move to the start of the string: string_obj + value_offset + 2 * start_index.
+    __ leaq(string_obj, Address(string_obj, counter, ScaleFactor::TIMES_2, value_offset));
+
+    // Now update ecx, the work counter: it's gonna be string.length - start_index.
+    __ negq(counter);  // Needs to be 64-bit negation, as the address computation is 64-bit.
+    __ leaq(counter, Address(string_length, counter, ScaleFactor::TIMES_1, 0));
+  }
+
+  // Everything is set up for repne scasw:
+  //   * Comparison address in RDI.
+  //   * Counter in ECX.
+  __ repne_scasw();
+
+  // Did we find a match?
+  __ j(kNotEqual, &not_found_label);
+
+  // Yes, we matched.  Compute the index of the result.
+  __ subl(string_length, counter);
+  __ leal(out, Address(string_length, -1));
+
+  Label done;
+  __ jmp(&done);
+
+  // Failed to match; return -1.
+  __ Bind(&not_found_label);
+  __ movl(out, Immediate(-1));
+
+  // And join up at the end.
+  __ Bind(&done);
+  if (slow_path != nullptr) {
+    __ Bind(slow_path->GetExitLabel());
+  }
+}
+
+void IntrinsicLocationsBuilderX86_64::VisitStringIndexOf(HInvoke* invoke) {
+  CreateStringIndexOfLocations(invoke, arena_, true);
+}
+
+void IntrinsicCodeGeneratorX86_64::VisitStringIndexOf(HInvoke* invoke) {
+  GenerateStringIndexOf(invoke, GetAssembler(), codegen_, GetAllocator(), true);
+}
+
+void IntrinsicLocationsBuilderX86_64::VisitStringIndexOfAfter(HInvoke* invoke) {
+  CreateStringIndexOfLocations(invoke, arena_, false);
+}
+
+void IntrinsicCodeGeneratorX86_64::VisitStringIndexOfAfter(HInvoke* invoke) {
+  GenerateStringIndexOf(invoke, GetAssembler(), codegen_, GetAllocator(), false);
+}
+
 void IntrinsicLocationsBuilderX86_64::VisitStringNewStringFromBytes(HInvoke* invoke) {
   LocationSummary* locations = new (arena_) LocationSummary(invoke,
                                                             LocationSummary::kCall,
@@ -1434,8 +1587,6 @@
 }
 
 UNIMPLEMENTED_INTRINSIC(StringGetCharsNoCheck)
-UNIMPLEMENTED_INTRINSIC(StringIndexOf)
-UNIMPLEMENTED_INTRINSIC(StringIndexOfAfter)
 UNIMPLEMENTED_INTRINSIC(SystemArrayCopyChar)
 UNIMPLEMENTED_INTRINSIC(ReferenceGetReferent)
 
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index b9e58c7..47da9cc 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -16,7 +16,9 @@
 
 #include "nodes.h"
 
+#include "code_generator.h"
 #include "ssa_builder.h"
+#include "base/bit_vector-inl.h"
 #include "utils/growable_array.h"
 #include "scoped_thread_state_change.h"
 
@@ -346,6 +348,7 @@
 }
 
 bool HLoopInformation::Populate() {
+  DCHECK_EQ(blocks_.NumSetBits(), 0u) << "Loop information has already been populated";
   for (size_t i = 0, e = GetBackEdges().Size(); i < e; ++i) {
     HBasicBlock* back_edge = GetBackEdges().Get(i);
     DCHECK(back_edge->GetDominator() != nullptr);
@@ -365,6 +368,39 @@
   return true;
 }
 
+void HLoopInformation::Update() {
+  HGraph* graph = header_->GetGraph();
+  for (uint32_t id : blocks_.Indexes()) {
+    HBasicBlock* block = graph->GetBlocks().Get(id);
+    // Reset loop information of non-header blocks inside the loop, except
+    // members of inner nested loops because those should already have been
+    // updated by their own LoopInformation.
+    if (block->GetLoopInformation() == this && block != header_) {
+      block->SetLoopInformation(nullptr);
+    }
+  }
+  blocks_.ClearAllBits();
+
+  if (back_edges_.IsEmpty()) {
+    // The loop has been dismantled, delete its suspend check and remove info
+    // from the header.
+    DCHECK(HasSuspendCheck());
+    header_->RemoveInstruction(suspend_check_);
+    header_->SetLoopInformation(nullptr);
+    header_ = nullptr;
+    suspend_check_ = nullptr;
+  } else {
+    if (kIsDebugBuild) {
+      for (size_t i = 0, e = back_edges_.Size(); i < e; ++i) {
+        DCHECK(header_->Dominates(back_edges_.Get(i)));
+      }
+    }
+    // This loop still has reachable back edges. Repopulate the list of blocks.
+    bool populate_successful = Populate();
+    DCHECK(populate_successful);
+  }
+}
+
 HBasicBlock* HLoopInformation::GetPreHeader() const {
   return header_->GetDominator();
 }
@@ -759,6 +795,84 @@
   }
 }
 
+HConstant* HTypeConversion::TryStaticEvaluation() const {
+  HGraph* graph = GetBlock()->GetGraph();
+  if (GetInput()->IsIntConstant()) {
+    int32_t value = GetInput()->AsIntConstant()->GetValue();
+    switch (GetResultType()) {
+      case Primitive::kPrimLong:
+        return graph->GetLongConstant(static_cast<int64_t>(value));
+      case Primitive::kPrimFloat:
+        return graph->GetFloatConstant(static_cast<float>(value));
+      case Primitive::kPrimDouble:
+        return graph->GetDoubleConstant(static_cast<double>(value));
+      default:
+        return nullptr;
+    }
+  } else if (GetInput()->IsLongConstant()) {
+    int64_t value = GetInput()->AsLongConstant()->GetValue();
+    switch (GetResultType()) {
+      case Primitive::kPrimInt:
+        return graph->GetIntConstant(static_cast<int32_t>(value));
+      case Primitive::kPrimFloat:
+        return graph->GetFloatConstant(static_cast<float>(value));
+      case Primitive::kPrimDouble:
+        return graph->GetDoubleConstant(static_cast<double>(value));
+      default:
+        return nullptr;
+    }
+  } else if (GetInput()->IsFloatConstant()) {
+    float value = GetInput()->AsFloatConstant()->GetValue();
+    switch (GetResultType()) {
+      case Primitive::kPrimInt:
+        if (std::isnan(value))
+          return graph->GetIntConstant(0);
+        if (value >= kPrimIntMax)
+          return graph->GetIntConstant(kPrimIntMax);
+        if (value <= kPrimIntMin)
+          return graph->GetIntConstant(kPrimIntMin);
+        return graph->GetIntConstant(static_cast<int32_t>(value));
+      case Primitive::kPrimLong:
+        if (std::isnan(value))
+          return graph->GetLongConstant(0);
+        if (value >= kPrimLongMax)
+          return graph->GetLongConstant(kPrimLongMax);
+        if (value <= kPrimLongMin)
+          return graph->GetLongConstant(kPrimLongMin);
+        return graph->GetLongConstant(static_cast<int64_t>(value));
+      case Primitive::kPrimDouble:
+        return graph->GetDoubleConstant(static_cast<double>(value));
+      default:
+        return nullptr;
+    }
+  } else if (GetInput()->IsDoubleConstant()) {
+    double value = GetInput()->AsDoubleConstant()->GetValue();
+    switch (GetResultType()) {
+      case Primitive::kPrimInt:
+        if (std::isnan(value))
+          return graph->GetIntConstant(0);
+        if (value >= kPrimIntMax)
+          return graph->GetIntConstant(kPrimIntMax);
+        if (value <= kPrimLongMin)
+          return graph->GetIntConstant(kPrimIntMin);
+        return graph->GetIntConstant(static_cast<int32_t>(value));
+      case Primitive::kPrimLong:
+        if (std::isnan(value))
+          return graph->GetLongConstant(0);
+        if (value >= kPrimLongMax)
+          return graph->GetLongConstant(kPrimLongMax);
+        if (value <= kPrimLongMin)
+          return graph->GetLongConstant(kPrimLongMin);
+        return graph->GetLongConstant(static_cast<int64_t>(value));
+      case Primitive::kPrimFloat:
+        return graph->GetFloatConstant(static_cast<float>(value));
+      default:
+        return nullptr;
+    }
+  }
+  return nullptr;
+}
+
 HConstant* HUnaryOperation::TryStaticEvaluation() const {
   if (GetInput()->IsIntConstant()) {
     int32_t value = Evaluate(GetInput()->AsIntConstant()->GetValue());
@@ -1049,20 +1163,6 @@
   SetGraph(nullptr);
 }
 
-void HBasicBlock::UpdateLoopInformation() {
-  // Check if loop information points to a dismantled loop. If so, replace with
-  // the loop information of a larger loop which contains this block, or nullptr
-  // otherwise. We iterate in case the larger loop has been destroyed too.
-  while (IsInLoop() && loop_information_->GetBackEdges().IsEmpty()) {
-    if (IsLoopHeader()) {
-      HSuspendCheck* suspend_check = loop_information_->GetSuspendCheck();
-      DCHECK_EQ(suspend_check->GetBlock(), this);
-      RemoveInstruction(suspend_check);
-    }
-    loop_information_ = loop_information_->GetPreHeader()->GetLoopInformation();
-  }
-}
-
 void HBasicBlock::MergeWith(HBasicBlock* other) {
   DCHECK_EQ(GetGraph(), other->GetGraph());
   DCHECK(GetDominatedBlocks().Contains(other));
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 031761e..cb2e5cc 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -436,6 +436,12 @@
   // that is the header dominates the back edge.
   bool Populate();
 
+  // Reanalyzes the loop by removing loop info from its blocks and re-running
+  // Populate(). If there are no back edges left, the loop info is completely
+  // removed as well as its SuspendCheck instruction. It must be run on nested
+  // inner loops first.
+  void Update();
+
   // Returns whether this loop information contains `block`.
   // Note that this loop information *must* be populated before entering this function.
   bool Contains(const HBasicBlock& block) const;
@@ -705,14 +711,9 @@
     loop_information_ = info;
   }
 
-  // Checks if the loop information points to a valid loop. If the loop has been
-  // dismantled (does not have a back edge any more), loop information is
-  // removed or replaced with the information of the first valid outer loop.
-  void UpdateLoopInformation();
-
   bool IsInLoop() const { return loop_information_ != nullptr; }
 
-  // Returns wheter this block dominates the blocked passed as parameter.
+  // Returns whether this block dominates the blocked passed as parameter.
   bool Dominates(HBasicBlock* block) const;
 
   size_t GetLifetimeStart() const { return lifetime_start_; }
@@ -2196,15 +2197,16 @@
   size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
 
   bool IsMinusOne() const OVERRIDE {
-    return bit_cast<uint32_t, float>(AsFloatConstant()->GetValue()) ==
-        bit_cast<uint32_t, float>((-1.0f));
+    return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>((-1.0f));
   }
   bool IsZero() const OVERRIDE {
-    return AsFloatConstant()->GetValue() == 0.0f;
+    return value_ == 0.0f;
   }
   bool IsOne() const OVERRIDE {
-    return bit_cast<uint32_t, float>(AsFloatConstant()->GetValue()) ==
-        bit_cast<uint32_t, float>(1.0f);
+    return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>(1.0f);
+  }
+  bool IsNaN() const {
+    return std::isnan(value_);
   }
 
   DECLARE_INSTRUCTION(FloatConstant);
@@ -2234,15 +2236,16 @@
   size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
 
   bool IsMinusOne() const OVERRIDE {
-    return bit_cast<uint64_t, double>(AsDoubleConstant()->GetValue()) ==
-        bit_cast<uint64_t, double>((-1.0));
+    return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>((-1.0));
   }
   bool IsZero() const OVERRIDE {
-    return AsDoubleConstant()->GetValue() == 0.0;
+    return value_ == 0.0;
   }
   bool IsOne() const OVERRIDE {
-    return bit_cast<uint64_t, double>(AsDoubleConstant()->GetValue()) ==
-        bit_cast<uint64_t, double>(1.0);
+    return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>(1.0);
+  }
+  bool IsNaN() const {
+    return std::isnan(value_);
   }
 
   DECLARE_INSTRUCTION(DoubleConstant);
@@ -2979,6 +2982,10 @@
   bool CanBeMoved() const OVERRIDE { return true; }
   bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { return true; }
 
+  // Try to statically evaluate the conversion and return a HConstant
+  // containing the result.  If the input cannot be converted, return nullptr.
+  HConstant* TryStaticEvaluation() const;
+
   DECLARE_INSTRUCTION(TypeConversion);
 
  private:
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index e993d77..8bb5d8e 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -320,8 +320,10 @@
                              const DexCompilationUnit& dex_compilation_unit,
                              PassInfoPrinter* pass_info_printer,
                              StackHandleScopeCollection* handles) {
-  HDeadCodeElimination dce1(graph, stats);
-  HDeadCodeElimination dce2(graph, stats, "dead_code_elimination_final");
+  HDeadCodeElimination dce1(graph, stats,
+                            HDeadCodeElimination::kInitialDeadCodeEliminationPassName);
+  HDeadCodeElimination dce2(graph, stats,
+                            HDeadCodeElimination::kFinalDeadCodeEliminationPassName);
   HConstantFolding fold1(graph);
   InstructionSimplifier simplify1(graph, stats);
   HBooleanSimplifier boolean_simplify(graph);
diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc
index f53f846..925099a 100644
--- a/compiler/optimizing/register_allocator.cc
+++ b/compiler/optimizing/register_allocator.cc
@@ -775,7 +775,7 @@
     } else if (current->IsLowInterval()) {
       reg = FindAvailableRegisterPair(free_until, current->GetStart());
     } else {
-      reg = FindAvailableRegister(free_until);
+      reg = FindAvailableRegister(free_until, current);
     }
   }
 
@@ -839,14 +839,52 @@
   return reg;
 }
 
-int RegisterAllocator::FindAvailableRegister(size_t* next_use) const {
+bool RegisterAllocator::IsCallerSaveRegister(int reg) const {
+  return processing_core_registers_
+      ? !codegen_->IsCoreCalleeSaveRegister(reg)
+      : !codegen_->IsFloatingPointCalleeSaveRegister(reg);
+}
+
+int RegisterAllocator::FindAvailableRegister(size_t* next_use, LiveInterval* current) const {
+  // We special case intervals that do not span a safepoint to try to find a caller-save
+  // register if one is available. We iterate from 0 to the number of registers,
+  // so if there are caller-save registers available at the end, we continue the iteration.
+  bool prefers_caller_save = !current->HasWillCallSafepoint();
   int reg = kNoRegister;
-  // Pick the register that is used the last.
   for (size_t i = 0; i < number_of_registers_; ++i) {
-    if (IsBlocked(i)) continue;
-    if (reg == kNoRegister || next_use[i] > next_use[reg]) {
+    if (IsBlocked(i)) {
+      // Register cannot be used. Continue.
+      continue;
+    }
+
+    // Best case: we found a register fully available.
+    if (next_use[i] == kMaxLifetimePosition) {
+      if (prefers_caller_save && !IsCallerSaveRegister(i)) {
+        // We can get shorter encodings on some platforms by using
+        // small register numbers. So only update the candidate if the previous
+        // one was not available for the whole method.
+        if (reg == kNoRegister || next_use[reg] != kMaxLifetimePosition) {
+          reg = i;
+        }
+        // Continue the iteration in the hope of finding a caller save register.
+        continue;
+      } else {
+        reg = i;
+        // We know the register is good enough. Return it.
+        break;
+      }
+    }
+
+    // If we had no register before, take this one as a reference.
+    if (reg == kNoRegister) {
       reg = i;
-      if (next_use[i] == kMaxLifetimePosition) break;
+      continue;
+    }
+
+    // Pick the register that is used the last.
+    if (next_use[i] > next_use[reg]) {
+      reg = i;
+      continue;
     }
   }
   return reg;
@@ -971,7 +1009,7 @@
       || (first_use >= next_use[GetHighForLowRegister(reg)]);
   } else {
     DCHECK(!current->IsHighInterval());
-    reg = FindAvailableRegister(next_use);
+    reg = FindAvailableRegister(next_use, current);
     should_spill = (first_use >= next_use[reg]);
   }
 
diff --git a/compiler/optimizing/register_allocator.h b/compiler/optimizing/register_allocator.h
index dc9c708..6d5bfc3 100644
--- a/compiler/optimizing/register_allocator.h
+++ b/compiler/optimizing/register_allocator.h
@@ -140,7 +140,8 @@
   void DumpInterval(std::ostream& stream, LiveInterval* interval) const;
   void DumpAllIntervals(std::ostream& stream) const;
   int FindAvailableRegisterPair(size_t* next_use, size_t starting_at) const;
-  int FindAvailableRegister(size_t* next_use) const;
+  int FindAvailableRegister(size_t* next_use, LiveInterval* current) const;
+  bool IsCallerSaveRegister(int reg) const;
 
   // Try splitting an active non-pair or unaligned pair interval at the given `position`.
   // Returns whether it was successful at finding such an interval.
diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h
index 82c5454..ce4bbd4 100644
--- a/compiler/optimizing/ssa_liveness_analysis.h
+++ b/compiler/optimizing/ssa_liveness_analysis.h
@@ -76,7 +76,7 @@
   }
 
   void Dump(std::ostream& stream) const {
-    stream << "[" << start_ << ", " << end_ << ")";
+    stream << start_ << "-" << end_;
   }
 
   LiveRange* Dup(ArenaAllocator* allocator) const {
@@ -542,6 +542,15 @@
     return defined_by_;
   }
 
+  bool HasWillCallSafepoint() const {
+    for (SafepointPosition* safepoint = first_safepoint_;
+         safepoint != nullptr;
+         safepoint = safepoint->GetNext()) {
+      if (safepoint->GetLocations()->WillCall()) return true;
+    }
+    return false;
+  }
+
   SafepointPosition* FindSafepointJustBefore(size_t position) const {
     for (SafepointPosition* safepoint = first_safepoint_, *previous = nullptr;
          safepoint != nullptr;
diff --git a/compiler/utils/arm/assembler_arm.cc b/compiler/utils/arm/assembler_arm.cc
index c410660..eca6f5a 100644
--- a/compiler/utils/arm/assembler_arm.cc
+++ b/compiler/utils/arm/assembler_arm.cc
@@ -860,8 +860,6 @@
   // Set up call to Thread::Current()->pDeliverException.
   __ LoadFromOffset(kLoadWord, R12, TR, QUICK_ENTRYPOINT_OFFSET(4, pDeliverException).Int32Value());
   __ blx(R12);
-  // Call never returns.
-  __ bkpt(0);
 #undef __
 }
 
diff --git a/compiler/utils/arm/assembler_arm.h b/compiler/utils/arm/assembler_arm.h
index 313f365..dee8287 100644
--- a/compiler/utils/arm/assembler_arm.h
+++ b/compiler/utils/arm/assembler_arm.h
@@ -398,6 +398,8 @@
                    Condition cond = AL) = 0;
   virtual void mls(Register rd, Register rn, Register rm, Register ra,
                    Condition cond = AL) = 0;
+  virtual void smull(Register rd_lo, Register rd_hi, Register rn, Register rm,
+                     Condition cond = AL) = 0;
   virtual void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
                      Condition cond = AL) = 0;
 
diff --git a/compiler/utils/arm/assembler_arm32.cc b/compiler/utils/arm/assembler_arm32.cc
index 9579691..6e165fc 100644
--- a/compiler/utils/arm/assembler_arm32.cc
+++ b/compiler/utils/arm/assembler_arm32.cc
@@ -200,6 +200,13 @@
 }
 
 
+void Arm32Assembler::smull(Register rd_lo, Register rd_hi, Register rn,
+                           Register rm, Condition cond) {
+  // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
+  EmitMulOp(cond, B23 | B22, rd_lo, rd_hi, rn, rm);
+}
+
+
 void Arm32Assembler::umull(Register rd_lo, Register rd_hi, Register rn,
                            Register rm, Condition cond) {
   // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
diff --git a/compiler/utils/arm/assembler_arm32.h b/compiler/utils/arm/assembler_arm32.h
index b922d66..55ec7b4 100644
--- a/compiler/utils/arm/assembler_arm32.h
+++ b/compiler/utils/arm/assembler_arm32.h
@@ -90,6 +90,8 @@
            Condition cond = AL) OVERRIDE;
   void mls(Register rd, Register rn, Register rm, Register ra,
            Condition cond = AL) OVERRIDE;
+  void smull(Register rd_lo, Register rd_hi, Register rn, Register rm,
+             Condition cond = AL) OVERRIDE;
   void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
              Condition cond = AL) OVERRIDE;
 
diff --git a/compiler/utils/arm/assembler_arm32_test.cc b/compiler/utils/arm/assembler_arm32_test.cc
index 4a0ae0b..efd517b 100644
--- a/compiler/utils/arm/assembler_arm32_test.cc
+++ b/compiler/utils/arm/assembler_arm32_test.cc
@@ -293,12 +293,29 @@
     f();
   }
 
+  // NOTE: Only support simple test like "aaa=bbb"
+  bool EvalFilterString(std::string filter) {
+    if (filter.compare("") == 0) {
+      return false;
+    }
+
+    size_t equal_sign_index = filter.find('=');
+    if (equal_sign_index == std::string::npos) {
+      EXPECT_TRUE(false) << "Unsupported filter string.";
+    }
+
+    std::string lhs = filter.substr(0, equal_sign_index);
+    std::string rhs = filter.substr(equal_sign_index + 1, std::string::npos);
+    return lhs.compare(rhs) == 0;
+  }
+
   void TemplateHelper(std::function<void(arm::Register)> f, int depth ATTRIBUTE_UNUSED,
-                      bool without_pc,
-                      std::string fmt, std::ostringstream& oss) {
+                      bool without_pc, std::string fmt, std::string filter,
+                      std::ostringstream& oss) {
     std::vector<arm::Register*> registers = without_pc ? GetRegistersWithoutPC() : GetRegisters();
     for (auto reg : registers) {
       std::string after_reg = fmt;
+      std::string after_reg_filter = filter;
 
       std::string reg_string = GetRegName<RegisterView::kUsePrimaryName>(*reg);
       size_t reg_index;
@@ -308,14 +325,23 @@
         after_reg.replace(reg_index, strlen(reg_token), reg_string);
       }
 
+      while ((reg_index = after_reg_filter.find(reg_token)) != std::string::npos) {
+        after_reg_filter.replace(reg_index, strlen(reg_token), reg_string);
+      }
+      if (EvalFilterString(after_reg_filter)) {
+        continue;
+      }
+
       ExecuteAndPrint([&] () { f(*reg); }, after_reg, oss);
     }
   }
 
   void TemplateHelper(std::function<void(const arm::ShifterOperand&)> f, int depth ATTRIBUTE_UNUSED,
-                      bool without_pc ATTRIBUTE_UNUSED, std::string fmt, std::ostringstream& oss) {
+                      bool without_pc ATTRIBUTE_UNUSED, std::string fmt, std::string filter,
+                      std::ostringstream& oss) {
     for (const arm::ShifterOperand& shift : GetShiftOperands()) {
       std::string after_shift = fmt;
+      std::string after_shift_filter = filter;
 
       std::string shift_string = GetShiftString(shift);
       size_t shift_index;
@@ -323,30 +349,48 @@
         after_shift.replace(shift_index, ConstexprStrLen(SHIFT_TOKEN), shift_string);
       }
 
+      while ((shift_index = after_shift_filter.find(SHIFT_TOKEN)) != std::string::npos) {
+        after_shift_filter.replace(shift_index, ConstexprStrLen(SHIFT_TOKEN), shift_string);
+      }
+      if (EvalFilterString(after_shift_filter)) {
+        continue;
+      }
+
       ExecuteAndPrint([&] () { f(shift); }, after_shift, oss);
     }
   }
 
   void TemplateHelper(std::function<void(arm::Condition)> f, int depth ATTRIBUTE_UNUSED,
-                      bool without_pc ATTRIBUTE_UNUSED, std::string fmt, std::ostringstream& oss) {
+                      bool without_pc ATTRIBUTE_UNUSED, std::string fmt, std::string filter,
+                      std::ostringstream& oss) {
     for (arm::Condition c : GetConditions()) {
       std::string after_cond = fmt;
+      std::string after_cond_filter = filter;
 
       size_t cond_index = after_cond.find(COND_TOKEN);
       if (cond_index != std::string::npos) {
         after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
       }
 
+      cond_index = after_cond_filter.find(COND_TOKEN);
+      if (cond_index != std::string::npos) {
+        after_cond_filter.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
+      }
+      if (EvalFilterString(after_cond_filter)) {
+        continue;
+      }
+
       ExecuteAndPrint([&] () { f(c); }, after_cond, oss);
     }
   }
 
   template <typename... Args>
   void TemplateHelper(std::function<void(arm::Register, Args...)> f, int depth, bool without_pc,
-                      std::string fmt, std::ostringstream& oss) {
+                      std::string fmt, std::string filter, std::ostringstream& oss) {
     std::vector<arm::Register*> registers = without_pc ? GetRegistersWithoutPC() : GetRegisters();
     for (auto reg : registers) {
       std::string after_reg = fmt;
+      std::string after_reg_filter = filter;
 
       std::string reg_string = GetRegName<RegisterView::kUsePrimaryName>(*reg);
       size_t reg_index;
@@ -356,17 +400,26 @@
         after_reg.replace(reg_index, strlen(reg_token), reg_string);
       }
 
+      while ((reg_index = after_reg_filter.find(reg_token)) != std::string::npos) {
+        after_reg_filter.replace(reg_index, strlen(reg_token), reg_string);
+      }
+      if (EvalFilterString(after_reg_filter)) {
+        continue;
+      }
+
       auto lambda = [&] (Args... args) { f(*reg, args...); };  // NOLINT [readability/braces] [4]
       TemplateHelper(std::function<void(Args...)>(lambda), depth + 1, without_pc,
-          after_reg, oss);
+          after_reg, after_reg_filter, oss);
     }
   }
 
   template <typename... Args>
   void TemplateHelper(std::function<void(const arm::ShifterOperand&, Args...)> f, int depth,
-                      bool without_pc, std::string fmt, std::ostringstream& oss) {
+                      bool without_pc, std::string fmt, std::string filter,
+                      std::ostringstream& oss) {
     for (const arm::ShifterOperand& shift : GetShiftOperands()) {
       std::string after_shift = fmt;
+      std::string after_shift_filter = filter;
 
       std::string shift_string = GetShiftString(shift);
       size_t shift_index;
@@ -374,26 +427,42 @@
         after_shift.replace(shift_index, ConstexprStrLen(SHIFT_TOKEN), shift_string);
       }
 
+      while ((shift_index = after_shift_filter.find(SHIFT_TOKEN)) != std::string::npos) {
+        after_shift_filter.replace(shift_index, ConstexprStrLen(SHIFT_TOKEN), shift_string);
+      }
+      if (EvalFilterString(after_shift_filter)) {
+        continue;
+      }
+
       auto lambda = [&] (Args... args) { f(shift, args...); };  // NOLINT [readability/braces] [4]
       TemplateHelper(std::function<void(Args...)>(lambda), depth, without_pc,
-          after_shift, oss);
+          after_shift, after_shift_filter, oss);
     }
   }
 
   template <typename... Args>
   void TemplateHelper(std::function<void(arm::Condition, Args...)> f, int depth, bool without_pc,
-                      std::string fmt, std::ostringstream& oss) {
+                      std::string fmt, std::string filter, std::ostringstream& oss) {
     for (arm::Condition c : GetConditions()) {
       std::string after_cond = fmt;
+      std::string after_cond_filter = filter;
 
       size_t cond_index = after_cond.find(COND_TOKEN);
       if (cond_index != std::string::npos) {
         after_cond.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
       }
 
+      cond_index = after_cond_filter.find(COND_TOKEN);
+      if (cond_index != std::string::npos) {
+        after_cond_filter.replace(cond_index, ConstexprStrLen(IMM1_TOKEN), GetConditionString(c));
+      }
+      if (EvalFilterString(after_cond_filter)) {
+        continue;
+      }
+
       auto lambda = [&] (Args... args) { f(c, args...); };  // NOLINT [readability/braces] [4]
       TemplateHelper(std::function<void(Args...)>(lambda), depth, without_pc,
-          after_cond, oss);
+          after_cond, after_cond_filter, oss);
     }
   }
 
@@ -421,13 +490,13 @@
 
   template <typename... Args>
   void GenericTemplateHelper(std::function<void(Args...)> f, bool without_pc,
-                             std::string fmt, std::string test_name) {
+                             std::string fmt, std::string test_name, std::string filter) {
     first_ = false;
     WarnOnCombinations(CountHelper<Args...>(without_pc));
 
     std::ostringstream oss;
 
-    TemplateHelper(f, 0, without_pc, fmt, oss);
+    TemplateHelper(f, 0, without_pc, fmt, filter, oss);
 
     oss << "\n";  // Trailing newline.
 
@@ -436,26 +505,26 @@
 
   template <typename... Args>
   void T2Helper(void (arm::Arm32Assembler::*f)(Args...), bool without_pc, std::string fmt,
-                std::string test_name) {
-    GenericTemplateHelper(GetBoundFunction2(f), without_pc, fmt, test_name);
+                std::string test_name, std::string filter = "") {
+    GenericTemplateHelper(GetBoundFunction2(f), without_pc, fmt, test_name, filter);
   }
 
   template <typename... Args>
   void T3Helper(void (arm::Arm32Assembler::*f)(Args...), bool without_pc, std::string fmt,
-      std::string test_name) {
-    GenericTemplateHelper(GetBoundFunction3(f), without_pc, fmt, test_name);
+      std::string test_name, std::string filter = "") {
+    GenericTemplateHelper(GetBoundFunction3(f), without_pc, fmt, test_name, filter);
   }
 
   template <typename... Args>
   void T4Helper(void (arm::Arm32Assembler::*f)(Args...), bool without_pc, std::string fmt,
-      std::string test_name) {
-    GenericTemplateHelper(GetBoundFunction4(f), without_pc, fmt, test_name);
+      std::string test_name, std::string filter = "") {
+    GenericTemplateHelper(GetBoundFunction4(f), without_pc, fmt, test_name, filter);
   }
 
   template <typename... Args>
   void T5Helper(void (arm::Arm32Assembler::*f)(Args...), bool without_pc, std::string fmt,
-      std::string test_name) {
-    GenericTemplateHelper(GetBoundFunction5(f), without_pc, fmt, test_name);
+      std::string test_name, std::string filter = "") {
+    GenericTemplateHelper(GetBoundFunction5(f), without_pc, fmt, test_name, filter);
   }
 
  private:
@@ -565,15 +634,18 @@
 }
 
 TEST_F(AssemblerArm32Test, Mla) {
-  T5Helper(&arm::Arm32Assembler::mla, true, "mla{cond} {reg1}, {reg2}, {reg3}, {reg4}", "mul");
+  T5Helper(&arm::Arm32Assembler::mla, true, "mla{cond} {reg1}, {reg2}, {reg3}, {reg4}", "mla");
 }
 
-/* TODO: Needs support to filter out register combinations, as rdhi must not be equal to rdlo.
 TEST_F(AssemblerArm32Test, Umull) {
   T5Helper(&arm::Arm32Assembler::umull, true, "umull{cond} {reg1}, {reg2}, {reg3}, {reg4}",
-           "umull");
+           "umull", "{reg1}={reg2}");  // Skip the cases where reg1 == reg2.
 }
-*/
+
+TEST_F(AssemblerArm32Test, Smull) {
+  T5Helper(&arm::Arm32Assembler::smull, true, "smull{cond} {reg1}, {reg2}, {reg3}, {reg4}",
+           "smull", "{reg1}={reg2}");  // Skip the cases where reg1 == reg2.
+}
 
 TEST_F(AssemblerArm32Test, Sdiv) {
   T4Helper(&arm::Arm32Assembler::sdiv, true, "sdiv{cond} {reg1}, {reg2}, {reg3}", "sdiv");
@@ -655,9 +727,10 @@
   T4Helper(&arm::Arm32Assembler::rsc, true, "rsc{cond} {reg1}, {reg2}, {shift}", "rsc");
 }
 
-/* TODO: Needs support to filter out register combinations, as reg1 must not be equal to reg3.
+/* TODO: Need better filter support.
 TEST_F(AssemblerArm32Test, Strex) {
-  RRRCWithoutPCHelper(&arm::Arm32Assembler::strex, "strex{cond} {reg1}, {reg2}, [{reg3}]", "strex");
+  T4Helper(&arm::Arm32Assembler::strex, "strex{cond} {reg1}, {reg2}, [{reg3}]", "strex",
+           "{reg1}={reg2}||{reg1}={reg3}");  // Skip the cases where reg1 == reg2 || reg1 == reg3.
 }
 */
 
diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc
index 3b42f63..e7cf26e 100644
--- a/compiler/utils/arm/assembler_thumb2.cc
+++ b/compiler/utils/arm/assembler_thumb2.cc
@@ -238,6 +238,24 @@
 }
 
 
+void Thumb2Assembler::smull(Register rd_lo, Register rd_hi, Register rn,
+                            Register rm, Condition cond) {
+  CheckCondition(cond);
+
+  uint32_t op1 = 0U /* 0b000; */;
+  uint32_t op2 = 0U /* 0b0000 */;
+  int32_t encoding = B31 | B30 | B29 | B28 | B27 | B25 | B24 | B23 |
+      op1 << 20 |
+      op2 << 4 |
+      static_cast<uint32_t>(rd_lo) << 12 |
+      static_cast<uint32_t>(rd_hi) << 8 |
+      static_cast<uint32_t>(rn) << 16 |
+      static_cast<uint32_t>(rm);
+
+  Emit32(encoding);
+}
+
+
 void Thumb2Assembler::umull(Register rd_lo, Register rd_hi, Register rn,
                             Register rm, Condition cond) {
   CheckCondition(cond);
@@ -740,13 +758,6 @@
     return true;
   }
 
-  // Check for MOV with an ROR.
-  if (opcode == MOV && so.IsRegister() && so.IsShift() && so.GetShift() == ROR) {
-    if (so.GetImmediate() != 0) {
-      return true;
-    }
-  }
-
   bool rn_is_valid = true;
 
   // Check for single operand instructions and ADD/SUB.
@@ -792,6 +803,19 @@
     }
   }
 
+  // Check for register shift operand.
+  if (so.IsRegister() && so.IsShift()) {
+    if (opcode != MOV) {
+      return true;
+    }
+    // Check for MOV with an ROR.
+    if (so.GetShift() == ROR) {
+      if (so.GetImmediate() != 0) {
+        return true;
+      }
+    }
+  }
+
   // The instruction can be encoded in 16 bits.
   return false;
 }
diff --git a/compiler/utils/arm/assembler_thumb2.h b/compiler/utils/arm/assembler_thumb2.h
index e33c240..17eae8b 100644
--- a/compiler/utils/arm/assembler_thumb2.h
+++ b/compiler/utils/arm/assembler_thumb2.h
@@ -112,6 +112,8 @@
            Condition cond = AL) OVERRIDE;
   void mls(Register rd, Register rn, Register rm, Register ra,
            Condition cond = AL) OVERRIDE;
+  void smull(Register rd_lo, Register rd_hi, Register rn, Register rm,
+             Condition cond = AL) OVERRIDE;
   void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
              Condition cond = AL) OVERRIDE;
 
diff --git a/compiler/utils/arm/assembler_thumb2_test.cc b/compiler/utils/arm/assembler_thumb2_test.cc
index 5f5561a..733441b 100644
--- a/compiler/utils/arm/assembler_thumb2_test.cc
+++ b/compiler/utils/arm/assembler_thumb2_test.cc
@@ -89,23 +89,24 @@
   EXPECT_TRUE(CheckTools());
 }
 
+#define __ GetAssembler()->
 
 TEST_F(AssemblerThumb2Test, Sbfx) {
-  GetAssembler()->sbfx(arm::R0, arm::R1, 0, 1);
-  GetAssembler()->sbfx(arm::R0, arm::R1, 0, 8);
-  GetAssembler()->sbfx(arm::R0, arm::R1, 0, 16);
-  GetAssembler()->sbfx(arm::R0, arm::R1, 0, 32);
+  __ sbfx(arm::R0, arm::R1, 0, 1);
+  __ sbfx(arm::R0, arm::R1, 0, 8);
+  __ sbfx(arm::R0, arm::R1, 0, 16);
+  __ sbfx(arm::R0, arm::R1, 0, 32);
 
-  GetAssembler()->sbfx(arm::R0, arm::R1, 8, 1);
-  GetAssembler()->sbfx(arm::R0, arm::R1, 8, 8);
-  GetAssembler()->sbfx(arm::R0, arm::R1, 8, 16);
-  GetAssembler()->sbfx(arm::R0, arm::R1, 8, 24);
+  __ sbfx(arm::R0, arm::R1, 8, 1);
+  __ sbfx(arm::R0, arm::R1, 8, 8);
+  __ sbfx(arm::R0, arm::R1, 8, 16);
+  __ sbfx(arm::R0, arm::R1, 8, 24);
 
-  GetAssembler()->sbfx(arm::R0, arm::R1, 16, 1);
-  GetAssembler()->sbfx(arm::R0, arm::R1, 16, 8);
-  GetAssembler()->sbfx(arm::R0, arm::R1, 16, 16);
+  __ sbfx(arm::R0, arm::R1, 16, 1);
+  __ sbfx(arm::R0, arm::R1, 16, 8);
+  __ sbfx(arm::R0, arm::R1, 16, 16);
 
-  GetAssembler()->sbfx(arm::R0, arm::R1, 31, 1);
+  __ sbfx(arm::R0, arm::R1, 31, 1);
 
   const char* expected =
       "sbfx r0, r1, #0, #1\n"
@@ -127,21 +128,21 @@
 }
 
 TEST_F(AssemblerThumb2Test, Ubfx) {
-  GetAssembler()->ubfx(arm::R0, arm::R1, 0, 1);
-  GetAssembler()->ubfx(arm::R0, arm::R1, 0, 8);
-  GetAssembler()->ubfx(arm::R0, arm::R1, 0, 16);
-  GetAssembler()->ubfx(arm::R0, arm::R1, 0, 32);
+  __ ubfx(arm::R0, arm::R1, 0, 1);
+  __ ubfx(arm::R0, arm::R1, 0, 8);
+  __ ubfx(arm::R0, arm::R1, 0, 16);
+  __ ubfx(arm::R0, arm::R1, 0, 32);
 
-  GetAssembler()->ubfx(arm::R0, arm::R1, 8, 1);
-  GetAssembler()->ubfx(arm::R0, arm::R1, 8, 8);
-  GetAssembler()->ubfx(arm::R0, arm::R1, 8, 16);
-  GetAssembler()->ubfx(arm::R0, arm::R1, 8, 24);
+  __ ubfx(arm::R0, arm::R1, 8, 1);
+  __ ubfx(arm::R0, arm::R1, 8, 8);
+  __ ubfx(arm::R0, arm::R1, 8, 16);
+  __ ubfx(arm::R0, arm::R1, 8, 24);
 
-  GetAssembler()->ubfx(arm::R0, arm::R1, 16, 1);
-  GetAssembler()->ubfx(arm::R0, arm::R1, 16, 8);
-  GetAssembler()->ubfx(arm::R0, arm::R1, 16, 16);
+  __ ubfx(arm::R0, arm::R1, 16, 1);
+  __ ubfx(arm::R0, arm::R1, 16, 8);
+  __ ubfx(arm::R0, arm::R1, 16, 16);
 
-  GetAssembler()->ubfx(arm::R0, arm::R1, 31, 1);
+  __ ubfx(arm::R0, arm::R1, 31, 1);
 
   const char* expected =
       "ubfx r0, r1, #0, #1\n"
@@ -163,7 +164,7 @@
 }
 
 TEST_F(AssemblerThumb2Test, Vmstat) {
-  GetAssembler()->vmstat();
+  __ vmstat();
 
   const char* expected = "vmrs APSR_nzcv, FPSCR\n";
 
@@ -171,10 +172,10 @@
 }
 
 TEST_F(AssemblerThumb2Test, ldrexd) {
-  GetAssembler()->ldrexd(arm::R0, arm::R1, arm::R0);
-  GetAssembler()->ldrexd(arm::R0, arm::R1, arm::R1);
-  GetAssembler()->ldrexd(arm::R0, arm::R1, arm::R2);
-  GetAssembler()->ldrexd(arm::R5, arm::R3, arm::R7);
+  __ ldrexd(arm::R0, arm::R1, arm::R0);
+  __ ldrexd(arm::R0, arm::R1, arm::R1);
+  __ ldrexd(arm::R0, arm::R1, arm::R2);
+  __ ldrexd(arm::R5, arm::R3, arm::R7);
 
   const char* expected =
       "ldrexd r0, r1, [r0]\n"
@@ -185,10 +186,10 @@
 }
 
 TEST_F(AssemblerThumb2Test, strexd) {
-  GetAssembler()->strexd(arm::R9, arm::R0, arm::R1, arm::R0);
-  GetAssembler()->strexd(arm::R9, arm::R0, arm::R1, arm::R1);
-  GetAssembler()->strexd(arm::R9, arm::R0, arm::R1, arm::R2);
-  GetAssembler()->strexd(arm::R9, arm::R5, arm::R3, arm::R7);
+  __ strexd(arm::R9, arm::R0, arm::R1, arm::R0);
+  __ strexd(arm::R9, arm::R0, arm::R1, arm::R1);
+  __ strexd(arm::R9, arm::R0, arm::R1, arm::R2);
+  __ strexd(arm::R9, arm::R5, arm::R3, arm::R7);
 
   const char* expected =
       "strexd r9, r0, r1, [r0]\n"
@@ -199,9 +200,9 @@
 }
 
 TEST_F(AssemblerThumb2Test, LdrdStrd) {
-  GetAssembler()->ldrd(arm::R0, arm::Address(arm::R2, 8));
-  GetAssembler()->ldrd(arm::R0, arm::Address(arm::R12));
-  GetAssembler()->strd(arm::R0, arm::Address(arm::R2, 8));
+  __ ldrd(arm::R0, arm::Address(arm::R2, 8));
+  __ ldrd(arm::R0, arm::Address(arm::R12));
+  __ strd(arm::R0, arm::Address(arm::R2, 8));
 
   const char* expected =
       "ldrd r0, r1, [r2, #8]\n"
@@ -211,7 +212,6 @@
 }
 
 TEST_F(AssemblerThumb2Test, eor) {
-#define __ GetAssembler()->
   __ eor(arm::R1, arm::R1, arm::ShifterOperand(arm::R0));
   __ eor(arm::R1, arm::R0, arm::ShifterOperand(arm::R1));
   __ eor(arm::R1, arm::R8, arm::ShifterOperand(arm::R0));
@@ -230,23 +230,47 @@
 TEST_F(AssemblerThumb2Test, sub) {
   __ subs(arm::R1, arm::R0, arm::ShifterOperand(42));
   __ sub(arm::R1, arm::R0, arm::ShifterOperand(42));
+  __ subs(arm::R1, arm::R0, arm::ShifterOperand(arm::R2, arm::ASR, 31));
+  __ sub(arm::R1, arm::R0, arm::ShifterOperand(arm::R2, arm::ASR, 31));
 
   const char* expected =
       "subs r1, r0, #42\n"
-      "subw r1, r0, #42\n";
+      "subw r1, r0, #42\n"
+      "subs r1, r0, r2, asr #31\n"
+      "sub r1, r0, r2, asr #31\n";
   DriverStr(expected, "sub");
 }
 
 TEST_F(AssemblerThumb2Test, add) {
   __ adds(arm::R1, arm::R0, arm::ShifterOperand(42));
   __ add(arm::R1, arm::R0, arm::ShifterOperand(42));
+  __ adds(arm::R1, arm::R0, arm::ShifterOperand(arm::R2, arm::ASR, 31));
+  __ add(arm::R1, arm::R0, arm::ShifterOperand(arm::R2, arm::ASR, 31));
 
   const char* expected =
       "adds r1, r0, #42\n"
-      "addw r1, r0, #42\n";
+      "addw r1, r0, #42\n"
+      "adds r1, r0, r2, asr #31\n"
+      "add r1, r0, r2, asr #31\n";
   DriverStr(expected, "add");
 }
 
+TEST_F(AssemblerThumb2Test, umull) {
+  __ umull(arm::R0, arm::R1, arm::R2, arm::R3);
+
+  const char* expected =
+      "umull r0, r1, r2, r3\n";
+  DriverStr(expected, "umull");
+}
+
+TEST_F(AssemblerThumb2Test, smull) {
+  __ smull(arm::R0, arm::R1, arm::R2, arm::R3);
+
+  const char* expected =
+      "smull r0, r1, r2, r3\n";
+  DriverStr(expected, "smull");
+}
+
 TEST_F(AssemblerThumb2Test, StoreWordToThumbOffset) {
   arm::StoreOperandType type = arm::kStoreWord;
   int32_t offset = 4092;
diff --git a/compiler/utils/assembler_thumb_test.cc b/compiler/utils/assembler_thumb_test.cc
index 772fa9a..7738627 100644
--- a/compiler/utils/assembler_thumb_test.cc
+++ b/compiler/utils/assembler_thumb_test.cc
@@ -15,9 +15,11 @@
  */
 
 #include <dirent.h>
+#include <errno.h>
 #include <fstream>
-#include <sys/types.h>
 #include <map>
+#include <string.h>
+#include <sys/types.h>
 
 #include "gtest/gtest.h"
 #include "utils/arm/assembler_thumb2.h"
@@ -105,12 +107,14 @@
 
   // Assemble the .S
   snprintf(cmd, sizeof(cmd), "%sas %s -o %s.o", toolsdir.c_str(), filename, filename);
-  system(cmd);
+  int cmd_result = system(cmd);
+  ASSERT_EQ(cmd_result, 0) << strerror(errno);
 
   // Remove the $d symbols to prevent the disassembler dumping the instructions
   // as .word
   snprintf(cmd, sizeof(cmd), "%sobjcopy -N '$d' %s.o %s.oo", toolsdir.c_str(), filename, filename);
-  system(cmd);
+  int cmd_result2 = system(cmd);
+  ASSERT_EQ(cmd_result2, 0) << strerror(errno);
 
   // Disassemble.
 
@@ -119,7 +123,8 @@
   if (kPrintResults) {
     // Print the results only, don't check. This is used to generate new output for inserting
     // into the .inc file.
-    system(cmd);
+    int cmd_result3 = system(cmd);
+    ASSERT_EQ(cmd_result3, 0) << strerror(errno);
   } else {
     // Check the results match the appropriate results in the .inc file.
     FILE *fp = popen(cmd, "r");
diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc
index f2541a2..7e75200 100644
--- a/compiler/utils/x86/assembler_x86.cc
+++ b/compiler/utils/x86/assembler_x86.cc
@@ -1507,6 +1507,14 @@
 }
 
 
+void X86Assembler::repne_scasw() {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x66);
+  EmitUint8(0xF2);
+  EmitUint8(0xAF);
+}
+
+
 X86Assembler* X86Assembler::lock() {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xF0);
diff --git a/compiler/utils/x86/assembler_x86.h b/compiler/utils/x86/assembler_x86.h
index 946c96d..136b0cb 100644
--- a/compiler/utils/x86/assembler_x86.h
+++ b/compiler/utils/x86/assembler_x86.h
@@ -464,6 +464,8 @@
   void jmp(const Address& address);
   void jmp(Label* label);
 
+  void repne_scasw();
+
   X86Assembler* lock();
   void cmpxchgl(const Address& address, Register reg);
   void cmpxchg8b(const Address& address);
diff --git a/compiler/utils/x86/assembler_x86_test.cc b/compiler/utils/x86/assembler_x86_test.cc
index f326e49..aacc57b 100644
--- a/compiler/utils/x86/assembler_x86_test.cc
+++ b/compiler/utils/x86/assembler_x86_test.cc
@@ -190,4 +190,10 @@
   DriverStr(expected, "FPUIntegerStore");
 }
 
+TEST_F(AssemblerX86Test, Repnescasw) {
+  GetAssembler()->repne_scasw();
+  const char* expected = "repne scasw\n";
+  DriverStr(expected, "Repnescasw");
+}
+
 }  // namespace art
diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc
index c0ca7ef..feceeca 100644
--- a/compiler/utils/x86_64/assembler_x86_64.cc
+++ b/compiler/utils/x86_64/assembler_x86_64.cc
@@ -2065,6 +2065,14 @@
 }
 
 
+void X86_64Assembler::repne_scasw() {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x66);
+  EmitUint8(0xF2);
+  EmitUint8(0xAF);
+}
+
+
 void X86_64Assembler::LoadDoubleConstant(XmmRegister dst, double value) {
   // TODO: Need to have a code constants table.
   int64_t constant = bit_cast<int64_t, double>(value);
diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h
index f5327a8..162714a 100644
--- a/compiler/utils/x86_64/assembler_x86_64.h
+++ b/compiler/utils/x86_64/assembler_x86_64.h
@@ -601,6 +601,8 @@
   void bswapl(CpuRegister dst);
   void bswapq(CpuRegister dst);
 
+  void repne_scasw();
+
   //
   // Macros for High-level operations.
   //
diff --git a/compiler/utils/x86_64/assembler_x86_64_test.cc b/compiler/utils/x86_64/assembler_x86_64_test.cc
index 9e4144a..0be4d63 100644
--- a/compiler/utils/x86_64/assembler_x86_64_test.cc
+++ b/compiler/utils/x86_64/assembler_x86_64_test.cc
@@ -1215,4 +1215,10 @@
   DriverStr(Repeatrb(&x86_64::X86_64Assembler::movsxb, "movsbl %{reg2}, %{reg1}"), "movsxb");
 }
 
+TEST_F(AssemblerX86_64Test, Repnescasw) {
+  GetAssembler()->repne_scasw();
+  const char* expected = "repne scasw\n";
+  DriverStr(expected, "Repnescasw");
+}
+
 }  // namespace art
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index 4dc0967..ef84a17 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -650,29 +650,34 @@
 template <typename ElfFileImpl>
 bool PatchOat::PatchElf(ElfFileImpl* oat_file) {
   TimingLogger::ScopedTiming t("Fixup Elf Text Section", timings_);
+
+  // Fix up absolute references to locations within the boot image.
   if (!oat_file->ApplyOatPatchesTo(".text", delta_)) {
     return false;
   }
 
+  // Update the OatHeader fields referencing the boot image.
   if (!PatchOatHeader<ElfFileImpl>(oat_file)) {
     return false;
   }
 
-  bool need_fixup = false;
+  bool need_boot_oat_fixup = true;
   for (unsigned int i = 0; i < oat_file->GetProgramHeaderNum(); ++i) {
     auto hdr = oat_file->GetProgramHeader(i);
-    if ((hdr->p_vaddr != 0 && hdr->p_vaddr != hdr->p_offset) ||
-        (hdr->p_paddr != 0 && hdr->p_paddr != hdr->p_offset)) {
-      need_fixup = true;
+    if (hdr->p_type == PT_LOAD && hdr->p_vaddr == 0u) {
+      need_boot_oat_fixup = false;
       break;
     }
   }
-  if (!need_fixup) {
-    // This was never passed through ElfFixup so all headers/symbols just have their offset as
-    // their addr. Therefore we do not need to update these parts.
+  if (!need_boot_oat_fixup) {
+    // This is an app oat file that can be loaded at an arbitrary address in memory.
+    // Boot image references were patched above and there's nothing else to do.
     return true;
   }
 
+  // This is a boot oat file that's loaded at a particular address and we need
+  // to patch all absolute addresses, starting with ELF program headers.
+
   t.NewTiming("Fixup Elf Headers");
   // Fixup Phdr's
   oat_file->FixupProgramHeaders(delta_);
diff --git a/runtime/arch/arm/entrypoints_init_arm.cc b/runtime/arch/arm/entrypoints_init_arm.cc
index f14dfc2..cafc868 100644
--- a/runtime/arch/arm/entrypoints_init_arm.cc
+++ b/runtime/arch/arm/entrypoints_init_arm.cc
@@ -166,6 +166,9 @@
   qpoints->pThrowStackOverflow = art_quick_throw_stack_overflow;
 
   qpoints->pDeoptimize = art_quick_deoptimize;
+
+  // Read barrier
+  qpoints->pReadBarrierJni = ReadBarrierJni;
 }
 
 }  // namespace art
diff --git a/runtime/arch/arm64/entrypoints_init_arm64.cc b/runtime/arch/arm64/entrypoints_init_arm64.cc
index 4b12f00..8c8f8d5 100644
--- a/runtime/arch/arm64/entrypoints_init_arm64.cc
+++ b/runtime/arch/arm64/entrypoints_init_arm64.cc
@@ -159,6 +159,9 @@
 
   // Deoptimize
   qpoints->pDeoptimize = art_quick_deoptimize;
+
+  // Read barrier
+  qpoints->pReadBarrierJni = ReadBarrierJni;
 };
 
 }  // namespace art
diff --git a/runtime/arch/mips/entrypoints_init_mips.cc b/runtime/arch/mips/entrypoints_init_mips.cc
index a980a86..ff04106 100644
--- a/runtime/arch/mips/entrypoints_init_mips.cc
+++ b/runtime/arch/mips/entrypoints_init_mips.cc
@@ -272,6 +272,9 @@
   static_assert(IsDirectEntrypoint(kQuickA64Load), "Non-direct C stub marked direct.");
   qpoints->pA64Store = QuasiAtomic::Write64;
   static_assert(IsDirectEntrypoint(kQuickA64Store), "Non-direct C stub marked direct.");
+
+  qpoints->pReadBarrierJni = ReadBarrierJni;
+  static_assert(!IsDirectEntrypoint(kQuickReadBarrierJni), "Non-direct C stub marked direct.");
 };
 
 }  // namespace art
diff --git a/runtime/arch/mips64/entrypoints_init_mips64.cc b/runtime/arch/mips64/entrypoints_init_mips64.cc
index b328708..321c27b 100644
--- a/runtime/arch/mips64/entrypoints_init_mips64.cc
+++ b/runtime/arch/mips64/entrypoints_init_mips64.cc
@@ -180,6 +180,9 @@
   // Atomic 64-bit load/store
   qpoints->pA64Load = QuasiAtomic::Read64;
   qpoints->pA64Store = QuasiAtomic::Write64;
+
+  // Read barrier
+  qpoints->pReadBarrierJni = ReadBarrierJni;
 };
 
 }  // namespace art
diff --git a/runtime/arch/x86/entrypoints_init_x86.cc b/runtime/arch/x86/entrypoints_init_x86.cc
index a371632..737f4d1 100644
--- a/runtime/arch/x86/entrypoints_init_x86.cc
+++ b/runtime/arch/x86/entrypoints_init_x86.cc
@@ -138,6 +138,9 @@
 
   // Deoptimize
   qpoints->pDeoptimize = art_quick_deoptimize_from_compiled_slow_path;
+
+  // Read barrier
+  qpoints->pReadBarrierJni = ReadBarrierJni;
 };
 
 }  // namespace art
diff --git a/runtime/arch/x86_64/entrypoints_init_x86_64.cc b/runtime/arch/x86_64/entrypoints_init_x86_64.cc
index 0cddec4..d0ab9d5 100644
--- a/runtime/arch/x86_64/entrypoints_init_x86_64.cc
+++ b/runtime/arch/x86_64/entrypoints_init_x86_64.cc
@@ -142,6 +142,9 @@
 
   // Deoptimize
   qpoints->pDeoptimize = art_quick_deoptimize_from_compiled_slow_path;
+
+  // Read barrier
+  qpoints->pReadBarrierJni = ReadBarrierJni;
 #endif  // __APPLE__
 };
 
diff --git a/runtime/art_field.cc b/runtime/art_field.cc
index 2aed440..47d5a76 100644
--- a/runtime/art_field.cc
+++ b/runtime/art_field.cc
@@ -63,6 +63,17 @@
       FindInstanceFieldWithOffset(klass->GetSuperClass(), field_offset) : nullptr;
 }
 
+ArtField* ArtField::FindStaticFieldWithOffset(mirror::Class* klass, uint32_t field_offset) {
+  DCHECK(klass != nullptr);
+  auto* static_fields = klass->GetSFields();
+  for (size_t i = 0, count = klass->NumStaticFields(); i < count; ++i) {
+    if (static_fields[i].GetOffset().Uint32Value() == field_offset) {
+      return &static_fields[i];
+    }
+  }
+  return nullptr;
+}
+
 mirror::Class* ArtField::ProxyFindSystemClass(const char* descriptor) {
   DCHECK(GetDeclaringClass()->IsProxyClass());
   return Runtime::Current()->GetClassLinker()->FindSystemClass(Thread::Current(), descriptor);
diff --git a/runtime/art_field.h b/runtime/art_field.h
index c0620bf..9d3dbd9 100644
--- a/runtime/art_field.h
+++ b/runtime/art_field.h
@@ -161,6 +161,9 @@
   // Returns an instance field with this offset in the given class or null if not found.
   static ArtField* FindInstanceFieldWithOffset(mirror::Class* klass, uint32_t field_offset)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  // Returns a static field with this offset in the given class or null if not found.
+  static ArtField* FindStaticFieldWithOffset(mirror::Class* klass, uint32_t field_offset)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
diff --git a/runtime/asm_support.h b/runtime/asm_support.h
index de4783a..3e677a4 100644
--- a/runtime/asm_support.h
+++ b/runtime/asm_support.h
@@ -108,7 +108,7 @@
 ADD_TEST_EQ(THREAD_SELF_OFFSET,
             art::Thread::SelfOffset<__SIZEOF_POINTER__>().Int32Value())
 
-#define THREAD_LOCAL_POS_OFFSET (THREAD_CARD_TABLE_OFFSET + 145 * __SIZEOF_POINTER__)
+#define THREAD_LOCAL_POS_OFFSET (THREAD_CARD_TABLE_OFFSET + 146 * __SIZEOF_POINTER__)
 ADD_TEST_EQ(THREAD_LOCAL_POS_OFFSET,
             art::Thread::ThreadLocalPosOffset<__SIZEOF_POINTER__>().Int32Value())
 #define THREAD_LOCAL_END_OFFSET (THREAD_LOCAL_POS_OFFSET + __SIZEOF_POINTER__)
diff --git a/runtime/base/bit_vector.cc b/runtime/base/bit_vector.cc
index 65cb028..39ce0d2 100644
--- a/runtime/base/bit_vector.cc
+++ b/runtime/base/bit_vector.cc
@@ -24,11 +24,6 @@
 
 namespace art {
 
-// The number of words necessary to encode bits.
-static constexpr uint32_t BitsToWords(uint32_t bits) {
-  return RoundUp(bits, 32) / 32;
-}
-
 // TODO: replace excessive argument defaulting when we are at gcc 4.7
 // or later on host with delegating constructor support. Specifically,
 // starts_bits and storage_size/storage are mutually exclusive.
diff --git a/runtime/base/bit_vector.h b/runtime/base/bit_vector.h
index be4d363..6e4367a 100644
--- a/runtime/base/bit_vector.h
+++ b/runtime/base/bit_vector.h
@@ -20,6 +20,8 @@
 #include <stdint.h>
 #include <iterator>
 
+#include "utils.h"
+
 namespace art {
 
 class Allocator;
@@ -116,6 +118,11 @@
 
   virtual ~BitVector();
 
+  // The number of words necessary to encode bits.
+  static constexpr uint32_t BitsToWords(uint32_t bits) {
+    return RoundUp(bits, kWordBits) / kWordBits;
+  }
+
   // Mark the specified bit as "set".
   void SetBit(uint32_t idx) {
     /*
diff --git a/runtime/base/logging.cc b/runtime/base/logging.cc
index 0ae7863..859de4b 100644
--- a/runtime/base/logging.cc
+++ b/runtime/base/logging.cc
@@ -289,17 +289,17 @@
   CHECK_EQ(strlen(log_characters), INTERNAL_FATAL + 1U);
 
   const char* program_name = ProgramInvocationShortName();
-  write(STDERR_FILENO, program_name, strlen(program_name));
-  write(STDERR_FILENO, " ", 1);
-  write(STDERR_FILENO, &log_characters[log_severity], 1);
-  write(STDERR_FILENO, " ", 1);
+  TEMP_FAILURE_RETRY(write(STDERR_FILENO, program_name, strlen(program_name)));
+  TEMP_FAILURE_RETRY(write(STDERR_FILENO, " ", 1));
+  TEMP_FAILURE_RETRY(write(STDERR_FILENO, &log_characters[log_severity], 1));
+  TEMP_FAILURE_RETRY(write(STDERR_FILENO, " ", 1));
   // TODO: pid and tid.
-  write(STDERR_FILENO, file, strlen(file));
+  TEMP_FAILURE_RETRY(write(STDERR_FILENO, file, strlen(file)));
   // TODO: line.
   UNUSED(line);
-  write(STDERR_FILENO, "] ", 2);
-  write(STDERR_FILENO, message, strlen(message));
-  write(STDERR_FILENO, "\n", 1);
+  TEMP_FAILURE_RETRY(write(STDERR_FILENO, "] ", 2));
+  TEMP_FAILURE_RETRY(write(STDERR_FILENO, message, strlen(message)));
+  TEMP_FAILURE_RETRY(write(STDERR_FILENO, "\n", 1));
 #endif
 }
 
diff --git a/runtime/base/unix_file/fd_file.cc b/runtime/base/unix_file/fd_file.cc
index f272d88..07cadc4 100644
--- a/runtime/base/unix_file/fd_file.cc
+++ b/runtime/base/unix_file/fd_file.cc
@@ -107,7 +107,7 @@
 }
 
 int FdFile::Close() {
-  int result = TEMP_FAILURE_RETRY(close(fd_));
+  int result = close(fd_);
 
   // Test here, so the file is closed and not leaked.
   if (kCheckSafeUsage) {
diff --git a/runtime/check_reference_map_visitor.h b/runtime/check_reference_map_visitor.h
index 5d9cd35..d87a563 100644
--- a/runtime/check_reference_map_visitor.h
+++ b/runtime/check_reference_map_visitor.h
@@ -29,7 +29,7 @@
 class CheckReferenceMapVisitor : public StackVisitor {
  public:
   explicit CheckReferenceMapVisitor(Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(thread, nullptr) {}
+      : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames) {}
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     mirror::ArtMethod* m = GetMethod();
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc
index 0808999..b401066 100644
--- a/runtime/common_throws.cc
+++ b/runtime/common_throws.cc
@@ -283,8 +283,7 @@
 // NoSuchFieldError
 
 void ThrowNoSuchFieldError(const StringPiece& scope, mirror::Class* c,
-                           const StringPiece& type, const StringPiece& name)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+                           const StringPiece& type, const StringPiece& name) {
   std::ostringstream msg;
   std::string temp;
   msg << "No " << scope << "field " << name << " of type " << type
@@ -292,6 +291,13 @@
   ThrowException("Ljava/lang/NoSuchFieldError;", c, msg.str().c_str());
 }
 
+void ThrowNoSuchFieldException(mirror::Class* c, const StringPiece& name) {
+  std::ostringstream msg;
+  std::string temp;
+  msg << "No field " << name << " in class " << c->GetDescriptor(&temp);
+  ThrowException("Ljava/lang/NoSuchFieldException;", c, msg.str().c_str());
+}
+
 // NoSuchMethodError
 
 void ThrowNoSuchMethodError(InvokeType type, mirror::Class* c, const StringPiece& name,
diff --git a/runtime/common_throws.h b/runtime/common_throws.h
index df95cf9..49890e2 100644
--- a/runtime/common_throws.h
+++ b/runtime/common_throws.h
@@ -149,6 +149,9 @@
                            const StringPiece& type, const StringPiece& name)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+void ThrowNoSuchFieldException(mirror::Class* c, const StringPiece& name)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
 // NoSuchMethodError
 
 void ThrowNoSuchMethodError(InvokeType type, mirror::Class* c, const StringPiece& name,
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 9b33e50..852ba49 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -411,7 +411,7 @@
 }
 
 void SingleStepControl::VisitRoots(RootVisitor* visitor, const RootInfo& root_info) {
-  visitor->VisitRootIfNonNull(reinterpret_cast<mirror::Object**>(&method_), root_info);
+  method_.VisitRootIfNonNull(visitor, root_info);
 }
 
 void SingleStepControl::AddDexPc(uint32_t dex_pc) {
@@ -890,8 +890,10 @@
                         std::vector<JDWP::ObjectId>* monitor_vector,
                         std::vector<uint32_t>* stack_depth_vector)
         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(thread, context), current_stack_depth(0),
-        monitors(monitor_vector), stack_depths(stack_depth_vector) {}
+      : StackVisitor(thread, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+        current_stack_depth(0),
+        monitors(monitor_vector),
+        stack_depths(stack_depth_vector) {}
 
     // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
     // annotalysis.
@@ -2141,6 +2143,7 @@
     case kWaitingForDebuggerToAttach:
     case kWaitingForDeoptimization:
     case kWaitingForGcToComplete:
+    case kWaitingForGetObjectsAllocated:
     case kWaitingForJniOnLoad:
     case kWaitingForMethodTracingStart:
     case kWaitingForSignalCatcherOutput:
@@ -2252,7 +2255,8 @@
 static int GetStackDepth(Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   struct CountStackDepthVisitor : public StackVisitor {
     explicit CountStackDepthVisitor(Thread* thread_in)
-        : StackVisitor(thread_in, nullptr), depth(0) {}
+        : StackVisitor(thread_in, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+          depth(0) {}
 
     // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
     // annotalysis.
@@ -2292,8 +2296,11 @@
     GetFrameVisitor(Thread* thread, size_t start_frame_in, size_t frame_count_in,
                     JDWP::ExpandBuf* buf_in)
         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-        : StackVisitor(thread, nullptr), depth_(0),
-          start_frame_(start_frame_in), frame_count_(frame_count_in), buf_(buf_in) {
+        : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+          depth_(0),
+          start_frame_(start_frame_in),
+          frame_count_(frame_count_in),
+          buf_(buf_in) {
       expandBufAdd4BE(buf_, frame_count_);
     }
 
@@ -2410,7 +2417,9 @@
 struct GetThisVisitor : public StackVisitor {
   GetThisVisitor(Thread* thread, Context* context, JDWP::FrameId frame_id_in)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(thread, context), this_object(nullptr), frame_id(frame_id_in) {}
+      : StackVisitor(thread, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+        this_object(nullptr),
+        frame_id(frame_id_in) {}
 
   // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
   // annotalysis.
@@ -2450,7 +2459,9 @@
  public:
   FindFrameVisitor(Thread* thread, Context* context, JDWP::FrameId frame_id)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(thread, context), frame_id_(frame_id), error_(JDWP::ERR_INVALID_FRAMEID) {}
+      : StackVisitor(thread, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+        frame_id_(frame_id),
+        error_(JDWP::ERR_INVALID_FRAMEID) {}
 
   // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
   // annotalysis.
@@ -2834,7 +2845,7 @@
  public:
   CatchLocationFinder(Thread* self, const Handle<mirror::Throwable>& exception, Context* context)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-    : StackVisitor(self, context),
+    : StackVisitor(self, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
       self_(self),
       exception_(exception),
       handle_scope_(self),
@@ -2918,10 +2929,11 @@
   if (!IsDebuggerActive()) {
     return;
   }
-  StackHandleScope<1> handle_scope(Thread::Current());
+  Thread* const self = Thread::Current();
+  StackHandleScope<1> handle_scope(self);
   Handle<mirror::Throwable> h_exception(handle_scope.NewHandle(exception_object));
   std::unique_ptr<Context> context(Context::Create());
-  CatchLocationFinder clf(Thread::Current(), h_exception, context.get());
+  CatchLocationFinder clf(self, h_exception, context.get());
   clf.WalkStack(/* include_transitions */ false);
   JDWP::EventLocation exception_throw_location;
   SetEventLocation(&exception_throw_location, clf.GetThrowMethod(), clf.GetThrowDexPc());
@@ -3582,8 +3594,10 @@
   // is for step-out.
   struct SingleStepStackVisitor : public StackVisitor {
     explicit SingleStepStackVisitor(Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-        : StackVisitor(thread, nullptr), stack_depth(0), method(nullptr), line_number(-1) {
-    }
+        : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+          stack_depth(0),
+          method(nullptr),
+          line_number(-1) {}
 
     // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
     // annotalysis.
@@ -3968,7 +3982,7 @@
   Handle<mirror::Object> object_result = hs.NewHandle(is_object_result ? result.GetL() : nullptr);
   Handle<mirror::Throwable> exception = hs.NewHandle(soa.Self()->GetException());
   soa.Self()->ClearException();
-  pReq->exception = gRegistry->Add(exception.Get());
+  pReq->exception = gRegistry->Add(exception);
   if (pReq->exception != 0) {
     VLOG(jdwp) << "  JDWP invocation returning with exception=" << exception.Get()
                << " " << exception->Dump();
@@ -4696,7 +4710,9 @@
 struct AllocRecordStackVisitor : public StackVisitor {
   AllocRecordStackVisitor(Thread* thread, AllocRecord* record_in)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(thread, nullptr), record(record_in), depth(0) {}
+      : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+        record(record_in),
+        depth(0) {}
 
   // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
   // annotalysis.
diff --git a/runtime/debugger.h b/runtime/debugger.h
index 789a0a4..811d345 100644
--- a/runtime/debugger.h
+++ b/runtime/debugger.h
@@ -109,8 +109,8 @@
     return stack_depth_;
   }
 
-  mirror::ArtMethod* GetMethod() const {
-    return method_;
+  mirror::ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return method_.Read();
   }
 
   const std::set<uint32_t>& GetDexPcs() const {
@@ -138,7 +138,7 @@
   // set of DEX pcs associated to the source line number where the suspension occurred.
   // This is used to support SD_INTO and SD_OVER single-step depths so we detect when a single-step
   // causes the execution of an instruction in a different method or at a different line number.
-  mirror::ArtMethod* method_;
+  GcRoot<mirror::ArtMethod> method_;
   std::set<uint32_t> dex_pcs_;
 
   DISALLOW_COPY_AND_ASSIGN(SingleStepControl);
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index e909e64..0c5210d 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -1080,9 +1080,9 @@
 
 // Base on bionic phdr_table_get_load_size
 template <typename ElfTypes>
-size_t ElfFileImpl<ElfTypes>::GetLoadedSize() const {
-  Elf_Addr min_vaddr = 0xFFFFFFFFu;
-  Elf_Addr max_vaddr = 0x00000000u;
+bool ElfFileImpl<ElfTypes>::GetLoadedSize(size_t* size, std::string* error_msg) const {
+  Elf_Addr min_vaddr = static_cast<Elf_Addr>(-1);
+  Elf_Addr max_vaddr = 0u;
   for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
     Elf_Phdr* program_header = GetProgramHeader(i);
     if (program_header->p_type != PT_LOAD) {
@@ -1093,6 +1093,15 @@
        min_vaddr = begin_vaddr;
     }
     Elf_Addr end_vaddr = program_header->p_vaddr + program_header->p_memsz;
+    if (UNLIKELY(begin_vaddr > end_vaddr)) {
+      std::ostringstream oss;
+      oss << "Program header #" << i << " has overflow in p_vaddr+p_memsz: 0x" << std::hex
+          << program_header->p_vaddr << "+0x" << program_header->p_memsz << "=0x" << end_vaddr
+          << " in ELF file \"" << file_->GetPath() << "\"";
+      *error_msg = oss.str();
+      *size = static_cast<size_t>(-1);
+      return false;
+    }
     if (end_vaddr > max_vaddr) {
       max_vaddr = end_vaddr;
     }
@@ -1100,8 +1109,18 @@
   min_vaddr = RoundDown(min_vaddr, kPageSize);
   max_vaddr = RoundUp(max_vaddr, kPageSize);
   CHECK_LT(min_vaddr, max_vaddr) << file_->GetPath();
-  size_t loaded_size = max_vaddr - min_vaddr;
-  return loaded_size;
+  Elf_Addr loaded_size = max_vaddr - min_vaddr;
+  // Check that the loaded_size fits in size_t.
+  if (UNLIKELY(loaded_size > std::numeric_limits<size_t>::max())) {
+    std::ostringstream oss;
+    oss << "Loaded size is 0x" << std::hex << loaded_size << " but maximum size_t is 0x"
+        << std::numeric_limits<size_t>::max() << " for ELF file \"" << file_->GetPath() << "\"";
+    *error_msg = oss.str();
+    *size = static_cast<size_t>(-1);
+    return false;
+  }
+  *size = loaded_size;
+  return true;
 }
 
 template <typename ElfTypes>
@@ -1164,9 +1183,14 @@
       }
       std::string reservation_name("ElfFile reservation for ");
       reservation_name += file_->GetPath();
+      size_t loaded_size;
+      if (!GetLoadedSize(&loaded_size, error_msg)) {
+        DCHECK(!error_msg->empty());
+        return false;
+      }
       std::unique_ptr<MemMap> reserve(MemMap::MapAnonymous(reservation_name.c_str(),
                                                            reserve_base_override,
-                                                           GetLoadedSize(), PROT_NONE, false, false,
+                                                           loaded_size, PROT_NONE, false, false,
                                                            error_msg));
       if (reserve.get() == nullptr) {
         *error_msg = StringPrintf("Failed to allocate %s: %s",
@@ -1915,8 +1939,8 @@
   DELEGATE_TO_IMPL(FindSymbolAddress, section_type, symbol_name, build_map);
 }
 
-size_t ElfFile::GetLoadedSize() const {
-  DELEGATE_TO_IMPL(GetLoadedSize);
+bool ElfFile::GetLoadedSize(size_t* size, std::string* error_msg) const {
+  DELEGATE_TO_IMPL(GetLoadedSize, size, error_msg);
 }
 
 bool ElfFile::Strip(File* file, std::string* error_msg) {
diff --git a/runtime/elf_file.h b/runtime/elf_file.h
index fe6896d..48cb4b8 100644
--- a/runtime/elf_file.h
+++ b/runtime/elf_file.h
@@ -66,7 +66,7 @@
                              const std::string& symbol_name,
                              bool build_map);
 
-  size_t GetLoadedSize() const;
+  bool GetLoadedSize(size_t* size, std::string* error_msg) const;
 
   // Strip an ELF file of unneeded debugging information.
   // Returns true on success, false on failure.
diff --git a/runtime/elf_file_impl.h b/runtime/elf_file_impl.h
index 80950c6..3ad096f 100644
--- a/runtime/elf_file_impl.h
+++ b/runtime/elf_file_impl.h
@@ -106,8 +106,8 @@
   Elf_Word GetRelaNum(Elf_Shdr&) const;
   Elf_Rela& GetRela(Elf_Shdr&, Elf_Word) const;
 
-  // Returns the expected size when the file is loaded at runtime
-  size_t GetLoadedSize() const;
+  // Retrieves the expected size when the file is loaded at runtime. Returns true if successful.
+  bool GetLoadedSize(size_t* size, std::string* error_msg) const;
 
   // Load segments into memory based on PT_LOAD program headers.
   // executable is true at run time, false at compile time.
diff --git a/runtime/entrypoints/quick/quick_entrypoints.h b/runtime/entrypoints/quick/quick_entrypoints.h
index db8c0e3..b72ce34 100644
--- a/runtime/entrypoints/quick/quick_entrypoints.h
+++ b/runtime/entrypoints/quick/quick_entrypoints.h
@@ -32,6 +32,8 @@
 class ArtMethod;
 class Class;
 class Object;
+template<class MirrorType>
+class CompressedReference;
 }  // namespace mirror
 
 class Thread;
@@ -65,6 +67,10 @@
                                                              jobject locked, Thread* self)
     NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
 
+extern void ReadBarrierJni(mirror::CompressedReference<mirror::Object>* handle_on_stack,
+                           Thread* self)
+    NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_ENTRYPOINTS_QUICK_QUICK_ENTRYPOINTS_H_
diff --git a/runtime/entrypoints/quick/quick_entrypoints_list.h b/runtime/entrypoints/quick/quick_entrypoints_list.h
index 035f57a..0aca58f 100644
--- a/runtime/entrypoints/quick/quick_entrypoints_list.h
+++ b/runtime/entrypoints/quick/quick_entrypoints_list.h
@@ -143,7 +143,9 @@
   V(NewStringFromCodePoints, void) \
   V(NewStringFromString, void) \
   V(NewStringFromStringBuffer, void) \
-  V(NewStringFromStringBuilder, void)
+  V(NewStringFromStringBuilder, void) \
+\
+  V(ReadBarrierJni, void, mirror::CompressedReference<mirror::Object>*, Thread*)
 
 #endif  // ART_RUNTIME_ENTRYPOINTS_QUICK_QUICK_ENTRYPOINTS_LIST_H_
 #undef ART_RUNTIME_ENTRYPOINTS_QUICK_QUICK_ENTRYPOINTS_LIST_H_   // #define is only for lint.
diff --git a/runtime/entrypoints/quick/quick_jni_entrypoints.cc b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
index e478d2a..51817a2 100644
--- a/runtime/entrypoints/quick/quick_jni_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
@@ -22,6 +22,13 @@
 
 namespace art {
 
+extern void ReadBarrierJni(mirror::CompressedReference<mirror::Object>* handle_on_stack,
+                           Thread* self ATTRIBUTE_UNUSED) {
+  // Call the read barrier and update the handle.
+  mirror::Object* to_ref = ReadBarrier::BarrierForRoot(handle_on_stack);
+  handle_on_stack->Assign(to_ref);
+}
+
 // Called on entry to JNI, transition out of Runnable and release share of mutator_lock_.
 extern uint32_t JniMethodStart(Thread* self) {
   JNIEnvExt* env = self->GetJniEnv();
diff --git a/runtime/entrypoints_order_test.cc b/runtime/entrypoints_order_test.cc
index 1fb45f4..482f656 100644
--- a/runtime/entrypoints_order_test.cc
+++ b/runtime/entrypoints_order_test.cc
@@ -305,8 +305,10 @@
                          sizeof(void*));
     EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pNewStringFromStringBuffer, pNewStringFromStringBuilder,
                          sizeof(void*));
+    EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pNewStringFromStringBuilder, pReadBarrierJni,
+                         sizeof(void*));
 
-    CHECKED(OFFSETOF_MEMBER(QuickEntryPoints, pNewStringFromStringBuilder)
+    CHECKED(OFFSETOF_MEMBER(QuickEntryPoints, pReadBarrierJni)
             + sizeof(void*) == sizeof(QuickEntryPoints), QuickEntryPoints_all);
   }
 };
diff --git a/runtime/gc/accounting/heap_bitmap.h b/runtime/gc/accounting/heap_bitmap.h
index 245e074..1648aef 100644
--- a/runtime/gc/accounting/heap_bitmap.h
+++ b/runtime/gc/accounting/heap_bitmap.h
@@ -39,9 +39,11 @@
   void Clear(const mirror::Object* obj) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
   template<typename LargeObjectSetVisitor>
   bool Set(const mirror::Object* obj, const LargeObjectSetVisitor& visitor)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
       EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) ALWAYS_INLINE;
   template<typename LargeObjectSetVisitor>
   bool AtomicTestAndSet(const mirror::Object* obj, const LargeObjectSetVisitor& visitor)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
       EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) ALWAYS_INLINE;
   ContinuousSpaceBitmap* GetContinuousSpaceBitmap(const mirror::Object* obj) const;
   LargeObjectBitmap* GetLargeObjectBitmap(const mirror::Object* obj) const;
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index 55a8411..53e56da 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -368,10 +368,13 @@
 
 class MarkSweepMarkObjectSlowPath {
  public:
-  explicit MarkSweepMarkObjectSlowPath(MarkSweep* mark_sweep) : mark_sweep_(mark_sweep) {
+  explicit MarkSweepMarkObjectSlowPath(MarkSweep* mark_sweep, Object* holder = nullptr,
+                                       MemberOffset offset = MemberOffset(0))
+      : mark_sweep_(mark_sweep), holder_(holder), offset_(offset) {
   }
 
-  void operator()(const Object* obj) const ALWAYS_INLINE {
+  void operator()(const Object* obj) const ALWAYS_INLINE
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (kProfileLargeObjects) {
       // TODO: Differentiate between marking and testing somehow.
       ++mark_sweep_->large_object_test_;
@@ -384,6 +387,13 @@
       LOG(INTERNAL_FATAL) << "Tried to mark " << obj << " not contained by any spaces";
       LOG(INTERNAL_FATAL) << "Attempting see if it's a bad root";
       mark_sweep_->VerifyRoots();
+      if (holder_ != nullptr) {
+        ArtField* field = holder_->FindFieldByOffset(offset_);
+        LOG(INTERNAL_FATAL) << "Field info: holder=" << holder_
+                            << " holder_type=" << PrettyTypeOf(holder_)
+                            << " offset=" << offset_.Uint32Value()
+                            << " field=" << (field != nullptr ? field->GetName() : "nullptr");
+      }
       PrintFileToLog("/proc/self/maps", LogSeverity::INTERNAL_FATAL);
       MemMap::DumpMaps(LOG(INTERNAL_FATAL), true);
       LOG(FATAL) << "Can't mark invalid object";
@@ -392,9 +402,11 @@
 
  private:
   MarkSweep* const mark_sweep_;
+  mirror::Object* const holder_;
+  MemberOffset offset_;
 };
 
-inline void MarkSweep::MarkObjectNonNull(Object* obj) {
+inline void MarkSweep::MarkObjectNonNull(Object* obj, Object* holder, MemberOffset offset) {
   DCHECK(obj != nullptr);
   if (kUseBakerOrBrooksReadBarrier) {
     // Verify all the objects have the correct pointer installed.
@@ -416,7 +428,7 @@
     if (kCountMarkedObjects) {
       ++mark_slowpath_count_;
     }
-    MarkSweepMarkObjectSlowPath visitor(this);
+    MarkSweepMarkObjectSlowPath visitor(this, holder, offset);
     // TODO: We already know that the object is not in the current_space_bitmap_ but MarkBitmap::Set
     // will check again.
     if (!mark_bitmap_->Set(obj, visitor)) {
@@ -456,9 +468,9 @@
 }
 
 // Used to mark objects when processing the mark stack. If an object is null, it is not marked.
-inline void MarkSweep::MarkObject(Object* obj) {
+inline void MarkSweep::MarkObject(Object* obj, Object* holder, MemberOffset offset) {
   if (obj != nullptr) {
-    MarkObjectNonNull(obj);
+    MarkObjectNonNull(obj, holder, offset);
   } else if (kCountMarkedObjects) {
     ++mark_null_count_;
   }
@@ -1209,7 +1221,7 @@
       Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
       Locks::heap_bitmap_lock_->AssertExclusiveHeld(Thread::Current());
     }
-    mark_sweep_->MarkObject(obj->GetFieldObject<mirror::Object>(offset));
+    mark_sweep_->MarkObject(obj->GetFieldObject<mirror::Object>(offset), obj, offset);
   }
 
  private:
diff --git a/runtime/gc/collector/mark_sweep.h b/runtime/gc/collector/mark_sweep.h
index 7e1af7b..d29d87a 100644
--- a/runtime/gc/collector/mark_sweep.h
+++ b/runtime/gc/collector/mark_sweep.h
@@ -199,7 +199,8 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Marks an object.
-  void MarkObject(mirror::Object* obj)
+  void MarkObject(mirror::Object* obj, mirror::Object* holder = nullptr,
+                  MemberOffset offset = MemberOffset(0))
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
       EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
 
@@ -222,7 +223,8 @@
   static void VerifyImageRootVisitor(mirror::Object* root, void* arg)
       SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
 
-  void MarkObjectNonNull(mirror::Object* obj)
+  void MarkObjectNonNull(mirror::Object* obj, mirror::Object* holder = nullptr,
+                         MemberOffset offset = MemberOffset(0))
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
       EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
 
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 4129d75..11a0e3c 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -1612,10 +1612,19 @@
 }
 
 size_t Heap::GetObjectsAllocated() const {
+  Thread* self = Thread::Current();
+  ScopedThreadStateChange tsc(self, kWaitingForGetObjectsAllocated);
+  auto* tl = Runtime::Current()->GetThreadList();
+  // Need SuspendAll here to prevent lock violation if RosAlloc does it during InspectAll.
+  tl->SuspendAll(__FUNCTION__);
   size_t total = 0;
-  for (space::AllocSpace* space : alloc_spaces_) {
-    total += space->GetObjectsAllocated();
+  {
+    ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
+    for (space::AllocSpace* space : alloc_spaces_) {
+      total += space->GetObjectsAllocated();
+    }
   }
+  tl->ResumeAll();
   return total;
 }
 
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index d0eb083..efead51 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -981,7 +981,11 @@
     // ClassObjects have their static fields appended, so aren't all the same size.
     // But they're at least this size.
     __ AddU4(sizeof(mirror::Class));  // instance size
-  } else if (klass->IsArrayClass() || klass->IsStringClass() || klass->IsPrimitive()) {
+  } else if (klass->IsStringClass()) {
+    // Strings are variable length with character data at the end like arrays.
+    // This outputs the size of an empty string.
+    __ AddU4(sizeof(mirror::String));
+  } else if (klass->IsArrayClass() || klass->IsPrimitive()) {
     __ AddU4(0);
   } else {
     __ AddU4(klass->GetObjectSize());  // instance size
@@ -1146,13 +1150,20 @@
   // Output native value character array for strings.
   if (orig_klass->IsStringClass()) {
     mirror::String* s = obj->AsString();
-    __ AddObjectId(reinterpret_cast<mirror::Object*>(s->GetValue()));
+    mirror::Object* value;
+    if (s->GetLength() == 0) {
+      // If string is empty, use an object-aligned address within the string for the value.
+      value = reinterpret_cast<mirror::Object*>(reinterpret_cast<uintptr_t>(s) + kObjectAlignment);
+    } else {
+      value = reinterpret_cast<mirror::Object*>(s->GetValue());
+    }
+    __ AddObjectId(value);
 
     // Patch the instance field length.
     __ UpdateU4(size_patch_offset, output_->Length() - (size_patch_offset + 4));
 
     __ AddU1(HPROF_PRIMITIVE_ARRAY_DUMP);
-    __ AddObjectId(reinterpret_cast<mirror::Object*>(s->GetValue()));
+    __ AddObjectId(value);
     __ AddU4(StackTraceSerialNumber(obj));
     __ AddU4(s->GetLength());
     __ AddU1(hprof_basic_char);
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index f810bc8..98e6200 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -44,6 +44,11 @@
 
 constexpr bool kVerboseInstrumentation = false;
 
+// Instrumentation works on non-inlined frames by updating returned PCs
+// of compiled frames.
+static constexpr StackVisitor::StackWalkKind kInstrumentationStackWalk =
+    StackVisitor::StackWalkKind::kSkipInlinedFrames;
+
 static bool InstallStubsClassVisitor(mirror::Class* klass, void* arg)
     EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Instrumentation* instrumentation = reinterpret_cast<Instrumentation*>(arg);
@@ -162,7 +167,7 @@
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   struct InstallStackVisitor FINAL : public StackVisitor {
     InstallStackVisitor(Thread* thread_in, Context* context, uintptr_t instrumentation_exit_pc)
-        : StackVisitor(thread_in, context),
+        : StackVisitor(thread_in, context, kInstrumentationStackWalk),
           instrumentation_stack_(thread_in->GetInstrumentationStack()),
           instrumentation_exit_pc_(instrumentation_exit_pc),
           reached_existing_instrumentation_frames_(false), instrumentation_stack_depth_(0),
@@ -303,7 +308,8 @@
   struct RestoreStackVisitor FINAL : public StackVisitor {
     RestoreStackVisitor(Thread* thread_in, uintptr_t instrumentation_exit_pc,
                         Instrumentation* instrumentation)
-        : StackVisitor(thread_in, nullptr), thread_(thread_in),
+        : StackVisitor(thread_in, nullptr, kInstrumentationStackWalk),
+          thread_(thread_in),
           instrumentation_exit_pc_(instrumentation_exit_pc),
           instrumentation_(instrumentation),
           instrumentation_stack_(thread_in->GetInstrumentationStack()),
@@ -964,7 +970,7 @@
 static void CheckStackDepth(Thread* self, const InstrumentationStackFrame& instrumentation_frame,
                             int delta)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  size_t frame_id = StackVisitor::ComputeNumFrames(self) + delta;
+  size_t frame_id = StackVisitor::ComputeNumFrames(self, kInstrumentationStackWalk) + delta;
   if (frame_id != instrumentation_frame.frame_id_) {
     LOG(ERROR) << "Expected frame_id=" << frame_id << " but found "
         << instrumentation_frame.frame_id_;
@@ -977,7 +983,7 @@
                                                     mirror::ArtMethod* method,
                                                     uintptr_t lr, bool interpreter_entry) {
   // We have a callee-save frame meaning this value is guaranteed to never be 0.
-  size_t frame_id = StackVisitor::ComputeNumFrames(self);
+  size_t frame_id = StackVisitor::ComputeNumFrames(self, kInstrumentationStackWalk);
   std::deque<instrumentation::InstrumentationStackFrame>* stack = self->GetInstrumentationStack();
   if (kVerboseInstrumentation) {
     LOG(INFO) << "Entering " << PrettyMethod(method) << " from PC " << reinterpret_cast<void*>(lr);
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index ae67efb..59d3008 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -616,16 +616,17 @@
       uint16_t regList = inst->Fetch16(2);
       uint16_t count = num_ins;
       size_t arg_index = 0;
-      if (string_init) {
-        // Skip the referrer for the new static StringFactory call.
-        regList >>= 4;
-        ++arg_index;
-      }
       if (count == 5) {
         AssignRegister(new_shadow_frame, shadow_frame, first_dest_reg + 4U,
                        (inst_data >> 8) & 0x0f);
         --count;
-       }
+      }
+      if (string_init) {
+        // Skip the referrer for the new static StringFactory call.
+        regList >>= 4;
+        ++first_dest_reg;
+        --count;
+      }
       for (; arg_index < count; ++arg_index, regList >>= 4) {
         AssignRegister(new_shadow_frame, shadow_frame, first_dest_reg + arg_index, regList & 0x0f);
       }
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index f30c93a..317106b 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -755,6 +755,114 @@
   result->SetL(h_obj.Get());
 }
 
+// This allows reading the new style of String objects during compilation.
+static void UnstartedStringGetCharsNoCheck(
+    Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  jint start = shadow_frame->GetVReg(arg_offset + 1);
+  jint end = shadow_frame->GetVReg(arg_offset + 2);
+  jint index = shadow_frame->GetVReg(arg_offset + 4);
+  mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString();
+  if (string == nullptr) {
+    AbortTransactionOrFail(self, "String.getCharsNoCheck with null object");
+    return;
+  }
+  DCHECK_GE(start, 0);
+  DCHECK_GE(end, string->GetLength());
+  StackHandleScope<1> hs(self);
+  Handle<mirror::CharArray> h_char_array(hs.NewHandle(shadow_frame->GetVRegReference(arg_offset + 3)->AsCharArray()));
+  DCHECK_LE(index, h_char_array->GetLength());
+  DCHECK_LE(end - start, h_char_array->GetLength() - index);
+  string->GetChars(start, end, h_char_array, index);
+}
+
+// This allows reading chars from the new style of String objects during compilation.
+static void UnstartedStringCharAt(
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  jint index = shadow_frame->GetVReg(arg_offset + 1);
+  mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString();
+  if (string == nullptr) {
+    AbortTransactionOrFail(self, "String.charAt with null object");
+    return;
+  }
+  result->SetC(string->CharAt(index));
+}
+
+// This allows setting chars from the new style of String objects during compilation.
+static void UnstartedStringSetCharAt(
+    Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  jint index = shadow_frame->GetVReg(arg_offset + 1);
+  jchar c = shadow_frame->GetVReg(arg_offset + 2);
+  mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString();
+  if (string == nullptr) {
+    AbortTransactionOrFail(self, "String.setCharAt with null object");
+    return;
+  }
+  string->SetCharAt(index, c);
+}
+
+// This allows creating the new style of String objects during compilation.
+static void UnstartedStringFactoryNewStringFromChars(
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  jint offset = shadow_frame->GetVReg(arg_offset);
+  jint char_count = shadow_frame->GetVReg(arg_offset + 1);
+  DCHECK_GE(char_count, 0);
+  StackHandleScope<1> hs(self);
+  Handle<mirror::CharArray> h_char_array(hs.NewHandle(shadow_frame->GetVRegReference(arg_offset + 2)->AsCharArray()));
+  Runtime* runtime = Runtime::Current();
+  gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
+  result->SetL(mirror::String::AllocFromCharArray<true>(self, char_count, h_char_array, offset, allocator));
+}
+
+// This allows creating the new style of String objects during compilation.
+static void UnstartedStringFactoryNewStringFromString(
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::String* to_copy = shadow_frame->GetVRegReference(arg_offset)->AsString();
+  if (to_copy == nullptr) {
+    AbortTransactionOrFail(self, "StringFactory.newStringFromString with null object");
+    return;
+  }
+  StackHandleScope<1> hs(self);
+  Handle<mirror::String> h_string(hs.NewHandle(to_copy));
+  Runtime* runtime = Runtime::Current();
+  gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
+  result->SetL(mirror::String::AllocFromString<true>(self, h_string->GetLength(), h_string, 0,
+                                                     allocator));
+}
+
+// This allows creating the new style of String objects during compilation.
+static void UnstartedStringFastSubstring(
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  jint start = shadow_frame->GetVReg(arg_offset + 1);
+  jint length = shadow_frame->GetVReg(arg_offset + 2);
+  DCHECK_GE(start, 0);
+  DCHECK_GE(length, 0);
+  StackHandleScope<1> hs(self);
+  Handle<mirror::String> h_string(hs.NewHandle(shadow_frame->GetVRegReference(arg_offset)->AsString()));
+  DCHECK_LE(start, h_string->GetLength());
+  DCHECK_LE(start + length, h_string->GetLength());
+  Runtime* runtime = Runtime::Current();
+  gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
+  result->SetL(mirror::String::AllocFromString<true>(self, length, h_string, start, allocator));
+}
+
+// This allows getting the char array for new style of String objects during compilation.
+static void UnstartedStringToCharArray(
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString();
+  if (string == nullptr) {
+    AbortTransactionOrFail(self, "String.charAt with null object");
+    return;
+  }
+  result->SetL(string->ToCharArray(self));
+}
+
 static void UnstartedJNIVMRuntimeNewUnpaddedArray(Thread* self,
                                                   mirror::ArtMethod* method ATTRIBUTE_UNUSED,
                                                   mirror::Object* receiver ATTRIBUTE_UNUSED,
@@ -1079,6 +1187,20 @@
           &UnstartedMemoryPeekArrayEntry },
       { "java.io.Reader java.security.Security.getSecurityPropertiesReader()",
           &UnstartedSecurityGetSecurityPropertiesReader },
+      { "void java.lang.String.getCharsNoCheck(int, int, char[], int)",
+          &UnstartedStringGetCharsNoCheck },
+      { "char java.lang.String.charAt(int)",
+          &UnstartedStringCharAt },
+      { "void java.lang.String.setCharAt(int, char)",
+          &UnstartedStringSetCharAt },
+      { "java.lang.String java.lang.StringFactory.newStringFromChars(int, int, char[])",
+          &UnstartedStringFactoryNewStringFromChars },
+      { "java.lang.String java.lang.StringFactory.newStringFromString(java.lang.String)",
+          &UnstartedStringFactoryNewStringFromString },
+      { "java.lang.String java.lang.String.fastSubstring(int, int)",
+          &UnstartedStringFastSubstring },
+      { "char[] java.lang.String.toCharArray()",
+          &UnstartedStringToCharArray },
   };
 
   for (auto& def : defs) {
@@ -1162,6 +1284,8 @@
   std::string name(PrettyMethod(shadow_frame->GetMethod()));
   const auto& iter = invoke_handlers_.find(name);
   if (iter != invoke_handlers_.end()) {
+    // Clear out the result in case it's not zeroed out.
+    result->SetL(0);
     (*iter->second)(self, shadow_frame, result, arg_offset);
   } else {
     // Not special, continue with regular interpreter execution.
@@ -1175,6 +1299,8 @@
   std::string name(PrettyMethod(method));
   const auto& iter = jni_handlers_.find(name);
   if (iter != jni_handlers_.end()) {
+    // Clear out the result in case it's not zeroed out.
+    result->SetL(0);
     (*iter->second)(self, method, receiver, args, result);
   } else if (Runtime::Current()->IsActiveTransaction()) {
     AbortTransactionF(self, "Attempt to invoke native method in non-started runtime: %s",
diff --git a/runtime/jdwp/jdwp_event.cc b/runtime/jdwp/jdwp_event.cc
index ab3f2e4..ff75268 100644
--- a/runtime/jdwp/jdwp_event.cc
+++ b/runtime/jdwp/jdwp_event.cc
@@ -32,6 +32,8 @@
 #include "scoped_thread_state_change.h"
 #include "thread-inl.h"
 
+#include "handle_scope-inl.h"
+
 /*
 General notes:
 
@@ -108,20 +110,32 @@
  * Stuff to compare against when deciding if a mod matches.  Only the
  * values for mods valid for the event being evaluated will be filled in.
  * The rest will be zeroed.
+ * Must be allocated on the stack only. This is enforced by removing the
+ * operator new.
  */
 struct ModBasket {
-  ModBasket() : pLoc(nullptr), thread(nullptr), locationClass(nullptr), exceptionClass(nullptr),
-                caught(false), field(nullptr), thisPtr(nullptr) { }
+  explicit ModBasket(Thread* self)
+    : hs(self), pLoc(nullptr), thread(self),
+      locationClass(hs.NewHandle<mirror::Class>(nullptr)),
+      exceptionClass(hs.NewHandle<mirror::Class>(nullptr)),
+      caught(false),
+      field(nullptr),
+      thisPtr(hs.NewHandle<mirror::Object>(nullptr)) { }
 
-  const EventLocation*  pLoc;             /* LocationOnly */
-  std::string           className;        /* ClassMatch/ClassExclude */
-  Thread*               thread;           /* ThreadOnly */
-  mirror::Class*        locationClass;    /* ClassOnly */
-  mirror::Class*        exceptionClass;   /* ExceptionOnly */
-  bool                  caught;           /* ExceptionOnly */
-  ArtField*             field;            /* FieldOnly */
-  mirror::Object*       thisPtr;          /* InstanceOnly */
+  StackHandleScope<3> hs;
+  const EventLocation*            pLoc;             /* LocationOnly */
+  std::string                     className;        /* ClassMatch/ClassExclude */
+  Thread* const                   thread;           /* ThreadOnly */
+  MutableHandle<mirror::Class>    locationClass;    /* ClassOnly */
+  MutableHandle<mirror::Class>    exceptionClass;   /* ExceptionOnly */
+  bool                            caught;           /* ExceptionOnly */
+  ArtField*                       field;            /* FieldOnly */
+  MutableHandle<mirror::Object>   thisPtr;          /* InstanceOnly */
   /* nothing for StepOnly -- handled differently */
+
+ private:
+  DISALLOW_ALLOCATION();  // forbids allocation on the heap.
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ModBasket);
 };
 
 static bool NeedsFullDeoptimization(JdwpEventKind eventKind) {
@@ -457,7 +471,7 @@
       }
       break;
     case MK_CLASS_ONLY:
-      if (!Dbg::MatchType(basket.locationClass, pMod->classOnly.refTypeId)) {
+      if (!Dbg::MatchType(basket.locationClass.Get(), pMod->classOnly.refTypeId)) {
         return false;
       }
       break;
@@ -478,7 +492,7 @@
       break;
     case MK_EXCEPTION_ONLY:
       if (pMod->exceptionOnly.refTypeId != 0 &&
-          !Dbg::MatchType(basket.exceptionClass, pMod->exceptionOnly.refTypeId)) {
+          !Dbg::MatchType(basket.exceptionClass.Get(), pMod->exceptionOnly.refTypeId)) {
         return false;
       }
       if ((basket.caught && !pMod->exceptionOnly.caught) ||
@@ -497,7 +511,7 @@
       }
       break;
     case MK_INSTANCE_ONLY:
-      if (!Dbg::MatchInstance(pMod->instanceOnly.objectId, basket.thisPtr)) {
+      if (!Dbg::MatchInstance(pMod->instanceOnly.objectId, basket.thisPtr.Get())) {
         return false;
       }
       break;
@@ -825,12 +839,11 @@
   DCHECK(pLoc->method != nullptr);
   DCHECK_EQ(pLoc->method->IsStatic(), thisPtr == nullptr);
 
-  ModBasket basket;
+  ModBasket basket(Thread::Current());
   basket.pLoc = pLoc;
-  basket.locationClass = pLoc->method->GetDeclaringClass();
-  basket.thisPtr = thisPtr;
-  basket.thread = Thread::Current();
-  basket.className = Dbg::GetClassName(basket.locationClass);
+  basket.locationClass.Assign(pLoc->method->GetDeclaringClass());
+  basket.thisPtr.Assign(thisPtr);
+  basket.className = Dbg::GetClassName(basket.locationClass.Get());
 
   /*
    * On rare occasions we may need to execute interpreted code in the VM
@@ -924,16 +937,15 @@
   DCHECK_EQ(fieldValue != nullptr, is_modification);
   DCHECK_EQ(field->IsStatic(), this_object == nullptr);
 
-  ModBasket basket;
+  ModBasket basket(Thread::Current());
   basket.pLoc = pLoc;
-  basket.locationClass = pLoc->method->GetDeclaringClass();
-  basket.thisPtr = this_object;
-  basket.thread = Thread::Current();
-  basket.className = Dbg::GetClassName(basket.locationClass);
+  basket.locationClass.Assign(pLoc->method->GetDeclaringClass());
+  basket.thisPtr.Assign(this_object);
+  basket.className = Dbg::GetClassName(basket.locationClass.Get());
   basket.field = field;
 
   if (InvokeInProgress()) {
-    VLOG(jdwp) << "Not posting field event during invoke";
+    VLOG(jdwp) << "Not posting field event during invoke (" << basket.className << ")";
     return;
   }
 
@@ -975,7 +987,7 @@
   uint8_t tag;
   {
     ScopedObjectAccessUnchecked soa(Thread::Current());
-    tag = Dbg::TagFromObject(soa, basket.thisPtr);
+    tag = Dbg::TagFromObject(soa, basket.thisPtr.Get());
   }
 
   for (const JdwpEvent* pEvent : match_list) {
@@ -1028,8 +1040,7 @@
     return;
   }
 
-  ModBasket basket;
-  basket.thread = thread;
+  ModBasket basket(thread);
 
   std::vector<JdwpEvent*> match_list;
   const JdwpEventKind match_kind = (start) ? EK_THREAD_START : EK_THREAD_DEATH;
@@ -1106,18 +1117,15 @@
     VLOG(jdwp) << "Unexpected: exception event with empty throw location";
   }
 
-  ModBasket basket;
+  ModBasket basket(Thread::Current());
   basket.pLoc = pThrowLoc;
   if (pThrowLoc->method != nullptr) {
-    basket.locationClass = pThrowLoc->method->GetDeclaringClass();
-  } else {
-    basket.locationClass = nullptr;
+    basket.locationClass.Assign(pThrowLoc->method->GetDeclaringClass());
   }
-  basket.thread = Thread::Current();
-  basket.className = Dbg::GetClassName(basket.locationClass);
-  basket.exceptionClass = exception_object->GetClass();
+  basket.className = Dbg::GetClassName(basket.locationClass.Get());
+  basket.exceptionClass.Assign(exception_object->GetClass());
   basket.caught = (pCatchLoc->method != 0);
-  basket.thisPtr = thisPtr;
+  basket.thisPtr.Assign(thisPtr);
 
   /* don't try to post an exception caused by the debugger */
   if (InvokeInProgress()) {
@@ -1188,10 +1196,9 @@
 void JdwpState::PostClassPrepare(mirror::Class* klass) {
   DCHECK(klass != nullptr);
 
-  ModBasket basket;
-  basket.locationClass = klass;
-  basket.thread = Thread::Current();
-  basket.className = Dbg::GetClassName(basket.locationClass);
+  ModBasket basket(Thread::Current());
+  basket.locationClass.Assign(klass);
+  basket.className = Dbg::GetClassName(basket.locationClass.Get());
 
   /* suppress class prep caused by debugger */
   if (InvokeInProgress()) {
@@ -1214,7 +1221,7 @@
   // debuggers seem to like that.  There might be some advantage to honesty,
   // since the class may not yet be verified.
   int status = JDWP::CS_VERIFIED | JDWP::CS_PREPARED;
-  JDWP::JdwpTypeTag tag = Dbg::GetTypeTag(basket.locationClass);
+  JDWP::JdwpTypeTag tag = Dbg::GetTypeTag(basket.locationClass.Get());
   std::string temp;
   std::string signature(basket.locationClass->GetDescriptor(&temp));
 
diff --git a/runtime/jdwp/object_registry.cc b/runtime/jdwp/object_registry.cc
index a42a58f..2b28f7d 100644
--- a/runtime/jdwp/object_registry.cc
+++ b/runtime/jdwp/object_registry.cc
@@ -36,17 +36,45 @@
 }
 
 JDWP::RefTypeId ObjectRegistry::AddRefType(mirror::Class* c) {
-  return InternalAdd(c);
+  return Add(c);
+}
+
+JDWP::RefTypeId ObjectRegistry::AddRefType(Handle<mirror::Class> c_h) {
+  return Add(c_h);
 }
 
 JDWP::ObjectId ObjectRegistry::Add(mirror::Object* o) {
-  return InternalAdd(o);
-}
-
-JDWP::ObjectId ObjectRegistry::InternalAdd(mirror::Object* o) {
   if (o == nullptr) {
     return 0;
   }
+  Thread* const self = Thread::Current();
+  StackHandleScope<1> hs(self);
+  return InternalAdd(hs.NewHandle(o));
+}
+
+// Template instantiations must be declared below.
+template<class T>
+JDWP::ObjectId ObjectRegistry::Add(Handle<T> obj_h) {
+  if (obj_h.Get() == nullptr) {
+    return 0;
+  }
+  return InternalAdd(obj_h);
+}
+
+// Explicit template instantiation.
+template
+SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::thread_suspend_count_lock_)
+JDWP::ObjectId ObjectRegistry::Add(Handle<mirror::Object> obj_h);
+
+template
+SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::thread_suspend_count_lock_)
+JDWP::ObjectId ObjectRegistry::Add(Handle<mirror::Throwable> obj_h);
+
+template<class T>
+JDWP::ObjectId ObjectRegistry::InternalAdd(Handle<T> obj_h) {
+  CHECK(obj_h.Get() != nullptr);
 
   Thread* const self = Thread::Current();
   self->AssertNoPendingException();
@@ -55,9 +83,6 @@
   Locks::thread_list_lock_->AssertNotHeld(self);
   Locks::thread_suspend_count_lock_->AssertNotHeld(self);
 
-  StackHandleScope<1> hs(self);
-  Handle<mirror::Object> obj_h(hs.NewHandle(o));
-
   // Call IdentityHashCode here to avoid a lock level violation between lock_ and monitor_lock.
   int32_t identity_hash_code = obj_h->IdentityHashCode();
 
diff --git a/runtime/jdwp/object_registry.h b/runtime/jdwp/object_registry.h
index 27a4e55..4c149cd 100644
--- a/runtime/jdwp/object_registry.h
+++ b/runtime/jdwp/object_registry.h
@@ -23,6 +23,7 @@
 #include <map>
 
 #include "base/casts.h"
+#include "handle.h"
 #include "jdwp/jdwp.h"
 #include "safe_map.h"
 
@@ -65,11 +66,23 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
       LOCKS_EXCLUDED(Locks::thread_list_lock_,
                      Locks::thread_suspend_count_lock_);
+
   JDWP::RefTypeId AddRefType(mirror::Class* c)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
       LOCKS_EXCLUDED(Locks::thread_list_lock_,
                      Locks::thread_suspend_count_lock_);
 
+  template<class T>
+  JDWP::ObjectId Add(Handle<T> obj_h)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      LOCKS_EXCLUDED(Locks::thread_list_lock_,
+                     Locks::thread_suspend_count_lock_);
+
+  JDWP::RefTypeId AddRefType(Handle<mirror::Class> c_h)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      LOCKS_EXCLUDED(Locks::thread_list_lock_,
+                     Locks::thread_suspend_count_lock_);
+
   template<typename T> T Get(JDWP::ObjectId id, JDWP::JdwpError* error)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (id == 0) {
@@ -98,7 +111,8 @@
   jobject GetJObject(JDWP::ObjectId id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
  private:
-  JDWP::ObjectId InternalAdd(mirror::Object* o)
+  template<class T>
+  JDWP::ObjectId InternalAdd(Handle<T> obj_h)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
       LOCKS_EXCLUDED(lock_,
                      Locks::thread_list_lock_,
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 9bb08a2..fd386d7 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -2099,6 +2099,35 @@
         return JNI_ERR;
       }
       bool is_fast = false;
+      // Notes about fast JNI calls:
+      //
+      // On a normal JNI call, the calling thread usually transitions
+      // from the kRunnable state to the kNative state. But if the
+      // called native function needs to access any Java object, it
+      // will have to transition back to the kRunnable state.
+      //
+      // There is a cost to this double transition. For a JNI call
+      // that should be quick, this cost may dominate the call cost.
+      //
+      // On a fast JNI call, the calling thread avoids this double
+      // transition by not transitioning from kRunnable to kNative and
+      // stays in the kRunnable state.
+      //
+      // There are risks to using a fast JNI call because it can delay
+      // a response to a thread suspension request which is typically
+      // used for a GC root scanning, etc. If a fast JNI call takes a
+      // long time, it could cause longer thread suspension latency
+      // and GC pauses.
+      //
+      // Thus, fast JNI should be used with care. It should be used
+      // for a JNI call that takes a short amount of time (eg. no
+      // long-running loop) and does not block (eg. no locks, I/O,
+      // etc.)
+      //
+      // A '!' prefix in the signature in the JNINativeMethod
+      // indicates that it's a fast JNI call and the runtime omits the
+      // thread state transition from kRunnable to kNative at the
+      // entry.
       if (*sig == '!') {
         is_fast = true;
         ++sig;
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index 543cf9b..9518c9d 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -511,7 +511,6 @@
   if (class_linker->IsQuickGenericJniStub(entry_point)) {
     // Generic JNI frame.
     DCHECK(IsNative());
-    StackHandleScope<1> hs(Thread::Current());
     uint32_t handle_refs = GetNumberOfReferenceArgsWithoutReceiver(this) + 1;
     size_t scope_size = HandleScope::SizeOf(handle_refs);
     QuickMethodFrameInfo callee_info = runtime->GetCalleeSaveMethodFrameInfo(Runtime::kRefsAndArgs);
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index 5dac985..f9740bb 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -244,5 +244,10 @@
   UNREACHABLE();
 }
 
+ArtField* Object::FindFieldByOffset(MemberOffset offset) {
+  return IsClass() ? ArtField::FindStaticFieldWithOffset(AsClass(), offset.Uint32Value())
+      : ArtField::FindInstanceFieldWithOffset(GetClass(), offset.Uint32Value());
+}
+
 }  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index f2d879f..5afe99f 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -439,6 +439,8 @@
   void VisitReferences(const Visitor& visitor, const JavaLangRefVisitor& ref_visitor)
       NO_THREAD_SAFETY_ANALYSIS;
 
+  ArtField* FindFieldByOffset(MemberOffset offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   // Used by object_test.
   static void SetHashCodeSeed(uint32_t new_seed);
   // Generate an identity hash code. Public for object test.
diff --git a/runtime/native/dalvik_system_VMStack.cc b/runtime/native/dalvik_system_VMStack.cc
index 17fbc4f..1d7d853 100644
--- a/runtime/native/dalvik_system_VMStack.cc
+++ b/runtime/native/dalvik_system_VMStack.cc
@@ -84,7 +84,8 @@
 static jobject VMStack_getClosestUserClassLoader(JNIEnv* env, jclass) {
   struct ClosestUserClassLoaderVisitor : public StackVisitor {
     explicit ClosestUserClassLoaderVisitor(Thread* thread)
-      : StackVisitor(thread, nullptr), class_loader(nullptr) {}
+      : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+        class_loader(nullptr) {}
 
     bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
       DCHECK(class_loader == nullptr);
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index a779e97..795a0ea 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -252,7 +252,7 @@
     std::string name_str = name_string->ToModifiedUtf8();
     // We may have a pending exception if we failed to resolve.
     if (!soa.Self()->IsExceptionPending()) {
-      soa.Self()->ThrowNewException("Ljava/lang/NoSuchFieldException;", name_str.c_str());
+      ThrowNoSuchFieldException(DecodeClass(soa, javaThis), name_str.c_str());
     }
     return nullptr;
   }
diff --git a/runtime/native/java_lang_Thread.cc b/runtime/native/java_lang_Thread.cc
index be7022e..6569d83 100644
--- a/runtime/native/java_lang_Thread.cc
+++ b/runtime/native/java_lang_Thread.cc
@@ -84,6 +84,7 @@
     case kWaitingInMainDebuggerLoop:      return kJavaWaiting;
     case kWaitingForDebuggerSuspension:   return kJavaWaiting;
     case kWaitingForDeoptimization:       return kJavaWaiting;
+    case kWaitingForGetObjectsAllocated:  return kJavaWaiting;
     case kWaitingForJniOnLoad:            return kJavaWaiting;
     case kWaitingForSignalCatcherOutput:  return kJavaWaiting;
     case kWaitingInMainSignalCatcherLoop: return kJavaWaiting;
diff --git a/runtime/nth_caller_visitor.h b/runtime/nth_caller_visitor.h
index 632ccde..d2d7fa8 100644
--- a/runtime/nth_caller_visitor.h
+++ b/runtime/nth_caller_visitor.h
@@ -27,8 +27,11 @@
 // Walks up the stack 'n' callers, when used with Thread::WalkStack.
 struct NthCallerVisitor : public StackVisitor {
   NthCallerVisitor(Thread* thread, size_t n_in, bool include_runtime_and_upcalls = false)
-      : StackVisitor(thread, nullptr), n(n_in),
-        include_runtime_and_upcalls_(include_runtime_and_upcalls), count(0), caller(nullptr) {}
+      : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+        n(n_in),
+        include_runtime_and_upcalls_(include_runtime_and_upcalls),
+        count(0),
+        caller(nullptr) {}
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     mirror::ArtMethod* m = GetMethod();
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index 2f67263..d07c09c 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -96,9 +96,8 @@
 
 OatFileAssistant::~OatFileAssistant() {
   // Clean up the lock file.
-  if (lock_file_.get() != nullptr) {
-    lock_file_->Erase();
-    TEMP_FAILURE_RETRY(unlink(lock_file_->GetPath().c_str()));
+  if (flock_.HasFile()) {
+    TEMP_FAILURE_RETRY(unlink(flock_.GetFile()->GetPath().c_str()));
   }
 }
 
@@ -121,7 +120,7 @@
 
 bool OatFileAssistant::Lock(std::string* error_msg) {
   CHECK(error_msg != nullptr);
-  CHECK(lock_file_.get() == nullptr) << "OatFileAssistant::Lock already acquired";
+  CHECK(!flock_.HasFile()) << "OatFileAssistant::Lock already acquired";
 
   if (OatFileName() == nullptr) {
     *error_msg = "Failed to determine lock file";
@@ -129,13 +128,7 @@
   }
   std::string lock_file_name = *OatFileName() + ".flock";
 
-  lock_file_.reset(OS::CreateEmptyFile(lock_file_name.c_str()));
-  if (lock_file_.get() == nullptr) {
-    *error_msg = "Failed to create lock file " + lock_file_name;
-    return false;
-  }
-
-  if (!flock_.Init(lock_file_.get(), error_msg)) {
+  if (!flock_.Init(lock_file_name.c_str(), error_msg)) {
     TEMP_FAILURE_RETRY(unlink(lock_file_name.c_str()));
     return false;
   }
@@ -465,7 +458,7 @@
 
   const ImageInfo* image_info = GetImageInfo();
   if (image_info == nullptr) {
-    VLOG(oat) << "No image for to check oat relocation against.";
+    VLOG(oat) << "No image to check oat relocation against.";
     return false;
   }
 
diff --git a/runtime/oat_file_assistant.h b/runtime/oat_file_assistant.h
index 3b2e2c4..4c0b0e2 100644
--- a/runtime/oat_file_assistant.h
+++ b/runtime/oat_file_assistant.h
@@ -353,7 +353,6 @@
   // To implement Lock(), we lock a dummy file where the oat file would go
   // (adding ".flock" to the target file name) and retain the lock for the
   // remaining lifetime of the OatFileAssistant object.
-  std::unique_ptr<File> lock_file_;
   ScopedFlock flock_;
 
   // In a properly constructed OatFileAssistant object, dex_location_ should
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index 3f6b2d2..865fcb0 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -29,6 +29,7 @@
 #include "class_linker-inl.h"
 #include "common_runtime_test.h"
 #include "compiler_callbacks.h"
+#include "gc/space/image_space.h"
 #include "mem_map.h"
 #include "os.h"
 #include "scoped_thread_state_change.h"
@@ -610,10 +611,23 @@
   // Things aren't relocated, so it should fall back to interpreted.
   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
   ASSERT_TRUE(oat_file.get() != nullptr);
+
   EXPECT_FALSE(oat_file->IsExecutable());
   std::vector<std::unique_ptr<const DexFile>> dex_files;
   dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
   EXPECT_EQ(1u, dex_files.size());
+
+  // Add some extra checks to help diagnose apparently flaky test failures.
+  Runtime* runtime = Runtime::Current();
+  const gc::space::ImageSpace* image_space = runtime->GetHeap()->GetImageSpace();
+  ASSERT_TRUE(image_space != nullptr);
+  const ImageHeader& image_header = image_space->GetImageHeader();
+  const OatHeader& oat_header = oat_file->GetOatHeader();
+  EXPECT_FALSE(oat_file->IsPic());
+  EXPECT_EQ(image_header.GetOatChecksum(), oat_header.GetImageFileLocationOatChecksum());
+  EXPECT_NE(reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin()),
+      oat_header.GetImageFileLocationOatDataBegin());
+  EXPECT_NE(image_header.GetPatchDelta(), oat_header.GetImagePatchDelta());
 }
 
 // Case: We have a DEX file and a PIC ODEX file, but no OAT file.
diff --git a/runtime/profiler.cc b/runtime/profiler.cc
index 90a47b3..3b0e6c1 100644
--- a/runtime/profiler.cc
+++ b/runtime/profiler.cc
@@ -58,8 +58,10 @@
   BoundedStackVisitor(std::vector<std::pair<mirror::ArtMethod*, uint32_t>>* stack,
       Thread* thread, uint32_t max_depth)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(thread, nullptr), stack_(stack), max_depth_(max_depth), depth_(0) {
-  }
+      : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+        stack_(stack),
+        max_depth_(max_depth),
+        depth_(0) {}
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     mirror::ArtMethod* m = GetMethod();
@@ -300,7 +302,9 @@
   } while (length > 0);
 
   // Truncate the file to the new length.
-  ftruncate(fd, full_length);
+  if (ftruncate(fd, full_length) == -1) {
+    LOG(ERROR) << "Failed to truncate profile file " << full_name;
+  }
 
   // Now unlock the file, allowing another process in.
   err = flock(fd, LOCK_UN);
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index 9e79bd2..730759a 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -46,7 +46,9 @@
   CatchBlockStackVisitor(Thread* self, Context* context, Handle<mirror::Throwable>* exception,
                          QuickExceptionHandler* exception_handler)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(self, context), self_(self), exception_(exception),
+      : StackVisitor(self, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+        self_(self),
+        exception_(exception),
         exception_handler_(exception_handler) {
   }
 
@@ -160,7 +162,9 @@
  public:
   DeoptimizeStackVisitor(Thread* self, Context* context, QuickExceptionHandler* exception_handler)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(self, context), self_(self), exception_handler_(exception_handler),
+      : StackVisitor(self, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+        self_(self),
+        exception_handler_(exception_handler),
         prev_shadow_frame_(nullptr) {
     CHECK(!self_->HasDeoptimizationShadowFrame());
   }
@@ -338,7 +342,7 @@
  public:
   InstrumentationStackVisitor(Thread* self, size_t frame_depth)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(self, nullptr),
+      : StackVisitor(self, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
         frame_depth_(frame_depth),
         instrumentation_frames_to_pop_(0) {
     CHECK_NE(frame_depth_, kInvalidFrameDepth);
@@ -349,7 +353,12 @@
     if (current_frame_depth < frame_depth_) {
       CHECK(GetMethod() != nullptr);
       if (UNLIKELY(reinterpret_cast<uintptr_t>(GetQuickInstrumentationExitPc()) == GetReturnPc())) {
-        ++instrumentation_frames_to_pop_;
+        if (!IsInInlinedFrame()) {
+          // We do not count inlined frames, because we do not instrument them. The reason we
+          // include them in the stack walking is the check against `frame_depth_`, which is
+          // given to us by a visitor that visits inlined frames.
+          ++instrumentation_frames_to_pop_;
+        }
       }
       return true;
     } else {
diff --git a/runtime/stack.cc b/runtime/stack.cc
index a566886..800acaa 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -85,16 +85,20 @@
   return false;
 }
 
-StackVisitor::StackVisitor(Thread* thread, Context* context)
-    : thread_(thread), cur_shadow_frame_(nullptr),
-      cur_quick_frame_(nullptr), cur_quick_frame_pc_(0), num_frames_(0), cur_depth_(0),
-      context_(context) {
-  DCHECK(thread == Thread::Current() || thread->IsSuspended()) << *thread;
-}
+StackVisitor::StackVisitor(Thread* thread, Context* context, StackWalkKind walk_kind)
+    : StackVisitor(thread, context, walk_kind, 0) {}
 
-StackVisitor::StackVisitor(Thread* thread, Context* context, size_t num_frames)
-    : thread_(thread), cur_shadow_frame_(nullptr),
-      cur_quick_frame_(nullptr), cur_quick_frame_pc_(0), num_frames_(num_frames), cur_depth_(0),
+StackVisitor::StackVisitor(Thread* thread,
+                           Context* context,
+                           StackWalkKind walk_kind,
+                           size_t num_frames)
+    : thread_(thread),
+      walk_kind_(walk_kind),
+      cur_shadow_frame_(nullptr),
+      cur_quick_frame_(nullptr),
+      cur_quick_frame_pc_(0),
+      num_frames_(num_frames),
+      cur_depth_(0),
       context_(context) {
   DCHECK(thread == Thread::Current() || thread->IsSuspended()) << *thread;
 }
@@ -565,10 +569,10 @@
   *reinterpret_cast<uintptr_t*>(pc_addr) = new_ret_pc;
 }
 
-size_t StackVisitor::ComputeNumFrames(Thread* thread) {
+size_t StackVisitor::ComputeNumFrames(Thread* thread, StackWalkKind walk_kind) {
   struct NumFramesVisitor : public StackVisitor {
-    explicit NumFramesVisitor(Thread* thread_in)
-        : StackVisitor(thread_in, nullptr), frames(0) {}
+    NumFramesVisitor(Thread* thread_in, StackWalkKind walk_kind_in)
+        : StackVisitor(thread_in, nullptr, walk_kind_in), frames(0) {}
 
     bool VisitFrame() OVERRIDE {
       frames++;
@@ -577,16 +581,23 @@
 
     size_t frames;
   };
-  NumFramesVisitor visitor(thread);
+  NumFramesVisitor visitor(thread, walk_kind);
   visitor.WalkStack(true);
   return visitor.frames;
 }
 
 bool StackVisitor::GetNextMethodAndDexPc(mirror::ArtMethod** next_method, uint32_t* next_dex_pc) {
   struct HasMoreFramesVisitor : public StackVisitor {
-    explicit HasMoreFramesVisitor(Thread* thread, size_t num_frames, size_t frame_height)
-        : StackVisitor(thread, nullptr, num_frames), frame_height_(frame_height),
-          found_frame_(false), has_more_frames_(false), next_method_(nullptr), next_dex_pc_(0) {
+    HasMoreFramesVisitor(Thread* thread,
+                         StackWalkKind walk_kind,
+                         size_t num_frames,
+                         size_t frame_height)
+        : StackVisitor(thread, nullptr, walk_kind, num_frames),
+          frame_height_(frame_height),
+          found_frame_(false),
+          has_more_frames_(false),
+          next_method_(nullptr),
+          next_dex_pc_(0) {
     }
 
     bool VisitFrame() OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -610,7 +621,7 @@
     mirror::ArtMethod* next_method_;
     uint32_t next_dex_pc_;
   };
-  HasMoreFramesVisitor visitor(thread_, GetNumFrames(), GetFrameHeight());
+  HasMoreFramesVisitor visitor(thread_, walk_kind_, GetNumFrames(), GetFrameHeight());
   visitor.WalkStack(true);
   *next_method = visitor.next_method_;
   *next_dex_pc = visitor.next_dex_pc_;
@@ -620,7 +631,7 @@
 void StackVisitor::DescribeStack(Thread* thread) {
   struct DescribeStackVisitor : public StackVisitor {
     explicit DescribeStackVisitor(Thread* thread_in)
-        : StackVisitor(thread_in, nullptr) {}
+        : StackVisitor(thread_in, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames) {}
 
     bool VisitFrame() OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
       LOG(INFO) << "Frame Id=" << GetFrameId() << " " << DescribeLocation();
diff --git a/runtime/stack.h b/runtime/stack.h
index ab8641b..bf61016 100644
--- a/runtime/stack.h
+++ b/runtime/stack.h
@@ -409,8 +409,17 @@
 };
 
 class StackVisitor {
+ public:
+  // This enum defines a flag to control whether inlined frames are included
+  // when walking the stack.
+  enum class StackWalkKind {
+    kIncludeInlinedFrames,
+    kSkipInlinedFrames,
+  };
+
  protected:
-  StackVisitor(Thread* thread, Context* context) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  StackVisitor(Thread* thread, Context* context, StackWalkKind walk_kind)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
  public:
   virtual ~StackVisitor() {}
@@ -465,7 +474,7 @@
 
   size_t GetNumFrames() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (num_frames_ == 0) {
-      num_frames_ = ComputeNumFrames(thread_);
+      num_frames_ = ComputeNumFrames(thread_, walk_kind_);
     }
     return num_frames_;
   }
@@ -601,6 +610,10 @@
     return sizeof(StackReference<mirror::ArtMethod>) + (out_num * sizeof(uint32_t));
   }
 
+  bool IsInInlinedFrame() const {
+    return false;
+  }
+
   uintptr_t GetCurrentQuickFramePc() const {
     return cur_quick_frame_pc_;
   }
@@ -621,13 +634,14 @@
 
   std::string DescribeLocation() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  static size_t ComputeNumFrames(Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  static size_t ComputeNumFrames(Thread* thread, StackWalkKind walk_kind)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static void DescribeStack(Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
  private:
   // Private constructor known in the case that num_frames_ has already been computed.
-  StackVisitor(Thread* thread, Context* context, size_t num_frames)
+  StackVisitor(Thread* thread, Context* context, StackWalkKind walk_kind, size_t num_frames)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   bool IsAccessibleRegister(uint32_t reg, bool is_float) const {
@@ -690,6 +704,7 @@
   void SanityCheckFrame() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   Thread* const thread_;
+  const StackWalkKind walk_kind_;
   ShadowFrame* cur_shadow_frame_;
   StackReference<mirror::ArtMethod>* cur_quick_frame_;
   uintptr_t cur_quick_frame_pc_;
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 605a1b5..148bb6d 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -940,10 +940,14 @@
 struct StackDumpVisitor : public StackVisitor {
   StackDumpVisitor(std::ostream& os_in, Thread* thread_in, Context* context, bool can_allocate_in)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(thread_in, context), os(os_in), thread(thread_in),
-        can_allocate(can_allocate_in), last_method(nullptr), last_line_number(0),
-        repetition_count(0), frame_count(0) {
-  }
+      : StackVisitor(thread_in, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+        os(os_in),
+        thread(thread_in),
+        can_allocate(can_allocate_in),
+        last_method(nullptr),
+        last_line_number(0),
+        repetition_count(0),
+        frame_count(0) {}
 
   virtual ~StackDumpVisitor() {
     if (frame_count == 0) {
@@ -1528,7 +1532,7 @@
  public:
   explicit CountStackDepthVisitor(Thread* thread)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(thread, nullptr),
+      : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
         depth_(0), skip_depth_(0), skipping_(true) {}
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -1568,8 +1572,12 @@
 class BuildInternalStackTraceVisitor : public StackVisitor {
  public:
   explicit BuildInternalStackTraceVisitor(Thread* self, Thread* thread, int skip_depth)
-      : StackVisitor(thread, nullptr), self_(self),
-        skip_depth_(skip_depth), count_(0), dex_pc_trace_(nullptr), method_trace_(nullptr) {}
+      : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+        self_(self),
+        skip_depth_(skip_depth),
+        count_(0),
+        dex_pc_trace_(nullptr),
+        method_trace_(nullptr) {}
 
   bool Init(int depth)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -2072,6 +2080,7 @@
   QUICK_ENTRY_POINT_INFO(pNewStringFromString)
   QUICK_ENTRY_POINT_INFO(pNewStringFromStringBuffer)
   QUICK_ENTRY_POINT_INFO(pNewStringFromStringBuilder)
+  QUICK_ENTRY_POINT_INFO(pReadBarrierJni)
 #undef QUICK_ENTRY_POINT_INFO
 
   os << offset;
@@ -2111,7 +2120,10 @@
 struct CurrentMethodVisitor FINAL : public StackVisitor {
   CurrentMethodVisitor(Thread* thread, Context* context, bool abort_on_error)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(thread, context), this_object_(nullptr), method_(nullptr), dex_pc_(0),
+      : StackVisitor(thread, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+        this_object_(nullptr),
+        method_(nullptr),
+        dex_pc_(0),
         abort_on_error_(abort_on_error) {}
   bool VisitFrame() OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     mirror::ArtMethod* m = GetMethod();
@@ -2154,7 +2166,10 @@
  public:
   ReferenceMapVisitor(Thread* thread, Context* context, RootVisitor& visitor)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(thread, context), visitor_(visitor) {}
+        // We are visiting the references in compiled frames, so we do not need
+        // to know the inlined frames.
+      : StackVisitor(thread, context, StackVisitor::StackWalkKind::kSkipInlinedFrames),
+        visitor_(visitor) {}
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (false) {
diff --git a/runtime/thread_state.h b/runtime/thread_state.h
index b5479ed..c7ea7f4 100644
--- a/runtime/thread_state.h
+++ b/runtime/thread_state.h
@@ -42,6 +42,7 @@
   kWaitingForDeoptimization,        // WAITING        TS_WAIT      waiting for deoptimization suspend all
   kWaitingForMethodTracingStart,    // WAITING        TS_WAIT      waiting for method tracing to start
   kWaitingForVisitObjects,          // WAITING        TS_WAIT      waiting for visiting objects
+  kWaitingForGetObjectsAllocated,   // WAITING        TS_WAIT      waiting for getting the number of allocated objects
   kStarting,                        // NEW            TS_WAIT      native thread started, not yet ready to run managed code
   kNative,                          // RUNNABLE       TS_RUNNING   running in a JNI native method
   kSuspended,                       // RUNNABLE       TS_RUNNING   suspended by GC or debugger
diff --git a/runtime/trace.cc b/runtime/trace.cc
index 3b8feda..7636792 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -91,8 +91,9 @@
 
 class BuildStackTraceVisitor : public StackVisitor {
  public:
-  explicit BuildStackTraceVisitor(Thread* thread) : StackVisitor(thread, nullptr),
-      method_trace_(Trace::AllocStackTrace()) {}
+  explicit BuildStackTraceVisitor(Thread* thread)
+      : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+        method_trace_(Trace::AllocStackTrace()) {}
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     mirror::ArtMethod* m = GetMethod();
diff --git a/test/046-reflect/src/Main.java b/test/046-reflect/src/Main.java
index 59f7001..0d8e576 100644
--- a/test/046-reflect/src/Main.java
+++ b/test/046-reflect/src/Main.java
@@ -233,6 +233,20 @@
             field.set(instance, null);
 
             /*
+             * Try getDeclaredField on a non-existant field.
+             */
+            try {
+                field = target.getDeclaredField("nonExistant");
+                System.out.println("ERROR: Expected NoSuchFieldException");
+            } catch (NoSuchFieldException nsfe) {
+                String msg = nsfe.getMessage();
+                if (!msg.contains("Target;")) {
+                    System.out.println("  NoSuchFieldException '" + msg +
+                        "' didn't contain class");
+                }
+            }
+
+            /*
              * Do some stuff with long.
              */
             long longVal;
@@ -868,4 +882,4 @@
             System.out.println(e);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/test/082-inline-execute/src/Main.java b/test/082-inline-execute/src/Main.java
index abd6cb8..4dfa73c 100644
--- a/test/082-inline-execute/src/Main.java
+++ b/test/082-inline-execute/src/Main.java
@@ -262,9 +262,80 @@
 
     testIndexOfNull();
 
+    // Same data as above, but stored so it's not a literal in the next test. -2 stands for
+    // indexOf(I) instead of indexOf(II).
+    start--;
+    int[][] searchData = {
+        { 'a', -2, -1 },
+        { 'a', -2, 0 },
+        { 'b', -2, 1 },
+        { 'c', -2, 2 },
+        { 'j', -2, 9 },
+        { 'a', -2, 0 },
+        { 'b', -2, 38 },
+        { 'c', -2, 39 },
+        { 'a', 20, -1 },
+        { 'a', 0, -1 },
+        { 'a', -1, -1 },
+        { '/', ++start, -1 },
+        { 'a', negIndex[0], -1 },
+        { 'a', 0, 0 },
+        { 'a', 1, -1 },
+        { 'a', 1234, -1 },
+        { 'b', 0, 1 },
+        { 'b', 1, 1 },
+        { 'c', 2, 2 },
+        { 'j', 5, 9 },
+        { 'j', 9, 9 },
+        { 'a', 10, 10 },
+        { 'b', 40, -1 },
+    };
+    testStringIndexOfChars(searchData);
+
     testSurrogateIndexOf();
   }
 
+  private static void testStringIndexOfChars(int[][] searchData) {
+    // Use a try-catch to avoid inlining.
+    try {
+      testStringIndexOfCharsImpl(searchData);
+    } catch (Exception e) {
+      System.out.println("Unexpected exception");
+    }
+  }
+
+  private static void testStringIndexOfCharsImpl(int[][] searchData) {
+    String str0 = "";
+    String str1 = "/";
+    String str3 = "abc";
+    String str10 = "abcdefghij";
+    String str40 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabc";
+
+    Assert.assertEquals(str0.indexOf(searchData[0][0]), searchData[0][2]);
+    Assert.assertEquals(str3.indexOf(searchData[1][0]), searchData[1][2]);
+    Assert.assertEquals(str3.indexOf(searchData[2][0]), searchData[2][2]);
+    Assert.assertEquals(str3.indexOf(searchData[3][0]), searchData[3][2]);
+    Assert.assertEquals(str10.indexOf(searchData[4][0]), searchData[4][2]);
+    Assert.assertEquals(str40.indexOf(searchData[5][0]), searchData[5][2]);
+    Assert.assertEquals(str40.indexOf(searchData[6][0]), searchData[6][2]);
+    Assert.assertEquals(str40.indexOf(searchData[7][0]), searchData[7][2]);
+    Assert.assertEquals(str0.indexOf(searchData[8][0], searchData[8][1]), searchData[8][2]);
+    Assert.assertEquals(str0.indexOf(searchData[9][0], searchData[9][1]), searchData[9][2]);
+    Assert.assertEquals(str0.indexOf(searchData[10][0], searchData[10][1]), searchData[10][2]);
+    Assert.assertEquals(str1.indexOf(searchData[11][0], searchData[11][1]), searchData[11][2]);
+    Assert.assertEquals(str1.indexOf(searchData[12][0], searchData[12][1]), searchData[12][2]);
+    Assert.assertEquals(str3.indexOf(searchData[13][0], searchData[13][1]), searchData[13][2]);
+    Assert.assertEquals(str3.indexOf(searchData[14][0], searchData[14][1]), searchData[14][2]);
+    Assert.assertEquals(str3.indexOf(searchData[15][0], searchData[15][1]), searchData[15][2]);
+    Assert.assertEquals(str3.indexOf(searchData[16][0], searchData[16][1]), searchData[16][2]);
+    Assert.assertEquals(str3.indexOf(searchData[17][0], searchData[17][1]), searchData[17][2]);
+    Assert.assertEquals(str3.indexOf(searchData[18][0], searchData[18][1]), searchData[18][2]);
+    Assert.assertEquals(str10.indexOf(searchData[19][0], searchData[19][1]), searchData[19][2]);
+    Assert.assertEquals(str10.indexOf(searchData[20][0], searchData[20][1]), searchData[20][2]);
+    Assert.assertEquals(str40.indexOf(searchData[21][0], searchData[21][1]), searchData[21][2]);
+    Assert.assertEquals(str40.indexOf(searchData[22][0], searchData[22][1]), searchData[22][2]);
+  }
+
   private static void testSurrogateIndexOf() {
     int supplementaryChar = 0x20b9f;
     String surrogatePair = "\ud842\udf9f";
@@ -274,6 +345,9 @@
     Assert.assertEquals(stringWithSurrogates.indexOf(supplementaryChar, 2), "hello ".length());
     Assert.assertEquals(stringWithSurrogates.indexOf(supplementaryChar, 6), 6);
     Assert.assertEquals(stringWithSurrogates.indexOf(supplementaryChar, 7), -1);
+
+    Assert.assertEquals(stringWithSurrogates.indexOf(supplementaryChar - 0x10000), -1);
+    Assert.assertEquals(stringWithSurrogates.indexOf(supplementaryChar | 0x80000000), -1);
   }
 
   private static void testIndexOfNull() {
diff --git a/test/127-secondarydex/expected.txt b/test/127-secondarydex/expected.txt
index 29a1411..1c8defb 100644
--- a/test/127-secondarydex/expected.txt
+++ b/test/127-secondarydex/expected.txt
@@ -1,3 +1,4 @@
 testSlowPathDirectInvoke
 Test
 Got null pointer exception
+Test
diff --git a/test/127-secondarydex/src/Main.java b/test/127-secondarydex/src/Main.java
index c921c5b..0ede8ed 100644
--- a/test/127-secondarydex/src/Main.java
+++ b/test/127-secondarydex/src/Main.java
@@ -24,6 +24,7 @@
 public class Main {
     public static void main(String[] args) {
         testSlowPathDirectInvoke();
+        testString();
     }
 
     public static void testSlowPathDirectInvoke() {
@@ -40,4 +41,11 @@
             System.out.println("Got unexpected exception " + e);
         }
     }
+
+    // For string change, test that String.<init> is compiled properly in
+    // secondary dex. See http://b/20870917
+    public static void testString() {
+        Test t = new Test();
+        System.out.println(t.toString());
+    }
 }
diff --git a/test/127-secondarydex/src/Test.java b/test/127-secondarydex/src/Test.java
index 82cb901..8547e79 100644
--- a/test/127-secondarydex/src/Test.java
+++ b/test/127-secondarydex/src/Test.java
@@ -22,4 +22,8 @@
     private void print() {
         System.out.println("Test");
     }
+
+    public String toString() {
+        return new String("Test");
+    }
 }
diff --git a/test/422-type-conversion/src/Main.java b/test/422-type-conversion/src/Main.java
index 7ce2868..447b9b8 100644
--- a/test/422-type-conversion/src/Main.java
+++ b/test/422-type-conversion/src/Main.java
@@ -625,65 +625,67 @@
     assertCharEquals((char)0, $opt$IntToChar(-2147483648));  // -(2^31)
   }
 
+  // A dummy value to defeat inlining of these routines.
+  static boolean doThrow = false;
 
   // These methods produce int-to-long Dex instructions.
-  static long $opt$ByteToLong(byte a) { return (long)a; }
-  static long $opt$ShortToLong(short a) { return (long)a; }
-  static long $opt$IntToLong(int a) { return (long)a; }
-  static long $opt$CharToLong(int a) { return (long)a; }
+  static long $opt$ByteToLong(byte a) { if (doThrow) throw new Error(); return (long)a; }
+  static long $opt$ShortToLong(short a) { if (doThrow) throw new Error(); return (long)a; }
+  static long $opt$IntToLong(int a) { if (doThrow) throw new Error(); return (long)a; }
+  static long $opt$CharToLong(int a) { if (doThrow) throw new Error(); return (long)a; }
 
   // These methods produce int-to-float Dex instructions.
-  static float $opt$ByteToFloat(byte a) { return (float)a; }
-  static float $opt$ShortToFloat(short a) { return (float)a; }
-  static float $opt$IntToFloat(int a) { return (float)a; }
-  static float $opt$CharToFloat(char a) { return (float)a; }
+  static float $opt$ByteToFloat(byte a) { if (doThrow) throw new Error(); return (float)a; }
+  static float $opt$ShortToFloat(short a) { if (doThrow) throw new Error(); return (float)a; }
+  static float $opt$IntToFloat(int a) { if (doThrow) throw new Error(); return (float)a; }
+  static float $opt$CharToFloat(char a) { if (doThrow) throw new Error(); return (float)a; }
 
   // These methods produce int-to-double Dex instructions.
-  static double $opt$ByteToDouble(byte a) { return (double)a; }
-  static double $opt$ShortToDouble(short a) { return (double)a; }
-  static double $opt$IntToDouble(int a) { return (double)a; }
-  static double $opt$CharToDouble(int a) { return (double)a; }
+  static double $opt$ByteToDouble(byte a) { if (doThrow) throw new Error(); return (double)a; }
+  static double $opt$ShortToDouble(short a) { if (doThrow) throw new Error(); return (double)a; }
+  static double $opt$IntToDouble(int a) { if (doThrow) throw new Error(); return (double)a; }
+  static double $opt$CharToDouble(int a) { if (doThrow) throw new Error(); return (double)a; }
 
   // These methods produce long-to-int Dex instructions.
-  static int $opt$LongToInt(long a) { return (int)a; }
-  static int $opt$LongLiteralToInt() { return (int)42L; }
+  static int $opt$LongToInt(long a) { if (doThrow) throw new Error(); return (int)a; }
+  static int $opt$LongLiteralToInt() { if (doThrow) throw new Error(); return (int)42L; }
 
   // This method produces a long-to-float Dex instruction.
-  static float $opt$LongToFloat(long a) { return (float)a; }
+  static float $opt$LongToFloat(long a) { if (doThrow) throw new Error(); return (float)a; }
 
   // This method produces a long-to-double Dex instruction.
-  static double $opt$LongToDouble(long a) { return (double)a; }
+  static double $opt$LongToDouble(long a) { if (doThrow) throw new Error(); return (double)a; }
 
   // This method produces a float-to-int Dex instruction.
-  static int $opt$FloatToInt(float a) { return (int)a; }
+  static int $opt$FloatToInt(float a) { if (doThrow) throw new Error(); return (int)a; }
 
   // This method produces a float-to-long Dex instruction.
-  static long $opt$FloatToLong(float a){ return (long)a; }
+  static long $opt$FloatToLong(float a){ if (doThrow) throw new Error(); return (long)a; }
 
   // This method produces a float-to-double Dex instruction.
-  static double $opt$FloatToDouble(float a) { return (double)a; }
+  static double $opt$FloatToDouble(float a) { if (doThrow) throw new Error(); return (double)a; }
 
   // This method produces a double-to-int Dex instruction.
-  static int $opt$DoubleToInt(double a){ return (int)a; }
+  static int $opt$DoubleToInt(double a){ if (doThrow) throw new Error(); return (int)a; }
 
   // This method produces a double-to-long Dex instruction.
-  static long $opt$DoubleToLong(double a){ return (long)a; }
+  static long $opt$DoubleToLong(double a){ if (doThrow) throw new Error(); return (long)a; }
 
   // This method produces a double-to-float Dex instruction.
-  static float $opt$DoubleToFloat(double a) { return (float)a; }
+  static float $opt$DoubleToFloat(double a) { if (doThrow) throw new Error(); return (float)a; }
 
   // These methods produce int-to-byte Dex instructions.
-  static byte $opt$ShortToByte(short a) { return (byte)a; }
-  static byte $opt$IntToByte(int a) { return (byte)a; }
-  static byte $opt$CharToByte(char a) { return (byte)a; }
+  static byte $opt$ShortToByte(short a) { if (doThrow) throw new Error(); return (byte)a; }
+  static byte $opt$IntToByte(int a) { if (doThrow) throw new Error(); return (byte)a; }
+  static byte $opt$CharToByte(char a) { if (doThrow) throw new Error(); return (byte)a; }
 
   // These methods produce int-to-short Dex instructions.
-  static short $opt$ByteToShort(byte a) { return (short)a; }
-  static short $opt$IntToShort(int a) { return (short)a; }
-  static short $opt$CharToShort(char a) { return (short)a; }
+  static short $opt$ByteToShort(byte a) { if (doThrow) throw new Error(); return (short)a; }
+  static short $opt$IntToShort(int a) { if (doThrow) throw new Error(); return (short)a; }
+  static short $opt$CharToShort(char a) { if (doThrow) throw new Error(); return (short)a; }
 
   // These methods produce int-to-char Dex instructions.
-  static char $opt$ByteToChar(byte a) { return (char)a; }
-  static char $opt$ShortToChar(short a) { return (char)a; }
-  static char $opt$IntToChar(int a) { return (char)a; }
+  static char $opt$ByteToChar(byte a) { if (doThrow) throw new Error(); return (char)a; }
+  static char $opt$ShortToChar(short a) { if (doThrow) throw new Error(); return (char)a; }
+  static char $opt$IntToChar(int a) { if (doThrow) throw new Error(); return (char)a; }
 }
diff --git a/test/441-checker-inliner/src/Main.java b/test/441-checker-inliner/src/Main.java
index 631b140..8894d4e 100644
--- a/test/441-checker-inliner/src/Main.java
+++ b/test/441-checker-inliner/src/Main.java
@@ -17,9 +17,9 @@
 public class Main {
 
   // CHECK-START: void Main.InlineVoid() inliner (before)
-  // CHECK-DAG:     [[Const42:i\d+]] IntConstant 42
+  // CHECK-DAG:     <<Const42:i\d+>> IntConstant 42
   // CHECK-DAG:                      InvokeStaticOrDirect
-  // CHECK-DAG:                      InvokeStaticOrDirect [ [[Const42]] ]
+  // CHECK-DAG:                      InvokeStaticOrDirect [<<Const42>>]
 
   // CHECK-START: void Main.InlineVoid() inliner (after)
   // CHECK-NOT:                      InvokeStaticOrDirect
@@ -30,94 +30,94 @@
   }
 
   // CHECK-START: int Main.InlineParameter(int) inliner (before)
-  // CHECK-DAG:     [[Param:i\d+]]  ParameterValue
-  // CHECK-DAG:     [[Result:i\d+]] InvokeStaticOrDirect [ [[Param]] ]
-  // CHECK-DAG:                     Return [ [[Result]] ]
+  // CHECK-DAG:     <<Param:i\d+>>  ParameterValue
+  // CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect [<<Param>>]
+  // CHECK-DAG:                     Return [<<Result>>]
 
   // CHECK-START: int Main.InlineParameter(int) inliner (after)
-  // CHECK-DAG:     [[Param:i\d+]]  ParameterValue
-  // CHECK-DAG:                     Return [ [[Param]] ]
+  // CHECK-DAG:     <<Param:i\d+>>  ParameterValue
+  // CHECK-DAG:                     Return [<<Param>>]
 
   public static int InlineParameter(int a) {
     return returnParameter(a);
   }
 
   // CHECK-START: long Main.InlineWideParameter(long) inliner (before)
-  // CHECK-DAG:     [[Param:j\d+]]  ParameterValue
-  // CHECK-DAG:     [[Result:j\d+]] InvokeStaticOrDirect [ [[Param]] ]
-  // CHECK-DAG:                     Return [ [[Result]] ]
+  // CHECK-DAG:     <<Param:j\d+>>  ParameterValue
+  // CHECK-DAG:     <<Result:j\d+>> InvokeStaticOrDirect [<<Param>>]
+  // CHECK-DAG:                     Return [<<Result>>]
 
   // CHECK-START: long Main.InlineWideParameter(long) inliner (after)
-  // CHECK-DAG:     [[Param:j\d+]]  ParameterValue
-  // CHECK-DAG:                     Return [ [[Param]] ]
+  // CHECK-DAG:     <<Param:j\d+>>  ParameterValue
+  // CHECK-DAG:                     Return [<<Param>>]
 
   public static long InlineWideParameter(long a) {
     return returnWideParameter(a);
   }
 
   // CHECK-START: java.lang.Object Main.InlineReferenceParameter(java.lang.Object) inliner (before)
-  // CHECK-DAG:     [[Param:l\d+]]  ParameterValue
-  // CHECK-DAG:     [[Result:l\d+]] InvokeStaticOrDirect [ [[Param]] ]
-  // CHECK-DAG:                     Return [ [[Result]] ]
+  // CHECK-DAG:     <<Param:l\d+>>  ParameterValue
+  // CHECK-DAG:     <<Result:l\d+>> InvokeStaticOrDirect [<<Param>>]
+  // CHECK-DAG:                     Return [<<Result>>]
 
   // CHECK-START: java.lang.Object Main.InlineReferenceParameter(java.lang.Object) inliner (after)
-  // CHECK-DAG:     [[Param:l\d+]]  ParameterValue
-  // CHECK-DAG:                     Return [ [[Param]] ]
+  // CHECK-DAG:     <<Param:l\d+>>  ParameterValue
+  // CHECK-DAG:                     Return [<<Param>>]
 
   public static Object InlineReferenceParameter(Object o) {
     return returnReferenceParameter(o);
   }
 
   // CHECK-START: int Main.InlineInt() inliner (before)
-  // CHECK-DAG:     [[Result:i\d+]] InvokeStaticOrDirect
-  // CHECK-DAG:                     Return [ [[Result]] ]
+  // CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect
+  // CHECK-DAG:                     Return [<<Result>>]
 
   // CHECK-START: int Main.InlineInt() inliner (after)
-  // CHECK-DAG:     [[Const4:i\d+]] IntConstant 4
-  // CHECK-DAG:                     Return [ [[Const4]] ]
+  // CHECK-DAG:     <<Const4:i\d+>> IntConstant 4
+  // CHECK-DAG:                     Return [<<Const4>>]
 
   public static int InlineInt() {
     return returnInt();
   }
 
   // CHECK-START: long Main.InlineWide() inliner (before)
-  // CHECK-DAG:     [[Result:j\d+]] InvokeStaticOrDirect
-  // CHECK-DAG:                     Return [ [[Result]] ]
+  // CHECK-DAG:     <<Result:j\d+>> InvokeStaticOrDirect
+  // CHECK-DAG:                     Return [<<Result>>]
 
   // CHECK-START: long Main.InlineWide() inliner (after)
-  // CHECK-DAG:     [[Const8:j\d+]] LongConstant 8
-  // CHECK-DAG:                     Return [ [[Const8]] ]
+  // CHECK-DAG:     <<Const8:j\d+>> LongConstant 8
+  // CHECK-DAG:                     Return [<<Const8>>]
 
   public static long InlineWide() {
     return returnWide();
   }
 
   // CHECK-START: int Main.InlineAdd() inliner (before)
-  // CHECK-DAG:     [[Const3:i\d+]] IntConstant 3
-  // CHECK-DAG:     [[Const5:i\d+]] IntConstant 5
-  // CHECK-DAG:     [[Result:i\d+]] InvokeStaticOrDirect
-  // CHECK-DAG:                     Return [ [[Result]] ]
+  // CHECK-DAG:     <<Const3:i\d+>> IntConstant 3
+  // CHECK-DAG:     <<Const5:i\d+>> IntConstant 5
+  // CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect
+  // CHECK-DAG:                     Return [<<Result>>]
 
   // CHECK-START: int Main.InlineAdd() inliner (after)
-  // CHECK-DAG:     [[Const3:i\d+]] IntConstant 3
-  // CHECK-DAG:     [[Const5:i\d+]] IntConstant 5
-  // CHECK-DAG:     [[Add:i\d+]]    Add [ [[Const3]] [[Const5]] ]
-  // CHECK-DAG:                     Return [ [[Add]] ]
+  // CHECK-DAG:     <<Const3:i\d+>> IntConstant 3
+  // CHECK-DAG:     <<Const5:i\d+>> IntConstant 5
+  // CHECK-DAG:     <<Add:i\d+>>    Add [<<Const3>>,<<Const5>>]
+  // CHECK-DAG:                     Return [<<Add>>]
 
   public static int InlineAdd() {
     return returnAdd(3, 5);
   }
 
   // CHECK-START: int Main.InlineFieldAccess() inliner (before)
-  // CHECK-DAG:     [[After:i\d+]]  InvokeStaticOrDirect
-  // CHECK-DAG:                     Return [ [[After]] ]
+  // CHECK-DAG:     <<After:i\d+>>  InvokeStaticOrDirect
+  // CHECK-DAG:                     Return [<<After>>]
 
   // CHECK-START: int Main.InlineFieldAccess() inliner (after)
-  // CHECK-DAG:     [[Const1:i\d+]] IntConstant 1
-  // CHECK-DAG:     [[Before:i\d+]] StaticFieldGet
-  // CHECK-DAG:     [[After:i\d+]]  Add [ [[Before]] [[Const1]] ]
-  // CHECK-DAG:                     StaticFieldSet [ {{l\d+}} [[After]] ]
-  // CHECK-DAG:                     Return [ [[After]] ]
+  // CHECK-DAG:     <<Const1:i\d+>> IntConstant 1
+  // CHECK-DAG:     <<Before:i\d+>> StaticFieldGet
+  // CHECK-DAG:     <<After:i\d+>>  Add [<<Before>>,<<Const1>>]
+  // CHECK-DAG:                     StaticFieldSet [{{l\d+}},<<After>>]
+  // CHECK-DAG:                     Return [<<After>>]
 
   // CHECK-START: int Main.InlineFieldAccess() inliner (after)
   // CHECK-NOT:                     InvokeStaticOrDirect
@@ -127,22 +127,22 @@
   }
 
   // CHECK-START: int Main.InlineWithControlFlow(boolean) inliner (before)
-  // CHECK-DAG:     [[Const1:i\d+]] IntConstant 1
-  // CHECK-DAG:     [[Const3:i\d+]] IntConstant 3
-  // CHECK-DAG:     [[Const5:i\d+]] IntConstant 5
-  // CHECK-DAG:     [[Add:i\d+]]    InvokeStaticOrDirect [ [[Const1]] [[Const3]] ]
-  // CHECK-DAG:     [[Sub:i\d+]]    InvokeStaticOrDirect [ [[Const5]] [[Const3]] ]
-  // CHECK-DAG:     [[Phi:i\d+]]    Phi [ [[Add]] [[Sub]] ]
-  // CHECK-DAG:                     Return [ [[Phi]] ]
+  // CHECK-DAG:     <<Const1:i\d+>> IntConstant 1
+  // CHECK-DAG:     <<Const3:i\d+>> IntConstant 3
+  // CHECK-DAG:     <<Const5:i\d+>> IntConstant 5
+  // CHECK-DAG:     <<Add:i\d+>>    InvokeStaticOrDirect [<<Const1>>,<<Const3>>]
+  // CHECK-DAG:     <<Sub:i\d+>>    InvokeStaticOrDirect [<<Const5>>,<<Const3>>]
+  // CHECK-DAG:     <<Phi:i\d+>>    Phi [<<Add>>,<<Sub>>]
+  // CHECK-DAG:                     Return [<<Phi>>]
 
   // CHECK-START: int Main.InlineWithControlFlow(boolean) inliner (after)
-  // CHECK-DAG:     [[Const1:i\d+]] IntConstant 1
-  // CHECK-DAG:     [[Const3:i\d+]] IntConstant 3
-  // CHECK-DAG:     [[Const5:i\d+]] IntConstant 5
-  // CHECK-DAG:     [[Add:i\d+]]    Add [ [[Const1]] [[Const3]] ]
-  // CHECK-DAG:     [[Sub:i\d+]]    Sub [ [[Const5]] [[Const3]] ]
-  // CHECK-DAG:     [[Phi:i\d+]]    Phi [ [[Add]] [[Sub]] ]
-  // CHECK-DAG:                     Return [ [[Phi]] ]
+  // CHECK-DAG:     <<Const1:i\d+>> IntConstant 1
+  // CHECK-DAG:     <<Const3:i\d+>> IntConstant 3
+  // CHECK-DAG:     <<Const5:i\d+>> IntConstant 5
+  // CHECK-DAG:     <<Add:i\d+>>    Add [<<Const1>>,<<Const3>>]
+  // CHECK-DAG:     <<Sub:i\d+>>    Sub [<<Const5>>,<<Const3>>]
+  // CHECK-DAG:     <<Phi:i\d+>>    Phi [<<Add>>,<<Sub>>]
+  // CHECK-DAG:                     Return [<<Phi>>]
 
   public static int InlineWithControlFlow(boolean cond) {
     int x, const1, const3, const5;
diff --git a/test/442-checker-constant-folding/src/Main.java b/test/442-checker-constant-folding/src/Main.java
index 6b21fed..c258db9 100644
--- a/test/442-checker-constant-folding/src/Main.java
+++ b/test/442-checker-constant-folding/src/Main.java
@@ -16,6 +16,12 @@
 
 public class Main {
 
+  public static void assertFalse(boolean condition) {
+    if (condition) {
+      throw new Error();
+    }
+  }
+
   public static void assertIntEquals(int expected, int result) {
     if (expected != result) {
       throw new Error("Expected: " + expected + ", found: " + result);
@@ -28,19 +34,31 @@
     }
   }
 
+  public static void assertFloatEquals(float expected, float result) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+
+  public static void assertDoubleEquals(double expected, double result) {
+    if (expected != result) {
+      throw new Error("Expected: " + expected + ", found: " + result);
+    }
+  }
+
   /**
    * Tiny three-register program exercising int constant folding
    * on negation.
    */
 
   // CHECK-START: int Main.IntNegation() constant_folding (before)
-  // CHECK-DAG:     [[Const42:i\d+]]  IntConstant 42
-  // CHECK-DAG:     [[Neg:i\d+]]      Neg [ [[Const42]] ]
-  // CHECK-DAG:                       Return [ [[Neg]] ]
+  // CHECK-DAG:     <<Const42:i\d+>>  IntConstant 42
+  // CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Const42>>]
+  // CHECK-DAG:                       Return [<<Neg>>]
 
   // CHECK-START: int Main.IntNegation() constant_folding (after)
-  // CHECK-DAG:     [[ConstN42:i\d+]] IntConstant -42
-  // CHECK-DAG:                       Return [ [[ConstN42]] ]
+  // CHECK-DAG:     <<ConstN42:i\d+>> IntConstant -42
+  // CHECK-DAG:                       Return [<<ConstN42>>]
 
   public static int IntNegation() {
     int x, y;
@@ -55,14 +73,14 @@
    */
 
   // CHECK-START: int Main.IntAddition1() constant_folding (before)
-  // CHECK-DAG:     [[Const1:i\d+]]  IntConstant 1
-  // CHECK-DAG:     [[Const2:i\d+]]  IntConstant 2
-  // CHECK-DAG:     [[Add:i\d+]]     Add [ [[Const1]] [[Const2]] ]
-  // CHECK-DAG:                      Return [ [[Add]] ]
+  // CHECK-DAG:     <<Const1:i\d+>>  IntConstant 1
+  // CHECK-DAG:     <<Const2:i\d+>>  IntConstant 2
+  // CHECK-DAG:     <<Add:i\d+>>     Add [<<Const1>>,<<Const2>>]
+  // CHECK-DAG:                      Return [<<Add>>]
 
   // CHECK-START: int Main.IntAddition1() constant_folding (after)
-  // CHECK-DAG:     [[Const3:i\d+]]  IntConstant 3
-  // CHECK-DAG:                      Return [ [[Const3]] ]
+  // CHECK-DAG:     <<Const3:i\d+>>  IntConstant 3
+  // CHECK-DAG:                      Return [<<Const3>>]
 
   public static int IntAddition1() {
     int a, b, c;
@@ -78,18 +96,18 @@
   */
 
   // CHECK-START: int Main.IntAddition2() constant_folding (before)
-  // CHECK-DAG:     [[Const1:i\d+]]  IntConstant 1
-  // CHECK-DAG:     [[Const2:i\d+]]  IntConstant 2
-  // CHECK-DAG:     [[Const5:i\d+]]  IntConstant 5
-  // CHECK-DAG:     [[Const6:i\d+]]  IntConstant 6
-  // CHECK-DAG:     [[Add1:i\d+]]    Add [ [[Const1]] [[Const2]] ]
-  // CHECK-DAG:     [[Add2:i\d+]]    Add [ [[Const5]] [[Const6]] ]
-  // CHECK-DAG:     [[Add3:i\d+]]    Add [ [[Add1]] [[Add2]] ]
-  // CHECK-DAG:                      Return [ [[Add3]] ]
+  // CHECK-DAG:     <<Const1:i\d+>>  IntConstant 1
+  // CHECK-DAG:     <<Const2:i\d+>>  IntConstant 2
+  // CHECK-DAG:     <<Const5:i\d+>>  IntConstant 5
+  // CHECK-DAG:     <<Const6:i\d+>>  IntConstant 6
+  // CHECK-DAG:     <<Add1:i\d+>>    Add [<<Const1>>,<<Const2>>]
+  // CHECK-DAG:     <<Add2:i\d+>>    Add [<<Const5>>,<<Const6>>]
+  // CHECK-DAG:     <<Add3:i\d+>>    Add [<<Add1>>,<<Add2>>]
+  // CHECK-DAG:                      Return [<<Add3>>]
 
   // CHECK-START: int Main.IntAddition2() constant_folding (after)
-  // CHECK-DAG:     [[Const14:i\d+]] IntConstant 14
-  // CHECK-DAG:                      Return [ [[Const14]] ]
+  // CHECK-DAG:     <<Const14:i\d+>> IntConstant 14
+  // CHECK-DAG:                      Return [<<Const14>>]
 
   public static int IntAddition2() {
     int a, b, c;
@@ -109,14 +127,14 @@
    */
 
   // CHECK-START: int Main.IntSubtraction() constant_folding (before)
-  // CHECK-DAG:     [[Const6:i\d+]]  IntConstant 6
-  // CHECK-DAG:     [[Const2:i\d+]]  IntConstant 2
-  // CHECK-DAG:     [[Sub:i\d+]]     Sub [ [[Const6]] [[Const2]] ]
-  // CHECK-DAG:                      Return [ [[Sub]] ]
+  // CHECK-DAG:     <<Const6:i\d+>>  IntConstant 6
+  // CHECK-DAG:     <<Const2:i\d+>>  IntConstant 2
+  // CHECK-DAG:     <<Sub:i\d+>>     Sub [<<Const6>>,<<Const2>>]
+  // CHECK-DAG:                      Return [<<Sub>>]
 
   // CHECK-START: int Main.IntSubtraction() constant_folding (after)
-  // CHECK-DAG:     [[Const4:i\d+]]  IntConstant 4
-  // CHECK-DAG:                      Return [ [[Const4]] ]
+  // CHECK-DAG:     <<Const4:i\d+>>  IntConstant 4
+  // CHECK-DAG:                      Return [<<Const4>>]
 
   public static int IntSubtraction() {
     int a, b, c;
@@ -132,14 +150,14 @@
    */
 
   // CHECK-START: long Main.LongAddition() constant_folding (before)
-  // CHECK-DAG:     [[Const1:j\d+]]  LongConstant 1
-  // CHECK-DAG:     [[Const2:j\d+]]  LongConstant 2
-  // CHECK-DAG:     [[Add:j\d+]]     Add [ [[Const1]] [[Const2]] ]
-  // CHECK-DAG:                      Return [ [[Add]] ]
+  // CHECK-DAG:     <<Const1:j\d+>>  LongConstant 1
+  // CHECK-DAG:     <<Const2:j\d+>>  LongConstant 2
+  // CHECK-DAG:     <<Add:j\d+>>     Add [<<Const1>>,<<Const2>>]
+  // CHECK-DAG:                      Return [<<Add>>]
 
   // CHECK-START: long Main.LongAddition() constant_folding (after)
-  // CHECK-DAG:     [[Const3:j\d+]]  LongConstant 3
-  // CHECK-DAG:                      Return [ [[Const3]] ]
+  // CHECK-DAG:     <<Const3:j\d+>>  LongConstant 3
+  // CHECK-DAG:                      Return [<<Const3>>]
 
   public static long LongAddition() {
     long a, b, c;
@@ -155,14 +173,14 @@
    */
 
   // CHECK-START: long Main.LongSubtraction() constant_folding (before)
-  // CHECK-DAG:     [[Const6:j\d+]]  LongConstant 6
-  // CHECK-DAG:     [[Const2:j\d+]]  LongConstant 2
-  // CHECK-DAG:     [[Sub:j\d+]]     Sub [ [[Const6]] [[Const2]] ]
-  // CHECK-DAG:                      Return [ [[Sub]] ]
+  // CHECK-DAG:     <<Const6:j\d+>>  LongConstant 6
+  // CHECK-DAG:     <<Const2:j\d+>>  LongConstant 2
+  // CHECK-DAG:     <<Sub:j\d+>>     Sub [<<Const6>>,<<Const2>>]
+  // CHECK-DAG:                      Return [<<Sub>>]
 
   // CHECK-START: long Main.LongSubtraction() constant_folding (after)
-  // CHECK-DAG:     [[Const4:j\d+]]  LongConstant 4
-  // CHECK-DAG:                      Return [ [[Const4]] ]
+  // CHECK-DAG:     <<Const4:j\d+>>  LongConstant 4
+  // CHECK-DAG:                      Return [<<Const4>>]
 
   public static long LongSubtraction() {
     long a, b, c;
@@ -177,14 +195,14 @@
    */
 
   // CHECK-START: int Main.StaticCondition() constant_folding (before)
-  // CHECK-DAG:     [[Const7:i\d+]]  IntConstant 7
-  // CHECK-DAG:     [[Const2:i\d+]]  IntConstant 2
-  // CHECK-DAG:     [[Cond:z\d+]]    GreaterThanOrEqual [ [[Const7]] [[Const2]] ]
-  // CHECK-DAG:                      If [ [[Cond]] ]
+  // CHECK-DAG:     <<Const7:i\d+>>  IntConstant 7
+  // CHECK-DAG:     <<Const2:i\d+>>  IntConstant 2
+  // CHECK-DAG:     <<Cond:z\d+>>    GreaterThanOrEqual [<<Const7>>,<<Const2>>]
+  // CHECK-DAG:                      If [<<Cond>>]
 
   // CHECK-START: int Main.StaticCondition() constant_folding (after)
-  // CHECK-DAG:     [[Const1:i\d+]]  IntConstant 1
-  // CHECK-DAG:                      If [ [[Const1]] ]
+  // CHECK-DAG:     <<Const1:i\d+>>  IntConstant 1
+  // CHECK-DAG:                      If [<<Const1>>]
 
   public static int StaticCondition() {
     int a, b, c;
@@ -207,18 +225,18 @@
    */
 
   // CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding (before)
-  // CHECK-DAG:     [[Const2:i\d+]]  IntConstant 2
-  // CHECK-DAG:     [[Const5:i\d+]]  IntConstant 5
-  // CHECK-DAG:     [[Add:i\d+]]     Add [ [[Const5]] [[Const2]] ]
-  // CHECK-DAG:     [[Sub:i\d+]]     Sub [ [[Const5]] [[Const2]] ]
-  // CHECK-DAG:     [[Phi:i\d+]]     Phi [ [[Add]] [[Sub]] ]
-  // CHECK-DAG:                      Return [ [[Phi]] ]
+  // CHECK-DAG:     <<Const2:i\d+>>  IntConstant 2
+  // CHECK-DAG:     <<Const5:i\d+>>  IntConstant 5
+  // CHECK-DAG:     <<Add:i\d+>>     Add [<<Const5>>,<<Const2>>]
+  // CHECK-DAG:     <<Sub:i\d+>>     Sub [<<Const5>>,<<Const2>>]
+  // CHECK-DAG:     <<Phi:i\d+>>     Phi [<<Add>>,<<Sub>>]
+  // CHECK-DAG:                      Return [<<Phi>>]
 
   // CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding (after)
-  // CHECK-DAG:     [[Const3:i\d+]]  IntConstant 3
-  // CHECK-DAG:     [[Const7:i\d+]]  IntConstant 7
-  // CHECK-DAG:     [[Phi:i\d+]]     Phi [ [[Const7]] [[Const3]] ]
-  // CHECK-DAG:                      Return [ [[Phi]] ]
+  // CHECK-DAG:     <<Const3:i\d+>>  IntConstant 3
+  // CHECK-DAG:     <<Const7:i\d+>>  IntConstant 7
+  // CHECK-DAG:     <<Phi:i\d+>>     Phi [<<Const7>>,<<Const3>>]
+  // CHECK-DAG:                      Return [<<Phi>>]
 
   public static int JumpsAndConditionals(boolean cond) {
     int a, b, c;
@@ -236,177 +254,393 @@
    */
 
   // CHECK-START: int Main.And0(int) constant_folding (before)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
-  // CHECK-DAG:     [[And:i\d+]]      And [ [[Arg]] [[Const0]] ]
-  // CHECK-DAG:                       Return [ [[And]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:     <<And:i\d+>>      And [<<Arg>>,<<Const0>>]
+  // CHECK-DAG:                       Return [<<And>>]
 
   // CHECK-START: int Main.And0(int) constant_folding (after)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
   // CHECK-NOT:                       And
-  // CHECK-DAG:                       Return [ [[Const0]] ]
+  // CHECK-DAG:                       Return [<<Const0>>]
 
   public static int And0(int arg) {
     return arg & 0;
   }
 
   // CHECK-START: long Main.Mul0(long) constant_folding (before)
-  // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:j\d+]]   LongConstant 0
-  // CHECK-DAG:     [[Mul:j\d+]]      Mul [ [[Arg]] [[Const0]] ]
-  // CHECK-DAG:                       Return [ [[Mul]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
+  // CHECK-DAG:     <<Mul:j\d+>>      Mul [<<Arg>>,<<Const0>>]
+  // CHECK-DAG:                       Return [<<Mul>>]
 
   // CHECK-START: long Main.Mul0(long) constant_folding (after)
-  // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:j\d+]]   LongConstant 0
+  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
   // CHECK-NOT:                       Mul
-  // CHECK-DAG:                       Return [ [[Const0]] ]
+  // CHECK-DAG:                       Return [<<Const0>>]
 
   public static long Mul0(long arg) {
     return arg * 0;
   }
 
   // CHECK-START: int Main.OrAllOnes(int) constant_folding (before)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[ConstF:i\d+]]   IntConstant -1
-  // CHECK-DAG:     [[Or:i\d+]]       Or [ [[Arg]] [[ConstF]] ]
-  // CHECK-DAG:                       Return [ [[Or]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<ConstF:i\d+>>   IntConstant -1
+  // CHECK-DAG:     <<Or:i\d+>>       Or [<<Arg>>,<<ConstF>>]
+  // CHECK-DAG:                       Return [<<Or>>]
 
   // CHECK-START: int Main.OrAllOnes(int) constant_folding (after)
-  // CHECK-DAG:     [[ConstF:i\d+]]   IntConstant -1
+  // CHECK-DAG:     <<ConstF:i\d+>>   IntConstant -1
   // CHECK-NOT:                       Or
-  // CHECK-DAG:                       Return [ [[ConstF]] ]
+  // CHECK-DAG:                       Return [<<ConstF>>]
 
   public static int OrAllOnes(int arg) {
     return arg | -1;
   }
 
   // CHECK-START: long Main.Rem0(long) constant_folding (before)
-  // CHECK-DAG:     [[Arg:j\d+]]           ParameterValue
-  // CHECK-DAG:     [[Const0:j\d+]]        LongConstant 0
-  // CHECK-DAG:     [[DivZeroCheck:j\d+]]  DivZeroCheck [ [[Arg]] ]
-  // CHECK-DAG:     [[Rem:j\d+]]           Rem [ [[Const0]] [[DivZeroCheck]] ]
-  // CHECK-DAG:                            Return [ [[Rem]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>           ParameterValue
+  // CHECK-DAG:     <<Const0:j\d+>>        LongConstant 0
+  // CHECK-DAG:     <<DivZeroCheck:j\d+>>  DivZeroCheck [<<Arg>>]
+  // CHECK-DAG:     <<Rem:j\d+>>           Rem [<<Const0>>,<<DivZeroCheck>>]
+  // CHECK-DAG:                            Return [<<Rem>>]
 
   // CHECK-START: long Main.Rem0(long) constant_folding (after)
-  // CHECK-DAG:     [[Const0:j\d+]]        LongConstant 0
+  // CHECK-DAG:     <<Const0:j\d+>>        LongConstant 0
   // CHECK-NOT:                            Rem
-  // CHECK-DAG:                            Return [ [[Const0]] ]
+  // CHECK-DAG:                            Return [<<Const0>>]
 
   public static long Rem0(long arg) {
     return 0 % arg;
   }
 
   // CHECK-START: int Main.Rem1(int) constant_folding (before)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const1:i\d+]]   IntConstant 1
-  // CHECK-DAG:     [[Rem:i\d+]]      Rem [ [[Arg]] [[Const1]] ]
-  // CHECK-DAG:                       Return [ [[Rem]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  // CHECK-DAG:     <<Rem:i\d+>>      Rem [<<Arg>>,<<Const1>>]
+  // CHECK-DAG:                       Return [<<Rem>>]
 
   // CHECK-START: int Main.Rem1(int) constant_folding (after)
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
   // CHECK-NOT:                       Rem
-  // CHECK-DAG:                       Return [ [[Const0]] ]
+  // CHECK-DAG:                       Return [<<Const0>>]
 
   public static int Rem1(int arg) {
     return arg % 1;
   }
 
   // CHECK-START: long Main.RemN1(long) constant_folding (before)
-  // CHECK-DAG:     [[Arg:j\d+]]           ParameterValue
-  // CHECK-DAG:     [[ConstN1:j\d+]]       LongConstant -1
-  // CHECK-DAG:     [[DivZeroCheck:j\d+]]  DivZeroCheck [ [[Arg]] ]
-  // CHECK-DAG:     [[Rem:j\d+]]           Rem [ [[Arg]] [[DivZeroCheck]] ]
-  // CHECK-DAG:                            Return [ [[Rem]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>           ParameterValue
+  // CHECK-DAG:     <<ConstN1:j\d+>>       LongConstant -1
+  // CHECK-DAG:     <<DivZeroCheck:j\d+>>  DivZeroCheck [<<ConstN1>>]
+  // CHECK-DAG:     <<Rem:j\d+>>           Rem [<<Arg>>,<<DivZeroCheck>>]
+  // CHECK-DAG:                            Return [<<Rem>>]
 
   // CHECK-START: long Main.RemN1(long) constant_folding (after)
-  // CHECK-DAG:     [[Const0:j\d+]]        LongConstant 0
+  // CHECK-DAG:     <<Const0:j\d+>>        LongConstant 0
   // CHECK-NOT:                            Rem
-  // CHECK-DAG:                            Return [ [[Const0]] ]
+  // CHECK-DAG:                            Return [<<Const0>>]
 
   public static long RemN1(long arg) {
     return arg % -1;
   }
 
   // CHECK-START: int Main.Shl0(int) constant_folding (before)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
-  // CHECK-DAG:     [[Shl:i\d+]]      Shl [ [[Const0]] [[Arg]] ]
-  // CHECK-DAG:                       Return [ [[Shl]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:     <<Shl:i\d+>>      Shl [<<Const0>>,<<Arg>>]
+  // CHECK-DAG:                       Return [<<Shl>>]
 
   // CHECK-START: int Main.Shl0(int) constant_folding (after)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
   // CHECK-NOT:                       Shl
-  // CHECK-DAG:                       Return [ [[Const0]] ]
+  // CHECK-DAG:                       Return [<<Const0>>]
 
   public static int Shl0(int arg) {
     return 0 << arg;
   }
 
   // CHECK-START: long Main.Shr0(int) constant_folding (before)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:j\d+]]   LongConstant 0
-  // CHECK-DAG:     [[Shr:j\d+]]      Shr [ [[Const0]] [[Arg]] ]
-  // CHECK-DAG:                       Return [ [[Shr]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
+  // CHECK-DAG:     <<Shr:j\d+>>      Shr [<<Const0>>,<<Arg>>]
+  // CHECK-DAG:                       Return [<<Shr>>]
 
   // CHECK-START: long Main.Shr0(int) constant_folding (after)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:j\d+]]   LongConstant 0
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
   // CHECK-NOT:                       Shr
-  // CHECK-DAG:                       Return [ [[Const0]] ]
+  // CHECK-DAG:                       Return [<<Const0>>]
 
   public static long Shr0(int arg) {
     return (long)0 >> arg;
   }
 
   // CHECK-START: long Main.SubSameLong(long) constant_folding (before)
-  // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
-  // CHECK-DAG:     [[Sub:j\d+]]      Sub [ [[Arg]] [[Arg]] ]
-  // CHECK-DAG:                       Return [ [[Sub]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  // CHECK-DAG:     <<Sub:j\d+>>      Sub [<<Arg>>,<<Arg>>]
+  // CHECK-DAG:                       Return [<<Sub>>]
 
   // CHECK-START: long Main.SubSameLong(long) constant_folding (after)
-  // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:j\d+]]   LongConstant 0
+  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
   // CHECK-NOT:                       Sub
-  // CHECK-DAG:                       Return [ [[Const0]] ]
+  // CHECK-DAG:                       Return [<<Const0>>]
 
   public static long SubSameLong(long arg) {
     return arg - arg;
   }
 
   // CHECK-START: int Main.UShr0(int) constant_folding (before)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
-  // CHECK-DAG:     [[UShr:i\d+]]     UShr [ [[Const0]] [[Arg]] ]
-  // CHECK-DAG:                       Return [ [[UShr]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:     <<UShr:i\d+>>     UShr [<<Const0>>,<<Arg>>]
+  // CHECK-DAG:                       Return [<<UShr>>]
 
   // CHECK-START: int Main.UShr0(int) constant_folding (after)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
   // CHECK-NOT:                       UShr
-  // CHECK-DAG:                       Return [ [[Const0]] ]
+  // CHECK-DAG:                       Return [<<Const0>>]
 
   public static int UShr0(int arg) {
     return 0 >>> arg;
   }
 
   // CHECK-START: int Main.XorSameInt(int) constant_folding (before)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Xor:i\d+]]      Xor [ [[Arg]] [[Arg]] ]
-  // CHECK-DAG:                       Return [ [[Xor]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Xor:i\d+>>      Xor [<<Arg>>,<<Arg>>]
+  // CHECK-DAG:                       Return [<<Xor>>]
 
   // CHECK-START: int Main.XorSameInt(int) constant_folding (after)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
   // CHECK-NOT:                       Xor
-  // CHECK-DAG:                       Return [ [[Const0]] ]
+  // CHECK-DAG:                       Return [<<Const0>>]
 
   public static int XorSameInt(int arg) {
     return arg ^ arg;
   }
 
+  // CHECK-START: boolean Main.CmpFloatGreaterThanNaN(float) constant_folding (before)
+  // CHECK-DAG:     <<Arg:f\d+>>      ParameterValue
+  // CHECK-DAG:     <<ConstNan:f\d+>> FloatConstant nan
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:                       IntConstant 1
+  // CHECK-DAG:     <<Cmp:i\d+>>      Compare [<<Arg>>,<<ConstNan>>]
+  // CHECK-DAG:     <<Le:z\d+>>       LessThanOrEqual [<<Cmp>>,<<Const0>>]
+  // CHECK-DAG:                       If [<<Le>>]
+
+  // CHECK-START: boolean Main.CmpFloatGreaterThanNaN(float) constant_folding (after)
+  // CHECK-DAG:                       ParameterValue
+  // CHECK-DAG:                       FloatConstant nan
+  // CHECK-DAG:                       IntConstant 0
+  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  // CHECK-DAG:                       If [<<Const1>>]
+
+  // CHECK-START: boolean Main.CmpFloatGreaterThanNaN(float) constant_folding (after)
+  // CHECK-NOT:                       Compare
+  // CHECK-NOT:                       LessThanOrEqual
+
+  public static boolean CmpFloatGreaterThanNaN(float arg) {
+    return arg > Float.NaN;
+  }
+
+  // CHECK-START: boolean Main.CmpDoubleLessThanNaN(double) constant_folding (before)
+  // CHECK-DAG:     <<Arg:d\d+>>      ParameterValue
+  // CHECK-DAG:     <<ConstNan:d\d+>> DoubleConstant nan
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:                       IntConstant 1
+  // CHECK-DAG:     <<Cmp:i\d+>>      Compare [<<Arg>>,<<ConstNan>>]
+  // CHECK-DAG:     <<Ge:z\d+>>       GreaterThanOrEqual [<<Cmp>>,<<Const0>>]
+  // CHECK-DAG:                       If [<<Ge>>]
+
+  // CHECK-START: boolean Main.CmpDoubleLessThanNaN(double) constant_folding (after)
+  // CHECK-DAG:                       ParameterValue
+  // CHECK-DAG:                       DoubleConstant nan
+  // CHECK-DAG:                       IntConstant 0
+  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  // CHECK-DAG:                       If [<<Const1>>]
+
+  // CHECK-START: boolean Main.CmpDoubleLessThanNaN(double) constant_folding (after)
+  // CHECK-NOT:                       Compare
+  // CHECK-NOT:                       GreaterThanOrEqual
+
+  public static boolean CmpDoubleLessThanNaN(double arg) {
+    return arg < Double.NaN;
+  }
+
+  // CHECK-START: int Main.ReturnInt33() constant_folding (before)
+  // CHECK-DAG:     <<Const33:j\d+>>  LongConstant 33
+  // CHECK-DAG:     <<Convert:i\d+>>  TypeConversion [<<Const33>>]
+  // CHECK-DAG:                       Return [<<Convert>>]
+
+  // CHECK-START: int Main.ReturnInt33() constant_folding (after)
+  // CHECK-DAG:     <<Const33:i\d+>>  IntConstant 33
+  // CHECK-DAG:                       Return [<<Const33>>]
+
+  public static int ReturnInt33() {
+    long imm = 33L;
+    return (int) imm;
+  }
+
+  // CHECK-START: int Main.ReturnIntMax() constant_folding (before)
+  // CHECK-DAG:     <<ConstMax:f\d+>> FloatConstant 1e+34
+  // CHECK-DAG:     <<Convert:i\d+>>  TypeConversion [<<ConstMax>>]
+  // CHECK-DAG:                       Return [<<Convert>>]
+
+  // CHECK-START: int Main.ReturnIntMax() constant_folding (after)
+  // CHECK-DAG:     <<ConstMax:i\d+>> IntConstant 2147483647
+  // CHECK-DAG:                       Return [<<ConstMax>>]
+
+  public static int ReturnIntMax() {
+    float imm = 1.0e34f;
+    return (int) imm;
+  }
+
+  // CHECK-START: int Main.ReturnInt0() constant_folding (before)
+  // CHECK-DAG:     <<ConstNaN:d\d+>> DoubleConstant nan
+  // CHECK-DAG:     <<Convert:i\d+>>  TypeConversion [<<ConstNaN>>]
+  // CHECK-DAG:                       Return [<<Convert>>]
+
+  // CHECK-START: int Main.ReturnInt0() constant_folding (after)
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:                       Return [<<Const0>>]
+
+  public static int ReturnInt0() {
+    double imm = Double.NaN;
+    return (int) imm;
+  }
+
+  // CHECK-START: long Main.ReturnLong33() constant_folding (before)
+  // CHECK-DAG:     <<Const33:i\d+>>  IntConstant 33
+  // CHECK-DAG:     <<Convert:j\d+>>  TypeConversion [<<Const33>>]
+  // CHECK-DAG:                       Return [<<Convert>>]
+
+  // CHECK-START: long Main.ReturnLong33() constant_folding (after)
+  // CHECK-DAG:     <<Const33:j\d+>>  LongConstant 33
+  // CHECK-DAG:                       Return [<<Const33>>]
+
+  public static long ReturnLong33() {
+    int imm = 33;
+    return (long) imm;
+  }
+
+  // CHECK-START: long Main.ReturnLong34() constant_folding (before)
+  // CHECK-DAG:     <<Const34:f\d+>>  FloatConstant 34
+  // CHECK-DAG:     <<Convert:j\d+>>  TypeConversion [<<Const34>>]
+  // CHECK-DAG:                       Return [<<Convert>>]
+
+  // CHECK-START: long Main.ReturnLong34() constant_folding (after)
+  // CHECK-DAG:     <<Const34:j\d+>>  LongConstant 34
+  // CHECK-DAG:                       Return [<<Const34>>]
+
+  public static long ReturnLong34() {
+    float imm = 34.0f;
+    return (long) imm;
+  }
+
+  // CHECK-START: long Main.ReturnLong0() constant_folding (before)
+  // CHECK-DAG:     <<ConstNaN:d\d+>> DoubleConstant nan
+  // CHECK-DAG:     <<Convert:j\d+>>  TypeConversion [<<ConstNaN>>]
+  // CHECK-DAG:                       Return [<<Convert>>]
+
+  // CHECK-START: long Main.ReturnLong0() constant_folding (after)
+  // CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
+  // CHECK-DAG:                       Return [<<Const0>>]
+
+  public static long ReturnLong0() {
+    double imm = -Double.NaN;
+    return (long) imm;
+  }
+
+  // CHECK-START: float Main.ReturnFloat33() constant_folding (before)
+  // CHECK-DAG:     <<Const33:i\d+>>  IntConstant 33
+  // CHECK-DAG:     <<Convert:f\d+>>  TypeConversion [<<Const33>>]
+  // CHECK-DAG:                       Return [<<Convert>>]
+
+  // CHECK-START: float Main.ReturnFloat33() constant_folding (after)
+  // CHECK-DAG:     <<Const33:f\d+>>  FloatConstant 33
+  // CHECK-DAG:                       Return [<<Const33>>]
+
+  public static float ReturnFloat33() {
+    int imm = 33;
+    return (float) imm;
+  }
+
+  // CHECK-START: float Main.ReturnFloat34() constant_folding (before)
+  // CHECK-DAG:     <<Const34:j\d+>>  LongConstant 34
+  // CHECK-DAG:     <<Convert:f\d+>>  TypeConversion [<<Const34>>]
+  // CHECK-DAG:                       Return [<<Convert>>]
+
+  // CHECK-START: float Main.ReturnFloat34() constant_folding (after)
+  // CHECK-DAG:     <<Const34:f\d+>>  FloatConstant 34
+  // CHECK-DAG:                       Return [<<Const34>>]
+
+  public static float ReturnFloat34() {
+    long imm = 34L;
+    return (float) imm;
+  }
+
+  // CHECK-START: float Main.ReturnFloat99P25() constant_folding (before)
+  // CHECK-DAG:     <<Const:d\d+>>    DoubleConstant 99.25
+  // CHECK-DAG:     <<Convert:f\d+>>  TypeConversion [<<Const>>]
+  // CHECK-DAG:                       Return [<<Convert>>]
+
+  // CHECK-START: float Main.ReturnFloat99P25() constant_folding (after)
+  // CHECK-DAG:     <<Const:f\d+>>    FloatConstant 99.25
+  // CHECK-DAG:                       Return [<<Const>>]
+
+  public static float ReturnFloat99P25() {
+    double imm = 99.25;
+    return (float) imm;
+  }
+
+  // CHECK-START: double Main.ReturnDouble33() constant_folding (before)
+  // CHECK-DAG:     <<Const33:i\d+>>  IntConstant 33
+  // CHECK-DAG:     <<Convert:d\d+>>  TypeConversion [<<Const33>>]
+  // CHECK-DAG:                       Return [<<Convert>>]
+
+  // CHECK-START: double Main.ReturnDouble33() constant_folding (after)
+  // CHECK-DAG:     <<Const33:d\d+>>  DoubleConstant 33
+  // CHECK-DAG:                       Return [<<Const33>>]
+
+  public static double ReturnDouble33() {
+    int imm = 33;
+    return (double) imm;
+  }
+
+  // CHECK-START: double Main.ReturnDouble34() constant_folding (before)
+  // CHECK-DAG:     <<Const34:j\d+>>  LongConstant 34
+  // CHECK-DAG:     <<Convert:d\d+>>  TypeConversion [<<Const34>>]
+  // CHECK-DAG:                       Return [<<Convert>>]
+
+  // CHECK-START: double Main.ReturnDouble34() constant_folding (after)
+  // CHECK-DAG:     <<Const34:d\d+>>  DoubleConstant 34
+  // CHECK-DAG:                       Return [<<Const34>>]
+
+  public static double ReturnDouble34() {
+    long imm = 34L;
+    return (double) imm;
+  }
+
+  // CHECK-START: double Main.ReturnDouble99P25() constant_folding (before)
+  // CHECK-DAG:     <<Const:f\d+>>    FloatConstant 99.25
+  // CHECK-DAG:     <<Convert:d\d+>>  TypeConversion [<<Const>>]
+  // CHECK-DAG:                       Return [<<Convert>>]
+
+  // CHECK-START: double Main.ReturnDouble99P25() constant_folding (after)
+  // CHECK-DAG:     <<Const:d\d+>>    DoubleConstant 99.25
+  // CHECK-DAG:                       Return [<<Const>>]
+
+  public static double ReturnDouble99P25() {
+    float imm = 99.25f;
+    return (double) imm;
+  }
+
   public static void main(String[] args) {
     assertIntEquals(IntNegation(), -42);
     assertIntEquals(IntAddition1(), 3);
@@ -417,17 +651,31 @@
     assertIntEquals(StaticCondition(), 5);
     assertIntEquals(JumpsAndConditionals(true), 7);
     assertIntEquals(JumpsAndConditionals(false), 3);
-    int random = 123456;  // Chosen randomly.
-    assertIntEquals(And0(random), 0);
-    assertLongEquals(Mul0(random), 0);
-    assertIntEquals(OrAllOnes(random), -1);
-    assertLongEquals(Rem0(random), 0);
-    assertIntEquals(Rem1(random), 0);
-    assertLongEquals(RemN1(random), 0);
-    assertIntEquals(Shl0(random), 0);
-    assertLongEquals(Shr0(random), 0);
-    assertLongEquals(SubSameLong(random), 0);
-    assertIntEquals(UShr0(random), 0);
-    assertIntEquals(XorSameInt(random), 0);
+    int arbitrary = 123456;  // Value chosen arbitrarily.
+    assertIntEquals(And0(arbitrary), 0);
+    assertLongEquals(Mul0(arbitrary), 0);
+    assertIntEquals(OrAllOnes(arbitrary), -1);
+    assertLongEquals(Rem0(arbitrary), 0);
+    assertIntEquals(Rem1(arbitrary), 0);
+    assertLongEquals(RemN1(arbitrary), 0);
+    assertIntEquals(Shl0(arbitrary), 0);
+    assertLongEquals(Shr0(arbitrary), 0);
+    assertLongEquals(SubSameLong(arbitrary), 0);
+    assertIntEquals(UShr0(arbitrary), 0);
+    assertIntEquals(XorSameInt(arbitrary), 0);
+    assertFalse(CmpFloatGreaterThanNaN(arbitrary));
+    assertFalse(CmpDoubleLessThanNaN(arbitrary));
+    assertIntEquals(ReturnInt33(), 33);
+    assertIntEquals(ReturnIntMax(), 2147483647);
+    assertIntEquals(ReturnInt0(), 0);
+    assertLongEquals(ReturnLong33(), 33);
+    assertLongEquals(ReturnLong34(), 34);
+    assertLongEquals(ReturnLong0(), 0);
+    assertFloatEquals(ReturnFloat33(), 33);
+    assertFloatEquals(ReturnFloat34(), 34);
+    assertFloatEquals(ReturnFloat99P25(), 99.25f);
+    assertDoubleEquals(ReturnDouble33(), 33);
+    assertDoubleEquals(ReturnDouble34(), 34);
+    assertDoubleEquals(ReturnDouble99P25(), 99.25);
   }
 }
diff --git a/test/445-checker-licm/src/Main.java b/test/445-checker-licm/src/Main.java
index 91ac2ed..96918d3 100644
--- a/test/445-checker-licm/src/Main.java
+++ b/test/445-checker-licm/src/Main.java
@@ -17,13 +17,13 @@
 public class Main {
 
   // CHECK-START: int Main.div() licm (before)
-  // CHECK-DAG: Div ( loop_header:{{B\d+}} )
+  // CHECK-DAG: Div loop:{{B\d+}}
 
   // CHECK-START: int Main.div() licm (after)
-  // CHECK-NOT: Div ( loop_header:{{B\d+}} )
+  // CHECK-NOT: Div loop:{{B\d+}}
 
   // CHECK-START: int Main.div() licm (after)
-  // CHECK-DAG: Div ( loop_header:null )
+  // CHECK-DAG: Div loop:none
 
   public static int div() {
     int result = 0;
@@ -34,13 +34,13 @@
   }
 
   // CHECK-START: int Main.innerDiv() licm (before)
-  // CHECK-DAG: Div ( loop_header:{{B\d+}} )
+  // CHECK-DAG: Div loop:{{B\d+}}
 
   // CHECK-START: int Main.innerDiv() licm (after)
-  // CHECK-NOT: Div ( loop_header:{{B\d+}} )
+  // CHECK-NOT: Div loop:{{B\d+}}
 
   // CHECK-START: int Main.innerDiv() licm (after)
-  // CHECK-DAG: Div ( loop_header:null )
+  // CHECK-DAG: Div loop:none
 
   public static int innerDiv() {
     int result = 0;
@@ -53,10 +53,10 @@
   }
 
   // CHECK-START: int Main.innerDiv2() licm (before)
-  // CHECK-DAG: Mul ( loop_header:{{B4}} )
+  // CHECK-DAG: Mul loop:B4
 
   // CHECK-START: int Main.innerDiv2() licm (after)
-  // CHECK-DAG: Mul ( loop_header:{{B2}} )
+  // CHECK-DAG: Mul loop:B2
 
   public static int innerDiv2() {
     int result = 0;
@@ -72,10 +72,10 @@
   }
 
   // CHECK-START: int Main.innerDiv3(int, int) licm (before)
-  // CHECK-DAG: Div ( loop_header:{{B\d+}} )
+  // CHECK-DAG: Div loop:{{B\d+}}
 
   // CHECK-START: int Main.innerDiv3(int, int) licm (after)
-  // CHECK-DAG: Div ( loop_header:{{B\d+}} )
+  // CHECK-DAG: Div loop:{{B\d+}}
 
   public static int innerDiv3(int a, int b) {
     int result = 0;
@@ -88,16 +88,16 @@
   }
 
   // CHECK-START: int Main.arrayLength(int[]) licm (before)
-  // CHECK-DAG: [[NullCheck:l\d+]] NullCheck ( loop_header:{{B\d+}} )
-  // CHECK-DAG:                    ArrayLength [ [[NullCheck]] ] ( loop_header:{{B\d+}} )
+  // CHECK-DAG: <<NullCheck:l\d+>> NullCheck loop:{{B\d+}}
+  // CHECK-DAG:                    ArrayLength [<<NullCheck>>] loop:{{B\d+}}
 
   // CHECK-START: int Main.arrayLength(int[]) licm (after)
-  // CHECK-NOT:                    NullCheck ( loop_header:{{B\d+}} )
-  // CHECK-NOT:                    ArrayLength ( loop_header:{{B\d+}} )
+  // CHECK-NOT:                    NullCheck loop:{{B\d+}}
+  // CHECK-NOT:                    ArrayLength loop:{{B\d+}}
 
   // CHECK-START: int Main.arrayLength(int[]) licm (after)
-  // CHECK-DAG: [[NullCheck:l\d+]] NullCheck ( loop_header:null )
-  // CHECK-DAG:                    ArrayLength [ [[NullCheck]] ] ( loop_header:null )
+  // CHECK-DAG: <<NullCheck:l\d+>> NullCheck loop:none
+  // CHECK-DAG:                    ArrayLength [<<NullCheck>>] loop:none
 
   public static int arrayLength(int[] array) {
     int result = 0;
diff --git a/test/446-checker-inliner2/src/Main.java b/test/446-checker-inliner2/src/Main.java
index ecf071e..9ed66d6 100644
--- a/test/446-checker-inliner2/src/Main.java
+++ b/test/446-checker-inliner2/src/Main.java
@@ -17,15 +17,15 @@
 public class Main {
 
   // CHECK-START: int Main.inlineInstanceCall(Main) inliner (before)
-  // CHECK-DAG:     [[Invoke:i\d+]]  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ [[Invoke]] ]
+  // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   // CHECK-START: int Main.inlineInstanceCall(Main) inliner (after)
   // CHECK-NOT:                      InvokeStaticOrDirect
 
   // CHECK-START: int Main.inlineInstanceCall(Main) inliner (after)
-  // CHECK-DAG:     [[Field:i\d+]]   InstanceFieldGet
-  // CHECK-DAG:                      Return [ [[Field]] ]
+  // CHECK-DAG:     <<Field:i\d+>>   InstanceFieldGet
+  // CHECK-DAG:                      Return [<<Field>>]
 
   public static int inlineInstanceCall(Main m) {
     return m.foo();
@@ -38,15 +38,15 @@
   int field = 42;
 
   // CHECK-START: int Main.inlineNestedCall() inliner (before)
-  // CHECK-DAG:     [[Invoke:i\d+]]  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ [[Invoke]] ]
+  // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   // CHECK-START: int Main.inlineNestedCall() inliner (after)
   // CHECK-NOT:                      InvokeStaticOrDirect
 
   // CHECK-START: int Main.inlineNestedCall() inliner (after)
-  // CHECK-DAG:     [[Const38:i\d+]] IntConstant 38
-  // CHECK-DAG:                      Return [ [[Const38]] ]
+  // CHECK-DAG:     <<Const38:i\d+>> IntConstant 38
+  // CHECK-DAG:                      Return [<<Const38>>]
 
   public static int inlineNestedCall() {
     return nestedCall();
diff --git a/test/447-checker-inliner3/src/Main.java b/test/447-checker-inliner3/src/Main.java
index db4b236..9d022b9 100644
--- a/test/447-checker-inliner3/src/Main.java
+++ b/test/447-checker-inliner3/src/Main.java
@@ -17,8 +17,8 @@
 public class Main {
 
   // CHECK-START: int Main.inlineIfThenElse() inliner (before)
-  // CHECK-DAG:     [[Invoke:i\d+]]  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ [[Invoke]] ]
+  // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   // CHECK-START: int Main.inlineIfThenElse() inliner (after)
   // CHECK-NOT:                      InvokeStaticOrDirect
diff --git a/test/454-get-vreg/get_vreg_jni.cc b/test/454-get-vreg/get_vreg_jni.cc
index 6b4bc11..0ef2964 100644
--- a/test/454-get-vreg/get_vreg_jni.cc
+++ b/test/454-get-vreg/get_vreg_jni.cc
@@ -29,7 +29,9 @@
  public:
   TestVisitor(Thread* thread, Context* context, mirror::Object* this_value)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(thread, context), this_value_(this_value), found_method_index_(0) {}
+      : StackVisitor(thread, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+        this_value_(this_value),
+        found_method_index_(0) {}
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     mirror::ArtMethod* m = GetMethod();
diff --git a/test/455-set-vreg/set_vreg_jni.cc b/test/455-set-vreg/set_vreg_jni.cc
index 0a83ac0..dffbfa4 100644
--- a/test/455-set-vreg/set_vreg_jni.cc
+++ b/test/455-set-vreg/set_vreg_jni.cc
@@ -29,7 +29,8 @@
  public:
   TestVisitor(Thread* thread, Context* context, mirror::Object* this_value)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(thread, context), this_value_(this_value) {}
+      : StackVisitor(thread, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+        this_value_(this_value) {}
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     mirror::ArtMethod* m = GetMethod();
diff --git a/test/457-regs/regs_jni.cc b/test/457-regs/regs_jni.cc
index 1b32348..193ab9d 100644
--- a/test/457-regs/regs_jni.cc
+++ b/test/457-regs/regs_jni.cc
@@ -29,7 +29,7 @@
  public:
   TestVisitor(Thread* thread, Context* context)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(thread, context) {}
+      : StackVisitor(thread, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames) {}
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     mirror::ArtMethod* m = GetMethod();
diff --git a/test/458-checker-instruction-simplification/src/Main.java b/test/458-checker-instruction-simplification/src/Main.java
index efb7b83..742210c 100644
--- a/test/458-checker-instruction-simplification/src/Main.java
+++ b/test/458-checker-instruction-simplification/src/Main.java
@@ -51,14 +51,14 @@
    */
 
   // CHECK-START: long Main.Add0(long) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:j\d+]]     ParameterValue
-  // CHECK-DAG:     [[Const0:j\d+]]  LongConstant 0
-  // CHECK-DAG:     [[Add:j\d+]]     Add [ [[Const0]] [[Arg]] ]
-  // CHECK-DAG:                      Return [ [[Add]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>     ParameterValue
+  // CHECK-DAG:     <<Const0:j\d+>>  LongConstant 0
+  // CHECK-DAG:     <<Add:j\d+>>     Add [<<Const0>>,<<Arg>>]
+  // CHECK-DAG:                      Return [<<Add>>]
 
   // CHECK-START: long Main.Add0(long) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:j\d+]]     ParameterValue
-  // CHECK-DAG:                      Return [ [[Arg]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>     ParameterValue
+  // CHECK-DAG:                      Return [<<Arg>>]
 
   // CHECK-START: long Main.Add0(long) instruction_simplifier (after)
   // CHECK-NOT:                        Add
@@ -68,14 +68,14 @@
   }
 
   // CHECK-START: int Main.AndAllOnes(int) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[ConstF:i\d+]]  IntConstant -1
-  // CHECK-DAG:     [[And:i\d+]]     And [ [[Arg]] [[ConstF]] ]
-  // CHECK-DAG:                      Return [ [[And]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<ConstF:i\d+>>  IntConstant -1
+  // CHECK-DAG:     <<And:i\d+>>     And [<<Arg>>,<<ConstF>>]
+  // CHECK-DAG:                      Return [<<And>>]
 
   // CHECK-START: int Main.AndAllOnes(int) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:i\d+]]     ParameterValue
-  // CHECK-DAG:                      Return [ [[Arg]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>     ParameterValue
+  // CHECK-DAG:                      Return [<<Arg>>]
 
   // CHECK-START: int Main.AndAllOnes(int) instruction_simplifier (after)
   // CHECK-NOT:                      And
@@ -85,14 +85,14 @@
   }
 
   // CHECK-START: long Main.Div1(long) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:j\d+]]     ParameterValue
-  // CHECK-DAG:     [[Const1:j\d+]]  LongConstant 1
-  // CHECK-DAG:     [[Div:j\d+]]     Div [ [[Arg]] [[Const1]] ]
-  // CHECK-DAG:                      Return [ [[Div]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>     ParameterValue
+  // CHECK-DAG:     <<Const1:j\d+>>  LongConstant 1
+  // CHECK-DAG:     <<Div:j\d+>>     Div [<<Arg>>,<<Const1>>]
+  // CHECK-DAG:                      Return [<<Div>>]
 
   // CHECK-START: long Main.Div1(long) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:j\d+]]     ParameterValue
-  // CHECK-DAG:                      Return [ [[Arg]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>     ParameterValue
+  // CHECK-DAG:                      Return [<<Arg>>]
 
   // CHECK-START: long Main.Div1(long) instruction_simplifier (after)
   // CHECK-NOT:                      Div
@@ -102,15 +102,15 @@
   }
 
   // CHECK-START: int Main.DivN1(int) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[ConstN1:i\d+]]  IntConstant -1
-  // CHECK-DAG:     [[Div:i\d+]]      Div [ [[Arg]] [[ConstN1]] ]
-  // CHECK-DAG:                       Return [ [[Div]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<ConstN1:i\d+>>  IntConstant -1
+  // CHECK-DAG:     <<Div:i\d+>>      Div [<<Arg>>,<<ConstN1>>]
+  // CHECK-DAG:                       Return [<<Div>>]
 
   // CHECK-START: int Main.DivN1(int) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Neg:i\d+]]      Neg [ [[Arg]] ]
-  // CHECK-DAG:                       Return [ [[Neg]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Arg>>]
+  // CHECK-DAG:                       Return [<<Neg>>]
 
   // CHECK-START: int Main.DivN1(int) instruction_simplifier (after)
   // CHECK-NOT:                       Div
@@ -120,14 +120,14 @@
   }
 
   // CHECK-START: long Main.Mul1(long) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:j\d+]]     ParameterValue
-  // CHECK-DAG:     [[Const1:j\d+]]  LongConstant 1
-  // CHECK-DAG:     [[Mul:j\d+]]     Mul [ [[Arg]] [[Const1]] ]
-  // CHECK-DAG:                      Return [ [[Mul]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>     ParameterValue
+  // CHECK-DAG:     <<Const1:j\d+>>  LongConstant 1
+  // CHECK-DAG:     <<Mul:j\d+>>     Mul [<<Arg>>,<<Const1>>]
+  // CHECK-DAG:                      Return [<<Mul>>]
 
   // CHECK-START: long Main.Mul1(long) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:j\d+]]     ParameterValue
-  // CHECK-DAG:                      Return [ [[Arg]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>     ParameterValue
+  // CHECK-DAG:                      Return [<<Arg>>]
 
   // CHECK-START: long Main.Mul1(long) instruction_simplifier (after)
   // CHECK-NOT:                       Mul
@@ -137,15 +137,15 @@
   }
 
   // CHECK-START: int Main.MulN1(int) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[ConstN1:i\d+]]  IntConstant -1
-  // CHECK-DAG:     [[Mul:i\d+]]      Mul [ [[Arg]] [[ConstN1]] ]
-  // CHECK-DAG:                       Return [ [[Mul]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<ConstN1:i\d+>>  IntConstant -1
+  // CHECK-DAG:     <<Mul:i\d+>>      Mul [<<Arg>>,<<ConstN1>>]
+  // CHECK-DAG:                       Return [<<Mul>>]
 
   // CHECK-START: int Main.MulN1(int) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Neg:i\d+]]      Neg [ [[Arg]] ]
-  // CHECK-DAG:                       Return [ [[Neg]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Arg>>]
+  // CHECK-DAG:                       Return [<<Neg>>]
 
   // CHECK-START: int Main.MulN1(int) instruction_simplifier (after)
   // CHECK-NOT:                       Mul
@@ -155,16 +155,16 @@
   }
 
   // CHECK-START: long Main.MulPowerOfTwo128(long) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:j\d+]]       ParameterValue
-  // CHECK-DAG:     [[Const128:j\d+]]  LongConstant 128
-  // CHECK-DAG:     [[Mul:j\d+]]       Mul [ [[Arg]] [[Const128]] ]
-  // CHECK-DAG:                        Return [ [[Mul]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>       ParameterValue
+  // CHECK-DAG:     <<Const128:j\d+>>  LongConstant 128
+  // CHECK-DAG:     <<Mul:j\d+>>       Mul [<<Arg>>,<<Const128>>]
+  // CHECK-DAG:                        Return [<<Mul>>]
 
   // CHECK-START: long Main.MulPowerOfTwo128(long) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:j\d+]]       ParameterValue
-  // CHECK-DAG:     [[Const7:i\d+]]    IntConstant 7
-  // CHECK-DAG:     [[Shl:j\d+]]       Shl [ [[Arg]] [[Const7]] ]
-  // CHECK-DAG:                        Return [ [[Shl]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>       ParameterValue
+  // CHECK-DAG:     <<Const7:i\d+>>    IntConstant 7
+  // CHECK-DAG:     <<Shl:j\d+>>       Shl [<<Arg>>,<<Const7>>]
+  // CHECK-DAG:                        Return [<<Shl>>]
 
   // CHECK-START: long Main.MulPowerOfTwo128(long) instruction_simplifier (after)
   // CHECK-NOT:                        Mul
@@ -174,14 +174,14 @@
   }
 
   // CHECK-START: int Main.Or0(int) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
-  // CHECK-DAG:     [[Or:i\d+]]       Or [ [[Arg]] [[Const0]] ]
-  // CHECK-DAG:                       Return [ [[Or]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:     <<Or:i\d+>>       Or [<<Arg>>,<<Const0>>]
+  // CHECK-DAG:                       Return [<<Or>>]
 
   // CHECK-START: int Main.Or0(int) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:                       Return [ [[Arg]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:                       Return [<<Arg>>]
 
   // CHECK-START: int Main.Or0(int) instruction_simplifier (after)
   // CHECK-NOT:                       Or
@@ -191,13 +191,13 @@
   }
 
   // CHECK-START: long Main.OrSame(long) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:j\d+]]       ParameterValue
-  // CHECK-DAG:     [[Or:j\d+]]        Or [ [[Arg]] [[Arg]] ]
-  // CHECK-DAG:                        Return [ [[Or]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>       ParameterValue
+  // CHECK-DAG:     <<Or:j\d+>>        Or [<<Arg>>,<<Arg>>]
+  // CHECK-DAG:                        Return [<<Or>>]
 
   // CHECK-START: long Main.OrSame(long) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:j\d+]]       ParameterValue
-  // CHECK-DAG:                        Return [ [[Arg]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>       ParameterValue
+  // CHECK-DAG:                        Return [<<Arg>>]
 
   // CHECK-START: long Main.OrSame(long) instruction_simplifier (after)
   // CHECK-NOT:                        Or
@@ -207,14 +207,14 @@
   }
 
   // CHECK-START: int Main.Shl0(int) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
-  // CHECK-DAG:     [[Shl:i\d+]]      Shl [ [[Arg]] [[Const0]] ]
-  // CHECK-DAG:                       Return [ [[Shl]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:     <<Shl:i\d+>>      Shl [<<Arg>>,<<Const0>>]
+  // CHECK-DAG:                       Return [<<Shl>>]
 
   // CHECK-START: int Main.Shl0(int) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:                       Return [ [[Arg]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:                       Return [<<Arg>>]
 
   // CHECK-START: int Main.Shl0(int) instruction_simplifier (after)
   // CHECK-NOT:                       Shl
@@ -224,15 +224,15 @@
   }
 
   // CHECK-START: int Main.Shl1(int) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const1:i\d+]]   IntConstant 1
-  // CHECK-DAG:     [[Shl:i\d+]]      Shl [ [[Arg]] [[Const1]] ]
-  // CHECK-DAG:                       Return [ [[Shl]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  // CHECK-DAG:     <<Shl:i\d+>>      Shl [<<Arg>>,<<Const1>>]
+  // CHECK-DAG:                       Return [<<Shl>>]
 
   // CHECK-START: int Main.Shl1(int) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Add:i\d+]]      Add [ [[Arg]] [[Arg]] ]
-  // CHECK-DAG:                       Return [ [[Add]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Add:i\d+>>      Add [<<Arg>>,<<Arg>>]
+  // CHECK-DAG:                       Return [<<Add>>]
 
   // CHECK-START: int Main.Shl1(int) instruction_simplifier (after)
   // CHECK-NOT:                       Shl
@@ -242,14 +242,14 @@
   }
 
   // CHECK-START: long Main.Shr0(long) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
-  // CHECK-DAG:     [[Shr:j\d+]]      Shr [ [[Arg]] [[Const0]] ]
-  // CHECK-DAG:                       Return [ [[Shr]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:     <<Shr:j\d+>>      Shr [<<Arg>>,<<Const0>>]
+  // CHECK-DAG:                       Return [<<Shr>>]
 
   // CHECK-START: long Main.Shr0(long) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
-  // CHECK-DAG:                       Return [ [[Arg]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  // CHECK-DAG:                       Return [<<Arg>>]
 
   // CHECK-START: long Main.Shr0(long) instruction_simplifier (after)
   // CHECK-NOT:                       Shr
@@ -259,14 +259,14 @@
   }
 
   // CHECK-START: long Main.Sub0(long) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:j\d+]]   LongConstant 0
-  // CHECK-DAG:     [[Sub:j\d+]]      Sub [ [[Arg]] [[Const0]] ]
-  // CHECK-DAG:                       Return [ [[Sub]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
+  // CHECK-DAG:     <<Sub:j\d+>>      Sub [<<Arg>>,<<Const0>>]
+  // CHECK-DAG:                       Return [<<Sub>>]
 
   // CHECK-START: long Main.Sub0(long) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
-  // CHECK-DAG:                       Return [ [[Arg]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  // CHECK-DAG:                       Return [<<Arg>>]
 
   // CHECK-START: long Main.Sub0(long) instruction_simplifier (after)
   // CHECK-NOT:                       Sub
@@ -276,15 +276,15 @@
   }
 
   // CHECK-START: int Main.SubAliasNeg(int) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
-  // CHECK-DAG:     [[Sub:i\d+]]      Sub [ [[Const0]] [[Arg]] ]
-  // CHECK-DAG:                       Return [ [[Sub]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:     <<Sub:i\d+>>      Sub [<<Const0>>,<<Arg>>]
+  // CHECK-DAG:                       Return [<<Sub>>]
 
   // CHECK-START: int Main.SubAliasNeg(int) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Neg:i\d+]]      Neg [ [[Arg]] ]
-  // CHECK-DAG:                       Return [ [[Neg]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Arg>>]
+  // CHECK-DAG:                       Return [<<Neg>>]
 
   // CHECK-START: int Main.SubAliasNeg(int) instruction_simplifier (after)
   // CHECK-NOT:                       Sub
@@ -294,14 +294,14 @@
   }
 
   // CHECK-START: long Main.UShr0(long) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
-  // CHECK-DAG:     [[UShr:j\d+]]     UShr [ [[Arg]] [[Const0]] ]
-  // CHECK-DAG:                       Return [ [[UShr]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:     <<UShr:j\d+>>     UShr [<<Arg>>,<<Const0>>]
+  // CHECK-DAG:                       Return [<<UShr>>]
 
   // CHECK-START: long Main.UShr0(long) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
-  // CHECK-DAG:                       Return [ [[Arg]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  // CHECK-DAG:                       Return [<<Arg>>]
 
   // CHECK-START: long Main.UShr0(long) instruction_simplifier (after)
   // CHECK-NOT:                       UShr
@@ -311,14 +311,14 @@
   }
 
   // CHECK-START: int Main.Xor0(int) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
-  // CHECK-DAG:     [[Xor:i\d+]]      Xor [ [[Arg]] [[Const0]] ]
-  // CHECK-DAG:                       Return [ [[Xor]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:     <<Xor:i\d+>>      Xor [<<Arg>>,<<Const0>>]
+  // CHECK-DAG:                       Return [<<Xor>>]
 
   // CHECK-START: int Main.Xor0(int) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:                       Return [ [[Arg]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:                       Return [<<Arg>>]
 
   // CHECK-START: int Main.Xor0(int) instruction_simplifier (after)
   // CHECK-NOT:                       Xor
@@ -328,15 +328,15 @@
   }
 
   // CHECK-START: int Main.XorAllOnes(int) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[ConstF:i\d+]]   IntConstant -1
-  // CHECK-DAG:     [[Xor:i\d+]]      Xor [ [[Arg]] [[ConstF]] ]
-  // CHECK-DAG:                       Return [ [[Xor]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<ConstF:i\d+>>   IntConstant -1
+  // CHECK-DAG:     <<Xor:i\d+>>      Xor [<<Arg>>,<<ConstF>>]
+  // CHECK-DAG:                       Return [<<Xor>>]
 
   // CHECK-START: int Main.XorAllOnes(int) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Not:i\d+]]      Not [ [[Arg]] ]
-  // CHECK-DAG:                       Return [ [[Not]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Not:i\d+>>      Not [<<Arg>>]
+  // CHECK-DAG:                       Return [<<Not>>]
 
   // CHECK-START: int Main.XorAllOnes(int) instruction_simplifier (after)
   // CHECK-NOT:                       Xor
@@ -353,20 +353,20 @@
    */
 
   // CHECK-START: int Main.AddNegs1(int, int) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg1:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Arg2:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Neg1:i\d+]]     Neg [ [[Arg1]] ]
-  // CHECK-DAG:     [[Neg2:i\d+]]     Neg [ [[Arg2]] ]
-  // CHECK-DAG:     [[Add:i\d+]]      Add [ [[Neg1]] [[Neg2]] ]
-  // CHECK-DAG:                       Return [ [[Add]] ]
+  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Neg1:i\d+>>     Neg [<<Arg1>>]
+  // CHECK-DAG:     <<Neg2:i\d+>>     Neg [<<Arg2>>]
+  // CHECK-DAG:     <<Add:i\d+>>      Add [<<Neg1>>,<<Neg2>>]
+  // CHECK-DAG:                       Return [<<Add>>]
 
   // CHECK-START: int Main.AddNegs1(int, int) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg1:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Arg2:i\d+]]     ParameterValue
+  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
   // CHECK-NOT:                       Neg
-  // CHECK-DAG:     [[Add:i\d+]]      Add [ [[Arg1]] [[Arg2]] ]
-  // CHECK-DAG:     [[Neg:i\d+]]      Neg [ [[Add]] ]
-  // CHECK-DAG:                       Return [ [[Neg]] ]
+  // CHECK-DAG:     <<Add:i\d+>>      Add [<<Arg1>>,<<Arg2>>]
+  // CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Add>>]
+  // CHECK-DAG:                       Return [<<Neg>>]
 
   public static int AddNegs1(int arg1, int arg2) {
     return -arg1 + -arg2;
@@ -384,34 +384,34 @@
    */
 
   // CHECK-START: int Main.AddNegs2(int, int) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg1:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Arg2:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Neg1:i\d+]]     Neg [ [[Arg1]] ]
-  // CHECK-DAG:     [[Neg2:i\d+]]     Neg [ [[Arg2]] ]
-  // CHECK-DAG:     [[Add1:i\d+]]     Add [ [[Neg1]] [[Neg2]] ]
-  // CHECK-DAG:     [[Add2:i\d+]]     Add [ [[Neg1]] [[Neg2]] ]
-  // CHECK-DAG:     [[Or:i\d+]]       Or [ [[Add1]] [[Add2]] ]
-  // CHECK-DAG:                       Return [ [[Or]] ]
+  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Neg1:i\d+>>     Neg [<<Arg1>>]
+  // CHECK-DAG:     <<Neg2:i\d+>>     Neg [<<Arg2>>]
+  // CHECK-DAG:     <<Add1:i\d+>>     Add [<<Neg1>>,<<Neg2>>]
+  // CHECK-DAG:     <<Add2:i\d+>>     Add [<<Neg1>>,<<Neg2>>]
+  // CHECK-DAG:     <<Or:i\d+>>       Or [<<Add1>>,<<Add2>>]
+  // CHECK-DAG:                       Return [<<Or>>]
 
   // CHECK-START: int Main.AddNegs2(int, int) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg1:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Arg2:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Neg1:i\d+]]     Neg [ [[Arg1]] ]
-  // CHECK-DAG:     [[Neg2:i\d+]]     Neg [ [[Arg2]] ]
-  // CHECK-DAG:     [[Add1:i\d+]]     Add [ [[Neg1]] [[Neg2]] ]
-  // CHECK-DAG:     [[Add2:i\d+]]     Add [ [[Neg1]] [[Neg2]] ]
+  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Neg1:i\d+>>     Neg [<<Arg1>>]
+  // CHECK-DAG:     <<Neg2:i\d+>>     Neg [<<Arg2>>]
+  // CHECK-DAG:     <<Add1:i\d+>>     Add [<<Neg1>>,<<Neg2>>]
+  // CHECK-DAG:     <<Add2:i\d+>>     Add [<<Neg1>>,<<Neg2>>]
   // CHECK-NOT:                       Neg
-  // CHECK-DAG:     [[Or:i\d+]]       Or [ [[Add1]] [[Add2]] ]
-  // CHECK-DAG:                       Return [ [[Or]] ]
+  // CHECK-DAG:     <<Or:i\d+>>       Or [<<Add1>>,<<Add2>>]
+  // CHECK-DAG:                       Return [<<Or>>]
 
   // CHECK-START: int Main.AddNegs2(int, int) GVN (after)
-  // CHECK-DAG:     [[Arg1:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Arg2:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Neg1:i\d+]]     Neg [ [[Arg1]] ]
-  // CHECK-DAG:     [[Neg2:i\d+]]     Neg [ [[Arg2]] ]
-  // CHECK-DAG:     [[Add:i\d+]]      Add [ [[Neg1]] [[Neg2]] ]
-  // CHECK-DAG:     [[Or:i\d+]]       Or [ [[Add]] [[Add]] ]
-  // CHECK-DAG:                       Return [ [[Or]] ]
+  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Neg1:i\d+>>     Neg [<<Arg1>>]
+  // CHECK-DAG:     <<Neg2:i\d+>>     Neg [<<Arg2>>]
+  // CHECK-DAG:     <<Add:i\d+>>      Add [<<Neg1>>,<<Neg2>>]
+  // CHECK-DAG:     <<Or:i\d+>>       Or [<<Add>>,<<Add>>]
+  // CHECK-DAG:                       Return [<<Or>>]
 
   public static int AddNegs2(int arg1, int arg2) {
     int temp1 = -arg1;
@@ -429,26 +429,26 @@
 
   // CHECK-START: long Main.AddNegs3(long, long) instruction_simplifier (before)
   // -------------- Arguments and initial negation operations.
-  // CHECK-DAG:     [[Arg1:j\d+]]     ParameterValue
-  // CHECK-DAG:     [[Arg2:j\d+]]     ParameterValue
-  // CHECK-DAG:     [[Neg1:j\d+]]     Neg [ [[Arg1]] ]
-  // CHECK-DAG:     [[Neg2:j\d+]]     Neg [ [[Arg2]] ]
+  // CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
+  // CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
+  // CHECK-DAG:     <<Neg1:j\d+>>     Neg [<<Arg1>>]
+  // CHECK-DAG:     <<Neg2:j\d+>>     Neg [<<Arg2>>]
   // CHECK:                           Goto
   // -------------- Loop
   // CHECK:                           SuspendCheck
-  // CHECK:         [[Add:j\d+]]      Add [ [[Neg1]] [[Neg2]] ]
+  // CHECK:         <<Add:j\d+>>      Add [<<Neg1>>,<<Neg2>>]
   // CHECK:                           Goto
 
   // CHECK-START: long Main.AddNegs3(long, long) instruction_simplifier (after)
   // -------------- Arguments and initial negation operations.
-  // CHECK-DAG:     [[Arg1:j\d+]]     ParameterValue
-  // CHECK-DAG:     [[Arg2:j\d+]]     ParameterValue
-  // CHECK-DAG:     [[Neg1:j\d+]]     Neg [ [[Arg1]] ]
-  // CHECK-DAG:     [[Neg2:j\d+]]     Neg [ [[Arg2]] ]
+  // CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
+  // CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
+  // CHECK-DAG:     <<Neg1:j\d+>>     Neg [<<Arg1>>]
+  // CHECK-DAG:     <<Neg2:j\d+>>     Neg [<<Arg2>>]
   // CHECK:                           Goto
   // -------------- Loop
   // CHECK:                           SuspendCheck
-  // CHECK:         [[Add:j\d+]]      Add [ [[Neg1]] [[Neg2]] ]
+  // CHECK:         <<Add:j\d+>>      Add [<<Neg1>>,<<Neg2>>]
   // CHECK-NOT:                       Neg
   // CHECK:                           Goto
 
@@ -469,17 +469,17 @@
    */
 
   // CHECK-START: long Main.AddNeg1(long, long) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg1:j\d+]]     ParameterValue
-  // CHECK-DAG:     [[Arg2:j\d+]]     ParameterValue
-  // CHECK-DAG:     [[Neg:j\d+]]      Neg [ [[Arg1]] ]
-  // CHECK-DAG:     [[Add:j\d+]]      Add [ [[Neg]] [[Arg2]] ]
-  // CHECK-DAG:                       Return [ [[Add]] ]
+  // CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
+  // CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
+  // CHECK-DAG:     <<Neg:j\d+>>      Neg [<<Arg1>>]
+  // CHECK-DAG:     <<Add:j\d+>>      Add [<<Neg>>,<<Arg2>>]
+  // CHECK-DAG:                       Return [<<Add>>]
 
   // CHECK-START: long Main.AddNeg1(long, long) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg1:j\d+]]     ParameterValue
-  // CHECK-DAG:     [[Arg2:j\d+]]     ParameterValue
-  // CHECK-DAG:     [[Sub:j\d+]]      Sub [ [[Arg2]] [[Arg1]] ]
-  // CHECK-DAG:                       Return [ [[Sub]] ]
+  // CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
+  // CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
+  // CHECK-DAG:     <<Sub:j\d+>>      Sub [<<Arg2>>,<<Arg1>>]
+  // CHECK-DAG:                       Return [<<Sub>>]
 
   // CHECK-START: long Main.AddNeg1(long, long) instruction_simplifier (after)
   // CHECK-NOT:                       Neg
@@ -499,22 +499,22 @@
    */
 
   // CHECK-START: long Main.AddNeg2(long, long) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg1:j\d+]]     ParameterValue
-  // CHECK-DAG:     [[Arg2:j\d+]]     ParameterValue
-  // CHECK-DAG:     [[Neg:j\d+]]      Neg [ [[Arg2]] ]
-  // CHECK-DAG:     [[Add1:j\d+]]     Add [ [[Arg1]] [[Neg]] ]
-  // CHECK-DAG:     [[Add2:j\d+]]     Add [ [[Arg1]] [[Neg]] ]
-  // CHECK-DAG:     [[Res:j\d+]]      Or [ [[Add1]] [[Add2]] ]
-  // CHECK-DAG:                       Return [ [[Res]] ]
+  // CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
+  // CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
+  // CHECK-DAG:     <<Neg:j\d+>>      Neg [<<Arg2>>]
+  // CHECK-DAG:     <<Add1:j\d+>>     Add [<<Arg1>>,<<Neg>>]
+  // CHECK-DAG:     <<Add2:j\d+>>     Add [<<Arg1>>,<<Neg>>]
+  // CHECK-DAG:     <<Res:j\d+>>      Or [<<Add1>>,<<Add2>>]
+  // CHECK-DAG:                       Return [<<Res>>]
 
   // CHECK-START: long Main.AddNeg2(long, long) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg1:j\d+]]     ParameterValue
-  // CHECK-DAG:     [[Arg2:j\d+]]     ParameterValue
-  // CHECK-DAG:     [[Neg:j\d+]]      Neg [ [[Arg2]] ]
-  // CHECK-DAG:     [[Add1:j\d+]]     Add [ [[Arg1]] [[Neg]] ]
-  // CHECK-DAG:     [[Add2:j\d+]]     Add [ [[Arg1]] [[Neg]] ]
-  // CHECK-DAG:     [[Res:j\d+]]      Or [ [[Add1]] [[Add2]] ]
-  // CHECK-DAG:                       Return [ [[Res]] ]
+  // CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
+  // CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
+  // CHECK-DAG:     <<Neg:j\d+>>      Neg [<<Arg2>>]
+  // CHECK-DAG:     <<Add1:j\d+>>     Add [<<Arg1>>,<<Neg>>]
+  // CHECK-DAG:     <<Add2:j\d+>>     Add [<<Arg1>>,<<Neg>>]
+  // CHECK-DAG:     <<Res:j\d+>>      Or [<<Add1>>,<<Add2>>]
+  // CHECK-DAG:                       Return [<<Res>>]
 
   // CHECK-START: long Main.AddNeg2(long, long) instruction_simplifier (after)
   // CHECK-NOT:                       Sub
@@ -530,14 +530,14 @@
    */
 
   // CHECK-START: long Main.NegNeg1(long) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
-  // CHECK-DAG:     [[Neg1:j\d+]]     Neg [ [[Arg]] ]
-  // CHECK-DAG:     [[Neg2:j\d+]]     Neg [ [[Neg1]] ]
-  // CHECK-DAG:                       Return [ [[Neg2]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  // CHECK-DAG:     <<Neg1:j\d+>>     Neg [<<Arg>>]
+  // CHECK-DAG:     <<Neg2:j\d+>>     Neg [<<Neg1>>]
+  // CHECK-DAG:                       Return [<<Neg2>>]
 
   // CHECK-START: long Main.NegNeg1(long) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
-  // CHECK-DAG:                       Return [ [[Arg]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  // CHECK-DAG:                       Return [<<Arg>>]
 
   // CHECK-START: long Main.NegNeg1(long) instruction_simplifier (after)
   // CHECK-NOT:                       Neg
@@ -554,26 +554,26 @@
    */
 
   // CHECK-START: int Main.NegNeg2(int) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Neg1:i\d+]]     Neg [ [[Arg]] ]
-  // CHECK-DAG:     [[Neg2:i\d+]]     Neg [ [[Neg1]] ]
-  // CHECK-DAG:     [[Add:i\d+]]      Add [ [[Neg1]] [[Neg2]] ]
-  // CHECK-DAG:                       Return [ [[Add]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Neg1:i\d+>>     Neg [<<Arg>>]
+  // CHECK-DAG:     <<Neg2:i\d+>>     Neg [<<Neg1>>]
+  // CHECK-DAG:     <<Add:i\d+>>      Add [<<Neg1>>,<<Neg2>>]
+  // CHECK-DAG:                       Return [<<Add>>]
 
   // CHECK-START: int Main.NegNeg2(int) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Sub:i\d+]]      Sub [ [[Arg]] [[Arg]] ]
-  // CHECK-DAG:                       Return [ [[Sub]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Sub:i\d+>>      Sub [<<Arg>>,<<Arg>>]
+  // CHECK-DAG:                       Return [<<Sub>>]
 
   // CHECK-START: int Main.NegNeg2(int) instruction_simplifier (after)
   // CHECK-NOT:                       Neg
   // CHECK-NOT:                       Add
 
   // CHECK-START: int Main.NegNeg2(int) constant_folding_after_inlining (after)
-  // CHECK:         [[Const0:i\d+]]   IntConstant 0
+  // CHECK:         <<Const0:i\d+>>   IntConstant 0
   // CHECK-NOT:                       Neg
   // CHECK-NOT:                       Add
-  // CHECK:                           Return [ [[Const0]] ]
+  // CHECK:                           Return [<<Const0>>]
 
   public static int NegNeg2(int arg) {
     int temp = -arg;
@@ -588,15 +588,15 @@
    */
 
   // CHECK-START: long Main.NegNeg3(long) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:j\d+]]   LongConstant 0
-  // CHECK-DAG:     [[Neg:j\d+]]      Neg [ [[Arg]] ]
-  // CHECK-DAG:     [[Sub:j\d+]]      Sub [ [[Const0]] [[Neg]] ]
-  // CHECK-DAG:                       Return [ [[Sub]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
+  // CHECK-DAG:     <<Neg:j\d+>>      Neg [<<Arg>>]
+  // CHECK-DAG:     <<Sub:j\d+>>      Sub [<<Const0>>,<<Neg>>]
+  // CHECK-DAG:                       Return [<<Sub>>]
 
   // CHECK-START: long Main.NegNeg3(long) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
-  // CHECK-DAG:                       Return [ [[Arg]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  // CHECK-DAG:                       Return [<<Arg>>]
 
   // CHECK-START: long Main.NegNeg3(long) instruction_simplifier (after)
   // CHECK-NOT:                       Neg
@@ -613,17 +613,17 @@
    */
 
   // CHECK-START: int Main.NegSub1(int, int) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg1:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Arg2:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Sub:i\d+]]      Sub [ [[Arg1]] [[Arg2]] ]
-  // CHECK-DAG:     [[Neg:i\d+]]      Neg [ [[Sub]] ]
-  // CHECK-DAG:                       Return [ [[Neg]] ]
+  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Sub:i\d+>>      Sub [<<Arg1>>,<<Arg2>>]
+  // CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Sub>>]
+  // CHECK-DAG:                       Return [<<Neg>>]
 
   // CHECK-START: int Main.NegSub1(int, int) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg1:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Arg2:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Sub:i\d+]]      Sub [ [[Arg2]] [[Arg1]] ]
-  // CHECK-DAG:                       Return [ [[Sub]] ]
+  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Sub:i\d+>>      Sub [<<Arg2>>,<<Arg1>>]
+  // CHECK-DAG:                       Return [<<Sub>>]
 
   // CHECK-START: int Main.NegSub1(int, int) instruction_simplifier (after)
   // CHECK-NOT:                       Neg
@@ -643,22 +643,22 @@
    */
 
   // CHECK-START: int Main.NegSub2(int, int) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg1:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Arg2:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Sub:i\d+]]      Sub [ [[Arg1]] [[Arg2]] ]
-  // CHECK-DAG:     [[Neg1:i\d+]]     Neg [ [[Sub]] ]
-  // CHECK-DAG:     [[Neg2:i\d+]]     Neg [ [[Sub]] ]
-  // CHECK-DAG:     [[Or:i\d+]]       Or [ [[Neg1]] [[Neg2]] ]
-  // CHECK-DAG:                       Return [ [[Or]] ]
+  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Sub:i\d+>>      Sub [<<Arg1>>,<<Arg2>>]
+  // CHECK-DAG:     <<Neg1:i\d+>>     Neg [<<Sub>>]
+  // CHECK-DAG:     <<Neg2:i\d+>>     Neg [<<Sub>>]
+  // CHECK-DAG:     <<Or:i\d+>>       Or [<<Neg1>>,<<Neg2>>]
+  // CHECK-DAG:                       Return [<<Or>>]
 
   // CHECK-START: int Main.NegSub2(int, int) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg1:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Arg2:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Sub:i\d+]]      Sub [ [[Arg1]] [[Arg2]] ]
-  // CHECK-DAG:     [[Neg1:i\d+]]     Neg [ [[Sub]] ]
-  // CHECK-DAG:     [[Neg2:i\d+]]     Neg [ [[Sub]] ]
-  // CHECK-DAG:     [[Or:i\d+]]       Or [ [[Neg1]] [[Neg2]] ]
-  // CHECK-DAG:                       Return [ [[Or]] ]
+  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Sub:i\d+>>      Sub [<<Arg1>>,<<Arg2>>]
+  // CHECK-DAG:     <<Neg1:i\d+>>     Neg [<<Sub>>]
+  // CHECK-DAG:     <<Neg2:i\d+>>     Neg [<<Sub>>]
+  // CHECK-DAG:     <<Or:i\d+>>       Or [<<Neg1>>,<<Neg2>>]
+  // CHECK-DAG:                       Return [<<Or>>]
 
   public static int NegSub2(int arg1, int arg2) {
     int temp = arg1 - arg2;
@@ -671,15 +671,15 @@
    */
 
   // CHECK-START: long Main.NotNot1(long) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
-  // CHECK-DAG:     [[ConstF1:j\d+]]  LongConstant -1
-  // CHECK-DAG:     [[Xor1:j\d+]]     Xor [ [[Arg]] [[ConstF1]] ]
-  // CHECK-DAG:     [[Xor2:j\d+]]     Xor [ [[Xor1]] [[ConstF1]] ]
-  // CHECK-DAG:                       Return [ [[Xor2]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  // CHECK-DAG:     <<ConstF1:j\d+>>  LongConstant -1
+  // CHECK-DAG:     <<Xor1:j\d+>>     Xor [<<Arg>>,<<ConstF1>>]
+  // CHECK-DAG:     <<Xor2:j\d+>>     Xor [<<Xor1>>,<<ConstF1>>]
+  // CHECK-DAG:                       Return [<<Xor2>>]
 
   // CHECK-START: long Main.NotNot1(long) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
-  // CHECK-DAG:                       Return [ [[Arg]] ]
+  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  // CHECK-DAG:                       Return [<<Arg>>]
 
   // CHECK-START: long Main.NotNot1(long) instruction_simplifier (after)
   // CHECK-NOT:                       Xor
@@ -689,18 +689,18 @@
   }
 
   // CHECK-START: int Main.NotNot2(int) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[ConstF1:i\d+]]  IntConstant -1
-  // CHECK-DAG:     [[Xor1:i\d+]]     Xor [ [[Arg]] [[ConstF1]] ]
-  // CHECK-DAG:     [[Xor2:i\d+]]     Xor [ [[Xor1]] [[ConstF1]] ]
-  // CHECK-DAG:     [[Add:i\d+]]      Add [ [[Xor1]] [[Xor2]] ]
-  // CHECK-DAG:                       Return [ [[Add]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<ConstF1:i\d+>>  IntConstant -1
+  // CHECK-DAG:     <<Xor1:i\d+>>     Xor [<<Arg>>,<<ConstF1>>]
+  // CHECK-DAG:     <<Xor2:i\d+>>     Xor [<<Xor1>>,<<ConstF1>>]
+  // CHECK-DAG:     <<Add:i\d+>>      Add [<<Xor1>>,<<Xor2>>]
+  // CHECK-DAG:                       Return [<<Add>>]
 
   // CHECK-START: int Main.NotNot2(int) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
-  // CHECK-DAG:     [[Not:i\d+]]      Not [ [[Arg]] ]
-  // CHECK-DAG:     [[Add:i\d+]]      Add [ [[Not]] [[Arg]] ]
-  // CHECK-DAG:                       Return [ [[Add]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  // CHECK-DAG:     <<Not:i\d+>>      Not [<<Arg>>]
+  // CHECK-DAG:     <<Add:i\d+>>      Add [<<Not>>,<<Arg>>]
+  // CHECK-DAG:                       Return [<<Add>>]
 
   // CHECK-START: int Main.NotNot2(int) instruction_simplifier (after)
   // CHECK-NOT:                       Xor
@@ -716,18 +716,18 @@
    */
 
   // CHECK-START: int Main.SubNeg1(int, int) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg1:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Arg2:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Neg:i\d+]]      Neg [ [[Arg1]] ]
-  // CHECK-DAG:     [[Sub:i\d+]]      Sub [ [[Neg]] [[Arg2]] ]
-  // CHECK-DAG:                       Return [ [[Sub]] ]
+  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Arg1>>]
+  // CHECK-DAG:     <<Sub:i\d+>>      Sub [<<Neg>>,<<Arg2>>]
+  // CHECK-DAG:                       Return [<<Sub>>]
 
   // CHECK-START: int Main.SubNeg1(int, int) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg1:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Arg2:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Add:i\d+]]      Add [ [[Arg1]] [[Arg2]] ]
-  // CHECK-DAG:     [[Neg:i\d+]]      Neg [ [[Add]] ]
-  // CHECK-DAG:                       Return [ [[Neg]] ]
+  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Add:i\d+>>      Add [<<Arg1>>,<<Arg2>>]
+  // CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Add>>]
+  // CHECK-DAG:                       Return [<<Neg>>]
 
   // CHECK-START: int Main.SubNeg1(int, int) instruction_simplifier (after)
   // CHECK-NOT:                       Sub
@@ -747,22 +747,22 @@
    */
 
   // CHECK-START: int Main.SubNeg2(int, int) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg1:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Arg2:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Neg:i\d+]]      Neg [ [[Arg1]] ]
-  // CHECK-DAG:     [[Sub1:i\d+]]     Sub [ [[Neg]] [[Arg2]] ]
-  // CHECK-DAG:     [[Sub2:i\d+]]     Sub [ [[Neg]] [[Arg2]] ]
-  // CHECK-DAG:     [[Or:i\d+]]       Or [ [[Sub1]] [[Sub2]] ]
-  // CHECK-DAG:                       Return [ [[Or]] ]
+  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Arg1>>]
+  // CHECK-DAG:     <<Sub1:i\d+>>     Sub [<<Neg>>,<<Arg2>>]
+  // CHECK-DAG:     <<Sub2:i\d+>>     Sub [<<Neg>>,<<Arg2>>]
+  // CHECK-DAG:     <<Or:i\d+>>       Or [<<Sub1>>,<<Sub2>>]
+  // CHECK-DAG:                       Return [<<Or>>]
 
   // CHECK-START: int Main.SubNeg2(int, int) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg1:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Arg2:i\d+]]     ParameterValue
-  // CHECK-DAG:     [[Neg:i\d+]]      Neg [ [[Arg1]] ]
-  // CHECK-DAG:     [[Sub1:i\d+]]     Sub [ [[Neg]] [[Arg2]] ]
-  // CHECK-DAG:     [[Sub2:i\d+]]     Sub [ [[Neg]] [[Arg2]] ]
-  // CHECK-DAG:     [[Or:i\d+]]       Or [ [[Sub1]] [[Sub2]] ]
-  // CHECK-DAG:                       Return [ [[Or]] ]
+  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  // CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Arg1>>]
+  // CHECK-DAG:     <<Sub1:i\d+>>     Sub [<<Neg>>,<<Arg2>>]
+  // CHECK-DAG:     <<Sub2:i\d+>>     Sub [<<Neg>>,<<Arg2>>]
+  // CHECK-DAG:     <<Or:i\d+>>       Or [<<Sub1>>,<<Sub2>>]
+  // CHECK-DAG:                       Return [<<Or>>]
 
   // CHECK-START: int Main.SubNeg2(int, int) instruction_simplifier (after)
   // CHECK-NOT:                       Add
@@ -781,24 +781,24 @@
 
   // CHECK-START: long Main.SubNeg3(long, long) instruction_simplifier (before)
   // -------------- Arguments and initial negation operation.
-  // CHECK-DAG:     [[Arg1:j\d+]]     ParameterValue
-  // CHECK-DAG:     [[Arg2:j\d+]]     ParameterValue
-  // CHECK-DAG:     [[Neg:j\d+]]      Neg [ [[Arg1]] ]
+  // CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
+  // CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
+  // CHECK-DAG:     <<Neg:j\d+>>      Neg [<<Arg1>>]
   // CHECK:                           Goto
   // -------------- Loop
   // CHECK:                           SuspendCheck
-  // CHECK:         [[Sub:j\d+]]      Sub [ [[Neg]] [[Arg2]] ]
+  // CHECK:         <<Sub:j\d+>>      Sub [<<Neg>>,<<Arg2>>]
   // CHECK:                           Goto
 
   // CHECK-START: long Main.SubNeg3(long, long) instruction_simplifier (after)
   // -------------- Arguments and initial negation operation.
-  // CHECK-DAG:     [[Arg1:j\d+]]     ParameterValue
-  // CHECK-DAG:     [[Arg2:j\d+]]     ParameterValue
-  // CHECK-DAG:     [[Neg:j\d+]]      Neg [ [[Arg1]] ]
+  // CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
+  // CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
+  // CHECK-DAG:     <<Neg:j\d+>>      Neg [<<Arg1>>]
   // CHECK-DAG:                       Goto
   // -------------- Loop
   // CHECK:                           SuspendCheck
-  // CHECK:         [[Sub:j\d+]]      Sub [ [[Neg]] [[Arg2]] ]
+  // CHECK:         <<Sub:j\d+>>      Sub [<<Neg>>,<<Arg2>>]
   // CHECK-NOT:                       Neg
   // CHECK:                           Goto
 
@@ -812,116 +812,116 @@
   }
 
   // CHECK-START: int Main.EqualTrueRhs(boolean) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:z\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const1:i\d+]]   IntConstant 1
-  // CHECK-DAG:     [[Cond:z\d+]]     Equal [ [[Arg]] [[Const1]] ]
-  // CHECK-DAG:                       If [ [[Cond]] ]
+  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  // CHECK-DAG:     <<Cond:z\d+>>     Equal [<<Arg>>,<<Const1>>]
+  // CHECK-DAG:                       If [<<Cond>>]
 
   // CHECK-START: int Main.EqualTrueRhs(boolean) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:z\d+]]      ParameterValue
-  // CHECK-DAG:                       If [ [[Arg]] ]
+  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  // CHECK-DAG:                       If [<<Arg>>]
 
   public static int EqualTrueRhs(boolean arg) {
     return (arg != true) ? 3 : 5;
   }
 
   // CHECK-START: int Main.EqualTrueLhs(boolean) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:z\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const1:i\d+]]   IntConstant 1
-  // CHECK-DAG:     [[Cond:z\d+]]     Equal [ [[Const1]] [[Arg]] ]
-  // CHECK-DAG:                       If [ [[Cond]] ]
+  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  // CHECK-DAG:     <<Cond:z\d+>>     Equal [<<Const1>>,<<Arg>>]
+  // CHECK-DAG:                       If [<<Cond>>]
 
   // CHECK-START: int Main.EqualTrueLhs(boolean) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:z\d+]]      ParameterValue
-  // CHECK-DAG:                       If [ [[Arg]] ]
+  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  // CHECK-DAG:                       If [<<Arg>>]
 
   public static int EqualTrueLhs(boolean arg) {
     return (true != arg) ? 3 : 5;
   }
 
   // CHECK-START: int Main.EqualFalseRhs(boolean) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:z\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
-  // CHECK-DAG:     [[Cond:z\d+]]     Equal [ [[Arg]] [[Const0]] ]
-  // CHECK-DAG:                       If [ [[Cond]] ]
+  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:     <<Cond:z\d+>>     Equal [<<Arg>>,<<Const0>>]
+  // CHECK-DAG:                       If [<<Cond>>]
 
   // CHECK-START: int Main.EqualFalseRhs(boolean) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:z\d+]]      ParameterValue
-  // CHECK-DAG:     [[NotArg:z\d+]]   BooleanNot [ [[Arg]] ]
-  // CHECK-DAG:                       If [ [[NotArg]] ]
+  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  // CHECK-DAG:     <<NotArg:z\d+>>   BooleanNot [<<Arg>>]
+  // CHECK-DAG:                       If [<<NotArg>>]
 
   public static int EqualFalseRhs(boolean arg) {
     return (arg != false) ? 3 : 5;
   }
 
   // CHECK-START: int Main.EqualFalseLhs(boolean) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:z\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
-  // CHECK-DAG:     [[Cond:z\d+]]     Equal [ [[Const0]] [[Arg]] ]
-  // CHECK-DAG:                       If [ [[Cond]] ]
+  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:     <<Cond:z\d+>>     Equal [<<Const0>>,<<Arg>>]
+  // CHECK-DAG:                       If [<<Cond>>]
 
   // CHECK-START: int Main.EqualFalseLhs(boolean) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:z\d+]]      ParameterValue
-  // CHECK-DAG:     [[NotArg:z\d+]]   BooleanNot [ [[Arg]] ]
-  // CHECK-DAG:                       If [ [[NotArg]] ]
+  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  // CHECK-DAG:     <<NotArg:z\d+>>   BooleanNot [<<Arg>>]
+  // CHECK-DAG:                       If [<<NotArg>>]
 
   public static int EqualFalseLhs(boolean arg) {
     return (false != arg) ? 3 : 5;
   }
 
   // CHECK-START: int Main.NotEqualTrueRhs(boolean) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:z\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const1:i\d+]]   IntConstant 1
-  // CHECK-DAG:     [[Cond:z\d+]]     NotEqual [ [[Arg]] [[Const1]] ]
-  // CHECK-DAG:                       If [ [[Cond]] ]
+  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  // CHECK-DAG:     <<Cond:z\d+>>     NotEqual [<<Arg>>,<<Const1>>]
+  // CHECK-DAG:                       If [<<Cond>>]
 
   // CHECK-START: int Main.NotEqualTrueRhs(boolean) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:z\d+]]      ParameterValue
-  // CHECK-DAG:     [[NotArg:z\d+]]   BooleanNot [ [[Arg]] ]
-  // CHECK-DAG:                       If [ [[NotArg]] ]
+  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  // CHECK-DAG:     <<NotArg:z\d+>>   BooleanNot [<<Arg>>]
+  // CHECK-DAG:                       If [<<NotArg>>]
 
   public static int NotEqualTrueRhs(boolean arg) {
     return (arg == true) ? 3 : 5;
   }
 
   // CHECK-START: int Main.NotEqualTrueLhs(boolean) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:z\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const1:i\d+]]   IntConstant 1
-  // CHECK-DAG:     [[Cond:z\d+]]     NotEqual [ [[Const1]] [[Arg]] ]
-  // CHECK-DAG:                       If [ [[Cond]] ]
+  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  // CHECK-DAG:     <<Cond:z\d+>>     NotEqual [<<Const1>>,<<Arg>>]
+  // CHECK-DAG:                       If [<<Cond>>]
 
   // CHECK-START: int Main.NotEqualTrueLhs(boolean) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:z\d+]]      ParameterValue
-  // CHECK-DAG:     [[NotArg:z\d+]]   BooleanNot [ [[Arg]] ]
-  // CHECK-DAG:                       If [ [[NotArg]] ]
+  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  // CHECK-DAG:     <<NotArg:z\d+>>   BooleanNot [<<Arg>>]
+  // CHECK-DAG:                       If [<<NotArg>>]
 
   public static int NotEqualTrueLhs(boolean arg) {
     return (true == arg) ? 3 : 5;
   }
 
   // CHECK-START: int Main.NotEqualFalseRhs(boolean) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:z\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
-  // CHECK-DAG:     [[Cond:z\d+]]     NotEqual [ [[Arg]] [[Const0]] ]
-  // CHECK-DAG:                       If [ [[Cond]] ]
+  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:     <<Cond:z\d+>>     NotEqual [<<Arg>>,<<Const0>>]
+  // CHECK-DAG:                       If [<<Cond>>]
 
   // CHECK-START: int Main.NotEqualFalseRhs(boolean) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:z\d+]]      ParameterValue
-  // CHECK-DAG:                       If [ [[Arg]] ]
+  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  // CHECK-DAG:                       If [<<Arg>>]
 
   public static int NotEqualFalseRhs(boolean arg) {
     return (arg == false) ? 3 : 5;
   }
 
   // CHECK-START: int Main.NotEqualFalseLhs(boolean) instruction_simplifier (before)
-  // CHECK-DAG:     [[Arg:z\d+]]      ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
-  // CHECK-DAG:     [[Cond:z\d+]]     NotEqual [ [[Const0]] [[Arg]] ]
-  // CHECK-DAG:                       If [ [[Cond]] ]
+  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:     <<Cond:z\d+>>     NotEqual [<<Const0>>,<<Arg>>]
+  // CHECK-DAG:                       If [<<Cond>>]
 
   // CHECK-START: int Main.NotEqualFalseLhs(boolean) instruction_simplifier (after)
-  // CHECK-DAG:     [[Arg:z\d+]]      ParameterValue
-  // CHECK-DAG:                       If [ [[Arg]] ]
+  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  // CHECK-DAG:                       If [<<Arg>>]
 
   public static int NotEqualFalseLhs(boolean arg) {
     return (false == arg) ? 3 : 5;
@@ -934,15 +934,15 @@
    */
 
   // CHECK-START: boolean Main.NotNotBool(boolean) instruction_simplifier_after_types (before)
-  // CHECK-DAG:     [[Arg:z\d+]]       ParameterValue
-  // CHECK-DAG:     [[NotArg:z\d+]]    BooleanNot [ [[Arg]] ]
-  // CHECK-DAG:     [[NotNotArg:z\d+]] BooleanNot [ [[NotArg]] ]
-  // CHECK-DAG:                        Return [ [[NotNotArg]] ]
+  // CHECK-DAG:     <<Arg:z\d+>>       ParameterValue
+  // CHECK-DAG:     <<NotArg:z\d+>>    BooleanNot [<<Arg>>]
+  // CHECK-DAG:     <<NotNotArg:z\d+>> BooleanNot [<<NotArg>>]
+  // CHECK-DAG:                        Return [<<NotNotArg>>]
 
   // CHECK-START: boolean Main.NotNotBool(boolean) instruction_simplifier_after_types (after)
-  // CHECK-DAG:     [[Arg:z\d+]]       ParameterValue
-  // CHECK-DAG:                        BooleanNot [ [[Arg]] ]
-  // CHECK-DAG:                        Return [ [[Arg]] ]
+  // CHECK-DAG:     <<Arg:z\d+>>       ParameterValue
+  // CHECK-DAG:                        BooleanNot [<<Arg>>]
+  // CHECK-DAG:                        Return [<<Arg>>]
 
   // CHECK-START: boolean Main.NotNotBool(boolean) instruction_simplifier_after_types (after)
   // CHECK:                            BooleanNot
@@ -957,16 +957,16 @@
   }
 
   // CHECK-START: float Main.Div2(float) instruction_simplifier (before)
-  // CHECK-DAG:      [[Arg:f\d+]]      ParameterValue
-  // CHECK-DAG:      [[Const2:f\d+]]   FloatConstant 2
-  // CHECK-DAG:      [[Div:f\d+]]      Div [ [[Arg]] [[Const2]] ]
-  // CHECK-DAG:                        Return [ [[Div]] ]
+  // CHECK-DAG:      <<Arg:f\d+>>      ParameterValue
+  // CHECK-DAG:      <<Const2:f\d+>>   FloatConstant 2
+  // CHECK-DAG:      <<Div:f\d+>>      Div [<<Arg>>,<<Const2>>]
+  // CHECK-DAG:                        Return [<<Div>>]
 
   // CHECK-START: float Main.Div2(float) instruction_simplifier (after)
-  // CHECK-DAG:      [[Arg:f\d+]]      ParameterValue
-  // CHECK-DAG:      [[ConstP5:f\d+]]  FloatConstant 0.5
-  // CHECK-DAG:      [[Mul:f\d+]]      Mul [ [[Arg]] [[ConstP5]] ]
-  // CHECK-DAG:                        Return [ [[Mul]] ]
+  // CHECK-DAG:      <<Arg:f\d+>>      ParameterValue
+  // CHECK-DAG:      <<ConstP5:f\d+>>  FloatConstant 0.5
+  // CHECK-DAG:      <<Mul:f\d+>>      Mul [<<Arg>>,<<ConstP5>>]
+  // CHECK-DAG:                        Return [<<Mul>>]
 
   // CHECK-START: float Main.Div2(float) instruction_simplifier (after)
   // CHECK-NOT:                        Div
@@ -976,16 +976,16 @@
   }
 
   // CHECK-START: double Main.Div2(double) instruction_simplifier (before)
-  // CHECK-DAG:      [[Arg:d\d+]]      ParameterValue
-  // CHECK-DAG:      [[Const2:d\d+]]   DoubleConstant 2
-  // CHECK-DAG:      [[Div:d\d+]]      Div [ [[Arg]] [[Const2]] ]
-  // CHECK-DAG:                        Return [ [[Div]] ]
+  // CHECK-DAG:      <<Arg:d\d+>>      ParameterValue
+  // CHECK-DAG:      <<Const2:d\d+>>   DoubleConstant 2
+  // CHECK-DAG:      <<Div:d\d+>>      Div [<<Arg>>,<<Const2>>]
+  // CHECK-DAG:                        Return [<<Div>>]
 
   // CHECK-START: double Main.Div2(double) instruction_simplifier (after)
-  // CHECK-DAG:      [[Arg:d\d+]]      ParameterValue
-  // CHECK-DAG:      [[ConstP5:d\d+]]  DoubleConstant 0.5
-  // CHECK-DAG:      [[Mul:d\d+]]      Mul [ [[Arg]] [[ConstP5]] ]
-  // CHECK-DAG:                        Return [ [[Mul]] ]
+  // CHECK-DAG:      <<Arg:d\d+>>      ParameterValue
+  // CHECK-DAG:      <<ConstP5:d\d+>>  DoubleConstant 0.5
+  // CHECK-DAG:      <<Mul:d\d+>>      Mul [<<Arg>>,<<ConstP5>>]
+  // CHECK-DAG:                        Return [<<Mul>>]
 
   // CHECK-START: double Main.Div2(double) instruction_simplifier (after)
   // CHECK-NOT:                        Div
@@ -994,16 +994,16 @@
   }
 
   // CHECK-START: float Main.DivMP25(float) instruction_simplifier (before)
-  // CHECK-DAG:      [[Arg:f\d+]]      ParameterValue
-  // CHECK-DAG:      [[ConstMP25:f\d+]]   FloatConstant -0.25
-  // CHECK-DAG:      [[Div:f\d+]]      Div [ [[Arg]] [[ConstMP25]] ]
-  // CHECK-DAG:                        Return [ [[Div]] ]
+  // CHECK-DAG:      <<Arg:f\d+>>      ParameterValue
+  // CHECK-DAG:      <<ConstMP25:f\d+>>   FloatConstant -0.25
+  // CHECK-DAG:      <<Div:f\d+>>      Div [<<Arg>>,<<ConstMP25>>]
+  // CHECK-DAG:                        Return [<<Div>>]
 
   // CHECK-START: float Main.DivMP25(float) instruction_simplifier (after)
-  // CHECK-DAG:      [[Arg:f\d+]]      ParameterValue
-  // CHECK-DAG:      [[ConstM4:f\d+]]  FloatConstant -4
-  // CHECK-DAG:      [[Mul:f\d+]]      Mul [ [[Arg]] [[ConstM4]] ]
-  // CHECK-DAG:                        Return [ [[Mul]] ]
+  // CHECK-DAG:      <<Arg:f\d+>>      ParameterValue
+  // CHECK-DAG:      <<ConstM4:f\d+>>  FloatConstant -4
+  // CHECK-DAG:      <<Mul:f\d+>>      Mul [<<Arg>>,<<ConstM4>>]
+  // CHECK-DAG:                        Return [<<Mul>>]
 
   // CHECK-START: float Main.DivMP25(float) instruction_simplifier (after)
   // CHECK-NOT:                        Div
@@ -1013,16 +1013,16 @@
   }
 
   // CHECK-START: double Main.DivMP25(double) instruction_simplifier (before)
-  // CHECK-DAG:      [[Arg:d\d+]]      ParameterValue
-  // CHECK-DAG:      [[ConstMP25:d\d+]]   DoubleConstant -0.25
-  // CHECK-DAG:      [[Div:d\d+]]      Div [ [[Arg]] [[ConstMP25]] ]
-  // CHECK-DAG:                        Return [ [[Div]] ]
+  // CHECK-DAG:      <<Arg:d\d+>>      ParameterValue
+  // CHECK-DAG:      <<ConstMP25:d\d+>>   DoubleConstant -0.25
+  // CHECK-DAG:      <<Div:d\d+>>      Div [<<Arg>>,<<ConstMP25>>]
+  // CHECK-DAG:                        Return [<<Div>>]
 
   // CHECK-START: double Main.DivMP25(double) instruction_simplifier (after)
-  // CHECK-DAG:      [[Arg:d\d+]]      ParameterValue
-  // CHECK-DAG:      [[ConstM4:d\d+]]  DoubleConstant -4
-  // CHECK-DAG:      [[Mul:d\d+]]      Mul [ [[Arg]] [[ConstM4]] ]
-  // CHECK-DAG:                        Return [ [[Mul]] ]
+  // CHECK-DAG:      <<Arg:d\d+>>      ParameterValue
+  // CHECK-DAG:      <<ConstM4:d\d+>>  DoubleConstant -4
+  // CHECK-DAG:      <<Mul:d\d+>>      Mul [<<Arg>>,<<ConstM4>>]
+  // CHECK-DAG:                        Return [<<Mul>>]
 
   // CHECK-START: double Main.DivMP25(double) instruction_simplifier (after)
   // CHECK-NOT:                        Div
diff --git a/test/461-get-reference-vreg/get_reference_vreg_jni.cc b/test/461-get-reference-vreg/get_reference_vreg_jni.cc
index f0b78e1..a8ef684 100644
--- a/test/461-get-reference-vreg/get_reference_vreg_jni.cc
+++ b/test/461-get-reference-vreg/get_reference_vreg_jni.cc
@@ -29,7 +29,9 @@
  public:
   TestVisitor(Thread* thread, Context* context, mirror::Object* this_value)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(thread, context), this_value_(this_value), found_method_index_(0) {}
+      : StackVisitor(thread, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+        this_value_(this_value),
+        found_method_index_(0) {}
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     mirror::ArtMethod* m = GetMethod();
diff --git a/test/462-checker-inlining-across-dex-files/src/Main.java b/test/462-checker-inlining-across-dex-files/src/Main.java
index d5563b8..3d583b4 100644
--- a/test/462-checker-inlining-across-dex-files/src/Main.java
+++ b/test/462-checker-inlining-across-dex-files/src/Main.java
@@ -22,7 +22,7 @@
 public class Main {
 
   // CHECK-START: void Main.inlineEmptyMethod() inliner (before)
-  // CHECK-DAG:     [[Invoke:v\d+]]  InvokeStaticOrDirect
+  // CHECK-DAG:     <<Invoke:v\d+>>  InvokeStaticOrDirect
   // CHECK-DAG:                      ReturnVoid
 
   // CHECK-START: void Main.inlineEmptyMethod() inliner (after)
@@ -33,120 +33,122 @@
   }
 
   // CHECK-START: int Main.inlineReturnIntMethod() inliner (before)
-  // CHECK-DAG:     [[Invoke:i\d+]]  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ [[Invoke]] ]
+  // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   // CHECK-START: int Main.inlineReturnIntMethod() inliner (after)
   // CHECK-NOT:                      InvokeStaticOrDirect
 
   // CHECK-START: int Main.inlineReturnIntMethod() inliner (after)
-  // CHECK-DAG:     [[Const38:i\d+]] IntConstant 38
-  // CHECK-DAG:                      Return [ [[Const38]] ]
+  // CHECK-DAG:     <<Const38:i\d+>> IntConstant 38
+  // CHECK-DAG:                      Return [<<Const38>>]
 
   public static int inlineReturnIntMethod() {
     return OtherDex.returnIntMethod();
   }
 
   // CHECK-START: int Main.dontInlineOtherDexStatic() inliner (before)
-  // CHECK-DAG:     [[Invoke:i\d+]]  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ [[Invoke]] ]
+  // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   // CHECK-START: int Main.dontInlineOtherDexStatic() inliner (after)
-  // CHECK-DAG:     [[Invoke:i\d+]]  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ [[Invoke]] ]
+  // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   public static int dontInlineOtherDexStatic() {
     return OtherDex.returnOtherDexStatic();
   }
 
   // CHECK-START: int Main.inlineMainStatic() inliner (before)
-  // CHECK-DAG:     [[Invoke:i\d+]]  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ [[Invoke]] ]
+  // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   // CHECK-START: int Main.inlineMainStatic() inliner (after)
   // CHECK-NOT:                      InvokeStaticOrDirect
 
   // CHECK-START: int Main.inlineMainStatic() inliner (after)
-  // CHECK-DAG:     [[Static:i\d+]]  StaticFieldGet
-  // CHECK-DAG:                      Return [ [[Static]] ]
+  // CHECK-DAG:     <<Static:i\d+>>  StaticFieldGet
+  // CHECK-DAG:                      Return [<<Static>>]
 
   public static int inlineMainStatic() {
     return OtherDex.returnMainStatic();
   }
 
   // CHECK-START: int Main.dontInlineRecursiveCall() inliner (before)
-  // CHECK-DAG:     [[Invoke:i\d+]]  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ [[Invoke]] ]
+  // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   // CHECK-START: int Main.dontInlineRecursiveCall() inliner (after)
-  // CHECK-DAG:     [[Invoke:i\d+]]  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ [[Invoke]] ]
+  // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   public static int dontInlineRecursiveCall() {
     return OtherDex.recursiveCall();
   }
 
   // CHECK-START: java.lang.String Main.dontInlineReturnString() inliner (before)
-  // CHECK-DAG:     [[Invoke:l\d+]]  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ [[Invoke]] ]
+  // CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   // CHECK-START: java.lang.String Main.dontInlineReturnString() inliner (after)
-  // CHECK-DAG:     [[Invoke:l\d+]]  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ [[Invoke]] ]
+  // CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   public static String dontInlineReturnString() {
     return OtherDex.returnString();
   }
 
   // CHECK-START: java.lang.Class Main.dontInlineOtherDexClass() inliner (before)
-  // CHECK-DAG:     [[Invoke:l\d+]]  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ [[Invoke]] ]
+  // CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   // CHECK-START: java.lang.Class Main.dontInlineOtherDexClass() inliner (after)
-  // CHECK-DAG:     [[Invoke:l\d+]]  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ [[Invoke]] ]
+  // CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   public static Class dontInlineOtherDexClass() {
     return OtherDex.returnOtherDexClass();
   }
 
   // CHECK-START: java.lang.Class Main.inlineMainClass() inliner (before)
-  // CHECK-DAG:     [[Invoke:l\d+]]  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ [[Invoke]] ]
+  // CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   // CHECK-START: java.lang.Class Main.inlineMainClass() inliner (after)
   // CHECK-NOT:                      InvokeStaticOrDirect
 
   // CHECK-START: java.lang.Class Main.inlineMainClass() inliner (after)
-  // CHECK-DAG:     [[Class:l\d+]]  LoadClass
-  // CHECK-DAG:                     Return [ [[Class]] ]
+  // CHECK-DAG:                     Return [<<Class:l\d+>>]
+  // CHECK-DAG:     <<Class>>       LoadClass
+  // Note: Verify backwards because there are two LoadClass instructions
 
   public static Class inlineMainClass() {
     return OtherDex.returnMainClass();
   }
 
   // CHECK-START: java.lang.Class Main.dontInlineOtherDexClassStaticCall() inliner (before)
-  // CHECK-DAG:     [[Invoke:l\d+]]  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ [[Invoke]] ]
+  // CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   // CHECK-START: java.lang.Class Main.dontInlineOtherDexClassStaticCall() inliner (after)
-  // CHECK-DAG:     [[Invoke:l\d+]]  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ [[Invoke]] ]
+  // CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   public static Class dontInlineOtherDexClassStaticCall() {
     return OtherDex.returnOtherDexClassStaticCall();
   }
 
   // CHECK-START: java.lang.Class Main.inlineOtherDexCallingMain() inliner (before)
-  // CHECK-DAG:     [[Invoke:l\d+]]  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ [[Invoke]] ]
+  // CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   // CHECK-START: java.lang.Class Main.inlineOtherDexCallingMain() inliner (after)
   // CHECK-NOT:                      InvokeStaticOrDirect
 
   // CHECK-START: java.lang.Class Main.inlineOtherDexCallingMain() inliner (after)
-  // CHECK-DAG:     [[Class:l\d+]]  LoadClass
-  // CHECK-DAG:                     Return [ [[Class]] ]
+  // CHECK-DAG:                     Return [<<Class:l\d+>>]
+  // CHECK-DAG:     <<Class>>       LoadClass
+  // Note: Verify backwards because there are two LoadClass instructions
 
   public static Class inlineOtherDexCallingMain() {
     return OtherDex.returnOtherDexCallingMain();
diff --git a/test/463-checker-boolean-simplifier/src/Main.java b/test/463-checker-boolean-simplifier/src/Main.java
index 4346103..e237448 100644
--- a/test/463-checker-boolean-simplifier/src/Main.java
+++ b/test/463-checker-boolean-simplifier/src/Main.java
@@ -38,12 +38,12 @@
    */
 
   // CHECK-START: boolean Main.BooleanNot(boolean) boolean_simplifier (before)
-  // CHECK-DAG:     [[Param:z\d+]]    ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
-  // CHECK-DAG:     [[Const1:i\d+]]   IntConstant 1
-  // CHECK-DAG:                       If [ [[Param]] ]
-  // CHECK-DAG:     [[Phi:i\d+]]      Phi [ [[Const1]] [[Const0]] ]
-  // CHECK-DAG:                       Return [ [[Phi]] ]
+  // CHECK-DAG:     <<Param:z\d+>>    ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  // CHECK-DAG:                       If [<<Param>>]
+  // CHECK-DAG:     <<Phi:i\d+>>      Phi [<<Const1>>,<<Const0>>]
+  // CHECK-DAG:                       Return [<<Phi>>]
 
   // CHECK-START: boolean Main.BooleanNot(boolean) boolean_simplifier (before)
   // CHECK:                           Goto
@@ -52,10 +52,10 @@
   // CHECK-NOT:                       Goto
 
   // CHECK-START: boolean Main.BooleanNot(boolean) boolean_simplifier (after)
-  // CHECK-DAG:     [[Param:z\d+]]    ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
-  // CHECK-DAG:     [[NotParam:z\d+]] BooleanNot [ [[Param]] ]
-  // CHECK-DAG:                       Return [ [[NotParam]] ]
+  // CHECK-DAG:     <<Param:z\d+>>    ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:     <<NotParam:z\d+>> BooleanNot [<<Param>>]
+  // CHECK-DAG:                       Return [<<NotParam>>]
 
   // CHECK-START: boolean Main.BooleanNot(boolean) boolean_simplifier (after)
   // CHECK-NOT:                       If
@@ -75,22 +75,22 @@
    */
 
   // CHECK-START: boolean Main.GreaterThan(int, int) boolean_simplifier (before)
-  // CHECK-DAG:     [[ParamX:i\d+]]   ParameterValue
-  // CHECK-DAG:     [[ParamY:i\d+]]   ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
-  // CHECK-DAG:     [[Const1:i\d+]]   IntConstant 1
-  // CHECK-DAG:     [[Cond:z\d+]]     GreaterThan [ [[ParamX]] [[ParamY]] ]
-  // CHECK-DAG:                       If [ [[Cond]] ]
-  // CHECK-DAG:     [[Phi:i\d+]]      Phi [ [[Const0]] [[Const1]] ]
-  // CHECK-DAG:                       Return [ [[Phi]] ]
+  // CHECK-DAG:     <<ParamX:i\d+>>   ParameterValue
+  // CHECK-DAG:     <<ParamY:i\d+>>   ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  // CHECK-DAG:     <<Cond:z\d+>>     GreaterThan [<<ParamX>>,<<ParamY>>]
+  // CHECK-DAG:                       If [<<Cond>>]
+  // CHECK-DAG:     <<Phi:i\d+>>      Phi [<<Const0>>,<<Const1>>]
+  // CHECK-DAG:                       Return [<<Phi>>]
 
   // CHECK-START: boolean Main.GreaterThan(int, int) boolean_simplifier (after)
-  // CHECK-DAG:     [[ParamX:i\d+]]   ParameterValue
-  // CHECK-DAG:     [[ParamY:i\d+]]   ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
-  // CHECK-DAG:     [[Const1:i\d+]]   IntConstant 1
-  // CHECK-DAG:     [[Cond:z\d+]]     GreaterThan [ [[ParamX]] [[ParamY]] ]
-  // CHECK-DAG:                       Return [ [[Cond]] ]
+  // CHECK-DAG:     <<ParamX:i\d+>>   ParameterValue
+  // CHECK-DAG:     <<ParamY:i\d+>>   ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  // CHECK-DAG:     <<Cond:z\d+>>     GreaterThan [<<ParamX>>,<<ParamY>>]
+  // CHECK-DAG:                       Return [<<Cond>>]
 
   public static boolean GreaterThan(int x, int y) {
     return (x <= y) ? false : true;
@@ -102,22 +102,22 @@
    */
 
   // CHECK-START: boolean Main.LessThan(int, int) boolean_simplifier (before)
-  // CHECK-DAG:     [[ParamX:i\d+]]   ParameterValue
-  // CHECK-DAG:     [[ParamY:i\d+]]   ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
-  // CHECK-DAG:     [[Const1:i\d+]]   IntConstant 1
-  // CHECK-DAG:     [[Cond:z\d+]]     GreaterThanOrEqual [ [[ParamX]] [[ParamY]] ]
-  // CHECK-DAG:                       If [ [[Cond]] ]
-  // CHECK-DAG:     [[Phi:i\d+]]      Phi [ [[Const1]] [[Const0]] ]
-  // CHECK-DAG:                       Return [ [[Phi]] ]
+  // CHECK-DAG:     <<ParamX:i\d+>>   ParameterValue
+  // CHECK-DAG:     <<ParamY:i\d+>>   ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  // CHECK-DAG:     <<Cond:z\d+>>     GreaterThanOrEqual [<<ParamX>>,<<ParamY>>]
+  // CHECK-DAG:                       If [<<Cond>>]
+  // CHECK-DAG:     <<Phi:i\d+>>      Phi [<<Const1>>,<<Const0>>]
+  // CHECK-DAG:                       Return [<<Phi>>]
 
   // CHECK-START: boolean Main.LessThan(int, int) boolean_simplifier (after)
-  // CHECK-DAG:     [[ParamX:i\d+]]   ParameterValue
-  // CHECK-DAG:     [[ParamY:i\d+]]   ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
-  // CHECK-DAG:     [[Const1:i\d+]]   IntConstant 1
-  // CHECK-DAG:     [[Cond:z\d+]]     LessThan [ [[ParamX]] [[ParamY]] ]
-  // CHECK-DAG:                       Return [ [[Cond]] ]
+  // CHECK-DAG:     <<ParamX:i\d+>>   ParameterValue
+  // CHECK-DAG:     <<ParamY:i\d+>>   ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  // CHECK-DAG:     <<Cond:z\d+>>     LessThan [<<ParamX>>,<<ParamY>>]
+  // CHECK-DAG:                       Return [<<Cond>>]
 
   // CHECK-START: boolean Main.LessThan(int, int) boolean_simplifier (after)
   // CHECK-NOT:                       GreaterThanOrEqual
@@ -132,51 +132,51 @@
    */
 
   // CHECK-START: boolean Main.ValuesOrdered(int, int, int) boolean_simplifier (before)
-  // CHECK-DAG:     [[ParamX:i\d+]]   ParameterValue
-  // CHECK-DAG:     [[ParamY:i\d+]]   ParameterValue
-  // CHECK-DAG:     [[ParamZ:i\d+]]   ParameterValue
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
-  // CHECK-DAG:     [[Const1:i\d+]]   IntConstant 1
-  // CHECK-DAG:     [[CondXY:z\d+]]   GreaterThan [ [[ParamX]] [[ParamY]] ]
-  // CHECK-DAG:                       If [ [[CondXY]] ]
-  // CHECK-DAG:     [[CondYZ:z\d+]]   GreaterThan [ [[ParamY]] [[ParamZ]] ]
-  // CHECK-DAG:                       If [ [[CondYZ]] ]
-  // CHECK-DAG:     [[CondXYZ:z\d+]]  NotEqual [ [[PhiXY:i\d+]] [[PhiYZ:i\d+]] ]
-  // CHECK-DAG:                       If [ [[CondXYZ]] ]
-  // CHECK-DAG:                       Return [ [[PhiXYZ:i\d+]] ]
-  // CHECK-DAG:     [[PhiXY]]         Phi [ [[Const1]] [[Const0]] ]
-  // CHECK-DAG:     [[PhiYZ]]         Phi [ [[Const1]] [[Const0]] ]
-  // CHECK-DAG:     [[PhiXYZ]]        Phi [ [[Const1]] [[Const0]] ]
+  // CHECK-DAG:     <<ParamX:i\d+>>   ParameterValue
+  // CHECK-DAG:     <<ParamY:i\d+>>   ParameterValue
+  // CHECK-DAG:     <<ParamZ:i\d+>>   ParameterValue
+  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  // CHECK-DAG:     <<CondXY:z\d+>>   GreaterThan [<<ParamX>>,<<ParamY>>]
+  // CHECK-DAG:                       If [<<CondXY>>]
+  // CHECK-DAG:     <<CondYZ:z\d+>>   GreaterThan [<<ParamY>>,<<ParamZ>>]
+  // CHECK-DAG:                       If [<<CondYZ>>]
+  // CHECK-DAG:     <<CondXYZ:z\d+>>  NotEqual [<<PhiXY:i\d+>>,<<PhiYZ:i\d+>>]
+  // CHECK-DAG:                       If [<<CondXYZ>>]
+  // CHECK-DAG:                       Return [<<PhiXYZ:i\d+>>]
+  // CHECK-DAG:     <<PhiXY>>         Phi [<<Const1>>,<<Const0>>]
+  // CHECK-DAG:     <<PhiYZ>>         Phi [<<Const1>>,<<Const0>>]
+  // CHECK-DAG:     <<PhiXYZ>>        Phi [<<Const1>>,<<Const0>>]
 
   // CHECK-START: boolean Main.ValuesOrdered(int, int, int) boolean_simplifier (after)
-  // CHECK-DAG:     [[ParamX:i\d+]]   ParameterValue
-  // CHECK-DAG:     [[ParamY:i\d+]]   ParameterValue
-  // CHECK-DAG:     [[ParamZ:i\d+]]   ParameterValue
-  // CHECK-DAG:     [[CmpXY:z\d+]]    LessThanOrEqual [ [[ParamX]] [[ParamY]] ]
-  // CHECK-DAG:     [[CmpYZ:z\d+]]    LessThanOrEqual [ [[ParamY]] [[ParamZ]] ]
-  // CHECK-DAG:     [[CmpXYZ:z\d+]]   Equal [ [[CmpXY]] [[CmpYZ]] ]
-  // CHECK-DAG:                       Return [ [[CmpXYZ]] ]
+  // CHECK-DAG:     <<ParamX:i\d+>>   ParameterValue
+  // CHECK-DAG:     <<ParamY:i\d+>>   ParameterValue
+  // CHECK-DAG:     <<ParamZ:i\d+>>   ParameterValue
+  // CHECK-DAG:     <<CmpXY:z\d+>>    LessThanOrEqual [<<ParamX>>,<<ParamY>>]
+  // CHECK-DAG:     <<CmpYZ:z\d+>>    LessThanOrEqual [<<ParamY>>,<<ParamZ>>]
+  // CHECK-DAG:     <<CmpXYZ:z\d+>>   Equal [<<CmpXY>>,<<CmpYZ>>]
+  // CHECK-DAG:                       Return [<<CmpXYZ>>]
 
   public static boolean ValuesOrdered(int x, int y, int z) {
     return (x <= y) == (y <= z);
   }
 
   // CHECK-START: int Main.NegatedCondition(boolean) boolean_simplifier (before)
-  // CHECK-DAG:     [[Param:z\d+]]    ParameterValue
-  // CHECK-DAG:     [[Const42:i\d+]]  IntConstant 42
-  // CHECK-DAG:     [[Const43:i\d+]]  IntConstant 43
-  // CHECK-DAG:     [[NotParam:z\d+]] BooleanNot [ [[Param]] ]
-  // CHECK-DAG:                       If [ [[NotParam]] ]
-  // CHECK-DAG:     [[Phi:i\d+]]      Phi [ [[Const42]] [[Const43]] ]
-  // CHECK-DAG:                       Return [ [[Phi]] ]
+  // CHECK-DAG:     <<Param:z\d+>>    ParameterValue
+  // CHECK-DAG:     <<Const42:i\d+>>  IntConstant 42
+  // CHECK-DAG:     <<Const43:i\d+>>  IntConstant 43
+  // CHECK-DAG:     <<NotParam:z\d+>> BooleanNot [<<Param>>]
+  // CHECK-DAG:                       If [<<NotParam>>]
+  // CHECK-DAG:     <<Phi:i\d+>>      Phi [<<Const42>>,<<Const43>>]
+  // CHECK-DAG:                       Return [<<Phi>>]
 
   // CHECK-START: int Main.NegatedCondition(boolean) boolean_simplifier (after)
-  // CHECK-DAG:     [[Param:z\d+]]    ParameterValue
-  // CHECK-DAG:     [[Const42:i\d+]]  IntConstant 42
-  // CHECK-DAG:     [[Const43:i\d+]]  IntConstant 43
-  // CHECK-DAG:                       If [ [[Param]] ]
-  // CHECK-DAG:     [[Phi:i\d+]]      Phi [ [[Const42]] [[Const43]] ]
-  // CHECK-DAG:                       Return [ [[Phi]] ]
+  // CHECK-DAG:     <<Param:z\d+>>    ParameterValue
+  // CHECK-DAG:     <<Const42:i\d+>>  IntConstant 42
+  // CHECK-DAG:     <<Const43:i\d+>>  IntConstant 43
+  // CHECK-DAG:                       If [<<Param>>]
+  // CHECK-DAG:     <<Phi:i\d+>>      Phi [<<Const42>>,<<Const43>>]
+  // CHECK-DAG:                       Return [<<Phi>>]
 
   // Note: The fact that branches are swapped is verified by running the test.
 
diff --git a/test/464-checker-inline-sharpen-calls/src/Main.java b/test/464-checker-inline-sharpen-calls/src/Main.java
index 1b25b42..e451f70 100644
--- a/test/464-checker-inline-sharpen-calls/src/Main.java
+++ b/test/464-checker-inline-sharpen-calls/src/Main.java
@@ -20,7 +20,7 @@
   }
 
   // CHECK-START: void Main.inlineSharpenInvokeVirtual(Main) inliner (before)
-  // CHECK-DAG:     [[Invoke:v\d+]]  InvokeStaticOrDirect
+  // CHECK-DAG:     <<Invoke:v\d+>>  InvokeStaticOrDirect
   // CHECK-DAG:                      ReturnVoid
 
   // CHECK-START: void Main.inlineSharpenInvokeVirtual(Main) inliner (after)
@@ -31,15 +31,15 @@
   }
 
   // CHECK-START: int Main.inlineSharpenStringInvoke() inliner (before)
-  // CHECK-DAG:     [[Invoke:i\d+]]  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ [[Invoke]] ]
+  // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   // CHECK-START: int Main.inlineSharpenStringInvoke() inliner (after)
   // CHECK-NOT:                      InvokeStaticOrDirect
 
   // CHECK-START: int Main.inlineSharpenStringInvoke() inliner (after)
-  // CHECK-DAG:     [[Field:i\d+]]   InstanceFieldGet
-  // CHECK-DAG:                      Return [ [[Field]] ]
+  // CHECK-DAG:     <<Field:i\d+>>   InstanceFieldGet
+  // CHECK-DAG:                      Return [<<Field>>]
 
   public static int inlineSharpenStringInvoke() {
     return "Foo".length();
diff --git a/test/465-checker-clinit-gvn/src/Main.java b/test/465-checker-clinit-gvn/src/Main.java
index dcaef6f..ac2863c 100644
--- a/test/465-checker-clinit-gvn/src/Main.java
+++ b/test/465-checker-clinit-gvn/src/Main.java
@@ -27,14 +27,14 @@
 public final class Main {
 
   // CHECK-START: int Main.accessTwoStatics() GVN (before)
-  // CHECK-DAG:     [[Class1:l\d+]]  LoadClass
-  // CHECK-DAG:                      ClinitCheck [ [[Class1]] ]
-  // CHECK-DAG:     [[Class2:l\d+]]  LoadClass
-  // CHECK-DAG:                      ClinitCheck [ [[Class2]] ]
+  // CHECK-DAG:     <<Class1:l\d+>>  LoadClass
+  // CHECK-DAG:                      ClinitCheck [<<Class1>>]
+  // CHECK-DAG:     <<Class2:l\d+>>  LoadClass
+  // CHECK-DAG:                      ClinitCheck [<<Class2>>]
 
   // CHECK-START: int Main.accessTwoStatics() GVN (after)
-  // CHECK-DAG:     [[Class:l\d+]]   LoadClass
-  // CHECK-DAG:                      ClinitCheck [ [[Class]] ]
+  // CHECK-DAG:     <<Class:l\d+>>   LoadClass
+  // CHECK-DAG:                      ClinitCheck [<<Class>>]
   // CHECK-NOT:                      ClinitCheck
 
   public static int accessTwoStatics() {
@@ -42,14 +42,14 @@
   }
 
   // CHECK-START: int Main.accessTwoStaticsCallInBetween() GVN (before)
-  // CHECK-DAG:     [[Class1:l\d+]]  LoadClass
-  // CHECK-DAG:                      ClinitCheck [ [[Class1]] ]
-  // CHECK-DAG:     [[Class2:l\d+]]  LoadClass
-  // CHECK-DAG:                      ClinitCheck [ [[Class2]] ]
+  // CHECK-DAG:     <<Class1:l\d+>>  LoadClass
+  // CHECK-DAG:                      ClinitCheck [<<Class1>>]
+  // CHECK-DAG:     <<Class2:l\d+>>  LoadClass
+  // CHECK-DAG:                      ClinitCheck [<<Class2>>]
 
   // CHECK-START: int Main.accessTwoStaticsCallInBetween() GVN (after)
-  // CHECK-DAG:     [[Class:l\d+]]   LoadClass
-  // CHECK-DAG:                      ClinitCheck [ [[Class]] ]
+  // CHECK-DAG:     <<Class:l\d+>>   LoadClass
+  // CHECK-DAG:                      ClinitCheck [<<Class>>]
   // CHECK-NOT:                      ClinitCheck
 
   public static int accessTwoStaticsCallInBetween() {
diff --git a/test/466-get-live-vreg/get_live_vreg_jni.cc b/test/466-get-live-vreg/get_live_vreg_jni.cc
index 6715ba1..4724e8e 100644
--- a/test/466-get-live-vreg/get_live_vreg_jni.cc
+++ b/test/466-get-live-vreg/get_live_vreg_jni.cc
@@ -28,7 +28,7 @@
 class TestVisitor : public StackVisitor {
  public:
   TestVisitor(Thread* thread, Context* context) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(thread, context) {}
+      : StackVisitor(thread, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames) {}
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     mirror::ArtMethod* m = GetMethod();
diff --git a/test/468-checker-bool-simplifier-regression/smali/TestCase.smali b/test/468-checker-bool-simplifier-regression/smali/TestCase.smali
index f36304d..33e6dc3 100644
--- a/test/468-checker-bool-simplifier-regression/smali/TestCase.smali
+++ b/test/468-checker-bool-simplifier-regression/smali/TestCase.smali
@@ -18,6 +18,19 @@
 
 .field public static value:Z
 
+# CHECK-START: boolean TestCase.testCase() boolean_simplifier (before)
+# CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+# CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+# CHECK-DAG:     <<Value:z\d+>>    StaticFieldGet
+# CHECK-DAG:                       If [<<Value>>]
+# CHECK-DAG:     <<Phi:i\d+>>      Phi [<<Const1>>,<<Const0>>]
+# CHECK-DAG:                       Return [<<Phi>>]
+
+# CHECK-START: boolean TestCase.testCase() boolean_simplifier (after)
+# CHECK-DAG:     <<Value:z\d+>>    StaticFieldGet
+# CHECK-DAG:     <<Not:z\d+>>      BooleanNot [<<Value>>]
+# CHECK-DAG:                       Return [<<Not>>]
+
 .method public static testCase()Z
     .registers 2
     sget-boolean v0, LTestCase;->value:Z
diff --git a/test/468-checker-bool-simplifier-regression/src/Main.java b/test/468-checker-bool-simplifier-regression/src/Main.java
index d45f3bf..8fe05c7 100644
--- a/test/468-checker-bool-simplifier-regression/src/Main.java
+++ b/test/468-checker-bool-simplifier-regression/src/Main.java
@@ -18,19 +18,6 @@
 
 public class Main {
 
-  // CHECK-START: boolean TestCase.testCase() boolean_simplifier (before)
-  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
-  // CHECK-DAG:     [[Const1:i\d+]]   IntConstant 1
-  // CHECK-DAG:     [[Value:z\d+]]    StaticFieldGet
-  // CHECK-DAG:                       If [ [[Value]] ]
-  // CHECK-DAG:     [[Phi:i\d+]]      Phi [ [[Const1]] [[Const0]] ]
-  // CHECK-DAG:                       Return [ [[Phi]] ]
-
-  // CHECK-START: boolean TestCase.testCase() boolean_simplifier (after)
-  // CHECK-DAG:     [[Value:z\d+]]    StaticFieldGet
-  // CHECK-DAG:     [[Not:z\d+]]      BooleanNot [ [[Value]] ]
-  // CHECK-DAG:                       Return [ [[Not]] ]
-
   public static boolean runTest(boolean input) throws Exception {
     Class<?> c = Class.forName("TestCase");
     Method m = c.getMethod("testCase");
diff --git a/test/474-checker-boolean-input/src/Main.java b/test/474-checker-boolean-input/src/Main.java
index 9151986..490f7f9 100644
--- a/test/474-checker-boolean-input/src/Main.java
+++ b/test/474-checker-boolean-input/src/Main.java
@@ -28,8 +28,8 @@
    */
 
   // CHECK-START: boolean Main.TestPhiAsBoolean(int) boolean_simplifier (after)
-  // CHECK-DAG:     [[Phi:i\d+]]     Phi
-  // CHECK-DAG:                      BooleanNot [ [[Phi]] ]
+  // CHECK-DAG:     <<Phi:i\d+>>     Phi
+  // CHECK-DAG:                      BooleanNot [<<Phi>>]
 
   public static boolean f1;
   public static boolean f2;
@@ -48,8 +48,8 @@
    */
 
   // CHECK-START: boolean Main.TestAndAsBoolean(boolean, boolean) boolean_simplifier (after)
-  // CHECK-DAG:     [[And:i\d+]]     And
-  // CHECK-DAG:                      BooleanNot [ [[And]] ]
+  // CHECK-DAG:     <<And:i\d+>>     And
+  // CHECK-DAG:                      BooleanNot [<<And>>]
 
   public static boolean InlineAnd(boolean x, boolean y) {
     return x & y;
@@ -65,8 +65,8 @@
    */
 
   // CHECK-START: boolean Main.TestOrAsBoolean(boolean, boolean) boolean_simplifier (after)
-  // CHECK-DAG:     [[Or:i\d+]]      Or
-  // CHECK-DAG:                      BooleanNot [ [[Or]] ]
+  // CHECK-DAG:     <<Or:i\d+>>      Or
+  // CHECK-DAG:                      BooleanNot [<<Or>>]
 
   public static boolean InlineOr(boolean x, boolean y) {
     return x | y;
@@ -82,8 +82,8 @@
    */
 
   // CHECK-START: boolean Main.TestXorAsBoolean(boolean, boolean) boolean_simplifier (after)
-  // CHECK-DAG:     [[Xor:i\d+]]     Xor
-  // CHECK-DAG:                      BooleanNot [ [[Xor]] ]
+  // CHECK-DAG:     <<Xor:i\d+>>     Xor
+  // CHECK-DAG:                      BooleanNot [<<Xor>>]
 
   public static boolean InlineXor(boolean x, boolean y) {
     return x ^ y;
diff --git a/test/476-checker-ctor-memory-barrier/src/Main.java b/test/476-checker-ctor-memory-barrier/src/Main.java
index 10aa2ab..769ae20 100644
--- a/test/476-checker-ctor-memory-barrier/src/Main.java
+++ b/test/476-checker-ctor-memory-barrier/src/Main.java
@@ -17,7 +17,7 @@
 
 class ClassWithoutFinals {
   // CHECK-START: void ClassWithoutFinals.<init>() register (after)
-  // CHECK-NOT: MemoryBarrier {{StoreStore}}
+  // CHECK-NOT: MemoryBarrier kind:StoreStore
   public ClassWithoutFinals() {}
 }
 
@@ -26,7 +26,7 @@
   public ClassWithFinals obj;
 
   // CHECK-START: void ClassWithFinals.<init>(boolean) register (after)
-  // CHECK:     MemoryBarrier {{StoreStore}}
+  // CHECK:     MemoryBarrier kind:StoreStore
   // CHECK-NOT: {{.*}}
   // CHECK:     ReturnVoid
   public ClassWithFinals(boolean cond) {
@@ -38,7 +38,7 @@
   }
 
   // CHECK-START: void ClassWithFinals.<init>() register (after)
-  // CHECK:     MemoryBarrier {{StoreStore}}
+  // CHECK:     MemoryBarrier kind:StoreStore
   // CHECK-NOT: {{.*}}
   // CHECK:     ReturnVoid
   public ClassWithFinals() {
@@ -46,8 +46,8 @@
   }
 
   // CHECK-START: void ClassWithFinals.<init>(int) register (after)
-  // CHECK:     MemoryBarrier {{StoreStore}}
-  // CHECK:     MemoryBarrier {{StoreStore}}
+  // CHECK:     MemoryBarrier kind:StoreStore
+  // CHECK:     MemoryBarrier kind:StoreStore
   // CHECK-NOT: {{.*}}
   // CHECK:     ReturnVoid
   public ClassWithFinals(int x) {
@@ -61,7 +61,7 @@
 
 class InheritFromClassWithFinals extends ClassWithFinals {
   // CHECK-START: void InheritFromClassWithFinals.<init>() register (after)
-  // CHECK:     MemoryBarrier {{StoreStore}}
+  // CHECK:     MemoryBarrier kind:StoreStore
   // CHECK-NOT: {{.*}}
   // CHECK:     ReturnVoid
 
@@ -75,7 +75,7 @@
   // CHECK:     InvokeStaticOrDirect
 
   // CHECK-START: void InheritFromClassWithFinals.<init>(boolean) register (after)
-  // CHECK-NOT: MemoryBarrier {{StoreStore}}
+  // CHECK-NOT: MemoryBarrier kind:StoreStore
   public InheritFromClassWithFinals(boolean cond) {
     super(cond);
     // should not inline the super constructor
@@ -86,8 +86,8 @@
   final int y;
 
   // CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>() register (after)
-  // CHECK:     MemoryBarrier {{StoreStore}}
-  // CHECK:     MemoryBarrier {{StoreStore}}
+  // CHECK:     MemoryBarrier kind:StoreStore
+  // CHECK:     MemoryBarrier kind:StoreStore
   // CHECK-NOT: {{.*}}
   // CHECK:     ReturnVoid
 
@@ -100,7 +100,7 @@
 
   // CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>(boolean) register (after)
   // CHECK:     InvokeStaticOrDirect
-  // CHECK:     MemoryBarrier {{StoreStore}}
+  // CHECK:     MemoryBarrier kind:StoreStore
   // CHECK-NOT: {{.*}}
   // CHECK:     ReturnVoid
   public HaveFinalsAndInheritFromClassWithFinals(boolean cond) {
@@ -116,13 +116,13 @@
   // CHECK:     InvokeStaticOrDirect
 
   // CHECK-START: ClassWithFinals Main.noInlineNoConstructorBarrier() register (after)
-  // CHECK-NOT: MemoryBarrier {{StoreStore}}
+  // CHECK-NOT: MemoryBarrier kind:StoreStore
   public static ClassWithFinals noInlineNoConstructorBarrier() {
     return new ClassWithFinals(false);
   }
 
   // CHECK-START: ClassWithFinals Main.inlineConstructorBarrier() register (after)
-  // CHECK:     MemoryBarrier {{StoreStore}}
+  // CHECK:     MemoryBarrier kind:StoreStore
   // CHECK-NOT: {{.*}}
   // CHECK:     Return
 
@@ -133,7 +133,7 @@
   }
 
   // CHECK-START: InheritFromClassWithFinals Main.doubleInlineConstructorBarrier() register (after)
-  // CHECK:     MemoryBarrier {{StoreStore}}
+  // CHECK:     MemoryBarrier kind:StoreStore
   // CHECK-NOT: {{.*}}
   // CHECK:     Return
 
diff --git a/test/478-checker-clinit-check-pruning/src/Main.java b/test/478-checker-clinit-check-pruning/src/Main.java
index 6da8945..61199a7 100644
--- a/test/478-checker-clinit-check-pruning/src/Main.java
+++ b/test/478-checker-clinit-check-pruning/src/Main.java
@@ -24,13 +24,13 @@
    */
 
   // CHECK-START: void Main.invokeStaticInlined() builder (after)
-  // CHECK-DAG:     [[LoadClass:l\d+]]    LoadClass
-  // CHECK-DAG:     [[ClinitCheck:l\d+]]  ClinitCheck [ [[LoadClass]] ]
-  // CHECK-DAG:                           InvokeStaticOrDirect [ [[ClinitCheck]] ]
+  // CHECK-DAG:     <<LoadClass:l\d+>>    LoadClass
+  // CHECK-DAG:     <<ClinitCheck:l\d+>>  ClinitCheck [<<LoadClass>>]
+  // CHECK-DAG:                           InvokeStaticOrDirect [<<ClinitCheck>>]
 
   // CHECK-START: void Main.invokeStaticInlined() inliner (after)
-  // CHECK-DAG:     [[LoadClass:l\d+]]    LoadClass
-  // CHECK-DAG:     [[ClinitCheck:l\d+]]  ClinitCheck [ [[LoadClass]] ]
+  // CHECK-DAG:     <<LoadClass:l\d+>>    LoadClass
+  // CHECK-DAG:     <<ClinitCheck:l\d+>>  ClinitCheck [<<LoadClass>>]
 
   // CHECK-START: void Main.invokeStaticInlined() inliner (after)
   // CHECK-NOT:                           InvokeStaticOrDirect
@@ -67,14 +67,14 @@
    */
 
   // CHECK-START: void Main.invokeStaticNotInlined() builder (after)
-  // CHECK-DAG:     [[LoadClass:l\d+]]    LoadClass
-  // CHECK-DAG:     [[ClinitCheck:l\d+]]  ClinitCheck [ [[LoadClass]] ]
-  // CHECK-DAG:                           InvokeStaticOrDirect [ [[ClinitCheck]] ]
+  // CHECK-DAG:     <<LoadClass:l\d+>>    LoadClass
+  // CHECK-DAG:     <<ClinitCheck:l\d+>>  ClinitCheck [<<LoadClass>>]
+  // CHECK-DAG:                           InvokeStaticOrDirect [<<ClinitCheck>>]
 
   // CHECK-START: void Main.invokeStaticNotInlined() inliner (after)
-  // CHECK-DAG:     [[LoadClass:l\d+]]    LoadClass
-  // CHECK-DAG:     [[ClinitCheck:l\d+]]  ClinitCheck [ [[LoadClass]] ]
-  // CHECK-DAG:                           InvokeStaticOrDirect [ [[ClinitCheck]] ]
+  // CHECK-DAG:     <<LoadClass:l\d+>>    LoadClass
+  // CHECK-DAG:     <<ClinitCheck:l\d+>>  ClinitCheck [<<LoadClass>>]
+  // CHECK-DAG:                           InvokeStaticOrDirect [<<ClinitCheck>>]
 
   // The following checks ensure the clinit check and load class
   // instructions added by the builder are pruned by the
diff --git a/test/480-checker-dead-blocks/src/Main.java b/test/480-checker-dead-blocks/src/Main.java
index 83dbb26..b76755e 100644
--- a/test/480-checker-dead-blocks/src/Main.java
+++ b/test/480-checker-dead-blocks/src/Main.java
@@ -31,19 +31,19 @@
   }
 
   // CHECK-START: int Main.testTrueBranch(int, int) dead_code_elimination_final (before)
-  // CHECK-DAG:     [[ArgX:i\d+]]    ParameterValue
-  // CHECK-DAG:     [[ArgY:i\d+]]    ParameterValue
+  // CHECK-DAG:     <<ArgX:i\d+>>    ParameterValue
+  // CHECK-DAG:     <<ArgY:i\d+>>    ParameterValue
   // CHECK-DAG:                      If
-  // CHECK-DAG:     [[Add:i\d+]]     Add [ [[ArgX]] [[ArgY]] ]
-  // CHECK-DAG:     [[Sub:i\d+]]     Sub [ [[ArgX]] [[ArgY]] ]
-  // CHECK-DAG:     [[Phi:i\d+]]     Phi [ [[Add]] [[Sub]] ]
-  // CHECK-DAG:                      Return [ [[Phi]] ]
+  // CHECK-DAG:     <<Add:i\d+>>     Add [<<ArgX>>,<<ArgY>>]
+  // CHECK-DAG:     <<Sub:i\d+>>     Sub [<<ArgX>>,<<ArgY>>]
+  // CHECK-DAG:     <<Phi:i\d+>>     Phi [<<Add>>,<<Sub>>]
+  // CHECK-DAG:                      Return [<<Phi>>]
 
   // CHECK-START: int Main.testTrueBranch(int, int) dead_code_elimination_final (after)
-  // CHECK-DAG:     [[ArgX:i\d+]]    ParameterValue
-  // CHECK-DAG:     [[ArgY:i\d+]]    ParameterValue
-  // CHECK-DAG:     [[Add:i\d+]]     Add [ [[ArgX]] [[ArgY]] ]
-  // CHECK-DAG:                      Return [ [[Add]] ]
+  // CHECK-DAG:     <<ArgX:i\d+>>    ParameterValue
+  // CHECK-DAG:     <<ArgY:i\d+>>    ParameterValue
+  // CHECK-DAG:     <<Add:i\d+>>     Add [<<ArgX>>,<<ArgY>>]
+  // CHECK-DAG:                      Return [<<Add>>]
 
   // CHECK-START: int Main.testTrueBranch(int, int) dead_code_elimination_final (after)
   // CHECK-NOT:                      If
@@ -61,19 +61,19 @@
   }
 
   // CHECK-START: int Main.testFalseBranch(int, int) dead_code_elimination_final (before)
-  // CHECK-DAG:     [[ArgX:i\d+]]    ParameterValue
-  // CHECK-DAG:     [[ArgY:i\d+]]    ParameterValue
+  // CHECK-DAG:     <<ArgX:i\d+>>    ParameterValue
+  // CHECK-DAG:     <<ArgY:i\d+>>    ParameterValue
   // CHECK-DAG:                      If
-  // CHECK-DAG:     [[Add:i\d+]]     Add [ [[ArgX]] [[ArgY]] ]
-  // CHECK-DAG:     [[Sub:i\d+]]     Sub [ [[ArgX]] [[ArgY]] ]
-  // CHECK-DAG:     [[Phi:i\d+]]     Phi [ [[Add]] [[Sub]] ]
-  // CHECK-DAG:                      Return [ [[Phi]] ]
+  // CHECK-DAG:     <<Add:i\d+>>     Add [<<ArgX>>,<<ArgY>>]
+  // CHECK-DAG:     <<Sub:i\d+>>     Sub [<<ArgX>>,<<ArgY>>]
+  // CHECK-DAG:     <<Phi:i\d+>>     Phi [<<Add>>,<<Sub>>]
+  // CHECK-DAG:                      Return [<<Phi>>]
 
   // CHECK-START: int Main.testFalseBranch(int, int) dead_code_elimination_final (after)
-  // CHECK-DAG:     [[ArgX:i\d+]]    ParameterValue
-  // CHECK-DAG:     [[ArgY:i\d+]]    ParameterValue
-  // CHECK-DAG:     [[Sub:i\d+]]     Sub [ [[ArgX]] [[ArgY]] ]
-  // CHECK-DAG:                      Return [ [[Sub]] ]
+  // CHECK-DAG:     <<ArgX:i\d+>>    ParameterValue
+  // CHECK-DAG:     <<ArgY:i\d+>>    ParameterValue
+  // CHECK-DAG:     <<Sub:i\d+>>     Sub [<<ArgX>>,<<ArgY>>]
+  // CHECK-DAG:                      Return [<<Sub>>]
 
   // CHECK-START: int Main.testFalseBranch(int, int) dead_code_elimination_final (after)
   // CHECK-NOT:                      If
@@ -125,8 +125,8 @@
   // CHECK-DAG:                      Add
 
   // CHECK-START: int Main.testDeadLoop(int) dead_code_elimination_final (after)
-  // CHECK-DAG:     [[Arg:i\d+]]     ParameterValue
-  // CHECK-DAG:                      Return [ [[Arg]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>     ParameterValue
+  // CHECK-DAG:                      Return [<<Arg>>]
 
   // CHECK-START: int Main.testDeadLoop(int) dead_code_elimination_final (after)
   // CHECK-NOT:                      If
@@ -145,8 +145,8 @@
   // CHECK-DAG:                      Add
 
   // CHECK-START: int Main.testUpdateLoopInformation(int) dead_code_elimination_final (after)
-  // CHECK-DAG:     [[Arg:i\d+]]     ParameterValue
-  // CHECK-DAG:                      Return [ [[Arg]] ]
+  // CHECK-DAG:     <<Arg:i\d+>>     ParameterValue
+  // CHECK-DAG:                      Return [<<Arg>>]
 
   // CHECK-START: int Main.testUpdateLoopInformation(int) dead_code_elimination_final (after)
   // CHECK-NOT:                      If
diff --git a/test/482-checker-loop-back-edge-use/src/Main.java b/test/482-checker-loop-back-edge-use/src/Main.java
index 74184e8..9e1076a 100644
--- a/test/482-checker-loop-back-edge-use/src/Main.java
+++ b/test/482-checker-loop-back-edge-use/src/Main.java
@@ -18,16 +18,16 @@
 public class Main {
 
   // CHECK-START: void Main.loop1(boolean) liveness (after)
-  // CHECK:         ParameterValue (liveness: 2 ranges: { [2, 22) }, uses: { 17 22 }
-  // CHECK:         Goto (liveness: 20)
+  // CHECK:         ParameterValue  liveness:2  ranges:[2-22] uses:[17,22]
+  // CHECK:         Goto            liveness:20
   public static void loop1(boolean incoming) {
     while (incoming) {}
   }
 
   // CHECK-START: void Main.loop2(boolean) liveness (after)
-  // CHECK:         ParameterValue (liveness: 2 ranges: { [2, 42) }, uses: { 33 38 42 }
-  // CHECK:         Goto (liveness: 36)
-  // CHECK:         Goto (liveness: 40)
+  // CHECK:         ParameterValue  liveness:2  ranges:[2-42] uses:[33,38,42]
+  // CHECK:         Goto            liveness:36
+  // CHECK:         Goto            liveness:40
   public static void loop2(boolean incoming) {
     while (true) {
       System.out.println("foo");
@@ -36,11 +36,11 @@
   }
 
   // CHECK-START: void Main.loop3(boolean) liveness (after)
-  // CHECK:         ParameterValue (liveness: 2 ranges: { [2, 60) }, uses: { 56 60 }
-  // CHECK:         Goto (liveness: 58)
+  // CHECK:         ParameterValue  liveness:2  ranges:[2-60] uses:[56,60]
+  // CHECK:         Goto            liveness:58
 
   // CHECK-START: void Main.loop3(boolean) liveness (after)
-  // CHECK-NOT:     Goto (liveness: 54)
+  // CHECK-NOT:     Goto liveness:54
   public static void loop3(boolean incoming) {
     // 'incoming' only needs a use at the outer loop's back edge.
     while (System.currentTimeMillis() != 42) {
@@ -50,10 +50,10 @@
   }
 
   // CHECK-START: void Main.loop4(boolean) liveness (after)
-  // CHECK:         ParameterValue (liveness: 2 ranges: { [2, 22) }, uses: { 22 }
+  // CHECK:         ParameterValue  liveness:2  ranges:[2-22] uses:[22]
 
   // CHECK-START: void Main.loop4(boolean) liveness (after)
-  // CHECK-NOT:     Goto (liveness: 20)
+  // CHECK-NOT:     Goto            liveness:20
   public static void loop4(boolean incoming) {
     // 'incoming' has no loop use, so should not have back edge uses.
     System.out.println(incoming);
@@ -63,9 +63,9 @@
   }
 
   // CHECK-START: void Main.loop5(boolean) liveness (after)
-  // CHECK:         ParameterValue (liveness: 2 ranges: { [2, 50) }, uses: { 33 42 46 50 }
-  // CHECK:         Goto (liveness: 44)
-  // CHECK:         Goto (liveness: 48)
+  // CHECK:         ParameterValue  liveness:2  ranges:[2-50] uses:[33,42,46,50]
+  // CHECK:         Goto            liveness:44
+  // CHECK:         Goto            liveness:48
   public static void loop5(boolean incoming) {
     // 'incoming' must have a use at both back edges.
     while (Runtime.getRuntime() != null) {
@@ -76,11 +76,11 @@
   }
 
   // CHECK-START: void Main.loop6(boolean) liveness (after)
-  // CHECK          ParameterValue (liveness: 2 ranges: { [2, 46) }, uses: { 24 46 }
-  // CHECK:         Goto (liveness: 44)
+  // CHECK          ParameterValue  liveness:2  ranges:[2-46] uses:[24,46]
+  // CHECK:         Goto            liveness:44
 
   // CHECK-START: void Main.loop6(boolean) liveness (after)
-  // CHECK-NOT:     Goto (liveness: 22)
+  // CHECK-NOT:     Goto            liveness:22
   public static void loop6(boolean incoming) {
     // 'incoming' must have a use only at the first loop's back edge.
     while (true) {
@@ -90,9 +90,9 @@
   }
 
   // CHECK-START: void Main.loop7(boolean) liveness (after)
-  // CHECK:         ParameterValue (liveness: 2 ranges: { [2, 50) }, uses: { 32 41 46 50 }
-  // CHECK:         Goto (liveness: 44)
-  // CHECK:         Goto (liveness: 48)
+  // CHECK:         ParameterValue  liveness:2  ranges:[2-50] uses:[32,41,46,50]
+  // CHECK:         Goto            liveness:44
+  // CHECK:         Goto            liveness:48
   public static void loop7(boolean incoming) {
     // 'incoming' must have a use at both back edges.
     while (Runtime.getRuntime() != null) {
@@ -102,9 +102,9 @@
   }
 
   // CHECK-START: void Main.loop8() liveness (after)
-  // CHECK:         StaticFieldGet (liveness: 12 ranges: { [12, 44) }, uses: { 35 40 44 }
-  // CHECK:         Goto (liveness: 38)
-  // CHECK:         Goto (liveness: 42)
+  // CHECK:         StaticFieldGet  liveness:12 ranges:[12-44] uses:[35,40,44]
+  // CHECK:         Goto            liveness:38
+  // CHECK:         Goto            liveness:42
   public static void loop8() {
     // 'incoming' must have a use at both back edges.
     boolean incoming = field;
@@ -114,8 +114,8 @@
   }
 
   // CHECK-START: void Main.loop9() liveness (after)
-  // CHECK:         StaticFieldGet (liveness: 22 ranges: { [22, 36) }, uses: { 31 36 }
-  // CHECK:         Goto (liveness: 38)
+  // CHECK:         StaticFieldGet  liveness:22 ranges:[22-36] uses:[31,36]
+  // CHECK:         Goto            liveness:38
   public static void loop9() {
     while (Runtime.getRuntime() != null) {
       // 'incoming' must only have a use in the inner loop.
diff --git a/test/485-checker-dce-loop-update/expected.txt b/test/485-checker-dce-loop-update/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/485-checker-dce-loop-update/expected.txt
diff --git a/test/485-checker-dce-loop-update/info.txt b/test/485-checker-dce-loop-update/info.txt
new file mode 100644
index 0000000..fccf10c
--- /dev/null
+++ b/test/485-checker-dce-loop-update/info.txt
@@ -0,0 +1,2 @@
+Tests loop information update after DCE because block removal can disconnect loops, leaving other
+live blocks outside the loop they had been a member of.
\ No newline at end of file
diff --git a/test/485-checker-dce-loop-update/smali/TestCase.smali b/test/485-checker-dce-loop-update/smali/TestCase.smali
new file mode 100644
index 0000000..487a5df
--- /dev/null
+++ b/test/485-checker-dce-loop-update/smali/TestCase.smali
@@ -0,0 +1,274 @@
+# Copyright (C) 2015 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.
+
+.class public LTestCase;
+
+.super Ljava/lang/Object;
+
+.method public static $inline$True()Z
+  .registers 1
+  const/4 v0, 1
+  return v0
+.end method
+
+
+# CHECK-START: int TestCase.testSingleExit(int, boolean) dead_code_elimination_final (before)
+# CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
+# CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
+# CHECK-DAG:     <<Cst1:i\d+>>  IntConstant 1
+# CHECK-DAG:     <<Cst5:i\d+>>  IntConstant 5
+# CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
+# CHECK-DAG:     <<PhiX:i\d+>>  Phi [<<ArgX>>,<<Add5:i\d+>>,<<Add7:i\d+>>] loop:<<HeaderY:B\d+>>
+# CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
+# CHECK-DAG:                    If [<<Cst1>>]                              loop:<<HeaderY>>
+# CHECK-DAG:     <<Add5>>       Add [<<PhiX>>,<<Cst5>>]                    loop:<<HeaderY>>
+# CHECK-DAG:     <<Add7>>       Add [<<PhiX>>,<<Cst7>>]                    loop:<<HeaderY>>
+# CHECK-DAG:                    Return [<<PhiX>>]                          loop:none
+
+# CHECK-START: int TestCase.testSingleExit(int, boolean) dead_code_elimination_final (after)
+# CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
+# CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
+# CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
+# CHECK-DAG:     <<PhiX:i\d+>>  Phi [<<ArgX>>,<<AddX:i\d+>>]               loop:<<HeaderY:B\d+>>
+# CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
+# CHECK-DAG:     <<AddX>>       Add [<<PhiX>>,<<Cst7>>]                    loop:<<HeaderY>>
+# CHECK-DAG:                    Return [<<PhiX>>]                          loop:none
+
+.method public static testSingleExit(IZ)I
+  .registers 3
+
+  # p0 = int X
+  # p1 = boolean Y
+  # v0 = true
+
+  invoke-static {}, LTestCase;->$inline$True()Z
+  move-result v0
+
+  :loop_start
+  if-eqz p1, :loop_body   # cannot be determined statically
+  if-nez v0, :loop_end    # will always exit
+
+  # Dead block
+  add-int/lit8 p0, p0, 5
+  goto :loop_start
+
+  # Live block
+  :loop_body
+  add-int/lit8 p0, p0, 7
+  goto :loop_start
+
+  :loop_end
+  return p0
+.end method
+
+
+# CHECK-START: int TestCase.testMultipleExits(int, boolean, boolean) dead_code_elimination_final (before)
+# CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
+# CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
+# CHECK-DAG:     <<ArgZ:z\d+>>  ParameterValue
+# CHECK-DAG:     <<Cst1:i\d+>>  IntConstant 1
+# CHECK-DAG:     <<Cst5:i\d+>>  IntConstant 5
+# CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
+# CHECK-DAG:     <<PhiX:i\d+>>  Phi [<<ArgX>>,<<Add5:i\d+>>,<<Add7:i\d+>>] loop:<<HeaderY:B\d+>>
+# CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
+# CHECK-DAG:                    If [<<ArgZ>>]                              loop:<<HeaderY>>
+# CHECK-DAG:                    If [<<Cst1>>]                              loop:<<HeaderY>>
+# CHECK-DAG:     <<Add5>>       Add [<<PhiX>>,<<Cst5>>]                    loop:<<HeaderY>>
+# CHECK-DAG:     <<Add7>>       Add [<<PhiX>>,<<Cst7>>]                    loop:<<HeaderY>>
+# CHECK-DAG:                    Return [<<PhiX>>]                          loop:none
+
+# CHECK-START: int TestCase.testMultipleExits(int, boolean, boolean) dead_code_elimination_final (after)
+# CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
+# CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
+# CHECK-DAG:     <<ArgZ:z\d+>>  ParameterValue
+# CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
+# CHECK-DAG:     <<PhiX:i\d+>>  Phi [<<ArgX>>,<<Add7:i\d+>>]               loop:<<HeaderY:B\d+>>
+# CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
+# CHECK-DAG:     <<Add7>>       Add [<<PhiX>>,<<Cst7>>]                    loop:<<HeaderY>>
+# CHECK-DAG:                    If [<<ArgZ>>]                              loop:none
+# CHECK-DAG:                    Return [<<PhiX>>]                          loop:none
+
+.method public static testMultipleExits(IZZ)I
+  .registers 4
+
+  # p0 = int X
+  # p1 = boolean Y
+  # p2 = boolean Z
+  # v0 = true
+
+  invoke-static {}, LTestCase;->$inline$True()Z
+  move-result v0
+
+  :loop_start
+  if-eqz p1, :loop_body   # cannot be determined statically
+  if-nez p2, :loop_end    # may exit
+  if-nez v0, :loop_end    # will always exit
+
+  # Dead block
+  add-int/lit8 p0, p0, 5
+  goto :loop_start
+
+  # Live block
+  :loop_body
+  add-int/lit8 p0, p0, 7
+  goto :loop_start
+
+  :loop_end
+  return p0
+.end method
+
+
+# CHECK-START: int TestCase.testExitPredecessors(int, boolean, boolean) dead_code_elimination_final (before)
+# CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
+# CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
+# CHECK-DAG:     <<ArgZ:z\d+>>  ParameterValue
+# CHECK-DAG:     <<Cst1:i\d+>>  IntConstant 1
+# CHECK-DAG:     <<Cst5:i\d+>>  IntConstant 5
+# CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
+# CHECK-DAG:     <<Cst9:i\d+>>  IntConstant 9
+# CHECK-DAG:     <<PhiX1:i\d+>> Phi [<<ArgX>>,<<Add5:i\d+>>,<<Add7:i\d+>>] loop:<<HeaderY:B\d+>>
+# CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
+# CHECK-DAG:                    If [<<ArgZ>>]                              loop:<<HeaderY>>
+# CHECK-DAG:     <<Mul9:i\d+>>  Mul [<<PhiX1>>,<<Cst9>>]                   loop:<<HeaderY>>
+# CHECK-DAG:     <<PhiX2:i\d+>> Phi [<<Mul9>>,<<PhiX1>>]                   loop:<<HeaderY>>
+# CHECK-DAG:                    If [<<Cst1>>]                              loop:<<HeaderY>>
+# CHECK-DAG:     <<Add5>>       Add [<<PhiX2>>,<<Cst5>>]                   loop:<<HeaderY>>
+# CHECK-DAG:     <<Add7>>       Add [<<PhiX1>>,<<Cst7>>]                   loop:<<HeaderY>>
+# CHECK-DAG:                    Return [<<PhiX2>>]                         loop:none
+
+# CHECK-START: int TestCase.testExitPredecessors(int, boolean, boolean) dead_code_elimination_final (after)
+# CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
+# CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
+# CHECK-DAG:     <<ArgZ:z\d+>>  ParameterValue
+# CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
+# CHECK-DAG:     <<Cst9:i\d+>>  IntConstant 9
+# CHECK-DAG:     <<PhiX1:i\d+>> Phi [<<ArgX>>,<<Add7:i\d+>>]               loop:<<HeaderY:B\d+>>
+# CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
+# CHECK-DAG:     <<Add7>>       Add [<<PhiX1>>,<<Cst7>>]                   loop:<<HeaderY>>
+# CHECK-DAG:                    If [<<ArgZ>>]                              loop:none
+# CHECK-DAG:     <<Mul9:i\d+>>  Mul [<<PhiX1>>,<<Cst9>>]                   loop:none
+# CHECK-DAG:     <<PhiX2:i\d+>> Phi [<<Mul9>>,<<PhiX1>>]                   loop:none
+# CHECK-DAG:                    Return [<<PhiX2>>]                         loop:none
+
+.method public static testExitPredecessors(IZZ)I
+  .registers 4
+
+  # p0 = int X
+  # p1 = boolean Y
+  # p2 = boolean Z
+  # v0 = true
+
+  invoke-static {}, LTestCase;->$inline$True()Z
+  move-result v0
+
+  :loop_start
+  if-eqz p1, :loop_body   # cannot be determined statically
+
+  # Additional logic which will end up outside the loop
+  if-eqz p2, :skip_if
+  mul-int/lit8 p0, p0, 9
+  :skip_if
+
+  if-nez v0, :loop_end    # will always take the branch
+
+  # Dead block
+  add-int/lit8 p0, p0, 5
+  goto :loop_start
+
+  # Live block
+  :loop_body
+  add-int/lit8 p0, p0, 7
+  goto :loop_start
+
+  :loop_end
+  return p0
+.end method
+
+
+# CHECK-START: int TestCase.testInnerLoop(int, boolean, boolean) dead_code_elimination_final (before)
+# CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
+# CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
+# CHECK-DAG:     <<ArgZ:z\d+>>  ParameterValue
+# CHECK-DAG:     <<Cst0:i\d+>>  IntConstant 0
+# CHECK-DAG:     <<Cst1:i\d+>>  IntConstant 1
+# CHECK-DAG:     <<Cst5:i\d+>>  IntConstant 5
+# CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
+#
+# CHECK-DAG:     <<PhiX:i\d+>>  Phi [<<ArgX>>,<<Add5:i\d+>>,<<Add7:i\d+>>] loop:<<HeaderY:B\d+>>
+# CHECK-DAG:     <<PhiZ1:i\d+>> Phi [<<ArgZ>>,<<XorZ:i\d+>>,<<PhiZ1>>]     loop:<<HeaderY>>
+# CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
+#
+#                               ### Inner loop ###
+# CHECK-DAG:     <<PhiZ2:i\d+>> Phi [<<PhiZ1>>,<<XorZ>>]                   loop:<<HeaderZ:B\d+>>
+# CHECK-DAG:     <<XorZ>>       Xor [<<PhiZ2>>,<<Cst1>>]                   loop:<<HeaderZ>>
+# CHECK-DAG:     <<CondZ:z\d+>> Equal [<<XorZ>>,<<Cst0>>]                  loop:<<HeaderZ>>
+# CHECK-DAG:                    If [<<CondZ>>]                             loop:<<HeaderZ>>
+#
+# CHECK-DAG:     <<Add5>>       Add [<<PhiX>>,<<Cst5>>]                    loop:<<HeaderY>>
+# CHECK-DAG:     <<Add7>>       Add [<<PhiX>>,<<Cst7>>]                    loop:<<HeaderY>>
+# CHECK-DAG:                    Return [<<PhiX>>]                          loop:none
+
+# CHECK-START: int TestCase.testInnerLoop(int, boolean, boolean) dead_code_elimination_final (after)
+# CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
+# CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
+# CHECK-DAG:     <<ArgZ:z\d+>>  ParameterValue
+# CHECK-DAG:     <<Cst0:i\d+>>  IntConstant 0
+# CHECK-DAG:     <<Cst1:i\d+>>  IntConstant 1
+# CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
+#
+# CHECK-DAG:     <<PhiX:i\d+>>  Phi [<<ArgX>>,<<Add7:i\d+>>]               loop:<<HeaderY:B\d+>>
+# CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
+# CHECK-DAG:     <<Add7>>       Add [<<PhiX>>,<<Cst7>>]                    loop:<<HeaderY>>
+#
+#                               ### Inner loop ###
+# CHECK-DAG:     <<PhiZ:i\d+>>  Phi [<<ArgZ>>,<<XorZ:i\d+>>]               loop:<<HeaderZ:B\d+>>
+# CHECK-DAG:     <<XorZ>>       Xor [<<PhiZ>>,<<Cst1>>]                    loop:<<HeaderZ>>
+# CHECK-DAG:     <<CondZ:z\d+>> Equal [<<XorZ>>,<<Cst0>>]                  loop:<<HeaderZ>>
+# CHECK-DAG:                    If [<<CondZ>>]                             loop:<<HeaderZ>>
+#
+# CHECK-DAG:                    Return [<<PhiX>>]                          loop:none
+
+.method public static testInnerLoop(IZZ)I
+  .registers 4
+
+  # p0 = int X
+  # p1 = boolean Y
+  # p2 = boolean Z
+  # v0 = true
+
+  invoke-static {}, LTestCase;->$inline$True()Z
+  move-result v0
+
+  :loop_start
+  if-eqz p1, :loop_body   # cannot be determined statically
+
+  # Inner loop which will end up outside its parent
+  :inner_loop_start
+  xor-int/lit8 p2, p2, 1
+  if-eqz p2, :inner_loop_start
+
+  if-nez v0, :loop_end    # will always take the branch
+
+  # Dead block
+  add-int/lit8 p0, p0, 5
+  goto :loop_start
+
+  # Live block
+  :loop_body
+  add-int/lit8 p0, p0, 7
+  goto :loop_start
+
+  :loop_end
+  return p0
+.end method
diff --git a/test/485-checker-dce-loop-update/src/Main.java b/test/485-checker-dce-loop-update/src/Main.java
new file mode 100644
index 0000000..6bfe08b
--- /dev/null
+++ b/test/485-checker-dce-loop-update/src/Main.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+import java.lang.reflect.Method;
+
+public class Main {
+
+  // Workaround for b/18051191.
+  class InnerClass {}
+
+  public static void main(String[] args) throws Exception {
+    return;
+  }
+}
diff --git a/test/701-easy-div-rem/build b/test/701-easy-div-rem/build
new file mode 100644
index 0000000..1dc8452
--- /dev/null
+++ b/test/701-easy-div-rem/build
@@ -0,0 +1,28 @@
+#!/bin/bash
+#
+# Copyright (C) 2014 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.
+
+# Stop if something fails.
+set -e
+
+# Write out the source file.
+mkdir src
+python ./genMain.py
+
+# Increase the file size limitation for classes.lst as the machine generated
+# source file contains a lot of methods and is quite large.
+ulimit -S 4096
+
+./default-build
diff --git a/test/701-easy-div-rem/genMain.py b/test/701-easy-div-rem/genMain.py
index 80eac34..75eee17 100644
--- a/test/701-easy-div-rem/genMain.py
+++ b/test/701-easy-div-rem/genMain.py
@@ -12,15 +12,28 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+upper_bound_int_pow2 = 31
+upper_bound_long_pow2 = 63
+upper_bound_constant = 100
 all_tests = [
     ({'@INT@': 'int', '@SUFFIX@':''},
-     [('CheckDiv', 'idiv_by_pow2_', [2**i for i in range(31)]),
-      ('CheckDiv', 'idiv_by_small_', [i for i in range(3, 16) if i not in (4, 8)]),
-      ('CheckRem', 'irem_by_pow2_', [2**i for i in range(31)])]),
+     [('CheckDiv', 'idiv_by_pow2_', [2**i for i in range(upper_bound_int_pow2)]),
+      ('CheckDiv', 'idiv_by_pow2_neg_', [-2**i for i in range(upper_bound_int_pow2)]),
+      ('CheckDiv', 'idiv_by_constant_', [i for i in range(1, upper_bound_constant)]),
+      ('CheckDiv', 'idiv_by_constant_neg_', [-i for i in range(1, upper_bound_constant)]),
+      ('CheckRem', 'irem_by_pow2_', [2**i for i in range(upper_bound_int_pow2)]),
+      ('CheckRem', 'irem_by_pow2_neg_', [-2**i for i in range(upper_bound_int_pow2)]),
+      ('CheckRem', 'irem_by_constant_', [i for i in range(1, upper_bound_constant)]),
+      ('CheckRem', 'irem_by_constant_neg_', [-i for i in range(1, upper_bound_constant)])]),
     ({'@INT@': 'long', '@SUFFIX@': 'l'},
-     [('CheckDiv', 'ldiv_by_pow2_', [2**i for i in range(63)]),
-      ('CheckDiv', 'ldiv_by_small_', [i for i in range(3, 16) if i not in (4, 8)]),
-      ('CheckRem', 'lrem_by_pow2_', [2**i for i in range(63)])])
+     [('CheckDiv', 'ldiv_by_pow2_', [2**i for i in range(upper_bound_long_pow2)]),
+      ('CheckDiv', 'ldiv_by_pow2_neg_', [-2**i for i in range(upper_bound_long_pow2)]),
+      ('CheckDiv', 'ldiv_by_constant_', [i for i in range(1, upper_bound_constant)]),
+      ('CheckDiv', 'ldiv_by_constant_neg_', [-i for i in range(1, upper_bound_constant)]),
+      ('CheckRem', 'lrem_by_pow2_', [2**i for i in range(upper_bound_long_pow2)]),
+      ('CheckRem', 'lrem_by_pow2_neg_', [-2**i for i in range(upper_bound_long_pow2)]),
+      ('CheckRem', 'lrem_by_constant_', [i for i in range(1, upper_bound_constant)]),
+      ('CheckRem', 'lrem_by_constant_neg_', [-i for i in range(1, upper_bound_constant)])])
 ]
 
 def subst_vars(variables, text):
diff --git a/test/701-easy-div-rem/src/Main.java b/test/701-easy-div-rem/src/Main.java
deleted file mode 100644
index f995f61..0000000
--- a/test/701-easy-div-rem/src/Main.java
+++ /dev/null
@@ -1,529 +0,0 @@
-/*
- * Copyright (C) 2014 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 {
-    public static int num_errors = 0;
-
-    public static void reportError(String message) {
-        if (num_errors == 10) {
-            System.out.println("Omitting other error messages...");
-        } else if (num_errors < 10) {
-            System.out.println(message);
-        }
-        num_errors += 1;
-    }
-
-    public static void intCheckDiv(String desc, int result, int dividend, int divisor) {
-        int correct_result = dividend / divisor;
-        if (result != correct_result) {
-            reportError(desc + "(" + dividend + ") == " + result +
-                        " should be " + correct_result);
-        }
-    }
-    public static void intCheckRem(String desc, int result, int dividend, int divisor) {
-        int correct_result = dividend % divisor;
-        if (result != correct_result) {
-            reportError(desc + "(" + dividend + ") == " + result +
-                        " should be " + correct_result);
-        }
-    }
-    public static void longCheckDiv(String desc, long result, long dividend, long divisor) {
-        long correct_result = dividend / divisor;
-        if (result != correct_result) {
-            reportError(desc + "(" + dividend + ") == " + result +
-                        " should be " + correct_result);
-        }
-    }
-    public static void longCheckRem(String desc, long result, long dividend, long divisor) {
-        long correct_result = dividend % divisor;
-        if (result != correct_result) {
-            reportError(desc + "(" + dividend + ") == " + result +
-                        " should be " + correct_result);
-        }
-    }
-
-    public static int idiv_by_pow2_0(int x) {return x / 1;}
-    public static int idiv_by_pow2_1(int x) {return x / 2;}
-    public static int idiv_by_pow2_2(int x) {return x / 4;}
-    public static int idiv_by_pow2_3(int x) {return x / 8;}
-    public static int idiv_by_pow2_4(int x) {return x / 16;}
-    public static int idiv_by_pow2_5(int x) {return x / 32;}
-    public static int idiv_by_pow2_6(int x) {return x / 64;}
-    public static int idiv_by_pow2_7(int x) {return x / 128;}
-    public static int idiv_by_pow2_8(int x) {return x / 256;}
-    public static int idiv_by_pow2_9(int x) {return x / 512;}
-    public static int idiv_by_pow2_10(int x) {return x / 1024;}
-    public static int idiv_by_pow2_11(int x) {return x / 2048;}
-    public static int idiv_by_pow2_12(int x) {return x / 4096;}
-    public static int idiv_by_pow2_13(int x) {return x / 8192;}
-    public static int idiv_by_pow2_14(int x) {return x / 16384;}
-    public static int idiv_by_pow2_15(int x) {return x / 32768;}
-    public static int idiv_by_pow2_16(int x) {return x / 65536;}
-    public static int idiv_by_pow2_17(int x) {return x / 131072;}
-    public static int idiv_by_pow2_18(int x) {return x / 262144;}
-    public static int idiv_by_pow2_19(int x) {return x / 524288;}
-    public static int idiv_by_pow2_20(int x) {return x / 1048576;}
-    public static int idiv_by_pow2_21(int x) {return x / 2097152;}
-    public static int idiv_by_pow2_22(int x) {return x / 4194304;}
-    public static int idiv_by_pow2_23(int x) {return x / 8388608;}
-    public static int idiv_by_pow2_24(int x) {return x / 16777216;}
-    public static int idiv_by_pow2_25(int x) {return x / 33554432;}
-    public static int idiv_by_pow2_26(int x) {return x / 67108864;}
-    public static int idiv_by_pow2_27(int x) {return x / 134217728;}
-    public static int idiv_by_pow2_28(int x) {return x / 268435456;}
-    public static int idiv_by_pow2_29(int x) {return x / 536870912;}
-    public static int idiv_by_pow2_30(int x) {return x / 1073741824;}
-    public static int idiv_by_small_0(int x) {return x / 3;}
-    public static int idiv_by_small_1(int x) {return x / 5;}
-    public static int idiv_by_small_2(int x) {return x / 6;}
-    public static int idiv_by_small_3(int x) {return x / 7;}
-    public static int idiv_by_small_4(int x) {return x / 9;}
-    public static int idiv_by_small_5(int x) {return x / 10;}
-    public static int idiv_by_small_6(int x) {return x / 11;}
-    public static int idiv_by_small_7(int x) {return x / 12;}
-    public static int idiv_by_small_8(int x) {return x / 13;}
-    public static int idiv_by_small_9(int x) {return x / 14;}
-    public static int idiv_by_small_10(int x) {return x / 15;}
-    public static int irem_by_pow2_0(int x) {return x % 1;}
-    public static int irem_by_pow2_1(int x) {return x % 2;}
-    public static int irem_by_pow2_2(int x) {return x % 4;}
-    public static int irem_by_pow2_3(int x) {return x % 8;}
-    public static int irem_by_pow2_4(int x) {return x % 16;}
-    public static int irem_by_pow2_5(int x) {return x % 32;}
-    public static int irem_by_pow2_6(int x) {return x % 64;}
-    public static int irem_by_pow2_7(int x) {return x % 128;}
-    public static int irem_by_pow2_8(int x) {return x % 256;}
-    public static int irem_by_pow2_9(int x) {return x % 512;}
-    public static int irem_by_pow2_10(int x) {return x % 1024;}
-    public static int irem_by_pow2_11(int x) {return x % 2048;}
-    public static int irem_by_pow2_12(int x) {return x % 4096;}
-    public static int irem_by_pow2_13(int x) {return x % 8192;}
-    public static int irem_by_pow2_14(int x) {return x % 16384;}
-    public static int irem_by_pow2_15(int x) {return x % 32768;}
-    public static int irem_by_pow2_16(int x) {return x % 65536;}
-    public static int irem_by_pow2_17(int x) {return x % 131072;}
-    public static int irem_by_pow2_18(int x) {return x % 262144;}
-    public static int irem_by_pow2_19(int x) {return x % 524288;}
-    public static int irem_by_pow2_20(int x) {return x % 1048576;}
-    public static int irem_by_pow2_21(int x) {return x % 2097152;}
-    public static int irem_by_pow2_22(int x) {return x % 4194304;}
-    public static int irem_by_pow2_23(int x) {return x % 8388608;}
-    public static int irem_by_pow2_24(int x) {return x % 16777216;}
-    public static int irem_by_pow2_25(int x) {return x % 33554432;}
-    public static int irem_by_pow2_26(int x) {return x % 67108864;}
-    public static int irem_by_pow2_27(int x) {return x % 134217728;}
-    public static int irem_by_pow2_28(int x) {return x % 268435456;}
-    public static int irem_by_pow2_29(int x) {return x % 536870912;}
-    public static int irem_by_pow2_30(int x) {return x % 1073741824;}
-    public static long ldiv_by_pow2_0(long x) {return x / 1l;}
-    public static long ldiv_by_pow2_1(long x) {return x / 2l;}
-    public static long ldiv_by_pow2_2(long x) {return x / 4l;}
-    public static long ldiv_by_pow2_3(long x) {return x / 8l;}
-    public static long ldiv_by_pow2_4(long x) {return x / 16l;}
-    public static long ldiv_by_pow2_5(long x) {return x / 32l;}
-    public static long ldiv_by_pow2_6(long x) {return x / 64l;}
-    public static long ldiv_by_pow2_7(long x) {return x / 128l;}
-    public static long ldiv_by_pow2_8(long x) {return x / 256l;}
-    public static long ldiv_by_pow2_9(long x) {return x / 512l;}
-    public static long ldiv_by_pow2_10(long x) {return x / 1024l;}
-    public static long ldiv_by_pow2_11(long x) {return x / 2048l;}
-    public static long ldiv_by_pow2_12(long x) {return x / 4096l;}
-    public static long ldiv_by_pow2_13(long x) {return x / 8192l;}
-    public static long ldiv_by_pow2_14(long x) {return x / 16384l;}
-    public static long ldiv_by_pow2_15(long x) {return x / 32768l;}
-    public static long ldiv_by_pow2_16(long x) {return x / 65536l;}
-    public static long ldiv_by_pow2_17(long x) {return x / 131072l;}
-    public static long ldiv_by_pow2_18(long x) {return x / 262144l;}
-    public static long ldiv_by_pow2_19(long x) {return x / 524288l;}
-    public static long ldiv_by_pow2_20(long x) {return x / 1048576l;}
-    public static long ldiv_by_pow2_21(long x) {return x / 2097152l;}
-    public static long ldiv_by_pow2_22(long x) {return x / 4194304l;}
-    public static long ldiv_by_pow2_23(long x) {return x / 8388608l;}
-    public static long ldiv_by_pow2_24(long x) {return x / 16777216l;}
-    public static long ldiv_by_pow2_25(long x) {return x / 33554432l;}
-    public static long ldiv_by_pow2_26(long x) {return x / 67108864l;}
-    public static long ldiv_by_pow2_27(long x) {return x / 134217728l;}
-    public static long ldiv_by_pow2_28(long x) {return x / 268435456l;}
-    public static long ldiv_by_pow2_29(long x) {return x / 536870912l;}
-    public static long ldiv_by_pow2_30(long x) {return x / 1073741824l;}
-    public static long ldiv_by_pow2_31(long x) {return x / 2147483648l;}
-    public static long ldiv_by_pow2_32(long x) {return x / 4294967296l;}
-    public static long ldiv_by_pow2_33(long x) {return x / 8589934592l;}
-    public static long ldiv_by_pow2_34(long x) {return x / 17179869184l;}
-    public static long ldiv_by_pow2_35(long x) {return x / 34359738368l;}
-    public static long ldiv_by_pow2_36(long x) {return x / 68719476736l;}
-    public static long ldiv_by_pow2_37(long x) {return x / 137438953472l;}
-    public static long ldiv_by_pow2_38(long x) {return x / 274877906944l;}
-    public static long ldiv_by_pow2_39(long x) {return x / 549755813888l;}
-    public static long ldiv_by_pow2_40(long x) {return x / 1099511627776l;}
-    public static long ldiv_by_pow2_41(long x) {return x / 2199023255552l;}
-    public static long ldiv_by_pow2_42(long x) {return x / 4398046511104l;}
-    public static long ldiv_by_pow2_43(long x) {return x / 8796093022208l;}
-    public static long ldiv_by_pow2_44(long x) {return x / 17592186044416l;}
-    public static long ldiv_by_pow2_45(long x) {return x / 35184372088832l;}
-    public static long ldiv_by_pow2_46(long x) {return x / 70368744177664l;}
-    public static long ldiv_by_pow2_47(long x) {return x / 140737488355328l;}
-    public static long ldiv_by_pow2_48(long x) {return x / 281474976710656l;}
-    public static long ldiv_by_pow2_49(long x) {return x / 562949953421312l;}
-    public static long ldiv_by_pow2_50(long x) {return x / 1125899906842624l;}
-    public static long ldiv_by_pow2_51(long x) {return x / 2251799813685248l;}
-    public static long ldiv_by_pow2_52(long x) {return x / 4503599627370496l;}
-    public static long ldiv_by_pow2_53(long x) {return x / 9007199254740992l;}
-    public static long ldiv_by_pow2_54(long x) {return x / 18014398509481984l;}
-    public static long ldiv_by_pow2_55(long x) {return x / 36028797018963968l;}
-    public static long ldiv_by_pow2_56(long x) {return x / 72057594037927936l;}
-    public static long ldiv_by_pow2_57(long x) {return x / 144115188075855872l;}
-    public static long ldiv_by_pow2_58(long x) {return x / 288230376151711744l;}
-    public static long ldiv_by_pow2_59(long x) {return x / 576460752303423488l;}
-    public static long ldiv_by_pow2_60(long x) {return x / 1152921504606846976l;}
-    public static long ldiv_by_pow2_61(long x) {return x / 2305843009213693952l;}
-    public static long ldiv_by_pow2_62(long x) {return x / 4611686018427387904l;}
-    public static long ldiv_by_small_0(long x) {return x / 3l;}
-    public static long ldiv_by_small_1(long x) {return x / 5l;}
-    public static long ldiv_by_small_2(long x) {return x / 6l;}
-    public static long ldiv_by_small_3(long x) {return x / 7l;}
-    public static long ldiv_by_small_4(long x) {return x / 9l;}
-    public static long ldiv_by_small_5(long x) {return x / 10l;}
-    public static long ldiv_by_small_6(long x) {return x / 11l;}
-    public static long ldiv_by_small_7(long x) {return x / 12l;}
-    public static long ldiv_by_small_8(long x) {return x / 13l;}
-    public static long ldiv_by_small_9(long x) {return x / 14l;}
-    public static long ldiv_by_small_10(long x) {return x / 15l;}
-    public static long lrem_by_pow2_0(long x) {return x % 1l;}
-    public static long lrem_by_pow2_1(long x) {return x % 2l;}
-    public static long lrem_by_pow2_2(long x) {return x % 4l;}
-    public static long lrem_by_pow2_3(long x) {return x % 8l;}
-    public static long lrem_by_pow2_4(long x) {return x % 16l;}
-    public static long lrem_by_pow2_5(long x) {return x % 32l;}
-    public static long lrem_by_pow2_6(long x) {return x % 64l;}
-    public static long lrem_by_pow2_7(long x) {return x % 128l;}
-    public static long lrem_by_pow2_8(long x) {return x % 256l;}
-    public static long lrem_by_pow2_9(long x) {return x % 512l;}
-    public static long lrem_by_pow2_10(long x) {return x % 1024l;}
-    public static long lrem_by_pow2_11(long x) {return x % 2048l;}
-    public static long lrem_by_pow2_12(long x) {return x % 4096l;}
-    public static long lrem_by_pow2_13(long x) {return x % 8192l;}
-    public static long lrem_by_pow2_14(long x) {return x % 16384l;}
-    public static long lrem_by_pow2_15(long x) {return x % 32768l;}
-    public static long lrem_by_pow2_16(long x) {return x % 65536l;}
-    public static long lrem_by_pow2_17(long x) {return x % 131072l;}
-    public static long lrem_by_pow2_18(long x) {return x % 262144l;}
-    public static long lrem_by_pow2_19(long x) {return x % 524288l;}
-    public static long lrem_by_pow2_20(long x) {return x % 1048576l;}
-    public static long lrem_by_pow2_21(long x) {return x % 2097152l;}
-    public static long lrem_by_pow2_22(long x) {return x % 4194304l;}
-    public static long lrem_by_pow2_23(long x) {return x % 8388608l;}
-    public static long lrem_by_pow2_24(long x) {return x % 16777216l;}
-    public static long lrem_by_pow2_25(long x) {return x % 33554432l;}
-    public static long lrem_by_pow2_26(long x) {return x % 67108864l;}
-    public static long lrem_by_pow2_27(long x) {return x % 134217728l;}
-    public static long lrem_by_pow2_28(long x) {return x % 268435456l;}
-    public static long lrem_by_pow2_29(long x) {return x % 536870912l;}
-    public static long lrem_by_pow2_30(long x) {return x % 1073741824l;}
-    public static long lrem_by_pow2_31(long x) {return x % 2147483648l;}
-    public static long lrem_by_pow2_32(long x) {return x % 4294967296l;}
-    public static long lrem_by_pow2_33(long x) {return x % 8589934592l;}
-    public static long lrem_by_pow2_34(long x) {return x % 17179869184l;}
-    public static long lrem_by_pow2_35(long x) {return x % 34359738368l;}
-    public static long lrem_by_pow2_36(long x) {return x % 68719476736l;}
-    public static long lrem_by_pow2_37(long x) {return x % 137438953472l;}
-    public static long lrem_by_pow2_38(long x) {return x % 274877906944l;}
-    public static long lrem_by_pow2_39(long x) {return x % 549755813888l;}
-    public static long lrem_by_pow2_40(long x) {return x % 1099511627776l;}
-    public static long lrem_by_pow2_41(long x) {return x % 2199023255552l;}
-    public static long lrem_by_pow2_42(long x) {return x % 4398046511104l;}
-    public static long lrem_by_pow2_43(long x) {return x % 8796093022208l;}
-    public static long lrem_by_pow2_44(long x) {return x % 17592186044416l;}
-    public static long lrem_by_pow2_45(long x) {return x % 35184372088832l;}
-    public static long lrem_by_pow2_46(long x) {return x % 70368744177664l;}
-    public static long lrem_by_pow2_47(long x) {return x % 140737488355328l;}
-    public static long lrem_by_pow2_48(long x) {return x % 281474976710656l;}
-    public static long lrem_by_pow2_49(long x) {return x % 562949953421312l;}
-    public static long lrem_by_pow2_50(long x) {return x % 1125899906842624l;}
-    public static long lrem_by_pow2_51(long x) {return x % 2251799813685248l;}
-    public static long lrem_by_pow2_52(long x) {return x % 4503599627370496l;}
-    public static long lrem_by_pow2_53(long x) {return x % 9007199254740992l;}
-    public static long lrem_by_pow2_54(long x) {return x % 18014398509481984l;}
-    public static long lrem_by_pow2_55(long x) {return x % 36028797018963968l;}
-    public static long lrem_by_pow2_56(long x) {return x % 72057594037927936l;}
-    public static long lrem_by_pow2_57(long x) {return x % 144115188075855872l;}
-    public static long lrem_by_pow2_58(long x) {return x % 288230376151711744l;}
-    public static long lrem_by_pow2_59(long x) {return x % 576460752303423488l;}
-    public static long lrem_by_pow2_60(long x) {return x % 1152921504606846976l;}
-    public static long lrem_by_pow2_61(long x) {return x % 2305843009213693952l;}
-    public static long lrem_by_pow2_62(long x) {return x % 4611686018427387904l;}
-
-    public static void intCheckAll(int x) {
-        intCheckDiv("idiv_by_pow2_0", idiv_by_pow2_0(x), x, 1);
-        intCheckDiv("idiv_by_pow2_1", idiv_by_pow2_1(x), x, 2);
-        intCheckDiv("idiv_by_pow2_2", idiv_by_pow2_2(x), x, 4);
-        intCheckDiv("idiv_by_pow2_3", idiv_by_pow2_3(x), x, 8);
-        intCheckDiv("idiv_by_pow2_4", idiv_by_pow2_4(x), x, 16);
-        intCheckDiv("idiv_by_pow2_5", idiv_by_pow2_5(x), x, 32);
-        intCheckDiv("idiv_by_pow2_6", idiv_by_pow2_6(x), x, 64);
-        intCheckDiv("idiv_by_pow2_7", idiv_by_pow2_7(x), x, 128);
-        intCheckDiv("idiv_by_pow2_8", idiv_by_pow2_8(x), x, 256);
-        intCheckDiv("idiv_by_pow2_9", idiv_by_pow2_9(x), x, 512);
-        intCheckDiv("idiv_by_pow2_10", idiv_by_pow2_10(x), x, 1024);
-        intCheckDiv("idiv_by_pow2_11", idiv_by_pow2_11(x), x, 2048);
-        intCheckDiv("idiv_by_pow2_12", idiv_by_pow2_12(x), x, 4096);
-        intCheckDiv("idiv_by_pow2_13", idiv_by_pow2_13(x), x, 8192);
-        intCheckDiv("idiv_by_pow2_14", idiv_by_pow2_14(x), x, 16384);
-        intCheckDiv("idiv_by_pow2_15", idiv_by_pow2_15(x), x, 32768);
-        intCheckDiv("idiv_by_pow2_16", idiv_by_pow2_16(x), x, 65536);
-        intCheckDiv("idiv_by_pow2_17", idiv_by_pow2_17(x), x, 131072);
-        intCheckDiv("idiv_by_pow2_18", idiv_by_pow2_18(x), x, 262144);
-        intCheckDiv("idiv_by_pow2_19", idiv_by_pow2_19(x), x, 524288);
-        intCheckDiv("idiv_by_pow2_20", idiv_by_pow2_20(x), x, 1048576);
-        intCheckDiv("idiv_by_pow2_21", idiv_by_pow2_21(x), x, 2097152);
-        intCheckDiv("idiv_by_pow2_22", idiv_by_pow2_22(x), x, 4194304);
-        intCheckDiv("idiv_by_pow2_23", idiv_by_pow2_23(x), x, 8388608);
-        intCheckDiv("idiv_by_pow2_24", idiv_by_pow2_24(x), x, 16777216);
-        intCheckDiv("idiv_by_pow2_25", idiv_by_pow2_25(x), x, 33554432);
-        intCheckDiv("idiv_by_pow2_26", idiv_by_pow2_26(x), x, 67108864);
-        intCheckDiv("idiv_by_pow2_27", idiv_by_pow2_27(x), x, 134217728);
-        intCheckDiv("idiv_by_pow2_28", idiv_by_pow2_28(x), x, 268435456);
-        intCheckDiv("idiv_by_pow2_29", idiv_by_pow2_29(x), x, 536870912);
-        intCheckDiv("idiv_by_pow2_30", idiv_by_pow2_30(x), x, 1073741824);
-        intCheckDiv("idiv_by_small_0", idiv_by_small_0(x), x, 3);
-        intCheckDiv("idiv_by_small_1", idiv_by_small_1(x), x, 5);
-        intCheckDiv("idiv_by_small_2", idiv_by_small_2(x), x, 6);
-        intCheckDiv("idiv_by_small_3", idiv_by_small_3(x), x, 7);
-        intCheckDiv("idiv_by_small_4", idiv_by_small_4(x), x, 9);
-        intCheckDiv("idiv_by_small_5", idiv_by_small_5(x), x, 10);
-        intCheckDiv("idiv_by_small_6", idiv_by_small_6(x), x, 11);
-        intCheckDiv("idiv_by_small_7", idiv_by_small_7(x), x, 12);
-        intCheckDiv("idiv_by_small_8", idiv_by_small_8(x), x, 13);
-        intCheckDiv("idiv_by_small_9", idiv_by_small_9(x), x, 14);
-        intCheckDiv("idiv_by_small_10", idiv_by_small_10(x), x, 15);
-        intCheckRem("irem_by_pow2_0", irem_by_pow2_0(x), x, 1);
-        intCheckRem("irem_by_pow2_1", irem_by_pow2_1(x), x, 2);
-        intCheckRem("irem_by_pow2_2", irem_by_pow2_2(x), x, 4);
-        intCheckRem("irem_by_pow2_3", irem_by_pow2_3(x), x, 8);
-        intCheckRem("irem_by_pow2_4", irem_by_pow2_4(x), x, 16);
-        intCheckRem("irem_by_pow2_5", irem_by_pow2_5(x), x, 32);
-        intCheckRem("irem_by_pow2_6", irem_by_pow2_6(x), x, 64);
-        intCheckRem("irem_by_pow2_7", irem_by_pow2_7(x), x, 128);
-        intCheckRem("irem_by_pow2_8", irem_by_pow2_8(x), x, 256);
-        intCheckRem("irem_by_pow2_9", irem_by_pow2_9(x), x, 512);
-        intCheckRem("irem_by_pow2_10", irem_by_pow2_10(x), x, 1024);
-        intCheckRem("irem_by_pow2_11", irem_by_pow2_11(x), x, 2048);
-        intCheckRem("irem_by_pow2_12", irem_by_pow2_12(x), x, 4096);
-        intCheckRem("irem_by_pow2_13", irem_by_pow2_13(x), x, 8192);
-        intCheckRem("irem_by_pow2_14", irem_by_pow2_14(x), x, 16384);
-        intCheckRem("irem_by_pow2_15", irem_by_pow2_15(x), x, 32768);
-        intCheckRem("irem_by_pow2_16", irem_by_pow2_16(x), x, 65536);
-        intCheckRem("irem_by_pow2_17", irem_by_pow2_17(x), x, 131072);
-        intCheckRem("irem_by_pow2_18", irem_by_pow2_18(x), x, 262144);
-        intCheckRem("irem_by_pow2_19", irem_by_pow2_19(x), x, 524288);
-        intCheckRem("irem_by_pow2_20", irem_by_pow2_20(x), x, 1048576);
-        intCheckRem("irem_by_pow2_21", irem_by_pow2_21(x), x, 2097152);
-        intCheckRem("irem_by_pow2_22", irem_by_pow2_22(x), x, 4194304);
-        intCheckRem("irem_by_pow2_23", irem_by_pow2_23(x), x, 8388608);
-        intCheckRem("irem_by_pow2_24", irem_by_pow2_24(x), x, 16777216);
-        intCheckRem("irem_by_pow2_25", irem_by_pow2_25(x), x, 33554432);
-        intCheckRem("irem_by_pow2_26", irem_by_pow2_26(x), x, 67108864);
-        intCheckRem("irem_by_pow2_27", irem_by_pow2_27(x), x, 134217728);
-        intCheckRem("irem_by_pow2_28", irem_by_pow2_28(x), x, 268435456);
-        intCheckRem("irem_by_pow2_29", irem_by_pow2_29(x), x, 536870912);
-        intCheckRem("irem_by_pow2_30", irem_by_pow2_30(x), x, 1073741824);
-    }
-
-    public static void longCheckAll(long x) {
-        longCheckDiv("ldiv_by_pow2_0", ldiv_by_pow2_0(x), x, 1l);
-        longCheckDiv("ldiv_by_pow2_1", ldiv_by_pow2_1(x), x, 2l);
-        longCheckDiv("ldiv_by_pow2_2", ldiv_by_pow2_2(x), x, 4l);
-        longCheckDiv("ldiv_by_pow2_3", ldiv_by_pow2_3(x), x, 8l);
-        longCheckDiv("ldiv_by_pow2_4", ldiv_by_pow2_4(x), x, 16l);
-        longCheckDiv("ldiv_by_pow2_5", ldiv_by_pow2_5(x), x, 32l);
-        longCheckDiv("ldiv_by_pow2_6", ldiv_by_pow2_6(x), x, 64l);
-        longCheckDiv("ldiv_by_pow2_7", ldiv_by_pow2_7(x), x, 128l);
-        longCheckDiv("ldiv_by_pow2_8", ldiv_by_pow2_8(x), x, 256l);
-        longCheckDiv("ldiv_by_pow2_9", ldiv_by_pow2_9(x), x, 512l);
-        longCheckDiv("ldiv_by_pow2_10", ldiv_by_pow2_10(x), x, 1024l);
-        longCheckDiv("ldiv_by_pow2_11", ldiv_by_pow2_11(x), x, 2048l);
-        longCheckDiv("ldiv_by_pow2_12", ldiv_by_pow2_12(x), x, 4096l);
-        longCheckDiv("ldiv_by_pow2_13", ldiv_by_pow2_13(x), x, 8192l);
-        longCheckDiv("ldiv_by_pow2_14", ldiv_by_pow2_14(x), x, 16384l);
-        longCheckDiv("ldiv_by_pow2_15", ldiv_by_pow2_15(x), x, 32768l);
-        longCheckDiv("ldiv_by_pow2_16", ldiv_by_pow2_16(x), x, 65536l);
-        longCheckDiv("ldiv_by_pow2_17", ldiv_by_pow2_17(x), x, 131072l);
-        longCheckDiv("ldiv_by_pow2_18", ldiv_by_pow2_18(x), x, 262144l);
-        longCheckDiv("ldiv_by_pow2_19", ldiv_by_pow2_19(x), x, 524288l);
-        longCheckDiv("ldiv_by_pow2_20", ldiv_by_pow2_20(x), x, 1048576l);
-        longCheckDiv("ldiv_by_pow2_21", ldiv_by_pow2_21(x), x, 2097152l);
-        longCheckDiv("ldiv_by_pow2_22", ldiv_by_pow2_22(x), x, 4194304l);
-        longCheckDiv("ldiv_by_pow2_23", ldiv_by_pow2_23(x), x, 8388608l);
-        longCheckDiv("ldiv_by_pow2_24", ldiv_by_pow2_24(x), x, 16777216l);
-        longCheckDiv("ldiv_by_pow2_25", ldiv_by_pow2_25(x), x, 33554432l);
-        longCheckDiv("ldiv_by_pow2_26", ldiv_by_pow2_26(x), x, 67108864l);
-        longCheckDiv("ldiv_by_pow2_27", ldiv_by_pow2_27(x), x, 134217728l);
-        longCheckDiv("ldiv_by_pow2_28", ldiv_by_pow2_28(x), x, 268435456l);
-        longCheckDiv("ldiv_by_pow2_29", ldiv_by_pow2_29(x), x, 536870912l);
-        longCheckDiv("ldiv_by_pow2_30", ldiv_by_pow2_30(x), x, 1073741824l);
-        longCheckDiv("ldiv_by_pow2_31", ldiv_by_pow2_31(x), x, 2147483648l);
-        longCheckDiv("ldiv_by_pow2_32", ldiv_by_pow2_32(x), x, 4294967296l);
-        longCheckDiv("ldiv_by_pow2_33", ldiv_by_pow2_33(x), x, 8589934592l);
-        longCheckDiv("ldiv_by_pow2_34", ldiv_by_pow2_34(x), x, 17179869184l);
-        longCheckDiv("ldiv_by_pow2_35", ldiv_by_pow2_35(x), x, 34359738368l);
-        longCheckDiv("ldiv_by_pow2_36", ldiv_by_pow2_36(x), x, 68719476736l);
-        longCheckDiv("ldiv_by_pow2_37", ldiv_by_pow2_37(x), x, 137438953472l);
-        longCheckDiv("ldiv_by_pow2_38", ldiv_by_pow2_38(x), x, 274877906944l);
-        longCheckDiv("ldiv_by_pow2_39", ldiv_by_pow2_39(x), x, 549755813888l);
-        longCheckDiv("ldiv_by_pow2_40", ldiv_by_pow2_40(x), x, 1099511627776l);
-        longCheckDiv("ldiv_by_pow2_41", ldiv_by_pow2_41(x), x, 2199023255552l);
-        longCheckDiv("ldiv_by_pow2_42", ldiv_by_pow2_42(x), x, 4398046511104l);
-        longCheckDiv("ldiv_by_pow2_43", ldiv_by_pow2_43(x), x, 8796093022208l);
-        longCheckDiv("ldiv_by_pow2_44", ldiv_by_pow2_44(x), x, 17592186044416l);
-        longCheckDiv("ldiv_by_pow2_45", ldiv_by_pow2_45(x), x, 35184372088832l);
-        longCheckDiv("ldiv_by_pow2_46", ldiv_by_pow2_46(x), x, 70368744177664l);
-        longCheckDiv("ldiv_by_pow2_47", ldiv_by_pow2_47(x), x, 140737488355328l);
-        longCheckDiv("ldiv_by_pow2_48", ldiv_by_pow2_48(x), x, 281474976710656l);
-        longCheckDiv("ldiv_by_pow2_49", ldiv_by_pow2_49(x), x, 562949953421312l);
-        longCheckDiv("ldiv_by_pow2_50", ldiv_by_pow2_50(x), x, 1125899906842624l);
-        longCheckDiv("ldiv_by_pow2_51", ldiv_by_pow2_51(x), x, 2251799813685248l);
-        longCheckDiv("ldiv_by_pow2_52", ldiv_by_pow2_52(x), x, 4503599627370496l);
-        longCheckDiv("ldiv_by_pow2_53", ldiv_by_pow2_53(x), x, 9007199254740992l);
-        longCheckDiv("ldiv_by_pow2_54", ldiv_by_pow2_54(x), x, 18014398509481984l);
-        longCheckDiv("ldiv_by_pow2_55", ldiv_by_pow2_55(x), x, 36028797018963968l);
-        longCheckDiv("ldiv_by_pow2_56", ldiv_by_pow2_56(x), x, 72057594037927936l);
-        longCheckDiv("ldiv_by_pow2_57", ldiv_by_pow2_57(x), x, 144115188075855872l);
-        longCheckDiv("ldiv_by_pow2_58", ldiv_by_pow2_58(x), x, 288230376151711744l);
-        longCheckDiv("ldiv_by_pow2_59", ldiv_by_pow2_59(x), x, 576460752303423488l);
-        longCheckDiv("ldiv_by_pow2_60", ldiv_by_pow2_60(x), x, 1152921504606846976l);
-        longCheckDiv("ldiv_by_pow2_61", ldiv_by_pow2_61(x), x, 2305843009213693952l);
-        longCheckDiv("ldiv_by_pow2_62", ldiv_by_pow2_62(x), x, 4611686018427387904l);
-        longCheckDiv("ldiv_by_small_0", ldiv_by_small_0(x), x, 3l);
-        longCheckDiv("ldiv_by_small_1", ldiv_by_small_1(x), x, 5l);
-        longCheckDiv("ldiv_by_small_2", ldiv_by_small_2(x), x, 6l);
-        longCheckDiv("ldiv_by_small_3", ldiv_by_small_3(x), x, 7l);
-        longCheckDiv("ldiv_by_small_4", ldiv_by_small_4(x), x, 9l);
-        longCheckDiv("ldiv_by_small_5", ldiv_by_small_5(x), x, 10l);
-        longCheckDiv("ldiv_by_small_6", ldiv_by_small_6(x), x, 11l);
-        longCheckDiv("ldiv_by_small_7", ldiv_by_small_7(x), x, 12l);
-        longCheckDiv("ldiv_by_small_8", ldiv_by_small_8(x), x, 13l);
-        longCheckDiv("ldiv_by_small_9", ldiv_by_small_9(x), x, 14l);
-        longCheckDiv("ldiv_by_small_10", ldiv_by_small_10(x), x, 15l);
-        longCheckRem("lrem_by_pow2_0", lrem_by_pow2_0(x), x, 1l);
-        longCheckRem("lrem_by_pow2_1", lrem_by_pow2_1(x), x, 2l);
-        longCheckRem("lrem_by_pow2_2", lrem_by_pow2_2(x), x, 4l);
-        longCheckRem("lrem_by_pow2_3", lrem_by_pow2_3(x), x, 8l);
-        longCheckRem("lrem_by_pow2_4", lrem_by_pow2_4(x), x, 16l);
-        longCheckRem("lrem_by_pow2_5", lrem_by_pow2_5(x), x, 32l);
-        longCheckRem("lrem_by_pow2_6", lrem_by_pow2_6(x), x, 64l);
-        longCheckRem("lrem_by_pow2_7", lrem_by_pow2_7(x), x, 128l);
-        longCheckRem("lrem_by_pow2_8", lrem_by_pow2_8(x), x, 256l);
-        longCheckRem("lrem_by_pow2_9", lrem_by_pow2_9(x), x, 512l);
-        longCheckRem("lrem_by_pow2_10", lrem_by_pow2_10(x), x, 1024l);
-        longCheckRem("lrem_by_pow2_11", lrem_by_pow2_11(x), x, 2048l);
-        longCheckRem("lrem_by_pow2_12", lrem_by_pow2_12(x), x, 4096l);
-        longCheckRem("lrem_by_pow2_13", lrem_by_pow2_13(x), x, 8192l);
-        longCheckRem("lrem_by_pow2_14", lrem_by_pow2_14(x), x, 16384l);
-        longCheckRem("lrem_by_pow2_15", lrem_by_pow2_15(x), x, 32768l);
-        longCheckRem("lrem_by_pow2_16", lrem_by_pow2_16(x), x, 65536l);
-        longCheckRem("lrem_by_pow2_17", lrem_by_pow2_17(x), x, 131072l);
-        longCheckRem("lrem_by_pow2_18", lrem_by_pow2_18(x), x, 262144l);
-        longCheckRem("lrem_by_pow2_19", lrem_by_pow2_19(x), x, 524288l);
-        longCheckRem("lrem_by_pow2_20", lrem_by_pow2_20(x), x, 1048576l);
-        longCheckRem("lrem_by_pow2_21", lrem_by_pow2_21(x), x, 2097152l);
-        longCheckRem("lrem_by_pow2_22", lrem_by_pow2_22(x), x, 4194304l);
-        longCheckRem("lrem_by_pow2_23", lrem_by_pow2_23(x), x, 8388608l);
-        longCheckRem("lrem_by_pow2_24", lrem_by_pow2_24(x), x, 16777216l);
-        longCheckRem("lrem_by_pow2_25", lrem_by_pow2_25(x), x, 33554432l);
-        longCheckRem("lrem_by_pow2_26", lrem_by_pow2_26(x), x, 67108864l);
-        longCheckRem("lrem_by_pow2_27", lrem_by_pow2_27(x), x, 134217728l);
-        longCheckRem("lrem_by_pow2_28", lrem_by_pow2_28(x), x, 268435456l);
-        longCheckRem("lrem_by_pow2_29", lrem_by_pow2_29(x), x, 536870912l);
-        longCheckRem("lrem_by_pow2_30", lrem_by_pow2_30(x), x, 1073741824l);
-        longCheckRem("lrem_by_pow2_31", lrem_by_pow2_31(x), x, 2147483648l);
-        longCheckRem("lrem_by_pow2_32", lrem_by_pow2_32(x), x, 4294967296l);
-        longCheckRem("lrem_by_pow2_33", lrem_by_pow2_33(x), x, 8589934592l);
-        longCheckRem("lrem_by_pow2_34", lrem_by_pow2_34(x), x, 17179869184l);
-        longCheckRem("lrem_by_pow2_35", lrem_by_pow2_35(x), x, 34359738368l);
-        longCheckRem("lrem_by_pow2_36", lrem_by_pow2_36(x), x, 68719476736l);
-        longCheckRem("lrem_by_pow2_37", lrem_by_pow2_37(x), x, 137438953472l);
-        longCheckRem("lrem_by_pow2_38", lrem_by_pow2_38(x), x, 274877906944l);
-        longCheckRem("lrem_by_pow2_39", lrem_by_pow2_39(x), x, 549755813888l);
-        longCheckRem("lrem_by_pow2_40", lrem_by_pow2_40(x), x, 1099511627776l);
-        longCheckRem("lrem_by_pow2_41", lrem_by_pow2_41(x), x, 2199023255552l);
-        longCheckRem("lrem_by_pow2_42", lrem_by_pow2_42(x), x, 4398046511104l);
-        longCheckRem("lrem_by_pow2_43", lrem_by_pow2_43(x), x, 8796093022208l);
-        longCheckRem("lrem_by_pow2_44", lrem_by_pow2_44(x), x, 17592186044416l);
-        longCheckRem("lrem_by_pow2_45", lrem_by_pow2_45(x), x, 35184372088832l);
-        longCheckRem("lrem_by_pow2_46", lrem_by_pow2_46(x), x, 70368744177664l);
-        longCheckRem("lrem_by_pow2_47", lrem_by_pow2_47(x), x, 140737488355328l);
-        longCheckRem("lrem_by_pow2_48", lrem_by_pow2_48(x), x, 281474976710656l);
-        longCheckRem("lrem_by_pow2_49", lrem_by_pow2_49(x), x, 562949953421312l);
-        longCheckRem("lrem_by_pow2_50", lrem_by_pow2_50(x), x, 1125899906842624l);
-        longCheckRem("lrem_by_pow2_51", lrem_by_pow2_51(x), x, 2251799813685248l);
-        longCheckRem("lrem_by_pow2_52", lrem_by_pow2_52(x), x, 4503599627370496l);
-        longCheckRem("lrem_by_pow2_53", lrem_by_pow2_53(x), x, 9007199254740992l);
-        longCheckRem("lrem_by_pow2_54", lrem_by_pow2_54(x), x, 18014398509481984l);
-        longCheckRem("lrem_by_pow2_55", lrem_by_pow2_55(x), x, 36028797018963968l);
-        longCheckRem("lrem_by_pow2_56", lrem_by_pow2_56(x), x, 72057594037927936l);
-        longCheckRem("lrem_by_pow2_57", lrem_by_pow2_57(x), x, 144115188075855872l);
-        longCheckRem("lrem_by_pow2_58", lrem_by_pow2_58(x), x, 288230376151711744l);
-        longCheckRem("lrem_by_pow2_59", lrem_by_pow2_59(x), x, 576460752303423488l);
-        longCheckRem("lrem_by_pow2_60", lrem_by_pow2_60(x), x, 1152921504606846976l);
-        longCheckRem("lrem_by_pow2_61", lrem_by_pow2_61(x), x, 2305843009213693952l);
-        longCheckRem("lrem_by_pow2_62", lrem_by_pow2_62(x), x, 4611686018427387904l);
-    }
-
-    public static void main(String[] args) {
-      int i;
-      long l;
-
-      System.out.println("Begin");
-
-      System.out.println("Int: checking some equally spaced dividends...");
-      for (i = -1000; i < 1000; i += 300) {
-          intCheckAll(i);
-          intCheckAll(-i);
-      }
-
-      System.out.println("Int: checking small dividends...");
-      for (i = 1; i < 100; i += 1) {
-          intCheckAll(i);
-          intCheckAll(-i);
-      }
-
-      System.out.println("Int: checking big dividends...");
-      for (i = 0; i < 100; i += 1) {
-          intCheckAll(Integer.MAX_VALUE - i);
-          intCheckAll(Integer.MIN_VALUE + i);
-      }
-
-      System.out.println("Long: checking some equally spaced dividends...");
-      for (l = 0l; l < 1000000000000l; l += 300000000000l) {
-          longCheckAll(l);
-          longCheckAll(-l);
-      }
-
-      System.out.println("Long: checking small dividends...");
-      for (l = 1l; l < 100l; l += 1l) {
-          longCheckAll(l);
-          longCheckAll(-l);
-      }
-
-      System.out.println("Long: checking big dividends...");
-      for (l = 0l; l < 100l; l += 1l) {
-          longCheckAll(Long.MAX_VALUE - l);
-          longCheckAll(Long.MIN_VALUE + l);
-      }
-
-      System.out.println("End");
-    }
-}
diff --git a/test/702-LargeBranchOffset/build b/test/702-LargeBranchOffset/build
index eacf730..20030fa 100644
--- a/test/702-LargeBranchOffset/build
+++ b/test/702-LargeBranchOffset/build
@@ -17,11 +17,7 @@
 # Stop if something fails.
 set -e
 
-# Write out a bunch of source files.
+# Write out the source file.
 cpp -P src/Main.java.in src/Main.java
 
-mkdir classes
-${JAVAC} -d classes src/*.java
-
-${DX} --debug --dex --output=classes.dex classes
-zip $TEST_NAME.jar classes.dex
+./default-build
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 40f5f00..07e7620 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -428,8 +428,7 @@
 TEST_ART_BROKEN_OPTIMIZING_DEBUGGABLE_RUN_TESTS :=
 
 # Tests that should fail in the read barrier configuration.
-TEST_ART_BROKEN_READ_BARRIER_RUN_TESTS := \
-  098-ddmc  # b/20720510
+TEST_ART_BROKEN_READ_BARRIER_RUN_TESTS :=
 
 ifeq ($(ART_USE_READ_BARRIER),true)
   ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
diff --git a/test/run-test b/test/run-test
index 2873a35..54c6bbd 100755
--- a/test/run-test
+++ b/test/run-test
@@ -39,7 +39,7 @@
 else
   tmp_dir="${TMPDIR}/$USER/${test_dir}"
 fi
-checker="${progdir}/../tools/checker.py"
+checker="${progdir}/../tools/checker/checker.py"
 
 export JAVA="java"
 export JAVAC="javac -g"
@@ -501,14 +501,20 @@
 
 if [ '!' -r "$build" ]; then
     cp "${progdir}/etc/default-build" build
+else
+    cp "${progdir}/etc/default-build" .
 fi
 
 if [ '!' -r "$run" ]; then
     cp "${progdir}/etc/default-run" run
+else
+    cp "${progdir}/etc/default-run" .
 fi
 
 if [ '!' -r "$check_cmd" ]; then
     cp "${progdir}/etc/default-check" check
+else
+    cp "${progdir}/etc/default-check" .
 fi
 
 chmod 755 "$build"
diff --git a/tools/checker.py b/tools/checker.py
deleted file mode 100755
index 0bce236..0000000
--- a/tools/checker.py
+++ /dev/null
@@ -1,777 +0,0 @@
-#!/usr/bin/env python2
-#
-# Copyright (C) 2014 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.
-
-
-# Checker is a testing tool which compiles a given test file and compares the
-# state of the control-flow graph before and after each optimization pass
-# against a set of assertions specified alongside the tests.
-#
-# Tests are written in Java, turned into DEX and compiled with the Optimizing
-# compiler. "Check lines" are assertions formatted as comments of the Java file.
-# They begin with prefix 'CHECK' followed by a pattern that the engine attempts
-# to match in the compiler-generated output.
-#
-# Assertions are tested in groups which correspond to the individual compiler
-# passes. Each group of check lines therefore must start with a 'CHECK-START'
-# header which specifies the output group it should be tested against. The group
-# name must exactly match one of the groups recognized in the output (they can
-# be listed with the '--list-groups' command-line flag).
-#
-# Matching of check lines is carried out in the order of appearance in the
-# source file. There are three types of check lines:
-#  - CHECK:     Must match an output line which appears in the output group
-#               later than lines matched against any preceeding checks. Output
-#               lines must therefore match the check lines in the same order.
-#               These are referred to as "in-order" checks in the code.
-#  - CHECK-DAG: Must match an output line which appears in the output group
-#               later than lines matched against any preceeding in-order checks.
-#               In other words, the order of output lines does not matter
-#               between consecutive DAG checks.
-#  - CHECK-NOT: Must not match any output line which appears in the output group
-#               later than lines matched against any preceeding checks and
-#               earlier than lines matched against any subsequent checks.
-#               Surrounding non-negative checks (or boundaries of the group)
-#               therefore create a scope within which the assertion is verified.
-#
-# Check-line patterns are treated as plain text rather than regular expressions
-# but are whitespace agnostic.
-#
-# Actual regex patterns can be inserted enclosed in '{{' and '}}' brackets. If
-# curly brackets need to be used inside the body of the regex, they need to be
-# enclosed in round brackets. For example, the pattern '{{foo{2}}}' will parse
-# the invalid regex 'foo{2', but '{{(fo{2})}}' will match 'foo'.
-#
-# Regex patterns can be named and referenced later. A new variable is defined
-# with '[[name:regex]]' and can be referenced with '[[name]]'. Variables are
-# only valid within the scope of the defining group. Within a group they cannot
-# be redefined or used undefined.
-#
-# Example:
-#   The following assertions can be placed in a Java source file:
-#
-#   // CHECK-START: int MyClass.MyMethod() constant_folding (after)
-#   // CHECK:         [[ID:i[0-9]+]] IntConstant {{11|22}}
-#   // CHECK:                        Return [ [[ID]] ]
-#
-#   The engine will attempt to match the check lines against the output of the
-#   group named on the first line. Together they verify that the CFG after
-#   constant folding returns an integer constant with value either 11 or 22.
-#
-
-from __future__ import print_function
-import argparse
-import os
-import re
-import shutil
-import sys
-import tempfile
-
-class Logger(object):
-
-  class Level(object):
-    NoOutput, Error, Info = range(3)
-
-  class Color(object):
-    Default, Blue, Gray, Purple, Red = range(5)
-
-    @staticmethod
-    def terminalCode(color, out=sys.stdout):
-      if not out.isatty():
-        return ''
-      elif color == Logger.Color.Blue:
-        return '\033[94m'
-      elif color == Logger.Color.Gray:
-        return '\033[37m'
-      elif color == Logger.Color.Purple:
-        return '\033[95m'
-      elif color == Logger.Color.Red:
-        return '\033[91m'
-      else:
-        return '\033[0m'
-
-  Verbosity = Level.Info
-
-  @staticmethod
-  def log(text, level=Level.Info, color=Color.Default, newLine=True, out=sys.stdout):
-    if level <= Logger.Verbosity:
-      text = Logger.Color.terminalCode(color, out) + text + \
-             Logger.Color.terminalCode(Logger.Color.Default, out)
-      if newLine:
-        print(text, file=out)
-      else:
-        print(text, end="", file=out)
-      out.flush()
-
-  @staticmethod
-  def fail(msg, file=None, line=-1):
-    location = ""
-    if file:
-      location += file + ":"
-    if line > 0:
-      location += str(line) + ":"
-    if location:
-      location += " "
-
-    Logger.log(location, Logger.Level.Error, color=Logger.Color.Gray, newLine=False, out=sys.stderr)
-    Logger.log("error: ", Logger.Level.Error, color=Logger.Color.Red, newLine=False, out=sys.stderr)
-    Logger.log(msg, Logger.Level.Error, out=sys.stderr)
-    sys.exit(msg)
-
-  @staticmethod
-  def startTest(name):
-    Logger.log("TEST ", color=Logger.Color.Purple, newLine=False)
-    Logger.log(name + "... ", newLine=False)
-
-  @staticmethod
-  def testPassed():
-    Logger.log("PASS", color=Logger.Color.Blue)
-
-  @staticmethod
-  def testFailed(msg, file=None, line=-1):
-    Logger.log("FAIL", color=Logger.Color.Red)
-    Logger.fail(msg, file, line)
-
-class CommonEqualityMixin:
-  """Mixin for class equality as equality of the fields."""
-  def __eq__(self, other):
-    return (isinstance(other, self.__class__)
-           and self.__dict__ == other.__dict__)
-
-  def __ne__(self, other):
-    return not self.__eq__(other)
-
-  def __repr__(self):
-    return "<%s: %s>" % (type(self).__name__, str(self.__dict__))
-
-
-class CheckElement(CommonEqualityMixin):
-  """Single element of the check line."""
-
-  class Variant(object):
-    """Supported language constructs."""
-    Text, Pattern, VarRef, VarDef, Separator = range(5)
-
-  rStartOptional = r"("
-  rEndOptional = r")?"
-
-  rName = r"([a-zA-Z][a-zA-Z0-9]*)"
-  rRegex = r"(.+?)"
-  rPatternStartSym = r"(\{\{)"
-  rPatternEndSym = r"(\}\})"
-  rVariableStartSym = r"(\[\[)"
-  rVariableEndSym = r"(\]\])"
-  rVariableSeparator = r"(:)"
-
-  regexPattern = rPatternStartSym + rRegex + rPatternEndSym
-  regexVariable = rVariableStartSym + \
-                    rName + \
-                    (rStartOptional + rVariableSeparator + rRegex + rEndOptional) + \
-                  rVariableEndSym
-
-  def __init__(self, variant, name, pattern):
-    self.variant = variant
-    self.name = name
-    self.pattern = pattern
-
-  @staticmethod
-  def newSeparator():
-    return CheckElement(CheckElement.Variant.Separator, None, None)
-
-  @staticmethod
-  def parseText(text):
-    return CheckElement(CheckElement.Variant.Text, None, re.escape(text))
-
-  @staticmethod
-  def parsePattern(patternElem):
-    return CheckElement(CheckElement.Variant.Pattern, None, patternElem[2:-2])
-
-  @staticmethod
-  def parseVariable(varElem):
-    colonPos = varElem.find(":")
-    if colonPos == -1:
-      # Variable reference
-      name = varElem[2:-2]
-      return CheckElement(CheckElement.Variant.VarRef, name, None)
-    else:
-      # Variable definition
-      name = varElem[2:colonPos]
-      body = varElem[colonPos+1:-2]
-      return CheckElement(CheckElement.Variant.VarDef, name, body)
-
-class CheckLine(CommonEqualityMixin):
-  """Representation of a single assertion in the check file formed of one or
-     more regex elements. Matching against an output line is successful only
-     if all regex elements can be matched in the given order."""
-
-  class Variant(object):
-    """Supported types of assertions."""
-    InOrder, DAG, Not = range(3)
-
-  def __init__(self, content, variant=Variant.InOrder, fileName=None, lineNo=-1):
-    self.fileName = fileName
-    self.lineNo = lineNo
-    self.content = content.strip()
-
-    self.variant = variant
-    self.lineParts = self.__parse(self.content)
-    if not self.lineParts:
-      Logger.fail("Empty check line", self.fileName, self.lineNo)
-
-    if self.variant == CheckLine.Variant.Not:
-      for elem in self.lineParts:
-        if elem.variant == CheckElement.Variant.VarDef:
-          Logger.fail("CHECK-NOT lines cannot define variables", self.fileName, self.lineNo)
-
-  def __eq__(self, other):
-    return (isinstance(other, self.__class__) and
-            self.variant == other.variant and
-            self.lineParts == other.lineParts)
-
-  # Returns True if the given Match object was at the beginning of the line.
-  def __isMatchAtStart(self, match):
-    return (match is not None) and (match.start() == 0)
-
-  # Takes in a list of Match objects and returns the minimal start point among
-  # them. If there aren't any successful matches it returns the length of
-  # the searched string.
-  def __firstMatch(self, matches, string):
-    starts = map(lambda m: len(string) if m is None else m.start(), matches)
-    return min(starts)
-
-  # This method parses the content of a check line stripped of the initial
-  # comment symbol and the CHECK keyword.
-  def __parse(self, line):
-    lineParts = []
-    # Loop as long as there is something to parse.
-    while line:
-      # Search for the nearest occurrence of the special markers.
-      matchWhitespace = re.search(r"\s+", line)
-      matchPattern = re.search(CheckElement.regexPattern, line)
-      matchVariable = re.search(CheckElement.regexVariable, line)
-
-      # If one of the above was identified at the current position, extract them
-      # from the line, parse them and add to the list of line parts.
-      if self.__isMatchAtStart(matchWhitespace):
-        # A whitespace in the check line creates a new separator of line parts.
-        # This allows for ignored output between the previous and next parts.
-        line = line[matchWhitespace.end():]
-        lineParts.append(CheckElement.newSeparator())
-      elif self.__isMatchAtStart(matchPattern):
-        pattern = line[0:matchPattern.end()]
-        line = line[matchPattern.end():]
-        lineParts.append(CheckElement.parsePattern(pattern))
-      elif self.__isMatchAtStart(matchVariable):
-        var = line[0:matchVariable.end()]
-        line = line[matchVariable.end():]
-        lineParts.append(CheckElement.parseVariable(var))
-      else:
-        # If we're not currently looking at a special marker, this is a plain
-        # text match all the way until the first special marker (or the end
-        # of the line).
-        firstMatch = self.__firstMatch([ matchWhitespace, matchPattern, matchVariable ], line)
-        text = line[0:firstMatch]
-        line = line[firstMatch:]
-        lineParts.append(CheckElement.parseText(text))
-    return lineParts
-
-  # Returns the regex pattern to be matched in the output line. Variable
-  # references are substituted with their current values provided in the
-  # 'varState' argument.
-  # An exception is raised if a referenced variable is undefined.
-  def __generatePattern(self, linePart, varState):
-    if linePart.variant == CheckElement.Variant.VarRef:
-      try:
-        return re.escape(varState[linePart.name])
-      except KeyError:
-        Logger.testFailed("Use of undefined variable \"" + linePart.name + "\"",
-                          self.fileName, self.lineNo)
-    else:
-      return linePart.pattern
-
-  def __isSeparated(self, outputLine, matchStart):
-    return (matchStart == 0) or (outputLine[matchStart - 1:matchStart].isspace())
-
-  # Attempts to match the check line against a line from the output file with
-  # the given initial variable values. It returns the new variable state if
-  # successful and None otherwise.
-  def match(self, outputLine, initialVarState):
-    # Do the full matching on a shadow copy of the variable state. If the
-    # matching fails half-way, we will not need to revert the state.
-    varState = dict(initialVarState)
-
-    matchStart = 0
-    isAfterSeparator = True
-
-    # Now try to parse all of the parts of the check line in the right order.
-    # Variable values are updated on-the-fly, meaning that a variable can
-    # be referenced immediately after its definition.
-    for part in self.lineParts:
-      if part.variant == CheckElement.Variant.Separator:
-        isAfterSeparator = True
-        continue
-
-      # Find the earliest match for this line part.
-      pattern = self.__generatePattern(part, varState)
-      while True:
-        match = re.search(pattern, outputLine[matchStart:])
-        if (match is None) or (not isAfterSeparator and not self.__isMatchAtStart(match)):
-          return None
-        matchEnd = matchStart + match.end()
-        matchStart += match.start()
-
-        # Check if this is a valid match if we expect a whitespace separator
-        # before the matched text. Otherwise loop and look for another match.
-        if not isAfterSeparator or self.__isSeparated(outputLine, matchStart):
-          break
-        else:
-          matchStart += 1
-
-      if part.variant == CheckElement.Variant.VarDef:
-        if part.name in varState:
-          Logger.testFailed("Multiple definitions of variable \"" + part.name + "\"",
-                            self.fileName, self.lineNo)
-        varState[part.name] = outputLine[matchStart:matchEnd]
-
-      matchStart = matchEnd
-      isAfterSeparator = False
-
-    # All parts were successfully matched. Return the new variable state.
-    return varState
-
-
-class CheckGroup(CommonEqualityMixin):
-  """Represents a named collection of check lines which are to be matched
-     against an output group of the same name."""
-
-  def __init__(self, name, lines, fileName=None, lineNo=-1):
-    self.fileName = fileName
-    self.lineNo = lineNo
-
-    if not name:
-      Logger.fail("Check group does not have a name", self.fileName, self.lineNo)
-    if not lines:
-      Logger.fail("Check group does not have a body", self.fileName, self.lineNo)
-
-    self.name = name
-    self.lines = lines
-
-  def __eq__(self, other):
-    return (isinstance(other, self.__class__) and
-            self.name == other.name and
-            self.lines == other.lines)
-
-  def __headAndTail(self, list):
-    return list[0], list[1:]
-
-  # Splits a list of check lines at index 'i' such that lines[i] is the first
-  # element whose variant is not equal to the given parameter.
-  def __splitByVariant(self, lines, variant):
-    i = 0
-    while i < len(lines) and lines[i].variant == variant:
-      i += 1
-    return lines[:i], lines[i:]
-
-  # Extracts the first sequence of check lines which are independent of each
-  # other's match location, i.e. either consecutive DAG lines or a single
-  # InOrder line. Any Not lines preceeding this sequence are also extracted.
-  def __nextIndependentChecks(self, checkLines):
-    notChecks, checkLines = self.__splitByVariant(checkLines, CheckLine.Variant.Not)
-    if not checkLines:
-      return notChecks, [], []
-
-    head, tail = self.__headAndTail(checkLines)
-    if head.variant == CheckLine.Variant.InOrder:
-      return notChecks, [head], tail
-    else:
-      assert head.variant == CheckLine.Variant.DAG
-      independentChecks, checkLines = self.__splitByVariant(checkLines, CheckLine.Variant.DAG)
-      return notChecks, independentChecks, checkLines
-
-  # If successful, returns the line number of the first output line matching the
-  # check line and the updated variable state. Otherwise returns -1 and None,
-  # respectively. The 'lineFilter' parameter can be used to supply a list of
-  # line numbers (counting from 1) which should be skipped.
-  def __findFirstMatch(self, checkLine, outputLines, startLineNo, lineFilter, varState):
-    matchLineNo = startLineNo
-    for outputLine in outputLines:
-      if matchLineNo not in lineFilter:
-        newVarState = checkLine.match(outputLine, varState)
-        if newVarState is not None:
-          return matchLineNo, newVarState
-      matchLineNo += 1
-    return -1, None
-
-  # Matches the given positive check lines against the output in order of
-  # appearance. Variable state is propagated but the scope of the search remains
-  # the same for all checks. Each output line can only be matched once.
-  # If all check lines are matched, the resulting variable state is returned
-  # together with the remaining output. The function also returns output lines
-  # which appear before either of the matched lines so they can be tested
-  # against Not checks.
-  def __matchIndependentChecks(self, checkLines, outputLines, startLineNo, varState):
-    # If no checks are provided, skip over the entire output.
-    if not checkLines:
-      return outputLines, [], startLineNo + len(outputLines), varState
-
-    # Keep track of which lines have been matched.
-    matchedLines = []
-
-    # Find first unused output line which matches each check line.
-    for checkLine in checkLines:
-      matchLineNo, varState = \
-        self.__findFirstMatch(checkLine, outputLines, startLineNo, matchedLines, varState)
-      if varState is None:
-        Logger.testFailed("Could not match check line \"" + checkLine.content + "\" " +
-                          "starting from output line " + str(startLineNo),
-                          self.fileName, checkLine.lineNo)
-      matchedLines.append(matchLineNo)
-
-    # Return new variable state and the output lines which lie outside the
-    # match locations of this independent group.
-    minMatchLineNo = min(matchedLines)
-    maxMatchLineNo = max(matchedLines)
-    preceedingLines = outputLines[:minMatchLineNo - startLineNo]
-    remainingLines = outputLines[maxMatchLineNo - startLineNo + 1:]
-    return preceedingLines, remainingLines, maxMatchLineNo + 1, varState
-
-  # Makes sure that the given check lines do not match any of the given output
-  # lines. Variable state does not change.
-  def __matchNotLines(self, checkLines, outputLines, startLineNo, varState):
-    for checkLine in checkLines:
-      assert checkLine.variant == CheckLine.Variant.Not
-      matchLineNo, matchVarState = \
-        self.__findFirstMatch(checkLine, outputLines, startLineNo, [], varState)
-      if matchVarState is not None:
-        Logger.testFailed("CHECK-NOT line \"" + checkLine.content + "\" matches output line " + \
-                          str(matchLineNo), self.fileName, checkLine.lineNo)
-
-  # Matches the check lines in this group against an output group. It is
-  # responsible for running the checks in the right order and scope, and
-  # for propagating the variable state between the check lines.
-  def match(self, outputGroup):
-    varState = {}
-    checkLines = self.lines
-    outputLines = outputGroup.body
-    startLineNo = outputGroup.lineNo
-
-    while checkLines:
-      # Extract the next sequence of location-independent checks to be matched.
-      notChecks, independentChecks, checkLines = self.__nextIndependentChecks(checkLines)
-
-      # Match the independent checks.
-      notOutput, outputLines, newStartLineNo, newVarState = \
-        self.__matchIndependentChecks(independentChecks, outputLines, startLineNo, varState)
-
-      # Run the Not checks against the output lines which lie between the last
-      # two independent groups or the bounds of the output.
-      self.__matchNotLines(notChecks, notOutput, startLineNo, varState)
-
-      # Update variable state.
-      startLineNo = newStartLineNo
-      varState = newVarState
-
-class OutputGroup(CommonEqualityMixin):
-  """Represents a named part of the test output against which a check group of
-     the same name is to be matched."""
-
-  def __init__(self, name, body, fileName=None, lineNo=-1):
-    if not name:
-      Logger.fail("Output group does not have a name", fileName, lineNo)
-    if not body:
-      Logger.fail("Output group does not have a body", fileName, lineNo)
-
-    self.name = name
-    self.body = body
-    self.lineNo = lineNo
-
-  def __eq__(self, other):
-    return (isinstance(other, self.__class__) and
-            self.name == other.name and
-            self.body == other.body)
-
-
-class FileSplitMixin(object):
-  """Mixin for representing text files which need to be split into smaller
-     chunks before being parsed."""
-
-  def _parseStream(self, stream):
-    lineNo = 0
-    allGroups = []
-    currentGroup = None
-
-    for line in stream:
-      lineNo += 1
-      line = line.strip()
-      if not line:
-        continue
-
-      # Let the child class process the line and return information about it.
-      # The _processLine method can modify the content of the line (or delete it
-      # entirely) and specify whether it starts a new group.
-      processedLine, newGroupName = self._processLine(line, lineNo)
-      if newGroupName is not None:
-        currentGroup = (newGroupName, [], lineNo)
-        allGroups.append(currentGroup)
-      if processedLine is not None:
-        if currentGroup is not None:
-          currentGroup[1].append(processedLine)
-        else:
-          self._exceptionLineOutsideGroup(line, lineNo)
-
-    # Finally, take the generated line groups and let the child class process
-    # each one before storing the final outcome.
-    return list(map(lambda group: self._processGroup(group[0], group[1], group[2]), allGroups))
-
-
-class CheckFile(FileSplitMixin):
-  """Collection of check groups extracted from the input test file."""
-
-  def __init__(self, prefix, checkStream, fileName=None):
-    self.fileName = fileName
-    self.prefix = prefix
-    self.groups = self._parseStream(checkStream)
-
-  # Attempts to parse a check line. The regex searches for a comment symbol
-  # followed by the CHECK keyword, given attribute and a colon at the very
-  # beginning of the line. Whitespaces are ignored.
-  def _extractLine(self, prefix, line):
-    rIgnoreWhitespace = r"\s*"
-    rCommentSymbols = [r"//", r"#"]
-    regexPrefix = rIgnoreWhitespace + \
-                  r"(" + r"|".join(rCommentSymbols) + r")" + \
-                  rIgnoreWhitespace + \
-                  prefix + r":"
-
-    # The 'match' function succeeds only if the pattern is matched at the
-    # beginning of the line.
-    match = re.match(regexPrefix, line)
-    if match is not None:
-      return line[match.end():].strip()
-    else:
-      return None
-
-  # This function is invoked on each line of the check file and returns a pair
-  # which instructs the parser how the line should be handled. If the line is to
-  # be included in the current check group, it is returned in the first value.
-  # If the line starts a new check group, the name of the group is returned in
-  # the second value.
-  def _processLine(self, line, lineNo):
-    # Lines beginning with 'CHECK-START' start a new check group.
-    startLine = self._extractLine(self.prefix + "-START", line)
-    if startLine is not None:
-      return None, startLine
-
-    # Lines starting only with 'CHECK' are matched in order.
-    plainLine = self._extractLine(self.prefix, line)
-    if plainLine is not None:
-      return (plainLine, CheckLine.Variant.InOrder, lineNo), None
-
-    # 'CHECK-DAG' lines are no-order assertions.
-    dagLine = self._extractLine(self.prefix + "-DAG", line)
-    if dagLine is not None:
-      return (dagLine, CheckLine.Variant.DAG, lineNo), None
-
-    # 'CHECK-NOT' lines are no-order negative assertions.
-    notLine = self._extractLine(self.prefix + "-NOT", line)
-    if notLine is not None:
-      return (notLine, CheckLine.Variant.Not, lineNo), None
-
-    # Other lines are ignored.
-    return None, None
-
-  def _exceptionLineOutsideGroup(self, line, lineNo):
-    Logger.fail("Check line not inside a group", self.fileName, lineNo)
-
-  # Constructs a check group from the parser-collected check lines.
-  def _processGroup(self, name, lines, lineNo):
-    checkLines = list(map(lambda line: CheckLine(line[0], line[1], self.fileName, line[2]), lines))
-    return CheckGroup(name, checkLines, self.fileName, lineNo)
-
-  def match(self, outputFile):
-    for checkGroup in self.groups:
-      # TODO: Currently does not handle multiple occurrences of the same group
-      # name, e.g. when a pass is run multiple times. It will always try to
-      # match a check group against the first output group of the same name.
-      outputGroup = outputFile.findGroup(checkGroup.name)
-      if outputGroup is None:
-        Logger.fail("Group \"" + checkGroup.name + "\" not found in the output",
-                    self.fileName, checkGroup.lineNo)
-      Logger.startTest(checkGroup.name)
-      checkGroup.match(outputGroup)
-      Logger.testPassed()
-
-
-class OutputFile(FileSplitMixin):
-  """Representation of the output generated by the test and split into groups
-     within which the checks are performed.
-
-     C1visualizer format is parsed with a state machine which differentiates
-     between the 'compilation' and 'cfg' blocks. The former marks the beginning
-     of a method. It is parsed for the method's name but otherwise ignored. Each
-     subsequent CFG block represents one stage of the compilation pipeline and
-     is parsed into an output group named "<method name> <pass name>".
-     """
-
-  class ParsingState:
-    OutsideBlock, InsideCompilationBlock, StartingCfgBlock, InsideCfgBlock = range(4)
-
-  def __init__(self, outputStream, fileName=None):
-    self.fileName = fileName
-
-    # Initialize the state machine
-    self.lastMethodName = None
-    self.state = OutputFile.ParsingState.OutsideBlock
-    self.groups = self._parseStream(outputStream)
-
-  # This function is invoked on each line of the output file and returns a pair
-  # which instructs the parser how the line should be handled. If the line is to
-  # be included in the current group, it is returned in the first value. If the
-  # line starts a new output group, the name of the group is returned in the
-  # second value.
-  def _processLine(self, line, lineNo):
-    if self.state == OutputFile.ParsingState.StartingCfgBlock:
-      # Previous line started a new 'cfg' block which means that this one must
-      # contain the name of the pass (this is enforced by C1visualizer).
-      if re.match("name\s+\"[^\"]+\"", line):
-        # Extract the pass name, prepend it with the name of the method and
-        # return as the beginning of a new group.
-        self.state = OutputFile.ParsingState.InsideCfgBlock
-        return (None, self.lastMethodName + " " + line.split("\"")[1])
-      else:
-        Logger.fail("Expected output group name", self.fileName, lineNo)
-
-    elif self.state == OutputFile.ParsingState.InsideCfgBlock:
-      if line == "end_cfg":
-        self.state = OutputFile.ParsingState.OutsideBlock
-        return (None, None)
-      else:
-        return (line, None)
-
-    elif self.state == OutputFile.ParsingState.InsideCompilationBlock:
-      # Search for the method's name. Format: method "<name>"
-      if re.match("method\s+\"[^\"]*\"", line):
-        methodName = line.split("\"")[1].strip()
-        if not methodName:
-          Logger.fail("Empty method name in output", self.fileName, lineNo)
-        self.lastMethodName = methodName
-      elif line == "end_compilation":
-        self.state = OutputFile.ParsingState.OutsideBlock
-      return (None, None)
-
-    else:
-      assert self.state == OutputFile.ParsingState.OutsideBlock
-      if line == "begin_cfg":
-        # The line starts a new group but we'll wait until the next line from
-        # which we can extract the name of the pass.
-        if self.lastMethodName is None:
-          Logger.fail("Expected method header", self.fileName, lineNo)
-        self.state = OutputFile.ParsingState.StartingCfgBlock
-        return (None, None)
-      elif line == "begin_compilation":
-        self.state = OutputFile.ParsingState.InsideCompilationBlock
-        return (None, None)
-      else:
-        Logger.fail("Output line not inside a group", self.fileName, lineNo)
-
-  # Constructs an output group from the parser-collected output lines.
-  def _processGroup(self, name, lines, lineNo):
-    return OutputGroup(name, lines, self.fileName, lineNo + 1)
-
-  def findGroup(self, name):
-    for group in self.groups:
-      if group.name == name:
-        return group
-    return None
-
-
-def ParseArguments():
-  parser = argparse.ArgumentParser()
-  parser.add_argument("tested_file",
-                      help="text file the checks should be verified against")
-  parser.add_argument("source_path", nargs="?",
-                      help="path to file/folder with checking annotations")
-  parser.add_argument("--check-prefix", dest="check_prefix", default="CHECK", metavar="PREFIX",
-                      help="prefix of checks in the test files (default: CHECK)")
-  parser.add_argument("--list-groups", dest="list_groups", action="store_true",
-                      help="print a list of all groups found in the tested file")
-  parser.add_argument("--dump-group", dest="dump_group", metavar="GROUP",
-                      help="print the contents of an output group")
-  parser.add_argument("-q", "--quiet", action="store_true",
-                      help="print only errors")
-  return parser.parse_args()
-
-
-def ListGroups(outputFilename):
-  outputFile = OutputFile(open(outputFilename, "r"))
-  for group in outputFile.groups:
-    Logger.log(group.name)
-
-
-def DumpGroup(outputFilename, groupName):
-  outputFile = OutputFile(open(outputFilename, "r"))
-  group = outputFile.findGroup(groupName)
-  if group:
-    lineNo = group.lineNo
-    maxLineNo = lineNo + len(group.body)
-    lenLineNo = len(str(maxLineNo)) + 2
-    for line in group.body:
-      Logger.log((str(lineNo) + ":").ljust(lenLineNo) + line)
-      lineNo += 1
-  else:
-    Logger.fail("Group \"" + groupName + "\" not found in the output")
-
-
-# Returns a list of files to scan for check annotations in the given path. Path
-# to a file is returned as a single-element list, directories are recursively
-# traversed and all '.java' files returned.
-def FindCheckFiles(path):
-  if not path:
-    Logger.fail("No source path provided")
-  elif os.path.isfile(path):
-    return [ path ]
-  elif os.path.isdir(path):
-    foundFiles = []
-    for root, dirs, files in os.walk(path):
-      for file in files:
-        if os.path.splitext(file)[1] == ".java":
-          foundFiles.append(os.path.join(root, file))
-    return foundFiles
-  else:
-    Logger.fail("Source path \"" + path + "\" not found")
-
-
-def RunChecks(checkPrefix, checkPath, outputFilename):
-  outputBaseName = os.path.basename(outputFilename)
-  outputFile = OutputFile(open(outputFilename, "r"), outputBaseName)
-
-  for checkFilename in FindCheckFiles(checkPath):
-    checkBaseName = os.path.basename(checkFilename)
-    checkFile = CheckFile(checkPrefix, open(checkFilename, "r"), checkBaseName)
-    checkFile.match(outputFile)
-
-
-if __name__ == "__main__":
-  args = ParseArguments()
-
-  if args.quiet:
-    Logger.Verbosity = Logger.Level.Error
-
-  if args.list_groups:
-    ListGroups(args.tested_file)
-  elif args.dump_group:
-    DumpGroup(args.tested_file, args.dump_group)
-  else:
-    RunChecks(args.check_prefix, args.source_path, args.tested_file)
diff --git a/tools/checker/README b/tools/checker/README
new file mode 100644
index 0000000..2763948
--- /dev/null
+++ b/tools/checker/README
@@ -0,0 +1,54 @@
+Checker is a testing tool which compiles a given test file and compares the
+state of the control-flow graph before and after each optimization pass
+against a set of assertions specified alongside the tests.
+
+Tests are written in Java, turned into DEX and compiled with the Optimizing
+compiler. "Check lines" are assertions formatted as comments of the Java file.
+They begin with prefix 'CHECK' followed by a pattern that the engine attempts
+to match in the compiler-generated output.
+
+Assertions are tested in groups which correspond to the individual compiler
+passes. Each group of check lines therefore must start with a 'CHECK-START'
+header which specifies the output group it should be tested against. The group
+name must exactly match one of the groups recognized in the output (they can
+be listed with the '--list-passes' command-line flag).
+
+Matching of check lines is carried out in the order of appearance in the
+source file. There are three types of check lines:
+ - CHECK:     Must match an output line which appears in the output group
+              later than lines matched against any preceeding checks. Output
+              lines must therefore match the check lines in the same order.
+              These are referred to as "in-order" checks in the code.
+ - CHECK-DAG: Must match an output line which appears in the output group
+              later than lines matched against any preceeding in-order checks.
+              In other words, the order of output lines does not matter
+              between consecutive DAG checks.
+ - CHECK-NOT: Must not match any output line which appears in the output group
+              later than lines matched against any preceeding checks and
+              earlier than lines matched against any subsequent checks.
+              Surrounding non-negative checks (or boundaries of the group)
+              therefore create a scope within which the assertion is verified.
+
+Check-line patterns are treated as plain text rather than regular expressions
+but are whitespace agnostic.
+
+Actual regex patterns can be inserted enclosed in '{{' and '}}' brackets. If
+curly brackets need to be used inside the body of the regex, they need to be
+enclosed in round brackets. For example, the pattern '{{foo{2}}}' will parse
+the invalid regex 'foo{2', but '{{(fo{2})}}' will match 'foo'.
+
+Regex patterns can be named and referenced later. A new variable is defined
+with '<<name:regex>>' and can be referenced with '<<name>>'. Variables are
+only valid within the scope of the defining group. Within a group they cannot
+be redefined or used undefined.
+
+Example:
+  The following assertions can be placed in a Java source file:
+
+  // CHECK-START: int MyClass.MyMethod() constant_folding (after)
+  // CHECK:         <<ID:i\d+>>  IntConstant {{11|22}}
+  // CHECK:                      Return [ <<ID>> ]
+
+  The engine will attempt to match the check lines against the output of the
+  group named on the first line. Together they verify that the CFG after
+  constant folding returns an integer constant with value either 11 or 22.
diff --git a/tools/checker/checker.py b/tools/checker/checker.py
new file mode 100755
index 0000000..ed630e3
--- /dev/null
+++ b/tools/checker/checker.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env python2
+#
+# Copyright (C) 2014 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.
+
+import argparse
+import os
+
+from common.logger                    import Logger
+from file_format.c1visualizer.parser  import ParseC1visualizerStream
+from file_format.checker.parser       import ParseCheckerStream
+from match.file                       import MatchFiles
+
+def ParseArguments():
+  parser = argparse.ArgumentParser()
+  parser.add_argument("tested_file",
+                      help="text file the checks should be verified against")
+  parser.add_argument("source_path", nargs="?",
+                      help="path to file/folder with checking annotations")
+  parser.add_argument("--check-prefix", dest="check_prefix", default="CHECK", metavar="PREFIX",
+                      help="prefix of checks in the test files (default: CHECK)")
+  parser.add_argument("--list-passes", dest="list_passes", action="store_true",
+                      help="print a list of all passes found in the tested file")
+  parser.add_argument("--dump-pass", dest="dump_pass", metavar="PASS",
+                      help="print a compiler pass dump")
+  parser.add_argument("-q", "--quiet", action="store_true",
+                      help="print only errors")
+  return parser.parse_args()
+
+
+def ListPasses(outputFilename):
+  c1File = ParseC1visualizerStream(os.path.basename(outputFilename), open(outputFilename, "r"))
+  for compiler_pass in c1File.passes:
+    Logger.log(compiler_pass.name)
+
+
+def DumpPass(outputFilename, passName):
+  c1File = ParseC1visualizerStream(os.path.basename(outputFilename), open(outputFilename, "r"))
+  compiler_pass = c1File.findPass(passName)
+  if compiler_pass:
+    maxLineNo = compiler_pass.startLineNo + len(compiler_pass.body)
+    lenLineNo = len(str(maxLineNo)) + 2
+    curLineNo = compiler_pass.startLineNo
+    for line in compiler_pass.body:
+      Logger.log((str(curLineNo) + ":").ljust(lenLineNo) + line)
+      curLineNo += 1
+  else:
+    Logger.fail("Pass \"" + passName + "\" not found in the output")
+
+
+def FindCheckerFiles(path):
+  """ Returns a list of files to scan for check annotations in the given path.
+      Path to a file is returned as a single-element list, directories are
+      recursively traversed and all '.java' files returned.
+  """
+  if not path:
+    Logger.fail("No source path provided")
+  elif os.path.isfile(path):
+    return [ path ]
+  elif os.path.isdir(path):
+    foundFiles = []
+    for root, dirs, files in os.walk(path):
+      for file in files:
+        extension = os.path.splitext(file)[1]
+        if extension in [".java", ".smali"]:
+          foundFiles.append(os.path.join(root, file))
+    return foundFiles
+  else:
+    Logger.fail("Source path \"" + path + "\" not found")
+
+
+def RunTests(checkPrefix, checkPath, outputFilename):
+  c1File = ParseC1visualizerStream(os.path.basename(outputFilename), open(outputFilename, "r"))
+  for checkFilename in FindCheckerFiles(checkPath):
+    checkerFile = ParseCheckerStream(os.path.basename(checkFilename),
+                                     checkPrefix,
+                                     open(checkFilename, "r"))
+    MatchFiles(checkerFile, c1File)
+
+
+if __name__ == "__main__":
+  args = ParseArguments()
+
+  if args.quiet:
+    Logger.Verbosity = Logger.Level.Error
+
+  if args.list_passes:
+    ListPasses(args.tested_file)
+  elif args.dump_pass:
+    DumpPass(args.tested_file, args.dump_pass)
+  else:
+    RunTests(args.check_prefix, args.source_path, args.tested_file)
diff --git a/tools/checker/common/__init__.py b/tools/checker/common/__init__.py
new file mode 100644
index 0000000..d0a140b
--- /dev/null
+++ b/tools/checker/common/__init__.py
@@ -0,0 +1,13 @@
+# Copyright (C) 2014 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.
diff --git a/tools/checker/common/logger.py b/tools/checker/common/logger.py
new file mode 100644
index 0000000..28bb458
--- /dev/null
+++ b/tools/checker/common/logger.py
@@ -0,0 +1,81 @@
+# Copyright (C) 2014 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.
+
+from __future__ import print_function
+import sys
+
+class Logger(object):
+
+  class Level(object):
+    NoOutput, Error, Info = range(3)
+
+  class Color(object):
+    Default, Blue, Gray, Purple, Red = range(5)
+
+    @staticmethod
+    def terminalCode(color, out=sys.stdout):
+      if not out.isatty():
+        return ''
+      elif color == Logger.Color.Blue:
+        return '\033[94m'
+      elif color == Logger.Color.Gray:
+        return '\033[37m'
+      elif color == Logger.Color.Purple:
+        return '\033[95m'
+      elif color == Logger.Color.Red:
+        return '\033[91m'
+      else:
+        return '\033[0m'
+
+  Verbosity = Level.Info
+
+  @staticmethod
+  def log(text, level=Level.Info, color=Color.Default, newLine=True, out=sys.stdout):
+    if level <= Logger.Verbosity:
+      text = Logger.Color.terminalCode(color, out) + text + \
+             Logger.Color.terminalCode(Logger.Color.Default, out)
+      if newLine:
+        print(text, file=out)
+      else:
+        print(text, end="", file=out)
+      out.flush()
+
+  @staticmethod
+  def fail(msg, file=None, line=-1):
+    location = ""
+    if file:
+      location += file + ":"
+    if line > 0:
+      location += str(line) + ":"
+    if location:
+      location += " "
+
+    Logger.log(location, Logger.Level.Error, color=Logger.Color.Gray, newLine=False, out=sys.stderr)
+    Logger.log("error: ", Logger.Level.Error, color=Logger.Color.Red, newLine=False, out=sys.stderr)
+    Logger.log(msg, Logger.Level.Error, out=sys.stderr)
+    sys.exit(msg)
+
+  @staticmethod
+  def startTest(name):
+    Logger.log("TEST ", color=Logger.Color.Purple, newLine=False)
+    Logger.log(name + "... ", newLine=False)
+
+  @staticmethod
+  def testPassed():
+    Logger.log("PASS", color=Logger.Color.Blue)
+
+  @staticmethod
+  def testFailed(msg, file=None, line=-1):
+    Logger.log("FAIL", color=Logger.Color.Red)
+    Logger.fail(msg, file, line)
diff --git a/tools/checker/common/mixins.py b/tools/checker/common/mixins.py
new file mode 100644
index 0000000..819de24
--- /dev/null
+++ b/tools/checker/common/mixins.py
@@ -0,0 +1,26 @@
+# Copyright (C) 2014 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.
+
+class EqualityMixin:
+  """ Object equality via equality of dictionaries. """
+
+  def __eq__(self, other):
+    return isinstance(other, self.__class__) \
+       and self.__dict__ == other.__dict__
+
+class PrintableMixin:
+  """ Prints object as name-dictionary pair. """
+
+  def __repr__(self):
+    return "<%s: %s>" % (type(self).__name__, str(self.__dict__))
diff --git a/tools/checker/common/testing.py b/tools/checker/common/testing.py
new file mode 100644
index 0000000..1299c07
--- /dev/null
+++ b/tools/checker/common/testing.py
@@ -0,0 +1,22 @@
+# Copyright (C) 2014 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.
+
+def ToUnicode(string):
+  """ Converts a string into Unicode.
+
+  This is a delegate function for the built-in `unicode`. It checks if the input
+  is not `None`, because `unicode` turns it into an actual "None" string.
+  """
+  assert string is not None
+  return unicode(string)
diff --git a/tools/checker/file_format/__init__.py b/tools/checker/file_format/__init__.py
new file mode 100644
index 0000000..d0a140b
--- /dev/null
+++ b/tools/checker/file_format/__init__.py
@@ -0,0 +1,13 @@
+# Copyright (C) 2014 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.
diff --git a/tools/checker/file_format/c1visualizer/__init__.py b/tools/checker/file_format/c1visualizer/__init__.py
new file mode 100644
index 0000000..d0a140b
--- /dev/null
+++ b/tools/checker/file_format/c1visualizer/__init__.py
@@ -0,0 +1,13 @@
+# Copyright (C) 2014 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.
diff --git a/tools/checker/file_format/c1visualizer/parser.py b/tools/checker/file_format/c1visualizer/parser.py
new file mode 100644
index 0000000..335a195
--- /dev/null
+++ b/tools/checker/file_format/c1visualizer/parser.py
@@ -0,0 +1,87 @@
+# Copyright (C) 2014 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.
+
+from common.logger                   import Logger
+from file_format.common              import SplitStream
+from file_format.c1visualizer.struct import C1visualizerFile, C1visualizerPass
+
+import re
+
+class C1ParserState:
+  OutsideBlock, InsideCompilationBlock, StartingCfgBlock, InsideCfgBlock = range(4)
+
+  def __init__(self):
+    self.currentState = C1ParserState.OutsideBlock
+    self.lastMethodName = None
+
+def __parseC1Line(line, lineNo, state, fileName):
+  """ This function is invoked on each line of the output file and returns
+      a pair which instructs the parser how the line should be handled. If the
+      line is to be included in the current group, it is returned in the first
+      value. If the line starts a new output group, the name of the group is
+      returned in the second value.
+  """
+  if state.currentState == C1ParserState.StartingCfgBlock:
+    # Previous line started a new 'cfg' block which means that this one must
+    # contain the name of the pass (this is enforced by C1visualizer).
+    if re.match("name\s+\"[^\"]+\"", line):
+      # Extract the pass name, prepend it with the name of the method and
+      # return as the beginning of a new group.
+      state.currentState = C1ParserState.InsideCfgBlock
+      return (None, state.lastMethodName + " " + line.split("\"")[1])
+    else:
+      Logger.fail("Expected output group name", fileName, lineNo)
+
+  elif state.currentState == C1ParserState.InsideCfgBlock:
+    if line == "end_cfg":
+      state.currentState = C1ParserState.OutsideBlock
+      return (None, None)
+    else:
+      return (line, None)
+
+  elif state.currentState == C1ParserState.InsideCompilationBlock:
+    # Search for the method's name. Format: method "<name>"
+    if re.match("method\s+\"[^\"]*\"", line):
+      methodName = line.split("\"")[1].strip()
+      if not methodName:
+        Logger.fail("Empty method name in output", fileName, lineNo)
+      state.lastMethodName = methodName
+    elif line == "end_compilation":
+      state.currentState = C1ParserState.OutsideBlock
+    return (None, None)
+
+  else:
+    assert state.currentState == C1ParserState.OutsideBlock
+    if line == "begin_cfg":
+      # The line starts a new group but we'll wait until the next line from
+      # which we can extract the name of the pass.
+      if state.lastMethodName is None:
+        Logger.fail("Expected method header", fileName, lineNo)
+      state.currentState = C1ParserState.StartingCfgBlock
+      return (None, None)
+    elif line == "begin_compilation":
+      state.currentState = C1ParserState.InsideCompilationBlock
+      return (None, None)
+    else:
+      Logger.fail("C1visualizer line not inside a group", fileName, lineNo)
+
+def ParseC1visualizerStream(fileName, stream):
+  c1File = C1visualizerFile(fileName)
+  state = C1ParserState()
+  fnProcessLine = lambda line, lineNo: __parseC1Line(line, lineNo, state, fileName)
+  fnLineOutsideChunk = lambda line, lineNo: \
+      Logger.fail("C1visualizer line not inside a group", fileName, lineNo)
+  for passName, passLines, startLineNo in SplitStream(stream, fnProcessLine, fnLineOutsideChunk):
+    C1visualizerPass(c1File, passName, passLines, startLineNo + 1)
+  return c1File
diff --git a/tools/checker/file_format/c1visualizer/struct.py b/tools/checker/file_format/c1visualizer/struct.py
new file mode 100644
index 0000000..991564e
--- /dev/null
+++ b/tools/checker/file_format/c1visualizer/struct.py
@@ -0,0 +1,60 @@
+# Copyright (C) 2014 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.
+
+from common.logger import Logger
+from common.mixins import PrintableMixin
+
+class C1visualizerFile(PrintableMixin):
+
+  def __init__(self, fileName):
+    self.fileName = fileName
+    self.passes = []
+
+  def addPass(self, new_pass):
+    self.passes.append(new_pass)
+
+  def findPass(self, name):
+    for entry in self.passes:
+      if entry.name == name:
+        return entry
+    return None
+
+  def __eq__(self, other):
+    return isinstance(other, self.__class__) \
+       and self.passes == other.passes
+
+
+class C1visualizerPass(PrintableMixin):
+
+  def __init__(self, parent, name, body, startLineNo):
+    self.parent = parent
+    self.name = name
+    self.body = body
+    self.startLineNo = startLineNo
+
+    if not self.name:
+      Logger.fail("C1visualizer pass does not have a name", self.fileName, self.startLineNo)
+    if not self.body:
+      Logger.fail("C1visualizer pass does not have a body", self.fileName, self.startLineNo)
+
+    self.parent.addPass(self)
+
+  @property
+  def fileName(self):
+    return self.parent.fileName
+
+  def __eq__(self, other):
+    return isinstance(other, self.__class__) \
+       and self.name == other.name \
+       and self.body == other.body
diff --git a/tools/checker/file_format/c1visualizer/test.py b/tools/checker/file_format/c1visualizer/test.py
new file mode 100644
index 0000000..812a4cf
--- /dev/null
+++ b/tools/checker/file_format/c1visualizer/test.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python2
+#
+# Copyright (C) 2014 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.
+
+from common.testing                  import ToUnicode
+from file_format.c1visualizer.parser import ParseC1visualizerStream
+from file_format.c1visualizer.struct import C1visualizerFile, C1visualizerPass
+
+import io
+import unittest
+
+class C1visualizerParser_Test(unittest.TestCase):
+
+  def createFile(self, passList):
+    """ Creates an instance of CheckerFile from provided info.
+
+    Data format: [ ( <case-name>, [ ( <text>, <assert-variant> ), ... ] ), ... ]
+    """
+    c1File = C1visualizerFile("<c1_file>")
+    for passEntry in passList:
+      passName = passEntry[0]
+      passBody = passEntry[1]
+      c1Pass = C1visualizerPass(c1File, passName, passBody, 0)
+    return c1File
+
+  def assertParsesTo(self, c1Text, expectedData):
+    expectedFile = self.createFile(expectedData)
+    actualFile = ParseC1visualizerStream("<c1_file>", io.StringIO(ToUnicode(c1Text)))
+    return self.assertEqual(expectedFile, actualFile)
+
+  def test_EmptyFile(self):
+    self.assertParsesTo("", [])
+
+  def test_SingleGroup(self):
+    self.assertParsesTo(
+      """
+        begin_compilation
+          method "MyMethod"
+        end_compilation
+        begin_cfg
+          name "pass1"
+          foo
+          bar
+        end_cfg
+      """,
+      [ ( "MyMethod pass1", [ "foo", "bar" ] ) ])
+
+  def test_MultipleGroups(self):
+    self.assertParsesTo(
+      """
+        begin_compilation
+          name "xyz1"
+          method "MyMethod1"
+          date 1234
+        end_compilation
+        begin_cfg
+          name "pass1"
+          foo
+          bar
+        end_cfg
+        begin_cfg
+          name "pass2"
+          abc
+          def
+        end_cfg
+      """,
+      [ ( "MyMethod1 pass1", [ "foo", "bar" ] ),
+        ( "MyMethod1 pass2", [ "abc", "def" ] ) ])
+    self.assertParsesTo(
+      """
+        begin_compilation
+          name "xyz1"
+          method "MyMethod1"
+          date 1234
+        end_compilation
+        begin_cfg
+          name "pass1"
+          foo
+          bar
+        end_cfg
+        begin_compilation
+          name "xyz2"
+          method "MyMethod2"
+          date 5678
+        end_compilation
+        begin_cfg
+          name "pass2"
+          abc
+          def
+        end_cfg
+      """,
+      [ ( "MyMethod1 pass1", [ "foo", "bar" ] ),
+        ( "MyMethod2 pass2", [ "abc", "def" ] ) ])
diff --git a/tools/checker/file_format/checker/__init__.py b/tools/checker/file_format/checker/__init__.py
new file mode 100644
index 0000000..d0a140b
--- /dev/null
+++ b/tools/checker/file_format/checker/__init__.py
@@ -0,0 +1,13 @@
+# Copyright (C) 2014 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.
diff --git a/tools/checker/file_format/checker/parser.py b/tools/checker/file_format/checker/parser.py
new file mode 100644
index 0000000..d7a38da
--- /dev/null
+++ b/tools/checker/file_format/checker/parser.py
@@ -0,0 +1,142 @@
+# Copyright (C) 2014 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.
+
+from file_format.common         import SplitStream
+from file_format.checker.struct import CheckerFile, TestCase, TestAssertion, RegexExpression
+
+import re
+
+def __extractLine(prefix, line):
+  """ Attempts to parse a check line. The regex searches for a comment symbol
+      followed by the CHECK keyword, given attribute and a colon at the very
+      beginning of the line. Whitespaces are ignored.
+  """
+  rIgnoreWhitespace = r"\s*"
+  rCommentSymbols = [r"//", r"#"]
+  regexPrefix = rIgnoreWhitespace + \
+                r"(" + r"|".join(rCommentSymbols) + r")" + \
+                rIgnoreWhitespace + \
+                prefix + r":"
+
+  # The 'match' function succeeds only if the pattern is matched at the
+  # beginning of the line.
+  match = re.match(regexPrefix, line)
+  if match is not None:
+    return line[match.end():].strip()
+  else:
+    return None
+
+def __processLine(line, lineNo, prefix):
+  """ This function is invoked on each line of the check file and returns a pair
+      which instructs the parser how the line should be handled. If the line is
+      to be included in the current check group, it is returned in the first
+      value. If the line starts a new check group, the name of the group is
+      returned in the second value.
+  """
+  # Lines beginning with 'CHECK-START' start a new test case.
+  startLine = __extractLine(prefix + "-START", line)
+  if startLine is not None:
+    return None, startLine
+
+  # Lines starting only with 'CHECK' are matched in order.
+  plainLine = __extractLine(prefix, line)
+  if plainLine is not None:
+    return (plainLine, TestAssertion.Variant.InOrder, lineNo), None
+
+  # 'CHECK-DAG' lines are no-order assertions.
+  dagLine = __extractLine(prefix + "-DAG", line)
+  if dagLine is not None:
+    return (dagLine, TestAssertion.Variant.DAG, lineNo), None
+
+  # 'CHECK-NOT' lines are no-order negative assertions.
+  notLine = __extractLine(prefix + "-NOT", line)
+  if notLine is not None:
+    return (notLine, TestAssertion.Variant.Not, lineNo), None
+
+  # Other lines are ignored.
+  return None, None
+
+def __isMatchAtStart(match):
+  """ Tests if the given Match occurred at the beginning of the line. """
+  return (match is not None) and (match.start() == 0)
+
+def __firstMatch(matches, string):
+  """ Takes in a list of Match objects and returns the minimal start point among
+      them. If there aren't any successful matches it returns the length of
+      the searched string.
+  """
+  starts = map(lambda m: len(string) if m is None else m.start(), matches)
+  return min(starts)
+
+def ParseCheckerAssertion(parent, line, variant, lineNo):
+  """ This method parses the content of a check line stripped of the initial
+      comment symbol and the CHECK keyword.
+  """
+  assertion = TestAssertion(parent, variant, line, lineNo)
+  # Loop as long as there is something to parse.
+  while line:
+    # Search for the nearest occurrence of the special markers.
+    matchWhitespace = re.search(r"\s+", line)
+    matchPattern = re.search(RegexExpression.Regex.regexPattern, line)
+    matchVariableReference = re.search(RegexExpression.Regex.regexVariableReference, line)
+    matchVariableDefinition = re.search(RegexExpression.Regex.regexVariableDefinition, line)
+
+    # If one of the above was identified at the current position, extract them
+    # from the line, parse them and add to the list of line parts.
+    if __isMatchAtStart(matchWhitespace):
+      # A whitespace in the check line creates a new separator of line parts.
+      # This allows for ignored output between the previous and next parts.
+      line = line[matchWhitespace.end():]
+      assertion.addExpression(RegexExpression.createSeparator())
+    elif __isMatchAtStart(matchPattern):
+      pattern = line[0:matchPattern.end()]
+      pattern = pattern[2:-2]
+      line = line[matchPattern.end():]
+      assertion.addExpression(RegexExpression.createPattern(pattern))
+    elif __isMatchAtStart(matchVariableReference):
+      var = line[0:matchVariableReference.end()]
+      line = line[matchVariableReference.end():]
+      name = var[2:-2]
+      assertion.addExpression(RegexExpression.createVariableReference(name))
+    elif __isMatchAtStart(matchVariableDefinition):
+      var = line[0:matchVariableDefinition.end()]
+      line = line[matchVariableDefinition.end():]
+      colonPos = var.find(":")
+      name = var[2:colonPos]
+      body = var[colonPos+1:-2]
+      assertion.addExpression(RegexExpression.createVariableDefinition(name, body))
+    else:
+      # If we're not currently looking at a special marker, this is a plain
+      # text match all the way until the first special marker (or the end
+      # of the line).
+      firstMatch = __firstMatch([ matchWhitespace,
+                                  matchPattern,
+                                  matchVariableReference,
+                                  matchVariableDefinition ],
+                                line)
+      text = line[0:firstMatch]
+      line = line[firstMatch:]
+      assertion.addExpression(RegexExpression.createText(text))
+  return assertion
+
+def ParseCheckerStream(fileName, prefix, stream):
+  checkerFile = CheckerFile(fileName)
+  fnProcessLine = lambda line, lineNo: __processLine(line, lineNo, prefix)
+  fnLineOutsideChunk = lambda line, lineNo: \
+      Logger.fail("C1visualizer line not inside a group", fileName, lineNo)
+  for caseName, caseLines, startLineNo in SplitStream(stream, fnProcessLine, fnLineOutsideChunk):
+    testCase = TestCase(checkerFile, caseName, startLineNo)
+    for caseLine in caseLines:
+      ParseCheckerAssertion(testCase, caseLine[0], caseLine[1], caseLine[2])
+  return checkerFile
diff --git a/tools/checker/file_format/checker/struct.py b/tools/checker/file_format/checker/struct.py
new file mode 100644
index 0000000..381c92b
--- /dev/null
+++ b/tools/checker/file_format/checker/struct.py
@@ -0,0 +1,156 @@
+# Copyright (C) 2014 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.
+
+from common.logger import Logger
+from common.mixins import EqualityMixin, PrintableMixin
+
+import re
+
+class CheckerFile(PrintableMixin):
+
+  def __init__(self, fileName):
+    self.fileName = fileName
+    self.testCases = []
+
+  def addTestCase(self, new_test_case):
+    self.testCases.append(new_test_case)
+
+  def __eq__(self, other):
+    return isinstance(other, self.__class__) \
+       and self.testCases == other.testCases
+
+
+class TestCase(PrintableMixin):
+
+  def __init__(self, parent, name, startLineNo):
+    assert isinstance(parent, CheckerFile)
+
+    self.parent = parent
+    self.name = name
+    self.assertions = []
+    self.startLineNo = startLineNo
+
+    if not self.name:
+      Logger.fail("Test case does not have a name", self.parent.fileName, self.startLineNo)
+
+    self.parent.addTestCase(self)
+
+  @property
+  def fileName(self):
+    return self.parent.fileName
+
+  def addAssertion(self, new_assertion):
+    self.assertions.append(new_assertion)
+
+  def __eq__(self, other):
+    return isinstance(other, self.__class__) \
+       and self.name == other.name \
+       and self.assertions == other.assertions
+
+
+class TestAssertion(PrintableMixin):
+
+  class Variant(object):
+    """Supported types of assertions."""
+    InOrder, DAG, Not = range(3)
+
+  def __init__(self, parent, variant, originalText, lineNo):
+    assert isinstance(parent, TestCase)
+
+    self.parent = parent
+    self.variant = variant
+    self.expressions = []
+    self.lineNo = lineNo
+    self.originalText = originalText
+
+    self.parent.addAssertion(self)
+
+  @property
+  def fileName(self):
+    return self.parent.fileName
+
+  def addExpression(self, new_expression):
+    assert isinstance(new_expression, RegexExpression)
+    if self.variant == TestAssertion.Variant.Not:
+      if new_expression.variant == RegexExpression.Variant.VarDef:
+        Logger.fail("CHECK-NOT lines cannot define variables", self.fileName, self.lineNo)
+    self.expressions.append(new_expression)
+
+  def toRegex(self):
+    """ Returns a regex pattern for this entire assertion. Only used in tests. """
+    regex = ""
+    for expression in self.expressions:
+      if expression.variant == RegexExpression.Variant.Separator:
+        regex = regex + ", "
+      else:
+        regex = regex + "(" + expression.pattern + ")"
+    return regex
+
+  def __eq__(self, other):
+    return isinstance(other, self.__class__) \
+       and self.variant == other.variant \
+       and self.expressions == other.expressions
+
+
+class RegexExpression(EqualityMixin, PrintableMixin):
+
+  class Variant(object):
+    """Supported language constructs."""
+    Text, Pattern, VarRef, VarDef, Separator = range(5)
+
+  class Regex(object):
+    rName = r"([a-zA-Z][a-zA-Z0-9]*)"
+    rRegex = r"(.+?)"
+    rPatternStartSym = r"(\{\{)"
+    rPatternEndSym = r"(\}\})"
+    rVariableStartSym = r"(<<)"
+    rVariableEndSym = r"(>>)"
+    rVariableSeparator = r"(:)"
+
+    regexPattern = rPatternStartSym + rRegex + rPatternEndSym
+    regexVariableReference = rVariableStartSym + rName + rVariableEndSym
+    regexVariableDefinition = rVariableStartSym + rName + rVariableSeparator + rRegex + rVariableEndSym
+
+  def __init__(self, variant, name, pattern):
+    self.variant = variant
+    self.name = name
+    self.pattern = pattern
+
+  def __eq__(self, other):
+    return isinstance(other, self.__class__) \
+       and self.variant == other.variant \
+       and self.name == other.name \
+       and self.pattern == other.pattern
+
+  @staticmethod
+  def createSeparator():
+    return RegexExpression(RegexExpression.Variant.Separator, None, None)
+
+  @staticmethod
+  def createText(text):
+    return RegexExpression(RegexExpression.Variant.Text, None, re.escape(text))
+
+  @staticmethod
+  def createPattern(pattern):
+    return RegexExpression(RegexExpression.Variant.Pattern, None, pattern)
+
+  @staticmethod
+  def createVariableReference(name):
+    assert re.match(RegexExpression.Regex.rName, name)
+    return RegexExpression(RegexExpression.Variant.VarRef, name, None)
+
+  @staticmethod
+  def createVariableDefinition(name, pattern):
+    assert re.match(RegexExpression.Regex.rName, name)
+    return RegexExpression(RegexExpression.Variant.VarDef, name, pattern)
diff --git a/tools/checker/file_format/checker/test.py b/tools/checker/file_format/checker/test.py
new file mode 100644
index 0000000..475e8c3
--- /dev/null
+++ b/tools/checker/file_format/checker/test.py
@@ -0,0 +1,238 @@
+#!/usr/bin/env python2
+#
+# Copyright (C) 2014 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.
+
+from common.testing             import ToUnicode
+from file_format.checker.parser import ParseCheckerStream
+from file_format.checker.struct import CheckerFile, TestCase, TestAssertion, RegexExpression
+
+import io
+import unittest
+
+CheckerException = SystemExit
+
+class CheckerParser_PrefixTest(unittest.TestCase):
+
+  def tryParse(self, string):
+    checkerText = u"// CHECK-START: pass\n" + ToUnicode(string)
+    checkFile = ParseCheckerStream("<test-file>", "CHECK", io.StringIO(checkerText))
+    self.assertEqual(len(checkFile.testCases), 1)
+    testCase = checkFile.testCases[0]
+    return len(testCase.assertions) != 0
+
+  def test_InvalidFormat(self):
+    self.assertFalse(self.tryParse("CHECK"))
+    self.assertFalse(self.tryParse(":CHECK"))
+    self.assertFalse(self.tryParse("CHECK:"))
+    self.assertFalse(self.tryParse("//CHECK"))
+    self.assertFalse(self.tryParse("#CHECK"))
+
+    self.assertTrue(self.tryParse("//CHECK:foo"))
+    self.assertTrue(self.tryParse("#CHECK:bar"))
+
+  def test_InvalidLabel(self):
+    self.assertFalse(self.tryParse("//ACHECK:foo"))
+    self.assertFalse(self.tryParse("#ACHECK:foo"))
+
+  def test_NotFirstOnTheLine(self):
+    self.assertFalse(self.tryParse("A// CHECK: foo"))
+    self.assertFalse(self.tryParse("A # CHECK: foo"))
+    self.assertFalse(self.tryParse("// // CHECK: foo"))
+    self.assertFalse(self.tryParse("# # CHECK: foo"))
+
+  def test_WhitespaceAgnostic(self):
+    self.assertTrue(self.tryParse("  //CHECK: foo"))
+    self.assertTrue(self.tryParse("//  CHECK: foo"))
+    self.assertTrue(self.tryParse("    //CHECK: foo"))
+    self.assertTrue(self.tryParse("//    CHECK: foo"))
+
+
+class CheckerParser_RegexExpressionTest(unittest.TestCase):
+
+  def parseAssertion(self, string, variant=""):
+    checkerText = u"// CHECK-START: pass\n// CHECK" + ToUnicode(variant) + u": " + ToUnicode(string)
+    checkerFile = ParseCheckerStream("<test-file>", "CHECK", io.StringIO(checkerText))
+    self.assertEqual(len(checkerFile.testCases), 1)
+    testCase = checkerFile.testCases[0]
+    self.assertEqual(len(testCase.assertions), 1)
+    return testCase.assertions[0]
+
+  def parseExpression(self, string):
+    line = self.parseAssertion(string)
+    self.assertEqual(1, len(line.expressions))
+    return line.expressions[0]
+
+  def assertEqualsRegex(self, string, expected):
+    self.assertEqual(expected, self.parseAssertion(string).toRegex())
+
+  def assertEqualsText(self, string, text):
+    self.assertEqual(self.parseExpression(string), RegexExpression.createText(text))
+
+  def assertEqualsPattern(self, string, pattern):
+    self.assertEqual(self.parseExpression(string), RegexExpression.createPattern(pattern))
+
+  def assertEqualsVarRef(self, string, name):
+    self.assertEqual(self.parseExpression(string), RegexExpression.createVariableReference(name))
+
+  def assertEqualsVarDef(self, string, name, pattern):
+    self.assertEqual(self.parseExpression(string),
+                     RegexExpression.createVariableDefinition(name, pattern))
+
+  def assertVariantNotEqual(self, string, variant):
+    self.assertNotEqual(variant, self.parseExpression(string).variant)
+
+  # Test that individual parts of the line are recognized
+
+  def test_TextOnly(self):
+    self.assertEqualsText("foo", "foo")
+    self.assertEqualsText("  foo  ", "foo")
+    self.assertEqualsRegex("f$o^o", "(f\$o\^o)")
+
+  def test_PatternOnly(self):
+    self.assertEqualsPattern("{{a?b.c}}", "a?b.c")
+
+  def test_VarRefOnly(self):
+    self.assertEqualsVarRef("<<ABC>>", "ABC")
+
+  def test_VarDefOnly(self):
+    self.assertEqualsVarDef("<<ABC:a?b.c>>", "ABC", "a?b.c")
+
+  def test_TextWithWhitespace(self):
+    self.assertEqualsRegex("foo bar", "(foo), (bar)")
+    self.assertEqualsRegex("foo   bar", "(foo), (bar)")
+
+  def test_TextWithRegex(self):
+    self.assertEqualsRegex("foo{{abc}}bar", "(foo)(abc)(bar)")
+
+  def test_TextWithVar(self):
+    self.assertEqualsRegex("foo<<ABC:abc>>bar", "(foo)(abc)(bar)")
+
+  def test_PlainWithRegexAndWhitespaces(self):
+    self.assertEqualsRegex("foo {{abc}}bar", "(foo), (abc)(bar)")
+    self.assertEqualsRegex("foo{{abc}} bar", "(foo)(abc), (bar)")
+    self.assertEqualsRegex("foo {{abc}} bar", "(foo), (abc), (bar)")
+
+  def test_PlainWithVarAndWhitespaces(self):
+    self.assertEqualsRegex("foo <<ABC:abc>>bar", "(foo), (abc)(bar)")
+    self.assertEqualsRegex("foo<<ABC:abc>> bar", "(foo)(abc), (bar)")
+    self.assertEqualsRegex("foo <<ABC:abc>> bar", "(foo), (abc), (bar)")
+
+  def test_AllKinds(self):
+    self.assertEqualsRegex("foo <<ABC:abc>>{{def}}bar", "(foo), (abc)(def)(bar)")
+    self.assertEqualsRegex("foo<<ABC:abc>> {{def}}bar", "(foo)(abc), (def)(bar)")
+    self.assertEqualsRegex("foo <<ABC:abc>> {{def}} bar", "(foo), (abc), (def), (bar)")
+
+  # # Test that variables and patterns are parsed correctly
+
+  def test_ValidPattern(self):
+    self.assertEqualsPattern("{{abc}}", "abc")
+    self.assertEqualsPattern("{{a[b]c}}", "a[b]c")
+    self.assertEqualsPattern("{{(a{bc})}}", "(a{bc})")
+
+  def test_ValidRef(self):
+    self.assertEqualsVarRef("<<ABC>>", "ABC")
+    self.assertEqualsVarRef("<<A1BC2>>", "A1BC2")
+
+  def test_ValidDef(self):
+    self.assertEqualsVarDef("<<ABC:abc>>", "ABC", "abc")
+    self.assertEqualsVarDef("<<ABC:ab:c>>", "ABC", "ab:c")
+    self.assertEqualsVarDef("<<ABC:a[b]c>>", "ABC", "a[b]c")
+    self.assertEqualsVarDef("<<ABC:(a[bc])>>", "ABC", "(a[bc])")
+
+  def test_Empty(self):
+    self.assertVariantNotEqual("{{}}", RegexExpression.Variant.Pattern)
+    self.assertVariantNotEqual("<<>>", RegexExpression.Variant.VarRef)
+    self.assertVariantNotEqual("<<:>>", RegexExpression.Variant.VarDef)
+
+  def test_InvalidVarName(self):
+    self.assertVariantNotEqual("<<0ABC>>", RegexExpression.Variant.VarRef)
+    self.assertVariantNotEqual("<<AB=C>>", RegexExpression.Variant.VarRef)
+    self.assertVariantNotEqual("<<ABC=>>", RegexExpression.Variant.VarRef)
+    self.assertVariantNotEqual("<<0ABC:abc>>", RegexExpression.Variant.VarDef)
+    self.assertVariantNotEqual("<<AB=C:abc>>", RegexExpression.Variant.VarDef)
+    self.assertVariantNotEqual("<<ABC=:abc>>", RegexExpression.Variant.VarDef)
+
+  def test_BodyMatchNotGreedy(self):
+    self.assertEqualsRegex("{{abc}}{{def}}", "(abc)(def)")
+    self.assertEqualsRegex("<<ABC:abc>><<DEF:def>>", "(abc)(def)")
+
+  def test_NoVarDefsInNotChecks(self):
+    with self.assertRaises(CheckerException):
+      self.parseAssertion("<<ABC:abc>>", "-NOT")
+
+
+class CheckerParser_FileLayoutTest(unittest.TestCase):
+
+  # Creates an instance of CheckerFile from provided info.
+  # Data format: [ ( <case-name>, [ ( <text>, <assert-variant> ), ... ] ), ... ]
+  def createFile(self, caseList):
+    testFile = CheckerFile("<test_file>")
+    for caseEntry in caseList:
+      caseName = caseEntry[0]
+      testCase = TestCase(testFile, caseName, 0)
+      assertionList = caseEntry[1]
+      for assertionEntry in assertionList:
+        content = assertionEntry[0]
+        variant = assertionEntry[1]
+        assertion = TestAssertion(testCase, variant, content, 0)
+        assertion.addExpression(RegexExpression.createText(content))
+    return testFile
+
+  def assertParsesTo(self, checkerText, expectedData):
+    expectedFile = self.createFile(expectedData)
+    actualFile = ParseCheckerStream("<test_file>", "CHECK", io.StringIO(ToUnicode(checkerText)))
+    return self.assertEqual(expectedFile, actualFile)
+
+  def test_EmptyFile(self):
+    self.assertParsesTo("", [])
+
+  def test_SingleGroup(self):
+    self.assertParsesTo(
+      """
+        // CHECK-START: Example Group
+        // CHECK:  foo
+        // CHECK:    bar
+      """,
+      [ ( "Example Group", [ ("foo", TestAssertion.Variant.InOrder),
+                             ("bar", TestAssertion.Variant.InOrder) ] ) ])
+
+  def test_MultipleGroups(self):
+    self.assertParsesTo(
+      """
+        // CHECK-START: Example Group1
+        // CHECK: foo
+        // CHECK: bar
+        // CHECK-START: Example Group2
+        // CHECK: abc
+        // CHECK: def
+      """,
+      [ ( "Example Group1", [ ("foo", TestAssertion.Variant.InOrder),
+                              ("bar", TestAssertion.Variant.InOrder) ] ),
+        ( "Example Group2", [ ("abc", TestAssertion.Variant.InOrder),
+                              ("def", TestAssertion.Variant.InOrder) ] ) ])
+
+  def test_AssertionVariants(self):
+    self.assertParsesTo(
+      """
+        // CHECK-START: Example Group
+        // CHECK:     foo
+        // CHECK-NOT: bar
+        // CHECK-DAG: abc
+        // CHECK-DAG: def
+      """,
+      [ ( "Example Group", [ ("foo", TestAssertion.Variant.InOrder),
+                             ("bar", TestAssertion.Variant.Not),
+                             ("abc", TestAssertion.Variant.DAG),
+                             ("def", TestAssertion.Variant.DAG) ] ) ])
diff --git a/tools/checker/file_format/common.py b/tools/checker/file_format/common.py
new file mode 100644
index 0000000..f91fdeb
--- /dev/null
+++ b/tools/checker/file_format/common.py
@@ -0,0 +1,48 @@
+# Copyright (C) 2014 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.
+
+def SplitStream(stream, fnProcessLine, fnLineOutsideChunk):
+  """ Reads the given input stream and splits it into chunks based on
+      information extracted from individual lines.
+
+  Arguments:
+   - fnProcessLine: Called on each line with the text and line number. Must
+     return a pair, name of the chunk started on this line and data extracted
+     from this line (or None in both cases).
+   - fnLineOutsideChunk: Called on attempt to attach data prior to creating
+     a chunk.
+  """
+  lineNo = 0
+  allChunks = []
+  currentChunk = None
+
+  for line in stream:
+    lineNo += 1
+    line = line.strip()
+    if not line:
+      continue
+
+    # Let the child class process the line and return information about it.
+    # The _processLine method can modify the content of the line (or delete it
+    # entirely) and specify whether it starts a new group.
+    processedLine, newChunkName = fnProcessLine(line, lineNo)
+    if newChunkName is not None:
+      currentChunk = (newChunkName, [], lineNo)
+      allChunks.append(currentChunk)
+    if processedLine is not None:
+      if currentChunk is not None:
+        currentChunk[1].append(processedLine)
+      else:
+        fnLineOutsideChunk(line, lineNo)
+  return allChunks
diff --git a/tools/checker/match/__init__.py b/tools/checker/match/__init__.py
new file mode 100644
index 0000000..d0a140b
--- /dev/null
+++ b/tools/checker/match/__init__.py
@@ -0,0 +1,13 @@
+# Copyright (C) 2014 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.
diff --git a/tools/checker/match/file.py b/tools/checker/match/file.py
new file mode 100644
index 0000000..2ed4aa7
--- /dev/null
+++ b/tools/checker/match/file.py
@@ -0,0 +1,147 @@
+# Copyright (C) 2014 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.
+
+from common.logger                    import Logger
+from file_format.c1visualizer.struct  import C1visualizerFile, C1visualizerPass
+from file_format.checker.struct       import CheckerFile, TestCase, TestAssertion
+from match.line                       import MatchLines
+
+def __headAndTail(list):
+  return list[0], list[1:]
+
+def __splitByVariant(lines, variant):
+  """ Splits a list of check lines at index 'i' such that lines[i] is the first
+      element whose variant is not equal to the given parameter.
+  """
+  i = 0
+  while i < len(lines) and lines[i].variant == variant:
+    i += 1
+  return lines[:i], lines[i:]
+
+def __nextIndependentChecks(checkLines):
+  """ Extracts the first sequence of check lines which are independent of each
+      other's match location, i.e. either consecutive DAG lines or a single
+      InOrder line. Any Not lines preceeding this sequence are also extracted.
+  """
+  notChecks, checkLines = __splitByVariant(checkLines, TestAssertion.Variant.Not)
+  if not checkLines:
+    return notChecks, [], []
+
+  head, tail = __headAndTail(checkLines)
+  if head.variant == TestAssertion.Variant.InOrder:
+    return notChecks, [head], tail
+  else:
+    assert head.variant == TestAssertion.Variant.DAG
+    independentChecks, checkLines = __splitByVariant(checkLines, TestAssertion.Variant.DAG)
+    return notChecks, independentChecks, checkLines
+
+def __findFirstMatch(checkLine, outputLines, startLineNo, lineFilter, varState):
+  """ If successful, returns the line number of the first output line matching
+      the check line and the updated variable state. Otherwise returns -1 and
+      None, respectively. The 'lineFilter' parameter can be used to supply a
+      list of line numbers (counting from 1) which should be skipped.
+  """
+  matchLineNo = startLineNo
+  for outputLine in outputLines:
+    if matchLineNo not in lineFilter:
+      newVarState = MatchLines(checkLine, outputLine, varState)
+      if newVarState is not None:
+        return matchLineNo, newVarState
+    matchLineNo += 1
+  return -1, None
+
+def __matchIndependentChecks(checkLines, outputLines, startLineNo, varState):
+  """ Matches the given positive check lines against the output in order of
+      appearance. Variable state is propagated but the scope of the search
+      remains the same for all checks. Each output line can only be matched
+      once. If all check lines are matched, the resulting variable state is
+      returned together with the remaining output. The function also returns
+      output lines which appear before either of the matched lines so they can
+      be tested against Not checks.
+  """
+  # If no checks are provided, skip over the entire output.
+  if not checkLines:
+    return outputLines, [], startLineNo + len(outputLines), varState
+
+  # Keep track of which lines have been matched.
+  matchedLines = []
+
+  # Find first unused output line which matches each check line.
+  for checkLine in checkLines:
+    matchLineNo, varState = \
+      __findFirstMatch(checkLine, outputLines, startLineNo, matchedLines, varState)
+    if varState is None:
+      Logger.testFailed("Could not match check line \"" + checkLine.originalText + "\" " +
+                        "starting from output line " + str(startLineNo),
+                        checkLine.fileName, checkLine.lineNo)
+    matchedLines.append(matchLineNo)
+
+  # Return new variable state and the output lines which lie outside the
+  # match locations of this independent group.
+  minMatchLineNo = min(matchedLines)
+  maxMatchLineNo = max(matchedLines)
+  preceedingLines = outputLines[:minMatchLineNo - startLineNo]
+  remainingLines = outputLines[maxMatchLineNo - startLineNo + 1:]
+  return preceedingLines, remainingLines, maxMatchLineNo + 1, varState
+
+def __matchNotLines(checkLines, outputLines, startLineNo, varState):
+  """ Makes sure that the given check lines do not match any of the given output
+      lines. Variable state does not change.
+  """
+  for checkLine in checkLines:
+    assert checkLine.variant == TestAssertion.Variant.Not
+    matchLineNo, matchVarState = \
+      __findFirstMatch(checkLine, outputLines, startLineNo, [], varState)
+    if matchVarState is not None:
+      Logger.testFailed("CHECK-NOT line \"" + checkLine.originalText + "\" matches output line " + \
+                        str(matchLineNo), checkLine.fileName, checkLine.lineNo)
+
+def __matchGroups(checkGroup, outputGroup):
+  """ Matches the check lines in this group against an output group. It is
+      responsible for running the checks in the right order and scope, and
+      for propagating the variable state between the check lines.
+  """
+  varState = {}
+  checkLines = checkGroup.assertions
+  outputLines = outputGroup.body
+  startLineNo = outputGroup.startLineNo
+
+  while checkLines:
+    # Extract the next sequence of location-independent checks to be matched.
+    notChecks, independentChecks, checkLines = __nextIndependentChecks(checkLines)
+
+    # Match the independent checks.
+    notOutput, outputLines, newStartLineNo, newVarState = \
+      __matchIndependentChecks(independentChecks, outputLines, startLineNo, varState)
+
+    # Run the Not checks against the output lines which lie between the last
+    # two independent groups or the bounds of the output.
+    __matchNotLines(notChecks, notOutput, startLineNo, varState)
+
+    # Update variable state.
+    startLineNo = newStartLineNo
+    varState = newVarState
+
+def MatchFiles(checkerFile, c1File):
+  for testCase in checkerFile.testCases:
+    # TODO: Currently does not handle multiple occurrences of the same group
+    # name, e.g. when a pass is run multiple times. It will always try to
+    # match a check group against the first output group of the same name.
+    c1Pass = c1File.findPass(testCase.name)
+    if c1Pass is None:
+      Logger.fail("Test case \"" + testCase.name + "\" not found in the C1visualizer output",
+                  testCase.fileName, testCase.startLineNo)
+    Logger.startTest(testCase.name)
+    __matchGroups(testCase, c1Pass)
+    Logger.testPassed()
diff --git a/tools/checker/match/line.py b/tools/checker/match/line.py
new file mode 100644
index 0000000..f0253c3
--- /dev/null
+++ b/tools/checker/match/line.py
@@ -0,0 +1,89 @@
+# Copyright (C) 2014 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.
+
+from common.logger              import Logger
+from file_format.checker.struct import TestAssertion, RegexExpression
+
+import re
+
+def __isMatchAtStart(match):
+  """ Tests if the given Match occurred at the beginning of the line. """
+  return (match is not None) and (match.start() == 0)
+
+def __generatePattern(checkLine, linePart, varState):
+  """ Returns the regex pattern to be matched in the output line. Variable
+      references are substituted with their current values provided in the
+      'varState' argument.
+
+  An exception is raised if a referenced variable is undefined.
+  """
+  if linePart.variant == RegexExpression.Variant.VarRef:
+    try:
+      return re.escape(varState[linePart.name])
+    except KeyError:
+      Logger.testFailed("Use of undefined variable \"" + linePart.name + "\"",
+                        checkLine.fileName, checkLine.lineNo)
+  else:
+    return linePart.pattern
+
+def __isSeparated(outputLine, matchStart):
+  return (matchStart == 0) or (outputLine[matchStart - 1:matchStart].isspace())
+
+def MatchLines(checkLine, outputLine, initialVarState):
+  """ Attempts to match the check line against a line from the output file with
+      the given initial variable values. It returns the new variable state if
+      successful and None otherwise.
+  """
+  # Do the full matching on a shadow copy of the variable state. If the
+  # matching fails half-way, we will not need to revert the state.
+  varState = dict(initialVarState)
+
+  matchStart = 0
+  isAfterSeparator = True
+
+  # Now try to parse all of the parts of the check line in the right order.
+  # Variable values are updated on-the-fly, meaning that a variable can
+  # be referenced immediately after its definition.
+  for part in checkLine.expressions:
+    if part.variant == RegexExpression.Variant.Separator:
+      isAfterSeparator = True
+      continue
+
+    # Find the earliest match for this line part.
+    pattern = __generatePattern(checkLine, part, varState)
+    while True:
+      match = re.search(pattern, outputLine[matchStart:])
+      if (match is None) or (not isAfterSeparator and not __isMatchAtStart(match)):
+        return None
+      matchEnd = matchStart + match.end()
+      matchStart += match.start()
+
+      # Check if this is a valid match if we expect a whitespace separator
+      # before the matched text. Otherwise loop and look for another match.
+      if not isAfterSeparator or __isSeparated(outputLine, matchStart):
+        break
+      else:
+        matchStart += 1
+
+    if part.variant == RegexExpression.Variant.VarDef:
+      if part.name in varState:
+        Logger.testFailed("Multiple definitions of variable \"" + part.name + "\"",
+                          checkLine.fileName, checkLine.lineNo)
+      varState[part.name] = outputLine[matchStart:matchEnd]
+
+    matchStart = matchEnd
+    isAfterSeparator = False
+
+  # All parts were successfully matched. Return the new variable state.
+  return varState
diff --git a/tools/checker/match/test.py b/tools/checker/match/test.py
new file mode 100644
index 0000000..bb3b1af
--- /dev/null
+++ b/tools/checker/match/test.py
@@ -0,0 +1,326 @@
+# Copyright (C) 2014 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.
+
+from common.testing                  import ToUnicode
+from file_format.c1visualizer.parser import ParseC1visualizerStream
+from file_format.c1visualizer.struct import C1visualizerFile, C1visualizerPass
+from file_format.checker.parser      import ParseCheckerStream, ParseCheckerAssertion
+from file_format.checker.struct      import CheckerFile, TestCase, TestAssertion, RegexExpression
+from match.file                      import MatchFiles
+from match.line                      import MatchLines
+
+import io
+import unittest
+
+CheckerException = SystemExit
+
+class MatchLines_Test(unittest.TestCase):
+
+  def createTestAssertion(self, checkerString):
+    checkerFile = CheckerFile("<checker-file>")
+    testCase = TestCase(checkerFile, "TestMethod TestPass", 0)
+    return ParseCheckerAssertion(testCase, checkerString, TestAssertion.Variant.InOrder, 0)
+
+  def tryMatch(self, checkerString, c1String, varState={}):
+    return MatchLines(self.createTestAssertion(checkerString), ToUnicode(c1String), varState)
+
+  def matches(self, checkerString, c1String, varState={}):
+    return self.tryMatch(checkerString, c1String, varState) is not None
+
+  def test_TextAndWhitespace(self):
+    self.assertTrue(self.matches("foo", "foo"))
+    self.assertTrue(self.matches("foo", "  foo  "))
+    self.assertTrue(self.matches("foo", "foo bar"))
+    self.assertFalse(self.matches("foo", "XfooX"))
+    self.assertFalse(self.matches("foo", "zoo"))
+
+    self.assertTrue(self.matches("foo bar", "foo   bar"))
+    self.assertTrue(self.matches("foo bar", "abc foo bar def"))
+    self.assertTrue(self.matches("foo bar", "foo foo bar bar"))
+
+    self.assertTrue(self.matches("foo bar", "foo X bar"))
+    self.assertFalse(self.matches("foo bar", "foo Xbar"))
+
+  def test_Pattern(self):
+    self.assertTrue(self.matches("foo{{A|B}}bar", "fooAbar"))
+    self.assertTrue(self.matches("foo{{A|B}}bar", "fooBbar"))
+    self.assertFalse(self.matches("foo{{A|B}}bar", "fooCbar"))
+
+  def test_VariableReference(self):
+    self.assertTrue(self.matches("foo<<X>>bar", "foobar", {"X": ""}))
+    self.assertTrue(self.matches("foo<<X>>bar", "fooAbar", {"X": "A"}))
+    self.assertTrue(self.matches("foo<<X>>bar", "fooBbar", {"X": "B"}))
+    self.assertFalse(self.matches("foo<<X>>bar", "foobar", {"X": "A"}))
+    self.assertFalse(self.matches("foo<<X>>bar", "foo bar", {"X": "A"}))
+    with self.assertRaises(CheckerException):
+      self.assertTrue(self.matches("foo<<X>>bar", "foobar", {}))
+
+  def test_VariableDefinition(self):
+    self.assertTrue(self.matches("foo<<X:A|B>>bar", "fooAbar"))
+    self.assertTrue(self.matches("foo<<X:A|B>>bar", "fooBbar"))
+    self.assertFalse(self.matches("foo<<X:A|B>>bar", "fooCbar"))
+
+    env = self.tryMatch("foo<<X:A.*B>>bar", "fooABbar", {})
+    self.assertEqual(env, {"X": "AB"})
+    env = self.tryMatch("foo<<X:A.*B>>bar", "fooAxxBbar", {})
+    self.assertEqual(env, {"X": "AxxB"})
+
+    self.assertTrue(self.matches("foo<<X:A|B>>bar<<X>>baz", "fooAbarAbaz"))
+    self.assertTrue(self.matches("foo<<X:A|B>>bar<<X>>baz", "fooBbarBbaz"))
+    self.assertFalse(self.matches("foo<<X:A|B>>bar<<X>>baz", "fooAbarBbaz"))
+
+  def test_NoVariableRedefinition(self):
+    with self.assertRaises(CheckerException):
+      self.matches("<<X:...>><<X>><<X:...>><<X>>", "foofoobarbar")
+
+  def test_EnvNotChangedOnPartialMatch(self):
+    env = {"Y": "foo"}
+    self.assertFalse(self.matches("<<X:A>>bar", "Abaz", env))
+    self.assertFalse("X" in env.keys())
+
+  def test_VariableContentEscaped(self):
+    self.assertTrue(self.matches("<<X:..>>foo<<X>>", ".*foo.*"))
+    self.assertFalse(self.matches("<<X:..>>foo<<X>>", ".*fooAAAA"))
+
+
+class MatchFiles_Test(unittest.TestCase):
+
+  def matches(self, checkerString, c1String):
+    checkerString = \
+      """
+        // CHECK-START: MyMethod MyPass
+      """ + checkerString
+    c1String = \
+      """
+        begin_compilation
+          name "MyMethod"
+          method "MyMethod"
+          date 1234
+        end_compilation
+        begin_cfg
+          name "MyPass"
+      """ + c1String + \
+      """
+        end_cfg
+      """
+    checkerFile = ParseCheckerStream("<test-file>", "CHECK", io.StringIO(ToUnicode(checkerString)))
+    c1File = ParseC1visualizerStream("<c1-file>", io.StringIO(ToUnicode(c1String)))
+    try:
+      MatchFiles(checkerFile, c1File)
+      return True
+    except CheckerException:
+      return False
+
+  def test_Text(self):
+    self.assertTrue(self.matches( "// CHECK: foo bar", "foo bar"))
+    self.assertFalse(self.matches("// CHECK: foo bar", "abc def"))
+
+  def test_Pattern(self):
+    self.assertTrue(self.matches( "// CHECK: abc {{de.}}", "abc de#"))
+    self.assertFalse(self.matches("// CHECK: abc {{de.}}", "abc d#f"))
+
+  def test_Variables(self):
+    self.assertTrue(self.matches(
+    """
+      // CHECK: foo<<X:.>>bar
+      // CHECK: abc<<X>>def
+    """,
+    """
+      foo bar
+      abc def
+    """))
+    self.assertTrue(self.matches(
+    """
+      // CHECK: foo<<X:([0-9]+)>>bar
+      // CHECK: abc<<X>>def
+      // CHECK: ### <<X>> ###
+    """,
+    """
+      foo1234bar
+      abc1234def
+      ### 1234 ###
+    """))
+    self.assertFalse(self.matches(
+    """
+      // CHECK: foo<<X:([0-9]+)>>bar
+      // CHECK: abc<<X>>def
+    """,
+    """
+      foo1234bar
+      abc1235def
+    """))
+
+  def test_InOrderAssertions(self):
+    self.assertTrue(self.matches(
+    """
+      // CHECK: foo
+      // CHECK: bar
+    """,
+    """
+      foo
+      bar
+    """))
+    self.assertFalse(self.matches(
+    """
+      // CHECK: foo
+      // CHECK: bar
+    """,
+    """
+      bar
+      foo
+    """))
+
+  def test_DagAssertions(self):
+    self.assertTrue(self.matches(
+    """
+      // CHECK-DAG: foo
+      // CHECK-DAG: bar
+    """,
+    """
+      foo
+      bar
+    """))
+    self.assertTrue(self.matches(
+    """
+      // CHECK-DAG: foo
+      // CHECK-DAG: bar
+    """,
+    """
+      bar
+      foo
+    """))
+
+  def test_DagAssertionsScope(self):
+    self.assertTrue(self.matches(
+    """
+      // CHECK:     foo
+      // CHECK-DAG: abc
+      // CHECK-DAG: def
+      // CHECK:     bar
+    """,
+    """
+      foo
+      def
+      abc
+      bar
+    """))
+    self.assertFalse(self.matches(
+    """
+      // CHECK:     foo
+      // CHECK-DAG: abc
+      // CHECK-DAG: def
+      // CHECK:     bar
+    """,
+    """
+      foo
+      abc
+      bar
+      def
+    """))
+    self.assertFalse(self.matches(
+    """
+      // CHECK:     foo
+      // CHECK-DAG: abc
+      // CHECK-DAG: def
+      // CHECK:     bar
+    """,
+    """
+      foo
+      def
+      bar
+      abc
+    """))
+
+  def test_NotAssertions(self):
+    self.assertTrue(self.matches(
+    """
+      // CHECK-NOT: foo
+    """,
+    """
+      abc
+      def
+    """))
+    self.assertFalse(self.matches(
+    """
+      // CHECK-NOT: foo
+    """,
+    """
+      abc foo
+      def
+    """))
+    self.assertFalse(self.matches(
+    """
+      // CHECK-NOT: foo
+      // CHECK-NOT: bar
+    """,
+    """
+      abc
+      def bar
+    """))
+
+  def test_NotAssertionsScope(self):
+    self.assertTrue(self.matches(
+    """
+      // CHECK:     abc
+      // CHECK-NOT: foo
+      // CHECK:     def
+    """,
+    """
+      abc
+      def
+    """))
+    self.assertTrue(self.matches(
+    """
+      // CHECK:     abc
+      // CHECK-NOT: foo
+      // CHECK:     def
+    """,
+    """
+      abc
+      def
+      foo
+    """))
+    self.assertFalse(self.matches(
+    """
+      // CHECK:     abc
+      // CHECK-NOT: foo
+      // CHECK:     def
+    """,
+    """
+      abc
+      foo
+      def
+    """))
+
+  def test_LineOnlyMatchesOnce(self):
+    self.assertTrue(self.matches(
+    """
+      // CHECK-DAG: foo
+      // CHECK-DAG: foo
+    """,
+    """
+      foo
+      abc
+      foo
+    """))
+    self.assertFalse(self.matches(
+    """
+      // CHECK-DAG: foo
+      // CHECK-DAG: foo
+    """,
+    """
+      foo
+      abc
+      bar
+    """))
diff --git a/tools/checker/run_unit_tests.py b/tools/checker/run_unit_tests.py
new file mode 100755
index 0000000..01708db
--- /dev/null
+++ b/tools/checker/run_unit_tests.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python2
+#
+# Copyright (C) 2014 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.
+
+from common.logger                 import Logger
+from file_format.c1visualizer.test import C1visualizerParser_Test
+from file_format.checker.test      import CheckerParser_PrefixTest, \
+                                          CheckerParser_RegexExpressionTest, \
+                                          CheckerParser_FileLayoutTest
+from match.test                    import MatchLines_Test, \
+                                          MatchFiles_Test
+
+import unittest
+
+if __name__ == '__main__':
+  Logger.Verbosity = Logger.Level.NoOutput
+  unittest.main(verbosity=2)
diff --git a/tools/checker_test.py b/tools/checker_test.py
deleted file mode 100755
index 667ca90..0000000
--- a/tools/checker_test.py
+++ /dev/null
@@ -1,474 +0,0 @@
-#!/usr/bin/env python2
-#
-# Copyright (C) 2014 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.
-
-# This is a test file which exercises all feautres supported by the domain-
-# specific markup language implemented by Checker.
-
-import checker
-import io
-import unittest
-
-# The parent type of exception expected to be thrown by Checker during tests.
-# It must be specific enough to not cover exceptions thrown due to actual flaws
-# in Checker.
-CheckerException = SystemExit
-
-
-class TestCheckFile_PrefixExtraction(unittest.TestCase):
-  def __tryParse(self, string):
-    checkFile = checker.CheckFile(None, [])
-    return checkFile._extractLine("CHECK", string)
-
-  def test_InvalidFormat(self):
-    self.assertIsNone(self.__tryParse("CHECK"))
-    self.assertIsNone(self.__tryParse(":CHECK"))
-    self.assertIsNone(self.__tryParse("CHECK:"))
-    self.assertIsNone(self.__tryParse("//CHECK"))
-    self.assertIsNone(self.__tryParse("#CHECK"))
-
-    self.assertIsNotNone(self.__tryParse("//CHECK:foo"))
-    self.assertIsNotNone(self.__tryParse("#CHECK:bar"))
-
-  def test_InvalidLabel(self):
-    self.assertIsNone(self.__tryParse("//ACHECK:foo"))
-    self.assertIsNone(self.__tryParse("#ACHECK:foo"))
-
-  def test_NotFirstOnTheLine(self):
-    self.assertIsNone(self.__tryParse("A// CHECK: foo"))
-    self.assertIsNone(self.__tryParse("A # CHECK: foo"))
-    self.assertIsNone(self.__tryParse("// // CHECK: foo"))
-    self.assertIsNone(self.__tryParse("# # CHECK: foo"))
-
-  def test_WhitespaceAgnostic(self):
-    self.assertIsNotNone(self.__tryParse("  //CHECK: foo"))
-    self.assertIsNotNone(self.__tryParse("//  CHECK: foo"))
-    self.assertIsNotNone(self.__tryParse("    //CHECK: foo"))
-    self.assertIsNotNone(self.__tryParse("//    CHECK: foo"))
-
-
-class TestCheckLine_Parse(unittest.TestCase):
-  def __getPartPattern(self, linePart):
-    if linePart.variant == checker.CheckElement.Variant.Separator:
-      return "\s+"
-    else:
-      return linePart.pattern
-
-  def __getRegex(self, checkLine):
-    return "".join(map(lambda x: "(" + self.__getPartPattern(x) + ")", checkLine.lineParts))
-
-  def __tryParse(self, string):
-    return checker.CheckLine(string)
-
-  def __parsesTo(self, string, expected):
-    self.assertEqual(expected, self.__getRegex(self.__tryParse(string)))
-
-  def __tryParseNot(self, string):
-    return checker.CheckLine(string, checker.CheckLine.Variant.Not)
-
-  def __parsesPattern(self, string, pattern):
-    line = self.__tryParse(string)
-    self.assertEqual(1, len(line.lineParts))
-    self.assertEqual(checker.CheckElement.Variant.Pattern, line.lineParts[0].variant)
-    self.assertEqual(pattern, line.lineParts[0].pattern)
-
-  def __parsesVarRef(self, string, name):
-    line = self.__tryParse(string)
-    self.assertEqual(1, len(line.lineParts))
-    self.assertEqual(checker.CheckElement.Variant.VarRef, line.lineParts[0].variant)
-    self.assertEqual(name, line.lineParts[0].name)
-
-  def __parsesVarDef(self, string, name, body):
-    line = self.__tryParse(string)
-    self.assertEqual(1, len(line.lineParts))
-    self.assertEqual(checker.CheckElement.Variant.VarDef, line.lineParts[0].variant)
-    self.assertEqual(name, line.lineParts[0].name)
-    self.assertEqual(body, line.lineParts[0].pattern)
-
-  def __doesNotParse(self, string, partType):
-    line = self.__tryParse(string)
-    self.assertEqual(1, len(line.lineParts))
-    self.assertNotEqual(partType, line.lineParts[0].variant)
-
-  # Test that individual parts of the line are recognized
-
-  def test_TextOnly(self):
-    self.__parsesTo("foo", "(foo)")
-    self.__parsesTo("  foo  ", "(foo)")
-    self.__parsesTo("f$o^o", "(f\$o\^o)")
-
-  def test_TextWithWhitespace(self):
-    self.__parsesTo("foo bar", "(foo)(\s+)(bar)")
-    self.__parsesTo("foo   bar", "(foo)(\s+)(bar)")
-
-  def test_RegexOnly(self):
-    self.__parsesPattern("{{a?b.c}}", "a?b.c")
-
-  def test_VarRefOnly(self):
-    self.__parsesVarRef("[[ABC]]", "ABC")
-
-  def test_VarDefOnly(self):
-    self.__parsesVarDef("[[ABC:a?b.c]]", "ABC", "a?b.c")
-
-  def test_TextWithRegex(self):
-    self.__parsesTo("foo{{abc}}bar", "(foo)(abc)(bar)")
-
-  def test_TextWithVar(self):
-    self.__parsesTo("foo[[ABC:abc]]bar", "(foo)(abc)(bar)")
-
-  def test_PlainWithRegexAndWhitespaces(self):
-    self.__parsesTo("foo {{abc}}bar", "(foo)(\s+)(abc)(bar)")
-    self.__parsesTo("foo{{abc}} bar", "(foo)(abc)(\s+)(bar)")
-    self.__parsesTo("foo {{abc}} bar", "(foo)(\s+)(abc)(\s+)(bar)")
-
-  def test_PlainWithVarAndWhitespaces(self):
-    self.__parsesTo("foo [[ABC:abc]]bar", "(foo)(\s+)(abc)(bar)")
-    self.__parsesTo("foo[[ABC:abc]] bar", "(foo)(abc)(\s+)(bar)")
-    self.__parsesTo("foo [[ABC:abc]] bar", "(foo)(\s+)(abc)(\s+)(bar)")
-
-  def test_AllKinds(self):
-    self.__parsesTo("foo [[ABC:abc]]{{def}}bar", "(foo)(\s+)(abc)(def)(bar)")
-    self.__parsesTo("foo[[ABC:abc]] {{def}}bar", "(foo)(abc)(\s+)(def)(bar)")
-    self.__parsesTo("foo [[ABC:abc]] {{def}} bar", "(foo)(\s+)(abc)(\s+)(def)(\s+)(bar)")
-
-  # Test that variables and patterns are parsed correctly
-
-  def test_ValidPattern(self):
-    self.__parsesPattern("{{abc}}", "abc")
-    self.__parsesPattern("{{a[b]c}}", "a[b]c")
-    self.__parsesPattern("{{(a{bc})}}", "(a{bc})")
-
-  def test_ValidRef(self):
-    self.__parsesVarRef("[[ABC]]", "ABC")
-    self.__parsesVarRef("[[A1BC2]]", "A1BC2")
-
-  def test_ValidDef(self):
-    self.__parsesVarDef("[[ABC:abc]]", "ABC", "abc")
-    self.__parsesVarDef("[[ABC:ab:c]]", "ABC", "ab:c")
-    self.__parsesVarDef("[[ABC:a[b]c]]", "ABC", "a[b]c")
-    self.__parsesVarDef("[[ABC:(a[bc])]]", "ABC", "(a[bc])")
-
-  def test_Empty(self):
-    self.__doesNotParse("{{}}", checker.CheckElement.Variant.Pattern)
-    self.__doesNotParse("[[]]", checker.CheckElement.Variant.VarRef)
-    self.__doesNotParse("[[:]]", checker.CheckElement.Variant.VarDef)
-
-  def test_InvalidVarName(self):
-    self.__doesNotParse("[[0ABC]]", checker.CheckElement.Variant.VarRef)
-    self.__doesNotParse("[[AB=C]]", checker.CheckElement.Variant.VarRef)
-    self.__doesNotParse("[[ABC=]]", checker.CheckElement.Variant.VarRef)
-    self.__doesNotParse("[[0ABC:abc]]", checker.CheckElement.Variant.VarDef)
-    self.__doesNotParse("[[AB=C:abc]]", checker.CheckElement.Variant.VarDef)
-    self.__doesNotParse("[[ABC=:abc]]", checker.CheckElement.Variant.VarDef)
-
-  def test_BodyMatchNotGreedy(self):
-    self.__parsesTo("{{abc}}{{def}}", "(abc)(def)")
-    self.__parsesTo("[[ABC:abc]][[DEF:def]]", "(abc)(def)")
-
-  def test_NoVarDefsInNotChecks(self):
-    with self.assertRaises(CheckerException):
-      self.__tryParseNot("[[ABC:abc]]")
-
-class TestCheckLine_Match(unittest.TestCase):
-  def __matchSingle(self, checkString, outputString, varState={}):
-    checkLine = checker.CheckLine(checkString)
-    newVarState = checkLine.match(outputString, varState)
-    self.assertIsNotNone(newVarState)
-    return newVarState
-
-  def __notMatchSingle(self, checkString, outputString, varState={}):
-    checkLine = checker.CheckLine(checkString)
-    self.assertIsNone(checkLine.match(outputString, varState))
-
-  def test_TextAndWhitespace(self):
-    self.__matchSingle("foo", "foo")
-    self.__matchSingle("foo", "  foo  ")
-    self.__matchSingle("foo", "foo bar")
-    self.__notMatchSingle("foo", "XfooX")
-    self.__notMatchSingle("foo", "zoo")
-
-    self.__matchSingle("foo bar", "foo   bar")
-    self.__matchSingle("foo bar", "abc foo bar def")
-    self.__matchSingle("foo bar", "foo foo bar bar")
-
-    self.__matchSingle("foo bar", "foo X bar")
-    self.__notMatchSingle("foo bar", "foo Xbar")
-
-  def test_Pattern(self):
-    self.__matchSingle("foo{{A|B}}bar", "fooAbar")
-    self.__matchSingle("foo{{A|B}}bar", "fooBbar")
-    self.__notMatchSingle("foo{{A|B}}bar", "fooCbar")
-
-  def test_VariableReference(self):
-    self.__matchSingle("foo[[X]]bar", "foobar", {"X": ""})
-    self.__matchSingle("foo[[X]]bar", "fooAbar", {"X": "A"})
-    self.__matchSingle("foo[[X]]bar", "fooBbar", {"X": "B"})
-    self.__notMatchSingle("foo[[X]]bar", "foobar", {"X": "A"})
-    self.__notMatchSingle("foo[[X]]bar", "foo bar", {"X": "A"})
-    with self.assertRaises(CheckerException):
-      self.__matchSingle("foo[[X]]bar", "foobar", {})
-
-  def test_VariableDefinition(self):
-    self.__matchSingle("foo[[X:A|B]]bar", "fooAbar")
-    self.__matchSingle("foo[[X:A|B]]bar", "fooBbar")
-    self.__notMatchSingle("foo[[X:A|B]]bar", "fooCbar")
-
-    env = self.__matchSingle("foo[[X:A.*B]]bar", "fooABbar", {})
-    self.assertEqual(env, {"X": "AB"})
-    env = self.__matchSingle("foo[[X:A.*B]]bar", "fooAxxBbar", {})
-    self.assertEqual(env, {"X": "AxxB"})
-
-    self.__matchSingle("foo[[X:A|B]]bar[[X]]baz", "fooAbarAbaz")
-    self.__matchSingle("foo[[X:A|B]]bar[[X]]baz", "fooBbarBbaz")
-    self.__notMatchSingle("foo[[X:A|B]]bar[[X]]baz", "fooAbarBbaz")
-
-  def test_NoVariableRedefinition(self):
-    with self.assertRaises(CheckerException):
-      self.__matchSingle("[[X:...]][[X]][[X:...]][[X]]", "foofoobarbar")
-
-  def test_EnvNotChangedOnPartialMatch(self):
-    env = {"Y": "foo"}
-    self.__notMatchSingle("[[X:A]]bar", "Abaz", env)
-    self.assertFalse("X" in env.keys())
-
-  def test_VariableContentEscaped(self):
-    self.__matchSingle("[[X:..]]foo[[X]]", ".*foo.*")
-    self.__notMatchSingle("[[X:..]]foo[[X]]", ".*fooAAAA")
-
-
-CheckVariant = checker.CheckLine.Variant
-
-def prepareSingleCheck(line):
-  if isinstance(line, str):
-    return checker.CheckLine(line)
-  else:
-    return checker.CheckLine(line[0], line[1])
-
-def prepareChecks(lines):
-  if isinstance(lines, str):
-    lines = lines.splitlines()
-  return list(map(lambda line: prepareSingleCheck(line), lines))
-
-
-class TestCheckGroup_Match(unittest.TestCase):
-  def __matchMulti(self, checkLines, outputString):
-    checkGroup = checker.CheckGroup("MyGroup", prepareChecks(checkLines))
-    outputGroup = checker.OutputGroup("MyGroup", outputString.splitlines())
-    return checkGroup.match(outputGroup)
-
-  def __notMatchMulti(self, checkString, outputString):
-    with self.assertRaises(CheckerException):
-      self.__matchMulti(checkString, outputString)
-
-  def test_TextAndPattern(self):
-    self.__matchMulti("""foo bar
-                         abc {{def}}""",
-                      """foo bar
-                         abc def""");
-    self.__matchMulti("""foo bar
-                         abc {{de.}}""",
-                      """=======
-                         foo bar
-                         =======
-                         abc de#
-                         =======""");
-    self.__notMatchMulti("""//XYZ: foo bar
-                            //XYZ: abc {{def}}""",
-                         """=======
-                            foo bar
-                            =======
-                            abc de#
-                            =======""");
-
-  def test_Variables(self):
-    self.__matchMulti("""foo[[X:.]]bar
-                         abc[[X]]def""",
-                      """foo bar
-                         abc def""");
-    self.__matchMulti("""foo[[X:([0-9]+)]]bar
-                         abc[[X]]def
-                         ### [[X]] ###""",
-                      """foo1234bar
-                         abc1234def
-                         ### 1234 ###""");
-
-  def test_Ordering(self):
-    self.__matchMulti([("foo", CheckVariant.InOrder),
-                       ("bar", CheckVariant.InOrder)],
-                      """foo
-                         bar""")
-    self.__notMatchMulti([("foo", CheckVariant.InOrder),
-                          ("bar", CheckVariant.InOrder)],
-                         """bar
-                            foo""")
-    self.__matchMulti([("abc", CheckVariant.DAG),
-                       ("def", CheckVariant.DAG)],
-                      """abc
-                         def""")
-    self.__matchMulti([("abc", CheckVariant.DAG),
-                       ("def", CheckVariant.DAG)],
-                      """def
-                         abc""")
-    self.__matchMulti([("foo", CheckVariant.InOrder),
-                       ("abc", CheckVariant.DAG),
-                       ("def", CheckVariant.DAG),
-                       ("bar", CheckVariant.InOrder)],
-                      """foo
-                         def
-                         abc
-                         bar""")
-    self.__notMatchMulti([("foo", CheckVariant.InOrder),
-                          ("abc", CheckVariant.DAG),
-                          ("def", CheckVariant.DAG),
-                          ("bar", CheckVariant.InOrder)],
-                         """foo
-                            abc
-                            bar""")
-    self.__notMatchMulti([("foo", CheckVariant.InOrder),
-                          ("abc", CheckVariant.DAG),
-                          ("def", CheckVariant.DAG),
-                          ("bar", CheckVariant.InOrder)],
-                         """foo
-                            def
-                            bar""")
-
-  def test_NotAssertions(self):
-    self.__matchMulti([("foo", CheckVariant.Not)],
-                      """abc
-                         def""")
-    self.__notMatchMulti([("foo", CheckVariant.Not)],
-                         """abc foo
-                            def""")
-    self.__notMatchMulti([("foo", CheckVariant.Not),
-                          ("bar", CheckVariant.Not)],
-                         """abc
-                            def bar""")
-
-  def test_LineOnlyMatchesOnce(self):
-    self.__matchMulti([("foo", CheckVariant.DAG),
-                       ("foo", CheckVariant.DAG)],
-                       """foo
-                          foo""")
-    self.__notMatchMulti([("foo", CheckVariant.DAG),
-                          ("foo", CheckVariant.DAG)],
-                          """foo
-                             bar""")
-
-class TestOutputFile_Parse(unittest.TestCase):
-  def __parsesTo(self, string, expected):
-    if isinstance(string, str):
-      string = unicode(string)
-    outputStream = io.StringIO(string)
-    return self.assertEqual(checker.OutputFile(outputStream).groups, expected)
-
-  def test_NoInput(self):
-    self.__parsesTo(None, [])
-    self.__parsesTo("", [])
-
-  def test_SingleGroup(self):
-    self.__parsesTo("""begin_compilation
-                         method "MyMethod"
-                       end_compilation
-                       begin_cfg
-                         name "pass1"
-                         foo
-                         bar
-                       end_cfg""",
-                    [ checker.OutputGroup("MyMethod pass1", [ "foo", "bar" ]) ])
-
-  def test_MultipleGroups(self):
-    self.__parsesTo("""begin_compilation
-                         name "xyz1"
-                         method "MyMethod1"
-                         date 1234
-                       end_compilation
-                       begin_cfg
-                         name "pass1"
-                         foo
-                         bar
-                       end_cfg
-                       begin_cfg
-                         name "pass2"
-                         abc
-                         def
-                       end_cfg""",
-                    [ checker.OutputGroup("MyMethod1 pass1", [ "foo", "bar" ]),
-                      checker.OutputGroup("MyMethod1 pass2", [ "abc", "def" ]) ])
-
-    self.__parsesTo("""begin_compilation
-                         name "xyz1"
-                         method "MyMethod1"
-                         date 1234
-                       end_compilation
-                       begin_cfg
-                         name "pass1"
-                         foo
-                         bar
-                       end_cfg
-                       begin_compilation
-                         name "xyz2"
-                         method "MyMethod2"
-                         date 5678
-                       end_compilation
-                       begin_cfg
-                         name "pass2"
-                         abc
-                         def
-                       end_cfg""",
-                    [ checker.OutputGroup("MyMethod1 pass1", [ "foo", "bar" ]),
-                      checker.OutputGroup("MyMethod2 pass2", [ "abc", "def" ]) ])
-
-class TestCheckFile_Parse(unittest.TestCase):
-  def __parsesTo(self, string, expected):
-    if isinstance(string, str):
-      string = unicode(string)
-    checkStream = io.StringIO(string)
-    return self.assertEqual(checker.CheckFile("CHECK", checkStream).groups, expected)
-
-  def test_NoInput(self):
-    self.__parsesTo(None, [])
-    self.__parsesTo("", [])
-
-  def test_SingleGroup(self):
-    self.__parsesTo("""// CHECK-START: Example Group
-                       // CHECK:  foo
-                       // CHECK:    bar""",
-                    [ checker.CheckGroup("Example Group", prepareChecks([ "foo", "bar" ])) ])
-
-  def test_MultipleGroups(self):
-    self.__parsesTo("""// CHECK-START: Example Group1
-                       // CHECK: foo
-                       // CHECK: bar
-                       // CHECK-START: Example Group2
-                       // CHECK: abc
-                       // CHECK: def""",
-                    [ checker.CheckGroup("Example Group1", prepareChecks([ "foo", "bar" ])),
-                      checker.CheckGroup("Example Group2", prepareChecks([ "abc", "def" ])) ])
-
-  def test_CheckVariants(self):
-    self.__parsesTo("""// CHECK-START: Example Group
-                       // CHECK:     foo
-                       // CHECK-NOT: bar
-                       // CHECK-DAG: abc
-                       // CHECK-DAG: def""",
-                    [ checker.CheckGroup("Example Group",
-                                         prepareChecks([ ("foo", CheckVariant.InOrder),
-                                                         ("bar", CheckVariant.Not),
-                                                         ("abc", CheckVariant.DAG),
-                                                         ("def", CheckVariant.DAG) ])) ])
-
-if __name__ == '__main__':
-  checker.Logger.Verbosity = checker.Logger.Level.NoOutput
-  unittest.main()
diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt
index a387036..a8bc4e1 100644
--- a/tools/libcore_failures.txt
+++ b/tools/libcore_failures.txt
@@ -109,18 +109,6 @@
   bug: 19165288
 },
 {
-  description: "Bug in libcore",
-  result: EXEC_FAILED,
-  names: ["libcore.javax.crypto.ECDHKeyAgreementTest#testInit_withUnsupportedPrivateKeyType"],
-  bug: 19730263
-},
-{
-  description: "Needs to be run as root",
-  result: EXEC_FAILED,
-  modes: [host],
-  names: ["libcore.io.OsTest#test_PacketSocketAddress"]
-},
-{
   description: "Needs kernel updates on host/device",
   result: EXEC_FAILED,
   names: ["libcore.io.OsTest#test_socketPing"]
@@ -130,5 +118,11 @@
   modes: [device],
   result: EXEC_FAILED,
   names: ["org.apache.harmony.tests.java.lang.ProcessManagerTest#testEnvironment"]
+},
+{
+  description: "Crypto failures",
+  result: EXEC_FAILED,
+  names: ["libcore.javax.crypto.CipherTest#testCipher_ShortBlock_Failure",
+          "libcore.javax.crypto.CipherTest#testCipher_Success"]
 }
 ]
diff --git a/tools/run-jdwp-tests.sh b/tools/run-jdwp-tests.sh
index 1dd443b..77e8004 100755
--- a/tools/run-jdwp-tests.sh
+++ b/tools/run-jdwp-tests.sh
@@ -21,11 +21,10 @@
 
 # Jar containing all the tests.
 test_jar=out/host/linux-x86/framework/apache-harmony-jdwp-tests-hostdex.jar
-junit_jar=out/host/linux-x86/framework/junit.jar
 
-if [ ! -f $test_jar -o ! -f $junit_jar ]; then
+if [ ! -f $test_jar ]; then
   echo "Before running, you must build jdwp tests and vogar:" \
-       "make junit apache-harmony-jdwp-tests-hostdex vogar vogar.jar"
+       "make apache-harmony-jdwp-tests-hostdex vogar vogar.jar"
   exit 1
 fi
 
@@ -80,7 +79,6 @@
       --vm-arg -Djpda.settings.transportAddress=127.0.0.1:55107 \
       --vm-arg -Djpda.settings.debuggeeJavaPath="\"$art_debugee $image $debuggee_args\"" \
       --classpath $test_jar \
-      --classpath $junit_jar \
       --vm-arg -Xcompiler-option --vm-arg --compiler-backend=Optimizing \
       --vm-arg -Xcompiler-option --vm-arg --debuggable \
       org.apache.harmony.jpda.tests.share.AllTests