2016-02-23 15:33:06 +00:00
|
|
|
// 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/int64-lowering.h"
|
2019-05-21 09:30:15 +00:00
|
|
|
#include "src/codegen/signature.h"
|
2016-02-23 15:33:06 +00:00
|
|
|
#include "src/compiler/common-operator.h"
|
|
|
|
#include "src/compiler/linkage.h"
|
|
|
|
#include "src/compiler/machine-operator.h"
|
2018-04-27 12:59:22 +00:00
|
|
|
#include "src/compiler/node-properties.h"
|
2016-02-23 15:33:06 +00:00
|
|
|
#include "src/compiler/node.h"
|
2017-06-27 15:38:52 +00:00
|
|
|
#include "src/compiler/wasm-compiler.h"
|
2017-02-13 09:52:26 +00:00
|
|
|
#include "src/objects-inl.h"
|
2018-05-07 11:02:21 +00:00
|
|
|
#include "src/wasm/value-type.h"
|
2016-02-23 15:33:06 +00:00
|
|
|
#include "src/wasm/wasm-module.h"
|
|
|
|
#include "test/unittests/compiler/graph-unittest.h"
|
|
|
|
#include "test/unittests/compiler/node-test-utils.h"
|
|
|
|
#include "testing/gmock-support.h"
|
|
|
|
|
|
|
|
using testing::AllOf;
|
|
|
|
using testing::Capture;
|
|
|
|
using testing::CaptureEq;
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
namespace compiler {
|
|
|
|
|
|
|
|
class Int64LoweringTest : public GraphTest {
|
|
|
|
public:
|
2016-03-08 12:41:25 +00:00
|
|
|
Int64LoweringTest()
|
2016-03-15 10:41:55 +00:00
|
|
|
: GraphTest(),
|
|
|
|
machine_(zone(), MachineRepresentation::kWord32,
|
|
|
|
MachineOperatorBuilder::Flag::kAllOptionalOps) {
|
2017-12-02 00:30:37 +00:00
|
|
|
value_[0] = 0x1234567890ABCDEF;
|
|
|
|
value_[1] = 0x1EDCBA098765432F;
|
2016-02-23 15:33:06 +00:00
|
|
|
value_[2] = 0x1133557799886644;
|
|
|
|
}
|
|
|
|
|
|
|
|
MachineOperatorBuilder* machine() { return &machine_; }
|
|
|
|
|
|
|
|
void LowerGraph(Node* node, Signature<MachineRepresentation>* signature) {
|
2016-11-02 13:15:39 +00:00
|
|
|
Node* zero = graph()->NewNode(common()->Int32Constant(0));
|
|
|
|
Node* ret = graph()->NewNode(common()->Return(), zero, node,
|
|
|
|
graph()->start(), graph()->start());
|
2016-02-23 15:33:06 +00:00
|
|
|
NodeProperties::MergeControlToEnd(graph(), common(), ret);
|
|
|
|
|
|
|
|
Int64Lowering lowering(graph(), machine(), common(), zone(), signature);
|
|
|
|
lowering.LowerGraph();
|
|
|
|
}
|
|
|
|
|
|
|
|
void LowerGraph(Node* node, MachineRepresentation return_type,
|
|
|
|
MachineRepresentation rep = MachineRepresentation::kWord32,
|
|
|
|
int num_params = 0) {
|
|
|
|
Signature<MachineRepresentation>::Builder sig_builder(zone(), 1,
|
|
|
|
num_params);
|
|
|
|
sig_builder.AddReturn(return_type);
|
|
|
|
for (int i = 0; i < num_params; i++) {
|
|
|
|
sig_builder.AddParam(rep);
|
|
|
|
}
|
|
|
|
LowerGraph(node, sig_builder.Build());
|
|
|
|
}
|
|
|
|
|
|
|
|
void CompareCallDescriptors(const CallDescriptor* lhs,
|
|
|
|
const CallDescriptor* rhs) {
|
|
|
|
EXPECT_THAT(lhs->CalleeSavedFPRegisters(), rhs->CalleeSavedFPRegisters());
|
|
|
|
EXPECT_THAT(lhs->CalleeSavedRegisters(), rhs->CalleeSavedRegisters());
|
|
|
|
EXPECT_THAT(lhs->FrameStateCount(), rhs->FrameStateCount());
|
|
|
|
EXPECT_THAT(lhs->InputCount(), rhs->InputCount());
|
|
|
|
for (size_t i = 0; i < lhs->InputCount(); i++) {
|
|
|
|
EXPECT_THAT(lhs->GetInputLocation(i), rhs->GetInputLocation(i));
|
|
|
|
EXPECT_THAT(lhs->GetInputType(i), rhs->GetInputType(i));
|
|
|
|
}
|
|
|
|
EXPECT_THAT(lhs->ReturnCount(), rhs->ReturnCount());
|
|
|
|
for (size_t i = 0; i < lhs->ReturnCount(); i++) {
|
|
|
|
EXPECT_THAT(lhs->GetReturnLocation(i), rhs->GetReturnLocation(i));
|
|
|
|
EXPECT_THAT(lhs->GetReturnType(i), rhs->GetReturnType(i));
|
|
|
|
}
|
|
|
|
EXPECT_THAT(lhs->flags(), rhs->flags());
|
|
|
|
EXPECT_THAT(lhs->kind(), rhs->kind());
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t value(int i) { return value_[i]; }
|
|
|
|
|
|
|
|
int32_t low_word_value(int i) {
|
2017-12-02 00:30:37 +00:00
|
|
|
return static_cast<int32_t>(value_[i] & 0xFFFFFFFF);
|
2016-02-23 15:33:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int32_t high_word_value(int i) {
|
|
|
|
return static_cast<int32_t>(value_[i] >> 32);
|
|
|
|
}
|
|
|
|
|
2016-02-25 12:14:35 +00:00
|
|
|
void TestComparison(
|
|
|
|
const Operator* op,
|
|
|
|
Matcher<Node*> (*high_word_matcher)(const Matcher<Node*>& lhs_matcher,
|
|
|
|
const Matcher<Node*>& rhs_matcher),
|
|
|
|
Matcher<Node*> (*low_word_matcher)(const Matcher<Node*>& lhs_matcher,
|
|
|
|
const Matcher<Node*>& rhs_matcher)) {
|
|
|
|
LowerGraph(
|
|
|
|
graph()->NewNode(op, Int64Constant(value(0)), Int64Constant(value(1))),
|
|
|
|
MachineRepresentation::kWord32);
|
|
|
|
EXPECT_THAT(
|
|
|
|
graph()->end()->InputAt(1),
|
|
|
|
IsReturn(IsWord32Or(
|
|
|
|
high_word_matcher(IsInt32Constant(high_word_value(0)),
|
|
|
|
IsInt32Constant(high_word_value(1))),
|
|
|
|
IsWord32And(
|
|
|
|
IsWord32Equal(IsInt32Constant(high_word_value(0)),
|
|
|
|
IsInt32Constant(high_word_value(1))),
|
|
|
|
low_word_matcher(IsInt32Constant(low_word_value(0)),
|
|
|
|
IsInt32Constant(low_word_value(1))))),
|
|
|
|
start(), start()));
|
|
|
|
}
|
|
|
|
|
2016-02-23 15:33:06 +00:00
|
|
|
private:
|
|
|
|
MachineOperatorBuilder machine_;
|
|
|
|
int64_t value_[3];
|
|
|
|
};
|
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, Int64Constant) {
|
|
|
|
LowerGraph(Int64Constant(value(0)), MachineRepresentation::kWord64);
|
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsInt32Constant(low_word_value(0)),
|
|
|
|
IsInt32Constant(high_word_value(0)), start(), start()));
|
|
|
|
}
|
|
|
|
|
2016-06-23 11:40:16 +00:00
|
|
|
#if defined(V8_TARGET_LITTLE_ENDIAN)
|
2016-07-22 20:55:03 +00:00
|
|
|
#define LOAD_VERIFY(kLoad) \
|
|
|
|
Matcher<Node*> high_word_load_matcher = \
|
|
|
|
Is##kLoad(MachineType::Int32(), IsInt32Constant(base), \
|
|
|
|
IsInt32Add(IsInt32Constant(index), IsInt32Constant(0x4)), \
|
|
|
|
start(), start()); \
|
|
|
|
\
|
|
|
|
EXPECT_THAT( \
|
|
|
|
graph()->end()->InputAt(1), \
|
|
|
|
IsReturn2( \
|
|
|
|
Is##kLoad(MachineType::Int32(), IsInt32Constant(base), \
|
|
|
|
IsInt32Constant(index), \
|
|
|
|
AllOf(CaptureEq(&high_word_load), high_word_load_matcher), \
|
|
|
|
start()), \
|
|
|
|
AllOf(CaptureEq(&high_word_load), high_word_load_matcher), start(), \
|
|
|
|
start()));
|
2016-06-23 11:40:16 +00:00
|
|
|
#elif defined(V8_TARGET_BIG_ENDIAN)
|
2016-07-22 20:55:03 +00:00
|
|
|
#define LOAD_VERIFY(kLoad) \
|
|
|
|
Matcher<Node*> high_word_load_matcher = \
|
|
|
|
Is##kLoad(MachineType::Int32(), IsInt32Constant(base), \
|
|
|
|
IsInt32Constant(index), start(), start()); \
|
|
|
|
\
|
|
|
|
EXPECT_THAT( \
|
|
|
|
graph()->end()->InputAt(1), \
|
|
|
|
IsReturn2( \
|
|
|
|
Is##kLoad(MachineType::Int32(), IsInt32Constant(base), \
|
|
|
|
IsInt32Add(IsInt32Constant(index), IsInt32Constant(0x4)), \
|
|
|
|
AllOf(CaptureEq(&high_word_load), high_word_load_matcher), \
|
|
|
|
start()), \
|
|
|
|
AllOf(CaptureEq(&high_word_load), high_word_load_matcher), start(), \
|
2016-06-23 11:40:16 +00:00
|
|
|
start()));
|
|
|
|
#endif
|
2016-02-23 15:33:06 +00:00
|
|
|
|
2016-07-22 20:55:03 +00:00
|
|
|
#define INT64_LOAD_LOWERING(kLoad) \
|
|
|
|
int32_t base = 0x1234; \
|
|
|
|
int32_t index = 0x5678; \
|
|
|
|
\
|
|
|
|
LowerGraph(graph()->NewNode(machine()->kLoad(MachineType::Int64()), \
|
|
|
|
Int32Constant(base), Int32Constant(index), \
|
|
|
|
start(), start()), \
|
|
|
|
MachineRepresentation::kWord64); \
|
|
|
|
\
|
|
|
|
Capture<Node*> high_word_load; \
|
|
|
|
LOAD_VERIFY(kLoad)
|
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, Int64Load) { INT64_LOAD_LOWERING(Load); }
|
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, UnalignedInt64Load) {
|
|
|
|
INT64_LOAD_LOWERING(UnalignedLoad);
|
|
|
|
}
|
2016-02-23 15:33:06 +00:00
|
|
|
|
2016-06-23 11:40:16 +00:00
|
|
|
#if defined(V8_TARGET_LITTLE_ENDIAN)
|
2016-07-22 20:55:03 +00:00
|
|
|
#define STORE_VERIFY(kStore, kRep) \
|
|
|
|
EXPECT_THAT( \
|
|
|
|
graph()->end()->InputAt(1), \
|
|
|
|
IsReturn(IsInt32Constant(return_value), \
|
|
|
|
Is##kStore( \
|
|
|
|
kRep, IsInt32Constant(base), IsInt32Constant(index), \
|
|
|
|
IsInt32Constant(low_word_value(0)), \
|
|
|
|
Is##kStore( \
|
|
|
|
kRep, IsInt32Constant(base), \
|
|
|
|
IsInt32Add(IsInt32Constant(index), IsInt32Constant(4)), \
|
|
|
|
IsInt32Constant(high_word_value(0)), start(), start()), \
|
|
|
|
start()), \
|
|
|
|
start()));
|
2016-06-23 11:40:16 +00:00
|
|
|
#elif defined(V8_TARGET_BIG_ENDIAN)
|
2016-07-22 20:55:03 +00:00
|
|
|
#define STORE_VERIFY(kStore, kRep) \
|
|
|
|
EXPECT_THAT( \
|
|
|
|
graph()->end()->InputAt(1), \
|
|
|
|
IsReturn(IsInt32Constant(return_value), \
|
|
|
|
Is##kStore( \
|
|
|
|
kRep, IsInt32Constant(base), \
|
|
|
|
IsInt32Add(IsInt32Constant(index), IsInt32Constant(4)), \
|
|
|
|
IsInt32Constant(low_word_value(0)), \
|
|
|
|
Is##kStore( \
|
|
|
|
kRep, IsInt32Constant(base), IsInt32Constant(index), \
|
|
|
|
IsInt32Constant(high_word_value(0)), start(), start()), \
|
|
|
|
start()), \
|
|
|
|
start()));
|
2016-06-23 11:40:16 +00:00
|
|
|
#endif
|
2016-07-22 20:55:03 +00:00
|
|
|
|
|
|
|
#define INT64_STORE_LOWERING(kStore, kRep32, kRep64) \
|
|
|
|
int32_t base = 1111; \
|
|
|
|
int32_t index = 2222; \
|
|
|
|
int32_t return_value = 0x5555; \
|
|
|
|
\
|
|
|
|
Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 0); \
|
|
|
|
sig_builder.AddReturn(MachineRepresentation::kWord32); \
|
|
|
|
\
|
|
|
|
Node* store = graph()->NewNode(machine()->kStore(kRep64), \
|
|
|
|
Int32Constant(base), Int32Constant(index), \
|
|
|
|
Int64Constant(value(0)), start(), start()); \
|
|
|
|
\
|
2016-11-02 13:15:39 +00:00
|
|
|
Node* zero = graph()->NewNode(common()->Int32Constant(0)); \
|
|
|
|
Node* ret = graph()->NewNode(common()->Return(), zero, \
|
2016-07-22 20:55:03 +00:00
|
|
|
Int32Constant(return_value), store, start()); \
|
|
|
|
\
|
|
|
|
NodeProperties::MergeControlToEnd(graph(), common(), ret); \
|
|
|
|
\
|
|
|
|
Int64Lowering lowering(graph(), machine(), common(), zone(), \
|
|
|
|
sig_builder.Build()); \
|
|
|
|
lowering.LowerGraph(); \
|
|
|
|
\
|
|
|
|
STORE_VERIFY(kStore, kRep32)
|
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, Int64Store) {
|
|
|
|
const StoreRepresentation rep64(MachineRepresentation::kWord64,
|
|
|
|
WriteBarrierKind::kNoWriteBarrier);
|
|
|
|
const StoreRepresentation rep32(MachineRepresentation::kWord32,
|
|
|
|
WriteBarrierKind::kNoWriteBarrier);
|
|
|
|
INT64_STORE_LOWERING(Store, rep32, rep64);
|
|
|
|
}
|
|
|
|
|
2017-02-01 16:27:12 +00:00
|
|
|
TEST_F(Int64LoweringTest, Int32Store) {
|
|
|
|
const StoreRepresentation rep32(MachineRepresentation::kWord32,
|
|
|
|
WriteBarrierKind::kNoWriteBarrier);
|
|
|
|
int32_t base = 1111;
|
|
|
|
int32_t index = 2222;
|
|
|
|
int32_t return_value = 0x5555;
|
|
|
|
|
|
|
|
Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 0);
|
|
|
|
sig_builder.AddReturn(MachineRepresentation::kWord32);
|
|
|
|
|
|
|
|
Node* store = graph()->NewNode(machine()->Store(rep32), Int32Constant(base),
|
|
|
|
Int32Constant(index), Int64Constant(value(0)),
|
|
|
|
start(), start());
|
|
|
|
|
|
|
|
Node* zero = graph()->NewNode(common()->Int32Constant(0));
|
|
|
|
Node* ret = graph()->NewNode(common()->Return(), zero,
|
|
|
|
Int32Constant(return_value), store, start());
|
|
|
|
|
|
|
|
NodeProperties::MergeControlToEnd(graph(), common(), ret);
|
|
|
|
|
|
|
|
Int64Lowering lowering(graph(), machine(), common(), zone(),
|
|
|
|
sig_builder.Build());
|
|
|
|
lowering.LowerGraph();
|
|
|
|
|
|
|
|
EXPECT_THAT(
|
|
|
|
graph()->end()->InputAt(1),
|
|
|
|
IsReturn(IsInt32Constant(return_value),
|
|
|
|
IsStore(rep32, IsInt32Constant(base), IsInt32Constant(index),
|
|
|
|
IsInt32Constant(low_word_value(0)), start(), start()),
|
|
|
|
start()));
|
|
|
|
}
|
|
|
|
|
2016-07-22 20:55:03 +00:00
|
|
|
TEST_F(Int64LoweringTest, Int64UnalignedStore) {
|
|
|
|
const UnalignedStoreRepresentation rep64(MachineRepresentation::kWord64);
|
|
|
|
const UnalignedStoreRepresentation rep32(MachineRepresentation::kWord32);
|
|
|
|
INT64_STORE_LOWERING(UnalignedStore, rep32, rep64);
|
2016-02-23 15:33:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, Int64And) {
|
|
|
|
LowerGraph(graph()->NewNode(machine()->Word64And(), Int64Constant(value(0)),
|
|
|
|
Int64Constant(value(1))),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsWord32And(IsInt32Constant(low_word_value(0)),
|
|
|
|
IsInt32Constant(low_word_value(1))),
|
|
|
|
IsWord32And(IsInt32Constant(high_word_value(0)),
|
|
|
|
IsInt32Constant(high_word_value(1))),
|
|
|
|
start(), start()));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, TruncateInt64ToInt32) {
|
|
|
|
LowerGraph(graph()->NewNode(machine()->TruncateInt64ToInt32(),
|
|
|
|
Int64Constant(value(0))),
|
|
|
|
MachineRepresentation::kWord32);
|
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
|
|
|
IsReturn(IsInt32Constant(low_word_value(0)), start(), start()));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, Parameter) {
|
[wasm] Introduce the WasmContext
The WasmContext struct introduced in this CL is used to store the
mem_size and mem_start address of the wasm memory. These variables can
be accessed at C++ level at graph build time (e.g., initialized during
instance building). When the GrowMemory runtime is invoked, the context
variables can be changed in the WasmContext at C++ level so that the
generated code will load the correct values.
This requires to insert a relocatable pointer only in the
JSToWasmWrapper (and in the other wasm entry points), the value is then
passed from function to function as an automatically added additional
parameter. The WasmContext is then dropped when creating an Interpreter
Entry or when invoking a JavaScript function. This removes the need of
patching the generated code at runtime (i.e., when the memory grows)
with respect to WASM_MEMORY_REFERENCE and WASM_MEMORY_SIZE_REFERENCE.
However, we still need to patch the code at instance build time to patch
the JSToWasmWrappers; in fact the address of the WasmContext is not
known during compilation, but only when the instance is built.
The WasmContext address is passed as the first parameter. This has the
advantage of not having to move the WasmContext around if the function
does not use many registers. This CL also changes the wasm calling
convention so that the first parameter register is different from the
return value register. The WasmContext is attached to every
WasmMemoryObject, to share the same context with multiple instances
sharing the same memory. Moreover, the nodes representing the
WasmContext variables are cached in the SSA environment, similarly to
other local variables that might change during execution. The nodes are
created when initializing the SSA environment and refreshed every time a
grow_memory or a function call happens, so that we are sure that they
always represent the correct mem_size and mem_start variables.
This CL also removes the WasmMemorySize runtime (since it's now possible
to directly retrieve mem_size from the context) and simplifies the
GrowMemory runtime (since every instance now has a memory_object).
R=ahaas@chromium.org,clemensh@chromium.org
CC=gdeepti@chromium.org
Change-Id: I3f058e641284f5a1bbbfc35a64c88da6ff08e240
Reviewed-on: https://chromium-review.googlesource.com/671008
Commit-Queue: Enrico Bacis <enricobacis@google.com>
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48209}
2017-09-28 14:59:37 +00:00
|
|
|
LowerGraph(Parameter(1), MachineRepresentation::kWord64,
|
2016-02-23 15:33:06 +00:00
|
|
|
MachineRepresentation::kWord64, 1);
|
|
|
|
|
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
[wasm] Introduce the WasmContext
The WasmContext struct introduced in this CL is used to store the
mem_size and mem_start address of the wasm memory. These variables can
be accessed at C++ level at graph build time (e.g., initialized during
instance building). When the GrowMemory runtime is invoked, the context
variables can be changed in the WasmContext at C++ level so that the
generated code will load the correct values.
This requires to insert a relocatable pointer only in the
JSToWasmWrapper (and in the other wasm entry points), the value is then
passed from function to function as an automatically added additional
parameter. The WasmContext is then dropped when creating an Interpreter
Entry or when invoking a JavaScript function. This removes the need of
patching the generated code at runtime (i.e., when the memory grows)
with respect to WASM_MEMORY_REFERENCE and WASM_MEMORY_SIZE_REFERENCE.
However, we still need to patch the code at instance build time to patch
the JSToWasmWrappers; in fact the address of the WasmContext is not
known during compilation, but only when the instance is built.
The WasmContext address is passed as the first parameter. This has the
advantage of not having to move the WasmContext around if the function
does not use many registers. This CL also changes the wasm calling
convention so that the first parameter register is different from the
return value register. The WasmContext is attached to every
WasmMemoryObject, to share the same context with multiple instances
sharing the same memory. Moreover, the nodes representing the
WasmContext variables are cached in the SSA environment, similarly to
other local variables that might change during execution. The nodes are
created when initializing the SSA environment and refreshed every time a
grow_memory or a function call happens, so that we are sure that they
always represent the correct mem_size and mem_start variables.
This CL also removes the WasmMemorySize runtime (since it's now possible
to directly retrieve mem_size from the context) and simplifies the
GrowMemory runtime (since every instance now has a memory_object).
R=ahaas@chromium.org,clemensh@chromium.org
CC=gdeepti@chromium.org
Change-Id: I3f058e641284f5a1bbbfc35a64c88da6ff08e240
Reviewed-on: https://chromium-review.googlesource.com/671008
Commit-Queue: Enrico Bacis <enricobacis@google.com>
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48209}
2017-09-28 14:59:37 +00:00
|
|
|
IsReturn2(IsParameter(1), IsParameter(2), start(), start()));
|
2016-02-23 15:33:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, Parameter2) {
|
|
|
|
Signature<MachineRepresentation>::Builder sig_builder(zone(), 1, 5);
|
|
|
|
sig_builder.AddReturn(MachineRepresentation::kWord32);
|
|
|
|
|
|
|
|
sig_builder.AddParam(MachineRepresentation::kWord32);
|
|
|
|
sig_builder.AddParam(MachineRepresentation::kWord64);
|
|
|
|
sig_builder.AddParam(MachineRepresentation::kFloat64);
|
|
|
|
sig_builder.AddParam(MachineRepresentation::kWord64);
|
|
|
|
sig_builder.AddParam(MachineRepresentation::kWord32);
|
|
|
|
|
|
|
|
int start_parameter = start()->op()->ValueOutputCount();
|
[wasm] Introduce the WasmContext
The WasmContext struct introduced in this CL is used to store the
mem_size and mem_start address of the wasm memory. These variables can
be accessed at C++ level at graph build time (e.g., initialized during
instance building). When the GrowMemory runtime is invoked, the context
variables can be changed in the WasmContext at C++ level so that the
generated code will load the correct values.
This requires to insert a relocatable pointer only in the
JSToWasmWrapper (and in the other wasm entry points), the value is then
passed from function to function as an automatically added additional
parameter. The WasmContext is then dropped when creating an Interpreter
Entry or when invoking a JavaScript function. This removes the need of
patching the generated code at runtime (i.e., when the memory grows)
with respect to WASM_MEMORY_REFERENCE and WASM_MEMORY_SIZE_REFERENCE.
However, we still need to patch the code at instance build time to patch
the JSToWasmWrappers; in fact the address of the WasmContext is not
known during compilation, but only when the instance is built.
The WasmContext address is passed as the first parameter. This has the
advantage of not having to move the WasmContext around if the function
does not use many registers. This CL also changes the wasm calling
convention so that the first parameter register is different from the
return value register. The WasmContext is attached to every
WasmMemoryObject, to share the same context with multiple instances
sharing the same memory. Moreover, the nodes representing the
WasmContext variables are cached in the SSA environment, similarly to
other local variables that might change during execution. The nodes are
created when initializing the SSA environment and refreshed every time a
grow_memory or a function call happens, so that we are sure that they
always represent the correct mem_size and mem_start variables.
This CL also removes the WasmMemorySize runtime (since it's now possible
to directly retrieve mem_size from the context) and simplifies the
GrowMemory runtime (since every instance now has a memory_object).
R=ahaas@chromium.org,clemensh@chromium.org
CC=gdeepti@chromium.org
Change-Id: I3f058e641284f5a1bbbfc35a64c88da6ff08e240
Reviewed-on: https://chromium-review.googlesource.com/671008
Commit-Queue: Enrico Bacis <enricobacis@google.com>
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48209}
2017-09-28 14:59:37 +00:00
|
|
|
LowerGraph(Parameter(5), sig_builder.Build());
|
2016-02-23 15:33:06 +00:00
|
|
|
|
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
[wasm] Introduce the WasmContext
The WasmContext struct introduced in this CL is used to store the
mem_size and mem_start address of the wasm memory. These variables can
be accessed at C++ level at graph build time (e.g., initialized during
instance building). When the GrowMemory runtime is invoked, the context
variables can be changed in the WasmContext at C++ level so that the
generated code will load the correct values.
This requires to insert a relocatable pointer only in the
JSToWasmWrapper (and in the other wasm entry points), the value is then
passed from function to function as an automatically added additional
parameter. The WasmContext is then dropped when creating an Interpreter
Entry or when invoking a JavaScript function. This removes the need of
patching the generated code at runtime (i.e., when the memory grows)
with respect to WASM_MEMORY_REFERENCE and WASM_MEMORY_SIZE_REFERENCE.
However, we still need to patch the code at instance build time to patch
the JSToWasmWrappers; in fact the address of the WasmContext is not
known during compilation, but only when the instance is built.
The WasmContext address is passed as the first parameter. This has the
advantage of not having to move the WasmContext around if the function
does not use many registers. This CL also changes the wasm calling
convention so that the first parameter register is different from the
return value register. The WasmContext is attached to every
WasmMemoryObject, to share the same context with multiple instances
sharing the same memory. Moreover, the nodes representing the
WasmContext variables are cached in the SSA environment, similarly to
other local variables that might change during execution. The nodes are
created when initializing the SSA environment and refreshed every time a
grow_memory or a function call happens, so that we are sure that they
always represent the correct mem_size and mem_start variables.
This CL also removes the WasmMemorySize runtime (since it's now possible
to directly retrieve mem_size from the context) and simplifies the
GrowMemory runtime (since every instance now has a memory_object).
R=ahaas@chromium.org,clemensh@chromium.org
CC=gdeepti@chromium.org
Change-Id: I3f058e641284f5a1bbbfc35a64c88da6ff08e240
Reviewed-on: https://chromium-review.googlesource.com/671008
Commit-Queue: Enrico Bacis <enricobacis@google.com>
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48209}
2017-09-28 14:59:37 +00:00
|
|
|
IsReturn(IsParameter(7), start(), start()));
|
2016-02-23 15:33:06 +00:00
|
|
|
// The parameter of the start node should increase by 2, because we lowered
|
|
|
|
// two parameter nodes.
|
|
|
|
EXPECT_THAT(start()->op()->ValueOutputCount(), start_parameter + 2);
|
|
|
|
}
|
|
|
|
|
2019-03-21 11:56:38 +00:00
|
|
|
TEST_F(Int64LoweringTest, ParameterWithJSContextParam) {
|
|
|
|
Signature<MachineRepresentation>::Builder sig_builder(zone(), 0, 2);
|
|
|
|
sig_builder.AddParam(MachineRepresentation::kWord64);
|
|
|
|
sig_builder.AddParam(MachineRepresentation::kWord64);
|
|
|
|
|
|
|
|
auto sig = sig_builder.Build();
|
|
|
|
|
|
|
|
Node* js_context = graph()->NewNode(
|
|
|
|
common()->Parameter(Linkage::GetJSCallContextParamIndex(
|
|
|
|
static_cast<int>(sig->parameter_count()) + 1),
|
|
|
|
"%context"),
|
|
|
|
start());
|
|
|
|
LowerGraph(js_context, sig);
|
|
|
|
|
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
|
|
|
IsReturn(js_context, start(), start()));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, ParameterWithJSClosureParam) {
|
|
|
|
Signature<MachineRepresentation>::Builder sig_builder(zone(), 0, 2);
|
|
|
|
sig_builder.AddParam(MachineRepresentation::kWord64);
|
|
|
|
sig_builder.AddParam(MachineRepresentation::kWord64);
|
|
|
|
|
|
|
|
auto sig = sig_builder.Build();
|
|
|
|
|
|
|
|
Node* js_closure = graph()->NewNode(
|
|
|
|
common()->Parameter(Linkage::kJSCallClosureParamIndex, "%closure"),
|
|
|
|
start());
|
|
|
|
LowerGraph(js_closure, sig);
|
|
|
|
|
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
|
|
|
IsReturn(js_closure, start(), start()));
|
|
|
|
}
|
|
|
|
|
[wasm] Introduce the WasmContext
The WasmContext struct introduced in this CL is used to store the
mem_size and mem_start address of the wasm memory. These variables can
be accessed at C++ level at graph build time (e.g., initialized during
instance building). When the GrowMemory runtime is invoked, the context
variables can be changed in the WasmContext at C++ level so that the
generated code will load the correct values.
This requires to insert a relocatable pointer only in the
JSToWasmWrapper (and in the other wasm entry points), the value is then
passed from function to function as an automatically added additional
parameter. The WasmContext is then dropped when creating an Interpreter
Entry or when invoking a JavaScript function. This removes the need of
patching the generated code at runtime (i.e., when the memory grows)
with respect to WASM_MEMORY_REFERENCE and WASM_MEMORY_SIZE_REFERENCE.
However, we still need to patch the code at instance build time to patch
the JSToWasmWrappers; in fact the address of the WasmContext is not
known during compilation, but only when the instance is built.
The WasmContext address is passed as the first parameter. This has the
advantage of not having to move the WasmContext around if the function
does not use many registers. This CL also changes the wasm calling
convention so that the first parameter register is different from the
return value register. The WasmContext is attached to every
WasmMemoryObject, to share the same context with multiple instances
sharing the same memory. Moreover, the nodes representing the
WasmContext variables are cached in the SSA environment, similarly to
other local variables that might change during execution. The nodes are
created when initializing the SSA environment and refreshed every time a
grow_memory or a function call happens, so that we are sure that they
always represent the correct mem_size and mem_start variables.
This CL also removes the WasmMemorySize runtime (since it's now possible
to directly retrieve mem_size from the context) and simplifies the
GrowMemory runtime (since every instance now has a memory_object).
R=ahaas@chromium.org,clemensh@chromium.org
CC=gdeepti@chromium.org
Change-Id: I3f058e641284f5a1bbbfc35a64c88da6ff08e240
Reviewed-on: https://chromium-review.googlesource.com/671008
Commit-Queue: Enrico Bacis <enricobacis@google.com>
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48209}
2017-09-28 14:59:37 +00:00
|
|
|
// The following tests assume that pointers are 32 bit and therefore pointers do
|
|
|
|
// not get lowered. This assumption does not hold on 64 bit platforms, which
|
|
|
|
// invalidates these tests.
|
|
|
|
// TODO(wasm): We can find an alternative to re-activate these tests.
|
|
|
|
#if V8_TARGET_ARCH_32_BIT
|
2016-02-23 15:33:06 +00:00
|
|
|
TEST_F(Int64LoweringTest, CallI64Return) {
|
|
|
|
int32_t function = 0x9999;
|
[wasm] Introduce the WasmContext
The WasmContext struct introduced in this CL is used to store the
mem_size and mem_start address of the wasm memory. These variables can
be accessed at C++ level at graph build time (e.g., initialized during
instance building). When the GrowMemory runtime is invoked, the context
variables can be changed in the WasmContext at C++ level so that the
generated code will load the correct values.
This requires to insert a relocatable pointer only in the
JSToWasmWrapper (and in the other wasm entry points), the value is then
passed from function to function as an automatically added additional
parameter. The WasmContext is then dropped when creating an Interpreter
Entry or when invoking a JavaScript function. This removes the need of
patching the generated code at runtime (i.e., when the memory grows)
with respect to WASM_MEMORY_REFERENCE and WASM_MEMORY_SIZE_REFERENCE.
However, we still need to patch the code at instance build time to patch
the JSToWasmWrappers; in fact the address of the WasmContext is not
known during compilation, but only when the instance is built.
The WasmContext address is passed as the first parameter. This has the
advantage of not having to move the WasmContext around if the function
does not use many registers. This CL also changes the wasm calling
convention so that the first parameter register is different from the
return value register. The WasmContext is attached to every
WasmMemoryObject, to share the same context with multiple instances
sharing the same memory. Moreover, the nodes representing the
WasmContext variables are cached in the SSA environment, similarly to
other local variables that might change during execution. The nodes are
created when initializing the SSA environment and refreshed every time a
grow_memory or a function call happens, so that we are sure that they
always represent the correct mem_size and mem_start variables.
This CL also removes the WasmMemorySize runtime (since it's now possible
to directly retrieve mem_size from the context) and simplifies the
GrowMemory runtime (since every instance now has a memory_object).
R=ahaas@chromium.org,clemensh@chromium.org
CC=gdeepti@chromium.org
Change-Id: I3f058e641284f5a1bbbfc35a64c88da6ff08e240
Reviewed-on: https://chromium-review.googlesource.com/671008
Commit-Queue: Enrico Bacis <enricobacis@google.com>
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48209}
2017-09-28 14:59:37 +00:00
|
|
|
Node* context_address = Int32Constant(0);
|
2016-02-23 15:33:06 +00:00
|
|
|
|
2018-05-07 11:02:21 +00:00
|
|
|
wasm::FunctionSig::Builder sig_builder(zone(), 1, 0);
|
|
|
|
sig_builder.AddReturn(wasm::kWasmI64);
|
2016-02-23 15:33:06 +00:00
|
|
|
|
2018-02-09 19:19:25 +00:00
|
|
|
auto call_descriptor =
|
2017-06-27 15:38:52 +00:00
|
|
|
compiler::GetWasmCallDescriptor(zone(), sig_builder.Build());
|
2016-02-23 15:33:06 +00:00
|
|
|
|
2018-02-09 19:19:25 +00:00
|
|
|
LowerGraph(
|
|
|
|
graph()->NewNode(common()->Call(call_descriptor), Int32Constant(function),
|
|
|
|
context_address, start(), start()),
|
|
|
|
MachineRepresentation::kWord64);
|
2016-02-23 15:33:06 +00:00
|
|
|
|
|
|
|
Capture<Node*> call;
|
|
|
|
Matcher<Node*> call_matcher =
|
|
|
|
IsCall(testing::_, IsInt32Constant(function), start(), start());
|
|
|
|
|
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsProjection(0, AllOf(CaptureEq(&call), call_matcher)),
|
|
|
|
IsProjection(1, AllOf(CaptureEq(&call), call_matcher)),
|
|
|
|
start(), start()));
|
|
|
|
|
|
|
|
CompareCallDescriptors(
|
2018-03-21 16:21:56 +00:00
|
|
|
CallDescriptorOf(
|
2018-03-05 08:41:11 +00:00
|
|
|
graph()->end()->InputAt(1)->InputAt(1)->InputAt(0)->op()),
|
2018-02-09 19:19:25 +00:00
|
|
|
compiler::GetI32WasmCallDescriptor(zone(), call_descriptor));
|
2016-02-23 15:33:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, CallI64Parameter) {
|
|
|
|
int32_t function = 0x9999;
|
[wasm] Introduce the WasmContext
The WasmContext struct introduced in this CL is used to store the
mem_size and mem_start address of the wasm memory. These variables can
be accessed at C++ level at graph build time (e.g., initialized during
instance building). When the GrowMemory runtime is invoked, the context
variables can be changed in the WasmContext at C++ level so that the
generated code will load the correct values.
This requires to insert a relocatable pointer only in the
JSToWasmWrapper (and in the other wasm entry points), the value is then
passed from function to function as an automatically added additional
parameter. The WasmContext is then dropped when creating an Interpreter
Entry or when invoking a JavaScript function. This removes the need of
patching the generated code at runtime (i.e., when the memory grows)
with respect to WASM_MEMORY_REFERENCE and WASM_MEMORY_SIZE_REFERENCE.
However, we still need to patch the code at instance build time to patch
the JSToWasmWrappers; in fact the address of the WasmContext is not
known during compilation, but only when the instance is built.
The WasmContext address is passed as the first parameter. This has the
advantage of not having to move the WasmContext around if the function
does not use many registers. This CL also changes the wasm calling
convention so that the first parameter register is different from the
return value register. The WasmContext is attached to every
WasmMemoryObject, to share the same context with multiple instances
sharing the same memory. Moreover, the nodes representing the
WasmContext variables are cached in the SSA environment, similarly to
other local variables that might change during execution. The nodes are
created when initializing the SSA environment and refreshed every time a
grow_memory or a function call happens, so that we are sure that they
always represent the correct mem_size and mem_start variables.
This CL also removes the WasmMemorySize runtime (since it's now possible
to directly retrieve mem_size from the context) and simplifies the
GrowMemory runtime (since every instance now has a memory_object).
R=ahaas@chromium.org,clemensh@chromium.org
CC=gdeepti@chromium.org
Change-Id: I3f058e641284f5a1bbbfc35a64c88da6ff08e240
Reviewed-on: https://chromium-review.googlesource.com/671008
Commit-Queue: Enrico Bacis <enricobacis@google.com>
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48209}
2017-09-28 14:59:37 +00:00
|
|
|
Node* context_address = Int32Constant(0);
|
2016-02-23 15:33:06 +00:00
|
|
|
|
2018-05-07 11:02:21 +00:00
|
|
|
wasm::FunctionSig::Builder sig_builder(zone(), 1, 3);
|
|
|
|
sig_builder.AddReturn(wasm::kWasmI32);
|
|
|
|
sig_builder.AddParam(wasm::kWasmI64);
|
|
|
|
sig_builder.AddParam(wasm::kWasmI32);
|
|
|
|
sig_builder.AddParam(wasm::kWasmI64);
|
2016-02-23 15:33:06 +00:00
|
|
|
|
2018-02-09 19:19:25 +00:00
|
|
|
auto call_descriptor =
|
2017-06-27 15:38:52 +00:00
|
|
|
compiler::GetWasmCallDescriptor(zone(), sig_builder.Build());
|
2016-02-23 15:33:06 +00:00
|
|
|
|
2018-02-09 19:19:25 +00:00
|
|
|
LowerGraph(
|
|
|
|
graph()->NewNode(common()->Call(call_descriptor), Int32Constant(function),
|
|
|
|
context_address, Int64Constant(value(0)),
|
|
|
|
Int32Constant(low_word_value(1)),
|
|
|
|
Int64Constant(value(2)), start(), start()),
|
|
|
|
MachineRepresentation::kWord32);
|
2016-02-23 15:33:06 +00:00
|
|
|
|
|
|
|
EXPECT_THAT(
|
|
|
|
graph()->end()->InputAt(1),
|
[wasm] Introduce the WasmContext
The WasmContext struct introduced in this CL is used to store the
mem_size and mem_start address of the wasm memory. These variables can
be accessed at C++ level at graph build time (e.g., initialized during
instance building). When the GrowMemory runtime is invoked, the context
variables can be changed in the WasmContext at C++ level so that the
generated code will load the correct values.
This requires to insert a relocatable pointer only in the
JSToWasmWrapper (and in the other wasm entry points), the value is then
passed from function to function as an automatically added additional
parameter. The WasmContext is then dropped when creating an Interpreter
Entry or when invoking a JavaScript function. This removes the need of
patching the generated code at runtime (i.e., when the memory grows)
with respect to WASM_MEMORY_REFERENCE and WASM_MEMORY_SIZE_REFERENCE.
However, we still need to patch the code at instance build time to patch
the JSToWasmWrappers; in fact the address of the WasmContext is not
known during compilation, but only when the instance is built.
The WasmContext address is passed as the first parameter. This has the
advantage of not having to move the WasmContext around if the function
does not use many registers. This CL also changes the wasm calling
convention so that the first parameter register is different from the
return value register. The WasmContext is attached to every
WasmMemoryObject, to share the same context with multiple instances
sharing the same memory. Moreover, the nodes representing the
WasmContext variables are cached in the SSA environment, similarly to
other local variables that might change during execution. The nodes are
created when initializing the SSA environment and refreshed every time a
grow_memory or a function call happens, so that we are sure that they
always represent the correct mem_size and mem_start variables.
This CL also removes the WasmMemorySize runtime (since it's now possible
to directly retrieve mem_size from the context) and simplifies the
GrowMemory runtime (since every instance now has a memory_object).
R=ahaas@chromium.org,clemensh@chromium.org
CC=gdeepti@chromium.org
Change-Id: I3f058e641284f5a1bbbfc35a64c88da6ff08e240
Reviewed-on: https://chromium-review.googlesource.com/671008
Commit-Queue: Enrico Bacis <enricobacis@google.com>
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48209}
2017-09-28 14:59:37 +00:00
|
|
|
IsReturn(IsCall(testing::_, IsInt32Constant(function), context_address,
|
2016-02-23 15:33:06 +00:00
|
|
|
IsInt32Constant(low_word_value(0)),
|
|
|
|
IsInt32Constant(high_word_value(0)),
|
|
|
|
IsInt32Constant(low_word_value(1)),
|
|
|
|
IsInt32Constant(low_word_value(2)),
|
|
|
|
IsInt32Constant(high_word_value(2)), start(), start()),
|
|
|
|
start(), start()));
|
|
|
|
|
2018-02-09 19:19:25 +00:00
|
|
|
CompareCallDescriptors(
|
2018-03-21 16:21:56 +00:00
|
|
|
CallDescriptorOf(graph()->end()->InputAt(1)->InputAt(1)->op()),
|
2018-02-09 19:19:25 +00:00
|
|
|
compiler::GetI32WasmCallDescriptor(zone(), call_descriptor));
|
2016-02-23 15:33:06 +00:00
|
|
|
}
|
|
|
|
|
2016-03-14 15:33:15 +00:00
|
|
|
TEST_F(Int64LoweringTest, Int64Add) {
|
|
|
|
LowerGraph(graph()->NewNode(machine()->Int64Add(), Int64Constant(value(0)),
|
|
|
|
Int64Constant(value(1))),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
|
|
|
|
Capture<Node*> add;
|
|
|
|
Matcher<Node*> add_matcher = IsInt32PairAdd(
|
|
|
|
IsInt32Constant(low_word_value(0)), IsInt32Constant(high_word_value(0)),
|
|
|
|
IsInt32Constant(low_word_value(1)), IsInt32Constant(high_word_value(1)));
|
|
|
|
|
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsProjection(0, AllOf(CaptureEq(&add), add_matcher)),
|
|
|
|
IsProjection(1, AllOf(CaptureEq(&add), add_matcher)),
|
|
|
|
start(), start()));
|
|
|
|
}
|
[wasm] Introduce the WasmContext
The WasmContext struct introduced in this CL is used to store the
mem_size and mem_start address of the wasm memory. These variables can
be accessed at C++ level at graph build time (e.g., initialized during
instance building). When the GrowMemory runtime is invoked, the context
variables can be changed in the WasmContext at C++ level so that the
generated code will load the correct values.
This requires to insert a relocatable pointer only in the
JSToWasmWrapper (and in the other wasm entry points), the value is then
passed from function to function as an automatically added additional
parameter. The WasmContext is then dropped when creating an Interpreter
Entry or when invoking a JavaScript function. This removes the need of
patching the generated code at runtime (i.e., when the memory grows)
with respect to WASM_MEMORY_REFERENCE and WASM_MEMORY_SIZE_REFERENCE.
However, we still need to patch the code at instance build time to patch
the JSToWasmWrappers; in fact the address of the WasmContext is not
known during compilation, but only when the instance is built.
The WasmContext address is passed as the first parameter. This has the
advantage of not having to move the WasmContext around if the function
does not use many registers. This CL also changes the wasm calling
convention so that the first parameter register is different from the
return value register. The WasmContext is attached to every
WasmMemoryObject, to share the same context with multiple instances
sharing the same memory. Moreover, the nodes representing the
WasmContext variables are cached in the SSA environment, similarly to
other local variables that might change during execution. The nodes are
created when initializing the SSA environment and refreshed every time a
grow_memory or a function call happens, so that we are sure that they
always represent the correct mem_size and mem_start variables.
This CL also removes the WasmMemorySize runtime (since it's now possible
to directly retrieve mem_size from the context) and simplifies the
GrowMemory runtime (since every instance now has a memory_object).
R=ahaas@chromium.org,clemensh@chromium.org
CC=gdeepti@chromium.org
Change-Id: I3f058e641284f5a1bbbfc35a64c88da6ff08e240
Reviewed-on: https://chromium-review.googlesource.com/671008
Commit-Queue: Enrico Bacis <enricobacis@google.com>
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48209}
2017-09-28 14:59:37 +00:00
|
|
|
#endif
|
2016-05-03 11:46:38 +00:00
|
|
|
|
2016-03-16 10:56:29 +00:00
|
|
|
TEST_F(Int64LoweringTest, Int64Sub) {
|
|
|
|
LowerGraph(graph()->NewNode(machine()->Int64Sub(), Int64Constant(value(0)),
|
|
|
|
Int64Constant(value(1))),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
|
|
|
|
Capture<Node*> sub;
|
|
|
|
Matcher<Node*> sub_matcher = IsInt32PairSub(
|
|
|
|
IsInt32Constant(low_word_value(0)), IsInt32Constant(high_word_value(0)),
|
|
|
|
IsInt32Constant(low_word_value(1)), IsInt32Constant(high_word_value(1)));
|
|
|
|
|
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsProjection(0, AllOf(CaptureEq(&sub), sub_matcher)),
|
|
|
|
IsProjection(1, AllOf(CaptureEq(&sub), sub_matcher)),
|
|
|
|
start(), start()));
|
|
|
|
}
|
|
|
|
|
2016-03-30 10:39:04 +00:00
|
|
|
TEST_F(Int64LoweringTest, Int64Mul) {
|
|
|
|
LowerGraph(graph()->NewNode(machine()->Int64Mul(), Int64Constant(value(0)),
|
|
|
|
Int64Constant(value(1))),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
|
|
|
|
Capture<Node*> mul_capture;
|
|
|
|
Matcher<Node*> mul_matcher = IsInt32PairMul(
|
|
|
|
IsInt32Constant(low_word_value(0)), IsInt32Constant(high_word_value(0)),
|
|
|
|
IsInt32Constant(low_word_value(1)), IsInt32Constant(high_word_value(1)));
|
|
|
|
|
|
|
|
EXPECT_THAT(
|
|
|
|
graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsProjection(0, AllOf(CaptureEq(&mul_capture), mul_matcher)),
|
|
|
|
IsProjection(1, AllOf(CaptureEq(&mul_capture), mul_matcher)),
|
|
|
|
start(), start()));
|
|
|
|
}
|
|
|
|
|
2016-02-23 16:30:27 +00:00
|
|
|
TEST_F(Int64LoweringTest, Int64Ior) {
|
|
|
|
LowerGraph(graph()->NewNode(machine()->Word64Or(), Int64Constant(value(0)),
|
|
|
|
Int64Constant(value(1))),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsWord32Or(IsInt32Constant(low_word_value(0)),
|
|
|
|
IsInt32Constant(low_word_value(1))),
|
|
|
|
IsWord32Or(IsInt32Constant(high_word_value(0)),
|
|
|
|
IsInt32Constant(high_word_value(1))),
|
|
|
|
start(), start()));
|
|
|
|
}
|
|
|
|
|
2016-02-24 09:51:30 +00:00
|
|
|
TEST_F(Int64LoweringTest, Int64Xor) {
|
|
|
|
LowerGraph(graph()->NewNode(machine()->Word64Xor(), Int64Constant(value(0)),
|
|
|
|
Int64Constant(value(1))),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsWord32Xor(IsInt32Constant(low_word_value(0)),
|
|
|
|
IsInt32Constant(low_word_value(1))),
|
|
|
|
IsWord32Xor(IsInt32Constant(high_word_value(0)),
|
|
|
|
IsInt32Constant(high_word_value(1))),
|
|
|
|
start(), start()));
|
|
|
|
}
|
2016-05-03 11:46:38 +00:00
|
|
|
|
2016-03-07 15:17:54 +00:00
|
|
|
TEST_F(Int64LoweringTest, Int64Shl) {
|
|
|
|
LowerGraph(graph()->NewNode(machine()->Word64Shl(), Int64Constant(value(0)),
|
|
|
|
Int64Constant(value(1))),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
|
|
|
|
Capture<Node*> shl;
|
|
|
|
Matcher<Node*> shl_matcher = IsWord32PairShl(
|
|
|
|
IsInt32Constant(low_word_value(0)), IsInt32Constant(high_word_value(0)),
|
|
|
|
IsInt32Constant(low_word_value(1)));
|
|
|
|
|
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsProjection(0, AllOf(CaptureEq(&shl), shl_matcher)),
|
|
|
|
IsProjection(1, AllOf(CaptureEq(&shl), shl_matcher)),
|
|
|
|
start(), start()));
|
|
|
|
}
|
2016-05-03 11:46:38 +00:00
|
|
|
|
2016-03-09 16:37:29 +00:00
|
|
|
TEST_F(Int64LoweringTest, Int64ShrU) {
|
|
|
|
LowerGraph(graph()->NewNode(machine()->Word64Shr(), Int64Constant(value(0)),
|
|
|
|
Int64Constant(value(1))),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
|
|
|
|
Capture<Node*> shr;
|
|
|
|
Matcher<Node*> shr_matcher = IsWord32PairShr(
|
|
|
|
IsInt32Constant(low_word_value(0)), IsInt32Constant(high_word_value(0)),
|
|
|
|
IsInt32Constant(low_word_value(1)));
|
|
|
|
|
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsProjection(0, AllOf(CaptureEq(&shr), shr_matcher)),
|
|
|
|
IsProjection(1, AllOf(CaptureEq(&shr), shr_matcher)),
|
|
|
|
start(), start()));
|
|
|
|
}
|
2016-05-03 11:46:38 +00:00
|
|
|
|
2016-03-09 16:37:29 +00:00
|
|
|
TEST_F(Int64LoweringTest, Int64ShrS) {
|
|
|
|
LowerGraph(graph()->NewNode(machine()->Word64Sar(), Int64Constant(value(0)),
|
|
|
|
Int64Constant(value(1))),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
|
|
|
|
Capture<Node*> sar;
|
|
|
|
Matcher<Node*> sar_matcher = IsWord32PairSar(
|
|
|
|
IsInt32Constant(low_word_value(0)), IsInt32Constant(high_word_value(0)),
|
|
|
|
IsInt32Constant(low_word_value(1)));
|
|
|
|
|
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsProjection(0, AllOf(CaptureEq(&sar), sar_matcher)),
|
|
|
|
IsProjection(1, AllOf(CaptureEq(&sar), sar_matcher)),
|
|
|
|
start(), start()));
|
|
|
|
}
|
2016-05-03 11:46:38 +00:00
|
|
|
|
2016-02-24 12:09:19 +00:00
|
|
|
TEST_F(Int64LoweringTest, Int64Eq) {
|
|
|
|
LowerGraph(graph()->NewNode(machine()->Word64Equal(), Int64Constant(value(0)),
|
|
|
|
Int64Constant(value(1))),
|
|
|
|
MachineRepresentation::kWord32);
|
|
|
|
EXPECT_THAT(
|
|
|
|
graph()->end()->InputAt(1),
|
|
|
|
IsReturn(IsWord32Equal(
|
|
|
|
IsWord32Or(IsWord32Xor(IsInt32Constant(low_word_value(0)),
|
|
|
|
IsInt32Constant(low_word_value(1))),
|
|
|
|
IsWord32Xor(IsInt32Constant(high_word_value(0)),
|
|
|
|
IsInt32Constant(high_word_value(1)))),
|
|
|
|
IsInt32Constant(0)),
|
|
|
|
start(), start()));
|
|
|
|
}
|
|
|
|
|
2016-02-25 12:14:35 +00:00
|
|
|
TEST_F(Int64LoweringTest, Int64LtS) {
|
|
|
|
TestComparison(machine()->Int64LessThan(), IsInt32LessThan, IsUint32LessThan);
|
|
|
|
}
|
2016-05-03 11:46:38 +00:00
|
|
|
|
2016-02-25 12:14:35 +00:00
|
|
|
TEST_F(Int64LoweringTest, Int64LeS) {
|
|
|
|
TestComparison(machine()->Int64LessThanOrEqual(), IsInt32LessThan,
|
|
|
|
IsUint32LessThanOrEqual);
|
|
|
|
}
|
2016-05-03 11:46:38 +00:00
|
|
|
|
2016-02-25 12:14:35 +00:00
|
|
|
TEST_F(Int64LoweringTest, Int64LtU) {
|
|
|
|
TestComparison(machine()->Uint64LessThan(), IsUint32LessThan,
|
|
|
|
IsUint32LessThan);
|
|
|
|
}
|
2016-05-03 11:46:38 +00:00
|
|
|
|
2016-02-25 12:14:35 +00:00
|
|
|
TEST_F(Int64LoweringTest, Int64LeU) {
|
|
|
|
TestComparison(machine()->Uint64LessThanOrEqual(), IsUint32LessThan,
|
|
|
|
IsUint32LessThanOrEqual);
|
|
|
|
}
|
2016-02-23 16:30:27 +00:00
|
|
|
|
2016-03-08 14:11:50 +00:00
|
|
|
TEST_F(Int64LoweringTest, I32ConvertI64) {
|
|
|
|
LowerGraph(graph()->NewNode(machine()->TruncateInt64ToInt32(),
|
|
|
|
Int64Constant(value(0))),
|
|
|
|
MachineRepresentation::kWord32);
|
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
|
|
|
IsReturn(IsInt32Constant(low_word_value(0)), start(), start()));
|
|
|
|
}
|
2016-05-03 11:46:38 +00:00
|
|
|
|
2016-03-09 16:20:59 +00:00
|
|
|
TEST_F(Int64LoweringTest, I64SConvertI32) {
|
|
|
|
LowerGraph(graph()->NewNode(machine()->ChangeInt32ToInt64(),
|
|
|
|
Int32Constant(low_word_value(0))),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
|
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsInt32Constant(low_word_value(0)),
|
|
|
|
IsWord32Sar(IsInt32Constant(low_word_value(0)),
|
|
|
|
IsInt32Constant(31)),
|
|
|
|
start(), start()));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, I64SConvertI32_2) {
|
|
|
|
LowerGraph(
|
|
|
|
graph()->NewNode(machine()->ChangeInt32ToInt64(),
|
|
|
|
graph()->NewNode(machine()->TruncateInt64ToInt32(),
|
|
|
|
Int64Constant(value(0)))),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
|
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsInt32Constant(low_word_value(0)),
|
|
|
|
IsWord32Sar(IsInt32Constant(low_word_value(0)),
|
|
|
|
IsInt32Constant(31)),
|
|
|
|
start(), start()));
|
|
|
|
}
|
2016-05-03 11:46:38 +00:00
|
|
|
|
2016-03-09 16:20:59 +00:00
|
|
|
TEST_F(Int64LoweringTest, I64UConvertI32) {
|
|
|
|
LowerGraph(graph()->NewNode(machine()->ChangeUint32ToUint64(),
|
|
|
|
Int32Constant(low_word_value(0))),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
|
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsInt32Constant(low_word_value(0)), IsInt32Constant(0),
|
|
|
|
start(), start()));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, I64UConvertI32_2) {
|
|
|
|
LowerGraph(
|
|
|
|
graph()->NewNode(machine()->ChangeUint32ToUint64(),
|
|
|
|
graph()->NewNode(machine()->TruncateInt64ToInt32(),
|
|
|
|
Int64Constant(value(0)))),
|
|
|
|
MachineRepresentation::kWord64);
|
2016-02-23 16:30:27 +00:00
|
|
|
|
2016-03-09 16:20:59 +00:00
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsInt32Constant(low_word_value(0)), IsInt32Constant(0),
|
|
|
|
start(), start()));
|
|
|
|
}
|
2016-05-03 11:46:38 +00:00
|
|
|
|
2016-03-15 12:45:43 +00:00
|
|
|
TEST_F(Int64LoweringTest, F64ReinterpretI64) {
|
|
|
|
LowerGraph(graph()->NewNode(machine()->BitcastInt64ToFloat64(),
|
|
|
|
Int64Constant(value(0))),
|
|
|
|
MachineRepresentation::kFloat64);
|
|
|
|
|
|
|
|
Capture<Node*> stack_slot_capture;
|
2017-05-16 12:27:56 +00:00
|
|
|
Matcher<Node*> stack_slot_matcher =
|
|
|
|
IsStackSlot(StackSlotRepresentation(sizeof(int64_t), 0));
|
2016-03-15 12:45:43 +00:00
|
|
|
|
|
|
|
Capture<Node*> store_capture;
|
|
|
|
Matcher<Node*> store_matcher =
|
|
|
|
IsStore(StoreRepresentation(MachineRepresentation::kWord32,
|
|
|
|
WriteBarrierKind::kNoWriteBarrier),
|
|
|
|
AllOf(CaptureEq(&stack_slot_capture), stack_slot_matcher),
|
2017-03-07 18:03:08 +00:00
|
|
|
IsInt32Constant(kInt64LowerHalfMemoryOffset),
|
2016-06-23 11:40:16 +00:00
|
|
|
IsInt32Constant(low_word_value(0)),
|
2016-03-15 12:45:43 +00:00
|
|
|
IsStore(StoreRepresentation(MachineRepresentation::kWord32,
|
|
|
|
WriteBarrierKind::kNoWriteBarrier),
|
|
|
|
AllOf(CaptureEq(&stack_slot_capture), stack_slot_matcher),
|
2017-03-07 18:03:08 +00:00
|
|
|
IsInt32Constant(kInt64UpperHalfMemoryOffset),
|
2016-06-23 11:40:16 +00:00
|
|
|
IsInt32Constant(high_word_value(0)), start(), start()),
|
2016-03-15 12:45:43 +00:00
|
|
|
start());
|
|
|
|
|
|
|
|
EXPECT_THAT(
|
|
|
|
graph()->end()->InputAt(1),
|
|
|
|
IsReturn(IsLoad(MachineType::Float64(),
|
|
|
|
AllOf(CaptureEq(&stack_slot_capture), stack_slot_matcher),
|
|
|
|
IsInt32Constant(0),
|
|
|
|
AllOf(CaptureEq(&store_capture), store_matcher), start()),
|
|
|
|
start(), start()));
|
|
|
|
}
|
2016-05-03 11:46:38 +00:00
|
|
|
|
2016-03-15 12:17:09 +00:00
|
|
|
TEST_F(Int64LoweringTest, I64ReinterpretF64) {
|
|
|
|
LowerGraph(graph()->NewNode(machine()->BitcastFloat64ToInt64(),
|
|
|
|
Float64Constant(bit_cast<double>(value(0)))),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
|
|
|
|
Capture<Node*> stack_slot;
|
2017-05-16 12:27:56 +00:00
|
|
|
Matcher<Node*> stack_slot_matcher =
|
|
|
|
IsStackSlot(StackSlotRepresentation(sizeof(int64_t), 0));
|
2016-02-23 16:30:27 +00:00
|
|
|
|
2016-03-15 12:17:09 +00:00
|
|
|
Capture<Node*> store;
|
|
|
|
Matcher<Node*> store_matcher = IsStore(
|
|
|
|
StoreRepresentation(MachineRepresentation::kFloat64,
|
|
|
|
WriteBarrierKind::kNoWriteBarrier),
|
|
|
|
AllOf(CaptureEq(&stack_slot), stack_slot_matcher), IsInt32Constant(0),
|
|
|
|
IsFloat64Constant(bit_cast<double>(value(0))), start(), start());
|
|
|
|
|
|
|
|
EXPECT_THAT(
|
|
|
|
graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsLoad(MachineType::Int32(),
|
|
|
|
AllOf(CaptureEq(&stack_slot), stack_slot_matcher),
|
2017-03-07 18:03:08 +00:00
|
|
|
IsInt32Constant(kInt64LowerHalfMemoryOffset),
|
2016-03-15 12:17:09 +00:00
|
|
|
AllOf(CaptureEq(&store), store_matcher), start()),
|
|
|
|
IsLoad(MachineType::Int32(),
|
|
|
|
AllOf(CaptureEq(&stack_slot), stack_slot_matcher),
|
2017-03-07 18:03:08 +00:00
|
|
|
IsInt32Constant(kInt64UpperHalfMemoryOffset),
|
2016-03-15 12:17:09 +00:00
|
|
|
AllOf(CaptureEq(&store), store_matcher), start()),
|
|
|
|
start(), start()));
|
|
|
|
}
|
2016-05-03 11:46:38 +00:00
|
|
|
|
2016-03-16 11:02:28 +00:00
|
|
|
TEST_F(Int64LoweringTest, I64Clz) {
|
|
|
|
LowerGraph(graph()->NewNode(machine()->Word64Clz(), Int64Constant(value(0))),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
|
|
|
|
Capture<Node*> branch_capture;
|
|
|
|
Matcher<Node*> branch_matcher = IsBranch(
|
|
|
|
IsWord32Equal(IsInt32Constant(high_word_value(0)), IsInt32Constant(0)),
|
|
|
|
start());
|
|
|
|
|
|
|
|
EXPECT_THAT(
|
|
|
|
graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(
|
|
|
|
IsPhi(MachineRepresentation::kWord32,
|
|
|
|
IsInt32Add(IsWord32Clz(IsInt32Constant(low_word_value(0))),
|
|
|
|
IsInt32Constant(32)),
|
|
|
|
IsWord32Clz(IsInt32Constant(high_word_value(0))),
|
|
|
|
IsMerge(
|
|
|
|
IsIfTrue(AllOf(CaptureEq(&branch_capture), branch_matcher)),
|
|
|
|
IsIfFalse(
|
|
|
|
AllOf(CaptureEq(&branch_capture), branch_matcher)))),
|
|
|
|
IsInt32Constant(0), start(), start()));
|
|
|
|
}
|
2016-05-03 11:46:38 +00:00
|
|
|
|
2016-03-16 12:14:44 +00:00
|
|
|
TEST_F(Int64LoweringTest, I64Ctz) {
|
2016-06-30 14:16:43 +00:00
|
|
|
LowerGraph(graph()->NewNode(machine()->Word64Ctz().placeholder(),
|
2016-03-16 12:14:44 +00:00
|
|
|
Int64Constant(value(0))),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
Capture<Node*> branch_capture;
|
|
|
|
Matcher<Node*> branch_matcher = IsBranch(
|
|
|
|
IsWord32Equal(IsInt32Constant(low_word_value(0)), IsInt32Constant(0)),
|
|
|
|
start());
|
|
|
|
EXPECT_THAT(
|
|
|
|
graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(
|
|
|
|
IsPhi(MachineRepresentation::kWord32,
|
|
|
|
IsInt32Add(IsWord32Ctz(IsInt32Constant(high_word_value(0))),
|
|
|
|
IsInt32Constant(32)),
|
|
|
|
IsWord32Ctz(IsInt32Constant(low_word_value(0))),
|
|
|
|
IsMerge(
|
|
|
|
IsIfTrue(AllOf(CaptureEq(&branch_capture), branch_matcher)),
|
|
|
|
IsIfFalse(
|
|
|
|
AllOf(CaptureEq(&branch_capture), branch_matcher)))),
|
|
|
|
IsInt32Constant(0), start(), start()));
|
|
|
|
}
|
2016-03-15 06:26:23 +00:00
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, Dfs) {
|
|
|
|
Node* common = Int64Constant(value(0));
|
|
|
|
LowerGraph(graph()->NewNode(machine()->Word64And(), common,
|
|
|
|
graph()->NewNode(machine()->Word64And(), common,
|
|
|
|
Int64Constant(value(1)))),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
|
|
|
|
EXPECT_THAT(
|
|
|
|
graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsWord32And(IsInt32Constant(low_word_value(0)),
|
|
|
|
IsWord32And(IsInt32Constant(low_word_value(0)),
|
|
|
|
IsInt32Constant(low_word_value(1)))),
|
|
|
|
IsWord32And(IsInt32Constant(high_word_value(0)),
|
|
|
|
IsWord32And(IsInt32Constant(high_word_value(0)),
|
|
|
|
IsInt32Constant(high_word_value(1)))),
|
|
|
|
start(), start()));
|
|
|
|
}
|
2016-03-15 10:41:55 +00:00
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, I64Popcnt) {
|
2016-06-30 14:16:43 +00:00
|
|
|
LowerGraph(graph()->NewNode(machine()->Word64Popcnt().placeholder(),
|
2016-03-15 10:41:55 +00:00
|
|
|
Int64Constant(value(0))),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
|
|
|
|
EXPECT_THAT(
|
|
|
|
graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsInt32Add(IsWord32Popcnt(IsInt32Constant(low_word_value(0))),
|
|
|
|
IsWord32Popcnt(IsInt32Constant(high_word_value(0)))),
|
|
|
|
IsInt32Constant(0), start(), start()));
|
|
|
|
}
|
2016-03-30 08:13:50 +00:00
|
|
|
|
2016-03-31 17:04:51 +00:00
|
|
|
TEST_F(Int64LoweringTest, I64Ror) {
|
|
|
|
LowerGraph(graph()->NewNode(machine()->Word64Ror(), Int64Constant(value(0)),
|
|
|
|
Parameter(0)),
|
|
|
|
MachineRepresentation::kWord64, MachineRepresentation::kWord64, 1);
|
|
|
|
|
|
|
|
Matcher<Node*> branch_lt32_matcher =
|
|
|
|
IsBranch(IsInt32LessThan(IsParameter(0), IsInt32Constant(32)), start());
|
|
|
|
|
|
|
|
Matcher<Node*> low_input_matcher = IsPhi(
|
|
|
|
MachineRepresentation::kWord32, IsInt32Constant(low_word_value(0)),
|
|
|
|
IsInt32Constant(high_word_value(0)),
|
|
|
|
IsMerge(IsIfTrue(branch_lt32_matcher), IsIfFalse(branch_lt32_matcher)));
|
|
|
|
|
|
|
|
Matcher<Node*> high_input_matcher = IsPhi(
|
|
|
|
MachineRepresentation::kWord32, IsInt32Constant(high_word_value(0)),
|
|
|
|
IsInt32Constant(low_word_value(0)),
|
|
|
|
IsMerge(IsIfTrue(branch_lt32_matcher), IsIfFalse(branch_lt32_matcher)));
|
|
|
|
|
|
|
|
Matcher<Node*> shift_matcher =
|
2017-12-02 00:30:37 +00:00
|
|
|
IsWord32And(IsParameter(0), IsInt32Constant(0x1F));
|
2016-03-31 17:04:51 +00:00
|
|
|
|
|
|
|
Matcher<Node*> bit_mask_matcher = IsWord32Shl(
|
|
|
|
IsWord32Sar(IsInt32Constant(std::numeric_limits<int32_t>::min()),
|
|
|
|
shift_matcher),
|
|
|
|
IsInt32Constant(1));
|
|
|
|
|
|
|
|
Matcher<Node*> inv_mask_matcher =
|
|
|
|
IsWord32Xor(bit_mask_matcher, IsInt32Constant(-1));
|
|
|
|
|
|
|
|
EXPECT_THAT(
|
|
|
|
graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(
|
|
|
|
IsWord32Or(IsWord32And(IsWord32Ror(low_input_matcher, shift_matcher),
|
|
|
|
inv_mask_matcher),
|
|
|
|
IsWord32And(IsWord32Ror(high_input_matcher, shift_matcher),
|
|
|
|
bit_mask_matcher)),
|
|
|
|
IsWord32Or(IsWord32And(IsWord32Ror(high_input_matcher, shift_matcher),
|
|
|
|
inv_mask_matcher),
|
|
|
|
IsWord32And(IsWord32Ror(low_input_matcher, shift_matcher),
|
|
|
|
bit_mask_matcher)),
|
|
|
|
start(), start()));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, I64Ror_0) {
|
|
|
|
LowerGraph(graph()->NewNode(machine()->Word64Ror(), Int64Constant(value(0)),
|
|
|
|
Int32Constant(0)),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
|
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsInt32Constant(low_word_value(0)),
|
|
|
|
IsInt32Constant(high_word_value(0)), start(), start()));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, I64Ror_32) {
|
|
|
|
LowerGraph(graph()->NewNode(machine()->Word64Ror(), Int64Constant(value(0)),
|
|
|
|
Int32Constant(32)),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
|
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsInt32Constant(high_word_value(0)),
|
|
|
|
IsInt32Constant(low_word_value(0)), start(), start()));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, I64Ror_11) {
|
|
|
|
LowerGraph(graph()->NewNode(machine()->Word64Ror(), Int64Constant(value(0)),
|
|
|
|
Int32Constant(11)),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
|
|
|
|
EXPECT_THAT(
|
|
|
|
graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsWord32Or(IsWord32Shr(IsInt32Constant(low_word_value(0)),
|
|
|
|
IsInt32Constant(11)),
|
|
|
|
IsWord32Shl(IsInt32Constant(high_word_value(0)),
|
|
|
|
IsInt32Constant(21))),
|
|
|
|
IsWord32Or(IsWord32Shr(IsInt32Constant(high_word_value(0)),
|
|
|
|
IsInt32Constant(11)),
|
|
|
|
IsWord32Shl(IsInt32Constant(low_word_value(0)),
|
|
|
|
IsInt32Constant(21))),
|
|
|
|
start(), start()));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, I64Ror_43) {
|
|
|
|
LowerGraph(graph()->NewNode(machine()->Word64Ror(), Int64Constant(value(0)),
|
|
|
|
Int32Constant(43)),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
|
|
|
|
EXPECT_THAT(
|
|
|
|
graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsWord32Or(IsWord32Shr(IsInt32Constant(high_word_value(0)),
|
|
|
|
IsInt32Constant(11)),
|
|
|
|
IsWord32Shl(IsInt32Constant(low_word_value(0)),
|
|
|
|
IsInt32Constant(21))),
|
|
|
|
IsWord32Or(IsWord32Shr(IsInt32Constant(low_word_value(0)),
|
|
|
|
IsInt32Constant(11)),
|
|
|
|
IsWord32Shl(IsInt32Constant(high_word_value(0)),
|
|
|
|
IsInt32Constant(21))),
|
|
|
|
start(), start()));
|
|
|
|
}
|
|
|
|
|
2016-03-30 08:13:50 +00:00
|
|
|
TEST_F(Int64LoweringTest, I64PhiWord64) {
|
|
|
|
LowerGraph(graph()->NewNode(common()->Phi(MachineRepresentation::kWord64, 2),
|
|
|
|
Int64Constant(value(0)), Int64Constant(value(1)),
|
|
|
|
start()),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
|
|
|
|
EXPECT_THAT(graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsPhi(MachineRepresentation::kWord32,
|
|
|
|
IsInt32Constant(low_word_value(0)),
|
|
|
|
IsInt32Constant(low_word_value(1)), start()),
|
|
|
|
IsPhi(MachineRepresentation::kWord32,
|
|
|
|
IsInt32Constant(high_word_value(0)),
|
|
|
|
IsInt32Constant(high_word_value(1)), start()),
|
|
|
|
start(), start()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestPhi(Int64LoweringTest* test, MachineRepresentation rep, Node* v1,
|
|
|
|
Node* v2) {
|
|
|
|
test->LowerGraph(test->graph()->NewNode(test->common()->Phi(rep, 2), v1, v2,
|
|
|
|
test->start()),
|
|
|
|
rep);
|
|
|
|
|
|
|
|
EXPECT_THAT(test->graph()->end()->InputAt(1),
|
|
|
|
IsReturn(IsPhi(rep, v1, v2, test->start()), test->start(),
|
|
|
|
test->start()));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, I64PhiFloat32) {
|
|
|
|
TestPhi(this, MachineRepresentation::kFloat32, Float32Constant(1.5),
|
|
|
|
Float32Constant(2.5));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, I64PhiFloat64) {
|
|
|
|
TestPhi(this, MachineRepresentation::kFloat64, Float32Constant(1.5),
|
|
|
|
Float32Constant(2.5));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, I64PhiWord32) {
|
|
|
|
TestPhi(this, MachineRepresentation::kWord32, Float32Constant(1),
|
|
|
|
Float32Constant(2));
|
|
|
|
}
|
2016-07-29 19:31:54 +00:00
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, I64ReverseBytes) {
|
2018-08-14 08:39:05 +00:00
|
|
|
LowerGraph(graph()->NewNode(machine()->Word64ReverseBytes(),
|
2016-07-29 19:31:54 +00:00
|
|
|
Int64Constant(value(0))),
|
|
|
|
MachineRepresentation::kWord64);
|
|
|
|
EXPECT_THAT(
|
|
|
|
graph()->end()->InputAt(1),
|
|
|
|
IsReturn2(IsWord32ReverseBytes(IsInt32Constant(high_word_value(0))),
|
|
|
|
IsWord32ReverseBytes(IsInt32Constant(low_word_value(0))),
|
|
|
|
start(), start()));
|
|
|
|
}
|
2016-10-18 06:30:38 +00:00
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, EffectPhiLoop) {
|
|
|
|
// Construct a cycle consisting of an EffectPhi, a Store, and a Load.
|
|
|
|
Node* eff_phi = graph()->NewNode(common()->EffectPhi(1), graph()->start(),
|
|
|
|
graph()->start());
|
|
|
|
|
|
|
|
StoreRepresentation store_rep(MachineRepresentation::kWord64,
|
|
|
|
WriteBarrierKind::kNoWriteBarrier);
|
|
|
|
LoadRepresentation load_rep(MachineType::Int64());
|
|
|
|
|
|
|
|
Node* load =
|
|
|
|
graph()->NewNode(machine()->Load(load_rep), Int64Constant(value(0)),
|
|
|
|
Int64Constant(value(1)), eff_phi, graph()->start());
|
|
|
|
|
|
|
|
Node* store =
|
|
|
|
graph()->NewNode(machine()->Store(store_rep), Int64Constant(value(0)),
|
|
|
|
Int64Constant(value(1)), load, load, graph()->start());
|
|
|
|
|
|
|
|
eff_phi->InsertInput(zone(), 1, store);
|
|
|
|
NodeProperties::ChangeOp(eff_phi,
|
|
|
|
common()->ResizeMergeOrPhi(eff_phi->op(), 2));
|
|
|
|
|
|
|
|
LowerGraph(load, MachineRepresentation::kWord64);
|
|
|
|
}
|
2016-11-17 11:50:37 +00:00
|
|
|
|
|
|
|
TEST_F(Int64LoweringTest, LoopCycle) {
|
|
|
|
// New node with two placeholders.
|
|
|
|
Node* compare = graph()->NewNode(machine()->Word64Equal(), Int64Constant(0),
|
|
|
|
Int64Constant(value(0)));
|
|
|
|
|
|
|
|
Node* load = graph()->NewNode(
|
|
|
|
machine()->Load(MachineType::Int64()), Int64Constant(value(1)),
|
|
|
|
Int64Constant(value(2)), graph()->start(),
|
|
|
|
graph()->NewNode(
|
|
|
|
common()->Loop(2), graph()->start(),
|
|
|
|
graph()->NewNode(common()->IfFalse(),
|
|
|
|
graph()->NewNode(common()->Branch(), compare,
|
|
|
|
graph()->start()))));
|
|
|
|
|
|
|
|
NodeProperties::ReplaceValueInput(compare, load, 0);
|
|
|
|
|
|
|
|
LowerGraph(load, MachineRepresentation::kWord64);
|
|
|
|
}
|
2016-02-23 15:33:06 +00:00
|
|
|
} // namespace compiler
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|