8994347c35
We'll soon start collecting data from the JS heap prior to the typed lowering pass, and then refrain from reading the heap in that pass. This CL prepares the broker machinery by introducing a hash table that maps an object (handle) to the corresponding cached data. For the time being, that cached data is essentially just the handle itself. Bug: v8:7790 Change-Id: I830e9c72faafb7ae1d10e8a111636b3a3762bbc6 Reviewed-on: https://chromium-review.googlesource.com/1143405 Commit-Queue: Georg Neis <neis@chromium.org> Reviewed-by: Maya Lekova <mslekova@chromium.org> Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> Cr-Commit-Position: refs/heads/master@{#54618}
547 lines
20 KiB
C++
547 lines
20 KiB
C++
// Copyright 2014 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "src/compiler/common-operator.h"
|
|
#include "src/compiler/common-operator-reducer.h"
|
|
#include "src/compiler/machine-operator.h"
|
|
#include "src/compiler/operator.h"
|
|
#include "src/compiler/simplified-operator.h"
|
|
#include "src/machine-type.h"
|
|
#include "test/unittests/compiler/graph-reducer-unittest.h"
|
|
#include "test/unittests/compiler/graph-unittest.h"
|
|
#include "test/unittests/compiler/node-test-utils.h"
|
|
|
|
using testing::StrictMock;
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
namespace compiler {
|
|
namespace common_operator_reducer_unittest {
|
|
|
|
class CommonOperatorReducerTest : public GraphTest {
|
|
public:
|
|
explicit CommonOperatorReducerTest(int num_parameters = 1)
|
|
: GraphTest(num_parameters), machine_(zone()), simplified_(zone()) {}
|
|
~CommonOperatorReducerTest() override {}
|
|
|
|
protected:
|
|
Reduction Reduce(
|
|
AdvancedReducer::Editor* editor, Node* node,
|
|
MachineOperatorBuilder::Flags flags = MachineOperatorBuilder::kNoFlags) {
|
|
JSHeapBroker broker(isolate(), zone());
|
|
MachineOperatorBuilder machine(zone(), MachineType::PointerRepresentation(),
|
|
flags);
|
|
CommonOperatorReducer reducer(editor, graph(), &broker, common(), &machine,
|
|
zone());
|
|
return reducer.Reduce(node);
|
|
}
|
|
|
|
Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags =
|
|
MachineOperatorBuilder::kNoFlags) {
|
|
StrictMock<MockAdvancedReducerEditor> editor;
|
|
return Reduce(&editor, node, flags);
|
|
}
|
|
|
|
MachineOperatorBuilder* machine() { return &machine_; }
|
|
SimplifiedOperatorBuilder* simplified() { return &simplified_; }
|
|
|
|
private:
|
|
MachineOperatorBuilder machine_;
|
|
SimplifiedOperatorBuilder simplified_;
|
|
};
|
|
|
|
|
|
namespace {
|
|
|
|
const BranchHint kBranchHints[] = {BranchHint::kNone, BranchHint::kFalse,
|
|
BranchHint::kTrue};
|
|
|
|
|
|
const MachineRepresentation kMachineRepresentations[] = {
|
|
MachineRepresentation::kBit, MachineRepresentation::kWord8,
|
|
MachineRepresentation::kWord16, MachineRepresentation::kWord32,
|
|
MachineRepresentation::kWord64, MachineRepresentation::kFloat32,
|
|
MachineRepresentation::kFloat64, MachineRepresentation::kTagged};
|
|
|
|
|
|
const Operator kOp0(0, Operator::kNoProperties, "Op0", 0, 0, 0, 1, 1, 0);
|
|
|
|
} // namespace
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Branch
|
|
|
|
|
|
TEST_F(CommonOperatorReducerTest, BranchWithInt32ZeroConstant) {
|
|
TRACED_FOREACH(BranchHint, hint, kBranchHints) {
|
|
Node* const control = graph()->start();
|
|
Node* const branch =
|
|
graph()->NewNode(common()->Branch(hint), Int32Constant(0), control);
|
|
Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
|
|
Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
|
|
StrictMock<MockAdvancedReducerEditor> editor;
|
|
EXPECT_CALL(editor, Replace(if_true, IsDead()));
|
|
EXPECT_CALL(editor, Replace(if_false, control));
|
|
Reduction const r = Reduce(&editor, branch);
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(r.replacement(), IsDead());
|
|
}
|
|
}
|
|
|
|
|
|
TEST_F(CommonOperatorReducerTest, BranchWithInt32OneConstant) {
|
|
TRACED_FOREACH(BranchHint, hint, kBranchHints) {
|
|
Node* const control = graph()->start();
|
|
Node* const branch =
|
|
graph()->NewNode(common()->Branch(hint), Int32Constant(1), control);
|
|
Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
|
|
Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
|
|
StrictMock<MockAdvancedReducerEditor> editor;
|
|
EXPECT_CALL(editor, Replace(if_true, control));
|
|
EXPECT_CALL(editor, Replace(if_false, IsDead()));
|
|
Reduction const r = Reduce(&editor, branch);
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(r.replacement(), IsDead());
|
|
}
|
|
}
|
|
|
|
|
|
TEST_F(CommonOperatorReducerTest, BranchWithFalseConstant) {
|
|
TRACED_FOREACH(BranchHint, hint, kBranchHints) {
|
|
Node* const control = graph()->start();
|
|
Node* const branch =
|
|
graph()->NewNode(common()->Branch(hint), FalseConstant(), control);
|
|
Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
|
|
Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
|
|
StrictMock<MockAdvancedReducerEditor> editor;
|
|
EXPECT_CALL(editor, Replace(if_true, IsDead()));
|
|
EXPECT_CALL(editor, Replace(if_false, control));
|
|
Reduction const r = Reduce(&editor, branch);
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(r.replacement(), IsDead());
|
|
}
|
|
}
|
|
|
|
|
|
TEST_F(CommonOperatorReducerTest, BranchWithTrueConstant) {
|
|
TRACED_FOREACH(BranchHint, hint, kBranchHints) {
|
|
Node* const control = graph()->start();
|
|
Node* const branch =
|
|
graph()->NewNode(common()->Branch(hint), TrueConstant(), control);
|
|
Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
|
|
Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
|
|
StrictMock<MockAdvancedReducerEditor> editor;
|
|
EXPECT_CALL(editor, Replace(if_true, control));
|
|
EXPECT_CALL(editor, Replace(if_false, IsDead()));
|
|
Reduction const r = Reduce(&editor, branch);
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(r.replacement(), IsDead());
|
|
}
|
|
}
|
|
|
|
|
|
TEST_F(CommonOperatorReducerTest, BranchWithBooleanNot) {
|
|
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(simplified()->BooleanNot(), value), 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()));
|
|
}
|
|
}
|
|
|
|
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
|
|
|
|
|
|
TEST_F(CommonOperatorReducerTest, MergeOfUnusedDiamond0) {
|
|
Node* const value = Parameter(0);
|
|
Node* const control = graph()->start();
|
|
Node* const branch = graph()->NewNode(common()->Branch(), value, control);
|
|
Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
|
|
Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
|
|
Reduction const r =
|
|
Reduce(graph()->NewNode(common()->Merge(2), if_true, if_false));
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_EQ(control, r.replacement());
|
|
EXPECT_THAT(branch, IsDead());
|
|
}
|
|
|
|
|
|
TEST_F(CommonOperatorReducerTest, MergeOfUnusedDiamond1) {
|
|
Node* const value = Parameter(0);
|
|
Node* const control = graph()->start();
|
|
Node* const branch = graph()->NewNode(common()->Branch(), value, control);
|
|
Node* const if_true = graph()->NewNode(common()->IfTrue(), branch);
|
|
Node* const if_false = graph()->NewNode(common()->IfFalse(), branch);
|
|
Reduction const r =
|
|
Reduce(graph()->NewNode(common()->Merge(2), if_false, if_true));
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_EQ(control, r.replacement());
|
|
EXPECT_THAT(branch, IsDead());
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// EffectPhi
|
|
|
|
|
|
TEST_F(CommonOperatorReducerTest, EffectPhiWithMerge) {
|
|
const int kMaxInputs = 64;
|
|
Node* inputs[kMaxInputs];
|
|
Node* const input = graph()->NewNode(&kOp0);
|
|
TRACED_FORRANGE(int, input_count, 2, kMaxInputs - 1) {
|
|
int const value_input_count = input_count - 1;
|
|
for (int i = 0; i < value_input_count; ++i) {
|
|
inputs[i] = graph()->start();
|
|
}
|
|
Node* const merge = graph()->NewNode(common()->Merge(value_input_count),
|
|
value_input_count, inputs);
|
|
for (int i = 0; i < value_input_count; ++i) {
|
|
inputs[i] = input;
|
|
}
|
|
inputs[value_input_count] = merge;
|
|
StrictMock<MockAdvancedReducerEditor> editor;
|
|
EXPECT_CALL(editor, Revisit(merge));
|
|
Reduction r =
|
|
Reduce(&editor, graph()->NewNode(common()->EffectPhi(value_input_count),
|
|
input_count, inputs));
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_EQ(input, r.replacement());
|
|
}
|
|
}
|
|
|
|
|
|
TEST_F(CommonOperatorReducerTest, EffectPhiWithLoop) {
|
|
Node* const e0 = graph()->NewNode(&kOp0);
|
|
Node* const loop =
|
|
graph()->NewNode(common()->Loop(2), graph()->start(), graph()->start());
|
|
loop->ReplaceInput(1, loop);
|
|
Node* const ephi = graph()->NewNode(common()->EffectPhi(2), e0, e0, loop);
|
|
ephi->ReplaceInput(1, ephi);
|
|
StrictMock<MockAdvancedReducerEditor> editor;
|
|
EXPECT_CALL(editor, Revisit(loop));
|
|
Reduction const r = Reduce(&editor, ephi);
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_EQ(e0, r.replacement());
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Phi
|
|
|
|
|
|
TEST_F(CommonOperatorReducerTest, PhiWithMerge) {
|
|
const int kMaxInputs = 64;
|
|
Node* inputs[kMaxInputs];
|
|
Node* const input = graph()->NewNode(&kOp0);
|
|
TRACED_FORRANGE(int, input_count, 2, kMaxInputs - 1) {
|
|
int const value_input_count = input_count - 1;
|
|
TRACED_FOREACH(MachineRepresentation, rep, kMachineRepresentations) {
|
|
for (int i = 0; i < value_input_count; ++i) {
|
|
inputs[i] = graph()->start();
|
|
}
|
|
Node* const merge = graph()->NewNode(common()->Merge(value_input_count),
|
|
value_input_count, inputs);
|
|
for (int i = 0; i < value_input_count; ++i) {
|
|
inputs[i] = input;
|
|
}
|
|
inputs[value_input_count] = merge;
|
|
StrictMock<MockAdvancedReducerEditor> editor;
|
|
EXPECT_CALL(editor, Revisit(merge));
|
|
Reduction r = Reduce(
|
|
&editor, graph()->NewNode(common()->Phi(rep, value_input_count),
|
|
input_count, inputs));
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_EQ(input, r.replacement());
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
TEST_F(CommonOperatorReducerTest, PhiWithLoop) {
|
|
Node* const p0 = Parameter(0);
|
|
Node* const loop =
|
|
graph()->NewNode(common()->Loop(2), graph()->start(), graph()->start());
|
|
loop->ReplaceInput(1, loop);
|
|
Node* const phi = graph()->NewNode(
|
|
common()->Phi(MachineRepresentation::kTagged, 2), p0, p0, loop);
|
|
phi->ReplaceInput(1, phi);
|
|
StrictMock<MockAdvancedReducerEditor> editor;
|
|
EXPECT_CALL(editor, Revisit(loop));
|
|
Reduction const r = Reduce(&editor, phi);
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_EQ(p0, r.replacement());
|
|
}
|
|
|
|
|
|
TEST_F(CommonOperatorReducerTest, PhiToFloat32Abs) {
|
|
Node* p0 = Parameter(0);
|
|
Node* c0 = Float32Constant(0.0);
|
|
Node* check = graph()->NewNode(machine()->Float32LessThan(), c0, p0);
|
|
Node* branch = graph()->NewNode(common()->Branch(), check, graph()->start());
|
|
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
|
|
Node* vtrue = p0;
|
|
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
|
|
Node* vfalse = graph()->NewNode(machine()->Float32Sub(), c0, p0);
|
|
Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
|
|
Node* phi = graph()->NewNode(
|
|
common()->Phi(MachineRepresentation::kFloat32, 2), vtrue, vfalse, merge);
|
|
StrictMock<MockAdvancedReducerEditor> editor;
|
|
EXPECT_CALL(editor, Revisit(merge));
|
|
Reduction r = Reduce(&editor, phi);
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(r.replacement(), IsFloat32Abs(p0));
|
|
}
|
|
|
|
|
|
TEST_F(CommonOperatorReducerTest, PhiToFloat64Abs) {
|
|
Node* p0 = Parameter(0);
|
|
Node* c0 = Float64Constant(0.0);
|
|
Node* check = graph()->NewNode(machine()->Float64LessThan(), c0, p0);
|
|
Node* branch = graph()->NewNode(common()->Branch(), check, graph()->start());
|
|
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
|
|
Node* vtrue = p0;
|
|
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
|
|
Node* vfalse = graph()->NewNode(machine()->Float64Sub(), c0, p0);
|
|
Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
|
|
Node* phi = graph()->NewNode(
|
|
common()->Phi(MachineRepresentation::kFloat64, 2), vtrue, vfalse, merge);
|
|
StrictMock<MockAdvancedReducerEditor> editor;
|
|
EXPECT_CALL(editor, Revisit(merge));
|
|
Reduction r = Reduce(&editor, phi);
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(r.replacement(), IsFloat64Abs(p0));
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Return
|
|
|
|
|
|
TEST_F(CommonOperatorReducerTest, ReturnWithPhiAndEffectPhiAndMerge) {
|
|
Node* cond = Parameter(2);
|
|
Node* branch = graph()->NewNode(common()->Branch(), cond, graph()->start());
|
|
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
|
|
Node* etrue = graph()->start();
|
|
Node* vtrue = Parameter(0);
|
|
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
|
|
Node* efalse = graph()->start();
|
|
Node* vfalse = Parameter(1);
|
|
Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
|
|
Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
|
|
Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
|
|
vtrue, vfalse, merge);
|
|
|
|
Node* zero = graph()->NewNode(common()->Int32Constant(0));
|
|
Node* ret = graph()->NewNode(common()->Return(), zero, phi, ephi, merge);
|
|
graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
|
|
StrictMock<MockAdvancedReducerEditor> editor;
|
|
EXPECT_CALL(editor, Replace(merge, IsDead()));
|
|
Reduction const r = Reduce(&editor, ret);
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(r.replacement(), IsDead());
|
|
EXPECT_THAT(graph()->end(), IsEnd(ret, IsReturn(vtrue, etrue, if_true),
|
|
IsReturn(vfalse, efalse, if_false)));
|
|
}
|
|
|
|
TEST_F(CommonOperatorReducerTest, MultiReturnWithPhiAndEffectPhiAndMerge) {
|
|
Node* cond = Parameter(2);
|
|
Node* branch = graph()->NewNode(common()->Branch(), cond, graph()->start());
|
|
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
|
|
Node* etrue = graph()->start();
|
|
Node* vtrue1 = Parameter(0);
|
|
Node* vtrue2 = Parameter(1);
|
|
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
|
|
Node* efalse = graph()->start();
|
|
Node* vfalse1 = Parameter(1);
|
|
Node* vfalse2 = Parameter(0);
|
|
Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
|
|
Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
|
|
Node* phi1 = graph()->NewNode(
|
|
common()->Phi(MachineRepresentation::kTagged, 2), vtrue1, vfalse1, merge);
|
|
Node* phi2 = graph()->NewNode(
|
|
common()->Phi(MachineRepresentation::kTagged, 2), vtrue2, vfalse2, merge);
|
|
|
|
Node* zero = graph()->NewNode(common()->Int32Constant(0));
|
|
Node* ret =
|
|
graph()->NewNode(common()->Return(2), zero, phi1, phi2, ephi, merge);
|
|
graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
|
|
StrictMock<MockAdvancedReducerEditor> editor;
|
|
Reduction const r = Reduce(&editor, ret);
|
|
// For now a return with multiple return values should not be reduced.
|
|
ASSERT_TRUE(!r.Changed());
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Select
|
|
|
|
|
|
TEST_F(CommonOperatorReducerTest, SelectWithSameThenAndElse) {
|
|
Node* const input = graph()->NewNode(&kOp0);
|
|
TRACED_FOREACH(BranchHint, hint, kBranchHints) {
|
|
TRACED_FOREACH(MachineRepresentation, rep, kMachineRepresentations) {
|
|
Reduction r = Reduce(
|
|
graph()->NewNode(common()->Select(rep, hint), input, input, input));
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_EQ(input, r.replacement());
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
TEST_F(CommonOperatorReducerTest, SelectWithInt32ZeroConstant) {
|
|
Node* p0 = Parameter(0);
|
|
Node* p1 = Parameter(1);
|
|
Node* select =
|
|
graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
|
|
Int32Constant(0), p0, p1);
|
|
Reduction r = Reduce(select);
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_EQ(p1, r.replacement());
|
|
}
|
|
|
|
|
|
TEST_F(CommonOperatorReducerTest, SelectWithInt32OneConstant) {
|
|
Node* p0 = Parameter(0);
|
|
Node* p1 = Parameter(1);
|
|
Node* select =
|
|
graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
|
|
Int32Constant(1), p0, p1);
|
|
Reduction r = Reduce(select);
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_EQ(p0, r.replacement());
|
|
}
|
|
|
|
|
|
TEST_F(CommonOperatorReducerTest, SelectWithFalseConstant) {
|
|
Node* p0 = Parameter(0);
|
|
Node* p1 = Parameter(1);
|
|
Node* select =
|
|
graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
|
|
FalseConstant(), p0, p1);
|
|
Reduction r = Reduce(select);
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_EQ(p1, r.replacement());
|
|
}
|
|
|
|
|
|
TEST_F(CommonOperatorReducerTest, SelectWithTrueConstant) {
|
|
Node* p0 = Parameter(0);
|
|
Node* p1 = Parameter(1);
|
|
Node* select = graph()->NewNode(
|
|
common()->Select(MachineRepresentation::kTagged), TrueConstant(), p0, p1);
|
|
Reduction r = Reduce(select);
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_EQ(p0, r.replacement());
|
|
}
|
|
|
|
|
|
TEST_F(CommonOperatorReducerTest, SelectToFloat32Abs) {
|
|
Node* p0 = Parameter(0);
|
|
Node* c0 = Float32Constant(0.0);
|
|
Node* check = graph()->NewNode(machine()->Float32LessThan(), c0, p0);
|
|
Node* select =
|
|
graph()->NewNode(common()->Select(MachineRepresentation::kFloat32), check,
|
|
p0, graph()->NewNode(machine()->Float32Sub(), c0, p0));
|
|
Reduction r = Reduce(select);
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(r.replacement(), IsFloat32Abs(p0));
|
|
}
|
|
|
|
|
|
TEST_F(CommonOperatorReducerTest, SelectToFloat64Abs) {
|
|
Node* p0 = Parameter(0);
|
|
Node* c0 = Float64Constant(0.0);
|
|
Node* check = graph()->NewNode(machine()->Float64LessThan(), c0, p0);
|
|
Node* select =
|
|
graph()->NewNode(common()->Select(MachineRepresentation::kFloat64), check,
|
|
p0, graph()->NewNode(machine()->Float64Sub(), c0, p0));
|
|
Reduction r = Reduce(select);
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(r.replacement(), IsFloat64Abs(p0));
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Switch
|
|
|
|
TEST_F(CommonOperatorReducerTest, SwitchInputMatchesCaseWithDefault) {
|
|
Node* const control = graph()->start();
|
|
|
|
Node* sw = graph()->NewNode(common()->Switch(2), Int32Constant(1), control);
|
|
Node* const if_1 = graph()->NewNode(common()->IfValue(1), sw);
|
|
graph()->NewNode(common()->IfDefault(), sw);
|
|
|
|
StrictMock<MockAdvancedReducerEditor> editor;
|
|
EXPECT_CALL(editor, Replace(if_1, control));
|
|
Reduction r = Reduce(&editor, sw);
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(r.replacement(), IsDead());
|
|
}
|
|
|
|
TEST_F(CommonOperatorReducerTest, SwitchInputMatchesDefaultWithCase) {
|
|
Node* const control = graph()->start();
|
|
|
|
Node* sw = graph()->NewNode(common()->Switch(2), Int32Constant(0), control);
|
|
graph()->NewNode(common()->IfValue(1), sw);
|
|
Node* const if_default = graph()->NewNode(common()->IfDefault(), sw);
|
|
|
|
StrictMock<MockAdvancedReducerEditor> editor;
|
|
EXPECT_CALL(editor, Replace(if_default, control));
|
|
Reduction r = Reduce(&editor, sw);
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(r.replacement(), IsDead());
|
|
}
|
|
|
|
TEST_F(CommonOperatorReducerTest, SwitchInputMatchesCaseExtraCaseWithDefault) {
|
|
Node* const control = graph()->start();
|
|
|
|
Node* sw = graph()->NewNode(common()->Switch(3), Int32Constant(0), control);
|
|
Node* const if_0 = graph()->NewNode(common()->IfValue(0), sw);
|
|
graph()->NewNode(common()->IfValue(1), sw);
|
|
graph()->NewNode(common()->IfDefault(), sw);
|
|
|
|
StrictMock<MockAdvancedReducerEditor> editor;
|
|
EXPECT_CALL(editor, Replace(if_0, control));
|
|
Reduction r = Reduce(&editor, sw);
|
|
ASSERT_TRUE(r.Changed());
|
|
EXPECT_THAT(r.replacement(), IsDead());
|
|
}
|
|
|
|
} // namespace common_operator_reducer_unittest
|
|
} // namespace compiler
|
|
} // namespace internal
|
|
} // namespace v8
|