Commit 37058c14 authored by bmeurer@chromium.org's avatar bmeurer@chromium.org

[turbofan] Add TruncateFloat64ToInt32 machine operator.

Fix ChangeLowering to use TruncateFloat64ToInt32.

TEST=cctest,compiler-unittests
R=jarin@chromium.org

Review URL: https://codereview.chromium.org/484103002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23214 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 597123b8
......@@ -158,6 +158,10 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
DCHECK_EQ(LeaveCC, i.OutputSBit());
break;
}
case kArchTruncateDoubleToI:
__ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
DCHECK_EQ(LeaveCC, i.OutputSBit());
break;
case kArmAdd:
__ add(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1),
i.OutputSBit());
......
......@@ -74,6 +74,7 @@ class ArmOperandGenerator V8_FINAL : public OperandGenerator {
case kArchNop:
case kArchRet:
case kArchDeoptimize:
case kArchTruncateDoubleToI:
case kArmMul:
case kArmMla:
case kArmMls:
......
......@@ -149,6 +149,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
break;
}
case kArchTruncateDoubleToI:
__ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
break;
case kArm64Add:
__ Add(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
......
......@@ -124,7 +124,7 @@ Reduction ChangeLowering::ChangeTaggedToInt32(Node* val, Node* control) {
Node* load = graph()->NewNode(
machine()->Load(kMachFloat64), val, HeapNumberValueIndexConstant(),
graph()->NewNode(common()->ControlEffect(), if_true));
Node* change = graph()->NewNode(machine()->ChangeFloat64ToInt32(), load);
Node* change = graph()->NewNode(machine()->TruncateFloat64ToInt32(), load);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* integer =
......
......@@ -129,6 +129,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
break;
}
case kArchTruncateDoubleToI:
__ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
break;
case kIA32Add:
if (HasImmediateInput(instr, 1)) {
__ add(i.InputOperand(0), i.InputImmediate(1));
......
......@@ -33,6 +33,7 @@ namespace compiler {
V(ArchJmp) \
V(ArchNop) \
V(ArchRet) \
V(ArchTruncateDoubleToI) \
TARGET_ARCH_OPCODE_LIST(V)
enum ArchOpcode {
......
......@@ -587,6 +587,8 @@ void InstructionSelector::VisitNode(Node* node) {
return VisitChangeInt32ToInt64(node);
case IrOpcode::kChangeUint32ToUint64:
return VisitChangeUint32ToUint64(node);
case IrOpcode::kTruncateFloat64ToInt32:
return VisitTruncateFloat64ToInt32(node);
case IrOpcode::kTruncateInt64ToInt32:
return VisitTruncateInt64ToInt32(node);
case IrOpcode::kFloat64Add:
......@@ -690,6 +692,13 @@ void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) {
}
void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
OperandGenerator g(this);
Emit(kArchTruncateDoubleToI, g.DefineAsRegister(node),
g.UseDoubleRegister(node->InputAt(0)));
}
void InstructionSelector::VisitFloat64Equal(Node* node) {
FlagsContinuation cont(kUnorderedEqual, node);
VisitFloat64Compare(node, &cont);
......
......@@ -358,6 +358,9 @@ class MachineNodeFactory {
Node* ChangeUint32ToUint64(Node* a) {
return NEW_NODE_1(MACHINE()->ChangeUint32ToUint64(), a);
}
Node* TruncateFloat64ToInt32(Node* a) {
return NEW_NODE_1(MACHINE()->TruncateFloat64ToInt32(), a);
}
Node* TruncateInt64ToInt32(Node* a) {
return NEW_NODE_1(MACHINE()->TruncateInt64ToInt32(), a);
}
......
......@@ -134,6 +134,9 @@ class MachineOperatorBuilder {
Operator* ChangeInt32ToInt64() { UNOP(ChangeInt32ToInt64); }
Operator* ChangeUint32ToUint64() { UNOP(ChangeUint32ToUint64); }
// Truncate double to int32 using JavaScript semantics.
Operator* TruncateFloat64ToInt32() { UNOP(TruncateFloat64ToInt32); }
// Truncate the high order bits and convert the remaining bits to int32.
Operator* TruncateInt64ToInt32() { UNOP(TruncateInt64ToInt32); }
......
......@@ -159,61 +159,62 @@
V(StoreElement)
// Opcodes for Machine-level operators.
#define MACHINE_OP_LIST(V) \
V(Load) \
V(Store) \
V(Word32And) \
V(Word32Or) \
V(Word32Xor) \
V(Word32Shl) \
V(Word32Shr) \
V(Word32Sar) \
V(Word32Ror) \
V(Word32Equal) \
V(Word64And) \
V(Word64Or) \
V(Word64Xor) \
V(Word64Shl) \
V(Word64Shr) \
V(Word64Sar) \
V(Word64Ror) \
V(Word64Equal) \
V(Int32Add) \
V(Int32AddWithOverflow) \
V(Int32Sub) \
V(Int32SubWithOverflow) \
V(Int32Mul) \
V(Int32Div) \
V(Int32UDiv) \
V(Int32Mod) \
V(Int32UMod) \
V(Int32LessThan) \
V(Int32LessThanOrEqual) \
V(Uint32LessThan) \
V(Uint32LessThanOrEqual) \
V(Int64Add) \
V(Int64Sub) \
V(Int64Mul) \
V(Int64Div) \
V(Int64UDiv) \
V(Int64Mod) \
V(Int64UMod) \
V(Int64LessThan) \
V(Int64LessThanOrEqual) \
V(ChangeInt32ToFloat64) \
V(ChangeUint32ToFloat64) \
V(ChangeFloat64ToInt32) \
V(ChangeFloat64ToUint32) \
V(ChangeInt32ToInt64) \
V(ChangeUint32ToUint64) \
V(TruncateInt64ToInt32) \
V(Float64Add) \
V(Float64Sub) \
V(Float64Mul) \
V(Float64Div) \
V(Float64Mod) \
V(Float64Equal) \
V(Float64LessThan) \
#define MACHINE_OP_LIST(V) \
V(Load) \
V(Store) \
V(Word32And) \
V(Word32Or) \
V(Word32Xor) \
V(Word32Shl) \
V(Word32Shr) \
V(Word32Sar) \
V(Word32Ror) \
V(Word32Equal) \
V(Word64And) \
V(Word64Or) \
V(Word64Xor) \
V(Word64Shl) \
V(Word64Shr) \
V(Word64Sar) \
V(Word64Ror) \
V(Word64Equal) \
V(Int32Add) \
V(Int32AddWithOverflow) \
V(Int32Sub) \
V(Int32SubWithOverflow) \
V(Int32Mul) \
V(Int32Div) \
V(Int32UDiv) \
V(Int32Mod) \
V(Int32UMod) \
V(Int32LessThan) \
V(Int32LessThanOrEqual) \
V(Uint32LessThan) \
V(Uint32LessThanOrEqual) \
V(Int64Add) \
V(Int64Sub) \
V(Int64Mul) \
V(Int64Div) \
V(Int64UDiv) \
V(Int64Mod) \
V(Int64UMod) \
V(Int64LessThan) \
V(Int64LessThanOrEqual) \
V(ChangeInt32ToFloat64) \
V(ChangeUint32ToFloat64) \
V(ChangeFloat64ToInt32) \
V(ChangeFloat64ToUint32) \
V(ChangeInt32ToInt64) \
V(ChangeUint32ToUint64) \
V(TruncateFloat64ToInt32) \
V(TruncateInt64ToInt32) \
V(Float64Add) \
V(Float64Sub) \
V(Float64Mul) \
V(Float64Div) \
V(Float64Mod) \
V(Float64Equal) \
V(Float64LessThan) \
V(Float64LessThanOrEqual)
#define VALUE_OP_LIST(V) \
......
......@@ -222,6 +222,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
break;
}
case kArchTruncateDoubleToI:
__ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
break;
case kX64Add32:
ASSEMBLE_BINOP(addl);
break;
......
......@@ -194,7 +194,10 @@
'test-mark-compact/Promotion': [PASS, FAIL],
# BUG(v8:3434).
' test-api/LoadICFastApi_DirectCall_GCMoveStubWithProfiler': [SKIP]
' test-api/LoadICFastApi_DirectCall_GCMoveStubWithProfiler': [SKIP],
# TODO(rodolph): Please investigate.
'test-run-machops/RunTruncateFloat64ToInt32P': [SKIP],
}], # 'arch == arm64'
['arch == arm64 and simulator_run == True', {
......
......@@ -4245,4 +4245,74 @@ TEST(RunTruncateInt64ToInt32P) {
}
}
TEST(RunTruncateFloat64ToInt32P) {
struct {
double from;
double raw;
} kValues[] = {{0, 0},
{0.5, 0},
{-0.5, 0},
{1.5, 1},
{-1.5, -1},
{5.5, 5},
{-5.0, -5},
{v8::base::OS::nan_value(), 0},
{std::numeric_limits<double>::infinity(), 0},
{-v8::base::OS::nan_value(), 0},
{-std::numeric_limits<double>::infinity(), 0},
{4.94065645841e-324, 0},
{-4.94065645841e-324, 0},
{0.9999999999999999, 0},
{-0.9999999999999999, 0},
{4294967296.0, 0},
{-4294967296.0, 0},
{9223372036854775000.0, 4294966272.0},
{-9223372036854775000.0, -4294966272.0},
{4.5036e+15, 372629504},
{-4.5036e+15, -372629504},
{287524199.5377777, 0x11234567},
{-287524199.5377777, -0x11234567},
{2300193596.302222, 2300193596.0},
{-2300193596.302222, -2300193596.0},
{4600387192.604444, 305419896},
{-4600387192.604444, -305419896},
{4823855600872397.0, 1737075661},
{-4823855600872397.0, -1737075661},
{4503603922337791.0, -1},
{-4503603922337791.0, 1},
{4503601774854143.0, 2147483647},
{-4503601774854143.0, -2147483647},
{9007207844675582.0, -2},
{-9007207844675582.0, 2},
{2.4178527921507624e+24, -536870912},
{-2.4178527921507624e+24, 536870912},
{2.417853945072267e+24, -536870912},
{-2.417853945072267e+24, 536870912},
{4.8357055843015248e+24, -1073741824},
{-4.8357055843015248e+24, 1073741824},
{4.8357078901445341e+24, -1073741824},
{-4.8357078901445341e+24, 1073741824},
{2147483647.0, 2147483647.0},
{-2147483648.0, -2147483648.0},
{9.6714111686030497e+24, -2147483648.0},
{-9.6714111686030497e+24, -2147483648.0},
{9.6714157802890681e+24, -2147483648.0},
{-9.6714157802890681e+24, -2147483648.0},
{1.9342813113834065e+25, 2147483648.0},
{-1.9342813113834065e+25, 2147483648.0},
{3.868562622766813e+25, 0},
{-3.868562622766813e+25, 0},
{1.7976931348623157e+308, 0},
{-1.7976931348623157e+308, 0}};
double input = -1.0;
RawMachineAssemblerTester<int32_t> m;
m.Return(m.TruncateFloat64ToInt32(m.LoadFromPointer(&input, kMachFloat64)));
for (size_t i = 0; i < ARRAY_SIZE(kValues); ++i) {
input = kValues[i].from;
uint64_t expected = static_cast<int64_t>(kValues[i].raw);
CHECK_EQ(static_cast<int>(expected), m.Call());
}
}
#endif // V8_TURBOFAN_TARGET
......@@ -263,7 +263,7 @@ TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToInt32) {
Capture<Node*> branch, if_true;
EXPECT_THAT(
phi,
IsPhi(IsChangeFloat64ToInt32(IsLoad(
IsPhi(IsTruncateFloat64ToInt32(IsLoad(
kMachFloat64, val, IsInt32Constant(HeapNumberValueOffset()),
IsControlEffect(CaptureEq(&if_true)))),
IsWord32Sar(val, IsInt32Constant(SmiShiftAmount())),
......@@ -341,7 +341,7 @@ TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToInt32) {
Capture<Node*> branch, if_true;
EXPECT_THAT(
phi,
IsPhi(IsChangeFloat64ToInt32(IsLoad(
IsPhi(IsTruncateFloat64ToInt32(IsLoad(
kMachFloat64, val, IsInt32Constant(HeapNumberValueOffset()),
IsControlEffect(CaptureEq(&if_true)))),
IsTruncateInt64ToInt32(
......
......@@ -680,6 +680,7 @@ IS_UNOP_MATCHER(ChangeFloat64ToInt32)
IS_UNOP_MATCHER(ChangeInt32ToFloat64)
IS_UNOP_MATCHER(ChangeInt32ToInt64)
IS_UNOP_MATCHER(ChangeUint32ToUint64)
IS_UNOP_MATCHER(TruncateFloat64ToInt32)
IS_UNOP_MATCHER(TruncateInt64ToInt32)
#undef IS_UNOP_MATCHER
......
......@@ -98,6 +98,7 @@ Matcher<Node*> IsChangeFloat64ToInt32(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsChangeInt32ToFloat64(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsChangeInt32ToInt64(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsChangeUint32ToUint64(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsTruncateFloat64ToInt32(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsTruncateInt64ToInt32(const Matcher<Node*>& input_matcher);
} // namespace compiler
......
......@@ -71,6 +71,10 @@ InstructionSelectorTest::Stream InstructionSelectorTest::StreamBuilder::Build(
}
// -----------------------------------------------------------------------------
// Return.
TARGET_TEST_F(InstructionSelectorTest, ReturnParameter) {
StreamBuilder m(this, kMachInt32, kMachInt32);
m.Return(m.Parameter(0));
......@@ -96,6 +100,23 @@ TARGET_TEST_F(InstructionSelectorTest, ReturnZero) {
EXPECT_EQ(1U, s[1]->InputCount());
}
// -----------------------------------------------------------------------------
// Conversions.
TARGET_TEST_F(InstructionSelectorTest, TruncateFloat64ToInt32WithParameter) {
StreamBuilder m(this, kMachInt32, kMachFloat64);
m.Return(m.TruncateFloat64ToInt32(m.Parameter(0)));
Stream s = m.Build(kAllInstructions);
ASSERT_EQ(3U, s.size());
EXPECT_EQ(kArchNop, s[0]->arch_opcode());
EXPECT_EQ(kArchTruncateDoubleToI, s[1]->arch_opcode());
EXPECT_EQ(1U, s[1]->InputCount());
EXPECT_EQ(1U, s[1]->OutputCount());
EXPECT_EQ(kArchRet, s[2]->arch_opcode());
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -57,6 +57,16 @@ TEST_P(MachineOperatorCommonTest, ChangeUint32ToUint64) {
}
TEST_P(MachineOperatorCommonTest, TruncateFloat64ToInt32) {
Operator* op = machine()->TruncateFloat64ToInt32();
EXPECT_EQ(1, OperatorProperties::GetValueInputCount(op));
EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op));
EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op));
EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op));
}
TEST_P(MachineOperatorCommonTest, TruncateInt64ToInt32) {
Operator* op = machine()->TruncateInt64ToInt32();
EXPECT_EQ(1, OperatorProperties::GetValueInputCount(op));
......
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