Merge "Verify the checksum before DCHECKS in  ProfileCompilationInfo::GetOrAddDexFileData"
diff --git a/compiler/optimizing/code_generator_vector_arm64.cc b/compiler/optimizing/code_generator_vector_arm64.cc
index 18a55c8..9095ecd 100644
--- a/compiler/optimizing/code_generator_vector_arm64.cc
+++ b/compiler/optimizing/code_generator_vector_arm64.cc
@@ -27,13 +27,12 @@
 using helpers::ARM64EncodableConstantOrRegister;
 using helpers::Arm64CanEncodeConstantAsImmediate;
 using helpers::DRegisterFrom;
+using helpers::VRegisterFrom;
 using helpers::HeapOperand;
 using helpers::InputRegisterAt;
 using helpers::Int64ConstantFrom;
-using helpers::OutputRegister;
-using helpers::VRegisterFrom;
-using helpers::WRegisterFrom;
 using helpers::XRegisterFrom;
+using helpers::WRegisterFrom;
 
 #define __ GetVIXLAssembler()->
 
@@ -128,51 +127,20 @@
   }
 }
 
-void LocationsBuilderARM64::VisitVecExtractScalar(HVecExtractScalar* instruction) {
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
-  switch (instruction->GetPackedType()) {
-    case Primitive::kPrimBoolean:
-    case Primitive::kPrimByte:
-    case Primitive::kPrimChar:
-    case Primitive::kPrimShort:
-    case Primitive::kPrimInt:
-    case Primitive::kPrimLong:
-      locations->SetInAt(0, Location::RequiresFpuRegister());
-      locations->SetOut(Location::RequiresRegister());
-      break;
-    case Primitive::kPrimFloat:
-    case Primitive::kPrimDouble:
-      locations->SetInAt(0, Location::RequiresFpuRegister());
-      locations->SetOut(Location::SameAsFirstInput());
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type";
-      UNREACHABLE();
-  }
+void LocationsBuilderARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
 }
 
-void InstructionCodeGeneratorARM64::VisitVecExtractScalar(HVecExtractScalar* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister src = VRegisterFrom(locations->InAt(0));
-  switch (instruction->GetPackedType()) {
-    case Primitive::kPrimInt:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Umov(OutputRegister(instruction), src.V4S(), 0);
-      break;
-    case Primitive::kPrimLong:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ Umov(OutputRegister(instruction), src.V2D(), 0);
-      break;
-    case Primitive::kPrimFloat:
-    case Primitive::kPrimDouble:
-      DCHECK_LE(2u, instruction->GetVectorLength());
-      DCHECK_LE(instruction->GetVectorLength(), 4u);
-      DCHECK(locations->InAt(0).Equals(locations->Out()));  // no code required
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type";
-      UNREACHABLE();
-  }
+void InstructionCodeGeneratorARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+}
+
+void LocationsBuilderARM64::VisitVecSumReduce(HVecSumReduce* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+}
+
+void InstructionCodeGeneratorARM64::VisitVecSumReduce(HVecSumReduce* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
 }
 
 // Helper to set up locations for vector unary operations.
@@ -201,46 +169,6 @@
   }
 }
 
-void LocationsBuilderARM64::VisitVecReduce(HVecReduce* instruction) {
-  CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
-}
-
-void InstructionCodeGeneratorARM64::VisitVecReduce(HVecReduce* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister src = VRegisterFrom(locations->InAt(0));
-  VRegister dst = DRegisterFrom(locations->Out());
-  switch (instruction->GetPackedType()) {
-    case Primitive::kPrimInt:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      switch (instruction->GetKind()) {
-        case HVecReduce::kSum:
-          __ Addv(dst.S(), src.V4S());
-          break;
-        case HVecReduce::kMin:
-          __ Sminv(dst.S(), src.V4S());
-          break;
-        case HVecReduce::kMax:
-          __ Smaxv(dst.S(), src.V4S());
-          break;
-      }
-      break;
-    case Primitive::kPrimLong:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      switch (instruction->GetKind()) {
-        case HVecReduce::kSum:
-          __ Addp(dst.D(), src.V2D());
-          break;
-        default:
-          LOG(FATAL) << "Unsupported SIMD min/max";
-          UNREACHABLE();
-      }
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type";
-      UNREACHABLE();
-  }
-}
-
 void LocationsBuilderARM64::VisitVecCnv(HVecCnv* instruction) {
   CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
 }
@@ -335,7 +263,6 @@
       break;
     default:
       LOG(FATAL) << "Unsupported SIMD type";
-      UNREACHABLE();
   }
 }
 
@@ -878,77 +805,6 @@
   }
 }
 
-void LocationsBuilderARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
-
-  DCHECK_EQ(1u, instruction->InputCount());  // only one input currently implemented
-
-  HInstruction* input = instruction->InputAt(0);
-  bool is_zero = IsZeroBitPattern(input);
-
-  switch (instruction->GetPackedType()) {
-    case Primitive::kPrimBoolean:
-    case Primitive::kPrimByte:
-    case Primitive::kPrimChar:
-    case Primitive::kPrimShort:
-    case Primitive::kPrimInt:
-    case Primitive::kPrimLong:
-      locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
-                                    : Location::RequiresRegister());
-      locations->SetOut(Location::RequiresFpuRegister());
-      break;
-    case Primitive::kPrimFloat:
-    case Primitive::kPrimDouble:
-      locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
-                                    : Location::RequiresFpuRegister());
-      locations->SetOut(Location::RequiresFpuRegister());
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type";
-      UNREACHABLE();
-  }
-}
-
-void InstructionCodeGeneratorARM64::VisitVecSetScalars(HVecSetScalars* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  VRegister dst = VRegisterFrom(locations->Out());
-
-  DCHECK_EQ(1u, instruction->InputCount());  // only one input currently implemented
-
-  // Zero out all other elements first.
-  __ Movi(dst.V16B(), 0);
-
-  // Shorthand for any type of zero.
-  if (IsZeroBitPattern(instruction->InputAt(0))) {
-    return;
-  }
-
-  // Set required elements.
-  switch (instruction->GetPackedType()) {
-    case Primitive::kPrimBoolean:
-    case Primitive::kPrimByte:
-      DCHECK_EQ(16u, instruction->GetVectorLength());
-      __ Mov(dst.V16B(), 0, InputRegisterAt(instruction, 0));
-      break;
-    case Primitive::kPrimChar:
-    case Primitive::kPrimShort:
-      DCHECK_EQ(8u, instruction->GetVectorLength());
-      __ Mov(dst.V8H(), 0, InputRegisterAt(instruction, 0));
-      break;
-    case Primitive::kPrimInt:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ Mov(dst.V4S(), 0, InputRegisterAt(instruction, 0));
-      break;
-    case Primitive::kPrimLong:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ Mov(dst.V2D(), 0, InputRegisterAt(instruction, 0));
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type";
-      UNREACHABLE();
-  }
-}
-
 void LocationsBuilderARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instr);
   switch (instr->GetPackedType()) {
diff --git a/compiler/optimizing/code_generator_vector_arm_vixl.cc b/compiler/optimizing/code_generator_vector_arm_vixl.cc
index 7a11dff..527691d 100644
--- a/compiler/optimizing/code_generator_vector_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_vector_arm_vixl.cc
@@ -73,11 +73,19 @@
   }
 }
 
-void LocationsBuilderARMVIXL::VisitVecExtractScalar(HVecExtractScalar* instruction) {
+void LocationsBuilderARMVIXL::VisitVecSetScalars(HVecSetScalars* instruction) {
   LOG(FATAL) << "No SIMD for " << instruction->GetId();
 }
 
-void InstructionCodeGeneratorARMVIXL::VisitVecExtractScalar(HVecExtractScalar* instruction) {
+void InstructionCodeGeneratorARMVIXL::VisitVecSetScalars(HVecSetScalars* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+}
+
+void LocationsBuilderARMVIXL::VisitVecSumReduce(HVecSumReduce* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+}
+
+void InstructionCodeGeneratorARMVIXL::VisitVecSumReduce(HVecSumReduce* instruction) {
   LOG(FATAL) << "No SIMD for " << instruction->GetId();
 }
 
@@ -104,14 +112,6 @@
   }
 }
 
-void LocationsBuilderARMVIXL::VisitVecReduce(HVecReduce* instruction) {
-  CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
-}
-
-void InstructionCodeGeneratorARMVIXL::VisitVecReduce(HVecReduce* instruction) {
-  LOG(FATAL) << "No SIMD for " << instruction->GetId();
-}
-
 void LocationsBuilderARMVIXL::VisitVecCnv(HVecCnv* instruction) {
   CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
 }
@@ -621,14 +621,6 @@
   }
 }
 
-void LocationsBuilderARMVIXL::VisitVecSetScalars(HVecSetScalars* instruction) {
-  LOG(FATAL) << "No SIMD for " << instruction->GetId();
-}
-
-void InstructionCodeGeneratorARMVIXL::VisitVecSetScalars(HVecSetScalars* instruction) {
-  LOG(FATAL) << "No SIMD for " << instruction->GetId();
-}
-
 void LocationsBuilderARMVIXL::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
   LOG(FATAL) << "No SIMD for " << instr->GetId();
 }
diff --git a/compiler/optimizing/code_generator_vector_mips.cc b/compiler/optimizing/code_generator_vector_mips.cc
index c2fbf7f..6bf28ab 100644
--- a/compiler/optimizing/code_generator_vector_mips.cc
+++ b/compiler/optimizing/code_generator_vector_mips.cc
@@ -88,11 +88,19 @@
   }
 }
 
-void LocationsBuilderMIPS::VisitVecExtractScalar(HVecExtractScalar* instruction) {
+void LocationsBuilderMIPS::VisitVecSetScalars(HVecSetScalars* instruction) {
   LOG(FATAL) << "No SIMD for " << instruction->GetId();
 }
 
-void InstructionCodeGeneratorMIPS::VisitVecExtractScalar(HVecExtractScalar* instruction) {
+void InstructionCodeGeneratorMIPS::VisitVecSetScalars(HVecSetScalars* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+}
+
+void LocationsBuilderMIPS::VisitVecSumReduce(HVecSumReduce* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+}
+
+void InstructionCodeGeneratorMIPS::VisitVecSumReduce(HVecSumReduce* instruction) {
   LOG(FATAL) << "No SIMD for " << instruction->GetId();
 }
 
@@ -125,14 +133,6 @@
   }
 }
 
-void LocationsBuilderMIPS::VisitVecReduce(HVecReduce* instruction) {
-  CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
-}
-
-void InstructionCodeGeneratorMIPS::VisitVecReduce(HVecReduce* instruction) {
-  LOG(FATAL) << "No SIMD for " << instruction->GetId();
-}
-
 void LocationsBuilderMIPS::VisitVecCnv(HVecCnv* instruction) {
   CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
 }
@@ -818,14 +818,6 @@
   }
 }
 
-void LocationsBuilderMIPS::VisitVecSetScalars(HVecSetScalars* instruction) {
-  LOG(FATAL) << "No SIMD for " << instruction->GetId();
-}
-
-void InstructionCodeGeneratorMIPS::VisitVecSetScalars(HVecSetScalars* instruction) {
-  LOG(FATAL) << "No SIMD for " << instruction->GetId();
-}
-
 void LocationsBuilderMIPS::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instr);
   switch (instr->GetPackedType()) {
diff --git a/compiler/optimizing/code_generator_vector_mips64.cc b/compiler/optimizing/code_generator_vector_mips64.cc
index 9d3a777..75bf7a7 100644
--- a/compiler/optimizing/code_generator_vector_mips64.cc
+++ b/compiler/optimizing/code_generator_vector_mips64.cc
@@ -91,11 +91,19 @@
   }
 }
 
-void LocationsBuilderMIPS64::VisitVecExtractScalar(HVecExtractScalar* instruction) {
+void LocationsBuilderMIPS64::VisitVecSetScalars(HVecSetScalars* instruction) {
   LOG(FATAL) << "No SIMD for " << instruction->GetId();
 }
 
-void InstructionCodeGeneratorMIPS64::VisitVecExtractScalar(HVecExtractScalar* instruction) {
+void InstructionCodeGeneratorMIPS64::VisitVecSetScalars(HVecSetScalars* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+}
+
+void LocationsBuilderMIPS64::VisitVecSumReduce(HVecSumReduce* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+}
+
+void InstructionCodeGeneratorMIPS64::VisitVecSumReduce(HVecSumReduce* instruction) {
   LOG(FATAL) << "No SIMD for " << instruction->GetId();
 }
 
@@ -128,14 +136,6 @@
   }
 }
 
-void LocationsBuilderMIPS64::VisitVecReduce(HVecReduce* instruction) {
-  CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
-}
-
-void InstructionCodeGeneratorMIPS64::VisitVecReduce(HVecReduce* instruction) {
-  LOG(FATAL) << "No SIMD for " << instruction->GetId();
-}
-
 void LocationsBuilderMIPS64::VisitVecCnv(HVecCnv* instruction) {
   CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
 }
@@ -822,14 +822,6 @@
   }
 }
 
-void LocationsBuilderMIPS64::VisitVecSetScalars(HVecSetScalars* instruction) {
-  LOG(FATAL) << "No SIMD for " << instruction->GetId();
-}
-
-void InstructionCodeGeneratorMIPS64::VisitVecSetScalars(HVecSetScalars* instruction) {
-  LOG(FATAL) << "No SIMD for " << instruction->GetId();
-}
-
 void LocationsBuilderMIPS64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instr);
   switch (instr->GetPackedType()) {
diff --git a/compiler/optimizing/code_generator_vector_x86.cc b/compiler/optimizing/code_generator_vector_x86.cc
index 57e7dc6..e7aec76 100644
--- a/compiler/optimizing/code_generator_vector_x86.cc
+++ b/compiler/optimizing/code_generator_vector_x86.cc
@@ -27,28 +27,22 @@
 
 void LocationsBuilderX86::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
-  HInstruction* input = instruction->InputAt(0);
-  bool is_zero = IsZeroBitPattern(input);
   switch (instruction->GetPackedType()) {
     case Primitive::kPrimLong:
-      // Long needs extra temporary to load from the register pair.
-      if (!is_zero) {
-        locations->AddTemp(Location::RequiresFpuRegister());
-      }
+      // Long needs extra temporary to load the register pair.
+      locations->AddTemp(Location::RequiresFpuRegister());
       FALLTHROUGH_INTENDED;
     case Primitive::kPrimBoolean:
     case Primitive::kPrimByte:
     case Primitive::kPrimChar:
     case Primitive::kPrimShort:
     case Primitive::kPrimInt:
-      locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
-                                    : Location::RequiresRegister());
+      locations->SetInAt(0, Location::RequiresRegister());
       locations->SetOut(Location::RequiresFpuRegister());
       break;
     case Primitive::kPrimFloat:
     case Primitive::kPrimDouble:
-      locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
-                                    : Location::RequiresFpuRegister());
+      locations->SetInAt(0, Location::RequiresFpuRegister());
       locations->SetOut(Location::SameAsFirstInput());
       break;
     default:
