Version 2.19.0-60.0.dev

Merge commit 'd94a1cd419d8d644516336f9bbeae2e751ecdbf1' into 'dev'
diff --git a/runtime/tests/vm/dart/causal_stacks/utils.dart b/runtime/tests/vm/dart/causal_stacks/utils.dart
index 2269e31..4356953 100644
--- a/runtime/tests/vm/dart/causal_stacks/utils.dart
+++ b/runtime/tests/vm/dart/causal_stacks/utils.dart
@@ -205,21 +205,26 @@
 
   // Use the DWARF stack decoder if we're running in --dwarf-stack-traces mode
   // and in precompiled mode (otherwise --dwarf-stack-traces has no effect).
-  final decodeTrace = frames.first.startsWith('Warning:');
-  if (decodeTrace) {
-    Expect.isNotNull(debugInfoFilename);
-    final dwarf = Dwarf.fromFile(debugInfoFilename!)!;
-    frames = await Stream.fromIterable(original)
-        .transform(DwarfStackTraceDecoder(dwarf))
-        .where(_lineRE.hasMatch)
-        .toList();
+  bool usingDwarf = false;
+  if (debugInfoFilename != null) {
+    try {
+      final dwarf = Dwarf.fromFile(debugInfoFilename)!;
+      usingDwarf = true;
+      frames = await Stream.fromIterable(original)
+          .transform(DwarfStackTraceDecoder(dwarf))
+          .where(_lineRE.hasMatch)
+          .toList();
+    } on FileSystemException {
+      // We're not running in precompiled mode, so the file doesn't exist and
+      // we can continue normally.
+    }
   }
 
   void printFrameInformation() {
     print('RegExps for expected stack:');
     expects.forEach((s) => print('"${s}"'));
     print('');
-    if (decodeTrace) {
+    if (usingDwarf) {
       print('Non-symbolic actual stack:');
       original.forEach(print);
       print('');
diff --git a/runtime/tests/vm/dart_2/causal_stacks/utils.dart b/runtime/tests/vm/dart_2/causal_stacks/utils.dart
index d7c80d1..ec673b5 100644
--- a/runtime/tests/vm/dart_2/causal_stacks/utils.dart
+++ b/runtime/tests/vm/dart_2/causal_stacks/utils.dart
@@ -207,21 +207,26 @@
 
   // Use the DWARF stack decoder if we're running in --dwarf-stack-traces mode
   // and in precompiled mode (otherwise --dwarf-stack-traces has no effect).
-  final decodeTrace = frames.first.startsWith('Warning:');
-  if (decodeTrace) {
-    Expect.isNotNull(debugInfoFilename);
-    final dwarf = Dwarf.fromFile(debugInfoFilename);
-    frames = await Stream.fromIterable(original)
-        .transform(DwarfStackTraceDecoder(dwarf))
-        .where(_lineRE.hasMatch)
-        .toList();
+  bool usingDwarf = false;
+  if (debugInfoFilename != null) {
+    try {
+      final dwarf = Dwarf.fromFile(debugInfoFilename);
+      usingDwarf = true;
+      frames = await Stream.fromIterable(original)
+          .transform(DwarfStackTraceDecoder(dwarf))
+          .where(_lineRE.hasMatch)
+          .toList();
+    } on FileSystemException {
+      // We're not running in precompiled mode, so the file doesn't exist and
+      // we can continue normally.
+    }
   }
 
   void printFrameInformation() {
     print('RegExps for expected stack:');
     expects.forEach((s) => print('"${s}"'));
     print('');
-    if (decodeTrace) {
+    if (usingDwarf) {
       print('Non-symbolic actual stack:');
       original.forEach(print);
       print('');
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index 02122a3..64576491 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -662,20 +662,6 @@
   }
 }
 
-void Assembler::LoadSImmediate(VRegister vd, float imms) {
-  int32_t imm32 = bit_cast<int32_t, float>(imms);
-  if (imm32 == 0) {
-    veor(vd, vd, vd);
-  } else if (constant_pool_allowed()) {
-    intptr_t index = object_pool_builder().FindImmediate(imm32);
-    intptr_t offset = target::ObjectPool::element_offset(index);
-    LoadSFromOffset(vd, PP, offset);
-  } else {
-    LoadImmediate(TMP, imm32);
-    fmovsr(vd, TMP);
-  }
-}
-
 void Assembler::LoadDImmediate(VRegister vd, double immd) {
   if (fmovdi(vd, immd)) return;
 
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index 56b0fda..ea47f52 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -2066,7 +2066,6 @@
     LoadImmediate(reg, imm.value());
   }
 
-  void LoadSImmediate(VRegister reg, float immd);
   void LoadDImmediate(VRegister reg, double immd);
   void LoadQImmediate(VRegister reg, simd128_value_t immq);
 
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index 73d84a5..51c1fa9 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -2199,13 +2199,6 @@
   addl(dest, inc_imm);
 }
 
-void Assembler::LoadSImmediate(XmmRegister dst, float value) {
-  int32_t constant = bit_cast<int32_t, float>(value);
-  pushl(Immediate(constant));
-  movss(dst, Address(ESP, 0));
-  addl(ESP, Immediate(target::kWordSize));
-}
-
 void Assembler::LoadDImmediate(XmmRegister dst, double value) {
   // TODO(5410843): Need to have a code constants table.
   int64_t constant = bit_cast<int64_t, double>(value);
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h
index 77b453b..7ef5339 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.h
+++ b/runtime/vm/compiler/assembler/assembler_ia32.h
@@ -759,7 +759,6 @@
     LoadImmediate(reg, immediate.value());
   }
 
-  void LoadSImmediate(XmmRegister dst, float value);
   void LoadDImmediate(XmmRegister dst, double value);
 
   void Drop(intptr_t stack_elements);
diff --git a/runtime/vm/compiler/assembler/assembler_riscv.cc b/runtime/vm/compiler/assembler/assembler_riscv.cc
index 08a4b28..10beeac 100644
--- a/runtime/vm/compiler/assembler/assembler_riscv.cc
+++ b/runtime/vm/compiler/assembler/assembler_riscv.cc
@@ -3351,18 +3351,6 @@
   }
 }
 
-void Assembler::LoadSImmediate(FRegister reg, float imms) {
-  int32_t imm = bit_cast<int32_t, float>(imms);
-  if (imm == 0) {
-    fmvwx(reg, ZR);  // bit_cast uint32_t -> float
-  } else {
-    ASSERT(constant_pool_allowed());
-    intptr_t index = object_pool_builder().FindImmediate(imm);
-    intptr_t offset = target::ObjectPool::element_offset(index);
-    LoadSFromOffset(reg, PP, offset);
-  }
-}
-
 void Assembler::LoadDImmediate(FRegister reg, double immd) {
   int64_t imm = bit_cast<int64_t, double>(immd);
   if (imm == 0) {
diff --git a/runtime/vm/compiler/assembler/assembler_riscv.h b/runtime/vm/compiler/assembler/assembler_riscv.h
index 18eeb4a..cefa220 100644
--- a/runtime/vm/compiler/assembler/assembler_riscv.h
+++ b/runtime/vm/compiler/assembler/assembler_riscv.h
@@ -432,8 +432,6 @@
   void feqs(Register rd, FRegister rs1, FRegister rs2);
   void flts(Register rd, FRegister rs1, FRegister rs2);
   void fles(Register rd, FRegister rs1, FRegister rs2);
-  void fgts(Register rd, FRegister rs1, FRegister rs2) { flts(rd, rs2, rs1); }
-  void fges(Register rd, FRegister rs1, FRegister rs2) { fles(rd, rs2, rs1); }
   void fclasss(Register rd, FRegister rs1);
   // int32_t <- float
   void fcvtws(Register rd, FRegister rs1, RoundingMode rounding = RNE);
@@ -519,8 +517,6 @@
   void feqd(Register rd, FRegister rs1, FRegister rs2);
   void fltd(Register rd, FRegister rs1, FRegister rs2);
   void fled(Register rd, FRegister rs1, FRegister rs2);
-  void fgtd(Register rd, FRegister rs1, FRegister rs2) { fltd(rd, rs2, rs1); }
-  void fged(Register rd, FRegister rs1, FRegister rs2) { fled(rd, rs2, rs1); }
   void fclassd(Register rd, FRegister rs1);
   // int32_t <- double
   void fcvtwd(Register rd, FRegister rs1, RoundingMode rounding = RNE);
@@ -1022,9 +1018,6 @@
                              Register index);
   void LoadSFromOffset(FRegister dest, Register base, int32_t offset);
   void LoadDFromOffset(FRegister dest, Register base, int32_t offset);
-  void LoadSFieldFromOffset(FRegister dest, Register base, int32_t offset) {
-    LoadSFromOffset(dest, base, offset - kHeapObjectTag);
-  }
   void LoadDFieldFromOffset(FRegister dest, Register base, int32_t offset) {
     LoadDFromOffset(dest, base, offset - kHeapObjectTag);
   }
@@ -1050,9 +1043,6 @@
     sx(ZR, address);
   }
   void StoreSToOffset(FRegister src, Register base, int32_t offset);
-  void StoreSFieldToOffset(FRegister src, Register base, int32_t offset) {
-    StoreSToOffset(src, base, offset - kHeapObjectTag);
-  }
   void StoreDToOffset(FRegister src, Register base, int32_t offset);
   void StoreDFieldToOffset(FRegister src, Register base, int32_t offset) {
     StoreDToOffset(src, base, offset - kHeapObjectTag);
@@ -1192,7 +1182,6 @@
   // Note: the function never clobbers TMP, TMP2 scratch registers.
   void LoadImmediate(Register reg, intx_t imm);
 
-  void LoadSImmediate(FRegister reg, float imms);
   void LoadDImmediate(FRegister reg, double immd);
   void LoadQImmediate(FRegister reg, simd128_value_t immq);
 
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index b7e098c..bfed044 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -1394,17 +1394,6 @@
   }
 }
 
-void Assembler::LoadSImmediate(FpuRegister dst, float immediate) {
-  int32_t bits = bit_cast<int32_t>(immediate);
-  if (bits == 0) {
-    xorps(dst, dst);
-  } else {
-    intptr_t index = object_pool_builder().FindImmediate(bits);
-    LoadUnboxedSingle(
-        dst, PP, target::ObjectPool::element_offset(index) - kHeapObjectTag);
-  }
-}
-
 void Assembler::LoadDImmediate(FpuRegister dst, double immediate) {
   int64_t bits = bit_cast<int64_t>(immediate);
   if (bits == 0) {
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index d0b48f8..eafff9b 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -787,7 +787,6 @@
   void LoadImmediate(Register reg, int32_t immediate) {
     LoadImmediate(reg, Immediate(immediate));
   }
-  void LoadSImmediate(FpuRegister dst, float immediate);
   void LoadDImmediate(FpuRegister dst, double immediate);
   void LoadQImmediate(FpuRegister dst, simd128_value_t immediate);
 
@@ -1083,9 +1082,6 @@
     movq(Address(base, offset), src);
   }
 
-  void LoadUnboxedSingle(FpuRegister dst, Register base, int32_t offset) {
-    movss(dst, Address(base, offset));
-  }
   void LoadUnboxedDouble(FpuRegister dst, Register base, int32_t offset) {
     movsd(dst, Address(base, offset));
   }
diff --git a/runtime/vm/compiler/backend/block_builder.h b/runtime/vm/compiler/backend/block_builder.h
index de4c656..4a36631 100644
--- a/runtime/vm/compiler/backend/block_builder.h
+++ b/runtime/vm/compiler/backend/block_builder.h
@@ -136,8 +136,6 @@
     entry_->AsJoinEntry()->InsertPhi(phi);
   }
 
-  Instruction* last() const { return current_; }
-
  private:
   static CompileType* TypeForRepresentation(Representation rep) {
     switch (rep) {
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index 8e53015..8456490 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -872,16 +872,6 @@
   }
 }
 
-void ConstantPropagator::VisitBoolToInt(BoolToIntInstr* instr) {
-  // TODO(riscv)
-  SetValue(instr, non_constant_);
-}
-
-void ConstantPropagator::VisitIntToBool(IntToBoolInstr* instr) {
-  // TODO(riscv)
-  SetValue(instr, non_constant_);
-}
-
 void ConstantPropagator::VisitInstanceOf(InstanceOfInstr* instr) {
   Definition* def = instr->value()->definition();
   const Object& value = def->constant_value();
@@ -1226,27 +1216,8 @@
   VisitUnaryIntegerOp(instr);
 }
 
-static bool IsIntegerOrDouble(const Object& value) {
-  return value.IsInteger() || value.IsDouble();
-}
-
-static double ToDouble(const Object& value) {
-  return value.IsInteger() ? Integer::Cast(value).AsDoubleValue()
-                           : Double::Cast(value).value();
-}
-
 void ConstantPropagator::VisitUnaryDoubleOp(UnaryDoubleOpInstr* instr) {
-  const Object& value = instr->value()->definition()->constant_value();
-  if (IsUnknown(value)) {
-    return;
-  }
-  if (value.IsDouble()) {
-    const double result_val = Evaluator::EvaluateUnaryDoubleOp(
-        ToDouble(value), instr->op_kind(), instr->representation());
-    const Double& result = Double::ZoneHandle(Double::NewCanonical(result_val));
-    SetValue(instr, result);
-    return;
-  }
+  // TODO(kmillikin): Handle unary operations.
   SetValue(instr, non_constant_);
 }
 
@@ -1302,6 +1273,11 @@
   SetValue(instr, non_constant_);
 }
 
+void ConstantPropagator::VisitDoubleToDouble(DoubleToDoubleInstr* instr) {
+  // TODO(kmillikin): Handle conversion.
+  SetValue(instr, non_constant_);
+}
+
 void ConstantPropagator::VisitDoubleToFloat(DoubleToFloatInstr* instr) {
   // TODO(kmillikin): Handle conversion.
   SetValue(instr, non_constant_);
@@ -1312,11 +1288,6 @@
   SetValue(instr, non_constant_);
 }
 
-void ConstantPropagator::VisitFloatCompare(FloatCompareInstr* instr) {
-  // TODO(riscv)
-  SetValue(instr, non_constant_);
-}
-
 void ConstantPropagator::VisitInvokeMathCFunction(
     InvokeMathCFunctionInstr* instr) {
   // TODO(kmillikin): Handle conversion.
@@ -1332,25 +1303,6 @@
   SetValue(instr, non_constant_);
 }
 
-void ConstantPropagator::VisitUnboxLane(UnboxLaneInstr* instr) {
-  if (BoxLanesInstr* box = instr->value()->definition()->AsBoxLanes()) {
-    const Object& value =
-        box->InputAt(instr->lane())->definition()->constant_value();
-    if (IsUnknown(value)) {
-      return;
-    }
-    SetValue(instr, value);
-    return;
-  }
-
-  SetValue(instr, non_constant_);
-}
-
-void ConstantPropagator::VisitBoxLanes(BoxLanesInstr* instr) {
-  // TODO(riscv)
-  SetValue(instr, non_constant_);
-}
-
 void ConstantPropagator::VisitConstant(ConstantInstr* instr) {
   SetValue(instr, instr->value());
 }
@@ -1369,6 +1321,15 @@
   UNREACHABLE();
 }
 
