[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;
     }