Merge "Add test for Change-Id: Ied0412a01922b40a3f5d89bed49707498582abc1"
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index 730e61d..5d4f1d3 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -30,6 +30,7 @@
   Interfaces \
   Main \
   MultiDex \
+  MultiDexModifiedSecondary \
   MyClass \
   MyClassNatives \
   Nested \
@@ -68,7 +69,7 @@
 ART_GTEST_instrumentation_test_DEX_DEPS := Instrumentation
 ART_GTEST_jni_compiler_test_DEX_DEPS := MyClassNatives
 ART_GTEST_jni_internal_test_DEX_DEPS := AllFields StaticLeafMethods
-ART_GTEST_oat_file_assistant_test_DEX_DEPS := Main MainStripped MultiDex Nested
+ART_GTEST_oat_file_assistant_test_DEX_DEPS := Main MainStripped MultiDex MultiDexModifiedSecondary Nested
 ART_GTEST_oat_file_test_DEX_DEPS := Main MultiDex
 ART_GTEST_object_test_DEX_DEPS := ProtoCompare ProtoCompare2 StaticsFromCode XandY
 ART_GTEST_proxy_test_DEX_DEPS := Interfaces
diff --git a/cmdline/cmdline_types.h b/cmdline/cmdline_types.h
index 03165ed..e02fe4b 100644
--- a/cmdline/cmdline_types.h
+++ b/cmdline/cmdline_types.h
@@ -579,6 +579,8 @@
         log_verbosity.class_linker = true;
       } else if (verbose_options[j] == "compiler") {
         log_verbosity.compiler = true;
+      } else if (verbose_options[j] == "deopt") {
+        log_verbosity.deopt = true;
       } else if (verbose_options[j] == "gc") {
         log_verbosity.gc = true;
       } else if (verbose_options[j] == "heap") {
diff --git a/compiler/cfi_test.h b/compiler/cfi_test.h
index f7501d2..5e345db 100644
--- a/compiler/cfi_test.h
+++ b/compiler/cfi_test.h
@@ -30,6 +30,8 @@
 
 namespace art {
 
+constexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_DEBUG_FRAME_FORMAT;
+
 class CFITest : public dwarf::DwarfTest {
  public:
   void GenerateExpected(FILE* f, InstructionSet isa, const char* isa_str,
@@ -46,11 +48,11 @@
     // Pretty-print CFI opcodes.
     constexpr bool is64bit = false;
     dwarf::DebugFrameOpCodeWriter<> initial_opcodes;
-    dwarf::WriteEhFrameCIE(is64bit, dwarf::DW_EH_PE_absptr, dwarf::Reg(8),
-                           initial_opcodes, &eh_frame_data_);
-    std::vector<uintptr_t> eh_frame_patches;
-    dwarf::WriteEhFrameFDE(is64bit, 0, 0, actual_asm.size(), &actual_cfi,
-                           &eh_frame_data_, &eh_frame_patches);
+    dwarf::WriteDebugFrameCIE(is64bit, dwarf::DW_EH_PE_absptr, dwarf::Reg(8),
+                              initial_opcodes, kCFIFormat, &debug_frame_data_);
+    std::vector<uintptr_t> debug_frame_patches;
+    dwarf::WriteDebugFrameFDE(is64bit, 0, 0, actual_asm.size(), &actual_cfi,
+                              kCFIFormat, &debug_frame_data_, &debug_frame_patches);
     ReformatCfi(Objdump(false, "-W"), &lines);
     // Pretty-print assembly.
     auto* opts = new DisassemblerOptions(false, actual_asm.data(), true);
diff --git a/compiler/dwarf/dwarf_constants.h b/compiler/dwarf/dwarf_constants.h
index 61a44cd..3b570e5 100644
--- a/compiler/dwarf/dwarf_constants.h
+++ b/compiler/dwarf/dwarf_constants.h
@@ -680,6 +680,14 @@
   DW_EH_PE_aligned = 0x50,
 };
 
+enum CFIFormat : uint8_t {
+  // This is the original format as defined by the specification.
+  // It is used for the .debug_frame section.
+  DW_DEBUG_FRAME_FORMAT,
+  // Slightly modified format used for the .eh_frame section.
+  DW_EH_FRAME_FORMAT
+};
+
 }  // namespace dwarf
 }  // namespace art
 
diff --git a/compiler/dwarf/dwarf_test.cc b/compiler/dwarf/dwarf_test.cc
index edba00a..4971f0e 100644
--- a/compiler/dwarf/dwarf_test.cc
+++ b/compiler/dwarf/dwarf_test.cc
@@ -26,6 +26,8 @@
 namespace art {
 namespace dwarf {
 
+constexpr CFIFormat kCFIFormat = DW_DEBUG_FRAME_FORMAT;
+
 // Run the tests only on host since we need objdump.
 #ifndef HAVE_ANDROID_OS
 
@@ -120,30 +122,30 @@
   DW_CHECK_NEXT("DW_CFA_restore: r5 (ebp)");
 
   DebugFrameOpCodeWriter<> initial_opcodes;
-  WriteEhFrameCIE(is64bit, DW_EH_PE_absptr, Reg(is64bit ? 16 : 8),
-                  initial_opcodes, &eh_frame_data_);
-  std::vector<uintptr_t> eh_frame_patches;
+  WriteDebugFrameCIE(is64bit, DW_EH_PE_absptr, Reg(is64bit ? 16 : 8),
+                     initial_opcodes, kCFIFormat, &debug_frame_data_);
+  std::vector<uintptr_t> debug_frame_patches;
   std::vector<uintptr_t> expected_patches { 28 };  // NOLINT
-  WriteEhFrameFDE(is64bit, 0, 0x01000000, 0x01000000, opcodes.data(),
-                  &eh_frame_data_, &eh_frame_patches);
+  WriteDebugFrameFDE(is64bit, 0, 0x01000000, 0x01000000, opcodes.data(),
+                     kCFIFormat, &debug_frame_data_, &debug_frame_patches);
 
-  EXPECT_EQ(expected_patches, eh_frame_patches);
+  EXPECT_EQ(expected_patches, debug_frame_patches);
   CheckObjdumpOutput(is64bit, "-W");
 }
 
 TEST_F(DwarfTest, DebugFrame64) {
   constexpr bool is64bit = true;
   DebugFrameOpCodeWriter<> initial_opcodes;
-  WriteEhFrameCIE(is64bit, DW_EH_PE_absptr, Reg(16),
-                  initial_opcodes, &eh_frame_data_);
+  WriteDebugFrameCIE(is64bit, DW_EH_PE_absptr, Reg(16),
+                     initial_opcodes, kCFIFormat, &debug_frame_data_);
   DebugFrameOpCodeWriter<> opcodes;
-  std::vector<uintptr_t> eh_frame_patches;
+  std::vector<uintptr_t> debug_frame_patches;
   std::vector<uintptr_t> expected_patches { 32 };  // NOLINT
-  WriteEhFrameFDE(is64bit, 0, 0x0100000000000000, 0x0200000000000000,
-                  opcodes.data(), &eh_frame_data_, &eh_frame_patches);
+  WriteDebugFrameFDE(is64bit, 0, 0x0100000000000000, 0x0200000000000000,
+                     opcodes.data(), kCFIFormat, &debug_frame_data_, &debug_frame_patches);
   DW_CHECK("FDE cie=00000000 pc=100000000000000..300000000000000");
 
-  EXPECT_EQ(expected_patches, eh_frame_patches);
+  EXPECT_EQ(expected_patches, debug_frame_patches);
   CheckObjdumpOutput(is64bit, "-W");
 }
 
@@ -173,11 +175,11 @@
   DW_CHECK_NEXT("DW_CFA_offset: r14 (r14)");
   DW_CHECK_NEXT("DW_CFA_offset: r15 (r15)");
   DebugFrameOpCodeWriter<> initial_opcodes;
-  WriteEhFrameCIE(is64bit, DW_EH_PE_absptr, Reg(16),
-                  initial_opcodes, &eh_frame_data_);
-  std::vector<uintptr_t> eh_frame_patches;
-  WriteEhFrameFDE(is64bit, 0, 0x0100000000000000, 0x0200000000000000,
-                  opcodes.data(), &eh_frame_data_, &eh_frame_patches);
+  WriteDebugFrameCIE(is64bit, DW_EH_PE_absptr, Reg(16),
+                     initial_opcodes, kCFIFormat, &debug_frame_data_);
+  std::vector<uintptr_t> debug_frame_patches;
+  WriteDebugFrameFDE(is64bit, 0, 0x0100000000000000, 0x0200000000000000,
+                     opcodes.data(), kCFIFormat, &debug_frame_data_, &debug_frame_patches);
 
   CheckObjdumpOutput(is64bit, "-W");
 }
diff --git a/compiler/dwarf/dwarf_test.h b/compiler/dwarf/dwarf_test.h
index 230ebe3..3afb5ea 100644
--- a/compiler/dwarf/dwarf_test.h
+++ b/compiler/dwarf/dwarf_test.h
@@ -69,7 +69,7 @@
     RawSection debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
     RawSection debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
     RawSection debug_line(".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
-    RawSection eh_frame(".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0);
+    RawSection debug_frame(".debug_frame", SHT_PROGBITS, 0, nullptr, 0, 8, 0);
     if (!debug_info_data_.empty()) {
       debug_info.SetBuffer(debug_info_data_);
       builder.RegisterSection(&debug_info);
@@ -86,9 +86,9 @@
       debug_line.SetBuffer(debug_line_data_);
       builder.RegisterSection(&debug_line);
     }
-    if (!eh_frame_data_.empty()) {
-      eh_frame.SetBuffer(eh_frame_data_);
-      builder.RegisterSection(&eh_frame);
+    if (!debug_frame_data_.empty()) {
+      debug_frame.SetBuffer(debug_frame_data_);
+      builder.RegisterSection(&debug_frame);
     }
     ScratchFile file;
     builder.Write(file.GetFile());
@@ -167,7 +167,7 @@
   }
 
   // Buffers which are going to assembled into ELF file and passed to objdump.
-  std::vector<uint8_t> eh_frame_data_;
+  std::vector<uint8_t> debug_frame_data_;
   std::vector<uint8_t> debug_info_data_;
   std::vector<uint8_t> debug_abbrev_data_;
   std::vector<uint8_t> debug_str_data_;
diff --git a/compiler/dwarf/headers.h b/compiler/dwarf/headers.h
index 9f64766..ad315ee 100644
--- a/compiler/dwarf/headers.h
+++ b/compiler/dwarf/headers.h
@@ -35,17 +35,18 @@
 // and compilers are expected *not* to use it by default.
 // In particular, it is not related to machine architecture.
 
-// Write common information entry (CIE) to .eh_frame section.
+// Write common information entry (CIE) to .debug_frame or .eh_frame section.
 template<typename Allocator>
-void WriteEhFrameCIE(bool is64bit,
-                     ExceptionHeaderValueApplication address_type,
-                     Reg return_address_register,
-                     const DebugFrameOpCodeWriter<Allocator>& opcodes,
-                     std::vector<uint8_t>* eh_frame) {
-  Writer<> writer(eh_frame);
+void WriteDebugFrameCIE(bool is64bit,
+                        ExceptionHeaderValueApplication address_type,
+                        Reg return_address_register,
+                        const DebugFrameOpCodeWriter<Allocator>& opcodes,
+                        CFIFormat format,
+                        std::vector<uint8_t>* debug_frame) {
+  Writer<> writer(debug_frame);
   size_t cie_header_start_ = writer.data()->size();
   writer.PushUint32(0);  // Length placeholder.
-  writer.PushUint32(0);  // CIE id.
+  writer.PushUint32((format == DW_EH_FRAME_FORMAT) ? 0 : 0xFFFFFFFF);  // CIE id.
   writer.PushUint8(1);   // Version.
   writer.PushString("zR");
   writer.PushUleb128(DebugFrameOpCodeWriter<Allocator>::kCodeAlignmentFactor);
@@ -62,20 +63,26 @@
   writer.UpdateUint32(cie_header_start_, writer.data()->size() - cie_header_start_ - 4);
 }
 
-// Write frame description entry (FDE) to .eh_frame section.
+// Write frame description entry (FDE) to .debug_frame or .eh_frame section.
 template<typename Allocator>
-void WriteEhFrameFDE(bool is64bit, size_t cie_offset,
-                     uint64_t initial_address, uint64_t address_range,
-                     const std::vector<uint8_t, Allocator>* opcodes,
-                     std::vector<uint8_t>* eh_frame,
-                     std::vector<uintptr_t>* eh_frame_patches) {
-  Writer<> writer(eh_frame);
+void WriteDebugFrameFDE(bool is64bit, size_t cie_offset,
+                        uint64_t initial_address, uint64_t address_range,
+                        const std::vector<uint8_t, Allocator>* opcodes,
+                        CFIFormat format,
+                        std::vector<uint8_t>* debug_frame,
+                        std::vector<uintptr_t>* debug_frame_patches) {
+  Writer<> writer(debug_frame);
   size_t fde_header_start = writer.data()->size();
   writer.PushUint32(0);  // Length placeholder.
-  uint32_t cie_pointer = writer.data()->size() - cie_offset;
-  writer.PushUint32(cie_pointer);
+  if (format == DW_EH_FRAME_FORMAT) {
+    uint32_t cie_pointer = writer.data()->size() - cie_offset;
+    writer.PushUint32(cie_pointer);
+  } else {
+    uint32_t cie_pointer = cie_offset;
+    writer.PushUint32(cie_pointer);
+  }
   // Relocate initial_address, but not address_range (it is size).
-  eh_frame_patches->push_back(writer.data()->size());
+  debug_frame_patches->push_back(writer.data()->size());
   if (is64bit) {
     writer.PushUint64(initial_address);
     writer.PushUint64(address_range);
diff --git a/compiler/elf_builder.h b/compiler/elf_builder.h
index 63d3a0d..972bd08 100644
--- a/compiler/elf_builder.h
+++ b/compiler/elf_builder.h
@@ -56,12 +56,12 @@
    public:
     Section(const std::string& name, Elf_Word type, Elf_Word flags,
             const Section* link, Elf_Word info, Elf_Word align, Elf_Word entsize)
-        : header_(), section_index_(0), name_(name), link_(link) {
-      header_.sh_type = type;
-      header_.sh_flags = flags;
-      header_.sh_info = info;
-      header_.sh_addralign = align;
-      header_.sh_entsize = entsize;
+        : header_(new Elf_Shdr()), section_index_(0), name_(name), link_(link) {
+      header_->sh_type = type;
+      header_->sh_flags = flags;
+      header_->sh_info = info;
+      header_->sh_addralign = align;
+      header_->sh_entsize = entsize;
     }
     virtual ~Section() {}
 
@@ -79,11 +79,11 @@
     }
 
     const Elf_Shdr* GetHeader() const {
-      return &header_;
+      return header_.get();
     }
 
     Elf_Shdr* GetHeader() {
-      return &header_;
+      return header_.get();
     }
 
     Elf_Word GetSectionIndex() const {
@@ -100,7 +100,9 @@
     }
 
    private:
-    Elf_Shdr header_;
+    // Elf_Shdr is somewhat large so allocate it on the heap.
+    // Otherwise we get in trouble with stack frame sizes.
+    std::unique_ptr<Elf_Shdr> header_;
     Elf_Word section_index_;
     const std::string name_;
     const Section* const link_;
diff --git a/compiler/elf_writer_debug.cc b/compiler/elf_writer_debug.cc
index 5e9cf76..a1aabc3 100644
--- a/compiler/elf_writer_debug.cc
+++ b/compiler/elf_writer_debug.cc
@@ -29,9 +29,10 @@
 namespace art {
 namespace dwarf {
 
-static void WriteEhFrameCIE(InstructionSet isa,
-                            ExceptionHeaderValueApplication addr_type,
-                            std::vector<uint8_t>* eh_frame) {
+static void WriteDebugFrameCIE(InstructionSet isa,
+                               ExceptionHeaderValueApplication addr_type,
+                               CFIFormat format,
+                               std::vector<uint8_t>* eh_frame) {
   // Scratch registers should be marked as undefined.  This tells the
   // debugger that its value in the previous frame is not recoverable.
   bool is64bit = Is64BitInstructionSet(isa);
@@ -57,7 +58,8 @@
         }
       }
       auto return_reg = Reg::ArmCore(14);  // R14(LR).
-      WriteEhFrameCIE(is64bit, addr_type, return_reg, opcodes, eh_frame);
+      WriteDebugFrameCIE(is64bit, addr_type, return_reg,
+                         opcodes, format, eh_frame);
       return;
     }
     case kArm64: {
@@ -80,7 +82,8 @@
         }
       }
       auto return_reg = Reg::Arm64Core(30);  // R30(LR).
-      WriteEhFrameCIE(is64bit, addr_type, return_reg, opcodes, eh_frame);
+      WriteDebugFrameCIE(is64bit, addr_type, return_reg,
+                         opcodes, format, eh_frame);
       return;
     }
     case kMips:
@@ -96,7 +99,8 @@
         }
       }
       auto return_reg = Reg::MipsCore(31);  // R31(RA).
-      WriteEhFrameCIE(is64bit, addr_type, return_reg, opcodes, eh_frame);
+      WriteDebugFrameCIE(is64bit, addr_type, return_reg,
+                         opcodes, format, eh_frame);
       return;
     }
     case kX86: {
@@ -122,7 +126,8 @@
         }
       }
       auto return_reg = Reg::X86Core(8);  // R8(EIP).
-      WriteEhFrameCIE(is64bit, addr_type, return_reg, opcodes, eh_frame);
+      WriteDebugFrameCIE(is64bit, addr_type, return_reg,
+                         opcodes, format, eh_frame);
       return;
     }
     case kX86_64: {
@@ -148,7 +153,8 @@
         }
       }
       auto return_reg = Reg::X86_64Core(16);  // R16(RIP).
-      WriteEhFrameCIE(is64bit, addr_type, return_reg, opcodes, eh_frame);
+      WriteDebugFrameCIE(is64bit, addr_type, return_reg,
+                         opcodes, format, eh_frame);
       return;
     }
     case kNone:
@@ -158,58 +164,61 @@
   UNREACHABLE();
 }
 
-void WriteEhFrame(const CompilerDriver* compiler,
-                  const OatWriter* oat_writer,
-                  ExceptionHeaderValueApplication address_type,
-                  std::vector<uint8_t>* eh_frame,
-                  std::vector<uintptr_t>* eh_frame_patches,
-                  std::vector<uint8_t>* eh_frame_hdr,
-                  std::vector<uintptr_t>* eh_frame_hdr_patches) {
+void WriteCFISection(const CompilerDriver* compiler,
+                     const OatWriter* oat_writer,
+                     ExceptionHeaderValueApplication address_type,
+                     CFIFormat format,
+                     std::vector<uint8_t>* debug_frame,
+                     std::vector<uintptr_t>* debug_frame_patches,
+                     std::vector<uint8_t>* eh_frame_hdr,
+                     std::vector<uintptr_t>* eh_frame_hdr_patches) {
   const auto& method_infos = oat_writer->GetMethodDebugInfo();
   const InstructionSet isa = compiler->GetInstructionSet();
 
-  // Write .eh_frame section.
+  // Write .eh_frame/.debug_frame section.
   std::map<uint32_t, size_t> address_to_fde_offset_map;
-  size_t cie_offset = eh_frame->size();
-  WriteEhFrameCIE(isa, address_type, eh_frame);
+  size_t cie_offset = debug_frame->size();
+  WriteDebugFrameCIE(isa, address_type, format, debug_frame);
   for (const OatWriter::DebugInfo& mi : method_infos) {
     if (!mi.deduped_) {  // Only one FDE per unique address.
       const SwapVector<uint8_t>* opcodes = mi.compiled_method_->GetCFIInfo();
       if (opcodes != nullptr) {
-        address_to_fde_offset_map.emplace(mi.low_pc_, eh_frame->size());
-        WriteEhFrameFDE(Is64BitInstructionSet(isa), cie_offset,
-                        mi.low_pc_, mi.high_pc_ - mi.low_pc_,
-                        opcodes, eh_frame, eh_frame_patches);
+        address_to_fde_offset_map.emplace(mi.low_pc_, debug_frame->size());
+        WriteDebugFrameFDE(Is64BitInstructionSet(isa), cie_offset,
+                           mi.low_pc_, mi.high_pc_ - mi.low_pc_,
+                           opcodes, format, debug_frame, debug_frame_patches);
       }
     }
   }
 
-  // Write .eh_frame_hdr section.
-  Writer<> header(eh_frame_hdr);
-  header.PushUint8(1);  // Version.
-  // Encoding of .eh_frame pointer - libunwind does not honor datarel here,
-  // so we have to use pcrel which means relative to the pointer's location.
-  header.PushUint8(DW_EH_PE_pcrel | DW_EH_PE_sdata4);
-  // Encoding of binary search table size.
-  header.PushUint8(DW_EH_PE_udata4);
-  // Encoding of binary search table addresses - libunwind supports only this
-  // specific combination, which means relative to the start of .eh_frame_hdr.
-  header.PushUint8(DW_EH_PE_datarel | DW_EH_PE_sdata4);
-  // .eh_frame pointer - .eh_frame_hdr section is after .eh_frame section
-  const int32_t relative_eh_frame_begin = -static_cast<int32_t>(eh_frame->size());
-  header.PushInt32(relative_eh_frame_begin - 4U);
-  // Binary search table size (number of entries).
-  header.PushUint32(dchecked_integral_cast<uint32_t>(address_to_fde_offset_map.size()));
-  // Binary search table.
-  for (const auto& address_to_fde_offset : address_to_fde_offset_map) {
-    u_int32_t code_address = address_to_fde_offset.first;
-    int32_t fde_address = dchecked_integral_cast<int32_t>(address_to_fde_offset.second);
-    eh_frame_hdr_patches->push_back(header.data()->size());
-    header.PushUint32(code_address);
-    // We know the exact layout (eh_frame is immediately before eh_frame_hdr)
-    // and the data is relative to the start of the eh_frame_hdr,
-    // so patching isn't necessary (in contrast to the code address above).
-    header.PushInt32(relative_eh_frame_begin + fde_address);
+  if (format == DW_EH_FRAME_FORMAT) {
+    // Write .eh_frame_hdr section.
+    Writer<> header(eh_frame_hdr);
+    header.PushUint8(1);  // Version.
+    // Encoding of .eh_frame pointer - libunwind does not honor datarel here,
+    // so we have to use pcrel which means relative to the pointer's location.
+    header.PushUint8(DW_EH_PE_pcrel | DW_EH_PE_sdata4);
+    // Encoding of binary search table size.
+    header.PushUint8(DW_EH_PE_udata4);
+    // Encoding of binary search table addresses - libunwind supports only this
+    // specific combination, which means relative to the start of .eh_frame_hdr.
+    header.PushUint8(DW_EH_PE_datarel | DW_EH_PE_sdata4);
+    // .eh_frame pointer - .eh_frame_hdr section is after .eh_frame section
+    const int32_t relative_eh_frame_begin = -static_cast<int32_t>(debug_frame->size());
+    header.PushInt32(relative_eh_frame_begin - 4U);
+    // Binary search table size (number of entries).
+    header.PushUint32(dchecked_integral_cast<uint32_t>(address_to_fde_offset_map.size()));
+    // Binary search table.
+    for (const auto& address_to_fde_offset : address_to_fde_offset_map) {
+      u_int32_t code_address = address_to_fde_offset.first;
+      int32_t fde_address = dchecked_integral_cast<int32_t>(address_to_fde_offset.second);
+      eh_frame_hdr_patches->push_back(header.data()->size());
+      header.PushUint32(code_address);
+      // We know the exact layout (eh_frame is immediately before eh_frame_hdr)
+      // and the data is relative to the start of the eh_frame_hdr,
+      // so patching isn't necessary (in contrast to the code address above).
+      header.PushInt32(relative_eh_frame_begin + fde_address);
+    }
   }
 }
 
diff --git a/compiler/elf_writer_debug.h b/compiler/elf_writer_debug.h
index 28d0e2c..69f7e0d 100644
--- a/compiler/elf_writer_debug.h
+++ b/compiler/elf_writer_debug.h
@@ -25,13 +25,14 @@
 namespace art {
 namespace dwarf {
 
-void WriteEhFrame(const CompilerDriver* compiler,
-                  const OatWriter* oat_writer,
-                  ExceptionHeaderValueApplication address_type,
-                  std::vector<uint8_t>* eh_frame,
-                  std::vector<uintptr_t>* eh_frame_patches,
-                  std::vector<uint8_t>* eh_frame_hdr,
-                  std::vector<uintptr_t>* eh_frame_hdr_patches);
+void WriteCFISection(const CompilerDriver* compiler,
+                     const OatWriter* oat_writer,
+                     ExceptionHeaderValueApplication address_type,
+                     CFIFormat format,
+                     std::vector<uint8_t>* debug_frame,
+                     std::vector<uintptr_t>* debug_frame_patches,
+                     std::vector<uint8_t>* eh_frame_hdr,
+                     std::vector<uintptr_t>* eh_frame_hdr_patches);
 
 void WriteDebugSections(const CompilerDriver* compiler,
                         const OatWriter* oat_writer,
diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc
index 79f9955..96dd7ca 100644
--- a/compiler/elf_writer_quick.cc
+++ b/compiler/elf_writer_quick.cc
@@ -37,6 +37,14 @@
 
 namespace art {
 
+// .eh_frame and .debug_frame are almost identical.
+// Except for some minor formatting differences, the main difference
+// is that .eh_frame is allocated within the running program because
+// it is used by C++ exception handling (which we do not use so we
+// can choose either).  C++ compilers generally tend to use .eh_frame
+// because if they need it sometimes, they might as well always use it.
+constexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_EH_FRAME_FORMAT;
+
 template <typename ElfTypes>
 bool ElfWriterQuick<ElfTypes>::Create(File* elf_file,
                                       OatWriter* oat_writer,
@@ -161,12 +169,17 @@
   using RawSection = typename ElfBuilder<ElfTypes>::RawSection;
   const auto* text = builder->GetText();
   const bool is64bit = Is64BitInstructionSet(isa);
+  const int pointer_size = GetInstructionSetPointerSize(isa);
   RawSection eh_frame(".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0,
                       is64bit ? Patch<Elf_Addr, uint64_t, kPointerRelativeAddress> :
                                 Patch<Elf_Addr, uint32_t, kPointerRelativeAddress>,
                       text);
   RawSection eh_frame_hdr(".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0,
                           Patch<Elf_Addr, uint32_t, kSectionRelativeAddress>, text);
+  RawSection debug_frame(".debug_frame", SHT_PROGBITS, 0, nullptr, 0, pointer_size, 0,
+                         is64bit ? Patch<Elf_Addr, uint64_t, kAbsoluteAddress> :
+                                   Patch<Elf_Addr, uint32_t, kAbsoluteAddress>,
+                         text);
   RawSection debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0,
                         Patch<Elf_Addr, uint32_t, kAbsoluteAddress>, text);
   RawSection debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
@@ -175,12 +188,25 @@
                         Patch<Elf_Addr, uint32_t, kAbsoluteAddress>, text);
   if (!oat_writer->GetMethodDebugInfo().empty()) {
     if (compiler_driver_->GetCompilerOptions().GetIncludeCFI()) {
-      dwarf::WriteEhFrame(
-          compiler_driver_, oat_writer, dwarf::DW_EH_PE_pcrel,
-          eh_frame.GetBuffer(), eh_frame.GetPatchLocations(),
-          eh_frame_hdr.GetBuffer(), eh_frame_hdr.GetPatchLocations());
-      builder->RegisterSection(&eh_frame);
-      builder->RegisterSection(&eh_frame_hdr);
+      if (kCFIFormat == dwarf::DW_EH_FRAME_FORMAT) {
+        dwarf::WriteCFISection(
+            compiler_driver_, oat_writer,
+            dwarf::DW_EH_PE_pcrel, kCFIFormat,
+            eh_frame.GetBuffer(), eh_frame.GetPatchLocations(),
+            eh_frame_hdr.GetBuffer(), eh_frame_hdr.GetPatchLocations());
+        builder->RegisterSection(&eh_frame);
+        builder->RegisterSection(&eh_frame_hdr);
+      } else {
+        DCHECK(kCFIFormat == dwarf::DW_DEBUG_FRAME_FORMAT);
+        dwarf::WriteCFISection(
+            compiler_driver_, oat_writer,
+            dwarf::DW_EH_PE_absptr, kCFIFormat,
+            debug_frame.GetBuffer(), debug_frame.GetPatchLocations(),
+            nullptr, nullptr);
+        builder->RegisterSection(&debug_frame);
+        *oat_writer->GetAbsolutePatchLocationsFor(".debug_frame") =
+            *debug_frame.GetPatchLocations();
+      }
     }
     if (compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
       // Add methods to .symtab.
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index a5c6f23..c4eaabf 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -539,11 +539,6 @@
 }
 
 static bool RequiresConstructorBarrier(const DexCompilationUnit* cu, const CompilerDriver& driver) {
-  // dex compilation unit is null only when unit testing.
-  if (cu == nullptr) {
-    return false;
-  }
-
   Thread* self = Thread::Current();
   return cu->IsConstructor()
       && driver.RequiresConstructorBarrier(self, cu->GetDexFile(), cu->GetClassDefIndex());
@@ -551,9 +546,12 @@
 
 void HGraphBuilder::BuildReturn(const Instruction& instruction, Primitive::Type type) {
   if (type == Primitive::kPrimVoid) {
-    // Note that we might insert redundant barriers when inlining `super` calls.
-    // TODO: add a data flow analysis to get rid of duplicate barriers.
-    if (RequiresConstructorBarrier(dex_compilation_unit_, *compiler_driver_)) {
+    if (graph_->ShouldGenerateConstructorBarrier()) {
+      // The compilation unit is null during testing.
+      if (dex_compilation_unit_ != nullptr) {
+        DCHECK(RequiresConstructorBarrier(dex_compilation_unit_, *compiler_driver_))
+          << "Inconsistent use of ShouldGenerateConstructorBarrier. Should not generate a barrier.";
+      }
       current_block_->AddInstruction(new (arena_) HMemoryBarrier(kStoreStore));
     }
     current_block_->AddInstruction(new (arena_) HReturnVoid());
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index 0e776b3..4805cee 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -645,23 +645,34 @@
     }
   }
 
+  uint32_t outer_dex_pc = dex_pc;
+  uint32_t outer_environment_size = 0;
+  uint32_t inlining_depth = 0;
+  if (instruction != nullptr) {
+    for (HEnvironment* environment = instruction->GetEnvironment();
+         environment != nullptr;
+         environment = environment->GetParent()) {
+      outer_dex_pc = environment->GetDexPc();
+      outer_environment_size = environment->Size();
+      if (environment != instruction->GetEnvironment()) {
+        inlining_depth++;
+      }
+    }
+  }
+
   // Collect PC infos for the mapping table.
   struct PcInfo pc_info;
-  pc_info.dex_pc = dex_pc;
+  pc_info.dex_pc = outer_dex_pc;
   pc_info.native_pc = GetAssembler()->CodeSize();
   pc_infos_.Add(pc_info);
 
-  uint32_t inlining_depth = 0;
-
   if (instruction == nullptr) {
     // For stack overflow checks.
-    stack_map_stream_.BeginStackMapEntry(dex_pc, pc_info.native_pc, 0, 0, 0, inlining_depth);
+    stack_map_stream_.BeginStackMapEntry(pc_info.dex_pc, pc_info.native_pc, 0, 0, 0, 0);
     stack_map_stream_.EndStackMapEntry();
     return;
   }
   LocationSummary* locations = instruction->GetLocations();
-  HEnvironment* environment = instruction->GetEnvironment();
-  size_t environment_size = instruction->EnvironmentSize();
 
   uint32_t register_mask = locations->GetRegisterMask();
   if (locations->OnlyCallsOnSlowPath()) {
@@ -674,23 +685,32 @@
   }
   // The register mask must be a subset of callee-save registers.
   DCHECK_EQ(register_mask & core_callee_save_mask_, register_mask);
-  stack_map_stream_.BeginStackMapEntry(dex_pc,
+  stack_map_stream_.BeginStackMapEntry(pc_info.dex_pc,
                                        pc_info.native_pc,
                                        register_mask,
                                        locations->GetStackMask(),
-                                       environment_size,
+                                       outer_environment_size,
                                        inlining_depth);
-  if (environment != nullptr) {
-    // TODO: Handle parent environment.
-    DCHECK(environment->GetParent() == nullptr);
-    DCHECK_EQ(environment->GetDexPc(), dex_pc);
+
+  EmitEnvironment(instruction->GetEnvironment(), slow_path);
+  stack_map_stream_.EndStackMapEntry();
+}
+
+void CodeGenerator::EmitEnvironment(HEnvironment* environment, SlowPathCode* slow_path) {
+  if (environment == nullptr) return;
+
+  if (environment->GetParent() != nullptr) {
+    // We emit the parent environment first.
+    EmitEnvironment(environment->GetParent(), slow_path);
+    stack_map_stream_.BeginInlineInfoEntry(
+        environment->GetMethodIdx(), environment->GetDexPc(), environment->Size());
   }
 
   // Walk over the environment, and record the location of dex registers.
-  for (size_t i = 0; i < environment_size; ++i) {
+  for (size_t i = 0, environment_size = environment->Size(); i < environment_size; ++i) {
     HInstruction* current = environment->GetInstructionAt(i);
     if (current == nullptr) {
-      stack_map_stream_.AddDexRegisterEntry(i, DexRegisterLocation::Kind::kNone, 0);
+      stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kNone, 0);
       continue;
     }
 
@@ -701,41 +721,44 @@
         if (current->IsLongConstant()) {
           int64_t value = current->AsLongConstant()->GetValue();
           stack_map_stream_.AddDexRegisterEntry(
-              i, DexRegisterLocation::Kind::kConstant, Low32Bits(value));
+              DexRegisterLocation::Kind::kConstant, Low32Bits(value));
           stack_map_stream_.AddDexRegisterEntry(
-              ++i, DexRegisterLocation::Kind::kConstant, High32Bits(value));
+              DexRegisterLocation::Kind::kConstant, High32Bits(value));
+          ++i;
           DCHECK_LT(i, environment_size);
         } else if (current->IsDoubleConstant()) {
           int64_t value = bit_cast<int64_t, double>(current->AsDoubleConstant()->GetValue());
           stack_map_stream_.AddDexRegisterEntry(
-              i, DexRegisterLocation::Kind::kConstant, Low32Bits(value));
+              DexRegisterLocation::Kind::kConstant, Low32Bits(value));
           stack_map_stream_.AddDexRegisterEntry(
-              ++i, DexRegisterLocation::Kind::kConstant, High32Bits(value));
+              DexRegisterLocation::Kind::kConstant, High32Bits(value));
+          ++i;
           DCHECK_LT(i, environment_size);
         } else if (current->IsIntConstant()) {
           int32_t value = current->AsIntConstant()->GetValue();
-          stack_map_stream_.AddDexRegisterEntry(i, DexRegisterLocation::Kind::kConstant, value);
+          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kConstant, value);
         } else if (current->IsNullConstant()) {
-          stack_map_stream_.AddDexRegisterEntry(i, DexRegisterLocation::Kind::kConstant, 0);
+          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kConstant, 0);
         } else {
           DCHECK(current->IsFloatConstant()) << current->DebugName();
           int32_t value = bit_cast<int32_t, float>(current->AsFloatConstant()->GetValue());
-          stack_map_stream_.AddDexRegisterEntry(i, DexRegisterLocation::Kind::kConstant, value);
+          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kConstant, value);
         }
         break;
       }
 
       case Location::kStackSlot: {
         stack_map_stream_.AddDexRegisterEntry(
-            i, DexRegisterLocation::Kind::kInStack, location.GetStackIndex());
+            DexRegisterLocation::Kind::kInStack, location.GetStackIndex());
         break;
       }
 
       case Location::kDoubleStackSlot: {
         stack_map_stream_.AddDexRegisterEntry(
-            i, DexRegisterLocation::Kind::kInStack, location.GetStackIndex());
+            DexRegisterLocation::Kind::kInStack, location.GetStackIndex());
         stack_map_stream_.AddDexRegisterEntry(
-            ++i, DexRegisterLocation::Kind::kInStack, location.GetHighStackIndex(kVRegSize));
+            DexRegisterLocation::Kind::kInStack, location.GetHighStackIndex(kVRegSize));
+        ++i;
         DCHECK_LT(i, environment_size);
         break;
       }