@@ -59,53 +53,46 @@
 
 void InstructionCodeGeneratorX86::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
   LocationSummary* locations = instruction->GetLocations();
-  XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
-
-  // Shorthand for any type of zero.
-  if (IsZeroBitPattern(instruction->InputAt(0))) {
-    __ xorps(dst, dst);
-    return;
-  }
-
+  XmmRegister reg = locations->Out().AsFpuRegister<XmmRegister>();
   switch (instruction->GetPackedType()) {
     case Primitive::kPrimBoolean:
     case Primitive::kPrimByte:
       DCHECK_EQ(16u, instruction->GetVectorLength());
-      __ movd(dst, locations->InAt(0).AsRegister<Register>());
-      __ punpcklbw(dst, dst);
-      __ punpcklwd(dst, dst);
-      __ pshufd(dst, dst, Immediate(0));
+      __ movd(reg, locations->InAt(0).AsRegister<Register>());
+      __ punpcklbw(reg, reg);
+      __ punpcklwd(reg, reg);
+      __ pshufd(reg, reg, Immediate(0));
       break;
     case Primitive::kPrimChar:
     case Primitive::kPrimShort:
       DCHECK_EQ(8u, instruction->GetVectorLength());
-      __ movd(dst, locations->InAt(0).AsRegister<Register>());
-      __ punpcklwd(dst, dst);
-      __ pshufd(dst, dst, Immediate(0));
+      __ movd(reg, locations->InAt(0).AsRegister<Register>());
+      __ punpcklwd(reg, reg);
+      __ pshufd(reg, reg, Immediate(0));
       break;
     case Primitive::kPrimInt:
       DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ movd(dst, locations->InAt(0).AsRegister<Register>());
-      __ pshufd(dst, dst, Immediate(0));
+      __ movd(reg, locations->InAt(0).AsRegister<Register>());
+      __ pshufd(reg, reg, Immediate(0));
       break;
     case Primitive::kPrimLong: {
       XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
       DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ movd(dst, locations->InAt(0).AsRegisterPairLow<Register>());
+      __ movd(reg, locations->InAt(0).AsRegisterPairLow<Register>());
       __ movd(tmp, locations->InAt(0).AsRegisterPairHigh<Register>());
-      __ punpckldq(dst, tmp);
-      __ punpcklqdq(dst, dst);
+      __ punpckldq(reg, tmp);
+      __ punpcklqdq(reg, reg);
       break;
     }
     case Primitive::kPrimFloat:
       DCHECK(locations->InAt(0).Equals(locations->Out()));
       DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ shufps(dst, dst, Immediate(0));
+      __ shufps(reg, reg, Immediate(0));
       break;
     case Primitive::kPrimDouble:
       DCHECK(locations->InAt(0).Equals(locations->Out()));
       DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ shufpd(dst, dst, Immediate(0));
+      __ shufpd(reg, reg, Immediate(0));
       break;
     default:
       LOG(FATAL) << "Unsupported SIMD type";
@@ -113,65 +100,20 @@
   }
 }
 
-void LocationsBuilderX86::VisitVecExtractScalar(HVecExtractScalar* instruction) {
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
-  switch (instruction->GetPackedType()) {
-    case Primitive::kPrimLong:
-      // Long needs extra temporary to store into the register pair.
-      locations->AddTemp(Location::RequiresFpuRegister());
-      FALLTHROUGH_INTENDED;
-    case Primitive::kPrimBoolean:
-    case Primitive::kPrimByte:
-    case Primitive::kPrimChar:
-    case Primitive::kPrimShort:
-    case Primitive::kPrimInt:
-      locations->SetInAt(0, Location::RequiresFpuRegister());
-      locations->SetOut(Location::RequiresRegister());
-      break;
-    case Primitive::kPrimFloat:
-    case Primitive::kPrimDouble:
-      locations->SetInAt(0, Location::RequiresFpuRegister());
-      locations->SetOut(Location::SameAsFirstInput());
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type";
-      UNREACHABLE();
-  }
+void LocationsBuilderX86::VisitVecSetScalars(HVecSetScalars* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
 }
 
-void InstructionCodeGeneratorX86::VisitVecExtractScalar(HVecExtractScalar* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
-  switch (instruction->GetPackedType()) {
-    case Primitive::kPrimBoolean:
-    case Primitive::kPrimByte:
-    case Primitive::kPrimChar:
-    case Primitive::kPrimShort:  // TODO: up to here, and?
-      LOG(FATAL) << "Unsupported SIMD type";
-      UNREACHABLE();
-    case Primitive::kPrimInt:
-      DCHECK_LE(4u, instruction->GetVectorLength());
-      DCHECK_LE(instruction->GetVectorLength(), 16u);
-      __ movd(locations->Out().AsRegister<Register>(), src);
-      break;
-    case Primitive::kPrimLong: {
-      XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ movd(locations->Out().AsRegisterPairLow<Register>(), src);
-      __ pshufd(tmp, src, Immediate(1));
-      __ movd(locations->Out().AsRegisterPairHigh<Register>(), tmp);
-      break;
-    }
-    case Primitive::kPrimFloat:
-    case Primitive::kPrimDouble:
-      DCHECK_LE(2u, instruction->GetVectorLength());
-      DCHECK_LE(instruction->GetVectorLength(), 4u);
-      DCHECK(locations->InAt(0).Equals(locations->Out()));  // no code required
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type";
-      UNREACHABLE();
-  }
+void InstructionCodeGeneratorX86::VisitVecSetScalars(HVecSetScalars* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+}
+
+void LocationsBuilderX86::VisitVecSumReduce(HVecSumReduce* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+}
+
+void InstructionCodeGeneratorX86::VisitVecSumReduce(HVecSumReduce* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
 }
 
 // Helper to set up locations for vector unary operations.
@@ -195,73 +137,6 @@
   }
 }
 
-void LocationsBuilderX86::VisitVecReduce(HVecReduce* instruction) {
-  CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
-  // Long reduction or min/max require a temporary.
-  if (instruction->GetPackedType() == Primitive::kPrimLong ||
-      instruction->GetKind() == HVecReduce::kMin ||
-      instruction->GetKind() == HVecReduce::kMax) {
-    instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister());
-  }
-}
-
-void InstructionCodeGeneratorX86::VisitVecReduce(HVecReduce* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
-  XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
-  switch (instruction->GetPackedType()) {
-    case Primitive::kPrimInt:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      switch (instruction->GetKind()) {
-        case HVecReduce::kSum:
-          __ movaps(dst, src);
-          __ phaddd(dst, dst);
-          __ phaddd(dst, dst);
-          break;
-        case HVecReduce::kMin: {
-          XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
-          __ movaps(tmp, src);
-          __ movaps(dst, src);
-          __ psrldq(tmp, Immediate(8));
-          __ pminsd(dst, tmp);
-          __ psrldq(tmp, Immediate(4));
-          __ pminsd(dst, tmp);
-          break;
-        }
-        case HVecReduce::kMax: {
-          XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
-          __ movaps(tmp, src);
-          __ movaps(dst, src);
-          __ psrldq(tmp, Immediate(8));
-          __ pmaxsd(dst, tmp);
-          __ psrldq(tmp, Immediate(4));
-          __ pmaxsd(dst, tmp);
-          break;
-        }
-      }
-      break;
-    case Primitive::kPrimLong: {
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
-      switch (instruction->GetKind()) {
-        case HVecReduce::kSum:
-          __ movaps(tmp, src);
-          __ movaps(dst, src);
-          __ punpckhqdq(tmp, tmp);
-          __ paddq(dst, tmp);
-          break;
-        case HVecReduce::kMin:
-        case HVecReduce::kMax:
-          LOG(FATAL) << "Unsupported SIMD type";
-      }
-      break;
-    }
-    default:
-      LOG(FATAL) << "Unsupported SIMD type";
-      UNREACHABLE();
-  }
-}
-
 void LocationsBuilderX86::VisitVecCnv(HVecCnv* instruction) {
   CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
 }
@@ -946,91 +821,6 @@
   }
 }
 
-void LocationsBuilderX86::VisitVecSetScalars(HVecSetScalars* instruction) {
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
-
-  DCHECK_EQ(1u, instruction->InputCount());  // only one input currently implemented
-
-  HInstruction* input = instruction->InputAt(0);
-  bool is_zero = IsZeroBitPattern(input);
-
-  switch (instruction->GetPackedType()) {
-    case Primitive::kPrimLong:
-      // Long needs extra temporary to load from register pairs.
-      if (!is_zero) {
-        locations->AddTemp(Location::RequiresFpuRegister());
-      }
-      FALLTHROUGH_INTENDED;
-    case Primitive::kPrimBoolean:
-    case Primitive::kPrimByte:
-    case Primitive::kPrimChar:
-    case Primitive::kPrimShort:
-    case Primitive::kPrimInt:
-      locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
-                                    : Location::RequiresRegister());
-      locations->SetOut(Location::RequiresFpuRegister());
-      break;
-    case Primitive::kPrimFloat:
-    case Primitive::kPrimDouble:
-      locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
-                                    : Location::RequiresFpuRegister());
-      locations->SetOut(Location::RequiresFpuRegister());
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type";
-      UNREACHABLE();
-  }
-}
-
-void InstructionCodeGeneratorX86::VisitVecSetScalars(HVecSetScalars* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
-
-  DCHECK_EQ(1u, instruction->InputCount());  // only one input currently implemented
-
-  // Zero out all other elements first.
-  __ xorps(dst, dst);
-
-  // Shorthand for any type of zero.
-  if (IsZeroBitPattern(instruction->InputAt(0))) {
-    return;
-  }
-
-  // Set required elements.
-  switch (instruction->GetPackedType()) {
-    case Primitive::kPrimBoolean:
-    case Primitive::kPrimByte:
-    case Primitive::kPrimChar:
-    case Primitive::kPrimShort:  // TODO: up to here, and?
-      LOG(FATAL) << "Unsupported SIMD type";
-      UNREACHABLE();
-    case Primitive::kPrimInt:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ movd(dst, locations->InAt(0).AsRegister<Register>());
-      break;
-    case Primitive::kPrimLong: {
-      XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ xorps(tmp, tmp);
-      __ movd(dst, locations->InAt(0).AsRegisterPairLow<Register>());
-      __ movd(tmp, locations->InAt(0).AsRegisterPairHigh<Register>());
-      __ punpckldq(dst, tmp);
-      break;
-    }
-    case Primitive::kPrimFloat:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ movss(dst, locations->InAt(1).AsFpuRegister<XmmRegister>());
-      break;
-    case Primitive::kPrimDouble:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ movsd(dst, locations->InAt(1).AsFpuRegister<XmmRegister>());
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type";
-      UNREACHABLE();
-  }
-}
-
 void LocationsBuilderX86::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
   LOG(FATAL) << "No SIMD for " << instr->GetId();
 }
@@ -1078,7 +868,6 @@
     case 8: scale = TIMES_8; break;
     default: break;
   }
-  // Incorporate the string or array offset in the address computation.
   uint32_t offset = is_string_char_at
       ? mirror::String::ValueOffset().Uint32Value()
       : mirror::Array::DataOffset(size).Uint32Value();
@@ -1113,7 +902,7 @@
         __ testb(Address(locations->InAt(0).AsRegister<Register>(), count_offset), Immediate(1));
         __ j(kNotZero, &not_compressed);
         // Zero extend 8 compressed bytes into 8 chars.
-        __ movsd(reg, VecAddress(locations, 1, instruction->IsStringCharAt()));
+        __ movsd(reg, VecAddress(locations, 1, /*is_string_char_at*/ true));
         __ pxor(tmp, tmp);
         __ punpcklbw(reg, tmp);
         __ jmp(&done);
diff --git a/compiler/optimizing/code_generator_vector_x86_64.cc b/compiler/optimizing/code_generator_vector_x86_64.cc
index efab0db..c7ee81c 100644
--- a/compiler/optimizing/code_generator_vector_x86_64.cc
+++ b/compiler/optimizing/code_generator_vector_x86_64.cc
@@ -27,8 +27,6 @@
 
 void LocationsBuilderX86_64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
-  HInstruction* input = instruction->InputAt(0);
-  bool is_zero = IsZeroBitPattern(input);
   switch (instruction->GetPackedType()) {
     case Primitive::kPrimBoolean:
     case Primitive::kPrimByte:
@@ -36,14 +34,12 @@
     case Primitive::kPrimShort:
     case Primitive::kPrimInt:
     case Primitive::kPrimLong:
-      locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
-                                    : Location::RequiresRegister());
+      locations->SetInAt(0, Location::RequiresRegister());
       locations->SetOut(Location::RequiresFpuRegister());
       break;
     case Primitive::kPrimFloat:
     case Primitive::kPrimDouble:
-      locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
-                                    : Location::RequiresFpuRegister());
+      locations->SetInAt(0, Location::RequiresFpuRegister());
       locations->SetOut(Location::SameAsFirstInput());
       break;
     default:
