Opt Compiler: ARM64: Enable Callee-saved register, as defined by AAPCS64.

For now we block kQuickSuspendRegister - x19, since Quick and the runtime
use this as a suspend counter register.

Change-Id: I090d386670e81e7924e4aa9a3864ef30d0580a30
Signed-off-by: Serban Constantinescu <serban.constantinescu@arm.com>
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 3bc23fe..7588a29 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -402,15 +402,15 @@
                     kNumberOfAllocatableRegisters,
                     kNumberOfAllocatableFPRegisters,
                     kNumberOfAllocatableRegisterPairs,
-                    (1 << LR),
-                    0,
+                    callee_saved_core_registers.list(),
+                    callee_saved_fp_registers.list(),
                     compiler_options),
       block_labels_(nullptr),
       location_builder_(graph, this),
       instruction_visitor_(graph, this),
       move_resolver_(graph->GetArena(), this) {
   // Save the link register (containing the return address) to mimic Quick.
-  AddAllocatedRegister(Location::RegisterLocation(LR));
+  AddAllocatedRegister(LocationFrom(lr));
 }
 
 #undef __
@@ -448,26 +448,28 @@
     UseScratchRegisterScope temps(GetVIXLAssembler());
     Register temp = temps.AcquireX();
     DCHECK(GetCompilerOptions().GetImplicitStackOverflowChecks());
-    __ Add(temp, sp, -static_cast<int32_t>(GetStackOverflowReservedBytes(kArm64)));
+    __ Sub(temp, sp, static_cast<int32_t>(GetStackOverflowReservedBytes(kArm64)));
     __ Ldr(wzr, MemOperand(temp, 0));
     RecordPcInfo(nullptr, 0);
   }
 
   int frame_size = GetFrameSize();
   __ Str(kArtMethodRegister, MemOperand(sp, -frame_size, PreIndex));
-  __ PokeCPURegList(GetFramePreservedRegisters(), frame_size - FrameEntrySpillSize());
+  __ PokeCPURegList(GetFramePreservedCoreRegisters(), frame_size - GetCoreSpillSize());
+  __ PokeCPURegList(GetFramePreservedFPRegisters(), frame_size - FrameEntrySpillSize());
 
   // Stack layout:
-  // sp[frame_size - 8]        : lr.
-  // ...                       : other preserved registers.
-  // sp[frame_size - regs_size]: first preserved register.
-  // ...                       : reserved frame space.
-  // sp[0]                     : current method.
+  //      sp[frame_size - 8]        : lr.
+  //      ...                       : other preserved core registers.
+  //      ...                       : other preserved fp registers.
+  //      ...                       : reserved frame space.
+  //      sp[0]                     : current method.
 }
 
 void CodeGeneratorARM64::GenerateFrameExit() {
   int frame_size = GetFrameSize();
-  __ PeekCPURegList(GetFramePreservedRegisters(), frame_size - FrameEntrySpillSize());
+  __ PeekCPURegList(GetFramePreservedFPRegisters(), frame_size - FrameEntrySpillSize());
+  __ PeekCPURegList(GetFramePreservedCoreRegisters(), frame_size - GetCoreSpillSize());
   __ Drop(frame_size);
 }
 
@@ -555,26 +557,38 @@
   __ Bind(&done);
 }
 
-void CodeGeneratorARM64::SetupBlockedRegisters(bool is_baseline ATTRIBUTE_UNUSED) const {
-  // Block reserved registers:
-  //   ip0 (VIXL temporary)
-  //   ip1 (VIXL temporary)
-  //   tr
-  //   lr
-  // sp is not part of the allocatable registers, so we don't need to block it.
-  // TODO: Avoid blocking callee-saved registers, and instead preserve them
-  // where necessary.
+void CodeGeneratorARM64::SetupBlockedRegisters(bool is_baseline) const {
+  // Blocked core registers:
+  //      lr        : Runtime reserved.
+  //      tr        : Runtime reserved.
+  //      xSuspend  : Runtime reserved. TODO: Unblock this when the runtime stops using it.
+  //      ip1       : VIXL core temp.
+  //      ip0       : VIXL core temp.
+  //
+  // Blocked fp registers:
+  //      d31       : VIXL fp temp.
   CPURegList reserved_core_registers = vixl_reserved_core_registers;
   reserved_core_registers.Combine(runtime_reserved_core_registers);
-  reserved_core_registers.Combine(quick_callee_saved_registers);
   while (!reserved_core_registers.IsEmpty()) {
     blocked_core_registers_[reserved_core_registers.PopLowestIndex().code()] = true;
   }
+
   CPURegList reserved_fp_registers = vixl_reserved_fp_registers;
-  reserved_fp_registers.Combine(CPURegList::GetCalleeSavedFP());
   while (!reserved_core_registers.IsEmpty()) {
     blocked_fpu_registers_[reserved_fp_registers.PopLowestIndex().code()] = true;
   }
+
+  if (is_baseline) {
+    CPURegList reserved_core_baseline_registers = callee_saved_core_registers;
+    while (!reserved_core_baseline_registers.IsEmpty()) {
+      blocked_core_registers_[reserved_core_baseline_registers.PopLowestIndex().code()] = true;
+    }
+
+    CPURegList reserved_fp_baseline_registers = callee_saved_fp_registers;
+    while (!reserved_fp_baseline_registers.IsEmpty()) {
+      blocked_fpu_registers_[reserved_fp_baseline_registers.PopLowestIndex().code()] = true;
+    }
+  }
 }
 
 Location CodeGeneratorARM64::AllocateFreeRegister(Primitive::Type type) const {