Use GPRs for mints.

Changes:

* Register allocator now allocates GPRs for kUnboxedMint.
* Register allocator supports for SameAsFirstInput for register pairs.
* Register allocator properly handles register pairs in environment uses and materialization uses.
* BoxInteger updated on IA32/ARM.
* UnboxInteger updated on IA32/ARM.
* BinaryMintOp updated on IA32/ARM.
* ShiftMintOp updated on IA32/ARM.
* UnaryMintOp updated on IA32/ARM.
* RelationalOp updated on IA32/ARM.
* EqualityCompare updated on IA32/ARM.
* LoadIndexed and StoreIndexed updated on IA32/ARM.
* New Deopt instructions added.
* Update live_registers when an instruction has a fixed register input and a call on the slow path.
* Improve printing of register pairs in flow graph.
* Do not assume live registers in slow paths contain tagged values.
* LiveRange pairs for kUnboxedMint definitions marked as kUntagged representation (reduces stack usage).
* Live register spilling on ARM uses same register order as stack map encoding.
* Spill slots containing tagged and untagged are segregated.
* Print stack maps when printing live ranges with safe points.
* Print allocated spill slot when printing live ranges.

Status:

* IA32 completed. All tests are passing.
* ARM completed. All tests passing.

R=fschneider@google.com, srdjan@google.com, zra@google.com

Review URL: https://codereview.chromium.org//252333002

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36468 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index d712f98..a7c442d 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -273,12 +273,24 @@
 }
 
 
+void Assembler::adcs(Register rd, Register rn, ShifterOperand so,
+                    Condition cond) {
+  EmitType01(cond, so.type(), ADC, 1, rn, rd, so);
+}
+
+
 void Assembler::sbc(Register rd, Register rn, ShifterOperand so,
                     Condition cond) {
   EmitType01(cond, so.type(), SBC, 0, rn, rd, so);
 }
 
 
+void Assembler::sbcs(Register rd, Register rn, ShifterOperand so,
+                    Condition cond) {
+  EmitType01(cond, so.type(), SBC, 1, rn, rd, so);
+}
+
+
 void Assembler::rsc(Register rd, Register rn, ShifterOperand so,
                     Condition cond) {
   EmitType01(cond, so.type(), RSC, 0, rn, rd, so);
@@ -2161,6 +2173,11 @@
 }
 
 
+void Assembler::SignFill(Register rd, Register rm) {
+  Asr(rd, rm, 31);
+}
+
+
 void Assembler::Vreciprocalqs(QRegister qd, QRegister qm) {
   ASSERT(qm != QTMP);
   ASSERT(qd != QTMP);
diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h
index 607754b..19033fa 100644
--- a/runtime/vm/assembler_arm.h
+++ b/runtime/vm/assembler_arm.h
@@ -351,8 +351,12 @@
 
   void adc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
 
+  void adcs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
+
   void sbc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
 
+  void sbcs(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
+
   void rsc(Register rd, Register rn, ShifterOperand so, Condition cond = AL);
 
   void tst(Register rn, ShifterOperand so, Condition cond = AL);
@@ -694,6 +698,9 @@
   void Ror(Register rd, Register rm, Register rs, Condition cond = AL);
   void Rrx(Register rd, Register rm, Condition cond = AL);
 
+  // Fill rd with the sign of rm.
+  void SignFill(Register rd, Register rm);
+
   void Vreciprocalqs(QRegister qd, QRegister qm);
   void VreciprocalSqrtqs(QRegister qd, QRegister qm);
   // If qm must be preserved, then provide a (non-QTMP) temporary.
diff --git a/runtime/vm/assembler_arm_test.cc b/runtime/vm/assembler_arm_test.cc
index 6973e27..8029184 100644
--- a/runtime/vm/assembler_arm_test.cc
+++ b/runtime/vm/assembler_arm_test.cc
@@ -683,6 +683,40 @@
 }
 
 
+ASSEMBLER_TEST_GENERATE(AddCarry, assembler) {
+  __ LoadImmediate(R2, 0xFFFFFFFF);
+  __ mov(R1, ShifterOperand(1));
+  __ mov(R0, ShifterOperand(0));
+  __ adds(R2, R2, ShifterOperand(R1));
+  __ adcs(R0, R0, ShifterOperand(R0));
+  __ bx(LR);
+}
+
+
+ASSEMBLER_TEST_RUN(AddCarry, test) {
+  EXPECT(test != NULL);
+  typedef int (*AddCarry)();
+  EXPECT_EQ(1, EXECUTE_TEST_CODE_INT32(AddCarry, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(SubCarry, assembler) {
+  __ LoadImmediate(R2, 0x0);
+  __ mov(R1, ShifterOperand(1));
+  __ mov(R0, ShifterOperand(0));
+  __ subs(R2, R2, ShifterOperand(R1));
+  __ sbcs(R0, R0, ShifterOperand(R0));
+  __ bx(LR);
+}
+
+
+ASSEMBLER_TEST_RUN(SubCarry, test) {
+  EXPECT(test != NULL);
+  typedef int (*SubCarry)();
+  EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT32(SubCarry, test->entry()));
+}
+
+
 ASSEMBLER_TEST_GENERATE(AndOrr, assembler) {
   __ mov(R1, ShifterOperand(40));
   __ mov(R2, ShifterOperand(0));
diff --git a/runtime/vm/bitmap.cc b/runtime/vm/bitmap.cc
index c0f19ab..8a2ebde 100644
--- a/runtime/vm/bitmap.cc
+++ b/runtime/vm/bitmap.cc
@@ -72,6 +72,17 @@
 }
 
 
+void BitmapBuilder::Print() const {
+  for (intptr_t i = 0; i < Length(); i++) {
+    if (Get(i)) {
+      OS::Print("1");
+    } else {
+      OS::Print("0");
+    }
+  }
+}
+
+
 bool BitmapBuilder::GetBit(intptr_t bit_offset) const {
   if (!InRange(bit_offset)) {
     return false;
diff --git a/runtime/vm/bitmap.h b/runtime/vm/bitmap.h
index fc2c685..6d3376a3 100644
--- a/runtime/vm/bitmap.h
+++ b/runtime/vm/bitmap.h
@@ -47,6 +47,8 @@
   // Sets min..max (inclusive) to value.
   void SetRange(intptr_t min, intptr_t max, bool value);
 
+  void Print() const;
+
  private:
   static const intptr_t kInitialSizeInBytes = 16;
   static const intptr_t kIncrementSizeInBytes = 16;
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index c461d93..0c9a7ec 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -189,6 +189,7 @@
     case DeoptInstr::kStackSlot:
     case DeoptInstr::kDoubleStackSlot:
     case DeoptInstr::kInt64StackSlot:
+    case DeoptInstr::kInt64StackSlotPair:
     case DeoptInstr::kFloat32x4StackSlot:
     case DeoptInstr::kInt32x4StackSlot:
     case DeoptInstr::kFloat64x2StackSlot:
@@ -199,7 +200,8 @@
 
     case DeoptInstr::kRegister:
     case DeoptInstr::kFpuRegister:
-    case DeoptInstr::kInt64FpuRegister:
+    case DeoptInstr::kInt64RegisterPair:
+    case DeoptInstr::kInt64StackSlotRegister:
     case DeoptInstr::kFloat32x4FpuRegister:
     case DeoptInstr::kInt32x4FpuRegister:
     case DeoptInstr::kFloat64x2FpuRegister:
@@ -451,7 +453,7 @@
 
   virtual const char* ToCString() const {
     return Isolate::Current()->current_zone()->PrintToString(
-        "ms%" Pd "", stack_slot_index_);
+        "int64 stack slot:%" Pd "", stack_slot_index_);
   }
 
   void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
@@ -719,21 +721,28 @@
 };
 
 
-class DeoptInt64FpuRegisterInstr: public DeoptInstr {
+class DeoptInt64RegisterPairInstr: public DeoptInstr {
  public:
-  explicit DeoptInt64FpuRegisterInstr(intptr_t reg_as_int)
-      : reg_(static_cast<FpuRegister>(reg_as_int)) {}
+  DeoptInt64RegisterPairInstr(intptr_t lo_reg_as_int, intptr_t hi_reg_as_int)
+      : lo_reg_(static_cast<Register>(lo_reg_as_int)),
+        hi_reg_(static_cast<Register>(hi_reg_as_int)) {}
 
-  virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); }
-  virtual DeoptInstr::Kind kind() const { return kInt64FpuRegister; }
+  virtual intptr_t source_index() const {
+    return EncodeRegisters(static_cast<intptr_t>(lo_reg_),
+                           static_cast<intptr_t>(hi_reg_));
+  }
+  virtual DeoptInstr::Kind kind() const { return kInt64RegisterPair; }
 
   virtual const char* ToCString() const {
     return Isolate::Current()->current_zone()->PrintToString(
-        "%s(m)", Assembler::FpuRegisterName(reg_));
+        "int64 register pair: %s,%s", Assembler::RegisterName(hi_reg_),
+                                      Assembler::RegisterName(lo_reg_));
   }
 
   void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
-    int64_t value = deopt_context->FpuRegisterValueAsInt64(reg_);
+    uint32_t lo_value = deopt_context->RegisterValue(lo_reg_);
+    int32_t hi_value = deopt_context->RegisterValue(hi_reg_);
+    int64_t value = Utils::LowHighTo64Bits(lo_value, hi_value);
     *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0);
     if (Smi::IsValid64(value)) {
       *dest_addr = reinterpret_cast<intptr_t>(
@@ -744,10 +753,178 @@
     }
   }
 
- private:
-  const FpuRegister reg_;
+  static const intptr_t kFieldWidth = kBitsPerWord / 2;
+  class LoRegister : public BitField<intptr_t, 0, kFieldWidth> { };
+  class HiRegister : public BitField<intptr_t, kFieldWidth, kFieldWidth> { };
+  static intptr_t EncodeRegisters(intptr_t lo_reg_as_int,
+                                  intptr_t hi_reg_as_int) {
+    return LoRegister::encode(lo_reg_as_int) |
+           HiRegister::encode(hi_reg_as_int);
+  }
 
-  DISALLOW_COPY_AND_ASSIGN(DeoptInt64FpuRegisterInstr);
+  static intptr_t DecodeLoRegister(intptr_t v) {
+    return LoRegister::decode(v);
+  }
+
+  static intptr_t DecodeHiRegister(intptr_t v) {
+    return HiRegister::decode(v);
+  }
+
+ private:
+  const Register lo_reg_;
+  const Register hi_reg_;
+
+  DISALLOW_COPY_AND_ASSIGN(DeoptInt64RegisterPairInstr);
+};
+
+
+class DeoptInt64StackSlotPairInstr: public DeoptInstr {
+ public:
+  DeoptInt64StackSlotPairInstr(intptr_t lo_slot, intptr_t hi_slot)
+      : lo_slot_(static_cast<Register>(lo_slot)),
+        hi_slot_(static_cast<Register>(hi_slot)) {}
+
+  virtual intptr_t source_index() const {
+    return EncodeSlots(static_cast<intptr_t>(lo_slot_),
+                       static_cast<intptr_t>(hi_slot_));
+  }
+  virtual DeoptInstr::Kind kind() const { return kInt64StackSlotPair; }
+
+  virtual const char* ToCString() const {
+    return Isolate::Current()->current_zone()->PrintToString(
+        "int64 stack slots: %" Pd", %" Pd "", lo_slot_, hi_slot_);
+  }
+
+  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
+    intptr_t lo_source_index =
+        deopt_context->source_frame_size() - lo_slot_ - 1;
+    int32_t* lo_source_addr = reinterpret_cast<int32_t*>(
+        deopt_context->GetSourceFrameAddressAt(lo_source_index));
+    intptr_t hi_source_index =
+       deopt_context->source_frame_size() - hi_slot_ - 1;
+    int32_t* hi_source_addr = reinterpret_cast<int32_t*>(
+        deopt_context->GetSourceFrameAddressAt(hi_source_index));
+    int64_t value = Utils::LowHighTo64Bits(*lo_source_addr, *hi_source_addr);
+    *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0);
+    if (Smi::IsValid64(value)) {
+      *dest_addr = reinterpret_cast<intptr_t>(
+          Smi::New(static_cast<intptr_t>(value)));
+    } else {
+      deopt_context->DeferMintMaterialization(
+          value, reinterpret_cast<RawMint**>(dest_addr));
+    }
+  }
+
+  static const intptr_t kFieldWidth = kBitsPerWord / 2;
+  class LoSlot : public BitField<intptr_t, 0, kFieldWidth> { };
+  class HiSlot : public BitField<intptr_t, kFieldWidth, kFieldWidth> { };
+  static intptr_t EncodeSlots(intptr_t lo_slot,
+                              intptr_t hi_slot) {
+    return LoSlot::encode(lo_slot) |
+           HiSlot::encode(hi_slot);
+  }
+
+  static intptr_t DecodeLoSlot(intptr_t v) {
+    return LoSlot::decode(v);
+  }
+
+  static intptr_t DecodeHiSlot(intptr_t v) {
+    return HiSlot::decode(v);
+  }
+
+ private:
+  const intptr_t lo_slot_;
+  const intptr_t hi_slot_;
+
+  DISALLOW_COPY_AND_ASSIGN(DeoptInt64StackSlotPairInstr);
+};
+
+
+class DeoptInt64StackSlotRegisterInstr : public DeoptInstr {
+ public:
+  DeoptInt64StackSlotRegisterInstr(intptr_t source_index,
+                                   intptr_t reg_as_int,
+                                   bool flip)
+      : slot_(source_index),
+        reg_(static_cast<Register>(reg_as_int)),
+        flip_(flip) {
+    // when flip_ is false, stack slot is low bits and reg is high bits.
+    // when flip_ is true, stack slot is high bits and reg is low bits.
+  }
+
+  virtual intptr_t source_index() const {
+    return Encode(static_cast<intptr_t>(slot_),
+                  static_cast<intptr_t>(reg_),
+                  flip_ ? 1 : 0);
+  }
+  virtual DeoptInstr::Kind kind() const { return kInt64StackSlotRegister; }
+
+  virtual const char* ToCString() const {
+    if (flip_) {
+      return Isolate::Current()->current_zone()->PrintToString(
+          "int64 reg: %s, stack slot:  %" Pd "", Assembler::RegisterName(reg_),
+                                                 slot_);
+    } else {
+      return Isolate::Current()->current_zone()->PrintToString(
+          "int64 stack slot: %" Pd", reg: %s", slot_,
+                                               Assembler::RegisterName(reg_));
+    }
+  }
+
+  void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
+    intptr_t slot_source_index =
+        deopt_context->source_frame_size() - slot_ - 1;
+    int32_t* slot_source_addr = reinterpret_cast<int32_t*>(
+        deopt_context->GetSourceFrameAddressAt(slot_source_index));
+    int32_t slot_value = *slot_source_addr;
+    int32_t reg_value = deopt_context->RegisterValue(reg_);
+    int64_t value;
+    if (flip_) {
+      value = Utils::LowHighTo64Bits(reg_value, slot_value);
+    } else {
+      value = Utils::LowHighTo64Bits(slot_value, reg_value);
+    }
+    *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0);
+    if (Smi::IsValid64(value)) {
+      *dest_addr = reinterpret_cast<intptr_t>(
+          Smi::New(static_cast<intptr_t>(value)));
+    } else {
+      deopt_context->DeferMintMaterialization(
+          value, reinterpret_cast<RawMint**>(dest_addr));
+    }
+  }
+
+  static const intptr_t kFieldWidth = kBitsPerWord / 2;
+  class Slot : public BitField<intptr_t, 0, kFieldWidth> { };
+  class Reg : public BitField<intptr_t, kFieldWidth, kFieldWidth - 1> { };
+  // 1 bit for the flip.
+  class Flip : public BitField<intptr_t, kFieldWidth * 2 - 1, 1> { };
+
+  static intptr_t Encode(intptr_t slot,
+                         intptr_t reg_as_int,
+                         bool flip) {
+    return Slot::encode(slot) |
+           Reg::encode(reg_as_int) |
+           Flip::encode(flip ? 1 : 0);
+  }
+
+  static intptr_t DecodeSlot(intptr_t v) {
+    return Slot::decode(v);
+  }
+
+  static intptr_t DecodeReg(intptr_t v) {
+    return Reg::decode(v);
+  }
+
+  static bool DecodeFlip(intptr_t v) {
+    return Flip::decode(v);
+  }
+
+ private:
+  const intptr_t slot_;
+  const Register reg_;
+  const bool flip_;
+  DISALLOW_COPY_AND_ASSIGN(DeoptInt64StackSlotRegisterInstr);
 };
 
 
