Commit e8145cab authored by yangguo@chromium.org's avatar yangguo@chromium.org

Tweak register allocation for Math.round and do not use roundsd.

R=svenpanne@chromium.org
BUG=

Review URL: https://chromiumcodereview.appspot.com/12374046

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13792 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 46af26a5
......@@ -3733,77 +3733,64 @@ void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
}
}
void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
void LCodeGen::DoMathRound(LMathRound* instr) {
CpuFeatures::Scope scope(SSE2);
Register output_reg = ToRegister(instr->result());
XMMRegister input_reg = ToDoubleRegister(instr->value());
XMMRegister xmm_scratch = xmm0;
XMMRegister input_temp = ToDoubleRegister(instr->temp());
ExternalReference one_half = ExternalReference::address_of_one_half();
ExternalReference minus_one_half =
ExternalReference::address_of_minus_one_half();
bool minus_zero_check =
instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
Label done, round_to_zero, below_one_half, do_not_compensate;
__ movdbl(xmm_scratch, Operand::StaticVariable(one_half));
__ ucomisd(xmm_scratch, input_reg);
__ j(above, &below_one_half);
// CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x).
__ addsd(xmm_scratch, input_reg);
__ cvttsd2si(output_reg, Operand(xmm_scratch));
// Overflow is signalled with minint.
__ cmp(output_reg, 0x80000000u);
__ RecordComment("D2I conversion overflow");
DeoptimizeIf(equal, instr->environment());
__ jmp(&done);
if (CpuFeatures::IsSupported(SSE4_1) && !minus_zero_check) {
CpuFeatures::Scope scope(SSE4_1);
__ addsd(xmm_scratch, input_reg);
__ roundsd(xmm_scratch, xmm_scratch, Assembler::kRoundDown);
__ cvttsd2si(output_reg, Operand(xmm_scratch));
// Overflow is signalled with minint.
__ cmp(output_reg, 0x80000000u);
__ RecordComment("D2I conversion overflow");
DeoptimizeIf(equal, instr->environment());
} else {
Label done, round_to_zero, below_one_half, do_not_compensate;
__ ucomisd(xmm_scratch, input_reg);
__ j(above, &below_one_half);
// CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x).
__ addsd(xmm_scratch, input_reg);
__ cvttsd2si(output_reg, Operand(xmm_scratch));
// Overflow is signalled with minint.
__ cmp(output_reg, 0x80000000u);
__ RecordComment("D2I conversion overflow");
DeoptimizeIf(equal, instr->environment());
__ jmp(&done);
__ bind(&below_one_half);
__ movdbl(xmm_scratch, Operand::StaticVariable(minus_one_half));
__ ucomisd(xmm_scratch, input_reg);
__ j(below_equal, &round_to_zero);
// CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then
// compare and compensate.
__ subsd(input_reg, xmm_scratch);
__ cvttsd2si(output_reg, Operand(input_reg));
// Catch minint due to overflow, and to prevent overflow when compensating.
__ cmp(output_reg, 0x80000000u);
__ RecordComment("D2I conversion overflow");
DeoptimizeIf(equal, instr->environment());
__ bind(&below_one_half);
__ movdbl(xmm_scratch, Operand::StaticVariable(minus_one_half));
__ ucomisd(xmm_scratch, input_reg);
__ j(below_equal, &round_to_zero);
// CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then
// compare and compensate.
__ movsd(input_temp, input_reg); // Do not alter input_reg.
__ subsd(input_temp, xmm_scratch);
__ cvttsd2si(output_reg, Operand(input_temp));
// Catch minint due to overflow, and to prevent overflow when compensating.
__ cmp(output_reg, 0x80000000u);
__ RecordComment("D2I conversion overflow");
DeoptimizeIf(equal, instr->environment());
__ cvtsi2sd(xmm_scratch, output_reg);
__ ucomisd(xmm_scratch, input_reg);
__ j(equal, &done);
__ sub(output_reg, Immediate(1));
// No overflow because we already ruled out minint.
__ jmp(&done);
__ cvtsi2sd(xmm_scratch, output_reg);
__ ucomisd(xmm_scratch, input_temp);
__ j(equal, &done);
__ sub(output_reg, Immediate(1));
// No overflow because we already ruled out minint.
__ jmp(&done);
__ bind(&round_to_zero);
// We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
// we can ignore the difference between a result of -0 and +0.
if (minus_zero_check) {
// If the sign is positive, we return +0.
__ movmskpd(output_reg, input_reg);
__ test(output_reg, Immediate(1));
__ RecordComment("Minus zero");
DeoptimizeIf(not_zero, instr->environment());
}
__ Set(output_reg, Immediate(0));
__ bind(&done);
__ bind(&round_to_zero);
// We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
// we can ignore the difference between a result of -0 and +0.
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
// If the sign is positive, we return +0.
__ movmskpd(output_reg, input_reg);
__ test(output_reg, Immediate(1));
__ RecordComment("Minus zero");
DeoptimizeIf(not_zero, instr->environment());
}
__ Set(output_reg, Immediate(0));
__ bind(&done);
}
......@@ -4035,9 +4022,6 @@ void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
case kMathFloor:
DoMathFloor(instr);
break;
case kMathRound:
DoMathRound(instr);
break;
case kMathSqrt:
DoMathSqrt(instr);
break;
......
......@@ -286,7 +286,6 @@ class LCodeGen BASE_EMBEDDED {
void EmitIntegerMathAbs(LUnaryMathOperation* instr);
void DoMathAbs(LUnaryMathOperation* instr);
void DoMathFloor(LUnaryMathOperation* instr);
void DoMathRound(LUnaryMathOperation* instr);
void DoMathSqrt(LUnaryMathOperation* instr);
void DoMathLog(LUnaryMathOperation* instr);
void DoMathTan(LUnaryMathOperation* instr);
......
......@@ -314,6 +314,12 @@ void LMathPowHalf::PrintDataTo(StringStream* stream) {
}
void LMathRound::PrintDataTo(StringStream* stream) {
stream->Add("/round ");
value()->PrintTo(stream);
}
void LLoadContextSlot::PrintDataTo(StringStream* stream) {
context()->PrintTo(stream);
stream->Add("[%d]", slot_index());
......@@ -1158,21 +1164,16 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
input);
return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
} else {
LOperand* input;
if (op == kMathRound &&
(!CpuFeatures::IsSupported(SSE4_1) ||
instr->CheckFlag(HValue::kBailoutOnMinusZero))) {
// Math.round implemented without roundsd. Input may be overwritten.
ASSERT(instr->value()->representation().IsDouble());
input = UseTempRegister(instr->value());
} else {
input = UseRegisterAtStart(instr->value());
}
LOperand* input = UseRegisterAtStart(instr->value());
LOperand* context = UseAny(instr->context()); // Deferred use by MathAbs.
if (op == kMathPowHalf) {
LOperand* temp = TempRegister();
LMathPowHalf* result = new(zone()) LMathPowHalf(context, input, temp);
return DefineSameAsFirst(result);
} else if (op == kMathRound) {
LOperand* temp = FixedTemp(xmm4);
LMathRound* result = new(zone()) LMathRound(context, input, temp);
return AssignEnvironment(DefineAsRegister(result));
}
LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(context,
input);
......@@ -1181,8 +1182,6 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
case kMathFloor:
return AssignEnvironment(DefineAsRegister(result));
case kMathRound:
return AssignEnvironment(DefineAsRegister(result));
case kMathSqrt:
return DefineSameAsFirst(result);
default:
......
......@@ -133,6 +133,7 @@ class LCodeGen;
V(MathFloorOfDiv) \
V(MathMinMax) \
V(MathPowHalf) \
V(MathRound) \
V(ModI) \
V(MulI) \
V(NumberTagD) \
......@@ -701,6 +702,25 @@ class LMathPowHalf: public LTemplateInstruction<1, 2, 1> {
};
class LMathRound: public LTemplateInstruction<1, 2, 1> {
public:
LMathRound(LOperand* context, LOperand* value, LOperand* temp) {
inputs_[1] = context;
inputs_[0] = value;
temps_[0] = temp;
}
LOperand* context() { return inputs_[1]; }
LOperand* value() { return inputs_[0]; }
LOperand* temp() { return temps_[0]; }
DECLARE_CONCRETE_INSTRUCTION(MathRound, "math-round")
DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
virtual void PrintDataTo(StringStream* stream);
};
class LCmpObjectEqAndBranch: public LControlInstruction<2, 0> {
public:
LCmpObjectEqAndBranch(LOperand* left, LOperand* right) {
......
......@@ -3534,69 +3534,57 @@ void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5
static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5
bool minus_zero_check =
instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
Label done, round_to_zero, below_one_half, do_not_compensate, restore;
__ movq(kScratchRegister, one_half, RelocInfo::NONE64);
__ movq(xmm_scratch, kScratchRegister);
__ ucomisd(xmm_scratch, input_reg);
__ j(above, &below_one_half);
// CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x).
__ addsd(xmm_scratch, input_reg);
__ cvttsd2si(output_reg, xmm_scratch);
// Overflow is signalled with minint.
__ cmpl(output_reg, Immediate(0x80000000));
__ RecordComment("D2I conversion overflow");
DeoptimizeIf(equal, instr->environment());
__ jmp(&done);
if (CpuFeatures::IsSupported(SSE4_1) && !minus_zero_check) {
CpuFeatures::Scope scope(SSE4_1);
__ addsd(xmm_scratch, input_reg);
__ roundsd(xmm_scratch, xmm_scratch, Assembler::kRoundDown);
__ cvttsd2si(output_reg, xmm_scratch);
// Overflow is signalled with minint.
__ cmpl(output_reg, Immediate(0x80000000));
__ RecordComment("D2I conversion overflow");
DeoptimizeIf(equal, instr->environment());
} else {
Label done, round_to_zero, below_one_half, do_not_compensate;
__ ucomisd(xmm_scratch, input_reg);
__ j(above, &below_one_half);
// CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x).
__ addsd(xmm_scratch, input_reg);
__ cvttsd2si(output_reg, xmm_scratch);
// Overflow is signalled with minint.
__ cmpl(output_reg, Immediate(0x80000000));
__ RecordComment("D2I conversion overflow");
DeoptimizeIf(equal, instr->environment());
__ jmp(&done);
__ bind(&below_one_half);
__ movq(kScratchRegister, minus_one_half, RelocInfo::NONE64);
__ movq(xmm_scratch, kScratchRegister);
__ ucomisd(xmm_scratch, input_reg);
__ j(below_equal, &round_to_zero);
__ bind(&below_one_half);
__ movq(kScratchRegister, minus_one_half, RelocInfo::NONE64);
__ movq(xmm_scratch, kScratchRegister);
__ ucomisd(xmm_scratch, input_reg);
__ j(below_equal, &round_to_zero);
// CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then
// compare and compensate.
__ subsd(input_reg, xmm_scratch);
__ cvttsd2si(output_reg, input_reg);
// Catch minint due to overflow, and to prevent overflow when compensating.
__ cmpl(output_reg, Immediate(0x80000000));
__ RecordComment("D2I conversion overflow");
DeoptimizeIf(equal, instr->environment());
// CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then
// compare and compensate.
__ movq(kScratchRegister, input_reg); // Back up input_reg.
__ subsd(input_reg, xmm_scratch);
__ cvttsd2si(output_reg, input_reg);
// Catch minint due to overflow, and to prevent overflow when compensating.
__ cmpl(output_reg, Immediate(0x80000000));
__ RecordComment("D2I conversion overflow");
DeoptimizeIf(equal, instr->environment());
__ cvtlsi2sd(xmm_scratch, output_reg);
__ ucomisd(input_reg, xmm_scratch);
__ j(equal, &done, Label::kNear);
__ subl(output_reg, Immediate(1));
// No overflow because we already ruled out minint.
__ jmp(&done);
__ cvtlsi2sd(xmm_scratch, output_reg);
__ ucomisd(input_reg, xmm_scratch);
__ j(equal, &restore, Label::kNear);
__ subl(output_reg, Immediate(1));
// No overflow because we already ruled out minint.
__ bind(&restore);
__ movq(input_reg, kScratchRegister); // Restore input_reg.
__ jmp(&done);
__ bind(&round_to_zero);
// We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
// we can ignore the difference between a result of -0 and +0.
if (minus_zero_check) {
__ movq(output_reg, input_reg);
__ testq(output_reg, output_reg);
__ RecordComment("Minus zero");
DeoptimizeIf(negative, instr->environment());
}
__ Set(output_reg, 0);
__ bind(&done);
__ bind(&round_to_zero);
// We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
// we can ignore the difference between a result of -0 and +0.
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ movq(output_reg, input_reg);
__ testq(output_reg, output_reg);
__ RecordComment("Minus zero");
DeoptimizeIf(negative, instr->environment());
}
__ Set(output_reg, 0);
__ bind(&done);
}
......
......@@ -1095,16 +1095,7 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
LMathExp* result = new(zone()) LMathExp(value, temp1, temp2);
return DefineAsRegister(result);
} else {
LOperand* input;
if (op == kMathRound &&
(!CpuFeatures::IsSupported(SSE4_1) ||
instr->CheckFlag(HValue::kBailoutOnMinusZero))) {
// Math.round implemented without roundsd. Input may be overwritten.
ASSERT(instr->value()->representation().IsDouble());
input = UseTempRegister(instr->value());
} else {
input = UseRegisterAtStart(instr->value());
}
LOperand* input = UseRegisterAtStart(instr->value());
LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input);
switch (op) {
case kMathAbs:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment