diff --git a/clang/include/clang/Basic/BuiltinsWebAssembly.def b/clang/include/clang/Basic/BuiltinsWebAssembly.def --- a/clang/include/clang/Basic/BuiltinsWebAssembly.def +++ b/clang/include/clang/Basic/BuiltinsWebAssembly.def @@ -132,6 +132,8 @@ TARGET_BUILTIN(__builtin_wasm_min_f64x2, "V2dV2dV2d", "nc", "unimplemented-simd128") TARGET_BUILTIN(__builtin_wasm_max_f64x2, "V2dV2dV2d", "nc", "unimplemented-simd128") +TARGET_BUILTIN(__builtin_wasm_dot_s_i32x4_i16x8, "V4iV8s", "nc", "simd128") + TARGET_BUILTIN(__builtin_wasm_sqrt_f32x4, "V4fV4f", "nc", "unimplemented-simd128") TARGET_BUILTIN(__builtin_wasm_sqrt_f64x2, "V2dV2d", "nc", "unimplemented-simd128") diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -14360,6 +14360,11 @@ Function *Callee = CGM.getIntrinsic(IntNo, ConvertType(E->getType())); return Builder.CreateCall(Callee, {LHS, RHS}); } + case WebAssembly::BI__builtin_wasm_dot_s_i32x4_i16x8: { + Value *Vec = EmitScalarExpr(E->getArg(0)); + Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_dot); + return Builder.CreateCall(Callee, {Vec}); + } case WebAssembly::BI__builtin_wasm_any_true_i8x16: case WebAssembly::BI__builtin_wasm_any_true_i16x8: case WebAssembly::BI__builtin_wasm_any_true_i32x4: diff --git a/clang/test/CodeGen/builtins-wasm.c b/clang/test/CodeGen/builtins-wasm.c --- a/clang/test/CodeGen/builtins-wasm.c +++ b/clang/test/CodeGen/builtins-wasm.c @@ -436,6 +436,12 @@ // WEBASSEMBLY-NEXT: ret } +i32x4 dot_i16x8_s(i16x8 x) { + return __builtin_wasm_dot_s_i32x4_i16x8(x); + // WEBASSEMBLY: call <4 x i32> @llvm.wasm.dot(<8 x i16> %x) + // WEBASSEMBLY-NEXT: ret +} + i32x4 bitselect(i32x4 x, i32x4 y, i32x4 c) { return __builtin_wasm_bitselect(x, y, c); // WEBASSEMBLY: call <4 x i32> @llvm.wasm.bitselect.v4i32( diff --git a/llvm/include/llvm/IR/IntrinsicsWebAssembly.td b/llvm/include/llvm/IR/IntrinsicsWebAssembly.td --- a/llvm/include/llvm/IR/IntrinsicsWebAssembly.td +++ b/llvm/include/llvm/IR/IntrinsicsWebAssembly.td @@ -152,6 +152,10 @@ Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable]>; +def int_wasm_dot : + Intrinsic<[llvm_v4i32_ty], + [llvm_v8i16_ty], + [IntrNoMem, IntrSpeculatable]>; def int_wasm_narrow_signed : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty, LLVMMatchType<1>], diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td @@ -639,6 +639,11 @@ (i32 (!cast(reduction[1]#"_"#ty) (ty V128:$x)))>; } +// Widening dot product: i32x4.dot_i16x8_s +defm DOT : SIMD_I<(outs V128:$dst), (ins V128:$vec), (outs), (ins), + [(set V128:$dst, (v4i32 (int_wasm_dot V128:$vec)))], + "i32x4.dot_i16x8_s\t$dst, $vec", "i32x4.dot_i16x8_s", 217>; + //===----------------------------------------------------------------------===// // Bit shifts //===----------------------------------------------------------------------===// diff --git a/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll b/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll --- a/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll +++ b/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll @@ -407,6 +407,16 @@ ret i32 %a } +; CHECK-LABEL: dot: +; SIMD128-NEXT: .functype dot (v128) -> (v128){{$}} +; SIMD128-NEXT: i32x4.dot_i16x8_s $push[[R:[0-9]+]]=, $0{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +declare <4 x i32> @llvm.wasm.dot(<8 x i16>) +define <4 x i32> @dot(<8 x i16> %x) { + %a = call <4 x i32> @llvm.wasm.dot(<8 x i16> %x) + ret <4 x i32> %a +} + ; CHECK-LABEL: bitselect_v4i32: ; SIMD128-NEXT: .functype bitselect_v4i32 (v128, v128, v128) -> (v128){{$}} ; SIMD128-NEXT: v128.bitselect $push[[R:[0-9]+]]=, $0, $1, $2{{$}} diff --git a/llvm/test/MC/WebAssembly/simd-encodings.s b/llvm/test/MC/WebAssembly/simd-encodings.s --- a/llvm/test/MC/WebAssembly/simd-encodings.s +++ b/llvm/test/MC/WebAssembly/simd-encodings.s @@ -571,4 +571,7 @@ # CHECK: v128.andnot # encoding: [0xfd,0xd8,0x01] v128.andnot + # CHECK: i32x4.dot_i16x8_s # encoding: [0xfd,0xd9,0x01] + i32x4.dot_i16x8_s + end_function