OLD | NEW |
---|---|
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/simd-scalar-lowering.h" | 5 #include "src/compiler/simd-scalar-lowering.h" |
6 #include "src/compiler/diamond.h" | 6 #include "src/compiler/diamond.h" |
7 #include "src/compiler/linkage.h" | 7 #include "src/compiler/linkage.h" |
8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
9 #include "src/compiler/node-properties.h" | 9 #include "src/compiler/node-properties.h" |
10 | 10 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
73 | 73 |
74 #define FOREACH_INT32X4_OPCODE(V) \ | 74 #define FOREACH_INT32X4_OPCODE(V) \ |
75 V(Int32x4Splat) \ | 75 V(Int32x4Splat) \ |
76 V(Int32x4ExtractLane) \ | 76 V(Int32x4ExtractLane) \ |
77 V(Int32x4ReplaceLane) \ | 77 V(Int32x4ReplaceLane) \ |
78 V(Int32x4Neg) \ | 78 V(Int32x4Neg) \ |
79 V(Simd128Not) \ | 79 V(Simd128Not) \ |
80 V(Int32x4Add) \ | 80 V(Int32x4Add) \ |
81 V(Int32x4Sub) \ | 81 V(Int32x4Sub) \ |
82 V(Int32x4Mul) \ | 82 V(Int32x4Mul) \ |
83 V(Int32x4Min) \ | |
84 V(Int32x4Max) \ | |
85 V(Uint32x4Min) \ | |
86 V(Uint32x4Max) \ | |
83 V(Simd128And) \ | 87 V(Simd128And) \ |
84 V(Simd128Or) \ | 88 V(Simd128Or) \ |
85 V(Simd128Xor) | 89 V(Simd128Xor) \ |
90 V(Int32x4FromFloat32x4) \ | |
91 V(Uint32x4FromFloat32x4) | |
86 | 92 |
87 #define FOREACH_FLOAT32X4_OPCODE(V) \ | 93 #define FOREACH_FLOAT32X4_OPCODE(V) \ |
88 V(Float32x4Splat) \ | 94 V(Float32x4Splat) \ |
89 V(Float32x4ExtractLane) \ | 95 V(Float32x4ExtractLane) \ |
90 V(Float32x4ReplaceLane) \ | 96 V(Float32x4ReplaceLane) \ |
91 V(Float32x4Abs) \ | 97 V(Float32x4Abs) \ |
92 V(Float32x4Neg) \ | 98 V(Float32x4Neg) \ |
93 V(Float32x4Add) \ | 99 V(Float32x4Add) \ |
94 V(Float32x4Sub) \ | 100 V(Float32x4Sub) \ |
95 V(Float32x4Mul) \ | 101 V(Float32x4Mul) \ |
(...skipping 11 matching lines...) Expand all Loading... | |
107 case IrOpcode::kParameter: | 113 case IrOpcode::kParameter: |
108 case IrOpcode::kCall: { | 114 case IrOpcode::kCall: { |
109 replacements_[node->id()].type = SimdType::kInt32; | 115 replacements_[node->id()].type = SimdType::kInt32; |
110 break; | 116 break; |
111 } | 117 } |
112 FOREACH_FLOAT32X4_OPCODE(CASE_STMT) { | 118 FOREACH_FLOAT32X4_OPCODE(CASE_STMT) { |
113 replacements_[node->id()].type = SimdType::kFloat32; | 119 replacements_[node->id()].type = SimdType::kFloat32; |
114 break; | 120 break; |
115 } | 121 } |
116 #undef CASE_STMT | 122 #undef CASE_STMT |
117 default: { | 123 default: { |
titzer
2017/03/01 09:40:28
Probably time for an innner switch now?
aseemgarg
2017/03/01 10:55:16
Done.
| |
118 if (output->opcode() == IrOpcode::kFloat32x4FromInt32x4 || | 124 if (output->opcode() == IrOpcode::kFloat32x4FromInt32x4 || |
119 output->opcode() == IrOpcode::kFloat32x4FromUint32x4) { | 125 output->opcode() == IrOpcode::kFloat32x4FromUint32x4) { |
120 replacements_[node->id()].type = SimdType::kInt32; | 126 replacements_[node->id()].type = SimdType::kInt32; |
127 } else if (output->opcode() == IrOpcode::kInt32x4FromFloat32x4 || | |
128 output->opcode() == IrOpcode::kUint32x4FromFloat32x4) { | |
129 replacements_[node->id()].type = SimdType::kFloat32; | |
121 } else { | 130 } else { |
122 replacements_[node->id()].type = replacements_[output->id()].type; | 131 replacements_[node->id()].type = replacements_[output->id()].type; |
123 } | 132 } |
124 } | 133 } |
125 } | 134 } |
126 } | 135 } |
127 | 136 |
128 static int GetParameterIndexAfterLowering( | 137 static int GetParameterIndexAfterLowering( |
129 Signature<MachineRepresentation>* signature, int old_index) { | 138 Signature<MachineRepresentation>* signature, int old_index) { |
130 // In function calls, the simd128 types are passed as 4 Int32 types. The | 139 // In function calls, the simd128 types are passed as 4 Int32 types. The |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
257 const Operator* op) { | 266 const Operator* op) { |
258 DCHECK(node->InputCount() == 1); | 267 DCHECK(node->InputCount() == 1); |
259 Node** rep = GetReplacementsWithType(node->InputAt(0), input_rep_type); | 268 Node** rep = GetReplacementsWithType(node->InputAt(0), input_rep_type); |
260 Node* rep_node[kMaxLanes]; | 269 Node* rep_node[kMaxLanes]; |
261 for (int i = 0; i < kMaxLanes; ++i) { | 270 for (int i = 0; i < kMaxLanes; ++i) { |
262 rep_node[i] = graph()->NewNode(op, rep[i]); | 271 rep_node[i] = graph()->NewNode(op, rep[i]); |
263 } | 272 } |
264 ReplaceNode(node, rep_node); | 273 ReplaceNode(node, rep_node); |
265 } | 274 } |
266 | 275 |
276 void SimdScalarLowering::LowerIntMinMax(Node* node, const Operator* op, | |
277 bool is_max) { | |
278 DCHECK(node->InputCount() == 2); | |
279 Node** rep_left = GetReplacementsWithType(node->InputAt(0), SimdType::kInt32); | |
280 Node** rep_right = | |
281 GetReplacementsWithType(node->InputAt(1), SimdType::kInt32); | |
282 Node* rep_node[kMaxLanes]; | |
283 for (int i = 0; i < kMaxLanes; ++i) { | |
284 Diamond d(graph(), common(), | |
285 graph()->NewNode(op, rep_left[i], rep_right[i])); | |
286 if (is_max) { | |
287 rep_node[i] = | |
288 d.Phi(MachineRepresentation::kWord32, rep_right[i], rep_left[i]); | |
289 } else { | |
290 rep_node[i] = | |
291 d.Phi(MachineRepresentation::kWord32, rep_left[i], rep_right[i]); | |
292 } | |
293 } | |
294 ReplaceNode(node, rep_node); | |
295 } | |
296 | |
297 void SimdScalarLowering::LowerConvertFromFloat(Node* node, bool is_signed) { | |
298 DCHECK(node->InputCount() == 1); | |
299 Node** rep = GetReplacementsWithType(node->InputAt(0), SimdType::kFloat32); | |
300 Node* rep_node[kMaxLanes]; | |
301 Node* double_zero = graph()->NewNode(common()->Float64Constant(0.0)); | |
302 Node* min = graph()->NewNode( | |
303 common()->Float64Constant(static_cast<double>(is_signed ? kMinInt : 0))); | |
304 Node* max = graph()->NewNode(common()->Float64Constant( | |
305 static_cast<double>(is_signed ? kMaxInt : 0xffffffffu))); | |
306 for (int i = 0; i < kMaxLanes; ++i) { | |
307 Node* double_rep = | |
308 graph()->NewNode(machine()->ChangeFloat32ToFloat64(), rep[i]); | |
309 Diamond nan_d(graph(), common(), graph()->NewNode(machine()->Float64Equal(), | |
310 double_rep, double_rep)); | |
311 Node* temp = | |
312 nan_d.Phi(MachineRepresentation::kFloat64, double_rep, double_zero); | |
313 Diamond min_d(graph(), common(), | |
314 graph()->NewNode(machine()->Float64LessThan(), temp, min)); | |
315 temp = min_d.Phi(MachineRepresentation::kFloat64, min, temp); | |
316 Diamond max_d(graph(), common(), | |
317 graph()->NewNode(machine()->Float64LessThan(), max, temp)); | |
318 // if (!machine()->Float32RoundTruncate().IsSupported()) { | |
titzer
2017/03/01 09:40:28
Is this code ncessary? if not, then please remove
aseemgarg
2017/03/01 10:55:16
Removed. All bots are passing with this commented
| |
319 // trunc = BuildF32Trunc(input); | |
320 // } else { | |
321 // trunc = | |
322 // } | |
323 temp = max_d.Phi(MachineRepresentation::kFloat64, max, temp); | |
324 Node* trunc = | |
325 graph()->NewNode(machine()->Float64RoundTruncate().op(), temp); | |
326 if (is_signed) { | |
327 rep_node[i] = graph()->NewNode(machine()->ChangeFloat64ToInt32(), trunc); | |
328 } else { | |
329 rep_node[i] = | |
330 graph()->NewNode(machine()->TruncateFloat64ToUint32(), trunc); | |
331 } | |
332 } | |
333 ReplaceNode(node, rep_node); | |
334 } | |
335 | |
336 void SimdScalarLowering::LowerShiftOp(Node* node, const Operator* op) { | |
337 static int32_t shift_mask = 0x1f; | |
338 DCHECK_EQ(1, node->InputCount()); | |
339 int32_t shift_amount = OpParameter<int32_t>(node); | |
340 Node* shift_node = | |
341 graph()->NewNode(common()->Int32Constant(shift_amount & shift_mask)); | |
342 Node** rep = GetReplacementsWithType(node->InputAt(0), SimdType::kInt32); | |
343 Node* rep_node[kMaxLanes]; | |
344 for (int i = 0; i < kMaxLanes; ++i) { | |
345 rep_node[i] = graph()->NewNode(op, rep[i], shift_node); | |
346 } | |
347 ReplaceNode(node, rep_node); | |
348 } | |
349 | |
267 void SimdScalarLowering::LowerNode(Node* node) { | 350 void SimdScalarLowering::LowerNode(Node* node) { |
268 SimdType rep_type = ReplacementType(node); | 351 SimdType rep_type = ReplacementType(node); |
269 switch (node->opcode()) { | 352 switch (node->opcode()) { |
270 case IrOpcode::kStart: { | 353 case IrOpcode::kStart: { |
271 int parameter_count = GetParameterCountAfterLowering(); | 354 int parameter_count = GetParameterCountAfterLowering(); |
272 // Only exchange the node if the parameter count actually changed. | 355 // Only exchange the node if the parameter count actually changed. |
273 if (parameter_count != static_cast<int>(signature()->parameter_count())) { | 356 if (parameter_count != static_cast<int>(signature()->parameter_count())) { |
274 int delta = | 357 int delta = |
275 parameter_count - static_cast<int>(signature()->parameter_count()); | 358 parameter_count - static_cast<int>(signature()->parameter_count()); |
276 int new_output_count = node->op()->ValueOutputCount() + delta; | 359 int new_output_count = node->op()->ValueOutputCount() + delta; |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
415 LowerBinaryOp(node, rep_type, machine()->instruction()); \ | 498 LowerBinaryOp(node, rep_type, machine()->instruction()); \ |
416 break; \ | 499 break; \ |
417 } | 500 } |
418 I32X4_BINOP_CASE(kInt32x4Add, Int32Add) | 501 I32X4_BINOP_CASE(kInt32x4Add, Int32Add) |
419 I32X4_BINOP_CASE(kInt32x4Sub, Int32Sub) | 502 I32X4_BINOP_CASE(kInt32x4Sub, Int32Sub) |
420 I32X4_BINOP_CASE(kInt32x4Mul, Int32Mul) | 503 I32X4_BINOP_CASE(kInt32x4Mul, Int32Mul) |
421 I32X4_BINOP_CASE(kSimd128And, Word32And) | 504 I32X4_BINOP_CASE(kSimd128And, Word32And) |
422 I32X4_BINOP_CASE(kSimd128Or, Word32Or) | 505 I32X4_BINOP_CASE(kSimd128Or, Word32Or) |
423 I32X4_BINOP_CASE(kSimd128Xor, Word32Xor) | 506 I32X4_BINOP_CASE(kSimd128Xor, Word32Xor) |
424 #undef I32X4_BINOP_CASE | 507 #undef I32X4_BINOP_CASE |
508 case IrOpcode::kInt32x4Max: { | |
509 LowerIntMinMax(node, machine()->Int32LessThan(), true); | |
510 break; | |
511 } | |
512 case IrOpcode::kInt32x4Min: { | |
513 LowerIntMinMax(node, machine()->Int32LessThan(), false); | |
514 break; | |
515 } | |
516 case IrOpcode::kUint32x4Max: { | |
517 LowerIntMinMax(node, machine()->Uint32LessThan(), true); | |
518 break; | |
519 } | |
520 case IrOpcode::kUint32x4Min: { | |
521 LowerIntMinMax(node, machine()->Uint32LessThan(), false); | |
522 break; | |
523 } | |
425 case IrOpcode::kInt32x4Neg: { | 524 case IrOpcode::kInt32x4Neg: { |
426 DCHECK(node->InputCount() == 1); | 525 DCHECK(node->InputCount() == 1); |
427 Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type); | 526 Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type); |
428 Node* rep_node[kMaxLanes]; | 527 Node* rep_node[kMaxLanes]; |
429 for (int i = 0; i < kMaxLanes; ++i) { | 528 for (int i = 0; i < kMaxLanes; ++i) { |
430 rep_node[i] = graph()->NewNode( | 529 rep_node[i] = graph()->NewNode( |
431 machine()->Int32Sub(), graph()->NewNode(common()->Int32Constant(0)), | 530 machine()->Int32Sub(), graph()->NewNode(common()->Int32Constant(0)), |
432 rep[i]); | 531 rep[i]); |
433 } | 532 } |
434 ReplaceNode(node, rep_node); | 533 ReplaceNode(node, rep_node); |
435 break; | 534 break; |
436 } | 535 } |
437 case IrOpcode::kSimd128Not: { | 536 case IrOpcode::kSimd128Not: { |
438 DCHECK(node->InputCount() == 1); | 537 DCHECK(node->InputCount() == 1); |
439 Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type); | 538 Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type); |
440 Node* rep_node[kMaxLanes]; | 539 Node* rep_node[kMaxLanes]; |
441 for (int i = 0; i < kMaxLanes; ++i) { | 540 for (int i = 0; i < kMaxLanes; ++i) { |
442 rep_node[i] = graph()->NewNode( | 541 rep_node[i] = graph()->NewNode( |
443 machine()->Word32Xor(), rep[i], | 542 machine()->Word32Xor(), rep[i], |
444 graph()->NewNode(common()->Int32Constant(0xffffffff))); | 543 graph()->NewNode(common()->Int32Constant(0xffffffff))); |
445 } | 544 } |
446 ReplaceNode(node, rep_node); | 545 ReplaceNode(node, rep_node); |
447 break; | 546 break; |
448 } | 547 } |
548 case IrOpcode::kInt32x4FromFloat32x4: { | |
549 LowerConvertFromFloat(node, true); | |
550 break; | |
551 } | |
552 case IrOpcode::kUint32x4FromFloat32x4: { | |
553 LowerConvertFromFloat(node, false); | |
554 break; | |
555 } | |
556 case IrOpcode::kInt32x4ShiftLeftByScalar: { | |
557 LowerShiftOp(node, machine()->Word32Shl()); | |
558 break; | |
559 } | |
560 case IrOpcode::kInt32x4ShiftRightByScalar: { | |
561 LowerShiftOp(node, machine()->Word32Sar()); | |
562 break; | |
563 } | |
564 case IrOpcode::kUint32x4ShiftRightByScalar: { | |
565 LowerShiftOp(node, machine()->Word32Shr()); | |
566 break; | |
567 } | |
449 #define F32X4_BINOP_CASE(name) \ | 568 #define F32X4_BINOP_CASE(name) \ |
450 case IrOpcode::kFloat32x4##name: { \ | 569 case IrOpcode::kFloat32x4##name: { \ |
451 LowerBinaryOp(node, rep_type, machine()->Float32##name()); \ | 570 LowerBinaryOp(node, rep_type, machine()->Float32##name()); \ |
452 break; \ | 571 break; \ |
453 } | 572 } |
454 F32X4_BINOP_CASE(Add) | 573 F32X4_BINOP_CASE(Add) |
455 F32X4_BINOP_CASE(Sub) | 574 F32X4_BINOP_CASE(Sub) |
456 F32X4_BINOP_CASE(Mul) | 575 F32X4_BINOP_CASE(Mul) |
457 F32X4_BINOP_CASE(Div) | 576 F32X4_BINOP_CASE(Div) |
458 F32X4_BINOP_CASE(Min) | 577 F32X4_BINOP_CASE(Min) |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
618 } else { | 737 } else { |
619 UNREACHABLE(); | 738 UNREACHABLE(); |
620 } | 739 } |
621 } | 740 } |
622 ReplaceNode(phi, rep_nodes); | 741 ReplaceNode(phi, rep_nodes); |
623 } | 742 } |
624 } | 743 } |
625 } // namespace compiler | 744 } // namespace compiler |
626 } // namespace internal | 745 } // namespace internal |
627 } // namespace v8 | 746 } // namespace v8 |
OLD | NEW |