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()); \ |