@@ -744,16 +767,18 @@
         int id = location.reg();
         if (slow_path != nullptr && slow_path->IsCoreRegisterSaved(id)) {
           uint32_t offset = slow_path->GetStackOffsetOfCoreRegister(id);
-          stack_map_stream_.AddDexRegisterEntry(i, DexRegisterLocation::Kind::kInStack, offset);
+          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInStack, offset);
           if (current->GetType() == Primitive::kPrimLong) {
             stack_map_stream_.AddDexRegisterEntry(
-                ++i, DexRegisterLocation::Kind::kInStack, offset + kVRegSize);
+                DexRegisterLocation::Kind::kInStack, offset + kVRegSize);
+            ++i;
             DCHECK_LT(i, environment_size);
           }
         } else {
-          stack_map_stream_.AddDexRegisterEntry(i, DexRegisterLocation::Kind::kInRegister, id);
+          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInRegister, id);
           if (current->GetType() == Primitive::kPrimLong) {
-            stack_map_stream_.AddDexRegisterEntry(++i, DexRegisterLocation::Kind::kInRegister, id);
+            stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInRegister, id);
+            ++i;
             DCHECK_LT(i, environment_size);
           }
         }
@@ -764,17 +789,18 @@
         int id = location.reg();
         if (slow_path != nullptr && slow_path->IsFpuRegisterSaved(id)) {
           uint32_t offset = slow_path->GetStackOffsetOfFpuRegister(id);
-          stack_map_stream_.AddDexRegisterEntry(i, DexRegisterLocation::Kind::kInStack, offset);
+          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInStack, offset);
           if (current->GetType() == Primitive::kPrimDouble) {
             stack_map_stream_.AddDexRegisterEntry(
-                ++i, DexRegisterLocation::Kind::kInStack, offset + kVRegSize);
+                DexRegisterLocation::Kind::kInStack, offset + kVRegSize);
+            ++i;
             DCHECK_LT(i, environment_size);
           }
         } else {
-          stack_map_stream_.AddDexRegisterEntry(i, DexRegisterLocation::Kind::kInFpuRegister, id);
+          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInFpuRegister, id);
           if (current->GetType() == Primitive::kPrimDouble) {
-            stack_map_stream_.AddDexRegisterEntry(
-                ++i, DexRegisterLocation::Kind::kInFpuRegister, id);
+            stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInFpuRegister, id);
+            ++i;
             DCHECK_LT(i, environment_size);
           }
         }
@@ -786,16 +812,17 @@
         int high = location.high();
         if (slow_path != nullptr && slow_path->IsFpuRegisterSaved(low)) {
           uint32_t offset = slow_path->GetStackOffsetOfFpuRegister(low);
-          stack_map_stream_.AddDexRegisterEntry(i, DexRegisterLocation::Kind::kInStack, offset);
+          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInStack, offset);
         } else {
-          stack_map_stream_.AddDexRegisterEntry(i, DexRegisterLocation::Kind::kInFpuRegister, low);
+          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInFpuRegister, low);
         }
         if (slow_path != nullptr && slow_path->IsFpuRegisterSaved(high)) {
           uint32_t offset = slow_path->GetStackOffsetOfFpuRegister(high);
-          stack_map_stream_.AddDexRegisterEntry(++i, DexRegisterLocation::Kind::kInStack, offset);
+          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInStack, offset);
+          ++i;
         } else {
-          stack_map_stream_.AddDexRegisterEntry(
-              ++i, DexRegisterLocation::Kind::kInFpuRegister, high);
+          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInFpuRegister, high);
+          ++i;
         }
         DCHECK_LT(i, environment_size);
         break;
@@ -806,23 +833,23 @@
         int high = location.high();
         if (slow_path != nullptr && slow_path->IsCoreRegisterSaved(low)) {
           uint32_t offset = slow_path->GetStackOffsetOfCoreRegister(low);
-          stack_map_stream_.AddDexRegisterEntry(i, DexRegisterLocation::Kind::kInStack, offset);
+          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInStack, offset);
         } else {
-          stack_map_stream_.AddDexRegisterEntry(i, DexRegisterLocation::Kind::kInRegister, low);
+          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInRegister, low);
         }
         if (slow_path != nullptr && slow_path->IsCoreRegisterSaved(high)) {
           uint32_t offset = slow_path->GetStackOffsetOfCoreRegister(high);
-          stack_map_stream_.AddDexRegisterEntry(++i, DexRegisterLocation::Kind::kInStack, offset);
+          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInStack, offset);
         } else {
-          stack_map_stream_.AddDexRegisterEntry(
-              ++i, DexRegisterLocation::Kind::kInRegister, high);
+          stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kInRegister, high);
         }
+        ++i;
         DCHECK_LT(i, environment_size);
         break;
       }
 
       case Location::kInvalid: {
-        stack_map_stream_.AddDexRegisterEntry(i, DexRegisterLocation::Kind::kNone, 0);
+        stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kNone, 0);
         break;
       }
 
@@ -830,7 +857,10 @@
         LOG(FATAL) << "Unexpected kind " << location.GetKind();
     }
   }
-  stack_map_stream_.EndStackMapEntry();
+
+  if (environment->GetParent() != nullptr) {
+    stack_map_stream_.EndInlineInfoEntry();
+  }
 }
 
 bool CodeGenerator::CanMoveNullCheckToUser(HNullCheck* null_check) {
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index fcfedab..740beab 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -82,8 +82,8 @@
 
   virtual void EmitNativeCode(CodeGenerator* codegen) = 0;
 
-  void SaveLiveRegisters(CodeGenerator* codegen, LocationSummary* locations);
-  void RestoreLiveRegisters(CodeGenerator* codegen, LocationSummary* locations);
+  virtual void SaveLiveRegisters(CodeGenerator* codegen, LocationSummary* locations);
+  virtual void RestoreLiveRegisters(CodeGenerator* codegen, LocationSummary* locations);
   void RecordPcInfo(CodeGenerator* codegen, HInstruction* instruction, uint32_t dex_pc);
 
   bool IsCoreRegisterSaved(int reg) const {
@@ -102,11 +102,13 @@
     return saved_fpu_stack_offsets_[reg];
   }
 
- private:
+ protected:
   static constexpr size_t kMaximumNumberOfExpectedRegisters = 32;
   static constexpr uint32_t kRegisterNotSaved = -1;
   uint32_t saved_core_stack_offsets_[kMaximumNumberOfExpectedRegisters];
   uint32_t saved_fpu_stack_offsets_[kMaximumNumberOfExpectedRegisters];
+
+ private:
   DISALLOW_COPY_AND_ASSIGN(SlowPathCode);
 };
 
@@ -441,6 +443,7 @@
   size_t GetStackOffsetOfSavedRegister(size_t index);
   void CompileInternal(CodeAllocator* allocator, bool is_baseline);
   void BlockIfInRegister(Location location, bool is_out = false) const;
+  void EmitEnvironment(HEnvironment* environment, SlowPathCode* slow_path);
 
   HGraph* const graph_;
   const CompilerOptions& compiler_options_;
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 93d0e5b..1c76630 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"
@@ -390,7 +391,7 @@
       location_builder_(graph, this),
       instruction_visitor_(graph, this),
       move_resolver_(graph->GetArena(), this),
-      assembler_(true),
+      assembler_(false /* can_relocate_branches */),
       isa_features_(isa_features) {
   // Save the PC register to mimic Quick.
   AddAllocatedRegister(Location::RegisterLocation(PC));
@@ -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>();
@@ -2880,7 +3037,8 @@
 }
 
 void InstructionCodeGeneratorARM::HandleFieldSet(HInstruction* instruction,
-                                                 const FieldInfo& field_info) {
+                                                 const FieldInfo& field_info,
+                                                 bool value_can_be_null) {
   DCHECK(instruction->IsInstanceFieldSet() || instruction->IsStaticFieldSet());
 
   LocationSummary* locations = instruction->GetLocations();
@@ -2969,7 +3127,8 @@
   if (CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1))) {
     Register temp = locations->GetTemp(0).AsRegister<Register>();
     Register card = locations->GetTemp(1).AsRegister<Register>();
-    codegen_->MarkGCCard(temp, card, base, value.AsRegister<Register>());
+    codegen_->MarkGCCard(
+        temp, card, base, value.AsRegister<Register>(), value_can_be_null);
   }
 
   if (is_volatile) {
@@ -3096,7 +3255,7 @@
 }
 
 void InstructionCodeGeneratorARM::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
-  HandleFieldSet(instruction, instruction->GetFieldInfo());
+  HandleFieldSet(instruction, instruction->GetFieldInfo(), instruction->GetValueCanBeNull());
 }
 
 void LocationsBuilderARM::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
@@ -3120,7 +3279,7 @@
 }
 
 void InstructionCodeGeneratorARM::VisitStaticFieldSet(HStaticFieldSet* instruction) {
-  HandleFieldSet(instruction, instruction->GetFieldInfo());
+  HandleFieldSet(instruction, instruction->GetFieldInfo(), instruction->GetValueCanBeNull());
 }
 
 void LocationsBuilderARM::VisitNullCheck(HNullCheck* instruction) {
@@ -3390,7 +3549,7 @@
           DCHECK_EQ(value_type, Primitive::kPrimNot);
           Register temp = locations->GetTemp(0).AsRegister<Register>();
           Register card = locations->GetTemp(1).AsRegister<Register>();
-          codegen_->MarkGCCard(temp, card, obj, value);
+          codegen_->MarkGCCard(temp, card, obj, value, instruction->GetValueCanBeNull());
         }
       } else {
         DCHECK_EQ(value_type, Primitive::kPrimNot);
@@ -3495,13 +3654,21 @@
   __ b(slow_path->GetEntryLabel(), CS);
 }
 
-void CodeGeneratorARM::MarkGCCard(Register temp, Register card, Register object, Register value) {
+void CodeGeneratorARM::MarkGCCard(Register temp,
+                                  Register card,
+                                  Register object,
+                                  Register value,
+                                  bool can_be_null) {
   Label is_null;
-  __ CompareAndBranchIfZero(value, &is_null);
+  if (can_be_null) {
+    __ CompareAndBranchIfZero(value, &is_null);
+  }
   __ LoadFromOffset(kLoadWord, card, TR, Thread::CardTableOffset<kArmWordSize>().Int32Value());
   __ Lsr(temp, object, gc::accounting::CardTable::kCardShift);
   __ strb(card, Address(card, temp));
-  __ Bind(&is_null);
+  if (can_be_null) {
+    __ Bind(&is_null);
+  }
 }
 
 void LocationsBuilderARM::VisitTemporary(HTemporary* temp) {
diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h
index 1a498e1..071bbee 100644
--- a/compiler/optimizing/code_generator_arm.h
+++ b/compiler/optimizing/code_generator_arm.h
@@ -181,7 +181,9 @@
                                HInstruction* instruction);
   void GenerateWideAtomicLoad(Register addr, uint32_t offset,
                               Register out_lo, Register out_hi);
-  void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info);
+  void HandleFieldSet(HInstruction* instruction,
+                      const FieldInfo& field_info,
+                      bool value_can_be_null);
   void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
   void GenerateImplicitNullCheck(HNullCheck* instruction);
   void GenerateExplicitNullCheck(HNullCheck* instruction);
@@ -189,6 +191,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_;
@@ -270,7 +276,7 @@
       int32_t offset, HInstruction* instruction, uint32_t dex_pc, SlowPathCode* slow_path);
 
   // Emit a write barrier.
-  void MarkGCCard(Register temp, Register card, Register object, Register value);
+  void MarkGCCard(Register temp, Register card, Register object, Register value, bool can_be_null);
 
   Label* GetLabelOf(HBasicBlock* block) const {
     return CommonGetLabelOf<Label>(block_labels_.GetRawStorage(), block);
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 0a0902b..b6d99ab 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"
@@ -64,6 +65,7 @@
 using helpers::WRegisterFrom;
 using helpers::XRegisterFrom;
 using helpers::ARM64EncodableConstantOrRegister;
+using helpers::ArtVixlRegCodeCoherentForRegSet;
 
 static constexpr size_t kHeapRefSize = sizeof(mirror::HeapReference<mirror::Object>);
 static constexpr int kCurrentMethodStackOffset = 0;
@@ -105,6 +107,88 @@
 #define __ down_cast<CodeGeneratorARM64*>(codegen)->GetVIXLAssembler()->
 #define QUICK_ENTRY_POINT(x) QUICK_ENTRYPOINT_OFFSET(kArm64WordSize, x).Int32Value()
 
+// Calculate memory accessing operand for save/restore live registers.
+static void SaveRestoreLiveRegistersHelper(CodeGenerator* codegen,
+                                           RegisterSet* register_set,
+                                           int64_t spill_offset,
+                                           bool is_save) {
+  DCHECK(ArtVixlRegCodeCoherentForRegSet(register_set->GetCoreRegisters(),
+                                         codegen->GetNumberOfCoreRegisters(),
+                                         register_set->GetFloatingPointRegisters(),
+                                         codegen->GetNumberOfFloatingPointRegisters()));
+
+  CPURegList core_list = CPURegList(CPURegister::kRegister, kXRegSize,
+      register_set->GetCoreRegisters() & (~callee_saved_core_registers.list()));
+  CPURegList fp_list = CPURegList(CPURegister::kFPRegister, kDRegSize,
+      register_set->GetFloatingPointRegisters() & (~callee_saved_fp_registers.list()));
+
+  MacroAssembler* masm = down_cast<CodeGeneratorARM64*>(codegen)->GetVIXLAssembler();
+  UseScratchRegisterScope temps(masm);
+
+  Register base = masm->StackPointer();
+  int64_t core_spill_size = core_list.TotalSizeInBytes();
+  int64_t fp_spill_size = fp_list.TotalSizeInBytes();
+  int64_t reg_size = kXRegSizeInBytes;
+  int64_t max_ls_pair_offset = spill_offset + core_spill_size + fp_spill_size - 2 * reg_size;
+  uint32_t ls_access_size = WhichPowerOf2(reg_size);
+  if (((core_list.Count() > 1) || (fp_list.Count() > 1)) &&
+      !masm->IsImmLSPair(max_ls_pair_offset, ls_access_size)) {
+    // If the offset does not fit in the instruction's immediate field, use an alternate register
+    // to compute the base address(float point registers spill base address).
+    Register new_base = temps.AcquireSameSizeAs(base);
+    __ Add(new_base, base, Operand(spill_offset + core_spill_size));
+    base = new_base;
+    spill_offset = -core_spill_size;
+    int64_t new_max_ls_pair_offset = fp_spill_size - 2 * reg_size;
+    DCHECK(masm->IsImmLSPair(spill_offset, ls_access_size));
+    DCHECK(masm->IsImmLSPair(new_max_ls_pair_offset, ls_access_size));
+  }
+
+  if (is_save) {
+    __ StoreCPURegList(core_list, MemOperand(base, spill_offset));
+    __ StoreCPURegList(fp_list, MemOperand(base, spill_offset + core_spill_size));
+  } else {
+    __ LoadCPURegList(core_list, MemOperand(base, spill_offset));
+    __ LoadCPURegList(fp_list, MemOperand(base, spill_offset + core_spill_size));
+  }
+}
+
+void SlowPathCodeARM64::SaveLiveRegisters(CodeGenerator* codegen, LocationSummary* locations) {
+  RegisterSet* register_set = locations->GetLiveRegisters();
+  size_t stack_offset = codegen->GetFirstRegisterSlotInSlowPath();
+  for (size_t i = 0, e = codegen->GetNumberOfCoreRegisters(); i < e; ++i) {
+    if (!codegen->IsCoreCalleeSaveRegister(i) && register_set->ContainsCoreRegister(i)) {
+      // If the register holds an object, update the stack mask.
+      if (locations->RegisterContainsObject(i)) {
+        locations->SetStackBit(stack_offset / kVRegSize);
+      }
+      DCHECK_LT(stack_offset, codegen->GetFrameSize() - codegen->FrameEntrySpillSize());
+      DCHECK_LT(i, kMaximumNumberOfExpectedRegisters);
+      saved_core_stack_offsets_[i] = stack_offset;
+      stack_offset += kXRegSizeInBytes;
+    }
+  }
+
+  for (size_t i = 0, e = codegen->GetNumberOfFloatingPointRegisters(); i < e; ++i) {
+    if (!codegen->IsFloatingPointCalleeSaveRegister(i) &&
+        register_set->ContainsFloatingPointRegister(i)) {
+      DCHECK_LT(stack_offset, codegen->GetFrameSize() - codegen->FrameEntrySpillSize());
+      DCHECK_LT(i, kMaximumNumberOfExpectedRegisters);
+      saved_fpu_stack_offsets_[i] = stack_offset;
+      stack_offset += kDRegSizeInBytes;
+    }
+  }
+
+  SaveRestoreLiveRegistersHelper(codegen, register_set,
+                                 codegen->GetFirstRegisterSlotInSlowPath(), true /* is_save */);
+}
+
+void SlowPathCodeARM64::RestoreLiveRegisters(CodeGenerator* codegen, LocationSummary* locations) {
+  RegisterSet* register_set = locations->GetLiveRegisters();
+  SaveRestoreLiveRegistersHelper(codegen, register_set,
+                                 codegen->GetFirstRegisterSlotInSlowPath(), false /* is_save */);
+}
+
 class BoundsCheckSlowPathARM64 : public SlowPathCodeARM64 {
  public:
   BoundsCheckSlowPathARM64(HBoundsCheck* instruction,
@@ -529,6 +613,19 @@
   GetAssembler()->cfi().DefCFAOffset(GetFrameSize());
 }
 
+vixl::CPURegList CodeGeneratorARM64::GetFramePreservedCoreRegisters() const {
+  DCHECK(ArtVixlRegCodeCoherentForRegSet(core_spill_mask_, GetNumberOfCoreRegisters(), 0, 0));
+  return vixl::CPURegList(vixl::CPURegister::kRegister, vixl::kXRegSize,
+                          core_spill_mask_);
+}
+
+vixl::CPURegList CodeGeneratorARM64::GetFramePreservedFPRegisters() const {
+  DCHECK(ArtVixlRegCodeCoherentForRegSet(0, 0, fpu_spill_mask_,
+                                         GetNumberOfFloatingPointRegisters()));
+  return vixl::CPURegList(vixl::CPURegister::kFPRegister, vixl::kDRegSize,
+                          fpu_spill_mask_);
+}
+
 void CodeGeneratorARM64::Bind(HBasicBlock* block) {
   __ Bind(GetLabelOf(block));
 }
@@ -604,16 +701,20 @@
   return Location::NoLocation();
 }
 
-void CodeGeneratorARM64::MarkGCCard(Register object, Register value) {
+void CodeGeneratorARM64::MarkGCCard(Register object, Register value, bool value_can_be_null) {
   UseScratchRegisterScope temps(GetVIXLAssembler());
   Register card = temps.AcquireX();
   Register temp = temps.AcquireW();   // Index within the CardTable - 32bit.
   vixl::Label done;
-  __ Cbz(value, &done);
+  if (value_can_be_null) {
+    __ Cbz(value, &done);
+  }
   __ Ldr(card, MemOperand(tr, Thread::CardTableOffset<kArm64WordSize>().Int32Value()));
   __ Lsr(temp, object, gc::accounting::CardTable::kCardShift);
   __ Strb(card, MemOperand(card, temp.X()));
-  __ Bind(&done);
+  if (value_can_be_null) {
+    __ Bind(&done);
+  }
 }
 
 void CodeGeneratorARM64::SetupBlockedRegisters(bool is_baseline) const {
@@ -1168,7 +1269,8 @@
 }
 
 void InstructionCodeGeneratorARM64::HandleFieldSet(HInstruction* instruction,
-                                                   const FieldInfo& field_info) {
+                                                   const FieldInfo& field_info,
+                                                   bool value_can_be_null) {
   DCHECK(instruction->IsInstanceFieldSet() || instruction->IsStaticFieldSet());
   BlockPoolsScope block_pools(GetVIXLAssembler());
 
@@ -1194,7 +1296,7 @@
   }
 
   if (CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1))) {
-    codegen_->MarkGCCard(obj, Register(value));
+    codegen_->MarkGCCard(obj, Register(value), value_can_be_null);
   }
 }
 
@@ -1420,7 +1522,7 @@
       codegen_->MaybeRecordImplicitNullCheck(instruction);
     }
     if (CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue())) {
-      codegen_->MarkGCCard(obj, value.W());
+      codegen_->MarkGCCard(obj, value.W(), instruction->GetValueCanBeNull());
     }
   }
 }
@@ -1603,6 +1705,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);
@@ -1610,7 +1858,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;
 
@@ -1631,7 +1879,7 @@
   switch (type) {
     case Primitive::kPrimInt:
     case Primitive::kPrimLong:
-      __ Sdiv(OutputRegister(div), InputRegisterAt(div, 0), InputRegisterAt(div, 1));
+      GenerateDivRemIntegral(div);
       break;
 
     case Primitive::kPrimFloat:
@@ -1846,7 +2094,7 @@
 }
 
 void InstructionCodeGeneratorARM64::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
-  HandleFieldSet(instruction, instruction->GetFieldInfo());
+  HandleFieldSet(instruction, instruction->GetFieldInfo(), instruction->GetValueCanBeNull());
 }
 
 void LocationsBuilderARM64::VisitInstanceOf(HInstanceOf* instruction) {
@@ -2454,7 +2702,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;
 
@@ -2479,14 +2727,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;
     }
 
@@ -2596,7 +2837,7 @@
 }
 
 void InstructionCodeGeneratorARM64::VisitStaticFieldSet(HStaticFieldSet* instruction) {
-  HandleFieldSet(instruction, instruction->GetFieldInfo());
+  HandleFieldSet(instruction, instruction->GetFieldInfo(), instruction->GetValueCanBeNull());
 }
 
 void LocationsBuilderARM64::VisitSuspendCheck(HSuspendCheck* instruction) {
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index 8aeea54..b56ca10 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -70,6 +70,9 @@
   vixl::Label* GetEntryLabel() { return &entry_label_; }
   vixl::Label* GetExitLabel() { return &exit_label_; }
 
+  void SaveLiveRegisters(CodeGenerator* codegen, LocationSummary* locations) OVERRIDE;
+  void RestoreLiveRegisters(CodeGenerator* codegen, LocationSummary* locations) OVERRIDE;
+
  private:
   vixl::Label entry_label_;
   vixl::Label exit_label_;
@@ -154,7 +157,9 @@
   void GenerateMemoryBarrier(MemBarrierKind kind);
   void GenerateSuspendCheck(HSuspendCheck* instruction, HBasicBlock* successor);
   void HandleBinaryOp(HBinaryOperation* instr);
-  void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info);
+  void HandleFieldSet(HInstruction* instruction,
+                      const FieldInfo& field_info,
+                      bool value_can_be_null);
   void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
   void HandleShift(HBinaryOperation* instr);
   void GenerateImplicitNullCheck(HNullCheck* instruction);
@@ -163,6 +168,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_;
@@ -227,15 +237,8 @@
   void GenerateFrameEntry() OVERRIDE;
   void GenerateFrameExit() OVERRIDE;
 
