Add assembly operations with constants in optimizing compiler.

Change-Id: I5bcc35ab50d4457186effef5592a75d7f4e5b65f
diff --git a/compiler/Android.mk b/compiler/Android.mk
index 02dad2a..ac2f9d6 100644
--- a/compiler/Android.mk
+++ b/compiler/Android.mk
@@ -95,8 +95,8 @@
 	optimizing/register_allocator.cc \
 	optimizing/ssa_builder.cc \
 	optimizing/ssa_liveness_analysis.cc \
-	optimizing/ssa_type_propagation.cc \
 	optimizing/ssa_phi_elimination.cc \
+	optimizing/ssa_type_propagation.cc \
 	trampolines/trampoline_compiler.cc \
 	utils/arena_allocator.cc \
 	utils/arena_bit_vector.cc \
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 9d17fb1..bc1e75b 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -378,11 +378,17 @@
 }
 
 void CodeGeneratorARM::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
+  LocationSummary* locations = instruction->GetLocations();
+  if (locations != nullptr && locations->Out().Equals(location)) {
+    return;
+  }
+
   if (instruction->AsIntConstant() != nullptr) {
     int32_t value = instruction->AsIntConstant()->GetValue();
     if (location.IsRegister()) {
       __ LoadImmediate(location.AsArm().AsCoreRegister(), value);
     } else {
+      DCHECK(location.IsStackSlot());
       __ LoadImmediate(IP, value);
       __ str(IP, Address(SP, location.GetStackIndex()));
     }
@@ -392,6 +398,7 @@
       __ LoadImmediate(location.AsArm().AsRegisterPairLow(), Low32Bits(value));
       __ LoadImmediate(location.AsArm().AsRegisterPairHigh(), High32Bits(value));
     } else {
+      DCHECK(location.IsDoubleStackSlot());
       __ LoadImmediate(IP, Low32Bits(value));
       __ str(IP, Address(SP, location.GetStackIndex()));
       __ LoadImmediate(IP, High32Bits(value));
@@ -425,11 +432,11 @@
       case Primitive::kPrimShort:
       case Primitive::kPrimNot:
       case Primitive::kPrimInt:
-        Move32(location, instruction->GetLocations()->Out());
+        Move32(location, locations->Out());
         break;
 
       case Primitive::kPrimLong:
-        Move64(location, instruction->GetLocations()->Out());
+        Move64(location, locations->Out());
         break;
 
       default:
@@ -479,20 +486,33 @@
   HCondition* condition = cond->AsCondition();
   if (condition->NeedsMaterialization()) {
     // Condition has been materialized, compare the output to 0
-    if (!if_instr->GetLocations()->InAt(0).IsRegister()) {
-      LOG(FATAL) << "Materialized condition is not in an ARM register";
-    }
+    DCHECK(if_instr->GetLocations()->InAt(0).IsRegister());
     __ cmp(if_instr->GetLocations()->InAt(0).AsArm().AsCoreRegister(),
            ShifterOperand(0));
     __ b(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()), EQ);
   } else {
     // Condition has not been materialized, use its inputs as the comparison and its
     // condition as the branch condition.
-    __ cmp(condition->GetLocations()->InAt(0).AsArm().AsCoreRegister(),
-           ShifterOperand(condition->GetLocations()->InAt(1).AsArm().AsCoreRegister()));
+    LocationSummary* locations = condition->GetLocations();
+    if (locations->InAt(1).IsRegister()) {
+      __ cmp(locations->InAt(0).AsArm().AsCoreRegister(),
+             ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister()));
+    } else {
+      DCHECK(locations->InAt(1).IsConstant());
+      int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
+      ShifterOperand operand;
+      if (ShifterOperand::CanHoldArm(value, &operand)) {
+        __ cmp(locations->InAt(0).AsArm().AsCoreRegister(), ShifterOperand(value));
+      } else {
+        Register temp = IP;
+        __ LoadImmediate(temp, value);
+        __ cmp(locations->InAt(0).AsArm().AsCoreRegister(), ShifterOperand(temp));
+      }
+    }
     __ b(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()),
          ARMCondition(condition->GetCondition()));
   }
+
   if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfFalseSuccessor())) {
     __ b(codegen_->GetLabelOf(if_instr->IfFalseSuccessor()));
   }