@@ -54,49 +50,42 @@
 
 void InstructionCodeGeneratorX86_64::VisitVecReplicateScalar(HVecReplicateScalar* instruction) {
   LocationSummary* locations = instruction->GetLocations();
-  XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
-
-  // Shorthand for any type of zero.
-  if (IsZeroBitPattern(instruction->InputAt(0))) {
-    __ xorps(dst, dst);
-    return;
-  }
-
+  XmmRegister reg = locations->Out().AsFpuRegister<XmmRegister>();
   switch (instruction->GetPackedType()) {
     case Primitive::kPrimBoolean:
     case Primitive::kPrimByte:
       DCHECK_EQ(16u, instruction->GetVectorLength());
-      __ movd(dst, locations->InAt(0).AsRegister<CpuRegister>());
-      __ punpcklbw(dst, dst);
-      __ punpcklwd(dst, dst);
-      __ pshufd(dst, dst, Immediate(0));
+      __ movd(reg, locations->InAt(0).AsRegister<CpuRegister>());
+      __ punpcklbw(reg, reg);
+      __ punpcklwd(reg, reg);
+      __ pshufd(reg, reg, Immediate(0));
       break;
     case Primitive::kPrimChar:
     case Primitive::kPrimShort:
       DCHECK_EQ(8u, instruction->GetVectorLength());
-      __ movd(dst, locations->InAt(0).AsRegister<CpuRegister>());
-      __ punpcklwd(dst, dst);
-      __ pshufd(dst, dst, Immediate(0));
+      __ movd(reg, locations->InAt(0).AsRegister<CpuRegister>());
+      __ punpcklwd(reg, reg);
+      __ pshufd(reg, reg, Immediate(0));
       break;
     case Primitive::kPrimInt:
       DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ movd(dst, locations->InAt(0).AsRegister<CpuRegister>());
-      __ pshufd(dst, dst, Immediate(0));
+      __ movd(reg, locations->InAt(0).AsRegister<CpuRegister>());
+      __ pshufd(reg, reg, Immediate(0));
       break;
     case Primitive::kPrimLong:
       DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ movd(dst, locations->InAt(0).AsRegister<CpuRegister>());  // is 64-bit
-      __ punpcklqdq(dst, dst);
+      __ movd(reg, locations->InAt(0).AsRegister<CpuRegister>());  // is 64-bit
+      __ punpcklqdq(reg, reg);
       break;
     case Primitive::kPrimFloat:
       DCHECK(locations->InAt(0).Equals(locations->Out()));
       DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ shufps(dst, dst, Immediate(0));
+      __ shufps(reg, reg, Immediate(0));
       break;
     case Primitive::kPrimDouble:
       DCHECK(locations->InAt(0).Equals(locations->Out()));
       DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ shufpd(dst, dst, Immediate(0));
+      __ shufpd(reg, reg, Immediate(0));
       break;
     default:
       LOG(FATAL) << "Unsupported SIMD type";
@@ -104,57 +93,20 @@
   }
 }
 
-void LocationsBuilderX86_64::VisitVecExtractScalar(HVecExtractScalar* instruction) {
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
-  switch (instruction->GetPackedType()) {
-    case Primitive::kPrimBoolean:
-    case Primitive::kPrimByte:
-    case Primitive::kPrimChar:
-    case Primitive::kPrimShort:
-    case Primitive::kPrimInt:
-    case Primitive::kPrimLong:
-      locations->SetInAt(0, Location::RequiresFpuRegister());
-      locations->SetOut(Location::RequiresRegister());
-      break;
-    case Primitive::kPrimFloat:
-    case Primitive::kPrimDouble:
-      locations->SetInAt(0, Location::RequiresFpuRegister());
-      locations->SetOut(Location::SameAsFirstInput());
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type";
-      UNREACHABLE();
-  }
+void LocationsBuilderX86_64::VisitVecSetScalars(HVecSetScalars* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
 }
 
-void InstructionCodeGeneratorX86_64::VisitVecExtractScalar(HVecExtractScalar* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
-  switch (instruction->GetPackedType()) {
-    case Primitive::kPrimBoolean:
-    case Primitive::kPrimByte:
-    case Primitive::kPrimChar:
-    case Primitive::kPrimShort:  // TODO: up to here, and?
-      LOG(FATAL) << "Unsupported SIMD type";
-      UNREACHABLE();
-    case Primitive::kPrimInt:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ movd(locations->Out().AsRegister<CpuRegister>(), src);
-      break;
-    case Primitive::kPrimLong:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ movd(locations->Out().AsRegister<CpuRegister>(), src);   // is 64-bit
-      break;
-    case Primitive::kPrimFloat:
-    case Primitive::kPrimDouble:
-      DCHECK_LE(2u, instruction->GetVectorLength());
-      DCHECK_LE(instruction->GetVectorLength(), 4u);
-      DCHECK(locations->InAt(0).Equals(locations->Out()));  // no code required
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type";
-      UNREACHABLE();
-  }
+void InstructionCodeGeneratorX86_64::VisitVecSetScalars(HVecSetScalars* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+}
+
+void LocationsBuilderX86_64::VisitVecSumReduce(HVecSumReduce* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
+}
+
+void InstructionCodeGeneratorX86_64::VisitVecSumReduce(HVecSumReduce* instruction) {
+  LOG(FATAL) << "No SIMD for " << instruction->GetId();
 }
 
 // Helper to set up locations for vector unary operations.
@@ -178,73 +130,6 @@
   }
 }
 
-void LocationsBuilderX86_64::VisitVecReduce(HVecReduce* instruction) {
-  CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
-  // Long reduction or min/max require a temporary.
-  if (instruction->GetPackedType() == Primitive::kPrimLong ||
-      instruction->GetKind() == HVecReduce::kMin ||
-      instruction->GetKind() == HVecReduce::kMax) {
-    instruction->GetLocations()->AddTemp(Location::RequiresFpuRegister());
-  }
-}
-
-void InstructionCodeGeneratorX86_64::VisitVecReduce(HVecReduce* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  XmmRegister src = locations->InAt(0).AsFpuRegister<XmmRegister>();
-  XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
-  switch (instruction->GetPackedType()) {
-    case Primitive::kPrimInt:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      switch (instruction->GetKind()) {
-        case HVecReduce::kSum:
-          __ movaps(dst, src);
-          __ phaddd(dst, dst);
-          __ phaddd(dst, dst);
-          break;
-        case HVecReduce::kMin: {
-          XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
-          __ movaps(tmp, src);
-          __ movaps(dst, src);
-          __ psrldq(tmp, Immediate(8));
-          __ pminsd(dst, tmp);
-          __ psrldq(tmp, Immediate(4));
-          __ pminsd(dst, tmp);
-          break;
-        }
-        case HVecReduce::kMax: {
-          XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
-          __ movaps(tmp, src);
-          __ movaps(dst, src);
-          __ psrldq(tmp, Immediate(8));
-          __ pmaxsd(dst, tmp);
-          __ psrldq(tmp, Immediate(4));
-          __ pmaxsd(dst, tmp);
-          break;
-        }
-      }
-      break;
-    case Primitive::kPrimLong: {
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      XmmRegister tmp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
-      switch (instruction->GetKind()) {
-        case HVecReduce::kSum:
-          __ movaps(tmp, src);
-          __ movaps(dst, src);
-          __ punpckhqdq(tmp, tmp);
-          __ paddq(dst, tmp);
-          break;
-        case HVecReduce::kMin:
-        case HVecReduce::kMax:
-          LOG(FATAL) << "Unsupported SIMD type";
-      }
-      break;
-    }
-    default:
-      LOG(FATAL) << "Unsupported SIMD type";
-      UNREACHABLE();
-  }
-}
-
 void LocationsBuilderX86_64::VisitVecCnv(HVecCnv* instruction) {
   CreateVecUnOpLocations(GetGraph()->GetArena(), instruction);
 }
@@ -929,81 +814,6 @@
   }
 }
 
-void LocationsBuilderX86_64::VisitVecSetScalars(HVecSetScalars* instruction) {
-  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
-
-  DCHECK_EQ(1u, instruction->InputCount());  // only one input currently implemented
-
-  HInstruction* input = instruction->InputAt(0);
-  bool is_zero = IsZeroBitPattern(input);
-
-  switch (instruction->GetPackedType()) {
-    case Primitive::kPrimBoolean:
-    case Primitive::kPrimByte:
-    case Primitive::kPrimChar:
-    case Primitive::kPrimShort:
-    case Primitive::kPrimInt:
-    case Primitive::kPrimLong:
-      locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
-                                    : Location::RequiresRegister());
-      locations->SetOut(Location::RequiresFpuRegister());
-      break;
-    case Primitive::kPrimFloat:
-    case Primitive::kPrimDouble:
-      locations->SetInAt(0, is_zero ? Location::ConstantLocation(input->AsConstant())
-                                    : Location::RequiresFpuRegister());
-      locations->SetOut(Location::RequiresFpuRegister());
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type";
-      UNREACHABLE();
-  }
-}
-
-void InstructionCodeGeneratorX86_64::VisitVecSetScalars(HVecSetScalars* instruction) {
-  LocationSummary* locations = instruction->GetLocations();
-  XmmRegister dst = locations->Out().AsFpuRegister<XmmRegister>();
-
-  DCHECK_EQ(1u, instruction->InputCount());  // only one input currently implemented
-
-  // Zero out all other elements first.
-  __ xorps(dst, dst);
-
-  // Shorthand for any type of zero.
-  if (IsZeroBitPattern(instruction->InputAt(0))) {
-    return;
-  }
-
-  // Set required elements.
-  switch (instruction->GetPackedType()) {
-    case Primitive::kPrimBoolean:
-    case Primitive::kPrimByte:
-    case Primitive::kPrimChar:
-    case Primitive::kPrimShort:  // TODO: up to here, and?
-      LOG(FATAL) << "Unsupported SIMD type";
-      UNREACHABLE();
-    case Primitive::kPrimInt:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ movd(dst, locations->InAt(0).AsRegister<CpuRegister>());
-      break;
-    case Primitive::kPrimLong:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ movd(dst, locations->InAt(0).AsRegister<CpuRegister>());  // is 64-bit
-      break;
-    case Primitive::kPrimFloat:
-      DCHECK_EQ(4u, instruction->GetVectorLength());
-      __ movss(dst, locations->InAt(0).AsFpuRegister<XmmRegister>());
-      break;
-    case Primitive::kPrimDouble:
-      DCHECK_EQ(2u, instruction->GetVectorLength());
-      __ movsd(dst, locations->InAt(0).AsFpuRegister<XmmRegister>());
-      break;
-    default:
-      LOG(FATAL) << "Unsupported SIMD type";
-      UNREACHABLE();
-  }
-}
-
 void LocationsBuilderX86_64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) {
   LOG(FATAL) << "No SIMD for " << instr->GetId();
 }
@@ -1051,7 +861,6 @@
     case 8: scale = TIMES_8; break;
     default: break;
   }
-  // Incorporate the string or array offset in the address computation.
   uint32_t offset = is_string_char_at
       ? mirror::String::ValueOffset().Uint32Value()
       : mirror::Array::DataOffset(size).Uint32Value();
@@ -1086,7 +895,7 @@
         __ testb(Address(locations->InAt(0).AsRegister<CpuRegister>(), count_offset), Immediate(1));
         __ j(kNotZero, &not_compressed);
         // Zero extend 8 compressed bytes into 8 chars.
-        __ movsd(reg, VecAddress(locations, 1, instruction->IsStringCharAt()));
+        __ movsd(reg, VecAddress(locations, 1, /*is_string_char_at*/ true));
         __ pxor(tmp, tmp);
         __ punpcklbw(reg, tmp);
         __ jmp(&done);
diff --git a/compiler/optimizing/induction_var_range.cc b/compiler/optimizing/induction_var_range.cc
index f35aace..089340e 100644
--- a/compiler/optimizing/induction_var_range.cc
+++ b/compiler/optimizing/induction_var_range.cc
@@ -87,8 +87,10 @@
                IsGEZero(instruction->InputAt(1));
       case Intrinsics::kMathAbsInt:
       case Intrinsics::kMathAbsLong:
-        // Instruction ABS(x) is >= 0.
-        return true;
+        // Instruction ABS(>=0) is >= 0.
+        // NOTE: ABS(minint) = minint prevents assuming
+        //       >= 0 without looking at the argument.
+        return IsGEZero(instruction->InputAt(0));
       default:
         break;
     }
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc
index f8f4eb2..027ba77 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -285,19 +285,6 @@
   return false;
 }
 
-// Translates operation to reduction kind.
-static HVecReduce::ReductionKind GetReductionKind(HInstruction* reduction) {
-  if (reduction->IsVecAdd() || reduction->IsVecSub()) {
-    return HVecReduce::kSum;
-  } else if (reduction->IsVecMin()) {
-    return HVecReduce::kMin;
-  } else if (reduction->IsVecMax()) {
-    return HVecReduce::kMax;
-  }
-  LOG(FATAL) << "Unsupported SIMD reduction";
-  UNREACHABLE();
-}
-
 // Test vector restrictions.
 static bool HasVectorRestrictions(uint64_t restrictions, uint64_t tested) {
   return (restrictions & tested) != 0;
@@ -347,8 +334,7 @@
       vector_peeling_candidate_(nullptr),
       vector_runtime_test_a_(nullptr),
       vector_runtime_test_b_(nullptr),
-      vector_map_(nullptr),
-      vector_permanent_map_(nullptr) {
+      vector_map_(nullptr) {
 }
 
 void HLoopOptimization::Run() {
@@ -402,14 +388,11 @@
     ArenaSet<ArrayReference> refs(loop_allocator_->Adapter(kArenaAllocLoopOptimization));
     ArenaSafeMap<HInstruction*, HInstruction*> map(
         std::less<HInstruction*>(), loop_allocator_->Adapter(kArenaAllocLoopOptimization));
-    ArenaSafeMap<HInstruction*, HInstruction*> perm(
-        std::less<HInstruction*>(), loop_allocator_->Adapter(kArenaAllocLoopOptimization));
     // Attach.
     iset_ = &iset;
     reductions_ = &reds;
     vector_refs_ = &refs;
     vector_map_ = &map;
-    vector_permanent_map_ = &perm;
     // Traverse.
     TraverseLoopsInnerToOuter(top_loop_);
     // Detach.
@@ -417,7 +400,6 @@
     reductions_ = nullptr;
     vector_refs_ = nullptr;
     vector_map_ = nullptr;
-    vector_permanent_map_ = nullptr;
   }
 }
 
@@ -621,6 +603,7 @@
   // Vectorize loop, if possible and valid.
   if (kEnableVectorization &&
       TrySetSimpleLoopHeader(header, &main_phi) &&
+      reductions_->empty() &&  // TODO: possible with some effort
       ShouldVectorize(node, body, trip_count) &&
       TryAssignLastValue(node->loop_info, main_phi, preheader, /*collect_loop_uses*/ true)) {
     Vectorize(node, body, exit, trip_count);
@@ -819,13 +802,6 @@
                     /*unroll*/ 1);
   }
 