@@ -1139,7 +1316,28 @@
     case kConstant: return new DeoptConstantInstr(source_index);
     case kRegister: return new DeoptRegisterInstr(source_index);
     case kFpuRegister: return new DeoptFpuRegisterInstr(source_index);
-    case kInt64FpuRegister: return new DeoptInt64FpuRegisterInstr(source_index);
+    case kInt64RegisterPair: {
+      intptr_t lo_reg_as_int =
+          DeoptInt64RegisterPairInstr::LoRegister::decode(source_index);
+      intptr_t hi_reg_as_int =
+          DeoptInt64RegisterPairInstr::HiRegister::decode(source_index);
+      return new DeoptInt64RegisterPairInstr(lo_reg_as_int, hi_reg_as_int);
+    }
+    case kInt64StackSlotPair: {
+      intptr_t lo_slot =
+          DeoptInt64StackSlotPairInstr::LoSlot::decode(source_index);
+      intptr_t hi_slot =
+          DeoptInt64StackSlotPairInstr::HiSlot::decode(source_index);
+      return new DeoptInt64StackSlotPairInstr(lo_slot, hi_slot);
+    }
+    case kInt64StackSlotRegister: {
+      intptr_t slot =
+          DeoptInt64StackSlotRegisterInstr::Slot::decode(source_index);
+      intptr_t reg_as_int =
+          DeoptInt64StackSlotRegisterInstr::Reg::decode(source_index);
+      bool flip = DeoptInt64StackSlotRegisterInstr::Flip::decode(source_index);
+      return new DeoptInt64StackSlotRegisterInstr(slot, reg_as_int, flip);
+    }
     case kFloat32x4FpuRegister:
         return new DeoptFloat32x4FpuRegisterInstr(source_index);
     case kFloat64x2FpuRegister:
@@ -1271,8 +1469,6 @@
   } else if (source_loc.IsFpuRegister()) {
     if (value->definition()->representation() == kUnboxedDouble) {
       deopt_instr = new DeoptFpuRegisterInstr(source_loc.fpu_reg());
-    } else if (value->definition()->representation() == kUnboxedMint) {
-      deopt_instr = new DeoptInt64FpuRegisterInstr(source_loc.fpu_reg());
     } else if (value->definition()->representation() == kUnboxedFloat32x4) {
       deopt_instr = new DeoptFloat32x4FpuRegisterInstr(source_loc.fpu_reg());
     } else if (value->definition()->representation() == kUnboxedInt32x4) {
@@ -1303,6 +1499,34 @@
       ASSERT(value->definition()->representation() == kUnboxedFloat64x2);
       deopt_instr = new DeoptFloat64x2StackSlotInstr(source_index);
     }
+  } else if (source_loc.IsPairLocation()) {
+    ASSERT(value->definition()->representation() == kUnboxedMint);
+    // There are four cases to consider here:
+    // (R = Register, S = Stack slot).
+    // 1) R, R.
+    // 2) S, S.
+    // 3) R, S.
+    // 4) S, R.
+    PairLocation* pair = source_loc.AsPairLocation();
+    if (pair->At(0).IsRegister() && pair->At(1).IsRegister()) {
+      deopt_instr = new DeoptInt64RegisterPairInstr(pair->At(0).reg(),
+                                                    pair->At(1).reg());
+    } else if (pair->At(0).IsStackSlot() && pair->At(1).IsStackSlot()) {
+      deopt_instr = new DeoptInt64StackSlotPairInstr(
+          CalculateStackIndex(pair->At(0)),
+          CalculateStackIndex(pair->At(1)));
+    } else if (pair->At(0).IsRegister() && pair->At(1).IsStackSlot()) {
+      deopt_instr = new DeoptInt64StackSlotRegisterInstr(
+          CalculateStackIndex(pair->At(1)),
+          pair->At(0).reg(),
+          true);
+    } else {
+      ASSERT(pair->At(0).IsStackSlot() && pair->At(1).IsRegister());
+      deopt_instr = new DeoptInt64StackSlotRegisterInstr(
+          CalculateStackIndex(pair->At(0)),
+          pair->At(1).reg(),
+          false);
+    }
   } else if (source_loc.IsInvalid() &&
              value->definition()->IsMaterializeObject()) {
     const intptr_t index = FindMaterialization(
diff --git a/runtime/vm/deopt_instructions.h b/runtime/vm/deopt_instructions.h
index 551d043..23a5e97 100644
--- a/runtime/vm/deopt_instructions.h
+++ b/runtime/vm/deopt_instructions.h
@@ -58,21 +58,29 @@
 
   intptr_t RegisterValue(Register reg) const {
     ASSERT(cpu_registers_ != NULL);
+    ASSERT(reg >= 0);
+    ASSERT(reg < kNumberOfCpuRegisters);
     return cpu_registers_[reg];
   }
 
   double FpuRegisterValue(FpuRegister reg) const {
     ASSERT(fpu_registers_ != NULL);
+    ASSERT(reg >= 0);
+    ASSERT(reg < kNumberOfFpuRegisters);
     return *reinterpret_cast<double*>(&fpu_registers_[reg]);
   }
 
   int64_t FpuRegisterValueAsInt64(FpuRegister reg) const {
     ASSERT(fpu_registers_ != NULL);
+    ASSERT(reg >= 0);
+    ASSERT(reg < kNumberOfFpuRegisters);
     return *reinterpret_cast<int64_t*>(&fpu_registers_[reg]);
   }
 
   simd128_value_t FpuRegisterValueAsSimd128(FpuRegister reg) const {
     ASSERT(fpu_registers_ != NULL);
+    ASSERT(reg >= 0);
+    ASSERT(reg < kNumberOfFpuRegisters);
     const float* address = reinterpret_cast<float*>(&fpu_registers_[reg]);
     return simd128_value_t().readFrom(address);
   }
@@ -216,16 +224,18 @@
     kConstant,
     kRegister,
     kFpuRegister,
-    kInt64FpuRegister,
+    kInt64RegisterPair,
     kFloat32x4FpuRegister,
     kFloat64x2FpuRegister,
     kInt32x4FpuRegister,
     kStackSlot,
     kDoubleStackSlot,
     kInt64StackSlot,
+    kInt64StackSlotPair,
     kFloat32x4StackSlot,
     kFloat64x2StackSlot,
     kInt32x4StackSlot,
+    kInt64StackSlotRegister,
     kPcMarker,
     kPp,
     kCallerFp,
diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc
index 4a3d66d..bfc098f 100644
--- a/runtime/vm/flow_graph_allocator.cc
+++ b/runtime/vm/flow_graph_allocator.cc
@@ -398,11 +398,24 @@
     return;
   }
 
-  OS::Print("  live range v%" Pd " [%" Pd ", %" Pd ") in ",
-            vreg(), Start(), End());
+  OS::Print("  live range v%" Pd " [%" Pd ", %" Pd ") in ", vreg(),
+                                                            Start(),
+                                                            End());
   assigned_location().Print();
+  if (spill_slot_.HasStackIndex()) {
+    intptr_t stack_slot = spill_slot_.stack_index();
+    OS::Print(" allocated spill slot: %" Pd "", stack_slot);
+  }
   OS::Print("\n");
 
+  SafepointPosition* safepoint = first_safepoint();
+  while (safepoint != NULL) {
+    OS::Print("    Safepoint [%" Pd "]: ", safepoint->pos());
+    safepoint->locs()->stack_bitmap()->Print();
+    OS::Print("\n");
+    safepoint = safepoint->next();
+  }
+
   UsePosition* use_pos = uses_;
   for (UseInterval* interval = first_use_interval_;
        interval != NULL;
@@ -564,6 +577,7 @@
   GraphEntryInstr* graph_entry = flow_graph_.graph_entry();
   for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) {
     Definition* defn = (*graph_entry->initial_definitions())[i];
+    ASSERT(!defn->HasPairRepresentation());
     LiveRange* range = GetLiveRange(defn->ssa_temp_index());
     range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos());
     range->DefineAt(graph_entry->start_pos());
@@ -612,11 +626,14 @@
     // in stack maps.
     spill_slots_.Add(range_end);
     quad_spill_slots_.Add(false);
+    untagged_spill_slots_.Add(false);
+    // Note, all incoming parameters are assumed to be tagged.
     MarkAsObjectAtSafepoints(range);
   } else if (defn->IsConstant() && block->IsCatchBlockEntry()) {
     // Constants at catch block entries consume spill slots.
     spill_slots_.Add(range_end);
     quad_spill_slots_.Add(false);
+    untagged_spill_slots_.Add(false);
   }
 }
 