@@ -502,7 +522,7 @@
 void LocationsBuilderARM::VisitCondition(HCondition* comp) {
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(comp);
   locations->SetInAt(0, Location::RequiresRegister());
-  locations->SetInAt(1, Location::RequiresRegister());
+  locations->SetInAt(1, Location::RegisterOrConstant(comp->InputAt(1)));
   if (comp->NeedsMaterialization()) {
     locations->SetOut(Location::RequiresRegister());
   }
@@ -510,16 +530,29 @@
 }
 
 void InstructionCodeGeneratorARM::VisitCondition(HCondition* comp) {
-  if (comp->NeedsMaterialization()) {
-    LocationSummary* locations = comp->GetLocations();
+  if (!comp->NeedsMaterialization()) return;
+
+  LocationSummary* locations = comp->GetLocations();
+  if (locations->InAt(1).IsRegister()) {
     __ cmp(locations->InAt(0).AsArm().AsCoreRegister(),
            ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister()));
-    __ it(ARMCondition(comp->GetCondition()), kItElse);
-    __ mov(locations->Out().AsArm().AsCoreRegister(), ShifterOperand(1),
-           ARMCondition(comp->GetCondition()));
-    __ mov(locations->Out().AsArm().AsCoreRegister(), ShifterOperand(0),
-           ARMOppositeCondition(comp->GetCondition()));
+  } else {
+    DCHECK(locations->InAt(1).IsConstant());
+    int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue();
+    ShifterOperand operand;
+    if (ShifterOperand::CanHoldArm(value, &operand)) {
+      __ cmp(locations->InAt(0).AsArm().AsCoreRegister(), ShifterOperand(value));
+    } else {
+      Register temp = IP;
+      __ LoadImmediate(temp, value);
+      __ cmp(locations->InAt(0).AsArm().AsCoreRegister(), ShifterOperand(temp));
+    }
   }
+  __ it(ARMCondition(comp->GetCondition()), kItElse);
+  __ mov(locations->Out().AsArm().AsCoreRegister(), ShifterOperand(1),
+         ARMCondition(comp->GetCondition()));
+  __ mov(locations->Out().AsArm().AsCoreRegister(), ShifterOperand(0),
+         ARMOppositeCondition(comp->GetCondition()));
 }
 
 void LocationsBuilderARM::VisitEqual(HEqual* comp) {
@@ -612,20 +645,17 @@
 }
 
 void LocationsBuilderARM::VisitIntConstant(HIntConstant* constant) {
-  // TODO: Support constant locations.
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
-  locations->SetOut(Location::RequiresRegister());
+  locations->SetOut(Location::ConstantLocation(constant));
   constant->SetLocations(locations);
 }
 
 void InstructionCodeGeneratorARM::VisitIntConstant(HIntConstant* constant) {
-  codegen_->Move(constant, constant->GetLocations()->Out(), nullptr);
 }
 
 void LocationsBuilderARM::VisitLongConstant(HLongConstant* constant) {
-  // TODO: Support constant locations.
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
-  locations->SetOut(Location::RequiresRegister());
+  locations->SetOut(Location::ConstantLocation(constant));
   constant->SetLocations(locations);
 }
 
@@ -762,7 +792,7 @@
     case Primitive::kPrimInt:
     case Primitive::kPrimLong: {
       locations->SetInAt(0, Location::RequiresRegister());
-      locations->SetInAt(1, Location::RequiresRegister());
+      locations->SetInAt(1, Location::RegisterOrConstant(add->InputAt(1)));
       locations->SetOut(Location::RequiresRegister());
       break;
     }
@@ -784,9 +814,15 @@
   LocationSummary* locations = add->GetLocations();
   switch (add->GetResultType()) {
     case Primitive::kPrimInt:
-      __ add(locations->Out().AsArm().AsCoreRegister(),
-             locations->InAt(0).AsArm().AsCoreRegister(),
-             ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister()));
+      if (locations->InAt(1).IsRegister()) {
+        __ add(locations->Out().AsArm().AsCoreRegister(),
+               locations->InAt(0).AsArm().AsCoreRegister(),
+               ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister()));
+      } else {
+        __ AddConstant(locations->Out().AsArm().AsCoreRegister(),
+                       locations->InAt(0).AsArm().AsCoreRegister(),
+                       locations->InAt(1).GetConstant()->AsIntConstant()->GetValue());
+      }
       break;
 
     case Primitive::kPrimLong:
@@ -816,7 +852,7 @@
     case Primitive::kPrimInt:
     case Primitive::kPrimLong: {
       locations->SetInAt(0, Location::RequiresRegister());
-      locations->SetInAt(1, Location::RequiresRegister());
+      locations->SetInAt(1, Location::RegisterOrConstant(sub->InputAt(1)));
       locations->SetOut(Location::RequiresRegister());
       break;
     }
@@ -837,11 +873,18 @@
 void InstructionCodeGeneratorARM::VisitSub(HSub* sub) {
   LocationSummary* locations = sub->GetLocations();
   switch (sub->GetResultType()) {
-    case Primitive::kPrimInt:
-      __ sub(locations->Out().AsArm().AsCoreRegister(),
-             locations->InAt(0).AsArm().AsCoreRegister(),
-             ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister()));
+    case Primitive::kPrimInt: {
+      if (locations->InAt(1).IsRegister()) {
+        __ sub(locations->Out().AsArm().AsCoreRegister(),
+               locations->InAt(0).AsArm().AsCoreRegister(),
+               ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister()));
+      } else {
+        __ AddConstant(locations->Out().AsArm().AsCoreRegister(),
+                       locations->InAt(0).AsArm().AsCoreRegister(),
+                       -locations->InAt(1).GetConstant()->AsIntConstant()->GetValue());
+      }
       break;
+    }
 
     case Primitive::kPrimLong:
       __ subs(locations->Out().AsArm().AsRegisterPairLow(),
@@ -1161,7 +1204,16 @@
       __ StoreToOffset(kStoreWord, IP, SP, destination.GetStackIndex());
     }
   } else {
-    LOG(FATAL) << "Unimplemented";
+    DCHECK(source.IsConstant());
+    DCHECK(source.GetConstant()->AsIntConstant() != nullptr);
+    int32_t value = source.GetConstant()->AsIntConstant()->GetValue();
+    if (destination.IsRegister()) {
+      __ LoadImmediate(destination.AsArm().AsCoreRegister(), value);
+    } else {
+      DCHECK(destination.IsStackSlot());
+      __ LoadImmediate(IP, value);
+      __ str(IP, Address(SP, destination.GetStackIndex()));
+    }
   }
 }
 
diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h
index 3cc16aa..85ab22b 100644
--- a/compiler/optimizing/code_generator_arm.h
+++ b/compiler/optimizing/code_generator_arm.h
@@ -89,7 +89,7 @@
 #define DECLARE_VISIT_INSTRUCTION(name)     \
   virtual void Visit##name(H##name* instr);
 
-  FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
+  FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
 
 #undef DECLARE_VISIT_INSTRUCTION
 
@@ -107,7 +107,7 @@
 #define DECLARE_VISIT_INSTRUCTION(name)     \
   virtual void Visit##name(H##name* instr);
 