+static bool IsIntegerOrDouble(const Object& value) {
+  return value.IsInteger() || value.IsDouble();
+}
+
+static double ToDouble(const Object& value) {
+  return value.IsInteger() ? Integer::Cast(value).AsDoubleValue()
+                           : Double::Cast(value).value();
+}
+
 void ConstantPropagator::VisitBinaryDoubleOp(BinaryDoubleOpInstr* instr) {
   const Object& left = instr->left()->definition()->constant_value();
   const Object& right = instr->right()->definition()->constant_value();
@@ -1382,9 +1343,8 @@
   const bool both_are_integers = left.IsInteger() && right.IsInteger();
   if (IsIntegerOrDouble(left) && IsIntegerOrDouble(right) &&
       !both_are_integers) {
-    const double result_val = Evaluator::EvaluateBinaryDoubleOp(
-        ToDouble(left), ToDouble(right), instr->op_kind(),
-        instr->representation());
+    const double result_val = Evaluator::EvaluateDoubleOp(
+        ToDouble(left), ToDouble(right), instr->op_kind());
     const Double& result = Double::ZoneHandle(Double::NewCanonical(result_val));
     SetValue(instr, result);
     return;
@@ -1424,6 +1384,11 @@
   SetValue(instr, non_constant_);
 }
 
+void ConstantPropagator::VisitMathUnary(MathUnaryInstr* instr) {
+  // TODO(kmillikin): Handle Math's unary operations (sqrt, cos, sin).
+  SetValue(instr, non_constant_);
+}
+
 void ConstantPropagator::VisitMathMinMax(MathMinMaxInstr* instr) {
   // TODO(srdjan): Handle min and max.
   SetValue(instr, non_constant_);
diff --git a/runtime/vm/compiler/backend/evaluator.cc b/runtime/vm/compiler/backend/evaluator.cc
index 2f9e3b3..9ab7d39 100644
--- a/runtime/vm/compiler/backend/evaluator.cc
+++ b/runtime/vm/compiler/backend/evaluator.cc
@@ -189,91 +189,20 @@
   return result.ptr();
 }
 
-double Evaluator::EvaluateUnaryDoubleOp(const double value,
-                                        Token::Kind token_kind,
-                                        Representation representation) {
-  // The different set of operations for float32 and float64 is due to the
-  // different set of operations made available by dart:core.double and
-  // dart:typed_data.Float64x2 versus dart:typed_data.Float32x4.
-  if (representation == kUnboxedDouble) {
-    switch (token_kind) {
-      case Token::kABS:
-        return fabs(value);
-      case Token::kNEGATE:
-        return -value;
-      case Token::kSQRT:
-        return sqrt(value);
-      case Token::kSQUARE:
-        return value * value;
-      case Token::kTRUNCATE:
-        return trunc(value);
-      case Token::kFLOOR:
-        return floor(value);
-      case Token::kCEILING:
-        return ceil(value);
-      default:
-        UNREACHABLE();
-    }
-  } else {
-    ASSERT(representation == kUnboxedFloat);
-    switch (token_kind) {
-      case Token::kABS:
-        return fabsf(static_cast<float>(value));
-      case Token::kNEGATE:
-        return -static_cast<float>(value);
-      case Token::kRECIPROCAL:
-        return 1.0f / static_cast<float>(value);
-      case Token::kRECIPROCAL_SQRT:
-        return sqrtf(1.0f / static_cast<float>(value));
-      case Token::kSQRT:
-        return sqrtf(static_cast<float>(value));
-      case Token::kSQUARE:
-        return static_cast<float>(value) * static_cast<float>(value);
-      default:
-        UNREACHABLE();
-    }
-  }
-}
-
-double Evaluator::EvaluateBinaryDoubleOp(const double left,
-                                         const double right,
-                                         Token::Kind token_kind,
-                                         Representation representation) {
-  if (representation == kUnboxedDouble) {
-    switch (token_kind) {
-      case Token::kADD:
-        return left + right;
-      case Token::kSUB:
-        return left - right;
-      case Token::kMUL:
-        return left * right;
-      case Token::kDIV:
-        return left / right;
-      case Token::kMIN:
-        return fmin(left, right);
-      case Token::kMAX:
-        return fmax(left, right);
-      default:
-        UNREACHABLE();
-    }
-  } else {
-    ASSERT(representation == kUnboxedFloat);
-    switch (token_kind) {
-      case Token::kADD:
-        return static_cast<float>(left) + static_cast<float>(right);
-      case Token::kSUB:
-        return static_cast<float>(left) - static_cast<float>(right);
-      case Token::kMUL:
-        return static_cast<float>(left) * static_cast<float>(right);
-      case Token::kDIV:
-        return static_cast<float>(left) / static_cast<float>(right);
-      case Token::kMIN:
-        return fminf(static_cast<float>(left), static_cast<float>(right));
-      case Token::kMAX:
-        return fmaxf(static_cast<float>(left), static_cast<float>(right));
-      default:
-        UNREACHABLE();
-    }
+double Evaluator::EvaluateDoubleOp(const double left,
+                                   const double right,
+                                   Token::Kind token_kind) {
+  switch (token_kind) {
+    case Token::kADD:
+      return left + right;
+    case Token::kSUB:
+      return left - right;
+    case Token::kMUL:
+      return left * right;
+    case Token::kDIV:
+      return left / right;
+    default:
+      UNREACHABLE();
   }
 }
 
diff --git a/runtime/vm/compiler/backend/evaluator.h b/runtime/vm/compiler/backend/evaluator.h
index afd05ed..dca583a 100644
--- a/runtime/vm/compiler/backend/evaluator.h
+++ b/runtime/vm/compiler/backend/evaluator.h
@@ -44,16 +44,10 @@
                                       Representation representation,
                                       Thread* thread);
 
-  // Evaluates a unary double operation and returns the result.
-  static double EvaluateUnaryDoubleOp(const double value,
-                                      Token::Kind token_kind,
-                                      Representation representation);
-
   // Evaluates a binary double operation and returns the result.
-  static double EvaluateBinaryDoubleOp(const double left,
-                                       const double right,
-                                       Token::Kind token_kind,
-                                       Representation representation);
+  static double EvaluateDoubleOp(const double left,
+                                 const double right,
+                                 Token::Kind token_kind);
 
   // Returns whether the value is an int64, and returns the int64 value
   // through the result parameter.
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index d167f2d..95691ce 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -220,7 +220,6 @@
     case kUnboxedInt64:
       return value.IsInteger();
 
-    case kUnboxedFloat:
     case kUnboxedDouble:
       return value.IsInteger() || value.IsDouble();
 
@@ -239,13 +238,11 @@
     return op;
   }
 
-  if (((representation == kUnboxedFloat) ||
-       (representation == kUnboxedDouble)) &&
-      value.IsInteger()) {
-    // Convert the boxed constant from int to float/double.
+  if (representation == kUnboxedDouble && value.IsInteger()) {
+    // Convert the boxed constant from int to double.
     return GetConstant(Double::Handle(Double::NewCanonical(
                            Integer::Cast(value).AsDoubleValue())),
-                       representation);
+                       kUnboxedDouble);
   }
 
   return GetConstant(value, representation);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index b0a50c6..6355ea9 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -395,9 +395,6 @@
     case kUnboxedUint32:
       src_kind = CatchEntryMove::SourceKind::kUint32Slot;
       break;
-    case kUnboxedFloat:
-      src_kind = CatchEntryMove::SourceKind::kFloatSlot;
-      break;
     case kUnboxedDouble:
       src_kind = CatchEntryMove::SourceKind::kDoubleSlot;
       break;
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 6be93b4..e7f9172 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -547,8 +547,7 @@
   while (true) {
     Definition* orig;
     if (def->IsConstraint() || def->IsBox() || def->IsUnbox() ||
-        def->IsIntConverter() || def->IsFloatToDouble() ||
-        def->IsDoubleToFloat()) {
+        def->IsIntConverter()) {
       orig = def->InputAt(0)->definition();
     } else {
       orig = def->OriginalDefinition();
@@ -2132,26 +2131,32 @@
 }
 
 Definition* DoubleToFloatInstr::Canonicalize(FlowGraph* flow_graph) {
+#ifdef DEBUG
+  // Must only be used in Float32 StoreIndexedInstr, FloatToDoubleInstr,
+  // Phis introduce by load forwarding, or MaterializeObject for
+  // eliminated Float32 array.
+  ASSERT(env_use_list() == NULL);
+  for (Value* use = input_use_list(); use != NULL; use = use->next_use()) {
+    ASSERT(use->instruction()->IsPhi() ||
+           use->instruction()->IsFloatToDouble() ||
+           (use->instruction()->IsStoreIndexed() &&
+            (use->instruction()->AsStoreIndexed()->class_id() ==
+             kTypedDataFloat32ArrayCid)) ||
+           (use->instruction()->IsMaterializeObject() &&
+            (use->instruction()->AsMaterializeObject()->cls().id() ==
+             kTypedDataFloat32ArrayCid)));
+  }
+#endif
   if (!HasUses()) return NULL;
   if (value()->definition()->IsFloatToDouble()) {
     // F2D(D2F(v)) == v.
     return value()->definition()->AsFloatToDouble()->value()->definition();
   }
-  if (value()->BindsToConstant()) {
-    double narrowed_val =
-        static_cast<float>(Double::Cast(value()->BoundConstant()).value());
-    return flow_graph->GetConstant(
-        Double::ZoneHandle(Double::NewCanonical(narrowed_val)), kUnboxedFloat);
-  }
   return this;
 }
 
 Definition* FloatToDoubleInstr::Canonicalize(FlowGraph* flow_graph) {
-  if (!HasUses()) return NULL;
-  if (value()->BindsToConstant()) {
-    return flow_graph->GetConstant(value()->BoundConstant(), kUnboxedDouble);
-  }
-  return this;
+  return HasUses() ? this : NULL;
 }
 
 Definition* BinaryDoubleOpInstr::Canonicalize(FlowGraph* flow_graph) {
@@ -2171,11 +2176,11 @@
 
   if ((op_kind() == Token::kMUL) &&
       (left()->definition() == right()->definition())) {
-    UnaryDoubleOpInstr* square = new UnaryDoubleOpInstr(
-        Token::kSQUARE, new Value(left()->definition()), DeoptimizationTarget(),
-        speculative_mode_, representation());
-    flow_graph->InsertBefore(this, square, env(), FlowGraph::kValue);
-    return square;
+    MathUnaryInstr* math_unary = new MathUnaryInstr(
+        MathUnaryInstr::kDoubleSquare, new Value(left()->definition()),
+        DeoptimizationTarget());
+    flow_graph->InsertBefore(this, math_unary, env(), FlowGraph::kValue);
+    return math_unary;
   }
 
   return this;
@@ -2616,6 +2621,13 @@
   return HasUses() ? this : NULL;
 }
 
+// A math unary instruction has a side effect (exception
+// thrown) if the argument is not a number.
+// TODO(srdjan): eliminate if has no uses and input is guaranteed to be number.
+Definition* MathUnaryInstr::Canonicalize(FlowGraph* flow_graph) {
+  return this;
+}
+
 bool LoadFieldInstr::TryEvaluateLoad(const Object& instance,
                                      const Slot& field,
                                      Object* result) {
@@ -2980,30 +2992,12 @@
   if ((unbox_defn != NULL) &&
       (unbox_defn->representation() == from_representation()) &&
       (unbox_defn->value()->Type()->ToCid() == Type()->ToCid())) {
-    if (from_representation() == kUnboxedFloat) {
-      // This is a narrowing conversion.
-      return this;
-    }
     return unbox_defn->value()->definition();
   }
 
   return this;
 }
 
-Definition* BoxLanesInstr::Canonicalize(FlowGraph* flow_graph) {
-  return HasUses() ? this : NULL;
-}
-
-Definition* UnboxLaneInstr::Canonicalize(FlowGraph* flow_graph) {
-  if (!HasUses()) return NULL;
-
-  if (BoxLanesInstr* box = value()->definition()->AsBoxLanes()) {
-    return box->InputAt(lane())->definition();
-  }
-
-  return this;
-}
-
 bool BoxIntegerInstr::ValueFitsSmi() const {
   Range* range = value()->definition()->range();
   return RangeUtils::Fits(range, RangeBoundary::kRangeBoundarySmi);
@@ -3060,28 +3054,11 @@
 Definition* UnboxInstr::Canonicalize(FlowGraph* flow_graph) {
   if (!HasUses() && !CanDeoptimize()) return NULL;
 
+  // Fold away Unbox<rep>(Box<rep>(v)).
   BoxInstr* box_defn = value()->definition()->AsBox();
-  if (box_defn != NULL) {
-    // Fold away Unbox<rep>(Box<rep>(v)).
-    if (box_defn->from_representation() == representation()) {
-      return box_defn->value()->definition();
-    }
-
-    if ((box_defn->from_representation() == kUnboxedDouble) &&
-        (representation() == kUnboxedFloat)) {
-      Definition* replacement = new DoubleToFloatInstr(
-          box_defn->value()->CopyWithType(), DeoptId::kNone);
-      flow_graph->InsertBefore(this, replacement, NULL, FlowGraph::kValue);
-      return replacement;
-    }
-
-    if ((box_defn->from_representation() == kUnboxedFloat) &&
-        (representation() == kUnboxedDouble)) {
-      Definition* replacement = new FloatToDoubleInstr(
-          box_defn->value()->CopyWithType(), DeoptId::kNone);
-      flow_graph->InsertBefore(this, replacement, NULL, FlowGraph::kValue);
-      return replacement;
-    }
+  if ((box_defn != NULL) &&
+      (box_defn->from_representation() == representation())) {
+    return box_defn->value()->definition();
   }
 
   if (representation() == kUnboxedDouble && value()->BindsToConstant()) {
@@ -3096,22 +3073,6 @@
     }
   }
 
-  if (representation() == kUnboxedFloat && value()->BindsToConstant()) {
-    const Object& val = value()->BoundConstant();
-    if (val.IsInteger()) {
-      double narrowed_val =
-          static_cast<float>(Integer::Cast(val).AsDoubleValue());
-      return flow_graph->GetConstant(
-          Double::ZoneHandle(Double::NewCanonical(narrowed_val)),
-          kUnboxedFloat);
-    } else if (val.IsDouble()) {
-      double narrowed_val = static_cast<float>(Double::Cast(val).value());
-      return flow_graph->GetConstant(
-          Double::ZoneHandle(Double::NewCanonical(narrowed_val)),
-          kUnboxedFloat);
-    }
-  }
-
   return this;
 }
 
@@ -6470,6 +6431,19 @@
   return kLibcPowRuntimeEntry;
 }
 
+const char* MathUnaryInstr::KindToCString(MathUnaryKind kind) {
+  switch (kind) {
+    case kIllegal:
+      return "illegal";
+    case kSqrt:
+      return "sqrt";
+    case kDoubleSquare:
+      return "double-square";
+  }
+  UNREACHABLE();
+  return "";
+}
+
 TruncDivModInstr::TruncDivModInstr(Value* lhs, Value* rhs, intptr_t deopt_id)
     : TemplateDefinition(deopt_id) {
   SetInputAt(0, lhs);
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index d4df4c7..af9f8b1 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -451,8 +451,6 @@
   M(LoadStaticField, _)                                                        \
   M(StoreStaticField, kNoGC)                                                   \
   M(BooleanNegate, kNoGC)                                                      \
-  M(BoolToInt, kNoGC)                                                          \
-  M(IntToBool, kNoGC)                                                          \
   M(InstanceOf, _)                                                             \
   M(CreateArray, _)                                                            \
   M(AllocateObject, _)                                                         \
@@ -476,9 +474,9 @@
   M(Int64ToDouble, kNoGC)                                                      \
   M(DoubleToInteger, _)                                                        \
   M(DoubleToSmi, kNoGC)                                                        \
+  M(DoubleToDouble, kNoGC)                                                     \
   M(DoubleToFloat, kNoGC)                                                      \
   M(FloatToDouble, kNoGC)                                                      \
-  M(FloatCompare, kNoGC)                                                       \
   M(CheckClass, kNoGC)                                                         \
   M(CheckClassId, kNoGC)                                                       \
   M(CheckSmi, kNoGC)                                                           \
@@ -489,6 +487,7 @@
   M(CheckEitherNonSmi, kNoGC)                                                  \
   M(BinaryDoubleOp, kNoGC)                                                     \
   M(DoubleTestOp, kNoGC)                                                       \
+  M(MathUnary, kNoGC)                                                          \
   M(MathMinMax, kNoGC)                                                         \
   M(Box, _)                                                                    \
   M(Unbox, kNoGC)                                                              \
@@ -516,8 +515,6 @@
   M(TestSmi, kNoGC)                                                            \
   M(TestCids, kNoGC)                                                           \
   M(ExtractNthOutput, kNoGC)                                                   \
-  M(UnboxLane, kNoGC)                                                          \
-  M(BoxLanes, _)                                                               \
   M(BinaryUint32Op, kNoGC)                                                     \
   M(ShiftUint32Op, kNoGC)                                                      \
   M(SpeculativeShiftUint32Op, kNoGC)                                           \
@@ -6254,58 +6251,6 @@
   DISALLOW_COPY_AND_ASSIGN(BooleanNegateInstr);
 };
 
-// bool ? -1 : 0
-class BoolToIntInstr : public TemplateDefinition<1, NoThrow> {
- public:
-  explicit BoolToIntInstr(Value* value) {
-    ASSERT(value->definition()->representation() == kTagged);
-    SetInputAt(0, value);
-  }
-
-  DECLARE_INSTRUCTION(BoolToInt)
-  virtual CompileType ComputeType() const;
-
-  Value* value() const { return inputs_[0]; }
-
-  virtual Representation RequiredInputRepresentation(intptr_t idx) const {
-    return kTagged;
-  }
-  virtual Representation representation() const { return kUnboxedInt32; }
-
-  virtual bool ComputeCanDeoptimize() const { return false; }
-
-  virtual bool HasUnknownSideEffects() const { return false; }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(BoolToIntInstr);
-};
-
-// int == 0 ? false : true
-class IntToBoolInstr : public TemplateDefinition<1, NoThrow> {
- public:
-  explicit IntToBoolInstr(Value* value) {
-    ASSERT(value->definition()->representation() == kUnboxedInt32);
-    SetInputAt(0, value);
-  }
-
-  DECLARE_INSTRUCTION(IntToBool)
-  virtual CompileType ComputeType() const;
-
-  Value* value() const { return inputs_[0]; }
-
-  virtual Representation RequiredInputRepresentation(intptr_t idx) const {
-    return kUnboxedInt32;
-  }
-  virtual Representation representation() const { return kTagged; }
-
-  virtual bool ComputeCanDeoptimize() const { return false; }
-
-  virtual bool HasUnknownSideEffects() const { return false; }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(IntToBoolInstr);
-};
-
 class InstanceOfInstr : public TemplateDefinition<3, Throws> {
  public:
   InstanceOfInstr(const InstructionSource& source,
@@ -7545,6 +7490,60 @@
          IsBoxInt64() || IsUnboxInt64();
 }
 
+class MathUnaryInstr : public TemplateDefinition<1, NoThrow, Pure> {
+ public:
+  enum MathUnaryKind {
+    kIllegal,
+    kSqrt,
+    kDoubleSquare,
+  };
+  MathUnaryInstr(MathUnaryKind kind, Value* value, intptr_t deopt_id)
+      : TemplateDefinition(deopt_id), kind_(kind) {
+    SetInputAt(0, value);
+  }
+
+  Value* value() const { return inputs_[0]; }
+  MathUnaryKind kind() const { return kind_; }
+
+  virtual bool ComputeCanDeoptimize() const { return false; }
+
+  virtual Representation representation() const { return kUnboxedDouble; }
+
+  virtual Representation RequiredInputRepresentation(intptr_t idx) const {
+    ASSERT(idx == 0);
+    return kUnboxedDouble;
+  }
+
+  virtual SpeculativeMode SpeculativeModeOfInput(intptr_t idx) const {
+    ASSERT(idx == 0);
+    return kNotSpeculative;
+  }
+
+  virtual intptr_t DeoptimizationTarget() const {
+    // Direct access since this instruction cannot deoptimize, and the deopt-id
+    // was inherited from another instruction that could deoptimize.
+    return GetDeoptId();
+  }
+
+  DECLARE_INSTRUCTION(MathUnary)
+  virtual CompileType ComputeType() const;
+
+  virtual bool AttributesEqual(const Instruction& other) const {
+    return kind() == other.AsMathUnary()->kind();
+  }
+
+  Definition* Canonicalize(FlowGraph* flow_graph);
+
+  static const char* KindToCString(MathUnaryKind kind);
+
+  PRINT_OPERANDS_TO_SUPPORT
+
+ private:
+  const MathUnaryKind kind_;
+
+  DISALLOW_COPY_AND_ASSIGN(MathUnaryInstr);
+};
+
 // Calls into the runtime and performs a case-insensitive comparison of the
 // UTF16 strings (i.e. TwoByteString or ExternalTwoByteString) located at
 // str[lhs_index:lhs_index + length] and str[rhs_index:rhs_index + length].
@@ -7664,15 +7663,11 @@
                       Value* right,
                       intptr_t deopt_id,
                       const InstructionSource& source,
-                      SpeculativeMode speculative_mode = kGuardInputs,
-                      Representation representation = kUnboxedDouble)
+                      SpeculativeMode speculative_mode = kGuardInputs)
       : TemplateDefinition(source, deopt_id),
         op_kind_(op_kind),
         token_pos_(source.token_pos),
-        speculative_mode_(speculative_mode),
-        representation_(representation) {
-    ASSERT((representation == kUnboxedFloat) ||
-           (representation == kUnboxedDouble));
+        speculative_mode_(speculative_mode) {
     SetInputAt(0, left);
     SetInputAt(1, right);
   }
@@ -7686,11 +7681,11 @@
 
   virtual bool ComputeCanDeoptimize() const { return false; }
 
-  virtual Representation representation() const { return representation_; }
+  virtual Representation representation() const { return kUnboxedDouble; }
 
   virtual Representation RequiredInputRepresentation(intptr_t idx) const {
     ASSERT((idx == 0) || (idx == 1));
-    return representation_;
+    return kUnboxedDouble;
   }
 
   virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
@@ -7713,15 +7708,13 @@
   virtual bool AttributesEqual(const Instruction& other) const {
     auto const other_bin_op = other.AsBinaryDoubleOp();
     return (op_kind() == other_bin_op->op_kind()) &&
-           (speculative_mode_ == other_bin_op->speculative_mode_) &&
-           (representation_ == other_bin_op->representation_);
+           (speculative_mode_ == other_bin_op->speculative_mode_);
   }
 
  private:
   const Token::Kind op_kind_;
   const TokenPosition token_pos_;
   const SpeculativeMode speculative_mode_;
-  const Representation representation_;
 
   DISALLOW_COPY_AND_ASSIGN(BinaryDoubleOpInstr);
 };
@@ -8304,19 +8297,17 @@
   DISALLOW_COPY_AND_ASSIGN(SpeculativeShiftUint32OpInstr);
 };
 
