| Index: runtime/vm/intermediate_language_ia32.cc
|
| diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
|
| index f25415b1eea6537ac471ffbd7206732240d2ec19..6183aa397ba3a515896579d192c69fa8543b4a05 100644
|
| --- a/runtime/vm/intermediate_language_ia32.cc
|
| +++ b/runtime/vm/intermediate_language_ia32.cc
|
| @@ -4844,8 +4844,57 @@ void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| }
|
|
|
|
|
| -LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const {
|
| - if (kind() == MergedMathInstr::kTruncDivMod) {
|
| +LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(bool opt) const {
|
| + // Only use this instruction in optimized code.
|
| + ASSERT(opt);
|
| + const intptr_t kNumInputs = 1;
|
| + LocationSummary* summary =
|
| + new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall);
|
| + if (representation() == kUnboxedDouble) {
|
| + if (index() == 0) {
|
| + summary->set_in(0, Location::Pair(Location::RequiresFpuRegister(),
|
| + Location::Any()));
|
| + } else {
|
| + ASSERT(index() == 1);
|
| + summary->set_in(0, Location::Pair(Location::Any(),
|
| + Location::RequiresFpuRegister()));
|
| + }
|
| + summary->set_out(0, Location::RequiresFpuRegister());
|
| + } else {
|
| + ASSERT(representation() == kTagged);
|
| + if (index() == 0) {
|
| + summary->set_in(0, Location::Pair(Location::RequiresRegister(),
|
| + Location::Any()));
|
| + } else {
|
| + ASSERT(index() == 1);
|
| + summary->set_in(0, Location::Pair(Location::Any(),
|
| + Location::RequiresRegister()));
|
| + }
|
| + summary->set_out(0, Location::RequiresRegister());
|
| + }
|
| + return summary;
|
| +}
|
| +
|
| +
|
| +void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| + ASSERT(locs()->in(0).IsPairLocation());
|
| + PairLocation* pair = locs()->in(0).AsPairLocation();
|
| + Location in_loc = pair->At(index());
|
| + if (representation() == kUnboxedDouble) {
|
| + XmmRegister out = locs()->out(0).fpu_reg();
|
| + XmmRegister in = in_loc.fpu_reg();
|
| + __ movaps(out, in);
|
| + } else {
|
| + ASSERT(representation() == kTagged);
|
| + Register out = locs()->out(0).reg();
|
| + Register in = in_loc.reg();
|
| + __ movl(out, in);
|
| + }
|
| +}
|
| +
|
| +
|
| +LocationSummary* MergedMath2Instr::MakeLocationSummary(bool opt) const {
|
| + if (kind() == MergedMath2Instr::kTruncDivMod) {
|
| const intptr_t kNumInputs = 2;
|
| const intptr_t kNumTemps = 1;
|
| LocationSummary* summary =
|
| @@ -4853,18 +4902,21 @@ LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const {
|
| // Both inputs must be writable because they will be untagged.
|
| summary->set_in(0, Location::RegisterLocation(EAX));
|
| summary->set_in(1, Location::WritableRegister());
|
| - summary->set_out(0, Location::RequiresRegister());
|
| + // Output is a pair of registers.
|
| + summary->set_out(0, Location::Pair(Location::RequiresRegister(),
|
| + Location::RequiresRegister()));
|
| // Will be used for sign extension and division.
|
| summary->set_temp(0, Location::RegisterLocation(EDX));
|
| return summary;
|
| }
|
| - if (kind() == MergedMathInstr::kSinCos) {
|
| + if (kind() == MergedMath2Instr::kSinCos) {
|
| const intptr_t kNumInputs = 1;
|
| const intptr_t kNumTemps = 0;
|
| LocationSummary* summary =
|
| - new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
|
| - summary->set_in(0, Location::FpuRegisterLocation(XMM1));
|
| - summary->set_out(0, Location::RegisterLocation(EAX));
|
| + new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
| + summary->set_in(0, Location::RequiresFpuRegister());
|
| + summary->set_out(0, Location::Pair(Location::RequiresFpuRegister(),
|
| + Location::RequiresFpuRegister()));
|
| return summary;
|
| }
|
| UNIMPLEMENTED();
|
| @@ -4879,6 +4931,132 @@ extern const RuntimeEntry kSinCosRuntimeEntry(
|
| static_cast<SinCosCFunction>(&SinCos)), 1, true, true);
|
|
|
|
|
| +void MergedMath2Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| + Label* deopt = NULL;
|
| + if (CanDeoptimize()) {
|
| + deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
|
| + }
|
| +
|
| + if (kind() == MergedMath2Instr::kTruncDivMod) {
|
| + Register left = locs()->in(0).reg();
|
| + Register right = locs()->in(1).reg();
|
| + ASSERT(locs()->out(0).IsPairLocation());
|
| + PairLocation* pair = locs()->out(0).AsPairLocation();
|
| + Register result1 = pair->At(0).reg();
|
| + Register result2 = pair->At(1).reg();
|
| + Range* right_range = InputAt(1)->definition()->range();
|
| + if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
|
| + // Handle divide by zero in runtime.
|
| + __ testl(right, right);
|
| + __ j(ZERO, deopt);
|
| + }
|
| + ASSERT(left == EAX);
|
| + ASSERT((right != EDX) && (right != EAX));
|
| + ASSERT(locs()->temp(0).reg() == EDX);
|
| + ASSERT((result1 != EDX) && (result1 != EAX));
|
| + ASSERT((result2 != EDX) && (result2 != EAX));
|
| + __ SmiUntag(left);
|
| + __ SmiUntag(right);
|
| + __ cdq(); // Sign extend EAX -> EDX:EAX.
|
| + __ idivl(right); // EAX: quotient, EDX: remainder.
|
| + // Check the corner case of dividing the 'MIN_SMI' with -1, in which
|
| + // case we cannot tag the result.
|
| + // TODO(srdjan): We could store instead untagged intermediate results in a
|
| + // typed array, but then the load indexed instructions would need to be
|
| + // able to deoptimize.
|
| + __ cmpl(EAX, Immediate(0x40000000));
|
| + __ j(EQUAL, deopt);
|
| + // Modulo result (EDX) correction:
|
| + // res = left % right;
|
| + // if (res < 0) {
|
| + // if (right < 0) {
|
| + // res = res - right;
|
| + // } else {
|
| + // res = res + right;
|
| + // }
|
| + // }
|
| + Label done;
|
| + __ cmpl(EDX, Immediate(0));
|
| + __ j(GREATER_EQUAL, &done, Assembler::kNearJump);
|
| + // Result is negative, adjust it.
|
| + if ((right_range == NULL) || right_range->Overlaps(-1, 1)) {
|
| + Label subtract;
|
| + __ cmpl(right, Immediate(0));
|
| + __ j(LESS, &subtract, Assembler::kNearJump);
|
| + __ addl(EDX, right);
|
| + __ jmp(&done, Assembler::kNearJump);
|
| + __ Bind(&subtract);
|
| + __ subl(EDX, right);
|
| + } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) {
|
| + // Right is positive.
|
| + __ addl(EDX, right);
|
| + } else {
|
| + // Right is negative.
|
| + __ subl(EDX, right);
|
| + }
|
| + __ Bind(&done);
|
| +
|
| + __ SmiTag(EAX);
|
| + __ SmiTag(EDX);
|
| + __ movl(result1, EAX);
|
| + __ movl(result2, EDX);
|
| + return;
|
| + }
|
| +
|
| + if (kind() == MergedMath2Instr::kSinCos) {
|
| + XmmRegister in = locs()->in(0).fpu_reg();
|
| + ASSERT(locs()->out(0).IsPairLocation());
|
| + PairLocation* pair = locs()->out(0).AsPairLocation();
|
| + XmmRegister out1 = pair->At(0).fpu_reg();
|
| + XmmRegister out2 = pair->At(1).fpu_reg();
|
| +
|
| + // Do x87 sincos, since the ia32 compilers may not fuse sin/cos into
|
| + // sincos.
|
| + __ pushl(EAX);
|
| + __ pushl(EAX);
|
| + __ movsd(Address(ESP, 0), in);
|
| + __ fldl(Address(ESP, 0));
|
| + __ fsincos();
|
| + __ fstpl(Address(ESP, 0));
|
| + __ movsd(out1, Address(ESP, 0));
|
| + __ fstpl(Address(ESP, 0));
|
| + __ movsd(out2, Address(ESP, 0));
|
| + __ addl(ESP, Immediate(2 * kWordSize));
|
| + return;
|
| + }
|
| +
|
| + UNIMPLEMENTED();
|
| +}
|
| +
|
| +
|
| +LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const {
|
| + if (kind() == MergedMathInstr::kTruncDivMod) {
|
| + const intptr_t kNumInputs = 2;
|
| + const intptr_t kNumTemps = 1;
|
| + LocationSummary* summary =
|
| + new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
| + // Both inputs must be writable because they will be untagged.
|
| + summary->set_in(0, Location::RegisterLocation(EAX));
|
| + summary->set_in(1, Location::WritableRegister());
|
| + summary->set_out(0, Location::RequiresRegister());
|
| + // Will be used for sign extension and division.
|
| + summary->set_temp(0, Location::RegisterLocation(EDX));
|
| + return summary;
|
| + }
|
| + if (kind() == MergedMathInstr::kSinCos) {
|
| + const intptr_t kNumInputs = 1;
|
| + const intptr_t kNumTemps = 0;
|
| + LocationSummary* summary =
|
| + new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
|
| + summary->set_in(0, Location::FpuRegisterLocation(XMM1));
|
| + summary->set_out(0, Location::RegisterLocation(EAX));
|
| + return summary;
|
| + }
|
| + UNIMPLEMENTED();
|
| + return NULL;
|
| +}
|
| +
|
| +
|
| void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| Label* deopt = NULL;
|
| if (CanDeoptimize()) {
|
|
|