Line data Source code
1 : // 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 :
7 : #include "src/compiler/node-matchers.h"
8 : #include "src/compiler/representation-change.h"
9 : #include "src/compiler/type-cache.h"
10 : #include "src/objects-inl.h"
11 : #include "test/cctest/cctest.h"
12 : #include "test/cctest/compiler/codegen-tester.h"
13 : #include "test/cctest/compiler/graph-builder-tester.h"
14 : #include "test/cctest/compiler/value-helper.h"
15 :
16 : namespace v8 {
17 : namespace internal {
18 : namespace compiler {
19 :
20 490 : class RepresentationChangerTester : public HandleAndZoneScope,
21 : public GraphAndBuilders {
22 : public:
23 1470 : explicit RepresentationChangerTester(int num_parameters = 0)
24 : : GraphAndBuilders(main_zone()),
25 : javascript_(main_zone()),
26 : jsgraph_(main_isolate(), main_graph_, &main_common_, &javascript_,
27 : &main_simplified_, &main_machine_),
28 1470 : changer_(&jsgraph_, main_isolate()) {
29 490 : Node* s = graph()->NewNode(common()->Start(num_parameters));
30 : graph()->SetStart(s);
31 490 : }
32 :
33 : JSOperatorBuilder javascript_;
34 : JSGraph jsgraph_;
35 : RepresentationChanger changer_;
36 :
37 : Isolate* isolate() { return main_isolate(); }
38 : Graph* graph() { return main_graph_; }
39 : CommonOperatorBuilder* common() { return &main_common_; }
40 : JSGraph* jsgraph() { return &jsgraph_; }
41 : RepresentationChanger* changer() { return &changer_; }
42 :
43 : // TODO(titzer): use ValueChecker / ValueUtil
44 300 : void CheckInt32Constant(Node* n, int32_t expected) {
45 : Int32Matcher m(n);
46 300 : CHECK(m.HasValue());
47 300 : CHECK_EQ(expected, m.Value());
48 300 : }
49 :
50 290 : void CheckInt64Constant(Node* n, int64_t expected) {
51 : Int64Matcher m(n);
52 290 : CHECK(m.HasValue());
53 290 : CHECK_EQ(expected, m.Value());
54 290 : }
55 :
56 290 : void CheckUint32Constant(Node* n, uint32_t expected) {
57 : Uint32Matcher m(n);
58 290 : CHECK(m.HasValue());
59 290 : CHECK_EQ(static_cast<int>(expected), static_cast<int>(m.Value()));
60 290 : }
61 :
62 830 : void CheckFloat64Constant(Node* n, double expected) {
63 : Float64Matcher m(n);
64 830 : CHECK(m.HasValue());
65 830 : CHECK_DOUBLE_EQ(expected, m.Value());
66 830 : }
67 :
68 875 : void CheckFloat32Constant(Node* n, float expected) {
69 875 : CHECK_EQ(IrOpcode::kFloat32Constant, n->opcode());
70 875 : float fval = OpParameter<float>(n->op());
71 875 : CHECK_FLOAT_EQ(expected, fval);
72 875 : }
73 :
74 : void CheckHeapConstant(Node* n, HeapObject expected) {
75 : HeapObjectMatcher m(n);
76 : CHECK(m.HasValue());
77 : CHECK_EQ(expected, *m.Value());
78 : }
79 :
80 825 : void CheckNumberConstant(Node* n, double expected) {
81 : NumberMatcher m(n);
82 825 : CHECK_EQ(IrOpcode::kNumberConstant, n->opcode());
83 825 : CHECK(m.HasValue());
84 825 : CHECK_DOUBLE_EQ(expected, m.Value());
85 825 : }
86 :
87 1140 : Node* Parameter(int index = 0) {
88 570 : Node* n = graph()->NewNode(common()->Parameter(index), graph()->start());
89 : NodeProperties::SetType(n, Type::Any());
90 570 : return n;
91 : }
92 :
93 7960 : Node* Return(Node* input) {
94 : Node* n = graph()->NewNode(common()->Return(), jsgraph()->Int32Constant(0),
95 3980 : input, graph()->start(), graph()->start());
96 3980 : return n;
97 : }
98 :
99 35 : void CheckTypeError(MachineRepresentation from, Type from_type,
100 : MachineRepresentation to) {
101 35 : changer()->testing_type_errors_ = true;
102 35 : changer()->type_error_ = false;
103 35 : Node* n = Parameter(0);
104 35 : Node* use = Return(n);
105 : Node* c = changer()->GetRepresentationFor(n, from, from_type, use,
106 70 : UseInfo(to, Truncation::None()));
107 35 : CHECK(changer()->type_error_);
108 35 : CHECK_EQ(n, c);
109 35 : }
110 :
111 105 : void CheckNop(MachineRepresentation from, Type from_type,
112 : MachineRepresentation to) {
113 105 : Node* n = Parameter(0);
114 105 : Node* use = Return(n);
115 : Node* c = changer()->GetRepresentationFor(n, from, from_type, use,
116 210 : UseInfo(to, Truncation::None()));
117 105 : CHECK_EQ(n, c);
118 105 : }
119 : };
120 :
121 :
122 : const MachineType kMachineTypes[] = {
123 : MachineType::Float32(), MachineType::Float64(), MachineType::Int8(),
124 : MachineType::Uint8(), MachineType::Int16(), MachineType::Uint16(),
125 : MachineType::Int32(), MachineType::Uint32(), MachineType::Int64(),
126 : MachineType::Uint64(), MachineType::AnyTagged()};
127 :
128 :
129 28342 : TEST(BoolToBit_constant) {
130 5 : RepresentationChangerTester r;
131 :
132 5 : Node* true_node = r.jsgraph()->TrueConstant();
133 5 : Node* true_use = r.Return(true_node);
134 : Node* true_bit = r.changer()->GetRepresentationFor(
135 : true_node, MachineRepresentation::kTagged, Type::None(), true_use,
136 10 : UseInfo(MachineRepresentation::kBit, Truncation::None()));
137 5 : r.CheckInt32Constant(true_bit, 1);
138 :
139 5 : Node* false_node = r.jsgraph()->FalseConstant();
140 5 : Node* false_use = r.Return(false_node);
141 : Node* false_bit = r.changer()->GetRepresentationFor(
142 : false_node, MachineRepresentation::kTagged, Type::None(), false_use,
143 10 : UseInfo(MachineRepresentation::kBit, Truncation::None()));
144 5 : r.CheckInt32Constant(false_bit, 0);
145 5 : }
146 :
147 28342 : TEST(ToTagged_constant) {
148 5 : RepresentationChangerTester r;
149 :
150 250 : for (double i : ValueHelper::float64_vector()) {
151 245 : Node* n = r.jsgraph()->Constant(i);
152 245 : Node* use = r.Return(n);
153 : Node* c = r.changer()->GetRepresentationFor(
154 : n, MachineRepresentation::kFloat64, Type::None(), use,
155 490 : UseInfo(MachineRepresentation::kTagged, Truncation::None()));
156 245 : r.CheckNumberConstant(c, i);
157 : }
158 :
159 580 : for (int i : ValueHelper::int32_vector()) {
160 290 : Node* n = r.jsgraph()->Constant(i);
161 290 : Node* use = r.Return(n);
162 : Node* c = r.changer()->GetRepresentationFor(
163 : n, MachineRepresentation::kWord32, Type::Signed32(), use,
164 580 : UseInfo(MachineRepresentation::kTagged, Truncation::None()));
165 290 : r.CheckNumberConstant(c, i);
166 : }
167 :
168 580 : for (uint32_t i : ValueHelper::uint32_vector()) {
169 290 : Node* n = r.jsgraph()->Constant(i);
170 290 : Node* use = r.Return(n);
171 : Node* c = r.changer()->GetRepresentationFor(
172 : n, MachineRepresentation::kWord32, Type::Unsigned32(), use,
173 580 : UseInfo(MachineRepresentation::kTagged, Truncation::None()));
174 290 : r.CheckNumberConstant(c, i);
175 : }
176 5 : }
177 :
178 28342 : TEST(ToFloat64_constant) {
179 5 : RepresentationChangerTester r;
180 :
181 250 : for (double i : ValueHelper::float64_vector()) {
182 245 : Node* n = r.jsgraph()->Constant(i);
183 245 : Node* use = r.Return(n);
184 : Node* c = r.changer()->GetRepresentationFor(
185 : n, MachineRepresentation::kTagged, Type::None(), use,
186 490 : UseInfo(MachineRepresentation::kFloat64, Truncation::None()));
187 245 : r.CheckFloat64Constant(c, i);
188 : }
189 :
190 580 : for (int i : ValueHelper::int32_vector()) {
191 290 : Node* n = r.jsgraph()->Constant(i);
192 290 : Node* use = r.Return(n);
193 : Node* c = r.changer()->GetRepresentationFor(
194 : n, MachineRepresentation::kWord32, Type::Signed32(), use,
195 580 : UseInfo(MachineRepresentation::kFloat64, Truncation::None()));
196 290 : r.CheckFloat64Constant(c, i);
197 : }
198 :
199 580 : for (uint32_t i : ValueHelper::uint32_vector()) {
200 290 : Node* n = r.jsgraph()->Constant(i);
201 290 : Node* use = r.Return(n);
202 : Node* c = r.changer()->GetRepresentationFor(
203 : n, MachineRepresentation::kWord32, Type::Unsigned32(), use,
204 580 : UseInfo(MachineRepresentation::kFloat64, Truncation::None()));
205 290 : r.CheckFloat64Constant(c, i);
206 : }
207 :
208 : {
209 5 : Node* n = r.jsgraph()->Constant(0);
210 5 : Node* use = r.Return(n);
211 : Node* c = r.changer()->GetRepresentationFor(
212 : n, MachineRepresentation::kWord64, Type::Range(0, 0, r.zone()), use,
213 10 : UseInfo(MachineRepresentation::kFloat64, Truncation::None()));
214 5 : r.CheckFloat64Constant(c, 0);
215 : }
216 5 : }
217 :
218 :
219 : static bool IsFloat32Int32(int32_t val) {
220 290 : return val >= -(1 << 23) && val <= (1 << 23);
221 : }
222 :
223 :
224 : static bool IsFloat32Uint32(uint32_t val) { return val <= (1 << 23); }
225 :
226 :
227 28342 : TEST(ToFloat32_constant) {
228 5 : RepresentationChangerTester r;
229 :
230 580 : for (double i : ValueHelper::float32_vector()) {
231 575 : Node* n = r.jsgraph()->Constant(i);
232 575 : Node* use = r.Return(n);
233 : Node* c = r.changer()->GetRepresentationFor(
234 : n, MachineRepresentation::kTagged, Type::None(), use,
235 1150 : UseInfo(MachineRepresentation::kFloat32, Truncation::None()));
236 575 : r.CheckFloat32Constant(c, i);
237 : }
238 :
239 580 : for (int i : ValueHelper::int32_vector()) {
240 290 : if (!IsFloat32Int32(i)) continue;
241 155 : Node* n = r.jsgraph()->Constant(i);
242 155 : Node* use = r.Return(n);
243 : Node* c = r.changer()->GetRepresentationFor(
244 : n, MachineRepresentation::kWord32, Type::Signed32(), use,
245 310 : UseInfo(MachineRepresentation::kFloat32, Truncation::None()));
246 155 : r.CheckFloat32Constant(c, static_cast<float>(i));
247 : }
248 :
249 580 : for (uint32_t i : ValueHelper::uint32_vector()) {
250 290 : if (!IsFloat32Uint32(i)) continue;
251 145 : Node* n = r.jsgraph()->Constant(i);
252 145 : Node* use = r.Return(n);
253 : Node* c = r.changer()->GetRepresentationFor(
254 : n, MachineRepresentation::kWord32, Type::Unsigned32(), use,
255 290 : UseInfo(MachineRepresentation::kFloat32, Truncation::None()));
256 145 : r.CheckFloat32Constant(c, static_cast<float>(i));
257 : }
258 5 : }
259 :
260 28342 : TEST(ToInt32_constant) {
261 5 : RepresentationChangerTester r;
262 : {
263 295 : FOR_INT32_INPUTS(i) {
264 290 : Node* n = r.jsgraph()->Constant(*i);
265 290 : Node* use = r.Return(n);
266 : Node* c = r.changer()->GetRepresentationFor(
267 : n, MachineRepresentation::kTagged, Type::Signed32(), use,
268 580 : UseInfo(MachineRepresentation::kWord32, Truncation::None()));
269 290 : r.CheckInt32Constant(c, *i);
270 : }
271 : }
272 5 : }
273 :
274 28342 : TEST(ToUint32_constant) {
275 5 : RepresentationChangerTester r;
276 295 : FOR_UINT32_INPUTS(i) {
277 290 : Node* n = r.jsgraph()->Constant(static_cast<double>(*i));
278 290 : Node* use = r.Return(n);
279 : Node* c = r.changer()->GetRepresentationFor(
280 : n, MachineRepresentation::kTagged, Type::Unsigned32(), use,
281 580 : UseInfo(MachineRepresentation::kWord32, Truncation::None()));
282 290 : r.CheckUint32Constant(c, *i);
283 : }
284 5 : }
285 :
286 28342 : TEST(ToInt64_constant) {
287 5 : RepresentationChangerTester r;
288 295 : FOR_INT32_INPUTS(i) {
289 290 : Node* n = r.jsgraph()->Constant(*i);
290 290 : Node* use = r.Return(n);
291 : Node* c = r.changer()->GetRepresentationFor(
292 290 : n, MachineRepresentation::kTagged, TypeCache::Get()->kSafeInteger, use,
293 580 : UseInfo(MachineRepresentation::kWord64, Truncation::None()));
294 290 : r.CheckInt64Constant(c, *i);
295 : }
296 5 : }
297 :
298 260 : static void CheckChange(IrOpcode::Value expected, MachineRepresentation from,
299 : Type from_type, UseInfo use_info) {
300 260 : RepresentationChangerTester r;
301 :
302 260 : Node* n = r.Parameter();
303 260 : Node* use = r.Return(n);
304 300 : Node* c =
305 260 : r.changer()->GetRepresentationFor(n, from, from_type, use, use_info);
306 :
307 260 : CHECK_NE(c, n);
308 260 : CHECK_EQ(expected, c->opcode());
309 260 : CHECK_EQ(n, c->InputAt(0));
310 :
311 260 : if (expected == IrOpcode::kCheckedFloat64ToInt32 ||
312 : expected == IrOpcode::kCheckedFloat64ToInt64) {
313 : CheckForMinusZeroMode mode =
314 40 : from_type.Maybe(Type::MinusZero())
315 : ? use_info.minus_zero_check()
316 40 : : CheckForMinusZeroMode::kDontCheckForMinusZero;
317 40 : CHECK_EQ(mode, CheckMinusZeroParametersOf(c->op()).mode());
318 : }
319 260 : }
320 :
321 215 : static void CheckChange(IrOpcode::Value expected, MachineRepresentation from,
322 : Type from_type, MachineRepresentation to) {
323 430 : CheckChange(expected, from, from_type, UseInfo(to, Truncation::Any()));
324 215 : }
325 :
326 115 : static void CheckTwoChanges(IrOpcode::Value expected2,
327 : IrOpcode::Value expected1,
328 : MachineRepresentation from, Type from_type,
329 : MachineRepresentation to, UseInfo use_info) {
330 115 : RepresentationChangerTester r;
331 :
332 115 : Node* n = r.Parameter();
333 115 : Node* use = r.Return(n);
334 115 : Node* c1 =
335 115 : r.changer()->GetRepresentationFor(n, from, from_type, use, use_info);
336 :
337 115 : CHECK_NE(c1, n);
338 115 : CHECK_EQ(expected1, c1->opcode());
339 115 : Node* c2 = c1->InputAt(0);
340 115 : CHECK_NE(c2, n);
341 115 : CHECK_EQ(expected2, c2->opcode());
342 115 : CHECK_EQ(n, c2->InputAt(0));
343 115 : }
344 :
345 110 : static void CheckTwoChanges(IrOpcode::Value expected2,
346 : IrOpcode::Value expected1,
347 : MachineRepresentation from, Type from_type,
348 : MachineRepresentation to) {
349 : CheckTwoChanges(expected2, expected1, from, from_type, to,
350 220 : UseInfo(to, Truncation::None()));
351 110 : }
352 :
353 55 : static void CheckChange(IrOpcode::Value expected, MachineRepresentation from,
354 : Type from_type, MachineRepresentation to,
355 : UseInfo use_info) {
356 55 : RepresentationChangerTester r;
357 :
358 55 : Node* n = r.Parameter();
359 55 : Node* use = r.Return(n);
360 55 : Node* c =
361 55 : r.changer()->GetRepresentationFor(n, from, from_type, use, use_info);
362 :
363 55 : CHECK_NE(c, n);
364 55 : CHECK_EQ(expected, c->opcode());
365 55 : CHECK_EQ(n, c->InputAt(0));
366 55 : }
367 :
368 28342 : TEST(Word64) {
369 : CheckChange(IrOpcode::kChangeInt32ToInt64, MachineRepresentation::kWord8,
370 5 : TypeCache::Get()->kInt8, MachineRepresentation::kWord64);
371 : CheckChange(IrOpcode::kChangeUint32ToUint64, MachineRepresentation::kWord8,
372 5 : TypeCache::Get()->kUint8, MachineRepresentation::kWord64);
373 : CheckChange(IrOpcode::kChangeInt32ToInt64, MachineRepresentation::kWord16,
374 5 : TypeCache::Get()->kInt16, MachineRepresentation::kWord64);
375 : CheckChange(IrOpcode::kChangeUint32ToUint64, MachineRepresentation::kWord16,
376 5 : TypeCache::Get()->kUint16, MachineRepresentation::kWord64);
377 : CheckChange(IrOpcode::kChangeInt32ToInt64, MachineRepresentation::kWord32,
378 5 : Type::Signed32(), MachineRepresentation::kWord64);
379 : CheckChange(IrOpcode::kChangeUint32ToUint64, MachineRepresentation::kWord32,
380 5 : Type::Unsigned32(), MachineRepresentation::kWord64);
381 :
382 : CheckChange(IrOpcode::kTruncateInt64ToInt32, MachineRepresentation::kWord64,
383 5 : Type::Signed32(), MachineRepresentation::kWord32);
384 : CheckChange(IrOpcode::kTruncateInt64ToInt32, MachineRepresentation::kWord64,
385 5 : Type::Unsigned32(), MachineRepresentation::kWord32);
386 : CheckChange(IrOpcode::kTruncateInt64ToInt32, MachineRepresentation::kWord64,
387 5 : TypeCache::Get()->kSafeInteger, MachineRepresentation::kWord32,
388 5 : UseInfo::TruncatingWord32());
389 : CheckChange(
390 : IrOpcode::kCheckedInt64ToInt32, MachineRepresentation::kWord64,
391 5 : TypeCache::Get()->kSafeInteger, MachineRepresentation::kWord32,
392 10 : UseInfo::CheckedSigned32AsWord32(kIdentifyZeros, VectorSlotPair()));
393 : CheckChange(
394 : IrOpcode::kCheckedUint64ToInt32, MachineRepresentation::kWord64,
395 5 : TypeCache::Get()->kPositiveSafeInteger, MachineRepresentation::kWord32,
396 10 : UseInfo::CheckedSigned32AsWord32(kIdentifyZeros, VectorSlotPair()));
397 :
398 : CheckChange(IrOpcode::kChangeFloat64ToInt64, MachineRepresentation::kFloat64,
399 5 : Type::Signed32(), MachineRepresentation::kWord64);
400 : CheckChange(IrOpcode::kChangeFloat64ToInt64, MachineRepresentation::kFloat64,
401 5 : Type::Unsigned32(), MachineRepresentation::kWord64);
402 : CheckChange(IrOpcode::kChangeFloat64ToInt64, MachineRepresentation::kFloat64,
403 5 : TypeCache::Get()->kSafeInteger, MachineRepresentation::kWord64);
404 : CheckChange(IrOpcode::kChangeFloat64ToInt64, MachineRepresentation::kFloat64,
405 5 : TypeCache::Get()->kInt64, MachineRepresentation::kWord64);
406 : CheckChange(IrOpcode::kChangeFloat64ToUint64, MachineRepresentation::kFloat64,
407 5 : TypeCache::Get()->kUint64, MachineRepresentation::kWord64);
408 : CheckChange(
409 : IrOpcode::kCheckedFloat64ToInt64, MachineRepresentation::kFloat64,
410 : Type::Number(), MachineRepresentation::kWord64,
411 10 : UseInfo::CheckedSigned64AsWord64(kIdentifyZeros, VectorSlotPair()));
412 :
413 : CheckChange(IrOpcode::kChangeInt64ToFloat64, MachineRepresentation::kWord64,
414 5 : Type::Signed32(), MachineRepresentation::kFloat64);
415 : CheckChange(IrOpcode::kChangeInt64ToFloat64, MachineRepresentation::kWord64,
416 5 : Type::Unsigned32(), MachineRepresentation::kFloat64);
417 : CheckChange(IrOpcode::kChangeInt64ToFloat64, MachineRepresentation::kWord64,
418 5 : TypeCache::Get()->kSafeInteger, MachineRepresentation::kFloat64);
419 :
420 : CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
421 : IrOpcode::kChangeFloat64ToInt64,
422 : MachineRepresentation::kFloat32, Type::Signed32(),
423 5 : MachineRepresentation::kWord64);
424 : CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
425 : IrOpcode::kChangeFloat64ToInt64,
426 : MachineRepresentation::kFloat32, Type::Unsigned32(),
427 5 : MachineRepresentation::kWord64);
428 : CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
429 : IrOpcode::kChangeFloat64ToInt64,
430 5 : MachineRepresentation::kFloat32, TypeCache::Get()->kInt64,
431 5 : MachineRepresentation::kWord64);
432 : CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
433 : IrOpcode::kChangeFloat64ToUint64,
434 5 : MachineRepresentation::kFloat32, TypeCache::Get()->kUint64,
435 5 : MachineRepresentation::kWord64);
436 : CheckTwoChanges(
437 : IrOpcode::kChangeFloat32ToFloat64, IrOpcode::kCheckedFloat64ToInt64,
438 : MachineRepresentation::kFloat32, Type::Number(),
439 : MachineRepresentation::kWord64,
440 10 : UseInfo::CheckedSigned64AsWord64(kIdentifyZeros, VectorSlotPair()));
441 :
442 : CheckTwoChanges(IrOpcode::kChangeInt64ToFloat64,
443 : IrOpcode::kTruncateFloat64ToFloat32,
444 : MachineRepresentation::kWord64, Type::Signed32(),
445 5 : MachineRepresentation::kFloat32);
446 :
447 : CheckChange(IrOpcode::kChangeTaggedToInt64, MachineRepresentation::kTagged,
448 5 : Type::Signed32(), MachineRepresentation::kWord64);
449 : CheckChange(IrOpcode::kChangeTaggedToInt64, MachineRepresentation::kTagged,
450 5 : Type::Unsigned32(), MachineRepresentation::kWord64);
451 : CheckChange(IrOpcode::kChangeTaggedToInt64, MachineRepresentation::kTagged,
452 5 : TypeCache::Get()->kSafeInteger, MachineRepresentation::kWord64);
453 : CheckChange(IrOpcode::kChangeTaggedToInt64, MachineRepresentation::kTagged,
454 5 : TypeCache::Get()->kInt64, MachineRepresentation::kWord64);
455 : CheckChange(IrOpcode::kChangeTaggedSignedToInt64,
456 : MachineRepresentation::kTaggedSigned, Type::SignedSmall(),
457 5 : MachineRepresentation::kWord64);
458 : CheckChange(
459 : IrOpcode::kCheckedTaggedToInt64, MachineRepresentation::kTagged,
460 : Type::Number(), MachineRepresentation::kWord64,
461 10 : UseInfo::CheckedSigned64AsWord64(kIdentifyZeros, VectorSlotPair()));
462 : CheckChange(
463 : IrOpcode::kCheckedTaggedToInt64, MachineRepresentation::kTaggedPointer,
464 : Type::Number(), MachineRepresentation::kWord64,
465 10 : UseInfo::CheckedSigned64AsWord64(kIdentifyZeros, VectorSlotPair()));
466 :
467 : CheckTwoChanges(IrOpcode::kTruncateInt64ToInt32,
468 : IrOpcode::kChangeInt31ToTaggedSigned,
469 : MachineRepresentation::kWord64, Type::Signed31(),
470 5 : MachineRepresentation::kTagged);
471 : CheckTwoChanges(IrOpcode::kTruncateInt64ToInt32,
472 : IrOpcode::kChangeInt32ToTagged,
473 : MachineRepresentation::kWord64, Type::Signed32(),
474 5 : MachineRepresentation::kTagged);
475 : CheckTwoChanges(IrOpcode::kTruncateInt64ToInt32,
476 : IrOpcode::kChangeUint32ToTagged,
477 : MachineRepresentation::kWord64, Type::Unsigned32(),
478 5 : MachineRepresentation::kTagged);
479 : CheckChange(IrOpcode::kChangeInt64ToTagged, MachineRepresentation::kWord64,
480 5 : TypeCache::Get()->kSafeInteger, MachineRepresentation::kTagged);
481 : CheckChange(IrOpcode::kChangeUint64ToTagged, MachineRepresentation::kWord64,
482 5 : TypeCache::Get()->kPositiveSafeInteger,
483 5 : MachineRepresentation::kTagged);
484 :
485 : CheckTwoChanges(IrOpcode::kTruncateInt64ToInt32,
486 : IrOpcode::kChangeInt31ToTaggedSigned,
487 : MachineRepresentation::kWord64, Type::Signed31(),
488 5 : MachineRepresentation::kTaggedSigned);
489 : if (SmiValuesAre32Bits()) {
490 : CheckTwoChanges(IrOpcode::kTruncateInt64ToInt32,
491 : IrOpcode::kChangeInt32ToTagged,
492 : MachineRepresentation::kWord64, Type::Signed32(),
493 5 : MachineRepresentation::kTaggedSigned);
494 : }
495 : CheckChange(IrOpcode::kCheckedInt64ToTaggedSigned,
496 5 : MachineRepresentation::kWord64, TypeCache::Get()->kSafeInteger,
497 : MachineRepresentation::kTaggedSigned,
498 10 : UseInfo::CheckedSignedSmallAsTaggedSigned(VectorSlotPair()));
499 : CheckChange(IrOpcode::kCheckedUint64ToTaggedSigned,
500 : MachineRepresentation::kWord64,
501 5 : TypeCache::Get()->kPositiveSafeInteger,
502 : MachineRepresentation::kTaggedSigned,
503 10 : UseInfo::CheckedSignedSmallAsTaggedSigned(VectorSlotPair()));
504 :
505 : CheckTwoChanges(
506 : IrOpcode::kChangeInt64ToFloat64, IrOpcode::kChangeFloat64ToTaggedPointer,
507 5 : MachineRepresentation::kWord64, TypeCache::Get()->kSafeInteger,
508 5 : MachineRepresentation::kTaggedPointer);
509 5 : }
510 :
511 28342 : TEST(SingleChanges) {
512 : CheckChange(IrOpcode::kChangeTaggedToBit, MachineRepresentation::kTagged,
513 5 : Type::Boolean(), MachineRepresentation::kBit);
514 : CheckChange(IrOpcode::kChangeBitToTagged, MachineRepresentation::kBit,
515 5 : Type::Boolean(), MachineRepresentation::kTagged);
516 :
517 : CheckChange(IrOpcode::kChangeInt31ToTaggedSigned,
518 : MachineRepresentation::kWord32, Type::Signed31(),
519 5 : MachineRepresentation::kTagged);
520 : CheckChange(IrOpcode::kChangeInt32ToTagged, MachineRepresentation::kWord32,
521 5 : Type::Signed32(), MachineRepresentation::kTagged);
522 : CheckChange(IrOpcode::kChangeUint32ToTagged, MachineRepresentation::kWord32,
523 5 : Type::Unsigned32(), MachineRepresentation::kTagged);
524 : CheckChange(IrOpcode::kChangeFloat64ToTagged, MachineRepresentation::kFloat64,
525 5 : Type::Number(), MachineRepresentation::kTagged);
526 : CheckTwoChanges(IrOpcode::kChangeFloat64ToInt32,
527 : IrOpcode::kChangeInt31ToTaggedSigned,
528 : MachineRepresentation::kFloat64, Type::Signed31(),
529 5 : MachineRepresentation::kTagged);
530 : CheckTwoChanges(IrOpcode::kChangeFloat64ToInt32,
531 : IrOpcode::kChangeInt32ToTagged,
532 : MachineRepresentation::kFloat64, Type::Signed32(),
533 5 : MachineRepresentation::kTagged);
534 : CheckTwoChanges(IrOpcode::kChangeFloat64ToUint32,
535 : IrOpcode::kChangeUint32ToTagged,
536 : MachineRepresentation::kFloat64, Type::Unsigned32(),
537 5 : MachineRepresentation::kTagged);
538 :
539 : CheckChange(IrOpcode::kChangeTaggedToInt32, MachineRepresentation::kTagged,
540 5 : Type::Signed32(), MachineRepresentation::kWord32);
541 : CheckChange(IrOpcode::kChangeTaggedToUint32, MachineRepresentation::kTagged,
542 5 : Type::Unsigned32(), MachineRepresentation::kWord32);
543 : CheckChange(IrOpcode::kChangeTaggedToFloat64, MachineRepresentation::kTagged,
544 5 : Type::Number(), MachineRepresentation::kFloat64);
545 : CheckChange(IrOpcode::kTruncateTaggedToFloat64,
546 : MachineRepresentation::kTagged, Type::NumberOrUndefined(),
547 5 : MachineRepresentation::kFloat64);
548 : CheckChange(IrOpcode::kChangeTaggedToFloat64, MachineRepresentation::kTagged,
549 5 : Type::Signed31(), MachineRepresentation::kFloat64);
550 :
551 : // Int32,Uint32 <-> Float64 are actually machine conversions.
552 : CheckChange(IrOpcode::kChangeInt32ToFloat64, MachineRepresentation::kWord32,
553 5 : Type::Signed32(), MachineRepresentation::kFloat64);
554 : CheckChange(IrOpcode::kChangeInt32ToFloat64, MachineRepresentation::kWord32,
555 : Type::Signed32OrMinusZero(), MachineRepresentation::kFloat64,
556 : UseInfo(MachineRepresentation::kFloat64,
557 10 : Truncation::Any(kIdentifyZeros)));
558 : CheckChange(IrOpcode::kChangeUint32ToFloat64, MachineRepresentation::kWord32,
559 5 : Type::Unsigned32(), MachineRepresentation::kFloat64);
560 : CheckChange(IrOpcode::kChangeFloat64ToInt32, MachineRepresentation::kFloat64,
561 5 : Type::Signed32(), MachineRepresentation::kWord32);
562 : CheckChange(IrOpcode::kChangeFloat64ToUint32, MachineRepresentation::kFloat64,
563 5 : Type::Unsigned32(), MachineRepresentation::kWord32);
564 :
565 : CheckChange(IrOpcode::kTruncateFloat64ToFloat32,
566 : MachineRepresentation::kFloat64, Type::Number(),
567 5 : MachineRepresentation::kFloat32);
568 :
569 : // Int32,Uint32 <-> Float32 require two changes.
570 : CheckTwoChanges(IrOpcode::kChangeInt32ToFloat64,
571 : IrOpcode::kTruncateFloat64ToFloat32,
572 : MachineRepresentation::kWord32, Type::Signed32(),
573 5 : MachineRepresentation::kFloat32);
574 : CheckTwoChanges(IrOpcode::kChangeUint32ToFloat64,
575 : IrOpcode::kTruncateFloat64ToFloat32,
576 : MachineRepresentation::kWord32, Type::Unsigned32(),
577 5 : MachineRepresentation::kFloat32);
578 : CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
579 : IrOpcode::kChangeFloat64ToInt32,
580 : MachineRepresentation::kFloat32, Type::Signed32(),
581 5 : MachineRepresentation::kWord32);
582 : CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
583 : IrOpcode::kChangeFloat64ToUint32,
584 : MachineRepresentation::kFloat32, Type::Unsigned32(),
585 5 : MachineRepresentation::kWord32);
586 :
587 : // Float32 <-> Tagged require two changes.
588 : CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
589 : IrOpcode::kChangeFloat64ToTagged,
590 : MachineRepresentation::kFloat32, Type::Number(),
591 5 : MachineRepresentation::kTagged);
592 : CheckTwoChanges(IrOpcode::kChangeTaggedToFloat64,
593 : IrOpcode::kTruncateFloat64ToFloat32,
594 : MachineRepresentation::kTagged, Type::Number(),
595 5 : MachineRepresentation::kFloat32);
596 5 : }
597 :
598 :
599 28342 : TEST(SignednessInWord32) {
600 5 : RepresentationChangerTester r;
601 :
602 : CheckChange(IrOpcode::kChangeTaggedToInt32, MachineRepresentation::kTagged,
603 5 : Type::Signed32(), MachineRepresentation::kWord32);
604 : CheckChange(IrOpcode::kChangeTaggedToUint32, MachineRepresentation::kTagged,
605 5 : Type::Unsigned32(), MachineRepresentation::kWord32);
606 : CheckChange(IrOpcode::kChangeInt32ToFloat64, MachineRepresentation::kWord32,
607 5 : Type::Signed32(), MachineRepresentation::kFloat64);
608 : CheckChange(IrOpcode::kChangeFloat64ToInt32, MachineRepresentation::kFloat64,
609 5 : Type::Signed32(), MachineRepresentation::kWord32);
610 : CheckChange(IrOpcode::kTruncateFloat64ToWord32,
611 : MachineRepresentation::kFloat64, Type::Number(),
612 : MachineRepresentation::kWord32,
613 10 : UseInfo(MachineRepresentation::kWord32, Truncation::Word32()));
614 : CheckChange(IrOpcode::kCheckedTruncateTaggedToWord32,
615 : MachineRepresentation::kTagged, Type::NonInternal(),
616 : MachineRepresentation::kWord32,
617 10 : UseInfo::CheckedNumberOrOddballAsWord32(VectorSlotPair()));
618 :
619 : CheckTwoChanges(IrOpcode::kChangeInt32ToFloat64,
620 : IrOpcode::kTruncateFloat64ToFloat32,
621 : MachineRepresentation::kWord32, Type::Signed32(),
622 5 : MachineRepresentation::kFloat32);
623 : CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
624 : IrOpcode::kTruncateFloat64ToWord32,
625 : MachineRepresentation::kFloat32, Type::Number(),
626 5 : MachineRepresentation::kWord32);
627 :
628 : CheckChange(
629 : IrOpcode::kCheckedUint32ToInt32, MachineRepresentation::kWord32,
630 : Type::Unsigned32(),
631 10 : UseInfo::CheckedSigned32AsWord32(kIdentifyZeros, VectorSlotPair()));
632 5 : }
633 :
634 10 : static void TestMinusZeroCheck(IrOpcode::Value expected, Type from_type) {
635 10 : RepresentationChangerTester r;
636 :
637 : CheckChange(
638 : expected, MachineRepresentation::kFloat64, from_type,
639 20 : UseInfo::CheckedSignedSmallAsWord32(kDistinguishZeros, VectorSlotPair()));
640 :
641 : CheckChange(
642 : expected, MachineRepresentation::kFloat64, from_type,
643 20 : UseInfo::CheckedSignedSmallAsWord32(kIdentifyZeros, VectorSlotPair()));
644 :
645 : CheckChange(
646 : expected, MachineRepresentation::kFloat64, from_type,
647 20 : UseInfo::CheckedSigned32AsWord32(kDistinguishZeros, VectorSlotPair()));
648 :
649 : CheckChange(
650 : expected, MachineRepresentation::kFloat64, from_type,
651 20 : UseInfo::CheckedSigned32AsWord32(kDistinguishZeros, VectorSlotPair()));
652 10 : }
653 :
654 28342 : TEST(MinusZeroCheck) {
655 5 : TestMinusZeroCheck(IrOpcode::kCheckedFloat64ToInt32, Type::NumberOrOddball());
656 : // PlainNumber cannot be minus zero so the minus zero check should be
657 : // eliminated.
658 5 : TestMinusZeroCheck(IrOpcode::kCheckedFloat64ToInt32, Type::PlainNumber());
659 5 : }
660 :
661 28342 : TEST(Nops) {
662 5 : RepresentationChangerTester r;
663 :
664 : // X -> X is always a nop for any single representation X.
665 60 : for (size_t i = 0; i < arraysize(kMachineTypes); i++) {
666 : r.CheckNop(kMachineTypes[i].representation(), Type::Number(),
667 55 : kMachineTypes[i].representation());
668 : }
669 :
670 : // 32-bit floats.
671 : r.CheckNop(MachineRepresentation::kFloat32, Type::Number(),
672 5 : MachineRepresentation::kFloat32);
673 :
674 : // 32-bit words can be used as smaller word sizes and vice versa, because
675 : // loads from memory implicitly sign or zero extend the value to the
676 : // full machine word size, and stores implicitly truncate.
677 : r.CheckNop(MachineRepresentation::kWord32, Type::Signed32(),
678 5 : MachineRepresentation::kWord8);
679 : r.CheckNop(MachineRepresentation::kWord32, Type::Signed32(),
680 5 : MachineRepresentation::kWord16);
681 : r.CheckNop(MachineRepresentation::kWord32, Type::Signed32(),
682 5 : MachineRepresentation::kWord32);
683 : r.CheckNop(MachineRepresentation::kWord8, Type::Signed32(),
684 5 : MachineRepresentation::kWord32);
685 : r.CheckNop(MachineRepresentation::kWord16, Type::Signed32(),
686 5 : MachineRepresentation::kWord32);
687 :
688 : // kRepBit (result of comparison) is implicitly a wordish thing.
689 : r.CheckNop(MachineRepresentation::kBit, Type::Boolean(),
690 5 : MachineRepresentation::kWord8);
691 : r.CheckNop(MachineRepresentation::kBit, Type::Boolean(),
692 5 : MachineRepresentation::kWord16);
693 : r.CheckNop(MachineRepresentation::kBit, Type::Boolean(),
694 5 : MachineRepresentation::kWord32);
695 : r.CheckNop(MachineRepresentation::kBit, Type::Boolean(),
696 5 : MachineRepresentation::kWord64);
697 5 : }
698 :
699 :
700 28342 : TEST(TypeErrors) {
701 5 : RepresentationChangerTester r;
702 :
703 : // Floats cannot be implicitly converted to/from comparison conditions.
704 : r.CheckTypeError(MachineRepresentation::kBit, Type::Number(),
705 5 : MachineRepresentation::kFloat32);
706 : r.CheckTypeError(MachineRepresentation::kBit, Type::Boolean(),
707 5 : MachineRepresentation::kFloat32);
708 :
709 : // Word64 is internal and shouldn't be implicitly converted.
710 : r.CheckTypeError(MachineRepresentation::kWord64, Type::Internal(),
711 5 : MachineRepresentation::kTagged);
712 : r.CheckTypeError(MachineRepresentation::kTagged, Type::Number(),
713 5 : MachineRepresentation::kWord64);
714 : r.CheckTypeError(MachineRepresentation::kTagged, Type::Boolean(),
715 5 : MachineRepresentation::kWord64);
716 : r.CheckTypeError(MachineRepresentation::kWord64, Type::Internal(),
717 5 : MachineRepresentation::kWord32);
718 : r.CheckTypeError(MachineRepresentation::kWord32, Type::Number(),
719 5 : MachineRepresentation::kWord64);
720 5 : }
721 :
722 : } // namespace compiler
723 : } // namespace internal
724 85011 : } // namespace v8
|