Revert "[VM] Reduce Smi size to 32 bit on 64 bit platforms"

This reverts commit cf78da8a48b886cbd70e6c50dd7461a621065e31.

Reason for revert: introduces significant performance regression (~30%) on analyzer benchmarks (warm-analysis) without clearly visible hot-spot.

Original change's description:
> [VM] Reduce Smi size to 32 bit on 64 bit platforms
> 
> This reduces small tagged integers on 64 bit platforms from 63 bits to
> 31 bits plus one tag bit.
> This is a step on the way to compile-time-optional compressed pointers
> on 64 bit platforms.  See more about this at go/dartvmlearnings
> This causes a slowdown for some uses of integers that don't fit in 31
> signed bits, but because both x64 and ARM64 have unboxed 64 bit
> integers now the performance hit should not be too bad.
> 
> This is a reapplication of
> https://dart-review.googlesource.com/c/sdk/+/46244
> It was reverted due to a compilation error on 32 bit
> ARM with DBC.
> 
> R=​vegorov@google.com
> 
> Change-Id: I943de1768519457f0e5a61ef0b4ef204b6a53281
> Reviewed-on: https://dart-review.googlesource.com/51321
> Reviewed-by: Vyacheslav Egorov <vegorov@google.com>

TBR=vegorov@google.com,erikcorry@google.com

# Not skipping CQ checks because original CL landed > 1 day ago.

Change-Id: I8c5b909ec38663b5f5b05f69ef488c97341f8f3d
Reviewed-on: https://dart-review.googlesource.com/54000
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
Commit-Queue: Vyacheslav Egorov <vegorov@google.com>
diff --git a/runtime/lib/compact_hash.dart b/runtime/lib/compact_hash.dart
index 6f55f41..82bc532 100644
--- a/runtime/lib/compact_hash.dart
+++ b/runtime/lib/compact_hash.dart
@@ -78,14 +78,19 @@
   static const int _UNUSED_PAIR = 0;
   static const int _DELETED_PAIR = 1;
 
-  // The top bits are wasted to avoid Mint allocation.
+  // On 32-bit, the top bits are wasted to avoid Mint allocation.
+  // TODO(koda): Reclaim the bits by making the compiler treat hash patterns
+  // as unsigned words.
   static int _indexSizeToHashMask(int indexSize) {
     int indexBits = indexSize.bitLength - 2;
-    return (1 << (30 - indexBits)) - 1;
+    return internal.is64Bit
+        ? (1 << (32 - indexBits)) - 1
+        : (1 << (30 - indexBits)) - 1;
   }
 
   static int _hashPattern(int fullHash, int hashMask, int size) {
     final int maskedHash = fullHash & hashMask;
+    // TODO(koda): Consider keeping bit length and use left shift.
     return (maskedHash == 0) ? (size >> 1) : maskedHash * (size >> 1);
   }
 
diff --git a/runtime/lib/integers_patch.dart b/runtime/lib/integers_patch.dart
index 15598fe..d1c13be 100644
--- a/runtime/lib/integers_patch.dart
+++ b/runtime/lib/integers_patch.dart
@@ -32,7 +32,7 @@
         return null; // Empty.
       }
     }
-    var smiLimit = 9;
+    var smiLimit = is64Bit ? 18 : 9;
     if ((last - ix) >= smiLimit) {
       return null; // May not fit into a Smi.
     }
