| 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 12 matching lines...) Expand all  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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 | 
| OLD | NEW | 
|---|