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 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8921 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
b814d6b099
commit
6549163a55
@ -635,6 +635,12 @@ void HBinaryCall::PrintDataTo(StringStream* stream) {
|
||||
}
|
||||
|
||||
|
||||
void HBoundsCheck::PrintDataTo(StringStream* stream) {
|
||||
index()->PrintNameTo(stream);
|
||||
stream->Add(" ");
|
||||
length()->PrintNameTo(stream);
|
||||
}
|
||||
|
||||
void HCallConstantFunction::PrintDataTo(StringStream* stream) {
|
||||
if (IsApplyFunction()) {
|
||||
stream->Add("optimized apply ");
|
||||
@ -1364,6 +1370,20 @@ bool HLoadNamedFieldPolymorphic::DataEquals(HValue* value) {
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
object()->PrintNameTo(stream);
|
||||
stream->Add("[");
|
||||
|
@ -2449,6 +2449,8 @@ class HBoundsCheck: public HTemplateInstruction<2> {
|
||||
return Representation::Integer32();
|
||||
}
|
||||
|
||||
virtual void PrintDataTo(StringStream* stream);
|
||||
|
||||
HValue* index() { return OperandAt(0); }
|
||||
HValue* length() { return OperandAt(1); }
|
||||
|
||||
@ -3416,6 +3418,8 @@ class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> {
|
||||
return Representation::Tagged();
|
||||
}
|
||||
|
||||
virtual void PrintDataTo(StringStream* stream);
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(LoadNamedFieldPolymorphic)
|
||||
|
||||
static const int kMaxLoadPolymorphism = 4;
|
||||
@ -3449,6 +3453,8 @@ class HLoadNamedGeneric: public HTemplateInstruction<2> {
|
||||
return Representation::Tagged();
|
||||
}
|
||||
|
||||
virtual void PrintDataTo(StringStream* stream);
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric)
|
||||
|
||||
private:
|
||||
|
@ -1957,6 +1957,18 @@ void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
@ -941,6 +941,16 @@ class Assembler : public AssemblerBase {
|
||||
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);
|
||||
|
@ -1141,7 +1141,17 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
|
||||
}
|
||||
} 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);
|
||||
|
@ -3830,7 +3830,6 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
|
||||
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 =
|
||||
|
@ -2713,35 +2713,54 @@ void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
|
||||
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 (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);
|
||||
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);
|
||||
}
|
||||
|
||||
// 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;
|
||||
Register output_reg = ToRegister(instr->result());
|
||||
@ -2751,13 +2770,11 @@ void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
|
||||
// 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));
|
||||
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user