@@ -632,7 +649,6 @@
 
 static Location::Kind RegisterKindForResult(Instruction* instr) {
   if ((instr->representation() == kUnboxedDouble) ||
-      (instr->representation() == kUnboxedMint) ||
       (instr->representation() == kUnboxedFloat32x4) ||
       (instr->representation() == kUnboxedInt32x4) ||
       (instr->representation() == kUnboxedFloat64x2) ||
@@ -802,8 +818,12 @@
 
     for (intptr_t i = 0; i < env->Length(); ++i) {
       Value* value = env->ValueAt(i);
-      locations[i] = Location::Any();
       Definition* def = value->definition();
+      if (def->HasPairRepresentation()) {
+        locations[i] = Location::Pair(Location::Any(), Location::Any());
+      } else {
+        locations[i] = Location::Any();
+      }
 
       if (def->IsPushArgument()) {
         // Frame size is unknown until after allocation.
@@ -827,13 +847,23 @@
         continue;
       }
 
-      LiveRange* range = GetLiveRange(def->ssa_temp_index());
-      range->AddUseInterval(block_start_pos, use_pos);
-      range->AddUse(use_pos, &locations[i]);
-
       if (def->HasPairRepresentation()) {
-        LiveRange* range =
+        PairLocation* location_pair = locations[i].AsPairLocation();
+        {
+          // First live range.
+          LiveRange* range = GetLiveRange(def->ssa_temp_index());
+          range->AddUseInterval(block_start_pos, use_pos);
+          range->AddUse(use_pos, location_pair->SlotAt(0));
+        }
+        {
+          // Second live range.
+          LiveRange* range =
             GetLiveRange(ToSecondPairVreg(def->ssa_temp_index()));
+          range->AddUseInterval(block_start_pos, use_pos);
+          range->AddUse(use_pos, location_pair->SlotAt(1));
+        }
+      } else {
+        LiveRange* range = GetLiveRange(def->ssa_temp_index());
         range->AddUseInterval(block_start_pos, use_pos);
         range->AddUse(use_pos, &locations[i]);
       }
@@ -869,13 +899,25 @@
       continue;
     }
 
-    locations[i] = Location::Any();
-
-    LiveRange* range = GetLiveRange(def->ssa_temp_index());
-    range->AddUseInterval(block_start_pos, use_pos);
-    range->AddUse(use_pos, &locations[i]);
     if (def->HasPairRepresentation()) {
-      LiveRange* range = GetLiveRange(ToSecondPairVreg(def->ssa_temp_index()));
+      locations[i] = Location::Pair(Location::Any(), Location::Any());
+      PairLocation* location_pair = locations[i].AsPairLocation();
+      {
+        // First live range.
+        LiveRange* range = GetLiveRange(def->ssa_temp_index());
+        range->AddUseInterval(block_start_pos, use_pos);
+        range->AddUse(use_pos, location_pair->SlotAt(0));
+      }
+      {
+        // Second live range.
+        LiveRange* range =
+            GetLiveRange(ToSecondPairVreg(def->ssa_temp_index()));
+        range->AddUseInterval(block_start_pos, use_pos);
+        range->AddUse(use_pos, location_pair->SlotAt(1));
+      }
+    } else {
+      locations[i] = Location::Any();
+      LiveRange* range = GetLiveRange(def->ssa_temp_index());
       range->AddUseInterval(block_start_pos, use_pos);
       range->AddUse(use_pos, &locations[i]);
     }
@@ -889,7 +931,8 @@
                                          intptr_t pos,
                                          Location* in_ref,
                                          Value* input,
-                                         intptr_t vreg) {
+                                         intptr_t vreg,
+                                         RegisterSet* live_registers) {
   ASSERT(in_ref != NULL);
   ASSERT(!in_ref->IsPairLocation());
   ASSERT(input != NULL);
@@ -903,6 +946,9 @@
     //      value    --*
     //      register   [-----)
     //
+    if (live_registers != NULL) {
+      live_registers->Add(*in_ref, range->representation());
+    }
     MoveOperands* move =
         AddMoveAt(pos - 1, *in_ref, Location::Any());
     BlockLocation(*in_ref, pos - 1, pos + 1);
@@ -1114,6 +1160,12 @@
       locs->out(0).IsUnallocated() &&
       (locs->out(0).policy() == Location::kSameAsFirstInput);
 
+  // Output is same as first input which is a pair.
+  if (output_same_as_first_input && locs->in(0).IsPairLocation()) {
+    // Make out into a PairLocation.
+    locs->set_out(0, Location::Pair(Location::RequiresRegister(),
+                                    Location::RequiresRegister()));
+  }
   // Add uses from the deoptimization environment.
   if (current->env() != NULL) ProcessEnvironmentUses(block, current);
 
@@ -1128,6 +1180,10 @@
       // the location is the first register or second register.
       Value* input = current->InputAt(j);
       Location* in_ref = locs->in_slot(j);
+      RegisterSet* live_registers = NULL;
+      if (locs->HasCallOnSlowPath()) {
+        live_registers = locs->live_registers();
+      }
       if (in_ref->IsPairLocation()) {
         ASSERT(input->definition()->HasPairRepresentation());
         PairLocation* pair = in_ref->AsPairLocation();
@@ -1135,12 +1191,12 @@
         // Each element of the pair is assigned it's own virtual register number
         // and is allocated its own LiveRange.
         ProcessOneInput(block, pos, pair->SlotAt(0),
-                        input, vreg);
+                        input, vreg, live_registers);
         ProcessOneInput(block, pos, pair->SlotAt(1), input,
-                        ToSecondPairVreg(vreg));
+                        ToSecondPairVreg(vreg), live_registers);
       } else {
         ProcessOneInput(block, pos, in_ref, input,
-                        input->definition()->ssa_temp_index());
+                        input->definition()->ssa_temp_index(), live_registers);
       }
     }
   }
@@ -1522,6 +1578,16 @@
 }
 
 
+UsePosition* AllocationFinger::FirstInterferingUse(intptr_t after) {
+  if (IsInstructionEndPosition(after)) {
+    // If after is a position at the end of the instruction disregard
+    // any use occuring at it.
+    after += 1;
+  }
+  return FirstRegisterUse(after);
+}
+
+
 void AllocationFinger::UpdateAfterSplit(intptr_t first_use_after_split_pos) {
   if ((first_register_use_ != NULL) &&
       (first_register_use_->pos() >= first_use_after_split_pos)) {
@@ -1695,7 +1761,8 @@
     split_pos = ToInstructionStart(to) - 1;
   }
 
-  ASSERT((split_pos != kIllegalPosition) && (from < split_pos));
+  ASSERT(split_pos != kIllegalPosition);
+  ASSERT(from < split_pos);
 
   return range->SplitAt(split_pos);
 }
@@ -1769,6 +1836,8 @@
       ((range->representation() == kUnboxedFloat32x4) ||
        (range->representation() == kUnboxedInt32x4)   ||
        (range->representation() == kUnboxedFloat64x2));
+  const bool need_untagged = (register_kind_ == Location::kRegister) &&
+      ((range->representation() == kUntagged));
 
   // Search for a free spill slot among allocated: the value in it should be
   // dead and its type should match (e.g. it should not be a part of the quad if
@@ -1780,6 +1849,7 @@
       : 0;
   for (; idx < spill_slots_.length(); idx++) {
     if ((need_quad == quad_spill_slots_[idx]) &&
+        (need_untagged == untagged_spill_slots_[idx]) &&
         (spill_slots_[idx] <= start)) {
       break;
     }
@@ -1789,9 +1859,11 @@
     // No free spill slot found. Allocate a new one.
     spill_slots_.Add(0);
     quad_spill_slots_.Add(need_quad);
+    untagged_spill_slots_.Add(need_untagged);
     if (need_quad) {  // Allocate two double stack slots if we need quad slot.
       spill_slots_.Add(0);
       quad_spill_slots_.Add(need_quad);
+      untagged_spill_slots_.Add(need_untagged);
     }
   }
 
@@ -1822,8 +1894,7 @@
       ASSERT(need_quad);
       location = Location::QuadStackSlot(slot_idx);
     } else {
-      ASSERT((range->representation() == kUnboxedDouble) ||
-             (range->representation() == kUnboxedMint));
+      ASSERT((range->representation() == kUnboxedDouble));
       location = Location::DoubleStackSlot(slot_idx);
     }
     range->set_spill_slot(location);
@@ -1841,6 +1912,7 @@
     for (SafepointPosition* safepoint = range->first_safepoint();
          safepoint != NULL;
          safepoint = safepoint->next()) {
+      // Mark the stack slot as having an object.
       safepoint->locs()->stack_bitmap()->Set(stack_index, true);
     }
     range = range->next_sibling();
@@ -2199,9 +2271,8 @@
         return false;
       }
 
-      const UsePosition* use =
-          allocated->finger()->FirstRegisterBeneficialUse(unallocated->Start());
-
+      UsePosition* use =
+          allocated->finger()->FirstInterferingUse(start);
       if ((use != NULL) && ((ToInstructionStart(use->pos()) - start) <= 1)) {
         // This register is blocked by interval that is used
         // as register in the current instruction and can't
@@ -2281,7 +2352,7 @@
   if (intersection == kMaxPosition) return false;
 
   const intptr_t spill_position = first_unallocated->start();
-  UsePosition* use = allocated->finger()->FirstRegisterUse(spill_position);
+  UsePosition* use = allocated->finger()->FirstInterferingUse(spill_position);
   if (use == NULL) {
     // No register uses after this point.
     SpillAfter(allocated, spill_position);
@@ -2316,6 +2387,7 @@
 
 
 void FlowGraphAllocator::ConvertUseTo(UsePosition* use, Location loc) {
+  ASSERT(!loc.IsPairLocation());
   ASSERT(use->location_slot() != NULL);
   Location* slot = use->location_slot();
   ASSERT(slot->IsUnallocated());
@@ -2350,7 +2422,7 @@
          safepoint = safepoint->next()) {
       if (!safepoint->locs()->always_calls()) {
         ASSERT(safepoint->locs()->can_call());
-        safepoint->locs()->live_registers()->Add(loc);
+        safepoint->locs()->live_registers()->Add(loc, range->representation());
       }
     }
   }
@@ -2669,12 +2741,22 @@
 }
 
 
+static Representation RepresentationForRange(Representation definition_rep) {
+  if (definition_rep == kUnboxedMint) {
+    // kUnboxedMint is split into two ranges, each of which are kUntagged.
+    return kUntagged;
+  }
+  return definition_rep;
+}
+
+
 void FlowGraphAllocator::CollectRepresentations() {
   // Parameters.
   GraphEntryInstr* graph_entry = flow_graph_.graph_entry();
   for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); ++i) {
     Definition* def = (*graph_entry->initial_definitions())[i];
-    value_representations_[def->ssa_temp_index()] = def->representation();
+    value_representations_[def->ssa_temp_index()] =
+        RepresentationForRange(def->representation());
     ASSERT(!def->HasPairRepresentation());
   }
 
@@ -2690,7 +2772,9 @@
            i < catch_entry->initial_definitions()->length();
            ++i) {
         Definition* def = (*catch_entry->initial_definitions())[i];
-        value_representations_[def->ssa_temp_index()] = def->representation();
+        ASSERT(!def->HasPairRepresentation());
+        value_representations_[def->ssa_temp_index()] =
+            RepresentationForRange(def->representation());
       }
     }
     // Phis.
@@ -2700,7 +2784,9 @@
         // TODO(johnmccutchan): Fix handling of PhiInstr with PairLocation.
         PhiInstr* phi = it.Current();
         if ((phi != NULL) && (phi->ssa_temp_index() >= 0)) {
-          value_representations_[phi->ssa_temp_index()] = phi->representation();
+          ASSERT(!phi->HasPairRepresentation());
+          value_representations_[phi->ssa_temp_index()] =
+              RepresentationForRange(phi->representation());
         }
       }
     }
@@ -2711,9 +2797,11 @@
       Definition* def = instr_it.Current()->AsDefinition();
       if ((def != NULL) && (def->ssa_temp_index() >= 0)) {
         const intptr_t vreg = def->ssa_temp_index();
-        value_representations_[vreg] = def->representation();
+        value_representations_[vreg] =
+            RepresentationForRange(def->representation());
         if (def->HasPairRepresentation()) {
-         value_representations_[ToSecondPairVreg(vreg)] = def->representation();
+         value_representations_[ToSecondPairVreg(vreg)] =
+            RepresentationForRange(def->representation());
         }
       }
     }
@@ -2761,6 +2849,7 @@
   cpu_spill_slot_count_ = spill_slots_.length();
   spill_slots_.Clear();
   quad_spill_slots_.Clear();
+  untagged_spill_slots_.Clear();
 
   PrepareForAllocation(Location::kFpuRegister,
                        kNumberOfFpuRegisters,
diff --git a/runtime/vm/flow_graph_allocator.h b/runtime/vm/flow_graph_allocator.h
index ab05f25..e795552b 100644
--- a/runtime/vm/flow_graph_allocator.h
+++ b/runtime/vm/flow_graph_allocator.h
@@ -113,7 +113,8 @@
                        intptr_t pos,
                        Location* in_ref,
                        Value* input,
-                       intptr_t vreg);
+                       intptr_t vreg,
+                       RegisterSet* live_registers);
   void ProcessOneOutput(BlockEntryInstr* block,
                         Instruction* current,
                         intptr_t pos,
@@ -317,6 +318,11 @@
   // are disjoint.
   GrowableArray<bool> quad_spill_slots_;
 
+  // Track whether a spill slot is expected to hold a tagged or untagged value.
+  // This is used to keep tagged and untagged spill slots disjoint. See bug
+  // #18955 for details.
+  GrowableArray<bool> untagged_spill_slots_;
+
   intptr_t cpu_spill_slot_count_;
 
   DISALLOW_COPY_AND_ASSIGN(FlowGraphAllocator);
@@ -498,6 +504,7 @@
   Location FirstHint();
   UsePosition* FirstRegisterUse(intptr_t after_pos);
   UsePosition* FirstRegisterBeneficialUse(intptr_t after_pos);
+  UsePosition* FirstInterferingUse(intptr_t after_pos);
 
  private:
   UseInterval* first_pending_use_interval_;
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 648bc6e..7da1818 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -567,7 +567,7 @@
       for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
         Register reg = static_cast<Register>(i);
         if (locs->live_registers()->ContainsRegister(reg)) {
-          bitmap->Set(bitmap->Length(), true);
+          bitmap->Set(bitmap->Length(), locs->live_registers()->IsTagged(reg));
         }
       }
     }
