Dan Gohman | 10e730a | 2015-06-29 23:51:55 +0000 | [diff] [blame] | 1 | // 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 Bastien | 5ca0bac | 2015-07-10 18:23:10 +0000 | [diff] [blame] | 9 | /// |
| 10 | /// \file |
Adrian Prantl | 5f8f34e4 | 2018-05-01 15:54:18 +0000 | [diff] [blame] | 11 | /// WebAssembly SIMD operand code-gen constructs. |
JF Bastien | 5ca0bac | 2015-07-10 18:23:10 +0000 | [diff] [blame] | 12 | /// |
Dan Gohman | 10e730a | 2015-06-29 23:51:55 +0000 | [diff] [blame] | 13 | //===----------------------------------------------------------------------===// |
| 14 | |
Thomas Lively | 2244292 | 2018-08-21 21:03:18 +0000 | [diff] [blame] | 15 | // constrained immediate argument types |
| 16 | foreach SIZE = [8, 16] in |
| 17 | def ImmI#SIZE : ImmLeaf<i32, "return (Imm & ((1UL << "#SIZE#") - 1)) == Imm;">; |
Heejin Ahn | a0fd9c3 | 2018-08-14 18:53:27 +0000 | [diff] [blame] | 18 | foreach SIZE = [2, 4, 8, 16, 32] in |
| 19 | def LaneIdx#SIZE : ImmLeaf<i32, "return 0 <= Imm && Imm < "#SIZE#";">; |
Derek Schuff | 51ed131 | 2018-08-07 21:24:01 +0000 | [diff] [blame] | 20 | |
Thomas Lively | 2244292 | 2018-08-21 21:03:18 +0000 | [diff] [blame] | 21 | // const vectors |
| 22 | multiclass 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 | } |
Thomas Lively | 123c3bb | 2018-08-23 00:43:47 +0000 | [diff] [blame^] | 28 | multiclass ExtractLane<ValueType vec_t, string vec, ImmLeaf imm_t, |
| 29 | WebAssemblyRegClass reg_t, bits<32> simdop, |
| 30 | string suffix = "", SDNode extract = vector_extract> { |
| 31 | defm EXTRACT_LANE_#vec_t#suffix : |
| 32 | SIMD_I<(outs reg_t:$dst), (ins V128:$vec, i32imm_op:$idx), |
| 33 | (outs), (ins i32imm_op:$idx), |
| 34 | [(set reg_t:$dst, (extract (vec_t V128:$vec), (i32 imm_t:$idx)))], |
| 35 | vec#".extract_lane"#suffix#"\t$dst, $vec, $idx", |
| 36 | vec#".extract_lane"#suffix#"\t$idx", simdop>; |
| 37 | } |
| 38 | multiclass ExtractPat<ValueType lane_t, int mask> { |
| 39 | def _s : PatFrag<(ops node:$vec, node:$idx), |
| 40 | (i32 (sext_inreg |
| 41 | (i32 (vector_extract |
| 42 | node:$vec, |
| 43 | node:$idx |
| 44 | )), |
| 45 | lane_t |
| 46 | ))>; |
| 47 | def _u : PatFrag<(ops node:$vec, node:$idx), |
| 48 | (i32 (and |
| 49 | (i32 (vector_extract |
| 50 | node:$vec, |
| 51 | node:$idx |
| 52 | )), |
| 53 | (i32 mask) |
| 54 | ))>; |
| 55 | } |
| 56 | defm extract_i8x16 : ExtractPat<i8, 0xff>; |
| 57 | defm extract_i16x8 : ExtractPat<i16, 0xffff>; |
| 58 | multiclass ExtractLaneExtended<string sign, bits<32> baseInst> { |
| 59 | defm "" : ExtractLane<v16i8, "i8x16", LaneIdx16, I32, baseInst, sign, |
| 60 | !cast<PatFrag>("extract_i8x16"#sign)>; |
| 61 | defm "" : ExtractLane<v8i16, "i16x8", LaneIdx8, I32, !add(baseInst, 2), sign, |
| 62 | !cast<PatFrag>("extract_i16x8"#sign)>; |
| 63 | } |
| 64 | multiclass ReplaceLane<ValueType vec_t, string vec, ImmLeaf imm_t, |
| 65 | WebAssemblyRegClass reg_t, ValueType lane_t, |
| 66 | bits<32> simdop> { |
| 67 | defm REPLACE_LANE_#vec_t : |
| 68 | SIMD_I<(outs V128:$dst), (ins V128:$vec, i32imm_op:$idx, reg_t:$x), |
| 69 | (outs), (ins i32imm_op:$idx), |
| 70 | [(set V128:$dst, (vector_insert |
| 71 | (vec_t V128:$vec), (lane_t reg_t:$x), (i32 imm_t:$idx)))], |
| 72 | vec#".replace_lane\t$dst, $vec, $idx, $x", |
| 73 | vec#".replace_lane\t$idx", simdop>; |
| 74 | } |
| 75 | def splat2 : PatFrag<(ops node:$x), (build_vector node:$x, node:$x)>; |
| 76 | def splat4 : PatFrag<(ops node:$x), (build_vector |
| 77 | node:$x, node:$x, node:$x, node:$x)>; |
| 78 | def splat8 : PatFrag<(ops node:$x), (build_vector |
| 79 | node:$x, node:$x, node:$x, node:$x, |
| 80 | node:$x, node:$x, node:$x, node:$x)>; |
| 81 | def splat16 : PatFrag<(ops node:$x), (build_vector |
| 82 | node:$x, node:$x, node:$x, node:$x, |
| 83 | node:$x, node:$x, node:$x, node:$x, |
| 84 | node:$x, node:$x, node:$x, node:$x, |
| 85 | node:$x, node:$x, node:$x, node:$x)>; |
| 86 | multiclass Splat<ValueType vec_t, string vec, WebAssemblyRegClass reg_t, |
| 87 | PatFrag splat_pat, bits<32> simdop> { |
| 88 | defm SPLAT_#vec_t : SIMD_I<(outs V128:$dst), (ins reg_t:$x), (outs), (ins), |
| 89 | [(set (vec_t V128:$dst), (splat_pat reg_t:$x))], |
| 90 | vec#".splat\t$dst, $x", vec#".splat", simdop>; |
| 91 | } |
| 92 | multiclass SIMDBinary<ValueType vec_t, string vec, SDNode node, string name, |
| 93 | bits<32> simdop> { |
| 94 | defm _#vec_t : SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs), |
| 95 | (outs), (ins), |
| 96 | [(set (vec_t V128:$dst), (node V128:$lhs, V128:$rhs))], |
| 97 | vec#"."#name#"\t$dst, $lhs, $rhs", vec#"."#name, |
| 98 | simdop>; |
| 99 | } |
| 100 | multiclass SIMDBinaryIntNoI64x2<SDNode node, string name, bits<32> baseInst> { |
| 101 | defm "" : SIMDBinary<v16i8, "i8x16", node, name, baseInst>; |
| 102 | defm "" : SIMDBinary<v8i16, "i16x8", node, name, !add(baseInst, 1)>; |
| 103 | defm "" : SIMDBinary<v4i32, "i32x4", node, name, !add(baseInst, 2)>; |
| 104 | } |
| 105 | multiclass SIMDBinaryInt<SDNode node, string name, bits<32> baseInst> { |
| 106 | defm "" : SIMDBinaryIntNoI64x2<node, name, baseInst>; |
| 107 | defm "" : SIMDBinary<v2i64, "i64x2", node, name, !add(baseInst, 3)>; |
| 108 | } |
| 109 | multiclass SIMDBinaryFP<SDNode node, string name, bits<32> baseInst> { |
| 110 | defm "" : SIMDBinary<v4f32, "f32x4", node, name, baseInst>; |
| 111 | defm "" : SIMDBinary<v2f64, "f64x2", node, name, !add(baseInst, 1)>; |
| 112 | } |
| 113 | |
| 114 | let Defs = [ARGUMENTS] in { |
Thomas Lively | 2244292 | 2018-08-21 21:03:18 +0000 | [diff] [blame] | 115 | defm "" : ConstVec<v16i8, |
| 116 | (ins vec_i8imm_op:$i0, vec_i8imm_op:$i1, |
| 117 | vec_i8imm_op:$i2, vec_i8imm_op:$i3, |
| 118 | vec_i8imm_op:$i4, vec_i8imm_op:$i5, |
| 119 | vec_i8imm_op:$i6, vec_i8imm_op:$i7, |
| 120 | vec_i8imm_op:$i8, vec_i8imm_op:$i9, |
| 121 | vec_i8imm_op:$iA, vec_i8imm_op:$iB, |
| 122 | vec_i8imm_op:$iC, vec_i8imm_op:$iD, |
| 123 | vec_i8imm_op:$iE, vec_i8imm_op:$iF), |
| 124 | (build_vector ImmI8:$i0, ImmI8:$i1, ImmI8:$i2, ImmI8:$i3, |
| 125 | ImmI8:$i4, ImmI8:$i5, ImmI8:$i6, ImmI8:$i7, |
| 126 | ImmI8:$i8, ImmI8:$i9, ImmI8:$iA, ImmI8:$iB, |
| 127 | ImmI8:$iC, ImmI8:$iD, ImmI8:$iE, ImmI8:$iF), |
| 128 | !strconcat("$i0, $i1, $i2, $i3, $i4, $i5, $i6, $i7, ", |
| 129 | "$i8, $i9, $iA, $iB, $iC, $iD, $iE, $iF")>; |
| 130 | defm "" : ConstVec<v8i16, |
| 131 | (ins vec_i16imm_op:$i0, vec_i16imm_op:$i1, |
| 132 | vec_i16imm_op:$i2, vec_i16imm_op:$i3, |
| 133 | vec_i16imm_op:$i4, vec_i16imm_op:$i5, |
| 134 | vec_i16imm_op:$i6, vec_i16imm_op:$i7), |
| 135 | (build_vector |
| 136 | ImmI16:$i0, ImmI16:$i1, ImmI16:$i2, ImmI16:$i3, |
| 137 | ImmI16:$i4, ImmI16:$i5, ImmI16:$i6, ImmI16:$i7), |
| 138 | "$i0, $i1, $i2, $i3, $i4, $i5, $i6, $i7">; |
| 139 | defm "" : ConstVec<v4i32, |
| 140 | (ins vec_i32imm_op:$i0, vec_i32imm_op:$i1, |
| 141 | vec_i32imm_op:$i2, vec_i32imm_op:$i3), |
| 142 | (build_vector (i32 imm:$i0), (i32 imm:$i1), |
| 143 | (i32 imm:$i2), (i32 imm:$i3)), |
| 144 | "$i0, $i1, $i2, $i3">; |
| 145 | defm "" : ConstVec<v2i64, |
| 146 | (ins vec_i64imm_op:$i0, vec_i64imm_op:$i1), |
| 147 | (build_vector (i64 imm:$i0), (i64 imm:$i1)), |
| 148 | "$i0, $i1">; |
| 149 | defm "" : ConstVec<v4f32, |
| 150 | (ins f32imm_op:$i0, f32imm_op:$i1, |
| 151 | f32imm_op:$i2, f32imm_op:$i3), |
| 152 | (build_vector (f32 fpimm:$i0), (f32 fpimm:$i1), |
| 153 | (f32 fpimm:$i2), (f32 fpimm:$i3)), |
| 154 | "$i0, $i1, $i2, $i3">; |
| 155 | defm "" : ConstVec<v2f64, |
| 156 | (ins f64imm_op:$i0, f64imm_op:$i1), |
| 157 | (build_vector (f64 fpimm:$i0), (f64 fpimm:$i1)), |
| 158 | "$i0, $i1">; |
Thomas Lively | 5222cb6 | 2018-08-15 18:15:18 +0000 | [diff] [blame] | 159 | defm "" : ExtractLaneExtended<"_s", 9>; |
| 160 | defm "" : ExtractLaneExtended<"_u", 10>; |
| 161 | defm "" : ExtractLane<v4i32, "i32x4", LaneIdx4, I32, 13>; |
| 162 | defm "" : ExtractLane<v2i64, "i64x2", LaneIdx2, I64, 14>; |
| 163 | defm "" : ExtractLane<v4f32, "f32x4", LaneIdx4, F32, 15>; |
| 164 | defm "" : ExtractLane<v2f64, "f64x2", LaneIdx2, F64, 16>; |
Thomas Lively | 123c3bb | 2018-08-23 00:43:47 +0000 | [diff] [blame^] | 165 | defm "" : ReplaceLane<v16i8, "i8x16", LaneIdx16, I32, i32, 17>; |
| 166 | defm "" : ReplaceLane<v8i16, "i16x8", LaneIdx8, I32, i32, 18>; |
| 167 | defm "" : ReplaceLane<v4i32, "i32x4", LaneIdx4, I32, i32, 19>; |
| 168 | defm "" : ReplaceLane<v2i64, "i64x2", LaneIdx2, I64, i64, 20>; |
| 169 | defm "" : ReplaceLane<v4f32, "f32x4", LaneIdx4, F32, f32, 21>; |
| 170 | defm "" : ReplaceLane<v2f64, "f64x2", LaneIdx2, F64, f64, 22>; |
| 171 | defm "" : Splat<v16i8, "i8x16", I32, splat16, 3>; |
| 172 | defm "" : Splat<v8i16, "i16x8", I32, splat8, 4>; |
| 173 | defm "" : Splat<v4i32, "i32x4", I32, splat4, 5>; |
| 174 | defm "" : Splat<v2i64, "i64x2", I64, splat2, 6>; |
| 175 | defm "" : Splat<v4f32, "f32x4", F32, splat4, 7>; |
| 176 | defm "" : Splat<v2f64, "f64x2", F64, splat2, 8>; |
| 177 | let isCommutable = 1 in { |
| 178 | defm ADD : SIMDBinaryInt<add, "add", 24>; |
| 179 | defm ADD : SIMDBinaryFP<fadd, "add", 122>; |
| 180 | defm MUL : SIMDBinaryIntNoI64x2<mul, "mul", 32>; |
| 181 | defm MUL : SIMDBinaryFP<fmul, "mul", 128>; |
| 182 | } // isCommutable = 1 |
| 183 | defm SUB : SIMDBinaryInt<sub, "sub", 28>; |
| 184 | defm SUB : SIMDBinaryFP<fsub, "sub", 124>; |
| 185 | defm DIV : SIMDBinaryFP<fdiv, "div", 126>; |
Heejin Ahn | a0fd9c3 | 2018-08-14 18:53:27 +0000 | [diff] [blame] | 186 | } // Defs = [ARGUMENTS] |
| 187 | |
| 188 | // follow convention of making implicit expansions unsigned |
| 189 | def : Pat<(i32 (vector_extract (v16i8 V128:$vec), (i32 LaneIdx16:$idx))), |
Thomas Lively | 5222cb6 | 2018-08-15 18:15:18 +0000 | [diff] [blame] | 190 | (EXTRACT_LANE_v16i8_u V128:$vec, (i32 LaneIdx16:$idx))>; |
Heejin Ahn | a0fd9c3 | 2018-08-14 18:53:27 +0000 | [diff] [blame] | 191 | def : Pat<(i32 (vector_extract (v8i16 V128:$vec), (i32 LaneIdx8:$idx))), |
Thomas Lively | 5222cb6 | 2018-08-15 18:15:18 +0000 | [diff] [blame] | 192 | (EXTRACT_LANE_v8i16_u V128:$vec, (i32 LaneIdx8:$idx))>; |
Heejin Ahn | a0fd9c3 | 2018-08-14 18:53:27 +0000 | [diff] [blame] | 193 | |
Thomas Lively | 2ee686d | 2018-08-22 23:06:27 +0000 | [diff] [blame] | 194 | // arbitrary other BUILD_VECTOR patterns |
| 195 | def : Pat<(v16i8 (build_vector |
| 196 | (i32 I32:$x0), (i32 I32:$x1), (i32 I32:$x2), (i32 I32:$x3), |
| 197 | (i32 I32:$x4), (i32 I32:$x5), (i32 I32:$x6), (i32 I32:$x7), |
| 198 | (i32 I32:$x8), (i32 I32:$x9), (i32 I32:$x10), (i32 I32:$x11), |
| 199 | (i32 I32:$x12), (i32 I32:$x13), (i32 I32:$x14), (i32 I32:$x15) |
| 200 | )), |
| 201 | (v16i8 (REPLACE_LANE_v16i8 |
| 202 | (v16i8 (REPLACE_LANE_v16i8 |
| 203 | (v16i8 (REPLACE_LANE_v16i8 |
| 204 | (v16i8 (REPLACE_LANE_v16i8 |
| 205 | (v16i8 (REPLACE_LANE_v16i8 |
| 206 | (v16i8 (REPLACE_LANE_v16i8 |
| 207 | (v16i8 (REPLACE_LANE_v16i8 |
| 208 | (v16i8 (REPLACE_LANE_v16i8 |
| 209 | (v16i8 (REPLACE_LANE_v16i8 |
| 210 | (v16i8 (REPLACE_LANE_v16i8 |
| 211 | (v16i8 (REPLACE_LANE_v16i8 |
| 212 | (v16i8 (REPLACE_LANE_v16i8 |
| 213 | (v16i8 (REPLACE_LANE_v16i8 |
| 214 | (v16i8 (REPLACE_LANE_v16i8 |
| 215 | (v16i8 (REPLACE_LANE_v16i8 |
| 216 | (v16i8 (SPLAT_v16i8 (i32 I32:$x0))), |
| 217 | 1, I32:$x1 |
| 218 | )), |
| 219 | 2, I32:$x2 |
| 220 | )), |
| 221 | 3, I32:$x3 |
| 222 | )), |
| 223 | 4, I32:$x4 |
| 224 | )), |
| 225 | 5, I32:$x5 |
| 226 | )), |
| 227 | 6, I32:$x6 |
| 228 | )), |
| 229 | 7, I32:$x7 |
| 230 | )), |
| 231 | 8, I32:$x8 |
| 232 | )), |
| 233 | 9, I32:$x9 |
| 234 | )), |
| 235 | 10, I32:$x10 |
| 236 | )), |
| 237 | 11, I32:$x11 |
| 238 | )), |
| 239 | 12, I32:$x12 |
| 240 | )), |
| 241 | 13, I32:$x13 |
| 242 | )), |
| 243 | 14, I32:$x14 |
| 244 | )), |
| 245 | 15, I32:$x15 |
| 246 | ))>; |
| 247 | def : Pat<(v8i16 (build_vector |
| 248 | (i32 I32:$x0), (i32 I32:$x1), (i32 I32:$x2), (i32 I32:$x3), |
| 249 | (i32 I32:$x4), (i32 I32:$x5), (i32 I32:$x6), (i32 I32:$x7) |
| 250 | )), |
| 251 | (v8i16 (REPLACE_LANE_v8i16 |
| 252 | (v8i16 (REPLACE_LANE_v8i16 |
| 253 | (v8i16 (REPLACE_LANE_v8i16 |
| 254 | (v8i16 (REPLACE_LANE_v8i16 |
| 255 | (v8i16 (REPLACE_LANE_v8i16 |
| 256 | (v8i16 (REPLACE_LANE_v8i16 |
| 257 | (v8i16 (REPLACE_LANE_v8i16 |
| 258 | (v8i16 (SPLAT_v8i16 (i32 I32:$x0))), |
| 259 | 1, I32:$x1 |
| 260 | )), |
| 261 | 2, I32:$x2 |
| 262 | )), |
| 263 | 3, I32:$x3 |
| 264 | )), |
| 265 | 4, I32:$x4 |
| 266 | )), |
| 267 | 5, I32:$x5 |
| 268 | )), |
| 269 | 6, I32:$x6 |
| 270 | )), |
| 271 | 7, I32:$x7 |
| 272 | ))>; |
| 273 | def : Pat<(v4i32 (build_vector |
| 274 | (i32 I32:$x0), (i32 I32:$x1), (i32 I32:$x2), (i32 I32:$x3) |
| 275 | )), |
| 276 | (v4i32 (REPLACE_LANE_v4i32 |
| 277 | (v4i32 (REPLACE_LANE_v4i32 |
| 278 | (v4i32 (REPLACE_LANE_v4i32 |
| 279 | (v4i32 (SPLAT_v4i32 (i32 I32:$x0))), |
| 280 | 1, I32:$x1 |
| 281 | )), |
| 282 | 2, I32:$x2 |
| 283 | )), |
| 284 | 3, I32:$x3 |
| 285 | ))>; |
| 286 | def : Pat<(v2i64 (build_vector (i64 I64:$x0), (i64 I64:$x1))), |
| 287 | (v2i64 (REPLACE_LANE_v2i64 |
| 288 | (v2i64 (SPLAT_v2i64 (i64 I64:$x0))), 1, I64:$x1))>; |
| 289 | def : Pat<(v4f32 (build_vector |
| 290 | (f32 F32:$x0), (f32 F32:$x1), (f32 F32:$x2), (f32 F32:$x3) |
| 291 | )), |
| 292 | (v4f32 (REPLACE_LANE_v4f32 |
| 293 | (v4f32 (REPLACE_LANE_v4f32 |
| 294 | (v4f32 (REPLACE_LANE_v4f32 |
| 295 | (v4f32 (SPLAT_v4f32 (f32 F32:$x0))), |
| 296 | 1, F32:$x1 |
| 297 | )), |
| 298 | 2, F32:$x2 |
| 299 | )), |
| 300 | 3, F32:$x3 |
| 301 | ))>; |
| 302 | def : Pat<(v2f64 (build_vector (f64 F64:$x0), (f64 F64:$x1))), |
| 303 | (v2f64 (REPLACE_LANE_v2f64 |
| 304 | (v2f64 (SPLAT_v2f64 (f64 F64:$x0))), 1, F64:$x1))>; |