summaryrefslogtreecommitdiffstats
path: root/compiler/optimizing/code_generator_x86_64.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing/code_generator_x86_64.cc')
-rw-r--r--compiler/optimizing/code_generator_x86_64.cc35
1 files changed, 32 insertions, 3 deletions
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 74adb31..adc022a 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -1868,8 +1868,19 @@ void LocationsBuilderX86_64::VisitAdd(HAdd* add) {
case Primitive::kPrimLong: {
locations->SetInAt(0, Location::RequiresRegister());
- locations->SetInAt(1, Location::RequiresRegister());
- locations->SetOut(Location::SameAsFirstInput());
+ // We can use a leaq or addq if the constant can fit in an immediate.
+ HInstruction* rhs = add->InputAt(1);
+ bool is_int32_constant = false;
+ if (rhs->IsLongConstant()) {
+ int64_t value = rhs->AsLongConstant()->GetValue();
+ if (static_cast<int32_t>(value) == value) {
+ is_int32_constant = true;
+ }
+ }
+ locations->SetInAt(1,
+ is_int32_constant ? Location::RegisterOrConstant(rhs) :
+ Location::RequiresRegister());
+ locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
break;
}
@@ -1917,7 +1928,25 @@ void InstructionCodeGeneratorX86_64::VisitAdd(HAdd* add) {
}
case Primitive::kPrimLong: {
- __ addq(first.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>());
+ if (second.IsRegister()) {
+ if (out.AsRegister<Register>() == first.AsRegister<Register>()) {
+ __ addq(out.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>());
+ } else {
+ __ leaq(out.AsRegister<CpuRegister>(), Address(
+ first.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>(), TIMES_1, 0));
+ }
+ } else {
+ DCHECK(second.IsConstant());
+ int64_t value = second.GetConstant()->AsLongConstant()->GetValue();
+ int32_t int32_value = Low32Bits(value);
+ DCHECK_EQ(int32_value, value);
+ if (out.AsRegister<Register>() == first.AsRegister<Register>()) {
+ __ addq(out.AsRegister<CpuRegister>(), Immediate(int32_value));
+ } else {
+ __ leaq(out.AsRegister<CpuRegister>(), Address(
+ first.AsRegister<CpuRegister>(), int32_value));
+ }
+ }
break;
}