@@ -133,7 +133,7 @@
 
   static int _parseRadix(
       String source, int radix, int start, int end, int sign) {
-    int tableIndex = (radix - 2) * 2;
+    int tableIndex = (radix - 2) * 4 + (is64Bit ? 2 : 0);
     int blockSize = _PARSE_LIMITS[tableIndex];
     int length = end - start;
     if (length <= blockSize) {
@@ -159,7 +159,7 @@
     int positiveOverflowLimit = 0;
     int negativeOverflowLimit = 0;
     if (_limitIntsTo64Bits) {
-      tableIndex = tableIndex << 1; // Pre-multiply by 2 for simpler indexing.
+      tableIndex = tableIndex << 1; // pre-multiply by 2 for simpler indexing
       positiveOverflowLimit = _int64OverflowLimits[tableIndex];
       if (positiveOverflowLimit == 0) {
         positiveOverflowLimit =
@@ -175,10 +175,14 @@
         if (result >= positiveOverflowLimit) {
           if ((result > positiveOverflowLimit) ||
               (smi > _int64OverflowLimits[tableIndex + 2])) {
+            // Although the unsigned overflow limits do not depend on the
+            // platform, the multiplier and block size, which are used to
+            // compute it, do.
+            int X = is64Bit ? 1 : 0;
             if (radix == 16 &&
-                !(result >= _int64UnsignedOverflowLimit &&
-                    (result > _int64UnsignedOverflowLimit ||
-                        smi > _int64UnsignedSmiOverflowLimit)) &&
+                !(result >= _int64UnsignedOverflowLimits[X] &&
+                    (result > _int64UnsignedOverflowLimits[X] ||
+                        smi > _int64UnsignedSmiOverflowLimits[X])) &&
                 blockEnd + blockSize > end) {
               return (result * multiplier) + smi;
             }
@@ -223,42 +227,43 @@
 
   // For each radix, 2-36, how many digits are guaranteed to fit in a smi,
   // and magnitude of such a block (radix ** digit-count).
+  // 32-bit limit/multiplier at (radix - 2)*4, 64-bit limit at (radix-2)*4+2
   static const _PARSE_LIMITS = const [
-    30, 1073741824, // radix: 2
-    18, 387420489,
-    15, 1073741824,
-    12, 244140625, //  radix: 5
-    11, 362797056,
-    10, 282475249,
-    10, 1073741824,
-    9, 387420489,
-    9, 1000000000, //  radix: 10
-    8, 214358881,
-    8, 429981696,
-    8, 815730721,
-    7, 105413504,
-    7, 170859375, //    radix: 15
-    7, 268435456,
-    7, 410338673,
-    7, 612220032,
-    7, 893871739,
-    6, 64000000, //    radix: 20
-    6, 85766121,
-    6, 113379904,
-    6, 148035889,
-    6, 191102976,
-    6, 244140625, //   radix: 25
-    6, 308915776,
-    6, 387420489,
-    6, 481890304,
-    6, 594823321,
-    6, 729000000, //    radix: 30
-    6, 887503681,
-    6, 1073741824,
-    5, 39135393,
-    5, 45435424,
-    5, 52521875, //    radix: 35
-    5, 60466176,
+    30, 1073741824, 62, 4611686018427387904, // radix: 2
+    18, 387420489, 39, 4052555153018976267,
+    15, 1073741824, 30, 1152921504606846976,
+    12, 244140625, 26, 1490116119384765625, //  radix: 5
+    11, 362797056, 23, 789730223053602816,
+    10, 282475249, 22, 3909821048582988049,
+    10, 1073741824, 20, 1152921504606846976,
+    9, 387420489, 19, 1350851717672992089,
+    9, 1000000000, 18, 1000000000000000000, //  radix: 10
+    8, 214358881, 17, 505447028499293771,
+    8, 429981696, 17, 2218611106740436992,
+    8, 815730721, 16, 665416609183179841,
+    7, 105413504, 16, 2177953337809371136,
+    7, 170859375, 15, 437893890380859375, //    radix: 15
+    7, 268435456, 15, 1152921504606846976,
+    7, 410338673, 15, 2862423051509815793,
+    7, 612220032, 14, 374813367582081024,
+    7, 893871739, 14, 799006685782884121,
+    6, 64000000, 14, 1638400000000000000, //    radix: 20
+    6, 85766121, 14, 3243919932521508681,
+    6, 113379904, 13, 282810057883082752,
+    6, 148035889, 13, 504036361936467383,
+    6, 191102976, 13, 876488338465357824,
+    6, 244140625, 13, 1490116119384765625, //   radix: 25
+    6, 308915776, 13, 2481152873203736576,
+    6, 387420489, 13, 4052555153018976267,
+    6, 481890304, 12, 232218265089212416,
+    6, 594823321, 12, 353814783205469041,
+    6, 729000000, 12, 531441000000000000, //    radix: 30
+    6, 887503681, 12, 787662783788549761,
+    6, 1073741824, 12, 1152921504606846976,
+    5, 39135393, 12, 1667889514952984961,
+    5, 45435424, 12, 2386420683693101056,
+    5, 52521875, 12, 3379220508056640625, //    radix: 35
+    5, 60466176, 11, 131621703842267136,
   ];
 
   /// Flag indicating if integers are limited by 64 bits
@@ -268,8 +273,11 @@
   static const _maxInt64 = 0x7fffffffffffffff;
   static const _minInt64 = -_maxInt64 - 1;
 
-  static const _int64UnsignedOverflowLimit = 0xfffffffff;
-  static const _int64UnsignedSmiOverflowLimit = 0xfffffff;
+  static const _int64UnsignedOverflowLimits = const [0xfffffffff, 0xf];
+  static const _int64UnsignedSmiOverflowLimits = const [
+    0xfffffff,
+    0xfffffffffffffff
+  ];
 
   /// In the `--limit-ints-to-64-bits` mode calculation of the expression
   ///
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index 5a6a9d1..b0d94c2 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -1069,18 +1069,12 @@
     const Register crn = ConcreteRegister(rn);
     EmitFPIntCvtOp(SCVTFD, static_cast<Register>(vd), crn, kWord);
   }
-  void fcvtzdsx(Register rd, VRegister vn) {
+  void fcvtzds(Register rd, VRegister vn) {
     ASSERT(rd != R31);
     ASSERT(rd != CSP);
     const Register crd = ConcreteRegister(rd);
     EmitFPIntCvtOp(FCVTZDS, crd, static_cast<Register>(vn));
   }
-  void fcvtzdsw(Register rd, VRegister vn) {
-    ASSERT(rd != R31);
-    ASSERT(rd != CSP);
-    const Register crd = ConcreteRegister(rd);
-    EmitFPIntCvtOp(FCVTZDS, crd, static_cast<Register>(vn), kWord);
-  }
   void fmovdd(VRegister vd, VRegister vn) { EmitFPOneSourceOp(FMOVDD, vd, vn); }
   void fabsd(VRegister vd, VRegister vn) { EmitFPOneSourceOp(FABSD, vd, vn); }
   void fnegd(VRegister vd, VRegister vn) { EmitFPOneSourceOp(FNEGD, vd, vn); }
@@ -1371,17 +1365,9 @@
     LslImmediate(dst, src, kSmiTagSize);
   }
 
-  void BranchIfNotSmi(Register reg, Label* label) {
-    ASSERT(kSmiTagMask == 1);
-    ASSERT(kSmiTag == 0);
-    tbnz(label, reg, 0);
-  }
+  void BranchIfNotSmi(Register reg, Label* label) { tbnz(label, reg, kSmiTag); }
 
-  void BranchIfSmi(Register reg, Label* label) {
-    ASSERT(kSmiTagMask == 1);
-    ASSERT(kSmiTag == 0);
-    tbz(label, reg, 0);
-  }
+  void BranchIfSmi(Register reg, Label* label) { tbz(label, reg, kSmiTag); }
 
   void Branch(const StubEntry& stub_entry,
               Register pp,
@@ -1465,11 +1451,6 @@
     kValueCanBeSmi,
   };
 
-  enum CanBeHeapPointer {
-    kValueIsNotHeapPointer,
-    kValueCanBeHeapPointer,
-  };
-
   // Storing into an object.
   void StoreIntoObject(Register object,
                        const Address& dest,
@@ -1611,22 +1592,6 @@
                       Register tmp,
                       OperandSize sz);
 
-  void AssertSmiInRange(
-      Register object,
-      CanBeHeapPointer can_be_heap_pointer = kValueIsNotHeapPointer) {
-#if defined(DEBUG)
-    Label ok;
-    if (can_be_heap_pointer == kValueCanBeHeapPointer) {
-      BranchIfNotSmi(object, &ok);
-    }
-    cmp(object, Operand(object, SXTW, 0));
-    b(&ok, EQ);
-    Stop("Smi out of range");
-
-    Bind(&ok);
-#endif
-  }
-
  private:
   AssemblerBuffer buffer_;  // Contains position independent code.
   ObjectPoolWrapper object_pool_wrapper_;
diff --git a/runtime/vm/compiler/assembler/assembler_arm64_test.cc b/runtime/vm/compiler/assembler/assembler_arm64_test.cc
index 523688b..a41fad24 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64_test.cc
@@ -2576,73 +2576,17 @@
   EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
 }
 
-ASSEMBLER_TEST_GENERATE(Fcvtzdsx, assembler) {
+ASSEMBLER_TEST_GENERATE(Fcvtzds, assembler) {
   __ LoadDImmediate(V0, 42.0);
-  __ fcvtzdsx(R0, V0);
+  __ fcvtzds(R0, V0);
   __ ret();
 }
 
-ASSEMBLER_TEST_RUN(Fcvtzdsx, test) {
+ASSEMBLER_TEST_RUN(Fcvtzds, test) {
   typedef int64_t (*Int64Return)() DART_UNUSED;
   EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
-ASSEMBLER_TEST_GENERATE(Fcvtzdsw, assembler) {
-  __ LoadDImmediate(V0, 42.0);
-  __ fcvtzdsw(R0, V0);
-  __ ret();
-}
-
-ASSEMBLER_TEST_RUN(Fcvtzdsw, test) {
-  typedef int64_t (*Int64Return)() DART_UNUSED;
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
-}
-
-ASSEMBLER_TEST_GENERATE(Fcvtzdsx_overflow, assembler) {
-  __ LoadDImmediate(V0, 1e20);
-  __ fcvtzdsx(R0, V0);
-  __ ret();
-}
-
-ASSEMBLER_TEST_RUN(Fcvtzdsx_overflow, test) {
-  typedef int64_t (*Int64Return)() DART_UNUSED;
-  EXPECT_EQ(kMaxInt64, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
-}
-
-ASSEMBLER_TEST_GENERATE(Fcvtzdsx_overflow_negative, assembler) {
-  __ LoadDImmediate(V0, -1e20);
-  __ fcvtzdsx(R0, V0);
-  __ ret();
-}
-
-ASSEMBLER_TEST_RUN(Fcvtzdsx_overflow_negative, test) {
-  typedef int64_t (*Int64Return)() DART_UNUSED;
-  EXPECT_EQ(kMinInt64, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
-}
-
-ASSEMBLER_TEST_GENERATE(Fcvtzdsw_overflow, assembler) {
-  __ LoadDImmediate(V0, 1e10);
-  __ fcvtzdsw(R0, V0);
-  __ ret();
-}
-
-ASSEMBLER_TEST_RUN(Fcvtzdsw_overflow, test) {
-  typedef int64_t (*Int64Return)() DART_UNUSED;
-  EXPECT_EQ(kMaxInt32, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
-}
-
-ASSEMBLER_TEST_GENERATE(Fcvtzdsw_overflow_negative, assembler) {
-  __ LoadDImmediate(V0, -1e10);
-  __ fcvtzdsw(R0, V0);
-  __ sxtw(R0, R0);
-  __ ret();
-}
-
-ASSEMBLER_TEST_RUN(Fcvtzdsw_overflow_negative, test) {
-  typedef int64_t (*Int64Return)() DART_UNUSED;
-  EXPECT_EQ(kMinInt32, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
-}
-
 ASSEMBLER_TEST_GENERATE(Scvtfdx, assembler) {
   __ LoadImmediate(R0, 42);
   __ scvtfdx(V0, R0);
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index 5d9375d3..569a962 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -521,10 +521,7 @@
     return CompareImmediate(reg, Immediate(immediate));
   }
 
-  void testl(Register reg, const Immediate& imm) {
-    Immediate imm2(imm.value() & 0xffffffffll);
-    testq(reg, imm2);
-  }
+  void testl(Register reg, const Immediate& imm) { testq(reg, imm); }
   void testb(const Address& address, const Immediate& imm);
 
   void testq(Register reg, const Immediate& imm);
@@ -713,11 +710,6 @@
     kValueCanBeSmi,
   };
 
-  enum CanBeHeapPointer {
-    kValueIsNotHeapPointer,
-    kValueCanBeHeapPointer,
-  };
-
   // Destroys value.
   void StoreIntoObject(Register object,      // Object we are storing into.
                        const Address& dest,  // Where we are storing into.
@@ -948,26 +940,6 @@
                                            Register array,
                                            Register index);
 
-  void AssertSmiInRange(
-      Register object,
-      CanBeHeapPointer can_be_heap_pointer = kValueIsNotHeapPointer) {
-#if defined(DEBUG)
-    Register tmp = object == TMP ? TMP2 : TMP;
-    Label ok;
-    if (can_be_heap_pointer == kValueCanBeHeapPointer) {
-      testl(object, Immediate(kSmiTagMask));
-      ASSERT(kSmiTag == 0);
-      j(ZERO, &ok);
-    }
-    movsxd(tmp, object);
-    cmpq(tmp, object);
-    j(EQUAL, &ok);
-    Stop("Smi out of range");
-
-    Bind(&ok);
-#endif
-  }
-
   static Address VMTagAddress() {
     return Address(THR, Thread::vm_tag_offset());
   }
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index fa6d94a..c0d51f7 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -1585,10 +1585,10 @@
   return Utils::IsPowerOfTwo(Utils::Abs(int_value));
 }
 
-static intptr_t SignificantRepresentationBits(Representation r) {
+static intptr_t RepresentationBits(Representation r) {
   switch (r) {
     case kTagged:
-      return 31;
+      return kBitsPerWord - 1;
     case kUnboxedInt32:
     case kUnboxedUint32:
       return 32;
@@ -1602,7 +1602,7 @@
 
 static int64_t RepresentationMask(Representation r) {
   return static_cast<int64_t>(static_cast<uint64_t>(-1) >>
-                              (64 - SignificantRepresentationBits(r)));
+                              (64 - RepresentationBits(r)));
 }
 
 static bool ToIntegerConstant(Value* value, int64_t* result) {
@@ -2163,8 +2163,7 @@
       break;
 
     case Token::kSHL: {
-      const intptr_t kMaxShift =
-          SignificantRepresentationBits(representation()) - 1;
+      const intptr_t kMaxShift = RepresentationBits(representation()) - 1;
       if (rhs == 0) {
         return left()->definition();
       } else if ((rhs < 0) || (rhs >= kMaxShift)) {
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 4f4a097..9c0a698 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -997,13 +997,9 @@
     case kTwoByteStringCid:
     case kExternalOneByteStringCid:
     case kExternalTwoByteStringCid:
-      return CompileType::FromCid(kSmiCid);
-
     case kTypedDataInt32ArrayCid:
     case kTypedDataUint32ArrayCid:
-      // TODO(erikcorry): Perhaps this can return a faster type.  See
-      // https://github.com/dart-lang/sdk/issues/32582
-      return CompileType::Int();
+      return CompileType::FromCid(kSmiCid);
 
     default:
       UNIMPLEMENTED();
@@ -1277,6 +1273,7 @@
         default:
           UNREACHABLE();
       }
+      __ SmiTag(result);
       break;
     case kTwoByteStringCid:
     case kExternalTwoByteStringCid:
@@ -1290,15 +1287,12 @@
         default:
           UNREACHABLE();
       }
+      __ SmiTag(result);
       break;
     default:
       UNREACHABLE();
       break;
   }
-  if (representation_ == kTagged) {
-    ASSERT(can_pack_into_smi());
-    __ SmiTag(result);
-  }
 }
 
 Representation StoreIndexedInstr::RequiredInputRepresentation(
@@ -2776,27 +2770,18 @@
   if (locs.in(1).IsConstant()) {
     const Object& constant = locs.in(1).constant();
     ASSERT(constant.IsSmi());
-    // Immediate shift operation takes 5 bits for the count.
-    const intptr_t kCountLimit = 0x1F;
-    // These should be around the same size.
-    COMPILE_ASSERT(kCountLimit + 1 == kSmiBits + 2);
+    // Immediate shift operation takes 6 bits for the count.
+    const intptr_t kCountLimit = 0x3F;
     const intptr_t value = Smi::Cast(constant).Value();
     ASSERT((0 < value) && (value < kCountLimit));
     if (shift_left->can_overflow()) {
       // Check for overflow (preserve left).
-      __ LslImmediate(TMP, left, value, kWord);
-      __ cmpw(left, Operand(TMP, ASR, value));
+      __ LslImmediate(TMP, left, value);
+      __ cmp(left, Operand(TMP, ASR, value));
       __ b(deopt, NE);  // Overflow.
     }
-    // Shift for result now we know there is no overflow.  This writes the full
-    // 64 bits of the output register, but unless we are in truncating mode the
-    // top bits will just be sign extension bits.
+    // Shift for result now we know there is no overflow.
     __ LslImmediate(result, left, value);
-    if (shift_left->is_truncating()) {
-      // This preserves the invariant that Smis only use the low 32 bits of the
-      // register, the high bits being sign extension bits.
-      __ sxtw(result, result);
-    }
     return;
   }
 
@@ -2804,33 +2789,28 @@
   const Register right = locs.in(1).reg();
   Range* right_range = shift_left->right_range();
   if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) {
+    // TODO(srdjan): Implement code below for is_truncating().
     // If left is constant, we know the maximal allowed size for right.
     const Object& obj = shift_left->left()->BoundConstant();
-    // Even though we have a non-Smi constant on the left, we might still emit
-    // a Smi op here.  In that case the Smi check above will have deopted, so
-    // we can't reach this point. Emit a breakpoint to be sure.
-    if (!obj.IsSmi()) {
-      __ Breakpoint();
-      return;
+    if (obj.IsSmi()) {
+      const intptr_t left_int = Smi::Cast(obj).Value();
+      if (left_int == 0) {
+        __ CompareRegisters(right, ZR);
+        __ b(deopt, MI);
+        __ mov(result, ZR);
+        return;
+      }
+      const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
+      const bool right_needs_check =
+          !RangeUtils::IsWithin(right_range, 0, max_right - 1);
+      if (right_needs_check) {
+        __ CompareImmediate(right,
+                            reinterpret_cast<int64_t>(Smi::New(max_right)));
+        __ b(deopt, CS);
+      }
+      __ SmiUntag(TMP, right);
+      __ lslv(result, left, TMP);
     }
-    const intptr_t left_int = Smi::Cast(obj).Value();
-    if (left_int == 0) {
-      __ CompareRegisters(right, ZR);
-      __ b(deopt, MI);
-      __ mov(result, ZR);
-      return;
-    }
-    const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
-    const bool right_needs_check =
-        !RangeUtils::IsWithin(right_range, 0, max_right - 1);
-    if (right_needs_check) {
-      __ CompareImmediate(right,
-                          reinterpret_cast<int64_t>(Smi::New(max_right)));
-      __ b(deopt, CS);
-    }
-    __ SmiUntag(TMP, right);
-    __ lslv(result, left, TMP);
-    ASSERT(!shift_left->is_truncating());
     return;
   }
 
@@ -2854,11 +2834,7 @@
       __ SmiUntag(TMP, right);
       __ lslv(result, left, TMP);
     }
-    if (shift_left->is_truncating()) {
-      __ sxtw(result, result);
-    }
   } else {
-    // If we can overflow.
     if (right_needs_check) {
       ASSERT(shift_left->CanDeoptimize());
       __ CompareImmediate(right,
@@ -2866,16 +2842,15 @@
       __ b(deopt, CS);
     }
     // Left is not a constant.
-    // Check if count is too large for handling it inlined.
+    // Check if count too large for handling it inlined.
     __ SmiUntag(TMP, right);
     // Overflow test (preserve left, right, and TMP);
     const Register temp = locs.temp(0).reg();
-    __ lslvw(temp, left, TMP);
-    __ asrvw(TMP2, temp, TMP);
-    __ cmpw(left, Operand(TMP2));
+    __ lslv(temp, left, TMP);
+    __ asrv(TMP2, temp, TMP);
+    __ CompareRegisters(left, TMP2);
     __ b(deopt, NE);  // Overflow.
-    // Shift for result now we know there is no overflow.  This is a 64 bit
-    // operation, so no sign extension is needed.
+    // Shift for result now we know there is no overflow.
     __ lslv(result, left, TMP);
   }
 }
@@ -2956,20 +2931,18 @@
 
   switch (op_kind()) {
     case Token::kADD:
-      __ addsw(result, left, Operand(right));
+      __ adds(result, left, Operand(right));
       __ b(slow_path->entry_label(), VS);
-      __ sxtw(result, result);
       break;
     case Token::kSUB:
-      __ subsw(result, left, Operand(right));
+      __ subs(result, left, Operand(right));
       __ b(slow_path->entry_label(), VS);
-      __ sxtw(result, result);
       break;
     case Token::kMUL:
       __ SmiUntag(TMP, left);
-      __ smull(result, TMP, right);
-      __ AsrImmediate(TMP, result, 31);
-      // TMP: result bits 31-63
+      __ mul(result, TMP, right);
+      __ smulh(TMP, TMP, right);
+      // TMP: result bits 64..127.
       __ cmp(TMP, Operand(result, ASR, 63));
       __ b(slow_path->entry_label(), NE);
       break;
@@ -2994,8 +2967,8 @@
 
       __ SmiUntag(TMP, right);
       __ lslv(result, left, TMP);
-      __ asrvw(TMP2, result, TMP);
-      __ cmp(left, Operand(TMP2, SXTW, 0));
+      __ asrv(TMP2, result, TMP);
+      __ CompareRegisters(left, TMP2);
       __ b(slow_path->entry_label(), NE);  // Overflow.
       break;
     case Token::kSHR:
@@ -3005,8 +2978,6 @@
                           reinterpret_cast<int64_t>(Smi::New(Smi::kBits)));
       __ b(slow_path->entry_label(), CS);
 
-      __ AssertSmiInRange(left);
-      __ AssertSmiInRange(right);
       __ SmiUntag(result, right);
       __ SmiUntag(TMP, left);
       __ asrv(result, TMP, result);
@@ -3016,7 +2987,6 @@
       UNIMPLEMENTED();
   }
   __ Bind(slow_path->exit_label());
-  __ AssertSmiInRange(result, Assembler::kValueCanBeHeapPointer);
 }
 
 class CheckedSmiComparisonSlowPath
@@ -3207,28 +3177,20 @@
       case Token::kADD: {
         if (deopt == NULL) {
           __ AddImmediate(result, left, imm);
-          if (is_truncating()) {
-            __ sxtw(result, result);
-          }
         } else {
-          __ AddImmediateSetFlags(result, left, imm, kWord);
+          __ AddImmediateSetFlags(result, left, imm);
           __ b(deopt, VS);
-          __ sxtw(result, result);
         }
         break;
       }
       case Token::kSUB: {
         if (deopt == NULL) {
           __ AddImmediate(result, left, -imm);
-          if (is_truncating()) {
-            __ sxtw(result, result);
-          }
         } else {
           // Negating imm and using AddImmediateSetFlags would not detect the
-          // overflow when imm == kMinInt32.
-          __ SubImmediateSetFlags(result, left, imm, kWord);
+          // overflow when imm == kMinInt64.
+          __ SubImmediateSetFlags(result, left, imm);
           __ b(deopt, VS);
-          __ sxtw(result, result);
         }
         break;
       }
@@ -3236,14 +3198,12 @@
         // Keep left value tagged and untag right value.
         const intptr_t value = Smi::Cast(constant).Value();
         __ LoadImmediate(TMP, value);
-        __ smull(result, left, TMP);
+        __ mul(result, left, TMP);
         if (deopt != NULL) {
-          __ AsrImmediate(TMP, result, 31);
-          // TMP: result bits 31..63.
+          __ smulh(TMP, left, TMP);
+          // TMP: result bits 64..127.
           __ cmp(TMP, Operand(result, ASR, 63));
           __ b(deopt, NE);
-        } else if (is_truncating()) {
-          __ sxtw(result, result);
         }
         break;
       }
@@ -3254,10 +3214,9 @@
         const intptr_t shift_count =
             Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize;
         ASSERT(kSmiTagSize == 1);
-        __ AsrImmediate(TMP, left, 31);  // All 1s or all 0s.
+        __ AsrImmediate(TMP, left, 63);
         ASSERT(shift_count > 1);  // 1, -1 case handled above.
         const Register temp = TMP2;
-        // Adjust so that we round to 0 instead of round down.
         __ add(temp, left, Operand(TMP, LSR, 64 - shift_count));
         ASSERT(shift_count > 0);
         __ AsrImmediate(result, temp, shift_count);
@@ -3292,7 +3251,6 @@
         UNREACHABLE();
         break;
     }
-    __ AssertSmiInRange(result);
     return;
   }
 
@@ -3301,26 +3259,18 @@
     case Token::kADD: {
       if (deopt == NULL) {
         __ add(result, left, Operand(right));
-        if (is_truncating()) {
-          __ sxtw(result, result);
-        }
       } else {
-        __ addsw(result, left, Operand(right));
+        __ adds(result, left, Operand(right));
         __ b(deopt, VS);
-        __ sxtw(result, result);
       }
       break;
     }
     case Token::kSUB: {
       if (deopt == NULL) {
         __ sub(result, left, Operand(right));
-        if (is_truncating()) {
-          __ sxtw(result, result);
-        }
       } else {
-        __ subsw(result, left, Operand(right));
+        __ subs(result, left, Operand(right));
         __ b(deopt, VS);
-        __ sxtw(result, result);
       }
       break;
     }
@@ -3328,13 +3278,10 @@
       __ SmiUntag(TMP, left);
       if (deopt == NULL) {
         __ mul(result, TMP, right);
-        if (is_truncating()) {
-          __ sxtw(result, result);
-        }
       } else {
-        __ smull(result, TMP, right);
-        __ AsrImmediate(TMP, result, 31);
-        // TMP: result bits 31..63.
+        __ mul(result, TMP, right);
+        __ smulh(TMP, TMP, right);
+        // TMP: result bits 64..127.
         __ cmp(TMP, Operand(result, ASR, 63));
         __ b(deopt, NE);
       }
@@ -3369,7 +3316,7 @@
 
       // Check the corner case of dividing the 'MIN_SMI' with -1, in which
       // case we cannot tag the result.
-      __ CompareImmediate(result, 0x40000000LL);
+      __ CompareImmediate(result, 0x4000000000000000LL);
       __ b(deopt, EQ);
       __ SmiTag(result);
       break;
@@ -3414,10 +3361,8 @@
         __ b(deopt, LT);
       }
       __ SmiUntag(TMP, right);
-      // The asrv operation masks the count to 6 bits, but any shift between 31
-      // and 63 gives the same result because 32 bit Smis are stored sign
-      // extended in the registers.
-      const intptr_t kCountLimit = 0x1F;
+      // sarl operation masks the count to 6 bits.
+      const intptr_t kCountLimit = 0x3F;
       if (!RangeUtils::OnlyLessThanOrEqualTo(right_range(), kCountLimit)) {
         __ LoadImmediate(TMP2, kCountLimit);
         __ CompareRegisters(TMP, TMP2);
@@ -3446,7 +3391,6 @@
       UNREACHABLE();
       break;
   }
-  __ AssertSmiInRange(result);
 }
 
 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone,
@@ -3599,17 +3543,10 @@
   ASSERT((from_representation() == kUnboxedInt32) ||
          (from_representation() == kUnboxedUint32));
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1;
+  const intptr_t kNumTemps = 0;
   LocationSummary* summary = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps,
-                      ValueFitsSmi() ? LocationSummary::kNoCall
-                                     : LocationSummary::kCallOnSlowPath);
-  // Get two distinct registers for input and output, plus a temp
-  // register for testing for overflow and allocating a Mint.
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
-  if (!ValueFitsSmi()) {
-    summary->set_temp(0, Location::RequiresRegister());
-  }
   summary->set_out(0, Location::RequiresRegister());
   return summary;
 }
