summaryrefslogtreecommitdiff
path: root/deps/v8/test/unittests/compiler
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2016-12-23 16:30:57 +0100
committerMichaël Zasso <targos@protonmail.com>2017-01-26 22:46:17 +0100
commit2739185b790e040c3b044c577327f5d44bffad4a (patch)
tree29a466999212f4c85958379d9d400eec8a185ba5 /deps/v8/test/unittests/compiler
parenta67a04d7654faaa04c8da00e42981ebc9fd0911c (diff)
downloadnode-new-2739185b790e040c3b044c577327f5d44bffad4a.tar.gz
deps: update V8 to 5.5.372.40
PR-URL: https://github.com/nodejs/node/pull/9618 Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8/test/unittests/compiler')
-rw-r--r--deps/v8/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc25
-rw-r--r--deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc218
-rw-r--r--deps/v8/test/unittests/compiler/branch-elimination-unittest.cc2
-rw-r--r--deps/v8/test/unittests/compiler/common-operator-reducer-unittest.cc20
-rw-r--r--deps/v8/test/unittests/compiler/control-equivalence-unittest.cc4
-rw-r--r--deps/v8/test/unittests/compiler/effect-control-linearizer-unittest.cc4
-rw-r--r--deps/v8/test/unittests/compiler/escape-analysis-unittest.cc11
-rw-r--r--deps/v8/test/unittests/compiler/instruction-selector-unittest.cc13
-rw-r--r--deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc185
-rw-r--r--deps/v8/test/unittests/compiler/js-create-lowering-unittest.cc15
-rw-r--r--deps/v8/test/unittests/compiler/js-operator-unittest.cc1
-rw-r--r--deps/v8/test/unittests/compiler/js-type-feedback-unittest.cc336
-rw-r--r--deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc255
-rw-r--r--deps/v8/test/unittests/compiler/load-elimination-unittest.cc263
-rw-r--r--deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc126
-rw-r--r--deps/v8/test/unittests/compiler/mips/instruction-selector-mips-unittest.cc243
-rw-r--r--deps/v8/test/unittests/compiler/mips64/instruction-selector-mips64-unittest.cc242
-rw-r--r--deps/v8/test/unittests/compiler/node-test-utils.cc39
-rw-r--r--deps/v8/test/unittests/compiler/node-test-utils.h10
-rw-r--r--deps/v8/test/unittests/compiler/opcodes-unittest.cc67
-rw-r--r--deps/v8/test/unittests/compiler/simplified-operator-reducer-unittest.cc119
-rw-r--r--deps/v8/test/unittests/compiler/simplified-operator-unittest.cc8
-rw-r--r--deps/v8/test/unittests/compiler/typed-optimization-unittest.cc226
-rw-r--r--deps/v8/test/unittests/compiler/zone-pool-unittest.cc2
24 files changed, 1618 insertions, 816 deletions
diff --git a/deps/v8/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc b/deps/v8/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
index 6317d91fa9..746624a691 100644
--- a/deps/v8/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
+++ b/deps/v8/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
@@ -2079,10 +2079,6 @@ TEST_P(InstructionSelectorFlagSettingTest, CmpZeroOnlyUserInBasicBlock) {
const FlagSettingInst inst = GetParam();
// Binop with additional users, but in a different basic block.
TRACED_FOREACH(Comparison, cmp, kBinopCmpZeroRightInstructions) {
- // We don't optimise this case at the moment.
- if (cmp.flags_condition == kEqual || cmp.flags_condition == kNotEqual) {
- continue;
- }
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
MachineType::Int32());
RawMachineLabel a, b;
@@ -2108,10 +2104,6 @@ TEST_P(InstructionSelectorFlagSettingTest, ShiftedOperand) {
const FlagSettingInst inst = GetParam();
// Like the test above, but with a shifted input to the binary operator.
TRACED_FOREACH(Comparison, cmp, kBinopCmpZeroRightInstructions) {
- // We don't optimise this case at the moment.
- if (cmp.flags_condition == kEqual || cmp.flags_condition == kNotEqual) {
- continue;
- }
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
MachineType::Int32());
RawMachineLabel a, b;
@@ -2158,8 +2150,7 @@ TEST_P(InstructionSelectorFlagSettingTest, UsersInSameBasicBlock) {
EXPECT_EQ(inst.arch_opcode, s[0]->arch_opcode());
EXPECT_NE(kFlags_branch, s[0]->flags_mode());
EXPECT_EQ(kArmMul, s[1]->arch_opcode());
- EXPECT_EQ(cmp.flags_condition == kEqual ? kArmTst : kArmCmp,
- s[2]->arch_opcode());
+ EXPECT_EQ(kArmCmp, s[2]->arch_opcode());
EXPECT_EQ(kFlags_branch, s[2]->flags_mode());
EXPECT_EQ(cmp.flags_condition, s[2]->flags_condition());
}
@@ -3059,10 +3050,11 @@ TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
- EXPECT_EQ(kArmTst, s[0]->arch_opcode());
- EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
+ EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
ASSERT_EQ(2U, s[0]->InputCount());
- EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
EXPECT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(kEqual, s[0]->flags_condition());
@@ -3072,10 +3064,11 @@ TEST_F(InstructionSelectorTest, Word32EqualWithZero) {
m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
- EXPECT_EQ(kArmTst, s[0]->arch_opcode());
- EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
+ EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode());
ASSERT_EQ(2U, s[0]->InputCount());
- EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
EXPECT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(kEqual, s[0]->flags_condition());
diff --git a/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc b/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
index 6ca5e5e684..7892c4bbb9 100644
--- a/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
+++ b/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
@@ -402,7 +402,6 @@ TEST_P(InstructionSelectorLogicalTest, Parameter) {
TEST_P(InstructionSelectorLogicalTest, Immediate) {
const MachInst2 dpi = GetParam();
const MachineType type = dpi.machine_type;
- // TODO(all): Add support for testing 64-bit immediates.
if (type == MachineType::Int32()) {
// Immediate on the right.
TRACED_FOREACH(int32_t, imm, kLogical32Immediates) {
@@ -429,6 +428,32 @@ TEST_P(InstructionSelectorLogicalTest, Immediate) {
EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
EXPECT_EQ(1U, s[0]->OutputCount());
}
+ } else if (type == MachineType::Int64()) {
+ // Immediate on the right.
+ TRACED_FOREACH(int64_t, imm, kLogical64Immediates) {
+ StreamBuilder m(this, type, type);
+ m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int64Constant(imm)));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
+ EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ }
+
+ // Immediate on the left; all logical ops should commute.
+ TRACED_FOREACH(int64_t, imm, kLogical64Immediates) {
+ StreamBuilder m(this, type, type);
+ m.Return((m.*dpi.constructor)(m.Int64Constant(imm), m.Parameter(0)));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
+ EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ }
}
}
@@ -1067,7 +1092,8 @@ TEST_F(InstructionSelectorTest, SubBranchWithImmediateOnRight) {
m.Return(m.Int32Constant(0));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
- EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
+ EXPECT_EQ((imm == 0) ? kArm64CompareAndBranch32 : kArm64Cmp32,
+ s[0]->arch_opcode());
EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
EXPECT_EQ(kNotEqual, s[0]->flags_condition());
}
@@ -3142,11 +3168,20 @@ const IntegerCmp kIntegerCmpInstructions[] = {
kUnsignedLessThanOrEqual,
kUnsignedGreaterThanOrEqual}};
+const IntegerCmp kIntegerCmpEqualityInstructions[] = {
+ {{&RawMachineAssembler::Word32Equal, "Word32Equal", kArm64Cmp32,
+ MachineType::Int32()},
+ kEqual,
+ kEqual},
+ {{&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kArm64Cmp32,
+ MachineType::Int32()},
+ kNotEqual,
+ kNotEqual}};
} // namespace
TEST_F(InstructionSelectorTest, Word32CompareNegateWithWord32Shift) {
- TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
+ TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpEqualityInstructions) {
TRACED_FOREACH(Shift, shift, kShiftInstructions) {
// Test 32-bit operations. Ignore ROR shifts, as compare-negate does not
// support them.
@@ -3183,19 +3218,16 @@ TEST_F(InstructionSelectorTest, CmpWithImmediateOnLeft) {
// kEqual and kNotEqual trigger the cbz/cbnz optimization, which
// is tested elsewhere.
if (cmp.cond == kEqual || cmp.cond == kNotEqual) continue;
+ // For signed less than or equal to zero, we generate TBNZ.
+ if (cmp.cond == kSignedLessThanOrEqual && imm == 0) continue;
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Node* const p0 = m.Parameter(0);
- RawMachineLabel a, b;
- m.Branch((m.*cmp.mi.constructor)(m.Int32Constant(imm), p0), &a, &b);
- m.Bind(&a);
- m.Return(m.Int32Constant(1));
- m.Bind(&b);
- m.Return(m.Int32Constant(0));
+ m.Return((m.*cmp.mi.constructor)(m.Int32Constant(imm), p0));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
ASSERT_LE(2U, s[0]->InputCount());
- EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.commuted_cond, s[0]->flags_condition());
EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
}
@@ -3203,24 +3235,19 @@ TEST_F(InstructionSelectorTest, CmpWithImmediateOnLeft) {
}
TEST_F(InstructionSelectorTest, CmnWithImmediateOnLeft) {
- TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
+ TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpEqualityInstructions) {
TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
// kEqual and kNotEqual trigger the cbz/cbnz optimization, which
// is tested elsewhere.
if (cmp.cond == kEqual || cmp.cond == kNotEqual) continue;
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Node* sub = m.Int32Sub(m.Int32Constant(0), m.Parameter(0));
- RawMachineLabel a, b;
- m.Branch((m.*cmp.mi.constructor)(m.Int32Constant(imm), sub), &a, &b);
- m.Bind(&a);
- m.Return(m.Int32Constant(1));
- m.Bind(&b);
- m.Return(m.Int32Constant(0));
+ m.Return((m.*cmp.mi.constructor)(m.Int32Constant(imm), sub));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
ASSERT_LE(2U, s[0]->InputCount());
- EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.cond, s[0]->flags_condition());
EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
}
@@ -3244,7 +3271,7 @@ TEST_F(InstructionSelectorTest, CmpSignedExtendByteOnLeft) {
}
TEST_F(InstructionSelectorTest, CmnSignedExtendByteOnLeft) {
- TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
+ TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpEqualityInstructions) {
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
MachineType::Int32());
Node* sub = m.Int32Sub(m.Int32Constant(0), m.Parameter(0));
@@ -3294,7 +3321,7 @@ TEST_F(InstructionSelectorTest, CmpShiftByImmediateOnLeft) {
}
TEST_F(InstructionSelectorTest, CmnShiftByImmediateOnLeft) {
- TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
+ TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpEqualityInstructions) {
TRACED_FOREACH(Shift, shift, kShiftInstructions) {
// Only test relevant shifted operands.
if (shift.mi.machine_type != MachineType::Int32()) continue;
@@ -3408,21 +3435,15 @@ TEST_P(InstructionSelectorFlagSettingTest, CmpZeroRight) {
TRACED_FOREACH(IntegerCmp, cmp, kBinopCmpZeroRightInstructions) {
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
MachineType::Int32());
- RawMachineLabel a, b;
Node* binop = (m.*inst.mi.constructor)(m.Parameter(0), m.Parameter(1));
- Node* comp = (m.*cmp.mi.constructor)(binop, m.Int32Constant(0));
- m.Branch(comp, &a, &b);
- m.Bind(&a);
- m.Return(m.Int32Constant(1));
- m.Bind(&b);
- m.Return(m.Int32Constant(0));
+ m.Return((m.*cmp.mi.constructor)(binop, m.Int32Constant(0)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
- ASSERT_EQ(4U, s[0]->InputCount()); // The labels are also inputs.
+ ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(inst.no_output_opcode, s[0]->arch_opcode());
EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
EXPECT_EQ(s.ToVreg(m.Parameter(1)), s.ToVreg(s[0]->InputAt(1)));
- EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.cond, s[0]->flags_condition());
}
}
@@ -3433,21 +3454,15 @@ TEST_P(InstructionSelectorFlagSettingTest, CmpZeroLeft) {
TRACED_FOREACH(IntegerCmp, cmp, kBinopCmpZeroLeftInstructions) {
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
MachineType::Int32());
- RawMachineLabel a, b;
Node* binop = (m.*inst.mi.constructor)(m.Parameter(0), m.Parameter(1));
- Node* comp = (m.*cmp.mi.constructor)(m.Int32Constant(0), binop);
- m.Branch(comp, &a, &b);
- m.Bind(&a);
- m.Return(m.Int32Constant(1));
- m.Bind(&b);
- m.Return(m.Int32Constant(0));
+ m.Return((m.*cmp.mi.constructor)(m.Int32Constant(0), binop));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
- ASSERT_EQ(4U, s[0]->InputCount()); // The labels are also inputs.
+ ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(inst.no_output_opcode, s[0]->arch_opcode());
EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
EXPECT_EQ(s.ToVreg(m.Parameter(1)), s.ToVreg(s[0]->InputAt(1)));
- EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.cond, s[0]->flags_condition());
}
}
@@ -3456,25 +3471,23 @@ TEST_P(InstructionSelectorFlagSettingTest, CmpZeroOnlyUserInBasicBlock) {
const FlagSettingInst inst = GetParam();
// Binop with additional users, but in a different basic block.
TRACED_FOREACH(IntegerCmp, cmp, kBinopCmpZeroRightInstructions) {
- // For kEqual and kNotEqual, we generate a cbz or cbnz.
- if (cmp.cond == kEqual || cmp.cond == kNotEqual) continue;
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
MachineType::Int32());
RawMachineLabel a, b;
Node* binop = (m.*inst.mi.constructor)(m.Parameter(0), m.Parameter(1));
Node* comp = (m.*cmp.mi.constructor)(binop, m.Int32Constant(0));
- m.Branch(comp, &a, &b);
+ m.Branch(m.Parameter(0), &a, &b);
m.Bind(&a);
m.Return(binop);
m.Bind(&b);
- m.Return(m.Int32Constant(0));
+ m.Return(comp);
Stream s = m.Build();
- ASSERT_EQ(1U, s.size());
- ASSERT_EQ(4U, s[0]->InputCount()); // The labels are also inputs.
+ ASSERT_EQ(2U, s.size()); // Flag-setting instruction and branch.
+ ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(inst.mi.arch_opcode, s[0]->arch_opcode());
EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
EXPECT_EQ(s.ToVreg(m.Parameter(1)), s.ToVreg(s[0]->InputAt(1)));
- EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.cond, s[0]->flags_condition());
}
}
@@ -3483,8 +3496,6 @@ TEST_P(InstructionSelectorFlagSettingTest, ShiftedOperand) {
const FlagSettingInst inst = GetParam();
// Like the test above, but with a shifted input to the binary operator.
TRACED_FOREACH(IntegerCmp, cmp, kBinopCmpZeroRightInstructions) {
- // For kEqual and kNotEqual, we generate a cbz or cbnz.
- if (cmp.cond == kEqual || cmp.cond == kNotEqual) continue;
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
MachineType::Int32());
RawMachineLabel a, b;
@@ -3492,20 +3503,20 @@ TEST_P(InstructionSelectorFlagSettingTest, ShiftedOperand) {
Node* shift = m.Word32Shl(m.Parameter(1), imm);
Node* binop = (m.*inst.mi.constructor)(m.Parameter(0), shift);
Node* comp = (m.*cmp.mi.constructor)(binop, m.Int32Constant(0));
- m.Branch(comp, &a, &b);
+ m.Branch(m.Parameter(0), &a, &b);
m.Bind(&a);
m.Return(binop);
m.Bind(&b);
- m.Return(m.Int32Constant(0));
+ m.Return(comp);
Stream s = m.Build();
- ASSERT_EQ(1U, s.size());
- ASSERT_EQ(5U, s[0]->InputCount()); // The labels are also inputs.
+ ASSERT_EQ(2U, s.size()); // Flag-setting instruction and branch.
+ ASSERT_EQ(3U, s[0]->InputCount());
EXPECT_EQ(inst.mi.arch_opcode, s[0]->arch_opcode());
EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
EXPECT_EQ(s.ToVreg(m.Parameter(1)), s.ToVreg(s[0]->InputAt(1)));
EXPECT_EQ(5, s.ToInt32(s[0]->InputAt(2)));
EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
- EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.cond, s[0]->flags_condition());
}
}
@@ -3521,19 +3532,18 @@ TEST_P(InstructionSelectorFlagSettingTest, UsersInSameBasicBlock) {
Node* binop = (m.*inst.mi.constructor)(m.Parameter(0), m.Parameter(1));
Node* mul = m.Int32Mul(m.Parameter(0), binop);
Node* comp = (m.*cmp.mi.constructor)(binop, m.Int32Constant(0));
- m.Branch(comp, &a, &b);
+ m.Branch(m.Parameter(0), &a, &b);
m.Bind(&a);
m.Return(mul);
m.Bind(&b);
- m.Return(m.Int32Constant(0));
+ m.Return(comp);
Stream s = m.Build();
- ASSERT_EQ(3U, s.size());
+ ASSERT_EQ(4U, s.size()); // Includes the compare and branch instruction.
EXPECT_EQ(inst.mi.arch_opcode, s[0]->arch_opcode());
- EXPECT_NE(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode());
EXPECT_EQ(kArm64Mul32, s[1]->arch_opcode());
- EXPECT_EQ(cmp.cond == kEqual ? kArm64CompareAndBranch32 : kArm64Cmp32,
- s[2]->arch_opcode());
- EXPECT_EQ(kFlags_branch, s[2]->flags_mode());
+ EXPECT_EQ(kArm64Cmp32, s[2]->arch_opcode());
+ EXPECT_EQ(kFlags_set, s[2]->flags_mode());
EXPECT_EQ(cmp.cond, s[2]->flags_condition());
}
}
@@ -3543,23 +3553,18 @@ TEST_P(InstructionSelectorFlagSettingTest, CommuteImmediate) {
// Immediate on left hand side of the binary operator.
TRACED_FOREACH(IntegerCmp, cmp, kBinopCmpZeroRightInstructions) {
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
- RawMachineLabel a, b;
// 3 can be an immediate on both arithmetic and logical instructions.
Node* imm = m.Int32Constant(3);
Node* binop = (m.*inst.mi.constructor)(imm, m.Parameter(0));
Node* comp = (m.*cmp.mi.constructor)(binop, m.Int32Constant(0));
- m.Branch(comp, &a, &b);
- m.Bind(&a);
- m.Return(m.Int32Constant(1));
- m.Bind(&b);
- m.Return(m.Int32Constant(0));
+ m.Return(comp);
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
- ASSERT_EQ(4U, s[0]->InputCount()); // The labels are also inputs.
+ ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(inst.no_output_opcode, s[0]->arch_opcode());
EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
EXPECT_EQ(3, s.ToInt32(s[0]->InputAt(1)));
- EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.cond, s[0]->flags_condition());
}
}
@@ -3606,23 +3611,18 @@ TEST_F(InstructionSelectorTest, TstInvalidImmediate) {
// Make sure we do not generate an invalid immediate for TST.
TRACED_FOREACH(IntegerCmp, cmp, kBinopCmpZeroRightInstructions) {
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
- RawMachineLabel a, b;
// 5 is not a valid constant for TST.
Node* imm = m.Int32Constant(5);
Node* binop = m.Word32And(imm, m.Parameter(0));
Node* comp = (m.*cmp.mi.constructor)(binop, m.Int32Constant(0));
- m.Branch(comp, &a, &b);
- m.Bind(&a);
- m.Return(m.Int32Constant(1));
- m.Bind(&b);
- m.Return(m.Int32Constant(0));
+ m.Return(comp);
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
- ASSERT_EQ(4U, s[0]->InputCount()); // The labels are also inputs.
+ ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
EXPECT_NE(InstructionOperand::IMMEDIATE, s[0]->InputAt(0)->kind());
EXPECT_NE(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
- EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.cond, s[0]->flags_condition());
}
}
@@ -4311,6 +4311,74 @@ TEST_F(InstructionSelectorTest, LoadAndShiftRight) {
}
}
+TEST_F(InstructionSelectorTest, CompareAgainstZero32) {
+ TRACED_FOREACH(IntegerCmp, cmp, kBinopCmpZeroRightInstructions) {
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+ Node* const param = m.Parameter(0);
+ RawMachineLabel a, b;
+ m.Branch((m.*cmp.mi.constructor)(param, m.Int32Constant(0)), &a, &b);
+ m.Bind(&a);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&b);
+ m.Return(m.Int32Constant(0));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(s.ToVreg(param), s.ToVreg(s[0]->InputAt(0)));
+ if (cmp.cond == kNegative || cmp.cond == kPositiveOrZero) {
+ EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
+ EXPECT_EQ(4U, s[0]->InputCount()); // The labels are also inputs.
+ EXPECT_EQ((cmp.cond == kNegative) ? kNotEqual : kEqual,
+ s[0]->flags_condition());
+ EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
+ EXPECT_EQ(31, s.ToInt32(s[0]->InputAt(1)));
+ } else {
+ EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode());
+ EXPECT_EQ(3U, s[0]->InputCount()); // The labels are also inputs.
+ EXPECT_EQ(cmp.cond, s[0]->flags_condition());
+ }
+ }
+}
+
+TEST_F(InstructionSelectorTest, CompareFloat64HighLessThanZero64) {
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Float64());
+ Node* const param = m.Parameter(0);
+ Node* const high = m.Float64ExtractHighWord32(param);
+ RawMachineLabel a, b;
+ m.Branch(m.Int32LessThan(high, m.Int32Constant(0)), &a, &b);
+ m.Bind(&a);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&b);
+ m.Return(m.Int32Constant(0));
+ Stream s = m.Build();
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kArm64U64MoveFloat64, s[0]->arch_opcode());
+ EXPECT_EQ(kArm64TestAndBranch, s[1]->arch_opcode());
+ EXPECT_EQ(kNotEqual, s[1]->flags_condition());
+ EXPECT_EQ(4U, s[1]->InputCount());
+ EXPECT_EQ(InstructionOperand::IMMEDIATE, s[1]->InputAt(1)->kind());
+ EXPECT_EQ(63, s.ToInt32(s[1]->InputAt(1)));
+}
+
+TEST_F(InstructionSelectorTest, CompareFloat64HighGreaterThanOrEqualZero64) {
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Float64());
+ Node* const param = m.Parameter(0);
+ Node* const high = m.Float64ExtractHighWord32(param);
+ RawMachineLabel a, b;
+ m.Branch(m.Int32GreaterThanOrEqual(high, m.Int32Constant(0)), &a, &b);
+ m.Bind(&a);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&b);
+ m.Return(m.Int32Constant(0));
+ Stream s = m.Build();
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kArm64U64MoveFloat64, s[0]->arch_opcode());
+ EXPECT_EQ(kArm64TestAndBranch, s[1]->arch_opcode());
+ EXPECT_EQ(kEqual, s[1]->flags_condition());
+ EXPECT_EQ(4U, s[1]->InputCount());
+ EXPECT_EQ(InstructionOperand::IMMEDIATE, s[1]->InputAt(1)->kind());
+ EXPECT_EQ(63, s.ToInt32(s[1]->InputAt(1)));
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/compiler/branch-elimination-unittest.cc b/deps/v8/test/unittests/compiler/branch-elimination-unittest.cc
index fcd702c428..9486d1fe6e 100644
--- a/deps/v8/test/unittests/compiler/branch-elimination-unittest.cc
+++ b/deps/v8/test/unittests/compiler/branch-elimination-unittest.cc
@@ -15,7 +15,7 @@ namespace v8 {
namespace internal {
namespace compiler {
-class BranchEliminationTest : public TypedGraphTest {
+class BranchEliminationTest : public GraphTest {
public:
BranchEliminationTest()
: machine_(zone(), MachineType::PointerRepresentation(),
diff --git a/deps/v8/test/unittests/compiler/common-operator-reducer-unittest.cc b/deps/v8/test/unittests/compiler/common-operator-reducer-unittest.cc
index f51a54d074..d284772395 100644
--- a/deps/v8/test/unittests/compiler/common-operator-reducer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/common-operator-reducer-unittest.cc
@@ -158,6 +158,26 @@ TEST_F(CommonOperatorReducerTest, BranchWithBooleanNot) {
}
}
+TEST_F(CommonOperatorReducerTest, BranchWithSelect) {
+ Node* const value = Parameter(0);
+ TRACED_FOREACH(BranchHint, hint, kBranchHints) {
+ Node* const control = graph()->start();
+ Node* const branch = graph()->NewNode(
+ common()->Branch(hint),
+ graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
+ value, FalseConstant(), TrueConstant()),
+ control);
+ Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Reduction const r = Reduce(branch);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_EQ(branch, r.replacement());
+ EXPECT_THAT(branch, IsBranch(value, control));
+ EXPECT_THAT(if_false, IsIfTrue(branch));
+ EXPECT_THAT(if_true, IsIfFalse(branch));
+ EXPECT_EQ(NegateBranchHint(hint), BranchHintOf(branch->op()));
+ }
+}
// -----------------------------------------------------------------------------
// Merge
diff --git a/deps/v8/test/unittests/compiler/control-equivalence-unittest.cc b/deps/v8/test/unittests/compiler/control-equivalence-unittest.cc
index a87f760c82..6534e90ccc 100644
--- a/deps/v8/test/unittests/compiler/control-equivalence-unittest.cc
+++ b/deps/v8/test/unittests/compiler/control-equivalence-unittest.cc
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/bit-vector.h"
#include "src/compiler/control-equivalence.h"
+#include "src/bit-vector.h"
#include "src/compiler/graph-visualizer.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/source-position.h"
-#include "src/zone-containers.h"
+#include "src/zone/zone-containers.h"
#include "test/unittests/compiler/graph-unittest.h"
namespace v8 {
diff --git a/deps/v8/test/unittests/compiler/effect-control-linearizer-unittest.cc b/deps/v8/test/unittests/compiler/effect-control-linearizer-unittest.cc
index 71a8696d09..0a12ea371a 100644
--- a/deps/v8/test/unittests/compiler/effect-control-linearizer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/effect-control-linearizer-unittest.cc
@@ -21,10 +21,10 @@ namespace compiler {
using testing::Capture;
-class EffectControlLinearizerTest : public TypedGraphTest {
+class EffectControlLinearizerTest : public GraphTest {
public:
EffectControlLinearizerTest()
- : TypedGraphTest(3),
+ : GraphTest(3),
machine_(zone()),
javascript_(zone()),
simplified_(zone()),
diff --git a/deps/v8/test/unittests/compiler/escape-analysis-unittest.cc b/deps/v8/test/unittests/compiler/escape-analysis-unittest.cc
index 990b813947..3a233d6872 100644
--- a/deps/v8/test/unittests/compiler/escape-analysis-unittest.cc
+++ b/deps/v8/test/unittests/compiler/escape-analysis-unittest.cc
@@ -2,22 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/bit-vector.h"
#include "src/compiler/escape-analysis.h"
+#include "src/bit-vector.h"
#include "src/compiler/escape-analysis-reducer.h"
#include "src/compiler/graph-visualizer.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/simplified-operator.h"
-#include "src/types.h"
-#include "src/zone-containers.h"
+#include "src/compiler/types.h"
+#include "src/zone/zone-containers.h"
#include "test/unittests/compiler/graph-unittest.h"
namespace v8 {
namespace internal {
namespace compiler {
-class EscapeAnalysisTest : public GraphTest {
+class EscapeAnalysisTest : public TypedGraphTest {
public:
EscapeAnalysisTest()
: simplified_(zone()),
@@ -468,8 +468,7 @@ TEST_F(EscapeAnalysisTest, DeoptReplacement) {
ASSERT_EQ(object1, NodeProperties::GetValueInput(object_state, 0));
}
-
-TEST_F(EscapeAnalysisTest, DeoptReplacementIdentity) {
+TEST_F(EscapeAnalysisTest, DISABLED_DeoptReplacementIdentity) {
Node* object1 = Constant(1);
BeginRegion();
Node* allocation = Allocate(Constant(kPointerSize * 2));
diff --git a/deps/v8/test/unittests/compiler/instruction-selector-unittest.cc b/deps/v8/test/unittests/compiler/instruction-selector-unittest.cc
index d2953159fc..18ccaaaea5 100644
--- a/deps/v8/test/unittests/compiler/instruction-selector-unittest.cc
+++ b/deps/v8/test/unittests/compiler/instruction-selector-unittest.cc
@@ -41,7 +41,8 @@ InstructionSelectorTest::Stream InstructionSelectorTest::StreamBuilder::Build(
SourcePositionTable source_position_table(graph());
InstructionSelector selector(test_->zone(), node_count, &linkage, &sequence,
schedule, &source_position_table, nullptr,
- source_position_mode, features);
+ source_position_mode, features,
+ InstructionSelector::kDisableScheduling);
selector.SelectInstructions();
if (FLAG_trace_turbo) {
OFStream out(stdout);
@@ -244,19 +245,13 @@ TARGET_TEST_F(InstructionSelectorTest, FinishRegion) {
m.AddNode(m.common()->FinishRegion(), param, m.graph()->start());
m.Return(finish);
Stream s = m.Build(kAllInstructions);
- ASSERT_EQ(4U, s.size());
+ ASSERT_EQ(3U, s.size());
EXPECT_EQ(kArchNop, s[0]->arch_opcode());
ASSERT_EQ(1U, s[0]->OutputCount());
ASSERT_TRUE(s[0]->Output()->IsUnallocated());
+ EXPECT_EQ(kArchRet, s[1]->arch_opcode());
EXPECT_EQ(s.ToVreg(param), s.ToVreg(s[0]->Output()));
- EXPECT_EQ(kArchNop, s[1]->arch_opcode());
- ASSERT_EQ(1U, s[1]->InputCount());
- ASSERT_TRUE(s[1]->InputAt(0)->IsUnallocated());
EXPECT_EQ(s.ToVreg(param), s.ToVreg(s[1]->InputAt(0)));
- ASSERT_EQ(1U, s[1]->OutputCount());
- ASSERT_TRUE(s[1]->Output()->IsUnallocated());
- EXPECT_TRUE(UnallocatedOperand::cast(s[1]->Output())->HasSameAsInputPolicy());
- EXPECT_EQ(s.ToVreg(finish), s.ToVreg(s[1]->Output()));
EXPECT_TRUE(s.IsReference(finish));
}
diff --git a/deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc b/deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc
index ed20e64194..48debc368c 100644
--- a/deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/js-builtin-reducer-unittest.cc
@@ -38,6 +38,15 @@ class JSBuiltinReducerTest : public TypedGraphTest {
return reducer.Reduce(node);
}
+ Node* GlobalFunction(const char* name) {
+ Handle<JSFunction> f = Handle<JSFunction>::cast(
+ Object::GetProperty(
+ isolate()->global_object(),
+ isolate()->factory()->NewStringFromAsciiChecked(name))
+ .ToHandleChecked());
+ return HeapConstant(f);
+ }
+
Node* MathFunction(const char* name) {
Handle<Object> m =
JSObject::GetProperty(isolate()->global_object(),
@@ -101,6 +110,91 @@ Type* const kNumberTypes[] = {
// -----------------------------------------------------------------------------
+// isFinite
+
+TEST_F(JSBuiltinReducerTest, GlobalIsFiniteWithNumber) {
+ Node* function = GlobalFunction("isFinite");
+
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ Node* context = UndefinedConstant();
+ Node* frame_state = graph()->start();
+ TRACED_FOREACH(Type*, t0, kNumberTypes) {
+ Node* p0 = Parameter(t0, 0);
+ Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+ UndefinedConstant(), p0, context, frame_state,
+ effect, control);
+ Reduction r = Reduce(call);
+
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsNumberEqual(IsNumberSubtract(p0, p0),
+ IsNumberSubtract(p0, p0)));
+ }
+}
+
+TEST_F(JSBuiltinReducerTest, GlobalIsFiniteWithPlainPrimitive) {
+ Node* function = GlobalFunction("isFinite");
+
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ Node* context = UndefinedConstant();
+ Node* frame_state = graph()->start();
+ Node* p0 = Parameter(Type::PlainPrimitive(), 0);
+ Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+ UndefinedConstant(), p0, context, frame_state,
+ effect, control);
+ Reduction r = Reduce(call);
+
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(),
+ IsNumberEqual(IsNumberSubtract(IsPlainPrimitiveToNumber(p0),
+ IsPlainPrimitiveToNumber(p0)),
+ IsNumberSubtract(IsPlainPrimitiveToNumber(p0),
+ IsPlainPrimitiveToNumber(p0))));
+}
+
+// -----------------------------------------------------------------------------
+// isNaN
+
+TEST_F(JSBuiltinReducerTest, GlobalIsNaNWithNumber) {
+ Node* function = GlobalFunction("isNaN");
+
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ Node* context = UndefinedConstant();
+ Node* frame_state = graph()->start();
+ TRACED_FOREACH(Type*, t0, kNumberTypes) {
+ Node* p0 = Parameter(t0, 0);
+ Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+ UndefinedConstant(), p0, context, frame_state,
+ effect, control);
+ Reduction r = Reduce(call);
+
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsBooleanNot(IsNumberEqual(p0, p0)));
+ }
+}
+
+TEST_F(JSBuiltinReducerTest, GlobalIsNaNWithPlainPrimitive) {
+ Node* function = GlobalFunction("isNaN");
+
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ Node* context = UndefinedConstant();
+ Node* frame_state = graph()->start();
+ Node* p0 = Parameter(Type::PlainPrimitive(), 0);
+ Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+ UndefinedConstant(), p0, context, frame_state,
+ effect, control);
+ Reduction r = Reduce(call);
+
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(),
+ IsBooleanNot(IsNumberEqual(IsPlainPrimitiveToNumber(p0),
+ IsPlainPrimitiveToNumber(p0))));
+}
+
+// -----------------------------------------------------------------------------
// Math.abs
TEST_F(JSBuiltinReducerTest, MathAbsWithNumber) {
@@ -1315,6 +1409,97 @@ TEST_F(JSBuiltinReducerTest, MathTruncWithPlainPrimitive) {
}
// -----------------------------------------------------------------------------
+// Number.isFinite
+
+TEST_F(JSBuiltinReducerTest, NumberIsFiniteWithNumber) {
+ Node* function = NumberFunction("isFinite");
+
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ Node* context = UndefinedConstant();
+ Node* frame_state = graph()->start();
+ TRACED_FOREACH(Type*, t0, kNumberTypes) {
+ Node* p0 = Parameter(t0, 0);
+ Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+ UndefinedConstant(), p0, context, frame_state,
+ effect, control);
+ Reduction r = Reduce(call);
+
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsNumberEqual(IsNumberSubtract(p0, p0),
+ IsNumberSubtract(p0, p0)));
+ }
+}
+
+// -----------------------------------------------------------------------------
+// Number.isInteger
+
+TEST_F(JSBuiltinReducerTest, NumberIsIntegerWithNumber) {
+ Node* function = NumberFunction("isInteger");
+
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ Node* context = UndefinedConstant();
+ Node* frame_state = graph()->start();
+ TRACED_FOREACH(Type*, t0, kNumberTypes) {
+ Node* p0 = Parameter(t0, 0);
+ Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+ UndefinedConstant(), p0, context, frame_state,
+ effect, control);
+ Reduction r = Reduce(call);
+
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(),
+ IsNumberEqual(IsNumberSubtract(p0, IsNumberTrunc(p0)),
+ IsNumberConstant(0.0)));
+ }
+}
+
+// -----------------------------------------------------------------------------
+// Number.isNaN
+
+TEST_F(JSBuiltinReducerTest, NumberIsNaNWithNumber) {
+ Node* function = NumberFunction("isNaN");
+
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ Node* context = UndefinedConstant();
+ Node* frame_state = graph()->start();
+ TRACED_FOREACH(Type*, t0, kNumberTypes) {
+ Node* p0 = Parameter(t0, 0);
+ Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+ UndefinedConstant(), p0, context, frame_state,
+ effect, control);
+ Reduction r = Reduce(call);
+
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsBooleanNot(IsNumberEqual(p0, p0)));
+ }
+}
+
+// -----------------------------------------------------------------------------
+// Number.isSafeInteger
+
+TEST_F(JSBuiltinReducerTest, NumberIsSafeIntegerWithIntegral32) {
+ Node* function = NumberFunction("isSafeInteger");
+
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ Node* context = UndefinedConstant();
+ Node* frame_state = graph()->start();
+ TRACED_FOREACH(Type*, t0, kIntegral32Types) {
+ Node* p0 = Parameter(t0, 0);
+ Node* call = graph()->NewNode(javascript()->CallFunction(3), function,
+ UndefinedConstant(), p0, context, frame_state,
+ effect, control);
+ Reduction r = Reduce(call);
+
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsTrueConstant());
+ }
+}
+
+// -----------------------------------------------------------------------------
// Number.parseInt
TEST_F(JSBuiltinReducerTest, NumberParseIntWithIntegral32) {
diff --git a/deps/v8/test/unittests/compiler/js-create-lowering-unittest.cc b/deps/v8/test/unittests/compiler/js-create-lowering-unittest.cc
index 9c001e9eb2..ebb1633401 100644
--- a/deps/v8/test/unittests/compiler/js-create-lowering-unittest.cc
+++ b/deps/v8/test/unittests/compiler/js-create-lowering-unittest.cc
@@ -40,7 +40,8 @@ class JSCreateLoweringTest : public TypedGraphTest {
// TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(zone(), graph());
JSCreateLowering reducer(&graph_reducer, &deps_, &jsgraph,
- MaybeHandle<LiteralsArray>(), zone());
+ MaybeHandle<LiteralsArray>(),
+ MaybeHandle<Context>(), zone());
return reducer.Reduce(node);
}
@@ -174,14 +175,15 @@ TEST_F(JSCreateLoweringTest, JSCreateFunctionContextViaInlinedAllocation) {
// JSCreateWithContext
TEST_F(JSCreateLoweringTest, JSCreateWithContext) {
+ Handle<ScopeInfo> scope_info(factory()->NewScopeInfo(1));
Node* const object = Parameter(Type::Receiver());
Node* const closure = Parameter(Type::Function());
Node* const context = Parameter(Type::Any());
Node* const effect = graph()->start();
Node* const control = graph()->start();
Reduction r =
- Reduce(graph()->NewNode(javascript()->CreateWithContext(), object,
- closure, context, effect, control));
+ Reduce(graph()->NewNode(javascript()->CreateWithContext(scope_info),
+ object, closure, context, effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
@@ -195,14 +197,15 @@ TEST_F(JSCreateLoweringTest, JSCreateWithContext) {
TEST_F(JSCreateLoweringTest, JSCreateCatchContext) {
Handle<String> name = factory()->length_string();
+ Handle<ScopeInfo> scope_info(factory()->NewScopeInfo(1));
Node* const exception = Parameter(Type::Receiver());
Node* const closure = Parameter(Type::Function());
Node* const context = Parameter(Type::Any());
Node* const effect = graph()->start();
Node* const control = graph()->start();
- Reduction r =
- Reduce(graph()->NewNode(javascript()->CreateCatchContext(name), exception,
- closure, context, effect, control));
+ Reduction r = Reduce(
+ graph()->NewNode(javascript()->CreateCatchContext(name, scope_info),
+ exception, closure, context, effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
diff --git a/deps/v8/test/unittests/compiler/js-operator-unittest.cc b/deps/v8/test/unittests/compiler/js-operator-unittest.cc
index 3b83d691f1..853249785e 100644
--- a/deps/v8/test/unittests/compiler/js-operator-unittest.cc
+++ b/deps/v8/test/unittests/compiler/js-operator-unittest.cc
@@ -46,7 +46,6 @@ const SharedOperator kSharedOperators[] = {
SHARED(ToObject, Operator::kFoldable, 1, 1, 1, 1, 1, 1, 2),
SHARED(Create, Operator::kEliminatable, 2, 1, 1, 0, 1, 1, 0),
SHARED(TypeOf, Operator::kPure, 1, 0, 0, 0, 1, 0, 0),
- SHARED(CreateWithContext, Operator::kNoProperties, 2, 0, 1, 1, 1, 1, 2),
#undef SHARED
};
diff --git a/deps/v8/test/unittests/compiler/js-type-feedback-unittest.cc b/deps/v8/test/unittests/compiler/js-type-feedback-unittest.cc
deleted file mode 100644
index dece25def1..0000000000
--- a/deps/v8/test/unittests/compiler/js-type-feedback-unittest.cc
+++ /dev/null
@@ -1,336 +0,0 @@
-// Copyright 2015 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.
-
-#include "src/compiler.h"
-
-#include "src/compiler/access-builder.h"
-#include "src/compiler/js-graph.h"
-#include "src/compiler/js-operator.h"
-#include "src/compiler/js-type-feedback.h"
-#include "src/compiler/machine-operator.h"
-#include "src/compiler/node-matchers.h"
-#include "src/compiler/node-properties.h"
-#include "src/compiler/operator-properties.h"
-
-#include "test/unittests/compiler/compiler-test-utils.h"
-#include "test/unittests/compiler/graph-unittest.h"
-#include "test/unittests/compiler/node-test-utils.h"
-#include "testing/gmock-support.h"
-
-using testing::Capture;
-
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-class JSTypeFeedbackTest : public TypedGraphTest {
- public:
- JSTypeFeedbackTest()
- : TypedGraphTest(3),
- javascript_(zone()),
- dependencies_(isolate(), zone()) {}
- ~JSTypeFeedbackTest() override { dependencies_.Rollback(); }
-
- protected:
- Reduction Reduce(Node* node,
- JSTypeFeedbackSpecializer::DeoptimizationMode mode) {
- Handle<GlobalObject> global_object(
- isolate()->native_context()->global_object(), isolate());
-
- MachineOperatorBuilder machine(zone());
- SimplifiedOperatorBuilder simplified(zone());
- JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified,
- &machine);
- JSTypeFeedbackTable table(zone());
- // TODO(titzer): mock the GraphReducer here for better unit testing.
- GraphReducer graph_reducer(zone(), graph());
- JSTypeFeedbackSpecializer reducer(&graph_reducer, &jsgraph, &table, nullptr,
- global_object, mode, &dependencies_);
- return reducer.Reduce(node);
- }
-
- Node* EmptyFrameState() {
- MachineOperatorBuilder machine(zone());
- JSGraph jsgraph(isolate(), graph(), common(), javascript(), nullptr,
- &machine);
- return jsgraph.EmptyFrameState();
- }
-
- JSOperatorBuilder* javascript() { return &javascript_; }
-
- void SetGlobalProperty(const char* string, int value) {
- SetGlobalProperty(string, Handle<Smi>(Smi::FromInt(value), isolate()));
- }
-
- void SetGlobalProperty(const char* string, double value) {
- SetGlobalProperty(string, isolate()->factory()->NewNumber(value));
- }
-
- void SetGlobalProperty(const char* string, Handle<Object> value) {
- Handle<JSObject> global(isolate()->context()->global_object(), isolate());
- Handle<String> name =
- isolate()->factory()->NewStringFromAsciiChecked(string);
- MaybeHandle<Object> result =
- JSReceiver::SetProperty(global, name, value, SLOPPY);
- result.Assert();
- }
-
- Node* ReturnLoadNamedFromGlobal(
- const char* string, Node* effect, Node* control,
- JSTypeFeedbackSpecializer::DeoptimizationMode mode) {
- VectorSlotPair feedback;
- Node* vector = UndefinedConstant();
- Node* context = UndefinedConstant();
-
- Handle<Name> name = isolate()->factory()->InternalizeUtf8String(string);
- const Operator* op = javascript()->LoadGlobal(name, feedback);
- Node* load = graph()->NewNode(op, vector, context, EmptyFrameState(),
- EmptyFrameState(), effect, control);
- Node* if_success = graph()->NewNode(common()->IfSuccess(), load);
- return graph()->NewNode(common()->Return(), load, load, if_success);
- }
-
- CompilationDependencies* dependencies() { return &dependencies_; }
-
- private:
- JSOperatorBuilder javascript_;
- CompilationDependencies dependencies_;
-};
-
-
-TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstSmi) {
- const int kValue = 111;
- const char* kName = "banana";
- SetGlobalProperty(kName, kValue);
-
- Node* ret = ReturnLoadNamedFromGlobal(
- kName, graph()->start(), graph()->start(),
- JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
- graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
-
- Reduction r = Reduce(ret->InputAt(0),
- JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
- EXPECT_FALSE(r.Changed());
- EXPECT_TRUE(dependencies()->IsEmpty());
-}
-
-
-TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstSmiWithDeoptimization) {
- const int kValue = 111;
- const char* kName = "banana";
- SetGlobalProperty(kName, kValue);
-
- Node* ret = ReturnLoadNamedFromGlobal(
- kName, graph()->start(), graph()->start(),
- JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
- graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
-
- Reduction r = Reduce(ret->InputAt(0),
- JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
-
- // Check LoadNamed(global) => HeapConstant[kValue]
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsNumberConstant(kValue));
-
- EXPECT_THAT(ret, IsReturn(IsNumberConstant(kValue), graph()->start(),
- graph()->start()));
- EXPECT_THAT(graph()->end(), IsEnd(ret));
-
- EXPECT_FALSE(dependencies()->IsEmpty());
- dependencies()->Rollback();
-}
-
-
-TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstNumber) {
- const double kValue = -11.25;
- const char* kName = "kiwi";
- SetGlobalProperty(kName, kValue);
-
- Node* ret = ReturnLoadNamedFromGlobal(
- kName, graph()->start(), graph()->start(),
- JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
- graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
-
- Reduction r = Reduce(ret->InputAt(0),
- JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
-
- EXPECT_FALSE(r.Changed());
- EXPECT_TRUE(dependencies()->IsEmpty());
-}
-
-
-TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstNumberWithDeoptimization) {
- const double kValue = -11.25;
- const char* kName = "kiwi";
- SetGlobalProperty(kName, kValue);
-
- Node* ret = ReturnLoadNamedFromGlobal(
- kName, graph()->start(), graph()->start(),
- JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
- graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
-
- Reduction r = Reduce(ret->InputAt(0),
- JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
-
- // Check LoadNamed(global) => HeapConstant[kValue]
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsNumberConstant(kValue));
-
- EXPECT_THAT(ret, IsReturn(IsNumberConstant(kValue), graph()->start(),
- graph()->start()));
- EXPECT_THAT(graph()->end(), IsEnd(ret));
-
- EXPECT_FALSE(dependencies()->IsEmpty());
-}
-
-
-TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstString) {
- Handle<HeapObject> kValue = isolate()->factory()->undefined_string();
- const char* kName = "mango";
- SetGlobalProperty(kName, kValue);
-
- Node* ret = ReturnLoadNamedFromGlobal(
- kName, graph()->start(), graph()->start(),
- JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
- graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
-
- Reduction r = Reduce(ret->InputAt(0),
- JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
- ASSERT_FALSE(r.Changed());
- EXPECT_TRUE(dependencies()->IsEmpty());
-}
-
-
-TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstStringWithDeoptimization) {
- Handle<HeapObject> kValue = isolate()->factory()->undefined_string();
- const char* kName = "mango";
- SetGlobalProperty(kName, kValue);
-
- Node* ret = ReturnLoadNamedFromGlobal(
- kName, graph()->start(), graph()->start(),
- JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
- graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
-
- Reduction r = Reduce(ret->InputAt(0),
- JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
-
- // Check LoadNamed(global) => HeapConstant[kValue]
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsHeapConstant(kValue));
-
- EXPECT_THAT(ret, IsReturn(IsHeapConstant(kValue), graph()->start(),
- graph()->start()));
- EXPECT_THAT(graph()->end(), IsEnd(ret));
-
- EXPECT_FALSE(dependencies()->IsEmpty());
- dependencies()->Rollback();
-}
-
-
-TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalPropertyCellSmi) {
- const char* kName = "melon";
- SetGlobalProperty(kName, 123);
- SetGlobalProperty(kName, 124);
-
- Node* ret = ReturnLoadNamedFromGlobal(
- kName, graph()->start(), graph()->start(),
- JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
- graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
-
- Reduction r = Reduce(ret->InputAt(0),
- JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
- ASSERT_FALSE(r.Changed());
- EXPECT_TRUE(dependencies()->IsEmpty());
-}
-
-
-TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalPropertyCellSmiWithDeoptimization) {
- const char* kName = "melon";
- SetGlobalProperty(kName, 123);
- SetGlobalProperty(kName, 124);
-
- Node* ret = ReturnLoadNamedFromGlobal(
- kName, graph()->start(), graph()->start(),
- JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
- graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
-
- Reduction r = Reduce(ret->InputAt(0),
- JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
-
- // Check LoadNamed(global) => LoadField[PropertyCell::value](cell)
- ASSERT_TRUE(r.Changed());
- FieldAccess access = AccessBuilder::ForPropertyCellValue();
- Capture<Node*> cell_capture;
- Matcher<Node*> load_field_match = IsLoadField(
- access, CaptureEq(&cell_capture), graph()->start(), graph()->start());
- EXPECT_THAT(r.replacement(), load_field_match);
-
- HeapObjectMatcher cell(cell_capture.value());
- EXPECT_TRUE(cell.HasValue());
- EXPECT_TRUE(cell.Value()->IsPropertyCell());
-
- EXPECT_THAT(ret,
- IsReturn(load_field_match, load_field_match, graph()->start()));
- EXPECT_THAT(graph()->end(), IsEnd(ret));
-
- EXPECT_FALSE(dependencies()->IsEmpty());
- dependencies()->Rollback();
-}
-
-
-TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalPropertyCellString) {
- const char* kName = "pineapple";
- SetGlobalProperty(kName, isolate()->factory()->undefined_string());
- SetGlobalProperty(kName, isolate()->factory()->undefined_value());
-
- Node* ret = ReturnLoadNamedFromGlobal(
- kName, graph()->start(), graph()->start(),
- JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
- graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
-
- Reduction r = Reduce(ret->InputAt(0),
- JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
- ASSERT_FALSE(r.Changed());
- EXPECT_TRUE(dependencies()->IsEmpty());
-}
-
-
-TEST_F(JSTypeFeedbackTest,
- JSLoadNamedGlobalPropertyCellStringWithDeoptimization) {
- const char* kName = "pineapple";
- SetGlobalProperty(kName, isolate()->factory()->undefined_string());
- SetGlobalProperty(kName, isolate()->factory()->undefined_value());
-
- Node* ret = ReturnLoadNamedFromGlobal(
- kName, graph()->start(), graph()->start(),
- JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
- graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
-
- Reduction r = Reduce(ret->InputAt(0),
- JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
-
- // Check LoadNamed(global) => LoadField[PropertyCell::value](cell)
- ASSERT_TRUE(r.Changed());
- FieldAccess access = AccessBuilder::ForPropertyCellValue();
- Capture<Node*> cell_capture;
- Matcher<Node*> load_field_match = IsLoadField(
- access, CaptureEq(&cell_capture), graph()->start(), graph()->start());
- EXPECT_THAT(r.replacement(), load_field_match);
-
- HeapObjectMatcher cell(cell_capture.value());
- EXPECT_TRUE(cell.HasValue());
- EXPECT_TRUE(cell.Value()->IsPropertyCell());
-
- EXPECT_THAT(ret,
- IsReturn(load_field_match, load_field_match, graph()->start()));
- EXPECT_THAT(graph()->end(), IsEnd(ret));
-
- EXPECT_FALSE(dependencies()->IsEmpty());
- dependencies()->Rollback();
-}
-
-} // namespace compiler
-} // namespace internal
-} // namespace v8
diff --git a/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc b/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc
index 72c582525e..ec1ff19880 100644
--- a/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc
+++ b/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc
@@ -33,36 +33,8 @@ const ExternalArrayType kExternalArrayTypes[] = {
kExternalInt16Array, kExternalUint32Array, kExternalInt32Array,
kExternalFloat32Array, kExternalFloat64Array};
-
-const double kFloat64Values[] = {
- -V8_INFINITY, -4.23878e+275, -5.82632e+265, -6.60355e+220, -6.26172e+212,
- -2.56222e+211, -4.82408e+201, -1.84106e+157, -1.63662e+127, -1.55772e+100,
- -1.67813e+72, -2.3382e+55, -3.179e+30, -1.441e+09, -1.0647e+09,
- -7.99361e+08, -5.77375e+08, -2.20984e+08, -32757, -13171, -9970, -3984,
- -107, -105, -92, -77, -61, -0.000208163, -1.86685e-06, -1.17296e-10,
- -9.26358e-11, -5.08004e-60, -1.74753e-65, -1.06561e-71, -5.67879e-79,
- -5.78459e-130, -2.90989e-171, -7.15489e-243, -3.76242e-252, -1.05639e-263,
- -4.40497e-267, -2.19666e-273, -4.9998e-276, -5.59821e-278, -2.03855e-282,
- -5.99335e-283, -7.17554e-284, -3.11744e-309, -0.0, 0.0, 2.22507e-308,
- 1.30127e-270, 7.62898e-260, 4.00313e-249, 3.16829e-233, 1.85244e-228,
- 2.03544e-129, 1.35126e-110, 1.01182e-106, 5.26333e-94, 1.35292e-90,
- 2.85394e-83, 1.78323e-77, 5.4967e-57, 1.03207e-25, 4.57401e-25, 1.58738e-05,
- 2, 125, 2310, 9636, 14802, 17168, 28945, 29305, 4.81336e+07, 1.41207e+08,
- 4.65962e+08, 1.40499e+09, 2.12648e+09, 8.80006e+30, 1.4446e+45, 1.12164e+54,
- 2.48188e+89, 6.71121e+102, 3.074e+112, 4.9699e+152, 5.58383e+166,
- 4.30654e+172, 7.08824e+185, 9.6586e+214, 2.028e+223, 6.63277e+243,
- 1.56192e+261, 1.23202e+269, 5.72883e+289, 8.5798e+290, 1.40256e+294,
- 1.79769e+308, V8_INFINITY};
-
-
const size_t kIndices[] = {0, 1, 42, 100, 1024};
-
-const double kIntegerValues[] = {-V8_INFINITY, INT_MIN, -1000.0, -42.0,
- -1.0, 0.0, 1.0, 42.0,
- 1000.0, INT_MAX, UINT_MAX, V8_INFINITY};
-
-
Type* const kJSTypes[] = {Type::Undefined(), Type::Null(), Type::Boolean(),
Type::Number(), Type::String(), Type::Object()};
@@ -112,100 +84,6 @@ class JSTypedLoweringTest : public TypedGraphTest {
// -----------------------------------------------------------------------------
-// Constant propagation
-
-
-TEST_F(JSTypedLoweringTest, ParameterWithMinusZero) {
- {
- Reduction r = Reduce(
- Parameter(Type::Constant(factory()->minus_zero_value(), zone())));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsNumberConstant(-0.0));
- }
- {
- Reduction r = Reduce(Parameter(Type::MinusZero()));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsNumberConstant(-0.0));
- }
- {
- Reduction r = Reduce(Parameter(
- Type::Union(Type::MinusZero(),
- Type::Constant(factory()->NewNumber(0), zone()), zone())));
- EXPECT_FALSE(r.Changed());
- }
-}
-
-
-TEST_F(JSTypedLoweringTest, ParameterWithNull) {
- Handle<HeapObject> null = factory()->null_value();
- {
- Reduction r = Reduce(Parameter(Type::Constant(null, zone())));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsHeapConstant(null));
- }
- {
- Reduction r = Reduce(Parameter(Type::Null()));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsHeapConstant(null));
- }
-}
-
-
-TEST_F(JSTypedLoweringTest, ParameterWithNaN) {
- const double kNaNs[] = {-std::numeric_limits<double>::quiet_NaN(),
- std::numeric_limits<double>::quiet_NaN(),
- std::numeric_limits<double>::signaling_NaN()};
- TRACED_FOREACH(double, nan, kNaNs) {
- Handle<Object> constant = factory()->NewNumber(nan);
- Reduction r = Reduce(Parameter(Type::Constant(constant, zone())));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN()));
- }
- {
- Reduction r =
- Reduce(Parameter(Type::Constant(factory()->nan_value(), zone())));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN()));
- }
- {
- Reduction r = Reduce(Parameter(Type::NaN()));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN()));
- }
-}
-
-
-TEST_F(JSTypedLoweringTest, ParameterWithPlainNumber) {
- TRACED_FOREACH(double, value, kFloat64Values) {
- Handle<Object> constant = factory()->NewNumber(value);
- Reduction r = Reduce(Parameter(Type::Constant(constant, zone())));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsNumberConstant(value));
- }
- TRACED_FOREACH(double, value, kIntegerValues) {
- Reduction r = Reduce(Parameter(Type::Range(value, value, zone())));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsNumberConstant(value));
- }
-}
-
-
-TEST_F(JSTypedLoweringTest, ParameterWithUndefined) {
- Handle<HeapObject> undefined = factory()->undefined_value();
- {
- Reduction r = Reduce(Parameter(Type::Undefined()));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsHeapConstant(undefined));
- }
- {
- Reduction r = Reduce(Parameter(Type::Constant(undefined, zone())));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsHeapConstant(undefined));
- }
-}
-
-
-// -----------------------------------------------------------------------------
// JSToBoolean
@@ -219,60 +97,6 @@ TEST_F(JSTypedLoweringTest, JSToBooleanWithBoolean) {
}
-TEST_F(JSTypedLoweringTest, JSToBooleanWithFalsish) {
- Node* input = Parameter(
- Type::Union(
- Type::MinusZero(),
- Type::Union(
- Type::NaN(),
- Type::Union(
- Type::Null(),
- Type::Union(
- Type::Undefined(),
- Type::Union(
- Type::Undetectable(),
- Type::Union(
- Type::Constant(factory()->false_value(), zone()),
- Type::Range(0.0, 0.0, zone()), zone()),
- zone()),
- zone()),
- zone()),
- zone()),
- zone()),
- 0);
- Node* context = Parameter(Type::Any(), 1);
- Reduction r = Reduce(graph()->NewNode(
- javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsFalseConstant());
-}
-
-
-TEST_F(JSTypedLoweringTest, JSToBooleanWithTruish) {
- Node* input = Parameter(
- Type::Union(
- Type::Constant(factory()->true_value(), zone()),
- Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone()),
- zone()),
- 0);
- Node* context = Parameter(Type::Any(), 1);
- Reduction r = Reduce(graph()->NewNode(
- javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsTrueConstant());
-}
-
-
-TEST_F(JSTypedLoweringTest, JSToBooleanWithNonZeroPlainNumber) {
- Node* input = Parameter(Type::Range(1, V8_INFINITY, zone()), 0);
- Node* context = Parameter(Type::Any(), 1);
- Reduction r = Reduce(graph()->NewNode(
- javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(), IsTrueConstant());
-}
-
-
TEST_F(JSTypedLoweringTest, JSToBooleanWithOrderedNumber) {
Node* input = Parameter(Type::OrderedNumber(), 0);
Node* context = Parameter(Type::Any(), 1);
@@ -289,24 +113,9 @@ TEST_F(JSTypedLoweringTest, JSToBooleanWithNumber) {
Reduction r = Reduce(graph()->NewNode(
javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
ASSERT_TRUE(r.Changed());
- EXPECT_THAT(r.replacement(),
- IsNumberLessThan(IsNumberConstant(0.0), IsNumberAbs(input)));
+ EXPECT_THAT(r.replacement(), IsNumberToBoolean(input));
}
-TEST_F(JSTypedLoweringTest, JSToBooleanWithString) {
- Node* input = Parameter(Type::String(), 0);
- Node* context = Parameter(Type::Any(), 1);
- Reduction r = Reduce(graph()->NewNode(
- javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
- ASSERT_TRUE(r.Changed());
- EXPECT_THAT(
- r.replacement(),
- IsNumberLessThan(IsNumberConstant(0.0),
- IsLoadField(AccessBuilder::ForStringLength(), input,
- graph()->start(), graph()->start())));
-}
-
-
TEST_F(JSTypedLoweringTest, JSToBooleanWithAny) {
Node* input = Parameter(Type::Any(), 0);
Node* context = Parameter(Type::Any(), 1);
@@ -1022,68 +831,6 @@ TEST_F(JSTypedLoweringTest, JSSubtractSmis) {
}
// -----------------------------------------------------------------------------
-// JSInstanceOf
-// Test that instanceOf is reduced if and only if the right-hand side is a
-// function constant. Functional correctness is ensured elsewhere.
-
-TEST_F(JSTypedLoweringTest, JSInstanceOfSpecializationWithoutSmiCheck) {
- Node* const context = Parameter(Type::Any());
- Node* const frame_state = EmptyFrameState();
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
-
- // Reduce if left-hand side is known to be an object.
- Node* instanceOf =
- graph()->NewNode(javascript()->InstanceOf(), Parameter(Type::Object(), 0),
- HeapConstant(isolate()->object_function()), context,
- frame_state, effect, control);
- Node* dummy = graph()->NewNode(javascript()->ToObject(), instanceOf, context,
- frame_state, effect, control);
- Reduction r = Reduce(instanceOf);
- ASSERT_TRUE(r.Changed());
- ASSERT_EQ(r.replacement(), dummy->InputAt(0));
- ASSERT_NE(instanceOf, dummy->InputAt(0));
-}
-
-
-TEST_F(JSTypedLoweringTest, JSInstanceOfSpecializationWithSmiCheck) {
- Node* const context = Parameter(Type::Any());
- Node* const frame_state = EmptyFrameState();
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
-
- // Reduce if left-hand side could be a Smi.
- Node* instanceOf =
- graph()->NewNode(javascript()->InstanceOf(), Parameter(Type::Any(), 0),
- HeapConstant(isolate()->object_function()), context,
- frame_state, effect, control);
- Node* dummy = graph()->NewNode(javascript()->ToObject(), instanceOf, context,
- frame_state, effect, control);
- Reduction r = Reduce(instanceOf);
- ASSERT_TRUE(r.Changed());
- ASSERT_EQ(r.replacement(), dummy->InputAt(0));
- ASSERT_NE(instanceOf, dummy->InputAt(0));
-}
-
-
-TEST_F(JSTypedLoweringTest, JSInstanceOfNoSpecialization) {
- Node* const context = Parameter(Type::Any());
- Node* const frame_state = EmptyFrameState();
- Node* const effect = graph()->start();
- Node* const control = graph()->start();
-
- // Do not reduce if right-hand side is not a function constant.
- Node* instanceOf = graph()->NewNode(
- javascript()->InstanceOf(), Parameter(Type::Any(), 0),
- Parameter(Type::Any()), context, frame_state, effect, control);
- Node* dummy = graph()->NewNode(javascript()->ToObject(), instanceOf, context,
- frame_state, effect, control);
- Reduction r = Reduce(instanceOf);
- ASSERT_FALSE(r.Changed());
- ASSERT_EQ(instanceOf, dummy->InputAt(0));
-}
-
-// -----------------------------------------------------------------------------
// JSBitwiseAnd
TEST_F(JSTypedLoweringTest, JSBitwiseAndWithSignedSmallHint) {
diff --git a/deps/v8/test/unittests/compiler/load-elimination-unittest.cc b/deps/v8/test/unittests/compiler/load-elimination-unittest.cc
index ada99b5a7f..81393941bb 100644
--- a/deps/v8/test/unittests/compiler/load-elimination-unittest.cc
+++ b/deps/v8/test/unittests/compiler/load-elimination-unittest.cc
@@ -213,6 +213,269 @@ TEST_F(LoadEliminationTest, StoreFieldAndStoreElementAndLoadField) {
EXPECT_EQ(value, r.replacement());
}
+TEST_F(LoadEliminationTest, LoadElementOnTrueBranchOfDiamond) {
+ Node* object = Parameter(Type::Any(), 0);
+ Node* index = Parameter(Type::UnsignedSmall(), 1);
+ Node* check = Parameter(Type::Boolean(), 2);
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ ElementAccess const access = {kTaggedBase, kPointerSize, Type::Any(),
+ MachineType::AnyTagged(), kNoWriteBarrier};
+
+ StrictMock<MockAdvancedReducerEditor> editor;
+ LoadElimination load_elimination(&editor, jsgraph(), zone());
+
+ load_elimination.Reduce(graph()->start());
+
+ Node* branch = graph()->NewNode(common()->Branch(), check, control);
+
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* etrue = graph()->NewNode(simplified()->LoadElement(access), object,
+ index, effect, if_true);
+ load_elimination.Reduce(etrue);
+
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* efalse = effect;
+
+ control = graph()->NewNode(common()->Merge(2), if_true, if_false);
+ effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
+ load_elimination.Reduce(effect);
+
+ Node* load = graph()->NewNode(simplified()->LoadElement(access), object,
+ index, effect, control);
+ Reduction r = load_elimination.Reduce(load);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_EQ(load, r.replacement());
+}
+
+TEST_F(LoadEliminationTest, LoadElementOnFalseBranchOfDiamond) {
+ Node* object = Parameter(Type::Any(), 0);
+ Node* index = Parameter(Type::UnsignedSmall(), 1);
+ Node* check = Parameter(Type::Boolean(), 2);
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ ElementAccess const access = {kTaggedBase, kPointerSize, Type::Any(),
+ MachineType::AnyTagged(), kNoWriteBarrier};
+
+ StrictMock<MockAdvancedReducerEditor> editor;
+ LoadElimination load_elimination(&editor, jsgraph(), zone());
+
+ load_elimination.Reduce(graph()->start());
+
+ Node* branch = graph()->NewNode(common()->Branch(), check, control);
+
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* etrue = effect;
+
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* efalse = graph()->NewNode(simplified()->LoadElement(access), object,
+ index, effect, if_false);
+ load_elimination.Reduce(efalse);
+
+ control = graph()->NewNode(common()->Merge(2), if_true, if_false);
+ effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
+ load_elimination.Reduce(effect);
+
+ Node* load = graph()->NewNode(simplified()->LoadElement(access), object,
+ index, effect, control);
+ Reduction r = load_elimination.Reduce(load);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_EQ(load, r.replacement());
+}
+
+TEST_F(LoadEliminationTest, LoadFieldOnFalseBranchOfDiamond) {
+ Node* object = Parameter(Type::Any(), 0);
+ Node* check = Parameter(Type::Boolean(), 1);
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ FieldAccess const access = {kTaggedBase,
+ kPointerSize,
+ MaybeHandle<Name>(),
+ Type::Any(),
+ MachineType::AnyTagged(),
+ kNoWriteBarrier};
+
+ StrictMock<MockAdvancedReducerEditor> editor;
+ LoadElimination load_elimination(&editor, jsgraph(), zone());
+
+ load_elimination.Reduce(graph()->start());
+
+ Node* branch = graph()->NewNode(common()->Branch(), check, control);
+
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* etrue = effect;
+
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* efalse = graph()->NewNode(simplified()->LoadField(access), object,
+ effect, if_false);
+ load_elimination.Reduce(efalse);
+
+ control = graph()->NewNode(common()->Merge(2), if_true, if_false);
+ effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
+ load_elimination.Reduce(effect);
+
+ Node* load = graph()->NewNode(simplified()->LoadField(access), object, effect,
+ control);
+ Reduction r = load_elimination.Reduce(load);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_EQ(load, r.replacement());
+}
+
+TEST_F(LoadEliminationTest, LoadFieldOnTrueBranchOfDiamond) {
+ Node* object = Parameter(Type::Any(), 0);
+ Node* check = Parameter(Type::Boolean(), 1);
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ FieldAccess const access = {kTaggedBase,
+ kPointerSize,
+ MaybeHandle<Name>(),
+ Type::Any(),
+ MachineType::AnyTagged(),
+ kNoWriteBarrier};
+
+ StrictMock<MockAdvancedReducerEditor> editor;
+ LoadElimination load_elimination(&editor, jsgraph(), zone());
+
+ load_elimination.Reduce(graph()->start());
+
+ Node* branch = graph()->NewNode(common()->Branch(), check, control);
+
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+ Node* etrue = graph()->NewNode(simplified()->LoadField(access), object,
+ effect, if_true);
+ load_elimination.Reduce(etrue);
+
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* efalse = effect;
+
+ control = graph()->NewNode(common()->Merge(2), if_true, if_false);
+ effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
+ load_elimination.Reduce(effect);
+
+ Node* load = graph()->NewNode(simplified()->LoadField(access), object, effect,
+ control);
+ Reduction r = load_elimination.Reduce(load);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_EQ(load, r.replacement());
+}
+
+TEST_F(LoadEliminationTest, LoadFieldWithTypeMismatch) {
+ Node* object = Parameter(Type::Any(), 0);
+ Node* value = Parameter(Type::Signed32(), 1);
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ FieldAccess const access = {kTaggedBase,
+ kPointerSize,
+ MaybeHandle<Name>(),
+ Type::Unsigned31(),
+ MachineType::AnyTagged(),
+ kNoWriteBarrier};
+
+ StrictMock<MockAdvancedReducerEditor> editor;
+ LoadElimination load_elimination(&editor, jsgraph(), zone());
+
+ load_elimination.Reduce(graph()->start());
+
+ Node* store = effect = graph()->NewNode(simplified()->StoreField(access),
+ object, value, effect, control);
+ load_elimination.Reduce(effect);
+
+ Node* load = graph()->NewNode(simplified()->LoadField(access), object, effect,
+ control);
+ EXPECT_CALL(editor,
+ ReplaceWithValue(load, IsTypeGuard(value, control), store, _));
+ Reduction r = load_elimination.Reduce(load);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsTypeGuard(value, control));
+}
+
+TEST_F(LoadEliminationTest, LoadElementWithTypeMismatch) {
+ Node* object = Parameter(Type::Any(), 0);
+ Node* index = Parameter(Type::UnsignedSmall(), 1);
+ Node* value = Parameter(Type::Signed32(), 2);
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ ElementAccess const access = {kTaggedBase, kPointerSize, Type::Unsigned31(),
+ MachineType::AnyTagged(), kNoWriteBarrier};
+
+ StrictMock<MockAdvancedReducerEditor> editor;
+ LoadElimination load_elimination(&editor, jsgraph(), zone());
+
+ load_elimination.Reduce(graph()->start());
+
+ Node* store = effect =
+ graph()->NewNode(simplified()->StoreElement(access), object, index, value,
+ effect, control);
+ load_elimination.Reduce(effect);
+
+ Node* load = graph()->NewNode(simplified()->LoadElement(access), object,
+ index, effect, control);
+ EXPECT_CALL(editor,
+ ReplaceWithValue(load, IsTypeGuard(value, control), store, _));
+ Reduction r = load_elimination.Reduce(load);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsTypeGuard(value, control));
+}
+
+TEST_F(LoadEliminationTest, AliasAnalysisForFinishRegion) {
+ Node* value0 = Parameter(Type::Signed32(), 0);
+ Node* value1 = Parameter(Type::Signed32(), 1);
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ FieldAccess const access = {kTaggedBase,
+ kPointerSize,
+ MaybeHandle<Name>(),
+ Type::Signed32(),
+ MachineType::AnyTagged(),
+ kNoWriteBarrier};
+
+ StrictMock<MockAdvancedReducerEditor> editor;
+ LoadElimination load_elimination(&editor, jsgraph(), zone());
+
+ load_elimination.Reduce(effect);
+
+ effect = graph()->NewNode(
+ common()->BeginRegion(RegionObservability::kNotObservable), effect);
+ load_elimination.Reduce(effect);
+
+ Node* object0 = effect =
+ graph()->NewNode(simplified()->Allocate(NOT_TENURED),
+ jsgraph()->Constant(16), effect, control);
+ load_elimination.Reduce(effect);
+
+ Node* region0 = effect =
+ graph()->NewNode(common()->FinishRegion(), object0, effect);
+ load_elimination.Reduce(effect);
+
+ effect = graph()->NewNode(
+ common()->BeginRegion(RegionObservability::kNotObservable), effect);
+ load_elimination.Reduce(effect);
+
+ Node* object1 = effect =
+ graph()->NewNode(simplified()->Allocate(NOT_TENURED),
+ jsgraph()->Constant(16), effect, control);
+ load_elimination.Reduce(effect);
+
+ Node* region1 = effect =
+ graph()->NewNode(common()->FinishRegion(), object1, effect);
+ load_elimination.Reduce(effect);
+
+ effect = graph()->NewNode(simplified()->StoreField(access), region0, value0,
+ effect, control);
+ load_elimination.Reduce(effect);
+
+ effect = graph()->NewNode(simplified()->StoreField(access), region1, value1,
+ effect, control);
+ load_elimination.Reduce(effect);
+
+ Node* load = graph()->NewNode(simplified()->LoadField(access), region0,
+ effect, control);
+ EXPECT_CALL(editor, ReplaceWithValue(load, value0, effect, _));
+ Reduction r = load_elimination.Reduce(load);
+ ASSERT_TRUE(r.Changed());
+ EXPECT_EQ(value0, r.replacement());
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc b/deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc
index ed426be5d8..1d29d9733f 100644
--- a/deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc
@@ -23,10 +23,10 @@ namespace v8 {
namespace internal {
namespace compiler {
-class MachineOperatorReducerTest : public TypedGraphTest {
+class MachineOperatorReducerTest : public GraphTest {
public:
explicit MachineOperatorReducerTest(int num_parameters = 2)
- : TypedGraphTest(num_parameters), machine_(zone()) {}
+ : GraphTest(num_parameters), machine_(zone()) {}
protected:
Reduction Reduce(Node* node) {
@@ -729,25 +729,52 @@ TEST_F(MachineOperatorReducerTest, ReduceToWord32RorWithParameters) {
EXPECT_EQ(reduction2.replacement(), node2);
EXPECT_THAT(reduction2.replacement(), IsWord32Ror(value, sub));
- // Testing rotate right.
- Node* shl_r = graph()->NewNode(machine()->Word32Shl(), value, sub);
- Node* shr_r = graph()->NewNode(machine()->Word32Shr(), value, shift);
-
- // (x << (32 - y)) | (x >>> y) => x ror y
- Node* node3 = graph()->NewNode(machine()->Word32Or(), shl_r, shr_r);
+ // (x << y) ^ (x >>> (32 - y)) => x ror (32 - y)
+ Node* node3 = graph()->NewNode(machine()->Word32Xor(), shl_l, shr_l);
Reduction reduction3 = Reduce(node3);
EXPECT_TRUE(reduction3.Changed());
EXPECT_EQ(reduction3.replacement(), node3);
- EXPECT_THAT(reduction3.replacement(), IsWord32Ror(value, shift));
+ EXPECT_THAT(reduction3.replacement(), IsWord32Ror(value, sub));
- // (x >>> y) | (x << (32 - y)) => x ror y
- Node* node4 = graph()->NewNode(machine()->Word32Or(), shr_r, shl_r);
+ // (x >>> (32 - y)) ^ (x << y) => x ror (32 - y)
+ Node* node4 = graph()->NewNode(machine()->Word32Xor(), shr_l, shl_l);
Reduction reduction4 = Reduce(node4);
EXPECT_TRUE(reduction4.Changed());
EXPECT_EQ(reduction4.replacement(), node4);
- EXPECT_THAT(reduction4.replacement(), IsWord32Ror(value, shift));
-}
+ EXPECT_THAT(reduction4.replacement(), IsWord32Ror(value, sub));
+
+ // Testing rotate right.
+ Node* shl_r = graph()->NewNode(machine()->Word32Shl(), value, sub);
+ Node* shr_r = graph()->NewNode(machine()->Word32Shr(), value, shift);
+
+ // (x << (32 - y)) | (x >>> y) => x ror y
+ Node* node5 = graph()->NewNode(machine()->Word32Or(), shl_r, shr_r);
+ Reduction reduction5 = Reduce(node5);
+ EXPECT_TRUE(reduction5.Changed());
+ EXPECT_EQ(reduction5.replacement(), node5);
+ EXPECT_THAT(reduction5.replacement(), IsWord32Ror(value, shift));
+ // (x >>> y) | (x << (32 - y)) => x ror y
+ Node* node6 = graph()->NewNode(machine()->Word32Or(), shr_r, shl_r);
+ Reduction reduction6 = Reduce(node6);
+ EXPECT_TRUE(reduction6.Changed());
+ EXPECT_EQ(reduction6.replacement(), node6);
+ EXPECT_THAT(reduction6.replacement(), IsWord32Ror(value, shift));
+
+ // (x << (32 - y)) ^ (x >>> y) => x ror y
+ Node* node7 = graph()->NewNode(machine()->Word32Xor(), shl_r, shr_r);
+ Reduction reduction7 = Reduce(node7);
+ EXPECT_TRUE(reduction7.Changed());
+ EXPECT_EQ(reduction7.replacement(), node7);
+ EXPECT_THAT(reduction7.replacement(), IsWord32Ror(value, shift));
+
+ // (x >>> y) ^ (x << (32 - y)) => x ror y
+ Node* node8 = graph()->NewNode(machine()->Word32Xor(), shr_r, shl_r);
+ Reduction reduction8 = Reduce(node8);
+ EXPECT_TRUE(reduction8.Changed());
+ EXPECT_EQ(reduction8.replacement(), node8);
+ EXPECT_THAT(reduction8.replacement(), IsWord32Ror(value, shift));
+}
TEST_F(MachineOperatorReducerTest, ReduceToWord32RorWithConstant) {
Node* value = Parameter(0);
@@ -1587,6 +1614,48 @@ TEST_F(MachineOperatorReducerTest, Float32SubMinusZeroMinusX) {
}
}
+TEST_F(MachineOperatorReducerTest, Float64MulWithTwo) {
+ Node* const p0 = Parameter(0);
+ {
+ Reduction r = Reduce(
+ graph()->NewNode(machine()->Float64Mul(), Float64Constant(2.0), p0));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsFloat64Add(p0, p0));
+ }
+ {
+ Reduction r = Reduce(
+ graph()->NewNode(machine()->Float64Mul(), p0, Float64Constant(2.0)));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsFloat64Add(p0, p0));
+ }
+}
+
+// -----------------------------------------------------------------------------
+// Float64Div
+
+TEST_F(MachineOperatorReducerTest, Float64DivWithMinusOne) {
+ Node* const p0 = Parameter(0);
+ {
+ Reduction r = Reduce(
+ graph()->NewNode(machine()->Float64Div(), p0, Float64Constant(-1.0)));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsFloat64Neg(p0));
+ }
+}
+
+TEST_F(MachineOperatorReducerTest, Float64DivWithPowerOfTwo) {
+ Node* const p0 = Parameter(0);
+ TRACED_FORRANGE(uint64_t, exponent, 1, 0x7fe) {
+ Double divisor = Double(exponent << Double::kPhysicalSignificandSize);
+ if (divisor.value() == 1.0) continue; // Skip x / 1.0 => x.
+ Reduction r = Reduce(graph()->NewNode(machine()->Float64Div(), p0,
+ Float64Constant(divisor.value())));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(),
+ IsFloat64Mul(p0, IsFloat64Constant(1.0 / divisor.value())));
+ }
+}
+
// -----------------------------------------------------------------------------
// Float64Acos
@@ -1772,6 +1841,37 @@ TEST_F(MachineOperatorReducerTest, Float64Log1pWithConstant) {
}
// -----------------------------------------------------------------------------
+// Float64Pow
+
+TEST_F(MachineOperatorReducerTest, Float64PowWithConstant) {
+ TRACED_FOREACH(double, x, kFloat64Values) {
+ TRACED_FOREACH(double, y, kFloat64Values) {
+ Reduction const r = Reduce(graph()->NewNode(
+ machine()->Float64Pow(), Float64Constant(x), Float64Constant(y)));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(),
+ IsFloat64Constant(NanSensitiveDoubleEq(Pow(x, y))));
+ }
+ }
+}
+
+TEST_F(MachineOperatorReducerTest, Float64PowWithZeroExponent) {
+ Node* const p0 = Parameter(0);
+ {
+ Reduction const r = Reduce(
+ graph()->NewNode(machine()->Float64Pow(), p0, Float64Constant(-0.0)));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsFloat64Constant(1.0));
+ }
+ {
+ Reduction const r = Reduce(
+ graph()->NewNode(machine()->Float64Pow(), p0, Float64Constant(0.0)));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsFloat64Constant(1.0));
+ }
+}
+
+// -----------------------------------------------------------------------------
// Float64Sin
TEST_F(MachineOperatorReducerTest, Float64SinWithConstant) {
diff --git a/deps/v8/test/unittests/compiler/mips/instruction-selector-mips-unittest.cc b/deps/v8/test/unittests/compiler/mips/instruction-selector-mips-unittest.cc
index 7b5c667261..dc14b85361 100644
--- a/deps/v8/test/unittests/compiler/mips/instruction-selector-mips-unittest.cc
+++ b/deps/v8/test/unittests/compiler/mips/instruction-selector-mips-unittest.cc
@@ -408,6 +408,36 @@ TEST_F(InstructionSelectorTest, Word32ShlWithWord32And) {
}
}
+TEST_F(InstructionSelectorTest, Word32SarWithWord32Shl) {
+ {
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+ Node* const p0 = m.Parameter(0);
+ Node* const r =
+ m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(24)), m.Int32Constant(24));
+ m.Return(r);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kMipsSeb, s[0]->arch_opcode());
+ ASSERT_EQ(1U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
+ }
+ {
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+ Node* const p0 = m.Parameter(0);
+ Node* const r =
+ m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(16)), m.Int32Constant(16));
+ m.Return(r);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kMipsSeh, s[0]->arch_opcode());
+ ASSERT_EQ(1U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
+ }
+}
// ----------------------------------------------------------------------------
// Logical instructions.
@@ -1149,6 +1179,219 @@ TEST_F(InstructionSelectorTest, Float64Abs) {
EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
}
+TEST_F(InstructionSelectorTest, Float32AddWithFloat32Mul) {
+ if (!IsMipsArchVariant(kMips32r2) && !IsMipsArchVariant(kMips32r6)) {
+ return;
+ }
+ {
+ StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
+ MachineType::Float32(), MachineType::Float32());
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* const p2 = m.Parameter(2);
+ Node* const n = m.Float32Add(m.Float32Mul(p0, p1), p2);
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ if (IsMipsArchVariant(kMips32r2)) {
+ EXPECT_EQ(kMipsMaddS, s[0]->arch_opcode());
+ } else if (IsMipsArchVariant(kMips32r6)) {
+ EXPECT_EQ(kMipsMaddfS, s[0]->arch_opcode());
+ }
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(2)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ if (IsMipsArchVariant(kMips32r2)) {
+ EXPECT_FALSE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ } else if (IsMipsArchVariant(kMips32r6)) {
+ EXPECT_TRUE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ }
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode());
+ }
+ {
+ StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
+ MachineType::Float32(), MachineType::Float32());
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* const p2 = m.Parameter(2);
+ Node* const n = m.Float32Add(p0, m.Float32Mul(p1, p2));
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ if (IsMipsArchVariant(kMips32r2)) {
+ EXPECT_EQ(kMipsMaddS, s[0]->arch_opcode());
+ } else if (IsMipsArchVariant(kMips32r6)) {
+ EXPECT_EQ(kMipsMaddfS, s[0]->arch_opcode());
+ }
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ if (IsMipsArchVariant(kMips32r2)) {
+ EXPECT_FALSE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ } else if (IsMipsArchVariant(kMips32r6)) {
+ EXPECT_TRUE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ }
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode());
+ }
+}
+
+TEST_F(InstructionSelectorTest, Float64AddWithFloat64Mul) {
+ if (!IsMipsArchVariant(kMips32r2) && !IsMipsArchVariant(kMips32r6)) {
+ return;
+ }
+ {
+ StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
+ MachineType::Float64(), MachineType::Float64());
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* const p2 = m.Parameter(2);
+ Node* const n = m.Float64Add(m.Float64Mul(p0, p1), p2);
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ if (IsMipsArchVariant(kMips32r2)) {
+ EXPECT_EQ(kMipsMaddD, s[0]->arch_opcode());
+ } else if (IsMipsArchVariant(kMips32r6)) {
+ EXPECT_EQ(kMipsMaddfD, s[0]->arch_opcode());
+ }
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(2)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ if (IsMipsArchVariant(kMips32r2)) {
+ EXPECT_FALSE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ } else if (IsMipsArchVariant(kMips32r6)) {
+ EXPECT_TRUE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ }
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode());
+ }
+ {
+ StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
+ MachineType::Float64(), MachineType::Float64());
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* const p2 = m.Parameter(2);
+ Node* const n = m.Float64Add(p0, m.Float64Mul(p1, p2));
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ if (IsMipsArchVariant(kMips32r2)) {
+ EXPECT_EQ(kMipsMaddD, s[0]->arch_opcode());
+ } else if (IsMipsArchVariant(kMips32r6)) {
+ EXPECT_EQ(kMipsMaddfD, s[0]->arch_opcode());
+ }
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ if (IsMipsArchVariant(kMips32r2)) {
+ EXPECT_FALSE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ } else if (IsMipsArchVariant(kMips32r6)) {
+ EXPECT_TRUE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ }
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode());
+ }
+}
+
+TEST_F(InstructionSelectorTest, Float32SubWithFloat32Mul) {
+ StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
+ MachineType::Float32(), MachineType::Float32());
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* const p2 = m.Parameter(2);
+ Node* n = nullptr;
+
+ if (!IsMipsArchVariant(kMips32r2) && !IsMipsArchVariant(kMips32r6)) {
+ return;
+ }
+
+ if (IsMipsArchVariant(kMips32r2)) {
+ n = m.Float32Sub(m.Float32Mul(p1, p2), p0);
+ } else if (IsMipsArchVariant(kMips32r6)) {
+ n = m.Float32Sub(p0, m.Float32Mul(p1, p2));
+ }
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ if (IsMipsArchVariant(kMips32r2)) {
+ EXPECT_EQ(kMipsMsubS, s[0]->arch_opcode());
+ } else if (IsMipsArchVariant(kMips32r6)) {
+ EXPECT_EQ(kMipsMsubfS, s[0]->arch_opcode());
+ }
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ if (IsMipsArchVariant(kMips32r2)) {
+ EXPECT_FALSE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ } else if (IsMipsArchVariant(kMips32r6)) {
+ EXPECT_TRUE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ }
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode());
+}
+
+TEST_F(InstructionSelectorTest, Float64SubWithFloat64Mul) {
+ StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
+ MachineType::Float64(), MachineType::Float64());
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* const p2 = m.Parameter(2);
+ Node* n = nullptr;
+
+ if (!IsMipsArchVariant(kMips32r2) && !IsMipsArchVariant(kMips32r6)) {
+ return;
+ }
+
+ if (IsMipsArchVariant(kMips32r2)) {
+ n = m.Float64Sub(m.Float64Mul(p1, p2), p0);
+ } else if (IsMipsArchVariant(kMips32r6)) {
+ n = m.Float64Sub(p0, m.Float64Mul(p1, p2));
+ }
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ if (IsMipsArchVariant(kMips32r2)) {
+ EXPECT_EQ(kMipsMsubD, s[0]->arch_opcode());
+ } else if (IsMipsArchVariant(kMips32r6)) {
+ EXPECT_EQ(kMipsMsubfD, s[0]->arch_opcode());
+ }
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ if (IsMipsArchVariant(kMips32r2)) {
+ EXPECT_FALSE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ } else if (IsMipsArchVariant(kMips32r6)) {
+ EXPECT_TRUE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ }
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode());
+}
TEST_F(InstructionSelectorTest, Float64Max) {
StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
diff --git a/deps/v8/test/unittests/compiler/mips64/instruction-selector-mips64-unittest.cc b/deps/v8/test/unittests/compiler/mips64/instruction-selector-mips64-unittest.cc
index c82cb9fe4f..be77126688 100644
--- a/deps/v8/test/unittests/compiler/mips64/instruction-selector-mips64-unittest.cc
+++ b/deps/v8/test/unittests/compiler/mips64/instruction-selector-mips64-unittest.cc
@@ -719,6 +719,51 @@ TEST_F(InstructionSelectorTest, Word64ShlWithWord64And) {
}
}
+TEST_F(InstructionSelectorTest, Word32SarWithWord32Shl) {
+ {
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+ Node* const p0 = m.Parameter(0);
+ Node* const r =
+ m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(24)), m.Int32Constant(24));
+ m.Return(r);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kMips64Seb, s[0]->arch_opcode());
+ ASSERT_EQ(1U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
+ }
+ {
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+ Node* const p0 = m.Parameter(0);
+ Node* const r =
+ m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(16)), m.Int32Constant(16));
+ m.Return(r);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kMips64Seh, s[0]->arch_opcode());
+ ASSERT_EQ(1U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
+ }
+ {
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+ Node* const p0 = m.Parameter(0);
+ Node* const r =
+ m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(32)), m.Int32Constant(32));
+ m.Return(r);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kMips64Shl, s[0]->arch_opcode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output()));
+ }
+}
// ----------------------------------------------------------------------------
// MUL/DIV instructions.
@@ -1491,6 +1536,203 @@ TEST_F(InstructionSelectorTest, Float64Abs) {
EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
}
+TEST_F(InstructionSelectorTest, Float32AddWithFloat32Mul) {
+ {
+ StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
+ MachineType::Float32(), MachineType::Float32());
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* const p2 = m.Parameter(2);
+ Node* const n = m.Float32Add(m.Float32Mul(p0, p1), p2);
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ if (kArchVariant == kMips64r2) {
+ EXPECT_EQ(kMips64MaddS, s[0]->arch_opcode());
+ } else if (kArchVariant == kMips64r6) {
+ EXPECT_EQ(kMips64MaddfS, s[0]->arch_opcode());
+ }
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(2)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ if (kArchVariant == kMips64r2) {
+ EXPECT_FALSE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ } else if (kArchVariant == kMips64r6) {
+ EXPECT_TRUE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ }
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode());
+ }
+ {
+ StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
+ MachineType::Float32(), MachineType::Float32());
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* const p2 = m.Parameter(2);
+ Node* const n = m.Float32Add(p0, m.Float32Mul(p1, p2));
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ if (kArchVariant == kMips64r2) {
+ EXPECT_EQ(kMips64MaddS, s[0]->arch_opcode());
+ } else if (kArchVariant == kMips64r6) {
+ EXPECT_EQ(kMips64MaddfS, s[0]->arch_opcode());
+ }
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ if (kArchVariant == kMips64r2) {
+ EXPECT_FALSE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ } else if (kArchVariant == kMips64r6) {
+ EXPECT_TRUE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ }
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode());
+ }
+}
+
+TEST_F(InstructionSelectorTest, Float64AddWithFloat64Mul) {
+ {
+ StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
+ MachineType::Float64(), MachineType::Float64());
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* const p2 = m.Parameter(2);
+ Node* const n = m.Float64Add(m.Float64Mul(p0, p1), p2);
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ if (kArchVariant == kMips64r2) {
+ EXPECT_EQ(kMips64MaddD, s[0]->arch_opcode());
+ } else if (kArchVariant == kMips64r6) {
+ EXPECT_EQ(kMips64MaddfD, s[0]->arch_opcode());
+ }
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(2)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ if (kArchVariant == kMips64r2) {
+ EXPECT_FALSE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ } else if (kArchVariant == kMips64r6) {
+ EXPECT_TRUE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ }
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode());
+ }
+ {
+ StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
+ MachineType::Float64(), MachineType::Float64());
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* const p2 = m.Parameter(2);
+ Node* const n = m.Float64Add(p0, m.Float64Mul(p1, p2));
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ if (kArchVariant == kMips64r2) {
+ EXPECT_EQ(kMips64MaddD, s[0]->arch_opcode());
+ } else if (kArchVariant == kMips64r6) {
+ EXPECT_EQ(kMips64MaddfD, s[0]->arch_opcode());
+ }
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ if (kArchVariant == kMips64r2) {
+ EXPECT_FALSE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ } else if (kArchVariant == kMips64r6) {
+ EXPECT_TRUE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ }
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode());
+ }
+}
+
+TEST_F(InstructionSelectorTest, Float32SubWithFloat32Mul) {
+ StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(),
+ MachineType::Float32(), MachineType::Float32());
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* const p2 = m.Parameter(2);
+ Node* n;
+ if (kArchVariant == kMips64r2) {
+ n = m.Float32Sub(m.Float32Mul(p1, p2), p0);
+ } else if (kArchVariant == kMips64r6) {
+ n = m.Float32Sub(p0, m.Float32Mul(p1, p2));
+ }
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ if (kArchVariant == kMips64r2) {
+ EXPECT_EQ(kMips64MsubS, s[0]->arch_opcode());
+ } else if (kArchVariant == kMips64r6) {
+ EXPECT_EQ(kMips64MsubfS, s[0]->arch_opcode());
+ }
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ if (kArchVariant == kMips64r2) {
+ EXPECT_FALSE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ } else if (kArchVariant == kMips64r6) {
+ EXPECT_TRUE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ }
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode());
+}
+
+TEST_F(InstructionSelectorTest, Float64SubWithFloat64Mul) {
+ StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
+ MachineType::Float64(), MachineType::Float64());
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* const p2 = m.Parameter(2);
+ Node* n;
+ if (kArchVariant == kMips64r2) {
+ n = m.Float64Sub(m.Float64Mul(p1, p2), p0);
+ } else if (kArchVariant == kMips64r6) {
+ n = m.Float64Sub(p0, m.Float64Mul(p1, p2));
+ }
+ m.Return(n);
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ if (kArchVariant == kMips64r2) {
+ EXPECT_EQ(kMips64MsubD, s[0]->arch_opcode());
+ } else if (kArchVariant == kMips64r6) {
+ EXPECT_EQ(kMips64MsubfD, s[0]->arch_opcode());
+ }
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ if (kArchVariant == kMips64r2) {
+ EXPECT_FALSE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ } else if (kArchVariant == kMips64r6) {
+ EXPECT_TRUE(
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy());
+ }
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode());
+}
TEST_F(InstructionSelectorTest, Float64Max) {
StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(),
diff --git a/deps/v8/test/unittests/compiler/node-test-utils.cc b/deps/v8/test/unittests/compiler/node-test-utils.cc
index 5620b8bec1..3a5b2c3aeb 100644
--- a/deps/v8/test/unittests/compiler/node-test-utils.cc
+++ b/deps/v8/test/unittests/compiler/node-test-utils.cc
@@ -406,6 +406,35 @@ class IsTerminateMatcher final : public NodeMatcher {
const Matcher<Node*> control_matcher_;
};
+class IsTypeGuardMatcher final : public NodeMatcher {
+ public:
+ IsTypeGuardMatcher(const Matcher<Node*>& value_matcher,
+ const Matcher<Node*>& control_matcher)
+ : NodeMatcher(IrOpcode::kTypeGuard),
+ value_matcher_(value_matcher),
+ control_matcher_(control_matcher) {}
+
+ void DescribeTo(std::ostream* os) const final {
+ NodeMatcher::DescribeTo(os);
+ *os << " whose value (";
+ value_matcher_.DescribeTo(os);
+ *os << ") and control (";
+ control_matcher_.DescribeTo(os);
+ *os << ")";
+ }
+
+ bool MatchAndExplain(Node* node, MatchResultListener* listener) const final {
+ return (NodeMatcher::MatchAndExplain(node, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0),
+ "value", value_matcher_, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetControlInput(node),
+ "control", control_matcher_, listener));
+ }
+
+ private:
+ const Matcher<Node*> value_matcher_;
+ const Matcher<Node*> control_matcher_;
+};
template <typename T>
class IsConstantMatcher final : public NodeMatcher {
@@ -1714,6 +1743,10 @@ Matcher<Node*> IsTerminate(const Matcher<Node*>& effect_matcher,
return MakeMatcher(new IsTerminateMatcher(effect_matcher, control_matcher));
}
+Matcher<Node*> IsTypeGuard(const Matcher<Node*>& value_matcher,
+ const Matcher<Node*>& control_matcher) {
+ return MakeMatcher(new IsTypeGuardMatcher(value_matcher, control_matcher));
+}
Matcher<Node*> IsExternalConstant(
const Matcher<ExternalReference>& value_matcher) {
@@ -2274,7 +2307,9 @@ IS_BINOP_MATCHER(Float32LessThan)
IS_BINOP_MATCHER(Float32LessThanOrEqual)
IS_BINOP_MATCHER(Float64Max)
IS_BINOP_MATCHER(Float64Min)
+IS_BINOP_MATCHER(Float64Add)
IS_BINOP_MATCHER(Float64Sub)
+IS_BINOP_MATCHER(Float64Mul)
IS_BINOP_MATCHER(Float64InsertLowWord32)
IS_BINOP_MATCHER(Float64InsertHighWord32)
#undef IS_BINOP_MATCHER
@@ -2285,6 +2320,9 @@ IS_BINOP_MATCHER(Float64InsertHighWord32)
return MakeMatcher(new IsUnopMatcher(IrOpcode::k##Name, input_matcher)); \
}
IS_UNOP_MATCHER(BooleanNot)
+IS_UNOP_MATCHER(BitcastTaggedToWord)
+IS_UNOP_MATCHER(BitcastWordToTagged)
+IS_UNOP_MATCHER(BitcastWordToTaggedSigned)
IS_UNOP_MATCHER(TruncateFloat64ToWord32)
IS_UNOP_MATCHER(ChangeFloat64ToInt32)
IS_UNOP_MATCHER(ChangeFloat64ToUint32)
@@ -2332,6 +2370,7 @@ IS_UNOP_MATCHER(NumberSqrt)
IS_UNOP_MATCHER(NumberTan)
IS_UNOP_MATCHER(NumberTanh)
IS_UNOP_MATCHER(NumberTrunc)
+IS_UNOP_MATCHER(NumberToBoolean)
IS_UNOP_MATCHER(NumberToInt32)
IS_UNOP_MATCHER(NumberToUint32)
IS_UNOP_MATCHER(PlainPrimitiveToNumber)
diff --git a/deps/v8/test/unittests/compiler/node-test-utils.h b/deps/v8/test/unittests/compiler/node-test-utils.h
index 2a24803380..3afe2adf14 100644
--- a/deps/v8/test/unittests/compiler/node-test-utils.h
+++ b/deps/v8/test/unittests/compiler/node-test-utils.h
@@ -83,6 +83,8 @@ Matcher<Node*> IsReturn2(const Matcher<Node*>& value_matcher,
const Matcher<Node*>& control_matcher);
Matcher<Node*> IsTerminate(const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher);
+Matcher<Node*> IsTypeGuard(const Matcher<Node*>& value_matcher,
+ const Matcher<Node*>& control_matcher);
Matcher<Node*> IsExternalConstant(
const Matcher<ExternalReference>& value_matcher);
Matcher<Node*> IsHeapConstant(Handle<HeapObject> value);
@@ -384,6 +386,9 @@ Matcher<Node*> IsInt64Sub(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsJSAdd(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsBitcastTaggedToWord(const Matcher<Node*>& input_matcher);
+Matcher<Node*> IsBitcastWordToTagged(const Matcher<Node*>& input_matcher);
+Matcher<Node*> IsBitcastWordToTaggedSigned(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsTruncateFloat64ToWord32(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsChangeFloat64ToInt32(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsChangeFloat64ToUint32(const Matcher<Node*>& input_matcher);
@@ -405,8 +410,12 @@ Matcher<Node*> IsFloat64Max(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsFloat64Min(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsFloat64Add(const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsFloat64Sub(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsFloat64Mul(const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsFloat64Abs(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsFloat64Neg(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsFloat64Sqrt(const Matcher<Node*>& input_matcher);
@@ -425,6 +434,7 @@ Matcher<Node*> IsToNumber(const Matcher<Node*>& base_matcher,
const Matcher<Node*>& control_matcher);
Matcher<Node*> IsLoadContext(const Matcher<ContextAccess>& access_matcher,
const Matcher<Node*>& context_matcher);
+Matcher<Node*> IsNumberToBoolean(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsNumberToInt32(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsNumberToUint32(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsParameter(const Matcher<int> index_matcher);
diff --git a/deps/v8/test/unittests/compiler/opcodes-unittest.cc b/deps/v8/test/unittests/compiler/opcodes-unittest.cc
index 3bb65c2e13..a0e67ecb27 100644
--- a/deps/v8/test/unittests/compiler/opcodes-unittest.cc
+++ b/deps/v8/test/unittests/compiler/opcodes-unittest.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "src/compiler/opcodes.h"
-#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gtest-support.h"
namespace v8 {
namespace internal {
@@ -81,65 +81,60 @@ bool IsComparisonOpcode(IrOpcode::Value opcode) {
const IrOpcode::Value kInvalidOpcode = static_cast<IrOpcode::Value>(123456789);
-} // namespace
+char const* const kMnemonics[] = {
+#define OPCODE(Opcode) #Opcode,
+ ALL_OP_LIST(OPCODE)
+#undef OPCODE
+};
+
+const IrOpcode::Value kOpcodes[] = {
+#define OPCODE(Opcode) IrOpcode::k##Opcode,
+ ALL_OP_LIST(OPCODE)
+#undef OPCODE
+};
+} // namespace
TEST(IrOpcodeTest, IsCommonOpcode) {
EXPECT_FALSE(IrOpcode::IsCommonOpcode(kInvalidOpcode));
-#define OPCODE(Opcode) \
- EXPECT_EQ(IsCommonOpcode(IrOpcode::k##Opcode), \
- IrOpcode::IsCommonOpcode(IrOpcode::k##Opcode));
- ALL_OP_LIST(OPCODE)
-#undef OPCODE
+ TRACED_FOREACH(IrOpcode::Value, opcode, kOpcodes) {
+ EXPECT_EQ(IsCommonOpcode(opcode), IrOpcode::IsCommonOpcode(opcode));
+ }
}
-
TEST(IrOpcodeTest, IsControlOpcode) {
EXPECT_FALSE(IrOpcode::IsControlOpcode(kInvalidOpcode));
-#define OPCODE(Opcode) \
- EXPECT_EQ(IsControlOpcode(IrOpcode::k##Opcode), \
- IrOpcode::IsControlOpcode(IrOpcode::k##Opcode));
- ALL_OP_LIST(OPCODE)
-#undef OPCODE
+ TRACED_FOREACH(IrOpcode::Value, opcode, kOpcodes) {
+ EXPECT_EQ(IsControlOpcode(opcode), IrOpcode::IsControlOpcode(opcode));
+ }
}
-
TEST(IrOpcodeTest, IsJsOpcode) {
EXPECT_FALSE(IrOpcode::IsJsOpcode(kInvalidOpcode));
-#define OPCODE(Opcode) \
- EXPECT_EQ(IsJsOpcode(IrOpcode::k##Opcode), \
- IrOpcode::IsJsOpcode(IrOpcode::k##Opcode));
- ALL_OP_LIST(OPCODE)
-#undef OPCODE
+ TRACED_FOREACH(IrOpcode::Value, opcode, kOpcodes) {
+ EXPECT_EQ(IsJsOpcode(opcode), IrOpcode::IsJsOpcode(opcode));
+ }
}
-
TEST(IrOpcodeTest, IsConstantOpcode) {
EXPECT_FALSE(IrOpcode::IsConstantOpcode(kInvalidOpcode));
-#define OPCODE(Opcode) \
- EXPECT_EQ(IsConstantOpcode(IrOpcode::k##Opcode), \
- IrOpcode::IsConstantOpcode(IrOpcode::k##Opcode));
- ALL_OP_LIST(OPCODE)
-#undef OPCODE
+ TRACED_FOREACH(IrOpcode::Value, opcode, kOpcodes) {
+ EXPECT_EQ(IsConstantOpcode(opcode), IrOpcode::IsConstantOpcode(opcode));
+ }
}
-
TEST(IrOpcodeTest, IsComparisonOpcode) {
EXPECT_FALSE(IrOpcode::IsComparisonOpcode(kInvalidOpcode));
-#define OPCODE(Opcode) \
- EXPECT_EQ(IsComparisonOpcode(IrOpcode::k##Opcode), \
- IrOpcode::IsComparisonOpcode(IrOpcode::k##Opcode));
- ALL_OP_LIST(OPCODE)
-#undef OPCODE
+ TRACED_FOREACH(IrOpcode::Value, opcode, kOpcodes) {
+ EXPECT_EQ(IsComparisonOpcode(opcode), IrOpcode::IsComparisonOpcode(opcode));
+ }
}
-
TEST(IrOpcodeTest, Mnemonic) {
EXPECT_STREQ("UnknownOpcode", IrOpcode::Mnemonic(kInvalidOpcode));
-#define OPCODE(Opcode) \
- EXPECT_STREQ(#Opcode, IrOpcode::Mnemonic(IrOpcode::k##Opcode));
- ALL_OP_LIST(OPCODE)
-#undef OPCODE
+ TRACED_FOREACH(IrOpcode::Value, opcode, kOpcodes) {
+ EXPECT_STREQ(kMnemonics[opcode], IrOpcode::Mnemonic(opcode));
+ }
}
} // namespace compiler
diff --git a/deps/v8/test/unittests/compiler/simplified-operator-reducer-unittest.cc b/deps/v8/test/unittests/compiler/simplified-operator-reducer-unittest.cc
index b21a148718..6f37609f3a 100644
--- a/deps/v8/test/unittests/compiler/simplified-operator-reducer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/simplified-operator-reducer-unittest.cc
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "src/compiler/simplified-operator.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/node-properties.h"
-#include "src/compiler/simplified-operator.h"
#include "src/compiler/simplified-operator-reducer.h"
+#include "src/compiler/types.h"
#include "src/conversions-inl.h"
-#include "src/types.h"
#include "test/unittests/compiler/graph-unittest.h"
#include "test/unittests/compiler/node-test-utils.h"
#include "testing/gmock-support.h"
@@ -97,10 +97,6 @@ const double kNaNs[] = {-std::numeric_limits<double>::quiet_NaN(),
bit_cast<double>(V8_UINT64_C(0x7FFFFFFFFFFFFFFF)),
bit_cast<double>(V8_UINT64_C(0xFFFFFFFFFFFFFFFF))};
-const CheckForMinusZeroMode kCheckForMinusZeroModes[] = {
- CheckForMinusZeroMode::kDontCheckForMinusZero,
- CheckForMinusZeroMode::kCheckForMinusZero};
-
} // namespace
@@ -191,13 +187,11 @@ TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToBitWithChangeBitToTagged) {
// ChangeFloat64ToTagged
TEST_F(SimplifiedOperatorReducerTest, ChangeFloat64ToTaggedWithConstant) {
- TRACED_FOREACH(CheckForMinusZeroMode, mode, kCheckForMinusZeroModes) {
- TRACED_FOREACH(double, n, kFloat64Values) {
- Reduction reduction = Reduce(graph()->NewNode(
- simplified()->ChangeFloat64ToTagged(mode), Float64Constant(n)));
- ASSERT_TRUE(reduction.Changed());
- EXPECT_THAT(reduction.replacement(), IsNumberConstant(BitEq(n)));
- }
+ TRACED_FOREACH(double, n, kFloat64Values) {
+ Reduction reduction = Reduce(graph()->NewNode(
+ simplified()->ChangeFloat64ToTagged(), Float64Constant(n)));
+ ASSERT_TRUE(reduction.Changed());
+ EXPECT_THAT(reduction.replacement(), IsNumberConstant(BitEq(n)));
}
}
@@ -222,13 +216,11 @@ TEST_F(SimplifiedOperatorReducerTest, ChangeInt32ToTaggedWithConstant) {
TEST_F(SimplifiedOperatorReducerTest,
ChangeTaggedToFloat64WithChangeFloat64ToTagged) {
Node* param0 = Parameter(0);
- TRACED_FOREACH(CheckForMinusZeroMode, mode, kCheckForMinusZeroModes) {
- Reduction reduction = Reduce(graph()->NewNode(
- simplified()->ChangeTaggedToFloat64(),
- graph()->NewNode(simplified()->ChangeFloat64ToTagged(mode), param0)));
- ASSERT_TRUE(reduction.Changed());
- EXPECT_EQ(param0, reduction.replacement());
- }
+ Reduction reduction = Reduce(graph()->NewNode(
+ simplified()->ChangeTaggedToFloat64(),
+ graph()->NewNode(simplified()->ChangeFloat64ToTagged(), param0)));
+ ASSERT_TRUE(reduction.Changed());
+ EXPECT_EQ(param0, reduction.replacement());
}
TEST_F(SimplifiedOperatorReducerTest,
@@ -279,13 +271,11 @@ TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToFloat64WithNaNConstant) {
TEST_F(SimplifiedOperatorReducerTest,
ChangeTaggedToInt32WithChangeFloat64ToTagged) {
Node* param0 = Parameter(0);
- TRACED_FOREACH(CheckForMinusZeroMode, mode, kCheckForMinusZeroModes) {
- Reduction reduction = Reduce(graph()->NewNode(
- simplified()->ChangeTaggedToInt32(),
- graph()->NewNode(simplified()->ChangeFloat64ToTagged(mode), param0)));
- ASSERT_TRUE(reduction.Changed());
- EXPECT_THAT(reduction.replacement(), IsChangeFloat64ToInt32(param0));
- }
+ Reduction reduction = Reduce(graph()->NewNode(
+ simplified()->ChangeTaggedToInt32(),
+ graph()->NewNode(simplified()->ChangeFloat64ToTagged(), param0)));
+ ASSERT_TRUE(reduction.Changed());
+ EXPECT_THAT(reduction.replacement(), IsChangeFloat64ToInt32(param0));
}
TEST_F(SimplifiedOperatorReducerTest,
@@ -305,13 +295,11 @@ TEST_F(SimplifiedOperatorReducerTest,
TEST_F(SimplifiedOperatorReducerTest,
ChangeTaggedToUint32WithChangeFloat64ToTagged) {
Node* param0 = Parameter(0);
- TRACED_FOREACH(CheckForMinusZeroMode, mode, kCheckForMinusZeroModes) {
- Reduction reduction = Reduce(graph()->NewNode(
- simplified()->ChangeTaggedToUint32(),
- graph()->NewNode(simplified()->ChangeFloat64ToTagged(mode), param0)));
- ASSERT_TRUE(reduction.Changed());
- EXPECT_THAT(reduction.replacement(), IsChangeFloat64ToUint32(param0));
- }
+ Reduction reduction = Reduce(graph()->NewNode(
+ simplified()->ChangeTaggedToUint32(),
+ graph()->NewNode(simplified()->ChangeFloat64ToTagged(), param0)));
+ ASSERT_TRUE(reduction.Changed());
+ EXPECT_THAT(reduction.replacement(), IsChangeFloat64ToUint32(param0));
}
TEST_F(SimplifiedOperatorReducerTest,
@@ -331,13 +319,11 @@ TEST_F(SimplifiedOperatorReducerTest,
TEST_F(SimplifiedOperatorReducerTest,
TruncateTaggedToWord3WithChangeFloat64ToTagged) {
Node* param0 = Parameter(0);
- TRACED_FOREACH(CheckForMinusZeroMode, mode, kCheckForMinusZeroModes) {
- Reduction reduction = Reduce(graph()->NewNode(
- simplified()->TruncateTaggedToWord32(),
- graph()->NewNode(simplified()->ChangeFloat64ToTagged(mode), param0)));
- ASSERT_TRUE(reduction.Changed());
- EXPECT_THAT(reduction.replacement(), IsTruncateFloat64ToWord32(param0));
- }
+ Reduction reduction = Reduce(graph()->NewNode(
+ simplified()->TruncateTaggedToWord32(),
+ graph()->NewNode(simplified()->ChangeFloat64ToTagged(), param0)));
+ ASSERT_TRUE(reduction.Changed());
+ EXPECT_THAT(reduction.replacement(), IsTruncateFloat64ToWord32(param0));
}
TEST_F(SimplifiedOperatorReducerTest, TruncateTaggedToWord32WithConstant) {
@@ -350,20 +336,20 @@ TEST_F(SimplifiedOperatorReducerTest, TruncateTaggedToWord32WithConstant) {
}
// -----------------------------------------------------------------------------
-// CheckTaggedPointer
+// CheckHeapObject
-TEST_F(SimplifiedOperatorReducerTest, CheckTaggedPointerWithChangeBitToTagged) {
+TEST_F(SimplifiedOperatorReducerTest, CheckHeapObjectWithChangeBitToTagged) {
Node* param0 = Parameter(0);
Node* effect = graph()->start();
Node* control = graph()->start();
Node* value = graph()->NewNode(simplified()->ChangeBitToTagged(), param0);
- Reduction reduction = Reduce(graph()->NewNode(
- simplified()->CheckTaggedPointer(), value, effect, control));
+ Reduction reduction = Reduce(graph()->NewNode(simplified()->CheckHeapObject(),
+ value, effect, control));
ASSERT_TRUE(reduction.Changed());
EXPECT_EQ(value, reduction.replacement());
}
-TEST_F(SimplifiedOperatorReducerTest, CheckTaggedPointerWithHeapConstant) {
+TEST_F(SimplifiedOperatorReducerTest, CheckHeapObjectWithHeapConstant) {
Node* effect = graph()->start();
Node* control = graph()->start();
Handle<HeapObject> kHeapObjects[] = {
@@ -372,34 +358,57 @@ TEST_F(SimplifiedOperatorReducerTest, CheckTaggedPointerWithHeapConstant) {
TRACED_FOREACH(Handle<HeapObject>, object, kHeapObjects) {
Node* value = HeapConstant(object);
Reduction reduction = Reduce(graph()->NewNode(
- simplified()->CheckTaggedPointer(), value, effect, control));
+ simplified()->CheckHeapObject(), value, effect, control));
ASSERT_TRUE(reduction.Changed());
EXPECT_EQ(value, reduction.replacement());
}
}
+TEST_F(SimplifiedOperatorReducerTest, CheckHeapObjectWithCheckHeapObject) {
+ Node* param0 = Parameter(0);
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ Node* value = effect = graph()->NewNode(simplified()->CheckHeapObject(),
+ param0, effect, control);
+ Reduction reduction = Reduce(graph()->NewNode(simplified()->CheckHeapObject(),
+ value, effect, control));
+ ASSERT_TRUE(reduction.Changed());
+ EXPECT_EQ(value, reduction.replacement());
+}
+
// -----------------------------------------------------------------------------
-// CheckTaggedSigned
+// CheckSmi
-TEST_F(SimplifiedOperatorReducerTest,
- CheckTaggedSignedWithChangeInt31ToTaggedSigned) {
+TEST_F(SimplifiedOperatorReducerTest, CheckSmiWithChangeInt31ToTaggedSigned) {
Node* param0 = Parameter(0);
Node* effect = graph()->start();
Node* control = graph()->start();
Node* value =
graph()->NewNode(simplified()->ChangeInt31ToTaggedSigned(), param0);
- Reduction reduction = Reduce(graph()->NewNode(
- simplified()->CheckTaggedSigned(), value, effect, control));
+ Reduction reduction = Reduce(
+ graph()->NewNode(simplified()->CheckSmi(), value, effect, control));
ASSERT_TRUE(reduction.Changed());
EXPECT_EQ(value, reduction.replacement());
}
-TEST_F(SimplifiedOperatorReducerTest, CheckTaggedSignedWithNumberConstant) {
+TEST_F(SimplifiedOperatorReducerTest, CheckSmiWithNumberConstant) {
Node* effect = graph()->start();
Node* control = graph()->start();
Node* value = NumberConstant(1.0);
- Reduction reduction = Reduce(graph()->NewNode(
- simplified()->CheckTaggedSigned(), value, effect, control));
+ Reduction reduction = Reduce(
+ graph()->NewNode(simplified()->CheckSmi(), value, effect, control));
+ ASSERT_TRUE(reduction.Changed());
+ EXPECT_EQ(value, reduction.replacement());
+}
+
+TEST_F(SimplifiedOperatorReducerTest, CheckSmiWithCheckSmi) {
+ Node* param0 = Parameter(0);
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+ Node* value = effect =
+ graph()->NewNode(simplified()->CheckSmi(), param0, effect, control);
+ Reduction reduction = Reduce(
+ graph()->NewNode(simplified()->CheckSmi(), value, effect, control));
ASSERT_TRUE(reduction.Changed());
EXPECT_EQ(value, reduction.replacement());
}
diff --git a/deps/v8/test/unittests/compiler/simplified-operator-unittest.cc b/deps/v8/test/unittests/compiler/simplified-operator-unittest.cc
index febd76a528..d32dcaec12 100644
--- a/deps/v8/test/unittests/compiler/simplified-operator-unittest.cc
+++ b/deps/v8/test/unittests/compiler/simplified-operator-unittest.cc
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "src/compiler/simplified-operator.h"
#include "src/compiler/opcodes.h"
-#include "src/compiler/operator.h"
#include "src/compiler/operator-properties.h"
-#include "src/compiler/simplified-operator.h"
-#include "src/types.h"
+#include "src/compiler/operator.h"
+#include "src/compiler/types.h"
#include "test/unittests/test-utils.h"
namespace v8 {
@@ -63,6 +63,8 @@ const PureOperator kPureOperators[] = {
PURE(ChangeTaggedToBit, Operator::kNoProperties, 1),
PURE(ChangeBitToTagged, Operator::kNoProperties, 1),
PURE(TruncateTaggedToWord32, Operator::kNoProperties, 1),
+ PURE(TruncateTaggedToFloat64, Operator::kNoProperties, 1),
+ PURE(TruncateTaggedToBit, Operator::kNoProperties, 1),
PURE(ObjectIsNumber, Operator::kNoProperties, 1),
PURE(ObjectIsReceiver, Operator::kNoProperties, 1),
PURE(ObjectIsSmi, Operator::kNoProperties, 1)
diff --git a/deps/v8/test/unittests/compiler/typed-optimization-unittest.cc b/deps/v8/test/unittests/compiler/typed-optimization-unittest.cc
new file mode 100644
index 0000000000..d73c72d4e0
--- /dev/null
+++ b/deps/v8/test/unittests/compiler/typed-optimization-unittest.cc
@@ -0,0 +1,226 @@
+// Copyright 2016 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.
+
+#include "src/compiler/typed-optimization.h"
+#include "src/code-factory.h"
+#include "src/compilation-dependencies.h"
+#include "src/compiler/access-builder.h"
+#include "src/compiler/js-graph.h"
+#include "src/compiler/js-operator.h"
+#include "src/compiler/machine-operator.h"
+#include "src/compiler/node-properties.h"
+#include "src/compiler/operator-properties.h"
+#include "src/isolate-inl.h"
+#include "test/unittests/compiler/compiler-test-utils.h"
+#include "test/unittests/compiler/graph-unittest.h"
+#include "test/unittests/compiler/node-test-utils.h"
+#include "testing/gmock-support.h"
+
+using testing::IsNaN;
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+namespace {
+
+const double kFloat64Values[] = {
+ -V8_INFINITY, -4.23878e+275, -5.82632e+265, -6.60355e+220,
+ -6.26172e+212, -2.56222e+211, -4.82408e+201, -1.84106e+157,
+ -1.63662e+127, -1.55772e+100, -1.67813e+72, -2.3382e+55,
+ -3.179e+30, -1.441e+09, -1.0647e+09, -7.99361e+08,
+ -5.77375e+08, -2.20984e+08, -32757, -13171,
+ -9970, -3984, -107, -105,
+ -92, -77, -61, -0.000208163,
+ -1.86685e-06, -1.17296e-10, -9.26358e-11, -5.08004e-60,
+ -1.74753e-65, -1.06561e-71, -5.67879e-79, -5.78459e-130,
+ -2.90989e-171, -7.15489e-243, -3.76242e-252, -1.05639e-263,
+ -4.40497e-267, -2.19666e-273, -4.9998e-276, -5.59821e-278,
+ -2.03855e-282, -5.99335e-283, -7.17554e-284, -3.11744e-309,
+ -0.0, 0.0, 2.22507e-308, 1.30127e-270,
+ 7.62898e-260, 4.00313e-249, 3.16829e-233, 1.85244e-228,
+ 2.03544e-129, 1.35126e-110, 1.01182e-106, 5.26333e-94,
+ 1.35292e-90, 2.85394e-83, 1.78323e-77, 5.4967e-57,
+ 1.03207e-25, 4.57401e-25, 1.58738e-05, 2,
+ 125, 2310, 9636, 14802,
+ 17168, 28945, 29305, 4.81336e+07,
+ 1.41207e+08, 4.65962e+08, 1.40499e+09, 2.12648e+09,
+ 8.80006e+30, 1.4446e+45, 1.12164e+54, 2.48188e+89,
+ 6.71121e+102, 3.074e+112, 4.9699e+152, 5.58383e+166,
+ 4.30654e+172, 7.08824e+185, 9.6586e+214, 2.028e+223,
+ 6.63277e+243, 1.56192e+261, 1.23202e+269, 5.72883e+289,
+ 8.5798e+290, 1.40256e+294, 1.79769e+308, V8_INFINITY};
+
+const double kIntegerValues[] = {-V8_INFINITY, INT_MIN, -1000.0, -42.0,
+ -1.0, 0.0, 1.0, 42.0,
+ 1000.0, INT_MAX, UINT_MAX, V8_INFINITY};
+
+} // namespace
+
+class TypedOptimizationTest : public TypedGraphTest {
+ public:
+ TypedOptimizationTest()
+ : TypedGraphTest(3), javascript_(zone()), deps_(isolate(), zone()) {}
+ ~TypedOptimizationTest() override {}
+
+ protected:
+ Reduction Reduce(Node* node) {
+ MachineOperatorBuilder machine(zone());
+ SimplifiedOperatorBuilder simplified(zone());
+ JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified,
+ &machine);
+ // TODO(titzer): mock the GraphReducer here for better unit testing.
+ GraphReducer graph_reducer(zone(), graph());
+ TypedOptimization reducer(&graph_reducer, &deps_,
+ TypedOptimization::kDeoptimizationEnabled,
+ &jsgraph);
+ return reducer.Reduce(node);
+ }
+
+ JSOperatorBuilder* javascript() { return &javascript_; }
+
+ private:
+ JSOperatorBuilder javascript_;
+ CompilationDependencies deps_;
+};
+
+TEST_F(TypedOptimizationTest, ParameterWithMinusZero) {
+ {
+ Reduction r = Reduce(
+ Parameter(Type::Constant(factory()->minus_zero_value(), zone())));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsNumberConstant(-0.0));
+ }
+ {
+ Reduction r = Reduce(Parameter(Type::MinusZero()));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsNumberConstant(-0.0));
+ }
+ {
+ Reduction r = Reduce(Parameter(
+ Type::Union(Type::MinusZero(),
+ Type::Constant(factory()->NewNumber(0), zone()), zone())));
+ EXPECT_FALSE(r.Changed());
+ }
+}
+
+TEST_F(TypedOptimizationTest, ParameterWithNull) {
+ Handle<HeapObject> null = factory()->null_value();
+ {
+ Reduction r = Reduce(Parameter(Type::Constant(null, zone())));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsHeapConstant(null));
+ }
+ {
+ Reduction r = Reduce(Parameter(Type::Null()));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsHeapConstant(null));
+ }
+}
+
+TEST_F(TypedOptimizationTest, ParameterWithNaN) {
+ const double kNaNs[] = {-std::numeric_limits<double>::quiet_NaN(),
+ std::numeric_limits<double>::quiet_NaN(),
+ std::numeric_limits<double>::signaling_NaN()};
+ TRACED_FOREACH(double, nan, kNaNs) {
+ Handle<Object> constant = factory()->NewNumber(nan);
+ Reduction r = Reduce(Parameter(Type::Constant(constant, zone())));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN()));
+ }
+ {
+ Reduction r =
+ Reduce(Parameter(Type::Constant(factory()->nan_value(), zone())));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN()));
+ }
+ {
+ Reduction r = Reduce(Parameter(Type::NaN()));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN()));
+ }
+}
+
+TEST_F(TypedOptimizationTest, ParameterWithPlainNumber) {
+ TRACED_FOREACH(double, value, kFloat64Values) {
+ Handle<Object> constant = factory()->NewNumber(value);
+ Reduction r = Reduce(Parameter(Type::Constant(constant, zone())));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsNumberConstant(value));
+ }
+ TRACED_FOREACH(double, value, kIntegerValues) {
+ Reduction r = Reduce(Parameter(Type::Range(value, value, zone())));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsNumberConstant(value));
+ }
+}
+
+TEST_F(TypedOptimizationTest, ParameterWithUndefined) {
+ Handle<HeapObject> undefined = factory()->undefined_value();
+ {
+ Reduction r = Reduce(Parameter(Type::Undefined()));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsHeapConstant(undefined));
+ }
+ {
+ Reduction r = Reduce(Parameter(Type::Constant(undefined, zone())));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsHeapConstant(undefined));
+ }
+}
+
+TEST_F(TypedOptimizationTest, JSToBooleanWithFalsish) {
+ Node* input = Parameter(
+ Type::Union(
+ Type::MinusZero(),
+ Type::Union(
+ Type::NaN(),
+ Type::Union(
+ Type::Null(),
+ Type::Union(
+ Type::Undefined(),
+ Type::Union(
+ Type::Undetectable(),
+ Type::Union(
+ Type::Constant(factory()->false_value(), zone()),
+ Type::Range(0.0, 0.0, zone()), zone()),
+ zone()),
+ zone()),
+ zone()),
+ zone()),
+ zone()),
+ 0);
+ Node* context = Parameter(Type::Any(), 1);
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsFalseConstant());
+}
+
+TEST_F(TypedOptimizationTest, JSToBooleanWithTruish) {
+ Node* input = Parameter(
+ Type::Union(
+ Type::Constant(factory()->true_value(), zone()),
+ Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone()),
+ zone()),
+ 0);
+ Node* context = Parameter(Type::Any(), 1);
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsTrueConstant());
+}
+
+TEST_F(TypedOptimizationTest, JSToBooleanWithNonZeroPlainNumber) {
+ Node* input = Parameter(Type::Range(1, V8_INFINITY, zone()), 0);
+ Node* context = Parameter(Type::Any(), 1);
+ Reduction r = Reduce(graph()->NewNode(
+ javascript()->ToBoolean(ToBooleanHint::kAny), input, context));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(), IsTrueConstant());
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
diff --git a/deps/v8/test/unittests/compiler/zone-pool-unittest.cc b/deps/v8/test/unittests/compiler/zone-pool-unittest.cc
index 47f1cc5c75..5bbdbfd45d 100644
--- a/deps/v8/test/unittests/compiler/zone-pool-unittest.cc
+++ b/deps/v8/test/unittests/compiler/zone-pool-unittest.cc
@@ -38,7 +38,7 @@ class ZonePoolTest : public TestWithIsolate {
}
private:
- base::AccountingAllocator allocator_;
+ v8::internal::AccountingAllocator allocator_;
ZonePool zone_pool_;
base::RandomNumberGenerator rng;
};