-  vixl::CPURegList GetFramePreservedCoreRegisters() const {
-    return vixl::CPURegList(vixl::CPURegister::kRegister, vixl::kXRegSize,
-                            core_spill_mask_);
-  }
-
-  vixl::CPURegList GetFramePreservedFPRegisters() const {
-    return vixl::CPURegList(vixl::CPURegister::kFPRegister, vixl::kDRegSize,
-                            fpu_spill_mask_);
-  }
+  vixl::CPURegList GetFramePreservedCoreRegisters() const;
+  vixl::CPURegList GetFramePreservedFPRegisters() const;
 
   void Bind(HBasicBlock* block) OVERRIDE;
 
@@ -266,7 +269,7 @@
   vixl::MacroAssembler* GetVIXLAssembler() { return GetAssembler()->vixl_masm_; }
 
   // Emit a write barrier.
-  void MarkGCCard(vixl::Register object, vixl::Register value);
+  void MarkGCCard(vixl::Register object, vixl::Register value, bool value_can_be_null);
 
   // Register allocation.
 
@@ -277,10 +280,10 @@
 
   Location GetStackLocation(HLoadLocal* load) const OVERRIDE;
 
-  size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id);
-  size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id);
-  size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id);
-  size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id);
+  size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE;
+  size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id) OVERRIDE;
+  size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) OVERRIDE;
+  size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) OVERRIDE;
 
   // The number of registers that can be allocated. The register allocator may
   // decide to reserve and not use a few of them.
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 0212da1..a6f01da 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -3227,16 +3227,24 @@
   DCHECK(!IsLeafMethod());
 }
 
-void CodeGeneratorX86::MarkGCCard(Register temp, Register card, Register object, Register value) {
+void CodeGeneratorX86::MarkGCCard(Register temp,
+                                  Register card,
+                                  Register object,
+                                  Register value,
+                                  bool value_can_be_null) {
   Label is_null;
-  __ testl(value, value);
-  __ j(kEqual, &is_null);
+  if (value_can_be_null) {
+    __ testl(value, value);
+    __ j(kEqual, &is_null);
+  }
   __ fs()->movl(card, Address::Absolute(Thread::CardTableOffset<kX86WordSize>().Int32Value()));
   __ movl(temp, object);
   __ shrl(temp, Immediate(gc::accounting::CardTable::kCardShift));
   __ movb(Address(temp, card, TIMES_1, 0),
           X86ManagedRegister::FromCpuRegister(card).AsByteRegister());
-  __ Bind(&is_null);
+  if (value_can_be_null) {
+    __ Bind(&is_null);
+  }
 }
 
 void LocationsBuilderX86::HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info) {
@@ -3381,7 +3389,8 @@
 }
 
 void InstructionCodeGeneratorX86::HandleFieldSet(HInstruction* instruction,
-                                                 const FieldInfo& field_info) {
+                                                 const FieldInfo& field_info,
+                                                 bool value_can_be_null) {
   DCHECK(instruction->IsInstanceFieldSet() || instruction->IsStaticFieldSet());
 
   LocationSummary* locations = instruction->GetLocations();
@@ -3454,7 +3463,7 @@
   if (CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1))) {
     Register temp = locations->GetTemp(0).AsRegister<Register>();
     Register card = locations->GetTemp(1).AsRegister<Register>();
-    codegen_->MarkGCCard(temp, card, base, value.AsRegister<Register>());
+    codegen_->MarkGCCard(temp, card, base, value.AsRegister<Register>(), value_can_be_null);
   }
 
   if (is_volatile) {
@@ -3475,7 +3484,7 @@
 }
 
 void InstructionCodeGeneratorX86::VisitStaticFieldSet(HStaticFieldSet* instruction) {
-  HandleFieldSet(instruction, instruction->GetFieldInfo());
+  HandleFieldSet(instruction, instruction->GetFieldInfo(), instruction->GetValueCanBeNull());
 }
 
 void LocationsBuilderX86::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
@@ -3483,7 +3492,7 @@
 }
 
 void InstructionCodeGeneratorX86::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
-  HandleFieldSet(instruction, instruction->GetFieldInfo());
+  HandleFieldSet(instruction, instruction->GetFieldInfo(), instruction->GetValueCanBeNull());
 }
 
 void LocationsBuilderX86::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
@@ -3817,7 +3826,8 @@
         if (needs_write_barrier) {
           Register temp = locations->GetTemp(0).AsRegister<Register>();
           Register card = locations->GetTemp(1).AsRegister<Register>();
-          codegen_->MarkGCCard(temp, card, obj, value.AsRegister<Register>());
+          codegen_->MarkGCCard(
+              temp, card, obj, value.AsRegister<Register>(), instruction->GetValueCanBeNull());
         }
       } else {
         DCHECK_EQ(value_type, Primitive::kPrimNot);
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 5a5a37b..28766d8 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -170,7 +170,9 @@
   void GenerateShrLong(const Location& loc, int shift);
   void GenerateUShrLong(const Location& loc, int shift);
   void GenerateMemoryBarrier(MemBarrierKind kind);
-  void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info);
+  void HandleFieldSet(HInstruction* instruction,
+                      const FieldInfo& field_info,
+                      bool value_can_be_null);
   void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
   // Push value to FPU stack. `is_fp` specifies whether the value is floating point or not.
   // `is_wide` specifies whether it is long/double or not.
@@ -260,7 +262,11 @@
   void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Register temp);
 
   // Emit a write barrier.
-  void MarkGCCard(Register temp, Register card, Register object, Register value);
+  void MarkGCCard(Register temp,
+                  Register card,
+                  Register object,
+                  Register value,
+                  bool value_can_be_null);
 
   void LoadCurrentMethod(Register reg);
 
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 63d6846..f49c26d 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -3249,7 +3249,8 @@
 }
 
 void InstructionCodeGeneratorX86_64::HandleFieldSet(HInstruction* instruction,
-                                                    const FieldInfo& field_info) {
+                                                    const FieldInfo& field_info,
+                                                    bool value_can_be_null) {
   DCHECK(instruction->IsInstanceFieldSet() || instruction->IsStaticFieldSet());
 
   LocationSummary* locations = instruction->GetLocations();
@@ -3329,7 +3330,7 @@
   if (CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1))) {
     CpuRegister temp = locations->GetTemp(0).AsRegister<CpuRegister>();
     CpuRegister card = locations->GetTemp(1).AsRegister<CpuRegister>();
-    codegen_->MarkGCCard(temp, card, base, value.AsRegister<CpuRegister>());
+    codegen_->MarkGCCard(temp, card, base, value.AsRegister<CpuRegister>(), value_can_be_null);
   }
 
   if (is_volatile) {
@@ -3342,7 +3343,7 @@
 }
 
 void InstructionCodeGeneratorX86_64::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
-  HandleFieldSet(instruction, instruction->GetFieldInfo());
+  HandleFieldSet(instruction, instruction->GetFieldInfo(), instruction->GetValueCanBeNull());
 }
 
 void LocationsBuilderX86_64::VisitInstanceFieldGet(HInstanceFieldGet* instruction) {
@@ -3366,7 +3367,7 @@
 }
 
 void InstructionCodeGeneratorX86_64::VisitStaticFieldSet(HStaticFieldSet* instruction) {
-  HandleFieldSet(instruction, instruction->GetFieldInfo());
+  HandleFieldSet(instruction, instruction->GetFieldInfo(), instruction->GetValueCanBeNull());
 }
 
 void LocationsBuilderX86_64::VisitNullCheck(HNullCheck* instruction) {
@@ -3671,7 +3672,8 @@
           DCHECK_EQ(value_type, Primitive::kPrimNot);
           CpuRegister temp = locations->GetTemp(0).AsRegister<CpuRegister>();
           CpuRegister card = locations->GetTemp(1).AsRegister<CpuRegister>();
-          codegen_->MarkGCCard(temp, card, obj, value.AsRegister<CpuRegister>());
+          codegen_->MarkGCCard(
+              temp, card, obj, value.AsRegister<CpuRegister>(), instruction->GetValueCanBeNull());
         }
       } else {
         DCHECK_EQ(value_type, Primitive::kPrimNot);
@@ -3816,16 +3818,21 @@
 void CodeGeneratorX86_64::MarkGCCard(CpuRegister temp,
                                      CpuRegister card,
                                      CpuRegister object,
-                                     CpuRegister value) {
+                                     CpuRegister value,
+                                     bool value_can_be_null) {
   Label is_null;
-  __ testl(value, value);
-  __ j(kEqual, &is_null);
+  if (value_can_be_null) {
+    __ testl(value, value);
+    __ j(kEqual, &is_null);
+  }
   __ gs()->movq(card, Address::Absolute(
       Thread::CardTableOffset<kX86_64WordSize>().Int32Value(), true));
   __ movq(temp, object);
   __ shrq(temp, Immediate(gc::accounting::CardTable::kCardShift));
   __ movb(Address(temp, card, TIMES_1, 0),  card);
-  __ Bind(&is_null);
+  if (value_can_be_null) {
+    __ Bind(&is_null);
+  }
 }
 
 void LocationsBuilderX86_64::VisitTemporary(HTemporary* temp) {
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index 480ea6b..d7bd525 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -174,7 +174,9 @@
   void GenerateDivRemIntegral(HBinaryOperation* instruction);
   void HandleShift(HBinaryOperation* operation);
   void GenerateMemoryBarrier(MemBarrierKind kind);
-  void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info);
+  void HandleFieldSet(HInstruction* instruction,
+                      const FieldInfo& field_info,
+                      bool value_can_be_null);
   void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
   void GenerateImplicitNullCheck(HNullCheck* instruction);
   void GenerateExplicitNullCheck(HNullCheck* instruction);
@@ -248,7 +250,11 @@
   }
 
   // Emit a write barrier.
-  void MarkGCCard(CpuRegister temp, CpuRegister card, CpuRegister object, CpuRegister value);
+  void MarkGCCard(CpuRegister temp,
+                  CpuRegister card,
+                  CpuRegister object,
+                  CpuRegister value,
+                  bool value_can_be_null);
 
   // Helper method to move a value between two locations.
   void Move(Location destination, Location source);
diff --git a/compiler/optimizing/common_arm64.h b/compiler/optimizing/common_arm64.h
index 53f1f3c..246fff9 100644
--- a/compiler/optimizing/common_arm64.h
+++ b/compiler/optimizing/common_arm64.h
@@ -218,6 +218,28 @@
   return Location::RequiresRegister();
 }
 
+// Check if registers in art register set have the same register code in vixl. If the register
+// codes are same, we can initialize vixl register list simply by the register masks. Currently,
+// only SP/WSP and ZXR/WZR codes are different between art and vixl.
+// Note: This function is only used for debug checks.
+static inline bool ArtVixlRegCodeCoherentForRegSet(uint32_t art_core_registers,
+                                                   size_t num_core,
+                                                   uint32_t art_fpu_registers,
+                                                   size_t num_fpu) {
+  // The register masks won't work if the number of register is larger than 32.
+  DCHECK_GE(sizeof(art_core_registers) * 8, num_core);
+  DCHECK_GE(sizeof(art_fpu_registers) * 8, num_fpu);
+  for (size_t art_reg_code = 0;  art_reg_code < num_core; ++art_reg_code) {
+    if (RegisterSet::Contains(art_core_registers, art_reg_code)) {
+      if (art_reg_code != static_cast<size_t>(VIXLRegCodeFromART(art_reg_code))) {
+        return false;
+      }
+    }
+  }
+  // There is no register code translation for float registers.
+  return true;
+}
+
 }  // namespace helpers
 }  // namespace arm64
 }  // namespace art