-  FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
+  FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
 
 #undef DECLARE_VISIT_INSTRUCTION
 
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 4e69a0c..af267d8 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -473,6 +473,10 @@
     // LHS is guaranteed to be in a register (see LocationsBuilderX86::VisitCondition).
     if (rhs.IsRegister()) {
       __ cmpl(lhs.AsX86().AsCpuRegister(), rhs.AsX86().AsCpuRegister());
+    } else if (rhs.IsConstant()) {
+      HIntConstant* instruction = rhs.GetConstant()->AsIntConstant();
+      Immediate imm(instruction->AsIntConstant()->GetValue());
+      __ cmpl(lhs.AsX86().AsCpuRegister(), imm);
     } else {
       __ cmpl(lhs.AsX86().AsCpuRegister(), Address(ESP, rhs.GetStackIndex()));
     }
@@ -530,7 +534,7 @@
   locations->SetInAt(0, Location::RequiresRegister());
   locations->SetInAt(1, Location::Any());
   if (comp->NeedsMaterialization()) {
-    locations->SetOut(Location::SameAsFirstInput());
+    locations->SetOut(Location::RequiresRegister());
   }
   comp->SetLocations(locations);
 }
@@ -541,6 +545,10 @@
     if (locations->InAt(1).IsRegister()) {
       __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(),
               locations->InAt(1).AsX86().AsCpuRegister());
+    } else if (locations->InAt(1).IsConstant()) {
+      HConstant* instruction = locations->InAt(1).GetConstant();
+      Immediate imm(instruction->AsIntConstant()->GetValue());
+      __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(), imm);
     } else {
       __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(),
               Address(ESP, locations->InAt(1).GetStackIndex()));
@@ -598,20 +606,17 @@
 }
 
 void LocationsBuilderX86::VisitIntConstant(HIntConstant* constant) {
-  // TODO: Support constant locations.
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
-  locations->SetOut(Location::RequiresRegister());
+  locations->SetOut(Location::ConstantLocation(constant));
   constant->SetLocations(locations);
 }
 
 void InstructionCodeGeneratorX86::VisitIntConstant(HIntConstant* constant) {
-  codegen_->Move(constant, constant->GetLocations()->Out(), nullptr);
 }
 
 void LocationsBuilderX86::VisitLongConstant(HLongConstant* constant) {
-  // TODO: Support constant locations.
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
-  locations->SetOut(Location::RequiresRegister());
+  locations->SetOut(Location::ConstantLocation(constant));
   constant->SetLocations(locations);
 }
 
@@ -769,6 +774,10 @@
       if (locations->InAt(1).IsRegister()) {
         __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
                 locations->InAt(1).AsX86().AsCpuRegister());
+      } else if (locations->InAt(1).IsConstant()) {
+        HConstant* instruction = locations->InAt(1).GetConstant();
+        Immediate imm(instruction->AsIntConstant()->GetValue());
+        __ addl(locations->InAt(0).AsX86().AsCpuRegister(), imm);
       } else {
         __ addl(locations->InAt(0).AsX86().AsCpuRegister(),
                 Address(ESP, locations->InAt(1).GetStackIndex()));
@@ -838,6 +847,10 @@
       if (locations->InAt(1).IsRegister()) {
         __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
                 locations->InAt(1).AsX86().AsCpuRegister());
+      } else if (locations->InAt(1).IsConstant()) {
+        HConstant* instruction = locations->InAt(1).GetConstant();
+        Immediate imm(instruction->AsIntConstant()->GetValue());
+        __ subl(locations->InAt(0).AsX86().AsCpuRegister(), imm);
       } else {
         __ subl(locations->InAt(0).AsX86().AsCpuRegister(),
                 Address(ESP, locations->InAt(1).GetStackIndex()));
@@ -1178,6 +1191,14 @@
       MoveMemoryToMemory(destination.GetStackIndex(),
                          source.GetStackIndex());
     }
+  } else if (source.IsConstant()) {
+    HIntConstant* instruction = source.GetConstant()->AsIntConstant();
+    Immediate imm(instruction->AsIntConstant()->GetValue());
+    if (destination.IsRegister()) {
+      __ movl(destination.AsX86().AsCpuRegister(), imm);
+    } else {
+      __ movl(Address(ESP, destination.GetStackIndex()), imm);
+    }
   } else {
     LOG(FATAL) << "Unimplemented";
   }
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index d622d2a..9c12771 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -90,7 +90,7 @@
 #define DECLARE_VISIT_INSTRUCTION(name)     \
   virtual void Visit##name(H##name* instr);
 
-  FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
+  FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
 
 #undef DECLARE_VISIT_INSTRUCTION
 
@@ -108,7 +108,7 @@
 #define DECLARE_VISIT_INSTRUCTION(name)     \
   virtual void Visit##name(H##name* instr);
 
-  FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
+  FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
 
 #undef DECLARE_VISIT_INSTRUCTION
 
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index e3ce5ce..4bda082 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -329,7 +329,14 @@
   } else {
     Location lhs = condition->GetLocations()->InAt(0);
     Location rhs = condition->GetLocations()->InAt(1);
-    __ cmpl(lhs.AsX86_64().AsCpuRegister(), rhs.AsX86_64().AsCpuRegister());
+    if (rhs.IsRegister()) {
+      __ cmpl(lhs.AsX86_64().AsCpuRegister(), rhs.AsX86_64().AsCpuRegister());
+    } else if (rhs.IsConstant()) {
+      __ cmpl(lhs.AsX86_64().AsCpuRegister(),
+              Immediate(rhs.GetConstant()->AsIntConstant()->GetValue()));
+    } else {
+      __ cmpl(lhs.AsX86_64().AsCpuRegister(), Address(CpuRegister(RSP), rhs.GetStackIndex()));
+    }
     __ j(X86_64Condition(condition->GetCondition()),
          codegen_->GetLabelOf(if_instr->IfTrueSuccessor()));
   }