-  // Link reductions to their final uses.
-  for (auto i = reductions_->begin(); i != reductions_->end(); ++i) {
-    if (i->first->IsPhi()) {
-      i->first->ReplaceWith(ReduceAndExtractIfNeeded(i->second));
-    }
-  }
-
   // Remove the original loop by disconnecting the body block
   // and removing all instructions from the header.
   block->DisconnectAndDelete();
@@ -865,10 +841,21 @@
   vector_header_->AddInstruction(cond);
   vector_header_->AddInstruction(new (global_allocator_) HIf(cond));
   vector_index_ = phi;
-  vector_permanent_map_->clear();  // preserved over unrolling
   for (uint32_t u = 0; u < unroll; u++) {
+    // Clear map, leaving loop invariants setup during unrolling.
+    if (u == 0) {
+      vector_map_->clear();
+    } else {
+      for (auto i = vector_map_->begin(); i != vector_map_->end(); ) {
+        if (i->second->IsVecReplicateScalar()) {
+          DCHECK(node->loop_info->IsDefinedOutOfTheLoop(i->first));
+          ++i;
+        } else {
+          i = vector_map_->erase(i);
+        }
+      }
+    }
     // Generate instruction map.
-    vector_map_->clear();
     for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
       bool vectorized_def = VectorizeDef(node, it.Current(), /*generate_code*/ true);
       DCHECK(vectorized_def);
@@ -885,17 +872,9 @@
         }
       }
     }
-    // Generate the induction.
     vector_index_ = new (global_allocator_) HAdd(induc_type, vector_index_, step);
     Insert(vector_body_, vector_index_);
   }
-  // Finalize phi inputs for the reductions (if any).
-  for (auto i = reductions_->begin(); i != reductions_->end(); ++i) {
-    if (!i->first->IsPhi()) {
-      DCHECK(i->second->IsPhi());
-      GenerateVecReductionPhiInputs(i->second->AsPhi(), i->first);
-    }
-  }
   // Finalize phi inputs for the loop index.
   phi->AddInput(lo);
   phi->AddInput(vector_index_);
@@ -931,23 +910,6 @@
     }
     return false;
   }
-  // Accept a left-hand-side reduction for
-  // (1) supported vector type,
-  // (2) vectorizable right-hand-side value.
-  auto redit = reductions_->find(instruction);
-  if (redit != reductions_->end()) {
-    Primitive::Type type = instruction->GetType();
-    if (TrySetVectorType(type, &restrictions) &&
-        VectorizeUse(node, instruction, generate_code, type, restrictions)) {
-      if (generate_code) {
-        HInstruction* new_red = vector_map_->Get(instruction);
-        vector_permanent_map_->Put(new_red, vector_map_->Get(redit->second));
-        vector_permanent_map_->Overwrite(redit->second, new_red);
-      }
-      return true;
-    }
-    return false;
-  }
   // Branch back okay.
   if (instruction->IsGoto()) {
     return true;
@@ -1003,21 +965,6 @@
       }
       return true;
     }
-  } else if (instruction->IsPhi()) {
-    // Accept particular phi operations.
-    if (reductions_->find(instruction) != reductions_->end()) {
-      // Deal with vector restrictions.
-      if (HasVectorRestrictions(restrictions, kNoReduction)) {
-        return false;
-      }
-      // Accept a reduction.
-      if (generate_code) {
-        GenerateVecReductionPhi(instruction->AsPhi());
-      }
-      return true;
-    }
-    // TODO: accept right-hand-side induction?
-    return false;
   } else if (instruction->IsTypeConversion()) {
     // Accept particular type conversions.
     HTypeConversion* conversion = instruction->AsTypeConversion();
@@ -1208,14 +1155,14 @@
       switch (type) {
         case Primitive::kPrimBoolean:
         case Primitive::kPrimByte:
-          *restrictions |= kNoDiv | kNoReduction;
+          *restrictions |= kNoDiv;
           return TrySetVectorLength(8);
         case Primitive::kPrimChar:
         case Primitive::kPrimShort:
-          *restrictions |= kNoDiv | kNoStringCharAt | kNoReduction;
+          *restrictions |= kNoDiv | kNoStringCharAt;
           return TrySetVectorLength(4);
         case Primitive::kPrimInt:
-          *restrictions |= kNoDiv | kNoReduction;
+          *restrictions |= kNoDiv;
           return TrySetVectorLength(2);
         default:
           break;
@@ -1227,11 +1174,11 @@
       switch (type) {
         case Primitive::kPrimBoolean:
         case Primitive::kPrimByte:
-          *restrictions |= kNoDiv | kNoReduction;
+          *restrictions |= kNoDiv;
           return TrySetVectorLength(16);
         case Primitive::kPrimChar:
         case Primitive::kPrimShort:
-          *restrictions |= kNoDiv | kNoReduction;
+          *restrictions |= kNoDiv;
           return TrySetVectorLength(8);
         case Primitive::kPrimInt:
           *restrictions |= kNoDiv;
@@ -1240,10 +1187,8 @@
           *restrictions |= kNoDiv | kNoMul | kNoMinMax;
           return TrySetVectorLength(2);
         case Primitive::kPrimFloat:
-          *restrictions |= kNoReduction;
           return TrySetVectorLength(4);
         case Primitive::kPrimDouble:
-          *restrictions |= kNoReduction;
           return TrySetVectorLength(2);
         default:
           return false;
@@ -1255,12 +1200,11 @@
         switch (type) {
           case Primitive::kPrimBoolean:
           case Primitive::kPrimByte:
-            *restrictions |=
-                kNoMul | kNoDiv | kNoShift | kNoAbs | kNoSignedHAdd | kNoUnroundedHAdd | kNoReduction;
+            *restrictions |= kNoMul | kNoDiv | kNoShift | kNoAbs | kNoSignedHAdd | kNoUnroundedHAdd;
             return TrySetVectorLength(16);
           case Primitive::kPrimChar:
           case Primitive::kPrimShort:
-            *restrictions |= kNoDiv | kNoAbs | kNoSignedHAdd | kNoUnroundedHAdd | kNoReduction;
+            *restrictions |= kNoDiv | kNoAbs | kNoSignedHAdd | kNoUnroundedHAdd;
             return TrySetVectorLength(8);
           case Primitive::kPrimInt:
             *restrictions |= kNoDiv;
@@ -1269,10 +1213,10 @@
             *restrictions |= kNoMul | kNoDiv | kNoShr | kNoAbs | kNoMinMax;
             return TrySetVectorLength(2);
           case Primitive::kPrimFloat:
-            *restrictions |= kNoMinMax | kNoReduction;  // minmax: -0.0 vs +0.0
+            *restrictions |= kNoMinMax;  // -0.0 vs +0.0
             return TrySetVectorLength(4);
           case Primitive::kPrimDouble:
-            *restrictions |= kNoMinMax | kNoReduction;  // minmax: -0.0 vs +0.0
+            *restrictions |= kNoMinMax;  // -0.0 vs +0.0
             return TrySetVectorLength(2);
           default:
             break;
@@ -1284,23 +1228,23 @@
         switch (type) {
           case Primitive::kPrimBoolean:
           case Primitive::kPrimByte:
-            *restrictions |= kNoDiv | kNoReduction;
+            *restrictions |= kNoDiv;
             return TrySetVectorLength(16);
           case Primitive::kPrimChar:
           case Primitive::kPrimShort:
-            *restrictions |= kNoDiv | kNoStringCharAt | kNoReduction;
+            *restrictions |= kNoDiv | kNoStringCharAt;
             return TrySetVectorLength(8);
           case Primitive::kPrimInt:
-            *restrictions |= kNoDiv | kNoReduction;
+            *restrictions |= kNoDiv;
             return TrySetVectorLength(4);
           case Primitive::kPrimLong:
-            *restrictions |= kNoDiv | kNoReduction;
+            *restrictions |= kNoDiv;
             return TrySetVectorLength(2);
           case Primitive::kPrimFloat:
-            *restrictions |= kNoMinMax | kNoReduction;  // min/max(x, NaN)
+            *restrictions |= kNoMinMax;  // min/max(x, NaN)
             return TrySetVectorLength(4);
           case Primitive::kPrimDouble:
-            *restrictions |= kNoMinMax | kNoReduction;  // min/max(x, NaN)
+            *restrictions |= kNoMinMax;  // min/max(x, NaN)
             return TrySetVectorLength(2);
           default:
             break;
@@ -1312,23 +1256,23 @@
         switch (type) {
           case Primitive::kPrimBoolean:
           case Primitive::kPrimByte:
-            *restrictions |= kNoDiv | kNoReduction;
+            *restrictions |= kNoDiv;
             return TrySetVectorLength(16);
           case Primitive::kPrimChar:
           case Primitive::kPrimShort:
-            *restrictions |= kNoDiv | kNoStringCharAt | kNoReduction;
+            *restrictions |= kNoDiv | kNoStringCharAt;
             return TrySetVectorLength(8);
           case Primitive::kPrimInt:
-            *restrictions |= kNoDiv | kNoReduction;
+            *restrictions |= kNoDiv;
             return TrySetVectorLength(4);
           case Primitive::kPrimLong:
-            *restrictions |= kNoDiv | kNoReduction;
+            *restrictions |= kNoDiv;
             return TrySetVectorLength(2);
           case Primitive::kPrimFloat:
-            *restrictions |= kNoMinMax | kNoReduction;  // min/max(x, NaN)
+            *restrictions |= kNoMinMax;  // min/max(x, NaN)
             return TrySetVectorLength(4);
           case Primitive::kPrimDouble:
-            *restrictions |= kNoMinMax | kNoReduction;  // min/max(x, NaN)
+            *restrictions |= kNoMinMax;  // min/max(x, NaN)
             return TrySetVectorLength(2);
           default:
             break;
@@ -1361,16 +1305,9 @@
       return;
     }
     // In vector code, explicit scalar expansion is needed.
-    HInstruction* vector = nullptr;
-    auto it = vector_permanent_map_->find(org);
-    if (it != vector_permanent_map_->end()) {
-      vector = it->second;  // reuse during unrolling
-    } else {
-      vector = new (global_allocator_) HVecReplicateScalar(
-          global_allocator_, org, type, vector_length_);
-      vector_permanent_map_->Put(org, Insert(vector_preheader_, vector));
-    }
-    vector_map_->Put(org, vector);
+    HInstruction* vector = new (global_allocator_) HVecReplicateScalar(
+        global_allocator_, org, type, vector_length_);
+    vector_map_->Put(org, Insert(vector_preheader_, vector));
   }
 }
 
@@ -1425,78 +1362,6 @@
   vector_map_->Put(org, vector);
 }
 
-void HLoopOptimization::GenerateVecReductionPhi(HPhi* phi) {
-  DCHECK(reductions_->find(phi) != reductions_->end());
-  DCHECK(reductions_->Get(phi->InputAt(1)) == phi);
-  HInstruction* vector = nullptr;
-  if (vector_mode_ == kSequential) {
-    HPhi* new_phi = new (global_allocator_) HPhi(
-        global_allocator_, kNoRegNumber, 0, phi->GetType());
-    vector_header_->AddPhi(new_phi);
-    vector = new_phi;
-  } else {
-    // Link vector reduction back to prior unrolled update, or a first phi.
-    auto it = vector_permanent_map_->find(phi);
-    if (it != vector_permanent_map_->end()) {
-      vector = it->second;
-    } else {
-      HPhi* new_phi = new (global_allocator_) HPhi(
-          global_allocator_, kNoRegNumber, 0, HVecOperation::kSIMDType);
-      vector_header_->AddPhi(new_phi);
-      vector = new_phi;
-    }
-  }
-  vector_map_->Put(phi, vector);
-}
-
-void HLoopOptimization::GenerateVecReductionPhiInputs(HPhi* phi, HInstruction* reduction) {
-  HInstruction* new_phi = vector_map_->Get(phi);
-  HInstruction* new_init = reductions_->Get(phi);
-  HInstruction* new_red = vector_map_->Get(reduction);
-  // Link unrolled vector loop back to new phi.
-  for (; !new_phi->IsPhi(); new_phi = vector_permanent_map_->Get(new_phi)) {
-    DCHECK(new_phi->IsVecOperation());
-  }
-  // Prepare the new initialization.
-  if (vector_mode_ == kVector) {
-    // Generate a [initial, 0, .., 0] vector.
-    new_init = Insert(
-            vector_preheader_,
-            new (global_allocator_) HVecSetScalars(
-                global_allocator_, &new_init, phi->GetType(), vector_length_, 1));
-  } else {
-    new_init = ReduceAndExtractIfNeeded(new_init);
-  }
-  // Set the phi inputs.
-  DCHECK(new_phi->IsPhi());
-  new_phi->AsPhi()->AddInput(new_init);
-  new_phi->AsPhi()->AddInput(new_red);
-  // New feed value for next phi (safe mutation in iteration).
-  reductions_->find(phi)->second = new_phi;
-}
-
-HInstruction* HLoopOptimization::ReduceAndExtractIfNeeded(HInstruction* instruction) {
-  if (instruction->IsPhi()) {
-    HInstruction* input = instruction->InputAt(1);
-    if (input->IsVecOperation()) {
-      Primitive::Type type = input->AsVecOperation()->GetPackedType();
-      HBasicBlock* exit = instruction->GetBlock()->GetSuccessors()[0];
-      // Generate a vector reduction and scalar extract
-      //    x = REDUCE( [x_1, .., x_n] )
-      //    y = x_1
-      // along the exit of the defining loop.
-      HVecReduce::ReductionKind kind = GetReductionKind(input);
-      HInstruction* reduce = new (global_allocator_) HVecReduce(
-          global_allocator_, instruction, type, vector_length_, kind);
-      exit->InsertInstructionBefore(reduce, exit->GetFirstInstruction());
-      instruction = new (global_allocator_) HVecExtractScalar(
-          global_allocator_, reduce, type, vector_length_, 0);
-      exit->InsertInstructionAfter(instruction, reduce);
-    }
-  }
-  return instruction;
-}
-
 #define GENERATE_VEC(x, y) \
   if (vector_mode_ == kVector) { \
     vector = (x); \
@@ -1677,9 +1542,10 @@
   // Test for top level arithmetic shift right x >> 1 or logical shift right x >>> 1
   // (note whether the sign bit in wider precision is shifted in has no effect
   // on the narrow precision computed by the idiom).
+  int64_t distance = 0;
   if ((instruction->IsShr() ||
        instruction->IsUShr()) &&
-      IsInt64Value(instruction->InputAt(1), 1)) {
+      IsInt64AndGet(instruction->InputAt(1), /*out*/ &distance) && distance == 1) {
     // Test for (a + b + c) >> 1 for optional constant c.
     HInstruction* a = nullptr;
     HInstruction* b = nullptr;
diff --git a/compiler/optimizing/loop_optimization.h b/compiler/optimizing/loop_optimization.h
index ba9126c..49be8a3 100644
--- a/compiler/optimizing/loop_optimization.h
+++ b/compiler/optimizing/loop_optimization.h
@@ -62,18 +62,17 @@
    * Vectorization restrictions (bit mask).
    */
   enum VectorRestrictions {
-    kNone            = 0,        // no restrictions
-    kNoMul           = 1 << 0,   // no multiplication
-    kNoDiv           = 1 << 1,   // no division
-    kNoShift         = 1 << 2,   // no shift
-    kNoShr           = 1 << 3,   // no arithmetic shift right
-    kNoHiBits        = 1 << 4,   // "wider" operations cannot bring in higher order bits
-    kNoSignedHAdd    = 1 << 5,   // no signed halving add
-    kNoUnroundedHAdd = 1 << 6,   // no unrounded halving add
-    kNoAbs           = 1 << 7,   // no absolute value
-    kNoMinMax        = 1 << 8,   // no min/max
-    kNoStringCharAt  = 1 << 9,   // no StringCharAt
-    kNoReduction     = 1 << 10,  // no reduction
+    kNone            = 0,    // no restrictions
+    kNoMul           = 1,    // no multiplication
+    kNoDiv           = 2,    // no division
+    kNoShift         = 4,    // no shift
+    kNoShr           = 8,    // no arithmetic shift right
+    kNoHiBits        = 16,   // "wider" operations cannot bring in higher order bits
+    kNoSignedHAdd    = 32,   // no signed halving add
+    kNoUnroundedHAdd = 64,   // no unrounded halving add
+    kNoAbs           = 128,  // no absolute value
+    kNoMinMax        = 256,  // no min/max
+    kNoStringCharAt  = 512,  // no StringCharAt
   };
 
   /*
@@ -156,9 +155,6 @@
                       HInstruction* opb,
                       HInstruction* offset,
                       Primitive::Type type);
-  void GenerateVecReductionPhi(HPhi* phi);
-  void GenerateVecReductionPhiInputs(HPhi* phi, HInstruction* reduction);
-  HInstruction* ReduceAndExtractIfNeeded(HInstruction* instruction);
   void GenerateVecOp(HInstruction* org,
                      HInstruction* opa,
                      HInstruction* opb,
@@ -257,10 +253,6 @@
   // Contents reside in phase-local heap memory.
   ArenaSafeMap<HInstruction*, HInstruction*>* vector_map_;
 
-  // Permanent mapping used during vectorization synthesis.
-  // Contents reside in phase-local heap memory.
-  ArenaSafeMap<HInstruction*, HInstruction*>* vector_permanent_map_;
-
   // Temporary vectorization bookkeeping.
   VectorMode vector_mode_;  // synthesis mode
   HBasicBlock* vector_preheader_;  // preheader of the new loop
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 869fdd4..f60d532 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -1374,8 +1374,7 @@
   M(UShr, BinaryOperation)                                              \
   M(Xor, BinaryOperation)                                               \
   M(VecReplicateScalar, VecUnaryOperation)                              \
-  M(VecExtractScalar, VecUnaryOperation)                                \
-  M(VecReduce, VecUnaryOperation)                                       \
+  M(VecSumReduce, VecUnaryOperation)                                    \
   M(VecCnv, VecUnaryOperation)                                          \
   M(VecNeg, VecUnaryOperation)                                          \
   M(VecAbs, VecUnaryOperation)                                          \
@@ -7031,17 +7030,6 @@
   return false;
 }
 
-// Returns true iff instruction is the given integral constant.
-inline bool IsInt64Value(HInstruction* instruction, int64_t value) {
-  int64_t val = 0;
-  return IsInt64AndGet(instruction, &val) && val == value;
-}
-
-// Returns true iff instruction is a zero bit pattern.
-inline bool IsZeroBitPattern(HInstruction* instruction) {
-  return instruction->IsConstant() && instruction->AsConstant()->IsZeroBitPattern();
-}
-
 #define INSTRUCTION_TYPE_CHECK(type, super)                                    \
   inline bool HInstruction::Is##type() const { return GetKind() == k##type; }  \
   inline const H##type* HInstruction::As##type() const {                       \
diff --git a/compiler/optimizing/nodes_vector.h b/compiler/optimizing/nodes_vector.h
index 886d75e..6261171 100644
--- a/compiler/optimizing/nodes_vector.h
+++ b/compiler/optimizing/nodes_vector.h
@@ -63,10 +63,6 @@
 // GetVectorLength() x GetPackedType() operations simultaneously.
 class HVecOperation : public HVariableInputSizeInstruction {
  public:
-  // A SIMD operation looks like a FPU location.
-  // TODO: we could introduce SIMD types in HIR.
-  static constexpr Primitive::Type kSIMDType = Primitive::kPrimDouble;
-
   HVecOperation(ArenaAllocator* arena,
                 Primitive::Type packed_type,
                 SideEffects side_effects,
@@ -93,9 +89,10 @@
     return vector_length_ * Primitive::ComponentSize(GetPackedType());
   }
 
-  // Returns the type of the vector operation.
+  // Returns the type of the vector operation: a SIMD operation looks like a FPU location.
+  // TODO: we could introduce SIMD types in HIR.
   Primitive::Type GetType() const OVERRIDE {
-    return kSIMDType;
+    return Primitive::kPrimDouble;
   }
 
   // Returns the true component type packed in a vector.
@@ -223,11 +220,8 @@
   DISALLOW_COPY_AND_ASSIGN(HVecMemoryOperation);
 };
 
-// Packed type consistency checker ("same vector length" integral types may mix freely).
+// Packed type consistency checker (same vector length integral types may mix freely).
 inline static bool HasConsistentPackedTypes(HInstruction* input, Primitive::Type type) {
-  if (input->IsPhi()) {
-    return input->GetType() == HVecOperation::kSIMDType;  // carries SIMD
-  }
   DCHECK(input->IsVecOperation());
   Primitive::Type input_type = input->AsVecOperation()->GetPackedType();
   switch (input_type) {
@@ -271,77 +265,27 @@
   DISALLOW_COPY_AND_ASSIGN(HVecReplicateScalar);
 };
 
-// Extracts a particular scalar from the given vector,
-// viz. extract[ x1, .. , xn ] = x_i.
-//
-// TODO: for now only i == 1 case supported.
-class HVecExtractScalar FINAL : public HVecUnaryOperation {
- public:
-  HVecExtractScalar(ArenaAllocator* arena,
-                    HInstruction* input,
-                    Primitive::Type packed_type,
-                    size_t vector_length,
-                    size_t index,
-                    uint32_t dex_pc = kNoDexPc)
+// Sum-reduces the given vector into a shorter vector (m < n) or scalar (m = 1),
+// viz. sum-reduce[ x1, .. , xn ] = [ y1, .., ym ], where yi = sum_j x_j.
+class HVecSumReduce FINAL : public HVecUnaryOperation {
+  HVecSumReduce(ArenaAllocator* arena,
+                HInstruction* input,
+                Primitive::Type packed_type,
+                size_t vector_length,
+                uint32_t dex_pc = kNoDexPc)
       : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) {
     DCHECK(HasConsistentPackedTypes(input, packed_type));
-    DCHECK_LT(index, vector_length);
-    DCHECK_EQ(index, 0u);
   }
 
-  // Yields a single component in the vector.
-  Primitive::Type GetType() const OVERRIDE {
-    return GetPackedType();
-  }
-
-  // An extract needs to stay in place, since SIMD registers are not
-  // kept alive across vector loop boundaries (yet).
-  bool CanBeMoved() const OVERRIDE { return false; }
-
-  DECLARE_INSTRUCTION(VecExtractScalar);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(HVecExtractScalar);
-};
-
-// Reduces the given vector into the first element as sum/min/max,
-// viz. sum-reduce[ x1, .. , xn ] = [ y, ---- ], where y = sum xi
-// and the "-" denotes "don't care" (implementation dependent).
-class HVecReduce FINAL : public HVecUnaryOperation {
- public:
-  enum ReductionKind {
-    kSum = 1,
-    kMin = 2,
-    kMax = 3
-  };
-
-  HVecReduce(ArenaAllocator* arena,
-             HInstruction* input,
-             Primitive::Type packed_type,
-             size_t vector_length,
-             ReductionKind kind,
-             uint32_t dex_pc = kNoDexPc)
-      : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc),
-        kind_(kind) {
-    DCHECK(HasConsistentPackedTypes(input, packed_type));
-  }
-
-  ReductionKind GetKind() const { return kind_; }
+  // TODO: probably integral promotion
+  Primitive::Type GetType() const OVERRIDE { return GetPackedType(); }
 
   bool CanBeMoved() const OVERRIDE { return true; }
 
-  bool InstructionDataEquals(const HInstruction* other) const OVERRIDE {
-    DCHECK(other->IsVecReduce());
-    const HVecReduce* o = other->AsVecReduce();
-    return HVecOperation::InstructionDataEquals(o) && GetKind() == o->GetKind();
-  }
-
-  DECLARE_INSTRUCTION(VecReduce);
+  DECLARE_INSTRUCTION(VecSumReduce);
 
  private:
-  const ReductionKind kind_;
-
-  DISALLOW_COPY_AND_ASSIGN(HVecReduce);
+  DISALLOW_COPY_AND_ASSIGN(HVecSumReduce);
 };
 
 // Converts every component in the vector,
@@ -810,23 +754,20 @@
 //
 
 // Assigns the given scalar elements to a vector,
-// viz. set( array(x1, .., xn) ) = [ x1, .. ,           xn ] if n == m,
-//      set( array(x1, .., xm) ) = [ x1, .. , xm, 0, .., 0 ] if m <  n.
+// viz. set( array(x1, .., xn) ) = [ x1, .. , xn ].
 class HVecSetScalars FINAL : public HVecOperation {
- public:
   HVecSetScalars(ArenaAllocator* arena,
                  HInstruction** scalars,  // array
                  Primitive::Type packed_type,
                  size_t vector_length,
-                 size_t number_of_scalars,
                  uint32_t dex_pc = kNoDexPc)
       : HVecOperation(arena,
                       packed_type,
                       SideEffects::None(),
-                      number_of_scalars,
+                      /* number_of_inputs */ vector_length,
                       vector_length,
                       dex_pc) {
-    for (size_t i = 0; i < number_of_scalars; i++) {
+    for (size_t i = 0; i < vector_length; i++) {
       DCHECK(!scalars[i]->IsVecOperation());
       SetRawInputAt(0, scalars[i]);
     }
diff --git a/compiler/optimizing/nodes_vector_test.cc b/compiler/optimizing/nodes_vector_test.cc
index 5a56a2c..0238ea4 100644
--- a/compiler/optimizing/nodes_vector_test.cc
+++ b/compiler/optimizing/nodes_vector_test.cc
@@ -332,32 +332,4 @@
   EXPECT_FALSE(v1->Equals(v3));  // different vector lengths
 }
 
-TEST_F(NodesVectorTest, VectorKindMattersOnReduce) {
-  HVecOperation* v0 = new (&allocator_)
-      HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 4);
-
-  HVecReduce* v1 = new (&allocator_) HVecReduce(
-      &allocator_, v0, Primitive::kPrimInt, 4, HVecReduce::kSum);
-  HVecReduce* v2 = new (&allocator_) HVecReduce(
-      &allocator_, v0, Primitive::kPrimInt, 4, HVecReduce::kMin);
-  HVecReduce* v3 = new (&allocator_) HVecReduce(
-      &allocator_, v0, Primitive::kPrimInt, 4, HVecReduce::kMax);
-
-  EXPECT_FALSE(v0->CanBeMoved());
-  EXPECT_TRUE(v1->CanBeMoved());
-  EXPECT_TRUE(v2->CanBeMoved());
-  EXPECT_TRUE(v3->CanBeMoved());
-
-  EXPECT_EQ(HVecReduce::kSum, v1->GetKind());
-  EXPECT_EQ(HVecReduce::kMin, v2->GetKind());
-  EXPECT_EQ(HVecReduce::kMax, v3->GetKind());
-
-  EXPECT_TRUE(v1->Equals(v1));
-  EXPECT_TRUE(v2->Equals(v2));
-  EXPECT_TRUE(v3->Equals(v3));
-
-  EXPECT_FALSE(v1->Equals(v2));  // different kinds
-  EXPECT_FALSE(v1->Equals(v3));
-}
-
 }  // namespace art
diff --git a/compiler/optimizing/scheduler_arm64.cc b/compiler/optimizing/scheduler_arm64.cc
index 1d9d28a..510619f 100644
--- a/compiler/optimizing/scheduler_arm64.cc
+++ b/compiler/optimizing/scheduler_arm64.cc
@@ -215,12 +215,12 @@
   last_visited_latency_ = kArm64SIMDReplicateOpLatency;
 }
 
-void SchedulingLatencyVisitorARM64::VisitVecExtractScalar(HVecExtractScalar* instr) {
-  HandleSimpleArithmeticSIMD(instr);
+void SchedulingLatencyVisitorARM64::VisitVecSetScalars(HVecSetScalars* instr) {
+  LOG(FATAL) << "Unsupported SIMD instruction " << instr->GetId();
 }
 
-void SchedulingLatencyVisitorARM64::VisitVecReduce(HVecReduce* instr) {
-  HandleSimpleArithmeticSIMD(instr);
+void SchedulingLatencyVisitorARM64::VisitVecSumReduce(HVecSumReduce* instr) {
+  LOG(FATAL) << "Unsupported SIMD instruction " << instr->GetId();
 }
 
 void SchedulingLatencyVisitorARM64::VisitVecCnv(HVecCnv* instr ATTRIBUTE_UNUSED) {
@@ -283,8 +283,8 @@
   last_visited_latency_ = kArm64SIMDIntegerOpLatency;
 }
 
-void SchedulingLatencyVisitorARM64::VisitVecAndNot(HVecAndNot* instr ATTRIBUTE_UNUSED) {
-  last_visited_latency_ = kArm64SIMDIntegerOpLatency;
+void SchedulingLatencyVisitorARM64::VisitVecAndNot(HVecAndNot* instr) {
+  LOG(FATAL) << "Unsupported SIMD instruction " << instr->GetId();
 }
 
 void SchedulingLatencyVisitorARM64::VisitVecOr(HVecOr* instr ATTRIBUTE_UNUSED) {
@@ -307,10 +307,6 @@
   HandleSimpleArithmeticSIMD(instr);
 }
 
-void SchedulingLatencyVisitorARM64::VisitVecSetScalars(HVecSetScalars* instr) {
-  HandleSimpleArithmeticSIMD(instr);
-}
-
 void SchedulingLatencyVisitorARM64::VisitVecMultiplyAccumulate(
     HVecMultiplyAccumulate* instr ATTRIBUTE_UNUSED) {
   last_visited_latency_ = kArm64SIMDMulIntegerLatency;
diff --git a/compiler/optimizing/scheduler_arm64.h b/compiler/optimizing/scheduler_arm64.h
index e1a80ec..63d5b7d 100644
--- a/compiler/optimizing/scheduler_arm64.h
+++ b/compiler/optimizing/scheduler_arm64.h
@@ -83,8 +83,8 @@
   M(SuspendCheck         , unused)                   \
   M(TypeConversion       , unused)                   \
   M(VecReplicateScalar   , unused)                   \
-  M(VecExtractScalar     , unused)                   \
-  M(VecReduce            , unused)                   \
+  M(VecSetScalars        , unused)                   \
+  M(VecSumReduce         , unused)                   \
   M(VecCnv               , unused)                   \
   M(VecNeg               , unused)                   \
   M(VecAbs               , unused)                   \
@@ -103,7 +103,6 @@
   M(VecShl               , unused)                   \
   M(VecShr               , unused)                   \
   M(VecUShr              , unused)                   \
-  M(VecSetScalars        , unused)                   \
   M(VecMultiplyAccumulate, unused)                   \
   M(VecLoad              , unused)                   \
   M(VecStore             , unused)
diff --git a/compiler/verifier_deps_test.cc b/compiler/verifier_deps_test.cc
index 6538925..5c097da 100644
--- a/compiler/verifier_deps_test.cc
+++ b/compiler/verifier_deps_test.cc
@@ -624,7 +624,7 @@
 }
 
 TEST_F(VerifierDepsTest, ConstClass_Unresolved) {
-  ASSERT_TRUE(VerifyMethod("ConstClass_Unresolved"));
+  ASSERT_FALSE(VerifyMethod("ConstClass_Unresolved"));
   ASSERT_TRUE(HasClass("LUnresolvedClass;", false));
 }
 
@@ -634,7 +634,7 @@
 }
 
 TEST_F(VerifierDepsTest, CheckCast_Unresolved) {
-  ASSERT_TRUE(VerifyMethod("CheckCast_Unresolved"));
+  ASSERT_FALSE(VerifyMethod("CheckCast_Unresolved"));
   ASSERT_TRUE(HasClass("LUnresolvedClass;", false));
 }
 
@@ -644,7 +644,7 @@
 }
 
 TEST_F(VerifierDepsTest, InstanceOf_Unresolved) {
-  ASSERT_TRUE(VerifyMethod("InstanceOf_Unresolved"));
+  ASSERT_FALSE(VerifyMethod("InstanceOf_Unresolved"));
   ASSERT_TRUE(HasClass("LUnresolvedClass;", false));
 }
 
@@ -654,12 +654,12 @@
 }
 
 TEST_F(VerifierDepsTest, NewInstance_Unresolved) {
-  ASSERT_TRUE(VerifyMethod("NewInstance_Unresolved"));
+  ASSERT_FALSE(VerifyMethod("NewInstance_Unresolved"));
   ASSERT_TRUE(HasClass("LUnresolvedClass;", false));
 }
 
 TEST_F(VerifierDepsTest, NewArray_Unresolved) {
-  ASSERT_TRUE(VerifyMethod("NewArray_Unresolved"));
+  ASSERT_FALSE(VerifyMethod("NewArray_Unresolved"));
   ASSERT_TRUE(HasClass("[LUnresolvedClass;", false));
 }
 
diff --git a/profman/profman.cc b/profman/profman.cc
index fd3bd11..d0c99e0 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -116,9 +116,9 @@
   UsageError("  --generate-test-profile=<filename>: generates a random profile file for testing.");
   UsageError("  --generate-test-profile-num-dex=<number>: number of dex files that should be");
   UsageError("      included in the generated profile. Defaults to 20.");
-  UsageError("  --generate-test-profile-method-ratio=<number>: the percentage from the maximum");
+  UsageError("  --generate-test-profile-method-percentage=<number>: the percentage from the maximum");
   UsageError("      number of methods that should be generated. Defaults to 5.");
-  UsageError("  --generate-test-profile-class-ratio=<number>: the percentage from the maximum");
+  UsageError("  --generate-test-profile-class-percentage=<number>: the percentage from the maximum");
   UsageError("      number of classes that should be generated. Defaults to 5.");
   UsageError("  --generate-test-profile-seed=<number>: seed for random number generator used when");
   UsageError("      generating random test profiles. Defaults to using NanoTime.");
@@ -151,8 +151,8 @@
 
 // Note: make sure you update the Usage if you change these values.
 static constexpr uint16_t kDefaultTestProfileNumDex = 20;
-static constexpr uint16_t kDefaultTestProfileMethodRatio = 5;
-static constexpr uint16_t kDefaultTestProfileClassRatio = 5;
+static constexpr uint16_t kDefaultTestProfileMethodPercentage = 5;
+static constexpr uint16_t kDefaultTestProfileClassPercentage = 5;
 
 // Separators used when parsing human friendly representation of profiles.
 static const std::string kMethodSep = "->";
@@ -178,8 +178,8 @@
       generate_boot_image_profile_(false),
       dump_output_to_fd_(kInvalidFd),
       test_profile_num_dex_(kDefaultTestProfileNumDex),
-      test_profile_method_ratio_(kDefaultTestProfileMethodRatio),
-      test_profile_class_ratio_(kDefaultTestProfileClassRatio),
+      test_profile_method_percerntage_(kDefaultTestProfileMethodPercentage),
+      test_profile_class_percentage_(kDefaultTestProfileClassPercentage),
       test_profile_seed_(NanoTime()),
       start_ns_(NanoTime()) {}
 
@@ -253,15 +253,15 @@
                         "--generate-test-profile-num-dex",
                         &test_profile_num_dex_,
                         Usage);
