v8/test/unittests/compiler/csa-load-elimination-unittest.cc
Manos Koukoutos f7bb9267eb [turbofan] Fix CsaLoadElimination for small types
CsaLoadElimination failed to account for truncation when optimizing
loads. This CL extends the notion of compatible Loads and Stores to
include ({store}, {load}) pairs which both have integral representation
and {store}'s representation is no smaller than {load}'s. In case the
representations are not identical, it truncates and possibly
sign-extends {store} before forwarding it to {load}.

Additional change: Extend ObjectMayAlias with wasm allocating builtin
calls.

Bug: v8:11504
Change-Id: I43f89a13793b54477a33be18aaf346462aefa8e5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2739975
Reviewed-by: Georg Neis <neis@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73340}
2021-03-11 11:09:06 +00:00

156 lines
5.2 KiB
C++

// Copyright 2021 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/csa-load-elimination.h"
#include "src/compiler/graph-reducer.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/machine-operator-reducer.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/node.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"
#include "testing/gmock-support.h"
using testing::_;
using testing::StrictMock;
namespace v8 {
namespace internal {
namespace compiler {
class CsaLoadEliminationTest : public GraphTest {
public:
CsaLoadEliminationTest()
: GraphTest(3),
simplified_(zone()),
machine_(zone()),
jsgraph_(isolate(), graph(), common(), nullptr, simplified(),
machine()),
reducer_(zone(), graph(), tick_counter(), broker()),
csa_(reducer(), jsgraph(), zone()),
mcr_(reducer(), jsgraph()) {
reducer()->AddReducer(&csa_);
reducer()->AddReducer(&mcr_);
}
~CsaLoadEliminationTest() override = default;
protected:
JSGraph* jsgraph() { return &jsgraph_; }
SimplifiedOperatorBuilder* simplified() { return &simplified_; }
MachineOperatorBuilder* machine() { return &machine_; }
GraphReducer* reducer() { return &reducer_; }
Node* param1() {
return graph()->NewNode(common()->Parameter(1), graph()->start());
}
Node* constant(int32_t value) {
return graph()->NewNode(common()->Int32Constant(value));
}
private:
SimplifiedOperatorBuilder simplified_;
MachineOperatorBuilder machine_;
JSGraph jsgraph_;
GraphReducer reducer_;
CsaLoadElimination csa_;
MachineOperatorReducer mcr_;
};
#define SETUP_SIMPLE_TEST(store_type, load_type, value_) \
Node* object = graph()->NewNode(common()->Parameter(0), graph()->start()); \
Node* offset = graph()->NewNode(common()->Int32Constant(5)); \
Node* value = value_; \
Node* control = graph()->start(); \
\
ObjectAccess store_access(MachineType::store_type(), kNoWriteBarrier); \
ObjectAccess load_access(MachineType::load_type(), kNoWriteBarrier); \
\
Node* store = \
graph()->NewNode(simplified()->StoreToObject(store_access), object, \
offset, value, graph()->start(), control); \
\
Node* load = graph()->NewNode(simplified()->LoadFromObject(load_access), \
object, offset, store, control); \
\
Node* ret = graph()->NewNode(common()->Return(0), load, load, control); \
\
graph()->end()->InsertInput(zone(), 0, ret); \
\
reducer()->ReduceGraph();
TEST_F(CsaLoadEliminationTest, Int32) {
SETUP_SIMPLE_TEST(Int32, Int32, param1())
EXPECT_EQ(ret->InputAt(0)->opcode(), IrOpcode::kParameter);
}
TEST_F(CsaLoadEliminationTest, Int64) {
SETUP_SIMPLE_TEST(Int64, Int64, param1())
EXPECT_EQ(ret->InputAt(0)->opcode(), IrOpcode::kParameter);
}
TEST_F(CsaLoadEliminationTest, Int64_to_Int32) {
SETUP_SIMPLE_TEST(Int64, Int32, param1())
EXPECT_EQ(ret->InputAt(0)->opcode(), IrOpcode::kTruncateInt64ToInt32);
}
TEST_F(CsaLoadEliminationTest, Int16_to_Int16) {
SETUP_SIMPLE_TEST(Int16, Int16, param1())
EXPECT_EQ(ret->InputAt(0)->opcode(), IrOpcode::kWord32Sar);
}
TEST_F(CsaLoadEliminationTest, Int16_to_Uint8) {
SETUP_SIMPLE_TEST(Int16, Uint8, param1())
EXPECT_EQ(ret->InputAt(0)->opcode(), IrOpcode::kWord32And);
}
TEST_F(CsaLoadEliminationTest, Int8_to_Uint16) {
SETUP_SIMPLE_TEST(Int8, Uint16, param1())
EXPECT_EQ(ret->InputAt(0)->opcode(), IrOpcode::kLoadFromObject);
}
TEST_F(CsaLoadEliminationTest, Int8_to_Uint64) {
SETUP_SIMPLE_TEST(Int8, Uint64, param1())
EXPECT_EQ(ret->InputAt(0)->opcode(), IrOpcode::kLoadFromObject);
}
TEST_F(CsaLoadEliminationTest, Int32_to_Int64) {
SETUP_SIMPLE_TEST(Int32, Int64, param1())
EXPECT_EQ(ret->InputAt(0)->opcode(), IrOpcode::kLoadFromObject);
}
TEST_F(CsaLoadEliminationTest, Int16_constant) {
SETUP_SIMPLE_TEST(Int32, Int16, constant(0xfedcba98))
Int32Matcher m(ret->InputAt(0));
EXPECT_TRUE(m.HasResolvedValue());
EXPECT_EQ(m.ResolvedValue(), int32_t(0xffffba98));
}
TEST_F(CsaLoadEliminationTest, Uint8_constant) {
SETUP_SIMPLE_TEST(Int32, Uint8, constant(0xfedcba98))
Uint32Matcher m(ret->InputAt(0));
EXPECT_TRUE(m.HasResolvedValue());
EXPECT_EQ(m.ResolvedValue(), uint32_t(0x98));
}
#undef SETUP_SIMPLE_TEST
} // namespace compiler
} // namespace internal
} // namespace v8