@@ -382,7 +389,7 @@
 void LocationsBuilderX86_64::VisitCondition(HCondition* comp) {
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(comp);
   locations->SetInAt(0, Location::RequiresRegister());
-  locations->SetInAt(1, Location::RequiresRegister());
+  locations->SetInAt(1, Location::Any());
   if (comp->NeedsMaterialization()) {
     locations->SetOut(Location::RequiresRegister());
   }
@@ -391,8 +398,17 @@
 
 void InstructionCodeGeneratorX86_64::VisitCondition(HCondition* comp) {
   if (comp->NeedsMaterialization()) {
-    __ cmpq(comp->GetLocations()->InAt(0).AsX86_64().AsCpuRegister(),
-            comp->GetLocations()->InAt(1).AsX86_64().AsCpuRegister());
+    LocationSummary* locations = comp->GetLocations();
+    if (locations->InAt(1).IsRegister()) {
+      __ cmpq(locations->InAt(0).AsX86_64().AsCpuRegister(),
+              locations->InAt(1).AsX86_64().AsCpuRegister());
+    } else if (locations->InAt(1).IsConstant()) {
+      __ cmpq(locations->InAt(0).AsX86_64().AsCpuRegister(),
+              Immediate(locations->InAt(1).GetConstant()->AsIntConstant()->GetValue()));
+    } else {
+      __ cmpq(locations->InAt(0).AsX86_64().AsCpuRegister(),
+              Address(CpuRegister(RSP), locations->InAt(1).GetStackIndex()));
+    }
     __ setcc(X86_64Condition(comp->GetCondition()),
              comp->GetLocations()->Out().AsX86_64().AsCpuRegister());
   }
@@ -480,25 +496,21 @@
 }
 
 void LocationsBuilderX86_64::VisitIntConstant(HIntConstant* constant) {
-  // TODO: Support constant locations.
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
-  locations->SetOut(Location::RequiresRegister());
+  locations->SetOut(Location::ConstantLocation(constant));
   constant->SetLocations(locations);
 }
 
 void InstructionCodeGeneratorX86_64::VisitIntConstant(HIntConstant* constant) {
-  codegen_->Move(constant, constant->GetLocations()->Out(), nullptr);
 }
 
 void LocationsBuilderX86_64::VisitLongConstant(HLongConstant* constant) {
-  // TODO: Support constant locations.
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant);
-  locations->SetOut(Location::RequiresRegister());
+  locations->SetOut(Location::ConstantLocation(constant));
   constant->SetLocations(locations);
 }
 
 void InstructionCodeGeneratorX86_64::VisitLongConstant(HLongConstant* constant) {
-  codegen_->Move(constant, constant->GetLocations()->Out(), nullptr);
 }
 
 void LocationsBuilderX86_64::VisitReturnVoid(HReturnVoid* ret) {
@@ -666,7 +678,12 @@
 void LocationsBuilderX86_64::VisitAdd(HAdd* add) {
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add);
   switch (add->GetResultType()) {
-    case Primitive::kPrimInt:
+    case Primitive::kPrimInt: {
+      locations->SetInAt(0, Location::RequiresRegister());
+      locations->SetInAt(1, Location::Any());
+      locations->SetOut(Location::SameAsFirstInput());
+      break;
+    }
     case Primitive::kPrimLong: {
       locations->SetInAt(0, Location::RequiresRegister());
       locations->SetInAt(1, Location::RequiresRegister());
@@ -693,8 +710,17 @@
             locations->Out().AsX86_64().AsCpuRegister().AsRegister());
   switch (add->GetResultType()) {
     case Primitive::kPrimInt: {
-      __ addl(locations->InAt(0).AsX86_64().AsCpuRegister(),
-              locations->InAt(1).AsX86_64().AsCpuRegister());
+      if (locations->InAt(1).IsRegister()) {
+        __ addl(locations->InAt(0).AsX86_64().AsCpuRegister(),
+                locations->InAt(1).AsX86_64().AsCpuRegister());
+      } else if (locations->InAt(1).IsConstant()) {
+        HConstant* instruction = locations->InAt(1).GetConstant();
+        Immediate imm(instruction->AsIntConstant()->GetValue());
+        __ addl(locations->InAt(0).AsX86_64().AsCpuRegister(), imm);
+      } else {
+        __ addl(locations->InAt(0).AsX86_64().AsCpuRegister(),
+                Address(CpuRegister(RSP), locations->InAt(1).GetStackIndex()));
+      }
       break;
     }
     case Primitive::kPrimLong: {
@@ -718,7 +744,12 @@
 void LocationsBuilderX86_64::VisitSub(HSub* sub) {
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub);
   switch (sub->GetResultType()) {
-    case Primitive::kPrimInt:
+    case Primitive::kPrimInt: {
+      locations->SetInAt(0, Location::RequiresRegister());
+      locations->SetInAt(1, Location::Any());
+      locations->SetOut(Location::SameAsFirstInput());
+      break;
+    }
     case Primitive::kPrimLong: {
       locations->SetInAt(0, Location::RequiresRegister());
       locations->SetInAt(1, Location::RequiresRegister());
@@ -745,8 +776,17 @@
             locations->Out().AsX86_64().AsCpuRegister().AsRegister());
   switch (sub->GetResultType()) {
     case Primitive::kPrimInt: {
-      __ subl(locations->InAt(0).AsX86_64().AsCpuRegister(),
-              locations->InAt(1).AsX86_64().AsCpuRegister());
+      if (locations->InAt(1).IsRegister()) {
+        __ subl(locations->InAt(0).AsX86_64().AsCpuRegister(),
+                locations->InAt(1).AsX86_64().AsCpuRegister());
+      } else if (locations->InAt(1).IsConstant()) {
+        HConstant* instruction = locations->InAt(1).GetConstant();
+        Immediate imm(instruction->AsIntConstant()->GetValue());
+        __ subl(locations->InAt(0).AsX86_64().AsCpuRegister(), imm);
+      } else {
+        __ subl(locations->InAt(0).AsX86_64().AsCpuRegister(),
+                Address(CpuRegister(RSP), locations->InAt(1).GetStackIndex()));
+      }
       break;
     }
     case Primitive::kPrimLong: {
@@ -1008,6 +1048,26 @@
       __ movq(CpuRegister(TMP), Address(CpuRegister(RSP), source.GetStackIndex()));
       __ movq(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP));
     }
+  } else if (source.IsConstant()) {
+    HConstant* constant = source.GetConstant();
+    if (constant->IsIntConstant()) {
+      Immediate imm(constant->AsIntConstant()->GetValue());
+      if (destination.IsRegister()) {
+        __ movl(destination.AsX86_64().AsCpuRegister(), imm);
+      } else {
+        __ movl(Address(CpuRegister(RSP), destination.GetStackIndex()), imm);
+      }
+    } else if (constant->IsLongConstant()) {
+      int64_t value = constant->AsLongConstant()->GetValue();
+      if (destination.IsRegister()) {
+        __ movq(destination.AsX86_64().AsCpuRegister(), Immediate(value));
+      } else {
+        __ movq(CpuRegister(TMP), Immediate(value));
+        __ movq(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP));
+      }
+    } else {
+      LOG(FATAL) << "Unimplemented constant type";
+    }
   } else {
     LOG(FATAL) << "Unimplemented";
   }
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index 8283dda..a20ca3f 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -87,7 +87,7 @@
 #define DECLARE_VISIT_INSTRUCTION(name)     \
   virtual void Visit##name(H##name* instr);
 
-  FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
+  FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
 
 #undef DECLARE_VISIT_INSTRUCTION
 
@@ -105,7 +105,7 @@
 #define DECLARE_VISIT_INSTRUCTION(name)     \
   virtual void Visit##name(H##name* instr);
 
-  FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
+  FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
 
 #undef DECLARE_VISIT_INSTRUCTION
 
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index f033e2e..f011e85 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -108,6 +108,10 @@
       } else {
         codegen_.DumpCoreRegister(output_, location.reg().RegId());
       }
+    } else if (location.IsConstant()) {
+      output_ << "constant";
+    } else if (location.IsInvalid()) {
+      output_ << "invalid";
     } else if (location.IsStackSlot()) {
       output_ << location.GetStackIndex() << "(sp)";
     } else {
diff --git a/compiler/optimizing/locations.cc b/compiler/optimizing/locations.cc
index 98766d2..468cfb7 100644
--- a/compiler/optimizing/locations.cc
+++ b/compiler/optimizing/locations.cc
@@ -29,4 +29,11 @@
   }
 }
 
