Index: lib/Target/WebAssembly/WebAssembly.h =================================================================== --- lib/Target/WebAssembly/WebAssembly.h +++ lib/Target/WebAssembly/WebAssembly.h @@ -18,9 +18,12 @@ #include "llvm/PassRegistry.h" #include "llvm/Support/CodeGen.h" +#include "llvm/Support/CommandLine.h" namespace llvm { +extern cl::opt EnableUnimplementedWasmInstrs; + class WebAssemblyTargetMachine; class ModulePass; class FunctionPass; Index: lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -50,9 +50,13 @@ 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::v2i64, MVT::v4f32, MVT::v2f64}) + MVT::v4i32, MVT::v4f32}) if (TRI->isTypeLegalForClass(*TRC, T)) return T; + if (EnableUnimplementedWasmInstrs) + for (MVT T : {MVT::v2i64, MVT::v2f64}) + if (TRI->isTypeLegalForClass(*TRC, T)) + return T; LLVM_DEBUG(errs() << "Unknown type for register number: " << RegNo); llvm_unreachable("Unknown register type"); return MVT::Other; @@ -168,6 +172,10 @@ LLVM_DEBUG(dbgs() << "EmitInstruction: " << *MI << '\n'); switch (MI->getOpcode()) { + case WebAssembly::ARGUMENT_v2i64: + case WebAssembly::ARGUMENT_v2f64: + if (!EnableUnimplementedWasmInstrs) + llvm_unreachable("unexpected argument type"); case WebAssembly::ARGUMENT_I32: case WebAssembly::ARGUMENT_I64: case WebAssembly::ARGUMENT_F32: @@ -175,12 +183,14 @@ 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; + case WebAssembly::FALLTHROUGH_RETURN_v2i64: + case WebAssembly::FALLTHROUGH_RETURN_v2f64: + if (!EnableUnimplementedWasmInstrs) + llvm_unreachable("unexpected return type"); case WebAssembly::FALLTHROUGH_RETURN_I32: case WebAssembly::FALLTHROUGH_RETURN_I64: case WebAssembly::FALLTHROUGH_RETURN_F32: @@ -188,9 +198,8 @@ case WebAssembly::FALLTHROUGH_RETURN_v16i8: case WebAssembly::FALLTHROUGH_RETURN_v8i16: case WebAssembly::FALLTHROUGH_RETURN_v4i32: - case WebAssembly::FALLTHROUGH_RETURN_v2i64: - case WebAssembly::FALLTHROUGH_RETURN_v4f32: - case WebAssembly::FALLTHROUGH_RETURN_v2f64: { + case WebAssembly::FALLTHROUGH_RETURN_v4f32: { + // 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 @@ -249,6 +249,9 @@ WebAssembly::ExprType retType; switch (MFI.getResults().front().SimpleTy) { + case MVT::ExceptRef: + retType = WebAssembly::ExprType::ExceptRef; + break; case MVT::i32: retType = WebAssembly::ExprType::I32; break; case MVT::i64: retType = WebAssembly::ExprType::I64; break; case MVT::f32: retType = WebAssembly::ExprType::F32; break; @@ -256,13 +259,17 @@ 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"); + case MVT::v2i64: + case MVT::v2f64: + if (EnableUnimplementedWasmInstrs) { + retType = WebAssembly::ExprType::V128; + break; + } + default: + llvm_unreachable("unexpected return type"); } for (MachineBasicBlock &MBB : reverse(MF)) { Index: lib/Target/WebAssembly/WebAssemblyCallIndirectFixup.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyCallIndirectFixup.cpp +++ lib/Target/WebAssembly/WebAssemblyCallIndirectFixup.cpp @@ -72,9 +72,17 @@ 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; + case PCALL_INDIRECT_v2i64: + if (EnableUnimplementedWasmInstrs) + return CALL_INDIRECT_v2i64; + else + llvm_unreachable("unexpected call type"); + case PCALL_INDIRECT_v2f64: + if (EnableUnimplementedWasmInstrs) + return CALL_INDIRECT_v2f64; + else + llvm_unreachable("unexpected call type"); default: return INSTRUCTION_LIST_END; } } Index: lib/Target/WebAssembly/WebAssemblyFastISel.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ lib/Target/WebAssembly/WebAssemblyFastISel.cpp @@ -134,12 +134,15 @@ case MVT::v16i8: case MVT::v8i16: case MVT::v4i32: - case MVT::v2i64: case MVT::v4f32: - case MVT::v2f64: if (Subtarget->hasSIMD128()) return VT; break; + case MVT::v2i64: + case MVT::v2f64: + if (Subtarget->hasSIMD128() && EnableUnimplementedWasmInstrs) + return VT; + break; default: break; } @@ -681,6 +684,8 @@ RC = &WebAssembly::V128RegClass; break; case MVT::v2i64: + if (!EnableUnimplementedWasmInstrs) + llvm_unreachable("unexpected argument type"); Opc = WebAssembly::ARGUMENT_v2i64; RC = &WebAssembly::V128RegClass; break; @@ -689,6 +694,8 @@ RC = &WebAssembly::V128RegClass; break; case MVT::v2f64: + if (!EnableUnimplementedWasmInstrs) + llvm_unreachable("unexpected argument type"); Opc = WebAssembly::ARGUMENT_v2f64; RC = &WebAssembly::V128RegClass; break; @@ -793,6 +800,8 @@ ResultReg = createResultReg(&WebAssembly::V128RegClass); break; case MVT::v2i64: + if (!EnableUnimplementedWasmInstrs) + llvm_unreachable("unexpected return type"); Opc = IsDirect ? WebAssembly::CALL_v2i64 : WebAssembly::PCALL_INDIRECT_v2i64; ResultReg = createResultReg(&WebAssembly::V128RegClass); @@ -803,6 +812,8 @@ ResultReg = createResultReg(&WebAssembly::V128RegClass); break; case MVT::v2f64: + if (!EnableUnimplementedWasmInstrs) + llvm_unreachable("unexpected return type"); Opc = IsDirect ? WebAssembly::CALL_v2f64 : WebAssembly::PCALL_INDIRECT_v2f64; ResultReg = createResultReg(&WebAssembly::V128RegClass); @@ -1318,12 +1329,16 @@ Opc = WebAssembly::RETURN_v4i32; break; case MVT::v2i64: + if (!EnableUnimplementedWasmInstrs) + llvm_unreachable("unexpected return type"); Opc = WebAssembly::RETURN_v2i64; break; case MVT::v4f32: Opc = WebAssembly::RETURN_v4f32; break; case MVT::v2f64: + if (!EnableUnimplementedWasmInstrs) + llvm_unreachable("unexpected return type"); Opc = WebAssembly::RETURN_v2f64; break; case MVT::ExceptRef: Index: lib/Target/WebAssembly/WebAssemblyISelLowering.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -14,6 +14,7 @@ #include "WebAssemblyISelLowering.h" #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" +#include "WebAssembly.h" #include "WebAssemblyMachineFunctionInfo.h" #include "WebAssemblySubtarget.h" #include "WebAssemblyTargetMachine.h" @@ -59,9 +60,11 @@ 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); + if (EnableUnimplementedWasmInstrs) { + addRegisterClass(MVT::v2i64, &WebAssembly::V128RegClass); + addRegisterClass(MVT::v2f64, &WebAssembly::V128RegClass); + } } // Compute derived properties from the register classes. computeRegisterProperties(Subtarget->getRegisterInfo()); Index: lib/Target/WebAssembly/WebAssemblyPeephole.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyPeephole.cpp +++ lib/Target/WebAssembly/WebAssemblyPeephole.cpp @@ -193,6 +193,8 @@ WebAssembly::COPY_V128); break; case WebAssembly::RETURN_v2i64: + if (!EnableUnimplementedWasmInstrs) + llvm_unreachable("unexpected return type"); Changed |= MaybeRewriteToFallthrough( MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_v2i64, WebAssembly::COPY_V128); @@ -203,6 +205,8 @@ WebAssembly::COPY_V128); break; case WebAssembly::RETURN_v2f64: + if (!EnableUnimplementedWasmInstrs) + llvm_unreachable("unexpected return type"); Changed |= MaybeRewriteToFallthrough( MI, MBB, MF, MFI, MRI, TII, WebAssembly::FALLTHROUGH_RETURN_v2f64, WebAssembly::COPY_V128); Index: lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp +++ lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp @@ -42,6 +42,12 @@ cl::desc("WebAssembly Emscripten-style setjmp/longjmp handling"), cl::init(false)); +// Emit proposed instructions that may not have been implemented in engines +cl::opt llvm::EnableUnimplementedWasmInstrs( + "wasm-enable-unimplemented-simd", + cl::desc("Emit potentially-unimplemented WebAssembly SIMD instructions"), + cl::init(false)); + extern "C" void LLVMInitializeWebAssemblyTarget() { // Register the target. RegisterTargetMachine X( Index: lib/Target/WebAssembly/WebAssemblyUtilities.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyUtilities.cpp +++ lib/Target/WebAssembly/WebAssemblyUtilities.cpp @@ -12,6 +12,7 @@ /// //===----------------------------------------------------------------------===// +#include "WebAssembly.h" #include "WebAssemblyUtilities.h" #include "WebAssemblyMachineFunctionInfo.h" #include "llvm/CodeGen/MachineInstr.h" @@ -34,10 +35,13 @@ 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; + case WebAssembly::ARGUMENT_v2i64: + case WebAssembly::ARGUMENT_v2f64: + if (EnableUnimplementedWasmInstrs) { + return true; + } default: return false; } @@ -90,11 +94,13 @@ 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; + case WebAssembly::CALL_v2i64: + case WebAssembly::CALL_v2f64: + if (EnableUnimplementedWasmInstrs) + return true; default: return false; } @@ -110,11 +116,13 @@ 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; + case WebAssembly::CALL_INDIRECT_v2i64: + case WebAssembly::CALL_INDIRECT_v2f64: + if (EnableUnimplementedWasmInstrs) + return true; default: return false; } Index: test/CodeGen/WebAssembly/simd-arith.ll =================================================================== --- test/CodeGen/WebAssembly/simd-arith.ll +++ test/CodeGen/WebAssembly/simd-arith.ll @@ -1,5 +1,7 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+simd128 | FileCheck %s --check-prefixes CHECK,SIMD128 -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+simd128 -fast-isel | FileCheck %s --check-prefixes CHECK,SIMD128 +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -wasm-enable-unimplemented-simd -mattr=+simd128 | FileCheck %s --check-prefixes CHECK,SIMD128 +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -wasm-enable-unimplemented-simd -mattr=+simd128 -fast-isel | FileCheck %s --check-prefixes CHECK,SIMD128 +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+simd128 | FileCheck %s --check-prefixes CHECK,SIMD128-VM +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+simd128 -fast-isel | FileCheck %s --check-prefixes CHECK,SIMD128-VM ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=-simd128 | FileCheck %s --check-prefixes CHECK,NO-SIMD128 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=-simd128 -fast-isel | FileCheck %s --check-prefixes CHECK,NO-SIMD128 @@ -121,6 +123,7 @@ ; ============================================================================== ; CHECK-LABEL: add_v2i64 ; NO-SIMD128-NOT: i64x2 +; SIMD128-VM-NOT: i64x2 ; SIMD128: .param v128, v128{{$}} ; SIMD128: .result v128{{$}} ; SIMD128: i64x2.add $push0=, $0, $1{{$}} @@ -132,6 +135,7 @@ ; CHECK-LABEL: sub_v2i64 ; NO-SIMD128-NOT: i64x2 +; SIMD128-VM-NOT: i64x2 ; SIMD128: .param v128, v128{{$}} ; SIMD128: .result v128{{$}} ; SIMD128: i64x2.sub $push0=, $0, $1{{$}} @@ -143,6 +147,7 @@ ; 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{{$}} @@ -204,6 +209,7 @@ ; ============================================================================== ; CHECK-LABEL: add_v2f64 ; NO-SIMD128-NOT: f64x2 +; SIMD129-VM-NOT: f62x2 ; SIMD128: .param v128, v128{{$}} ; SIMD128: .result v128{{$}} ; SIMD128: f64x2.add $push0=, $0, $1{{$}} @@ -215,6 +221,7 @@ ; CHECK-LABEL: sub_v2f64 ; NO-SIMD128-NOT: f64x2 +; SIMD129-VM-NOT: f62x2 ; SIMD128: .param v128, v128{{$}} ; SIMD128: .result v128{{$}} ; SIMD128: f64x2.sub $push0=, $0, $1{{$}} @@ -226,6 +233,7 @@ ; CHECK-LABEL: div_v2f64 ; NO-SIMD128-NOT: f64x2 +; SIMD129-VM-NOT: f62x2 ; SIMD128: .param v128, v128{{$}} ; SIMD128: .result v128{{$}} ; SIMD128: f64x2.div $push0=, $0, $1{{$}} @@ -237,6 +245,7 @@ ; CHECK-LABEL: mul_v2f64 ; NO-SIMD128-NOT: f64x2 +; SIMD129-VM-NOT: f62x2 ; SIMD128: .param v128, v128{{$}} ; SIMD128: .result v128{{$}} ; SIMD128: f64x2.mul $push0=, $0, $1{{$}}