@@ -3618,51 +3555,16 @@
   Register value = locs()->in(0).reg();
   Register out = locs()->out(0).reg();
   ASSERT(value != out);
-  Label done;
 
+  ASSERT(kSmiTagSize == 1);
+  // TODO(vegorov) implement and use UBFM/SBFM for this.
+  __ LslImmediate(out, value, 32);
   if (from_representation() == kUnboxedInt32) {
-    ASSERT(kSmiTag == 0);
-    // Signed Bitfield Insert in Zero instruction extracts the 31 significant
-    // bits from a Smi.
-    __ sbfiz(out, value, kSmiTagSize, 32 - kSmiTagSize);
-    if (ValueFitsSmi()) {
-      return;
-    }
-    Register temp = locs()->temp(0).reg();
-    __ cmp(out, Operand(value, LSL, 1));
-    __ b(&done, EQ);  // Jump if the sbfiz instruction didn't lose info.
-    BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
-                                    temp);
-    __ sxtw(temp, value);
+    __ AsrImmediate(out, out, 32 - kSmiTagSize);
   } else {
     ASSERT(from_representation() == kUnboxedUint32);
-    ASSERT(kSmiTag == 0);
-    // A 32 bit positive Smi has one tag bit and one unused sign bit,
-    // leaving only 30 bits for the payload.
-    __ ubfiz(out, value, kSmiTagSize, kSmiBits);
-    if (ValueFitsSmi()) {
-      return;
-    }
-    Register temp = locs()->temp(0).reg();
-    __ TestImmediate(value, 0xc0000000);
-    __ b(&done, EQ);  // Jump if both bits are zero.
-    BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
-                                    temp);
-    __ ubfiz(temp, value, 0, 32);  // Zero extend word.
+    __ LsrImmediate(out, out, 32 - kSmiTagSize);
   }
-
-  __ StoreToOffset(locs()->temp(0).reg(), out,
-                   Mint::value_offset() - kHeapObjectTag);
-
-#if defined(DEBUG)
-  Label skip_smi_test;
-  __ b(&skip_smi_test);
-  __ Bind(&done);
-  __ AssertSmiInRange(out, Assembler::kValueCanBeHeapPointer);
-  __ Bind(&skip_smi_test);
-#else
-  __ Bind(&done);
-#endif
 }
 
 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone,
@@ -3690,8 +3592,7 @@
   }
 
   ASSERT(kSmiTag == 0);
-  __ LslImmediate(out, in, kSmiTagSize, kWord);
-  __ sxtw(out, out);
+  __ LslImmediate(out, in, kSmiTagSize);
   Label done;
   __ cmp(in, Operand(out, ASR, kSmiTagSize));
   __ b(&done, EQ);
@@ -4432,9 +4333,8 @@
   switch (op_kind()) {
     case Token::kNEGATE: {
       Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp);
-      __ subsw(result, ZR, Operand(value));
+      __ subs(result, ZR, Operand(value));
       __ b(deopt, VS);
-      __ sxtw(result, result);
       break;
     }
     case Token::kBIT_NOT:
@@ -4445,7 +4345,6 @@
     default:
       UNREACHABLE();
   }
-  __ AssertSmiInRange(result);
 }
 
 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone,
@@ -4497,7 +4396,7 @@
   const Register value = locs()->in(0).reg();
   const VRegister result = locs()->out(0).fpu_reg();
   __ SmiUntag(TMP, value);
-  __ scvtfdw(result, TMP);
+  __ scvtfdx(result, TMP);
 }
 
 LocationSummary* Int64ToDoubleInstr::MakeLocationSummary(Zone* zone,
@@ -4541,13 +4440,12 @@
   __ fcmpd(VTMP, VTMP);
   __ b(&do_call, VS);
 
-  __ fcvtzdsx(result, VTMP);
+  __ fcvtzds(result, VTMP);
   // Overflow is signaled with minint.
 
   // Check for overflow and that it fits into Smi.
-  __ AsrImmediate(TMP, result, 30);
-  __ cmp(TMP, Operand(result, ASR, 63));
-  __ b(&do_call, NE);
+  __ CompareImmediate(result, 0xC000000000000000);
+  __ b(&do_call, MI);
   __ SmiTag(result);
   __ b(&done);
   __ Bind(&do_call);
@@ -4564,7 +4462,6 @@
                                args_info, locs(), ICData::Handle(),
                                ICData::kStatic);
   __ Bind(&done);
-  __ AssertSmiInRange(result, Assembler::kValueCanBeHeapPointer);
 }
 
 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone,
@@ -4588,13 +4485,11 @@
   __ fcmpd(value, value);
   __ b(deopt, VS);
 
-  __ fcvtzdsx(result, value);
+  __ fcvtzds(result, value);
   // Check for overflow and that it fits into Smi.
-  __ AsrImmediate(TMP, result, 30);
-  __ cmp(TMP, Operand(result, ASR, 63));
-  __ b(deopt, NE);
+  __ CompareImmediate(result, 0xC000000000000000);
+  __ b(deopt, MI);
   __ SmiTag(result);
-  __ AssertSmiInRange(result);
 }
 
 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone,
@@ -4863,7 +4758,7 @@
 
   // Check the corner case of dividing the 'MIN_SMI' with -1, in which
   // case we cannot tag the result.
-  __ CompareImmediate(result_div, 0x40000000);
+  __ CompareImmediate(result_div, 0x4000000000000000);
   __ b(deopt, EQ);
   // result_mod <- left - right * result_div.
   __ msub(result_mod, TMP, result_div, result_mod);
@@ -5392,10 +5287,6 @@
   Register shifter = locs()->in(1).reg();
 
   // TODO(johnmccutchan): Use range information to avoid these checks.
-  // Assert this is a legitimate Smi in debug mode, but does not assert
-  // anything about the range relative to the bit width.
-  __ AssertSmiInRange(shifter);
-
   __ SmiUntag(TMP, shifter);
   __ CompareImmediate(TMP, 0);
   // If shift value is < 0, deoptimize.
@@ -5415,7 +5306,7 @@
 
   __ CompareImmediate(TMP, kShifterLimit);
   // If shift value is > 31, return zero.
-  __ csel(out, ZR, out, GT);
+  __ csel(out, out, ZR, GT);
 }
 
 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone,
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index bf409ff..b44d650 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -1074,13 +1074,11 @@
     case kTwoByteStringCid:
     case kExternalOneByteStringCid:
     case kExternalTwoByteStringCid:
-      return CompileType::FromCid(kSmiCid);
-
     case kTypedDataInt32ArrayCid:
     case kTypedDataUint32ArrayCid:
+      return CompileType::FromCid(kSmiCid);
+
     case kTypedDataInt64ArrayCid:
-      // TODO(erikcorry): Perhaps this can return a faster type.  See
-      // https://github.com/dart-lang/sdk/issues/32582
       return CompileType::Int();
 
     default:
@@ -1263,24 +1261,16 @@
 
 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone,
                                                          bool opt) const {
-  const bool might_box = (representation() == kTagged) && !can_pack_into_smi();
   const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = might_box ? 2 : 0;
-  LocationSummary* summary = new (zone) LocationSummary(
-      zone, kNumInputs, kNumTemps,
-      might_box ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall);
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
   // The smi index is either untagged (element size == 1), or it is left smi
   // tagged (for all element sizes > 1).
   summary->set_in(1, index_scale() == 1 ? Location::WritableRegister()
                                         : Location::RequiresRegister());
   summary->set_out(0, Location::RequiresRegister());
-
-  if (might_box) {
-    summary->set_temp(0, Location::RequiresRegister());
-    summary->set_temp(1, Location::RequiresRegister());
-  }
-
   return summary;
 }
 
@@ -1312,6 +1302,7 @@
         default:
           UNREACHABLE();
       }
+      __ SmiTag(result);
       break;
     case kTwoByteStringCid:
     case kExternalTwoByteStringCid:
@@ -1325,34 +1316,12 @@
         default:
           UNREACHABLE();
       }
+      __ SmiTag(result);
       break;
     default:
       UNREACHABLE();
       break;
   }
-  if (representation_ == kTagged) {
-    if (can_pack_into_smi()) {
-      __ SmiTag(result);
-    } else {
-      // If the value cannot fit in a smi then allocate a mint box for it.
-      Register temp = locs()->temp(0).reg();
-      Register temp2 = locs()->temp(1).reg();
-      // Temp register needs to be manually preserved on allocation slow-path.
-      locs()->live_registers()->Add(locs()->temp(0), kUnboxedInt32);
-
-      ASSERT(temp != result);
-      __ MoveRegister(temp, result);
-      __ SmiTag(result);
-
-      Label done;
-      __ TestImmediate(temp, Immediate(0xc0000000ll));
-      __ j(ZERO, &done);
-      BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(),
-                                      result, temp2);
-      __ movq(FieldAddress(result, Mint::value_offset()), temp);
-      __ Bind(&done);
-    }
-  }
 }
 
 Representation StoreIndexedInstr::RequiredInputRepresentation(
@@ -2742,32 +2711,27 @@
   if (locs.in(1).IsConstant()) {
     const Object& constant = locs.in(1).constant();
     ASSERT(constant.IsSmi());
-    // shll operation masks the count to 5 bits.
-    const intptr_t kCountLimit = 0x1F;
+    // shlq operation masks the count to 6 bits.
+    const intptr_t kCountLimit = 0x3F;
     const intptr_t value = Smi::Cast(constant).Value();
     ASSERT((0 < value) && (value < kCountLimit));
     if (shift_left->can_overflow()) {
       if (value == 1) {
         // Use overflow flag.
-        __ shll(left, Immediate(1));
+        __ shlq(left, Immediate(1));
         __ j(OVERFLOW, deopt);
-        __ movsxd(left, left);
         return;
       }
       // Check for overflow.
       Register temp = locs.temp(0).reg();
       __ movq(temp, left);
-      __ shll(left, Immediate(value));
-      __ sarl(left, Immediate(value));
-      __ movsxd(left, left);
+      __ shlq(left, Immediate(value));
+      __ sarq(left, Immediate(value));
       __ cmpq(left, temp);
       __ j(NOT_EQUAL, deopt);  // Overflow.
     }
     // Shift for result now we know there is no overflow.
     __ shlq(left, Immediate(value));
-    if (shift_left->is_truncating()) {
-      __ movsxd(left, left);
-    }
     return;
   }
 
@@ -2778,32 +2742,23 @@
     // TODO(srdjan): Implement code below for is_truncating().
     // If left is constant, we know the maximal allowed size for right.
     const Object& obj = shift_left->left()->BoundConstant();
-    // Even though we have a non-Smi constant on the left, we might still emit
-    // a Smi op here.  In that case the Smi check above will have deopted, so
-    // we can't reach this point. Emit a breakpoint to be sure.
-    if (!obj.IsSmi()) {
-      __ int3();
-      return;
-    }
-    const intptr_t left_int = Smi::Cast(obj).Value();
-    if (left_int == 0) {
-      __ CompareImmediate(right, Immediate(0));
-      __ j(NEGATIVE, deopt);
-      return;
-    }
-    const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
-    const bool right_needs_check =
-        !RangeUtils::IsWithin(right_range, 0, max_right - 1);
-    if (right_needs_check) {
-      __ CompareImmediate(
-          right, Immediate(reinterpret_cast<int64_t>(Smi::New(max_right))));
-      __ j(ABOVE_EQUAL, deopt);
-    }
-    __ AssertSmiInRange(right);
-    __ SmiUntag(right);
-    __ shlq(left, right);
-    if (shift_left->is_truncating()) {
-      __ movsxd(left, left);
+    if (obj.IsSmi()) {
+      const intptr_t left_int = Smi::Cast(obj).Value();
+      if (left_int == 0) {
+        __ CompareImmediate(right, Immediate(0));
+        __ j(NEGATIVE, deopt);
+        return;
+      }
+      const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
+      const bool right_needs_check =
+          !RangeUtils::IsWithin(right_range, 0, max_right - 1);
+      if (right_needs_check) {
+        __ CompareImmediate(
+            right, Immediate(reinterpret_cast<int64_t>(Smi::New(max_right))));
+        __ j(ABOVE_EQUAL, deopt);
+      }
+      __ SmiUntag(right);
+      __ shlq(left, right);
     }
     return;
   }
@@ -2827,18 +2782,13 @@
       __ xorq(left, left);
       __ jmp(&done, Assembler::kNearJump);
       __ Bind(&is_not_zero);
-      __ AssertSmiInRange(right);
       __ SmiUntag(right);
       __ shlq(left, right);
       __ Bind(&done);
     } else {
-      __ AssertSmiInRange(right);
       __ SmiUntag(right);
       __ shlq(left, right);
     }
