LCOV - code coverage report
Current view: top level - src/compiler - simd-scalar-lowering.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 552 689 80.1 %
Date: 2019-04-17 Functions: 29 39 74.4 %

          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             : 
       7             : #include "src/compiler/diamond.h"
       8             : #include "src/compiler/linkage.h"
       9             : #include "src/compiler/node-matchers.h"
      10             : #include "src/compiler/node-properties.h"
      11             : #include "src/compiler/node.h"
      12             : #include "src/compiler/wasm-compiler.h"
      13             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : namespace compiler {
      17             : 
      18             : namespace {
      19             : static const int kNumLanes32 = 4;
      20             : static const int kNumLanes16 = 8;
      21             : static const int kNumLanes8 = 16;
      22             : static const int32_t kMask16 = 0xFFFF;
      23             : static const int32_t kMask8 = 0xFF;
      24             : static const int32_t kShift16 = 16;
      25             : static const int32_t kShift8 = 24;
      26             : }  // anonymous
      27             : 
      28        4084 : SimdScalarLowering::SimdScalarLowering(
      29             :     MachineGraph* mcgraph, Signature<MachineRepresentation>* signature)
      30             :     : mcgraph_(mcgraph),
      31             :       state_(mcgraph->graph(), 3),
      32        4084 :       stack_(mcgraph_->zone()),
      33             :       replacements_(nullptr),
      34             :       signature_(signature),
      35        4084 :       placeholder_(graph()->NewNode(common()->Parameter(-2, "placeholder"),
      36             :                                     graph()->start())),
      37       12252 :       parameter_count_after_lowering_(-1) {
      38             :   DCHECK_NOT_NULL(graph());
      39             :   DCHECK_NOT_NULL(graph()->end());
      40        4084 :   replacements_ = zone()->NewArray<Replacement>(graph()->NodeCount());
      41        4084 :   memset(static_cast<void*>(replacements_), 0,
      42             :          sizeof(Replacement) * graph()->NodeCount());
      43        4084 : }
      44             : 
      45        4084 : void SimdScalarLowering::LowerGraph() {
      46        8168 :   stack_.push_back({graph()->end(), 0});
      47             :   state_.Set(graph()->end(), State::kOnStack);
      48        8168 :   replacements_[graph()->end()->id()].type = SimdType::kInt32x4;
      49             : 
      50      250640 :   while (!stack_.empty()) {
      51             :     NodeState& top = stack_.back();
      52      493112 :     if (top.input_index == top.node->InputCount()) {
      53             :       // All inputs of top have already been lowered, now lower top.
      54       83216 :       stack_.pop_back();
      55       83216 :       state_.Set(top.node, State::kVisited);
      56       83216 :       LowerNode(top.node);
      57             :     } else {
      58             :       // Push the next input onto the stack.
      59      163340 :       Node* input = top.node->InputAt(top.input_index++);
      60      163340 :       if (state_.Get(input) == State::kUnvisited) {
      61       79132 :         SetLoweredType(input, top.node);
      62       79132 :         if (input->opcode() == IrOpcode::kPhi) {
      63             :           // To break cycles with phi nodes we push phis on a separate stack so
      64             :           // that they are processed after all other nodes.
      65          88 :           PreparePhiReplacement(input);
      66         176 :           stack_.push_front({input, 0});
      67       79044 :         } else if (input->opcode() == IrOpcode::kEffectPhi ||
      68             :                    input->opcode() == IrOpcode::kLoop) {
      69          32 :           stack_.push_front({input, 0});
      70             :         } else {
      71      158056 :           stack_.push_back({input, 0});
      72             :         }
      73             :         state_.Set(input, State::kOnStack);
      74             :       }
      75             :     }
      76             :   }
      77        4084 : }
      78             : 
      79             : #define FOREACH_INT32X4_OPCODE(V) \
      80             :   V(I32x4Splat)                   \
      81             :   V(I32x4ExtractLane)             \
      82             :   V(I32x4ReplaceLane)             \
      83             :   V(I32x4SConvertF32x4)           \
      84             :   V(I32x4UConvertF32x4)           \
      85             :   V(I32x4SConvertI16x8Low)        \
      86             :   V(I32x4SConvertI16x8High)       \
      87             :   V(I32x4Neg)                     \
      88             :   V(I32x4Shl)                     \
      89             :   V(I32x4ShrS)                    \
      90             :   V(I32x4Add)                     \
      91             :   V(I32x4AddHoriz)                \
      92             :   V(I32x4Sub)                     \
      93             :   V(I32x4Mul)                     \
      94             :   V(I32x4MinS)                    \
      95             :   V(I32x4MaxS)                    \
      96             :   V(I32x4ShrU)                    \
      97             :   V(I32x4MinU)                    \
      98             :   V(I32x4MaxU)                    \
      99             :   V(I32x4Eq)                      \
     100             :   V(I32x4Ne)                      \
     101             :   V(I32x4LtS)                     \
     102             :   V(I32x4LeS)                     \
     103             :   V(I32x4GtS)                     \
     104             :   V(I32x4GeS)                     \
     105             :   V(I32x4UConvertI16x8Low)        \
     106             :   V(I32x4UConvertI16x8High)       \
     107             :   V(I32x4LtU)                     \
     108             :   V(I32x4LeU)                     \
     109             :   V(I32x4GtU)                     \
     110             :   V(I32x4GeU)                     \
     111             :   V(S128And)                      \
     112             :   V(S128Or)                       \
     113             :   V(S128Xor)                      \
     114             :   V(S128Not)                      \
     115             :   V(S1x4AnyTrue)                  \
     116             :   V(S1x4AllTrue)                  \
     117             :   V(S1x8AnyTrue)                  \
     118             :   V(S1x8AllTrue)                  \
     119             :   V(S1x16AnyTrue)                 \
     120             :   V(S1x16AllTrue)
     121             : 
     122             : #define FOREACH_FLOAT32X4_OPCODE(V) \
     123             :   V(F32x4Splat)                     \
     124             :   V(F32x4ExtractLane)               \
     125             :   V(F32x4ReplaceLane)               \
     126             :   V(F32x4SConvertI32x4)             \
     127             :   V(F32x4UConvertI32x4)             \
     128             :   V(F32x4Abs)                       \
     129             :   V(F32x4Neg)                       \
     130             :   V(F32x4RecipApprox)               \
     131             :   V(F32x4RecipSqrtApprox)           \
     132             :   V(F32x4Add)                       \
     133             :   V(F32x4AddHoriz)                  \
     134             :   V(F32x4Sub)                       \
     135             :   V(F32x4Mul)                       \
     136             :   V(F32x4Min)                       \
     137             :   V(F32x4Max)
     138             : 
     139             : #define FOREACH_FLOAT32X4_TO_INT32X4OPCODE(V) \
     140             :   V(F32x4Eq)                                  \
     141             :   V(F32x4Ne)                                  \
     142             :   V(F32x4Lt)                                  \
     143             :   V(F32x4Le)                                  \
     144             :   V(F32x4Gt)                                  \
     145             :   V(F32x4Ge)
     146             : 
     147             : #define FOREACH_INT16X8_OPCODE(V) \
     148             :   V(I16x8Splat)                   \
     149             :   V(I16x8ExtractLane)             \
     150             :   V(I16x8ReplaceLane)             \
     151             :   V(I16x8SConvertI8x16Low)        \
     152             :   V(I16x8SConvertI8x16High)       \
     153             :   V(I16x8Neg)                     \
     154             :   V(I16x8Shl)                     \
     155             :   V(I16x8ShrS)                    \
     156             :   V(I16x8SConvertI32x4)           \
     157             :   V(I16x8Add)                     \
     158             :   V(I16x8AddSaturateS)            \
     159             :   V(I16x8AddHoriz)                \
     160             :   V(I16x8Sub)                     \
     161             :   V(I16x8SubSaturateS)            \
     162             :   V(I16x8Mul)                     \
     163             :   V(I16x8MinS)                    \
     164             :   V(I16x8MaxS)                    \
     165             :   V(I16x8UConvertI8x16Low)        \
     166             :   V(I16x8UConvertI8x16High)       \
     167             :   V(I16x8ShrU)                    \
     168             :   V(I16x8UConvertI32x4)           \
     169             :   V(I16x8AddSaturateU)            \
     170             :   V(I16x8SubSaturateU)            \
     171             :   V(I16x8MinU)                    \
     172             :   V(I16x8MaxU)                    \
     173             :   V(I16x8Eq)                      \
     174             :   V(I16x8Ne)                      \
     175             :   V(I16x8LtS)                     \
     176             :   V(I16x8LeS)                     \
     177             :   V(I16x8LtU)                     \
     178             :   V(I16x8LeU)
     179             : 
     180             : #define FOREACH_INT8X16_OPCODE(V) \
     181             :   V(I8x16Splat)                   \
     182             :   V(I8x16ExtractLane)             \
     183             :   V(I8x16ReplaceLane)             \
     184             :   V(I8x16SConvertI16x8)           \
     185             :   V(I8x16Neg)                     \
     186             :   V(I8x16Shl)                     \
     187             :   V(I8x16ShrS)                    \
     188             :   V(I8x16Add)                     \
     189             :   V(I8x16AddSaturateS)            \
     190             :   V(I8x16Sub)                     \
     191             :   V(I8x16SubSaturateS)            \
     192             :   V(I8x16Mul)                     \
     193             :   V(I8x16MinS)                    \
     194             :   V(I8x16MaxS)                    \
     195             :   V(I8x16ShrU)                    \
     196             :   V(I8x16UConvertI16x8)           \
     197             :   V(I8x16AddSaturateU)            \
     198             :   V(I8x16SubSaturateU)            \
     199             :   V(I8x16MinU)                    \
     200             :   V(I8x16MaxU)                    \
     201             :   V(I8x16Eq)                      \
     202             :   V(I8x16Ne)                      \
     203             :   V(I8x16LtS)                     \
     204             :   V(I8x16LeS)                     \
     205             :   V(I8x16LtU)                     \
     206             :   V(I8x16LeU)                     \
     207             :   V(S8x16Shuffle)
     208             : 
     209       28108 : MachineType SimdScalarLowering::MachineTypeFrom(SimdType simdType) {
     210       28108 :   switch (simdType) {
     211             :     case SimdType::kFloat32x4:
     212             :       return MachineType::Float32();
     213             :     case SimdType::kInt32x4:
     214             :       return MachineType::Int32();
     215             :     case SimdType::kInt16x8:
     216             :       return MachineType::Int16();
     217             :     case SimdType::kInt8x16:
     218             :       return MachineType::Int8();
     219             :   }
     220             :   return MachineType::None();
     221             : }
     222             : 
     223       79132 : void SimdScalarLowering::SetLoweredType(Node* node, Node* output) {
     224       79132 :   switch (node->opcode()) {
     225             : #define CASE_STMT(name) case IrOpcode::k##name:
     226             :     FOREACH_INT32X4_OPCODE(CASE_STMT)
     227             :     case IrOpcode::kReturn:
     228             :     case IrOpcode::kParameter:
     229             :     case IrOpcode::kCall: {
     230       22008 :       replacements_[node->id()].type = SimdType::kInt32x4;
     231       11004 :       break;
     232             :     }
     233             :       FOREACH_FLOAT32X4_OPCODE(CASE_STMT) {
     234         520 :         replacements_[node->id()].type = SimdType::kFloat32x4;
     235         260 :         break;
     236             :       }
     237             :       FOREACH_FLOAT32X4_TO_INT32X4OPCODE(CASE_STMT) {
     238          48 :         replacements_[node->id()].type = SimdType::kInt32x4;
     239          24 :         break;
     240             :       }
     241             :       FOREACH_INT16X8_OPCODE(CASE_STMT) {
     242        1488 :         replacements_[node->id()].type = SimdType::kInt16x8;
     243         744 :         break;
     244             :       }
     245             :       FOREACH_INT8X16_OPCODE(CASE_STMT) {
     246       14352 :         replacements_[node->id()].type = SimdType::kInt8x16;
     247        7176 :         break;
     248             :       }
     249             :     default: {
     250       59924 :       switch (output->opcode()) {
     251             :         case IrOpcode::kF32x4SConvertI32x4:
     252             :         case IrOpcode::kF32x4UConvertI32x4:
     253             :         case IrOpcode::kI16x8SConvertI32x4:
     254             :         case IrOpcode::kI16x8UConvertI32x4: {
     255           0 :           replacements_[node->id()].type = SimdType::kInt32x4;
     256           0 :           break;
     257             :         }
     258             :         case IrOpcode::kI8x16SConvertI16x8:
     259             :         case IrOpcode::kI8x16UConvertI16x8:
     260             :         case IrOpcode::kI32x4SConvertI16x8Low:
     261             :         case IrOpcode::kI32x4SConvertI16x8High:
     262             :         case IrOpcode::kI32x4UConvertI16x8Low:
     263             :         case IrOpcode::kI32x4UConvertI16x8High: {
     264           0 :           replacements_[node->id()].type = SimdType::kInt16x8;
     265           0 :           break;
     266             :         }
     267             :         case IrOpcode::kI16x8SConvertI8x16Low:
     268             :         case IrOpcode::kI16x8SConvertI8x16High:
     269             :         case IrOpcode::kI16x8UConvertI8x16Low:
     270             :         case IrOpcode::kI16x8UConvertI8x16High: {
     271           0 :           replacements_[node->id()].type = SimdType::kInt8x16;
     272           0 :           break;
     273             :         }
     274             :           FOREACH_FLOAT32X4_TO_INT32X4OPCODE(CASE_STMT)
     275             :         case IrOpcode::kI32x4SConvertF32x4:
     276             :         case IrOpcode::kI32x4UConvertF32x4: {
     277           0 :           replacements_[node->id()].type = SimdType::kFloat32x4;
     278           0 :           break;
     279             :         }
     280             :         case IrOpcode::kS128Select: {
     281           0 :           replacements_[node->id()].type = SimdType::kInt32x4;
     282           0 :           break;
     283             :         }
     284             :         default: {
     285      179772 :           replacements_[node->id()].type = replacements_[output->id()].type;
     286             :         }
     287             :       }
     288             :     }
     289             : #undef CASE_STMT
     290             :   }
     291       79132 : }
     292             : 
     293             : static int GetParameterIndexAfterLoweringSimd128(
     294             :     Signature<MachineRepresentation>* signature, int old_index) {
     295             :   // In function calls, the simd128 types are passed as 4 Int32 types. The
     296             :   // parameters are typecast to the types as needed for various operations.
     297             :   int result = old_index;
     298        6756 :   for (int i = 0; i < old_index; ++i) {
     299        2672 :     if (signature->GetParam(i) == MachineRepresentation::kSimd128) {
     300           0 :       result += 3;
     301             :     }
     302             :   }
     303             :   return result;
     304             : }
     305             : 
     306           0 : int SimdScalarLowering::GetParameterCountAfterLowering() {
     307        9488 :   if (parameter_count_after_lowering_ == -1) {
     308             :     // GetParameterIndexAfterLoweringSimd128(parameter_count) returns the
     309             :     // parameter count after lowering.
     310        4084 :     parameter_count_after_lowering_ = GetParameterIndexAfterLoweringSimd128(
     311        4084 :         signature(), static_cast<int>(signature()->parameter_count()));
     312             :   }
     313        9488 :   return parameter_count_after_lowering_;
     314             : }
     315             : 
     316             : static int GetReturnCountAfterLoweringSimd128(
     317             :     Signature<MachineRepresentation>* signature) {
     318        4228 :   int result = static_cast<int>(signature->return_count());
     319       12684 :   for (int i = 0; i < static_cast<int>(signature->return_count()); ++i) {
     320        8456 :     if (signature->GetReturn(i) == MachineRepresentation::kSimd128) {
     321           0 :       result += 3;
     322             :     }
     323             :   }
     324             :   return result;
     325             : }
     326             : 
     327           0 : int SimdScalarLowering::NumLanes(SimdType type) {
     328             :   int num_lanes = 0;
     329      112020 :   if (type == SimdType::kFloat32x4 || type == SimdType::kInt32x4) {
     330             :     num_lanes = kNumLanes32;
     331       63952 :   } else if (type == SimdType::kInt16x8) {
     332             :     num_lanes = kNumLanes16;
     333       62212 :   } else if (type == SimdType::kInt8x16) {
     334             :     num_lanes = kNumLanes8;
     335             :   } else {
     336           0 :     UNREACHABLE();
     337             :   }
     338           0 :   return num_lanes;
     339             : }
     340             : 
     341             : constexpr int SimdScalarLowering::kLaneOffsets[];
     342             : 
     343       13760 : void SimdScalarLowering::GetIndexNodes(Node* index, Node** new_indices,
     344             :                                        SimdType type) {
     345             :   int num_lanes = NumLanes(type);
     346       13760 :   int lane_width = kSimd128Size / num_lanes;
     347       13760 :   int laneIndex = kLaneOffsets[0] / lane_width;
     348       13760 :   new_indices[laneIndex] = index;
     349      403936 :   for (int i = 1; i < num_lanes; ++i) {
     350      195088 :     laneIndex = kLaneOffsets[i * lane_width] / lane_width;
     351      390176 :     new_indices[laneIndex] = graph()->NewNode(
     352             :         machine()->Int32Add(), index,
     353             :         graph()->NewNode(
     354      195088 :             common()->Int32Constant(static_cast<int>(i) * lane_width)));
     355             :   }
     356       13760 : }
     357             : 
     358       21868 : void SimdScalarLowering::LowerLoadOp(Node* node, SimdType type) {
     359       21868 :   MachineRepresentation rep = LoadRepresentationOf(node->op()).representation();
     360             :   const Operator* load_op;
     361       21868 :   switch (node->opcode()) {
     362             :     case IrOpcode::kLoad:
     363       21860 :       load_op = machine()->Load(MachineTypeFrom(type));
     364       21860 :       break;
     365             :     case IrOpcode::kUnalignedLoad:
     366           0 :       load_op = machine()->UnalignedLoad(MachineTypeFrom(type));
     367           0 :       break;
     368             :     case IrOpcode::kProtectedLoad:
     369           8 :       load_op = machine()->ProtectedLoad(MachineTypeFrom(type));
     370           8 :       break;
     371             :     default:
     372           0 :       UNREACHABLE();
     373             :   }
     374       21868 :   if (rep == MachineRepresentation::kSimd128) {
     375             :     Node* base = node->InputAt(0);
     376             :     Node* index = node->InputAt(1);
     377             :     int num_lanes = NumLanes(type);
     378        9680 :     Node** indices = zone()->NewArray<Node*>(num_lanes);
     379        9680 :     GetIndexNodes(index, indices, type);
     380             :     Node** rep_nodes = zone()->NewArray<Node*>(num_lanes);
     381        9680 :     rep_nodes[0] = node;
     382        9680 :     rep_nodes[0]->ReplaceInput(1, indices[0]);
     383        9680 :     NodeProperties::ChangeOp(rep_nodes[0], load_op);
     384        9680 :     if (node->InputCount() > 2) {
     385             :       DCHECK_LT(3, node->InputCount());
     386             :       Node* effect_input = node->InputAt(2);
     387             :       Node* control_input = node->InputAt(3);
     388      153856 :       for (int i = num_lanes - 1; i > 0; --i) {
     389      144176 :         rep_nodes[i] = graph()->NewNode(load_op, base, indices[i], effect_input,
     390      144176 :                                         control_input);
     391             :         effect_input = rep_nodes[i];
     392             :       }
     393        9680 :       rep_nodes[0]->ReplaceInput(2, rep_nodes[1]);
     394             :     } else {
     395           0 :       for (int i = 1; i < num_lanes; ++i) {
     396           0 :         rep_nodes[i] = graph()->NewNode(load_op, base, indices[i]);
     397             :       }
     398             :     }
     399        9680 :     ReplaceNode(node, rep_nodes, num_lanes);
     400             :   } else {
     401       12188 :     DefaultLowering(node);
     402             :   }
     403       21868 : }
     404             : 
     405        4080 : void SimdScalarLowering::LowerStoreOp(Node* node) {
     406             :   // For store operation, use replacement type of its input instead of the
     407             :   // one of its effected node.
     408             :   DCHECK_LT(2, node->InputCount());
     409             :   SimdType rep_type = ReplacementType(node->InputAt(2));
     410        4080 :   replacements_[node->id()].type = rep_type;
     411             :   const Operator* store_op;
     412             :   MachineRepresentation rep;
     413        4080 :   switch (node->opcode()) {
     414             :     case IrOpcode::kStore: {
     415        4076 :       rep = StoreRepresentationOf(node->op()).representation();
     416             :       WriteBarrierKind write_barrier_kind =
     417        4076 :           StoreRepresentationOf(node->op()).write_barrier_kind();
     418        4076 :       store_op = machine()->Store(StoreRepresentation(
     419       12228 :           MachineTypeFrom(rep_type).representation(), write_barrier_kind));
     420        4076 :       break;
     421             :     }
     422             :     case IrOpcode::kUnalignedStore: {
     423           0 :       rep = UnalignedStoreRepresentationOf(node->op());
     424             :       store_op =
     425           0 :           machine()->UnalignedStore(MachineTypeFrom(rep_type).representation());
     426           0 :       break;
     427             :     }
     428             :     case IrOpcode::kProtectedStore: {
     429           4 :       rep = StoreRepresentationOf(node->op()).representation();
     430             :       store_op =
     431           4 :           machine()->ProtectedStore(MachineTypeFrom(rep_type).representation());
     432           4 :       break;
     433             :     }
     434             :     default:
     435           0 :       UNREACHABLE();
     436             :   }
     437        4080 :   if (rep == MachineRepresentation::kSimd128) {
     438             :     Node* base = node->InputAt(0);
     439             :     Node* index = node->InputAt(1);
     440             :     int num_lanes = NumLanes(rep_type);
     441        4080 :     Node** indices = zone()->NewArray<Node*>(num_lanes);
     442        4080 :     GetIndexNodes(index, indices, rep_type);
     443             :     Node* value = node->InputAt(2);
     444             :     DCHECK(HasReplacement(1, value));
     445             :     Node** rep_nodes = zone()->NewArray<Node*>(num_lanes);
     446        4080 :     rep_nodes[0] = node;
     447        4080 :     Node** rep_inputs = GetReplacementsWithType(value, rep_type);
     448        4080 :     rep_nodes[0]->ReplaceInput(2, rep_inputs[0]);
     449        4080 :     rep_nodes[0]->ReplaceInput(1, indices[0]);
     450        4080 :     NodeProperties::ChangeOp(node, store_op);
     451        4080 :     if (node->InputCount() > 3) {
     452             :       DCHECK_LT(4, node->InputCount());
     453             :       Node* effect_input = node->InputAt(3);
     454             :       Node* control_input = node->InputAt(4);
     455       54992 :       for (int i = num_lanes - 1; i > 0; --i) {
     456       50912 :         rep_nodes[i] =
     457       50912 :             graph()->NewNode(store_op, base, indices[i], rep_inputs[i],
     458       50912 :                              effect_input, control_input);
     459             :         effect_input = rep_nodes[i];
     460             :       }
     461        4080 :       rep_nodes[0]->ReplaceInput(3, rep_nodes[1]);
     462             :     } else {
     463           0 :       for (int i = 1; i < num_lanes; ++i) {
     464           0 :         rep_nodes[i] =
     465           0 :             graph()->NewNode(store_op, base, indices[i], rep_inputs[i]);
     466             :       }
     467             :     }
     468        4080 :     ReplaceNode(node, rep_nodes, num_lanes);
     469             :   } else {
     470           0 :     DefaultLowering(node);
     471             :   }
     472        4080 : }
     473             : 
     474          68 : void SimdScalarLowering::LowerBinaryOp(Node* node, SimdType input_rep_type,
     475             :                                        const Operator* op,
     476             :                                        bool not_horizontal) {
     477             :   DCHECK_EQ(2, node->InputCount());
     478          68 :   Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
     479          68 :   Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type);
     480             :   int num_lanes = NumLanes(input_rep_type);
     481          68 :   Node** rep_node = zone()->NewArray<Node*>(num_lanes);
     482          68 :   if (not_horizontal) {
     483         540 :     for (int i = 0; i < num_lanes; ++i) {
     484         480 :       rep_node[i] = graph()->NewNode(op, rep_left[i], rep_right[i]);
     485             :     }
     486             :   } else {
     487          40 :     for (int i = 0; i < num_lanes / 2; ++i) {
     488          32 :       rep_node[i] = graph()->NewNode(op, rep_left[i * 2], rep_left[i * 2 + 1]);
     489          16 :       rep_node[i + num_lanes / 2] =
     490          32 :           graph()->NewNode(op, rep_right[i * 2], rep_right[i * 2 + 1]);
     491             :     }
     492             :   }
     493          68 :   ReplaceNode(node, rep_node, num_lanes);
     494          68 : }
     495             : 
     496         176 : void SimdScalarLowering::LowerCompareOp(Node* node, SimdType input_rep_type,
     497             :                                         const Operator* op,
     498             :                                         bool invert_inputs) {
     499             :   DCHECK_EQ(2, node->InputCount());
     500         176 :   Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
     501         176 :   Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type);
     502             :   int num_lanes = NumLanes(input_rep_type);
     503         176 :   Node** rep_node = zone()->NewArray<Node*>(num_lanes);
     504        3248 :   for (int i = 0; i < num_lanes; ++i) {
     505             :     Node* cmp_result = nullptr;
     506        1536 :     if (invert_inputs) {
     507         896 :       cmp_result = graph()->NewNode(op, rep_right[i], rep_left[i]);
     508             :     } else {
     509         640 :       cmp_result = graph()->NewNode(op, rep_left[i], rep_right[i]);
     510             :     }
     511             :     Diamond d_cmp(graph(), common(),
     512             :                   graph()->NewNode(machine()->Word32Equal(), cmp_result,
     513        3072 :                                    mcgraph_->Int32Constant(0)));
     514             :     MachineRepresentation rep =
     515             :         (input_rep_type == SimdType::kFloat32x4)
     516             :             ? MachineRepresentation::kWord32
     517        1536 :             : MachineTypeFrom(input_rep_type).representation();
     518        1536 :     rep_node[i] =
     519        1536 :         d_cmp.Phi(rep, mcgraph_->Int32Constant(0), mcgraph_->Int32Constant(-1));
     520             :   }
     521         176 :   ReplaceNode(node, rep_node, num_lanes);
     522         176 : }
     523             : 
     524        1632 : Node* SimdScalarLowering::FixUpperBits(Node* input, int32_t shift) {
     525        4896 :   return graph()->NewNode(machine()->Word32Sar(),
     526             :                           graph()->NewNode(machine()->Word32Shl(), input,
     527        1632 :                                            mcgraph_->Int32Constant(shift)),
     528        3264 :                           mcgraph_->Int32Constant(shift));
     529             : }
     530             : 
     531          28 : void SimdScalarLowering::LowerBinaryOpForSmallInt(Node* node,
     532             :                                                   SimdType input_rep_type,
     533             :                                                   const Operator* op,
     534             :                                                   bool not_horizontal) {
     535             :   DCHECK_EQ(2, node->InputCount());
     536             :   DCHECK(input_rep_type == SimdType::kInt16x8 ||
     537             :          input_rep_type == SimdType::kInt8x16);
     538          28 :   Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
     539          28 :   Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type);
     540             :   int num_lanes = NumLanes(input_rep_type);
     541          28 :   Node** rep_node = zone()->NewArray<Node*>(num_lanes);
     542             :   int32_t shift_val =
     543          28 :       (input_rep_type == SimdType::kInt16x8) ? kShift16 : kShift8;
     544          28 :   if (not_horizontal) {
     545         600 :     for (int i = 0; i < num_lanes; ++i) {
     546        1152 :       rep_node[i] = FixUpperBits(
     547         864 :           graph()->NewNode(op, rep_left[i], rep_right[i]), shift_val);
     548             :     }
     549             :   } else {
     550          36 :     for (int i = 0; i < num_lanes / 2; ++i) {
     551          64 :       rep_node[i] = FixUpperBits(
     552          32 :           graph()->NewNode(op, rep_left[i * 2], rep_left[i * 2 + 1]),
     553          16 :           shift_val);
     554          64 :       rep_node[i + num_lanes / 2] = FixUpperBits(
     555          32 :           graph()->NewNode(op, rep_right[i * 2], rep_right[i * 2 + 1]),
     556          16 :           shift_val);
     557             :     }
     558             :   }
     559          28 :   ReplaceNode(node, rep_node, num_lanes);
     560          28 : }
     561             : 
     562        1408 : Node* SimdScalarLowering::Mask(Node* input, int32_t mask) {
     563        1408 :   return graph()->NewNode(machine()->Word32And(), input,
     564        2816 :                           mcgraph_->Int32Constant(mask));
     565             : }
     566             : 
     567          32 : void SimdScalarLowering::LowerSaturateBinaryOp(Node* node,
     568             :                                                SimdType input_rep_type,
     569             :                                                const Operator* op,
     570             :                                                bool is_signed) {
     571             :   DCHECK_EQ(2, node->InputCount());
     572             :   DCHECK(input_rep_type == SimdType::kInt16x8 ||
     573             :          input_rep_type == SimdType::kInt8x16);
     574          32 :   Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
     575          32 :   Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type);
     576             :   int32_t min = 0;
     577             :   int32_t max = 0;
     578             :   int32_t mask = 0;
     579             :   int32_t shift_val = 0;
     580             :   MachineRepresentation phi_rep;
     581          32 :   if (input_rep_type == SimdType::kInt16x8) {
     582          16 :     if (is_signed) {
     583             :       min = std::numeric_limits<int16_t>::min();
     584             :       max = std::numeric_limits<int16_t>::max();
     585             :     } else {
     586             :       min = std::numeric_limits<uint16_t>::min();
     587             :       max = std::numeric_limits<uint16_t>::max();
     588             :     }
     589             :     mask = kMask16;
     590             :     shift_val = kShift16;
     591             :     phi_rep = MachineRepresentation::kWord16;
     592             :   } else {
     593          16 :     if (is_signed) {
     594             :       min = std::numeric_limits<int8_t>::min();
     595             :       max = std::numeric_limits<int8_t>::max();
     596             :     } else {
     597             :       min = std::numeric_limits<uint8_t>::min();
     598             :       max = std::numeric_limits<uint8_t>::max();
     599             :     }
     600             :     mask = kMask8;
     601             :     shift_val = kShift8;
     602             :     phi_rep = MachineRepresentation::kWord8;
     603             :   }
     604             :   int num_lanes = NumLanes(input_rep_type);
     605          32 :   Node** rep_node = zone()->NewArray<Node*>(num_lanes);
     606         800 :   for (int i = 0; i < num_lanes; ++i) {
     607             :     Node* op_result = nullptr;
     608         384 :     Node* left = is_signed ? rep_left[i] : Mask(rep_left[i], mask);
     609         384 :     Node* right = is_signed ? rep_right[i] : Mask(rep_right[i], mask);
     610             :     op_result = graph()->NewNode(op, left, right);
     611             :     Diamond d_min(graph(), common(),
     612             :                   graph()->NewNode(machine()->Int32LessThan(), op_result,
     613         768 :                                    mcgraph_->Int32Constant(min)));
     614         384 :     rep_node[i] = d_min.Phi(phi_rep, mcgraph_->Int32Constant(min), op_result);
     615             :     Diamond d_max(graph(), common(),
     616             :                   graph()->NewNode(machine()->Int32LessThan(),
     617         768 :                                    mcgraph_->Int32Constant(max), rep_node[i]));
     618         384 :     rep_node[i] = d_max.Phi(phi_rep, mcgraph_->Int32Constant(max), rep_node[i]);
     619             :     rep_node[i] =
     620         384 :         is_signed ? rep_node[i] : FixUpperBits(rep_node[i], shift_val);
     621             :   }
     622          32 :   ReplaceNode(node, rep_node, num_lanes);
     623          32 : }
     624             : 
     625          16 : void SimdScalarLowering::LowerUnaryOp(Node* node, SimdType input_rep_type,
     626             :                                       const Operator* op) {
     627             :   DCHECK_EQ(1, node->InputCount());
     628          16 :   Node** rep = GetReplacementsWithType(node->InputAt(0), input_rep_type);
     629             :   int num_lanes = NumLanes(input_rep_type);
     630          16 :   Node** rep_node = zone()->NewArray<Node*>(num_lanes);
     631         144 :   for (int i = 0; i < num_lanes; ++i) {
     632         128 :     rep_node[i] = graph()->NewNode(op, rep[i]);
     633             :   }
     634          16 :   ReplaceNode(node, rep_node, num_lanes);
     635          16 : }
     636             : 
     637          48 : void SimdScalarLowering::LowerIntMinMax(Node* node, const Operator* op,
     638             :                                         bool is_max, SimdType type) {
     639             :   DCHECK_EQ(2, node->InputCount());
     640          48 :   Node** rep_left = GetReplacementsWithType(node->InputAt(0), type);
     641          48 :   Node** rep_right = GetReplacementsWithType(node->InputAt(1), type);
     642             :   int num_lanes = NumLanes(type);
     643          48 :   Node** rep_node = zone()->NewArray<Node*>(num_lanes);
     644             :   MachineRepresentation rep = MachineRepresentation::kNone;
     645          48 :   if (type == SimdType::kInt32x4) {
     646             :     rep = MachineRepresentation::kWord32;
     647          32 :   } else if (type == SimdType::kInt16x8) {
     648             :     rep = MachineRepresentation::kWord16;
     649          16 :   } else if (type == SimdType::kInt8x16) {
     650             :     rep = MachineRepresentation::kWord8;
     651             :   } else {
     652           0 :     UNREACHABLE();
     653             :   }
     654         944 :   for (int i = 0; i < num_lanes; ++i) {
     655             :     Diamond d(graph(), common(),
     656         896 :               graph()->NewNode(op, rep_left[i], rep_right[i]));
     657         448 :     if (is_max) {
     658         224 :       rep_node[i] = d.Phi(rep, rep_right[i], rep_left[i]);
     659             :     } else {
     660         224 :       rep_node[i] = d.Phi(rep, rep_left[i], rep_right[i]);
     661             :     }
     662             :   }
     663          48 :   ReplaceNode(node, rep_node, num_lanes);
     664          48 : }
     665             : 
     666          32 : Node* SimdScalarLowering::BuildF64Trunc(Node* input) {
     667          32 :   if (machine()->Float64RoundTruncate().IsSupported()) {
     668          64 :     return graph()->NewNode(machine()->Float64RoundTruncate().op(), input);
     669             :   } else {
     670           0 :     ExternalReference ref = ExternalReference::wasm_f64_trunc();
     671             :     Node* stack_slot =
     672           0 :         graph()->NewNode(machine()->StackSlot(MachineRepresentation::kFloat64));
     673           0 :     const Operator* store_op = machine()->Store(
     674           0 :         StoreRepresentation(MachineRepresentation::kFloat64, kNoWriteBarrier));
     675             :     Node* effect =
     676           0 :         graph()->NewNode(store_op, stack_slot, mcgraph_->Int32Constant(0),
     677             :                          input, graph()->start(), graph()->start());
     678           0 :     Node* function = graph()->NewNode(common()->ExternalConstant(ref));
     679             :     Node** args = zone()->NewArray<Node*>(4);
     680           0 :     args[0] = function;
     681           0 :     args[1] = stack_slot;
     682           0 :     args[2] = effect;
     683           0 :     args[3] = graph()->start();
     684             :     Signature<MachineType>::Builder sig_builder(zone(), 0, 1);
     685             :     sig_builder.AddParam(MachineType::Pointer());
     686             :     auto call_descriptor =
     687           0 :         Linkage::GetSimplifiedCDescriptor(zone(), sig_builder.Build());
     688           0 :     Node* call = graph()->NewNode(common()->Call(call_descriptor), 4, args);
     689           0 :     return graph()->NewNode(machine()->Load(LoadRepresentation::Float64()),
     690             :                             stack_slot, mcgraph_->Int32Constant(0), call,
     691             :                             graph()->start());
     692             :   }
     693             : }
     694             : 
     695           8 : void SimdScalarLowering::LowerConvertFromFloat(Node* node, bool is_signed) {
     696             :   DCHECK_EQ(1, node->InputCount());
     697           8 :   Node** rep = GetReplacementsWithType(node->InputAt(0), SimdType::kFloat32x4);
     698             :   Node* rep_node[kNumLanes32];
     699           8 :   Node* double_zero = graph()->NewNode(common()->Float64Constant(0.0));
     700           8 :   Node* min = graph()->NewNode(
     701             :       common()->Float64Constant(static_cast<double>(is_signed ? kMinInt : 0)));
     702           8 :   Node* max = graph()->NewNode(common()->Float64Constant(
     703             :       static_cast<double>(is_signed ? kMaxInt : 0xFFFFFFFFu)));
     704          72 :   for (int i = 0; i < kNumLanes32; ++i) {
     705             :     Node* double_rep =
     706          32 :         graph()->NewNode(machine()->ChangeFloat32ToFloat64(), rep[i]);
     707             :     Diamond nan_d(graph(), common(), graph()->NewNode(machine()->Float64Equal(),
     708          64 :                                                       double_rep, double_rep));
     709             :     Node* temp =
     710          32 :         nan_d.Phi(MachineRepresentation::kFloat64, double_rep, double_zero);
     711             :     Diamond min_d(graph(), common(),
     712          64 :                   graph()->NewNode(machine()->Float64LessThan(), temp, min));
     713          32 :     temp = min_d.Phi(MachineRepresentation::kFloat64, min, temp);
     714             :     Diamond max_d(graph(), common(),
     715          64 :                   graph()->NewNode(machine()->Float64LessThan(), max, temp));
     716          32 :     temp = max_d.Phi(MachineRepresentation::kFloat64, max, temp);
     717          32 :     Node* trunc = BuildF64Trunc(temp);
     718          32 :     if (is_signed) {
     719          32 :       rep_node[i] = graph()->NewNode(machine()->ChangeFloat64ToInt32(), trunc);
     720             :     } else {
     721             :       rep_node[i] =
     722          32 :           graph()->NewNode(machine()->TruncateFloat64ToUint32(), trunc);
     723             :     }
     724             :   }
     725           8 :   ReplaceNode(node, rep_node, kNumLanes32);
     726           8 : }
     727             : 
     728          32 : void SimdScalarLowering::LowerConvertFromInt(Node* node,
     729             :                                              SimdType input_rep_type,
     730             :                                              SimdType output_rep_type,
     731             :                                              bool is_signed, int start_index) {
     732             :   DCHECK_EQ(1, node->InputCount());
     733          32 :   Node** rep = GetReplacementsWithType(node->InputAt(0), input_rep_type);
     734             : 
     735             :   int32_t mask = 0;
     736          32 :   if (input_rep_type == SimdType::kInt16x8) {
     737             :     DCHECK_EQ(output_rep_type, SimdType::kInt32x4);
     738             :     mask = kMask16;
     739             :   } else {
     740             :     DCHECK_EQ(output_rep_type, SimdType::kInt16x8);
     741             :     DCHECK_EQ(input_rep_type, SimdType::kInt8x16);
     742             :     mask = kMask8;
     743             :   }
     744             : 
     745             :   int num_lanes = NumLanes(output_rep_type);
     746          32 :   Node** rep_node = zone()->NewArray<Node*>(num_lanes);
     747         416 :   for (int i = 0; i < num_lanes; ++i) {
     748         192 :     rep_node[i] =
     749         192 :         is_signed ? rep[i + start_index] : Mask(rep[i + start_index], mask);
     750             :   }
     751             : 
     752          32 :   ReplaceNode(node, rep_node, num_lanes);
     753          32 : }
     754             : 
     755          16 : void SimdScalarLowering::LowerPack(Node* node, SimdType input_rep_type,
     756             :                                    SimdType output_rep_type, bool is_signed) {
     757             :   DCHECK_EQ(2, node->InputCount());
     758          16 :   Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
     759          16 :   Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type);
     760             :   const Operator* less_op =
     761          16 :       is_signed ? machine()->Int32LessThan() : machine()->Uint32LessThan();
     762             :   Node* min = nullptr;
     763             :   Node* max = nullptr;
     764             :   int32_t shift_val = 0;
     765             :   MachineRepresentation phi_rep;
     766          16 :   if (output_rep_type == SimdType::kInt16x8) {
     767             :     DCHECK(input_rep_type == SimdType::kInt32x4);
     768           8 :     if (is_signed) {
     769           4 :       min = mcgraph_->Int32Constant(std::numeric_limits<int16_t>::min());
     770           4 :       max = mcgraph_->Int32Constant(std::numeric_limits<int16_t>::max());
     771             :     } else {
     772           4 :       max = mcgraph_->Uint32Constant(std::numeric_limits<uint16_t>::max());
     773             :       shift_val = kShift16;
     774             :     }
     775             :     phi_rep = MachineRepresentation::kWord16;
     776             :   } else {
     777             :     DCHECK(output_rep_type == SimdType::kInt8x16 &&
     778             :            input_rep_type == SimdType::kInt16x8);
     779           8 :     if (is_signed) {
     780           4 :       min = mcgraph_->Int32Constant(std::numeric_limits<int8_t>::min());
     781           4 :       max = mcgraph_->Int32Constant(std::numeric_limits<int8_t>::max());
     782             :     } else {
     783           4 :       max = mcgraph_->Uint32Constant(std::numeric_limits<uint8_t>::max());
     784             :       shift_val = kShift8;
     785             :     }
     786             :     phi_rep = MachineRepresentation::kWord8;
     787             :   }
     788             :   int num_lanes = NumLanes(output_rep_type);
     789          16 :   Node** rep_node = zone()->NewArray<Node*>(num_lanes);
     790         400 :   for (int i = 0; i < num_lanes; ++i) {
     791             :     Node* input = nullptr;
     792         192 :     if (i < num_lanes / 2)
     793          96 :       input = rep_left[i];
     794             :     else
     795          96 :       input = rep_right[i - num_lanes / 2];
     796         192 :     if (is_signed) {
     797          96 :       Diamond d_min(graph(), common(), graph()->NewNode(less_op, input, min));
     798          96 :       input = d_min.Phi(phi_rep, min, input);
     799             :     }
     800         192 :     Diamond d_max(graph(), common(), graph()->NewNode(less_op, max, input));
     801         192 :     rep_node[i] = d_max.Phi(phi_rep, max, input);
     802             :     rep_node[i] =
     803         192 :         is_signed ? rep_node[i] : FixUpperBits(rep_node[i], shift_val);
     804             :   }
     805          16 :   ReplaceNode(node, rep_node, num_lanes);
     806          16 : }
     807             : 
     808         636 : void SimdScalarLowering::LowerShiftOp(Node* node, SimdType type) {
     809             :   DCHECK_EQ(1, node->InputCount());
     810         636 :   int32_t shift_amount = OpParameter<int32_t>(node->op());
     811         636 :   Node* shift_node = graph()->NewNode(common()->Int32Constant(shift_amount));
     812         636 :   Node** rep = GetReplacementsWithType(node->InputAt(0), type);
     813             :   int num_lanes = NumLanes(type);
     814         636 :   Node** rep_node = zone()->NewArray<Node*>(num_lanes);
     815        9180 :   for (int i = 0; i < num_lanes; ++i) {
     816        4272 :     rep_node[i] = rep[i];
     817        4272 :     switch (node->opcode()) {
     818             :       case IrOpcode::kI8x16ShrU:
     819         448 :         rep_node[i] = Mask(rep_node[i], kMask8);
     820             :         rep_node[i] =
     821         896 :             graph()->NewNode(machine()->Word32Shr(), rep_node[i], shift_node);
     822         448 :         break;
     823             :       case IrOpcode::kI16x8ShrU:
     824         480 :         rep_node[i] = Mask(rep_node[i], kMask16);
     825             :         V8_FALLTHROUGH;
     826             :       case IrOpcode::kI32x4ShrU:
     827             :         rep_node[i] =
     828        1952 :             graph()->NewNode(machine()->Word32Shr(), rep_node[i], shift_node);
     829         976 :         break;
     830             :       case IrOpcode::kI32x4Shl:
     831             :         rep_node[i] =
     832         992 :             graph()->NewNode(machine()->Word32Shl(), rep_node[i], shift_node);
     833         496 :         break;
     834             :       case IrOpcode::kI16x8Shl:
     835             :         rep_node[i] =
     836         960 :             graph()->NewNode(machine()->Word32Shl(), rep_node[i], shift_node);
     837         480 :         rep_node[i] = FixUpperBits(rep_node[i], kShift16);
     838         480 :         break;
     839             :       case IrOpcode::kI8x16Shl:
     840             :         rep_node[i] =
     841         896 :             graph()->NewNode(machine()->Word32Shl(), rep_node[i], shift_node);
     842         448 :         rep_node[i] = FixUpperBits(rep_node[i], kShift8);
     843         448 :         break;
     844             :       case IrOpcode::kI32x4ShrS:
     845             :       case IrOpcode::kI16x8ShrS:
     846             :       case IrOpcode::kI8x16ShrS:
     847             :         rep_node[i] =
     848        2848 :             graph()->NewNode(machine()->Word32Sar(), rep_node[i], shift_node);
     849        1424 :         break;
     850             :       default:
     851           0 :         UNREACHABLE();
     852             :     }
     853             :   }
     854         636 :   ReplaceNode(node, rep_node, num_lanes);
     855         636 : }
     856             : 
     857          76 : void SimdScalarLowering::LowerNotEqual(Node* node, SimdType input_rep_type,
     858             :                                        const Operator* op) {
     859             :   DCHECK_EQ(2, node->InputCount());
     860          76 :   Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
     861          76 :   Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type);
     862             :   int num_lanes = NumLanes(input_rep_type);
     863          76 :   Node** rep_node = zone()->NewArray<Node*>(num_lanes);
     864        1452 :   for (int i = 0; i < num_lanes; ++i) {
     865             :     Diamond d(graph(), common(),
     866        1376 :               graph()->NewNode(op, rep_left[i], rep_right[i]));
     867             :     MachineRepresentation rep =
     868             :         (input_rep_type == SimdType::kFloat32x4)
     869             :             ? MachineRepresentation::kWord32
     870         688 :             : MachineTypeFrom(input_rep_type).representation();
     871         688 :     rep_node[i] =
     872         688 :         d.Phi(rep, mcgraph_->Int32Constant(0), mcgraph_->Int32Constant(-1));
     873             :   }
     874          76 :   ReplaceNode(node, rep_node, num_lanes);
     875          76 : }
     876             : 
     877       83216 : void SimdScalarLowering::LowerNode(Node* node) {
     878             :   SimdType rep_type = ReplacementType(node);
     879             :   int num_lanes = NumLanes(rep_type);
     880       83216 :   switch (node->opcode()) {
     881             :     case IrOpcode::kStart: {
     882             :       int parameter_count = GetParameterCountAfterLowering();
     883             :       // Only exchange the node if the parameter count actually changed.
     884        4084 :       if (parameter_count != static_cast<int>(signature()->parameter_count())) {
     885             :         int delta =
     886           0 :             parameter_count - static_cast<int>(signature()->parameter_count());
     887           0 :         int new_output_count = node->op()->ValueOutputCount() + delta;
     888           0 :         NodeProperties::ChangeOp(node, common()->Start(new_output_count));
     889             :       }
     890             :       break;
     891             :     }
     892             :     case IrOpcode::kParameter: {
     893             :       DCHECK_EQ(1, node->InputCount());
     894             :       // Only exchange the node if the parameter count actually changed. We do
     895             :       // not even have to do the default lowering because the the start node,
     896             :       // the only input of a parameter node, only changes if the parameter count
     897             :       // changes.
     898        5404 :       if (GetParameterCountAfterLowering() !=
     899             :           static_cast<int>(signature()->parameter_count())) {
     900           0 :         int old_index = ParameterIndexOf(node->op());
     901             :         int new_index =
     902             :             GetParameterIndexAfterLoweringSimd128(signature(), old_index);
     903           0 :         if (old_index == new_index) {
     904           0 :           NodeProperties::ChangeOp(node, common()->Parameter(new_index));
     905             : 
     906             :           Node* new_node[kNumLanes32];
     907           0 :           for (int i = 0; i < kNumLanes32; ++i) {
     908           0 :             new_node[i] = nullptr;
     909             :           }
     910           0 :           new_node[0] = node;
     911           0 :           if (signature()->GetParam(old_index) ==
     912             :               MachineRepresentation::kSimd128) {
     913           0 :             for (int i = 1; i < kNumLanes32; ++i) {
     914           0 :               new_node[i] = graph()->NewNode(common()->Parameter(new_index + i),
     915           0 :                                              graph()->start());
     916             :             }
     917             :           }
     918           0 :           ReplaceNode(node, new_node, kNumLanes32);
     919             :         }
     920             :       }
     921             :       break;
     922             :     }
     923             :     case IrOpcode::kLoad:
     924             :     case IrOpcode::kUnalignedLoad:
     925             :     case IrOpcode::kProtectedLoad: {
     926       21868 :       LowerLoadOp(node, rep_type);
     927       21868 :       break;
     928             :     }
     929             :     case IrOpcode::kStore:
     930             :     case IrOpcode::kUnalignedStore:
     931             :     case IrOpcode::kProtectedStore: {
     932        4080 :       LowerStoreOp(node);
     933        4080 :       break;
     934             :     }
     935             :     case IrOpcode::kReturn: {
     936        4228 :       DefaultLowering(node);
     937             :       int new_return_count = GetReturnCountAfterLoweringSimd128(signature());
     938        4228 :       if (static_cast<int>(signature()->return_count()) != new_return_count) {
     939           0 :         NodeProperties::ChangeOp(node, common()->Return(new_return_count));
     940             :       }
     941             :       break;
     942             :     }
     943             :     case IrOpcode::kCall: {
     944             :       // TODO(turbofan): Make wasm code const-correct wrt. CallDescriptor.
     945             :       auto call_descriptor =
     946           0 :           const_cast<CallDescriptor*>(CallDescriptorOf(node->op()));
     947           0 :       if (DefaultLowering(node) ||
     948           0 :           (call_descriptor->ReturnCount() == 1 &&
     949             :            call_descriptor->GetReturnType(0) == MachineType::Simd128())) {
     950             :         // We have to adjust the call descriptor.
     951             :         const Operator* op = common()->Call(
     952           0 :             GetI32WasmCallDescriptorForSimd(zone(), call_descriptor));
     953           0 :         NodeProperties::ChangeOp(node, op);
     954             :       }
     955           0 :       if (call_descriptor->ReturnCount() == 1 &&
     956             :           call_descriptor->GetReturnType(0) == MachineType::Simd128()) {
     957             :         // We access the additional return values through projections.
     958             :         Node* rep_node[kNumLanes32];
     959           0 :         for (int i = 0; i < kNumLanes32; ++i) {
     960             :           rep_node[i] =
     961           0 :               graph()->NewNode(common()->Projection(i), node, graph()->start());
     962             :         }
     963           0 :         ReplaceNode(node, rep_node, kNumLanes32);
     964             :       }
     965             :       break;
     966             :     }
     967             :     case IrOpcode::kPhi: {
     968          88 :       MachineRepresentation rep = PhiRepresentationOf(node->op());
     969          88 :       if (rep == MachineRepresentation::kSimd128) {
     970             :         // The replacement nodes have already been created, we only have to
     971             :         // replace placeholder nodes.
     972             :         Node** rep_node = GetReplacements(node);
     973          40 :         for (int i = 0; i < node->op()->ValueInputCount(); ++i) {
     974             :           Node** rep_input =
     975          16 :               GetReplacementsWithType(node->InputAt(i), rep_type);
     976         144 :           for (int j = 0; j < num_lanes; j++) {
     977          64 :             rep_node[j]->ReplaceInput(i, rep_input[j]);
     978             :           }
     979             :         }
     980             :       } else {
     981          80 :         DefaultLowering(node);
     982             :       }
     983             :       break;
     984             :     }
     985             : #define I32X4_BINOP_CASE(opcode, instruction)                \
     986             :   case IrOpcode::opcode: {                                   \
     987             :     LowerBinaryOp(node, rep_type, machine()->instruction()); \
     988             :     break;                                                   \
     989             :   }
     990          12 :       I32X4_BINOP_CASE(kI32x4Add, Int32Add)
     991           4 :       I32X4_BINOP_CASE(kI32x4Sub, Int32Sub)
     992           4 :       I32X4_BINOP_CASE(kI32x4Mul, Int32Mul)
     993           4 :       I32X4_BINOP_CASE(kS128And, Word32And)
     994           4 :       I32X4_BINOP_CASE(kS128Or, Word32Or)
     995           4 :       I32X4_BINOP_CASE(kS128Xor, Word32Xor)
     996             : #undef I32X4_BINOP_CASE
     997             :     case IrOpcode::kI32x4AddHoriz: {
     998           4 :       LowerBinaryOp(node, rep_type, machine()->Int32Add(), false);
     999           4 :       break;
    1000             :     }
    1001             :     case IrOpcode::kI16x8AddHoriz: {
    1002           4 :       LowerBinaryOpForSmallInt(node, rep_type, machine()->Int32Add(), false);
    1003           4 :       break;
    1004             :     }
    1005             :     case IrOpcode::kI16x8Add:
    1006             :     case IrOpcode::kI8x16Add: {
    1007           8 :       LowerBinaryOpForSmallInt(node, rep_type, machine()->Int32Add());
    1008           8 :       break;
    1009             :     }
    1010             :     case IrOpcode::kI16x8Sub:
    1011             :     case IrOpcode::kI8x16Sub: {
    1012           8 :       LowerBinaryOpForSmallInt(node, rep_type, machine()->Int32Sub());
    1013           8 :       break;
    1014             :     }
    1015             :     case IrOpcode::kI16x8Mul:
    1016             :     case IrOpcode::kI8x16Mul: {
    1017           8 :       LowerBinaryOpForSmallInt(node, rep_type, machine()->Int32Mul());
    1018           8 :       break;
    1019             :     }
    1020             :     case IrOpcode::kI16x8AddSaturateS:
    1021             :     case IrOpcode::kI8x16AddSaturateS: {
    1022           8 :       LowerSaturateBinaryOp(node, rep_type, machine()->Int32Add(), true);
    1023           8 :       break;
    1024             :     }
    1025             :     case IrOpcode::kI16x8SubSaturateS:
    1026             :     case IrOpcode::kI8x16SubSaturateS: {
    1027           8 :       LowerSaturateBinaryOp(node, rep_type, machine()->Int32Sub(), true);
    1028           8 :       break;
    1029             :     }
    1030             :     case IrOpcode::kI16x8AddSaturateU:
    1031             :     case IrOpcode::kI8x16AddSaturateU: {
    1032           8 :       LowerSaturateBinaryOp(node, rep_type, machine()->Int32Add(), false);
    1033           8 :       break;
    1034             :     }
    1035             :     case IrOpcode::kI16x8SubSaturateU:
    1036             :     case IrOpcode::kI8x16SubSaturateU: {
    1037           8 :       LowerSaturateBinaryOp(node, rep_type, machine()->Int32Sub(), false);
    1038           8 :       break;
    1039             :     }
    1040             :     case IrOpcode::kI32x4MaxS:
    1041             :     case IrOpcode::kI16x8MaxS:
    1042             :     case IrOpcode::kI8x16MaxS: {
    1043          12 :       LowerIntMinMax(node, machine()->Int32LessThan(), true, rep_type);
    1044          12 :       break;
    1045             :     }
    1046             :     case IrOpcode::kI32x4MinS:
    1047             :     case IrOpcode::kI16x8MinS:
    1048             :     case IrOpcode::kI8x16MinS: {
    1049          12 :       LowerIntMinMax(node, machine()->Int32LessThan(), false, rep_type);
    1050          12 :       break;
    1051             :     }
    1052             :     case IrOpcode::kI32x4MaxU:
    1053             :     case IrOpcode::kI16x8MaxU:
    1054             :     case IrOpcode::kI8x16MaxU: {
    1055          12 :       LowerIntMinMax(node, machine()->Uint32LessThan(), true, rep_type);
    1056          12 :       break;
    1057             :     }
    1058             :     case IrOpcode::kI32x4MinU:
    1059             :     case IrOpcode::kI16x8MinU:
    1060             :     case IrOpcode::kI8x16MinU: {
    1061          12 :       LowerIntMinMax(node, machine()->Uint32LessThan(), false, rep_type);
    1062          12 :       break;
    1063             :     }
    1064             :     case IrOpcode::kI32x4Neg:
    1065             :     case IrOpcode::kI16x8Neg:
    1066             :     case IrOpcode::kI8x16Neg: {
    1067             :       DCHECK_EQ(1, node->InputCount());
    1068          12 :       Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type);
    1069             :       int num_lanes = NumLanes(rep_type);
    1070          12 :       Node** rep_node = zone()->NewArray<Node*>(num_lanes);
    1071          12 :       Node* zero = graph()->NewNode(common()->Int32Constant(0));
    1072         236 :       for (int i = 0; i < num_lanes; ++i) {
    1073         224 :         rep_node[i] = graph()->NewNode(machine()->Int32Sub(), zero, rep[i]);
    1074         112 :         if (node->opcode() == IrOpcode::kI16x8Neg) {
    1075          32 :           rep_node[i] = FixUpperBits(rep_node[i], kShift16);
    1076          80 :         } else if (node->opcode() == IrOpcode::kI8x16Neg) {
    1077          64 :           rep_node[i] = FixUpperBits(rep_node[i], kShift8);
    1078             :         }
    1079             :       }
    1080          12 :       ReplaceNode(node, rep_node, num_lanes);
    1081          12 :       break;
    1082             :     }
    1083             :     case IrOpcode::kS128Zero: {
    1084             :       DCHECK_EQ(0, node->InputCount());
    1085             :       Node* rep_node[kNumLanes32];
    1086           0 :       for (int i = 0; i < kNumLanes32; ++i) {
    1087           0 :         rep_node[i] = mcgraph_->Int32Constant(0);
    1088             :       }
    1089           0 :       ReplaceNode(node, rep_node, kNumLanes32);
    1090             :       break;
    1091             :     }
    1092             :     case IrOpcode::kS128Not: {
    1093             :       DCHECK_EQ(1, node->InputCount());
    1094           4 :       Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type);
    1095             :       Node* rep_node[kNumLanes32];
    1096           4 :       Node* mask = graph()->NewNode(common()->Int32Constant(0xFFFFFFFF));
    1097          36 :       for (int i = 0; i < kNumLanes32; ++i) {
    1098          32 :         rep_node[i] = graph()->NewNode(machine()->Word32Xor(), rep[i], mask);
    1099             :       }
    1100           4 :       ReplaceNode(node, rep_node, kNumLanes32);
    1101             :       break;
    1102             :     }
    1103             :     case IrOpcode::kI32x4SConvertF32x4: {
    1104           4 :       LowerConvertFromFloat(node, true);
    1105           4 :       break;
    1106             :     }
    1107             :     case IrOpcode::kI32x4UConvertF32x4: {
    1108           4 :       LowerConvertFromFloat(node, false);
    1109           4 :       break;
    1110             :     }
    1111             :     case IrOpcode::kI32x4SConvertI16x8Low: {
    1112             :       LowerConvertFromInt(node, SimdType::kInt16x8, SimdType::kInt32x4, true,
    1113           4 :                           0);
    1114           4 :       break;
    1115             :     }
    1116             :     case IrOpcode::kI32x4SConvertI16x8High: {
    1117             :       LowerConvertFromInt(node, SimdType::kInt16x8, SimdType::kInt32x4, true,
    1118           4 :                           4);
    1119           4 :       break;
    1120             :     }
    1121             :     case IrOpcode::kI32x4UConvertI16x8Low: {
    1122             :       LowerConvertFromInt(node, SimdType::kInt16x8, SimdType::kInt32x4, false,
    1123           4 :                           0);
    1124           4 :       break;
    1125             :     }
    1126             :     case IrOpcode::kI32x4UConvertI16x8High: {
    1127             :       LowerConvertFromInt(node, SimdType::kInt16x8, SimdType::kInt32x4, false,
    1128           4 :                           4);
    1129           4 :       break;
    1130             :     }
    1131             :     case IrOpcode::kI16x8SConvertI8x16Low: {
    1132             :       LowerConvertFromInt(node, SimdType::kInt8x16, SimdType::kInt16x8, true,
    1133           4 :                           0);
    1134           4 :       break;
    1135             :     }
    1136             :     case IrOpcode::kI16x8SConvertI8x16High: {
    1137             :       LowerConvertFromInt(node, SimdType::kInt8x16, SimdType::kInt16x8, true,
    1138           4 :                           8);
    1139           4 :       break;
    1140             :     }
    1141             :     case IrOpcode::kI16x8UConvertI8x16Low: {
    1142             :       LowerConvertFromInt(node, SimdType::kInt8x16, SimdType::kInt16x8, false,
    1143           4 :                           0);
    1144           4 :       break;
    1145             :     }
    1146             :     case IrOpcode::kI16x8UConvertI8x16High: {
    1147             :       LowerConvertFromInt(node, SimdType::kInt8x16, SimdType::kInt16x8, false,
    1148           4 :                           8);
    1149           4 :       break;
    1150             :     }
    1151             :     case IrOpcode::kI16x8SConvertI32x4: {
    1152           4 :       LowerPack(node, SimdType::kInt32x4, SimdType::kInt16x8, true);
    1153           4 :       break;
    1154             :     }
    1155             :     case IrOpcode::kI16x8UConvertI32x4: {
    1156           4 :       LowerPack(node, SimdType::kInt32x4, SimdType::kInt16x8, false);
    1157           4 :       break;
    1158             :     }
    1159             :     case IrOpcode::kI8x16SConvertI16x8: {
    1160           4 :       LowerPack(node, SimdType::kInt16x8, SimdType::kInt8x16, true);
    1161           4 :       break;
    1162             :     }
    1163             :     case IrOpcode::kI8x16UConvertI16x8: {
    1164           4 :       LowerPack(node, SimdType::kInt16x8, SimdType::kInt8x16, false);
    1165           4 :       break;
    1166             :     }
    1167             :     case IrOpcode::kI32x4Shl:
    1168             :     case IrOpcode::kI16x8Shl:
    1169             :     case IrOpcode::kI8x16Shl:
    1170             :     case IrOpcode::kI32x4ShrS:
    1171             :     case IrOpcode::kI16x8ShrS:
    1172             :     case IrOpcode::kI8x16ShrS:
    1173             :     case IrOpcode::kI32x4ShrU:
    1174             :     case IrOpcode::kI16x8ShrU:
    1175             :     case IrOpcode::kI8x16ShrU: {
    1176         636 :       LowerShiftOp(node, rep_type);
    1177         636 :       break;
    1178             :     }
    1179             :     case IrOpcode::kF32x4AddHoriz: {
    1180           4 :       LowerBinaryOp(node, rep_type, machine()->Float32Add(), false);
    1181           4 :       break;
    1182             :     }
    1183             : #define F32X4_BINOP_CASE(name)                                 \
    1184             :   case IrOpcode::kF32x4##name: {                               \
    1185             :     LowerBinaryOp(node, rep_type, machine()->Float32##name()); \
    1186             :     break;                                                     \
    1187             :   }
    1188          12 :       F32X4_BINOP_CASE(Add)
    1189           4 :       F32X4_BINOP_CASE(Sub)
    1190           4 :       F32X4_BINOP_CASE(Mul)
    1191           4 :       F32X4_BINOP_CASE(Min)
    1192           4 :       F32X4_BINOP_CASE(Max)
    1193             : #undef F32X4_BINOP_CASE
    1194             : #define F32X4_UNOP_CASE(name)                                 \
    1195             :   case IrOpcode::kF32x4##name: {                              \
    1196             :     LowerUnaryOp(node, rep_type, machine()->Float32##name()); \
    1197             :     break;                                                    \
    1198             :   }
    1199           4 :       F32X4_UNOP_CASE(Abs)
    1200           4 :       F32X4_UNOP_CASE(Neg)
    1201             : #undef F32x4_UNOP_CASE
    1202             :     case IrOpcode::kF32x4RecipApprox:
    1203             :     case IrOpcode::kF32x4RecipSqrtApprox: {
    1204             :       DCHECK_EQ(1, node->InputCount());
    1205           8 :       Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type);
    1206           8 :       Node** rep_node = zone()->NewArray<Node*>(num_lanes);
    1207           8 :       Node* float_one = graph()->NewNode(common()->Float32Constant(1.0));
    1208          72 :       for (int i = 0; i < num_lanes; ++i) {
    1209          32 :         Node* tmp = rep[i];
    1210          32 :         if (node->opcode() == IrOpcode::kF32x4RecipSqrtApprox) {
    1211          16 :           tmp = graph()->NewNode(machine()->Float32Sqrt(), rep[i]);
    1212             :         }
    1213          64 :         rep_node[i] = graph()->NewNode(machine()->Float32Div(), float_one, tmp);
    1214             :       }
    1215           8 :       ReplaceNode(node, rep_node, num_lanes);
    1216           8 :       break;
    1217             :     }
    1218             :     case IrOpcode::kF32x4SConvertI32x4: {
    1219           4 :       LowerUnaryOp(node, SimdType::kInt32x4, machine()->RoundInt32ToFloat32());
    1220           4 :       break;
    1221             :     }
    1222             :     case IrOpcode::kF32x4UConvertI32x4: {
    1223           4 :       LowerUnaryOp(node, SimdType::kInt32x4, machine()->RoundUint32ToFloat32());
    1224           4 :       break;
    1225             :     }
    1226             :     case IrOpcode::kI32x4Splat:
    1227             :     case IrOpcode::kF32x4Splat:
    1228             :     case IrOpcode::kI16x8Splat:
    1229             :     case IrOpcode::kI8x16Splat: {
    1230        1428 :       Node** rep_node = zone()->NewArray<Node*>(num_lanes);
    1231       22740 :       for (int i = 0; i < num_lanes; ++i) {
    1232       10656 :         if (HasReplacement(0, node->InputAt(0))) {
    1233          32 :           rep_node[i] = GetReplacements(node->InputAt(0))[0];
    1234             :         } else {
    1235       21280 :           rep_node[i] = node->InputAt(0);
    1236             :         }
    1237             :       }
    1238        1428 :       ReplaceNode(node, rep_node, num_lanes);
    1239        1428 :       break;
    1240             :     }
    1241             :     case IrOpcode::kI32x4ExtractLane:
    1242             :     case IrOpcode::kF32x4ExtractLane:
    1243             :     case IrOpcode::kI16x8ExtractLane:
    1244             :     case IrOpcode::kI8x16ExtractLane: {
    1245         140 :       int32_t lane = OpParameter<int32_t>(node->op());
    1246         140 :       Node** rep_node = zone()->NewArray<Node*>(num_lanes);
    1247         140 :       rep_node[0] = GetReplacementsWithType(node->InputAt(0), rep_type)[lane];
    1248        1492 :       for (int i = 1; i < num_lanes; ++i) {
    1249         676 :         rep_node[i] = nullptr;
    1250             :       }
    1251         140 :       ReplaceNode(node, rep_node, num_lanes);
    1252         140 :       break;
    1253             :     }
    1254             :     case IrOpcode::kI32x4ReplaceLane:
    1255             :     case IrOpcode::kF32x4ReplaceLane:
    1256             :     case IrOpcode::kI16x8ReplaceLane:
    1257             :     case IrOpcode::kI8x16ReplaceLane: {
    1258             :       DCHECK_EQ(2, node->InputCount());
    1259             :       Node* repNode = node->InputAt(1);
    1260         200 :       int32_t lane = OpParameter<int32_t>(node->op());
    1261         200 :       Node** old_rep_node = GetReplacementsWithType(node->InputAt(0), rep_type);
    1262         200 :       Node** rep_node = zone()->NewArray<Node*>(num_lanes);
    1263        3976 :       for (int i = 0; i < num_lanes; ++i) {
    1264        1888 :         rep_node[i] = old_rep_node[i];
    1265             :       }
    1266         200 :       if (HasReplacement(0, repNode)) {
    1267           0 :         rep_node[lane] = GetReplacements(repNode)[0];
    1268             :       } else {
    1269         200 :         rep_node[lane] = repNode;
    1270             :       }
    1271         200 :       ReplaceNode(node, rep_node, num_lanes);
    1272         200 :       break;
    1273             :     }
    1274             : #define COMPARISON_CASE(type, simd_op, lowering_op, invert)                    \
    1275             :   case IrOpcode::simd_op: {                                                    \
    1276             :     LowerCompareOp(node, SimdType::k##type, machine()->lowering_op(), invert); \
    1277             :     break;                                                                     \
    1278             :   }
    1279           4 :       COMPARISON_CASE(Float32x4, kF32x4Eq, Float32Equal, false)
    1280           8 :       COMPARISON_CASE(Float32x4, kF32x4Lt, Float32LessThan, false)
    1281           8 :       COMPARISON_CASE(Float32x4, kF32x4Le, Float32LessThanOrEqual, false)
    1282           0 :       COMPARISON_CASE(Float32x4, kF32x4Gt, Float32LessThan, true)
    1283           0 :       COMPARISON_CASE(Float32x4, kF32x4Ge, Float32LessThanOrEqual, true)
    1284          20 :       COMPARISON_CASE(Int32x4, kI32x4Eq, Word32Equal, false)
    1285           0 :       COMPARISON_CASE(Int32x4, kI32x4LtS, Int32LessThan, false)
    1286           0 :       COMPARISON_CASE(Int32x4, kI32x4LeS, Int32LessThanOrEqual, false)
    1287           8 :       COMPARISON_CASE(Int32x4, kI32x4GtS, Int32LessThan, true)
    1288           8 :       COMPARISON_CASE(Int32x4, kI32x4GeS, Int32LessThanOrEqual, true)
    1289           0 :       COMPARISON_CASE(Int32x4, kI32x4LtU, Uint32LessThan, false)
    1290           0 :       COMPARISON_CASE(Int32x4, kI32x4LeU, Uint32LessThanOrEqual, false)
    1291           8 :       COMPARISON_CASE(Int32x4, kI32x4GtU, Uint32LessThan, true)
    1292           8 :       COMPARISON_CASE(Int32x4, kI32x4GeU, Uint32LessThanOrEqual, true)
    1293          20 :       COMPARISON_CASE(Int16x8, kI16x8Eq, Word32Equal, false)
    1294           0 :       COMPARISON_CASE(Int16x8, kI16x8LtS, Int32LessThan, false)
    1295           0 :       COMPARISON_CASE(Int16x8, kI16x8LeS, Int32LessThanOrEqual, false)
    1296           8 :       COMPARISON_CASE(Int16x8, kI16x8GtS, Int32LessThan, true)
    1297           8 :       COMPARISON_CASE(Int16x8, kI16x8GeS, Int32LessThanOrEqual, true)
    1298           0 :       COMPARISON_CASE(Int16x8, kI16x8LtU, Uint32LessThan, false)
    1299           0 :       COMPARISON_CASE(Int16x8, kI16x8LeU, Uint32LessThanOrEqual, false)
    1300           8 :       COMPARISON_CASE(Int16x8, kI16x8GtU, Uint32LessThan, true)
    1301           8 :       COMPARISON_CASE(Int16x8, kI16x8GeU, Uint32LessThanOrEqual, true)
    1302          20 :       COMPARISON_CASE(Int8x16, kI8x16Eq, Word32Equal, false)
    1303           0 :       COMPARISON_CASE(Int8x16, kI8x16LtS, Int32LessThan, false)
    1304           0 :       COMPARISON_CASE(Int8x16, kI8x16LeS, Int32LessThanOrEqual, false)
    1305           8 :       COMPARISON_CASE(Int8x16, kI8x16GtS, Int32LessThan, true)
    1306           8 :       COMPARISON_CASE(Int8x16, kI8x16GeS, Int32LessThanOrEqual, true)
    1307           0 :       COMPARISON_CASE(Int8x16, kI8x16LtU, Uint32LessThan, false)
    1308           0 :       COMPARISON_CASE(Int8x16, kI8x16LeU, Uint32LessThanOrEqual, false)
    1309           8 :       COMPARISON_CASE(Int8x16, kI8x16GtU, Uint32LessThan, true)
    1310           8 :       COMPARISON_CASE(Int8x16, kI8x16GeU, Uint32LessThanOrEqual, true)
    1311             : #undef COMPARISON_CASE
    1312             :     case IrOpcode::kF32x4Ne: {
    1313           4 :       LowerNotEqual(node, SimdType::kFloat32x4, machine()->Float32Equal());
    1314           4 :       break;
    1315             :     }
    1316             :     case IrOpcode::kI32x4Ne: {
    1317          24 :       LowerNotEqual(node, SimdType::kInt32x4, machine()->Word32Equal());
    1318          24 :       break;
    1319             :     }
    1320             :     case IrOpcode::kI16x8Ne: {
    1321          24 :       LowerNotEqual(node, SimdType::kInt16x8, machine()->Word32Equal());
    1322          24 :       break;
    1323             :     }
    1324             :     case IrOpcode::kI8x16Ne: {
    1325          24 :       LowerNotEqual(node, SimdType::kInt8x16, machine()->Word32Equal());
    1326          24 :       break;
    1327             :     }
    1328             :     case IrOpcode::kS128Select: {
    1329             :       DCHECK_EQ(3, node->InputCount());
    1330             :       DCHECK(ReplacementType(node->InputAt(0)) == SimdType::kInt32x4 ||
    1331             :              ReplacementType(node->InputAt(0)) == SimdType::kInt16x8 ||
    1332             :              ReplacementType(node->InputAt(0)) == SimdType::kInt8x16);
    1333             :       Node** boolean_input = GetReplacements(node->InputAt(0));
    1334          16 :       Node** rep_left = GetReplacementsWithType(node->InputAt(1), rep_type);
    1335          16 :       Node** rep_right = GetReplacementsWithType(node->InputAt(2), rep_type);
    1336          16 :       Node** rep_node = zone()->NewArray<Node*>(num_lanes);
    1337         272 :       for (int i = 0; i < num_lanes; ++i) {
    1338             :         Node* tmp1 =
    1339         128 :             graph()->NewNode(machine()->Word32Xor(), rep_left[i], rep_right[i]);
    1340             :         Node* tmp2 =
    1341         128 :             graph()->NewNode(machine()->Word32And(), boolean_input[i], tmp1);
    1342         128 :         rep_node[i] =
    1343         256 :             graph()->NewNode(machine()->Word32Xor(), rep_right[i], tmp2);
    1344             :       }
    1345          16 :       ReplaceNode(node, rep_node, num_lanes);
    1346          16 :       break;
    1347             :     }
    1348             :     case IrOpcode::kS8x16Shuffle: {
    1349             :       DCHECK_EQ(2, node->InputCount());
    1350        6616 :       const uint8_t* shuffle = OpParameter<uint8_t*>(node->op());
    1351        6616 :       Node** rep_left = GetReplacementsWithType(node->InputAt(0), rep_type);
    1352        6616 :       Node** rep_right = GetReplacementsWithType(node->InputAt(1), rep_type);
    1353             :       Node** rep_node = zone()->NewArray<Node*>(16);
    1354      218328 :       for (int i = 0; i < 16; i++) {
    1355      105856 :         int lane = shuffle[i];
    1356      105856 :         rep_node[i] = lane < 16 ? rep_left[lane] : rep_right[lane - 16];
    1357             :       }
    1358        6616 :       ReplaceNode(node, rep_node, 16);
    1359        6616 :       break;
    1360             :     }
    1361             :     case IrOpcode::kS1x4AnyTrue:
    1362             :     case IrOpcode::kS1x4AllTrue:
    1363             :     case IrOpcode::kS1x8AnyTrue:
    1364             :     case IrOpcode::kS1x8AllTrue:
    1365             :     case IrOpcode::kS1x16AnyTrue:
    1366             :     case IrOpcode::kS1x16AllTrue: {
    1367             :       DCHECK_EQ(1, node->InputCount());
    1368             :       SimdType input_rep_type = ReplacementType(node->InputAt(0));
    1369             :       int input_num_lanes = NumLanes(input_rep_type);
    1370             :       Node** rep = GetReplacements(node->InputAt(0));
    1371          96 :       Node** rep_node = zone()->NewArray<Node*>(num_lanes);
    1372          96 :       Node* true_node = mcgraph_->Int32Constant(-1);
    1373          96 :       Node* false_node = mcgraph_->Int32Constant(0);
    1374             :       Node* tmp_result = false_node;
    1375         176 :       if (node->opcode() == IrOpcode::kS1x4AllTrue ||
    1376         160 :           node->opcode() == IrOpcode::kS1x8AllTrue ||
    1377             :           node->opcode() == IrOpcode::kS1x16AllTrue) {
    1378             :         tmp_result = true_node;
    1379             :       }
    1380        1888 :       for (int i = 0; i < input_num_lanes; ++i) {
    1381             :         Diamond is_false(
    1382             :             graph(), common(),
    1383        1792 :             graph()->NewNode(machine()->Word32Equal(), rep[i], false_node));
    1384        1728 :         if (node->opcode() == IrOpcode::kS1x4AllTrue ||
    1385        1600 :             node->opcode() == IrOpcode::kS1x8AllTrue ||
    1386             :             node->opcode() == IrOpcode::kS1x16AllTrue) {
    1387             :           tmp_result = is_false.Phi(MachineRepresentation::kWord32, false_node,
    1388         448 :                                     tmp_result);
    1389             :         } else {
    1390             :           tmp_result = is_false.Phi(MachineRepresentation::kWord32, tmp_result,
    1391         448 :                                     true_node);
    1392             :         }
    1393             :       }
    1394          96 :       rep_node[0] = tmp_result;
    1395         672 :       for (int i = 1; i < num_lanes; ++i) {
    1396         288 :         rep_node[i] = nullptr;
    1397             :       }
    1398          96 :       ReplaceNode(node, rep_node, num_lanes);
    1399          96 :       break;
    1400             :     }
    1401       33808 :     default: { DefaultLowering(node); }
    1402             :   }
    1403       83216 : }
    1404             : 
    1405       50304 : bool SimdScalarLowering::DefaultLowering(Node* node) {
    1406             :   bool something_changed = false;
    1407       94128 :   for (int i = NodeProperties::PastValueIndex(node) - 1; i >= 0; i--) {
    1408             :     Node* input = node->InputAt(i);
    1409       43824 :     if (HasReplacement(0, input)) {
    1410             :       something_changed = true;
    1411         232 :       node->ReplaceInput(i, GetReplacements(input)[0]);
    1412             :     }
    1413       43824 :     if (HasReplacement(1, input)) {
    1414             :       something_changed = true;
    1415           0 :       for (int j = 1; j < ReplacementCount(input); ++j) {
    1416           0 :         node->InsertInput(zone(), i + j, GetReplacements(input)[j]);
    1417             :       }
    1418             :     }
    1419             :   }
    1420       50304 :   return something_changed;
    1421             : }
    1422             : 
    1423       23424 : void SimdScalarLowering::ReplaceNode(Node* old, Node** new_nodes, int count) {
    1424       70272 :   replacements_[old->id()].node = zone()->NewArray<Node*>(count);
    1425      697760 :   for (int i = 0; i < count; ++i) {
    1426      674336 :     replacements_[old->id()].node[i] = new_nodes[i];
    1427             :   }
    1428       46848 :   replacements_[old->id()].num_replacements = count;
    1429       23424 : }
    1430             : 
    1431           0 : bool SimdScalarLowering::HasReplacement(size_t index, Node* node) {
    1432      197488 :   return replacements_[node->id()].node != nullptr &&
    1433         480 :          replacements_[node->id()].node[index] != nullptr;
    1434             : }
    1435             : 
    1436           0 : SimdScalarLowering::SimdType SimdScalarLowering::ReplacementType(Node* node) {
    1437      194088 :   return replacements_[node->id()].type;
    1438             : }
    1439             : 
    1440           0 : Node** SimdScalarLowering::GetReplacements(Node* node) {
    1441       38752 :   Node** result = replacements_[node->id()].node;
    1442             :   DCHECK(result);
    1443           0 :   return result;
    1444             : }
    1445             : 
    1446           0 : int SimdScalarLowering::ReplacementCount(Node* node) {
    1447           0 :   return replacements_[node->id()].num_replacements;
    1448             : }
    1449             : 
    1450          28 : void SimdScalarLowering::Int32ToFloat32(Node** replacements, Node** result) {
    1451         252 :   for (int i = 0; i < kNumLanes32; ++i) {
    1452         112 :     if (replacements[i] != nullptr) {
    1453         112 :       result[i] =
    1454         224 :           graph()->NewNode(machine()->BitcastInt32ToFloat32(), replacements[i]);
    1455             :     } else {
    1456           0 :       result[i] = nullptr;
    1457             :     }
    1458             :   }
    1459          28 : }
    1460             : 
    1461          12 : void SimdScalarLowering::Float32ToInt32(Node** replacements, Node** result) {
    1462         108 :   for (int i = 0; i < kNumLanes32; ++i) {
    1463          48 :     if (replacements[i] != nullptr) {
    1464          48 :       result[i] =
    1465          96 :           graph()->NewNode(machine()->BitcastFloat32ToInt32(), replacements[i]);
    1466             :     } else {
    1467           0 :       result[i] = nullptr;
    1468             :     }
    1469             :   }
    1470          12 : }
    1471             : 
    1472             : template <typename T>
    1473           0 : void SimdScalarLowering::Int32ToSmallerInt(Node** replacements, Node** result) {
    1474             :   const int num_ints = sizeof(int32_t) / sizeof(T);
    1475             :   const int bit_size = sizeof(T) * 8;
    1476             :   const Operator* sign_extend;
    1477             :   switch (sizeof(T)) {
    1478             :     case 1:
    1479           0 :       sign_extend = machine()->SignExtendWord8ToInt32();
    1480             :       break;
    1481             :     case 2:
    1482           0 :       sign_extend = machine()->SignExtendWord16ToInt32();
    1483             :       break;
    1484             :     default:
    1485             :       UNREACHABLE();
    1486             :   }
    1487             : 
    1488           0 :   for (int i = 0; i < kNumLanes32; i++) {
    1489           0 :     if (replacements[i] != nullptr) {
    1490           0 :       for (int j = 0; j < num_ints; j++) {
    1491           0 :         result[num_ints * i + j] = graph()->NewNode(
    1492             :             sign_extend,
    1493             :             graph()->NewNode(machine()->Word32Sar(), replacements[i],
    1494           0 :                              mcgraph_->Int32Constant(j * bit_size)));
    1495             :       }
    1496             :     } else {
    1497           0 :       for (int j = 0; j < num_ints; j++) {
    1498           0 :         result[num_ints * i + j] = nullptr;
    1499             :       }
    1500             :     }
    1501             :   }
    1502           0 : }
    1503             : 
    1504             : template <typename T>
    1505           0 : void SimdScalarLowering::SmallerIntToInt32(Node** replacements, Node** result) {
    1506             :   const int num_ints = sizeof(int32_t) / sizeof(T);
    1507             :   const int bit_size = sizeof(T) * 8;
    1508             :   const int bit_mask = (1 << bit_size) - 1;
    1509             : 
    1510           0 :   for (int i = 0; i < kNumLanes32; ++i) {
    1511           0 :     result[i] = mcgraph_->Int32Constant(0);
    1512           0 :     for (int j = 0; j < num_ints; j++) {
    1513           0 :       if (replacements[num_ints * i + j] != nullptr) {
    1514           0 :         Node* clean_bits = graph()->NewNode(machine()->Word32And(),
    1515             :                                             replacements[num_ints * i + j],
    1516           0 :                                             mcgraph_->Int32Constant(bit_mask));
    1517           0 :         Node* shift = graph()->NewNode(machine()->Word32Shl(), clean_bits,
    1518           0 :                                        mcgraph_->Int32Constant(j * bit_size));
    1519           0 :         result[i] = graph()->NewNode(machine()->Word32Or(), result[i], shift);
    1520             :       }
    1521             :     }
    1522             :   }
    1523           0 : }
    1524             : 
    1525       19304 : Node** SimdScalarLowering::GetReplacementsWithType(Node* node, SimdType type) {
    1526             :   Node** replacements = GetReplacements(node);
    1527       19304 :   if (ReplacementType(node) == type) {
    1528             :     return GetReplacements(node);
    1529             :   }
    1530             :   int num_lanes = NumLanes(type);
    1531          40 :   Node** result = zone()->NewArray<Node*>(num_lanes);
    1532          40 :   if (type == SimdType::kInt32x4) {
    1533          12 :     if (ReplacementType(node) == SimdType::kFloat32x4) {
    1534          12 :       Float32ToInt32(replacements, result);
    1535           0 :     } else if (ReplacementType(node) == SimdType::kInt16x8) {
    1536           0 :       SmallerIntToInt32<int16_t>(replacements, result);
    1537           0 :     } else if (ReplacementType(node) == SimdType::kInt8x16) {
    1538           0 :       SmallerIntToInt32<int8_t>(replacements, result);
    1539             :     } else {
    1540           0 :       UNREACHABLE();
    1541             :     }
    1542          28 :   } else if (type == SimdType::kFloat32x4) {
    1543          28 :     if (ReplacementType(node) == SimdType::kInt32x4) {
    1544          28 :       Int32ToFloat32(replacements, result);
    1545           0 :     } else if (ReplacementType(node) == SimdType::kInt16x8) {
    1546           0 :       UNIMPLEMENTED();
    1547             :     } else {
    1548           0 :       UNREACHABLE();
    1549             :     }
    1550           0 :   } else if (type == SimdType::kInt16x8) {
    1551           0 :     if (ReplacementType(node) == SimdType::kInt32x4) {
    1552           0 :       Int32ToSmallerInt<int16_t>(replacements, result);
    1553           0 :     } else if (ReplacementType(node) == SimdType::kFloat32x4) {
    1554           0 :       UNIMPLEMENTED();
    1555             :     } else {
    1556           0 :       UNREACHABLE();
    1557             :     }
    1558           0 :   } else if (type == SimdType::kInt8x16) {
    1559           0 :     if (ReplacementType(node) == SimdType::kInt32x4) {
    1560           0 :       Int32ToSmallerInt<int8_t>(replacements, result);
    1561             :     } else {
    1562           0 :       UNIMPLEMENTED();
    1563             :     }
    1564             :   } else {
    1565           0 :     UNREACHABLE();
    1566             :   }
    1567             :   return result;
    1568             : }
    1569             : 
    1570          88 : void SimdScalarLowering::PreparePhiReplacement(Node* phi) {
    1571          88 :   MachineRepresentation rep = PhiRepresentationOf(phi->op());
    1572          88 :   if (rep == MachineRepresentation::kSimd128) {
    1573             :     // We have to create the replacements for a phi node before we actually
    1574             :     // lower the phi to break potential cycles in the graph. The replacements of
    1575             :     // input nodes do not exist yet, so we use a placeholder node to pass the
    1576             :     // graph verifier.
    1577             :     int value_count = phi->op()->ValueInputCount();
    1578             :     SimdType type = ReplacementType(phi);
    1579             :     int num_lanes = NumLanes(type);
    1580           8 :     Node*** inputs_rep = zone()->NewArray<Node**>(num_lanes);
    1581          72 :     for (int i = 0; i < num_lanes; ++i) {
    1582          64 :       inputs_rep[i] = zone()->NewArray<Node*>(value_count + 1);
    1583          32 :       inputs_rep[i][value_count] = NodeProperties::GetControlInput(phi, 0);
    1584             :     }
    1585          40 :     for (int i = 0; i < value_count; ++i) {
    1586         144 :       for (int j = 0; j < num_lanes; ++j) {
    1587          64 :         inputs_rep[j][i] = placeholder_;
    1588             :       }
    1589             :     }
    1590             :     Node** rep_nodes = zone()->NewArray<Node*>(num_lanes);
    1591          72 :     for (int i = 0; i < num_lanes; ++i) {
    1592          96 :       rep_nodes[i] = graph()->NewNode(
    1593          64 :           common()->Phi(MachineTypeFrom(type).representation(), value_count),
    1594          64 :           value_count + 1, inputs_rep[i], false);
    1595             :     }
    1596           8 :     ReplaceNode(phi, rep_nodes, num_lanes);
    1597             :   }
    1598          88 : }
    1599             : }  // namespace compiler
    1600             : }  // namespace internal
    1601      121996 : }  // namespace v8

Generated by: LCOV version 1.10