summaryrefslogtreecommitdiff
path: root/compiler/optimizing
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing')
-rw-r--r--compiler/optimizing/code_generator_mips.cc124
-rw-r--r--compiler/optimizing/code_generator_mips.h1
-rw-r--r--compiler/optimizing/nodes.cc21
-rw-r--r--compiler/optimizing/nodes.h1
-rw-r--r--compiler/optimizing/nodes_arm.h2
-rw-r--r--compiler/optimizing/nodes_x86.h2
-rw-r--r--compiler/optimizing/optimizing_cfi_test_expected.inc172
-rw-r--r--compiler/optimizing/optimizing_compiler.cc29
-rw-r--r--compiler/optimizing/select_generator.cc4
9 files changed, 157 insertions, 199 deletions
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index 928d685fbe..ed0767ed52 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -665,6 +665,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));
}
@@ -694,105 +706,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 435a869368..8c0bae628e 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/nodes.cc b/compiler/optimizing/nodes.cc
index 150d6b029b..ae3c4b01e6 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -785,22 +785,6 @@ void HBasicBlock::ReplaceAndRemoveInstructionWith(HInstruction* initial,
RemoveInstruction(initial);
}
-void HBasicBlock::MoveInstructionBefore(HInstruction* insn, HInstruction* cursor) {
- DCHECK(!cursor->IsPhi());
- DCHECK(!insn->IsPhi());
- DCHECK(!insn->IsControlFlow());
- DCHECK(insn->CanBeMoved());
- DCHECK(!insn->HasSideEffects());
-
- HBasicBlock* from_block = insn->GetBlock();
- HBasicBlock* to_block = cursor->GetBlock();
- DCHECK(from_block != to_block);
-
- from_block->RemoveInstruction(insn, /* ensure_safety */ false);
- insn->SetBlock(to_block);
- to_block->instructions_.InsertInstructionBefore(insn, cursor);
-}
-
static void Add(HInstructionList* instruction_list,
HBasicBlock* block,
HInstruction* instruction) {
@@ -1352,6 +1336,11 @@ std::ostream& operator<<(std::ostream& os, const HInstruction::InstructionKind&
}
void HInstruction::MoveBefore(HInstruction* cursor) {
+ DCHECK(!IsPhi());
+ DCHECK(!IsControlFlow());
+ DCHECK(CanBeMoved());
+ DCHECK(!cursor->IsPhi());
+
next_->previous_ = previous_;
if (previous_ != nullptr) {
previous_->next_ = next_;
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index da84afbb39..711a6c1b2d 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -1049,7 +1049,6 @@ class HBasicBlock : public ArenaObject<kArenaAllocBasicBlock> {
// Replace instruction `initial` with `replacement` within this block.
void ReplaceAndRemoveInstructionWith(HInstruction* initial,
HInstruction* replacement);
- void MoveInstructionBefore(HInstruction* insn, HInstruction* cursor);
void AddPhi(HPhi* phi);
void InsertPhiAfter(HPhi* instruction, HPhi* cursor);
// RemoveInstruction and RemovePhi delete a given instruction from the respective
diff --git a/compiler/optimizing/nodes_arm.h b/compiler/optimizing/nodes_arm.h
index 371e8ef6bb..d9f9740e73 100644
--- a/compiler/optimizing/nodes_arm.h
+++ b/compiler/optimizing/nodes_arm.h
@@ -26,6 +26,8 @@ class HArmDexCacheArraysBase FINAL : public HExpression<0> {
dex_file_(&dex_file),
element_offset_(static_cast<size_t>(-1)) { }
+ bool CanBeMoved() const OVERRIDE { return true; }
+
void UpdateElementOffset(size_t element_offset) {
// Use the lowest offset from the requested elements so that all offsets from
// this base are non-negative because our assemblers emit negative-offset loads
diff --git a/compiler/optimizing/nodes_x86.h b/compiler/optimizing/nodes_x86.h
index c3696b5936..fa479760fe 100644
--- a/compiler/optimizing/nodes_x86.h
+++ b/compiler/optimizing/nodes_x86.h
@@ -26,6 +26,8 @@ class HX86ComputeBaseMethodAddress FINAL : public HExpression<0> {
HX86ComputeBaseMethodAddress()
: HExpression(Primitive::kPrimInt, SideEffects::None(), kNoDexPc) {}
+ bool CanBeMoved() const OVERRIDE { return true; }
+
DECLARE_INSTRUCTION(X86ComputeBaseMethodAddress);
private:
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,
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 37197af460..c9a4bfe987 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -321,6 +321,7 @@ class OptimizingCompiler FINAL : public Compiler {
jobject class_loader,
const DexFile& dex_file,
Handle<mirror::DexCache> dex_cache,
+ ArtMethod* method,
bool osr) const;
std::unique_ptr<OptimizingCompilerStats> compilation_stats_;
@@ -614,6 +615,7 @@ CodeGenerator* OptimizingCompiler::TryCompile(ArenaAllocator* arena,
jobject class_loader,
const DexFile& dex_file,
Handle<mirror::DexCache> dex_cache,
+ ArtMethod* method,
bool osr) const {
MaybeRecordStat(MethodCompilationStat::kAttemptCompilation);
CompilerDriver* compiler_driver = GetCompilerDriver();
@@ -679,17 +681,30 @@ CodeGenerator* OptimizingCompiler::TryCompile(ArenaAllocator* arena,
osr);
const uint8_t* interpreter_metadata = nullptr;
- {
+ if (method == nullptr) {
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<1> hs(soa.Self());
Handle<mirror::ClassLoader> loader(hs.NewHandle(
soa.Decode<mirror::ClassLoader*>(class_loader)));
- ArtMethod* art_method = compiler_driver->ResolveMethod(
+ method = compiler_driver->ResolveMethod(
soa, dex_cache, loader, &dex_compilation_unit, method_idx, invoke_type);
- // We may not get a method, for example if its class is erroneous.
- if (art_method != nullptr) {
- graph->SetArtMethod(art_method);
- interpreter_metadata = art_method->GetQuickenedInfo();
+ }
+ // For AOT compilation, we may not get a method, for example if its class is erroneous.
+ // JIT should always have a method.
+ DCHECK(Runtime::Current()->IsAotCompiler() || method != nullptr);
+ if (method != nullptr) {
+ graph->SetArtMethod(method);
+ ScopedObjectAccess soa(Thread::Current());
+ interpreter_metadata = method->GetQuickenedInfo();
+ uint16_t type_index = method->GetDeclaringClass()->GetDexTypeIndex();
+
+ // Update the dex cache if the type is not in it yet. Note that under AOT,
+ // the verifier must have set it, but under JIT, there's no guarantee, as we
+ // don't necessarily run the verifier.
+ // The compiler and the compiler driver assume the compiling class is
+ // in the dex cache.
+ if (dex_cache->GetResolvedType(type_index) == nullptr) {
+ dex_cache->SetResolvedType(type_index, method->GetDeclaringClass());
}
}
@@ -798,6 +813,7 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item,
jclass_loader,
dex_file,
dex_cache,
+ nullptr,
/* osr */ false));
if (codegen.get() != nullptr) {
MaybeRecordStat(MethodCompilationStat::kCompiled);
@@ -884,6 +900,7 @@ bool OptimizingCompiler::JitCompile(Thread* self,
jclass_loader,
*dex_file,
dex_cache,
+ method,
osr));
if (codegen.get() == nullptr) {
return false;
diff --git a/compiler/optimizing/select_generator.cc b/compiler/optimizing/select_generator.cc
index e52476ea03..e409035d9d 100644
--- a/compiler/optimizing/select_generator.cc
+++ b/compiler/optimizing/select_generator.cc
@@ -96,10 +96,10 @@ void HSelectGenerator::Run() {
// TODO(dbrazdil): This puts an instruction between If and its condition.
// Implement moving of conditions to first users if possible.
if (!true_block->IsSingleGoto()) {
- true_block->MoveInstructionBefore(true_block->GetFirstInstruction(), if_instruction);
+ true_block->GetFirstInstruction()->MoveBefore(if_instruction);
}
if (!false_block->IsSingleGoto()) {
- false_block->MoveInstructionBefore(false_block->GetFirstInstruction(), if_instruction);
+ false_block->GetFirstInstruction()->MoveBefore(if_instruction);
}
DCHECK(true_block->IsSingleGoto());
DCHECK(false_block->IsSingleGoto());