-      } else if (option.starts_with("--generate-test-profile-method-ratio")) {
+      } else if (option.starts_with("--generate-test-profile-method-percentage")) {
         ParseUintOption(option,
-                        "--generate-test-profile-method-ratio",
-                        &test_profile_method_ratio_,
+                        "--generate-test-profile-method-percentage",
+                        &test_profile_method_percerntage_,
                         Usage);
-      } else if (option.starts_with("--generate-test-profile-class-ratio")) {
+      } else if (option.starts_with("--generate-test-profile-class-percentage")) {
         ParseUintOption(option,
-                        "--generate-test-profile-class-ratio",
-                        &test_profile_class_ratio_,
+                        "--generate-test-profile-class-percentage",
+                        &test_profile_class_percentage_,
                         Usage);
       } else if (option.starts_with("--generate-test-profile-seed=")) {
         ParseUintOption(option, "--generate-test-profile-seed", &test_profile_seed_, Usage);
@@ -1014,11 +1014,11 @@
 
   int GenerateTestProfile() {
     // Validate parameters for this command.
-    if (test_profile_method_ratio_ > 100) {
-      Usage("Invalid ratio for --generate-test-profile-method-ratio");
+    if (test_profile_method_percerntage_ > 100) {
+      Usage("Invalid percentage for --generate-test-profile-method-percentage");
     }
-    if (test_profile_class_ratio_ > 100) {
-      Usage("Invalid ratio for --generate-test-profile-class-ratio");
+    if (test_profile_class_percentage_ > 100) {
+      Usage("Invalid percentage for --generate-test-profile-class-percentage");
     }
     // If given APK files or DEX locations, check that they're ok.
     if (!apk_files_.empty() || !apks_fd_.empty() || !dex_locations_.empty()) {
@@ -1039,8 +1039,8 @@
     if (apk_files_.empty() && apks_fd_.empty() && dex_locations_.empty()) {
       result = ProfileCompilationInfo::GenerateTestProfile(profile_test_fd,
                                                            test_profile_num_dex_,
-                                                           test_profile_method_ratio_,
-                                                           test_profile_class_ratio_,
+                                                           test_profile_method_percerntage_,
+                                                           test_profile_class_percentage_,
                                                            test_profile_seed_);
     } else {
       // Initialize MemMap for ZipArchive::OpenFromFd.
@@ -1051,6 +1051,8 @@
       // Create a random profile file based on the set of dex files.
       result = ProfileCompilationInfo::GenerateTestProfile(profile_test_fd,
                                                            dex_files,
+                                                           test_profile_method_percerntage_,
+                                                           test_profile_class_percentage_,
                                                            test_profile_seed_);
     }
     close(profile_test_fd);  // ignore close result.
@@ -1101,8 +1103,8 @@
   std::string test_profile_;
   std::string create_profile_from_file_;
   uint16_t test_profile_num_dex_;
-  uint16_t test_profile_method_ratio_;
-  uint16_t test_profile_class_ratio_;
+  uint16_t test_profile_method_percerntage_;
+  uint16_t test_profile_class_percentage_;
   uint32_t test_profile_seed_;
   uint64_t start_ns_;
 };
diff --git a/runtime/jit/profile_compilation_info.cc b/runtime/jit/profile_compilation_info.cc
index 78e223b..1f2163f 100644
--- a/runtime/jit/profile_compilation_info.cc
+++ b/runtime/jit/profile_compilation_info.cc
@@ -372,10 +372,6 @@
                << " bytes. Profile will not be written to disk.";
     return false;
   }
-  if (required_capacity > kProfileSizeWarningThresholdInBytes) {
-    LOG(WARNING) << "Profile data size exceeds "
-                 << std::to_string(kProfileSizeWarningThresholdInBytes);
-  }
   AddUintToBuffer(&buffer, required_capacity);
   if (!WriteBuffer(fd, buffer.data(), buffer.size())) {
     return false;
@@ -447,6 +443,11 @@
                                                                required_capacity,
                                                                &output_size);
 
+  if (output_size > kProfileSizeWarningThresholdInBytes) {
+    LOG(WARNING) << "Profile data size exceeds "
+                 << std::to_string(kProfileSizeWarningThresholdInBytes);
+  }
+
   buffer.clear();
   AddUintToBuffer(&buffer, output_size);
 
@@ -1580,16 +1581,16 @@
 // Naive implementation to generate a random profile file suitable for testing.
 bool ProfileCompilationInfo::GenerateTestProfile(int fd,
                                                  uint16_t number_of_dex_files,
-                                                 uint16_t method_ratio,
-                                                 uint16_t class_ratio,
+                                                 uint16_t method_percentage,
+                                                 uint16_t class_percentage,
                                                  uint32_t random_seed) {
   const std::string base_dex_location = "base.apk";
   ProfileCompilationInfo info;
   // The limits are defined by the dex specification.
   const uint16_t max_method = std::numeric_limits<uint16_t>::max();
   const uint16_t max_classes = std::numeric_limits<uint16_t>::max();
-  uint16_t number_of_methods = max_method * method_ratio / 100;
-  uint16_t number_of_classes = max_classes * class_ratio / 100;
+  uint16_t number_of_methods = max_method * method_percentage / 100;
+  uint16_t number_of_classes = max_classes * class_percentage / 100;
 
   std::srand(random_seed);
 
@@ -1626,28 +1627,47 @@
 }
 
 // Naive implementation to generate a random profile file suitable for testing.
+// Description of random selection:
+// * Select a random starting point S.
+// * For every index i, add (S+i) % (N - total number of methods/classes) to profile with the
+//   probably of 1/(N - i - number of methods/classes needed to add in profile).
 bool ProfileCompilationInfo::GenerateTestProfile(
     int fd,
     std::vector<std::unique_ptr<const DexFile>>& dex_files,
+    uint16_t method_percentage,
+    uint16_t class_percentage,
     uint32_t random_seed) {
   std::srand(random_seed);
   ProfileCompilationInfo info;
   for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
     const std::string& location = dex_file->GetLocation();
     uint32_t checksum = dex_file->GetLocationChecksum();
-    for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) {
-      // Randomly add a class from the dex file (with 50% chance).
-      if (std::rand() % 2 != 0) {
+
+    uint32_t number_of_classes = dex_file->NumClassDefs();
+    uint32_t classes_required_in_profile = (number_of_classes * class_percentage) / 100;
+    uint32_t class_start_index = rand() % number_of_classes;
+    for (uint32_t i = 0; i < number_of_classes && classes_required_in_profile; ++i) {
+      if (number_of_classes - i == classes_required_in_profile ||
+          std::rand() % (number_of_classes - i - classes_required_in_profile) == 0) {
+        uint32_t class_index = (i + class_start_index) % number_of_classes;
         info.AddClassIndex(location,
                            checksum,
-                           dex_file->GetClassDef(i).class_idx_,
+                           dex_file->GetClassDef(class_index).class_idx_,
                            dex_file->NumMethodIds());
+        classes_required_in_profile--;
       }
     }
-    for (uint32_t i = 0; i < dex_file->NumMethodIds(); ++i) {
-      // Randomly add a method from the dex file (with 50% chance).
-      if (std::rand() % 2 != 0) {
-        info.AddMethodIndex(MethodHotness::kFlagHot, MethodReference(dex_file.get(), i));
+
+    uint32_t number_of_methods = dex_file->NumMethodIds();
+    uint32_t methods_required_in_profile = (number_of_methods * method_percentage) / 100;
+    uint32_t method_start_index = rand() % number_of_methods;
+    for (uint32_t i = 0; i < number_of_methods && methods_required_in_profile; ++i) {
+      if (number_of_methods - i == methods_required_in_profile ||
+          std::rand() % (number_of_methods - i - methods_required_in_profile) == 0) {
+        uint32_t method_index = (method_start_index + i) % number_of_methods;
+        info.AddMethodIndex(MethodHotness::kFlagHot, MethodReference(dex_file.get(),
+                                                                     method_index));
+        methods_required_in_profile--;
       }
     }
   }
diff --git a/runtime/jit/profile_compilation_info.h b/runtime/jit/profile_compilation_info.h
index d38237d..7fd7a2d 100644
--- a/runtime/jit/profile_compilation_info.h
+++ b/runtime/jit/profile_compilation_info.h
@@ -376,6 +376,8 @@
   // the provided list of dex files.
   static bool GenerateTestProfile(int fd,
                                   std::vector<std::unique_ptr<const DexFile>>& dex_files,
+                                  uint16_t method_percentage,
+                                  uint16_t class_percentage,
                                   uint32_t random_seed);
 
   // Check that the given profile method info contain the same data.
diff --git a/runtime/verifier/method_verifier-inl.h b/runtime/verifier/method_verifier-inl.h
index 6c832e3..9bb875c 100644
--- a/runtime/verifier/method_verifier-inl.h
+++ b/runtime/verifier/method_verifier-inl.h
@@ -77,7 +77,7 @@
 
 inline const RegType& MethodVerifier::ResolveCheckedClass(dex::TypeIndex class_idx) {
   DCHECK(!HasFailures());
-  const RegType& result = ResolveClassAndCheckAccess(class_idx);
+  const RegType& result = ResolveClass<CheckAccess::kYes>(class_idx);
   DCHECK(!HasFailures());
   return result;
 }
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 312d8df..9a87607 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -1765,7 +1765,9 @@
         // it's effectively considered initialized the instant we reach here (in the sense that we
         // can return without doing anything or call virtual methods).
         {
-          const RegType& reg_type = ResolveClassAndCheckAccess(iterator.GetTypeIdx());
+          // Note: don't check access. No error would be thrown for declaring or passing an
+          //       inaccessible class. Only actual accesses to fields or methods will.
+          const RegType& reg_type = ResolveClass<CheckAccess::kNo>(iterator.GetTypeIdx());
           if (!reg_type.IsNonZeroReferenceTypes()) {
             DCHECK(HasFailures());
             return false;
@@ -2322,7 +2324,7 @@
     case Instruction::CONST_CLASS: {
       // Get type from instruction if unresolved then we need an access check
       // TODO: check Compiler::CanAccessTypeWithoutChecks returns false when res_type is unresolved
-      const RegType& res_type = ResolveClassAndCheckAccess(dex::TypeIndex(inst->VRegB_21c()));
+      const RegType& res_type = ResolveClass<CheckAccess::kYes>(dex::TypeIndex(inst->VRegB_21c()));
       // Register holds class, ie its type is class, on error it will hold Conflict.
       work_line_->SetRegisterType<LockOp::kClear>(
           this, inst->VRegA_21c(), res_type.IsConflict() ? res_type
@@ -2393,7 +2395,7 @@
        */
       const bool is_checkcast = (inst->Opcode() == Instruction::CHECK_CAST);
       const dex::TypeIndex type_idx((is_checkcast) ? inst->VRegB_21c() : inst->VRegC_22c());
-      const RegType& res_type = ResolveClassAndCheckAccess(type_idx);
+      const RegType& res_type = ResolveClass<CheckAccess::kYes>(type_idx);
       if (res_type.IsConflict()) {
         // If this is a primitive type, fail HARD.
         ObjPtr<mirror::Class> klass =
@@ -2463,7 +2465,7 @@
       break;
     }
     case Instruction::NEW_INSTANCE: {
-      const RegType& res_type = ResolveClassAndCheckAccess(dex::TypeIndex(inst->VRegB_21c()));
+      const RegType& res_type = ResolveClass<CheckAccess::kYes>(dex::TypeIndex(inst->VRegB_21c()));
       if (res_type.IsConflict()) {
         DCHECK_NE(failures_.size(), 0U);
         break;  // bad class
@@ -2675,7 +2677,7 @@
         // ensure that subsequent merges don't lose type information - such as becoming an
         // interface from a class that would lose information relevant to field checks.
         const RegType& orig_type = work_line_->GetRegisterType(this, instance_of_inst->VRegB_22c());
-        const RegType& cast_type = ResolveClassAndCheckAccess(
+        const RegType& cast_type = ResolveClass<CheckAccess::kYes>(
             dex::TypeIndex(instance_of_inst->VRegC_22c()));
 
         if (!orig_type.Equals(cast_type) &&
@@ -3723,7 +3725,8 @@
   return klass->IsInstantiable() || klass->IsPrimitive();
 }
 
-const RegType& MethodVerifier::ResolveClassAndCheckAccess(dex::TypeIndex class_idx) {
+template <MethodVerifier::CheckAccess C>
+const RegType& MethodVerifier::ResolveClass(dex::TypeIndex class_idx) {
   mirror::Class* klass = can_load_classes_
       ? Runtime::Current()->GetClassLinker()->ResolveType(
           *dex_file_, class_idx, dex_cache_, class_loader_)
@@ -3760,13 +3763,15 @@
   // Record result of class resolution attempt.
   VerifierDeps::MaybeRecordClassResolution(*dex_file_, class_idx, klass);
 
-  // Check if access is allowed. Unresolved types use xxxWithAccessCheck to
-  // check at runtime if access is allowed and so pass here. If result is
-  // primitive, skip the access check.
-  if (result->IsNonZeroReferenceTypes() && !result->IsUnresolvedTypes()) {
+  // If requested, check if access is allowed. Unresolved types are included in this check, as the
+  // interpreter only tests whether access is allowed when a class is not pre-verified and runs in
+  // the access-checks interpreter. If result is primitive, skip the access check.
+  //
+  // Note: we do this for unresolved classes to trigger re-verification at runtime.
+  if (C == CheckAccess::kYes && result->IsNonZeroReferenceTypes()) {
     const RegType& referrer = GetDeclaringClass();
-    if (!referrer.IsUnresolvedTypes() && !referrer.CanAccess(*result)) {
-      Fail(VERIFY_ERROR_ACCESS_CLASS) << "illegal class access: '"
+    if (!referrer.CanAccess(*result)) {
+      Fail(VERIFY_ERROR_ACCESS_CLASS) << "(possibly) illegal class access: '"
                                       << referrer << "' -> '" << *result << "'";
     }
   }
@@ -3785,7 +3790,8 @@
           if (!iterator.GetHandlerTypeIndex().IsValid()) {
             common_super = &reg_types_.JavaLangThrowable(false);
           } else {
-            const RegType& exception = ResolveClassAndCheckAccess(iterator.GetHandlerTypeIndex());
+            const RegType& exception =
+                ResolveClass<CheckAccess::kYes>(iterator.GetHandlerTypeIndex());
             if (!reg_types_.JavaLangThrowable(false).IsAssignableFrom(exception, this)) {
               DCHECK(!exception.IsUninitializedTypes());  // Comes from dex, shouldn't be uninit.
               if (exception.IsUnresolvedTypes()) {
@@ -3827,7 +3833,7 @@
 ArtMethod* MethodVerifier::ResolveMethodAndCheckAccess(
     uint32_t dex_method_idx, MethodType method_type) {
   const DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx);
-  const RegType& klass_type = ResolveClassAndCheckAccess(method_id.class_idx_);
+  const RegType& klass_type = ResolveClass<CheckAccess::kYes>(method_id.class_idx_);
   if (klass_type.IsConflict()) {
     std::string append(" in attempt to access method ");
     append += dex_file_->GetMethodName(method_id);
@@ -4598,7 +4604,7 @@
     DCHECK_EQ(inst->Opcode(), Instruction::FILLED_NEW_ARRAY_RANGE);
     type_idx = dex::TypeIndex(inst->VRegB_3rc());
   }
-  const RegType& res_type = ResolveClassAndCheckAccess(type_idx);
+  const RegType& res_type = ResolveClass<CheckAccess::kYes>(type_idx);
   if (res_type.IsConflict()) {  // bad class
     DCHECK_NE(failures_.size(), 0U);
   } else {
@@ -4812,7 +4818,7 @@
 ArtField* MethodVerifier::GetStaticField(int field_idx) {
   const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
   // Check access to class
-  const RegType& klass_type = ResolveClassAndCheckAccess(field_id.class_idx_);
+  const RegType& klass_type = ResolveClass<CheckAccess::kYes>(field_id.class_idx_);
   if (klass_type.IsConflict()) {  // bad class
     AppendToLastFailMessage(StringPrintf(" in attempt to access static field %d (%s) in %s",
                                          field_idx, dex_file_->GetFieldName(field_id),
@@ -4820,6 +4826,9 @@
     return nullptr;
   }
   if (klass_type.IsUnresolvedTypes()) {
+    // Accessibility checks depend on resolved fields.
+    DCHECK(klass_type.Equals(GetDeclaringClass()) || !failures_.empty());
+
     return nullptr;  // Can't resolve Class so no more to do here, will do checking at runtime.
   }
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
@@ -4850,7 +4859,7 @@
 ArtField* MethodVerifier::GetInstanceField(const RegType& obj_type, int field_idx) {
   const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
   // Check access to class.
-  const RegType& klass_type = ResolveClassAndCheckAccess(field_id.class_idx_);
+  const RegType& klass_type = ResolveClass<CheckAccess::kYes>(field_id.class_idx_);
   if (klass_type.IsConflict()) {
     AppendToLastFailMessage(StringPrintf(" in attempt to access instance field %d (%s) in %s",
                                          field_idx, dex_file_->GetFieldName(field_id),
@@ -4858,6 +4867,9 @@
     return nullptr;
   }
   if (klass_type.IsUnresolvedTypes()) {
+    // Accessibility checks depend on resolved fields.
+    DCHECK(klass_type.Equals(GetDeclaringClass()) || !failures_.empty());
+
     return nullptr;  // Can't resolve Class so no more to do here
   }
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
@@ -4994,6 +5006,31 @@
       DCHECK(!can_load_classes_ || self_->IsExceptionPending());
       self_->ClearException();
     }
+  } else {
+    // If we don't have the field (it seems we failed resolution) and this is a PUT, we need to
+    // redo verification at runtime as the field may be final, unless the field id shows it's in
+    // the same class.
+    //
+    // For simplicity, it is OK to not distinguish compile-time vs runtime, and post this an
+    // ACCESS_FIELD failure at runtime. This has the same effect as NO_FIELD - punting the class
+    // to the access-checks interpreter.
+    //
+    // Note: see b/34966607. This and above may be changed in the future.
+    if (kAccType == FieldAccessType::kAccPut) {
+      const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
+      const char* field_class_descriptor = dex_file_->GetFieldDeclaringClassDescriptor(field_id);
+      const RegType* field_class_type = &reg_types_.FromDescriptor(GetClassLoader(),
+                                                                   field_class_descriptor,
+                                                                   false);
+      if (!field_class_type->Equals(GetDeclaringClass())) {
+        Fail(VERIFY_ERROR_ACCESS_FIELD) << "could not check field put for final field modify of "
+                                        << field_class_descriptor
+                                        << "."
+                                        << dex_file_->GetFieldName(field_id)
+                                        << " from other class "
+                                        << GetDeclaringClass();
+      }
+    }
   }
   if (field_type == nullptr) {
     const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index ea8729c..da4102a 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -576,9 +576,14 @@
   void VerifyQuickFieldAccess(const Instruction* inst, const RegType& insn_type, bool is_primitive)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  // Resolves a class based on an index and performs access checks to ensure the referrer can
-  // access the resolved class.
-  const RegType& ResolveClassAndCheckAccess(dex::TypeIndex class_idx)
+  enum class CheckAccess {  // private.
+    kYes,
+    kNo,
+  };
+  // Resolves a class based on an index and, if C is kYes, performs access checks to ensure
+  // the referrer can access the resolved class.
+  template <CheckAccess C>
+  const RegType& ResolveClass(dex::TypeIndex class_idx)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   /*
diff --git a/test/1923-frame-pop/src/art/Test1923.java b/test/1923-frame-pop/src/art/Test1923.java
index b5265b7..6f41540 100644
--- a/test/1923-frame-pop/src/art/Test1923.java
+++ b/test/1923-frame-pop/src/art/Test1923.java
@@ -157,14 +157,19 @@
   public static void doRecurTestWith(final int times, int watch_frame) throws Exception {
     final String target_method_name_start = "recurTimes";
     final ThreadPauser safepoint = new ThreadPauser();
-    Thread target = new Thread(() -> {
-      try {
-        recurTimesA(times, safepoint);
-        System.out.println("Ran recurTimes(" + times + ") without errors!");
-      } catch (RecursionError e) {
-        System.out.println("Caught exception " + e + " while running recurTimes(" + times + ")");
-      }
-    });
+    Thread target = new Thread(
+        null,
+        () -> {
+          try {
+            recurTimesA(times, safepoint);
+            System.out.println("Ran recurTimes(" + times + ") without errors!");
+          } catch (RecursionError e) {
+            System.out.println("Caught exception " + e + " while running recurTimes(" + times + ")");
+          }
+        },
+        "RecurTimes(" + times + ") watching: " + watch_frame + " runner.",
+        // 4000 kb stack since ASAN can make us stack-overflow otherwise
+        4000 * 1024);
     target.start();
     safepoint.waitForOtherThreadToPause();
     Suspension.suspend(target);
diff --git a/test/1924-frame-pop-toggle/src/art/Test1924.java b/test/1924-frame-pop-toggle/src/art/Test1924.java
index 0ffbfc6..f0bb68c 100644
--- a/test/1924-frame-pop-toggle/src/art/Test1924.java
+++ b/test/1924-frame-pop-toggle/src/art/Test1924.java
@@ -157,14 +157,18 @@
   public static void doRecurTestWith(final int times, int watch_frame) throws Exception {
     final String target_method_name_start = "recurTimes";
     final ThreadPauser safepoint = new ThreadPauser();
-    Thread target = new Thread(() -> {
-      try {
-        recurTimesA(times, safepoint);
-        System.out.println("Ran recurTimes(" + times + ") without errors!");
-      } catch (RecursionError e) {
-        System.out.println("Caught exception " + e + " while running recurTimes(" + times + ")");
-      }
-    });
+    Thread target = new Thread(null,
+        () -> {
+          try {
+            recurTimesA(times, safepoint);
+            System.out.println("Ran recurTimes(" + times + ") without errors!");
+          } catch (RecursionError e) {
+            System.out.println("Caught exception " + e + " while running recurTimes(" + times + ")");
+          }
+        },
+        "RecurTimes(" + times + ") watching: " + watch_frame + " runner.",
+        // 4000 kb stack since ASAN can make us stack-overflow otherwise
+        4000 * 1024);
     target.start();
     safepoint.waitForOtherThreadToPause();
     Suspension.suspend(target);
diff --git a/test/620-checker-bce-intrinsics/src/Main.java b/test/620-checker-bce-intrinsics/src/Main.java
index afc3c65..e0b5986 100644
--- a/test/620-checker-bce-intrinsics/src/Main.java
+++ b/test/620-checker-bce-intrinsics/src/Main.java
@@ -34,15 +34,15 @@
     return x;
   }
 
-  /// CHECK-START: int Main.oneArrayAbs(int[], int) BCE (before)
+  /// CHECK-START: int Main.oneArrayAbs(int[], int[]) BCE (before)
   /// CHECK-DAG: BoundsCheck loop:<<Loop:B\d+>> outer_loop:none
   //
-  /// CHECK-START: int Main.oneArrayAbs(int[], int) BCE (after)
+  /// CHECK-START: int Main.oneArrayAbs(int[], int[]) BCE (after)
   /// CHECK-NOT: BoundsCheck
   /// CHECK-NOT: Deoptimize
-  static int oneArrayAbs(int[] a, int lo) {
+  static int oneArrayAbs(int[] a, int[] b) {
     int x = 0;
-    for (int i = Math.abs(lo); i < a.length; i++) {
+    for (int i = Math.abs(b.length); i < a.length; i++) {
       x += a[i];
     }
     return x;
@@ -221,15 +221,15 @@
     int[] b = { 6, 7, 8, 9, 4, 2 };
     int[] c = { 1, 2, 3 };
     int[] d = { 8, 5, 3, 2 };
+    int[] e = { };
 
     expectEquals(15, oneArray(a));
     expectEquals(36, oneArray(b));
     expectEquals(6,  oneArray(c));
     expectEquals(18, oneArray(d));
 
-    expectEquals(5,  oneArrayAbs(a, -4));
-    expectEquals(15, oneArrayAbs(a, 0));
-    expectEquals(5,  oneArrayAbs(a, 4));
+    expectEquals(15, oneArrayAbs(a, e));
+    expectEquals(5,  oneArrayAbs(a, d));
 
     expectEquals(30, twoArrays(a, a));
     expectEquals(49, twoArrays(a, b));
diff --git a/test/623-checker-loop-regressions/src/Main.java b/test/623-checker-loop-regressions/src/Main.java
index 0e85612..056ed91 100644
--- a/test/623-checker-loop-regressions/src/Main.java
+++ b/test/623-checker-loop-regressions/src/Main.java
@@ -464,6 +464,15 @@
     return r;
   }
 
+  static int absCanBeNegative(int x) {
+    int a[] = { 1, 2, 3 };
+    int y = 0;
+    for (int i = Math.abs(x); i < a.length; i++) {
+      y += a[i];
+    }
+    return y;
+  }
+
   public static void main(String[] args) {
     expectEquals(10, earlyExitFirst(-1));
     for (int i = 0; i <= 10; i++) {
@@ -586,6 +595,24 @@
       expectEquals(11, f[i]);
     }
 
+    expectEquals(0, absCanBeNegative(-3));
+    expectEquals(3, absCanBeNegative(-2));
+    expectEquals(5, absCanBeNegative(-1));
+    expectEquals(6, absCanBeNegative(0));
+    expectEquals(5, absCanBeNegative(1));
+    expectEquals(3, absCanBeNegative(2));
+    expectEquals(0, absCanBeNegative(3));
+    expectEquals(0, absCanBeNegative(Integer.MAX_VALUE));
+    // Abs(min_int) = min_int.
+    int verify = 0;
+    try {
+      absCanBeNegative(Integer.MIN_VALUE);
+      verify = 1;
+    } catch (ArrayIndexOutOfBoundsException e) {
+      verify = 2;
+    }
+    expectEquals(2, verify);
+
     System.out.println("passed");
   }
 
diff --git a/test/661-checker-simd-reduc/src/Main.java b/test/661-checker-simd-reduc/src/Main.java
index 8208a9e..741b5fa 100644
--- a/test/661-checker-simd-reduc/src/Main.java
+++ b/test/661-checker-simd-reduc/src/Main.java
@@ -51,26 +51,6 @@
     return sum;
   }
 
-  /// CHECK-START: int Main.reductionInt(int[]) loop_optimization (before)
-  /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
-  /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
-  //
-  /// CHECK-START-ARM64: int Main.reductionInt(int[]) loop_optimization (after)
-  /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
-  /// CHECK-DAG: <<Cons4:i\d+>>  IntConstant 4                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]     loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]        loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]   loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 VecAdd [<<Phi2>>,<<Load>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons4>>]      loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi2>>]          loop:none
-  /// CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
   private static int reductionInt(int[] x) {
     int sum = 0;
     for (int i = 0; i < x.length; i++) {
@@ -79,28 +59,6 @@
     return sum;
   }
 
-  /// CHECK-START: long Main.reductionLong(long[]) loop_optimization (before)
-  /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
-  /// CHECK-DAG: <<Long0:j\d+>>  LongConstant 0                loop:none
-  /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:j\d+>>   Phi [<<Long0>>,{{j\d+}}]      loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Get:j\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
-  //
-  /// CHECK-START-ARM64: long Main.reductionLong(long[]) loop_optimization (after)
-  /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
-  /// CHECK-DAG: <<Long0:j\d+>>  LongConstant 0                loop:none
-  /// CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Long0>>]     loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]        loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]   loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 VecAdd [<<Phi2>>,<<Load>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons2>>]      loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi2>>]          loop:none
-  /// CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>]    loop:none
   private static long reductionLong(long[] x) {
     long sum = 0;
     for (int i = 0; i < x.length; i++) {
@@ -109,90 +67,6 @@
     return sum;
   }
 
-  private static byte reductionByteM1(byte[] x) {
-    byte sum = -1;
-    for (int i = 0; i < x.length; i++) {
-      sum += x[i];
-    }
-    return sum;
-  }
-
-  private static short reductionShortM1(short[] x) {
-    short sum = -1;
-    for (int i = 0; i < x.length; i++) {
-      sum += x[i];
-    }
-    return sum;
-  }
-
-  private static char reductionCharM1(char[] x) {
-    char sum = 0xffff;
-    for (int i = 0; i < x.length; i++) {
-      sum += x[i];
-    }
-    return sum;
-  }
-
-  /// CHECK-START: int Main.reductionIntM1(int[]) loop_optimization (before)
-  /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
-  /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
-  /// CHECK-DAG: <<ConsM1:i\d+>> IntConstant -1                loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<ConsM1>>,{{i\d+}}]     loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
-  //
-  /// CHECK-START-ARM64: int Main.reductionIntM1(int[]) loop_optimization (after)
-  /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
-  /// CHECK-DAG: <<ConsM1:i\d+>> IntConstant -1                loop:none
-  /// CHECK-DAG: <<Cons4:i\d+>>  IntConstant 4                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsM1>>]    loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]        loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]   loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 VecAdd [<<Phi2>>,<<Load>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons4>>]      loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi2>>]          loop:none
-  /// CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
-  private static int reductionIntM1(int[] x) {
-    int sum = -1;
-    for (int i = 0; i < x.length; i++) {
-      sum += x[i];
-    }
-    return sum;
-  }
-
-  /// CHECK-START: long Main.reductionLongM1(long[]) loop_optimization (before)
-  /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
-  /// CHECK-DAG: <<LongM1:j\d+>> LongConstant -1               loop:none
-  /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:j\d+>>   Phi [<<LongM1>>,{{j\d+}}]     loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Get:j\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
-  //
-  /// CHECK-START-ARM64: long Main.reductionLongM1(long[]) loop_optimization (after)
-  /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
-  /// CHECK-DAG: <<LongM1:j\d+>> LongConstant -1               loop:none
-  /// CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<LongM1>>]    loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]        loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]   loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 VecAdd [<<Phi2>>,<<Load>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons2>>]      loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi2>>]          loop:none
-  /// CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>]    loop:none
-  private static long reductionLongM1(long[] x) {
-    long sum = -1L;
-    for (int i = 0; i < x.length; i++) {
-      sum += x[i];
-    }
-    return sum;
-  }
-
   private static byte reductionMinusByte(byte[] x) {
     byte sum = 0;
     for (int i = 0; i < x.length; i++) {
@@ -217,26 +91,6 @@
     return sum;
   }
 
-  /// CHECK-START: int Main.reductionMinusInt(int[]) loop_optimization (before)
-  /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
-  /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Sub [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
-  //
-  /// CHECK-START-ARM64: int Main.reductionMinusInt(int[]) loop_optimization (after)
-  /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
-  /// CHECK-DAG: <<Cons4:i\d+>>  IntConstant 4                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]     loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]        loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]   loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 VecSub [<<Phi2>>,<<Load>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons4>>]      loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi2>>]          loop:none
-  /// CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
   private static int reductionMinusInt(int[] x) {
     int sum = 0;
     for (int i = 0; i < x.length; i++) {
@@ -245,28 +99,6 @@
     return sum;
   }
 
-  /// CHECK-START: long Main.reductionMinusLong(long[]) loop_optimization (before)
-  /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
-  /// CHECK-DAG: <<Long0:j\d+>>  LongConstant 0                loop:none
-  /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:j\d+>>   Phi [<<Long0>>,{{j\d+}}]      loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Get:j\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Sub [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
-  //
-  /// CHECK-START-ARM64: long Main.reductionMinusLong(long[]) loop_optimization (after)
-  /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
-  /// CHECK-DAG: <<Long0:j\d+>>  LongConstant 0                loop:none
-  /// CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Long0>>]     loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]        loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]   loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 VecSub [<<Phi2>>,<<Load>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons2>>]      loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi2>>]          loop:none
-  /// CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>]    loop:none
   private static long reductionMinusLong(long[] x) {
     long sum = 0;
     for (int i = 0; i < x.length; i++) {
@@ -299,28 +131,6 @@
     return min;
   }
 
-  /// CHECK-START: int Main.reductionMinInt(int[]) loop_optimization (before)
-  /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
-  /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
-  /// CHECK-DAG: <<ConsM:i\d+>>  IntConstant 2147483647        loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<ConsM>>,{{i\d+}}]      loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 InvokeStaticOrDirect [<<Phi2>>,<<Get>>] intrinsic:MathMinIntInt loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
-  //
-  /// CHECK-START-ARM64: int Main.reductionMinInt(int[]) loop_optimization (after)
-  /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
-  /// CHECK-DAG: <<ConsM:i\d+>>  IntConstant 2147483647        loop:none
-  /// CHECK-DAG: <<Cons4:i\d+>>  IntConstant 4                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsM>>]     loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]        loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]   loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 VecMin [<<Phi2>>,<<Load>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons4>>]      loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi2>>]          loop:none
-  /// CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
   private static int reductionMinInt(int[] x) {
     int min = Integer.MAX_VALUE;
     for (int i = 0; i < x.length; i++) {
@@ -361,28 +171,6 @@
     return max;
   }
 
-  /// CHECK-START: int Main.reductionMaxInt(int[]) loop_optimization (before)
-  /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
-  /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
-  /// CHECK-DAG: <<ConsM:i\d+>>  IntConstant -2147483648       loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<ConsM>>,{{i\d+}}]      loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 InvokeStaticOrDirect [<<Phi2>>,<<Get>>] intrinsic:MathMaxIntInt loop:<<Loop>> outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
-  //
-  /// CHECK-START-ARM64: int Main.reductionMaxInt(int[]) loop_optimization (after)
-  /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
-  /// CHECK-DAG: <<ConsM:i\d+>>  IntConstant -2147483648       loop:none
-  /// CHECK-DAG: <<Cons4:i\d+>>  IntConstant 4                 loop:none
-  /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsM>>]     loop:none
-  /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
-  /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]        loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<Phi1>>]   loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 VecMax [<<Phi2>>,<<Load>>]    loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons4>>]      loop:<<Loop>>      outer_loop:none
-  /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi2>>]          loop:none
-  /// CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
   private static int reductionMaxInt(int[] x) {
     int max = Integer.MIN_VALUE;
     for (int i = 0; i < x.length; i++) {
@@ -465,11 +253,6 @@
     expectEquals(38070, reductionChar(xc));
     expectEquals(365750, reductionInt(xi));
     expectEquals(365750L, reductionLong(xl));
-    expectEquals(-75, reductionByteM1(xb));
-    expectEquals(-27467, reductionShortM1(xs));
-    expectEquals(38069, reductionCharM1(xc));
-    expectEquals(365749, reductionIntM1(xi));
-    expectEquals(365749L, reductionLongM1(xl));
     expectEquals(74, reductionMinusByte(xb));
     expectEquals(27466, reductionMinusShort(xs));
     expectEquals(27466, reductionMinusChar(xc));
diff --git a/test/954-invoke-polymorphic-verifier/smali/Unresolved.smali b/test/954-invoke-polymorphic-verifier/smali/Unresolved.smali
index 882f0e9..2604472 100644
--- a/test/954-invoke-polymorphic-verifier/smali/Unresolved.smali
+++ b/test/954-invoke-polymorphic-verifier/smali/Unresolved.smali
@@ -23,7 +23,7 @@
 .line 23
   invoke-direct {p0}, Ljava/lang/Object;-><init>()V
   # Get an unresolvable instance (abstract class)
-  invoke-static {}, LAbstract;->getUnresolvedInstance()Lother/thing/Foo;
+  invoke-static {}, LUnresolved;->getUnresolvedInstance()Lother/thing/Foo;
   move-result-object v0
   const-string v1, "1"
   const-string v2, "2"
diff --git a/test/knownfailures.json b/test/knownfailures.json
index df7544e..20cfc34 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -681,16 +681,6 @@
         "env_vars": {"SANITIZE_HOST": "address"}
     },
     {
-        "tests": [
-            "1923-frame-pop",
-            "1924-frame-pop-toggle"
-        ],
-        "description": "ASAN seems to make these tests overflow their stacks.",
-        "variant": "64",
-        "bug": "b/65189092",
-        "env_vars": {"SANITIZE_HOST": "address"}
-    },
-    {
         "tests": ["988-method-trace"],
         "variant": "redefine-stress | jvmti-stress",
         "description": "Test disabled due to redefine-stress disabling intrinsics which changes the trace output slightly."