+
+Location Location::RegisterOrConstant(HInstruction* instruction) {
+  return instruction->IsConstant()
+      ? Location::ConstantLocation(instruction->AsConstant())
+      : Location::RequiresRegister();
+}
+
 }  // namespace art
diff --git a/compiler/optimizing/locations.h b/compiler/optimizing/locations.h
index 40a39ad..aaddb09 100644
--- a/compiler/optimizing/locations.h
+++ b/compiler/optimizing/locations.h
@@ -24,6 +24,7 @@
 
 namespace art {
 
+class HConstant;
 class HInstruction;
 
 /**
@@ -34,23 +35,33 @@
  public:
   enum Kind {
     kInvalid = 0,
-    kStackSlot = 1,  // Word size slot.
-    kDoubleStackSlot = 2,  // 64bit stack slot.
-    kRegister = 3,
+    kConstant = 1,
+    kStackSlot = 2,  // Word size slot.
+    kDoubleStackSlot = 3,  // 64bit stack slot.
+    kRegister = 4,
     // On 32bits architectures, quick can pass a long where the
     // low bits are in the last parameter register, and the high
     // bits are in a stack slot. The kQuickParameter kind is for
     // handling this special case.
-    kQuickParameter = 4,
+    kQuickParameter = 5,
 
     // Unallocated location represents a location that is not fixed and can be
     // allocated by a register allocator.  Each unallocated location has
     // a policy that specifies what kind of location is suitable. Payload
     // contains register allocation policy.
-    kUnallocated = 5,
+    kUnallocated = 6,
   };
 
   Location() : value_(kInvalid) {
+    // Verify that non-tagged location kinds do not interfere with kConstantTag.
+    COMPILE_ASSERT((kInvalid & kLocationTagMask) != kConstant, TagError);
+    COMPILE_ASSERT((kUnallocated & kLocationTagMask) != kConstant, TagError);
+    COMPILE_ASSERT((kStackSlot & kLocationTagMask) != kConstant, TagError);
+    COMPILE_ASSERT((kDoubleStackSlot & kLocationTagMask) != kConstant, TagError);
+    COMPILE_ASSERT((kRegister & kLocationTagMask) != kConstant, TagError);
+    COMPILE_ASSERT((kConstant & kLocationTagMask) == kConstant, TagError);
+    COMPILE_ASSERT((kQuickParameter & kLocationTagMask) == kConstant, TagError);
+
     DCHECK(!IsValid());
   }
 
@@ -61,6 +72,20 @@
     return *this;
   }
 
+  bool IsConstant() const {
+    return (value_ & kLocationTagMask) == kConstant;
+  }
+
+  static Location ConstantLocation(HConstant* constant) {
+    DCHECK(constant != nullptr);
+    return Location(kConstant | reinterpret_cast<uword>(constant));
+  }
+
+  HConstant* GetConstant() const {
+    DCHECK(IsConstant());
+    return reinterpret_cast<HConstant*>(value_ & ~kLocationTagMask);
+  }
+
   bool IsValid() const {
     return value_ != kInvalid;
   }
@@ -69,11 +94,6 @@
     return !IsValid();
   }
 
-  bool IsConstant() const {
-    // TODO: support constants.
-    return false;
-  }
-
   // Empty location. Used if there the location should be ignored.
   static Location NoLocation() {
     return Location();
@@ -162,12 +182,13 @@
 
   const char* DebugString() const {
     switch (GetKind()) {
-      case kInvalid: return "?";
+      case kInvalid: return "I";
       case kRegister: return "R";
       case kStackSlot: return "S";
       case kDoubleStackSlot: return "DS";
       case kQuickParameter: return "Q";
       case kUnallocated: return "U";
+      case kConstant: return "C";
     }
     return "?";
   }
@@ -196,6 +217,8 @@
     return UnallocatedLocation(kRequiresRegister);
   }
 
+  static Location RegisterOrConstant(HInstruction* instruction);
+
   // The location of the first input to the instruction will be
   // used to replace this unallocated location.
   static Location SameAsFirstInput() {
@@ -215,6 +238,7 @@
   // Number of bits required to encode Kind value.
   static constexpr uint32_t kBitsForKind = 4;
   static constexpr uint32_t kBitsForPayload = kWordSize * kBitsPerByte - kBitsForKind;
+  static constexpr uword kLocationTagMask = 0x3;
 
   explicit Location(uword value) : value_(value) {}
 
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index e87b044..61a6f6b 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -408,7 +408,7 @@
   DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
 };
 
-#define FOR_EACH_INSTRUCTION(M)                            \
+#define FOR_EACH_CONCRETE_INSTRUCTION(M)                   \
   M(Add)                                                   \
   M(Condition)                                             \
   M(Equal)                                                 \
@@ -440,6 +440,9 @@
   M(NullCheck)                                             \
   M(Temporary)                                             \
 
+#define FOR_EACH_INSTRUCTION(M)                            \
+  FOR_EACH_CONCRETE_INSTRUCTION(M)                         \
+  M(Constant)
 
 #define FORWARD_DECLARATION(type) class H##type;
 FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
@@ -1078,11 +1081,21 @@
   DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
 };
 
+class HConstant : public HExpression<0> {
+ public:
+  explicit HConstant(Primitive::Type type) : HExpression(type) {}
+
+  DECLARE_INSTRUCTION(Constant);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(HConstant);
+};
+
 // Constants of the type int. Those can be from Dex instructions, or
 // synthesized (for example with the if-eqz instruction).
-class HIntConstant : public HExpression<0> {
+class HIntConstant : public HConstant {
  public:
-  explicit HIntConstant(int32_t value) : HExpression(Primitive::kPrimInt), value_(value) {}
+  explicit HIntConstant(int32_t value) : HConstant(Primitive::kPrimInt), value_(value) {}
 
   int32_t GetValue() const { return value_; }
 
@@ -1094,14 +1107,12 @@
   DISALLOW_COPY_AND_ASSIGN(HIntConstant);
 };
 
-class HLongConstant : public HExpression<0> {
+class HLongConstant : public HConstant {
  public:
-  explicit HLongConstant(int64_t value) : HExpression(Primitive::kPrimLong), value_(value) {}
+  explicit HLongConstant(int64_t value) : HConstant(Primitive::kPrimLong), value_(value) {}
 
   int64_t GetValue() const { return value_; }
 
-  virtual Primitive::Type GetType() const { return Primitive::kPrimLong; }
-
   DECLARE_INSTRUCTION(LongConstant);
 
  private:
@@ -1278,13 +1289,12 @@
 
   DECLARE_INSTRUCTION(Phi);
 
- protected:
+ private:
   GrowableArray<HInstruction*> inputs_;
   const uint32_t reg_number_;
   Primitive::Type type_;
   bool is_live_;
 
- private:
   DISALLOW_COPY_AND_ASSIGN(HPhi);
 };
 
diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc
index 68130dd..bd3a7d9 100644
--- a/compiler/optimizing/register_allocator.cc
+++ b/compiler/optimizing/register_allocator.cc
@@ -153,13 +153,13 @@
       if (current->HasRegister()) {
         DCHECK(instruction->IsParameterValue());
         inactive_.Add(current);
-      } else if (current->HasSpillSlot()) {
-        DCHECK(instruction->IsParameterValue());
+      } else if (current->HasSpillSlot() || instruction->IsConstant()) {
         // Split before first register use.
         size_t first_register_use = current->FirstRegisterUse();
         if (first_register_use != kNoLifetime) {
           LiveInterval* split = Split(current, first_register_use - 1);
-          // The new interval may start at a late
+          // Don't add direclty to `unhandled_`, it needs to be sorted and the start
+          // of this new interval might be after intervals already in the list.
           AddToUnhandled(split);
         } else {
           // Nothing to do, we won't allocate a register for this value.
@@ -579,6 +579,11 @@
     return;
   }
 
+  if (defined_by->IsConstant()) {
+    // Constants don't need a spill slot.
+    return;
+  }
+
   LiveInterval* last_sibling = interval;
   while (last_sibling->GetNextSibling() != nullptr) {
     last_sibling = last_sibling->GetNextSibling();
@@ -644,11 +649,16 @@
   if (interval->HasRegister()) {
     return Location::RegisterLocation(ManagedRegister(interval->GetRegister()));
   } else {
-    DCHECK(interval->GetParent()->HasSpillSlot());
-    if (NeedTwoSpillSlot(interval->GetType())) {
-      return Location::DoubleStackSlot(interval->GetParent()->GetSpillSlot());
+    HInstruction* defined_by = interval->GetParent()->GetDefinedBy();
+    if (defined_by->IsConstant()) {
+      return defined_by->GetLocations()->Out();
     } else {
-      return Location::StackSlot(interval->GetParent()->GetSpillSlot());
+      DCHECK(interval->GetParent()->HasSpillSlot());
+      if (NeedTwoSpillSlot(interval->GetType())) {
+        return Location::DoubleStackSlot(interval->GetParent()->GetSpillSlot());
+      } else {
+        return Location::StackSlot(interval->GetParent()->GetSpillSlot());
+      }
     }
   }
 }
diff --git a/compiler/utils/arm/assembler_arm.cc b/compiler/utils/arm/assembler_arm.cc
index 5fe8246..671ccb6 100644
--- a/compiler/utils/arm/assembler_arm.cc
+++ b/compiler/utils/arm/assembler_arm.cc
@@ -73,6 +73,11 @@
   return os;
 }
 
+ShifterOperand::ShifterOperand(uint32_t immed)
+    : type_(kImmediate), rm_(kNoRegister), rs_(kNoRegister),
+      is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(immed) {
+  CHECK(immed < (1u << 12) || ArmAssembler::ModifiedImmediate(immed) != kInvalidModifiedImmediate);
+}
 
 
 uint32_t ShifterOperand::encodingArm() const {
diff --git a/compiler/utils/arm/assembler_arm.h b/compiler/utils/arm/assembler_arm.h
index be19174..54965f6 100644
--- a/compiler/utils/arm/assembler_arm.h
+++ b/compiler/utils/arm/assembler_arm.h
@@ -35,9 +35,7 @@
       is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) {
   }
 
-  explicit ShifterOperand(uint32_t immed) : type_(kImmediate), rm_(kNoRegister), rs_(kNoRegister),
-      is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(immed) {
-  }
+  explicit ShifterOperand(uint32_t immed);
 
   // Data-processing operands - Register
   explicit ShifterOperand(Register rm) : type_(kRegister), rm_(rm), rs_(kNoRegister),
diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc
index 2ce4fd2..c693ec0 100644
--- a/compiler/utils/arm/assembler_thumb2.cc
+++ b/compiler/utils/arm/assembler_thumb2.cc
@@ -619,7 +619,8 @@
     return true;
   }
 
-  bool can_contain_high_register = opcode == MOV || opcode == ADD || opcode == SUB;
+  bool can_contain_high_register = (opcode == MOV)
+      || ((opcode == ADD || opcode == SUB) && (rn == rd));
 
   if (IsHighRegister(rd) || IsHighRegister(rn)) {
     if (can_contain_high_register) {
@@ -757,23 +758,21 @@
   int32_t encoding = 0;
   if (so.IsImmediate()) {
     // Check special cases.
-    if ((opcode == SUB || opcode == ADD) && rn == SP) {
-      // There are special ADD/SUB rd, SP, #imm12 instructions.
+    if ((opcode == SUB || opcode == ADD) && (so.GetImmediate() < (1u << 12))) {
       if (opcode == SUB) {
         thumb_opcode = 0b0101;
       } else {
         thumb_opcode = 0;
       }
       uint32_t imm = so.GetImmediate();
-      CHECK_LT(imm, (1u << 12));
 
       uint32_t i = (imm >> 11) & 1;
       uint32_t imm3 = (imm >> 8) & 0b111;
       uint32_t imm8 = imm & 0xff;
 
       encoding = B31 | B30 | B29 | B28 | B25 |
-           B19 | B18 | B16 |
            thumb_opcode << 21 |
+           rn << 16 |
            rd << 8 |
            i << 26 |
            imm3 << 12 |
@@ -882,7 +881,12 @@
         }
 
         break;
-      case CMN: thumb_opcode = 0b1011; rn = so.GetRegister(); break;
+      case CMN: {
+        thumb_opcode = 0b1011;
+        rd = rn;
+        rn = so.GetRegister();
+        break;
+      }
       case ORR: thumb_opcode = 0b1100; break;
       case MOV:
         dp_opcode = 0;
diff --git a/compiler/utils/assembler_thumb_test.cc b/compiler/utils/assembler_thumb_test.cc
index 68cb656..25928da 100644
--- a/compiler/utils/assembler_thumb_test.cc
+++ b/compiler/utils/assembler_thumb_test.cc
@@ -14,7 +14,10 @@
  * limitations under the License.
  */
 
+#include <dirent.h>
 #include <fstream>
+#include <sys/types.h>
+#include <map>
 
 #include "gtest/gtest.h"
 #include "utils/arm/assembler_thumb2.h"
@@ -40,6 +43,8 @@
 static constexpr bool kPrintResults = false;
 #endif
 
+static const char* TOOL_PREFIX = "arm-linux-androideabi-";
+
 void SetAndroidData() {
   const char* data = getenv("ANDROID_DATA");
   if (data == nullptr) {
@@ -109,9 +114,9 @@
   // Suffix on toolsdir will be something like "arm-eabi-4.8"
   while ((entry = readdir(dir)) != nullptr) {
     std::string subdir = toolsdir + std::string("/") + std::string(entry->d_name);
-    size_t eabi = subdir.find("arm-eabi-");
+    size_t eabi = subdir.find(TOOL_PREFIX);
     if (eabi != std::string::npos) {
-      std::string suffix = subdir.substr(eabi + sizeof("arm-eabi-"));
+      std::string suffix = subdir.substr(eabi + sizeof(TOOL_PREFIX));
       double version = strtod(suffix.c_str(), nullptr);
       if (version > maxversion) {
         maxversion = version;
@@ -169,19 +174,19 @@
   char cmd[256];
 
   // Assemble the .S
-  snprintf(cmd, sizeof(cmd), "%sarm-eabi-as %s -o %s.o", toolsdir.c_str(), filename, filename);
+  snprintf(cmd, sizeof(cmd), "%s%sas %s -o %s.o", toolsdir.c_str(), TOOL_PREFIX, filename, filename);
   system(cmd);
 
   // Remove the $d symbols to prevent the disassembler dumping the instructions
   // as .word
-  snprintf(cmd, sizeof(cmd), "%sarm-eabi-objcopy -N '$d' %s.o %s.oo", toolsdir.c_str(),
+  snprintf(cmd, sizeof(cmd), "%s%sobjcopy -N '$d' %s.o %s.oo", toolsdir.c_str(), TOOL_PREFIX,
     filename, filename);
   system(cmd);
 
   // Disassemble.
 
-  snprintf(cmd, sizeof(cmd), "%sarm-eabi-objdump -d %s.oo | grep '^  *[0-9a-f][0-9a-f]*:'",
-    toolsdir.c_str(), filename);
+  snprintf(cmd, sizeof(cmd), "%s%sobjdump -d %s.oo | grep '^  *[0-9a-f][0-9a-f]*:'",
+    toolsdir.c_str(), TOOL_PREFIX, filename);
   if (kPrintResults) {
     // Print the results only, don't check. This is used to generate new output for inserting
     // into the .inc file.
diff --git a/compiler/utils/assembler_thumb_test_expected.cc.inc b/compiler/utils/assembler_thumb_test_expected.cc.inc
index 3943e37..18035f3 100644
--- a/compiler/utils/assembler_thumb_test_expected.cc.inc
+++ b/compiler/utils/assembler_thumb_test_expected.cc.inc
@@ -48,8 +48,8 @@
 const char* DataProcessingImmediateResults[] = {
   "   0:	2055      	movs	r0, #85	; 0x55\n",
   "   2:	f06f 0055 	mvn.w	r0, #85	; 0x55\n",
-  "   6:	f101 0055 	add.w	r0, r1, #85	; 0x55\n",
-  "   a:	f1a1 0055 	sub.w	r0, r1, #85	; 0x55\n",
+  "   6:	f201 0055 	addw	r0, r1, #85	; 0x55\n",
+  "   a:	f2a1 0055 	subw	r0, r1, #85	; 0x55\n",
   "   e:	f001 0055 	and.w	r0, r1, #85	; 0x55\n",
   "  12:	f041 0055 	orr.w	r0, r1, #85	; 0x55\n",
   "  16:	f081 0055 	eor.w	r0, r1, #85	; 0x55\n",
diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc
index 78738d8..fe9349b 100644
--- a/compiler/utils/x86_64/assembler_x86_64.cc
+++ b/compiler/utils/x86_64/assembler_x86_64.cc
@@ -869,6 +869,22 @@
 }
 
 
+void X86_64Assembler::cmpq(CpuRegister reg, const Immediate& imm) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  CHECK(imm.is_int32());  // cmpq only supports 32b immediate.
+  EmitRex64(reg);
+  EmitComplex(7, Operand(reg), imm);
+}
+
+
+void X86_64Assembler::cmpq(CpuRegister reg, const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitRex64(reg);
+  EmitUint8(0x3B);
+  EmitOperand(reg.LowBits(), address);
+}
+
+
 void X86_64Assembler::addl(CpuRegister dst, CpuRegister src) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitOptionalRex32(dst, src);
@@ -1063,6 +1079,14 @@
 }
 
 
+void X86_64Assembler::addq(CpuRegister dst, const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitRex64(dst);
+  EmitUint8(0x03);
+  EmitOperand(dst.LowBits(), address);
+}
+
+
 void X86_64Assembler::addq(CpuRegister dst, CpuRegister src) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   // 0x01 is addq r/m64 <- r/m64 + r64, with op1 in r/m and op2 in reg: so reverse EmitRex64
@@ -1118,6 +1142,14 @@
 }
 
 
+void X86_64Assembler::subq(CpuRegister reg, const Address& address) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitRex64(reg);
+  EmitUint8(0x2B);
+  EmitOperand(reg.LowBits() & 7, address);
+}
+
+
 void X86_64Assembler::subl(CpuRegister reg, const Address& address) {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitOptionalRex32(reg, address);
diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h
index 7514854..330d2d5 100644
--- a/compiler/utils/x86_64/assembler_x86_64.h
+++ b/compiler/utils/x86_64/assembler_x86_64.h
@@ -385,6 +385,8 @@
   void cmpl(const Address& address, const Immediate& imm);
 
   void cmpq(CpuRegister reg0, CpuRegister reg1);
+  void cmpq(CpuRegister reg0, const Immediate& imm);
+  void cmpq(CpuRegister reg0, const Address& address);
 
   void testl(CpuRegister reg1, CpuRegister reg2);
   void testl(CpuRegister reg, const Immediate& imm);
@@ -408,6 +410,7 @@
 
   void addq(CpuRegister reg, const Immediate& imm);
   void addq(CpuRegister dst, CpuRegister src);
+  void addq(CpuRegister dst, const Address& address);
 
   void subl(CpuRegister dst, CpuRegister src);
   void subl(CpuRegister reg, const Immediate& imm);
@@ -415,6 +418,7 @@
 
   void subq(CpuRegister reg, const Immediate& imm);
   void subq(CpuRegister dst, CpuRegister src);
+  void subq(CpuRegister dst, const Address& address);
 
   void cdq();