1//===- IntrinsicsWebAssembly.td - Defines wasm intrinsics --*- tablegen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file defines all of the WebAssembly-specific intrinsics.
11///
12//===----------------------------------------------------------------------===//
13
14let TargetPrefix = "wasm" in {  // All intrinsics start with "llvm.wasm.".
15
16// Query the current memory size, and increase the current memory size.
17// Note that memory.size is not IntrNoMem because it must be sequenced with
18// respect to memory.grow calls.
19def int_wasm_memory_size : Intrinsic<[llvm_anyint_ty],
20                                     [llvm_i32_ty],
21                                     [IntrReadMem]>;
22def int_wasm_memory_grow : Intrinsic<[llvm_anyint_ty],
23                                     [llvm_i32_ty, LLVMMatchType<0>],
24                                     []>;
25
26//===----------------------------------------------------------------------===//
27// Trapping float-to-int conversions
28//===----------------------------------------------------------------------===//
29
30def int_wasm_trunc_signed : Intrinsic<[llvm_anyint_ty],
31                                      [llvm_anyfloat_ty],
32                                      [IntrNoMem]>;
33def int_wasm_trunc_unsigned : Intrinsic<[llvm_anyint_ty],
34                                        [llvm_anyfloat_ty],
35                                        [IntrNoMem]>;
36
37//===----------------------------------------------------------------------===//
38// Saturating float-to-int conversions
39//===----------------------------------------------------------------------===//
40
41def int_wasm_trunc_saturate_signed : Intrinsic<[llvm_anyint_ty],
42                                               [llvm_anyfloat_ty],
43                                               [IntrNoMem, IntrSpeculatable]>;
44def int_wasm_trunc_saturate_unsigned : Intrinsic<[llvm_anyint_ty],
45                                                 [llvm_anyfloat_ty],
46                                                 [IntrNoMem, IntrSpeculatable]>;
47
48//===----------------------------------------------------------------------===//
49// Exception handling intrinsics
50//===----------------------------------------------------------------------===//
51
52// throw / rethrow
53// The immediate argument is an index to a tag, which is 0 for C++.
54def int_wasm_throw : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty],
55                               [Throws, IntrNoReturn, ImmArg<ArgIndex<0>>]>;
56def int_wasm_rethrow : Intrinsic<[], [], [Throws, IntrNoReturn]>;
57
58// Since wasm does not use landingpad instructions, these instructions return
59// exception pointer and selector values until we lower them in WasmEHPrepare.
60def int_wasm_get_exception : Intrinsic<[llvm_ptr_ty], [llvm_token_ty],
61                                       [IntrHasSideEffects]>;
62def int_wasm_get_ehselector : Intrinsic<[llvm_i32_ty], [llvm_token_ty],
63                                        [IntrHasSideEffects]>;
64
65// wasm.catch returns the pointer to the exception object caught by wasm 'catch'
66// instruction. This returns a single pointer, which is sufficient for C++
67// support. The immediate argument is an index to for a tag, which is 0 for C++.
68def int_wasm_catch : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty],
69                               [IntrHasSideEffects, ImmArg<ArgIndex<0>>]>;
70
71// WebAssembly EH must maintain the landingpads in the order assigned to them
72// by WasmEHPrepare pass to generate landingpad table in EHStreamer. This is
73// used in order to give them the indices in WasmEHPrepare.
74def int_wasm_landingpad_index: Intrinsic<[], [llvm_token_ty, llvm_i32_ty],
75                                         [IntrNoMem, ImmArg<ArgIndex<1>>]>;
76
77// Returns LSDA address of the current function.
78def int_wasm_lsda : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>;
79
80//===----------------------------------------------------------------------===//
81// Atomic intrinsics
82//===----------------------------------------------------------------------===//
83
84// wait / notify
85def int_wasm_memory_atomic_wait32 :
86  Intrinsic<[llvm_i32_ty],
87            [LLVMPointerType<llvm_i32_ty>, llvm_i32_ty, llvm_i64_ty],
88            [IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<0>>,
89             NoCapture<ArgIndex<0>>, IntrHasSideEffects],
90            "", [SDNPMemOperand]>;
91def int_wasm_memory_atomic_wait64 :
92  Intrinsic<[llvm_i32_ty],
93            [LLVMPointerType<llvm_i64_ty>, llvm_i64_ty, llvm_i64_ty],
94            [IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<0>>,
95             NoCapture<ArgIndex<0>>, IntrHasSideEffects],
96            "", [SDNPMemOperand]>;
97def int_wasm_memory_atomic_notify:
98  Intrinsic<[llvm_i32_ty], [LLVMPointerType<llvm_i32_ty>, llvm_i32_ty],
99            [IntrInaccessibleMemOnly, NoCapture<ArgIndex<0>>,
100             IntrHasSideEffects],
101            "", [SDNPMemOperand]>;
102
103//===----------------------------------------------------------------------===//
104// SIMD intrinsics
105//===----------------------------------------------------------------------===//
106
107def int_wasm_swizzle :
108  Intrinsic<[llvm_v16i8_ty],
109            [llvm_v16i8_ty, llvm_v16i8_ty],
110            [IntrNoMem, IntrSpeculatable]>;
111def int_wasm_shuffle :
112  Intrinsic<[llvm_v16i8_ty],
113            [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, llvm_i32_ty,
114             llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty,
115             llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty,
116             llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
117            [IntrNoMem, IntrSpeculatable]>;
118def int_wasm_sub_saturate_signed :
119  Intrinsic<[llvm_anyvector_ty],
120            [LLVMMatchType<0>, LLVMMatchType<0>],
121            [IntrNoMem, IntrSpeculatable]>;
122def int_wasm_sub_saturate_unsigned :
123  Intrinsic<[llvm_anyvector_ty],
124            [LLVMMatchType<0>, LLVMMatchType<0>],
125            [IntrNoMem, IntrSpeculatable]>;
126def int_wasm_avgr_unsigned :
127  Intrinsic<[llvm_anyvector_ty],
128            [LLVMMatchType<0>, LLVMMatchType<0>],
129            [IntrNoMem, IntrSpeculatable]>;
130def int_wasm_bitselect :
131  Intrinsic<[llvm_anyvector_ty],
132            [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>],
133            [IntrNoMem, IntrSpeculatable]>;
134def int_wasm_anytrue :
135  Intrinsic<[llvm_i32_ty],
136            [llvm_anyvector_ty],
137            [IntrNoMem, IntrSpeculatable]>;
138def int_wasm_alltrue :
139  Intrinsic<[llvm_i32_ty],
140            [llvm_anyvector_ty],
141            [IntrNoMem, IntrSpeculatable]>;
142def int_wasm_bitmask :
143  Intrinsic<[llvm_i32_ty],
144            [llvm_anyvector_ty],
145            [IntrNoMem, IntrSpeculatable]>;
146def int_wasm_qfma :
147  Intrinsic<[llvm_anyvector_ty],
148            [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>],
149            [IntrNoMem, IntrSpeculatable]>;
150def int_wasm_qfms :
151  Intrinsic<[llvm_anyvector_ty],
152            [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>],
153            [IntrNoMem, IntrSpeculatable]>;
154def int_wasm_dot :
155  Intrinsic<[llvm_v4i32_ty],
156            [llvm_v8i16_ty, llvm_v8i16_ty],
157            [IntrNoMem, IntrSpeculatable]>;
158
159def int_wasm_narrow_signed :
160  Intrinsic<[llvm_anyvector_ty],
161            [llvm_anyvector_ty, LLVMMatchType<1>],
162            [IntrNoMem, IntrSpeculatable]>;
163def int_wasm_narrow_unsigned :
164  Intrinsic<[llvm_anyvector_ty],
165            [llvm_anyvector_ty, LLVMMatchType<1>],
166            [IntrNoMem, IntrSpeculatable]>;
167
168// TODO: Replace these intrinsics with normal ISel patterns once i32x4 to i64x2
169// widening is merged to the proposal.
170def int_wasm_widen_low_signed :
171  Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem, IntrSpeculatable]>;
172def int_wasm_widen_high_signed :
173  Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem, IntrSpeculatable]>;
174def int_wasm_widen_low_unsigned :
175  Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem, IntrSpeculatable]>;
176def int_wasm_widen_high_unsigned :
177  Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem, IntrSpeculatable]>;
178
179def int_wasm_q15mulr_saturate_signed :
180  Intrinsic<[llvm_v8i16_ty],
181            [llvm_v8i16_ty, llvm_v8i16_ty],
182            [IntrNoMem, IntrSpeculatable]>;
183
184// TODO: Replace these intrinsics with normal ISel patterns
185def int_wasm_pmin :
186  Intrinsic<[llvm_anyvector_ty],
187            [LLVMMatchType<0>, LLVMMatchType<0>],
188            [IntrNoMem, IntrSpeculatable]>;
189def int_wasm_pmax :
190  Intrinsic<[llvm_anyvector_ty],
191            [LLVMMatchType<0>, LLVMMatchType<0>],
192            [IntrNoMem, IntrSpeculatable]>;
193
194// TODO: Replace these instrinsics with normal ISel patterns once the
195// rounding instructions are merged to the proposal
196// (https://github.com/WebAssembly/simd/pull/232).
197def int_wasm_ceil :
198  Intrinsic<[llvm_anyvector_ty],
199            [LLVMMatchType<0>],
200            [IntrNoMem, IntrSpeculatable]>;
201def int_wasm_floor :
202  Intrinsic<[llvm_anyvector_ty],
203            [LLVMMatchType<0>],
204            [IntrNoMem, IntrSpeculatable]>;
205def int_wasm_trunc :
206  Intrinsic<[llvm_anyvector_ty],
207            [LLVMMatchType<0>],
208            [IntrNoMem, IntrSpeculatable]>;
209def int_wasm_nearest :
210  Intrinsic<[llvm_anyvector_ty],
211            [LLVMMatchType<0>],
212            [IntrNoMem, IntrSpeculatable]>;
213
214// TODO: Replace these intrinsic with normal ISel patterns once the
215// load_zero instructions are merged to the proposal.
216def int_wasm_load32_zero :
217  Intrinsic<[llvm_v4i32_ty],
218            [LLVMPointerType<llvm_i32_ty>],
219            [IntrReadMem, IntrArgMemOnly],
220             "", [SDNPMemOperand]>;
221
222def int_wasm_load64_zero :
223  Intrinsic<[llvm_v2i64_ty],
224            [LLVMPointerType<llvm_i64_ty>],
225            [IntrReadMem, IntrArgMemOnly],
226             "", [SDNPMemOperand]>;
227
228// These intrinsics do not mark their lane index arguments as immediate because
229// that changes the corresponding SDNode from ISD::Constant to
230// ISD::TargetConstant, which would require extra complications in the ISel
231// tablegen patterns. TODO: Replace these intrinsic with normal ISel patterns
232// once the load_lane instructions are merged to the proposal.
233def int_wasm_load8_lane :
234  Intrinsic<[llvm_v16i8_ty],
235            [LLVMPointerType<llvm_i8_ty>, llvm_v16i8_ty, llvm_i32_ty],
236            [IntrReadMem, IntrArgMemOnly],
237            "", [SDNPMemOperand]>;
238def int_wasm_load16_lane :
239  Intrinsic<[llvm_v8i16_ty],
240            [LLVMPointerType<llvm_i16_ty>, llvm_v8i16_ty, llvm_i32_ty],
241            [IntrReadMem, IntrArgMemOnly],
242            "", [SDNPMemOperand]>;
243def int_wasm_load32_lane :
244  Intrinsic<[llvm_v4i32_ty],
245            [LLVMPointerType<llvm_i32_ty>, llvm_v4i32_ty, llvm_i32_ty],
246            [IntrReadMem, IntrArgMemOnly],
247            "", [SDNPMemOperand]>;
248def int_wasm_load64_lane :
249  Intrinsic<[llvm_v2i64_ty],
250            [LLVMPointerType<llvm_i64_ty>, llvm_v2i64_ty, llvm_i32_ty],
251            [IntrReadMem, IntrArgMemOnly],
252            "", [SDNPMemOperand]>;
253def int_wasm_store8_lane :
254  Intrinsic<[],
255            [LLVMPointerType<llvm_i8_ty>, llvm_v16i8_ty, llvm_i32_ty],
256            [IntrWriteMem, IntrArgMemOnly],
257            "", [SDNPMemOperand]>;
258def int_wasm_store16_lane :
259  Intrinsic<[],
260            [LLVMPointerType<llvm_i16_ty>, llvm_v8i16_ty, llvm_i32_ty],
261            [IntrWriteMem, IntrArgMemOnly],
262            "", [SDNPMemOperand]>;
263def int_wasm_store32_lane :
264  Intrinsic<[],
265            [LLVMPointerType<llvm_i32_ty>, llvm_v4i32_ty, llvm_i32_ty],
266            [IntrWriteMem, IntrArgMemOnly],
267            "", [SDNPMemOperand]>;
268def int_wasm_store64_lane :
269  Intrinsic<[],
270            [LLVMPointerType<llvm_i64_ty>, llvm_v2i64_ty, llvm_i32_ty],
271            [IntrWriteMem, IntrArgMemOnly],
272            "", [SDNPMemOperand]>;
273
274// TODO: Replace this intrinsic with normal ISel patterns once popcnt is merged
275// to the proposal.
276def int_wasm_popcnt :
277  Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem, IntrSpeculatable]>;
278
279def int_wasm_extmul_low_signed :
280  Intrinsic<[llvm_anyvector_ty],
281            [LLVMSubdivide2VectorType<0>, LLVMSubdivide2VectorType<0>],
282            [IntrNoMem, IntrSpeculatable]>;
283def int_wasm_extmul_high_signed :
284  Intrinsic<[llvm_anyvector_ty],
285            [LLVMSubdivide2VectorType<0>, LLVMSubdivide2VectorType<0>],
286            [IntrNoMem, IntrSpeculatable]>;
287def int_wasm_extmul_low_unsigned :
288  Intrinsic<[llvm_anyvector_ty],
289            [LLVMSubdivide2VectorType<0>, LLVMSubdivide2VectorType<0>],
290            [IntrNoMem, IntrSpeculatable]>;
291def int_wasm_extmul_high_unsigned :
292  Intrinsic<[llvm_anyvector_ty],
293            [LLVMSubdivide2VectorType<0>, LLVMSubdivide2VectorType<0>],
294            [IntrNoMem, IntrSpeculatable]>;
295
296def int_wasm_extadd_pairwise_signed :
297  Intrinsic<[llvm_anyvector_ty],
298            [LLVMSubdivide2VectorType<0>],
299            [IntrNoMem, IntrSpeculatable]>;
300def int_wasm_extadd_pairwise_unsigned :
301  Intrinsic<[llvm_anyvector_ty],
302            [LLVMSubdivide2VectorType<0>],
303            [IntrNoMem, IntrSpeculatable]>;
304
305def int_wasm_signselect :
306  Intrinsic<[llvm_anyvector_ty],
307            [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>],
308            [IntrNoMem, IntrSpeculatable]>;
309
310// TODO: Remove this intrinsic and the associated builtin if i64x2.eq gets
311// merged to the proposal.
312def int_wasm_eq :
313  Intrinsic<[llvm_v2i64_ty],
314            [llvm_v2i64_ty, llvm_v2i64_ty],
315            [IntrNoMem, IntrSpeculatable]>;
316
317// TODO: Remove this after experiments have been run. Use the target-agnostic
318// int_prefetch if this becomes specified at some point.
319def int_wasm_prefetch_t :
320  Intrinsic<[], [llvm_ptr_ty],
321            [IntrInaccessibleMemOrArgMemOnly, IntrWillReturn,
322             ReadOnly<ArgIndex<0>>, NoCapture<ArgIndex<0>>],
323            "", [SDNPMemOperand]>;
324
325def int_wasm_prefetch_nt :
326  Intrinsic<[], [llvm_ptr_ty],
327            [IntrInaccessibleMemOrArgMemOnly, IntrWillReturn,
328             ReadOnly<ArgIndex<0>>, NoCapture<ArgIndex<0>>],
329            "", [SDNPMemOperand]>;
330
331// TODO: Remove these if possible if they are merged to the spec.
332def int_wasm_convert_low_signed :
333  Intrinsic<[llvm_v2f64_ty], [llvm_v4i32_ty],
334            [IntrNoMem, IntrSpeculatable]>;
335def int_wasm_convert_low_unsigned :
336  Intrinsic<[llvm_v2f64_ty], [llvm_v4i32_ty],
337            [IntrNoMem, IntrSpeculatable]>;
338def int_wasm_trunc_saturate_zero_signed :
339  Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty],
340            [IntrNoMem, IntrSpeculatable]>;
341def int_wasm_trunc_saturate_zero_unsigned :
342  Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty],
343            [IntrNoMem, IntrSpeculatable]>;
344def int_wasm_demote_zero :
345  Intrinsic<[llvm_v4f32_ty], [llvm_v2f64_ty],
346            [IntrNoMem, IntrSpeculatable]>;
347def int_wasm_promote_low :
348  Intrinsic<[llvm_v2f64_ty], [llvm_v4f32_ty],
349            [IntrNoMem, IntrSpeculatable]>;
350
351//===----------------------------------------------------------------------===//
352// Thread-local storage intrinsics
353//===----------------------------------------------------------------------===//
354
355def int_wasm_tls_size :
356  Intrinsic<[llvm_anyint_ty],
357            [],
358            [IntrNoMem, IntrSpeculatable]>;
359
360def int_wasm_tls_align :
361  Intrinsic<[llvm_anyint_ty],
362            [],
363            [IntrNoMem, IntrSpeculatable]>;
364
365def int_wasm_tls_base :
366  Intrinsic<[llvm_ptr_ty],
367            [],
368            [IntrReadMem]>;
369
370} // TargetPrefix = "wasm"
371