@@ -638,7 +638,6 @@
       Value* value = it.CurrentValue();
       switch (value->definition()->representation()) {
         case kUnboxedDouble:
-        case kUnboxedMint:
           it.SetCurrentLocation(Location::DoubleStackSlot(index));
           break;
         case kUnboxedFloat32x4:
@@ -649,6 +648,27 @@
         default:
           UNREACHABLE();
       }
+    } else if (loc.IsPairLocation()) {
+      intptr_t representation =
+          it.CurrentValue()->definition()->representation();
+      ASSERT(representation == kUnboxedMint);
+      PairLocation* value_pair = loc.AsPairLocation();
+      intptr_t index_lo;
+      intptr_t index_hi;
+      if (value_pair->At(0).IsRegister()) {
+        index_lo = cpu_reg_slots[value_pair->At(0).reg()];
+      } else {
+        ASSERT(value_pair->At(0).IsStackSlot());
+        index_lo = value_pair->At(0).stack_index();
+      }
+      if (value_pair->At(1).IsRegister()) {
+        index_hi = cpu_reg_slots[value_pair->At(1).reg()];
+      } else {
+        ASSERT(value_pair->At(1).IsStackSlot());
+        index_hi = value_pair->At(1).stack_index();
+      }
+      it.SetCurrentLocation(Location::Pair(Location::StackSlot(index_lo),
+                                           Location::StackSlot(index_hi)));
     } else if (loc.IsInvalid()) {
       Definition* def =
           it.CurrentValue()->definition();
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 3ea3503..17253e2 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -1446,23 +1446,25 @@
     ASSERT(offset == (fpu_regs_count * kFpuRegisterSize));
   }
 
-  // Store general purpose registers with the lowest register number at the
+  // Store general purpose registers with the highest register number at the
   // lowest address.
-  const intptr_t cpu_registers = locs->live_registers()->cpu_registers();
-  ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0);
-  if (cpu_registers != 0) {
-    __ PushList(cpu_registers);
+  for (intptr_t reg_idx = 0; reg_idx < kNumberOfCpuRegisters; ++reg_idx) {
+    Register reg = static_cast<Register>(reg_idx);
+    if (locs->live_registers()->ContainsRegister(reg)) {
+      __ Push(reg);
+    }
   }
 }
 
 
 void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) {
-  // General purpose registers have the lowest register number at the
+  // General purpose registers have the highest register number at the
   // lowest address.
-  const intptr_t cpu_registers = locs->live_registers()->cpu_registers();
-  ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0);
-  if (cpu_registers != 0) {
-    __ PopList(cpu_registers);
+  for (intptr_t reg_idx = kNumberOfCpuRegisters - 1; reg_idx >= 0; --reg_idx) {
+    Register reg = static_cast<Register>(reg_idx);
+    if (locs->live_registers()->ContainsRegister(reg)) {
+      __ Pop(reg);
+    }
   }
 
   const intptr_t fpu_regs_count = locs->live_registers()->FpuRegisterCount();
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index b6338bd..6ef9ef6 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -602,7 +602,7 @@
   Definition* converted = NULL;
   if ((from == kTagged) && (to == kUnboxedMint)) {
     ASSERT((deopt_target != NULL) ||
-           (use->Type()->ToCid() == kDoubleCid));
+           (use->Type()->ToCid() == kUnboxedMint));
     const intptr_t deopt_id = (deopt_target != NULL) ?
         deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId;
     converted = new UnboxIntegerInstr(use->CopyWithType(), deopt_id);
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index a21400c..c1bcf36 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -2131,7 +2131,6 @@
       Value* value = InputAt(i);
       switch (value->definition()->representation()) {
         case kUnboxedDouble:
-        case kUnboxedMint:
           locations_[i] = Location::DoubleStackSlot(index);
           break;
         case kUnboxedFloat32x4:
@@ -2142,6 +2141,8 @@
         default:
           UNREACHABLE();
       }
+    } else if (loc.IsPairLocation()) {
+      UNREACHABLE();
     } else if (loc.IsInvalid()) {
       // We currently only perform one iteration of allocation
       // sinking, so we do not expect to find materialized objects
@@ -2348,7 +2349,7 @@
   for (intptr_t i = 0; i < length; ++i) {
     copy->values_.Add(values_[i]->Copy());
     if (locations_ != NULL) {
-      copy->locations_[i] = locations_[i];
+      copy->locations_[i] = locations_[i].Copy();
     }
   }
   return copy;
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index a266402..b1b982c 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -1779,7 +1779,8 @@
   void ClearSSATempIndex() { ssa_temp_index_ = -1; }
   bool HasPairRepresentation() const {
     return (representation() == kPairOfTagged) ||
-           (representation() == kPairOfUnboxedDouble);
+           (representation() == kPairOfUnboxedDouble) ||
+           (representation() == kUnboxedMint);
   }
 
   // Compile time type of the definition, which may be requested before type
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index a54102b..fd12d67 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -380,14 +380,13 @@
 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   if (operation_cid() == kMintCid) {
-    const intptr_t kNumTemps = 3;
+    const intptr_t kNumTemps = 0;
     LocationSummary* locs =
         new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
-    locs->set_in(0, Location::RequiresFpuRegister());
-    locs->set_in(1, Location::RequiresFpuRegister());
-    locs->set_temp(0, Location::RequiresFpuRegister());
-    locs->set_temp(1, Location::RequiresRegister());
-    locs->set_temp(2, Location::RequiresRegister());
+    locs->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                   Location::RequiresRegister()));
+    locs->set_in(1, Location::Pair(Location::RequiresRegister(),
+                                   Location::RequiresRegister()));
     locs->set_out(0, Location::RequiresRegister());
     return locs;
   }
@@ -515,37 +514,32 @@
                                            LocationSummary* locs,
                                            Token::Kind kind) {
   ASSERT(Token::IsEqualityOperator(kind));
-  const QRegister left = locs->in(0).fpu_reg();
-  const QRegister right = locs->in(1).fpu_reg();
-  const QRegister tmpq = locs->temp(0).fpu_reg();
-  const Register tmp_lo = locs->temp(1).reg();
-  const Register tmp_hi = locs->temp(2).reg();
+  PairLocation* left_pair = locs->in(0).AsPairLocation();
+  Register left1 = left_pair->At(0).reg();
+  Register left2 = left_pair->At(1).reg();
+  PairLocation* right_pair = locs->in(1).AsPairLocation();
+  Register right1 = right_pair->At(0).reg();
+  Register right2 = right_pair->At(1).reg();
 
-  __ vceqqi(kWord, tmpq, left, right);
-  __ vmovrrd(tmp_lo, tmp_hi, EvenDRegisterOf(tmpq));
-  // tmp_lo and tmp_hi must both be 0xffffffff.
-  __ and_(tmp_lo, tmp_lo, ShifterOperand(tmp_hi));
-
-  Condition true_condition = TokenKindToMintCondition(kind);
-  __ CompareImmediate(tmp_lo, 0xffffffff);
-  return true_condition;
+  // Compare lower.
+  __ cmp(left1, ShifterOperand(right1));
+  // Compare upper if lower is equal.
+  __ cmp(left2, ShifterOperand(right2), EQ);
+  return TokenKindToMintCondition(kind);
 }
 
 
 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
                                              LocationSummary* locs,
                                              Token::Kind kind) {
-  const QRegister left = locs->in(0).fpu_reg();
-  const QRegister right = locs->in(1).fpu_reg();
-  const DRegister dleft0 = EvenDRegisterOf(left);
-  const DRegister dright0 = EvenDRegisterOf(right);
-  const SRegister sleft0 = EvenSRegisterOf(dleft0);
-  const SRegister sleft1 = OddSRegisterOf(dleft0);
-  const SRegister sright0 = EvenSRegisterOf(dright0);
-  const SRegister sright1 = OddSRegisterOf(dright0);
+  PairLocation* left_pair = locs->in(0).AsPairLocation();
+  Register left1 = left_pair->At(0).reg();
+  Register left2 = left_pair->At(1).reg();
+  PairLocation* right_pair = locs->in(1).AsPairLocation();
+  Register right1 = right_pair->At(0).reg();
+  Register right2 = right_pair->At(1).reg();
 
-  const Register tmp_left = locs->temp(0).reg();
-  const Register tmp_right = locs->temp(1).reg();
+  Register out = locs->temp(0).reg();
 
   // 64-bit comparison
   Condition hi_true_cond, hi_false_cond, lo_false_cond;
@@ -568,25 +562,18 @@
   }
 
   Label is_true, is_false, done;
-  __ vmovrs(tmp_left, sleft1);
-  __ vmovrs(tmp_right, sright1);
-  __ cmp(tmp_left, ShifterOperand(tmp_right));
-  __ b(&is_false, hi_false_cond);
-  __ b(&is_true, hi_true_cond);
+  // Compare upper halves first.
+  __ cmp(left2, ShifterOperand(right2));
+  __ LoadImmediate(out, 0, hi_false_cond);
+  __ LoadImmediate(out, 1, hi_true_cond);
+  // If higher words aren't equal, skip comparing lower words.
+  __ b(&done, NE);
 
-  __ vmovrs(tmp_left, sleft0);
-  __ vmovrs(tmp_right, sright0);
-  __ cmp(tmp_left, ShifterOperand(tmp_right));
-  __ b(&is_false, lo_false_cond);
-  // Else is true.
-  __ b(&is_true);
-
-  __ Bind(&is_false);
-  __ LoadImmediate(tmp_left, 0);
-  __ b(&done);
-  __ Bind(&is_true);
-  __ LoadImmediate(tmp_left, 1);
+  __ cmp(left1, ShifterOperand(right1));
+  __ LoadImmediate(out, 1);
+  __ LoadImmediate(out, 0, lo_false_cond);
   __ Bind(&done);
+
   return NegateCondition(lo_false_cond);
 }
 
@@ -793,13 +780,14 @@
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   if (operation_cid() == kMintCid) {
-    const intptr_t kNumTemps = 2;
+    const intptr_t kNumTemps = 1;
     LocationSummary* locs =
         new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
-    locs->set_in(0, Location::RequiresFpuRegister());
-    locs->set_in(1, Location::RequiresFpuRegister());
+    locs->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                   Location::RequiresRegister()));
+    locs->set_in(1, Location::Pair(Location::RequiresRegister(),
+                                   Location::RequiresRegister()));
     locs->set_temp(0, Location::RequiresRegister());
-    locs->set_temp(1, Location::RequiresRegister());
     locs->set_out(0, Location::RequiresRegister());
     return locs;
   }
@@ -1153,7 +1141,11 @@
     } else {
       locs->set_out(0, Location::RequiresFpuRegister());
     }
+  } else if (representation() == kUnboxedMint) {
+    locs->set_out(0, Location::Pair(Location::RequiresRegister(),
+                                    Location::RequiresRegister()));
   } else {
+    ASSERT(representation() == kTagged);
     locs->set_out(0, Location::RequiresRegister());
   }
   return locs;
@@ -1162,7 +1154,6 @@
 
 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   if ((representation() == kUnboxedDouble)    ||
-      (representation() == kUnboxedMint)      ||
       (representation() == kUnboxedFloat32x4) ||
       (representation() == kUnboxedInt32x4)   ||
       (representation() == kUnboxedFloat64x2)) {
@@ -1194,23 +1185,6 @@
     const QRegister result = locs()->out(0).fpu_reg();
     const DRegister dresult0 = EvenDRegisterOf(result);
     switch (class_id()) {
-      case kTypedDataInt32ArrayCid:
-        __ veorq(result, result, result);
-        __ ldr(TMP, element_address);
-        // Re-use the index register so we don't have to require a low-numbered
-        // Q register.
-        // Sign-extend into idx.
-        __ Asr(idx, TMP, 31);
-        __ vmovdrr(dresult0, TMP, idx);
-        break;
-      case kTypedDataUint32ArrayCid:
-        __ veorq(result, result, result);
-        __ ldr(TMP, element_address);
-        // Re-use the index register so we don't have to require a low-numbered
-        // Q register.
-        __ LoadImmediate(idx, 0);
-        __ vmovdrr(dresult0, TMP, idx);
-        break;
       case kTypedDataFloat32ArrayCid:
         // Load single precision float.
         // vldrs does not support indexed addressing.
@@ -1225,6 +1199,8 @@
       case kTypedDataFloat32x4ArrayCid:
         __ vldmd(IA, idx, dresult0, 2);
         break;
+      default:
+        UNREACHABLE();
     }
     return;
   }
@@ -1267,7 +1243,34 @@
       UNREACHABLE();
   }
 
