diff options
author | Calin Juravle <calin@google.com> | 2014-11-11 15:38:19 +0000 |
---|---|---|
committer | Calin Juravle <calin@google.com> | 2014-11-12 18:38:49 +0000 |
commit | f97f9fbfdf7f2e23c662f21081fadee6af37809d (patch) | |
tree | aa5c7b6d42fc1dcd26f4a4f4d75fa488c575091a /compiler/optimizing | |
parent | 0eaf65edf1b2af63a3eeb77ee1864d84d3154d1e (diff) | |
download | android_art-f97f9fbfdf7f2e23c662f21081fadee6af37809d.tar.gz android_art-f97f9fbfdf7f2e23c662f21081fadee6af37809d.tar.bz2 android_art-f97f9fbfdf7f2e23c662f21081fadee6af37809d.zip |
[optimizing compiler] add HTemporary support for long and doubles
Change-Id: I5247ecd71d0193050484b7632c804c9bfd20f924
Diffstat (limited to 'compiler/optimizing')
-rw-r--r-- | compiler/optimizing/builder.cc | 40 | ||||
-rw-r--r-- | compiler/optimizing/code_generator.cc | 9 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 7 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 7 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 18 |
5 files changed, 49 insertions, 32 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index d3ac4e02cf..a3ca061512 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -41,25 +41,29 @@ namespace art { */ class Temporaries : public ValueObject { public: - Temporaries(HGraph* graph, size_t count) : graph_(graph), count_(count), index_(0) { - graph_->UpdateNumberOfTemporaries(count_); - } + explicit Temporaries(HGraph* graph) : graph_(graph), index_(0) {} void Add(HInstruction* instruction) { - // We currently only support vreg size temps. - DCHECK(instruction->GetType() != Primitive::kPrimLong - && instruction->GetType() != Primitive::kPrimDouble); - HInstruction* temp = new (graph_->GetArena()) HTemporary(index_++); + HInstruction* temp = new (graph_->GetArena()) HTemporary(index_); instruction->GetBlock()->AddInstruction(temp); + DCHECK(temp->GetPrevious() == instruction); + + size_t offset; + if (instruction->GetType() == Primitive::kPrimLong + || instruction->GetType() == Primitive::kPrimDouble) { + offset = 2; + } else { + offset = 1; + } + index_ += offset; + + graph_->UpdateTemporariesVRegSlots(index_); } private: HGraph* const graph_; - // The total number of temporaries that will be used. - const size_t count_; - // Current index in the temporary stack, updated by `Add`. size_t index_; }; @@ -408,7 +412,7 @@ bool HGraphBuilder::BuildInvoke(const Instruction& instruction, } size_t start_index = 0; - Temporaries temps(graph_, is_instance_call ? 1 : 0); + Temporaries temps(graph_); if (is_instance_call) { HInstruction* arg = LoadLocal(is_range ? register_index : args[0], Primitive::kPrimNot); HNullCheck* null_check = new (arena_) HNullCheck(arg, dex_offset); @@ -466,7 +470,7 @@ bool HGraphBuilder::BuildInstanceFieldAccess(const Instruction& instruction, HInstruction* object = LoadLocal(obj_reg, Primitive::kPrimNot); current_block_->AddInstruction(new (arena_) HNullCheck(object, dex_offset)); if (is_put) { - Temporaries temps(graph_, 1); + Temporaries temps(graph_); HInstruction* null_check = current_block_->GetLastInstruction(); // We need one temporary for the null check. temps.Add(null_check); @@ -531,7 +535,7 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction, if (is_put) { // We need to keep the class alive before loading the value. - Temporaries temps(graph_, 1); + Temporaries temps(graph_); temps.Add(cls); HInstruction* value = LoadLocal(source_or_dest_reg, field_type); DCHECK_EQ(value->GetType(), field_type); @@ -556,7 +560,7 @@ void HGraphBuilder::BuildCheckedDiv(uint16_t out_reg, HInstruction* second = second_is_lit ? GetIntConstant(second_reg) : LoadLocal(second_reg, type); if (!second->IsIntConstant() || (second->AsIntConstant()->GetValue() == 0)) { second = new (arena_) HDivZeroCheck(second, dex_offset); - Temporaries temps(graph_, 1); + Temporaries temps(graph_); current_block_->AddInstruction(second); temps.Add(current_block_->GetLastInstruction()); } @@ -574,7 +578,7 @@ void HGraphBuilder::BuildArrayAccess(const Instruction& instruction, uint8_t index_reg = instruction.VRegC_23x(); // We need one temporary for the null check, one for the index, and one for the length. - Temporaries temps(graph_, 3); + Temporaries temps(graph_); HInstruction* object = LoadLocal(array_reg, Primitive::kPrimNot); object = new (arena_) HNullCheck(object, dex_offset); @@ -618,7 +622,7 @@ void HGraphBuilder::BuildFilledNewArray(uint32_t dex_offset, bool is_reference_array = (primitive == 'L') || (primitive == '['); Primitive::Type type = is_reference_array ? Primitive::kPrimNot : Primitive::kPrimInt; - Temporaries temps(graph_, 1); + Temporaries temps(graph_); temps.Add(object); for (size_t i = 0; i < number_of_vreg_arguments; ++i) { HInstruction* value = LoadLocal(is_range ? register_index + i : args[i], type); @@ -644,7 +648,7 @@ void HGraphBuilder::BuildFillArrayData(HInstruction* object, } void HGraphBuilder::BuildFillArrayData(const Instruction& instruction, uint32_t dex_offset) { - Temporaries temps(graph_, 1); + Temporaries temps(graph_); HInstruction* array = LoadLocal(instruction.VRegA_31t(), Primitive::kPrimNot); HNullCheck* null_check = new (arena_) HNullCheck(array, dex_offset); current_block_->AddInstruction(null_check); @@ -727,7 +731,7 @@ bool HGraphBuilder::BuildTypeCheck(const Instruction& instruction, HLoadClass* cls = new (arena_) HLoadClass(type_index, is_referrers_class, dex_offset); current_block_->AddInstruction(cls); // The class needs a temporary before being used by the type check. - Temporaries temps(graph_, 1); + Temporaries temps(graph_); temps.Add(cls); if (instruction.Opcode() == Instruction::INSTANCE_OF) { current_block_->AddInstruction( diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index 9d172638e1..abbb5244ee 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -51,7 +51,7 @@ void CodeGenerator::CompileBaseline(CodeAllocator* allocator, bool is_leaf) { MarkNotLeaf(); } ComputeFrameSize(GetGraph()->GetNumberOfLocalVRegs() - + GetGraph()->GetNumberOfTemporaries() + + GetGraph()->GetTemporariesVRegSlots() + 1 /* filler */, 0, /* the baseline compiler does not have live registers at slow path */ GetGraph()->GetMaximumNumberOfOutVRegs() @@ -150,12 +150,15 @@ void CodeGenerator::ComputeFrameSize(size_t number_of_spill_slots, Location CodeGenerator::GetTemporaryLocation(HTemporary* temp) const { uint16_t number_of_locals = GetGraph()->GetNumberOfLocalVRegs(); + // The type of the previous instruction tells us if we need a single or double stack slot. + Primitive::Type type = temp->GetType(); + int32_t temp_size = (type == Primitive::kPrimLong) || (type == Primitive::kPrimDouble) ? 2 : 1; // Use the temporary region (right below the dex registers). int32_t slot = GetFrameSize() - FrameEntrySpillSize() - kVRegSize // filler - (number_of_locals * kVRegSize) - - ((1 + temp->GetIndex()) * kVRegSize); - return Location::StackSlot(slot); + - ((temp_size + temp->GetIndex()) * kVRegSize); + return temp_size == 2 ? Location::DoubleStackSlot(slot) : Location::StackSlot(slot); } int32_t CodeGenerator::GetStackSlot(HLocal* local) const { diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index 56546c2901..87955ebae5 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -824,7 +824,12 @@ void CodeGeneratorARM::Move(HInstruction* instruction, Location location, HInstr } } else if (instruction->IsTemporary()) { Location temp_location = GetTemporaryLocation(instruction->AsTemporary()); - Move32(location, temp_location); + if (temp_location.IsStackSlot()) { + Move32(location, temp_location); + } else { + DCHECK(temp_location.IsDoubleStackSlot()); + Move64(location, temp_location); + } } else { DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary()); switch (instruction->GetType()) { diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index d470345765..d7ce38753f 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -686,7 +686,12 @@ void CodeGeneratorX86::Move(HInstruction* instruction, Location location, HInstr } } else if (instruction->IsTemporary()) { Location temp_location = GetTemporaryLocation(instruction->AsTemporary()); - Move32(location, temp_location); + if (temp_location.IsStackSlot()) { + Move32(location, temp_location); + } else { + DCHECK(temp_location.IsDoubleStackSlot()); + Move64(location, temp_location); + } } else if (instruction->IsLoadLocal()) { int slot = GetStackSlot(instruction->AsLoadLocal()->GetLocal()); switch (instruction->GetType()) { diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 6224a11f24..59fac527ce 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -90,7 +90,7 @@ class HGraph : public ArenaObject<kArenaAllocMisc> { maximum_number_of_out_vregs_(0), number_of_vregs_(0), number_of_in_vregs_(0), - number_of_temporaries_(0), + temporaries_vreg_slots_(0), current_instruction_id_(0) {} ArenaAllocator* GetArena() const { return arena_; } @@ -129,12 +129,12 @@ class HGraph : public ArenaObject<kArenaAllocMisc> { maximum_number_of_out_vregs_ = std::max(new_value, maximum_number_of_out_vregs_); } - void UpdateNumberOfTemporaries(size_t count) { - number_of_temporaries_ = std::max(count, number_of_temporaries_); + void UpdateTemporariesVRegSlots(size_t slots) { + temporaries_vreg_slots_ = std::max(slots, temporaries_vreg_slots_); } - size_t GetNumberOfTemporaries() const { - return number_of_temporaries_; + size_t GetTemporariesVRegSlots() const { + return temporaries_vreg_slots_; } void SetNumberOfVRegs(uint16_t number_of_vregs) { @@ -192,8 +192,8 @@ class HGraph : public ArenaObject<kArenaAllocMisc> { // The number of virtual registers used by parameters of this method. uint16_t number_of_in_vregs_; - // The number of temporaries that will be needed for the baseline compiler. - size_t number_of_temporaries_; + // Number of vreg size slots that the temporaries use (used in baseline compiler). + size_t temporaries_vreg_slots_; // The current id to assign to a newly added instruction. See HInstruction.id_. int current_instruction_id_; @@ -2158,8 +2158,8 @@ class HBoundsCheck : public HExpression<2> { * Some DEX instructions are folded into multiple HInstructions that need * to stay live until the last HInstruction. This class * is used as a marker for the baseline compiler to ensure its preceding - * HInstruction stays live. `index` is the temporary number that is used - * for knowing the stack offset where to store the instruction. + * HInstruction stays live. `index` represents the stack location index of the + * instruction (the actual offset is computed as index * vreg_size). */ class HTemporary : public HTemplateInstruction<0> { public: |