[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
This commit is contained in:
parent
597123b8cd
commit
37058c1413
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user