Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(91)

Side by Side Diff: src/compiler/representation-change.cc

Issue 1480433003: [turbofan] Introduce representation-change.cc, move stuff there, minus dead code. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/representation-change.h ('k') | src/compiler/simplified-lowering.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 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 "src/compiler/representation-change.h"
6
7 #include <sstream>
8
9 #include "src/base/bits.h"
10 #include "src/code-factory.h"
11 #include "src/compiler/machine-operator.h"
12
13 namespace v8 {
14 namespace internal {
15 namespace compiler {
16
17 const char* Truncation::description() const {
18 switch (kind()) {
19 case TruncationKind::kNone:
20 return "no-value-use";
21 case TruncationKind::kBool:
22 return "truncate-to-bool";
23 case TruncationKind::kWord32:
24 return "truncate-to-word32";
25 case TruncationKind::kWord64:
26 return "truncate-to-word64";
27 case TruncationKind::kFloat32:
28 return "truncate-to-float32";
29 case TruncationKind::kFloat64:
30 return "truncate-to-float64";
31 case TruncationKind::kAny:
32 return "no-truncation";
33 }
34 UNREACHABLE();
35 return nullptr;
36 }
37
38
39 // Partial order for truncations:
40 //
41 // kWord64 kAny
42 // ^ ^
43 // \ |
44 // \ kFloat64 <--+
45 // \ ^ ^ |
46 // \ / | |
47 // kWord32 kFloat32 kBool
48 // ^ ^ ^
49 // \ | /
50 // \ | /
51 // \ | /
52 // \ | /
53 // \ | /
54 // kNone
55
56 // static
57 Truncation::TruncationKind Truncation::Generalize(TruncationKind rep1,
58 TruncationKind rep2) {
59 if (LessGeneral(rep1, rep2)) return rep2;
60 if (LessGeneral(rep2, rep1)) return rep1;
61 // Handle the generalization of float64-representable values.
62 if (LessGeneral(rep1, TruncationKind::kFloat64) &&
63 LessGeneral(rep2, TruncationKind::kFloat64)) {
64 return TruncationKind::kFloat64;
65 }
66 // All other combinations are illegal.
67 FATAL("Tried to combine incompatible representations");
68 return TruncationKind::kNone;
69 }
70
71
72 // static
73 bool Truncation::LessGeneral(TruncationKind rep1, TruncationKind rep2) {
74 switch (rep1) {
75 case TruncationKind::kNone:
76 return true;
77 case TruncationKind::kBool:
78 return rep2 == TruncationKind::kBool || rep2 == TruncationKind::kAny;
79 case TruncationKind::kWord32:
80 return rep2 == TruncationKind::kWord32 ||
81 rep2 == TruncationKind::kWord64 ||
82 rep2 == TruncationKind::kFloat64 || rep2 == TruncationKind::kAny;
83 case TruncationKind::kWord64:
84 return rep2 == TruncationKind::kWord64;
85 case TruncationKind::kFloat32:
86 return rep2 == TruncationKind::kFloat32 ||
87 rep2 == TruncationKind::kFloat64 || rep2 == TruncationKind::kAny;
88 case TruncationKind::kFloat64:
89 return rep2 == TruncationKind::kFloat64 || rep2 == TruncationKind::kAny;
90 case TruncationKind::kAny:
91 return rep2 == TruncationKind::kAny;
92 }
93 UNREACHABLE();
94 return false;
95 }
96
97
98 namespace {
99
100 // TODO(titzer): should Word64 also be implicitly convertable to others?
101 bool IsWord(MachineTypeUnion type) {
102 return (type & (kRepWord8 | kRepWord16 | kRepWord32)) != 0;
103 }
104
105 } // namespace
106
107
108 // Changes representation from {output_type} to {use_rep}. The {truncation}
109 // parameter is only used for sanity checking - if the changer cannot figure
110 // out signedness for the word32->float64 conversion, then we check that the
111 // uses truncate to word32 (so they do not care about signedness).
112 Node* RepresentationChanger::GetRepresentationFor(Node* node,
113 MachineTypeUnion output_type,
114 MachineTypeUnion use_rep,
115 Truncation truncation) {
116 DCHECK((use_rep & kRepMask) == use_rep);
117 if (!base::bits::IsPowerOfTwo32(output_type & kRepMask)) {
118 // There should be only one output representation.
119 return TypeError(node, output_type, use_rep);
120 }
121 if (use_rep == (output_type & kRepMask)) {
122 // Representations are the same. That's a no-op.
123 return node;
124 }
125 if (IsWord(use_rep) && IsWord(output_type)) {
126 // Both are words less than or equal to 32-bits.
127 // Since loads of integers from memory implicitly sign or zero extend the
128 // value to the full machine word size and stores implicitly truncate,
129 // no representation change is necessary.
130 return node;
131 }
132 if (use_rep & kRepTagged) {
133 return GetTaggedRepresentationFor(node, output_type);
134 } else if (use_rep & kRepFloat32) {
135 return GetFloat32RepresentationFor(node, output_type, truncation);
136 } else if (use_rep & kRepFloat64) {
137 return GetFloat64RepresentationFor(node, output_type, truncation);
138 } else if (use_rep & kRepBit) {
139 return GetBitRepresentationFor(node, output_type);
140 } else if (IsWord(use_rep)) {
141 return GetWord32RepresentationFor(node, output_type);
142 } else if (use_rep & kRepWord64) {
143 return GetWord64RepresentationFor(node, output_type);
144 } else {
145 return node;
146 }
147 }
148
149
150 Node* RepresentationChanger::GetTaggedRepresentationFor(
151 Node* node, MachineTypeUnion output_type) {
152 // Eagerly fold representation changes for constants.
153 switch (node->opcode()) {
154 case IrOpcode::kNumberConstant:
155 case IrOpcode::kHeapConstant:
156 return node; // No change necessary.
157 case IrOpcode::kInt32Constant:
158 if (output_type & kTypeUint32) {
159 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
160 return jsgraph()->Constant(static_cast<double>(value));
161 } else if (output_type & kTypeInt32) {
162 int32_t value = OpParameter<int32_t>(node);
163 return jsgraph()->Constant(value);
164 } else if (output_type & kRepBit) {
165 return OpParameter<int32_t>(node) == 0 ? jsgraph()->FalseConstant()
166 : jsgraph()->TrueConstant();
167 } else {
168 return TypeError(node, output_type, kRepTagged);
169 }
170 case IrOpcode::kFloat64Constant:
171 return jsgraph()->Constant(OpParameter<double>(node));
172 case IrOpcode::kFloat32Constant:
173 return jsgraph()->Constant(OpParameter<float>(node));
174 default:
175 break;
176 }
177 // Select the correct X -> Tagged operator.
178 const Operator* op;
179 if (output_type & kRepBit) {
180 op = simplified()->ChangeBitToBool();
181 } else if (IsWord(output_type)) {
182 if (output_type & kTypeUint32) {
183 op = simplified()->ChangeUint32ToTagged();
184 } else if (output_type & kTypeInt32) {
185 op = simplified()->ChangeInt32ToTagged();
186 } else {
187 return TypeError(node, output_type, kRepTagged);
188 }
189 } else if (output_type & kRepFloat32) { // float32 -> float64 -> tagged
190 node = InsertChangeFloat32ToFloat64(node);
191 op = simplified()->ChangeFloat64ToTagged();
192 } else if (output_type & kRepFloat64) {
193 op = simplified()->ChangeFloat64ToTagged();
194 } else {
195 return TypeError(node, output_type, kRepTagged);
196 }
197 return jsgraph()->graph()->NewNode(op, node);
198 }
199
200
201 Node* RepresentationChanger::GetFloat32RepresentationFor(
202 Node* node, MachineTypeUnion output_type, Truncation truncation) {
203 // Eagerly fold representation changes for constants.
204 switch (node->opcode()) {
205 case IrOpcode::kFloat64Constant:
206 case IrOpcode::kNumberConstant:
207 return jsgraph()->Float32Constant(
208 DoubleToFloat32(OpParameter<double>(node)));
209 case IrOpcode::kInt32Constant:
210 if (output_type & kTypeUint32) {
211 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
212 return jsgraph()->Float32Constant(static_cast<float>(value));
213 } else {
214 int32_t value = OpParameter<int32_t>(node);
215 return jsgraph()->Float32Constant(static_cast<float>(value));
216 }
217 case IrOpcode::kFloat32Constant:
218 return node; // No change necessary.
219 default:
220 break;
221 }
222 // Select the correct X -> Float32 operator.
223 const Operator* op;
224 if (output_type & kRepBit) {
225 return TypeError(node, output_type, kRepFloat32);
226 } else if (IsWord(output_type)) {
227 if (output_type & kTypeUint32) {
228 op = machine()->ChangeUint32ToFloat64();
229 } else {
230 // Either the output is int32 or the uses only care about the
231 // low 32 bits (so we can pick int32 safely).
232 DCHECK(output_type & kTypeInt32 || truncation.TruncatesToWord32());
233 op = machine()->ChangeInt32ToFloat64();
234 }
235 // int32 -> float64 -> float32
236 node = jsgraph()->graph()->NewNode(op, node);
237 op = machine()->TruncateFloat64ToFloat32();
238 } else if (output_type & kRepTagged) {
239 op = simplified()->ChangeTaggedToFloat64(); // tagged -> float64 -> float32
240 node = jsgraph()->graph()->NewNode(op, node);
241 op = machine()->TruncateFloat64ToFloat32();
242 } else if (output_type & kRepFloat64) {
243 op = machine()->TruncateFloat64ToFloat32();
244 } else {
245 return TypeError(node, output_type, kRepFloat32);
246 }
247 return jsgraph()->graph()->NewNode(op, node);
248 }
249
250
251 Node* RepresentationChanger::GetFloat64RepresentationFor(
252 Node* node, MachineTypeUnion output_type, Truncation truncation) {
253 // Eagerly fold representation changes for constants.
254 switch (node->opcode()) {
255 case IrOpcode::kNumberConstant:
256 return jsgraph()->Float64Constant(OpParameter<double>(node));
257 case IrOpcode::kInt32Constant:
258 if (output_type & kTypeUint32) {
259 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
260 return jsgraph()->Float64Constant(static_cast<double>(value));
261 } else {
262 int32_t value = OpParameter<int32_t>(node);
263 return jsgraph()->Float64Constant(value);
264 }
265 case IrOpcode::kFloat64Constant:
266 return node; // No change necessary.
267 case IrOpcode::kFloat32Constant:
268 return jsgraph()->Float64Constant(OpParameter<float>(node));
269 default:
270 break;
271 }
272 // Select the correct X -> Float64 operator.
273 const Operator* op;
274 if (output_type & kRepBit) {
275 return TypeError(node, output_type, kRepFloat64);
276 } else if (IsWord(output_type)) {
277 if (output_type & kTypeUint32) {
278 op = machine()->ChangeUint32ToFloat64();
279 } else {
280 // Either the output is int32 or the uses only care about the
281 // low 32 bits (so we can pick int32 safely).
282 DCHECK(output_type & kTypeInt32 || truncation.TruncatesToWord32());
283 op = machine()->ChangeInt32ToFloat64();
284 }
285 } else if (output_type & kRepTagged) {
286 op = simplified()->ChangeTaggedToFloat64();
287 } else if (output_type & kRepFloat32) {
288 op = machine()->ChangeFloat32ToFloat64();
289 } else {
290 return TypeError(node, output_type, kRepFloat64);
291 }
292 return jsgraph()->graph()->NewNode(op, node);
293 }
294
295
296 Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) {
297 return jsgraph()->Int32Constant(DoubleToInt32(value));
298 }
299
300
301 Node* RepresentationChanger::GetWord32RepresentationFor(
302 Node* node, MachineTypeUnion output_type) {
303 // Eagerly fold representation changes for constants.
304 switch (node->opcode()) {
305 case IrOpcode::kInt32Constant:
306 return node; // No change necessary.
307 case IrOpcode::kFloat32Constant:
308 return MakeTruncatedInt32Constant(OpParameter<float>(node));
309 case IrOpcode::kNumberConstant:
310 case IrOpcode::kFloat64Constant:
311 return MakeTruncatedInt32Constant(OpParameter<double>(node));
312 default:
313 break;
314 }
315 // Select the correct X -> Word32 operator.
316 const Operator* op;
317 Type* type = NodeProperties::GetType(node);
318
319 if (output_type & kRepBit) {
320 return node; // Sloppy comparison -> word32
321 } else if (output_type & kRepFloat64) {
322 if (output_type & kTypeUint32 || type->Is(Type::Unsigned32())) {
323 op = machine()->ChangeFloat64ToUint32();
324 } else if (output_type & kTypeInt32 || type->Is(Type::Signed32())) {
325 op = machine()->ChangeFloat64ToInt32();
326 } else {
327 op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
328 }
329 } else if (output_type & kRepFloat32) {
330 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32
331 if (output_type & kTypeUint32 || type->Is(Type::Unsigned32())) {
332 op = machine()->ChangeFloat64ToUint32();
333 } else if (output_type & kTypeInt32 || type->Is(Type::Signed32())) {
334 op = machine()->ChangeFloat64ToInt32();
335 } else {
336 op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
337 }
338 } else if (output_type & kRepTagged) {
339 if (output_type & kTypeUint32 || type->Is(Type::Unsigned32())) {
340 op = simplified()->ChangeTaggedToUint32();
341 } else if (output_type & kTypeInt32 || type->Is(Type::Signed32())) {
342 op = simplified()->ChangeTaggedToInt32();
343 } else {
344 node = InsertChangeTaggedToFloat64(node);
345 op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
346 }
347 } else {
348 return TypeError(node, output_type, kRepWord32);
349 }
350 return jsgraph()->graph()->NewNode(op, node);
351 }
352
353
354 Node* RepresentationChanger::GetBitRepresentationFor(
355 Node* node, MachineTypeUnion output_type) {
356 // Eagerly fold representation changes for constants.
357 switch (node->opcode()) {
358 case IrOpcode::kHeapConstant: {
359 Handle<HeapObject> value = OpParameter<Handle<HeapObject>>(node);
360 DCHECK(value.is_identical_to(factory()->true_value()) ||
361 value.is_identical_to(factory()->false_value()));
362 return jsgraph()->Int32Constant(
363 value.is_identical_to(factory()->true_value()) ? 1 : 0);
364 }
365 default:
366 break;
367 }
368 // Select the correct X -> Bit operator.
369 const Operator* op;
370 if (output_type & kRepTagged) {
371 op = simplified()->ChangeBoolToBit();
372 } else {
373 return TypeError(node, output_type, kRepBit);
374 }
375 return jsgraph()->graph()->NewNode(op, node);
376 }
377
378
379 Node* RepresentationChanger::GetWord64RepresentationFor(
380 Node* node, MachineTypeUnion output_type) {
381 if (output_type & kRepBit) {
382 return node; // Sloppy comparison -> word64
383 }
384 // Can't really convert Word64 to anything else. Purported to be internal.
385 return TypeError(node, output_type, kRepWord64);
386 }
387
388
389 const Operator* RepresentationChanger::Int32OperatorFor(
390 IrOpcode::Value opcode) {
391 switch (opcode) {
392 case IrOpcode::kNumberAdd:
393 return machine()->Int32Add();
394 case IrOpcode::kNumberSubtract:
395 return machine()->Int32Sub();
396 case IrOpcode::kNumberMultiply:
397 return machine()->Int32Mul();
398 case IrOpcode::kNumberDivide:
399 return machine()->Int32Div();
400 case IrOpcode::kNumberModulus:
401 return machine()->Int32Mod();
402 case IrOpcode::kNumberBitwiseOr:
403 return machine()->Word32Or();
404 case IrOpcode::kNumberBitwiseXor:
405 return machine()->Word32Xor();
406 case IrOpcode::kNumberBitwiseAnd:
407 return machine()->Word32And();
408 case IrOpcode::kNumberEqual:
409 return machine()->Word32Equal();
410 case IrOpcode::kNumberLessThan:
411 return machine()->Int32LessThan();
412 case IrOpcode::kNumberLessThanOrEqual:
413 return machine()->Int32LessThanOrEqual();
414 default:
415 UNREACHABLE();
416 return NULL;
417 }
418 }
419
420
421 const Operator* RepresentationChanger::Uint32OperatorFor(
422 IrOpcode::Value opcode) {
423 switch (opcode) {
424 case IrOpcode::kNumberAdd:
425 return machine()->Int32Add();
426 case IrOpcode::kNumberSubtract:
427 return machine()->Int32Sub();
428 case IrOpcode::kNumberMultiply:
429 return machine()->Int32Mul();
430 case IrOpcode::kNumberDivide:
431 return machine()->Uint32Div();
432 case IrOpcode::kNumberModulus:
433 return machine()->Uint32Mod();
434 case IrOpcode::kNumberEqual:
435 return machine()->Word32Equal();
436 case IrOpcode::kNumberLessThan:
437 return machine()->Uint32LessThan();
438 case IrOpcode::kNumberLessThanOrEqual:
439 return machine()->Uint32LessThanOrEqual();
440 default:
441 UNREACHABLE();
442 return NULL;
443 }
444 }
445
446
447 const Operator* RepresentationChanger::Float64OperatorFor(
448 IrOpcode::Value opcode) {
449 switch (opcode) {
450 case IrOpcode::kNumberAdd:
451 return machine()->Float64Add();
452 case IrOpcode::kNumberSubtract:
453 return machine()->Float64Sub();
454 case IrOpcode::kNumberMultiply:
455 return machine()->Float64Mul();
456 case IrOpcode::kNumberDivide:
457 return machine()->Float64Div();
458 case IrOpcode::kNumberModulus:
459 return machine()->Float64Mod();
460 case IrOpcode::kNumberEqual:
461 return machine()->Float64Equal();
462 case IrOpcode::kNumberLessThan:
463 return machine()->Float64LessThan();
464 case IrOpcode::kNumberLessThanOrEqual:
465 return machine()->Float64LessThanOrEqual();
466 default:
467 UNREACHABLE();
468 return NULL;
469 }
470 }
471
472
473 MachineType RepresentationChanger::TypeFromUpperBound(Type* type) {
474 if (type->Is(Type::None()))
475 return kTypeAny; // TODO(titzer): should be an error
Benedikt Meurer 2015/11/25 09:31:05 Nit: Can we fix that? In follow up CL?
476 if (type->Is(Type::Signed32())) return kTypeInt32;
477 if (type->Is(Type::Unsigned32())) return kTypeUint32;
478 if (type->Is(Type::Number())) return kTypeNumber;
479 if (type->Is(Type::Boolean())) return kTypeBool;
480 return kTypeAny;
481 }
482
483
484 Node* RepresentationChanger::TypeError(Node* node, MachineTypeUnion output_type,
485 MachineTypeUnion use) {
486 type_error_ = true;
487 if (!testing_type_errors_) {
488 std::ostringstream out_str;
489 out_str << static_cast<MachineType>(output_type);
490
491 std::ostringstream use_str;
492 use_str << static_cast<MachineType>(use);
493
494 V8_Fatal(__FILE__, __LINE__,
495 "RepresentationChangerError: node #%d:%s of "
496 "%s cannot be changed to %s",
497 node->id(), node->op()->mnemonic(), out_str.str().c_str(),
498 use_str.str().c_str());
499 }
500 return node;
501 }
502
503
504 Node* RepresentationChanger::InsertChangeFloat32ToFloat64(Node* node) {
505 return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(), node);
506 }
507
508
509 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) {
510 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(),
511 node);
512 }
513
514 } // namespace compiler
515 } // namespace internal
516 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/representation-change.h ('k') | src/compiler/simplified-lowering.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698