[turbofan] Introduce CommonOperatorReducer.
The CommonOperatorReducer currently takes care of redundant Phis, EffectPhis and Selects. This functionality overlaps with ControlReducer, but is required to make certain optimizations effective, since the ControlReducer only runs really early and really late in the pipeline and therefore other reducers aren't reapplied properly after redundant phi/select elimination. TEST=unittests R=hpayer@chromium.org Review URL: https://codereview.chromium.org/817243003 Cr-Commit-Position: refs/heads/master@{#25922}
This commit is contained in:
parent
096e1972cd
commit
ee98a1d760
2
BUILD.gn
2
BUILD.gn
@ -490,6 +490,8 @@ source_set("v8_base") {
|
|||||||
"src/compiler/code-generator.cc",
|
"src/compiler/code-generator.cc",
|
||||||
"src/compiler/code-generator.h",
|
"src/compiler/code-generator.h",
|
||||||
"src/compiler/common-node-cache.h",
|
"src/compiler/common-node-cache.h",
|
||||||
|
"src/compiler/common-operator-reducer.cc",
|
||||||
|
"src/compiler/common-operator-reducer.h",
|
||||||
"src/compiler/common-operator.cc",
|
"src/compiler/common-operator.cc",
|
||||||
"src/compiler/common-operator.h",
|
"src/compiler/common-operator.h",
|
||||||
"src/compiler/control-builders.cc",
|
"src/compiler/control-builders.cc",
|
||||||
|
41
src/compiler/common-operator-reducer.cc
Normal file
41
src/compiler/common-operator-reducer.cc
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// 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/compiler/common-operator.h"
|
||||||
|
|
||||||
|
namespace v8 {
|
||||||
|
namespace internal {
|
||||||
|
namespace compiler {
|
||||||
|
|
||||||
|
Reduction CommonOperatorReducer::Reduce(Node* node) {
|
||||||
|
switch (node->opcode()) {
|
||||||
|
case IrOpcode::kEffectPhi:
|
||||||
|
case IrOpcode::kPhi: {
|
||||||
|
int const input_count = node->InputCount();
|
||||||
|
if (input_count > 1) {
|
||||||
|
Node* const replacement = node->InputAt(0);
|
||||||
|
for (int i = 1; i < input_count - 1; ++i) {
|
||||||
|
if (node->InputAt(i) != replacement) return NoChange();
|
||||||
|
}
|
||||||
|
return Replace(replacement);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IrOpcode::kSelect: {
|
||||||
|
if (node->InputAt(1) == node->InputAt(2)) {
|
||||||
|
return Replace(node->InputAt(1));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return NoChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace v8
|
27
src/compiler/common-operator-reducer.h
Normal file
27
src/compiler/common-operator-reducer.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef V8_COMPILER_COMMON_OPERATOR_REDUCER_H_
|
||||||
|
#define V8_COMPILER_COMMON_OPERATOR_REDUCER_H_
|
||||||
|
|
||||||
|
#include "src/compiler/graph-reducer.h"
|
||||||
|
|
||||||
|
namespace v8 {
|
||||||
|
namespace internal {
|
||||||
|
namespace compiler {
|
||||||
|
|
||||||
|
// Performs strength reduction on nodes that have common operators.
|
||||||
|
class CommonOperatorReducer FINAL : public Reducer {
|
||||||
|
public:
|
||||||
|
CommonOperatorReducer() {}
|
||||||
|
~CommonOperatorReducer() FINAL {}
|
||||||
|
|
||||||
|
Reduction Reduce(Node* node) FINAL;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace v8
|
||||||
|
|
||||||
|
#endif // V8_COMPILER_COMMON_OPERATOR_REDUCER_H_
|
@ -13,6 +13,7 @@
|
|||||||
#include "src/compiler/basic-block-instrumentor.h"
|
#include "src/compiler/basic-block-instrumentor.h"
|
||||||
#include "src/compiler/change-lowering.h"
|
#include "src/compiler/change-lowering.h"
|
||||||
#include "src/compiler/code-generator.h"
|
#include "src/compiler/code-generator.h"
|
||||||
|
#include "src/compiler/common-operator-reducer.h"
|
||||||
#include "src/compiler/control-reducer.h"
|
#include "src/compiler/control-reducer.h"
|
||||||
#include "src/compiler/graph-replay.h"
|
#include "src/compiler/graph-replay.h"
|
||||||
#include "src/compiler/graph-visualizer.h"
|
#include "src/compiler/graph-visualizer.h"
|
||||||
@ -421,12 +422,14 @@ struct TypedLoweringPhase {
|
|||||||
JSBuiltinReducer builtin_reducer(data->jsgraph());
|
JSBuiltinReducer builtin_reducer(data->jsgraph());
|
||||||
JSTypedLowering typed_lowering(data->jsgraph(), temp_zone);
|
JSTypedLowering typed_lowering(data->jsgraph(), temp_zone);
|
||||||
SimplifiedOperatorReducer simple_reducer(data->jsgraph());
|
SimplifiedOperatorReducer simple_reducer(data->jsgraph());
|
||||||
|
CommonOperatorReducer common_reducer;
|
||||||
GraphReducer graph_reducer(data->graph(), temp_zone);
|
GraphReducer graph_reducer(data->graph(), temp_zone);
|
||||||
graph_reducer.AddReducer(&vn_reducer);
|
graph_reducer.AddReducer(&vn_reducer);
|
||||||
graph_reducer.AddReducer(&builtin_reducer);
|
graph_reducer.AddReducer(&builtin_reducer);
|
||||||
graph_reducer.AddReducer(&typed_lowering);
|
graph_reducer.AddReducer(&typed_lowering);
|
||||||
graph_reducer.AddReducer(&load_elimination);
|
graph_reducer.AddReducer(&load_elimination);
|
||||||
graph_reducer.AddReducer(&simple_reducer);
|
graph_reducer.AddReducer(&simple_reducer);
|
||||||
|
graph_reducer.AddReducer(&common_reducer);
|
||||||
graph_reducer.ReduceGraph();
|
graph_reducer.ReduceGraph();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -443,10 +446,12 @@ struct SimplifiedLoweringPhase {
|
|||||||
ValueNumberingReducer vn_reducer(temp_zone);
|
ValueNumberingReducer vn_reducer(temp_zone);
|
||||||
SimplifiedOperatorReducer simple_reducer(data->jsgraph());
|
SimplifiedOperatorReducer simple_reducer(data->jsgraph());
|
||||||
MachineOperatorReducer machine_reducer(data->jsgraph());
|
MachineOperatorReducer machine_reducer(data->jsgraph());
|
||||||
|
CommonOperatorReducer common_reducer;
|
||||||
GraphReducer graph_reducer(data->graph(), temp_zone);
|
GraphReducer graph_reducer(data->graph(), temp_zone);
|
||||||
graph_reducer.AddReducer(&vn_reducer);
|
graph_reducer.AddReducer(&vn_reducer);
|
||||||
graph_reducer.AddReducer(&simple_reducer);
|
graph_reducer.AddReducer(&simple_reducer);
|
||||||
graph_reducer.AddReducer(&machine_reducer);
|
graph_reducer.AddReducer(&machine_reducer);
|
||||||
|
graph_reducer.AddReducer(&common_reducer);
|
||||||
graph_reducer.ReduceGraph();
|
graph_reducer.ReduceGraph();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -463,11 +468,13 @@ struct ChangeLoweringPhase {
|
|||||||
SimplifiedOperatorReducer simple_reducer(data->jsgraph());
|
SimplifiedOperatorReducer simple_reducer(data->jsgraph());
|
||||||
ChangeLowering lowering(data->jsgraph(), &linkage);
|
ChangeLowering lowering(data->jsgraph(), &linkage);
|
||||||
MachineOperatorReducer machine_reducer(data->jsgraph());
|
MachineOperatorReducer machine_reducer(data->jsgraph());
|
||||||
|
CommonOperatorReducer common_reducer;
|
||||||
GraphReducer graph_reducer(data->graph(), temp_zone);
|
GraphReducer graph_reducer(data->graph(), temp_zone);
|
||||||
graph_reducer.AddReducer(&vn_reducer);
|
graph_reducer.AddReducer(&vn_reducer);
|
||||||
graph_reducer.AddReducer(&simple_reducer);
|
graph_reducer.AddReducer(&simple_reducer);
|
||||||
graph_reducer.AddReducer(&lowering);
|
graph_reducer.AddReducer(&lowering);
|
||||||
graph_reducer.AddReducer(&machine_reducer);
|
graph_reducer.AddReducer(&machine_reducer);
|
||||||
|
graph_reducer.AddReducer(&common_reducer);
|
||||||
graph_reducer.ReduceGraph();
|
graph_reducer.ReduceGraph();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
110
test/unittests/compiler/common-operator-reducer-unittest.cc
Normal file
110
test/unittests/compiler/common-operator-reducer-unittest.cc
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
// 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-type.h"
|
||||||
|
#include "test/unittests/compiler/graph-unittest.h"
|
||||||
|
|
||||||
|
namespace v8 {
|
||||||
|
namespace internal {
|
||||||
|
namespace compiler {
|
||||||
|
|
||||||
|
class CommonOperatorReducerTest : public GraphTest {
|
||||||
|
public:
|
||||||
|
explicit CommonOperatorReducerTest(int num_parameters = 1)
|
||||||
|
: GraphTest(num_parameters) {}
|
||||||
|
~CommonOperatorReducerTest() OVERRIDE {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Reduction Reduce(Node* node) {
|
||||||
|
CommonOperatorReducer reducer;
|
||||||
|
return reducer.Reduce(node);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const BranchHint kBranchHints[] = {BranchHint::kNone, BranchHint::kFalse,
|
||||||
|
BranchHint::kTrue};
|
||||||
|
|
||||||
|
|
||||||
|
const MachineType kMachineTypes[] = {
|
||||||
|
kMachFloat32, kMachFloat64, kMachInt8, kMachUint8, kMachInt16,
|
||||||
|
kMachUint16, kMachInt32, kMachUint32, kMachInt64, kMachUint64,
|
||||||
|
kMachPtr, kMachAnyTagged, kRepBit, kRepWord8, kRepWord16,
|
||||||
|
kRepWord32, kRepWord64, kRepFloat32, kRepFloat64, kRepTagged};
|
||||||
|
|
||||||
|
|
||||||
|
const Operator kOp0(0, Operator::kNoProperties, "Op0", 0, 0, 0, 1, 1, 0);
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// EffectPhi
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(CommonOperatorReducerTest, RedundantEffectPhi) {
|
||||||
|
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] = input;
|
||||||
|
}
|
||||||
|
inputs[value_input_count] = graph()->start();
|
||||||
|
Reduction r = Reduce(graph()->NewNode(
|
||||||
|
common()->EffectPhi(value_input_count), input_count, inputs));
|
||||||
|
ASSERT_TRUE(r.Changed());
|
||||||
|
EXPECT_EQ(input, r.replacement());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Phi
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(CommonOperatorReducerTest, RedundantPhi) {
|
||||||
|
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(MachineType, type, kMachineTypes) {
|
||||||
|
for (int i = 0; i < value_input_count; ++i) {
|
||||||
|
inputs[i] = input;
|
||||||
|
}
|
||||||
|
inputs[value_input_count] = graph()->start();
|
||||||
|
Reduction r = Reduce(graph()->NewNode(
|
||||||
|
common()->Phi(type, value_input_count), input_count, inputs));
|
||||||
|
ASSERT_TRUE(r.Changed());
|
||||||
|
EXPECT_EQ(input, r.replacement());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Select
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(CommonOperatorReducerTest, RedundantSelect) {
|
||||||
|
Node* const input = graph()->NewNode(&kOp0);
|
||||||
|
TRACED_FOREACH(BranchHint, hint, kBranchHints) {
|
||||||
|
TRACED_FOREACH(MachineType, type, kMachineTypes) {
|
||||||
|
Reduction r = Reduce(
|
||||||
|
graph()->NewNode(common()->Select(type, hint), input, input, input));
|
||||||
|
ASSERT_TRUE(r.Changed());
|
||||||
|
EXPECT_EQ(input, r.replacement());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace v8
|
@ -38,6 +38,7 @@
|
|||||||
'base/utils/random-number-generator-unittest.cc',
|
'base/utils/random-number-generator-unittest.cc',
|
||||||
'char-predicates-unittest.cc',
|
'char-predicates-unittest.cc',
|
||||||
'compiler/change-lowering-unittest.cc',
|
'compiler/change-lowering-unittest.cc',
|
||||||
|
'compiler/common-operator-reducer-unittest.cc',
|
||||||
'compiler/common-operator-unittest.cc',
|
'compiler/common-operator-unittest.cc',
|
||||||
'compiler/compiler-test-utils.h',
|
'compiler/compiler-test-utils.h',
|
||||||
'compiler/control-equivalence-unittest.cc',
|
'compiler/control-equivalence-unittest.cc',
|
||||||
|
@ -417,6 +417,8 @@
|
|||||||
'../../src/compiler/code-generator.cc',
|
'../../src/compiler/code-generator.cc',
|
||||||
'../../src/compiler/code-generator.h',
|
'../../src/compiler/code-generator.h',
|
||||||
'../../src/compiler/common-node-cache.h',
|
'../../src/compiler/common-node-cache.h',
|
||||||
|
'../../src/compiler/common-operator-reducer.cc',
|
||||||
|
'../../src/compiler/common-operator-reducer.h',
|
||||||
'../../src/compiler/common-operator.cc',
|
'../../src/compiler/common-operator.cc',
|
||||||
'../../src/compiler/common-operator.h',
|
'../../src/compiler/common-operator.h',
|
||||||
'../../src/compiler/control-builders.cc',
|
'../../src/compiler/control-builders.cc',
|
||||||
|
Loading…
Reference in New Issue
Block a user