Merge changes Id749f453,Ie3ce9dd8

* changes:
  Always run oatdumps tests
  Disable oatdumps device build
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 8b2d6fd..3b2758b 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -63,9 +63,188 @@
 #define __ down_cast<ArmAssembler*>(codegen->GetAssembler())->  // NOLINT
 #define QUICK_ENTRY_POINT(x) QUICK_ENTRYPOINT_OFFSET(kArmPointerSize, x).Int32Value()
 
-class NullCheckSlowPathARM : public SlowPathCode {
+static constexpr int kRegListThreshold = 4;
+
+// SaveLiveRegisters and RestoreLiveRegisters from SlowPathCodeARM operate on sets of S registers,
+// for each live D registers they treat two corresponding S registers as live ones.
+//
+// Two following functions (SaveContiguousSRegisterList, RestoreContiguousSRegisterList) build
+// from a list of contiguous S registers a list of contiguous D registers (processing first/last
+// S registers corner cases) and save/restore this new list treating them as D registers.
+// - decreasing code size
+// - avoiding hazards on Cortex-A57, when a pair of S registers for an actual live D register is
+//   restored and then used in regular non SlowPath code as D register.
+//
+// For the following example (v means the S register is live):
+//   D names: |    D0   |    D1   |    D2   |    D4   | ...
+//   S names: | S0 | S1 | S2 | S3 | S4 | S5 | S6 | S7 | ...
+//   Live?    |    |  v |  v |  v |  v |  v |  v |    | ...
+//
+// S1 and S6 will be saved/restored independently; D registers list (D1, D2) will be processed
+// as D registers.
+static size_t SaveContiguousSRegisterList(size_t first,
+                                          size_t last,
+                                          CodeGenerator* codegen,
+                                          size_t stack_offset) {
+  DCHECK_LE(first, last);
+  if ((first == last) && (first == 0)) {
+    stack_offset += codegen->SaveFloatingPointRegister(stack_offset, first);
+    return stack_offset;
+  }
+  if (first % 2 == 1) {
+    stack_offset += codegen->SaveFloatingPointRegister(stack_offset, first++);
+  }
+
+  bool save_last = false;
+  if (last % 2 == 0) {
+    save_last = true;
+    --last;
+  }
+
+  if (first < last) {
+    DRegister d_reg = static_cast<DRegister>(first / 2);
+    DCHECK_EQ((last - first + 1) % 2, 0u);
+    size_t number_of_d_regs = (last - first + 1) / 2;
+
+    if (number_of_d_regs == 1) {
+       __ StoreDToOffset(d_reg, SP, stack_offset);
+    } else if (number_of_d_regs > 1) {
+      __ add(IP, SP, ShifterOperand(stack_offset));
+      __ vstmiad(IP, d_reg, number_of_d_regs);
+    }
+    stack_offset += number_of_d_regs * kArmWordSize * 2;
+  }
+
+  if (save_last) {
+    stack_offset += codegen->SaveFloatingPointRegister(stack_offset, last + 1);
+  }
+
+  return stack_offset;
+}
+
+static size_t RestoreContiguousSRegisterList(size_t first,
+                                             size_t last,
+                                             CodeGenerator* codegen,
+                                             size_t stack_offset) {
+  DCHECK_LE(first, last);
+  if ((first == last) && (first == 0)) {
+    stack_offset += codegen->RestoreFloatingPointRegister(stack_offset, first);
+    return stack_offset;
+  }
+  if (first % 2 == 1) {
+    stack_offset += codegen->RestoreFloatingPointRegister(stack_offset, first++);
+  }
+
+  bool restore_last = false;
+  if (last % 2 == 0) {
+    restore_last = true;
+    --last;
+  }
+
+  if (first < last) {
+    DRegister d_reg = static_cast<DRegister>(first / 2);
+    DCHECK_EQ((last - first + 1) % 2, 0u);
+    size_t number_of_d_regs = (last - first + 1) / 2;
+    if (number_of_d_regs == 1) {
+      __ LoadDFromOffset(d_reg, SP, stack_offset);
+    } else if (number_of_d_regs > 1) {
+      __ add(IP, SP, ShifterOperand(stack_offset));
+      __ vldmiad(IP, d_reg, number_of_d_regs);
+    }
+    stack_offset += number_of_d_regs * kArmWordSize * 2;
+  }
+
+  if (restore_last) {
+    stack_offset += codegen->RestoreFloatingPointRegister(stack_offset, last + 1);
+  }
+
+  return stack_offset;
+}
+
+void SlowPathCodeARM::SaveLiveRegisters(CodeGenerator* codegen, LocationSummary* locations) {
+  size_t stack_offset = codegen->GetFirstRegisterSlotInSlowPath();
+  size_t orig_offset = stack_offset;
+
+  const uint32_t core_spills = codegen->GetSlowPathSpills(locations, /* core_registers */ true);
+  for (uint32_t i : LowToHighBits(core_spills)) {
+    // 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 += kArmWordSize;
+  }
+
+  int reg_num = POPCOUNT(core_spills);
+  if (reg_num != 0) {
+    if (reg_num > kRegListThreshold) {
+      __ StoreList(RegList(core_spills), orig_offset);
+    } else {
+      stack_offset = orig_offset;
+      for (uint32_t i : LowToHighBits(core_spills)) {
+        stack_offset += codegen->SaveCoreRegister(stack_offset, i);
+      }
+    }
+  }
+
+  uint32_t fp_spills = codegen->GetSlowPathSpills(locations, /* core_registers */ false);
+  orig_offset = stack_offset;
+  for (size_t i : LowToHighBits(fp_spills)) {
+    DCHECK_LT(i, kMaximumNumberOfExpectedRegisters);
+    saved_fpu_stack_offsets_[i] = stack_offset;
+    stack_offset += kArmWordSize;
+  }
+
+  stack_offset = orig_offset;
+  while (fp_spills != 0u) {
+    uint32_t begin = CTZ(fp_spills);
+    uint32_t tmp = fp_spills + (1u << begin);
+    fp_spills &= tmp;  // Clear the contiguous range of 1s.
+    uint32_t end = (tmp == 0u) ? 32u : CTZ(tmp);  // CTZ(0) is undefined.
+    stack_offset = SaveContiguousSRegisterList(begin, end - 1, codegen, stack_offset);
+  }
+  DCHECK_LE(stack_offset, codegen->GetFrameSize() - codegen->FrameEntrySpillSize());
+}
+
+void SlowPathCodeARM::RestoreLiveRegisters(CodeGenerator* codegen, LocationSummary* locations) {
+  size_t stack_offset = codegen->GetFirstRegisterSlotInSlowPath();
+  size_t orig_offset = stack_offset;
+
+  const uint32_t core_spills = codegen->GetSlowPathSpills(locations, /* core_registers */ true);
+  for (uint32_t i : LowToHighBits(core_spills)) {
+    DCHECK_LT(stack_offset, codegen->GetFrameSize() - codegen->FrameEntrySpillSize());
+    DCHECK_LT(i, kMaximumNumberOfExpectedRegisters);
+    stack_offset += kArmWordSize;
+  }
+
+  int reg_num = POPCOUNT(core_spills);
+  if (reg_num != 0) {
+    if (reg_num > kRegListThreshold) {
+      __ LoadList(RegList(core_spills), orig_offset);
+    } else {
+      stack_offset = orig_offset;
+      for (uint32_t i : LowToHighBits(core_spills)) {
+        stack_offset += codegen->RestoreCoreRegister(stack_offset, i);
+      }
+    }
+  }
+
+  uint32_t fp_spills = codegen->GetSlowPathSpills(locations, /* core_registers */ false);
+  while (fp_spills != 0u) {
+    uint32_t begin = CTZ(fp_spills);
+    uint32_t tmp = fp_spills + (1u << begin);
+    fp_spills &= tmp;  // Clear the contiguous range of 1s.
+    uint32_t end = (tmp == 0u) ? 32u : CTZ(tmp);  // CTZ(0) is undefined.
+    stack_offset = RestoreContiguousSRegisterList(begin, end - 1, codegen, stack_offset);
+  }
+  DCHECK_LE(stack_offset, codegen->GetFrameSize() - codegen->FrameEntrySpillSize());
+}
+
+class NullCheckSlowPathARM : public SlowPathCodeARM {
  public:
-  explicit NullCheckSlowPathARM(HNullCheck* instruction) : SlowPathCode(instruction) {}
+  explicit NullCheckSlowPathARM(HNullCheck* instruction) : SlowPathCodeARM(instruction) {}
 
   void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
     CodeGeneratorARM* arm_codegen = down_cast<CodeGeneratorARM*>(codegen);
@@ -89,9 +268,9 @@
   DISALLOW_COPY_AND_ASSIGN(NullCheckSlowPathARM);
 };
 
-class DivZeroCheckSlowPathARM : public SlowPathCode {
+class DivZeroCheckSlowPathARM : public SlowPathCodeARM {
  public:
-  explicit DivZeroCheckSlowPathARM(HDivZeroCheck* instruction) : SlowPathCode(instruction) {}
+  explicit DivZeroCheckSlowPathARM(HDivZeroCheck* instruction) : SlowPathCodeARM(instruction) {}
 
   void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
     CodeGeneratorARM* arm_codegen = down_cast<CodeGeneratorARM*>(codegen);
@@ -112,10 +291,10 @@
   DISALLOW_COPY_AND_ASSIGN(DivZeroCheckSlowPathARM);
 };
 
-class SuspendCheckSlowPathARM : public SlowPathCode {
+class SuspendCheckSlowPathARM : public SlowPathCodeARM {
  public:
   SuspendCheckSlowPathARM(HSuspendCheck* instruction, HBasicBlock* successor)
-      : SlowPathCode(instruction), successor_(successor) {}
+      : SlowPathCodeARM(instruction), successor_(successor) {}
 
   void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
     CodeGeneratorARM* arm_codegen = down_cast<CodeGeneratorARM*>(codegen);
@@ -150,10 +329,10 @@
   DISALLOW_COPY_AND_ASSIGN(SuspendCheckSlowPathARM);
 };
 
-class BoundsCheckSlowPathARM : public SlowPathCode {
+class BoundsCheckSlowPathARM : public SlowPathCodeARM {
  public:
   explicit BoundsCheckSlowPathARM(HBoundsCheck* instruction)
-      : SlowPathCode(instruction) {}
+      : SlowPathCodeARM(instruction) {}
 
   void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
     CodeGeneratorARM* arm_codegen = down_cast<CodeGeneratorARM*>(codegen);
@@ -190,13 +369,13 @@
   DISALLOW_COPY_AND_ASSIGN(BoundsCheckSlowPathARM);
 };
 
-class LoadClassSlowPathARM : public SlowPathCode {
+class LoadClassSlowPathARM : public SlowPathCodeARM {
  public:
   LoadClassSlowPathARM(HLoadClass* cls,
                        HInstruction* at,
                        uint32_t dex_pc,
                        bool do_clinit)
-      : SlowPathCode(at), cls_(cls), at_(at), dex_pc_(dex_pc), do_clinit_(do_clinit) {
+      : SlowPathCodeARM(at), cls_(cls), at_(at), dex_pc_(dex_pc), do_clinit_(do_clinit) {
     DCHECK(at->IsLoadClass() || at->IsClinitCheck());
   }
 
@@ -247,10 +426,10 @@
   DISALLOW_COPY_AND_ASSIGN(LoadClassSlowPathARM);
 };
 
-class TypeCheckSlowPathARM : public SlowPathCode {
+class TypeCheckSlowPathARM : public SlowPathCodeARM {
  public:
   TypeCheckSlowPathARM(HInstruction* instruction, bool is_fatal)
-      : SlowPathCode(instruction), is_fatal_(is_fatal) {}
+      : SlowPathCodeARM(instruction), is_fatal_(is_fatal) {}
 
   void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
     LocationSummary* locations = instruction_->GetLocations();
@@ -307,10 +486,10 @@
   DISALLOW_COPY_AND_ASSIGN(TypeCheckSlowPathARM);
 };
 
-class DeoptimizationSlowPathARM : public SlowPathCode {
+class DeoptimizationSlowPathARM : public SlowPathCodeARM {
  public:
   explicit DeoptimizationSlowPathARM(HDeoptimize* instruction)
-    : SlowPathCode(instruction) {}
+    : SlowPathCodeARM(instruction) {}
 
   void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
     CodeGeneratorARM* arm_codegen = down_cast<CodeGeneratorARM*>(codegen);
@@ -325,9 +504,9 @@
   DISALLOW_COPY_AND_ASSIGN(DeoptimizationSlowPathARM);
 };
 
-class ArraySetSlowPathARM : public SlowPathCode {
+class ArraySetSlowPathARM : public SlowPathCodeARM {
  public:
-  explicit ArraySetSlowPathARM(HInstruction* instruction) : SlowPathCode(instruction) {}
+  explicit ArraySetSlowPathARM(HInstruction* instruction) : SlowPathCodeARM(instruction) {}
 
   void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
     LocationSummary* locations = instruction_->GetLocations();
@@ -367,10 +546,10 @@
 };
 
 // Slow path marking an object during a read barrier.
-class ReadBarrierMarkSlowPathARM : public SlowPathCode {
+class ReadBarrierMarkSlowPathARM : public SlowPathCodeARM {
  public:
   ReadBarrierMarkSlowPathARM(HInstruction* instruction, Location obj)
-      : SlowPathCode(instruction), obj_(obj) {
+      : SlowPathCodeARM(instruction), obj_(obj) {
     DCHECK(kEmitCompilerReadBarrier);
   }
 
@@ -434,7 +613,7 @@
 };
 
 // Slow path generating a read barrier for a heap reference.
-class ReadBarrierForHeapReferenceSlowPathARM : public SlowPathCode {
+class ReadBarrierForHeapReferenceSlowPathARM : public SlowPathCodeARM {
  public:
   ReadBarrierForHeapReferenceSlowPathARM(HInstruction* instruction,
                                          Location out,
@@ -442,7 +621,7 @@
                                          Location obj,
                                          uint32_t offset,
                                          Location index)
-      : SlowPathCode(instruction),
+      : SlowPathCodeARM(instruction),
         out_(out),
         ref_(ref),
         obj_(obj),
@@ -614,10 +793,10 @@
 };
 
 // Slow path generating a read barrier for a GC root.
-class ReadBarrierForRootSlowPathARM : public SlowPathCode {
+class ReadBarrierForRootSlowPathARM : public SlowPathCodeARM {
  public:
   ReadBarrierForRootSlowPathARM(HInstruction* instruction, Location out, Location root)
-      : SlowPathCode(instruction), out_(out), root_(root) {
+      : SlowPathCodeARM(instruction), out_(out), root_(root) {
     DCHECK(kEmitCompilerReadBarrier);
   }
 
@@ -1509,7 +1688,7 @@
 }
 
 void InstructionCodeGeneratorARM::VisitDeoptimize(HDeoptimize* deoptimize) {
-  SlowPathCode* slow_path = deopt_slow_paths_.NewSlowPath<DeoptimizationSlowPathARM>(deoptimize);
+  SlowPathCodeARM* slow_path = deopt_slow_paths_.NewSlowPath<DeoptimizationSlowPathARM>(deoptimize);
   GenerateTestAndBranch(deoptimize,
                         /* condition_input_index */ 0,
                         slow_path->GetEntryLabel(),
@@ -3096,7 +3275,7 @@
 }
 
 void InstructionCodeGeneratorARM::VisitDivZeroCheck(HDivZeroCheck* instruction) {
-  SlowPathCode* slow_path = new (GetGraph()->GetArena()) DivZeroCheckSlowPathARM(instruction);
+  SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) DivZeroCheckSlowPathARM(instruction);
   codegen_->AddSlowPath(slow_path);
 
   LocationSummary* locations = instruction->GetLocations();
@@ -4265,7 +4444,7 @@
 }
 
 void CodeGeneratorARM::GenerateExplicitNullCheck(HNullCheck* instruction) {
-  SlowPathCode* slow_path = new (GetGraph()->GetArena()) NullCheckSlowPathARM(instruction);
+  SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) NullCheckSlowPathARM(instruction);
   AddSlowPath(slow_path);
 
   LocationSummary* locations = instruction->GetLocations();
@@ -4683,7 +4862,7 @@
       uint32_t super_offset = mirror::Class::SuperClassOffset().Int32Value();
       uint32_t component_offset = mirror::Class::ComponentTypeOffset().Int32Value();
       Label done;
-      SlowPathCode* slow_path = nullptr;
+      SlowPathCodeARM* slow_path = nullptr;
 
       if (may_need_runtime_call_for_type_check) {
         slow_path = new (GetGraph()->GetArena()) ArraySetSlowPathARM(instruction);
@@ -4901,7 +5080,7 @@
 
 void InstructionCodeGeneratorARM::VisitBoundsCheck(HBoundsCheck* instruction) {
   LocationSummary* locations = instruction->GetLocations();
-  SlowPathCode* slow_path =
+  SlowPathCodeARM* slow_path =
       new (GetGraph()->GetArena()) BoundsCheckSlowPathARM(instruction);
   codegen_->AddSlowPath(slow_path);
 
@@ -5370,7 +5549,7 @@
 
   if (generate_null_check || cls->MustGenerateClinitCheck()) {
     DCHECK(cls->CanCallRuntime());
-    SlowPathCode* slow_path = new (GetGraph()->GetArena()) LoadClassSlowPathARM(
+    SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) LoadClassSlowPathARM(
         cls, cls, cls->GetDexPc(), cls->MustGenerateClinitCheck());
     codegen_->AddSlowPath(slow_path);
     if (generate_null_check) {
@@ -5395,7 +5574,7 @@
 
 void InstructionCodeGeneratorARM::VisitClinitCheck(HClinitCheck* check) {
   // We assume the class is not null.
-  SlowPathCode* slow_path = new (GetGraph()->GetArena()) LoadClassSlowPathARM(
+  SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) LoadClassSlowPathARM(
       check->GetLoadClass(), check, check->GetDexPc(), true);
   codegen_->AddSlowPath(slow_path);
   GenerateClassInitializationCheck(slow_path,
@@ -5403,7 +5582,7 @@
 }
 
 void InstructionCodeGeneratorARM::GenerateClassInitializationCheck(
-    SlowPathCode* slow_path, Register class_reg) {
+    SlowPathCodeARM* slow_path, Register class_reg) {
   __ LoadFromOffset(kLoadWord, IP, class_reg, mirror::Class::StatusOffset().Int32Value());
   __ cmp(IP, ShifterOperand(mirror::Class::kStatusInitialized));
   __ b(slow_path->GetEntryLabel(), LT);
@@ -5596,7 +5775,7 @@
   uint32_t component_offset = mirror::Class::ComponentTypeOffset().Int32Value();
   uint32_t primitive_offset = mirror::Class::PrimitiveTypeOffset().Int32Value();
   Label done, zero;
-  SlowPathCode* slow_path = nullptr;
+  SlowPathCodeARM* slow_path = nullptr;
 
   // Return 0 if `obj` is null.
   // avoid null check if we know obj is not null.
@@ -5788,7 +5967,7 @@
        type_check_kind == TypeCheckKind::kClassHierarchyCheck ||
        type_check_kind == TypeCheckKind::kArrayObjectCheck) &&
       !instruction->CanThrowIntoCatchBlock();
-  SlowPathCode* type_check_slow_path =
+  SlowPathCodeARM* type_check_slow_path =
       new (GetGraph()->GetArena()) TypeCheckSlowPathARM(instruction,
                                                         is_type_check_slow_path_fatal);
   codegen_->AddSlowPath(type_check_slow_path);
@@ -6282,7 +6461,7 @@
                     "have different sizes.");
 
       // Slow path marking the GC root `root`.
-      SlowPathCode* slow_path =
+      SlowPathCodeARM* slow_path =
           new (GetGraph()->GetArena()) ReadBarrierMarkSlowPathARM(instruction, root);
       codegen_->AddSlowPath(slow_path);
 
@@ -6423,7 +6602,7 @@
   __ MaybeUnpoisonHeapReference(ref_reg);
 
   // Slow path marking the object `ref` when it is gray.
-  SlowPathCode* slow_path =
+  SlowPathCodeARM* slow_path =
       new (GetGraph()->GetArena()) ReadBarrierMarkSlowPathARM(instruction, ref);
   AddSlowPath(slow_path);
 
@@ -6459,7 +6638,7 @@
   // not used by the artReadBarrierSlow entry point.
   //
   // TODO: Unpoison `ref` when it is used by artReadBarrierSlow.
-  SlowPathCode* slow_path = new (GetGraph()->GetArena())
+  SlowPathCodeARM* slow_path = new (GetGraph()->GetArena())
       ReadBarrierForHeapReferenceSlowPathARM(instruction, out, ref, obj, offset, index);
   AddSlowPath(slow_path);
 
@@ -6494,7 +6673,7 @@
   //
   // Note that GC roots are not affected by heap poisoning, so we do
   // not need to do anything special for this here.
-  SlowPathCode* slow_path =
+  SlowPathCodeARM* slow_path =
       new (GetGraph()->GetArena()) ReadBarrierForRootSlowPathARM(instruction, out, root);
   AddSlowPath(slow_path);
 
diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h
index 38a2410..424a1a1 100644
--- a/compiler/optimizing/code_generator_arm.h
+++ b/compiler/optimizing/code_generator_arm.h
@@ -50,6 +50,18 @@
 static constexpr size_t kRuntimeParameterFpuRegistersLength =
     arraysize(kRuntimeParameterFpuRegisters);
 
+class SlowPathCodeARM : public SlowPathCode {
+ public:
+  explicit SlowPathCodeARM(HInstruction* instruction) : SlowPathCode(instruction) {}
+
+  void SaveLiveRegisters(CodeGenerator* codegen, LocationSummary* locations) FINAL;
+  void RestoreLiveRegisters(CodeGenerator* codegen, LocationSummary* locations) FINAL;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SlowPathCodeARM);
+};
+
+
 class InvokeRuntimeCallingConvention : public CallingConvention<Register, SRegister> {
  public:
   InvokeRuntimeCallingConvention()
@@ -216,7 +228,7 @@
   // is the block to branch to if the suspend check is not needed, and after
   // the suspend call.
   void GenerateSuspendCheck(HSuspendCheck* check, HBasicBlock* successor);
-  void GenerateClassInitializationCheck(SlowPathCode* slow_path, Register class_reg);
+  void GenerateClassInitializationCheck(SlowPathCodeARM* slow_path, Register class_reg);
   void GenerateAndConst(Register out, Register first, uint32_t value);
   void GenerateOrrConst(Register out, Register first, uint32_t value);
   void GenerateEorConst(Register out, Register first, uint32_t value);
diff --git a/compiler/utils/arm/assembler_arm.h b/compiler/utils/arm/assembler_arm.h
index aefbf26..ee5811c 100644
--- a/compiler/utils/arm/assembler_arm.h
+++ b/compiler/utils/arm/assembler_arm.h
@@ -763,6 +763,9 @@
   virtual void PushList(RegList regs, Condition cond = AL) = 0;
   virtual void PopList(RegList regs, Condition cond = AL) = 0;
 
+  virtual void StoreList(RegList regs, size_t stack_offset) = 0;
+  virtual void LoadList(RegList regs, size_t stack_offset) = 0;
+
   virtual void Mov(Register rd, Register rm, Condition cond = AL) = 0;
 
   // Convenience shift instructions. Use mov instruction with shifter operand
diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc
index f5ccf40..2269ba2 100644
--- a/compiler/utils/arm/assembler_thumb2.cc
+++ b/compiler/utils/arm/assembler_thumb2.cc
@@ -3372,6 +3372,30 @@
   ldm(IA_W, SP, regs, cond);
 }
 
+void Thumb2Assembler::StoreList(RegList regs, size_t stack_offset) {
+  DCHECK_NE(regs, 0u);
+  DCHECK_EQ(regs & (1u << IP), 0u);
+  if (IsPowerOfTwo(regs)) {
+    Register reg = static_cast<Register>(CTZ(static_cast<uint32_t>(regs)));
+    str(reg, Address(SP, stack_offset));
+  } else {
+    add(IP, SP, ShifterOperand(stack_offset));
+    stm(IA, IP, regs);
+  }
+}
+
+void Thumb2Assembler::LoadList(RegList regs, size_t stack_offset) {
+  DCHECK_NE(regs, 0u);
+  DCHECK_EQ(regs & (1u << IP), 0u);
+  if (IsPowerOfTwo(regs)) {
+    Register reg = static_cast<Register>(CTZ(static_cast<uint32_t>(regs)));
+    ldr(reg, Address(SP, stack_offset));
+  } else {
+    Register lowest_reg = static_cast<Register>(CTZ(static_cast<uint32_t>(regs)));
+    add(lowest_reg, SP, ShifterOperand(stack_offset));
+    ldm(IA, lowest_reg, regs);
+  }
+}
 
 void Thumb2Assembler::Mov(Register rd, Register rm, Condition cond) {
   if (cond != AL || rd != rm) {
diff --git a/compiler/utils/arm/assembler_thumb2.h b/compiler/utils/arm/assembler_thumb2.h
index 917c947..1c495aa 100644
--- a/compiler/utils/arm/assembler_thumb2.h
+++ b/compiler/utils/arm/assembler_thumb2.h
@@ -293,6 +293,8 @@
 
   void PushList(RegList regs, Condition cond = AL) OVERRIDE;
   void PopList(RegList regs, Condition cond = AL) OVERRIDE;
+  void StoreList(RegList regs, size_t stack_offset) OVERRIDE;
+  void LoadList(RegList regs, size_t stack_offset) OVERRIDE;
 
   void Mov(Register rd, Register rm, Condition cond = AL) OVERRIDE;
 
diff --git a/runtime/arch/arm/asm_support_arm.S b/runtime/arch/arm/asm_support_arm.S
index 38ca76a..9eca862 100644
--- a/runtime/arch/arm/asm_support_arm.S
+++ b/runtime/arch/arm/asm_support_arm.S
@@ -68,14 +68,14 @@
     .set .Lruntime_current3_used, 0
     // The RUNTIME_CURRENT macros that are bound to the \name argument of DEF_ENTRY to ensure
     // that label names are unique.
-    .macro RUNTIME_CURRENT1 rDest, rTemp
-        RUNTIME_CURRENT \name, 1, \rDest, \rTemp
+    .macro RUNTIME_CURRENT1 rDest
+        RUNTIME_CURRENT \name, 1, \rDest
     .endm
-    .macro RUNTIME_CURRENT2 rDest, rTemp
-        RUNTIME_CURRENT \name, 2, \rDest, \rTemp
+    .macro RUNTIME_CURRENT2 rDest
+        RUNTIME_CURRENT \name, 2, \rDest
     .endm
-    .macro RUNTIME_CURRENT3 rDest, rTemp
-        RUNTIME_CURRENT \name, 3, \rDest, \rTemp
+    .macro RUNTIME_CURRENT3 rDest
+        RUNTIME_CURRENT \name, 3, \rDest
     .endm
 .endm
 
diff --git a/test/003-omnibus-opcodes/build b/test/003-omnibus-opcodes/build
index 56e8784..dba3549 100644
--- a/test/003-omnibus-opcodes/build
+++ b/test/003-omnibus-opcodes/build
@@ -26,6 +26,11 @@
   jar cf classes.jill.jar -C classes .
   ${JACK} --import classes.jill.jar --output-dex .
 else
-  ${DX} -JXmx256m --debug --dex --output=classes.dex classes
+  if [ ${NEED_DEX} = "true" ]; then
+    ${DX} -JXmx256m --debug --dex --output=classes.dex classes
   fi
-zip $TEST_NAME.jar classes.dex
+fi
+
+if [ ${NEED_DEX} = "true" ]; then
+  zip $TEST_NAME.jar classes.dex
+fi
diff --git a/test/005-annotations/build b/test/005-annotations/build
index 93bee50..216843d 100644
--- a/test/005-annotations/build
+++ b/test/005-annotations/build
@@ -32,7 +32,11 @@
   jar cf classes.jill.jar -C classes .
   ${JACK} --import classes.jill.jar --output-dex .
 else
-  ${DX} -JXmx256m --debug --dex --output=classes.dex classes
+  if [ ${NEED_DEX} = "true" ]; then
+    ${DX} -JXmx256m --debug --dex --output=classes.dex classes
+  fi
 fi
 
-zip $TEST_NAME.jar classes.dex
+if [ ${NEED_DEX} = "true" ]; then
+  zip $TEST_NAME.jar classes.dex
+fi
diff --git a/test/023-many-interfaces/build b/test/023-many-interfaces/build
index 3bb6747..b4b5bd4 100644
--- a/test/023-many-interfaces/build
+++ b/test/023-many-interfaces/build
@@ -29,6 +29,8 @@
   ${JAVAC} -d classes src/*.java
 
   # dx needs more memory for that test so do not pass Xmx option here.
-  ${DX} --debug --dex --dump-to=classes.lst --output=classes.dex classes
-  zip $TEST_NAME.jar classes.dex
+  if [ ${NEED_DEX} = "true" ]; then
+    ${DX} --debug --dex --dump-to=classes.lst --output=classes.dex classes
+    zip $TEST_NAME.jar classes.dex
+  fi
 fi
diff --git a/test/056-const-string-jumbo/build b/test/056-const-string-jumbo/build
index ae42519..5344ac3 100644
--- a/test/056-const-string-jumbo/build
+++ b/test/056-const-string-jumbo/build
@@ -45,7 +45,11 @@
   mkdir classes
   ${JAVAC} -d classes src/*.java
 
-  ${DX} -JXmx500m --debug --dex --no-optimize --positions=none --no-locals --output=classes.dex classes
+  if [ ${NEED_DEX} = "true" ]; then
+    ${DX} -JXmx500m --debug --dex --no-optimize --positions=none --no-locals --output=classes.dex classes
+  fi
 fi
 
-zip $TEST_NAME.jar classes.dex
+if [ ${NEED_DEX} = "true" ]; then
+  zip $TEST_NAME.jar classes.dex
+fi
diff --git a/test/111-unresolvable-exception/build b/test/111-unresolvable-exception/build
index 58ac26d..cf19f60 100644
--- a/test/111-unresolvable-exception/build
+++ b/test/111-unresolvable-exception/build
@@ -25,6 +25,11 @@
   jar cf classes.jill.jar -C classes .
   ${JACK} --import classes.jill.jar --output-dex .
 else
-  ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex classes
+  if [ ${NEED_DEX} = "true" ]; then
+    ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex classes
+  fi
 fi
-zip $TEST_NAME.jar classes.dex
+
+if [ ${NEED_DEX} = "true" ]; then
+  zip $TEST_NAME.jar classes.dex
+fi
diff --git a/test/113-multidex/build b/test/113-multidex/build
index 4557ccd..b980e50 100644
--- a/test/113-multidex/build
+++ b/test/113-multidex/build
@@ -37,10 +37,15 @@
   mv classes.dex classes2.dex
   mv classes-1.dex classes.dex
 else
-  # All except Main
-  ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex classes
+  if [ ${NEED_DEX} = "true" ]; then
+    # All except Main
+    ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex classes
 
-  # Only Main
-  ${DX} -JXmx256m --debug --dex --dump-to=classes2.lst --output=classes2.dex classes2
+    # Only Main
+    ${DX} -JXmx256m --debug --dex --dump-to=classes2.lst --output=classes2.dex classes2
+  fi
 fi
-zip $TEST_NAME.jar classes.dex classes2.dex
+
+if [ ${NEED_DEX} = "true" ]; then
+  zip $TEST_NAME.jar classes.dex classes2.dex
+fi
diff --git a/test/124-missing-classes/build b/test/124-missing-classes/build
index 0a340a2..ea45cd2 100644
--- a/test/124-missing-classes/build
+++ b/test/124-missing-classes/build
@@ -30,6 +30,11 @@
   jar cf classes.jill.jar -C classes .
   ${JACK} --import classes.jill.jar --output-dex .
 else
-  ${DX} -JXmx256m --debug --dex --output=classes.dex classes
+  if [ ${NEED_DEX} = "true" ]; then
+    ${DX} -JXmx256m --debug --dex --output=classes.dex classes
+  fi
 fi
-zip $TEST_NAME.jar classes.dex
+
+if [ ${NEED_DEX} = "true" ]; then
+  zip $TEST_NAME.jar classes.dex
+fi
diff --git a/test/126-miranda-multidex/build b/test/126-miranda-multidex/build
index 00b9ba0..2a5e7da 100644
--- a/test/126-miranda-multidex/build
+++ b/test/126-miranda-multidex/build
@@ -37,10 +37,15 @@
   mv classes.dex classes2.dex
   mv classes-1.dex classes.dex
 else
-  # All except Main
-  ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex classes
+  if [ ${NEED_DEX} = "true" ]; then
+    # All except Main
+    ${DX} -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex classes
 
-  # Only Main
-  ${DX} -JXmx256m --debug --dex --dump-to=classes2.lst --output=classes2.dex classes2
+    # Only Main
+    ${DX} -JXmx256m --debug --dex --dump-to=classes2.lst --output=classes2.dex classes2
+  fi
 fi
-zip $TEST_NAME.jar classes.dex classes2.dex
+
+if [ ${NEED_DEX} = "true" ]; then
+  zip $TEST_NAME.jar classes.dex classes2.dex
+fi
diff --git a/test/128-reg-spilling-on-implicit-nullcheck/expected.txt b/test/128-reg-spill-on-implicit-nullcheck/expected.txt
similarity index 100%
rename from test/128-reg-spilling-on-implicit-nullcheck/expected.txt
rename to test/128-reg-spill-on-implicit-nullcheck/expected.txt
diff --git a/test/128-reg-spilling-on-implicit-nullcheck/info.txt b/test/128-reg-spill-on-implicit-nullcheck/info.txt
similarity index 100%
rename from test/128-reg-spilling-on-implicit-nullcheck/info.txt
rename to test/128-reg-spill-on-implicit-nullcheck/info.txt
diff --git a/test/128-reg-spilling-on-implicit-nullcheck/src/Main.java b/test/128-reg-spill-on-implicit-nullcheck/src/Main.java
similarity index 100%
rename from test/128-reg-spilling-on-implicit-nullcheck/src/Main.java
rename to test/128-reg-spill-on-implicit-nullcheck/src/Main.java
diff --git a/test/201-built-in-exception-detail-messages/expected.txt b/test/201-built-in-except-detail-messages/expected.txt
similarity index 100%
rename from test/201-built-in-exception-detail-messages/expected.txt
rename to test/201-built-in-except-detail-messages/expected.txt
diff --git a/test/201-built-in-exception-detail-messages/info.txt b/test/201-built-in-except-detail-messages/info.txt
similarity index 100%
rename from test/201-built-in-exception-detail-messages/info.txt
rename to test/201-built-in-except-detail-messages/info.txt
diff --git a/test/201-built-in-exception-detail-messages/src/Main.java b/test/201-built-in-except-detail-messages/src/Main.java
similarity index 100%
rename from test/201-built-in-exception-detail-messages/src/Main.java
rename to test/201-built-in-except-detail-messages/src/Main.java
diff --git a/test/303-verification-stress/build b/test/303-verification-stress/build
index 5ff73ec..b67eaf2 100644
--- a/test/303-verification-stress/build
+++ b/test/303-verification-stress/build
@@ -29,6 +29,8 @@
   ${JAVAC} -d classes src/*.java
 
   # dx needs more memory for that test so do not pass Xmx option here.
-  ${DX} --debug --dex --output=classes.dex classes
-  zip $TEST_NAME.jar classes.dex
+  if [ ${NEED_DEX} = "true" ]; then
+    ${DX} --debug --dex --output=classes.dex classes
+    zip $TEST_NAME.jar classes.dex
+  fi
 fi
diff --git a/test/458-checker-instruction-simplification/expected.txt b/test/458-checker-instruct-simplification/expected.txt
similarity index 100%
rename from test/458-checker-instruction-simplification/expected.txt
rename to test/458-checker-instruct-simplification/expected.txt
diff --git a/test/458-checker-instruction-simplification/info.txt b/test/458-checker-instruct-simplification/info.txt
similarity index 100%
rename from test/458-checker-instruction-simplification/info.txt
rename to test/458-checker-instruct-simplification/info.txt
diff --git a/test/458-checker-instruction-simplification/smali/SmaliTests.smali b/test/458-checker-instruct-simplification/smali/SmaliTests.smali
similarity index 100%
rename from test/458-checker-instruction-simplification/smali/SmaliTests.smali
rename to test/458-checker-instruct-simplification/smali/SmaliTests.smali
diff --git a/test/458-checker-instruction-simplification/src/Main.java b/test/458-checker-instruct-simplification/src/Main.java
similarity index 100%
rename from test/458-checker-instruction-simplification/src/Main.java
rename to test/458-checker-instruct-simplification/src/Main.java
diff --git a/test/462-checker-inlining-across-dex-files/expected.txt b/test/462-checker-inlining-dex-files/expected.txt
similarity index 100%
rename from test/462-checker-inlining-across-dex-files/expected.txt
rename to test/462-checker-inlining-dex-files/expected.txt
diff --git a/test/462-checker-inlining-across-dex-files/info.txt b/test/462-checker-inlining-dex-files/info.txt
similarity index 100%
rename from test/462-checker-inlining-across-dex-files/info.txt
rename to test/462-checker-inlining-dex-files/info.txt
diff --git a/test/462-checker-inlining-across-dex-files/multidex.jpp b/test/462-checker-inlining-dex-files/multidex.jpp
similarity index 100%
rename from test/462-checker-inlining-across-dex-files/multidex.jpp
rename to test/462-checker-inlining-dex-files/multidex.jpp
diff --git a/test/462-checker-inlining-across-dex-files/src-multidex/OtherDex.java b/test/462-checker-inlining-dex-files/src-multidex/OtherDex.java
similarity index 100%
rename from test/462-checker-inlining-across-dex-files/src-multidex/OtherDex.java
rename to test/462-checker-inlining-dex-files/src-multidex/OtherDex.java
diff --git a/test/462-checker-inlining-across-dex-files/src/Main.java b/test/462-checker-inlining-dex-files/src/Main.java
similarity index 100%
rename from test/462-checker-inlining-across-dex-files/src/Main.java
rename to test/462-checker-inlining-dex-files/src/Main.java
diff --git a/test/468-checker-bool-simplifier-regression/expected.txt b/test/468-checker-bool-simplif-regression/expected.txt
similarity index 100%
rename from test/468-checker-bool-simplifier-regression/expected.txt
rename to test/468-checker-bool-simplif-regression/expected.txt
diff --git a/test/468-checker-bool-simplifier-regression/info.txt b/test/468-checker-bool-simplif-regression/info.txt
similarity index 100%
rename from test/468-checker-bool-simplifier-regression/info.txt
rename to test/468-checker-bool-simplif-regression/info.txt
diff --git a/test/468-checker-bool-simplifier-regression/smali/TestCase.smali b/test/468-checker-bool-simplif-regression/smali/TestCase.smali
similarity index 100%
rename from test/468-checker-bool-simplifier-regression/smali/TestCase.smali
rename to test/468-checker-bool-simplif-regression/smali/TestCase.smali
diff --git a/test/468-checker-bool-simplifier-regression/src/Main.java b/test/468-checker-bool-simplif-regression/src/Main.java
similarity index 100%
rename from test/468-checker-bool-simplifier-regression/src/Main.java
rename to test/468-checker-bool-simplif-regression/src/Main.java
diff --git a/test/477-long-to-float-conversion-precision/expected.txt b/test/477-long-2-float-convers-precision/expected.txt
similarity index 100%
rename from test/477-long-to-float-conversion-precision/expected.txt
rename to test/477-long-2-float-convers-precision/expected.txt
diff --git a/test/477-long-to-float-conversion-precision/info.txt b/test/477-long-2-float-convers-precision/info.txt
similarity index 100%
rename from test/477-long-to-float-conversion-precision/info.txt
rename to test/477-long-2-float-convers-precision/info.txt
diff --git a/test/477-long-to-float-conversion-precision/src/Main.java b/test/477-long-2-float-convers-precision/src/Main.java
similarity index 100%
rename from test/477-long-to-float-conversion-precision/src/Main.java
rename to test/477-long-2-float-convers-precision/src/Main.java
diff --git a/test/496-checker-inlining-and-class-loader/expected.txt b/test/496-checker-inlining-class-loader/expected.txt
similarity index 100%
rename from test/496-checker-inlining-and-class-loader/expected.txt
rename to test/496-checker-inlining-class-loader/expected.txt
diff --git a/test/496-checker-inlining-and-class-loader/info.txt b/test/496-checker-inlining-class-loader/info.txt
similarity index 100%
rename from test/496-checker-inlining-and-class-loader/info.txt
rename to test/496-checker-inlining-class-loader/info.txt
diff --git a/test/496-checker-inlining-and-class-loader/src/FirstSeenByMyClassLoader.java b/test/496-checker-inlining-class-loader/src/FirstSeenByMyClassLoader.java
similarity index 100%
rename from test/496-checker-inlining-and-class-loader/src/FirstSeenByMyClassLoader.java
rename to test/496-checker-inlining-class-loader/src/FirstSeenByMyClassLoader.java
diff --git a/test/496-checker-inlining-and-class-loader/src/Main.java b/test/496-checker-inlining-class-loader/src/Main.java
similarity index 100%
rename from test/496-checker-inlining-and-class-loader/src/Main.java
rename to test/496-checker-inlining-class-loader/src/Main.java
diff --git a/test/530-checker-regression-reftype-final/expected.txt b/test/530-checker-regression-reftyp-final/expected.txt
similarity index 100%
rename from test/530-checker-regression-reftype-final/expected.txt
rename to test/530-checker-regression-reftyp-final/expected.txt
diff --git a/test/530-checker-regression-reftype-final/info.txt b/test/530-checker-regression-reftyp-final/info.txt
similarity index 100%
rename from test/530-checker-regression-reftype-final/info.txt
rename to test/530-checker-regression-reftyp-final/info.txt
diff --git a/test/530-checker-regression-reftype-final/smali/TestCase.smali b/test/530-checker-regression-reftyp-final/smali/TestCase.smali
similarity index 100%
rename from test/530-checker-regression-reftype-final/smali/TestCase.smali
rename to test/530-checker-regression-reftyp-final/smali/TestCase.smali
diff --git a/test/530-checker-regression-reftype-final/src/Main.java b/test/530-checker-regression-reftyp-final/src/Main.java
similarity index 100%
rename from test/530-checker-regression-reftype-final/src/Main.java
rename to test/530-checker-regression-reftyp-final/src/Main.java
diff --git a/test/547-regression-trycatch-critical-edge/expected.txt b/test/547-regression-trycatch-critic-edge/expected.txt
similarity index 100%
rename from test/547-regression-trycatch-critical-edge/expected.txt
rename to test/547-regression-trycatch-critic-edge/expected.txt
diff --git a/test/547-regression-trycatch-critical-edge/info.txt b/test/547-regression-trycatch-critic-edge/info.txt
similarity index 100%
rename from test/547-regression-trycatch-critical-edge/info.txt
rename to test/547-regression-trycatch-critic-edge/info.txt
diff --git a/test/547-regression-trycatch-critical-edge/smali/TestCase.smali b/test/547-regression-trycatch-critic-edge/smali/TestCase.smali
similarity index 100%
rename from test/547-regression-trycatch-critical-edge/smali/TestCase.smali
rename to test/547-regression-trycatch-critic-edge/smali/TestCase.smali
diff --git a/test/547-regression-trycatch-critical-edge/src/Main.java b/test/547-regression-trycatch-critic-edge/src/Main.java
similarity index 100%
rename from test/547-regression-trycatch-critical-edge/src/Main.java
rename to test/547-regression-trycatch-critic-edge/src/Main.java
diff --git a/test/557-checker-instruction-simplifier-ror/expected.txt b/test/557-checker-instruct-simplifier-ror/expected.txt
similarity index 100%
rename from test/557-checker-instruction-simplifier-ror/expected.txt
rename to test/557-checker-instruct-simplifier-ror/expected.txt
diff --git a/test/557-checker-instruction-simplifier-ror/info.txt b/test/557-checker-instruct-simplifier-ror/info.txt
similarity index 100%
rename from test/557-checker-instruction-simplifier-ror/info.txt
rename to test/557-checker-instruct-simplifier-ror/info.txt
diff --git a/test/557-checker-instruction-simplifier-ror/src/Main.java b/test/557-checker-instruct-simplifier-ror/src/Main.java
similarity index 100%
rename from test/557-checker-instruction-simplifier-ror/src/Main.java
rename to test/557-checker-instruct-simplifier-ror/src/Main.java
diff --git a/test/580-checker-string-factory-intrinsics/expected.txt b/test/580-checker-string-fact-intrinsics/expected.txt
similarity index 100%
rename from test/580-checker-string-factory-intrinsics/expected.txt
rename to test/580-checker-string-fact-intrinsics/expected.txt
diff --git a/test/580-checker-string-factory-intrinsics/info.txt b/test/580-checker-string-fact-intrinsics/info.txt
similarity index 100%
rename from test/580-checker-string-factory-intrinsics/info.txt
rename to test/580-checker-string-fact-intrinsics/info.txt
diff --git a/test/580-checker-string-factory-intrinsics/src/Main.java b/test/580-checker-string-fact-intrinsics/src/Main.java
similarity index 100%
rename from test/580-checker-string-factory-intrinsics/src/Main.java
rename to test/580-checker-string-fact-intrinsics/src/Main.java
diff --git a/test/588-checker-irreducible-lifetime-hole/expected.txt b/test/588-checker-irreducib-lifetime-hole/expected.txt
similarity index 100%
rename from test/588-checker-irreducible-lifetime-hole/expected.txt
rename to test/588-checker-irreducib-lifetime-hole/expected.txt
diff --git a/test/588-checker-irreducible-lifetime-hole/info.txt b/test/588-checker-irreducib-lifetime-hole/info.txt
similarity index 100%
rename from test/588-checker-irreducible-lifetime-hole/info.txt
rename to test/588-checker-irreducib-lifetime-hole/info.txt
diff --git a/test/588-checker-irreducible-lifetime-hole/smali/IrreducibleLoop.smali b/test/588-checker-irreducib-lifetime-hole/smali/IrreducibleLoop.smali
similarity index 100%
rename from test/588-checker-irreducible-lifetime-hole/smali/IrreducibleLoop.smali
rename to test/588-checker-irreducib-lifetime-hole/smali/IrreducibleLoop.smali
diff --git a/test/588-checker-irreducible-lifetime-hole/src/Main.java b/test/588-checker-irreducib-lifetime-hole/src/Main.java
similarity index 100%
rename from test/588-checker-irreducible-lifetime-hole/src/Main.java
rename to test/588-checker-irreducib-lifetime-hole/src/Main.java
diff --git a/test/590-checker-array-set-null-regression/expected.txt b/test/590-checker-arr-set-null-regression/expected.txt
similarity index 100%
rename from test/590-checker-array-set-null-regression/expected.txt
rename to test/590-checker-arr-set-null-regression/expected.txt
diff --git a/test/590-checker-array-set-null-regression/info.txt b/test/590-checker-arr-set-null-regression/info.txt
similarity index 100%
rename from test/590-checker-array-set-null-regression/info.txt
rename to test/590-checker-arr-set-null-regression/info.txt
diff --git a/test/590-checker-array-set-null-regression/src/Main.java b/test/590-checker-arr-set-null-regression/src/Main.java
similarity index 100%
rename from test/590-checker-array-set-null-regression/src/Main.java
rename to test/590-checker-arr-set-null-regression/src/Main.java
diff --git a/test/593-checker-boolean-to-integral-conv/expected.txt b/test/593-checker-boolean-2-integral-conv/expected.txt
similarity index 100%
rename from test/593-checker-boolean-to-integral-conv/expected.txt
rename to test/593-checker-boolean-2-integral-conv/expected.txt
diff --git a/test/593-checker-boolean-to-integral-conv/info.txt b/test/593-checker-boolean-2-integral-conv/info.txt
similarity index 100%
rename from test/593-checker-boolean-to-integral-conv/info.txt
rename to test/593-checker-boolean-2-integral-conv/info.txt
diff --git a/test/593-checker-boolean-to-integral-conv/src/Main.java b/test/593-checker-boolean-2-integral-conv/src/Main.java
similarity index 100%
rename from test/593-checker-boolean-to-integral-conv/src/Main.java
rename to test/593-checker-boolean-2-integral-conv/src/Main.java
diff --git a/test/593-checker-long-to-float-regression/expected.txt b/test/593-checker-long-2-float-regression/expected.txt
similarity index 100%
rename from test/593-checker-long-to-float-regression/expected.txt
rename to test/593-checker-long-2-float-regression/expected.txt
diff --git a/test/593-checker-long-to-float-regression/info.txt b/test/593-checker-long-2-float-regression/info.txt
similarity index 100%
rename from test/593-checker-long-to-float-regression/info.txt
rename to test/593-checker-long-2-float-regression/info.txt
diff --git a/test/593-checker-long-to-float-regression/src/Main.java b/test/593-checker-long-2-float-regression/src/Main.java
similarity index 100%
rename from test/593-checker-long-to-float-regression/src/Main.java
rename to test/593-checker-long-2-float-regression/src/Main.java
diff --git a/test/961-default-iface-resolution-generated/build b/test/961-default-iface-resolut-generated/build
similarity index 100%
rename from test/961-default-iface-resolution-generated/build
rename to test/961-default-iface-resolut-generated/build
diff --git a/test/961-default-iface-resolution-generated/expected.txt b/test/961-default-iface-resolut-generated/expected.txt
similarity index 100%
rename from test/961-default-iface-resolution-generated/expected.txt
rename to test/961-default-iface-resolut-generated/expected.txt
diff --git a/test/961-default-iface-resolution-generated/info.txt b/test/961-default-iface-resolut-generated/info.txt
similarity index 100%
rename from test/961-default-iface-resolution-generated/info.txt
rename to test/961-default-iface-resolut-generated/info.txt
diff --git a/test/961-default-iface-resolution-generated/util-src/generate_java.py b/test/961-default-iface-resolut-generated/util-src/generate_java.py
similarity index 100%
rename from test/961-default-iface-resolution-generated/util-src/generate_java.py
rename to test/961-default-iface-resolut-generated/util-src/generate_java.py
diff --git a/test/968-default-partial-compile-generated/build b/test/968-default-part-compile-generated/build
similarity index 100%
rename from test/968-default-partial-compile-generated/build
rename to test/968-default-part-compile-generated/build
diff --git a/test/968-default-partial-compile-generated/expected.txt b/test/968-default-part-compile-generated/expected.txt
similarity index 100%
rename from test/968-default-partial-compile-generated/expected.txt
rename to test/968-default-part-compile-generated/expected.txt
diff --git a/test/968-default-partial-compile-generated/info.txt b/test/968-default-part-compile-generated/info.txt
similarity index 100%
rename from test/968-default-partial-compile-generated/info.txt
rename to test/968-default-part-compile-generated/info.txt
diff --git a/test/968-default-partial-compile-generated/util-src/generate_java.py b/test/968-default-part-compile-generated/util-src/generate_java.py
similarity index 100%
rename from test/968-default-partial-compile-generated/util-src/generate_java.py
rename to test/968-default-part-compile-generated/util-src/generate_java.py
diff --git a/test/968-default-partial-compile-generated/util-src/generate_smali.py b/test/968-default-part-compile-generated/util-src/generate_smali.py
similarity index 100%
rename from test/968-default-partial-compile-generated/util-src/generate_smali.py
rename to test/968-default-part-compile-generated/util-src/generate_smali.py
diff --git a/test/970-iface-super-resolution-generated/build b/test/970-iface-superresolution-generated/build
similarity index 100%
rename from test/970-iface-super-resolution-generated/build
rename to test/970-iface-superresolution-generated/build
diff --git a/test/970-iface-super-resolution-generated/expected.txt b/test/970-iface-superresolution-generated/expected.txt
similarity index 100%
rename from test/970-iface-super-resolution-generated/expected.txt
rename to test/970-iface-superresolution-generated/expected.txt
diff --git a/test/970-iface-super-resolution-generated/info.txt b/test/970-iface-superresolution-generated/info.txt
similarity index 100%
rename from test/970-iface-super-resolution-generated/info.txt
rename to test/970-iface-superresolution-generated/info.txt
diff --git a/test/970-iface-super-resolution-generated/util-src/generate_java.py b/test/970-iface-superresolution-generated/util-src/generate_java.py
similarity index 100%
rename from test/970-iface-super-resolution-generated/util-src/generate_java.py
rename to test/970-iface-superresolution-generated/util-src/generate_java.py
diff --git a/test/970-iface-super-resolution-generated/util-src/generate_smali.py b/test/970-iface-superresolution-generated/util-src/generate_smali.py
similarity index 100%
rename from test/970-iface-super-resolution-generated/util-src/generate_smali.py
rename to test/970-iface-superresolution-generated/util-src/generate_smali.py
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 5301a03..559e963 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -47,6 +47,14 @@
   ART_TEST_WITH_STRACE := true
 endif
 
+ifeq ($(ART_TEST_BISECTION),true)
+  # Need to keep rebuilding the test to bisection search it.
+  ART_TEST_RUN_TEST_NO_PREBUILD := true
+  ART_TEST_RUN_TEST_PREBUILD := false
+  # Bisection search writes to standard output.
+  ART_TEST_QUIET := false
+endif
+
 # Helper to create individual build targets for tests. Must be called with $(eval).
 # $(1): the test number
 define define-build-art-run-test
@@ -270,11 +278,11 @@
 # Tests that require python3.
 TEST_ART_PYTHON3_DEPENDENCY_RUN_TESTS := \
   960-default-smali \
-  961-default-iface-resolution-generated \
+  961-default-iface-resolut-generated \
   964-default-iface-init-generated \
-  968-default-partial-compile-generated \
+  968-default-part-compile-generated \
   969-iface-super \
-  970-iface-super-resolution-generated \
+  970-iface-superresolution-generated \
   971-iface-super
 
 # Check if we have python3 to run our tests.
@@ -354,12 +362,12 @@
 # Tests that are broken with GC stress.
 # * 137-cfi needs to unwind a second forked process. We're using a primitive sleep to wait till we
 #   hope the second process got into the expected state. The slowness of gcstress makes this bad.
-# * 961-default-iface-resolution-generated and 964-default-iface-init-generated are very long tests
+# * 961-default-iface-resolut-generated and 964-default-iface-init-generated are very long tests
 #   that often will take more than the timeout to run when gcstress is enabled. This is because
 #   gcstress slows down allocations significantly which these tests do a lot.
 TEST_ART_BROKEN_GCSTRESS_RUN_TESTS := \
   137-cfi \
-  961-default-iface-resolution-generated \
+  961-default-iface-resolut-generated \
   964-default-iface-init-generated
 
 ifneq (,$(filter gcstress,$(GC_TYPES)))
@@ -644,6 +652,38 @@
 
 TEST_ART_BROKEN_OPTIMIZING_HEAP_POISONING_RUN_TESTS :=
 
+# Tests incompatible with bisection bug search. Sorted by incompatibility reason.
+# 000 through 595 do not compile anything. 089 tests a build failure. 018 through 137
+# run dalvikvm more than once. 115 and 088 assume they are always compiled.
+# 055 tests performance which is degraded during bisecting.
+TEST_ART_INCOMPATIBLE_BISECTION_SEARCH_RUN_TESTS := \
+  000-nop \
+  134-nodex2oat-nofallback \
+  147-stripped-dex-fallback \
+  595-profile-saving \
+  \
+  089-many-methods \
+  \
+  018-stack-overflow \
+  116-nodex2oat \
+  117-nopatchoat \
+  118-noimage-dex2oat \
+  119-noimage-patchoat \
+  126-miranda-multidex \
+  137-cfi \
+  \
+  115-native-bridge \
+  088-monitor-verification \
+  \
+  055-enum-performance
+
+ifeq ($(ART_TEST_BISECTION),true)
+  ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES), \
+      $(PREBUILD_TYPES),$(OPTIMIZING_COMPILER_TYPES),$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES), \
+      $(IMAGE_TYPES),$(PICTEST_TYPES),$(DEBUGGABLE_TYPES), \
+      $(TEST_ART_INCOMPATIBLE_BISECTION_SEARCH_RUN_TESTS),$(ALL_ADDRESS_SIZES))
+endif
+
 # Clear variables ahead of appending to them when defining tests.
 $(foreach target, $(TARGET_TYPES), $(eval ART_RUN_TEST_$(call name-to-var,$(target))_RULES :=))
 $(foreach target, $(TARGET_TYPES), \
@@ -762,6 +802,9 @@
   ifeq ($(ART_TEST_RUN_TEST_ALWAYS_CLEAN),true)
     run_test_options += --always-clean
   endif
+  ifeq ($(ART_TEST_BISECTION),true)
+    run_test_options += --bisection-search
+  endif
   ifeq ($(1),host)
     uc_host_or_target := HOST
     test_groups := ART_RUN_TEST_HOST_RULES
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index a0e99d8..a445f4d 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -56,6 +56,8 @@
 USE_DEX2OAT_AND_PATCHOAT="y"
 INSTRUCTION_SET_FEATURES=""
 ARGS=""
+EXTERNAL_LOG_TAGS="n" # if y respect externally set ANDROID_LOG_TAGS.
+DRY_RUN="n" # if y prepare to run the test but don't run it.
 
 while true; do
     if [ "x$1" = "x--quiet" ]; then
@@ -235,6 +237,12 @@
         fi
         EXPERIMENTAL="$EXPERIMENTAL $2"
         shift 2
+    elif [ "x$1" = "x--external-log-tags" ]; then
+        EXTERNAL_LOG_TAGS="y"
+        shift
+    elif [ "x$1" = "x--dry-run" ]; then
+        DRY_RUN="y"
+        shift
     elif expr "x$1" : "x--" >/dev/null 2>&1; then
         echo "unknown $0 option: $1" 1>&2
         exit 1
@@ -493,12 +501,14 @@
 
     # Create a script with the command. The command can get longer than the longest
     # allowed adb command and there is no way to get the exit status from a adb shell
-    # command.
+    # command. Dalvik cache is cleaned before running to make subsequent executions
+    # of the script follow the same runtime path.
     cmdline="cd $DEX_LOCATION && \
              export ANDROID_DATA=$DEX_LOCATION && \
              export ANDROID_ADDITIONAL_PUBLIC_LIBRARIES=$PUBLIC_LIBS && \
              export DEX_LOCATION=$DEX_LOCATION && \
              export ANDROID_ROOT=$ANDROID_ROOT && \
+             rm -rf ${DEX_LOCATION}/dalvik-cache/ && \
              mkdir -p ${mkdir_locations} && \
              export LD_LIBRARY_PATH=$LD_LIBRARY_PATH && \
              export PATH=$ANDROID_ROOT/bin:$PATH && \
@@ -519,7 +529,9 @@
       adb push $cmdfile $DEX_LOCATION/cmdline.sh > /dev/null 2>&1
     fi
 
-    adb shell sh $DEX_LOCATION/cmdline.sh
+    if [ "$DRY_RUN" != "y" ]; then
+      adb shell sh $DEX_LOCATION/cmdline.sh
+    fi
 
     rm -f $cmdfile
 else
@@ -527,10 +539,12 @@
 
     # By default, and for prebuild dex2oat, we are interested in errors being logged. In dev mode
     # we want debug messages.
-    if [ "$DEV_MODE" = "y" ]; then
-        export ANDROID_LOG_TAGS='*:d'
-    else
-        export ANDROID_LOG_TAGS='*:e'
+    if [ "$EXTERNAL_LOG_TAGS" = "n" ]; then
+      if [ "$DEV_MODE" = "y" ]; then
+          export ANDROID_LOG_TAGS='*:d'
+      else
+          export ANDROID_LOG_TAGS='*:e'
+      fi
     fi
 
     export ANDROID_DATA="$DEX_LOCATION"
@@ -584,15 +598,21 @@
 
     # For running, we must turn off logging when dex2oat or patchoat are missing. Otherwise we use
     # the same defaults as for prebuilt: everything when --dev, otherwise errors and above only.
-    if [ "$DEV_MODE" = "y" ]; then
-        export ANDROID_LOG_TAGS='*:d'
-    elif [ "$USE_DEX2OAT_AND_PATCHOAT" = "n" ]; then
-        # All tests would log the error of failing dex2oat/patchoat. Be silent here and only
-        # log fatal events.
-        export ANDROID_LOG_TAGS='*:s'
-    else
-        # We are interested in LOG(ERROR) output.
-        export ANDROID_LOG_TAGS='*:e'
+    if [ "$EXTERNAL_LOG_TAGS" = "n" ]; then
+      if [ "$DEV_MODE" = "y" ]; then
+          export ANDROID_LOG_TAGS='*:d'
+      elif [ "$USE_DEX2OAT_AND_PATCHOAT" = "n" ]; then
+          # All tests would log the error of failing dex2oat/patchoat. Be silent here and only
+          # log fatal events.
+          export ANDROID_LOG_TAGS='*:s'
+      else
+          # We are interested in LOG(ERROR) output.
+          export ANDROID_LOG_TAGS='*:e'
+      fi
+    fi
+
+    if [ "$DRY_RUN" = "y" ]; then
+      exit 0
     fi
 
     if [ "$USE_GDB" = "y" ]; then
diff --git a/test/run-test b/test/run-test
index aea6435..ae53f9e 100755
--- a/test/run-test
+++ b/test/run-test
@@ -130,6 +130,7 @@
 pic_image_suffix=""
 multi_image_suffix=""
 android_root="/system"
+bisection_search="no"
 # By default we will use optimizing.
 image_args=""
 image_suffix=""
@@ -347,6 +348,9 @@
         shift
         run_args="${run_args} --instruction-set-features $1"
         shift
+    elif [ "x$1" = "x--bisection-search" ]; then
+        bisection_search="yes"
+        shift
     elif expr "x$1" : "x--" >/dev/null 2>&1; then
         echo "unknown $0 option: $1" 1>&2
         usage="yes"
@@ -519,6 +523,21 @@
     usage="yes"
 fi
 
+if [ "$bisection_search" = "yes" -a "$prebuild_mode" = "yes" ]; then
+    err_echo "--bisection-search and --prebuild are mutually exclusive"
+    usage="yes"
+fi
+
+if [ "$bisection_search" = "yes" -a "$have_dex2oat" = "no" ]; then
+    err_echo "--bisection-search and --no-dex2oat are mutually exclusive"
+    usage="yes"
+fi
+
+if [ "$bisection_search" = "yes" -a "$have_patchoat" = "no" ]; then
+    err_echo "--bisection-search and --no-patchoat are mutually exclusive"
+    usage="yes"
+fi
+
 if [ "$usage" = "no" ]; then
     if [ "x$1" = "x" -o "x$1" = "x-" ]; then
         test_dir=`basename "$oldwd"`
@@ -539,6 +558,13 @@
     shift
 fi
 
+# For building with javac and dx always use Java 7. The dx compiler
+# only support byte codes from Java 7 or earlier (class file major
+# version 51 or lower).
+if [ "$USE_JACK" != "true" ] && [ "$NEED_DEX" = "true" ]; then
+  export JAVAC="${JAVAC} -source 1.7 -target 1.7"
+fi
+
 if [ "$usage" = "yes" ]; then
     prog=`basename $prog`
     (
@@ -560,8 +586,8 @@
         echo "    --gdb                 Run under gdb; incompatible with some tests."
         echo "    --gdb-arg             Pass an option to gdb."
         echo "    --build-only          Build test files only (off by default)."
-        echo "    --build-with-javac-dx Build test files with javac and dx (on by default)."
-        echo "    --build-with-jack     Build test files with jack and jill (off by default)."
+        echo "    --build-with-javac-dx Build test files with javac and dx (off by default)."
+        echo "    --build-with-jack     Build test files with jack and jill (on by default)."
         echo "    --interpreter         Enable interpreter only mode (off by default)."
         echo "    --jit                 Enable jit (off by default)."
         echo "    --optimizing          Enable optimizing compiler (default)."
@@ -613,6 +639,7 @@
         echo "                          the boot class path."
         echo "    --pic-test            Compile the test code position independent."
         echo "    --quiet               Don't print anything except failure messages"
+        echo "    --bisection-search    Perform bisection bug search."
     ) 1>&2  # Direct to stderr so usage is not printed if --quiet is set.
     exit 1
 fi
@@ -881,6 +908,41 @@
 
 ) 2>&${real_stderr} 1>&2
 
+# Attempt bisection only if the test failed.
+if [ "$bisection_search" = "yes" -a "$good" != "yes" ]; then
+    # Bisecting works by skipping different optimization passes which breaks checker assertions.
+    if [ "$run_checker" == "yes" ]; then
+      echo "${test_dir}: not bisecting, checker test." 1>&2
+    else
+      # Increase file size limit, bisection search can generate large logfiles.
+      if ! ulimit -S unlimited; then
+        err_echo "ulimit file size setting failed"
+      fi
+      echo "${test_dir}: bisecting..." 1>&2
+      cwd=`pwd`
+      maybe_device_mode=""
+      raw_cmd=""
+      if [ "$target_mode" = "yes" ]; then
+        # Produce cmdline.sh in $DEX_LOCATION. "$@" is passed as a runtime option
+        # so that cmdline.sh forwards its arguments to dalvikvm. invoke-with is set
+        # to exec in order to preserve pid when calling dalvikvm. This is required
+        # for bisection search to correctly retrieve logs from device.
+        "./${run}" $run_args --runtime-option '"$@"' --invoke-with exec --dry-run "$@" &> /dev/null
+        adb shell chmod u+x "$DEX_LOCATION/cmdline.sh"
+        maybe_device_mode="--device"
+        raw_cmd="$DEX_LOCATION/cmdline.sh"
+      else
+        raw_cmd="$cwd/${run} --external-log-tags $run_args $@"
+      fi
+      $ANDROID_BUILD_TOP/art/tools/bisection_search/bisection_search.py \
+        $maybe_device_mode \
+        --raw-cmd="$raw_cmd" \
+        --check-script="$cwd/check" \
+        --expected-output="$cwd/expected.txt" \
+        --timeout=300
+    fi
+fi
+
 # Clean up test files.
 if [ "$always_clean" = "yes" -o "$good" = "yes" ] && [ "$never_clean" = "no" ]; then
     cd "$oldwd"