[WebAssembly] SIMD Splats

Implement and test SIMD splat ops.

Patch by Thomas Lively

Differential Revision: https://reviews.llvm.org/D50741

llvm-svn: 339744
This commit is contained in:
Derek Schuff 2018-08-15 00:30:27 +00:00
parent 7c6baa2184
commit 4ec8bca13e
2 changed files with 107 additions and 0 deletions

View File

@ -74,6 +74,34 @@ def : Pat<(i32 (vector_extract (v16i8 V128:$vec), (i32 LaneIdx16:$idx))),
def : Pat<(i32 (vector_extract (v8i16 V128:$vec), (i32 LaneIdx8:$idx))),
(EXTRACT_LANE_U_I16x8 V128:$vec, (i32 LaneIdx8:$idx))>;
// splats
def splat2 : PatFrag<(ops node:$x), (build_vector node:$x, node:$x)>;
def splat4 : PatFrag<(ops node:$x), (build_vector
node:$x, node:$x, node:$x, node:$x)>;
def splat8 : PatFrag<(ops node:$x), (build_vector
node:$x, node:$x, node:$x, node:$x,
node:$x, node:$x, node:$x, node:$x)>;
def splat16 : PatFrag<(ops node:$x), (build_vector
node:$x, node:$x, node:$x, node:$x,
node:$x, node:$x, node:$x, node:$x,
node:$x, node:$x, node:$x, node:$x,
node:$x, node:$x, node:$x, node:$x)>;
multiclass Splat<ValueType vec_t, string name, WebAssemblyRegClass reg_t,
PatFrag splat_pat, bits<32> simdop> {
defm SPLAT_#vec_t : SIMD_I<(outs V128:$dst), (ins reg_t:$x), (outs), (ins),
[(set (vec_t V128:$dst), (splat_pat reg_t:$x))],
name#".splat\t$dst, $x", name#".splat", simdop>;
}
let Defs = [ARGUMENTS] in {
defm "" : Splat<v16i8, "i8x16", I32, splat16, 3>;
defm "" : Splat<v8i16, "i16x8", I32, splat8, 4>;
defm "" : Splat<v4i32, "i32x4", I32, splat4, 5>;
defm "" : Splat<v2i64, "i64x2", I64, splat2, 6>;
defm "" : Splat<v4f32, "f32x4", F32, splat4, 7>;
defm "" : Splat<v2f64, "f64x2", F64, splat2, 8>;
}
// arithmetic
let Defs = [ARGUMENTS] in {
let isCommutable = 1 in

View File

@ -10,6 +10,20 @@ target triple = "wasm32-unknown-unknown"
; ==============================================================================
; 16 x i8
; ==============================================================================
; CHECK-LABEL: splat_v16i8:
; NO-SIMD128-NOT: i8x16
; SIMD128: .param i32{{$}}
; SIMD128: .result v128{{$}}
; SIMD128: i8x16.splat $push0=, $0 # encoding: [0xfd,0x03]{{$}}
; SIMD128: return $pop0 # encoding: [0x0f]{{$}}
define <16 x i8> @splat_v16i8(i8 %x) {
%v = insertelement <16 x i8> undef, i8 %x, i32 0
%res = shufflevector <16 x i8> %v, <16 x i8> undef,
<16 x i32> <i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0,
i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0>
ret <16 x i8> %res
}
; CHECK-LABEL: extract_v16i8_s:
; NO-SIMD128-NOT: i8x16
; SIMD128: .param v128{{$}}
@ -48,6 +62,19 @@ define i8 @extract_v16i8(<16 x i8> %v) {
; ==============================================================================
; 8 x i16
; ==============================================================================
; CHECK-LABEL: splat_v8i16:
; NO-SIMD128-NOT: i16x8
; SIMD128: .param i32{{$}}
; SIMD128: .result v128{{$}}
; SIMD128: i16x8.splat $push0=, $0 # encoding: [0xfd,0x04]{{$}}
; SIMD128: return $pop0 # encoding: [0x0f]{{$}}
define <8 x i16> @splat_v8i16(i16 %x) {
%v = insertelement <8 x i16> undef, i16 %x, i32 0
%res = shufflevector <8 x i16> %v, <8 x i16> undef,
<8 x i32> <i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0>
ret <8 x i16> %res
}
; CHECK-LABEL: extract_v8i16_s:
; NO-SIMD128-NOT: i16x8
; SIMD128: .param v128{{$}}
@ -86,6 +113,19 @@ define i16 @extract_v8i16(<8 x i16> %v) {
; ==============================================================================
; 4 x i32
; ==============================================================================
; CHECK-LABEL: splat_v4i32:
; NO-SIMD128-NOT: i32x4
; SIMD128: .param i32{{$}}
; SIMD128: .result v128{{$}}
; SIMD128: i32x4.splat $push0=, $0 # encoding: [0xfd,0x05]{{$}}
; SIMD128: return $pop0 # encoding: [0x0f]{{$}}
define <4 x i32> @splat_v4i32(i32 %x) {
%v = insertelement <4 x i32> undef, i32 %x, i32 0
%res = shufflevector <4 x i32> %v, <4 x i32> undef,
<4 x i32> <i32 0, i32 0, i32 0, i32 0>
ret <4 x i32> %res
}
; CHECK-LABEL: extract_v4i32:
; NO-SIMD128-NOT: i32x4
; SIMD128: .param v128{{$}}
@ -100,6 +140,19 @@ define i32 @extract_v4i32(<4 x i32> %v) {
; ==============================================================================
; 2 x i64
; ==============================================================================
; CHECK-LABEL: splat_v2i64:
; NO-SIMD128-NOT: i64x2
; SIMD128-VM-NOT: i64x2
; SIMD128: .param i64{{$}}
; SIMD128: .result v128{{$}}
; SIMD128: i64x2.splat $push0=, $0 # encoding: [0xfd,0x06]{{$}}
; SIMD128: return $pop0 # encoding: [0x0f]{{$}}
define <2 x i64> @splat_v2i64(i64 %x) {
%t1 = insertelement <2 x i64> zeroinitializer, i64 %x, i32 0
%res = insertelement <2 x i64> %t1, i64 %x, i32 1
ret <2 x i64> %res
}
; CHECK-LABEL: extract_v2i64:
; NO-SIMD128-NOT: i64x2
; SIMD128-VM-NOT: i64x2
@ -115,6 +168,19 @@ define i64 @extract_v2i64(<2 x i64> %v) {
; ==============================================================================
; 4 x f32
; ==============================================================================
; CHECK-LABEL: splat_v4f32:
; NO-SIMD128-NOT: f32x4
; SIMD128: .param f32{{$}}
; SIMD128: .result v128{{$}}
; SIMD128: f32x4.splat $push0=, $0 # encoding: [0xfd,0x07]{{$}}
; SIMD128: return $pop0 # encoding: [0x0f]{{$}}
define <4 x float> @splat_v4f32(float %x) {
%v = insertelement <4 x float> undef, float %x, i32 0
%res = shufflevector <4 x float> %v, <4 x float> undef,
<4 x i32> <i32 0, i32 0, i32 0, i32 0>
ret <4 x float> %res
}
; CHECK-LABEL: extract_v4f32:
; NO-SIMD128-NOT: f32x4
; SIMD128: .param v128{{$}}
@ -129,6 +195,19 @@ define float @extract_v4f32(<4 x float> %v) {
; ==============================================================================
; 2 x f64
; ==============================================================================
; CHECK-LABEL: splat_v2f64:
; NO-SIMD128-NOT: f64x2
; SIMD128-VM-NOT: f64x2
; SIMD128: .param f64{{$}}
; SIMD128: .result v128{{$}}
; SIMD128: f64x2.splat $push0=, $0 # encoding: [0xfd,0x08]{{$}}
; SIMD128: return $pop0 # encoding: [0x0f]{{$}}
define <2 x double> @splat_v2f64(double %x) {
%t1 = insertelement <2 x double> zeroinitializer, double %x, i3 0
%res = insertelement <2 x double> %t1, double %x, i32 1
ret <2 x double> %res
}
; CHECK-LABEL: extract_v2f64:
; NO-SIMD128-NOT: f64x2
; SIMD128-VM-NOT: f64x2