1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

[WebAssembly] Renumber SIMD opcodes

Summary:
As described in https://github.com/WebAssembly/simd/pull/209. This is
the final reorganization of the SIMD opcode space before
standardization. It has been landed in concert with corresponding
changes in other projects in the WebAssembly SIMD ecosystem.

Reviewers: aheejin

Subscribers: dschuff, sbc100, jgravelle-google, hiraditya, sunfish, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D79224
This commit is contained in:
Thomas Lively 2020-04-30 18:11:15 -07:00
parent c75883c3e9
commit 67397ff9ab
6 changed files with 633 additions and 692 deletions

View File

@ -183,11 +183,10 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
setCondCodeAction(static_cast<ISD::CondCode>(CC), MVT::v2i64, Custom);
// 64x2 conversions are not in the spec
if (!Subtarget->hasUnimplementedSIMD128())
for (auto Op :
{ISD::SINT_TO_FP, ISD::UINT_TO_FP, ISD::FP_TO_SINT, ISD::FP_TO_UINT})
for (auto T : {MVT::v2i64, MVT::v2f64})
setOperationAction(Op, T, Expand);
for (auto Op :
{ISD::SINT_TO_FP, ISD::UINT_TO_FP, ISD::FP_TO_SINT, ISD::FP_TO_UINT})
for (auto T : {MVT::v2i64, MVT::v2f64})
setOperationAction(Op, T, Expand);
}
// As a special case, these operators use the type to mean the type to

View File

