diff options
Diffstat (limited to 'compiler/optimizing/code_generator_x86_64.cc')
-rw-r--r-- | compiler/optimizing/code_generator_x86_64.cc | 35 |
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; } |