diff --git a/clang/include/clang/Basic/BuiltinsWebAssembly.def b/clang/include/clang/Basic/BuiltinsWebAssembly.def index 5ab05076acd5eb..4f448dfebeef77 100644 --- a/clang/include/clang/Basic/BuiltinsWebAssembly.def +++ b/clang/include/clang/Basic/BuiltinsWebAssembly.def @@ -211,5 +211,7 @@ TARGET_BUILTIN(__builtin_wasm_store16_lane, "vs*V8sIi", "n", "simd128") TARGET_BUILTIN(__builtin_wasm_store32_lane, "vi*V4iIi", "n", "simd128") TARGET_BUILTIN(__builtin_wasm_store64_lane, "vLLi*V2LLiIi", "n", "simd128") +TARGET_BUILTIN(__builtin_wasm_eq_i64x2, "V2LLiV2LLiV2LLi", "nc", "simd128") + #undef BUILTIN #undef TARGET_BUILTIN diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 5979a3daf57c24..448eab7bfdfc7d 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -16697,6 +16697,12 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_popcnt); return Builder.CreateCall(Callee, {Vec}); } + case WebAssembly::BI__builtin_wasm_eq_i64x2: { + Value *LHS = EmitScalarExpr(E->getArg(0)); + Value *RHS = EmitScalarExpr(E->getArg(1)); + Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_eq); + return Builder.CreateCall(Callee, {LHS, RHS}); + } 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 index 450f505208535b..4a7efaf9716e20 100644 --- a/clang/test/CodeGen/builtins-wasm.c +++ b/clang/test/CodeGen/builtins-wasm.c @@ -656,6 +656,12 @@ i8x16 popcnt(i8x16 x) { // WEBASSEMBLY-NEXT: ret } +i64x2 eq_i64x2(i64x2 x, i64x2 y) { + return __builtin_wasm_eq_i64x2(x, y); + // WEBASSEMBLY: call <2 x i64> @llvm.wasm.eq(<2 x i64> %x, <2 x i64> %y) + // WEBASSEMBLY-NEXT: ret +} + int any_true_i8x16(i8x16 x) { return __builtin_wasm_any_true_i8x16(x); // WEBASSEMBLY: call i32 @llvm.wasm.anytrue.v16i8(<16 x i8> %x) diff --git a/llvm/include/llvm/IR/IntrinsicsWebAssembly.td b/llvm/include/llvm/IR/IntrinsicsWebAssembly.td index e7a2ce76f1832a..2e38bd2d487f52 100644 --- a/llvm/include/llvm/IR/IntrinsicsWebAssembly.td +++ b/llvm/include/llvm/IR/IntrinsicsWebAssembly.td @@ -294,6 +294,13 @@ def int_wasm_signselect : [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable]>; +// TODO: Remove this intrinsic and the associated builtin if i64x2.eq gets +// merged to the proposal. +def int_wasm_eq : + Intrinsic<[llvm_v2i64_ty], + [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem, IntrSpeculatable]>; + //===----------------------------------------------------------------------===// // Thread-local storage intrinsics //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td index 7d7e8aa20d9373..05f4c28e14fc2d 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td @@ -641,6 +641,14 @@ foreach nodes = [[seteq, EQ_v2f64], [setne, NE_v2f64], [setlt, LT_v2f64], def : Pat<(v2i64 (nodes[0] (v2f64 V128:$lhs), (v2f64 V128:$rhs))), (v2i64 (nodes[1] (v2f64 V128:$lhs), (v2f64 V128:$rhs)))>; +// Prototype i64x2.eq +defm EQ_v2i64 : + SIMD_I<(outs V128:$dst), (ins V128:$lhs, V128:$rhs), (outs), (ins), + [(set (v2i64 V128:$dst), + (int_wasm_eq (v2i64 V128:$lhs), (v2i64 V128:$rhs)) + )], + "i64x2.eq\t$dst, $lhs, $rhs", "i64x2.eq", 192>; + //===----------------------------------------------------------------------===// // Bitwise operations diff --git a/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll b/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll index 38b624ea8e8489..625ccf58eda434 100644 --- a/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll +++ b/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll @@ -528,6 +528,16 @@ define <4 x i32> @trunc_sat_u_v4i32(<4 x float> %x) { ; ============================================================================== ; 2 x i64 ; ============================================================================== +; CHECK-LABEL: eq_v2i64: +; SIMD128-NEXT: .functype eq_v2i64 (v128, v128) -> (v128){{$}} +; SIMD128-NEXT: i64x2.eq $push[[R:[0-9]+]]=, $0, $1{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +declare <2 x i64> @llvm.wasm.eq(<2 x i64>, <2 x i64>) +define <2 x i64> @eq_v2i64(<2 x i64> %x, <2 x i64> %y) { + %a = call <2 x i64> @llvm.wasm.eq(<2 x i64> %x, <2 x i64> %y) + ret <2 x i64> %a +} + ; CHECK-LABEL: widen_low_s_v2i64: ; SIMD128-NEXT: .functype widen_low_s_v2i64 (v128) -> (v128){{$}} ; SIMD128-NEXT: i64x2.widen_low_i32x4_s $push[[R:[0-9]+]]=, $0{{$}} diff --git a/llvm/test/MC/WebAssembly/simd-encodings.s b/llvm/test/MC/WebAssembly/simd-encodings.s index 4e30409ef7f909..a0560b5978647d 100644 --- a/llvm/test/MC/WebAssembly/simd-encodings.s +++ b/llvm/test/MC/WebAssembly/simd-encodings.s @@ -511,6 +511,9 @@ main: # CHECK: i32x4.dot_i16x8_s # encoding: [0xfd,0xba,0x01] i32x4.dot_i16x8_s + # CHECK: i64x2.eq # encoding: [0xfd,0xc0,0x01] + i64x2.eq + # CHECK: i64x2.neg # encoding: [0xfd,0xc1,0x01] i64x2.neg