@ -67,10 +67,10 @@ multiclass SIMDLoadSplat<string vec, bits<32> simdop> {
vec#".load_splat\t$off$p2align", simdop>;
}
defm "" : SIMDLoadSplat<"v8x16", 194>;
defm "" : SIMDLoadSplat<"v16x8", 195>;
defm "" : SIMDLoadSplat<"v32x4", 196>;
defm "" : SIMDLoadSplat<"v64x2", 197>;
defm "" : SIMDLoadSplat<"v8x16", 7>;
defm "" : SIMDLoadSplat<"v16x8", 8>;
defm "" : SIMDLoadSplat<"v32x4", 9>;
defm "" : SIMDLoadSplat<"v64x2", 10>;
def wasm_load_splat_t : SDTypeProfile<1, 1, [SDTCisPtrTy<1>]>;
def wasm_load_splat : SDNode<"WebAssemblyISD::LOAD_SPLAT", wasm_load_splat_t,
@ -116,9 +116,9 @@ multiclass SIMDLoadExtend<ValueType vec_t, string name, bits<32> simdop> {
}
}
defm "" : SIMDLoadExtend<v8i16, "i16x8.load8x8", 210>;
defm "" : SIMDLoadExtend<v4i32, "i32x4.load16x4", 212>;
defm "" : SIMDLoadExtend<v2i64, "i64x2.load32x2", 214>;
defm "" : SIMDLoadExtend<v8i16, "i16x8.load8x8", 1>;
defm "" : SIMDLoadExtend<v4i32, "i32x4.load16x4", 3>;
defm "" : SIMDLoadExtend<v2i64, "i64x2.load32x2", 5>;
let Predicates = [HasUnimplementedSIMD128] in
foreach types = [[v8i16, i8], [v4i32, i16], [v2i64, i32]] in
@ -144,7 +144,7 @@ defm STORE_V128 :
SIMD_I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr, V128:$vec),
(outs), (ins P2Align:$p2align, offset32_op:$off), [],
"v128.store\t${off}(${addr})$p2align, $vec",
"v128.store\t$off$p2align", 1>;
"v128.store\t$off$p2align", 11>;
foreach vec_t = [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64] in {
// Def load and store patterns from WebAssemblyInstrMemory.td for vector types
@ -166,7 +166,7 @@ multiclass ConstVec<ValueType vec_t, dag ops, dag pat, string args> {
defm CONST_V128_#vec_t : SIMD_I<(outs V128:$dst), ops, (outs), ops,
[(set V128:$dst, (vec_t pat))],
"v128.const\t$dst, "#args,
"v128.const\t"#args, 2>;
"v128.const\t"#args, 12>;
}
defm "" : ConstVec<v16i8,
@ -244,7 +244,7 @@ defm SHUFFLE :
"v8x16.shuffle\t"#
"$m0, $m1, $m2, $m3, $m4, $m5, $m6, $m7, "#
"$m8, $m9, $mA, $mB, $mC, $mD, $mE, $mF",
3>;
13>;
// Shuffles after custom lowering
def wasm_shuffle_t : SDTypeProfile<1, 18, []>;
@ -278,7 +278,7 @@ defm SWIZZLE :
SIMD_I<(outs V128:$dst), (ins V128:$src, V128:$mask), (outs), (ins),
[(set (v16i8 V128:$dst),
(wasm_swizzle (v16i8 V128:$src), (v16i8 V128:$mask)))],
"v8x16.swizzle\t$dst, $src, $mask", "v8x16.swizzle", 192>;
"v8x16.swizzle\t$dst, $src, $mask", "v8x16.swizzle", 14>;
def : Pat<(int_wasm_swizzle (v16i8 V128:$src), (v16i8 V128:$mask)),
(SWIZZLE V128:$src, V128:$mask)>;
@ -305,12 +305,12 @@ multiclass Splat<ValueType vec_t, string vec, WebAssemblyRegClass reg_t,
vec#".splat\t$dst, $x", vec#".splat", simdop>;
}
defm "" : Splat<v16i8, "i8x16", I32, splat16, 4>;
defm "" : Splat<v8i16, "i16x8", I32, splat8, 8>;
defm "" : Splat<v4i32, "i32x4", I32, splat4, 12>;
defm "" : Splat<v2i64, "i64x2", I64, splat2, 15>;
defm "" : Splat<v4f32, "f32x4", F32, splat4, 18>;
defm "" : Splat<v2f64, "f64x2", F64, splat2, 21>;
defm "" : Splat<v16i8, "i8x16", I32, splat16, 15>;
defm "" : Splat<v8i16, "i16x8", I32, splat8, 16>;
defm "" : Splat<v4i32, "i32x4", I32, splat4, 17>;
defm "" : Splat<v2i64, "i64x2", I64, splat2, 18>;
defm "" : Splat<v4f32, "f32x4", F32, splat4, 19>;
defm "" : Splat<v2f64, "f64x2", F64, splat2, 20>;
// scalar_to_vector leaves high lanes undefined, so can be a splat
class ScalarSplatPat<ValueType vec_t, ValueType lane_t,
@ -339,14 +339,14 @@ multiclass ExtractLane<ValueType vec_t, string vec, WebAssemblyRegClass reg_t,
vec#".extract_lane"#suffix#"\t$idx", simdop>;
}
defm "" : ExtractLane<v16i8, "i8x16", I32, 5, "_s">;
defm "" : ExtractLane<v16i8, "i8x16", I32, 6, "_u">;
defm "" : ExtractLane<v8i16, "i16x8", I32, 9, "_s">;
defm "" : ExtractLane<v8i16, "i16x8", I32, 10, "_u">;
defm "" : ExtractLane<v4i32, "i32x4", I32, 13>;
defm "" : ExtractLane<v2i64, "i64x2", I64, 16>;
defm "" : ExtractLane<v4f32, "f32x4", F32, 19>;
defm "" : ExtractLane<v2f64, "f64x2", F64, 22>;
defm "" : ExtractLane<v16i8, "i8x16", I32, 21, "_s">;
defm "" : ExtractLane<v16i8, "i8x16", I32, 22, "_u">;
defm "" : ExtractLane<v8i16, "i16x8", I32, 24, "_s">;
defm "" : ExtractLane<v8i16, "i16x8", I32, 25, "_u">;
defm "" : ExtractLane<v4i32, "i32x4", I32, 27>;
defm "" : ExtractLane<v2i64, "i64x2", I64, 29>;
defm "" : ExtractLane<v4f32, "f32x4", F32, 31>;
defm "" : ExtractLane<v2f64, "f64x2", F64, 33>;
def : Pat<(vector_extract (v16i8 V128:$vec), (i32 LaneIdx16:$idx)),
(EXTRACT_LANE_v16i8_u V128:$vec, imm:$idx)>;
@ -387,12 +387,12 @@ multiclass ReplaceLane<ValueType vec_t, string vec, ImmLeaf imm_t,
vec#".replace_lane\t$idx", simdop>;
}
defm "" : ReplaceLane<v16i8, "i8x16", LaneIdx16, I32, i32, 7>;
defm "" : ReplaceLane<v8i16, "i16x8", LaneIdx8, I32, i32, 11>;
defm "" : ReplaceLane<v4i32, "i32x4", LaneIdx4, I32, i32, 14>;
defm "" : ReplaceLane<v2i64, "i64x2", LaneIdx2, I64, i64, 17>;
defm "" : ReplaceLane<v4f32, "f32x4", LaneIdx4, F32, f32, 20>;
defm "" : ReplaceLane<v2f64, "f64x2", LaneIdx2, F64, f64, 23>;
defm "" : ReplaceLane<v16i8, "i8x16", LaneIdx16, I32, i32, 23>;
defm "" : ReplaceLane<v8i16, "i16x8", LaneIdx8, I32, i32, 26>;
defm "" : ReplaceLane<v4i32, "i32x4", LaneIdx4, I32, i32, 28>;
defm "" : ReplaceLane<v2i64, "i64x2", LaneIdx2, I64, i64, 30>;
defm "" : ReplaceLane<v4f32, "f32x4", LaneIdx4, F32, f32, 32>;
defm "" : ReplaceLane<v2f64, "f64x2", LaneIdx2, F64, f64, 34>;
// Lower undef lane indices to zero
def : Pat<(vector_insert (v16i8 V128:$vec), I32:$x, undef),
@ -438,35 +438,35 @@ multiclass SIMDConditionFP<string name, CondCode cond, bits<32> baseInst> {
// Equality: eq
let isCommutable = 1 in {
defm EQ : SIMDConditionInt<"eq", SETEQ, 24>;
defm EQ : SIMDConditionFP<"eq", SETOEQ, 64>;
defm EQ : SIMDConditionInt<"eq", SETEQ, 35>;
defm EQ : SIMDConditionFP<"eq", SETOEQ, 65>;
} // isCommutable = 1
// Non-equality: ne
let isCommutable = 1 in {
defm NE : SIMDConditionInt<"ne", SETNE, 25>;
defm NE : SIMDConditionFP<"ne", SETUNE, 65>;
defm NE : SIMDConditionInt<"ne", SETNE, 36>;
defm NE : SIMDConditionFP<"ne", SETUNE, 66>;
} // isCommutable = 1
// Less than: lt_s / lt_u / lt
defm LT_S : SIMDConditionInt<"lt_s", SETLT, 26>;
defm LT_U : SIMDConditionInt<"lt_u", SETULT, 27>;
defm LT : SIMDConditionFP<"lt", SETOLT, 66>;
defm LT_S : SIMDConditionInt<"lt_s", SETLT, 37>;
defm LT_U : SIMDConditionInt<"lt_u", SETULT, 38>;
defm LT : SIMDConditionFP<"lt", SETOLT, 67>;
// Greater than: gt_s / gt_u / gt
defm GT_S : SIMDConditionInt<"gt_s", SETGT, 28>;
defm GT_U : SIMDConditionInt<"gt_u", SETUGT, 29>;
defm GT : SIMDConditionFP<"gt", SETOGT, 67>;
defm GT_S : SIMDConditionInt<"gt_s", SETGT, 39>;
defm GT_U : SIMDConditionInt<"gt_u", SETUGT, 40>;
defm GT : SIMDConditionFP<"gt", SETOGT, 68>;
// Less than or equal: le_s / le_u / le
defm LE_S : SIMDConditionInt<"le_s", SETLE, 30>;
defm LE_U : SIMDConditionInt<"le_u", SETULE, 31>;
defm LE : SIMDConditionFP<"le", SETOLE, 68>;
defm LE_S : SIMDConditionInt<"le_s", SETLE, 41>;
defm LE_U : SIMDConditionInt<"le_u", SETULE, 42>;
defm LE : SIMDConditionFP<"le", SETOLE, 69>;
// Greater than or equal: ge_s / ge_u / ge
defm GE_S : SIMDConditionInt<"ge_s", SETGE, 32>;
defm GE_U : SIMDConditionInt<"ge_u", SETUGE, 33>;
defm GE : SIMDConditionFP<"ge", SETOGE, 69>;
defm GE_S : SIMDConditionInt<"ge_s", SETGE, 43>;
defm GE_U : SIMDConditionInt<"ge_u", SETUGE, 44>;
defm GE : SIMDConditionFP<"ge", SETOGE, 70>;
// Lower float comparisons that don't care about NaN to standard WebAssembly
// float comparisons. These instructions are generated with nnan and in the
@ -515,19 +515,19 @@ multiclass SIMDUnary<ValueType vec_t, string vec, SDNode node, string name,
// Bitwise logic: v128.not
foreach vec_t = [v16i8, v8i16, v4i32, v2i64] in
defm NOT: SIMDUnary<vec_t, "v128", vnot, "not", 76>;
defm NOT: SIMDUnary<vec_t, "v128", vnot, "not", 77>;
// Bitwise logic: v128.and / v128.or / v128.xor
// Bitwise logic: v128.and / v128.andnot / v128.or / v128.xor
let isCommutable = 1 in {
defm AND : SIMDBitwise<and, "and", 77>;
defm OR : SIMDBitwise<or, "or", 78>;
defm XOR : SIMDBitwise<xor, "xor", 79>;
defm AND : SIMDBitwise<and, "and", 78>;
defm OR : SIMDBitwise<or, "or", 80>;
defm XOR : SIMDBitwise<xor, "xor", 81>;
} // isCommutable = 1
// Bitwise logic: v128.andnot
def andnot : PatFrag<(ops node:$left, node:$right), (and $left, (vnot $right))>;
let Predicates = [HasUnimplementedSIMD128] in
defm ANDNOT : SIMDBitwise<andnot, "andnot", 216>;
defm ANDNOT : SIMDBitwise<andnot, "andnot", 79>;
// Bitwise select: v128.bitselect
foreach vec_t = [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64] in
@ -538,7 +538,7 @@ foreach vec_t = [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64] in
(vec_t V128:$v1), (vec_t V128:$v2), (vec_t V128:$c)
))
)],
"v128.bitselect\t$dst, $v1, $v2, $c", "v128.bitselect", 80>;
"v128.bitselect\t$dst, $v1, $v2, $c", "v128.bitselect", 82>;
// Bitselect is equivalent to (c & v1) | (~c & v2)
foreach vec_t = [v16i8, v8i16, v4i32, v2i64] in
@ -553,9 +553,9 @@ foreach vec_t = [v16i8, v8i16, v4i32, v2i64] in
multiclass SIMDUnaryInt<SDNode node, string name, bits<32> baseInst> {
defm "" : SIMDUnary<v16i8, "i8x16", node, name, baseInst>;
defm "" : SIMDUnary<v8i16, "i16x8", node, name, !add(baseInst, 17)>;
defm "" : SIMDUnary<v4i32, "i32x4", node, name, !add(baseInst, 34)>;
defm "" : SIMDUnary<v2i64, "i64x2", node, name, !add(baseInst, 51)>;
defm "" : SIMDUnary<v8i16, "i16x8", node, name, !add(baseInst, 32)>;
defm "" : SIMDUnary<v4i32, "i32x4", node, name, !add(baseInst, 64)>;
defm "" : SIMDUnary<v2i64, "i64x2", node, name, !add(baseInst, 96)>;
}
multiclass SIMDReduceVec<ValueType vec_t, string vec, SDNode op, string name,
@ -567,27 +567,25 @@ multiclass SIMDReduceVec<ValueType vec_t, string vec, SDNode op, string name,
multiclass SIMDReduce<SDNode op, string name, bits<32> baseInst> {
defm "" : SIMDReduceVec<v16i8, "i8x16", op, name, baseInst>;
defm "" : SIMDReduceVec<v8i16, "i16x8", op, name, !add(baseInst, 17)>;
defm "" : SIMDReduceVec<v4i32, "i32x4", op, name, !add(baseInst, 34)>;
defm "" : SIMDReduceVec<v2i64, "i64x2", op, name, !add(baseInst, 51)>;
defm "" : SIMDReduceVec<v8i16, "i16x8", op, name, !add(baseInst, 32)>;
defm "" : SIMDReduceVec<v4i32, "i32x4", op, name, !add(baseInst, 64)>;
defm "" : SIMDReduceVec<v2i64, "i64x2", op, name, !add(baseInst, 96)>;
}
// Integer vector negation
def ivneg : PatFrag<(ops node:$in), (sub immAllZerosV, node:$in)>;
// Integer absolute value: abs
defm ABS : SIMDUnary<v16i8, "i8x16", abs, "abs", 225>;
defm ABS : SIMDUnary<v8i16, "i16x8", abs, "abs", 226>;
defm ABS : SIMDUnary<v4i32, "i32x4", abs, "abs", 227>;
defm ABS : SIMDUnaryInt<abs, "abs", 96>;
// Integer negation: neg
defm NEG : SIMDUnaryInt<ivneg, "neg", 81>;
defm NEG : SIMDUnaryInt<ivneg, "neg", 97>;
// Any lane true: any_true
defm ANYTRUE : SIMDReduce<int_wasm_anytrue, "any_true", 82>;
defm ANYTRUE : SIMDReduce<int_wasm_anytrue, "any_true", 98>;
// All lanes true: all_true
defm ALLTRUE : SIMDReduce<int_wasm_alltrue, "all_true", 83>;
defm ALLTRUE : SIMDReduce<int_wasm_alltrue, "all_true", 99>;
// Reductions already return 0 or 1, so and 1, setne 0, and seteq 1
// can be folded out
@ -619,9 +617,9 @@ multiclass SIMDBitmask<ValueType vec_t, string vec, bits<32> simdop> {
vec#".bitmask\t$dst, $vec", vec#".bitmask", simdop>;
}
defm BITMASK : SIMDBitmask<v16i8, "i8x16", 228>;
defm BITMASK : SIMDBitmask<v8i16, "i16x8", 229>;
defm BITMASK : SIMDBitmask<v4i32, "i32x4", 230>;
defm BITMASK : SIMDBitmask<v16i8, "i8x16", 100>;
defm BITMASK : SIMDBitmask<v8i16, "i16x8", 132>;
defm BITMASK : SIMDBitmask<v4i32, "i32x4", 164>;
//===----------------------------------------------------------------------===//
// Bit shifts
@ -639,19 +637,19 @@ multiclass SIMDShift<ValueType vec_t, string vec, SDNode node, dag shift_vec,
multiclass SIMDShiftInt<SDNode node, string name, bits<32> baseInst> {
defm "" : SIMDShift<v16i8, "i8x16", node, (splat16 I32:$x), name, baseInst>;
defm "" : SIMDShift<v8i16, "i16x8", node, (splat8 I32:$x), name,
!add(baseInst, 17)>;
!add(baseInst, 32)>;
defm "" : SIMDShift<v4i32, "i32x4", node, (splat4 I32:$x), name,
!add(baseInst, 34)>;
!add(baseInst, 64)>;
defm "" : SIMDShift<v2i64, "i64x2", node, (splat2 (i64 (zext I32:$x))),
name, !add(baseInst, 51)>;
name, !add(baseInst, 96)>;
}
// Left shift by scalar: shl
defm SHL : SIMDShiftInt<shl, "shl", 84>;
defm SHL : SIMDShiftInt<shl, "shl", 107>;
// Right shift by scalar: shr_s / shr_u
defm SHR_S : SIMDShiftInt<sra, "shr_s", 85>;
defm SHR_U : SIMDShiftInt<srl, "shr_u", 86>;
defm SHR_S : SIMDShiftInt<sra, "shr_s", 108>;
defm SHR_U : SIMDShiftInt<srl, "shr_u", 109>;
// Truncate i64 shift operands to i32s, except if they are already i32s
foreach shifts = [[shl, SHL_v2i64], [sra, SHR_S_v2i64], [srl, SHR_U_v2i64]] in {
@ -683,49 +681,49 @@ def : Pat<(v2i64 (shifts[0] (v2i64 V128:$vec), I32:$x)),
multiclass SIMDBinaryIntSmall<SDNode node, string name, bits<32> baseInst> {
defm "" : SIMDBinary<v16i8, "i8x16", node, name, baseInst>;
defm "" : SIMDBinary<v8i16, "i16x8", node, name, !add(baseInst, 17)>;
defm "" : SIMDBinary<v8i16, "i16x8", node, name, !add(baseInst, 32)>;
}
multiclass SIMDBinaryIntNoI64x2<SDNode node, string name, bits<32> baseInst> {
defm "" : SIMDBinaryIntSmall<node, name, baseInst>;
defm "" : SIMDBinary<v4i32, "i32x4", node, name, !add(baseInst, 34)>;
defm "" : SIMDBinary<v4i32, "i32x4", node, name, !add(baseInst, 64)>;
}
multiclass SIMDBinaryInt<SDNode node, string name, bits<32> baseInst> {
defm "" : SIMDBinaryIntNoI64x2<node, name, baseInst>;
defm "" : SIMDBinary<v2i64, "i64x2", node, name, !add(baseInst, 51)>;
defm "" : SIMDBinary<v2i64, "i64x2", node, name, !add(baseInst, 96)>;
}
// Integer addition: add / add_saturate_s / add_saturate_u
let isCommutable = 1 in {
defm ADD : SIMDBinaryInt<add, "add", 87>;
defm ADD_SAT_S : SIMDBinaryIntSmall<saddsat, "add_saturate_s", 88>;
defm ADD_SAT_U : SIMDBinaryIntSmall<uaddsat, "add_saturate_u", 89>;
defm ADD : SIMDBinaryInt<add, "add", 110>;
defm ADD_SAT_S : SIMDBinaryIntSmall<saddsat, "add_saturate_s", 111>;
defm ADD_SAT_U : SIMDBinaryIntSmall<uaddsat, "add_saturate_u", 112>;
} // isCommutable = 1
// Integer subtraction: sub / sub_saturate_s / sub_saturate_u
defm SUB : SIMDBinaryInt<sub, "sub", 90>;
defm SUB : SIMDBinaryInt<sub, "sub", 113>;
defm SUB_SAT_S :
SIMDBinaryIntSmall<int_wasm_sub_saturate_signed, "sub_saturate_s", 91>;
SIMDBinaryIntSmall<int_wasm_sub_saturate_signed, "sub_saturate_s", 114>;
defm SUB_SAT_U :
SIMDBinaryIntSmall<int_wasm_sub_saturate_unsigned, "sub_saturate_u", 92>;
SIMDBinaryIntSmall<int_wasm_sub_saturate_unsigned, "sub_saturate_u", 115>;
// Integer multiplication: mul
let isCommutable = 1 in
defm MUL : SIMDBinaryIntNoI64x2<mul, "mul", 93>;
defm MUL : SIMDBinaryIntNoI64x2<mul, "mul", 117>;
// Integer min_s / min_u / max_s / max_u
let isCommutable = 1 in {
defm MIN_S : SIMDBinaryIntNoI64x2<smin, "min_s", 94>;
defm MIN_U : SIMDBinaryIntNoI64x2<umin, "min_u", 95>;
defm MAX_S : SIMDBinaryIntNoI64x2<smax, "max_s", 96>;
defm MAX_U : SIMDBinaryIntNoI64x2<umax, "max_u", 97>;
defm MIN_S : SIMDBinaryIntNoI64x2<smin, "min_s", 118>;
defm MIN_U : SIMDBinaryIntNoI64x2<umin, "min_u", 119>;
defm MAX_S : SIMDBinaryIntNoI64x2<smax, "max_s", 120>;
defm MAX_U : SIMDBinaryIntNoI64x2<umax, "max_u", 121>;
} // isCommutable = 1
// Integer unsigned rounding average: avgr_u
let isCommutable = 1 in {
defm AVGR_U : SIMDBinary<v16i8, "i8x16", int_wasm_avgr_unsigned, "avgr_u", 217>;
defm AVGR_U : SIMDBinary<v8i16, "i16x8", int_wasm_avgr_unsigned, "avgr_u", 218>;
defm AVGR_U : SIMDBinary<v16i8, "i8x16", int_wasm_avgr_unsigned, "avgr_u", 123>;
defm AVGR_U : SIMDBinary<v8i16, "i16x8", int_wasm_avgr_unsigned, "avgr_u", 155>;
}
def add_nuw : PatFrag<(ops node:$lhs, node:$rhs),
@ -747,7 +745,7 @@ let isCommutable = 1 in
defm DOT : SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs), (outs), (ins),
[(set V128:$dst, (int_wasm_dot V128:$lhs, V128:$rhs))],
"i32x4.dot_i16x8_s\t$dst, $lhs, $rhs", "i32x4.dot_i16x8_s",
219>;
180>;
//===----------------------------------------------------------------------===//
// Floating-point unary arithmetic
@ -755,17 +753,17 @@ defm DOT : SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs), (outs), (ins),
multiclass SIMDUnaryFP<SDNode node, string name, bits<32> baseInst> {
defm "" : SIMDUnary<v4f32, "f32x4", node, name, baseInst>;
defm "" : SIMDUnary<v2f64, "f64x2", node, name, !add(baseInst, 11)>;
defm "" : SIMDUnary<v2f64, "f64x2", node, name, !add(baseInst, 12)>;
}
// Absolute value: abs
defm ABS : SIMDUnaryFP<fabs, "abs", 149>;
defm ABS : SIMDUnaryFP<fabs, "abs", 224>;
// Negation: neg
defm NEG : SIMDUnaryFP<fneg, "neg", 150>;
defm NEG : SIMDUnaryFP<fneg, "neg", 225>;
// Square root: sqrt
defm SQRT : SIMDUnaryFP<fsqrt, "sqrt", 151>;
defm SQRT : SIMDUnaryFP<fsqrt, "sqrt", 227>;
//===----------------------------------------------------------------------===//
// Floating-point binary arithmetic
@ -773,28 +771,28 @@ defm SQRT : SIMDUnaryFP<fsqrt, "sqrt", 151>;
multiclass SIMDBinaryFP<SDNode node, string name, bits<32> baseInst> {
defm "" : SIMDBinary<v4f32, "f32x4", node, name, baseInst>;
defm "" : SIMDBinary<v2f64, "f64x2", node, name, !add(baseInst, 11)>;
defm "" : SIMDBinary<v2f64, "f64x2", node, name, !add(baseInst, 12)>;
}
// Addition: add
let isCommutable = 1 in
defm ADD : SIMDBinaryFP<fadd, "add", 154>;
defm ADD : SIMDBinaryFP<fadd, "add", 228>;
// Subtraction: sub
defm SUB : SIMDBinaryFP<fsub, "sub", 155>;
defm SUB : SIMDBinaryFP<fsub, "sub", 229>;
// Multiplication: mul
let isCommutable = 1 in
defm MUL : SIMDBinaryFP<fmul, "mul", 156>;
defm MUL : SIMDBinaryFP<fmul, "mul", 230>;
// Division: div
defm DIV : SIMDBinaryFP<fdiv, "div", 157>;
defm DIV : SIMDBinaryFP<fdiv, "div", 231>;
// NaN-propagating minimum: min
defm MIN : SIMDBinaryFP<fminimum, "min", 158>;
defm MIN : SIMDBinaryFP<fminimum, "min", 232>;
// NaN-propagating maximum: max
defm MAX : SIMDBinaryFP<fmaximum, "max", 159>;
defm MAX : SIMDBinaryFP<fmaximum, "max", 233>;
//===----------------------------------------------------------------------===//
// Conversions
@ -808,23 +806,13 @@ multiclass SIMDConvert<ValueType vec_t, ValueType arg_t, SDNode op,
name#"\t$dst, $vec", name, simdop>;
}
// Integer to floating point: convert
defm "" : SIMDConvert<v4f32, v4i32, sint_to_fp, "f32x4.convert_i32x4_s", 175>;
defm "" : SIMDConvert<v4f32, v4i32, uint_to_fp, "f32x4.convert_i32x4_u", 176>;
let Predicates = [HasUnimplementedSIMD128] in {
defm "" : SIMDConvert<v2f64, v2i64, sint_to_fp, "f64x2.convert_i64x2_s", 177>;
defm "" : SIMDConvert<v2f64, v2i64, uint_to_fp, "f64x2.convert_i64x2_u", 178>;
}
// Floating point to integer with saturation: trunc_sat
defm "" : SIMDConvert<v4i32, v4f32, fp_to_sint, "i32x4.trunc_sat_f32x4_s", 171>;
defm "" : SIMDConvert<v4i32, v4f32, fp_to_uint, "i32x4.trunc_sat_f32x4_u", 172>;
defm "" : SIMDConvert<v4i32, v4f32, fp_to_sint, "i32x4.trunc_sat_f32x4_s", 248>;
defm "" : SIMDConvert<v4i32, v4f32, fp_to_uint, "i32x4.trunc_sat_f32x4_u", 249>;
let Predicates = [HasUnimplementedSIMD128] in {
defm "" : SIMDConvert<v2i64, v2f64, fp_to_sint, "i64x2.trunc_sat_f64x2_s", 173>;
defm "" : SIMDConvert<v2i64, v2f64, fp_to_uint, "i64x2.trunc_sat_f64x2_u", 174>;
}
// Integer to floating point: convert
defm "" : SIMDConvert<v4f32, v4i32, sint_to_fp, "f32x4.convert_i32x4_s", 250>;
defm "" : SIMDConvert<v4f32, v4i32, uint_to_fp, "f32x4.convert_i32x4_u", 251>;
// Widening operations
multiclass SIMDWiden<ValueType vec_t, string vec, ValueType arg_t, string arg,
@ -839,8 +827,8 @@ multiclass SIMDWiden<ValueType vec_t, string vec, ValueType arg_t, string arg,
vec#".widen_high_"#arg#"_u", !add(baseInst, 3)>;
}
defm "" : SIMDWiden<v8i16, "i16x8", v16i8, "i8x16", 202>;
defm "" : SIMDWiden<v4i32, "i32x4", v8i16, "i16x8", 206>;
defm "" : SIMDWiden<v8i16, "i16x8", v16i8, "i8x16", 135>;
defm "" : SIMDWiden<v4i32, "i32x4", v8i16, "i16x8", 167>;
// Narrowing operations
multiclass SIMDNarrow<ValueType vec_t, string vec, ValueType arg_t, string arg,
@ -859,18 +847,14 @@ multiclass SIMDNarrow<ValueType vec_t, string vec, ValueType arg_t, string arg,
!add(baseInst, 1)>;
}
defm "" : SIMDNarrow<v16i8, "i8x16", v8i16, "i16x8", 198>;
defm "" : SIMDNarrow<v8i16, "i16x8", v4i32, "i32x4", 200>;
defm "" : SIMDNarrow<v16i8, "i8x16", v8i16, "i16x8", 101>;
defm "" : SIMDNarrow<v8i16, "i16x8", v4i32, "i32x4", 133>;
// Lower llvm.wasm.trunc.saturate.* to saturating instructions
def : Pat<(v4i32 (int_wasm_trunc_saturate_signed (v4f32 V128:$src))),
(fp_to_sint_v4i32_v4f32 (v4f32 V128:$src))>;
def : Pat<(v4i32 (int_wasm_trunc_saturate_unsigned (v4f32 V128:$src))),
(fp_to_uint_v4i32_v4f32 (v4f32 V128:$src))>;
def : Pat<(v2i64 (int_wasm_trunc_saturate_signed (v2f64 V128:$src))),
(fp_to_sint_v2i64_v2f64 (v2f64 V128:$src))>;
def : Pat<(v2i64 (int_wasm_trunc_saturate_unsigned (v2f64 V128:$src))),
(fp_to_uint_v2i64_v2f64 (v2f64 V128:$src))>;
// Bitcasts are nops
// Matching bitcast t1 to t1 causes strange errors, so avoid repeating types
@ -902,5 +886,5 @@ multiclass SIMDQFM<ValueType vec_t, string vec, bits<32> baseInst> {
vec#".qfms\t$dst, $a, $b, $c", vec#".qfms", !add(baseInst, 1)>;
}
defm "" : SIMDQFM<v4f32, "f32x4", 0x98>;
defm "" : SIMDQFM<v2f64, "f64x2", 0xa3>;
defm "" : SIMDQFM<v4f32, "f32x4", 252>;
defm "" : SIMDQFM<v2f64, "f64x2", 254>;

