diff options
author | 2016-01-25 14:47:50 +0000 | |
---|---|---|
committer | 2016-02-04 12:59:22 -0500 | |
commit | 2f10a5fb8c236a6786928f0323bd312c3ee9a4cc (patch) | |
tree | 0dc51717b1f5d9b2c20898c5283467d4feb220e2 /compiler/optimizing/intrinsics_x86.cc | |
parent | a20748aceb63396c5e09366968bbc71308f745df (diff) |
Revert "Revert "X86: Use the constant area for more operations.""
This reverts commit cf8d1bb97e193e02b430d707d3b669565fababb4.
Handle the case of an intrinsic where CurrentMethod is still an input.
This will be the case when there are unresolved classes in the
hierarchy.
Add a test case to confirm that we don't crash when handling Math.abs,
which wants to add a pointer to the constant area for the bitmask to be
used to remove the sign bit.
Enhance 565-checker-condition-liveness to check for the case of deeply
nested EmitAtUseSite chains.
Change-Id: I022e8b96a32f5bf464331d0c318c56b9d0ac3c9a
Diffstat (limited to 'compiler/optimizing/intrinsics_x86.cc')
-rw-r--r-- | compiler/optimizing/intrinsics_x86.cc | 116 |
1 files changed, 81 insertions, 35 deletions
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc index acc40bc998..529f678761 100644 --- a/compiler/optimizing/intrinsics_x86.cc +++ b/compiler/optimizing/intrinsics_x86.cc @@ -37,10 +37,12 @@ namespace x86 { static constexpr int kDoubleNaNHigh = 0x7FF80000; static constexpr int kDoubleNaNLow = 0x00000000; -static constexpr int kFloatNaN = 0x7FC00000; +static constexpr int64_t kDoubleNaN = INT64_C(0x7FF8000000000000); +static constexpr int32_t kFloatNaN = INT32_C(0x7FC00000); IntrinsicLocationsBuilderX86::IntrinsicLocationsBuilderX86(CodeGeneratorX86* codegen) - : arena_(codegen->GetGraph()->GetArena()), codegen_(codegen) { + : arena_(codegen->GetGraph()->GetArena()), + codegen_(codegen) { } @@ -256,15 +258,37 @@ static void CreateFloatToFloat(ArenaAllocator* arena, HInvoke* invoke) { LocationSummary::kNoCall, kIntrinsified); locations->SetInAt(0, Location::RequiresFpuRegister()); - // TODO: Allow x86 to work with memory. This requires assembler support, see below. - // locations->SetInAt(0, Location::Any()); // X86 can work on memory directly. locations->SetOut(Location::SameAsFirstInput()); + HInvokeStaticOrDirect* static_or_direct = invoke->AsInvokeStaticOrDirect(); + DCHECK(static_or_direct != nullptr); + if (invoke->InputAt(static_or_direct->GetSpecialInputIndex())->IsX86ComputeBaseMethodAddress()) { + // We need addressibility for the constant area. + locations->SetInAt(1, Location::RequiresRegister()); + // We need a temporary to hold the constant. + locations->AddTemp(Location::RequiresFpuRegister()); + } } -static void MathAbsFP(LocationSummary* locations, bool is64bit, X86Assembler* assembler) { +static void MathAbsFP(LocationSummary* locations, + bool is64bit, + X86Assembler* assembler, + CodeGeneratorX86* codegen) { Location output = locations->Out(); - if (output.IsFpuRegister()) { + DCHECK(output.IsFpuRegister()); + if (locations->InAt(1).IsValid()) { + DCHECK(locations->InAt(1).IsRegister()); + // We also have a constant area pointer. + Register constant_area = locations->InAt(1).AsRegister<Register>(); + XmmRegister temp = locations->GetTemp(0).AsFpuRegister<XmmRegister>(); + if (is64bit) { + __ movsd(temp, codegen->LiteralInt64Address(INT64_C(0x7FFFFFFFFFFFFFFF), constant_area)); + __ andpd(output.AsFpuRegister<XmmRegister>(), temp); + } else { + __ movss(temp, codegen->LiteralInt32Address(INT32_C(0x7FFFFFFF), constant_area)); + __ andps(output.AsFpuRegister<XmmRegister>(), temp); + } + } else { // Create the right constant on an aligned stack. if (is64bit) { __ subl(ESP, Immediate(8)); @@ -277,19 +301,6 @@ static void MathAbsFP(LocationSummary* locations, bool is64bit, X86Assembler* as __ andps(output.AsFpuRegister<XmmRegister>(), Address(ESP, 0)); } __ addl(ESP, Immediate(16)); - } else { - // TODO: update when assember support is available. - UNIMPLEMENTED(FATAL) << "Needs assembler support."; -// Once assembler support is available, in-memory operations look like this: -// if (is64bit) { -// DCHECK(output.IsDoubleStackSlot()); -// __ andl(Address(Register(RSP), output.GetHighStackIndex(kX86WordSize)), -// Immediate(0x7FFFFFFF)); -// } else { -// DCHECK(output.IsStackSlot()); -// // Can use and with a literal directly. -// __ andl(Address(Register(RSP), output.GetStackIndex()), Immediate(0x7FFFFFFF)); -// } } } @@ -298,7 +309,7 @@ void IntrinsicLocationsBuilderX86::VisitMathAbsDouble(HInvoke* invoke) { } void IntrinsicCodeGeneratorX86::VisitMathAbsDouble(HInvoke* invoke) { - MathAbsFP(invoke->GetLocations(), /* is64bit */ true, GetAssembler()); + MathAbsFP(invoke->GetLocations(), /* is64bit */ true, GetAssembler(), codegen_); } void IntrinsicLocationsBuilderX86::VisitMathAbsFloat(HInvoke* invoke) { @@ -306,7 +317,7 @@ void IntrinsicLocationsBuilderX86::VisitMathAbsFloat(HInvoke* invoke) { } void IntrinsicCodeGeneratorX86::VisitMathAbsFloat(HInvoke* invoke) { - MathAbsFP(invoke->GetLocations(), /* is64bit */ false, GetAssembler()); + MathAbsFP(invoke->GetLocations(), /* is64bit */ false, GetAssembler(), codegen_); } static void CreateAbsIntLocation(ArenaAllocator* arena, HInvoke* invoke) { @@ -388,8 +399,11 @@ void IntrinsicCodeGeneratorX86::VisitMathAbsLong(HInvoke* invoke) { GenAbsLong(invoke->GetLocations(), GetAssembler()); } -static void GenMinMaxFP(LocationSummary* locations, bool is_min, bool is_double, - X86Assembler* assembler) { +static void GenMinMaxFP(LocationSummary* locations, + bool is_min, + bool is_double, + X86Assembler* assembler, + CodeGeneratorX86* codegen) { Location op1_loc = locations->InAt(0); Location op2_loc = locations->InAt(1); Location out_loc = locations->Out(); @@ -450,15 +464,26 @@ static void GenMinMaxFP(LocationSummary* locations, bool is_min, bool is_double, // NaN handling. __ Bind(&nan); - if (is_double) { - __ pushl(Immediate(kDoubleNaNHigh)); - __ pushl(Immediate(kDoubleNaNLow)); - __ movsd(out, Address(ESP, 0)); - __ addl(ESP, Immediate(8)); + // Do we have a constant area pointer? + if (locations->InAt(2).IsValid()) { + DCHECK(locations->InAt(2).IsRegister()); + Register constant_area = locations->InAt(2).AsRegister<Register>(); + if (is_double) { + __ movsd(out, codegen->LiteralInt64Address(kDoubleNaN, constant_area)); + } else { + __ movss(out, codegen->LiteralInt32Address(kFloatNaN, constant_area)); + } } else { - __ pushl(Immediate(kFloatNaN)); - __ movss(out, Address(ESP, 0)); - __ addl(ESP, Immediate(4)); + if (is_double) { + __ pushl(Immediate(kDoubleNaNHigh)); + __ pushl(Immediate(kDoubleNaNLow)); + __ movsd(out, Address(ESP, 0)); + __ addl(ESP, Immediate(8)); + } else { + __ pushl(Immediate(kFloatNaN)); + __ movss(out, Address(ESP, 0)); + __ addl(ESP, Immediate(4)); + } } __ jmp(&done); @@ -483,6 +508,11 @@ static void CreateFPFPToFPLocations(ArenaAllocator* arena, HInvoke* invoke) { // The following is sub-optimal, but all we can do for now. It would be fine to also accept // the second input to be the output (we can simply swap inputs). locations->SetOut(Location::SameAsFirstInput()); + HInvokeStaticOrDirect* static_or_direct = invoke->AsInvokeStaticOrDirect(); + DCHECK(static_or_direct != nullptr); + if (invoke->InputAt(static_or_direct->GetSpecialInputIndex())->IsX86ComputeBaseMethodAddress()) { + locations->SetInAt(2, Location::RequiresRegister()); + } } void IntrinsicLocationsBuilderX86::VisitMathMinDoubleDouble(HInvoke* invoke) { @@ -490,7 +520,11 @@ void IntrinsicLocationsBuilderX86::VisitMathMinDoubleDouble(HInvoke* invoke) { } void IntrinsicCodeGeneratorX86::VisitMathMinDoubleDouble(HInvoke* invoke) { - GenMinMaxFP(invoke->GetLocations(), /* is_min */ true, /* is_double */ true, GetAssembler()); + GenMinMaxFP(invoke->GetLocations(), + /* is_min */ true, + /* is_double */ true, + GetAssembler(), + codegen_); } void IntrinsicLocationsBuilderX86::VisitMathMinFloatFloat(HInvoke* invoke) { @@ -498,7 +532,11 @@ void IntrinsicLocationsBuilderX86::VisitMathMinFloatFloat(HInvoke* invoke) { } void IntrinsicCodeGeneratorX86::VisitMathMinFloatFloat(HInvoke* invoke) { - GenMinMaxFP(invoke->GetLocations(), /* is_min */ true, /* is_double */ false, GetAssembler()); + GenMinMaxFP(invoke->GetLocations(), + /* is_min */ true, + /* is_double */ false, + GetAssembler(), + codegen_); } void IntrinsicLocationsBuilderX86::VisitMathMaxDoubleDouble(HInvoke* invoke) { @@ -506,7 +544,11 @@ void IntrinsicLocationsBuilderX86::VisitMathMaxDoubleDouble(HInvoke* invoke) { } void IntrinsicCodeGeneratorX86::VisitMathMaxDoubleDouble(HInvoke* invoke) { - GenMinMaxFP(invoke->GetLocations(), /* is_min */ false, /* is_double */ true, GetAssembler()); + GenMinMaxFP(invoke->GetLocations(), + /* is_min */ false, + /* is_double */ true, + GetAssembler(), + codegen_); } void IntrinsicLocationsBuilderX86::VisitMathMaxFloatFloat(HInvoke* invoke) { @@ -514,7 +556,11 @@ void IntrinsicLocationsBuilderX86::VisitMathMaxFloatFloat(HInvoke* invoke) { } void IntrinsicCodeGeneratorX86::VisitMathMaxFloatFloat(HInvoke* invoke) { - GenMinMaxFP(invoke->GetLocations(), /* is_min */ false, /* is_double */ false, GetAssembler()); + GenMinMaxFP(invoke->GetLocations(), + /* is_min */ false, + /* is_double */ false, + GetAssembler(), + codegen_); } static void GenMinMax(LocationSummary* locations, bool is_min, bool is_long, |