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..8e1bf81917713df13fe64db136c2b014119a15dc 100644 |
--- a/src/compiler/simd-scalar-lowering.cc |
+++ b/src/compiler/simd-scalar-lowering.cc |
@@ -80,9 +80,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 +121,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 +279,75 @@ 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); |
+} |
+ |
+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 = |
+ graph()->NewNode(machine()->Float64RoundTruncate().op(), 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 +506,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 +544,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()); \ |