-  const Register result = locs()->out(0).reg();
+  if (representation() == kUnboxedMint) {
+    ASSERT(locs()->out(0).IsPairLocation());
+    PairLocation* result_pair = locs()->out(0).AsPairLocation();
+    Register result1 = result_pair->At(0).reg();
+    Register result2 = result_pair->At(1).reg();
+    switch (class_id()) {
+      case kTypedDataInt32ArrayCid:
+        // Load low word.
+        __ ldr(result1, element_address);
+        // Sign extend into high word.
+        __ SignFill(result2, result1);
+      break;
+      case kTypedDataUint32ArrayCid:
+        // Load low word.
+        __ ldr(result1, element_address);
+        // Zero high word.
+        __ eor(result2, result2, ShifterOperand(result2));
+      break;
+      default:
+        UNREACHABLE();
+      break;
+    }
+    return;
+  }
+
+  ASSERT(representation() == kTagged);
+
+  Register result = locs()->out(0).reg();
   switch (class_id()) {
     case kTypedDataInt8ArrayCid:
       ASSERT(index_scale() == 1);
@@ -1384,11 +1387,16 @@
       break;
     case kTypedDataInt32ArrayCid:
     case kTypedDataUint32ArrayCid:
-      // Mints are stored in Q registers. For smis, use a writable register
-      // because the value must be untagged before storing.
-      locs->set_in(2, value()->IsSmiValue()
-                      ? Location::WritableRegister()
-                      : Location::FpuRegisterLocation(Q7));
+      // For smis, use a writable register because the value must be untagged
+      // before storing. Mints are stored in register pairs.
+      if (value()->IsSmiValue()) {
+        locs->set_in(2, Location::WritableRegister());
+      } else {
+        // We only move the lower 32-bits so we don't care where the high bits
+        // are located.
+        locs->set_in(2, Location::Pair(Location::RequiresRegister(),
+                                       Location::Any()));
+      }
       break;
     case kTypedDataFloat32ArrayCid:
       // Need low register (<= Q7).
@@ -1573,10 +1581,9 @@
         __ str(value, element_address);
       } else {
         ASSERT(RequiredInputRepresentation(2) == kUnboxedMint);
-        const QRegister value = locs()->in(2).fpu_reg();
-        ASSERT(value == Q7);
-        __ vmovrs(TMP, EvenSRegisterOf(EvenDRegisterOf(value)));
-        __ str(TMP, element_address);
+        PairLocation* value_pair = locs()->in(2).AsPairLocation();
+        Register value1 = value_pair->At(0).reg();
+        __ str(value1, element_address);
       }
       break;
     }
@@ -5726,20 +5733,19 @@
 
 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler,
                                            Label* overflow,
-                                           QRegister result,
-                                           Register tmp_hi, Register tmp_lo) {
-  __ vmovrrd(tmp_lo, tmp_hi, EvenDRegisterOf(result));
+                                           Register result_lo,
+                                           Register result_hi) {
   // Compare upper half.
   Label check_lower;
-  __ CompareImmediate(tmp_hi, 0x00200000);
+  __ CompareImmediate(result_hi, 0x00200000);
   __ b(overflow, GT);
   __ b(&check_lower, NE);
 
-  __ CompareImmediate(tmp_lo, 0);
+  __ CompareImmediate(result_lo, 0);
   __ b(overflow, HI);
 
   __ Bind(&check_lower);
-  __ CompareImmediate(tmp_hi, -0x00200000);
+  __ CompareImmediate(result_hi, -0x00200000);
   __ b(overflow, LT);
   // Anything in the lower part would make the number bigger than the lower
   // bound, so we are done.
@@ -5748,19 +5754,13 @@
 
 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
-  const intptr_t value_cid = value()->Type()->ToCid();
-  const bool needs_writable_input = (value_cid != kMintCid);
-  const bool needs_temp = (value_cid != kMintCid);
-  const intptr_t kNumTemps = needs_temp ? 1 : 0;
+  const intptr_t kNumTemps = 1;
   LocationSummary* summary =
       new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  summary->set_in(0, needs_writable_input
-                     ? Location::WritableRegister()
-                     : Location::RequiresRegister());
-  if (needs_temp) {
-    summary->set_temp(0, Location::RequiresRegister());
-  }
-  summary->set_out(0, Location::RequiresFpuRegister());
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_temp(0, Location::RequiresRegister());
+  summary->set_out(0,  Location::Pair(Location::RequiresRegister(),
+                                      Location::RequiresRegister()));
   return summary;
 }
 
@@ -5768,19 +5768,30 @@
 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   const intptr_t value_cid = value()->Type()->ToCid();
   const Register value = locs()->in(0).reg();
-  const QRegister result = locs()->out(0).fpu_reg();
+  PairLocation* result_pair = locs()->out(0).AsPairLocation();
+  Register result_lo = result_pair->At(0).reg();
+  Register result_hi = result_pair->At(1).reg();
+  ASSERT(value != result_lo);
+  ASSERT(value != result_hi);
 
   __ Comment("UnboxIntegerInstr");
-  __ veorq(result, result, result);
   if (value_cid == kMintCid) {
-    __ LoadDFromOffset(EvenDRegisterOf(result), value,
-                       Mint::value_offset() - kHeapObjectTag);
+    // Load low word.
+    __ LoadFromOffset(kWord,
+                      result_lo,
+                      value,
+                      Mint::value_offset() - kHeapObjectTag);
+    // Load high word.
+    __ LoadFromOffset(kWord,
+                      result_hi,
+                      value,
+                      Mint::value_offset() - kHeapObjectTag + kWordSize);
   } else if (value_cid == kSmiCid) {
-    const Register temp = locs()->temp(0).reg();
-    __ SmiUntag(value);
-    // Sign extend value into temp.
-    __ Asr(temp, value, 31);
-    __ vmovdrr(EvenDRegisterOf(result), value, temp);
+    // Load Smi into result_lo.
+    __ mov(result_lo, ShifterOperand(value));
+    // Untag.
+    __ SmiUntag(result_lo);
+    __ SignFill(result_hi, result_lo);
   } else {
     const Register temp = locs()->temp(0).reg();
     Label* deopt = compiler->AddDeoptStub(deopt_id_,
@@ -5792,16 +5803,26 @@
     __ b(deopt, NE);
 
     // It's a Mint.
-    __ LoadDFromOffset(EvenDRegisterOf(result), value,
-                       Mint::value_offset() - kHeapObjectTag);
+    // Load low word.
+    __ LoadFromOffset(kWord,
+                      result_lo,
+                      value,
+                      Mint::value_offset() - kHeapObjectTag);
+    // Load high word.
+    __ LoadFromOffset(kWord,
+                      result_hi,
+                      value,
+                      Mint::value_offset() - kHeapObjectTag + kWordSize);
     __ b(&done);
 
     // It's a Smi.
     __ Bind(&is_smi);
-    __ SmiUntag(value);
-    // Sign extend into temp.
-    __ Asr(temp, value, 31);
-    __ vmovdrr(EvenDRegisterOf(result), value, temp);
+    // Load Smi into result_lo.
+    __ mov(result_lo, ShifterOperand(value));
+    // Untag.
+    __ SmiUntag(result_lo);
+    // Sign extend result_lo into result_hi.
+    __ SignFill(result_hi, result_lo);
     __ Bind(&done);
   }
 }
@@ -5809,14 +5830,14 @@
 
 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 2;
+  const intptr_t kNumTemps = 1;
   LocationSummary* summary =
       new LocationSummary(kNumInputs,
                           kNumTemps,
                           LocationSummary::kCallOnSlowPath);
-  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                    Location::RequiresRegister()));
   summary->set_temp(0, Location::RequiresRegister());
-  summary->set_temp(1, Location::RequiresRegister());
   summary->set_out(0, Location::RequiresRegister());
   return summary;
 }
@@ -5858,40 +5879,39 @@
 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this);
   compiler->AddSlowPathCode(slow_path);
-
-  const Register out_reg = locs()->out(0).reg();
-  const QRegister value = locs()->in(0).fpu_reg();
-  const DRegister dvalue0 = EvenDRegisterOf(value);
-  const Register lo = locs()->temp(0).reg();
-  const Register hi = locs()->temp(1).reg();
+  PairLocation* value_pair = locs()->in(0).AsPairLocation();
+  Register value_lo = value_pair->At(0).reg();
+  Register value_hi = value_pair->At(1).reg();
+  Register tmp = locs()->temp(0).reg();
+  Register out_reg = locs()->out(0).reg();
 
   // Unboxed operations produce smis or mint-sized values.
   // Check if value fits into a smi.
   __ Comment("BoxIntegerInstr");
   Label not_smi, done, maybe_pos_smi, maybe_neg_smi, is_smi;
-  __ vmovrrd(lo, hi, dvalue0);
-  __ CompareImmediate(hi, 0);
+  // Check high word.
+  __ CompareImmediate(value_hi, 0);
   __ b(&maybe_pos_smi, EQ);
 
-  __ CompareImmediate(hi, -1);
+  __ CompareImmediate(value_hi, -1);
   __ b(&maybe_neg_smi, EQ);
   __ b(&not_smi);
 
   __ Bind(&maybe_pos_smi);
-  __ CompareImmediate(lo, kSmiMax);
+  __ CompareImmediate(value_lo, kSmiMax);
   __ b(&is_smi, LS);  // unsigned lower or same.
   __ b(&not_smi);
 
   __ Bind(&maybe_neg_smi);
-  __ CompareImmediate(lo, 0);
+  __ CompareImmediate(value_lo, 0);
   __ b(&not_smi, GE);
-  __ CompareImmediate(lo, kSmiMin);
+  __ CompareImmediate(value_lo, kSmiMin);
   __ b(&not_smi, LT);
 
   // lo is a Smi. Tag it and return.
   __ Bind(&is_smi);
-  __ SmiTag(lo);
-  __ mov(out_reg, ShifterOperand(lo));
+  __ mov(out_reg, ShifterOperand(value_lo));
+  __ SmiTag(out_reg);
   __ b(&done);
 
   // Not a smi. Box it.
@@ -5900,148 +5920,169 @@
       Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()),
       slow_path->entry_label(),
       out_reg,
-      lo);
+      tmp);
   __ Bind(slow_path->exit_label());
-  __ StoreDToOffset(dvalue0, out_reg, Mint::value_offset() - kHeapObjectTag);
+  __ StoreToOffset(kWord,
+                   value_lo,
+                   out_reg,
+                   Mint::value_offset() - kHeapObjectTag);
+  __ StoreToOffset(kWord,
+                   value_hi,
+                   out_reg,
+                   Mint::value_offset() - kHeapObjectTag + kWordSize);
   __ Bind(&done);
 }
 
 
 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps =
-      FLAG_throw_on_javascript_int_overflow ? 2 : 0;
+  const intptr_t kNumTemps = 0;
   LocationSummary* summary =
       new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  summary->set_in(0, Location::RequiresFpuRegister());
-  summary->set_in(1, Location::RequiresFpuRegister());
-  if (FLAG_throw_on_javascript_int_overflow) {
-    summary->set_temp(0, Location::RequiresRegister());
-    summary->set_temp(1, Location::RequiresRegister());
-  }
-  if ((op_kind() == Token::kADD) || (op_kind() == Token::kSUB)) {
-    // Need another temp for checking for overflow.
-    summary->AddTemp(Location::RequiresFpuRegister());
-    summary->AddTemp(Location::FpuRegisterLocation(Q7));
-  }
-  summary->set_out(0, Location::RequiresFpuRegister());
+  summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                    Location::RequiresRegister()));
+  summary->set_in(1, Location::Pair(Location::RequiresRegister(),
+                                    Location::RequiresRegister()));
+  summary->set_out(0, Location::Pair(Location::RequiresRegister(),
+                                     Location::RequiresRegister()));
   return summary;
 }
 
 
 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const QRegister left = locs()->in(0).fpu_reg();
-  const QRegister right = locs()->in(1).fpu_reg();
-  const QRegister out = locs()->out(0).fpu_reg();
+  PairLocation* left_pair = locs()->in(0).AsPairLocation();
+  Register left_lo = left_pair->At(0).reg();
+  Register left_hi = left_pair->At(1).reg();
+  PairLocation* right_pair = locs()->in(1).AsPairLocation();
+  Register right_lo = right_pair->At(0).reg();
+  Register right_hi = right_pair->At(1).reg();
+  PairLocation* out_pair = locs()->out(0).AsPairLocation();
+  Register out_lo = out_pair->At(0).reg();
+  Register out_hi = out_pair->At(1).reg();
 
   Label* deopt = NULL;
   if (FLAG_throw_on_javascript_int_overflow) {
     deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
   }
   switch (op_kind()) {
-    case Token::kBIT_AND: __ vandq(out, left, right); break;
-    case Token::kBIT_OR: __ vorrq(out, left, right); break;
-    case Token::kBIT_XOR: __ veorq(out, left, right); break;
+    case Token::kBIT_AND: {
+      __ and_(out_lo, left_lo, ShifterOperand(right_lo));
+      __ and_(out_hi, left_hi, ShifterOperand(right_hi));
+    }
+    break;
+    case Token::kBIT_OR: {
+      __ orr(out_lo, left_lo, ShifterOperand(right_lo));
+      __ orr(out_hi, left_hi, ShifterOperand(right_hi));
+    }
+    break;
+    case Token::kBIT_XOR: {
+     __ eor(out_lo, left_lo, ShifterOperand(right_lo));
+     __ eor(out_hi, left_hi, ShifterOperand(right_hi));
+    }
+    break;
     case Token::kADD:
     case Token::kSUB: {
-      const intptr_t tmpidx = FLAG_throw_on_javascript_int_overflow ? 2 : 0;
-      const QRegister tmp = locs()->temp(tmpidx).fpu_reg();
-      const QRegister ro = locs()->temp(tmpidx + 1).fpu_reg();
-      ASSERT(ro == Q7);
       if (!FLAG_throw_on_javascript_int_overflow) {
         deopt  = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
       }
       if (op_kind() == Token::kADD) {
-        __ vaddqi(kWordPair, out, left, right);
+        __ adds(out_lo, left_lo, ShifterOperand(right_lo));
+        __ adcs(out_hi, left_hi, ShifterOperand(right_hi));
       } else {
         ASSERT(op_kind() == Token::kSUB);
-        __ vsubqi(kWordPair, out, left, right);
+        __ subs(out_lo, left_lo, ShifterOperand(right_lo));
+        __ sbcs(out_hi, left_hi, ShifterOperand(right_hi));
       }
-      __ veorq(ro, out, left);
-      __ veorq(tmp, left, right);
-      __ vandq(ro, tmp, ro);
-      __ vmovrs(TMP, OddSRegisterOf(EvenDRegisterOf(ro)));
-      // If TMP < 0, there was overflow.
-      __ cmp(TMP, ShifterOperand(0));
-      __ b(deopt, LT);
+      // Deopt on overflow.
+      __ b(deopt, VS);
       break;
     }
-    default: UNREACHABLE(); break;
+    default:
+      UNREACHABLE();
+    break;
   }
   if (FLAG_throw_on_javascript_int_overflow) {
-    const Register tmp1 = locs()->temp(0).reg();
-    const Register tmp2 = locs()->temp(1).reg();
-    EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
+    EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi);
   }
 }
 
 
 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps =
