[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:
Benedikt Meurer 2014-12-22 14:06:34 +01:00
parent 096e1972cd
commit ee98a1d760
7 changed files with 190 additions and 0 deletions

View File

@ -490,6 +490,8 @@ source_set("v8_base") {
"src/compiler/code-generator.cc",
"src/compiler/code-generator.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.h",
"src/compiler/control-builders.cc",

View 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

View 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_

View File

@ -13,6 +13,7 @@
#include "src/compiler/basic-block-instrumentor.h"
#include "src/compiler/change-lowering.h"
#include "src/compiler/code-generator.h"
#include "src/compiler/common-operator-reducer.h"
#include "src/compiler/control-reducer.h"
#include "src/compiler/graph-replay.h"
#include "src/compiler/graph-visualizer.h"
@ -421,12 +422,14 @@ struct TypedLoweringPhase {
JSBuiltinReducer builtin_reducer(data->jsgraph());
JSTypedLowering typed_lowering(data->jsgraph(), temp_zone);
SimplifiedOperatorReducer simple_reducer(data->jsgraph());
CommonOperatorReducer common_reducer;
GraphReducer graph_reducer(data->graph(), temp_zone);
graph_reducer.AddReducer(&vn_reducer);
graph_reducer.AddReducer(&builtin_reducer);
graph_reducer.AddReducer(&typed_lowering);
graph_reducer.AddReducer(&load_elimination);
graph_reducer.AddReducer(&simple_reducer);
graph_reducer.AddReducer(&common_reducer);
graph_reducer.ReduceGraph();
}
};
@ -443,10 +446,12 @@ struct SimplifiedLoweringPhase {
ValueNumberingReducer vn_reducer(temp_zone);
SimplifiedOperatorReducer simple_reducer(data->jsgraph());
MachineOperatorReducer machine_reducer(data->jsgraph());
CommonOperatorReducer common_reducer;
GraphReducer graph_reducer(data->graph(), temp_zone);
graph_reducer.AddReducer(&vn_reducer);
graph_reducer.AddReducer(&simple_reducer);
graph_reducer.AddReducer(&machine_reducer);
graph_reducer.AddReducer(&common_reducer);
graph_reducer.ReduceGraph();
}
};
@ -463,11 +468,13 @@ struct ChangeLoweringPhase {
SimplifiedOperatorReducer simple_reducer(data->jsgraph());
ChangeLowering lowering(data->jsgraph(), &linkage);
MachineOperatorReducer machine_reducer(data->jsgraph());
CommonOperatorReducer common_reducer;
GraphReducer graph_reducer(data->graph(), temp_zone);
graph_reducer.AddReducer(&vn_reducer);
graph_reducer.AddReducer(&simple_reducer);
graph_reducer.AddReducer(&lowering);
graph_reducer.AddReducer(&machine_reducer);
graph_reducer.AddReducer(&common_reducer);
graph_reducer.ReduceGraph();
}
};

View 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

View File

@ -38,6 +38,7 @@
'base/utils/random-number-generator-unittest.cc',
'char-predicates-unittest.cc',
'compiler/change-lowering-unittest.cc',
'compiler/common-operator-reducer-unittest.cc',
'compiler/common-operator-unittest.cc',
'compiler/compiler-test-utils.h',
'compiler/control-equivalence-unittest.cc',

View File

@ -417,6 +417,8 @@
'../../src/compiler/code-generator.cc',
'../../src/compiler/code-generator.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.h',
'../../src/compiler/control-builders.cc',