diff options
author | Alexandre Rames <alexandre.rames@arm.com> | 2014-11-07 17:13:31 +0000 |
---|---|---|
committer | Alexandre Rames <alexandre.rames@arm.com> | 2014-11-10 17:31:38 +0000 |
commit | fc19de8b201475231751b9df08fce01a093e5c2b (patch) | |
tree | 7c0e9c923a37d059f1707156d69f4908aca308ac /compiler/optimizing | |
parent | a89086e3be94fb262c4c4feb15241b30616c3b8f (diff) | |
download | android_art-fc19de8b201475231751b9df08fce01a093e5c2b.tar.gz android_art-fc19de8b201475231751b9df08fce01a093e5c2b.tar.bz2 android_art-fc19de8b201475231751b9df08fce01a093e5c2b.zip |
Opt compiler: Add arm64 support for a few more IRs.
Change-Id: I781ddcbc61eb2b04ae80b1c7697e1ed5694bd5b9
Diffstat (limited to 'compiler/optimizing')
-rw-r--r-- | compiler/optimizing/code_generator_arm64.cc | 427 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm64.h | 7 |
2 files changed, 304 insertions, 130 deletions
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index c57c68c75f..4dc836f412 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -392,51 +392,6 @@ void CodeGeneratorARM64::Bind(HBasicBlock* block) { __ Bind(GetLabelOf(block)); } -void CodeGeneratorARM64::MoveHelper(Location destination, - Location source, - Primitive::Type type) { - if (source.Equals(destination)) { - return; - } - if (destination.IsRegister()) { - Register dst = RegisterFrom(destination, type); - if (source.IsStackSlot() || source.IsDoubleStackSlot()) { - DCHECK(dst.Is64Bits() == source.IsDoubleStackSlot()); - __ Ldr(dst, StackOperandFrom(source)); - } else { - __ Mov(dst, OperandFrom(source, type)); - } - } else if (destination.IsFpuRegister()) { - FPRegister dst = FPRegisterFrom(destination, type); - if (source.IsStackSlot() || source.IsDoubleStackSlot()) { - DCHECK(dst.Is64Bits() == source.IsDoubleStackSlot()); - __ Ldr(dst, StackOperandFrom(source)); - } else if (source.IsFpuRegister()) { - __ Fmov(dst, FPRegisterFrom(source, type)); - } else { - HConstant* cst = source.GetConstant(); - if (cst->IsFloatConstant()) { - __ Fmov(dst, cst->AsFloatConstant()->GetValue()); - } else { - DCHECK(cst->IsDoubleConstant()); - __ Fmov(dst, cst->AsDoubleConstant()->GetValue()); - } - } - } else { - DCHECK(destination.IsStackSlot() || destination.IsDoubleStackSlot()); - if (source.IsRegister()) { - __ Str(RegisterFrom(source, type), StackOperandFrom(destination)); - } else if (source.IsFpuRegister()) { - __ Str(FPRegisterFrom(source, type), StackOperandFrom(destination)); - } else { - UseScratchRegisterScope temps(assembler_.vixl_masm_); - Register temp = destination.IsDoubleStackSlot() ? temps.AcquireX() : temps.AcquireW(); - __ Ldr(temp, StackOperandFrom(source)); - __ Str(temp, StackOperandFrom(destination)); - } - } -} - void CodeGeneratorARM64::Move(HInstruction* instruction, Location location, HInstruction* move_for) { @@ -567,8 +522,107 @@ void CodeGeneratorARM64::DumpFloatingPointRegister(std::ostream& stream, int reg stream << Arm64ManagedRegister::FromDRegister(DRegister(reg)); } +void CodeGeneratorARM64::MoveHelper(Location destination, + Location source, + Primitive::Type type) { + if (source.Equals(destination)) { + return; + } + if (destination.IsRegister()) { + Register dst = RegisterFrom(destination, type); + if (source.IsStackSlot() || source.IsDoubleStackSlot()) { + DCHECK(dst.Is64Bits() == source.IsDoubleStackSlot()); + __ Ldr(dst, StackOperandFrom(source)); + } else { + __ Mov(dst, OperandFrom(source, type)); + } + } else if (destination.IsFpuRegister()) { + FPRegister dst = FPRegisterFrom(destination, type); + if (source.IsStackSlot() || source.IsDoubleStackSlot()) { + DCHECK(dst.Is64Bits() == source.IsDoubleStackSlot()); + __ Ldr(dst, StackOperandFrom(source)); + } else if (source.IsFpuRegister()) { + __ Fmov(dst, FPRegisterFrom(source, type)); + } else { + HConstant* cst = source.GetConstant(); + if (cst->IsFloatConstant()) { + __ Fmov(dst, cst->AsFloatConstant()->GetValue()); + } else { + DCHECK(cst->IsDoubleConstant()); + __ Fmov(dst, cst->AsDoubleConstant()->GetValue()); + } + } + } else { + DCHECK(destination.IsStackSlot() || destination.IsDoubleStackSlot()); + if (source.IsRegister()) { + __ Str(RegisterFrom(source, type), StackOperandFrom(destination)); + } else if (source.IsFpuRegister()) { + __ Str(FPRegisterFrom(source, type), StackOperandFrom(destination)); + } else { + UseScratchRegisterScope temps(assembler_.vixl_masm_); + Register temp = destination.IsDoubleStackSlot() ? temps.AcquireX() : temps.AcquireW(); + __ Ldr(temp, StackOperandFrom(source)); + __ Str(temp, StackOperandFrom(destination)); + } + } +} + +void CodeGeneratorARM64::Load(Primitive::Type type, + vixl::Register dst, + const vixl::MemOperand& src) { + switch (type) { + case Primitive::kPrimBoolean: + __ Ldrb(dst, src); + break; + case Primitive::kPrimByte: + __ Ldrsb(dst, src); + break; + case Primitive::kPrimShort: + __ Ldrsh(dst, src); + break; + case Primitive::kPrimChar: + __ Ldrh(dst, src); + break; + case Primitive::kPrimInt: + case Primitive::kPrimNot: + case Primitive::kPrimLong: + DCHECK(dst.Is64Bits() == (type == Primitive::kPrimLong)); + __ Ldr(dst, src); + break; + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + case Primitive::kPrimVoid: + LOG(FATAL) << "Unreachable type " << type; + } +} + +void CodeGeneratorARM64::Store(Primitive::Type type, + vixl::Register rt, + const vixl::MemOperand& dst) { + switch (type) { + case Primitive::kPrimBoolean: + case Primitive::kPrimByte: + __ Strb(rt, dst); + break; + case Primitive::kPrimChar: + case Primitive::kPrimShort: + __ Strh(rt, dst); + break; + case Primitive::kPrimInt: + case Primitive::kPrimNot: + case Primitive::kPrimLong: + DCHECK(rt.Is64Bits() == (type == Primitive::kPrimLong)); + __ Str(rt, dst); + break; + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + case Primitive::kPrimVoid: + LOG(FATAL) << "Unreachable type " << type; + } +} + #undef __ -#define __ assembler_->vixl_masm_-> +#define __ GetAssembler()->vixl_masm_-> InstructionCodeGeneratorARM64::InstructionCodeGeneratorARM64(HGraph* graph, CodeGeneratorARM64* codegen) @@ -577,17 +631,12 @@ InstructionCodeGeneratorARM64::InstructionCodeGeneratorARM64(HGraph* graph, codegen_(codegen) {} #define FOR_EACH_UNIMPLEMENTED_INSTRUCTION(M) \ - M(ArrayGet) \ - M(ArraySet) \ M(ClinitCheck) \ - M(Div) \ M(DivZeroCheck) \ M(InvokeInterface) \ M(LoadClass) \ M(LoadException) \ M(LoadString) \ - M(Neg) \ - M(NewArray) \ M(ParallelMove) \ M(StaticFieldGet) \ M(StaticFieldSet) \ @@ -685,6 +734,37 @@ void InstructionCodeGeneratorARM64::VisitAdd(HAdd* instruction) { HandleAddSub(instruction); } +void LocationsBuilderARM64::VisitArrayGet(HArrayGet* instruction) { + LocationSummary* locations = + new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall); + locations->SetInAt(0, Location::RequiresRegister()); + locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); + locations->SetOut(Location::RequiresRegister()); +} + +void InstructionCodeGeneratorARM64::VisitArrayGet(HArrayGet* instruction) { + LocationSummary* locations = instruction->GetLocations(); + Primitive::Type type = instruction->GetType(); + Register obj = InputRegisterAt(instruction, 0); + Register out = OutputRegister(instruction); + Location index = locations->InAt(1); + size_t offset = mirror::Array::DataOffset(Primitive::ComponentSize(type)).Uint32Value(); + MemOperand source(obj); + UseScratchRegisterScope temps(GetAssembler()->vixl_masm_); + + if (index.IsConstant()) { + offset += Int64ConstantFrom(index) << Primitive::ComponentSizeShift(type); + source = MemOperand(obj, offset); + } else { + Register temp = temps.AcquireSameSizeAs(obj); + Register index_reg = RegisterFrom(index, Primitive::kPrimInt); + __ Add(temp, obj, Operand(index_reg, LSL, Primitive::ComponentSizeShift(type))); + source = MemOperand(temp, offset); + } + + codegen_->Load(type, out, source); +} + void LocationsBuilderARM64::VisitArrayLength(HArrayLength* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction); locations->SetInAt(0, Location::RequiresRegister()); @@ -696,6 +776,53 @@ void InstructionCodeGeneratorARM64::VisitArrayLength(HArrayLength* instruction) HeapOperand(InputRegisterAt(instruction, 0), mirror::Array::LengthOffset())); } +void LocationsBuilderARM64::VisitArraySet(HArraySet* instruction) { + Primitive::Type value_type = instruction->GetComponentType(); + bool is_object = value_type == Primitive::kPrimNot; + LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary( + instruction, is_object ? LocationSummary::kCall : LocationSummary::kNoCall); + if (is_object) { + InvokeRuntimeCallingConvention calling_convention; + locations->SetInAt(0, LocationFrom(calling_convention.GetRegisterAt(0))); + locations->SetInAt(1, LocationFrom(calling_convention.GetRegisterAt(1))); + locations->SetInAt(2, LocationFrom(calling_convention.GetRegisterAt(2))); + } else { + locations->SetInAt(0, Location::RequiresRegister()); + locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); + locations->SetInAt(2, Location::RequiresRegister()); + } +} + +void InstructionCodeGeneratorARM64::VisitArraySet(HArraySet* instruction) { + Primitive::Type value_type = instruction->GetComponentType(); + if (value_type == Primitive::kPrimNot) { + __ Ldr(lr, MemOperand(tr, QUICK_ENTRYPOINT_OFFSET(kArm64WordSize, pAputObject).Int32Value())); + __ Blr(lr); + codegen_->RecordPcInfo(instruction, instruction->GetDexPc()); + DCHECK(!codegen_->IsLeafMethod()); + } else { + LocationSummary* locations = instruction->GetLocations(); + Register obj = InputRegisterAt(instruction, 0); + Register value = InputRegisterAt(instruction, 2); + Location index = locations->InAt(1); + size_t offset = mirror::Array::DataOffset(Primitive::ComponentSize(value_type)).Uint32Value(); + MemOperand destination(obj); + UseScratchRegisterScope temps(GetAssembler()->vixl_masm_); + + if (index.IsConstant()) { + offset += Int64ConstantFrom(index) << Primitive::ComponentSizeShift(value_type); + destination = MemOperand(obj, offset); + } else { + Register temp = temps.AcquireSameSizeAs(obj); + Register index_reg = InputRegisterAt(instruction, 1); + __ Add(temp, obj, Operand(index_reg, LSL, Primitive::ComponentSizeShift(value_type))); + destination = MemOperand(temp, offset); + } + + codegen_->Store(value_type, value, destination); + } +} + void LocationsBuilderARM64::VisitCompare(HCompare* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall); @@ -763,6 +890,47 @@ void InstructionCodeGeneratorARM64::Visit##Name(H##Name* comp) { VisitCondition( FOR_EACH_CONDITION_INSTRUCTION(DEFINE_CONDITION_VISITORS) #undef FOR_EACH_CONDITION_INSTRUCTION +void LocationsBuilderARM64::VisitDiv(HDiv* div) { + LocationSummary* locations = + new (GetGraph()->GetArena()) LocationSummary(div, LocationSummary::kNoCall); + switch (div->GetResultType()) { + case Primitive::kPrimInt: + case Primitive::kPrimLong: + locations->SetInAt(0, Location::RequiresRegister()); + locations->SetInAt(1, Location::RequiresRegister()); + locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); + break; + + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + locations->SetInAt(0, Location::RequiresFpuRegister()); + locations->SetInAt(1, Location::RequiresFpuRegister()); + locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap); + break; + + default: + LOG(FATAL) << "Unexpected div type " << div->GetResultType(); + } +} + +void InstructionCodeGeneratorARM64::VisitDiv(HDiv* div) { + Primitive::Type type = div->GetResultType(); + switch (type) { + case Primitive::kPrimInt: + case Primitive::kPrimLong: + __ Sdiv(OutputRegister(div), InputRegisterAt(div, 0), InputRegisterAt(div, 1)); + break; + + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + __ Fdiv(OutputFPRegister(div), InputFPRegisterAt(div, 0), InputFPRegisterAt(div, 1)); + break; + + default: + LOG(FATAL) << "Unexpected div type " << type; + } +} + void LocationsBuilderARM64::VisitDoubleConstant(HDoubleConstant* constant) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant, LocationSummary::kNoCall); @@ -863,44 +1031,9 @@ void LocationsBuilderARM64::VisitInstanceFieldGet(HInstanceFieldGet* instruction } void InstructionCodeGeneratorARM64::VisitInstanceFieldGet(HInstanceFieldGet* instruction) { - Primitive::Type res_type = instruction->GetType(); - Register res = OutputRegister(instruction); - Register obj = InputRegisterAt(instruction, 0); - uint32_t offset = instruction->GetFieldOffset().Uint32Value(); - - switch (res_type) { - case Primitive::kPrimBoolean: { - __ Ldrb(res, MemOperand(obj, offset)); - break; - } - case Primitive::kPrimByte: { - __ Ldrsb(res, MemOperand(obj, offset)); - break; - } - case Primitive::kPrimShort: { - __ Ldrsh(res, MemOperand(obj, offset)); - break; - } - case Primitive::kPrimChar: { - __ Ldrh(res, MemOperand(obj, offset)); - break; - } - case Primitive::kPrimInt: - case Primitive::kPrimNot: - case Primitive::kPrimLong: { // TODO: support volatile. - DCHECK(res.IsX() == (res_type == Primitive::kPrimLong)); - __ Ldr(res, MemOperand(obj, offset)); - break; - } - - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: - LOG(FATAL) << "Unimplemented register res_type " << res_type; - break; - - case Primitive::kPrimVoid: - LOG(FATAL) << "Unreachable res_type " << res_type; - } + MemOperand field = MemOperand(InputRegisterAt(instruction, 0), + instruction->GetFieldOffset().Uint32Value()); + codegen_->Load(instruction->GetType(), OutputRegister(instruction), field); } void LocationsBuilderARM64::VisitInstanceFieldSet(HInstanceFieldSet* instruction) { @@ -910,43 +1043,12 @@ void LocationsBuilderARM64::VisitInstanceFieldSet(HInstanceFieldSet* instruction } void InstructionCodeGeneratorARM64::VisitInstanceFieldSet(HInstanceFieldSet* instruction) { - Register obj = InputRegisterAt(instruction, 0); + Primitive::Type field_type = instruction->GetFieldType(); Register value = InputRegisterAt(instruction, 1); - Primitive::Type field_type = instruction->InputAt(1)->GetType(); - uint32_t offset = instruction->GetFieldOffset().Uint32Value(); - - switch (field_type) { - case Primitive::kPrimBoolean: - case Primitive::kPrimByte: { - __ Strb(value, MemOperand(obj, offset)); - break; - } - - case Primitive::kPrimShort: - case Primitive::kPrimChar: { - __ Strh(value, MemOperand(obj, offset)); - break; - } - - case Primitive::kPrimInt: - case Primitive::kPrimNot: - case Primitive::kPrimLong: { - DCHECK(value.IsX() == (field_type == Primitive::kPrimLong)); - __ Str(value, MemOperand(obj, offset)); - - if (field_type == Primitive::kPrimNot) { - codegen_->MarkGCCard(obj, value); - } - break; - } - - case Primitive::kPrimFloat: - case Primitive::kPrimDouble: - LOG(FATAL) << "Unimplemented register type " << field_type; - break; - - case Primitive::kPrimVoid: - LOG(FATAL) << "Unreachable type " << field_type; + Register obj = InputRegisterAt(instruction, 0); + codegen_->Store(field_type, value, MemOperand(obj, instruction->GetFieldOffset().Uint32Value())); + if (field_type == Primitive::kPrimNot) { + codegen_->MarkGCCard(obj, value); } } @@ -1002,11 +1104,13 @@ void InstructionCodeGeneratorARM64::VisitInvokeStatic(HInvokeStatic* invoke) { // temp = method; __ Ldr(temp, MemOperand(sp, kCurrentMethodStackOffset)); // temp = temp->dex_cache_resolved_methods_; - __ Ldr(temp, MemOperand(temp.X(), mirror::ArtMethod::DexCacheResolvedMethodsOffset().SizeValue())); + __ Ldr(temp, MemOperand(temp.X(), + mirror::ArtMethod::DexCacheResolvedMethodsOffset().SizeValue())); // temp = temp[index_in_cache]; __ Ldr(temp, MemOperand(temp.X(), index_in_cache)); // lr = temp->entry_point_from_quick_compiled_code_; - __ Ldr(lr, MemOperand(temp.X(), mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().SizeValue())); + __ Ldr(lr, MemOperand(temp.X(), + mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().SizeValue())); // lr(); __ Blr(lr); @@ -1109,6 +1213,71 @@ void InstructionCodeGeneratorARM64::VisitMul(HMul* mul) { } } +void LocationsBuilderARM64::VisitNeg(HNeg* neg) { + LocationSummary* locations = + new (GetGraph()->GetArena()) LocationSummary(neg, LocationSummary::kNoCall); + switch (neg->GetResultType()) { + case Primitive::kPrimInt: + case Primitive::kPrimLong: { + locations->SetInAt(0, Location::RegisterOrConstant(neg->InputAt(0))); + locations->SetOut(Location::RequiresRegister()); + break; + } + + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + LOG(FATAL) << "Not yet implemented neg type " << neg->GetResultType(); + break; + + default: + LOG(FATAL) << "Unexpected neg type " << neg->GetResultType(); + } +} + +void InstructionCodeGeneratorARM64::VisitNeg(HNeg* neg) { + switch (neg->GetResultType()) { + case Primitive::kPrimInt: + case Primitive::kPrimLong: + __ Neg(OutputRegister(neg), InputOperandAt(neg, 0)); + break; + + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + LOG(FATAL) << "Not yet implemented neg type " << neg->GetResultType(); + break; + + default: + LOG(FATAL) << "Unexpected neg type " << neg->GetResultType(); + } +} + +void LocationsBuilderARM64::VisitNewArray(HNewArray* instruction) { + LocationSummary* locations = + new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); + InvokeRuntimeCallingConvention calling_convention; + locations->AddTemp(LocationFrom(calling_convention.GetRegisterAt(0))); + locations->AddTemp(LocationFrom(calling_convention.GetRegisterAt(1))); + locations->SetOut(LocationFrom(x0)); + locations->SetInAt(0, LocationFrom(calling_convention.GetRegisterAt(2))); +} + +void InstructionCodeGeneratorARM64::VisitNewArray(HNewArray* instruction) { + LocationSummary* locations = instruction->GetLocations(); + InvokeRuntimeCallingConvention calling_convention; + Register type_index = RegisterFrom(locations->GetTemp(0), Primitive::kPrimInt); + DCHECK(type_index.Is(w0)); + Register current_method = RegisterFrom(locations->GetTemp(1), Primitive::kPrimNot); + DCHECK(current_method.Is(w1)); + __ Ldr(current_method, MemOperand(sp, kCurrentMethodStackOffset)); + __ Mov(type_index, instruction->GetTypeIndex()); + int32_t quick_entrypoint_offset = + QUICK_ENTRYPOINT_OFFSET(kArm64WordSize, pAllocArrayWithAccessCheck).Int32Value(); + __ Ldr(lr, MemOperand(tr, quick_entrypoint_offset)); + __ Blr(lr); + codegen_->RecordPcInfo(instruction, instruction->GetDexPc()); + DCHECK(!codegen_->IsLeafMethod()); +} + void LocationsBuilderARM64::VisitNewInstance(HNewInstance* instruction) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall); @@ -1126,7 +1295,9 @@ void InstructionCodeGeneratorARM64::VisitNewInstance(HNewInstance* instruction) DCHECK(current_method.Is(w1)); __ Ldr(current_method, MemOperand(sp, kCurrentMethodStackOffset)); __ Mov(type_index, instruction->GetTypeIndex()); - __ Ldr(lr, MemOperand(tr, QUICK_ENTRYPOINT_OFFSET(kArm64WordSize, pAllocObjectWithAccessCheck).Int32Value())); + int32_t quick_entrypoint_offset = + QUICK_ENTRYPOINT_OFFSET(kArm64WordSize, pAllocObjectWithAccessCheck).Int32Value(); + __ Ldr(lr, MemOperand(tr, quick_entrypoint_offset)); __ Blr(lr); codegen_->RecordPcInfo(instruction, instruction->GetDexPc()); DCHECK(!codegen_->IsLeafMethod()); diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h index ad1f22195e..f2ead21e15 100644 --- a/compiler/optimizing/code_generator_arm64.h +++ b/compiler/optimizing/code_generator_arm64.h @@ -216,8 +216,6 @@ class CodeGeneratorARM64 : public CodeGenerator { return InstructionSet::kArm64; } - void MoveHelper(Location destination, Location source, Primitive::Type type); - void Initialize() OVERRIDE { HGraph* graph = GetGraph(); int length = graph->GetBlocks().Size(); @@ -227,6 +225,11 @@ class CodeGeneratorARM64 : public CodeGenerator { } } + // Code generation helpers. + void MoveHelper(Location destination, Location source, Primitive::Type type); + void Load(Primitive::Type type, vixl::Register dst, const vixl::MemOperand& src); + void Store(Primitive::Type type, vixl::Register rt, const vixl::MemOperand& dst); + private: // Labels for each block that will be compiled. vixl::Label* block_labels_; |