Merge "Revert "ART: Register allocation and runtime support for try/catch""
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 0a3f083..9895953 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -478,8 +478,6 @@
   graph_->SetEntryBlock(entry_block_);
   graph_->SetExitBlock(exit_block_);
 
-  graph_->SetHasTryCatch(code_item.tries_size_ != 0);
-
   InitializeLocals(code_item.registers_size_);
   graph_->SetMaximumNumberOfOutVRegs(code_item.outs_size_);
 
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index 3bbff6a..0bb90b2 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -248,12 +248,6 @@
 
   GenerateSlowPaths();
 
-  // Emit catch stack maps at the end of the stack map stream as expected by the
-  // runtime exception handler.
-  if (!is_baseline && graph_->HasTryCatch()) {
-    RecordCatchBlockInfo();
-  }
-
   // Finalize instructions in assember;
   Finalize(allocator);
 }
@@ -811,73 +805,6 @@
   stack_map_stream_.EndStackMapEntry();
 }
 
-void CodeGenerator::RecordCatchBlockInfo() {
-  ArenaAllocator* arena = graph_->GetArena();
-
-  for (size_t i = 0, e = block_order_->Size(); i < e; ++i) {
-    HBasicBlock* block = block_order_->Get(i);
-    if (!block->IsCatchBlock()) {
-      continue;
-    }
-
-    uint32_t dex_pc = block->GetDexPc();
-    uint32_t num_vregs = graph_->GetNumberOfVRegs();
-    uint32_t inlining_depth = 0;  // Inlining of catch blocks is not supported at the moment.
-    uint32_t native_pc = GetAddressOf(block);
-    uint32_t register_mask = 0;   // Not used.
-
-    // The stack mask is not used, so we leave it empty.
-    ArenaBitVector* stack_mask = new (arena) ArenaBitVector(arena, 0, /* expandable */ true);
-
-    stack_map_stream_.BeginStackMapEntry(dex_pc,
-                                         native_pc,
-                                         register_mask,
-                                         stack_mask,
-                                         num_vregs,
-                                         inlining_depth);
-
-    HInstruction* current_phi = block->GetFirstPhi();
-    for (size_t vreg = 0; vreg < num_vregs; ++vreg) {
-    while (current_phi != nullptr && current_phi->AsPhi()->GetRegNumber() < vreg) {
-      HInstruction* next_phi = current_phi->GetNext();
-      DCHECK(next_phi == nullptr ||
-             current_phi->AsPhi()->GetRegNumber() <= next_phi->AsPhi()->GetRegNumber())
-          << "Phis need to be sorted by vreg number to keep this a linear-time loop.";
-      current_phi = next_phi;
-    }
-
-      if (current_phi == nullptr || current_phi->AsPhi()->GetRegNumber() != vreg) {
-        stack_map_stream_.AddDexRegisterEntry(DexRegisterLocation::Kind::kNone, 0);
-      } else {
-        Location location = current_phi->GetLiveInterval()->ToLocation();
-        switch (location.GetKind()) {
-          case Location::kStackSlot: {
-            stack_map_stream_.AddDexRegisterEntry(
-                DexRegisterLocation::Kind::kInStack, location.GetStackIndex());
-            break;
-          }
-          case Location::kDoubleStackSlot: {
-            stack_map_stream_.AddDexRegisterEntry(
-                DexRegisterLocation::Kind::kInStack, location.GetStackIndex());
-            stack_map_stream_.AddDexRegisterEntry(
-                DexRegisterLocation::Kind::kInStack, location.GetHighStackIndex(kVRegSize));
-            ++vreg;
-            DCHECK_LT(vreg, num_vregs);
-            break;
-          }
-          default: {
-            // All catch phis must be allocated to a stack slot.
-            LOG(FATAL) << "Unexpected kind " << location.GetKind();
-            UNREACHABLE();
-          }
-        }
-      }
-    }
-
-    stack_map_stream_.EndStackMapEntry();
-  }
-}
-
 void CodeGenerator::EmitEnvironment(HEnvironment* environment, SlowPathCode* slow_path) {
   if (environment == nullptr) return;
 
@@ -1048,13 +975,6 @@
   }
 }
 
-bool CodeGenerator::IsImplicitNullCheckAllowed(HNullCheck* null_check) const {
-  return compiler_options_.GetImplicitNullChecks() &&
-         // Null checks which might throw into a catch block need to save live
-         // registers and therefore cannot be done implicitly.
-         !null_check->CanThrowIntoCatchBlock();
-}
-
 bool CodeGenerator::CanMoveNullCheckToUser(HNullCheck* null_check) {
   HInstruction* first_next_not_move = null_check->GetNextDisregardingMoves();
 
@@ -1070,6 +990,10 @@
     return;
   }
 
+  if (!compiler_options_.GetImplicitNullChecks()) {
+    return;
+  }
+
   if (!instr->CanDoImplicitNullCheckOn(instr->InputAt(0))) {
     return;
   }
@@ -1081,11 +1005,9 @@
   // and needs to record the pc.
   if (first_prev_not_move != nullptr && first_prev_not_move->IsNullCheck()) {
     HNullCheck* null_check = first_prev_not_move->AsNullCheck();
-    if (IsImplicitNullCheckAllowed(null_check)) {
-      // TODO: The parallel moves modify the environment. Their changes need to be
-      // reverted otherwise the stack maps at the throw point will not be correct.
-      RecordPcInfo(null_check, null_check->GetDexPc());
-    }
+    // TODO: The parallel moves modify the environment. Their changes need to be reverted
+    // otherwise the stack maps at the throw point will not be correct.
+    RecordPcInfo(null_check, null_check->GetDexPc());
   }
 }
 
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index a93d07a..b3c4d72 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -237,17 +237,6 @@
   bool CanMoveNullCheckToUser(HNullCheck* null_check);
   void MaybeRecordImplicitNullCheck(HInstruction* instruction);
 
-  // Records a stack map which the runtime might use to set catch phi values
-  // during exception delivery.
-  // TODO: Replace with a catch-entering instruction that records the environment.
-  void RecordCatchBlockInfo();
-
-  // Returns true if implicit null checks are allowed in the compiler options
-  // and if the null check is not inside a try block. We currently cannot do
-  // implicit null checks in that case because we need the NullCheckSlowPath to
-  // save live registers, which may be needed by the runtime to set catch phis.
-  bool IsImplicitNullCheckAllowed(HNullCheck* null_check) const;
-
   void AddSlowPath(SlowPathCode* slow_path) {
     slow_paths_.Add(slow_path);
   }
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index b3e38f0..a4c58b0 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -66,10 +66,6 @@
   void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
     CodeGeneratorARM* arm_codegen = down_cast<CodeGeneratorARM*>(codegen);
     __ Bind(GetEntryLabel());
-    if (instruction_->CanThrowIntoCatchBlock()) {
-      // Live registers will be restored in the catch block if caught.
-      SaveLiveRegisters(codegen, instruction_->GetLocations());
-    }
     arm_codegen->InvokeRuntime(
         QUICK_ENTRY_POINT(pThrowNullPointer), instruction_, instruction_->GetDexPc(), this);
   }
@@ -90,10 +86,6 @@
   void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
     CodeGeneratorARM* arm_codegen = down_cast<CodeGeneratorARM*>(codegen);
     __ Bind(GetEntryLabel());
-    if (instruction_->CanThrowIntoCatchBlock()) {
-      // Live registers will be restored in the catch block if caught.
-      SaveLiveRegisters(codegen, instruction_->GetLocations());
-    }
     arm_codegen->InvokeRuntime(
         QUICK_ENTRY_POINT(pThrowDivZero), instruction_, instruction_->GetDexPc(), this);
   }
@@ -158,10 +150,6 @@
     LocationSummary* locations = instruction_->GetLocations();
 
     __ Bind(GetEntryLabel());
-    if (instruction_->CanThrowIntoCatchBlock()) {
-      // Live registers will be restored in the catch block if caught.
-      SaveLiveRegisters(codegen, instruction_->GetLocations());
-    }
     // We're moving two locations to locations that could overlap, so we need a parallel
     // move resolver.
     InvokeRuntimeCallingConvention calling_convention;
