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

Side by Side Diff: src/compiler/simd-scalar-lowering.cc

Issue 2718323003: [wasm]implement simd lowering for f32x4->i32x4, i32x4 min/max and shift instructions (Closed)
Patch Set: comments Created 3 years, 9 months 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/simd-scalar-lowering.h ('k') | test/cctest/wasm/test-run-wasm-simd.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 12 matching lines...) Expand all
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: {
118 if (output->opcode() == IrOpcode::kFloat32x4FromInt32x4 || 124 switch (output->opcode()) {
119 output->opcode() == IrOpcode::kFloat32x4FromUint32x4) { 125 case IrOpcode::kFloat32x4FromInt32x4:
120 replacements_[node->id()].type = SimdType::kInt32; 126 case IrOpcode::kFloat32x4FromUint32x4: {
121 } else { 127 replacements_[node->id()].type = SimdType::kInt32;
122 replacements_[node->id()].type = replacements_[output->id()].type; 128 break;
129 }
130 case IrOpcode::kInt32x4FromFloat32x4:
131 case IrOpcode::kUint32x4FromFloat32x4: {
132 replacements_[node->id()].type = SimdType::kFloat32;
133 break;
134 }
135 default: {
136 replacements_[node->id()].type = replacements_[output->id()].type;
137 }
123 } 138 }
124 } 139 }
125 } 140 }
126 } 141 }
127 142
128 static int GetParameterIndexAfterLowering( 143 static int GetParameterIndexAfterLowering(
129 Signature<MachineRepresentation>* signature, int old_index) { 144 Signature<MachineRepresentation>* signature, int old_index) {
130 // In function calls, the simd128 types are passed as 4 Int32 types. The 145 // In function calls, the simd128 types are passed as 4 Int32 types. The
131 // parameters are typecast to the types as needed for various operations. 146 // parameters are typecast to the types as needed for various operations.
132 int result = old_index; 147 int result = old_index;
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 const Operator* op) { 272 const Operator* op) {
258 DCHECK(node->InputCount() == 1); 273 DCHECK(node->InputCount() == 1);
259 Node** rep = GetReplacementsWithType(node->InputAt(0), input_rep_type); 274 Node** rep = GetReplacementsWithType(node->InputAt(0), input_rep_type);
260 Node* rep_node[kMaxLanes]; 275 Node* rep_node[kMaxLanes];
261 for (int i = 0; i < kMaxLanes; ++i) { 276 for (int i = 0; i < kMaxLanes; ++i) {
262 rep_node[i] = graph()->NewNode(op, rep[i]); 277 rep_node[i] = graph()->NewNode(op, rep[i]);
263 } 278 }
264 ReplaceNode(node, rep_node); 279 ReplaceNode(node, rep_node);
265 } 280 }
266 281
282 void SimdScalarLowering::LowerIntMinMax(Node* node, const Operator* op,
283 bool is_max) {
284 DCHECK(node->InputCount() == 2);
285 Node** rep_left = GetReplacementsWithType(node->InputAt(0), SimdType::kInt32);
286 Node** rep_right =
287 GetReplacementsWithType(node->InputAt(1), SimdType::kInt32);
288 Node* rep_node[kMaxLanes];
289 for (int i = 0; i < kMaxLanes; ++i) {
290 Diamond d(graph(), common(),
291 graph()->NewNode(op, rep_left[i], rep_right[i]));
292 if (is_max) {
293 rep_node[i] =
294 d.Phi(MachineRepresentation::kWord32, rep_right[i], rep_left[i]);
295 } else {
296 rep_node[i] =
297 d.Phi(MachineRepresentation::kWord32, rep_left[i], rep_right[i]);
298 }
299 }
300 ReplaceNode(node, rep_node);
301 }
302
303 void SimdScalarLowering::LowerConvertFromFloat(Node* node, bool is_signed) {
304 DCHECK(node->InputCount() == 1);
305 Node** rep = GetReplacementsWithType(node->InputAt(0), SimdType::kFloat32);
306 Node* rep_node[kMaxLanes];
307 Node* double_zero = graph()->NewNode(common()->Float64Constant(0.0));
308 Node* min = graph()->NewNode(
309 common()->Float64Constant(static_cast<double>(is_signed ? kMinInt : 0)));
310 Node* max = graph()->NewNode(common()->Float64Constant(
311 static_cast<double>(is_signed ? kMaxInt : 0xffffffffu)));
312 for (int i = 0; i < kMaxLanes; ++i) {
313 Node* double_rep =
314 graph()->NewNode(machine()->ChangeFloat32ToFloat64(), rep[i]);
315 Diamond nan_d(graph(), common(), graph()->NewNode(machine()->Float64Equal(),
316 double_rep, double_rep));
317 Node* temp =
318 nan_d.Phi(MachineRepresentation::kFloat64, double_rep, double_zero);
319 Diamond min_d(graph(), common(),
320 graph()->NewNode(machine()->Float64LessThan(), temp, min));
321 temp = min_d.Phi(MachineRepresentation::kFloat64, min, temp);
322 Diamond max_d(graph(), common(),
323 graph()->NewNode(machine()->Float64LessThan(), max, temp));
324 temp = max_d.Phi(MachineRepresentation::kFloat64, max, temp);
325 Node* trunc =
326 graph()->NewNode(machine()->Float64RoundTruncate().op(), temp);
327 if (is_signed) {
328 rep_node[i] = graph()->NewNode(machine()->ChangeFloat64ToInt32(), trunc);
329 } else {
330 rep_node[i] =
331 graph()->NewNode(machine()->TruncateFloat64ToUint32(), trunc);
332 }
333 }
334 ReplaceNode(node, rep_node);
335 }
336
337 void SimdScalarLowering::LowerShiftOp(Node* node, const Operator* op) {
338 static int32_t shift_mask = 0x1f;
339 DCHECK_EQ(1, node->InputCount());
340 int32_t shift_amount = OpParameter<int32_t>(node);
341 Node* shift_node =
342 graph()->NewNode(common()->Int32Constant(shift_amount & shift_mask));
343 Node** rep = GetReplacementsWithType(node->InputAt(0), SimdType::kInt32);
344 Node* rep_node[kMaxLanes];
345 for (int i = 0; i < kMaxLanes; ++i) {
346 rep_node[i] = graph()->NewNode(op, rep[i], shift_node);
347 }
348 ReplaceNode(node, rep_node);
349 }
350
267 void SimdScalarLowering::LowerNode(Node* node) { 351 void SimdScalarLowering::LowerNode(Node* node) {
268 SimdType rep_type = ReplacementType(node); 352 SimdType rep_type = ReplacementType(node);
269 switch (node->opcode()) { 353 switch (node->opcode()) {
270 case IrOpcode::kStart: { 354 case IrOpcode::kStart: {
271 int parameter_count = GetParameterCountAfterLowering(); 355 int parameter_count = GetParameterCountAfterLowering();
272 // Only exchange the node if the parameter count actually changed. 356 // Only exchange the node if the parameter count actually changed.
273 if (parameter_count != static_cast<int>(signature()->parameter_count())) { 357 if (parameter_count != static_cast<int>(signature()->parameter_count())) {
274 int delta = 358 int delta =
275 parameter_count - static_cast<int>(signature()->parameter_count()); 359 parameter_count - static_cast<int>(signature()->parameter_count());
276 int new_output_count = node->op()->ValueOutputCount() + delta; 360 int new_output_count = node->op()->ValueOutputCount() + delta;
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 LowerBinaryOp(node, rep_type, machine()->instruction()); \ 499 LowerBinaryOp(node, rep_type, machine()->instruction()); \
416 break; \ 500 break; \
417 } 501 }
418 I32X4_BINOP_CASE(kInt32x4Add, Int32Add) 502 I32X4_BINOP_CASE(kInt32x4Add, Int32Add)
419 I32X4_BINOP_CASE(kInt32x4Sub, Int32Sub) 503 I32X4_BINOP_CASE(kInt32x4Sub, Int32Sub)
420 I32X4_BINOP_CASE(kInt32x4Mul, Int32Mul) 504 I32X4_BINOP_CASE(kInt32x4Mul, Int32Mul)
421 I32X4_BINOP_CASE(kSimd128And, Word32And) 505 I32X4_BINOP_CASE(kSimd128And, Word32And)
422 I32X4_BINOP_CASE(kSimd128Or, Word32Or) 506 I32X4_BINOP_CASE(kSimd128Or, Word32Or)
423 I32X4_BINOP_CASE(kSimd128Xor, Word32Xor) 507 I32X4_BINOP_CASE(kSimd128Xor, Word32Xor)
424 #undef I32X4_BINOP_CASE 508 #undef I32X4_BINOP_CASE
509 case IrOpcode::kInt32x4Max: {
510 LowerIntMinMax(node, machine()->Int32LessThan(), true);
511 break;
512 }
513 case IrOpcode::kInt32x4Min: {
514 LowerIntMinMax(node, machine()->Int32LessThan(), false);
515 break;
516 }
517 case IrOpcode::kUint32x4Max: {
518 LowerIntMinMax(node, machine()->Uint32LessThan(), true);
519 break;
520 }
521 case IrOpcode::kUint32x4Min: {
522 LowerIntMinMax(node, machine()->Uint32LessThan(), false);
523 break;
524 }
425 case IrOpcode::kInt32x4Neg: { 525 case IrOpcode::kInt32x4Neg: {
426 DCHECK(node->InputCount() == 1); 526 DCHECK(node->InputCount() == 1);
427 Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type); 527 Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type);
428 Node* rep_node[kMaxLanes]; 528 Node* rep_node[kMaxLanes];
429 Node* zero = graph()->NewNode(common()->Int32Constant(0)); 529 Node* zero = graph()->NewNode(common()->Int32Constant(0));
430 for (int i = 0; i < kMaxLanes; ++i) { 530 for (int i = 0; i < kMaxLanes; ++i) {
431 rep_node[i] = graph()->NewNode(machine()->Int32Sub(), zero, rep[i]); 531 rep_node[i] = graph()->NewNode(machine()->Int32Sub(), zero, rep[i]);
432 } 532 }
433 ReplaceNode(node, rep_node); 533 ReplaceNode(node, rep_node);
434 break; 534 break;
435 } 535 }
436 case IrOpcode::kSimd128Not: { 536 case IrOpcode::kSimd128Not: {
437 DCHECK(node->InputCount() == 1); 537 DCHECK(node->InputCount() == 1);
438 Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type); 538 Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type);
439 Node* rep_node[kMaxLanes]; 539 Node* rep_node[kMaxLanes];
440 Node* mask = graph()->NewNode(common()->Int32Constant(0xffffffff)); 540 Node* mask = graph()->NewNode(common()->Int32Constant(0xffffffff));
441 for (int i = 0; i < kMaxLanes; ++i) { 541 for (int i = 0; i < kMaxLanes; ++i) {
442 rep_node[i] = graph()->NewNode(machine()->Word32Xor(), rep[i], mask); 542 rep_node[i] = graph()->NewNode(machine()->Word32Xor(), rep[i], mask);
443 } 543 }
444 ReplaceNode(node, rep_node); 544 ReplaceNode(node, rep_node);
445 break; 545 break;
446 } 546 }
547 case IrOpcode::kInt32x4FromFloat32x4: {
548 LowerConvertFromFloat(node, true);
549 break;
550 }
551 case IrOpcode::kUint32x4FromFloat32x4: {
552 LowerConvertFromFloat(node, false);
553 break;
554 }
555 case IrOpcode::kInt32x4ShiftLeftByScalar: {
556 LowerShiftOp(node, machine()->Word32Shl());
557 break;
558 }
559 case IrOpcode::kInt32x4ShiftRightByScalar: {
560 LowerShiftOp(node, machine()->Word32Sar());
561 break;
562 }
563 case IrOpcode::kUint32x4ShiftRightByScalar: {
564 LowerShiftOp(node, machine()->Word32Shr());
565 break;
566 }
447 #define F32X4_BINOP_CASE(name) \ 567 #define F32X4_BINOP_CASE(name) \
448 case IrOpcode::kFloat32x4##name: { \ 568 case IrOpcode::kFloat32x4##name: { \
449 LowerBinaryOp(node, rep_type, machine()->Float32##name()); \ 569 LowerBinaryOp(node, rep_type, machine()->Float32##name()); \
450 break; \ 570 break; \
451 } 571 }
452 F32X4_BINOP_CASE(Add) 572 F32X4_BINOP_CASE(Add)
453 F32X4_BINOP_CASE(Sub) 573 F32X4_BINOP_CASE(Sub)
454 F32X4_BINOP_CASE(Mul) 574 F32X4_BINOP_CASE(Mul)
455 F32X4_BINOP_CASE(Div) 575 F32X4_BINOP_CASE(Div)
456 F32X4_BINOP_CASE(Min) 576 F32X4_BINOP_CASE(Min)
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
616 } else { 736 } else {
617 UNREACHABLE(); 737 UNREACHABLE();
618 } 738 }
619 } 739 }
620 ReplaceNode(phi, rep_nodes); 740 ReplaceNode(phi, rep_nodes);
621 } 741 }
622 } 742 }
623 } // namespace compiler 743 } // namespace compiler
624 } // namespace internal 744 } // namespace internal
625 } // namespace v8 745 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/simd-scalar-lowering.h ('k') | test/cctest/wasm/test-run-wasm-simd.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698