From 4f8862743a4fb0a380dcb6533a2b0580f37defe5 Mon Sep 17 00:00:00 2001 From: Derek Schuff Date: Tue, 7 Aug 2018 21:24:01 +0000 Subject: [PATCH] [WebAssembly] Update SIMD binary arithmetic Add missing SIMD types (v2f64) and binary ops. Also adds tablegen support for automatically prepending prefix byte to SIMD opcodes. Differential Revision: https://reviews.llvm.org/D50292 Patch by Thomas Lively git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@339186 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../InstPrinter/WebAssemblyInstPrinter.cpp | 2 + .../WebAssembly/WebAssemblyAsmPrinter.cpp | 8 +- .../WebAssembly/WebAssemblyCFGStackify.cpp | 2 + .../WebAssemblyCallIndirectFixup.cpp | 3 +- .../WebAssembly/WebAssemblyFastISel.cpp | 26 +++++ .../WebAssembly/WebAssemblyISelLowering.cpp | 2 + .../WebAssembly/WebAssemblyInstrCall.td | 10 ++ .../WebAssembly/WebAssemblyInstrControl.td | 2 + .../WebAssembly/WebAssemblyInstrFormats.td | 30 ++++-- .../WebAssembly/WebAssemblyInstrInfo.td | 2 + .../WebAssembly/WebAssemblyInstrSIMD.td | 21 +++- .../WebAssembly/WebAssemblyPeephole.cpp | 10 ++ .../WebAssembly/WebAssemblyRegisterInfo.td | 4 +- .../WebAssembly/WebAssemblyUtilities.cpp | 6 ++ test/CodeGen/WebAssembly/simd-arith.ll | 97 ++++++++++++++++++- 15 files changed, 203 insertions(+), 22 deletions(-) diff --git a/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp b/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp index d5763d837136c..c040c81aae5b5 100644 --- a/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp +++ b/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp @@ -229,7 +229,9 @@ const char *llvm::WebAssembly::TypeToString(MVT Ty) { 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"; diff --git a/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp index 1f280e1d13fc4..596264f01325d 100644 --- a/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ b/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -50,7 +50,7 @@ MVT WebAssemblyAsmPrinter::getRegType(unsigned RegNo) const { 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 @@ void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) { 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 @@ void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) { 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())); diff --git a/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp b/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp index 2ec595e999d98..b74eb45315120 100644 --- a/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp +++ b/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp @@ -256,7 +256,9 @@ static void FixEndsAtEndOfFunction( 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; diff --git a/lib/Target/WebAssembly/WebAssemblyCallIndirectFixup.cpp b/lib/Target/WebAssembly/WebAssemblyCallIndirectFixup.cpp index c1820bf66bc08..85b8bd6759dd3 100644 --- a/lib/Target/WebAssembly/WebAssemblyCallIndirectFixup.cpp +++ b/lib/Target/WebAssembly/WebAssemblyCallIndirectFixup.cpp @@ -72,7 +72,9 @@ static unsigned GetNonPseudoCallIndirectOpcode(const MachineInstr &MI) { 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 @@ bool WebAssemblyCallIndirectFixup::runOnMachineFunction(MachineFunction &MF) { return Changed; } - diff --git a/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/lib/Target/WebAssembly/WebAssemblyFastISel.cpp index 566ef68c027dc..20482c854463e 100644 --- a/lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ b/lib/Target/WebAssembly/WebAssemblyFastISel.cpp @@ -134,7 +134,9 @@ class WebAssemblyFastISel final : public FastISel { 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 @@ bool WebAssemblyFastISel::fastLowerArguments() { 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 @@ bool WebAssemblyFastISel::selectCall(const Instruction *I) { 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 @@ bool WebAssemblyFastISel::selectRet(const Instruction *I) { 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; diff --git a/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index b4bd161583d36..b405ef6335556 100644 --- a/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -59,7 +59,9 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering( 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()); diff --git a/lib/Target/WebAssembly/WebAssemblyInstrCall.td b/lib/Target/WebAssembly/WebAssemblyInstrCall.td index 34262752430cf..aa35028f6326a 100644 --- a/lib/Target/WebAssembly/WebAssemblyInstrCall.td +++ b/lib/Target/WebAssembly/WebAssemblyInstrCall.td @@ -91,7 +91,9 @@ let Uses = [SP32, SP64], isCall = 1 in { 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 @@ def : Pat<(v8i16 (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))), (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 @@ def : Pat<(v8i16 (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))), (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)>; diff --git a/lib/Target/WebAssembly/WebAssemblyInstrControl.td b/lib/Target/WebAssembly/WebAssemblyInstrControl.td index d90244b90662c..13dfa968583a0 100644 --- a/lib/Target/WebAssembly/WebAssemblyInstrControl.td +++ b/lib/Target/WebAssembly/WebAssemblyInstrControl.td @@ -124,7 +124,9 @@ let isReturn = 1 in { 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>; diff --git a/lib/Target/WebAssembly/WebAssemblyInstrFormats.td b/lib/Target/WebAssembly/WebAssemblyInstrFormats.td index 403152c806609..c99b20b60bccd 100644 --- a/lib/Target/WebAssembly/WebAssemblyInstrFormats.td +++ b/lib/Target/WebAssembly/WebAssemblyInstrFormats.td @@ -60,9 +60,9 @@ multiclass NRI pattern, string asmstr = "", 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 @@ multiclass BinaryFP f32Inst, !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), diff --git a/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/lib/Target/WebAssembly/WebAssemblyInstrInfo.td index aeb282a7febbc..3f97ef5f7b7ae 100644 --- a/lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ b/lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -172,7 +172,9 @@ defm "": ARGUMENT; defm "": SIMD_ARGUMENT; defm "": SIMD_ARGUMENT; defm "": SIMD_ARGUMENT; +defm "": SIMD_ARGUMENT; defm "": SIMD_ARGUMENT; +defm "": SIMD_ARGUMENT; let Defs = [ARGUMENTS] in { diff --git a/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td index 7d1edccdeb3c0..5ff0ecba03400 100644 --- a/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td +++ b/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] diff --git a/lib/Target/WebAssembly/WebAssemblyPeephole.cpp b/lib/Target/WebAssembly/WebAssemblyPeephole.cpp index a544844078050..2dfd85953f14c 100644 --- a/lib/Target/WebAssembly/WebAssemblyPeephole.cpp +++ b/lib/Target/WebAssembly/WebAssemblyPeephole.cpp @@ -192,11 +192,21 @@ bool WebAssemblyPeephole::runOnMachineFunction(MachineFunction &MF) { 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, diff --git a/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td b/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td index 29f42b96b249c..a7c3d177724d3 100644 --- a/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td +++ b/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td @@ -63,6 +63,6 @@ def I32 : WebAssemblyRegClass<[i32], 32, (add FP32, SP32, I32_0)>; 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)>; - diff --git a/lib/Target/WebAssembly/WebAssemblyUtilities.cpp b/lib/Target/WebAssembly/WebAssemblyUtilities.cpp index 5944cea5abd15..f4884de5844ee 100644 --- a/lib/Target/WebAssembly/WebAssemblyUtilities.cpp +++ b/lib/Target/WebAssembly/WebAssemblyUtilities.cpp @@ -34,7 +34,9 @@ bool WebAssembly::isArgument(const MachineInstr &MI) { 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 @@ bool WebAssembly::isCallDirect(const MachineInstr &MI) { 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 @@ bool WebAssembly::isCallIndirect(const MachineInstr &MI) { 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: diff --git a/test/CodeGen/WebAssembly/simd-arith.ll b/test/CodeGen/WebAssembly/simd-arith.ll index 8e2b4bc8a0dcf..b64cfa837ed90 100644 --- a/test/CodeGen/WebAssembly/simd-arith.ll +++ b/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 @@ define <4 x i32> @mul_v4i32(<4 x i32> %x, <4 x i32> %y) { 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 @@ define <4 x float> @sub_v4f32(<4 x float> %x, <4 x float> %y) { 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 @@ define <4 x float> @mul_v4f32(<4 x float> %x, <4 x float> %y) { 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 +}