-    if (shift_left->is_truncating()) {
-      __ movsxd(left, left);
-    }
   } else {
     if (right_needs_check) {
       ASSERT(shift_left->CanDeoptimize());
@@ -2848,18 +2798,16 @@
     }
     // Left is not a constant.
     Register temp = locs.temp(0).reg();
-    // Check if count is too large for handling it inlined.
-    __ movl(temp, left);
-    __ AssertSmiInRange(right);
+    // Check if count too large for handling it inlined.
+    __ movq(temp, left);
     __ SmiUntag(right);
     // Overflow test (preserve temp and right);
-    __ shll(temp, right);
-    __ sarl(temp, right);
-    __ cmpl(temp, left);
+    __ shlq(left, right);
+    __ sarq(left, right);
+    __ cmpq(left, temp);
     __ j(NOT_EQUAL, deopt);  // Overflow.
     // Shift for result now we know there is no overflow.
     __ shlq(left, right);
-    ASSERT(!shift_left->is_truncating());
   }
 }
 
@@ -2959,23 +2907,19 @@
   switch (op_kind()) {
     case Token::kADD:
       __ movq(result, left);
-      __ addl(result, right);
+      __ addq(result, right);
       __ j(OVERFLOW, slow_path->entry_label());
-      __ movsxd(result, result);
       break;
     case Token::kSUB:
       __ movq(result, left);
-      __ subl(result, right);
+      __ subq(result, right);
       __ j(OVERFLOW, slow_path->entry_label());
-      __ movsxd(result, result);
       break;
     case Token::kMUL:
       __ movq(result, left);
-      __ AssertSmiInRange(result);
       __ SmiUntag(result);
-      __ imull(result, right);
+      __ imulq(result, right);
       __ j(OVERFLOW, slow_path->entry_label());
-      __ movsxd(result, result);
       break;
     case Token::kBIT_OR:
       ASSERT(left == result);
@@ -2996,15 +2940,13 @@
       __ j(ABOVE_EQUAL, slow_path->entry_label());
 
       __ movq(RCX, right);
-      __ AssertSmiInRange(RCX);
       __ SmiUntag(RCX);
       __ movq(result, left);
-      __ shll(result, RCX);
+      __ shlq(result, RCX);
       __ movq(TMP, result);
-      __ sarl(TMP, RCX);
-      __ cmpl(TMP, left);
+      __ sarq(TMP, RCX);
+      __ cmpq(TMP, left);
       __ j(NOT_EQUAL, slow_path->entry_label());
-      __ movsxd(result, result);
       break;
     case Token::kSHR: {
       Label shift_count_ok;
@@ -3013,8 +2955,6 @@
       __ cmpq(right, Immediate(Smi::RawValue(Smi::kBits)));
       __ j(ABOVE_EQUAL, slow_path->entry_label());
 
-      __ AssertSmiInRange(left);
-      __ AssertSmiInRange(right);
       __ movq(RCX, right);
       __ SmiUntag(RCX);
       __ movq(result, left);
@@ -3272,41 +3212,20 @@
     const int64_t imm = reinterpret_cast<int64_t>(constant.raw());
     switch (op_kind()) {
       case Token::kADD: {
-        if (deopt != NULL) {
-          __ AddImmediate(left, Immediate(imm), Assembler::k32Bit);
-          __ j(OVERFLOW, deopt);
-        } else {
-          __ AddImmediate(left, Immediate(imm), Assembler::k64Bit);
-        }
-        if (deopt != NULL || is_truncating()) {
-          __ movsxd(left, left);
-        }
+        __ AddImmediate(left, Immediate(imm));
+        if (deopt != NULL) __ j(OVERFLOW, deopt);
         break;
       }
       case Token::kSUB: {
-        if (deopt != NULL) {
-          __ SubImmediate(left, Immediate(imm), Assembler::k32Bit);
-          __ j(OVERFLOW, deopt);
-        } else {
-          __ SubImmediate(left, Immediate(imm), Assembler::k64Bit);
-        }
-        if (deopt != NULL || is_truncating()) {
-          __ movsxd(left, left);
-        }
+        __ SubImmediate(left, Immediate(imm));
+        if (deopt != NULL) __ j(OVERFLOW, deopt);
         break;
       }
       case Token::kMUL: {
         // Keep left value tagged and untag right value.
         const intptr_t value = Smi::Cast(constant).Value();
-        if (deopt != NULL) {
-          __ MulImmediate(left, Immediate(value), Assembler::k32Bit);
-          __ j(OVERFLOW, deopt);
-        } else {
-          __ MulImmediate(left, Immediate(value), Assembler::k64Bit);
-        }
-        if (deopt != NULL || is_truncating()) {
-          __ movsxd(left, left);
-        }
+        __ MulImmediate(left, Immediate(value));
+        if (deopt != NULL) __ j(OVERFLOW, deopt);
         break;
       }
       case Token::kTRUNCDIV: {
@@ -3318,9 +3237,7 @@
         ASSERT(kSmiTagSize == 1);
         Register temp = locs()->temp(0).reg();
         __ movq(temp, left);
-        // Since Smis are sign extended this is enough shift to put all-1s or
-        // all-0s in the temp register.
-        __ sarq(temp, Immediate(31));
+        __ sarq(temp, Immediate(63));
         ASSERT(shift_count > 1);  // 1, -1 case handled above.
         __ shrq(temp, Immediate(64 - shift_count));
         __ addq(left, temp);
@@ -3349,10 +3266,8 @@
       }
 
       case Token::kSHR: {
-        // The sarq operation masks the count to 6 bits, but any shift between
-        // 31 and 63 gives the same result because 32 bit Smis are stored sign
-        // extended in the registers.
-        const intptr_t kCountLimit = 0x1F;
+        // sarq operation masks the count to 6 bits.
+        const intptr_t kCountLimit = 0x3F;
         const intptr_t value = Smi::Cast(constant).Value();
         __ sarq(left,
                 Immediate(Utils::Minimum(value + kSmiTagSize, kCountLimit)));
@@ -3364,7 +3279,6 @@
         UNREACHABLE();
         break;
     }
-    __ AssertSmiInRange(left);
     return;
   }  // locs()->in(1).IsConstant().
 
@@ -3372,40 +3286,19 @@
     const Address& right = locs()->in(1).ToStackSlotAddress();
     switch (op_kind()) {
       case Token::kADD: {
-        if (deopt != NULL) {
-          __ addl(left, right);
-          __ j(OVERFLOW, deopt);
-        } else {
-          __ addq(left, right);
-        }
-        if (deopt != NULL || is_truncating()) {
-          __ movsxd(left, left);
-        }
+        __ addq(left, right);
+        if (deopt != NULL) __ j(OVERFLOW, deopt);
         break;
       }
       case Token::kSUB: {
-        if (deopt != NULL) {
-          __ subl(left, right);
-          __ j(OVERFLOW, deopt);
-        } else {
-          __ subq(left, right);
-        }
-        if (deopt != NULL || is_truncating()) {
-          __ movsxd(left, left);
-        }
+        __ subq(left, right);
+        if (deopt != NULL) __ j(OVERFLOW, deopt);
         break;
       }
       case Token::kMUL: {
         __ SmiUntag(left);
-        if (deopt != NULL) {
-          __ imull(left, right);
-          __ j(OVERFLOW, deopt);
-        } else {
-          __ imulq(left, right);
-        }
-        if (deopt != NULL || is_truncating()) {
-          __ movsxd(left, left);
-        }
+        __ imulq(left, right);
+        if (deopt != NULL) __ j(OVERFLOW, deopt);
         break;
       }
       case Token::kBIT_AND: {
@@ -3434,40 +3327,19 @@
   Register right = locs()->in(1).reg();
   switch (op_kind()) {
     case Token::kADD: {
-      if (deopt != NULL) {
-        __ addl(left, right);
-        __ j(OVERFLOW, deopt);
-      } else {
-        __ addq(left, right);
-      }
-      if (deopt != NULL || is_truncating()) {
-        __ movsxd(left, left);
-      }
+      __ addq(left, right);
+      if (deopt != NULL) __ j(OVERFLOW, deopt);
       break;
     }
     case Token::kSUB: {
-      if (deopt != NULL) {
-        __ subl(left, right);
-        __ j(OVERFLOW, deopt);
-      } else {
-        __ subq(left, right);
-      }
-      if (deopt != NULL || is_truncating()) {
-        __ movsxd(left, left);
-      }
+      __ subq(left, right);
+      if (deopt != NULL) __ j(OVERFLOW, deopt);
       break;
     }
     case Token::kMUL: {
       __ SmiUntag(left);
-      if (deopt != NULL) {
-        __ imull(left, right);
-        __ j(OVERFLOW, deopt);
-      } else {
-        __ imulq(left, right);
-      }
-      if (deopt != NULL || is_truncating()) {
-        __ movsxd(left, left);
-      }
+      __ imulq(left, right);
+      if (deopt != NULL) __ j(OVERFLOW, deopt);
       break;
     }
     case Token::kBIT_AND: {
@@ -3486,6 +3358,8 @@
       break;
     }
     case Token::kTRUNCDIV: {
+      Label not_32bit, done;
+
       Register temp = locs()->temp(0).reg();
       ASSERT(left == RAX);
       ASSERT((right != RDX) && (right != RAX));
@@ -3496,20 +3370,43 @@
         __ testq(right, right);
         __ j(ZERO, deopt);
       }
+      // Check if both operands fit into 32bits as idiv with 64bit operands
+      // requires twice as many cycles and has much higher latency.
+      // We are checking this before untagging them to avoid corner case
+      // dividing INT_MAX by -1 that raises exception because quotient is
+      // too large for 32bit register.
+      __ movsxd(temp, left);
+      __ cmpq(temp, left);
+      __ j(NOT_EQUAL, &not_32bit);
+      __ movsxd(temp, right);
+      __ cmpq(temp, right);
+      __ j(NOT_EQUAL, &not_32bit);
+
       // Both operands are 31bit smis. Divide using 32bit idiv.
       __ SmiUntag(left);
       __ SmiUntag(right);
       __ cdq();
       __ idivl(right);
+      __ movsxd(result, result);
+      __ jmp(&done);
+
+      // Divide using 64bit idiv.
+      __ Bind(&not_32bit);
+      __ SmiUntag(left);
+      __ SmiUntag(right);
+      __ cqo();         // Sign extend RAX -> RDX:RAX.
+      __ idivq(right);  //  RAX: quotient, RDX: remainder.
       // Check the corner case of dividing the 'MIN_SMI' with -1, in which
       // case we cannot tag the result.
-      __ cmpl(result, Immediate(0x40000000));
+      __ CompareImmediate(result, Immediate(0x4000000000000000));
       __ j(EQUAL, deopt);
-      __ movsxd(result, result);
+      __ Bind(&done);
       __ SmiTag(result);
       break;
     }
     case Token::kMOD: {
+      Label not_32bit, div_done;
+
       Register temp = locs()->temp(0).reg();
       ASSERT(left == RDX);
       ASSERT((right != RDX) && (right != RAX));
@@ -3520,6 +3417,17 @@
         __ testq(right, right);
         __ j(ZERO, deopt);
       }
+      // Check if both operands fit into 32bits as idiv with 64bit operands
+      // requires twice as many cycles and has much higher latency.
+      // We are checking this before untagging them to avoid corner case
+      // dividing INT_MAX by -1 that raises exception because quotient is
+      // too large for 32bit register.
+      __ movsxd(temp, left);
+      __ cmpq(temp, left);
+      __ j(NOT_EQUAL, &not_32bit);
+      __ movsxd(temp, right);
+      __ cmpq(temp, right);
+      __ j(NOT_EQUAL, &not_32bit);
       // Both operands are 31bit smis. Divide using 32bit idiv.
       __ SmiUntag(left);
       __ SmiUntag(right);
@@ -3527,7 +3435,16 @@
       __ cdq();
       __ idivl(right);
       __ movsxd(result, result);
+      __ jmp(&div_done);
 
+      // Divide using 64bit idiv.
+      __ Bind(&not_32bit);
+      __ SmiUntag(left);
+      __ SmiUntag(right);
+      __ movq(RAX, RDX);
+      __ cqo();         // Sign extend RAX -> RDX:RAX.
+      __ idivq(right);  //  RAX: quotient, RDX: remainder.
+      __ Bind(&div_done);
       //  res = left % right;
       //  if (res < 0) {
       //    if (right < 0) {
@@ -3565,10 +3482,7 @@
         __ j(LESS, deopt);
       }
       __ SmiUntag(right);
-      // The sarq operation masks the count to 6 bits, but any shift between 31
-      // and 63 gives the same result because 32 bit Smis are stored sign
-      // extended in the registers.  We check for 63 in order to take the branch
-      // more predictably.
+      // sarq operation masks the count to 6 bits.
       const intptr_t kCountLimit = 0x3F;
       if (!RangeUtils::OnlyLessThanOrEqualTo(right_range(), kCountLimit)) {
         __ CompareImmediate(right, Immediate(kCountLimit));
@@ -3781,52 +3695,41 @@
                                        GetDeoptId(), ICData::kDeoptUnboxInteger)
                                  : NULL;
   ASSERT(value == locs()->out(0).reg());
-  Label done_and_no_need_to_check_range;
-
-  ASSERT(locs()->out(0).reg() == value);
 
   if (value_cid == kSmiCid) {
-    __ AssertSmiInRange(value);
     __ SmiUntag(value);
-    return;
   } else if (value_cid == kMintCid) {
     __ movq(value, FieldAddress(value, Mint::value_offset()));
   } else if (!CanDeoptimize()) {
+    // Type information is not conclusive, but range analysis found
+    // the value to be in int64 range. Therefore it must be a smi
+    // or mint value.
+    ASSERT(is_truncating());
     Label done;
     __ SmiUntag(value);
     __ j(NOT_CARRY, &done, Assembler::kNearJump);
-    // Multiply by two in addressing mode because we erroneously
-    // untagged a pointer by dividing it by two.
-    Address value_field(value, TIMES_2, Mint::value_offset());
-    if (is_truncating()) {
-      __ movl(value, value_field);
-      __ movsxd(value, value);
-    } else {
-      __ movq(value, value_field);
-    }
+    __ movq(value, Address(value, TIMES_2, Mint::value_offset()));
     __ Bind(&done);
     return;
   } else {
-    __ SmiUntagOrCheckClass(value, kMintCid, &done_and_no_need_to_check_range);
+    Label done;
+    // Optimistically untag value.
+    __ SmiUntagOrCheckClass(value, kMintCid, &done);
     __ j(NOT_EQUAL, deopt);
-    // Multiply by two in addressing mode because we erroneously
-    // untagged a pointer by dividing it by two.
+    // Undo untagging by multiplying value with 2.
     __ movq(value, Address(value, TIMES_2, Mint::value_offset()));
+    __ Bind(&done);
   }
 
-  // We get here for the Mint cases, which might be out of range for an
-  // unboxed int32 output.
-
-  // TODO(vegorov): Truncating unboxing leaves garbage in the higher word.
-  // Is this the best semantics?
+  // TODO(vegorov): as it is implemented right now truncating unboxing would
+  // leave "garbage" in the higher word.
   if (!is_truncating() && (deopt != NULL)) {
     ASSERT(representation() == kUnboxedInt32);
-    const Register temp = locs()->temp(0).reg();
+    Register temp = locs()->temp(0).reg();
     __ movsxd(temp, value);
     __ cmpq(temp, value);
     __ j(NOT_EQUAL, deopt);
   }
-  __ Bind(&done_and_no_need_to_check_range);
 }
 
 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone,
@@ -3834,61 +3737,27 @@
   ASSERT((from_representation() == kUnboxedInt32) ||
          (from_representation() == kUnboxedUint32));
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1;
+  const intptr_t kNumTemps = 0;
   LocationSummary* summary = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps,
-                      ValueFitsSmi() ? LocationSummary::kNoCall
-                                     : LocationSummary::kCallOnSlowPath);
-  const bool needs_writable_input =
-      ValueFitsSmi() || (from_representation() == kUnboxedUint32);
-  summary->set_in(0, needs_writable_input ? Location::RequiresRegister()
-                                          : Location::WritableRegister());
-  if (!ValueFitsSmi()) {
-    summary->set_temp(0, Location::RequiresRegister());
-  }
-  summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput()
-                                     : Location::RequiresRegister());
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_out(0, Location::RequiresRegister());
   return summary;
 }
 
 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
   const Register value = locs()->in(0).reg();
   const Register out = locs()->out(0).reg();
