| //===- IntrinsicsWebAssembly.td - Defines wasm intrinsics --*- tablegen -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| /// |
| /// \file |
| /// This file defines all of the WebAssembly-specific intrinsics. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| let TargetPrefix = "wasm" in { // All intrinsics start with "llvm.wasm.". |
| |
| // Query the current memory size, and increase the current memory size. |
| // Note that memory.size is not IntrNoMem because it must be sequenced with |
| // respect to memory.grow calls. |
| def int_wasm_memory_size : Intrinsic<[llvm_anyint_ty], |
| [llvm_i32_ty], |
| [IntrReadMem]>; |
| def int_wasm_memory_grow : Intrinsic<[llvm_anyint_ty], |
| [llvm_i32_ty, LLVMMatchType<0>], |
| []>; |
| |
| //===----------------------------------------------------------------------===// |
| // Trapping float-to-int conversions |
| //===----------------------------------------------------------------------===// |
| |
| def int_wasm_trunc_signed : Intrinsic<[llvm_anyint_ty], |
| [llvm_anyfloat_ty], |
| [IntrNoMem]>; |
| def int_wasm_trunc_unsigned : Intrinsic<[llvm_anyint_ty], |
| [llvm_anyfloat_ty], |
| [IntrNoMem]>; |
| |
| //===----------------------------------------------------------------------===// |
| // Saturating float-to-int conversions |
| //===----------------------------------------------------------------------===// |
| |
| def int_wasm_trunc_saturate_signed : Intrinsic<[llvm_anyint_ty], |
| [llvm_anyfloat_ty], |
| [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_trunc_saturate_unsigned : Intrinsic<[llvm_anyint_ty], |
| [llvm_anyfloat_ty], |
| [IntrNoMem, IntrSpeculatable]>; |
| |
| //===----------------------------------------------------------------------===// |
| // Exception handling intrinsics |
| //===----------------------------------------------------------------------===// |
| |
| // throw / rethrow |
| // The immediate argument is an index to a tag, which is 0 for C++. |
| def int_wasm_throw : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty], |
| [Throws, IntrNoReturn, ImmArg<ArgIndex<0>>]>; |
| def int_wasm_rethrow : Intrinsic<[], [], [Throws, IntrNoReturn]>; |
| |
| // Since wasm does not use landingpad instructions, these instructions return |
| // exception pointer and selector values until we lower them in WasmEHPrepare. |
| def int_wasm_get_exception : Intrinsic<[llvm_ptr_ty], [llvm_token_ty], |
| [IntrHasSideEffects]>; |
| def int_wasm_get_ehselector : Intrinsic<[llvm_i32_ty], [llvm_token_ty], |
| [IntrHasSideEffects]>; |
| |
| // wasm.catch returns the pointer to the exception object caught by wasm 'catch' |
| // instruction. This returns a single pointer, which is sufficient for C++ |
| // support. The immediate argument is an index to for a tag, which is 0 for C++. |
| def int_wasm_catch : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], |
| [IntrHasSideEffects, ImmArg<ArgIndex<0>>]>; |
| |
| // WebAssembly EH must maintain the landingpads in the order assigned to them |
| // by WasmEHPrepare pass to generate landingpad table in EHStreamer. This is |
| // used in order to give them the indices in WasmEHPrepare. |
| def int_wasm_landingpad_index: Intrinsic<[], [llvm_token_ty, llvm_i32_ty], |
| [IntrNoMem, ImmArg<ArgIndex<1>>]>; |
| |
| // Returns LSDA address of the current function. |
| def int_wasm_lsda : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; |
| |
| //===----------------------------------------------------------------------===// |
| // Atomic intrinsics |
| //===----------------------------------------------------------------------===// |
| |
| // wait / notify |
| def int_wasm_memory_atomic_wait32 : |
| Intrinsic<[llvm_i32_ty], |
| [LLVMPointerType<llvm_i32_ty>, llvm_i32_ty, llvm_i64_ty], |
| [IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<0>>, |
| NoCapture<ArgIndex<0>>, IntrHasSideEffects], |
| "", [SDNPMemOperand]>; |
| def int_wasm_memory_atomic_wait64 : |
| Intrinsic<[llvm_i32_ty], |
| [LLVMPointerType<llvm_i64_ty>, llvm_i64_ty, llvm_i64_ty], |
| [IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<0>>, |
| NoCapture<ArgIndex<0>>, IntrHasSideEffects], |
| "", [SDNPMemOperand]>; |
| def int_wasm_memory_atomic_notify: |
| Intrinsic<[llvm_i32_ty], [LLVMPointerType<llvm_i32_ty>, llvm_i32_ty], |
| [IntrInaccessibleMemOnly, NoCapture<ArgIndex<0>>, |
| IntrHasSideEffects], |
| "", [SDNPMemOperand]>; |
| |
| //===----------------------------------------------------------------------===// |
| // SIMD intrinsics |
| //===----------------------------------------------------------------------===// |
| |
| def int_wasm_swizzle : |
| Intrinsic<[llvm_v16i8_ty], |
| [llvm_v16i8_ty, llvm_v16i8_ty], |
| [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_shuffle : |
| Intrinsic<[llvm_v16i8_ty], |
| [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, llvm_i32_ty, |
| llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, |
| llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, |
| llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], |
| [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_sub_saturate_signed : |
| Intrinsic<[llvm_anyvector_ty], |
| [LLVMMatchType<0>, LLVMMatchType<0>], |
| [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_sub_saturate_unsigned : |
| Intrinsic<[llvm_anyvector_ty], |
| [LLVMMatchType<0>, LLVMMatchType<0>], |
| [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_avgr_unsigned : |
| Intrinsic<[llvm_anyvector_ty], |
| [LLVMMatchType<0>, LLVMMatchType<0>], |
| [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_bitselect : |
| Intrinsic<[llvm_anyvector_ty], |
| [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], |
| [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_anytrue : |
| Intrinsic<[llvm_i32_ty], |
| [llvm_anyvector_ty], |
| [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_alltrue : |
| Intrinsic<[llvm_i32_ty], |
| [llvm_anyvector_ty], |
| [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_bitmask : |
| Intrinsic<[llvm_i32_ty], |
| [llvm_anyvector_ty], |
| [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_qfma : |
| Intrinsic<[llvm_anyvector_ty], |
| [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], |
| [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_qfms : |
| Intrinsic<[llvm_anyvector_ty], |
| [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], |
| [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_dot : |
| Intrinsic<[llvm_v4i32_ty], |
| [llvm_v8i16_ty, llvm_v8i16_ty], |
| [IntrNoMem, IntrSpeculatable]>; |
| |
| def int_wasm_narrow_signed : |
| Intrinsic<[llvm_anyvector_ty], |
| [llvm_anyvector_ty, LLVMMatchType<1>], |
| [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_narrow_unsigned : |
| Intrinsic<[llvm_anyvector_ty], |
| [llvm_anyvector_ty, LLVMMatchType<1>], |
| [IntrNoMem, IntrSpeculatable]>; |
| |
| // TODO: Replace these intrinsics with normal ISel patterns once i32x4 to i64x2 |
| // widening is merged to the proposal. |
| def int_wasm_widen_low_signed : |
| Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_widen_high_signed : |
| Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_widen_low_unsigned : |
| Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_widen_high_unsigned : |
| Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem, IntrSpeculatable]>; |
| |
| def int_wasm_q15mulr_saturate_signed : |
| Intrinsic<[llvm_v8i16_ty], |
| [llvm_v8i16_ty, llvm_v8i16_ty], |
| [IntrNoMem, IntrSpeculatable]>; |
| |
| // TODO: Replace these intrinsics with normal ISel patterns |
| def int_wasm_pmin : |
| Intrinsic<[llvm_anyvector_ty], |
| [LLVMMatchType<0>, LLVMMatchType<0>], |
| [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_pmax : |
| Intrinsic<[llvm_anyvector_ty], |
| [LLVMMatchType<0>, LLVMMatchType<0>], |
| [IntrNoMem, IntrSpeculatable]>; |
| |
| // TODO: Replace these instrinsics with normal ISel patterns once the |
| // rounding instructions are merged to the proposal |
| // (https://github.com/WebAssembly/simd/pull/232). |
| def int_wasm_ceil : |
| Intrinsic<[llvm_anyvector_ty], |
| [LLVMMatchType<0>], |
| [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_floor : |
| Intrinsic<[llvm_anyvector_ty], |
| [LLVMMatchType<0>], |
| [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_trunc : |
| Intrinsic<[llvm_anyvector_ty], |
| [LLVMMatchType<0>], |
| [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_nearest : |
| Intrinsic<[llvm_anyvector_ty], |
| [LLVMMatchType<0>], |
| [IntrNoMem, IntrSpeculatable]>; |
| |
| // TODO: Replace these intrinsic with normal ISel patterns once the |
| // load_zero instructions are merged to the proposal. |
| def int_wasm_load32_zero : |
| Intrinsic<[llvm_v4i32_ty], |
| [LLVMPointerType<llvm_i32_ty>], |
| [IntrReadMem, IntrArgMemOnly], |
| "", [SDNPMemOperand]>; |
| |
| def int_wasm_load64_zero : |
| Intrinsic<[llvm_v2i64_ty], |
| [LLVMPointerType<llvm_i64_ty>], |
| [IntrReadMem, IntrArgMemOnly], |
| "", [SDNPMemOperand]>; |
| |
| // These intrinsics do not mark their lane index arguments as immediate because |
| // that changes the corresponding SDNode from ISD::Constant to |
| // ISD::TargetConstant, which would require extra complications in the ISel |
| // tablegen patterns. TODO: Replace these intrinsic with normal ISel patterns |
| // once the load_lane instructions are merged to the proposal. |
| def int_wasm_load8_lane : |
| Intrinsic<[llvm_v16i8_ty], |
| [LLVMPointerType<llvm_i8_ty>, llvm_v16i8_ty, llvm_i32_ty], |
| [IntrReadMem, IntrArgMemOnly], |
| "", [SDNPMemOperand]>; |
| def int_wasm_load16_lane : |
| Intrinsic<[llvm_v8i16_ty], |
| [LLVMPointerType<llvm_i16_ty>, llvm_v8i16_ty, llvm_i32_ty], |
| [IntrReadMem, IntrArgMemOnly], |
| "", [SDNPMemOperand]>; |
| def int_wasm_load32_lane : |
| Intrinsic<[llvm_v4i32_ty], |
| [LLVMPointerType<llvm_i32_ty>, llvm_v4i32_ty, llvm_i32_ty], |
| [IntrReadMem, IntrArgMemOnly], |
| "", [SDNPMemOperand]>; |
| def int_wasm_load64_lane : |
| Intrinsic<[llvm_v2i64_ty], |
| [LLVMPointerType<llvm_i64_ty>, llvm_v2i64_ty, llvm_i32_ty], |
| [IntrReadMem, IntrArgMemOnly], |
| "", [SDNPMemOperand]>; |
| def int_wasm_store8_lane : |
| Intrinsic<[], |
| [LLVMPointerType<llvm_i8_ty>, llvm_v16i8_ty, llvm_i32_ty], |
| [IntrWriteMem, IntrArgMemOnly], |
| "", [SDNPMemOperand]>; |
| def int_wasm_store16_lane : |
| Intrinsic<[], |
| [LLVMPointerType<llvm_i16_ty>, llvm_v8i16_ty, llvm_i32_ty], |
| [IntrWriteMem, IntrArgMemOnly], |
| "", [SDNPMemOperand]>; |
| def int_wasm_store32_lane : |
| Intrinsic<[], |
| [LLVMPointerType<llvm_i32_ty>, llvm_v4i32_ty, llvm_i32_ty], |
| [IntrWriteMem, IntrArgMemOnly], |
| "", [SDNPMemOperand]>; |
| def int_wasm_store64_lane : |
| Intrinsic<[], |
| [LLVMPointerType<llvm_i64_ty>, llvm_v2i64_ty, llvm_i32_ty], |
| [IntrWriteMem, IntrArgMemOnly], |
| "", [SDNPMemOperand]>; |
| |
| // TODO: Replace this intrinsic with normal ISel patterns once popcnt is merged |
| // to the proposal. |
| def int_wasm_popcnt : |
| Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem, IntrSpeculatable]>; |
| |
| def int_wasm_extmul_low_signed : |
| Intrinsic<[llvm_anyvector_ty], |
| [LLVMSubdivide2VectorType<0>, LLVMSubdivide2VectorType<0>], |
| [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_extmul_high_signed : |
| Intrinsic<[llvm_anyvector_ty], |
| [LLVMSubdivide2VectorType<0>, LLVMSubdivide2VectorType<0>], |
| [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_extmul_low_unsigned : |
| Intrinsic<[llvm_anyvector_ty], |
| [LLVMSubdivide2VectorType<0>, LLVMSubdivide2VectorType<0>], |
| [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_extmul_high_unsigned : |
| Intrinsic<[llvm_anyvector_ty], |
| [LLVMSubdivide2VectorType<0>, LLVMSubdivide2VectorType<0>], |
| [IntrNoMem, IntrSpeculatable]>; |
| |
| def int_wasm_extadd_pairwise_signed : |
| Intrinsic<[llvm_anyvector_ty], |
| [LLVMSubdivide2VectorType<0>], |
| [IntrNoMem, IntrSpeculatable]>; |
| def int_wasm_extadd_pairwise_unsigned : |
| Intrinsic<[llvm_anyvector_ty], |
| [LLVMSubdivide2VectorType<0>], |
| [IntrNoMem, IntrSpeculatable]>; |
| |
| def int_wasm_signselect : |
| Intrinsic<[llvm_anyvector_ty], |
| [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]>; |
| |
| // TODO: Remove this after experiments have been run. Use the target-agnostic |
| // int_prefetch if this becomes specified at some point. |
| def int_wasm_prefetch_t : |
| Intrinsic<[], [llvm_ptr_ty], |
| [IntrInaccessibleMemOrArgMemOnly, IntrWillReturn, |
| ReadOnly<ArgIndex<0>>, NoCapture<ArgIndex<0>>], |
| "", [SDNPMemOperand]>; |
| |
| def int_wasm_prefetch_nt : |
| Intrinsic<[], [llvm_ptr_ty], |
| [IntrInaccessibleMemOrArgMemOnly, IntrWillReturn, |
| ReadOnly<ArgIndex<0>>, NoCapture<ArgIndex<0>>], |
| "", [SDNPMemOperand]>; |
| |
| //===----------------------------------------------------------------------===// |
| // Thread-local storage intrinsics |
| //===----------------------------------------------------------------------===// |
| |
| def int_wasm_tls_size : |
| Intrinsic<[llvm_anyint_ty], |
| [], |
| [IntrNoMem, IntrSpeculatable]>; |
| |
| def int_wasm_tls_align : |
| Intrinsic<[llvm_anyint_ty], |
| [], |
| [IntrNoMem, IntrSpeculatable]>; |
| |
| def int_wasm_tls_base : |
| Intrinsic<[llvm_ptr_ty], |
| [], |
| [IntrReadMem]>; |
| |
| } // TargetPrefix = "wasm" |