diff --git a/compiler/optimizing/dead_code_elimination.cc b/compiler/optimizing/dead_code_elimination.cc
index 6fbe75e..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 {
 
@@ -132,6 +133,7 @@
 
 void HDeadCodeElimination::Run() {
   RemoveDeadBlocks();
+  SsaRedundantPhiElimination(graph_).Run();
   RemoveDeadInstructions();
 }
 
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index 739fb76..14a8b6f 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -42,13 +42,18 @@
 
 class StringList {
  public:
+  enum Format {
+    kArrayBrackets,
+    kSetBrackets,
+  };
+
   // Create an empty list
-  StringList() : is_empty_(true) {}
+  explicit StringList(Format format = kArrayBrackets) : format_(format), 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() {
+  explicit StringList(T* first_entry, Format format = kArrayBrackets) : StringList(format) {
     for (T* current = first_entry; current != nullptr; current = current->GetNext()) {
       current->Dump(NewEntryStream());
     }
@@ -58,12 +63,13 @@
     if (is_empty_) {
       is_empty_ = false;
     } else {
-      sstream_ << " ";
+      sstream_ << ",";
     }
     return sstream_;
   }
 
  private:
+  Format format_;
   bool is_empty_;
   std::ostringstream sstream_;
 
@@ -71,7 +77,13 @@
 };
 
 std::ostream& operator<<(std::ostream& os, const StringList& list) {
-  return os << "[ " << list.sstream_.str() << " ]";
+  switch (list.format_) {
+    case StringList::kArrayBrackets: return os << "[" << list.sstream_.str() << "]";
+    case StringList::kSetBrackets:   return os << "{" << list.sstream_.str() << "}";
+    default:
+      LOG(FATAL) << "Invalid StringList format";
+      UNREACHABLE();
+  }
 }
 
 /**
@@ -301,7 +313,8 @@
       StartAttributeStream("liveness") << instruction->GetLifetimePosition();
       if (instruction->HasLiveInterval()) {
         LiveInterval* interval = instruction->GetLiveInterval();
-        StartAttributeStream("ranges") << StringList(interval->GetFirstRange());
+        StartAttributeStream("ranges")
+            << StringList(interval->GetFirstRange(), StringList::kSetBrackets);
         StartAttributeStream("uses") << StringList(interval->GetFirstUse());
         StartAttributeStream("env_uses") << StringList(interval->GetFirstEnvironmentUse());
         StartAttributeStream("is_fixed") << interval->IsFixed();
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index afffc7a..56d868f 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -169,10 +169,30 @@
     resolved_method->GetAccessFlags(),
     nullptr);
 
+  bool requires_ctor_barrier = false;
+
+  if (dex_compilation_unit.IsConstructor()) {
+    // If it's a super invocation and we already generate a barrier there's no need
+    // to generate another one.
+    // We identify super calls by looking at the "this" pointer. If its value is the
+    // same as the local "this" pointer then we must have a super invocation.
+    bool is_super_invocation = invoke_instruction->InputAt(0)->IsParameterValue()
+        && invoke_instruction->InputAt(0)->AsParameterValue()->IsThis();
+    if (is_super_invocation && graph_->ShouldGenerateConstructorBarrier()) {
+      requires_ctor_barrier = false;
+    } else {
+      Thread* self = Thread::Current();
+      requires_ctor_barrier = compiler_driver_->RequiresConstructorBarrier(self,
+          dex_compilation_unit.GetDexFile(),
+          dex_compilation_unit.GetClassDefIndex());
+    }
+  }
+
   HGraph* callee_graph = new (graph_->GetArena()) HGraph(
       graph_->GetArena(),
       caller_dex_file,
       method_index,
+      requires_ctor_barrier,
       graph_->IsDebuggable(),
       graph_->GetCurrentInstructionId());
 
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index 46fad17..fcb3471 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -45,6 +45,8 @@
   void VisitEqual(HEqual* equal) OVERRIDE;
   void VisitNotEqual(HNotEqual* equal) OVERRIDE;
   void VisitBooleanNot(HBooleanNot* bool_not) OVERRIDE;
+  void VisitInstanceFieldSet(HInstanceFieldSet* equal) OVERRIDE;
+  void VisitStaticFieldSet(HStaticFieldSet* equal) OVERRIDE;
   void VisitArraySet(HArraySet* equal) OVERRIDE;
   void VisitTypeConversion(HTypeConversion* instruction) OVERRIDE;
   void VisitNullCheck(HNullCheck* instruction) OVERRIDE;
@@ -63,6 +65,7 @@
   void VisitUShr(HUShr* instruction) OVERRIDE;
   void VisitXor(HXor* instruction) OVERRIDE;
   void VisitInstanceOf(HInstanceOf* instruction) OVERRIDE;
+  bool IsDominatedByInputNullCheck(HInstruction* instr);
 
   OptimizingCompilerStats* stats_;
   bool simplification_occurred_ = false;
@@ -78,6 +81,8 @@
 }
 
 void InstructionSimplifierVisitor::Run() {
+  // Iterate in reverse post order to open up more simplifications to users
+  // of instructions that got simplified.
   for (HReversePostOrderIterator it(*GetGraph()); !it.Done();) {
     // The simplification of an instruction to another instruction may yield
     // possibilities for other simplifications. So although we perform a reverse
@@ -170,9 +175,20 @@
   }
 }
 
+bool InstructionSimplifierVisitor::IsDominatedByInputNullCheck(HInstruction* instr) {
+  HInstruction* input = instr->InputAt(0);
+  for (HUseIterator<HInstruction*> it(input->GetUses()); !it.Done(); it.Advance()) {
+    HInstruction* use = it.Current()->GetUser();
+    if (use->IsNullCheck() && use->StrictlyDominates(instr)) {
+      return true;
+    }
+  }
+  return false;
+}
+
 void InstructionSimplifierVisitor::VisitCheckCast(HCheckCast* check_cast) {
   HLoadClass* load_class = check_cast->InputAt(1)->AsLoadClass();
-  if (!check_cast->InputAt(0)->CanBeNull()) {
+  if (!check_cast->InputAt(0)->CanBeNull() || IsDominatedByInputNullCheck(check_cast)) {
     check_cast->ClearMustDoNullCheck();
   }
 
@@ -194,11 +210,25 @@
 }
 
 void InstructionSimplifierVisitor::VisitInstanceOf(HInstanceOf* instruction) {
-  if (!instruction->InputAt(0)->CanBeNull()) {
+  if (!instruction->InputAt(0)->CanBeNull() || IsDominatedByInputNullCheck(instruction)) {
     instruction->ClearMustDoNullCheck();
   }
 }
 
+void InstructionSimplifierVisitor::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
+  if ((instruction->GetValue()->GetType() == Primitive::kPrimNot)
+      && !instruction->GetValue()->CanBeNull()) {
+    instruction->ClearValueCanBeNull();
+  }
+}
+
+void InstructionSimplifierVisitor::VisitStaticFieldSet(HStaticFieldSet* instruction) {
+  if ((instruction->GetValue()->GetType() == Primitive::kPrimNot)
+      && !instruction->GetValue()->CanBeNull()) {
+    instruction->ClearValueCanBeNull();
+  }
+}
+
 void InstructionSimplifierVisitor::VisitSuspendCheck(HSuspendCheck* check) {
   HBasicBlock* block = check->GetBlock();
   // Currently always keep the suspend check at entry.
@@ -294,6 +324,10 @@
       instruction->ClearNeedsTypeCheck();
     }
   }
+
+  if (!value->CanBeNull()) {
+    instruction->ClearValueCanBeNull();
+  }
 }
 
 void InstructionSimplifierVisitor::VisitTypeConversion(HTypeConversion* instruction) {
diff --git a/compiler/optimizing/intrinsics_arm.cc b/compiler/optimizing/intrinsics_arm.cc
index dccfe9a..e785bf9 100644
--- a/compiler/optimizing/intrinsics_arm.cc
+++ b/compiler/optimizing/intrinsics_arm.cc
@@ -657,7 +657,8 @@
   if (type == Primitive::kPrimNot) {
     Register temp = locations->GetTemp(0).AsRegister<Register>();
     Register card = locations->GetTemp(1).AsRegister<Register>();
-    codegen->MarkGCCard(temp, card, base, value);
+    bool value_can_be_null = true;  // TODO: Worth finding out this information?
+    codegen->MarkGCCard(temp, card, base, value, value_can_be_null);
   }
 }
 
@@ -725,7 +726,8 @@
   if (type == Primitive::kPrimNot) {
     // Mark card for object assuming new value is stored. Worst case we will mark an unchanged
     // object and scan the receiver at the next GC for nothing.
-    codegen->MarkGCCard(tmp_ptr, tmp_lo, base, value_lo);
+    bool value_can_be_null = true;  // TODO: Worth finding out this information?
+    codegen->MarkGCCard(tmp_ptr, tmp_lo, base, value_lo, value_can_be_null);
   }
 
   // Prevent reordering with prior memory operations.
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index 2c4fab0..53497b6 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -797,7 +797,8 @@
   }
 
   if (type == Primitive::kPrimNot) {
-    codegen->MarkGCCard(base, value);
+    bool value_can_be_null = true;  // TODO: Worth finding out this information?
+    codegen->MarkGCCard(base, value, value_can_be_null);
   }
 }
 
@@ -856,7 +857,8 @@
   // This needs to be before the temp registers, as MarkGCCard also uses VIXL temps.
   if (type == Primitive::kPrimNot) {
     // Mark card for object assuming new value is stored.
-    codegen->MarkGCCard(base, value);
+    bool value_can_be_null = true;  // TODO: Worth finding out this information?
+    codegen->MarkGCCard(base, value, value_can_be_null);
   }
 
   UseScratchRegisterScope temps(masm);
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index 28b7a07..d2ca42d 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -1503,10 +1503,12 @@
   }
 
   if (type == Primitive::kPrimNot) {
+    bool value_can_be_null = true;  // TODO: Worth finding out this information?
     codegen->MarkGCCard(locations->GetTemp(0).AsRegister<Register>(),
                         locations->GetTemp(1).AsRegister<Register>(),
                         base,
-                        value_loc.AsRegister<Register>());
+                        value_loc.AsRegister<Register>(),
+                        value_can_be_null);
   }
 }
 
@@ -1602,10 +1604,12 @@
     Register value = locations->InAt(4).AsRegister<Register>();
     if (type == Primitive::kPrimNot) {
       // Mark card for object assuming new value is stored.
+      bool value_can_be_null = true;  // TODO: Worth finding out this information?
       codegen->MarkGCCard(locations->GetTemp(0).AsRegister<Register>(),
                           locations->GetTemp(1).AsRegister<Register>(),
                           base,
-                          value);
+                          value,
+                          value_can_be_null);
     }
 
     __ LockCmpxchgl(Address(base, offset, TIMES_1, 0), value);
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index 0efa714..2ccecfe 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -1374,10 +1374,12 @@
   }
 
   if (type == Primitive::kPrimNot) {
+    bool value_can_be_null = true;  // TODO: Worth finding out this information?
     codegen->MarkGCCard(locations->GetTemp(0).AsRegister<CpuRegister>(),
                         locations->GetTemp(1).AsRegister<CpuRegister>(),
                         base,
-                        value);
+                        value,
+                        value_can_be_null);
   }
 }
 
@@ -1459,10 +1461,12 @@
     // Integer or object.
     if (type == Primitive::kPrimNot) {
       // Mark card for object assuming new value is stored.
+      bool value_can_be_null = true;  // TODO: Worth finding out this information?
       codegen->MarkGCCard(locations->GetTemp(0).AsRegister<CpuRegister>(),
                           locations->GetTemp(1).AsRegister<CpuRegister>(),
                           base,
-                          value);
+                          value,
+                          value_can_be_null);
     }
 
     __ LockCmpxchgl(Address(base, offset, TIMES_1, 0), value);
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index cb2e5cc..680fb47 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -120,6 +120,7 @@
   HGraph(ArenaAllocator* arena,
          const DexFile& dex_file,
          uint32_t method_idx,
+         bool should_generate_constructor_barrier,
          bool debuggable = false,
          int start_instruction_id = 0)
       : arena_(arena),
@@ -137,6 +138,7 @@
         current_instruction_id_(start_instruction_id),
         dex_file_(dex_file),
         method_idx_(method_idx),
+        should_generate_constructor_barrier_(should_generate_constructor_barrier),
         cached_null_constant_(nullptr),
         cached_int_constants_(std::less<int32_t>(), arena->Adapter()),
         cached_float_constants_(std::less<int32_t>(), arena->Adapter()),
@@ -247,6 +249,10 @@
     has_bounds_checks_ = value;
   }
 
+  bool ShouldGenerateConstructorBarrier() const {
+    return should_generate_constructor_barrier_;
+  }
+
   bool IsDebuggable() const { return debuggable_; }
 
   // Returns a constant of the given type and value. If it does not exist
@@ -359,6 +365,8 @@
   // The method index in the dex file.
   const uint32_t method_idx_;
 
+  const bool should_generate_constructor_barrier_;
+
   // Cached constants.
   HNullConstant* cached_null_constant_;
   ArenaSafeMap<int32_t, HIntConstant*> cached_int_constants_;
@@ -2902,6 +2910,8 @@
 
   bool CanBeNull() const OVERRIDE { return !is_this_; }
 
+  bool IsThis() const { return is_this_; }
+
   DECLARE_INSTRUCTION(ParameterValue);
 
  private:
@@ -3163,7 +3173,8 @@
                     MemberOffset field_offset,
                     bool is_volatile)
       : HTemplateInstruction(SideEffects::ChangesSomething()),
-        field_info_(field_offset, field_type, is_volatile) {
+        field_info_(field_offset, field_type, is_volatile),
+        value_can_be_null_(true) {
     SetRawInputAt(0, object);
     SetRawInputAt(1, value);
   }
@@ -3177,11 +3188,14 @@
   Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
   bool IsVolatile() const { return field_info_.IsVolatile(); }
   HInstruction* GetValue() const { return InputAt(1); }
+  bool GetValueCanBeNull() const { return value_can_be_null_; }
+  void ClearValueCanBeNull() { value_can_be_null_ = false; }
 
   DECLARE_INSTRUCTION(InstanceFieldSet);
 
  private:
   const FieldInfo field_info_;
+  bool value_can_be_null_;
 
   DISALLOW_COPY_AND_ASSIGN(HInstanceFieldSet);
 };
@@ -3230,7 +3244,8 @@
       : HTemplateInstruction(SideEffects::ChangesSomething()),
         dex_pc_(dex_pc),
         expected_component_type_(expected_component_type),
-        needs_type_check_(value->GetType() == Primitive::kPrimNot) {
+        needs_type_check_(value->GetType() == Primitive::kPrimNot),
+        value_can_be_null_(true) {
     SetRawInputAt(0, array);
     SetRawInputAt(1, index);
     SetRawInputAt(2, value);
@@ -3252,6 +3267,11 @@
     needs_type_check_ = false;
   }
 
+  void ClearValueCanBeNull() {
+    value_can_be_null_ = false;
+  }
+
+  bool GetValueCanBeNull() const { return value_can_be_null_; }
   bool NeedsTypeCheck() const { return needs_type_check_; }
 
   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
@@ -3277,6 +3297,7 @@
   const uint32_t dex_pc_;
   const Primitive::Type expected_component_type_;
   bool needs_type_check_;
+  bool value_can_be_null_;
 
   DISALLOW_COPY_AND_ASSIGN(HArraySet);
 };
@@ -3577,7 +3598,8 @@
                   MemberOffset field_offset,
                   bool is_volatile)
       : HTemplateInstruction(SideEffects::ChangesSomething()),
-        field_info_(field_offset, field_type, is_volatile) {
+        field_info_(field_offset, field_type, is_volatile),
+        value_can_be_null_(true) {
     SetRawInputAt(0, cls);
     SetRawInputAt(1, value);
   }
@@ -3588,11 +3610,14 @@
   bool IsVolatile() const { return field_info_.IsVolatile(); }
 
   HInstruction* GetValue() const { return InputAt(1); }
+  bool GetValueCanBeNull() const { return value_can_be_null_; }
+  void ClearValueCanBeNull() { value_can_be_null_ = false; }
 
   DECLARE_INSTRUCTION(StaticFieldSet);
 
  private:
   const FieldInfo field_info_;
+  bool value_can_be_null_;
 
   DISALLOW_COPY_AND_ASSIGN(HStaticFieldSet);
 };
@@ -3895,7 +3920,9 @@
       }
       for (size_t i = 0, e = moves_.Size(); i < e; ++i) {
         DCHECK(!destination.OverlapsWith(moves_.Get(i).GetDestination()))
-            << "Overlapped destination for two moves in a parallel move.";
+            << "Overlapped destination for two moves in a parallel move: "
+            << moves_.Get(i).GetSource() << " ==> " << moves_.Get(i).GetDestination() << " and "
+            << source << " ==> " << destination;
       }
     }
     moves_.Add(MoveOperands(source, destination, type, instruction));
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 8bb5d8e..be9a424 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -512,9 +512,14 @@
     class_def_idx, method_idx, access_flags,
     compiler_driver->GetVerifiedMethod(&dex_file, method_idx));
 
+  bool requires_barrier = dex_compilation_unit.IsConstructor()
+      && compiler_driver->RequiresConstructorBarrier(Thread::Current(),
+                                                     dex_compilation_unit.GetDexFile(),
+                                                     dex_compilation_unit.GetClassDefIndex());
   ArenaAllocator arena(Runtime::Current()->GetArenaPool());
   HGraph* graph = new (&arena) HGraph(
-      &arena, dex_file, method_idx, compiler_driver->GetCompilerOptions().GetDebuggable());
+      &arena, dex_file, method_idx, requires_barrier,
+      compiler_driver->GetCompilerOptions().GetDebuggable());
 
   // For testing purposes, we put a special marker on method names that should be compiled
   // with this compiler. This makes sure we're not regressing.
diff --git a/compiler/optimizing/optimizing_unit_test.h b/compiler/optimizing/optimizing_unit_test.h
index 4f8ec65..1fe9346 100644
--- a/compiler/optimizing/optimizing_unit_test.h
+++ b/compiler/optimizing/optimizing_unit_test.h
@@ -74,7 +74,7 @@
 
 inline HGraph* CreateGraph(ArenaAllocator* allocator) {
   return new (allocator) HGraph(
-      allocator, *reinterpret_cast<DexFile*>(allocator->Alloc(sizeof(DexFile))), -1);
+      allocator, *reinterpret_cast<DexFile*>(allocator->Alloc(sizeof(DexFile))), -1, false);
 }
 
 // Create a control-flow graph from Dex instructions.
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_builder.cc b/compiler/optimizing/ssa_builder.cc
index 59a2852..aac5211 100644
--- a/compiler/optimizing/ssa_builder.cc
+++ b/compiler/optimizing/ssa_builder.cc
@@ -504,7 +504,7 @@
     // typed and the value in a dex register will not be used for both floating point and
     // non-floating point operations. So the only reason an instruction would want a floating
     // point equivalent is for an unused phi that will be removed by the dead phi elimination phase.
-    DCHECK(user->IsPhi());
+    DCHECK(user->IsPhi()) << "is actually " << user->DebugName() << " (" << user->GetId() << ")";
     return value;
   }
 }
diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h
index bd55e9f..4b19c5b 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/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc
index 8344fc3..89035a3 100644
--- a/compiler/optimizing/stack_map_stream.cc
+++ b/compiler/optimizing/stack_map_stream.cc
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #include "stack_map_stream.h"
 
 namespace art {
@@ -52,6 +51,7 @@
   dex_pc_max_ = std::max(dex_pc_max_, dex_pc);
   native_pc_offset_max_ = std::max(native_pc_offset_max_, native_pc_offset);
   register_mask_max_ = std::max(register_mask_max_, register_mask);
+  current_dex_register_ = 0;
 }
 
 void StackMapStream::EndStackMapEntry() {
@@ -60,11 +60,7 @@
   current_entry_ = StackMapEntry();
 }
 
-void StackMapStream::AddDexRegisterEntry(uint16_t dex_register,
-                                         DexRegisterLocation::Kind kind,
-                                         int32_t value) {
-  DCHECK_LT(dex_register, current_entry_.num_dex_registers);
-
+void StackMapStream::AddDexRegisterEntry(DexRegisterLocation::Kind kind, int32_t value) {
   if (kind != DexRegisterLocation::Kind::kNone) {
     // Ensure we only use non-compressed location kind at this stage.
     DCHECK(DexRegisterLocation::IsShortLocationKind(kind))
@@ -87,18 +83,47 @@
       location_catalog_entries_indices_.Insert(std::make_pair(location, index));
     }
 
-    current_entry_.live_dex_registers_mask->SetBit(dex_register);
-    current_entry_.dex_register_map_hash +=
-      (1 << (dex_register % (sizeof(current_entry_.dex_register_map_hash) * kBitsPerByte)));
-    current_entry_.dex_register_map_hash += static_cast<uint32_t>(value);
-    current_entry_.dex_register_map_hash += static_cast<uint32_t>(kind);
+    if (in_inline_frame_) {
+      // TODO: Support sharing DexRegisterMap across InlineInfo.
+      DCHECK_LT(current_dex_register_, current_inline_info_.num_dex_registers);
+      current_inline_info_.live_dex_registers_mask->SetBit(current_dex_register_);
+    } else {
+      DCHECK_LT(current_dex_register_, current_entry_.num_dex_registers);
+      current_entry_.live_dex_registers_mask->SetBit(current_dex_register_);
+      current_entry_.dex_register_map_hash += (1 <<
+          (current_dex_register_ % (sizeof(current_entry_.dex_register_map_hash) * kBitsPerByte)));
+      current_entry_.dex_register_map_hash += static_cast<uint32_t>(value);
+      current_entry_.dex_register_map_hash += static_cast<uint32_t>(kind);
+    }
   }
+  current_dex_register_++;
 }
 
-void StackMapStream::AddInlineInfoEntry(uint32_t method_index) {
-  InlineInfoEntry entry;
-  entry.method_index = method_index;
-  inline_infos_.Add(entry);
+void StackMapStream::BeginInlineInfoEntry(uint32_t method_index,
+                                          uint32_t dex_pc,
+                                          uint32_t num_dex_registers) {
+  DCHECK(!in_inline_frame_);
+  in_inline_frame_ = true;
+  current_inline_info_.method_index = method_index;
+  current_inline_info_.dex_pc = dex_pc;
+  current_inline_info_.num_dex_registers = num_dex_registers;
+  current_inline_info_.dex_register_locations_start_index = dex_register_locations_.Size();
+  if (num_dex_registers != 0) {
+    current_inline_info_.live_dex_registers_mask =
+        new (allocator_) ArenaBitVector(allocator_, num_dex_registers, true);
+  } else {
+    current_inline_info_.live_dex_registers_mask = nullptr;
+  }
+  current_dex_register_ = 0;
+}
+
+void StackMapStream::EndInlineInfoEntry() {
+  DCHECK(in_inline_frame_);
+  DCHECK_EQ(current_dex_register_, current_inline_info_.num_dex_registers)
+      << "Inline information contains less registers than expected";
+  in_inline_frame_ = false;
+  inline_infos_.Add(current_inline_info_);
+  current_inline_info_ = InlineInfoEntry();
 }
 
 size_t StackMapStream::PrepareForFillIn() {
@@ -142,17 +167,18 @@
   return size;
 }
 
-size_t StackMapStream::ComputeDexRegisterMapSize(const StackMapEntry& entry) const {
+size_t StackMapStream::ComputeDexRegisterMapSize(uint32_t num_dex_registers,
+                                                 const BitVector& live_dex_registers_mask) const {
   // Size of the map in bytes.
   size_t size = DexRegisterMap::kFixedSize;
   // Add the live bit mask for the Dex register liveness.
-  size += DexRegisterMap::GetLiveBitMaskSize(entry.num_dex_registers);
+  size += DexRegisterMap::GetLiveBitMaskSize(num_dex_registers);
   // Compute the size of the set of live Dex register entries.
   size_t number_of_live_dex_registers = 0;
   for (size_t dex_register_number = 0;
-       dex_register_number < entry.num_dex_registers;
+       dex_register_number < num_dex_registers;
        ++dex_register_number) {
-    if (entry.live_dex_registers_mask->IsBitSet(dex_register_number)) {
+    if (live_dex_registers_mask.IsBitSet(dex_register_number)) {
       ++number_of_live_dex_registers;
     }
   }
@@ -167,11 +193,18 @@
 
 size_t StackMapStream::ComputeDexRegisterMapsSize() const {
   size_t size = 0;
+  size_t inline_info_index = 0;
   for (size_t i = 0; i < stack_maps_.Size(); ++i) {
     StackMapEntry entry = stack_maps_.Get(i);
     if (entry.same_dex_register_map_as_ == kNoSameDexMapFound) {
+      size += ComputeDexRegisterMapSize(entry.num_dex_registers, *entry.live_dex_registers_mask);
+    } else {
       // Entries with the same dex map will have the same offset.
-      size += ComputeDexRegisterMapSize(entry);
+    }
+    for (size_t j = 0; j < entry.inlining_depth; ++j) {
+      InlineInfoEntry inline_entry = inline_infos_.Get(inline_info_index++);
+      size += ComputeDexRegisterMapSize(inline_entry.num_dex_registers,
+                                        *inline_entry.live_dex_registers_mask);
     }
   }
   return size;
@@ -247,34 +280,19 @@
                      .GetDexRegisterMapOffset(code_info));
       } else {
         // New dex registers maps should be added to the stack map.
-        MemoryRegion register_region =
-            dex_register_locations_region.Subregion(
-                next_dex_register_map_offset,
-                ComputeDexRegisterMapSize(entry));
+        MemoryRegion register_region = dex_register_locations_region.Subregion(
+            next_dex_register_map_offset,
+            ComputeDexRegisterMapSize(entry.num_dex_registers, *entry.live_dex_registers_mask));
         next_dex_register_map_offset += register_region.size();
         DexRegisterMap dex_register_map(register_region);
         stack_map.SetDexRegisterMapOffset(
           code_info, register_region.start() - dex_register_locations_region.start());
 
-        // Set the live bit mask.
-        dex_register_map.SetLiveBitMask(entry.num_dex_registers, *entry.live_dex_registers_mask);
-
-        // Set the dex register location mapping data.
-        for (size_t dex_register_number = 0, index_in_dex_register_locations = 0;
-             dex_register_number < entry.num_dex_registers;
-             ++dex_register_number) {
-          if (entry.live_dex_registers_mask->IsBitSet(dex_register_number)) {
-            size_t location_catalog_entry_index =
-                dex_register_locations_.Get(entry.dex_register_locations_start_index
-                                            + index_in_dex_register_locations);
-            dex_register_map.SetLocationCatalogEntryIndex(
-                index_in_dex_register_locations,
-                location_catalog_entry_index,
-                entry.num_dex_registers,
-                location_catalog_entries_.Size());
-            ++index_in_dex_register_locations;
-          }
-        }
+        // Set the dex register location.
+        FillInDexRegisterMap(dex_register_map,
+                             entry.num_dex_registers,
+                             *entry.live_dex_registers_mask,
+                             entry.dex_register_locations_start_index);
       }
     }
 
@@ -291,9 +309,29 @@
           code_info, inline_region.start() - dex_register_locations_region.start());
 
       inline_info.SetDepth(entry.inlining_depth);
-      for (size_t j = 0; j < entry.inlining_depth; ++j) {
-        InlineInfoEntry inline_entry = inline_infos_.Get(j + entry.inline_infos_start_index);
-        inline_info.SetMethodReferenceIndexAtDepth(j, inline_entry.method_index);
+      for (size_t depth = 0; depth < entry.inlining_depth; ++depth) {
+        InlineInfoEntry inline_entry = inline_infos_.Get(depth + entry.inline_infos_start_index);
+        inline_info.SetMethodIndexAtDepth(depth, inline_entry.method_index);
+        inline_info.SetDexPcAtDepth(depth, inline_entry.dex_pc);
+        if (inline_entry.num_dex_registers == 0) {
+          // No dex map available.
+          inline_info.SetDexRegisterMapOffsetAtDepth(depth, StackMap::kNoDexRegisterMap);
+          DCHECK(inline_entry.live_dex_registers_mask == nullptr);
+        } else {
+          MemoryRegion register_region = dex_register_locations_region.Subregion(
+              next_dex_register_map_offset,
+              ComputeDexRegisterMapSize(inline_entry.num_dex_registers,
+                                        *inline_entry.live_dex_registers_mask));
+          next_dex_register_map_offset += register_region.size();
+          DexRegisterMap dex_register_map(register_region);
+          inline_info.SetDexRegisterMapOffsetAtDepth(
+            depth, register_region.start() - dex_register_locations_region.start());
+
+          FillInDexRegisterMap(dex_register_map,
+                               inline_entry.num_dex_registers,
+                               *inline_entry.live_dex_registers_mask,
+                               inline_entry.dex_register_locations_start_index);
+        }
       }
     } else {
       if (inline_info_size_ != 0) {
@@ -303,6 +341,28 @@
   }
 }
 
+void StackMapStream::FillInDexRegisterMap(DexRegisterMap dex_register_map,
+                                          uint32_t num_dex_registers,
+                                          const BitVector& live_dex_registers_mask,
+                                          uint32_t start_index_in_dex_register_locations) const {
+  dex_register_map.SetLiveBitMask(num_dex_registers, live_dex_registers_mask);
+  // Set the dex register location mapping data.
+  for (size_t dex_register_number = 0, index_in_dex_register_locations = 0;
+       dex_register_number < num_dex_registers;
+       ++dex_register_number) {
+    if (live_dex_registers_mask.IsBitSet(dex_register_number)) {
+      size_t location_catalog_entry_index = dex_register_locations_.Get(
+          start_index_in_dex_register_locations + index_in_dex_register_locations);
+      dex_register_map.SetLocationCatalogEntryIndex(
+          index_in_dex_register_locations,
+          location_catalog_entry_index,
+          num_dex_registers,
+          location_catalog_entries_.Size());
+      ++index_in_dex_register_locations;
+    }
+  }
+}
+
 size_t StackMapStream::FindEntryWithTheSameDexMap() {
   size_t current_entry_index = stack_maps_.Size();
   auto entries_it = dex_map_hash_to_stack_map_indices_.find(current_entry_.dex_register_map_hash);
diff --git a/compiler/optimizing/stack_map_stream.h b/compiler/optimizing/stack_map_stream.h
index 0c626be..4c03f9f 100644
--- a/compiler/optimizing/stack_map_stream.h
+++ b/compiler/optimizing/stack_map_stream.h
@@ -72,6 +72,7 @@
         number_of_stack_maps_with_inline_info_(0),
         dex_map_hash_to_stack_map_indices_(std::less<uint32_t>(), allocator->Adapter()),
         current_entry_(),
+        current_inline_info_(),
         stack_mask_size_(0),
         inline_info_size_(0),
         dex_register_maps_size_(0),
@@ -81,7 +82,9 @@
         stack_maps_start_(0),
         dex_register_maps_start_(0),
         inline_infos_start_(0),
-        needed_size_(0) {}
+        needed_size_(0),
+        current_dex_register_(0),
+        in_inline_frame_(false) {}
 
   // See runtime/stack_map.h to know what these fields contain.
   struct StackMapEntry {
@@ -99,7 +102,11 @@
   };
 
   struct InlineInfoEntry {
+    uint32_t dex_pc;
     uint32_t method_index;
+    uint32_t num_dex_registers;
+    BitVector* live_dex_registers_mask;
+    size_t dex_register_locations_start_index;
   };
 
   void BeginStackMapEntry(uint32_t dex_pc,
@@ -110,11 +117,12 @@
                           uint8_t inlining_depth);
   void EndStackMapEntry();
 
-  void AddDexRegisterEntry(uint16_t dex_register,
-                           DexRegisterLocation::Kind kind,
-                           int32_t value);
+  void AddDexRegisterEntry(DexRegisterLocation::Kind kind, int32_t value);
 
-  void AddInlineInfoEntry(uint32_t method_index);
+  void BeginInlineInfoEntry(uint32_t method_index,
+                            uint32_t dex_pc,
+                            uint32_t num_dex_registers);
+  void EndInlineInfoEntry();
 
   // Prepares the stream to fill in a memory region. Must be called before FillIn.
   // Returns the size (in bytes) needed to store this stream.
@@ -123,7 +131,8 @@
 
  private:
   size_t ComputeDexRegisterLocationCatalogSize() const;
-  size_t ComputeDexRegisterMapSize(const StackMapEntry& entry) const;
+  size_t ComputeDexRegisterMapSize(uint32_t num_dex_registers,
+                                   const BitVector& live_dex_registers_mask) const;
   size_t ComputeDexRegisterMapsSize() const;
   size_t ComputeInlineInfoSize() const;
 
@@ -131,6 +140,10 @@
   // or kNoSameDexMapFound if no such entry exists.
   size_t FindEntryWithTheSameDexMap();
   bool HaveTheSameDexMaps(const StackMapEntry& a, const StackMapEntry& b) const;
+  void FillInDexRegisterMap(DexRegisterMap dex_register_map,
+                            uint32_t num_dex_registers,
+                            const BitVector& live_dex_registers_mask,
+                            uint32_t start_index_in_dex_register_locations) const;
 
   ArenaAllocator* allocator_;
   GrowableArray<StackMapEntry> stack_maps_;
@@ -155,6 +168,7 @@
   ArenaSafeMap<uint32_t, GrowableArray<uint32_t>> dex_map_hash_to_stack_map_indices_;
 
   StackMapEntry current_entry_;
+  InlineInfoEntry current_inline_info_;
   size_t stack_mask_size_;
   size_t inline_info_size_;
   size_t dex_register_maps_size_;
@@ -165,6 +179,8 @@
   size_t dex_register_maps_start_;
   size_t inline_infos_start_;
   size_t needed_size_;
+  uint32_t current_dex_register_;
+  bool in_inline_frame_;
 
   static constexpr uint32_t kNoSameDexMapFound = -1;
 
diff --git a/compiler/optimizing/stack_map_test.cc b/compiler/optimizing/stack_map_test.cc
index 3291a77..e04fa98 100644
--- a/compiler/optimizing/stack_map_test.cc
+++ b/compiler/optimizing/stack_map_test.cc
@@ -41,8 +41,8 @@
   ArenaBitVector sp_mask(&arena, 0, false);
   size_t number_of_dex_registers = 2;
   stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
-  stream.AddDexRegisterEntry(0, Kind::kInStack, 0);         // Short location.
-  stream.AddDexRegisterEntry(1, Kind::kConstant, -2);       // Short location.
+  stream.AddDexRegisterEntry(Kind::kInStack, 0);         // Short location.
+  stream.AddDexRegisterEntry(Kind::kConstant, -2);       // Short location.
   stream.EndStackMapEntry();
 
   size_t size = stream.PrepareForFillIn();
@@ -124,19 +124,22 @@
   sp_mask1.SetBit(2);
   sp_mask1.SetBit(4);
   size_t number_of_dex_registers = 2;
+  size_t number_of_dex_registers_in_inline_info = 0;
   stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask1, number_of_dex_registers, 2);
-  stream.AddDexRegisterEntry(0, Kind::kInStack, 0);         // Short location.
-  stream.AddDexRegisterEntry(1, Kind::kConstant, -2);       // Large location.
-  stream.AddInlineInfoEntry(42);
-  stream.AddInlineInfoEntry(82);
+  stream.AddDexRegisterEntry(Kind::kInStack, 0);         // Short location.
+  stream.AddDexRegisterEntry(Kind::kConstant, -2);       // Large location.
+  stream.BeginInlineInfoEntry(82, 3, number_of_dex_registers_in_inline_info);
+  stream.EndInlineInfoEntry();
+  stream.BeginInlineInfoEntry(42, 2, number_of_dex_registers_in_inline_info);
+  stream.EndInlineInfoEntry();
   stream.EndStackMapEntry();
 
   ArenaBitVector sp_mask2(&arena, 0, true);
   sp_mask2.SetBit(3);
   sp_mask1.SetBit(8);
   stream.BeginStackMapEntry(1, 128, 0xFF, &sp_mask2, number_of_dex_registers, 0);
-  stream.AddDexRegisterEntry(0, Kind::kInRegister, 18);     // Short location.
-  stream.AddDexRegisterEntry(1, Kind::kInFpuRegister, 3);   // Short location.
+  stream.AddDexRegisterEntry(Kind::kInRegister, 18);     // Short location.
+  stream.AddDexRegisterEntry(Kind::kInFpuRegister, 3);   // Short location.
   stream.EndStackMapEntry();
 
   size_t size = stream.PrepareForFillIn();
@@ -211,8 +214,10 @@
     ASSERT_TRUE(stack_map.HasInlineInfo(code_info));
     InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
     ASSERT_EQ(2u, inline_info.GetDepth());
-    ASSERT_EQ(42u, inline_info.GetMethodReferenceIndexAtDepth(0));
-    ASSERT_EQ(82u, inline_info.GetMethodReferenceIndexAtDepth(1));
+    ASSERT_EQ(82u, inline_info.GetMethodIndexAtDepth(0));
+    ASSERT_EQ(42u, inline_info.GetMethodIndexAtDepth(1));
+    ASSERT_EQ(3u, inline_info.GetDexPcAtDepth(0));
+    ASSERT_EQ(2u, inline_info.GetDexPcAtDepth(1));
   }
 
   // Second stack map.
@@ -277,8 +282,8 @@
   ArenaBitVector sp_mask(&arena, 0, false);
   uint32_t number_of_dex_registers = 2;
   stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
-  stream.AddDexRegisterEntry(0, Kind::kNone, 0);            // No location.
-  stream.AddDexRegisterEntry(1, Kind::kConstant, -2);       // Large location.
+  stream.AddDexRegisterEntry(Kind::kNone, 0);            // No location.
+  stream.AddDexRegisterEntry(Kind::kConstant, -2);       // Large location.
   stream.EndStackMapEntry();
 
   size_t size = stream.PrepareForFillIn();
@@ -364,13 +369,13 @@
     // as using a single value (in the whole CodeInfo object) would
     // make this Dex register mapping data empty (see
     // art::DexRegisterMap::SingleEntrySizeInBits).
-    stream.AddDexRegisterEntry(i, Kind::kConstant, i % 2);  // Short location.
+    stream.AddDexRegisterEntry(Kind::kConstant, i % 2);  // Short location.
   }
   stream.EndStackMapEntry();
   // Create the second stack map (and its Dex register map).
   stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
   for (uint32_t i = 0; i < number_of_dex_registers; ++i) {
-    stream.AddDexRegisterEntry(i, Kind::kConstant, 0);  // Short location.
+    stream.AddDexRegisterEntry(Kind::kConstant, 0);  // Short location.
   }
   stream.EndStackMapEntry();
 
@@ -420,18 +425,18 @@
   uint32_t number_of_dex_registers = 2;
   // First stack map.
   stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
-  stream.AddDexRegisterEntry(0, Kind::kInRegister, 0);  // Short location.
-  stream.AddDexRegisterEntry(1, Kind::kConstant, -2);   // Large location.
+  stream.AddDexRegisterEntry(Kind::kInRegister, 0);  // Short location.
+  stream.AddDexRegisterEntry(Kind::kConstant, -2);   // Large location.
   stream.EndStackMapEntry();
   // Second stack map, which should share the same dex register map.
   stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
-  stream.AddDexRegisterEntry(0, Kind::kInRegister, 0);  // Short location.
-  stream.AddDexRegisterEntry(1, Kind::kConstant, -2);   // Large location.
+  stream.AddDexRegisterEntry(Kind::kInRegister, 0);  // Short location.
+  stream.AddDexRegisterEntry(Kind::kConstant, -2);   // Large location.
   stream.EndStackMapEntry();
   // Third stack map (doesn't share the dex register map).
   stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask, number_of_dex_registers, 0);
-  stream.AddDexRegisterEntry(0, Kind::kInRegister, 2);  // Short location.
-  stream.AddDexRegisterEntry(1, Kind::kConstant, -2);   // Large location.
+  stream.AddDexRegisterEntry(Kind::kInRegister, 2);  // Short location.
+  stream.AddDexRegisterEntry(Kind::kConstant, -2);   // Large location.
   stream.EndStackMapEntry();
 
   size_t size = stream.PrepareForFillIn();
@@ -500,4 +505,167 @@
   ASSERT_FALSE(stack_map.HasInlineInfo(code_info));
 }
 
+TEST(StackMapTest, InlineTest) {
+  ArenaPool pool;
+  ArenaAllocator arena(&pool);
+  StackMapStream stream(&arena);
+
+  ArenaBitVector sp_mask1(&arena, 0, true);
+  sp_mask1.SetBit(2);
+  sp_mask1.SetBit(4);
+
+  // First stack map.
+  stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask1, 2, 2);
+  stream.AddDexRegisterEntry(Kind::kInStack, 0);
+  stream.AddDexRegisterEntry(Kind::kConstant, 4);
+
+  stream.BeginInlineInfoEntry(42, 2, 1);
+  stream.AddDexRegisterEntry(Kind::kInStack, 8);
+  stream.EndInlineInfoEntry();
+  stream.BeginInlineInfoEntry(82, 3, 3);
+  stream.AddDexRegisterEntry(Kind::kInStack, 16);
+  stream.AddDexRegisterEntry(Kind::kConstant, 20);
+  stream.AddDexRegisterEntry(Kind::kInRegister, 15);
+  stream.EndInlineInfoEntry();
+
+  stream.EndStackMapEntry();
+
+  // Second stack map.
+  stream.BeginStackMapEntry(2, 22, 0x3, &sp_mask1, 2, 3);
+  stream.AddDexRegisterEntry(Kind::kInStack, 56);
+  stream.AddDexRegisterEntry(Kind::kConstant, 0);
+
+  stream.BeginInlineInfoEntry(42, 2, 1);
+  stream.AddDexRegisterEntry(Kind::kInStack, 12);
+  stream.EndInlineInfoEntry();
+  stream.BeginInlineInfoEntry(82, 3, 3);
+  stream.AddDexRegisterEntry(Kind::kInStack, 80);
+  stream.AddDexRegisterEntry(Kind::kConstant, 10);
+  stream.AddDexRegisterEntry(Kind::kInRegister, 5);
+  stream.EndInlineInfoEntry();
+  stream.BeginInlineInfoEntry(52, 5, 0);
+  stream.EndInlineInfoEntry();
+
+  stream.EndStackMapEntry();
+
+  // Third stack map.
+  stream.BeginStackMapEntry(4, 56, 0x3, &sp_mask1, 2, 0);
+  stream.AddDexRegisterEntry(Kind::kNone, 0);
+  stream.AddDexRegisterEntry(Kind::kConstant, 4);
+  stream.EndStackMapEntry();
+
+  // Fourth stack map.
+  stream.BeginStackMapEntry(6, 78, 0x3, &sp_mask1, 2, 3);
+  stream.AddDexRegisterEntry(Kind::kInStack, 56);
+  stream.AddDexRegisterEntry(Kind::kConstant, 0);
+
+  stream.BeginInlineInfoEntry(42, 2, 0);
+  stream.EndInlineInfoEntry();
+  stream.BeginInlineInfoEntry(52, 5, 1);
+  stream.AddDexRegisterEntry(Kind::kInRegister, 2);
+  stream.EndInlineInfoEntry();
+  stream.BeginInlineInfoEntry(52, 10, 2);
+  stream.AddDexRegisterEntry(Kind::kNone, 0);
+  stream.AddDexRegisterEntry(Kind::kInRegister, 3);
+  stream.EndInlineInfoEntry();
+
+  stream.EndStackMapEntry();
+
+  size_t size = stream.PrepareForFillIn();
+  void* memory = arena.Alloc(size, kArenaAllocMisc);
+  MemoryRegion region(memory, size);
+  stream.FillIn(region);
+
+  CodeInfo ci(region);
+
+  {
+    // Verify first stack map.
+    StackMap sm0 = ci.GetStackMapAt(0);
+
+    DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm0, 2);
+    ASSERT_EQ(0, dex_registers0.GetStackOffsetInBytes(0, 2, ci));
+    ASSERT_EQ(4, dex_registers0.GetConstant(1, 2, ci));
+
+    InlineInfo if0 = ci.GetInlineInfoOf(sm0);
+    ASSERT_EQ(2u, if0.GetDepth());
+    ASSERT_EQ(2u, if0.GetDexPcAtDepth(0));
+    ASSERT_EQ(42u, if0.GetMethodIndexAtDepth(0));
+    ASSERT_EQ(3u, if0.GetDexPcAtDepth(1));
+    ASSERT_EQ(82u, if0.GetMethodIndexAtDepth(1));
+
+    DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if0, 1);
+    ASSERT_EQ(8, dex_registers1.GetStackOffsetInBytes(0, 1, ci));
+
+    DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, if0, 3);
+    ASSERT_EQ(16, dex_registers2.GetStackOffsetInBytes(0, 3, ci));
+    ASSERT_EQ(20, dex_registers2.GetConstant(1, 3, ci));
+    ASSERT_EQ(15, dex_registers2.GetMachineRegister(2, 3, ci));
+  }
+
+  {
+    // Verify second stack map.
+    StackMap sm1 = ci.GetStackMapAt(1);
+
+    DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm1, 2);
+    ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0, 2, ci));
+    ASSERT_EQ(0, dex_registers0.GetConstant(1, 2, ci));
+
+    InlineInfo if1 = ci.GetInlineInfoOf(sm1);
+    ASSERT_EQ(3u, if1.GetDepth());
+    ASSERT_EQ(2u, if1.GetDexPcAtDepth(0));
+    ASSERT_EQ(42u, if1.GetMethodIndexAtDepth(0));
+    ASSERT_EQ(3u, if1.GetDexPcAtDepth(1));
+    ASSERT_EQ(82u, if1.GetMethodIndexAtDepth(1));
+    ASSERT_EQ(5u, if1.GetDexPcAtDepth(2));
+    ASSERT_EQ(52u, if1.GetMethodIndexAtDepth(2));
+
+    DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if1, 1);
+    ASSERT_EQ(12, dex_registers1.GetStackOffsetInBytes(0, 1, ci));
+
+    DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(1, if1, 3);
+    ASSERT_EQ(80, dex_registers2.GetStackOffsetInBytes(0, 3, ci));
+    ASSERT_EQ(10, dex_registers2.GetConstant(1, 3, ci));
+    ASSERT_EQ(5, dex_registers2.GetMachineRegister(2, 3, ci));
+
+    ASSERT_FALSE(if1.HasDexRegisterMapAtDepth(2));
+  }
+
+  {
+    // Verify third stack map.
+    StackMap sm2 = ci.GetStackMapAt(2);
+
+    DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm2, 2);
+    ASSERT_FALSE(dex_registers0.IsDexRegisterLive(0));
+    ASSERT_EQ(4, dex_registers0.GetConstant(1, 2, ci));
+    ASSERT_FALSE(sm2.HasInlineInfo(ci));
+  }
+
+  {
+    // Verify fourth stack map.
+    StackMap sm3 = ci.GetStackMapAt(3);
+
+    DexRegisterMap dex_registers0 = ci.GetDexRegisterMapOf(sm3, 2);
+    ASSERT_EQ(56, dex_registers0.GetStackOffsetInBytes(0, 2, ci));
+    ASSERT_EQ(0, dex_registers0.GetConstant(1, 2, ci));
+
+    InlineInfo if2 = ci.GetInlineInfoOf(sm3);
+    ASSERT_EQ(3u, if2.GetDepth());
+    ASSERT_EQ(2u, if2.GetDexPcAtDepth(0));
+    ASSERT_EQ(42u, if2.GetMethodIndexAtDepth(0));
+    ASSERT_EQ(5u, if2.GetDexPcAtDepth(1));
+    ASSERT_EQ(52u, if2.GetMethodIndexAtDepth(1));
+    ASSERT_EQ(10u, if2.GetDexPcAtDepth(2));
+    ASSERT_EQ(52u, if2.GetMethodIndexAtDepth(2));
+
+    ASSERT_FALSE(if2.HasDexRegisterMapAtDepth(0));
+
+    DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(1, if2, 1);
+    ASSERT_EQ(2, dex_registers1.GetMachineRegister(0, 1, ci));
+
+    DexRegisterMap dex_registers2 = ci.GetDexRegisterMapAtDepth(2, if2, 2);
+    ASSERT_FALSE(dex_registers2.IsDexRegisterLive(0));
+    ASSERT_EQ(3, dex_registers2.GetMachineRegister(1, 2, ci));
+  }
+}
+
 }  // namespace art
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..75f2b77 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;
 }
@@ -1614,7 +1638,6 @@
     // branch the size may change if it so happens that other branches change size that change
     // the distance to the target and that distance puts this branch over the limit for 16 bits.
     if (size == Branch::k16Bit) {
-      DCHECK(!force_32bit_branches_);
       Emit16(0);          // Space for a 16 bit branch.
     } else {
       Emit32(0);            // Space for a 32 bit branch.
@@ -1622,7 +1645,7 @@
   } else {
     // Branch is to an unbound label.  Emit space for it.
     uint16_t branch_id = AddBranch(branch_type, pc, cond);    // Unresolved branch.
-    if (force_32bit_branches_ || force_32bit_) {
+    if (!CanRelocateBranches() || force_32bit_) {
       Emit16(static_cast<uint16_t>(label->position_));    // Emit current label link.
       Emit16(0);                   // another 16 bits.
     } else {
@@ -2258,7 +2281,7 @@
     uint32_t branch_location = branch->GetLocation();
     uint16_t next = buffer_.Load<uint16_t>(branch_location);       // Get next in chain.
     if (changed) {
-      DCHECK(!force_32bit_branches_);
+      DCHECK(CanRelocateBranches());
       MakeHoleForBranch(branch->GetLocation(), 2);
       if (branch->IsCompareAndBranch()) {
         // A cbz/cbnz instruction has changed size.  There is no valid encoding for
@@ -2718,21 +2741,21 @@
 
 
 void Thumb2Assembler::CompareAndBranchIfZero(Register r, Label* label) {
-  if (force_32bit_branches_) {
+  if (CanRelocateBranches()) {
+    cbz(r, label);
+  } else {
     cmp(r, ShifterOperand(0));
     b(label, EQ);
-  } else {
-    cbz(r, label);
   }
 }
 
 
 void Thumb2Assembler::CompareAndBranchIfNonZero(Register r, Label* label) {
-  if (force_32bit_branches_) {
+  if (CanRelocateBranches()) {
+    cbnz(r, label);
+  } else {
     cmp(r, ShifterOperand(0));
     b(label, NE);
-  } else {
-    cbnz(r, label);
   }
 }
 }  // namespace arm
diff --git a/compiler/utils/arm/assembler_thumb2.h b/compiler/utils/arm/assembler_thumb2.h
index e33c240..90d489f 100644
--- a/compiler/utils/arm/assembler_thumb2.h
+++ b/compiler/utils/arm/assembler_thumb2.h
@@ -31,8 +31,8 @@
 
 class Thumb2Assembler FINAL : public ArmAssembler {
  public:
-  explicit Thumb2Assembler(bool force_32bit_branches = false)
-      : force_32bit_branches_(force_32bit_branches),
+  explicit Thumb2Assembler(bool can_relocate_branches = true)
+      : can_relocate_branches_(can_relocate_branches),
         force_32bit_(false),
         it_cond_index_(kNoItCondition),
         next_condition_(AL) {
@@ -52,8 +52,8 @@
     return force_32bit_;
   }
 
-  bool IsForced32BitBranches() const {
-    return force_32bit_branches_;
+  bool CanRelocateBranches() const {
+    return can_relocate_branches_;
   }
 
   void FinalizeInstructions(const MemoryRegion& region) OVERRIDE {
@@ -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;
 
@@ -437,8 +439,12 @@
   void EmitShift(Register rd, Register rm, Shift shift, uint8_t amount, bool setcc = false);
   void EmitShift(Register rd, Register rn, Shift shift, Register rm, bool setcc = false);
 
-  bool force_32bit_branches_;  // Force the assembler to use 32 bit branch instructions.
-  bool force_32bit_;           // Force the assembler to use 32 bit thumb2 instructions.
+  // Whether the assembler can relocate branches. If false, unresolved branches will be
+  // emitted on 32bits.
+  bool can_relocate_branches_;
+
+  // Force the assembler to use 32 bit thumb2 instructions.
+  bool force_32bit_;
 
   // IfThen conditions.  Used to check that conditional instructions match the preceding IT.
   Condition it_conditions_[4];
@@ -554,12 +560,21 @@
     // size of the branch to change return true.  Otherwise return false.
     bool Resolve(uint32_t target) {
       target_ = target;
-      Size newsize = CalculateSize();
-      if (size_ != newsize) {
-        size_ = newsize;
-        return true;
+      if (assembler_->CanRelocateBranches()) {
+        Size new_size = CalculateSize();
+        if (size_ != new_size) {
+          size_ = new_size;
+          return true;
+        }
+        return false;
+      } else {
+        if (kIsDebugBuild) {
+          Size new_size = CalculateSize();
+          // Check that the size has not increased.
+          DCHECK(!(new_size == k32Bit && size_ == k16Bit));
+        }
+        return false;
       }
-      return false;
     }
 
     // Move a cbz/cbnz branch.  This is always forward.
@@ -575,6 +590,7 @@
     // size of the branch instruction.  It returns true if the branch
     // has changed size.
     bool Relocate(uint32_t oldlocation, int32_t delta) {
+      DCHECK(assembler_->CanRelocateBranches());
       if (location_ > oldlocation) {
         location_ += delta;
       }
@@ -587,9 +603,9 @@
       }
 
       // Calculate the new size.
-      Size newsize = CalculateSize();
-      if (size_ != newsize) {
-        size_ = newsize;
+      Size new_size = CalculateSize();
+      if (size_ != new_size) {
+        size_ = new_size;
         return true;
       }
       return false;
@@ -631,15 +647,13 @@
    private:
     // Calculate the size of the branch instruction based on its type and offset.
     Size CalculateSize() const {
-      if (assembler_->IsForced32BitBranches()) {
-        return k32Bit;
-      }
       if (target_ == kUnresolved) {
         if (assembler_->IsForced32Bit() && (type_ == kUnconditional || type_ == kConditional)) {
           return k32Bit;
         }
-        return k16Bit;
+        return assembler_->CanRelocateBranches() ? k16Bit : k32Bit;
       }
+      // When the target is resolved, we know the best encoding for it.
       int32_t delta = target_ - location_ - 4;
       if (delta < 0) {
         delta = -delta;
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/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index b4a45c6..3cf458a 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -979,7 +979,10 @@
       oss.str("");  // Reset.
       oss << kRuntimeISA;
       key_value_store_->Put(OatHeader::kDex2OatHostKey, oss.str());
-      key_value_store_->Put(OatHeader::kPicKey, compile_pic ? "true" : "false");
+      key_value_store_->Put(OatHeader::kPicKey,
+                            compile_pic ? OatHeader::kTrueValue : OatHeader::kFalseValue);
+      key_value_store_->Put(OatHeader::kDebuggableKey,
+                            debuggable ? OatHeader::kTrueValue : OatHeader::kFalseValue);
     }
   }
 
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index 7488578..3c145d7 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -313,8 +313,7 @@
     /*
      * All generated callsites for interface invokes and invocation slow paths will load arguments
      * as usual - except instead of loading arg0/r0 with the target Method*, arg0/r0 will contain
-     * the method_idx.  This wrapper will save arg1-arg3, load the caller's Method*, align the
-     * stack and call the appropriate C helper.
+     * the method_idx.  This wrapper will save arg1-arg3, and call the appropriate C helper.
      * NOTE: "this" is first visible argument of the target, and so can be found in arg1/r1.
      *
      * The helper will attempt to locate the target and return a 64-bit result in r0/r1 consisting
@@ -330,13 +329,10 @@
     .extern \cxx_name
 ENTRY \c_name
     SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME r2, r3  @ save callee saves in case allocation triggers GC
-    ldr    r2, [sp, #FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE]  @ pass caller Method*
-    mov    r3, r9                         @ pass Thread::Current
-    mov    r12, sp
-    str    r12, [sp, #-16]!               @ expand the frame and pass SP
+    mov    r2, r9                         @ pass Thread::Current
+    mov    r3, sp
     .cfi_adjust_cfa_offset 16
     bl     \cxx_name                      @ (method_idx, this, caller, Thread*, SP)
-    add    sp, #16                        @ strip the extra frame
     .cfi_adjust_cfa_offset -16
     mov    r12, r1                        @ save Method*->code_
     RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S
index f8b0734..6b16a2e5 100644
--- a/runtime/arch/arm64/quick_entrypoints_arm64.S
+++ b/runtime/arch/arm64/quick_entrypoints_arm64.S
@@ -459,8 +459,7 @@
     /*
      * All generated callsites for interface invokes and invocation slow paths will load arguments
      * as usual - except instead of loading arg0/x0 with the target Method*, arg0/x0 will contain
-     * the method_idx.  This wrapper will save arg1-arg3, load the caller's Method*, align the
-     * stack and call the appropriate C helper.
+     * the method_idx.  This wrapper will save arg1-arg3, and call the appropriate C helper.
      * NOTE: "this" is first visible argument of the target, and so can be found in arg1/x1.
      *
      * The helper will attempt to locate the target and return a 128-bit result in x0/x1 consisting
@@ -483,10 +482,9 @@
     // Helper signature is always
     // (method_idx, *this_object, *caller_method, *self, sp)
 
-    ldr    w2, [sp, #FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE]  // pass caller Method*
-    mov    x3, xSELF                      // pass Thread::Current
-    mov    x4, sp
-    bl     \cxx_name                      // (method_idx, this, caller, Thread*, SP)
+    mov    x2, xSELF                      // pass Thread::Current
+    mov    x3, sp
+    bl     \cxx_name                      // (method_idx, this, Thread*, SP)
     mov    xIP0, x1                       // save Method*->code_
     RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
     cbz    x0, 1f                         // did we find the target? if not go to exception delivery
diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S
index ee5c59f..92b180e 100644
--- a/runtime/arch/mips/quick_entrypoints_mips.S
+++ b/runtime/arch/mips/quick_entrypoints_mips.S
@@ -439,8 +439,7 @@
     /*
      * All generated callsites for interface invokes and invocation slow paths will load arguments
      * as usual - except instead of loading arg0/$a0 with the target Method*, arg0/$a0 will contain
-     * the method_idx.  This wrapper will save arg1-arg3, load the caller's Method*, align the
-     * stack and call the appropriate C helper.
+     * the method_idx.  This wrapper will save arg1-arg3, and call the appropriate C helper.
      * NOTE: "this" is first visable argument of the target, and so can be found in arg1/$a1.
      *
      * The helper will attempt to locate the target and return a 64-bit result in $v0/$v1 consisting
@@ -456,15 +455,13 @@
     .extern \cxx_name
 ENTRY \c_name
     SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME  # save callee saves in case allocation triggers GC
-    lw    $a2, FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE+ARG_SLOT_SIZE($sp)    # pass caller Method*
-    addiu $t0, $sp, ARG_SLOT_SIZE         # save $sp (remove arg slots)
-    move  $a3, rSELF                      # pass Thread::Current
-    jal   \cxx_name                       # (method_idx, this, caller, Thread*, $sp)
-    sw    $t0, 16($sp)                    # pass $sp
-    move  $a0, $v0                        # save target Method*
+    move  $a2, rSELF                       # pass Thread::Current
+    jal   \cxx_name                        # (method_idx, this, Thread*, $sp)
+    addiu $a3, $sp, ARG_SLOT_SIZE          # pass $sp (remove arg slots)
+    move  $a0, $v0                         # save target Method*
     RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
     beqz  $v0, 1f
-    move  $t9, $v1                        # save $v0->code_
+    move  $t9, $v1                         # save $v0->code_
     jalr  $zero, $t9
     nop
 1:
diff --git a/runtime/arch/mips64/quick_entrypoints_mips64.S b/runtime/arch/mips64/quick_entrypoints_mips64.S
index ff79b5d..b7320a6 100644
--- a/runtime/arch/mips64/quick_entrypoints_mips64.S
+++ b/runtime/arch/mips64/quick_entrypoints_mips64.S
@@ -529,10 +529,9 @@
     .extern \cxx_name
 ENTRY \c_name
     SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME  # save callee saves in case allocation triggers GC
-    lwu   $a2, FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE($sp)  # pass caller Method*
-    move  $a3, rSELF                       # pass Thread::Current
-    jal   \cxx_name                        # (method_idx, this, caller, Thread*, $sp)
-    move  $a4, $sp                         # pass $sp
+    move  $a2, rSELF                       # pass Thread::Current
+    jal   \cxx_name                        # (method_idx, this, Thread*, $sp)
+    move  $a3, $sp                         # pass $sp
     move  $a0, $v0                         # save target Method*
     move  $t9, $v1                         # save $v0->code_
     RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S
index 6ebeba3..d62c1bc 100644
--- a/runtime/arch/x86/quick_entrypoints_x86.S
+++ b/runtime/arch/x86/quick_entrypoints_x86.S
@@ -278,8 +278,7 @@
     /*
      * All generated callsites for interface invokes and invocation slow paths will load arguments
      * as usual - except instead of loading arg0/r0 with the target Method*, arg0/r0 will contain
-     * the method_idx.  This wrapper will save arg1-arg3, load the caller's Method*, align the
-     * stack and call the appropriate C helper.
+     * the method_idx.  This wrapper will save arg1-arg3 and call the appropriate C helper.
      * NOTE: "this" is first visible argument of the target, and so can be found in arg1/r1.
      *
      * The helper will attempt to locate the target and return a 64-bit result in r0/r1 consisting
@@ -297,19 +296,15 @@
     movl %esp, %edx  // remember SP
 
     // Outgoing argument set up
-    subl MACRO_LITERAL(12), %esp  // alignment padding
-    CFI_ADJUST_CFA_OFFSET(12)
     PUSH edx                      // pass SP
     pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
     CFI_ADJUST_CFA_OFFSET(4)
-    pushl 32+32(%edx)             // pass caller Method*
-    CFI_ADJUST_CFA_OFFSET(4)
     PUSH ecx                      // pass arg2
     PUSH eax                      // pass arg1
     call VAR(cxx_name, 1)         // cxx_name(arg1, arg2, arg3, Thread*, SP)
     movl %edx, %edi               // save code pointer in EDI
-    addl MACRO_LITERAL(36), %esp  // Pop arguments skip eax
-    CFI_ADJUST_CFA_OFFSET(-36)
+    addl MACRO_LITERAL(20), %esp  // Pop arguments skip eax
+    CFI_ADJUST_CFA_OFFSET(-20)
 
     // Restore FPRs.
     movsd 0(%esp), %xmm0
diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
index da4d92b..ddeb5b8 100644
--- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S
+++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
@@ -341,8 +341,7 @@
     /*
      * All generated callsites for interface invokes and invocation slow paths will load arguments
      * as usual - except instead of loading arg0/rdi with the target Method*, arg0/rdi will contain
-     * the method_idx.  This wrapper will save arg1-arg3, load the caller's Method*, align the
-     * stack and call the appropriate C helper.
+     * the method_idx.  This wrapper will save arg1-arg3, and call the appropriate C helper.
      * NOTE: "this" is first visible argument of the target, and so can be found in arg1/rsi.
      *
      * The helper will attempt to locate the target and return a 128-bit result in rax/rdx consisting
@@ -362,11 +361,10 @@
     // Helper signature is always
     // (method_idx, *this_object, *caller_method, *self, sp)
 
-    movl FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE(%rsp), %edx  // pass caller Method*
-    movq %gs:THREAD_SELF_OFFSET, %rcx                      // pass Thread
-    movq %rsp, %r8                                         // pass SP
+    movq %gs:THREAD_SELF_OFFSET, %rdx                      // pass Thread
+    movq %rsp, %rcx                                        // pass SP
 
-    call VAR(cxx_name, 1)                   // cxx_name(arg1, arg2, caller method*, Thread*, SP)
+    call VAR(cxx_name, 1)                   // cxx_name(arg1, arg2, Thread*, SP)
                                                            // save the code pointer
     movq %rax, %rdi
     movq %rdx, %rax
diff --git a/runtime/base/logging.h b/runtime/base/logging.h
index 8b34374..35b50d1 100644
--- a/runtime/base/logging.h
+++ b/runtime/base/logging.h
@@ -39,6 +39,7 @@
 struct LogVerbosity {
   bool class_linker;  // Enabled with "-verbose:class".
   bool compiler;
+  bool deopt;
   bool gc;
   bool heap;
   bool jdwp;
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/class_linker.cc b/runtime/class_linker.cc
index b099088..292f830 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -819,6 +819,34 @@
   }
 }
 
+const OatFile* ClassLinker::GetBootOatFile() {
+  // To grab the boot oat, look at the dex files in the boot classpath. Any of those is fine, as
+  // they were all compiled into the same oat file. So grab the first one, which is guaranteed to
+  // exist if the boot class-path isn't empty.
+  if (boot_class_path_.empty()) {
+    return nullptr;
+  }
+  const DexFile* boot_dex_file = boot_class_path_[0];
+  // Is it from an oat file?
+  if (boot_dex_file->GetOatDexFile() != nullptr) {
+    return boot_dex_file->GetOatDexFile()->GetOatFile();
+  }
+  return nullptr;
+}
+
+const OatFile* ClassLinker::GetPrimaryOatFile() {
+  ReaderMutexLock mu(Thread::Current(), dex_lock_);
+  const OatFile* boot_oat_file = GetBootOatFile();
+  if (boot_oat_file != nullptr) {
+    for (const OatFile* oat_file : oat_files_) {
+      if (oat_file != boot_oat_file) {
+        return oat_file;
+      }
+    }
+  }
+  return nullptr;
+}
+
 // Check for class-def collisions in dex files.
 //
 // This works by maintaining a heap with one class from each dex file, sorted by the class
@@ -835,18 +863,7 @@
 
   // Add dex files from already loaded oat files, but skip boot.
   {
-    // To grab the boot oat, look at the dex files in the boot classpath. Any of those is fine, as
-    // they were all compiled into the same oat file. So grab the first one, which is guaranteed to
-    // exist if the boot class-path isn't empty.
-    const OatFile* boot_oat = nullptr;
-    if (!boot_class_path_.empty()) {
-      const DexFile* boot_dex_file = boot_class_path_[0];
-      // Is it from an oat file?
-      if (boot_dex_file->GetOatDexFile() != nullptr) {
-        boot_oat = boot_dex_file->GetOatDexFile()->GetOatFile();
-      }
-    }
-
+    const OatFile* boot_oat = GetBootOatFile();
     for (const OatFile* loaded_oat_file : oat_files_) {
       if (loaded_oat_file == boot_oat) {
         continue;
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 57989b2..95c8aa0 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -295,6 +295,10 @@
     return boot_class_path_;
   }
 
+  // Returns the first non-image oat file in the class path.
+  const OatFile* GetPrimaryOatFile()
+      LOCKS_EXCLUDED(dex_lock_);
+
   void VisitClasses(ClassVisitor* visitor, void* arg)
       LOCKS_EXCLUDED(Locks::classlinker_classes_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -615,6 +619,9 @@
   const OatFile* FindOpenedOatFileFromOatLocation(const std::string& oat_location)
       LOCKS_EXCLUDED(dex_lock_);
 
+  // Returns the boot image oat file.
+  const OatFile* GetBootOatFile() SHARED_LOCKS_REQUIRED(dex_lock_);
+
   mirror::ArtMethod* CreateProxyConstructor(Thread* self, Handle<mirror::Class> klass,
                                             mirror::Class* proxy_class)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 4bc9f98..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) {
@@ -2929,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());
@@ -3981,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();
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 0c5210d..b1d933d 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -1402,25 +1402,23 @@
 
 template <typename ElfTypes>
 bool ElfFileImpl<ElfTypes>::FixupDebugSections(typename std::make_signed<Elf_Off>::type base_address_delta) {
-  const Elf_Shdr* debug_info = FindSectionByName(".debug_info");
-  const Elf_Shdr* debug_abbrev = FindSectionByName(".debug_abbrev");
-  const Elf_Shdr* debug_str = FindSectionByName(".debug_str");
-  const Elf_Shdr* strtab_sec = FindSectionByName(".strtab");
-  const Elf_Shdr* symtab_sec = FindSectionByName(".symtab");
-
-  if (debug_info == nullptr || debug_abbrev == nullptr ||
-      debug_str == nullptr || strtab_sec == nullptr || symtab_sec == nullptr) {
-    // Release version of ART does not generate debug info.
-    return true;
-  }
   if (base_address_delta == 0) {
     return true;
   }
-  if (!ApplyOatPatchesTo(".debug_info", base_address_delta)) {
-    return false;
+  if (FindSectionByName(".debug_frame") != nullptr) {
+    if (!ApplyOatPatchesTo(".debug_frame", base_address_delta)) {
+      return false;
+    }
   }
-  if (!ApplyOatPatchesTo(".debug_line", base_address_delta)) {
-    return false;
+  if (FindSectionByName(".debug_info") != nullptr) {
+    if (!ApplyOatPatchesTo(".debug_info", base_address_delta)) {
+      return false;
+    }
+  }
+  if (FindSectionByName(".debug_line") != nullptr) {
+    if (!ApplyOatPatchesTo(".debug_line", base_address_delta)) {
+      return false;
+    }
   }
   return true;
 }
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index 9292cff..625e695 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -38,25 +38,34 @@
 
 namespace art {
 
-inline mirror::ArtMethod* GetCalleeSaveMethodCaller(Thread* self, Runtime::CalleeSaveType type)
+inline mirror::ArtMethod* GetCalleeSaveMethodCaller(StackReference<mirror::ArtMethod>* sp,
+                                                    Runtime::CalleeSaveType type,
+                                                    bool do_caller_check = false)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  auto* refs_only_sp = self->GetManagedStack()->GetTopQuickFrame();
-  DCHECK_EQ(refs_only_sp->AsMirrorPtr(), Runtime::Current()->GetCalleeSaveMethod(type));
+  DCHECK_EQ(sp->AsMirrorPtr(), Runtime::Current()->GetCalleeSaveMethod(type));
 
   const size_t callee_frame_size = GetCalleeSaveFrameSize(kRuntimeISA, type);
   auto* caller_sp = reinterpret_cast<StackReference<mirror::ArtMethod>*>(
-          reinterpret_cast<uintptr_t>(refs_only_sp) + callee_frame_size);
+          reinterpret_cast<uintptr_t>(sp) + callee_frame_size);
   auto* caller = caller_sp->AsMirrorPtr();
 
-  if (kIsDebugBuild) {
-    NthCallerVisitor visitor(self, 1, true);
+  if (kIsDebugBuild && do_caller_check) {
+    // Note that do_caller_check is optional, as this method can be called by
+    // stubs, and tests without a proper call stack.
+    NthCallerVisitor visitor(Thread::Current(), 1, true);
     visitor.WalkStack();
-    CHECK(caller == visitor.caller);
+    CHECK_EQ(caller, visitor.caller);
   }
 
   return caller;
 }
 
+inline mirror::ArtMethod* GetCalleeSaveMethodCaller(Thread* self, Runtime::CalleeSaveType type)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return GetCalleeSaveMethodCaller(
+      self->GetManagedStack()->GetTopQuickFrame(), type, true /* do_caller_check */);
+}
+
 template <const bool kAccessCheck>
 ALWAYS_INLINE
 inline mirror::Class* CheckObjectAlloc(uint32_t type_idx,
diff --git a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
index 6a8aaf2..1b1ef66 100644
--- a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "base/logging.h"
 #include "callee_save_frame.h"
 #include "dex_file-inl.h"
 #include "interpreter/interpreter.h"
@@ -29,6 +30,12 @@
 
 extern "C" NO_RETURN void artDeoptimize(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
+
+  if (VLOG_IS_ON(deopt)) {
+    LOG(INFO) << "Deopting:";
+    self->Dump(LOG(INFO));
+  }
+
   self->SetException(Thread::GetDeoptimizationException());
   self->QuickDeliverException();
 }
diff --git a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
index 46629f5..9148878 100644
--- a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
@@ -25,8 +25,7 @@
 
 namespace art {
 
-extern "C" mirror::Class* artInitializeStaticStorageFromCode(uint32_t type_idx,
-                                                             Thread* self)
+extern "C" mirror::Class* artInitializeStaticStorageFromCode(uint32_t type_idx, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // Called to ensure static storage base is initialized for direct static field reads and writes.
   // A class may be accessing another class' fields when it doesn't have access, as access has been
@@ -36,8 +35,7 @@
   return ResolveVerifyAndClinit(type_idx, caller, self, true, false);
 }
 
-extern "C" mirror::Class* artInitializeTypeFromCode(uint32_t type_idx,
-                                                    Thread* self)
+extern "C" mirror::Class* artInitializeTypeFromCode(uint32_t type_idx, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // Called when method->dex_cache_resolved_types_[] misses.
   ScopedQuickEntrypointChecks sqec(self);
@@ -45,8 +43,7 @@
   return ResolveVerifyAndClinit(type_idx, caller, self, false, false);
 }
 
-extern "C" mirror::Class* artInitializeTypeAndVerifyAccessFromCode(uint32_t type_idx,
-                                                                   Thread* self)
+extern "C" mirror::Class* artInitializeTypeAndVerifyAccessFromCode(uint32_t type_idx, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // Called when caller isn't guaranteed to have access to a type and the dex cache may be
   // unpopulated.
@@ -55,8 +52,7 @@
   return ResolveVerifyAndClinit(type_idx, caller, self, false, true);
 }
 
-extern "C" mirror::String* artResolveStringFromCode(int32_t string_idx,
-                                                    Thread* self)
+extern "C" mirror::String* artResolveStringFromCode(int32_t string_idx, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
   auto* caller = GetCalleeSaveMethodCaller(self, Runtime::kRefsOnly);
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 2e7e2df..345b0ad 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -294,8 +294,13 @@
   static mirror::ArtMethod* GetCallingMethod(StackReference<mirror::ArtMethod>* sp)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK(sp->AsMirrorPtr()->IsCalleeSaveMethod());
-    uint8_t* previous_sp = reinterpret_cast<uint8_t*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_FrameSize;
-    return reinterpret_cast<StackReference<mirror::ArtMethod>*>(previous_sp)->AsMirrorPtr();
+    return GetCalleeSaveMethodCaller(sp, Runtime::kRefsAndArgs);
+  }
+
+  static uint32_t GetCallingDexPc(StackReference<mirror::ArtMethod>* sp)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    DCHECK(sp->AsMirrorPtr()->IsCalleeSaveMethod());
+    return GetCallingMethod(sp)->ToDexPc(QuickArgumentVisitor::GetCallingPc(sp));
   }
 
   // For the given quick ref and args quick frame, return the caller's PC.
@@ -827,12 +832,13 @@
 
   // Compute details about the called method (avoid GCs)
   ClassLinker* linker = Runtime::Current()->GetClassLinker();
-  mirror::ArtMethod* caller = QuickArgumentVisitor::GetCallingMethod(sp);
   InvokeType invoke_type;
   MethodReference called_method(nullptr, 0);
   const bool called_method_known_on_entry = !called->IsRuntimeMethod();
+  mirror::ArtMethod* caller = nullptr;
   if (!called_method_known_on_entry) {
-    uint32_t dex_pc = caller->ToDexPc(QuickArgumentVisitor::GetCallingPc(sp));
+    caller = QuickArgumentVisitor::GetCallingMethod(sp);
+    uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp);
     const DexFile::CodeItem* code;
     called_method.dex_file = caller->GetDexFile();
     code = caller->GetCodeItem();
@@ -1946,16 +1952,13 @@
 // to hold the mutator lock (see SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) annotations).
 
 template<InvokeType type, bool access_check>
-static TwoWordReturn artInvokeCommon(uint32_t method_idx, mirror::Object* this_object,
-                                     mirror::ArtMethod* caller_method,
-                                     Thread* self, StackReference<mirror::ArtMethod>* sp);
-
-template<InvokeType type, bool access_check>
-static TwoWordReturn artInvokeCommon(uint32_t method_idx, mirror::Object* this_object,
-                                     mirror::ArtMethod* caller_method,
-                                     Thread* self, StackReference<mirror::ArtMethod>* sp) {
+static TwoWordReturn artInvokeCommon(uint32_t method_idx,
+                                     mirror::Object* this_object,
+                                     Thread* self,
+                                     StackReference<mirror::ArtMethod>* sp) {
   ScopedQuickEntrypointChecks sqec(self);
   DCHECK_EQ(sp->AsMirrorPtr(), Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs));
+  mirror::ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethod(sp);
   mirror::ArtMethod* method = FindMethodFast(method_idx, this_object, caller_method, access_check,
                                              type);
   if (UNLIKELY(method == nullptr)) {
@@ -1994,7 +1997,6 @@
   template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)                                          \
   TwoWordReturn artInvokeCommon<type, access_check>(uint32_t method_idx,                        \
                                                     mirror::Object* this_object,                \
-                                                    mirror::ArtMethod* caller_method,           \
                                                     Thread* self,                               \
                                                     StackReference<mirror::ArtMethod>* sp)      \
 
@@ -2012,58 +2014,58 @@
 
 // See comments in runtime_support_asm.S
 extern "C" TwoWordReturn artInvokeInterfaceTrampolineWithAccessCheck(
-    uint32_t method_idx, mirror::Object* this_object,
-    mirror::ArtMethod* caller_method, Thread* self,
+    uint32_t method_idx,
+    mirror::Object* this_object,
+    Thread* self,
     StackReference<mirror::ArtMethod>* sp)
         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return artInvokeCommon<kInterface, true>(method_idx, this_object,
-                                           caller_method, self, sp);
+  return artInvokeCommon<kInterface, true>(method_idx, this_object, self, sp);
 }
 
 extern "C" TwoWordReturn artInvokeDirectTrampolineWithAccessCheck(
-    uint32_t method_idx, mirror::Object* this_object,
-    mirror::ArtMethod* caller_method, Thread* self,
+    uint32_t method_idx,
+    mirror::Object* this_object,
+    Thread* self,
     StackReference<mirror::ArtMethod>* sp)
         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return artInvokeCommon<kDirect, true>(method_idx, this_object, caller_method,
-                                        self, sp);
+  return artInvokeCommon<kDirect, true>(method_idx, this_object, self, sp);
 }
 
 extern "C" TwoWordReturn artInvokeStaticTrampolineWithAccessCheck(
-    uint32_t method_idx, mirror::Object* this_object,
-    mirror::ArtMethod* caller_method, Thread* self,
+    uint32_t method_idx,
+    mirror::Object* this_object,
+    Thread* self,
     StackReference<mirror::ArtMethod>* sp)
         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return artInvokeCommon<kStatic, true>(method_idx, this_object, caller_method,
-                                        self, sp);
+  return artInvokeCommon<kStatic, true>(method_idx, this_object, self, sp);
 }
 
 extern "C" TwoWordReturn artInvokeSuperTrampolineWithAccessCheck(
-    uint32_t method_idx, mirror::Object* this_object,
-    mirror::ArtMethod* caller_method, Thread* self,
+    uint32_t method_idx,
+    mirror::Object* this_object,
+    Thread* self,
     StackReference<mirror::ArtMethod>* sp)
         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return artInvokeCommon<kSuper, true>(method_idx, this_object, caller_method,
-                                       self, sp);
+  return artInvokeCommon<kSuper, true>(method_idx, this_object, self, sp);
 }
 
 extern "C" TwoWordReturn artInvokeVirtualTrampolineWithAccessCheck(
-    uint32_t method_idx, mirror::Object* this_object,
-    mirror::ArtMethod* caller_method, Thread* self,
+    uint32_t method_idx,
+    mirror::Object* this_object,
+    Thread* self,
     StackReference<mirror::ArtMethod>* sp)
         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return artInvokeCommon<kVirtual, true>(method_idx, this_object, caller_method,
-                                         self, sp);
+  return artInvokeCommon<kVirtual, true>(method_idx, this_object, self, sp);
 }
 
 // Determine target of interface dispatch. This object is known non-null.
 extern "C" TwoWordReturn artInvokeInterfaceTrampoline(mirror::ArtMethod* interface_method,
                                                       mirror::Object* this_object,
-                                                      mirror::ArtMethod* caller_method,
                                                       Thread* self,
                                                       StackReference<mirror::ArtMethod>* sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
+  mirror::ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethod(sp);
   mirror::ArtMethod* method;
   if (LIKELY(interface_method->GetDexMethodIndex() != DexFile::kDexNoIndex)) {
     method = this_object->GetClass()->FindVirtualMethodForInterface(interface_method);
@@ -2075,12 +2077,7 @@
   } else {
     DCHECK(interface_method == Runtime::Current()->GetResolutionMethod());
 
-    // Find the caller PC.
-    constexpr size_t pc_offset = GetCalleeSaveReturnPcOffset(kRuntimeISA, Runtime::kRefsAndArgs);
-    uintptr_t caller_pc = *reinterpret_cast<uintptr_t*>(reinterpret_cast<uint8_t*>(sp) + pc_offset);
-
-    // Map the caller PC to a dex PC.
-    uint32_t dex_pc = caller_method->ToDexPc(caller_pc);
+    uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp);
     const DexFile::CodeItem* code = caller_method->GetCodeItem();
     CHECK_LT(dex_pc, code->insns_size_in_code_units_);
     const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index 53e56da..5401b56 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -373,8 +373,7 @@
       : mark_sweep_(mark_sweep), holder_(holder), offset_(offset) {
   }
 
-  void operator()(const Object* obj) const ALWAYS_INLINE
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  void operator()(const Object* obj) const ALWAYS_INLINE NO_THREAD_SAFETY_ANALYSIS {
     if (kProfileLargeObjects) {
       // TODO: Differentiate between marking and testing somehow.
       ++mark_sweep_->large_object_test_;
@@ -385,17 +384,51 @@
                  (kIsDebugBuild && large_object_space != nullptr &&
                      !large_object_space->Contains(obj)))) {
       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) {
+        size_t holder_size = holder_->SizeOf();
         ArtField* field = holder_->FindFieldByOffset(offset_);
-        LOG(INTERNAL_FATAL) << "Field info: holder=" << holder_
+        LOG(INTERNAL_FATAL) << "Field info: "
+                            << " holder=" << holder_
+                            << " holder_size=" << holder_size
                             << " holder_type=" << PrettyTypeOf(holder_)
                             << " offset=" << offset_.Uint32Value()
-                            << " field=" << (field != nullptr ? field->GetName() : "nullptr");
+                            << " field=" << (field != nullptr ? field->GetName() : "nullptr")
+                            << " field_type="
+                            << (field != nullptr ? field->GetTypeDescriptor() : "")
+                            << " first_ref_field_offset="
+                            << (holder_->IsClass()
+                                ? holder_->AsClass()->GetFirstReferenceStaticFieldOffset()
+                                : holder_->GetClass()->GetFirstReferenceInstanceFieldOffset())
+                            << " num_of_ref_fields="
+                            << (holder_->IsClass()
+                                ? holder_->AsClass()->NumReferenceStaticFields()
+                                : holder_->GetClass()->NumReferenceInstanceFields())
+                            << "\n";
       }
       PrintFileToLog("/proc/self/maps", LogSeverity::INTERNAL_FATAL);
       MemMap::DumpMaps(LOG(INTERNAL_FATAL), true);
+      {
+        LOG(INTERNAL_FATAL) << "Attempting see if it's a bad root";
+        Thread* self = Thread::Current();
+        if (Locks::mutator_lock_->IsExclusiveHeld(self)) {
+          mark_sweep_->VerifyRoots();
+        } else {
+          const bool heap_bitmap_exclusive_locked =
+              Locks::heap_bitmap_lock_->IsExclusiveHeld(self);
+          if (heap_bitmap_exclusive_locked) {
+            Locks::heap_bitmap_lock_->ExclusiveUnlock(self);
+          }
+          Locks::mutator_lock_->SharedUnlock(self);
+          ThreadList* tl = Runtime::Current()->GetThreadList();
+          tl->SuspendAll(__FUNCTION__);
+          mark_sweep_->VerifyRoots();
+          tl->ResumeAll();
+          Locks::mutator_lock_->SharedLock(self);
+          if (heap_bitmap_exclusive_locked) {
+            Locks::heap_bitmap_lock_->ExclusiveLock(self);
+          }
+        }
+      }
       LOG(FATAL) << "Can't mark invalid object";
     }
   }
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index f350038..99f5d45 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -203,6 +203,9 @@
   oat_file_option_string += ImageHeader::GetOatLocationFromImageLocation(image_filename);
   arg_vector.push_back(oat_file_option_string);
 