-  Label done;
+  ASSERT(value != out);
 
+  ASSERT(kSmiTagSize == 1);
   if (from_representation() == kUnboxedInt32) {
-    __ MoveRegister(out, value);
-    ASSERT(kSmiTagMask == 1 && kSmiTag == 0);
-    __ addl(out, out);
-    __ movsxd(out, out);  // Does not affect flags.
+    __ movsxd(out, value);
   } else {
-    // Unsigned.
+    ASSERT(from_representation() == kUnboxedUint32);
     __ movl(out, value);
-    __ SmiTag(out);
   }
-
-  if (!ValueFitsSmi()) {
-    if (from_representation() == kUnboxedInt32) {
-      __ j(NO_OVERFLOW, &done);
-    } else {
-      ASSERT(value != out);
-      __ TestImmediate(value, Immediate(0xc0000000ll));
-      __ j(ZERO, &done);
-    }
-    // Allocate a mint.
-    // Value input is a writable register and we have to inform the compiler of
-    // the type so it can be preserved untagged on the slow path
-    locs()->live_registers()->Add(locs()->in(0), kUnboxedInt32);
-    BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
-                                    locs()->temp(0).reg());
-    if (from_representation() == kUnboxedInt32) {
-      __ movsxd(value, value);
-    } else {
-      __ movl(value, value);
-    }
-    __ movq(FieldAddress(out, Mint::value_offset()), value);
-    __ Bind(&done);
-  }
+  __ SmiTag(out);
 }
 
 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone,
@@ -3910,20 +3779,15 @@
 void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
   const Register out = locs()->out(0).reg();
   const Register value = locs()->in(0).reg();
-  __ leaq(out, Address(value, value, TIMES_1, 0));
+  __ MoveRegister(out, value);
+  __ SmiTag(out);
   if (!ValueFitsSmi()) {
     const Register temp = locs()->temp(0).reg();
     Label done;
-    __ movq(temp, value);
-    __ sarq(temp, Immediate(30));
-    __ addq(temp, Immediate(1));
-    __ cmpq(temp, Immediate(2));
-    __ j(BELOW, &done);
-
+    __ j(NO_OVERFLOW, &done);
     BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
                                     temp);
     __ movq(FieldAddress(out, Mint::value_offset()), value);
-
     __ Bind(&done);
   }
 }
@@ -4485,9 +4349,8 @@
   switch (op_kind()) {
     case Token::kNEGATE: {
       Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp);
-      __ cmpq(value, Immediate(-0x80000000ll));
-      __ j(EQUAL, deopt);
       __ negq(value);
+      __ j(OVERFLOW, deopt);
       break;
     }
     case Token::kBIT_NOT:
@@ -4636,7 +4499,6 @@
 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Register value = locs()->in(0).reg();
   FpuRegister result = locs()->out(0).fpu_reg();
-  __ AssertSmiInRange(value);
   __ SmiUntag(value);
   __ cvtsi2sdq(result, value);
 }
@@ -4666,15 +4528,14 @@
   ASSERT(result != value_obj);
   ASSERT(result != temp);
   __ movsd(value_double, FieldAddress(value_obj, Double::value_offset()));
-  __ cvttsd2sil(result, value_double);
+  __ cvttsd2siq(result, value_double);
   // Overflow is signalled with minint.
   Label do_call, done;
   // Check for overflow and that it fits into Smi.
-  __ movl(temp, result);
-  __ shll(temp, Immediate(1));
+  __ movq(temp, result);
+  __ shlq(temp, Immediate(1));
   __ j(OVERFLOW, &do_call, Assembler::kNearJump);
-  ASSERT(kSmiTagShift == 1 && kSmiTag == 0);
-  __ movsxd(result, temp);
+  __ SmiTag(result);
   __ jmp(&done);
   __ Bind(&do_call);
   __ pushq(value_obj);
@@ -4710,15 +4571,14 @@
   XmmRegister value = locs()->in(0).fpu_reg();
   Register temp = locs()->temp(0).reg();
 
-  __ cvttsd2sil(result, value);
+  __ cvttsd2siq(result, value);
   // Overflow is signalled with minint.
   Label do_call, done;
   // Check for overflow and that it fits into Smi.
-  __ movl(temp, result);
-  __ shll(temp, Immediate(1));
+  __ movq(temp, result);
+  __ shlq(temp, Immediate(1));
   __ j(OVERFLOW, deopt);
-  ASSERT(kSmiTagShift == 1 && kSmiTag == 0);
-  __ movsxd(result, temp);
+  __ SmiTag(result);
 }
 
 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone,
@@ -5017,7 +4877,6 @@
   // Both inputs must be writable because they will be untagged.
   summary->set_in(0, Location::RegisterLocation(RAX));
   summary->set_in(1, Location::WritableRegister());
-  // Output is a pair of registers.
   summary->set_out(0, Location::Pair(Location::RegisterLocation(RAX),
                                      Location::RegisterLocation(RDX)));
   return summary;
@@ -5032,26 +4891,50 @@
   PairLocation* pair = locs()->out(0).AsPairLocation();
   Register result1 = pair->At(0).reg();
   Register result2 = pair->At(1).reg();
+  Label not_32bit, done;
+  Register temp = RDX;
+  ASSERT(left == RAX);
+  ASSERT((right != RDX) && (right != RAX));
+  ASSERT(result1 == RAX);
+  ASSERT(result2 == RDX);
   if (RangeUtils::CanBeZero(divisor_range())) {
     // Handle divide by zero in runtime.
     __ testq(right, right);
     __ j(ZERO, deopt);
   }
-  ASSERT(left == RAX);
-  ASSERT((right != RDX) && (right != RAX));
-  ASSERT(result1 == RAX);
-  ASSERT(result2 == RDX);
+  // Check if both operands fit into 32bits as idiv with 64bit operands
+  // requires twice as many cycles and has much higher latency.
+  // We are checking this before untagging them to avoid corner case
+  // dividing INT_MAX by -1 that raises exception because quotient is
+  // too large for 32bit register.
+  __ movsxd(temp, left);
+  __ cmpq(temp, left);
+  __ j(NOT_EQUAL, &not_32bit);
+  __ movsxd(temp, right);
+  __ cmpq(temp, right);
+  __ j(NOT_EQUAL, &not_32bit);
+
   // Both operands are 31bit smis. Divide using 32bit idiv.
   __ SmiUntag(left);
   __ SmiUntag(right);
   __ cdq();
   __ idivl(right);
-  // Check the corner case of dividing the 'MIN_SMI' with -1, in which
-  // case we cannot tag the result.
-  __ cmpl(RAX, Immediate(0x40000000));
-  __ j(EQUAL, deopt);
   __ movsxd(RAX, RAX);
   __ movsxd(RDX, RDX);
+  __ jmp(&done);
+
+  // Divide using 64bit idiv.
+  __ Bind(&not_32bit);
+  __ SmiUntag(left);
+  __ SmiUntag(right);
+  __ cqo();         // Sign extend RAX -> RDX:RAX.
+  __ idivq(right);  //  RAX: quotient, RDX: remainder.
+  // Check the corner case of dividing the 'MIN_SMI' with -1, in which
+  // case we cannot tag the result.
+  __ CompareImmediate(RAX, Immediate(0x4000000000000000));
+  __ j(EQUAL, deopt);
+  __ Bind(&done);
+
   // Modulo correction (RDX).
   //  res = left % right;
   //  if (res < 0) {
@@ -5061,16 +4944,16 @@
   //      res = res + right;
   //    }
   //  }
-  Label done;
+  Label all_done;
   __ cmpq(RDX, Immediate(0));
-  __ j(GREATER_EQUAL, &done, Assembler::kNearJump);
+  __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump);
   // Result is negative, adjust it.
   if ((divisor_range() == NULL) || divisor_range()->Overlaps(-1, 1)) {
     Label subtract;
     __ cmpq(right, Immediate(0));
     __ j(LESS, &subtract, Assembler::kNearJump);
     __ addq(RDX, right);
-    __ jmp(&done, Assembler::kNearJump);
+    __ jmp(&all_done, Assembler::kNearJump);
     __ Bind(&subtract);
     __ subq(RDX, right);
   } else if (divisor_range()->IsPositive()) {
@@ -5080,7 +4963,7 @@
     // Right is negative.
     __ subq(RDX, right);
   }
-  __ Bind(&done);
+  __ Bind(&all_done);
 
   __ SmiTag(RAX);
   __ SmiTag(RDX);
@@ -5422,7 +5305,6 @@
     // Code for a variable shift amount.
     // Deoptimize if shift count is > 63 or negative.
     // Sarq and shlq instructions mask the count to 6 bits.
-    __ AssertSmiInRange(RCX);
     __ SmiUntag(RCX);
     if (!IsShiftCountInRange()) {
       __ cmpq(RCX, Immediate(kMintShiftCountLimit));
@@ -5455,15 +5337,15 @@
 }
 
 CompileType BinaryUint32OpInstr::ComputeType() const {
-  return CompileType::Int();
+  return CompileType::FromCid(kSmiCid);
 }
 
 CompileType ShiftUint32OpInstr::ComputeType() const {
-  return CompileType::Int();
+  return CompileType::FromCid(kSmiCid);
 }
 
 CompileType UnaryUint32OpInstr::ComputeType() const {
-  return CompileType::Int();
+  return CompileType::FromCid(kSmiCid);
 }
 
 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone,
@@ -5578,7 +5460,6 @@
   Label zero;
 
   // TODO(johnmccutchan): Use range information to avoid these checks.
-  __ AssertSmiInRange(shifter);
   __ SmiUntag(shifter);
   __ cmpq(shifter, Immediate(0));
   // If shift value is < 0, deoptimize.
@@ -5603,7 +5484,7 @@
 
   __ Bind(&zero);
   // Shift was greater than 31 bits, just return zero.
-  __ xorl(left, left);
+  __ xorq(left, left);
 
   // Exit path.
   __ Bind(&done);
@@ -5644,8 +5525,8 @@
     const Register out = locs()->out(0).reg();
     // Representations are bitwise equivalent but we want to normalize
     // upperbits for safety reasons.
-    // TODO(vegorov) if we ensure that we never leave garbage in the upper bits
-    // we could avoid this.
+    // TODO(vegorov) if we ensure that we never use upperbits we could
+    // avoid this.
     __ movl(out, value);
   } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) {
     // Representations are bitwise equivalent.
diff --git a/runtime/vm/compiler/backend/range_analysis_test.cc b/runtime/vm/compiler/backend/range_analysis_test.cc
index 175b42b..081c7e8 100644
--- a/runtime/vm/compiler/backend/range_analysis_test.cc
+++ b/runtime/vm/compiler/backend/range_analysis_test.cc
@@ -66,10 +66,17 @@
                 RangeBoundary::PositiveInfinity());
   TEST_RANGE_OP(Range::Shl, -1, 1, 63, 63, RangeBoundary(kMinInt64),
                 RangeBoundary::PositiveInfinity());
-  TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 30, 30, RangeBoundary(kSmiMin),
-                    RangeBoundary(kSmiMax));
-  TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 62, 62, RangeBoundary(kSmiMin),
-                    RangeBoundary(kSmiMax));
+  if (kBitsPerWord == 64) {
+    TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 62, 62, RangeBoundary(kSmiMin),
+                      RangeBoundary(kSmiMax));
+    TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 30, 30, RangeBoundary(-(1 << 30)),
+                      RangeBoundary(1 << 30));
+  } else {
+    TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 30, 30, RangeBoundary(kSmiMin),
+                      RangeBoundary(kSmiMax));
+    TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 62, 62, RangeBoundary(kSmiMin),
+                      RangeBoundary(kSmiMax));
+  }
   TEST_RANGE_OP(Range::Shl, 0, 100, 0, 64, RangeBoundary(0),
                 RangeBoundary::PositiveInfinity());
   TEST_RANGE_OP(Range::Shl, -100, 0, 0, 64, RangeBoundary::NegativeInfinity(),
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index 870884e..adfdeb3 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -1560,10 +1560,10 @@
 }
 
 void CallSpecializer::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) {
-  // Note that on ARM64 the result can always be packed into a Smi, so this
-  // is never triggered.
-  // TODO(zerny): Use kUnboxedUint32 once it is fully supported/optimized.
+// TODO(zerny): Use kUnboxedUint32 once it is fully supported/optimized.
+#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM)
   if (!instr->can_pack_into_smi()) instr->set_representation(kUnboxedInt64);
+#endif
 }
 
 static bool CidTestResultsContains(const ZoneGrowableArray<intptr_t>& results,
diff --git a/runtime/vm/compiler/intrinsifier_arm64.cc b/runtime/vm/compiler/intrinsifier_arm64.cc
index 2102c93..4598536 100644
--- a/runtime/vm/compiler/intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/intrinsifier_arm64.cc
@@ -265,9 +265,8 @@
 void Intrinsifier::Integer_addFromInteger(Assembler* assembler) {
   Label fall_through;
   TestBothArgumentsSmis(assembler, &fall_through);  // Checks two smis.
-  __ addsw(R0, R0, Operand(R1));                    // Adds.
+  __ adds(R0, R0, Operand(R1));                     // Adds.
   __ b(&fall_through, VS);                          // Fall-through on overflow.
-  __ sxtw(R0, R0);  // Sign extend - flags not affected.
   __ ret();
   __ Bind(&fall_through);
 }
@@ -279,9 +278,8 @@
 void Intrinsifier::Integer_subFromInteger(Assembler* assembler) {
   Label fall_through;
   TestBothArgumentsSmis(assembler, &fall_through);
-  __ subsw(R0, R0, Operand(R1));  // Subtract.
-  __ b(&fall_through, VS);        // Fall-through on overflow.
-  __ sxtw(R0, R0);                // Sign extend - flags not affected.
+  __ subs(R0, R0, Operand(R1));  // Subtract.
+  __ b(&fall_through, VS);       // Fall-through on overflow.
   __ ret();
   __ Bind(&fall_through);
 }
@@ -289,9 +287,8 @@
 void Intrinsifier::Integer_sub(Assembler* assembler) {
   Label fall_through;
   TestBothArgumentsSmis(assembler, &fall_through);
-  __ subsw(R0, R1, Operand(R0));  // Subtract.
-  __ b(&fall_through, VS);        // Fall-through on overflow.
-  __ sxtw(R0, R0);                // Sign extend - flags not affected.
+  __ subs(R0, R1, Operand(R0));  // Subtract.
+  __ b(&fall_through, VS);       // Fall-through on overflow.
   __ ret();
   __ Bind(&fall_through);
 }
@@ -302,9 +299,9 @@
   TestBothArgumentsSmis(assembler, &fall_through);  // checks two smis
   __ SmiUntag(R0);  // Untags R6. We only want result shifted by one.
 
-  __ smull(TMP, R0, R1);
-  __ AsrImmediate(TMP2, TMP, 31);
-  // TMP: result bits 31..63.
+  __ mul(TMP, R0, R1);
+  __ smulh(TMP2, R0, R1);
+  // TMP: result bits 64..127.
   __ cmp(TMP2, Operand(TMP, ASR, 63));
   __ b(&fall_through, NE);
   __ mov(R0, TMP);
@@ -420,7 +417,7 @@
 
   // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we
   // cannot tag the result.
-  __ CompareImmediate(R0, 0x40000000);
+  __ CompareImmediate(R0, 0x4000000000000000);
   __ b(&fall_through, EQ);
   __ SmiTag(R0);  // Not equal. Okay to tag and return.
   __ ret();       // Return.
@@ -431,9 +428,8 @@
   Label fall_through;
   __ ldr(R0, Address(SP, +0 * kWordSize));  // Grab first argument.
   __ BranchIfNotSmi(R0, &fall_through);
-  __ negsw(R0, R0);
+  __ negs(R0, R0);
   __ b(&fall_through, VS);
-  __ sxtw(R0, R0);  // Sign extend - flags not affected.
   __ ret();
   __ Bind(&fall_through);
 }
