OSDN Git Service

[WebAssembly] SIMD Splats
authorDerek Schuff <dschuff@google.com>
Wed, 15 Aug 2018 00:30:27 +0000 (00:30 +0000)
committerDerek Schuff <dschuff@google.com>
Wed, 15 Aug 2018 00:30:27 +0000 (00:30 +0000)
Implement and test SIMD splat ops.

Patch by Thomas Lively

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@339744 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
test/CodeGen/WebAssembly/simd.ll

index 1c0090e..fc91b57 100644 (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
index 134f41f..50d8b68 100644 (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