diff options
author | Calin Juravle <calin@google.com> | 2014-12-08 14:24:46 +0000 |
---|---|---|
committer | Calin Juravle <calin@google.com> | 2014-12-08 17:02:11 +0000 |
commit | d2ec87d84057174d4884ee16f652cbcfd31362e9 (patch) | |
tree | 9456c5851f157566380c37895407dfce4749bb4d /compiler | |
parent | f551efff34c20e2f0cf962c3fc267204d5e7611f (diff) | |
download | art-d2ec87d84057174d4884ee16f652cbcfd31362e9.tar.gz art-d2ec87d84057174d4884ee16f652cbcfd31362e9.tar.bz2 art-d2ec87d84057174d4884ee16f652cbcfd31362e9.zip |
[optimizing compiler] Add REM_FLOAT and REM_DOUBLE
- for arm, x86, x86_64 backends
- reinstated fmod quick entry points for x86. This is a partial revert
of bd3682eada753de52975ae2b4a712bd87dc139a6 which added inline assembly
for floting point rem on x86. Note that Quick still uses the inline
version.
- fix rem tests for longs
Change-Id: I73be19a9f2f2bcf3f718d9ca636e67bdd72b5440
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/optimizing/builder.cc | 20 | ||||
-rw-r--r-- | compiler/optimizing/code_generator.cc | 16 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 50 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 39 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86_64.cc | 43 |
5 files changed, 120 insertions, 48 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index ca72f3f242..0a3f830247 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -1435,6 +1435,16 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32 break; } + case Instruction::REM_FLOAT: { + Binop_23x<HRem>(instruction, Primitive::kPrimFloat, dex_pc); + break; + } + + case Instruction::REM_DOUBLE: { + Binop_23x<HRem>(instruction, Primitive::kPrimDouble, dex_pc); + break; + } + case Instruction::AND_INT: { Binop_23x<HAnd>(instruction, Primitive::kPrimInt); break; @@ -1574,6 +1584,16 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32 break; } + case Instruction::REM_FLOAT_2ADDR: { + Binop_12x<HRem>(instruction, Primitive::kPrimFloat, dex_pc); + break; + } + + case Instruction::REM_DOUBLE_2ADDR: { + Binop_12x<HRem>(instruction, Primitive::kPrimDouble, dex_pc); + break; + } + case Instruction::SHL_INT_2ADDR: { Binop_12x_shift<HShl>(instruction, Primitive::kPrimInt); break; diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index 7f358eaa6b..461409ddca 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -499,19 +499,27 @@ void CodeGenerator::BuildStackMaps(std::vector<uint8_t>* data) { } void CodeGenerator::RecordPcInfo(HInstruction* instruction, uint32_t dex_pc) { - if (instruction != nullptr && instruction->IsTypeConversion()) { + if (instruction != nullptr) { // The code generated for some type conversions may call the // runtime, thus normally requiring a subsequent call to this // method. However, the method verifier does not produce PC - // information for Dex type conversion instructions, as it - // considers them as "atomic" (they cannot join a GC). + // information for certain instructions, which are considered "atomic" + // (they cannot join a GC). // Therefore we do not currently record PC information for such // instructions. As this may change later, we added this special // case so that code generators may nevertheless call // CodeGenerator::RecordPcInfo without triggering an error in // CodeGenerator::BuildNativeGCMap ("Missing ref for dex pc 0x") // thereafter. - return; + if (instruction->IsTypeConversion()) { + return; + } + if (instruction->IsRem()) { + Primitive::Type type = instruction->AsRem()->GetResultType(); + if ((type == Primitive::kPrimFloat) || (type == Primitive::kPrimDouble)) { + return; + } + } } // Collect PC infos for the mapping table. diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index 36af393e3b..cbe5f0cc6e 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -44,7 +44,7 @@ static constexpr int kCurrentMethodStackOffset = 0; static constexpr Register kRuntimeParameterCoreRegisters[] = { R0, R1, R2, R3 }; static constexpr size_t kRuntimeParameterCoreRegistersLength = arraysize(kRuntimeParameterCoreRegisters); -static constexpr SRegister kRuntimeParameterFpuRegisters[] = { S0, S1 }; +static constexpr SRegister kRuntimeParameterFpuRegisters[] = { S0, S1, S2, S3 }; static constexpr size_t kRuntimeParameterFpuRegistersLength = arraysize(kRuntimeParameterFpuRegisters); @@ -2132,12 +2132,13 @@ void InstructionCodeGeneratorARM::VisitDiv(HDiv* div) { } void LocationsBuilderARM::VisitRem(HRem* rem) { - LocationSummary::CallKind call_kind = rem->GetResultType() == Primitive::kPrimLong - ? LocationSummary::kCall - : LocationSummary::kNoCall; + Primitive::Type type = rem->GetResultType(); + LocationSummary::CallKind call_kind = type == Primitive::kPrimInt + ? LocationSummary::kNoCall + : LocationSummary::kCall; LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(rem, call_kind); - switch (rem->GetResultType()) { + switch (type) { case Primitive::kPrimInt: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RequiresRegister()); @@ -2155,14 +2156,26 @@ void LocationsBuilderARM::VisitRem(HRem* rem) { locations->SetOut(Location::RegisterPairLocation(R2, R3)); break; } - case Primitive::kPrimFloat: + case Primitive::kPrimFloat: { + InvokeRuntimeCallingConvention calling_convention; + locations->SetInAt(0, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(0))); + locations->SetInAt(1, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(1))); + locations->SetOut(Location::FpuRegisterLocation(S0)); + break; + } + case Primitive::kPrimDouble: { - LOG(FATAL) << "Unimplemented rem type " << rem->GetResultType(); + InvokeRuntimeCallingConvention calling_convention; + locations->SetInAt(0, Location::FpuRegisterPairLocation( + calling_convention.GetFpuRegisterAt(0), calling_convention.GetFpuRegisterAt(1))); + locations->SetInAt(1, Location::FpuRegisterPairLocation( + calling_convention.GetFpuRegisterAt(2), calling_convention.GetFpuRegisterAt(3))); + locations->SetOut(Location::Location::FpuRegisterPairLocation(S0, S1)); break; } default: - LOG(FATAL) << "Unexpected rem type " << rem->GetResultType(); + LOG(FATAL) << "Unexpected rem type " << type; } } @@ -2172,7 +2185,8 @@ void InstructionCodeGeneratorARM::VisitRem(HRem* rem) { Location first = locations->InAt(0); Location second = locations->InAt(1); - switch (rem->GetResultType()) { + Primitive::Type type = rem->GetResultType(); + switch (type) { case Primitive::kPrimInt: { Register reg1 = first.AsRegister<Register>(); Register reg2 = second.AsRegister<Register>(); @@ -2188,26 +2202,22 @@ void InstructionCodeGeneratorARM::VisitRem(HRem* rem) { } case Primitive::kPrimLong: { - InvokeRuntimeCallingConvention calling_convention; - DCHECK_EQ(calling_convention.GetRegisterAt(0), first.AsRegisterPairLow<Register>()); - DCHECK_EQ(calling_convention.GetRegisterAt(1), first.AsRegisterPairHigh<Register>()); - DCHECK_EQ(calling_convention.GetRegisterAt(2), second.AsRegisterPairLow<Register>()); - DCHECK_EQ(calling_convention.GetRegisterAt(3), second.AsRegisterPairHigh<Register>()); - DCHECK_EQ(R2, out.AsRegisterPairLow<Register>()); - DCHECK_EQ(R3, out.AsRegisterPairHigh<Register>()); - codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pLmod), rem, rem->GetDexPc()); break; } - case Primitive::kPrimFloat: + case Primitive::kPrimFloat: { + codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pFmodf), rem, rem->GetDexPc()); + break; + } + case Primitive::kPrimDouble: { - LOG(FATAL) << "Unimplemented rem type " << rem->GetResultType(); + codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pFmod), rem, rem->GetDexPc()); break; } default: - LOG(FATAL) << "Unexpected rem type " << rem->GetResultType(); + LOG(FATAL) << "Unexpected rem type " << type; } } diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 2fd712f7e2..8a0c2deab9 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -2206,12 +2206,13 @@ void InstructionCodeGeneratorX86::VisitDiv(HDiv* div) { } void LocationsBuilderX86::VisitRem(HRem* rem) { - LocationSummary::CallKind call_kind = rem->GetResultType() == Primitive::kPrimLong - ? LocationSummary::kCall - : LocationSummary::kNoCall; + Primitive::Type type = rem->GetResultType(); + LocationSummary::CallKind call_kind = type == Primitive::kPrimInt + ? LocationSummary::kNoCall + : LocationSummary::kCall; LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(rem, call_kind); - switch (rem->GetResultType()) { + switch (type) { case Primitive::kPrimInt: { locations->SetInAt(0, Location::RegisterLocation(EAX)); locations->SetInAt(1, Location::RequiresRegister()); @@ -2228,14 +2229,29 @@ void LocationsBuilderX86::VisitRem(HRem* rem) { locations->SetOut(Location::RegisterPairLocation(EAX, EDX)); break; } - case Primitive::kPrimFloat: + case Primitive::kPrimFloat: { + InvokeRuntimeCallingConvention calling_convention; + // x86 floating-point parameters are passed through core registers (EAX, ECX). + locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0))); + locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1))); + // The runtime helper puts the result in XMM0. + locations->SetOut(Location::FpuRegisterLocation(XMM0)); + break; + } case Primitive::kPrimDouble: { - LOG(FATAL) << "Unimplemented rem type " << rem->GetResultType(); + InvokeRuntimeCallingConvention calling_convention; + // x86 floating-point parameters are passed through core registers (EAX_ECX, EDX_EBX). + locations->SetInAt(0, Location::RegisterPairLocation( + calling_convention.GetRegisterAt(0), calling_convention.GetRegisterAt(1))); + locations->SetInAt(1, Location::RegisterPairLocation( + calling_convention.GetRegisterAt(2), calling_convention.GetRegisterAt(3))); + // The runtime helper puts the result in XMM0. + locations->SetOut(Location::FpuRegisterLocation(XMM0)); break; } default: - LOG(FATAL) << "Unexpected rem type " << rem->GetResultType(); + LOG(FATAL) << "Unexpected rem type " << type; } } @@ -2247,9 +2263,14 @@ void InstructionCodeGeneratorX86::VisitRem(HRem* rem) { GenerateDivRemIntegral(rem); break; } - case Primitive::kPrimFloat: + case Primitive::kPrimFloat: { + __ fs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pFmodf))); + codegen_->RecordPcInfo(rem, rem->GetDexPc()); + break; + } case Primitive::kPrimDouble: { - LOG(FATAL) << "Unimplemented rem type " << type; + __ fs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86WordSize, pFmod))); + codegen_->RecordPcInfo(rem, rem->GetDexPc()); break; } default: diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 39a97661c9..233f4a4e4b 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -43,8 +43,9 @@ static constexpr int kCurrentMethodStackOffset = 0; static constexpr Register kRuntimeParameterCoreRegisters[] = { RDI, RSI, RDX }; static constexpr size_t kRuntimeParameterCoreRegistersLength = arraysize(kRuntimeParameterCoreRegisters); -static constexpr FloatRegister kRuntimeParameterFpuRegisters[] = { }; -static constexpr size_t kRuntimeParameterFpuRegistersLength = 0; +static constexpr FloatRegister kRuntimeParameterFpuRegisters[] = { XMM0, XMM1 }; +static constexpr size_t kRuntimeParameterFpuRegistersLength = + arraysize(kRuntimeParameterFpuRegisters); class InvokeRuntimeCallingConvention : public CallingConvention<Register, FloatRegister> { public: @@ -1999,16 +2000,16 @@ void InstructionCodeGeneratorX86_64::GenerateDivRemIntegral(HBinaryOperation* in // 0x80000000(00000000)/-1 triggers an arithmetic exception! // Dividing by -1 is actually negation and -0x800000000(00000000) = 0x80000000(00000000) // so it's safe to just use negl instead of more complex comparisons. - - __ cmpl(second_reg, Immediate(-1)); - __ j(kEqual, slow_path->GetEntryLabel()); - if (type == Primitive::kPrimInt) { + __ cmpl(second_reg, Immediate(-1)); + __ j(kEqual, slow_path->GetEntryLabel()); // edx:eax <- sign-extended of eax __ cdq(); // eax = quotient, edx = remainder __ idivl(second_reg); } else { + __ cmpq(second_reg, Immediate(-1)); + __ j(kEqual, slow_path->GetEntryLabel()); // rdx:rax <- sign-extended of rax __ cqo(); // rax = quotient, rdx = remainder @@ -2075,9 +2076,14 @@ void InstructionCodeGeneratorX86_64::VisitDiv(HDiv* div) { } void LocationsBuilderX86_64::VisitRem(HRem* rem) { - LocationSummary* locations = - new (GetGraph()->GetArena()) LocationSummary(rem, LocationSummary::kNoCall); - switch (rem->GetResultType()) { + Primitive::Type type = rem->GetResultType(); + LocationSummary::CallKind call_kind = + (type == Primitive::kPrimInt) || (type == Primitive::kPrimLong) + ? LocationSummary::kNoCall + : LocationSummary::kCall; + LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(rem, call_kind); + + switch (type) { case Primitive::kPrimInt: case Primitive::kPrimLong: { locations->SetInAt(0, Location::RegisterLocation(RAX)); @@ -2089,12 +2095,16 @@ void LocationsBuilderX86_64::VisitRem(HRem* rem) { case Primitive::kPrimFloat: case Primitive::kPrimDouble: { - LOG(FATAL) << "Unimplemented rem type " << rem->GetResultType(); + InvokeRuntimeCallingConvention calling_convention; + locations->SetInAt(0, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(0))); + locations->SetInAt(1, Location::FpuRegisterLocation(calling_convention.GetFpuRegisterAt(1))); + // The runtime helper puts the result in XMM0. + locations->SetOut(Location::FpuRegisterLocation(XMM0)); break; } default: - LOG(FATAL) << "Unexpected rem type " << rem->GetResultType(); + LOG(FATAL) << "Unexpected rem type " << type; } } @@ -2106,13 +2116,16 @@ void InstructionCodeGeneratorX86_64::VisitRem(HRem* rem) { GenerateDivRemIntegral(rem); break; } - - case Primitive::kPrimFloat: + case Primitive::kPrimFloat: { + __ gs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pFmodf), true)); + codegen_->RecordPcInfo(rem, rem->GetDexPc()); + break; + } case Primitive::kPrimDouble: { - LOG(FATAL) << "Unimplemented rem type " << rem->GetResultType(); + __ gs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86_64WordSize, pFmod), true)); + codegen_->RecordPcInfo(rem, rem->GetDexPc()); break; } - default: LOG(FATAL) << "Unexpected rem type " << rem->GetResultType(); } |