@@ -492,9 +488,9 @@
   // Check if count too large for handling it inlined.
   __ SmiUntag(TMP, right);  // SmiUntag right into TMP.
   // Overflow test (preserve left, right, and TMP);
-  __ lslvw(temp, left, TMP);
-  __ asrvw(TMP2, temp, TMP);
-  __ cmpw(left, Operand(TMP2));
+  __ lslv(temp, left, TMP);
+  __ asrv(TMP2, temp, TMP);
+  __ CompareRegisters(left, TMP2);
   __ b(&fall_through, NE);  // Overflow.
   // Shift for result now we know there is no overflow.
   __ lslv(result, left, TMP);
@@ -567,7 +563,6 @@
 
   __ CompareClassId(R0, kDoubleCid);
   __ b(&fall_through, EQ);
-  __ AssertSmiInRange(R1);
   __ LoadObject(R0, Bool::False());  // Smi == Mint -> false.
   __ ret();
 
@@ -578,7 +573,6 @@
   __ b(&fall_through, NE);
   // Receiver is Mint, return false if right is Smi.
   __ BranchIfNotSmi(R0, &fall_through);
-  __ AssertSmiInRange(R0);
   __ LoadObject(R0, Bool::False());
   __ ret();
   // TODO(srdjan): Implement Mint == Mint comparison.
@@ -1501,12 +1495,11 @@
   __ fcmpd(V0, V0);
   __ b(&fall_through, VS);
 
-  __ fcvtzdsx(R0, V0);
+  __ fcvtzds(R0, V0);
   // Overflow is signaled with minint.
   // Check for overflow and that it fits into Smi.
-  __ AsrImmediate(TMP, R0, 30);
-  __ cmp(TMP, Operand(R0, ASR, 63));
-  __ b(&fall_through, NE);
+  __ CompareImmediate(R0, 0xC000000000000000);
+  __ b(&fall_through, MI);
   __ SmiTag(R0);
   __ ret();
   __ Bind(&fall_through);
@@ -1523,10 +1516,10 @@
   __ fcmpd(V0, V0);
   __ b(&double_hash, VS);
 
-  // Convert double value to signed 32-bit int in R0 and back to a
+  // Convert double value to signed 64-bit int in R0 and back to a
   // double value in V1.
-  __ fcvtzdsw(R0, V0);
-  __ scvtfdw(V1, R0);
+  __ fcvtzds(R0, V0);
+  __ scvtfdx(V1, R0);
 
   // Tag the int as a Smi, making sure that it fits; this checks for
   // overflow in the conversion from double to int. Conversion
@@ -1534,9 +1527,8 @@
   // INT64_MAX or INT64_MIN (saturation).
   Label fall_through;
   ASSERT(kSmiTag == 0 && kSmiTagShift == 1);
-  __ addsw(R0, R0, Operand(R0));
+  __ adds(R0, R0, Operand(R0));
   __ b(&fall_through, VS);
-  __ sxtw(R0, R0);  // Sign extend - flags not affected.
 
   // Compare the two double values. If they are equal, we return the
   // Smi tagged result immediately as the hash code.
diff --git a/runtime/vm/compiler/intrinsifier_x64.cc b/runtime/vm/compiler/intrinsifier_x64.cc
index c8ddf76..1e2574c 100644
--- a/runtime/vm/compiler/intrinsifier_x64.cc
+++ b/runtime/vm/compiler/intrinsifier_x64.cc
@@ -269,10 +269,8 @@
   Label fall_through;
   TestBothArgumentsSmis(assembler, &fall_through);
   // RAX contains right argument.
-  __ AssertSmiInRange(RAX);
-  __ addl(RAX, Address(RSP, +2 * kWordSize));
+  __ addq(RAX, Address(RSP, +2 * kWordSize));
   __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
-  __ movsxd(RAX, RAX);
   // Result is in RAX.
   __ ret();
   __ Bind(&fall_through);
@@ -286,10 +284,8 @@
   Label fall_through;
   TestBothArgumentsSmis(assembler, &fall_through);
   // RAX contains right argument, which is the actual minuend of subtraction.
-  __ AssertSmiInRange(RAX);
-  __ subl(RAX, Address(RSP, +2 * kWordSize));
+  __ subq(RAX, Address(RSP, +2 * kWordSize));
   __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
-  __ movsxd(RAX, RAX);
   // Result is in RAX.
   __ ret();
   __ Bind(&fall_through);
@@ -299,13 +295,10 @@
   Label fall_through;
   TestBothArgumentsSmis(assembler, &fall_through);
   // RAX contains right argument, which is the actual subtrahend of subtraction.
-  __ AssertSmiInRange(RAX);
   __ movq(RCX, RAX);
   __ movq(RAX, Address(RSP, +2 * kWordSize));
-  __ AssertSmiInRange(RAX);
-  __ subl(RAX, RCX);
+  __ subq(RAX, RCX);
   __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
-  __ movsxd(RAX, RAX);
   // Result is in RAX.
   __ ret();
   __ Bind(&fall_through);
@@ -315,12 +308,10 @@
   Label fall_through;
   TestBothArgumentsSmis(assembler, &fall_through);
   // RAX is the right argument.
-  __ AssertSmiInRange(RAX);
   ASSERT(kSmiTag == 0);  // Adjust code below if not the case.
   __ SmiUntag(RAX);
-  __ imull(RAX, Address(RSP, +2 * kWordSize));
+  __ imulq(RAX, Address(RSP, +2 * kWordSize));
   __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
-  __ movsxd(RAX, RAX);
   // Result is in RAX.
   __ ret();
   __ Bind(&fall_through);
@@ -342,9 +333,7 @@
 //   RAX: Untagged fallthrough result (remainder to be adjusted), or
 //   RAX: Tagged return result (remainder).
 static void EmitRemainderOperation(Assembler* assembler) {
-  Label return_zero, try_modulo, not_32bit;
-  __ AssertSmiInRange(RAX);
-  __ AssertSmiInRange(RCX);
+  Label return_zero, try_modulo, not_32bit, done;
   // Check for quick zero results.
   __ cmpq(RAX, Immediate(0));
   __ j(EQUAL, &return_zero, Assembler::kNearJump);
@@ -366,12 +355,33 @@
 
   __ Bind(&try_modulo);
 
+  // Check if both operands fit into 32bits as idiv with 64bit operands
+  // requires twice as many cycles and has much higher latency. We are checking
+  // this before untagging them to avoid corner case dividing INT_MAX by -1 that
+  // raises exception because quotient is too large for 32bit register.
+  __ movsxd(RBX, RAX);
+  __ cmpq(RBX, RAX);
+  __ j(NOT_EQUAL, &not_32bit, Assembler::kNearJump);
+  __ movsxd(RBX, RCX);
+  __ cmpq(RBX, RCX);
+  __ j(NOT_EQUAL, &not_32bit, Assembler::kNearJump);
+
   // Both operands are 31bit smis. Divide using 32bit idiv.
   __ SmiUntag(RAX);
   __ SmiUntag(RCX);
   __ cdq();
   __ idivl(RCX);
   __ movsxd(RAX, RDX);
+  __ jmp(&done, Assembler::kNearJump);
+
+  // Divide using 64bit idiv.
+  __ Bind(&not_32bit);
+  __ SmiUntag(RAX);
+  __ SmiUntag(RCX);
+  __ cqo();
+  __ idivq(RCX);
+  __ movq(RAX, RDX);
+  __ Bind(&done);
 }
 
 // Implementation:
@@ -386,9 +396,7 @@
 void Intrinsifier::Integer_moduloFromInteger(Assembler* assembler) {
   Label fall_through, negative_result;
   TestBothArgumentsSmis(assembler, &fall_through);
-  __ AssertSmiInRange(RAX);
   __ movq(RCX, Address(RSP, +2 * kWordSize));
-  __ AssertSmiInRange(RCX);
   // RAX: Tagged left (dividend).
   // RCX: Tagged right (divisor).
   __ cmpq(RCX, Immediate(0));
@@ -422,17 +430,21 @@
   Label fall_through, not_32bit;
   TestBothArgumentsSmis(assembler, &fall_through);
   // RAX: right argument (divisor)
-  __ AssertSmiInRange(RAX);
   __ cmpq(RAX, Immediate(0));
   __ j(EQUAL, &fall_through, Assembler::kNearJump);
   __ movq(RCX, RAX);
   __ movq(RAX, Address(RSP, +2 * kWordSize));  // Left argument (dividend).
-  __ AssertSmiInRange(RAX);
 
-  // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we
-  // cannot tag the result.
-  __ cmpq(RAX, Immediate(-0x80000000ll));
-  __ j(EQUAL, &fall_through);
+  // Check if both operands fit into 32bits as idiv with 64bit operands
+  // requires twice as many cycles and has much higher latency. We are checking
+  // this before untagging them to avoid corner case dividing INT_MAX by -1 that
+  // raises exception because quotient is too large for 32bit register.
+  __ movsxd(RBX, RAX);
+  __ cmpq(RBX, RAX);
+  __ j(NOT_EQUAL, &not_32bit);
+  __ movsxd(RBX, RCX);
+  __ cmpq(RBX, RCX);
+  __ j(NOT_EQUAL, &not_32bit);
 
   // Both operands are 31bit smis. Divide using 32bit idiv.
   __ SmiUntag(RAX);
@@ -442,6 +454,21 @@
   __ movsxd(RAX, RAX);
   __ SmiTag(RAX);  // Result is guaranteed to fit into a smi.
   __ ret();
+
+  // Divide using 64bit idiv.
+  __ Bind(&not_32bit);
+  __ SmiUntag(RAX);
+  __ SmiUntag(RCX);
+  __ pushq(RDX);  // Preserve RDX in case of 'fall_through'.
+  __ cqo();
+  __ idivq(RCX);
+  __ popq(RDX);
+  // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we
+  // cannot tag the result.
+  __ cmpq(RAX, Immediate(0x4000000000000000));
+  __ j(EQUAL, &fall_through);
+  __ SmiTag(RAX);
+  __ ret();
   __ Bind(&fall_through);
 }
 
@@ -450,10 +477,8 @@
   __ movq(RAX, Address(RSP, +1 * kWordSize));
   __ testq(RAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);  // Non-smi value.
-  __ AssertSmiInRange(RAX);
-  __ cmpq(RAX, Immediate(-0x80000000ll));
-  __ j(EQUAL, &fall_through, Assembler::kNearJump);
   __ negq(RAX);
+  __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
   // Result is in RAX.
   __ ret();
   __ Bind(&fall_through);
@@ -462,7 +487,6 @@
 void Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) {
   Label fall_through;
   TestBothArgumentsSmis(assembler, &fall_through);
-  __ AssertSmiInRange(RAX);
   // RAX is the right argument.
   __ andq(RAX, Address(RSP, +2 * kWordSize));
   // Result is in RAX.
@@ -478,7 +502,6 @@
   Label fall_through;
   TestBothArgumentsSmis(assembler, &fall_through);
   // RAX is the right argument.
-  __ AssertSmiInRange(RAX);
   __ orq(RAX, Address(RSP, +2 * kWordSize));
   // Result is in RAX.
   __ ret();
@@ -494,7 +517,6 @@
   TestBothArgumentsSmis(assembler, &fall_through);
   // RAX is the right argument.
   __ xorq(RAX, Address(RSP, +2 * kWordSize));
-  __ AssertSmiInRange(RAX);
   // Result is in RAX.
   __ ret();
   __ Bind(&fall_through);
@@ -510,32 +532,28 @@
   Label fall_through, overflow;
   TestBothArgumentsSmis(assembler, &fall_through);
   // Shift value is in RAX. Compare with tagged Smi.
-  __ AssertSmiInRange(RAX);
   __ cmpq(RAX, Immediate(Smi::RawValue(Smi::kBits)));
   __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump);
 
   __ SmiUntag(RAX);
   __ movq(RCX, RAX);                           // Shift amount must be in RCX.
   __ movq(RAX, Address(RSP, +2 * kWordSize));  // Value.
-  __ AssertSmiInRange(RAX);
 
   // Overflow test - all the shifted-out bits must be same as the sign bit.
   __ movq(RDI, RAX);
-  __ shll(RAX, RCX);
-  __ sarl(RAX, RCX);
-  __ movsxd(RAX, RAX);
+  __ shlq(RAX, RCX);
+  __ sarq(RAX, RCX);
   __ cmpq(RAX, RDI);
   __ j(NOT_EQUAL, &overflow, Assembler::kNearJump);
 
-  __ shlq(RDI, RCX);  // Shift for result now we know there is no overflow.
-  __ movq(RAX, RDI);
+  __ shlq(RAX, RCX);  // Shift for result now we know there is no overflow.
 
   // RAX is a correctly tagged Smi.
   __ ret();
 
   __ Bind(&overflow);
-  // Mint is used on x64 for integers requiring 64 bit instead of 31 bits as
-  // represented by Smi.
+  // Mint is rarely used on x64 (only for integers requiring 64 bit instead of
+  // 63 bits as represented by Smi).
   __ Bind(&fall_through);
 }
 
