diff options
| -rw-r--r-- | compiler/optimizing/code_generator_arm_vixl.cc | 101 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator_arm_vixl.h | 1 | ||||
| -rw-r--r-- | test/538-checker-embed-constants/src/Main.java | 12 | ||||
| -rw-r--r-- | test/Android.arm_vixl.mk | 27 |
4 files changed, 91 insertions, 50 deletions
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc index e399f3228e..bb6857d0a6 100644 --- a/compiler/optimizing/code_generator_arm_vixl.cc +++ b/compiler/optimizing/code_generator_arm_vixl.cc @@ -2215,10 +2215,9 @@ void LocationsBuilderARMVIXL::VisitAdd(HAdd* add) { break; } - // TODO(VIXL): https://android-review.googlesource.com/#/c/254144/ case Primitive::kPrimLong: { locations->SetInAt(0, Location::RequiresRegister()); - locations->SetInAt(1, Location::RequiresRegister()); + locations->SetInAt(1, ArmEncodableConstantOrRegister(add->InputAt(1), ADD)); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; } @@ -2248,11 +2247,15 @@ void InstructionCodeGeneratorARMVIXL::VisitAdd(HAdd* add) { } break; - // TODO(VIXL): https://android-review.googlesource.com/#/c/254144/ case Primitive::kPrimLong: { - DCHECK(second.IsRegisterPair()); - __ Adds(LowRegisterFrom(out), LowRegisterFrom(first), LowRegisterFrom(second)); - __ Adc(HighRegisterFrom(out), HighRegisterFrom(first), HighRegisterFrom(second)); + if (second.IsConstant()) { + uint64_t value = static_cast<uint64_t>(Int64FromConstant(second.GetConstant())); + GenerateAddLongConst(out, first, value); + } else { + DCHECK(second.IsRegisterPair()); + __ Adds(LowRegisterFrom(out), LowRegisterFrom(first), LowRegisterFrom(second)); + __ Adc(HighRegisterFrom(out), HighRegisterFrom(first), HighRegisterFrom(second)); + } break; } @@ -2277,10 +2280,9 @@ void LocationsBuilderARMVIXL::VisitSub(HSub* sub) { break; } - // TODO(VIXL): https://android-review.googlesource.com/#/c/254144/ case Primitive::kPrimLong: { locations->SetInAt(0, Location::RequiresRegister()); - locations->SetInAt(1, Location::RequiresRegister()); + locations->SetInAt(1, ArmEncodableConstantOrRegister(sub->InputAt(1), SUB)); locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); break; } @@ -2307,11 +2309,15 @@ void InstructionCodeGeneratorARMVIXL::VisitSub(HSub* sub) { break; } - // TODO(VIXL): https://android-review.googlesource.com/#/c/254144/ case Primitive::kPrimLong: { - DCHECK(second.IsRegisterPair()); - __ Subs(LowRegisterFrom(out), LowRegisterFrom(first), LowRegisterFrom(second)); - __ Sbc(HighRegisterFrom(out), HighRegisterFrom(first), HighRegisterFrom(second)); + if (second.IsConstant()) { + uint64_t value = static_cast<uint64_t>(Int64FromConstant(second.GetConstant())); + GenerateAddLongConst(out, first, -value); + } else { + DCHECK(second.IsRegisterPair()); + __ Subs(LowRegisterFrom(out), LowRegisterFrom(first), LowRegisterFrom(second)); + __ Sbc(HighRegisterFrom(out), HighRegisterFrom(first), HighRegisterFrom(second)); + } break; } @@ -2478,7 +2484,8 @@ void InstructionCodeGeneratorARMVIXL::GenerateDivRemWithAnyConstant(HBinaryOpera int shift; CalculateMagicAndShiftForDivRem(imm, false /* is_long */, &magic, &shift); - __ Mov(temp1, Operand::From(magic)); + // TODO(VIXL): Change the static cast to Operand::From() after VIXL is fixed. + __ Mov(temp1, static_cast<int32_t>(magic)); __ Smull(temp2, temp1, dividend, temp1); if (imm > 0 && magic < 0) { @@ -4215,6 +4222,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArrayGet(HArrayGet* instruction) { } else { codegen_->LoadFromShiftedRegOffset(type, out_loc, temp, RegisterFrom(index)); } + temps.Release(temp); } break; } @@ -4254,6 +4262,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArrayGet(HArrayGet* instruction) { __ Add(temp, obj, data_offset); } codegen_->LoadFromShiftedRegOffset(type, out_loc, temp, RegisterFrom(index)); + temps.Release(temp); codegen_->MaybeRecordImplicitNullCheck(instruction); // If read barriers are enabled, emit read barriers other than @@ -4275,6 +4284,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArrayGet(HArrayGet* instruction) { vixl32::Register temp = temps.Acquire(); __ Add(temp, obj, Operand(RegisterFrom(index), vixl32::LSL, TIMES_8)); GetAssembler()->LoadFromOffset(kLoadWordPair, LowRegisterFrom(out_loc), temp, data_offset); + temps.Release(temp); } break; } @@ -4288,6 +4298,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArrayGet(HArrayGet* instruction) { vixl32::Register temp = temps.Acquire(); __ Add(temp, obj, Operand(RegisterFrom(index), vixl32::LSL, TIMES_4)); GetAssembler()->LoadSFromOffset(out, temp, data_offset); + temps.Release(temp); } break; } @@ -4300,6 +4311,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArrayGet(HArrayGet* instruction) { vixl32::Register temp = temps.Acquire(); __ Add(temp, obj, Operand(RegisterFrom(index), vixl32::LSL, TIMES_8)); GetAssembler()->LoadDFromOffset(DRegisterFrom(out_loc), temp, data_offset); + temps.Release(temp); } break; } @@ -4389,6 +4401,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArraySet(HArraySet* instruction) { __ Add(temp, array, data_offset); } codegen_->StoreToShiftedRegOffset(value_type, value_loc, temp, RegisterFrom(index)); + temps.Release(temp); } break; } @@ -4410,6 +4423,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArraySet(HArraySet* instruction) { vixl32::Register temp = temps.Acquire(); __ Add(temp, array, data_offset); codegen_->StoreToShiftedRegOffset(value_type, value_loc, temp, RegisterFrom(index)); + temps.Release(temp); } codegen_->MaybeRecordImplicitNullCheck(instruction); DCHECK(!needs_write_barrier); @@ -4443,6 +4457,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArraySet(HArraySet* instruction) { vixl32::Register temp = temps.Acquire(); __ Add(temp, array, data_offset); codegen_->StoreToShiftedRegOffset(value_type, value_loc, temp, RegisterFrom(index)); + temps.Release(temp); } codegen_->MaybeRecordImplicitNullCheck(instruction); __ B(&done); @@ -4512,6 +4527,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArraySet(HArraySet* instruction) { LocationFrom(source), temp, RegisterFrom(index)); + temps.Release(temp); } if (!may_need_runtime_call_for_type_check) { @@ -4541,6 +4557,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArraySet(HArraySet* instruction) { vixl32::Register temp = temps.Acquire(); __ Add(temp, array, Operand(RegisterFrom(index), vixl32::LSL, TIMES_8)); GetAssembler()->StoreToOffset(kStoreWordPair, LowRegisterFrom(value), temp, data_offset); + temps.Release(temp); } break; } @@ -4555,6 +4572,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArraySet(HArraySet* instruction) { vixl32::Register temp = temps.Acquire(); __ Add(temp, array, Operand(RegisterFrom(index), vixl32::LSL, TIMES_4)); GetAssembler()->StoreSToOffset(SRegisterFrom(value), temp, data_offset); + temps.Release(temp); } break; } @@ -4569,6 +4587,7 @@ void InstructionCodeGeneratorARMVIXL::VisitArraySet(HArraySet* instruction) { vixl32::Register temp = temps.Acquire(); __ Add(temp, array, Operand(RegisterFrom(index), vixl32::LSL, TIMES_8)); GetAssembler()->StoreDToOffset(DRegisterFrom(value), temp, data_offset); + temps.Release(temp); } break; } @@ -4904,9 +4923,12 @@ void ParallelMoveResolverARMVIXL::EmitSwap(size_t index) { } else if (source.IsStackSlot() && destination.IsRegister()) { Exchange(RegisterFrom(destination), source.GetStackIndex()); } else if (source.IsStackSlot() && destination.IsStackSlot()) { - TODO_VIXL32(FATAL); + Exchange(source.GetStackIndex(), destination.GetStackIndex()); } else if (source.IsFpuRegister() && destination.IsFpuRegister()) { - TODO_VIXL32(FATAL); + vixl32::SRegister temp = temps.AcquireS(); + __ Vmov(temp, SRegisterFrom(source)); + __ Vmov(SRegisterFrom(source), SRegisterFrom(destination)); + __ Vmov(SRegisterFrom(destination), temp); } else if (source.IsRegisterPair() && destination.IsRegisterPair()) { vixl32::DRegister temp = temps.AcquireD(); __ Vmov(temp, LowRegisterFrom(source), HighRegisterFrom(source)); @@ -4929,9 +4951,27 @@ void ParallelMoveResolverARMVIXL::EmitSwap(size_t index) { __ Vmov(first, second); __ Vmov(second, temp); } else if (source.IsFpuRegisterPair() || destination.IsFpuRegisterPair()) { - TODO_VIXL32(FATAL); + vixl32::DRegister reg = source.IsFpuRegisterPair() + ? DRegisterFrom(source) + : DRegisterFrom(destination); + int mem = source.IsFpuRegisterPair() + ? destination.GetStackIndex() + : source.GetStackIndex(); + vixl32::DRegister temp = temps.AcquireD(); + __ Vmov(temp, reg); + GetAssembler()->LoadDFromOffset(reg, sp, mem); + GetAssembler()->StoreDToOffset(temp, sp, mem); } else if (source.IsFpuRegister() || destination.IsFpuRegister()) { - TODO_VIXL32(FATAL); + vixl32::SRegister reg = source.IsFpuRegister() + ? SRegisterFrom(source) + : SRegisterFrom(destination); + int mem = source.IsFpuRegister() + ? destination.GetStackIndex() + : source.GetStackIndex(); + vixl32::Register temp = temps.Acquire(); + __ Vmov(temp, reg); + GetAssembler()->LoadSFromOffset(reg, sp, mem); + GetAssembler()->StoreToOffset(kStoreWord, temp, sp, mem); } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) { vixl32::DRegister temp1 = temps.AcquireD(); vixl32::DRegister temp2 = temps.AcquireD(); @@ -5715,6 +5755,33 @@ void InstructionCodeGeneratorARMVIXL::GenerateEorConst(vixl32::Register out, __ Eor(out, first, value); } +void InstructionCodeGeneratorARMVIXL::GenerateAddLongConst(Location out, + Location first, + uint64_t value) { + vixl32::Register out_low = LowRegisterFrom(out); + vixl32::Register out_high = HighRegisterFrom(out); + vixl32::Register first_low = LowRegisterFrom(first); + vixl32::Register first_high = HighRegisterFrom(first); + uint32_t value_low = Low32Bits(value); + uint32_t value_high = High32Bits(value); + if (value_low == 0u) { + if (!out_low.Is(first_low)) { + __ Mov(out_low, first_low); + } + __ Add(out_high, first_high, value_high); + return; + } + __ Adds(out_low, first_low, value_low); + if (GetAssembler()->ShifterOperandCanHold(ADC, value_high, kCcKeep)) { + __ Adc(out_high, first_high, value_high); + } else if (GetAssembler()->ShifterOperandCanHold(SBC, ~value_high, kCcKeep)) { + __ Sbc(out_high, first_high, ~value_high); + } else { + LOG(FATAL) << "Unexpected constant " << value_high; + UNREACHABLE(); + } +} + void InstructionCodeGeneratorARMVIXL::HandleBitwiseOperation(HBinaryOperation* instruction) { LocationSummary* locations = instruction->GetLocations(); Location first = locations->InAt(0); diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h index 38c756fb0f..89fef43e46 100644 --- a/compiler/optimizing/code_generator_arm_vixl.h +++ b/compiler/optimizing/code_generator_arm_vixl.h @@ -386,6 +386,7 @@ class InstructionCodeGeneratorARMVIXL : public InstructionCodeGenerator { void GenerateAndConst(vixl::aarch32::Register out, vixl::aarch32::Register first, uint32_t value); void GenerateOrrConst(vixl::aarch32::Register out, vixl::aarch32::Register first, uint32_t value); void GenerateEorConst(vixl::aarch32::Register out, vixl::aarch32::Register first, uint32_t value); + void GenerateAddLongConst(Location out, Location first, uint64_t value); void HandleBitwiseOperation(HBinaryOperation* operation); void HandleCondition(HCondition* condition); void HandleIntegerRotate(HRor* ror); diff --git a/test/538-checker-embed-constants/src/Main.java b/test/538-checker-embed-constants/src/Main.java index 6b25747463..0329e63ffd 100644 --- a/test/538-checker-embed-constants/src/Main.java +++ b/test/538-checker-embed-constants/src/Main.java @@ -105,7 +105,7 @@ public class Main { /// CHECK-NOT: and{{(\.w)?}} /// CHECK-NOT: bic{{(\.w)?}} /// CHECK-DAG: and {{r\d+}}, {{r\d+}}, #0xff - /// CHECK-DAG: movs {{r\d+}}, #0 + /// CHECK-DAG: mov{{s?}} {{r\d+}}, #0 /// CHECK-NOT: and{{(\.w)?}} /// CHECK-NOT: bic{{(\.w)?}} @@ -115,7 +115,7 @@ public class Main { /// CHECK-START-ARM: long Main.and511(long) disassembly (after) /// CHECK: mov {{r\d+}}, #511 - /// CHECK-NEXT: movs {{r\d+}}, #0 + /// CHECK-NEXT: mov{{s?}} {{r\d+}}, #0 /// CHECK-NOT: and{{(\.w)?}} /// CHECK-NOT: bic{{(\.w)?}} /// CHECK: and{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}} @@ -167,7 +167,7 @@ public class Main { /// CHECK-START-ARM: long Main.or511(long) disassembly (after) /// CHECK: mov {{r\d+}}, #511 - /// CHECK-NEXT: movs {{r\d+}}, #0 + /// CHECK-NEXT: mov{{s?}} {{r\d+}}, #0 /// CHECK-NOT: orr{{(\.w)?}} /// CHECK-NOT: orn /// CHECK: orr{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}} @@ -218,7 +218,7 @@ public class Main { /// CHECK-START-ARM: long Main.xor511(long) disassembly (after) /// CHECK: mov {{r\d+}}, #511 - /// CHECK-NEXT: movs {{r\d+}}, #0 + /// CHECK-NEXT: mov{{s?}} {{r\d+}}, #0 /// CHECK-NOT: eor{{(\.w)?}} /// CHECK: eor{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}} /// CHECK-NEXT: eor{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}} @@ -242,7 +242,7 @@ public class Main { // Note: No support for partial long constant embedding. /// CHECK-START-ARM: long Main.xor0xfffffff00000000f(long) disassembly (after) - /// CHECK-DAG: movs {{r\d+}}, #15 + /// CHECK-DAG: mov{{s?}} {{r\d+}}, #15 /// CHECK-DAG: mvn {{r\d+}}, #15 /// CHECK-NOT: eor{{(\.w)?}} /// CHECK-DAG: eor{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}} @@ -507,7 +507,7 @@ public class Main { /// CHECK: <<Arg:j\d+>> ParameterValue /// CHECK: <<ConstM1:j\d+>> LongConstant -1 /// CHECK: Add [<<Arg>>,<<ConstM1>>] - /// CHECK-NEXT: subs r{{\d+}}, #1 + /// CHECK-NEXT: {{adds|subs}} r{{\d+}}, #{{4294967295|1}} /// CHECK-NEXT: adc r{{\d+}}, r{{\d+}}, #4294967295 /// CHECK: Sub [<<Arg>>,<<ConstM1>>] /// CHECK-NEXT: adds r{{\d+}}, #1 diff --git a/test/Android.arm_vixl.mk b/test/Android.arm_vixl.mk index 21b31b40b7..72616a1414 100644 --- a/test/Android.arm_vixl.mk +++ b/test/Android.arm_vixl.mk @@ -16,36 +16,9 @@ # Known broken tests for the ARM VIXL backend. TEST_ART_BROKEN_OPTIMIZING_ARM_VIXL_RUN_TESTS := \ - 003-omnibus-opcodes \ - 020-string \ - 021-string2 \ - 042-new-instance \ - 044-proxy \ - 080-oom-throw \ - 082-inline-execute \ - 096-array-copy-concurrent-gc \ - 099-vmdebug \ - 100-reflect2 \ 103-string-append \ - 114-ParallelGC \ - 122-npe \ - 129-ThreadGetId \ 137-cfi \ - 144-static-field-sigquit \ - 412-new-array \ - 439-npe \ - 450-checker-types \ 488-checker-inline-recursive-calls \ - 515-dce-dominator \ - 520-equivalent-phi \ - 525-checker-arrays-fields1 \ - 525-checker-arrays-fields2 \ - 527-checker-array-access-split \ - 538-checker-embed-constants \ 552-checker-sharpening \ 562-checker-no-intermediate \ - 570-checker-osr \ 602-deoptimizeable \ - 700-LoadArgRegs \ - 800-smali \ - |