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 @@ -31,6 +31,7 @@ //===----------------------------------------------------------------------===// def int_wasm_ref_null_extern : Intrinsic<[llvm_externref_ty], [], [IntrNoMem]>; def int_wasm_ref_null_func : Intrinsic<[llvm_funcref_ty], [], [IntrNoMem]>; +def int_wasm_ref_is_null : Intrinsic<[llvm_i32_ty], [llvm_any_ty], [IntrNoMem]>; //===----------------------------------------------------------------------===// // Table intrinsics diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td @@ -27,6 +27,13 @@ vt#".select\t$dst, $lhs, $rhs, $cond", vt#".select", 0x1b>, Requires<[HasReferenceTypes]>; + defm REF_IS_NULL_#rc : I<(outs I32:$dst), (ins rc:$ref), + (outs I32:$dst), (ins), + [(set I32:$dst, (int_wasm_ref_is_null rc:$ref))], + "ref.is_null\t$ref", + "ref.is_null", + 0xd1>, + Requires<[HasReferenceTypes]>; } defm "" : REF_I; @@ -37,4 +44,4 @@ (!cast("SELECT_"#rc) rc:$lhs, rc:$rhs, I32:$cond)>; def : Pat<(select (i32 (seteq I32:$cond, 0)), rc:$lhs, rc:$rhs), (!cast("SELECT_"#rc) rc:$rhs, rc:$lhs, I32:$cond)>; -} +} \ No newline at end of file diff --git a/llvm/test/CodeGen/WebAssembly/ref-null.ll b/llvm/test/CodeGen/WebAssembly/ref-null.ll --- a/llvm/test/CodeGen/WebAssembly/ref-null.ll +++ b/llvm/test/CodeGen/WebAssembly/ref-null.ll @@ -6,6 +6,7 @@ declare %externref @llvm.wasm.ref.null.extern() nounwind declare %funcref @llvm.wasm.ref.null.func() nounwind +declare i32 @llvm.wasm.ref.is_null() nounwind define %externref @get_null_extern() { ; CHECK-LABEL: get_null_extern: @@ -24,3 +25,23 @@ %null = call %funcref @llvm.wasm.ref.null.func() ret %funcref %null } + +define i32 @ref_is_null_eref(%extenref %eref) { + ; CHECK-LABEL: ref_is_null: + ; CHECK-NEXT: .functype ref_is_null (externref) -> (i32) + %null = call %externref @llvm.wasm.ref.null.extern() + %is_null = call i32 @llvm.wasm.ref.is_null(%externref %null) + %arg_is_null = call i32 @llvm.wasm.ref.is_null(%externref %eref) + %res = i32 add nsw i32 %is_null, i32 %arg_is_null + ret i32 %res +} + +define i32 @ref_is_null_fref(%funcref %fref) { + ; CHECK-LABEL: ref_is_null: + ; CHECK-NEXT: .functype ref_is_null (externref) -> (i32) + %null = call %funcref @llvm.wasm.ref.null.func() + %is_null = call i32 @llvm.wasm.ref.is_null(%funcref %null) + %arg_is_null = call i32 @llvm.wasm.ref.is_null(%funcref %fref) + %res = i32 add nsw i32 %is_null, i32 %arg_is_null + ret i32 %res +} \ No newline at end of file diff --git a/llvm/test/MC/WebAssembly/reference-types.s b/llvm/test/MC/WebAssembly/reference-types.s --- a/llvm/test/MC/WebAssembly/reference-types.s +++ b/llvm/test/MC/WebAssembly/reference-types.s @@ -1,6 +1,15 @@ # RUN: llvm-mc -show-encoding -triple=wasm32-unknown-unknown -mattr=+reference-types < %s | FileCheck %s # RUN: llvm-mc -show-encoding -triple=wasm64-unknown-unknown -mattr=+reference-types < %s | FileCheck %s +# CHECK-LABEL:ref_is_null: +# CHECK: ref.is_null # encoding: [0xd1] +ref_is_null: + .functype ref_is_null () -> () + ref.null_func + ref.is_null + drop + end_function + # CHECK-LABEL: ref_null_test: # CHECK: ref.null_func # encoding: [0xd0,0x70] # CHECK: ref.null_extern # encoding: [0xd0,0x6f]