Index: lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp =================================================================== --- lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp +++ lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp @@ -211,13 +211,7 @@ case WebAssembly::ExprType::I64: O << "i64"; break; case WebAssembly::ExprType::F32: O << "f32"; break; case WebAssembly::ExprType::F64: O << "f64"; break; - case WebAssembly::ExprType::I8x16: O << "i8x16"; break; - case WebAssembly::ExprType::I16x8: O << "i16x8"; break; - case WebAssembly::ExprType::I32x4: O << "i32x4"; break; - case WebAssembly::ExprType::F32x4: O << "f32x4"; break; - case WebAssembly::ExprType::B8x16: O << "b8x16"; break; - case WebAssembly::ExprType::B16x8: O << "b16x8"; break; - case WebAssembly::ExprType::B32x4: O << "b32x4"; break; + case WebAssembly::ExprType::V128: O << "v128"; break; case WebAssembly::ExprType::ExceptRef: O << "except_ref"; break; } } @@ -235,7 +229,9 @@ case MVT::v16i8: case MVT::v8i16: case MVT::v4i32: + case MVT::v2i64: case MVT::v4f32: + case MVT::v2f64: return "v128"; case MVT::ExceptRef: return "except_ref"; Index: lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h =================================================================== --- lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h +++ lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h @@ -317,13 +317,7 @@ I64 = 0x7E, F32 = 0x7D, F64 = 0x7C, - I8x16 = 0x7B, - I16x8 = 0x7A, - I32x4 = 0x79, - F32x4 = 0x78, - B8x16 = 0x77, - B16x8 = 0x76, - B32x4 = 0x75, + V128 = 0x7B, ExceptRef = 0x68 }; Index: lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -50,7 +50,7 @@ const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo(); const TargetRegisterClass *TRC = MRI->getRegClass(RegNo); for (MVT T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64, MVT::v16i8, MVT::v8i16, - MVT::v4i32, MVT::v4f32}) + MVT::v4i32, MVT::v2i64, MVT::v4f32, MVT::v2f64}) if (TRI->isTypeLegalForClass(*TRC, T)) return T; LLVM_DEBUG(errs() << "Unknown type for register number: " << RegNo); @@ -175,7 +175,9 @@ case WebAssembly::ARGUMENT_v16i8: case WebAssembly::ARGUMENT_v8i16: case WebAssembly::ARGUMENT_v4i32: + case WebAssembly::ARGUMENT_v2i64: case WebAssembly::ARGUMENT_v4f32: + case WebAssembly::ARGUMENT_v2f64: // These represent values which are live into the function entry, so there's // no instruction to emit. break; @@ -186,7 +188,9 @@ case WebAssembly::FALLTHROUGH_RETURN_v16i8: case WebAssembly::FALLTHROUGH_RETURN_v8i16: case WebAssembly::FALLTHROUGH_RETURN_v4i32: - case WebAssembly::FALLTHROUGH_RETURN_v4f32: { + case WebAssembly::FALLTHROUGH_RETURN_v2i64: + case WebAssembly::FALLTHROUGH_RETURN_v4f32: + case WebAssembly::FALLTHROUGH_RETURN_v2f64: { // These instructions represent the implicit return at the end of a // function body. The operand is always a pop. assert(MFI->isVRegStackified(MI->getOperand(0).getReg())); Index: lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp +++ lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp @@ -253,10 +253,12 @@ case MVT::i64: retType = WebAssembly::ExprType::I64; break; case MVT::f32: retType = WebAssembly::ExprType::F32; break; case MVT::f64: retType = WebAssembly::ExprType::F64; break; - case MVT::v16i8: retType = WebAssembly::ExprType::I8x16; break; - case MVT::v8i16: retType = WebAssembly::ExprType::I16x8; break; - case MVT::v4i32: retType = WebAssembly::ExprType::I32x4; break; - case MVT::v4f32: retType = WebAssembly::ExprType::F32x4; break; + case MVT::v16i8: + case MVT::v8i16: + case MVT::v4i32: + case MVT::v2i64: + case MVT::v4f32: + case MVT::v2f64: retType = WebAssembly::ExprType::V128; break; case MVT::ExceptRef: retType = WebAssembly::ExprType::ExceptRef; break; default: llvm_unreachable("unexpected return type"); } Index: lib/Target/WebAssembly/WebAssemblyCallIndirectFixup.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyCallIndirectFixup.cpp +++ lib/Target/WebAssembly/WebAssemblyCallIndirectFixup.cpp @@ -72,7 +72,9 @@ case PCALL_INDIRECT_v16i8: return CALL_INDIRECT_v16i8; case PCALL_INDIRECT_v8i16: return CALL_INDIRECT_v8i16; case PCALL_INDIRECT_v4i32: return CALL_INDIRECT_v4i32; + case PCALL_INDIRECT_v2i64: return CALL_INDIRECT_v2i64; case PCALL_INDIRECT_v4f32: return CALL_INDIRECT_v4f32; + case PCALL_INDIRECT_v2f64: return CALL_INDIRECT_v2f64; default: return INSTRUCTION_LIST_END; } } @@ -133,4 +135,3 @@ return Changed; } - Index: lib/Target/WebAssembly/WebAssemblyFastISel.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ lib/Target/WebAssembly/WebAssemblyFastISel.cpp @@ -134,7 +134,9 @@ case MVT::v16i8: case MVT::v8i16: case MVT::v4i32: + case MVT::v2i64: case MVT::v4f32: + case MVT::v2f64: if (Subtarget->hasSIMD128()) return VT; break; @@ -678,10 +680,18 @@ Opc = WebAssembly::ARGUMENT_v4i32; RC = &WebAssembly::V128RegClass; break; + case MVT::v2i64: + Opc = WebAssembly::ARGUMENT_v2i64; + RC = &WebAssembly::V128RegClass; + break; case MVT::v4f32: Opc = WebAssembly::ARGUMENT_v4f32; RC = &WebAssembly::V128RegClass; break; + case MVT::v2f64: + Opc = WebAssembly::ARGUMENT_v2f64; + RC = &WebAssembly::V128RegClass; + break; case MVT::ExceptRef: Opc = WebAssembly::ARGUMENT_EXCEPT_REF; RC = &WebAssembly::EXCEPT_REFRegClass; @@ -782,11 +792,21 @@ IsDirect ? WebAssembly::CALL_v4i32 : WebAssembly::PCALL_INDIRECT_v4i32; ResultReg = createResultReg(&WebAssembly::V128RegClass); break; + case MVT::v2i64: + Opc = + IsDirect ? WebAssembly::CALL_v2i64 : WebAssembly::PCALL_INDIRECT_v2i64; + ResultReg = createResultReg(&WebAssembly::V128RegClass); + break; case MVT::v4f32: Opc = IsDirect ? WebAssembly::CALL_v4f32 : WebAssembly::PCALL_INDIRECT_v4f32; ResultReg = createResultReg(&WebAssembly::V128RegClass); break; + case MVT::v2f64: + Opc = + IsDirect ? WebAssembly::CALL_v2f64 : WebAssembly::PCALL_INDIRECT_v2f64; + ResultReg = createResultReg(&WebAssembly::V128RegClass); + break; case MVT::ExceptRef: Opc = IsDirect ? WebAssembly::CALL_EXCEPT_REF : WebAssembly::PCALL_INDIRECT_EXCEPT_REF; @@ -1297,9 +1317,15 @@ case MVT::v4i32: Opc = WebAssembly::RETURN_v4i32; break; + case MVT::v2i64: + Opc = WebAssembly::RETURN_v2i64; + break; case MVT::v4f32: Opc = WebAssembly::RETURN_v4f32; break; + case MVT::v2f64: + Opc = WebAssembly::RETURN_v2f64; + break; case MVT::ExceptRef: Opc = WebAssembly::RETURN_EXCEPT_REF; break; Index: lib/Target/WebAssembly/WebAssemblyISelLowering.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -59,7 +59,9 @@ addRegisterClass(MVT::v16i8, &WebAssembly::V128RegClass); addRegisterClass(MVT::v8i16, &WebAssembly::V128RegClass); addRegisterClass(MVT::v4i32, &WebAssembly::V128RegClass); + addRegisterClass(MVT::v2i64, &WebAssembly::V128RegClass); addRegisterClass(MVT::v4f32, &WebAssembly::V128RegClass); + addRegisterClass(MVT::v2f64, &WebAssembly::V128RegClass); } // Compute derived properties from the register classes. computeRegisterProperties(Subtarget->getRegisterInfo()); Index: lib/Target/WebAssembly/WebAssemblyInstrCall.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyInstrCall.td +++ lib/Target/WebAssembly/WebAssemblyInstrCall.td @@ -91,7 +91,9 @@ defm "" : SIMD_CALL; defm "" : SIMD_CALL; defm "" : SIMD_CALL; + defm "" : SIMD_CALL; defm "" : SIMD_CALL; + defm "" : SIMD_CALL; defm CALL_VOID : I<(outs), (ins function32_op:$callee, variable_ops), (outs), (ins function32_op:$callee), @@ -132,8 +134,12 @@ (CALL_v8i16 tglobaladdr:$callee)>, Requires<[HasSIMD128]>; def : Pat<(v4i32 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))), (CALL_v4i32 tglobaladdr:$callee)>, Requires<[HasSIMD128]>; +def : Pat<(v2i64 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))), + (CALL_v2i64 tglobaladdr:$callee)>, Requires<[HasSIMD128]>; def : Pat<(v4f32 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))), (CALL_v4f32 tglobaladdr:$callee)>, Requires<[HasSIMD128]>; +def : Pat<(v2f64 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))), + (CALL_v2f64 tglobaladdr:$callee)>, Requires<[HasSIMD128]>; def : Pat<(ExceptRef (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))), (CALL_EXCEPT_REF tglobaladdr:$callee)>; @@ -155,8 +161,12 @@ (CALL_v8i16 texternalsym:$callee)>, Requires<[HasSIMD128]>; def : Pat<(v4i32 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))), (CALL_v4i32 texternalsym:$callee)>, Requires<[HasSIMD128]>; +def : Pat<(v2i64 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))), + (CALL_v2i64 texternalsym:$callee)>, Requires<[HasSIMD128]>; def : Pat<(v4f32 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))), (CALL_v4f32 texternalsym:$callee)>, Requires<[HasSIMD128]>; +def : Pat<(v2f64 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))), + (CALL_v2f64 texternalsym:$callee)>, Requires<[HasSIMD128]>; def : Pat<(ExceptRef (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))), (CALL_EXCEPT_REF texternalsym:$callee)>; Index: lib/Target/WebAssembly/WebAssemblyInstrControl.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyInstrControl.td +++ lib/Target/WebAssembly/WebAssemblyInstrControl.td @@ -124,7 +124,9 @@ defm "": SIMD_RETURN; defm "": SIMD_RETURN; defm "": SIMD_RETURN; + defm "": SIMD_RETURN; defm "": SIMD_RETURN; + defm "": SIMD_RETURN; defm RETURN_VOID : NRI<(outs), (ins), [(WebAssemblyreturn)], "return", 0x0f>; Index: lib/Target/WebAssembly/WebAssemblyInstrFormats.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyInstrFormats.td +++ lib/Target/WebAssembly/WebAssemblyInstrFormats.td @@ -60,9 +60,9 @@ multiclass SIMD_I pattern_r, string asmstr_r = "", - string asmstr_s = "", bits<32> inst = -1> { + string asmstr_s = "", bits<32> simdop= -1> { defm "" : I, + !or(0xfd00, !and(0xff, simdop))>, Requires<[HasSIMD128]>; } @@ -119,31 +119,45 @@ !strconcat("f64.", !strconcat(name, "\t$dst, $lhs, $rhs")), !strconcat("f64.", name), f64Inst>; } -multiclass SIMDBinary { +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)>; + !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)>; + !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)>; + !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), (fnode V128:$lhs, V128:$rhs))], + [(set (v4f32 V128:$dst), (node V128:$lhs, V128:$rhs))], !strconcat("f32x4.", !strconcat(name, "\t$dst, $lhs, $rhs")), - !strconcat("f32x4.", name)>; + !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), Index: lib/Target/WebAssembly/WebAssemblyInstrInfo.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -172,7 +172,9 @@ defm "": SIMD_ARGUMENT; defm "": SIMD_ARGUMENT; defm "": SIMD_ARGUMENT; +defm "": SIMD_ARGUMENT; defm "": SIMD_ARGUMENT; +defm "": SIMD_ARGUMENT; let Defs = [ARGUMENTS] in { Index: lib/Target/WebAssembly/WebAssemblyInstrSIMD.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyInstrSIMD.td +++ lib/Target/WebAssembly/WebAssemblyInstrSIMD.td @@ -12,8 +12,19 @@ /// //===----------------------------------------------------------------------===// -let isCommutable = 1 in { -defm ADD : SIMDBinary; -defm MUL: SIMDBinary; -} // isCommutable = 1 -defm SUB: SIMDBinary; +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] Index: lib/Target/WebAssembly/WebAssemblyPeephole.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyPeephole.cpp +++ lib/Target/WebAssembly/WebAssemblyPeephole.cpp @@ -192,11 +192,21 @@ MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_v4i32, WebAssembly::COPY_V128); break; + case WebAssembly::RETURN_v2i64: + Changed |= MaybeRewriteToFallthrough( + MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_v2i64, + WebAssembly::COPY_V128); + break; case WebAssembly::RETURN_v4f32: Changed |= MaybeRewriteToFallthrough( MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_v4f32, WebAssembly::COPY_V128); break; + case WebAssembly::RETURN_v2f64: + Changed |= MaybeRewriteToFallthrough( + MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_v2f64, + WebAssembly::COPY_V128); + break; case WebAssembly::RETURN_VOID: Changed |= MaybeRewriteToFallthrough( MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_VOID, Index: lib/Target/WebAssembly/WebAssemblyRegisterInfo.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyRegisterInfo.td +++ lib/Target/WebAssembly/WebAssemblyRegisterInfo.td @@ -63,6 +63,5 @@ def I64 : WebAssemblyRegClass<[i64], 64, (add FP64, SP64, I64_0)>; def F32 : WebAssemblyRegClass<[f32], 32, (add F32_0)>; def F64 : WebAssemblyRegClass<[f64], 64, (add F64_0)>; -def V128 : WebAssemblyRegClass<[v4f32, v4i32, v16i8, v8i16], 128, (add V128_0)>; +def V128 : WebAssemblyRegClass<[v4f32, v2f64, v2i64, v4i32, v16i8, v8i16], 128, (add V128_0)>; def EXCEPT_REF : WebAssemblyRegClass<[ExceptRef], 0, (add EXCEPT_REF_0)>; - Index: lib/Target/WebAssembly/WebAssemblyUtilities.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyUtilities.cpp +++ lib/Target/WebAssembly/WebAssemblyUtilities.cpp @@ -34,7 +34,9 @@ case WebAssembly::ARGUMENT_v16i8: case WebAssembly::ARGUMENT_v8i16: case WebAssembly::ARGUMENT_v4i32: + case WebAssembly::ARGUMENT_v2i64: case WebAssembly::ARGUMENT_v4f32: + case WebAssembly::ARGUMENT_v2f64: return true; default: return false; @@ -88,7 +90,9 @@ case WebAssembly::CALL_v16i8: case WebAssembly::CALL_v8i16: case WebAssembly::CALL_v4i32: + case WebAssembly::CALL_v2i64: case WebAssembly::CALL_v4f32: + case WebAssembly::CALL_v2f64: case WebAssembly::CALL_EXCEPT_REF: return true; default: @@ -106,7 +110,9 @@ case WebAssembly::CALL_INDIRECT_v16i8: case WebAssembly::CALL_INDIRECT_v8i16: case WebAssembly::CALL_INDIRECT_v4i32: + case WebAssembly::CALL_INDIRECT_v2i64: case WebAssembly::CALL_INDIRECT_v4f32: + case WebAssembly::CALL_INDIRECT_v2f64: case WebAssembly::CALL_INDIRECT_EXCEPT_REF: return true; default: Index: test/CodeGen/WebAssembly/simd-arith.ll =================================================================== --- test/CodeGen/WebAssembly/simd-arith.ll +++ test/CodeGen/WebAssembly/simd-arith.ll @@ -8,10 +8,6 @@ target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" -declare i32 @llvm.ctlz.i32(i32, i1) -declare i32 @llvm.cttz.i32(i32, i1) -declare i32 @llvm.ctpop.i32(i32) - ; ============================================================================== ; 16 x i8 ; ============================================================================== @@ -120,6 +116,42 @@ ret <4 x i32> %a } +; ============================================================================== +; 2 x i64 +; ============================================================================== +; CHECK-LABEL: add_v2i64 +; NO-SIMD128-NOT: i64x2 +; SIMD128: .param v128, v128{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: i64x2.add $push0=, $0, $1{{$}} +; SIMD128: return $pop0{{$}} +define <2 x i64> @add_v2i64(<2 x i64> %x, <2 x i64> %y) { + %a = add <2 x i64> %x, %y + ret <2 x i64> %a +} + +; CHECK-LABEL: sub_v2i64 +; NO-SIMD128-NOT: i64x2 +; SIMD128: .param v128, v128{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: i64x2.sub $push0=, $0, $1{{$}} +; SIMD128: return $pop0{{$}} +define <2 x i64> @sub_v2i64(<2 x i64> %x, <2 x i64> %y) { + %a = sub <2 x i64> %x, %y + ret <2 x i64> %a +} + +; CHECK-LABEL: mul_v2i64 +; NO-SIMD128-NOT: i64x2 +; SIMD128: .param v128, v128{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: i64x2.mul $push0=, $0, $1{{$}} +; SIMD128: return $pop0{{$}} +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 +} + ; ============================================================================== ; 4 x float ; ============================================================================== @@ -145,6 +177,17 @@ ret <4 x float> %a } +; CHECK-LABEL: div_v4f32 +; NO-SIMD128-NOT: f32x4 +; SIMD128: .param v128, v128{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: f32x4.div $push0=, $0, $1{{$}} +; SIMD128: return $pop0{{$}} +define <4 x float> @div_v4f32(<4 x float> %x, <4 x float> %y) { + %a = fdiv <4 x float> %x, %y + ret <4 x float> %a +} + ; CHECK-LABEL: mul_v4f32 ; NO-SIMD128-NOT: f32x4 ; SIMD128: .param v128, v128{{$}} @@ -156,3 +199,49 @@ ret <4 x float> %a } +; ============================================================================== +; 2 x double +; ============================================================================== +; CHECK-LABEL: add_v2f64 +; NO-SIMD128-NOT: f64x2 +; SIMD128: .param v128, v128{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: f64x2.add $push0=, $0, $1{{$}} +; SIMD128: return $pop0{{$}} +define <2 x double> @add_v2f64(<2 x double> %x, <2 x double> %y) { + %a = fadd <2 x double> %x, %y + ret <2 x double> %a +} + +; CHECK-LABEL: sub_v2f64 +; NO-SIMD128-NOT: f64x2 +; SIMD128: .param v128, v128{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: f64x2.sub $push0=, $0, $1{{$}} +; SIMD128: return $pop0{{$}} +define <2 x double> @sub_v2f64(<2 x double> %x, <2 x double> %y) { + %a = fsub <2 x double> %x, %y + ret <2 x double> %a +} + +; CHECK-LABEL: div_v2f64 +; NO-SIMD128-NOT: f64x2 +; SIMD128: .param v128, v128{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: f64x2.div $push0=, $0, $1{{$}} +; SIMD128: return $pop0{{$}} +define <2 x double> @div_v2f64(<2 x double> %x, <2 x double> %y) { + %a = fdiv <2 x double> %x, %y + ret <2 x double> %a +} + +; CHECK-LABEL: mul_v2f64 +; NO-SIMD128-NOT: f64x2 +; SIMD128: .param v128, v128{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: f64x2.mul $push0=, $0, $1{{$}} +; SIMD128: return $pop0{{$}} +define <2 x double> @mul_v2f64(<2 x double> %x, <2 x double> %y) { + %a = fmul <2 x double> %x, %y + ret <2 x double> %a +}