+  // Note: we do not generate a fully debuggable boot image so we do not pass the
+  // compiler flag --debuggable here.
+
   Runtime::Current()->AddCurrentRuntimeFeaturesAsDex2OatArguments(&arg_vector);
   CHECK_EQ(image_isa, kRuntimeISA)
       << "We should always be generating an image for the current isa.";
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index 9006257..317106b 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -767,8 +767,12 @@
     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);
 }
 
@@ -785,6 +789,20 @@
   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)
@@ -800,19 +818,51 @@
 }
 
 // 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,
@@ -1141,10 +1191,16 @@
           &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) {
@@ -1228,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.
@@ -1241,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/oat.cc b/runtime/oat.cc
index c223e2e..4f6aabc 100644
--- a/runtime/oat.cc
+++ b/runtime/oat.cc
@@ -27,6 +27,8 @@
 
 constexpr uint8_t OatHeader::kOatMagic[4];
 constexpr uint8_t OatHeader::kOatVersion[4];
+constexpr const char OatHeader::kTrueValue[];
+constexpr const char OatHeader::kFalseValue[];
 
 static size_t ComputeOatHeaderSize(const SafeMap<std::string, std::string>* variable_data) {
   size_t estimate = 0U;
@@ -443,9 +445,16 @@
 }
 
 bool OatHeader::IsPic() const {
-  const char* pic_string = GetStoreValueByKey(OatHeader::kPicKey);
-  static const char kTrue[] = "true";
-  return (pic_string != nullptr && strncmp(pic_string, kTrue, sizeof(kTrue)) == 0);
+  return IsKeyEnabled(OatHeader::kPicKey);
+}
+
+bool OatHeader::IsDebuggable() const {
+  return IsKeyEnabled(OatHeader::kDebuggableKey);
+}
+
+bool OatHeader::IsKeyEnabled(const char* key) const {
+  const char* key_value = GetStoreValueByKey(key);
+  return (key_value != nullptr && strncmp(key_value, kTrueValue, sizeof(kTrueValue)) == 0);
 }
 
 void OatHeader::Flatten(const SafeMap<std::string, std::string>* key_value_store) {
diff --git a/runtime/oat.h b/runtime/oat.h
index aaf442a..604e161 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,14 +32,18 @@
 class PACKED(4) OatHeader {
  public:
   static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' };
-  static constexpr uint8_t kOatVersion[] = { '0', '6', '2', '\0' };
+  static constexpr uint8_t kOatVersion[] = { '0', '6', '3', '\0' };
 
   static constexpr const char* kImageLocationKey = "image-location";
   static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
   static constexpr const char* kDex2OatHostKey = "dex2oat-host";
   static constexpr const char* kPicKey = "pic";
+  static constexpr const char* kDebuggableKey = "debuggable";
   static constexpr const char* kClassPathKey = "classpath";
 
+  static constexpr const char kTrueValue[] = "true";
+  static constexpr const char kFalseValue[] = "false";
+
   static OatHeader* Create(InstructionSet instruction_set,
                            const InstructionSetFeatures* instruction_set_features,
                            const std::vector<const DexFile*>* dex_files,
@@ -99,6 +103,7 @@
 
   size_t GetHeaderSize() const;
   bool IsPic() const;
+  bool IsDebuggable() const;
 
  private:
   OatHeader(InstructionSet instruction_set,
@@ -108,6 +113,9 @@
             uint32_t image_file_location_oat_data_begin,
             const SafeMap<std::string, std::string>* variable_data);
 
+  // Returns true if the value of the given key is "true", false otherwise.
+  bool IsKeyEnabled(const char* key) const;
+
   void Flatten(const SafeMap<std::string, std::string>* variable_data);
 
   uint8_t magic_[4];
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index b0cbd0e..63ee4b1 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -703,6 +703,10 @@
   // TODO: Check against oat_patches. b/18144996
 }
 
+bool OatFile::IsDebuggable() const {
+  return GetOatHeader().IsDebuggable();
+}
+
 static constexpr char kDexClassPathEncodingSeparator = '*';
 
 std::string OatFile::EncodeDexFileDependencies(const std::vector<const DexFile*>& dex_files) {
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index b32dd22..12e9f6c 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -81,6 +81,9 @@
 
   bool IsPic() const;
 
+  // Indicates whether the oat file was compiled with full debugging capability.
+  bool IsDebuggable() const;
+
   ElfFile* GetElfFile() const {
     CHECK_NE(reinterpret_cast<uintptr_t>(elf_file_.get()), reinterpret_cast<uintptr_t>(nullptr))
         << "Cannot get an elf file from " << GetLocation();
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index d07c09c..094d8b7 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -417,7 +417,7 @@
           << secondary_dex_location
           << ". Expected: " << expected_secondary_checksum
           << ", Actual: " << actual_secondary_checksum;
-        return false;
+        return true;
       }
     } else {
       // If we can't get the checksum for the secondary location, we assume
@@ -690,12 +690,20 @@
     return false;
   }
 
+  ClassLinker* linker = runtime->GetClassLinker();
+  CHECK(linker != nullptr) << "ClassLinker is not created yet";
+  const OatFile* primary_oat_file = linker->GetPrimaryOatFile();
+  const bool debuggable = primary_oat_file != nullptr && primary_oat_file->IsDebuggable();
+
   std::vector<std::string> argv;
   argv.push_back(runtime->GetCompilerExecutable());
   argv.push_back("--runtime-arg");
   argv.push_back("-classpath");
   argv.push_back("--runtime-arg");
   argv.push_back(runtime->GetClassPathString());
+  if (debuggable) {
+    argv.push_back("--debuggable");
+  }
   runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv);
 
   if (!runtime->IsVerificationEnabled()) {
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index 865fcb0..d8e3797 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -67,10 +67,23 @@
       << "Expected stripped dex file to be at: " << GetStrippedDexSrc1();
     ASSERT_FALSE(DexFile::GetChecksum(GetStrippedDexSrc1().c_str(), &checksum, &error_msg))
       << "Expected stripped dex file to be stripped: " << GetStrippedDexSrc1();
-    ASSERT_TRUE(OS::FileExists(GetMultiDexSrc1().c_str()))
-      << "Expected multidex file to be at: " << GetMultiDexSrc1();
     ASSERT_TRUE(OS::FileExists(GetDexSrc2().c_str()))
       << "Expected dex file to be at: " << GetDexSrc2();
+
+    // GetMultiDexSrc2 should have the same primary dex checksum as
+    // GetMultiDexSrc1, but a different secondary dex checksum.
+    std::vector<std::unique_ptr<const DexFile>> multi1;
+    ASSERT_TRUE(DexFile::Open(GetMultiDexSrc1().c_str(),
+          GetMultiDexSrc1().c_str(), &error_msg, &multi1)) << error_msg;
+    ASSERT_GT(multi1.size(), 1u);
+
+    std::vector<std::unique_ptr<const DexFile>> multi2;
+    ASSERT_TRUE(DexFile::Open(GetMultiDexSrc2().c_str(),
+          GetMultiDexSrc2().c_str(), &error_msg, &multi2)) << error_msg;
+    ASSERT_GT(multi2.size(), 1u);
+
+    ASSERT_EQ(multi1[0]->GetLocationChecksum(), multi2[0]->GetLocationChecksum());
+    ASSERT_NE(multi1[1]->GetLocationChecksum(), multi2[1]->GetLocationChecksum());
   }
 
   virtual void SetUpRuntimeOptions(RuntimeOptions* options) {
@@ -149,6 +162,12 @@
     return GetTestDexFileName("MultiDex");
   }
 
+  // Returns the path to a multidex file equivalent to GetMultiDexSrc2, but
+  // with the contents of the secondary dex file changed.
+  std::string GetMultiDexSrc2() {
+    return GetTestDexFileName("MultiDexModifiedSecondary");
+  }
+
   std::string GetDexSrc2() {
     return GetTestDexFileName("Nested");
   }
@@ -344,6 +363,23 @@
   EXPECT_EQ(2u, dex_files.size());
 }
 
+// Case: We have a MultiDEX file where the secondary dex file is out of date.
+// Expect: The status is kDex2OatNeeded.
+TEST_F(OatFileAssistantTest, MultiDexSecondaryOutOfDate) {
+  std::string dex_location = GetScratchDir() + "/MultiDexSecondaryOutOfDate.jar";
+
+  // Compile code for GetMultiDexSrc1.
+  Copy(GetMultiDexSrc1(), dex_location);
+  GenerateOatForTest(dex_location.c_str());
+
+  // Now overwrite the dex file with GetMultiDexSrc2 so the secondary checksum
+  // is out of date.
+  Copy(GetMultiDexSrc2(), dex_location);
+
+  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
+  EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
+}
+
 // Case: We have a MultiDEX file and up-to-date OAT file for it with relative
 // encoded dex locations.
 // Expect: The oat file status is kNoDexOptNeeded.
@@ -1001,9 +1037,6 @@
 // TODO: More Tests:
 //  * Test class linker falls back to unquickened dex for DexNoOat
 //  * Test class linker falls back to unquickened dex for MultiDexNoOat
-//  * Test multidex files:
-//     - Multidex with only classes2.dex out of date should have status
-//       kOutOfDate
 //  * Test using secondary isa
 //  * Test with profiling info?
 //  * Test for status of oat while oat is being generated (how?)
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 2633898..2618661 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1678,10 +1678,6 @@
   std::string feature_string("--instruction-set-features=");
   feature_string += features->GetFeatureString();
   argv->push_back(feature_string);
-
-  if (Dbg::IsJdwpConfigured()) {
-    argv->push_back("--debuggable");
-  }
 }
 
 void Runtime::UpdateProfilerState(int state) {
diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def
index 8b504c1..922334e 100644
--- a/runtime/runtime_options.def
+++ b/runtime/runtime_options.def
@@ -62,7 +62,7 @@
 RUNTIME_OPTIONS_KEY (Unit,                DumpJITInfoOnShutdown)
 RUNTIME_OPTIONS_KEY (Unit,                IgnoreMaxFootprint)
 RUNTIME_OPTIONS_KEY (Unit,                LowMemoryMode)
-RUNTIME_OPTIONS_KEY (bool,                UseTLAB,                        kUseTlab)
+RUNTIME_OPTIONS_KEY (bool,                UseTLAB,                        (kUseTlab || kUseReadBarrier))
 RUNTIME_OPTIONS_KEY (bool,                EnableHSpaceCompactForOOM,      true)
 RUNTIME_OPTIONS_KEY (bool,                UseJIT,      false)
 RUNTIME_OPTIONS_KEY (unsigned int,        JITCompileThreshold, jit::Jit::kDefaultCompileThreshold)
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 800acaa..6795516 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -99,15 +99,45 @@
       cur_quick_frame_pc_(0),
       num_frames_(num_frames),
       cur_depth_(0),
+      current_inlining_depth_(0),
       context_(context) {
   DCHECK(thread == Thread::Current() || thread->IsSuspended()) << *thread;
 }
 
+InlineInfo StackVisitor::GetCurrentInlineInfo() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::ArtMethod* outer_method = GetCurrentQuickFrame()->AsMirrorPtr();
+  uint32_t native_pc_offset = outer_method->NativeQuickPcOffset(cur_quick_frame_pc_);
+  CodeInfo code_info = outer_method->GetOptimizedCodeInfo();
+  StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
+  return code_info.GetInlineInfoOf(stack_map);
+}
+
+mirror::ArtMethod* StackVisitor::GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  if (cur_shadow_frame_ != nullptr) {
+    return cur_shadow_frame_->GetMethod();
+  } else if (cur_quick_frame_ != nullptr) {
+    if (IsInInlinedFrame()) {
+      size_t depth_in_stack_map = current_inlining_depth_ - 1;
+      return GetCurrentQuickFrame()->AsMirrorPtr()->GetDexCacheResolvedMethod(
+          GetCurrentInlineInfo().GetMethodIndexAtDepth(depth_in_stack_map));
+    } else {
+      return cur_quick_frame_->AsMirrorPtr();
+    }
+  } else {
+    return nullptr;
+  }
+}
+
 uint32_t StackVisitor::GetDexPc(bool abort_on_failure) const {
   if (cur_shadow_frame_ != nullptr) {
     return cur_shadow_frame_->GetDexPC();
   } else if (cur_quick_frame_ != nullptr) {
-    return GetMethod()->ToDexPc(cur_quick_frame_pc_, abort_on_failure);
+    if (IsInInlinedFrame()) {
+      size_t depth_in_stack_map = current_inlining_depth_ - 1;
+      return GetCurrentInlineInfo().GetDexPcAtDepth(depth_in_stack_map);
+    } else {
+      return GetMethod()->ToDexPc(cur_quick_frame_pc_, abort_on_failure);
+    }
   } else {
     return 0;
   }
@@ -225,18 +255,27 @@
 
 bool StackVisitor::GetVRegFromOptimizedCode(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind,
                                             uint32_t* val) const {
-  const void* code_pointer = m->GetQuickOatCodePointer(sizeof(void*));
-  DCHECK(code_pointer != nullptr);
-  uint32_t native_pc_offset = m->NativeQuickPcOffset(cur_quick_frame_pc_);
-  CodeInfo code_info = m->GetOptimizedCodeInfo();
-  StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
+  DCHECK_EQ(m, GetMethod());
   const DexFile::CodeItem* code_item = m->GetCodeItem();
   DCHECK(code_item != nullptr) << PrettyMethod(m);  // Can't be null or how would we compile
                                                     // its instructions?
-  DCHECK_LT(vreg, code_item->registers_size_);
   uint16_t number_of_dex_registers = code_item->registers_size_;
-  DexRegisterMap dex_register_map =
-      code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
+  DCHECK_LT(vreg, code_item->registers_size_);
+
+  mirror::ArtMethod* outer_method = GetCurrentQuickFrame()->AsMirrorPtr();
+  const void* code_pointer = outer_method->GetQuickOatCodePointer(sizeof(void*));
+  DCHECK(code_pointer != nullptr);
+  CodeInfo code_info = outer_method->GetOptimizedCodeInfo();
+
+  uint32_t native_pc_offset = outer_method->NativeQuickPcOffset(cur_quick_frame_pc_);
+  StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
+  size_t depth_in_stack_map = current_inlining_depth_ - 1;
+
+  DexRegisterMap dex_register_map = IsInInlinedFrame()
+      ? code_info.GetDexRegisterMapAtDepth(
+            depth_in_stack_map, code_info.GetInlineInfoOf(stack_map), number_of_dex_registers)
+      : code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
+
   DexRegisterLocation::Kind location_kind =
       dex_register_map.GetLocationKind(vreg, number_of_dex_registers, code_info);
   switch (location_kind) {
@@ -704,6 +743,26 @@
       mirror::ArtMethod* method = cur_quick_frame_->AsMirrorPtr();
       while (method != nullptr) {
         SanityCheckFrame();
+
+        if ((walk_kind_ == StackWalkKind::kIncludeInlinedFrames)
+            && method->IsOptimized(sizeof(void*))) {
+          CodeInfo code_info = method->GetOptimizedCodeInfo();
+          uint32_t native_pc_offset = method->NativeQuickPcOffset(cur_quick_frame_pc_);
+          StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
+          if (stack_map.HasInlineInfo(code_info)) {
+            InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
+            DCHECK_EQ(current_inlining_depth_, 0u);
+            for (current_inlining_depth_ = inline_info.GetDepth();
+                 current_inlining_depth_ != 0;
+                 --current_inlining_depth_) {
+              bool should_continue = VisitFrame();
+              if (UNLIKELY(!should_continue)) {
+                return;
+              }
+            }
+          }
+        }
+
         bool should_continue = VisitFrame();
         if (UNLIKELY(!should_continue)) {
           return;
diff --git a/runtime/stack.h b/runtime/stack.h
index bf61016..5b43848 100644
--- a/runtime/stack.h
+++ b/runtime/stack.h
@@ -36,9 +36,10 @@
 }  // namespace mirror
 
 class Context;
-class ShadowFrame;
 class HandleScope;
+class InlineInfo;
 class ScopedObjectAccess;
+class ShadowFrame;
 class StackVisitor;
 class Thread;
 
@@ -430,15 +431,7 @@
   void WalkStack(bool include_transitions = false)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  mirror::ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    if (cur_shadow_frame_ != nullptr) {
-      return cur_shadow_frame_->GetMethod();
-    } else if (cur_quick_frame_ != nullptr) {
-      return cur_quick_frame_->AsMirrorPtr();
-    } else {
-      return nullptr;
-    }
-  }
+  mirror::ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   bool IsShadowFrame() const {
     return cur_shadow_frame_ != nullptr;
@@ -611,7 +604,7 @@
   }
 
   bool IsInInlinedFrame() const {
-    return false;
+    return current_inlining_depth_ != 0;
   }
 
   uintptr_t GetCurrentQuickFramePc() const {
@@ -703,6 +696,8 @@
 
   void SanityCheckFrame() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  InlineInfo GetCurrentInlineInfo() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   Thread* const thread_;
   const StackWalkKind walk_kind_;
   ShadowFrame* cur_shadow_frame_;
@@ -712,6 +707,9 @@
   size_t num_frames_;
   // Depth of the frame we're currently at.
   size_t cur_depth_;
+  // Current inlining depth of the method we are currently at.
+  // 0 if there is no inlined frame.
+  size_t current_inlining_depth_;
 
  protected:
   Context* const context_;
diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc
index 11e7e44..6a0c07d 100644
--- a/runtime/stack_map.cc
+++ b/runtime/stack_map.cc
@@ -257,21 +257,48 @@
     DumpStackMapHeader(os, i);
     if (stack_map.HasDexRegisterMap(*this)) {
       DexRegisterMap dex_register_map = GetDexRegisterMapOf(stack_map, number_of_dex_registers);
-      // TODO: Display the bit mask of live Dex registers.
-      for (size_t j = 0; j < number_of_dex_registers; ++j) {
-        if (dex_register_map.IsDexRegisterLive(j)) {
-          size_t location_catalog_entry_index = dex_register_map.GetLocationCatalogEntryIndex(
-              j, number_of_dex_registers, number_of_location_catalog_entries);
-          DexRegisterLocation location =
-              dex_register_map.GetDexRegisterLocation(j, number_of_dex_registers, *this);
-          DumpRegisterMapping(
-              os, j, location, "v",
-              "\t[entry " + std::to_string(static_cast<int>(location_catalog_entry_index)) + "]");
-        }
-      }
+      dex_register_map.Dump(os, *this, number_of_dex_registers);
     }
   }
-  // TODO: Dump the stack map's inline information.
+  // TODO: Dump the stack map's inline information? We need to know more from the caller:
+  //       we need to know the number of dex registers for each inlined method.
+}
+
+void DexRegisterMap::Dump(std::ostream& os,
+                          const CodeInfo& code_info,
+                          uint16_t number_of_dex_registers) const {
+  size_t number_of_location_catalog_entries =
+      code_info.GetNumberOfDexRegisterLocationCatalogEntries();
+  // TODO: Display the bit mask of live Dex registers.
+  for (size_t j = 0; j < number_of_dex_registers; ++j) {
+    if (IsDexRegisterLive(j)) {
+      size_t location_catalog_entry_index = GetLocationCatalogEntryIndex(
+          j, number_of_dex_registers, number_of_location_catalog_entries);
+      DexRegisterLocation location = GetDexRegisterLocation(j, number_of_dex_registers, code_info);
+      DumpRegisterMapping(
+          os, j, location, "v",
+          "\t[entry " + std::to_string(static_cast<int>(location_catalog_entry_index)) + "]");
+    }
+  }
+}
+
+void InlineInfo::Dump(std::ostream& os,
+                      const CodeInfo& code_info,
+                      uint16_t number_of_dex_registers[]) const {
+  os << "InlineInfo with depth " << static_cast<uint32_t>(GetDepth()) << "\n";
+
+  for (size_t i = 0; i < GetDepth(); ++i) {
+    os << " At depth " << i
+       << std::hex
+       << " (dex_pc=0x" << GetDexPcAtDepth(i)
+       << ", method_index=0x" << GetMethodIndexAtDepth(i)
+       << ")\n";
+    if (HasDexRegisterMapAtDepth(i)) {
+      DexRegisterMap dex_register_map =
+          code_info.GetDexRegisterMapAtDepth(i, *this, number_of_dex_registers[i]);
+      dex_register_map.Dump(os, code_info, number_of_dex_registers[i]);
+    }
+  }
 }
 
 }  // namespace art
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index f68cafe..16ae772 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -39,47 +39,6 @@
  * their own fields.
  */
 
-/**
- * Inline information for a specific PC. The information is of the form:
- * [inlining_depth, [method_dex reference]+]
- */
-class InlineInfo {
- public:
-  explicit InlineInfo(MemoryRegion region) : region_(region) {}
-
-  uint8_t GetDepth() const {
-    return region_.LoadUnaligned<uint8_t>(kDepthOffset);
-  }
-
-  void SetDepth(uint8_t depth) {
-    region_.StoreUnaligned<uint8_t>(kDepthOffset, depth);
-  }
-
-  uint32_t GetMethodReferenceIndexAtDepth(uint8_t depth) const {
-    return region_.LoadUnaligned<uint32_t>(kFixedSize + depth * SingleEntrySize());
-  }
-
-  void SetMethodReferenceIndexAtDepth(uint8_t depth, uint32_t index) {
-    region_.StoreUnaligned<uint32_t>(kFixedSize + depth * SingleEntrySize(), index);
-  }
-
-  static size_t SingleEntrySize() {
-    return sizeof(uint32_t);
-  }
-
- private:
-  // TODO: Instead of plain types such as "uint8_t", introduce
-  // typedefs (and document the memory layout of InlineInfo).
-  static constexpr int kDepthOffset = 0;
-  static constexpr int kFixedSize = kDepthOffset + sizeof(uint8_t);
-
-  MemoryRegion region_;
-
-  friend class CodeInfo;
-  friend class StackMap;
-  friend class StackMapStream;
-};
-
 // Dex register location container used by DexRegisterMap and StackMapStream.
 class DexRegisterLocation {
  public:
@@ -506,7 +465,8 @@
                       const CodeInfo& code_info) const {
     DexRegisterLocation location =
         GetDexRegisterLocation(dex_register_number, number_of_dex_registers, code_info);
-    DCHECK(location.GetKind() == DexRegisterLocation::Kind::kConstant);
+    DCHECK(location.GetKind() == DexRegisterLocation::Kind::kConstant)
+        << DexRegisterLocation::PrettyDescriptor(location.GetKind());
     return location.GetValue();
   }
 
@@ -641,6 +601,8 @@
     return region_.size();
   }
 
