Index: lib/Target/WebAssembly/WebAssemblyISelLowering.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -124,6 +124,9 @@ } } + if (Subtarget->hasSIMD128() && EnableUnimplementedWasmSIMDInstrs) + setOperationAction(ISD::MUL, MVT::v2i64, Expand); + // As a special case, these operators use the type to mean the type to // sign-extend from. setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); Index: lib/Target/WebAssembly/WebAssemblyInstrFormats.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyInstrFormats.td +++ lib/Target/WebAssembly/WebAssemblyInstrFormats.td @@ -119,46 +119,6 @@ !strconcat("f64.", !strconcat(name, "\t$dst, $lhs, $rhs")), !strconcat("f64.", name), f64Inst>; } -multiclass SIMDBinaryInt baseInst> { - defm _I8x16 : SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs), - (outs), (ins), - [(set (v16i8 V128:$dst), (node V128:$lhs, V128:$rhs))], - !strconcat("i8x16.", - !strconcat(name, "\t$dst, $lhs, $rhs")), - !strconcat("i8x16.", name), baseInst>; - defm _I16x8 : SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs), - (outs), (ins), - [(set (v8i16 V128:$dst), (node V128:$lhs, V128:$rhs))], - !strconcat("i16x8.", - !strconcat(name, "\t$dst, $lhs, $rhs")), - !strconcat("i16x8.", name), !add(baseInst, 1)>; - defm _I32x4 : SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs), - (outs), (ins), - [(set (v4i32 V128:$dst), (node V128:$lhs, V128:$rhs))], - !strconcat("i32x4.", - !strconcat(name, "\t$dst, $lhs, $rhs")), - !strconcat("i32x4.", name), !add(baseInst, 2)>; - defm _I64x2 : SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs), - (outs), (ins), - [(set (v2i64 V128:$dst), (node V128:$lhs, V128:$rhs))], - !strconcat("i64x2.", - !strconcat(name, "\t$dst, $lhs, $rhs")), - !strconcat("i64x2.", name), !add(baseInst, 3)>; -} -multiclass SIMDBinaryFP baseInst> { - defm _F32x4 : SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs), - (outs), (ins), - [(set (v4f32 V128:$dst), (node V128:$lhs, V128:$rhs))], - !strconcat("f32x4.", - !strconcat(name, "\t$dst, $lhs, $rhs")), - !strconcat("f32x4.", name), baseInst>; - defm _F64x2 : SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs), - (outs), (ins), - [(set (v2f64 V128:$dst), (node V128:$lhs, V128:$rhs))], - !strconcat("f64x2.", - !strconcat(name, "\t$dst, $lhs, $rhs")), - !strconcat("f64x2.", name), !add(baseInst, 1)>; -} multiclass ComparisonInt i32Inst, bits<32> i64Inst> { defm _I32 : I<(outs I32:$dst), (ins I32:$lhs, I32:$rhs), (outs), (ins), [(set I32:$dst, (setcc I32:$lhs, I32:$rhs, cond))], Index: lib/Target/WebAssembly/WebAssemblyInstrSIMD.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyInstrSIMD.td +++ lib/Target/WebAssembly/WebAssemblyInstrSIMD.td @@ -18,59 +18,12 @@ foreach SIZE = [2, 4, 8, 16, 32] in def LaneIdx#SIZE : ImmLeaf; -// const vectors multiclass ConstVec { 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, 0>; } -defm "" : ConstVec; -defm "" : ConstVec; -defm "" : ConstVec; -defm "" : ConstVec; -defm "" : ConstVec; -defm "" : ConstVec; - -// lane extraction multiclass ExtractLane simdop, string suffix = "", SDNode extract = vector_extract> { @@ -107,24 +60,9 @@ defm "" : ExtractLane("extract_i16x8"#sign)>; } -let Defs = [ARGUMENTS] in { -defm "" : ExtractLaneExtended<"_s", 9>; -defm "" : ExtractLaneExtended<"_u", 10>; -defm "" : ExtractLane; -defm "" : ExtractLane; -defm "" : ExtractLane; -defm "" : ExtractLane; -} // Defs = [ARGUMENTS] - -// follow convention of making implicit expansions unsigned -def : Pat<(i32 (vector_extract (v16i8 V128:$vec), (i32 LaneIdx16:$idx))), - (EXTRACT_LANE_v16i8_u V128:$vec, (i32 LaneIdx16:$idx))>; -def : Pat<(i32 (vector_extract (v8i16 V128:$vec), (i32 LaneIdx8:$idx))), - (EXTRACT_LANE_v8i16_u V128:$vec, (i32 LaneIdx8:$idx))>; - -// lane replacement -multiclass ReplaceLane simdop> { +multiclass ReplaceLane simdop> { defm REPLACE_LANE_#vec_t : SIMD_I<(outs V128:$dst), (ins V128:$vec, i32imm_op:$idx, reg_t:$x), (outs), (ins i32imm_op:$idx), @@ -133,16 +71,6 @@ vec#".replace_lane\t$dst, $vec, $idx, $x", vec#".replace_lane\t$idx", simdop>; } -let Defs = [ARGUMENTS] in { -defm "" : ReplaceLane; -defm "" : ReplaceLane; -defm "" : ReplaceLane; -defm "" : ReplaceLane; -defm "" : ReplaceLane; -defm "" : ReplaceLane; -} // Defs = [ARGUMENTS] - -// splats def splat2 : PatFrag<(ops node:$x), (build_vector node:$x, node:$x)>; def splat4 : PatFrag<(ops node:$x), (build_vector node:$x, node:$x, node:$x, node:$x)>; @@ -160,26 +88,216 @@ [(set (vec_t V128:$dst), (splat_pat reg_t:$x))], vec#".splat\t$dst, $x", vec#".splat", simdop>; } +multiclass SIMDBinary simdop> { + defm _#vec_t : SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs), + (outs), (ins), + [(set (vec_t V128:$dst), (node V128:$lhs, V128:$rhs))], + vec#"."#name#"\t$dst, $lhs, $rhs", vec#"."#name, + simdop>; +} +multiclass SIMDBinaryIntNoI64x2 baseInst> { + defm "" : SIMDBinary; + defm "" : SIMDBinary; + defm "" : SIMDBinary; +} +multiclass SIMDBinaryInt baseInst> { + defm "" : SIMDBinaryIntNoI64x2; + defm "" : SIMDBinary; +} +multiclass SIMDBinaryFP baseInst> { + defm "" : SIMDBinary; + defm "" : SIMDBinary; +} + let Defs = [ARGUMENTS] in { +defm "" : ConstVec; +defm "" : ConstVec; +defm "" : ConstVec; +defm "" : ConstVec; +defm "" : ConstVec; +defm "" : ConstVec; +defm "" : ExtractLaneExtended<"_s", 9>; +defm "" : ExtractLaneExtended<"_u", 10>; +defm "" : ExtractLane; +defm "" : ExtractLane; +defm "" : ExtractLane; +defm "" : ExtractLane; +defm "" : ReplaceLane; +defm "" : ReplaceLane; +defm "" : ReplaceLane; +defm "" : ReplaceLane; +defm "" : ReplaceLane; +defm "" : ReplaceLane; defm "" : Splat; defm "" : Splat; defm "" : Splat; defm "" : Splat; defm "" : Splat; defm "" : Splat; +let isCommutable = 1 in { +defm ADD : SIMDBinaryInt; +defm ADD : SIMDBinaryFP; +defm MUL : SIMDBinaryIntNoI64x2; +defm MUL : SIMDBinaryFP; +} // isCommutable = 1 +defm SUB : SIMDBinaryInt; +defm SUB : SIMDBinaryFP; +defm DIV : SIMDBinaryFP; } // Defs = [ARGUMENTS] -// arithmetic -let Defs = [ARGUMENTS] in { -let isCommutable = 1 in -defm ADD : SIMDBinaryInt; -defm SUB : SIMDBinaryInt; -let isCommutable = 1 in -defm MUL : SIMDBinaryInt; -let isCommutable = 1 in -defm ADD : SIMDBinaryFP; -defm SUB : SIMDBinaryFP; -defm DIV : SIMDBinaryFP; -let isCommutable = 1 in -defm MUL : SIMDBinaryFP; -} // Defs = [ARGUMENTS] +// follow convention of making implicit expansions unsigned +def : Pat<(i32 (vector_extract (v16i8 V128:$vec), (i32 LaneIdx16:$idx))), + (EXTRACT_LANE_v16i8_u V128:$vec, (i32 LaneIdx16:$idx))>; +def : Pat<(i32 (vector_extract (v8i16 V128:$vec), (i32 LaneIdx8:$idx))), + (EXTRACT_LANE_v8i16_u V128:$vec, (i32 LaneIdx8:$idx))>; + +// arbitrary other BUILD_VECTOR patterns +def : Pat<(v16i8 (build_vector + (i32 I32:$x0), (i32 I32:$x1), (i32 I32:$x2), (i32 I32:$x3), + (i32 I32:$x4), (i32 I32:$x5), (i32 I32:$x6), (i32 I32:$x7), + (i32 I32:$x8), (i32 I32:$x9), (i32 I32:$x10), (i32 I32:$x11), + (i32 I32:$x12), (i32 I32:$x13), (i32 I32:$x14), (i32 I32:$x15) + )), + (v16i8 (REPLACE_LANE_v16i8 + (v16i8 (REPLACE_LANE_v16i8 + (v16i8 (REPLACE_LANE_v16i8 + (v16i8 (REPLACE_LANE_v16i8 + (v16i8 (REPLACE_LANE_v16i8 + (v16i8 (REPLACE_LANE_v16i8 + (v16i8 (REPLACE_LANE_v16i8 + (v16i8 (REPLACE_LANE_v16i8 + (v16i8 (REPLACE_LANE_v16i8 + (v16i8 (REPLACE_LANE_v16i8 + (v16i8 (REPLACE_LANE_v16i8 + (v16i8 (REPLACE_LANE_v16i8 + (v16i8 (REPLACE_LANE_v16i8 + (v16i8 (REPLACE_LANE_v16i8 + (v16i8 (REPLACE_LANE_v16i8 + (v16i8 (SPLAT_v16i8 (i32 I32:$x0))), + 1, I32:$x1 + )), + 2, I32:$x2 + )), + 3, I32:$x3 + )), + 4, I32:$x4 + )), + 5, I32:$x5 + )), + 6, I32:$x6 + )), + 7, I32:$x7 + )), + 8, I32:$x8 + )), + 9, I32:$x9 + )), + 10, I32:$x10 + )), + 11, I32:$x11 + )), + 12, I32:$x12 + )), + 13, I32:$x13 + )), + 14, I32:$x14 + )), + 15, I32:$x15 + ))>; +def : Pat<(v8i16 (build_vector + (i32 I32:$x0), (i32 I32:$x1), (i32 I32:$x2), (i32 I32:$x3), + (i32 I32:$x4), (i32 I32:$x5), (i32 I32:$x6), (i32 I32:$x7) + )), + (v8i16 (REPLACE_LANE_v8i16 + (v8i16 (REPLACE_LANE_v8i16 + (v8i16 (REPLACE_LANE_v8i16 + (v8i16 (REPLACE_LANE_v8i16 + (v8i16 (REPLACE_LANE_v8i16 + (v8i16 (REPLACE_LANE_v8i16 + (v8i16 (REPLACE_LANE_v8i16 + (v8i16 (SPLAT_v8i16 (i32 I32:$x0))), + 1, I32:$x1 + )), + 2, I32:$x2 + )), + 3, I32:$x3 + )), + 4, I32:$x4 + )), + 5, I32:$x5 + )), + 6, I32:$x6 + )), + 7, I32:$x7 + ))>; +def : Pat<(v4i32 (build_vector + (i32 I32:$x0), (i32 I32:$x1), (i32 I32:$x2), (i32 I32:$x3) + )), + (v4i32 (REPLACE_LANE_v4i32 + (v4i32 (REPLACE_LANE_v4i32 + (v4i32 (REPLACE_LANE_v4i32 + (v4i32 (SPLAT_v4i32 (i32 I32:$x0))), + 1, I32:$x1 + )), + 2, I32:$x2 + )), + 3, I32:$x3 + ))>; +def : Pat<(v2i64 (build_vector (i64 I64:$x0), (i64 I64:$x1))), + (v2i64 (REPLACE_LANE_v2i64 + (v2i64 (SPLAT_v2i64 (i64 I64:$x0))), 1, I64:$x1))>; +def : Pat<(v4f32 (build_vector + (f32 F32:$x0), (f32 F32:$x1), (f32 F32:$x2), (f32 F32:$x3) + )), + (v4f32 (REPLACE_LANE_v4f32 + (v4f32 (REPLACE_LANE_v4f32 + (v4f32 (REPLACE_LANE_v4f32 + (v4f32 (SPLAT_v4f32 (f32 F32:$x0))), + 1, F32:$x1 + )), + 2, F32:$x2 + )), + 3, F32:$x3 + ))>; +def : Pat<(v2f64 (build_vector (f64 F64:$x0), (f64 F64:$x1))), + (v2f64 (REPLACE_LANE_v2f64 + (v2f64 (SPLAT_v2f64 (f64 F64:$x0))), 1, F64:$x1))>; Index: test/CodeGen/WebAssembly/simd-arith.ll =================================================================== --- test/CodeGen/WebAssembly/simd-arith.ll +++ test/CodeGen/WebAssembly/simd-arith.ll @@ -145,13 +145,13 @@ ret <2 x i64> %a } +; v2i64.mul is not in spec ; CHECK-LABEL: mul_v2i64 ; NO-SIMD128-NOT: i64x2 ; SIMD128-VM-NOT: i64x2 -; SIMD128: .param v128, v128{{$}} -; SIMD128: .result v128{{$}} -; SIMD128: i64x2.mul $push0=, $0, $1 # encoding: [0xfd,0x23]{{$}} -; SIMD128: return $pop0 # +; SIMD128-NOT: i64x2.mul +; SIMD128: i64x2.extract_lane +; SIMD128: i64.mul define <2 x i64> @mul_v2i64(<2 x i64> %x, <2 x i64> %y) { %a = mul <2 x i64> %x, %y ret <2 x i64> %a Index: test/CodeGen/WebAssembly/simd.ll =================================================================== --- test/CodeGen/WebAssembly/simd.ll +++ test/CodeGen/WebAssembly/simd.ll @@ -83,6 +83,50 @@ ret <16 x i8> %res } +; CHECK-LABEL: build_v16i8: +; NO-SIMD128-NOT: i8x16 +; SIMD128: .param i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: i8x16.splat $push0=, $0 # encoding: [0xfd,0x03] +; SIMD128: i8x16.replace_lane $push1=, $pop0, 1, $1 # encoding: [0xfd,0x11,0x01] +; SIMD128: i8x16.replace_lane $push2=, $pop1, 2, $2 # encoding: [0xfd,0x11,0x02] +; SIMD128: i8x16.replace_lane $push3=, $pop2, 3, $3 # encoding: [0xfd,0x11,0x03] +; SIMD128: i8x16.replace_lane $push4=, $pop3, 4, $4 # encoding: [0xfd,0x11,0x04] +; SIMD128: i8x16.replace_lane $push5=, $pop4, 5, $5 # encoding: [0xfd,0x11,0x05] +; SIMD128: i8x16.replace_lane $push6=, $pop5, 6, $6 # encoding: [0xfd,0x11,0x06] +; SIMD128: i8x16.replace_lane $push7=, $pop6, 7, $7 # encoding: [0xfd,0x11,0x07] +; SIMD128: i8x16.replace_lane $push8=, $pop7, 8, $8 # encoding: [0xfd,0x11,0x08] +; SIMD128: i8x16.replace_lane $push9=, $pop8, 9, $9 # encoding: [0xfd,0x11,0x09] +; SIMD128: i8x16.replace_lane $push10=, $pop9, 10, $10 # encoding: [0xfd,0x11,0x0a] +; SIMD128: i8x16.replace_lane $push11=, $pop10, 11, $11 # encoding: [0xfd,0x11,0x0b] +; SIMD128: i8x16.replace_lane $push12=, $pop11, 12, $12 # encoding: [0xfd,0x11,0x0c] +; SIMD128: i8x16.replace_lane $push13=, $pop12, 13, $13 # encoding: [0xfd,0x11,0x0d] +; SIMD128: i8x16.replace_lane $push14=, $pop13, 14, $14 # encoding: [0xfd,0x11,0x0e] +; SIMD128: i8x16.replace_lane $push15=, $pop14, 15, $15 # encoding: [0xfd,0x11,0x0f] +; SIMD128: return $pop15 # encoding: [0x0f] +define <16 x i8> @build_v16i8(i8 %x0, i8 %x1, i8 %x2, i8 %x3, + i8 %x4, i8 %x5, i8 %x6, i8 %x7, + i8 %x8, i8 %x9, i8 %x10, i8 %x11, + i8 %x12, i8 %x13, i8 %x14, i8 %x15) { + %t0 = insertelement <16 x i8> undef, i8 %x0, i32 0 + %t1 = insertelement <16 x i8> %t0, i8 %x1, i32 1 + %t2 = insertelement <16 x i8> %t1, i8 %x2, i32 2 + %t3 = insertelement <16 x i8> %t2, i8 %x3, i32 3 + %t4 = insertelement <16 x i8> %t3, i8 %x4, i32 4 + %t5 = insertelement <16 x i8> %t4, i8 %x5, i32 5 + %t6 = insertelement <16 x i8> %t5, i8 %x6, i32 6 + %t7 = insertelement <16 x i8> %t6, i8 %x7, i32 7 + %t8 = insertelement <16 x i8> %t7, i8 %x8, i32 8 + %t9 = insertelement <16 x i8> %t8, i8 %x9, i32 9 + %t10 = insertelement <16 x i8> %t9, i8 %x10, i32 10 + %t11 = insertelement <16 x i8> %t10, i8 %x11, i32 11 + %t12 = insertelement <16 x i8> %t11, i8 %x12, i32 12 + %t13 = insertelement <16 x i8> %t12, i8 %x13, i32 13 + %t14 = insertelement <16 x i8> %t13, i8 %x14, i32 14 + %res = insertelement <16 x i8> %t14, i8 %x15, i32 15 + ret <16 x i8> %res +} + ; ============================================================================== ; 8 x i16 ; ============================================================================== @@ -157,6 +201,32 @@ ret <8 x i16> %res } +; CHECK-LABEL: build_v8i16: +; NO-SIMD128-NOT: i16x8 +; SIMD128: .param i32, i32, i32, i32, i32, i32, i32, i32{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: i16x8.splat $push0=, $0 # encoding: [0xfd,0x04] +; SIMD128: i16x8.replace_lane $push1=, $pop0, 1, $1 # encoding: [0xfd,0x12,0x01] +; SIMD128: i16x8.replace_lane $push2=, $pop1, 2, $2 # encoding: [0xfd,0x12,0x02] +; SIMD128: i16x8.replace_lane $push3=, $pop2, 3, $3 # encoding: [0xfd,0x12,0x03] +; SIMD128: i16x8.replace_lane $push4=, $pop3, 4, $4 # encoding: [0xfd,0x12,0x04] +; SIMD128: i16x8.replace_lane $push5=, $pop4, 5, $5 # encoding: [0xfd,0x12,0x05] +; SIMD128: i16x8.replace_lane $push6=, $pop5, 6, $6 # encoding: [0xfd,0x12,0x06] +; SIMD128: i16x8.replace_lane $push7=, $pop6, 7, $7 # encoding: [0xfd,0x12,0x07] +; SIMD128: return $pop7 # encoding: [0x0f] +define <8 x i16> @build_v8i16(i16 %x0, i16 %x1, i16 %x2, i16 %x3, + i16 %x4, i16 %x5, i16 %x6, i16 %x7) { + %t0 = insertelement <8 x i16> undef, i16 %x0, i32 0 + %t1 = insertelement <8 x i16> %t0, i16 %x1, i32 1 + %t2 = insertelement <8 x i16> %t1, i16 %x2, i32 2 + %t3 = insertelement <8 x i16> %t2, i16 %x3, i32 3 + %t4 = insertelement <8 x i16> %t3, i16 %x4, i32 4 + %t5 = insertelement <8 x i16> %t4, i16 %x5, i32 5 + %t6 = insertelement <8 x i16> %t5, i16 %x6, i32 6 + %res = insertelement <8 x i16> %t6, i16 %x7, i32 7 + ret <8 x i16> %res +} + ; ============================================================================== ; 4 x i32 ; ============================================================================== @@ -206,6 +276,23 @@ ret <4 x i32> %res } +; CHECK-LABEL: build_v4i32: +; NO-SIMD128-NOT: i32x4 +; SIMD128: .param i32, i32, i32, i32{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: i32x4.splat $push0=, $0 # encoding: [0xfd,0x05] +; SIMD128: i32x4.replace_lane $push1=, $pop0, 1, $1 # encoding: [0xfd,0x13,0x01] +; SIMD128: i32x4.replace_lane $push2=, $pop1, 2, $2 # encoding: [0xfd,0x13,0x02] +; SIMD128: i32x4.replace_lane $push3=, $pop2, 3, $3 # encoding: [0xfd,0x13,0x03] +; SIMD128: return $pop3 # encoding: [0x0f] +define <4 x i32> @build_v4i32(i32 %x0, i32 %x1, i32 %x2, i32 %x3) { + %t0 = insertelement <4 x i32> undef, i32 %x0, i32 0 + %t1 = insertelement <4 x i32> %t0, i32 %x1, i32 1 + %t2 = insertelement <4 x i32> %t1, i32 %x2, i32 2 + %res = insertelement <4 x i32> %t2, i32 %x3, i32 3 + ret <4 x i32> %res +} + ; ============================================================================== ; 2 x i64 ; ============================================================================== @@ -258,6 +345,20 @@ ret <2 x i64> %res } +; CHECK-LABEL: build_v2i64: +; NO-SIMD128-NOT: i64x2 +; SIMD128-VM-NOT: i64x2 +; SIMD128: .param i64, i64{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: i64x2.splat $push0=, $0 # encoding: [0xfd,0x06] +; SIMD128: i64x2.replace_lane $push1=, $pop0, 1, $1 # encoding: [0xfd,0x14,0x01] +; SIMD128: return $pop1 # encoding: [0x0f] +define <2 x i64> @build_v2i64(i64 %x0, i64 %x1) { + %t0 = insertelement <2 x i64> undef, i64 %x0, i32 0 + %res = insertelement <2 x i64> %t0, i64 %x1, i32 1 + ret <2 x i64> %res +} + ; ============================================================================== ; 4 x f32 ; ============================================================================== @@ -309,6 +410,23 @@ ret <4 x float> %res } +; CHECK-LABEL: build_v4f32: +; NO-SIMD128-NOT: f32x4 +; SIMD128: .param f32, f32, f32, f32{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: f32x4.splat $push0=, $0 # encoding: [0xfd,0x07] +; SIMD128: f32x4.replace_lane $push1=, $pop0, 1, $1 # encoding: [0xfd,0x15,0x01] +; SIMD128: f32x4.replace_lane $push2=, $pop1, 2, $2 # encoding: [0xfd,0x15,0x02] +; SIMD128: f32x4.replace_lane $push3=, $pop2, 3, $3 # encoding: [0xfd,0x15,0x03] +; SIMD128: return $pop3 # encoding: [0x0f] +define <4 x float> @build_v4f32(float %x0, float %x1, float %x2, float %x3) { + %t0 = insertelement <4 x float> undef, float %x0, i32 0 + %t1 = insertelement <4 x float> %t0, float %x1, i32 1 + %t2 = insertelement <4 x float> %t1, float %x2, i32 2 + %res = insertelement <4 x float> %t2, float %x3, i32 3 + ret <4 x float> %res +} + ; ============================================================================== ; 2 x f64 ; ============================================================================== @@ -359,3 +477,17 @@ %res = insertelement <2 x double> %v, double %x, i32 0 ret <2 x double> %res } + +; CHECK-LABEL: build_v2f64: +; NO-SIMD128-NOT: f64x2 +; SIMD128-VM-NOT: f64x2 +; SIMD128: .param f64, f64{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: f64x2.splat $push0=, $0 # encoding: [0xfd,0x08] +; SIMD128: f64x2.replace_lane $push1=, $pop0, 1, $1 # encoding: [0xfd,0x16,0x01] +; SIMD128: return $pop1 # encoding: [0x0f] +define <2 x double> @build_v2f64(double %x0, double %x1) { + %t0 = insertelement <2 x double> undef, double %x0, i32 0 + %res = insertelement <2 x double> %t0, double %x1, i32 1 + ret <2 x double> %res +}