+// Handles only NEGATE.
 class UnaryDoubleOpInstr : public TemplateDefinition<1, NoThrow, Pure> {
  public:
   UnaryDoubleOpInstr(Token::Kind op_kind,
                      Value* value,
                      intptr_t deopt_id,
-                     SpeculativeMode speculative_mode = kGuardInputs,
-                     Representation representation = kUnboxedDouble)
+                     SpeculativeMode speculative_mode = kGuardInputs)
       : TemplateDefinition(deopt_id),
         op_kind_(op_kind),
-        speculative_mode_(speculative_mode),
-        representation_(representation) {
-    ASSERT((representation == kUnboxedFloat) ||
-           (representation == kUnboxedDouble));
+        speculative_mode_(speculative_mode) {
+    ASSERT(op_kind == Token::kNEGATE);
     SetInputAt(0, value);
   }
 
@@ -8334,11 +8325,11 @@
     return GetDeoptId();
   }
 
-  virtual Representation representation() const { return representation_; }
+  virtual Representation representation() const { return kUnboxedDouble; }
 
   virtual Representation RequiredInputRepresentation(intptr_t idx) const {
     ASSERT(idx == 0);
-    return representation_;
+    return kUnboxedDouble;
   }
 
   virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
@@ -8346,8 +8337,7 @@
   }
 
   virtual bool AttributesEqual(const Instruction& other) const {
-    return (speculative_mode_ == other.AsUnaryDoubleOp()->speculative_mode_) &&
-           (representation_ == other.AsUnaryDoubleOp()->representation_);
+    return speculative_mode_ == other.AsUnaryDoubleOp()->speculative_mode_;
   }
 
   PRINT_OPERANDS_TO_SUPPORT
@@ -8355,7 +8345,6 @@
  private:
   const Token::Kind op_kind_;
   const SpeculativeMode speculative_mode_;
-  const Representation representation_;
 
   DISALLOW_COPY_AND_ASSIGN(UnaryDoubleOpInstr);
 };
@@ -8585,6 +8574,51 @@
   DISALLOW_COPY_AND_ASSIGN(DoubleToSmiInstr);
 };
 
+class DoubleToDoubleInstr : public TemplateDefinition<1, NoThrow, Pure> {
+ public:
+  DoubleToDoubleInstr(Value* value,
+                      MethodRecognizer::Kind recognized_kind,
+                      intptr_t deopt_id)
+      : TemplateDefinition(deopt_id), recognized_kind_(recognized_kind) {
+    ASSERT((recognized_kind == MethodRecognizer::kDoubleTruncateToDouble) ||
+           (recognized_kind == MethodRecognizer::kDoubleFloorToDouble) ||
+           (recognized_kind == MethodRecognizer::kDoubleCeilToDouble));
+    SetInputAt(0, value);
+  }
+
+  Value* value() const { return inputs_[0]; }
+
+  MethodRecognizer::Kind recognized_kind() const { return recognized_kind_; }
+
+  DECLARE_INSTRUCTION(DoubleToDouble)
+  virtual CompileType ComputeType() const;
+
+  virtual bool ComputeCanDeoptimize() const { return false; }
+
+  virtual Representation representation() const { return kUnboxedDouble; }
+
+  virtual Representation RequiredInputRepresentation(intptr_t idx) const {
+    ASSERT(idx == 0);
+    return kUnboxedDouble;
+  }
+
+  virtual SpeculativeMode SpeculativeModeOfInput(intptr_t idx) const {
+    ASSERT(idx == 0);
+    return kNotSpeculative;
+  }
+
+  virtual intptr_t DeoptimizationTarget() const { return GetDeoptId(); }
+
+  virtual bool AttributesEqual(const Instruction& other) const {
+    return other.AsDoubleToDouble()->recognized_kind() == recognized_kind();
+  }
+
+ private:
+  const MethodRecognizer::Kind recognized_kind_;
+
+  DISALLOW_COPY_AND_ASSIGN(DoubleToDoubleInstr);
+};
+
 class DoubleToFloatInstr : public TemplateDefinition<1, NoThrow, Pure> {
  public:
   DoubleToFloatInstr(Value* value,
@@ -8657,42 +8691,6 @@
   DISALLOW_COPY_AND_ASSIGN(FloatToDoubleInstr);
 };
 
-// left op right ? -1 : 0
-class FloatCompareInstr : public TemplateDefinition<2, NoThrow, Pure> {
- public:
-  FloatCompareInstr(Token::Kind op_kind, Value* left, Value* right)
-      : op_kind_(op_kind) {
-    SetInputAt(0, left);
-    SetInputAt(1, right);
-  }
-
-  Value* left() const { return inputs_[0]; }
-  Value* right() const { return inputs_[1]; }
-
-  Token::Kind op_kind() const { return op_kind_; }
-
-  DECLARE_INSTRUCTION(FloatCompare)
-
-  virtual CompileType ComputeType() const;
-
-  virtual bool ComputeCanDeoptimize() const { return false; }
-
-  virtual Representation representation() const { return kUnboxedInt32; }
-
-  virtual Representation RequiredInputRepresentation(intptr_t idx) const {
-    return kUnboxedFloat;
-  }
-
-  virtual bool AttributesEqual(const Instruction& other) const {
-    return other.AsFloatCompare()->op_kind() == op_kind();
-  }
-
- private:
-  const Token::Kind op_kind_;
-
-  DISALLOW_COPY_AND_ASSIGN(FloatCompareInstr);
-};
-
 // TODO(sjindel): Replace with FFICallInstr.
 class InvokeMathCFunctionInstr : public PureDefinition {
  public:
@@ -8805,136 +8803,6 @@
   DISALLOW_COPY_AND_ASSIGN(ExtractNthOutputInstr);
 };
 
-class UnboxLaneInstr : public TemplateDefinition<1, NoThrow, Pure> {
- public:
-  UnboxLaneInstr(Value* value,
-                 intptr_t n,
-                 Representation definition_rep,
-                 intptr_t definition_cid)
-      : lane_(n),
-        definition_rep_(definition_rep),
-        definition_cid_(definition_cid) {
-    SetInputAt(0, value);
-  }
-
-  Value* value() const { return inputs_[0]; }
-
-  DECLARE_INSTRUCTION(UnboxLane)
-
-  virtual CompileType ComputeType() const;
-  virtual bool ComputeCanDeoptimize() const { return false; }
-
-  intptr_t lane() const { return lane_; }
-
-  virtual Representation representation() const { return definition_rep_; }
-
-  virtual Representation RequiredInputRepresentation(intptr_t idx) const {
-    ASSERT(idx == 0);
-    return kTagged;
-  }
-
-  virtual bool AttributesEqual(const Instruction& other) const {
-    auto const other_split = other.AsUnboxLane();
-    return (other_split->representation() == representation()) &&
-           (other_split->lane() == lane());
-  }
-
-  Definition* Canonicalize(FlowGraph* flow_graph);
-
-  PRINT_OPERANDS_TO_SUPPORT
-
- private:
-  const intptr_t lane_;
-  const Representation definition_rep_;
-  const intptr_t definition_cid_;
-  DISALLOW_COPY_AND_ASSIGN(UnboxLaneInstr);
-};
-
-class BoxLanesInstr : public TemplateDefinition<4, NoThrow, Pure> {
- public:
-  BoxLanesInstr(Representation from_representation, Value* x, Value* y)
-      : from_representation_(from_representation) {
-    ASSERT(from_representation == kUnboxedDouble);
-    ASSERT(x->definition()->representation() == from_representation);
-    ASSERT(y->definition()->representation() == from_representation);
-    SetInputAt(0, x);
-    SetInputAt(1, y);
-  }
-  BoxLanesInstr(Representation from_representation,
-                Value* x,
-                Value* y,
-                Value* z,
-                Value* w)
-      : from_representation_(from_representation) {
-    ASSERT((from_representation == kUnboxedInt32) ||
-           (from_representation == kUnboxedFloat));
-    ASSERT(x->definition()->representation() == from_representation);
-    ASSERT(y->definition()->representation() == from_representation);
-    ASSERT(z->definition()->representation() == from_representation);
-    ASSERT(w->definition()->representation() == from_representation);
-    SetInputAt(0, x);
-    SetInputAt(1, y);
-    SetInputAt(2, z);
-    SetInputAt(3, w);
-  }
-
-  intptr_t InputCount() const {
-    switch (from_representation_) {
-      case kUnboxedDouble:
-        return 2;
-      case kUnboxedFloat:
-        return 4;
-      case kUnboxedInt32:
-        return 4;
-      default:
-        UNREACHABLE();
-        return 0;
-    }
-  }
-  Value* x() const { return inputs_[0]; }
-  Value* y() const { return inputs_[1]; }
-  Value* z() const {
-    ASSERT((from_representation() == kUnboxedInt32) ||
-           (from_representation() == kUnboxedFloat));
-    return inputs_[2];
-  }
-  Value* w() const {
-    ASSERT((from_representation() == kUnboxedInt32) ||
-           (from_representation() == kUnboxedFloat));
-    return inputs_[3];
-  }
-  Representation from_representation() const { return from_representation_; }
-
-  DECLARE_INSTRUCTION(BoxLanes)
-  virtual CompileType ComputeType() const;
-
-  virtual bool ComputeCanDeoptimize() const { return false; }
-  virtual intptr_t DeoptimizationTarget() const { return DeoptId::kNone; }
-
-  virtual Representation RequiredInputRepresentation(intptr_t idx) const {
-    ASSERT(idx == 0 || idx == 1 || idx == 2 || idx == 3);
-    return from_representation();
-  }
-
-  virtual bool AttributesEqual(const Instruction& other) const {
-    return other.AsBoxLanes()->from_representation() == from_representation();
-  }
-
-  Definition* Canonicalize(FlowGraph* flow_graph);
-
-  virtual TokenPosition token_pos() const { return TokenPosition::kBox; }
-
-  virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
-    return kNotSpeculative;
-  }
-
-  PRINT_OPERANDS_TO_SUPPORT
-
- private:
-  const Representation from_representation_;
-  DISALLOW_COPY_AND_ASSIGN(BoxLanesInstr);
-};
-
 class TruncDivModInstr : public TemplateDefinition<2, NoThrow, Pure> {
  public:
   TruncDivModInstr(Value* lhs, Value* rhs, intptr_t deopt_id);
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 0e131fa..e4bc74b 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -698,10 +698,11 @@
     }
   } else if (destination.IsFpuRegister()) {
     const DRegister dst = EvenDRegisterOf(destination.fpu_reg());
-    if (representation() == kUnboxedFloat) {
-      __ LoadSImmediate(EvenSRegisterOf(dst), Double::Cast(value_).value());
+    if (Utils::DoublesBitEqual(Double::Cast(value_).value(), 0.0) &&
+        TargetCPUFeatures::neon_supported()) {
+      QRegister qdst = destination.fpu_reg();
+      __ veorq(qdst, qdst, qdst);
     } else {
-      ASSERT(representation() == kUnboxedDouble);
       ASSERT(tmp != kNoRegister);
       __ LoadDImmediate(dst, Double::Cast(value_).value(), tmp);
     }
@@ -5703,6 +5704,33 @@
 
 #undef DEFINE_EMIT
 
+LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone,
+                                                     bool opt) const {
+  ASSERT((kind() == MathUnaryInstr::kSqrt) ||
+         (kind() == MathUnaryInstr::kDoubleSquare));
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_out(0, Location::RequiresFpuRegister());
+  return summary;
+}
+
+void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (kind() == MathUnaryInstr::kSqrt) {
+    const DRegister val = EvenDRegisterOf(locs()->in(0).fpu_reg());
+    const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg());
+    __ vsqrtd(result, val);
+  } else if (kind() == MathUnaryInstr::kDoubleSquare) {
+    const DRegister val = EvenDRegisterOf(locs()->in(0).fpu_reg());
+    const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg());
+    __ vmuld(result, val, val);
+  } else {
+    UNREACHABLE();
+  }
+}
+
 LocationSummary* CaseInsensitiveCompareInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
@@ -5855,22 +5883,9 @@
 }
 
 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(representation() == kUnboxedDouble);
   const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg());
   const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg());
-  switch (op_kind()) {
-    case Token::kNEGATE:
-      __ vnegd(result, value);
-      break;
-    case Token::kSQRT:
-      __ vsqrtd(result, value);
-      break;
-    case Token::kSQUARE:
-      __ vmuld(result, value, value);
-      break;
-    default:
-      UNREACHABLE();
-  }
+  __ vnegd(result, value);
 }
 
 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone,
@@ -5985,6 +6000,16 @@
   __ SmiTag(result);
 }
 
+LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone,
+                                                          bool opt) const {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone,
                                                          bool opt) const {
   const intptr_t kNumInputs = 1;
@@ -6023,16 +6048,6 @@
   __ vcvtds(result, value);
 }
 
-LocationSummary* FloatCompareInstr::MakeLocationSummary(Zone* zone,
-                                                        bool opt) const {
-  UNREACHABLE();
-  return NULL;
-}
-
-void FloatCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
-}
-
 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone,
                                                                bool opt) const {
   ASSERT((InputCount() == 1) || (InputCount() == 2));
@@ -6283,26 +6298,6 @@
   }
 }
 
-LocationSummary* UnboxLaneInstr::MakeLocationSummary(Zone* zone,
-                                                     bool opt) const {
-  UNREACHABLE();
-  return NULL;
-}
-
-void UnboxLaneInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
-}
-
-LocationSummary* BoxLanesInstr::MakeLocationSummary(Zone* zone,
-                                                    bool opt) const {
-  UNREACHABLE();
-  return NULL;
-}
-
-void BoxLanesInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
-}
-
 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone,
                                                        bool opt) const {
   const intptr_t kNumInputs = 2;
@@ -7582,26 +7577,6 @@
          compiler::Operand(compiler::target::ObjectAlignment::kBoolValueMask));
 }
 
