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

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: 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 11 matching lines...) Expand all
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
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
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
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
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