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: {