@@ -2753,10 +2741,8 @@
 }
 
 void LocationsBuilderARM::VisitDivZeroCheck(HDivZeroCheck* instruction) {
-  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
-      ? LocationSummary::kCallOnSlowPath
-      : LocationSummary::kNoCall;
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
   locations->SetInAt(0, Location::RegisterOrConstant(instruction->InputAt(0)));
   if (instruction->HasUses()) {
     locations->SetOut(Location::SameAsFirstInput());
@@ -3509,10 +3495,8 @@
 }
 
 void LocationsBuilderARM::VisitNullCheck(HNullCheck* instruction) {
-  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
-      ? LocationSummary::kCallOnSlowPath
-      : LocationSummary::kNoCall;
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
   locations->SetInAt(0, Location::RequiresRegister());
   if (instruction->HasUses()) {
     locations->SetOut(Location::SameAsFirstInput());
@@ -3540,7 +3524,7 @@
 }
 
 void InstructionCodeGeneratorARM::VisitNullCheck(HNullCheck* instruction) {
-  if (codegen_->IsImplicitNullCheckAllowed(instruction)) {
+  if (codegen_->GetCompilerOptions().GetImplicitNullChecks()) {
     GenerateImplicitNullCheck(instruction);
   } else {
     GenerateExplicitNullCheck(instruction);
@@ -3879,10 +3863,8 @@
 }
 
 void LocationsBuilderARM::VisitBoundsCheck(HBoundsCheck* instruction) {
-  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
-      ? LocationSummary::kCallOnSlowPath
-      : LocationSummary::kNoCall;
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
   locations->SetInAt(0, Location::RequiresRegister());
   locations->SetInAt(1, Location::RequiresRegister());
   if (instruction->HasUses()) {
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 5094f67..6b1457b 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -198,10 +198,6 @@
     CodeGeneratorARM64* arm64_codegen = down_cast<CodeGeneratorARM64*>(codegen);
 
     __ Bind(GetEntryLabel());
-    if (instruction_->CanThrowIntoCatchBlock()) {
-      // Live registers will be restored in the catch block if caught.
-      SaveLiveRegisters(codegen, instruction_->GetLocations());
-    }
     // We're moving two locations to locations that could overlap, so we need a parallel
     // move resolver.
     InvokeRuntimeCallingConvention calling_convention;
@@ -230,10 +226,6 @@
   void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
     CodeGeneratorARM64* arm64_codegen = down_cast<CodeGeneratorARM64*>(codegen);
     __ Bind(GetEntryLabel());
-    if (instruction_->CanThrowIntoCatchBlock()) {
-      // Live registers will be restored in the catch block if caught.
-      SaveLiveRegisters(codegen, instruction_->GetLocations());
-    }
     arm64_codegen->InvokeRuntime(
         QUICK_ENTRY_POINT(pThrowDivZero), instruction_, instruction_->GetDexPc(), this);
     CheckEntrypointTypes<kQuickThrowDivZero, void, void>();
@@ -346,10 +338,6 @@
   void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
     CodeGeneratorARM64* arm64_codegen = down_cast<CodeGeneratorARM64*>(codegen);
     __ Bind(GetEntryLabel());
-    if (instruction_->CanThrowIntoCatchBlock()) {
-      // Live registers will be restored in the catch block if caught.
-      SaveLiveRegisters(codegen, instruction_->GetLocations());
-    }
     arm64_codegen->InvokeRuntime(
         QUICK_ENTRY_POINT(pThrowNullPointer), instruction_, instruction_->GetDexPc(), this);
     CheckEntrypointTypes<kQuickThrowNullPointer, void, void>();
@@ -1592,10 +1580,8 @@
 }
 
 void LocationsBuilderARM64::VisitBoundsCheck(HBoundsCheck* instruction) {
-  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
-      ? LocationSummary::kCallOnSlowPath
-      : LocationSummary::kNoCall;
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
   locations->SetInAt(0, Location::RequiresRegister());
   locations->SetInAt(1, ARM64EncodableConstantOrRegister(instruction->InputAt(1), instruction));
   if (instruction->HasUses()) {
@@ -1991,10 +1977,8 @@
 }
 
 void LocationsBuilderARM64::VisitDivZeroCheck(HDivZeroCheck* instruction) {
-  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
-      ? LocationSummary::kCallOnSlowPath
-      : LocationSummary::kNoCall;
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
   locations->SetInAt(0, Location::RegisterOrConstant(instruction->InputAt(0)));
   if (instruction->HasUses()) {
     locations->SetOut(Location::SameAsFirstInput());
@@ -2891,10 +2875,8 @@
 }
 
 void LocationsBuilderARM64::VisitNullCheck(HNullCheck* instruction) {
-  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
-      ? LocationSummary::kCallOnSlowPath
-      : LocationSummary::kNoCall;
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
   locations->SetInAt(0, Location::RequiresRegister());
   if (instruction->HasUses()) {
     locations->SetOut(Location::SameAsFirstInput());
@@ -2923,7 +2905,7 @@
 }
 
 void InstructionCodeGeneratorARM64::VisitNullCheck(HNullCheck* instruction) {
-  if (codegen_->IsImplicitNullCheckAllowed(instruction)) {
+  if (codegen_->GetCompilerOptions().GetImplicitNullChecks()) {
     GenerateImplicitNullCheck(instruction);
   } else {
     GenerateExplicitNullCheck(instruction);
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index 8d60026..10942ef 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -118,10 +118,6 @@
     LocationSummary* locations = instruction_->GetLocations();
     CodeGeneratorMIPS64* mips64_codegen = down_cast<CodeGeneratorMIPS64*>(codegen);
     __ Bind(GetEntryLabel());
-    if (instruction_->CanThrowIntoCatchBlock()) {
-      // Live registers will be restored in the catch block if caught.
-      SaveLiveRegisters(codegen, instruction_->GetLocations());
-    }
     // We're moving two locations to locations that could overlap, so we need a parallel
     // move resolver.
     InvokeRuntimeCallingConvention calling_convention;
@@ -155,10 +151,6 @@
   void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
     CodeGeneratorMIPS64* mips64_codegen = down_cast<CodeGeneratorMIPS64*>(codegen);
     __ Bind(GetEntryLabel());
-    if (instruction_->CanThrowIntoCatchBlock()) {
-      // Live registers will be restored in the catch block if caught.
-      SaveLiveRegisters(codegen, instruction_->GetLocations());
-    }
     mips64_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pThrowDivZero),
                                   instruction_,
                                   instruction_->GetDexPc(),
@@ -277,10 +269,6 @@
   void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
     CodeGeneratorMIPS64* mips64_codegen = down_cast<CodeGeneratorMIPS64*>(codegen);
     __ Bind(GetEntryLabel());
-    if (instruction_->CanThrowIntoCatchBlock()) {
-      // Live registers will be restored in the catch block if caught.
-      SaveLiveRegisters(codegen, instruction_->GetLocations());
-    }
     mips64_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pThrowNullPointer),
                                   instruction_,
                                   instruction_->GetDexPc(),
@@ -1578,10 +1566,8 @@
 }
 
 void LocationsBuilderMIPS64::VisitBoundsCheck(HBoundsCheck* instruction) {
-  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
-      ? LocationSummary::kCallOnSlowPath
-      : LocationSummary::kNoCall;
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
   locations->SetInAt(0, Location::RequiresRegister());
   locations->SetInAt(1, Location::RequiresRegister());
   if (instruction->HasUses()) {
@@ -1876,10 +1862,8 @@
 }
 
 void LocationsBuilderMIPS64::VisitDivZeroCheck(HDivZeroCheck* instruction) {
-  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
-      ? LocationSummary::kCallOnSlowPath
-      : LocationSummary::kNoCall;
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
   locations->SetInAt(0, Location::RegisterOrConstant(instruction->InputAt(0)));
   if (instruction->HasUses()) {
     locations->SetOut(Location::SameAsFirstInput());
@@ -2840,10 +2824,8 @@
 }
 
 void LocationsBuilderMIPS64::VisitNullCheck(HNullCheck* instruction) {
-  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
-      ? LocationSummary::kCallOnSlowPath
-      : LocationSummary::kNoCall;
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
   locations->SetInAt(0, Location::RequiresRegister());
   if (instruction->HasUses()) {
     locations->SetOut(Location::SameAsFirstInput());
@@ -2870,7 +2852,7 @@
 }
 
 void InstructionCodeGeneratorMIPS64::VisitNullCheck(HNullCheck* instruction) {
-  if (codegen_->IsImplicitNullCheckAllowed(instruction)) {
+  if (codegen_->GetCompilerOptions().GetImplicitNullChecks()) {
     GenerateImplicitNullCheck(instruction);
   } else {
     GenerateExplicitNullCheck(instruction);
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index dc5c86e..a5ad226 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -56,10 +56,6 @@
   void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
     CodeGeneratorX86* x86_codegen = down_cast<CodeGeneratorX86*>(codegen);
     __ Bind(GetEntryLabel());
-    if (instruction_->CanThrowIntoCatchBlock()) {
-      // Live registers will be restored in the catch block if caught.
-      SaveLiveRegisters(codegen, instruction_->GetLocations());
-    }
     x86_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pThrowNullPointer),
                                instruction_,
                                instruction_->GetDexPc(),
@@ -82,10 +78,6 @@
   void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
     CodeGeneratorX86* x86_codegen = down_cast<CodeGeneratorX86*>(codegen);
     __ Bind(GetEntryLabel());
-    if (instruction_->CanThrowIntoCatchBlock()) {
-      // Live registers will be restored in the catch block if caught.
-      SaveLiveRegisters(codegen, instruction_->GetLocations());
-    }
     x86_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pThrowDivZero),
                                instruction_,
                                instruction_->GetDexPc(),
@@ -133,10 +125,6 @@
     __ Bind(GetEntryLabel());
     // We're moving two locations to locations that could overlap, so we need a parallel
     // move resolver.
-    if (instruction_->CanThrowIntoCatchBlock()) {
-      // Live registers will be restored in the catch block if caught.
-      SaveLiveRegisters(codegen, instruction_->GetLocations());
-    }
     InvokeRuntimeCallingConvention calling_convention;
     x86_codegen->EmitParallelMoves(
         locations->InAt(0),
@@ -3051,10 +3039,8 @@
 }
 
 void LocationsBuilderX86::VisitDivZeroCheck(HDivZeroCheck* instruction) {
-  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
-      ? LocationSummary::kCallOnSlowPath
-      : LocationSummary::kNoCall;
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
   switch (instruction->GetType()) {
     case Primitive::kPrimByte:
     case Primitive::kPrimChar:
@@ -3998,11 +3984,9 @@
 }
 
 void LocationsBuilderX86::VisitNullCheck(HNullCheck* instruction) {
-  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
-      ? LocationSummary::kCallOnSlowPath
-      : LocationSummary::kNoCall;
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
-  Location loc = codegen_->IsImplicitNullCheckAllowed(instruction)
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
+  Location loc = codegen_->GetCompilerOptions().GetImplicitNullChecks()
       ? Location::RequiresRegister()
       : Location::Any();
   locations->SetInAt(0, loc);
@@ -4035,7 +4019,7 @@
     __ cmpl(Address(ESP, obj.GetStackIndex()), Immediate(0));
   } else {
     DCHECK(obj.IsConstant()) << obj;
-    DCHECK(obj.GetConstant()->IsNullConstant());
+    DCHECK_EQ(obj.GetConstant()->AsIntConstant()->GetValue(), 0);
     __ jmp(slow_path->GetEntryLabel());
     return;
   }
@@ -4043,7 +4027,7 @@
 }
 
 void InstructionCodeGeneratorX86::VisitNullCheck(HNullCheck* instruction) {
-  if (codegen_->IsImplicitNullCheckAllowed(instruction)) {
+  if (codegen_->GetCompilerOptions().GetImplicitNullChecks()) {
     GenerateImplicitNullCheck(instruction);
   } else {
     GenerateExplicitNullCheck(instruction);
@@ -4448,10 +4432,8 @@
 }
 
 void LocationsBuilderX86::VisitBoundsCheck(HBoundsCheck* instruction) {
-  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
-      ? LocationSummary::kCallOnSlowPath
-      : LocationSummary::kNoCall;
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
   locations->SetInAt(0, Location::RegisterOrConstant(instruction->InputAt(0)));
   locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
   if (instruction->HasUses()) {
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 0cf1089..0f3eb74 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -57,10 +57,6 @@
   void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
     CodeGeneratorX86_64* x64_codegen = down_cast<CodeGeneratorX86_64*>(codegen);
     __ Bind(GetEntryLabel());
-    if (instruction_->CanThrowIntoCatchBlock()) {
-      // Live registers will be restored in the catch block if caught.
-      SaveLiveRegisters(codegen, instruction_->GetLocations());
-    }
     x64_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pThrowNullPointer),
                                instruction_,
                                instruction_->GetDexPc(),
@@ -83,10 +79,6 @@
   void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
     CodeGeneratorX86_64* x64_codegen = down_cast<CodeGeneratorX86_64*>(codegen);
     __ Bind(GetEntryLabel());
-    if (instruction_->CanThrowIntoCatchBlock()) {
-      // Live registers will be restored in the catch block if caught.
-      SaveLiveRegisters(codegen, instruction_->GetLocations());
-    }
     x64_codegen->InvokeRuntime(QUICK_ENTRY_POINT(pThrowDivZero),
                                instruction_,
                                instruction_->GetDexPc(),
@@ -185,10 +177,6 @@
     LocationSummary* locations = instruction_->GetLocations();
     CodeGeneratorX86_64* x64_codegen = down_cast<CodeGeneratorX86_64*>(codegen);
     __ Bind(GetEntryLabel());
-    if (instruction_->CanThrowIntoCatchBlock()) {
-      // Live registers will be restored in the catch block if caught.
-      SaveLiveRegisters(codegen, instruction_->GetLocations());
-    }
     // We're moving two locations to locations that could overlap, so we need a parallel
     // move resolver.
     InvokeRuntimeCallingConvention calling_convention;
@@ -3206,10 +3194,8 @@
 }
 
 void LocationsBuilderX86_64::VisitDivZeroCheck(HDivZeroCheck* instruction) {
-  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
-      ? LocationSummary::kCallOnSlowPath
-      : LocationSummary::kNoCall;
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
   locations->SetInAt(0, Location::Any());
   if (instruction->HasUses()) {
     locations->SetOut(Location::SameAsFirstInput());
@@ -3762,11 +3748,9 @@
 }
 
 void LocationsBuilderX86_64::VisitNullCheck(HNullCheck* instruction) {
-  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
-      ? LocationSummary::kCallOnSlowPath
-      : LocationSummary::kNoCall;
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
-  Location loc = codegen_->IsImplicitNullCheckAllowed(instruction)
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
+  Location loc = codegen_->GetCompilerOptions().GetImplicitNullChecks()
       ? Location::RequiresRegister()
       : Location::Any();
   locations->SetInAt(0, loc);
@@ -3799,7 +3783,7 @@
     __ cmpl(Address(CpuRegister(RSP), obj.GetStackIndex()), Immediate(0));
   } else {
     DCHECK(obj.IsConstant()) << obj;
-    DCHECK(obj.GetConstant()->IsNullConstant());
+    DCHECK_EQ(obj.GetConstant()->AsIntConstant()->GetValue(), 0);
     __ jmp(slow_path->GetEntryLabel());
     return;
   }
@@ -3807,7 +3791,7 @@
 }
 
 void InstructionCodeGeneratorX86_64::VisitNullCheck(HNullCheck* instruction) {
-  if (codegen_->IsImplicitNullCheckAllowed(instruction)) {
+  if (codegen_->GetCompilerOptions().GetImplicitNullChecks()) {
     GenerateImplicitNullCheck(instruction);
   } else {
     GenerateExplicitNullCheck(instruction);
@@ -4191,10 +4175,8 @@
 }
 
 void LocationsBuilderX86_64::VisitBoundsCheck(HBoundsCheck* instruction) {
-  LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
-      ? LocationSummary::kCallOnSlowPath
-      : LocationSummary::kNoCall;
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
   locations->SetInAt(0, Location::RegisterOrConstant(instruction->InputAt(0)));
   locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
   if (instruction->HasUses()) {
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc
index 074ed71..3e35835 100644
--- a/compiler/optimizing/graph_checker.cc
+++ b/compiler/optimizing/graph_checker.cc
@@ -382,6 +382,17 @@
     }
   }
 
+  // Check Phi uniqueness (no two Phis with the same type refer to the same register).
+  for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
+    HPhi* phi = it.Current()->AsPhi();
+    if (phi->GetNextEquivalentPhiWithSameType() != nullptr) {
+      std::stringstream type_str;
+      type_str << phi->GetType();
+      AddError(StringPrintf("Equivalent phi (%d) found for VReg %d with type: %s",
+          phi->GetId(), phi->GetRegNumber(), type_str.str().c_str()));
+    }
+  }
+
   // Ensure try membership information is consistent.
   if (block->IsCatchBlock()) {
     if (block->IsTryBlock()) {
@@ -566,35 +577,6 @@
   }
 }
 
-static bool IsSameSizeConstant(HInstruction* insn1, HInstruction* insn2) {
-  return insn1->IsConstant()
-      && insn2->IsConstant()
-      && Primitive::Is64BitType(insn1->GetType()) == Primitive::Is64BitType(insn2->GetType());
-}
-
-static bool IsConstantEquivalent(HInstruction* insn1, HInstruction* insn2, BitVector* visited) {
-  if (insn1->IsPhi() &&
-      insn1->AsPhi()->IsVRegEquivalentOf(insn2) &&
-      insn1->InputCount() == insn2->InputCount()) {
-    // Testing only one of the two inputs for recursion is sufficient.
-    if (visited->IsBitSet(insn1->GetId())) {
-      return true;
-    }
-    visited->SetBit(insn1->GetId());
-
-    for (size_t i = 0, e = insn1->InputCount(); i < e; ++i) {
-      if (!IsConstantEquivalent(insn1->InputAt(i), insn2->InputAt(i), visited)) {
-        return false;
-      }
-    }
-    return true;
-  } else if (IsSameSizeConstant(insn1, insn2)) {
-    return insn1->AsConstant()->GetValueAsUint64() == insn2->AsConstant()->GetValueAsUint64();
-  } else {
-    return false;
-  }
-}
-
 void SSAChecker::VisitPhi(HPhi* phi) {
   VisitInstruction(phi);
 
@@ -654,45 +636,6 @@
       }
     }
   }
-
-  // Ensure that catch phis are sorted by their vreg number, as required by
-  // the register allocator and code generator. This does not apply to normal
-  // phis which can be constructed artifically.
-  if (phi->IsCatchPhi()) {
-    HInstruction* next_phi = phi->GetNext();
-    if (next_phi != nullptr && phi->GetRegNumber() > next_phi->AsPhi()->GetRegNumber()) {
-      AddError(StringPrintf("Catch phis %d and %d in block %d are not sorted by their "
-                            "vreg numbers.",
-                            phi->GetId(),
-                            next_phi->GetId(),
-                            phi->GetBlock()->GetBlockId()));
-    }
-  }
-
-  // Test phi equivalents. There should not be two of the same type and they
-  // should only be created for constants which were untyped in DEX.
-  for (HInstructionIterator phi_it(phi->GetBlock()->GetPhis()); !phi_it.Done(); phi_it.Advance()) {
-    HPhi* other_phi = phi_it.Current()->AsPhi();
-    if (phi != other_phi && phi->GetRegNumber() == other_phi->GetRegNumber()) {
-      if (phi->GetType() == other_phi->GetType()) {
-        std::stringstream type_str;
-        type_str << phi->GetType();
-        AddError(StringPrintf("Equivalent phi (%d) found for VReg %d with type: %s.",
-                              phi->GetId(),
-                              phi->GetRegNumber(),
-                              type_str.str().c_str()));
-      } else {
-        ArenaBitVector visited(GetGraph()->GetArena(), 0, /* expandable */ true);
-        if (!IsConstantEquivalent(phi, other_phi, &visited)) {
-          AddError(StringPrintf("Two phis (%d and %d) found for VReg %d but they "
-                                "are not equivalents of constants.",
-                                phi->GetId(),
-                                other_phi->GetId(),
-                                phi->GetRegNumber()));
-        }
-      }
-    }
-  }
 }
 
 void SSAChecker::HandleBooleanInput(HInstruction* instruction, size_t input_index) {
diff --git a/compiler/optimizing/licm_test.cc b/compiler/optimizing/licm_test.cc
index ec4a9ec..bc4a663 100644
--- a/compiler/optimizing/licm_test.cc
+++ b/compiler/optimizing/licm_test.cc
@@ -63,8 +63,8 @@
     // Provide boiler-plate instructions.
     parameter_ = new (&allocator_) HParameterValue(0, Primitive::kPrimNot);
     entry_->AddInstruction(parameter_);
-    constant_ = graph_->GetIntConstant(42);
-    loop_preheader_->AddInstruction(new (&allocator_) HGoto());
+    constant_ = new (&allocator_) HConstant(Primitive::kPrimInt);
+    loop_preheader_->AddInstruction(constant_);
     loop_header_->AddInstruction(new (&allocator_) HIf(parameter_));
     loop_body_->AddInstruction(new (&allocator_) HGoto());
     exit_->AddInstruction(new (&allocator_) HExit());
@@ -99,6 +99,23 @@
 // The actual LICM tests.
 //
 
+TEST_F(LICMTest, ConstantHoisting) {
+  BuildLoop();
+
+  // Populate the loop with instructions: set array to constant.
+  HInstruction* constant = new (&allocator_) HConstant(Primitive::kPrimDouble);
+  loop_body_->InsertInstructionBefore(constant, loop_body_->GetLastInstruction());
+  HInstruction* set_array = new (&allocator_) HArraySet(
+      parameter_, constant_, constant, Primitive::kPrimDouble, 0);
+  loop_body_->InsertInstructionBefore(set_array, loop_body_->GetLastInstruction());
+
+  EXPECT_EQ(constant->GetBlock(), loop_body_);
+  EXPECT_EQ(set_array->GetBlock(), loop_body_);
+  PerformLICM();
+  EXPECT_EQ(constant->GetBlock(), loop_preheader_);
+  EXPECT_EQ(set_array->GetBlock(), loop_body_);
+}
+
 TEST_F(LICMTest, FieldHoisting) {
   BuildLoop();
 
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 46ef04a..b3cf0b3 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -345,6 +345,16 @@
   }
 }
 
+bool HGraph::HasTryCatch() const {
+  for (size_t i = 0, e = blocks_.Size(); i < e; ++i) {
+    HBasicBlock* block = blocks_.Get(i);
+    if (block != nullptr && (block->IsTryBlock() || block->IsCatchBlock())) {
+      return true;
+    }
+  }
+  return false;
+}
+
 void HGraph::SimplifyCFG() {
   // Simplify the CFG for future analysis, and code generation:
   // (1): Split critical edges.
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index d52a4f7..5ec3f22 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -157,7 +157,6 @@
         number_of_in_vregs_(0),
         temporaries_vreg_slots_(0),
         has_bounds_checks_(false),
-        has_try_catch_(false),
         debuggable_(debuggable),
         current_instruction_id_(start_instruction_id),
         dex_file_(dex_file),
@@ -283,6 +282,7 @@
   }
 
   uint16_t GetNumberOfVRegs() const {
+    DCHECK(!in_ssa_form_);
     return number_of_vregs_;
   }
 
@@ -360,8 +360,8 @@
     return instruction_set_;
   }
 
-  bool HasTryCatch() const { return has_try_catch_; }
-  void SetHasTryCatch(bool value) { has_try_catch_ = value; }
+  // TODO: Remove once the full compilation pipeline is enabled for try/catch.
+  bool HasTryCatch() const;
 
  private:
   void VisitBlockForDominatorTree(HBasicBlock* block,
@@ -433,10 +433,6 @@
   // Has bounds checks. We can totally skip BCE if it's false.
   bool has_bounds_checks_;
 
-  // Flag whether there are any try/catch blocks in the graph. We will skip
-  // try/catch-related passes if false.
-  bool has_try_catch_;
-
   // Indicates whether the graph should be compiled in a way that
   // ensures full debuggability. If false, we can apply more
   // aggressive optimizations that may limit the level of debugging.
@@ -2191,8 +2187,6 @@
   virtual bool IsZero() const { return false; }
   virtual bool IsOne() const { return false; }
 
-  virtual uint64_t GetValueAsUint64() const = 0;
-
   DECLARE_INSTRUCTION(Constant);
 
  private:
@@ -2205,8 +2199,6 @@
     return true;
   }
 
-  uint64_t GetValueAsUint64() const OVERRIDE { return 0; }
-
   size_t ComputeHashCode() const OVERRIDE { return 0; }
 
   DECLARE_INSTRUCTION(NullConstant);
@@ -2224,8 +2216,6 @@
  public:
   int32_t GetValue() const { return value_; }
 
-  uint64_t GetValueAsUint64() const OVERRIDE { return static_cast<uint64_t>(value_); }
-
   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
     DCHECK(other->IsIntConstant());
     return other->AsIntConstant()->value_ == value_;
@@ -2257,8 +2247,6 @@
  public:
   int64_t GetValue() const { return value_; }
 
-  uint64_t GetValueAsUint64() const OVERRIDE { return value_; }
-
   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
     DCHECK(other->IsLongConstant());
     return other->AsLongConstant()->value_ == value_;
@@ -2878,13 +2866,10 @@
  public:
   float GetValue() const { return value_; }
 
-  uint64_t GetValueAsUint64() const OVERRIDE {
-    return static_cast<uint64_t>(bit_cast<uint32_t, float>(value_));
-  }
-
   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
     DCHECK(other->IsFloatConstant());
-    return other->AsFloatConstant()->GetValueAsUint64() == GetValueAsUint64();
+    return bit_cast<uint32_t, float>(other->AsFloatConstant()->value_) ==
+        bit_cast<uint32_t, float>(value_);
   }
 
   size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
@@ -2922,11 +2907,10 @@
  public:
   double GetValue() const { return value_; }
 
-  uint64_t GetValueAsUint64() const OVERRIDE { return bit_cast<uint64_t, double>(value_); }
-
   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
     DCHECK(other->IsDoubleConstant());
-    return other->AsDoubleConstant()->GetValueAsUint64() == GetValueAsUint64();
+    return bit_cast<uint64_t, double>(other->AsDoubleConstant()->value_) ==
+        bit_cast<uint64_t, double>(value_);
   }
 
   size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
@@ -4019,13 +4003,6 @@
   bool IsDead() const { return !is_live_; }
   bool IsLive() const { return is_live_; }
 
-  bool IsVRegEquivalentOf(HInstruction* other) const {
-    return other != nullptr
-        && other->IsPhi()
-        && other->AsPhi()->GetBlock() == GetBlock()
-        && other->AsPhi()->GetRegNumber() == GetRegNumber();
-  }
-
   // Returns the next equivalent phi (starting from the current one) or null if there is none.
   // An equivalent phi is a phi having the same dex register and type.
   // It assumes that phis with the same dex register are adjacent.
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 0099b21..f549ba8 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -485,43 +485,34 @@
 
   RunOptimizations(optimizations1, arraysize(optimizations1), pass_observer);
 
-  // TODO: Update passes incompatible with try/catch so we have the same
-  //       pipeline for all methods.
   if (graph->HasTryCatch()) {
-    HOptimization* optimizations2[] = {
-      side_effects,
-      gvn,
-      dce2,
-      // The codegen has a few assumptions that only the instruction simplifier
-      // can satisfy. For example, the code generator does not expect to see a
-      // HTypeConversion from a type to the same type.
-      simplify4,
-    };
-
-    RunOptimizations(optimizations2, arraysize(optimizations2), pass_observer);
-  } else {
-    MaybeRunInliner(graph, driver, stats, dex_compilation_unit, pass_observer, handles);
-
-    HOptimization* optimizations2[] = {
-      // BooleanSimplifier depends on the InstructionSimplifier removing
-      // redundant suspend checks to recognize empty blocks.
-      boolean_simplify,
-      fold2,  // TODO: if we don't inline we can also skip fold2.
-      side_effects,
-      gvn,
-      licm,
-      bce,
-      simplify3,
-      dce2,
-      // The codegen has a few assumptions that only the instruction simplifier
-      // can satisfy. For example, the code generator does not expect to see a
-      // HTypeConversion from a type to the same type.
-      simplify4,
-    };
-
-    RunOptimizations(optimizations2, arraysize(optimizations2), pass_observer);
+    // TODO: Update the optimizations below to work correctly under try/catch
+    //       semantics. The optimizations above suffice for running codegen
+    //       in the meanwhile.
+    return;
   }
 
+  MaybeRunInliner(graph, driver, stats, dex_compilation_unit, pass_observer, handles);
+
+  HOptimization* optimizations2[] = {
+    // BooleanSimplifier depends on the InstructionSimplifier removing redundant
+    // suspend checks to recognize empty blocks.
+    boolean_simplify,
+    fold2,  // TODO: if we don't inline we can also skip fold2.
+    side_effects,
+    gvn,
+    licm,
+    bce,
+    simplify3,
+    dce2,
+    // The codegen has a few assumptions that only the instruction simplifier can
+    // satisfy. For example, the code generator does not expect to see a
+    // HTypeConversion from a type to the same type.
+    simplify4,
+  };
+
+  RunOptimizations(optimizations2, arraysize(optimizations2), pass_observer);
+
   RunArchOptimizations(driver->GetInstructionSet(), graph, stats, pass_observer);
 }
 
@@ -575,6 +566,11 @@
   RunOptimizations(graph, compiler_driver, compilation_stats_.get(),
                    dex_compilation_unit, pass_observer, &handles);
 
+  if (graph->HasTryCatch()) {
+    soa.Self()->TransitionFromSuspendedToRunnable();
+    return nullptr;
+  }
+
   AllocateRegisters(graph, codegen, pass_observer);
 
   ArenaAllocator* arena = graph->GetArena();
diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc
index a4f1f45..6f1f6af 100644
--- a/compiler/optimizing/register_allocator.cc
+++ b/compiler/optimizing/register_allocator.cc
@@ -56,7 +56,6 @@
         long_spill_slots_(allocator, kDefaultNumberOfSpillSlots),
         float_spill_slots_(allocator, kDefaultNumberOfSpillSlots),
         double_spill_slots_(allocator, kDefaultNumberOfSpillSlots),
-        catch_phi_spill_slots_(0),
         safepoints_(allocator, 0),
         processing_core_registers_(false),
         number_of_registers_(-1),
@@ -125,7 +124,9 @@
   }
 }
 
-void RegisterAllocator::BlockRegister(Location location, size_t start, size_t end) {
+void RegisterAllocator::BlockRegister(Location location,
+                                      size_t start,
+                                      size_t end) {
   int reg = location.reg();
   DCHECK(location.IsRegister() || location.IsFpuRegister());
   LiveInterval* interval = location.IsRegister()
@@ -146,19 +147,6 @@
   interval->AddRange(start, end);
 }
 
-void RegisterAllocator::BlockRegisters(size_t start, size_t end, bool caller_save_only) {
-  for (size_t i = 0; i < codegen_->GetNumberOfCoreRegisters(); ++i) {
-    if (!caller_save_only || !codegen_->IsCoreCalleeSaveRegister(i)) {
-      BlockRegister(Location::RegisterLocation(i), start, end);
-    }
-  }
-  for (size_t i = 0; i < codegen_->GetNumberOfFloatingPointRegisters(); ++i) {
-    if (!caller_save_only || !codegen_->IsFloatingPointCalleeSaveRegister(i)) {
-      BlockRegister(Location::FpuRegisterLocation(i), start, end);
-    }
-  }
-}
-
 void RegisterAllocator::AllocateRegistersInternal() {
   // Iterate post-order, to ensure the list is sorted, and the last added interval
   // is the one with the lowest start position.
@@ -171,13 +159,6 @@
     for (HInstructionIterator inst_it(block->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
       ProcessInstruction(inst_it.Current());
     }
-
-    if (block->IsCatchBlock()) {
-      // By blocking all registers at the top of each catch block, we force
-      // intervals used after catch to spill.
-      size_t position = block->GetLifetimeStart();
-      BlockRegisters(position, position + 1);
-    }
   }
 
   number_of_registers_ = codegen_->GetNumberOfCoreRegisters();
@@ -294,7 +275,21 @@
   }
 
   if (locations->WillCall()) {
-    BlockRegisters(position, position + 1, /* caller_save_only */ true);
+    // Block all registers.
+    for (size_t i = 0; i < codegen_->GetNumberOfCoreRegisters(); ++i) {
+      if (!codegen_->IsCoreCalleeSaveRegister(i)) {
+        BlockRegister(Location::RegisterLocation(i),
+                      position,
+                      position + 1);
+      }
+    }
+    for (size_t i = 0; i < codegen_->GetNumberOfFloatingPointRegisters(); ++i) {
+      if (!codegen_->IsFloatingPointCalleeSaveRegister(i)) {
+        BlockRegister(Location::FpuRegisterLocation(i),
+                      position,
+                      position + 1);
+      }
+    }
   }
 
   for (size_t i = 0; i < instruction->InputCount(); ++i) {
@@ -383,10 +378,6 @@
     DCHECK(output.IsUnallocated() || output.IsConstant());
   }
 
-  if (instruction->IsPhi() && instruction->AsPhi()->IsCatchPhi()) {
-    AllocateSpillSlotForCatchPhi(instruction->AsPhi());
-  }
-
   // If needed, add interval to the list of unhandled intervals.
   if (current->HasSpillSlot() || instruction->IsConstant()) {
     // Split just before first register use.
@@ -1291,8 +1282,6 @@
   }
 
   HInstruction* defined_by = parent->GetDefinedBy();
-  DCHECK(!defined_by->IsPhi() || !defined_by->AsPhi()->IsCatchPhi());
-
   if (defined_by->IsParameterValue()) {
     // Parameters have their own stack slot.
     parent->SetSpillSlot(codegen_->GetStackSlotOfParameter(defined_by->AsParameterValue()));
@@ -1309,6 +1298,12 @@
     return;
   }
 
+  LiveInterval* last_sibling = interval;
+  while (last_sibling->GetNextSibling() != nullptr) {
+    last_sibling = last_sibling->GetNextSibling();
+  }
+  size_t end = last_sibling->GetEnd();
+
   GrowableArray<size_t>* spill_slots = nullptr;
   switch (interval->GetType()) {
     case Primitive::kPrimDouble:
@@ -1341,7 +1336,6 @@
     }
   }
 
-  size_t end = interval->GetLastSibling()->GetEnd();
   if (parent->NeedsTwoSpillSlots()) {
     if (slot == spill_slots->Size()) {
       // We need a new spill slot.
@@ -1377,28 +1371,6 @@
       || destination.IsDoubleStackSlot();
 }
 
-void RegisterAllocator::AllocateSpillSlotForCatchPhi(HPhi* phi) {
-  LiveInterval* interval = phi->GetLiveInterval();
-
-  HInstruction* previous_phi = phi->GetPrevious();
-  DCHECK(previous_phi == nullptr ||
-         previous_phi->AsPhi()->GetRegNumber() <= phi->GetRegNumber())
-      << "Phis expected to be sorted by vreg number, so that equivalent phis are adjacent.";
-
-  if (phi->IsVRegEquivalentOf(previous_phi)) {
-    // This is an equivalent of the previous phi. We need to assign the same
-    // catch phi slot.
-    DCHECK(previous_phi->GetLiveInterval()->HasSpillSlot());
-    interval->SetSpillSlot(previous_phi->GetLiveInterval()->GetSpillSlot());
-  } else {
-    // Allocate a new spill slot for this catch phi.
-    // TODO: Reuse spill slots when intervals of phis from different catch
-    //       blocks do not overlap.
-    interval->SetSpillSlot(catch_phi_spill_slots_);
-    catch_phi_spill_slots_ += interval->NeedsTwoSpillSlots() ? 2 : 1;
-  }
-}
-
 void RegisterAllocator::AddMove(HParallelMove* move,
                                 Location source,
                                 Location destination,
@@ -1525,7 +1497,7 @@
   DCHECK(IsValidDestination(destination)) << destination;
   if (source.Equals(destination)) return;
 
-  DCHECK_EQ(block->NumberOfNormalSuccessors(), 1u);
+  DCHECK_EQ(block->GetSuccessors().size(), 1u);
   HInstruction* last = block->GetLastInstruction();
   // We insert moves at exit for phi predecessors and connecting blocks.
   // A block ending with an if cannot branch to a block with phis because
@@ -1752,7 +1724,7 @@
 
   // If `from` has only one successor, we can put the moves at the exit of it. Otherwise
   // we need to put the moves at the entry of `to`.
-  if (from->NumberOfNormalSuccessors() == 1) {
+  if (from->GetSuccessors().size() == 1) {
     InsertParallelMoveAtExitOf(from,
                                interval->GetParent()->GetDefinedBy(),
                                source->ToLocation(),
@@ -1796,25 +1768,17 @@
     } else if (instruction->IsCurrentMethod()) {
       // The current method is always at offset 0.
       DCHECK(!current->HasSpillSlot() || (current->GetSpillSlot() == 0));
-    } else if (instruction->IsPhi() && instruction->AsPhi()->IsCatchPhi()) {
-      DCHECK(current->HasSpillSlot());
-      size_t slot = current->GetSpillSlot()
-                    + GetNumberOfSpillSlots()
-                    + reserved_out_slots_
-                    - catch_phi_spill_slots_;
-      current->SetSpillSlot(slot * kVRegSize);
     } else if (current->HasSpillSlot()) {
       // Adjust the stack slot, now that we know the number of them for each type.
       // The way this implementation lays out the stack is the following:
-      // [parameter slots       ]
-      // [catch phi spill slots ]
-      // [double spill slots    ]
-      // [long spill slots      ]
-      // [float spill slots     ]
-      // [int/ref values        ]
-      // [maximum out values    ] (number of arguments for calls)
-      // [art method            ].
-      size_t slot = current->GetSpillSlot();
+      // [parameter slots     ]
+      // [double spill slots  ]
+      // [long spill slots    ]
+      // [float spill slots   ]
+      // [int/ref values      ]
+      // [maximum out values  ] (number of arguments for calls)
+      // [art method          ].
+      uint32_t slot = current->GetSpillSlot();
       switch (current->GetType()) {
         case Primitive::kPrimDouble:
           slot += long_spill_slots_.Size();
@@ -1864,22 +1828,12 @@
   // Resolve non-linear control flow across branches. Order does not matter.
   for (HLinearOrderIterator it(*codegen_->GetGraph()); !it.Done(); it.Advance()) {
     HBasicBlock* block = it.Current();
-    if (block->IsCatchBlock()) {
-      // Instructions live at the top of catch blocks were forced to spill.
-      if (kIsDebugBuild) {
-        BitVector* live = liveness_.GetLiveInSet(*block);
-        for (uint32_t idx : live->Indexes()) {
-          LiveInterval* interval = liveness_.GetInstructionFromSsaIndex(idx)->GetLiveInterval();
-          DCHECK(!interval->GetSiblingAt(block->GetLifetimeStart())->HasRegister());
-        }
-      }
-    } else {
-      BitVector* live = liveness_.GetLiveInSet(*block);
-      for (uint32_t idx : live->Indexes()) {
-        LiveInterval* interval = liveness_.GetInstructionFromSsaIndex(idx)->GetLiveInterval();
-        for (HBasicBlock* predecessor : block->GetPredecessors()) {
-          ConnectSplitSiblings(interval, predecessor, block);
-        }
+    BitVector* live = liveness_.GetLiveInSet(*block);
+    for (uint32_t idx : live->Indexes()) {
+      HInstruction* current = liveness_.GetInstructionFromSsaIndex(idx);
+      LiveInterval* interval = current->GetLiveInterval();
+      for (HBasicBlock* predecessor : block->GetPredecessors()) {
+        ConnectSplitSiblings(interval, predecessor, block);
       }
     }
   }
@@ -1887,20 +1841,16 @@
   // Resolve phi inputs. Order does not matter.
   for (HLinearOrderIterator it(*codegen_->GetGraph()); !it.Done(); it.Advance()) {
     HBasicBlock* current = it.Current();
-    if (current->IsCatchBlock()) {
-      // Catch phi values are set at runtime by the exception delivery mechanism.
-    } else {
-      for (HInstructionIterator inst_it(current->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
-        HInstruction* phi = inst_it.Current();
-        for (size_t i = 0, e = current->GetPredecessors().size(); i < e; ++i) {
-          HBasicBlock* predecessor = current->GetPredecessor(i);
-          DCHECK_EQ(predecessor->NumberOfNormalSuccessors(), 1u);
-          HInstruction* input = phi->InputAt(i);
-          Location source = input->GetLiveInterval()->GetLocationAt(
-              predecessor->GetLifetimeEnd() - 1);
-          Location destination = phi->GetLiveInterval()->ToLocation();
-          InsertParallelMoveAtExitOf(predecessor, phi, source, destination);
-        }
+    for (HInstructionIterator inst_it(current->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
+      HInstruction* phi = inst_it.Current();
+      for (size_t i = 0, e = current->GetPredecessors().size(); i < e; ++i) {
+        HBasicBlock* predecessor = current->GetPredecessor(i);
+        DCHECK_EQ(predecessor->GetSuccessors().size(), 1u);
+        HInstruction* input = phi->InputAt(i);
+        Location source = input->GetLiveInterval()->GetLocationAt(
+            predecessor->GetLifetimeEnd() - 1);
+        Location destination = phi->GetLiveInterval()->ToLocation();
+        InsertParallelMoveAtExitOf(predecessor, phi, source, destination);
       }
     }
   }
diff --git a/compiler/optimizing/register_allocator.h b/compiler/optimizing/register_allocator.h
index e030464..c29fe75 100644
--- a/compiler/optimizing/register_allocator.h
+++ b/compiler/optimizing/register_allocator.h
@@ -29,7 +29,6 @@
 class HGraph;
 class HInstruction;
 class HParallelMove;
-class HPhi;
 class LiveInterval;
 class Location;
 class SsaLivenessAnalysis;
@@ -73,8 +72,7 @@
     return int_spill_slots_.Size()
         + long_spill_slots_.Size()
         + float_spill_slots_.Size()
-        + double_spill_slots_.Size()
-        + catch_phi_spill_slots_;
+        + double_spill_slots_.Size();
   }
 
   static constexpr const char* kRegisterAllocatorPassName = "register";
@@ -101,17 +99,10 @@
 
   // Update the interval for the register in `location` to cover [start, end).
   void BlockRegister(Location location, size_t start, size_t end);
-  void BlockRegisters(size_t start, size_t end, bool caller_save_only = false);
 
-  // Allocate a spill slot for the given interval. Should be called in linear
-  // order of interval starting positions.
+  // Allocate a spill slot for the given interval.
   void AllocateSpillSlotFor(LiveInterval* interval);
 
-  // Allocate a spill slot for the given catch phi. Will allocate the same slot
-  // for phis which share the same vreg. Must be called in reverse linear order
-  // of lifetime positions and ascending vreg numbers for correctness.
-  void AllocateSpillSlotForCatchPhi(HPhi* phi);
-
   // Connect adjacent siblings within blocks.
   void ConnectSiblings(LiveInterval* interval);
 
@@ -211,11 +202,6 @@
   GrowableArray<size_t> float_spill_slots_;
   GrowableArray<size_t> double_spill_slots_;
 
-  // Spill slots allocated to catch phis. This category is special-cased because
-  // (1) slots are allocated prior to linear scan and in reverse linear order,
-  // (2) equivalent phis need to share slots despite having different types.
-  size_t catch_phi_spill_slots_;
-
   // Instructions that need a safepoint.
   GrowableArray<HInstruction*> safepoints_;
 
diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc
index 63635f3..0c1831b 100644
--- a/compiler/optimizing/ssa_liveness_analysis.cc
+++ b/compiler/optimizing/ssa_liveness_analysis.cc
@@ -186,25 +186,14 @@
     // as live_in.
     for (HBasicBlock* successor : block->GetSuccessors()) {
       live_in->Union(GetLiveInSet(*successor));
-      if (successor->IsCatchBlock()) {
-        // Inputs of catch phis will be kept alive through their environment
-        // uses, allowing the runtime to copy their values to the corresponding
-        // catch phi spill slots when an exception is thrown.
-        // The only instructions which may not be recorded in the environments
-        // are constants created by the SSA builder as typed equivalents of
-        // untyped constants from the bytecode, or phis with only such constants
-        // as inputs (verified by SSAChecker). Their raw binary value must
-        // therefore be the same and we only need to keep alive one.
-      } else {
-        size_t phi_input_index = successor->GetPredecessorIndexOf(block);
-        for (HInstructionIterator phi_it(successor->GetPhis()); !phi_it.Done(); phi_it.Advance()) {
-          HInstruction* phi = phi_it.Current();
-          HInstruction* input = phi->InputAt(phi_input_index);
-          input->GetLiveInterval()->AddPhiUse(phi, phi_input_index, block);
-          // A phi input whose last user is the phi dies at the end of the predecessor block,
-          // and not at the phi's lifetime position.
-          live_in->SetBit(input->GetSsaIndex());
-        }
+      size_t phi_input_index = successor->GetPredecessorIndexOf(block);
+      for (HInstructionIterator inst_it(successor->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
+        HInstruction* phi = inst_it.Current();
+        HInstruction* input = phi->InputAt(phi_input_index);
+        input->GetLiveInterval()->AddPhiUse(phi, phi_input_index, block);
+        // A phi input whose last user is the phi dies at the end of the predecessor block,
+        // and not at the phi's lifetime position.
+        live_in->SetBit(input->GetSsaIndex());
       }
     }
 
diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h
index ef396cb..a7044de 100644
--- a/compiler/optimizing/ssa_liveness_analysis.h
+++ b/compiler/optimizing/ssa_liveness_analysis.h
@@ -1209,9 +1209,6 @@
     // A value that's not live in compiled code may still be needed in interpreter,
     // due to code motion, etc.
     if (env_holder->IsDeoptimize()) return true;
-    // A value live at a throwing instruction in a try block may be copied by
-    // the exception handler to its location at the top of the catch block.
-    if (env_holder->CanThrowIntoCatchBlock()) return true;
     if (instruction->GetBlock()->GetGraph()->IsDebuggable()) return true;
     return instruction->GetType() == Primitive::kPrimNot;
   }
diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc
index 1f0bac5..1f1530f 100644
--- a/compiler/optimizing/stack_map_stream.cc
+++ b/compiler/optimizing/stack_map_stream.cc
@@ -286,7 +286,7 @@
         stack_map.SetDexRegisterMapOffset(
             stack_map_encoding_,
             code_info.GetStackMapAt(entry.same_dex_register_map_as_, stack_map_encoding_)
-                .GetDexRegisterMapOffset(stack_map_encoding_));
+                     .GetDexRegisterMapOffset(stack_map_encoding_));
       } else {
         // New dex registers maps should be added to the stack map.
         MemoryRegion register_region = dex_register_locations_region.Subregion(
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index 65f41cc..5dbea52 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -225,41 +225,26 @@
 
 uintptr_t ArtMethod::ToNativeQuickPc(const uint32_t dex_pc, bool abort_on_failure) {
   const void* entry_point = GetQuickOatEntryPoint(sizeof(void*));
-  if (IsOptimized(sizeof(void*))) {
-    // Optimized code does not have a mapping table. Search for the dex-to-pc
-    // mapping in stack maps.
-    CodeInfo code_info = GetOptimizedCodeInfo();
-    StackMapEncoding encoding = code_info.ExtractEncoding();
-
-    // Assume the caller needs the mapping for a catch handler. If there are
-    // multiple stack maps for this dex_pc, it will hit the catch stack map first.
-    StackMap stack_map = code_info.GetCatchStackMapForDexPc(dex_pc, encoding);
-    if (stack_map.IsValid()) {
-      return reinterpret_cast<uintptr_t>(entry_point) + stack_map.GetNativePcOffset(encoding);
-    }
-  } else {
-    MappingTable table(entry_point != nullptr ?
-        GetMappingTable(EntryPointToCodePointer(entry_point), sizeof(void*)) : nullptr);
-    if (table.TotalSize() == 0) {
-      DCHECK_EQ(dex_pc, 0U);
-      return 0;   // Special no mapping/pc == 0 case
-    }
-    // Assume the caller wants a dex-to-pc mapping so check here first.
-    typedef MappingTable::DexToPcIterator It;
-    for (It cur = table.DexToPcBegin(), end = table.DexToPcEnd(); cur != end; ++cur) {
-      if (cur.DexPc() == dex_pc) {
-        return reinterpret_cast<uintptr_t>(entry_point) + cur.NativePcOffset();
-      }
-    }
-    // Now check pc-to-dex mappings.
-    typedef MappingTable::PcToDexIterator It2;
-    for (It2 cur = table.PcToDexBegin(), end = table.PcToDexEnd(); cur != end; ++cur) {
-      if (cur.DexPc() == dex_pc) {
-        return reinterpret_cast<uintptr_t>(entry_point) + cur.NativePcOffset();
-      }
+  MappingTable table(entry_point != nullptr ?
+      GetMappingTable(EntryPointToCodePointer(entry_point), sizeof(void*)) : nullptr);
+  if (table.TotalSize() == 0) {
+    DCHECK_EQ(dex_pc, 0U);
+    return 0;   // Special no mapping/pc == 0 case
+  }
+  // Assume the caller wants a dex-to-pc mapping so check here first.
+  typedef MappingTable::DexToPcIterator It;
+  for (It cur = table.DexToPcBegin(), end = table.DexToPcEnd(); cur != end; ++cur) {
+    if (cur.DexPc() == dex_pc) {
+      return reinterpret_cast<uintptr_t>(entry_point) + cur.NativePcOffset();
     }
   }
-
+  // Now check pc-to-dex mappings.
+  typedef MappingTable::PcToDexIterator It2;
+  for (It2 cur = table.PcToDexBegin(), end = table.PcToDexEnd(); cur != end; ++cur) {
+    if (cur.DexPc() == dex_pc) {
+      return reinterpret_cast<uintptr_t>(entry_point) + cur.NativePcOffset();
+    }
+  }
   if (abort_on_failure) {
     LOG(FATAL) << "Failed to find native offset for dex pc 0x" << std::hex << dex_pc
                << " in " << PrettyMethod(this);
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index b9d76b4..60defba 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -146,107 +146,6 @@
     // Put exception back in root set with clear throw location.
     self_->SetException(exception_ref.Get());
   }
-  // If the handler is in optimized code, we need to set the catch environment.
-  if (*handler_quick_frame_ != nullptr &&
-      handler_method_ != nullptr &&
-      handler_method_->IsOptimized(sizeof(void*))) {
-    SetCatchEnvironmentForOptimizedHandler(&visitor);
-  }
-}
-
-static VRegKind ToVRegKind(DexRegisterLocation::Kind kind) {
-  // Slightly hacky since we cannot map DexRegisterLocationKind and VRegKind
-  // one to one. However, StackVisitor::GetVRegFromOptimizedCode only needs to
-  // distinguish between core/FPU registers and low/high bits on 64-bit.
-  switch (kind) {
-    case DexRegisterLocation::Kind::kConstant:
-    case DexRegisterLocation::Kind::kInStack:
-      // VRegKind is ignored.
-      return VRegKind::kUndefined;
-
-    case DexRegisterLocation::Kind::kInRegister:
-      // Selects core register. For 64-bit registers, selects low 32 bits.
-      return VRegKind::kLongLoVReg;
-
-    case DexRegisterLocation::Kind::kInRegisterHigh:
-      // Selects core register. For 64-bit registers, selects high 32 bits.
-      return VRegKind::kLongHiVReg;
-
-    case DexRegisterLocation::Kind::kInFpuRegister:
-      // Selects FPU register. For 64-bit registers, selects low 32 bits.
-      return VRegKind::kDoubleLoVReg;
-
-    case DexRegisterLocation::Kind::kInFpuRegisterHigh:
-      // Selects FPU register. For 64-bit registers, selects high 32 bits.
-      return VRegKind::kDoubleHiVReg;
-
-    default:
-      LOG(FATAL) << "Unexpected vreg location "
-                 << DexRegisterLocation::PrettyDescriptor(kind);
-      UNREACHABLE();
-  }
-}
-
-void QuickExceptionHandler::SetCatchEnvironmentForOptimizedHandler(StackVisitor* stack_visitor) {
-  DCHECK(!is_deoptimization_);
-  DCHECK(*handler_quick_frame_ != nullptr) << "Method should not be called on upcall exceptions";
-  DCHECK(handler_method_ != nullptr && handler_method_->IsOptimized(sizeof(void*)));
-
-  if (kDebugExceptionDelivery) {
-    self_->DumpStack(LOG(INFO) << "Setting catch phis: ");
-  }
-
-  const size_t number_of_vregs = handler_method_->GetCodeItem()->registers_size_;
-  CodeInfo code_info = handler_method_->GetOptimizedCodeInfo();
-  StackMapEncoding encoding = code_info.ExtractEncoding();
-
-  // Find stack map of the throwing instruction.
-  StackMap throw_stack_map =
-      code_info.GetStackMapForNativePcOffset(stack_visitor->GetNativePcOffset(), encoding);
-  DCHECK(throw_stack_map.IsValid());
-  DexRegisterMap throw_vreg_map =
-      code_info.GetDexRegisterMapOf(throw_stack_map, encoding, number_of_vregs);
-
-  // Find stack map of the catch block.
-  StackMap catch_stack_map = code_info.GetCatchStackMapForDexPc(GetHandlerDexPc(), encoding);
-  DCHECK(catch_stack_map.IsValid());
-  DexRegisterMap catch_vreg_map =
-      code_info.GetDexRegisterMapOf(catch_stack_map, encoding, number_of_vregs);
-
-  // Copy values between them.
-  for (uint16_t vreg = 0; vreg < number_of_vregs; ++vreg) {
-    DexRegisterLocation::Kind catch_location =
-        catch_vreg_map.GetLocationKind(vreg, number_of_vregs, code_info, encoding);
-    if (catch_location == DexRegisterLocation::Kind::kNone) {
-      continue;
-    }
-    DCHECK(catch_location == DexRegisterLocation::Kind::kInStack);
-
-    // Get vreg value from its current location.
-    uint32_t vreg_value;
-    VRegKind vreg_kind = ToVRegKind(throw_vreg_map.GetLocationKind(vreg,
-                                                                   number_of_vregs,
-                                                                   code_info,
-                                                                   encoding));
-    bool get_vreg_success = stack_visitor->GetVReg(stack_visitor->GetMethod(),
-                                                   vreg,
-                                                   vreg_kind,
-                                                   &vreg_value);
-    CHECK(get_vreg_success) << "VReg " << vreg << " was optimized out ("
-                            << "method=" << PrettyMethod(stack_visitor->GetMethod()) << ", "
-                            << "dex_pc=" << stack_visitor->GetDexPc() << ", "
-                            << "native_pc_offset=" << stack_visitor->GetNativePcOffset() << ")";
-
-    // Copy value to the catch phi's stack slot.
-    int32_t slot_offset = catch_vreg_map.GetStackOffsetInBytes(vreg,
-                                                               number_of_vregs,
-                                                               code_info,
-                                                               encoding);
-    ArtMethod** frame_top = stack_visitor->GetCurrentQuickFrame();
-    uint8_t* slot_address = reinterpret_cast<uint8_t*>(frame_top) + slot_offset;
-    uint32_t* slot_ptr = reinterpret_cast<uint32_t*>(slot_address);
-    *slot_ptr = vreg_value;
-  }
 }
 
 // Prepares deoptimization.
diff --git a/runtime/quick_exception_handler.h b/runtime/quick_exception_handler.h
index 2e05c7e..4db95a8 100644
--- a/runtime/quick_exception_handler.h
+++ b/runtime/quick_exception_handler.h
@@ -49,14 +49,11 @@
   // Deoptimize the stack to the upcall. For every compiled frame, we create a "copy"
   // shadow frame that will be executed with the interpreter.
   void DeoptimizeStack() SHARED_REQUIRES(Locks::mutator_lock_);
+
   // Update the instrumentation stack by removing all methods that will be unwound
   // by the exception being thrown.
   void UpdateInstrumentationStack() SHARED_REQUIRES(Locks::mutator_lock_);
 
-  // Set up environment before delivering an exception to optimized code.
-  void SetCatchEnvironmentForOptimizedHandler(StackVisitor* stack_visitor)
-      SHARED_REQUIRES(Locks::mutator_lock_);
-
   // Long jump either to a catch handler or to the upcall.
   NO_RETURN void DoLongJump() SHARED_REQUIRES(Locks::mutator_lock_);
 
diff --git a/runtime/stack.cc b/runtime/stack.cc
index d956f0e..a765a3f 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -325,10 +325,6 @@
 
 bool StackVisitor::GetRegisterIfAccessible(uint32_t reg, VRegKind kind, uint32_t* val) const {
   const bool is_float = (kind == kFloatVReg) || (kind == kDoubleLoVReg) || (kind == kDoubleHiVReg);
-
-  // X86 float registers are 64-bit and the logic below does not apply.
-  DCHECK(!is_float || kRuntimeISA != InstructionSet::kX86);
-
   if (!IsAccessibleRegister(reg, is_float)) {
     return false;
   }
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index a15a081..07b79b5 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -1115,7 +1115,7 @@
     region_.StoreUnaligned<NumberOfStackMapsType>(kNumberOfStackMapsOffset, number_of_stack_maps);
   }
 
-  // Get the size of all the stack maps of this CodeInfo object, in bytes.
+  // Get the size all the stack maps of this CodeInfo object, in bytes.
   size_t GetStackMapsSize(const StackMapEncoding& encoding) const {
     return encoding.ComputeStackMapSize() * GetNumberOfStackMaps();
   }
@@ -1174,23 +1174,9 @@
     return StackMap();
   }
 
-  // Searches the stack map list backwards because catch stack maps are stored
-  // at the end.
-  StackMap GetCatchStackMapForDexPc(uint32_t dex_pc, const StackMapEncoding& encoding) const {
-    for (size_t i = GetNumberOfStackMaps(); i > 0; --i) {
-      StackMap stack_map = GetStackMapAt(i - 1, encoding);
-      if (stack_map.GetDexPc(encoding) == dex_pc) {
-        return stack_map;
-      }
-    }
-    return StackMap();
-  }
-
   StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset,
                                         const StackMapEncoding& encoding) const {
-    // TODO: Safepoint stack maps are sorted by native_pc_offset but catch stack
-    //       maps are not. If we knew that the method does not have try/catch,
-    //       we could do binary search.
+    // TODO: stack maps are sorted by native pc, we can do a binary search.
     for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) {
       StackMap stack_map = GetStackMapAt(i, encoding);
       if (stack_map.GetNativePcOffset(encoding) == native_pc_offset) {
diff --git a/test/510-checker-try-catch/smali/RegisterAllocator.smali b/test/510-checker-try-catch/smali/RegisterAllocator.smali
deleted file mode 100644
index fd3c84c..0000000
--- a/test/510-checker-try-catch/smali/RegisterAllocator.smali
+++ /dev/null
@@ -1,94 +0,0 @@
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-.class public LRegisterAllocator;
-
-.super Ljava/lang/Object;
-
-# Test that catch phis are allocated to a stack slot, and that equivalent catch
-# phis are allocated to the same stack slot.
-
-## CHECK-START: int RegisterAllocator.testEquivalentCatchPhiSlot_Single(int, int, int) register (after)
-## CHECK-DAG:     Phi reg:0 is_catch_phi:true locations:{{\[.*\]}}-><<SlotA1:\d+>>(sp)
-## CHECK-DAG:     Phi reg:0 is_catch_phi:true locations:{{\[.*\]}}-><<SlotA2:\d+>>(sp)
-## CHECK-DAG:     Phi reg:1 is_catch_phi:true locations:{{\[.*\]}}-><<SlotB:\d+>>(sp)
-## CHECK-EVAL:    <<SlotA1>> == <<SlotA2>>
-## CHECK-EVAL:    <<SlotB>> != <<SlotA1>>
-
-.method public static testEquivalentCatchPhiSlot_Single(III)I
-  .registers 8
-
-  :try_start
-  const/high16 v0, 0x40000000 # float 2
-  move v1, p0
-  div-int/2addr p0, p1
-
-  const/high16 v0, 0x41000000 # float 8
-  move v1, p1
-  div-int/2addr p0, p2
-  goto :return
-  :try_end
-  .catchall {:try_start .. :try_end} :catch_all
-
-  :catch_all
-  # 2x CatchPhi for v0, 1x for v1
-  if-eqz v1, :use_as_float
-
-  :use_as_int
-  goto :return
-
-  :use_as_float
-  float-to-int v0, v0
-
-  :return
-  return v0
-.end method
-
-# Test that wide catch phis are allocated to two stack slots.
-
-## CHECK-START: long RegisterAllocator.testEquivalentCatchPhiSlot_Wide(int, int, int) register (after)
-## CHECK-DAG:     Phi reg:0 is_catch_phi:true locations:{{\[.*\]}}->2x<<SlotB1:\d+>>(sp)
-## CHECK-DAG:     Phi reg:0 is_catch_phi:true locations:{{\[.*\]}}->2x<<SlotB2:\d+>>(sp)
-## CHECK-DAG:     Phi reg:2 is_catch_phi:true locations:{{\[.*\]}}-><<SlotA:\d+>>(sp)
-## CHECK-EVAL:    <<SlotB1>> == <<SlotB2>>
-## CHECK-EVAL:    abs(<<SlotA>> - <<SlotB1>>) >= 8
-
-.method public static testEquivalentCatchPhiSlot_Wide(III)J
-  .registers 8
-
-  :try_start
-  const-wide/high16 v0, 0x4000000000000000L # double 2
-  move v2, p0
-  div-int/2addr p0, p1
-
-  const-wide/high16 v0, 0x4100000000000000L # double 8
-  move v2, p1
-  div-int/2addr p0, p2
-  goto :return
-  :try_end
-  .catchall {:try_start .. :try_end} :catch_all
-
-  :catch_all
-  # 2x CatchPhi for v0, 1x for v2
-  if-eqz v2, :use_as_double
-
-  :use_as_long
-  goto :return
-
-  :use_as_double
-  double-to-long v0, v0
-
-  :return
-  return-wide v0
-.end method
diff --git a/test/510-checker-try-catch/smali/Runtime.smali b/test/510-checker-try-catch/smali/Runtime.smali
deleted file mode 100644
index 19b43a3..0000000
--- a/test/510-checker-try-catch/smali/Runtime.smali
+++ /dev/null
@@ -1,555 +0,0 @@
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-.class public LRuntime;
-.super Ljava/lang/Object;
-
-# The following tests all share the same structure, signature and return values:
-#  - foo(false, false):  normal path,         returns 42
-#  - foo(true, false):   exceptional path #1, returns 3
-#  - foo(false, true):   exceptional path #2, returns 8
-#  - foo(true, true):    undefined
-
-
-# Test register allocation of 32-bit core intervals crossing catch block positions.
-
-## CHECK-START: int Runtime.testUseAfterCatch_int(boolean, boolean) register (after)
-## CHECK-NOT:     Phi is_catch_phi:true
-
-.method public static testUseAfterCatch_int(ZZ)I
-  .registers 6
-
-  sget-object v0, LRuntime;->intArray:[I
-  const/4 v1, 0
-  aget v1, v0, v1
-  const/4 v2, 1
-  aget v2, v0, v2
-  const/4 v3, 2
-  aget v3, v0, v3
-
-  :try_start
-  invoke-static {p0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-  invoke-static {p1}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-  :try_end
-  .catchall {:try_start .. :try_end} :catch_all
-
-  return v3  # Normal path return.
-
-  :catch_all
-  if-eqz p0, :second_throw
-  return v1  # Exceptional path #1 return.
-
-  :second_throw
-  return v2  # Exceptional path #2 return.
-.end method
-
-
-# Test register allocation of 64-bit core intervals crossing catch block positions.
-
-# The sum of the low and high 32 bits treated as integers is returned to prove
-# that both vregs allocated correctly.
-
-## CHECK-START: int Runtime.testUseAfterCatch_long(boolean, boolean) register (after)
-## CHECK-NOT:     Phi is_catch_phi:true
-
-.method public static testUseAfterCatch_long(ZZ)I
-  .registers 10
-
-  sget-object v0, LRuntime;->longArray:[J
-  const/4 v1, 0
-  aget-wide v1, v0, v1
-  const/4 v3, 1
-  aget-wide v3, v0, v3
-  const/4 v5, 2
-  aget-wide v5, v0, v5
-
-  :try_start
-  invoke-static {p0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-  invoke-static {p1}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-  :try_end
-  .catchall {:try_start .. :try_end} :catch_all
-
-  const v0, 32
-  ushr-long v7, v5, v0
-  long-to-int v5, v5
-  long-to-int v7, v7
-  add-int/2addr v5, v7
-  return v5  # Normal path return.
-
-  :catch_all
-  const v0, 32
-  if-eqz p0, :second_throw
-
-  ushr-long v7, v1, v0
-  long-to-int v1, v1
-  long-to-int v7, v7
-  add-int/2addr v1, v7
-  return v1  # Exceptional path #1 return.
-
-  :second_throw
-  ushr-long v7, v3, v0
-  long-to-int v3, v3
-  long-to-int v7, v7
-  add-int/2addr v3, v7
-  return v3  # Exceptional path #2 return.
-.end method
-
-
-# Test register allocation of 32-bit floating-point intervals crossing catch block positions.
-
-## CHECK-START: int Runtime.testUseAfterCatch_float(boolean, boolean) register (after)
-## CHECK-NOT:     Phi is_catch_phi:true
-
-.method public static testUseAfterCatch_float(ZZ)I
-  .registers 6
-
-  sget-object v0, LRuntime;->floatArray:[F
-  const/4 v1, 0
-  aget v1, v0, v1
-  const/4 v2, 1
-  aget v2, v0, v2
-  const/4 v3, 2
-  aget v3, v0, v3
-
-  :try_start
-  invoke-static {p0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-  invoke-static {p1}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-  :try_end
-  .catchall {:try_start .. :try_end} :catch_all
-
-  float-to-int v3, v3
-  return v3  # Normal path return.
-
-  :catch_all
-  if-eqz p0, :second_throw
-  float-to-int v1, v1
-  return v1  # Exceptional path #1 return.
-
-  :second_throw
-  float-to-int v2, v2
-  return v2  # Exceptional path #2 return.
-.end method
-
-
-# Test register allocation of 64-bit floating-point intervals crossing catch block positions.
-
-## CHECK-START: int Runtime.testUseAfterCatch_double(boolean, boolean) register (after)
-## CHECK-NOT:     Phi is_catch_phi:true
-
-.method public static testUseAfterCatch_double(ZZ)I
-  .registers 10
-
-  sget-object v0, LRuntime;->doubleArray:[D
-  const/4 v1, 0
-  aget-wide v1, v0, v1
-  const/4 v3, 1
-  aget-wide v3, v0, v3
-  const/4 v5, 2
-  aget-wide v5, v0, v5
-
-  :try_start
-  invoke-static {p0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-  invoke-static {p1}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-  :try_end
-  .catchall {:try_start .. :try_end} :catch_all
-
-  double-to-int v5, v5
-  return v5  # Normal path return.
-
-  :catch_all
-  if-eqz p0, :second_throw
-  double-to-int v1, v1
-  return v1  # Exceptional path #1 return.
-
-  :second_throw
-  double-to-int v3, v3
-  return v3  # Exceptional path #2 return.
-.end method
-
-
-# Test catch-phi runtime support for constant values.
-
-# Register v0 holds different constants at two throwing instructions. Runtime is
-# expected to load them from stack map and copy to the catch phi's location.
-
-## CHECK-START: int Runtime.testCatchPhi_const(boolean, boolean) register (after)
-## CHECK-DAG:     <<Const3:i\d+>> IntConstant 3
-## CHECK-DAG:     <<Const8:i\d+>> IntConstant 8
-## CHECK-DAG:                     Phi [<<Const3>>,<<Const8>>] is_catch_phi:true
-
-.method public static testCatchPhi_const(ZZ)I
-  .registers 3
-
-  :try_start
-  const v0, 3
-  invoke-static {p0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-
-  const v0, 8
-  invoke-static {p1}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-  :try_end
-  .catchall {:try_start .. :try_end} :catch_all
-
-  const v0, 42
-  return v0  # Normal path return.
-
-  :catch_all
-  return v0  # Exceptional path #1/#2 return.
-.end method
-
-
-# Test catch-phi runtime support for 32-bit values stored in core registers.
-
-# Register v0 holds different integer values at two throwing instructions.
-# Runtime is expected to find their location in the stack map and copy the value
-# to the location of the catch phi.
-
-## CHECK-START: int Runtime.testCatchPhi_int(boolean, boolean) register (after)
-## CHECK-DAG:     <<Val1:i\d+>> ArrayGet
-## CHECK-DAG:     <<Val2:i\d+>> ArrayGet
-## CHECK-DAG:                   Phi [<<Val1>>,<<Val2>>] is_catch_phi:true
-
-.method public static testCatchPhi_int(ZZ)I
-  .registers 6
-
-  sget-object v0, LRuntime;->intArray:[I
-  const/4 v1, 0
-  aget v1, v0, v1
-  const/4 v2, 1
-  aget v2, v0, v2
-  const/4 v3, 2
-  aget v3, v0, v3
-
-  :try_start
-  move v0, v1  # Set catch phi value
-  invoke-static {p0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-
-  move v0, v2  # Set catch phi value
-  invoke-static {p1}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-  :try_end
-  .catchall {:try_start .. :try_end} :catch_all
-
-  return v3  # Normal path return.
-
-  :catch_all
-  return v0  # Exceptional path #1/#2 return.
-.end method
-
-
-# Test catch-phi runtime support for 64-bit values stored in core registers.
-
-# Register pair (v0, v1) holds different long values at two throwing instructions.
-# Runtime is expected to find their location in the stack map and copy the value
-# to the location of the catch phi. The sum of the low and high 32 bits treated
-# as integers is returned to prove that both vregs were copied.
-
-# Note: values will be spilled on x86 because of too few callee-save core registers.
-
-## CHECK-START: int Runtime.testCatchPhi_long(boolean, boolean) register (after)
-## CHECK-DAG:     <<Val1:j\d+>> ArrayGet
-## CHECK-DAG:     <<Val2:j\d+>> ArrayGet
-## CHECK-DAG:                   Phi [<<Val1>>,<<Val2>>] is_catch_phi:true
-
-.method public static testCatchPhi_long(ZZ)I
-  .registers 10
-
-  sget-object v0, LRuntime;->longArray:[J
-  const/4 v2, 0
-  aget-wide v2, v0, v2
-  const/4 v4, 1
-  aget-wide v4, v0, v4
-  const/4 v6, 2
-  aget-wide v6, v0, v6
-
-  :try_start
-  move-wide v0, v2  # Set catch phi value
-  invoke-static {p0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-
-  move-wide v0, v4  # Set catch phi value
-  invoke-static {p1}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-  :try_end
-  .catchall {:try_start .. :try_end} :catch_all
-
-  const v2, 32
-  ushr-long v2, v6, v2
-  long-to-int v2, v2
-  long-to-int v6, v6
-  add-int/2addr v6, v2
-  return v6  # Normal path return.
-
-  :catch_all
-  const v2, 32
-  ushr-long v2, v0, v2
-  long-to-int v2, v2
-  long-to-int v0, v0
-  add-int/2addr v0, v2
-  return v0  # Exceptional path #1/#2 return.
-.end method
-
-
-# Test catch-phi runtime support for 32-bit values stored in FPU registers.
-
-# Register v0 holds different float values at two throwing instructions. Runtime
-# is expected to find their location in the stack map and copy the value to the
-# location of the catch phi. The value is converted to int and returned.
-
-# Note: values will be spilled on x86 as there are no callee-save FPU registers.
-
-## CHECK-START: int Runtime.testCatchPhi_float(boolean, boolean) register (after)
-## CHECK-DAG:     <<Val1:f\d+>> ArrayGet
-## CHECK-DAG:     <<Val2:f\d+>> ArrayGet
-## CHECK-DAG:                   Phi [<<Val1>>,<<Val2>>] is_catch_phi:true
-
-.method public static testCatchPhi_float(ZZ)I
-  .registers 6
-
-  sget-object v0, LRuntime;->floatArray:[F
-  const/4 v1, 0
-  aget v1, v0, v1
-  const/4 v2, 1
-  aget v2, v0, v2
-  const/4 v3, 2
-  aget v3, v0, v3
-
-  :try_start
-  move v0, v1  # Set catch phi value
-  invoke-static {p0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-
-  move v0, v2  # Set catch phi value
-  invoke-static {p1}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-  :try_end
-  .catchall {:try_start .. :try_end} :catch_all
-
-  float-to-int v3, v3
-  return v3  # Normal path return.
-
-  :catch_all
-  float-to-int v0, v0
-  return v0  # Exceptional path #1/#2 return.
-.end method
-
-
-# Test catch-phi runtime support for 64-bit values stored in FPU registers.
-
-# Register pair (v0, v1) holds different double values at two throwing instructions.
-# Runtime is expected to find their location in the stack map and copy the value
-# to the location of the catch phi. The value is converted to int and returned.
-# Values were chosen so that all 64 bits are used.
-
-# Note: values will be spilled on x86 as there are no callee-save FPU registers.
-
-## CHECK-START: int Runtime.testCatchPhi_double(boolean, boolean) register (after)
-## CHECK-DAG:     <<Val1:d\d+>> ArrayGet
-## CHECK-DAG:     <<Val2:d\d+>> ArrayGet
-## CHECK-DAG:                   Phi [<<Val1>>,<<Val2>>] is_catch_phi:true
-
-.method public static testCatchPhi_double(ZZ)I
-  .registers 10
-
-  sget-object v0, LRuntime;->doubleArray:[D
-  const/4 v2, 0
-  aget-wide v2, v0, v2
-  const/4 v4, 1
-  aget-wide v4, v0, v4
-  const/4 v6, 2
-  aget-wide v6, v0, v6
-
-  :try_start
-  move-wide v0, v2  # Set catch phi value
-  invoke-static {p0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-
-  move-wide v0, v4  # Set catch phi value
-  invoke-static {p1}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-  :try_end
-  .catchall {:try_start .. :try_end} :catch_all
-
-  double-to-int v6, v6
-  return v6
-
-  :catch_all
-  double-to-int v0, v0
-  return v0
-.end method
-
-# Test catch-phi runtime support for 32-bit values stored on the stack.
-
-# Register v0 holds different integer values at two throwing instructions.
-# These values were forced to spill by an always-throwing try/catch after their
-# definition. Runtime is expected to find their location in the stack map and
-# copy the value to the location of the catch phi. The value is then returned.
-
-## CHECK-START: int Runtime.testCatchPhi_singleSlot(boolean, boolean) register (after)
-## CHECK:         <<Val1:i\d+>> ArrayGet
-## CHECK-NEXT:                  ParallelMove moves:[{{.*->}}{{\d+}}(sp)]
-## CHECK:         <<Val2:i\d+>> ArrayGet
-## CHECK-NEXT:                  ParallelMove moves:[{{.*->}}{{\d+}}(sp)]
-## CHECK:                       Phi [<<Val1>>,<<Val2>>] is_catch_phi:true
-
-.method public static testCatchPhi_singleSlot(ZZ)I
-  .registers 6
-
-  sget-object v0, LRuntime;->intArray:[I
-  const/4 v1, 0
-  aget v1, v0, v1
-  const/4 v2, 1
-  aget v2, v0, v2
-  const/4 v3, 2
-  aget v3, v0, v3
-
-  # Insert a try/catch to force v1,v2,v3 to spill.
-  :try_start_spill
-  const/4 v0, 1
-  invoke-static {v0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-  :try_end_spill
-  .catchall {:try_start_spill .. :try_end_spill} :catch_all_spill
-  return v0         # Unreachable
-  :catch_all_spill  # Catch and continue
-
-  :try_start
-  move v0, v1  # Set catch phi value
-  invoke-static {p0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-
-  move v0, v2  # Set catch phi value
-  invoke-static {p1}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-  :try_end
-  .catchall {:try_start .. :try_end} :catch_all
-
-  return v3  # Normal path return.
-
-  :catch_all
-  return v0  # Exceptional path #1/#2 return.
-.end method
-
-# Test catch-phi runtime support for 64-bit values stored on the stack.
-
-# Register pair (v0, v1) holds different double values at two throwing instructions.
-# These values were forced to spill by an always-throwing try/catch after their
-# definition. Runtime is expected to find their location in the stack map and
-# copy the value to the location of the catch phi. The value is converted to int
-# and returned. Values were chosen so that all 64 bits are used.
-
-## CHECK-START: int Runtime.testCatchPhi_doubleSlot(boolean, boolean) register (after)
-## CHECK:         <<Val1:d\d+>> ArrayGet
-## CHECK-NEXT:                  ParallelMove moves:[{{.*->}}2x{{\d+}}(sp)]
-## CHECK:         <<Val2:d\d+>> ArrayGet
-## CHECK-NEXT:                  ParallelMove moves:[{{.*->}}2x{{\d+}}(sp)]
-## CHECK:                       Phi [<<Val1>>,<<Val2>>] is_catch_phi:true
-
-.method public static testCatchPhi_doubleSlot(ZZ)I
-  .registers 10
-
-  sget-object v0, LRuntime;->doubleArray:[D
-  const/4 v2, 0
-  aget-wide v2, v0, v2
-  const/4 v4, 1
-  aget-wide v4, v0, v4
-  const/4 v6, 2
-  aget-wide v6, v0, v6
-
-  # Insert a try/catch to force (v2, v3), (v4, v5), (v6, v7) to spill.
-  :try_start_spill
-  const/4 v0, 1
-  invoke-static {v0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-  :try_end_spill
-  .catchall {:try_start_spill .. :try_end_spill} :catch_all_spill
-  return v0         # Unreachable
-  :catch_all_spill  # Catch and continue
-
-  :try_start
-  move-wide v0, v2  # Set catch phi value
-  invoke-static {p0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-
-  move-wide v0, v4  # Set catch phi value
-  invoke-static {p1}, LRuntime;->$noinline$ThrowIfTrue(Z)V
-  :try_end
-  .catchall {:try_start .. :try_end} :catch_all
-
-  double-to-int v6, v6
-  return v6  # Normal path return.
-
-  :catch_all
-  double-to-int v0, v0
-  return v0  # Exceptional path #1/#2 return.
-.end method
-
-
-
-# Helper methods and initialization.
-
-.method public static $noinline$ThrowIfTrue(Z)V
-  .registers 2
-  if-nez p0, :throw
-  return-void
-
-  :throw
-  new-instance v0, Ljava/lang/Exception;
-  invoke-direct {v0}, Ljava/lang/Exception;-><init>()V
-  throw v0
-.end method
-
-.method public static constructor <clinit>()V
-  .registers 2
-
-  const/4 v1, 4
-
-  new-array v0, v1, [I
-  fill-array-data v0, :array_int
-  sput-object v0, LRuntime;->intArray:[I
-
-  new-array v0, v1, [J
-  fill-array-data v0, :array_long
-  sput-object v0, LRuntime;->longArray:[J
-
-  new-array v0, v1, [F
-  fill-array-data v0, :array_float
-  sput-object v0, LRuntime;->floatArray:[F
-
-  new-array v0, v1, [D
-  fill-array-data v0, :array_double
-  sput-object v0, LRuntime;->doubleArray:[D
-
-  return-void
-
-:array_int
-.array-data 4
-  0x03  # int 3
-  0x08  # int 8
-  0x2a  # int 42
-.end array-data
-
-:array_long
-.array-data 8
-  0x0000000100000002L # long (1 << 32) + 2
-  0x0000000500000003L # long (5 << 32) + 3
-  0x0000001e0000000cL # long (30 << 32) + 12
-.end array-data
-
-:array_float
-.array-data 4
-  0x40400000  # float 3
-  0x41000000  # float 8
-  0x42280000  # float 42
-.end array-data
-
-:array_double
-.array-data 8
-  0x400b333333333333L  # double 3.4
-  0x4020cccccccccccdL  # double 8.4
-  0x4045333333333333L  # double 42.4
-.end array-data
-.end method
-
-.field public static intArray:[I
-.field public static longArray:[J
-.field public static floatArray:[F
-.field public static doubleArray:[D
diff --git a/test/510-checker-try-catch/src/Main.java b/test/510-checker-try-catch/src/Main.java
index 25cdc0e..ae78ba0 100644
--- a/test/510-checker-try-catch/src/Main.java
+++ b/test/510-checker-try-catch/src/Main.java
@@ -14,55 +14,10 @@
  * limitations under the License.
  */
 
-import java.lang.reflect.Method;
-
 public class Main {
 
   // Workaround for b/18051191.
   class InnerClass {}
 
-  public enum TestPath {
-    ExceptionalFlow1(true, false, 3),
-    ExceptionalFlow2(false, true, 8),
-    NormalFlow(false, false, 42);
-
-    TestPath(boolean arg1, boolean arg2, int expected) {
-      this.arg1 = arg1;
-      this.arg2 = arg2;
-      this.expected = expected;
-    }
-
-    public boolean arg1;
-    public boolean arg2;
-    public int expected;
-  }
-
-  public static void testMethod(String method) throws Exception {
-    Class<?> c = Class.forName("Runtime");
-    Method m = c.getMethod(method, new Class[] { boolean.class, boolean.class });
-
-    for (TestPath path : TestPath.values()) {
-      Object[] arguments = new Object[] { path.arg1, path.arg2 };
-      int actual = (Integer) m.invoke(null, arguments);
-
-      if (actual != path.expected) {
-        throw new Error("Method: \"" + method + "\", path: " + path + ", " +
-                        "expected: " + path.expected + ", actual: " + actual);
-      }
-    }
-  }
-
-  public static void main(String[] args) throws Exception {
-    testMethod("testUseAfterCatch_int");
-    testMethod("testUseAfterCatch_long");
-    testMethod("testUseAfterCatch_float");
-    testMethod("testUseAfterCatch_double");
-    testMethod("testCatchPhi_const");
-    testMethod("testCatchPhi_int");
-    testMethod("testCatchPhi_long");
-    testMethod("testCatchPhi_float");
-    testMethod("testCatchPhi_double");
-    testMethod("testCatchPhi_singleSlot");
-    testMethod("testCatchPhi_doubleSlot");
-  }
+  public static void main(String[] args) {}
 }