[wasm]implement simd lowering for packing integer conversions

I16x8SConvertI32x4, I16x8UConvertI32x4,
I8x16SConvertI16x8, I8x16UConvertI16x8

Change-Id: Iab462c3fb6c60de7b54a925e438862362605fe8d
Reviewed-on: https://chromium-review.googlesource.com/1016178
Reviewed-by: Aseem Garg <aseemgarg@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Commit-Queue: Jing Bao <jing.bao@intel.com>
Cr-Commit-Position: refs/heads/master@{#52771}
This commit is contained in:
jing.bao 2018-04-18 16:47:06 +08:00 committed by Commit Bot
parent 9b3dafb99a
commit 2aa995bf9b
3 changed files with 92 additions and 3 deletions

View File

@ -147,6 +147,7 @@ void SimdScalarLowering::LowerGraph() {
V(I16x8Neg) \
V(I16x8Shl) \
V(I16x8ShrS) \
V(I16x8SConvertI32x4) \
V(I16x8Add) \
V(I16x8AddSaturateS) \
V(I16x8AddHoriz) \
@ -156,6 +157,7 @@ void SimdScalarLowering::LowerGraph() {
V(I16x8MinS) \
V(I16x8MaxS) \
V(I16x8ShrU) \
V(I16x8UConvertI32x4) \
V(I16x8AddSaturateU) \
V(I16x8SubSaturateU) \
V(I16x8MinU) \
@ -171,6 +173,7 @@ void SimdScalarLowering::LowerGraph() {
V(I8x16Splat) \
V(I8x16ExtractLane) \
V(I8x16ReplaceLane) \
V(I8x16SConvertI16x8) \
V(I8x16Neg) \
V(I8x16Shl) \
V(I8x16ShrS) \
@ -182,6 +185,7 @@ void SimdScalarLowering::LowerGraph() {
V(I8x16MinS) \
V(I8x16MaxS) \
V(I8x16ShrU) \
V(I8x16UConvertI16x8) \
V(I8x16AddSaturateU) \
V(I8x16SubSaturateU) \
V(I8x16MinU) \
@ -237,9 +241,16 @@ void SimdScalarLowering::SetLoweredType(Node* node, Node* output) {
default: {
switch (output->opcode()) {
case IrOpcode::kF32x4SConvertI32x4:
case IrOpcode::kF32x4UConvertI32x4: {
case IrOpcode::kF32x4UConvertI32x4:
case IrOpcode::kI16x8SConvertI32x4:
case IrOpcode::kI16x8UConvertI32x4: {
replacements_[node->id()].type = SimdType::kInt32x4;
break;
}
case IrOpcode::kI8x16SConvertI16x8:
case IrOpcode::kI8x16UConvertI16x8: {
replacements_[node->id()].type = SimdType::kInt16x8;
break;
}
FOREACH_FLOAT32X4_TO_INT32X4OPCODE(CASE_STMT)
case IrOpcode::kI32x4SConvertF32x4:
@ -669,6 +680,66 @@ void SimdScalarLowering::LowerConvertFromFloat(Node* node, bool is_signed) {
ReplaceNode(node, rep_node, kNumLanes32);
}
void SimdScalarLowering::LowerPack(Node* node, SimdType input_rep_type,
SimdType output_rep_type, bool is_signed) {
DCHECK_EQ(2, node->InputCount());
Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type);
const Operator* less_op =
is_signed ? machine()->Int32LessThan() : machine()->Uint32LessThan();
Node* min = nullptr;
Node* max = nullptr;
int32_t shift_val = 0;
MachineRepresentation phi_rep;
if (output_rep_type == SimdType::kInt16x8) {
DCHECK(input_rep_type == SimdType::kInt32x4);
if (is_signed) {
min = jsgraph_->Int32Constant(std::numeric_limits<int16_t>::min());
max = jsgraph_->Int32Constant(std::numeric_limits<int16_t>::max());
} else {
max = jsgraph_->Uint32Constant(std::numeric_limits<uint16_t>::max());
shift_val = kShift16;
}
phi_rep = MachineRepresentation::kWord16;
} else {
DCHECK(output_rep_type == SimdType::kInt8x16 &&
input_rep_type == SimdType::kInt16x8);
if (is_signed) {
min = jsgraph_->Int32Constant(std::numeric_limits<int8_t>::min());
max = jsgraph_->Int32Constant(std::numeric_limits<int8_t>::max());
} else {
max = jsgraph_->Uint32Constant(std::numeric_limits<uint8_t>::max());
shift_val = kShift8;
}
phi_rep = MachineRepresentation::kWord8;
}
int num_lanes = NumLanes(output_rep_type);
Node** rep_node = zone()->NewArray<Node*>(num_lanes);
for (int i = 0; i < num_lanes; ++i) {
Node* input = nullptr;
#if defined(V8_TARGET_BIG_ENDIAN)
if (i < num_lanes / 2)
input = rep_right[i];
else
input = rep_left[i - num_lanes / 2];
#else
if (i < num_lanes / 2)
input = rep_left[i];
else
input = rep_right[i - num_lanes / 2];
#endif
if (is_signed) {
Diamond d_min(graph(), common(), graph()->NewNode(less_op, input, min));
input = d_min.Phi(phi_rep, min, input);
}
Diamond d_max(graph(), common(), graph()->NewNode(less_op, max, input));
rep_node[i] = d_max.Phi(phi_rep, max, input);
rep_node[i] =
is_signed ? rep_node[i] : FixUpperBits(rep_node[i], shift_val);
}
ReplaceNode(node, rep_node, num_lanes);
}
void SimdScalarLowering::LowerShiftOp(Node* node, SimdType type) {
DCHECK_EQ(1, node->InputCount());
int32_t shift_amount = OpParameter<int32_t>(node->op());
@ -999,6 +1070,22 @@ void SimdScalarLowering::LowerNode(Node* node) {
LowerConvertFromFloat(node, false);
break;
}
case IrOpcode::kI16x8SConvertI32x4: {
LowerPack(node, SimdType::kInt32x4, SimdType::kInt16x8, true);
break;
}
case IrOpcode::kI16x8UConvertI32x4: {
LowerPack(node, SimdType::kInt32x4, SimdType::kInt16x8, false);
break;
}
case IrOpcode::kI8x16SConvertI16x8: {
LowerPack(node, SimdType::kInt16x8, SimdType::kInt8x16, true);
break;
}
case IrOpcode::kI8x16UConvertI16x8: {
LowerPack(node, SimdType::kInt16x8, SimdType::kInt8x16, false);
break;
}
case IrOpcode::kI32x4Shl:
case IrOpcode::kI16x8Shl:
case IrOpcode::kI8x16Shl:

View File

@ -87,6 +87,8 @@ class SimdScalarLowering {
void LowerIntMinMax(Node* node, const Operator* op, bool is_max,
SimdType type);
void LowerConvertFromFloat(Node* node, bool is_signed);
void LowerPack(Node* node, SimdType input_rep_type, SimdType output_rep_type,
bool is_signed);
void LowerShiftOp(Node* node, SimdType type);
Node* BuildF64Trunc(Node* input);
void LowerNotEqual(Node* node, SimdType input_rep_type, const Operator* op);

View File

@ -1090,7 +1090,7 @@ WASM_SIMD_TEST(I16x8Neg) {
#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_MIPS || \
V8_TARGET_ARCH_MIPS64
// Tests both signed and unsigned conversion from I32x4 (packing).
WASM_SIMD_COMPILED_TEST(I16x8ConvertI32x4) {
WASM_SIMD_TEST(I16x8ConvertI32x4) {
WasmRunner<int32_t, int32_t, int32_t, int32_t> r(kExecuteTurbofan,
lower_simd);
byte a = 0;
@ -1284,7 +1284,7 @@ WASM_SIMD_TEST(I8x16Neg) {
#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_MIPS || \
V8_TARGET_ARCH_MIPS64
// Tests both signed and unsigned conversion from I16x8 (packing).
WASM_SIMD_COMPILED_TEST(I8x16ConvertI16x8) {
WASM_SIMD_TEST(I8x16ConvertI16x8) {
WasmRunner<int32_t, int32_t, int32_t, int32_t> r(kExecuteTurbofan,
lower_simd);
byte a = 0;