-LocationSummary* BoolToIntInstr::MakeLocationSummary(Zone* zone,
-                                                     bool opt) const {
-  UNREACHABLE();
-  return NULL;
-}
-
-void BoolToIntInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
-}
-
-LocationSummary* IntToBoolInstr::MakeLocationSummary(Zone* zone,
-                                                     bool opt) const {
-  UNREACHABLE();
-  return NULL;
-}
-
-void IntToBoolInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
-}
-
 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone,
                                                           bool opt) const {
   const intptr_t kNumInputs = (type_arguments() != nullptr) ? 1 : 0;
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index e61557a..ca277fb 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -625,12 +625,6 @@
   } else if (destination.IsFpuRegister()) {
     const VRegister dst = destination.fpu_reg();
     __ LoadDImmediate(dst, Double::Cast(value_).value());
-    if (representation() == kUnboxedFloat) {
-      __ LoadSImmediate(dst, Double::Cast(value_).value());
-    } else {
-      ASSERT(representation() == kUnboxedDouble);
-      __ LoadDImmediate(dst, Double::Cast(value_).value());
-    }
   } else if (destination.IsDoubleStackSlot()) {
     const intptr_t dest_offset = destination.ToStackSlotOffset();
     if (Utils::DoublesBitEqual(Double::Cast(value_).value(), 0.0)) {
@@ -4802,6 +4796,33 @@
 
 #undef DEFINE_EMIT
 
+LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone,
+                                                     bool opt) const {
+  ASSERT((kind() == MathUnaryInstr::kSqrt) ||
+         (kind() == MathUnaryInstr::kDoubleSquare));
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_out(0, Location::RequiresFpuRegister());
+  return summary;
+}
+
+void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (kind() == MathUnaryInstr::kSqrt) {
+    const VRegister val = locs()->in(0).fpu_reg();
+    const VRegister result = locs()->out(0).fpu_reg();
+    __ fsqrtd(result, val);
+  } else if (kind() == MathUnaryInstr::kDoubleSquare) {
+    const VRegister val = locs()->in(0).fpu_reg();
+    const VRegister result = locs()->out(0).fpu_reg();
+    __ fmuld(result, val, val);
+  } else {
+    UNREACHABLE();
+  }
+}
+
 LocationSummary* CaseInsensitiveCompareInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
@@ -4954,22 +4975,9 @@
 }
 
 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(representation() == kUnboxedDouble);
   const VRegister result = locs()->out(0).fpu_reg();
   const VRegister value = locs()->in(0).fpu_reg();
-  switch (op_kind()) {
-    case Token::kNEGATE:
-      __ fnegd(result, value);
-      break;
-    case Token::kSQRT:
-      __ fsqrtd(result, value);
-      break;
-    case Token::kSQUARE:
-      __ fmuld(result, value, value);
-      break;
-    default:
-      UNREACHABLE();
-  }
+  __ fnegd(result, value);
 }
 
 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone,
@@ -5118,6 +5126,16 @@
   __ SmiTag(result);
 }
 
+LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone,
+                                                          bool opt) const {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone,
                                                          bool opt) const {
   const intptr_t kNumInputs = 1;
@@ -5152,16 +5170,6 @@
   __ fcvtds(result, value);
 }
 
-LocationSummary* FloatCompareInstr::MakeLocationSummary(Zone* zone,
-                                                        bool opt) const {
-  UNREACHABLE();
-  return NULL;
-}
-
-void FloatCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
-}
-
 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone,
                                                                bool opt) const {
   ASSERT((InputCount() == 1) || (InputCount() == 2));
@@ -5364,26 +5372,6 @@
   }
 }
 
-LocationSummary* UnboxLaneInstr::MakeLocationSummary(Zone* zone,
-                                                     bool opt) const {
-  UNREACHABLE();
-  return NULL;
-}
-
-void UnboxLaneInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
-}
-
-LocationSummary* BoxLanesInstr::MakeLocationSummary(Zone* zone,
-                                                    bool opt) const {
-  UNREACHABLE();
-  return NULL;
-}
-
-void BoxLanesInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
-}
-
 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone,
                                                        bool opt) const {
   const intptr_t kNumInputs = 2;
@@ -6687,26 +6675,6 @@
       compiler::Immediate(compiler::target::ObjectAlignment::kBoolValueMask));
 }
 
-LocationSummary* BoolToIntInstr::MakeLocationSummary(Zone* zone,
-                                                     bool opt) const {
-  UNREACHABLE();
-  return NULL;
-}
-
-void BoolToIntInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
-}
-
-LocationSummary* IntToBoolInstr::MakeLocationSummary(Zone* zone,
-                                                     bool opt) const {
-  UNREACHABLE();
-  return NULL;
-}
-
-void IntToBoolInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
-}
-
 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone,
                                                           bool opt) const {
   const intptr_t kNumInputs = (type_arguments() != nullptr) ? 1 : 0;
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 4d24aa2..b84f33e 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -421,23 +421,18 @@
       __ LoadObjectSafely(destination.reg(), value_);
     }
   } else if (destination.IsFpuRegister()) {
-    if (representation() == kUnboxedFloat) {
-      __ LoadSImmediate(destination.fpu_reg(),
-                        static_cast<float>(Double::Cast(value_).value()));
+    const double value_as_double = Double::Cast(value_).value();
+    uword addr = FindDoubleConstant(value_as_double);
+    if (addr == 0) {
+      __ pushl(EAX);
+      __ LoadObject(EAX, value_);
+      __ movsd(destination.fpu_reg(),
+               compiler::FieldAddress(EAX, Double::value_offset()));
+      __ popl(EAX);
+    } else if (Utils::DoublesBitEqual(value_as_double, 0.0)) {
+      __ xorps(destination.fpu_reg(), destination.fpu_reg());
     } else {
-      const double value_as_double = Double::Cast(value_).value();
-      uword addr = FindDoubleConstant(value_as_double);
-      if (addr == 0) {
-        __ pushl(EAX);
-        __ LoadObject(EAX, value_);
-        __ movsd(destination.fpu_reg(),
-                 compiler::FieldAddress(EAX, Double::value_offset()));
-        __ popl(EAX);
-      } else if (Utils::DoublesBitEqual(value_as_double, 0.0)) {
-        __ xorps(destination.fpu_reg(), destination.fpu_reg());
-      } else {
-        __ movsd(destination.fpu_reg(), compiler::Address::Absolute(addr));
-      }
+      __ movsd(destination.fpu_reg(), compiler::Address::Absolute(addr));
     }
   } else if (destination.IsDoubleStackSlot()) {
     const double value_as_double = Double::Cast(value_).value();
@@ -4822,6 +4817,35 @@
 
 #undef DEFINE_EMIT
 
+LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone,
+                                                     bool opt) const {
+  ASSERT((kind() == MathUnaryInstr::kSqrt) ||
+         (kind() == MathUnaryInstr::kDoubleSquare));
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  if (kind() == MathUnaryInstr::kDoubleSquare) {
+    summary->set_out(0, Location::SameAsFirstInput());
+  } else {
+    summary->set_out(0, Location::RequiresFpuRegister());
+  }
+  return summary;
+}
+
+void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (kind() == MathUnaryInstr::kSqrt) {
+    __ sqrtsd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg());
+  } else if (kind() == MathUnaryInstr::kDoubleSquare) {
+    XmmRegister value_reg = locs()->in(0).fpu_reg();
+    __ mulsd(value_reg, value_reg);
+    ASSERT(value_reg == locs()->out(0).fpu_reg());
+  } else {
+    UNREACHABLE();
+  }
+}
+
 LocationSummary* CaseInsensitiveCompareInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
@@ -4977,31 +5001,9 @@
 }
 
 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(representation() == kUnboxedDouble);
   XmmRegister value = locs()->in(0).fpu_reg();
   ASSERT(locs()->out(0).fpu_reg() == value);
-  switch (op_kind()) {
-    case Token::kNEGATE:
-      __ DoubleNegate(value);
-      break;
-    case Token::kSQRT:
-      __ sqrtsd(value, value);
-      break;
-    case Token::kSQUARE:
-      __ mulsd(value, value);
-      break;
-    case Token::kTRUNCATE:
-      __ roundsd(value, value, compiler::Assembler::kRoundToZero);
-      break;
-    case Token::kFLOOR:
-      __ roundsd(value, value, compiler::Assembler::kRoundDown);
-      break;
-    case Token::kCEILING:
-      __ roundsd(value, value, compiler::Assembler::kRoundUp);
-      break;
-    default:
-      UNREACHABLE();
-  }
+  __ DoubleNegate(value);
 }
 
 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone,
@@ -5124,6 +5126,35 @@
   __ SmiTag(result);
 }
 
+LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone,
+                                                          bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* result = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  result->set_in(0, Location::RequiresFpuRegister());
+  result->set_out(0, Location::RequiresFpuRegister());
+  return result;
+}
+
+void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  XmmRegister value = locs()->in(0).fpu_reg();
+  XmmRegister result = locs()->out(0).fpu_reg();
+  switch (recognized_kind()) {
+    case MethodRecognizer::kDoubleTruncateToDouble:
+      __ roundsd(result, value, compiler::Assembler::kRoundToZero);
+      break;
+    case MethodRecognizer::kDoubleFloorToDouble:
+      __ roundsd(result, value, compiler::Assembler::kRoundDown);
+      break;
+    case MethodRecognizer::kDoubleCeilToDouble:
+      __ roundsd(result, value, compiler::Assembler::kRoundUp);
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone,
                                                          bool opt) const {
   const intptr_t kNumInputs = 1;
@@ -5154,16 +5185,6 @@
   __ cvtss2sd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg());
 }
 
-LocationSummary* FloatCompareInstr::MakeLocationSummary(Zone* zone,
-                                                        bool opt) const {
-  UNREACHABLE();
-  return NULL;
-}
-
-void FloatCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
-}
-
 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone,
                                                                bool opt) const {
   ASSERT((InputCount() == 1) || (InputCount() == 2));
@@ -5390,26 +5411,6 @@
   }
 }
 
-LocationSummary* UnboxLaneInstr::MakeLocationSummary(Zone* zone,
-                                                     bool opt) const {
-  UNREACHABLE();
-  return NULL;
-}
-
-void UnboxLaneInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
-}
-
-LocationSummary* BoxLanesInstr::MakeLocationSummary(Zone* zone,
-                                                    bool opt) const {
-  UNREACHABLE();
-  return NULL;
-}
-
-void BoxLanesInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
-}
-
 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone,
                                                        bool opt) const {
   const intptr_t kNumInputs = 2;
@@ -6661,26 +6662,6 @@
                       compiler::target::ObjectAlignment::kBoolValueMask));
 }
 
-LocationSummary* BoolToIntInstr::MakeLocationSummary(Zone* zone,
-                                                     bool opt) const {
-  UNREACHABLE();
-  return NULL;
-}
-
-void BoolToIntInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
-}
-
-LocationSummary* IntToBoolInstr::MakeLocationSummary(Zone* zone,
-                                                     bool opt) const {
-  UNREACHABLE();
-  return NULL;
-}
-
-void IntToBoolInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
-}
-
 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone,
                                                           bool opt) const {
   const intptr_t kNumInputs = (type_arguments() != nullptr) ? 1 : 0;
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index da9c0c9..05b7050 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -484,9 +484,7 @@
     range_->PrintTo(f);
   }
 
-  if (representation() != kNoRepresentation && representation() != kTagged) {
-    f->Printf(" %s", RepresentationToCString(representation()));
-  } else if (type_ != NULL) {
+  if (type_ != NULL) {
     f->AddString(" ");
     type_->PrintTo(f);
   }
@@ -555,6 +553,10 @@
     buffer[pos] = '\0';
     f->Printf("#%s\\n...", buffer);
   }
+
+  if (representation() != kNoRepresentation && representation() != kTagged) {
+    f->Printf(" %s", RepresentationToCString(representation()));
+  }
 }
 
 void ConstraintInstr::PrintOperandsTo(BaseTextBuffer* f) const {
@@ -908,6 +910,11 @@
   TemplateAllocation::PrintOperandsTo(f);
 }
 
+void MathUnaryInstr::PrintOperandsTo(BaseTextBuffer* f) const {
+  f->Printf("'%s', ", MathUnaryInstr::KindToCString(kind()));
+  value()->PrintTo(f);
+}
+
 void TruncDivModInstr::PrintOperandsTo(BaseTextBuffer* f) const {
   Definition::PrintOperandsTo(f);
 }
@@ -917,15 +924,6 @@
   Definition::PrintOperandsTo(f);
 }
 
-void UnboxLaneInstr::PrintOperandsTo(BaseTextBuffer* f) const {
-  Definition::PrintOperandsTo(f);
-  f->Printf(", lane %" Pd, lane());
-}
-
-void BoxLanesInstr::PrintOperandsTo(BaseTextBuffer* f) const {
-  Definition::PrintOperandsTo(f);
-}
-
 void UnaryIntegerOpInstr::PrintOperandsTo(BaseTextBuffer* f) const {
   f->Printf("%s, ", Token::Str(op_kind()));
   value()->PrintTo(f);
diff --git a/runtime/vm/compiler/backend/il_riscv.cc b/runtime/vm/compiler/backend/il_riscv.cc
index 2222f9b..041f180 100644
--- a/runtime/vm/compiler/backend/il_riscv.cc
+++ b/runtime/vm/compiler/backend/il_riscv.cc
@@ -715,12 +715,7 @@
     }
   } else if (destination.IsFpuRegister()) {
     const FRegister dst = destination.fpu_reg();
-    if (representation() == kUnboxedFloat) {
-      __ LoadSImmediate(dst, Double::Cast(value_).value());
-    } else {
-      ASSERT(representation() == kUnboxedDouble);
-      __ LoadDImmediate(dst, Double::Cast(value_).value());
-    }
+    __ LoadDImmediate(dst, Double::Cast(value_).value());
   } else if (destination.IsDoubleStackSlot()) {
     const intptr_t dest_offset = destination.ToStackSlotOffset();
 #if XLEN == 32
@@ -1203,7 +1198,7 @@
       __ CompareImmediate(TMP, 0);
       return NE;
     case Token::kGT:
-      __ fgtd(TMP, left, right);
+      __ fltd(TMP, right, left);
       __ CompareImmediate(TMP, 0);
       return NE;
     case Token::kLTE:
@@ -1211,7 +1206,7 @@
       __ CompareImmediate(TMP, 0);
       return NE;
     case Token::kGTE:
-      __ fged(TMP, left, right);
+      __ fled(TMP, right, left);
       __ CompareImmediate(TMP, 0);
       return NE;
     default:
@@ -3368,11 +3363,9 @@
         __ LoadDFieldFromOffset(result, temp, Double::value_offset());
         break;
       case kFloat32x4Cid:
-        __ Comment("UnboxedFloat32x4LoadFieldInstr");
         UNIMPLEMENTED();
         break;
       case kFloat64x2Cid:
-        __ Comment("UnboxedFloat64x2LoadFieldInstr");
         UNIMPLEMENTED();
         break;
       default:
@@ -4441,16 +4434,6 @@
     }
 #endif
 
-    case kUnboxedFloat: {
-      const FRegister result = locs()->out(0).fpu_reg();
-      __ SmiUntag(TMP, box);
-#if XLEN == 32
-      __ fcvtsw(result, TMP);
-#elif XLEN == 64
-      __ fcvtsl(result, TMP);
-#endif
-      break;
-    }
     case kUnboxedDouble: {
       const FRegister result = locs()->out(0).fpu_reg();
       __ SmiUntag(TMP, box);
@@ -4825,53 +4808,21 @@
   const FRegister left = locs()->in(0).fpu_reg();
   const FRegister right = locs()->in(1).fpu_reg();
   const FRegister result = locs()->out(0).fpu_reg();
-  if (representation() == kUnboxedDouble) {
-    switch (op_kind()) {
-      case Token::kADD:
-        __ faddd(result, left, right);
-        break;
-      case Token::kSUB:
-        __ fsubd(result, left, right);
-        break;
-      case Token::kMUL:
-        __ fmuld(result, left, right);
-        break;
-      case Token::kDIV:
-        __ fdivd(result, left, right);
-        break;
-      case Token::kMIN:
-        __ fmind(result, left, right);
-        break;
-      case Token::kMAX:
-        __ fmaxd(result, left, right);
-        break;
-      default:
-        UNREACHABLE();
-    }
-  } else {
-    ASSERT(representation() == kUnboxedFloat);
-    switch (op_kind()) {
-      case Token::kADD:
-        __ fadds(result, left, right);
-        break;
-      case Token::kSUB:
-        __ fsubs(result, left, right);
-        break;
-      case Token::kMUL:
-        __ fmuls(result, left, right);
-        break;
-      case Token::kDIV:
-        __ fdivs(result, left, right);
-        break;
-      case Token::kMIN:
-        __ fmins(result, left, right);
-        break;
-      case Token::kMAX:
-        __ fmaxs(result, left, right);
-        break;
-      default:
-        UNREACHABLE();
-    }
+  switch (op_kind()) {
+    case Token::kADD:
+      __ faddd(result, left, right);
+      break;
+    case Token::kSUB:
+      __ fsubd(result, left, right);
+      break;
+    case Token::kMUL:
+      __ fmuld(result, left, right);
+      break;
+    case Token::kDIV:
+      __ fdivd(result, left, right);
+      break;
+    default:
+      UNREACHABLE();
   }
 }
 
@@ -4902,13 +4853,259 @@
   return kind() == Token::kEQ ? NOT_ZERO : ZERO;
 }
 
