diff options
Diffstat (limited to 'compiler/optimizing')
| -rw-r--r-- | compiler/optimizing/code_generator_mips.cc | 124 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator_mips.h | 1 | ||||
| -rw-r--r-- | compiler/optimizing/optimizing_cfi_test_expected.inc | 172 |
3 files changed, 123 insertions, 174 deletions
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc index 12d1164d03..abc6b1309d 100644 --- a/compiler/optimizing/code_generator_mips.cc +++ b/compiler/optimizing/code_generator_mips.cc @@ -663,6 +663,18 @@ void ParallelMoveResolverMIPS::Exchange(int index1, int index2, bool double_slot } } +void CodeGeneratorMIPS::ComputeSpillMask() { + core_spill_mask_ = allocated_registers_.GetCoreRegisters() & core_callee_save_mask_; + fpu_spill_mask_ = allocated_registers_.GetFloatingPointRegisters() & fpu_callee_save_mask_; + DCHECK_NE(core_spill_mask_, 0u) << "At least the return address register must be saved"; + // If there're FPU callee-saved registers and there's an odd number of GPR callee-saved + // registers, include the ZERO register to force alignment of FPU callee-saved registers + // within the stack frame. + if ((fpu_spill_mask_ != 0) && (POPCOUNT(core_spill_mask_) % 2 != 0)) { + core_spill_mask_ |= (1 << ZERO); + } +} + static dwarf::Reg DWARFReg(Register reg) { return dwarf::Reg::MipsCore(static_cast<int>(reg)); } @@ -692,105 +704,61 @@ void CodeGeneratorMIPS::GenerateFrameEntry() { } // Spill callee-saved registers. - // Note that their cumulative size is small and they can be indexed using - // 16-bit offsets. - - // TODO: increment/decrement SP in one step instead of two or remove this comment. - uint32_t ofs = FrameEntrySpillSize(); - bool unaligned_float = ofs & 0x7; - bool fpu_32bit = isa_features_.Is32BitFloatingPoint(); + uint32_t ofs = GetFrameSize(); __ IncreaseFrameSize(ofs); - for (int i = arraysize(kCoreCalleeSaves) - 1; i >= 0; --i) { - Register reg = kCoreCalleeSaves[i]; - if (allocated_registers_.ContainsCoreRegister(reg)) { - ofs -= kMipsWordSize; - __ Sw(reg, SP, ofs); + for (uint32_t mask = core_spill_mask_; mask != 0; ) { + Register reg = static_cast<Register>(MostSignificantBit(mask)); + mask ^= 1u << reg; + ofs -= kMipsWordSize; + // The ZERO register is only included for alignment. + if (reg != ZERO) { + __ StoreToOffset(kStoreWord, reg, SP, ofs); __ cfi().RelOffset(DWARFReg(reg), ofs); } } - for (int i = arraysize(kFpuCalleeSaves) - 1; i >= 0; --i) { - FRegister reg = kFpuCalleeSaves[i]; - if (allocated_registers_.ContainsFloatingPointRegister(reg)) { - ofs -= kMipsDoublewordSize; - // TODO: Change the frame to avoid unaligned accesses for fpu registers. - if (unaligned_float) { - if (fpu_32bit) { - __ Swc1(reg, SP, ofs); - __ Swc1(static_cast<FRegister>(reg + 1), SP, ofs + 4); - } else { - __ Mfhc1(TMP, reg); - __ Swc1(reg, SP, ofs); - __ Sw(TMP, SP, ofs + 4); - } - } else { - __ Sdc1(reg, SP, ofs); - } - // TODO: __ cfi().RelOffset(DWARFReg(reg), ofs); - } + for (uint32_t mask = fpu_spill_mask_; mask != 0; ) { + FRegister reg = static_cast<FRegister>(MostSignificantBit(mask)); + mask ^= 1u << reg; + ofs -= kMipsDoublewordSize; + __ StoreDToOffset(reg, SP, ofs); + // TODO: __ cfi().RelOffset(DWARFReg(reg), ofs); } - // Allocate the rest of the frame and store the current method pointer - // at its end. - - __ IncreaseFrameSize(GetFrameSize() - FrameEntrySpillSize()); - - static_assert(IsInt<16>(kCurrentMethodStackOffset), - "kCurrentMethodStackOffset must fit into int16_t"); - __ Sw(kMethodRegisterArgument, SP, kCurrentMethodStackOffset); + // Store the current method pointer. + __ StoreToOffset(kStoreWord, kMethodRegisterArgument, SP, kCurrentMethodStackOffset); } void CodeGeneratorMIPS::GenerateFrameExit() { __ cfi().RememberState(); if (!HasEmptyFrame()) { - // Deallocate the rest of the frame. - - __ DecreaseFrameSize(GetFrameSize() - FrameEntrySpillSize()); - // Restore callee-saved registers. - // Note that their cumulative size is small and they can be indexed using - // 16-bit offsets. - - // TODO: increment/decrement SP in one step instead of two or remove this comment. - - uint32_t ofs = 0; - bool unaligned_float = FrameEntrySpillSize() & 0x7; - bool fpu_32bit = isa_features_.Is32BitFloatingPoint(); - - for (size_t i = 0; i < arraysize(kFpuCalleeSaves); ++i) { - FRegister reg = kFpuCalleeSaves[i]; - if (allocated_registers_.ContainsFloatingPointRegister(reg)) { - if (unaligned_float) { - if (fpu_32bit) { - __ Lwc1(reg, SP, ofs); - __ Lwc1(static_cast<FRegister>(reg + 1), SP, ofs + 4); - } else { - __ Lwc1(reg, SP, ofs); - __ Lw(TMP, SP, ofs + 4); - __ Mthc1(TMP, reg); - } - } else { - __ Ldc1(reg, SP, ofs); - } - ofs += kMipsDoublewordSize; - // TODO: __ cfi().Restore(DWARFReg(reg)); - } - } - for (size_t i = 0; i < arraysize(kCoreCalleeSaves); ++i) { - Register reg = kCoreCalleeSaves[i]; - if (allocated_registers_.ContainsCoreRegister(reg)) { - __ Lw(reg, SP, ofs); - ofs += kMipsWordSize; + // For better instruction scheduling restore RA before other registers. + uint32_t ofs = GetFrameSize(); + for (uint32_t mask = core_spill_mask_; mask != 0; ) { + Register reg = static_cast<Register>(MostSignificantBit(mask)); + mask ^= 1u << reg; + ofs -= kMipsWordSize; + // The ZERO register is only included for alignment. + if (reg != ZERO) { + __ LoadFromOffset(kLoadWord, reg, SP, ofs); __ cfi().Restore(DWARFReg(reg)); } } - DCHECK_EQ(ofs, FrameEntrySpillSize()); - __ DecreaseFrameSize(ofs); + for (uint32_t mask = fpu_spill_mask_; mask != 0; ) { + FRegister reg = static_cast<FRegister>(MostSignificantBit(mask)); + mask ^= 1u << reg; + ofs -= kMipsDoublewordSize; + __ LoadDFromOffset(reg, SP, ofs); + // TODO: __ cfi().Restore(DWARFReg(reg)); + } + + __ DecreaseFrameSize(GetFrameSize()); } __ Jr(RA); diff --git a/compiler/optimizing/code_generator_mips.h b/compiler/optimizing/code_generator_mips.h index 5e6fec8cf5..46fe3016c4 100644 --- a/compiler/optimizing/code_generator_mips.h +++ b/compiler/optimizing/code_generator_mips.h @@ -262,6 +262,7 @@ class CodeGeneratorMIPS : public CodeGenerator { OptimizingCompilerStats* stats = nullptr); virtual ~CodeGeneratorMIPS() {} + void ComputeSpillMask() OVERRIDE; void GenerateFrameEntry() OVERRIDE; void GenerateFrameExit() OVERRIDE; diff --git a/compiler/optimizing/optimizing_cfi_test_expected.inc b/compiler/optimizing/optimizing_cfi_test_expected.inc index fc66823b04..764160adce 100644 --- a/compiler/optimizing/optimizing_cfi_test_expected.inc +++ b/compiler/optimizing/optimizing_cfi_test_expected.inc @@ -140,53 +140,43 @@ static constexpr uint8_t expected_cfi_kX86_64[] = { // 0x0000002d: .cfi_def_cfa_offset: 64 static constexpr uint8_t expected_asm_kMips[] = { - 0xE4, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xBF, 0xAF, 0x14, 0x00, 0xB1, 0xAF, - 0x10, 0x00, 0xB0, 0xAF, 0x08, 0x00, 0xB6, 0xE7, 0x0C, 0x00, 0xB7, 0xE7, - 0x00, 0x00, 0xB4, 0xE7, 0x04, 0x00, 0xB5, 0xE7, 0xDC, 0xFF, 0xBD, 0x27, - 0x00, 0x00, 0xA4, 0xAF, 0x24, 0x00, 0xBD, 0x27, 0x00, 0x00, 0xB4, 0xC7, - 0x04, 0x00, 0xB5, 0xC7, 0x08, 0x00, 0xB6, 0xC7, 0x0C, 0x00, 0xB7, 0xC7, - 0x10, 0x00, 0xB0, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xBF, 0x8F, - 0x1C, 0x00, 0xBD, 0x27, 0x09, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, + 0xC0, 0xFF, 0xBD, 0x27, 0x3C, 0x00, 0xBF, 0xAF, 0x38, 0x00, 0xB1, 0xAF, + 0x34, 0x00, 0xB0, 0xAF, 0x28, 0x00, 0xB6, 0xF7, 0x20, 0x00, 0xB4, 0xF7, + 0x00, 0x00, 0xA4, 0xAF, 0x3C, 0x00, 0xBF, 0x8F, 0x38, 0x00, 0xB1, 0x8F, + 0x34, 0x00, 0xB0, 0x8F, 0x28, 0x00, 0xB6, 0xD7, 0x20, 0x00, 0xB4, 0xD7, + 0x40, 0x00, 0xBD, 0x27, 0x09, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, }; static constexpr uint8_t expected_cfi_kMips[] = { - 0x44, 0x0E, 0x1C, 0x44, 0x9F, 0x01, 0x44, 0x91, 0x02, 0x44, 0x90, 0x03, - 0x54, 0x0E, 0x40, 0x44, 0x0A, 0x44, 0x0E, 0x1C, 0x54, 0xD0, 0x44, 0xD1, - 0x44, 0xDF, 0x44, 0x0E, 0x00, 0x48, 0x0B, 0x0E, 0x40, + 0x44, 0x0E, 0x40, 0x44, 0x9F, 0x01, 0x44, 0x91, 0x02, 0x44, 0x90, 0x03, + 0x4C, 0x0A, 0x44, 0xDF, 0x44, 0xD1, 0x44, 0xD0, 0x4C, 0x0E, 0x00, 0x48, + 0x0B, 0x0E, 0x40, }; -// 0x00000000: addiu r29, r29, -28 -// 0x00000004: .cfi_def_cfa_offset: 28 -// 0x00000004: sw r31, +24(r29) +// 0x00000000: addiu r29, r29, -64 +// 0x00000004: .cfi_def_cfa_offset: 64 +// 0x00000004: sw r31, +60(r29) // 0x00000008: .cfi_offset: r31 at cfa-4 -// 0x00000008: sw r17, +20(r29) +// 0x00000008: sw r17, +56(r29) // 0x0000000c: .cfi_offset: r17 at cfa-8 -// 0x0000000c: sw r16, +16(r29) +// 0x0000000c: sw r16, +52(r29) // 0x00000010: .cfi_offset: r16 at cfa-12 -// 0x00000010: swc1 f22, +8(r29) -// 0x00000014: swc1 f23, +12(r29) -// 0x00000018: swc1 f20, +0(r29) -// 0x0000001c: swc1 f21, +4(r29) -// 0x00000020: addiu r29, r29, -36 -// 0x00000024: .cfi_def_cfa_offset: 64 -// 0x00000024: sw r4, +0(r29) -// 0x00000028: .cfi_remember_state -// 0x00000028: addiu r29, r29, 36 -// 0x0000002c: .cfi_def_cfa_offset: 28 -// 0x0000002c: lwc1 f20, +0(r29) -// 0x00000030: lwc1 f21, +4(r29) -// 0x00000034: lwc1 f22, +8(r29) -// 0x00000038: lwc1 f23, +12(r29) -// 0x0000003c: lw r16, +16(r29) -// 0x00000040: .cfi_restore: r16 -// 0x00000040: lw r17, +20(r29) -// 0x00000044: .cfi_restore: r17 -// 0x00000044: lw r31, +24(r29) -// 0x00000048: .cfi_restore: r31 -// 0x00000048: addiu r29, r29, 28 -// 0x0000004c: .cfi_def_cfa_offset: 0 -// 0x0000004c: jr r31 -// 0x00000050: nop -// 0x00000054: .cfi_restore_state -// 0x00000054: .cfi_def_cfa_offset: 64 +// 0x00000010: sdc1 f22, +40(r29) +// 0x00000014: sdc1 f20, +32(r29) +// 0x00000018: sw r4, +0(r29) +// 0x0000001c: .cfi_remember_state +// 0x0000001c: lw r31, +60(r29) +// 0x00000020: .cfi_restore: r31 +// 0x00000020: lw r17, +56(r29) +// 0x00000024: .cfi_restore: r17 +// 0x00000024: lw r16, +52(r29) +// 0x00000028: .cfi_restore: r16 +// 0x00000028: ldc1 f22, +40(r29) +// 0x0000002c: ldc1 f20, +32(r29) +// 0x00000030: addiu r29, r29, 64 +// 0x00000034: .cfi_def_cfa_offset: 0 +// 0x00000034: jr r31 +// 0x00000038: nop +// 0x0000003c: .cfi_restore_state +// 0x0000003c: .cfi_def_cfa_offset: 64 static constexpr uint8_t expected_asm_kMips64[] = { 0xD8, 0xFF, 0xBD, 0x67, 0x20, 0x00, 0xBF, 0xFF, 0x18, 0x00, 0xB1, 0xFF, @@ -349,75 +339,65 @@ static constexpr uint8_t expected_cfi_kThumb2_adjust[] = { // 0x00000098: .cfi_def_cfa_offset: 64 static constexpr uint8_t expected_asm_kMips_adjust_head[] = { - 0xE4, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xBF, 0xAF, 0x14, 0x00, 0xB1, 0xAF, - 0x10, 0x00, 0xB0, 0xAF, 0x08, 0x00, 0xB6, 0xE7, 0x0C, 0x00, 0xB7, 0xE7, - 0x00, 0x00, 0xB4, 0xE7, 0x04, 0x00, 0xB5, 0xE7, 0xDC, 0xFF, 0xBD, 0x27, + 0xC0, 0xFF, 0xBD, 0x27, 0x3C, 0x00, 0xBF, 0xAF, 0x38, 0x00, 0xB1, 0xAF, + 0x34, 0x00, 0xB0, 0xAF, 0x28, 0x00, 0xB6, 0xF7, 0x20, 0x00, 0xB4, 0xF7, 0x00, 0x00, 0xA4, 0xAF, 0x08, 0x00, 0x04, 0x14, 0xFC, 0xFF, 0xBD, 0x27, 0x00, 0x00, 0xBF, 0xAF, 0x00, 0x00, 0x10, 0x04, 0x02, 0x00, 0x01, 0x3C, 0x18, 0x00, 0x21, 0x34, 0x21, 0x08, 0x3F, 0x00, 0x00, 0x00, 0xBF, 0x8F, 0x09, 0x00, 0x20, 0x00, 0x04, 0x00, 0xBD, 0x27, }; static constexpr uint8_t expected_asm_kMips_adjust_tail[] = { - 0x24, 0x00, 0xBD, 0x27, 0x00, 0x00, 0xB4, 0xC7, 0x04, 0x00, 0xB5, 0xC7, - 0x08, 0x00, 0xB6, 0xC7, 0x0C, 0x00, 0xB7, 0xC7, 0x10, 0x00, 0xB0, 0x8F, - 0x14, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xBF, 0x8F, 0x1C, 0x00, 0xBD, 0x27, + 0x3C, 0x00, 0xBF, 0x8F, 0x38, 0x00, 0xB1, 0x8F, 0x34, 0x00, 0xB0, 0x8F, + 0x28, 0x00, 0xB6, 0xD7, 0x20, 0x00, 0xB4, 0xD7, 0x40, 0x00, 0xBD, 0x27, 0x09, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, }; static constexpr uint8_t expected_cfi_kMips_adjust[] = { - 0x44, 0x0E, 0x1C, 0x44, 0x9F, 0x01, 0x44, 0x91, 0x02, 0x44, 0x90, 0x03, - 0x54, 0x0E, 0x40, 0x4C, 0x0E, 0x44, 0x60, 0x0E, 0x40, 0x04, 0x04, 0x00, - 0x02, 0x00, 0x0A, 0x44, 0x0E, 0x1C, 0x54, 0xD0, 0x44, 0xD1, 0x44, 0xDF, - 0x44, 0x0E, 0x00, 0x48, 0x0B, 0x0E, 0x40, + 0x44, 0x0E, 0x40, 0x44, 0x9F, 0x01, 0x44, 0x91, 0x02, 0x44, 0x90, 0x03, + 0x54, 0x0E, 0x44, 0x60, 0x0E, 0x40, 0x04, 0x04, 0x00, 0x02, 0x00, 0x0A, + 0x44, 0xDF, 0x44, 0xD1, 0x44, 0xD0, 0x4C, 0x0E, 0x00, 0x48, 0x0B, 0x0E, + 0x40, }; -// 0x00000000: addiu r29, r29, -28 -// 0x00000004: .cfi_def_cfa_offset: 28 -// 0x00000004: sw r31, +24(r29) +// 0x00000000: addiu r29, r29, -64 +// 0x00000004: .cfi_def_cfa_offset: 64 +// 0x00000004: sw r31, +60(r29) // 0x00000008: .cfi_offset: r31 at cfa-4 -// 0x00000008: sw r17, +20(r29) +// 0x00000008: sw r17, +56(r29) // 0x0000000c: .cfi_offset: r17 at cfa-8 -// 0x0000000c: sw r16, +16(r29) +// 0x0000000c: sw r16, +52(r29) // 0x00000010: .cfi_offset: r16 at cfa-12 -// 0x00000010: swc1 f22, +8(r29) -// 0x00000014: swc1 f23, +12(r29) -// 0x00000018: swc1 f20, +0(r29) -// 0x0000001c: swc1 f21, +4(r29) -// 0x00000020: addiu r29, r29, -36 -// 0x00000024: .cfi_def_cfa_offset: 64 -// 0x00000024: sw r4, +0(r29) -// 0x00000028: bne r0, r4, 0x0000004c ; +36 -// 0x0000002c: addiu r29, r29, -4 -// 0x00000030: .cfi_def_cfa_offset: 68 -// 0x00000030: sw r31, +0(r29) -// 0x00000034: bltzal r0, 0x00000038 ; +4 -// 0x00000038: lui r1, 0x20000 -// 0x0000003c: ori r1, r1, 24 -// 0x00000040: addu r1, r1, r31 -// 0x00000044: lw r31, +0(r29) -// 0x00000048: jr r1 -// 0x0000004c: addiu r29, r29, 4 -// 0x00000050: .cfi_def_cfa_offset: 64 -// 0x00000050: nop +// 0x00000010: sdc1 f22, +40(r29) +// 0x00000014: sdc1 f20, +32(r29) +// 0x00000018: sw r4, +0(r29) +// 0x0000001c: bne r0, r4, 0x00000040 ; +36 +// 0x00000020: addiu r29, r29, -4 +// 0x00000024: .cfi_def_cfa_offset: 68 +// 0x00000024: sw r31, +0(r29) +// 0x00000028: bltzal r0, 0x0000002c ; +4 +// 0x0000002c: lui r1, 0x20000 +// 0x00000030: ori r1, r1, 24 +// 0x00000034: addu r1, r1, r31 +// 0x00000038: lw r31, +0(r29) +// 0x0000003c: jr r1 +// 0x00000040: addiu r29, r29, 4 +// 0x00000044: .cfi_def_cfa_offset: 64 +// 0x00000044: nop // ... -// 0x00020050: nop -// 0x00020054: .cfi_remember_state -// 0x00020054: addiu r29, r29, 36 -// 0x00020058: .cfi_def_cfa_offset: 28 -// 0x00020058: lwc1 f20, +0(r29) -// 0x0002005c: lwc1 f21, +4(r29) -// 0x00020060: lwc1 f22, +8(r29) -// 0x00020064: lwc1 f23, +12(r29) -// 0x00020068: lw r16, +16(r29) -// 0x0002006c: .cfi_restore: r16 -// 0x0002006c: lw r17, +20(r29) -// 0x00020070: .cfi_restore: r17 -// 0x00020070: lw r31, +24(r29) -// 0x00020074: .cfi_restore: r31 -// 0x00020074: addiu r29, r29, 28 -// 0x00020078: .cfi_def_cfa_offset: 0 -// 0x00020078: jr r31 -// 0x0002007c: nop -// 0x00020080: .cfi_restore_state -// 0x00020080: .cfi_def_cfa_offset: 64 +// 0x00020044: nop +// 0x00020048: .cfi_remember_state +// 0x00020048: lw r31, +60(r29) +// 0x0002004c: .cfi_restore: r31 +// 0x0002004c: lw r17, +56(r29) +// 0x00020050: .cfi_restore: r17 +// 0x00020050: lw r16, +52(r29) +// 0x00020054: .cfi_restore: r16 +// 0x00020054: ldc1 f22, +40(r29) +// 0x00020058: ldc1 f20, +32(r29) +// 0x0002005c: addiu r29, r29, 64 +// 0x00020060: .cfi_def_cfa_offset: 0 +// 0x00020060: jr r31 +// 0x00020064: nop +// 0x00020068: .cfi_restore_state +// 0x00020068: .cfi_def_cfa_offset: 64 static constexpr uint8_t expected_asm_kMips64_adjust_head[] = { 0xD8, 0xFF, 0xBD, 0x67, 0x20, 0x00, 0xBF, 0xFF, 0x18, 0x00, 0xB1, 0xFF, |