summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Geoffray <ngeoffray@google.com>2015-04-13 12:53:56 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2015-04-13 12:53:57 +0000
commite4e88d7b37c977b4c755485174a54c04aa3de951 (patch)
treeb25d5be5b8e7320d05f42da549c11cc82d7dbc51
parent6cfece6336c86017694758bbc0dc68b62c02de86 (diff)
parent386ce406f150645158d6067c4e0a36565aefc44f (diff)
downloadandroid_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.cc158
-rw-r--r--compiler/optimizing/code_generator_x86.h4
-rw-r--r--compiler/utils/x86/assembler_x86.cc7
-rw-r--r--compiler/utils/x86/assembler_x86.h1
-rw-r--r--compiler/utils/x86_64/assembler_x86_64.cc7
-rw-r--r--compiler/utils/x86_64/assembler_x86_64.h1
-rw-r--r--test/422-type-conversion/src/Main.java1
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() {