+// SIMD
+
+#define DEFINE_EMIT(Name, Args)                                                \
+  static void Emit##Name(FlowGraphCompiler* compiler, SimdOpInstr* instr,      \
+                         PP_APPLY(PP_UNPACK, Args))
+
+#define SIMD_OP_FLOAT_ARITH(V, Name, op)                                       \
+  V(Float32x4##Name, op##s)                                                    \
+  V(Float64x2##Name, op##d)
+
+#define SIMD_OP_SIMPLE_BINARY(V)                                               \
+  SIMD_OP_FLOAT_ARITH(V, Add, vadd)                                            \
+  SIMD_OP_FLOAT_ARITH(V, Sub, vsub)                                            \
+  SIMD_OP_FLOAT_ARITH(V, Mul, vmul)                                            \
+  SIMD_OP_FLOAT_ARITH(V, Div, vdiv)                                            \
+  SIMD_OP_FLOAT_ARITH(V, Min, vmin)                                            \
+  SIMD_OP_FLOAT_ARITH(V, Max, vmax)                                            \
+  V(Int32x4Add, vaddw)                                                         \
+  V(Int32x4Sub, vsubw)                                                         \
+  V(Int32x4BitAnd, vand)                                                       \
+  V(Int32x4BitOr, vorr)                                                        \
+  V(Int32x4BitXor, veor)                                                       \
+  V(Float32x4Equal, vceqs)                                                     \
+  V(Float32x4GreaterThan, vcgts)                                               \
+  V(Float32x4GreaterThanOrEqual, vcges)
+
+DEFINE_EMIT(SimdBinaryOp, (FRegister result, FRegister left, FRegister right)) {
+  UNIMPLEMENTED();
+}
+
+#define SIMD_OP_SIMPLE_UNARY(V)                                                \
+  SIMD_OP_FLOAT_ARITH(V, Sqrt, vsqrt)                                          \
+  SIMD_OP_FLOAT_ARITH(V, Negate, vneg)                                         \
+  SIMD_OP_FLOAT_ARITH(V, Abs, vabs)                                            \
+  V(Float32x4Reciprocal, VRecps)                                               \
+  V(Float32x4ReciprocalSqrt, VRSqrts)
+
+DEFINE_EMIT(SimdUnaryOp, (FRegister result, FRegister value)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Simd32x4GetSignMask,
+            (Register out, FRegister value, Temp<Register> temp)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(
+    Float32x4FromDoubles,
+    (FRegister r, FRegister v0, FRegister v1, FRegister v2, FRegister v3)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(
+    Float32x4Clamp,
+    (FRegister result, FRegister value, FRegister lower, FRegister upper)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(
+    Float64x2Clamp,
+    (FRegister result, FRegister value, FRegister lower, FRegister upper)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Float32x4With,
+            (FRegister result, FRegister replacement, FRegister value)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Simd32x4ToSimd32x4, (SameAsFirstInput, FRegister value)) {
+  // TODO(dartbug.com/30949) these operations are essentially nop and should
+  // not generate any code. They should be removed from the graph before
+  // code generation.
+}
+
+DEFINE_EMIT(SimdZero, (FRegister v)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Float64x2GetSignMask, (Register out, FRegister value)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Float64x2With,
+            (SameAsFirstInput, FRegister left, FRegister right)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(
+    Int32x4FromInts,
+    (FRegister result, Register v0, Register v1, Register v2, Register v3)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Int32x4FromBools,
+            (FRegister result,
+             Register v0,
+             Register v1,
+             Register v2,
+             Register v3,
+             Temp<Register> temp)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Int32x4GetFlag, (Register result, FRegister value)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Int32x4Select,
+            (FRegister out,
+             FRegister mask,
+             FRegister trueValue,
+             FRegister falseValue,
+             Temp<FRegister> temp)) {
+  UNIMPLEMENTED();
+}
+
+DEFINE_EMIT(Int32x4WithFlag,
+            (SameAsFirstInput, FRegister mask, Register flag)) {
+  UNIMPLEMENTED();
+}
+
+// Map SimdOpInstr::Kind-s to corresponding emit functions. Uses the following
+// format:
+//
+//     CASE(OpA) CASE(OpB) ____(Emitter) - Emitter is used to emit OpA and OpB.
+//     SIMPLE(OpA) - Emitter with name OpA is used to emit OpA.
+//
+#define SIMD_OP_VARIANTS(CASE, ____)                                           \
+  SIMD_OP_SIMPLE_BINARY(CASE)                                                  \
+  CASE(Float32x4ShuffleMix)                                                    \
+  CASE(Int32x4ShuffleMix)                                                      \
+  CASE(Float32x4NotEqual)                                                      \
+  CASE(Float32x4LessThan)                                                      \
+  CASE(Float32x4LessThanOrEqual)                                               \
+  CASE(Float32x4Scale)                                                         \
+  CASE(Float64x2FromDoubles)                                                   \
+  CASE(Float64x2Scale)                                                         \
+  ____(SimdBinaryOp)                                                           \
+  SIMD_OP_SIMPLE_UNARY(CASE)                                                   \
+  CASE(Float32x4GetX)                                                          \
+  CASE(Float32x4GetY)                                                          \
+  CASE(Float32x4GetZ)                                                          \
+  CASE(Float32x4GetW)                                                          \
+  CASE(Int32x4Shuffle)                                                         \
+  CASE(Float32x4Shuffle)                                                       \
+  CASE(Float32x4Splat)                                                         \
+  CASE(Float64x2GetX)                                                          \
+  CASE(Float64x2GetY)                                                          \
+  CASE(Float64x2Splat)                                                         \
+  CASE(Float64x2ToFloat32x4)                                                   \
+  CASE(Float32x4ToFloat64x2)                                                   \
+  ____(SimdUnaryOp)                                                            \
+  CASE(Float32x4GetSignMask)                                                   \
+  CASE(Int32x4GetSignMask)                                                     \
+  ____(Simd32x4GetSignMask)                                                    \
+  CASE(Float32x4FromDoubles)                                                   \
+  ____(Float32x4FromDoubles)                                                   \
+  CASE(Float32x4Zero)                                                          \
+  CASE(Float64x2Zero)                                                          \
+  ____(SimdZero)                                                               \
+  CASE(Float32x4Clamp)                                                         \
+  ____(Float32x4Clamp)                                                         \
+  CASE(Float64x2Clamp)                                                         \
+  ____(Float64x2Clamp)                                                         \
+  CASE(Float32x4WithX)                                                         \
+  CASE(Float32x4WithY)                                                         \
+  CASE(Float32x4WithZ)                                                         \
+  CASE(Float32x4WithW)                                                         \
+  ____(Float32x4With)                                                          \
+  CASE(Float32x4ToInt32x4)                                                     \
+  CASE(Int32x4ToFloat32x4)                                                     \
+  ____(Simd32x4ToSimd32x4)                                                     \
+  CASE(Float64x2GetSignMask)                                                   \
+  ____(Float64x2GetSignMask)                                                   \
+  CASE(Float64x2WithX)                                                         \
+  CASE(Float64x2WithY)                                                         \
+  ____(Float64x2With)                                                          \
+  CASE(Int32x4FromInts)                                                        \
+  ____(Int32x4FromInts)                                                        \
+  CASE(Int32x4FromBools)                                                       \
+  ____(Int32x4FromBools)                                                       \
+  CASE(Int32x4GetFlagX)                                                        \
+  CASE(Int32x4GetFlagY)                                                        \
+  CASE(Int32x4GetFlagZ)                                                        \
+  CASE(Int32x4GetFlagW)                                                        \
+  ____(Int32x4GetFlag)                                                         \
+  CASE(Int32x4Select)                                                          \
+  ____(Int32x4Select)                                                          \
+  CASE(Int32x4WithFlagX)                                                       \
+  CASE(Int32x4WithFlagY)                                                       \
+  CASE(Int32x4WithFlagZ)                                                       \
+  CASE(Int32x4WithFlagW)                                                       \
+  ____(Int32x4WithFlag)
+
 LocationSummary* SimdOpInstr::MakeLocationSummary(Zone* zone, bool opt) const {
+  switch (kind()) {
+#define CASE(Name, ...) case k##Name:
+#define EMIT(Name)                                                             \
+  return MakeLocationSummaryFromEmitter(zone, this, &Emit##Name);
+    SIMD_OP_VARIANTS(CASE, EMIT)
+#undef CASE
+#undef EMIT
+    case kIllegalSimdOp:
+      UNREACHABLE();
+      break;
+  }
   UNREACHABLE();
   return NULL;
 }
 
 void SimdOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
+  switch (kind()) {
+#define CASE(Name, ...) case k##Name:
+#define EMIT(Name)                                                             \
+  InvokeEmitter(compiler, this, &Emit##Name);                                  \
+  break;
+    SIMD_OP_VARIANTS(CASE, EMIT)
+#undef CASE
+#undef EMIT
+    case kIllegalSimdOp:
+      UNREACHABLE();
+      break;
+  }
+}
+
+#undef DEFINE_EMIT
+
+LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone,
+                                                     bool opt) const {
+  ASSERT((kind() == MathUnaryInstr::kSqrt) ||
+         (kind() == MathUnaryInstr::kDoubleSquare));
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_out(0, Location::RequiresFpuRegister());
+  return summary;
+}
+
+void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (kind() == MathUnaryInstr::kSqrt) {
+    const FRegister val = locs()->in(0).fpu_reg();
+    const FRegister result = locs()->out(0).fpu_reg();
+    __ fsqrtd(result, val);
+  } else if (kind() == MathUnaryInstr::kDoubleSquare) {
+    const FRegister val = locs()->in(0).fpu_reg();
+    const FRegister result = locs()->out(0).fpu_reg();
+    __ fmuld(result, val, val);
+  } else {
+    UNREACHABLE();
+  }
 }
 
 LocationSummary* CaseInsensitiveCompareInstr::MakeLocationSummary(
@@ -5052,53 +5249,7 @@
 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   const FRegister result = locs()->out(0).fpu_reg();
   const FRegister value = locs()->in(0).fpu_reg();
-  if (representation() == kUnboxedDouble) {
-    switch (op_kind()) {
-      case Token::kABS:
-        __ fabsd(result, value);
-        break;
-      case Token::kNEGATE:
-        __ fnegd(result, value);
-        break;
-      case Token::kSQRT:
-        __ fsqrtd(result, value);
-        break;
-      case Token::kSQUARE:
-        __ fmuld(result, value, value);
-        break;
-      default:
-        UNREACHABLE();
-    }
-  } else {
-    ASSERT(representation() == kUnboxedFloat);
-    switch (op_kind()) {
-      case Token::kABS:
-        __ fabss(result, value);
-        break;
-      case Token::kNEGATE:
-        __ fnegs(result, value);
-        break;
-      case Token::kRECIPROCAL:
-        __ li(TMP, 1);
-        __ fcvtsw(FTMP, TMP);
-        __ fdivs(result, FTMP, value);
-        break;
-      case Token::kRECIPROCAL_SQRT:
-        __ li(TMP, 1);
-        __ fcvtsw(FTMP, TMP);
-        __ fdivs(result, FTMP, value);
-        __ fsqrts(result, result);
-        break;
-      case Token::kSQRT:
-        __ fsqrts(result, value);
-        break;
-      case Token::kSQUARE:
-        __ fmuls(result, value, value);
-        break;
-      default:
-        UNREACHABLE();
-    }
-  }
+  __ fnegd(result, value);
 }
 
 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone,
@@ -5246,6 +5397,16 @@
   __ bne(TMP, TMP2, deopt);
 }
 
+LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone,
+                                                          bool opt) const {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone,
                                                          bool opt) const {
   const intptr_t kNumInputs = 1;
@@ -5280,45 +5441,6 @@
   __ fcvtds(result, value);
 }
 
-LocationSummary* FloatCompareInstr::MakeLocationSummary(Zone* zone,
-                                                        bool opt) const {
-  const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = 0;
-  LocationSummary* result = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  result->set_in(0, Location::RequiresFpuRegister());
-  result->set_in(1, Location::RequiresFpuRegister());
-  result->set_out(0, Location::RequiresRegister());
-  return result;
-}
-
-void FloatCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const FRegister lhs = locs()->in(0).fpu_reg();
-  const FRegister rhs = locs()->in(1).fpu_reg();
-  const Register result = locs()->out(0).reg();
-
-  switch (op_kind()) {
-    case Token::kEQ:
-      __ feqs(result, lhs, rhs);  // lhs op rhs ? 1 : 0
-      break;
-    case Token::kLT:
-      __ flts(result, lhs, rhs);
-      break;
-    case Token::kLTE:
-      __ fles(result, lhs, rhs);
-      break;
-    case Token::kGT:
-      __ fgts(result, lhs, rhs);
-      break;
-    case Token::kGTE:
-      __ fges(result, lhs, rhs);
-      break;
-    default:
-      UNREACHABLE();
-  }
-  __ neg(result, result);  // lhs op rhs ? -1 : 0
-}
-
 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone,
                                                                bool opt) const {
   ASSERT((InputCount() == 1) || (InputCount() == 2));
@@ -5400,119 +5522,6 @@
   }
 }
 
-LocationSummary* UnboxLaneInstr::MakeLocationSummary(Zone* zone,
-                                                     bool opt) const {
-  const intptr_t kNumInputs = 1;
-  LocationSummary* summary =
-      new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall);
-  summary->set_in(0, Location::RequiresRegister());
-  switch (representation()) {
-    case kUnboxedDouble:
-    case kUnboxedFloat:
-      summary->set_out(0, Location::RequiresFpuRegister());
-      break;
-    case kUnboxedInt32:
-      summary->set_out(0, Location::RequiresRegister());
-      break;
-    default:
-      UNREACHABLE();
-  }
-  return summary;
-}
-
-void UnboxLaneInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Register in = locs()->in(0).reg();
-  switch (representation()) {
-    case kUnboxedDouble:
-      __ fld(locs()->out(0).fpu_reg(),
-             compiler::FieldAddress(
-                 in, compiler::target::Float64x2::value_offset() +
-                         lane() * sizeof(double)));
-      break;
-    case kUnboxedFloat:
-      __ flw(locs()->out(0).fpu_reg(),
-             compiler::FieldAddress(
-                 in, compiler::target::Float32x4::value_offset() +
-                         lane() * sizeof(float)));
-      break;
-    case kUnboxedInt32:
-      __ lw(
-          locs()->out(0).reg(),
-          compiler::FieldAddress(in, compiler::target::Int32x4::value_offset() +
-                                         lane() * sizeof(int32_t)));
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-LocationSummary* BoxLanesInstr::MakeLocationSummary(Zone* zone,
-                                                    bool opt) const {
-  const intptr_t kNumInputs = InputCount();
-  LocationSummary* summary = new (zone)
-      LocationSummary(zone, kNumInputs, 0, LocationSummary::kCallOnSlowPath);
-  switch (from_representation()) {
-    case kUnboxedDouble:
-      summary->set_in(0, Location::RequiresFpuRegister());
-      summary->set_in(1, Location::RequiresFpuRegister());
-      break;
-    case kUnboxedFloat:
-      summary->set_in(0, Location::RequiresFpuRegister());
-      summary->set_in(1, Location::RequiresFpuRegister());
-      summary->set_in(2, Location::RequiresFpuRegister());
-      summary->set_in(3, Location::RequiresFpuRegister());
-      break;
-    case kUnboxedInt32:
-      summary->set_in(0, Location::RequiresRegister());
-      summary->set_in(1, Location::RequiresRegister());
-      summary->set_in(2, Location::RequiresRegister());
-      summary->set_in(3, Location::RequiresRegister());
-      break;
-    default:
-      UNREACHABLE();
-  }
-  summary->set_out(0, Location::RequiresRegister());
-  return summary;
-}
-
-void BoxLanesInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Register result = locs()->out(0).reg();
-  switch (from_representation()) {
-    case kUnboxedDouble:
-      BoxAllocationSlowPath::Allocate(compiler, this,
-                                      compiler->float64x2_class(), result, TMP);
-      for (intptr_t i = 0; i < 2; i++) {
-        __ fsd(locs()->in(i).fpu_reg(),
-               compiler::FieldAddress(
-                   result, compiler::target::Float64x2::value_offset() +
-                               i * sizeof(double)));
-      }
-      break;
-    case kUnboxedFloat:
-      BoxAllocationSlowPath::Allocate(compiler, this,
-                                      compiler->float32x4_class(), result, TMP);
-      for (intptr_t i = 0; i < 4; i++) {
-        __ fsw(locs()->in(i).fpu_reg(),
-               compiler::FieldAddress(
-                   result, compiler::target::Float32x4::value_offset() +
-                               i * sizeof(float)));
-      }
-      break;
-    case kUnboxedInt32:
-      BoxAllocationSlowPath::Allocate(compiler, this, compiler->int32x4_class(),
-                                      result, TMP);
-      for (intptr_t i = 0; i < 4; i++) {
-        __ sw(locs()->in(i).reg(),
-              compiler::FieldAddress(result,
-                                     compiler::target::Int32x4::value_offset() +
-                                         i * sizeof(int32_t)));
-      }
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone,
                                                        bool opt) const {
   const intptr_t kNumInputs = 2;
@@ -7606,36 +7615,6 @@
   __ xori(result, input, compiler::target::ObjectAlignment::kBoolValueMask);
 }
 
-LocationSummary* BoolToIntInstr::MakeLocationSummary(Zone* zone,
-                                                     bool opt) const {
-  return LocationSummary::Make(zone, 1, Location::RequiresRegister(),
-                               LocationSummary::kNoCall);
-}
-
-void BoolToIntInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const Register input = locs()->in(0).reg();
-  const Register result = locs()->out(0).reg();
-  __ LoadObject(TMP, Bool::True());
-  __ xor_(TMP, TMP, input);
-  __ seqz(TMP, TMP);
-  __ neg(result, TMP);
-}
-
-LocationSummary* IntToBoolInstr::MakeLocationSummary(Zone* zone,
-                                                     bool opt) const {
-  return LocationSummary::Make(zone, 1, Location::RequiresRegister(),
-                               LocationSummary::kNoCall);
-}
-
-void IntToBoolInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const Register input = locs()->in(0).reg();
-  const Register result = locs()->out(0).reg();
-  __ seqz(result, input);
-  __ slli(result, result, kBoolValueBitPosition);
-  __ add(result, result, NULL_REG);
-  __ addi(result, result, kTrueOffsetFromNull);
-}
-
 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone,
                                                           bool opt) const {
   const intptr_t kNumInputs = (type_arguments() != nullptr) ? 1 : 0;
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index c91ed77..b7bca3f 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -567,12 +567,7 @@
       __ LoadObject(destination.reg(), value_);
     }
   } else if (destination.IsFpuRegister()) {
-    if (representation() == kUnboxedFloat) {
-      __ LoadSImmediate(destination.fpu_reg(), Double::Cast(value_).value());
-    } else {
-      ASSERT(representation() == kUnboxedDouble);
-      __ LoadDImmediate(destination.fpu_reg(), Double::Cast(value_).value());
-    }
+    __ LoadDImmediate(destination.fpu_reg(), Double::Cast(value_).value());
   } else if (destination.IsDoubleStackSlot()) {
     __ LoadDImmediate(FpuTMP, Double::Cast(value_).value());
     __ movsd(LocationToStackSlotAddress(destination), FpuTMP);
@@ -5048,6 +5043,35 @@
 
 #undef DEFINE_EMIT
 
+LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone,
+                                                     bool opt) const {
+  ASSERT((kind() == MathUnaryInstr::kSqrt) ||
+         (kind() == MathUnaryInstr::kDoubleSquare));
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  if (kind() == MathUnaryInstr::kDoubleSquare) {
+    summary->set_out(0, Location::SameAsFirstInput());
+  } else {
+    summary->set_out(0, Location::RequiresFpuRegister());
+  }
+  return summary;
+}
+
+void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  if (kind() == MathUnaryInstr::kSqrt) {
+    __ sqrtsd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg());
+  } else if (kind() == MathUnaryInstr::kDoubleSquare) {
+    XmmRegister value_reg = locs()->in(0).fpu_reg();
+    __ mulsd(value_reg, value_reg);
+    ASSERT(value_reg == locs()->out(0).fpu_reg());
+  } else {
+    UNREACHABLE();
+  }
+}
+
 LocationSummary* CaseInsensitiveCompareInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
