| Index: src/compiler/simd-scalar-lowering.cc | 
| diff --git a/src/compiler/simd-scalar-lowering.cc b/src/compiler/simd-scalar-lowering.cc | 
| index cfa46c3cafe817c92ee61c462928a8aa67fddbff..d2487e2e79bbb1cf6e6eb604c216a762c87faca6 100644 | 
| --- a/src/compiler/simd-scalar-lowering.cc | 
| +++ b/src/compiler/simd-scalar-lowering.cc | 
| @@ -17,24 +17,19 @@ namespace internal { | 
| namespace compiler { | 
|  | 
| SimdScalarLowering::SimdScalarLowering( | 
| -    Graph* graph, MachineOperatorBuilder* machine, | 
| -    CommonOperatorBuilder* common, Zone* zone, | 
| -    Signature<MachineRepresentation>* signature) | 
| -    : zone_(zone), | 
| -      graph_(graph), | 
| -      machine_(machine), | 
| -      common_(common), | 
| -      state_(graph, 3), | 
| -      stack_(zone), | 
| +    JSGraph* jsgraph, Signature<MachineRepresentation>* signature) | 
| +    : jsgraph_(jsgraph), | 
| +      state_(jsgraph->graph(), 3), | 
| +      stack_(jsgraph_->zone()), | 
| replacements_(nullptr), | 
| signature_(signature), | 
| -      placeholder_( | 
| -          graph->NewNode(common->Parameter(-2, "placeholder"), graph->start())), | 
| +      placeholder_(graph()->NewNode(common()->Parameter(-2, "placeholder"), | 
| +                                    graph()->start())), | 
| parameter_count_after_lowering_(-1) { | 
| -  DCHECK_NOT_NULL(graph); | 
| -  DCHECK_NOT_NULL(graph->end()); | 
| -  replacements_ = zone->NewArray<Replacement>(graph->NodeCount()); | 
| -  memset(replacements_, 0, sizeof(Replacement) * graph->NodeCount()); | 
| +  DCHECK_NOT_NULL(graph()); | 
| +  DCHECK_NOT_NULL(graph()->end()); | 
| +  replacements_ = zone()->NewArray<Replacement>(graph()->NodeCount()); | 
| +  memset(replacements_, 0, sizeof(Replacement) * graph()->NodeCount()); | 
| } | 
|  | 
| void SimdScalarLowering::LowerGraph() { | 
| @@ -80,9 +75,15 @@ void SimdScalarLowering::LowerGraph() { | 
| V(Int32x4Add)                   \ | 
| V(Int32x4Sub)                   \ | 
| V(Int32x4Mul)                   \ | 
| +  V(Int32x4Min)                   \ | 
| +  V(Int32x4Max)                   \ | 
| +  V(Uint32x4Min)                  \ | 
| +  V(Uint32x4Max)                  \ | 
| V(Simd128And)                   \ | 
| V(Simd128Or)                    \ | 
| -  V(Simd128Xor) | 
| +  V(Simd128Xor)                   \ | 
| +  V(Int32x4FromFloat32x4)         \ | 
| +  V(Uint32x4FromFloat32x4) | 
|  | 
| #define FOREACH_FLOAT32X4_OPCODE(V) \ | 
| V(Float32x4Splat)                 \ | 
| @@ -115,11 +116,20 @@ void SimdScalarLowering::SetLoweredType(Node* node, Node* output) { | 
| } | 
| #undef CASE_STMT | 
| default: { | 
| -      if (output->opcode() == IrOpcode::kFloat32x4FromInt32x4 || | 
| -          output->opcode() == IrOpcode::kFloat32x4FromUint32x4) { | 
| -        replacements_[node->id()].type = SimdType::kInt32; | 
| -      } else { | 
| -        replacements_[node->id()].type = replacements_[output->id()].type; | 
| +      switch (output->opcode()) { | 
| +        case IrOpcode::kFloat32x4FromInt32x4: | 
| +        case IrOpcode::kFloat32x4FromUint32x4: { | 
| +          replacements_[node->id()].type = SimdType::kInt32; | 
| +          break; | 
| +        } | 
| +        case IrOpcode::kInt32x4FromFloat32x4: | 
| +        case IrOpcode::kUint32x4FromFloat32x4: { | 
| +          replacements_[node->id()].type = SimdType::kFloat32; | 
| +          break; | 
| +        } | 
| +        default: { | 
| +          replacements_[node->id()].type = replacements_[output->id()].type; | 
| +        } | 
| } | 
| } | 
| } | 
| @@ -264,6 +274,104 @@ void SimdScalarLowering::LowerUnaryOp(Node* node, SimdType input_rep_type, | 
| ReplaceNode(node, rep_node); | 
| } | 
|  | 
| +void SimdScalarLowering::LowerIntMinMax(Node* node, const Operator* op, | 
| +                                        bool is_max) { | 
| +  DCHECK(node->InputCount() == 2); | 
| +  Node** rep_left = GetReplacementsWithType(node->InputAt(0), SimdType::kInt32); | 
| +  Node** rep_right = | 
| +      GetReplacementsWithType(node->InputAt(1), SimdType::kInt32); | 
| +  Node* rep_node[kMaxLanes]; | 
| +  for (int i = 0; i < kMaxLanes; ++i) { | 
| +    Diamond d(graph(), common(), | 
| +              graph()->NewNode(op, rep_left[i], rep_right[i])); | 
| +    if (is_max) { | 
| +      rep_node[i] = | 
| +          d.Phi(MachineRepresentation::kWord32, rep_right[i], rep_left[i]); | 
| +    } else { | 
| +      rep_node[i] = | 
| +          d.Phi(MachineRepresentation::kWord32, rep_left[i], rep_right[i]); | 
| +    } | 
| +  } | 
| +  ReplaceNode(node, rep_node); | 
| +} | 
| + | 
| +Node* SimdScalarLowering::BuildF64Trunc(Node* input) { | 
| +  if (machine()->Float64RoundTruncate().IsSupported()) { | 
| +    return graph()->NewNode(machine()->Float64RoundTruncate().op(), input); | 
| +  } else { | 
| +    ExternalReference ref = | 
| +        ExternalReference::wasm_f64_trunc(jsgraph_->isolate()); | 
| +    Node* stack_slot = | 
| +        graph()->NewNode(machine()->StackSlot(MachineRepresentation::kFloat64)); | 
| +    const Operator* store_op = machine()->Store( | 
| +        StoreRepresentation(MachineRepresentation::kFloat64, kNoWriteBarrier)); | 
| +    Node* effect = | 
| +        graph()->NewNode(store_op, stack_slot, jsgraph_->Int32Constant(0), | 
| +                         input, graph()->start(), graph()->start()); | 
| +    Node* function = graph()->NewNode(common()->ExternalConstant(ref)); | 
| +    Node** args = zone()->NewArray<Node*>(4); | 
| +    args[0] = function; | 
| +    args[1] = stack_slot; | 
| +    args[2] = effect; | 
| +    args[3] = graph()->start(); | 
| +    Signature<MachineType>::Builder sig_builder(zone(), 0, 1); | 
| +    sig_builder.AddParam(MachineType::Pointer()); | 
| +    CallDescriptor* desc = | 
| +        Linkage::GetSimplifiedCDescriptor(zone(), sig_builder.Build()); | 
| +    Node* call = graph()->NewNode(common()->Call(desc), 4, args); | 
| +    return graph()->NewNode(machine()->Load(LoadRepresentation::Float64()), | 
| +                            stack_slot, jsgraph_->Int32Constant(0), call, | 
| +                            graph()->start()); | 
| +  } | 
| +} | 
| + | 
| +void SimdScalarLowering::LowerConvertFromFloat(Node* node, bool is_signed) { | 
| +  DCHECK(node->InputCount() == 1); | 
| +  Node** rep = GetReplacementsWithType(node->InputAt(0), SimdType::kFloat32); | 
| +  Node* rep_node[kMaxLanes]; | 
| +  Node* double_zero = graph()->NewNode(common()->Float64Constant(0.0)); | 
| +  Node* min = graph()->NewNode( | 
| +      common()->Float64Constant(static_cast<double>(is_signed ? kMinInt : 0))); | 
| +  Node* max = graph()->NewNode(common()->Float64Constant( | 
| +      static_cast<double>(is_signed ? kMaxInt : 0xffffffffu))); | 
| +  for (int i = 0; i < kMaxLanes; ++i) { | 
| +    Node* double_rep = | 
| +        graph()->NewNode(machine()->ChangeFloat32ToFloat64(), rep[i]); | 
| +    Diamond nan_d(graph(), common(), graph()->NewNode(machine()->Float64Equal(), | 
| +                                                      double_rep, double_rep)); | 
| +    Node* temp = | 
| +        nan_d.Phi(MachineRepresentation::kFloat64, double_rep, double_zero); | 
| +    Diamond min_d(graph(), common(), | 
| +                  graph()->NewNode(machine()->Float64LessThan(), temp, min)); | 
| +    temp = min_d.Phi(MachineRepresentation::kFloat64, min, temp); | 
| +    Diamond max_d(graph(), common(), | 
| +                  graph()->NewNode(machine()->Float64LessThan(), max, temp)); | 
| +    temp = max_d.Phi(MachineRepresentation::kFloat64, max, temp); | 
| +    Node* trunc = BuildF64Trunc(temp); | 
| +    if (is_signed) { | 
| +      rep_node[i] = graph()->NewNode(machine()->ChangeFloat64ToInt32(), trunc); | 
| +    } else { | 
| +      rep_node[i] = | 
| +          graph()->NewNode(machine()->TruncateFloat64ToUint32(), trunc); | 
| +    } | 
| +  } | 
| +  ReplaceNode(node, rep_node); | 
| +} | 
| + | 
| +void SimdScalarLowering::LowerShiftOp(Node* node, const Operator* op) { | 
| +  static int32_t shift_mask = 0x1f; | 
| +  DCHECK_EQ(1, node->InputCount()); | 
| +  int32_t shift_amount = OpParameter<int32_t>(node); | 
| +  Node* shift_node = | 
| +      graph()->NewNode(common()->Int32Constant(shift_amount & shift_mask)); | 
| +  Node** rep = GetReplacementsWithType(node->InputAt(0), SimdType::kInt32); | 
| +  Node* rep_node[kMaxLanes]; | 
| +  for (int i = 0; i < kMaxLanes; ++i) { | 
| +    rep_node[i] = graph()->NewNode(op, rep[i], shift_node); | 
| +  } | 
| +  ReplaceNode(node, rep_node); | 
| +} | 
| + | 
| void SimdScalarLowering::LowerNode(Node* node) { | 
| SimdType rep_type = ReplacementType(node); | 
| switch (node->opcode()) { | 
| @@ -422,6 +530,22 @@ void SimdScalarLowering::LowerNode(Node* node) { | 
| I32X4_BINOP_CASE(kSimd128Or, Word32Or) | 
| I32X4_BINOP_CASE(kSimd128Xor, Word32Xor) | 
| #undef I32X4_BINOP_CASE | 
| +    case IrOpcode::kInt32x4Max: { | 
| +      LowerIntMinMax(node, machine()->Int32LessThan(), true); | 
| +      break; | 
| +    } | 
| +    case IrOpcode::kInt32x4Min: { | 
| +      LowerIntMinMax(node, machine()->Int32LessThan(), false); | 
| +      break; | 
| +    } | 
| +    case IrOpcode::kUint32x4Max: { | 
| +      LowerIntMinMax(node, machine()->Uint32LessThan(), true); | 
| +      break; | 
| +    } | 
| +    case IrOpcode::kUint32x4Min: { | 
| +      LowerIntMinMax(node, machine()->Uint32LessThan(), false); | 
| +      break; | 
| +    } | 
| case IrOpcode::kInt32x4Neg: { | 
| DCHECK(node->InputCount() == 1); | 
| Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type); | 
| @@ -444,6 +568,26 @@ void SimdScalarLowering::LowerNode(Node* node) { | 
| ReplaceNode(node, rep_node); | 
| break; | 
| } | 
| +    case IrOpcode::kInt32x4FromFloat32x4: { | 
| +      LowerConvertFromFloat(node, true); | 
| +      break; | 
| +    } | 
| +    case IrOpcode::kUint32x4FromFloat32x4: { | 
| +      LowerConvertFromFloat(node, false); | 
| +      break; | 
| +    } | 
| +    case IrOpcode::kInt32x4ShiftLeftByScalar: { | 
| +      LowerShiftOp(node, machine()->Word32Shl()); | 
| +      break; | 
| +    } | 
| +    case IrOpcode::kInt32x4ShiftRightByScalar: { | 
| +      LowerShiftOp(node, machine()->Word32Sar()); | 
| +      break; | 
| +    } | 
| +    case IrOpcode::kUint32x4ShiftRightByScalar: { | 
| +      LowerShiftOp(node, machine()->Word32Shr()); | 
| +      break; | 
| +    } | 
| #define F32X4_BINOP_CASE(name)                                 \ | 
| case IrOpcode::kFloat32x4##name: {                           \ | 
| LowerBinaryOp(node, rep_type, machine()->Float32##name()); \ | 
|  |