MIPS32R2: Allow all kinds of class/string loads and invokes

Force generating nal instruction before PC-relative addressing in the
presence of irreducible loops (HMipsComputeBaseMethodAddress is not
used in those situations).

This patch fixes a lot of JIT tests failures.

Test: ./testrunner.py --target --optimizing --jit (CI20 and QEMU)
Test: mma test-art-target-gtest (CI20 and QEMU)

Change-Id: I1815a6bb5783f439c8263612abff557f797bfef1
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index 6256722..a733fa2 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -290,7 +290,9 @@
       // For non-Baker read barriers we need to re-calculate the address of
       // the class entry.
       const bool isR6 = mips_codegen->GetInstructionSetFeatures().IsR6();
-      Register base = isR6 ? ZERO : locations->InAt(0).AsRegister<Register>();
+      const bool has_irreducible_loops = codegen->GetGraph()->HasIrreducibleLoops();
+      Register base =
+          (isR6 || has_irreducible_loops) ? ZERO : locations->InAt(0).AsRegister<Register>();
       CodeGeneratorMIPS::PcRelativePatchInfo* info_high =
           mips_codegen->NewTypeBssEntryPatch(cls_->GetDexFile(), type_index);
       CodeGeneratorMIPS::PcRelativePatchInfo* info_low =
@@ -380,7 +382,9 @@
       // For non-Baker read barriers we need to re-calculate the address of
       // the string entry.
       const bool isR6 = mips_codegen->GetInstructionSetFeatures().IsR6();
-      Register base = isR6 ? ZERO : locations->InAt(0).AsRegister<Register>();
+      const bool has_irreducible_loops = codegen->GetGraph()->HasIrreducibleLoops();
+      Register base =
+          (isR6 || has_irreducible_loops) ? ZERO : locations->InAt(0).AsRegister<Register>();
       CodeGeneratorMIPS::PcRelativePatchInfo* info_high =
           mips_codegen->NewStringBssEntryPatch(load->GetDexFile(), string_index);
       CodeGeneratorMIPS::PcRelativePatchInfo* info_low =
@@ -7332,7 +7336,8 @@
   DCHECK(!invoke->IsStaticWithExplicitClinitCheck());
 
   bool is_r6 = codegen_->GetInstructionSetFeatures().IsR6();
-  bool has_extra_input = invoke->HasPcRelativeMethodLoadKind() && !is_r6;
+  bool has_irreducible_loops = codegen_->GetGraph()->HasIrreducibleLoops();
+  bool has_extra_input = invoke->HasPcRelativeMethodLoadKind() && !is_r6 && !has_irreducible_loops;
 
   IntrinsicLocationsBuilderMIPS intrinsic(codegen_);
   if (intrinsic.TryDispatch(invoke)) {
@@ -7370,75 +7375,49 @@
 
 HLoadString::LoadKind CodeGeneratorMIPS::GetSupportedLoadStringKind(
     HLoadString::LoadKind desired_string_load_kind) {
-  // We disable PC-relative load on pre-R6 when there is an irreducible loop, as the optimization
-  // is incompatible with it.
-  // TODO: Create as many HMipsComputeBaseMethodAddress instructions as needed for methods
-  // with irreducible loops.
-  bool has_irreducible_loops = GetGraph()->HasIrreducibleLoops();
-  bool is_r6 = GetInstructionSetFeatures().IsR6();
-  bool fallback_load = has_irreducible_loops && !is_r6;
   switch (desired_string_load_kind) {
     case HLoadString::LoadKind::kBootImageLinkTimePcRelative:
     case HLoadString::LoadKind::kBootImageInternTable:
     case HLoadString::LoadKind::kBssEntry:
       DCHECK(!Runtime::Current()->UseJitCompilation());
       break;
-    case HLoadString::LoadKind::kBootImageAddress:
-      break;
     case HLoadString::LoadKind::kJitTableAddress:
       DCHECK(Runtime::Current()->UseJitCompilation());
-      fallback_load = false;
       break;
+    case HLoadString::LoadKind::kBootImageAddress:
     case HLoadString::LoadKind::kRuntimeCall:
-      fallback_load = false;
       break;
   }
-  if (fallback_load) {
-    desired_string_load_kind = HLoadString::LoadKind::kRuntimeCall;
-  }
   return desired_string_load_kind;
 }
 
 HLoadClass::LoadKind CodeGeneratorMIPS::GetSupportedLoadClassKind(
     HLoadClass::LoadKind desired_class_load_kind) {
-  // We disable PC-relative load on pre-R6 when there is an irreducible loop, as the optimization
-  // is incompatible with it.
-  // TODO: Create as many HMipsComputeBaseMethodAddress instructions as needed for methods
-  // with irreducible loops.
-  bool has_irreducible_loops = GetGraph()->HasIrreducibleLoops();
-  bool is_r6 = GetInstructionSetFeatures().IsR6();
-  bool fallback_load = has_irreducible_loops && !is_r6;
   switch (desired_class_load_kind) {
     case HLoadClass::LoadKind::kInvalid:
       LOG(FATAL) << "UNREACHABLE";
       UNREACHABLE();
     case HLoadClass::LoadKind::kReferrersClass:
-      fallback_load = false;
       break;
     case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
     case HLoadClass::LoadKind::kBootImageClassTable:
     case HLoadClass::LoadKind::kBssEntry:
       DCHECK(!Runtime::Current()->UseJitCompilation());
       break;
-    case HLoadClass::LoadKind::kBootImageAddress:
-      break;
     case HLoadClass::LoadKind::kJitTableAddress:
       DCHECK(Runtime::Current()->UseJitCompilation());
-      fallback_load = false;
       break;
+    case HLoadClass::LoadKind::kBootImageAddress:
     case HLoadClass::LoadKind::kRuntimeCall:
-      fallback_load = false;
       break;
   }
-  if (fallback_load) {
-    desired_class_load_kind = HLoadClass::LoadKind::kRuntimeCall;
-  }
   return desired_class_load_kind;
 }
 
 Register CodeGeneratorMIPS::GetInvokeStaticOrDirectExtraParameter(HInvokeStaticOrDirect* invoke,
                                                                   Register temp) {
   CHECK(!GetInstructionSetFeatures().IsR6());
+  CHECK(!GetGraph()->HasIrreducibleLoops());
   CHECK_EQ(invoke->InputCount(), invoke->GetNumberOfArguments() + 1u);
   Location location = invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex());
   if (!invoke->GetLocations()->Intrinsified()) {
@@ -7466,27 +7445,7 @@
 HInvokeStaticOrDirect::DispatchInfo CodeGeneratorMIPS::GetSupportedInvokeStaticOrDirectDispatch(
       const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info,
       HInvokeStaticOrDirect* invoke ATTRIBUTE_UNUSED) {
-  HInvokeStaticOrDirect::DispatchInfo dispatch_info = desired_dispatch_info;
-  // We disable PC-relative load on pre-R6 when there is an irreducible loop, as the optimization
-  // is incompatible with it.
-  // TODO: Create as many HMipsComputeBaseMethodAddress instructions as needed for methods
-  // with irreducible loops.
-  bool has_irreducible_loops = GetGraph()->HasIrreducibleLoops();
-  bool is_r6 = GetInstructionSetFeatures().IsR6();
-  bool fallback_load = has_irreducible_loops && !is_r6;
-  switch (dispatch_info.method_load_kind) {
-    case HInvokeStaticOrDirect::MethodLoadKind::kBootImageLinkTimePcRelative:
-    case HInvokeStaticOrDirect::MethodLoadKind::kBssEntry:
-      break;
-    default:
-      fallback_load = false;
-      break;
-  }
-  if (fallback_load) {
-    dispatch_info.method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall;
-    dispatch_info.method_load_data = 0;
-  }
-  return dispatch_info;
+  return desired_dispatch_info;
 }
 
 void CodeGeneratorMIPS::GenerateStaticOrDirectCall(
@@ -7496,7 +7455,8 @@
   HInvokeStaticOrDirect::MethodLoadKind method_load_kind = invoke->GetMethodLoadKind();
   HInvokeStaticOrDirect::CodePtrLocation code_ptr_location = invoke->GetCodePtrLocation();
   bool is_r6 = GetInstructionSetFeatures().IsR6();
-  Register base_reg = (invoke->HasPcRelativeMethodLoadKind() && !is_r6)
+  bool has_irreducible_loops = GetGraph()->HasIrreducibleLoops();
+  Register base_reg = (invoke->HasPcRelativeMethodLoadKind() && !is_r6 && !has_irreducible_loops)
       ? GetInvokeStaticOrDirectExtraParameter(invoke, temp.AsRegister<Register>())
       : ZERO;
 
@@ -7635,6 +7595,7 @@
   }
   DCHECK(!cls->NeedsAccessCheck());
   const bool isR6 = codegen_->GetInstructionSetFeatures().IsR6();
+  const bool has_irreducible_loops = codegen_->GetGraph()->HasIrreducibleLoops();
   const bool requires_read_barrier = kEmitCompilerReadBarrier && !cls->IsInBootImage();
   LocationSummary::CallKind call_kind = (cls->NeedsEnvironment() || requires_read_barrier)
       ? LocationSummary::kCallOnSlowPath
@@ -7652,6 +7613,10 @@
       if (isR6) {
         break;
       }
+      if (has_irreducible_loops) {
+        codegen_->ClobberRA();
+        break;
+      }
       FALLTHROUGH_INTENDED;
     case HLoadClass::LoadKind::kReferrersClass:
       locations->SetInAt(0, Location::RequiresRegister());
@@ -7690,12 +7655,15 @@
   Register out = out_loc.AsRegister<Register>();
   Register base_or_current_method_reg;
   bool isR6 = codegen_->GetInstructionSetFeatures().IsR6();
+  bool has_irreducible_loops = GetGraph()->HasIrreducibleLoops();
   switch (load_kind) {
     // We need an extra register for PC-relative literals on R2.
     case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
     case HLoadClass::LoadKind::kBootImageAddress:
+    case HLoadClass::LoadKind::kBootImageClassTable:
     case HLoadClass::LoadKind::kBssEntry:
-      base_or_current_method_reg = isR6 ? ZERO : locations->InAt(0).AsRegister<Register>();
+      base_or_current_method_reg =
+          (isR6 || has_irreducible_loops) ? ZERO : locations->InAt(0).AsRegister<Register>();
       break;
     case HLoadClass::LoadKind::kReferrersClass:
     case HLoadClass::LoadKind::kRuntimeCall:
@@ -7741,9 +7709,13 @@
       uint32_t address = dchecked_integral_cast<uint32_t>(
           reinterpret_cast<uintptr_t>(cls->GetClass().Get()));
       DCHECK_NE(address, 0u);
-      __ LoadLiteral(out,
-                     base_or_current_method_reg,
-                     codegen_->DeduplicateBootImageAddressLiteral(address));
+      if (isR6 || !has_irreducible_loops) {
+        __ LoadLiteral(out,
+                       base_or_current_method_reg,
+                       codegen_->DeduplicateBootImageAddressLiteral(address));
+      } else {
+        __ LoadConst32(out, address);
+      }
       break;
     }
     case HLoadClass::LoadKind::kBootImageClassTable: {
@@ -7848,6 +7820,7 @@
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(load, call_kind);
   HLoadString::LoadKind load_kind = load->GetLoadKind();
   const bool isR6 = codegen_->GetInstructionSetFeatures().IsR6();
+  const bool has_irreducible_loops = codegen_->GetGraph()->HasIrreducibleLoops();
   switch (load_kind) {
     // We need an extra register for PC-relative literals on R2.
     case HLoadString::LoadKind::kBootImageAddress:
@@ -7857,6 +7830,10 @@
       if (isR6) {
         break;
       }
+      if (has_irreducible_loops) {
+        codegen_->ClobberRA();
+        break;
+      }
       FALLTHROUGH_INTENDED;
     // We need an extra register for PC-relative dex cache accesses.
     case HLoadString::LoadKind::kRuntimeCall:
@@ -7895,13 +7872,15 @@
   Register out = out_loc.AsRegister<Register>();
   Register base_or_current_method_reg;
   bool isR6 = codegen_->GetInstructionSetFeatures().IsR6();
+  bool has_irreducible_loops = GetGraph()->HasIrreducibleLoops();
   switch (load_kind) {
     // We need an extra register for PC-relative literals on R2.
     case HLoadString::LoadKind::kBootImageAddress:
     case HLoadString::LoadKind::kBootImageLinkTimePcRelative:
     case HLoadString::LoadKind::kBootImageInternTable:
     case HLoadString::LoadKind::kBssEntry:
-      base_or_current_method_reg = isR6 ? ZERO : locations->InAt(0).AsRegister<Register>();
+      base_or_current_method_reg =
+          (isR6 || has_irreducible_loops) ? ZERO : locations->InAt(0).AsRegister<Register>();
       break;
     default:
       base_or_current_method_reg = ZERO;
@@ -7925,9 +7904,13 @@
       uint32_t address = dchecked_integral_cast<uint32_t>(
           reinterpret_cast<uintptr_t>(load->GetString().Get()));
       DCHECK_NE(address, 0u);
-      __ LoadLiteral(out,
-                     base_or_current_method_reg,
-                     codegen_->DeduplicateBootImageAddressLiteral(address));
+      if (isR6 || !has_irreducible_loops) {
+        __ LoadLiteral(out,
+                       base_or_current_method_reg,
+                       codegen_->DeduplicateBootImageAddressLiteral(address));
+      } else {
+        __ LoadConst32(out, address);
+      }
       return;
     }
     case HLoadString::LoadKind::kBootImageInternTable: {