[optimizing compiler] x86 goodness
Implement the x86 version of
https://android-review.googlesource.com/#/c/129560/, which made some
enhancements to x86_64 code.
- Use leal to implement 3 operand adds
- Use testl rather than cmpl to 0 for registers
- Use leaq for x86_64 for adds with constant in int32_t range
Note:
- The range and register allocator tests seem quite fragile. I had to
change ADD_INT_LIT8 to XOR_INT_LIT8 for the register allocator test to
get the code to run. It seems like this is a bit hard-coded to
expected code generation sequences. I also changes BuildTwoAdds to
BuildTwoSubs for the same reason.
- For the live range test, I just changed the expected output, as the
Locations were different.
Change-Id: I402f2e95ddc8be4eb0befb3dae1b29feadfa29ab
Signed-off-by: Mark Mendell <mark.p.mendell@intel.com>
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 @@
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 @@
}
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;
}