Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(455)

Unified Diff: src/ia32/lithium-codegen-ia32.cc

Issue 20781007: Add X87 implementations for Integer32ToDouble, DoubleToI, DoubleToSmi (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: add a test that was still missing in cl Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-ia32.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ia32/lithium-codegen-ia32.cc
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 6dc0171b00b11e4cbc3659ce07243f2f1d703b16..bffc06267a98726110a941e5550892a817e753c6 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -359,10 +359,9 @@ bool LCodeGen::GenerateBody() {
instr->CompileToNative(this);
- if (!CpuFeatures::IsSupported(SSE2)) {
- if (FLAG_debug_code && FLAG_enable_slow_asserts) {
- __ VerifyX87StackDepth(x87_stack_depth_);
- }
+ if (!CpuFeatures::IsSupported(SSE2) &&
+ FLAG_debug_code && FLAG_enable_slow_asserts) {
+ __ VerifyX87StackDepth(x87_stack_.depth());
}
}
EnsureSpaceForLazyDeopt();
@@ -497,21 +496,21 @@ XMMRegister LCodeGen::ToDoubleRegister(int index) const {
void LCodeGen::X87LoadForUsage(X87Register reg) {
- ASSERT(X87StackContains(reg));
- X87Fxch(reg);
- x87_stack_depth_--;
+ ASSERT(x87_stack_.Contains(reg));
+ x87_stack_.Fxch(reg);
+ x87_stack_.pop();
}
-void LCodeGen::X87Fxch(X87Register reg, int other_slot) {
- ASSERT(X87StackContains(reg) && x87_stack_depth_ > other_slot);
- int i = X87ArrayIndex(reg);
- int st = x87_st2idx(i);
+void LCodeGen::X87Stack::Fxch(X87Register reg, int other_slot) {
+ ASSERT(Contains(reg) && stack_depth_ > other_slot);
+ int i = ArrayIndex(reg);
+ int st = st2idx(i);
if (st != other_slot) {
- int other_i = x87_st2idx(other_slot);
- X87Register other = x87_stack_[other_i];
- x87_stack_[other_i] = reg;
- x87_stack_[i] = other;
+ int other_i = st2idx(other_slot);
+ X87Register other = stack_[other_i];
+ stack_[other_i] = reg;
+ stack_[i] = other;
if (st == 0) {
__ fxch(other_slot);
} else if (other_slot == 0) {
@@ -525,88 +524,101 @@ void LCodeGen::X87Fxch(X87Register reg, int other_slot) {
}
-int LCodeGen::x87_st2idx(int pos) {
- return x87_stack_depth_ - pos - 1;
+int LCodeGen::X87Stack::st2idx(int pos) {
+ return stack_depth_ - pos - 1;
}
-int LCodeGen::X87ArrayIndex(X87Register reg) {
- for (int i = 0; i < x87_stack_depth_; i++) {
- if (x87_stack_[i].is(reg)) return i;
+int LCodeGen::X87Stack::ArrayIndex(X87Register reg) {
+ for (int i = 0; i < stack_depth_; i++) {
+ if (stack_[i].is(reg)) return i;
}
UNREACHABLE();
return -1;
}
-bool LCodeGen::X87StackContains(X87Register reg) {
- for (int i = 0; i < x87_stack_depth_; i++) {
- if (x87_stack_[i].is(reg)) return true;
+bool LCodeGen::X87Stack::Contains(X87Register reg) {
+ for (int i = 0; i < stack_depth_; i++) {
+ if (stack_[i].is(reg)) return true;
}
return false;
}
-void LCodeGen::X87Free(X87Register reg) {
- ASSERT(X87StackContains(reg));
- int i = X87ArrayIndex(reg);
- int st = x87_st2idx(i);
+void LCodeGen::X87Stack::Free(X87Register reg) {
+ ASSERT(Contains(reg));
+ int i = ArrayIndex(reg);
+ int st = st2idx(i);
if (st > 0) {
// keep track of how fstp(i) changes the order of elements
- int tos_i = x87_st2idx(0);
- x87_stack_[i] = x87_stack_[tos_i];
+ int tos_i = st2idx(0);
+ stack_[i] = stack_[tos_i];
}
- x87_stack_depth_--;
+ pop();
__ fstp(st);
}
void LCodeGen::X87Mov(X87Register dst, Operand src, X87OperandType opts) {
- if (X87StackContains(dst)) {
- X87Fxch(dst);
+ if (x87_stack_.Contains(dst)) {
+ x87_stack_.Fxch(dst);
__ fstp(0);
} else {
- ASSERT(x87_stack_depth_ < X87Register::kNumAllocatableRegisters);
- x87_stack_[x87_stack_depth_] = dst;
- x87_stack_depth_++;
+ x87_stack_.push(dst);
}
X87Fld(src, opts);
}
void LCodeGen::X87Fld(Operand src, X87OperandType opts) {
- if (opts == kX87DoubleOperand) {
- __ fld_d(src);
- } else if (opts == kX87FloatOperand) {
- __ fld_s(src);
- } else if (opts == kX87IntOperand) {
- __ fild_s(src);
- } else {
- UNREACHABLE();
+ ASSERT(!src.is_reg_only());
+ switch (opts) {
+ case kX87DoubleOperand:
+ __ fld_d(src);
+ break;
+ case kX87FloatOperand:
+ __ fld_s(src);
+ break;
+ case kX87IntOperand:
+ __ fild_s(src);
+ break;
+ default:
+ UNREACHABLE();
}
}
-void LCodeGen::X87Mov(Operand dst, X87Register src) {
- X87Fxch(src);
- __ fst_d(dst);
+void LCodeGen::X87Mov(Operand dst, X87Register src, X87OperandType opts) {
+ ASSERT(!dst.is_reg_only());
+ x87_stack_.Fxch(src);
+ switch (opts) {
+ case kX87DoubleOperand:
+ __ fst_d(dst);
+ break;
+ case kX87IntOperand:
+ __ fist_s(dst);
+ break;
+ default:
+ UNREACHABLE();
+ }
}
-void LCodeGen::X87PrepareToWrite(X87Register reg) {
- if (X87StackContains(reg)) {
- X87Free(reg);
+void LCodeGen::X87Stack::PrepareToWrite(X87Register reg) {
+ if (Contains(reg)) {
+ Free(reg);
}
// Mark this register as the next register to write to
- x87_stack_[x87_stack_depth_] = reg;
+ stack_[stack_depth_] = reg;
}
-void LCodeGen::X87CommitWrite(X87Register reg) {
+void LCodeGen::X87Stack::CommitWrite(X87Register reg) {
// Assert the reg is prepared to write, but not on the virtual stack yet
- ASSERT(!X87StackContains(reg) && x87_stack_[x87_stack_depth_].is(reg) &&
- x87_stack_depth_ < X87Register::kNumAllocatableRegisters);
- x87_stack_depth_++;
+ ASSERT(!Contains(reg) && stack_[stack_depth_].is(reg) &&
+ stack_depth_ < X87Register::kNumAllocatableRegisters);
+ stack_depth_++;
}
@@ -614,38 +626,47 @@ void LCodeGen::X87PrepareBinaryOp(
X87Register left, X87Register right, X87Register result) {
// You need to use DefineSameAsFirst for x87 instructions
ASSERT(result.is(left));
- X87Fxch(right, 1);
- X87Fxch(left);
+ x87_stack_.Fxch(right, 1);
+ x87_stack_.Fxch(left);
}
-void LCodeGen::FlushX87StackIfNecessary(LInstruction* instr) {
- if (x87_stack_depth_ > 0 && instr->ClobbersDoubleRegisters()) {
+void LCodeGen::X87Stack::FlushIfNecessary(LInstruction* instr, LCodeGen* cgen) {
+ if (stack_depth_ > 0 && instr->ClobbersDoubleRegisters()) {
bool double_inputs = instr->HasDoubleRegisterInput();
// Flush stack from tos down, since FreeX87() will mess with tos
- for (int i = x87_stack_depth_-1; i >= 0; i--) {
- X87Register reg = x87_stack_[i];
+ for (int i = stack_depth_-1; i >= 0; i--) {
+ X87Register reg = stack_[i];
// Skip registers which contain the inputs for the next instruction
// when flushing the stack
- if (double_inputs && instr->IsDoubleInput(reg, this)) {
+ if (double_inputs && instr->IsDoubleInput(reg, cgen)) {
continue;
}
- X87Free(reg);
- if (i < x87_stack_depth_-1) i++;
+ Free(reg);
+ if (i < stack_depth_-1) i++;
}
}
if (instr->IsReturn()) {
- while (x87_stack_depth_ > 0) {
+ while (stack_depth_ > 0) {
__ fstp(0);
- x87_stack_depth_--;
+ stack_depth_--;
}
}
}
void LCodeGen::EmitFlushX87ForDeopt() {
- for (int i = 0; i < x87_stack_depth_; i++) __ fstp(0);
+ // The deoptimizer does not support X87 Registers. But as long as we
+ // deopt from a stub its not a problem, since we will re-materialize the
+ // original stub inputs, which can't be double registers.
+ ASSERT(info()->IsStub());
+ if (FLAG_debug_code && FLAG_enable_slow_asserts) {
+ __ pushfd();
+ __ VerifyX87StackDepth(x87_stack_.depth());
+ __ popfd();
+ }
+ for (int i = 0; i < x87_stack_.depth(); i++) __ fstp(0);
}
@@ -1003,7 +1024,7 @@ void LCodeGen::DeoptimizeIf(Condition cc,
// we can have inputs or outputs of the current instruction on the stack,
// thus we need to flush them here from the physical stack to leave it in a
// consistent state.
- if (x87_stack_depth_ > 0) {
+ if (x87_stack_.depth() > 0) {
Label done;
if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear);
EmitFlushX87ForDeopt();
@@ -1865,15 +1886,16 @@ void LCodeGen::DoConstantD(LConstantD* instr) {
uint64_t int_val = BitCast<uint64_t, double>(v);
int32_t lower = static_cast<int32_t>(int_val);
int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
+ ASSERT(instr->result()->IsDoubleRegister());
if (!CpuFeatures::IsSafeForSnapshot(SSE2)) {
__ push(Immediate(upper));
__ push(Immediate(lower));
- X87Mov(ToX87Register(instr->result()), Operand(esp, 0));
+ X87Register reg = ToX87Register(instr->result());
+ X87Mov(reg, Operand(esp, 0));
__ add(Operand(esp), Immediate(kDoubleSize));
} else {
CpuFeatureScope scope1(masm(), SSE2);
- ASSERT(instr->result()->IsDoubleRegister());
XMMRegister res = ToDoubleRegister(instr->result());
if (int_val == 0) {
__ xorps(res, res);
@@ -2266,7 +2288,6 @@ void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) {
void LCodeGen::DoBranch(LBranch* instr) {
Representation r = instr->hydrogen()->value()->representation();
if (r.IsSmiOrInteger32()) {
- ASSERT(!info()->IsStub());
Register reg = ToRegister(instr->value());
__ test(reg, Operand(reg));
EmitBranch(instr, not_zero);
@@ -4874,15 +4895,20 @@ void LCodeGen::DoStringAdd(LStringAdd* instr) {
void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
+ LOperand* input = instr->value();
+ LOperand* output = instr->result();
+ ASSERT(input->IsRegister() || input->IsStackSlot());
+ ASSERT(output->IsDoubleRegister());
if (CpuFeatures::IsSupported(SSE2)) {
CpuFeatureScope scope(masm(), SSE2);
- LOperand* input = instr->value();
- ASSERT(input->IsRegister() || input->IsStackSlot());
- LOperand* output = instr->result();
- ASSERT(output->IsDoubleRegister());
__ cvtsi2sd(ToDoubleRegister(output), ToOperand(input));
+ } else if (input->IsRegister()) {
+ Register input_reg = ToRegister(input);
+ __ push(input_reg);
+ X87Mov(ToX87Register(output), Operand(esp, 0), kX87IntOperand);
+ __ pop(input_reg);
} else {
- UNREACHABLE();
+ X87Mov(ToX87Register(output), ToOperand(input), kX87IntOperand);
}
}
@@ -5570,44 +5596,75 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
ASSERT(input->IsDoubleRegister());
LOperand* result = instr->result();
ASSERT(result->IsRegister());
- CpuFeatureScope scope(masm(), SSE2);
-
- XMMRegister input_reg = ToDoubleRegister(input);
Register result_reg = ToRegister(result);
- __ cvttsd2si(result_reg, Operand(input_reg));
+ Label done;
+ if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
+ CpuFeatureScope scope(masm(), SSE2);
- if (instr->truncating()) {
- // Performs a truncating conversion of a floating point number as used by
- // the JS bitwise operations.
- Label fast_case_succeeded;
- __ cmp(result_reg, 0x80000000u);
- __ j(not_equal, &fast_case_succeeded);
- __ sub(esp, Immediate(kDoubleSize));
- __ movdbl(MemOperand(esp, 0), input_reg);
- DoubleToIStub stub(esp, result_reg, 0, true);
- __ call(stub.GetCode(isolate()), RelocInfo::CODE_TARGET);
- __ add(esp, Immediate(kDoubleSize));
- __ bind(&fast_case_succeeded);
+ XMMRegister input_reg = ToDoubleRegister(input);
+
+ __ cvttsd2si(result_reg, Operand(input_reg));
+
+ if (instr->truncating()) {
+ // Performs a truncating conversion of a floating point number as used by
+ // the JS bitwise operations.
+ Label fast_case_succeeded;
+ __ cmp(result_reg, 0x80000000u);
+ __ j(not_equal, &fast_case_succeeded);
+ __ sub(esp, Immediate(kDoubleSize));
+ __ movdbl(MemOperand(esp, 0), input_reg);
+ DoubleToIStub stub(esp, result_reg, 0, true);
+ __ call(stub.GetCode(isolate()), RelocInfo::CODE_TARGET);
+ __ add(esp, Immediate(kDoubleSize));
+ __ bind(&fast_case_succeeded);
+ } else {
+ __ cvtsi2sd(xmm0, Operand(result_reg));
+ __ ucomisd(xmm0, input_reg);
+ DeoptimizeIf(not_equal, instr->environment());
+ DeoptimizeIf(parity_even, instr->environment()); // NaN.
+ if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ // The integer converted back is equal to the original. We
+ // only have to test if we got -0 as an input.
+ __ test(result_reg, Operand(result_reg));
+ __ j(not_zero, &done, Label::kNear);
+ __ movmskpd(result_reg, input_reg);
+ // Bit 0 contains the sign of the double in input_reg.
+ // If input was positive, we are ok and return 0, otherwise
+ // deoptimize.
+ __ and_(result_reg, 1);
+ DeoptimizeIf(not_zero, instr->environment());
+ }
+ __ bind(&done);
+ }
} else {
- Label done;
- __ cvtsi2sd(xmm0, Operand(result_reg));
- __ ucomisd(xmm0, input_reg);
- DeoptimizeIf(not_equal, instr->environment());
- DeoptimizeIf(parity_even, instr->environment()); // NaN.
+ X87Register input_reg = ToX87Register(input);
+ __ push(result_reg);
+ X87Mov(Operand(esp, 0), input_reg, kX87IntOperand);
+ if (instr->truncating()) {
+ __ pop(result_reg);
+ } else {
+ X87Fxch(input_reg);
+ __ fld(0);
+ __ fild_s(Operand(esp, 0));
+ __ pop(result_reg);
+ __ FCmp();
+ DeoptimizeIf(not_equal, instr->environment());
+ DeoptimizeIf(parity_even, instr->environment()); // NaN.
+ }
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
- // The integer converted back is equal to the original. We
- // only have to test if we got -0 as an input.
__ test(result_reg, Operand(result_reg));
__ j(not_zero, &done, Label::kNear);
- __ movmskpd(result_reg, input_reg);
- // Bit 0 contains the sign of the double in input_reg.
- // If input was positive, we are ok and return 0, otherwise
- // deoptimize.
- __ and_(result_reg, 1);
+ // To check for minus zero, we load the value again as float, and check
+ // if that is still 0.
+ X87Fxch(input_reg);
+ __ push(result_reg);
+ __ fst_s(Operand(esp, 0));
+ __ pop(result_reg);
+ __ test(result_reg, Operand(result_reg));
DeoptimizeIf(not_zero, instr->environment());
+ __ bind(&done);
}
- __ bind(&done);
}
}
@@ -5617,30 +5674,56 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
ASSERT(input->IsDoubleRegister());
LOperand* result = instr->result();
ASSERT(result->IsRegister());
- CpuFeatureScope scope(masm(), SSE2);
-
- XMMRegister input_reg = ToDoubleRegister(input);
Register result_reg = ToRegister(result);
Label done;
- __ cvttsd2si(result_reg, Operand(input_reg));
- __ cvtsi2sd(xmm0, Operand(result_reg));
- __ ucomisd(xmm0, input_reg);
- DeoptimizeIf(not_equal, instr->environment());
- DeoptimizeIf(parity_even, instr->environment()); // NaN.
+ if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
+ CpuFeatureScope scope(masm(), SSE2);
- if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
- // The integer converted back is equal to the original. We
- // only have to test if we got -0 as an input.
- __ test(result_reg, Operand(result_reg));
- __ j(not_zero, &done, Label::kNear);
- __ movmskpd(result_reg, input_reg);
- // Bit 0 contains the sign of the double in input_reg.
- // If input was positive, we are ok and return 0, otherwise
- // deoptimize.
- __ and_(result_reg, 1);
- DeoptimizeIf(not_zero, instr->environment());
- __ bind(&done);
+ XMMRegister input_reg = ToDoubleRegister(input);
+
+ __ cvttsd2si(result_reg, Operand(input_reg));
+ __ cvtsi2sd(xmm0, Operand(result_reg));
+ __ ucomisd(xmm0, input_reg);
+ DeoptimizeIf(not_equal, instr->environment());
+ DeoptimizeIf(parity_even, instr->environment()); // NaN.
+ if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ // The integer converted back is equal to the original. We
+ // only have to test if we got -0 as an input.
+ __ test(result_reg, Operand(result_reg));
+ __ j(not_zero, &done, Label::kNear);
+ __ movmskpd(result_reg, input_reg);
+ // Bit 0 contains the sign of the double in input_reg.
+ // If input was positive, we are ok and return 0, otherwise
+ // deoptimize.
+ __ and_(result_reg, 1);
+ DeoptimizeIf(not_zero, instr->environment());
+ __ bind(&done);
+ }
+ } else {
+ X87Register input_reg = ToX87Register(input);
+ X87Fxch(input_reg);
+ __ push(result_reg);
+ X87Mov(Operand(esp, 0), input_reg, kX87IntOperand);
+ __ fld(0);
+ __ fild_s(Operand(esp, 0));
+ __ pop(result_reg);
+ __ FCmp();
+ DeoptimizeIf(not_equal, instr->environment());
+ DeoptimizeIf(parity_even, instr->environment()); // NaN.
+
+ if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ __ test(result_reg, Operand(result_reg));
+ __ j(not_zero, &done, Label::kNear);
+ // To check for minus zero, we load the value again as float, and check
+ // if that is still 0.
+ __ push(result_reg);
+ __ fst_s(Operand(esp, 0));
+ __ pop(result_reg);
+ __ test(result_reg, Operand(result_reg));
+ DeoptimizeIf(not_zero, instr->environment());
+ __ bind(&done);
+ }
}
__ SmiTag(result_reg);
DeoptimizeIf(overflow, instr->environment());
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698