blob: 08b925aeee90997c403ee047512fd2e7ad13ab07 [file] [log] [blame]
Dan Gohman10e730a2015-06-29 23:51:55 +00001// WebAssemblyInstrSIMD.td - WebAssembly SIMD codegen support -*- tablegen -*-//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
JF Bastien5ca0bac2015-07-10 18:23:10 +00009///
10/// \file
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000011/// WebAssembly SIMD operand code-gen constructs.
JF Bastien5ca0bac2015-07-10 18:23:10 +000012///
Dan Gohman10e730a2015-06-29 23:51:55 +000013//===----------------------------------------------------------------------===//
14
Thomas Lively22442922018-08-21 21:03:18 +000015// constrained immediate argument types
16foreach SIZE = [8, 16] in
17def ImmI#SIZE : ImmLeaf<i32, "return (Imm & ((1UL << "#SIZE#") - 1)) == Imm;">;
Heejin Ahna0fd9c32018-08-14 18:53:27 +000018foreach SIZE = [2, 4, 8, 16, 32] in
19def LaneIdx#SIZE : ImmLeaf<i32, "return 0 <= Imm && Imm < "#SIZE#";">;
Derek Schuff51ed1312018-08-07 21:24:01 +000020
Thomas Lively22442922018-08-21 21:03:18 +000021// const vectors
22multiclass ConstVec<ValueType vec_t, dag ops, dag pat, string args> {
23 defm CONST_V128_#vec_t : SIMD_I<(outs V128:$dst), ops, (outs), ops,
24 [(set V128:$dst, (vec_t pat))],
25 "v128.const\t$dst, "#args,
26 "v128.const\t"#args, 0>;
27}
28defm "" : ConstVec<v16i8,
29 (ins vec_i8imm_op:$i0, vec_i8imm_op:$i1,
30 vec_i8imm_op:$i2, vec_i8imm_op:$i3,
31 vec_i8imm_op:$i4, vec_i8imm_op:$i5,
32 vec_i8imm_op:$i6, vec_i8imm_op:$i7,
33 vec_i8imm_op:$i8, vec_i8imm_op:$i9,
34 vec_i8imm_op:$iA, vec_i8imm_op:$iB,
35 vec_i8imm_op:$iC, vec_i8imm_op:$iD,
36 vec_i8imm_op:$iE, vec_i8imm_op:$iF),
37 (build_vector ImmI8:$i0, ImmI8:$i1, ImmI8:$i2, ImmI8:$i3,
38 ImmI8:$i4, ImmI8:$i5, ImmI8:$i6, ImmI8:$i7,
39 ImmI8:$i8, ImmI8:$i9, ImmI8:$iA, ImmI8:$iB,
40 ImmI8:$iC, ImmI8:$iD, ImmI8:$iE, ImmI8:$iF),
41 !strconcat("$i0, $i1, $i2, $i3, $i4, $i5, $i6, $i7, ",
42 "$i8, $i9, $iA, $iB, $iC, $iD, $iE, $iF")>;
43defm "" : ConstVec<v8i16,
44 (ins vec_i16imm_op:$i0, vec_i16imm_op:$i1,
45 vec_i16imm_op:$i2, vec_i16imm_op:$i3,
46 vec_i16imm_op:$i4, vec_i16imm_op:$i5,
47 vec_i16imm_op:$i6, vec_i16imm_op:$i7),
48 (build_vector
49 ImmI16:$i0, ImmI16:$i1, ImmI16:$i2, ImmI16:$i3,
50 ImmI16:$i4, ImmI16:$i5, ImmI16:$i6, ImmI16:$i7),
51 "$i0, $i1, $i2, $i3, $i4, $i5, $i6, $i7">;
52defm "" : ConstVec<v4i32,
53 (ins vec_i32imm_op:$i0, vec_i32imm_op:$i1,
54 vec_i32imm_op:$i2, vec_i32imm_op:$i3),
55 (build_vector (i32 imm:$i0), (i32 imm:$i1),
56 (i32 imm:$i2), (i32 imm:$i3)),
57 "$i0, $i1, $i2, $i3">;
58defm "" : ConstVec<v2i64,
59 (ins vec_i64imm_op:$i0, vec_i64imm_op:$i1),
60 (build_vector (i64 imm:$i0), (i64 imm:$i1)),
61 "$i0, $i1">;
62defm "" : ConstVec<v4f32,
63 (ins f32imm_op:$i0, f32imm_op:$i1,
64 f32imm_op:$i2, f32imm_op:$i3),
65 (build_vector (f32 fpimm:$i0), (f32 fpimm:$i1),
66 (f32 fpimm:$i2), (f32 fpimm:$i3)),
67 "$i0, $i1, $i2, $i3">;
68defm "" : ConstVec<v2f64,
69 (ins f64imm_op:$i0, f64imm_op:$i1),
70 (build_vector (f64 fpimm:$i0), (f64 fpimm:$i1)),
71 "$i0, $i1">;
72
Heejin Ahna0fd9c32018-08-14 18:53:27 +000073// lane extraction
Thomas Lively5222cb62018-08-15 18:15:18 +000074multiclass ExtractLane<ValueType vec_t, string vec, ImmLeaf imm_t,
75 WebAssemblyRegClass reg_t, bits<32> simdop,
76 string suffix = "", SDNode extract = vector_extract> {
77 defm EXTRACT_LANE_#vec_t#suffix :
Thomas Lively22442922018-08-21 21:03:18 +000078 SIMD_I<(outs reg_t:$dst), (ins V128:$vec, i32imm_op:$idx),
79 (outs), (ins i32imm_op:$idx),
Thomas Lively5222cb62018-08-15 18:15:18 +000080 [(set reg_t:$dst, (extract (vec_t V128:$vec), (i32 imm_t:$idx)))],
81 vec#".extract_lane"#suffix#"\t$dst, $vec, $idx",
82 vec#".extract_lane"#suffix#"\t$idx", simdop>;
Heejin Ahna0fd9c32018-08-14 18:53:27 +000083}
84multiclass ExtractPat<ValueType lane_t, int mask> {
85 def _s : PatFrag<(ops node:$vec, node:$idx),
86 (i32 (sext_inreg
87 (i32 (vector_extract
88 node:$vec,
89 node:$idx
90 )),
91 lane_t
92 ))>;
93 def _u : PatFrag<(ops node:$vec, node:$idx),
94 (i32 (and
95 (i32 (vector_extract
96 node:$vec,
97 node:$idx
98 )),
99 (i32 mask)
100 ))>;
101}
102defm extract_i8x16 : ExtractPat<i8, 0xff>;
103defm extract_i16x8 : ExtractPat<i16, 0xffff>;
104multiclass ExtractLaneExtended<string sign, bits<32> baseInst> {
Thomas Lively5222cb62018-08-15 18:15:18 +0000105 defm "" : ExtractLane<v16i8, "i8x16", LaneIdx16, I32, baseInst, sign,
106 !cast<PatFrag>("extract_i8x16"#sign)>;
107 defm "" : ExtractLane<v8i16, "i16x8", LaneIdx8, I32, !add(baseInst, 2), sign,
108 !cast<PatFrag>("extract_i16x8"#sign)>;
Heejin Ahna0fd9c32018-08-14 18:53:27 +0000109}
Heejin Ahna0fd9c32018-08-14 18:53:27 +0000110let Defs = [ARGUMENTS] in {
Thomas Lively5222cb62018-08-15 18:15:18 +0000111defm "" : ExtractLaneExtended<"_s", 9>;
112defm "" : ExtractLaneExtended<"_u", 10>;
113defm "" : ExtractLane<v4i32, "i32x4", LaneIdx4, I32, 13>;
114defm "" : ExtractLane<v2i64, "i64x2", LaneIdx2, I64, 14>;
115defm "" : ExtractLane<v4f32, "f32x4", LaneIdx4, F32, 15>;
116defm "" : ExtractLane<v2f64, "f64x2", LaneIdx2, F64, 16>;
Heejin Ahna0fd9c32018-08-14 18:53:27 +0000117} // Defs = [ARGUMENTS]
118
119// follow convention of making implicit expansions unsigned
120def : Pat<(i32 (vector_extract (v16i8 V128:$vec), (i32 LaneIdx16:$idx))),
Thomas Lively5222cb62018-08-15 18:15:18 +0000121 (EXTRACT_LANE_v16i8_u V128:$vec, (i32 LaneIdx16:$idx))>;
Heejin Ahna0fd9c32018-08-14 18:53:27 +0000122def : Pat<(i32 (vector_extract (v8i16 V128:$vec), (i32 LaneIdx8:$idx))),
Thomas Lively5222cb62018-08-15 18:15:18 +0000123 (EXTRACT_LANE_v8i16_u V128:$vec, (i32 LaneIdx8:$idx))>;
Heejin Ahna0fd9c32018-08-14 18:53:27 +0000124
Derek Schuff82812fb2018-08-15 16:18:51 +0000125// lane replacement
126multiclass ReplaceLane<ValueType vec_t, string vec, WebAssemblyRegClass reg_t,
127 ValueType lane_t, ImmLeaf imm_t, bits<32> simdop> {
Thomas Lively5222cb62018-08-15 18:15:18 +0000128 defm REPLACE_LANE_#vec_t :
Thomas Lively22442922018-08-21 21:03:18 +0000129 SIMD_I<(outs V128:$dst), (ins V128:$vec, i32imm_op:$idx, reg_t:$x),
130 (outs), (ins i32imm_op:$idx),
Thomas Lively5222cb62018-08-15 18:15:18 +0000131 [(set V128:$dst, (vector_insert
132 (vec_t V128:$vec), (lane_t reg_t:$x), (i32 imm_t:$idx)))],
133 vec#".replace_lane\t$dst, $vec, $idx, $x",
134 vec#".replace_lane\t$idx", simdop>;
Derek Schuff82812fb2018-08-15 16:18:51 +0000135}
136let Defs = [ARGUMENTS] in {
137defm "" : ReplaceLane<v16i8, "i8x16", I32, i32, LaneIdx16, 17>;
138defm "" : ReplaceLane<v8i16, "i16x8", I32, i32, LaneIdx8, 18>;
139defm "" : ReplaceLane<v4i32, "i32x4", I32, i32, LaneIdx4, 19>;
140defm "" : ReplaceLane<v2i64, "i64x2", I64, i64, LaneIdx2, 20>;
141defm "" : ReplaceLane<v4f32, "f32x4", F32, f32, LaneIdx4, 21>;
142defm "" : ReplaceLane<v2f64, "f64x2", F64, f64, LaneIdx2, 22>;
143} // Defs = [ARGUMENTS]
Derek Schuff4ec8bca2018-08-15 00:30:27 +0000144
145// splats
146def splat2 : PatFrag<(ops node:$x), (build_vector node:$x, node:$x)>;
147def splat4 : PatFrag<(ops node:$x), (build_vector
148 node:$x, node:$x, node:$x, node:$x)>;
149def splat8 : PatFrag<(ops node:$x), (build_vector
150 node:$x, node:$x, node:$x, node:$x,
151 node:$x, node:$x, node:$x, node:$x)>;
152def splat16 : PatFrag<(ops node:$x), (build_vector
153 node:$x, node:$x, node:$x, node:$x,
154 node:$x, node:$x, node:$x, node:$x,
155 node:$x, node:$x, node:$x, node:$x,
156 node:$x, node:$x, node:$x, node:$x)>;
Thomas Lively5222cb62018-08-15 18:15:18 +0000157multiclass Splat<ValueType vec_t, string vec, WebAssemblyRegClass reg_t,
Derek Schuff4ec8bca2018-08-15 00:30:27 +0000158 PatFrag splat_pat, bits<32> simdop> {
159 defm SPLAT_#vec_t : SIMD_I<(outs V128:$dst), (ins reg_t:$x), (outs), (ins),
160 [(set (vec_t V128:$dst), (splat_pat reg_t:$x))],
Thomas Lively5222cb62018-08-15 18:15:18 +0000161 vec#".splat\t$dst, $x", vec#".splat", simdop>;
Derek Schuff4ec8bca2018-08-15 00:30:27 +0000162}
163let Defs = [ARGUMENTS] in {
164defm "" : Splat<v16i8, "i8x16", I32, splat16, 3>;
165defm "" : Splat<v8i16, "i16x8", I32, splat8, 4>;
166defm "" : Splat<v4i32, "i32x4", I32, splat4, 5>;
167defm "" : Splat<v2i64, "i64x2", I64, splat2, 6>;
168defm "" : Splat<v4f32, "f32x4", F32, splat4, 7>;
169defm "" : Splat<v2f64, "f64x2", F64, splat2, 8>;
Derek Schuff82812fb2018-08-15 16:18:51 +0000170} // Defs = [ARGUMENTS]
Derek Schuff4ec8bca2018-08-15 00:30:27 +0000171
Heejin Ahna0fd9c32018-08-14 18:53:27 +0000172// arithmetic
173let Defs = [ARGUMENTS] in {
Derek Schuff51ed1312018-08-07 21:24:01 +0000174let isCommutable = 1 in
175defm ADD : SIMDBinaryInt<add, "add ", 24>;
176defm SUB : SIMDBinaryInt<sub, "sub ", 28>;
177let isCommutable = 1 in
178defm MUL : SIMDBinaryInt<mul, "mul ", 32>;
Derek Schuff51ed1312018-08-07 21:24:01 +0000179let isCommutable = 1 in
180defm ADD : SIMDBinaryFP<fadd, "add ", 122>;
181defm SUB : SIMDBinaryFP<fsub, "sub ", 124>;
182defm DIV : SIMDBinaryFP<fdiv, "div ", 126>;
183let isCommutable = 1 in
184defm MUL : SIMDBinaryFP<fmul, "mul ", 128>;
Derek Schuff51ed1312018-08-07 21:24:01 +0000185} // Defs = [ARGUMENTS]