@@ -5105,39 +5129,14 @@
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresFpuRegister());
-  summary->set_out(0, Location::RequiresFpuRegister());
+  summary->set_out(0, Location::SameAsFirstInput());
   return summary;
 }
 
 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(representation() == kUnboxedDouble);
-  XmmRegister result = locs()->out(0).fpu_reg();
   XmmRegister value = locs()->in(0).fpu_reg();
-  switch (op_kind()) {
-    case Token::kNEGATE:
-      __ DoubleNegate(result, value);
-      break;
-    case Token::kSQRT:
-      __ sqrtsd(result, value);
-      break;
-    case Token::kSQUARE:
-      if (result != value) {
-        __ movsd(result, value);
-      }
-      __ mulsd(result, value);
-      break;
-    case Token::kTRUNCATE:
-      __ roundsd(result, value, compiler::Assembler::kRoundToZero);
-      break;
-    case Token::kFLOOR:
-      __ roundsd(result, value, compiler::Assembler::kRoundDown);
-      break;
-    case Token::kCEILING:
-      __ roundsd(result, value, compiler::Assembler::kRoundUp);
-      break;
-    default:
-      UNREACHABLE();
-  }
+  ASSERT(locs()->out(0).fpu_reg() == value);
+  __ DoubleNegate(value, value);
 }
 
 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone,
@@ -5362,6 +5361,40 @@
   __ SmiTag(result);
 }
 
+LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone,
+                                                          bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* result = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  result->set_in(0, Location::RequiresFpuRegister());
+  result->set_out(0, Location::RequiresFpuRegister());
+  return result;
+}
+
+void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  XmmRegister value = locs()->in(0).fpu_reg();
+  XmmRegister result = locs()->out(0).fpu_reg();
+  if (value != result) {
+    // Clear full register to avoid false dependency due to
+    // a partial access to XMM register in roundsd instruction.
+    __ xorps(result, result);
+  }
+  switch (recognized_kind()) {
+    case MethodRecognizer::kDoubleTruncateToDouble:
+      __ roundsd(result, value, compiler::Assembler::kRoundToZero);
+      break;
+    case MethodRecognizer::kDoubleFloorToDouble:
+      __ roundsd(result, value, compiler::Assembler::kRoundDown);
+      break;
+    case MethodRecognizer::kDoubleCeilToDouble:
+      __ roundsd(result, value, compiler::Assembler::kRoundUp);
+      break;
+    default:
+      UNREACHABLE();
+  }
+}
+
 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone,
                                                          bool opt) const {
   const intptr_t kNumInputs = 1;
@@ -5392,16 +5425,6 @@
   __ cvtss2sd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg());
 }
 
-LocationSummary* FloatCompareInstr::MakeLocationSummary(Zone* zone,
-                                                        bool opt) const {
-  UNREACHABLE();
-  return NULL;
-}
-
-void FloatCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
-}
-
 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone,
                                                                bool opt) const {
   // Calling convention on x64 uses XMM0 and XMM1 to pass the first two
@@ -5627,26 +5650,6 @@
   }
 }
 
-LocationSummary* UnboxLaneInstr::MakeLocationSummary(Zone* zone,
-                                                     bool opt) const {
-  UNREACHABLE();
-  return NULL;
-}
-
-void UnboxLaneInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
-}
-
-LocationSummary* BoxLanesInstr::MakeLocationSummary(Zone* zone,
-                                                    bool opt) const {
-  UNREACHABLE();
-  return NULL;
-}
-
-void BoxLanesInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
-}
-
 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone,
                                                        bool opt) const {
   const intptr_t kNumInputs = 2;
@@ -7009,26 +7012,6 @@
                       compiler::target::ObjectAlignment::kBoolValueMask));
 }
 
-LocationSummary* BoolToIntInstr::MakeLocationSummary(Zone* zone,
-                                                     bool opt) const {
-  UNREACHABLE();
-  return NULL;
-}
-
-void BoolToIntInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
-}
-
-LocationSummary* IntToBoolInstr::MakeLocationSummary(Zone* zone,
-                                                     bool opt) const {
-  UNREACHABLE();
-  return NULL;
-}
-
-void IntToBoolInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
-}
-
 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone,
                                                           bool opt) const {
   const intptr_t kNumInputs = (type_arguments() != nullptr) ? 1 : 0;
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index 7fdd085..dd8279d 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -78,7 +78,6 @@
             "Max. number of inlined calls per depth");
 DEFINE_FLAG(bool, print_inlining_tree, false, "Print inlining tree");
 
-DECLARE_FLAG(bool, enable_simd_inline);
 DECLARE_FLAG(int, max_deoptimization_counter_threshold);
 DECLARE_FLAG(bool, print_flow_graph);
 DECLARE_FLAG(bool, print_flow_graph_optimized);
@@ -808,8 +807,7 @@
   for (intptr_t i = 0; i < defns->length(); ++i) {
     ConstantInstr* constant = (*defns)[i]->AsConstant();
     if (constant != nullptr && constant->HasUses()) {
-      constant->ReplaceUsesWith(caller_graph->GetConstant(
-          constant->value(), constant->representation()));
+      constant->ReplaceUsesWith(caller_graph->GetConstant(constant->value()));
     }
   }
 
@@ -817,8 +815,7 @@
   for (intptr_t i = 0; i < defns->length(); ++i) {
     ConstantInstr* constant = (*defns)[i]->AsConstant();
     if (constant != nullptr && constant->HasUses()) {
-      constant->ReplaceUsesWith(caller_graph->GetConstant(
-          constant->value(), constant->representation()));
+      constant->ReplaceUsesWith(caller_graph->GetConstant(constant->value()));
     }
 
     SpecialParameterInstr* param = (*defns)[i]->AsSpecialParameter();
@@ -3540,585 +3537,6 @@
   return true;
 }
 