-      FLAG_throw_on_javascript_int_overflow ? 2 : 1;
+  const intptr_t kNumTemps = 1;
   LocationSummary* summary =
       new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                    Location::RequiresRegister()));
   summary->set_in(1, Location::WritableRegister());
-  summary->set_temp(0, Location::FpuRegisterLocation(Q7));
-  if (FLAG_throw_on_javascript_int_overflow) {
-    summary->set_temp(1, Location::RequiresRegister());
-  }
-  summary->set_out(0, Location::RequiresFpuRegister());
+  summary->set_temp(0, Location::RequiresRegister());
+  summary->set_out(0, Location::Pair(Location::RequiresRegister(),
+                                     Location::RequiresRegister()));
   return summary;
 }
 
 
 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const QRegister value = locs()->in(0).fpu_reg();
-  const Register shift = locs()->in(1).reg();
-  const QRegister temp = locs()->temp(0).fpu_reg();
-  ASSERT(temp == Q7);
-  const QRegister out = locs()->out(0).fpu_reg();
-  const DRegister dtemp0 = EvenDRegisterOf(temp);
-  const SRegister stemp0 = EvenSRegisterOf(dtemp0);
-  const SRegister stemp1 = OddSRegisterOf(dtemp0);
+  PairLocation* left_pair = locs()->in(0).AsPairLocation();
+  Register left_lo = left_pair->At(0).reg();
+  Register left_hi = left_pair->At(1).reg();
+  Register shift = locs()->in(1).reg();
+  PairLocation* out_pair = locs()->out(0).AsPairLocation();
+  Register out_lo = out_pair->At(0).reg();
+  Register out_hi = out_pair->At(1).reg();
+  Register temp = locs()->temp(0).reg();
 
   Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp);
   Label done;
 
+  // Early out if shift is 0.
   __ CompareImmediate(shift, 0);
-  __ vmovq(out, value);
+  __ mov(out_lo, ShifterOperand(left_lo));
+  __ mov(out_hi, ShifterOperand(left_hi));
   __ b(&done, EQ);
+
+  // Untag shift count.
   __ SmiUntag(shift);
 
-  // vshlq takes the shift value from low byte. Deopt if shift is
-  // outside of [0, 63].
-  __ CompareImmediate(shift, 63);
-  __ b(deopt, GT);
-  __ CompareImmediate(shift, 0);
+  // Deopt if shift is negative.
+  __ CompareImmediate(shift, 1);
   __ b(deopt, LT);
 
-  __ veorq(temp, temp, temp);  // Zero out temp.
+  // Deopt if shift is larger than 63.
+  __ CompareImmediate(shift, 63);
+  __ b(deopt, GT);
+
   switch (op_kind()) {
     case Token::kSHR: {
-      __ rsb(shift, shift, ShifterOperand(0));  // Negate shift.
-      __ vmovsr(stemp0, shift);  // Move the shift into the low S register.
-      __ vshlqi(kWordPair, out, value, temp);
+      __ cmp(shift, ShifterOperand(32));
+
+      __ mov(out_lo, ShifterOperand(out_hi), HI);
+      __ Asr(out_hi, out_hi, 31, HI);
+      __ sub(shift, shift, ShifterOperand(32), HI);
+
+      __ rsb(temp, shift, ShifterOperand(32));
+      __ mov(temp, ShifterOperand(out_hi, LSL, temp));
+      __ orr(out_lo, temp, ShifterOperand(out_lo, LSR, shift));
+      __ Asr(out_hi, out_hi, shift);
       break;
     }
     case Token::kSHL: {
-      __ vmovsr(stemp0, shift);  // Move the shift into the low S register.
-      __ vshlqu(kWordPair, out, value, temp);
+      __ rsbs(temp, shift, ShifterOperand(32));
+      __ sub(temp, shift, ShifterOperand(32), MI);
+      __ mov(out_hi, ShifterOperand(out_lo, LSL, temp), MI);
+      __ mov(out_hi, ShifterOperand(out_hi, LSL, shift), PL);
+      __ orr(out_hi, out_hi, ShifterOperand(out_lo, LSR, temp), PL);
+      __ mov(out_lo, ShifterOperand(out_lo, LSL, shift));
 
-      // check for overflow by shifting back and comparing.
-      __ rsb(shift, shift, ShifterOperand(0));
-      __ vmovsr(stemp0, shift);
-      __ vshlqi(kWordPair, temp, out, temp);
-      __ vceqqi(kWord, temp, temp, value);
-      // Low 64 bits of temp should be all 1's, otherwise temp != value and
-      // we deopt.
-      __ vmovrs(shift, stemp0);
-      __ CompareImmediate(shift, -1);
-      __ b(deopt, NE);
-      __ vmovrs(shift, stemp1);
-      __ CompareImmediate(shift, -1);
+      // Check for overflow.
+
+      // Copy high word from output.
+      __ mov(temp, ShifterOperand(out_hi));
+      // Shift copy right.
+      __ Asr(temp, temp, shift);
+      // Compare with high word from input.
+      __ cmp(temp, ShifterOperand(left_hi));
+      // Overflow if they aren't equal.
       __ b(deopt, NE);
       break;
     }
@@ -6052,42 +6093,43 @@
 
   __ Bind(&done);
   if (FLAG_throw_on_javascript_int_overflow) {
-    const Register tmp1 = locs()->in(1).reg();
-    const Register tmp2 = locs()->temp(1).reg();
-    EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
+    EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi);
   }
 }
 
 
 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps =
-      FLAG_throw_on_javascript_int_overflow ? 2 : 0;
+  const intptr_t kNumTemps = 0;
   LocationSummary* summary =
       new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  summary->set_in(0, Location::RequiresFpuRegister());
-  summary->set_out(0, Location::RequiresFpuRegister());
-  if (FLAG_throw_on_javascript_int_overflow) {
-    summary->set_temp(0, Location::RequiresRegister());
-    summary->set_temp(1, Location::RequiresRegister());
-  }
+  summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                    Location::RequiresRegister()));
+  summary->set_out(0, Location::Pair(Location::RequiresRegister(),
+                                     Location::RequiresRegister()));
   return summary;
 }
 
 
 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   ASSERT(op_kind() == Token::kBIT_NOT);
-  const QRegister value = locs()->in(0).fpu_reg();
-  const QRegister out = locs()->out(0).fpu_reg();
+  PairLocation* left_pair = locs()->in(0).AsPairLocation();
+  Register left_lo = left_pair->At(0).reg();
+  Register left_hi = left_pair->At(1).reg();
+
+  PairLocation* out_pair = locs()->out(0).AsPairLocation();
+  Register out_lo = out_pair->At(0).reg();
+  Register out_hi = out_pair->At(1).reg();
+
   Label* deopt = NULL;
+
   if (FLAG_throw_on_javascript_int_overflow) {
     deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp);
   }
-  __ vmvnq(out, value);
+  __ mvn(out_lo, ShifterOperand(left_lo));
+  __ mvn(out_hi, ShifterOperand(left_hi));
   if (FLAG_throw_on_javascript_int_overflow) {
-    const Register tmp1 = locs()->temp(0).reg();
-    const Register tmp2 = locs()->temp(1).reg();
-    EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
+    EmitJavascriptIntOverflowCheck(compiler, deopt, out_lo, out_hi);
   }
 }
 
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index a8f9823..7e082dd 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -253,12 +253,13 @@
 LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
   if (operation_cid() == kMintCid) {
-    const intptr_t kNumTemps = 1;
+    const intptr_t kNumTemps = 0;
     LocationSummary* locs =
         new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
-    locs->set_in(0, Location::RequiresFpuRegister());
-    locs->set_in(1, Location::RequiresFpuRegister());
-    locs->set_temp(0, Location::RequiresRegister());
+    locs->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                   Location::RequiresRegister()));
+    locs->set_in(1, Location::Pair(Location::RequiresRegister(),
+                                   Location::RequiresRegister()));
     locs->set_out(0, Location::RequiresRegister());
     return locs;
   }
@@ -392,22 +393,19 @@
 
 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler,
                                            Label* overflow,
-                                           XmmRegister result,
-                                           Register tmp) {
+                                           Register result_lo,
+                                           Register result_hi) {
   // Compare upper half.
   Label check_lower;
-  __ pextrd(tmp, result, Immediate(1));
-  __ cmpl(tmp, Immediate(0x00200000));
+  __ cmpl(result_hi, Immediate(0x00200000));
   __ j(GREATER, overflow);
   __ j(NOT_EQUAL, &check_lower);
 
-  __ pextrd(tmp, result, Immediate(0));
-  __ cmpl(tmp, Immediate(0));
+  __ cmpl(result_lo, Immediate(0));
   __ j(ABOVE, overflow);
 
   __ Bind(&check_lower);
-  __ pextrd(tmp, result, Immediate(1));
-  __ cmpl(tmp, Immediate(-0x00200000));
+  __ cmpl(result_hi, Immediate(-0x00200000));
   __ j(LESS, overflow);
   // Anything in the lower part would make the number bigger than the lower
   // bound, so we are done.
@@ -434,15 +432,20 @@
                                            Token::Kind kind,
                                            BranchLabels labels) {
   ASSERT(Token::IsEqualityOperator(kind));
-  XmmRegister left = locs.in(0).fpu_reg();
-  XmmRegister right = locs.in(1).fpu_reg();
-  Register temp = locs.temp(0).reg();
-  __ movaps(XMM0, left);
-  __ pcmpeqq(XMM0, right);
-  __ movd(temp, XMM0);
-
+  PairLocation* left_pair = locs.in(0).AsPairLocation();
+  Register left1 = left_pair->At(0).reg();
+  Register left2 = left_pair->At(1).reg();
+  PairLocation* right_pair = locs.in(1).AsPairLocation();
+  Register right1 = right_pair->At(0).reg();
+  Register right2 = right_pair->At(1).reg();
+  Label done;
+  // Compare lower.
+  __ cmpl(left1, right1);
+  __ j(NOT_EQUAL, &done);
+  // Lower is equal, compare upper.
+  __ cmpl(left2, right2);
+  __ Bind(&done);
   Condition true_condition = TokenKindToMintCondition(kind);
-  __ cmpl(temp, Immediate(-1));
   return true_condition;
 }
 
@@ -451,10 +454,12 @@
                                              const LocationSummary& locs,
                                              Token::Kind kind,
                                              BranchLabels labels) {
-  XmmRegister left = locs.in(0).fpu_reg();
-  XmmRegister right = locs.in(1).fpu_reg();
-  Register left_tmp = locs.temp(0).reg();
-  Register right_tmp = locs.temp(1).reg();
+  PairLocation* left_pair = locs.in(0).AsPairLocation();
+  Register left1 = left_pair->At(0).reg();
+  Register left2 = left_pair->At(1).reg();
+  PairLocation* right_pair = locs.in(1).AsPairLocation();
+  Register right1 = right_pair->At(0).reg();
+  Register right2 = right_pair->At(1).reg();
 
   Condition hi_cond = OVERFLOW, lo_cond = OVERFLOW;
   switch (kind) {
@@ -480,16 +485,12 @@
   ASSERT(hi_cond != OVERFLOW && lo_cond != OVERFLOW);
   Label is_true, is_false;
   // Compare upper halves first.
-  __ pextrd(left_tmp, left, Immediate(1));
-  __ pextrd(right_tmp, right, Immediate(1));
-  __ cmpl(left_tmp, right_tmp);
+  __ cmpl(left2, right2);
   __ j(hi_cond, labels.true_label);
   __ j(FlipCondition(hi_cond), labels.false_label);
 
   // If upper is equal, compare lower half.
-  __ pextrd(left_tmp, left, Immediate(0));
-  __ pextrd(right_tmp, right, Immediate(0));
-  __ cmpl(left_tmp, right_tmp);
+  __ cmpl(left1, right1);
   return lo_cond;
 }
 
@@ -688,13 +689,13 @@
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
   if (operation_cid() == kMintCid) {
-    const intptr_t kNumTemps = 2;
+    const intptr_t kNumTemps = 0;
     LocationSummary* locs =
         new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
-    locs->set_in(0, Location::RequiresFpuRegister());
-    locs->set_in(1, Location::RequiresFpuRegister());
-    locs->set_temp(0, Location::RequiresRegister());
-    locs->set_temp(1, Location::RequiresRegister());
+    locs->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                   Location::RequiresRegister()));
+    locs->set_in(1, Location::Pair(Location::RequiresRegister(),
+                                   Location::RequiresRegister()));
     locs->set_out(0, Location::RequiresRegister());
     return locs;
   }