@@ -543,7 +561,6 @@
   Label fall_through, true_label;
   TestBothArgumentsSmis(assembler, &fall_through);
   // RAX contains the right argument.
-  __ AssertSmiInRange(RAX);
   __ cmpq(Address(RSP, +2 * kWordSize), RAX);
   __ j(true_condition, &true_label, Assembler::kNearJump);
   __ LoadObject(RAX, Bool::False());
@@ -589,9 +606,6 @@
   __ orq(RAX, RCX);
   __ testq(RAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, &check_for_mint, Assembler::kNearJump);
-  // Or-ing them together should still leave them both as compressible smis.
-  __ AssertSmiInRange(RAX);
-  __ AssertSmiInRange(RCX);
   // Both arguments are smi, '===' is good enough.
   __ LoadObject(RAX, Bool::False());
   __ ret();
@@ -609,21 +623,9 @@
   // Left (receiver) is Smi, return false if right is not Double.
   // Note that an instance of Mint or Bigint never contains a value that can be
   // represented by Smi.
-  __ AssertSmiInRange(RAX);
   __ movq(RAX, Address(RSP, +kArgumentOffset * kWordSize));
   __ CompareClassId(RAX, kDoubleCid);
   __ j(EQUAL, &fall_through);
-#if defined(DEBUG)
-  Label ok;
-  __ CompareClassId(RAX, kMintCid);
-  __ j(NOT_EQUAL, &ok);
-  __ movq(RAX, FieldAddress(RAX, Mint::value_offset()));
-  __ sarq(RCX, Immediate(1));
-  __ cmpq(RAX, RCX);
-  __ j(NOT_EQUAL, &ok);
-  __ Stop("Smi wrapped in a Mint");
-  __ Bind(&ok);
-#endif
   __ LoadObject(RAX, Bool::False());
   __ ret();
 
@@ -635,7 +637,6 @@
   __ movq(RAX, Address(RSP, +kArgumentOffset * kWordSize));
   __ testq(RAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, &fall_through);
-  __ AssertSmiInRange(RAX);
   // Smi == Mint -> false.
   __ LoadObject(RAX, Bool::False());
   __ ret();
@@ -665,7 +666,6 @@
   __ Bind(&shift_count_ok);
   __ movq(RCX, RAX);                           // Shift amount must be in RCX.
   __ movq(RAX, Address(RSP, +2 * kWordSize));  // Value.
-  __ AssertSmiInRange(RAX);
   __ SmiUntag(RAX);                            // Value.
   __ sarq(RAX, RCX);
   __ SmiTag(RAX);