+  void Dump(std::ostream& o, const CodeInfo& code_info, uint16_t number_of_dex_registers) const;
+
  private:
   // Return the index in the Dex register map corresponding to the Dex
   // register number `dex_register_number`.
@@ -675,9 +637,6 @@
  * The information is of the form:
  * [dex_pc, native_pc_offset, dex_register_map_offset, inlining_info_offset, register_mask,
  * stack_mask].
- *
- * Note that register_mask is fixed size, but stack_mask is variable size, depending on the
- * stack size of a method.
  */
 class StackMap {
  public:
@@ -759,6 +718,72 @@
   friend class StackMapStream;
 };
 
+/**
+ * Inline information for a specific PC. The information is of the form:
+ * [inlining_depth, [dex_pc, method_index, dex_register_map_offset]+]
+ */
+class InlineInfo {
+ public:
+  explicit InlineInfo(MemoryRegion region) : region_(region) {}
+
+  uint8_t GetDepth() const {
+    return region_.LoadUnaligned<uint8_t>(kDepthOffset);
+  }
+
+  void SetDepth(uint8_t depth) {
+    region_.StoreUnaligned<uint8_t>(kDepthOffset, depth);
+  }
+
+  uint32_t GetMethodIndexAtDepth(uint8_t depth) const {
+    return region_.LoadUnaligned<uint32_t>(kFixedSize + depth * SingleEntrySize());
+  }
+
+  void SetMethodIndexAtDepth(uint8_t depth, uint32_t index) {
+    region_.StoreUnaligned<uint32_t>(kFixedSize + depth * SingleEntrySize(), index);
+  }
+
+  uint32_t GetDexPcAtDepth(uint8_t depth) const {
+    return region_.LoadUnaligned<uint32_t>(
+        kFixedSize + depth * SingleEntrySize() + sizeof(uint32_t));
+  }
+
+  void SetDexPcAtDepth(uint8_t depth, uint32_t dex_pc) {
+    region_.StoreUnaligned<uint32_t>(
+        kFixedSize + depth * SingleEntrySize() + sizeof(uint32_t), dex_pc);
+  }
+
+  uint32_t GetDexRegisterMapOffsetAtDepth(uint8_t depth) const {
+    return region_.LoadUnaligned<uint32_t>(
+        kFixedSize + depth * SingleEntrySize() + sizeof(uint32_t) + sizeof(uint32_t));
+  }
+
+  void SetDexRegisterMapOffsetAtDepth(uint8_t depth, uint32_t offset) {
+    region_.StoreUnaligned<uint32_t>(
+        kFixedSize + depth * SingleEntrySize() + sizeof(uint32_t) + sizeof(uint32_t), offset);
+  }
+
+  bool HasDexRegisterMapAtDepth(uint8_t depth) const {
+    return GetDexRegisterMapOffsetAtDepth(depth) != StackMap::kNoDexRegisterMap;
+  }
+
+  static size_t SingleEntrySize() {
+    return sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t);
+  }
+
+  void Dump(std::ostream& os, const CodeInfo& info, uint16_t* number_of_dex_registers) const;
+
+ private:
+  // TODO: Instead of plain types such as "uint8_t", introduce
+  // typedefs (and document the memory layout of InlineInfo).
+  static constexpr int kDepthOffset = 0;
+  static constexpr int kFixedSize = kDepthOffset + sizeof(uint8_t);
+
+  MemoryRegion region_;
+
+  friend class CodeInfo;
+  friend class StackMap;
+  friend class StackMapStream;
+};
 
 /**
  * Wrapper around all compiler information collected for a method.
@@ -960,6 +985,17 @@
     return DexRegisterMap(region_.Subregion(offset, size));
   }
 
+  // Return the `DexRegisterMap` pointed by `inline_info` at depth `depth`.
+  DexRegisterMap GetDexRegisterMapAtDepth(uint8_t depth,
+                                          InlineInfo inline_info,
+                                          uint32_t number_of_dex_registers) const {
+    DCHECK(inline_info.HasDexRegisterMapAtDepth(depth));
+    uint32_t offset =
+        GetDexRegisterMapsOffset() + inline_info.GetDexRegisterMapOffsetAtDepth(depth);
+    size_t size = ComputeDexRegisterMapSizeOf(offset, number_of_dex_registers);
+    return DexRegisterMap(region_.Subregion(offset, size));
+  }
+
   InlineInfo GetInlineInfoOf(StackMap stack_map) const {
     DCHECK(stack_map.HasInlineInfo(*this));
     uint32_t offset = stack_map.GetInlineDescriptorOffset(*this) + GetDexRegisterMapsOffset();
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 475fe8b..1b1bc54 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -286,6 +286,13 @@
   }
 }
 
+static bool IsLargeMethod(const DexFile::CodeItem* const code_item) {
+  uint16_t registers_size = code_item->registers_size_;
+  uint32_t insns_size = code_item->insns_size_in_code_units_;
+
+  return registers_size * insns_size > 4*1024*1024;
+}
+
 MethodVerifier::FailureKind MethodVerifier::VerifyMethod(Thread* self, uint32_t method_idx,
                                                          const DexFile* dex_file,
                                                          Handle<mirror::DexCache> dex_cache,
@@ -329,7 +336,8 @@
     uint64_t duration_ns = NanoTime() - start_ns;
     if (duration_ns > MsToNs(100)) {
       LOG(WARNING) << "Verification of " << PrettyMethod(method_idx, *dex_file)
-                   << " took " << PrettyDuration(duration_ns);
+                   << " took " << PrettyDuration(duration_ns)
+                   << (IsLargeMethod(code_item) ? " (large method)" : "");
     }
   }
   return result;
@@ -1211,10 +1219,6 @@
   uint16_t registers_size = code_item_->registers_size_;
   uint32_t insns_size = code_item_->insns_size_in_code_units_;
 
-  if (registers_size * insns_size > 4*1024*1024) {
-    LOG(WARNING) << "warning: method is huge (regs=" << registers_size
-                 << " insns_size=" << insns_size << ")";
-  }
   /* Create and initialize table holding register status */
   reg_table_.Init(kTrackCompilerInterestPoints,
                   insn_flags_.get(),
diff --git a/test/441-checker-inliner/src/Main.java b/test/441-checker-inliner/src/Main.java
index 1c3855f..8894d4e 100644
--- a/test/441-checker-inliner/src/Main.java
+++ b/test/441-checker-inliner/src/Main.java
@@ -19,7 +19,7 @@
   // CHECK-START: void Main.InlineVoid() inliner (before)
   // 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
@@ -31,12 +31,12 @@
 
   // 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:     <<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:                     Return [<<Param>>]
 
   public static int InlineParameter(int a) {
     return returnParameter(a);
@@ -44,12 +44,12 @@
 
   // 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:     <<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:                     Return [<<Param>>]
 
   public static long InlineWideParameter(long a) {
     return returnWideParameter(a);
@@ -57,12 +57,12 @@
 
   // 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:     <<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:                     Return [<<Param>>]
 
   public static Object InlineReferenceParameter(Object o) {
     return returnReferenceParameter(o);
@@ -70,11 +70,11 @@
 
   // CHECK-START: int Main.InlineInt() inliner (before)
   // CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect
-  // CHECK-DAG:                     Return [ <<Result>> ]
+  // CHECK-DAG:                     Return [<<Result>>]
 
   // CHECK-START: int Main.InlineInt() inliner (after)
   // CHECK-DAG:     <<Const4:i\d+>> IntConstant 4
-  // CHECK-DAG:                     Return [ <<Const4>> ]
+  // CHECK-DAG:                     Return [<<Const4>>]
 
   public static int InlineInt() {
     return returnInt();
@@ -82,11 +82,11 @@
 
   // CHECK-START: long Main.InlineWide() inliner (before)
   // CHECK-DAG:     <<Result:j\d+>> InvokeStaticOrDirect
-  // CHECK-DAG:                     Return [ <<Result>> ]
+  // CHECK-DAG:                     Return [<<Result>>]
 
   // CHECK-START: long Main.InlineWide() inliner (after)
   // CHECK-DAG:     <<Const8:j\d+>> LongConstant 8
-  // CHECK-DAG:                     Return [ <<Const8>> ]
+  // CHECK-DAG:                     Return [<<Const8>>]
 
   public static long InlineWide() {
     return returnWide();
@@ -96,13 +96,13 @@
   // 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:                     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:     <<Add:i\d+>>    Add [<<Const3>>,<<Const5>>]
+  // CHECK-DAG:                     Return [<<Add>>]
 
   public static int InlineAdd() {
     return returnAdd(3, 5);
@@ -110,14 +110,14 @@
 
   // CHECK-START: int Main.InlineFieldAccess() inliner (before)
   // CHECK-DAG:     <<After:i\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                     Return [ <<After>> ]
+  // 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:     <<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
@@ -130,19 +130,19 @@
   // 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:     <<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:     <<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 9a2e4fc..c258db9 100644
--- a/test/442-checker-constant-folding/src/Main.java
+++ b/test/442-checker-constant-folding/src/Main.java
@@ -53,12 +53,12 @@
 
   // 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:     <<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:                       Return [<<ConstN42>>]
 
   public static int IntNegation() {
     int x, y;
@@ -75,12 +75,12 @@
   // 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:     <<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:                      Return [<<Const3>>]
 
   public static int IntAddition1() {
     int a, b, c;
@@ -100,14 +100,14 @@
   // 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:     <<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:                      Return [<<Const14>>]
 
   public static int IntAddition2() {
     int a, b, c;
@@ -129,12 +129,12 @@
   // 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:     <<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:                      Return [<<Const4>>]
 
   public static int IntSubtraction() {
     int a, b, c;
@@ -152,12 +152,12 @@
   // 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:     <<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:                      Return [<<Const3>>]
 
   public static long LongAddition() {
     long a, b, c;
@@ -175,12 +175,12 @@
   // 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:     <<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:                      Return [<<Const4>>]
 
   public static long LongSubtraction() {
     long a, b, c;
@@ -197,12 +197,12 @@
   // 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:     <<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:                      If [<<Const1>>]
 
   public static int StaticCondition() {
     int a, b, c;
@@ -227,16 +227,16 @@
   // 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:     <<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:     <<Phi:i\d+>>     Phi [<<Const7>>,<<Const3>>]
+  // CHECK-DAG:                      Return [<<Phi>>]
 
   public static int JumpsAndConditionals(boolean cond) {
     int a, b, c;
@@ -256,14 +256,14 @@
   // 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:     <<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-NOT:                       And
-  // CHECK-DAG:                       Return [ <<Const0>> ]
+  // CHECK-DAG:                       Return [<<Const0>>]
 
   public static int And0(int arg) {
     return arg & 0;
@@ -272,14 +272,14 @@
   // 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:     <<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-NOT:                       Mul
-  // CHECK-DAG:                       Return [ <<Const0>> ]
+  // CHECK-DAG:                       Return [<<Const0>>]
 
   public static long Mul0(long arg) {
     return arg * 0;
@@ -288,13 +288,13 @@
   // 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:     <<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-NOT:                       Or
-  // CHECK-DAG:                       Return [ <<ConstF>> ]
+  // CHECK-DAG:                       Return [<<ConstF>>]
 
   public static int OrAllOnes(int arg) {
     return arg | -1;
@@ -303,14 +303,14 @@
   // 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:     <<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-NOT:                            Rem
-  // CHECK-DAG:                            Return [ <<Const0>> ]
+  // CHECK-DAG:                            Return [<<Const0>>]
 
   public static long Rem0(long arg) {
     return 0 % arg;
@@ -319,13 +319,13 @@
   // 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:     <<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-NOT:                       Rem
-  // CHECK-DAG:                       Return [ <<Const0>> ]
+  // CHECK-DAG:                       Return [<<Const0>>]
 
   public static int Rem1(int arg) {
     return arg % 1;
@@ -334,14 +334,14 @@
   // 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:     <<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-NOT:                            Rem
-  // CHECK-DAG:                            Return [ <<Const0>> ]
+  // CHECK-DAG:                            Return [<<Const0>>]
 
   public static long RemN1(long arg) {
     return arg % -1;
@@ -350,14 +350,14 @@
   // 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:     <<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-NOT:                       Shl
-  // CHECK-DAG:                       Return [ <<Const0>> ]
+  // CHECK-DAG:                       Return [<<Const0>>]
 
   public static int Shl0(int arg) {
     return 0 << arg;
@@ -366,14 +366,14 @@
   // 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:     <<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-NOT:                       Shr
-  // CHECK-DAG:                       Return [ <<Const0>> ]
+  // CHECK-DAG:                       Return [<<Const0>>]
 
   public static long Shr0(int arg) {
     return (long)0 >> arg;
@@ -381,14 +381,14 @@
 
   // 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:     <<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-NOT:                       Sub
-  // CHECK-DAG:                       Return [ <<Const0>> ]
+  // CHECK-DAG:                       Return [<<Const0>>]
 
   public static long SubSameLong(long arg) {
     return arg - arg;
@@ -397,14 +397,14 @@
   // 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:     <<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-NOT:                       UShr
-  // CHECK-DAG:                       Return [ <<Const0>> ]
+  // CHECK-DAG:                       Return [<<Const0>>]
 
   public static int UShr0(int arg) {
     return 0 >>> arg;
@@ -412,14 +412,14 @@
 
   // 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:     <<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-NOT:                       Xor
-  // CHECK-DAG:                       Return [ <<Const0>> ]
+  // CHECK-DAG:                       Return [<<Const0>>]
 
   public static int XorSameInt(int arg) {
     return arg ^ arg;
@@ -430,16 +430,16 @@
   // 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-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-DAG:                       If [<<Const1>>]
 
   // CHECK-START: boolean Main.CmpFloatGreaterThanNaN(float) constant_folding (after)
   // CHECK-NOT:                       Compare
@@ -454,16 +454,16 @@
   // 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-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-DAG:                       If [<<Const1>>]
 
   // CHECK-START: boolean Main.CmpDoubleLessThanNaN(double) constant_folding (after)
   // CHECK-NOT:                       Compare
@@ -475,12 +475,12 @@
 
   // 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-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>> ]
+  // CHECK-DAG:                       Return [<<Const33>>]
 
   public static int ReturnInt33() {
     long imm = 33L;
@@ -489,12 +489,12 @@
 
   // 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-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>> ]
+  // CHECK-DAG:                       Return [<<ConstMax>>]
 
   public static int ReturnIntMax() {
     float imm = 1.0e34f;
@@ -503,12 +503,12 @@
 
   // 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-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>> ]
+  // CHECK-DAG:                       Return [<<Const0>>]
 
   public static int ReturnInt0() {
     double imm = Double.NaN;
@@ -517,12 +517,12 @@
 
   // 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-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>> ]
+  // CHECK-DAG:                       Return [<<Const33>>]
 
   public static long ReturnLong33() {
     int imm = 33;
@@ -531,12 +531,12 @@
 
   // 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-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>> ]
+  // CHECK-DAG:                       Return [<<Const34>>]
 
   public static long ReturnLong34() {
     float imm = 34.0f;
@@ -545,12 +545,12 @@
 
   // 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-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>> ]
+  // CHECK-DAG:                       Return [<<Const0>>]
 
   public static long ReturnLong0() {
     double imm = -Double.NaN;
@@ -559,12 +559,12 @@
 
   // 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-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>> ]
+  // CHECK-DAG:                       Return [<<Const33>>]
 
   public static float ReturnFloat33() {
     int imm = 33;
@@ -573,12 +573,12 @@
 
   // 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-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>> ]
+  // CHECK-DAG:                       Return [<<Const34>>]
 
   public static float ReturnFloat34() {
     long imm = 34L;
@@ -587,12 +587,12 @@
 
   // 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-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>> ]
+  // CHECK-DAG:                       Return [<<Const>>]
 
   public static float ReturnFloat99P25() {
     double imm = 99.25;
@@ -601,12 +601,12 @@
 
   // 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-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>> ]
+  // CHECK-DAG:                       Return [<<Const33>>]
 
   public static double ReturnDouble33() {
     int imm = 33;
@@ -615,12 +615,12 @@
 
   // 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-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>> ]
+  // CHECK-DAG:                       Return [<<Const34>>]
 
   public static double ReturnDouble34() {
     long imm = 34L;
@@ -629,12 +629,12 @@
 
   // 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-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>> ]
+  // CHECK-DAG:                       Return [<<Const>>]
 
   public static double ReturnDouble99P25() {
     float imm = 99.25f;
diff --git a/test/445-checker-licm/src/Main.java b/test/445-checker-licm/src/Main.java
index ce2ab9a..96918d3 100644
--- a/test/445-checker-licm/src/Main.java
+++ b/test/445-checker-licm/src/Main.java
@@ -89,7 +89,7 @@
 
   // CHECK-START: int Main.arrayLength(int[]) licm (before)
   // CHECK-DAG: <<NullCheck:l\d+>> NullCheck loop:{{B\d+}}
-  // CHECK-DAG:                    ArrayLength [ <<NullCheck>> ] loop:{{B\d+}}
+  // CHECK-DAG:                    ArrayLength [<<NullCheck>>] loop:{{B\d+}}
 
   // CHECK-START: int Main.arrayLength(int[]) licm (after)
   // CHECK-NOT:                    NullCheck loop:{{B\d+}}
@@ -97,7 +97,7 @@
 
   // CHECK-START: int Main.arrayLength(int[]) licm (after)
   // CHECK-DAG: <<NullCheck:l\d+>> NullCheck loop:none
-  // CHECK-DAG:                    ArrayLength [ <<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 5d4ddf8..9ed66d6 100644
--- a/test/446-checker-inliner2/src/Main.java
+++ b/test/446-checker-inliner2/src/Main.java
@@ -18,14 +18,14 @@
 
   // CHECK-START: int Main.inlineInstanceCall(Main) inliner (before)
   // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ <<Invoke>> ]
+  // 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:                      Return [<<Field>>]
 
   public static int inlineInstanceCall(Main m) {
     return m.foo();
@@ -39,14 +39,14 @@
 
   // CHECK-START: int Main.inlineNestedCall() inliner (before)
   // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ <<Invoke>> ]
+  // 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:                      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 34faafa..9d022b9 100644
--- a/test/447-checker-inliner3/src/Main.java
+++ b/test/447-checker-inliner3/src/Main.java
@@ -18,7 +18,7 @@
 
   // CHECK-START: int Main.inlineIfThenElse() inliner (before)
   // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ <<Invoke>> ]
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   // CHECK-START: int Main.inlineIfThenElse() inliner (after)
   // CHECK-NOT:                      InvokeStaticOrDirect
diff --git a/test/458-checker-instruction-simplification/src/Main.java b/test/458-checker-instruction-simplification/src/Main.java
index ebad8e5..742210c 100644
--- a/test/458-checker-instruction-simplification/src/Main.java
+++ b/test/458-checker-instruction-simplification/src/Main.java
@@ -53,12 +53,12 @@
   // 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:     <<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:                      Return [<<Arg>>]
 
   // CHECK-START: long Main.Add0(long) instruction_simplifier (after)
   // CHECK-NOT:                        Add
@@ -70,12 +70,12 @@
   // 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:     <<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:                      Return [<<Arg>>]
 
   // CHECK-START: int Main.AndAllOnes(int) instruction_simplifier (after)
   // CHECK-NOT:                      And
@@ -87,12 +87,12 @@
   // 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:     <<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:                      Return [<<Arg>>]
 
   // CHECK-START: long Main.Div1(long) instruction_simplifier (after)
   // CHECK-NOT:                      Div
@@ -104,13 +104,13 @@
   // 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:     <<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:     <<Neg:i\d+>>      Neg [<<Arg>>]
+  // CHECK-DAG:                       Return [<<Neg>>]
 
   // CHECK-START: int Main.DivN1(int) instruction_simplifier (after)
   // CHECK-NOT:                       Div
@@ -122,12 +122,12 @@
   // 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:     <<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:                      Return [<<Arg>>]
 
   // CHECK-START: long Main.Mul1(long) instruction_simplifier (after)
   // CHECK-NOT:                       Mul
@@ -139,13 +139,13 @@
   // 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:     <<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:     <<Neg:i\d+>>      Neg [<<Arg>>]
+  // CHECK-DAG:                       Return [<<Neg>>]
 
   // CHECK-START: int Main.MulN1(int) instruction_simplifier (after)
   // CHECK-NOT:                       Mul
@@ -157,14 +157,14 @@
   // 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:     <<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:     <<Shl:j\d+>>       Shl [<<Arg>>,<<Const7>>]
+  // CHECK-DAG:                        Return [<<Shl>>]
 
   // CHECK-START: long Main.MulPowerOfTwo128(long) instruction_simplifier (after)
   // CHECK-NOT:                        Mul
@@ -176,12 +176,12 @@
   // 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:     <<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:                       Return [<<Arg>>]
 
   // CHECK-START: int Main.Or0(int) instruction_simplifier (after)
   // CHECK-NOT:                       Or
@@ -192,12 +192,12 @@
 
   // 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:     <<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:                        Return [<<Arg>>]
 
   // CHECK-START: long Main.OrSame(long) instruction_simplifier (after)
   // CHECK-NOT:                        Or
@@ -209,12 +209,12 @@
   // 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:     <<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:                       Return [<<Arg>>]
 
   // CHECK-START: int Main.Shl0(int) instruction_simplifier (after)
   // CHECK-NOT:                       Shl
@@ -226,13 +226,13 @@
   // 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:     <<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:     <<Add:i\d+>>      Add [<<Arg>>,<<Arg>>]
+  // CHECK-DAG:                       Return [<<Add>>]
 
   // CHECK-START: int Main.Shl1(int) instruction_simplifier (after)
   // CHECK-NOT:                       Shl
@@ -244,12 +244,12 @@
   // 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:     <<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:                       Return [<<Arg>>]
 
   // CHECK-START: long Main.Shr0(long) instruction_simplifier (after)
   // CHECK-NOT:                       Shr
@@ -261,12 +261,12 @@
   // 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:     <<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:                       Return [<<Arg>>]
 
   // CHECK-START: long Main.Sub0(long) instruction_simplifier (after)
   // CHECK-NOT:                       Sub
@@ -278,13 +278,13 @@
   // 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:     <<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:     <<Neg:i\d+>>      Neg [<<Arg>>]
+  // CHECK-DAG:                       Return [<<Neg>>]
 
   // CHECK-START: int Main.SubAliasNeg(int) instruction_simplifier (after)
   // CHECK-NOT:                       Sub
@@ -296,12 +296,12 @@
   // 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:     <<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:                       Return [<<Arg>>]
 
   // CHECK-START: long Main.UShr0(long) instruction_simplifier (after)
   // CHECK-NOT:                       UShr
@@ -313,12 +313,12 @@
   // 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:     <<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:                       Return [<<Arg>>]
 
   // CHECK-START: int Main.Xor0(int) instruction_simplifier (after)
   // CHECK-NOT:                       Xor
@@ -330,13 +330,13 @@
   // 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:     <<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:     <<Not:i\d+>>      Not [<<Arg>>]
+  // CHECK-DAG:                       Return [<<Not>>]
 
   // CHECK-START: int Main.XorAllOnes(int) instruction_simplifier (after)
   // CHECK-NOT:                       Xor
@@ -355,18 +355,18 @@
   // 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:     <<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-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;
@@ -386,32 +386,32 @@
   // 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:     <<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:     <<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:     <<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;
@@ -431,24 +431,24 @@
   // -------------- 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:     <<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:     <<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
 
@@ -471,15 +471,15 @@
   // 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:     <<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:     <<Sub:j\d+>>      Sub [<<Arg2>>,<<Arg1>>]
+  // CHECK-DAG:                       Return [<<Sub>>]
 
   // CHECK-START: long Main.AddNeg1(long, long) instruction_simplifier (after)
   // CHECK-NOT:                       Neg
@@ -501,20 +501,20 @@
   // 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:     <<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:     <<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
@@ -531,13 +531,13 @@
 
   // 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:     <<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:                       Return [<<Arg>>]
 
   // CHECK-START: long Main.NegNeg1(long) instruction_simplifier (after)
   // CHECK-NOT:                       Neg
@@ -555,15 +555,15 @@
 
   // 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:     <<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:     <<Sub:i\d+>>      Sub [<<Arg>>,<<Arg>>]
+  // CHECK-DAG:                       Return [<<Sub>>]
 
   // CHECK-START: int Main.NegNeg2(int) instruction_simplifier (after)
   // CHECK-NOT:                       Neg
@@ -573,7 +573,7 @@
   // 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;
@@ -590,13 +590,13 @@
   // 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:     <<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:                       Return [<<Arg>>]
 
   // CHECK-START: long Main.NegNeg3(long) instruction_simplifier (after)
   // CHECK-NOT:                       Neg
@@ -615,15 +615,15 @@
   // 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:     <<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:     <<Sub:i\d+>>      Sub [<<Arg2>>,<<Arg1>>]
+  // CHECK-DAG:                       Return [<<Sub>>]
 
   // CHECK-START: int Main.NegSub1(int, int) instruction_simplifier (after)
   // CHECK-NOT:                       Neg
@@ -645,20 +645,20 @@
   // 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:     <<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:     <<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;
@@ -673,13 +673,13 @@
   // 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:     <<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:                       Return [<<Arg>>]
 
   // CHECK-START: long Main.NotNot1(long) instruction_simplifier (after)
   // CHECK-NOT:                       Xor
@@ -691,16 +691,16 @@
   // 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:     <<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:     <<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
@@ -718,16 +718,16 @@
   // 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:     <<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:     <<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
@@ -749,20 +749,20 @@
   // 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:     <<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:     <<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
@@ -783,22 +783,22 @@
   // -------------- 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:     <<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:     <<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
 
@@ -814,12 +814,12 @@
   // 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:     <<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:                       If [<<Arg>>]
 
   public static int EqualTrueRhs(boolean arg) {
     return (arg != true) ? 3 : 5;
@@ -828,12 +828,12 @@
   // 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:     <<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:                       If [<<Arg>>]
 
   public static int EqualTrueLhs(boolean arg) {
     return (true != arg) ? 3 : 5;
@@ -842,13 +842,13 @@
   // 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:     <<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:     <<NotArg:z\d+>>   BooleanNot [<<Arg>>]
+  // CHECK-DAG:                       If [<<NotArg>>]
 
   public static int EqualFalseRhs(boolean arg) {
     return (arg != false) ? 3 : 5;
@@ -857,13 +857,13 @@
   // 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:     <<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:     <<NotArg:z\d+>>   BooleanNot [<<Arg>>]
+  // CHECK-DAG:                       If [<<NotArg>>]
 
   public static int EqualFalseLhs(boolean arg) {
     return (false != arg) ? 3 : 5;
@@ -872,13 +872,13 @@
   // 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:     <<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:     <<NotArg:z\d+>>   BooleanNot [<<Arg>>]
+  // CHECK-DAG:                       If [<<NotArg>>]
 
   public static int NotEqualTrueRhs(boolean arg) {
     return (arg == true) ? 3 : 5;
@@ -887,13 +887,13 @@
   // 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:     <<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:     <<NotArg:z\d+>>   BooleanNot [<<Arg>>]
+  // CHECK-DAG:                       If [<<NotArg>>]
 
   public static int NotEqualTrueLhs(boolean arg) {
     return (true == arg) ? 3 : 5;
@@ -902,12 +902,12 @@
   // 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:     <<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:                       If [<<Arg>>]
 
   public static int NotEqualFalseRhs(boolean arg) {
     return (arg == false) ? 3 : 5;
@@ -916,12 +916,12 @@
   // 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:     <<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:                       If [<<Arg>>]
 
   public static int NotEqualFalseLhs(boolean arg) {
     return (false == arg) ? 3 : 5;
@@ -935,14 +935,14 @@
 
   // 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:     <<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:                        BooleanNot [<<Arg>>]
+  // CHECK-DAG:                        Return [<<Arg>>]
 
   // CHECK-START: boolean Main.NotNotBool(boolean) instruction_simplifier_after_types (after)
   // CHECK:                            BooleanNot
@@ -959,14 +959,14 @@
   // 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:      <<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:      <<Mul:f\d+>>      Mul [<<Arg>>,<<ConstP5>>]
+  // CHECK-DAG:                        Return [<<Mul>>]
 
   // CHECK-START: float Main.Div2(float) instruction_simplifier (after)
   // CHECK-NOT:                        Div
@@ -978,14 +978,14 @@
   // 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:      <<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:      <<Mul:d\d+>>      Mul [<<Arg>>,<<ConstP5>>]
+  // CHECK-DAG:                        Return [<<Mul>>]
 
   // CHECK-START: double Main.Div2(double) instruction_simplifier (after)
   // CHECK-NOT:                        Div
@@ -996,14 +996,14 @@
   // 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:      <<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:      <<Mul:f\d+>>      Mul [<<Arg>>,<<ConstM4>>]
+  // CHECK-DAG:                        Return [<<Mul>>]
 
   // CHECK-START: float Main.DivMP25(float) instruction_simplifier (after)
   // CHECK-NOT:                        Div
@@ -1015,14 +1015,14 @@
   // 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:      <<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:      <<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/462-checker-inlining-across-dex-files/src/Main.java b/test/462-checker-inlining-across-dex-files/src/Main.java
index 5ebf3d1..218c7ce 100644
--- a/test/462-checker-inlining-across-dex-files/src/Main.java
+++ b/test/462-checker-inlining-across-dex-files/src/Main.java
@@ -34,14 +34,14 @@
 
   // CHECK-START: int Main.inlineReturnIntMethod() inliner (before)
   // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ <<Invoke>> ]
+  // 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:                      Return [<<Const38>>]
 
   public static int inlineReturnIntMethod() {
     return OtherDex.returnIntMethod();
@@ -49,11 +49,11 @@
 
   // CHECK-START: int Main.dontInlineOtherDexStatic() inliner (before)
   // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ <<Invoke>> ]
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   // CHECK-START: int Main.dontInlineOtherDexStatic() inliner (after)
   // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ <<Invoke>> ]
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   public static int dontInlineOtherDexStatic() {
     return OtherDex.returnOtherDexStatic();
@@ -61,14 +61,14 @@
 
   // CHECK-START: int Main.inlineMainStatic() inliner (before)
   // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ <<Invoke>> ]
+  // 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:                      Return [<<Static>>]
 
   public static int inlineMainStatic() {
     return OtherDex.returnMainStatic();
@@ -76,11 +76,11 @@
 
   // CHECK-START: int Main.dontInlineRecursiveCall() inliner (before)
   // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ <<Invoke>> ]
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   // CHECK-START: int Main.dontInlineRecursiveCall() inliner (after)
   // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ <<Invoke>> ]
+  // CHECK-DAG:                      Return [<<Invoke>>]
 
   public static int dontInlineRecursiveCall() {
     return OtherDex.recursiveCall();
@@ -88,11 +88,11 @@
 
   // CHECK-START: java.lang.String Main.dontInlineReturnString() inliner (before)
   // CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ <<Invoke>> ]
+  // 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:                      Return [<<Invoke>>]
 
   public static String dontInlineReturnString() {
     return OtherDex.returnString();
@@ -100,11 +100,11 @@
 
   // CHECK-START: java.lang.Class Main.dontInlineOtherDexClass() inliner (before)
   // CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ <<Invoke>> ]
+  // 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:                      Return [<<Invoke>>]
 
   public static Class dontInlineOtherDexClass() {
     return OtherDex.returnOtherDexClass();
@@ -112,14 +112,16 @@
 
   // CHECK-START: java.lang.Class Main.inlineMainClass() inliner (before)
   // CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ <<Invoke>> ]
+  // 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: There are two LoadClass instructions. We obtain the correct
+  //       instruction id by matching the Return's input list first.
 
   public static Class inlineMainClass() {
     return OtherDex.returnMainClass();
@@ -127,11 +129,11 @@
 
   // CHECK-START: java.lang.Class Main.dontInlineOtherDexClassStaticCall() inliner (before)
   // CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ <<Invoke>> ]
+  // 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:                      Return [<<Invoke>>]
 
   public static Class dontInlineOtherDexClassStaticCall() {
     return OtherDex.returnOtherDexClassStaticCall();
@@ -139,14 +141,16 @@
 
   // CHECK-START: java.lang.Class Main.inlineOtherDexCallingMain() inliner (before)
   // CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ <<Invoke>> ]
+  // 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: There are two LoadClass instructions. We obtain the correct
+  //       instruction id by matching the Return's input list first.
 
   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 3f3110f..e237448 100644
--- a/test/463-checker-boolean-simplifier/src/Main.java
+++ b/test/463-checker-boolean-simplifier/src/Main.java
@@ -41,9 +41,9 @@
   // 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:                       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
@@ -54,8 +54,8 @@
   // 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:     <<NotParam:z\d+>> BooleanNot [<<Param>>]
+  // CHECK-DAG:                       Return [<<NotParam>>]
 
   // CHECK-START: boolean Main.BooleanNot(boolean) boolean_simplifier (after)
   // CHECK-NOT:                       If
@@ -79,18 +79,18 @@
   // 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:     <<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:     <<Cond:z\d+>>     GreaterThan [<<ParamX>>,<<ParamY>>]
+  // CHECK-DAG:                       Return [<<Cond>>]
 
   public static boolean GreaterThan(int x, int y) {
     return (x <= y) ? false : true;
@@ -106,18 +106,18 @@
   // 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:     <<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:     <<Cond:z\d+>>     LessThan [<<ParamX>>,<<ParamY>>]
+  // CHECK-DAG:                       Return [<<Cond>>]
 
   // CHECK-START: boolean Main.LessThan(int, int) boolean_simplifier (after)
   // CHECK-NOT:                       GreaterThanOrEqual
@@ -137,25 +137,25 @@
   // 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:     <<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:     <<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);
@@ -165,18 +165,18 @@
   // 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:     <<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:                       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 626823e..e451f70 100644
--- a/test/464-checker-inline-sharpen-calls/src/Main.java
+++ b/test/464-checker-inline-sharpen-calls/src/Main.java
@@ -32,14 +32,14 @@
 
   // CHECK-START: int Main.inlineSharpenStringInvoke() inliner (before)
   // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [ <<Invoke>> ]
+  // 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:                      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 b712715..ac2863c 100644
--- a/test/465-checker-clinit-gvn/src/Main.java
+++ b/test/465-checker-clinit-gvn/src/Main.java
@@ -28,13 +28,13 @@
 
   // CHECK-START: int Main.accessTwoStatics() GVN (before)
   // CHECK-DAG:     <<Class1:l\d+>>  LoadClass
-  // CHECK-DAG:                      ClinitCheck [ <<Class1>> ]
+  // CHECK-DAG:                      ClinitCheck [<<Class1>>]
   // CHECK-DAG:     <<Class2:l\d+>>  LoadClass
-  // CHECK-DAG:                      ClinitCheck [ <<Class2>> ]
+  // CHECK-DAG:                      ClinitCheck [<<Class2>>]
 
   // CHECK-START: int Main.accessTwoStatics() GVN (after)
   // CHECK-DAG:     <<Class:l\d+>>   LoadClass
-  // CHECK-DAG:                      ClinitCheck [ <<Class>> ]
+  // CHECK-DAG:                      ClinitCheck [<<Class>>]
   // CHECK-NOT:                      ClinitCheck
 
   public static int accessTwoStatics() {
@@ -43,13 +43,13 @@
 
   // CHECK-START: int Main.accessTwoStaticsCallInBetween() GVN (before)
   // CHECK-DAG:     <<Class1:l\d+>>  LoadClass
-  // CHECK-DAG:                      ClinitCheck [ <<Class1>> ]
+  // CHECK-DAG:                      ClinitCheck [<<Class1>>]
   // CHECK-DAG:     <<Class2:l\d+>>  LoadClass
-  // CHECK-DAG:                      ClinitCheck [ <<Class2>> ]
+  // CHECK-DAG:                      ClinitCheck [<<Class2>>]
 
   // CHECK-START: int Main.accessTwoStaticsCallInBetween() GVN (after)
   // CHECK-DAG:     <<Class:l\d+>>   LoadClass
-  // CHECK-DAG:                      ClinitCheck [ <<Class>> ]
+  // CHECK-DAG:                      ClinitCheck [<<Class>>]
   // CHECK-NOT:                      ClinitCheck
 
   public static int accessTwoStaticsCallInBetween() {
diff --git a/test/468-checker-bool-simplifier-regression/smali/TestCase.smali b/test/468-checker-bool-simplifier-regression/smali/TestCase.smali
index 0cb5313..33e6dc3 100644
--- a/test/468-checker-bool-simplifier-regression/smali/TestCase.smali
+++ b/test/468-checker-bool-simplifier-regression/smali/TestCase.smali
@@ -22,14 +22,14 @@
 # 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-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>> ]
+# CHECK-DAG:     <<Not:z\d+>>      BooleanNot [<<Value>>]
+# CHECK-DAG:                       Return [<<Not>>]
 
 .method public static testCase()Z
     .registers 2
diff --git a/test/474-checker-boolean-input/src/Main.java b/test/474-checker-boolean-input/src/Main.java
index a395ff9..490f7f9 100644
--- a/test/474-checker-boolean-input/src/Main.java
+++ b/test/474-checker-boolean-input/src/Main.java
@@ -29,7 +29,7 @@
 
   // CHECK-START: boolean Main.TestPhiAsBoolean(int) boolean_simplifier (after)
   // CHECK-DAG:     <<Phi:i\d+>>     Phi
-  // CHECK-DAG:                      BooleanNot [ <<Phi>> ]
+  // CHECK-DAG:                      BooleanNot [<<Phi>>]
 
   public static boolean f1;
   public static boolean f2;
@@ -49,7 +49,7 @@
 
   // CHECK-START: boolean Main.TestAndAsBoolean(boolean, boolean) boolean_simplifier (after)
   // CHECK-DAG:     <<And:i\d+>>     And
-  // CHECK-DAG:                      BooleanNot [ <<And>> ]
+  // CHECK-DAG:                      BooleanNot [<<And>>]
 
   public static boolean InlineAnd(boolean x, boolean y) {
     return x & y;
@@ -66,7 +66,7 @@
 
   // CHECK-START: boolean Main.TestOrAsBoolean(boolean, boolean) boolean_simplifier (after)
   // CHECK-DAG:     <<Or:i\d+>>      Or
-  // CHECK-DAG:                      BooleanNot [ <<Or>> ]
+  // CHECK-DAG:                      BooleanNot [<<Or>>]
 
   public static boolean InlineOr(boolean x, boolean y) {
     return x | y;
@@ -83,7 +83,7 @@
 
   // CHECK-START: boolean Main.TestXorAsBoolean(boolean, boolean) boolean_simplifier (after)
   // CHECK-DAG:     <<Xor:i\d+>>     Xor
-  // CHECK-DAG:                      BooleanNot [ <<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 769ae20..75cb1d7 100644
--- a/test/476-checker-ctor-memory-barrier/src/Main.java
+++ b/test/476-checker-ctor-memory-barrier/src/Main.java
@@ -14,6 +14,7 @@
 * limitations under the License.
 */
 
+// TODO: Add more tests after we can inline functions with calls.
 
 class ClassWithoutFinals {
   // CHECK-START: void ClassWithoutFinals.<init>() register (after)
@@ -80,6 +81,20 @@
     super(cond);
     // should not inline the super constructor
   }
+
+  // CHECK-START: void InheritFromClassWithFinals.<init>(int) register (after)
+  // CHECK:     MemoryBarrier kind:StoreStore
+  // CHECK:     MemoryBarrier kind:StoreStore
+  // CHECK:     ReturnVoid
+
+  // CHECK-START: void InheritFromClassWithFinals.<init>(int) register (after)
+  // CHECK-NOT: InvokeStaticOrDirect
+  public InheritFromClassWithFinals(int unused) {
+    // Should inline the super constructor and insert a memory barrier.
+
+    // Should inline the new instance call and insert another memory barrier.
+    new InheritFromClassWithFinals();
+  }
 }
 
 class HaveFinalsAndInheritFromClassWithFinals extends ClassWithFinals {
@@ -87,14 +102,13 @@
 
   // CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>() register (after)
   // CHECK:     MemoryBarrier kind:StoreStore
-  // CHECK:     MemoryBarrier kind:StoreStore
   // CHECK-NOT: {{.*}}
   // CHECK:     ReturnVoid
 
   // CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>() register (after)
   // CHECK-NOT: InvokeStaticOrDirect
   public HaveFinalsAndInheritFromClassWithFinals() {
-    // Should inline the super constructor.
+    // Should inline the super constructor and remove the memory barrier.
     y = 0;
   }
 
@@ -108,6 +122,25 @@
     // should not inline the super constructor
     y = 0;
   }
+
+  // CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>(int) register (after)
+  // CHECK:     MemoryBarrier kind:StoreStore
+  // CHECK:     MemoryBarrier kind:StoreStore
+  // CHECK:     MemoryBarrier kind:StoreStore
+  // CHECK-NOT: {{.*}}
+  // CHECK:     ReturnVoid
+
+  // CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>(int) register (after)
+  // CHECK-NOT: InvokeStaticOrDirect
+  public HaveFinalsAndInheritFromClassWithFinals(int unused) {
+    // Should inline the super constructor and keep just one memory barrier.
+    y = 0;
+
+    // Should inline new instance and keep one barrier.
+    new HaveFinalsAndInheritFromClassWithFinals();
+    // Should inline new instance and keep one barrier.
+    new InheritFromClassWithFinals();
+  }
 }
 
 public class Main {
@@ -121,27 +154,51 @@
     return new ClassWithFinals(false);
   }
 
-  // CHECK-START: ClassWithFinals Main.inlineConstructorBarrier() register (after)
+  // CHECK-START: void Main.inlineNew() register (after)
   // CHECK:     MemoryBarrier kind:StoreStore
   // CHECK-NOT: {{.*}}
-  // CHECK:     Return
+  // CHECK:     ReturnVoid
 
-  // CHECK-START: ClassWithFinals Main.inlineConstructorBarrier() register (after)
+  // CHECK-START: void Main.inlineNew() register (after)
   // CHECK-NOT: InvokeStaticOrDirect
-  public static ClassWithFinals inlineConstructorBarrier() {
-    return new ClassWithFinals();
+  public static void inlineNew() {
+    new ClassWithFinals();
   }
 
-  // CHECK-START: InheritFromClassWithFinals Main.doubleInlineConstructorBarrier() register (after)
+  // CHECK-START: void Main.inlineNew1() register (after)
   // CHECK:     MemoryBarrier kind:StoreStore
   // CHECK-NOT: {{.*}}
-  // CHECK:     Return
+  // CHECK:     ReturnVoid
 
-  // CHECK-START: InheritFromClassWithFinals Main.doubleInlineConstructorBarrier() register (after)
+  // CHECK-START: void Main.inlineNew1() register (after)
   // CHECK-NOT: InvokeStaticOrDirect
-  public static InheritFromClassWithFinals doubleInlineConstructorBarrier() {
-    return new InheritFromClassWithFinals();
+  public static void inlineNew1() {
+    new InheritFromClassWithFinals();
   }
 
-  public static void main(String[] args) {  }
+  // CHECK-START: void Main.inlineNew2() register (after)
+  // CHECK:     MemoryBarrier kind:StoreStore
+  // CHECK-NOT: {{.*}}
+  // CHECK:     ReturnVoid
+
+  // CHECK-START: void Main.inlineNew2() register (after)
+  // CHECK-NOT: InvokeStaticOrDirect
+  public static void inlineNew2() {
+    new HaveFinalsAndInheritFromClassWithFinals();
+  }
+
+  // CHECK-START: void Main.inlineNew3() register (after)
+  // CHECK:     MemoryBarrier kind:StoreStore
+  // CHECK:     MemoryBarrier kind:StoreStore
+  // CHECK-NOT: {{.*}}
+  // CHECK:     ReturnVoid
+
+  // CHECK-START: void Main.inlineNew3() register (after)
+  // CHECK-NOT: InvokeStaticOrDirect
+  public static void inlineNew3() {
+    new HaveFinalsAndInheritFromClassWithFinals();
+    new HaveFinalsAndInheritFromClassWithFinals();
+  }
+
+  public static void main(String[] args) {}
 }
diff --git a/test/478-checker-clinit-check-pruning/src/Main.java b/test/478-checker-clinit-check-pruning/src/Main.java
index b36b7d6..61199a7 100644
--- a/test/478-checker-clinit-check-pruning/src/Main.java
+++ b/test/478-checker-clinit-check-pruning/src/Main.java
@@ -25,12 +25,12 @@
 
   // 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:     <<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:     <<ClinitCheck:l\d+>>  ClinitCheck [<<LoadClass>>]
 
   // CHECK-START: void Main.invokeStaticInlined() inliner (after)
   // CHECK-NOT:                           InvokeStaticOrDirect
@@ -68,13 +68,13 @@
 
   // 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:     <<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:     <<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 dda1a43..b76755e 100644
--- a/test/480-checker-dead-blocks/src/Main.java
+++ b/test/480-checker-dead-blocks/src/Main.java
@@ -34,16 +34,16 @@
   // 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:     <<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
@@ -64,16 +64,16 @@
   // 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:     <<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
@@ -126,7 +126,7 @@
 
   // CHECK-START: int Main.testDeadLoop(int) dead_code_elimination_final (after)
   // CHECK-DAG:     <<Arg:i\d+>>     ParameterValue
-  // CHECK-DAG:                      Return [ <<Arg>> ]
+  // CHECK-DAG:                      Return [<<Arg>>]
 
   // CHECK-START: int Main.testDeadLoop(int) dead_code_elimination_final (after)
   // CHECK-NOT:                      If
@@ -146,7 +146,7 @@
 
   // CHECK-START: int Main.testUpdateLoopInformation(int) dead_code_elimination_final (after)
   // CHECK-DAG:     <<Arg:i\d+>>     ParameterValue
-  // CHECK-DAG:                      Return [ <<Arg>> ]
+  // 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 334792e..0ed9267 100644
--- a/test/482-checker-loop-back-edge-use/src/Main.java
+++ b/test/482-checker-loop-back-edge-use/src/Main.java
@@ -18,14 +18,14 @@
 public class Main {
 
   // CHECK-START: void Main.loop1(boolean) liveness (after)
-  // CHECK:         ParameterValue  liveness:2  ranges:[ 2-22 ] uses:[ 17 22 ]
+  // 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:         ParameterValue  liveness:2  ranges:{[2,42)} uses:[33,38,42]
   // CHECK:         Goto            liveness:36
   // CHECK:         Goto            liveness:40
   public static void loop2(boolean incoming) {
@@ -36,7 +36,7 @@
   }
 
   // CHECK-START: void Main.loop3(boolean) liveness (after)
-  // CHECK:         ParameterValue  liveness:2  ranges:[ 2-60 ] uses:[ 56 60 ]
+  // CHECK:         ParameterValue  liveness:2  ranges:{[2,60)} uses:[56,60]
   // CHECK:         Goto            liveness:58
 
   // CHECK-START: void Main.loop3(boolean) liveness (after)
@@ -50,7 +50,7 @@
   }
 
   // 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
@@ -63,7 +63,7 @@
   }
 
   // CHECK-START: void Main.loop5(boolean) liveness (after)
-  // CHECK:         ParameterValue  liveness:2  ranges:[ 2-50 ] uses:[ 33 42 46 50 ]
+  // 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) {
@@ -76,7 +76,7 @@
   }
 
   // CHECK-START: void Main.loop6(boolean) liveness (after)
-  // CHECK          ParameterValue  liveness:2  ranges:[ 2-46 ] uses:[ 24 46 ]
+  // CHECK          ParameterValue  liveness:2  ranges:{[2,46)} uses:[24,46]
   // CHECK:         Goto            liveness:44
 
   // CHECK-START: void Main.loop6(boolean) liveness (after)
@@ -90,7 +90,7 @@
   }
 
   // CHECK-START: void Main.loop7(boolean) liveness (after)
-  // CHECK:         ParameterValue  liveness:2  ranges:[ 2-50 ] uses:[ 32 41 46 50 ]
+  // 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) {
@@ -102,7 +102,7 @@
   }
 
   // CHECK-START: void Main.loop8() liveness (after)
-  // CHECK:         StaticFieldGet  liveness:12 ranges:[ 12-44 ] uses:[ 35 40 44 ]
+  // CHECK:         StaticFieldGet  liveness:12 ranges:{[12,44)} uses:[35,40,44]
   // CHECK:         Goto            liveness:38
   // CHECK:         Goto            liveness:42
   public static void loop8() {
@@ -114,7 +114,7 @@
   }
 
   // CHECK-START: void Main.loop9() liveness (after)
-  // CHECK:         StaticFieldGet  liveness:22 ranges:[ 22-36 ] uses:[ 31 36 ]
+  // CHECK:         StaticFieldGet  liveness:22 ranges:{[22,36)} uses:[31,36]
   // CHECK:         Goto            liveness:38
   public static void loop9() {
     while (Runtime.getRuntime() != null) {
diff --git a/test/485-checker-dce-loop-update/smali/TestCase.smali b/test/485-checker-dce-loop-update/smali/TestCase.smali
index bdc4038..487a5df 100644
--- a/test/485-checker-dce-loop-update/smali/TestCase.smali
+++ b/test/485-checker-dce-loop-update/smali/TestCase.smali
@@ -29,21 +29,21 @@
 # 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-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
+# 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
@@ -80,24 +80,24 @@
 # 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-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
+# 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
@@ -137,15 +137,15 @@
 # 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-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
@@ -153,13 +153,13 @@
 # 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
+# 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
@@ -205,19 +205,19 @@
 # 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>>
+# 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:     <<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-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
@@ -227,18 +227,17 @@
 # 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:     <<PhiZ1:i\d+>> Phi [ <<ArgZ>> <<PhiZ1>> ]                   loop:<<HeaderY>>
-# CHECK-DAG:                    If [ <<ArgY>> ]                              loop:<<HeaderY>>
-# CHECK-DAG:     <<Add7>>       Add [ <<PhiX>> <<Cst7>> ]                    loop:<<HeaderY>>
+# 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:     <<PhiZ2:i\d+>> Phi [ <<PhiZ1>> <<XorZ:i\d+>> ]              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:     <<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
+# CHECK-DAG:                    Return [<<PhiX>>]                          loop:none
 
 .method public static testInnerLoop(IZZ)I
   .registers 4
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/MultiDexModifiedSecondary/Main.java b/test/MultiDexModifiedSecondary/Main.java
new file mode 100644
index 0000000..659dba9
--- /dev/null
+++ b/test/MultiDexModifiedSecondary/Main.java
@@ -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.
+ */
+
+class Main {
+    public static void main(String args[]) {
+      Second second = new Second();
+      System.out.println(second.getSecond());
+    }
+}
diff --git a/test/MultiDexModifiedSecondary/README.txt b/test/MultiDexModifiedSecondary/README.txt
new file mode 100644
index 0000000..4cf3a56
--- /dev/null
+++ b/test/MultiDexModifiedSecondary/README.txt
@@ -0,0 +1,4 @@
+MultiDexModifiedSecondary is designed to result in a multidex file that has
+the same classes.dex file as MultiDex, but a different classes2.dex.
+
+This is used in the OatFileAssistantTest.MultiDexSecondaryOutOfDate gtest.
diff --git a/test/MultiDexModifiedSecondary/Second.java b/test/MultiDexModifiedSecondary/Second.java
new file mode 100644
index 0000000..3555a7f
--- /dev/null
+++ b/test/MultiDexModifiedSecondary/Second.java
@@ -0,0 +1,25 @@
+/*
+ * 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 Second {
+  public String getThird() {
+    return "I Third That.";
+  }
+
+  public String getSecond() {
+    return "I Second That.";
+  }
+}
diff --git a/test/MultiDexModifiedSecondary/main.jpp b/test/MultiDexModifiedSecondary/main.jpp
new file mode 100644
index 0000000..a5d7a6c
--- /dev/null
+++ b/test/MultiDexModifiedSecondary/main.jpp
@@ -0,0 +1,3 @@
+main:
+  @@com.android.jack.annotations.ForceInMainDex
+  class Main
diff --git a/test/MultiDexModifiedSecondary/main.list b/test/MultiDexModifiedSecondary/main.list
new file mode 100644
index 0000000..44ba78e
--- /dev/null
+++ b/test/MultiDexModifiedSecondary/main.list
@@ -0,0 +1 @@
+Main.class
diff --git a/test/run-test b/test/run-test
index 239681f..54c6bbd 100755
--- a/test/run-test
+++ b/test/run-test
@@ -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/README b/tools/checker/README
index 2763948..858a773 100644
--- a/tools/checker/README
+++ b/tools/checker/README
@@ -47,7 +47,7 @@
 
   // CHECK-START: int MyClass.MyMethod() constant_folding (after)
   // CHECK:         <<ID:i\d+>>  IntConstant {{11|22}}
-  // CHECK:                      Return [ <<ID>> ]
+  // 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
diff --git a/tools/checker/common/immutables.py b/tools/checker/common/immutables.py
new file mode 100644
index 0000000..e016867
--- /dev/null
+++ b/tools/checker/common/immutables.py
@@ -0,0 +1,25 @@
+# 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 ImmutableDict(dict):
+  def __setitem__(self, key, value):
+    raise RuntimeError("Cannot modify ImmutableDict")
+
+  def __delitem__(self, key):
+    raise RuntimeError("Cannot modify ImmutableDict")
+
+  def copyWith(self, key, value):
+    newDict = ImmutableDict(self)
+    dict.__setitem__(newDict, key, value)
+    return newDict
diff --git a/tools/checker/match/file.py b/tools/checker/match/file.py
index 2ed4aa7..116fe9a 100644
--- a/tools/checker/match/file.py
+++ b/tools/checker/match/file.py
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from common.immutables                import ImmutableDict
 from common.logger                    import Logger
 from file_format.c1visualizer.struct  import C1visualizerFile, C1visualizerPass
 from file_format.checker.struct       import CheckerFile, TestCase, TestAssertion
@@ -112,7 +113,7 @@
       responsible for running the checks in the right order and scope, and
       for propagating the variable state between the check lines.
   """
-  varState = {}
+  varState = ImmutableDict()
   checkLines = checkGroup.assertions
   outputLines = outputGroup.body
   startLineNo = outputGroup.startLineNo
diff --git a/tools/checker/match/line.py b/tools/checker/match/line.py
index f0253c3..711d814 100644
--- a/tools/checker/match/line.py
+++ b/tools/checker/match/line.py
@@ -13,77 +13,84 @@
 # limitations under the License.
 
 from common.logger              import Logger
-from file_format.checker.struct import TestAssertion, RegexExpression
+from file_format.checker.struct import 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 headAndTail(list):
+  return list[0], list[1:]
 
-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.
+def splitAtSeparators(expressions):
+  """ Splits a list of RegexExpressions at separators. """
+  splitExpressions = []
+  wordStart = 0
+  for index, expression in enumerate(expressions):
+    if expression.variant == RegexExpression.Variant.Separator:
+      splitExpressions.append(expressions[wordStart:index])
+      wordStart = index + 1
+  splitExpressions.append(expressions[wordStart:])
+  return splitExpressions
 
-  An exception is raised if a referenced variable is undefined.
+def matchWords(checkerWord, stringWord, variables, pos):
+  """ Attempts to match a list of RegexExpressions against a string.
+      Returns updated variable dictionary if successful and None otherwise.
   """
-  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
+  for expression in checkerWord:
+    # If `expression` is a variable reference, replace it with the value.
+    if expression.variant == RegexExpression.Variant.VarRef:
+      if expression.name in variables:
+        pattern = re.escape(variables[expression.name])
       else:
-        matchStart += 1
+        Logger.testFailed("Multiple definitions of variable \"{}\"".format(expression.name),
+                          pos.fileName, pos.lineNo)
+    else:
+      pattern = expression.pattern
 
-    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]
+    # Match the expression's regex pattern against the remainder of the word.
+    # Note: re.match will succeed only if matched from the beginning.
+    match = re.match(pattern, stringWord)
+    if not match:
+      return None
 
-    matchStart = matchEnd
-    isAfterSeparator = False
+    # If `expression` was a variable definition, set the variable's value.
+    if expression.variant == RegexExpression.Variant.VarDef:
+      if expression.name not in variables:
+        variables = variables.copyWith(expression.name, stringWord[:match.end()])
+      else:
+        Logger.testFailed("Multiple definitions of variable \"{}\"".format(expression.name),
+                          pos.fileName, pos.lineNo)
 
-  # All parts were successfully matched. Return the new variable state.
-  return varState
+    # Move cursor by deleting the matched characters.
+    stringWord = stringWord[match.end():]
+
+  # Make sure the entire word matched, i.e. `stringWord` is empty.
+  if stringWord:
+    return None
+
+  return variables
+
+def MatchLines(checkerLine, stringLine, variables):
+  """ Attempts to match a CHECK line against a string. Returns variable state
+      after the match if successful and None otherwise.
+  """
+  checkerWords = splitAtSeparators(checkerLine.expressions)
+  stringWords = stringLine.split()
+
+  while checkerWords:
+    # Get the next run of RegexExpressions which must match one string word.
+    checkerWord, checkerWords = headAndTail(checkerWords)
+
+    # Keep reading words until a match is found.
+    wordMatched = False
+    while stringWords:
+      stringWord, stringWords = headAndTail(stringWords)
+      newVariables = matchWords(checkerWord, stringWord, variables, checkerLine)
+      if newVariables is not None:
+        wordMatched = True
+        variables = newVariables
+        break
+    if not wordMatched:
+      return None
+
+  # All RegexExpressions matched. Return new variable state.
+  return variables
diff --git a/tools/checker/match/test.py b/tools/checker/match/test.py
index bb3b1af..97725ad 100644
--- a/tools/checker/match/test.py
+++ b/tools/checker/match/test.py
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from common.immutables               import ImmutableDict
 from common.testing                  import ToUnicode
 from file_format.c1visualizer.parser import ParseC1visualizerStream
 from file_format.c1visualizer.struct import C1visualizerFile, C1visualizerPass
@@ -33,7 +34,9 @@
     return ParseCheckerAssertion(testCase, checkerString, TestAssertion.Variant.InOrder, 0)
 
   def tryMatch(self, checkerString, c1String, varState={}):
-    return MatchLines(self.createTestAssertion(checkerString), ToUnicode(c1String), varState)
+    return MatchLines(self.createTestAssertion(checkerString),
+                      ToUnicode(c1String),
+                      ImmutableDict(varState))
 
   def matches(self, checkerString, c1String, varState={}):
     return self.tryMatch(checkerString, c1String, varState) is not None
@@ -137,8 +140,8 @@
       // CHECK: abc<<X>>def
     """,
     """
-      foo bar
-      abc def
+      foo0bar
+      abc0def
     """))
     self.assertTrue(self.matches(
     """
@@ -161,6 +164,12 @@
       abc1235def
     """))
 
+  def test_WholeWordMustMatch(self):
+    self.assertTrue(self.matches( "// CHECK: b{{.}}r", "abc bar def"))
+    self.assertFalse(self.matches( "// CHECK: b{{.}}r", "abc Xbar def"))
+    self.assertFalse(self.matches( "// CHECK: b{{.}}r", "abc barX def"))
+    self.assertFalse(self.matches( "// CHECK: b{{.}}r", "abc b r def"))
+
   def test_InOrderAssertions(self):
     self.assertTrue(self.matches(
     """
diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt
index 8ce19dd..a8bc4e1 100644
--- a/tools/libcore_failures.txt
+++ b/tools/libcore_failures.txt
@@ -109,12 +109,6 @@
   bug: 19165288
 },
 {
-  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"]