2b873b94e9
This CL adds functionality to read the source positions directly from the JS heap rather than from serialized data. In order to do this, we create a PersistentHandles container in the OptimizedCompilationInfo which gets passed onto the JSHeapBroker. This allows us to create the handles in the main thread and pass them safely to the background thread. In order to read safely from the background thread, we need a LocalHeap which blocks the GC from running and potentially moving the handles. This LocalHeap is created only when the JSHeapBroker has finalized serializing and destroyed when retiring it. Bug: v8:7790 Change-Id: I19f8b08d12e5be0a3df34d6af2043310c0c7b6fe Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2277802 Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Dominik Inführ <dinfuehr@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Commit-Queue: Santiago Aboy Solanes <solanes@chromium.org> Cr-Commit-Position: refs/heads/master@{#68836}
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-reducer.h"
|
|
#include "src/codegen/machine-type.h"
|
|
#include "src/compiler/common-operator.h"
|
|
#include "src/compiler/machine-operator.h"
|
|
#include "src/compiler/operator.h"
|
|
#include "src/compiler/simplified-operator.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 = default;
|
|
|
|
protected:
|
|
Reduction Reduce(
|
|
AdvancedReducer::Editor* editor, Node* node,
|
|
MachineOperatorBuilder::Flags flags = MachineOperatorBuilder::kNoFlags) {
|
|
JSHeapBroker broker(isolate(), zone(), isolate()->NewPersistentHandles());
|
|
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
|