LCOV - code coverage report
Current view: top level - src/compiler - simd-scalar-lowering.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 0 370 0.0 %
Date: 2017-04-26 Functions: 0 22 0.0 %

          Line data    Source code
       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
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/compiler/simd-scalar-lowering.h"
       6             : #include "src/compiler/diamond.h"
       7             : #include "src/compiler/linkage.h"
       8             : #include "src/compiler/node-matchers.h"
       9             : #include "src/compiler/node-properties.h"
      10             : 
      11             : #include "src/compiler/node.h"
      12             : #include "src/objects-inl.h"
      13             : #include "src/wasm/wasm-module.h"
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : namespace compiler {
      18             : 
      19           0 : SimdScalarLowering::SimdScalarLowering(
      20           0 :     JSGraph* jsgraph, Signature<MachineRepresentation>* signature)
      21             :     : jsgraph_(jsgraph),
      22             :       state_(jsgraph->graph(), 3),
      23             :       stack_(jsgraph_->zone()),
      24             :       replacements_(nullptr),
      25             :       signature_(signature),
      26             :       placeholder_(graph()->NewNode(common()->Parameter(-2, "placeholder"),
      27           0 :                                     graph()->start())),
      28           0 :       parameter_count_after_lowering_(-1) {
      29             :   DCHECK_NOT_NULL(graph());
      30             :   DCHECK_NOT_NULL(graph()->end());
      31           0 :   replacements_ = zone()->NewArray<Replacement>(graph()->NodeCount());
      32           0 :   memset(replacements_, 0, sizeof(Replacement) * graph()->NodeCount());
      33           0 : }
      34             : 
      35           0 : void SimdScalarLowering::LowerGraph() {
      36           0 :   stack_.push_back({graph()->end(), 0});
      37           0 :   state_.Set(graph()->end(), State::kOnStack);
      38           0 :   replacements_[graph()->end()->id()].type = SimdType::kInt32;
      39             : 
      40           0 :   while (!stack_.empty()) {
      41             :     NodeState& top = stack_.back();
      42           0 :     if (top.input_index == top.node->InputCount()) {
      43             :       // All inputs of top have already been lowered, now lower top.
      44             :       stack_.pop_back();
      45           0 :       state_.Set(top.node, State::kVisited);
      46           0 :       LowerNode(top.node);
      47             :     } else {
      48             :       // Push the next input onto the stack.
      49           0 :       Node* input = top.node->InputAt(top.input_index++);
      50           0 :       if (state_.Get(input) == State::kUnvisited) {
      51           0 :         SetLoweredType(input, top.node);
      52           0 :         if (input->opcode() == IrOpcode::kPhi) {
      53             :           // To break cycles with phi nodes we push phis on a separate stack so
      54             :           // that they are processed after all other nodes.
      55           0 :           PreparePhiReplacement(input);
      56           0 :           stack_.push_front({input, 0});
      57           0 :         } else if (input->opcode() == IrOpcode::kEffectPhi ||
      58             :                    input->opcode() == IrOpcode::kLoop) {
      59           0 :           stack_.push_front({input, 0});
      60             :         } else {
      61           0 :           stack_.push_back({input, 0});
      62             :         }
      63             :         state_.Set(input, State::kOnStack);
      64             :       }
      65             :     }
      66             :   }
      67           0 : }
      68             : 
      69             : #define FOREACH_INT32X4_OPCODE(V) \
      70             :   V(I32x4Splat)                   \
      71             :   V(I32x4ExtractLane)             \
      72             :   V(I32x4ReplaceLane)             \
      73             :   V(I32x4SConvertF32x4)           \
      74             :   V(I32x4UConvertF32x4)           \
      75             :   V(I32x4Neg)                     \
      76             :   V(I32x4Add)                     \
      77             :   V(I32x4Sub)                     \
      78             :   V(I32x4Mul)                     \
      79             :   V(I32x4MinS)                    \
      80             :   V(I32x4MaxS)                    \
      81             :   V(I32x4MinU)                    \
      82             :   V(I32x4MaxU)                    \
      83             :   V(S128And)                      \
      84             :   V(S128Or)                       \
      85             :   V(S128Xor)                      \
      86             :   V(S128Not)
      87             : 
      88             : #define FOREACH_FLOAT32X4_OPCODE(V) \
      89             :   V(F32x4Splat)                     \
      90             :   V(F32x4ExtractLane)               \
      91             :   V(F32x4ReplaceLane)               \
      92             :   V(F32x4SConvertI32x4)             \
      93             :   V(F32x4UConvertI32x4)             \
      94             :   V(F32x4Abs)                       \
      95             :   V(F32x4Neg)                       \
      96             :   V(F32x4Add)                       \
      97             :   V(F32x4Sub)                       \
      98             :   V(F32x4Mul)                       \
      99             :   V(F32x4Min)                       \
     100             :   V(F32x4Max)
     101             : 
     102             : #define FOREACH_FLOAT32X4_TO_SIMD1X4OPCODE(V) \
     103             :   V(F32x4Eq)                                  \
     104             :   V(F32x4Ne)                                  \
     105             :   V(F32x4Lt)                                  \
     106             :   V(F32x4Le)                                  \
     107             :   V(F32x4Gt)                                  \
     108             :   V(F32x4Ge)
     109             : 
     110             : #define FOREACH_INT32X4_TO_SIMD1X4OPCODE(V) \
     111             :   V(I32x4Eq)                                \
     112             :   V(I32x4Ne)                                \
     113             :   V(I32x4LtS)                               \
     114             :   V(I32x4LeS)                               \
     115             :   V(I32x4GtS)                               \
     116             :   V(I32x4GeS)                               \
     117             :   V(I32x4LtU)                               \
     118             :   V(I32x4LeU)                               \
     119             :   V(I32x4GtU)                               \
     120             :   V(I32x4GeU)
     121             : 
     122           0 : void SimdScalarLowering::SetLoweredType(Node* node, Node* output) {
     123           0 :   switch (node->opcode()) {
     124             : #define CASE_STMT(name) case IrOpcode::k##name:
     125             :     FOREACH_INT32X4_OPCODE(CASE_STMT)
     126             :     case IrOpcode::kReturn:
     127             :     case IrOpcode::kParameter:
     128             :     case IrOpcode::kCall: {
     129           0 :       replacements_[node->id()].type = SimdType::kInt32;
     130           0 :       break;
     131             :     }
     132             :       FOREACH_FLOAT32X4_OPCODE(CASE_STMT) {
     133           0 :         replacements_[node->id()].type = SimdType::kFloat32;
     134           0 :         break;
     135             :       }
     136             :       FOREACH_FLOAT32X4_TO_SIMD1X4OPCODE(CASE_STMT)
     137             :       FOREACH_INT32X4_TO_SIMD1X4OPCODE(CASE_STMT) {
     138           0 :         replacements_[node->id()].type = SimdType::kSimd1x4;
     139           0 :         break;
     140             :       }
     141             :     default: {
     142           0 :       switch (output->opcode()) {
     143             :         FOREACH_FLOAT32X4_TO_SIMD1X4OPCODE(CASE_STMT)
     144             :         case IrOpcode::kF32x4SConvertI32x4:
     145             :         case IrOpcode::kF32x4UConvertI32x4: {
     146           0 :           replacements_[node->id()].type = SimdType::kInt32;
     147           0 :           break;
     148             :         }
     149             :           FOREACH_INT32X4_TO_SIMD1X4OPCODE(CASE_STMT)
     150             :         case IrOpcode::kI32x4SConvertF32x4:
     151             :         case IrOpcode::kI32x4UConvertF32x4: {
     152           0 :           replacements_[node->id()].type = SimdType::kFloat32;
     153           0 :           break;
     154             :         }
     155             :         case IrOpcode::kS32x4Select: {
     156           0 :           replacements_[node->id()].type = SimdType::kSimd1x4;
     157           0 :           break;
     158             :         }
     159             :         default: {
     160           0 :           replacements_[node->id()].type = replacements_[output->id()].type;
     161             :         }
     162             :       }
     163             :     }
     164             : #undef CASE_STMT
     165             :   }
     166           0 : }
     167             : 
     168             : static int GetParameterIndexAfterLowering(
     169           0 :     Signature<MachineRepresentation>* signature, int old_index) {
     170             :   // In function calls, the simd128 types are passed as 4 Int32 types. The
     171             :   // parameters are typecast to the types as needed for various operations.
     172             :   int result = old_index;
     173           0 :   for (int i = 0; i < old_index; ++i) {
     174           0 :     if (signature->GetParam(i) == MachineRepresentation::kSimd128) {
     175           0 :       result += 3;
     176             :     }
     177             :   }
     178             :   return result;
     179             : }
     180             : 
     181           0 : int SimdScalarLowering::GetParameterCountAfterLowering() {
     182           0 :   if (parameter_count_after_lowering_ == -1) {
     183             :     // GetParameterIndexAfterLowering(parameter_count) returns the parameter
     184             :     // count after lowering.
     185             :     parameter_count_after_lowering_ = GetParameterIndexAfterLowering(
     186           0 :         signature(), static_cast<int>(signature()->parameter_count()));
     187             :   }
     188           0 :   return parameter_count_after_lowering_;
     189             : }
     190             : 
     191             : static int GetReturnCountAfterLowering(
     192           0 :     Signature<MachineRepresentation>* signature) {
     193           0 :   int result = static_cast<int>(signature->return_count());
     194           0 :   for (int i = 0; i < static_cast<int>(signature->return_count()); ++i) {
     195           0 :     if (signature->GetReturn(i) == MachineRepresentation::kSimd128) {
     196           0 :       result += 3;
     197             :     }
     198             :   }
     199             :   return result;
     200             : }
     201             : 
     202           0 : void SimdScalarLowering::GetIndexNodes(Node* index, Node** new_indices) {
     203           0 :   new_indices[0] = index;
     204           0 :   for (size_t i = 1; i < kMaxLanes; ++i) {
     205           0 :     new_indices[i] = graph()->NewNode(machine()->Int32Add(), index,
     206             :                                       graph()->NewNode(common()->Int32Constant(
     207           0 :                                           static_cast<int>(i) * kLaneWidth)));
     208             :   }
     209           0 : }
     210             : 
     211           0 : void SimdScalarLowering::LowerLoadOp(MachineRepresentation rep, Node* node,
     212           0 :                                      const Operator* load_op) {
     213           0 :   if (rep == MachineRepresentation::kSimd128) {
     214             :     Node* base = node->InputAt(0);
     215             :     Node* index = node->InputAt(1);
     216             :     Node* indices[kMaxLanes];
     217           0 :     GetIndexNodes(index, indices);
     218             :     Node* rep_nodes[kMaxLanes];
     219           0 :     rep_nodes[0] = node;
     220           0 :     NodeProperties::ChangeOp(rep_nodes[0], load_op);
     221           0 :     if (node->InputCount() > 2) {
     222             :       DCHECK(node->InputCount() > 3);
     223             :       Node* effect_input = node->InputAt(2);
     224             :       Node* control_input = node->InputAt(3);
     225             :       rep_nodes[3] = graph()->NewNode(load_op, base, indices[3], effect_input,
     226           0 :                                       control_input);
     227             :       rep_nodes[2] = graph()->NewNode(load_op, base, indices[2], rep_nodes[3],
     228           0 :                                       control_input);
     229             :       rep_nodes[1] = graph()->NewNode(load_op, base, indices[1], rep_nodes[2],
     230           0 :                                       control_input);
     231           0 :       rep_nodes[0]->ReplaceInput(2, rep_nodes[1]);
     232             :     } else {
     233           0 :       for (size_t i = 1; i < kMaxLanes; ++i) {
     234           0 :         rep_nodes[i] = graph()->NewNode(load_op, base, indices[i]);
     235             :       }
     236             :     }
     237             :     ReplaceNode(node, rep_nodes);
     238             :   } else {
     239           0 :     DefaultLowering(node);
     240             :   }
     241           0 : }
     242             : 
     243           0 : void SimdScalarLowering::LowerStoreOp(MachineRepresentation rep, Node* node,
     244             :                                       const Operator* store_op,
     245           0 :                                       SimdType rep_type) {
     246           0 :   if (rep == MachineRepresentation::kSimd128) {
     247             :     Node* base = node->InputAt(0);
     248             :     Node* index = node->InputAt(1);
     249             :     Node* indices[kMaxLanes];
     250           0 :     GetIndexNodes(index, indices);
     251             :     DCHECK(node->InputCount() > 2);
     252             :     Node* value = node->InputAt(2);
     253             :     DCHECK(HasReplacement(1, value));
     254             :     Node* rep_nodes[kMaxLanes];
     255           0 :     rep_nodes[0] = node;
     256           0 :     Node** rep_inputs = GetReplacementsWithType(value, rep_type);
     257           0 :     rep_nodes[0]->ReplaceInput(2, rep_inputs[0]);
     258           0 :     NodeProperties::ChangeOp(node, store_op);
     259           0 :     if (node->InputCount() > 3) {
     260             :       DCHECK(node->InputCount() > 4);
     261             :       Node* effect_input = node->InputAt(3);
     262             :       Node* control_input = node->InputAt(4);
     263             :       rep_nodes[3] = graph()->NewNode(store_op, base, indices[3], rep_inputs[3],
     264           0 :                                       effect_input, control_input);
     265             :       rep_nodes[2] = graph()->NewNode(store_op, base, indices[2], rep_inputs[2],
     266           0 :                                       rep_nodes[3], control_input);
     267             :       rep_nodes[1] = graph()->NewNode(store_op, base, indices[1], rep_inputs[1],
     268           0 :                                       rep_nodes[2], control_input);
     269           0 :       rep_nodes[0]->ReplaceInput(3, rep_nodes[1]);
     270             : 
     271             :     } else {
     272           0 :       for (size_t i = 1; i < kMaxLanes; ++i) {
     273             :         rep_nodes[i] =
     274           0 :             graph()->NewNode(store_op, base, indices[i], rep_inputs[i]);
     275             :       }
     276             :     }
     277             : 
     278             :     ReplaceNode(node, rep_nodes);
     279             :   } else {
     280           0 :     DefaultLowering(node);
     281             :   }
     282           0 : }
     283             : 
     284           0 : void SimdScalarLowering::LowerBinaryOp(Node* node, SimdType input_rep_type,
     285           0 :                                        const Operator* op, bool invert_inputs) {
     286             :   DCHECK(node->InputCount() == 2);
     287           0 :   Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
     288           0 :   Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type);
     289             :   Node* rep_node[kMaxLanes];
     290           0 :   for (int i = 0; i < kMaxLanes; ++i) {
     291           0 :     if (invert_inputs) {
     292           0 :       rep_node[i] = graph()->NewNode(op, rep_right[i], rep_left[i]);
     293             :     } else {
     294           0 :       rep_node[i] = graph()->NewNode(op, rep_left[i], rep_right[i]);
     295             :     }
     296             :   }
     297             :   ReplaceNode(node, rep_node);
     298           0 : }
     299             : 
     300           0 : void SimdScalarLowering::LowerUnaryOp(Node* node, SimdType input_rep_type,
     301           0 :                                       const Operator* op) {
     302             :   DCHECK(node->InputCount() == 1);
     303           0 :   Node** rep = GetReplacementsWithType(node->InputAt(0), input_rep_type);
     304             :   Node* rep_node[kMaxLanes];
     305           0 :   for (int i = 0; i < kMaxLanes; ++i) {
     306           0 :     rep_node[i] = graph()->NewNode(op, rep[i]);
     307             :   }
     308             :   ReplaceNode(node, rep_node);
     309           0 : }
     310             : 
     311           0 : void SimdScalarLowering::LowerIntMinMax(Node* node, const Operator* op,
     312           0 :                                         bool is_max) {
     313             :   DCHECK(node->InputCount() == 2);
     314           0 :   Node** rep_left = GetReplacementsWithType(node->InputAt(0), SimdType::kInt32);
     315             :   Node** rep_right =
     316           0 :       GetReplacementsWithType(node->InputAt(1), SimdType::kInt32);
     317             :   Node* rep_node[kMaxLanes];
     318           0 :   for (int i = 0; i < kMaxLanes; ++i) {
     319             :     Diamond d(graph(), common(),
     320           0 :               graph()->NewNode(op, rep_left[i], rep_right[i]));
     321           0 :     if (is_max) {
     322             :       rep_node[i] =
     323           0 :           d.Phi(MachineRepresentation::kWord32, rep_right[i], rep_left[i]);
     324             :     } else {
     325             :       rep_node[i] =
     326           0 :           d.Phi(MachineRepresentation::kWord32, rep_left[i], rep_right[i]);
     327             :     }
     328             :   }
     329             :   ReplaceNode(node, rep_node);
     330           0 : }
     331             : 
     332           0 : Node* SimdScalarLowering::BuildF64Trunc(Node* input) {
     333           0 :   if (machine()->Float64RoundTruncate().IsSupported()) {
     334           0 :     return graph()->NewNode(machine()->Float64RoundTruncate().op(), input);
     335             :   } else {
     336             :     ExternalReference ref =
     337           0 :         ExternalReference::wasm_f64_trunc(jsgraph_->isolate());
     338             :     Node* stack_slot =
     339           0 :         graph()->NewNode(machine()->StackSlot(MachineRepresentation::kFloat64));
     340             :     const Operator* store_op = machine()->Store(
     341           0 :         StoreRepresentation(MachineRepresentation::kFloat64, kNoWriteBarrier));
     342             :     Node* effect =
     343             :         graph()->NewNode(store_op, stack_slot, jsgraph_->Int32Constant(0),
     344           0 :                          input, graph()->start(), graph()->start());
     345           0 :     Node* function = graph()->NewNode(common()->ExternalConstant(ref));
     346             :     Node** args = zone()->NewArray<Node*>(4);
     347           0 :     args[0] = function;
     348           0 :     args[1] = stack_slot;
     349           0 :     args[2] = effect;
     350           0 :     args[3] = graph()->start();
     351             :     Signature<MachineType>::Builder sig_builder(zone(), 0, 1);
     352             :     sig_builder.AddParam(MachineType::Pointer());
     353             :     CallDescriptor* desc =
     354           0 :         Linkage::GetSimplifiedCDescriptor(zone(), sig_builder.Build());
     355           0 :     Node* call = graph()->NewNode(common()->Call(desc), 4, args);
     356             :     return graph()->NewNode(machine()->Load(LoadRepresentation::Float64()),
     357             :                             stack_slot, jsgraph_->Int32Constant(0), call,
     358           0 :                             graph()->start());
     359             :   }
     360             : }
     361             : 
     362           0 : void SimdScalarLowering::LowerConvertFromFloat(Node* node, bool is_signed) {
     363             :   DCHECK(node->InputCount() == 1);
     364           0 :   Node** rep = GetReplacementsWithType(node->InputAt(0), SimdType::kFloat32);
     365             :   Node* rep_node[kMaxLanes];
     366           0 :   Node* double_zero = graph()->NewNode(common()->Float64Constant(0.0));
     367             :   Node* min = graph()->NewNode(
     368           0 :       common()->Float64Constant(static_cast<double>(is_signed ? kMinInt : 0)));
     369             :   Node* max = graph()->NewNode(common()->Float64Constant(
     370           0 :       static_cast<double>(is_signed ? kMaxInt : 0xffffffffu)));
     371           0 :   for (int i = 0; i < kMaxLanes; ++i) {
     372             :     Node* double_rep =
     373           0 :         graph()->NewNode(machine()->ChangeFloat32ToFloat64(), rep[i]);
     374             :     Diamond nan_d(graph(), common(), graph()->NewNode(machine()->Float64Equal(),
     375           0 :                                                       double_rep, double_rep));
     376             :     Node* temp =
     377           0 :         nan_d.Phi(MachineRepresentation::kFloat64, double_rep, double_zero);
     378             :     Diamond min_d(graph(), common(),
     379           0 :                   graph()->NewNode(machine()->Float64LessThan(), temp, min));
     380           0 :     temp = min_d.Phi(MachineRepresentation::kFloat64, min, temp);
     381             :     Diamond max_d(graph(), common(),
     382           0 :                   graph()->NewNode(machine()->Float64LessThan(), max, temp));
     383           0 :     temp = max_d.Phi(MachineRepresentation::kFloat64, max, temp);
     384           0 :     Node* trunc = BuildF64Trunc(temp);
     385           0 :     if (is_signed) {
     386           0 :       rep_node[i] = graph()->NewNode(machine()->ChangeFloat64ToInt32(), trunc);
     387             :     } else {
     388             :       rep_node[i] =
     389           0 :           graph()->NewNode(machine()->TruncateFloat64ToUint32(), trunc);
     390             :     }
     391             :   }
     392             :   ReplaceNode(node, rep_node);
     393           0 : }
     394             : 
     395           0 : void SimdScalarLowering::LowerShiftOp(Node* node, const Operator* op) {
     396             :   static int32_t shift_mask = 0x1f;
     397             :   DCHECK_EQ(1, node->InputCount());
     398           0 :   int32_t shift_amount = OpParameter<int32_t>(node);
     399             :   Node* shift_node =
     400           0 :       graph()->NewNode(common()->Int32Constant(shift_amount & shift_mask));
     401           0 :   Node** rep = GetReplacementsWithType(node->InputAt(0), SimdType::kInt32);
     402             :   Node* rep_node[kMaxLanes];
     403           0 :   for (int i = 0; i < kMaxLanes; ++i) {
     404           0 :     rep_node[i] = graph()->NewNode(op, rep[i], shift_node);
     405             :   }
     406             :   ReplaceNode(node, rep_node);
     407           0 : }
     408             : 
     409           0 : void SimdScalarLowering::LowerNotEqual(Node* node, SimdType input_rep_type,
     410           0 :                                        const Operator* op) {
     411             :   DCHECK(node->InputCount() == 2);
     412           0 :   Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
     413           0 :   Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type);
     414             :   Node* rep_node[kMaxLanes];
     415           0 :   for (int i = 0; i < kMaxLanes; ++i) {
     416             :     Diamond d(graph(), common(),
     417           0 :               graph()->NewNode(op, rep_left[i], rep_right[i]));
     418             :     rep_node[i] = d.Phi(MachineRepresentation::kWord32,
     419           0 :                         jsgraph_->Int32Constant(0), jsgraph_->Int32Constant(1));
     420             :   }
     421             :   ReplaceNode(node, rep_node);
     422           0 : }
     423             : 
     424           0 : void SimdScalarLowering::LowerNode(Node* node) {
     425             :   SimdType rep_type = ReplacementType(node);
     426           0 :   switch (node->opcode()) {
     427             :     case IrOpcode::kStart: {
     428           0 :       int parameter_count = GetParameterCountAfterLowering();
     429             :       // Only exchange the node if the parameter count actually changed.
     430           0 :       if (parameter_count != static_cast<int>(signature()->parameter_count())) {
     431             :         int delta =
     432           0 :             parameter_count - static_cast<int>(signature()->parameter_count());
     433           0 :         int new_output_count = node->op()->ValueOutputCount() + delta;
     434           0 :         NodeProperties::ChangeOp(node, common()->Start(new_output_count));
     435             :       }
     436             :       break;
     437             :     }
     438             :     case IrOpcode::kParameter: {
     439             :       DCHECK(node->InputCount() == 1);
     440             :       // Only exchange the node if the parameter count actually changed. We do
     441             :       // not even have to do the default lowering because the the start node,
     442             :       // the only input of a parameter node, only changes if the parameter count
     443             :       // changes.
     444           0 :       if (GetParameterCountAfterLowering() !=
     445           0 :           static_cast<int>(signature()->parameter_count())) {
     446           0 :         int old_index = ParameterIndexOf(node->op());
     447             :         int new_index = GetParameterIndexAfterLowering(signature(), old_index);
     448           0 :         if (old_index == new_index) {
     449           0 :           NodeProperties::ChangeOp(node, common()->Parameter(new_index));
     450             : 
     451             :           Node* new_node[kMaxLanes];
     452           0 :           for (int i = 0; i < kMaxLanes; ++i) {
     453           0 :             new_node[i] = nullptr;
     454             :           }
     455           0 :           new_node[0] = node;
     456           0 :           if (signature()->GetParam(old_index) ==
     457             :               MachineRepresentation::kSimd128) {
     458           0 :             for (int i = 1; i < kMaxLanes; ++i) {
     459             :               new_node[i] = graph()->NewNode(common()->Parameter(new_index + i),
     460           0 :                                              graph()->start());
     461             :             }
     462             :           }
     463             :           ReplaceNode(node, new_node);
     464             :         }
     465             :       }
     466             :       break;
     467             :     }
     468             :     case IrOpcode::kLoad: {
     469             :       MachineRepresentation rep =
     470           0 :           LoadRepresentationOf(node->op()).representation();
     471             :       const Operator* load_op;
     472           0 :       if (rep_type == SimdType::kInt32) {
     473           0 :         load_op = machine()->Load(MachineType::Int32());
     474           0 :       } else if (rep_type == SimdType::kFloat32) {
     475           0 :         load_op = machine()->Load(MachineType::Float32());
     476             :       }
     477           0 :       LowerLoadOp(rep, node, load_op);
     478           0 :       break;
     479             :     }
     480             :     case IrOpcode::kUnalignedLoad: {
     481             :       MachineRepresentation rep =
     482           0 :           UnalignedLoadRepresentationOf(node->op()).representation();
     483             :       const Operator* load_op;
     484           0 :       if (rep_type == SimdType::kInt32) {
     485           0 :         load_op = machine()->UnalignedLoad(MachineType::Int32());
     486           0 :       } else if (rep_type == SimdType::kFloat32) {
     487           0 :         load_op = machine()->UnalignedLoad(MachineType::Float32());
     488             :       }
     489           0 :       LowerLoadOp(rep, node, load_op);
     490           0 :       break;
     491             :     }
     492             :     case IrOpcode::kStore: {
     493             :       MachineRepresentation rep =
     494           0 :           StoreRepresentationOf(node->op()).representation();
     495             :       WriteBarrierKind write_barrier_kind =
     496           0 :           StoreRepresentationOf(node->op()).write_barrier_kind();
     497             :       const Operator* store_op;
     498           0 :       if (rep_type == SimdType::kInt32) {
     499             :         store_op = machine()->Store(StoreRepresentation(
     500           0 :             MachineRepresentation::kWord32, write_barrier_kind));
     501             :       } else {
     502             :         store_op = machine()->Store(StoreRepresentation(
     503           0 :             MachineRepresentation::kFloat32, write_barrier_kind));
     504             :       }
     505           0 :       LowerStoreOp(rep, node, store_op, rep_type);
     506           0 :       break;
     507             :     }
     508             :     case IrOpcode::kUnalignedStore: {
     509           0 :       MachineRepresentation rep = UnalignedStoreRepresentationOf(node->op());
     510             :       const Operator* store_op;
     511           0 :       if (rep_type == SimdType::kInt32) {
     512           0 :         store_op = machine()->UnalignedStore(MachineRepresentation::kWord32);
     513             :       } else {
     514           0 :         store_op = machine()->UnalignedStore(MachineRepresentation::kFloat32);
     515             :       }
     516           0 :       LowerStoreOp(rep, node, store_op, rep_type);
     517           0 :       break;
     518             :     }
     519             :     case IrOpcode::kReturn: {
     520           0 :       DefaultLowering(node);
     521             :       int new_return_count = GetReturnCountAfterLowering(signature());
     522           0 :       if (static_cast<int>(signature()->return_count()) != new_return_count) {
     523           0 :         NodeProperties::ChangeOp(node, common()->Return(new_return_count));
     524             :       }
     525             :       break;
     526             :     }
     527             :     case IrOpcode::kCall: {
     528             :       // TODO(turbofan): Make WASM code const-correct wrt. CallDescriptor.
     529           0 :       CallDescriptor* descriptor =
     530           0 :           const_cast<CallDescriptor*>(CallDescriptorOf(node->op()));
     531           0 :       if (DefaultLowering(node) ||
     532           0 :           (descriptor->ReturnCount() == 1 &&
     533             :            descriptor->GetReturnType(0) == MachineType::Simd128())) {
     534             :         // We have to adjust the call descriptor.
     535             :         const Operator* op =
     536             :             common()->Call(wasm::ModuleEnv::GetI32WasmCallDescriptorForSimd(
     537           0 :                 zone(), descriptor));
     538           0 :         NodeProperties::ChangeOp(node, op);
     539             :       }
     540           0 :       if (descriptor->ReturnCount() == 1 &&
     541             :           descriptor->GetReturnType(0) == MachineType::Simd128()) {
     542             :         // We access the additional return values through projections.
     543             :         Node* rep_node[kMaxLanes];
     544           0 :         for (int i = 0; i < kMaxLanes; ++i) {
     545             :           rep_node[i] =
     546           0 :               graph()->NewNode(common()->Projection(i), node, graph()->start());
     547             :         }
     548             :         ReplaceNode(node, rep_node);
     549             :       }
     550             :       break;
     551             :     }
     552             :     case IrOpcode::kPhi: {
     553           0 :       MachineRepresentation rep = PhiRepresentationOf(node->op());
     554           0 :       if (rep == MachineRepresentation::kSimd128) {
     555             :         // The replacement nodes have already been created, we only have to
     556             :         // replace placeholder nodes.
     557           0 :         Node** rep_node = GetReplacements(node);
     558           0 :         for (int i = 0; i < node->op()->ValueInputCount(); ++i) {
     559             :           Node** rep_input =
     560           0 :               GetReplacementsWithType(node->InputAt(i), rep_type);
     561           0 :           for (int j = 0; j < kMaxLanes; j++) {
     562           0 :             rep_node[j]->ReplaceInput(i, rep_input[j]);
     563             :           }
     564             :         }
     565             :       } else {
     566           0 :         DefaultLowering(node);
     567             :       }
     568             :       break;
     569             :     }
     570             : #define I32X4_BINOP_CASE(opcode, instruction)                \
     571             :   case IrOpcode::opcode: {                                   \
     572             :     LowerBinaryOp(node, rep_type, machine()->instruction()); \
     573             :     break;                                                   \
     574             :   }
     575           0 :       I32X4_BINOP_CASE(kI32x4Add, Int32Add)
     576           0 :       I32X4_BINOP_CASE(kI32x4Sub, Int32Sub)
     577           0 :       I32X4_BINOP_CASE(kI32x4Mul, Int32Mul)
     578           0 :       I32X4_BINOP_CASE(kS128And, Word32And)
     579           0 :       I32X4_BINOP_CASE(kS128Or, Word32Or)
     580           0 :       I32X4_BINOP_CASE(kS128Xor, Word32Xor)
     581             : #undef I32X4_BINOP_CASE
     582             :     case IrOpcode::kI32x4MaxS: {
     583           0 :       LowerIntMinMax(node, machine()->Int32LessThan(), true);
     584           0 :       break;
     585             :     }
     586             :     case IrOpcode::kI32x4MinS: {
     587           0 :       LowerIntMinMax(node, machine()->Int32LessThan(), false);
     588           0 :       break;
     589             :     }
     590             :     case IrOpcode::kI32x4MaxU: {
     591           0 :       LowerIntMinMax(node, machine()->Uint32LessThan(), true);
     592           0 :       break;
     593             :     }
     594             :     case IrOpcode::kI32x4MinU: {
     595           0 :       LowerIntMinMax(node, machine()->Uint32LessThan(), false);
     596           0 :       break;
     597             :     }
     598             :     case IrOpcode::kI32x4Neg: {
     599             :       DCHECK(node->InputCount() == 1);
     600           0 :       Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type);
     601             :       Node* rep_node[kMaxLanes];
     602           0 :       Node* zero = graph()->NewNode(common()->Int32Constant(0));
     603           0 :       for (int i = 0; i < kMaxLanes; ++i) {
     604           0 :         rep_node[i] = graph()->NewNode(machine()->Int32Sub(), zero, rep[i]);
     605             :       }
     606             :       ReplaceNode(node, rep_node);
     607             :       break;
     608             :     }
     609             :     case IrOpcode::kS128Not: {
     610             :       DCHECK(node->InputCount() == 1);
     611           0 :       Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type);
     612             :       Node* rep_node[kMaxLanes];
     613           0 :       Node* mask = graph()->NewNode(common()->Int32Constant(0xffffffff));
     614           0 :       for (int i = 0; i < kMaxLanes; ++i) {
     615           0 :         rep_node[i] = graph()->NewNode(machine()->Word32Xor(), rep[i], mask);
     616             :       }
     617             :       ReplaceNode(node, rep_node);
     618             :       break;
     619             :     }
     620             :     case IrOpcode::kI32x4SConvertF32x4: {
     621           0 :       LowerConvertFromFloat(node, true);
     622           0 :       break;
     623             :     }
     624             :     case IrOpcode::kI32x4UConvertF32x4: {
     625           0 :       LowerConvertFromFloat(node, false);
     626           0 :       break;
     627             :     }
     628             :     case IrOpcode::kI32x4Shl: {
     629           0 :       LowerShiftOp(node, machine()->Word32Shl());
     630           0 :       break;
     631             :     }
     632             :     case IrOpcode::kI32x4ShrS: {
     633           0 :       LowerShiftOp(node, machine()->Word32Sar());
     634           0 :       break;
     635             :     }
     636             :     case IrOpcode::kI32x4ShrU: {
     637           0 :       LowerShiftOp(node, machine()->Word32Shr());
     638           0 :       break;
     639             :     }
     640             : #define F32X4_BINOP_CASE(name)                                 \
     641             :   case IrOpcode::kF32x4##name: {                               \
     642             :     LowerBinaryOp(node, rep_type, machine()->Float32##name()); \
     643             :     break;                                                     \
     644             :   }
     645           0 :       F32X4_BINOP_CASE(Add)
     646           0 :       F32X4_BINOP_CASE(Sub)
     647           0 :       F32X4_BINOP_CASE(Mul)
     648           0 :       F32X4_BINOP_CASE(Min)
     649           0 :       F32X4_BINOP_CASE(Max)
     650             : #undef F32X4_BINOP_CASE
     651             : #define F32X4_UNOP_CASE(name)                                 \
     652             :   case IrOpcode::kF32x4##name: {                              \
     653             :     LowerUnaryOp(node, rep_type, machine()->Float32##name()); \
     654             :     break;                                                    \
     655             :   }
     656           0 :       F32X4_UNOP_CASE(Abs)
     657           0 :       F32X4_UNOP_CASE(Neg)
     658             : #undef F32x4_UNOP_CASE
     659             :     case IrOpcode::kF32x4SConvertI32x4: {
     660           0 :       LowerUnaryOp(node, SimdType::kInt32, machine()->RoundInt32ToFloat32());
     661           0 :       break;
     662             :     }
     663             :     case IrOpcode::kF32x4UConvertI32x4: {
     664           0 :       LowerUnaryOp(node, SimdType::kInt32, machine()->RoundUint32ToFloat32());
     665           0 :       break;
     666             :     }
     667             :     case IrOpcode::kI32x4Splat:
     668             :     case IrOpcode::kF32x4Splat: {
     669             :       Node* rep_node[kMaxLanes];
     670           0 :       for (int i = 0; i < kMaxLanes; ++i) {
     671           0 :         if (HasReplacement(0, node->InputAt(0))) {
     672           0 :           rep_node[i] = GetReplacements(node->InputAt(0))[0];
     673             :         } else {
     674           0 :           rep_node[i] = node->InputAt(0);
     675             :         }
     676             :       }
     677             :       ReplaceNode(node, rep_node);
     678             :       break;
     679             :     }
     680             :     case IrOpcode::kI32x4ExtractLane:
     681             :     case IrOpcode::kF32x4ExtractLane: {
     682           0 :       int32_t lane = OpParameter<int32_t>(node);
     683             :       Node* rep_node[kMaxLanes] = {
     684           0 :           GetReplacementsWithType(node->InputAt(0), rep_type)[lane], nullptr,
     685           0 :           nullptr, nullptr};
     686             :       ReplaceNode(node, rep_node);
     687             :       break;
     688             :     }
     689             :     case IrOpcode::kI32x4ReplaceLane:
     690             :     case IrOpcode::kF32x4ReplaceLane: {
     691             :       DCHECK_EQ(2, node->InputCount());
     692             :       Node* repNode = node->InputAt(1);
     693           0 :       int32_t lane = OpParameter<int32_t>(node);
     694             :       DCHECK(lane >= 0 && lane <= 3);
     695           0 :       Node** rep_node = GetReplacementsWithType(node->InputAt(0), rep_type);
     696           0 :       if (HasReplacement(0, repNode)) {
     697           0 :         rep_node[lane] = GetReplacements(repNode)[0];
     698             :       } else {
     699           0 :         rep_node[lane] = repNode;
     700             :       }
     701             :       ReplaceNode(node, rep_node);
     702             :       break;
     703             :     }
     704             : #define COMPARISON_CASE(type, simd_op, lowering_op, invert)                   \
     705             :   case IrOpcode::simd_op: {                                                   \
     706             :     LowerBinaryOp(node, SimdType::k##type, machine()->lowering_op(), invert); \
     707             :     break;                                                                    \
     708             :   }
     709           0 :       COMPARISON_CASE(Float32, kF32x4Eq, Float32Equal, false)
     710           0 :       COMPARISON_CASE(Float32, kF32x4Lt, Float32LessThan, false)
     711           0 :       COMPARISON_CASE(Float32, kF32x4Le, Float32LessThanOrEqual, false)
     712           0 :       COMPARISON_CASE(Float32, kF32x4Gt, Float32LessThan, true)
     713           0 :       COMPARISON_CASE(Float32, kF32x4Ge, Float32LessThanOrEqual, true)
     714           0 :       COMPARISON_CASE(Int32, kI32x4Eq, Word32Equal, false)
     715           0 :       COMPARISON_CASE(Int32, kI32x4LtS, Int32LessThan, false)
     716           0 :       COMPARISON_CASE(Int32, kI32x4LeS, Int32LessThanOrEqual, false)
     717           0 :       COMPARISON_CASE(Int32, kI32x4GtS, Int32LessThan, true)
     718           0 :       COMPARISON_CASE(Int32, kI32x4GeS, Int32LessThanOrEqual, true)
     719           0 :       COMPARISON_CASE(Int32, kI32x4LtU, Uint32LessThan, false)
     720           0 :       COMPARISON_CASE(Int32, kI32x4LeU, Uint32LessThanOrEqual, false)
     721           0 :       COMPARISON_CASE(Int32, kI32x4GtU, Uint32LessThan, true)
     722           0 :       COMPARISON_CASE(Int32, kI32x4GeU, Uint32LessThanOrEqual, true)
     723             : #undef COMPARISON_CASE
     724             :     case IrOpcode::kF32x4Ne: {
     725           0 :       LowerNotEqual(node, SimdType::kFloat32, machine()->Float32Equal());
     726           0 :       break;
     727             :     }
     728             :     case IrOpcode::kI32x4Ne: {
     729           0 :       LowerNotEqual(node, SimdType::kInt32, machine()->Word32Equal());
     730           0 :       break;
     731             :     }
     732             :     case IrOpcode::kS32x4Select: {
     733             :       DCHECK(node->InputCount() == 3);
     734             :       DCHECK(ReplacementType(node->InputAt(0)) == SimdType::kSimd1x4);
     735           0 :       Node** boolean_input = GetReplacements(node->InputAt(0));
     736           0 :       Node** rep_left = GetReplacementsWithType(node->InputAt(1), rep_type);
     737           0 :       Node** rep_right = GetReplacementsWithType(node->InputAt(2), rep_type);
     738             :       Node* rep_node[kMaxLanes];
     739           0 :       for (int i = 0; i < kMaxLanes; ++i) {
     740             :         Diamond d(graph(), common(),
     741           0 :                   graph()->NewNode(machine()->Word32Equal(), boolean_input[i],
     742           0 :                                    jsgraph_->Int32Constant(0)));
     743           0 :         if (rep_type == SimdType::kFloat32) {
     744             :           rep_node[i] =
     745           0 :               d.Phi(MachineRepresentation::kFloat32, rep_right[1], rep_left[0]);
     746           0 :         } else if (rep_type == SimdType::kInt32) {
     747             :           rep_node[i] =
     748           0 :               d.Phi(MachineRepresentation::kWord32, rep_right[1], rep_left[0]);
     749             :         } else {
     750           0 :           UNREACHABLE();
     751             :         }
     752             :       }
     753             :       ReplaceNode(node, rep_node);
     754             :       break;
     755             :     }
     756           0 :     default: { DefaultLowering(node); }
     757             :   }
     758           0 : }
     759             : 
     760           0 : bool SimdScalarLowering::DefaultLowering(Node* node) {
     761             :   bool something_changed = false;
     762           0 :   for (int i = NodeProperties::PastValueIndex(node) - 1; i >= 0; i--) {
     763             :     Node* input = node->InputAt(i);
     764           0 :     if (HasReplacement(0, input)) {
     765             :       something_changed = true;
     766           0 :       node->ReplaceInput(i, GetReplacements(input)[0]);
     767             :     }
     768           0 :     if (HasReplacement(1, input)) {
     769             :       something_changed = true;
     770           0 :       for (int j = 1; j < kMaxLanes; j++) {
     771           0 :         node->InsertInput(zone(), i + j, GetReplacements(input)[j]);
     772             :       }
     773             :     }
     774             :   }
     775           0 :   return something_changed;
     776             : }
     777             : 
     778           0 : void SimdScalarLowering::ReplaceNode(Node* old, Node** new_node) {
     779             :   // if new_low == nullptr, then also new_high == nullptr.
     780             :   DCHECK(new_node[0] != nullptr ||
     781             :          (new_node[1] == nullptr && new_node[2] == nullptr &&
     782             :           new_node[3] == nullptr));
     783           0 :   for (int i = 0; i < kMaxLanes; ++i) {
     784           0 :     replacements_[old->id()].node[i] = new_node[i];
     785             :   }
     786           0 : }
     787             : 
     788           0 : bool SimdScalarLowering::HasReplacement(size_t index, Node* node) {
     789           0 :   return replacements_[node->id()].node[index] != nullptr;
     790             : }
     791             : 
     792           0 : SimdScalarLowering::SimdType SimdScalarLowering::ReplacementType(Node* node) {
     793           0 :   return replacements_[node->id()].type;
     794             : }
     795             : 
     796           0 : Node** SimdScalarLowering::GetReplacements(Node* node) {
     797           0 :   Node** result = replacements_[node->id()].node;
     798             :   DCHECK(result);
     799           0 :   return result;
     800             : }
     801             : 
     802           0 : Node** SimdScalarLowering::GetReplacementsWithType(Node* node, SimdType type) {
     803           0 :   Node** replacements = GetReplacements(node);
     804           0 :   if (ReplacementType(node) == type) {
     805             :     return GetReplacements(node);
     806             :   }
     807             :   Node** result = zone()->NewArray<Node*>(kMaxLanes);
     808           0 :   if (ReplacementType(node) == SimdType::kInt32 && type == SimdType::kFloat32) {
     809           0 :     for (int i = 0; i < kMaxLanes; ++i) {
     810           0 :       if (replacements[i] != nullptr) {
     811           0 :         result[i] = graph()->NewNode(machine()->BitcastInt32ToFloat32(),
     812           0 :                                      replacements[i]);
     813             :       } else {
     814           0 :         result[i] = nullptr;
     815             :       }
     816             :     }
     817           0 :   } else if (ReplacementType(node) == SimdType::kFloat32 &&
     818             :              type == SimdType::kInt32) {
     819           0 :     for (int i = 0; i < kMaxLanes; ++i) {
     820           0 :       if (replacements[i] != nullptr) {
     821           0 :         result[i] = graph()->NewNode(machine()->BitcastFloat32ToInt32(),
     822           0 :                                      replacements[i]);
     823             :       } else {
     824           0 :         result[i] = nullptr;
     825             :       }
     826             :     }
     827             :   } else {
     828           0 :     UNREACHABLE();
     829             :   }
     830           0 :   return result;
     831             : }
     832             : 
     833           0 : void SimdScalarLowering::PreparePhiReplacement(Node* phi) {
     834           0 :   MachineRepresentation rep = PhiRepresentationOf(phi->op());
     835           0 :   if (rep == MachineRepresentation::kSimd128) {
     836             :     // We have to create the replacements for a phi node before we actually
     837             :     // lower the phi to break potential cycles in the graph. The replacements of
     838             :     // input nodes do not exist yet, so we use a placeholder node to pass the
     839             :     // graph verifier.
     840           0 :     int value_count = phi->op()->ValueInputCount();
     841             :     SimdType type = ReplacementType(phi);
     842             :     Node** inputs_rep[kMaxLanes];
     843           0 :     for (int i = 0; i < kMaxLanes; ++i) {
     844           0 :       inputs_rep[i] = zone()->NewArray<Node*>(value_count + 1);
     845           0 :       inputs_rep[i][value_count] = NodeProperties::GetControlInput(phi, 0);
     846             :     }
     847           0 :     for (int i = 0; i < value_count; ++i) {
     848           0 :       for (int j = 0; j < kMaxLanes; j++) {
     849           0 :         inputs_rep[j][i] = placeholder_;
     850             :       }
     851             :     }
     852             :     Node* rep_nodes[kMaxLanes];
     853           0 :     for (int i = 0; i < kMaxLanes; ++i) {
     854           0 :       if (type == SimdType::kInt32) {
     855             :         rep_nodes[i] = graph()->NewNode(
     856             :             common()->Phi(MachineRepresentation::kWord32, value_count),
     857           0 :             value_count + 1, inputs_rep[i], false);
     858           0 :       } else if (type == SimdType::kFloat32) {
     859             :         rep_nodes[i] = graph()->NewNode(
     860             :             common()->Phi(MachineRepresentation::kFloat32, value_count),
     861           0 :             value_count + 1, inputs_rep[i], false);
     862             :       } else {
     863           0 :         UNREACHABLE();
     864             :       }
     865             :     }
     866             :     ReplaceNode(phi, rep_nodes);
     867             :   }
     868           0 : }
     869             : }  // namespace compiler
     870             : }  // namespace internal
     871             : }  // namespace v8

Generated by: LCOV version 1.10