-class SimdLowering : public ValueObject {
- public:
-  SimdLowering(FlowGraph* flow_graph,
-               Instruction* call,
-               GraphEntryInstr* graph_entry,
-               FunctionEntryInstr** entry,
-               Instruction** last,
-               Definition** result)
-      : flow_graph_(flow_graph),
-        call_(call),
-        graph_entry_(graph_entry),
-        entry_(entry),
-        last_(last),
-        result_(result) {
-    *entry_ = new (zone())
-        FunctionEntryInstr(graph_entry_, flow_graph_->allocate_block_id(),
-                           call_->GetBlock()->try_index(), call_->deopt_id());
-    *last = *entry_;
-  }
-
-  bool TryInline(MethodRecognizer::Kind kind) {
-    switch (kind) {
-      // ==== Int32x4 ====
-      case MethodRecognizer::kInt32x4FromInts:
-        UnboxScalar(0, kUnboxedInt32, 4);
-        UnboxScalar(1, kUnboxedInt32, 4);
-        UnboxScalar(2, kUnboxedInt32, 4);
-        UnboxScalar(3, kUnboxedInt32, 4);
-        Gather(4);
-        BoxVector(kUnboxedInt32, 4);
-        return true;
-      case MethodRecognizer::kInt32x4FromBools:
-        UnboxBool(0, 4);
-        UnboxBool(1, 4);
-        UnboxBool(2, 4);
-        UnboxBool(3, 4);
-        Gather(4);
-        BoxVector(kUnboxedInt32, 4);
-        return true;
-      case MethodRecognizer::kInt32x4GetFlagX:
-        UnboxVector(0, kUnboxedInt32, kMintCid, 4);
-        IntToBool();
-        Return(0);
-        return true;
-      case MethodRecognizer::kInt32x4GetFlagY:
-        UnboxVector(0, kUnboxedInt32, kMintCid, 4);
-        IntToBool();
-        Return(1);
-        return true;
-      case MethodRecognizer::kInt32x4GetFlagZ:
-        UnboxVector(0, kUnboxedInt32, kMintCid, 4);
-        IntToBool();
-        Return(2);
-        return true;
-      case MethodRecognizer::kInt32x4GetFlagW:
-        UnboxVector(0, kUnboxedInt32, kMintCid, 4);
-        IntToBool();
-        Return(3);
-        return true;
-      case MethodRecognizer::kInt32x4WithFlagX:
-        UnboxVector(0, kUnboxedInt32, kMintCid, 4);
-        UnboxBool(1, 4);
-        With(0);
-        BoxVector(kUnboxedInt32, 4);
-        return true;
-      case MethodRecognizer::kInt32x4WithFlagY:
-        UnboxVector(0, kUnboxedInt32, kMintCid, 4);
-        UnboxBool(1, 4);
-        With(1);
-        BoxVector(kUnboxedInt32, 4);
-        return true;
-      case MethodRecognizer::kInt32x4WithFlagZ:
-        UnboxVector(0, kUnboxedInt32, kMintCid, 4);
-        UnboxBool(1, 4);
-        With(2);
-        BoxVector(kUnboxedInt32, 4);
-        return true;
-      case MethodRecognizer::kInt32x4WithFlagW:
-        UnboxVector(0, kUnboxedInt32, kMintCid, 4);
-        UnboxBool(1, 4);
-        With(3);
-        BoxVector(kUnboxedInt32, 4);
-        return true;
-      case MethodRecognizer::kInt32x4Shuffle: {
-        Definition* mask_definition =
-            call_->ArgumentAt(call_->ArgumentCount() - 1);
-        intptr_t mask = 0;
-        if (!CheckMask(mask_definition, &mask)) {
-          return false;
-        }
-        UnboxVector(0, kUnboxedInt32, kMintCid, 4);
-        Shuffle(mask);
-        BoxVector(kUnboxedInt32, 4);
-        return true;
-      }
-      case MethodRecognizer::kInt32x4ShuffleMix: {
-        Definition* mask_definition =
-            call_->ArgumentAt(call_->ArgumentCount() - 1);
-        intptr_t mask = 0;
-        if (!CheckMask(mask_definition, &mask)) {
-          return false;
-        }
-        UnboxVector(0, kUnboxedInt32, kMintCid, 4);
-        UnboxVector(1, kUnboxedInt32, kMintCid, 4);
-        ShuffleMix(mask);
-        BoxVector(kUnboxedInt32, 4);
-        return true;
-      }
-      case MethodRecognizer::kInt32x4GetSignMask:
-      case MethodRecognizer::kInt32x4Select:
-        // TODO(riscv)
-        return false;
-
-      // ==== Float32x4 ====
-      case MethodRecognizer::kFloat32x4Abs:
-        Float32x4Unary(Token::kABS);
-        return true;
-      case MethodRecognizer::kFloat32x4Negate:
-        Float32x4Unary(Token::kNEGATE);
-        return true;
-      case MethodRecognizer::kFloat32x4Sqrt:
-        Float32x4Unary(Token::kSQRT);
-        return true;
-      case MethodRecognizer::kFloat32x4Reciprocal:
-        Float32x4Unary(Token::kRECIPROCAL);
-        return true;
-      case MethodRecognizer::kFloat32x4ReciprocalSqrt:
-        Float32x4Unary(Token::kRECIPROCAL_SQRT);
-        return true;
-      case MethodRecognizer::kFloat32x4GetSignMask:
-        // TODO(riscv)
-        return false;
-      case MethodRecognizer::kFloat32x4Equal:
-        Float32x4Compare(Token::kEQ);
-        return true;
-      case MethodRecognizer::kFloat32x4GreaterThan:
-        Float32x4Compare(Token::kGT);
-        return true;
-      case MethodRecognizer::kFloat32x4GreaterThanOrEqual:
-        Float32x4Compare(Token::kGTE);
-        return true;
-      case MethodRecognizer::kFloat32x4LessThan:
-        Float32x4Compare(Token::kLT);
-        return true;
-      case MethodRecognizer::kFloat32x4LessThanOrEqual:
-        Float32x4Compare(Token::kLTE);
-        return true;
-      case MethodRecognizer::kFloat32x4Add:
-        Float32x4Binary(Token::kADD);
-        return true;
-      case MethodRecognizer::kFloat32x4Sub:
-        Float32x4Binary(Token::kSUB);
-        return true;
-      case MethodRecognizer::kFloat32x4Mul:
-        Float32x4Binary(Token::kMUL);
-        return true;
-      case MethodRecognizer::kFloat32x4Div:
-        Float32x4Binary(Token::kDIV);
-        return true;
-      case MethodRecognizer::kFloat32x4Min:
-        Float32x4Binary(Token::kMIN);
-        return true;
-      case MethodRecognizer::kFloat32x4Max:
-        Float32x4Binary(Token::kMAX);
-        return true;
-      case MethodRecognizer::kFloat32x4Scale:
-        UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
-        UnboxScalar(1, kUnboxedFloat, 4);
-        BinaryDoubleOp(Token::kMUL, kUnboxedFloat, 4);
-        BoxVector(kUnboxedFloat, 4);
-        return true;
-      case MethodRecognizer::kFloat32x4Splat:
-        UnboxScalar(0, kUnboxedFloat, 4);
-        Splat(4);
-        BoxVector(kUnboxedFloat, 4);
-        return true;
-      case MethodRecognizer::kFloat32x4WithX:
-        UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
-        UnboxScalar(1, kUnboxedFloat, 4);
-        With(0);
-        BoxVector(kUnboxedFloat, 4);
-        return true;
-      case MethodRecognizer::kFloat32x4WithY:
-        UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
-        UnboxScalar(1, kUnboxedFloat, 4);
-        With(1);
-        BoxVector(kUnboxedFloat, 4);
-        return true;
-      case MethodRecognizer::kFloat32x4WithZ:
-        UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
-        UnboxScalar(1, kUnboxedFloat, 4);
-        With(2);
-        BoxVector(kUnboxedFloat, 4);
-        return true;
-      case MethodRecognizer::kFloat32x4WithW:
-        UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
-        UnboxScalar(1, kUnboxedFloat, 4);
-        With(3);
-        BoxVector(kUnboxedFloat, 4);
-        return true;
-      case MethodRecognizer::kFloat32x4Zero:
-        UnboxDoubleZero(kUnboxedFloat, 4);
-        BoxVector(kUnboxedFloat, 4);
-        return true;
-      case MethodRecognizer::kFloat32x4FromDoubles:
-        UnboxScalar(0, kUnboxedFloat, 4);
-        UnboxScalar(1, kUnboxedFloat, 4);
-        UnboxScalar(2, kUnboxedFloat, 4);
-        UnboxScalar(3, kUnboxedFloat, 4);
-        Gather(4);
-        BoxVector(kUnboxedFloat, 4);
-        return true;
-      case MethodRecognizer::kFloat32x4GetX:
-        UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
-        BoxScalar(0, kUnboxedFloat);
-        return true;
-      case MethodRecognizer::kFloat32x4GetY:
-        UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
-        BoxScalar(1, kUnboxedFloat);
-        return true;
-      case MethodRecognizer::kFloat32x4GetZ:
-        UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
-        BoxScalar(2, kUnboxedFloat);
-        return true;
-      case MethodRecognizer::kFloat32x4GetW:
-        UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
-        BoxScalar(3, kUnboxedFloat);
-        return true;
-      case MethodRecognizer::kFloat32x4Shuffle: {
-        Definition* mask_definition =
-            call_->ArgumentAt(call_->ArgumentCount() - 1);
-        intptr_t mask = 0;
-        if (!CheckMask(mask_definition, &mask)) {
-          return false;
-        }
-        UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
-        Shuffle(mask);
-        BoxVector(kUnboxedFloat, 4);
-        return true;
-      }
-      case MethodRecognizer::kFloat32x4ShuffleMix: {
-        Definition* mask_definition =
-            call_->ArgumentAt(call_->ArgumentCount() - 1);
-        intptr_t mask = 0;
-        if (!CheckMask(mask_definition, &mask)) {
-          return false;
-        }
-        UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
-        UnboxVector(1, kUnboxedFloat, kDoubleCid, 4);
-        ShuffleMix(mask);
-        BoxVector(kUnboxedFloat, 4);
-        return true;
-      }
-
-      // ==== Float64x2 ====
-      case MethodRecognizer::kFloat64x2Abs:
-        Float64x2Unary(Token::kABS);
-        return true;
-      case MethodRecognizer::kFloat64x2Negate:
-        Float64x2Unary(Token::kNEGATE);
-        return true;
-      case MethodRecognizer::kFloat64x2Sqrt:
-        Float64x2Unary(Token::kSQRT);
-        return true;
-      case MethodRecognizer::kFloat64x2Add:
-        Float64x2Binary(Token::kADD);
-        return true;
-      case MethodRecognizer::kFloat64x2Sub:
-        Float64x2Binary(Token::kSUB);
-        return true;
-      case MethodRecognizer::kFloat64x2Mul:
-        Float64x2Binary(Token::kMUL);
-        return true;
-      case MethodRecognizer::kFloat64x2Div:
-        Float64x2Binary(Token::kDIV);
-        return true;
-      case MethodRecognizer::kFloat64x2Min:
-        Float64x2Binary(Token::kMIN);
-        return true;
-      case MethodRecognizer::kFloat64x2Max:
-        Float64x2Binary(Token::kMAX);
-        return true;
-      case MethodRecognizer::kFloat64x2Scale:
-        UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
-        UnboxScalar(1, kUnboxedDouble, 2);
-        BinaryDoubleOp(Token::kMUL, kUnboxedDouble, 2);
-        BoxVector(kUnboxedDouble, 2);
-        return true;
-      case MethodRecognizer::kFloat64x2Splat:
-        UnboxScalar(0, kUnboxedDouble, 2);
-        Splat(2);
-        BoxVector(kUnboxedDouble, 2);
-        return true;
-      case MethodRecognizer::kFloat64x2WithX:
-        UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
-        UnboxScalar(1, kUnboxedDouble, 2);
-        With(0);
-        BoxVector(kUnboxedDouble, 2);
-        return true;
-      case MethodRecognizer::kFloat64x2WithY:
-        UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
-        UnboxScalar(1, kUnboxedDouble, 2);
-        With(1);
-        BoxVector(kUnboxedDouble, 2);
-        return true;
-      case MethodRecognizer::kFloat64x2Zero:
-        UnboxDoubleZero(kUnboxedDouble, 2);
-        BoxVector(kUnboxedDouble, 2);
-        return true;
-      case MethodRecognizer::kFloat64x2FromDoubles:
-        UnboxScalar(0, kUnboxedDouble, 2);
-        UnboxScalar(1, kUnboxedDouble, 2);
-        Gather(2);
-        BoxVector(kUnboxedDouble, 2);
-        return true;
-      case MethodRecognizer::kFloat64x2GetX:
-        UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
-        BoxScalar(0, kUnboxedDouble);
-        return true;
-      case MethodRecognizer::kFloat64x2GetY:
-        UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
-        BoxScalar(1, kUnboxedDouble);
-        return true;
-
-      // Mixed
-      case MethodRecognizer::kFloat32x4ToFloat64x2: {
-        UnboxVector(0, kUnboxedFloat, kDoubleCid, 4, 1);
-        Float32x4ToFloat64x2();
-        BoxVector(kUnboxedDouble, 2);
-        return true;
-      }
-      case MethodRecognizer::kFloat64x2ToFloat32x4: {
-        UnboxVector(0, kUnboxedDouble, kDoubleCid, 2, 1);
-        Float64x2ToFloat32x4();
-        BoxVector(kUnboxedFloat, 4);
-        return true;
-      }
-      case MethodRecognizer::kInt32x4ToFloat32x4:
-        UnboxVector(0, kUnboxedInt32, kMintCid, 4, 1);
-        Int32x4ToFloat32x4();
-        BoxVector(kUnboxedFloat, 4);
-        return true;
-      case MethodRecognizer::kFloat32x4ToInt32x4:
-        UnboxVector(0, kUnboxedFloat, kDoubleCid, 4, 1);
-        Float32x4ToInt32x4();
-        BoxVector(kUnboxedInt32, 4);
-        return true;
-      default:
-        return false;
-    }
-  }
-
- private:
-  void Float32x4Unary(Token::Kind op) {
-    UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
-    UnaryDoubleOp(op, kUnboxedFloat, 4);
-    BoxVector(kUnboxedFloat, 4);
-  }
-  void Float32x4Binary(Token::Kind op) {
-    UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
-    UnboxVector(1, kUnboxedFloat, kDoubleCid, 4);
-    BinaryDoubleOp(op, kUnboxedFloat, 4);
-    BoxVector(kUnboxedFloat, 4);
-  }
-  void Float32x4Compare(Token::Kind op) {
-    UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
-    UnboxVector(1, kUnboxedFloat, kDoubleCid, 4);
-    FloatCompare(op);
-    BoxVector(kUnboxedInt32, 4);
-  }
-  void Float64x2Unary(Token::Kind op) {
-    UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
-    UnaryDoubleOp(op, kUnboxedDouble, 2);
-    BoxVector(kUnboxedDouble, 2);
-  }
-  void Float64x2Binary(Token::Kind op) {
-    UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
-    UnboxVector(1, kUnboxedDouble, kDoubleCid, 2);
-    BinaryDoubleOp(op, kUnboxedDouble, 2);
-    BoxVector(kUnboxedDouble, 2);
-  }
-
-  void UnboxVector(intptr_t i,
-                   Representation rep,
-                   intptr_t cid,
-                   intptr_t n,
-                   intptr_t type_args = 0) {
-    Definition* arg = call_->ArgumentAt(i + type_args);
-    if (CompilerState::Current().is_aot()) {
-      // Add null-checks in case of the arguments are known to be compatible
-      // but they are possibly nullable.
-      // By inserting the null-check, we can allow the unbox instruction later
-      // inserted to be non-speculative.
-      arg = AddDefinition(new (zone()) CheckNullInstr(
-          new (zone()) Value(arg), Symbols::SecondArg(), call_->deopt_id(),
-          call_->source(), CheckNullInstr::kArgumentError));
-    }
-    for (intptr_t lane = 0; lane < n; lane++) {
-      in_[i][lane] = AddDefinition(
-          new (zone()) UnboxLaneInstr(new (zone()) Value(arg), lane, rep, cid));
-    }
-  }
-
-  void UnboxScalar(intptr_t i,
-                   Representation rep,
-                   intptr_t n,
-                   intptr_t type_args = 0) {
-    Definition* arg = call_->ArgumentAt(i + type_args);
-    if (CompilerState::Current().is_aot()) {
-      // Add null-checks in case of the arguments are known to be compatible
-      // but they are possibly nullable.
-      // By inserting the null-check, we can allow the unbox instruction later
-      // inserted to be non-speculative.
-      arg = AddDefinition(new (zone()) CheckNullInstr(
-          new (zone()) Value(arg), Symbols::SecondArg(), call_->deopt_id(),
-          call_->source(), CheckNullInstr::kArgumentError));
-    }
-    Definition* unbox = AddDefinition(
-        UnboxInstr::Create(rep, new (zone()) Value(arg), DeoptId::kNone,
-                           Instruction::kNotSpeculative));
-    for (intptr_t lane = 0; lane < n; lane++) {
-      in_[i][lane] = unbox;
-    }
-  }
-
-  void UnboxBool(intptr_t i, intptr_t n) {
-    Definition* unbox = AddDefinition(new (zone()) BoolToIntInstr(
-        call_->ArgumentValueAt(i)->CopyWithType(zone())));
-    for (intptr_t lane = 0; lane < n; lane++) {
-      in_[i][lane] = unbox;
-    }
-  }
-
-  void UnboxDoubleZero(Representation rep, intptr_t n) {
-    Definition* zero = flow_graph_->GetConstant(
-        Double::ZoneHandle(Double::NewCanonical(0.0)), rep);
-    for (intptr_t lane = 0; lane < n; lane++) {
-      op_[lane] = zero;
-    }
-  }
-
-  void UnaryDoubleOp(Token::Kind op, Representation rep, intptr_t n) {
-    for (intptr_t lane = 0; lane < n; lane++) {
-      op_[lane] = AddDefinition(new (zone()) UnaryDoubleOpInstr(
-          op, new (zone()) Value(in_[0][lane]), call_->deopt_id(),
-          Instruction::kNotSpeculative, rep));
-    }
-  }
-
-  void BinaryDoubleOp(Token::Kind op, Representation rep, intptr_t n) {
-    for (intptr_t lane = 0; lane < n; lane++) {
-      op_[lane] = AddDefinition(new (zone()) BinaryDoubleOpInstr(
-          op, new (zone()) Value(in_[0][lane]),
-          new (zone()) Value(in_[1][lane]), call_->deopt_id(), call_->source(),
-          Instruction::kNotSpeculative, rep));
-    }
-  }
-
-  void FloatCompare(Token::Kind op) {
-    for (intptr_t lane = 0; lane < 4; lane++) {
-      op_[lane] = AddDefinition(
-          new (zone()) FloatCompareInstr(op, new (zone()) Value(in_[0][lane]),
-                                         new (zone()) Value(in_[1][lane])));
-    }
-  }
-
-  void With(intptr_t i) {
-    for (intptr_t lane = 0; lane < 4; lane++) {
-      op_[lane] = in_[0][lane];
-    }
-    op_[i] = in_[1][0];
-  }
-  void Splat(intptr_t n) {
-    for (intptr_t lane = 0; lane < n; lane++) {
-      op_[lane] = in_[0][0];
-    }
-  }
-  void Gather(intptr_t n) {
-    for (intptr_t lane = 0; lane < n; lane++) {
-      op_[lane] = in_[lane][0];
-    }
-  }
-  void Shuffle(intptr_t mask) {
-    op_[0] = in_[0][(mask >> 0) & 3];
-    op_[1] = in_[0][(mask >> 2) & 3];
-    op_[2] = in_[0][(mask >> 4) & 3];
-    op_[3] = in_[0][(mask >> 6) & 3];
-  }
-  void ShuffleMix(intptr_t mask) {
-    op_[0] = in_[0][(mask >> 0) & 3];
-    op_[1] = in_[0][(mask >> 2) & 3];
-    op_[2] = in_[1][(mask >> 4) & 3];
-    op_[3] = in_[1][(mask >> 6) & 3];
-  }
-  void Float32x4ToFloat64x2() {
-    for (intptr_t lane = 0; lane < 2; lane++) {
-      op_[lane] = AddDefinition(new (zone()) FloatToDoubleInstr(
-          new (zone()) Value(in_[0][lane]), DeoptId::kNone));
-    }
-  }
-  void Float64x2ToFloat32x4() {
-    for (intptr_t lane = 0; lane < 2; lane++) {
-      op_[lane] = AddDefinition(new (zone()) DoubleToFloatInstr(
-          new (zone()) Value(in_[0][lane]), DeoptId::kNone));
-    }
-    Definition* zero = flow_graph_->GetConstant(
-        Double::ZoneHandle(Double::NewCanonical(0.0)), kUnboxedFloat);
-    op_[2] = zero;
-    op_[3] = zero;
-  }
-  void Int32x4ToFloat32x4() {
-    for (intptr_t lane = 0; lane < 4; lane++) {
-      op_[lane] = AddDefinition(new (zone()) BitCastInstr(
-          kUnboxedInt32, kUnboxedFloat, new (zone()) Value(in_[0][lane])));
-    }
-  }
-  void Float32x4ToInt32x4() {
-    for (intptr_t lane = 0; lane < 4; lane++) {
-      op_[lane] = AddDefinition(new (zone()) BitCastInstr(
-          kUnboxedFloat, kUnboxedInt32, new (zone()) Value(in_[0][lane])));
-    }
-  }
-  void IntToBool() {
-    for (intptr_t lane = 0; lane < 4; lane++) {
-      op_[lane] = AddDefinition(
-          new (zone()) IntToBoolInstr(new (zone()) Value(in_[0][lane])));
-    }
-  }
-
-  void BoxVector(Representation rep, intptr_t n) {
-    Definition* box;
-    if (n == 2) {
-      box = new (zone()) BoxLanesInstr(rep, new (zone()) Value(op_[0]),
-                                       new (zone()) Value(op_[1]));
-    } else {
-      ASSERT(n == 4);
-      box = new (zone()) BoxLanesInstr(
-          rep, new (zone()) Value(op_[0]), new (zone()) Value(op_[1]),
-          new (zone()) Value(op_[2]), new (zone()) Value(op_[3]));
-    }
-    Done(AddDefinition(box));
-  }
-
-  void BoxScalar(intptr_t lane, Representation rep) {
-    Definition* box = BoxInstr::Create(rep, new (zone()) Value(in_[0][lane]));
-    Done(AddDefinition(box));
-  }
-
-  void Return(intptr_t lane) { Done(op_[lane]); }
-
-  void Done(Definition* result) {
-    // InheritDeoptTarget also inherits environment (which may add 'entry' into
-    // env_use_list()), so InheritDeoptTarget should be done only after decided
-    // to inline.
-    (*entry_)->InheritDeoptTarget(zone(), call_);
-    *result_ = result;
-  }
-
-  Definition* AddDefinition(Definition* def) {
-    *last_ = flow_graph_->AppendTo(
-        *last_, def, call_->deopt_id() != DeoptId::kNone ? call_->env() : NULL,
-        FlowGraph::kValue);
-    return def;
-  }
-  Zone* zone() { return flow_graph_->zone(); }
-
-  FlowGraph* flow_graph_;
-  Instruction* call_;
-  GraphEntryInstr* graph_entry_;
-  FunctionEntryInstr** entry_;
-  Instruction** last_;
-  Definition** result_;
-
-  // First index is the argment number, second index is the lane number.
-  Definition* in_[4][4];
-  // Index is the lane number.
-  Definition* op_[4];
-};
-
 static bool InlineSimdOp(FlowGraph* flow_graph,
                          bool is_dynamic_call,
                          Instruction* call,
@@ -4128,6 +3546,9 @@
                          FunctionEntryInstr** entry,
                          Instruction** last,
                          Definition** result) {
+  if (!ShouldInlineSimd()) {
+    return false;
+  }
   if (is_dynamic_call && call->ArgumentCount() > 1) {
     // Issue(dartbug.com/37737): Dynamic invocation forwarders have the
     // same recognized kind as the method they are forwarding to.
@@ -4142,19 +3563,6 @@
     return false;
   }
 
-  if (!FLAG_enable_simd_inline) {
-    return false;
-  }
-
-  if (!FlowGraphCompiler::SupportsUnboxedSimd128()) {
-#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
-    SimdLowering lowering(flow_graph, call, graph_entry, entry, last, result);
-    return lowering.TryInline(kind);
-#else
-    UNREACHABLE();
-#endif
-  }
-
   *entry =
       new (Z) FunctionEntryInstr(graph_entry, flow_graph->allocate_block_id(),
                                  call->GetBlock()->try_index(), DeoptId::kNone);
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index f4e263b..b9804d5 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -1323,14 +1323,6 @@
   return CompileType::Bool();
 }
 
-CompileType BoolToIntInstr::ComputeType() const {
-  return CompileType::Int();
-}
-
-CompileType IntToBoolInstr::ComputeType() const {
-  return CompileType::Bool();
-}
-
 CompileType InstanceOfInstr::ComputeType() const {
   return CompileType::Bool();
 }
@@ -1762,6 +1754,10 @@
   return CompileType::FromCid(simd_op_result_cids[kind()]);
 }
 
+CompileType MathUnaryInstr::ComputeType() const {
+  return CompileType::FromCid(kDoubleCid);
+}
+
 CompileType MathMinMaxInstr::ComputeType() const {
   return CompileType::FromCid(result_cid_);
 }
@@ -1815,20 +1811,6 @@
   }
 }
 
-CompileType BoxLanesInstr::ComputeType() const {
-  switch (from_representation()) {
-    case kUnboxedFloat:
-      return CompileType::FromCid(kFloat32x4Cid);
-    case kUnboxedDouble:
-      return CompileType::FromCid(kFloat64x2Cid);
-    case kUnboxedInt32:
-      return CompileType::FromCid(kInt32x4Cid);
-    default:
-      UNREACHABLE();
-      return CompileType::Dynamic();
-  }
-}
-
 CompileType Int32ToDoubleInstr::ComputeType() const {
   return CompileType::FromCid(kDoubleCid);
 }
@@ -1841,12 +1823,12 @@
   return CompileType::FromCid(kDoubleCid);
 }
 
