summaryrefslogtreecommitdiffstats
path: root/compiler/optimizing/code_generator_arm.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing/code_generator_arm.cc')
-rw-r--r--compiler/optimizing/code_generator_arm.cc83
1 files changed, 33 insertions, 50 deletions
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index c4ba0fd3e5..1ca1cee275 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -49,9 +49,6 @@ static constexpr SRegister kRuntimeParameterFpuRegisters[] = { S0, S1, S2, S3 };
static constexpr size_t kRuntimeParameterFpuRegistersLength =
arraysize(kRuntimeParameterFpuRegisters);
-static constexpr DRegister DTMP = D7;
-static constexpr SRegister STMP = S14;
-
class InvokeRuntimeCallingConvention : public CallingConvention<Register, SRegister> {
public:
InvokeRuntimeCallingConvention()
@@ -387,8 +384,10 @@ size_t CodeGeneratorARM::RestoreFloatingPointRegister(size_t stack_index, uint32
}
CodeGeneratorARM::CodeGeneratorARM(HGraph* graph,
- const ArmInstructionSetFeatures* isa_features)
- : CodeGenerator(graph, kNumberOfCoreRegisters, kNumberOfSRegisters, kNumberOfRegisterPairs),
+ const ArmInstructionSetFeatures& isa_features,
+ const CompilerOptions& compiler_options)
+ : CodeGenerator(graph, kNumberOfCoreRegisters, kNumberOfSRegisters,
+ kNumberOfRegisterPairs, compiler_options),
block_labels_(graph->GetArena(), 0),
location_builder_(graph, this),
instruction_visitor_(graph, this),
@@ -475,11 +474,6 @@ void CodeGeneratorARM::SetupBlockedRegisters() const {
blocked_core_registers_[R10] = true;
blocked_core_registers_[R11] = true;
- // Don't allocate our temporary double register.
- blocked_fpu_registers_[STMP] = true;
- blocked_fpu_registers_[STMP + 1] = true;
- DCHECK_EQ(FromLowSToD(STMP), DTMP);
-
blocked_fpu_registers_[S16] = true;
blocked_fpu_registers_[S17] = true;
blocked_fpu_registers_[S18] = true;
@@ -793,7 +787,7 @@ void CodeGeneratorARM::Move(HInstruction* instruction, Location location, HInstr
__ StoreToOffset(kStoreWord, IP, SP, location.GetStackIndex());
}
} else {
- DCHECK(const_to_move->IsLongConstant()) << const_to_move;
+ DCHECK(const_to_move->IsLongConstant()) << const_to_move->DebugName();
int64_t value = const_to_move->AsLongConstant()->GetValue();
if (location.IsRegisterPair()) {
__ LoadImmediate(location.AsRegisterPairLow<Register>(), Low32Bits(value));
@@ -2616,7 +2610,7 @@ void LocationsBuilderARM::HandleFieldSet(HInstruction* instruction, const FieldI
bool is_wide = field_type == Primitive::kPrimLong || field_type == Primitive::kPrimDouble;
bool generate_volatile = field_info.IsVolatile()
&& is_wide
- && !codegen_->GetInstructionSetFeatures()->HasAtomicLdrdAndStrd();
+ && !codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
// Temporary registers for the write barrier.
// TODO: consider renaming StoreNeedsWriteBarrier to StoreNeedsGCMark.
if (CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1))) {
@@ -2649,7 +2643,7 @@ void InstructionCodeGeneratorARM::HandleFieldSet(HInstruction* instruction,
Location value = locations->InAt(1);
bool is_volatile = field_info.IsVolatile();
- bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures()->HasAtomicLdrdAndStrd();
+ bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
Primitive::Type field_type = field_info.GetFieldType();
uint32_t offset = field_info.GetFieldOffset().Uint32Value();
@@ -2738,7 +2732,7 @@ void LocationsBuilderARM::HandleFieldGet(HInstruction* instruction, const FieldI
bool generate_volatile = field_info.IsVolatile()
&& (field_info.GetFieldType() == Primitive::kPrimDouble)
- && !codegen_->GetInstructionSetFeatures()->HasAtomicLdrdAndStrd();
+ && !codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
if (generate_volatile) {
// Arm encoding have some additional constraints for ldrexd/strexd:
// - registers need to be consecutive
@@ -2759,7 +2753,7 @@ void InstructionCodeGeneratorARM::HandleFieldGet(HInstruction* instruction,
Register base = locations->InAt(0).AsRegister<Register>();
Location out = locations->Out();
bool is_volatile = field_info.IsVolatile();
- bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures()->HasAtomicLdrdAndStrd();
+ bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd();
Primitive::Type field_type = field_info.GetFieldType();
uint32_t offset = field_info.GetFieldOffset().Uint32Value();
@@ -2864,13 +2858,22 @@ void InstructionCodeGeneratorARM::VisitStaticFieldSet(HStaticFieldSet* instructi
void LocationsBuilderARM::VisitNullCheck(HNullCheck* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
- locations->SetInAt(0, Location::RequiresRegister());
+ Location loc = codegen_->GetCompilerOptions().GetImplicitNullChecks()
+ ? Location::RequiresRegister()
+ : Location::RegisterOrConstant(instruction->InputAt(0));
+ locations->SetInAt(0, loc);
if (instruction->HasUses()) {
locations->SetOut(Location::SameAsFirstInput());
}
}
-void InstructionCodeGeneratorARM::VisitNullCheck(HNullCheck* instruction) {
+void InstructionCodeGeneratorARM::GenerateImplicitNullCheck(HNullCheck* instruction) {
+ Location obj = instruction->GetLocations()->InAt(0);
+ __ LoadFromOffset(kLoadWord, IP, obj.AsRegister<Register>(), 0);
+ codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
+}
+
+void InstructionCodeGeneratorARM::GenerateExplicitNullCheck(HNullCheck* instruction) {
SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) NullCheckSlowPathARM(instruction);
codegen_->AddSlowPath(slow_path);
@@ -2887,6 +2890,14 @@ void InstructionCodeGeneratorARM::VisitNullCheck(HNullCheck* instruction) {
}
}
+void InstructionCodeGeneratorARM::VisitNullCheck(HNullCheck* instruction) {
+ if (codegen_->GetCompilerOptions().GetImplicitNullChecks()) {
+ GenerateImplicitNullCheck(instruction);
+ } else {
+ GenerateExplicitNullCheck(instruction);
+ }
+}
+
void LocationsBuilderARM::VisitArrayGet(HArrayGet* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
@@ -3302,15 +3313,6 @@ void ParallelMoveResolverARM::EmitMove(size_t index) {
DCHECK(destination.IsStackSlot());
__ StoreSToOffset(source.AsFpuRegister<SRegister>(), SP, destination.GetStackIndex());
}
- } else if (source.IsFpuRegisterPair()) {
- if (destination.IsFpuRegisterPair()) {
- __ vmovd(FromLowSToD(destination.AsFpuRegisterPairLow<SRegister>()),
- FromLowSToD(source.AsFpuRegisterPairLow<SRegister>()));
- } else {
- DCHECK(destination.IsDoubleStackSlot()) << destination;
- __ StoreDToOffset(FromLowSToD(source.AsFpuRegisterPairLow<SRegister>()),
- SP, destination.GetStackIndex());
- }
} else if (source.IsDoubleStackSlot()) {
if (destination.IsFpuRegisterPair()) {
__ LoadDFromOffset(FromLowSToD(destination.AsFpuRegisterPairLow<SRegister>()),
@@ -3383,9 +3385,9 @@ void ParallelMoveResolverARM::EmitSwap(size_t index) {
} else if (source.IsStackSlot() && destination.IsStackSlot()) {
Exchange(source.GetStackIndex(), destination.GetStackIndex());
} else if (source.IsFpuRegister() && destination.IsFpuRegister()) {
- __ vmovs(STMP, source.AsFpuRegister<SRegister>());
+ __ vmovrs(IP, source.AsFpuRegister<SRegister>());
__ vmovs(source.AsFpuRegister<SRegister>(), destination.AsFpuRegister<SRegister>());
- __ vmovs(destination.AsFpuRegister<SRegister>(), STMP);
+ __ vmovsr(destination.AsFpuRegister<SRegister>(), IP);
} else if (source.IsFpuRegister() || destination.IsFpuRegister()) {
SRegister reg = source.IsFpuRegister() ? source.AsFpuRegister<SRegister>()
: destination.AsFpuRegister<SRegister>();
@@ -3393,29 +3395,10 @@ void ParallelMoveResolverARM::EmitSwap(size_t index) {
? destination.GetStackIndex()
: source.GetStackIndex();
- __ vmovs(STMP, reg);
- __ LoadSFromOffset(reg, SP, mem);
- __ StoreSToOffset(STMP, SP, mem);
- } else if (source.IsFpuRegisterPair() && destination.IsFpuRegisterPair()) {
- __ vmovd(DTMP, FromLowSToD(source.AsFpuRegisterPairLow<SRegister>()));
- __ vmovd(FromLowSToD(source.AsFpuRegisterPairLow<SRegister>()),
- FromLowSToD(destination.AsFpuRegisterPairLow<SRegister>()));
- __ vmovd(FromLowSToD(destination.AsFpuRegisterPairLow<SRegister>()), DTMP);
- } else if (source.IsFpuRegisterPair() || destination.IsFpuRegisterPair()) {
- DRegister reg = source.IsFpuRegisterPair()
- ? FromLowSToD(source.AsFpuRegisterPairLow<SRegister>())
- : FromLowSToD(destination.AsFpuRegisterPairLow<SRegister>());
- int mem = source.IsFpuRegisterPair()
- ? destination.GetStackIndex()
- : source.GetStackIndex();
-
- __ vmovd(DTMP, reg);
- __ LoadDFromOffset(reg, SP, mem);
- __ StoreDToOffset(DTMP, SP, mem);
+ __ vmovrs(IP, reg);
+ __ LoadFromOffset(kLoadWord, IP, SP, mem);
+ __ StoreToOffset(kStoreWord, IP, SP, mem);
} else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
- // TODO: We could use DTMP and ask for a pair scratch register (float or core).
- // This would save four instructions if two scratch registers are available, and
- // two instructions if not.
Exchange(source.GetStackIndex(), destination.GetStackIndex());
Exchange(source.GetHighStackIndex(kArmWordSize), destination.GetHighStackIndex(kArmWordSize));
} else {