diff options
author | Nicolas Geoffray <ngeoffray@google.com> | 2015-04-13 12:53:56 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2015-04-13 12:53:57 +0000 |
commit | e4e88d7b37c977b4c755485174a54c04aa3de951 (patch) | |
tree | b25d5be5b8e7320d05f42da549c11cc82d7dbc51 | |
parent | 6cfece6336c86017694758bbc0dc68b62c02de86 (diff) | |
parent | 386ce406f150645158d6067c4e0a36565aefc44f (diff) | |
download | android_art-e4e88d7b37c977b4c755485174a54c04aa3de951.tar.gz android_art-e4e88d7b37c977b4c755485174a54c04aa3de951.tar.bz2 android_art-e4e88d7b37c977b4c755485174a54c04aa3de951.zip |
Merge "Revert "Optimizing: Fix long-to-fp conversion on x86.""
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 158 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.h | 4 | ||||
-rw-r--r-- | compiler/utils/x86/assembler_x86.cc | 7 | ||||
-rw-r--r-- | compiler/utils/x86/assembler_x86.h | 1 | ||||
-rw-r--r-- | compiler/utils/x86_64/assembler_x86_64.cc | 7 | ||||
-rw-r--r-- | compiler/utils/x86_64/assembler_x86_64.h | 1 | ||||
-rw-r--r-- | test/422-type-conversion/src/Main.java | 1 |
7 files changed, 74 insertions, 105 deletions
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 78c2d36adf..48445d79da 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -1545,8 +1545,10 @@ void LocationsBuilderX86::VisitTypeConversion(HTypeConversion* conversion) { case Primitive::kPrimLong: // Processing a Dex `long-to-float' instruction. - locations->SetInAt(0, Location::Any()); - locations->SetOut(Location::Any()); + locations->SetInAt(0, Location::RequiresRegister()); + locations->SetOut(Location::RequiresFpuRegister()); + locations->AddTemp(Location::RequiresFpuRegister()); + locations->AddTemp(Location::RequiresFpuRegister()); break; case Primitive::kPrimDouble: @@ -1576,8 +1578,10 @@ void LocationsBuilderX86::VisitTypeConversion(HTypeConversion* conversion) { case Primitive::kPrimLong: // Processing a Dex `long-to-double' instruction. - locations->SetInAt(0, Location::Any()); - locations->SetOut(Location::Any()); + locations->SetInAt(0, Location::RequiresRegister()); + locations->SetOut(Location::RequiresFpuRegister()); + locations->AddTemp(Location::RequiresFpuRegister()); + locations->AddTemp(Location::RequiresFpuRegister()); break; case Primitive::kPrimFloat: @@ -1798,31 +1802,37 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio case Primitive::kPrimLong: { // Processing a Dex `long-to-float' instruction. - size_t adjustment = 0; - - // Create stack space for the call to - // InstructionCodeGeneratorX86::PushOntoFPStack and/or X86Assembler::fstps below. - // TODO: enhance register allocator to ask for stack temporaries. - if (!in.IsDoubleStackSlot() || !out.IsStackSlot()) { - adjustment = Primitive::ComponentSize(Primitive::kPrimLong); - __ subl(ESP, Immediate(adjustment)); - } - - // Load the value to the FP stack, using temporaries if needed. - PushOntoFPStack(in, 0, adjustment, false, true); - - if (out.IsStackSlot()) { - __ fstps(Address(ESP, out.GetStackIndex() + adjustment)); - } else { - __ fstps(Address(ESP, 0)); - Location stack_temp = Location::StackSlot(0); - codegen_->Move32(out, stack_temp); - } - - // Remove the temporary stack space we allocated. - if (adjustment != 0) { - __ addl(ESP, Immediate(adjustment)); - } + Register low = in.AsRegisterPairLow<Register>(); + Register high = in.AsRegisterPairHigh<Register>(); + XmmRegister result = out.AsFpuRegister<XmmRegister>(); + XmmRegister temp = locations->GetTemp(0).AsFpuRegister<XmmRegister>(); + XmmRegister constant = locations->GetTemp(1).AsFpuRegister<XmmRegister>(); + + // Operations use doubles for precision reasons (each 32-bit + // half of a long fits in the 53-bit mantissa of a double, + // but not in the 24-bit mantissa of a float). This is + // especially important for the low bits. The result is + // eventually converted to float. + + // low = low - 2^31 (to prevent bit 31 of `low` to be + // interpreted as a sign bit) + __ subl(low, Immediate(0x80000000)); + // temp = int-to-double(high) + __ cvtsi2sd(temp, high); + // temp = temp * 2^32 + __ LoadLongConstant(constant, k2Pow32EncodingForDouble); + __ mulsd(temp, constant); + // result = int-to-double(low) + __ cvtsi2sd(result, low); + // result = result + 2^31 (restore the original value of `low`) + __ LoadLongConstant(constant, k2Pow31EncodingForDouble); + __ addsd(result, constant); + // result = result + temp + __ addsd(result, temp); + // result = double-to-float(result) + __ cvtsd2ss(result, result); + // Restore low. + __ addl(low, Immediate(0x80000000)); break; } @@ -1851,31 +1861,29 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio case Primitive::kPrimLong: { // Processing a Dex `long-to-double' instruction. - size_t adjustment = 0; - - // Create stack space for the call to - // InstructionCodeGeneratorX86::PushOntoFPStack and/or X86Assembler::fstpl below. - // TODO: enhance register allocator to ask for stack temporaries. - if (!in.IsDoubleStackSlot() || !out.IsDoubleStackSlot()) { - adjustment = Primitive::ComponentSize(Primitive::kPrimLong); - __ subl(ESP, Immediate(adjustment)); - } - - // Load the value to the FP stack, using temporaries if needed. - PushOntoFPStack(in, 0, adjustment, false, true); - - if (out.IsDoubleStackSlot()) { - __ fstpl(Address(ESP, out.GetStackIndex() + adjustment)); - } else { - __ fstpl(Address(ESP, 0)); - Location stack_temp = Location::DoubleStackSlot(0); - codegen_->Move64(out, stack_temp); - } - - // Remove the temporary stack space we allocated. - if (adjustment != 0) { - __ addl(ESP, Immediate(adjustment)); - } + Register low = in.AsRegisterPairLow<Register>(); + Register high = in.AsRegisterPairHigh<Register>(); + XmmRegister result = out.AsFpuRegister<XmmRegister>(); + XmmRegister temp = locations->GetTemp(0).AsFpuRegister<XmmRegister>(); + XmmRegister constant = locations->GetTemp(1).AsFpuRegister<XmmRegister>(); + + // low = low - 2^31 (to prevent bit 31 of `low` to be + // interpreted as a sign bit) + __ subl(low, Immediate(0x80000000)); + // temp = int-to-double(high) + __ cvtsi2sd(temp, high); + // temp = temp * 2^32 + __ LoadLongConstant(constant, k2Pow32EncodingForDouble); + __ mulsd(temp, constant); + // result = int-to-double(low) + __ cvtsi2sd(result, low); + // result = result + 2^31 (restore the original value of `low`) + __ LoadLongConstant(constant, k2Pow31EncodingForDouble); + __ addsd(result, constant); + // result = result + temp + __ addsd(result, temp); + // Restore low. + __ addl(low, Immediate(0x80000000)); break; } @@ -2215,43 +2223,24 @@ void InstructionCodeGeneratorX86::VisitMul(HMul* mul) { } } -void InstructionCodeGeneratorX86::PushOntoFPStack(Location source, - uint32_t temp_offset, - uint32_t stack_adjustment, - bool is_fp, - bool is_wide) { +void InstructionCodeGeneratorX86::PushOntoFPStack(Location source, uint32_t temp_offset, + uint32_t stack_adjustment, bool is_float) { if (source.IsStackSlot()) { - DCHECK(!is_wide); - if (is_fp) { - __ flds(Address(ESP, source.GetStackIndex() + stack_adjustment)); - } else { - __ filds(Address(ESP, source.GetStackIndex() + stack_adjustment)); - } + DCHECK(is_float); + __ flds(Address(ESP, source.GetStackIndex() + stack_adjustment)); } else if (source.IsDoubleStackSlot()) { - DCHECK(is_wide); - if (is_fp) { - __ fldl(Address(ESP, source.GetStackIndex() + stack_adjustment)); - } else { - __ fildl(Address(ESP, source.GetStackIndex() + stack_adjustment)); - } + DCHECK(!is_float); + __ fldl(Address(ESP, source.GetStackIndex() + stack_adjustment)); } else { // Write the value to the temporary location on the stack and load to FP stack. - if (!is_wide) { + if (is_float) { Location stack_temp = Location::StackSlot(temp_offset); codegen_->Move32(stack_temp, source); - if (is_fp) { - __ flds(Address(ESP, temp_offset)); - } else { - __ filds(Address(ESP, temp_offset)); - } + __ flds(Address(ESP, temp_offset)); } else { Location stack_temp = Location::DoubleStackSlot(temp_offset); codegen_->Move64(stack_temp, source); - if (is_fp) { - __ fldl(Address(ESP, temp_offset)); - } else { - __ fildl(Address(ESP, temp_offset)); - } + __ fldl(Address(ESP, temp_offset)); } } } @@ -2270,9 +2259,8 @@ void InstructionCodeGeneratorX86::GenerateRemFP(HRem *rem) { __ subl(ESP, Immediate(2 * elem_size)); // Load the values to the FP stack in reverse order, using temporaries if needed. - const bool is_wide = !is_float; - PushOntoFPStack(second, elem_size, 2 * elem_size, /* is_fp */ true, is_wide); - PushOntoFPStack(first, 0, 2 * elem_size, /* is_fp */ true, is_wide); + PushOntoFPStack(second, elem_size, 2 * elem_size, is_float); + PushOntoFPStack(first, 0, 2 * elem_size, is_float); // Loop doing FPREM until we stabilize. Label retry; diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h index bfccecc7fd..00a4323a54 100644 --- a/compiler/optimizing/code_generator_x86.h +++ b/compiler/optimizing/code_generator_x86.h @@ -175,10 +175,8 @@ class InstructionCodeGeneratorX86 : public HGraphVisitor { void GenerateMemoryBarrier(MemBarrierKind kind); void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info); void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info); - // Push value to FPU stack. `is_fp` specifies whether the value is floating point or not. - // `is_wide` specifies whether it is long/double or not. void PushOntoFPStack(Location source, uint32_t temp_offset, - uint32_t stack_adjustment, bool is_fp, bool is_wide); + uint32_t stack_adjustment, bool is_float); void GenerateImplicitNullCheck(HNullCheck* instruction); void GenerateExplicitNullCheck(HNullCheck* instruction); diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc index 329698ce1e..51cc7acbd0 100644 --- a/compiler/utils/x86/assembler_x86.cc +++ b/compiler/utils/x86/assembler_x86.cc @@ -883,13 +883,6 @@ void X86Assembler::fildl(const Address& src) { } -void X86Assembler::filds(const Address& src) { - AssemblerBuffer::EnsureCapacity ensured(&buffer_); - EmitUint8(0xDB); - EmitOperand(0, src); -} - - void X86Assembler::fincstp() { AssemblerBuffer::EnsureCapacity ensured(&buffer_); EmitUint8(0xD9); diff --git a/compiler/utils/x86/assembler_x86.h b/compiler/utils/x86/assembler_x86.h index a933474a39..f3675aeceb 100644 --- a/compiler/utils/x86/assembler_x86.h +++ b/compiler/utils/x86/assembler_x86.h @@ -349,7 +349,6 @@ class X86Assembler FINAL : public Assembler { void fistpl(const Address& dst); void fistps(const Address& dst); void fildl(const Address& src); - void filds(const Address& src); void fincstp(); void ffree(const Immediate& index); diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc index 32204a9970..638659d635 100644 --- a/compiler/utils/x86_64/assembler_x86_64.cc +++ b/compiler/utils/x86_64/assembler_x86_64.cc @@ -988,13 +988,6 @@ void X86_64Assembler::fildl(const Address& src) { } -void X86_64Assembler::filds(const Address& src) { - AssemblerBuffer::EnsureCapacity ensured(&buffer_); - EmitUint8(0xDB); - EmitOperand(0, src); -} - - void X86_64Assembler::fincstp() { AssemblerBuffer::EnsureCapacity ensured(&buffer_); EmitUint8(0xD9); diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h index 16ef70b85e..15b8b15c74 100644 --- a/compiler/utils/x86_64/assembler_x86_64.h +++ b/compiler/utils/x86_64/assembler_x86_64.h @@ -448,7 +448,6 @@ class X86_64Assembler FINAL : public Assembler { void fistpl(const Address& dst); void fistps(const Address& dst); void fildl(const Address& src); - void filds(const Address& src); void fincstp(); void ffree(const Immediate& index); diff --git a/test/422-type-conversion/src/Main.java b/test/422-type-conversion/src/Main.java index da5bd766a3..7ce2868283 100644 --- a/test/422-type-conversion/src/Main.java +++ b/test/422-type-conversion/src/Main.java @@ -321,7 +321,6 @@ public class Main { assertFloatEquals(9223372036854775807F, $opt$LongToFloat(9223372036854775807L)); // 2^63 - 1 assertFloatEquals(-9223372036854775807F, $opt$LongToFloat(-9223372036854775807L)); // -(2^63 - 1) assertFloatEquals(-9223372036854775808F, $opt$LongToFloat(-9223372036854775808L)); // -(2^63) - assertFloatEquals(Float.intBitsToFloat(-555858671), $opt$LongToFloat(-8008112895877447681L)); } private static void longToDouble() { |