Add assembly operations with constants in optimizing compiler.

Change-Id: I5bcc35ab50d4457186effef5592a75d7f4e5b65f
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());
+      }
     }
   }
 }