summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/simd-scalar-lowering.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/simd-scalar-lowering.cc')
-rw-r--r--deps/v8/src/compiler/simd-scalar-lowering.cc834
1 files changed, 623 insertions, 211 deletions
diff --git a/deps/v8/src/compiler/simd-scalar-lowering.cc b/deps/v8/src/compiler/simd-scalar-lowering.cc
index 8f967788db..6cf88d33cf 100644
--- a/deps/v8/src/compiler/simd-scalar-lowering.cc
+++ b/deps/v8/src/compiler/simd-scalar-lowering.cc
@@ -16,6 +16,16 @@ namespace v8 {
namespace internal {
namespace compiler {
+namespace {
+static const int kNumLanes32 = 4;
+static const int kNumLanes16 = 8;
+static const int kNumLanes8 = 16;
+static const int32_t kMask16 = 0xffff;
+static const int32_t kMask8 = 0xff;
+static const int32_t kShift16 = 16;
+static const int32_t kShift8 = 24;
+} // anonymous
+
SimdScalarLowering::SimdScalarLowering(
JSGraph* jsgraph, Signature<MachineRepresentation>* signature)
: jsgraph_(jsgraph),
@@ -35,7 +45,7 @@ SimdScalarLowering::SimdScalarLowering(
void SimdScalarLowering::LowerGraph() {
stack_.push_back({graph()->end(), 0});
state_.Set(graph()->end(), State::kOnStack);
- replacements_[graph()->end()->id()].type = SimdType::kInt32;
+ replacements_[graph()->end()->id()].type = SimdType::kInt32x4;
while (!stack_.empty()) {
NodeState& top = stack_.back();
@@ -73,11 +83,14 @@ void SimdScalarLowering::LowerGraph() {
V(I32x4SConvertF32x4) \
V(I32x4UConvertF32x4) \
V(I32x4Neg) \
+ V(I32x4Shl) \
+ V(I32x4ShrS) \
V(I32x4Add) \
V(I32x4Sub) \
V(I32x4Mul) \
V(I32x4MinS) \
V(I32x4MaxS) \
+ V(I32x4ShrU) \
V(I32x4MinU) \
V(I32x4MaxU) \
V(S128And) \
@@ -96,7 +109,6 @@ void SimdScalarLowering::LowerGraph() {
V(F32x4Add) \
V(F32x4Sub) \
V(F32x4Mul) \
- V(F32x4Div) \
V(F32x4Min) \
V(F32x4Max)
@@ -120,6 +132,74 @@ void SimdScalarLowering::LowerGraph() {
V(I32x4GtU) \
V(I32x4GeU)
+#define FOREACH_INT16X8_OPCODE(V) \
+ V(I16x8Splat) \
+ V(I16x8ExtractLane) \
+ V(I16x8ReplaceLane) \
+ V(I16x8Neg) \
+ V(I16x8Shl) \
+ V(I16x8ShrS) \
+ V(I16x8Add) \
+ V(I16x8AddSaturateS) \
+ V(I16x8Sub) \
+ V(I16x8SubSaturateS) \
+ V(I16x8Mul) \
+ V(I16x8MinS) \
+ V(I16x8MaxS) \
+ V(I16x8ShrU) \
+ V(I16x8AddSaturateU) \
+ V(I16x8SubSaturateU) \
+ V(I16x8MinU) \
+ V(I16x8MaxU)
+
+#define FOREACH_INT8X16_OPCODE(V) \
+ V(I8x16Splat) \
+ V(I8x16ExtractLane) \
+ V(I8x16ReplaceLane) \
+ V(I8x16Neg) \
+ V(I8x16Shl) \
+ V(I8x16ShrS) \
+ V(I8x16Add) \
+ V(I8x16AddSaturateS) \
+ V(I8x16Sub) \
+ V(I8x16SubSaturateS) \
+ V(I8x16Mul) \
+ V(I8x16MinS) \
+ V(I8x16MaxS) \
+ V(I8x16ShrU) \
+ V(I8x16AddSaturateU) \
+ V(I8x16SubSaturateU) \
+ V(I8x16MinU) \
+ V(I8x16MaxU)
+
+#define FOREACH_INT16X8_TO_SIMD1X8OPCODE(V) \
+ V(I16x8Eq) \
+ V(I16x8Ne) \
+ V(I16x8LtS) \
+ V(I16x8LeS) \
+ V(I16x8LtU) \
+ V(I16x8LeU)
+
+#define FOREACH_INT8X16_TO_SIMD1X16OPCODE(V) \
+ V(I8x16Eq) \
+ V(I8x16Ne) \
+ V(I8x16LtS) \
+ V(I8x16LeS) \
+ V(I8x16LtU) \
+ V(I8x16LeU)
+
+#define FOREACH_SIMD_TYPE_TO_MACHINE_TYPE(V) \
+ V(Float32x4, Float32) \
+ V(Int32x4, Int32) \
+ V(Int16x8, Int16) \
+ V(Int8x16, Int8)
+
+#define FOREACH_SIMD_TYPE_TO_MACHINE_REP(V) \
+ V(Float32x4, Float32) \
+ V(Int32x4, Word32) \
+ V(Int16x8, Word16) \
+ V(Int8x16, Word8)
+
void SimdScalarLowering::SetLoweredType(Node* node, Node* output) {
switch (node->opcode()) {
#define CASE_STMT(name) case IrOpcode::k##name:
@@ -127,11 +207,11 @@ void SimdScalarLowering::SetLoweredType(Node* node, Node* output) {
case IrOpcode::kReturn:
case IrOpcode::kParameter:
case IrOpcode::kCall: {
- replacements_[node->id()].type = SimdType::kInt32;
+ replacements_[node->id()].type = SimdType::kInt32x4;
break;
}
FOREACH_FLOAT32X4_OPCODE(CASE_STMT) {
- replacements_[node->id()].type = SimdType::kFloat32;
+ replacements_[node->id()].type = SimdType::kFloat32x4;
break;
}
FOREACH_FLOAT32X4_TO_SIMD1X4OPCODE(CASE_STMT)
@@ -139,24 +219,52 @@ void SimdScalarLowering::SetLoweredType(Node* node, Node* output) {
replacements_[node->id()].type = SimdType::kSimd1x4;
break;
}
+ FOREACH_INT16X8_OPCODE(CASE_STMT) {
+ replacements_[node->id()].type = SimdType::kInt16x8;
+ break;
+ }
+ FOREACH_INT16X8_TO_SIMD1X8OPCODE(CASE_STMT) {
+ replacements_[node->id()].type = SimdType::kSimd1x8;
+ break;
+ }
+ FOREACH_INT8X16_OPCODE(CASE_STMT) {
+ replacements_[node->id()].type = SimdType::kInt8x16;
+ break;
+ }
+ FOREACH_INT8X16_TO_SIMD1X16OPCODE(CASE_STMT) {
+ replacements_[node->id()].type = SimdType::kSimd1x16;
+ break;
+ }
default: {
switch (output->opcode()) {
FOREACH_FLOAT32X4_TO_SIMD1X4OPCODE(CASE_STMT)
case IrOpcode::kF32x4SConvertI32x4:
case IrOpcode::kF32x4UConvertI32x4: {
- replacements_[node->id()].type = SimdType::kInt32;
+ replacements_[node->id()].type = SimdType::kInt32x4;
break;
}
FOREACH_INT32X4_TO_SIMD1X4OPCODE(CASE_STMT)
case IrOpcode::kI32x4SConvertF32x4:
case IrOpcode::kI32x4UConvertF32x4: {
- replacements_[node->id()].type = SimdType::kFloat32;
+ replacements_[node->id()].type = SimdType::kFloat32x4;
break;
}
case IrOpcode::kS32x4Select: {
replacements_[node->id()].type = SimdType::kSimd1x4;
break;
}
+ FOREACH_INT16X8_TO_SIMD1X8OPCODE(CASE_STMT) {
+ replacements_[node->id()].type = SimdType::kInt16x8;
+ break;
+ }
+ FOREACH_INT8X16_TO_SIMD1X16OPCODE(CASE_STMT) {
+ replacements_[node->id()].type = SimdType::kInt8x16;
+ break;
+ }
+ case IrOpcode::kS16x8Select: {
+ replacements_[node->id()].type = SimdType::kSimd1x8;
+ break;
+ }
default: {
replacements_[node->id()].type = replacements_[output->id()].type;
}
@@ -200,42 +308,66 @@ static int GetReturnCountAfterLowering(
return result;
}
-void SimdScalarLowering::GetIndexNodes(Node* index, Node** new_indices) {
- new_indices[0] = index;
- for (size_t i = 1; i < kMaxLanes; ++i) {
- new_indices[i] = graph()->NewNode(machine()->Int32Add(), index,
- graph()->NewNode(common()->Int32Constant(
- static_cast<int>(i) * kLaneWidth)));
+int SimdScalarLowering::NumLanes(SimdType type) {
+ int num_lanes = 0;
+ if (type == SimdType::kFloat32x4 || type == SimdType::kInt32x4 ||
+ type == SimdType::kSimd1x4) {
+ num_lanes = kNumLanes32;
+ } else if (type == SimdType::kInt16x8 || type == SimdType::kSimd1x8) {
+ num_lanes = kNumLanes16;
+ } else if (type == SimdType::kInt8x16 || type == SimdType::kSimd1x16) {
+ num_lanes = kNumLanes8;
+ } else {
+ UNREACHABLE();
+ }
+ return num_lanes;
+}
+
+constexpr int SimdScalarLowering::kLaneOffsets[];
+
+void SimdScalarLowering::GetIndexNodes(Node* index, Node** new_indices,
+ SimdType type) {
+ int num_lanes = NumLanes(type);
+ int lane_width = kSimd128Size / num_lanes;
+ int laneIndex = kLaneOffsets[0] / lane_width;
+ new_indices[laneIndex] = index;
+ for (int i = 1; i < num_lanes; ++i) {
+ laneIndex = kLaneOffsets[i * lane_width] / lane_width;
+ new_indices[laneIndex] = graph()->NewNode(
+ machine()->Int32Add(), index,
+ graph()->NewNode(
+ common()->Int32Constant(static_cast<int>(i) * lane_width)));
}
}
void SimdScalarLowering::LowerLoadOp(MachineRepresentation rep, Node* node,
- const Operator* load_op) {
+ const Operator* load_op, SimdType type) {
if (rep == MachineRepresentation::kSimd128) {
Node* base = node->InputAt(0);
Node* index = node->InputAt(1);
- Node* indices[kMaxLanes];
- GetIndexNodes(index, indices);
- Node* rep_nodes[kMaxLanes];
+ int num_lanes = NumLanes(type);
+ Node** indices = zone()->NewArray<Node*>(num_lanes);
+ GetIndexNodes(index, indices, type);
+ Node** rep_nodes = zone()->NewArray<Node*>(num_lanes);
rep_nodes[0] = node;
+ rep_nodes[0]->ReplaceInput(1, indices[0]);
NodeProperties::ChangeOp(rep_nodes[0], load_op);
if (node->InputCount() > 2) {
DCHECK(node->InputCount() > 3);
Node* effect_input = node->InputAt(2);
Node* control_input = node->InputAt(3);
- rep_nodes[3] = graph()->NewNode(load_op, base, indices[3], effect_input,
- control_input);
- rep_nodes[2] = graph()->NewNode(load_op, base, indices[2], rep_nodes[3],
- control_input);
- rep_nodes[1] = graph()->NewNode(load_op, base, indices[1], rep_nodes[2],
- control_input);
+ for (int i = num_lanes - 1; i > 0; --i) {
+ rep_nodes[i] = graph()->NewNode(load_op, base, indices[i], effect_input,
+ control_input);
+ effect_input = rep_nodes[i];
+ }
rep_nodes[0]->ReplaceInput(2, rep_nodes[1]);
} else {
- for (size_t i = 1; i < kMaxLanes; ++i) {
+ for (int i = 1; i < num_lanes; ++i) {
rep_nodes[i] = graph()->NewNode(load_op, base, indices[i]);
}
}
- ReplaceNode(node, rep_nodes);
+ ReplaceNode(node, rep_nodes, num_lanes);
} else {
DefaultLowering(node);
}
@@ -247,36 +379,36 @@ void SimdScalarLowering::LowerStoreOp(MachineRepresentation rep, Node* node,
if (rep == MachineRepresentation::kSimd128) {
Node* base = node->InputAt(0);
Node* index = node->InputAt(1);
- Node* indices[kMaxLanes];
- GetIndexNodes(index, indices);
+ int num_lanes = NumLanes(rep_type);
+ Node** indices = zone()->NewArray<Node*>(num_lanes);
+ GetIndexNodes(index, indices, rep_type);
DCHECK(node->InputCount() > 2);
Node* value = node->InputAt(2);
DCHECK(HasReplacement(1, value));
- Node* rep_nodes[kMaxLanes];
+ Node** rep_nodes = zone()->NewArray<Node*>(num_lanes);
rep_nodes[0] = node;
Node** rep_inputs = GetReplacementsWithType(value, rep_type);
rep_nodes[0]->ReplaceInput(2, rep_inputs[0]);
+ rep_nodes[0]->ReplaceInput(1, indices[0]);
NodeProperties::ChangeOp(node, store_op);
if (node->InputCount() > 3) {
DCHECK(node->InputCount() > 4);
Node* effect_input = node->InputAt(3);
Node* control_input = node->InputAt(4);
- rep_nodes[3] = graph()->NewNode(store_op, base, indices[3], rep_inputs[3],
- effect_input, control_input);
- rep_nodes[2] = graph()->NewNode(store_op, base, indices[2], rep_inputs[2],
- rep_nodes[3], control_input);
- rep_nodes[1] = graph()->NewNode(store_op, base, indices[1], rep_inputs[1],
- rep_nodes[2], control_input);
+ for (int i = num_lanes - 1; i > 0; --i) {
+ rep_nodes[i] =
+ graph()->NewNode(store_op, base, indices[i], rep_inputs[i],
+ effect_input, control_input);
+ effect_input = rep_nodes[i];
+ }
rep_nodes[0]->ReplaceInput(3, rep_nodes[1]);
-
} else {
- for (size_t i = 1; i < kMaxLanes; ++i) {
+ for (int i = 1; i < num_lanes; ++i) {
rep_nodes[i] =
graph()->NewNode(store_op, base, indices[i], rep_inputs[i]);
}
}
-
- ReplaceNode(node, rep_nodes);
+ ReplaceNode(node, rep_nodes, num_lanes);
} else {
DefaultLowering(node);
}
@@ -287,47 +419,146 @@ void SimdScalarLowering::LowerBinaryOp(Node* node, SimdType input_rep_type,
DCHECK(node->InputCount() == 2);
Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type);
- Node* rep_node[kMaxLanes];
- for (int i = 0; i < kMaxLanes; ++i) {
+ int num_lanes = NumLanes(input_rep_type);
+ Node** rep_node = zone()->NewArray<Node*>(num_lanes);
+ for (int i = 0; i < num_lanes; ++i) {
if (invert_inputs) {
rep_node[i] = graph()->NewNode(op, rep_right[i], rep_left[i]);
} else {
rep_node[i] = graph()->NewNode(op, rep_left[i], rep_right[i]);
}
}
- ReplaceNode(node, rep_node);
+ ReplaceNode(node, rep_node, num_lanes);
+}
+
+Node* SimdScalarLowering::FixUpperBits(Node* input, int32_t shift) {
+ return graph()->NewNode(machine()->Word32Sar(),
+ graph()->NewNode(machine()->Word32Shl(), input,
+ jsgraph_->Int32Constant(shift)),
+ jsgraph_->Int32Constant(shift));
+}
+
+void SimdScalarLowering::LowerBinaryOpForSmallInt(Node* node,
+ SimdType input_rep_type,
+ const Operator* op) {
+ DCHECK(node->InputCount() == 2);
+ DCHECK(input_rep_type == SimdType::kInt16x8 ||
+ input_rep_type == SimdType::kInt8x16);
+ Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
+ Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type);
+ int num_lanes = NumLanes(input_rep_type);
+ Node** rep_node = zone()->NewArray<Node*>(num_lanes);
+ int32_t shift_val =
+ (input_rep_type == SimdType::kInt16x8) ? kShift16 : kShift8;
+ for (int i = 0; i < num_lanes; ++i) {
+ rep_node[i] = FixUpperBits(graph()->NewNode(op, rep_left[i], rep_right[i]),
+ shift_val);
+ }
+ ReplaceNode(node, rep_node, num_lanes);
+}
+
+Node* SimdScalarLowering::Mask(Node* input, int32_t mask) {
+ return graph()->NewNode(machine()->Word32And(), input,
+ jsgraph_->Int32Constant(mask));
+}
+
+void SimdScalarLowering::LowerSaturateBinaryOp(Node* node,
+ SimdType input_rep_type,
+ const Operator* op,
+ bool is_signed) {
+ DCHECK(node->InputCount() == 2);
+ DCHECK(input_rep_type == SimdType::kInt16x8 ||
+ input_rep_type == SimdType::kInt8x16);
+ Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
+ Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type);
+ int32_t min = 0;
+ int32_t max = 0;
+ int32_t mask = 0;
+ int32_t shift_val = 0;
+ MachineRepresentation phi_rep;
+ if (input_rep_type == SimdType::kInt16x8) {
+ if (is_signed) {
+ min = std::numeric_limits<int16_t>::min();
+ max = std::numeric_limits<int16_t>::max();
+ } else {
+ min = std::numeric_limits<uint16_t>::min();
+ max = std::numeric_limits<uint16_t>::max();
+ }
+ mask = kMask16;
+ shift_val = kShift16;
+ phi_rep = MachineRepresentation::kWord16;
+ } else {
+ if (is_signed) {
+ min = std::numeric_limits<int8_t>::min();
+ max = std::numeric_limits<int8_t>::max();
+ } else {
+ min = std::numeric_limits<uint8_t>::min();
+ max = std::numeric_limits<uint8_t>::max();
+ }
+ mask = kMask8;
+ shift_val = kShift8;
+ phi_rep = MachineRepresentation::kWord8;
+ }
+ int num_lanes = NumLanes(input_rep_type);
+ Node** rep_node = zone()->NewArray<Node*>(num_lanes);
+ for (int i = 0; i < num_lanes; ++i) {
+ Node* op_result = nullptr;
+ Node* left = is_signed ? rep_left[i] : Mask(rep_left[i], mask);
+ Node* right = is_signed ? rep_right[i] : Mask(rep_right[i], mask);
+ op_result = graph()->NewNode(op, left, right);
+ Diamond d_min(graph(), common(),
+ graph()->NewNode(machine()->Int32LessThan(), op_result,
+ jsgraph_->Int32Constant(min)));
+ rep_node[i] = d_min.Phi(phi_rep, jsgraph_->Int32Constant(min), op_result);
+ Diamond d_max(graph(), common(),
+ graph()->NewNode(machine()->Int32LessThan(),
+ jsgraph_->Int32Constant(max), rep_node[i]));
+ rep_node[i] = d_max.Phi(phi_rep, jsgraph_->Int32Constant(max), rep_node[i]);
+ rep_node[i] =
+ is_signed ? rep_node[i] : FixUpperBits(rep_node[i], shift_val);
+ }
+ ReplaceNode(node, rep_node, num_lanes);
}
void SimdScalarLowering::LowerUnaryOp(Node* node, SimdType input_rep_type,
const Operator* op) {
DCHECK(node->InputCount() == 1);
Node** rep = GetReplacementsWithType(node->InputAt(0), input_rep_type);
- Node* rep_node[kMaxLanes];
- for (int i = 0; i < kMaxLanes; ++i) {
+ int num_lanes = NumLanes(input_rep_type);
+ Node** rep_node = zone()->NewArray<Node*>(num_lanes);
+ for (int i = 0; i < num_lanes; ++i) {
rep_node[i] = graph()->NewNode(op, rep[i]);
}
- ReplaceNode(node, rep_node);
+ ReplaceNode(node, rep_node, num_lanes);
}
void SimdScalarLowering::LowerIntMinMax(Node* node, const Operator* op,
- bool is_max) {
+ bool is_max, SimdType type) {
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) {
+ Node** rep_left = GetReplacementsWithType(node->InputAt(0), type);
+ Node** rep_right = GetReplacementsWithType(node->InputAt(1), type);
+ int num_lanes = NumLanes(type);
+ Node** rep_node = zone()->NewArray<Node*>(num_lanes);
+ MachineRepresentation rep = MachineRepresentation::kNone;
+ if (type == SimdType::kInt32x4) {
+ rep = MachineRepresentation::kWord32;
+ } else if (type == SimdType::kInt16x8) {
+ rep = MachineRepresentation::kWord16;
+ } else if (type == SimdType::kInt8x16) {
+ rep = MachineRepresentation::kWord8;
+ } else {
+ UNREACHABLE();
+ }
+ for (int i = 0; i < num_lanes; ++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]);
+ rep_node[i] = d.Phi(rep, rep_right[i], rep_left[i]);
} else {
- rep_node[i] =
- d.Phi(MachineRepresentation::kWord32, rep_left[i], rep_right[i]);
+ rep_node[i] = d.Phi(rep, rep_left[i], rep_right[i]);
}
}
- ReplaceNode(node, rep_node);
+ ReplaceNode(node, rep_node, num_lanes);
}
Node* SimdScalarLowering::BuildF64Trunc(Node* input) {
@@ -362,14 +593,14 @@ Node* SimdScalarLowering::BuildF64Trunc(Node* input) {
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** rep = GetReplacementsWithType(node->InputAt(0), SimdType::kFloat32x4);
+ Node* rep_node[kNumLanes32];
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) {
+ for (int i = 0; i < kNumLanes32; ++i) {
Node* double_rep =
graph()->NewNode(machine()->ChangeFloat32ToFloat64(), rep[i]);
Diamond nan_d(graph(), common(), graph()->NewNode(machine()->Float64Equal(),
@@ -390,21 +621,55 @@ void SimdScalarLowering::LowerConvertFromFloat(Node* node, bool is_signed) {
graph()->NewNode(machine()->TruncateFloat64ToUint32(), trunc);
}
}
- ReplaceNode(node, rep_node);
+ ReplaceNode(node, rep_node, kNumLanes32);
}
-void SimdScalarLowering::LowerShiftOp(Node* node, const Operator* op) {
- static int32_t shift_mask = 0x1f;
+void SimdScalarLowering::LowerShiftOp(Node* node, SimdType type) {
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);
+ Node* shift_node = graph()->NewNode(common()->Int32Constant(shift_amount));
+ Node** rep = GetReplacementsWithType(node->InputAt(0), type);
+ int num_lanes = NumLanes(type);
+ Node** rep_node = zone()->NewArray<Node*>(num_lanes);
+ for (int i = 0; i < num_lanes; ++i) {
+ rep_node[i] = rep[i];
+ switch (node->opcode()) {
+ case IrOpcode::kI8x16ShrU:
+ rep_node[i] = Mask(rep_node[i], kMask8);
+ rep_node[i] =
+ graph()->NewNode(machine()->Word32Shr(), rep_node[i], shift_node);
+ break;
+ case IrOpcode::kI16x8ShrU:
+ rep_node[i] = Mask(rep_node[i], kMask16); // Fall through.
+ case IrOpcode::kI32x4ShrU:
+ rep_node[i] =
+ graph()->NewNode(machine()->Word32Shr(), rep_node[i], shift_node);
+ break;
+ case IrOpcode::kI32x4Shl:
+ rep_node[i] =
+ graph()->NewNode(machine()->Word32Shl(), rep_node[i], shift_node);
+ break;
+ case IrOpcode::kI16x8Shl:
+ rep_node[i] =
+ graph()->NewNode(machine()->Word32Shl(), rep_node[i], shift_node);
+ rep_node[i] = FixUpperBits(rep_node[i], kShift16);
+ break;
+ case IrOpcode::kI8x16Shl:
+ rep_node[i] =
+ graph()->NewNode(machine()->Word32Shl(), rep_node[i], shift_node);
+ rep_node[i] = FixUpperBits(rep_node[i], kShift8);
+ break;
+ case IrOpcode::kI32x4ShrS:
+ case IrOpcode::kI16x8ShrS:
+ case IrOpcode::kI8x16ShrS:
+ rep_node[i] =
+ graph()->NewNode(machine()->Word32Sar(), rep_node[i], shift_node);
+ break;
+ default:
+ UNREACHABLE();
+ }
}
- ReplaceNode(node, rep_node);
+ ReplaceNode(node, rep_node, num_lanes);
}
void SimdScalarLowering::LowerNotEqual(Node* node, SimdType input_rep_type,
@@ -412,18 +677,20 @@ void SimdScalarLowering::LowerNotEqual(Node* node, SimdType input_rep_type,
DCHECK(node->InputCount() == 2);
Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type);
- Node* rep_node[kMaxLanes];
- for (int i = 0; i < kMaxLanes; ++i) {
+ int num_lanes = NumLanes(input_rep_type);
+ Node** rep_node = zone()->NewArray<Node*>(num_lanes);
+ for (int i = 0; i < num_lanes; ++i) {
Diamond d(graph(), common(),
graph()->NewNode(op, rep_left[i], rep_right[i]));
rep_node[i] = d.Phi(MachineRepresentation::kWord32,
jsgraph_->Int32Constant(0), jsgraph_->Int32Constant(1));
}
- ReplaceNode(node, rep_node);
+ ReplaceNode(node, rep_node, num_lanes);
}
void SimdScalarLowering::LowerNode(Node* node) {
SimdType rep_type = ReplacementType(node);
+ int num_lanes = NumLanes(rep_type);
switch (node->opcode()) {
case IrOpcode::kStart: {
int parameter_count = GetParameterCountAfterLowering();
@@ -449,19 +716,19 @@ void SimdScalarLowering::LowerNode(Node* node) {
if (old_index == new_index) {
NodeProperties::ChangeOp(node, common()->Parameter(new_index));
- Node* new_node[kMaxLanes];
- for (int i = 0; i < kMaxLanes; ++i) {
+ Node* new_node[kNumLanes32];
+ for (int i = 0; i < kNumLanes32; ++i) {
new_node[i] = nullptr;
}
new_node[0] = node;
if (signature()->GetParam(old_index) ==
MachineRepresentation::kSimd128) {
- for (int i = 1; i < kMaxLanes; ++i) {
+ for (int i = 1; i < kNumLanes32; ++i) {
new_node[i] = graph()->NewNode(common()->Parameter(new_index + i),
graph()->start());
}
}
- ReplaceNode(node, new_node);
+ ReplaceNode(node, new_node, kNumLanes32);
}
}
break;
@@ -470,24 +737,36 @@ void SimdScalarLowering::LowerNode(Node* node) {
MachineRepresentation rep =
LoadRepresentationOf(node->op()).representation();
const Operator* load_op;
- if (rep_type == SimdType::kInt32) {
- load_op = machine()->Load(MachineType::Int32());
- } else if (rep_type == SimdType::kFloat32) {
- load_op = machine()->Load(MachineType::Float32());
+#define LOAD_CASE(sType, mType) \
+ case SimdType::k##sType: \
+ load_op = machine()->Load(MachineType::mType()); \
+ break;
+
+ switch (rep_type) {
+ FOREACH_SIMD_TYPE_TO_MACHINE_TYPE(LOAD_CASE)
+ default:
+ UNREACHABLE();
}
- LowerLoadOp(rep, node, load_op);
+#undef LOAD_CASE
+ LowerLoadOp(rep, node, load_op, rep_type);
break;
}
case IrOpcode::kUnalignedLoad: {
MachineRepresentation rep =
UnalignedLoadRepresentationOf(node->op()).representation();
const Operator* load_op;
- if (rep_type == SimdType::kInt32) {
- load_op = machine()->UnalignedLoad(MachineType::Int32());
- } else if (rep_type == SimdType::kFloat32) {
- load_op = machine()->UnalignedLoad(MachineType::Float32());
+#define UNALIGNED_LOAD_CASE(sType, mType) \
+ case SimdType::k##sType: \
+ load_op = machine()->UnalignedLoad(MachineType::mType()); \
+ break;
+
+ switch (rep_type) {
+ FOREACH_SIMD_TYPE_TO_MACHINE_TYPE(UNALIGNED_LOAD_CASE)
+ default:
+ UNREACHABLE();
}
- LowerLoadOp(rep, node, load_op);
+#undef UNALIGHNED_LOAD_CASE
+ LowerLoadOp(rep, node, load_op, rep_type);
break;
}
case IrOpcode::kStore: {
@@ -496,24 +775,35 @@ void SimdScalarLowering::LowerNode(Node* node) {
WriteBarrierKind write_barrier_kind =
StoreRepresentationOf(node->op()).write_barrier_kind();
const Operator* store_op;
- if (rep_type == SimdType::kInt32) {
- store_op = machine()->Store(StoreRepresentation(
- MachineRepresentation::kWord32, write_barrier_kind));
- } else {
- store_op = machine()->Store(StoreRepresentation(
- MachineRepresentation::kFloat32, write_barrier_kind));
+#define STORE_CASE(sType, mType) \
+ case SimdType::k##sType: \
+ store_op = machine()->Store(StoreRepresentation( \
+ MachineRepresentation::k##mType, write_barrier_kind)); \
+ break;
+
+ switch (rep_type) {
+ FOREACH_SIMD_TYPE_TO_MACHINE_REP(STORE_CASE)
+ default:
+ UNREACHABLE();
}
+#undef STORE_CASE
LowerStoreOp(rep, node, store_op, rep_type);
break;
}
case IrOpcode::kUnalignedStore: {
MachineRepresentation rep = UnalignedStoreRepresentationOf(node->op());
const Operator* store_op;
- if (rep_type == SimdType::kInt32) {
- store_op = machine()->UnalignedStore(MachineRepresentation::kWord32);
- } else {
- store_op = machine()->UnalignedStore(MachineRepresentation::kFloat32);
+#define UNALIGNED_STORE_CASE(sType, mType) \
+ case SimdType::k##sType: \
+ store_op = machine()->UnalignedStore(MachineRepresentation::k##mType); \
+ break;
+
+ switch (rep_type) {
+ FOREACH_SIMD_TYPE_TO_MACHINE_REP(UNALIGNED_STORE_CASE)
+ default:
+ UNREACHABLE();
}
+#undef UNALIGNED_STORE_CASE
LowerStoreOp(rep, node, store_op, rep_type);
break;
}
@@ -541,12 +831,12 @@ void SimdScalarLowering::LowerNode(Node* node) {
if (descriptor->ReturnCount() == 1 &&
descriptor->GetReturnType(0) == MachineType::Simd128()) {
// We access the additional return values through projections.
- Node* rep_node[kMaxLanes];
- for (int i = 0; i < kMaxLanes; ++i) {
+ Node* rep_node[kNumLanes32];
+ for (int i = 0; i < kNumLanes32; ++i) {
rep_node[i] =
graph()->NewNode(common()->Projection(i), node, graph()->start());
}
- ReplaceNode(node, rep_node);
+ ReplaceNode(node, rep_node, kNumLanes32);
}
break;
}
@@ -559,7 +849,7 @@ void SimdScalarLowering::LowerNode(Node* node) {
for (int i = 0; i < node->op()->ValueInputCount(); ++i) {
Node** rep_input =
GetReplacementsWithType(node->InputAt(i), rep_type);
- for (int j = 0; j < kMaxLanes; j++) {
+ for (int j = 0; j < num_lanes; j++) {
rep_node[j]->ReplaceInput(i, rep_input[j]);
}
}
@@ -580,42 +870,93 @@ void SimdScalarLowering::LowerNode(Node* node) {
I32X4_BINOP_CASE(kS128Or, Word32Or)
I32X4_BINOP_CASE(kS128Xor, Word32Xor)
#undef I32X4_BINOP_CASE
- case IrOpcode::kI32x4MaxS: {
- LowerIntMinMax(node, machine()->Int32LessThan(), true);
+ case IrOpcode::kI16x8Add:
+ case IrOpcode::kI8x16Add: {
+ LowerBinaryOpForSmallInt(node, rep_type, machine()->Int32Add());
+ break;
+ }
+ case IrOpcode::kI16x8Sub:
+ case IrOpcode::kI8x16Sub: {
+ LowerBinaryOpForSmallInt(node, rep_type, machine()->Int32Sub());
+ break;
+ }
+ case IrOpcode::kI16x8Mul:
+ case IrOpcode::kI8x16Mul: {
+ LowerBinaryOpForSmallInt(node, rep_type, machine()->Int32Mul());
break;
}
- case IrOpcode::kI32x4MinS: {
- LowerIntMinMax(node, machine()->Int32LessThan(), false);
+ case IrOpcode::kI16x8AddSaturateS:
+ case IrOpcode::kI8x16AddSaturateS: {
+ LowerSaturateBinaryOp(node, rep_type, machine()->Int32Add(), true);
break;
}
- case IrOpcode::kI32x4MaxU: {
- LowerIntMinMax(node, machine()->Uint32LessThan(), true);
+ case IrOpcode::kI16x8SubSaturateS:
+ case IrOpcode::kI8x16SubSaturateS: {
+ LowerSaturateBinaryOp(node, rep_type, machine()->Int32Sub(), true);
break;
}
- case IrOpcode::kI32x4MinU: {
- LowerIntMinMax(node, machine()->Uint32LessThan(), false);
+ case IrOpcode::kI16x8AddSaturateU:
+ case IrOpcode::kI8x16AddSaturateU: {
+ LowerSaturateBinaryOp(node, rep_type, machine()->Int32Add(), false);
break;
}
- case IrOpcode::kI32x4Neg: {
+ case IrOpcode::kI16x8SubSaturateU:
+ case IrOpcode::kI8x16SubSaturateU: {
+ LowerSaturateBinaryOp(node, rep_type, machine()->Int32Sub(), false);
+ break;
+ }
+ case IrOpcode::kI32x4MaxS:
+ case IrOpcode::kI16x8MaxS:
+ case IrOpcode::kI8x16MaxS: {
+ LowerIntMinMax(node, machine()->Int32LessThan(), true, rep_type);
+ break;
+ }
+ case IrOpcode::kI32x4MinS:
+ case IrOpcode::kI16x8MinS:
+ case IrOpcode::kI8x16MinS: {
+ LowerIntMinMax(node, machine()->Int32LessThan(), false, rep_type);
+ break;
+ }
+ case IrOpcode::kI32x4MaxU:
+ case IrOpcode::kI16x8MaxU:
+ case IrOpcode::kI8x16MaxU: {
+ LowerIntMinMax(node, machine()->Uint32LessThan(), true, rep_type);
+ break;
+ }
+ case IrOpcode::kI32x4MinU:
+ case IrOpcode::kI16x8MinU:
+ case IrOpcode::kI8x16MinU: {
+ LowerIntMinMax(node, machine()->Uint32LessThan(), false, rep_type);
+ break;
+ }
+ case IrOpcode::kI32x4Neg:
+ case IrOpcode::kI16x8Neg:
+ case IrOpcode::kI8x16Neg: {
DCHECK(node->InputCount() == 1);
Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type);
- Node* rep_node[kMaxLanes];
+ int num_lanes = NumLanes(rep_type);
+ Node** rep_node = zone()->NewArray<Node*>(num_lanes);
Node* zero = graph()->NewNode(common()->Int32Constant(0));
- for (int i = 0; i < kMaxLanes; ++i) {
+ for (int i = 0; i < num_lanes; ++i) {
rep_node[i] = graph()->NewNode(machine()->Int32Sub(), zero, rep[i]);
+ if (node->opcode() == IrOpcode::kI16x8Neg) {
+ rep_node[i] = FixUpperBits(rep_node[i], kShift16);
+ } else if (node->opcode() == IrOpcode::kI8x16Neg) {
+ rep_node[i] = FixUpperBits(rep_node[i], kShift8);
+ }
}
- ReplaceNode(node, rep_node);
+ ReplaceNode(node, rep_node, num_lanes);
break;
}
case IrOpcode::kS128Not: {
DCHECK(node->InputCount() == 1);
Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type);
- Node* rep_node[kMaxLanes];
+ Node* rep_node[kNumLanes32];
Node* mask = graph()->NewNode(common()->Int32Constant(0xffffffff));
- for (int i = 0; i < kMaxLanes; ++i) {
+ for (int i = 0; i < kNumLanes32; ++i) {
rep_node[i] = graph()->NewNode(machine()->Word32Xor(), rep[i], mask);
}
- ReplaceNode(node, rep_node);
+ ReplaceNode(node, rep_node, kNumLanes32);
break;
}
case IrOpcode::kI32x4SConvertF32x4: {
@@ -626,16 +967,16 @@ void SimdScalarLowering::LowerNode(Node* node) {
LowerConvertFromFloat(node, false);
break;
}
- case IrOpcode::kI32x4Shl: {
- LowerShiftOp(node, machine()->Word32Shl());
- break;
- }
- case IrOpcode::kI32x4ShrS: {
- LowerShiftOp(node, machine()->Word32Sar());
- break;
- }
- case IrOpcode::kI32x4ShrU: {
- LowerShiftOp(node, machine()->Word32Shr());
+ case IrOpcode::kI32x4Shl:
+ case IrOpcode::kI16x8Shl:
+ case IrOpcode::kI8x16Shl:
+ case IrOpcode::kI32x4ShrS:
+ case IrOpcode::kI16x8ShrS:
+ case IrOpcode::kI8x16ShrS:
+ case IrOpcode::kI32x4ShrU:
+ case IrOpcode::kI16x8ShrU:
+ case IrOpcode::kI8x16ShrU: {
+ LowerShiftOp(node, rep_type);
break;
}
#define F32X4_BINOP_CASE(name) \
@@ -646,7 +987,6 @@ void SimdScalarLowering::LowerNode(Node* node) {
F32X4_BINOP_CASE(Add)
F32X4_BINOP_CASE(Sub)
F32X4_BINOP_CASE(Mul)
- F32X4_BINOP_CASE(Div)
F32X4_BINOP_CASE(Min)
F32X4_BINOP_CASE(Max)
#undef F32X4_BINOP_CASE
@@ -657,51 +997,57 @@ void SimdScalarLowering::LowerNode(Node* node) {
}
F32X4_UNOP_CASE(Abs)
F32X4_UNOP_CASE(Neg)
- F32X4_UNOP_CASE(Sqrt)
#undef F32x4_UNOP_CASE
case IrOpcode::kF32x4SConvertI32x4: {
- LowerUnaryOp(node, SimdType::kInt32, machine()->RoundInt32ToFloat32());
+ LowerUnaryOp(node, SimdType::kInt32x4, machine()->RoundInt32ToFloat32());
break;
}
case IrOpcode::kF32x4UConvertI32x4: {
- LowerUnaryOp(node, SimdType::kInt32, machine()->RoundUint32ToFloat32());
+ LowerUnaryOp(node, SimdType::kInt32x4, machine()->RoundUint32ToFloat32());
break;
}
case IrOpcode::kI32x4Splat:
- case IrOpcode::kF32x4Splat: {
- Node* rep_node[kMaxLanes];
- for (int i = 0; i < kMaxLanes; ++i) {
+ case IrOpcode::kF32x4Splat:
+ case IrOpcode::kI16x8Splat:
+ case IrOpcode::kI8x16Splat: {
+ Node** rep_node = zone()->NewArray<Node*>(num_lanes);
+ for (int i = 0; i < num_lanes; ++i) {
if (HasReplacement(0, node->InputAt(0))) {
rep_node[i] = GetReplacements(node->InputAt(0))[0];
} else {
rep_node[i] = node->InputAt(0);
}
}
- ReplaceNode(node, rep_node);
+ ReplaceNode(node, rep_node, num_lanes);
break;
}
case IrOpcode::kI32x4ExtractLane:
- case IrOpcode::kF32x4ExtractLane: {
+ case IrOpcode::kF32x4ExtractLane:
+ case IrOpcode::kI16x8ExtractLane:
+ case IrOpcode::kI8x16ExtractLane: {
int32_t lane = OpParameter<int32_t>(node);
- Node* rep_node[kMaxLanes] = {
- GetReplacementsWithType(node->InputAt(0), rep_type)[lane], nullptr,
- nullptr, nullptr};
- ReplaceNode(node, rep_node);
+ Node** rep_node = zone()->NewArray<Node*>(num_lanes);
+ rep_node[0] = GetReplacementsWithType(node->InputAt(0), rep_type)[lane];
+ for (int i = 1; i < num_lanes; ++i) {
+ rep_node[i] = nullptr;
+ }
+ ReplaceNode(node, rep_node, num_lanes);
break;
}
case IrOpcode::kI32x4ReplaceLane:
- case IrOpcode::kF32x4ReplaceLane: {
+ case IrOpcode::kF32x4ReplaceLane:
+ case IrOpcode::kI16x8ReplaceLane:
+ case IrOpcode::kI8x16ReplaceLane: {
DCHECK_EQ(2, node->InputCount());
Node* repNode = node->InputAt(1);
int32_t lane = OpParameter<int32_t>(node);
- DCHECK(lane >= 0 && lane <= 3);
Node** rep_node = GetReplacementsWithType(node->InputAt(0), rep_type);
if (HasReplacement(0, repNode)) {
rep_node[lane] = GetReplacements(repNode)[0];
} else {
rep_node[lane] = repNode;
}
- ReplaceNode(node, rep_node);
+ ReplaceNode(node, rep_node, num_lanes);
break;
}
#define COMPARISON_CASE(type, simd_op, lowering_op, invert) \
@@ -709,51 +1055,84 @@ void SimdScalarLowering::LowerNode(Node* node) {
LowerBinaryOp(node, SimdType::k##type, machine()->lowering_op(), invert); \
break; \
}
- COMPARISON_CASE(Float32, kF32x4Eq, Float32Equal, false)
- COMPARISON_CASE(Float32, kF32x4Lt, Float32LessThan, false)
- COMPARISON_CASE(Float32, kF32x4Le, Float32LessThanOrEqual, false)
- COMPARISON_CASE(Float32, kF32x4Gt, Float32LessThan, true)
- COMPARISON_CASE(Float32, kF32x4Ge, Float32LessThanOrEqual, true)
- COMPARISON_CASE(Int32, kI32x4Eq, Word32Equal, false)
- COMPARISON_CASE(Int32, kI32x4LtS, Int32LessThan, false)
- COMPARISON_CASE(Int32, kI32x4LeS, Int32LessThanOrEqual, false)
- COMPARISON_CASE(Int32, kI32x4GtS, Int32LessThan, true)
- COMPARISON_CASE(Int32, kI32x4GeS, Int32LessThanOrEqual, true)
- COMPARISON_CASE(Int32, kI32x4LtU, Uint32LessThan, false)
- COMPARISON_CASE(Int32, kI32x4LeU, Uint32LessThanOrEqual, false)
- COMPARISON_CASE(Int32, kI32x4GtU, Uint32LessThan, true)
- COMPARISON_CASE(Int32, kI32x4GeU, Uint32LessThanOrEqual, true)
+ COMPARISON_CASE(Float32x4, kF32x4Eq, Float32Equal, false)
+ COMPARISON_CASE(Float32x4, kF32x4Lt, Float32LessThan, false)
+ COMPARISON_CASE(Float32x4, kF32x4Le, Float32LessThanOrEqual, false)
+ COMPARISON_CASE(Float32x4, kF32x4Gt, Float32LessThan, true)
+ COMPARISON_CASE(Float32x4, kF32x4Ge, Float32LessThanOrEqual, true)
+ COMPARISON_CASE(Int32x4, kI32x4Eq, Word32Equal, false)
+ COMPARISON_CASE(Int32x4, kI32x4LtS, Int32LessThan, false)
+ COMPARISON_CASE(Int32x4, kI32x4LeS, Int32LessThanOrEqual, false)
+ COMPARISON_CASE(Int32x4, kI32x4GtS, Int32LessThan, true)
+ COMPARISON_CASE(Int32x4, kI32x4GeS, Int32LessThanOrEqual, true)
+ COMPARISON_CASE(Int32x4, kI32x4LtU, Uint32LessThan, false)
+ COMPARISON_CASE(Int32x4, kI32x4LeU, Uint32LessThanOrEqual, false)
+ COMPARISON_CASE(Int32x4, kI32x4GtU, Uint32LessThan, true)
+ COMPARISON_CASE(Int32x4, kI32x4GeU, Uint32LessThanOrEqual, true)
+ COMPARISON_CASE(Int16x8, kI16x8Eq, Word32Equal, false)
+ COMPARISON_CASE(Int16x8, kI16x8LtS, Int32LessThan, false)
+ COMPARISON_CASE(Int16x8, kI16x8LeS, Int32LessThanOrEqual, false)
+ COMPARISON_CASE(Int16x8, kI16x8GtS, Int32LessThan, true)
+ COMPARISON_CASE(Int16x8, kI16x8GeS, Int32LessThanOrEqual, true)
+ COMPARISON_CASE(Int16x8, kI16x8LtU, Uint32LessThan, false)
+ COMPARISON_CASE(Int16x8, kI16x8LeU, Uint32LessThanOrEqual, false)
+ COMPARISON_CASE(Int16x8, kI16x8GtU, Uint32LessThan, true)
+ COMPARISON_CASE(Int16x8, kI16x8GeU, Uint32LessThanOrEqual, true)
+ COMPARISON_CASE(Int8x16, kI8x16Eq, Word32Equal, false)
+ COMPARISON_CASE(Int8x16, kI8x16LtS, Int32LessThan, false)
+ COMPARISON_CASE(Int8x16, kI8x16LeS, Int32LessThanOrEqual, false)
+ COMPARISON_CASE(Int8x16, kI8x16GtS, Int32LessThan, true)
+ COMPARISON_CASE(Int8x16, kI8x16GeS, Int32LessThanOrEqual, true)
+ COMPARISON_CASE(Int8x16, kI8x16LtU, Uint32LessThan, false)
+ COMPARISON_CASE(Int8x16, kI8x16LeU, Uint32LessThanOrEqual, false)
+ COMPARISON_CASE(Int8x16, kI8x16GtU, Uint32LessThan, true)
+ COMPARISON_CASE(Int8x16, kI8x16GeU, Uint32LessThanOrEqual, true)
#undef COMPARISON_CASE
case IrOpcode::kF32x4Ne: {
- LowerNotEqual(node, SimdType::kFloat32, machine()->Float32Equal());
+ LowerNotEqual(node, SimdType::kFloat32x4, machine()->Float32Equal());
break;
}
case IrOpcode::kI32x4Ne: {
- LowerNotEqual(node, SimdType::kInt32, machine()->Word32Equal());
+ LowerNotEqual(node, SimdType::kInt32x4, machine()->Word32Equal());
break;
}
- case IrOpcode::kS32x4Select: {
+ case IrOpcode::kI16x8Ne: {
+ LowerNotEqual(node, SimdType::kInt16x8, machine()->Word32Equal());
+ break;
+ }
+ case IrOpcode::kI8x16Ne: {
+ LowerNotEqual(node, SimdType::kInt8x16, machine()->Word32Equal());
+ break;
+ }
+ case IrOpcode::kS32x4Select:
+ case IrOpcode::kS16x8Select:
+ case IrOpcode::kS8x16Select: {
DCHECK(node->InputCount() == 3);
- DCHECK(ReplacementType(node->InputAt(0)) == SimdType::kSimd1x4);
+ DCHECK(ReplacementType(node->InputAt(0)) == SimdType::kSimd1x4 ||
+ ReplacementType(node->InputAt(0)) == SimdType::kSimd1x8 ||
+ ReplacementType(node->InputAt(0)) == SimdType::kSimd1x16);
Node** boolean_input = GetReplacements(node->InputAt(0));
Node** rep_left = GetReplacementsWithType(node->InputAt(1), rep_type);
Node** rep_right = GetReplacementsWithType(node->InputAt(2), rep_type);
- Node* rep_node[kMaxLanes];
- for (int i = 0; i < kMaxLanes; ++i) {
+ Node** rep_node = zone()->NewArray<Node*>(num_lanes);
+ for (int i = 0; i < num_lanes; ++i) {
Diamond d(graph(), common(),
graph()->NewNode(machine()->Word32Equal(), boolean_input[i],
jsgraph_->Int32Constant(0)));
- if (rep_type == SimdType::kFloat32) {
- rep_node[i] =
- d.Phi(MachineRepresentation::kFloat32, rep_right[1], rep_left[0]);
- } else if (rep_type == SimdType::kInt32) {
- rep_node[i] =
- d.Phi(MachineRepresentation::kWord32, rep_right[1], rep_left[0]);
- } else {
- UNREACHABLE();
+#define SELECT_CASE(sType, mType) \
+ case SimdType::k##sType: \
+ rep_node[i] = \
+ d.Phi(MachineRepresentation::k##mType, rep_right[1], rep_left[0]); \
+ break;
+
+ switch (rep_type) {
+ FOREACH_SIMD_TYPE_TO_MACHINE_REP(SELECT_CASE)
+ default:
+ UNREACHABLE();
}
+#undef SELECT_CASE
}
- ReplaceNode(node, rep_node);
+ ReplaceNode(node, rep_node, num_lanes);
break;
}
default: { DefaultLowering(node); }
@@ -770,7 +1149,7 @@ bool SimdScalarLowering::DefaultLowering(Node* node) {
}
if (HasReplacement(1, input)) {
something_changed = true;
- for (int j = 1; j < kMaxLanes; j++) {
+ for (int j = 1; j < ReplacementCount(input); ++j) {
node->InsertInput(zone(), i + j, GetReplacements(input)[j]);
}
}
@@ -778,18 +1157,17 @@ bool SimdScalarLowering::DefaultLowering(Node* node) {
return something_changed;
}
-void SimdScalarLowering::ReplaceNode(Node* old, Node** new_node) {
- // if new_low == nullptr, then also new_high == nullptr.
- DCHECK(new_node[0] != nullptr ||
- (new_node[1] == nullptr && new_node[2] == nullptr &&
- new_node[3] == nullptr));
- for (int i = 0; i < kMaxLanes; ++i) {
- replacements_[old->id()].node[i] = new_node[i];
+void SimdScalarLowering::ReplaceNode(Node* old, Node** new_nodes, int count) {
+ replacements_[old->id()].node = zone()->NewArray<Node*>(count);
+ for (int i = 0; i < count; ++i) {
+ replacements_[old->id()].node[i] = new_nodes[i];
}
+ replacements_[old->id()].num_replacements = count;
}
bool SimdScalarLowering::HasReplacement(size_t index, Node* node) {
- return replacements_[node->id()].node[index] != nullptr;
+ return replacements_[node->id()].node != nullptr &&
+ replacements_[node->id()].node[index] != nullptr;
}
SimdScalarLowering::SimdType SimdScalarLowering::ReplacementType(Node* node) {
@@ -802,30 +1180,61 @@ Node** SimdScalarLowering::GetReplacements(Node* node) {
return result;
}
+int SimdScalarLowering::ReplacementCount(Node* node) {
+ return replacements_[node->id()].num_replacements;
+}
+
+void SimdScalarLowering::Int32ToFloat32(Node** replacements, Node** result) {
+ for (int i = 0; i < kNumLanes32; ++i) {
+ if (replacements[i] != nullptr) {
+ result[i] =
+ graph()->NewNode(machine()->BitcastInt32ToFloat32(), replacements[i]);
+ } else {
+ result[i] = nullptr;
+ }
+ }
+}
+
+void SimdScalarLowering::Float32ToInt32(Node** replacements, Node** result) {
+ for (int i = 0; i < kNumLanes32; ++i) {
+ if (replacements[i] != nullptr) {
+ result[i] =
+ graph()->NewNode(machine()->BitcastFloat32ToInt32(), replacements[i]);
+ } else {
+ result[i] = nullptr;
+ }
+ }
+}
+
Node** SimdScalarLowering::GetReplacementsWithType(Node* node, SimdType type) {
Node** replacements = GetReplacements(node);
if (ReplacementType(node) == type) {
return GetReplacements(node);
}
- Node** result = zone()->NewArray<Node*>(kMaxLanes);
- if (ReplacementType(node) == SimdType::kInt32 && type == SimdType::kFloat32) {
- for (int i = 0; i < kMaxLanes; ++i) {
- if (replacements[i] != nullptr) {
- result[i] = graph()->NewNode(machine()->BitcastInt32ToFloat32(),
- replacements[i]);
- } else {
- result[i] = nullptr;
- }
+ int num_lanes = NumLanes(type);
+ Node** result = zone()->NewArray<Node*>(num_lanes);
+ if (type == SimdType::kInt32x4) {
+ if (ReplacementType(node) == SimdType::kFloat32x4) {
+ Float32ToInt32(replacements, result);
+ } else if (ReplacementType(node) == SimdType::kInt16x8) {
+ UNIMPLEMENTED();
+ } else {
+ UNREACHABLE();
}
- } else if (ReplacementType(node) == SimdType::kFloat32 &&
- type == SimdType::kInt32) {
- for (int i = 0; i < kMaxLanes; ++i) {
- if (replacements[i] != nullptr) {
- result[i] = graph()->NewNode(machine()->BitcastFloat32ToInt32(),
- replacements[i]);
- } else {
- result[i] = nullptr;
- }
+ } else if (type == SimdType::kFloat32x4) {
+ if (ReplacementType(node) == SimdType::kInt32x4) {
+ Int32ToFloat32(replacements, result);
+ } else if (ReplacementType(node) == SimdType::kInt16x8) {
+ UNIMPLEMENTED();
+ } else {
+ UNREACHABLE();
+ }
+ } else if (type == SimdType::kInt16x8) {
+ if (ReplacementType(node) == SimdType::kInt32x4 ||
+ ReplacementType(node) == SimdType::kFloat32x4) {
+ UNIMPLEMENTED();
+ } else {
+ UNREACHABLE();
}
} else {
UNREACHABLE();
@@ -842,31 +1251,34 @@ void SimdScalarLowering::PreparePhiReplacement(Node* phi) {
// graph verifier.
int value_count = phi->op()->ValueInputCount();
SimdType type = ReplacementType(phi);
- Node** inputs_rep[kMaxLanes];
- for (int i = 0; i < kMaxLanes; ++i) {
+ int num_lanes = NumLanes(type);
+ Node*** inputs_rep = zone()->NewArray<Node**>(num_lanes);
+ for (int i = 0; i < num_lanes; ++i) {
inputs_rep[i] = zone()->NewArray<Node*>(value_count + 1);
inputs_rep[i][value_count] = NodeProperties::GetControlInput(phi, 0);
}
for (int i = 0; i < value_count; ++i) {
- for (int j = 0; j < kMaxLanes; j++) {
+ for (int j = 0; j < num_lanes; ++j) {
inputs_rep[j][i] = placeholder_;
}
}
- Node* rep_nodes[kMaxLanes];
- for (int i = 0; i < kMaxLanes; ++i) {
- if (type == SimdType::kInt32) {
- rep_nodes[i] = graph()->NewNode(
- common()->Phi(MachineRepresentation::kWord32, value_count),
- value_count + 1, inputs_rep[i], false);
- } else if (type == SimdType::kFloat32) {
- rep_nodes[i] = graph()->NewNode(
- common()->Phi(MachineRepresentation::kFloat32, value_count),
- value_count + 1, inputs_rep[i], false);
- } else {
- UNREACHABLE();
+ Node** rep_nodes = zone()->NewArray<Node*>(num_lanes);
+ for (int i = 0; i < num_lanes; ++i) {
+#define PHI_CASE(sType, mType) \
+ case SimdType::k##sType: \
+ rep_nodes[i] = graph()->NewNode( \
+ common()->Phi(MachineRepresentation::k##mType, value_count), \
+ value_count + 1, inputs_rep[i], false); \
+ break;
+
+ switch (type) {
+ FOREACH_SIMD_TYPE_TO_MACHINE_REP(PHI_CASE)
+ default:
+ UNREACHABLE();
}
+#undef PHI_CASE
}
- ReplaceNode(phi, rep_nodes);
+ ReplaceNode(phi, rep_nodes, num_lanes);
}
}
} // namespace compiler