@@ -1020,7 +1021,17 @@
       (representation() == kUnboxedInt32x4) ||
       (representation() == kUnboxedFloat64x2)) {
     locs->set_out(0, Location::RequiresFpuRegister());
+  } else if (representation() == kUnboxedMint) {
+    if (class_id() == kTypedDataInt32ArrayCid) {
+      locs->set_out(0, Location::Pair(Location::RegisterLocation(EAX),
+                                      Location::RegisterLocation(EDX)));
+    } else {
+      ASSERT(class_id() == kTypedDataUint32ArrayCid);
+      locs->set_out(0, Location::Pair(Location::RequiresRegister(),
+                                      Location::RequiresRegister()));
+    }
   } else {
+    ASSERT(representation() == kTagged);
     locs->set_out(0, Location::RequiresRegister());
   }
   return locs;
@@ -1049,7 +1060,6 @@
   }
 
   if ((representation() == kUnboxedDouble) ||
-      (representation() == kUnboxedMint) ||
       (representation() == kUnboxedFloat32x4) ||
       (representation() == kUnboxedInt32x4) ||
       (representation() == kUnboxedFloat64x2)) {
@@ -1058,14 +1068,6 @@
       __ SmiUntag(index.reg());
     }
     switch (class_id()) {
-      case kTypedDataInt32ArrayCid:
-        __ movss(result, element_address);
-        __ pmovsxdq(result, result);
-        break;
-      case kTypedDataUint32ArrayCid:
-        __ xorpd(result, result);
-        __ movss(result, element_address);
-        break;
       case kTypedDataFloat32ArrayCid:
         __ movss(result, element_address);
         break;
@@ -1077,10 +1079,39 @@
       case kTypedDataFloat64x2ArrayCid:
         __ movups(result, element_address);
         break;
+      default:
+        UNREACHABLE();
     }
     return;
   }
 
+  if (representation() == kUnboxedMint) {
+    ASSERT(locs()->out(0).IsPairLocation());
+    PairLocation* result_pair = locs()->out(0).AsPairLocation();
+    Register result1 = result_pair->At(0).reg();
+    Register result2 = result_pair->At(1).reg();
+    if ((index_scale() == 1) && index.IsRegister()) {
+      __ SmiUntag(index.reg());
+    }
+    switch (class_id()) {
+      case kTypedDataInt32ArrayCid:
+        ASSERT(result1 == EAX);
+        ASSERT(result2 == EDX);
+        __ movl(result1, element_address);
+        __ cdq();
+        break;
+      case kTypedDataUint32ArrayCid:
+        __ movl(result1, element_address);
+        __ xorl(result2, result2);
+        break;
+      default:
+        UNREACHABLE();
+    }
+    return;
+  }
+
+  ASSERT(representation() == kTagged);
+
   Register result = locs()->out(0).reg();
   if ((index_scale() == 1) && index.IsRegister()) {
     __ SmiUntag(index.reg());
@@ -1212,11 +1243,16 @@
       break;
     case kTypedDataInt32ArrayCid:
     case kTypedDataUint32ArrayCid:
-      // Mints are stored in XMM registers. For smis, use a writable register
-      // because the value must be untagged before storing.
-      locs->set_in(2, value()->IsSmiValue()
-                      ? Location::WritableRegister()
-                      : Location::RequiresFpuRegister());
+      // For smis, use a writable register because the value must be untagged
+      // before storing. Mints are stored in registers pairs.
+      if (value()->IsSmiValue()) {
+        locs->set_in(2, Location::WritableRegister());
+      } else {
+        // We only move the lower 32-bits so we don't care where the high bits
+        // are located.
+        locs->set_in(2, Location::Pair(Location::RequiresRegister(),
+                                       Location::Any()));
+      }
       break;
     case kTypedDataFloat32ArrayCid:
     case kTypedDataFloat64ArrayCid:
@@ -1333,7 +1369,9 @@
         __ movl(element_address, value);
       } else {
         ASSERT(RequiredInputRepresentation(2) == kUnboxedMint);
-      __ movss(element_address, locs()->in(2).fpu_reg());
+        PairLocation* value_pair = locs()->in(2).AsPairLocation();
+        Register value1 = value_pair->At(0).reg();
+        __ movl(element_address, value1);
       }
       break;
     case kTypedDataFloat32ArrayCid:
@@ -5536,19 +5574,12 @@
 
 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
-  const intptr_t value_cid = value()->Type()->ToCid();
-  const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kMintCid));
-  const bool needs_writable_input = (value_cid == kSmiCid);
-  const intptr_t kNumTemps = needs_temp ? 1 : 0;
+  const intptr_t kNumTemps = 0;
   LocationSummary* summary =
       new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  summary->set_in(0, needs_writable_input
-                     ? Location::WritableRegister()
-                     : Location::RequiresRegister());
-  if (needs_temp) {
-    summary->set_temp(0, Location::RequiresRegister());
-  }
-  summary->set_out(0, Location::RequiresFpuRegister());
+  summary->set_in(0, Location::RequiresRegister());
+  summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX),
+                                     Location::RegisterLocation(EDX)));
   return summary;
 }
 
@@ -5556,30 +5587,39 @@
 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   const intptr_t value_cid = value()->Type()->ToCid();
   const Register value = locs()->in(0).reg();
-  const XmmRegister result = locs()->out(0).fpu_reg();
+  PairLocation* result_pair = locs()->out(0).AsPairLocation();
+  Register result_lo = result_pair->At(0).reg();
+  Register result_hi = result_pair->At(1).reg();
+
+  ASSERT(value != result_lo);
+  ASSERT(value != result_hi);
+  ASSERT(result_lo == EAX);
+  ASSERT(result_hi == EDX);
 
   if (value_cid == kMintCid) {
-    __ movsd(result, FieldAddress(value, Mint::value_offset()));
+    __ movl(result_lo, FieldAddress(value, Mint::value_offset()));
+    __ movl(result_hi, FieldAddress(value, Mint::value_offset() + kWordSize));
   } else if (value_cid == kSmiCid) {
-    __ SmiUntag(value);  // Untag input before conversion.
-    __ movd(result, value);
-    __ pmovsxdq(result, result);
+    __ movl(result_lo, value);
+    __ SmiUntag(result_lo);
+    // Sign extend into result_hi.
+    __ cdq();
   } else {
-    Register temp = locs()->temp(0).reg();
     Label* deopt = compiler->AddDeoptStub(deopt_id_,
                                           ICData::kDeoptUnboxInteger);
     Label is_smi, done;
     __ testl(value, Immediate(kSmiTagMask));
     __ j(ZERO, &is_smi);
-    __ CompareClassId(value, kMintCid, temp);
+    __ CompareClassId(value, kMintCid, result_lo);
     __ j(NOT_EQUAL, deopt);
-    __ movsd(result, FieldAddress(value, Mint::value_offset()));
+    __ movl(result_lo, FieldAddress(value, Mint::value_offset()));
+    __ movl(result_hi, FieldAddress(value, Mint::value_offset() + kWordSize));
     __ jmp(&done);
     __ Bind(&is_smi);
-    __ movl(temp, value);
-    __ SmiUntag(temp);
-    __ movd(result, temp);
-    __ pmovsxdq(result, result);
+    __ movl(result_lo, value);
+    __ SmiUntag(result_lo);
+    // Sign extend into result_hi.
+    __ cdq();
     __ Bind(&done);
   }
 }
@@ -5587,15 +5627,14 @@
 
 LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 2;
+  const intptr_t kNumTemps = 1;
   LocationSummary* summary =
       new LocationSummary(kNumInputs,
                           kNumTemps,
                           LocationSummary::kCallOnSlowPath);
-  summary->set_in(0, Location::RequiresFpuRegister());
-  summary->set_temp(0, Location::RegisterLocation(EAX));
-  summary->set_temp(1, Location::RegisterLocation(EDX));
-  // TODO(fschneider): Save one temp by using result register as a temp.
+  summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                    Location::RequiresRegister()));
+  summary->set_temp(0, Location::RequiresRegister());
   summary->set_out(0, Location::RequiresRegister());
   return summary;
 }
@@ -5637,30 +5676,32 @@
 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this);
   compiler->AddSlowPathCode(slow_path);
-
+  PairLocation* value_pair = locs()->in(0).AsPairLocation();
+  Register value_lo = value_pair->At(0).reg();
+  Register value_hi = value_pair->At(1).reg();
   Register out_reg = locs()->out(0).reg();
-  XmmRegister value = locs()->in(0).fpu_reg();
+
+  // Copy value_hi into out_reg as a temporary.
+  // We modify value_lo but restore it before using it.
+  __ movl(out_reg, value_hi);
 
   // Unboxed operations produce smis or mint-sized values.
   // Check if value fits into a smi.
   Label not_smi, done;
-  __ pextrd(EDX, value, Immediate(1));  // Upper half.
-  __ pextrd(EAX, value, Immediate(0));  // Lower half.
+
   // 1. Compute (x + -kMinSmi) which has to be in the range
   //    0 .. -kMinSmi+kMaxSmi for x to fit into a smi.
-  __ addl(EAX, Immediate(0x40000000));
-  __ adcl(EDX, Immediate(0));
+  __ addl(value_lo, Immediate(0x40000000));
+  __ adcl(out_reg, Immediate(0));
   // 2. Unsigned compare to -kMinSmi+kMaxSmi.
-  __ cmpl(EAX, Immediate(0x80000000));
-  __ sbbl(EDX, Immediate(0));
+  __ cmpl(value_lo, Immediate(0x80000000));
+  __ sbbl(out_reg, Immediate(0));
   __ j(ABOVE_EQUAL, &not_smi);
   // 3. Restore lower half if result is a smi.
-  __ subl(EAX, Immediate(0x40000000));
-
-  __ SmiTag(EAX);
-  __ movl(out_reg, EAX);
+  __ subl(value_lo, Immediate(0x40000000));
+  __ movl(out_reg, value_lo);
+  __ SmiTag(out_reg);
   __ jmp(&done);
-
   __ Bind(&not_smi);
   __ TryAllocate(
       Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()),
@@ -5669,7 +5710,10 @@
       out_reg,
       kNoRegister);
   __ Bind(slow_path->exit_label());
-  __ movsd(FieldAddress(out_reg, Mint::value_offset()), value);
+  // 3. Restore lower half of input before using it.
+  __ subl(value_lo, Immediate(0x40000000));
+  __ movl(FieldAddress(out_reg, Mint::value_offset()), value_lo);
+  __ movl(FieldAddress(out_reg, Mint::value_offset() + kWordSize), value_hi);
   __ Bind(&done);
 }
 
@@ -5680,27 +5724,25 @@
     case Token::kBIT_AND:
     case Token::kBIT_OR:
     case Token::kBIT_XOR: {
-      const intptr_t kNumTemps =
-          FLAG_throw_on_javascript_int_overflow ? 1 : 0;
+      const intptr_t kNumTemps = 0;
       LocationSummary* summary =
           new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
-      summary->set_in(0, Location::RequiresFpuRegister());
-      summary->set_in(1, Location::RequiresFpuRegister());
-      if (FLAG_throw_on_javascript_int_overflow) {
-        summary->set_temp(0, Location::RequiresRegister());
-      }
+      summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                        Location::RequiresRegister()));
+      summary->set_in(1, Location::Pair(Location::RequiresRegister(),
+                                        Location::RequiresRegister()));
       summary->set_out(0, Location::SameAsFirstInput());
       return summary;
     }
     case Token::kADD:
     case Token::kSUB: {
-      const intptr_t kNumTemps = 2;
+      const intptr_t kNumTemps = 0;
       LocationSummary* summary =
           new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
-      summary->set_in(0, Location::RequiresFpuRegister());
-      summary->set_in(1, Location::RequiresFpuRegister());
-      summary->set_temp(0, Location::RequiresRegister());
-      summary->set_temp(1, Location::RequiresRegister());
+      summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                        Location::RequiresRegister()));
+      summary->set_in(1, Location::Pair(Location::RequiresRegister(),
+                                        Location::RequiresRegister()));
       summary->set_out(0, Location::SameAsFirstInput());
       return summary;
     }
@@ -5712,67 +5754,68 @@
 
 
 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  XmmRegister left = locs()->in(0).fpu_reg();
