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

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

Issue 2724973003: [wasm]implement simd lowering for f32x4->i32x4, i32x4 min/max and shift instructions (Closed)
Patch Set: comment 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') | src/compiler/wasm-compiler.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
11 #include "src/compiler/node.h" 11 #include "src/compiler/node.h"
12 #include "src/objects-inl.h" 12 #include "src/objects-inl.h"
13 #include "src/wasm/wasm-module.h" 13 #include "src/wasm/wasm-module.h"
14 14
15 namespace v8 { 15 namespace v8 {
16 namespace internal { 16 namespace internal {
17 namespace compiler { 17 namespace compiler {
18 18
19 SimdScalarLowering::SimdScalarLowering( 19 SimdScalarLowering::SimdScalarLowering(
20 Graph* graph, MachineOperatorBuilder* machine, 20 JSGraph* jsgraph, Signature<MachineRepresentation>* signature)
21 CommonOperatorBuilder* common, Zone* zone, 21 : jsgraph_(jsgraph),
22 Signature<MachineRepresentation>* signature) 22 state_(jsgraph->graph(), 3),
23 : zone_(zone), 23 stack_(jsgraph_->zone()),
24 graph_(graph),
25 machine_(machine),
26 common_(common),
27 state_(graph, 3),
28 stack_(zone),
29 replacements_(nullptr), 24 replacements_(nullptr),
30 signature_(signature), 25 signature_(signature),
31 placeholder_( 26 placeholder_(graph()->NewNode(common()->Parameter(-2, "placeholder"),
32 graph->NewNode(common->Parameter(-2, "placeholder"), graph->start())), 27 graph()->start())),
33 parameter_count_after_lowering_(-1) { 28 parameter_count_after_lowering_(-1) {
34 DCHECK_NOT_NULL(graph); 29 DCHECK_NOT_NULL(graph());
35 DCHECK_NOT_NULL(graph->end()); 30 DCHECK_NOT_NULL(graph()->end());
36 replacements_ = zone->NewArray<Replacement>(graph->NodeCount()); 31 replacements_ = zone()->NewArray<Replacement>(graph()->NodeCount());
37 memset(replacements_, 0, sizeof(Replacement) * graph->NodeCount()); 32 memset(replacements_, 0, sizeof(Replacement) * graph()->NodeCount());
38 } 33 }
39 34
40 void SimdScalarLowering::LowerGraph() { 35 void SimdScalarLowering::LowerGraph() {
41 stack_.push_back({graph()->end(), 0}); 36 stack_.push_back({graph()->end(), 0});
42 state_.Set(graph()->end(), State::kOnStack); 37 state_.Set(graph()->end(), State::kOnStack);
43 replacements_[graph()->end()->id()].type = SimdType::kInt32; 38 replacements_[graph()->end()->id()].type = SimdType::kInt32;
44 39
45 while (!stack_.empty()) { 40 while (!stack_.empty()) {
46 NodeState& top = stack_.back(); 41 NodeState& top = stack_.back();
47 if (top.input_index == top.node->InputCount()) { 42 if (top.input_index == top.node->InputCount()) {
(...skipping 25 matching lines...) Expand all
73 68
74 #define FOREACH_INT32X4_OPCODE(V) \ 69 #define FOREACH_INT32X4_OPCODE(V) \
75 V(Int32x4Splat) \ 70 V(Int32x4Splat) \
76 V(Int32x4ExtractLane) \ 71 V(Int32x4ExtractLane) \
77 V(Int32x4ReplaceLane) \ 72 V(Int32x4ReplaceLane) \
78 V(Int32x4Neg) \ 73 V(Int32x4Neg) \
79 V(Simd128Not) \ 74 V(Simd128Not) \
80 V(Int32x4Add) \ 75 V(Int32x4Add) \
81 V(Int32x4Sub) \ 76 V(Int32x4Sub) \
82 V(Int32x4Mul) \ 77 V(Int32x4Mul) \
78 V(Int32x4Min) \
79 V(Int32x4Max) \
80 V(Uint32x4Min) \
81 V(Uint32x4Max) \
83 V(Simd128And) \ 82 V(Simd128And) \
84 V(Simd128Or) \ 83 V(Simd128Or) \
85 V(Simd128Xor) 84 V(Simd128Xor) \
85 V(Int32x4FromFloat32x4) \
86 V(Uint32x4FromFloat32x4)
86 87
87 #define FOREACH_FLOAT32X4_OPCODE(V) \ 88 #define FOREACH_FLOAT32X4_OPCODE(V) \
88 V(Float32x4Splat) \ 89 V(Float32x4Splat) \
89 V(Float32x4ExtractLane) \ 90 V(Float32x4ExtractLane) \
90 V(Float32x4ReplaceLane) \ 91 V(Float32x4ReplaceLane) \
91 V(Float32x4Abs) \ 92 V(Float32x4Abs) \
92 V(Float32x4Neg) \ 93 V(Float32x4Neg) \
93 V(Float32x4Add) \ 94 V(Float32x4Add) \
94 V(Float32x4Sub) \ 95 V(Float32x4Sub) \
95 V(Float32x4Mul) \ 96 V(Float32x4Mul) \
(...skipping 12 matching lines...) Expand all
108 case IrOpcode::kCall: { 109 case IrOpcode::kCall: {
109 replacements_[node->id()].type = SimdType::kInt32; 110 replacements_[node->id()].type = SimdType::kInt32;
110 break; 111 break;
111 } 112 }
112 FOREACH_FLOAT32X4_OPCODE(CASE_STMT) { 113 FOREACH_FLOAT32X4_OPCODE(CASE_STMT) {
113 replacements_[node->id()].type = SimdType::kFloat32; 114 replacements_[node->id()].type = SimdType::kFloat32;
114 break; 115 break;
115 } 116 }
116 #undef CASE_STMT 117 #undef CASE_STMT
117 default: { 118 default: {
118 if (output->opcode() == IrOpcode::kFloat32x4FromInt32x4 || 119 switch (output->opcode()) {
119 output->opcode() == IrOpcode::kFloat32x4FromUint32x4) { 120 case IrOpcode::kFloat32x4FromInt32x4:
120 replacements_[node->id()].type = SimdType::kInt32; 121 case IrOpcode::kFloat32x4FromUint32x4: {
121 } else { 122 replacements_[node->id()].type = SimdType::kInt32;
122 replacements_[node->id()].type = replacements_[output->id()].type; 123 break;
124 }
125 case IrOpcode::kInt32x4FromFloat32x4:
126 case IrOpcode::kUint32x4FromFloat32x4: {
127 replacements_[node->id()].type = SimdType::kFloat32;
128 break;
129 }
130 default: {
131 replacements_[node->id()].type = replacements_[output->id()].type;
132 }
123 } 133 }
124 } 134 }
125 } 135 }
126 } 136 }
127 137
128 static int GetParameterIndexAfterLowering( 138 static int GetParameterIndexAfterLowering(
129 Signature<MachineRepresentation>* signature, int old_index) { 139 Signature<MachineRepresentation>* signature, int old_index) {
130 // In function calls, the simd128 types are passed as 4 Int32 types. The 140 // 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. 141 // parameters are typecast to the types as needed for various operations.
132 int result = old_index; 142 int result = old_index;
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 const Operator* op) { 267 const Operator* op) {
258 DCHECK(node->InputCount() == 1); 268 DCHECK(node->InputCount() == 1);
259 Node** rep = GetReplacementsWithType(node->InputAt(0), input_rep_type); 269 Node** rep = GetReplacementsWithType(node->InputAt(0), input_rep_type);
260 Node* rep_node[kMaxLanes]; 270 Node* rep_node[kMaxLanes];
261 for (int i = 0; i < kMaxLanes; ++i) { 271 for (int i = 0; i < kMaxLanes; ++i) {
262 rep_node[i] = graph()->NewNode(op, rep[i]); 272 rep_node[i] = graph()->NewNode(op, rep[i]);
263 } 273 }
264 ReplaceNode(node, rep_node); 274 ReplaceNode(node, rep_node);
265 } 275 }
266 276
277 void SimdScalarLowering::LowerIntMinMax(Node* node, const Operator* op,
278 bool is_max) {
279 DCHECK(node->InputCount() == 2);
280 Node** rep_left = GetReplacementsWithType(node->InputAt(0), SimdType::kInt32);
281 Node** rep_right =
282 GetReplacementsWithType(node->InputAt(1), SimdType::kInt32);
283 Node* rep_node[kMaxLanes];
284 for (int i = 0; i < kMaxLanes; ++i) {
285 Diamond d(graph(), common(),
286 graph()->NewNode(op, rep_left[i], rep_right[i]));
287 if (is_max) {
288 rep_node[i] =
289 d.Phi(MachineRepresentation::kWord32, rep_right[i], rep_left[i]);
290 } else {
291 rep_node[i] =
292 d.Phi(MachineRepresentation::kWord32, rep_left[i], rep_right[i]);
293 }
294 }
295 ReplaceNode(node, rep_node);
296 }
297
298 Node* SimdScalarLowering::BuildF64Trunc(Node* input) {
299 if (machine()->Float64RoundTruncate().IsSupported()) {
300 return graph()->NewNode(machine()->Float64RoundTruncate().op(), input);
301 } else {
302 ExternalReference ref =
303 ExternalReference::wasm_f64_trunc(jsgraph_->isolate());
304 Node* stack_slot =
305 graph()->NewNode(machine()->StackSlot(MachineRepresentation::kFloat64));
306 const Operator* store_op = machine()->Store(
307 StoreRepresentation(MachineRepresentation::kFloat64, kNoWriteBarrier));
308 Node* effect =
309 graph()->NewNode(store_op, stack_slot, jsgraph_->Int32Constant(0),
310 input, graph()->start(), graph()->start());
311 Node* function = graph()->NewNode(common()->ExternalConstant(ref));
312 Node** args = zone()->NewArray<Node*>(4);
313 args[0] = function;
314 args[1] = stack_slot;
315 args[2] = effect;
316 args[3] = graph()->start();
317 Signature<MachineType>::Builder sig_builder(zone(), 0, 1);
318 sig_builder.AddParam(MachineType::Pointer());
319 CallDescriptor* desc =
320 Linkage::GetSimplifiedCDescriptor(zone(), sig_builder.Build());
321 Node* call = graph()->NewNode(common()->Call(desc), 4, args);
322 return graph()->NewNode(machine()->Load(LoadRepresentation::Float64()),
323 stack_slot, jsgraph_->Int32Constant(0), call,
324 graph()->start());
325 }
326 }
327
328 void SimdScalarLowering::LowerConvertFromFloat(Node* node, bool is_signed) {
329 DCHECK(node->InputCount() == 1);
330 Node** rep = GetReplacementsWithType(node->InputAt(0), SimdType::kFloat32);
331 Node* rep_node[kMaxLanes];
332 Node* double_zero = graph()->NewNode(common()->Float64Constant(0.0));
333 Node* min = graph()->NewNode(
334 common()->Float64Constant(static_cast<double>(is_signed ? kMinInt : 0)));
335 Node* max = graph()->NewNode(common()->Float64Constant(
336 static_cast<double>(is_signed ? kMaxInt : 0xffffffffu)));
337 for (int i = 0; i < kMaxLanes; ++i) {
338 Node* double_rep =
339 graph()->NewNode(machine()->ChangeFloat32ToFloat64(), rep[i]);
340 Diamond nan_d(graph(), common(), graph()->NewNode(machine()->Float64Equal(),
341 double_rep, double_rep));
342 Node* temp =
343 nan_d.Phi(MachineRepresentation::kFloat64, double_rep, double_zero);
344 Diamond min_d(graph(), common(),
345 graph()->NewNode(machine()->Float64LessThan(), temp, min));
346 temp = min_d.Phi(MachineRepresentation::kFloat64, min, temp);
347 Diamond max_d(graph(), common(),
348 graph()->NewNode(machine()->Float64LessThan(), max, temp));
349 temp = max_d.Phi(MachineRepresentation::kFloat64, max, temp);
350 Node* trunc = BuildF64Trunc(temp);
351 if (is_signed) {
352 rep_node[i] = graph()->NewNode(machine()->ChangeFloat64ToInt32(), trunc);
353 } else {
354 rep_node[i] =
355 graph()->NewNode(machine()->TruncateFloat64ToUint32(), trunc);
356 }
357 }
358 ReplaceNode(node, rep_node);
359 }
360
361 void SimdScalarLowering::LowerShiftOp(Node* node, const Operator* op) {
362 static int32_t shift_mask = 0x1f;
363 DCHECK_EQ(1, node->InputCount());
364 int32_t shift_amount = OpParameter<int32_t>(node);
365 Node* shift_node =
366 graph()->NewNode(common()->Int32Constant(shift_amount & shift_mask));
367 Node** rep = GetReplacementsWithType(node->InputAt(0), SimdType::kInt32);
368 Node* rep_node[kMaxLanes];
369 for (int i = 0; i < kMaxLanes; ++i) {
370 rep_node[i] = graph()->NewNode(op, rep[i], shift_node);
371 }
372 ReplaceNode(node, rep_node);
373 }
374
267 void SimdScalarLowering::LowerNode(Node* node) { 375 void SimdScalarLowering::LowerNode(Node* node) {
268 SimdType rep_type = ReplacementType(node); 376 SimdType rep_type = ReplacementType(node);
269 switch (node->opcode()) { 377 switch (node->opcode()) {
270 case IrOpcode::kStart: { 378 case IrOpcode::kStart: {
271 int parameter_count = GetParameterCountAfterLowering(); 379 int parameter_count = GetParameterCountAfterLowering();
272 // Only exchange the node if the parameter count actually changed. 380 // Only exchange the node if the parameter count actually changed.
273 if (parameter_count != static_cast<int>(signature()->parameter_count())) { 381 if (parameter_count != static_cast<int>(signature()->parameter_count())) {
274 int delta = 382 int delta =
275 parameter_count - static_cast<int>(signature()->parameter_count()); 383 parameter_count - static_cast<int>(signature()->parameter_count());
276 int new_output_count = node->op()->ValueOutputCount() + delta; 384 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()); \ 523 LowerBinaryOp(node, rep_type, machine()->instruction()); \
416 break; \ 524 break; \
417 } 525 }
418 I32X4_BINOP_CASE(kInt32x4Add, Int32Add) 526 I32X4_BINOP_CASE(kInt32x4Add, Int32Add)
419 I32X4_BINOP_CASE(kInt32x4Sub, Int32Sub) 527 I32X4_BINOP_CASE(kInt32x4Sub, Int32Sub)
420 I32X4_BINOP_CASE(kInt32x4Mul, Int32Mul) 528 I32X4_BINOP_CASE(kInt32x4Mul, Int32Mul)
421 I32X4_BINOP_CASE(kSimd128And, Word32And) 529 I32X4_BINOP_CASE(kSimd128And, Word32And)
422 I32X4_BINOP_CASE(kSimd128Or, Word32Or) 530 I32X4_BINOP_CASE(kSimd128Or, Word32Or)
423 I32X4_BINOP_CASE(kSimd128Xor, Word32Xor) 531 I32X4_BINOP_CASE(kSimd128Xor, Word32Xor)
424 #undef I32X4_BINOP_CASE 532 #undef I32X4_BINOP_CASE
533 case IrOpcode::kInt32x4Max: {
534 LowerIntMinMax(node, machine()->Int32LessThan(), true);
535 break;
536 }
537 case IrOpcode::kInt32x4Min: {
538 LowerIntMinMax(node, machine()->Int32LessThan(), false);
539 break;
540 }
541 case IrOpcode::kUint32x4Max: {
542 LowerIntMinMax(node, machine()->Uint32LessThan(), true);
543 break;
544 }
545 case IrOpcode::kUint32x4Min: {
546 LowerIntMinMax(node, machine()->Uint32LessThan(), false);
547 break;
548 }
425 case IrOpcode::kInt32x4Neg: { 549 case IrOpcode::kInt32x4Neg: {
426 DCHECK(node->InputCount() == 1); 550 DCHECK(node->InputCount() == 1);
427 Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type); 551 Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type);
428 Node* rep_node[kMaxLanes]; 552 Node* rep_node[kMaxLanes];
429 Node* zero = graph()->NewNode(common()->Int32Constant(0)); 553 Node* zero = graph()->NewNode(common()->Int32Constant(0));
430 for (int i = 0; i < kMaxLanes; ++i) { 554 for (int i = 0; i < kMaxLanes; ++i) {
431 rep_node[i] = graph()->NewNode(machine()->Int32Sub(), zero, rep[i]); 555 rep_node[i] = graph()->NewNode(machine()->Int32Sub(), zero, rep[i]);
432 } 556 }
433 ReplaceNode(node, rep_node); 557 ReplaceNode(node, rep_node);
434 break; 558 break;
435 } 559 }
436 case IrOpcode::kSimd128Not: { 560 case IrOpcode::kSimd128Not: {
437 DCHECK(node->InputCount() == 1); 561 DCHECK(node->InputCount() == 1);
438 Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type); 562 Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type);
439 Node* rep_node[kMaxLanes]; 563 Node* rep_node[kMaxLanes];
440 Node* mask = graph()->NewNode(common()->Int32Constant(0xffffffff)); 564 Node* mask = graph()->NewNode(common()->Int32Constant(0xffffffff));
441 for (int i = 0; i < kMaxLanes; ++i) { 565 for (int i = 0; i < kMaxLanes; ++i) {
442 rep_node[i] = graph()->NewNode(machine()->Word32Xor(), rep[i], mask); 566 rep_node[i] = graph()->NewNode(machine()->Word32Xor(), rep[i], mask);
443 } 567 }
444 ReplaceNode(node, rep_node); 568 ReplaceNode(node, rep_node);
445 break; 569 break;
446 } 570 }
571 case IrOpcode::kInt32x4FromFloat32x4: {
572 LowerConvertFromFloat(node, true);
573 break;
574 }
575 case IrOpcode::kUint32x4FromFloat32x4: {
576 LowerConvertFromFloat(node, false);
577 break;
578 }
579 case IrOpcode::kInt32x4ShiftLeftByScalar: {
580 LowerShiftOp(node, machine()->Word32Shl());
581 break;
582 }
583 case IrOpcode::kInt32x4ShiftRightByScalar: {
584 LowerShiftOp(node, machine()->Word32Sar());
585 break;
586 }
587 case IrOpcode::kUint32x4ShiftRightByScalar: {
588 LowerShiftOp(node, machine()->Word32Shr());
589 break;
590 }
447 #define F32X4_BINOP_CASE(name) \ 591 #define F32X4_BINOP_CASE(name) \
448 case IrOpcode::kFloat32x4##name: { \ 592 case IrOpcode::kFloat32x4##name: { \
449 LowerBinaryOp(node, rep_type, machine()->Float32##name()); \ 593 LowerBinaryOp(node, rep_type, machine()->Float32##name()); \
450 break; \ 594 break; \
451 } 595 }
452 F32X4_BINOP_CASE(Add) 596 F32X4_BINOP_CASE(Add)
453 F32X4_BINOP_CASE(Sub) 597 F32X4_BINOP_CASE(Sub)
454 F32X4_BINOP_CASE(Mul) 598 F32X4_BINOP_CASE(Mul)
455 F32X4_BINOP_CASE(Div) 599 F32X4_BINOP_CASE(Div)
456 F32X4_BINOP_CASE(Min) 600 F32X4_BINOP_CASE(Min)
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
616 } else { 760 } else {
617 UNREACHABLE(); 761 UNREACHABLE();
618 } 762 }
619 } 763 }
620 ReplaceNode(phi, rep_nodes); 764 ReplaceNode(phi, rep_nodes);
621 } 765 }
622 } 766 }
623 } // namespace compiler 767 } // namespace compiler
624 } // namespace internal 768 } // namespace internal
625 } // namespace v8 769 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/simd-scalar-lowering.h ('k') | src/compiler/wasm-compiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698