View File

@ -31,8 +31,6 @@ define <4 x float> @convert_u_v4f32(<4 x i32> %x) {
; NO-SIMD128-NOT: i64x2
; SIMD128-VM-NOT: f64x2.convert_i64x2_s
; SIMD128-NEXT: .functype convert_s_v2f64 (v128) -> (v128){{$}}
; SIMD128-NEXT: f64x2.convert_i64x2_s $push[[R:[0-9]+]]=, $0
; SIMD128-NEXT: return $pop[[R]]
define <2 x double> @convert_s_v2f64(<2 x i64> %x) {
%a = sitofp <2 x i64> %x to <2 x double>
ret <2 x double> %a
@ -42,8 +40,6 @@ define <2 x double> @convert_s_v2f64(<2 x i64> %x) {
; NO-SIMD128-NOT: i64x2
; SIMD128-VM-NOT: f64x2.convert_i64x2_u
; SIMD128-NEXT: .functype convert_u_v2f64 (v128) -> (v128){{$}}
; SIMD128-NEXT: f64x2.convert_i64x2_u $push[[R:[0-9]+]]=, $0
; SIMD128-NEXT: return $pop[[R]]
define <2 x double> @convert_u_v2f64(<2 x i64> %x) {
%a = uitofp <2 x i64> %x to <2 x double>
ret <2 x double> %a
@ -73,8 +69,6 @@ define <4 x i32> @trunc_sat_u_v4i32(<4 x float> %x) {
; NO-SIMD128-NOT: f64x2
; SIMD128-VM-NOT: i64x2.trunc_sat_f64x2_s
; SIMD128-NEXT: .functype trunc_sat_s_v2i64 (v128) -> (v128){{$}}
; SIMD128-NEXT: i64x2.trunc_sat_f64x2_s $push[[R:[0-9]+]]=, $0
; SIMD128-NEXT: return $pop[[R]]
define <2 x i64> @trunc_sat_s_v2i64(<2 x double> %x) {
%a = fptosi <2 x double> %x to <2 x i64>
ret <2 x i64> %a
@ -84,8 +78,6 @@ define <2 x i64> @trunc_sat_s_v2i64(<2 x double> %x) {
; NO-SIMD128-NOT: f64x2
; SIMD128-VM-NOT: i64x2.trunc_sat_f64x2_u
; SIMD128-NEXT: .functype trunc_sat_u_v2i64 (v128) -> (v128){{$}}
; SIMD128-NEXT: i64x2.trunc_sat_f64x2_u $push[[R:[0-9]+]]=, $0
; SIMD128-NEXT: return $pop[[R]]
define <2 x i64> @trunc_sat_u_v2i64(<2 x double> %x) {
%a = fptoui <2 x double> %x to <2 x i64>
ret <2 x i64> %a

View File

@ -456,28 +456,6 @@ define <2 x i64> @bitselect_v2i64(<2 x i64> %v1, <2 x i64> %v2, <2 x i64> %c) {
ret <2 x i64> %a
}
; CHECK-LABEL: trunc_sat_s_v2i64:
; NO-SIMD128-NOT: f32x4
; SIMD128-NEXT: .functype trunc_sat_s_v2i64 (v128) -> (v128){{$}}
; SIMD128-NEXT: i64x2.trunc_sat_f64x2_s $push[[R:[0-9]+]]=, $0
; SIMD128-NEXT: return $pop[[R]]
declare <2 x i64> @llvm.wasm.trunc.saturate.signed.v2i64.v2f64(<2 x double>)
define <2 x i64> @trunc_sat_s_v2i64(<2 x double> %x) {
%a = call <2 x i64> @llvm.wasm.trunc.saturate.signed.v2i64.v2f64(<2 x double> %x)
ret <2 x i64> %a
}
; CHECK-LABEL: trunc_sat_u_v2i64:
; NO-SIMD128-NOT: f32x4
; SIMD128-NEXT: .functype trunc_sat_u_v2i64 (v128) -> (v128){{$}}
; SIMD128-NEXT: i64x2.trunc_sat_f64x2_u $push[[R:[0-9]+]]=, $0
; SIMD128-NEXT: return $pop[[R]]
declare <2 x i64> @llvm.wasm.trunc.saturate.unsigned.v2i64.v2f64(<2 x double>)
define <2 x i64> @trunc_sat_u_v2i64(<2 x double> %x) {
%a = call <2 x i64> @llvm.wasm.trunc.saturate.unsigned.v2i64.v2f64(<2 x double> %x)
ret <2 x i64> %a
}
; ==============================================================================
; 4 x f32
; ==============================================================================

View File

@ -34,19 +34,19 @@
0xFC 0x07
# CHECK: v128.const 50462976, 117835012, 185207048, 252579084
0xFD 0x02 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F
0xFD 0x0C 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F
# CHECK: v8x16.shuffle 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
0xFD 0x03 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F
0xFD 0x0D 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F
# Check LEB128 encoding of SIMD instructions
# CHECK: i64x2.all_true
0xFD 0x86 0x01
# CHECK: i16x8.all_true
0xFD 0x83 0x01
# Including non-canonical LEB128 encodings
# CHECK: i64x2.any_true
# CHECK-NOT: i64.div_u
0xFD 0x85 0x81 0x80 0x80 0x80 0x80 0x00
# CHECK: i16x8.any_true
# CHECK-NOT: i16x8.neg
0xFD 0x82 0x81 0x80 0x80 0x80 0x80 0x00
# Check br_table, which has its own operand type.
# CHECK: br_table {0, 1, 2}

File diff suppressed because it is too large Load Diff