-CompileType FloatToDoubleInstr::ComputeType() const {
+CompileType DoubleToDoubleInstr::ComputeType() const {
   return CompileType::FromCid(kDoubleCid);
 }
 
-CompileType FloatCompareInstr::ComputeType() const {
-  return CompileType::Int();
+CompileType FloatToDoubleInstr::ComputeType() const {
+  return CompileType::FromCid(kDoubleCid);
 }
 
 CompileType DoubleToFloatInstr::ComputeType() const {
@@ -1866,10 +1848,6 @@
   return CompileType::FromCid(definition_cid_);
 }
 
-CompileType UnboxLaneInstr::ComputeType() const {
-  return CompileType::FromCid(definition_cid_);
-}
-
 static AbstractTypePtr ExtractElementTypeFromArrayType(
     const AbstractType& array_type) {
   if (array_type.IsTypeParameter()) {
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index c48dc65..7cd28de 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -1244,6 +1244,15 @@
   return Fragment(instr);
 }
 
+Fragment BaseFlowGraphBuilder::DoubleToDouble(
+    MethodRecognizer::Kind recognized_kind) {
+  Value* value = Pop();
+  auto* instr =
+      new (Z) DoubleToDoubleInstr(value, recognized_kind, GetNextDeoptId());
+  Push(instr);
+  return Fragment(instr);
+}
+
 Fragment BaseFlowGraphBuilder::DoubleToInteger(
     MethodRecognizer::Kind recognized_kind) {
   Value* value = Pop();
@@ -1253,10 +1262,9 @@
   return Fragment(instr);
 }
 
-Fragment BaseFlowGraphBuilder::UnaryDoubleOp(Token::Kind op) {
+Fragment BaseFlowGraphBuilder::MathUnary(MathUnaryInstr::MathUnaryKind kind) {
   Value* value = Pop();
-  auto* instr = new (Z) UnaryDoubleOpInstr(op, value, GetNextDeoptId(),
-                                           Instruction::kNotSpeculative);
+  auto* instr = new (Z) MathUnaryInstr(kind, value, GetNextDeoptId());
   Push(instr);
   return Fragment(instr);
 }
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.h b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
index 0632510..a91212e 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.h
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
@@ -455,13 +455,18 @@
   Fragment InvokeMathCFunction(MethodRecognizer::Kind recognized_kind,
                                intptr_t num_inputs);
 
+  // Pops double value and converts it to double as specified
+  // by the recognized method (kDoubleTruncateToDouble,
+  // kDoubleFloorToDouble or kDoubleCeilToDouble).
+  Fragment DoubleToDouble(MethodRecognizer::Kind recognized_kind);
+
   // Pops double value and converts it to int as specified
   // by the recognized method (kDoubleToInteger,
   // kDoubleFloorToInt or kDoubleCeilToInt).
   Fragment DoubleToInteger(MethodRecognizer::Kind recognized_kind);
 
   // Pops double value and applies unary math operation.
-  Fragment UnaryDoubleOp(Token::Kind op);
+  Fragment MathUnary(MathUnaryInstr::MathUnaryKind kind);
 
   // Records coverage for this position, if the current VM mode supports it.
   Fragment RecordCoverage(TokenPosition position);
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index b1cc2ff..1e3707e 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -1634,26 +1634,14 @@
           ((kind == MethodRecognizer::kDoubleTruncateToDouble) ||
            (kind == MethodRecognizer::kDoubleFloorToDouble) ||
            (kind == MethodRecognizer::kDoubleCeilToDouble))) {
-        switch (kind) {
-          case MethodRecognizer::kDoubleTruncateToDouble:
-            body += UnaryDoubleOp(Token::kTRUNCATE);
-            break;
-          case MethodRecognizer::kDoubleFloorToDouble:
-            body += UnaryDoubleOp(Token::kFLOOR);
-            break;
-          case MethodRecognizer::kDoubleCeilToDouble:
-            body += UnaryDoubleOp(Token::kCEILING);
-            break;
-          default:
-            UNREACHABLE();
-        }
+        body += DoubleToDouble(kind);
       } else {
         body += InvokeMathCFunction(kind, function.NumParameters());
       }
     } break;
     case MethodRecognizer::kMathSqrt: {
       body += LoadLocal(parsed_function_->RawParameterVariable(0));
-      body += UnaryDoubleOp(Token::kSQRT);
+      body += MathUnary(MathUnaryInstr::kSqrt);
     } break;
     case MethodRecognizer::kFinalizerBase_setIsolate:
       ASSERT_EQUAL(function.NumParameters(), 1);
diff --git a/runtime/vm/deferred_objects.cc b/runtime/vm/deferred_objects.cc
index de229ac..b64d7dd 100644
--- a/runtime/vm/deferred_objects.cc
+++ b/runtime/vm/deferred_objects.cc
@@ -395,9 +395,15 @@
                   static_cast<uint64_t>(Integer::Cast(value).AsInt64Value()));
               break;
             case kTypedDataFloat32ArrayCid:
+              // Although element of Float32 array is represented with Double,
+              // it is already converted to 32-bit float via DoubleToFloat
+              // instruction before it was stored.
+              // Reinterpret double value as float to get the value back.
               typed_data.SetFloat32(
                   element_offset,
-                  static_cast<float>(Double::Cast(value).value()));
+                  bit_cast<float, uint32_t>(
+                      static_cast<uint32_t>(bit_cast<uint64_t, double>(
+                          Double::Cast(value).value()))));
               break;
             case kTypedDataFloat64ArrayCid:
               typed_data.SetFloat64(element_offset,
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 497c453..20eec15 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -232,7 +232,6 @@
     case DeoptInstr::kInt32x4:
     case DeoptInstr::kFloat64x2:
     case DeoptInstr::kWord:
-    case DeoptInstr::kFloat:
     case DeoptInstr::kDouble:
     case DeoptInstr::kMint:
     case DeoptInstr::kMintPair:
@@ -669,12 +668,6 @@
   DISALLOW_COPY_AND_ASSIGN(DeoptFpuInstr);
 };
 
-typedef DeoptFpuInstr<DeoptInstr::kFloat,
-                      CatchEntryMove::SourceKind::kFloatSlot,
-                      float,
-                      DoublePtr>
-    DeoptFloatInstr;
-
 typedef DeoptFpuInstr<DeoptInstr::kDouble,
                       CatchEntryMove::SourceKind::kDoubleSlot,
                       double,
@@ -909,8 +902,6 @@
   switch (kind) {
     case kWord:
       return new DeoptWordInstr(source_index);
-    case kFloat:
-      return new DeoptFloatInstr(source_index);
     case kDouble:
       return new DeoptDoubleInstr(source_index);
     case kMint:
@@ -954,8 +945,6 @@
   switch (kind) {
     case kWord:
       return "word";
-    case kFloat:
-      return "float";
     case kDouble:
       return "double";
     case kMint:
@@ -1138,9 +1127,6 @@
             new (zone()) DeoptUint32Instr(ToCpuRegisterSource(source_loc));
         break;
       case kUnboxedFloat:
-        deopt_instr = new (zone()) DeoptFloatInstr(
-            ToFpuRegisterSource(source_loc, Location::kDoubleStackSlot));
-        break;
       case kUnboxedDouble:
         deopt_instr = new (zone()) DeoptDoubleInstr(
             ToFpuRegisterSource(source_loc, Location::kDoubleStackSlot));
diff --git a/runtime/vm/deopt_instructions.h b/runtime/vm/deopt_instructions.h
index ccfff06..cbd15c2 100644
--- a/runtime/vm/deopt_instructions.h
+++ b/runtime/vm/deopt_instructions.h
@@ -82,15 +82,7 @@
     return cpu_registers_[reg];
   }
 
-  float FpuRegisterValueAsFloat(FpuRegister reg) const {
-    ASSERT(FlowGraphCompiler::SupportsUnboxedDoubles());
-    ASSERT(fpu_registers_ != NULL);
-    ASSERT(reg >= 0);
-    ASSERT(reg < kNumberOfFpuRegisters);
-    return *reinterpret_cast<float*>(&fpu_registers_[reg]);
-  }
-
-  double FpuRegisterValueAsDouble(FpuRegister reg) const {
+  double FpuRegisterValue(FpuRegister reg) const {
     ASSERT(FlowGraphCompiler::SupportsUnboxedDoubles());
     ASSERT(fpu_registers_ != NULL);
     ASSERT(reg >= 0);
@@ -167,11 +159,6 @@
         idx, reinterpret_cast<ObjectPtr*>(slot), deferred_slots_);
   }
 
-  void DeferMaterialization(float value, DoublePtr* slot) {
-    deferred_slots_ = new DeferredDouble(
-        value, reinterpret_cast<ObjectPtr*>(slot), deferred_slots_);
-  }
-
   void DeferMaterialization(double value, DoublePtr* slot) {
     deferred_slots_ = new DeferredDouble(
         value, reinterpret_cast<ObjectPtr*>(slot), deferred_slots_);
@@ -280,7 +267,6 @@
     kRetAddress,
     kConstant,
     kWord,
-    kFloat,
     kDouble,
     kFloat32x4,
     kFloat64x2,
@@ -372,16 +358,9 @@
 };
 
 template <>
-struct RegisterReader<FpuRegister, float> {
-  static double Read(DeoptContext* context, FpuRegister reg) {
-    return context->FpuRegisterValueAsFloat(reg);
-  }
-};
-
-template <>
 struct RegisterReader<FpuRegister, double> {
   static double Read(DeoptContext* context, FpuRegister reg) {
-    return context->FpuRegisterValueAsDouble(reg);
+    return context->FpuRegisterValue(reg);
   }
 };
 
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 0d71595..23e9aa2 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -237,10 +237,6 @@
           value = *TaggedSlotAt(fp, move.src_slot());
           break;
 
-        case CatchEntryMove::SourceKind::kFloatSlot:
-          value = Double::New(*SlotAt<float>(fp, move.src_slot()));
-          break;
-
         case CatchEntryMove::SourceKind::kDoubleSlot:
           value = Double::New(*SlotAt<double>(fp, move.src_slot()));
           break;
@@ -373,11 +369,6 @@
       Utils::SNPrint(from, ARRAY_SIZE(from), "fp[%" Pd "]", src_slot());
       break;
 
-    case SourceKind::kFloatSlot:
-      Utils::SNPrint(from, ARRAY_SIZE(from), "f32 [fp + %" Pd "]",
-                     src_slot() * compiler::target::kWordSize);
-      break;
-
     case SourceKind::kDoubleSlot:
       Utils::SNPrint(from, ARRAY_SIZE(from), "f64 [fp + %" Pd "]",
                      src_slot() * compiler::target::kWordSize);
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h
index f87201d..89090a6 100644
--- a/runtime/vm/exceptions.h
+++ b/runtime/vm/exceptions.h
@@ -147,7 +147,6 @@
   enum class SourceKind {
     kConstant,
     kTaggedSlot,
-    kFloatSlot,
     kDoubleSlot,
     kFloat32x4Slot,
     kFloat64x2Slot,
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index af9539d..3b988bd 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -1739,13 +1739,6 @@
   // how the vm_tag (kEmbedderTagId) can be set, these tags need to
   // move to the OSThread structure.
   set_user_tag(UserTags::kDefaultUserTag);
-
-  if (group()->obfuscate()) {
-    OS::PrintErr(
-        "Warning: This VM has been configured to obfuscate symbol information "
-        "which violates the Dart standard.\n"
-        "         See dartbug.com/30524 for more information.\n");
-  }
 }
 
 #undef REUSABLE_HANDLE_SCOPE_INIT
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 4af9fe1..e7c7b72 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -25948,12 +25948,6 @@
         isolate_instructions_image.instructions_relocated_address();
     auto const vm_relocated_address =
         vm_instructions_image.instructions_relocated_address();
-    // The Dart standard requires the output of StackTrace.toString to include
-    // all pending activations with precise source locations (i.e., to expand
-    // inlined frames and provide line and column numbers).
-    buffer.Printf(
-        "Warning: This VM has been configured to produce stack traces "
-        "that violate the Dart standard.\n");
     // This prologue imitates Android's debuggerd to make it possible to paste
     // the stack trace into ndk-stack.
     buffer.Printf(
diff --git a/runtime/vm/token.cc b/runtime/vm/token.cc
index ad55e39..ba33707 100644
--- a/runtime/vm/token.cc
+++ b/runtime/vm/token.cc
@@ -56,8 +56,6 @@
     case Token::kSHL:
     case Token::kSHR:
     case Token::kUSHR:
-    case Token::kMAX:
-    case Token::kMIN:
       return true;
     default:
       return false;
@@ -65,21 +63,7 @@
 }
 
 bool Token::IsUnaryArithmeticOperator(Token::Kind token) {
-  switch (token) {
-    case Token::kBIT_NOT:
-    case Token::kNEGATE:
-    case Token::kABS:
-    case Token::kSQRT:
-    case Token::kSQUARE:
-    case Token::kRECIPROCAL:
-    case Token::kRECIPROCAL_SQRT:
-    case Token::kTRUNCATE:
-    case Token::kFLOOR:
-    case Token::kCEILING:
-      return true;
-    default:
-      return false;
-  }
+  return (token == kBIT_NOT) || (token == kNEGATE);
 }
 
 bool Token::IsBinaryBitwiseOperator(Token::Kind token) {
diff --git a/runtime/vm/token.h b/runtime/vm/token.h
index 174af7d..e2fc074 100644
--- a/runtime/vm/token.h
+++ b/runtime/vm/token.h
@@ -140,17 +140,7 @@
   TOK(kSCRIPTTAG, "#!", 0, kNoAttribute)                                       \
                                                                                \
   /* Support for optimized code */                                             \
-  TOK(kREM, "rem", 0, kNoAttribute)                                            \
-  TOK(kABS, "abs", 0, kNoAttribute)                                            \
-  TOK(kSQRT, "sqrt", 0, kNoAttribute)                                          \
-  TOK(kMIN, "min", 0, kNoAttribute)                                            \
-  TOK(kMAX, "max", 0, kNoAttribute)                                            \
-  TOK(kRECIPROCAL, "reciprocal", 0, kNoAttribute)                              \
-  TOK(kRECIPROCAL_SQRT, "reciprocal-sqrt", 0, kNoAttribute)                    \
-  TOK(kSQUARE, "square", 0, kNoAttribute)                                      \
-  TOK(kTRUNCATE, "truncate", 0, kNoAttribute)                                  \
-  TOK(kFLOOR, "floor", 0, kNoAttribute)                                        \
-  TOK(kCEILING, "ceiling", 0, kNoAttribute)
+  TOK(kREM, "", 0, kNoAttribute)
 
 // List of keywords. The list must be alphabetically ordered. The
 // keyword recognition code depends on the ordering.
diff --git a/sdk/lib/typed_data/typed_data.dart b/sdk/lib/typed_data/typed_data.dart
index 661b998..7dce112 100644
--- a/sdk/lib/typed_data/typed_data.dart
+++ b/sdk/lib/typed_data/typed_data.dart
@@ -2456,75 +2456,21 @@
   Float32x4 operator /(Float32x4 other);
 
   /// Relational less than.
-  ///
-  /// Equivalent to:
-  ///
-  /// ```
-  /// Int32x4(this.x < other.x ? -1 : 0,
-  ///         this.y < other.y ? -1 : 0,
-  ///         this.z < other.z ? -1 : 0,
-  ///         this.w < other.w ? -1 : 0);
-  /// ```
   Int32x4 lessThan(Float32x4 other);
 
   /// Relational less than or equal.
-  ///
-  /// Equivalent to:
-  ///
-  /// ```
-  /// Int32x4(this.x <= other.x ? -1 : 0,
-  ///         this.y <= other.y ? -1 : 0,
-  ///         this.z <= other.z ? -1 : 0,
-  ///         this.w <= other.w ? -1 : 0);
-  /// ```
   Int32x4 lessThanOrEqual(Float32x4 other);
 
   /// Relational greater than.
-  ///
-  /// Equivalent to:
-  ///
-  /// ```
-  /// Int32x4(this.x > other.x ? -1 : 0,
-  ///         this.y > other.y ? -1 : 0,
-  ///         this.z > other.z ? -1 : 0,
-  ///         this.w > other.w ? -1 : 0);
-  /// ```
   Int32x4 greaterThan(Float32x4 other);
 
   /// Relational greater than or equal.
-  ///
-  /// Equivalent to:
-  ///
-  /// ```
-  /// Int32x4(this.x >= other.x ? -1 : 0,
-  ///         this.y >= other.y ? -1 : 0,
-  ///         this.z >= other.z ? -1 : 0,
-  ///         this.w >= other.w ? -1 : 0);
-  /// ```
   Int32x4 greaterThanOrEqual(Float32x4 other);
 
   /// Relational equal.
-  ///
-  /// Equivalent to:
-  ///
-  /// ```
-  /// Int32x4(this.x == other.x ? -1 : 0,
-  ///         this.y == other.y ? -1 : 0,
-  ///         this.z == other.z ? -1 : 0,
-  ///         this.w == other.w ? -1 : 0);
-  /// ```
   Int32x4 equal(Float32x4 other);
 
   /// Relational not-equal.
-  ///
-  /// Equivalent to:
-  ///
-  /// ```
-  /// Int32x4(this.x != other.x ? -1 : 0,
-  ///         this.y != other.y ? -1 : 0,
-  ///         this.z != other.z ? -1 : 0,
-  ///         this.w != other.w ? -1 : 0);
-  /// ```
   Int32x4 notEqual(Float32x4 other);
 
   /// Returns a copy of [this] each lane being scaled by [s].
@@ -2856,14 +2802,7 @@
 /// The lanes are "x", "y", "z", and "w" respectively.
 abstract class Int32x4 {
   external factory Int32x4(int x, int y, int z, int w);
-
-  /// Equivalent to:
-  ///
-  /// ```
-  /// Int32x4(x ? -1 : 0, y ? -1 : 0, z ? -1 : 0, w ? -1 : 0)
-  /// ```
   external factory Int32x4.bool(bool x, bool y, bool z, bool w);
-
   external factory Int32x4.fromFloat32x4Bits(Float32x4 x);
 
   /// The bit-wise or operator.
diff --git a/tools/VERSION b/tools/VERSION
index a7d80de..98ebbad 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 19
 PATCH 0
-PRERELEASE 59
+PRERELEASE 60
 PRERELEASE_PATCH 0
\ No newline at end of file