d70dc1ace4
This adds a new optimization phase to the TurboFan pipeline, which walks over the effect chain and tries to eliminate redundant loads (and even some stores) of object fields. We currently ignore element access, but that will probably need to be handled as well at some point. We also don't have any special treatment to properly track object maps, which is also on the list of things that will happen afterwards. The implementation is pretty simple currently, and probably way to inefficient. It's meant to be a proof-of-concept to iterate on. R=jarin@chromium.org BUG=v8:4930,v8:5141 Review-Url: https://codereview.chromium.org/2120253002 Cr-Commit-Position: refs/heads/master@{#37528}
81 lines
2.8 KiB
C++
81 lines
2.8 KiB
C++
// 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/load-elimination.h"
|
|
#include "src/compiler/access-builder.h"
|
|
#include "src/compiler/node.h"
|
|
#include "src/compiler/simplified-operator.h"
|
|
#include "test/unittests/compiler/graph-unittest.h"
|
|
#include "test/unittests/compiler/node-test-utils.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
namespace compiler {
|
|
|
|
class LoadEliminationTest : public TypedGraphTest {
|
|
public:
|
|
LoadEliminationTest() : TypedGraphTest(3), simplified_(zone()) {}
|
|
~LoadEliminationTest() override {}
|
|
|
|
protected:
|
|
void Run() {
|
|
LoadElimination load_elimination(graph(), zone());
|
|
load_elimination.Run();
|
|
}
|
|
|
|
SimplifiedOperatorBuilder* simplified() { return &simplified_; }
|
|
|
|
private:
|
|
SimplifiedOperatorBuilder simplified_;
|
|
};
|
|
|
|
TEST_F(LoadEliminationTest, LoadFieldAndLoadField) {
|
|
Node* object = Parameter(Type::Any(), 0);
|
|
Node* effect = graph()->start();
|
|
Node* control = graph()->start();
|
|
FieldAccess access = {kTaggedBase,
|
|
kPointerSize,
|
|
MaybeHandle<Name>(),
|
|
Type::Any(),
|
|
MachineType::AnyTagged(),
|
|
kNoWriteBarrier};
|
|
Node* load1 = effect = graph()->NewNode(simplified()->LoadField(access),
|
|
object, effect, control);
|
|
Node* load2 = effect = graph()->NewNode(simplified()->LoadField(access),
|
|
object, effect, control);
|
|
control = graph()->NewNode(common()->Return(), load2, effect, control);
|
|
graph()->end()->ReplaceInput(0, control);
|
|
|
|
Run();
|
|
|
|
EXPECT_THAT(graph()->end(), IsEnd(IsReturn(load1, load1, graph()->start())));
|
|
}
|
|
|
|
TEST_F(LoadEliminationTest, StoreFieldAndLoadField) {
|
|
Node* object = Parameter(Type::Any(), 0);
|
|
Node* value = Parameter(Type::Any(), 1);
|
|
Node* effect = graph()->start();
|
|
Node* control = graph()->start();
|
|
FieldAccess access = {kTaggedBase,
|
|
kPointerSize,
|
|
MaybeHandle<Name>(),
|
|
Type::Any(),
|
|
MachineType::AnyTagged(),
|
|
kNoWriteBarrier};
|
|
Node* store = effect = graph()->NewNode(simplified()->StoreField(access),
|
|
object, value, effect, control);
|
|
Node* load = effect = graph()->NewNode(simplified()->LoadField(access),
|
|
object, effect, control);
|
|
control = graph()->NewNode(common()->Return(), load, effect, control);
|
|
graph()->end()->ReplaceInput(0, control);
|
|
|
|
Run();
|
|
|
|
EXPECT_THAT(graph()->end(), IsEnd(IsReturn(value, store, graph()->start())));
|
|
}
|
|
|
|
} // namespace compiler
|
|
} // namespace internal
|
|
} // namespace v8
|