@@ -676,7 +676,6 @@
 // Argument is Smi (receiver).
 void Intrinsifier::Smi_bitNegate(Assembler* assembler) {
   __ movq(RAX, Address(RSP, +1 * kWordSize));  // Index.
-  __ AssertSmiInRange(RAX);
   __ notq(RAX);
   __ andq(RAX, Immediate(~kSmiTagMask));  // Remove inverted smi-tag.
   __ ret();
@@ -685,7 +684,6 @@
 void Intrinsifier::Smi_bitLength(Assembler* assembler) {
   ASSERT(kSmiTagShift == 1);
   __ movq(RAX, Address(RSP, +1 * kWordSize));  // Index.
-  __ AssertSmiInRange(RAX);
   // XOR with sign bit to complement bits if value is negative.
   __ movq(RCX, RAX);
   __ sarq(RCX, Immediate(63));  // All 0 or all 1.
@@ -711,7 +709,6 @@
   __ subq(R8, Immediate(2));  // x_used > 0, Smi. R8 = x_used - 1, round up.
   __ sarq(R8, Immediate(2));  // R8 + 1 = number of digit pairs to read.
   __ movq(RCX, Address(RSP, 2 * kWordSize));  // n is Smi
-  __ AssertSmiInRange(RCX);
   __ SmiUntag(RCX);
   __ movq(RBX, Address(RSP, 1 * kWordSize));  // r_digits
   __ movq(RSI, RCX);
@@ -747,7 +744,6 @@
 
   __ movq(RDI, Address(RSP, 4 * kWordSize));  // x_digits
   __ movq(RCX, Address(RSP, 2 * kWordSize));  // n is Smi
-  __ AssertSmiInRange(RCX);
   __ SmiUntag(RCX);
   __ movq(RBX, Address(RSP, 1 * kWordSize));  // r_digits
   __ movq(RDX, RCX);
@@ -1235,7 +1231,6 @@
   __ LoadObject(RAX, Bool::True());
   __ ret();
   __ Bind(&is_smi);
-  __ AssertSmiInRange(RAX);
   __ SmiUntag(RAX);
   __ cvtsi2sdq(XMM1, RAX);
   __ jmp(&double_op);
@@ -1296,7 +1291,6 @@
   __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
   __ ret();
   __ Bind(&is_smi);
-  __ AssertSmiInRange(RAX);
   __ SmiUntag(RAX);
   __ cvtsi2sdq(XMM1, RAX);
   __ jmp(&double_op);
@@ -1326,7 +1320,6 @@
   __ testq(RAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, &fall_through);
   // Is Smi.
-  __ AssertSmiInRange(RAX);
   __ SmiUntag(RAX);
   __ cvtsi2sdq(XMM1, RAX);
   __ movq(RAX, Address(RSP, +2 * kWordSize));
@@ -1349,7 +1342,6 @@
   __ testq(RAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, &fall_through);
   // Is Smi.
-  __ AssertSmiInRange(RAX);
   __ SmiUntag(RAX);
   __ cvtsi2sdq(XMM0, RAX);
   const Class& double_class =
@@ -1420,15 +1412,14 @@
 void Intrinsifier::DoubleToInteger(Assembler* assembler) {
   __ movq(RAX, Address(RSP, +1 * kWordSize));
   __ movsd(XMM0, FieldAddress(RAX, Double::value_offset()));
-  __ cvttsd2sil(RAX, XMM0);
+  __ cvttsd2siq(RAX, XMM0);
   // Overflow is signalled with minint.
   Label fall_through;
   // Check for overflow and that it fits into Smi.
   __ movq(RCX, RAX);
-  __ shll(RCX, Immediate(1));
+  __ shlq(RCX, Immediate(1));
   __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
-  ASSERT(kSmiTagShift == 1 && kSmiTag == 0);
-  __ movsxd(RAX, RCX);
+  __ SmiTag(RAX);
   __ ret();
   __ Bind(&fall_through);
 }
@@ -1440,17 +1431,16 @@
   // back to a double in XMM1.
   __ movq(RCX, Address(RSP, +1 * kWordSize));
   __ movsd(XMM0, FieldAddress(RCX, Double::value_offset()));
-  __ cvttsd2sil(RAX, XMM0);
-  __ cvtsi2sdl(XMM1, RAX);
+  __ cvttsd2siq(RAX, XMM0);
+  __ cvtsi2sdq(XMM1, RAX);
 
   // Tag the int as a Smi, making sure that it fits; this checks for
   // overflow and NaN in the conversion from double to int. Conversion
-  // overflow from cvttsd2sil is signalled with an INT32_MIN value.
+  // overflow from cvttsd2si is signalled with an INT64_MIN value.
   Label fall_through;
   ASSERT(kSmiTag == 0 && kSmiTagShift == 1);
-  __ addl(RAX, RAX);
+  __ addq(RAX, RAX);
   __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
-  __ movsxd(RAX, RAX);
 
   // Compare the two double values. If they are equal, we return the
   // Smi tagged result immediately as the hash code.
@@ -1488,7 +1478,6 @@
   __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
   __ ret();
   __ Bind(&is_smi);
-  __ AssertSmiInRange(RAX);
   __ SmiUntag(RAX);
   __ cvtsi2sdq(XMM1, RAX);
   __ jmp(&double_op);
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index cbf0db4..95b3f87 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -708,14 +708,14 @@
 
 enum Extend {
   kNoExtend = -1,
-  UXTB = 0,  // Zero extend byte.
-  UXTH = 1,  // Zero extend halfword (16 bits).
-  UXTW = 2,  // Zero extend word (32 bits).
-  UXTX = 3,  // Zero extend doubleword (64 bits).
-  SXTB = 4,  // Sign extend byte.
-  SXTH = 5,  // Sign extend halfword (16 bits).
-  SXTW = 6,  // Sign extend word (32 bits).
-  SXTX = 7,  // Sign extend doubleword (64 bits).
+  UXTB = 0,
+  UXTH = 1,
+  UXTW = 2,
+  UXTX = 3,
+  SXTB = 4,
+  SXTH = 5,
+  SXTW = 6,
+  SXTX = 7,
   kMaxExtend = 8,
 };
 
diff --git a/runtime/vm/globals.h b/runtime/vm/globals.h
index c15516d..4fa43f2 100644
--- a/runtime/vm/globals.h
+++ b/runtime/vm/globals.h
@@ -21,8 +21,9 @@
 #undef OVERFLOW  // From math.h conflicts in constants_ia32.h
 
 namespace dart {
-// Smi value range is from -(2^N) to (2^N)-1.  N=30
-const intptr_t kSmiBits = 30;
+// Smi value range is from -(2^N) to (2^N)-1.
+// N=30 (32-bit build) or N=62 (64-bit build).
+const intptr_t kSmiBits = kBitsPerWord - 2;
 const intptr_t kSmiMax = (static_cast<intptr_t>(1) << kSmiBits) - 1;
 const intptr_t kSmiMin = -(static_cast<intptr_t>(1) << kSmiBits);
 
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 622665c..6a99622 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -7873,16 +7873,7 @@
   virtual uword ComputeCanonicalTableHash() const;
 
   static const intptr_t kBytesPerElement = kWordSize;
-  // The length field is a Smi so that sets one limit on the max Array length.
-  // But we also need to be able to represent the length in bytes in an
-  // intptr_t, which is a different limit.  Either may be smaller.  We can't
-  // use Utils::Minimum here because it is not a const expression.
-  static const intptr_t kElementLimitDueToIntptrMax = static_cast<intptr_t>(
-      (kIntptrMax - sizeof(RawArray) - kObjectAlignment + kBytesPerElement) /
-      kBytesPerElement);
-  static const intptr_t kMaxElements = kSmiMax < kElementLimitDueToIntptrMax
-                                           ? kSmiMax
-                                           : kElementLimitDueToIntptrMax;
+  static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
   static const intptr_t kMaxNewSpaceElements =
       (Heap::kNewAllocatableSize - sizeof(RawArray)) / kBytesPerElement;
 
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 31437e4..4890d04 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -308,10 +308,16 @@
   EXPECT(Smi::IsValid(-15));
   EXPECT(Smi::IsValid(0xFFu));
 // Upper two bits must be either 00 or 11.
+#if defined(ARCH_IS_64_BIT)
+  EXPECT(!Smi::IsValid(kMaxInt64));
+  EXPECT(Smi::IsValid(0x3FFFFFFFFFFFFFFF));
+  EXPECT(Smi::IsValid(-1));
+#else
   EXPECT(!Smi::IsValid(kMaxInt32));
   EXPECT(Smi::IsValid(0x3FFFFFFF));
   EXPECT(Smi::IsValid(-1));
   EXPECT(!Smi::IsValid(0xFFFFFFFFu));
+#endif
 
   EXPECT_EQ(5, smi.AsInt64Value());
   EXPECT_EQ(5.0, smi.AsDoubleValue());
@@ -439,6 +445,9 @@
 }
 
 ISOLATE_UNIT_TEST_CASE(Mint) {
+// On 64-bit architectures a Smi is stored in a 64 bit word. A Midint cannot
+// be allocated if it does fit into a Smi.
+#if !defined(ARCH_IS_64_BIT)
   {
     Mint& med = Mint::Handle();
     EXPECT(med.IsNull());
@@ -508,6 +517,7 @@
   EXPECT_EQ(mint1.value(), mint_value);
   EXPECT_EQ(mint2.value(), mint_value);
   EXPECT_EQ(mint1.raw(), mint2.raw());
+#endif
 }
 
 ISOLATE_UNIT_TEST_CASE(Double) {
@@ -2737,6 +2747,22 @@
   EXPECT(Smi::Cast(result).Value() == kSmiTestValue);
 }
 
+#if defined(ARCH_IS_64_BIT)
+// Test for Embedded Smi object in the instructions.
+ISOLATE_UNIT_TEST_CASE(EmbedSmiIn64BitCode) {
+  extern void GenerateEmbedSmiInCode(Assembler * assembler, intptr_t value);
+  const intptr_t kSmiTestValue = DART_INT64_C(5) << 32;
+  Assembler _assembler_;
+  GenerateEmbedSmiInCode(&_assembler_, kSmiTestValue);
+  const Function& function =
+      Function::Handle(CreateFunction("Test_EmbedSmiIn64BitCode"));
+  const Code& code = Code::Handle(Code::FinalizeCode(function, &_assembler_));
+  function.AttachCode(code);
+  const Object& result =
+      Object::Handle(DartEntry::InvokeFunction(function, Array::empty_array()));
+  EXPECT(Smi::Cast(result).Value() == kSmiTestValue);
+}
+#endif  // ARCH_IS_64_BIT
 
 ISOLATE_UNIT_TEST_CASE(ExceptionHandlers) {
   const int kNumEntries = 4;
diff --git a/runtime/vm/regexp.cc b/runtime/vm/regexp.cc
index 3d23411..4d99e0f 100644
--- a/runtime/vm/regexp.cc
+++ b/runtime/vm/regexp.cc
@@ -3023,19 +3023,10 @@
                               Trace* current_trace,
                               PreloadState* state) {
   if (state->eats_at_least_ == PreloadState::kEatsAtLeastNotYetInitialized) {
-    // On ARM64, only read 16 bits ahead for now.  This ensures that boxing is
-    // trivial even with the new smaller Smis.  See
-    // https://github.com/dart-lang/sdk/issues/29951 and
-    // LoadCodeUnitsInstr::EmitNativeCode.
-#if defined(TARGET_ARCH_ARM64)
-    const int kMaxBytesLoaded = 2;
-#else
-    const int kMaxBytesLoaded = 4;
-#endif
-    const int kMaxTwoByteCharactersLoaded = kMaxBytesLoaded / 2;
-    state->eats_at_least_ = EatsAtLeast(
-        compiler->one_byte() ? kMaxBytesLoaded : kMaxTwoByteCharactersLoaded,
-        kRecursionBudget, current_trace->at_start() == Trace::FALSE_VALUE);
+    // Save some time by looking at most one machine word ahead.
+    state->eats_at_least_ =
+        EatsAtLeast(compiler->one_byte() ? 4 : 2, kRecursionBudget,
+                    current_trace->at_start() == Trace::FALSE_VALUE);
   }
   state->preload_characters_ =
       CalculatePreloadCharacters(compiler, state->eats_at_least_);
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index 926b75e..3db2d65 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -3199,21 +3199,13 @@
       set_vregisterd(vd, 1, 0);
     } else if (instr->Bits(16, 5) == 24) {
       // Format(instr, "fcvtzds'sf 'rd, 'vn");
-      const intptr_t max = instr->Bit(31) == 1 ? INT64_MAX : INT32_MAX;
-      const intptr_t min = instr->Bit(31) == 1 ? INT64_MIN : INT32_MIN;
       const double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn, 0));
-      int64_t result;
-      if (vn_val >= static_cast<double>(max)) {
-        result = max;
-      } else if (vn_val <= static_cast<double>(min)) {
-        result = min;
+      if (vn_val >= static_cast<double>(INT64_MAX)) {
+        set_register(instr, rd, INT64_MAX, instr->RdMode());
+      } else if (vn_val <= static_cast<double>(INT64_MIN)) {
+        set_register(instr, rd, INT64_MIN, instr->RdMode());
       } else {
-        result = static_cast<int64_t>(vn_val);
-      }
-      if (instr->Bit(31) == 1) {
-        set_register(instr, rd, result, instr->RdMode());
-      } else {
-        set_register(instr, rd, result & 0xffffffffll, instr->RdMode());
+        set_register(instr, rd, static_cast<int64_t>(vn_val), instr->RdMode());
       }
     } else {
       UnimplementedInstruction(instr);
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index c9906c3..487143f 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -636,11 +636,11 @@
 // __builtin_s{add,sub,mul}_overflow() intrinsics here and below.
 // Note that they may clobber the output location even when there is overflow:
 // https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html
-DART_FORCE_INLINE static bool SignedAddWithOverflow(int32_t lhs,
-                                                    int32_t rhs,
+DART_FORCE_INLINE static bool SignedAddWithOverflow(intptr_t lhs,
+                                                    intptr_t rhs,
                                                     intptr_t* out) {
   intptr_t res = 1;
-#if defined(HOST_ARCH_IA32)
+#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64)
   asm volatile(
       "add %2, %1\n"
       "jo 1f;\n"
@@ -650,19 +650,7 @@
       : "+r"(res), "+r"(lhs)
       : "r"(rhs), "r"(out)
       : "cc");
-#elif defined(HOST_ARCH_X64)
-  int64_t tmp;
-  asm volatile(
-      "addl %[rhs], %[lhs]\n"
-      "jo 1f;\n"
-      "xor %[res], %[res]\n"
-      "movslq %[lhs], %[tmp]\n"
-      "mov %[tmp], 0(%[out])\n"
-      "1: "
-      : [res] "+r"(res), [lhs] "+r"(lhs), [tmp] "=&r"(tmp)
-      : [rhs] "r"(rhs), [out] "r"(out)
-      : "cc");
-#elif defined(HOST_ARCH_ARM)
+#elif defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64)
   asm volatile(
       "adds %1, %1, %2;\n"
       "bvs 1f;\n"
@@ -672,28 +660,17 @@
       : "+r"(res), "+r"(lhs)
       : "r"(rhs), "r"(out)
       : "cc");
-#elif defined(HOST_ARCH_ARM64)
-  asm volatile(
-      "adds %w1, %w1, %w2;\n"
-      "bvs 1f;\n"
-      "sxtw %x1, %w1;\n"
-      "mov %0, #0;\n"
-      "str %x1, [%3, #0]\n"
-      "1:"
-      : "+r"(res), "+r"(lhs)
-      : "r"(rhs), "r"(out)
-      : "cc");
 #else
 #error "Unsupported platform"
 #endif
   return (res != 0);
 }
 
-DART_FORCE_INLINE static bool SignedSubWithOverflow(int32_t lhs,
-                                                    int32_t rhs,
+DART_FORCE_INLINE static bool SignedSubWithOverflow(intptr_t lhs,
+                                                    intptr_t rhs,
                                                     intptr_t* out) {
   intptr_t res = 1;
-#if defined(HOST_ARCH_IA32)
+#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64)
   asm volatile(
       "sub %2, %1\n"
       "jo 1f;\n"
@@ -703,19 +680,7 @@
       : "+r"(res), "+r"(lhs)
       : "r"(rhs), "r"(out)
       : "cc");
-#elif defined(HOST_ARCH_X64)
-  int64_t tmp;
-  asm volatile(
-      "subl %[rhs], %[lhs]\n"
-      "jo 1f;\n"
-      "xor %[res], %[res]\n"
-      "movslq %[lhs], %[tmp]\n"
-      "mov %[tmp], 0(%[out])\n"
-      "1: "
-      : [res] "+r"(res), [lhs] "+r"(lhs), [tmp] "=&r"(tmp)
-      : [rhs] "r"(rhs), [out] "r"(out)
-      : "cc");
-#elif defined(HOST_ARCH_ARM)
+#elif defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64)
   asm volatile(
       "subs %1, %1, %2;\n"
       "bvs 1f;\n"
@@ -725,28 +690,17 @@
       : "+r"(res), "+r"(lhs)
       : "r"(rhs), "r"(out)
       : "cc");
-#elif defined(HOST_ARCH_ARM64)
-  asm volatile(
-      "subs %w1, %w1, %w2;\n"
-      "bvs 1f;\n"
-      "sxtw %x1, %w1;\n"
-      "mov %0, #0;\n"
-      "str %x1, [%3, #0]\n"
-      "1:"
-      : "+r"(res), "+r"(lhs)
-      : "r"(rhs), "r"(out)
-      : "cc");
 #else
 #error "Unsupported platform"
 #endif
   return (res != 0);
 }
 
-DART_FORCE_INLINE static bool SignedMulWithOverflow(int32_t lhs,
-                                                    int32_t rhs,
+DART_FORCE_INLINE static bool SignedMulWithOverflow(intptr_t lhs,
+                                                    intptr_t rhs,
                                                     intptr_t* out) {
   intptr_t res = 1;
-#if defined(HOST_ARCH_IA32)
+#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64)
   asm volatile(
       "imul %2, %1\n"
       "jo 1f;\n"
@@ -756,18 +710,6 @@
       : "+r"(res), "+r"(lhs)
       : "r"(rhs), "r"(out)
       : "cc");
-#elif defined(HOST_ARCH_X64)
-  int64_t tmp;
-  asm volatile(
-      "imull %[rhs], %[lhs]\n"
-      "jo 1f;\n"
-      "xor %[res], %[res]\n"
-      "movslq %[lhs], %[tmp]\n"
-      "mov %[tmp], 0(%[out])\n"
-      "1: "
-      : [res] "+r"(res), [lhs] "+r"(lhs), [tmp] "=&r"(tmp)
-      : [rhs] "r"(rhs), [out] "r"(out)
-      : "cc");
 #elif defined(HOST_ARCH_ARM)
   asm volatile(
       "smull %1, ip, %1, %2;\n"
@@ -782,12 +724,12 @@
 #elif defined(HOST_ARCH_ARM64)
   int64_t prod_lo = 0;
   asm volatile(
-      "smull %x1, %w2, %w3\n"
-      "asr %x2, %x1, #63\n"
-      "cmp %x2, %x1, ASR #31;\n"
+      "mul %1, %2, %3\n"
+      "smulh %2, %2, %3\n"
+      "cmp %2, %1, ASR #63;\n"
       "bne 1f;\n"
       "mov %0, #0;\n"
-      "str %x1, [%4, #0]\n"
+      "str %1, [%4, #0]\n"
       "1:"
       : "=r"(res), "+r"(prod_lo), "+r"(lhs)
       : "r"(rhs), "r"(out)
@@ -2029,7 +1971,11 @@
     if (rhs != 0) {
       const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
       const intptr_t res = (lhs >> kSmiTagSize) / (rhs >> kSmiTagSize);
+#if defined(ARCH_IS_64_BIT)
+      const intptr_t untaggable = 0x4000000000000000LL;
+#else
       const intptr_t untaggable = 0x40000000L;
+#endif  // defined(ARCH_IS_64_BIT)
       if (res != untaggable) {
         *reinterpret_cast<intptr_t*>(&FP[rA]) = res << kSmiTagSize;
         pc++;
@@ -2055,12 +2001,11 @@
   {
     BYTECODE(Shl, A_B_C);
     const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]) >> kSmiTagSize;
-    const int kBitsPerInt32 = 32;
-    if (static_cast<uintptr_t>(rhs) < kBitsPerInt32) {
-      const int32_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
-      const int32_t res = lhs << rhs;
+    if (static_cast<uintptr_t>(rhs) < kBitsPerWord) {
+      const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
+      const intptr_t res = lhs << rhs;
       if (lhs == (res >> rhs)) {
-        *reinterpret_cast<intptr_t*>(&FP[rA]) = static_cast<intptr_t>(res);
+        *reinterpret_cast<intptr_t*>(&FP[rA]) = res;
         pc++;
       }
     }
@@ -2071,7 +2016,8 @@
     BYTECODE(Shr, A_B_C);
     const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]) >> kSmiTagSize;
     if (rhs >= 0) {
-      const intptr_t shift_amount = (rhs >= 32) ? (32 - 1) : rhs;
+      const intptr_t shift_amount =
+          (rhs >= kBitsPerWord) ? (kBitsPerWord - 1) : rhs;
       const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]) >> kSmiTagSize;
       *reinterpret_cast<intptr_t*>(&FP[rA]) = (lhs >> shift_amount)
                                               << kSmiTagSize;
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index 22067a5..dc70397 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -253,6 +253,10 @@
 // here covers most of the 64-bit range. On 32-bit platforms the smi
 // range covers most of the 32-bit range and values outside that
 // range are also represented as mints.
+#if defined(ARCH_IS_64_BIT)
+  EXPECT_EQ(Dart_CObject_kInt64, mint_cobject->type);
+  EXPECT_EQ(value, mint_cobject->value.as_int64);
+#else
   if (kMinInt32 < value && value < kMaxInt32) {
     EXPECT_EQ(Dart_CObject_kInt32, mint_cobject->type);
     EXPECT_EQ(value, mint_cobject->value.as_int32);
@@ -260,6 +264,7 @@
     EXPECT_EQ(Dart_CObject_kInt64, mint_cobject->type);
     EXPECT_EQ(value, mint_cobject->value.as_int64);
   }
+#endif
 }
 
 TEST_CASE(SerializeMints) {
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index 401a611..f0354a8 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -1334,18 +1334,14 @@
   __ ldr(R1, Address(SP, +1 * kWordSize));  // Left.
   __ orr(TMP, R0, Operand(R1));
   __ BranchIfNotSmi(TMP, not_smi_or_overflow);
-  __ AssertSmiInRange(R0);
-  __ AssertSmiInRange(R1);
   switch (kind) {
     case Token::kADD: {
-      __ addsw(R0, R1, Operand(R0));  // Adds.
-      __ sxtw(R0, R0);
+      __ adds(R0, R1, Operand(R0));   // Adds.
       __ b(not_smi_or_overflow, VS);  // Branch if overflow.
       break;
     }
     case Token::kSUB: {
-      __ subsw(R0, R1, Operand(R0));  // Subtract.
-      __ sxtw(R0, R0);
+      __ subs(R0, R1, Operand(R0));   // Subtract.
       __ b(not_smi_or_overflow, VS);  // Branch if overflow.
       break;
     }
@@ -1387,8 +1383,6 @@
     __ StoreToOffset(R1, R6, count_offset);
   }
 
-  __ AssertSmiInRange(R0, Assembler::kValueCanBeHeapPointer);
-
   __ ret();
 }
 
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index b21d9db..fc8e781 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -1274,15 +1274,13 @@
   __ j(NOT_ZERO, not_smi_or_overflow);
   switch (kind) {
     case Token::kADD: {
-      __ addl(RAX, RCX);
+      __ addq(RAX, RCX);
       __ j(OVERFLOW, not_smi_or_overflow);
-      __ movsxd(RAX, RAX);
       break;
     }
     case Token::kSUB: {
-      __ subl(RAX, RCX);
+      __ subq(RAX, RCX);
       __ j(OVERFLOW, not_smi_or_overflow);
-      __ movsxd(RAX, RAX);
       break;
     }
     case Token::kEQ: {
diff --git a/runtime/vm/token_position.h b/runtime/vm/token_position.h
index eadb562..c28f9a4 100644
--- a/runtime/vm/token_position.h
+++ b/runtime/vm/token_position.h
@@ -18,7 +18,7 @@
 // ClassifyingTokenPositions N -> -1 - N
 //
 // Synthetically created AstNodes are given real source positions but encoded
-// as negative numbers from [kSmiMin, -1 - N]. For example:
+// as negative numbers from [kSmiMin32, -1 - N]. For example:
 //
 // A source position of 0 in a synthetic AstNode would be encoded as -2 - N.
 // A source position of 1 in a synthetic AstNode would be encoded as -3 - N.
@@ -86,7 +86,7 @@
 #undef DECLARE_VALUES
   static const intptr_t kMinSourcePos = 0;
   static const TokenPosition kMinSource;
-  static const intptr_t kMaxSourcePos = kSmiMax - kMaxSentinelDescriptors - 2;
+  static const intptr_t kMaxSourcePos = kSmiMax32 - kMaxSentinelDescriptors - 2;
   static const TokenPosition kMaxSource;
 
   // Decode from a snapshot.
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 76eadd0..2dd3260 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -188,6 +188,9 @@
 LibTest/collection/ListMixin/ListMixin_class_A01_t02: Skip # co19 issue 673, These tests take too much memory (300 MB) for our 1 GB test machine co19 issue 673. http://code.google.com/p/co19/issues/detail?id=673
 LibTest/core/List/List_class_A01_t02: Skip # co19 issue 673, These tests take too much memory (300 MB) for our 1 GB test machine co19 issue 673. http://code.google.com/p/co19/issues/detail?id=673
 
+[ $arch != arm64 && $arch != simarm64 && $arch != simdbc && $arch != simdbc64 && $arch != x64 && ($runtime == dart_precompiled || $runtime == vm) ]
+LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
+
 [ $arch == ia32 && $mode == release && $runtime == vm && $system == linux ]
 service/dev_fs_spawn_test: Pass, Fail # Issue 28411
 
@@ -379,9 +382,6 @@
 LibTest/typed_data/Uint64List/Uint64List.view_A01_t02: CompileTimeError # Large integer literal
 WebPlatformTest/*: SkipByDesign # dart:html not supported on VM.
 
-[ $runtime == dart_precompiled || $runtime == vm ]
-LibTest/core/int/operator_left_shift_A01_t02: Fail # Can't represent 1 << 2147483647 without running out of memory.
-
 [ $runtime == flutter || $hot_reload || $hot_reload_rollback ]
 Language/Expressions/Assignment/prefix_object_t02: Skip # Requires deferred libraries
 Language/Expressions/Constants/constant_constructor_t03: Skip # Requires deferred libraries
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index aa44463..d6a5423 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -614,4 +614,5 @@
 
 [ $hot_reload || $hot_reload_rollback ]
 bigint_parse_radix_test: Pass, Timeout # Issue 31659
+bigint_test: Pass, Crash # Issue 31660
 integer_parsed_mul_div_vm_test: Pass, Slow # Slow