diff options
Diffstat (limited to 'compiler/optimizing')
| -rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 158 | ||||
| -rw-r--r-- | compiler/optimizing/code_generator_x86.h | 4 |
2 files changed, 74 insertions, 88 deletions
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index ef896aa949..92b62e2c84 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -1525,8 +1525,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: @@ -1556,8 +1558,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: @@ -1778,31 +1782,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; } @@ -1831,31 +1841,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; } @@ -2195,43 +2203,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)); } } } @@ -2250,9 +2239,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 1cb9e326ce..0cc3c6533a 100644 --- a/compiler/optimizing/code_generator_x86.h +++ b/compiler/optimizing/code_generator_x86.h @@ -171,10 +171,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); |