Revision: 8921
Author: [email protected]
Date: Fri Aug 12 03:13:40 2011
Log: Add roundsd instruction to ia32 and use it in optimized
Math.floor.
It is available platforms that have SSE 4.1 and allows us to handle
negative numbers without deoptimization. Before we would deoptimize
on negative inputs to Math.floor. x64 already uses this instruction.
* Change Math.floor unit test to make sure every test case gets
optimized by changing the source code for each test case.
* Fix HIR debug printing for some instructions.
Review URL: http://codereview.chromium.org/7628017
http://code.google.com/p/v8/source/detail?r=8921
Modified:
/branches/bleeding_edge/src/hydrogen-instructions.cc
/branches/bleeding_edge/src/hydrogen-instructions.h
/branches/bleeding_edge/src/ia32/assembler-ia32.cc
/branches/bleeding_edge/src/ia32/assembler-ia32.h
/branches/bleeding_edge/src/ia32/disasm-ia32.cc
/branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
/branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
/branches/bleeding_edge/test/mjsunit/math-floor.js
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.cc Wed Aug 10
05:32:43 2011
+++ /branches/bleeding_edge/src/hydrogen-instructions.cc Fri Aug 12
03:13:40 2011
@@ -635,6 +635,12 @@
}
+void HBoundsCheck::PrintDataTo(StringStream* stream) {
+ index()->PrintNameTo(stream);
+ stream->Add(" ");
+ length()->PrintNameTo(stream);
+}
+
void HCallConstantFunction::PrintDataTo(StringStream* stream) {
if (IsApplyFunction()) {
stream->Add("optimized apply ");
@@ -1362,6 +1368,20 @@
}
return true;
}
+
+
+void HLoadNamedFieldPolymorphic::PrintDataTo(StringStream* stream) {
+ object()->PrintNameTo(stream);
+ stream->Add(" .");
+ stream->Add(*String::cast(*name())->ToCString());
+}
+
+
+void HLoadNamedGeneric::PrintDataTo(StringStream* stream) {
+ object()->PrintNameTo(stream);
+ stream->Add(" .");
+ stream->Add(*String::cast(*name())->ToCString());
+}
void HLoadKeyedFastElement::PrintDataTo(StringStream* stream) {
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Thu Aug 11 07:00:16
2011
+++ /branches/bleeding_edge/src/hydrogen-instructions.h Fri Aug 12 03:13:40
2011
@@ -2448,6 +2448,8 @@
virtual Representation RequiredInputRepresentation(int index) const {
return Representation::Integer32();
}
+
+ virtual void PrintDataTo(StringStream* stream);
HValue* index() { return OperandAt(0); }
HValue* length() { return OperandAt(1); }
@@ -3415,6 +3417,8 @@
virtual Representation RequiredInputRepresentation(int index) const {
return Representation::Tagged();
}
+
+ virtual void PrintDataTo(StringStream* stream);
DECLARE_CONCRETE_INSTRUCTION(LoadNamedFieldPolymorphic)
@@ -3448,6 +3452,8 @@
virtual Representation RequiredInputRepresentation(int index) const {
return Representation::Tagged();
}
+
+ virtual void PrintDataTo(StringStream* stream);
DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
=======================================
--- /branches/bleeding_edge/src/ia32/assembler-ia32.cc Wed Jun 8 06:55:33
2011
+++ /branches/bleeding_edge/src/ia32/assembler-ia32.cc Fri Aug 12 03:13:40
2011
@@ -1957,6 +1957,18 @@
}
+void Assembler::roundsd(XMMRegister dst, XMMRegister src, RoundingMode
mode) {
+ ASSERT(CpuFeatures::IsEnabled(SSE4_1));
+ EnsureSpace ensure_space(this);
+ EMIT(0x66);
+ EMIT(0x0F);
+ EMIT(0x3A);
+ EMIT(0x0B);
+ emit_sse_operand(dst, src);
+ // Mask precision exeption.
+ EMIT(static_cast<byte>(mode) | 0x8);
+}
+
void Assembler::movmskpd(Register dst, XMMRegister src) {
ASSERT(CpuFeatures::IsEnabled(SSE2));
EnsureSpace ensure_space(this);
=======================================
--- /branches/bleeding_edge/src/ia32/assembler-ia32.h Thu Jun 30 06:05:03
2011
+++ /branches/bleeding_edge/src/ia32/assembler-ia32.h Fri Aug 12 03:13:40
2011
@@ -941,6 +941,16 @@
void andpd(XMMRegister dst, XMMRegister src);
void ucomisd(XMMRegister dst, XMMRegister src);
+
+ enum RoundingMode {
+ kRoundToNearest = 0x0,
+ kRoundDown = 0x1,
+ kRoundUp = 0x2,
+ kRoundToZero = 0x3
+ };
+
+ void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode);
+
void movmskpd(Register dst, XMMRegister src);
void cmpltsd(XMMRegister dst, XMMRegister src);
=======================================
--- /branches/bleeding_edge/src/ia32/disasm-ia32.cc Fri Aug 5 04:32:46 2011
+++ /branches/bleeding_edge/src/ia32/disasm-ia32.cc Fri Aug 12 03:13:40 2011
@@ -1141,7 +1141,17 @@
}
} else if (*data == 0x3A) {
data++;
- if (*data == 0x16) {
+ if (*data == 0x0B) {
+ data++;
+ int mod, regop, rm;
+ get_modrm(*data, &mod, ®op, &rm);
+ int8_t imm8 = static_cast<int8_t>(data[1]);
+ AppendToBuffer("roundsd %s,%s,%d",
+ NameOfXMMRegister(regop),
+ NameOfXMMRegister(rm),
+ static_cast<int>(imm8));
+ data += 2;
+ } else if (*data == 0x16) {
data++;
int mod, regop, rm;
get_modrm(*data, &mod, ®op, &rm);
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Wed Aug 10
05:12:06 2011
+++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Fri Aug 12
03:13:40 2011
@@ -3830,7 +3830,6 @@
void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
const char* comment) {
- // TODO(svenpanne): Allowing format strings in Comment would be nice
here...
Comment cmt(masm_, comment);
bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
UnaryOverwriteMode overwrite =
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Thu Aug 11
07:00:16 2011
+++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Fri Aug 12
03:13:40 2011
@@ -2713,34 +2713,53 @@
XMMRegister xmm_scratch = xmm0;
Register output_reg = ToRegister(instr->result());
XMMRegister input_reg = ToDoubleRegister(instr->value());
- Label done;
-
- // Deoptimize on negative numbers.
- __ xorps(xmm_scratch, xmm_scratch); // Zero the register.
- __ ucomisd(input_reg, xmm_scratch);
- DeoptimizeIf(below, instr->environment());
-
- if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
- // Check for negative zero.
- Label positive_sign;
- __ j(above, &positive_sign, Label::kNear);
- __ movmskpd(output_reg, input_reg);
- __ test(output_reg, Immediate(1));
- DeoptimizeIf(not_zero, instr->environment());
- __ Set(output_reg, Immediate(0));
- __ jmp(&done, Label::kNear);
- __ bind(&positive_sign);
- }
-
- // Use truncating instruction (OK because input is positive).
- __ cvttsd2si(output_reg, Operand(input_reg));
-
- // Overflow is signalled with minint.
- __ cmp(output_reg, 0x80000000u);
- DeoptimizeIf(equal, instr->environment());
- __ bind(&done);
-}
-
+
+ if (CpuFeatures::IsSupported(SSE4_1)) {
+ CpuFeatures::Scope scope(SSE4_1);
+ if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ // Deoptimize on negative zero.
+ Label non_zero;
+ __ xorps(xmm_scratch, xmm_scratch); // Zero the register.
+ __ ucomisd(input_reg, xmm_scratch);
+ __ j(not_equal, &non_zero, Label::kNear);
+ __ movmskpd(output_reg, input_reg);
+ __ test(output_reg, Immediate(1));
+ DeoptimizeIf(not_zero, instr->environment());
+ __ bind(&non_zero);
+ }
+ __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown);
+ __ cvttsd2si(output_reg, Operand(xmm_scratch));
+ // Overflow is signalled with minint.
+ __ cmp(output_reg, 0x80000000u);
+ DeoptimizeIf(equal, instr->environment());
+ } else {
+ Label done;
+ // Deoptimize on negative numbers.
+ __ xorps(xmm_scratch, xmm_scratch); // Zero the register.
+ __ ucomisd(input_reg, xmm_scratch);
+ DeoptimizeIf(below, instr->environment());
+
+ if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ // Check for negative zero.
+ Label positive_sign;
+ __ j(above, &positive_sign, Label::kNear);
+ __ movmskpd(output_reg, input_reg);
+ __ test(output_reg, Immediate(1));
+ DeoptimizeIf(not_zero, instr->environment());
+ __ Set(output_reg, Immediate(0));
+ __ jmp(&done, Label::kNear);
+ __ bind(&positive_sign);
+ }
+
+ // Use truncating instruction (OK because input is positive).
+ __ cvttsd2si(output_reg, Operand(input_reg));
+
+ // Overflow is signalled with minint.
+ __ cmp(output_reg, 0x80000000u);
+ DeoptimizeIf(equal, instr->environment());
+ __ bind(&done);
+ }
+}
void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
XMMRegister xmm_scratch = xmm0;
@@ -2751,13 +2770,11 @@
// xmm_scratch = 0.5
ExternalReference one_half = ExternalReference::address_of_one_half();
__ movdbl(xmm_scratch, Operand::StaticVariable(one_half));
-
__ ucomisd(xmm_scratch, input_reg);
__ j(above, &below_half);
// input = input + 0.5
__ addsd(input_reg, xmm_scratch);
-
// Compute Math.floor(value + 0.5).
// Use truncating instruction (OK because input is positive).
__ cvttsd2si(output_reg, Operand(input_reg));
=======================================
--- /branches/bleeding_edge/test/mjsunit/math-floor.js Wed Aug 10 05:32:43
2011
+++ /branches/bleeding_edge/test/mjsunit/math-floor.js Fri Aug 12 03:13:40
2011
@@ -27,10 +27,11 @@
// Flags: --max-new-space-size=256 --allow-natives-syntax
+var test_id = 0;
+
function testFloor(expect, input) {
- function test(n) {
- return Math.floor(n);
- }
+ var test = new Function('n',
+ '"' + (test_id++) + '";return Math.floor(n)');
assertEquals(expect, test(input));
assertEquals(expect, test(input));
assertEquals(expect, test(input));
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev