Revision: 25018
Author: [email protected]
Date: Thu Oct 30 14:15:20 2014 UTC
Log: Add floor, ceil, round (truncate) instructions for ia32, x64 (if
SSE4.1) and
add floor, ceil, round (truncate and away from zero) for arm64.
[email protected], [email protected], [email protected],
[email protected]
TEST=test/mjsunit/asm/math-floor.js,test/mjsunit/asm/math-ceil.js,test/unittest/compiler/js-builtin-reducer-unittest.cc
Review URL: https://codereview.chromium.org/677433002
https://code.google.com/p/v8/source/detail?r=25018
Added:
/branches/bleeding_edge/test/mjsunit/asm/math-ceil.js
/branches/bleeding_edge/test/mjsunit/asm/math-floor.js
Modified:
/branches/bleeding_edge/src/compiler/arm/code-generator-arm.cc
/branches/bleeding_edge/src/compiler/arm/instruction-codes-arm.h
/branches/bleeding_edge/src/compiler/arm/instruction-selector-arm.cc
/branches/bleeding_edge/src/compiler/arm64/code-generator-arm64.cc
/branches/bleeding_edge/src/compiler/arm64/instruction-codes-arm64.h
/branches/bleeding_edge/src/compiler/arm64/instruction-selector-arm64.cc
/branches/bleeding_edge/src/compiler/ia32/code-generator-ia32.cc
/branches/bleeding_edge/src/compiler/ia32/instruction-codes-ia32.h
/branches/bleeding_edge/src/compiler/ia32/instruction-selector-ia32.cc
/branches/bleeding_edge/src/compiler/instruction-selector.cc
/branches/bleeding_edge/src/compiler/js-builtin-reducer.cc
/branches/bleeding_edge/src/compiler/js-builtin-reducer.h
/branches/bleeding_edge/src/compiler/mips/instruction-selector-mips.cc
/branches/bleeding_edge/src/compiler/raw-machine-assembler.cc
/branches/bleeding_edge/src/compiler/raw-machine-assembler.h
/branches/bleeding_edge/src/compiler/x64/code-generator-x64.cc
/branches/bleeding_edge/src/compiler/x64/instruction-codes-x64.h
/branches/bleeding_edge/src/compiler/x64/instruction-selector-x64.cc
/branches/bleeding_edge/test/cctest/compiler/codegen-tester.h
/branches/bleeding_edge/test/cctest/compiler/test-run-machops.cc
/branches/bleeding_edge/test/unittests/compiler/js-builtin-reducer-unittest.cc
/branches/bleeding_edge/test/unittests/compiler/node-test-utils.cc
/branches/bleeding_edge/test/unittests/compiler/node-test-utils.h
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/asm/math-ceil.js Thu Oct 30
14:15:20 2014 UTC
@@ -0,0 +1,38 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function Module(stdlib) {
+ "use asm";
+
+ var ceil = stdlib.Math.ceil;
+
+ // f: double -> float
+ function f(a) {
+ a = +a;
+ return ceil(a);
+ }
+
+ return { f: f };
+}
+
+var f = Module({ Math: Math }).f;
+
+assertTrue(isNaN(f(NaN)));
+assertTrue(isNaN(f(undefined)));
+assertTrue(isNaN(f(function() {})));
+
+assertEquals(0, f(0));
+assertEquals(+0, f(+0));
+assertEquals(-0, f(-0));
+assertEquals(1, f(0.49999));
+assertEquals(1, f(0.6));
+assertEquals(1, f(0.5));
+assertEquals(-0, f(-0.1));
+assertEquals(-0, f(-0.5));
+assertEquals(-0, f(-0.6));
+assertEquals(-1, f(-1.6));
+assertEquals(-0, f(-0.50001));
+
+assertEquals("Infinity", String(f(Infinity)));
+assertEquals("-Infinity", String(f(-Infinity)));
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/asm/math-floor.js Thu Oct 30
14:15:20 2014 UTC
@@ -0,0 +1,38 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function Module(stdlib) {
+ "use asm";
+
+ var floor = stdlib.Math.floor;
+
+ // f: double -> float
+ function f(a) {
+ a = +a;
+ return floor(a);
+ }
+
+ return { f: f };
+}
+
+var f = Module({ Math: Math }).f;
+
+assertTrue(isNaN(f(NaN)));
+assertTrue(isNaN(f(undefined)));
+assertTrue(isNaN(f(function() {})));
+
+assertEquals(0, f(0));
+assertEquals(+0, f(+0));
+assertEquals(-0, f(-0));
+assertEquals(0, f(0.49999));
+assertEquals(+0, f(0.6));
+assertEquals(+0, f(0.5));
+assertEquals(-1, f(-0.1));
+assertEquals(-1, f(-0.5));
+assertEquals(-1, f(-0.6));
+assertEquals(-2, f(-1.6));
+assertEquals(-1, f(-0.50001));
+
+assertEquals("Infinity", String(f(Infinity)));
+assertEquals("-Infinity", String(f(-Infinity)));
=======================================
--- /branches/bleeding_edge/src/compiler/arm/code-generator-arm.cc Mon Oct
27 12:39:20 2014 UTC
+++ /branches/bleeding_edge/src/compiler/arm/code-generator-arm.cc Thu Oct
30 14:15:20 2014 UTC
@@ -363,6 +363,18 @@
case kArmVsqrtF64:
__ vsqrt(i.OutputFloat64Register(), i.InputFloat64Register(0));
break;
+ case kArmVfloorF64:
+ __ vrintm(i.OutputFloat64Register(), i.InputFloat64Register(0));
+ break;
+ case kArmVceilF64:
+ __ vrintp(i.OutputFloat64Register(), i.InputFloat64Register(0));
+ break;
+ case kArmVroundTruncateF64:
+ __ vrintz(i.OutputFloat64Register(), i.InputFloat64Register(0));
+ break;
+ case kArmVroundTiesAwayF64:
+ __ vrinta(i.OutputFloat64Register(), i.InputFloat64Register(0));
+ break;
case kArmVnegF64:
__ vneg(i.OutputFloat64Register(), i.InputFloat64Register(0));
break;
=======================================
--- /branches/bleeding_edge/src/compiler/arm/instruction-codes-arm.h Tue
Oct 14 11:57:06 2014 UTC
+++ /branches/bleeding_edge/src/compiler/arm/instruction-codes-arm.h Thu
Oct 30 14:15:20 2014 UTC
@@ -44,6 +44,10 @@
V(ArmVmodF64) \
V(ArmVnegF64) \
V(ArmVsqrtF64) \
+ V(ArmVfloorF64) \
+ V(ArmVceilF64) \
+ V(ArmVroundTruncateF64) \
+ V(ArmVroundTiesAwayF64) \
V(ArmVcvtF32F64) \
V(ArmVcvtF64F32) \
V(ArmVcvtF64S32) \
=======================================
--- /branches/bleeding_edge/src/compiler/arm/instruction-selector-arm.cc
Tue Oct 28 13:56:26 2014 UTC
+++ /branches/bleeding_edge/src/compiler/arm/instruction-selector-arm.cc
Thu Oct 30 14:15:20 2014 UTC
@@ -100,6 +100,10 @@
case kArmVmodF64:
case kArmVnegF64:
case kArmVsqrtF64:
+ case kArmVfloorF64:
+ case kArmVceilF64:
+ case kArmVroundTruncateF64:
+ case kArmVroundTiesAwayF64:
case kArmVcvtF32F64:
case kArmVcvtF64F32:
case kArmVcvtF64S32:
@@ -113,6 +117,14 @@
return false;
}
};
+
+
+static void VisitRRFloat64(InstructionSelector* selector, ArchOpcode
opcode,
+ Node* node) {
+ ArmOperandGenerator g(selector);
+ selector->Emit(opcode, g.DefineAsRegister(node),
+ g.UseRegister(node->InputAt(0)));
+}
static void VisitRRRFloat64(InstructionSelector* selector, ArchOpcode
opcode,
@@ -824,6 +836,30 @@
ArmOperandGenerator g(this);
Emit(kArmVsqrtF64, g.DefineAsRegister(node),
g.UseRegister(node->InputAt(0)));
}
+
+
+void InstructionSelector::VisitFloat64Floor(Node* node) {
+ DCHECK(CpuFeatures::IsSupported(ARMv8));
+ VisitRRFloat64(this, kArmVfloorF64, node);
+}
+
+
+void InstructionSelector::VisitFloat64Ceil(Node* node) {
+ DCHECK(CpuFeatures::IsSupported(ARMv8));
+ VisitRRFloat64(this, kArmVceilF64, node);
+}
+
+
+void InstructionSelector::VisitFloat64RoundTruncate(Node* node) {
+ DCHECK(CpuFeatures::IsSupported(ARMv8));
+ VisitRRFloat64(this, kArmVroundTruncateF64, node);
+}
+
+
+void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
+ DCHECK(CpuFeatures::IsSupported(ARMv8));
+ VisitRRFloat64(this, kArmVroundTiesAwayF64, node);
+}
void InstructionSelector::VisitCall(Node* node) {
@@ -1139,10 +1175,19 @@
// static
MachineOperatorBuilder::Flags
InstructionSelector::SupportedMachineOperatorFlags() {
- return MachineOperatorBuilder::kInt32DivIsSafe |
- MachineOperatorBuilder::kInt32ModIsSafe |
- MachineOperatorBuilder::kUint32DivIsSafe |
- MachineOperatorBuilder::kUint32ModIsSafe;
+ MachineOperatorBuilder::Flags flags =
+ MachineOperatorBuilder::kInt32DivIsSafe |
+ MachineOperatorBuilder::kInt32ModIsSafe |
+ MachineOperatorBuilder::kUint32DivIsSafe |
+ MachineOperatorBuilder::kUint32ModIsSafe;
+
+ if (CpuFeatures::IsSupported(ARMv8)) {
+ flags |= MachineOperatorBuilder::kFloat64Floor |
+ MachineOperatorBuilder::kFloat64Ceil |
+ MachineOperatorBuilder::kFloat64RoundTruncate |
+ MachineOperatorBuilder::kFloat64RoundTiesAway;
+ }
+ return flags;
}
} // namespace compiler
=======================================
--- /branches/bleeding_edge/src/compiler/arm64/code-generator-arm64.cc Mon
Oct 27 12:39:20 2014 UTC
+++ /branches/bleeding_edge/src/compiler/arm64/code-generator-arm64.cc Thu
Oct 30 14:15:20 2014 UTC
@@ -222,6 +222,18 @@
case kArchTruncateDoubleToI:
__ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
break;
+ case kArm64Float64Ceil:
+ __ Frintp(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
+ break;
+ case kArm64Float64Floor:
+ __ Frintm(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
+ break;
+ case kArm64Float64RoundTruncate:
+ __ Frintz(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
+ break;
+ case kArm64Float64RoundTiesAway:
+ __ Frinta(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
+ break;
case kArm64Add:
__ Add(i.OutputRegister(), i.InputRegister(0),
i.InputOperand2_64(1));
break;
=======================================
--- /branches/bleeding_edge/src/compiler/arm64/instruction-codes-arm64.h
Tue Oct 14 11:57:06 2014 UTC
+++ /branches/bleeding_edge/src/compiler/arm64/instruction-codes-arm64.h
Thu Oct 30 14:15:20 2014 UTC
@@ -78,6 +78,10 @@
V(Arm64Float64Div) \
V(Arm64Float64Mod) \
V(Arm64Float64Sqrt) \
+ V(Arm64Float64Floor) \
+ V(Arm64Float64Ceil) \
+ V(Arm64Float64RoundTruncate) \
+ V(Arm64Float64RoundTiesAway) \
V(Arm64Float32ToFloat64) \
V(Arm64Float64ToFloat32) \
V(Arm64Float64ToInt32) \
=======================================
---
/branches/bleeding_edge/src/compiler/arm64/instruction-selector-arm64.cc
Wed Oct 29 16:47:10 2014 UTC
+++
/branches/bleeding_edge/src/compiler/arm64/instruction-selector-arm64.cc
Thu Oct 30 14:15:20 2014 UTC
@@ -84,6 +84,14 @@
Assembler::IsImmLSUnscaled(value);
}
};
+
+
+static void VisitRRFloat64(InstructionSelector* selector, ArchOpcode
opcode,
+ Node* node) {
+ Arm64OperandGenerator g(selector);
+ selector->Emit(opcode, g.DefineAsRegister(node),
+ g.UseRegister(node->InputAt(0)));
+}
static void VisitRRR(InstructionSelector* selector, ArchOpcode opcode,
@@ -899,9 +907,27 @@
void InstructionSelector::VisitFloat64Sqrt(Node* node) {
- Arm64OperandGenerator g(this);
- Emit(kArm64Float64Sqrt, g.DefineAsRegister(node),
- g.UseRegister(node->InputAt(0)));
+ VisitRRFloat64(this, kArm64Float64Sqrt, node);
+}
+
+
+void InstructionSelector::VisitFloat64Floor(Node* node) {
+ VisitRRFloat64(this, kArm64Float64Floor, node);
+}
+
+
+void InstructionSelector::VisitFloat64Ceil(Node* node) {
+ VisitRRFloat64(this, kArm64Float64Ceil, node);
+}
+
+
+void InstructionSelector::VisitFloat64RoundTruncate(Node* node) {
+ VisitRRFloat64(this, kArm64Float64RoundTruncate, node);
+}
+
+
+void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
+ VisitRRFloat64(this, kArm64Float64RoundTiesAway, node);
}
@@ -1317,9 +1343,11 @@
// static
MachineOperatorBuilder::Flags
InstructionSelector::SupportedMachineOperatorFlags() {
- return MachineOperatorBuilder::kNoFlags;
+ return MachineOperatorBuilder::kFloat64Floor |
+ MachineOperatorBuilder::kFloat64Ceil |
+ MachineOperatorBuilder::kFloat64RoundTruncate |
+ MachineOperatorBuilder::kFloat64RoundTiesAway;
}
-
} // namespace compiler
} // namespace internal
} // namespace v8
=======================================
--- /branches/bleeding_edge/src/compiler/ia32/code-generator-ia32.cc Mon
Oct 27 12:39:20 2014 UTC
+++ /branches/bleeding_edge/src/compiler/ia32/code-generator-ia32.cc Thu
Oct 30 14:15:20 2014 UTC
@@ -353,6 +353,24 @@
case kSSEFloat64Sqrt:
__ sqrtsd(i.OutputDoubleRegister(), i.InputOperand(0));
break;
+ case kSSEFloat64Floor: {
+ CpuFeatureScope sse_scope(masm(), SSE4_1);
+ __ roundsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
+ v8::internal::Assembler::kRoundDown);
+ break;
+ }
+ case kSSEFloat64Ceil: {
+ CpuFeatureScope sse_scope(masm(), SSE4_1);
+ __ roundsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
+ v8::internal::Assembler::kRoundUp);
+ break;
+ }
+ case kSSEFloat64RoundTruncate: {
+ CpuFeatureScope sse_scope(masm(), SSE4_1);
+ __ roundsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
+ v8::internal::Assembler::kRoundToZero);
+ break;
+ }
case kSSECvtss2sd:
__ cvtss2sd(i.OutputDoubleRegister(), i.InputOperand(0));
break;
=======================================
--- /branches/bleeding_edge/src/compiler/ia32/instruction-codes-ia32.h Tue
Oct 14 11:57:06 2014 UTC
+++ /branches/bleeding_edge/src/compiler/ia32/instruction-codes-ia32.h Thu
Oct 30 14:15:20 2014 UTC
@@ -36,6 +36,9 @@
V(SSEFloat64Div) \
V(SSEFloat64Mod) \
V(SSEFloat64Sqrt) \
+ V(SSEFloat64Floor) \
+ V(SSEFloat64Ceil) \
+ V(SSEFloat64RoundTruncate) \
V(SSECvtss2sd) \
V(SSECvtsd2ss) \
V(SSEFloat64ToInt32) \
=======================================
--- /branches/bleeding_edge/src/compiler/ia32/instruction-selector-ia32.cc
Tue Oct 28 13:56:26 2014 UTC
+++ /branches/bleeding_edge/src/compiler/ia32/instruction-selector-ia32.cc
Thu Oct 30 14:15:20 2014 UTC
@@ -140,6 +140,14 @@
InstructionOperand* displacement_operand_;
AddressingMode mode_;
};
+
+
+static void VisitRRFloat64(InstructionSelector* selector, ArchOpcode
opcode,
+ Node* node) {
+ IA32OperandGenerator g(selector);
+ selector->Emit(opcode, g.DefineAsRegister(node),
+ g.UseRegister(node->InputAt(0)));
+}
void InstructionSelector::VisitLoad(Node* node) {
@@ -596,6 +604,29 @@
}
+void InstructionSelector::VisitFloat64Floor(Node* node) {
+ DCHECK(CpuFeatures::IsSupported(SSE4_1));
+ VisitRRFloat64(this, kSSEFloat64Floor, node);
+}
+
+
+void InstructionSelector::VisitFloat64Ceil(Node* node) {
+ DCHECK(CpuFeatures::IsSupported(SSE4_1));
+ VisitRRFloat64(this, kSSEFloat64Ceil, node);
+}
+
+
+void InstructionSelector::VisitFloat64RoundTruncate(Node* node) {
+ DCHECK(CpuFeatures::IsSupported(SSE4_1));
+ VisitRRFloat64(this, kSSEFloat64RoundTruncate, node);
+}
+
+
+void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
+ UNREACHABLE();
+}
+
+
void InstructionSelector::VisitCall(Node* node) {
IA32OperandGenerator g(this);
CallDescriptor* descriptor = OpParameter<CallDescriptor*>(node);
@@ -881,9 +912,13 @@
// static
MachineOperatorBuilder::Flags
InstructionSelector::SupportedMachineOperatorFlags() {
- return MachineOperatorBuilder::kNoFlags;
+ if (CpuFeatures::IsSupported(SSE4_1)) {
+ return MachineOperatorBuilder::kFloat64Floor |
+ MachineOperatorBuilder::kFloat64Ceil |
+ MachineOperatorBuilder::kFloat64RoundTruncate;
+ }
+ return MachineOperatorBuilder::Flag::kNoFlags;
}
-
} // namespace compiler
} // namespace internal
} // namespace v8
=======================================
--- /branches/bleeding_edge/src/compiler/instruction-selector.cc Thu Oct 30
09:50:15 2014 UTC
+++ /branches/bleeding_edge/src/compiler/instruction-selector.cc Thu Oct 30
14:15:20 2014 UTC
@@ -603,6 +603,10 @@
case IrOpcode::kFloat64Div:
case IrOpcode::kFloat64Mod:
case IrOpcode::kFloat64Sqrt:
+ case IrOpcode::kFloat64Floor:
+ case IrOpcode::kFloat64Ceil:
+ case IrOpcode::kFloat64RoundTruncate:
+ case IrOpcode::kFloat64RoundTiesAway:
return kMachFloat64;
case IrOpcode::kFloat64Equal:
case IrOpcode::kFloat64LessThan:
@@ -792,11 +796,20 @@
return VisitFloat64LessThan(node);
case IrOpcode::kFloat64LessThanOrEqual:
return VisitFloat64LessThanOrEqual(node);
+ case IrOpcode::kFloat64Floor:
+ return MarkAsDouble(node), VisitFloat64Floor(node);
+ case IrOpcode::kFloat64Ceil:
+ return MarkAsDouble(node), VisitFloat64Ceil(node);
+ case IrOpcode::kFloat64RoundTruncate:
+ return MarkAsDouble(node), VisitFloat64RoundTruncate(node);
+ case IrOpcode::kFloat64RoundTiesAway:
+ return MarkAsDouble(node), VisitFloat64RoundTiesAway(node);
case IrOpcode::kLoadStackPointer:
return VisitLoadStackPointer(node);
default:
V8_Fatal(__FILE__, __LINE__, "Unexpected operator #%d:%s @ node #%d",
node->opcode(), node->op()->mnemonic(), node->id());
+ break;
}
}
=======================================
--- /branches/bleeding_edge/src/compiler/js-builtin-reducer.cc Wed Oct 29
18:46:44 2014 UTC
+++ /branches/bleeding_edge/src/compiler/js-builtin-reducer.cc Thu Oct 30
14:15:20 2014 UTC
@@ -189,6 +189,32 @@
}
return NoChange();
}
+
+
+// ES6 draft 10-14-14, section 20.2.2.16.
+Reduction JSBuiltinReducer::ReduceMathFloor(Node* node) {
+ if (!machine()->HasFloat64Floor()) return NoChange();
+ JSCallReduction r(node);
+ if (r.InputsMatchOne(Type::Number())) {
+ // Math.floor(a:number) -> Float64Floor(a)
+ Node* value = graph()->NewNode(machine()->Float64Floor(), r.left());
+ return Replace(value);
+ }
+ return NoChange();
+}
+
+
+// ES6 draft 10-14-14, section 20.2.2.10.
+Reduction JSBuiltinReducer::ReduceMathCeil(Node* node) {
+ if (!machine()->HasFloat64Ceil()) return NoChange();
+ JSCallReduction r(node);
+ if (r.InputsMatchOne(Type::Number())) {
+ // Math.ceil(a:number) -> Float64Ceil(a)
+ Node* value = graph()->NewNode(machine()->Float64Ceil(), r.left());
+ return Replace(value);
+ }
+ return NoChange();
+}
Reduction JSBuiltinReducer::Reduce(Node* node) {
@@ -207,6 +233,10 @@
return ReplaceWithPureReduction(node, ReduceMathImul(node));
case kMathFround:
return ReplaceWithPureReduction(node, ReduceMathFround(node));
+ case kMathFloor:
+ return ReplaceWithPureReduction(node, ReduceMathFloor(node));
+ case kMathCeil:
+ return ReplaceWithPureReduction(node, ReduceMathCeil(node));
default:
break;
}
=======================================
--- /branches/bleeding_edge/src/compiler/js-builtin-reducer.h Fri Sep 26
14:06:56 2014 UTC
+++ /branches/bleeding_edge/src/compiler/js-builtin-reducer.h Thu Oct 30
14:15:20 2014 UTC
@@ -35,6 +35,8 @@
Reduction ReduceMathMax(Node* node);
Reduction ReduceMathImul(Node* node);
Reduction ReduceMathFround(Node* node);
+ Reduction ReduceMathFloor(Node* node);
+ Reduction ReduceMathCeil(Node* node);
JSGraph* jsgraph_;
SimplifiedOperatorBuilder simplified_;
=======================================
--- /branches/bleeding_edge/src/compiler/mips/instruction-selector-mips.cc
Tue Oct 28 16:54:35 2014 UTC
+++ /branches/bleeding_edge/src/compiler/mips/instruction-selector-mips.cc
Thu Oct 30 14:15:20 2014 UTC
@@ -407,6 +407,22 @@
MipsOperandGenerator g(this);
Emit(kMipsSqrtD, g.DefineAsRegister(node),
g.UseRegister(node->InputAt(0)));
}
+
+
+void InstructionSelector::VisitFloat64Floor(Node* node) { UNREACHABLE(); }
+
+
+void InstructionSelector::VisitFloat64Ceil(Node* node) { UNREACHABLE(); }
+
+
+void InstructionSelector::VisitFloat64RoundTruncate(Node* node) {
+ UNREACHABLE();
+}
+
+
+void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
+ UNREACHABLE();
+}
void InstructionSelector::VisitCall(Node* node) {
=======================================
--- /branches/bleeding_edge/src/compiler/raw-machine-assembler.cc Mon Oct
27 10:12:16 2014 UTC
+++ /branches/bleeding_edge/src/compiler/raw-machine-assembler.cc Thu Oct
30 14:15:20 2014 UTC
@@ -13,10 +13,11 @@
RawMachineAssembler::RawMachineAssembler(Graph* graph,
MachineSignature* machine_sig,
- MachineType word)
+ MachineType word,
+ MachineOperatorBuilder::Flags
flags)
: GraphBuilder(graph),
schedule_(new (zone()) Schedule(zone())),
- machine_(word),
+ machine_(word, flags),
common_(zone()),
machine_sig_(machine_sig),
call_descriptor_(
=======================================
--- /branches/bleeding_edge/src/compiler/raw-machine-assembler.h Mon Oct 27
10:12:16 2014 UTC
+++ /branches/bleeding_edge/src/compiler/raw-machine-assembler.h Thu Oct 30
14:15:20 2014 UTC
@@ -45,7 +45,9 @@
};
RawMachineAssembler(Graph* graph, MachineSignature* machine_sig,
- MachineType word = kMachPtr);
+ MachineType word = kMachPtr,
+ MachineOperatorBuilder::Flags flags =
+ MachineOperatorBuilder::Flag::kNoFlags);
virtual ~RawMachineAssembler() {}
Isolate* isolate() const { return zone()->isolate(); }
@@ -380,6 +382,14 @@
Node* TruncateInt64ToInt32(Node* a) {
return NewNode(machine()->TruncateInt64ToInt32(), a);
}
+ Node* Float64Floor(Node* a) { return NewNode(machine()->Float64Floor(),
a); }
+ Node* Float64Ceil(Node* a) { return NewNode(machine()->Float64Ceil(),
a); }
+ Node* Float64RoundTruncate(Node* a) {
+ return NewNode(machine()->Float64RoundTruncate(), a);
+ }
+ Node* Float64RoundTiesAway(Node* a) {
+ return NewNode(machine()->Float64RoundTiesAway(), a);
+ }
// Parameters.
Node* Parameter(size_t index);
=======================================
--- /branches/bleeding_edge/src/compiler/x64/code-generator-x64.cc Mon Oct
27 12:39:20 2014 UTC
+++ /branches/bleeding_edge/src/compiler/x64/code-generator-x64.cc Thu Oct
30 14:15:20 2014 UTC
@@ -407,6 +407,24 @@
__ sqrtsd(i.OutputDoubleRegister(), i.InputOperand(0));
}
break;
+ case kSSEFloat64Floor: {
+ CpuFeatureScope sse_scope(masm(), SSE4_1);
+ __ roundsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
+ v8::internal::Assembler::kRoundDown);
+ break;
+ }
+ case kSSEFloat64Ceil: {
+ CpuFeatureScope sse_scope(masm(), SSE4_1);
+ __ roundsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
+ v8::internal::Assembler::kRoundUp);
+ break;
+ }
+ case kSSEFloat64RoundTruncate: {
+ CpuFeatureScope sse_scope(masm(), SSE4_1);
+ __ roundsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
+ v8::internal::Assembler::kRoundToZero);
+ break;
+ }
case kSSECvtss2sd:
if (instr->InputAt(0)->IsDoubleRegister()) {
__ cvtss2sd(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
=======================================
--- /branches/bleeding_edge/src/compiler/x64/instruction-codes-x64.h Tue
Oct 14 11:57:06 2014 UTC
+++ /branches/bleeding_edge/src/compiler/x64/instruction-codes-x64.h Thu
Oct 30 14:15:20 2014 UTC
@@ -52,6 +52,9 @@
V(SSEFloat64Div) \
V(SSEFloat64Mod) \
V(SSEFloat64Sqrt) \
+ V(SSEFloat64Floor) \
+ V(SSEFloat64Ceil) \
+ V(SSEFloat64RoundTruncate) \
V(SSECvtss2sd) \
V(SSECvtsd2ss) \
V(SSEFloat64ToInt32) \
=======================================
--- /branches/bleeding_edge/src/compiler/x64/instruction-selector-x64.cc
Tue Oct 28 13:56:26 2014 UTC
+++ /branches/bleeding_edge/src/compiler/x64/instruction-selector-x64.cc
Thu Oct 30 14:15:20 2014 UTC
@@ -118,6 +118,14 @@
InstructionOperand* displacement_operand_;
AddressingMode mode_;
};
+
+
+static void VisitRRFloat64(InstructionSelector* selector, ArchOpcode
opcode,
+ Node* node) {
+ X64OperandGenerator g(selector);
+ selector->Emit(opcode, g.DefineAsRegister(node),
+ g.UseRegister(node->InputAt(0)));
+}
void InstructionSelector::VisitLoad(Node* node) {
@@ -723,6 +731,29 @@
}
+void InstructionSelector::VisitFloat64Floor(Node* node) {
+ DCHECK(CpuFeatures::IsSupported(SSE4_1));
+ VisitRRFloat64(this, kSSEFloat64Floor, node);
+}
+
+
+void InstructionSelector::VisitFloat64Ceil(Node* node) {
+ DCHECK(CpuFeatures::IsSupported(SSE4_1));
+ VisitRRFloat64(this, kSSEFloat64Ceil, node);
+}
+
+
+void InstructionSelector::VisitFloat64RoundTruncate(Node* node) {
+ DCHECK(CpuFeatures::IsSupported(SSE4_1));
+ VisitRRFloat64(this, kSSEFloat64RoundTruncate, node);
+}
+
+
+void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
+ UNREACHABLE();
+}
+
+
void InstructionSelector::VisitCall(Node* node) {
X64OperandGenerator g(this);
CallDescriptor* descriptor = OpParameter<CallDescriptor*>(node);
@@ -1112,9 +1143,13 @@
// static
MachineOperatorBuilder::Flags
InstructionSelector::SupportedMachineOperatorFlags() {
+ if (CpuFeatures::IsSupported(SSE4_1)) {
+ return MachineOperatorBuilder::kFloat64Floor |
+ MachineOperatorBuilder::kFloat64Ceil |
+ MachineOperatorBuilder::kFloat64RoundTruncate;
+ }
return MachineOperatorBuilder::kNoFlags;
}
-
} // namespace compiler
} // namespace internal
} // namespace v8
=======================================
--- /branches/bleeding_edge/test/cctest/compiler/codegen-tester.h Mon Oct
27 12:39:20 2014 UTC
+++ /branches/bleeding_edge/test/cctest/compiler/codegen-tester.h Thu Oct
30 14:15:20 2014 UTC
@@ -7,6 +7,7 @@
#include "src/v8.h"
+#include "src/compiler/instruction-selector.h"
#include "src/compiler/pipeline.h"
#include "src/compiler/raw-machine-assembler.h"
#include "src/simulator.h"
@@ -23,7 +24,9 @@
public:
MachineAssemblerTester(MachineType return_type, MachineType p0,
MachineType p1, MachineType p2, MachineType p3,
- MachineType p4)
+ MachineType p4,
+ MachineOperatorBuilder::Flags flags =
+ MachineOperatorBuilder::Flag::kNoFlags)
: HandleAndZoneScope(),
CallHelper(
main_isolate(),
@@ -31,7 +34,7 @@
MachineAssembler(
new (main_zone()) Graph(main_zone()),
MakeMachineSignature(main_zone(), return_type, p0, p1, p2, p3,
p4),
- kMachPtr) {}
+ kMachPtr, flags) {}
Node* LoadFromPointer(void* address, MachineType rep, int32_t offset =
0) {
return this->Load(rep, this->PointerConstant(address),
@@ -89,8 +92,8 @@
MachineType p3 = kMachNone,
MachineType p4 = kMachNone)
: MachineAssemblerTester<RawMachineAssembler>(
- ReturnValueTraits<ReturnType>::Representation(), p0, p1, p2,
p3,
- p4) {}
+ ReturnValueTraits<ReturnType>::Representation(), p0, p1, p2,
p3, p4,
+ InstructionSelector::SupportedMachineOperatorFlags()) {}
template <typename Ci, typename Fn>
void Run(const Ci& ci, const Fn& fn) {
=======================================
--- /branches/bleeding_edge/test/cctest/compiler/test-run-machops.cc Thu
Oct 30 09:00:58 2014 UTC
+++ /branches/bleeding_edge/test/cctest/compiler/test-run-machops.cc Thu
Oct 30 14:15:20 2014 UTC
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <cmath>
#include <functional>
#include <limits>
@@ -4536,4 +4537,171 @@
}
}
+
+static double two_30 = 1 << 30; // 2^30 is a smi boundary.
+static double two_52 = two_30 * (1 << 22); // 2^52 is a precision
boundary.
+static double kValues[] = {0.1,
+ 0.2,
+ 0.49999999999999994,
+ 0.5,
+ 0.7,
+ 1.0 - std::numeric_limits<double>::epsilon(),
+ -0.1,
+ -0.49999999999999994,
+ -0.5,
+ -0.7,
+ 1.1,
+ 1.0 + std::numeric_limits<double>::epsilon(),
+ 1.5,
+ 1.7,
+ -1,
+ -1 + std::numeric_limits<double>::epsilon(),
+ -1 - std::numeric_limits<double>::epsilon(),
+ -1.1,
+ -1.5,
+ -1.7,
+ std::numeric_limits<double>::min(),
+ -std::numeric_limits<double>::min(),
+ std::numeric_limits<double>::max(),
+ -std::numeric_limits<double>::max(),
+ std::numeric_limits<double>::infinity(),
+ -std::numeric_limits<double>::infinity(),
+ two_30,
+ two_30 + 0.1,
+ two_30 + 0.5,
+ two_30 + 0.7,
+ two_30 - 1,
+ two_30 - 1 + 0.1,
+ two_30 - 1 + 0.5,
+ two_30 - 1 + 0.7,
+ -two_30,
+ -two_30 + 0.1,
+ -two_30 + 0.5,
+ -two_30 + 0.7,
+ -two_30 + 1,
+ -two_30 + 1 + 0.1,
+ -two_30 + 1 + 0.5,
+ -two_30 + 1 + 0.7,
+ two_52,
+ two_52 + 0.1,
+ two_52 + 0.5,
+ two_52 + 0.5,
+ two_52 + 0.7,
+ two_52 + 0.7,
+ two_52 - 1,
+ two_52 - 1 + 0.1,
+ two_52 - 1 + 0.5,
+ two_52 - 1 + 0.7,
+ -two_52,
+ -two_52 + 0.1,
+ -two_52 + 0.5,
+ -two_52 + 0.7,
+ -two_52 + 1,
+ -two_52 + 1 + 0.1,
+ -two_52 + 1 + 0.5,
+ -two_52 + 1 + 0.7,
+ two_30,
+ two_30 - 0.1,
+ two_30 - 0.5,
+ two_30 - 0.7,
+ two_30 - 1,
+ two_30 - 1 - 0.1,
+ two_30 - 1 - 0.5,
+ two_30 - 1 - 0.7,
+ -two_30,
+ -two_30 - 0.1,
+ -two_30 - 0.5,
+ -two_30 - 0.7,
+ -two_30 + 1,
+ -two_30 + 1 - 0.1,
+ -two_30 + 1 - 0.5,
+ -two_30 + 1 - 0.7,
+ two_52,
+ two_52 - 0.1,
+ two_52 - 0.5,
+ two_52 - 0.5,
+ two_52 - 0.7,
+ two_52 - 0.7,
+ two_52 - 1,
+ two_52 - 1 - 0.1,
+ two_52 - 1 - 0.5,
+ two_52 - 1 - 0.7,
+ -two_52,
+ -two_52 - 0.1,
+ -two_52 - 0.5,
+ -two_52 - 0.7,
+ -two_52 + 1,
+ -two_52 + 1 - 0.1,
+ -two_52 + 1 - 0.5,
+ -two_52 + 1 - 0.7};
+
+
+TEST(RunFloat64Floor) {
+ double input = -1.0;
+ double result = 0.0;
+ RawMachineAssemblerTester<int32_t> m;
+ if (!m.machine()->HasFloat64Floor()) return;
+ m.StoreToPointer(&result, kMachFloat64,
+ m.Float64Floor(m.LoadFromPointer(&input,
kMachFloat64)));
+ m.Return(m.Int32Constant(0));
+ for (size_t i = 0; i < arraysize(kValues); ++i) {
+ input = kValues[i];
+ CHECK_EQ(0, m.Call());
+ double expected = std::floor(kValues[i]);
+ CHECK_EQ(expected, result);
+ }
+}
+
+
+TEST(RunFloat64Ceil) {
+ double input = -1.0;
+ double result = 0.0;
+ RawMachineAssemblerTester<int32_t> m;
+ if (!m.machine()->HasFloat64Ceil()) return;
+ m.StoreToPointer(&result, kMachFloat64,
+ m.Float64Ceil(m.LoadFromPointer(&input, kMachFloat64)));
+ m.Return(m.Int32Constant(0));
+ for (size_t i = 0; i < arraysize(kValues); ++i) {
+ input = kValues[i];
+ CHECK_EQ(0, m.Call());
+ double expected = std::ceil(kValues[i]);
+ CHECK_EQ(expected, result);
+ }
+}
+
+
+TEST(RunFloat64RoundTruncate) {
+ double input = -1.0;
+ double result = 0.0;
+ RawMachineAssemblerTester<int32_t> m;
+ if (!m.machine()->HasFloat64Ceil()) return;
+ m.StoreToPointer(
+ &result, kMachFloat64,
+ m.Float64RoundTruncate(m.LoadFromPointer(&input, kMachFloat64)));
+ m.Return(m.Int32Constant(0));
+ for (size_t i = 0; i < arraysize(kValues); ++i) {
+ input = kValues[i];
+ CHECK_EQ(0, m.Call());
+ double expected = trunc(kValues[i]);
+ CHECK_EQ(expected, result);
+ }
+}
+
+
+TEST(RunFloat64RoundTiesAway) {
+ double input = -1.0;
+ double result = 0.0;
+ RawMachineAssemblerTester<int32_t> m;
+ if (!m.machine()->HasFloat64RoundTiesAway()) return;
+ m.StoreToPointer(
+ &result, kMachFloat64,
+ m.Float64RoundTiesAway(m.LoadFromPointer(&input, kMachFloat64)));
+ m.Return(m.Int32Constant(0));
+ for (size_t i = 0; i < arraysize(kValues); ++i) {
+ input = kValues[i];
+ CHECK_EQ(0, m.Call());
+ double expected = round(kValues[i]);
+ CHECK_EQ(expected, result);
+ }
+}
#endif // V8_TURBOFAN_TARGET
=======================================
---
/branches/bleeding_edge/test/unittests/compiler/js-builtin-reducer-unittest.cc
Mon Oct 20 11:26:23 2014 UTC
+++
/branches/bleeding_edge/test/unittests/compiler/js-builtin-reducer-unittest.cc
Thu Oct 30 14:15:20 2014 UTC
@@ -21,8 +21,9 @@
JSBuiltinReducerTest() : javascript_(zone()) {}
protected:
- Reduction Reduce(Node* node) {
- MachineOperatorBuilder machine;
+ Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags =
+ MachineOperatorBuilder::Flag::kNoFlags)
{
+ MachineOperatorBuilder machine(kMachPtr, flags);
JSGraph jsgraph(graph(), common(), javascript(), &machine);
JSBuiltinReducer reducer(&jsgraph);
return reducer.Reduce(node);
@@ -237,6 +238,79 @@
}
}
+
+//
-----------------------------------------------------------------------------
+// Math.floor
+
+
+TEST_F(JSBuiltinReducerTest, MathFloorAvailable) {
+ Handle<JSFunction> f = MathFunction("floor");
+
+ TRACED_FOREACH(Type*, t0, kNumberTypes) {
+ Node* p0 = Parameter(t0, 0);
+ Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
+ Node* call =
+ graph()->NewNode(javascript()->CallFunction(3,
NO_CALL_FUNCTION_FLAGS),
+ fun, UndefinedConstant(), p0);
+ Reduction r = Reduce(call,
MachineOperatorBuilder::Flag::kFloat64Floor);
+
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsFloat64Floor(p0));
+ }
+}
+
+
+TEST_F(JSBuiltinReducerTest, MathFloorUnavailable) {
+ Handle<JSFunction> f = MathFunction("floor");
+
+ TRACED_FOREACH(Type*, t0, kNumberTypes) {
+ Node* p0 = Parameter(t0, 0);
+ Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
+ Node* call =
+ graph()->NewNode(javascript()->CallFunction(3,
NO_CALL_FUNCTION_FLAGS),
+ fun, UndefinedConstant(), p0);
+ Reduction r = Reduce(call, MachineOperatorBuilder::Flag::kNoFlags);
+
+ ASSERT_FALSE(r.Changed());
+ }
+}
+
+
+//
-----------------------------------------------------------------------------
+// Math.ceil
+
+
+TEST_F(JSBuiltinReducerTest, MathCeilAvailable) {
+ Handle<JSFunction> f = MathFunction("ceil");
+
+ TRACED_FOREACH(Type*, t0, kNumberTypes) {
+ Node* p0 = Parameter(t0, 0);
+ Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
+ Node* call =
+ graph()->NewNode(javascript()->CallFunction(3,
NO_CALL_FUNCTION_FLAGS),
+ fun, UndefinedConstant(), p0);
+ Reduction r = Reduce(call, MachineOperatorBuilder::Flag::kFloat64Ceil);
+
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsFloat64Ceil(p0));
+ }
+}
+
+
+TEST_F(JSBuiltinReducerTest, MathCeilUnavailable) {
+ Handle<JSFunction> f = MathFunction("ceil");
+
+ TRACED_FOREACH(Type*, t0, kNumberTypes) {
+ Node* p0 = Parameter(t0, 0);
+ Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
+ Node* call =
+ graph()->NewNode(javascript()->CallFunction(3,
NO_CALL_FUNCTION_FLAGS),
+ fun, UndefinedConstant(), p0);
+ Reduction r = Reduce(call, MachineOperatorBuilder::Flag::kNoFlags);
+
+ ASSERT_FALSE(r.Changed());
+ }
+}
} // namespace compiler
} // namespace internal
} // namespace v8
=======================================
--- /branches/bleeding_edge/test/unittests/compiler/node-test-utils.cc Wed
Oct 29 14:16:32 2014 UTC
+++ /branches/bleeding_edge/test/unittests/compiler/node-test-utils.cc Thu
Oct 30 14:15:20 2014 UTC
@@ -949,6 +949,10 @@
IS_UNOP_MATCHER(TruncateFloat64ToInt32)
IS_UNOP_MATCHER(TruncateInt64ToInt32)
IS_UNOP_MATCHER(Float64Sqrt)
+IS_UNOP_MATCHER(Float64Floor)
+IS_UNOP_MATCHER(Float64Ceil)
+IS_UNOP_MATCHER(Float64RoundTruncate)
+IS_UNOP_MATCHER(Float64RoundTiesAway)
#undef IS_UNOP_MATCHER
} // namespace compiler
=======================================
--- /branches/bleeding_edge/test/unittests/compiler/node-test-utils.h Wed
Oct 29 14:16:32 2014 UTC
+++ /branches/bleeding_edge/test/unittests/compiler/node-test-utils.h Thu
Oct 30 14:15:20 2014 UTC
@@ -149,6 +149,10 @@
Matcher<Node*> IsTruncateFloat64ToInt32(const Matcher<Node*>&
input_matcher);
Matcher<Node*> IsTruncateInt64ToInt32(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsFloat64Sqrt(const Matcher<Node*>& input_matcher);
+Matcher<Node*> IsFloat64Floor(const Matcher<Node*>& input_matcher);
+Matcher<Node*> IsFloat64Ceil(const Matcher<Node*>& input_matcher);
+Matcher<Node*> IsFloat64RoundTruncate(const Matcher<Node*>& input_matcher);
+Matcher<Node*> IsFloat64RoundTiesAway(const Matcher<Node*>& input_matcher);
} // namespace compiler
} // namespace internal
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.