MIPS32: Ensure preservation of RA in leaf methods if it's clobbered
Test: booted MIPS32 in QEMU
Test: test-art-host-gtest
Test: test-art-target-gtest-codegen_test in QEMU
Test: test-art-target-run-test-optimizing on CI20
Change-Id: Ia3da5902d967cd7af313f03ebf414320b0063619
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index e0de03b..1e62513 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -697,16 +697,17 @@
if ((fpu_spill_mask_ != 0) && (POPCOUNT(core_spill_mask_) % 2 != 0)) {
core_spill_mask_ |= (1 << ZERO);
}
+}
+
+bool CodeGeneratorMIPS::HasAllocatedCalleeSaveRegisters() const {
// If RA is clobbered by PC-relative operations on R2 and it's the only spilled register
- // (this can happen in leaf methods), artificially spill the ZERO register in order to
- // force explicit saving and restoring of RA. RA isn't saved/restored when it's the only
- // spilled register.
+ // (this can happen in leaf methods), force CodeGenerator::InitializeCodeGeneration()
+ // into the path that creates a stack frame so that RA can be explicitly saved and restored.
+ // RA can't otherwise be saved/restored when it's the only spilled register.
// TODO: Can this be improved? It causes creation of a stack frame (while RA might be
// saved in an unused temporary register) and saving of RA and the current method pointer
// in the frame.
- if (clobbered_ra_ && core_spill_mask_ == (1u << RA) && fpu_spill_mask_ == 0) {
- core_spill_mask_ |= (1 << ZERO);
- }
+ return CodeGenerator::HasAllocatedCalleeSaveRegisters() || clobbered_ra_;
}
static dwarf::Reg DWARFReg(Register reg) {
@@ -729,6 +730,9 @@
}
if (HasEmptyFrame()) {
+ CHECK_EQ(fpu_spill_mask_, 0u);
+ CHECK_EQ(core_spill_mask_, 1u << RA);
+ CHECK(!clobbered_ra_);
return;
}
@@ -762,6 +766,7 @@
}
// Store the current method pointer.
+ // TODO: can we not do this if RequiresCurrentMethod() returns false?
__ StoreToOffset(kStoreWord, kMethodRegisterArgument, SP, kCurrentMethodStackOffset);
}