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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 V(Float32x4Neg) \ | 93 V(Float32x4Neg) \ |
94 V(Float32x4Add) \ | 94 V(Float32x4Add) \ |
95 V(Float32x4Sub) \ | 95 V(Float32x4Sub) \ |
96 V(Float32x4Mul) \ | 96 V(Float32x4Mul) \ |
97 V(Float32x4Div) \ | 97 V(Float32x4Div) \ |
98 V(Float32x4Min) \ | 98 V(Float32x4Min) \ |
99 V(Float32x4Max) \ | 99 V(Float32x4Max) \ |
100 V(Float32x4FromInt32x4) \ | 100 V(Float32x4FromInt32x4) \ |
101 V(Float32x4FromUint32x4) | 101 V(Float32x4FromUint32x4) |
102 | 102 |
| 103 #define FOREACH_FLOAT32X4_TO_SIMD1X4OPCODE(V) \ |
| 104 V(Float32x4Equal) \ |
| 105 V(Float32x4NotEqual) \ |
| 106 V(Float32x4LessThan) \ |
| 107 V(Float32x4LessThanOrEqual) \ |
| 108 V(Float32x4GreaterThan) \ |
| 109 V(Float32x4GreaterThanOrEqual) |
| 110 |
| 111 #define FOREACH_INT32X4_TO_SIMD1X4OPCODE(V) \ |
| 112 V(Int32x4Equal) \ |
| 113 V(Int32x4NotEqual) \ |
| 114 V(Int32x4LessThan) \ |
| 115 V(Int32x4LessThanOrEqual) \ |
| 116 V(Int32x4GreaterThan) \ |
| 117 V(Int32x4GreaterThanOrEqual) \ |
| 118 V(Uint32x4LessThan) \ |
| 119 V(Uint32x4LessThanOrEqual) \ |
| 120 V(Uint32x4GreaterThan) \ |
| 121 V(Uint32x4GreaterThanOrEqual) |
| 122 |
103 void SimdScalarLowering::SetLoweredType(Node* node, Node* output) { | 123 void SimdScalarLowering::SetLoweredType(Node* node, Node* output) { |
104 switch (node->opcode()) { | 124 switch (node->opcode()) { |
105 #define CASE_STMT(name) case IrOpcode::k##name: | 125 #define CASE_STMT(name) case IrOpcode::k##name: |
106 FOREACH_INT32X4_OPCODE(CASE_STMT) | 126 FOREACH_INT32X4_OPCODE(CASE_STMT) |
107 case IrOpcode::kReturn: | 127 case IrOpcode::kReturn: |
108 case IrOpcode::kParameter: | 128 case IrOpcode::kParameter: |
109 case IrOpcode::kCall: { | 129 case IrOpcode::kCall: { |
110 replacements_[node->id()].type = SimdType::kInt32; | 130 replacements_[node->id()].type = SimdType::kInt32; |
111 break; | 131 break; |
112 } | 132 } |
113 FOREACH_FLOAT32X4_OPCODE(CASE_STMT) { | 133 FOREACH_FLOAT32X4_OPCODE(CASE_STMT) { |
114 replacements_[node->id()].type = SimdType::kFloat32; | 134 replacements_[node->id()].type = SimdType::kFloat32; |
115 break; | 135 break; |
116 } | 136 } |
117 #undef CASE_STMT | 137 FOREACH_FLOAT32X4_TO_SIMD1X4OPCODE(CASE_STMT) |
| 138 FOREACH_INT32X4_TO_SIMD1X4OPCODE(CASE_STMT) { |
| 139 replacements_[node->id()].type = SimdType::kSimd1x4; |
| 140 break; |
| 141 } |
118 default: { | 142 default: { |
119 switch (output->opcode()) { | 143 switch (output->opcode()) { |
| 144 FOREACH_FLOAT32X4_TO_SIMD1X4OPCODE(CASE_STMT) |
120 case IrOpcode::kFloat32x4FromInt32x4: | 145 case IrOpcode::kFloat32x4FromInt32x4: |
121 case IrOpcode::kFloat32x4FromUint32x4: { | 146 case IrOpcode::kFloat32x4FromUint32x4: { |
122 replacements_[node->id()].type = SimdType::kInt32; | 147 replacements_[node->id()].type = SimdType::kInt32; |
123 break; | 148 break; |
124 } | 149 } |
| 150 FOREACH_INT32X4_TO_SIMD1X4OPCODE(CASE_STMT) |
125 case IrOpcode::kInt32x4FromFloat32x4: | 151 case IrOpcode::kInt32x4FromFloat32x4: |
126 case IrOpcode::kUint32x4FromFloat32x4: { | 152 case IrOpcode::kUint32x4FromFloat32x4: { |
127 replacements_[node->id()].type = SimdType::kFloat32; | 153 replacements_[node->id()].type = SimdType::kFloat32; |
128 break; | 154 break; |
129 } | 155 } |
| 156 case IrOpcode::kSimd32x4Select: { |
| 157 replacements_[node->id()].type = SimdType::kSimd1x4; |
| 158 break; |
| 159 } |
130 default: { | 160 default: { |
131 replacements_[node->id()].type = replacements_[output->id()].type; | 161 replacements_[node->id()].type = replacements_[output->id()].type; |
132 } | 162 } |
133 } | 163 } |
134 } | 164 } |
| 165 #undef CASE_STMT |
135 } | 166 } |
136 } | 167 } |
137 | 168 |
138 static int GetParameterIndexAfterLowering( | 169 static int GetParameterIndexAfterLowering( |
139 Signature<MachineRepresentation>* signature, int old_index) { | 170 Signature<MachineRepresentation>* signature, int old_index) { |
140 // In function calls, the simd128 types are passed as 4 Int32 types. The | 171 // In function calls, the simd128 types are passed as 4 Int32 types. The |
141 // parameters are typecast to the types as needed for various operations. | 172 // parameters are typecast to the types as needed for various operations. |
142 int result = old_index; | 173 int result = old_index; |
143 for (int i = 0; i < old_index; ++i) { | 174 for (int i = 0; i < old_index; ++i) { |
144 if (signature->GetParam(i) == MachineRepresentation::kSimd128) { | 175 if (signature->GetParam(i) == MachineRepresentation::kSimd128) { |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 } | 276 } |
246 } | 277 } |
247 | 278 |
248 ReplaceNode(node, rep_nodes); | 279 ReplaceNode(node, rep_nodes); |
249 } else { | 280 } else { |
250 DefaultLowering(node); | 281 DefaultLowering(node); |
251 } | 282 } |
252 } | 283 } |
253 | 284 |
254 void SimdScalarLowering::LowerBinaryOp(Node* node, SimdType input_rep_type, | 285 void SimdScalarLowering::LowerBinaryOp(Node* node, SimdType input_rep_type, |
255 const Operator* op) { | 286 const Operator* op, bool invert_inputs) { |
256 DCHECK(node->InputCount() == 2); | 287 DCHECK(node->InputCount() == 2); |
257 Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type); | 288 Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type); |
258 Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type); | 289 Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type); |
259 Node* rep_node[kMaxLanes]; | 290 Node* rep_node[kMaxLanes]; |
260 for (int i = 0; i < kMaxLanes; ++i) { | 291 for (int i = 0; i < kMaxLanes; ++i) { |
261 rep_node[i] = graph()->NewNode(op, rep_left[i], rep_right[i]); | 292 if (invert_inputs) { |
| 293 rep_node[i] = graph()->NewNode(op, rep_right[i], rep_left[i]); |
| 294 } else { |
| 295 rep_node[i] = graph()->NewNode(op, rep_left[i], rep_right[i]); |
| 296 } |
262 } | 297 } |
263 ReplaceNode(node, rep_node); | 298 ReplaceNode(node, rep_node); |
264 } | 299 } |
265 | 300 |
266 void SimdScalarLowering::LowerUnaryOp(Node* node, SimdType input_rep_type, | 301 void SimdScalarLowering::LowerUnaryOp(Node* node, SimdType input_rep_type, |
267 const Operator* op) { | 302 const Operator* op) { |
268 DCHECK(node->InputCount() == 1); | 303 DCHECK(node->InputCount() == 1); |
269 Node** rep = GetReplacementsWithType(node->InputAt(0), input_rep_type); | 304 Node** rep = GetReplacementsWithType(node->InputAt(0), input_rep_type); |
270 Node* rep_node[kMaxLanes]; | 305 Node* rep_node[kMaxLanes]; |
271 for (int i = 0; i < kMaxLanes; ++i) { | 306 for (int i = 0; i < kMaxLanes; ++i) { |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 Node* shift_node = | 400 Node* shift_node = |
366 graph()->NewNode(common()->Int32Constant(shift_amount & shift_mask)); | 401 graph()->NewNode(common()->Int32Constant(shift_amount & shift_mask)); |
367 Node** rep = GetReplacementsWithType(node->InputAt(0), SimdType::kInt32); | 402 Node** rep = GetReplacementsWithType(node->InputAt(0), SimdType::kInt32); |
368 Node* rep_node[kMaxLanes]; | 403 Node* rep_node[kMaxLanes]; |
369 for (int i = 0; i < kMaxLanes; ++i) { | 404 for (int i = 0; i < kMaxLanes; ++i) { |
370 rep_node[i] = graph()->NewNode(op, rep[i], shift_node); | 405 rep_node[i] = graph()->NewNode(op, rep[i], shift_node); |
371 } | 406 } |
372 ReplaceNode(node, rep_node); | 407 ReplaceNode(node, rep_node); |
373 } | 408 } |
374 | 409 |
| 410 void SimdScalarLowering::LowerNotEqual(Node* node, SimdType input_rep_type, |
| 411 const Operator* op) { |
| 412 DCHECK(node->InputCount() == 2); |
| 413 Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type); |
| 414 Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type); |
| 415 Node* rep_node[kMaxLanes]; |
| 416 for (int i = 0; i < kMaxLanes; ++i) { |
| 417 Diamond d(graph(), common(), |
| 418 graph()->NewNode(op, rep_left[i], rep_right[i])); |
| 419 rep_node[i] = d.Phi(MachineRepresentation::kWord32, |
| 420 jsgraph_->Int32Constant(0), jsgraph_->Int32Constant(1)); |
| 421 } |
| 422 ReplaceNode(node, rep_node); |
| 423 } |
| 424 |
375 void SimdScalarLowering::LowerNode(Node* node) { | 425 void SimdScalarLowering::LowerNode(Node* node) { |
376 SimdType rep_type = ReplacementType(node); | 426 SimdType rep_type = ReplacementType(node); |
377 switch (node->opcode()) { | 427 switch (node->opcode()) { |
378 case IrOpcode::kStart: { | 428 case IrOpcode::kStart: { |
379 int parameter_count = GetParameterCountAfterLowering(); | 429 int parameter_count = GetParameterCountAfterLowering(); |
380 // Only exchange the node if the parameter count actually changed. | 430 // Only exchange the node if the parameter count actually changed. |
381 if (parameter_count != static_cast<int>(signature()->parameter_count())) { | 431 if (parameter_count != static_cast<int>(signature()->parameter_count())) { |
382 int delta = | 432 int delta = |
383 parameter_count - static_cast<int>(signature()->parameter_count()); | 433 parameter_count - static_cast<int>(signature()->parameter_count()); |
384 int new_output_count = node->op()->ValueOutputCount() + delta; | 434 int new_output_count = node->op()->ValueOutputCount() + delta; |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
647 DCHECK(lane >= 0 && lane <= 3); | 697 DCHECK(lane >= 0 && lane <= 3); |
648 Node** rep_node = GetReplacementsWithType(node->InputAt(0), rep_type); | 698 Node** rep_node = GetReplacementsWithType(node->InputAt(0), rep_type); |
649 if (HasReplacement(0, repNode)) { | 699 if (HasReplacement(0, repNode)) { |
650 rep_node[lane] = GetReplacements(repNode)[0]; | 700 rep_node[lane] = GetReplacements(repNode)[0]; |
651 } else { | 701 } else { |
652 rep_node[lane] = repNode; | 702 rep_node[lane] = repNode; |
653 } | 703 } |
654 ReplaceNode(node, rep_node); | 704 ReplaceNode(node, rep_node); |
655 break; | 705 break; |
656 } | 706 } |
| 707 #define COMPARISON_CASE(type, simd_op, lowering_op, invert) \ |
| 708 case IrOpcode::simd_op: { \ |
| 709 LowerBinaryOp(node, SimdType::k##type, machine()->lowering_op(), invert); \ |
| 710 break; \ |
| 711 } |
| 712 COMPARISON_CASE(Float32, kFloat32x4Equal, Float32Equal, false) |
| 713 COMPARISON_CASE(Float32, kFloat32x4LessThan, Float32LessThan, false) |
| 714 COMPARISON_CASE(Float32, kFloat32x4LessThanOrEqual, |
| 715 Float32LessThanOrEqual, false) |
| 716 COMPARISON_CASE(Float32, kFloat32x4GreaterThan, Float32LessThan, true) |
| 717 COMPARISON_CASE(Float32, kFloat32x4GreaterThanOrEqual, |
| 718 Float32LessThanOrEqual, true) |
| 719 COMPARISON_CASE(Int32, kInt32x4Equal, Word32Equal, false) |
| 720 COMPARISON_CASE(Int32, kInt32x4LessThan, Int32LessThan, false) |
| 721 COMPARISON_CASE(Int32, kInt32x4LessThanOrEqual, Int32LessThanOrEqual, |
| 722 false) |
| 723 COMPARISON_CASE(Int32, kInt32x4GreaterThan, Int32LessThan, true) |
| 724 COMPARISON_CASE(Int32, kInt32x4GreaterThanOrEqual, Int32LessThanOrEqual, |
| 725 true) |
| 726 COMPARISON_CASE(Int32, kUint32x4LessThan, Uint32LessThan, false) |
| 727 COMPARISON_CASE(Int32, kUint32x4LessThanOrEqual, Uint32LessThanOrEqual, |
| 728 false) |
| 729 COMPARISON_CASE(Int32, kUint32x4GreaterThan, Uint32LessThan, true) |
| 730 COMPARISON_CASE(Int32, kUint32x4GreaterThanOrEqual, Uint32LessThanOrEqual, |
| 731 true) |
| 732 #undef COMPARISON_CASE |
| 733 case IrOpcode::kFloat32x4NotEqual: { |
| 734 LowerNotEqual(node, SimdType::kFloat32, machine()->Float32Equal()); |
| 735 break; |
| 736 } |
| 737 case IrOpcode::kInt32x4NotEqual: { |
| 738 LowerNotEqual(node, SimdType::kInt32, machine()->Word32Equal()); |
| 739 break; |
| 740 } |
| 741 case IrOpcode::kSimd32x4Select: { |
| 742 DCHECK(node->InputCount() == 3); |
| 743 DCHECK(ReplacementType(node->InputAt(0)) == SimdType::kSimd1x4); |
| 744 Node** boolean_input = GetReplacements(node->InputAt(0)); |
| 745 Node** rep_left = GetReplacementsWithType(node->InputAt(1), rep_type); |
| 746 Node** rep_right = GetReplacementsWithType(node->InputAt(2), rep_type); |
| 747 Node* rep_node[kMaxLanes]; |
| 748 for (int i = 0; i < kMaxLanes; ++i) { |
| 749 Diamond d(graph(), common(), |
| 750 graph()->NewNode(machine()->Word32Equal(), boolean_input[i], |
| 751 jsgraph_->Int32Constant(0))); |
| 752 if (rep_type == SimdType::kFloat32) { |
| 753 rep_node[i] = |
| 754 d.Phi(MachineRepresentation::kFloat32, rep_right[1], rep_left[0]); |
| 755 } else if (rep_type == SimdType::kInt32) { |
| 756 rep_node[i] = |
| 757 d.Phi(MachineRepresentation::kWord32, rep_right[1], rep_left[0]); |
| 758 } else { |
| 759 UNREACHABLE(); |
| 760 } |
| 761 } |
| 762 ReplaceNode(node, rep_node); |
| 763 break; |
| 764 } |
657 default: { DefaultLowering(node); } | 765 default: { DefaultLowering(node); } |
658 } | 766 } |
659 } | 767 } |
660 | 768 |
661 bool SimdScalarLowering::DefaultLowering(Node* node) { | 769 bool SimdScalarLowering::DefaultLowering(Node* node) { |
662 bool something_changed = false; | 770 bool something_changed = false; |
663 for (int i = NodeProperties::PastValueIndex(node) - 1; i >= 0; i--) { | 771 for (int i = NodeProperties::PastValueIndex(node) - 1; i >= 0; i--) { |
664 Node* input = node->InputAt(i); | 772 Node* input = node->InputAt(i); |
665 if (HasReplacement(0, input)) { | 773 if (HasReplacement(0, input)) { |
666 something_changed = true; | 774 something_changed = true; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
708 Node** result = zone()->NewArray<Node*>(kMaxLanes); | 816 Node** result = zone()->NewArray<Node*>(kMaxLanes); |
709 if (ReplacementType(node) == SimdType::kInt32 && type == SimdType::kFloat32) { | 817 if (ReplacementType(node) == SimdType::kInt32 && type == SimdType::kFloat32) { |
710 for (int i = 0; i < kMaxLanes; ++i) { | 818 for (int i = 0; i < kMaxLanes; ++i) { |
711 if (replacements[i] != nullptr) { | 819 if (replacements[i] != nullptr) { |
712 result[i] = graph()->NewNode(machine()->BitcastInt32ToFloat32(), | 820 result[i] = graph()->NewNode(machine()->BitcastInt32ToFloat32(), |
713 replacements[i]); | 821 replacements[i]); |
714 } else { | 822 } else { |
715 result[i] = nullptr; | 823 result[i] = nullptr; |
716 } | 824 } |
717 } | 825 } |
718 } else { | 826 } else if (ReplacementType(node) == SimdType::kFloat32 && |
| 827 type == SimdType::kInt32) { |
719 for (int i = 0; i < kMaxLanes; ++i) { | 828 for (int i = 0; i < kMaxLanes; ++i) { |
720 if (replacements[i] != nullptr) { | 829 if (replacements[i] != nullptr) { |
721 result[i] = graph()->NewNode(machine()->BitcastFloat32ToInt32(), | 830 result[i] = graph()->NewNode(machine()->BitcastFloat32ToInt32(), |
722 replacements[i]); | 831 replacements[i]); |
723 } else { | 832 } else { |
724 result[i] = nullptr; | 833 result[i] = nullptr; |
725 } | 834 } |
726 } | 835 } |
| 836 } else { |
| 837 UNREACHABLE(); |
727 } | 838 } |
728 return result; | 839 return result; |
729 } | 840 } |
730 | 841 |
731 void SimdScalarLowering::PreparePhiReplacement(Node* phi) { | 842 void SimdScalarLowering::PreparePhiReplacement(Node* phi) { |
732 MachineRepresentation rep = PhiRepresentationOf(phi->op()); | 843 MachineRepresentation rep = PhiRepresentationOf(phi->op()); |
733 if (rep == MachineRepresentation::kSimd128) { | 844 if (rep == MachineRepresentation::kSimd128) { |
734 // We have to create the replacements for a phi node before we actually | 845 // We have to create the replacements for a phi node before we actually |
735 // lower the phi to break potential cycles in the graph. The replacements of | 846 // lower the phi to break potential cycles in the graph. The replacements of |
736 // input nodes do not exist yet, so we use a placeholder node to pass the | 847 // input nodes do not exist yet, so we use a placeholder node to pass the |
(...skipping 23 matching lines...) Expand all Loading... |
760 } else { | 871 } else { |
761 UNREACHABLE(); | 872 UNREACHABLE(); |
762 } | 873 } |
763 } | 874 } |
764 ReplaceNode(phi, rep_nodes); | 875 ReplaceNode(phi, rep_nodes); |
765 } | 876 } |
766 } | 877 } |
767 } // namespace compiler | 878 } // namespace compiler |
768 } // namespace internal | 879 } // namespace internal |
769 } // namespace v8 | 880 } // namespace v8 |
OLD | NEW |