blob: b56721e95073288b2981477835406e2f11c206e7 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <limits>
6
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007#include "src/ast/scopes.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include "src/compiler/access-builder.h"
9#include "src/compiler/control-builders.h"
Ben Murdochc5610432016-08-08 18:44:38 +010010#include "src/compiler/effect-control-linearizer.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011#include "src/compiler/graph-visualizer.h"
Ben Murdochc5610432016-08-08 18:44:38 +010012#include "src/compiler/memory-optimizer.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013#include "src/compiler/node-properties.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014#include "src/compiler/pipeline.h"
15#include "src/compiler/representation-change.h"
Ben Murdochc5610432016-08-08 18:44:38 +010016#include "src/compiler/scheduler.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017#include "src/compiler/simplified-lowering.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018#include "src/compiler/source-position.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019#include "src/compiler/typer.h"
20#include "src/compiler/verifier.h"
21#include "src/execution.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022#include "src/parsing/parser.h"
23#include "src/parsing/rewriter.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024#include "test/cctest/cctest.h"
25#include "test/cctest/compiler/codegen-tester.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000026#include "test/cctest/compiler/function-tester.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000027#include "test/cctest/compiler/graph-builder-tester.h"
28#include "test/cctest/compiler/value-helper.h"
29
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000030namespace v8 {
31namespace internal {
32namespace compiler {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000033
34template <typename ReturnType>
35class SimplifiedLoweringTester : public GraphBuilderTester<ReturnType> {
36 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000037 SimplifiedLoweringTester(MachineType p0 = MachineType::None(),
38 MachineType p1 = MachineType::None())
39 : GraphBuilderTester<ReturnType>(p0, p1),
40 typer(this->isolate(), this->graph()),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000041 javascript(this->zone()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000042 jsgraph(this->isolate(), this->graph(), this->common(), &javascript,
43 this->simplified(), this->machine()),
44 source_positions(jsgraph.graph()),
45 lowering(&jsgraph, this->zone(), &source_positions) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000046
47 Typer typer;
48 JSOperatorBuilder javascript;
49 JSGraph jsgraph;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000050 SourcePositionTable source_positions;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000051 SimplifiedLowering lowering;
52
53 void LowerAllNodes() {
54 this->End();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040055 typer.Run();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000056 lowering.LowerAllNodes();
57 }
58
Emily Bernierd0a1eb72015-03-24 16:35:39 -040059 void LowerAllNodesAndLowerChanges() {
60 this->End();
61 typer.Run();
62 lowering.LowerAllNodes();
63
Ben Murdochc5610432016-08-08 18:44:38 +010064 Schedule* schedule = Scheduler::ComputeSchedule(this->zone(), this->graph(),
65 Scheduler::kNoFlags);
66 EffectControlLinearizer linearizer(&jsgraph, schedule, this->zone());
67 linearizer.Run();
68
69 MemoryOptimizer memory_optimizer(&jsgraph, this->zone());
70 memory_optimizer.Optimize();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040071 }
72
73 void CheckNumberCall(double expected, double input) {
74 // TODO(titzer): make calls to NewNumber work in cctests.
75 if (expected <= Smi::kMinValue) return;
76 if (expected >= Smi::kMaxValue) return;
77 Handle<Object> num = factory()->NewNumber(input);
78 Object* result = this->Call(*num);
79 CHECK(factory()->NewNumber(expected)->SameValue(result));
80 }
81
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000082 template <typename T>
83 T* CallWithPotentialGC() {
84 // TODO(titzer): we wrap the code in a JSFunction here to reuse the
85 // JSEntryStub; that could be done with a special prologue or other stub.
86 Handle<JSFunction> fun = FunctionTester::ForMachineGraph(this->graph(), 0);
87 Handle<Object>* args = NULL;
88 MaybeHandle<Object> result = Execution::Call(
89 this->isolate(), fun, factory()->undefined_value(), 0, args);
90 return T::cast(*result.ToHandleChecked());
91 }
92
Ben Murdochb8a8cc12014-11-26 15:28:44 +000093 Factory* factory() { return this->isolate()->factory(); }
94 Heap* heap() { return this->isolate()->heap(); }
95};
96
97
Ben Murdochb8a8cc12014-11-26 15:28:44 +000098// TODO(titzer): factor these tests out to test-run-simplifiedops.cc.
99// TODO(titzer): test tagged representation for input to NumberToInt32.
100TEST(RunNumberToInt32_float64) {
101 // TODO(titzer): explicit load/stores here are only because of representations
102 double input;
103 int32_t result;
104 SimplifiedLoweringTester<Object*> t;
Ben Murdochc5610432016-08-08 18:44:38 +0100105 FieldAccess load = {kUntaggedBase, 0,
106 Handle<Name>(), Type::Number(),
107 MachineType::Float64(), kNoWriteBarrier};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000108 Node* loaded = t.LoadField(load, t.PointerConstant(&input));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000109 NodeProperties::SetType(loaded, Type::Number());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000110 Node* convert = t.NumberToInt32(loaded);
Ben Murdochc5610432016-08-08 18:44:38 +0100111 FieldAccess store = {kUntaggedBase, 0,
112 Handle<Name>(), Type::Signed32(),
113 MachineType::Int32(), kNoWriteBarrier};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000114 t.StoreField(store, t.PointerConstant(&result), convert);
115 t.Return(t.jsgraph.TrueConstant());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000116 t.LowerAllNodesAndLowerChanges();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000117 t.GenerateCode();
118
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000119 FOR_FLOAT64_INPUTS(i) {
120 input = *i;
121 int32_t expected = DoubleToInt32(*i);
122 t.Call();
123 CHECK_EQ(expected, result);
124 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000125}
126
127
128// TODO(titzer): test tagged representation for input to NumberToUint32.
129TEST(RunNumberToUint32_float64) {
130 // TODO(titzer): explicit load/stores here are only because of representations
131 double input;
132 uint32_t result;
133 SimplifiedLoweringTester<Object*> t;
Ben Murdochc5610432016-08-08 18:44:38 +0100134 FieldAccess load = {kUntaggedBase, 0,
135 Handle<Name>(), Type::Number(),
136 MachineType::Float64(), kNoWriteBarrier};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000137 Node* loaded = t.LoadField(load, t.PointerConstant(&input));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000138 NodeProperties::SetType(loaded, Type::Number());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000139 Node* convert = t.NumberToUint32(loaded);
Ben Murdochc5610432016-08-08 18:44:38 +0100140 FieldAccess store = {kUntaggedBase, 0,
141 Handle<Name>(), Type::Unsigned32(),
142 MachineType::Uint32(), kNoWriteBarrier};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000143 t.StoreField(store, t.PointerConstant(&result), convert);
144 t.Return(t.jsgraph.TrueConstant());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000145 t.LowerAllNodesAndLowerChanges();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000146 t.GenerateCode();
147
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000148 FOR_FLOAT64_INPUTS(i) {
149 input = *i;
150 uint32_t expected = DoubleToUint32(*i);
151 t.Call();
152 CHECK_EQ(static_cast<int32_t>(expected), static_cast<int32_t>(result));
153 }
154 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000155
156
157// Create a simple JSObject with a unique map.
158static Handle<JSObject> TestObject() {
159 static int index = 0;
160 char buffer[50];
161 v8::base::OS::SNPrintF(buffer, 50, "({'a_%d':1})", index++);
162 return Handle<JSObject>::cast(v8::Utils::OpenHandle(*CompileRun(buffer)));
163}
164
165
166TEST(RunLoadMap) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000167 SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000168 FieldAccess access = AccessBuilder::ForMap();
169 Node* load = t.LoadField(access, t.Parameter(0));
170 t.Return(load);
171
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000172 t.LowerAllNodesAndLowerChanges();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000173 t.GenerateCode();
174
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000175 Handle<JSObject> src = TestObject();
176 Handle<Map> src_map(src->map());
177 Object* result = t.Call(*src); // TODO(titzer): raw pointers in call
178 CHECK_EQ(*src_map, result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000179}
180
181
182TEST(RunStoreMap) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000183 SimplifiedLoweringTester<int32_t> t(MachineType::AnyTagged(),
184 MachineType::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000185 FieldAccess access = AccessBuilder::ForMap();
186 t.StoreField(access, t.Parameter(1), t.Parameter(0));
187 t.Return(t.jsgraph.TrueConstant());
188
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000189 t.LowerAllNodesAndLowerChanges();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000190 t.GenerateCode();
191
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192 Handle<JSObject> src = TestObject();
193 Handle<Map> src_map(src->map());
194 Handle<JSObject> dst = TestObject();
195 CHECK(src->map() != dst->map());
196 t.Call(*src_map, *dst); // TODO(titzer): raw pointers in call
197 CHECK(*src_map == dst->map());
198 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000199
200
201TEST(RunLoadProperties) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000202 SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000203 FieldAccess access = AccessBuilder::ForJSObjectProperties();
204 Node* load = t.LoadField(access, t.Parameter(0));
205 t.Return(load);
206
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000207 t.LowerAllNodesAndLowerChanges();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000208 t.GenerateCode();
209
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000210 Handle<JSObject> src = TestObject();
211 Handle<FixedArray> src_props(src->properties());
212 Object* result = t.Call(*src); // TODO(titzer): raw pointers in call
213 CHECK_EQ(*src_props, result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000214}
215
216
217TEST(RunLoadStoreMap) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000218 SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged(),
219 MachineType::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000220 FieldAccess access = AccessBuilder::ForMap();
221 Node* load = t.LoadField(access, t.Parameter(0));
222 t.StoreField(access, t.Parameter(1), load);
223 t.Return(load);
224
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000225 t.LowerAllNodesAndLowerChanges();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000226 t.GenerateCode();
227
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000228 Handle<JSObject> src = TestObject();
229 Handle<Map> src_map(src->map());
230 Handle<JSObject> dst = TestObject();
231 CHECK(src->map() != dst->map());
232 Object* result = t.Call(*src, *dst); // TODO(titzer): raw pointers in call
233 CHECK(result->IsMap());
234 CHECK_EQ(*src_map, result);
235 CHECK(*src_map == dst->map());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236}
237
238
239TEST(RunLoadStoreFixedArrayIndex) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240 SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000241 ElementAccess access = AccessBuilder::ForFixedArrayElement();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400242 Node* load = t.LoadElement(access, t.Parameter(0), t.Int32Constant(0));
243 t.StoreElement(access, t.Parameter(0), t.Int32Constant(1), load);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000244 t.Return(load);
245
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000246 t.LowerAllNodesAndLowerChanges();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000247 t.GenerateCode();
248
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000249 Handle<FixedArray> array = t.factory()->NewFixedArray(2);
250 Handle<JSObject> src = TestObject();
251 Handle<JSObject> dst = TestObject();
252 array->set(0, *src);
253 array->set(1, *dst);
254 Object* result = t.Call(*array);
255 CHECK_EQ(*src, result);
256 CHECK_EQ(*src, array->get(0));
257 CHECK_EQ(*src, array->get(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000258}
259
260
261TEST(RunLoadStoreArrayBuffer) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000262 SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000263 const int index = 12;
264 const int array_length = 2 * index;
265 ElementAccess buffer_access =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000266 AccessBuilder::ForTypedArrayElement(kExternalInt8Array, true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000267 Node* backing_store = t.LoadField(
268 AccessBuilder::ForJSArrayBufferBackingStore(), t.Parameter(0));
269 Node* load =
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400270 t.LoadElement(buffer_access, backing_store, t.Int32Constant(index));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000271 t.StoreElement(buffer_access, backing_store, t.Int32Constant(index + 1),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400272 load);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000273 t.Return(t.jsgraph.TrueConstant());
274
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000275 t.LowerAllNodesAndLowerChanges();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000276 t.GenerateCode();
277
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000278 Handle<JSArrayBuffer> array = t.factory()->NewJSArrayBuffer();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000279 JSArrayBuffer::SetupAllocatingData(array, t.isolate(), array_length);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000280 uint8_t* data = reinterpret_cast<uint8_t*>(array->backing_store());
281 for (int i = 0; i < array_length; i++) {
282 data[i] = i;
283 }
284
285 // TODO(titzer): raw pointers in call
286 Object* result = t.Call(*array);
287 CHECK_EQ(t.isolate()->heap()->true_value(), result);
288 for (int i = 0; i < array_length; i++) {
289 uint8_t expected = i;
290 if (i == (index + 1)) expected = index;
291 CHECK_EQ(data[i], expected);
292 }
293 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000294
295
296TEST(RunLoadFieldFromUntaggedBase) {
297 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3)};
298
299 for (size_t i = 0; i < arraysize(smis); i++) {
300 int offset = static_cast<int>(i * sizeof(Smi*));
Ben Murdochc5610432016-08-08 18:44:38 +0100301 FieldAccess access = {kUntaggedBase,
302 offset,
303 Handle<Name>(),
304 Type::Integral32(),
305 MachineType::AnyTagged(),
306 kNoWriteBarrier};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000307
308 SimplifiedLoweringTester<Object*> t;
309 Node* load = t.LoadField(access, t.PointerConstant(smis));
310 t.Return(load);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000311 t.LowerAllNodesAndLowerChanges();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000312
313 for (int j = -5; j <= 5; j++) {
314 Smi* expected = Smi::FromInt(j);
315 smis[i] = expected;
316 CHECK_EQ(expected, t.Call());
317 }
318 }
319}
320
321
322TEST(RunStoreFieldToUntaggedBase) {
323 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3)};
324
325 for (size_t i = 0; i < arraysize(smis); i++) {
326 int offset = static_cast<int>(i * sizeof(Smi*));
Ben Murdochc5610432016-08-08 18:44:38 +0100327 FieldAccess access = {kUntaggedBase,
328 offset,
329 Handle<Name>(),
330 Type::Integral32(),
331 MachineType::AnyTagged(),
332 kNoWriteBarrier};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000333
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000334 SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000335 Node* p0 = t.Parameter(0);
336 t.StoreField(access, t.PointerConstant(smis), p0);
337 t.Return(p0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000338 t.LowerAllNodesAndLowerChanges();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000339
340 for (int j = -5; j <= 5; j++) {
341 Smi* expected = Smi::FromInt(j);
342 smis[i] = Smi::FromInt(-100);
343 CHECK_EQ(expected, t.Call(expected));
344 CHECK_EQ(expected, smis[i]);
345 }
346 }
347}
348
349
350TEST(RunLoadElementFromUntaggedBase) {
351 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3),
352 Smi::FromInt(4), Smi::FromInt(5)};
353
354 for (size_t i = 0; i < arraysize(smis); i++) { // for header sizes
355 for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index
356 int offset = static_cast<int>(i * sizeof(Smi*));
357 ElementAccess access = {kUntaggedBase, offset, Type::Integral32(),
Ben Murdochc5610432016-08-08 18:44:38 +0100358 MachineType::AnyTagged(), kNoWriteBarrier};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000359
360 SimplifiedLoweringTester<Object*> t;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400361 Node* load = t.LoadElement(access, t.PointerConstant(smis),
362 t.Int32Constant(static_cast<int>(j)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000363 t.Return(load);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000364 t.LowerAllNodesAndLowerChanges();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000365
366 for (int k = -5; k <= 5; k++) {
367 Smi* expected = Smi::FromInt(k);
368 smis[i + j] = expected;
369 CHECK_EQ(expected, t.Call());
370 }
371 }
372 }
373}
374
375
376TEST(RunStoreElementFromUntaggedBase) {
377 Smi* smis[] = {Smi::FromInt(1), Smi::FromInt(2), Smi::FromInt(3),
378 Smi::FromInt(4), Smi::FromInt(5)};
379
380 for (size_t i = 0; i < arraysize(smis); i++) { // for header sizes
381 for (size_t j = 0; (i + j) < arraysize(smis); j++) { // for element index
382 int offset = static_cast<int>(i * sizeof(Smi*));
383 ElementAccess access = {kUntaggedBase, offset, Type::Integral32(),
Ben Murdochc5610432016-08-08 18:44:38 +0100384 MachineType::AnyTagged(), kNoWriteBarrier};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000385
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000386 SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000387 Node* p0 = t.Parameter(0);
388 t.StoreElement(access, t.PointerConstant(smis),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400389 t.Int32Constant(static_cast<int>(j)), p0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000390 t.Return(p0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000391 t.LowerAllNodesAndLowerChanges();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000392
393 for (int k = -5; k <= 5; k++) {
394 Smi* expected = Smi::FromInt(k);
395 smis[i + j] = Smi::FromInt(-100);
396 CHECK_EQ(expected, t.Call(expected));
397 CHECK_EQ(expected, smis[i + j]);
398 }
399
400 // TODO(titzer): assert the contents of the array.
401 }
402 }
403}
404
405
406// A helper class for accessing fields and elements of various types, on both
407// tagged and untagged base pointers. Contains both tagged and untagged buffers
408// for testing direct memory access from generated code.
409template <typename E>
410class AccessTester : public HandleAndZoneScope {
411 public:
412 bool tagged;
413 MachineType rep;
414 E* original_elements;
415 size_t num_elements;
416 E* untagged_array;
417 Handle<ByteArray> tagged_array; // TODO(titzer): use FixedArray for tagged.
418
419 AccessTester(bool t, MachineType r, E* orig, size_t num)
420 : tagged(t),
421 rep(r),
422 original_elements(orig),
423 num_elements(num),
424 untagged_array(static_cast<E*>(malloc(ByteSize()))),
425 tagged_array(main_isolate()->factory()->NewByteArray(
426 static_cast<int>(ByteSize()))) {
427 Reinitialize();
428 }
429
430 ~AccessTester() { free(untagged_array); }
431
432 size_t ByteSize() { return num_elements * sizeof(E); }
433
434 // Nuke both {untagged_array} and {tagged_array} with {original_elements}.
435 void Reinitialize() {
436 memcpy(untagged_array, original_elements, ByteSize());
437 CHECK_EQ(static_cast<int>(ByteSize()), tagged_array->length());
438 E* raw = reinterpret_cast<E*>(tagged_array->GetDataStartAddress());
439 memcpy(raw, original_elements, ByteSize());
440 }
441
442 // Create and run code that copies the element in either {untagged_array}
443 // or {tagged_array} at index {from_index} to index {to_index}.
444 void RunCopyElement(int from_index, int to_index) {
445 // TODO(titzer): test element and field accesses where the base is not
446 // a constant in the code.
447 BoundsCheck(from_index);
448 BoundsCheck(to_index);
449 ElementAccess access = GetElementAccess();
450
451 SimplifiedLoweringTester<Object*> t;
452 Node* ptr = GetBaseNode(&t);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400453 Node* load = t.LoadElement(access, ptr, t.Int32Constant(from_index));
454 t.StoreElement(access, ptr, t.Int32Constant(to_index), load);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000455 t.Return(t.jsgraph.TrueConstant());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000456 t.LowerAllNodesAndLowerChanges();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000457 t.GenerateCode();
458
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000459 Object* result = t.Call();
460 CHECK_EQ(t.isolate()->heap()->true_value(), result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000461 }
462
463 // Create and run code that copies the field in either {untagged_array}
464 // or {tagged_array} at index {from_index} to index {to_index}.
465 void RunCopyField(int from_index, int to_index) {
466 BoundsCheck(from_index);
467 BoundsCheck(to_index);
468 FieldAccess from_access = GetFieldAccess(from_index);
469 FieldAccess to_access = GetFieldAccess(to_index);
470
471 SimplifiedLoweringTester<Object*> t;
472 Node* ptr = GetBaseNode(&t);
473 Node* load = t.LoadField(from_access, ptr);
474 t.StoreField(to_access, ptr, load);
475 t.Return(t.jsgraph.TrueConstant());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000476 t.LowerAllNodesAndLowerChanges();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000477 t.GenerateCode();
478
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000479 Object* result = t.Call();
480 CHECK_EQ(t.isolate()->heap()->true_value(), result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000481 }
482
483 // Create and run code that copies the elements from {this} to {that}.
484 void RunCopyElements(AccessTester<E>* that) {
485// TODO(titzer): Rewrite this test without StructuredGraphBuilder support.
486#if 0
487 SimplifiedLoweringTester<Object*> t;
488
489 Node* one = t.Int32Constant(1);
490 Node* index = t.Int32Constant(0);
491 Node* limit = t.Int32Constant(static_cast<int>(num_elements));
492 t.environment()->Push(index);
493 Node* src = this->GetBaseNode(&t);
494 Node* dst = that->GetBaseNode(&t);
495 {
496 LoopBuilder loop(&t);
497 loop.BeginLoop();
498 // Loop exit condition
499 index = t.environment()->Top();
500 Node* condition = t.Int32LessThan(index, limit);
501 loop.BreakUnless(condition);
502 // dst[index] = src[index]
503 index = t.environment()->Pop();
504 Node* load = t.LoadElement(this->GetElementAccess(), src, index);
505 t.StoreElement(that->GetElementAccess(), dst, index, load);
506 // index++
507 index = t.Int32Add(index, one);
508 t.environment()->Push(index);
509 // continue
510 loop.EndBody();
511 loop.EndLoop();
512 }
513 index = t.environment()->Pop();
514 t.Return(t.jsgraph.TrueConstant());
515 t.LowerAllNodes();
516 t.GenerateCode();
517
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000518 Object* result = t.Call();
519 CHECK_EQ(t.isolate()->heap()->true_value(), result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000520#endif
521 }
522
523 E GetElement(int index) {
524 BoundsCheck(index);
525 if (tagged) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000526 return GetTaggedElement(index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000527 } else {
528 return untagged_array[index];
529 }
530 }
531
532 private:
533 ElementAccess GetElementAccess() {
534 ElementAccess access = {tagged ? kTaggedBase : kUntaggedBase,
535 tagged ? FixedArrayBase::kHeaderSize : 0,
Ben Murdochc5610432016-08-08 18:44:38 +0100536 Type::Any(), rep, kFullWriteBarrier};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000537 return access;
538 }
539
540 FieldAccess GetFieldAccess(int field) {
541 int offset = field * sizeof(E);
542 FieldAccess access = {tagged ? kTaggedBase : kUntaggedBase,
543 offset + (tagged ? FixedArrayBase::kHeaderSize : 0),
Ben Murdochc5610432016-08-08 18:44:38 +0100544 Handle<Name>(),
545 Type::Any(),
546 rep,
547 kFullWriteBarrier};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000548 return access;
549 }
550
551 template <typename T>
552 Node* GetBaseNode(SimplifiedLoweringTester<T>* t) {
553 return tagged ? t->HeapConstant(tagged_array)
554 : t->PointerConstant(untagged_array);
555 }
556
557 void BoundsCheck(int index) {
558 CHECK_GE(index, 0);
559 CHECK_LT(index, static_cast<int>(num_elements));
560 CHECK_EQ(static_cast<int>(ByteSize()), tagged_array->length());
561 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000562
563 E GetTaggedElement(int index) {
564 E* raw = reinterpret_cast<E*>(tagged_array->GetDataStartAddress());
565 return raw[index];
566 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000567};
568
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000569template <>
570double AccessTester<double>::GetTaggedElement(int index) {
571 return ReadDoubleValue(tagged_array->GetDataStartAddress() +
572 index * sizeof(double));
573}
574
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000575
576template <typename E>
577static void RunAccessTest(MachineType rep, E* original_elements, size_t num) {
578 int num_elements = static_cast<int>(num);
579
580 for (int taggedness = 0; taggedness < 2; taggedness++) {
581 AccessTester<E> a(taggedness == 1, rep, original_elements, num);
582 for (int field = 0; field < 2; field++) {
583 for (int i = 0; i < num_elements - 1; i++) {
584 a.Reinitialize();
585 if (field == 0) {
586 a.RunCopyField(i, i + 1); // Test field read/write.
587 } else {
588 a.RunCopyElement(i, i + 1); // Test element read/write.
589 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000590 for (int j = 0; j < num_elements; j++) {
591 E expect =
592 j == (i + 1) ? original_elements[i] : original_elements[j];
593 CHECK_EQ(expect, a.GetElement(j));
594 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000595 }
596 }
597 }
598 // Test array copy.
599 for (int tf = 0; tf < 2; tf++) {
600 for (int tt = 0; tt < 2; tt++) {
601 AccessTester<E> a(tf == 1, rep, original_elements, num);
602 AccessTester<E> b(tt == 1, rep, original_elements, num);
603 a.RunCopyElements(&b);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000604 for (int i = 0; i < num_elements; i++) {
605 CHECK_EQ(a.GetElement(i), b.GetElement(i));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000606 }
607 }
608 }
609}
610
611
612TEST(RunAccessTests_uint8) {
613 uint8_t data[] = {0x07, 0x16, 0x25, 0x34, 0x43, 0x99,
614 0xab, 0x78, 0x89, 0x19, 0x2b, 0x38};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000615 RunAccessTest<uint8_t>(MachineType::Int8(), data, arraysize(data));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000616}
617
618
619TEST(RunAccessTests_uint16) {
620 uint16_t data[] = {0x071a, 0x162b, 0x253c, 0x344d, 0x435e, 0x7777};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000621 RunAccessTest<uint16_t>(MachineType::Int16(), data, arraysize(data));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000622}
623
624
625TEST(RunAccessTests_int32) {
626 int32_t data[] = {-211, 211, 628347, 2000000000, -2000000000, -1, -100000034};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000627 RunAccessTest<int32_t>(MachineType::Int32(), data, arraysize(data));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000628}
629
630
631#define V8_2PART_INT64(a, b) (((static_cast<int64_t>(a) << 32) + 0x##b##u))
632
633
634TEST(RunAccessTests_int64) {
635 if (kPointerSize != 8) return;
636 int64_t data[] = {V8_2PART_INT64(0x10111213, 14151617),
637 V8_2PART_INT64(0x20212223, 24252627),
638 V8_2PART_INT64(0x30313233, 34353637),
639 V8_2PART_INT64(0xa0a1a2a3, a4a5a6a7),
640 V8_2PART_INT64(0xf0f1f2f3, f4f5f6f7)};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000641 RunAccessTest<int64_t>(MachineType::Int64(), data, arraysize(data));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000642}
643
644
645TEST(RunAccessTests_float64) {
646 double data[] = {1.25, -1.25, 2.75, 11.0, 11100.8};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000647 RunAccessTest<double>(MachineType::Float64(), data, arraysize(data));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000648}
649
650
651TEST(RunAccessTests_Smi) {
652 Smi* data[] = {Smi::FromInt(-1), Smi::FromInt(-9),
653 Smi::FromInt(0), Smi::FromInt(666),
654 Smi::FromInt(77777), Smi::FromInt(Smi::kMaxValue)};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000655 RunAccessTest<Smi*>(MachineType::AnyTagged(), data, arraysize(data));
656}
657
658
659TEST(RunAllocate) {
660 PretenureFlag flag[] = {NOT_TENURED, TENURED};
661
662 for (size_t i = 0; i < arraysize(flag); i++) {
663 SimplifiedLoweringTester<HeapObject*> t;
664 FieldAccess access = AccessBuilder::ForMap();
665 Node* size = t.jsgraph.Constant(HeapNumber::kSize);
666 Node* alloc = t.NewNode(t.simplified()->Allocate(flag[i]), size);
667 Node* map = t.jsgraph.Constant(t.factory()->heap_number_map());
668 t.StoreField(access, alloc, map);
669 t.Return(alloc);
670
671 t.LowerAllNodesAndLowerChanges();
672 t.GenerateCode();
673
674 HeapObject* result = t.CallWithPotentialGC<HeapObject>();
675 CHECK(t.heap()->new_space()->Contains(result) || flag[i] == TENURED);
676 CHECK(t.heap()->old_space()->Contains(result) || flag[i] == NOT_TENURED);
677 CHECK(result->IsHeapNumber());
678 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000679}
680
681
682// Fills in most of the nodes of the graph in order to make tests shorter.
683class TestingGraph : public HandleAndZoneScope, public GraphAndBuilders {
684 public:
685 Typer typer;
686 JSOperatorBuilder javascript;
687 JSGraph jsgraph;
688 Node* p0;
689 Node* p1;
690 Node* p2;
691 Node* start;
692 Node* end;
693 Node* ret;
694
695 explicit TestingGraph(Type* p0_type, Type* p1_type = Type::None(),
696 Type* p2_type = Type::None())
697 : GraphAndBuilders(main_zone()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000698 typer(main_isolate(), graph()),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000699 javascript(main_zone()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000700 jsgraph(main_isolate(), graph(), common(), &javascript, simplified(),
701 machine()) {
702 start = graph()->NewNode(common()->Start(4));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000703 graph()->SetStart(start);
704 ret =
705 graph()->NewNode(common()->Return(), jsgraph.Constant(0), start, start);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000706 end = graph()->NewNode(common()->End(1), ret);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000707 graph()->SetEnd(end);
708 p0 = graph()->NewNode(common()->Parameter(0), start);
709 p1 = graph()->NewNode(common()->Parameter(1), start);
710 p2 = graph()->NewNode(common()->Parameter(2), start);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400711 typer.Run();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000712 NodeProperties::SetType(p0, p0_type);
713 NodeProperties::SetType(p1, p1_type);
714 NodeProperties::SetType(p2, p2_type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000715 }
716
717 void CheckLoweringBinop(IrOpcode::Value expected, const Operator* op) {
718 Node* node = Return(graph()->NewNode(op, p0, p1));
719 Lower();
720 CHECK_EQ(expected, node->opcode());
721 }
722
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000723 void CheckLoweringStringBinop(IrOpcode::Value expected, const Operator* op) {
724 Node* node = Return(
725 graph()->NewNode(op, p0, p1, graph()->start(), graph()->start()));
726 Lower();
727 CHECK_EQ(expected, node->opcode());
728 }
729
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000730 void CheckLoweringTruncatedBinop(IrOpcode::Value expected, const Operator* op,
731 const Operator* trunc) {
732 Node* node = graph()->NewNode(op, p0, p1);
733 Return(graph()->NewNode(trunc, node));
734 Lower();
735 CHECK_EQ(expected, node->opcode());
736 }
737
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000738 void Lower() {
739 SourcePositionTable table(jsgraph.graph());
740 SimplifiedLowering(&jsgraph, jsgraph.zone(), &table).LowerAllNodes();
741 }
742
743 void LowerAllNodesAndLowerChanges() {
744 SourcePositionTable table(jsgraph.graph());
745 SimplifiedLowering(&jsgraph, jsgraph.zone(), &table).LowerAllNodes();
746
Ben Murdochc5610432016-08-08 18:44:38 +0100747 Schedule* schedule = Scheduler::ComputeSchedule(this->zone(), this->graph(),
748 Scheduler::kNoFlags);
749 EffectControlLinearizer linearizer(&jsgraph, schedule, this->zone());
750 linearizer.Run();
751
752 MemoryOptimizer memory_optimizer(&jsgraph, this->zone());
753 memory_optimizer.Optimize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000754 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000755
756 // Inserts the node as the return value of the graph.
757 Node* Return(Node* node) {
758 ret->ReplaceInput(0, node);
759 return node;
760 }
761
762 // Inserts the node as the effect input to the return of the graph.
763 void Effect(Node* node) { ret->ReplaceInput(1, node); }
764
765 Node* ExampleWithOutput(MachineType type) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000766 if (type.semantic() == MachineSemantic::kInt32) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000767 return graph()->NewNode(machine()->Int32Add(), jsgraph.Int32Constant(1),
768 jsgraph.Int32Constant(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000769 } else if (type.semantic() == MachineSemantic::kUint32) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000770 return graph()->NewNode(machine()->Word32Shr(), jsgraph.Int32Constant(1),
771 jsgraph.Int32Constant(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000772 } else if (type.representation() == MachineRepresentation::kFloat64) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000773 return graph()->NewNode(machine()->Float64Add(),
774 jsgraph.Float64Constant(1),
775 jsgraph.Float64Constant(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000776 } else if (type.representation() == MachineRepresentation::kBit) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000777 return graph()->NewNode(machine()->Word32Equal(),
778 jsgraph.Int32Constant(1),
779 jsgraph.Int32Constant(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000780 } else if (type.representation() == MachineRepresentation::kWord64) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000781 return graph()->NewNode(machine()->Int64Add(), Int64Constant(1),
782 Int64Constant(1));
783 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000784 CHECK(type.representation() == MachineRepresentation::kTagged);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000785 return p0;
786 }
787 }
788
789 Node* Use(Node* node, MachineType type) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000790 if (type.semantic() == MachineSemantic::kInt32) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000791 return graph()->NewNode(machine()->Int32LessThan(), node,
792 jsgraph.Int32Constant(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000793 } else if (type.semantic() == MachineSemantic::kUint32) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000794 return graph()->NewNode(machine()->Uint32LessThan(), node,
795 jsgraph.Int32Constant(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000796 } else if (type.representation() == MachineRepresentation::kFloat64) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000797 return graph()->NewNode(machine()->Float64Add(), node,
798 jsgraph.Float64Constant(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000799 } else if (type.representation() == MachineRepresentation::kWord64) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000800 return graph()->NewNode(machine()->Int64LessThan(), node,
801 Int64Constant(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000802 } else if (type.representation() == MachineRepresentation::kWord32) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400803 return graph()->NewNode(machine()->Word32Equal(), node,
804 jsgraph.Int32Constant(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000805 } else {
806 return graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), node,
807 jsgraph.TrueConstant());
808 }
809 }
810
811 Node* Branch(Node* cond) {
812 Node* br = graph()->NewNode(common()->Branch(), cond, start);
813 Node* tb = graph()->NewNode(common()->IfTrue(), br);
814 Node* fb = graph()->NewNode(common()->IfFalse(), br);
815 Node* m = graph()->NewNode(common()->Merge(2), tb, fb);
816 NodeProperties::ReplaceControlInput(ret, m);
817 return br;
818 }
819
820 Node* Int64Constant(int64_t v) {
821 return graph()->NewNode(common()->Int64Constant(v));
822 }
823
824 SimplifiedOperatorBuilder* simplified() { return &main_simplified_; }
825 MachineOperatorBuilder* machine() { return &main_machine_; }
826 CommonOperatorBuilder* common() { return &main_common_; }
827 Graph* graph() { return main_graph_; }
828};
829
830
831TEST(LowerBooleanNot_bit_bit) {
832 // BooleanNot(x: kRepBit) used as kRepBit
833 TestingGraph t(Type::Boolean());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000834 Node* b = t.ExampleWithOutput(MachineType::Bool());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000835 Node* inv = t.graph()->NewNode(t.simplified()->BooleanNot(), b);
836 Node* use = t.Branch(inv);
837 t.Lower();
838 Node* cmp = use->InputAt(0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400839 CHECK_EQ(t.machine()->Word32Equal()->opcode(), cmp->opcode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000840 CHECK(b == cmp->InputAt(0) || b == cmp->InputAt(1));
841 Node* f = t.jsgraph.Int32Constant(0);
842 CHECK(f == cmp->InputAt(0) || f == cmp->InputAt(1));
843}
844
845
846TEST(LowerBooleanNot_bit_tagged) {
847 // BooleanNot(x: kRepBit) used as kRepTagged
848 TestingGraph t(Type::Boolean());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000849 Node* b = t.ExampleWithOutput(MachineType::Bool());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000850 Node* inv = t.graph()->NewNode(t.simplified()->BooleanNot(), b);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000851 Node* use = t.Use(inv, MachineType::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000852 t.Return(use);
853 t.Lower();
Ben Murdochc5610432016-08-08 18:44:38 +0100854 CHECK_EQ(IrOpcode::kChangeBitToTagged, use->InputAt(0)->opcode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000855 Node* cmp = use->InputAt(0)->InputAt(0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400856 CHECK_EQ(t.machine()->Word32Equal()->opcode(), cmp->opcode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000857 CHECK(b == cmp->InputAt(0) || b == cmp->InputAt(1));
858 Node* f = t.jsgraph.Int32Constant(0);
859 CHECK(f == cmp->InputAt(0) || f == cmp->InputAt(1));
860}
861
862
863TEST(LowerBooleanNot_tagged_bit) {
864 // BooleanNot(x: kRepTagged) used as kRepBit
865 TestingGraph t(Type::Boolean());
866 Node* b = t.p0;
867 Node* inv = t.graph()->NewNode(t.simplified()->BooleanNot(), b);
868 Node* use = t.Branch(inv);
869 t.Lower();
870 Node* cmp = use->InputAt(0);
871 CHECK_EQ(t.machine()->WordEqual()->opcode(), cmp->opcode());
872 CHECK(b == cmp->InputAt(0) || b == cmp->InputAt(1));
873 Node* f = t.jsgraph.FalseConstant();
874 CHECK(f == cmp->InputAt(0) || f == cmp->InputAt(1));
875}
876
877
878TEST(LowerBooleanNot_tagged_tagged) {
879 // BooleanNot(x: kRepTagged) used as kRepTagged
880 TestingGraph t(Type::Boolean());
881 Node* b = t.p0;
882 Node* inv = t.graph()->NewNode(t.simplified()->BooleanNot(), b);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000883 Node* use = t.Use(inv, MachineType::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000884 t.Return(use);
885 t.Lower();
Ben Murdochc5610432016-08-08 18:44:38 +0100886 CHECK_EQ(IrOpcode::kChangeBitToTagged, use->InputAt(0)->opcode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000887 Node* cmp = use->InputAt(0)->InputAt(0);
888 CHECK_EQ(t.machine()->WordEqual()->opcode(), cmp->opcode());
889 CHECK(b == cmp->InputAt(0) || b == cmp->InputAt(1));
890 Node* f = t.jsgraph.FalseConstant();
891 CHECK(f == cmp->InputAt(0) || f == cmp->InputAt(1));
892}
893
894
895TEST(LowerBooleanToNumber_bit_int32) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000896 // BooleanToNumber(x: kRepBit) used as MachineType::Int32()
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000897 TestingGraph t(Type::Boolean());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000898 Node* b = t.ExampleWithOutput(MachineType::Bool());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000899 Node* cnv = t.graph()->NewNode(t.simplified()->BooleanToNumber(), b);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000900 Node* use = t.Use(cnv, MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000901 t.Return(use);
902 t.Lower();
903 CHECK_EQ(b, use->InputAt(0));
904}
905
906
907TEST(LowerBooleanToNumber_tagged_int32) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000908 // BooleanToNumber(x: kRepTagged) used as MachineType::Int32()
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000909 TestingGraph t(Type::Boolean());
910 Node* b = t.p0;
911 Node* cnv = t.graph()->NewNode(t.simplified()->BooleanToNumber(), b);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000912 Node* use = t.Use(cnv, MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000913 t.Return(use);
914 t.Lower();
915 CHECK_EQ(t.machine()->WordEqual()->opcode(), cnv->opcode());
916 CHECK(b == cnv->InputAt(0) || b == cnv->InputAt(1));
917 Node* c = t.jsgraph.TrueConstant();
918 CHECK(c == cnv->InputAt(0) || c == cnv->InputAt(1));
919}
920
921
922TEST(LowerBooleanToNumber_bit_tagged) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000923 // BooleanToNumber(x: kRepBit) used as MachineType::AnyTagged()
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000924 TestingGraph t(Type::Boolean());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000925 Node* b = t.ExampleWithOutput(MachineType::Bool());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000926 Node* cnv = t.graph()->NewNode(t.simplified()->BooleanToNumber(), b);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000927 Node* use = t.Use(cnv, MachineType::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000928 t.Return(use);
929 t.Lower();
930 CHECK_EQ(b, use->InputAt(0)->InputAt(0));
Ben Murdochc5610432016-08-08 18:44:38 +0100931 CHECK_EQ(IrOpcode::kChangeInt31ToTaggedSigned, use->InputAt(0)->opcode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000932}
933
934
935TEST(LowerBooleanToNumber_tagged_tagged) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000936 // BooleanToNumber(x: kRepTagged) used as MachineType::AnyTagged()
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000937 TestingGraph t(Type::Boolean());
938 Node* b = t.p0;
939 Node* cnv = t.graph()->NewNode(t.simplified()->BooleanToNumber(), b);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000940 Node* use = t.Use(cnv, MachineType::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000941 t.Return(use);
942 t.Lower();
943 CHECK_EQ(cnv, use->InputAt(0)->InputAt(0));
Ben Murdochc5610432016-08-08 18:44:38 +0100944 CHECK_EQ(IrOpcode::kChangeInt31ToTaggedSigned, use->InputAt(0)->opcode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000945 CHECK_EQ(t.machine()->WordEqual()->opcode(), cnv->opcode());
946 CHECK(b == cnv->InputAt(0) || b == cnv->InputAt(1));
947 Node* c = t.jsgraph.TrueConstant();
948 CHECK(c == cnv->InputAt(0) || c == cnv->InputAt(1));
949}
950
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000951static Type* test_types[] = {Type::Signed32(), Type::Unsigned32(),
Ben Murdochda12d292016-06-02 14:46:10 +0100952 Type::Number()};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000953
954TEST(LowerNumberCmp_to_int32) {
955 TestingGraph t(Type::Signed32(), Type::Signed32());
956
957 t.CheckLoweringBinop(IrOpcode::kWord32Equal, t.simplified()->NumberEqual());
958 t.CheckLoweringBinop(IrOpcode::kInt32LessThan,
959 t.simplified()->NumberLessThan());
960 t.CheckLoweringBinop(IrOpcode::kInt32LessThanOrEqual,
961 t.simplified()->NumberLessThanOrEqual());
962}
963
964
965TEST(LowerNumberCmp_to_uint32) {
966 TestingGraph t(Type::Unsigned32(), Type::Unsigned32());
967
968 t.CheckLoweringBinop(IrOpcode::kWord32Equal, t.simplified()->NumberEqual());
969 t.CheckLoweringBinop(IrOpcode::kUint32LessThan,
970 t.simplified()->NumberLessThan());
971 t.CheckLoweringBinop(IrOpcode::kUint32LessThanOrEqual,
972 t.simplified()->NumberLessThanOrEqual());
973}
974
975
976TEST(LowerNumberCmp_to_float64) {
Ben Murdochda12d292016-06-02 14:46:10 +0100977 TestingGraph t(Type::Number(), Type::Number());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000978
Ben Murdochda12d292016-06-02 14:46:10 +0100979 t.CheckLoweringBinop(IrOpcode::kFloat64Equal, t.simplified()->NumberEqual());
980 t.CheckLoweringBinop(IrOpcode::kFloat64LessThan,
981 t.simplified()->NumberLessThan());
982 t.CheckLoweringBinop(IrOpcode::kFloat64LessThanOrEqual,
983 t.simplified()->NumberLessThanOrEqual());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000984}
985
986
987TEST(LowerNumberAddSub_to_int32) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400988 HandleAndZoneScope scope;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000989 Type* small_range = Type::Range(1, 10, scope.main_zone());
990 Type* large_range = Type::Range(-1e+13, 1e+14, scope.main_zone());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400991 static Type* types[] = {Type::Signed32(), Type::Integral32(), small_range,
992 large_range};
993
994 for (size_t i = 0; i < arraysize(types); i++) {
995 for (size_t j = 0; j < arraysize(types); j++) {
996 TestingGraph t(types[i], types[j]);
997 t.CheckLoweringTruncatedBinop(IrOpcode::kInt32Add,
998 t.simplified()->NumberAdd(),
999 t.simplified()->NumberToInt32());
1000 t.CheckLoweringTruncatedBinop(IrOpcode::kInt32Sub,
1001 t.simplified()->NumberSubtract(),
1002 t.simplified()->NumberToInt32());
1003 }
1004 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001005}
1006
1007
1008TEST(LowerNumberAddSub_to_uint32) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001009 HandleAndZoneScope scope;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001010 Type* small_range = Type::Range(1, 10, scope.main_zone());
1011 Type* large_range = Type::Range(-1e+13, 1e+14, scope.main_zone());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001012 static Type* types[] = {Type::Signed32(), Type::Integral32(), small_range,
1013 large_range};
1014
1015 for (size_t i = 0; i < arraysize(types); i++) {
1016 for (size_t j = 0; j < arraysize(types); j++) {
1017 TestingGraph t(types[i], types[j]);
1018 t.CheckLoweringTruncatedBinop(IrOpcode::kInt32Add,
1019 t.simplified()->NumberAdd(),
1020 t.simplified()->NumberToUint32());
1021 t.CheckLoweringTruncatedBinop(IrOpcode::kInt32Sub,
1022 t.simplified()->NumberSubtract(),
1023 t.simplified()->NumberToUint32());
1024 }
1025 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001026}
1027
1028
1029TEST(LowerNumberAddSub_to_float64) {
1030 for (size_t i = 0; i < arraysize(test_types); i++) {
1031 TestingGraph t(test_types[i], test_types[i]);
1032
1033 t.CheckLoweringBinop(IrOpcode::kFloat64Add, t.simplified()->NumberAdd());
1034 t.CheckLoweringBinop(IrOpcode::kFloat64Sub,
1035 t.simplified()->NumberSubtract());
1036 }
1037}
1038
1039
1040TEST(LowerNumberDivMod_to_float64) {
1041 for (size_t i = 0; i < arraysize(test_types); i++) {
1042 TestingGraph t(test_types[i], test_types[i]);
1043
1044 t.CheckLoweringBinop(IrOpcode::kFloat64Div, t.simplified()->NumberDivide());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001045 if (!test_types[i]->Is(Type::Unsigned32())) {
1046 t.CheckLoweringBinop(IrOpcode::kFloat64Mod,
1047 t.simplified()->NumberModulus());
1048 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001049 }
1050}
1051
1052
1053static void CheckChangeOf(IrOpcode::Value change, Node* of, Node* node) {
1054 CHECK_EQ(change, node->opcode());
1055 CHECK_EQ(of, node->InputAt(0));
1056}
1057
1058
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001059TEST(LowerNumberToInt32_to_ChangeTaggedToInt32) {
1060 // NumberToInt32(x: kRepTagged | kTypeInt32) used as kRepWord32
1061 TestingGraph t(Type::Signed32());
1062 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), t.p0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001063 Node* use = t.Use(trunc, MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001064 t.Return(use);
1065 t.Lower();
1066 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p0, use->InputAt(0));
1067}
1068
Ben Murdochc5610432016-08-08 18:44:38 +01001069TEST(LowerNumberToInt32_to_TruncateFloat64ToWord32) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001070 // NumberToInt32(x: kRepFloat64) used as MachineType::Int32()
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001071 TestingGraph t(Type::Number());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001072 Node* p0 = t.ExampleWithOutput(MachineType::Float64());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001073 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), p0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001074 Node* use = t.Use(trunc, MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001075 t.Return(use);
1076 t.Lower();
Ben Murdochc5610432016-08-08 18:44:38 +01001077 CheckChangeOf(IrOpcode::kTruncateFloat64ToWord32, p0, use->InputAt(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001078}
1079
Ben Murdochc5610432016-08-08 18:44:38 +01001080TEST(LowerNumberToInt32_to_TruncateTaggedToWord32) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001081 // NumberToInt32(x: kTypeNumber | kRepTagged) used as MachineType::Int32()
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001082 TestingGraph t(Type::Number());
1083 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), t.p0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001084 Node* use = t.Use(trunc, MachineType::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001085 t.Return(use);
1086 t.Lower();
Ben Murdochc5610432016-08-08 18:44:38 +01001087 CheckChangeOf(IrOpcode::kTruncateTaggedToWord32, t.p0, use->InputAt(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001088}
1089
1090
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001091TEST(LowerNumberToUint32_to_ChangeTaggedToUint32) {
1092 // NumberToUint32(x: kRepTagged | kTypeUint32) used as kRepWord32
1093 TestingGraph t(Type::Unsigned32());
1094 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), t.p0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001095 Node* use = t.Use(trunc, MachineType::Uint32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001096 t.Return(use);
1097 t.Lower();
1098 CheckChangeOf(IrOpcode::kChangeTaggedToUint32, t.p0, use->InputAt(0));
1099}
1100
Ben Murdochc5610432016-08-08 18:44:38 +01001101TEST(LowerNumberToUint32_to_TruncateFloat64ToWord32) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001102 // NumberToUint32(x: kRepFloat64) used as MachineType::Uint32()
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001103 TestingGraph t(Type::Number());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001104 Node* p0 = t.ExampleWithOutput(MachineType::Float64());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001105 // TODO(titzer): run the typer here, or attach machine type to param.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001106 NodeProperties::SetType(p0, Type::Number());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001107 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), p0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001108 Node* use = t.Use(trunc, MachineType::Uint32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001109 t.Return(use);
1110 t.Lower();
Ben Murdochc5610432016-08-08 18:44:38 +01001111 CheckChangeOf(IrOpcode::kTruncateFloat64ToWord32, p0, use->InputAt(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001112}
1113
Ben Murdochc5610432016-08-08 18:44:38 +01001114TEST(LowerNumberToUint32_to_TruncateTaggedToWord32) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001115 // NumberToInt32(x: kTypeNumber | kRepTagged) used as MachineType::Uint32()
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001116 TestingGraph t(Type::Number());
1117 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), t.p0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001118 Node* use = t.Use(trunc, MachineType::Uint32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001119 t.Return(use);
1120 t.Lower();
Ben Murdochc5610432016-08-08 18:44:38 +01001121 CheckChangeOf(IrOpcode::kTruncateTaggedToWord32, t.p0, use->InputAt(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001122}
1123
Ben Murdochc5610432016-08-08 18:44:38 +01001124TEST(LowerNumberToUint32_to_TruncateFloat64ToWord32_uint32) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001125 // NumberToUint32(x: kRepFloat64) used as kRepWord32
1126 TestingGraph t(Type::Unsigned32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001127 Node* input = t.ExampleWithOutput(MachineType::Float64());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001128 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), input);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001129 Node* use = t.Use(trunc, MachineType::RepWord32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001130 t.Return(use);
1131 t.Lower();
Ben Murdochc5610432016-08-08 18:44:38 +01001132 CheckChangeOf(IrOpcode::kTruncateFloat64ToWord32, input, use->InputAt(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001133}
1134
1135
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001136TEST(LowerReferenceEqual_to_wordeq) {
1137 TestingGraph t(Type::Any(), Type::Any());
1138 IrOpcode::Value opcode =
1139 static_cast<IrOpcode::Value>(t.machine()->WordEqual()->opcode());
1140 t.CheckLoweringBinop(opcode, t.simplified()->ReferenceEqual(Type::Any()));
1141}
1142
Ben Murdochda12d292016-06-02 14:46:10 +01001143void CheckChangeInsertion(IrOpcode::Value expected, MachineType from,
1144 MachineType to, Type* type = Type::Any()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001145 TestingGraph t(Type::Any());
1146 Node* in = t.ExampleWithOutput(from);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001147 NodeProperties::SetType(in, type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001148 Node* use = t.Use(in, to);
1149 t.Return(use);
1150 t.Lower();
1151 CHECK_EQ(expected, use->InputAt(0)->opcode());
1152 CHECK_EQ(in, use->InputAt(0)->InputAt(0));
1153}
1154
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001155TEST(InsertBasicChanges) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001156 CheckChangeInsertion(IrOpcode::kChangeFloat64ToInt32, MachineType::Float64(),
1157 MachineType::Int32(), Type::Signed32());
1158 CheckChangeInsertion(IrOpcode::kChangeFloat64ToUint32, MachineType::Float64(),
1159 MachineType::Uint32(), Type::Unsigned32());
Ben Murdochc5610432016-08-08 18:44:38 +01001160 CheckChangeInsertion(IrOpcode::kTruncateFloat64ToWord32,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001161 MachineType::Float64(), MachineType::Uint32(),
1162 Type::Integral32());
1163 CheckChangeInsertion(IrOpcode::kChangeTaggedToInt32, MachineType::AnyTagged(),
1164 MachineType::Int32(), Type::Signed32());
1165 CheckChangeInsertion(IrOpcode::kChangeTaggedToUint32,
1166 MachineType::AnyTagged(), MachineType::Uint32(),
1167 Type::Unsigned32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001168
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001169 CheckChangeInsertion(IrOpcode::kChangeFloat64ToTagged, MachineType::Float64(),
Ben Murdoch61f157c2016-09-16 13:49:30 +01001170 MachineType::AnyTagged(), Type::Number());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001171 CheckChangeInsertion(IrOpcode::kChangeTaggedToFloat64,
Ben Murdochda12d292016-06-02 14:46:10 +01001172 MachineType::AnyTagged(), MachineType::Float64(),
1173 Type::Number());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001174
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001175 CheckChangeInsertion(IrOpcode::kChangeInt32ToFloat64, MachineType::Int32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001176 MachineType::Float64(), Type::Signed32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001177 CheckChangeInsertion(IrOpcode::kChangeInt32ToTagged, MachineType::Int32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001178 MachineType::AnyTagged(), Type::Signed32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001179
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001180 CheckChangeInsertion(IrOpcode::kChangeUint32ToFloat64, MachineType::Uint32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001181 MachineType::Float64(), Type::Unsigned32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001182 CheckChangeInsertion(IrOpcode::kChangeUint32ToTagged, MachineType::Uint32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001183 MachineType::AnyTagged(), Type::Unsigned32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001184}
1185
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001186static void CheckChangesAroundBinop(TestingGraph* t, const Operator* op,
1187 IrOpcode::Value input_change,
Ben Murdochda12d292016-06-02 14:46:10 +01001188 IrOpcode::Value output_change,
1189 Type* type = Type::Any()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001190 Node* binop =
1191 op->ControlInputCount() == 0
1192 ? t->graph()->NewNode(op, t->p0, t->p1)
1193 : t->graph()->NewNode(op, t->p0, t->p1, t->graph()->start());
Ben Murdochda12d292016-06-02 14:46:10 +01001194 NodeProperties::SetType(binop, type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001195 t->Return(binop);
1196 t->Lower();
1197 CHECK_EQ(input_change, binop->InputAt(0)->opcode());
1198 CHECK_EQ(input_change, binop->InputAt(1)->opcode());
1199 CHECK_EQ(t->p0, binop->InputAt(0)->InputAt(0));
1200 CHECK_EQ(t->p1, binop->InputAt(1)->InputAt(0));
1201 CHECK_EQ(output_change, t->ret->InputAt(0)->opcode());
1202 CHECK_EQ(binop, t->ret->InputAt(0)->InputAt(0));
1203}
1204
1205
1206TEST(InsertChangesAroundInt32Binops) {
1207 TestingGraph t(Type::Signed32(), Type::Signed32());
1208
1209 const Operator* ops[] = {t.machine()->Int32Add(), t.machine()->Int32Sub(),
1210 t.machine()->Int32Mul(), t.machine()->Int32Div(),
1211 t.machine()->Int32Mod(), t.machine()->Word32And(),
1212 t.machine()->Word32Or(), t.machine()->Word32Xor(),
1213 t.machine()->Word32Shl(), t.machine()->Word32Sar()};
1214
1215 for (size_t i = 0; i < arraysize(ops); i++) {
1216 CheckChangesAroundBinop(&t, ops[i], IrOpcode::kChangeTaggedToInt32,
Ben Murdochda12d292016-06-02 14:46:10 +01001217 IrOpcode::kChangeInt32ToTagged, Type::Signed32());
1218 CheckChangesAroundBinop(&t, ops[i], IrOpcode::kChangeTaggedToInt32,
1219 IrOpcode::kChangeInt32ToTagged, Type::Signed32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001220 }
1221}
1222
1223
1224TEST(InsertChangesAroundInt32Cmp) {
1225 TestingGraph t(Type::Signed32(), Type::Signed32());
1226
1227 const Operator* ops[] = {t.machine()->Int32LessThan(),
1228 t.machine()->Int32LessThanOrEqual()};
1229
1230 for (size_t i = 0; i < arraysize(ops); i++) {
1231 CheckChangesAroundBinop(&t, ops[i], IrOpcode::kChangeTaggedToInt32,
Ben Murdochc5610432016-08-08 18:44:38 +01001232 IrOpcode::kChangeBitToTagged);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001233 }
1234}
1235
1236
1237TEST(InsertChangesAroundUint32Cmp) {
1238 TestingGraph t(Type::Unsigned32(), Type::Unsigned32());
1239
1240 const Operator* ops[] = {t.machine()->Uint32LessThan(),
1241 t.machine()->Uint32LessThanOrEqual()};
1242
1243 for (size_t i = 0; i < arraysize(ops); i++) {
1244 CheckChangesAroundBinop(&t, ops[i], IrOpcode::kChangeTaggedToUint32,
Ben Murdochc5610432016-08-08 18:44:38 +01001245 IrOpcode::kChangeBitToTagged);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001246 }
1247}
1248
1249
1250TEST(InsertChangesAroundFloat64Binops) {
1251 TestingGraph t(Type::Number(), Type::Number());
1252
1253 const Operator* ops[] = {
1254 t.machine()->Float64Add(), t.machine()->Float64Sub(),
1255 t.machine()->Float64Mul(), t.machine()->Float64Div(),
1256 t.machine()->Float64Mod(),
1257 };
1258
1259 for (size_t i = 0; i < arraysize(ops); i++) {
1260 CheckChangesAroundBinop(&t, ops[i], IrOpcode::kChangeTaggedToFloat64,
Ben Murdoch61f157c2016-09-16 13:49:30 +01001261 IrOpcode::kChangeFloat64ToTagged, Type::Number());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001262 }
1263}
1264
1265
1266TEST(InsertChangesAroundFloat64Cmp) {
1267 TestingGraph t(Type::Number(), Type::Number());
1268
1269 const Operator* ops[] = {t.machine()->Float64Equal(),
1270 t.machine()->Float64LessThan(),
1271 t.machine()->Float64LessThanOrEqual()};
1272
1273 for (size_t i = 0; i < arraysize(ops); i++) {
1274 CheckChangesAroundBinop(&t, ops[i], IrOpcode::kChangeTaggedToFloat64,
Ben Murdochc5610432016-08-08 18:44:38 +01001275 IrOpcode::kChangeBitToTagged);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001276 }
1277}
1278
1279
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001280namespace {
1281
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001282void CheckFieldAccessArithmetic(FieldAccess access, Node* load_or_store) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001283 IntPtrMatcher mindex(load_or_store->InputAt(1));
1284 CHECK(mindex.Is(access.offset - access.tag()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001285}
1286
1287
1288Node* CheckElementAccessArithmetic(ElementAccess access, Node* load_or_store) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001289 Node* index = load_or_store->InputAt(1);
1290 if (kPointerSize == 8) {
1291 CHECK_EQ(IrOpcode::kChangeUint32ToUint64, index->opcode());
1292 index = index->InputAt(0);
1293 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001294
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001295 Int32BinopMatcher mindex(index);
1296 CHECK_EQ(IrOpcode::kInt32Add, mindex.node()->opcode());
1297 CHECK(mindex.right().Is(access.header_size - access.tag()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001298
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001299 const int element_size_shift =
1300 ElementSizeLog2Of(access.machine_type.representation());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001301 if (element_size_shift) {
1302 Int32BinopMatcher shl(mindex.left().node());
1303 CHECK_EQ(IrOpcode::kWord32Shl, shl.node()->opcode());
1304 CHECK(shl.right().Is(element_size_shift));
1305 return shl.left().node();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001306 } else {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001307 return mindex.left().node();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001308 }
1309}
1310
1311
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001312const MachineType kMachineReps[] = {
1313 MachineType::Int8(), MachineType::Int16(), MachineType::Int32(),
1314 MachineType::Uint32(), MachineType::Int64(), MachineType::Float64(),
1315 MachineType::AnyTagged()};
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001316
1317} // namespace
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001318
1319
1320TEST(LowerLoadField_to_load) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001321 for (size_t i = 0; i < arraysize(kMachineReps); i++) {
Ben Murdochc5610432016-08-08 18:44:38 +01001322 TestingGraph t(Type::Any(), Type::Signed32());
1323 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
1324 Handle<Name>::null(), Type::Any(),
1325 kMachineReps[i], kNoWriteBarrier};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001326
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001327 Node* load = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0,
1328 t.start, t.start);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001329 Node* use = t.Use(load, kMachineReps[i]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001330 t.Return(use);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001331 t.LowerAllNodesAndLowerChanges();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001332 CHECK_EQ(IrOpcode::kLoad, load->opcode());
1333 CHECK_EQ(t.p0, load->InputAt(0));
1334 CheckFieldAccessArithmetic(access, load);
1335
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001336 MachineType rep = LoadRepresentationOf(load->op());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001337 CHECK_EQ(kMachineReps[i], rep);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001338 }
1339}
1340
1341
1342TEST(LowerStoreField_to_store) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001343 {
1344 TestingGraph t(Type::Any(), Type::Signed32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001345
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001346 for (size_t i = 0; i < arraysize(kMachineReps); i++) {
Ben Murdochc5610432016-08-08 18:44:38 +01001347 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
1348 Handle<Name>::null(), Type::Any(),
1349 kMachineReps[i], kNoWriteBarrier};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001350
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001351 Node* val = t.ExampleWithOutput(kMachineReps[i]);
1352 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0,
1353 val, t.start, t.start);
1354 t.Effect(store);
1355 t.LowerAllNodesAndLowerChanges();
1356 CHECK_EQ(IrOpcode::kStore, store->opcode());
1357 CHECK_EQ(val, store->InputAt(2));
1358 CheckFieldAccessArithmetic(access, store);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001359
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001360 StoreRepresentation rep = StoreRepresentationOf(store->op());
1361 if (kMachineReps[i].representation() == MachineRepresentation::kTagged) {
Ben Murdochc5610432016-08-08 18:44:38 +01001362 CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001363 }
1364 CHECK_EQ(kMachineReps[i].representation(), rep.representation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001365 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001366 }
1367 {
1368 HandleAndZoneScope scope;
1369 Zone* z = scope.main_zone();
1370 TestingGraph t(Type::Any(), Type::Intersect(Type::SignedSmall(),
1371 Type::TaggedSigned(), z));
Ben Murdochc5610432016-08-08 18:44:38 +01001372 FieldAccess access = {
1373 kTaggedBase, FixedArrayBase::kHeaderSize, Handle<Name>::null(),
1374 Type::Any(), MachineType::AnyTagged(), kNoWriteBarrier};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001375 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0,
1376 t.p1, t.start, t.start);
1377 t.Effect(store);
1378 t.LowerAllNodesAndLowerChanges();
1379 CHECK_EQ(IrOpcode::kStore, store->opcode());
1380 CHECK_EQ(t.p1, store->InputAt(2));
1381 StoreRepresentation rep = StoreRepresentationOf(store->op());
1382 CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001383 }
1384}
1385
1386
1387TEST(LowerLoadElement_to_load) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001388 for (size_t i = 0; i < arraysize(kMachineReps); i++) {
Ben Murdochc5610432016-08-08 18:44:38 +01001389 TestingGraph t(Type::Any(), Type::Signed32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001390 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
Ben Murdochc5610432016-08-08 18:44:38 +01001391 Type::Any(), kMachineReps[i], kNoWriteBarrier};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001392
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001393 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0,
1394 t.p1, t.start, t.start);
1395 Node* use = t.Use(load, kMachineReps[i]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001396 t.Return(use);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001397 t.LowerAllNodesAndLowerChanges();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001398 CHECK_EQ(IrOpcode::kLoad, load->opcode());
1399 CHECK_EQ(t.p0, load->InputAt(0));
1400 CheckElementAccessArithmetic(access, load);
1401
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001402 MachineType rep = LoadRepresentationOf(load->op());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001403 CHECK_EQ(kMachineReps[i], rep);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001404 }
1405}
1406
1407
1408TEST(LowerStoreElement_to_store) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001409 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001410 for (size_t i = 0; i < arraysize(kMachineReps); i++) {
Ben Murdochc5610432016-08-08 18:44:38 +01001411 TestingGraph t(Type::Any(), Type::Signed32());
1412
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001413 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
Ben Murdochc5610432016-08-08 18:44:38 +01001414 Type::Any(), kMachineReps[i], kNoWriteBarrier};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001415
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001416 Node* val = t.ExampleWithOutput(kMachineReps[i]);
1417 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access),
1418 t.p0, t.p1, val, t.start, t.start);
1419 t.Effect(store);
1420 t.LowerAllNodesAndLowerChanges();
1421 CHECK_EQ(IrOpcode::kStore, store->opcode());
1422 CHECK_EQ(val, store->InputAt(2));
1423 CheckElementAccessArithmetic(access, store);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001424
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001425 StoreRepresentation rep = StoreRepresentationOf(store->op());
1426 if (kMachineReps[i].representation() == MachineRepresentation::kTagged) {
Ben Murdochc5610432016-08-08 18:44:38 +01001427 CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001428 }
1429 CHECK_EQ(kMachineReps[i].representation(), rep.representation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001430 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001431 }
1432 {
1433 HandleAndZoneScope scope;
1434 Zone* z = scope.main_zone();
1435 TestingGraph t(
1436 Type::Any(), Type::Signed32(),
1437 Type::Intersect(Type::SignedSmall(), Type::TaggedSigned(), z));
1438 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
Ben Murdochc5610432016-08-08 18:44:38 +01001439 Type::Any(), MachineType::AnyTagged(),
1440 kNoWriteBarrier};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001441 Node* store = t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0,
1442 t.p1, t.p2, t.start, t.start);
1443 t.Effect(store);
1444 t.LowerAllNodesAndLowerChanges();
1445 CHECK_EQ(IrOpcode::kStore, store->opcode());
1446 CHECK_EQ(t.p2, store->InputAt(2));
1447 StoreRepresentation rep = StoreRepresentationOf(store->op());
1448 CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001449 }
1450}
1451
1452
1453TEST(InsertChangeForLoadElementIndex) {
1454 // LoadElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length) =>
1455 // Load(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k))
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001456 TestingGraph t(Type::Any(), Type::Signed32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001457 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(),
Ben Murdochc5610432016-08-08 18:44:38 +01001458 MachineType::AnyTagged(), kNoWriteBarrier};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001459
1460 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001461 t.p1, t.start, t.start);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001462 t.Return(load);
1463 t.Lower();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001464 CHECK_EQ(IrOpcode::kLoadElement, load->opcode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001465 CHECK_EQ(t.p0, load->InputAt(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001466 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, load->InputAt(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001467}
1468
1469
1470TEST(InsertChangeForStoreElementIndex) {
1471 // StoreElement(obj: Tagged, index: kTypeInt32 | kRepTagged, length, val) =>
1472 // Store(obj, Int32Add(Int32Mul(ChangeTaggedToInt32(index), #k), #k), val)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001473 TestingGraph t(Type::Any(), Type::Signed32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001474 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(),
Ben Murdochc5610432016-08-08 18:44:38 +01001475 MachineType::AnyTagged(), kFullWriteBarrier};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001476
1477 Node* store =
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001478 t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0, t.p1,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001479 t.jsgraph.TrueConstant(), t.start, t.start);
1480 t.Effect(store);
1481 t.Lower();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001482 CHECK_EQ(IrOpcode::kStoreElement, store->opcode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001483 CHECK_EQ(t.p0, store->InputAt(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001484 CheckChangeOf(IrOpcode::kChangeTaggedToInt32, t.p1, store->InputAt(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001485}
1486
1487
1488TEST(InsertChangeForLoadElement) {
1489 // TODO(titzer): test all load/store representation change insertions.
1490 TestingGraph t(Type::Any(), Type::Signed32(), Type::Any());
Ben Murdoch61f157c2016-09-16 13:49:30 +01001491 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
1492 Type::Number(), MachineType::Float64(),
1493 kNoWriteBarrier};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001494
1495 Node* load = t.graph()->NewNode(t.simplified()->LoadElement(access), t.p0,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001496 t.p1, t.start, t.start);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001497 t.Return(load);
1498 t.Lower();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001499 CHECK_EQ(IrOpcode::kLoadElement, load->opcode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001500 CHECK_EQ(t.p0, load->InputAt(0));
1501 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0));
1502}
1503
1504
1505TEST(InsertChangeForLoadField) {
1506 // TODO(titzer): test all load/store representation change insertions.
1507 TestingGraph t(Type::Any(), Type::Signed32());
Ben Murdochc5610432016-08-08 18:44:38 +01001508 FieldAccess access = {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001509 kTaggedBase, FixedArrayBase::kHeaderSize, Handle<Name>::null(),
1510 Type::Number(), MachineType::Float64(), kNoWriteBarrier};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001511
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001512 Node* load = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0,
1513 t.start, t.start);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001514 t.Return(load);
1515 t.Lower();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001516 CHECK_EQ(IrOpcode::kLoadField, load->opcode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001517 CHECK_EQ(t.p0, load->InputAt(0));
1518 CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0));
1519}
1520
1521
1522TEST(InsertChangeForStoreElement) {
1523 // TODO(titzer): test all load/store representation change insertions.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001524 TestingGraph t(Type::Any(), Type::Signed32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001525 ElementAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize, Type::Any(),
Ben Murdochc5610432016-08-08 18:44:38 +01001526 MachineType::Float64(), kFullWriteBarrier};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001527
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001528 Node* store =
1529 t.graph()->NewNode(t.simplified()->StoreElement(access), t.p0,
1530 t.jsgraph.Int32Constant(0), t.p1, t.start, t.start);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001531 t.Effect(store);
1532 t.Lower();
1533
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001534 CHECK_EQ(IrOpcode::kStoreElement, store->opcode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001535 CHECK_EQ(t.p0, store->InputAt(0));
1536 CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p1, store->InputAt(2));
1537}
1538
1539
1540TEST(InsertChangeForStoreField) {
1541 // TODO(titzer): test all load/store representation change insertions.
1542 TestingGraph t(Type::Any(), Type::Signed32());
Ben Murdochc5610432016-08-08 18:44:38 +01001543 FieldAccess access = {
1544 kTaggedBase, FixedArrayBase::kHeaderSize, Handle<Name>::null(),
1545 Type::Any(), MachineType::Float64(), kNoWriteBarrier};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001546
1547 Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0,
1548 t.p1, t.start, t.start);
1549 t.Effect(store);
1550 t.Lower();
1551
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001552 CHECK_EQ(IrOpcode::kStoreField, store->opcode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001553 CHECK_EQ(t.p0, store->InputAt(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001554 CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p1, store->InputAt(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001555}
1556
1557
1558TEST(UpdatePhi) {
1559 TestingGraph t(Type::Any(), Type::Signed32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001560 static const MachineType kMachineTypes[] = {
1561 MachineType::Int32(), MachineType::Uint32(), MachineType::Float64()};
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001562 Type* kTypes[] = {Type::Signed32(), Type::Unsigned32(), Type::Number()};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001563
1564 for (size_t i = 0; i < arraysize(kMachineTypes); i++) {
Ben Murdochc5610432016-08-08 18:44:38 +01001565 FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
1566 Handle<Name>::null(), kTypes[i],
1567 kMachineTypes[i], kFullWriteBarrier};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001568
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001569 Node* load0 = t.graph()->NewNode(t.simplified()->LoadField(access), t.p0,
1570 t.start, t.start);
1571 Node* load1 = t.graph()->NewNode(t.simplified()->LoadField(access), t.p1,
1572 t.start, t.start);
1573 Node* phi =
1574 t.graph()->NewNode(t.common()->Phi(MachineRepresentation::kTagged, 2),
1575 load0, load1, t.start);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001576 t.Return(t.Use(phi, kMachineTypes[i]));
1577 t.Lower();
1578
1579 CHECK_EQ(IrOpcode::kPhi, phi->opcode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001580 CHECK_EQ(kMachineTypes[i].representation(), PhiRepresentationOf(phi->op()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001581 }
1582}
1583
1584
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001585TEST(RunNumberDivide_minus_1_TruncatingToInt32) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001586 SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001587 Node* num = t.NumberToInt32(t.Parameter(0));
1588 Node* div = t.NumberDivide(num, t.jsgraph.Constant(-1));
1589 Node* trunc = t.NumberToInt32(div);
1590 t.Return(trunc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001591
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001592 t.LowerAllNodesAndLowerChanges();
1593 t.GenerateCode();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001594
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001595 FOR_INT32_INPUTS(i) {
1596 int32_t x = 0 - *i;
1597 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001598 }
1599}
1600
1601
1602TEST(RunNumberMultiply_TruncatingToInt32) {
1603 int32_t constants[] = {-100, -10, -1, 0, 1, 100, 1000, 3000999};
1604
1605 for (size_t i = 0; i < arraysize(constants); i++) {
1606 double k = static_cast<double>(constants[i]);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001607 SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001608 Node* num = t.NumberToInt32(t.Parameter(0));
1609 Node* mul = t.NumberMultiply(num, t.jsgraph.Constant(k));
1610 Node* trunc = t.NumberToInt32(mul);
1611 t.Return(trunc);
1612
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001613 t.LowerAllNodesAndLowerChanges();
1614 t.GenerateCode();
1615
1616 FOR_INT32_INPUTS(i) {
1617 int32_t x = DoubleToInt32(static_cast<double>(*i) * k);
1618 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
1619 }
1620 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001621}
1622
1623
1624TEST(RunNumberMultiply_TruncatingToUint32) {
1625 uint32_t constants[] = {0, 1, 2, 3, 4, 100, 1000, 1024, 2048, 3000999};
1626
1627 for (size_t i = 0; i < arraysize(constants); i++) {
1628 double k = static_cast<double>(constants[i]);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001629 SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001630 Node* num = t.NumberToUint32(t.Parameter(0));
1631 Node* mul = t.NumberMultiply(num, t.jsgraph.Constant(k));
1632 Node* trunc = t.NumberToUint32(mul);
1633 t.Return(trunc);
1634
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001635 t.LowerAllNodesAndLowerChanges();
1636 t.GenerateCode();
1637
1638 FOR_UINT32_INPUTS(i) {
1639 uint32_t x = DoubleToUint32(static_cast<double>(*i) * k);
1640 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001641 }
1642 }
1643}
1644
1645
1646TEST(RunNumberDivide_2_TruncatingToUint32) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001647 SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001648 Node* num = t.NumberToUint32(t.Parameter(0));
1649 Node* div = t.NumberDivide(num, t.jsgraph.Constant(2));
1650 Node* trunc = t.NumberToUint32(div);
1651 t.Return(trunc);
1652
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001653 t.LowerAllNodesAndLowerChanges();
1654 t.GenerateCode();
1655
1656 FOR_UINT32_INPUTS(i) {
1657 uint32_t x = DoubleToUint32(static_cast<double>(*i / 2.0));
1658 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
1659 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001660}
1661
1662
1663TEST(NumberMultiply_ConstantOutOfRange) {
1664 TestingGraph t(Type::Signed32());
1665 Node* k = t.jsgraph.Constant(1000000023);
1666 Node* mul = t.graph()->NewNode(t.simplified()->NumberMultiply(), t.p0, k);
1667 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), mul);
1668 t.Return(trunc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001669 t.Lower();
1670
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001671 CHECK_EQ(IrOpcode::kFloat64Mul, mul->opcode());
1672}
1673
1674
1675TEST(NumberMultiply_NonTruncating) {
1676 TestingGraph t(Type::Signed32());
1677 Node* k = t.jsgraph.Constant(111);
1678 Node* mul = t.graph()->NewNode(t.simplified()->NumberMultiply(), t.p0, k);
1679 t.Return(mul);
1680 t.Lower();
1681
1682 CHECK_EQ(IrOpcode::kFloat64Mul, mul->opcode());
1683}
1684
1685
1686TEST(NumberDivide_TruncatingToInt32) {
1687 int32_t constants[] = {-100, -10, 1, 4, 100, 1000};
1688
1689 for (size_t i = 0; i < arraysize(constants); i++) {
1690 TestingGraph t(Type::Signed32());
1691 Node* k = t.jsgraph.Constant(constants[i]);
1692 Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001693 Node* use = t.Use(div, MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001694 t.Return(use);
1695 t.Lower();
1696
1697 CHECK_EQ(IrOpcode::kInt32Div, use->InputAt(0)->opcode());
1698 }
1699}
1700
1701
1702TEST(RunNumberDivide_TruncatingToInt32) {
1703 int32_t constants[] = {-100, -10, -1, 1, 2, 100, 1000, 1024, 2048};
1704
1705 for (size_t i = 0; i < arraysize(constants); i++) {
1706 int32_t k = constants[i];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001707 SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001708 Node* num = t.NumberToInt32(t.Parameter(0));
1709 Node* div = t.NumberDivide(num, t.jsgraph.Constant(k));
1710 Node* trunc = t.NumberToInt32(div);
1711 t.Return(trunc);
1712
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001713 t.LowerAllNodesAndLowerChanges();
1714 t.GenerateCode();
1715
1716 FOR_INT32_INPUTS(i) {
1717 if (*i == INT_MAX) continue; // exclude max int.
1718 int32_t x = DoubleToInt32(static_cast<double>(*i) / k);
1719 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001720 }
1721 }
1722}
1723
1724
1725TEST(NumberDivide_TruncatingToUint32) {
1726 double constants[] = {1, 3, 100, 1000, 100998348};
1727
1728 for (size_t i = 0; i < arraysize(constants); i++) {
1729 TestingGraph t(Type::Unsigned32());
1730 Node* k = t.jsgraph.Constant(constants[i]);
1731 Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001732 Node* use = t.Use(div, MachineType::Uint32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001733 t.Return(use);
1734 t.Lower();
1735
1736 CHECK_EQ(IrOpcode::kUint32Div, use->InputAt(0)->opcode());
1737 }
1738}
1739
1740
1741TEST(RunNumberDivide_TruncatingToUint32) {
1742 uint32_t constants[] = {100, 10, 1, 1, 2, 4, 1000, 1024, 2048};
1743
1744 for (size_t i = 0; i < arraysize(constants); i++) {
1745 uint32_t k = constants[i];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001746 SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001747 Node* num = t.NumberToUint32(t.Parameter(0));
1748 Node* div = t.NumberDivide(num, t.jsgraph.Constant(static_cast<double>(k)));
1749 Node* trunc = t.NumberToUint32(div);
1750 t.Return(trunc);
1751
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001752 t.LowerAllNodesAndLowerChanges();
1753 t.GenerateCode();
1754
1755 FOR_UINT32_INPUTS(i) {
1756 uint32_t x = *i / k;
1757 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001758 }
1759 }
1760}
1761
1762
1763TEST(NumberDivide_BadConstants) {
1764 {
1765 TestingGraph t(Type::Signed32());
1766 Node* k = t.jsgraph.Constant(-1);
1767 Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001768 Node* use = t.Use(div, MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001769 t.Return(use);
1770 t.Lower();
1771
1772 CHECK_EQ(IrOpcode::kInt32Sub, use->InputAt(0)->opcode());
1773 }
1774
1775 {
1776 TestingGraph t(Type::Signed32());
1777 Node* k = t.jsgraph.Constant(0);
1778 Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001779 Node* use = t.Use(div, MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001780 t.Return(use);
1781 t.Lower();
1782
1783 CHECK_EQ(IrOpcode::kInt32Constant, use->InputAt(0)->opcode());
1784 CHECK_EQ(0, OpParameter<int32_t>(use->InputAt(0)));
1785 }
1786
1787 {
1788 TestingGraph t(Type::Unsigned32());
1789 Node* k = t.jsgraph.Constant(0);
1790 Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001791 Node* use = t.Use(div, MachineType::Uint32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001792 t.Return(use);
1793 t.Lower();
1794
1795 CHECK_EQ(IrOpcode::kInt32Constant, use->InputAt(0)->opcode());
1796 CHECK_EQ(0, OpParameter<int32_t>(use->InputAt(0)));
1797 }
1798}
1799
1800
1801TEST(NumberModulus_TruncatingToInt32) {
1802 int32_t constants[] = {-100, -10, 1, 4, 100, 1000};
1803
1804 for (size_t i = 0; i < arraysize(constants); i++) {
1805 TestingGraph t(Type::Signed32());
1806 Node* k = t.jsgraph.Constant(constants[i]);
1807 Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001808 Node* use = t.Use(mod, MachineType::Int32());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001809 t.Return(use);
1810 t.Lower();
1811
1812 CHECK_EQ(IrOpcode::kInt32Mod, use->InputAt(0)->opcode());
1813 }
1814}
1815
1816
1817TEST(RunNumberModulus_TruncatingToInt32) {
1818 int32_t constants[] = {-100, -10, -1, 1, 2, 100, 1000, 1024, 2048};
1819
1820 for (size_t i = 0; i < arraysize(constants); i++) {
1821 int32_t k = constants[i];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001822 SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001823 Node* num = t.NumberToInt32(t.Parameter(0));
1824 Node* mod = t.NumberModulus(num, t.jsgraph.Constant(k));
1825 Node* trunc = t.NumberToInt32(mod);
1826 t.Return(trunc);
1827
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001828 t.LowerAllNodesAndLowerChanges();
1829 t.GenerateCode();
1830
1831 FOR_INT32_INPUTS(i) {
1832 if (*i == INT_MAX) continue; // exclude max int.
1833 int32_t x = DoubleToInt32(std::fmod(static_cast<double>(*i), k));
1834 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001835 }
1836 }
1837}
1838
1839
1840TEST(NumberModulus_TruncatingToUint32) {
1841 double constants[] = {1, 3, 100, 1000, 100998348};
1842
1843 for (size_t i = 0; i < arraysize(constants); i++) {
1844 TestingGraph t(Type::Unsigned32());
1845 Node* k = t.jsgraph.Constant(constants[i]);
1846 Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k);
1847 Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), mod);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001848 t.Return(trunc);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001849 t.Lower();
1850
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001851 CHECK_EQ(IrOpcode::kUint32Mod, t.ret->InputAt(0)->InputAt(0)->opcode());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001852 }
1853}
1854
1855
1856TEST(RunNumberModulus_TruncatingToUint32) {
1857 uint32_t constants[] = {1, 2, 100, 1000, 1024, 2048};
1858
1859 for (size_t i = 0; i < arraysize(constants); i++) {
1860 uint32_t k = constants[i];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001861 SimplifiedLoweringTester<Object*> t(MachineType::AnyTagged());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001862 Node* num = t.NumberToUint32(t.Parameter(0));
1863 Node* mod =
1864 t.NumberModulus(num, t.jsgraph.Constant(static_cast<double>(k)));
1865 Node* trunc = t.NumberToUint32(mod);
1866 t.Return(trunc);
1867
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001868 t.LowerAllNodesAndLowerChanges();
1869 t.GenerateCode();
1870
1871 FOR_UINT32_INPUTS(i) {
1872 uint32_t x = *i % k;
1873 t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001874 }
1875 }
1876}
1877
1878
1879TEST(NumberModulus_Int32) {
1880 int32_t constants[] = {-100, -10, 1, 4, 100, 1000};
1881
1882 for (size_t i = 0; i < arraysize(constants); i++) {
1883 TestingGraph t(Type::Signed32());
1884 Node* k = t.jsgraph.Constant(constants[i]);
1885 Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k);
1886 t.Return(mod);
1887 t.Lower();
1888
1889 CHECK_EQ(IrOpcode::kFloat64Mod, mod->opcode()); // Pesky -0 behavior.
1890 }
1891}
1892
1893
1894TEST(NumberModulus_Uint32) {
1895 const double kConstants[] = {2, 100, 1000, 1024, 2048};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001896 const MachineType kTypes[] = {MachineType::Int32(), MachineType::Uint32()};
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001897
1898 for (auto const type : kTypes) {
1899 for (auto const c : kConstants) {
1900 TestingGraph t(Type::Unsigned32());
1901 Node* k = t.jsgraph.Constant(c);
1902 Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k);
1903 Node* use = t.Use(mod, type);
1904 t.Return(use);
1905 t.Lower();
1906
1907 CHECK_EQ(IrOpcode::kUint32Mod, use->InputAt(0)->opcode());
1908 }
1909 }
1910}
1911
1912
1913TEST(PhiRepresentation) {
1914 HandleAndZoneScope scope;
1915 Zone* z = scope.main_zone();
1916
1917 struct TestData {
1918 Type* arg1;
1919 Type* arg2;
1920 MachineType use;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001921 MachineRepresentation expected;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001922 };
1923
1924 TestData test_data[] = {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001925 {Type::Signed32(), Type::Unsigned32(), MachineType::Int32(),
1926 MachineRepresentation::kWord32},
1927 {Type::Signed32(), Type::Unsigned32(), MachineType::Uint32(),
1928 MachineRepresentation::kWord32},
1929 {Type::Signed32(), Type::Signed32(), MachineType::Int32(),
1930 MachineRepresentation::kWord32},
1931 {Type::Unsigned32(), Type::Unsigned32(), MachineType::Int32(),
1932 MachineRepresentation::kWord32},
1933 {Type::Number(), Type::Signed32(), MachineType::Int32(),
1934 MachineRepresentation::kWord32}};
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001935
1936 for (auto const d : test_data) {
1937 TestingGraph t(d.arg1, d.arg2, Type::Boolean());
1938
1939 Node* br = t.graph()->NewNode(t.common()->Branch(), t.p2, t.start);
1940 Node* tb = t.graph()->NewNode(t.common()->IfTrue(), br);
1941 Node* fb = t.graph()->NewNode(t.common()->IfFalse(), br);
1942 Node* m = t.graph()->NewNode(t.common()->Merge(2), tb, fb);
1943
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001944 Node* phi = t.graph()->NewNode(
1945 t.common()->Phi(MachineRepresentation::kTagged, 2), t.p0, t.p1, m);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001946
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001947 Type* phi_type = Type::Union(d.arg1, d.arg2, z);
1948 NodeProperties::SetType(phi, phi_type);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001949
1950 Node* use = t.Use(phi, d.use);
1951 t.Return(use);
1952 t.Lower();
1953
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001954 CHECK_EQ(d.expected, PhiRepresentationOf(phi->op()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001955 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001956}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001957
1958} // namespace compiler
1959} // namespace internal
1960} // namespace v8