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} 28multiclass 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} 38multiclass 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} 56defm extract_i8x16 : ExtractPat<i8, 0xff>; 57defm extract_i16x8 : ExtractPat<i16, 0xffff>; 58multiclass 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} 64multiclass 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} 75def splat2 : PatFrag<(ops node:$x), (build_vector node:$x, node:$x)>; 76def splat4 : PatFrag<(ops node:$x), (build_vector 77 node:$x, node:$x, node:$x, node:$x)>; 78def 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)>; 81def 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)>; 86multiclass 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} 92multiclass 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} 100multiclass 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} 105multiclass 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} 109multiclass 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} 113multiclass SIMDBitwise<SDNode node, string name, bits<32> simdop> { 114 defm "" : SIMDBinary<v16i8, "v128", node, name, simdop>; 115 defm "" : SIMDBinary<v8i16, "v128", node, name, simdop>; 116 defm "" : SIMDBinary<v4i32, "v128", node, name, simdop>; 117 defm "" : SIMDBinary<v2i64, "v128", node, name, simdop>; 118} 119 120let Defs = [ARGUMENTS] in { 121defm "" : ConstVec<v16i8, 122 (ins vec_i8imm_op:$i0, vec_i8imm_op:$i1, 123 vec_i8imm_op:$i2, vec_i8imm_op:$i3, 124 vec_i8imm_op:$i4, vec_i8imm_op:$i5, 125 vec_i8imm_op:$i6, vec_i8imm_op:$i7, 126 vec_i8imm_op:$i8, vec_i8imm_op:$i9, 127 vec_i8imm_op:$iA, vec_i8imm_op:$iB, 128 vec_i8imm_op:$iC, vec_i8imm_op:$iD, 129 vec_i8imm_op:$iE, vec_i8imm_op:$iF), 130 (build_vector ImmI8:$i0, ImmI8:$i1, ImmI8:$i2, ImmI8:$i3, 131 ImmI8:$i4, ImmI8:$i5, ImmI8:$i6, ImmI8:$i7, 132 ImmI8:$i8, ImmI8:$i9, ImmI8:$iA, ImmI8:$iB, 133 ImmI8:$iC, ImmI8:$iD, ImmI8:$iE, ImmI8:$iF), 134 !strconcat("$i0, $i1, $i2, $i3, $i4, $i5, $i6, $i7, ", 135 "$i8, $i9, $iA, $iB, $iC, $iD, $iE, $iF")>; 136defm "" : ConstVec<v8i16, 137 (ins vec_i16imm_op:$i0, vec_i16imm_op:$i1, 138 vec_i16imm_op:$i2, vec_i16imm_op:$i3, 139 vec_i16imm_op:$i4, vec_i16imm_op:$i5, 140 vec_i16imm_op:$i6, vec_i16imm_op:$i7), 141 (build_vector 142 ImmI16:$i0, ImmI16:$i1, ImmI16:$i2, ImmI16:$i3, 143 ImmI16:$i4, ImmI16:$i5, ImmI16:$i6, ImmI16:$i7), 144 "$i0, $i1, $i2, $i3, $i4, $i5, $i6, $i7">; 145defm "" : ConstVec<v4i32, 146 (ins vec_i32imm_op:$i0, vec_i32imm_op:$i1, 147 vec_i32imm_op:$i2, vec_i32imm_op:$i3), 148 (build_vector (i32 imm:$i0), (i32 imm:$i1), 149 (i32 imm:$i2), (i32 imm:$i3)), 150 "$i0, $i1, $i2, $i3">; 151defm "" : ConstVec<v2i64, 152 (ins vec_i64imm_op:$i0, vec_i64imm_op:$i1), 153 (build_vector (i64 imm:$i0), (i64 imm:$i1)), 154 "$i0, $i1">; 155defm "" : ConstVec<v4f32, 156 (ins f32imm_op:$i0, f32imm_op:$i1, 157 f32imm_op:$i2, f32imm_op:$i3), 158 (build_vector (f32 fpimm:$i0), (f32 fpimm:$i1), 159 (f32 fpimm:$i2), (f32 fpimm:$i3)), 160 "$i0, $i1, $i2, $i3">; 161defm "" : ConstVec<v2f64, 162 (ins f64imm_op:$i0, f64imm_op:$i1), 163 (build_vector (f64 fpimm:$i0), (f64 fpimm:$i1)), 164 "$i0, $i1">; 165 166defm "" : ExtractLaneExtended<"_s", 9>; 167defm "" : ExtractLaneExtended<"_u", 10>; 168defm "" : ExtractLane<v4i32, "i32x4", LaneIdx4, I32, 13>; 169defm "" : ExtractLane<v2i64, "i64x2", LaneIdx2, I64, 14>; 170defm "" : ExtractLane<v4f32, "f32x4", LaneIdx4, F32, 15>; 171defm "" : ExtractLane<v2f64, "f64x2", LaneIdx2, F64, 16>; 172 173defm "" : ReplaceLane<v16i8, "i8x16", LaneIdx16, I32, i32, 17>; 174defm "" : ReplaceLane<v8i16, "i16x8", LaneIdx8, I32, i32, 18>; 175defm "" : ReplaceLane<v4i32, "i32x4", LaneIdx4, I32, i32, 19>; 176defm "" : ReplaceLane<v2i64, "i64x2", LaneIdx2, I64, i64, 20>; 177defm "" : ReplaceLane<v4f32, "f32x4", LaneIdx4, F32, f32, 21>; 178defm "" : ReplaceLane<v2f64, "f64x2", LaneIdx2, F64, f64, 22>; 179 180defm "" : Splat<v16i8, "i8x16", I32, splat16, 3>; 181defm "" : Splat<v8i16, "i16x8", I32, splat8, 4>; 182defm "" : Splat<v4i32, "i32x4", I32, splat4, 5>; 183defm "" : Splat<v2i64, "i64x2", I64, splat2, 6>; 184defm "" : Splat<v4f32, "f32x4", F32, splat4, 7>; 185defm "" : Splat<v2f64, "f64x2", F64, splat2, 8>; 186 187let isCommutable = 1 in { 188defm ADD : SIMDBinaryInt<add, "add", 24>; 189defm ADD : SIMDBinaryFP<fadd, "add", 122>; 190defm MUL : SIMDBinaryIntNoI64x2<mul, "mul", 32>; 191defm MUL : SIMDBinaryFP<fmul, "mul", 128>; 192} // isCommutable = 1 193 194defm SUB : SIMDBinaryInt<sub, "sub", 28>; 195defm SUB : SIMDBinaryFP<fsub, "sub", 124>; 196defm DIV : SIMDBinaryFP<fdiv, "div", 126>; 197 198let isCommutable = 1 in { 199defm AND : SIMDBitwise<and, "and", 59>; 200defm OR : SIMDBitwise<or, "or", 60>; 201defm XOR : SIMDBitwise<xor, "xor", 61>; 202} // isCommutable = 1 203 204} // Defs = [ARGUMENTS] 205 206// follow convention of making implicit expansions unsigned 207def : Pat<(i32 (vector_extract (v16i8 V128:$vec), (i32 LaneIdx16:$idx))), 208 (EXTRACT_LANE_v16i8_u V128:$vec, (i32 LaneIdx16:$idx))>; 209def : Pat<(i32 (vector_extract (v8i16 V128:$vec), (i32 LaneIdx8:$idx))), 210 (EXTRACT_LANE_v8i16_u V128:$vec, (i32 LaneIdx8:$idx))>; 211 212// arbitrary other BUILD_VECTOR patterns 213def : Pat<(v16i8 (build_vector 214 (i32 I32:$x0), (i32 I32:$x1), (i32 I32:$x2), (i32 I32:$x3), 215 (i32 I32:$x4), (i32 I32:$x5), (i32 I32:$x6), (i32 I32:$x7), 216 (i32 I32:$x8), (i32 I32:$x9), (i32 I32:$x10), (i32 I32:$x11), 217 (i32 I32:$x12), (i32 I32:$x13), (i32 I32:$x14), (i32 I32:$x15) 218 )), 219 (v16i8 (REPLACE_LANE_v16i8 220 (v16i8 (REPLACE_LANE_v16i8 221 (v16i8 (REPLACE_LANE_v16i8 222 (v16i8 (REPLACE_LANE_v16i8 223 (v16i8 (REPLACE_LANE_v16i8 224 (v16i8 (REPLACE_LANE_v16i8 225 (v16i8 (REPLACE_LANE_v16i8 226 (v16i8 (REPLACE_LANE_v16i8 227 (v16i8 (REPLACE_LANE_v16i8 228 (v16i8 (REPLACE_LANE_v16i8 229 (v16i8 (REPLACE_LANE_v16i8 230 (v16i8 (REPLACE_LANE_v16i8 231 (v16i8 (REPLACE_LANE_v16i8 232 (v16i8 (REPLACE_LANE_v16i8 233 (v16i8 (REPLACE_LANE_v16i8 234 (v16i8 (SPLAT_v16i8 (i32 I32:$x0))), 235 1, I32:$x1 236 )), 237 2, I32:$x2 238 )), 239 3, I32:$x3 240 )), 241 4, I32:$x4 242 )), 243 5, I32:$x5 244 )), 245 6, I32:$x6 246 )), 247 7, I32:$x7 248 )), 249 8, I32:$x8 250 )), 251 9, I32:$x9 252 )), 253 10, I32:$x10 254 )), 255 11, I32:$x11 256 )), 257 12, I32:$x12 258 )), 259 13, I32:$x13 260 )), 261 14, I32:$x14 262 )), 263 15, I32:$x15 264 ))>; 265def : Pat<(v8i16 (build_vector 266 (i32 I32:$x0), (i32 I32:$x1), (i32 I32:$x2), (i32 I32:$x3), 267 (i32 I32:$x4), (i32 I32:$x5), (i32 I32:$x6), (i32 I32:$x7) 268 )), 269 (v8i16 (REPLACE_LANE_v8i16 270 (v8i16 (REPLACE_LANE_v8i16 271 (v8i16 (REPLACE_LANE_v8i16 272 (v8i16 (REPLACE_LANE_v8i16 273 (v8i16 (REPLACE_LANE_v8i16 274 (v8i16 (REPLACE_LANE_v8i16 275 (v8i16 (REPLACE_LANE_v8i16 276 (v8i16 (SPLAT_v8i16 (i32 I32:$x0))), 277 1, I32:$x1 278 )), 279 2, I32:$x2 280 )), 281 3, I32:$x3 282 )), 283 4, I32:$x4 284 )), 285 5, I32:$x5 286 )), 287 6, I32:$x6 288 )), 289 7, I32:$x7 290 ))>; 291def : Pat<(v4i32 (build_vector 292 (i32 I32:$x0), (i32 I32:$x1), (i32 I32:$x2), (i32 I32:$x3) 293 )), 294 (v4i32 (REPLACE_LANE_v4i32 295 (v4i32 (REPLACE_LANE_v4i32 296 (v4i32 (REPLACE_LANE_v4i32 297 (v4i32 (SPLAT_v4i32 (i32 I32:$x0))), 298 1, I32:$x1 299 )), 300 2, I32:$x2 301 )), 302 3, I32:$x3 303 ))>; 304def : Pat<(v2i64 (build_vector (i64 I64:$x0), (i64 I64:$x1))), 305 (v2i64 (REPLACE_LANE_v2i64 306 (v2i64 (SPLAT_v2i64 (i64 I64:$x0))), 1, I64:$x1))>; 307def : Pat<(v4f32 (build_vector 308 (f32 F32:$x0), (f32 F32:$x1), (f32 F32:$x2), (f32 F32:$x3) 309 )), 310 (v4f32 (REPLACE_LANE_v4f32 311 (v4f32 (REPLACE_LANE_v4f32 312 (v4f32 (REPLACE_LANE_v4f32 313 (v4f32 (SPLAT_v4f32 (f32 F32:$x0))), 314 1, F32:$x1 315 )), 316 2, F32:$x2 317 )), 318 3, F32:$x3 319 ))>; 320def : Pat<(v2f64 (build_vector (f64 F64:$x0), (f64 F64:$x1))), 321 (v2f64 (REPLACE_LANE_v2f64 322 (v2f64 (SPLAT_v2f64 (f64 F64:$x0))), 1, F64:$x1))>; 323