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//===----------------------------------------------------------------------===// 9/// 10/// \file 11/// WebAssembly SIMD operand code-gen constructs. 12/// 13//===----------------------------------------------------------------------===// 14 15// constrained immediate argument types 16foreach SIZE = [8, 16] in 17def ImmI#SIZE : ImmLeaf<i32, "return (Imm & ((1UL << "#SIZE#") - 1)) == Imm;">; 18foreach SIZE = [2, 4, 8, 16, 32] in 19def LaneIdx#SIZE : ImmLeaf<i32, "return 0 <= Imm && Imm < "#SIZE#";">; 20 21// 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 73// lane extraction 74multiclass 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 : 78 SIMD_I<(outs reg_t:$dst), (ins V128:$vec, i32imm_op:$idx), 79 (outs), (ins i32imm_op:$idx), 80 [(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>; 83} 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> { 105 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)>; 109} 110let Defs = [ARGUMENTS] in { 111defm "" : 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>; 117} // Defs = [ARGUMENTS] 118 119// follow convention of making implicit expansions unsigned 120def : Pat<(i32 (vector_extract (v16i8 V128:$vec), (i32 LaneIdx16:$idx))), 121 (EXTRACT_LANE_v16i8_u V128:$vec, (i32 LaneIdx16:$idx))>; 122def : Pat<(i32 (vector_extract (v8i16 V128:$vec), (i32 LaneIdx8:$idx))), 123 (EXTRACT_LANE_v8i16_u V128:$vec, (i32 LaneIdx8:$idx))>; 124 125// lane replacement 126multiclass ReplaceLane<ValueType vec_t, string vec, WebAssemblyRegClass reg_t, 127 ValueType lane_t, ImmLeaf imm_t, bits<32> simdop> { 128 defm REPLACE_LANE_#vec_t : 129 SIMD_I<(outs V128:$dst), (ins V128:$vec, i32imm_op:$idx, reg_t:$x), 130 (outs), (ins i32imm_op:$idx), 131 [(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>; 135} 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] 144 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)>; 157multiclass Splat<ValueType vec_t, string vec, WebAssemblyRegClass reg_t, 158 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))], 161 vec#".splat\t$dst, $x", vec#".splat", simdop>; 162} 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>; 170} // Defs = [ARGUMENTS] 171 172// arbitrary other BUILD_VECTOR patterns 173def : Pat<(v16i8 (build_vector 174 (i32 I32:$x0), (i32 I32:$x1), (i32 I32:$x2), (i32 I32:$x3), 175 (i32 I32:$x4), (i32 I32:$x5), (i32 I32:$x6), (i32 I32:$x7), 176 (i32 I32:$x8), (i32 I32:$x9), (i32 I32:$x10), (i32 I32:$x11), 177 (i32 I32:$x12), (i32 I32:$x13), (i32 I32:$x14), (i32 I32:$x15) 178 )), 179 (v16i8 (REPLACE_LANE_v16i8 180 (v16i8 (REPLACE_LANE_v16i8 181 (v16i8 (REPLACE_LANE_v16i8 182 (v16i8 (REPLACE_LANE_v16i8 183 (v16i8 (REPLACE_LANE_v16i8 184 (v16i8 (REPLACE_LANE_v16i8 185 (v16i8 (REPLACE_LANE_v16i8 186 (v16i8 (REPLACE_LANE_v16i8 187 (v16i8 (REPLACE_LANE_v16i8 188 (v16i8 (REPLACE_LANE_v16i8 189 (v16i8 (REPLACE_LANE_v16i8 190 (v16i8 (REPLACE_LANE_v16i8 191 (v16i8 (REPLACE_LANE_v16i8 192 (v16i8 (REPLACE_LANE_v16i8 193 (v16i8 (REPLACE_LANE_v16i8 194 (v16i8 (SPLAT_v16i8 (i32 I32:$x0))), 195 1, I32:$x1 196 )), 197 2, I32:$x2 198 )), 199 3, I32:$x3 200 )), 201 4, I32:$x4 202 )), 203 5, I32:$x5 204 )), 205 6, I32:$x6 206 )), 207 7, I32:$x7 208 )), 209 8, I32:$x8 210 )), 211 9, I32:$x9 212 )), 213 10, I32:$x10 214 )), 215 11, I32:$x11 216 )), 217 12, I32:$x12 218 )), 219 13, I32:$x13 220 )), 221 14, I32:$x14 222 )), 223 15, I32:$x15 224 ))>; 225def : Pat<(v8i16 (build_vector 226 (i32 I32:$x0), (i32 I32:$x1), (i32 I32:$x2), (i32 I32:$x3), 227 (i32 I32:$x4), (i32 I32:$x5), (i32 I32:$x6), (i32 I32:$x7) 228 )), 229 (v8i16 (REPLACE_LANE_v8i16 230 (v8i16 (REPLACE_LANE_v8i16 231 (v8i16 (REPLACE_LANE_v8i16 232 (v8i16 (REPLACE_LANE_v8i16 233 (v8i16 (REPLACE_LANE_v8i16 234 (v8i16 (REPLACE_LANE_v8i16 235 (v8i16 (REPLACE_LANE_v8i16 236 (v8i16 (SPLAT_v8i16 (i32 I32:$x0))), 237 1, I32:$x1 238 )), 239 2, I32:$x2 240 )), 241 3, I32:$x3 242 )), 243 4, I32:$x4 244 )), 245 5, I32:$x5 246 )), 247 6, I32:$x6 248 )), 249 7, I32:$x7 250 ))>; 251def : Pat<(v4i32 (build_vector 252 (i32 I32:$x0), (i32 I32:$x1), (i32 I32:$x2), (i32 I32:$x3) 253 )), 254 (v4i32 (REPLACE_LANE_v4i32 255 (v4i32 (REPLACE_LANE_v4i32 256 (v4i32 (REPLACE_LANE_v4i32 257 (v4i32 (SPLAT_v4i32 (i32 I32:$x0))), 258 1, I32:$x1 259 )), 260 2, I32:$x2 261 )), 262 3, I32:$x3 263 ))>; 264def : Pat<(v2i64 (build_vector (i64 I64:$x0), (i64 I64:$x1))), 265 (v2i64 (REPLACE_LANE_v2i64 266 (v2i64 (SPLAT_v2i64 (i64 I64:$x0))), 1, I64:$x1))>; 267def : Pat<(v4f32 (build_vector 268 (f32 F32:$x0), (f32 F32:$x1), (f32 F32:$x2), (f32 F32:$x3) 269 )), 270 (v4f32 (REPLACE_LANE_v4f32 271 (v4f32 (REPLACE_LANE_v4f32 272 (v4f32 (REPLACE_LANE_v4f32 273 (v4f32 (SPLAT_v4f32 (f32 F32:$x0))), 274 1, F32:$x1 275 )), 276 2, F32:$x2 277 )), 278 3, F32:$x3 279 ))>; 280def : Pat<(v2f64 (build_vector (f64 F64:$x0), (f64 F64:$x1))), 281 (v2f64 (REPLACE_LANE_v2f64 282 (v2f64 (SPLAT_v2f64 (f64 F64:$x0))), 1, F64:$x1))>; 283 284// arithmetic 285let Defs = [ARGUMENTS] in { 286let isCommutable = 1 in 287defm ADD : SIMDBinaryInt<add, "add ", 24>; 288defm SUB : SIMDBinaryInt<sub, "sub ", 28>; 289let isCommutable = 1 in 290defm MUL : SIMDBinaryIntNoI64x2<mul, "mul ", 32>; 291 292let isCommutable = 1 in 293defm ADD : SIMDBinaryFP<fadd, "add ", 122>; 294defm SUB : SIMDBinaryFP<fsub, "sub ", 124>; 295defm DIV : SIMDBinaryFP<fdiv, "div ", 126>; 296let isCommutable = 1 in 297defm MUL : SIMDBinaryFP<fmul, "mul ", 128>; 298} // Defs = [ARGUMENTS] 299