[vm] Minor ARM64 code generation improvements discovered during RISC-V port.
TEST=ci
Change-Id: I4bd17df224933f732eb9cef0a9b2da8dfad0a7d4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/227940
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm64.cc b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
index f9c178a..4056cbf 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
@@ -51,9 +51,8 @@
       R1);
 
   // Set the length field in the growable array object to 0.
-  __ LoadImmediate(R1, 0);
   __ StoreCompressedIntoObjectNoBarrier(
-      R0, FieldAddress(R0, target::GrowableObjectArray::length_offset()), R1);
+      R0, FieldAddress(R0, target::GrowableObjectArray::length_offset()), ZR);
   __ ret();  // Returns the newly allocated object in R0.
 
   __ Bind(normal_ir_body);
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 1c5673c..979c8ba 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -5286,10 +5286,16 @@
   __ CompareObjectRegisters(result_mod, ZR);
   __ b(&done, GE);
   // Result is negative, adjust it.
-  __ CompareObjectRegisters(right, ZR);
-  __ sub(TMP2, result_mod, compiler::Operand(right), compiler::kObjectBytes);
-  __ add(TMP, result_mod, compiler::Operand(right), compiler::kObjectBytes);
-  __ csel(result_mod, TMP, TMP2, GE);
+  if (RangeUtils::IsNegative(divisor_range())) {
+    __ sub(result_mod, result_mod, compiler::Operand(right));
+  } else if (RangeUtils::IsPositive(divisor_range())) {
+    __ add(result_mod, result_mod, compiler::Operand(right));
+  } else {
+    __ CompareObjectRegisters(right, ZR);
+    __ sub(TMP2, result_mod, compiler::Operand(right), compiler::kObjectBytes);
+    __ add(TMP, result_mod, compiler::Operand(right), compiler::kObjectBytes);
+    __ csel(result_mod, TMP, TMP2, GE);
+  }
   __ Bind(&done);
 }
 
@@ -5634,8 +5640,7 @@
 
   // Handle modulo/division by zero exception on slow path.
   if (slow_path->has_divide_by_zero()) {
-    __ CompareRegisters(right, ZR);
-    __ b(slow_path->entry_label(), EQ);
+    __ cbz(slow_path->entry_label(), right);
   }
 
   // Perform actual operation
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index 7d02f87..20c4ba0 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -2082,6 +2082,10 @@
   return OnlyGreaterThanOrEqualTo(0);
 }
 
+bool Range::IsNegative() const {
+  return OnlyLessThanOrEqualTo(-1);
+}
+
 bool Range::OnlyLessThanOrEqualTo(int64_t val) const {
   const RangeBoundary upper_bound = max().UpperBound();
   return !upper_bound.IsPositiveInfinity() &&
diff --git a/runtime/vm/compiler/backend/range_analysis.h b/runtime/vm/compiler/backend/range_analysis.h
index b0037f4..aa247c7 100644
--- a/runtime/vm/compiler/backend/range_analysis.h
+++ b/runtime/vm/compiler/backend/range_analysis.h
@@ -413,6 +413,9 @@
   // [0, +inf]
   bool IsPositive() const;
 
+  // [-inf, -1]
+  bool IsNegative() const;
+
   // [-inf, val].
   bool OnlyLessThanOrEqualTo(int64_t val) const;
 
@@ -560,6 +563,9 @@
   static bool IsPositive(Range* range) {
     return !Range::IsUnknown(range) && range->IsPositive();
   }
+  static bool IsNegative(Range* range) {
+    return !Range::IsUnknown(range) && range->IsNegative();
+  }
 
   static bool Overlaps(Range* range, intptr_t min, intptr_t max) {
     return Range::IsUnknown(range) || range->Overlaps(min, max);
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index bcdc1f4..4d22204 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -1961,15 +1961,15 @@
       Label not_parameterized_case;
 
       const Register kClsIdReg = R4;
-      const Register kTypeOffestReg = R5;
+      const Register kTypeOffsetReg = R5;
 
       __ ExtractClassIdFromTags(kClsIdReg, kTagsReg);
 
       // Load class' type_arguments_field offset in words.
-      __ LoadClassById(kTypeOffestReg, kClsIdReg);
+      __ LoadClassById(kTypeOffsetReg, kClsIdReg);
       __ ldr(
-          kTypeOffestReg,
-          FieldAddress(kTypeOffestReg,
+          kTypeOffsetReg,
+          FieldAddress(kTypeOffsetReg,
                        target::Class::
                            host_type_arguments_field_offset_in_words_offset()),
           kFourBytes);
@@ -1977,7 +1977,7 @@
       // Set the type arguments in the new object.
       __ StoreCompressedIntoObjectNoBarrier(
           AllocateObjectABI::kResultReg,
-          Address(AllocateObjectABI::kResultReg, kTypeOffestReg, UXTX,
+          Address(AllocateObjectABI::kResultReg, kTypeOffsetReg, UXTX,
                   Address::Scaled),
           AllocateObjectABI::kTypeArgumentsReg);
 
@@ -3723,9 +3723,7 @@
     /* R0: new object start as a tagged pointer. */
     /* R1: new object end address. */
     /* R2: iterator which initially points to the start of the variable */
-    /* R3: scratch register. */
     /* data area to be initialized. */
-    __ mov(R3, ZR);
     __ AddImmediate(R2, R0, target::TypedData::HeaderSize() - 1);
     __ StoreInternalPointer(
         R0, FieldAddress(R0, target::TypedDataBase::data_field_offset()), R2);
@@ -3733,7 +3731,7 @@
     __ Bind(&init_loop);
     __ cmp(R2, Operand(R1));
     __ b(&done, CS);
-    __ str(R3, Address(R2, 0));
+    __ str(ZR, Address(R2, 0));
     __ add(R2, R2, Operand(target::kWordSize));
     __ b(&init_loop);
     __ Bind(&done);