LCOV - code coverage report
Current view: top level - src/compiler - simd-scalar-lowering.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 576 714 80.7 %
Date: 2019-01-20 Functions: 32 40 80.0 %

          Line data    Source code
       1             : // Copyright 2016 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/compiler/simd-scalar-lowering.h"
       6             : 
       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        5085 : SimdScalarLowering::SimdScalarLowering(
      29       25425 :     MachineGraph* mcgraph, Signature<MachineRepresentation>* signature)
      30             :     : mcgraph_(mcgraph),
      31             :       state_(mcgraph->graph(), 3),
      32             :       stack_(mcgraph_->zone()),
      33             :       replacements_(nullptr),
      34             :       signature_(signature),
      35             :       placeholder_(graph()->NewNode(common()->Parameter(-2, "placeholder"),
      36       10170 :                                     graph()->start())),
      37       20340 :       parameter_count_after_lowering_(-1) {
      38             :   DCHECK_NOT_NULL(graph());
      39             :   DCHECK_NOT_NULL(graph()->end());
      40       10170 :   replacements_ = zone()->NewArray<Replacement>(graph()->NodeCount());
      41             :   memset(static_cast<void*>(replacements_), 0,
      42       10170 :          sizeof(Replacement) * graph()->NodeCount());
      43        5085 : }
      44             : 
      45       15255 : void SimdScalarLowering::LowerGraph() {
      46       10170 :   stack_.push_back({graph()->end(), 0});
      47        5085 :   state_.Set(graph()->end(), State::kOnStack);
      48       15255 :   replacements_[graph()->end()->id()].type = SimdType::kInt32x4;
      49             : 
      50      547965 :   while (!stack_.empty()) {
      51             :     NodeState& top = stack_.back();
      52     1075590 :     if (top.input_index == top.node->InputCount()) {
      53             :       // All inputs of top have already been lowered, now lower top.
      54             :       stack_.pop_back();
      55      181480 :       state_.Set(top.node, State::kVisited);
      56      181480 :       LowerNode(top.node);
      57             :     } else {
      58             :       // Push the next input onto the stack.
      59      532710 :       Node* input = top.node->InputAt(top.input_index++);
      60      356315 :       if (state_.Get(input) == State::kUnvisited) {
      61      176395 :         SetLoweredType(input, top.node);
      62      176395 :         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         110 :           PreparePhiReplacement(input);
      66         220 :           stack_.push_front({input, 0});
      67      176285 :         } else if (input->opcode() == IrOpcode::kEffectPhi ||
      68             :                    input->opcode() == IrOpcode::kLoop) {
      69          40 :           stack_.push_front({input, 0});
      70             :         } else {
      71      352530 :           stack_.push_back({input, 0});
      72             :         }
      73             :         state_.Set(input, State::kOnStack);
      74             :       }
      75             :     }
      76             :   }
      77        5085 : }
      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       33345 : MachineType SimdScalarLowering::MachineTypeFrom(SimdType simdType) {
     210       33345 :   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      608490 : void SimdScalarLowering::SetLoweredType(Node* node, Node* output) {
     224      176395 :   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       57590 :       replacements_[node->id()].type = SimdType::kInt32x4;
     231       28795 :       break;
     232             :     }
     233             :       FOREACH_FLOAT32X4_OPCODE(CASE_STMT) {
     234        1450 :         replacements_[node->id()].type = SimdType::kFloat32x4;
     235         725 :         break;
     236             :       }
     237             :       FOREACH_FLOAT32X4_TO_INT32X4OPCODE(CASE_STMT) {
     238          60 :         replacements_[node->id()].type = SimdType::kInt32x4;
     239          30 :         break;
     240             :       }
     241             :       FOREACH_INT16X8_OPCODE(CASE_STMT) {
     242        8340 :         replacements_[node->id()].type = SimdType::kInt16x8;
     243        4170 :         break;
     244             :       }
     245             :       FOREACH_INT8X16_OPCODE(CASE_STMT) {
     246       29650 :         replacements_[node->id()].type = SimdType::kInt8x16;
     247       14825 :         break;
     248             :       }
     249             :     default: {
     250      127850 :       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      383550 :           replacements_[node->id()].type = replacements_[output->id()].type;
     286             :         }
     287             :       }
     288             :     }
     289             : #undef CASE_STMT
     290             :   }
     291      176395 : }
     292             : 
     293             : static int GetParameterIndexAfterLoweringSimd128(
     294        2995 :     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        2995 :   for (int i = 0; i < old_index; ++i) {
     299        5990 :     if (signature->GetParam(i) == MachineRepresentation::kSimd128) {
     300           0 :       result += 3;
     301             :     }
     302             :   }
     303             :   return result;
     304             : }
     305             : 
     306       18230 : int SimdScalarLowering::GetParameterCountAfterLowering() {
     307       13145 :   if (parameter_count_after_lowering_ == -1) {
     308             :     // GetParameterIndexAfterLoweringSimd128(parameter_count) returns the
     309             :     // parameter count after lowering.
     310             :     parameter_count_after_lowering_ = GetParameterIndexAfterLoweringSimd128(
     311       10170 :         signature(), static_cast<int>(signature()->parameter_count()));
     312             :   }
     313       13145 :   return parameter_count_after_lowering_;
     314             : }
     315             : 
     316             : static int GetReturnCountAfterLoweringSimd128(
     317       32890 :     Signature<MachineRepresentation>* signature) {
     318       16445 :   int result = static_cast<int>(signature->return_count());
     319       16445 :   for (int i = 0; i < static_cast<int>(signature->return_count()); ++i) {
     320       32890 :     if (signature->GetReturn(i) == MachineRepresentation::kSimd128) {
     321           0 :       result += 3;
     322             :     }
     323             :   }
     324             :   return result;
     325             : }
     326             : 
     327      216790 : int SimdScalarLowering::NumLanes(SimdType type) {
     328             :   int num_lanes = 0;
     329      216790 :   if (type == SimdType::kFloat32x4 || type == SimdType::kInt32x4) {
     330             :     num_lanes = kNumLanes32;
     331       91345 :   } else if (type == SimdType::kInt16x8) {
     332             :     num_lanes = kNumLanes16;
     333       86610 :   } else if (type == SimdType::kInt8x16) {
     334             :     num_lanes = kNumLanes8;
     335             :   } else {
     336           0 :     UNREACHABLE();
     337             :   }
     338      216790 :   return num_lanes;
     339             : }
     340             : 
     341             : constexpr int SimdScalarLowering::kLaneOffsets[];
     342             : 
     343       16860 : void SimdScalarLowering::GetIndexNodes(Node* index, Node** new_indices,
     344     1003680 :                                        SimdType type) {
     345       16860 :   int num_lanes = NumLanes(type);
     346       16860 :   int lane_width = kSimd128Size / num_lanes;
     347       16860 :   int laneIndex = kLaneOffsets[0] / lane_width;
     348       16860 :   new_indices[laneIndex] = index;
     349      267780 :   for (int i = 1; i < num_lanes; ++i) {
     350      250920 :     laneIndex = kLaneOffsets[i * lane_width] / lane_width;
     351      250920 :     new_indices[laneIndex] = graph()->NewNode(
     352             :         machine()->Int32Add(), index,
     353             :         graph()->NewNode(
     354      752760 :             common()->Int32Constant(static_cast<int>(i) * lane_width)));
     355             :   }
     356       16860 : }
     357             : 
     358      302095 : void SimdScalarLowering::LowerLoadOp(Node* node, SimdType type) {
     359       27005 :   MachineRepresentation rep = LoadRepresentationOf(node->op()).representation();
     360             :   const Operator* load_op;
     361       27005 :   switch (node->opcode()) {
     362             :     case IrOpcode::kLoad:
     363       53990 :       load_op = machine()->Load(MachineTypeFrom(type));
     364       26995 :       break;
     365             :     case IrOpcode::kUnalignedLoad:
     366           0 :       load_op = machine()->UnalignedLoad(MachineTypeFrom(type));
     367           0 :       break;
     368             :     case IrOpcode::kProtectedLoad:
     369          20 :       load_op = machine()->ProtectedLoad(MachineTypeFrom(type));
     370          10 :       break;
     371             :     default:
     372           0 :       UNREACHABLE();
     373             :   }
     374       27005 :   if (rep == MachineRepresentation::kSimd128) {
     375             :     Node* base = node->InputAt(0);
     376             :     Node* index = node->InputAt(1);
     377       13080 :     int num_lanes = NumLanes(type);
     378       13080 :     Node** indices = zone()->NewArray<Node*>(num_lanes);
     379       13080 :     GetIndexNodes(index, indices, type);
     380             :     Node** rep_nodes = zone()->NewArray<Node*>(num_lanes);
     381       13080 :     rep_nodes[0] = node;
     382       13080 :     rep_nodes[0]->ReplaceInput(1, indices[0]);
     383       13080 :     NodeProperties::ChangeOp(rep_nodes[0], load_op);
     384       13080 :     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      208000 :       for (int i = num_lanes - 1; i > 0; --i) {
     389      194920 :         rep_nodes[i] = graph()->NewNode(load_op, base, indices[i], effect_input,
     390      389840 :                                         control_input);
     391             :         effect_input = rep_nodes[i];
     392             :       }
     393       13080 :       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       13080 :     ReplaceNode(node, rep_nodes, num_lanes);
     400             :   } else {
     401       13925 :     DefaultLowering(node);
     402             :   }
     403       27005 : }
     404             : 
     405       78675 : 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        3780 :   replacements_[node->id()].type = rep_type;
     411             :   const Operator* store_op;
     412             :   MachineRepresentation rep;
     413        3780 :   switch (node->opcode()) {
     414             :     case IrOpcode::kStore: {
     415        3775 :       rep = StoreRepresentationOf(node->op()).representation();
     416             :       WriteBarrierKind write_barrier_kind =
     417        3775 :           StoreRepresentationOf(node->op()).write_barrier_kind();
     418             :       store_op = machine()->Store(StoreRepresentation(
     419        7550 :           MachineTypeFrom(rep_type).representation(), write_barrier_kind));
     420        3775 :       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           5 :       rep = StoreRepresentationOf(node->op()).representation();
     430             :       store_op =
     431          10 :           machine()->ProtectedStore(MachineTypeFrom(rep_type).representation());
     432           5 :       break;
     433             :     }
     434             :     default:
     435           0 :       UNREACHABLE();
     436             :   }
     437        3780 :   if (rep == MachineRepresentation::kSimd128) {
     438             :     Node* base = node->InputAt(0);
     439             :     Node* index = node->InputAt(1);
     440        3780 :     int num_lanes = NumLanes(rep_type);
     441        3780 :     Node** indices = zone()->NewArray<Node*>(num_lanes);
     442        3780 :     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        3780 :     rep_nodes[0] = node;
     447        3780 :     Node** rep_inputs = GetReplacementsWithType(value, rep_type);
     448        3780 :     rep_nodes[0]->ReplaceInput(2, rep_inputs[0]);
     449        3780 :     rep_nodes[0]->ReplaceInput(1, indices[0]);
     450        3780 :     NodeProperties::ChangeOp(node, store_op);
     451        3780 :     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       59780 :       for (int i = num_lanes - 1; i > 0; --i) {
     456       56000 :         rep_nodes[i] =
     457      112000 :             graph()->NewNode(store_op, base, indices[i], rep_inputs[i],
     458      168000 :                              effect_input, control_input);
     459             :         effect_input = rep_nodes[i];
     460             :       }
     461        3780 :       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        3780 :     ReplaceNode(node, rep_nodes, num_lanes);
     469             :   } else {
     470           0 :     DefaultLowering(node);
     471             :   }
     472        3780 : }
     473             : 
     474          85 : void SimdScalarLowering::LowerBinaryOp(Node* node, SimdType input_rep_type,
     475             :                                        const Operator* op,
     476         425 :                                        bool not_horizontal) {
     477             :   DCHECK_EQ(2, node->InputCount());
     478          85 :   Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
     479          85 :   Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type);
     480          85 :   int num_lanes = NumLanes(input_rep_type);
     481          85 :   Node** rep_node = zone()->NewArray<Node*>(num_lanes);
     482          85 :   if (not_horizontal) {
     483         300 :     for (int i = 0; i < num_lanes; ++i) {
     484         600 :       rep_node[i] = graph()->NewNode(op, rep_left[i], rep_right[i]);
     485             :     }
     486             :   } else {
     487          20 :     for (int i = 0; i < num_lanes / 2; ++i) {
     488          40 :       rep_node[i] = graph()->NewNode(op, rep_left[i * 2], rep_left[i * 2 + 1]);
     489          20 :       rep_node[i + num_lanes / 2] =
     490          40 :           graph()->NewNode(op, rep_right[i * 2], rep_right[i * 2 + 1]);
     491             :     }
     492             :   }
     493          85 :   ReplaceNode(node, rep_node, num_lanes);
     494          85 : }
     495             : 
     496         220 : void SimdScalarLowering::LowerCompareOp(Node* node, SimdType input_rep_type,
     497             :                                         const Operator* op,
     498        7900 :                                         bool invert_inputs) {
     499             :   DCHECK_EQ(2, node->InputCount());
     500         220 :   Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
     501         220 :   Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type);
     502         220 :   int num_lanes = NumLanes(input_rep_type);
     503         220 :   Node** rep_node = zone()->NewArray<Node*>(num_lanes);
     504        2140 :   for (int i = 0; i < num_lanes; ++i) {
     505             :     Node* cmp_result = nullptr;
     506        1920 :     if (invert_inputs) {
     507        1120 :       cmp_result = graph()->NewNode(op, rep_right[i], rep_left[i]);
     508             :     } else {
     509         800 :       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        5760 :                                    mcgraph_->Int32Constant(0)));
     514             :     MachineRepresentation rep =
     515             :         (input_rep_type == SimdType::kFloat32x4)
     516             :             ? MachineRepresentation::kWord32
     517        1920 :             : MachineTypeFrom(input_rep_type).representation();
     518        1920 :     rep_node[i] =
     519        1920 :         d_cmp.Phi(rep, mcgraph_->Int32Constant(0), mcgraph_->Int32Constant(-1));
     520             :   }
     521         220 :   ReplaceNode(node, rep_node, num_lanes);
     522         220 : }
     523             : 
     524       10200 : Node* SimdScalarLowering::FixUpperBits(Node* input, int32_t shift) {
     525             :   return graph()->NewNode(machine()->Word32Sar(),
     526             :                           graph()->NewNode(machine()->Word32Shl(), input,
     527             :                                            mcgraph_->Int32Constant(shift)),
     528        8160 :                           mcgraph_->Int32Constant(shift));
     529             : }
     530             : 
     531          35 : void SimdScalarLowering::LowerBinaryOpForSmallInt(Node* node,
     532             :                                                   SimdType input_rep_type,
     533             :                                                   const Operator* op,
     534         435 :                                                   bool not_horizontal) {
     535             :   DCHECK_EQ(2, node->InputCount());
     536             :   DCHECK(input_rep_type == SimdType::kInt16x8 ||
     537             :          input_rep_type == SimdType::kInt8x16);
     538          35 :   Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
     539          35 :   Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type);
     540          35 :   int num_lanes = NumLanes(input_rep_type);
     541          35 :   Node** rep_node = zone()->NewArray<Node*>(num_lanes);
     542             :   int32_t shift_val =
     543          35 :       (input_rep_type == SimdType::kInt16x8) ? kShift16 : kShift8;
     544          35 :   if (not_horizontal) {
     545         360 :     for (int i = 0; i < num_lanes; ++i) {
     546         360 :       rep_node[i] = FixUpperBits(
     547         720 :           graph()->NewNode(op, rep_left[i], rep_right[i]), shift_val);
     548             :     }
     549             :   } else {
     550          20 :     for (int i = 0; i < num_lanes / 2; ++i) {
     551          20 :       rep_node[i] = FixUpperBits(
     552          40 :           graph()->NewNode(op, rep_left[i * 2], rep_left[i * 2 + 1]),
     553          60 :           shift_val);
     554          20 :       rep_node[i + num_lanes / 2] = FixUpperBits(
     555          40 :           graph()->NewNode(op, rep_right[i * 2], rep_right[i * 2 + 1]),
     556          60 :           shift_val);
     557             :     }
     558             :   }
     559          35 :   ReplaceNode(node, rep_node, num_lanes);
     560          35 : }
     561             : 
     562        5280 : Node* SimdScalarLowering::Mask(Node* input, int32_t mask) {
     563             :   return graph()->NewNode(machine()->Word32And(), input,
     564        5280 :                           mcgraph_->Int32Constant(mask));
     565             : }
     566             : 
     567          40 : void SimdScalarLowering::LowerSaturateBinaryOp(Node* node,
     568             :                                                SimdType input_rep_type,
     569             :                                                const Operator* op,
     570        3400 :                                                bool is_signed) {
     571             :   DCHECK_EQ(2, node->InputCount());
     572             :   DCHECK(input_rep_type == SimdType::kInt16x8 ||
     573             :          input_rep_type == SimdType::kInt8x16);
     574          40 :   Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
     575          40 :   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          40 :   if (input_rep_type == SimdType::kInt16x8) {
     582          20 :     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          20 :     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          40 :   int num_lanes = NumLanes(input_rep_type);
     605          40 :   Node** rep_node = zone()->NewArray<Node*>(num_lanes);
     606         520 :   for (int i = 0; i < num_lanes; ++i) {
     607             :     Node* op_result = nullptr;
     608         480 :     Node* left = is_signed ? rep_left[i] : Mask(rep_left[i], mask);
     609         480 :     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        1440 :                                    mcgraph_->Int32Constant(min)));
     614         480 :     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        1440 :                                    mcgraph_->Int32Constant(max), rep_node[i]));
     618         480 :     rep_node[i] = d_max.Phi(phi_rep, mcgraph_->Int32Constant(max), rep_node[i]);
     619             :     rep_node[i] =
     620         480 :         is_signed ? rep_node[i] : FixUpperBits(rep_node[i], shift_val);
     621             :   }
     622          40 :   ReplaceNode(node, rep_node, num_lanes);
     623          40 : }
     624             : 
     625          20 : void SimdScalarLowering::LowerUnaryOp(Node* node, SimdType input_rep_type,
     626         100 :                                       const Operator* op) {
     627             :   DCHECK_EQ(1, node->InputCount());
     628          20 :   Node** rep = GetReplacementsWithType(node->InputAt(0), input_rep_type);
     629          20 :   int num_lanes = NumLanes(input_rep_type);
     630          20 :   Node** rep_node = zone()->NewArray<Node*>(num_lanes);
     631         100 :   for (int i = 0; i < num_lanes; ++i) {
     632         160 :     rep_node[i] = graph()->NewNode(op, rep[i]);
     633             :   }
     634          20 :   ReplaceNode(node, rep_node, num_lanes);
     635          20 : }
     636             : 
     637          60 : void SimdScalarLowering::LowerIntMinMax(Node* node, const Operator* op,
     638        1180 :                                         bool is_max, SimdType type) {
     639             :   DCHECK_EQ(2, node->InputCount());
     640          60 :   Node** rep_left = GetReplacementsWithType(node->InputAt(0), type);
     641          60 :   Node** rep_right = GetReplacementsWithType(node->InputAt(1), type);
     642          60 :   int num_lanes = NumLanes(type);
     643          60 :   Node** rep_node = zone()->NewArray<Node*>(num_lanes);
     644             :   MachineRepresentation rep = MachineRepresentation::kNone;
     645          60 :   if (type == SimdType::kInt32x4) {
     646             :     rep = MachineRepresentation::kWord32;
     647          40 :   } else if (type == SimdType::kInt16x8) {
     648             :     rep = MachineRepresentation::kWord16;
     649          20 :   } else if (type == SimdType::kInt8x16) {
     650             :     rep = MachineRepresentation::kWord8;
     651             :   } else {
     652           0 :     UNREACHABLE();
     653             :   }
     654         620 :   for (int i = 0; i < num_lanes; ++i) {
     655             :     Diamond d(graph(), common(),
     656        1120 :               graph()->NewNode(op, rep_left[i], rep_right[i]));
     657         560 :     if (is_max) {
     658         280 :       rep_node[i] = d.Phi(rep, rep_right[i], rep_left[i]);
     659             :     } else {
     660         280 :       rep_node[i] = d.Phi(rep, rep_left[i], rep_right[i]);
     661             :     }
     662             :   }
     663          60 :   ReplaceNode(node, rep_node, num_lanes);
     664          60 : }
     665             : 
     666         120 : Node* SimdScalarLowering::BuildF64Trunc(Node* input) {
     667          40 :   if (machine()->Float64RoundTruncate().IsSupported()) {
     668          80 :     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             :     const Operator* store_op = machine()->Store(
     674           0 :         StoreRepresentation(MachineRepresentation::kFloat64, kNoWriteBarrier));
     675             :     Node* effect =
     676             :         graph()->NewNode(store_op, stack_slot, mcgraph_->Int32Constant(0),
     677           0 :                          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             :     return graph()->NewNode(machine()->Load(LoadRepresentation::Float64()),
     690             :                             stack_slot, mcgraph_->Int32Constant(0), call,
     691           0 :                             graph()->start());
     692             :   }
     693             : }
     694             : 
     695         590 : void SimdScalarLowering::LowerConvertFromFloat(Node* node, bool is_signed) {
     696             :   DCHECK_EQ(1, node->InputCount());
     697          10 :   Node** rep = GetReplacementsWithType(node->InputAt(0), SimdType::kFloat32x4);
     698             :   Node* rep_node[kNumLanes32];
     699          10 :   Node* double_zero = graph()->NewNode(common()->Float64Constant(0.0));
     700             :   Node* min = graph()->NewNode(
     701          20 :       common()->Float64Constant(static_cast<double>(is_signed ? kMinInt : 0)));
     702             :   Node* max = graph()->NewNode(common()->Float64Constant(
     703          20 :       static_cast<double>(is_signed ? kMaxInt : 0xFFFFFFFFu)));
     704          50 :   for (int i = 0; i < kNumLanes32; ++i) {
     705             :     Node* double_rep =
     706          80 :         graph()->NewNode(machine()->ChangeFloat32ToFloat64(), rep[i]);
     707             :     Diamond nan_d(graph(), common(), graph()->NewNode(machine()->Float64Equal(),
     708          80 :                                                       double_rep, double_rep));
     709             :     Node* temp =
     710          40 :         nan_d.Phi(MachineRepresentation::kFloat64, double_rep, double_zero);
     711             :     Diamond min_d(graph(), common(),
     712          80 :                   graph()->NewNode(machine()->Float64LessThan(), temp, min));
     713          40 :     temp = min_d.Phi(MachineRepresentation::kFloat64, min, temp);
     714             :     Diamond max_d(graph(), common(),
     715          80 :                   graph()->NewNode(machine()->Float64LessThan(), max, temp));
     716          40 :     temp = max_d.Phi(MachineRepresentation::kFloat64, max, temp);
     717          40 :     Node* trunc = BuildF64Trunc(temp);
     718          40 :     if (is_signed) {
     719          40 :       rep_node[i] = graph()->NewNode(machine()->ChangeFloat64ToInt32(), trunc);
     720             :     } else {
     721             :       rep_node[i] =
     722          40 :           graph()->NewNode(machine()->TruncateFloat64ToUint32(), trunc);
     723             :     }
     724             :   }
     725          10 :   ReplaceNode(node, rep_node, kNumLanes32);
     726          10 : }
     727             : 
     728          40 : void SimdScalarLowering::LowerConvertFromInt(Node* node,
     729             :                                              SimdType input_rep_type,
     730             :                                              SimdType output_rep_type,
     731          40 :                                              bool is_signed, int start_index) {
     732             :   DCHECK_EQ(1, node->InputCount());
     733          40 :   Node** rep = GetReplacementsWithType(node->InputAt(0), input_rep_type);
     734             : 
     735             :   int32_t mask = 0;
     736          40 :   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          40 :   int num_lanes = NumLanes(output_rep_type);
     746          40 :   Node** rep_node = zone()->NewArray<Node*>(num_lanes);
     747         280 :   for (int i = 0; i < num_lanes; ++i) {
     748         240 :     rep_node[i] =
     749         240 :         is_signed ? rep[i + start_index] : Mask(rep[i + start_index], mask);
     750             :   }
     751             : 
     752          40 :   ReplaceNode(node, rep_node, num_lanes);
     753          40 : }
     754             : 
     755          20 : void SimdScalarLowering::LowerPack(Node* node, SimdType input_rep_type,
     756         760 :                                    SimdType output_rep_type, bool is_signed) {
     757             :   DCHECK_EQ(2, node->InputCount());
     758          20 :   Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
     759          20 :   Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type);
     760             :   const Operator* less_op =
     761          40 :       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          20 :   if (output_rep_type == SimdType::kInt16x8) {
     767             :     DCHECK(input_rep_type == SimdType::kInt32x4);
     768          10 :     if (is_signed) {
     769           5 :       min = mcgraph_->Int32Constant(std::numeric_limits<int16_t>::min());
     770           5 :       max = mcgraph_->Int32Constant(std::numeric_limits<int16_t>::max());
     771             :     } else {
     772           5 :       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          10 :     if (is_signed) {
     780           5 :       min = mcgraph_->Int32Constant(std::numeric_limits<int8_t>::min());
     781           5 :       max = mcgraph_->Int32Constant(std::numeric_limits<int8_t>::max());
     782             :     } else {
     783           5 :       max = mcgraph_->Uint32Constant(std::numeric_limits<uint8_t>::max());
     784             :       shift_val = kShift8;
     785             :     }
     786             :     phi_rep = MachineRepresentation::kWord8;
     787             :   }
     788          20 :   int num_lanes = NumLanes(output_rep_type);
     789          20 :   Node** rep_node = zone()->NewArray<Node*>(num_lanes);
     790         260 :   for (int i = 0; i < num_lanes; ++i) {
     791             :     Node* input = nullptr;
     792         240 :     if (i < num_lanes / 2)
     793         120 :       input = rep_left[i];
     794             :     else
     795         120 :       input = rep_right[i - num_lanes / 2];
     796         240 :     if (is_signed) {
     797         120 :       Diamond d_min(graph(), common(), graph()->NewNode(less_op, input, min));
     798         120 :       input = d_min.Phi(phi_rep, min, input);
     799             :     }
     800         240 :     Diamond d_max(graph(), common(), graph()->NewNode(less_op, max, input));
     801         240 :     rep_node[i] = d_max.Phi(phi_rep, max, input);
     802             :     rep_node[i] =
     803         240 :         is_signed ? rep_node[i] : FixUpperBits(rep_node[i], shift_val);
     804             :   }
     805          20 :   ReplaceNode(node, rep_node, num_lanes);
     806          20 : }
     807             : 
     808       19200 : void SimdScalarLowering::LowerShiftOp(Node* node, SimdType type) {
     809             :   DCHECK_EQ(1, node->InputCount());
     810         795 :   int32_t shift_amount = OpParameter<int32_t>(node->op());
     811         795 :   Node* shift_node = graph()->NewNode(common()->Int32Constant(shift_amount));
     812         795 :   Node** rep = GetReplacementsWithType(node->InputAt(0), type);
     813         795 :   int num_lanes = NumLanes(type);
     814         795 :   Node** rep_node = zone()->NewArray<Node*>(num_lanes);
     815        6135 :   for (int i = 0; i < num_lanes; ++i) {
     816        5340 :     rep_node[i] = rep[i];
     817        5340 :     switch (node->opcode()) {
     818             :       case IrOpcode::kI8x16ShrU:
     819         560 :         rep_node[i] = Mask(rep_node[i], kMask8);
     820             :         rep_node[i] =
     821        1120 :             graph()->NewNode(machine()->Word32Shr(), rep_node[i], shift_node);
     822         560 :         break;
     823             :       case IrOpcode::kI16x8ShrU:
     824         600 :         rep_node[i] = Mask(rep_node[i], kMask16);
     825             :         V8_FALLTHROUGH;
     826             :       case IrOpcode::kI32x4ShrU:
     827             :         rep_node[i] =
     828        3660 :             graph()->NewNode(machine()->Word32Shr(), rep_node[i], shift_node);
     829        1220 :         break;
     830             :       case IrOpcode::kI32x4Shl:
     831             :         rep_node[i] =
     832        1240 :             graph()->NewNode(machine()->Word32Shl(), rep_node[i], shift_node);
     833         620 :         break;
     834             :       case IrOpcode::kI16x8Shl:
     835             :         rep_node[i] =
     836        1200 :             graph()->NewNode(machine()->Word32Shl(), rep_node[i], shift_node);
     837         600 :         rep_node[i] = FixUpperBits(rep_node[i], kShift16);
     838         600 :         break;
     839             :       case IrOpcode::kI8x16Shl:
     840             :         rep_node[i] =
     841        1120 :             graph()->NewNode(machine()->Word32Shl(), rep_node[i], shift_node);
     842         560 :         rep_node[i] = FixUpperBits(rep_node[i], kShift8);
     843         560 :         break;
     844             :       case IrOpcode::kI32x4ShrS:
     845             :       case IrOpcode::kI16x8ShrS:
     846             :       case IrOpcode::kI8x16ShrS:
     847             :         rep_node[i] =
     848        3560 :             graph()->NewNode(machine()->Word32Sar(), rep_node[i], shift_node);
     849        1780 :         break;
     850             :       default:
     851           0 :         UNREACHABLE();
     852             :     }
     853             :   }
     854         795 :   ReplaceNode(node, rep_node, num_lanes);
     855         795 : }
     856             : 
     857          80 : void SimdScalarLowering::LowerNotEqual(Node* node, SimdType input_rep_type,
     858        1520 :                                        const Operator* op) {
     859             :   DCHECK_EQ(2, node->InputCount());
     860          80 :   Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
     861          80 :   Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type);
     862          80 :   int num_lanes = NumLanes(input_rep_type);
     863          80 :   Node** rep_node = zone()->NewArray<Node*>(num_lanes);
     864         800 :   for (int i = 0; i < num_lanes; ++i) {
     865             :     Diamond d(graph(), common(),
     866        1440 :               graph()->NewNode(op, rep_left[i], rep_right[i]));
     867             :     MachineRepresentation rep =
     868             :         (input_rep_type == SimdType::kFloat32x4)
     869             :             ? MachineRepresentation::kWord32
     870         720 :             : MachineTypeFrom(input_rep_type).representation();
     871         720 :     rep_node[i] =
     872         720 :         d.Phi(rep, mcgraph_->Int32Constant(0), mcgraph_->Int32Constant(-1));
     873             :   }
     874          80 :   ReplaceNode(node, rep_node, num_lanes);
     875          80 : }
     876             : 
     877      421110 : void SimdScalarLowering::LowerNode(Node* node) {
     878             :   SimdType rep_type = ReplacementType(node);
     879      181480 :   int num_lanes = NumLanes(rep_type);
     880      181480 :   switch (node->opcode()) {
     881             :     case IrOpcode::kStart: {
     882        5085 :       int parameter_count = GetParameterCountAfterLowering();
     883             :       // Only exchange the node if the parameter count actually changed.
     884        5085 :       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       16120 :       if (GetParameterCountAfterLowering() !=
     899        8060 :           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             :               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       27005 :       LowerLoadOp(node, rep_type);
     927       27005 :       break;
     928             :     }
     929             :     case IrOpcode::kStore:
     930             :     case IrOpcode::kUnalignedStore:
     931             :     case IrOpcode::kProtectedStore: {
     932        3780 :       LowerStoreOp(node);
     933        3780 :       break;
     934             :     }
     935             :     case IrOpcode::kReturn: {
     936       16445 :       DefaultLowering(node);
     937             :       int new_return_count = GetReturnCountAfterLoweringSimd128(signature());
     938       16445 :       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           0 :       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         110 :       MachineRepresentation rep = PhiRepresentationOf(node->op());
     969         110 :       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          90 :         for (int i = 0; i < node->op()->ValueInputCount(); ++i) {
     974             :           Node** rep_input =
     975          20 :               GetReplacementsWithType(node->InputAt(i), rep_type);
     976         100 :           for (int j = 0; j < num_lanes; j++) {
     977          80 :             rep_node[j]->ReplaceInput(i, rep_input[j]);
     978             :           }
     979             :         }
     980             :       } else {
     981         100 :         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          15 :       I32X4_BINOP_CASE(kI32x4Add, Int32Add)
     991           5 :       I32X4_BINOP_CASE(kI32x4Sub, Int32Sub)
     992           5 :       I32X4_BINOP_CASE(kI32x4Mul, Int32Mul)
     993           5 :       I32X4_BINOP_CASE(kS128And, Word32And)
     994           5 :       I32X4_BINOP_CASE(kS128Or, Word32Or)
     995           5 :       I32X4_BINOP_CASE(kS128Xor, Word32Xor)
     996             : #undef I32X4_BINOP_CASE
     997             :     case IrOpcode::kI32x4AddHoriz: {
     998           5 :       LowerBinaryOp(node, rep_type, machine()->Int32Add(), false);
     999           5 :       break;
    1000             :     }
    1001             :     case IrOpcode::kI16x8AddHoriz: {
    1002           5 :       LowerBinaryOpForSmallInt(node, rep_type, machine()->Int32Add(), false);
    1003           5 :       break;
    1004             :     }
    1005             :     case IrOpcode::kI16x8Add:
    1006             :     case IrOpcode::kI8x16Add: {
    1007          10 :       LowerBinaryOpForSmallInt(node, rep_type, machine()->Int32Add());
    1008          10 :       break;
    1009             :     }
    1010             :     case IrOpcode::kI16x8Sub:
    1011             :     case IrOpcode::kI8x16Sub: {
    1012          10 :       LowerBinaryOpForSmallInt(node, rep_type, machine()->Int32Sub());
    1013          10 :       break;
    1014             :     }
    1015             :     case IrOpcode::kI16x8Mul:
    1016             :     case IrOpcode::kI8x16Mul: {
    1017          10 :       LowerBinaryOpForSmallInt(node, rep_type, machine()->Int32Mul());
    1018          10 :       break;
    1019             :     }
    1020             :     case IrOpcode::kI16x8AddSaturateS:
    1021             :     case IrOpcode::kI8x16AddSaturateS: {
    1022          10 :       LowerSaturateBinaryOp(node, rep_type, machine()->Int32Add(), true);
    1023          10 :       break;
    1024             :     }
    1025             :     case IrOpcode::kI16x8SubSaturateS:
    1026             :     case IrOpcode::kI8x16SubSaturateS: {
    1027          10 :       LowerSaturateBinaryOp(node, rep_type, machine()->Int32Sub(), true);
    1028          10 :       break;
    1029             :     }
    1030             :     case IrOpcode::kI16x8AddSaturateU:
    1031             :     case IrOpcode::kI8x16AddSaturateU: {
    1032          10 :       LowerSaturateBinaryOp(node, rep_type, machine()->Int32Add(), false);
    1033          10 :       break;
    1034             :     }
    1035             :     case IrOpcode::kI16x8SubSaturateU:
    1036             :     case IrOpcode::kI8x16SubSaturateU: {
    1037          10 :       LowerSaturateBinaryOp(node, rep_type, machine()->Int32Sub(), false);
    1038          10 :       break;
    1039             :     }
    1040             :     case IrOpcode::kI32x4MaxS:
    1041             :     case IrOpcode::kI16x8MaxS:
    1042             :     case IrOpcode::kI8x16MaxS: {
    1043          15 :       LowerIntMinMax(node, machine()->Int32LessThan(), true, rep_type);
    1044          15 :       break;
    1045             :     }
    1046             :     case IrOpcode::kI32x4MinS:
    1047             :     case IrOpcode::kI16x8MinS:
    1048             :     case IrOpcode::kI8x16MinS: {
    1049          15 :       LowerIntMinMax(node, machine()->Int32LessThan(), false, rep_type);
    1050          15 :       break;
    1051             :     }
    1052             :     case IrOpcode::kI32x4MaxU:
    1053             :     case IrOpcode::kI16x8MaxU:
    1054             :     case IrOpcode::kI8x16MaxU: {
    1055          15 :       LowerIntMinMax(node, machine()->Uint32LessThan(), true, rep_type);
    1056          15 :       break;
    1057             :     }
    1058             :     case IrOpcode::kI32x4MinU:
    1059             :     case IrOpcode::kI16x8MinU:
    1060             :     case IrOpcode::kI8x16MinU: {
    1061          15 :       LowerIntMinMax(node, machine()->Uint32LessThan(), false, rep_type);
    1062          15 :       break;
    1063             :     }
    1064             :     case IrOpcode::kI32x4Neg:
    1065             :     case IrOpcode::kI16x8Neg:
    1066             :     case IrOpcode::kI8x16Neg: {
    1067             :       DCHECK_EQ(1, node->InputCount());
    1068          15 :       Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type);
    1069          15 :       int num_lanes = NumLanes(rep_type);
    1070          15 :       Node** rep_node = zone()->NewArray<Node*>(num_lanes);
    1071          15 :       Node* zero = graph()->NewNode(common()->Int32Constant(0));
    1072         155 :       for (int i = 0; i < num_lanes; ++i) {
    1073         420 :         rep_node[i] = graph()->NewNode(machine()->Int32Sub(), zero, rep[i]);
    1074         140 :         if (node->opcode() == IrOpcode::kI16x8Neg) {
    1075          40 :           rep_node[i] = FixUpperBits(rep_node[i], kShift16);
    1076         100 :         } else if (node->opcode() == IrOpcode::kI8x16Neg) {
    1077          80 :           rep_node[i] = FixUpperBits(rep_node[i], kShift8);
    1078             :         }
    1079             :       }
    1080          15 :       ReplaceNode(node, rep_node, num_lanes);
    1081          15 :       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           5 :       Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type);
    1095             :       Node* rep_node[kNumLanes32];
    1096           5 :       Node* mask = graph()->NewNode(common()->Int32Constant(0xFFFFFFFF));
    1097          25 :       for (int i = 0; i < kNumLanes32; ++i) {
    1098          60 :         rep_node[i] = graph()->NewNode(machine()->Word32Xor(), rep[i], mask);
    1099             :       }
    1100           5 :       ReplaceNode(node, rep_node, kNumLanes32);
    1101             :       break;
    1102             :     }
    1103             :     case IrOpcode::kI32x4SConvertF32x4: {
    1104           5 :       LowerConvertFromFloat(node, true);
    1105           5 :       break;
    1106             :     }
    1107             :     case IrOpcode::kI32x4UConvertF32x4: {
    1108           5 :       LowerConvertFromFloat(node, false);
    1109           5 :       break;
    1110             :     }
    1111             :     case IrOpcode::kI32x4SConvertI16x8Low: {
    1112             :       LowerConvertFromInt(node, SimdType::kInt16x8, SimdType::kInt32x4, true,
    1113           5 :                           0);
    1114           5 :       break;
    1115             :     }
    1116             :     case IrOpcode::kI32x4SConvertI16x8High: {
    1117             :       LowerConvertFromInt(node, SimdType::kInt16x8, SimdType::kInt32x4, true,
    1118           5 :                           4);
    1119           5 :       break;
    1120             :     }
    1121             :     case IrOpcode::kI32x4UConvertI16x8Low: {
    1122             :       LowerConvertFromInt(node, SimdType::kInt16x8, SimdType::kInt32x4, false,
    1123           5 :                           0);
    1124           5 :       break;
    1125             :     }
    1126             :     case IrOpcode::kI32x4UConvertI16x8High: {
    1127             :       LowerConvertFromInt(node, SimdType::kInt16x8, SimdType::kInt32x4, false,
    1128           5 :                           4);
    1129           5 :       break;
    1130             :     }
    1131             :     case IrOpcode::kI16x8SConvertI8x16Low: {
    1132             :       LowerConvertFromInt(node, SimdType::kInt8x16, SimdType::kInt16x8, true,
    1133           5 :                           0);
    1134           5 :       break;
    1135             :     }
    1136             :     case IrOpcode::kI16x8SConvertI8x16High: {
    1137             :       LowerConvertFromInt(node, SimdType::kInt8x16, SimdType::kInt16x8, true,
    1138           5 :                           8);
    1139           5 :       break;
    1140             :     }
    1141             :     case IrOpcode::kI16x8UConvertI8x16Low: {
    1142             :       LowerConvertFromInt(node, SimdType::kInt8x16, SimdType::kInt16x8, false,
    1143           5 :                           0);
    1144           5 :       break;
    1145             :     }
    1146             :     case IrOpcode::kI16x8UConvertI8x16High: {
    1147             :       LowerConvertFromInt(node, SimdType::kInt8x16, SimdType::kInt16x8, false,
    1148           5 :                           8);
    1149           5 :       break;
    1150             :     }
    1151             :     case IrOpcode::kI16x8SConvertI32x4: {
    1152           5 :       LowerPack(node, SimdType::kInt32x4, SimdType::kInt16x8, true);
    1153           5 :       break;
    1154             :     }
    1155             :     case IrOpcode::kI16x8UConvertI32x4: {
    1156           5 :       LowerPack(node, SimdType::kInt32x4, SimdType::kInt16x8, false);
    1157           5 :       break;
    1158             :     }
    1159             :     case IrOpcode::kI8x16SConvertI16x8: {
    1160           5 :       LowerPack(node, SimdType::kInt16x8, SimdType::kInt8x16, true);
    1161           5 :       break;
    1162             :     }
    1163             :     case IrOpcode::kI8x16UConvertI16x8: {
    1164           5 :       LowerPack(node, SimdType::kInt16x8, SimdType::kInt8x16, false);
    1165           5 :       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         795 :       LowerShiftOp(node, rep_type);
    1177         795 :       break;
    1178             :     }
    1179             :     case IrOpcode::kF32x4AddHoriz: {
    1180           5 :       LowerBinaryOp(node, rep_type, machine()->Float32Add(), false);
    1181           5 :       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          15 :       F32X4_BINOP_CASE(Add)
    1189           5 :       F32X4_BINOP_CASE(Sub)
    1190           5 :       F32X4_BINOP_CASE(Mul)
    1191           5 :       F32X4_BINOP_CASE(Min)
    1192           5 :       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           5 :       F32X4_UNOP_CASE(Abs)
    1200           5 :       F32X4_UNOP_CASE(Neg)
    1201             : #undef F32x4_UNOP_CASE
    1202             :     case IrOpcode::kF32x4RecipApprox:
    1203             :     case IrOpcode::kF32x4RecipSqrtApprox: {
    1204             :       DCHECK_EQ(1, node->InputCount());
    1205          10 :       Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type);
    1206          10 :       Node** rep_node = zone()->NewArray<Node*>(num_lanes);
    1207          10 :       Node* float_one = graph()->NewNode(common()->Float32Constant(1.0));
    1208          50 :       for (int i = 0; i < num_lanes; ++i) {
    1209          40 :         Node* tmp = rep[i];
    1210          40 :         if (node->opcode() == IrOpcode::kF32x4RecipSqrtApprox) {
    1211          20 :           tmp = graph()->NewNode(machine()->Float32Sqrt(), rep[i]);
    1212             :         }
    1213         120 :         rep_node[i] = graph()->NewNode(machine()->Float32Div(), float_one, tmp);
    1214             :       }
    1215          10 :       ReplaceNode(node, rep_node, num_lanes);
    1216          10 :       break;
    1217             :     }
    1218             :     case IrOpcode::kF32x4SConvertI32x4: {
    1219           5 :       LowerUnaryOp(node, SimdType::kInt32x4, machine()->RoundInt32ToFloat32());
    1220           5 :       break;
    1221             :     }
    1222             :     case IrOpcode::kF32x4UConvertI32x4: {
    1223           5 :       LowerUnaryOp(node, SimdType::kInt32x4, machine()->RoundUint32ToFloat32());
    1224           5 :       break;
    1225             :     }
    1226             :     case IrOpcode::kI32x4Splat:
    1227             :     case IrOpcode::kF32x4Splat:
    1228             :     case IrOpcode::kI16x8Splat:
    1229             :     case IrOpcode::kI8x16Splat: {
    1230        1735 :       Node** rep_node = zone()->NewArray<Node*>(num_lanes);
    1231       14635 :       for (int i = 0; i < num_lanes; ++i) {
    1232       12900 :         if (HasReplacement(0, node->InputAt(0))) {
    1233          40 :           rep_node[i] = GetReplacements(node->InputAt(0))[0];
    1234             :         } else {
    1235       25760 :           rep_node[i] = node->InputAt(0);
    1236             :         }
    1237             :       }
    1238        1735 :       ReplaceNode(node, rep_node, num_lanes);
    1239        1735 :       break;
    1240             :     }
    1241             :     case IrOpcode::kI32x4ExtractLane:
    1242             :     case IrOpcode::kF32x4ExtractLane:
    1243             :     case IrOpcode::kI16x8ExtractLane:
    1244             :     case IrOpcode::kI8x16ExtractLane: {
    1245       11350 :       int32_t lane = OpParameter<int32_t>(node->op());
    1246       11350 :       Node** rep_node = zone()->NewArray<Node*>(num_lanes);
    1247       11350 :       rep_node[0] = GetReplacementsWithType(node->InputAt(0), rep_type)[lane];
    1248      117560 :       for (int i = 1; i < num_lanes; ++i) {
    1249      106210 :         rep_node[i] = nullptr;
    1250             :       }
    1251       11350 :       ReplaceNode(node, rep_node, num_lanes);
    1252       11350 :       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         230 :       int32_t lane = OpParameter<int32_t>(node->op());
    1261         230 :       Node** old_rep_node = GetReplacementsWithType(node->InputAt(0), rep_type);
    1262         230 :       Node** rep_node = zone()->NewArray<Node*>(num_lanes);
    1263        2430 :       for (int i = 0; i < num_lanes; ++i) {
    1264        2200 :         rep_node[i] = old_rep_node[i];
    1265             :       }
    1266         230 :       if (HasReplacement(0, repNode)) {
    1267           0 :         rep_node[lane] = GetReplacements(repNode)[0];
    1268             :       } else {
    1269         230 :         rep_node[lane] = repNode;
    1270             :       }
    1271         230 :       ReplaceNode(node, rep_node, num_lanes);
    1272         230 :       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           5 :       COMPARISON_CASE(Float32x4, kF32x4Eq, Float32Equal, false)
    1280          10 :       COMPARISON_CASE(Float32x4, kF32x4Lt, Float32LessThan, false)
    1281          10 :       COMPARISON_CASE(Float32x4, kF32x4Le, Float32LessThanOrEqual, false)
    1282           0 :       COMPARISON_CASE(Float32x4, kF32x4Gt, Float32LessThan, true)
    1283           0 :       COMPARISON_CASE(Float32x4, kF32x4Ge, Float32LessThanOrEqual, true)
    1284          25 :       COMPARISON_CASE(Int32x4, kI32x4Eq, Word32Equal, false)
    1285           0 :       COMPARISON_CASE(Int32x4, kI32x4LtS, Int32LessThan, false)
    1286           0 :       COMPARISON_CASE(Int32x4, kI32x4LeS, Int32LessThanOrEqual, false)
    1287          10 :       COMPARISON_CASE(Int32x4, kI32x4GtS, Int32LessThan, true)
    1288          10 :       COMPARISON_CASE(Int32x4, kI32x4GeS, Int32LessThanOrEqual, true)
    1289           0 :       COMPARISON_CASE(Int32x4, kI32x4LtU, Uint32LessThan, false)
    1290           0 :       COMPARISON_CASE(Int32x4, kI32x4LeU, Uint32LessThanOrEqual, false)
    1291          10 :       COMPARISON_CASE(Int32x4, kI32x4GtU, Uint32LessThan, true)
    1292          10 :       COMPARISON_CASE(Int32x4, kI32x4GeU, Uint32LessThanOrEqual, true)
    1293          25 :       COMPARISON_CASE(Int16x8, kI16x8Eq, Word32Equal, false)
    1294           0 :       COMPARISON_CASE(Int16x8, kI16x8LtS, Int32LessThan, false)
    1295           0 :       COMPARISON_CASE(Int16x8, kI16x8LeS, Int32LessThanOrEqual, false)
    1296          10 :       COMPARISON_CASE(Int16x8, kI16x8GtS, Int32LessThan, true)
    1297          10 :       COMPARISON_CASE(Int16x8, kI16x8GeS, Int32LessThanOrEqual, true)
    1298           0 :       COMPARISON_CASE(Int16x8, kI16x8LtU, Uint32LessThan, false)
    1299           0 :       COMPARISON_CASE(Int16x8, kI16x8LeU, Uint32LessThanOrEqual, false)
    1300          10 :       COMPARISON_CASE(Int16x8, kI16x8GtU, Uint32LessThan, true)
    1301          10 :       COMPARISON_CASE(Int16x8, kI16x8GeU, Uint32LessThanOrEqual, true)
    1302          25 :       COMPARISON_CASE(Int8x16, kI8x16Eq, Word32Equal, false)
    1303           0 :       COMPARISON_CASE(Int8x16, kI8x16LtS, Int32LessThan, false)
    1304           0 :       COMPARISON_CASE(Int8x16, kI8x16LeS, Int32LessThanOrEqual, false)
    1305          10 :       COMPARISON_CASE(Int8x16, kI8x16GtS, Int32LessThan, true)
    1306          10 :       COMPARISON_CASE(Int8x16, kI8x16GeS, Int32LessThanOrEqual, true)
    1307           0 :       COMPARISON_CASE(Int8x16, kI8x16LtU, Uint32LessThan, false)
    1308           0 :       COMPARISON_CASE(Int8x16, kI8x16LeU, Uint32LessThanOrEqual, false)
    1309          10 :       COMPARISON_CASE(Int8x16, kI8x16GtU, Uint32LessThan, true)
    1310          10 :       COMPARISON_CASE(Int8x16, kI8x16GeU, Uint32LessThanOrEqual, true)
    1311             : #undef COMPARISON_CASE
    1312             :     case IrOpcode::kF32x4Ne: {
    1313           5 :       LowerNotEqual(node, SimdType::kFloat32x4, machine()->Float32Equal());
    1314           5 :       break;
    1315             :     }
    1316             :     case IrOpcode::kI32x4Ne: {
    1317          25 :       LowerNotEqual(node, SimdType::kInt32x4, machine()->Word32Equal());
    1318          25 :       break;
    1319             :     }
    1320             :     case IrOpcode::kI16x8Ne: {
    1321          25 :       LowerNotEqual(node, SimdType::kInt16x8, machine()->Word32Equal());
    1322          25 :       break;
    1323             :     }
    1324             :     case IrOpcode::kI8x16Ne: {
    1325          25 :       LowerNotEqual(node, SimdType::kInt8x16, machine()->Word32Equal());
    1326          25 :       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           0 :       Node** rep_left = GetReplacementsWithType(node->InputAt(1), rep_type);
    1335           0 :       Node** rep_right = GetReplacementsWithType(node->InputAt(2), rep_type);
    1336           0 :       Node** rep_node = zone()->NewArray<Node*>(num_lanes);
    1337           0 :       for (int i = 0; i < num_lanes; ++i) {
    1338             :         Node* tmp1 =
    1339           0 :             graph()->NewNode(machine()->Word32Xor(), rep_left[i], rep_right[i]);
    1340             :         Node* tmp2 =
    1341           0 :             graph()->NewNode(machine()->Word32And(), boolean_input[i], tmp1);
    1342           0 :         rep_node[i] =
    1343           0 :             graph()->NewNode(machine()->Word32Xor(), rep_right[i], tmp2);
    1344             :       }
    1345           0 :       ReplaceNode(node, rep_node, num_lanes);
    1346           0 :       break;
    1347             :     }
    1348             :     case IrOpcode::kS8x16Shuffle: {
    1349             :       DCHECK_EQ(2, node->InputCount());
    1350        9250 :       const uint8_t* shuffle = OpParameter<uint8_t*>(node->op());
    1351        9250 :       Node** rep_left = GetReplacementsWithType(node->InputAt(0), rep_type);
    1352        9250 :       Node** rep_right = GetReplacementsWithType(node->InputAt(1), rep_type);
    1353             :       Node** rep_node = zone()->NewArray<Node*>(16);
    1354      157250 :       for (int i = 0; i < 16; i++) {
    1355      148000 :         int lane = shuffle[i];
    1356      148000 :         rep_node[i] = lane < 16 ? rep_left[lane] : rep_right[lane - 16];
    1357             :       }
    1358        9250 :       ReplaceNode(node, rep_node, 16);
    1359        9250 :       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         120 :       int input_num_lanes = NumLanes(input_rep_type);
    1370             :       Node** rep = GetReplacements(node->InputAt(0));
    1371         120 :       Node** rep_node = zone()->NewArray<Node*>(num_lanes);
    1372         120 :       Node* true_node = mcgraph_->Int32Constant(-1);
    1373         120 :       Node* false_node = mcgraph_->Int32Constant(0);
    1374             :       Node* tmp_result = false_node;
    1375         220 :       if (node->opcode() == IrOpcode::kS1x4AllTrue ||
    1376         200 :           node->opcode() == IrOpcode::kS1x8AllTrue ||
    1377             :           node->opcode() == IrOpcode::kS1x16AllTrue) {
    1378             :         tmp_result = true_node;
    1379             :       }
    1380        1120 :       for (int i = 0; i < input_num_lanes; ++i) {
    1381             :         Diamond is_false(
    1382             :             graph(), common(),
    1383        3360 :             graph()->NewNode(machine()->Word32Equal(), rep[i], false_node));
    1384        2160 :         if (node->opcode() == IrOpcode::kS1x4AllTrue ||
    1385        2000 :             node->opcode() == IrOpcode::kS1x8AllTrue ||
    1386             :             node->opcode() == IrOpcode::kS1x16AllTrue) {
    1387             :           tmp_result = is_false.Phi(MachineRepresentation::kWord32, false_node,
    1388         560 :                                     tmp_result);
    1389             :         } else {
    1390             :           tmp_result = is_false.Phi(MachineRepresentation::kWord32, tmp_result,
    1391         560 :                                     true_node);
    1392             :         }
    1393             :       }
    1394         120 :       rep_node[0] = tmp_result;
    1395         480 :       for (int i = 1; i < num_lanes; ++i) {
    1396         360 :         rep_node[i] = nullptr;
    1397             :       }
    1398         120 :       ReplaceNode(node, rep_node, num_lanes);
    1399         120 :       break;
    1400             :     }
    1401       96875 :     default: { DefaultLowering(node); }
    1402             :   }
    1403      181480 : }
    1404             : 
    1405      127345 : bool SimdScalarLowering::DefaultLowering(Node* node) {
    1406             :   bool something_changed = false;
    1407      258285 :   for (int i = NodeProperties::PastValueIndex(node) - 1; i >= 0; i--) {
    1408             :     Node* input = node->InputAt(i);
    1409      130940 :     if (HasReplacement(0, input)) {
    1410             :       something_changed = true;
    1411       11465 :       node->ReplaceInput(i, GetReplacements(input)[0]);
    1412             :     }
    1413      130940 :     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      127345 :   return something_changed;
    1421             : }
    1422             : 
    1423      723480 : void SimdScalarLowering::ReplaceNode(Node* old, Node** new_nodes, int count) {
    1424      122970 :   replacements_[old->id()].node = zone()->NewArray<Node*>(count);
    1425      600510 :   for (int i = 0; i < count; ++i) {
    1426     1119040 :     replacements_[old->id()].node[i] = new_nodes[i];
    1427             :   }
    1428       81980 :   replacements_[old->id()].num_replacements = count;
    1429       40990 : }
    1430             : 
    1431      275010 : bool SimdScalarLowering::HasReplacement(size_t index, Node* node) {
    1432      572970 :   return replacements_[node->id()].node != nullptr &&
    1433       22950 :          replacements_[node->id()].node[index] != nullptr;
    1434             : }
    1435             : 
    1436      185440 : SimdScalarLowering::SimdType SimdScalarLowering::ReplacementType(Node* node) {
    1437      406615 :   return replacements_[node->id()].type;
    1438             : }
    1439             : 
    1440       36005 : Node** SimdScalarLowering::GetReplacements(Node* node) {
    1441       71870 :   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         315 : void SimdScalarLowering::Int32ToFloat32(Node** replacements, Node** result) {
    1451         175 :   for (int i = 0; i < kNumLanes32; ++i) {
    1452         140 :     if (replacements[i] != nullptr) {
    1453         140 :       result[i] =
    1454         280 :           graph()->NewNode(machine()->BitcastInt32ToFloat32(), replacements[i]);
    1455             :     } else {
    1456           0 :       result[i] = nullptr;
    1457             :     }
    1458             :   }
    1459          35 : }
    1460             : 
    1461         135 : void SimdScalarLowering::Float32ToInt32(Node** replacements, Node** result) {
    1462          75 :   for (int i = 0; i < kNumLanes32; ++i) {
    1463          60 :     if (replacements[i] != nullptr) {
    1464          60 :       result[i] =
    1465         120 :           graph()->NewNode(machine()->BitcastFloat32ToInt32(), replacements[i]);
    1466             :     } else {
    1467           0 :       result[i] = nullptr;
    1468             :     }
    1469             :   }
    1470          15 : }
    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             :         Node* clean_bits = graph()->NewNode(machine()->Word32And(),
    1515             :                                             replacements[num_ints * i + j],
    1516           0 :                                             mcgraph_->Int32Constant(bit_mask));
    1517             :         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       35905 : Node** SimdScalarLowering::GetReplacementsWithType(Node* node, SimdType type) {
    1526             :   Node** replacements = GetReplacements(node);
    1527       35855 :   if (ReplacementType(node) == type) {
    1528             :     return GetReplacements(node);
    1529             :   }
    1530          50 :   int num_lanes = NumLanes(type);
    1531          50 :   Node** result = zone()->NewArray<Node*>(num_lanes);
    1532          50 :   if (type == SimdType::kInt32x4) {
    1533          15 :     if (ReplacementType(node) == SimdType::kFloat32x4) {
    1534          15 :       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          35 :   } else if (type == SimdType::kFloat32x4) {
    1543          35 :     if (ReplacementType(node) == SimdType::kInt32x4) {
    1544          35 :       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          50 :   return result;
    1568             : }
    1569             : 
    1570         260 : void SimdScalarLowering::PreparePhiReplacement(Node* phi) {
    1571         110 :   MachineRepresentation rep = PhiRepresentationOf(phi->op());
    1572         110 :   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          10 :     int value_count = phi->op()->ValueInputCount();
    1578             :     SimdType type = ReplacementType(phi);
    1579          10 :     int num_lanes = NumLanes(type);
    1580          10 :     Node*** inputs_rep = zone()->NewArray<Node**>(num_lanes);
    1581          50 :     for (int i = 0; i < num_lanes; ++i) {
    1582          80 :       inputs_rep[i] = zone()->NewArray<Node*>(value_count + 1);
    1583          40 :       inputs_rep[i][value_count] = NodeProperties::GetControlInput(phi, 0);
    1584             :     }
    1585          20 :     for (int i = 0; i < value_count; ++i) {
    1586          80 :       for (int j = 0; j < num_lanes; ++j) {
    1587          80 :         inputs_rep[j][i] = placeholder_;
    1588             :       }
    1589             :     }
    1590             :     Node** rep_nodes = zone()->NewArray<Node*>(num_lanes);
    1591          50 :     for (int i = 0; i < num_lanes; ++i) {
    1592          40 :       rep_nodes[i] = graph()->NewNode(
    1593             :           common()->Phi(MachineTypeFrom(type).representation(), value_count),
    1594         120 :           value_count + 1, inputs_rep[i], false);
    1595             :     }
    1596          10 :     ReplaceNode(phi, rep_nodes, num_lanes);
    1597             :   }
    1598         110 : }
    1599             : }  // namespace compiler
    1600             : }  // namespace internal
    1601      183867 : }  // namespace v8

Generated by: LCOV version 1.10