-  XmmRegister right = locs()->in(1).fpu_reg();
-
-  ASSERT(locs()->out(0).fpu_reg() == left);
+  PairLocation* left_pair = locs()->in(0).AsPairLocation();
+  Register left_lo = left_pair->At(0).reg();
+  Register left_hi = left_pair->At(1).reg();
+  PairLocation* right_pair = locs()->in(1).AsPairLocation();
+  Register right_lo = right_pair->At(0).reg();
+  Register right_hi = right_pair->At(1).reg();
+  PairLocation* out_pair = locs()->out(0).AsPairLocation();
+  Register out_lo = out_pair->At(0).reg();
+  Register out_hi = out_pair->At(1).reg();
+  ASSERT(out_lo == left_lo);
+  ASSERT(out_hi == left_hi);
 
   Label* deopt = NULL;
   if (FLAG_throw_on_javascript_int_overflow) {
     deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
   }
   switch (op_kind()) {
-    case Token::kBIT_AND: __ andpd(left, right); break;
-    case Token::kBIT_OR:  __ orpd(left, right); break;
-    case Token::kBIT_XOR: __ xorpd(left, right); break;
+    case Token::kBIT_AND:
+      __ andl(left_lo, right_lo);
+      __ andl(left_hi, right_hi);
+      break;
+    case Token::kBIT_OR:
+      __ orl(left_lo, right_lo);
+      __ orl(left_hi, right_hi);
+      break;
+    case Token::kBIT_XOR:
+      __ xorl(left_lo, right_lo);
+      __ xorl(left_hi, right_hi);
+      break;
     case Token::kADD:
     case Token::kSUB: {
-      Register lo = locs()->temp(0).reg();
-      Register hi = locs()->temp(1).reg();
       if (!FLAG_throw_on_javascript_int_overflow) {
         deopt  = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
       }
-
-      Label done, overflow;
-      __ pextrd(lo, right, Immediate(0));  // Lower half
-      __ pextrd(hi, right, Immediate(1));  // Upper half
-      __ subl(ESP, Immediate(2 * kWordSize));
-      __ movq(Address(ESP, 0), left);
       if (op_kind() == Token::kADD) {
-        __ addl(Address(ESP, 0), lo);
-        __ adcl(Address(ESP, 1 * kWordSize), hi);
+        __ addl(left_lo, right_lo);
+        __ adcl(left_hi, right_hi);
       } else {
-        __ subl(Address(ESP, 0), lo);
-        __ sbbl(Address(ESP, 1 * kWordSize), hi);
+        __ subl(left_lo, right_lo);
+        __ sbbl(left_hi, right_hi);
       }
-      __ j(OVERFLOW, &overflow);
-      __ movq(left, Address(ESP, 0));
-      __ addl(ESP, Immediate(2 * kWordSize));
-      __ jmp(&done);
-      __ Bind(&overflow);
-      __ addl(ESP, Immediate(2 * kWordSize));
-      __ jmp(deopt);
-      __ Bind(&done);
+      __ j(OVERFLOW, deopt);
       break;
     }
     default: UNREACHABLE();
   }
   if (FLAG_throw_on_javascript_int_overflow) {
-    Register tmp = locs()->temp(0).reg();
-    EmitJavascriptIntOverflowCheck(compiler, deopt, left, tmp);
+    EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi);
   }
 }
 
 
 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1;
+  const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 0;
   LocationSummary* summary =
       new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                    Location::RequiresRegister()));
   summary->set_in(1, Location::RegisterLocation(ECX));
-  summary->set_temp(0, Location::RequiresRegister());
   if (op_kind() == Token::kSHL) {
+    summary->set_temp(0, Location::RequiresRegister());
     summary->set_temp(1, Location::RequiresRegister());
   }
   summary->set_out(0, Location::SameAsFirstInput());
@@ -5781,16 +5824,19 @@
 
 
 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  XmmRegister left = locs()->in(0).fpu_reg();
-  ASSERT(locs()->in(1).reg() == ECX);
-  ASSERT(locs()->out(0).fpu_reg() == left);
+  PairLocation* left_pair = locs()->in(0).AsPairLocation();
+  Register left_lo = left_pair->At(0).reg();
+  Register left_hi = left_pair->At(1).reg();
+  PairLocation* out_pair = locs()->out(0).AsPairLocation();
+  Register out_lo = out_pair->At(0).reg();
+  Register out_hi = out_pair->At(1).reg();
+  ASSERT(out_lo == left_lo);
+  ASSERT(out_hi == left_hi);
 
   Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp);
   Label done;
   __ testl(ECX, ECX);
   __ j(ZERO, &done);  // Shift by 0 is a nop.
-  __ subl(ESP, Immediate(2 * kWordSize));
-  __ movq(Address(ESP, 0), left);
   // Deoptimize if shift count is > 31.
   // sarl operation masks the count to 5 bits and
   // shrd is undefined with count > operand size (32)
@@ -5801,23 +5847,21 @@
   __ j(ABOVE, deopt);
   switch (op_kind()) {
     case Token::kSHR: {
-      Register temp = locs()->temp(0).reg();
-      __ movl(temp, Address(ESP, 1 * kWordSize));  // High half.
-      __ shrd(Address(ESP, 0), temp);  // Shift count in CL.
-      __ sarl(Address(ESP, 1 * kWordSize), ECX);  // Shift count in CL.
+      __ shrd(left_lo, left_hi);  // Shift count in CL.
+      __ sarl(left_hi, ECX);  // Shift count in CL.
       break;
     }
     case Token::kSHL: {
       Register temp1 = locs()->temp(0).reg();
       Register temp2 = locs()->temp(1).reg();
-      __ movl(temp1, Address(ESP, 0 * kWordSize));  // Low 32 bits.
-      __ movl(temp2, Address(ESP, 1 * kWordSize));  // High 32 bits.
-      __ shll(Address(ESP, 0 * kWordSize), ECX);  // Shift count in CL.
-      __ shld(Address(ESP, 1 * kWordSize), temp1);  // Shift count in CL.
+      __ movl(temp1, left_lo);  // Low 32 bits.
+      __ movl(temp2, left_hi);  // High 32 bits.
+      __ shll(left_lo, ECX);  // Shift count in CL.
+      __ shld(left_hi, temp1);  // Shift count in CL.
       // Check for overflow by shifting back the high 32 bits
       // and comparing with the input.
       __ movl(temp1, temp2);
-      __ movl(temp2, Address(ESP, 1 * kWordSize));
+      __ movl(temp2, left_hi);
       __ sarl(temp2, ECX);
       __ cmpl(temp1, temp2);
       __ j(NOT_EQUAL, deopt);
@@ -5827,23 +5871,20 @@
       UNREACHABLE();
       break;
   }
-  __ movq(left, Address(ESP, 0));
-  __ addl(ESP, Immediate(2 * kWordSize));
   __ Bind(&done);
   if (FLAG_throw_on_javascript_int_overflow) {
-    Register tmp = locs()->temp(0).reg();
-    EmitJavascriptIntOverflowCheck(compiler, deopt, left, tmp);
+    EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi);
   }
 }
 
 
 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const {
   const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps =
-      FLAG_throw_on_javascript_int_overflow ? 1 : 0;
+  const intptr_t kNumTemps = 0;
   LocationSummary* summary =
       new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+                                    Location::RequiresRegister()));
   summary->set_out(0, Location::SameAsFirstInput());
   if (FLAG_throw_on_javascript_int_overflow) {
     summary->set_temp(0, Location::RequiresRegister());
@@ -5854,17 +5895,25 @@
 
 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   ASSERT(op_kind() == Token::kBIT_NOT);
-  XmmRegister value = locs()->in(0).fpu_reg();
-  ASSERT(value == locs()->out(0).fpu_reg());
+  PairLocation* left_pair = locs()->in(0).AsPairLocation();
+  Register left_lo = left_pair->At(0).reg();
+  Register left_hi = left_pair->At(1).reg();
+  PairLocation* out_pair = locs()->out(0).AsPairLocation();
+  Register out_lo = out_pair->At(0).reg();
+  Register out_hi = out_pair->At(1).reg();
+  ASSERT(out_lo == left_lo);
+  ASSERT(out_hi == left_hi);
+
   Label* deopt = NULL;
   if (FLAG_throw_on_javascript_int_overflow) {
     deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp);
   }
-  __ pcmpeqq(XMM0, XMM0);  // Generate all 1's.
-  __ pxor(value, XMM0);
+
+  __ notl(left_lo);
+  __ notl(left_hi);
+
   if (FLAG_throw_on_javascript_int_overflow) {
-    Register tmp = locs()->temp(0).reg();
-    EmitJavascriptIntOverflowCheck(compiler, deopt, value, tmp);
+    EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi);
   }
 }
 
diff --git a/runtime/vm/locations.cc b/runtime/vm/locations.cc
index d9d044a..9809707 100644
--- a/runtime/vm/locations.cc
+++ b/runtime/vm/locations.cc
@@ -210,6 +210,12 @@
     f->Print("DS%+" Pd "", stack_index());
   } else if (kind() == kQuadStackSlot) {
     f->Print("QS%+" Pd "", stack_index());
+  } else if (IsPairLocation()) {
+    f->Print("(");
+    AsPairLocation()->At(0).PrintTo(f);
+    f->Print(", ");
+    AsPairLocation()->At(1).PrintTo(f);
+    f->Print(")");
   } else {
     f->Print("%s", Name());
   }
@@ -233,6 +239,19 @@
 }
 
 
+Location Location::Copy() const {
+  if (IsPairLocation()) {
+    PairLocation* pair = AsPairLocation();
+    ASSERT(!pair->At(0).IsPairLocation());
+    ASSERT(!pair->At(1).IsPairLocation());
+    return Location::Pair(pair->At(0).Copy(), pair->At(1).Copy());
+  } else {
+    // Copy by value.
+    return *this;
+  }
+}
+
+
 void LocationSummary::PrintTo(BufferFormatter* f) const {
   if (input_count() > 0) {
     f->Print(" (");
diff --git a/runtime/vm/locations.h b/runtime/vm/locations.h
index cabb8db..cf6a60b 100644
--- a/runtime/vm/locations.h
+++ b/runtime/vm/locations.h
@@ -331,11 +331,15 @@
   }
 
   intptr_t stack_index() const {
-    ASSERT(IsStackSlot() || IsDoubleStackSlot() || IsQuadStackSlot());
+    ASSERT(HasStackIndex());
     // Decode stack index manually to preserve sign.
     return payload() - kStackIndexBias;
   }
 
+  bool HasStackIndex() const {
+    return IsStackSlot() || IsDoubleStackSlot() || IsQuadStackSlot();
+  }
+
   // Return a memory operand for stack slot locations.
   Address ToStackSlotAddress() const;
 
@@ -365,6 +369,8 @@
     return KindField::decode(value_);
   }
 
+  Location Copy() const;
+
  private:
   explicit Location(uword value) : value_(value) { }
 
@@ -428,15 +434,20 @@
 
 class RegisterSet : public ValueObject {
  public:
-  RegisterSet() : cpu_registers_(0), fpu_registers_(0) {
+  RegisterSet() : cpu_registers_(0), untagged_cpu_registers_(0),
+                  fpu_registers_(0) {
     ASSERT(kNumberOfCpuRegisters <= (kWordSize * kBitsPerByte));
     ASSERT(kNumberOfFpuRegisters <= (kWordSize * kBitsPerByte));
   }
 
 
-  void Add(Location loc) {
+  void Add(Location loc, Representation rep = kTagged) {
     if (loc.IsRegister()) {
       cpu_registers_ |= (1 << loc.reg());
+      if (rep != kTagged) {
+        // CPU register contains an untagged value.
+        MarkUntagged(loc);
+      }
     } else if (loc.IsFpuRegister()) {
       fpu_registers_ |= (1 << loc.fpu_reg());
     }
@@ -450,6 +461,32 @@
     }
   }
 
+  void DebugPrint() {
+    for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
+      Register r = static_cast<Register>(i);
+      if (ContainsRegister(r)) {
+        OS::Print("%s %s\n", Assembler::RegisterName(r),
+                           IsTagged(r) ? "tagged" : "untagged");
+      }
+    }
+
+    for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) {
+      FpuRegister r = static_cast<FpuRegister>(i);
+      if (ContainsFpuRegister(r)) {
+        OS::Print("%s\n", Assembler::FpuRegisterName(r));
+      }
+    }
+  }
+
+  void MarkUntagged(Location loc) {
+    ASSERT(loc.IsRegister());
+    untagged_cpu_registers_ |= (1 << loc.reg());
+  }
+
+  bool IsTagged(Register reg) const {
+    return (untagged_cpu_registers_ & (1 << reg)) == 0;
+  }
+
   bool ContainsRegister(Register reg) const {
     return (cpu_registers_ & (1 << reg)) != 0;
   }
@@ -468,6 +505,7 @@
 
  private:
   intptr_t cpu_registers_;
+  intptr_t untagged_cpu_registers_;
   intptr_t fpu_registers_;
 
   DISALLOW_COPY_AND_ASSIGN(RegisterSet);
@@ -561,6 +599,10 @@
     return contains_call_ != kNoCall;
   }
 
+  bool HasCallOnSlowPath() {
+    return can_call() && !always_calls();
+  }
+
   void PrintTo(BufferFormatter* f) const;
 
   static LocationSummary* Make(intptr_t input_count,