blob: d1aa5af7fa2c45f7a88a48998a63639df606fa07 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
13namespace v8 {
14namespace internal {
15namespace compiler {
16
17const 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
57Truncation::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 truncations");
68 return TruncationKind::kNone;
69}
70
71
72// static
73bool 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
98namespace {
99
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000100bool IsWord(MachineRepresentation rep) {
101 return rep == MachineRepresentation::kWord8 ||
102 rep == MachineRepresentation::kWord16 ||
103 rep == MachineRepresentation::kWord32;
104}
105
106} // namespace
107
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000108// Changes representation from {output_rep} 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).
112Node* RepresentationChanger::GetRepresentationFor(
113 Node* node, MachineRepresentation output_rep, Type* output_type,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100114 Node* use_node, UseInfo use_info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000115 if (output_rep == MachineRepresentation::kNone) {
116 // The output representation should be set.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100117 return TypeError(node, output_rep, output_type, use_info.representation());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000118 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100119
120 // Handle the no-op shortcuts when no checking is necessary.
121 if (use_info.type_check() == TypeCheckKind::kNone ||
122 output_rep != MachineRepresentation::kWord32) {
123 if (use_info.representation() == output_rep) {
124 // Representations are the same. That's a no-op.
125 return node;
126 }
127 if (IsWord(use_info.representation()) && IsWord(output_rep)) {
128 // Both are words less than or equal to 32-bits.
129 // Since loads of integers from memory implicitly sign or zero extend the
130 // value to the full machine word size and stores implicitly truncate,
131 // no representation change is necessary.
132 return node;
133 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000134 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100135
136 switch (use_info.representation()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000137 case MachineRepresentation::kTagged:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100138 DCHECK(use_info.type_check() == TypeCheckKind::kNone);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000139 return GetTaggedRepresentationFor(node, output_rep, output_type);
140 case MachineRepresentation::kFloat32:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100141 DCHECK(use_info.type_check() == TypeCheckKind::kNone);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000142 return GetFloat32RepresentationFor(node, output_rep, output_type,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100143 use_info.truncation());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000144 case MachineRepresentation::kFloat64:
145 return GetFloat64RepresentationFor(node, output_rep, output_type,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100146 use_node, use_info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147 case MachineRepresentation::kBit:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100148 DCHECK(use_info.type_check() == TypeCheckKind::kNone);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000149 return GetBitRepresentationFor(node, output_rep, output_type);
150 case MachineRepresentation::kWord8:
151 case MachineRepresentation::kWord16:
152 case MachineRepresentation::kWord32:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100153 return GetWord32RepresentationFor(node, output_rep, output_type, use_node,
154 use_info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000155 case MachineRepresentation::kWord64:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100156 DCHECK(use_info.type_check() == TypeCheckKind::kNone);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000157 return GetWord64RepresentationFor(node, output_rep, output_type);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100158 case MachineRepresentation::kSimd128: // Fall through.
159 // TODO(bbudge) Handle conversions between tagged and untagged.
160 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000161 case MachineRepresentation::kNone:
162 return node;
163 }
164 UNREACHABLE();
165 return nullptr;
166}
167
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000168Node* RepresentationChanger::GetTaggedRepresentationFor(
169 Node* node, MachineRepresentation output_rep, Type* output_type) {
170 // Eagerly fold representation changes for constants.
171 switch (node->opcode()) {
172 case IrOpcode::kNumberConstant:
173 case IrOpcode::kHeapConstant:
174 return node; // No change necessary.
175 case IrOpcode::kInt32Constant:
176 if (output_type->Is(Type::Signed32())) {
177 int32_t value = OpParameter<int32_t>(node);
178 return jsgraph()->Constant(value);
179 } else if (output_type->Is(Type::Unsigned32())) {
180 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
181 return jsgraph()->Constant(static_cast<double>(value));
182 } else if (output_rep == MachineRepresentation::kBit) {
183 return OpParameter<int32_t>(node) == 0 ? jsgraph()->FalseConstant()
184 : jsgraph()->TrueConstant();
185 } else {
186 return TypeError(node, output_rep, output_type,
187 MachineRepresentation::kTagged);
188 }
189 case IrOpcode::kFloat64Constant:
190 return jsgraph()->Constant(OpParameter<double>(node));
191 case IrOpcode::kFloat32Constant:
192 return jsgraph()->Constant(OpParameter<float>(node));
193 default:
194 break;
195 }
196 // Select the correct X -> Tagged operator.
197 const Operator* op;
198 if (output_rep == MachineRepresentation::kBit) {
Ben Murdochc5610432016-08-08 18:44:38 +0100199 op = simplified()->ChangeBitToTagged();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000200 } else if (IsWord(output_rep)) {
Ben Murdochc5610432016-08-08 18:44:38 +0100201 if (output_type->Is(Type::Signed31())) {
202 op = simplified()->ChangeInt31ToTaggedSigned();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203 } else if (output_type->Is(Type::Signed32())) {
204 op = simplified()->ChangeInt32ToTagged();
Ben Murdochc5610432016-08-08 18:44:38 +0100205 } else if (output_type->Is(Type::Unsigned32())) {
206 op = simplified()->ChangeUint32ToTagged();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000207 } else {
208 return TypeError(node, output_rep, output_type,
209 MachineRepresentation::kTagged);
210 }
211 } else if (output_rep ==
212 MachineRepresentation::kFloat32) { // float32 -> float64 -> tagged
213 node = InsertChangeFloat32ToFloat64(node);
Ben Murdochc5610432016-08-08 18:44:38 +0100214 // TODO(bmeurer): Pass -0 hint to ChangeFloat64ToTagged.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000215 op = simplified()->ChangeFloat64ToTagged();
216 } else if (output_rep == MachineRepresentation::kFloat64) {
Ben Murdochc5610432016-08-08 18:44:38 +0100217 if (output_type->Is(Type::Signed31())) { // float64 -> int32 -> tagged
218 node = InsertChangeFloat64ToInt32(node);
219 op = simplified()->ChangeInt31ToTaggedSigned();
220 } else if (output_type->Is(
221 Type::Signed32())) { // float64 -> int32 -> tagged
222 node = InsertChangeFloat64ToInt32(node);
223 op = simplified()->ChangeInt32ToTagged();
224 } else if (output_type->Is(
225 Type::Unsigned32())) { // float64 -> uint32 -> tagged
226 node = InsertChangeFloat64ToUint32(node);
227 op = simplified()->ChangeUint32ToTagged();
228 } else {
229 // TODO(bmeurer): Pass -0 hint to ChangeFloat64ToTagged.
230 op = simplified()->ChangeFloat64ToTagged();
231 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000232 } else {
233 return TypeError(node, output_rep, output_type,
234 MachineRepresentation::kTagged);
235 }
236 return jsgraph()->graph()->NewNode(op, node);
237}
238
239
240Node* RepresentationChanger::GetFloat32RepresentationFor(
241 Node* node, MachineRepresentation output_rep, Type* output_type,
242 Truncation truncation) {
243 // Eagerly fold representation changes for constants.
244 switch (node->opcode()) {
245 case IrOpcode::kFloat64Constant:
246 case IrOpcode::kNumberConstant:
247 return jsgraph()->Float32Constant(
248 DoubleToFloat32(OpParameter<double>(node)));
249 case IrOpcode::kInt32Constant:
250 if (output_type->Is(Type::Unsigned32())) {
251 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
252 return jsgraph()->Float32Constant(static_cast<float>(value));
253 } else {
254 int32_t value = OpParameter<int32_t>(node);
255 return jsgraph()->Float32Constant(static_cast<float>(value));
256 }
257 case IrOpcode::kFloat32Constant:
258 return node; // No change necessary.
259 default:
260 break;
261 }
262 // Select the correct X -> Float32 operator.
Ben Murdochda12d292016-06-02 14:46:10 +0100263 const Operator* op = nullptr;
264 if (IsWord(output_rep)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000265 if (output_type->Is(Type::Signed32())) {
Ben Murdochda12d292016-06-02 14:46:10 +0100266 // int32 -> float64 -> float32
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000267 op = machine()->ChangeInt32ToFloat64();
Ben Murdochda12d292016-06-02 14:46:10 +0100268 node = jsgraph()->graph()->NewNode(op, node);
269 op = machine()->TruncateFloat64ToFloat32();
270 } else if (output_type->Is(Type::Unsigned32()) ||
271 truncation.TruncatesToWord32()) {
272 // Either the output is uint32 or the uses only care about the
273 // low 32 bits (so we can pick uint32 safely).
274
275 // uint32 -> float64 -> float32
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000276 op = machine()->ChangeUint32ToFloat64();
Ben Murdochda12d292016-06-02 14:46:10 +0100277 node = jsgraph()->graph()->NewNode(op, node);
278 op = machine()->TruncateFloat64ToFloat32();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000279 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000280 } else if (output_rep == MachineRepresentation::kTagged) {
Ben Murdochc5610432016-08-08 18:44:38 +0100281 if (output_type->Is(Type::NumberOrUndefined())) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100282 // tagged -> float64 -> float32
283 if (output_type->Is(Type::Number())) {
284 op = simplified()->ChangeTaggedToFloat64();
285 } else {
286 op = simplified()->TruncateTaggedToFloat64();
287 }
Ben Murdochda12d292016-06-02 14:46:10 +0100288 node = jsgraph()->graph()->NewNode(op, node);
289 op = machine()->TruncateFloat64ToFloat32();
290 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000291 } else if (output_rep == MachineRepresentation::kFloat64) {
292 op = machine()->TruncateFloat64ToFloat32();
Ben Murdochda12d292016-06-02 14:46:10 +0100293 }
294 if (op == nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000295 return TypeError(node, output_rep, output_type,
296 MachineRepresentation::kFloat32);
297 }
298 return jsgraph()->graph()->NewNode(op, node);
299}
300
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301Node* RepresentationChanger::GetFloat64RepresentationFor(
302 Node* node, MachineRepresentation output_rep, Type* output_type,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100303 Node* use_node, UseInfo use_info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000304 // Eagerly fold representation changes for constants.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100305 if ((use_info.type_check() == TypeCheckKind::kNone)) {
306 // TODO(jarin) Handle checked constant conversions.
307 switch (node->opcode()) {
308 case IrOpcode::kNumberConstant:
309 return jsgraph()->Float64Constant(OpParameter<double>(node));
310 case IrOpcode::kInt32Constant:
311 if (output_type->Is(Type::Signed32())) {
312 int32_t value = OpParameter<int32_t>(node);
313 return jsgraph()->Float64Constant(value);
314 } else {
315 DCHECK(output_type->Is(Type::Unsigned32()));
316 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
317 return jsgraph()->Float64Constant(static_cast<double>(value));
318 }
319 case IrOpcode::kFloat64Constant:
320 return node; // No change necessary.
321 case IrOpcode::kFloat32Constant:
322 return jsgraph()->Float64Constant(OpParameter<float>(node));
323 default:
324 break;
325 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000326 }
327 // Select the correct X -> Float64 operator.
Ben Murdochda12d292016-06-02 14:46:10 +0100328 const Operator* op = nullptr;
329 if (IsWord(output_rep)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000330 if (output_type->Is(Type::Signed32())) {
331 op = machine()->ChangeInt32ToFloat64();
Ben Murdochda12d292016-06-02 14:46:10 +0100332 } else if (output_type->Is(Type::Unsigned32()) ||
Ben Murdoch61f157c2016-09-16 13:49:30 +0100333 use_info.truncation().TruncatesToWord32()) {
Ben Murdochda12d292016-06-02 14:46:10 +0100334 // Either the output is uint32 or the uses only care about the
335 // low 32 bits (so we can pick uint32 safely).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000336 op = machine()->ChangeUint32ToFloat64();
337 }
338 } else if (output_rep == MachineRepresentation::kTagged) {
Ben Murdochc5610432016-08-08 18:44:38 +0100339 if (output_type->Is(Type::Undefined())) {
340 return jsgraph()->Float64Constant(
341 std::numeric_limits<double>::quiet_NaN());
342 } else if (output_type->Is(Type::TaggedSigned())) {
343 node = InsertChangeTaggedSignedToInt32(node);
344 op = machine()->ChangeInt32ToFloat64();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100345 } else if (output_type->Is(Type::Number())) {
Ben Murdochda12d292016-06-02 14:46:10 +0100346 op = simplified()->ChangeTaggedToFloat64();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100347 } else if (output_type->Is(Type::NumberOrUndefined())) {
348 // TODO(jarin) Here we should check that truncation is Number.
349 op = simplified()->TruncateTaggedToFloat64();
350 } else if (use_info.type_check() == TypeCheckKind::kNumberOrUndefined) {
351 op = simplified()->CheckedTaggedToFloat64();
Ben Murdochda12d292016-06-02 14:46:10 +0100352 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000353 } else if (output_rep == MachineRepresentation::kFloat32) {
354 op = machine()->ChangeFloat32ToFloat64();
Ben Murdochda12d292016-06-02 14:46:10 +0100355 }
356 if (op == nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000357 return TypeError(node, output_rep, output_type,
358 MachineRepresentation::kFloat64);
359 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100360 return InsertConversion(node, op, use_node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000361}
362
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000363Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) {
364 return jsgraph()->Int32Constant(DoubleToInt32(value));
365}
366
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000367Node* RepresentationChanger::GetWord32RepresentationFor(
Ben Murdochda12d292016-06-02 14:46:10 +0100368 Node* node, MachineRepresentation output_rep, Type* output_type,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100369 Node* use_node, UseInfo use_info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000370 // Eagerly fold representation changes for constants.
371 switch (node->opcode()) {
372 case IrOpcode::kInt32Constant:
373 return node; // No change necessary.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100374 case IrOpcode::kFloat32Constant: {
375 float const fv = OpParameter<float>(node);
376 if (use_info.type_check() == TypeCheckKind::kNone ||
377 (use_info.type_check() == TypeCheckKind::kSigned32 &&
378 IsInt32Double(fv))) {
379 return MakeTruncatedInt32Constant(fv);
380 }
381 break;
382 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000383 case IrOpcode::kNumberConstant:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100384 case IrOpcode::kFloat64Constant: {
385 double const fv = OpParameter<double>(node);
386 if (use_info.type_check() == TypeCheckKind::kNone ||
387 (use_info.type_check() == TypeCheckKind::kSigned32 &&
388 IsInt32Double(fv))) {
389 return MakeTruncatedInt32Constant(fv);
390 }
391 break;
392 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000393 default:
394 break;
395 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100396
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000397 // Select the correct X -> Word32 operator.
Ben Murdochda12d292016-06-02 14:46:10 +0100398 const Operator* op = nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000399 if (output_rep == MachineRepresentation::kBit) {
400 return node; // Sloppy comparison -> word32
401 } else if (output_rep == MachineRepresentation::kFloat64) {
Ben Murdochda12d292016-06-02 14:46:10 +0100402 if (output_type->Is(Type::Unsigned32())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000403 op = machine()->ChangeFloat64ToUint32();
Ben Murdochda12d292016-06-02 14:46:10 +0100404 } else if (output_type->Is(Type::Signed32())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000405 op = machine()->ChangeFloat64ToInt32();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100406 } else if (use_info.truncation().TruncatesToWord32()) {
Ben Murdochc5610432016-08-08 18:44:38 +0100407 op = machine()->TruncateFloat64ToWord32();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100408 } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
409 op = simplified()->CheckedFloat64ToInt32();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000410 }
411 } else if (output_rep == MachineRepresentation::kFloat32) {
412 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32
Ben Murdochda12d292016-06-02 14:46:10 +0100413 if (output_type->Is(Type::Unsigned32())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000414 op = machine()->ChangeFloat64ToUint32();
Ben Murdochda12d292016-06-02 14:46:10 +0100415 } else if (output_type->Is(Type::Signed32())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000416 op = machine()->ChangeFloat64ToInt32();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100417 } else if (use_info.truncation().TruncatesToWord32()) {
Ben Murdochc5610432016-08-08 18:44:38 +0100418 op = machine()->TruncateFloat64ToWord32();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100419 } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
420 op = simplified()->CheckedFloat64ToInt32();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000421 }
422 } else if (output_rep == MachineRepresentation::kTagged) {
Ben Murdochc5610432016-08-08 18:44:38 +0100423 if (output_type->Is(Type::TaggedSigned())) {
424 op = simplified()->ChangeTaggedSignedToInt32();
425 } else if (output_type->Is(Type::Unsigned32())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000426 op = simplified()->ChangeTaggedToUint32();
Ben Murdochda12d292016-06-02 14:46:10 +0100427 } else if (output_type->Is(Type::Signed32())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000428 op = simplified()->ChangeTaggedToInt32();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100429 } else if (use_info.truncation().TruncatesToWord32()) {
Ben Murdochc5610432016-08-08 18:44:38 +0100430 op = simplified()->TruncateTaggedToWord32();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100431 } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
432 op = simplified()->CheckedTaggedToInt32();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000433 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100434 } else if (output_rep == MachineRepresentation::kWord32) {
435 // Only the checked case should get here, the non-checked case is
436 // handled in GetRepresentationFor.
437 DCHECK(use_info.type_check() == TypeCheckKind::kSigned32);
438 if (output_type->Is(Type::Signed32())) {
439 return node;
440 } else if (output_type->Is(Type::Unsigned32())) {
441 op = simplified()->CheckedUint32ToInt32();
442 }
443 } else if (output_rep == MachineRepresentation::kWord8 ||
444 output_rep == MachineRepresentation::kWord16) {
445 DCHECK(use_info.representation() == MachineRepresentation::kWord32);
446 DCHECK(use_info.type_check() == TypeCheckKind::kSigned32);
447 return node;
Ben Murdochda12d292016-06-02 14:46:10 +0100448 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100449
Ben Murdochda12d292016-06-02 14:46:10 +0100450 if (op == nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000451 return TypeError(node, output_rep, output_type,
452 MachineRepresentation::kWord32);
453 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100454 return InsertConversion(node, op, use_node);
455}
456
457Node* RepresentationChanger::InsertConversion(Node* node, const Operator* op,
458 Node* use_node) {
459 if (op->ControlInputCount() > 0) {
460 // If the operator can deoptimize (which means it has control
461 // input), we need to connect it to the effect and control chains.
462 Node* effect = NodeProperties::GetEffectInput(use_node);
463 Node* control = NodeProperties::GetControlInput(use_node);
464 Node* conversion = jsgraph()->graph()->NewNode(op, node, effect, control);
465 NodeProperties::ReplaceEffectInput(use_node, conversion);
466 return conversion;
467 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000468 return jsgraph()->graph()->NewNode(op, node);
469}
470
471
472Node* RepresentationChanger::GetBitRepresentationFor(
473 Node* node, MachineRepresentation output_rep, Type* output_type) {
474 // Eagerly fold representation changes for constants.
475 switch (node->opcode()) {
476 case IrOpcode::kHeapConstant: {
477 Handle<HeapObject> value = OpParameter<Handle<HeapObject>>(node);
478 DCHECK(value.is_identical_to(factory()->true_value()) ||
479 value.is_identical_to(factory()->false_value()));
480 return jsgraph()->Int32Constant(
481 value.is_identical_to(factory()->true_value()) ? 1 : 0);
482 }
483 default:
484 break;
485 }
486 // Select the correct X -> Bit operator.
487 const Operator* op;
488 if (output_rep == MachineRepresentation::kTagged) {
Ben Murdochc5610432016-08-08 18:44:38 +0100489 op = simplified()->ChangeTaggedToBit();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000490 } else {
491 return TypeError(node, output_rep, output_type,
492 MachineRepresentation::kBit);
493 }
494 return jsgraph()->graph()->NewNode(op, node);
495}
496
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000497Node* RepresentationChanger::GetWord64RepresentationFor(
498 Node* node, MachineRepresentation output_rep, Type* output_type) {
499 if (output_rep == MachineRepresentation::kBit) {
500 return node; // Sloppy comparison -> word64
501 }
502 // Can't really convert Word64 to anything else. Purported to be internal.
503 return TypeError(node, output_rep, output_type,
504 MachineRepresentation::kWord64);
505}
506
Ben Murdoch61f157c2016-09-16 13:49:30 +0100507Node* RepresentationChanger::GetCheckedWord32RepresentationFor(
508 Node* node, MachineRepresentation output_rep, Type* output_type,
509 Node* use_node, Truncation truncation, TypeCheckKind check) {
510 // TODO(jarin) Eagerly fold constants (or insert hard deopt if the constant
511 // does not pass the check).
512
513 // If the input is already Signed32 in Word32 representation, we do not
514 // have to do anything. (We could fold this into the big if below, but
515 // it feels nicer to have the shortcut return first).
516 if (output_rep == MachineRepresentation::kWord32 ||
517 output_type->Is(Type::Signed32())) {
518 return node;
519 }
520
521 // Select the correct X -> Word32 operator.
522 const Operator* op = nullptr;
523 if (output_rep == MachineRepresentation::kWord32) {
524 if (output_type->Is(Type::Unsigned32())) {
525 op = simplified()->CheckedUint32ToInt32();
526 }
527 } else if (output_rep == MachineRepresentation::kBit) {
528 return node; // Sloppy comparison -> word32
529 } else if (output_rep == MachineRepresentation::kFloat64) {
530 if (output_type->Is(Type::Unsigned32())) {
531 op = machine()->ChangeFloat64ToUint32();
532 } else if (output_type->Is(Type::Signed32())) {
533 op = machine()->ChangeFloat64ToInt32();
534 } else if (truncation.TruncatesToWord32()) {
535 op = machine()->TruncateFloat64ToWord32();
536 } else if (check == TypeCheckKind::kSigned32) {
537 op = simplified()->CheckedFloat64ToInt32();
538 }
539 } else if (output_rep == MachineRepresentation::kFloat32) {
540 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32
541 if (output_type->Is(Type::Unsigned32())) {
542 op = machine()->ChangeFloat64ToUint32();
543 } else if (output_type->Is(Type::Signed32())) {
544 op = machine()->ChangeFloat64ToInt32();
545 } else if (truncation.TruncatesToWord32()) {
546 op = machine()->TruncateFloat64ToWord32();
547 } else if (check == TypeCheckKind::kSigned32) {
548 op = simplified()->CheckedFloat64ToInt32();
549 }
550 } else if (output_rep == MachineRepresentation::kTagged) {
551 if (output_type->Is(Type::TaggedSigned())) {
552 op = simplified()->ChangeTaggedSignedToInt32();
553 } else if (output_type->Is(Type::Unsigned32())) {
554 op = simplified()->ChangeTaggedToUint32();
555 } else if (output_type->Is(Type::Signed32())) {
556 op = simplified()->ChangeTaggedToInt32();
557 } else if (truncation.TruncatesToWord32()) {
558 op = simplified()->TruncateTaggedToWord32();
559 } else if (check == TypeCheckKind::kSigned32) {
560 op = simplified()->CheckedTaggedToInt32();
561 }
562 }
563 if (op == nullptr) {
564 return TypeError(node, output_rep, output_type,
565 MachineRepresentation::kWord32);
566 }
567 if (op->ControlInputCount() > 0) {
568 // If the operator can deoptimize (which means it has control
569 // input), we need to connect it to the effect and control chains.
570 UNIMPLEMENTED();
571 }
572 return jsgraph()->graph()->NewNode(op, node);
573}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000574
575const Operator* RepresentationChanger::Int32OperatorFor(
576 IrOpcode::Value opcode) {
577 switch (opcode) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100578 case IrOpcode::kSpeculativeNumberAdd: // Fall through.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000579 case IrOpcode::kNumberAdd:
580 return machine()->Int32Add();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100581 case IrOpcode::kSpeculativeNumberSubtract: // Fall through.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000582 case IrOpcode::kNumberSubtract:
583 return machine()->Int32Sub();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100584 case IrOpcode::kSpeculativeNumberMultiply:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000585 case IrOpcode::kNumberMultiply:
586 return machine()->Int32Mul();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100587 case IrOpcode::kSpeculativeNumberDivide:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000588 case IrOpcode::kNumberDivide:
589 return machine()->Int32Div();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100590 case IrOpcode::kSpeculativeNumberModulus:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000591 case IrOpcode::kNumberModulus:
592 return machine()->Int32Mod();
593 case IrOpcode::kNumberBitwiseOr:
594 return machine()->Word32Or();
595 case IrOpcode::kNumberBitwiseXor:
596 return machine()->Word32Xor();
597 case IrOpcode::kNumberBitwiseAnd:
598 return machine()->Word32And();
599 case IrOpcode::kNumberEqual:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100600 case IrOpcode::kSpeculativeNumberEqual:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000601 return machine()->Word32Equal();
602 case IrOpcode::kNumberLessThan:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100603 case IrOpcode::kSpeculativeNumberLessThan:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000604 return machine()->Int32LessThan();
605 case IrOpcode::kNumberLessThanOrEqual:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100606 case IrOpcode::kSpeculativeNumberLessThanOrEqual:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000607 return machine()->Int32LessThanOrEqual();
608 default:
609 UNREACHABLE();
610 return nullptr;
611 }
612}
613
Ben Murdoch61f157c2016-09-16 13:49:30 +0100614const Operator* RepresentationChanger::Int32OverflowOperatorFor(
615 IrOpcode::Value opcode) {
616 switch (opcode) {
617 case IrOpcode::kSpeculativeNumberAdd: // Fall through.
618 return simplified()->CheckedInt32Add();
619 case IrOpcode::kSpeculativeNumberSubtract: // Fall through.
620 return simplified()->CheckedInt32Sub();
621 default:
622 UNREACHABLE();
623 return nullptr;
624 }
625}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000626
627const Operator* RepresentationChanger::Uint32OperatorFor(
628 IrOpcode::Value opcode) {
629 switch (opcode) {
630 case IrOpcode::kNumberAdd:
631 return machine()->Int32Add();
632 case IrOpcode::kNumberSubtract:
633 return machine()->Int32Sub();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100634 case IrOpcode::kSpeculativeNumberMultiply:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000635 case IrOpcode::kNumberMultiply:
636 return machine()->Int32Mul();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100637 case IrOpcode::kSpeculativeNumberDivide:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000638 case IrOpcode::kNumberDivide:
639 return machine()->Uint32Div();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100640 case IrOpcode::kSpeculativeNumberModulus:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000641 case IrOpcode::kNumberModulus:
642 return machine()->Uint32Mod();
643 case IrOpcode::kNumberEqual:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100644 case IrOpcode::kSpeculativeNumberEqual:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000645 return machine()->Word32Equal();
646 case IrOpcode::kNumberLessThan:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100647 case IrOpcode::kSpeculativeNumberLessThan:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000648 return machine()->Uint32LessThan();
649 case IrOpcode::kNumberLessThanOrEqual:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100650 case IrOpcode::kSpeculativeNumberLessThanOrEqual:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000651 return machine()->Uint32LessThanOrEqual();
Ben Murdochda12d292016-06-02 14:46:10 +0100652 case IrOpcode::kNumberClz32:
653 return machine()->Word32Clz();
654 case IrOpcode::kNumberImul:
655 return machine()->Int32Mul();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000656 default:
657 UNREACHABLE();
658 return nullptr;
659 }
660}
661
662
663const Operator* RepresentationChanger::Float64OperatorFor(
664 IrOpcode::Value opcode) {
665 switch (opcode) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100666 case IrOpcode::kSpeculativeNumberAdd:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000667 case IrOpcode::kNumberAdd:
668 return machine()->Float64Add();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100669 case IrOpcode::kSpeculativeNumberSubtract:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000670 case IrOpcode::kNumberSubtract:
671 return machine()->Float64Sub();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100672 case IrOpcode::kSpeculativeNumberMultiply:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000673 case IrOpcode::kNumberMultiply:
674 return machine()->Float64Mul();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100675 case IrOpcode::kSpeculativeNumberDivide:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000676 case IrOpcode::kNumberDivide:
677 return machine()->Float64Div();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100678 case IrOpcode::kSpeculativeNumberModulus:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000679 case IrOpcode::kNumberModulus:
680 return machine()->Float64Mod();
681 case IrOpcode::kNumberEqual:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100682 case IrOpcode::kSpeculativeNumberEqual:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000683 return machine()->Float64Equal();
684 case IrOpcode::kNumberLessThan:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100685 case IrOpcode::kSpeculativeNumberLessThan:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000686 return machine()->Float64LessThan();
687 case IrOpcode::kNumberLessThanOrEqual:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100688 case IrOpcode::kSpeculativeNumberLessThanOrEqual:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000689 return machine()->Float64LessThanOrEqual();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100690 case IrOpcode::kNumberAbs:
691 return machine()->Float64Abs();
692 case IrOpcode::kNumberAtan:
693 return machine()->Float64Atan();
694 case IrOpcode::kNumberAtan2:
695 return machine()->Float64Atan2();
696 case IrOpcode::kNumberCos:
697 return machine()->Float64Cos();
698 case IrOpcode::kNumberExp:
699 return machine()->Float64Exp();
700 case IrOpcode::kNumberFround:
701 return machine()->TruncateFloat64ToFloat32();
702 case IrOpcode::kNumberAtanh:
703 return machine()->Float64Atanh();
704 case IrOpcode::kNumberLog:
705 return machine()->Float64Log();
706 case IrOpcode::kNumberLog1p:
707 return machine()->Float64Log1p();
708 case IrOpcode::kNumberLog2:
709 return machine()->Float64Log2();
710 case IrOpcode::kNumberLog10:
711 return machine()->Float64Log10();
712 case IrOpcode::kNumberSin:
713 return machine()->Float64Sin();
714 case IrOpcode::kNumberTan:
715 return machine()->Float64Tan();
716 case IrOpcode::kNumberSqrt:
717 return machine()->Float64Sqrt();
718 case IrOpcode::kNumberCbrt:
719 return machine()->Float64Cbrt();
720 case IrOpcode::kNumberExpm1:
721 return machine()->Float64Expm1();
722 case IrOpcode::kNumberSilenceNaN:
723 return machine()->Float64SilenceNaN();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000724 default:
725 UNREACHABLE();
726 return nullptr;
727 }
728}
729
730
731Node* RepresentationChanger::TypeError(Node* node,
732 MachineRepresentation output_rep,
733 Type* output_type,
734 MachineRepresentation use) {
735 type_error_ = true;
736 if (!testing_type_errors_) {
737 std::ostringstream out_str;
738 out_str << output_rep << " (";
739 output_type->PrintTo(out_str, Type::SEMANTIC_DIM);
740 out_str << ")";
741
742 std::ostringstream use_str;
743 use_str << use;
744
745 V8_Fatal(__FILE__, __LINE__,
746 "RepresentationChangerError: node #%d:%s of "
747 "%s cannot be changed to %s",
748 node->id(), node->op()->mnemonic(), out_str.str().c_str(),
749 use_str.str().c_str());
750 }
751 return node;
752}
753
754
755Node* RepresentationChanger::InsertChangeFloat32ToFloat64(Node* node) {
756 return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(), node);
757}
758
Ben Murdochc5610432016-08-08 18:44:38 +0100759Node* RepresentationChanger::InsertChangeFloat64ToUint32(Node* node) {
760 return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToUint32(), node);
761}
762
763Node* RepresentationChanger::InsertChangeFloat64ToInt32(Node* node) {
764 return jsgraph()->graph()->NewNode(machine()->ChangeFloat64ToInt32(), node);
765}
766
767Node* RepresentationChanger::InsertChangeTaggedSignedToInt32(Node* node) {
768 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(),
769 node);
770}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000771
772Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) {
773 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(),
774 node);
775}
776
777} // namespace compiler
778} // namespace internal
779} // namespace v8